On Wednesday, November 14, 2018 at 10:23:52 PM UTC+1, Tom M wrote:
> 
> Hi,
> 
> I propose the following patch (please see the attachment) to fix issues of 
> John and Tony. It ads handling of 'showbreak' and 'linebreak' in visual block 
> operations.
> 
> Tom

Oooops, wrong attachment. Please see the correct one.
Sorry for the noise.

Tom

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to vim_dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
>From ca2062628e4ff4fe8c6a51812fb8b7c054a87b3a Mon Sep 17 00:00:00 2001
From: tom <tom@debian9>
Date: Wed, 14 Nov 2018 22:54:06 +0100
Subject: [PATCH] support showbreak and linebreak in visual block operations

---
 src/buffer.c          |  2 +-
 src/charset.c         | 78 +++++++++++++++++++++++++++++++++++++++------
 src/edit.c            | 14 ++++-----
 src/evalfunc.c        |  2 +-
 src/ex_cmds.c         |  4 +--
 src/mbyte.c           |  2 +-
 src/misc1.c           | 22 ++++++-------
 src/misc2.c           | 10 +++---
 src/move.c            |  4 +--
 src/normal.c          | 87 +++++++++++++++++++++++++++++++++++++--------------
 src/ops.c             | 45 +++++++++++++++++++++-----
 src/proto/charset.pro |  6 ++--
 src/regexp.c          |  4 +--
 src/screen.c          | 14 ++++-----
 src/search.c          |  2 +-
 src/vim.h             |  2 +-
 16 files changed, 214 insertions(+), 84 deletions(-)

diff --git a/src/buffer.c b/src/buffer.c
index 8e892dadf..574fc5efe 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -4289,7 +4289,7 @@ build_stl_str_hl(
 	    if (wp->w_p_list && lcs_tab1 == NUL)
 	    {
 		wp->w_p_list = FALSE;
-		getvcol(wp, &wp->w_cursor, NULL, &virtcol, NULL);
+		getvcol(wp, &wp->w_cursor, NULL, &virtcol, NULL, NULL);
 		wp->w_p_list = TRUE;
 	    }
 	    ++virtcol;
diff --git a/src/charset.c b/src/charset.c
index 028095453..be1861c17 100644
--- a/src/charset.c
+++ b/src/charset.c
@@ -1276,6 +1276,9 @@ in_win_border(win_T *wp, colnr_T vcol)
  *  start: on the first position of this character (TAB, ctrl)
  * cursor: where the cursor is on this character (first char, except for TAB)
  *    end: on the last position of this character (TAB, ctrl)
+ * If "headp" not NULL, set *headp to the size of what we add for 'showbreak'
+ * string at start of line.  Warning: *headp is only set if it's a non-zero
+ * value, init to 0 before calling.
  *
  * This is used very often, keep it fast!
  */
@@ -1285,7 +1288,8 @@ getvcol(
     pos_T	*pos,
     colnr_T	*start,
     colnr_T	*cursor,
-    colnr_T	*end)
+    colnr_T	*end,
+    int		*headp UNUSED)
 {
     colnr_T	vcol;
     char_u	*ptr;		/* points to current char */
@@ -1423,6 +1427,8 @@ getvcol(
 	else
 	    *cursor = vcol + head;	    /* cursor at start */
     }
+    if (headp != NULL)
+	*headp = head;
 }
 
 /*
@@ -1437,10 +1443,10 @@ getvcol_nolist(pos_T *posp)
     curwin->w_p_list = FALSE;
 #ifdef FEAT_VIRTUALEDIT
     if (posp->coladd)
-	getvvcol(curwin, posp, NULL, &vcol, NULL);
+	getvvcol(curwin, posp, NULL, &vcol, NULL, NULL);
     else
 #endif
-	getvcol(curwin, posp, NULL, &vcol, NULL);
+	getvcol(curwin, posp, NULL, &vcol, NULL, NULL);
     curwin->w_p_list = list_save;
     return vcol;
 }
@@ -1455,7 +1461,8 @@ getvvcol(
     pos_T	*pos,
     colnr_T	*start,
     colnr_T	*cursor,
-    colnr_T	*end)
+    colnr_T	*end,
+    int		*headp)
 {
     colnr_T	col;
     colnr_T	coladd;
@@ -1467,7 +1474,7 @@ getvvcol(
     if (virtual_active())
     {
 	/* For virtual mode, only want one value */
-	getvcol(wp, pos, &col, NULL, NULL);
+	getvcol(wp, pos, &col, NULL, NULL, headp);
 
 	coladd = pos->coladd;
 	endadd = 0;
@@ -1497,11 +1504,62 @@ getvvcol(
 	    *end = col + endadd;
     }
     else
-	getvcol(wp, pos, start, cursor, end);
+	getvcol(wp, pos, start, cursor, end, headp);
 }
 #endif
 
 /*
+ * Like getvvcol() without head, but don't count the "phantom" whitespace added
+ * by 'lbr' to the size of the char.
+ */
+    void
+getvvcol_chop_lbr(
+    pos_T	*pos,
+    colnr_T	*start,
+    colnr_T	*cursor,
+    colnr_T	*end)
+{
+    colnr_T	start_vcol, cursor_vcol, end_vcol;
+    char_u	*char_ptr, *line;
+    int		csize;
+    int		head = 0;
+
+    getvvcol(curwin, pos, &start_vcol, &cursor_vcol, &end_vcol, &head);
+
+#ifdef FEAT_LINEBREAK
+    if (curwin->w_p_wrap && curwin->w_p_lbr && pos->col != MAXCOL
+# ifdef FEAT_VIRTUALEDIT
+	    && !virtual_active()
+# endif
+       )
+    {
+	line = ml_get(pos->lnum);
+	// Special check for an empty line, which can happen on exit, when
+	// ml_get_buf() always returns an empty string.
+	if (*line == NUL)
+	    pos->col = 0;
+	char_ptr = line + pos->col;
+	if (*char_ptr != NUL)
+	{
+	    curwin->w_p_lbr = FALSE;
+	    // Count end vcol again. Ignore lbr. But do consider sbr/bri.
+	    csize = win_lbr_chartabsize(curwin, line, char_ptr,
+						start_vcol - head, NULL);
+	    curwin->w_p_lbr = TRUE;
+	    end_vcol = start_vcol - head + csize - 1;
+	}
+    }
+#endif
+
+    if (start != NULL)
+	*start = start_vcol;
+    if (cursor != NULL)
+	*cursor = cursor_vcol;
+    if (end != NULL)
+	*end = end_vcol;
+}
+
+/*
  * Get the leftmost and rightmost virtual column of pos1 and pos2.
  * Used for Visual block mode.
  */
@@ -1517,13 +1575,13 @@ getvcols(
 
     if (LT_POSP(pos1, pos2))
     {
-	getvvcol(wp, pos1, &from1, NULL, &to1);
-	getvvcol(wp, pos2, &from2, NULL, &to2);
+	getvvcol(wp, pos1, &from1, NULL, &to1, NULL);
+	getvvcol(wp, pos2, &from2, NULL, &to2, NULL);
     }
     else
     {
-	getvvcol(wp, pos2, &from1, NULL, &to1);
-	getvvcol(wp, pos1, &from2, NULL, &to2);
+	getvvcol(wp, pos2, &from1, NULL, &to1, NULL);
+	getvvcol(wp, pos1, &from2, NULL, &to2, NULL);
     }
     if (from2 < from1)
 	*left = from2;
diff --git a/src/edit.c b/src/edit.c
index 239881ee5..89ee044df 100644
--- a/src/edit.c
+++ b/src/edit.c
@@ -7968,7 +7968,7 @@ replace_do_bs(int limit_col)
 	{
 	    /* Get the number of screen cells used by the character we are
 	     * going to delete. */
-	    getvcol(curwin, &curwin->w_cursor, NULL, &start_vcol, NULL);
+	    getvcol(curwin, &curwin->w_cursor, NULL, &start_vcol, NULL, NULL);
 	    orig_vcols = chartabsize(ml_get_cursor(), start_vcol);
 	}
 #ifdef FEAT_MBYTE
@@ -9049,7 +9049,7 @@ ins_del(void)
 ins_bs_one(colnr_T *vcolp)
 {
     dec_cursor();
-    getvcol(curwin, &curwin->w_cursor, vcolp, NULL, NULL);
+    getvcol(curwin, &curwin->w_cursor, vcolp, NULL, NULL, NULL);
     if (State & REPLACE_FLAG)
     {
 	/* Don't delete characters before the insert point when in
@@ -9299,10 +9299,10 @@ ins_bs(
 	    /* Compute the virtual column where we want to be.  Since
 	     * 'showbreak' may get in the way, need to get the last column of
 	     * the previous character. */
-	    getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL);
+	    getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL, NULL);
 	    start_vcol = vcol;
 	    dec_cursor();
-	    getvcol(curwin, &curwin->w_cursor, NULL, NULL, &want_vcol);
+	    getvcol(curwin, &curwin->w_cursor, NULL, NULL, &want_vcol, NULL);
 	    inc_cursor();
 #ifdef FEAT_VARTABS
 	    if (p_sta && in_indent)
@@ -9342,7 +9342,7 @@ ins_bs(
 		    if ((State & REPLACE_FLAG))
 			replace_push(NUL);
 		}
-		getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL);
+		getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL, NULL);
 	    }
 
 	    /* If we are now back where we started delete one character.  Can
@@ -10248,8 +10248,8 @@ ins_tab(void)
 	}
 
 	/* compute virtual column numbers of first white and cursor */
-	getvcol(curwin, &fpos, &vcol, NULL, NULL);
-	getvcol(curwin, cursor, &want_vcol, NULL, NULL);
+	getvcol(curwin, &fpos, &vcol, NULL, NULL, NULL);
+	getvcol(curwin, cursor, &want_vcol, NULL, NULL, NULL);
 
 	/* Use as many TABs as possible.  Beware of 'breakindent', 'showbreak'
 	 * and 'linebreak' adding extra virtual columns. */
diff --git a/src/evalfunc.c b/src/evalfunc.c
index f55739ed5..edc5dbb7a 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -13877,7 +13877,7 @@ f_virtcol(typval_T *argvars, typval_T *rettv)
     if (fp != NULL && fp->lnum <= curbuf->b_ml.ml_line_count
 						    && fnum == curbuf->b_fnum)
     {
-	getvvcol(curwin, fp, NULL, NULL, &vcol);
+	getvvcol(curwin, fp, NULL, NULL, &vcol, NULL);
 	++vcol;
     }
 
diff --git a/src/ex_cmds.c b/src/ex_cmds.c
index cb728d405..0e5aabfa9 100644
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -5403,11 +5403,11 @@ do_sub(exarg_T *eap)
 			    print_line_no_prefix(lnum,
 					 subflags.do_number, subflags.do_list);
 
-			    getvcol(curwin, &curwin->w_cursor, &sc, NULL, NULL);
+			    getvcol(curwin, &curwin->w_cursor, &sc, NULL, NULL, NULL);
 			    curwin->w_cursor.col = regmatch.endpos[0].col - 1;
 			    if (curwin->w_cursor.col < 0)
 				curwin->w_cursor.col = 0;
-			    getvcol(curwin, &curwin->w_cursor, NULL, NULL, &ec);
+			    getvcol(curwin, &curwin->w_cursor, NULL, NULL, &ec, NULL);
 			    if (subflags.do_number || curwin->w_p_nu)
 			    {
 				int numw = number_width(curwin) + 1;
diff --git a/src/mbyte.c b/src/mbyte.c
index 26233e423..2f2dc93e6 100644
--- a/src/mbyte.c
+++ b/src/mbyte.c
@@ -4852,7 +4852,7 @@ init_preedit_start_col(void)
     if (State & CMDLINE)
 	preedit_start_col = cmdline_getvcol_cursor();
     else if (curwin != NULL && curwin->w_buffer != NULL)
-	getvcol(curwin, &curwin->w_cursor, &preedit_start_col, NULL, NULL);
+	getvcol(curwin, &curwin->w_cursor, &preedit_start_col, NULL, NULL, NULL);
     /* Prevent that preediting marks the buffer as changed. */
     xim_changed_while_preediting = curbuf->b_changed;
 }
diff --git a/src/misc1.c b/src/misc1.c
index 820f8f994..8bce02818 100644
--- a/src/misc1.c
+++ b/src/misc1.c
@@ -626,7 +626,7 @@ get_number_indent(linenr_T lnum)
 
     if (pos.lnum == 0 || *ml_get_pos(&pos) == NUL)
 	return -1;
-    getvcol(curwin, &pos, &col, NULL, NULL);
+    getvcol(curwin, &pos, &col, NULL, NULL, NULL);
     return (int)col;
 }
 
@@ -2404,7 +2404,7 @@ ins_char_bytes(char_u *buf, int charlen)
 	     * be deleted to make room for the new character, counting screen
 	     * cells.  May result in adding spaces to fill a gap.
 	     */
-	    getvcol(curwin, &curwin->w_cursor, NULL, &vcol, NULL);
+	    getvcol(curwin, &curwin->w_cursor, NULL, &vcol, NULL, NULL);
 #ifndef FEAT_MBYTE
 	    buf[0] = c;
 	    buf[1] = NUL;
@@ -6134,7 +6134,7 @@ get_indent_nolabel (linenr_T lnum)	/* XXX */
 
     fp.col = (colnr_T)(p - l);
     fp.lnum = lnum;
-    getvcol(curwin, &fp, &col, NULL, NULL);
+    getvcol(curwin, &fp, &col, NULL, NULL, NULL);
     return (int)col;
 }
 
@@ -6218,7 +6218,7 @@ cin_first_id_amount(void)
     p = skipwhite(p + len);
     fp.lnum = curwin->w_cursor.lnum;
     fp.col = (colnr_T)(p - line);
-    getvcol(curwin, &fp, &col, NULL, NULL);
+    getvcol(curwin, &fp, &col, NULL, NULL, NULL);
     return (int)col;
 }
 
@@ -6266,7 +6266,7 @@ cin_get_equal_amount(linenr_T lnum)
 
     fp.lnum = lnum;
     fp.col = (colnr_T)(s - line);
-    getvcol(curwin, &fp, &col, NULL, NULL);
+    getvcol(curwin, &fp, &col, NULL, NULL, NULL);
     return (int)col;
 }
 
@@ -6872,7 +6872,7 @@ get_baseclass_amount(int col)
     else
     {
 	curwin->w_cursor.col = col;
-	getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL);
+	getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL, NULL);
 	amount = (int)vcol;
     }
     if (amount < curbuf->b_ind_cpp_baseclass)
@@ -7483,7 +7483,7 @@ get_c_indent(void)
 	    && (trypos = find_line_comment()) != NULL) /* XXX */
     {
 	/* find how indented the line beginning the comment is */
-	getvcol(curwin, trypos, &col, NULL, NULL);
+	getvcol(curwin, trypos, &col, NULL, NULL, NULL);
 	amount = col;
 	goto theend;
     }
@@ -7505,7 +7505,7 @@ get_c_indent(void)
 	int	done = FALSE;
 
 	/* find how indented the line beginning the comment is */
-	getvcol(curwin, comment_pos, &col, NULL, NULL);
+	getvcol(curwin, comment_pos, &col, NULL, NULL, NULL);
 	amount = col;
 	*lead_start = NUL;
 	*lead_middle = NUL;
@@ -7633,7 +7633,7 @@ get_c_indent(void)
 		    if (*look != NUL)		    /* if something after it */
 			comment_pos->col = (colnr_T)(skipwhite(look) - start);
 		}
-		getvcol(curwin, comment_pos, &col, NULL, NULL);
+		getvcol(curwin, comment_pos, &col, NULL, NULL, NULL);
 		amount = col;
 		if (curbuf->b_ind_in_comment2 || *look == NUL)
 		    amount += curbuf->b_ind_in_comment;
@@ -7846,7 +7846,7 @@ get_c_indent(void)
 		 */
 		if (our_paren_pos.col > 0)
 		{
-		    getvcol(curwin, &our_paren_pos, &col, NULL, NULL);
+		    getvcol(curwin, &our_paren_pos, &col, NULL, NULL, NULL);
 		    if (cur_amount > (int)col)
 			cur_amount = col;
 		}
@@ -7941,7 +7941,7 @@ get_c_indent(void)
 	look = skipwhite(start);
 	if (*look == '{')
 	{
-	    getvcol(curwin, trypos, &col, NULL, NULL);
+	    getvcol(curwin, trypos, &col, NULL, NULL, NULL);
 	    amount = col;
 	    if (*start == '{')
 		start_brace = BRACE_IN_COL0;
diff --git a/src/misc2.c b/src/misc2.c
index ce695979d..53b11a9c4 100644
--- a/src/misc2.c
+++ b/src/misc2.c
@@ -43,7 +43,7 @@ getviscol(void)
 {
     colnr_T	x;
 
-    getvvcol(curwin, &curwin->w_cursor, &x, NULL, NULL);
+    getvvcol(curwin, &curwin->w_cursor, &x, NULL, NULL, NULL);
     return (int)x;
 }
 
@@ -59,7 +59,7 @@ getviscol2(colnr_T col, colnr_T coladd)
     pos.lnum = curwin->w_cursor.lnum;
     pos.col = col;
     pos.coladd = coladd;
-    getvvcol(curwin, &pos, &x, NULL, NULL);
+    getvvcol(curwin, &pos, &x, NULL, NULL, NULL);
     return (int)x;
 }
 
@@ -301,7 +301,7 @@ coladvance2(
 	    {
 		colnr_T	    scol, ecol;
 
-		getvcol(curwin, pos, &scol, NULL, &ecol);
+		getvcol(curwin, pos, &scol, NULL, &ecol, NULL);
 		pos->coladd = ecol - scol;
 	    }
 	}
@@ -635,7 +635,7 @@ check_cursor_col_win(win_T *win)
 	    {
 		int cs, ce;
 
-		getvcol(win, &win->w_cursor, &cs, NULL, &ce);
+		getvcol(win, &win->w_cursor, &cs, NULL, &ce, NULL);
 		if (win->w_cursor.coladd > ce - cs)
 		    win->w_cursor.coladd = ce - cs;
 	    }
@@ -707,7 +707,7 @@ leftcol_changed(void)
      * advance the cursor one more char.  If this fails (last char of the
      * line) adjust the scrolling.
      */
-    getvvcol(curwin, &curwin->w_cursor, &s, NULL, &e);
+    getvvcol(curwin, &curwin->w_cursor, &s, NULL, &e, NULL);
     if (e > (colnr_T)lastcol)
     {
 	retval = TRUE;
diff --git a/src/move.c b/src/move.c
index 214c362f4..e841f650c 100644
--- a/src/move.c
+++ b/src/move.c
@@ -819,7 +819,7 @@ validate_virtcol_win(win_T *wp)
     check_cursor_moved(wp);
     if (!(wp->w_valid & VALID_VIRTCOL))
     {
-	getvvcol(wp, &wp->w_cursor, NULL, &(wp->w_virtcol), NULL);
+	getvvcol(wp, &wp->w_cursor, NULL, &(wp->w_virtcol), NULL, NULL);
 	wp->w_valid |= VALID_VIRTCOL;
 #ifdef FEAT_SYN_HL
 	if (wp->w_p_cuc
@@ -976,7 +976,7 @@ curs_columns(
     else
 #endif
 	getvvcol(curwin, &curwin->w_cursor,
-				&startcol, &(curwin->w_virtcol), &endcol);
+				&startcol, &(curwin->w_virtcol), &endcol, NULL);
 
     /* remove '$' from change command when cursor moves onto it */
     if (startcol > dollar_vcol)
diff --git a/src/normal.c b/src/normal.c
index a0683b207..d3134b90a 100644
--- a/src/normal.c
+++ b/src/normal.c
@@ -1595,8 +1595,19 @@ do_pending_operator(cmdarg_T *cap, int old_col, int gui_yank)
 
 	if (VIsual_active || redo_VIsual_busy)
 	{
+#ifdef FEAT_LINEBREAK
+	    // Temporarily restore linebreak, so that vcols reflect it.
+	    if (curwin->w_p_lbr != lbr_saved)
+		curwin->w_p_lbr = lbr_saved;
+#endif
+
 	    get_op_vcol(oap, redo_VIsual_vcol, TRUE);
 
+#ifdef FEAT_LINEBREAK
+	    // Revert the temporary restore of linebreak.
+	    curwin->w_p_lbr = FALSE;
+#endif
+
 	    if (!redo_VIsual_busy && !gui_yank)
 	    {
 		/*
@@ -1610,12 +1621,12 @@ do_pending_operator(cmdarg_T *cap, int old_col, int gui_yank)
 		{
 		    if (VIsual_mode != Ctrl_V)
 			getvvcol(curwin, &(oap->end),
-						  NULL, NULL, &oap->end_vcol);
+						  NULL, NULL, &oap->end_vcol, NULL);
 		    if (VIsual_mode == Ctrl_V || oap->line_count <= 1)
 		    {
 			if (VIsual_mode != Ctrl_V)
 			    getvvcol(curwin, &(oap->start),
-						&oap->start_vcol, NULL, NULL);
+						&oap->start_vcol, NULL, NULL, NULL);
 			resel_VIsual_vcol = oap->end_vcol - oap->start_vcol + 1;
 		    }
 		    else
@@ -1733,6 +1744,9 @@ do_pending_operator(cmdarg_T *cap, int old_col, int gui_yank)
 		    curwin->w_p_lbr = lbr_saved;
 #endif
 		    redraw_curbuf_later(INVERTED);
+#ifdef FEAT_LINEBREAK
+		    curwin->w_p_lbr = FALSE;
+#endif
 		}
 	    }
 	}
@@ -1782,6 +1796,9 @@ do_pending_operator(cmdarg_T *cap, int old_col, int gui_yank)
 	    curwin->w_p_lbr = lbr_saved;
 #endif
 	    redraw_curbuf_later(INVERTED);
+#ifdef FEAT_LINEBREAK
+	    curwin->w_p_lbr = FALSE;
+#endif
 	}
 
 	/*
@@ -1821,7 +1838,16 @@ do_pending_operator(cmdarg_T *cap, int old_col, int gui_yank)
 	{
 	case OP_LSHIFT:
 	case OP_RSHIFT:
+#ifdef FEAT_LINEBREAK
+	    // Temporarily restore linebreak, vcols are calculated with it.
+	    if (curwin->w_p_lbr != lbr_saved)
+		curwin->w_p_lbr = lbr_saved;
+#endif
 	    op_shift(oap, TRUE, oap->is_VIsual ? (int)cap->count1 : 1);
+#ifdef FEAT_LINEBREAK
+	    // Reset linebreak, so that formatting works correctly.
+	    curwin->w_p_lbr = FALSE;
+#endif
 	    auto_format(FALSE, TRUE);
 	    break;
 
@@ -1849,7 +1875,16 @@ do_pending_operator(cmdarg_T *cap, int old_col, int gui_yank)
 	    }
 	    else
 	    {
+#ifdef FEAT_LINEBREAK
+		// Temporarily restore linebreak, vcols are calculated with it.
+		if (curwin->w_p_lbr != lbr_saved)
+		    curwin->w_p_lbr = lbr_saved;
+#endif
 		(void)op_delete(oap);
+#ifdef FEAT_LINEBREAK
+		// Reset linebreak, so that formatting works correctly.
+		curwin->w_p_lbr = FALSE;
+#endif
 		if (oap->motion_type == MLINE && has_format_option(FO_AUTO))
 		    u_save_cursor();	    /* cursor line wasn't saved yet */
 		auto_format(FALSE, TRUE);
@@ -1868,9 +1903,15 @@ do_pending_operator(cmdarg_T *cap, int old_col, int gui_yank)
 	    else
 	    {
 #ifdef FEAT_LINEBREAK
-		curwin->w_p_lbr = lbr_saved;
+		// Temporarily restore linebreak, vcols are calculated with it.
+		if (curwin->w_p_lbr != lbr_saved)
+		    curwin->w_p_lbr = lbr_saved;
 #endif
 		(void)op_yank(oap, FALSE, !gui_yank);
+#ifdef FEAT_LINEBREAK
+		// Reset linebreak, so that formatting works correctly.
+		curwin->w_p_lbr = FALSE;
+#endif
 	    }
 	    check_cursor_col();
 	    break;
@@ -1897,10 +1938,7 @@ do_pending_operator(cmdarg_T *cap, int old_col, int gui_yank)
 		/* Restore linebreak, so that when the user edits it looks as
 		 * before. */
 		if (curwin->w_p_lbr != lbr_saved)
-		{
 		    curwin->w_p_lbr = lbr_saved;
-		    get_op_vcol(oap, redo_VIsual_mode, FALSE);
-		}
 #endif
 		/* Reset finish_op now, don't want it set inside edit(). */
 		finish_op = FALSE;
@@ -1958,7 +1996,18 @@ do_pending_operator(cmdarg_T *cap, int old_col, int gui_yank)
 		CancelRedo();
 	    }
 	    else
+	    {
+#ifdef FEAT_LINEBREAK
+		// Temporarily restore linebreak, vcols are calculated with it.
+		if (curwin->w_p_lbr != lbr_saved)
+		    curwin->w_p_lbr = lbr_saved;
+#endif
 		op_tilde(oap);
+#ifdef FEAT_LINEBREAK
+		// Reset linebreak, so that formatting works correctly.
+		curwin->w_p_lbr = FALSE;
+#endif
+	    }
 	    check_cursor_col();
 	    break;
 
@@ -2004,13 +2053,9 @@ do_pending_operator(cmdarg_T *cap, int old_col, int gui_yank)
 		restart_edit_save = restart_edit;
 		restart_edit = 0;
 #ifdef FEAT_LINEBREAK
-		/* Restore linebreak, so that when the user edits it looks as
-		 * before. */
+		// Temporarily restore linebreak, vcols are calculated with it.
 		if (curwin->w_p_lbr != lbr_saved)
-		{
 		    curwin->w_p_lbr = lbr_saved;
-		    get_op_vcol(oap, redo_VIsual_mode, FALSE);
-		}
 #endif
 		op_insert(oap, cap->count1);
 #ifdef FEAT_LINEBREAK
@@ -2045,13 +2090,9 @@ do_pending_operator(cmdarg_T *cap, int old_col, int gui_yank)
 	    else
 	    {
 # ifdef FEAT_LINEBREAK
-		/* Restore linebreak, so that when the user edits it looks as
-		 * before. */
+		// Temporarily restore linebreak, vcols are calculated with it.
 		if (curwin->w_p_lbr != lbr_saved)
-		{
 		    curwin->w_p_lbr = lbr_saved;
-		    get_op_vcol(oap, redo_VIsual_mode, FALSE);
-		}
 # endif
 		op_replace(oap, cap->nchar);
 	    }
@@ -2702,7 +2743,7 @@ do_mouse(
 			{
 			    getvcols(curwin, &curwin->w_cursor, &VIsual,
 						     &leftcol, &rightcol);
-			    getvcol(curwin, &m_pos, NULL, &m_pos.col, NULL);
+			    getvcol(curwin, &m_pos, NULL, &m_pos.col, NULL, NULL);
 			    if (m_pos.col < leftcol || m_pos.col > rightcol)
 				jump_flags = MOUSE_MAY_STOP_VIS;
 			}
@@ -4936,7 +4977,7 @@ dozet:
 			col = 0;	/* like the cursor is in col 0 */
 		    else
 #endif
-		    getvcol(curwin, &curwin->w_cursor, &col, NULL, NULL);
+		    getvcol(curwin, &curwin->w_cursor, &col, NULL, NULL, NULL);
 		    if ((long)col > p_siso)
 			col -= p_siso;
 		    else
@@ -4957,7 +4998,7 @@ dozet:
 			col = 0;	/* like the cursor is in col 0 */
 		    else
 #endif
-		    getvcol(curwin, &curwin->w_cursor, NULL, NULL, &col);
+		    getvcol(curwin, &curwin->w_cursor, NULL, NULL, &col, NULL);
 		    n = curwin->w_width - curwin_col_off();
 		    if ((long)col + p_siso < n)
 			col = 0;
@@ -6433,7 +6474,7 @@ nv_csearch(cmdarg_T *cap)
 	{
 	    colnr_T	scol, ecol;
 
-	    getvcol(curwin, &curwin->w_cursor, &scol, NULL, &ecol);
+	    getvcol(curwin, &curwin->w_cursor, &scol, NULL, &ecol, NULL);
 	    curwin->w_cursor.coladd = ecol - scol;
 	}
 	else
@@ -9650,11 +9691,11 @@ get_op_vcol(
 	mb_adjustpos(curwin->w_buffer, &oap->end);
 #endif
 
-    getvvcol(curwin, &(oap->start), &oap->start_vcol, NULL, &oap->end_vcol);
+    getvvcol_chop_lbr(&(oap->start), &oap->start_vcol, NULL, &oap->end_vcol);
 
     if (!redo_VIsual_busy)
     {
-	getvvcol(curwin, &(oap->end), &start, NULL, &end);
+	getvvcol_chop_lbr(&(oap->end), &start, NULL, &end);
 
 	if (start < oap->start_vcol)
 	    oap->start_vcol = start;
@@ -9677,7 +9718,7 @@ get_op_vcol(
 		curwin->w_cursor.lnum <= oap->end.lnum;
 					++curwin->w_cursor.lnum)
 	{
-	    getvvcol(curwin, &curwin->w_cursor, NULL, NULL, &end);
+	    getvvcol_chop_lbr(&curwin->w_cursor, NULL, NULL, &end);
 	    if (end > oap->end_vcol)
 		oap->end_vcol = end;
 	}
diff --git a/src/ops.c b/src/ops.c
index d6559a2b1..069c128a3 100644
--- a/src/ops.c
+++ b/src/ops.c
@@ -3200,7 +3200,7 @@ op_yank(oparg_T *oap, int deleting, int mess)
 #ifdef FEAT_VIRTUALEDIT
 			if (virtual_op)
 			{
-			    getvcol(curwin, &oap->start, &cs, NULL, &ce);
+			    getvcol(curwin, &oap->start, &cs, NULL, &ce, NULL);
 			    if (ce != cs && oap->start.coladd > 0)
 			    {
 				/* Part of a tab selected -- but don't
@@ -3219,7 +3219,7 @@ op_yank(oparg_T *oap, int deleting, int mess)
 #ifdef FEAT_VIRTUALEDIT
 			if (virtual_op)
 			{
-			    getvcol(curwin, &oap->end, &cs, NULL, &ce);
+			    getvcol(curwin, &oap->end, &cs, NULL, &ce, NULL);
 			    if (p[endcol] == NUL || (cs + oap->end.coladd < ce
 # ifdef FEAT_MBYTE
 					/* Don't add space for double-wide
@@ -3745,10 +3745,10 @@ do_put(
 	{
 #ifdef FEAT_VIRTUALEDIT
 	    if (ve_flags == VE_ALL)
-		getvcol(curwin, &curwin->w_cursor, &col, NULL, &endcol2);
+		getvcol(curwin, &curwin->w_cursor, &col, NULL, &endcol2, NULL);
 	    else
 #endif
-		getvcol(curwin, &curwin->w_cursor, NULL, NULL, &col);
+		getvcol(curwin, &curwin->w_cursor, NULL, NULL, &col, NULL);
 
 #ifdef FEAT_MBYTE
 	    if (has_mbyte)
@@ -3763,7 +3763,7 @@ do_put(
 	    ++col;
 	}
 	else
-	    getvcol(curwin, &curwin->w_cursor, &col, NULL, &endcol2);
+	    getvcol(curwin, &curwin->w_cursor, &col, NULL, &endcol2, NULL);
 
 #ifdef FEAT_VIRTUALEDIT
 	col += curwin->w_cursor.coladd;
@@ -4205,7 +4205,7 @@ adjust_cursor_eol(void)
 	    colnr_T	    scol, ecol;
 
 	    /* Coladd is set to the width of the last character. */
-	    getvcol(curwin, &curwin->w_cursor, &scol, NULL, &ecol);
+	    getvcol(curwin, &curwin->w_cursor, &scol, NULL, &ecol, NULL);
 	    curwin->w_cursor.coladd = ecol - scol + 1;
 	}
 #endif
@@ -5396,6 +5396,7 @@ block_prep(
     linenr_T		lnum,
     int			is_del)
 {
+    int		head = 0;
     int		incr = 0;
     char_u	*pend;
     char_u	*pstart;
@@ -5422,8 +5423,18 @@ block_prep(
     prev_pstart = line;
     while (bdp->start_vcol < oap->start_vcol && *pstart)
     {
-	/* Count a tab for what it's worth (if list mode not on) */
-	incr = lbr_chartabsize(line, pstart, (colnr_T)bdp->start_vcol);
+	head = 0;
+	// Count a tab for what it's worth.
+	incr = win_lbr_chartabsize(curwin, line, pstart,
+					    (colnr_T)bdp->start_vcol, &head);
+	if (bdp->start_vcol + head >= oap->start_vcol)
+	{
+	    bdp->start_vcol += head;
+	    // 'showbreak' is in effect, nr of chars's vcols is actually
+	    // smaller.
+	    incr = incr - head;
+	    break;
+	}
 	bdp->start_vcol += incr;
 #ifdef FEAT_VISUALEXTRA
 	if (VIM_ISWHITE(*pstart))
@@ -5487,6 +5498,7 @@ block_prep(
 	}
 	else
 	{
+	    bdp->end_vcol = bdp->start_vcol - head;
 	    prev_pend = pend;
 	    while (bdp->end_vcol <= oap->end_vcol && *pend != NUL)
 	    {
@@ -5495,6 +5507,23 @@ block_prep(
 		incr = lbr_chartabsize_adv(line, &pend, (colnr_T)bdp->end_vcol);
 		bdp->end_vcol += incr;
 	    }
+#ifdef FEAT_LINEBREAK
+	    if (curwin->w_p_wrap && curwin->w_p_lbr && *prev_pend != NUL
+		    && is_del)
+	    {
+		bdp->end_vcol -= incr;
+		curwin->w_p_lbr = FALSE;
+		// Don't count the "phantom" whitespace added by lbr to the
+		// right side of the last character. But do consider sbr/bri.
+		incr = win_lbr_chartabsize(curwin, line, prev_pend,
+						    bdp->end_vcol, &head);
+		curwin->w_p_lbr = TRUE;
+		bdp->end_vcol += incr;
+		// If 'showbreak' is in effect, nr of chars's vcols is actually
+		// smaller.
+		incr -= head;
+	    }
+#endif
 	    if (bdp->end_vcol <= oap->end_vcol
 		    && (!is_del
 			|| oap->op_type == OP_APPEND
diff --git a/src/proto/charset.pro b/src/proto/charset.pro
index bb4132fe7..5bea9bee0 100644
--- a/src/proto/charset.pro
+++ b/src/proto/charset.pro
@@ -29,10 +29,12 @@ int vim_isprintc_strict(int c);
 int lbr_chartabsize(char_u *line, unsigned char *s, colnr_T col);
 int lbr_chartabsize_adv(char_u *line, char_u **s, colnr_T col);
 int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *headp);
+// int win_nolbr_chartabsize(win_T *wp, char_u *s, colnr_T col, int *headp);
 int in_win_border(win_T *wp, colnr_T vcol);
-void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *end);
+void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *end, int *headp);
 colnr_T getvcol_nolist(pos_T *posp);
-void getvvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *end);
+void getvvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *end, int *headp);
+void getvvcol_chop_lbr(pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *end);
 void getvcols(win_T *wp, pos_T *pos1, pos_T *pos2, colnr_T *left, colnr_T *right);
 char_u *skipwhite(char_u *q);
 int getwhitecols_curline(void);
diff --git a/src/regexp.c b/src/regexp.c
index 04116675f..6e31f03df 100644
--- a/src/regexp.c
+++ b/src/regexp.c
@@ -4207,8 +4207,8 @@ reg_match_visual(void)
     }
     else if (mode == Ctrl_V)
     {
-	getvvcol(wp, &top, &start, NULL, &end);
-	getvvcol(wp, &bot, &start2, NULL, &end2);
+	getvvcol(wp, &top, &start, NULL, &end, NULL);
+	getvvcol(wp, &bot, &start2, NULL, &end2, NULL);
 	if (start2 < start)
 	    start = start2;
 	if (end2 > end)
diff --git a/src/screen.c b/src/screen.c
index 69f755844..d4e2a9a3b 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -3385,7 +3385,7 @@ win_line(
 			fromcol = 0;
 		    else
 		    {
-			getvvcol(wp, top, (colnr_T *)&fromcol, NULL, NULL);
+			getvvcol(wp, top, (colnr_T *)&fromcol, NULL, NULL, NULL);
 			if (gchar_pos(top) == NUL)
 			    tocol = fromcol + 1;
 		    }
@@ -3407,10 +3407,10 @@ win_line(
 		    {
 			pos = *bot;
 			if (*p_sel == 'e')
-			    getvvcol(wp, &pos, (colnr_T *)&tocol, NULL, NULL);
+			    getvvcol(wp, &pos, (colnr_T *)&tocol, NULL, NULL, NULL);
 			else
 			{
-			    getvvcol(wp, &pos, NULL, NULL, (colnr_T *)&tocol);
+			    getvvcol(wp, &pos, NULL, NULL, (colnr_T *)&tocol, NULL);
 			    ++tocol;
 			}
 		    }
@@ -3450,14 +3450,14 @@ win_line(
 	{
 	    if (lnum == curwin->w_cursor.lnum)
 		getvcol(curwin, &(curwin->w_cursor),
-						 (colnr_T *)&fromcol, NULL, NULL);
+						 (colnr_T *)&fromcol, NULL, NULL, NULL);
 	    else
 		fromcol = 0;
 	    if (lnum == curwin->w_cursor.lnum + search_match_lines)
 	    {
 		pos.lnum = lnum;
 		pos.col = search_match_endcol;
-		getvcol(curwin, &pos, (colnr_T *)&tocol, NULL, NULL);
+		getvcol(curwin, &pos, (colnr_T *)&tocol, NULL, NULL, NULL);
 	    }
 	    else
 		tocol = MAXCOL;
@@ -5295,7 +5295,7 @@ win_line(
 	    colnr_T tcol;
 
 	    if (preedit_end_col == MAXCOL)
-		getvcol(curwin, &(wp->w_cursor), &tcol, NULL, NULL);
+		getvcol(curwin, &(wp->w_cursor), &tcol, NULL, NULL, NULL);
 	    else
 		tcol = preedit_end_col;
 	    if ((long)preedit_start_col <= vcol && vcol < (long)tcol)
@@ -11056,7 +11056,7 @@ win_redr_ruler(win_T *wp, int always, int ignore_pum)
 	if (wp->w_p_list && lcs_tab1 == NUL)
 	{
 	    wp->w_p_list = FALSE;
-	    getvvcol(wp, &wp->w_cursor, NULL, &virtcol, NULL);
+	    getvvcol(wp, &wp->w_cursor, NULL, &virtcol, NULL, NULL);
 	    wp->w_p_list = TRUE;
 	}
 
diff --git a/src/search.c b/src/search.c
index dff532d8f..a6fe1c050 100644
--- a/src/search.c
+++ b/src/search.c
@@ -2644,7 +2644,7 @@ showmatch(
     else if (lpos->lnum >= curwin->w_topline && lpos->lnum < curwin->w_botline)
     {
 	if (!curwin->w_p_wrap)
-	    getvcol(curwin, lpos, NULL, &vcol, NULL);
+	    getvcol(curwin, lpos, NULL, &vcol, NULL, NULL);
 	if (curwin->w_p_wrap || (vcol >= curwin->w_leftcol
 			       && vcol < curwin->w_leftcol + curwin->w_width))
 	{
diff --git a/src/vim.h b/src/vim.h
index 7a66ab0e2..a02be5df2 100644
--- a/src/vim.h
+++ b/src/vim.h
@@ -2173,7 +2173,7 @@ typedef enum {
 #include "globals.h"	    /* global variables and messages */
 
 #ifndef FEAT_VIRTUALEDIT
-# define getvvcol(w, p, s, c, e) getvcol((w), (p), (s), (c), (e))
+# define getvvcol(w, p, s, c, e, h) getvcol((w), (p), (s), (c), (e), (h))
 # define virtual_active() FALSE
 # define virtual_op FALSE
 #endif
-- 
2.11.0

Raspunde prin e-mail lui