diff options
Diffstat (limited to 'src/nvim/screen.c')
-rw-r--r-- | src/nvim/screen.c | 280 |
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; |