mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
updated for version 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.
This commit is contained in:
parent
c467d9b274
commit
0a36fece92
147
src/getchar.c
147
src/getchar.c
@ -40,13 +40,13 @@
|
||||
|
||||
#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};
|
||||
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 struct buffheader save_redobuff = {{NULL, {NUL}}, NULL, 0, 0};
|
||||
static struct buffheader save_old_redobuff = {{NULL, {NUL}}, NULL, 0, 0};
|
||||
static buffheader_T save_redobuff = {{NULL, {NUL}}, NULL, 0, 0};
|
||||
static buffheader_T save_old_redobuff = {{NULL, {NUL}}, NULL, 0, 0};
|
||||
#endif
|
||||
static struct buffheader recordbuff = {{NULL, {NUL}}, NULL, 0, 0};
|
||||
static buffheader_T recordbuff = {{NULL, {NUL}}, NULL, 0, 0};
|
||||
|
||||
static int typeahead_char = 0; /* typeahead char that's not flushed */
|
||||
|
||||
@ -112,11 +112,12 @@ 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 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,9 +138,9 @@ static char_u *eval_map_expr __ARGS((char_u *str, int c));
|
||||
*/
|
||||
void
|
||||
free_buff(buf)
|
||||
struct buffheader *buf;
|
||||
buffheader_T *buf;
|
||||
{
|
||||
struct buffblock *p, *np;
|
||||
buffblock_T *p, *np;
|
||||
|
||||
for (p = buf->bh_first.b_next; p != NULL; p = np)
|
||||
{
|
||||
@ -155,14 +156,14 @@ free_buff(buf)
|
||||
*/
|
||||
static char_u *
|
||||
get_buffcont(buffer, dozero)
|
||||
struct buffheader *buffer;
|
||||
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;
|
||||
struct buffblock *bp;
|
||||
buffblock_T *bp;
|
||||
|
||||
/* compute the total length of the string */
|
||||
for (bp = buffer->bh_first.b_next; bp != NULL; bp = bp->b_next)
|
||||
@ -230,11 +231,11 @@ get_inserted()
|
||||
*/
|
||||
static void
|
||||
add_buff(buf, s, slen)
|
||||
struct buffheader *buf;
|
||||
buffheader_T *buf;
|
||||
char_u *s;
|
||||
long slen; /* length of "s" or -1 */
|
||||
{
|
||||
struct buffblock *p;
|
||||
buffblock_T *p;
|
||||
long_u len;
|
||||
|
||||
if (slen < 0)
|
||||
@ -270,7 +271,7 @@ add_buff(buf, s, slen)
|
||||
len = MINIMAL_SIZE;
|
||||
else
|
||||
len = slen;
|
||||
p = (struct buffblock *)lalloc((long_u)(sizeof(struct buffblock) + len),
|
||||
p = (buffblock_T *)lalloc((long_u)(sizeof(buffblock_T) + len),
|
||||
TRUE);
|
||||
if (p == NULL)
|
||||
return; /* no space, just forget it */
|
||||
@ -289,7 +290,7 @@ add_buff(buf, s, slen)
|
||||
*/
|
||||
static void
|
||||
add_num_buff(buf, n)
|
||||
struct buffheader *buf;
|
||||
buffheader_T *buf;
|
||||
long n;
|
||||
{
|
||||
char_u number[32];
|
||||
@ -304,7 +305,7 @@ add_num_buff(buf, n)
|
||||
*/
|
||||
static void
|
||||
add_char_buff(buf, c)
|
||||
struct buffheader *buf;
|
||||
buffheader_T *buf;
|
||||
int c;
|
||||
{
|
||||
#ifdef FEAT_MBYTE
|
||||
@ -354,46 +355,71 @@ add_char_buff(buf, c)
|
||||
#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 stuff buffer.
|
||||
* 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_stuff(advance)
|
||||
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;
|
||||
struct buffblock *curr;
|
||||
buffblock_T *curr;
|
||||
|
||||
if (stuffbuff.bh_first.b_next == NULL) /* buffer is empty */
|
||||
if (buf->bh_first.b_next == NULL) /* buffer is empty */
|
||||
return NUL;
|
||||
|
||||
curr = stuffbuff.bh_first.b_next;
|
||||
c = curr->b_str[stuffbuff.bh_index];
|
||||
curr = buf->bh_first.b_next;
|
||||
c = curr->b_str[buf->bh_index];
|
||||
|
||||
if (advance)
|
||||
{
|
||||
if (curr->b_str[++stuffbuff.bh_index] == NUL)
|
||||
if (curr->b_str[++buf->bh_index] == NUL)
|
||||
{
|
||||
stuffbuff.bh_first.b_next = curr->b_next;
|
||||
buf->bh_first.b_next = curr->b_next;
|
||||
vim_free(curr);
|
||||
stuffbuff.bh_index = 0;
|
||||
buf->bh_index = 0;
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prepare the stuff buffer for reading (if it contains something).
|
||||
* Prepare the read buffers for reading (if they contains something).
|
||||
*/
|
||||
static void
|
||||
start_stuff()
|
||||
{
|
||||
if (stuffbuff.bh_first.b_next != NULL)
|
||||
if (readbuf1.bh_first.b_next != NULL)
|
||||
{
|
||||
stuffbuff.bh_curr = &(stuffbuff.bh_first);
|
||||
stuffbuff.bh_space = 0;
|
||||
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,7 +429,18 @@ start_stuff()
|
||||
int
|
||||
stuff_empty()
|
||||
{
|
||||
return (stuffbuff.bh_first.b_next == NULL);
|
||||
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,7 +465,7 @@ flush_buffers(flush_typeahead)
|
||||
init_typebuf();
|
||||
|
||||
start_stuff();
|
||||
while (read_stuff(TRUE) != NUL)
|
||||
while (read_readbuffers(TRUE) != NUL)
|
||||
;
|
||||
|
||||
if (flush_typeahead) /* remove all typeahead */
|
||||
@ -483,7 +520,7 @@ CancelRedo()
|
||||
redobuff = old_redobuff;
|
||||
old_redobuff.bh_first.b_next = NULL;
|
||||
start_stuff();
|
||||
while (read_stuff(TRUE) != NUL)
|
||||
while (read_readbuffers(TRUE) != NUL)
|
||||
;
|
||||
}
|
||||
}
|
||||
@ -638,7 +675,7 @@ AppendNumberToRedobuff(n)
|
||||
stuffReadbuff(s)
|
||||
char_u *s;
|
||||
{
|
||||
add_buff(&stuffbuff, s, -1L);
|
||||
add_buff(&readbuf1, s, -1L);
|
||||
}
|
||||
|
||||
void
|
||||
@ -646,7 +683,7 @@ stuffReadbuffLen(s, len)
|
||||
char_u *s;
|
||||
long len;
|
||||
{
|
||||
add_buff(&stuffbuff, s, len);
|
||||
add_buff(&readbuf1, s, len);
|
||||
}
|
||||
|
||||
#if defined(FEAT_EVAL) || defined(PROTO)
|
||||
@ -692,7 +729,7 @@ stuffReadbuffSpec(s)
|
||||
stuffcharReadbuff(c)
|
||||
int c;
|
||||
{
|
||||
add_char_buff(&stuffbuff, c);
|
||||
add_char_buff(&readbuf1, c);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -702,7 +739,7 @@ stuffcharReadbuff(c)
|
||||
stuffnumReadbuff(n)
|
||||
long n;
|
||||
{
|
||||
add_num_buff(&stuffbuff, n);
|
||||
add_num_buff(&readbuf1, n);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -718,7 +755,7 @@ read_redo(init, old_redo)
|
||||
int init;
|
||||
int old_redo;
|
||||
{
|
||||
static struct buffblock *bp;
|
||||
static buffblock_T *bp;
|
||||
static char_u *p;
|
||||
int c;
|
||||
#ifdef FEAT_MBYTE
|
||||
@ -795,11 +832,11 @@ copy_redo(old_redo)
|
||||
int c;
|
||||
|
||||
while ((c = read_redo(FALSE, old_redo)) != NUL)
|
||||
stuffcharReadbuff(c);
|
||||
add_char_buff(&readbuf2, c);
|
||||
}
|
||||
|
||||
/*
|
||||
* Stuff the redo buffer into the stuffbuff.
|
||||
* 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,13 +860,13 @@ start_redo(count, old_redo)
|
||||
/* copy the buffer name, if present */
|
||||
if (c == '"')
|
||||
{
|
||||
add_buff(&stuffbuff, (char_u *)"\"", 1L);
|
||||
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(&stuffbuff, c);
|
||||
add_char_buff(&readbuf2, c);
|
||||
c = read_redo(FALSE, old_redo);
|
||||
}
|
||||
|
||||
@ -850,18 +887,18 @@ start_redo(count, old_redo)
|
||||
{
|
||||
while (VIM_ISDIGIT(c)) /* skip "old" count */
|
||||
c = read_redo(FALSE, old_redo);
|
||||
add_num_buff(&stuffbuff, count);
|
||||
add_num_buff(&readbuf2, count);
|
||||
}
|
||||
|
||||
/* copy from the redo buffer into the stuff buffer */
|
||||
add_char_buff(&stuffbuff, c);
|
||||
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 the stuffbuff.
|
||||
* the redo buffer into readbuf2.
|
||||
* return FAIL for failure, OK otherwise
|
||||
*/
|
||||
int
|
||||
@ -879,7 +916,7 @@ start_redo_ins()
|
||||
if (vim_strchr((char_u *)"AaIiRrOo", c) != NULL)
|
||||
{
|
||||
if (c == 'O' || c == 'o')
|
||||
stuffReadbuff(NL_STR);
|
||||
add_buff(&readbuf2, NL_STR, -1L);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1360,8 +1397,10 @@ save_typeahead(tp)
|
||||
tp->old_mod_mask = old_mod_mask;
|
||||
old_char = -1;
|
||||
|
||||
tp->save_stuffbuff = stuffbuff;
|
||||
stuffbuff.bh_first.b_next = NULL;
|
||||
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,8 +1423,10 @@ restore_typeahead(tp)
|
||||
old_char = tp->old_char;
|
||||
old_mod_mask = tp->old_mod_mask;
|
||||
|
||||
free_buff(&stuffbuff);
|
||||
stuffbuff = tp->save_stuffbuff;
|
||||
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,7 +2033,7 @@ vgetorpeek(advance)
|
||||
typeahead_char = 0;
|
||||
}
|
||||
else
|
||||
c = read_stuff(advance);
|
||||
c = read_readbuffers(advance);
|
||||
if (c != NUL && !got_int)
|
||||
{
|
||||
if (advance)
|
||||
|
@ -979,11 +979,6 @@ EXTERN int RedrawingDisabled INIT(= 0);
|
||||
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}
|
||||
|
11
src/normal.c
11
src/normal.c
@ -655,8 +655,8 @@ normal_cmd(oap, toplevel)
|
||||
#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())
|
||||
* when there is no count. Do set it for redo. */
|
||||
if (toplevel && readbuf1_empty())
|
||||
set_vcount_ca(&ca, &set_prevcount);
|
||||
#endif
|
||||
|
||||
@ -736,8 +736,8 @@ getcount:
|
||||
#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())
|
||||
* right after the count. Do set it for redo. */
|
||||
if (toplevel && readbuf1_empty())
|
||||
set_vcount_ca(&ca, &set_prevcount);
|
||||
#endif
|
||||
if (ctrl_w)
|
||||
@ -819,8 +819,9 @@ getcount:
|
||||
#ifdef FEAT_EVAL
|
||||
/*
|
||||
* Only set v:count when called from main() and not a stuffed command.
|
||||
* Do set it for redo.
|
||||
*/
|
||||
if (toplevel && stuff_empty())
|
||||
if (toplevel && readbuf1_empty())
|
||||
set_vcount(ca.count0, ca.count1, set_prevcount);
|
||||
#endif
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
/* getchar.c */
|
||||
void free_buff __ARGS((struct buffheader *buf));
|
||||
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));
|
||||
|
@ -471,12 +471,16 @@ struct nr_trans
|
||||
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
|
||||
{
|
||||
struct buffblock *b_next; /* pointer to next buffblock */
|
||||
buffblock_T *b_next; /* pointer to next buffblock */
|
||||
char_u b_str[1]; /* contents (actually longer) */
|
||||
};
|
||||
|
||||
@ -485,8 +489,8 @@ struct buffblock
|
||||
*/
|
||||
struct buffheader
|
||||
{
|
||||
struct buffblock bh_first; /* first (dummy) block of list */
|
||||
struct buffblock *bh_curr; /* buffblock for appending */
|
||||
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,7 +968,8 @@ typedef struct
|
||||
int typebuf_valid; /* TRUE when save_typebuf valid */
|
||||
int old_char;
|
||||
int old_mod_mask;
|
||||
struct buffheader save_stuffbuff;
|
||||
buffheader_T save_readbuf1;
|
||||
buffheader_T save_readbuf2;
|
||||
#ifdef USE_INPUT_BUF
|
||||
char_u *save_inputbuf;
|
||||
#endif
|
||||
|
@ -738,6 +738,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
171,
|
||||
/**/
|
||||
170,
|
||||
/**/
|
||||
|
Loading…
x
Reference in New Issue
Block a user