Skip to content

Commit 2c03ee0

Browse files
brammooldouglaskayama
authored andcommitted
patch 7.4.753 Problem: Appending in Visual mode with 'linebreak' set does not work properly. Also when 'selection' is "exclusive". (Ingo Karkat) Solution: Recalculate virtual columns. (Christian Brabandt)
1 parent c995a66 commit 2c03ee0

6 files changed

Lines changed: 112 additions & 60 deletions

File tree

src/normal.c

Lines changed: 88 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ static void nv_drop __ARGS((cmdarg_T *cap));
174174
#ifdef FEAT_AUTOCMD
175175
static void nv_cursorhold __ARGS((cmdarg_T *cap));
176176
#endif
177+
static void get_op_vcol __ARGS((oparg_T *oap, colnr_T col, int initial));
177178

178179
static char *e_noident = N_("E349: No identifier under cursor");
179180

@@ -1418,6 +1419,8 @@ do_pending_operator(cap, old_col, gui_yank)
14181419
{
14191420
#ifdef FEAT_LINEBREAK
14201421
/* Avoid a problem with unwanted linebreaks in block mode. */
1422+
if (curwin->w_p_lbr)
1423+
curwin->w_valid &= ~VALID_VIRTCOL;
14211424
curwin->w_p_lbr = FALSE;
14221425
#endif
14231426
oap->is_VIsual = VIsual_active;
@@ -1631,61 +1634,7 @@ do_pending_operator(cap, old_col, gui_yank)
16311634

16321635
if (VIsual_active || redo_VIsual_busy)
16331636
{
1634-
if (VIsual_mode == Ctrl_V) /* block mode */
1635-
{
1636-
colnr_T start, end;
1637-
1638-
oap->block_mode = TRUE;
1639-
1640-
getvvcol(curwin, &(oap->start),
1641-
&oap->start_vcol, NULL, &oap->end_vcol);
1642-
if (!redo_VIsual_busy)
1643-
{
1644-
getvvcol(curwin, &(oap->end), &start, NULL, &end);
1645-
1646-
if (start < oap->start_vcol)
1647-
oap->start_vcol = start;
1648-
if (end > oap->end_vcol)
1649-
{
1650-
if (*p_sel == 'e' && start >= 1
1651-
&& start - 1 >= oap->end_vcol)
1652-
oap->end_vcol = start - 1;
1653-
else
1654-
oap->end_vcol = end;
1655-
}
1656-
}
1657-
1658-
/* if '$' was used, get oap->end_vcol from longest line */
1659-
if (curwin->w_curswant == MAXCOL)
1660-
{
1661-
curwin->w_cursor.col = MAXCOL;
1662-
oap->end_vcol = 0;
1663-
for (curwin->w_cursor.lnum = oap->start.lnum;
1664-
curwin->w_cursor.lnum <= oap->end.lnum;
1665-
++curwin->w_cursor.lnum)
1666-
{
1667-
getvvcol(curwin, &curwin->w_cursor, NULL, NULL, &end);
1668-
if (end > oap->end_vcol)
1669-
oap->end_vcol = end;
1670-
}
1671-
}
1672-
else if (redo_VIsual_busy)
1673-
oap->end_vcol = oap->start_vcol + redo_VIsual_vcol - 1;
1674-
/*
1675-
* Correct oap->end.col and oap->start.col to be the
1676-
* upper-left and lower-right corner of the block area.
1677-
*
1678-
* (Actually, this does convert column positions into character
1679-
* positions)
1680-
*/
1681-
curwin->w_cursor.lnum = oap->end.lnum;
1682-
coladvance(oap->end_vcol);
1683-
oap->end = curwin->w_cursor;
1684-
1685-
curwin->w_cursor = oap->start;
1686-
coladvance(oap->start_vcol);
1687-
oap->start = curwin->w_cursor;
1688-
}
1637+
get_op_vcol(oap, redo_VIsual_vcol, TRUE);
16891638

16901639
if (!redo_VIsual_busy && !gui_yank)
16911640
{
@@ -1982,7 +1931,11 @@ do_pending_operator(cap, old_col, gui_yank)
19821931
#ifdef FEAT_LINEBREAK
19831932
/* Restore linebreak, so that when the user edits it looks as
19841933
* before. */
1985-
curwin->w_p_lbr = lbr_saved;
1934+
if (curwin->w_p_lbr != lbr_saved)
1935+
{
1936+
curwin->w_p_lbr = lbr_saved;
1937+
get_op_vcol(oap, redo_VIsual_mode, FALSE);
1938+
}
19861939
#endif
19871940
/* Reset finish_op now, don't want it set inside edit(). */
19881941
finish_op = FALSE;
@@ -2082,7 +2035,11 @@ do_pending_operator(cap, old_col, gui_yank)
20822035
#ifdef FEAT_LINEBREAK
20832036
/* Restore linebreak, so that when the user edits it looks as
20842037
* before. */
2085-
curwin->w_p_lbr = lbr_saved;
2038+
if (curwin->w_p_lbr != lbr_saved)
2039+
{
2040+
curwin->w_p_lbr = lbr_saved;
2041+
get_op_vcol(oap, redo_VIsual_mode, FALSE);
2042+
}
20862043
#endif
20872044
op_insert(oap, cap->count1);
20882045
#ifdef FEAT_LINEBREAK
@@ -2114,11 +2071,15 @@ do_pending_operator(cap, old_col, gui_yank)
21142071
#ifdef FEAT_VISUALEXTRA
21152072
else
21162073
{
2117-
#ifdef FEAT_LINEBREAK
2074+
# ifdef FEAT_LINEBREAK
21182075
/* Restore linebreak, so that when the user edits it looks as
21192076
* before. */
2120-
curwin->w_p_lbr = lbr_saved;
2121-
#endif
2077+
if (curwin->w_p_lbr != lbr_saved)
2078+
{
2079+
curwin->w_p_lbr = lbr_saved;
2080+
get_op_vcol(oap, redo_VIsual_mode, FALSE);
2081+
}
2082+
# endif
21222083
op_replace(oap, cap->nchar);
21232084
}
21242085
#endif
@@ -9576,3 +9537,70 @@ nv_cursorhold(cap)
95769537
cap->retval |= CA_COMMAND_BUSY; /* don't call edit() now */
95779538
}
95789539
#endif
9540+
9541+
/*
9542+
* calculate start/end virtual columns for operating in block mode
9543+
*/
9544+
static void
9545+
get_op_vcol(oap, redo_VIsual_vcol, initial)
9546+
oparg_T *oap;
9547+
colnr_T redo_VIsual_vcol;
9548+
int initial; /* when true: adjust position for 'selectmode' */
9549+
{
9550+
colnr_T start, end;
9551+
9552+
if (VIsual_mode != Ctrl_V)
9553+
return;
9554+
9555+
oap->block_mode = TRUE;
9556+
9557+
#ifdef FEAT_MBYTE
9558+
/* prevent from moving onto a trail byte */
9559+
if (has_mbyte)
9560+
mb_adjustpos(curwin->w_buffer, &oap->end);
9561+
#endif
9562+
9563+
getvvcol(curwin, &(oap->start), &oap->start_vcol, NULL, &oap->end_vcol);
9564+
getvvcol(curwin, &(oap->end), &start, NULL, &end);
9565+
9566+
if (start < oap->start_vcol)
9567+
oap->start_vcol = start;
9568+
if (end > oap->end_vcol)
9569+
{
9570+
if (initial && *p_sel == 'e' && start >= 1
9571+
&& start - 1 >= oap->end_vcol)
9572+
oap->end_vcol = start - 1;
9573+
else
9574+
oap->end_vcol = end;
9575+
}
9576+
/* if '$' was used, get oap->end_vcol from longest line */
9577+
if (curwin->w_curswant == MAXCOL)
9578+
{
9579+
curwin->w_cursor.col = MAXCOL;
9580+
oap->end_vcol = 0;
9581+
for (curwin->w_cursor.lnum = oap->start.lnum;
9582+
curwin->w_cursor.lnum <= oap->end.lnum;
9583+
++curwin->w_cursor.lnum)
9584+
{
9585+
getvvcol(curwin, &curwin->w_cursor, NULL, NULL, &end);
9586+
if (end > oap->end_vcol)
9587+
oap->end_vcol = end;
9588+
}
9589+
}
9590+
else if (redo_VIsual_busy)
9591+
oap->end_vcol = oap->start_vcol + redo_VIsual_vcol - 1;
9592+
/*
9593+
* Correct oap->end.col and oap->start.col to be the
9594+
* upper-left and lower-right corner of the block area.
9595+
*
9596+
* (Actually, this does convert column positions into character
9597+
* positions)
9598+
*/
9599+
curwin->w_cursor.lnum = oap->end.lnum;
9600+
coladvance(oap->end_vcol);
9601+
oap->end = curwin->w_cursor;
9602+
9603+
curwin->w_cursor = oap->start;
9604+
coladvance(oap->start_vcol);
9605+
oap->start = curwin->w_cursor;
9606+
}

src/testdir/test_listlbr.in

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,21 @@ STARTTEST
5959
:set cpo&vim linebreak
6060
:let g:test ="Test 6: set linebreak with visual block mode"
6161
:let line="REMOVE: this not"
62+
:$put =g:test
6263
:$put =line
6364
:let line="REMOVE: aaaaaaaaaaaaa"
6465
:$put =line
6566
:1/^REMOVE:
6667
0jf x:$put
68+
:set cpo&vim linebreak
69+
:let g:test ="Test 7: set linebreak with visual block mode and v_b_A"
70+
:$put =g:test
71+
Golong line: 40afoobar aTARGET at end
72+
:exe "norm! $3B\<C-v>eAx\<Esc>"
73+
:set cpo&vim linebreak sbr=
74+
:let g:test ="Test 8: set linebreak with visual char mode and changing block"
75+
:$put =g:test
76+
Go1111-1111-1111-11-1111-1111-11110f-lv3lc2222bgj.
6777
:%w! test.out
6878
:qa!
6979
ENDTEST

src/testdir/test_listlbr.ok

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,12 @@ Sabbbbbb bla
3232
~
3333
~
3434
~
35+
Test 6: set linebreak with visual block mode
3536
this not
3637
aaaaaaaaaaaaa
3738
REMOVE:
3839
REMOVE:
40+
Test 7: set linebreak with visual block mode and v_b_A
41+
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
42+
Test 8: set linebreak with visual char mode and changing block
43+
1111-2222-1111-11-1111-2222-1111

src/testdir/test_listlbr_utf8.in

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,11 @@ GGlGGlGGlGGlGGlGGlGGlGGlGGlGGl
9191
:else
9292
: call append('$', "Not all attributes are different")
9393
:endif
94+
:set cpo&vim linebreak selection=exclusive
95+
:let g:test ="Test 8: set linebreak with visual block mode and v_b_A and selection=exclusive and multibyte char"
96+
:$put =g:test
97+
Golong line: 40afoobar aTARGETÃ' at end
98+
:exe "norm! $3B\<C-v>eAx\<Esc>"
9499
:%w! test.out
95100
:qa!
96101
ENDTEST

src/testdir/test_listlbr_utf8.ok

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,5 @@ Test 6: Screenattributes for comment
4444
/* and some more */
4545
ScreenAttributes for test6:
4646
Attribut 0 and 1 and 3 and 5 are different!
47+
Test 8: set linebreak with visual block mode and v_b_A and selection=exclusive and multibyte char
48+
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 TARGETÃx' at end

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,8 @@ static char *(features[]) =
756756

757757
static int included_patches[] =
758758
{ /* Add new patch number below this line */
759+
/**/
760+
753,
759761
/**/
760762
752,
761763
/**/

0 commit comments

Comments
 (0)