mirror of
				https://github.com/neovim/neovim.git
				synced 2025-11-04 09:44:31 +00:00 
			
		
		
		
	Merge #6597 'winhighlight'
This commit is contained in:
		@@ -3128,7 +3128,8 @@ A jump table for the options with a short description can be found at |Q_op|.
 | 
			
		||||
	use for that occasion.  The occasions are:
 | 
			
		||||
	|hl-SpecialKey|	 8  Meta and special keys listed with ":map"
 | 
			
		||||
	|hl-Whitespace|	 0
 | 
			
		||||
	|hl-EndOfBuffer|   ~ lines after the last line in the buffer
 | 
			
		||||
	|hl-EndOfBuffer|   ~  lines after the last line in the buffer
 | 
			
		||||
	|hl-NormalNC|	 I  non-current ("inactive") window
 | 
			
		||||
	|hl-TermCursor|	 z  Cursor in a focused terminal
 | 
			
		||||
	|hl-TermCursorNC|  Z Cursor in an unfocused terminal
 | 
			
		||||
	|hl-NonText|	 @  '@' at the end of the window and
 | 
			
		||||
@@ -6843,6 +6844,17 @@ A jump table for the options with a short description can be found at |Q_op|.
 | 
			
		||||
	'winheight' applies to the current window.  Use 'winminheight' to set
 | 
			
		||||
	the minimal height for other windows.
 | 
			
		||||
 | 
			
		||||
						*'winhighlight'* *'winhl'*
 | 
			
		||||
'winhighlight' 'winhl'	string (default empty)
 | 
			
		||||
			local to window
 | 
			
		||||
	Window-local highlights.  Comma-delimited list of |group-name| pairs
 | 
			
		||||
	"{hl-builtin}:{hl-group},..." where each {hl-builtin} is a group (from
 | 
			
		||||
	|highlight-groups|) to be overridden by {hl-group} in the window where
 | 
			
		||||
	this option was set.
 | 
			
		||||
	Currently |hl-Normal| and |hl-NormalNC| can be overridden.
 | 
			
		||||
	Useful for changing the background color. Example: >
 | 
			
		||||
		set winhighlight=Normal:MyNormal,NormalNC:MyNormalNC
 | 
			
		||||
<
 | 
			
		||||
			*'winfixheight'* *'wfh'* *'nowinfixheight'* *'nowfh'*
 | 
			
		||||
'winfixheight' 'wfh'	boolean	(default off)
 | 
			
		||||
			local to window
 | 
			
		||||
 
 | 
			
		||||
@@ -4922,6 +4922,8 @@ NonText		'@' at the end of the window, characters from 'showbreak'
 | 
			
		||||
		fit at the end of the line). See also |hl-EndOfBuffer|.
 | 
			
		||||
							*hl-Normal*
 | 
			
		||||
Normal		normal text
 | 
			
		||||
							*hl-NormalNC*
 | 
			
		||||
NormalNC	normal text in non-current window
 | 
			
		||||
							*hl-Pmenu*
 | 
			
		||||
Pmenu		Popup menu: normal item.
 | 
			
		||||
							*hl-PmenuSel*
 | 
			
		||||
 
 | 
			
		||||
@@ -2316,7 +2316,7 @@ void get_winopts(buf_T *buf)
 | 
			
		||||
  /* Set 'foldlevel' to 'foldlevelstart' if it's not negative. */
 | 
			
		||||
  if (p_fdls >= 0)
 | 
			
		||||
    curwin->w_p_fdl = p_fdls;
 | 
			
		||||
  check_colorcolumn(curwin);
 | 
			
		||||
  didset_window_options(curwin);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 
 | 
			
		||||
@@ -233,6 +233,8 @@ typedef struct {
 | 
			
		||||
# define w_p_crb_save w_onebuf_opt.wo_crb_save
 | 
			
		||||
  char_u *wo_scl;
 | 
			
		||||
# define w_p_scl w_onebuf_opt.wo_scl    // 'signcolumn'
 | 
			
		||||
  char_u *wo_winhl;
 | 
			
		||||
# define w_p_winhl w_onebuf_opt.wo_winhl    // 'winhighlight'
 | 
			
		||||
 | 
			
		||||
  int wo_scriptID[WV_COUNT];            /* SIDs for window-local options */
 | 
			
		||||
# define w_p_scriptID w_onebuf_opt.wo_scriptID
 | 
			
		||||
@@ -930,6 +932,10 @@ struct window_S {
 | 
			
		||||
 | 
			
		||||
  synblock_T  *w_s;                 /* for :ownsyntax */
 | 
			
		||||
 | 
			
		||||
  int w_hl_id;                      ///< 'winhighlight' id
 | 
			
		||||
  int w_hl_id_inactive;             ///< 'winhighlight' id for inactive window
 | 
			
		||||
  int w_hl_attr;                    ///< 'winhighlight' final attrs
 | 
			
		||||
 | 
			
		||||
  win_T       *w_prev;              /* link to previous window */
 | 
			
		||||
  win_T       *w_next;              /* link to next window */
 | 
			
		||||
  bool w_closing;                   /* window is being closed, don't let
 | 
			
		||||
 
 | 
			
		||||
@@ -465,6 +465,7 @@ typedef enum {
 | 
			
		||||
  , HLF_MC          // 'colorcolumn'
 | 
			
		||||
  , HLF_QFL         // selected quickfix line
 | 
			
		||||
  , HLF_0           // Whitespace
 | 
			
		||||
  , HLF_INACTIVE    // NormalNC: Normal text in non-current windows
 | 
			
		||||
  , HLF_COUNT       // MUST be the last one
 | 
			
		||||
} hlf_T;
 | 
			
		||||
 | 
			
		||||
@@ -473,7 +474,7 @@ typedef enum {
 | 
			
		||||
#define HL_FLAGS { '8', '~', 'z', 'Z', '@', 'd', 'e', 'i', 'l', 'm', 'M', 'n', \
 | 
			
		||||
                   'N', 'r', 's', 'S', 'c', 't', 'v', 'V', 'w', 'W', 'f', 'F', \
 | 
			
		||||
                   'A', 'C', 'D', 'T', '-', '>', 'B', 'P', 'R', 'L', '+', '=', \
 | 
			
		||||
                   'x', 'X', '*', '#', '_', '!', '.', 'o', 'q', '0' }
 | 
			
		||||
                   'x', 'X', '*', '#', '_', '!', '.', 'o', 'q', '0', 'I' }
 | 
			
		||||
 | 
			
		||||
EXTERN int highlight_attr[HLF_COUNT];       /* Highl. attr for each context. */
 | 
			
		||||
EXTERN int highlight_user[9];                   /* User[1-9] attributes */
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,9 @@
 | 
			
		||||
//   - Add a BV_XX or WV_XX entry to option_defs.h
 | 
			
		||||
//   - Add a variable to the window or buffer struct in buffer_defs.h.
 | 
			
		||||
//   - For a window option, add some code to copy_winopt().
 | 
			
		||||
//   - For a window string option, add code to check_winopt()
 | 
			
		||||
//     and clear_winopt(). If setting the option needs parsing,
 | 
			
		||||
//     add some code to didset_window_options().
 | 
			
		||||
//   - For a buffer option, add some code to buf_copy_options().
 | 
			
		||||
//   - For a buffer string option, add code to check_buf_options().
 | 
			
		||||
// - If it's a numeric option, add any necessary bounds checks to do_set().
 | 
			
		||||
@@ -249,7 +252,7 @@ typedef struct vimoption {
 | 
			
		||||
  "B:SpellBad,P:SpellCap,R:SpellRare,L:SpellLocal,+:Pmenu,=:PmenuSel," \
 | 
			
		||||
  "x:PmenuSbar,X:PmenuThumb,*:TabLine,#:TabLineSel,_:TabLineFill," \
 | 
			
		||||
  "!:CursorColumn,.:CursorLine,o:ColorColumn,q:QuickFixLine," \
 | 
			
		||||
  "0:Whitespace"
 | 
			
		||||
  "0:Whitespace,I:NormalNC"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * options[] is initialized here.
 | 
			
		||||
@@ -3171,6 +3174,10 @@ did_set_string_option (
 | 
			
		||||
    if (!valid_filetype(*varp)) {
 | 
			
		||||
      errmsg = e_invarg;
 | 
			
		||||
    }
 | 
			
		||||
  } else if (varp == &curwin->w_p_winhl) {
 | 
			
		||||
    if (!parse_winhl_opt(curwin)) {
 | 
			
		||||
      errmsg = e_invarg;
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    // Options that are a list of flags.
 | 
			
		||||
    p = NULL;
 | 
			
		||||
@@ -3579,6 +3586,38 @@ static char_u *compile_cap_prog(synblock_T *synblock)
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Handle setting `winhighlight' in window "wp"
 | 
			
		||||
static bool parse_winhl_opt(win_T *wp)
 | 
			
		||||
{
 | 
			
		||||
  int w_hl_id = 0, w_hl_id_inactive = 0;
 | 
			
		||||
 | 
			
		||||
  const char *p = (const char *)wp->w_p_winhl;
 | 
			
		||||
  while (*p) {
 | 
			
		||||
    char *colon = strchr(p, ':');
 | 
			
		||||
    if (!colon) {
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
    size_t nlen = (size_t)(colon-p);
 | 
			
		||||
    char *hi = colon+1;
 | 
			
		||||
    char *commap = xstrchrnul(hi, ',');
 | 
			
		||||
    int hl_id = syn_check_group((char_u *)hi, (int)(commap-hi));
 | 
			
		||||
 | 
			
		||||
    if (strncmp("Normal", p, nlen) == 0) {
 | 
			
		||||
      w_hl_id = hl_id;
 | 
			
		||||
    } else if (strncmp("NormalNC", p, nlen) == 0) {
 | 
			
		||||
      w_hl_id_inactive = hl_id;
 | 
			
		||||
    } else {
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    p = *commap ? commap+1 : "";
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  wp->w_hl_id = w_hl_id;
 | 
			
		||||
  wp->w_hl_id_inactive = w_hl_id_inactive;
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Set the scriptID for an option, taking care of setting the buffer- or
 | 
			
		||||
 * window-local value.
 | 
			
		||||
@@ -5488,6 +5527,7 @@ static char_u *get_varp(vimoption_T *p)
 | 
			
		||||
  case PV_WM:     return (char_u *)&(curbuf->b_p_wm);
 | 
			
		||||
  case PV_KMAP:   return (char_u *)&(curbuf->b_p_keymap);
 | 
			
		||||
  case PV_SCL:    return (char_u *)&(curwin->w_p_scl);
 | 
			
		||||
  case PV_WINHL:  return (char_u *)&(curwin->w_p_winhl);
 | 
			
		||||
  default:        EMSG(_("E356: get_varp ERROR"));
 | 
			
		||||
  }
 | 
			
		||||
  /* always return a valid pointer to avoid a crash! */
 | 
			
		||||
@@ -5514,7 +5554,6 @@ void win_copy_options(win_T *wp_from, win_T *wp_to)
 | 
			
		||||
  copy_winopt(&wp_from->w_allbuf_opt, &wp_to->w_allbuf_opt);
 | 
			
		||||
  /* Is this right? */
 | 
			
		||||
  wp_to->w_farsi = wp_from->w_farsi;
 | 
			
		||||
  briopt_check(wp_to);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@@ -5566,6 +5605,7 @@ void copy_winopt(winopt_T *from, winopt_T *to)
 | 
			
		||||
  to->wo_fdt = vim_strsave(from->wo_fdt);
 | 
			
		||||
  to->wo_fmr = vim_strsave(from->wo_fmr);
 | 
			
		||||
  to->wo_scl = vim_strsave(from->wo_scl);
 | 
			
		||||
  to->wo_winhl = vim_strsave(from->wo_winhl);
 | 
			
		||||
  check_winopt(to);             // don't want NULL pointers
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -5595,6 +5635,7 @@ static void check_winopt(winopt_T *wop)
 | 
			
		||||
  check_string_option(&wop->wo_cc);
 | 
			
		||||
  check_string_option(&wop->wo_cocu);
 | 
			
		||||
  check_string_option(&wop->wo_briopt);
 | 
			
		||||
  check_string_option(&wop->wo_winhl);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@@ -5614,8 +5655,17 @@ void clear_winopt(winopt_T *wop)
 | 
			
		||||
  clear_string_option(&wop->wo_cc);
 | 
			
		||||
  clear_string_option(&wop->wo_cocu);
 | 
			
		||||
  clear_string_option(&wop->wo_briopt);
 | 
			
		||||
  clear_string_option(&wop->wo_winhl);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void didset_window_options(win_T *wp)
 | 
			
		||||
{
 | 
			
		||||
  check_colorcolumn(wp);
 | 
			
		||||
  briopt_check(wp);
 | 
			
		||||
  parse_winhl_opt(wp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copy global option values to local options for one buffer.
 | 
			
		||||
 * Used when creating a new buffer and sometimes when entering a buffer.
 | 
			
		||||
 
 | 
			
		||||
@@ -807,6 +807,7 @@ enum {
 | 
			
		||||
  , WV_WFW
 | 
			
		||||
  , WV_WRAP
 | 
			
		||||
  , WV_SCL
 | 
			
		||||
  , WV_WINHL
 | 
			
		||||
  , WV_COUNT        // must be the last one
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2701,6 +2701,14 @@ return {
 | 
			
		||||
      varname='p_wak',
 | 
			
		||||
      defaults={if_true={vi="menu"}}
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      full_name='winhighlight', abbreviation='winhl',
 | 
			
		||||
      type='string', scope={'window'},
 | 
			
		||||
      vi_def=true,
 | 
			
		||||
      alloced=true,
 | 
			
		||||
      redraw={'current_window'},
 | 
			
		||||
      defaults={if_true={vi=""}}
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      full_name='window', abbreviation='wi',
 | 
			
		||||
      type='number', scope={'global'},
 | 
			
		||||
 
 | 
			
		||||
@@ -1584,6 +1584,11 @@ static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T h
 | 
			
		||||
# define FDC_OFF n
 | 
			
		||||
  int fdc = compute_foldcolumn(wp, 0);
 | 
			
		||||
 | 
			
		||||
  int attr = hl_attr(hl);
 | 
			
		||||
  if (wp->w_hl_attr != 0) {
 | 
			
		||||
    attr = hl_combine_attr(wp->w_hl_attr, attr);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (wp->w_p_rl) {
 | 
			
		||||
    // No check for cmdline window: should never be right-left.
 | 
			
		||||
    n = fdc;
 | 
			
		||||
@@ -1612,10 +1617,10 @@ static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T h
 | 
			
		||||
 | 
			
		||||
    screen_fill(wp->w_winrow + row, wp->w_winrow + endrow,
 | 
			
		||||
                wp->w_wincol, W_ENDCOL(wp) - 1 - FDC_OFF,
 | 
			
		||||
                c2, c2, hl_attr(hl));
 | 
			
		||||
                c2, c2, attr);
 | 
			
		||||
    screen_fill(wp->w_winrow + row, wp->w_winrow + endrow,
 | 
			
		||||
                W_ENDCOL(wp) - 1 - FDC_OFF, W_ENDCOL(wp) - FDC_OFF,
 | 
			
		||||
                c1, c2, hl_attr(hl));
 | 
			
		||||
                c1, c2, attr);
 | 
			
		||||
  } else {
 | 
			
		||||
    if (cmdwin_type != 0 && wp == curwin) {
 | 
			
		||||
      /* draw the cmdline character in the leftmost column */
 | 
			
		||||
@@ -1653,7 +1658,7 @@ static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T h
 | 
			
		||||
 | 
			
		||||
    screen_fill(wp->w_winrow + row, wp->w_winrow + endrow,
 | 
			
		||||
                wp->w_wincol + FDC_OFF, W_ENDCOL(wp),
 | 
			
		||||
                c1, c2, hl_attr(hl));
 | 
			
		||||
                c1, c2, attr);
 | 
			
		||||
  }
 | 
			
		||||
  set_empty_rows(wp, row);
 | 
			
		||||
}
 | 
			
		||||
@@ -2418,6 +2423,10 @@ win_line (
 | 
			
		||||
    line_attr = hl_attr(HLF_QFL);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (wp->w_hl_attr != 0) {
 | 
			
		||||
    line_attr = hl_combine_attr(wp->w_hl_attr, line_attr);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (line_attr != 0) {
 | 
			
		||||
    area_highlighting = true;
 | 
			
		||||
  }
 | 
			
		||||
@@ -2849,6 +2858,10 @@ win_line (
 | 
			
		||||
        } else
 | 
			
		||||
          char_attr = 0;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (wp->w_hl_attr != 0) {
 | 
			
		||||
        char_attr = hl_combine_attr(wp->w_hl_attr, char_attr);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* When still displaying '$' of change command, stop at cursor */
 | 
			
		||||
@@ -3083,10 +3096,14 @@ win_line (
 | 
			
		||||
            mb_l = 1;
 | 
			
		||||
            mb_utf8 = FALSE;
 | 
			
		||||
            multi_attr = hl_attr(HLF_AT);
 | 
			
		||||
            /* put the pointer back to output the double-width
 | 
			
		||||
             * character at the start of the next line. */
 | 
			
		||||
            ++n_extra;
 | 
			
		||||
            --p_extra;
 | 
			
		||||
            if (wp->w_hl_attr != 0) {
 | 
			
		||||
              multi_attr = hl_combine_attr(wp->w_hl_attr, multi_attr);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // put the pointer back to output the double-width
 | 
			
		||||
            // character at the start of the next line.
 | 
			
		||||
            n_extra++;
 | 
			
		||||
            p_extra--;
 | 
			
		||||
          } else {
 | 
			
		||||
            n_extra -= mb_l - 1;
 | 
			
		||||
            p_extra += mb_l - 1;
 | 
			
		||||
@@ -3221,11 +3238,15 @@ win_line (
 | 
			
		||||
          mb_utf8 = FALSE;
 | 
			
		||||
          mb_l = 1;
 | 
			
		||||
          multi_attr = hl_attr(HLF_AT);
 | 
			
		||||
          /* Put pointer back so that the character will be
 | 
			
		||||
           * displayed at the start of the next line. */
 | 
			
		||||
          --ptr;
 | 
			
		||||
        } else if (*ptr != NUL)
 | 
			
		||||
          if (wp->w_hl_attr != 0) {
 | 
			
		||||
            multi_attr = hl_combine_attr(wp->w_hl_attr, multi_attr);
 | 
			
		||||
          }
 | 
			
		||||
          // Put pointer back so that the character will be
 | 
			
		||||
          // displayed at the start of the next line.
 | 
			
		||||
          ptr--;
 | 
			
		||||
        } else if (*ptr != NUL) {
 | 
			
		||||
          ptr += mb_l - 1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* If a double-width char doesn't fit at the left side display
 | 
			
		||||
         * a '<' in the first column.  Don't do this for unprintable
 | 
			
		||||
@@ -3752,7 +3773,10 @@ win_line (
 | 
			
		||||
        mb_utf8 = false;  // don't draw as UTF-8
 | 
			
		||||
      }
 | 
			
		||||
      saved_attr3 = char_attr;  // save current attr
 | 
			
		||||
      char_attr = hl_attr(HLF_AT);  // later copied to char_attr
 | 
			
		||||
      char_attr = hl_attr(HLF_AT);  // overwriting char_attr
 | 
			
		||||
      if (wp->w_hl_attr != 0) {
 | 
			
		||||
        char_attr = hl_combine_attr(wp->w_hl_attr, char_attr);
 | 
			
		||||
      }
 | 
			
		||||
      n_attr3 = 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -3836,6 +3860,10 @@ win_line (
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (wp->w_hl_attr != 0) {
 | 
			
		||||
          char_attr = hl_combine_attr(wp->w_hl_attr, char_attr);
 | 
			
		||||
        }
 | 
			
		||||
        ScreenAttrs[off] = char_attr;
 | 
			
		||||
        if (wp->w_p_rl) {
 | 
			
		||||
          --col;
 | 
			
		||||
@@ -3897,6 +3925,14 @@ win_line (
 | 
			
		||||
            if (rightmost_vcol < color_cols[i])
 | 
			
		||||
              rightmost_vcol = color_cols[i];
 | 
			
		||||
 | 
			
		||||
        int cuc_attr = hl_attr(HLF_CUC);
 | 
			
		||||
        int mc_attr = hl_attr(HLF_MC);
 | 
			
		||||
        if (wp->w_hl_attr != 0) {
 | 
			
		||||
          cuc_attr = hl_combine_attr(wp->w_hl_attr, cuc_attr);
 | 
			
		||||
          mc_attr = hl_combine_attr(wp->w_hl_attr, mc_attr);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        while (col < wp->w_width) {
 | 
			
		||||
          ScreenLines[off] = ' ';
 | 
			
		||||
          if (enc_utf8)
 | 
			
		||||
@@ -3906,12 +3942,13 @@ win_line (
 | 
			
		||||
            draw_color_col = advance_color_col(VCOL_HLC,
 | 
			
		||||
                &color_cols);
 | 
			
		||||
 | 
			
		||||
          if (wp->w_p_cuc && VCOL_HLC == (long)wp->w_virtcol)
 | 
			
		||||
            ScreenAttrs[off++] = hl_attr(HLF_CUC);
 | 
			
		||||
          else if (draw_color_col && VCOL_HLC == *color_cols)
 | 
			
		||||
            ScreenAttrs[off++] = hl_attr(HLF_MC);
 | 
			
		||||
          else
 | 
			
		||||
            ScreenAttrs[off++] = 0;
 | 
			
		||||
          if (wp->w_p_cuc && VCOL_HLC == (long)wp->w_virtcol) {
 | 
			
		||||
            ScreenAttrs[off++] = cuc_attr;
 | 
			
		||||
          } else if (draw_color_col && VCOL_HLC == *color_cols) {
 | 
			
		||||
            ScreenAttrs[off++] = mc_attr;
 | 
			
		||||
          } else {
 | 
			
		||||
            ScreenAttrs[off++] = wp->w_hl_attr;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          if (VCOL_HLC >= rightmost_vcol)
 | 
			
		||||
            break;
 | 
			
		||||
@@ -3920,6 +3957,7 @@ win_line (
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // TODO(bfredl): integrate with the common beyond-the-end-loop
 | 
			
		||||
      if (wp->w_buffer->terminal) {
 | 
			
		||||
        // terminal buffers may need to highlight beyond the end of the
 | 
			
		||||
        // logical line
 | 
			
		||||
@@ -3961,6 +3999,9 @@ win_line (
 | 
			
		||||
            || (n_extra && (c_extra != NUL || *p_extra != NUL)))) {
 | 
			
		||||
      c = lcs_ext;
 | 
			
		||||
      char_attr = hl_attr(HLF_AT);
 | 
			
		||||
      if (wp->w_hl_attr != 0) {
 | 
			
		||||
        char_attr = hl_combine_attr(wp->w_hl_attr, char_attr);
 | 
			
		||||
      }
 | 
			
		||||
      mb_c = c;
 | 
			
		||||
      if (enc_utf8 && (*mb_char2len)(c) > 1) {
 | 
			
		||||
        mb_utf8 = TRUE;
 | 
			
		||||
@@ -5510,7 +5551,19 @@ static void init_search_hl(win_T *wp)
 | 
			
		||||
  search_hl.buf = wp->w_buffer;
 | 
			
		||||
  search_hl.lnum = 0;
 | 
			
		||||
  search_hl.first_lnum = 0;
 | 
			
		||||
  /* time limit is set at the toplevel, for all windows */
 | 
			
		||||
  // time limit is set at the toplevel, for all windows
 | 
			
		||||
 | 
			
		||||
  // determine window specific background set in 'winhighlight'
 | 
			
		||||
  if (wp != curwin && wp->w_hl_id_inactive > 0) {
 | 
			
		||||
    wp->w_hl_attr = syn_id2attr(wp->w_hl_id_inactive);
 | 
			
		||||
  } else if (wp->w_hl_id > 0) {
 | 
			
		||||
    wp->w_hl_attr = syn_id2attr(wp->w_hl_id);
 | 
			
		||||
  } else {
 | 
			
		||||
    wp->w_hl_attr = 0;
 | 
			
		||||
  }
 | 
			
		||||
  if (wp != curwin) {
 | 
			
		||||
    wp->w_hl_attr = hl_combine_attr(hl_attr(HLF_INACTIVE), wp->w_hl_attr);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 
 | 
			
		||||
@@ -1043,7 +1043,7 @@ static void win_init(win_T *newp, win_T *oldp, int flags)
 | 
			
		||||
 | 
			
		||||
  win_init_some(newp, oldp);
 | 
			
		||||
 | 
			
		||||
  check_colorcolumn(newp);
 | 
			
		||||
  didset_window_options(newp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@@ -3722,6 +3722,12 @@ static void win_enter_ext(win_T *wp, bool undo_sync, int curwin_invalid,
 | 
			
		||||
  if (restart_edit)
 | 
			
		||||
    redraw_later(VALID);        /* causes status line redraw */
 | 
			
		||||
 | 
			
		||||
  if (hl_attr(HLF_INACTIVE)
 | 
			
		||||
      || (prevwin && prevwin->w_hl_id_inactive)
 | 
			
		||||
      || curwin->w_hl_id_inactive) {
 | 
			
		||||
    redraw_all_later(NOT_VALID);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* set window height to desired minimal value */
 | 
			
		||||
  if (curwin->w_height < p_wh && !curwin->w_p_wfh)
 | 
			
		||||
    win_setheight((int)p_wh);
 | 
			
		||||
 
 | 
			
		||||
@@ -194,8 +194,8 @@ describe('ui/cursor', function()
 | 
			
		||||
        if m.blinkoff then m.blinkoff = 400 end
 | 
			
		||||
        if m.blinkwait then m.blinkwait = 700 end
 | 
			
		||||
      end
 | 
			
		||||
      if m.hl_id then m.hl_id = 46 end
 | 
			
		||||
      if m.id_lm then m.id_lm = 47 end
 | 
			
		||||
      if m.hl_id then m.hl_id = 47 end
 | 
			
		||||
      if m.id_lm then m.id_lm = 48 end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    -- Assert the new expectation.
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@ local Screen = require('test.functional.ui.screen')
 | 
			
		||||
local os = require('os')
 | 
			
		||||
local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
 | 
			
		||||
local command = helpers.command
 | 
			
		||||
local eval = helpers.eval
 | 
			
		||||
local eval, exc_exec = helpers.eval, helpers.exc_exec
 | 
			
		||||
local feed_command, request, eq = helpers.feed_command, helpers.request, helpers.eq
 | 
			
		||||
 | 
			
		||||
describe('colorscheme compatibility', function()
 | 
			
		||||
@@ -650,3 +650,296 @@ describe("'listchars' highlight", function()
 | 
			
		||||
    ]])
 | 
			
		||||
  end)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
describe("'winhighlight' highlight", function()
 | 
			
		||||
  local screen
 | 
			
		||||
 | 
			
		||||
  before_each(function()
 | 
			
		||||
    clear()
 | 
			
		||||
    screen = Screen.new(20,8)
 | 
			
		||||
    screen:attach()
 | 
			
		||||
    screen:set_default_attr_ids({
 | 
			
		||||
      [0] = {bold=true, foreground=Screen.colors.Blue},
 | 
			
		||||
      [1] = {background = Screen.colors.DarkBlue},
 | 
			
		||||
      [2] = {background = Screen.colors.DarkBlue, bold = true, foreground = Screen.colors.Blue1},
 | 
			
		||||
      [3] = {bold = true, reverse = true},
 | 
			
		||||
      [4] = {reverse = true},
 | 
			
		||||
      [5] = {background = Screen.colors.DarkGreen},
 | 
			
		||||
      [6] = {background = Screen.colors.DarkGreen, bold = true, foreground = Screen.colors.Blue1},
 | 
			
		||||
      [7] = {background = Screen.colors.DarkMagenta},
 | 
			
		||||
      [8] = {background = Screen.colors.DarkMagenta, bold = true, foreground = Screen.colors.Blue1},
 | 
			
		||||
      [9] = {foreground = Screen.colors.Brown},
 | 
			
		||||
      [10] = {foreground = Screen.colors.Brown, background = Screen.colors.DarkBlue},
 | 
			
		||||
    })
 | 
			
		||||
    command("hi Background1 guibg=DarkBlue")
 | 
			
		||||
    command("hi Background2 guibg=DarkGreen")
 | 
			
		||||
  end)
 | 
			
		||||
 | 
			
		||||
  it('works', function()
 | 
			
		||||
    insert("aa")
 | 
			
		||||
    command("split")
 | 
			
		||||
    command("set winhl=Normal:Background1")
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
      {1:a^a                  }|
 | 
			
		||||
      {2:~                   }|
 | 
			
		||||
      {2:~                   }|
 | 
			
		||||
      {3:[No Name] [+]       }|
 | 
			
		||||
      aa                  |
 | 
			
		||||
      {0:~                   }|
 | 
			
		||||
      {4:[No Name] [+]       }|
 | 
			
		||||
                          |
 | 
			
		||||
    ]])
 | 
			
		||||
 | 
			
		||||
    command("enew")
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
      {1:^                    }|
 | 
			
		||||
      {2:~                   }|
 | 
			
		||||
      {2:~                   }|
 | 
			
		||||
      {3:[No Name]           }|
 | 
			
		||||
      aa                  |
 | 
			
		||||
      {0:~                   }|
 | 
			
		||||
      {4:[No Name] [+]       }|
 | 
			
		||||
                          |
 | 
			
		||||
    ]])
 | 
			
		||||
  end)
 | 
			
		||||
 | 
			
		||||
  it('handles invalid values', function()
 | 
			
		||||
    command("set winhl=Normal:Background1")
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
      {1:^                    }|
 | 
			
		||||
      {2:~                   }|
 | 
			
		||||
      {2:~                   }|
 | 
			
		||||
      {2:~                   }|
 | 
			
		||||
      {2:~                   }|
 | 
			
		||||
      {2:~                   }|
 | 
			
		||||
      {2:~                   }|
 | 
			
		||||
                          |
 | 
			
		||||
    ]])
 | 
			
		||||
 | 
			
		||||
    eq('Vim(set):E474: Invalid argument: winhl=xxx:yyy',
 | 
			
		||||
       exc_exec("set winhl=xxx:yyy"))
 | 
			
		||||
    eq('Normal:Background1', eval('&winhl'))
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
      {1:^                    }|
 | 
			
		||||
      {2:~                   }|
 | 
			
		||||
      {2:~                   }|
 | 
			
		||||
      {2:~                   }|
 | 
			
		||||
      {2:~                   }|
 | 
			
		||||
      {2:~                   }|
 | 
			
		||||
      {2:~                   }|
 | 
			
		||||
                          |
 | 
			
		||||
    ]])
 | 
			
		||||
  end)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  it('works local to the buffer', function()
 | 
			
		||||
    insert("aa")
 | 
			
		||||
    command("split")
 | 
			
		||||
    command("setlocal winhl=Normal:Background1")
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
      {1:a^a                  }|
 | 
			
		||||
      {2:~                   }|
 | 
			
		||||
      {2:~                   }|
 | 
			
		||||
      {3:[No Name] [+]       }|
 | 
			
		||||
      aa                  |
 | 
			
		||||
      {0:~                   }|
 | 
			
		||||
      {4:[No Name] [+]       }|
 | 
			
		||||
                          |
 | 
			
		||||
    ]])
 | 
			
		||||
 | 
			
		||||
    command("enew")
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
      ^                    |
 | 
			
		||||
      {0:~                   }|
 | 
			
		||||
      {0:~                   }|
 | 
			
		||||
      {3:[No Name]           }|
 | 
			
		||||
      aa                  |
 | 
			
		||||
      {0:~                   }|
 | 
			
		||||
      {4:[No Name] [+]       }|
 | 
			
		||||
                          |
 | 
			
		||||
    ]])
 | 
			
		||||
 | 
			
		||||
    command("bnext")
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
      {1:^aa                  }|
 | 
			
		||||
      {2:~                   }|
 | 
			
		||||
      {2:~                   }|
 | 
			
		||||
      {3:[No Name] [+]       }|
 | 
			
		||||
      aa                  |
 | 
			
		||||
      {0:~                   }|
 | 
			
		||||
      {4:[No Name] [+]       }|
 | 
			
		||||
      <f 1 --100%-- col 1 |
 | 
			
		||||
    ]])
 | 
			
		||||
 | 
			
		||||
  end)
 | 
			
		||||
 | 
			
		||||
  it('for inactive window works', function()
 | 
			
		||||
    command("set winhl=Normal:Background1,NormalNC:Background2")
 | 
			
		||||
    -- tests global value is copied across split
 | 
			
		||||
    command("split")
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
      {1:^                    }|
 | 
			
		||||
      {2:~                   }|
 | 
			
		||||
      {2:~                   }|
 | 
			
		||||
      {3:[No Name]           }|
 | 
			
		||||
      {5:                    }|
 | 
			
		||||
      {6:~                   }|
 | 
			
		||||
      {4:[No Name]           }|
 | 
			
		||||
                          |
 | 
			
		||||
    ]])
 | 
			
		||||
 | 
			
		||||
    feed("<c-w><c-w>")
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
      {5:                    }|
 | 
			
		||||
      {6:~                   }|
 | 
			
		||||
      {6:~                   }|
 | 
			
		||||
      {4:[No Name]           }|
 | 
			
		||||
      {1:^                    }|
 | 
			
		||||
      {2:~                   }|
 | 
			
		||||
      {3:[No Name]           }|
 | 
			
		||||
                          |
 | 
			
		||||
    ]])
 | 
			
		||||
 | 
			
		||||
    feed("<c-w><c-w>")
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
      {1:^                    }|
 | 
			
		||||
      {2:~                   }|
 | 
			
		||||
      {2:~                   }|
 | 
			
		||||
      {3:[No Name]           }|
 | 
			
		||||
      {5:                    }|
 | 
			
		||||
      {6:~                   }|
 | 
			
		||||
      {4:[No Name]           }|
 | 
			
		||||
                          |
 | 
			
		||||
    ]])
 | 
			
		||||
 | 
			
		||||
  end)
 | 
			
		||||
 | 
			
		||||
  it('works with NormalNC', function()
 | 
			
		||||
    command("hi NormalNC guibg=DarkMagenta")
 | 
			
		||||
    -- tests global value is copied across split
 | 
			
		||||
    command("split")
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
      ^                    |
 | 
			
		||||
      {0:~                   }|
 | 
			
		||||
      {0:~                   }|
 | 
			
		||||
      {3:[No Name]           }|
 | 
			
		||||
      {7:                    }|
 | 
			
		||||
      {8:~                   }|
 | 
			
		||||
      {4:[No Name]           }|
 | 
			
		||||
                          |
 | 
			
		||||
    ]])
 | 
			
		||||
 | 
			
		||||
    command("wincmd w")
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
      {7:                    }|
 | 
			
		||||
      {8:~                   }|
 | 
			
		||||
      {8:~                   }|
 | 
			
		||||
      {4:[No Name]           }|
 | 
			
		||||
      ^                    |
 | 
			
		||||
      {0:~                   }|
 | 
			
		||||
      {3:[No Name]           }|
 | 
			
		||||
                          |
 | 
			
		||||
    ]])
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    -- winbg=Normal:... overrides global NormalNC
 | 
			
		||||
    command("set winhl=Normal:Background1")
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
      {7:                    }|
 | 
			
		||||
      {8:~                   }|
 | 
			
		||||
      {8:~                   }|
 | 
			
		||||
      {4:[No Name]           }|
 | 
			
		||||
      {1:^                    }|
 | 
			
		||||
      {2:~                   }|
 | 
			
		||||
      {3:[No Name]           }|
 | 
			
		||||
                          |
 | 
			
		||||
    ]])
 | 
			
		||||
 | 
			
		||||
    command("wincmd w")
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
      ^                    |
 | 
			
		||||
      {0:~                   }|
 | 
			
		||||
      {0:~                   }|
 | 
			
		||||
      {3:[No Name]           }|
 | 
			
		||||
      {1:                    }|
 | 
			
		||||
      {2:~                   }|
 | 
			
		||||
      {4:[No Name]           }|
 | 
			
		||||
                          |
 | 
			
		||||
    ]])
 | 
			
		||||
 | 
			
		||||
    command("wincmd w")
 | 
			
		||||
    command("set winhl=Normal:Background1,NormalNC:Background2")
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
      {7:                    }|
 | 
			
		||||
      {8:~                   }|
 | 
			
		||||
      {8:~                   }|
 | 
			
		||||
      {4:[No Name]           }|
 | 
			
		||||
      {1:^                    }|
 | 
			
		||||
      {2:~                   }|
 | 
			
		||||
      {3:[No Name]           }|
 | 
			
		||||
                          |
 | 
			
		||||
    ]])
 | 
			
		||||
 | 
			
		||||
    command("wincmd w")
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
      ^                    |
 | 
			
		||||
      {0:~                   }|
 | 
			
		||||
      {0:~                   }|
 | 
			
		||||
      {3:[No Name]           }|
 | 
			
		||||
      {5:                    }|
 | 
			
		||||
      {6:~                   }|
 | 
			
		||||
      {4:[No Name]           }|
 | 
			
		||||
                          |
 | 
			
		||||
    ]])
 | 
			
		||||
 | 
			
		||||
  end)
 | 
			
		||||
 | 
			
		||||
  it('applies also to non-text', function()
 | 
			
		||||
    insert('Lorem ipsum dolor sit amet ')
 | 
			
		||||
    command('set shiftwidth=2')
 | 
			
		||||
    feed('>>')
 | 
			
		||||
    command('set number')
 | 
			
		||||
    command('set breakindent')
 | 
			
		||||
    command('set briopt=shift:5,min:0')
 | 
			
		||||
    command('set list')
 | 
			
		||||
    command('set showbreak=↪')
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
      {9:  1 }  ^Lorem ipsum do|
 | 
			
		||||
      {9:    }       {0:↪}lor sit |
 | 
			
		||||
      {9:    }       {0:↪}amet{0:-}   |
 | 
			
		||||
      {0:~                   }|
 | 
			
		||||
      {0:~                   }|
 | 
			
		||||
      {0:~                   }|
 | 
			
		||||
      {0:~                   }|
 | 
			
		||||
                          |
 | 
			
		||||
    ]])
 | 
			
		||||
 | 
			
		||||
    command('set winhl=Normal:Background1')
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
      {10:  1 }{1:  ^Lorem ipsum do}|
 | 
			
		||||
      {10:    }{1:       }{2:↪}{1:lor sit }|
 | 
			
		||||
      {10:    }{1:       }{2:↪}{1:amet}{2:-}{1:   }|
 | 
			
		||||
      {2:~                   }|
 | 
			
		||||
      {2:~                   }|
 | 
			
		||||
      {2:~                   }|
 | 
			
		||||
      {2:~                   }|
 | 
			
		||||
                          |
 | 
			
		||||
    ]])
 | 
			
		||||
 | 
			
		||||
    command('set nowrap')
 | 
			
		||||
    command('set listchars+=extends:❯,precedes:❮')
 | 
			
		||||
    feed('3w')
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
      {10:  1 }{2:❮}{1: dolor ^sit ame}{2:❯}|
 | 
			
		||||
      {2:~                   }|
 | 
			
		||||
      {2:~                   }|
 | 
			
		||||
      {2:~                   }|
 | 
			
		||||
      {2:~                   }|
 | 
			
		||||
      {2:~                   }|
 | 
			
		||||
      {2:~                   }|
 | 
			
		||||
                          |
 | 
			
		||||
    ]])
 | 
			
		||||
  end)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user