On Mo, 18 Mai 2015, Ingo Karkat wrote:

> Hello Vim developers,
> 
> appending to the end of a visual blockwise selection can be done with
> the A command. I just noticed that this doesn't work reliably any more
> when
> - lines are wrapped and the cursor is in a following screen line AND
> - :set linebreak
> This happens with "real" blocks as well as a corner case single-line
> blockwise selection.
> To reproduce:
> 
>     vim -N -u NONE
>     :set linebreak
>     :normal! 40afoo bar
>     :normal! BB^VeAX
> Appending should be after the selected word ("barfooX"), but it occurs
> at the beginning instead ("Xbarfoo").
> 
> I've bisected this down to the following patch:
> 
> ,----[ bad change ]----
> | 7.4.576  redrawing problem with 'relativenumber' and 'linebreak'
> `----
> 
> Attached is a test that verifies the correct behavior.
> 
> I can reproduce this on Vim version 7.4.716 on Windows/x64 as well as on
> latest Vim 7.4.729 on Linux/x64.
> 

I can reproduce it. Thanks for the feedback. Looks like one needs to 
recalculate the virtual column numbers after resetting the linebreak 
option. This also happens for the OP_REPLACE part. Here is a patch, 
including your testcase.

Best,
Christian
-- 
Wie man sein Kind nicht nennen sollte: 
  Kris Tal 

-- 
-- 
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/normal.c b/src/normal.c
--- a/src/normal.c
+++ b/src/normal.c
@@ -174,6 +174,7 @@ static void	nv_drop __ARGS((cmdarg_T *ca
 #ifdef FEAT_AUTOCMD
 static void	nv_cursorhold __ARGS((cmdarg_T *cap));
 #endif
+static void	get_op_vcol __ARGS((oparg_T *oap, colnr_T col));
 
 static char *e_noident = N_("E349: No identifier under cursor");
 
@@ -1629,61 +1630,7 @@ do_pending_operator(cap, old_col, gui_ya
 
 	if (VIsual_active || redo_VIsual_busy)
 	{
-	    if (VIsual_mode == Ctrl_V)	/* block mode */
-	    {
-		colnr_T	    start, end;
-
-		oap->block_mode = TRUE;
-
-		getvvcol(curwin, &(oap->start),
-				      &oap->start_vcol, NULL, &oap->end_vcol);
-		if (!redo_VIsual_busy)
-		{
-		    getvvcol(curwin, &(oap->end), &start, NULL, &end);
-
-		    if (start < oap->start_vcol)
-			oap->start_vcol = start;
-		    if (end > oap->end_vcol)
-		    {
-			if (*p_sel == 'e' && start >= 1
-						&& start - 1 >= oap->end_vcol)
-			    oap->end_vcol = start - 1;
-			else
-			    oap->end_vcol = end;
-		    }
-		}
-
-		/* if '$' was used, get oap->end_vcol from longest line */
-		if (curwin->w_curswant == MAXCOL)
-		{
-		    curwin->w_cursor.col = MAXCOL;
-		    oap->end_vcol = 0;
-		    for (curwin->w_cursor.lnum = oap->start.lnum;
-			    curwin->w_cursor.lnum <= oap->end.lnum;
-						      ++curwin->w_cursor.lnum)
-		    {
-			getvvcol(curwin, &curwin->w_cursor, NULL, NULL, &end);
-			if (end > oap->end_vcol)
-			    oap->end_vcol = end;
-		    }
-		}
-		else if (redo_VIsual_busy)
-		    oap->end_vcol = oap->start_vcol + redo_VIsual_vcol - 1;
-		/*
-		 * Correct oap->end.col and oap->start.col to be the
-		 * upper-left and lower-right corner of the block area.
-		 *
-		 * (Actually, this does convert column positions into character
-		 * positions)
-		 */
-		curwin->w_cursor.lnum = oap->end.lnum;
-		coladvance(oap->end_vcol);
-		oap->end = curwin->w_cursor;
-
-		curwin->w_cursor = oap->start;
-		coladvance(oap->start_vcol);
-		oap->start = curwin->w_cursor;
-	    }
+	    get_op_vcol(oap, redo_VIsual_vcol);
 
 	    if (!redo_VIsual_busy && !gui_yank)
 	    {
@@ -2088,7 +2035,11 @@ do_pending_operator(cap, old_col, gui_ya
 #ifdef FEAT_LINEBREAK
 		/* Restore linebreak, so that when the user edits it looks as
 		 * before. */
-		curwin->w_p_lbr = lbr_saved;
+		if (curwin->w_p_lbr != lbr_saved)
+		{
+		    curwin->w_p_lbr = lbr_saved;
+		    get_op_vcol(oap, redo_VIsual_mode);
+		}
 #endif
 		op_insert(oap, cap->count1);
 #ifdef FEAT_LINEBREAK
@@ -2123,7 +2074,11 @@ do_pending_operator(cap, old_col, gui_ya
 #ifdef FEAT_LINEBREAK
 		/* Restore linebreak, so that when the user edits it looks as
 		 * before. */
-		curwin->w_p_lbr = lbr_saved;
+		if (curwin->w_p_lbr != lbr_saved)
+		{
+		    curwin->w_p_lbr = lbr_saved;
+		    get_op_vcol(oap, redo_VIsual_mode);
+		}
 #endif
 		op_replace(oap, cap->nchar);
 	    }
@@ -9543,3 +9498,63 @@ nv_cursorhold(cap)
     cap->retval |= CA_COMMAND_BUSY;	/* don't call edit() now */
 }
 #endif
+
+/*
+ * calculate start/end virtual columns for operating in block mode
+ */
+    static void
+get_op_vcol(oap, redo_VIsual_vcol)
+    oparg_T	*oap;
+    colnr_T	redo_VIsual_vcol;
+{
+    colnr_T	    start, end;
+
+    if (VIsual_mode != Ctrl_V)
+	return;
+
+    oap->block_mode = TRUE;
+
+    getvvcol(curwin, &(oap->start), &oap->start_vcol, NULL, &oap->end_vcol);
+    getvvcol(curwin, &(oap->end), &start, NULL, &end);
+
+    if (start < oap->start_vcol)
+	oap->start_vcol = start;
+    if (end > oap->end_vcol)
+    {
+	if (*p_sel == 'e' && start >= 1
+				&& start - 1 >= oap->end_vcol)
+	    oap->end_vcol = start - 1;
+	else
+	    oap->end_vcol = end;
+    }
+    /* if '$' was used, get oap->end_vcol from longest line */
+    if (curwin->w_curswant == MAXCOL)
+    {
+	curwin->w_cursor.col = MAXCOL;
+	oap->end_vcol = 0;
+	for (curwin->w_cursor.lnum = oap->start.lnum;
+		curwin->w_cursor.lnum <= oap->end.lnum;
+					++curwin->w_cursor.lnum)
+	{
+	    getvvcol(curwin, &curwin->w_cursor, NULL, NULL, &end);
+	    if (end > oap->end_vcol)
+		oap->end_vcol = end;
+	}
+    }
+    else if (redo_VIsual_busy)
+	oap->end_vcol = oap->start_vcol + redo_VIsual_vcol - 1;
+    /*
+     * Correct oap->end.col and oap->start.col to be the
+     * upper-left and lower-right corner of the block area.
+     *
+     * (Actually, this does convert column positions into character
+     * positions)
+     */
+    curwin->w_cursor.lnum = oap->end.lnum;
+    coladvance(oap->end_vcol);
+    oap->end = curwin->w_cursor;
+
+    curwin->w_cursor = oap->start;
+    coladvance(oap->start_vcol);
+    oap->start = curwin->w_cursor;
+}
diff --git a/src/testdir/test_listlbr.in b/src/testdir/test_listlbr.in
--- a/src/testdir/test_listlbr.in
+++ b/src/testdir/test_listlbr.in
@@ -59,11 +59,17 @@ STARTTEST
 :set cpo&vim linebreak
 :let g:test ="Test 6: set linebreak with visual block mode"
 :let line="REMOVE: this not"
+:$put =g:test
 :$put =line
 :let line="REMOVE: aaaaaaaaaaaaa"
 :$put =line
 :1/^REMOVE:
 0jf x:$put
+:set cpo&vim linebreak
+:let g:test ="Test 7: set linebreak with visual block mode and v_b_A"
+:$put =g:test
+Golong line: 40afoobar aTARGET at end
+:exe "norm! $3B\<C-v>eAx\<Esc>"
 :%w! test.out
 :qa!
 ENDTEST
diff --git a/src/testdir/test_listlbr.ok b/src/testdir/test_listlbr.ok
--- a/src/testdir/test_listlbr.ok
+++ b/src/testdir/test_listlbr.ok
@@ -32,7 +32,10 @@ Sabbbbbb bla
 ~                   
 ~                   
 ~                   
+Test 6: set linebreak with visual block mode
 this not
 aaaaaaaaaaaaa
 REMOVE: 
 REMOVE: 
+Test 7: set linebreak with visual block mode and v_b_A
+long line: foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar TARGETx at end

Raspunde prin e-mail lui