vi: move mark[i] pointers if text[] moves after realloc
While at it, optimized :s/find/repl/ a bit function old new delta text_hole_make 120 150 +30 colon 2848 2844 -4 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
7eaa03709b
commit
800a9a056a
64
editors/vi.c
64
editors/vi.c
@ -1040,13 +1040,13 @@ static void colon(char *buf)
|
|||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
#if ENABLE_FEATURE_VI_YANKMARK
|
#if ENABLE_FEATURE_VI_YANKMARK
|
||||||
if (Ureg >= 0 && Ureg < 28 && reg[Ureg] != 0) {
|
if (Ureg >= 0 && Ureg < 28) {
|
||||||
free(reg[Ureg]); // free orig line reg- for 'U'
|
free(reg[Ureg]); // free orig line reg- for 'U'
|
||||||
reg[Ureg]= 0;
|
reg[Ureg] = NULL;
|
||||||
}
|
}
|
||||||
if (YDreg >= 0 && YDreg < 28 && reg[YDreg] != 0) {
|
if (YDreg >= 0 && YDreg < 28) {
|
||||||
free(reg[YDreg]); // free default yank/delete register
|
free(reg[YDreg]); // free default yank/delete register
|
||||||
reg[YDreg]= 0;
|
reg[YDreg] = NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// how many lines in text[]?
|
// how many lines in text[]?
|
||||||
@ -1225,51 +1225,53 @@ static void colon(char *buf)
|
|||||||
#endif /* FEATURE_VI_SET */
|
#endif /* FEATURE_VI_SET */
|
||||||
#if ENABLE_FEATURE_VI_SEARCH
|
#if ENABLE_FEATURE_VI_SEARCH
|
||||||
} else if (cmd[0] == 's') { // substitute a pattern with a replacement pattern
|
} else if (cmd[0] == 's') { // substitute a pattern with a replacement pattern
|
||||||
char *ls, *F, *R;
|
char *F, *R, *flags;
|
||||||
int gflag;
|
size_t len_F, len_R;
|
||||||
|
int gflag; // global replace flag
|
||||||
|
|
||||||
// F points to the "find" pattern
|
// F points to the "find" pattern
|
||||||
// R points to the "replace" pattern
|
// R points to the "replace" pattern
|
||||||
// replace the cmd line delimiters "/" with NULLs
|
// replace the cmd line delimiters "/" with NULs
|
||||||
gflag = 0; // global replace flag
|
|
||||||
c = orig_buf[1]; // what is the delimiter
|
c = orig_buf[1]; // what is the delimiter
|
||||||
F = orig_buf + 2; // start of "find"
|
F = orig_buf + 2; // start of "find"
|
||||||
R = strchr(F, c); // middle delimiter
|
R = strchr(F, c); // middle delimiter
|
||||||
if (!R)
|
if (!R)
|
||||||
goto colon_s_fail;
|
goto colon_s_fail;
|
||||||
|
len_F = R - F;
|
||||||
*R++ = '\0'; // terminate "find"
|
*R++ = '\0'; // terminate "find"
|
||||||
buf1 = strchr(R, c);
|
flags = strchr(R, c);
|
||||||
if (!buf1)
|
if (!flags)
|
||||||
goto colon_s_fail;
|
goto colon_s_fail;
|
||||||
*buf1++ = '\0'; // terminate "replace"
|
len_R = flags - R;
|
||||||
if (*buf1 == 'g') { // :s/foo/bar/g
|
*flags++ = '\0'; // terminate "replace"
|
||||||
buf1++;
|
gflag = *flags;
|
||||||
gflag++; // turn on gflag
|
|
||||||
}
|
|
||||||
q = begin_line(q);
|
q = begin_line(q);
|
||||||
if (b < 0) { // maybe :s/foo/bar/
|
if (b < 0) { // maybe :s/foo/bar/
|
||||||
q = begin_line(dot); // start with cur line
|
q = begin_line(dot); // start with cur line
|
||||||
b = count_lines(text, q); // cur line number
|
b = count_lines(text, q); // cur line number
|
||||||
}
|
}
|
||||||
if (e < 0)
|
if (e < 0)
|
||||||
e = b; // maybe :.s/foo/bar/
|
e = b; // maybe :.s/foo/bar/
|
||||||
|
|
||||||
for (i = b; i <= e; i++) { // so, :20,23 s \0 find \0 replace \0
|
for (i = b; i <= e; i++) { // so, :20,23 s \0 find \0 replace \0
|
||||||
ls = q; // orig line start
|
char *ls = q; // orig line start
|
||||||
|
char *found;
|
||||||
vc4:
|
vc4:
|
||||||
buf1 = char_search(q, F, FORWARD, LIMITED); // search cur line only for "find"
|
found = char_search(q, F, FORWARD, LIMITED); // search cur line only for "find"
|
||||||
if (buf1) {
|
if (found) {
|
||||||
uintptr_t bias;
|
uintptr_t bias;
|
||||||
// we found the "find" pattern - delete it
|
// we found the "find" pattern - delete it
|
||||||
text_hole_delete(buf1, buf1 + strlen(F) - 1);
|
text_hole_delete(found, found + len_F - 1);
|
||||||
// inset the "replace" patern
|
// inset the "replace" patern
|
||||||
bias = string_insert(buf1, R); // insert the string
|
bias = string_insert(found, R); // insert the string
|
||||||
buf1 += bias;
|
found += bias;
|
||||||
ls += bias;
|
ls += bias;
|
||||||
/*q += bias; - recalculated anyway */
|
/*q += bias; - recalculated anyway */
|
||||||
// check for "global" :s/foo/bar/g
|
// check for "global" :s/foo/bar/g
|
||||||
if (gflag == 1) {
|
if (gflag == 'g') {
|
||||||
if ((buf1 + strlen(R)) < end_line(ls)) {
|
if ((found + len_R) < end_line(ls)) {
|
||||||
q = buf1 + strlen(R);
|
q = found + len_R;
|
||||||
goto vc4; // don't let q move past cur line
|
goto vc4; // don't let q move past cur line
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2073,6 +2075,14 @@ static uintptr_t text_hole_make(char *p, int size) // at "p", make a 'size' byte
|
|||||||
dot += bias;
|
dot += bias;
|
||||||
end += bias;
|
end += bias;
|
||||||
p += bias;
|
p += bias;
|
||||||
|
#if ENABLE_FEATURE_VI_YANKMARK
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < ARRAY_SIZE(mark); i++)
|
||||||
|
if (mark[i])
|
||||||
|
mark[i] += bias;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
text = new_text;
|
text = new_text;
|
||||||
}
|
}
|
||||||
memmove(p + size, p, end - size - p);
|
memmove(p + size, p, end - size - p);
|
||||||
@ -3305,7 +3315,7 @@ static void do_cmd(int c)
|
|||||||
end_cmd_q(); // stop adding to q
|
end_cmd_q(); // stop adding to q
|
||||||
break;
|
break;
|
||||||
case 'U': // U- Undo; replace current line with original version
|
case 'U': // U- Undo; replace current line with original version
|
||||||
if (reg[Ureg] != 0) {
|
if (reg[Ureg] != NULL) {
|
||||||
p = begin_line(dot);
|
p = begin_line(dot);
|
||||||
q = end_line(dot);
|
q = end_line(dot);
|
||||||
p = text_hole_delete(p, q); // delete cur line
|
p = text_hole_delete(p, q); // delete cur line
|
||||||
|
Loading…
x
Reference in New Issue
Block a user