vim-patch: 7.4.330

Problem:    Using a regexp pattern to highlight a specific position can
be slow.
Solution:   Add matchaddpos() to highlight specific positions
efficiently.
(Alexey Radkov.)

https://code.google.com/p/vim/source/detail?r=f9fa2e506b9f07549cd91074835c5c553db7b3a7
This commit is contained in:
Felipe Morales
2014-08-22 20:45:26 -04:00
parent 057f26f0a6
commit bf3d945798
8 changed files with 370 additions and 69 deletions

View File

@@ -880,6 +880,28 @@ typedef struct {
proftime_T tm; /* for a time limit */ proftime_T tm; /* for a time limit */
} match_T; } match_T;
/// number of positions supported by matchaddpos()
#define MAXPOSMATCH 8
/// Same as lpos_T, but with additional field len.
typedef struct
{
linenr_T lnum; ///< line number
colnr_T col; ///< column number
int len; ///< length: 0 - to the end of line
} llpos_T;
/// posmatch_T provides an array for storing match items for matchaddpos()
/// function.
typedef struct posmatch posmatch_T;
struct posmatch
{
llpos_T pos[MAXPOSMATCH]; ///< array of positions
int cur; ///< internal position counter
linenr_T toplnum; ///< top buffer line
linenr_T botlnum; ///< bottom buffer line
};
/* /*
* matchitem_T provides a linked list for storing match items for ":match" and * matchitem_T provides a linked list for storing match items for ":match" and
* the match functions. * the match functions.
@@ -892,6 +914,7 @@ struct matchitem {
char_u *pattern; /* pattern to highlight */ char_u *pattern; /* pattern to highlight */
int hlg_id; /* highlight group ID */ int hlg_id; /* highlight group ID */
regmmatch_T match; /* regexp program for pattern */ regmmatch_T match; /* regexp program for pattern */
posmatch_T pos; // position matches
match_T hl; /* struct for doing the actual highlighting */ match_T hl; /* struct for doing the actual highlighting */
}; };

View File

@@ -6456,6 +6456,7 @@ static struct fst {
{"mapcheck", 1, 3, f_mapcheck}, {"mapcheck", 1, 3, f_mapcheck},
{"match", 2, 4, f_match}, {"match", 2, 4, f_match},
{"matchadd", 2, 4, f_matchadd}, {"matchadd", 2, 4, f_matchadd},
{"matchaddpos", 2, 4, f_matchaddpos},
{"matcharg", 1, 1, f_matcharg}, {"matcharg", 1, 1, f_matcharg},
{"matchdelete", 1, 1, f_matchdelete}, {"matchdelete", 1, 1, f_matchdelete},
{"matchend", 2, 4, f_matchend}, {"matchend", 2, 4, f_matchend},
@@ -9300,12 +9301,34 @@ static void f_getline(typval_T *argvars, typval_T *rettv)
static void f_getmatches(typval_T *argvars, typval_T *rettv) static void f_getmatches(typval_T *argvars, typval_T *rettv)
{ {
matchitem_T *cur = curwin->w_match_head; matchitem_T *cur = curwin->w_match_head;
int i;
rettv_list_alloc(rettv); rettv_list_alloc(rettv);
while (cur != NULL) { while (cur != NULL) {
dict_T *dict = dict_alloc(); dict_T *dict = dict_alloc();
dict_add_nr_str(dict, "group", 0L, syn_id2name(cur->hlg_id)); if (cur->match.regprog == NULL) {
// match added with matchaddpos()
for (i = 0; i < MAXPOSMATCH; ++i) {
llpos_T *llpos;
char buf[6];
llpos = &cur->pos.pos[i];
if (llpos->lnum == 0) {
break;
}
list_T *l = list_alloc();
list_append_number(l, (varnumber_T)llpos->lnum);
if (llpos->col > 0) {
list_append_number(l, (varnumber_T)llpos->col);
list_append_number(l, (varnumber_T)llpos->len);
}
sprintf(buf, "pos%d", i + 1);
dict_add_list(dict, buf, l);
}
} else {
dict_add_nr_str(dict, "pattern", 0L, cur->pattern); dict_add_nr_str(dict, "pattern", 0L, cur->pattern);
}
dict_add_nr_str(dict, "group", 0L, syn_id2name(cur->hlg_id));
dict_add_nr_str(dict, "priority", (long)cur->priority, NULL); dict_add_nr_str(dict, "priority", (long)cur->priority, NULL);
dict_add_nr_str(dict, "id", (long)cur->id, NULL); dict_add_nr_str(dict, "id", (long)cur->id, NULL);
list_append_dict(rettv->vval.v_list, dict); list_append_dict(rettv->vval.v_list, dict);
@@ -11104,7 +11127,52 @@ static void f_matchadd(typval_T *argvars, typval_T *rettv)
return; return;
} }
rettv->vval.v_number = match_add(curwin, grp, pat, prio, id); rettv->vval.v_number = match_add(curwin, grp, pat, prio, id, NULL);
}
static void f_matchaddpos(typval_T *argvars, typval_T *rettv) FUNC_ATTR_NONNULL_ALL
{
rettv->vval.v_number = -1;
char_u buf[NUMBUFLEN];
char_u *group;
group = get_tv_string_buf_chk(&argvars[0], buf);
if (group == NULL) {
return;
}
if (argvars[1].v_type != VAR_LIST) {
EMSG2(_(e_listarg), "matchaddpos()");
return;
}
list_T *l;
l = argvars[1].vval.v_list;
if (l == NULL) {
return;
}
int error = false;
int prio = 10;
int id = -1;
if (argvars[2].v_type != VAR_UNKNOWN) {
prio = get_tv_number_chk(&argvars[2], &error);
if (argvars[3].v_type != VAR_UNKNOWN) {
id = get_tv_number_chk(&argvars[3], &error);
}
}
if (error == true) {
return;
}
// id == 3 is ok because matchaddpos() is supposed to substitute :3match
if (id == 1 || id == 2) {
EMSGN("E798: ID is reserved for \"match\": %" PRId64, id);
return;
}
rettv->vval.v_number = match_add(curwin, group, NULL, prio, id, l);
} }
/* /*
@@ -12914,7 +12982,7 @@ static void f_setmatches(typval_T *argvars, typval_T *rettv)
match_add(curwin, get_dict_string(d, (char_u *)"group", FALSE), match_add(curwin, get_dict_string(d, (char_u *)"group", FALSE),
get_dict_string(d, (char_u *)"pattern", FALSE), get_dict_string(d, (char_u *)"pattern", FALSE),
(int)get_dict_number(d, (char_u *)"priority"), (int)get_dict_number(d, (char_u *)"priority"),
(int)get_dict_number(d, (char_u *)"id")); (int)get_dict_number(d, (char_u *)"id"), NULL);
li = li->li_next; li = li->li_next;
} }
rettv->vval.v_number = 0; rettv->vval.v_number = 0;

View File

@@ -8859,7 +8859,7 @@ static void ex_match(exarg_T *eap)
c = *end; c = *end;
*end = NUL; *end = NUL;
match_add(curwin, g, p + 1, 10, id); match_add(curwin, g, p + 1, 10, id, NULL);
free(g); free(g);
*end = c; *end = c;
} }

View File

@@ -2658,38 +2658,42 @@ win_line (
shl->startcol = MAXCOL; shl->startcol = MAXCOL;
shl->endcol = MAXCOL; shl->endcol = MAXCOL;
shl->attr_cur = 0; shl->attr_cur = 0;
if (shl->rm.regprog != NULL) {
v = (long)(ptr - line); v = (long)(ptr - line);
next_search_hl(wp, shl, lnum, (colnr_T)v); if (cur != NULL) {
cur->pos.cur = 0;
}
next_search_hl(wp, shl, lnum, (colnr_T)v, cur);
/* Need to get the line again, a multi-line regexp may have made it // Need to get the line again, a multi-line regexp may have made it
* invalid. */ // invalid.
line = ml_get_buf(wp->w_buffer, lnum, FALSE); line = ml_get_buf(wp->w_buffer, lnum, false);
ptr = line + v; ptr = line + v;
if (shl->lnum != 0 && shl->lnum <= lnum) { if (shl->lnum != 0 && shl->lnum <= lnum) {
if (shl->lnum == lnum) if (shl->lnum == lnum) {
shl->startcol = shl->rm.startpos[0].col; shl->startcol = shl->rm.startpos[0].col;
else } else {
shl->startcol = 0; shl->startcol = 0;
}
if (lnum == shl->lnum + shl->rm.endpos[0].lnum if (lnum == shl->lnum + shl->rm.endpos[0].lnum
- shl->rm.startpos[0].lnum) - shl->rm.startpos[0].lnum) {
shl->endcol = shl->rm.endpos[0].col; shl->endcol = shl->rm.endpos[0].col;
else } else {
shl->endcol = MAXCOL; shl->endcol = MAXCOL;
/* Highlight one character for an empty match. */ }
// Highlight one character for an empty match.
if (shl->startcol == shl->endcol) { if (shl->startcol == shl->endcol) {
if (has_mbyte && line[shl->endcol] != NUL) if (has_mbyte && line[shl->endcol] != NUL) {
shl->endcol += (*mb_ptr2len)(line + shl->endcol); shl->endcol += (*mb_ptr2len)(line + shl->endcol);
else } else {
++shl->endcol; ++shl->endcol;
} }
if ((long)shl->startcol < v) { /* match at leftcol */ }
if ((long)shl->startcol < v) { // match at leftcol
shl->attr_cur = shl->attr; shl->attr_cur = shl->attr;
search_attr = shl->attr; search_attr = shl->attr;
} }
area_highlighting = TRUE; area_highlighting = true;
}
} }
if (shl != &search_hl && cur != NULL) if (shl != &search_hl && cur != NULL)
cur = cur->next; cur = cur->next;
@@ -2701,7 +2705,7 @@ win_line (
if (wp->w_p_cul && lnum == wp->w_cursor.lnum if (wp->w_p_cul && lnum == wp->w_cursor.lnum
&& !(wp == curwin && VIsual_active)) { && !(wp == curwin && VIsual_active)) {
line_attr = hl_attr(HLF_CUL); line_attr = hl_attr(HLF_CUL);
area_highlighting = TRUE; area_highlighting = true;
} }
off = (unsigned)(current_ScreenLine - ScreenLines); off = (unsigned)(current_ScreenLine - ScreenLines);
@@ -2942,7 +2946,13 @@ win_line (
shl_flag = TRUE; shl_flag = TRUE;
} else } else
shl = &cur->hl; shl = &cur->hl;
while (shl->rm.regprog != NULL) { if (cur != NULL) {
cur->pos.cur = 0;
}
bool pos_inprogress = true; // mark that a position match search is
// in progress
while (shl->rm.regprog != NULL
|| (cur != NULL && pos_inprogress)) {
if (shl->startcol != MAXCOL if (shl->startcol != MAXCOL
&& v >= (long)shl->startcol && v >= (long)shl->startcol
&& v < (long)shl->endcol) { && v < (long)shl->endcol) {
@@ -2950,7 +2960,8 @@ win_line (
} else if (v == (long)shl->endcol) { } else if (v == (long)shl->endcol) {
shl->attr_cur = 0; shl->attr_cur = 0;
next_search_hl(wp, shl, lnum, (colnr_T)v); next_search_hl(wp, shl, lnum, (colnr_T)v, cur);
pos_inprogress = !(cur == NULL || cur->pos.cur == 0);
/* Need to get the line again, a multi-line regexp /* Need to get the line again, a multi-line regexp
* may have made it invalid. */ * may have made it invalid. */
@@ -5602,9 +5613,16 @@ static void prepare_search_hl(win_T *wp, linenr_T lnum)
NULL, NULL, TRUE, NULL)) NULL, NULL, TRUE, NULL))
break; break;
} }
if (cur != NULL) {
cur->pos.cur = 0;
}
bool pos_inprogress = true; // mark that a position match search is
// in progress
n = 0; n = 0;
while (shl->first_lnum < lnum && shl->rm.regprog != NULL) { while (shl->first_lnum < lnum && (shl->rm.regprog != NULL
next_search_hl(wp, shl, shl->first_lnum, (colnr_T)n); || (cur != NULL && pos_inprogress))) {
next_search_hl(wp, shl, shl->first_lnum, (colnr_T)n, cur);
pos_inprogress = !(cur == NULL || cur->pos.cur == 0);
if (shl->lnum != 0) { if (shl->lnum != 0) {
shl->first_lnum = shl->lnum shl->first_lnum = shl->lnum
+ shl->rm.endpos[0].lnum + shl->rm.endpos[0].lnum
@@ -5634,12 +5652,13 @@ next_search_hl (
win_T *win, win_T *win,
match_T *shl, /* points to search_hl or a match */ match_T *shl, /* points to search_hl or a match */
linenr_T lnum, linenr_T lnum,
colnr_T mincol /* minimal column for a match */ colnr_T mincol, /* minimal column for a match */
matchitem_T *cur /* to retrieve match positions if any */
) )
{ {
linenr_T l; linenr_T l;
colnr_T matchcol; colnr_T matchcol;
long nmatched; long nmatched = 0;
if (shl->lnum != 0) { if (shl->lnum != 0) {
/* Check for three situations: /* Check for three situations:
@@ -5693,21 +5712,24 @@ next_search_hl (
matchcol = shl->rm.endpos[0].col; matchcol = shl->rm.endpos[0].col;
shl->lnum = lnum; shl->lnum = lnum;
nmatched = vim_regexec_multi(&shl->rm, win, shl->buf, lnum, matchcol, if (shl->rm.regprog != NULL) {
&(shl->tm) nmatched = vim_regexec_multi(&shl->rm, win, shl->buf, lnum, matchcol, &(shl->tm));
);
if (called_emsg || got_int) { if (called_emsg || got_int) {
/* Error while handling regexp: stop using this regexp. */ // Error while handling regexp: stop using this regexp.
if (shl == &search_hl) { if (shl == &search_hl) {
/* don't free regprog in the match list, it's a copy */ // don't free regprog in the match list, it's a copy
vim_regfree(shl->rm.regprog); vim_regfree(shl->rm.regprog);
SET_NO_HLSEARCH(TRUE); SET_NO_HLSEARCH(TRUE);
} }
shl->rm.regprog = NULL; shl->rm.regprog = NULL;
shl->lnum = 0; shl->lnum = 0;
got_int = FALSE; /* avoid the "Type :quit to exit Vim" message */ got_int = FALSE; /* avoid the "Type :quit to exit Vim"
message */
break; break;
} }
} else if (cur != NULL) {
nmatched = next_search_hl_pos(shl, lnum, &(cur->pos), matchcol);
}
if (nmatched == 0) { if (nmatched == 0) {
shl->lnum = 0; /* no match found */ shl->lnum = 0; /* no match found */
break; break;
@@ -5722,6 +5744,59 @@ next_search_hl (
} }
} }
static int
next_search_hl_pos(
match_T *shl, // points to a match
linenr_T lnum,
posmatch_T *posmatch, // match positions
colnr_T mincol // minimal column for a match
)
{
int i;
int bot = -1;
shl->lnum = 0;
for (i = posmatch->cur; i < MAXPOSMATCH; i++) {
if (posmatch->pos[i].lnum == 0) {
break;
}
if (posmatch->pos[i].col < mincol) {
continue;
}
if (posmatch->pos[i].lnum == lnum) {
if (shl->lnum == lnum) {
// partially sort positions by column numbers
// on the same line
if (posmatch->pos[i].col < posmatch->pos[bot].col) {
llpos_T tmp = posmatch->pos[i];
posmatch->pos[i] = posmatch->pos[bot];
posmatch->pos[bot] = tmp;
}
} else {
bot = i;
shl->lnum = lnum;
}
}
}
posmatch->cur = 0;
if (shl->lnum == lnum) {
colnr_T start = posmatch->pos[bot].col == 0
? 0: posmatch->pos[bot].col - 1;
colnr_T end = posmatch->pos[bot].col == 0
? MAXCOL : start + posmatch->pos[bot].len;
shl->rm.startpos[0].lnum = 0;
shl->rm.startpos[0].col = start;
shl->rm.endpos[0].lnum = 0;
shl->rm.endpos[0].col = end;
posmatch->cur = bot + 1;
return true;
}
return false;
}
static void screen_start_highlight(int attr) static void screen_start_highlight(int attr)
{ {
attrentry_T *aep = NULL; attrentry_T *aep = NULL;

View File

@@ -1,5 +1,5 @@
Test for ":match", ":2match", ":3match", "clearmatches()", "getmatches()", Test for ":match", ":2match", ":3match", "clearmatches()", "getmatches()",
"matchadd()", "matcharg()", "matchdelete()", and "setmatches()". "matchadd()", "matchaddpos()", "matcharg()", "matchdelete()", and "setmatches()".
STARTTEST STARTTEST
:so small.vim :so small.vim
@@ -147,9 +147,26 @@ STARTTEST
:unlet rf1 :unlet rf1
:unlet rf2 :unlet rf2
:unlet rf3 :unlet rf3
:highlight clear MyGroup1 :" --- Check that "matchaddpos()" positions matches correctly
:highlight clear MyGroup2 :let @r .= "*** Test 11:\n"
:highlight clear MyGroup3 :set nolazyredraw
:call setline(1, 'abcdefghijklmnopq')
:call matchaddpos("MyGroup1", [[1, 5], [1, 8, 3]], 10, 3)
:1
:redraw!
:let v1 = screenattr(1, 1)
:let v5 = screenattr(1, 5)
:let v6 = screenattr(1, 6)
:let v8 = screenattr(1, 8)
:let v10 = screenattr(1, 10)
:let v11 = screenattr(1, 11)
:let @r .= string(getmatches())."\n"
:if v1 != v5 && v6 == v1 && v8 == v5 && v10 == v5 && v11 == v1
: let @r .= "OK\n"
:else
: let @r .= "FAILED\n"
:endif
:call clearmatches()
G"rp G"rp
:/^Results/,$wq! test.out :/^Results/,$wq! test.out
ENDTEST ENDTEST

View File

@@ -9,3 +9,6 @@ Results of test63:
*** Test 8: OK *** Test 8: OK
*** Test 9: OK *** Test 9: OK
*** Test 10: OK *** Test 10: OK
*** Test 11:
[{'group': 'MyGroup1', 'id': 3, 'priority': 10, 'pos1': [1, 5, 1], 'pos2': [1, 8, 3]}]
OK

View File

@@ -265,7 +265,7 @@ static int included_patches[] = {
//333 NA //333 NA
//332 NA //332 NA
331, 331,
//330, 330,
329, 329,
328, 328,
327, 327,

View File

@@ -5190,16 +5190,18 @@ void restore_buffer(buf_T *save_curbuf)
* If no particular ID is desired, -1 must be specified for 'id'. * If no particular ID is desired, -1 must be specified for 'id'.
* Return ID of added match, -1 on failure. * Return ID of added match, -1 on failure.
*/ */
int match_add(win_T *wp, char_u *grp, char_u *pat, int prio, int id) int match_add(win_T *wp, char_u *grp, char_u *pat, int prio, int id, list_T *pos_list)
{ {
matchitem_T *cur; matchitem_T *cur;
matchitem_T *prev; matchitem_T *prev;
matchitem_T *m; matchitem_T *m;
int hlg_id; int hlg_id;
regprog_T *regprog; regprog_T *regprog = NULL;
int rtype = SOME_VALID;
if (*grp == NUL || *pat == NUL) if (*grp == NUL || (pat != NULL && *pat == NUL)) {
return -1; return -1;
}
if (id < -1 || id == 0) { if (id < -1 || id == 0) {
EMSGN("E799: Invalid ID: %" PRId64 EMSGN("E799: Invalid ID: %" PRId64
" (must be greater than or equal to 1)", " (must be greater than or equal to 1)",
@@ -5220,7 +5222,7 @@ int match_add(win_T *wp, char_u *grp, char_u *pat, int prio, int id)
EMSG2(_(e_nogroup), grp); EMSG2(_(e_nogroup), grp);
return -1; return -1;
} }
if ((regprog = vim_regcomp(pat, RE_MAGIC)) == NULL) { if (pat != NULL && (regprog = vim_regcomp(pat, RE_MAGIC)) == NULL) {
EMSG2(_(e_invarg2), pat); EMSG2(_(e_invarg2), pat);
return -1; return -1;
} }
@@ -5236,15 +5238,108 @@ int match_add(win_T *wp, char_u *grp, char_u *pat, int prio, int id)
} }
/* Build new match. */ /* Build new match. */
m = xmalloc(sizeof(matchitem_T)); m = xcalloc(1, sizeof(matchitem_T));
m->id = id; m->id = id;
m->priority = prio; m->priority = prio;
m->pattern = vim_strsave(pat); m->pattern = pat == NULL ? NULL: vim_strsave(pat);
m->pos.cur = 0;
m->hlg_id = hlg_id; m->hlg_id = hlg_id;
m->match.regprog = regprog; m->match.regprog = regprog;
m->match.rmm_ic = FALSE; m->match.rmm_ic = FALSE;
m->match.rmm_maxcol = 0; m->match.rmm_maxcol = 0;
// Set up position matches
if (pos_list != NULL)
{
linenr_T toplnum = 0;
linenr_T botlnum = 0;
listitem_T *li;
int i;
for (i = 0, li = pos_list->lv_first; i < MAXPOSMATCH;
i++, li = li->li_next) {
linenr_T lnum = 0;
colnr_T col = 0;
int len = 1;
list_T *subl;
listitem_T *subli;
int error;
if (li == NULL) {
m->pos.pos[i].lnum = 0;
break;
}
if (li->li_tv.v_type == VAR_LIST) {
subl = li->li_tv.vval.v_list;
if (subl == NULL) {
goto fail;
}
subli = subl->lv_first;
if (subli == NULL) {
goto fail;
}
lnum = get_tv_number_chk(&subli->li_tv, &error);
if (error == TRUE) {
goto fail;
}
m->pos.pos[i].lnum = lnum;
if (lnum == 0) {
--i;
continue;
}
subli = subli->li_next;
if (subli != NULL) {
col = get_tv_number_chk(&subli->li_tv, &error);
if (error == TRUE)
goto fail;
subli = subli->li_next;
if (subli != NULL) {
len = get_tv_number_chk(&subli->li_tv, &error);
if (error == true) {
goto fail;
}
}
}
m->pos.pos[i].col = col;
m->pos.pos[i].len = len;
} else if (li->li_tv.v_type == VAR_NUMBER) {
if (li->li_tv.vval.v_number == 0)
continue;
m->pos.pos[i].lnum = li->li_tv.vval.v_number;
m->pos.pos[i].col = 0;
m->pos.pos[i].len = 0;
} else {
EMSG(_("List or number required"));
goto fail;
}
if (toplnum == 0 || lnum < toplnum) {
toplnum = lnum;
}
if (botlnum == 0 || lnum > botlnum) {
botlnum = lnum;
}
}
// Calculate top and bottom lines for redrawing area
if (toplnum != 0){
if (wp->w_buffer->b_mod_set) {
if (wp->w_buffer->b_mod_top > toplnum) {
wp->w_buffer->b_mod_top = toplnum;
}
if (wp->w_buffer->b_mod_bot < botlnum) {
wp->w_buffer->b_mod_bot = botlnum;
}
} else {
wp->w_buffer->b_mod_top = toplnum;
wp->w_buffer->b_mod_bot = botlnum;
}
m->pos.toplnum = toplnum;
m->pos.botlnum = botlnum;
wp->w_buffer->b_mod_set = TRUE;
rtype = VALID;
}
}
/* Insert new match. The match list is in ascending order with regard to /* Insert new match. The match list is in ascending order with regard to
* the match priorities. */ * the match priorities. */
cur = wp->w_match_head; cur = wp->w_match_head;
@@ -5259,8 +5354,12 @@ int match_add(win_T *wp, char_u *grp, char_u *pat, int prio, int id)
prev->next = m; prev->next = m;
m->next = cur; m->next = cur;
redraw_later(SOME_VALID); redraw_later(rtype);
return id; return id;
fail:
free(m);
return -1;
} }
/* /*
@@ -5271,6 +5370,7 @@ int match_delete(win_T *wp, int id, int perr)
{ {
matchitem_T *cur = wp->w_match_head; matchitem_T *cur = wp->w_match_head;
matchitem_T *prev = cur; matchitem_T *prev = cur;
int rtype = SOME_VALID;
if (id < 1) { if (id < 1) {
if (perr == TRUE) if (perr == TRUE)
@@ -5294,8 +5394,23 @@ int match_delete(win_T *wp, int id, int perr)
prev->next = cur->next; prev->next = cur->next;
vim_regfree(cur->match.regprog); vim_regfree(cur->match.regprog);
free(cur->pattern); free(cur->pattern);
if (cur->pos.toplnum != 0) {
if (wp->w_buffer->b_mod_set) {
if (wp->w_buffer->b_mod_top > cur->pos.toplnum) {
wp->w_buffer->b_mod_top = cur->pos.toplnum;
}
if (wp->w_buffer->b_mod_bot < cur->pos.botlnum) {
wp->w_buffer->b_mod_bot = cur->pos.botlnum;
}
} else {
wp->w_buffer->b_mod_top = cur->pos.toplnum;
wp->w_buffer->b_mod_bot = cur->pos.botlnum;
}
wp->w_buffer->b_mod_set = TRUE;
rtype = VALID;
}
free(cur); free(cur);
redraw_later(SOME_VALID); redraw_later(rtype);
return 0; return 0;
} }