To: vim_dev@googlegroups.com Subject: Patch 7.4.171 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 7.4.171 Problem: Redo does not set v:count and v:count1. Solution: Use a separate buffer for redo, so that we can set the counts when performing redo. Files: src/getchar.c, src/globals.h, src/normal.c, src/proto/getchar.pro, src/structs.h *** ../vim-7.4.170/src/getchar.c 2013-06-29 13:43:27.000000000 +0200 --- src/getchar.c 2014-02-11 14:54:46.830097259 +0100 *************** *** 40,52 **** #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 */ --- 40,52 ---- #define MINIMAL_SIZE 20 /* minimal size for b_str */ ! static buffheader_T redobuff = {{NULL, {NUL}}, NULL, 0, 0}; ! static buffheader_T old_redobuff = {{NULL, {NUL}}, NULL, 0, 0}; #if defined(FEAT_AUTOCMD) || defined(FEAT_EVAL) || defined(PROTO) ! static buffheader_T save_redobuff = {{NULL, {NUL}}, NULL, 0, 0}; ! static buffheader_T save_old_redobuff = {{NULL, {NUL}}, NULL, 0, 0}; #endif ! static buffheader_T recordbuff = {{NULL, {NUL}}, NULL, 0, 0}; static int typeahead_char = 0; /* typeahead char that's not flushed */ *************** *** 112,122 **** 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)); --- 112,123 ---- static int last_recorded_len = 0; /* number of last recorded chars */ ! static char_u *get_buffcont __ARGS((buffheader_T *, int)); ! static void add_buff __ARGS((buffheader_T *, char_u *, long n)); ! static void add_num_buff __ARGS((buffheader_T *, long)); ! static void add_char_buff __ARGS((buffheader_T *, int)); ! static int read_readbuffers __ARGS((int advance)); ! static int read_readbuf __ARGS((buffheader_T *buf, int advance)); static void start_stuff __ARGS((void)); static int read_redo __ARGS((int, int)); static void copy_redo __ARGS((int)); *************** *** 137,145 **** */ void free_buff(buf) ! struct buffheader *buf; { ! struct buffblock *p, *np; for (p = buf->bh_first.b_next; p != NULL; p = np) { --- 138,146 ---- */ void free_buff(buf) ! buffheader_T *buf; { ! buffblock_T *p, *np; for (p = buf->bh_first.b_next; p != NULL; p = np) { *************** *** 155,168 **** */ 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) --- 156,169 ---- */ static char_u * get_buffcont(buffer, dozero) ! buffheader_T *buffer; int dozero; /* count == zero is not an error */ { long_u count = 0; char_u *p = NULL; char_u *p2; char_u *str; ! buffblock_T *bp; /* compute the total length of the string */ for (bp = buffer->bh_first.b_next; bp != NULL; bp = bp->b_next) *************** *** 230,240 **** */ 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) --- 231,241 ---- */ static void add_buff(buf, s, slen) ! buffheader_T *buf; char_u *s; long slen; /* length of "s" or -1 */ { ! buffblock_T *p; long_u len; if (slen < 0) *************** *** 270,276 **** 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 */ --- 271,277 ---- len = MINIMAL_SIZE; else len = slen; ! p = (buffblock_T *)lalloc((long_u)(sizeof(buffblock_T) + len), TRUE); if (p == NULL) return; /* no space, just forget it */ *************** *** 289,295 **** */ static void add_num_buff(buf, n) ! struct buffheader *buf; long n; { char_u number[32]; --- 290,296 ---- */ static void add_num_buff(buf, n) ! buffheader_T *buf; long n; { char_u number[32]; *************** *** 304,310 **** */ static void add_char_buff(buf, c) ! struct buffheader *buf; int c; { #ifdef FEAT_MBYTE --- 305,311 ---- */ static void add_char_buff(buf, c) ! buffheader_T *buf; int c; { #ifdef FEAT_MBYTE *************** *** 354,399 **** #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; } } --- 355,425 ---- #endif } + /* First read ahead buffer. Used for translated commands. */ + static buffheader_T readbuf1 = {{NULL, {NUL}}, NULL, 0, 0}; + + /* Second read ahead buffer. Used for redo. */ + static buffheader_T readbuf2 = {{NULL, {NUL}}, NULL, 0, 0}; + /* ! * Get one byte from the read buffers. Use readbuf1 one first, use readbuf2 ! * if that one is empty. * If advance == TRUE go to the next char. * No translation is done K_SPECIAL and CSI are escaped. */ static int ! read_readbuffers(advance) int advance; { ! int c; ! ! c = read_readbuf(&readbuf1, advance); ! if (c == NUL) ! c = read_readbuf(&readbuf2, advance); ! return c; ! } ! ! static int ! read_readbuf(buf, advance) ! buffheader_T *buf; ! int advance; ! { ! char_u c; ! buffblock_T *curr; ! if (buf->bh_first.b_next == NULL) /* buffer is empty */ return NUL; ! curr = buf->bh_first.b_next; ! c = curr->b_str[buf->bh_index]; if (advance) { ! if (curr->b_str[++buf->bh_index] == NUL) { ! buf->bh_first.b_next = curr->b_next; vim_free(curr); ! buf->bh_index = 0; } } return c; } /* ! * Prepare the read buffers for reading (if they contains something). */ static void start_stuff() { ! if (readbuf1.bh_first.b_next != NULL) { ! readbuf1.bh_curr = &(readbuf1.bh_first); ! readbuf1.bh_space = 0; ! } ! if (readbuf2.bh_first.b_next != NULL) ! { ! readbuf2.bh_curr = &(readbuf2.bh_first); ! readbuf2.bh_space = 0; } } *************** *** 403,409 **** int stuff_empty() { ! return (stuffbuff.bh_first.b_next == NULL); } /* --- 429,446 ---- int stuff_empty() { ! return (readbuf1.bh_first.b_next == NULL ! && readbuf2.bh_first.b_next == NULL); ! } ! ! /* ! * Return TRUE if readbuf1 is empty. There may still be redo characters in ! * redbuf2. ! */ ! int ! readbuf1_empty() ! { ! return (readbuf1.bh_first.b_next == NULL); } /* *************** *** 428,434 **** init_typebuf(); start_stuff(); ! while (read_stuff(TRUE) != NUL) ; if (flush_typeahead) /* remove all typeahead */ --- 465,471 ---- init_typebuf(); start_stuff(); ! while (read_readbuffers(TRUE) != NUL) ; if (flush_typeahead) /* remove all typeahead */ *************** *** 483,489 **** redobuff = old_redobuff; old_redobuff.bh_first.b_next = NULL; start_stuff(); ! while (read_stuff(TRUE) != NUL) ; } } --- 520,526 ---- redobuff = old_redobuff; old_redobuff.bh_first.b_next = NULL; start_stuff(); ! while (read_readbuffers(TRUE) != NUL) ; } } *************** *** 638,644 **** stuffReadbuff(s) char_u *s; { ! add_buff(&stuffbuff, s, -1L); } void --- 675,681 ---- stuffReadbuff(s) char_u *s; { ! add_buff(&readbuf1, s, -1L); } void *************** *** 646,652 **** char_u *s; long len; { ! add_buff(&stuffbuff, s, len); } #if defined(FEAT_EVAL) || defined(PROTO) --- 683,689 ---- char_u *s; long len; { ! add_buff(&readbuf1, s, len); } #if defined(FEAT_EVAL) || defined(PROTO) *************** *** 692,698 **** stuffcharReadbuff(c) int c; { ! add_char_buff(&stuffbuff, c); } /* --- 729,735 ---- stuffcharReadbuff(c) int c; { ! add_char_buff(&readbuf1, c); } /* *************** *** 702,708 **** stuffnumReadbuff(n) long n; { ! add_num_buff(&stuffbuff, n); } /* --- 739,745 ---- stuffnumReadbuff(n) long n; { ! add_num_buff(&readbuf1, n); } /* *************** *** 718,730 **** int init; int old_redo; { ! static struct buffblock *bp; ! static char_u *p; ! int c; #ifdef FEAT_MBYTE ! int n; ! char_u buf[MB_MAXBYTES + 1]; ! int i; #endif if (init) --- 755,767 ---- int init; int old_redo; { ! static buffblock_T *bp; ! static char_u *p; ! int c; #ifdef FEAT_MBYTE ! int n; ! char_u buf[MB_MAXBYTES + 1]; ! int i; #endif if (init) *************** *** 795,805 **** int c; while ((c = read_redo(FALSE, old_redo)) != NUL) ! stuffcharReadbuff(c); } /* ! * Stuff the redo buffer into the stuffbuff. * Insert the redo count into the command. * If "old_redo" is TRUE, the last but one command is repeated * instead of the last command (inserting text). This is used for --- 832,842 ---- int c; while ((c = read_redo(FALSE, old_redo)) != NUL) ! add_char_buff(&readbuf2, c); } /* ! * Stuff the redo buffer into readbuf2. * Insert the redo count into the command. * If "old_redo" is TRUE, the last but one command is repeated * instead of the last command (inserting text). This is used for *************** *** 823,835 **** /* copy the buffer name, if present */ if (c == '"') { ! add_buff(&stuffbuff, (char_u *)"\"", 1L); c = read_redo(FALSE, old_redo); /* if a numbered buffer is used, increment the number */ if (c >= '1' && c < '9') ++c; ! add_char_buff(&stuffbuff, c); c = read_redo(FALSE, old_redo); } --- 860,872 ---- /* copy the buffer name, if present */ if (c == '"') { ! add_buff(&readbuf2, (char_u *)"\"", 1L); c = read_redo(FALSE, old_redo); /* if a numbered buffer is used, increment the number */ if (c >= '1' && c < '9') ++c; ! add_char_buff(&readbuf2, c); c = read_redo(FALSE, old_redo); } *************** *** 850,867 **** { while (VIM_ISDIGIT(c)) /* skip "old" count */ c = read_redo(FALSE, old_redo); ! add_num_buff(&stuffbuff, count); } /* copy from the redo buffer into the stuff buffer */ ! add_char_buff(&stuffbuff, c); copy_redo(old_redo); return OK; } /* * Repeat the last insert (R, o, O, a, A, i or I command) by stuffing ! * the redo buffer into the stuffbuff. * return FAIL for failure, OK otherwise */ int --- 887,904 ---- { while (VIM_ISDIGIT(c)) /* skip "old" count */ c = read_redo(FALSE, old_redo); ! add_num_buff(&readbuf2, count); } /* copy from the redo buffer into the stuff buffer */ ! add_char_buff(&readbuf2, c); copy_redo(old_redo); return OK; } /* * Repeat the last insert (R, o, O, a, A, i or I command) by stuffing ! * the redo buffer into readbuf2. * return FAIL for failure, OK otherwise */ int *************** *** 879,885 **** if (vim_strchr((char_u *)"AaIiRrOo", c) != NULL) { if (c == 'O' || c == 'o') ! stuffReadbuff(NL_STR); break; } } --- 916,922 ---- if (vim_strchr((char_u *)"AaIiRrOo", c) != NULL) { if (c == 'O' || c == 'o') ! add_buff(&readbuf2, NL_STR, -1L); break; } } *************** *** 1360,1367 **** tp->old_mod_mask = old_mod_mask; old_char = -1; ! tp->save_stuffbuff = stuffbuff; ! stuffbuff.bh_first.b_next = NULL; # ifdef USE_INPUT_BUF tp->save_inputbuf = get_input_buf(); # endif --- 1397,1406 ---- tp->old_mod_mask = old_mod_mask; old_char = -1; ! tp->save_readbuf1 = readbuf1; ! readbuf1.bh_first.b_next = NULL; ! tp->save_readbuf2 = readbuf2; ! readbuf2.bh_first.b_next = NULL; # ifdef USE_INPUT_BUF tp->save_inputbuf = get_input_buf(); # endif *************** *** 1384,1391 **** old_char = tp->old_char; old_mod_mask = tp->old_mod_mask; ! free_buff(&stuffbuff); ! stuffbuff = tp->save_stuffbuff; # ifdef USE_INPUT_BUF set_input_buf(tp->save_inputbuf); # endif --- 1423,1432 ---- old_char = tp->old_char; old_mod_mask = tp->old_mod_mask; ! free_buff(&readbuf1); ! readbuf1 = tp->save_readbuf1; ! free_buff(&readbuf2); ! readbuf2 = tp->save_readbuf2; # ifdef USE_INPUT_BUF set_input_buf(tp->save_inputbuf); # endif *************** *** 1992,1998 **** typeahead_char = 0; } else ! c = read_stuff(advance); if (c != NUL && !got_int) { if (advance) --- 2033,2039 ---- typeahead_char = 0; } else ! c = read_readbuffers(advance); if (c != NUL && !got_int) { if (advance) *** ../vim-7.4.170/src/globals.h 2013-11-09 03:31:45.000000000 +0100 --- src/globals.h 2014-02-11 14:17:44.070063200 +0100 *************** *** 979,989 **** EXTERN int readonlymode INIT(= FALSE); /* Set to TRUE for "view" */ EXTERN int recoverymode INIT(= FALSE); /* Set to TRUE for "-r" option */ - EXTERN struct buffheader stuffbuff /* stuff buffer */ - #ifdef DO_INIT - = {{NULL, {NUL}}, NULL, 0, 0} - #endif - ; EXTERN typebuf_T typebuf /* typeahead buffer */ #ifdef DO_INIT = {NULL, NULL, 0, 0, 0, 0, 0, 0, 0} --- 979,984 ---- *** ../vim-7.4.170/src/normal.c 2014-01-14 13:18:53.000000000 +0100 --- src/normal.c 2014-02-11 14:53:54.246096453 +0100 *************** *** 655,662 **** #ifdef FEAT_EVAL /* Set v:count here, when called from main() and not a stuffed * command, so that v:count can be used in an expression mapping ! * when there is no count. */ ! if (toplevel && stuff_empty()) set_vcount_ca(&ca, &set_prevcount); #endif --- 655,662 ---- #ifdef FEAT_EVAL /* Set v:count here, when called from main() and not a stuffed * command, so that v:count can be used in an expression mapping ! * when there is no count. Do set it for redo. */ ! if (toplevel && readbuf1_empty()) set_vcount_ca(&ca, &set_prevcount); #endif *************** *** 736,743 **** #ifdef FEAT_EVAL /* Set v:count here, when called from main() and not a stuffed * command, so that v:count can be used in an expression mapping ! * right after the count. */ ! if (toplevel && stuff_empty()) set_vcount_ca(&ca, &set_prevcount); #endif if (ctrl_w) --- 736,743 ---- #ifdef FEAT_EVAL /* Set v:count here, when called from main() and not a stuffed * command, so that v:count can be used in an expression mapping ! * right after the count. Do set it for redo. */ ! if (toplevel && readbuf1_empty()) set_vcount_ca(&ca, &set_prevcount); #endif if (ctrl_w) *************** *** 819,826 **** #ifdef FEAT_EVAL /* * Only set v:count when called from main() and not a stuffed command. */ ! if (toplevel && stuff_empty()) set_vcount(ca.count0, ca.count1, set_prevcount); #endif --- 819,827 ---- #ifdef FEAT_EVAL /* * Only set v:count when called from main() and not a stuffed command. + * Do set it for redo. */ ! if (toplevel && readbuf1_empty()) set_vcount(ca.count0, ca.count1, set_prevcount); #endif *** ../vim-7.4.170/src/proto/getchar.pro 2013-08-10 13:37:12.000000000 +0200 --- src/proto/getchar.pro 2014-02-11 14:55:14.806097687 +0100 *************** *** 1,8 **** /* getchar.c */ ! void free_buff __ARGS((struct buffheader *buf)); char_u *get_recorded __ARGS((void)); char_u *get_inserted __ARGS((void)); int stuff_empty __ARGS((void)); void typeahead_noflush __ARGS((int c)); void flush_buffers __ARGS((int flush_typeahead)); void ResetRedobuff __ARGS((void)); --- 1,9 ---- /* getchar.c */ ! void free_buff __ARGS((buffheader_T *buf)); char_u *get_recorded __ARGS((void)); char_u *get_inserted __ARGS((void)); int stuff_empty __ARGS((void)); + int readbuf1_empty __ARGS((void)); void typeahead_noflush __ARGS((int c)); void flush_buffers __ARGS((int flush_typeahead)); void ResetRedobuff __ARGS((void)); *** ../vim-7.4.170/src/structs.h 2013-11-12 04:43:57.000000000 +0100 --- src/structs.h 2014-02-11 14:35:43.606079741 +0100 *************** *** 471,483 **** blocknr_T nt_new_bnum; /* new, positive, number */ }; /* * structure used to store one block of the stuff/redo/recording buffers */ struct buffblock { ! struct buffblock *b_next; /* pointer to next buffblock */ ! char_u b_str[1]; /* contents (actually longer) */ }; /* --- 471,487 ---- blocknr_T nt_new_bnum; /* new, positive, number */ }; + + typedef struct buffblock buffblock_T; + typedef struct buffheader buffheader_T; + /* * structure used to store one block of the stuff/redo/recording buffers */ struct buffblock { ! buffblock_T *b_next; /* pointer to next buffblock */ ! char_u b_str[1]; /* contents (actually longer) */ }; /* *************** *** 485,494 **** */ struct buffheader { ! struct buffblock bh_first; /* first (dummy) block of list */ ! struct buffblock *bh_curr; /* buffblock for appending */ ! int bh_index; /* index for reading */ ! int bh_space; /* space in bh_curr for appending */ }; /* --- 489,498 ---- */ struct buffheader { ! buffblock_T bh_first; /* first (dummy) block of list */ ! buffblock_T *bh_curr; /* buffblock for appending */ ! int bh_index; /* index for reading */ ! int bh_space; /* space in bh_curr for appending */ }; /* *************** *** 964,970 **** int typebuf_valid; /* TRUE when save_typebuf valid */ int old_char; int old_mod_mask; ! struct buffheader save_stuffbuff; #ifdef USE_INPUT_BUF char_u *save_inputbuf; #endif --- 968,975 ---- int typebuf_valid; /* TRUE when save_typebuf valid */ int old_char; int old_mod_mask; ! buffheader_T save_readbuf1; ! buffheader_T save_readbuf2; #ifdef USE_INPUT_BUF char_u *save_inputbuf; #endif *** ../vim-7.4.170/src/version.c 2014-02-11 12:15:39.781950970 +0100 --- src/version.c 2014-02-11 15:05:17.306106920 +0100 *************** *** 740,741 **** --- 740,743 ---- { /* Add new patch number below this line */ + /**/ + 171, /**/ -- Linux is just like a wigwam: no Windows, no Gates and an Apache inside. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///