On Fr, 09 Mai 2014, Ken Takata wrote:
> Hi Christian,
>
> 2014/5/9 Fri 7:06:49 UTC+9 Christian Brabandt wrote:
> > Hi Ken!
> >
> > On Mi, 07 Mai 2014, Ken Takata wrote:
> >
> > > 2014/5/8 Thu 6:50:22 UTC+9 Christian Brabandt wrote:
> > > > Hi,
> > > > here is an updated breakindent patch (breakindent_patch.diff) for
> > > > current Vim. Changes include:
> > > >
> > > > - displaywidth() function has an optional parameter, that takes the
> > > > indent for that particular line into account
> > > > - correctly check for 'relativenumber' option (and not only number
> > > > option)
> > > > - in diff mode, highlight the indent accordingly. (Note: In diff
> > > > mode, there seems to be a bug in Vim, that the filler lines are
> > > > not correctly calculated, when wrap is on. This needs to be fixed
> > > > independently of this patch, not that wrapping makes much sense
> > > > in
> > > > diff mode anyhow)
> > > > - style adjusted to match more the Vim style
> > > >
> > > > Since I personally prefer, that the 'sbr' setting will still be drawn
> > > > at
> > > > the start of the screen line, rather then after the indent, here is a
> > > > second patch (sbr_linestart_breakindent.diff), that makes this the
> > > > default. This patch needs to be applied after the
> > > > breakindent_patch.diff.
> > > >
> > > > Here is an example:
> > > > The original patch does this:
> > > >
> > > > ,----
> > > > | Lorem ipsum dolor sit amet,
> > > > | consetetur sadipscing elitr,
> > > > | sed
> > > > | Lorem ipsum dolor sit amet,
> > > > | >>consetetur sadipscing elitr,
> > > > | >>sed
> > > > `----
> > > >
> > > > While the second version makes it more like this:
> > > > ,----
> > > > | Lorem ipsum dolor sit amet,
> > > > | consetetur sadipscing elitr,
> > > > | sed
> > > > | Lorem ipsum dolor sit amet,
> > > > |>> consetetur sadipscing elitr,
> > > > |>> sed
> > > > `----
> > > >
> > > > Any opinions on where the 'sbr' should be drawn (should this be put
> > > > into
> > > > another option)?
> > > >
> > > > Please test this patch and report problems.
> > > >
> > > > Bram, would you be willing to include this feature?
> > >
> > > I already sent another updated breakindent patch which also fixes
> > > coding style:
> > > https://groups.google.com/d/msg/vim_dev/SML3mtGd50s/VDvFN11MwcEJ
> > > (And minor updated version is available at here:
> > > https://bitbucket.org/k_takata/vim-ktakata-mq/src/f8c3f9f5de704bc74a9d61fc633ecd2266b10d0a/vim-7.4.178-breakindent.patch)
> >
> > Sorry, I didn't see this.
> >
> > Here is a merged patch, including some more improvements:
> > - 'breakindentshift' wasn't copied to a new window
> > - Diff mode didn't work correctly (lines after filler lines could be
> > indented incorrectly)
> > - Highlight in diff mode correctly
> >
> > 1 Question remains:
> > - Where to draw the 'sbr' setting? Does anybody have an opinion on that?
>
> Thank you!
> But I found some style issues. Here is an updated patch. Please check.
> (sbr_linestart_breakindent.diff is not updated, sorry.)
Thanks, I enhanced it further. You can adjust the behaviour now using
:set breakindentopt
>
> I think that the following two hunks are not needed, so I removed them.
> If I was wrong, please restore them.
Yes, that was wrong. Sorry about that.
Mit freundlichen Grüßen
Christian
--
Wer sich zu sicher ist, gerät leicht in einen alltäglichen Trott.
-- H. und S. Schumacher
--
--
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/runtime/doc/eval.txt b/runtime/doc/eval.txt
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -1979,7 +1979,8 @@ sqrt( {expr}) Float square root of {ex
str2float( {expr}) Float convert String to Float
str2nr( {expr} [, {base}]) Number convert String to Number
strchars( {expr}) Number character length of the String {expr}
-strdisplaywidth( {expr} [, {col}]) Number display length of the String {expr}
+strdisplaywidth( {expr} [, {col} [, {lnum}]])
+ Number display length of the String {expr}
strftime( {format}[, {time}]) String time in specified format
stridx( {haystack}, {needle}[, {start}])
Number index of {needle} in {haystack}
@@ -5698,13 +5699,15 @@ strchars({expr}) *strchars()*
separately.
Also see |strlen()|, |strdisplaywidth()| and |strwidth()|.
-strdisplaywidth({expr}[, {col}]) *strdisplaywidth()*
+strdisplaywidth({expr}[, {col}[, {lnum}]]) *strdisplaywidth()*
The result is a Number, which is the number of display cells
String {expr} occupies on the screen when it starts a {col}.
When {col} is omitted zero is used. Otherwise it is the
- screen column where to start. This matters for Tab
- characters.
- The option settings of the current window are used. This
+ screen column where to start. This matters for Tab chars
+
+ When {lnum} is omitted the cursor line is used. Otherwise
+ it is the line where to start. This matters for the indent.
+ The option settings of the current window are used. This
matters for anything that's displayed differently, such as
'tabstop' and 'display'.
When {expr} contains characters with East Asian Width Class
@@ -6553,8 +6556,8 @@ jumplist Compiled with |jumplist| suppo
keymap Compiled with 'keymap' support.
langmap Compiled with 'langmap' support.
libcall Compiled with |libcall()| support.
-linebreak Compiled with 'linebreak', 'breakat' and 'showbreak'
- support.
+linebreak Compiled with 'linebreak', 'breakat', 'showbreak' and
+ 'breakindent' support.
lispindent Compiled with support for lisp indenting.
listcmds Compiled with commands for the buffer list |:files|
and the argument list |arglist|.
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -1200,6 +1200,38 @@ A jump table for the options with a shor
break if 'linebreak' is on. Only works for ASCII and also for 8-bit
characters when 'encoding' is an 8-bit encoding.
+ *'breakindent'* *'bri'*
+'breakindent' 'bri' boolean (default off)
+ local to window
+ {not in Vi}
+ {not available when compiled without the |+linebreak|
+ feature}
+ Every wrapped line will continue visually indented (same amount of
+ space as the beginning of that line), thus preserving horizontal blocks
+ of text.
+
+ *'breakindentmin'* *'brimin'*
+'breakindentopt' 'briopt' string (default "min:20,shift:0")
+ local to window
+ {not in Vi}
+ {not available when compiled without the |+linebreak|
+ feature}
+ Settings for 'breakindent'. It can consist of the following optional
+ items and must be seperated by a comma:
+ min:{n} Minimum text width that will be kept after
+ applying 'breakindent', even if the resulting
+ text should normally be narrower. This prevents
+ text indented almost to the right window border
+ occupying lot of vertical space when broken.
+ shift:{n} After applying 'breakindent', wrapped line
+ beginning will be shift by given number of
+ characters. It permits dynamic French paragraph
+ indentation (negative) or emphasizing the line
+ continuation (positive).
+ sbr Display the 'showbreak' value before applying the
+ additional indent.
+ If empty, the default for min is 20 and shift is 0
+
*'browsedir'* *'bsdir'*
'browsedir' 'bsdir' string (default: "last")
global
@@ -4572,12 +4604,13 @@ A jump table for the options with a shor
{not in Vi}
{not available when compiled without the |+linebreak|
feature}
- If on Vim will wrap long lines at a character in 'breakat' rather
+ If on, Vim will wrap long lines at a character in 'breakat' rather
than at the last character that fits on the screen. Unlike
'wrapmargin' and 'textwidth', this does not insert <EOL>s in the file,
- it only affects the way the file is displayed, not its contents. The
- value of 'showbreak' is used to put in front of wrapped lines.
- This option is not used when the 'wrap' option is off or 'list' is on.
+ it only affects the way the file is displayed, not its contents.
+ If 'breakindent' is set, line is visually indented. Then, the value
+ of 'showbreak' is used to put in front of wrapped lines. This option
+ is not used when the 'wrap' option is off or 'list' is on.
Note that <Tab> characters after an <EOL> are mostly not displayed
with the right amount of white space.
diff --git a/runtime/optwin.vim b/runtime/optwin.vim
--- a/runtime/optwin.vim
+++ b/runtime/optwin.vim
@@ -324,6 +324,12 @@ call <SID>BinOptionG("wrap", &wrap)
call append("$", "linebreak\twrap long lines at a character in 'breakat'")
call append("$", "\t(local to window)")
call <SID>BinOptionL("lbr")
+call append("$", "breakindent\tpreserve indentation in wrapped text")
+call append("$", "\t(local to window)")
+call <SID>BinOptionL("bri")
+call append("$", "breakindentopt\tadjust breakindent behaviour")
+call append("$", "\t(local to window)")
+call <SID>OptionL("briopt")
call append("$", "breakat\twhich characters might cause a line break")
call <SID>OptionG("brk", &brk)
call append("$", "showbreak\tstring to put before wrapped screen lines")
diff --git a/src/buffer.c b/src/buffer.c
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -2700,6 +2700,9 @@ get_winopts(buf)
#ifdef FEAT_SYN_HL
check_colorcolumn(curwin);
#endif
+#ifdef FEAT_LINEBREAK
+ briopt_changed();
+#endif
}
/*
diff --git a/src/charset.c b/src/charset.c
--- a/src/charset.c
+++ b/src/charset.c
@@ -852,24 +852,26 @@ win_chartabsize(wp, p, col)
* taking into account the size of a tab.
*/
int
-linetabsize(s)
+linetabsize(s, lnum)
char_u *s;
+ linenr_T lnum;
{
- return linetabsize_col(0, s);
+ return linetabsize_col(0, s, lnum);
}
/*
* Like linetabsize(), but starting at column "startcol".
*/
int
-linetabsize_col(startcol, s)
+linetabsize_col(startcol, s, lnum)
int startcol;
char_u *s;
+ linenr_T lnum;
{
colnr_T col = startcol;
while (*s != NUL)
- col += lbr_chartabsize_adv(&s, col);
+ col += lbr_chartabsize_adv(&s, col, lnum);
return (int)col;
}
@@ -877,16 +879,17 @@ linetabsize_col(startcol, s)
* Like linetabsize(), but for a given window instead of the current one.
*/
int
-win_linetabsize(wp, p, len)
+win_linetabsize(wp, p, len, lnum)
win_T *wp;
char_u *p;
colnr_T len;
+ linenr_T lnum;
{
colnr_T col = 0;
char_u *s;
for (s = p; *s != NUL && (len == MAXCOL || s < p + len); mb_ptr_adv(s))
- col += win_lbr_chartabsize(wp, s, col, NULL);
+ col += win_lbr_chartabsize(wp, s, col, NULL, lnum);
return (int)col;
}
@@ -1021,12 +1024,13 @@ vim_isprintc_strict(c)
* like chartabsize(), but also check for line breaks on the screen
*/
int
-lbr_chartabsize(s, col)
+lbr_chartabsize(s, col, lnum)
unsigned char *s;
colnr_T col;
+ linenr_T lnum;
{
#ifdef FEAT_LINEBREAK
- if (!curwin->w_p_lbr && *p_sbr == NUL)
+ if (!curwin->w_p_lbr && *p_sbr == NUL && !curwin->w_p_bri)
{
#endif
#ifdef FEAT_MBYTE
@@ -1036,7 +1040,7 @@ lbr_chartabsize(s, col)
RET_WIN_BUF_CHARTABSIZE(curwin, curbuf, s, col)
#ifdef FEAT_LINEBREAK
}
- return win_lbr_chartabsize(curwin, s, col, NULL);
+ return win_lbr_chartabsize(curwin, s, col, NULL, lnum);
#endif
}
@@ -1044,13 +1048,14 @@ lbr_chartabsize(s, col)
* Call lbr_chartabsize() and advance the pointer.
*/
int
-lbr_chartabsize_adv(s, col)
+lbr_chartabsize_adv(s, col, lnum)
char_u **s;
colnr_T col;
+ linenr_T lnum;
{
int retval;
- retval = lbr_chartabsize(*s, col);
+ retval = lbr_chartabsize(*s, col, lnum);
mb_ptr_adv(*s);
return retval;
}
@@ -1061,13 +1066,17 @@ lbr_chartabsize_adv(s, col)
* If "headp" not NULL, set *headp to the size of what we for 'showbreak'
* string at start of line. Warning: *headp is only set if it's a non-zero
* value, init to 0 before calling.
+ *
+ * linenr argument needed if in visual highlighting and breakindent=on, then
+ * the line calculated is not current; if 0, normal functionality is preserved.
*/
int
-win_lbr_chartabsize(wp, s, col, headp)
+win_lbr_chartabsize(wp, s, col, headp, lnum)
win_T *wp;
char_u *s;
colnr_T col;
int *headp UNUSED;
+ linenr_T lnum;
{
#ifdef FEAT_LINEBREAK
int c;
@@ -1086,9 +1095,9 @@ win_lbr_chartabsize(wp, s, col, headp)
int n;
/*
- * No 'linebreak' and 'showbreak': return quickly.
+ * No 'linebreak', 'showbreak' and 'breakindent': return quickly.
*/
- if (!wp->w_p_lbr && *p_sbr == NUL)
+ if (!wp->w_p_lbr && !wp->w_p_bri && *p_sbr == NUL)
#endif
{
#ifdef FEAT_MBYTE
@@ -1163,11 +1172,12 @@ win_lbr_chartabsize(wp, s, col, headp)
# endif
/*
- * May have to add something for 'showbreak' string at start of line
+ * May have to add something for 'breakindent' and/or 'showbreak'
+ * string at start of line.
* Set *headp to the size of what we add.
*/
added = 0;
- if (*p_sbr != NUL && wp->w_p_wrap && col != 0)
+ if ((*p_sbr != NUL || wp->w_p_bri) && wp->w_p_wrap && col != 0)
{
numberextra = win_col_off(wp);
col += numberextra + mb_added;
@@ -1180,7 +1190,12 @@ win_lbr_chartabsize(wp, s, col, headp)
}
if (col == 0 || col + size > (colnr_T)W_WIDTH(wp))
{
- added = vim_strsize(p_sbr);
+ added = 0;
+ if (*p_sbr != NUL)
+ added += vim_strsize(p_sbr);
+ if (wp->w_p_bri)
+ added += get_breakindent_win(wp, lnum);
+
if (tab_corr)
size += (added / wp->w_buffer->b_p_ts) * wp->w_buffer->b_p_ts;
else
@@ -1288,12 +1303,13 @@ getvcol(wp, pos, start, cursor, end)
/*
* This function is used very often, do some speed optimizations.
- * When 'list', 'linebreak' and 'showbreak' are not set use a simple loop.
+ * When 'list', 'linebreak', 'showbreak' and 'breakindent' are not set
+ * use a simple loop.
* Also use this when 'list' is set but tabs take their normal size.
*/
if ((!wp->w_p_list || lcs_tab1 != NUL)
#ifdef FEAT_LINEBREAK
- && !wp->w_p_lbr && *p_sbr == NUL
+ && !wp->w_p_lbr && *p_sbr == NUL && !wp->w_p_bri
#endif
)
{
@@ -1355,7 +1371,7 @@ getvcol(wp, pos, start, cursor, end)
{
/* A tab gets expanded, depending on the current column */
head = 0;
- incr = win_lbr_chartabsize(wp, ptr, vcol, &head);
+ incr = win_lbr_chartabsize(wp, ptr, vcol, &head, pos->lnum);
/* make sure we don't go past the end of the line */
if (*ptr == NUL)
{
diff --git a/src/edit.c b/src/edit.c
--- a/src/edit.c
+++ b/src/edit.c
@@ -430,7 +430,7 @@ edit(cmdchar, startln, count)
if (startln)
Insstart.col = 0;
}
- Insstart_textlen = (colnr_T)linetabsize(ml_get_curline());
+ Insstart_textlen = (colnr_T)linetabsize(ml_get_curline(), Insstart.lnum);
Insstart_blank_vcol = MAXCOL;
if (!did_ai)
ai_col = 0;
@@ -1956,7 +1956,8 @@ change_indent(type, amount, round, repla
else
#endif
++new_cursor_col;
- vcol += lbr_chartabsize(ptr + new_cursor_col, (colnr_T)vcol);
+ vcol += lbr_chartabsize(ptr + new_cursor_col, (colnr_T)vcol,
+ curwin->w_cursor.lnum);
}
vcol = last_vcol;
@@ -6766,7 +6767,8 @@ stop_arrow()
ins_need_undo = FALSE;
}
Insstart = curwin->w_cursor; /* new insertion starts here */
- Insstart_textlen = (colnr_T)linetabsize(ml_get_curline());
+ Insstart_textlen = (colnr_T)linetabsize(ml_get_curline(),
+ curwin->w_cursor.lnum);
ai_col = 0;
#ifdef FEAT_VREPLACE
if (State & VREPLACE_FLAG)
@@ -7121,9 +7123,10 @@ oneleft()
for (;;)
{
coladvance(v - width);
- /* getviscol() is slow, skip it when 'showbreak' is empty and
- * there are no multi-byte characters */
- if ((*p_sbr == NUL
+ /* getviscol() is slow, skip it when 'showbreak' is empty,
+ * 'breakindent' is not set and there are no multi-byte
+ * characters */
+ if ((*p_sbr == NUL && !curwin->w_p_bri
# ifdef FEAT_MBYTE
&& !has_mbyte
# endif
@@ -9753,11 +9756,11 @@ ins_tab()
getvcol(curwin, &fpos, &vcol, NULL, NULL);
getvcol(curwin, cursor, &want_vcol, NULL, NULL);
- /* Use as many TABs as possible. Beware of 'showbreak' and
- * 'linebreak' adding extra virtual columns. */
+ /* Use as many TABs as possible. Beware of 'breakindent', 'showbreak'
+ * and 'linebreak' adding extra virtual columns. */
while (vim_iswhite(*ptr))
{
- i = lbr_chartabsize((char_u *)"\t", vcol);
+ i = lbr_chartabsize((char_u *)"\t", vcol, cursor->lnum);
if (vcol + i > want_vcol)
break;
if (*ptr != TAB)
@@ -9783,7 +9786,7 @@ ins_tab()
/* Skip over the spaces we need. */
while (vcol < want_vcol && *ptr == ' ')
{
- vcol += lbr_chartabsize(ptr, vcol);
+ vcol += lbr_chartabsize(ptr, vcol, cursor->lnum);
++ptr;
++repl_off;
}
@@ -10039,7 +10042,7 @@ ins_copychar(lnum)
while ((colnr_T)temp < curwin->w_virtcol && *ptr != NUL)
{
prev_ptr = ptr;
- temp += lbr_chartabsize_adv(&ptr, (colnr_T)temp);
+ temp += lbr_chartabsize_adv(&ptr, (colnr_T)temp, lnum);
}
if ((colnr_T)temp > curwin->w_virtcol)
ptr = prev_ptr;
diff --git a/src/eval.c b/src/eval.c
--- a/src/eval.c
+++ b/src/eval.c
@@ -8125,7 +8125,7 @@ static struct fst
#endif
{"str2nr", 1, 2, f_str2nr},
{"strchars", 1, 1, f_strchars},
- {"strdisplaywidth", 1, 2, f_strdisplaywidth},
+ {"strdisplaywidth", 1, 3, f_strdisplaywidth},
#ifdef HAVE_STRFTIME
{"strftime", 1, 2, f_strftime},
#endif
@@ -17842,11 +17842,17 @@ f_strdisplaywidth(argvars, rettv)
{
char_u *s = get_tv_string(&argvars[0]);
int col = 0;
+ linenr_T lnum = 0;
if (argvars[1].v_type != VAR_UNKNOWN)
+ {
col = get_tv_number(&argvars[1]);
- rettv->vval.v_number = (varnumber_T)(linetabsize_col(col, s) - col);
+ if (argvars[2].v_type != VAR_UNKNOWN)
+ lnum = get_tv_lnum(&argvars[2]);
+ }
+
+ rettv->vval.v_number = (varnumber_T)(linetabsize_col(col, s, lnum) - col);
}
/*
diff --git a/src/ex_cmds.c b/src/ex_cmds.c
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -261,7 +261,7 @@ linelen(has_tab)
;
save = *last;
*last = NUL;
- len = linetabsize(line); /* get line length */
+ len = linetabsize(line, curwin->w_cursor.lnum); /* get line length */
if (has_tab != NULL) /* check for embedded TAB */
*has_tab = (vim_strrchr(first, TAB) != NULL);
*last = save;
diff --git a/src/getchar.c b/src/getchar.c
--- a/src/getchar.c
+++ b/src/getchar.c
@@ -2676,7 +2676,8 @@ vgetorpeek(advance)
if (!vim_iswhite(ptr[col]))
curwin->w_wcol = vcol;
vcol += lbr_chartabsize(ptr + col,
- (colnr_T)vcol);
+ (colnr_T)vcol,
+ curwin->w_cursor.lnum);
#ifdef FEAT_MBYTE
if (has_mbyte)
col += (*mb_ptr2len)(ptr + col);
diff --git a/src/gui_beval.c b/src/gui_beval.c
--- a/src/gui_beval.c
+++ b/src/gui_beval.c
@@ -335,7 +335,7 @@ get_beval_info(beval, getword, winp, lnu
{
/* Not past end of the file. */
lbuf = ml_get_buf(wp->w_buffer, lnum, FALSE);
- if (col <= win_linetabsize(wp, lbuf, (colnr_T)MAXCOL))
+ if (col <= win_linetabsize(wp, lbuf, (colnr_T)MAXCOL, lnum))
{
/* Not past end of line. */
if (getword)
diff --git a/src/misc1.c b/src/misc1.c
--- a/src/misc1.c
+++ b/src/misc1.c
@@ -476,6 +476,48 @@ get_number_indent(lnum)
return (int)col;
}
+#ifdef FEAT_LINEBREAK
+/*
+ * Return appropriate space number for breakindent, taking influencing
+ * parameters into account. Window must be specified, since it is not
+ * necessarily always the current one. If lnum==0, current line is calculated,
+ * specified line otherwise.
+ */
+ int
+get_breakindent_win(wp, lnum)
+ win_T* wp;
+ linenr_T lnum;
+{
+ int bri;
+ /* window width minus barren space, i.e. what rests for text */
+ const int eff_wwidth = W_WIDTH(wp)
+ - ((wp->w_p_nu || wp->w_p_rnu) && (vim_strchr(p_cpo, CPO_NUMCOL) == NULL)
+ ? number_width(wp) : 0);
+
+ bri = get_indent_buf(wp->w_buffer, lnum ? lnum : wp->w_cursor.lnum) +
+ wp->w_p_brishift;
+
+ /* minus the length of the showbreak string */
+ if (wp->w_p_brisbr)
+ bri -= (*p_sbr == NUL ? 0 : vim_strsize(p_sbr));
+
+ /* Add offset for number column, if 'n' is in 'cpoptions' */
+ bri += win_col_off2(wp);
+
+ /* never indent past left window margin */
+ if (bri < 0)
+ bri = 0;
+ /* always leave at least bri_min characters on the left,
+ * if text width is sufficient */
+ else if (bri > eff_wwidth - wp->w_p_brimin)
+ bri = (eff_wwidth - wp->w_p_brimin < 0)
+ ? 0 : eff_wwidth - wp->w_p_brimin;
+
+ return bri;
+}
+#endif
+
+
#if defined(FEAT_CINDENT) || defined(FEAT_SMARTINDENT)
static int cin_is_cinword __ARGS((char_u *line));
@@ -1958,7 +2000,7 @@ plines_win_nofold(wp, lnum)
s = ml_get_buf(wp->w_buffer, lnum, FALSE);
if (*s == NUL) /* empty line */
return 1;
- col = win_linetabsize(wp, s, (colnr_T)MAXCOL);
+ col = win_linetabsize(wp, s, (colnr_T)MAXCOL, lnum);
/*
* If list mode is on, then the '$' at the end of the line may take up one
@@ -2014,7 +2056,7 @@ plines_win_col(wp, lnum, column)
col = 0;
while (*s != NUL && --column >= 0)
{
- col += win_lbr_chartabsize(wp, s, (colnr_T)col, NULL);
+ col += win_lbr_chartabsize(wp, s, (colnr_T)col, NULL, lnum);
mb_ptr_adv(s);
}
@@ -2026,7 +2068,7 @@ plines_win_col(wp, lnum, column)
* 'ts') -- webb.
*/
if (*s == TAB && (State & NORMAL) && (!wp->w_p_list || lcs_tab1))
- col += win_lbr_chartabsize(wp, s, (colnr_T)col, NULL) - 1;
+ col += win_lbr_chartabsize(wp, s, (colnr_T)col, NULL, lnum) - 1;
/*
* Add column offset for 'number', 'relativenumber', 'foldcolumn', etc.
@@ -9002,7 +9044,8 @@ get_lisp_indent()
amount = 0;
while (*that && col)
{
- amount += lbr_chartabsize_adv(&that, (colnr_T)amount);
+ amount += lbr_chartabsize_adv(&that, (colnr_T)amount,
+ pos->lnum);
col--;
}
@@ -9025,7 +9068,8 @@ get_lisp_indent()
while (vim_iswhite(*that))
{
- amount += lbr_chartabsize(that, (colnr_T)amount);
+ amount += lbr_chartabsize(that, (colnr_T)amount,
+ pos->lnum);
++that;
}
@@ -9064,14 +9108,17 @@ get_lisp_indent()
--parencount;
if (*that == '\\' && *(that+1) != NUL)
amount += lbr_chartabsize_adv(&that,
- (colnr_T)amount);
+ (colnr_T)amount,
+ pos->lnum);
amount += lbr_chartabsize_adv(&that,
- (colnr_T)amount);
+ (colnr_T)amount,
+ pos->lnum);
}
}
while (vim_iswhite(*that))
{
- amount += lbr_chartabsize(that, (colnr_T)amount);
+ amount += lbr_chartabsize(that, (colnr_T)amount,
+ pos->lnum);
that++;
}
if (!*that || *that == ';')
diff --git a/src/misc2.c b/src/misc2.c
--- a/src/misc2.c
+++ b/src/misc2.c
@@ -162,7 +162,7 @@ coladvance2(pos, addspaces, finetune, wc
#ifdef FEAT_VIRTUALEDIT
if ((addspaces || finetune) && !VIsual_active)
{
- curwin->w_curswant = linetabsize(line) + one_more;
+ curwin->w_curswant = linetabsize(line, pos->lnum) + one_more;
if (curwin->w_curswant > 0)
--curwin->w_curswant;
}
@@ -180,7 +180,7 @@ coladvance2(pos, addspaces, finetune, wc
# endif
&& wcol >= (colnr_T)width)
{
- csize = linetabsize(line);
+ csize = linetabsize(line, pos->lnum);
if (csize > 0)
csize--;
@@ -201,10 +201,10 @@ coladvance2(pos, addspaces, finetune, wc
{
/* Count a tab for what it's worth (if list mode not on) */
#ifdef FEAT_LINEBREAK
- csize = win_lbr_chartabsize(curwin, ptr, col, &head);
+ csize = win_lbr_chartabsize(curwin, ptr, col, &head, pos->lnum);
mb_ptr_adv(ptr);
#else
- csize = lbr_chartabsize_adv(&ptr, col);
+ csize = lbr_chartabsize_adv(&ptr, col, pos->lnum);
#endif
col += csize;
}
diff --git a/src/normal.c b/src/normal.c
--- a/src/normal.c
+++ b/src/normal.c
@@ -4389,7 +4389,7 @@ nv_screengo(oap, dir, dist)
int dir;
long dist;
{
- int linelen = linetabsize(ml_get_curline());
+ int linelen = linetabsize(ml_get_curline(), curwin->w_cursor.lnum);
int retval = OK;
int atend = FALSE;
int n;
@@ -4462,7 +4462,7 @@ nv_screengo(oap, dir, dist)
(void)hasFolding(curwin->w_cursor.lnum,
&curwin->w_cursor.lnum, NULL);
#endif
- linelen = linetabsize(ml_get_curline());
+ linelen = linetabsize(ml_get_curline(), curwin->w_cursor.lnum);
if (linelen > width1)
curwin->w_curswant += (((linelen - width1 - 1) / width2)
+ 1) * width2;
@@ -4492,7 +4492,7 @@ nv_screengo(oap, dir, dist)
}
curwin->w_cursor.lnum++;
curwin->w_curswant %= width2;
- linelen = linetabsize(ml_get_curline());
+ linelen = linetabsize(ml_get_curline(), curwin->w_cursor.lnum);
}
}
}
diff --git a/src/ops.c b/src/ops.c
--- a/src/ops.c
+++ b/src/ops.c
@@ -420,7 +420,8 @@ shift_block(oap, amount)
}
for ( ; vim_iswhite(*bd.textstart); )
{
- incr = lbr_chartabsize_adv(&bd.textstart, (colnr_T)(bd.start_vcol));
+ incr = lbr_chartabsize_adv(&bd.textstart, (colnr_T)(bd.start_vcol),
+ curwin->w_cursor.lnum);
total += incr;
bd.start_vcol += incr;
}
@@ -480,7 +481,8 @@ shift_block(oap, amount)
while (vim_iswhite(*non_white))
{
- incr = lbr_chartabsize_adv(&non_white, non_white_col);
+ incr = lbr_chartabsize_adv(&non_white, non_white_col,
+ curwin->w_cursor.lnum);
non_white_col += incr;
}
@@ -505,7 +507,8 @@ shift_block(oap, amount)
verbatim_copy_width -= bd.start_char_vcols;
while (verbatim_copy_width < destination_col)
{
- incr = lbr_chartabsize(verbatim_copy_end, verbatim_copy_width);
+ incr = lbr_chartabsize(verbatim_copy_end, verbatim_copy_width,
+ curwin->w_cursor.lnum);
if (verbatim_copy_width + incr > destination_col)
break;
verbatim_copy_width += incr;
@@ -3615,7 +3618,7 @@ do_put(regname, dir, count, flags)
for (ptr = oldp; vcol < col && *ptr; )
{
/* Count a tab for what it's worth (if list mode not on) */
- incr = lbr_chartabsize_adv(&ptr, (colnr_T)vcol);
+ incr = lbr_chartabsize_adv(&ptr, (colnr_T)vcol, lnum);
vcol += incr;
}
bd.textcol = (colnr_T)(ptr - oldp);
@@ -3649,7 +3652,7 @@ do_put(regname, dir, count, flags)
/* calculate number of spaces required to fill right side of block*/
spaces = y_width + 1;
for (j = 0; j < yanklen; j++)
- spaces -= lbr_chartabsize(&y_array[i][j], 0);
+ spaces -= lbr_chartabsize(&y_array[i][j], 0, lnum);
if (spaces < 0)
spaces = 0;
@@ -5201,7 +5204,7 @@ block_prep(oap, bdp, lnum, is_del)
while (bdp->start_vcol < oap->start_vcol && *pstart)
{
/* Count a tab for what it's worth (if list mode not on) */
- incr = lbr_chartabsize(pstart, (colnr_T)bdp->start_vcol);
+ incr = lbr_chartabsize(pstart, (colnr_T)bdp->start_vcol, lnum);
bdp->start_vcol += incr;
#ifdef FEAT_VISUALEXTRA
if (vim_iswhite(*pstart))
@@ -5270,7 +5273,7 @@ block_prep(oap, bdp, lnum, is_del)
{
/* Count a tab for what it's worth (if list mode not on) */
prev_pend = pend;
- incr = lbr_chartabsize_adv(&pend, (colnr_T)bdp->end_vcol);
+ incr = lbr_chartabsize_adv(&pend, (colnr_T)bdp->end_vcol, lnum);
bdp->end_vcol += incr;
}
if (bdp->end_vcol <= oap->end_vcol
@@ -6880,7 +6883,8 @@ cursor_pos_info()
validate_virtcol();
col_print(buf1, sizeof(buf1), (int)curwin->w_cursor.col + 1,
(int)curwin->w_virtcol + 1);
- col_print(buf2, sizeof(buf2), (int)STRLEN(p), linetabsize(p));
+ col_print(buf2, sizeof(buf2), (int)STRLEN(p),
+ linetabsize(p, curwin->w_cursor.lnum));
if (char_count_cursor == byte_count_cursor
&& char_count == byte_count)
diff --git a/src/option.c b/src/option.c
--- a/src/option.c
+++ b/src/option.c
@@ -188,6 +188,10 @@
#ifdef FEAT_ARABIC
# define PV_ARAB OPT_WIN(WV_ARAB)
#endif
+#ifdef FEAT_LINEBREAK
+# define PV_BRI OPT_WIN(WV_BRI)
+# define PV_BRIOPT OPT_WIN(WV_BRIOPT)
+#endif
#ifdef FEAT_DIFF
# define PV_DIFF OPT_WIN(WV_DIFF)
#endif
@@ -648,6 +652,24 @@ static struct vimoption
{(char_u *)0L, (char_u *)0L}
#endif
SCRIPTID_INIT},
+ {"breakindent", "bri", P_BOOL|P_VI_DEF|P_VIM|P_RWIN,
+#ifdef FEAT_LINEBREAK
+ (char_u *)VAR_WIN, PV_BRI,
+ {(char_u *)FALSE, (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ SCRIPTID_INIT},
+ {"breakindentopt", "briopt", P_STRING|P_ALLOCED|P_VI_DEF|P_RBUF|P_COMMA|P_NODUP,
+#ifdef FEAT_LINEBREAK
+ (char_u *)VAR_WIN, PV_BRIOPT,
+ {(char_u *)"min:20,shift:0", (char_u *)NULL}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)"", (char_u *)NULL}
+#endif
+ SCRIPTID_INIT},
{"browsedir", "bsdir",P_STRING|P_VI_DEF,
#ifdef FEAT_BROWSE
(char_u *)&p_bsdir, PV_NONE,
@@ -5709,6 +5731,14 @@ did_set_string_option(opt_idx, varp, new
*p_pm == '.' ? p_pm + 1 : p_pm) == 0)
errmsg = (char_u *)N_("E589: 'backupext' and 'patchmode' are equal");
}
+#ifdef FEAT_LINEBREAK
+ /* 'breakindentopt' */
+ else if (varp == &curwin->w_p_briopt)
+ {
+ if (briopt_changed() == FAIL)
+ errmsg = e_invarg;
+ }
+#endif
/*
* 'isident', 'iskeyword', 'isprint or 'isfname' option: refill chartab[]
@@ -10013,6 +10043,8 @@ get_varp(p)
case PV_WRAP: return (char_u *)&(curwin->w_p_wrap);
#ifdef FEAT_LINEBREAK
case PV_LBR: return (char_u *)&(curwin->w_p_lbr);
+ case PV_BRI: return (char_u *)&(curwin->w_p_bri);
+ case PV_BRIOPT: return (char_u *)&(curwin->w_p_briopt);
#endif
#ifdef FEAT_SCROLLBIND
case PV_SCBIND: return (char_u *)&(curwin->w_p_scb);
@@ -10202,6 +10234,11 @@ copy_winopt(from, to)
#endif
#ifdef FEAT_LINEBREAK
to->wo_lbr = from->wo_lbr;
+ to->wo_bri = from->wo_bri;
+ to->wo_brimin = from->wo_brimin;
+ to->wo_brishift = from->wo_brishift;
+ to->wo_briopt = vim_strsave(from->wo_briopt);
+ to->wo_brisbr = from->wo_brisbr;
#endif
#ifdef FEAT_SCROLLBIND
to->wo_scb = from->wo_scb;
@@ -10289,6 +10326,9 @@ check_winopt(wop)
#ifdef FEAT_CONCEAL
check_string_option(&wop->wo_cocu);
#endif
+#ifdef FEAT_LINEBREAK
+ check_string_option(&wop->wo_briopt);
+#endif
}
/*
@@ -10308,6 +10348,9 @@ clear_winopt(wop)
# endif
clear_string_option(&wop->wo_fmr);
#endif
+#ifdef FEAT_LINEBREAK
+ clear_string_option(&wop->wo_briopt);
+#endif
#ifdef FEAT_RIGHTLEFT
clear_string_option(&wop->wo_rlc);
#endif
@@ -11922,3 +11965,47 @@ find_mps_values(initc, findc, backwards,
++ptr;
}
}
+#ifdef FEAT_LINEBREAK
+/*
+ * This is called when 'breakindentopt' is changed.
+ */
+ int
+briopt_changed()
+{
+ char_u *p;
+ /* Defaults */
+ int bri_shift = 0;
+ long bri_min = 20;
+ int bri_sbr = FALSE;
+
+ p = curwin->w_p_briopt;
+ while (*p != NUL)
+ {
+ if (STRNCMP(p, "shift:", 6) == 0 && ((p[6] == '-' && VIM_ISDIGIT(p[7])) || VIM_ISDIGIT(p[6])))
+ {
+ p += 6;
+ bri_shift = getdigits(&p);
+ }
+ else if (STRNCMP(p, "min:", 4) == 0 && VIM_ISDIGIT(p[4]))
+ {
+ p += 4;
+ bri_min = getdigits(&p);
+ }
+ else if (STRNCMP(p, "sbr", 3) == 0)
+ {
+ p += 3;
+ bri_sbr = TRUE;
+ }
+ if (*p != ',' && *p != NUL)
+ return FAIL;
+ if (*p == ',')
+ ++p;
+ }
+
+ curwin->w_p_brishift = bri_shift;
+ curwin->w_p_brimin = bri_min;
+ curwin->w_p_brisbr = bri_sbr;
+
+ return OK;
+}
+#endif
diff --git a/src/option.h b/src/option.h
--- a/src/option.h
+++ b/src/option.h
@@ -1051,6 +1051,10 @@ enum
#ifdef FEAT_CURSORBIND
, WV_CRBIND
#endif
+#ifdef FEAT_LINEBREAK
+ , WV_BRI
+ , WV_BRIOPT
+#endif
#ifdef FEAT_DIFF
, WV_DIFF
#endif
diff --git a/src/proto/charset.pro b/src/proto/charset.pro
--- a/src/proto/charset.pro
+++ b/src/proto/charset.pro
@@ -14,9 +14,9 @@ int ptr2cells __ARGS((char_u *p));
int vim_strsize __ARGS((char_u *s));
int vim_strnsize __ARGS((char_u *s, int len));
int chartabsize __ARGS((char_u *p, colnr_T col));
-int linetabsize __ARGS((char_u *s));
-int linetabsize_col __ARGS((int startcol, char_u *s));
-int win_linetabsize __ARGS((win_T *wp, char_u *p, colnr_T len));
+int linetabsize __ARGS((char_u *s, linenr_T lnum));
+int linetabsize_col __ARGS((int startcol, char_u *s, linenr_T lnum));
+int win_linetabsize __ARGS((win_T *wp, char_u *p, colnr_T len, linenr_T lnum));
int vim_isIDc __ARGS((int c));
int vim_iswordc __ARGS((int c));
int vim_iswordc_buf __ARGS((int c, buf_T *buf));
@@ -26,9 +26,9 @@ int vim_isfilec __ARGS((int c));
int vim_isfilec_or_wc __ARGS((int c));
int vim_isprintc __ARGS((int c));
int vim_isprintc_strict __ARGS((int c));
-int lbr_chartabsize __ARGS((unsigned char *s, colnr_T col));
-int lbr_chartabsize_adv __ARGS((char_u **s, colnr_T col));
-int win_lbr_chartabsize __ARGS((win_T *wp, char_u *s, colnr_T col, int *headp));
+int lbr_chartabsize __ARGS((unsigned char *s, colnr_T col, linenr_T lnum));
+int lbr_chartabsize_adv __ARGS((char_u **s, colnr_T col, linenr_T lnum));
+int win_lbr_chartabsize __ARGS((win_T *wp, char_u *s, colnr_T col, int *headp, linenr_T lnum));
int in_win_border __ARGS((win_T *wp, colnr_T vcol));
void getvcol __ARGS((win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *end));
colnr_T getvcol_nolist __ARGS((pos_T *posp));
diff --git a/src/proto/misc1.pro b/src/proto/misc1.pro
--- a/src/proto/misc1.pro
+++ b/src/proto/misc1.pro
@@ -5,6 +5,7 @@ int get_indent_buf __ARGS((buf_T *buf, l
int get_indent_str __ARGS((char_u *ptr, int ts));
int set_indent __ARGS((int size, int flags));
int get_number_indent __ARGS((linenr_T lnum));
+int get_breakindent_win __ARGS((win_T *wp, linenr_T lnum));
int open_line __ARGS((int dir, int flags, int second_line_indent));
int get_leader_len __ARGS((char_u *line, char_u **flags, int backward, int include_space));
int get_last_leader_offset __ARGS((char_u *line, char_u **flags));
diff --git a/src/proto/option.pro b/src/proto/option.pro
--- a/src/proto/option.pro
+++ b/src/proto/option.pro
@@ -63,4 +63,5 @@ int check_ff_value __ARGS((char_u *p));
long get_sw_value __ARGS((buf_T *buf));
long get_sts_value __ARGS((void));
void find_mps_values __ARGS((int *initc, int *findc, int *backwards, int switchit));
+int briopt_changed __ARGS((void));
/* vim: set ft=c : */
diff --git a/src/regexp.c b/src/regexp.c
--- a/src/regexp.c
+++ b/src/regexp.c
@@ -4227,7 +4227,8 @@ reg_match_visual()
end = end2;
if (top.col == MAXCOL || bot.col == MAXCOL)
end = MAXCOL;
- cols = win_linetabsize(wp, regline, (colnr_T)(reginput - regline));
+ cols = win_linetabsize(wp, regline, (colnr_T)(reginput - regline),
+ reglnum + reg_firstlnum);
if (cols < start || cols > end - (*p_sel == 'e'))
return FALSE;
}
@@ -4432,7 +4433,8 @@ regmatch(scan)
case RE_VCOL:
if (!re_num_cmp((long_u)win_linetabsize(
reg_win == NULL ? curwin : reg_win,
- regline, (colnr_T)(reginput - regline)) + 1, scan))
+ regline, (colnr_T)(reginput - regline),
+ reglnum + reg_firstlnum) + 1, scan))
status = RA_NOMATCH;
break;
diff --git a/src/regexp_nfa.c b/src/regexp_nfa.c
--- a/src/regexp_nfa.c
+++ b/src/regexp_nfa.c
@@ -6357,7 +6357,8 @@ nfa_regmatch(prog, start, submatch, m)
result = nfa_re_num_cmp(t->state->val, t->state->c - NFA_VCOL,
(long_u)win_linetabsize(
reg_win == NULL ? curwin : reg_win,
- regline, (colnr_T)(reginput - regline)) + 1);
+ regline, (colnr_T)(reginput - regline),
+ reglnum + reg_firstlnum) + 1);
if (result)
{
add_here = TRUE;
diff --git a/src/screen.c b/src/screen.c
--- a/src/screen.c
+++ b/src/screen.c
@@ -2959,10 +2959,15 @@ win_line(wp, lnum, startrow, endrow, noc
# define WL_SIGN WL_FOLD /* column for signs */
#endif
#define WL_NR WL_SIGN + 1 /* line number */
+#ifdef FEAT_LINEBREAK
+# define WL_BRI WL_NR + 1 /* 'breakindent' */
+#else
+# define WL_BRI WL_NR
+#endif
#if defined(FEAT_LINEBREAK) || defined(FEAT_DIFF)
-# define WL_SBR WL_NR + 1 /* 'showbreak' or 'diff' */
+# define WL_SBR WL_BRI + 1 /* 'showbreak' or 'diff' */
#else
-# define WL_SBR WL_NR
+# define WL_SBR WL_BRI
#endif
#define WL_LINE WL_SBR + 1 /* text in the line */
int draw_state = WL_START; /* what to draw next */
@@ -3298,7 +3303,7 @@ win_line(wp, lnum, startrow, endrow, noc
#endif
while (vcol < v && *ptr != NUL)
{
- c = win_lbr_chartabsize(wp, ptr, (colnr_T)vcol, NULL);
+ c = win_lbr_chartabsize(wp, ptr, (colnr_T)vcol, NULL, lnum);
vcol += c;
#ifdef FEAT_MBYTE
prev_ptr = ptr;
@@ -3668,6 +3673,51 @@ win_line(wp, lnum, startrow, endrow, noc
}
}
+#ifdef FEAT_LINEBREAK
+ if (wp->w_p_brisbr && draw_state == WL_BRI - 1 &&
+ n_extra == 0 && *p_sbr != NUL)
+ /* draw indent after showbreak value */
+ draw_state = WL_BRI;
+ else if (wp->w_p_brisbr && draw_state == WL_SBR &&
+ n_extra == 0)
+ /* After the showbreak, draw the breakindent */
+ draw_state = WL_BRI - 1;
+
+ /* draw 'breakindent': indent wrapped text accordingly */
+ if (draw_state == WL_BRI - 1 && n_extra == 0)
+ {
+ draw_state = WL_BRI;
+# ifdef FEAT_DIFF
+ /* FIXME: handle (filler_todo > 0): or modify showbreak so that
+ * ---- lines are shorter by the amount needed? */
+# endif
+ /* FIXME: what is startrow? Don't we need it as well?? */
+ if (wp->w_p_bri && n_extra == 0 && row != startrow
+#ifdef FEAT_DIFF
+ && filler_lines == 0
+#endif
+ )
+ {
+ char_attr = 0; /* was: hl_attr(HLF_AT); */
+#ifdef FEAT_DIFF
+ if (diff_hlf != (hlf_T)0)
+ char_attr = hl_attr(diff_hlf);
+#endif
+ p_extra = NUL;
+ c_extra = ' ';
+ n_extra = get_breakindent_win(wp, lnum);
+ /* FIXME: why do we need to adjust vcol if showbreak does not??
+ * vcol += n_extra;
+ * FIXME: is this relevant here? copied shamelessly from showbreak
+ *
+ * Correct end of highlighted area for 'breakindent',
+ * required when 'linebreak' is also set. */
+ if (tocol == vcol)
+ tocol += n_extra;
+ }
+ }
+#endif
+
#if defined(FEAT_LINEBREAK) || defined(FEAT_DIFF)
if (draw_state == WL_SBR - 1 && n_extra == 0)
{
@@ -4379,7 +4429,7 @@ win_line(wp, lnum, startrow, endrow, noc
# ifdef FEAT_MBYTE
has_mbyte ? mb_l :
# endif
- 1), (colnr_T)vcol, NULL) - 1;
+ 1), (colnr_T)vcol, NULL, lnum) - 1;
c_extra = ' ';
if (vim_iswhite(c))
{
diff --git a/src/structs.h b/src/structs.h
--- a/src/structs.h
+++ b/src/structs.h
@@ -134,6 +134,18 @@ typedef struct
int wo_arab;
# define w_p_arab w_onebuf_opt.wo_arab /* 'arabic' */
#endif
+#ifdef FEAT_LINEBREAK
+ int wo_bri;
+# define w_p_bri w_onebuf_opt.wo_bri /* 'breakindent' */
+ long wo_brimin;
+# define w_p_brimin w_onebuf_opt.wo_brimin /* 'breakindentmin' */
+ long wo_brishift;
+# define w_p_brishift w_onebuf_opt.wo_brishift /* 'breakindentshift' */
+ char_u *wo_briopt;
+# define w_p_briopt w_onebuf_opt.wo_briopt /* 'breakindentopt' */
+ int wo_brisbr;
+# define w_p_brisbr w_onebuf_opt.wo_brisbr /* sbr in breakindent */
+#endif
#ifdef FEAT_DIFF
int wo_diff;
# define w_p_diff w_onebuf_opt.wo_diff /* 'diff' */
diff --git a/src/ui.c b/src/ui.c
--- a/src/ui.c
+++ b/src/ui.c
@@ -3167,7 +3167,7 @@ vcol2col(wp, lnum, vcol)
start = ptr = ml_get_buf(wp->w_buffer, lnum, FALSE);
while (count < vcol && *ptr != NUL)
{
- count += win_lbr_chartabsize(wp, ptr, count, NULL);
+ count += win_lbr_chartabsize(wp, ptr, count, NULL, lnum);
mb_ptr_adv(ptr);
}
return (int)(ptr - start);