/* vi:set ts=8 sts=4 sw=4: * * VIM - Vi IMproved by Bram Moolenaar * * Do ":help uganda" in Vim to read copying and usage conditions. * Do ":help credits" in Vim to see a list of people who contributed. * See README.txt for an overview of the Vim source code. */ /* * getchar.c * * functions related with getting a character from the user/mapping/redo/... * * manipulations with redo buffer and stuff buffer * mappings and abbreviations */ #include "vim.h" /* * These buffers are used for storing: * - stuffed characters: A command that is translated into another command. * - redo characters: will redo the last change. * - recorded chracters: for the "q" command. * * The bytes are stored like in the typeahead buffer: * - K_SPECIAL introduces a special key (two more bytes follow). A literal * K_SPECIAL is stored as K_SPECIAL KS_SPECIAL KE_FILLER. * - CSI introduces a GUI termcap code (also when gui.in_use is FALSE, * otherwise switching the GUI on would make mappings invalid). * A literal CSI is stored as CSI KS_EXTRA KE_CSI. * These translations are also done on multi-byte characters! * * Escaping CSI bytes is done by the system-specific input functions, called * by ui_inchar(). * Escaping K_SPECIAL is done by inchar(). * Un-escaping is done by vgetc(). */ #define MINIMAL_SIZE 20 /* minimal size for b_str */ static struct buffheader redobuff = {{NULL, {NUL}}, NULL, 0, 0};static struct buffheader old_redobuff = {{NULL, {NUL}}, NULL, 0, 0};#if defined(FEAT_AUTOCMD) || defined(FEAT_EVAL) || defined(PROTO)static struct buffheader save_redobuff = {{NULL, {NUL}}, NULL, 0, 0};static struct buffheader save_old_redobuff = {{NULL, {NUL}}, NULL, 0, 0};#endifstatic struct buffheader recordbuff = {{NULL, {NUL}}, NULL, 0, 0}; static int typeahead_char = 0; /* typeahead char that's not flushed */ /* * when block_redo is TRUE redo buffer will not be changed * used by edit() to repeat insertions and 'V' command for redoing */static int block_redo = FALSE; /* * Make a hash value for a mapping. * "mode" is the lower 4 bits of the State for the mapping. * "c1" is the first character of the "lhs". * Returns a value between 0 and 255, index in maphash. * Put Normal/Visual mode mappings mostly separately from Insert/Cmdline mode. */#define MAP_HASH(mode, c1) (((mode) & (NORMAL + VISUAL + SELECTMODE + OP_PENDING)) ? (c1) : ((c1) ^ 0x80)) /* * Each mapping is put in one of the 256 hash lists, to speed up finding it. */static mapblock_T *(maphash[256]);static int maphash_valid = FALSE; /* * List used for abbreviations. */static mapblock_T *first_abbr = NULL; /* first entry in abbrlist */ static int KeyNoremap = 0; /* remapping flags */ /* * variables used by vgetorpeek() and flush_buffers() * * typebuf.tb_buf[] contains all characters that are not consumed yet. * typebuf.tb_buf[typebuf.tb_off] is the first valid character. * typebuf.tb_buf[typebuf.tb_off + typebuf.tb_len - 1] is the last valid char. * typebuf.tb_buf[typebuf.tb_off + typebuf.tb_len] must be NUL. * The head of the buffer may contain the result of mappings, abbreviations * and @a commands. The length of this part is typebuf.tb_maplen. * typebuf.tb_silent is the part where <silent> applies. * After the head are characters that come from the terminal. * typebuf.tb_no_abbr_cnt is the number of characters in typebuf.tb_buf that * should not be considered for abbreviations. * Some parts of typebuf.tb_buf may not be mapped. These parts are remembered * in typebuf.tb_noremap[], which is the same length as typebuf.tb_buf and * contains RM_NONE for the characters that are not to be remapped. * typebuf.tb_noremap[typebuf.tb_off] is the first valid flag. * (typebuf has been put in globals.h, because check_termcode() needs it). */#define RM_YES 0 /* tb_noremap: remap */#define RM_NONE 1 /* tb_noremap: don't remap */#define RM_SCRIPT 2 /* tb_noremap: remap local script mappings */#define RM_ABBR 4 /* tb_noremap: don't remap, do abbrev. */ /* typebuf.tb_buf has three parts: room in front (for result of mappings), the * middle for typeahead and room for new characters (which needs to be 3 * * MAXMAPLEN) for the Amiga). */#define TYPELEN_INIT (5 * (MAXMAPLEN + 3))static char_u typebuf_init[TYPELEN_INIT]; /* initial typebuf.tb_buf */static char_u noremapbuf_init[TYPELEN_INIT]; /* initial typebuf.tb_noremap */ static int last_recorded_len = 0; /* number of last recorded chars */ static char_u *get_buffcont __ARGS((struct buffheader *, int));static void add_buff __ARGS((struct buffheader *, char_u *, long n));static void add_num_buff __ARGS((struct buffheader *, long));static void add_char_buff __ARGS((struct buffheader *, int));static int read_stuff __ARGS((int advance));static void start_stuff __ARGS((void));static int read_redo __ARGS((int, int));static void copy_redo __ARGS((int));static void init_typebuf __ARGS((void));static void gotchars __ARGS((char_u *, int));static void may_sync_undo __ARGS((void));static void closescript __ARGS((void));static int vgetorpeek __ARGS((int));static void map_free __ARGS((mapblock_T **));static void validate_maphash __ARGS((void));static void showmap __ARGS((mapblock_T *mp, int local));#ifdef FEAT_EVALstatic char_u *eval_map_expr __ARGS((char_u *str));#endif /* * Free and clear a buffer. */ voidfree_buff(buf) struct buffheader *buf;{ struct buffblock *p, *np; for (p = buf->bh_first.b_next; p != NULL; p = np) { np = p->b_next; vim_free(p); } buf->bh_first.b_next = NULL;} /* * Return the contents of a buffer as a single string. * K_SPECIAL and CSI in the returned string are escaped. */ static char_u *get_buffcont(buffer, dozero) struct buffheader *buffer; int dozero; /* count == zero is not an error */{ long_u count = 0; char_u *p = NULL; char_u *p2; char_u *str; struct buffblock *bp; /* compute the total length of the string */ for (bp = buffer->bh_first.b_next; bp != NULL; bp = bp->b_next) count += (long_u)STRLEN(bp->b_str); if ((count || dozero) && (p = lalloc(count + 1, TRUE)) != NULL) { p2 = p; for (bp = buffer->bh_first.b_next; bp != NULL; bp = bp->b_next) for (str = bp->b_str; *str; ) *p2++ = *str++; *p2 = NUL; } return (p);} /* * Return the contents of the record buffer as a single string * and clear the record buffer. * K_SPECIAL and CSI in the returned string are escaped. */ char_u *get_recorded(){ char_u *p; size_t len; p = get_buffcont(&recordbuff, TRUE); free_buff(&recordbuff); /* * Remove the characters that were added the last time, these must be the * (possibly mapped) characters that stopped the recording. */ len = STRLEN(p); if ((int)len >= last_recorded_len) { len -= last_recorded_len; p[len] = NUL; } /* * When stopping recording from Insert mode with CTRL-O q, also remove the * CTRL-O. */ if (len > 0 && restart_edit != 0 && p[len - 1] == Ctrl_O) p[len - 1] = NUL; return (p);} /* * Return the contents of the redo buffer as a single string. * K_SPECIAL and CSI in the returned string are escaped. */ char_u *get_inserted(){ return(get_buffcont(&redobuff, FALSE));} /* * Add string "s" after the current block of buffer "buf". * K_SPECIAL and CSI should have been escaped already. */ static voidadd_buff(buf, s, slen) struct buffheader *buf; char_u *s; long slen; /* length of "s" or -1 */{ struct buffblock *p; long_u len; if (slen < 0) slen = (long)STRLEN(s); if (slen == 0) /* don't add empty strings */ return; if (buf->bh_first.b_next == NULL) /* first add to list */ { buf->bh_space = 0; buf->bh_curr = &(buf->bh_first); } else if (buf->bh_curr == NULL) /* buffer has already been read */ { EMSG(_("E222: Add to read buffer")); return; } else if (buf->bh_index != 0) STRCPY(buf->bh_first.b_next->b_str, buf->bh_first.b_next->b_str + buf->bh_index); buf->bh_index = 0; if (buf->bh_space >= (int)slen) { len = (long_u)STRLEN(buf->bh_curr->b_str); vim_strncpy(buf->bh_curr->b_str + len, s, (size_t)slen); buf->bh_space -= slen; } else { if (slen < MINIMAL_SIZE) len = MINIMAL_SIZE; else len = slen; p = (struct buffblock *)lalloc((long_u)(sizeof(struct buffblock) + len), TRUE); if (p == NULL) return; /* no space, just forget it */ buf->bh_space = (int)(len - slen); vim_strncpy(p->b_str, s, (size_t)slen); p->b_next = buf->bh_curr->b_next; buf->bh_curr->b_next = p; buf->bh_curr = p; } return;} /* * Add number "n" to buffer "buf". */ static voidadd_num_buff(buf, n) struct buffheader *buf; long n;{ char_u number[32]; sprintf((char *)number, "%ld", n); add_buff(buf, number, -1L);} /* * Add character 'c' to buffer "buf". * Translates special keys, NUL, CSI, K_SPECIAL and multibyte characters. */ static voidadd_char_buff(buf, c) struct buffheader *buf; int c;{#ifdef FEAT_MBYTE char_u bytes[MB_MAXBYTES + 1]; int len; int i;#endif char_u temp[4]; #ifdef FEAT_MBYTE if (IS_SPECIAL(c)) len = 1; else len = (*mb_char2bytes)(c, bytes); for (i = 0; i < len; ++i) { if (!IS_SPECIAL(c)) c = bytes[i];#endif if (IS_SPECIAL(c) || c == K_SPECIAL || c == NUL) { /* translate special key code into three byte sequence */ temp[0] = K_SPECIAL; temp[1] = K_SECOND(c); temp[2] = K_THIRD(c); temp[3] = NUL; }#ifdef FEAT_GUI else if (c == CSI) { /* Translate a CSI to a CSI - KS_EXTRA - KE_CSI sequence */ temp[0] = CSI; temp[1] = KS_EXTRA; temp[2] = (int)KE_CSI; temp[3] = NUL; }#endif else { temp[0] = c; temp[1] = NUL; } add_buff(buf, temp, -1L);#ifdef FEAT_MBYTE }#endif} /* * Get one byte from the stuff buffer. * If advance == TRUE go to the next char. * No translation is done K_SPECIAL and CSI are escaped. */ static intread_stuff(advance) int advance;{ char_u c; struct buffblock *curr; if (stuffbuff.bh_first.b_next == NULL) /* buffer is empty */ return NUL; curr = stuffbuff.bh_first.b_next; c = curr->b_str[stuffbuff.bh_index]; if (advance) { if (curr->b_str[++stuffbuff.bh_index] == NUL) { stuffbuff.bh_first.b_next = curr->b_next; vim_free(curr); stuffbuff.bh_index = 0; } } return c;} /* * Prepare the stuff buffer for reading (if it contains something). */ static voidstart_stuff(){ if (stuffbuff.bh_first.b_next != NULL) { stuffbuff.bh_curr = &(stuffbuff.bh_first); stuffbuff.bh_space = 0; }} /* * Return TRUE if the stuff buffer is empty. */ intstuff_empty(){ return (stuffbuff.bh_first.b_next == NULL);} /* * Set a typeahead character that won't be flushed. */ voidtypeahead_noflush(c) int c;{ typeahead_char = c;} /* * Remove the contents of the stuff buffer and the mapped characters in the * typeahead buffer (used in case of an error). If 'typeahead' is true, * flush all typeahead characters (used when interrupted by a CTRL-C). */ voidflush_buffers(typeahead) int typeahead;{ init_typebuf(); start_stuff(); while (read_stuff(TRUE) != NUL) ; if (typeahead) /* remove all typeahead */ { /* * We have to get all characters, because we may delete the first part * of an escape sequence. * In an xterm we get one char at a time and we have to get them all. */ while (inchar(typebuf.tb_buf, typebuf.tb_buflen - 1, 10L, typebuf.tb_change_cnt) != 0) ; typebuf.tb_off = MAXMAPLEN; typebuf.tb_len = 0; } else /* remove mapped characters only */ { typebuf.tb_off += typebuf.tb_maplen; typebuf.tb_len -= typebuf.tb_maplen; } typebuf.tb_maplen = 0; typebuf.tb_silent = 0; cmd_silent = FALSE; typebuf.tb_no_abbr_cnt = 0;} /* * The previous contents of the redo buffer is kept in old_redobuffer. * This is used for the CTRL-O <.> command in insert mode. */ voidResetRedobuff(){ if (!block_redo) { free_buff(&old_redobuff); old_redobuff = redobuff; redobuff.bh_first.b_next = NULL; }} #if defined(FEAT_AUTOCMD) || defined(FEAT_EVAL) || defined(PROTO)/* * Save redobuff and old_redobuff to save_redobuff and save_old_redobuff. * Used before executing autocommands and user functions. */static int save_level = 0; voidsaveRedobuff(){ char_u *s; if (save_level++ == 0) { save_redobuff = redobuff; redobuff.bh_first.b_next = NULL; save_old_redobuff = old_redobuff; old_redobuff.bh_first.b_next = NULL; /* Make a copy, so that ":normal ." in a function works. */ s = get_buffcont(&save_redobuff, FALSE); if (s != NULL) { add_buff(&redobuff, s, -1L); vim_free(s); } }} Lines 1–500 of 5067. Load more
/* vi:set ts=8 sts=4 sw=4: * * VIM - Vi IMproved by Bram Moolenaar * * Do ":help uganda" in Vim to read copying and usage conditions. * Do ":help credits" in Vim to see a list of people who contributed. * See README.txt for an overview of the Vim source code. */ /* * getchar.c * * functions related with getting a character from the user/mapping/redo/... * * manipulations with redo buffer and stuff buffer * mappings and abbreviations */ #include "vim.h" /* * These buffers are used for storing: * - stuffed characters: A command that is translated into another command. * - redo characters: will redo the last change. * - recorded chracters: for the "q" command. * * The bytes are stored like in the typeahead buffer: * - K_SPECIAL introduces a special key (two more bytes follow). A literal * K_SPECIAL is stored as K_SPECIAL KS_SPECIAL KE_FILLER. * - CSI introduces a GUI termcap code (also when gui.in_use is FALSE, * otherwise switching the GUI on would make mappings invalid). * A literal CSI is stored as CSI KS_EXTRA KE_CSI. * These translations are also done on multi-byte characters! * * Escaping CSI bytes is done by the system-specific input functions, called * by ui_inchar(). * Escaping K_SPECIAL is done by inchar(). * Un-escaping is done by vgetc(). */ #define MINIMAL_SIZE 20 /* minimal size for b_str */ static struct buffheader redobuff = {{NULL, {NUL}}, NULL, 0, 0}; static struct buffheader old_redobuff = {{NULL, {NUL}}, NULL, 0, 0}; #if defined(FEAT_AUTOCMD) || defined(FEAT_EVAL) || defined(PROTO) static struct buffheader save_redobuff = {{NULL, {NUL}}, NULL, 0, 0}; static struct buffheader save_old_redobuff = {{NULL, {NUL}}, NULL, 0, 0}; #endif static struct buffheader recordbuff = {{NULL, {NUL}}, NULL, 0, 0}; static int typeahead_char = 0; /* typeahead char that's not flushed */ /* * when block_redo is TRUE redo buffer will not be changed * used by edit() to repeat insertions and 'V' command for redoing */ static int block_redo = FALSE; /* * Make a hash value for a mapping. * "mode" is the lower 4 bits of the State for the mapping. * "c1" is the first character of the "lhs". * Returns a value between 0 and 255, index in maphash. * Put Normal/Visual mode mappings mostly separately from Insert/Cmdline mode. */ #define MAP_HASH(mode, c1) (((mode) & (NORMAL + VISUAL + SELECTMODE + OP_PENDING)) ? (c1) : ((c1) ^ 0x80)) /* * Each mapping is put in one of the 256 hash lists, to speed up finding it. */ static mapblock_T *(maphash[256]); static int maphash_valid = FALSE; /* * List used for abbreviations. */ static mapblock_T *first_abbr = NULL; /* first entry in abbrlist */ static int KeyNoremap = 0; /* remapping flags */ /* * variables used by vgetorpeek() and flush_buffers() * * typebuf.tb_buf[] contains all characters that are not consumed yet. * typebuf.tb_buf[typebuf.tb_off] is the first valid character. * typebuf.tb_buf[typebuf.tb_off + typebuf.tb_len - 1] is the last valid char. * typebuf.tb_buf[typebuf.tb_off + typebuf.tb_len] must be NUL. * The head of the buffer may contain the result of mappings, abbreviations * and @a commands. The length of this part is typebuf.tb_maplen. * typebuf.tb_silent is the part where <silent> applies. * After the head are characters that come from the terminal. * typebuf.tb_no_abbr_cnt is the number of characters in typebuf.tb_buf that * should not be considered for abbreviations. * Some parts of typebuf.tb_buf may not be mapped. These parts are remembered * in typebuf.tb_noremap[], which is the same length as typebuf.tb_buf and * contains RM_NONE for the characters that are not to be remapped. * typebuf.tb_noremap[typebuf.tb_off] is the first valid flag. * (typebuf has been put in globals.h, because check_termcode() needs it). */ #define RM_YES 0 /* tb_noremap: remap */ #define RM_NONE 1 /* tb_noremap: don't remap */ #define RM_SCRIPT 2 /* tb_noremap: remap local script mappings */ #define RM_ABBR 4 /* tb_noremap: don't remap, do abbrev. */ /* typebuf.tb_buf has three parts: room in front (for result of mappings), the * middle for typeahead and room for new characters (which needs to be 3 * * MAXMAPLEN) for the Amiga). */ #define TYPELEN_INIT (5 * (MAXMAPLEN + 3)) static char_u typebuf_init[TYPELEN_INIT]; /* initial typebuf.tb_buf */ static char_u noremapbuf_init[TYPELEN_INIT]; /* initial typebuf.tb_noremap */ static int last_recorded_len = 0; /* number of last recorded chars */ static char_u *get_buffcont __ARGS((struct buffheader *, int)); static void add_buff __ARGS((struct buffheader *, char_u *, long n)); static void add_num_buff __ARGS((struct buffheader *, long)); static void add_char_buff __ARGS((struct buffheader *, int)); static int read_stuff __ARGS((int advance)); static void start_stuff __ARGS((void)); static int read_redo __ARGS((int, int)); static void copy_redo __ARGS((int)); static void init_typebuf __ARGS((void)); static void gotchars __ARGS((char_u *, int)); static void may_sync_undo __ARGS((void)); static void closescript __ARGS((void)); static int vgetorpeek __ARGS((int)); static void map_free __ARGS((mapblock_T **)); static void validate_maphash __ARGS((void)); static void showmap __ARGS((mapblock_T *mp, int local)); #ifdef FEAT_EVAL static char_u *eval_map_expr __ARGS((char_u *str)); #endif /* * Free and clear a buffer. */ void free_buff(buf) struct buffheader *buf; { struct buffblock *p, *np; for (p = buf->bh_first.b_next; p != NULL; p = np) { np = p->b_next; vim_free(p); } buf->bh_first.b_next = NULL; } /* * Return the contents of a buffer as a single string. * K_SPECIAL and CSI in the returned string are escaped. */ static char_u * get_buffcont(buffer, dozero) struct buffheader *buffer; int dozero; /* count == zero is not an error */ { long_u count = 0; char_u *p = NULL; char_u *p2; char_u *str; struct buffblock *bp; /* compute the total length of the string */ for (bp = buffer->bh_first.b_next; bp != NULL; bp = bp->b_next) count += (long_u)STRLEN(bp->b_str); if ((count || dozero) && (p = lalloc(count + 1, TRUE)) != NULL) { p2 = p; for (bp = buffer->bh_first.b_next; bp != NULL; bp = bp->b_next) for (str = bp->b_str; *str; ) *p2++ = *str++; *p2 = NUL; } return (p); } /* * Return the contents of the record buffer as a single string * and clear the record buffer. * K_SPECIAL and CSI in the returned string are escaped. */ char_u * get_recorded() { char_u *p; size_t len; p = get_buffcont(&recordbuff, TRUE); free_buff(&recordbuff); /* * Remove the characters that were added the last time, these must be the * (possibly mapped) characters that stopped the recording. */ len = STRLEN(p); if ((int)len >= last_recorded_len) { len -= last_recorded_len; p[len] = NUL; } /* * When stopping recording from Insert mode with CTRL-O q, also remove the * CTRL-O. */ if (len > 0 && restart_edit != 0 && p[len - 1] == Ctrl_O) p[len - 1] = NUL; return (p); } /* * Return the contents of the redo buffer as a single string. * K_SPECIAL and CSI in the returned string are escaped. */ char_u * get_inserted() { return(get_buffcont(&redobuff, FALSE)); } /* * Add string "s" after the current block of buffer "buf". * K_SPECIAL and CSI should have been escaped already. */ static void add_buff(buf, s, slen) struct buffheader *buf; char_u *s; long slen; /* length of "s" or -1 */ { struct buffblock *p; long_u len; if (slen < 0) slen = (long)STRLEN(s); if (slen == 0) /* don't add empty strings */ return; if (buf->bh_first.b_next == NULL) /* first add to list */ { buf->bh_space = 0; buf->bh_curr = &(buf->bh_first); } else if (buf->bh_curr == NULL) /* buffer has already been read */ { EMSG(_("E222: Add to read buffer")); return; } else if (buf->bh_index != 0) STRCPY(buf->bh_first.b_next->b_str, buf->bh_first.b_next->b_str + buf->bh_index); buf->bh_index = 0; if (buf->bh_space >= (int)slen) { len = (long_u)STRLEN(buf->bh_curr->b_str); vim_strncpy(buf->bh_curr->b_str + len, s, (size_t)slen); buf->bh_space -= slen; } else { if (slen < MINIMAL_SIZE) len = MINIMAL_SIZE; else len = slen; p = (struct buffblock *)lalloc((long_u)(sizeof(struct buffblock) + len), TRUE); if (p == NULL) return; /* no space, just forget it */ buf->bh_space = (int)(len - slen); vim_strncpy(p->b_str, s, (size_t)slen); p->b_next = buf->bh_curr->b_next; buf->bh_curr->b_next = p; buf->bh_curr = p; } return; } /* * Add number "n" to buffer "buf". */ static void add_num_buff(buf, n) struct buffheader *buf; long n; { char_u number[32]; sprintf((char *)number, "%ld", n); add_buff(buf, number, -1L); } /* * Add character 'c' to buffer "buf". * Translates special keys, NUL, CSI, K_SPECIAL and multibyte characters. */ static void add_char_buff(buf, c) struct buffheader *buf; int c; { #ifdef FEAT_MBYTE char_u bytes[MB_MAXBYTES + 1]; int len; int i; #endif char_u temp[4]; #ifdef FEAT_MBYTE if (IS_SPECIAL(c)) len = 1; else len = (*mb_char2bytes)(c, bytes); for (i = 0; i < len; ++i) { if (!IS_SPECIAL(c)) c = bytes[i]; #endif if (IS_SPECIAL(c) || c == K_SPECIAL || c == NUL) { /* translate special key code into three byte sequence */ temp[0] = K_SPECIAL; temp[1] = K_SECOND(c); temp[2] = K_THIRD(c); temp[3] = NUL; } #ifdef FEAT_GUI else if (c == CSI) { /* Translate a CSI to a CSI - KS_EXTRA - KE_CSI sequence */ temp[0] = CSI; temp[1] = KS_EXTRA; temp[2] = (int)KE_CSI; temp[3] = NUL; } #endif else { temp[0] = c; temp[1] = NUL; } add_buff(buf, temp, -1L); #ifdef FEAT_MBYTE } #endif } /* * Get one byte from the stuff buffer. * If advance == TRUE go to the next char. * No translation is done K_SPECIAL and CSI are escaped. */ static int read_stuff(advance) int advance; { char_u c; struct buffblock *curr; if (stuffbuff.bh_first.b_next == NULL) /* buffer is empty */ return NUL; curr = stuffbuff.bh_first.b_next; c = curr->b_str[stuffbuff.bh_index]; if (advance) { if (curr->b_str[++stuffbuff.bh_index] == NUL) { stuffbuff.bh_first.b_next = curr->b_next; vim_free(curr); stuffbuff.bh_index = 0; } } return c; } /* * Prepare the stuff buffer for reading (if it contains something). */ static void start_stuff() { if (stuffbuff.bh_first.b_next != NULL) { stuffbuff.bh_curr = &(stuffbuff.bh_first); stuffbuff.bh_space = 0; } } /* * Return TRUE if the stuff buffer is empty. */ int stuff_empty() { return (stuffbuff.bh_first.b_next == NULL); } /* * Set a typeahead character that won't be flushed. */ void typeahead_noflush(c) int c; { typeahead_char = c; } /* * Remove the contents of the stuff buffer and the mapped characters in the * typeahead buffer (used in case of an error). If 'typeahead' is true, * flush all typeahead characters (used when interrupted by a CTRL-C). */ void flush_buffers(typeahead) int typeahead; { init_typebuf(); start_stuff(); while (read_stuff(TRUE) != NUL) ; if (typeahead) /* remove all typeahead */ { /* * We have to get all characters, because we may delete the first part * of an escape sequence. * In an xterm we get one char at a time and we have to get them all. */ while (inchar(typebuf.tb_buf, typebuf.tb_buflen - 1, 10L, typebuf.tb_change_cnt) != 0) ; typebuf.tb_off = MAXMAPLEN; typebuf.tb_len = 0; } else /* remove mapped characters only */ { typebuf.tb_off += typebuf.tb_maplen; typebuf.tb_len -= typebuf.tb_maplen; } typebuf.tb_maplen = 0; typebuf.tb_silent = 0; cmd_silent = FALSE; typebuf.tb_no_abbr_cnt = 0; } /* * The previous contents of the redo buffer is kept in old_redobuffer. * This is used for the CTRL-O <.> command in insert mode. */ void ResetRedobuff() { if (!block_redo) { free_buff(&old_redobuff); old_redobuff = redobuff; redobuff.bh_first.b_next = NULL; } } #if defined(FEAT_AUTOCMD) || defined(FEAT_EVAL) || defined(PROTO) /* * Save redobuff and old_redobuff to save_redobuff and save_old_redobuff. * Used before executing autocommands and user functions. */ static int save_level = 0; void saveRedobuff() { char_u *s; if (save_level++ == 0) { save_redobuff = redobuff; redobuff.bh_first.b_next = NULL; save_old_redobuff = old_redobuff; old_redobuff.bh_first.b_next = NULL; /* Make a copy, so that ":normal ." in a function works. */ s = get_buffcont(&save_redobuff, FALSE); if (s != NULL) { add_buff(&redobuff, s, -1L); vim_free(s); } } }