Mercurial > vim
comparison src/screen.c @ 5979:f9fa2e506b9f v7.4.330
updated for version 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)
author | Bram Moolenaar <bram@vim.org> |
---|---|
date | Tue, 17 Jun 2014 17:48:32 +0200 |
parents | 4d7af1962d6c |
children | 8ae50e3ef8bf |
comparison
equal
deleted
inserted
replaced
5978:4f8d7e5811e0 | 5979:f9fa2e506b9f |
---|---|
142 #define SEARCH_HL_PRIORITY 0 | 142 #define SEARCH_HL_PRIORITY 0 |
143 static void start_search_hl __ARGS((void)); | 143 static void start_search_hl __ARGS((void)); |
144 static void end_search_hl __ARGS((void)); | 144 static void end_search_hl __ARGS((void)); |
145 static void init_search_hl __ARGS((win_T *wp)); | 145 static void init_search_hl __ARGS((win_T *wp)); |
146 static void prepare_search_hl __ARGS((win_T *wp, linenr_T lnum)); | 146 static void prepare_search_hl __ARGS((win_T *wp, linenr_T lnum)); |
147 static void next_search_hl __ARGS((win_T *win, match_T *shl, linenr_T lnum, colnr_T mincol)); | 147 static void next_search_hl __ARGS((win_T *win, match_T *shl, linenr_T lnum, colnr_T mincol, matchitem_T *cur)); |
148 static int next_search_hl_pos __ARGS((match_T *shl, linenr_T lnum, posmatch_T *pos, colnr_T mincol)); | |
148 #endif | 149 #endif |
149 static void screen_start_highlight __ARGS((int attr)); | 150 static void screen_start_highlight __ARGS((int attr)); |
150 static void screen_char __ARGS((unsigned off, int row, int col)); | 151 static void screen_char __ARGS((unsigned off, int row, int col)); |
151 #ifdef FEAT_MBYTE | 152 #ifdef FEAT_MBYTE |
152 static void screen_char_2 __ARGS((unsigned off, int row, int col)); | 153 static void screen_char_2 __ARGS((unsigned off, int row, int col)); |
2927 #ifdef FEAT_SEARCH_EXTRA | 2928 #ifdef FEAT_SEARCH_EXTRA |
2928 matchitem_T *cur; /* points to the match list */ | 2929 matchitem_T *cur; /* points to the match list */ |
2929 match_T *shl; /* points to search_hl or a match */ | 2930 match_T *shl; /* points to search_hl or a match */ |
2930 int shl_flag; /* flag to indicate whether search_hl | 2931 int shl_flag; /* flag to indicate whether search_hl |
2931 has been processed or not */ | 2932 has been processed or not */ |
2933 int pos_inprogress; /* marks that position match search is | |
2934 in progress */ | |
2932 int prevcol_hl_flag; /* flag to indicate whether prevcol | 2935 int prevcol_hl_flag; /* flag to indicate whether prevcol |
2933 equals startcol of search_hl or one | 2936 equals startcol of search_hl or one |
2934 of the matches */ | 2937 of the matches */ |
2935 #endif | 2938 #endif |
2936 #ifdef FEAT_ARABIC | 2939 #ifdef FEAT_ARABIC |
3437 else | 3440 else |
3438 shl = &cur->hl; | 3441 shl = &cur->hl; |
3439 shl->startcol = MAXCOL; | 3442 shl->startcol = MAXCOL; |
3440 shl->endcol = MAXCOL; | 3443 shl->endcol = MAXCOL; |
3441 shl->attr_cur = 0; | 3444 shl->attr_cur = 0; |
3442 if (shl->rm.regprog != NULL) | 3445 v = (long)(ptr - line); |
3443 { | 3446 if (cur != NULL) |
3444 v = (long)(ptr - line); | 3447 cur->pos.cur = 0; |
3445 next_search_hl(wp, shl, lnum, (colnr_T)v); | 3448 next_search_hl(wp, shl, lnum, (colnr_T)v, cur); |
3446 | 3449 |
3447 /* Need to get the line again, a multi-line regexp may have made it | 3450 /* Need to get the line again, a multi-line regexp may have made it |
3448 * invalid. */ | 3451 * invalid. */ |
3449 line = ml_get_buf(wp->w_buffer, lnum, FALSE); | 3452 line = ml_get_buf(wp->w_buffer, lnum, FALSE); |
3450 ptr = line + v; | 3453 ptr = line + v; |
3451 | 3454 |
3452 if (shl->lnum != 0 && shl->lnum <= lnum) | 3455 if (shl->lnum != 0 && shl->lnum <= lnum) |
3453 { | 3456 { |
3454 if (shl->lnum == lnum) | 3457 if (shl->lnum == lnum) |
3455 shl->startcol = shl->rm.startpos[0].col; | 3458 shl->startcol = shl->rm.startpos[0].col; |
3459 else | |
3460 shl->startcol = 0; | |
3461 if (lnum == shl->lnum + shl->rm.endpos[0].lnum | |
3462 - shl->rm.startpos[0].lnum) | |
3463 shl->endcol = shl->rm.endpos[0].col; | |
3464 else | |
3465 shl->endcol = MAXCOL; | |
3466 /* Highlight one character for an empty match. */ | |
3467 if (shl->startcol == shl->endcol) | |
3468 { | |
3469 #ifdef FEAT_MBYTE | |
3470 if (has_mbyte && line[shl->endcol] != NUL) | |
3471 shl->endcol += (*mb_ptr2len)(line + shl->endcol); | |
3456 else | 3472 else |
3457 shl->startcol = 0; | 3473 #endif |
3458 if (lnum == shl->lnum + shl->rm.endpos[0].lnum | 3474 ++shl->endcol; |
3459 - shl->rm.startpos[0].lnum) | 3475 } |
3460 shl->endcol = shl->rm.endpos[0].col; | 3476 if ((long)shl->startcol < v) /* match at leftcol */ |
3461 else | 3477 { |
3462 shl->endcol = MAXCOL; | 3478 shl->attr_cur = shl->attr; |
3463 /* Highlight one character for an empty match. */ | 3479 search_attr = shl->attr; |
3464 if (shl->startcol == shl->endcol) | 3480 } |
3465 { | 3481 area_highlighting = TRUE; |
3466 #ifdef FEAT_MBYTE | |
3467 if (has_mbyte && line[shl->endcol] != NUL) | |
3468 shl->endcol += (*mb_ptr2len)(line + shl->endcol); | |
3469 else | |
3470 #endif | |
3471 ++shl->endcol; | |
3472 } | |
3473 if ((long)shl->startcol < v) /* match at leftcol */ | |
3474 { | |
3475 shl->attr_cur = shl->attr; | |
3476 search_attr = shl->attr; | |
3477 } | |
3478 area_highlighting = TRUE; | |
3479 } | |
3480 } | 3482 } |
3481 if (shl != &search_hl && cur != NULL) | 3483 if (shl != &search_hl && cur != NULL) |
3482 cur = cur->next; | 3484 cur = cur->next; |
3483 } | 3485 } |
3484 #endif | 3486 #endif |
3486 #ifdef FEAT_SYN_HL | 3488 #ifdef FEAT_SYN_HL |
3487 /* Cursor line highlighting for 'cursorline' in the current window. Not | 3489 /* Cursor line highlighting for 'cursorline' in the current window. Not |
3488 * when Visual mode is active, because it's not clear what is selected | 3490 * when Visual mode is active, because it's not clear what is selected |
3489 * then. */ | 3491 * then. */ |
3490 if (wp->w_p_cul && lnum == wp->w_cursor.lnum | 3492 if (wp->w_p_cul && lnum == wp->w_cursor.lnum |
3491 && !(wp == curwin && VIsual_active)) | 3493 && !(wp == curwin && VIsual_active)) |
3492 { | 3494 { |
3493 line_attr = hl_attr(HLF_CUL); | 3495 line_attr = hl_attr(HLF_CUL); |
3494 area_highlighting = TRUE; | 3496 area_highlighting = TRUE; |
3495 } | 3497 } |
3496 #endif | 3498 #endif |
3790 shl = &search_hl; | 3792 shl = &search_hl; |
3791 shl_flag = TRUE; | 3793 shl_flag = TRUE; |
3792 } | 3794 } |
3793 else | 3795 else |
3794 shl = &cur->hl; | 3796 shl = &cur->hl; |
3795 while (shl->rm.regprog != NULL) | 3797 if (cur != NULL) |
3798 cur->pos.cur = 0; | |
3799 pos_inprogress = TRUE; | |
3800 while (shl->rm.regprog != NULL | |
3801 || (cur != NULL && pos_inprogress)) | |
3796 { | 3802 { |
3797 if (shl->startcol != MAXCOL | 3803 if (shl->startcol != MAXCOL |
3798 && v >= (long)shl->startcol | 3804 && v >= (long)shl->startcol |
3799 && v < (long)shl->endcol) | 3805 && v < (long)shl->endcol) |
3800 { | 3806 { |
3801 shl->attr_cur = shl->attr; | 3807 shl->attr_cur = shl->attr; |
3802 } | 3808 } |
3803 else if (v == (long)shl->endcol) | 3809 else if (v == (long)shl->endcol) |
3804 { | 3810 { |
3805 shl->attr_cur = 0; | 3811 shl->attr_cur = 0; |
3806 | 3812 next_search_hl(wp, shl, lnum, (colnr_T)v, cur); |
3807 next_search_hl(wp, shl, lnum, (colnr_T)v); | 3813 pos_inprogress = cur == NULL || cur->pos.cur == 0 |
3814 ? FALSE : TRUE; | |
3808 | 3815 |
3809 /* Need to get the line again, a multi-line regexp | 3816 /* Need to get the line again, a multi-line regexp |
3810 * may have made it invalid. */ | 3817 * may have made it invalid. */ |
3811 line = ml_get_buf(wp->w_buffer, lnum, FALSE); | 3818 line = ml_get_buf(wp->w_buffer, lnum, FALSE); |
3812 ptr = line + v; | 3819 ptr = line + v; |
7275 { | 7282 { |
7276 matchitem_T *cur; /* points to the match list */ | 7283 matchitem_T *cur; /* points to the match list */ |
7277 match_T *shl; /* points to search_hl or a match */ | 7284 match_T *shl; /* points to search_hl or a match */ |
7278 int shl_flag; /* flag to indicate whether search_hl | 7285 int shl_flag; /* flag to indicate whether search_hl |
7279 has been processed or not */ | 7286 has been processed or not */ |
7287 int pos_inprogress; /* marks that position match search is | |
7288 in progress */ | |
7280 int n; | 7289 int n; |
7281 | 7290 |
7282 /* | 7291 /* |
7283 * When using a multi-line pattern, start searching at the top | 7292 * When using a multi-line pattern, start searching at the top |
7284 * of the window or just after a closed fold. | 7293 * of the window or just after a closed fold. |
7309 break; | 7318 break; |
7310 # else | 7319 # else |
7311 shl->first_lnum = wp->w_topline; | 7320 shl->first_lnum = wp->w_topline; |
7312 # endif | 7321 # endif |
7313 } | 7322 } |
7323 if (cur != NULL) | |
7324 cur->pos.cur = 0; | |
7325 pos_inprogress = TRUE; | |
7314 n = 0; | 7326 n = 0; |
7315 while (shl->first_lnum < lnum && shl->rm.regprog != NULL) | 7327 while (shl->first_lnum < lnum && (shl->rm.regprog != NULL |
7316 { | 7328 || (cur != NULL && pos_inprogress))) |
7317 next_search_hl(wp, shl, shl->first_lnum, (colnr_T)n); | 7329 { |
7330 next_search_hl(wp, shl, shl->first_lnum, (colnr_T)n, cur); | |
7331 pos_inprogress = cur == NULL || cur->pos.cur == 0 | |
7332 ? FALSE : TRUE; | |
7318 if (shl->lnum != 0) | 7333 if (shl->lnum != 0) |
7319 { | 7334 { |
7320 shl->first_lnum = shl->lnum | 7335 shl->first_lnum = shl->lnum |
7321 + shl->rm.endpos[0].lnum | 7336 + shl->rm.endpos[0].lnum |
7322 - shl->rm.startpos[0].lnum; | 7337 - shl->rm.startpos[0].lnum; |
7341 * Note: Assumes a previous match is always before "lnum", unless | 7356 * Note: Assumes a previous match is always before "lnum", unless |
7342 * shl->lnum is zero. | 7357 * shl->lnum is zero. |
7343 * Careful: Any pointers for buffer lines will become invalid. | 7358 * Careful: Any pointers for buffer lines will become invalid. |
7344 */ | 7359 */ |
7345 static void | 7360 static void |
7346 next_search_hl(win, shl, lnum, mincol) | 7361 next_search_hl(win, shl, lnum, mincol, cur) |
7347 win_T *win; | 7362 win_T *win; |
7348 match_T *shl; /* points to search_hl or a match */ | 7363 match_T *shl; /* points to search_hl or a match */ |
7349 linenr_T lnum; | 7364 linenr_T lnum; |
7350 colnr_T mincol; /* minimal column for a match */ | 7365 colnr_T mincol; /* minimal column for a match */ |
7366 matchitem_T *cur; /* to retrieve match postions if any */ | |
7351 { | 7367 { |
7352 linenr_T l; | 7368 linenr_T l; |
7353 colnr_T matchcol; | 7369 colnr_T matchcol; |
7354 long nmatched; | 7370 long nmatched; |
7355 | 7371 |
7413 } | 7429 } |
7414 else | 7430 else |
7415 matchcol = shl->rm.endpos[0].col; | 7431 matchcol = shl->rm.endpos[0].col; |
7416 | 7432 |
7417 shl->lnum = lnum; | 7433 shl->lnum = lnum; |
7418 nmatched = vim_regexec_multi(&shl->rm, win, shl->buf, lnum, matchcol, | 7434 if (shl->rm.regprog != NULL) |
7435 { | |
7436 nmatched = vim_regexec_multi(&shl->rm, win, shl->buf, lnum, | |
7437 matchcol, | |
7419 #ifdef FEAT_RELTIME | 7438 #ifdef FEAT_RELTIME |
7420 &(shl->tm) | 7439 &(shl->tm) |
7421 #else | 7440 #else |
7422 NULL | 7441 NULL |
7423 #endif | 7442 #endif |
7424 ); | 7443 ); |
7425 if (called_emsg || got_int) | 7444 if (called_emsg || got_int) |
7426 { | 7445 { |
7427 /* Error while handling regexp: stop using this regexp. */ | 7446 /* Error while handling regexp: stop using this regexp. */ |
7428 if (shl == &search_hl) | 7447 if (shl == &search_hl) |
7429 { | 7448 { |
7430 /* don't free regprog in the match list, it's a copy */ | 7449 /* don't free regprog in the match list, it's a copy */ |
7431 vim_regfree(shl->rm.regprog); | 7450 vim_regfree(shl->rm.regprog); |
7432 SET_NO_HLSEARCH(TRUE); | 7451 SET_NO_HLSEARCH(TRUE); |
7433 } | 7452 } |
7434 shl->rm.regprog = NULL; | 7453 shl->rm.regprog = NULL; |
7435 shl->lnum = 0; | 7454 shl->lnum = 0; |
7436 got_int = FALSE; /* avoid the "Type :quit to exit Vim" message */ | 7455 got_int = FALSE; /* avoid the "Type :quit to exit Vim" |
7437 break; | 7456 message */ |
7457 break; | |
7458 } | |
7459 } | |
7460 else if (cur != NULL) | |
7461 { | |
7462 nmatched = next_search_hl_pos(shl, lnum, &(cur->pos), matchcol); | |
7438 } | 7463 } |
7439 if (nmatched == 0) | 7464 if (nmatched == 0) |
7440 { | 7465 { |
7441 shl->lnum = 0; /* no match found */ | 7466 shl->lnum = 0; /* no match found */ |
7442 break; | 7467 break; |
7450 break; /* useful match found */ | 7475 break; /* useful match found */ |
7451 } | 7476 } |
7452 } | 7477 } |
7453 } | 7478 } |
7454 #endif | 7479 #endif |
7480 | |
7481 static int | |
7482 next_search_hl_pos(shl, lnum, posmatch, mincol) | |
7483 match_T *shl; /* points to a match */ | |
7484 linenr_T lnum; | |
7485 posmatch_T *posmatch; /* match positions */ | |
7486 colnr_T mincol; /* minimal column for a match */ | |
7487 { | |
7488 int i; | |
7489 int bot = -1; | |
7490 | |
7491 shl->lnum = 0; | |
7492 for (i = posmatch->cur; i < MAXPOSMATCH; i++) | |
7493 { | |
7494 if (posmatch->pos[i].lnum == 0) | |
7495 break; | |
7496 if (posmatch->pos[i].col < mincol) | |
7497 continue; | |
7498 if (posmatch->pos[i].lnum == lnum) | |
7499 { | |
7500 if (shl->lnum == lnum) | |
7501 { | |
7502 /* partially sort positions by column numbers | |
7503 * on the same line */ | |
7504 if (posmatch->pos[i].col < posmatch->pos[bot].col) | |
7505 { | |
7506 llpos_T tmp = posmatch->pos[i]; | |
7507 | |
7508 posmatch->pos[i] = posmatch->pos[bot]; | |
7509 posmatch->pos[bot] = tmp; | |
7510 } | |
7511 } | |
7512 else | |
7513 { | |
7514 bot = i; | |
7515 shl->lnum = lnum; | |
7516 } | |
7517 } | |
7518 } | |
7519 posmatch->cur = 0; | |
7520 if (shl->lnum == lnum) | |
7521 { | |
7522 colnr_T start = posmatch->pos[bot].col == 0 | |
7523 ? 0 : posmatch->pos[bot].col - 1; | |
7524 colnr_T end = posmatch->pos[bot].col == 0 | |
7525 ? MAXCOL : start + posmatch->pos[bot].len; | |
7526 | |
7527 shl->rm.startpos[0].lnum = 0; | |
7528 shl->rm.startpos[0].col = start; | |
7529 shl->rm.endpos[0].lnum = 0; | |
7530 shl->rm.endpos[0].col = end; | |
7531 posmatch->cur = bot + 1; | |
7532 return TRUE; | |
7533 } | |
7534 return FALSE; | |
7535 } | |
7455 | 7536 |
7456 static void | 7537 static void |
7457 screen_start_highlight(attr) | 7538 screen_start_highlight(attr) |
7458 int attr; | 7539 int attr; |
7459 { | 7540 { |