Logo Search packages:      
Sourcecode: vile version File versions

map.c

/*
 * map.c    -- map and map! interface routines
 *    Original interface by Otto Lind, 6/3/93
 *    Additional map and map! support by Kevin Buettner, 9/17/94
 *
 * $Header: /usr/build/vile/vile/RCS/map.c,v 1.97 2002/11/01 23:58:39 tom Exp $
 *
 */

#include "estruct.h"
#include "edef.h"

#if DISP_NTWIN
# define NTWIN_CURSOR_MINWAIT 550   /* msec */
#endif

/*
 * Picture for struct maprec
 * -------------------------
 *
 * Assume the following mappings...
 *
 * map za abc
 * map zb def
 * map q  quit
 *
 * These may be represented by the following picture...
 *
 *   |
 *   v
 * +---+--------+---+---+   +---+--------+---+---+
 * | z |  NULL  | o | o-+-->| q | "quit" | 0 | 0 |
 * +---+--------+-|-+---+   +---+--------+---+---+
 *                |
 *            v
 *              +---+--------+---+---+   +---+--------+---+---+
 *              | a | "abc"  | 0 | o-+-->| b | "def"  | 0 | 0 |
 *              +---+--------+---+---+   +---+--------+---+---+
 *
 * where the pertinent fields are as follows:
 *
 * +----+-----+-------+-------+
 * | ch | srv | dlink | flink |
 * +----+-----+-------+-------+
 *
 * When matching a character sequence, we follow dlink when we've found a
 * matching character.  We change the character to be matched to the next
 * character in the sequence.  If the character doesn't match, we stay at
 * the same level (with the same character) and follow flink.
 *
 */

struct maprec {
      int         ch;         /* character to match         */
      UINT        flags;            /* flags word                 */
      struct maprec *   dlink;            /* Where to go to match the   */
                              /*   next character in a multi-     */
                              /*   character sequence.      */
      struct maprec *   flink;            /* Where to try next if match */
                              /*   against current character      */
                              /*   is unsuccessful          */
      int         irv;        /* system defined mapping: The      */
                              /*   (wide) character code to */
                              /*   replace a matched sequence by */
      char        * srv;            /* user defined mapping: This */
                              /*   is the string to replace a     */
                              /*   matched sequence by      */
};

#define MAPF_SYSTIMER   0x01
#define MAPF_USERTIMER  0x02
#define MAPF_TIMERS     0x03
#define MAPF_NOREMAP    0x04

static int suppress_sysmap;

static struct maprec *map_command = NULL;
static struct maprec *map_insert = NULL;
static struct maprec *map_syskey = NULL;
static struct maprec *abbr_map = NULL;

static      int   map_common(struct maprec **mpp, const char *bufname, UINT remapflag);
static      int   unmap_common(struct maprec **mpp, const char *bufname);
static      void  addtomap(struct maprec **mpp, const char * ks, int kslen, UINT flags, int irv, char * srv);
static      int   delfrommap(struct maprec **mpp, const char * ks);

static      int   abbr_getc (void);
static      int   abbr_c_avail (void);

static      int   mapgetc (void);

typedef     int (*AvailFunc) (void);
typedef     int (*GetFunc) (void);
typedef     int (*StartFunc) (void);

static      int   maplookup(int c, ITBUFF **outp, struct maprec *mp, GetFunc get, AvailFunc avail, StartFunc start, int suffix);

#if !OPT_UPBUFF
#define relist_mappings(name)
#endif

#define NUMKEYSTR (KBLOCK / 2)

#ifdef DOKEYLOG
int do_keylog = 1;
#endif

#if OPT_SHOW_MAPS
#define MAPS_PREFIX 12

/*ARGSUSED*/
static void
makemaplist(int dummy GCC_UNUSED, void *mapp)
{
    TBUFF *lhsstr = 0;
    struct maprec **lhsstack;
    struct maprec *mp = (struct maprec *) mapp;
    int footnote = 0;
    size_t depth = 0;
    size_t maxdepth;
    size_t i;

    lhsstr = tb_init(&lhsstr, 0);
    lhsstack = typeallocn(struct maprec *, maxdepth = NSTRING);
    for_ever {
      if (mp) {
          const char *remapnote;
          char *mapstr;
          char esc_seq[10];   /* FIXME */
          tb_put(&lhsstr, depth, mp->ch);
          if (depth+1 >= maxdepth)
            lhsstack = typereallocn(struct maprec *, lhsstack, maxdepth *= 2);
          lhsstack[depth++] = mp->flink;

          mapstr = (char *)0;
          if (mp->srv) {
            mapstr = mp->srv;
          } else if (mp->irv != -1) {
            (void)kcod2escape_seq(mp->irv, esc_seq);
            mapstr = esc_seq;
          }
          if (mapstr) {
                if (mapp && (struct maprec *)mapp == abbr_map) {
                      /* the abbr map is stored inverted */
                      for (i = depth; i != 0; )
                        bputc(tb_values(lhsstr)[--i]);
                } else {
                      if (mp->flags & MAPF_NOREMAP) {
                        remapnote = "(n)";
                        footnote++;
                      } else {
                        remapnote = "   ";
                      }
                      bprintf("%s ", remapnote);
                      for (i = 0; i < depth; i++)
                        bputc(tb_values(lhsstr)[i]);
                }
                bprintf("\t%s\n", mapstr);
          }
          mp = mp->dlink;
      }
      else if (depth != 0)
          mp = lhsstack[--depth];
      else
          break;
    }
    if (footnote) {
      bprintf("[(n) means never remap]\n");
    }
    tb_free(&lhsstr);
    free((char *)lhsstack);
}

static int
show_mapped_chars(const char *bname)
{
      struct maprec *mp;
      if (strcmp(bname, MAP_BufName) == 0)
            mp = map_command;
      else if (strcmp(bname, MAPBANG_BufName) == 0)
            mp = map_insert;
      else if (strcmp(bname, ABBR_BufName) == 0)
            mp = abbr_map;
      else if (strcmp(bname, SYSMAP_BufName) == 0)
            mp = map_syskey;
      else
            return FALSE;
      return liststuff(bname, FALSE, makemaplist, 0, (void *)mp);
}

#if OPT_UPBUFF
static int
show_Mappings(BUFFER *bp)
{
      b_clr_obsolete(bp);
      return show_mapped_chars(bp->b_bname);
}

#undef relist_mappings

static void
relist_mappings(const char * bufname)
{
    update_scratch(bufname, show_Mappings);
}
#endif      /* OPT_UPBUFF */

#endif      /* OPT_SHOW_MAPS */

/*
** set a map for the character/string combo
*/
/* ARGSUSED */
int
map(int f GCC_UNUSED, int n GCC_UNUSED)
{
    return map_common(&map_command, MAP_BufName, 0);
}

/* ARGSUSED */
int
map_bang(int f GCC_UNUSED, int n GCC_UNUSED)
{
    return map_common(&map_insert, MAPBANG_BufName, 0);
}

/* ARGSUSED */
int
noremap(int f GCC_UNUSED, int n GCC_UNUSED)
{
    return map_common(&map_command, MAP_BufName, MAPF_NOREMAP);
}

/* ARGSUSED */
int
noremap_bang(int f GCC_UNUSED, int n GCC_UNUSED)
{
    return map_common(&map_insert, MAPBANG_BufName, MAPF_NOREMAP);
}

/* ARGSUSED */
int
abbrev(int f GCC_UNUSED, int n GCC_UNUSED)
{
    return map_common(&abbr_map, ABBR_BufName, MAPF_NOREMAP);
}

#if OPT_SHOW_MAPS
/* ARGSUSED */
int
sysmap(int f GCC_UNUSED, int n GCC_UNUSED)
{
      return show_mapped_chars(SYSMAP_BufName);
}
#endif

static int
map_common(struct maprec **mpp, const char *bufname, UINT remapflag)
{
    int      status;
    static TBUFF *kbuf;
    static TBUFF *val;
    int len;

#if OPT_SHOW_MAPS
    if (end_named_cmd()) {
      return show_mapped_chars(bufname);
    }
#endif
    tb_scopy(&kbuf, "");
    status = kbd_reply("change this string: ", &kbuf, eol_history,
                  ' ', KBD_NOMAP|KBD_NOEVAL, no_completion);
    if (status != TRUE)
      return status;

    hst_glue(' ');
    tb_scopy(&val, "");
    if (!clexec) {
          status = kbd_reply("to this new string: ", &val, eol_history,
                  '\n', KBD_NOMAP, no_completion);
    } else {
          (void)mac_literalarg(&val); /* consume to end of line */
          status = tb_length(val) > 1;
    }
    if (status != TRUE)
      return status;

    len = tb_length(kbuf) - 1;
    if ((*mpp && *mpp == abbr_map) || (strcmp(bufname, ABBR_BufName) == 0)) {
      /* reverse the lhs */
      int i;
      char t;
      char *s = tb_values(kbuf);
      for (i = 0; i < len/2; i++) {
          t = s[len-i-1];
          s[len-i-1] = s[i];
          s[i] = t;
      }
    }

    addtomap(mpp, tb_values(kbuf), len, MAPF_USERTIMER|remapflag, -1, tb_values(val));
    relist_mappings(bufname);
    return TRUE;
}

/*
** remove map entry, restore saved CMDFUNC for key
*/
/* ARGSUSED */
int
unmap(int f GCC_UNUSED, int n GCC_UNUSED)
{
    return unmap_common(&map_command, MAP_BufName);
}

/* ARGSUSED */
int
unmap_bang(int f GCC_UNUSED, int n GCC_UNUSED)
{
    return unmap_common(&map_insert, MAPBANG_BufName);
}

/* ARGSUSED */
int
unmap_system(int f GCC_UNUSED, int n GCC_UNUSED)
{
    return unmap_common(&map_syskey, SYSMAP_BufName);
}

/* ARGSUSED */
int
unabbr(int f GCC_UNUSED, int n GCC_UNUSED)
{
    return unmap_common(&abbr_map, ABBR_BufName);
}

static int
unmap_common(struct maprec **mpp, const char *bufname)
{
    int      status;
    static TBUFF *kbuf;

    /* otherwise it'll be mapped, and not found when looked up */
    if (mpp && mpp == &map_syskey)
      suppress_sysmap = TRUE;

    tb_scopy(&kbuf, "");
    status = kbd_reply("unmap string: ", &kbuf, eol_history,
                  ' ', KBD_NOMAP, no_completion);
    suppress_sysmap = FALSE;
    if (status != TRUE)
      return status;

    if ((*mpp && *mpp == abbr_map) || (strcmp(bufname, ABBR_BufName) == 0)) {
      /* reverse the lhs */
      int i;
      char t;
      int len = tb_length(kbuf) - 1;
      char *s = tb_values(kbuf);
      for (i = 0; i < len/2; i++) {
          t = s[len-i-1];
          s[len-i-1] = s[i];
          s[i] = t;
      }
    }

    if (delfrommap(mpp, tb_values(kbuf)) != TRUE) {
      mlforce("[Sequence not mapped]");
      return FALSE;
    }
    relist_mappings(bufname);
    return TRUE;
}

/* addtosysmap is used to initialize the system default function key map
*/
void
addtosysmap(const char * seq, int seqlen, int code)
{
    addtomap(&map_syskey, seq, seqlen, MAPF_SYSTIMER,
                  code, (char *)0);
}

static void
addtomap(
    struct maprec **mpp,
    const char * ks,
    int     kslen,
    UINT    flags,
    int           irv,
    char *  srv)
{
    struct maprec *mp = NULL;

    if (ks == 0 || kslen == 0)
      return;

    while (*mpp && kslen) {
      mp = *mpp;
      mp->flags |= flags;
      if (char2int(*ks) == mp->ch) {
          mpp = &mp->dlink;
          ks++;
          kslen--;
      }
      else
          mpp = &mp->flink;
    }

    while (kslen) {
      mp = typealloc(struct maprec);
      if (mp == 0)
          break;
      *mpp = mp;
      mp->dlink = mp->flink = NULL;
      mp->ch = char2int(*ks++);
      mp->srv = NULL;
      mp->flags = flags;
      mp->irv = -1;
      mpp = &mp->dlink;
      kslen--;
    }

    if (irv != -1)
      mp->irv = irv;
    if (srv) {
      if (mp->srv)
          free(mp->srv);
      mp->srv = strmalloc(srv);
    }
    mp->flags = flags;
}

static int
delfrommap(struct maprec **mpp, const char * ks)
{
    struct maprec **save_m = mpp;
    struct maprec ***mstk = 0;
    const char *save_k = ks;
    int depth = 0;
    int pass;

    if (ks == 0 || *ks == 0)
      return FALSE;

    for (pass = 0; pass < 2; pass++) {
      mpp   = save_m;
      ks    = save_k;
      depth = 0;
      while (*mpp && *ks) {
          if (pass)
            mstk[depth] = mpp;
          if ((*mpp)->ch == char2int(*ks)) {
            mpp = &(*mpp)->dlink;
            ks++;
            depth++;
          }
          else
            mpp = &(*mpp)->flink;
      }

      if (*ks)
          return FALSE;       /* not in map */
      if (!pass)
          mstk = typecallocn(struct maprec **, depth+1);
    }

    depth--;
    if ((*mstk[depth])->srv) {
      free((*mstk[depth])->srv);
      (*mstk[depth])->srv = NULL;
    } else if ((*mstk[depth])->irv != -1) {
      (*mstk[depth])->irv = -1;
    } else {
      free((char *)mstk);
      return FALSE;
    }

    for (; depth >= 0; depth--) {
      struct maprec *mp = *mstk[depth];
      if (mp->irv == -1 && mp->dlink == NULL && mp->srv == NULL) {
          *mstk[depth] = mp->flink;
          if (depth > 0 && (*mstk[depth-1])->dlink == mp)
            (*mstk[depth-1])->dlink = NULL;
          free((char *)mp);
      }
      else
          break;
    }
    free((char *)mstk);
    return TRUE;
}


#define INPUT_FROM_TTGET 1
#define INPUT_FROM_MAPGETC 2

static ITBUFF *sysmappedchars = NULL;
static ITBUFF *mapgetc_ungottenchars = NULL;
static int mapgetc_ungotcnt = 0;

static void
save_keystroke(int c)
{
    KILL *kp;
    KILLREG *kr = &kbs[KEYST_KREG];

    beginDisplay();
#ifdef DOKEYLOG
    if (do_keylog) {
      static int keyfd = -1;
      static char *tfilenam;
      if (!tfilenam)
          tfilenam = tempnam("/tmp/vilekeylogs", "vilek");
      if (tfilenam) {
          if (keyfd < 0)
            keyfd = open(tfilenam, O_CREAT | O_WRONLY, 0600);
          if (keyfd >= 0)
            write(keyfd, &c, 1);
      }
    }
#endif
    if (kr->kbufh == NULL) {
      kr->kbufh = typealloc(KILL);
      kr->kused = 0;
    }
    if (kr->kbufh != NULL) {

      kp = kr->kbufp = kr->kbufh;
      kp->d_next = NULL;

      kp->d_chunk[kr->kused++] = (UCHAR) c;
      if (kr->kused >= NUMKEYSTR * 2) {   /* time to dump the oldest half */
          (void) memcpy((kp->d_chunk),
                    (&kp->d_chunk[NUMKEYSTR / 2]),
                    NUMKEYSTR / 2);
          kr->kused = NUMKEYSTR / 2;
      }
    }
    endofDisplay();
}

/* these two wrappers are provided because at least one pcc-based
      compiler balks at passing term.getch or term.typahead as a function pointer */

static int
normal_getc(void)
{
      int c = term.getch();
      TRACE(("normal/getc:%c (%#x)\n", c, c));
      save_keystroke(c);
      return c;
}

static int
normal_typeahead(void)
{
      return(term.typahead());
}

static int
normal_start(void)
{
      return TRUE;
}

int
sysmapped_c(void)
{
    int c;

    /* still some left? */
    if (itb_more(sysmappedchars))
      return itb_last(sysmappedchars);

    if ((c = term.getch()) == -1)
      return c;   /* see comment in ttgetc */

    TRACE(("mapped/getc:%c (%#x)\n", c, c));

    save_keystroke(c);

    if (suppress_sysmap)
      return c;

    /* will push back on sysmappedchars successful, or not */
    (void)maplookup(c, &sysmappedchars, map_syskey,
            normal_getc, normal_typeahead, normal_start, TRUE);

    return itb_last(sysmappedchars);
}

int
sysmapped_c_avail(void)
{
    return itb_more(sysmappedchars) || (!mapgetc_ungotcnt && term.typahead());
}


/* make the assumption that no input will magically appear
 * (un)available to tgetc in between a mapungetc and the next mapgetc.
 * Hence characters can't be ungotten onto the wrong buffer (exception
 * is the last tgot char might be mapungot onto the map buffer.  This
 * is OK (if assumption holds) because the next character will be
 * gotten from this buffer.
 */

void
mapungetc(int c)
{
    if (tgetc_avail()) {
      tungetc(c);
    } else {
      (void)itb_append(&mapgetc_ungottenchars, c);
      mapgetc_ungotcnt++;
    }
}

static int infloopcount;
static int mapgetc_raw_flag;

static int
mapgetc(void)
{
    UINT remapflag;
    if (global_g_val(GMDREMAP))
      remapflag = 0;
    else
      remapflag = NOREMAP;

    if (!tgetc_avail() && mapgetc_ungotcnt > 0) {
          if (infloopcount++ > global_g_val(GVAL_MAPLENGTH)) {
            (void)itb_init(&mapgetc_ungottenchars, esc_c);
            mapgetc_ungotcnt = 0;
            mlforce("[Infinite loop detected in %s sequence]",
                      (insertmode) ? "map!" : "map");
            catnap(1000,FALSE);  /* FIXME: be sure message gets out */
            return esc_c|NOREMAP;
          }
          mapgetc_ungotcnt--;
          return itb_last(mapgetc_ungottenchars) | remapflag;
    }
    infloopcount = 0;
    return tgetc(mapgetc_raw_flag);
}

int
mapped_c_avail(void)
{
    return mapgetc_ungotcnt > 0 || tgetc_avail();
}

int
mapped_ungotc_avail(void)
{
    return mapgetc_ungotcnt > 0;
}

static int
mapped_c_start(void)
{
    return TRUE;
}

int
mapped_c(int remap, int raw)
{
    int c;
    int matched;
    struct maprec *mp;
    int speckey = FALSE;
    static ITBUFF *mappedchars = NULL;

    /* still some pushback left? */
    mapgetc_raw_flag = raw;
    c = mapgetc();

    if ((c & YESREMAP) == 0 && (!remap || (c & NOREMAP)))
      return (c & ~REMAPFLAGS);

    c &= ~REMAPFLAGS;

    if (reading_msg_line)
      mp = 0;
    else if (insertmode)
      mp = map_insert;
    else
      mp = map_command;

    /* if we got a function key from the lower layers, turn it into '#c'
      and see if the user remapped that */
    if ((c & SPEC)
#if OPT_KEY_MODIFY
     && !(c & mod_KEY)  /* we don't do this special case */
#endif
     ) {
      mapungetc(kcod2key(c));
      c = poundc;
      speckey = TRUE;
    }

    do {
      (void)itb_init(&mappedchars, esc_c);

      matched = maplookup(c, &mappedchars, mp, mapgetc, mapped_c_avail, mapped_c_start, TRUE);


      while(itb_more(mappedchars))
          mapungetc(itb_next(mappedchars));

      /* if the user has not mapped '#c', we return the wide code we got
          in the first place.  unless they wanted it quoted.  then we
          leave it as is */
      if (!raw && speckey && !matched) {
          c = mapgetc() & ~REMAPFLAGS;
          if (c != poundc)
                dbgwrite("BUG: # problem in mapped_c");
          return (mapgetc() & ~REMAPFLAGS) | SPEC;
      }

      c = mapgetc();

      if (!global_g_val(GMDREMAPFIRST))
            matched = FALSE;

      speckey = FALSE;

    } while (matched &&
      ((remap && !(c & NOREMAP)) || (c & YESREMAP)) );

    return c & ~REMAPFLAGS;

}

static int abbr_curr_off;
static int abbr_search_lim;

static int
abbr_getc(void)
{
    if (abbr_curr_off <= abbr_search_lim)
      return -1; /* won't match anything in the tree */
    return lgetc(DOT.l, --abbr_curr_off) & 0xff;
}

static int
abbr_c_avail(void)
{
    return TRUE;
}

static int
abbr_c_start(void)
{
    if (abbr_curr_off > abbr_search_lim) {
      /* we need to check the char in front of the match.
         if it's a similar type to the first char of the match,
         i.e. both idents, or both non-idents, we do nothing.
         if whitespace precedes either ident or non-ident, the
         match is good.
       */
      int first, prev;
      first = lgetc(DOT.l,abbr_curr_off);
      prev = lgetc(DOT.l,abbr_curr_off-1);
      if ((isident(first) && isident(prev)) ||
          (!isident(first) && !(isident(prev) || isSpace(prev)))) {
            return FALSE;
      }
    }
    return TRUE;
}

void
abbr_check(int *backsp_limit_p)
{
    int matched;
    ITBUFF *abbr_chars = NULL;
    int status = TRUE;

    if (llength(DOT.l) < 1)
      return;
    abbr_curr_off = DOT.o;
    abbr_search_lim = *backsp_limit_p;
    (void)itb_init(&abbr_chars, esc_c);
    matched = maplookup(abbr_getc(), &abbr_chars, abbr_map,
      abbr_getc, abbr_c_avail, abbr_c_start, FALSE);


    if (matched) {
          /* there are still some conditions that have to be met by
             the preceding chars, if any */
          if (!abbr_c_start()) {
            itb_free(&abbr_chars);
            return;
          }
          DOT.o -= matched;
          ldelete((B_COUNT)matched, FALSE);
          while(status && itb_more(abbr_chars))
            status = inschar(itb_last(abbr_chars), backsp_limit_p);
    }
    itb_free(&abbr_chars);
    return;
}

/* do map tranlations.
      C is first char to begin mapping on
      OUTP is an ITBUFF in which to put the result
      MP is the map in which to look
      GET is a routine to use to get the next character
      AVAIL is the routine that tells if GET can return something now
  returns number of characters matched
*/
static int
maplookup(
    int c,
    ITBUFF **outp,
    struct maprec *mp,
    GetFunc get,
    AvailFunc avail,
    StartFunc start,
    int suffix)
{
    struct maprec *rmp = NULL;
    ITBUFF *unmatched = 0;
    int matchedcnt;
    int use_sys_timing;
    int had_start = FALSE;
    register int count = 0;   /* index into 'unmatched[]' */

    /*
     * we don't want to delay for a user-specified :map!  starting with
     * poundc since it's likely that the mapping is happening on behalf of
     * a function key.  (it's so the user can ":map! #1 foobar" but still be
     * able to insert a '#' character normally.)  if they've changed poundc
     * so it's not something one normally inserts, then it's okay to delay
     * on it.
     */
    use_sys_timing = (insertmode && c == poundc &&
                        (isPrint(poundc) || isSpace(poundc)));

    unmatched = itb_init(&unmatched, 0);
    itb_append(&unmatched, c);
    count++;

    matchedcnt = 0;
    while (mp != 0) {
      if (c == mp->ch) {
          if (mp->irv != -1 || mp->srv != NULL) {
            rmp = mp;
            matchedcnt += count;
            unmatched = itb_init(&unmatched, 0);
            count = 0;

            /* our code supports matching the longer of two maps one of
             * which is a subset of the other.  vi matches the shorter
             * one.
             */
            if ((*start)()) {
                had_start = TRUE;
                if (!global_g_val(GMDMAPLONGER)) {
                  break;
                }
            }
          }

          mp = mp->dlink;

          if (!mp)
            break;

          /* if there's no recorded input, and no user typeahead */
          if (!(*avail)()) {

            /* give it a little extra time... */
            int timer = 0;
#if DISP_NTWIN
            int cursor_state = 0;
#endif

            /* we want to use the longer of the two timers */

            /* get the user timer.  it may be zero */
            if (!use_sys_timing && (mp->flags & MAPF_USERTIMER) != 0)
                  timer = global_g_val(GVAL_TIMEOUTUSERVAL);

            /* if there was no user timer, or this is a system
                  sequence, use the system timer if it's bigger */
            if (timer == 0 || (mp->flags & MAPF_SYSTIMER) != 0) {
                  if (timer < global_g_val(GVAL_TIMEOUTVAL))
                        timer = global_g_val(GVAL_TIMEOUTVAL);
            }

#if DISP_NTWIN
            if (timer > NTWIN_CURSOR_MINWAIT) {
                  /*
                   * editor waits for a potentially long time
                   * for the next character, during which the
                   * cursor will be invisible; so turn it back on.
                   * unfortunately, the cursor won't blink
                   * because there's no thread driving the
                   * message pump.
                   */

                  cursor_state = winvile_cursor_state(TRUE, FALSE);
            }
#endif
            catnap(timer,TRUE);
#if DISP_NTWIN
            if (timer > NTWIN_CURSOR_MINWAIT) /* restore cursor state */
                  (void) winvile_cursor_state(cursor_state, FALSE);
#endif

            if (!(*avail)())
                break;
          }

          if ((c = (*get)()) < 0)
            break;

          itb_append(&unmatched, c & ~REMAPFLAGS);
          count++;

      }
      else
          mp = mp->flink;
    }

    if (had_start && (rmp != 0)) {
      /* unget the unmatched suffix */
      while (suffix && (count > 0))
          (void)itb_append(outp, itb_values(unmatched)[--count]);
      /* unget the mapping and elide correct number of recorded chars */
      if (rmp->srv) {
          UINT remapflag;
          char *cp;
          /* cp = rmp->srv + cnt; */
          for (cp = rmp->srv; *cp; cp++)
            ;
          if (rmp->flags & MAPF_NOREMAP)
            remapflag = NOREMAP;
          else
            remapflag = 0;
          while (cp > rmp->srv)
            (void)itb_append(outp, char2int(*--cp)|remapflag);
      }
      else {
          (void)itb_append(outp, rmp->irv);
      }
    }
    else {  /* didn't find a match */
      while (count > 0)
          (void)itb_append(outp, itb_values(unmatched)[--count]);
      matchedcnt = 0;
    }
    itb_free(&unmatched);
    return matchedcnt;
}

#if NO_LEAKS
static void
free_maprec(struct maprec **p)
{
      struct      maprec *q;
      if ((q = *p) != 0) {
            free_maprec(&(q->flink));
            free_maprec(&(q->dlink));
            FreeAndNull(q->srv);
            *p = 0;
            free((char *)q);
      }
}

void
map_leaks(void)
{
      free_maprec(&map_command);
      free_maprec(&map_insert);
      free_maprec(&map_syskey);
      free_maprec(&abbr_map);
}
#endif      /* NO_LEAKS */

Generated by  Doxygen 1.6.0   Back to index