On Mon, Dec 24, 2018 at 9:36 AM Christian Brabandt <[email protected]> wrote:
> I'll have a look.
>
> Tom, can you provide a simple test case?

It's about the issue reported by John Little and Tony Mechelynck on
Wed, Oct 24, 2018: "linebreak, showbreak, and visual block yank
problem". See: https://groups.google.com/forum/#!topic/vim_dev/xy7eYYZXe_w
.

This example yanks "56\nEF" when it should yank "78\nGH":
setl lbr
call setline(1, repeat('a', winwidth(0)-2) . '.123456789')
call setline(2, repeat('a', winwidth(0)-4) . '.ABCDEFGHI')
exe "norm gg0f7\<c-v>jly"

The point is, that 'linebreak' is not fully supported by
do_pending_operator(), lbr is temporarily reset while executing
operations. So the start/end vcols are calculated incorrectly. I
managed to correct it (via fixing get_op_vcol()), but that's just the
easy part. It seems that startspaces/endspaces computation in
block_prep() needs amending too. And with that all functions that call
block_prep() - functioons implementing block yank, delete, change,
append (this is where I am beeing at the moment), insert, tilde, ... I
am completely new to most of the code, so the progress is slow.
Anyway, comments are welcome.

I am attaching a patch file - my current state of my changes. Main
changes are in normal.c, charset.c and ops.c. Other than that it's all
just consequences of altering getvcol() prototype.

Mery Christmas!

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 [email protected].
For more options, visit https://groups.google.com/d/optout.
diff --git a/src/charset.c b/src/charset.c
index 028095453..92ed0e6eb 100644
--- a/src/charset.c
+++ b/src/charset.c
@@ -1273,9 +1273,11 @@ in_win_border(win_T *wp, colnr_T vcol)
 
 /*
  * Get virtual column number of pos.
- *  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)
+ *   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)
+ * virtcol: the real first virtual column, either equal to 'start' or even
+ * 	    less if 'sbr' or 'bri' comes into play
  *
  * This is used very often, keep it fast!
  */
@@ -1283,6 +1285,7 @@ in_win_border(win_T *wp, colnr_T vcol)
 getvcol(
     win_T	*wp,
     pos_T	*pos,
+    colnr_T	*virtcol,
     colnr_T	*start,
     colnr_T	*cursor,
     colnr_T	*end)
@@ -1406,6 +1409,8 @@ getvcol(
 	    MB_PTR_ADV(ptr);
 	}
     }
+    if (virtcol != NULL)
+	*virtcol = vcol;
     if (start != NULL)
 	*start = vcol + head;
     if (end != NULL)
@@ -1437,10 +1442,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, NULL, &vcol, NULL);
     else
 #endif
-	getvcol(curwin, posp, NULL, &vcol, NULL);
+	getvcol(curwin, posp, NULL, NULL, &vcol, NULL);
     curwin->w_p_list = list_save;
     return vcol;
 }
@@ -1453,6 +1458,7 @@ getvcol_nolist(pos_T *posp)
 getvvcol(
     win_T	*wp,
     pos_T	*pos,
+    colnr_T	*virtcol,
     colnr_T	*start,
     colnr_T	*cursor,
     colnr_T	*end)
@@ -1467,7 +1473,7 @@ getvvcol(
     if (virtual_active())
     {
 	/* For virtual mode, only want one value */
-	getvcol(wp, pos, &col, NULL, NULL);
+	getvcol(wp, pos, NULL, &col, NULL, NULL);
 
 	coladd = pos->coladd;
 	endadd = 0;
@@ -1497,11 +1503,57 @@ getvvcol(
 	    *end = col + endadd;
     }
     else
-	getvcol(wp, pos, start, cursor, end);
+	getvcol(wp, pos, NULL, start, cursor, end);
 }
 #endif
 
 /*
+ * Like getvvcol() but don't count the extension of the character size applied
+ * by 'lbr'
+ */
+    void
+chop_lbr_getvvcol(
+    win_T	*wp,
+    pos_T	*pos,
+    colnr_T	*start,
+    colnr_T	*end)
+{
+    colnr_T	init_vcol, start_vcol, end_vcol;
+    char_u	*char_ptr, *line;
+    int		char_size;
+
+    getvvcol(wp, pos, &init_vcol, &start_vcol, NULL, &end_vcol);
+
+#ifdef FEAT_LINEBREAK
+    if (wp->w_p_wrap && wp->w_p_lbr && pos->col != MAXCOL
+# ifdef FEAT_VIRTUALEDIT
+	    && !virtual_active()
+# endif
+       )
+    {
+	line = char_ptr = 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)
+	    char_ptr = line + pos->col;
+	if (*char_ptr != NUL)
+	{
+	    wp->w_p_lbr = FALSE;
+	    // Recount end vcol. This time ignore lbr, but do consider sbr/bri.
+	    char_size = win_lbr_chartabsize(wp, line, char_ptr, init_vcol,
+									NULL);
+	    wp->w_p_lbr = TRUE;
+	    end_vcol = start_vcol + char_size - 1;
+	}
+    }
+#endif
+    if (start != NULL)
+	*start = start_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 +1569,13 @@ getvcols(
 
     if (LT_POSP(pos1, pos2))
     {
-	getvvcol(wp, pos1, &from1, NULL, &to1);
-	getvvcol(wp, pos2, &from2, NULL, &to2);
+	getvvcol(wp, pos1, NULL, &from1, NULL, &to1);
+	getvvcol(wp, pos2, NULL, &from2, NULL, &to2);
     }
     else
     {
-	getvvcol(wp, pos2, &from1, NULL, &to1);
-	getvvcol(wp, pos1, &from2, NULL, &to2);
+	getvvcol(wp, pos2, NULL, &from1, NULL, &to1);
+	getvvcol(wp, pos1, NULL, &from2, NULL, &to2);
     }
     if (from2 < from1)
 	*left = from2;
diff --git a/src/normal.c b/src/normal.c
index a0683b207..f626e7af9 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, NULL, &oap->end_vcol);
 		    if (VIsual_mode == Ctrl_V || oap->line_count <= 1)
 		    {
 			if (VIsual_mode != Ctrl_V)
 			    getvvcol(curwin, &(oap->start),
-						&oap->start_vcol, NULL, NULL);
+					    NULL, &oap->start_vcol, 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,15 @@ 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.
+	    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 +1874,15 @@ do_pending_operator(cmdarg_T *cap, int old_col, int gui_yank)
 	    }
 	    else
 	    {
+#ifdef FEAT_LINEBREAK
+		// Temporarily restore linebreak, vcols are calculated with it.
+		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 +1901,14 @@ do_pending_operator(cmdarg_T *cap, int old_col, int gui_yank)
 	    else
 	    {
 #ifdef FEAT_LINEBREAK
+		// Temporarily restore linebreak, vcols are calculated with it.
 		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;
@@ -1894,13 +1932,9 @@ do_pending_operator(cmdarg_T *cap, int old_col, int gui_yank)
 		    restart_edit_save = 0;
 		restart_edit = 0;
 #ifdef FEAT_LINEBREAK
-		/* 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);
-		}
+		// Temporarily restore linebreak, vcols are calculated with it.
+		// Also restore it, so that when the user edits it looks as before.
+		curwin->w_p_lbr = lbr_saved;
 #endif
 		/* Reset finish_op now, don't want it set inside edit(). */
 		finish_op = FALSE;
@@ -1958,7 +1992,17 @@ 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.
+		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 +2048,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. */
-		if (curwin->w_p_lbr != lbr_saved)
-		{
-		    curwin->w_p_lbr = lbr_saved;
-		    get_op_vcol(oap, redo_VIsual_mode, FALSE);
-		}
+		// Temporarily restore linebreak, vcols are calculated with it.
+		// Also restore it, so that when the user edits it looks as before.
+		curwin->w_p_lbr = lbr_saved;
 #endif
 		op_insert(oap, cap->count1);
 #ifdef FEAT_LINEBREAK
@@ -2045,13 +2085,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. */
-		if (curwin->w_p_lbr != lbr_saved)
-		{
-		    curwin->w_p_lbr = lbr_saved;
-		    get_op_vcol(oap, redo_VIsual_mode, FALSE);
-		}
+		// Temporarily restore linebreak, vcols are calculated with it.
+		// Also restore it, so that when the user edits it looks as before.
+		curwin->w_p_lbr = lbr_saved;
 # endif
 		op_replace(oap, cap->nchar);
 	    }
@@ -2702,7 +2738,8 @@ do_mouse(
 			{
 			    getvcols(curwin, &curwin->w_cursor, &VIsual,
 						     &leftcol, &rightcol);
-			    getvcol(curwin, &m_pos, NULL, &m_pos.col, NULL);
+			    getvcol(curwin, &m_pos,
+					NULL, NULL, &m_pos.col, NULL);
 			    if (m_pos.col < leftcol || m_pos.col > rightcol)
 				jump_flags = MOUSE_MAY_STOP_VIS;
 			}
@@ -4936,7 +4973,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, NULL, &col, NULL, NULL);
 		    if ((long)col > p_siso)
 			col -= p_siso;
 		    else
@@ -4957,7 +4994,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, NULL, &col);
 		    n = curwin->w_width - curwin_col_off();
 		    if ((long)col + p_siso < n)
 			col = 0;
@@ -6433,7 +6470,7 @@ nv_csearch(cmdarg_T *cap)
 	{
 	    colnr_T	scol, ecol;
 
-	    getvcol(curwin, &curwin->w_cursor, &scol, NULL, &ecol);
+	    getvcol(curwin, &curwin->w_cursor, NULL, &scol, NULL, &ecol);
 	    curwin->w_cursor.coladd = ecol - scol;
 	}
 	else
@@ -9650,11 +9687,11 @@ get_op_vcol(
 	mb_adjustpos(curwin->w_buffer, &oap->end);
 #endif
 
-    getvvcol(curwin, &(oap->start), &oap->start_vcol, NULL, &oap->end_vcol);
+    chop_lbr_getvvcol(curwin, &(oap->start), &oap->start_vcol, &oap->end_vcol);
 
     if (!redo_VIsual_busy)
     {
-	getvvcol(curwin, &(oap->end), &start, NULL, &end);
+	chop_lbr_getvvcol(curwin, &(oap->end), &start, &end);
 
 	if (start < oap->start_vcol)
 	    oap->start_vcol = start;
@@ -9677,7 +9714,7 @@ get_op_vcol(
 		curwin->w_cursor.lnum <= oap->end.lnum;
 					++curwin->w_cursor.lnum)
 	{
-	    getvvcol(curwin, &curwin->w_cursor, NULL, NULL, &end);
+	    chop_lbr_getvvcol(curwin, &curwin->w_cursor, NULL, &end);
 	    if (end > oap->end_vcol)
 		oap->end_vcol = end;
 	}
diff --git a/src/ops.c b/src/ops.c
index d6559a2b1..95f6e4d4e 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, NULL, &cs, NULL, &ce);
 			    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, NULL, &cs, NULL, &ce);
 			    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, NULL, &col, NULL, &endcol2);
 	    else
 #endif
-		getvcol(curwin, &curwin->w_cursor, NULL, NULL, &col);
+		getvcol(curwin, &curwin->w_cursor, NULL, NULL, NULL, &col);
 
 #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, NULL, &col, NULL, &endcol2);
 
 #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, NULL, &scol, NULL, &ecol);
 	    curwin->w_cursor.coladd = ecol - scol + 1;
 	}
 #endif
@@ -5396,6 +5396,8 @@ block_prep(
     linenr_T		lnum,
     int			is_del)
 {
+    colnr_T	start_vcol_nolbr;
+    colnr_T	start_char_vcols_lbr;
     int		incr = 0;
     char_u	*pend;
     char_u	*pstart;
@@ -5441,6 +5443,23 @@ block_prep(
 	MB_PTR_ADV(pstart);
     }
     bdp->start_char_vcols = incr;
+    start_char_vcols_lbr = bdp->start_char_vcols;
+#ifdef FEAT_LINEBREAK
+    if (curwin->w_p_wrap && curwin->w_p_lbr && prev_pstart != line)
+    {
+	// Recount start char vcols. Ignore lbr, but do consider sbr/bri.
+	curwin->w_p_lbr = FALSE;
+	start_vcol_nolbr = bdp->start_vcol - bdp->start_char_vcols;
+	incr = win_lbr_chartabsize(curwin, line,
+					prev_pstart, start_vcol_nolbr, NULL);
+	bdp->start_char_vcols = incr;
+	start_vcol_nolbr += incr;
+	curwin->w_p_lbr = TRUE;
+    }
+    else
+#endif
+	start_vcol_nolbr = bdp->start_vcol;
+
     if (bdp->start_vcol < oap->start_vcol)	/* line too short */
     {
 	bdp->end_vcol = bdp->start_vcol;
@@ -5454,9 +5473,17 @@ block_prep(
     {
 	/* notice: this converts partly selected Multibyte characters to
 	 * spaces, too. */
-	bdp->startspaces = bdp->start_vcol - oap->start_vcol;
-	if (is_del && bdp->startspaces)
-	    bdp->startspaces = bdp->start_char_vcols - bdp->startspaces;
+	if (oap->start_vcol < start_vcol_nolbr
+		|| start_vcol_nolbr == bdp->start_vcol)
+	{
+	    bdp->startspaces = start_vcol_nolbr - oap->start_vcol;
+	    if (is_del && bdp->startspaces)
+		bdp->startspaces = bdp->start_char_vcols - bdp->startspaces;
+	}
+	// TODO: remove the following old code backup
+	// bdp->startspaces = bdp->start_vcol - oap->start_vcol;
+	// if (is_del && bdp->startspaces)
+	//     bdp->startspaces = bdp->start_char_vcols - bdp->startspaces;
 	pend = pstart;
 	bdp->end_vcol = bdp->start_vcol;
 	if (bdp->end_vcol > oap->end_vcol)	/* it's all in one character */
@@ -5479,14 +5506,21 @@ block_prep(
 		    /* just putting the sum of those two into
 		     * bdp->startspaces doesn't work for Visual replace,
 		     * so we have to split the tab in two */
-		    bdp->startspaces = bdp->start_char_vcols
+		    bdp->startspaces = start_char_vcols_lbr
 					- (bdp->start_vcol - oap->start_vcol);
-		    bdp->endspaces = bdp->end_vcol - oap->end_vcol - 1;
+		    if (bdp->startspaces > bdp->start_char_vcols)
+			bdp->startspaces = bdp->start_char_vcols;
+		    // if lbr not in effect: start_vcol_nolbr == bdp->end_vcol
+		    bdp->endspaces = start_vcol_nolbr - oap->end_vcol - 1;
+		    if (bdp->endspaces < 0)
+			bdp->endspaces = 0;
 		}
 	    }
 	}
 	else
 	{
+	    colnr_T	end_vcol_lbr;
+
 	    prev_pend = pend;
 	    while (bdp->end_vcol <= oap->end_vcol && *pend != NUL)
 	    {
@@ -5495,13 +5529,29 @@ block_prep(
 		incr = lbr_chartabsize_adv(line, &pend, (colnr_T)bdp->end_vcol);
 		bdp->end_vcol += incr;
 	    }
+	    end_vcol_lbr = bdp->end_vcol;
+#ifdef FEAT_LINEBREAK
+            if (curwin->w_p_wrap && curwin->w_p_lbr && *prev_pend != NUL)
+	    {
+		// Recount end vcol. This time ignore lbr, but do consider
+		// sbr/bri.
+		curwin->w_p_lbr = FALSE;
+		bdp->end_vcol -= incr;
+		incr = win_lbr_chartabsize(curwin, line,
+					    prev_pend, bdp->end_vcol, NULL);
+		bdp->end_vcol += incr;
+		curwin->w_p_lbr = TRUE;
+	    }
+#endif
 	    if (bdp->end_vcol <= oap->end_vcol
 		    && (!is_del
 			|| oap->op_type == OP_APPEND
 			|| oap->op_type == OP_REPLACE)) /* line too short */
 	    {
 #ifdef FEAT_VISUALEXTRA
-		bdp->is_short = TRUE;
+		// bdp->is_short = TRUE;
+		// TODO: set to TRUE as before ???
+		bdp->is_short = end_vcol_lbr <= oap->end_vcol;
 #endif
 		/* Alternative: include spaces to fill up the block.
 		 * Disadvantage: can lead to trailing spaces when the line is
@@ -5523,6 +5573,7 @@ block_prep(
 			pend = prev_pend;
 		}
 	    }
+	    bdp->end_vcol = end_vcol_lbr;
 	}
 #ifdef FEAT_VISUALEXTRA
 	bdp->end_char_vcols = incr;
diff --git a/src/proto/charset.pro b/src/proto/charset.pro
index bb4132fe7..0c12de4e6 100644
--- a/src/proto/charset.pro
+++ b/src/proto/charset.pro
@@ -30,9 +30,10 @@ 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 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 *init, colnr_T *start, colnr_T *cursor, colnr_T *end);
 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 chop_lbr_getvvcol(win_T *wp, pos_T *pos, colnr_T *start, 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..03a100509 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, NULL, &start, NULL, &end);
+	getvvcol(wp, &bot, NULL, &start2, NULL, &end2);
 	if (start2 < start)
 	    start = start2;
 	if (end2 > end)
diff --git a/src/screen.c b/src/screen.c
index 69f755844..9eeda54e6 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -3385,7 +3385,8 @@ win_line(
 			fromcol = 0;
 		    else
 		    {
-			getvvcol(wp, top, (colnr_T *)&fromcol, NULL, NULL);
+			getvvcol(wp, top,
+				    NULL, (colnr_T *)&fromcol, NULL, NULL);
 			if (gchar_pos(top) == NUL)
 			    tocol = fromcol + 1;
 		    }
@@ -3407,10 +3408,12 @@ win_line(
 		    {
 			pos = *bot;
 			if (*p_sel == 'e')
-			    getvvcol(wp, &pos, (colnr_T *)&tocol, NULL, NULL);
+			    getvvcol(wp, &pos, NULL,
+					(colnr_T *)&tocol, NULL, NULL);
 			else
 			{
-			    getvvcol(wp, &pos, NULL, NULL, (colnr_T *)&tocol);
+			    getvvcol(wp, &pos,
+					NULL, NULL, NULL, (colnr_T *)&tocol);
 			    ++tocol;
 			}
 		    }
@@ -3450,14 +3453,14 @@ win_line(
 	{
 	    if (lnum == curwin->w_cursor.lnum)
 		getvcol(curwin, &(curwin->w_cursor),
-						 (colnr_T *)&fromcol, NULL, NULL);
+					 NULL, (colnr_T *)&fromcol, 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, NULL, (colnr_T *)&tocol, NULL, NULL);
 	    }
 	    else
 		tocol = MAXCOL;
@@ -5295,7 +5298,7 @@ win_line(
 	    colnr_T tcol;
 
 	    if (preedit_end_col == MAXCOL)
-		getvcol(curwin, &(wp->w_cursor), &tcol, NULL, NULL);
+		getvcol(curwin, &(wp->w_cursor), NULL, &tcol, NULL, NULL);
 	    else
 		tcol = preedit_end_col;
 	    if ((long)preedit_start_col <= vcol && vcol < (long)tcol)
@@ -11056,7 +11059,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, NULL, &virtcol, NULL);
 	    wp->w_p_list = TRUE;
 	}
 
diff --git a/src/search.c b/src/search.c
index dff532d8f..b5a699fbe 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, NULL, &vcol, NULL);
 	if (curwin->w_p_wrap || (vcol >= curwin->w_leftcol
 			       && vcol < curwin->w_leftcol + curwin->w_width))
 	{
diff --git a/src/testdir/Makefile b/src/testdir/Makefile
index e9e0f4b32..c6567feef 100644
--- a/src/testdir/Makefile
+++ b/src/testdir/Makefile
@@ -38,6 +38,14 @@ SCRIPTS_BENCH = bench_re_freeze.out
 
 nongui:	nolog $(SCRIPTS_FIRST) $(SCRIPTS) newtests report
 
+tom39a:	nolog $(SCRIPTS_FIRST) tom39a.res report
+
+tom:	nolog $(SCRIPTS_FIRST) test_lbr_visual_block_yank_delete.res report
+
+tom2:	nolog $(SCRIPTS_FIRST) tom2.res report
+
+tom3:	nolog $(SCRIPTS_FIRST) tom3.res report
+
 gui:	nolog $(SCRIPTS_FIRST) $(SCRIPTS) $(SCRIPTS_GUI) newtests report
 
 benchmark: $(SCRIPTS_BENCH)
diff --git a/src/vim.h b/src/vim.h
index 7a66ab0e2..679f1197a 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, i, s, c, e) getvcol((w), (p), (i), (s), (c), (e))
 # define virtual_active() FALSE
 # define virtual_op FALSE
 #endif
diff --git a/src/buffer.c b/src/buffer.c
index 8e892dadf..df2996f24 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, NULL, &virtcol, NULL);
 		wp->w_p_list = TRUE;
 	    }
 	    ++virtcol;
diff --git a/src/edit.c b/src/edit.c
index 239881ee5..bb1d32697 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, NULL, &start_vcol, 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, NULL, vcolp, 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, NULL, &vcol, NULL, NULL);
 	    start_vcol = vcol;
 	    dec_cursor();
-	    getvcol(curwin, &curwin->w_cursor, NULL, NULL, &want_vcol);
+	    getvcol(curwin, &curwin->w_cursor, NULL, NULL, NULL, &want_vcol);
 	    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, NULL, &vcol, 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, NULL, &vcol, NULL, NULL);
+	getvcol(curwin, cursor, NULL, &want_vcol, 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..47402b9bb 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, NULL, &vcol);
 	++vcol;
     }
 
diff --git a/src/ex_cmds.c b/src/ex_cmds.c
index cb728d405..fd84cb5f0 100644
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -5403,11 +5403,13 @@ 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,
+					NULL, &sc, 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, NULL, &ec);
 			    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..1500ad1df 100644
--- a/src/mbyte.c
+++ b/src/mbyte.c
@@ -4852,7 +4852,8 @@ 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,
+		NULL, &preedit_start_col, 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..3c1be0d40 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, NULL, &col, 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, NULL, &vcol, 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, NULL, &col, 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, NULL, &col, 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, NULL, &col, 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, NULL, &vcol, 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, NULL, &col, 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, NULL, &col, 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, NULL, &col, 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, NULL, &col, 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, NULL, &col, NULL, NULL);
 	    amount = col;
 	    if (*start == '{')
 		start_brace = BRACE_IN_COL0;
diff --git a/src/misc2.c b/src/misc2.c
index ce695979d..b8130af49 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, NULL, &x, 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, NULL, &x, NULL, NULL);
     return (int)x;
 }
 
@@ -301,7 +301,7 @@ coladvance2(
 	    {
 		colnr_T	    scol, ecol;
 
-		getvcol(curwin, pos, &scol, NULL, &ecol);
+		getvcol(curwin, pos, NULL, &scol, NULL, &ecol);
 		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, NULL, &cs, NULL, &ce);
 		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, NULL, &s, NULL, &e);
     if (e > (colnr_T)lastcol)
     {
 	retval = TRUE;
diff --git a/src/move.c b/src/move.c
index 214c362f4..820bb8254 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, NULL, &(wp->w_virtcol), 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);
+			    NULL, &startcol, &(curwin->w_virtcol), &endcol);
 
     /* remove '$' from change command when cursor moves onto it */
     if (startcol > dollar_vcol)

Raspunde prin e-mail lui