aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/screen.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/screen.c')
-rw-r--r--src/nvim/screen.c280
1 files changed, 172 insertions, 108 deletions
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index 811f265902..122c23ed84 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -206,10 +206,7 @@ void redraw_later_clear(void)
*/
void redraw_all_later(int type)
{
- win_T *wp;
-
- FOR_ALL_WINDOWS(wp)
- {
+ FOR_ALL_WINDOWS(wp) {
redraw_win_later(wp, type);
}
}
@@ -224,12 +221,10 @@ void redraw_curbuf_later(int type)
void redraw_buf_later(buf_T *buf, int type)
{
- win_T *wp;
-
- FOR_ALL_WINDOWS(wp)
- {
- if (wp->w_buffer == buf)
+ FOR_ALL_WINDOWS(wp) {
+ if (wp->w_buffer == buf) {
redraw_win_later(wp, type);
+ }
}
}
@@ -390,7 +385,6 @@ void update_curbuf(int type)
*/
void update_screen(int type)
{
- win_T *wp;
static int did_intro = FALSE;
int did_one;
@@ -438,8 +432,7 @@ void update_screen(int type)
check_for_delay(FALSE);
if (screen_ins_lines(0, 0, msg_scrolled, (int)Rows, NULL) == FAIL)
type = CLEAR;
- FOR_ALL_WINDOWS(wp)
- {
+ FOR_ALL_WINDOWS(wp) {
if (wp->w_winrow < msg_scrolled) {
if (wp->w_winrow + wp->w_height > msg_scrolled
&& wp->w_redr_type < REDRAW_TOP
@@ -450,8 +443,9 @@ void update_screen(int type)
} else {
wp->w_redr_type = NOT_VALID;
if (wp->w_winrow + wp->w_height + wp->w_status_height
- <= msg_scrolled)
+ <= msg_scrolled) {
wp->w_redr_status = TRUE;
+ }
}
}
}
@@ -512,8 +506,7 @@ void update_screen(int type)
* Correct stored syntax highlighting info for changes in each displayed
* buffer. Each buffer must only be done once.
*/
- FOR_ALL_WINDOWS(wp)
- {
+ FOR_ALL_WINDOWS(wp) {
if (wp->w_buffer->b_mod_set) {
win_T *wwp;
@@ -534,8 +527,7 @@ void update_screen(int type)
*/
did_one = FALSE;
search_hl.rm.regprog = NULL;
- FOR_ALL_WINDOWS(wp)
- {
+ FOR_ALL_WINDOWS(wp) {
if (wp->w_redr_type != 0) {
cursor_off();
if (!did_one) {
@@ -558,8 +550,9 @@ void update_screen(int type)
/* Reset b_mod_set flags. Going through all windows is probably faster
* than going through all buffers (there could be many buffers). */
- for (wp = firstwin; wp != NULL; wp = wp->w_next)
+ FOR_ALL_WINDOWS(wp) {
wp->w_buffer->b_mod_set = FALSE;
+ }
updating_screen = FALSE;
@@ -662,31 +655,28 @@ static void update_finish(void)
void update_debug_sign(buf_T *buf, linenr_T lnum)
{
- win_T *wp;
int doit = FALSE;
win_foldinfo.fi_level = 0;
/* update/delete a specific mark */
- FOR_ALL_WINDOWS(wp)
- {
- if (buf != NULL && lnum > 0) {
- if (wp->w_buffer == buf && lnum >= wp->w_topline
- && lnum < wp->w_botline)
- {
- if (wp->w_redraw_top == 0 || wp->w_redraw_top > lnum) {
- wp->w_redraw_top = lnum;
- }
- if (wp->w_redraw_bot == 0 || wp->w_redraw_bot < lnum) {
- wp->w_redraw_bot = lnum;
- }
- redraw_win_later(wp, VALID);
- }
- } else {
- redraw_win_later(wp, VALID);
- }
- if (wp->w_redr_type != 0) {
- doit = TRUE;
+ FOR_ALL_WINDOWS(wp) {
+ if (buf != NULL && lnum > 0) {
+ if (wp->w_buffer == buf && lnum >= wp->w_topline
+ && lnum < wp->w_botline) {
+ if (wp->w_redraw_top == 0 || wp->w_redraw_top > lnum) {
+ wp->w_redraw_top = lnum;
+ }
+ if (wp->w_redraw_bot == 0 || wp->w_redraw_bot < lnum) {
+ wp->w_redraw_bot = lnum;
+ }
+ redraw_win_later(wp, VALID);
}
+ } else {
+ redraw_win_later(wp, VALID);
+ }
+ if (wp->w_redr_type != 0) {
+ doit = TRUE;
+ }
}
/* Return when there is nothing to do, screen updating is already
@@ -698,13 +688,13 @@ void update_debug_sign(buf_T *buf, linenr_T lnum)
/* update all windows that need updating */
update_prepare();
- for (wp = firstwin; wp; wp = wp->w_next) {
- if (wp->w_redr_type != 0) {
- win_update(wp);
- }
- if (wp->w_redr_status) {
- win_redr_status(wp);
- }
+ FOR_ALL_WINDOWS(wp) {
+ if (wp->w_redr_type != 0) {
+ win_update(wp);
+ }
+ if (wp->w_redr_status) {
+ win_redr_status(wp);
+ }
}
update_finish();
@@ -1366,8 +1356,9 @@ static void win_update(win_T *wp)
(foldmethodIsSyntax(wp)
&& hasAnyFolding(wp)) ||
syntax_check_changed(lnum)))
- /* match in fixed position might need redraw */
- || wp->w_match_head != NULL
+ // match in fixed position might need redraw
+ // if lines were inserted or deleted
+ || (wp->w_match_head != NULL && buf->b_mod_xlines != 0)
))))) {
if (lnum == mod_top)
top_to_mod = FALSE;
@@ -2658,38 +2649,42 @@ win_line (
shl->startcol = MAXCOL;
shl->endcol = MAXCOL;
shl->attr_cur = 0;
- if (shl->rm.regprog != NULL) {
- v = (long)(ptr - line);
- next_search_hl(wp, shl, lnum, (colnr_T)v);
+ v = (long)(ptr - line);
+ 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
- * invalid. */
- line = ml_get_buf(wp->w_buffer, lnum, FALSE);
- ptr = line + v;
+ // Need to get the line again, a multi-line regexp may have made it
+ // invalid.
+ line = ml_get_buf(wp->w_buffer, lnum, false);
+ ptr = line + v;
- if (shl->lnum != 0 && shl->lnum <= lnum) {
- if (shl->lnum == lnum)
- shl->startcol = shl->rm.startpos[0].col;
- else
- shl->startcol = 0;
- if (lnum == shl->lnum + shl->rm.endpos[0].lnum
- - shl->rm.startpos[0].lnum)
+ if (shl->lnum != 0 && shl->lnum <= lnum) {
+ if (shl->lnum == lnum) {
+ shl->startcol = shl->rm.startpos[0].col;
+ } else {
+ shl->startcol = 0;
+ }
+ if (lnum == shl->lnum + shl->rm.endpos[0].lnum
+ - shl->rm.startpos[0].lnum) {
shl->endcol = shl->rm.endpos[0].col;
- else
+ } else {
shl->endcol = MAXCOL;
- /* Highlight one character for an empty match. */
- if (shl->startcol == shl->endcol) {
- if (has_mbyte && line[shl->endcol] != NUL)
- shl->endcol += (*mb_ptr2len)(line + shl->endcol);
- else
- ++shl->endcol;
- }
- if ((long)shl->startcol < v) { /* match at leftcol */
- shl->attr_cur = shl->attr;
- search_attr = shl->attr;
- }
- area_highlighting = TRUE;
}
+ // Highlight one character for an empty match.
+ if (shl->startcol == shl->endcol) {
+ if (has_mbyte && line[shl->endcol] != NUL) {
+ shl->endcol += (*mb_ptr2len)(line + shl->endcol);
+ } else {
+ ++shl->endcol;
+ }
+ }
+ if ((long)shl->startcol < v) { // match at leftcol
+ shl->attr_cur = shl->attr;
+ search_attr = shl->attr;
+ }
+ area_highlighting = true;
}
if (shl != &search_hl && cur != NULL)
cur = cur->next;
@@ -2699,9 +2694,9 @@ win_line (
* when Visual mode is active, because it's not clear what is selected
* then. */
if (wp->w_p_cul && lnum == wp->w_cursor.lnum
- && !(wp == curwin && VIsual_active)) {
+ && !(wp == curwin && VIsual_active)) {
line_attr = hl_attr(HLF_CUL);
- area_highlighting = TRUE;
+ area_highlighting = true;
}
off = (unsigned)(current_ScreenLine - ScreenLines);
@@ -2942,15 +2937,22 @@ win_line (
shl_flag = TRUE;
} else
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
&& v >= (long)shl->startcol
&& v < (long)shl->endcol) {
shl->attr_cur = shl->attr;
- } else if (v == (long)shl->endcol) {
+ } else if (v >= (long)shl->endcol) {
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
* may have made it invalid. */
@@ -3563,7 +3565,7 @@ win_line (
} else if (c != NUL) {
p_extra = transchar(c);
if (n_extra == 0) {
- n_extra = byte2cells(c);
+ n_extra = byte2cells(c) - 1;
}
if ((dy_flags & DY_UHEX) && wp->w_p_rl)
rl_mirror(p_extra); /* reverse "<12>" */
@@ -4552,13 +4554,13 @@ void rl_mirror(char_u *str)
*/
void status_redraw_all(void)
{
- win_T *wp;
- for (wp = firstwin; wp; wp = wp->w_next)
+ FOR_ALL_WINDOWS(wp) {
if (wp->w_status_height) {
wp->w_redr_status = TRUE;
redraw_later(VALID);
}
+ }
}
/*
@@ -4566,13 +4568,12 @@ void status_redraw_all(void)
*/
void status_redraw_curbuf(void)
{
- win_T *wp;
-
- for (wp = firstwin; wp; wp = wp->w_next)
+ FOR_ALL_WINDOWS(wp) {
if (wp->w_status_height != 0 && wp->w_buffer == curbuf) {
wp->w_redr_status = TRUE;
redraw_later(VALID);
}
+ }
}
/*
@@ -4580,11 +4581,11 @@ void status_redraw_curbuf(void)
*/
void redraw_statuslines(void)
{
- win_T *wp;
-
- for (wp = firstwin; wp; wp = wp->w_next)
- if (wp->w_redr_status)
+ FOR_ALL_WINDOWS(wp) {
+ if (wp->w_redr_status) {
win_redr_status(wp);
+ }
+ }
if (redraw_tabline)
draw_tabline();
}
@@ -5602,9 +5603,16 @@ static void prepare_search_hl(win_T *wp, linenr_T lnum)
NULL, NULL, TRUE, NULL))
break;
}
+ if (cur != NULL) {
+ cur->pos.cur = 0;
+ }
+ bool pos_inprogress = true; // mark that a position match search is
+ // in progress
n = 0;
- while (shl->first_lnum < lnum && shl->rm.regprog != NULL) {
- next_search_hl(wp, shl, shl->first_lnum, (colnr_T)n);
+ while (shl->first_lnum < lnum && (shl->rm.regprog != NULL
+ || (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) {
shl->first_lnum = shl->lnum
+ shl->rm.endpos[0].lnum
@@ -5634,12 +5642,13 @@ next_search_hl (
win_T *win,
match_T *shl, /* points to search_hl or a match */
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;
colnr_T matchcol;
- long nmatched;
+ long nmatched = 0;
if (shl->lnum != 0) {
/* Check for three situations:
@@ -5674,8 +5683,8 @@ next_search_hl (
if (shl->lnum == 0)
matchcol = 0;
else if (vim_strchr(p_cpo, CPO_SEARCH) == NULL
- || (shl->rm.endpos[0].lnum == 0
- && shl->rm.endpos[0].col <= shl->rm.startpos[0].col)) {
+ || (shl->rm.endpos[0].lnum == 0
+ && shl->rm.endpos[0].col <= shl->rm.startpos[0].col)) {
char_u *ml;
matchcol = shl->rm.startpos[0].col;
@@ -5693,20 +5702,22 @@ next_search_hl (
matchcol = shl->rm.endpos[0].col;
shl->lnum = lnum;
- nmatched = vim_regexec_multi(&shl->rm, win, shl->buf, lnum, matchcol,
- &(shl->tm)
- );
- if (called_emsg || got_int) {
- /* Error while handling regexp: stop using this regexp. */
- if (shl == &search_hl) {
- /* don't free regprog in the match list, it's a copy */
- vim_regfree(shl->rm.regprog);
- SET_NO_HLSEARCH(TRUE);
+ if (shl->rm.regprog != NULL) {
+ nmatched = vim_regexec_multi(&shl->rm, win, shl->buf, lnum, matchcol, &(shl->tm));
+ if (called_emsg || got_int) {
+ // Error while handling regexp: stop using this regexp.
+ if (shl == &search_hl) {
+ // don't free regprog in the match list, it's a copy
+ vim_regfree(shl->rm.regprog);
+ SET_NO_HLSEARCH(TRUE);
+ }
+ shl->rm.regprog = NULL;
+ shl->lnum = 0;
+ got_int = FALSE; // avoid the "Type :quit to exit Vim" message
+ break;
}
- shl->rm.regprog = NULL;
- shl->lnum = 0;
- got_int = FALSE; /* avoid the "Type :quit to exit Vim" message */
- break;
+ } else if (cur != NULL) {
+ nmatched = next_search_hl_pos(shl, lnum, &(cur->pos), matchcol);
}
if (nmatched == 0) {
shl->lnum = 0; /* no match found */
@@ -5722,6 +5733,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)
{
attrentry_T *aep = NULL;