On Wednesday, October 24, 2018 at 3:42:38 PM UTC+2, Tony Mechelynck wrote:
> On Wed, Oct 24, 2018 at 1:57 PM John Little <[email protected]> wrote:
> >
> > I noticed a problem today when editing a paragraph that was wrapped to
> > several lines on screen. To reproduce, use a file with a line with normal
> > prose text that wraps to several screen lines, say x.txt, then
> >
> > vim -u NONE -c "set linebreak showbreak=....>" x.txt
> >
> > Move to the end of the long line, start a block selection with ctrl-V,
> > press y to yank it. The yanked text will be from an earlier part of the
> > line, not the text in the block selection. The offset increases with the
> > amount of space showing on the right of the text, space that without the
> > 'linebreak' option would not be blank. It doesn't happen with v for a
> > character selection.
> >
> > I bisected my .vimrc to find the settings triggering the problem, then used
> > git bisect to find the problem was introduced with v7.4.576:
> >
> > Date: Wed Jan 14 17:52:30 2015 +0100
> >
> > updated for version 7.4.576
> > Problem: Redrawing problem with 'relativenumber' and 'linebreak'.
> > Solution: Temporarily reset 'linebreak' and restore it in more places.
> > (Christian Brabandt)
> >
> > I could give a more detailed example, but Google groups might wrap it into
> > a confusing mess.
> >
> > I suppose that using a block selection for part of a line that is wrapped
> > with 'linebreak' is marginally useful so this problem is very minor.
> >
> > Regards, John Little
>
>
> I confirm the problem, and in addition, when yanking a visual block
> extending over the common part (near, but not after, the end) of
> several successive long lines all wrapped with 'linebreak', the value
> that appears in the register after the yank is not only from an
> earlier part of the lines but of a different width than the highlight
> (which is displayed at the same visual abscissa, and thus not at the
> same distance from start-of-line, in all the lines over which it
> extends). If the selected block is shortly after a 'linebreak' wrap,
> the yanked text may even include some "virtual spaces" generated by
> 'linebreak' to wrap the line at a 'breakat' character.
>
> The difference in width is not explained by the difference in bytes
> for different UTF-8 characters: for instance in one file, after ":set
> lbr sbr=---\|" (not my usual setting) I see two consecutive file lines
> whose second screen lines start as:
>
> ---|href="#sryvatj">срыва́ть</a>
> ---|cou, un(e) risque-tout.</p>
>
> including the ---| 'showbreak' value. By block-selecting the /a
> together with the /p (a 2x2 block, all in ASCII) then yanking, I get
> atj">срыва́т^Jrisque-tout (which is rectangular in terms of
> characters, not bytes; but much longer) into the register. The excess
> length corresponds approximately AFAICT to the sum amount of virtual
> whitespace added by 'linebreak' at the end of both previous screen
> lines.
>
> (That file is online as part of my "Russian-French dictionary"
> project; the lines in question are lines 3131-3132 of
> http://users.skynet.be/antoine.mechelynck/slovarj/ru-fr.18.html as
> displayed in a full-screen gvim with
> encoding=utf-8
> lines=68
> columns=174
> guifont=Bitstream Vera Sans Mono 8
> linebreak
> showbreak=---|
> ).
>
> Try it, it is easier to see than to explain.
>
> Best regards,
> Tony.
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
--
--
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.
>From e1f2d9270b077f072e3ac7652aa8cdb0c4b2fe76 Mon Sep 17 00:00:00 2001
From: tom <tom@debian9>
Date: Wed, 14 Nov 2018 22:07:40 +0100
Subject: [PATCH] support showbreak and linebreak in visual block ops
---
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 | 96 +++++++++++++++++++++++++++++++++++++++------------
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, 223 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..1cde1b0bb 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,20 @@ 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;
+ // FIXME: FALSE or TRUE ???
+// get_op_vcol(oap, redo_VIsual_mode, FALSE);
+ }
+#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 +1907,19 @@ 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;
+ // FIXME: FALSE or TRUE ???
+// get_op_vcol(oap, redo_VIsual_mode, FALSE);
+ }
#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 +1946,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 +2004,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 +2061,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 +2098,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 +2751,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 +4985,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 +5006,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 +6482,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 +9699,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;
@@ -9662,6 +9711,7 @@ get_op_vcol(
{
if (initial && *p_sel == 'e' && start >= 1
&& start - 1 >= oap->end_vcol)
+ // FIXME: does this need fixing???
oap->end_vcol = start - 1;
else
oap->end_vcol = end;
@@ -9677,7 +9727,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