changeset 2314:233eb4412f5d vim73

Added 'colorcolumn' option. Partly by Gregor Uhlenheuer.
author Bram Moolenaar <bram@vim.org>
date Wed, 14 Jul 2010 19:53:30 +0200
parents e382b66b936d
children 2e6dbc2fccd4
files runtime/doc/options.txt runtime/doc/syntax.txt runtime/doc/tags runtime/doc/todo.txt src/option.c src/option.h src/os_macosx.m src/proto/option.pro src/screen.c src/structs.h src/syntax.c src/vim.h src/window.c
diffstat 13 files changed, 259 insertions(+), 107 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -2163,7 +2163,7 @@ A jump table for the options with a shor
 	column.  This option is useful for viewing the
 	differences between two versions of a file (see 'diff'); in diff mode,
 	inserted and deleted lines (though not characters within a line) are
-	taken into account. 
+	taken into account.
 
 
 			*'cursorcolumn'* *'cuc'* *'nocursorcolumn'* *'nocuc'*
@@ -4547,6 +4547,25 @@ A jump table for the options with a shor
 <	This option cannot be set from a |modeline| or in the |sandbox|, for
 	security reasons.
 
+						*'colorcolumn'* *'cc'*
+'colorcolumn' 'cc'	string	(default "")
+			local to window
+			{not in Vi}
+			{not available when compiled without the |+syntax|
+			feature}
+	'colorcolumn' is a comma separated list of screen columns that are
+	highlighted with ColorColumn |hl-ColorColumn|.  Useful to align
+	text.  Will make screen redrawing slower.
+	The screen column can be an absolute number, or a number preceded with
+	'+' or '-', which is added to or subtracted from 'textwidth'. >
+
+		:set cc=+1  " highlight column after 'textwidth'
+		:set cc=+1,+2,+3  " highlight three columns after 'textwidth'
+		:hi ColorColumn ctermbg=lightgrey guibg=lightgrey
+<
+	When 'textwidth' is zero then the items with '-' and '+' are not used.
+	A maximum of 256 columns are highlighted.
+
 						*'matchpairs'* *'mps'*
 'matchpairs' 'mps'	string	(default "(:),{:},[:]")
 			local to buffer
@@ -6013,7 +6032,7 @@ A jump table for the options with a shor
 		:set showbreak=>\ 
 <	Note the backslash to escape the trailing space.  It's easier like
 	this: >
-		:let &showbreak = '+++ ' 
+		:let &showbreak = '+++ '
 <	Only printable single-cell characters are allowed, excluding <Tab> and
 	comma (in a future version the comma might be used to separate the
 	part that is shown at the end and at the start of a line).
--- a/runtime/doc/syntax.txt
+++ b/runtime/doc/syntax.txt
@@ -4212,6 +4212,8 @@ These are the default highlighting group
 'highlight' option default.  Note that the highlighting depends on the value
 of 'background'.  You can see the current settings with the ":highlight"
 command.
+							*hl-ColorColumn*
+ColorColumn	used for the columns set with 'colorcolumn'
 							*hl-Conceal*
 Conceal		placeholder characters substituted for concealed
 		text (see 'conceallevel')
--- a/runtime/doc/tags
+++ b/runtime/doc/tags
@@ -101,6 +101,7 @@
 'buftype'	options.txt	/*'buftype'*
 'casemap'	options.txt	/*'casemap'*
 'cb'	options.txt	/*'cb'*
+'cc'	options.txt	/*'cc'*
 'ccv'	options.txt	/*'ccv'*
 'cd'	options.txt	/*'cd'*
 'cdpath'	options.txt	/*'cdpath'*
@@ -126,6 +127,7 @@
 'cmp'	options.txt	/*'cmp'*
 'cms'	options.txt	/*'cms'*
 'co'	options.txt	/*'co'*
+'colorcolumn'	options.txt	/*'colorcolumn'*
 'columns'	options.txt	/*'columns'*
 'com'	options.txt	/*'com'*
 'comments'	options.txt	/*'comments'*
--- a/runtime/doc/todo.txt
+++ b/runtime/doc/todo.txt
@@ -1098,12 +1098,8 @@ Vim 7.3:
 - Conceal feature: no update when moving to another window. (Dominique Pelle,
   2010 Jul 5)  Vince will look into it.
 Patches to possibly include:
-- Patch for vertical line at certain column position, 'guidecolumn' option.
-  (Pankaj Garg, 2009 Apr 14, aka Lone, Apr 15)
-  Update 2009 May 2, 'margincolumn'
+- 'colorcolumn': make it local to window.
   Alternative patch. (2010 Feb 2, Gregor Uhlenheuer, update 2010 Jul 12)
-  Fix by Lech Lorens, Apr 19
-  When there are multiple columns it makes sense to call it 'guidecolumn'
 - Another patch for Javascript indenting. (Hari Kumar, 2010 Jul 11)
   Needs a few tests.
 - Add different highlighting for a fold line depending on the fold level.
--- a/src/option.c
+++ b/src/option.c
@@ -232,6 +232,7 @@
 #ifdef FEAT_SYN_HL
 # define PV_CUC		OPT_WIN(WV_CUC)
 # define PV_CUL		OPT_WIN(WV_CUL)
+# define PV_CC		OPT_WIN(WV_CC)
 #endif
 #ifdef FEAT_STL_OPT
 # define PV_STL		OPT_BOTH(OPT_WIN(WV_STL))
@@ -466,7 +467,7 @@ struct vimoption
 #if defined(FEAT_DIFF) || defined(FEAT_FOLDING) || defined(FEAT_SPELL) \
 	|| defined(FEAT_VERTSPLIT) || defined(FEAT_CLIPBOARD) \
 	|| defined(FEAT_INS_EXPAND) || defined(FEAT_SYN_HL) || defined(FEAT_CONCEAL)
-# define HIGHLIGHT_INIT "8:SpecialKey,@:NonText,d:Directory,e:ErrorMsg,i:IncSearch,l:Search,m:MoreMsg,M:ModeMsg,n:LineNr,r:Question,s:StatusLine,S:StatusLineNC,c:VertSplit,t:Title,v:Visual,V:VisualNOS,w:WarningMsg,W:WildMenu,f:Folded,F:FoldColumn,A:DiffAdd,C:DiffChange,D:DiffDelete,T:DiffText,>:SignColumn,-:Conceal,B:SpellBad,P:SpellCap,R:SpellRare,L:SpellLocal,+:Pmenu,=:PmenuSel,x:PmenuSbar,X:PmenuThumb,*:TabLine,#:TabLineSel,_:TabLineFill,!:CursorColumn,.:CursorLine"
+# define HIGHLIGHT_INIT "8:SpecialKey,@:NonText,d:Directory,e:ErrorMsg,i:IncSearch,l:Search,m:MoreMsg,M:ModeMsg,n:LineNr,r:Question,s:StatusLine,S:StatusLineNC,c:VertSplit,t:Title,v:Visual,V:VisualNOS,w:WarningMsg,W:WildMenu,f:Folded,F:FoldColumn,A:DiffAdd,C:DiffChange,D:DiffDelete,T:DiffText,>:SignColumn,-:Conceal,B:SpellBad,P:SpellCap,R:SpellRare,L:SpellLocal,+:Pmenu,=:PmenuSel,x:PmenuSbar,X:PmenuThumb,*:TabLine,#:TabLineSel,_:TabLineFill,!:CursorColumn,.:CursorLine,o:ColorColumn"
 #else
 # define HIGHLIGHT_INIT "8:SpecialKey,@:NonText,d:Directory,e:ErrorMsg,i:IncSearch,l:Search,m:MoreMsg,M:ModeMsg,n:LineNr,r:Question,s:StatusLine,S:StatusLineNC,t:Title,v:Visual,w:WarningMsg,W:WildMenu,>:SignColumn,*:TabLine,#:TabLineSel,_:TabLineFill"
 #endif
@@ -774,6 +775,13 @@ static struct vimoption
 			    (char_u *)NULL, PV_NONE,
 #endif
 			    {(char_u *)7L, (char_u *)0L} SCRIPTID_INIT},
+    {"colorcolumn", "cc",   P_STRING|P_VI_DEF|P_COMMA|P_NODUP|P_RWIN,
+#ifdef FEAT_SYN_HL
+			    (char_u *)VAR_WIN, PV_CC,
+#else
+			    (char_u *)NULL, PV_NONE,
+#endif
+			    {(char_u *)"", (char_u *)0L} SCRIPTID_INIT},
     {"columns",	    "co",   P_NUM|P_NODEFAULT|P_NO_MKRC|P_VI_DEF|P_RCLR,
 			    (char_u *)&Columns, PV_NONE,
 			    {(char_u *)80L, (char_u *)0L} SCRIPTID_INIT},
@@ -2526,7 +2534,7 @@ static struct vimoption
 			    (char_u *)FALSE,
 #endif
 				(char_u *)0L} SCRIPTID_INIT},
-    {"textwidth",   "tw",   P_NUM|P_VI_DEF|P_VIM,
+    {"textwidth",   "tw",   P_NUM|P_VI_DEF|P_VIM|P_RBUF,
 			    (char_u *)&p_tw, PV_TW,
 			    {(char_u *)0L, (char_u *)0L} SCRIPTID_INIT},
     {"thesaurus",   "tsr",  P_STRING|P_EXPAND|P_VI_DEF|P_COMMA|P_NODUP,
@@ -2975,6 +2983,9 @@ static void set_string_option_global __A
 static void set_string_option __ARGS((int opt_idx, char_u *value, int opt_flags));
 static char_u *did_set_string_option __ARGS((int opt_idx, char_u **varp, int new_value_alloced, char_u *oldval, char_u *errbuf, int opt_flags));
 static char_u *set_chars_option __ARGS((char_u **varp));
+#ifdef FEAT_SYN_HL
+static int int_cmp __ARGS((const void *a, const void *b));
+#endif
 #ifdef FEAT_CLIPBOARD
 static char_u *check_clipboard_option __ARGS((void));
 #endif
@@ -5638,6 +5649,12 @@ did_set_string_option(opt_idx, varp, new
 	}
     }
 
+#ifdef FEAT_SYN_HL
+    /* 'colorcolumn' */
+    else if (varp == &curwin->w_p_cc)
+	errmsg = check_colorcolumn(curwin);
+#endif
+
 #ifdef FEAT_MULTI_LANG
     /* 'helplang' */
     else if (varp == &p_hlg)
@@ -6911,6 +6928,85 @@ did_set_string_option(opt_idx, varp, new
     return errmsg;
 }
 
+#ifdef FEAT_SYN_HL
+/*
+ * Simple int comparison function for use with qsort()
+ */
+    static int
+int_cmp(a, b)
+    const void *a;
+    const void *b;
+{
+    return *(const int *)a - *(const int *)b;
+}
+
+/*
+ * Handle setting 'colorcolumn' or 'textwidth' in window "wp".
+ * Returns error message, NULL if it's OK.
+ */
+    char_u *
+check_colorcolumn(wp)
+    win_T	*wp;
+{
+    char_u	*s;
+    int		col;
+    int		count = 0;
+    int		color_cols[256];
+    int		i;
+    int		j = 0;
+
+    for (s = wp->w_p_cc; *s != NUL && count < 255; ++s)
+    {
+	if (*s == '-' || *s == '+')
+	{
+	    /* -N and +N: add to 'textwidth' */
+	    col = (*s == '-') ? -1 : 1;
+	    ++s;
+	    if (!VIM_ISDIGIT(*s))
+		return e_invarg;
+	    col = col * getdigits(&s);
+	    if (wp->w_buffer->b_p_tw == 0)
+		continue;  /* 'textwidth' not set, skip this item */
+	    col += wp->w_buffer->b_p_tw;
+	    if (col < 0)
+		continue;
+	}
+	else if (VIM_ISDIGIT(*s))
+	    col = getdigits(&s);
+	else
+	    return e_invarg;
+	color_cols[count++] = col - 1;  /* 1-based to 0-based */
+
+	if (*s == NUL)
+	    break;
+	if (*s != ',')
+	    return e_invarg;
+    }
+
+    vim_free(wp->w_p_cc_cols);
+    if (count == 0)
+	wp->w_p_cc_cols = NULL;
+    else
+    {
+	wp->w_p_cc_cols = (int *)alloc((unsigned)sizeof(int) * (count + 1));
+	if (wp->w_p_cc_cols != NULL)
+	{
+	    /* sort the columns for faster usage on screen redraw inside
+	     * win_line() */
+	    qsort(color_cols, count, sizeof(int), int_cmp);
+
+	    for (i = 0; i < count; ++i)
+		/* skip duplicates */
+		if (j == 0 || wp->w_p_cc_cols[j - 1] != color_cols[i])
+		    wp->w_p_cc_cols[j++] = color_cols[i];
+	    wp->w_p_cc_cols[j] = -1;  /* end marker */
+	}
+    }
+
+    return NULL;  /* no error */
+}
+#endif
+
 /*
  * Handle setting 'listchars' or 'fillchars'.
  * Returns error message, NULL if it's OK.
@@ -8179,6 +8275,28 @@ set_num_option(opt_idx, varp, value, err
     }
 #endif
 
+    else if (pp == &curbuf->b_p_tw)
+    {
+	if (curbuf->b_p_tw < 0)
+	{
+	    errmsg = e_positive;
+	    curbuf->b_p_tw = 0;
+	}
+#ifdef FEAT_SYN_HL
+# ifdef FEAT_WINDOWS
+	{
+	    win_T	*wp;
+	    tabpage_T	*tp;
+
+	    FOR_ALL_TAB_WINDOWS(tp, wp)
+		check_colorcolumn(wp);
+	}
+# else
+	check_colorcolumn(curwin);
+# endif
+#endif
+    }
+
     /*
      * Check the bounds for numeric options here
      */
@@ -8251,11 +8369,6 @@ set_num_option(opt_idx, varp, value, err
 	errmsg = e_positive;
 	curbuf->b_p_ts = 8;
     }
-    if (curbuf->b_p_tw < 0)
-    {
-	errmsg = e_positive;
-	curbuf->b_p_tw = 0;
-    }
     if (p_tm < 0)
     {
 	errmsg = e_positive;
@@ -9341,6 +9454,7 @@ get_varp(p)
 #ifdef FEAT_SYN_HL
 	case PV_CUC:	return (char_u *)&(curwin->w_p_cuc);
 	case PV_CUL:	return (char_u *)&(curwin->w_p_cul);
+	case PV_CC:	return (char_u *)&(curwin->w_p_cc);
 #endif
 #ifdef FEAT_DIFF
 	case PV_DIFF:	return (char_u *)&(curwin->w_p_diff);
@@ -9582,6 +9696,7 @@ copy_winopt(from, to)
 #ifdef FEAT_SYN_HL
     to->wo_cuc = from->wo_cuc;
     to->wo_cul = from->wo_cul;
+    to->wo_cc = vim_strsave(from->wo_cc);
 #endif
 #ifdef FEAT_DIFF
     to->wo_diff = from->wo_diff;
@@ -9636,6 +9751,9 @@ check_winopt(wop)
 #ifdef FEAT_STL_OPT
     check_string_option(&wop->wo_stl);
 #endif
+#ifdef FEAT_SYN_HL
+    check_string_option(&wop->wo_cc);
+#endif
 }
 
 /*
@@ -9660,6 +9778,9 @@ clear_winopt(wop)
 #ifdef FEAT_STL_OPT
     clear_string_option(&wop->wo_stl);
 #endif
+#ifdef FEAT_SYN_HL
+    clear_string_option(&wop->wo_cc);
+#endif
 }
 
 /*
@@ -9682,7 +9803,7 @@ buf_copy_options(buf, flags)
     int		did_isk = FALSE;
 
     /*
-     * Don't do anything of the buffer is invalid.
+     * Don't do anything if the buffer is invalid.
      */
     if (buf == NULL || !buf_valid(buf))
 	return;
--- a/src/option.h
+++ b/src/option.h
@@ -589,6 +589,10 @@ EXTERN int	p_magic;	/* 'magic' */
 EXTERN char_u	*p_mef;		/* 'makeef' */
 EXTERN char_u	*p_mp;		/* 'makeprg' */
 #endif
+#ifdef FEAT_SYN_HL
+EXTERN char_u   *p_cc;		/* 'colorcolumn' */
+EXTERN int      p_cc_cols[256]; /* array for 'colorcolumn' columns */
+#endif
 EXTERN long	p_mat;		/* 'matchtime' */
 #ifdef FEAT_MBYTE
 EXTERN long	p_mco;		/* 'maxcombine' */
@@ -1069,6 +1073,7 @@ enum
 #ifdef FEAT_SYN_HL
     , WV_CUC
     , WV_CUL
+    , WV_CC
 #endif
 #ifdef FEAT_STL_OPT
     , WV_STL
--- a/src/os_macosx.m
+++ b/src/os_macosx.m
@@ -544,75 +544,6 @@ iconv_errno()
 }
 #endif /* MACOS_X_ICONVEMU */
 
-#ifdef USE_MCH_GETTEXT
-
-#define GETTEXT_BUFNUM		64
-#define GETTEXT_BUFSIZE		256
-
-    char *
-mch_gettext(const char *msgid)
-{
-    static char		buf[GETTEXT_BUFNUM][GETTEXT_BUFSIZE];
-    static int		bufnum = 0;
-    const char		*msg = NULL;
-    CFStringRef		strkey = NULL, strmsg = NULL;
-    CFStringEncoding	enc;
-
-    if (!msgid)
-	goto MCH_GETTEXT_FINISH;
-    enc = CFStringGetSystemEncoding();
-    TRACE("mch_gettext(%s)\n", msgid);
-
-    strkey = CFStringCreateWithCString(NULL, msgid, enc);
-    if (!strkey)
-    {
-	TRACE("  Can't create a CFString for msgid.\n");
-	goto MCH_GETTEXT_FINISH;
-    }
-
-    strmsg = CFCopyLocalizedString(strkey, NULL);
-    if (!strmsg)
-    {
-	TRACE("  No localized strings for msgid.\n");
-	goto MCH_GETTEXT_FINISH;
-    }
-
-    msg = CFStringGetCStringPtr(strmsg, enc);
-    if (!msg)
-    {
-	/* This is as backup when CFStringGetCStringPtr was failed */
-	CFStringGetCString(strmsg, buf[bufnum], GETTEXT_BUFSIZE, enc);
-	msg = buf[bufnum];
-	if (++bufnum >= GETTEXT_BUFNUM)
-	    bufnum = 0;
-    }
-    TRACE("  Localized to: %s\n", msg);
-
-MCH_GETTEXT_FINISH:
-    if (strkey)
-	CFRelease(strkey);
-    if (strmsg)
-	CFRelease(strmsg);
-    return (char *)(msg ? msg : msgid);
-}
-
-    char *
-mch_bindtextdomain(const char *domain, const char *dirname)
-{
-    TRACE("mch_bindtextdomain(%s, %s)\n", domain, dirname);
-    return (char*)dirname;
-}
-
-    char *
-mch_textdomain(const char *domain)
-{
-    TRACE("mch_textdomain(%s)\n", domain);
-    return (char*)domain;
-}
-#endif
-
-
-
 #ifdef FEAT_CLIPBOARD
 
     void
--- a/src/proto/option.pro
+++ b/src/proto/option.pro
@@ -19,6 +19,7 @@ void clear_string_option __ARGS((char_u 
 void set_term_option_alloced __ARGS((char_u **p));
 int was_set_insecurely __ARGS((char_u *opt, int opt_flags));
 void set_string_option_direct __ARGS((char_u *name, int opt_idx, char_u *val, int opt_flags, int set_sid));
+char_u *check_colorcolumn __ARGS((win_T *wp));
 char_u *check_stl_option __ARGS((char_u *s));
 int get_option_value __ARGS((char_u *name, long *numval, char_u **stringval, int opt_flags));
 void set_option_value __ARGS((char_u *name, long number, char_u *string, int opt_flags));
--- a/src/screen.c
+++ b/src/screen.c
@@ -2126,6 +2126,23 @@ win_draw_end(wp, c1, c2, row, endrow, hl
     set_empty_rows(wp, row);
 }
 
+#ifdef FEAT_SYN_HL
+static int advance_color_col __ARGS((int vcol, int **color_cols));
+
+/*
+ * Advance **color_cols and return TRUE when there are columns to draw.
+ */
+    static int
+advance_color_col(vcol, color_cols)
+    int	    vcol;
+    int	    **color_cols;
+{
+    while (**color_cols >= 0 && vcol > **color_cols)
+	++*color_cols;
+    return (**color_cols >= 0);
+}
+#endif
+
 #ifdef FEAT_FOLDING
 /*
  * Display one folded line.
@@ -2666,6 +2683,8 @@ win_line(wp, lnum, startrow, endrow, noc
     int		has_syntax = FALSE;	/* this buffer has syntax highl. */
     int		save_did_emsg;
     int		eol_hl_off = 0;		/* 1 if highlighted char after EOL */
+    int		draw_color_col = FALSE;	/* highlight colorcolumn */
+    int		*color_cols = NULL;	/* pointer to according columns array */
 #endif
 #ifdef FEAT_SPELL
     int		has_spell = FALSE;	/* this buffer has spell checking */
@@ -2795,6 +2814,11 @@ win_line(wp, lnum, startrow, endrow, noc
 	    extra_check = TRUE;
 	}
     }
+
+    /* Check for columns to display for 'colorcolumn'. */
+    color_cols = wp->w_p_cc_cols;
+    if (color_cols != NULL)
+	draw_color_col = advance_color_col(vcol, &color_cols);
 #endif
 
 #ifdef FEAT_SPELL
@@ -3073,6 +3097,7 @@ win_line(wp, lnum, startrow, endrow, noc
 #if defined(FEAT_SYN_HL) || defined(FEAT_VIRTUALEDIT) || defined(FEAT_VISUAL)
 	/* When:
 	 * - 'cuc' is set, or
+	 * - 'colorcolumn' is set, or
 	 * - 'virtualedit' is set, or
 	 * - the visual mode is active,
 	 * the end of the line may be before the start of the displayed part.
@@ -3080,6 +3105,7 @@ win_line(wp, lnum, startrow, endrow, noc
 	if (vcol < v && (
 # ifdef FEAT_SYN_HL
 	     wp->w_p_cuc
+	     || draw_color_col
 #  if defined(FEAT_VIRTUALEDIT) || defined(FEAT_VISUAL)
 	     ||
 #  endif
@@ -4641,25 +4667,41 @@ win_line(wp, lnum, startrow, endrow, noc
 		--vcol;
 	    }
 
-	    /* Highlight 'cursorcolumn' past end of the line. */
+	    /* Highlight 'cursorcolumn' & 'colorcolumn' past end of the line. */
 	    if (wp->w_p_wrap)
 		v = wp->w_skipcol;
 	    else
 		v = wp->w_leftcol;
+
 	    /* check if line ends before left margin */
 	    if (vcol < v + col - win_col_off(wp))
-
 		vcol = v + col - win_col_off(wp);
-	    if (wp->w_p_cuc
-		    && (int)wp->w_virtcol >= vcol - eol_hl_off
-		    && (int)wp->w_virtcol < W_WIDTH(wp) * (row - startrow + 1)
+
+	    if (draw_color_col)
+		draw_color_col = advance_color_col(vcol, &color_cols);
+
+	    if (((wp->w_p_cuc
+		      && (int)wp->w_virtcol >= vcol - eol_hl_off
+		      && (int)wp->w_virtcol < W_WIDTH(wp) * (row - startrow + 1)
 									   + v
-		    && lnum != wp->w_cursor.lnum
+		      && lnum != wp->w_cursor.lnum)
+		    || draw_color_col)
 # ifdef FEAT_RIGHTLEFT
 		    && !wp->w_p_rl
 # endif
 		    )
 	    {
+		int	rightmost_vcol = 0;
+		int	i;
+
+		if (wp->w_p_cuc)
+		    rightmost_vcol = wp->w_virtcol;
+		if (draw_color_col)
+		    /* determine rightmost colorcolumn to possibly draw */
+		    for (i = 0; color_cols[i] >= 0; ++i)
+			if (rightmost_vcol < color_cols[i])
+			    rightmost_vcol = color_cols[i];
+
 		while (col < W_WIDTH(wp))
 		{
 		    ScreenLines[off] = ' ';
@@ -4668,12 +4710,19 @@ win_line(wp, lnum, startrow, endrow, noc
 			ScreenLinesUC[off] = 0;
 #endif
 		    ++col;
-		    if (vcol == (long)wp->w_virtcol)
-		    {
-			ScreenAttrs[off] = hl_attr(HLF_CUC);
+		    if (wp->w_p_cuc && vcol == (long)wp->w_virtcol)
+			ScreenAttrs[off++] = hl_attr(HLF_CUC);
+		    else if (draw_color_col && vcol == *color_cols)
+			ScreenAttrs[off++] = hl_attr(HLF_MC);
+		    else
+			ScreenAttrs[off++] = 0;
+
+		    if (vcol >= rightmost_vcol)
 			break;
-		    }
-		    ScreenAttrs[off++] = 0;
+
+		    if (draw_color_col)
+			draw_color_col = advance_color_col(vcol, &color_cols);
+
 		    ++vcol;
 		}
 	    }
@@ -4737,18 +4786,29 @@ win_line(wp, lnum, startrow, endrow, noc
 	}
 
 #ifdef FEAT_SYN_HL
+	/* advance to the next 'colorcolumn' */
+	if (draw_color_col)
+	    draw_color_col = advance_color_col(vcol, &color_cols);
+
 	/* Highlight the cursor column if 'cursorcolumn' is set.  But don't
-	 * highlight the cursor position itself. */
-	if (wp->w_p_cuc && vcol == (long)wp->w_virtcol
-		&& lnum != wp->w_cursor.lnum
-		&& draw_state == WL_LINE
-		&& !lnum_in_visual_area)
-	{
-	    vcol_save_attr = char_attr;
-	    char_attr = hl_combine_attr(char_attr, hl_attr(HLF_CUC));
-	}
-	else
-	    vcol_save_attr = -1;
+	 * highlight the cursor position itself.
+	 * Also highlight the 'colorcolumn' if it is different than
+	 * 'cursorcolumn' */
+	vcol_save_attr = -1;
+	if (draw_state == WL_LINE && !lnum_in_visual_area)
+	{
+	    if (wp->w_p_cuc && vcol == (long)wp->w_virtcol
+						 && lnum != wp->w_cursor.lnum)
+	    {
+		vcol_save_attr = char_attr;
+		char_attr = hl_combine_attr(char_attr, hl_attr(HLF_CUC));
+	    }
+	    else if (draw_color_col && vcol == *color_cols)
+	    {
+		vcol_save_attr = char_attr;
+		char_attr = hl_combine_attr(char_attr, hl_attr(HLF_MC));
+	    }
+	}
 #endif
 
 	/*
--- a/src/structs.h
+++ b/src/structs.h
@@ -202,6 +202,8 @@ typedef struct
 # define w_p_cuc w_onebuf_opt.wo_cuc	/* 'cursorcolumn' */
     int		wo_cul;
 # define w_p_cul w_onebuf_opt.wo_cul	/* 'cursorline' */
+    char_u	*wo_cc;
+# define w_p_cc w_onebuf_opt.wo_cc	/* 'colorcolumn' */
 #endif
 #ifdef FEAT_STL_OPT
     char_u	*wo_stl;
@@ -2010,6 +2012,9 @@ struct window_S
     long_u	w_p_fde_flags;	    /* flags for 'foldexpr' */
     long_u	w_p_fdt_flags;	    /* flags for 'foldtext' */
 #endif
+#ifdef FEAT_SYN_HL
+    int		*w_p_cc_cols;	    /* array of columns to highlight or NULL */
+#endif
 
     /* transform a pointer to a "onebuf" option into a "allbuf" option */
 #define GLOBAL_WO(p)	((char *)p + sizeof(winopt_T))
--- a/src/syntax.c
+++ b/src/syntax.c
@@ -6531,6 +6531,8 @@ static char *(highlight_init_light[]) =
 	     "CursorColumn term=reverse ctermbg=LightGrey guibg=Grey90"),
 	CENT("CursorLine term=underline cterm=underline",
 	     "CursorLine term=underline cterm=underline guibg=Grey90"),
+	CENT("ColorColumn term=reverse ctermbg=LightRed",
+	     "ColorColumn term=reverse ctermbg=LightRed guibg=LightRed"),
 #endif
 #ifdef FEAT_CONCEAL
 	CENT("Conceal ctermbg=DarkGrey ctermfg=LightGrey",
@@ -6615,6 +6617,8 @@ static char *(highlight_init_dark[]) =
 	     "CursorColumn term=reverse ctermbg=DarkGrey guibg=Grey40"),
 	CENT("CursorLine term=underline cterm=underline",
 	     "CursorLine term=underline cterm=underline guibg=Grey40"),
+	CENT("ColorColumn term=reverse ctermbg=DarkRed",
+	     "ColorColumn term=reverse ctermbg=DarkRed guibg=DarkRed"),
 #endif
 #ifdef FEAT_AUTOCMD
 	CENT("MatchParen term=reverse ctermbg=DarkCyan",
--- a/src/vim.h
+++ b/src/vim.h
@@ -1334,6 +1334,7 @@ typedef enum
     , HLF_TPF	    /* tabpage line filler */
     , HLF_CUC	    /* 'cursurcolumn' */
     , HLF_CUL	    /* 'cursurline' */
+    , HLF_MC	    /* 'colorcolumn' */
     , HLF_COUNT	    /* MUST be the last one */
 } hlf_T;
 
@@ -1343,7 +1344,7 @@ typedef enum
 		  'n', 'r', 's', 'S', 'c', 't', 'v', 'V', 'w', 'W', \
 		  'f', 'F', 'A', 'C', 'D', 'T', '-', '>', \
 		  'B', 'P', 'R', 'L', \
-		  '+', '=', 'x', 'X', '*', '#', '_', '!', '.'}
+		  '+', '=', 'x', 'X', '*', '#', '_', '!', '.', 'o'}
 
 /*
  * Boolean constants
--- a/src/window.c
+++ b/src/window.c
@@ -1225,6 +1225,10 @@ win_init(newp, oldp, flags)
 # endif
 
     win_init_some(newp, oldp);
+
+# ifdef FEAT_SYN_HL
+    check_colorcolumn(newp);
+# endif
 }
 
 /*
@@ -4413,6 +4417,7 @@ win_free(wp, tp)
 
 #ifdef FEAT_SYN_HL
     reset_synblock(wp);  /* free independent synblock */
+    vim_free(wp->w_p_cc_cols);
 #endif
 
 #ifdef FEAT_AUTOCMD