changeset 2378:85b7dc8da5eb vim73

Add the 'concealcursor' option to decide when the cursor line is to be concealed or not. Rename 'conc' to 'cole' as the short name for 'conceallevel'.
author Bram Moolenaar <bram@vim.org>
date Fri, 23 Jul 2010 22:10:27 +0200
parents 878562053ba3
children b67b0b5a93d3
files runtime/doc/options.txt runtime/doc/quickref.txt runtime/doc/syntax.txt runtime/doc/tags runtime/doc/todo.txt runtime/ftplugin/help.vim src/edit.c src/feature.h src/globals.h src/gui.c src/main.c src/normal.c src/option.c src/option.h src/proto/screen.pro src/screen.c src/structs.h src/ui.c src/undo.c
diffstat 19 files changed, 212 insertions(+), 58 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -1,4 +1,4 @@
-*options.txt*	For Vim version 7.3b.  Last change: 2010 Jul 20
+*options.txt*	For Vim version 7.3b.  Last change: 2010 Jul 23
 
 
 		  VIM REFERENCE MANUAL	  by Bram Moolenaar
@@ -1707,7 +1707,26 @@ A jump table for the options with a shor
 		    combination with "menu" or "menuone".
 
 
-'conceallevel' 'conc'		*'conceallevel'* *'conc'*
+						*'concealcursor'* *'cocu'*
+'concealcursor' 'cocu'	string (default: "")
+			local to window
+			{not in Vi}
+			{not available when compiled without the |+conceal|
+			feature}
+	Sets the modes in which text in the cursor line can also be concealed.
+	When the current mode is listed then concealing happens just like in
+	other lines.
+	  n		Normal mode
+	  v		Visual mode
+	  i		Insert mode
+
+	A useful value is "n".  This is used in help files.  So long as you
+	are moving around text is concealed, but when starting to insert text
+	or selecting a Visual area the concealed text is displayed, so that
+	you can see what you are doing.
+
+
+'conceallevel' 'cole'		*'conceallevel'* *'cole'*
 			number (default 0)
 			local to window
 			{not in Vi}
@@ -1727,7 +1746,8 @@ A jump table for the options with a shor
 	3		Concealed text is completely hidden.
 
 	Note: in the cursor line concealed text is not hidden, so that you can
-	edit and copy the text.
+	edit and copy the text.  This can be changed with the 'concealcursor'
+	option.
 
 				*'confirm'* *'cf'* *'noconfirm'* *'nocf'*
 'confirm' 'cf'		boolean (default off)
--- a/runtime/doc/quickref.txt
+++ b/runtime/doc/quickref.txt
@@ -1,4 +1,4 @@
-*quickref.txt*  For Vim version 7.3b.  Last change: 2009 Jan 22
+*quickref.txt*  For Vim version 7.3b.  Last change: 2010 Jul 22
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -647,7 +647,8 @@ Short explanation of each option:		*opti
 'complete'	  'cpt'     specify how Insert mode completion works
 'completefunc'	  'cfu'     function to be used for Insert mode completion
 'completeopt'	  'cot'     options for Insert mode completion
-'conceallevel'	  'conc'    whether concealable text is shown or hidden 
+'concealcursor'	  'cocu'    whether concealable text is hidden in cursor line
+'conceallevel'	  'cole'    whether concealable text is shown or hidden 
 'confirm'	  'cf'	    ask what to do about unsaved/read-only files
 'conskey'	  'consk'   get keys directly from console (MS-DOS only)
 'copyindent'	  'ci'	    make 'autoindent' use existing indent structure
--- a/runtime/doc/syntax.txt
+++ b/runtime/doc/syntax.txt
@@ -1,4 +1,4 @@
-*syntax.txt*	For Vim version 7.3b.  Last change: 2010 Jul 21
+*syntax.txt*	For Vim version 7.3b.  Last change: 2010 Jul 23
 
 
 		  VIM REFERENCE MANUAL	  by Bram Moolenaar
@@ -3149,9 +3149,9 @@ conceal						*conceal* *:syn-conceal*
 
 When the "conceal" argument is given, the item is marked as concealable.
 Whether or not it is actually concealed depends on the value of the
-'conceallevel' option.  If 'modifiable' option is on, concealable items
-in the current line are always displayed unconcealed to be able to edit
-the line.
+'conceallevel' option.  The 'concealcursor' option is used to decide whether
+concealable items in the current line are displayed unconcealed to be able to
+edit the line.
 
 concealends						*:syn-concealends*
 
--- a/runtime/doc/tags
+++ b/runtime/doc/tags
@@ -127,6 +127,8 @@
 'cmp'	options.txt	/*'cmp'*
 'cms'	options.txt	/*'cms'*
 'co'	options.txt	/*'co'*
+'cocu'	options.txt	/*'cocu'*
+'cole'	options.txt	/*'cole'*
 'colorcolumn'	options.txt	/*'colorcolumn'*
 'columns'	options.txt	/*'columns'*
 'com'	options.txt	/*'com'*
@@ -136,7 +138,7 @@
 'complete'	options.txt	/*'complete'*
 'completefunc'	options.txt	/*'completefunc'*
 'completeopt'	options.txt	/*'completeopt'*
-'conc'	options.txt	/*'conc'*
+'concealcursor'	options.txt	/*'concealcursor'*
 'conceallevel'	options.txt	/*'conceallevel'*
 'confirm'	options.txt	/*'confirm'*
 'consk'	options.txt	/*'consk'*
--- a/runtime/doc/todo.txt
+++ b/runtime/doc/todo.txt
@@ -1,4 +1,4 @@
-*todo.txt*      For Vim version 7.3b.  Last change: 2010 Jul 22
+*todo.txt*      For Vim version 7.3b.  Last change: 2010 Jul 23
 
 
 		  VIM REFERENCE MANUAL	  by Bram Moolenaar
@@ -30,11 +30,16 @@ be worked on, but only if you sponsor Vi
 							*known-bugs*
 -------------------- Known bugs and current work -----------------------
 
-Conceal in help files doesn't work nice.  How about adding an 'concealcursor'
-option, when on:
-- cursorline is concealed.
-- line is redrawn on every movement
-- display function corrects cursor position.
+a |test| and a |test| and a |test|.
+Conceal in help files doesn't work nice.  How about adding a 'concealcursor'
+option:
+-> implemented, but column isn't quite right just after concealed character.
+- Don't conceal in Insert and Visual mode?  Or make 'concealcursor' a string
+  option with mode characters.
+- Check position in wrapped line.
+
+Trick with syntax ID works, but it's not nice.  Can we give a sequence nr to
+syntax item matches?  At least the ones with a replacement char.
 
 Include patch for horizontal scoll wheel? (Bjorn Winckler, 2010 Jul 20)
 Additional patch Jul 21.
@@ -272,6 +277,10 @@ Win32: use different args for SearchPath
 Win32: completion of file name ":e c:\!test" results in ":e c:\\!test", which
 does not work. (Nieko Maatjes, 2009 Jan 8, Ingo Karkat, 2009 Jan 22)
 
+opening/closing window causes other window with 'winfixheight' to change
+height.  Also happens when there is another window in the frame, if it's not
+very high. (Yegappan Lakshmanan, 2010 Jul 22)
+
 Directory wrong in session file, caused by ":lcd" in BufEnter autocommand.
 (Felix Kater, 2009 Mar 3)
 
--- a/runtime/ftplugin/help.vim
+++ b/runtime/ftplugin/help.vim
@@ -11,9 +11,9 @@ let b:did_ftplugin = 1
 let s:cpo_save = &cpo
 set cpo&vim
 
-let b:undo_ftplugin = "setl fo< tw< conc<"
+let b:undo_ftplugin = "setl fo< tw< cole< cocu<"
 
-setlocal formatoptions+=tcroql textwidth=78 conc=2
+setlocal formatoptions+=tcroql textwidth=78 cole=2 cocu=n
 
 let &cpo = s:cpo_save
 unlet s:cpo_save
--- a/src/edit.c
+++ b/src/edit.c
@@ -377,6 +377,12 @@ edit(cmdchar, startln, count)
     }
 #endif
 
+#ifdef FEAT_CONCEAL
+    /* Check if the cursor line needs redrawing before changing State.  If
+     * 'concealcursor' is "n" it needs to be redrawn without concealing. */
+    conceal_check_cursur_line_redraw();
+#endif
+
 #ifdef FEAT_MOUSE
     /*
      * When doing a paste with the middle mouse button, Insstart is set to
@@ -1476,7 +1482,7 @@ ins_redraw(ready)
 		    ||
 # endif
 # ifdef FEAT_CONCEAL
-		    curwin->w_p_conc > 0
+		    curwin->w_p_cole > 0
 # endif
 		    )
 	    && !equalpos(last_cursormoved, curwin->w_cursor)
@@ -1498,7 +1504,7 @@ ins_redraw(ready)
 		apply_autocmds(EVENT_CURSORMOVEDI, NULL, NULL, FALSE, curbuf);
 # endif
 # ifdef FEAT_CONCEAL
-	    if (curwin->w_p_conc > 0)
+	    if (curwin->w_p_cole > 0)
 	    {
 		conceal_old_cursor_line = last_cursormoved.lnum;
 		conceal_new_cursor_line = curwin->w_cursor.lnum;
@@ -1513,11 +1519,15 @@ ins_redraw(ready)
 	else if (clear_cmdline || redraw_cmdline)
 	    showmode();		/* clear cmdline and show mode */
 # if defined(FEAT_CONCEAL)
-	if (conceal_update_lines
-		&& conceal_old_cursor_line != conceal_new_cursor_line)
-	{
-	    update_single_line(curwin, conceal_old_cursor_line);
-	    update_single_line(curwin, conceal_new_cursor_line);
+	if ((conceal_update_lines
+		&& (conceal_old_cursor_line != conceal_new_cursor_line
+		    || conceal_cursor_line(curwin)))
+		|| need_cursor_line_redraw)
+	{
+	    if (conceal_old_cursor_line != conceal_new_cursor_line)
+		update_single_line(curwin, conceal_old_cursor_line);
+	    update_single_line(curwin, conceal_new_cursor_line == 0
+			   ? curwin->w_cursor.lnum : conceal_new_cursor_line);
 	    curwin->w_valid &= ~VALID_CROW;
 	}
 # endif
--- a/src/feature.h
+++ b/src/feature.h
@@ -1163,8 +1163,11 @@
 #endif
 
 /* GUI and some consoles can change the shape of the cursor.  The code is also
- * needed for the 'mouseshape' option. */
-#if defined(FEAT_GUI) || defined(MCH_CURSOR_SHAPE) || defined(FEAT_MOUSESHAPE) \
+ * needed for the 'mouseshape' and 'concealcursor' options. */
+#if defined(FEAT_GUI) \
+	    || defined(MCH_CURSOR_SHAPE) \
+	    || defined(FEAT_MOUSESHAPE) \
+	    || defined(FEAT_CONCEAL) \
 	    || (defined(UNIX) && defined(FEAT_NORMAL))
 # define CURSOR_SHAPE
 #endif
--- a/src/globals.h
+++ b/src/globals.h
@@ -1343,6 +1343,11 @@ EXTERN disptick_T	display_tick INIT(= 0)
 EXTERN linenr_T		spell_redraw_lnum INIT(= 0);
 #endif
 
+#ifdef FEAT_CONCEAL
+/* Set when the cursor line needs to be redrawn. */
+EXTERN int		need_cursor_line_redraw INIT(= FALSE);
+#endif
+
 #ifdef ALT_X_INPUT
 /* we need to be able to go into the dispatch loop while processing a command
  * received via alternate input. However, we don't want to process another
--- a/src/gui.c
+++ b/src/gui.c
@@ -4922,7 +4922,7 @@ gui_update_screen()
 		||
 # endif
 # ifdef FEAT_CONCEAL
-		curwin->w_p_conc > 0
+		curwin->w_p_cole > 0
 # endif
 		)
 		     && !equalpos(last_cursormoved, curwin->w_cursor))
@@ -4932,7 +4932,7 @@ gui_update_screen()
 	    apply_autocmds(EVENT_CURSORMOVED, NULL, NULL, FALSE, curbuf);
 # endif
 # ifdef FEAT_CONCEAL
-	if (curwin->w_p_conc > 0)
+	if (curwin->w_p_cole > 0)
 	{
 	    conceal_old_cursor_line = last_cursormoved.lnum;
 	    conceal_new_cursor_line = curwin->w_cursor.lnum;
@@ -4947,9 +4947,12 @@ gui_update_screen()
     setcursor();
 # if defined(FEAT_CONCEAL)
     if (conceal_update_lines
-	    && conceal_old_cursor_line != conceal_new_cursor_line)
+	    && (conceal_old_cursor_line != conceal_new_cursor_line
+		|| conceal_cursor_line(curwin)
+		|| need_cursor_line_redraw))
     {
-	update_single_line(curwin, conceal_old_cursor_line);
+	if (conceal_old_cursor_line != conceal_new_cursor_line)
+	    update_single_line(curwin, conceal_old_cursor_line);
 	update_single_line(curwin, conceal_new_cursor_line);
 	curwin->w_valid &= ~VALID_CROW;
     }
--- a/src/main.c
+++ b/src/main.c
@@ -1098,7 +1098,7 @@ main_loop(cmdwin, noexmode)
 			||
 # endif
 # ifdef FEAT_CONCEAL
-			curwin->w_p_conc > 0
+			curwin->w_p_cole > 0
 # endif
 			)
 		 && !equalpos(last_cursormoved, curwin->w_cursor))
@@ -1109,7 +1109,7 @@ main_loop(cmdwin, noexmode)
 							       FALSE, curbuf);
 # endif
 # ifdef FEAT_CONCEAL
-		if (curwin->w_p_conc > 0)
+		if (curwin->w_p_cole > 0)
 		{
 		    conceal_old_cursor_line = last_cursormoved.lnum;
 		    conceal_new_cursor_line = curwin->w_cursor.lnum;
@@ -1197,9 +1197,12 @@ main_loop(cmdwin, noexmode)
 
 # if defined(FEAT_CONCEAL)
 	    if (conceal_update_lines
-		    && conceal_old_cursor_line != conceal_new_cursor_line)
+		    && (conceal_old_cursor_line != conceal_new_cursor_line
+			|| conceal_cursor_line(curwin)
+			|| need_cursor_line_redraw))
 	    {
-		update_single_line(curwin, conceal_old_cursor_line);
+		if (conceal_old_cursor_line != conceal_new_cursor_line)
+		    update_single_line(curwin, conceal_old_cursor_line);
 		update_single_line(curwin, conceal_new_cursor_line);
 		curwin->w_valid &= ~VALID_CROW;
 	    }
--- a/src/normal.c
+++ b/src/normal.c
@@ -7623,6 +7623,11 @@ may_start_select(c)
 n_start_visual_mode(c)
     int		c;
 {
+#ifdef FEAT_CONCEAL
+    /* Check for redraw before changing the state. */
+    conceal_check_cursur_line_redraw();
+#endif
+
     VIsual_mode = c;
     VIsual_active = TRUE;
     VIsual_reselect = TRUE;
@@ -7642,6 +7647,11 @@ n_start_visual_mode(c)
 #ifdef FEAT_MOUSE
     setmouse();
 #endif
+#ifdef FEAT_CONCEAL
+    /* Check for redraw after changing the state. */
+    conceal_check_cursur_line_redraw();
+#endif
+
     if (p_smd && msg_silent == 0)
 	redraw_cmdline = TRUE;	/* show visual mode later */
 #ifdef FEAT_CLIPBOARD
@@ -8296,7 +8306,7 @@ n_opencmd(cap)
 		    0, 0))
 	{
 #ifdef FEAT_CONCEAL
-	    if (curwin->w_p_conc > 0 && oldline != curwin->w_cursor.lnum)
+	    if (curwin->w_p_cole > 0 && oldline != curwin->w_cursor.lnum)
 		update_single_line(curwin, oldline);
 #endif
 	    /* When '#' is in 'cpoptions' ignore the count. */
--- a/src/option.c
+++ b/src/option.c
@@ -248,7 +248,8 @@
 # define PV_CRBIND	OPT_WIN(WV_CRBIND)
 #endif
 #ifdef FEAT_CONCEAL
-# define PV_CONCEAL	OPT_WIN(WV_CONCEAL)
+# define PV_COCU	OPT_WIN(WV_COCU)
+# define PV_COLE	OPT_WIN(WV_COLE)
 #endif
 
 /* WV_ and BV_ values get typecasted to this for the "indir" field */
@@ -816,9 +817,18 @@ static struct vimoption
 			    {(char_u *)0L, (char_u *)0L}
 #endif
 			    SCRIPTID_INIT},
-    {"conceallevel","conc", P_NUM|P_RWIN|P_VI_DEF,
+    {"concealcursor","cocu", P_STRING|P_ALLOCED|P_RWIN|P_VI_DEF,
 #ifdef FEAT_CONCEAL
-			    (char_u *)VAR_WIN, PV_CONCEAL,
+			    (char_u *)VAR_WIN, PV_COCU,
+			    {(char_u *)"", (char_u *)NULL}
+#else
+			    (char_u *)NULL, PV_NONE,
+			    {(char_u *)NULL, (char_u *)0L}
+#endif
+			    SCRIPTID_INIT},
+    {"conceallevel","cole", P_NUM|P_RWIN|P_VI_DEF,
+#ifdef FEAT_CONCEAL
+			    (char_u *)VAR_WIN, PV_COLE,
 #else
 			    (char_u *)NULL, PV_NONE,
 #endif
@@ -6848,6 +6858,10 @@ did_set_string_option(opt_idx, varp, new
 	    p = (char_u *)CPO_ALL;
 	else if (varp == &(curbuf->b_p_fo))
 	    p = (char_u *)FO_ALL;
+#ifdef FEAT_CONCEAL
+	else if (varp == &curwin->w_p_cocu)
+	    p = (char_u *)COCU_ALL;
+#endif
 	else if (varp == &p_mouse)
 	{
 #ifdef FEAT_MOUSE
@@ -7505,7 +7519,7 @@ set_bool_option(opt_idx, varp, value, op
 	redraw_titles();
 # endif
 # ifdef FEAT_CONCEAL
-	if (curwin->w_p_conc > 0)
+	if (curwin->w_p_cole > 0)
 	    update_single_line(curwin, curwin->w_cursor.lnum);
 # endif
     }
@@ -8273,17 +8287,17 @@ set_num_option(opt_idx, varp, value, err
 	    ml_open_files();
     }
 #ifdef FEAT_CONCEAL
-    else if (pp == &curwin->w_p_conc)
-    {
-	if (curwin->w_p_conc < 0)
+    else if (pp == &curwin->w_p_cole)
+    {
+	if (curwin->w_p_cole < 0)
 	{
 	    errmsg = e_positive;
-	    curwin->w_p_conc = 0;
-	}
-	else if (curwin->w_p_conc > 3)
+	    curwin->w_p_cole = 0;
+	}
+	else if (curwin->w_p_cole > 3)
 	{
 	    errmsg = e_invarg;
-	    curwin->w_p_conc = 3;
+	    curwin->w_p_cole = 3;
 	}
     }
 #endif
@@ -9554,7 +9568,8 @@ get_varp(p)
 	case PV_CRBIND: return (char_u *)&(curwin->w_p_crb);
 #endif
 #ifdef FEAT_CONCEAL
-	case PV_CONCEAL:    return (char_u *)&(curwin->w_p_conc);
+	case PV_COCU:    return (char_u *)&(curwin->w_p_cocu);
+	case PV_COLE:    return (char_u *)&(curwin->w_p_cole);
 #endif
 
 	case PV_AI:	return (char_u *)&(curbuf->b_p_ai);
@@ -9749,6 +9764,9 @@ copy_winopt(from, to)
 #ifdef FEAT_DIFF
     to->wo_diff = from->wo_diff;
 #endif
+#ifdef FEAT_CONCEAL
+    to->wo_cocu = vim_strsave(from->wo_cocu);
+#endif
 #ifdef FEAT_FOLDING
     to->wo_fdc = from->wo_fdc;
     to->wo_fen = from->wo_fen;
@@ -9802,6 +9820,9 @@ check_winopt(wop)
 #ifdef FEAT_SYN_HL
     check_string_option(&wop->wo_cc);
 #endif
+#ifdef FEAT_CONCEAL
+    check_string_option(&wop->wo_cocu);
+#endif
 }
 
 /*
@@ -9829,6 +9850,9 @@ clear_winopt(wop)
 #ifdef FEAT_SYN_HL
     clear_string_option(&wop->wo_cc);
 #endif
+#ifdef FEAT_CONCEAL
+    clear_string_option(&wop->wo_cocu);
+#endif
 }
 
 /*
--- a/src/option.h
+++ b/src/option.h
@@ -189,6 +189,8 @@
 #define MOUSE_NONE	' '		/* don't use Visual selection */
 #define MOUSE_NONEF	'x'		/* forced modeless selection */
 
+#define COCU_ALL	"nvi"		/* flags for 'concealcursor' */
+
 /* characters for p_shm option: */
 #define SHM_RO		'r'		/* readonly */
 #define SHM_MOD		'm'		/* modified */
@@ -1029,7 +1031,8 @@ enum
     , WV_ARAB
 #endif
 #ifdef FEAT_CONCEAL
-    , WV_CONCEAL
+    , WV_COCU
+    , WV_COLE
 #endif
 #ifdef FEAT_CURSORBIND
     , WV_CRBIND
--- a/src/proto/screen.pro
+++ b/src/proto/screen.pro
@@ -8,6 +8,8 @@ void redraw_buf_later __ARGS((buf_T *buf
 void redrawWinline __ARGS((linenr_T lnum, int invalid));
 void update_curbuf __ARGS((int type));
 void update_screen __ARGS((int type));
+int conceal_cursor_line __ARGS((win_T *wp));
+void conceal_check_cursur_line_redraw __ARGS((void));
 void update_single_line __ARGS((win_T *wp, linenr_T lnum));
 void update_debug_sign __ARGS((buf_T *buf, linenr_T lnum));
 void updateWindow __ARGS((win_T *wp));
--- a/src/screen.c
+++ b/src/screen.c
@@ -587,6 +587,44 @@ update_screen(type)
 }
 
 #if defined(FEAT_CONCEAL) || defined(PROTO)
+/*
+ * Return TRUE if the cursor line in window "wp" may be concealed, according
+ * to the 'concealcursor' option.
+ */
+    int
+conceal_cursor_line(wp)
+    win_T	*wp;
+{
+    int		c;
+
+    if (*wp->w_p_cocu == NUL)
+	return FALSE;
+    if (get_real_state() & VISUAL)
+	c = 'v';
+    else if (State & INSERT)
+	c = 'i';
+    else if (State & NORMAL)
+	c = 'n';
+    else
+	return FALSE;
+    return vim_strchr(wp->w_p_cocu, c) != NULL;
+}
+
+/*
+ * Check if the cursor line needs to be redrawn because of 'concealcursor'.
+ */
+    void
+conceal_check_cursur_line_redraw()
+{
+    if (curwin->w_p_cole > 0 && conceal_cursor_line(curwin))
+    {
+	need_cursor_line_redraw = TRUE;
+	/* Need to recompute cursor column, e.g., when starting Visual mode
+	 * without concealing. */
+	curs_columns(TRUE);
+    }
+}
+
     void
 update_single_line(wp, lnum)
     win_T	*wp;
@@ -632,6 +670,7 @@ update_single_line(wp, lnum)
 	}
 # endif
     }
+    need_cursor_line_redraw = FALSE;
 }
 #endif
 
@@ -2781,7 +2820,8 @@ win_line(wp, lnum, startrow, endrow, noc
     int		is_concealing	= FALSE;
     int		boguscols	= 0;	/* nonexistent columns added to force
 					   wrapping */
-    int		vcol_off = 0;		/* offset for concealed characters */
+    int		vcol_off        = 0;	/* offset for concealed characters */
+    int		did_wcol	= FALSE;
 # define VCOL_HLC (vcol - vcol_off)
 #else
 # define VCOL_HLC (vcol)
@@ -4381,14 +4421,15 @@ win_line(wp, lnum, startrow, endrow, noc
 	    }
 
 #ifdef FEAT_CONCEAL
-	    if (   wp->w_p_conc > 0
-		&& (lnum != wp->w_cursor.lnum || curwin != wp)
+	    if (   wp->w_p_cole > 0
+		&& (wp != curwin || lnum != wp->w_cursor.lnum ||
+						      conceal_cursor_line(wp))
 		&& (syntax_flags & HL_CONCEAL) != 0)
 	    {
 		char_attr = conceal_attr;
 		if (prev_syntax_id != syntax_id
-			&& (syn_get_sub_char() != NUL || wp->w_p_conc == 1)
-			&& wp->w_p_conc != 3)
+			&& (syn_get_sub_char() != NUL || wp->w_p_cole == 1)
+			&& wp->w_p_cole != 3)
 		{
 		    /* First time at this concealed item: display one
 		     * character. */
@@ -4447,6 +4488,18 @@ win_line(wp, lnum, startrow, endrow, noc
 #endif /* FEAT_CONCEAL */
 	}
 
+#ifdef FEAT_CONCEAL
+	/* In the cursor line and we may be concealing characters: correct
+	 * the cursor column when we reach its position. */
+	if (!did_wcol && wp == curwin && lnum == wp->w_cursor.lnum
+		&& conceal_cursor_line(wp)
+		&& (int)wp->w_virtcol <= vcol + n_skip)
+	{
+	    wp->w_wcol = col - boguscols;
+	    did_wcol = TRUE;
+	}
+#endif
+
 	/* Don't override visual selection highlighting. */
 	if (n_attr > 0
 		&& draw_state == WL_LINE
@@ -4913,7 +4966,7 @@ win_line(wp, lnum, startrow, endrow, noc
 	    }
 	}
 #ifdef FEAT_CONCEAL
-	else if (wp->w_p_conc > 0 && is_concealing)
+	else if (wp->w_p_cole > 0 && is_concealing)
 	{
 	    --n_skip;
 	    ++vcol_off;
--- a/src/structs.h
+++ b/src/structs.h
@@ -216,8 +216,10 @@ typedef struct
     int		wo_wrap;
 #define w_p_wrap w_onebuf_opt.wo_wrap	/* 'wrap' */
 #ifdef FEAT_CONCEAL
-    long	wo_conc;		/* 'conceal' */
-# define w_p_conc w_onebuf_opt.wo_conc
+    char_u	*wo_cocu;		/* 'concealcursor' */
+# define w_p_cocu w_onebuf_opt.wo_cocu
+    long	wo_cole;		/* 'conceallevel' */
+# define w_p_cole w_onebuf_opt.wo_cole
 #endif
 #ifdef FEAT_CURSORBIND
     int		wo_crb;
--- a/src/ui.c
+++ b/src/ui.c
@@ -1912,6 +1912,10 @@ ui_cursor_shape()
 # ifdef MCH_CURSOR_SHAPE
     mch_update_cursor();
 # endif
+
+# ifdef FEAT_CONCEAL
+    conceal_check_cursur_line_redraw();
+# endif
 }
 #endif
 
--- a/src/undo.c
+++ b/src/undo.c
@@ -2711,7 +2711,7 @@ u_undo_end(did_undo, absolute)
 
 	FOR_ALL_WINDOWS(wp)
 	{
-	    if (wp->w_buffer == curbuf && wp->w_p_conc > 0)
+	    if (wp->w_buffer == curbuf && wp->w_p_cole > 0)
 		redraw_win_later(wp, NOT_VALID);
 	}
     }