diff options
author | Bram Moolenaar <Bram@vim.org> | 2019-09-14 21:01:23 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2019-09-14 21:01:23 +0200 |
commit | 017ba07fa2cdc578245618717229444fd50c470d (patch) | |
tree | d848d329da08cbda1e846d6e7acf1a440f61d667 /src/screen.c | |
parent | d9b0d83b13d2691e4544709abd87eac004715175 (diff) | |
download | vim-git-017ba07fa2cdc578245618717229444fd50c470d.tar.gz |
patch 8.1.2029: cannot control 'cursorline' highlighting wellv8.1.2029
Problem: Cannot control 'cursorline' highlighting well.
Solution: Add "screenline". (Christian Brabandt, closes #4933)
Diffstat (limited to 'src/screen.c')
-rw-r--r-- | src/screen.c | 207 |
1 files changed, 172 insertions, 35 deletions
diff --git a/src/screen.c b/src/screen.c index eb71d7678..4ea0cffbd 100644 --- a/src/screen.c +++ b/src/screen.c @@ -158,6 +158,9 @@ static void win_redr_custom(win_T *wp, int draw_ruler); #ifdef FEAT_CMDL_INFO static void win_redr_ruler(win_T *wp, int always, int ignore_pum); #endif +#ifdef FEAT_SYN_HL +static void margin_columns_win(win_T *wp, int *left_col, int *right_col); +#endif /* Ugly global: overrule attribute used by screen_char() */ static int screen_char_attr = 0; @@ -3270,7 +3273,8 @@ win_line( #if defined(FEAT_SIGNS) || defined(FEAT_QUICKFIX) \ || defined(FEAT_SYN_HL) || defined(FEAT_DIFF) # define LINE_ATTR - int line_attr = 0; /* attribute for the whole line */ + int line_attr = 0; // attribute for the whole line + int line_attr_save; #endif #ifdef FEAT_SIGNS int sign_present = FALSE; @@ -3286,6 +3290,17 @@ win_line( #ifdef FEAT_TERMINAL int get_term_attr = FALSE; #endif +#ifdef FEAT_SYN_HL + int cul_attr = 0; // set when 'cursorline' active + + // 'cursorlineopt' has "screenline" and cursor is in this line + int cul_screenline = FALSE; + + // margin columns for the screen line, needed for when 'cursorlineopt' + // contains "screenline" + int left_curline_col = 0; + int right_curline_col = 0; +#endif /* draw_state: items that are drawn in sequence: */ #define WL_START 0 /* nothing done yet */ @@ -3815,14 +3830,33 @@ win_line( // Cursor line highlighting for 'cursorline' in the current window. if (wp->w_p_cul && lnum == wp->w_cursor.lnum) { - // Do not show the cursor line when Visual mode is active, because it's - // not clear what is selected then. Do update w_last_cursorline. - if (!(wp == curwin && VIsual_active) && *wp->w_p_culopt != 'n') + // Do not show the cursor line in the text when Visual mode is active, + // because it's not clear what is selected then. Do update + // w_last_cursorline. + if (!(wp == curwin && VIsual_active) + && wp->w_p_culopt_flags != CULOPT_NBR) { - line_attr = HL_ATTR(HLF_CUL); + cul_screenline = (wp->w_p_wrap + && (wp->w_p_culopt_flags & CULOPT_SCRLINE)); + + // Only set line_attr here when "screenline" is not present in + // 'cursorlineopt'. Otherwise it's done later. + if (!cul_screenline) + { + cul_attr = HL_ATTR(HLF_CUL); + line_attr = cul_attr; + wp->w_last_cursorline = wp->w_cursor.lnum; + } + else + { + line_attr_save = line_attr; + wp->w_last_cursorline = 0; + margin_columns_win(wp, &left_curline_col, &right_curline_col); + } area_highlighting = TRUE; } - wp->w_last_cursorline = wp->w_cursor.lnum; + else + wp->w_last_cursorline = wp->w_cursor.lnum; } #endif @@ -4016,13 +4050,17 @@ win_line( n_extra = number_width(wp) + 1; char_attr = hl_combine_attr(wcr_attr, HL_ATTR(HLF_N)); #ifdef FEAT_SYN_HL - /* When 'cursorline' is set highlight the line number of - * the current line differently. - * TODO: Can we use CursorLine instead of CursorLineNr - * when CursorLineNr isn't set? */ + // When 'cursorline' is set highlight the line number of + // the current line differently. + // When 'cursorlineopt' has "screenline" only highlight + // the line number itself. + // TODO: Can we use CursorLine instead of CursorLineNr + // when CursorLineNr isn't set? if ((wp->w_p_cul || wp->w_p_rnu) - && *wp->w_p_culopt != 'l' - && lnum == wp->w_cursor.lnum) + && (wp->w_p_culopt_flags & CULOPT_NBR) + && (row == startrow + || wp->w_p_culopt_flags & CULOPT_LINE) + && lnum == wp->w_cursor.lnum) char_attr = hl_combine_attr(wcr_attr, HL_ATTR(HLF_CLN)); #endif } @@ -4056,10 +4094,8 @@ win_line( { char_attr = HL_ATTR(diff_hlf); # ifdef FEAT_SYN_HL - if (wp->w_p_cul && lnum == wp->w_cursor.lnum - && *wp->w_p_culopt != 'n') - char_attr = hl_combine_attr(char_attr, - HL_ATTR(HLF_CUL)); + if (cul_attr != 0) + char_attr = hl_combine_attr(char_attr, cul_attr); # endif } # endif @@ -4117,13 +4153,11 @@ win_line( * required when 'linebreak' is also set. */ if (tocol == vcol) tocol += n_extra; -#ifdef FEAT_SYN_HL - /* combine 'showbreak' with 'cursorline' */ - if (wp->w_p_cul && lnum == wp->w_cursor.lnum - && *wp->w_p_culopt != 'n') - char_attr = hl_combine_attr(char_attr, - HL_ATTR(HLF_CUL)); -#endif +# ifdef FEAT_SYN_HL + // combine 'showbreak' with 'cursorline' + if (cul_attr != 0) + char_attr = hl_combine_attr(char_attr, cul_attr); +# endif } # endif } @@ -4145,6 +4179,23 @@ win_line( char_attr = win_attr; } } +#ifdef FEAT_SYN_HL + if (cul_screenline) + { + if (draw_state == WL_LINE + && vcol >= left_curline_col + && vcol < right_curline_col) + { + cul_attr = HL_ATTR(HLF_CUL); + line_attr = cul_attr; + } + else + { + cul_attr = 0; + line_attr = line_attr_save; + } + } +#endif // When still displaying '$' of change command, stop at cursor. // When only displaying the (relative) line number and that's done, @@ -4216,8 +4267,11 @@ win_line( diff_hlf = HLF_CHD; /* changed line */ line_attr = HL_ATTR(diff_hlf); if (wp->w_p_cul && lnum == wp->w_cursor.lnum - && *wp->w_p_culopt != 'n') - line_attr = hl_combine_attr(line_attr, HL_ATTR(HLF_CUL)); + && wp->w_p_culopt_flags != CULOPT_NBR + && (!cul_screenline || (vcol >= left_curline_col + && vcol <= right_curline_col))) + line_attr = hl_combine_attr( + line_attr, HL_ATTR(HLF_CUL)); } #endif @@ -4301,9 +4355,12 @@ win_line( else if (line_attr != 0 && ((fromcol == -10 && tocol == MAXCOL) || vcol < fromcol || vcol_prev < fromcol_prev || vcol >= tocol)) + { // Use line_attr when not in the Visual or 'incsearch' area // (area_attr may be 0 when "noinvcur" is set). char_attr = line_attr; + attr_pri = FALSE; + } #else if (area_attr != 0) char_attr = area_attr; @@ -4410,6 +4467,10 @@ win_line( mb_l = 1; mb_utf8 = FALSE; multi_attr = HL_ATTR(HLF_AT); +#ifdef FEAT_SYN_HL + if (cul_attr) + multi_attr = hl_combine_attr(multi_attr, cul_attr); +#endif /* put the pointer back to output the double-width * character at the start of the next line. */ ++n_extra; @@ -4672,10 +4733,10 @@ win_line( if (win_attr != 0) syntax_attr = hl_combine_attr(win_attr, syntax_attr); -#ifdef SYN_TIME_LIMIT +# ifdef SYN_TIME_LIMIT if (wp->w_s->b_syn_slow) has_syntax = FALSE; -#endif +# endif /* Need to get the line again, a multi-line regexp may * have made it invalid. */ @@ -4692,7 +4753,15 @@ win_line( comb_attr = hl_combine_attr(text_prop_attr, comb_attr); # endif if (!attr_pri) - char_attr = comb_attr; + { +#ifdef FEAT_SYN_HL + if (cul_attr) + char_attr = hl_combine_attr( + comb_attr, cul_attr); + else +#endif + char_attr = comb_attr; + } else char_attr = hl_combine_attr(comb_attr, char_attr); } @@ -5185,9 +5254,12 @@ win_line( { char_attr = HL_ATTR(diff_hlf); if (wp->w_p_cul && lnum == wp->w_cursor.lnum - && *wp->w_p_culopt != 'n') - char_attr = hl_combine_attr(char_attr, - HL_ATTR(HLF_CUL)); + && wp->w_p_culopt_flags != CULOPT_NBR + && (!cul_screenline + || (vcol >= left_curline_col + && vcol <= right_curline_col))) + char_attr = hl_combine_attr( + char_attr, HL_ATTR(HLF_CUL)); } } # endif @@ -5196,8 +5268,12 @@ win_line( { char_attr = win_attr; if (wp->w_p_cul && lnum == wp->w_cursor.lnum) - char_attr = hl_combine_attr(char_attr, - HL_ATTR(HLF_CUL)); + { + if (!cul_screenline || (vcol >= left_curline_col + && vcol <= right_curline_col)) + char_attr = hl_combine_attr( + char_attr, HL_ATTR(HLF_CUL)); + } else if (line_attr) char_attr = hl_combine_attr(char_attr, line_attr); } @@ -5305,7 +5381,12 @@ win_line( if (n_attr > 0 && draw_state == WL_LINE && !attr_pri) - char_attr = extra_attr; + { + if (line_attr) + char_attr = hl_combine_attr(extra_attr, line_attr); + else + char_attr = extra_attr; + } #if defined(FEAT_XIM) && defined(FEAT_GUI_GTK) /* XIM don't send preedit_start and preedit_end, but they send @@ -5969,7 +6050,16 @@ win_line( saved_p_extra = p_extra; saved_c_extra = c_extra; saved_c_final = c_final; - saved_char_attr = char_attr; +#ifdef FEAT_SYN_HL + if (!(cul_screenline +# ifdef FEAT_DIFF + && diff_hlf == (hlf_T)0) +# endif + ) + saved_char_attr = char_attr; + else +#endif + saved_char_attr = 0; n_extra = 0; lcs_prec_todo = lcs_prec; #ifdef FEAT_LINEBREAK @@ -11024,3 +11114,50 @@ set_chars_option(char_u **varp) return NULL; // no error } + +#ifdef FEAT_SYN_HL +/* + * Used when 'cursorlineopt' contains "screenline": compute the margins between + * which the highlighting is used. + */ + static void +margin_columns_win(win_T *wp, int *left_col, int *right_col) +{ + // cache previous calculations depending on w_virtcol + static int saved_w_virtcol; + static win_T *prev_wp; + static int prev_left_col; + static int prev_right_col; + static int prev_col_off; + + int cur_col_off = win_col_off(wp); + int width1; + int width2; + + if (saved_w_virtcol == wp->w_virtcol + && prev_wp == wp && prev_col_off == cur_col_off) + { + *right_col = prev_right_col; + *left_col = prev_left_col; + return; + } + + width1 = wp->w_width - cur_col_off; + width2 = width1 + win_col_off2(wp); + + *left_col = 0; + *right_col = width1; + + if (wp->w_virtcol >= (colnr_T)width1) + *right_col = width1 + ((wp->w_virtcol - width1) / width2 + 1) * width2; + if (wp->w_virtcol >= (colnr_T)width1 && width2 > 0) + *left_col = (wp->w_virtcol - width1) / width2 * width2 + width1; + + // cache values + prev_left_col = *left_col; + prev_right_col = *right_col; + prev_wp = wp; + saved_w_virtcol = wp->w_virtcol; + prev_col_off = cur_col_off; +} +#endif |