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'.
diff --git a/src/edit.c b/src/edit.c
index 87fd569..3370a28 100644
--- a/src/edit.c
+++ b/src/edit.c
@@ -377,6 +377,12 @@
     }
 #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 @@
 		    ||
 # 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 @@
 		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 @@
 	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)
+	if ((conceal_update_lines
+		&& (conceal_old_cursor_line != conceal_new_cursor_line
+		    || conceal_cursor_line(curwin)))
+		|| need_cursor_line_redraw)
 	{
-	    update_single_line(curwin, conceal_old_cursor_line);
-	    update_single_line(curwin, conceal_new_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 == 0
+			   ? curwin->w_cursor.lnum : conceal_new_cursor_line);
 	    curwin->w_valid &= ~VALID_CROW;
 	}
 # endif
diff --git a/src/feature.h b/src/feature.h
index 68ffe0c..3f25898 100644
--- 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
diff --git a/src/globals.h b/src/globals.h
index bb5f3cf..93f1514 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -1343,6 +1343,11 @@
 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
diff --git a/src/gui.c b/src/gui.c
index c899323..5aece03 100644
--- a/src/gui.c
+++ b/src/gui.c
@@ -4922,7 +4922,7 @@
 		||
 # 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 @@
 	    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 @@
     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;
     }
diff --git a/src/main.c b/src/main.c
index 029b64c..d94b32a 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1098,7 +1098,7 @@
 			||
 # 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 @@
 							       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 @@
 
 # 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;
 	    }
diff --git a/src/normal.c b/src/normal.c
index 4d2f4c6..d9e9588 100644
--- a/src/normal.c
+++ b/src/normal.c
@@ -7623,6 +7623,11 @@
 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 @@
 #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 @@
 		    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. */
diff --git a/src/option.c b/src/option.c
index f16c4ba..8d7f09a 100644
--- 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 @@
 			    {(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 @@
 	    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 @@
 	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 @@
 	    ml_open_files();
     }
 #ifdef FEAT_CONCEAL
-    else if (pp == &curwin->w_p_conc)
+    else if (pp == &curwin->w_p_cole)
     {
-	if (curwin->w_p_conc < 0)
+	if (curwin->w_p_cole < 0)
 	{
 	    errmsg = e_positive;
-	    curwin->w_p_conc = 0;
+	    curwin->w_p_cole = 0;
 	}
-	else if (curwin->w_p_conc > 3)
+	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 @@
 	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 @@
 #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 @@
 #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 @@
 #ifdef FEAT_SYN_HL
     clear_string_option(&wop->wo_cc);
 #endif
+#ifdef FEAT_CONCEAL
+    clear_string_option(&wop->wo_cocu);
+#endif
 }
 
 /*
diff --git a/src/option.h b/src/option.h
index 817e337..2164467 100644
--- 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 @@
     , WV_ARAB
 #endif
 #ifdef FEAT_CONCEAL
-    , WV_CONCEAL
+    , WV_COCU
+    , WV_COLE
 #endif
 #ifdef FEAT_CURSORBIND
     , WV_CRBIND
diff --git a/src/proto/screen.pro b/src/proto/screen.pro
index 05114d0..efaf4c6 100644
--- a/src/proto/screen.pro
+++ b/src/proto/screen.pro
@@ -8,6 +8,8 @@
 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));
diff --git a/src/screen.c b/src/screen.c
index 71eb16f..f9183e1 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -587,6 +587,44 @@
 }
 
 #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 @@
 	}
 # endif
     }
+    need_cursor_line_redraw = FALSE;
 }
 #endif
 
@@ -2781,7 +2820,8 @@
     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 @@
 	    }
 
 #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 @@
 #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 @@
 	    }
 	}
 #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;
diff --git a/src/structs.h b/src/structs.h
index 42b1d2a..7b8acee 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -216,8 +216,10 @@
     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;
diff --git a/src/ui.c b/src/ui.c
index cabee59..1337807 100644
--- a/src/ui.c
+++ b/src/ui.c
@@ -1912,6 +1912,10 @@
 # ifdef MCH_CURSOR_SHAPE
     mch_update_cursor();
 # endif
+
+# ifdef FEAT_CONCEAL
+    conceal_check_cursur_line_redraw();
+# endif
 }
 #endif
 
diff --git a/src/undo.c b/src/undo.c
index 77f57bc..58b55ba 100644
--- a/src/undo.c
+++ b/src/undo.c
@@ -2711,7 +2711,7 @@
 
 	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);
 	}
     }