From 47391b18e2084f2747b10aa6158bc40e03f01528 Mon Sep 17 00:00:00 2001 From: Felipe Morales Date: Thu, 26 Jun 2014 00:21:57 -0400 Subject: Port vim's patch 7.4.338 ('breakindent') --- src/nvim/buffer_defs.h | 7 ++++ src/nvim/charset.c | 56 +++++++++++++++---------- src/nvim/cursor.c | 2 +- src/nvim/edit.c | 22 ++++++---- src/nvim/ex_getln.c | 8 ++-- src/nvim/getchar.c | 2 +- src/nvim/indent.c | 75 +++++++++++++++++++++++++++++----- src/nvim/misc1.c | 11 ++--- src/nvim/ops.c | 20 +++++---- src/nvim/option.c | 63 ++++++++++++++++++++++++++++ src/nvim/option_defs.h | 2 + src/nvim/screen.c | 42 ++++++++++++++++--- src/nvim/testdir/test_breakindent.in | 79 ++++++++++++++++++++++++++++++++++++ src/nvim/testdir/test_breakindent.ok | 55 +++++++++++++++++++++++++ 14 files changed, 381 insertions(+), 63 deletions(-) create mode 100644 src/nvim/testdir/test_breakindent.in create mode 100644 src/nvim/testdir/test_breakindent.ok (limited to 'src') diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 9f5d7b86eb..4162df63ab 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -136,6 +136,10 @@ struct buffheader { typedef struct { int wo_arab; # define w_p_arab w_onebuf_opt.wo_arab /* 'arabic' */ + int wo_bri; +# define w_p_bri w_onebuf_opt.wo_bri /* 'breakindent' */ + char_u *wo_briopt; +# define w_p_briopt w_onebuf_opt.wo_briopt /* 'breakindentopt' */ int wo_diff; # define w_p_diff w_onebuf_opt.wo_diff /* 'diff' */ long wo_fdc; @@ -1069,6 +1073,9 @@ struct window_S { long_u w_p_fde_flags; /* flags for 'foldexpr' */ long_u w_p_fdt_flags; /* flags for 'foldtext' */ int *w_p_cc_cols; /* array of columns to highlight or NULL */ + int w_p_brimin; /* minimum width for breakindent */ + int w_p_brishift; /* additional shift for breakindent */ + bool w_p_brisbr; /* sbr in 'briopt' */ /* transform a pointer to a "onebuf" option into a "allbuf" option */ #define GLOBAL_WO(p) ((char *)p + sizeof(winopt_T)) diff --git a/src/nvim/charset.c b/src/nvim/charset.c index baf6895b4c..3392cceb9f 100644 --- a/src/nvim/charset.c +++ b/src/nvim/charset.c @@ -13,6 +13,7 @@ #include "nvim/charset.h" #include "nvim/farsi.h" #include "nvim/func_attr.h" +#include "nvim/indent.h" #include "nvim/main.h" #include "nvim/mbyte.h" #include "nvim/memline.h" @@ -775,9 +776,10 @@ int linetabsize(char_u *s) int linetabsize_col(int startcol, char_u *s) { colnr_T col = startcol; + char_u *line = s; /* pointer to start of line, for breakindent */ while (*s != NUL) { - col += lbr_chartabsize_adv(&s, col); + col += lbr_chartabsize_adv(line, &s, col); } return (int)col; } @@ -785,17 +787,17 @@ int linetabsize_col(int startcol, char_u *s) /// Like linetabsize(), but for a given window instead of the current one. /// /// @param wp -/// @param p +/// @param line /// @param len /// /// @return Number of characters the string will take on the screen. -int win_linetabsize(win_T *wp, char_u *p, colnr_T len) +int win_linetabsize(win_T *wp, char_u *line, colnr_T len) { 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); + for (s = line; *s != NUL && (len == MAXCOL || s < line + len); mb_ptr_adv(s)) { + col += win_lbr_chartabsize(wp, line, s, col, NULL); } return (int)col; } @@ -922,32 +924,34 @@ int vim_isprintc_strict(int c) /// like chartabsize(), but also check for line breaks on the screen /// +/// @param line /// @param s /// @param col /// /// @return The number of characters taken up on the screen. -int lbr_chartabsize(unsigned char *s, colnr_T col) +int lbr_chartabsize(char_u *line, unsigned char *s, colnr_T col) { - if (!curwin->w_p_lbr && (*p_sbr == NUL)) { + if (!curwin->w_p_lbr && (*p_sbr == NUL) && !curwin->w_p_bri) { if (curwin->w_p_wrap) { return win_nolbr_chartabsize(curwin, s, col, NULL); } RET_WIN_BUF_CHARTABSIZE(curwin, curbuf, s, col) } - return win_lbr_chartabsize(curwin, s, col, NULL); + return win_lbr_chartabsize(curwin, line == NULL ? s: line, s, col, NULL); } /// Call lbr_chartabsize() and advance the pointer. /// +/// @param line /// @param s /// @param col /// /// @return The number of characters take up on the screen. -int lbr_chartabsize_adv(char_u **s, colnr_T col) +int lbr_chartabsize_adv(char_u *line, char_u **s, colnr_T col) { int retval; - retval = lbr_chartabsize(*s, col); + retval = lbr_chartabsize(line, *s, col); mb_ptr_adv(*s); return retval; } @@ -959,12 +963,13 @@ int lbr_chartabsize_adv(char_u **s, colnr_T col) /// value, init to 0 before calling. /// /// @param wp +/// @param line /// @param s /// @param col /// @param headp /// /// @return The number of characters taken up on the screen. -int win_lbr_chartabsize(win_T *wp, char_u *s, colnr_T col, int *headp) +int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *headp) { colnr_T col2; colnr_T colmax; @@ -975,8 +980,8 @@ int win_lbr_chartabsize(win_T *wp, char_u *s, colnr_T col, int *headp) int tab_corr = (*s == TAB); int n; - // No 'linebreak' and 'showbreak': return quickly. - if (!wp->w_p_lbr && (*p_sbr == NUL)) { + // No 'linebreak', 'showbreak' and 'breakindent': return quickly. + if (!wp->w_p_lbr && !wp->w_p_bri && (*p_sbr == NUL)) { if (wp->w_p_wrap) { return win_nolbr_chartabsize(wp, s, col, headp); } @@ -1039,11 +1044,12 @@ int win_lbr_chartabsize(win_T *wp, char_u *s, colnr_T col, int *headp) mb_added = 1; } - // 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; @@ -1056,7 +1062,12 @@ int win_lbr_chartabsize(win_T *wp, char_u *s, colnr_T col, int *headp) } if ((col == 0) || (col + size > (colnr_T)wp->w_width)) { - 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, line); + if (tab_corr) { size += (added / wp->w_buffer->b_p_ts) * wp->w_buffer->b_p_ts; } else { @@ -1157,13 +1168,14 @@ void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T vcol; char_u *ptr; // points to current char char_u *posptr; // points to char at pos->col + char_u *line; // start of the line int incr; int head; int ts = wp->w_buffer->b_p_ts; int c; vcol = 0; - ptr = ml_get_buf(wp->w_buffer, pos->lnum, FALSE); + line = ptr = ml_get_buf(wp->w_buffer, pos->lnum, FALSE); if (pos->col == MAXCOL) { // continue until the NUL @@ -1173,11 +1185,13 @@ void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, } // This function is used very often, do some speed optimizations. - // When 'list', 'linebreak' and 'showbreak' are not set use a simple loop. - // Also use this when 'list' is set but tabs take their normal size. + // 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)) && !wp->w_p_lbr - && (*p_sbr == NUL)) { + && (*p_sbr == NUL) + && !wp->w_p_bri ) { for (;;) { head = 0; c = *ptr; @@ -1229,7 +1243,7 @@ void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, for (;;) { // A tab gets expanded, depending on the current column head = 0; - incr = win_lbr_chartabsize(wp, ptr, vcol, &head); + incr = win_lbr_chartabsize(wp, line, ptr, vcol, &head); // make sure we don't go past the end of the line if (*ptr == NUL) { diff --git a/src/nvim/cursor.c b/src/nvim/cursor.c index 64a3b73f15..cd84d7014c 100644 --- a/src/nvim/cursor.c +++ b/src/nvim/cursor.c @@ -138,7 +138,7 @@ static int coladvance2( ptr = line; while (col <= wcol && *ptr != NUL) { /* Count a tab for what it's worth (if list mode not on) */ - csize = win_lbr_chartabsize(curwin, ptr, col, &head); + csize = win_lbr_chartabsize(curwin, line, ptr, col, &head); mb_ptr_adv(ptr); col += csize; } diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 93e127394b..6158176e56 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -1551,7 +1551,7 @@ change_indent ( new_cursor_col += (*mb_ptr2len)(ptr + new_cursor_col); else ++new_cursor_col; - vcol += lbr_chartabsize(ptr + new_cursor_col, (colnr_T)vcol); + vcol += lbr_chartabsize(ptr, ptr + new_cursor_col, (colnr_T)vcol); } vcol = last_vcol; @@ -5898,9 +5898,11 @@ int oneleft(void) width = 1; for (;; ) { coladvance(v - width); - /* getviscol() is slow, skip it when 'showbreak' is empty and - * there are no multi-byte characters */ + /* 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 && !has_mbyte ) || getviscol() < v) break; @@ -7914,10 +7916,10 @@ static int ins_tab(void) 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(NULL, (char_u *)"\t", vcol); if (vcol + i > want_vcol) break; if (*ptr != TAB) { @@ -7936,10 +7938,11 @@ static int ins_tab(void) if (change_col >= 0) { int repl_off = 0; + char_u *line = ptr; /* Skip over the spaces we need. */ while (vcol < want_vcol && *ptr == ' ') { - vcol += lbr_chartabsize(ptr, vcol); + vcol += lbr_chartabsize(line, ptr, vcol); ++ptr; ++repl_off; } @@ -8126,6 +8129,7 @@ int ins_copychar(linenr_T lnum) int c; int temp; char_u *ptr, *prev_ptr; + char_u *line; if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count) { vim_beep(); @@ -8134,12 +8138,12 @@ int ins_copychar(linenr_T lnum) /* try to advance to the cursor column */ temp = 0; - ptr = ml_get(lnum); + line = ptr = ml_get(lnum); prev_ptr = ptr; validate_virtcol(); while ((colnr_T)temp < curwin->w_virtcol && *ptr != NUL) { prev_ptr = ptr; - temp += lbr_chartabsize_adv(&ptr, (colnr_T)temp); + temp += lbr_chartabsize_adv(line, &ptr, (colnr_T)temp); } if ((colnr_T)temp > curwin->w_virtcol) ptr = prev_ptr; diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 28048c933c..74f3edc8d9 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -1817,10 +1817,10 @@ getexmodeline ( p = (char_u *)line_ga.ga_data; p[line_ga.ga_len] = NUL; - indent = get_indent_str(p, 8); + indent = get_indent_str(p, 8, FALSE); indent += sw - indent % sw; add_indent: - while (get_indent_str(p, 8) < indent) { + while (get_indent_str(p, 8, FALSE) < indent) { char_u *s = skipwhite(p); ga_grow(&line_ga, 1); @@ -1858,11 +1858,11 @@ redraw: p[--line_ga.ga_len] = NUL; } else { p[line_ga.ga_len] = NUL; - indent = get_indent_str(p, 8); + indent = get_indent_str(p, 8, FALSE); --indent; indent -= indent % get_sw_value(curbuf); } - while (get_indent_str(p, 8) > indent) { + while (get_indent_str(p, 8, FALSE) > indent) { char_u *s = skipwhite(p); memmove(s - 1, s, line_ga.ga_len - (s - p) + 1); diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index e98bb2744c..6c772a8a66 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -2163,7 +2163,7 @@ static int vgetorpeek(int advance) while (col < curwin->w_cursor.col) { if (!vim_iswhite(ptr[col])) curwin->w_wcol = vcol; - vcol += lbr_chartabsize(ptr + col, + vcol += lbr_chartabsize(ptr, ptr + col, (colnr_T)vcol); if (has_mbyte) col += (*mb_ptr2len)(ptr + col); diff --git a/src/nvim/indent.c b/src/nvim/indent.c index d4c6b36177..7673a297f6 100644 --- a/src/nvim/indent.c +++ b/src/nvim/indent.c @@ -10,8 +10,10 @@ #include "nvim/memory.h" #include "nvim/misc1.h" #include "nvim/misc2.h" +#include "nvim/move.h" #include "nvim/option.h" #include "nvim/regexp.h" +#include "nvim/screen.h" #include "nvim/search.h" #include "nvim/strings.h" #include "nvim/undo.h" @@ -24,14 +26,14 @@ // Count the size (in window cells) of the indent in the current line. int get_indent(void) { - return get_indent_str(get_cursor_line_ptr(), (int)curbuf->b_p_ts); + return get_indent_str(get_cursor_line_ptr(), (int)curbuf->b_p_ts, false); } // Count the size (in window cells) of the indent in line "lnum". int get_indent_lnum(linenr_T lnum) { - return get_indent_str(ml_get(lnum), (int)curbuf->b_p_ts); + return get_indent_str(ml_get(lnum), (int)curbuf->b_p_ts, false); } @@ -39,20 +41,27 @@ int get_indent_lnum(linenr_T lnum) // "buf". int get_indent_buf(buf_T *buf, linenr_T lnum) { - return get_indent_str(ml_get_buf(buf, lnum, false), (int)buf->b_p_ts); + return get_indent_str(ml_get_buf(buf, lnum, false), (int)buf->b_p_ts, false); } // Count the size (in window cells) of the indent in line "ptr", with // 'tabstop' at "ts". -int get_indent_str(char_u *ptr, int ts) +// If @param list is TRUE, count only screen size for tabs. +int get_indent_str(char_u *ptr, int ts, int list) { int count = 0; for (; *ptr; ++ptr) { // Count a tab for what it is worth. if (*ptr == TAB) { - count += ts - (count % ts); + if (!list || lcs_tab1) { // count a tab for what it is worth + count += ts - (count % ts); + } else { + // in list mode, when tab is not set, count screen char width for Tab: + // ^I + count += ptr2cells(ptr); + } } else if (*ptr == ' ') { // Count a space for one. count++; @@ -433,6 +442,50 @@ int get_number_indent(linenr_T lnum) return (int)col; } +/* + * Return appropriate space number for breakindent, taking influencing + * parameters into account. Window must be specified, since it is not + * necessarily always the current one. + */ +int get_breakindent_win(win_T *wp, char_u *line) { + static int prev_indent = 0; /* cached indent value */ + static int prev_ts = 0L; /* cached tabstop value */ + static char_u *prev_line = NULL; /* cached pointer to line */ + int bri = 0; + /* window width minus window margin space, i.e. what rests for text */ + const int eff_wwidth = wp->w_width + - ((wp->w_p_nu || wp->w_p_rnu) + && (vim_strchr(p_cpo, CPO_NUMCOL) == NULL) + ? number_width(wp) + 1 : 0); + + /* used cached indent, unless pointer or 'tabstop' changed */ + if (prev_line != line || prev_ts != wp->w_buffer->b_p_ts) + { + prev_line = line; + prev_ts = wp->w_buffer->b_p_ts; + prev_indent = get_indent_str(line, + (int)wp->w_buffer->b_p_ts, wp->w_p_list) + wp->w_p_brishift; + } + + /* indent minus the length of the showbreak string */ + bri = prev_indent; + if (wp->w_p_brisbr) + bri -= 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; +} // When extra == 0: Return true if the cursor is before or on the first // non-blank in the line. @@ -608,10 +661,12 @@ int get_lisp_indent(void) if (vi_lisp && (get_indent() == 0)) { amount = 2; } else { + char_u *line = that; + amount = 0; while (*that && col) { - amount += lbr_chartabsize_adv(&that, (colnr_T)amount); + amount += lbr_chartabsize_adv(line, &that, (colnr_T)amount); col--; } @@ -628,7 +683,7 @@ int get_lisp_indent(void) firsttry = amount; while (vim_iswhite(*that)) { - amount += lbr_chartabsize(that, (colnr_T)amount); + amount += lbr_chartabsize(line, that, (colnr_T)amount); that++; } @@ -658,15 +713,15 @@ int get_lisp_indent(void) parencount--; } if ((*that == '\\') && (*(that + 1) != NUL)) { - amount += lbr_chartabsize_adv(&that, (colnr_T)amount); + amount += lbr_chartabsize_adv(line, &that, (colnr_T)amount); } - amount += lbr_chartabsize_adv(&that, (colnr_T)amount); + amount += lbr_chartabsize_adv(line, &that, (colnr_T)amount); } } while (vim_iswhite(*that)) { - amount += lbr_chartabsize(that, (colnr_T)amount); + amount += lbr_chartabsize(line, that, (colnr_T)amount); that++; } diff --git a/src/nvim/misc1.c b/src/nvim/misc1.c index f0c4ee492e..986374b352 100644 --- a/src/nvim/misc1.c +++ b/src/nvim/misc1.c @@ -194,7 +194,7 @@ open_line ( /* * count white space on current line */ - newindent = get_indent_str(saved_line, (int)curbuf->b_p_ts); + newindent = get_indent_str(saved_line, (int)curbuf->b_p_ts, FALSE); if (newindent == 0 && !(flags & OPENLINE_COM_LIST)) newindent = second_line_indent; /* for ^^D command in insert mode */ @@ -631,7 +631,7 @@ open_line ( if (curbuf->b_p_ai || do_si ) - newindent = get_indent_str(leader, (int)curbuf->b_p_ts); + newindent = get_indent_str(leader, (int)curbuf->b_p_ts, FALSE); /* Add the indent offset */ if (newindent + off < 0) { @@ -1306,6 +1306,7 @@ int plines_win_col(win_T *wp, linenr_T lnum, long column) char_u *s; int lines = 0; int width; + char_u *line; /* Check for filler lines above this buffer line. When folded the result * is one line anyway. */ @@ -1317,11 +1318,11 @@ int plines_win_col(win_T *wp, linenr_T lnum, long column) if (wp->w_width == 0) return lines + 1; - s = ml_get_buf(wp->w_buffer, lnum, FALSE); + line = s = ml_get_buf(wp->w_buffer, lnum, FALSE); col = 0; while (*s != NUL && --column >= 0) { - col += win_lbr_chartabsize(wp, s, (colnr_T)col, NULL); + col += win_lbr_chartabsize(wp, line, s, (colnr_T)col, NULL); mb_ptr_adv(s); } @@ -1333,7 +1334,7 @@ int plines_win_col(win_T *wp, linenr_T lnum, long 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, line, s, (colnr_T)col, NULL) - 1; /* * Add column offset for 'number', 'relativenumber', 'foldcolumn', etc. diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 0bf338947b..0b0a913a95 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -350,7 +350,8 @@ static void shift_block(oparg_T *oap, int amount) ++bd.textstart; } for (; vim_iswhite(*bd.textstart); ) { - incr = lbr_chartabsize_adv(&bd.textstart, (colnr_T)(bd.start_vcol)); + // TODO: is passing bd.textstart for start of the line OK? + incr = lbr_chartabsize_adv(bd.textstart, &bd.textstart, (colnr_T)(bd.start_vcol)); total += incr; bd.start_vcol += incr; } @@ -405,7 +406,7 @@ static void shift_block(oparg_T *oap, int amount) non_white_col = bd.start_vcol; while (vim_iswhite(*non_white)) { - incr = lbr_chartabsize_adv(&non_white, non_white_col); + incr = lbr_chartabsize_adv(bd.textstart, &non_white, non_white_col); non_white_col += incr; } @@ -429,7 +430,10 @@ static void shift_block(oparg_T *oap, int amount) if (bd.startspaces) verbatim_copy_width -= bd.start_char_vcols; while (verbatim_copy_width < destination_col) { - incr = lbr_chartabsize(verbatim_copy_end, verbatim_copy_width); + char_u *line = verbatim_copy_end; + + // TODO: is passing verbatim_copy_end for start of the line OK? + incr = lbr_chartabsize(line, verbatim_copy_end, verbatim_copy_width); if (verbatim_copy_width + incr > destination_col) break; verbatim_copy_width += incr; @@ -2824,7 +2828,7 @@ do_put ( oldlen = (int)STRLEN(oldp); 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(oldp, &ptr, (colnr_T)vcol); vcol += incr; } bd.textcol = (colnr_T)(ptr - oldp); @@ -2854,7 +2858,7 @@ do_put ( /* 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(NULL, &y_array[i][j], 0); if (spaces < 0) spaces = 0; @@ -4114,7 +4118,7 @@ static void block_prep(oparg_T *oap, struct block_def *bdp, linenr_T lnum, int i 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(pstart, (colnr_T)bdp->start_vcol); + incr = lbr_chartabsize(line, pstart, (colnr_T)bdp->start_vcol); bdp->start_vcol += incr; if (vim_iswhite(*pstart)) { bdp->pre_whitesp += incr; @@ -4163,7 +4167,9 @@ static void block_prep(oparg_T *oap, struct block_def *bdp, linenr_T lnum, int i while (bdp->end_vcol <= oap->end_vcol && *pend != NUL) { /* 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); + // TODO: is passing prev_pend for start of the line OK? + // prehaps it should be "line" + incr = lbr_chartabsize_adv(prev_pend, &pend, (colnr_T)bdp->end_vcol); bdp->end_vcol += incr; } if (bdp->end_vcol <= oap->end_vcol diff --git a/src/nvim/option.c b/src/nvim/option.c index 63ea2ee338..7d40fb3d6b 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -176,6 +176,8 @@ */ #define PV_LIST OPT_WIN(WV_LIST) # define PV_ARAB OPT_WIN(WV_ARAB) +# define PV_BRI OPT_WIN(WV_BRI) +# define PV_BRIOPT OPT_WIN(WV_BRIOPT) # define PV_DIFF OPT_WIN(WV_DIFF) # define PV_FDC OPT_WIN(WV_FDC) # define PV_FEN OPT_WIN(WV_FEN) @@ -471,6 +473,14 @@ static struct vimoption (char_u *)&p_breakat, PV_NONE, {(char_u *)" \t!@*-+;:,./?", (char_u *)0L} SCRIPTID_INIT}, + {"breakindent", "bri", P_BOOL|P_VI_DEF|P_VIM|P_RWIN, + (char_u *)VAR_WIN, PV_BRI, + {(char_u *)FALSE, (char_u *)0L} + SCRIPTID_INIT}, + {"breakindentopt", "briopt", P_STRING|P_ALLOCED|P_VI_DEF|P_RBUF|P_COMMA|P_NODUP, + (char_u *)VAR_WIN, PV_BRIOPT, + {(char_u *)"", (char_u *)NULL} + SCRIPTID_INIT}, {"browsedir", "bsdir",P_STRING|P_VI_DEF, (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} @@ -3481,6 +3491,7 @@ static void didset_options(void) (void)compile_cap_prog(curwin->w_s); /* set cedit_key */ (void)check_cedit(); + briopt_check(); } /* @@ -3815,6 +3826,11 @@ did_set_string_option ( *p_pm == '.' ? p_pm + 1 : p_pm) == 0) errmsg = (char_u *)N_("E589: 'backupext' and 'patchmode' are equal"); } + /* 'breakindentopt' */ + else if (varp == &curwin->w_p_briopt) { + if (briopt_check() == FAIL) + errmsg = e_invarg; + } /* * 'isident', 'iskeyword', 'isprint or 'isfname' option: refill chartab[] * If the new option is invalid, use old value. 'lisp' option: refill @@ -6681,6 +6697,8 @@ static char_u *get_varp(struct vimoption *p) case PV_SCROLL: return (char_u *)&(curwin->w_p_scr); case PV_WRAP: return (char_u *)&(curwin->w_p_wrap); 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); case PV_SCBIND: return (char_u *)&(curwin->w_p_scb); case PV_CRBIND: return (char_u *)&(curwin->w_p_crb); case PV_COCU: return (char_u *)&(curwin->w_p_cocu); @@ -6788,6 +6806,8 @@ void copy_winopt(winopt_T *from, winopt_T *to) to->wo_wrap = from->wo_wrap; to->wo_wrap_save = from->wo_wrap_save; to->wo_lbr = from->wo_lbr; + to->wo_bri = from->wo_bri; + to->wo_briopt = vim_strsave(from->wo_briopt); to->wo_scb = from->wo_scb; to->wo_scb_save = from->wo_scb_save; to->wo_crb = from->wo_crb; @@ -6842,6 +6862,7 @@ void check_winopt(winopt_T *wop) check_string_option(&wop->wo_stl); check_string_option(&wop->wo_cc); check_string_option(&wop->wo_cocu); + check_string_option(&wop->wo_briopt); } /* @@ -6859,6 +6880,7 @@ void clear_winopt(winopt_T *wop) clear_string_option(&wop->wo_stl); clear_string_option(&wop->wo_cc); clear_string_option(&wop->wo_cocu); + clear_string_option(&wop->wo_briopt); } /* @@ -8134,3 +8156,44 @@ void find_mps_values(int *initc, int *findc, int *backwards, int switchit) ++ptr; } } + +/* This is called when 'breakindentopt' is changed and whenn a window is + initialized */ +int briopt_check() { + char_u *p; + int bri_shift = 0; + long bri_min = 20; + bool 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; +} + diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h index d862ab2761..555e9166d6 100644 --- a/src/nvim/option_defs.h +++ b/src/nvim/option_defs.h @@ -726,6 +726,8 @@ enum { , WV_COCU , WV_COLE , WV_CRBIND + , WV_BRI + , WV_BRIOPT , WV_DIFF , WV_FDC , WV_FEN diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 03c59bf584..61e783f2b1 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -106,6 +106,7 @@ #include "nvim/farsi.h" #include "nvim/fileio.h" #include "nvim/fold.h" +#include "nvim/indent.h" #include "nvim/getchar.h" #include "nvim/main.h" #include "nvim/mbyte.h" @@ -2283,7 +2284,8 @@ win_line ( # define WL_FOLD WL_CMDLINE + 1 /* 'foldcolumn' */ # define WL_SIGN WL_FOLD + 1 /* column for signs */ #define WL_NR WL_SIGN + 1 /* line number */ -# define WL_SBR WL_NR + 1 /* 'showbreak' or 'diff' */ +# define WL_BRI WL_NR + 1 /* 'breakindent' */ +# define WL_SBR WL_BRI + 1 /* 'showbreak' or 'diff' */ #define WL_LINE WL_SBR + 1 /* text in the line */ int draw_state = WL_START; /* what to draw next */ @@ -2540,7 +2542,7 @@ win_line ( if (v > 0) { char_u *prev_ptr = ptr; while (vcol < v && *ptr != NUL) { - c = win_lbr_chartabsize(wp, ptr, (colnr_T)vcol, NULL); + c = win_lbr_chartabsize(wp, line, ptr, (colnr_T)vcol, NULL); vcol += c; prev_ptr = ptr; mb_ptr_adv(ptr); @@ -2817,6 +2819,34 @@ win_line ( } } + 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 accodringly + if (draw_state == WL_BRI - 1 && n_extra == 0) { + draw_state = WL_BRI; + if (wp->w_p_bri && n_extra == 0 && row != startrow && filler_lines == 0) { + char_attr = 0; // was: hl_attr(HLF_AT); + + if (diff_hlf != (hlf_T)0) + char_attr = hl_attr(diff_hlf); + + p_extra = NULL; + c_extra = ' '; + n_extra = get_breakindent_win(wp, ml_get_buf(wp->w_buffer, lnum, FALSE)); + /* Correct end of highlighted area for 'breakindent', + required wen 'linebreak' is also set. */ + if (tocol == vcol) + tocol += n_extra; + } + } + if (draw_state == WL_SBR - 1 && n_extra == 0) { draw_state = WL_SBR; if (filler_todo > 0) { @@ -3380,9 +3410,11 @@ win_line ( */ if (wp->w_p_lbr && vim_isbreak(c) && !vim_isbreak(*ptr) && !wp->w_p_list) { - n_extra = win_lbr_chartabsize(wp, ptr - ( - has_mbyte ? mb_l : - 1), (colnr_T)vcol, NULL) - 1; + char_u *p = ptr - ( + has_mbyte ? mb_l : + 1); + // TODO: is passing p for start of the line OK? + n_extra = win_lbr_chartabsize(wp, p, p, (colnr_T)vcol, NULL) - 1; c_extra = ' '; if (vim_iswhite(c)) { if (c == TAB) diff --git a/src/nvim/testdir/test_breakindent.in b/src/nvim/testdir/test_breakindent.in new file mode 100644 index 0000000000..8f40e4f7e5 --- /dev/null +++ b/src/nvim/testdir/test_breakindent.in @@ -0,0 +1,79 @@ +Test for breakindent + +STARTTEST +:so small.vim +:if !exists("+breakindent") | e! test.ok | w! test.out | qa! | endif +:10new|:vsp|:vert resize 20 +:put =\"\tabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP\" +:set ts=4 sw=4 sts=4 breakindent +:fu! ScreenChar(width) +: let c='' +: for i in range(1,a:width) +: let c.=nr2char(screenchar(line('.'), i)) +: endfor +: let c.="\n" +: for i in range(1,a:width) +: let c.=nr2char(screenchar(line('.')+1, i)) +: endfor +: let c.="\n" +: for i in range(1,a:width) +: let c.=nr2char(screenchar(line('.')+2, i)) +: endfor +: return c +:endfu +:fu DoRecordScreen() +: wincmd l +: $put =printf(\"\n%s\", g:test) +: $put =g:line1 +: wincmd p +:endfu +:let g:test="Test 1: Simple breakindent" +:let line1=ScreenChar(8) +:call DoRecordScreen() +:let g:test="Test 2: Simple breakindent + sbr=>>" +:set sbr=>> +:let line1=ScreenChar(8) +:call DoRecordScreen() +:let g:test ="Test 3: Simple breakindent + briopt:sbr" +:set briopt=sbr,min:0 sbr=++ +:let line1=ScreenChar(8) +:call DoRecordScreen() +:let g:test ="Test 4: Simple breakindent + min width: 18" +:set sbr= briopt=min:18 +:let line1=ScreenChar(8) +:call DoRecordScreen() +:let g:test =" Test 5: Simple breakindent + shift by 2" +:set briopt=shift:2,min:0 +:let line1=ScreenChar(8) +:call DoRecordScreen() +:let g:test=" Test 6: Simple breakindent + shift by -1" +:set briopt=shift:-1,min:0 +:let line1=ScreenChar(8) +:call DoRecordScreen() +:let g:test=" Test 7: breakindent + shift by +1 + nu + sbr=? briopt:sbr" +:set briopt=shift:1,sbr,min:0 nu sbr=? nuw=4 +:let line1=ScreenChar(10) +:call DoRecordScreen() +:let g:test=" Test 8: breakindent + shift:1 + nu + sbr=# list briopt:sbr" +:set briopt=shift:1,sbr,min:0 nu sbr=# list +:let line1=ScreenChar(10) +:call DoRecordScreen() +:let g:test=" Test 9: breakindent + shift by +1 + 'nu' + sbr=# list" +:set briopt-=sbr +:let line1=ScreenChar(10) +:call DoRecordScreen() +:let g:test=" Test 10: breakindent + shift by +1 + 'nu' + sbr=~ cpo+=n" +:set cpo+=n sbr=~ nu nuw=4 nolist briopt=sbr,min:0 +:let line1=ScreenChar(10) +:call DoRecordScreen() +:wincmd p +:let g:test="\n Test 11: strdisplaywidth when breakindent is on" +:set cpo-=n sbr=>> nu nuw=4 nolist briopt= ts=4 +:let text=getline(2) "skip leading tab when calculating text width +:let width = strlen(text[1:])+indent(2)*4+strlen(&sbr)*3 " text wraps 3 times +:$put =g:test +:$put =printf(\"strdisplaywidth: %d == calculated: %d\", strdisplaywidth(text), width) +:%w! test.out +:qa! +ENDTEST +dummy text diff --git a/src/nvim/testdir/test_breakindent.ok b/src/nvim/testdir/test_breakindent.ok new file mode 100644 index 0000000000..723cb25012 --- /dev/null +++ b/src/nvim/testdir/test_breakindent.ok @@ -0,0 +1,55 @@ + + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP + +Test 1: Simple breakindent + abcd + qrst + GHIJ + +Test 2: Simple breakindent + sbr=>> + abcd + >>qr + >>EF + +Test 3: Simple breakindent + briopt:sbr + abcd +++ qrst +++ GHIJ + +Test 4: Simple breakindent + min width: 18 + abcd + qrstuv + IJKLMN + + Test 5: Simple breakindent + shift by 2 + abcd + qr + EF + + Test 6: Simple breakindent + shift by -1 + abcd + qrstu + HIJKL + + Test 7: breakindent + shift by +1 + nu + sbr=? briopt:sbr + 2 ab +? m +? x + + Test 8: breakindent + shift:1 + nu + sbr=# list briopt:sbr + 2 ^Iabcd +# opq +# BCD + + Test 9: breakindent + shift by +1 + 'nu' + sbr=# list + 2 ^Iabcd + #op + #AB + + Test 10: breakindent + shift by +1 + 'nu' + sbr=~ cpo+=n + 2 ab +~ mn +~ yz + + Test 11: strdisplaywidth when breakindent is on +strdisplaywidth: 46 == calculated: 64 -- cgit From 22c782bcb24aa191163ebf80de5a75acaba823b3 Mon Sep 17 00:00:00 2001 From: Felipe Morales Date: Sat, 16 Aug 2014 12:18:05 -0400 Subject: vim-patch: 7.4.346 Do not cache "brishift". Indent was not updated when changing 'breakindentopt'. Reported by itchiny, fixed by chrisbra in vim patch 7.3.346 (https://code.google.com/p/vim/source/detail?r=3248c6e40aee01a7254d111dd846c6ec7889a804). --- src/nvim/indent.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/nvim/indent.c b/src/nvim/indent.c index 7673a297f6..9258ee93b6 100644 --- a/src/nvim/indent.c +++ b/src/nvim/indent.c @@ -464,11 +464,11 @@ int get_breakindent_win(win_T *wp, char_u *line) { prev_line = line; prev_ts = wp->w_buffer->b_p_ts; prev_indent = get_indent_str(line, - (int)wp->w_buffer->b_p_ts, wp->w_p_list) + wp->w_p_brishift; + (int)wp->w_buffer->b_p_ts, wp->w_p_list); } + bri = prev_indent + wp->w_p_brishift; /* indent minus the length of the showbreak string */ - bri = prev_indent; if (wp->w_p_brisbr) bri -= vim_strsize(p_sbr); -- cgit From dfdfee0260a95eb020d0b9cea2273b1f5002c184 Mon Sep 17 00:00:00 2001 From: Felipe Morales Date: Sat, 16 Aug 2014 12:58:11 -0400 Subject: vim-patch: 7.4.353 Make 'breakindent' work with the 'list' option. Originally patched in vim patch 7.4.353, by chrisbra (https://code.google.com/p/vim/source/detail?r=d42a1d3b74d40f580359dbd139d2d0dfa7235252) Updated version.c. --- src/nvim/charset.c | 1 - src/nvim/option.c | 5 +-- src/nvim/screen.c | 66 ++++++++++++++++++++++++++++++++++------ src/nvim/testdir/test_listlbr.in | 62 +++++++++++++++++++++++++++++++++++++ src/nvim/testdir/test_listlbr.ok | 39 ++++++++++++++++++++++++ src/nvim/version.c | 6 ++-- 6 files changed, 164 insertions(+), 15 deletions(-) create mode 100644 src/nvim/testdir/test_listlbr.in create mode 100644 src/nvim/testdir/test_listlbr.ok (limited to 'src') diff --git a/src/nvim/charset.c b/src/nvim/charset.c index 3392cceb9f..955f101a61 100644 --- a/src/nvim/charset.c +++ b/src/nvim/charset.c @@ -997,7 +997,6 @@ int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *he if (wp->w_p_lbr && vim_isbreak(c) && !vim_isbreak(s[1]) - && !wp->w_p_list && wp->w_p_wrap && (wp->w_width != 0)) { // Count all characters from first non-blank after a blank up to next diff --git a/src/nvim/option.c b/src/nvim/option.c index 7d40fb3d6b..a878ba6455 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -8157,9 +8157,10 @@ void find_mps_values(int *initc, int *findc, int *backwards, int switchit) } } -/* This is called when 'breakindentopt' is changed and whenn a window is +/* This is called when 'breakindentopt' is changed and when a window is initialized */ -int briopt_check() { +int briopt_check(void) +{ char_u *p; int bri_shift = 0; long bri_min = 20; diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 61e783f2b1..f6ee877a66 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -2197,6 +2197,7 @@ win_line ( char_u extra[18]; /* line number and 'fdc' must fit in here */ int n_extra = 0; /* number of extra chars */ char_u *p_extra = NULL; /* string of extra chars, plus NUL */ + char_u *p_extra_free = NULL; /* p_extra needs to be freed */ int c_extra = NUL; /* extra chars, all the same */ int extra_attr = 0; /* attributes when n_extra != 0 */ static char_u *at_end_str = (char_u *)""; /* used for p_extra when @@ -3108,6 +3109,10 @@ win_line ( } --n_extra; } else { + if (p_extra_free != NULL) { + free(p_extra_free); + p_extra_free = NULL; + } /* * Get a character from the line itself. */ @@ -3408,19 +3413,20 @@ win_line ( /* * Found last space before word: check for line break. */ - if (wp->w_p_lbr && vim_isbreak(c) && !vim_isbreak(*ptr) - && !wp->w_p_list) { + if (wp->w_p_lbr && vim_isbreak(c) && !vim_isbreak(*ptr)) { char_u *p = ptr - ( has_mbyte ? mb_l : 1); // TODO: is passing p for start of the line OK? - n_extra = win_lbr_chartabsize(wp, p, p, (colnr_T)vcol, NULL) - 1; + n_extra = win_lbr_chartabsize(wp, line, p, (colnr_T)vcol, NULL) - 1; c_extra = ' '; if (vim_iswhite(c)) { if (c == TAB) /* See "Tab alignment" below. */ FIX_FOR_BOGUSCOLS; - c = ' '; + if (!wp->w_p_list) { + c = ' '; + } } } @@ -3451,9 +3457,36 @@ win_line ( * into "ScreenLines". */ if (c == TAB && (!wp->w_p_list || lcs_tab1)) { + int tab_len = 0; /* tab amount depends on current column */ - n_extra = (int)wp->w_buffer->b_p_ts + tab_len = (int)wp->w_buffer->b_p_ts - vcol % (int)wp->w_buffer->b_p_ts - 1; + if (!wp->w_p_lbr) { + n_extra = tab_len; + } else { + char_u *p; + int len = n_extra; + int i; + int saved_nextra = n_extra; + + /* if n_extra > 0, it gives the number of chars to use for + * a tab, else we need to calculate the width for a tab */ + len = (tab_len * mb_char2len(lcs_tab2)); + if (n_extra > 0) { + len += n_extra - tab_len; + } + c = lcs_tab1; + p = xmalloc(len + 1); + memset(p, ' ', len); + p[len] = NUL; + p_extra_free = p; + for (i = 0; i < tab_len; i++) { + mb_char2bytes(lcs_tab2, p); + p += mb_char2len(lcs_tab2); + n_extra += mb_char2len(lcs_tab2) - (saved_nextra > 0 ? 1: 0); + } + p_extra = p_extra_free; + } /* Tab alignment should be identical regardless of * 'conceallevel' value. So tab compensates of all * previous concealed characters, and thus resets vcol_off @@ -3464,8 +3497,12 @@ win_line ( mb_utf8 = FALSE; /* don't draw as UTF-8 */ if (wp->w_p_list) { c = lcs_tab1; - c_extra = lcs_tab2; - n_attr = n_extra + 1; + if (wp->w_p_lbr) { + c_extra = NUL; /* using p_extra from above */ + } else { + c_extra = lcs_tab2; + } + n_attr = tab_len + 1; extra_attr = hl_attr(HLF_8); saved_attr2 = char_attr; /* save current attr */ mb_c = c; @@ -3527,9 +3564,20 @@ win_line ( p_extra = transchar(c); if ((dy_flags & DY_UHEX) && wp->w_p_rl) rl_mirror(p_extra); /* reverse "<12>" */ - n_extra = byte2cells(c) - 1; c_extra = NUL; - c = *p_extra++; + if (wp->w_p_lbr) { + char_u *p; + + c = *p_extra; + p = xmalloc(n_extra + 1); + memset(p, ' ', n_extra); + STRNCPY(p, p_extra + 1, STRLEN(p_extra) - 1); + p[n_extra] = NUL; + p_extra_free = p_extra = p; + } else { + n_extra = byte2cells(c) - 1; + c = *p_extra++; + } if (!attr_pri) { n_attr = n_extra + 1; extra_attr = hl_attr(HLF_8); diff --git a/src/nvim/testdir/test_listlbr.in b/src/nvim/testdir/test_listlbr.in new file mode 100644 index 0000000000..0d50d4b060 --- /dev/null +++ b/src/nvim/testdir/test_listlbr.in @@ -0,0 +1,62 @@ +Test for linebreak and list option + +STARTTEST +:so small.vim +:if !exists("+linebreak") | e! test.ok | w! test.out | qa! | endif +:10new|:vsp|:vert resize 20 +:put =\"\tabcdef hijklmn\tpqrstuvwxyz\u00a01060ABCDEFGHIJKLMNOP \" +:norm! zt +:set ts=4 sw=4 sts=4 linebreak sbr=+ wrap +:fu! ScreenChar(width) +: let c='' +: for j in range(1,4) +: for i in range(1,a:width) +: let c.=nr2char(screenchar(j, i)) +: endfor +: let c.="\n" +: endfor +: return c +:endfu +:fu! DoRecordScreen() +: wincmd l +: $put =printf(\"\n%s\", g:test) +: $put =g:line +: wincmd p +:endfu +:let g:test="Test 1: set linebreak" +:redraw! +:let line=ScreenChar(winwidth(0)) +:call DoRecordScreen() +:let g:test="Test 2: set linebreak + set list" +:set linebreak list listchars= +:redraw! +:let line=ScreenChar(winwidth(0)) +:call DoRecordScreen() +:let g:test ="Test 3: set linebreak + set list + fancy listchars" +:exe "set linebreak list listchars=nbsp:\u2423,tab:\u2595\u2014,trail:\u02d1,eol:\ub6" +:redraw! +:let line=ScreenChar(winwidth(0)) +:call DoRecordScreen() +:let g:test ="Test 4: set linebreak nolist" +:set nolist linebreak +:redraw! +:let line=ScreenChar(winwidth(0)) +:call DoRecordScreen() +:let g:test ="Test 5: set nolinebreak list" +:set list nolinebreak +:redraw! +:let line=ScreenChar(winwidth(0)) +:call DoRecordScreen() +:let g:test ="Test 6: set linebreak with tab and 1 line as long as screen: should break!" +:set nolist linebreak ts=8 +:let line="1\t".repeat('a', winwidth(0)-2) +:$put =line +:$ +:norm! zt +:redraw! +:let line=ScreenChar(winwidth(0)) +:call DoRecordScreen() +:%w! test.out +:qa! +ENDTEST +dummy text diff --git a/src/nvim/testdir/test_listlbr.ok b/src/nvim/testdir/test_listlbr.ok new file mode 100644 index 0000000000..f391d50aea --- /dev/null +++ b/src/nvim/testdir/test_listlbr.ok @@ -0,0 +1,39 @@ + + abcdef hijklmn pqrstuvwxyz 1060ABCDEFGHIJKLMNOP + +Test 1: set linebreak + abcdef ++hijklmn ++pqrstuvwxyz 1060ABC ++DEFGHIJKLMNOP + +Test 2: set linebreak + set list +^Iabcdef hijklmn^I ++pqrstuvwxyz 1060ABC ++DEFGHIJKLMNOP + + +Test 3: set linebreak + set list + fancy listchars +▕———abcdef ++hijklmn▕——— ++pqrstuvwxyz␣1060ABC ++DEFGHIJKLMNOPˑ¶ + +Test 4: set linebreak nolist + abcdef ++hijklmn ++pqrstuvwxyz 1060ABC ++DEFGHIJKLMNOP + +Test 5: set nolinebreak list +▕———abcdef hijklmn▕— ++pqrstuvwxyz␣1060ABC ++DEFGHIJKLMNOPˑ¶ +¶ +1 aaaaaaaaaaaaaaaaaa + +Test 6: set linebreak with tab and 1 line as long as screen: should break! +1 ++aaaaaaaaaaaaaaaaaa +~ +~ diff --git a/src/nvim/version.c b/src/nvim/version.c index 6e503200f0..6ec6bc0b7e 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -242,14 +242,14 @@ static int included_patches[] = { //356 NA //355, //354, - //353, + 353, //352, //351, //350, //349, //348, //347, - //346, + 346, //345, //344, //343, @@ -257,7 +257,7 @@ static int included_patches[] = { //341, //340 NA //339, - //338, + 338, //337, //336, 335, -- cgit From 244ea637244369e2b17496233096813ddf975f2f Mon Sep 17 00:00:00 2001 From: Felipe Morales Date: Sat, 16 Aug 2014 15:20:04 -0400 Subject: vim-patch:7.4.371 Problem: When 'linebreak' is set control characters are not correctly displayed. (Kimmy Lindvall) Solution: Set n_extra. (Christian Brabandt) --- src/nvim/screen.c | 3 +++ src/nvim/version.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/screen.c b/src/nvim/screen.c index f6ee877a66..5eaebfbf7c 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -3562,6 +3562,9 @@ win_line ( mb_utf8 = FALSE; /* don't draw as UTF-8 */ } else if (c != NUL) { p_extra = transchar(c); + if (n_extra == 0) { + n_extra = byte2cells(c); + } if ((dy_flags & DY_UHEX) && wp->w_p_rl) rl_mirror(p_extra); /* reverse "<12>" */ c_extra = NUL; diff --git a/src/nvim/version.c b/src/nvim/version.c index 6ec6bc0b7e..2c4172d6e0 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -224,7 +224,7 @@ static int included_patches[] = { //374, //373, //372, - //371, + 371, //370, //369, //368, -- cgit From 91aabcb75b2ff8fa3b718e2f08b5f723f5900d0f Mon Sep 17 00:00:00 2001 From: Felipe Morales Date: Sat, 16 Aug 2014 15:46:30 -0400 Subject: vim-patch:7.4.370 Problem: Linebreak test fails when encoding is not utf-8. (Danek Duvall) Solution: Split the test in a single byte one and a utf-8 one. (Christian Brabandt) --- src/nvim/testdir/test_listlbr.in | 18 ++++----------- src/nvim/testdir/test_listlbr.ok | 24 +++++--------------- src/nvim/testdir/test_listlbr_utf8.in | 41 +++++++++++++++++++++++++++++++++++ src/nvim/testdir/test_listlbr_utf8.ok | 14 ++++++++++++ src/nvim/version.c | 2 +- 5 files changed, 66 insertions(+), 33 deletions(-) create mode 100644 src/nvim/testdir/test_listlbr_utf8.in create mode 100644 src/nvim/testdir/test_listlbr_utf8.ok (limited to 'src') diff --git a/src/nvim/testdir/test_listlbr.in b/src/nvim/testdir/test_listlbr.in index 0d50d4b060..0cce4c23a5 100644 --- a/src/nvim/testdir/test_listlbr.in +++ b/src/nvim/testdir/test_listlbr.in @@ -1,10 +1,10 @@ -Test for linebreak and list option +Test for linebreak and list option (non-utf8) STARTTEST :so small.vim :if !exists("+linebreak") | e! test.ok | w! test.out | qa! | endif :10new|:vsp|:vert resize 20 -:put =\"\tabcdef hijklmn\tpqrstuvwxyz\u00a01060ABCDEFGHIJKLMNOP \" +:put =\"\tabcdef hijklmn\tpqrstuvwxyz_1060ABCDEFGHIJKLMNOP \" :norm! zt :set ts=4 sw=4 sts=4 linebreak sbr=+ wrap :fu! ScreenChar(width) @@ -32,22 +32,12 @@ STARTTEST :redraw! :let line=ScreenChar(winwidth(0)) :call DoRecordScreen() -:let g:test ="Test 3: set linebreak + set list + fancy listchars" -:exe "set linebreak list listchars=nbsp:\u2423,tab:\u2595\u2014,trail:\u02d1,eol:\ub6" -:redraw! -:let line=ScreenChar(winwidth(0)) -:call DoRecordScreen() -:let g:test ="Test 4: set linebreak nolist" +:let g:test ="Test 3: set linebreak nolist" :set nolist linebreak :redraw! :let line=ScreenChar(winwidth(0)) :call DoRecordScreen() -:let g:test ="Test 5: set nolinebreak list" -:set list nolinebreak -:redraw! -:let line=ScreenChar(winwidth(0)) -:call DoRecordScreen() -:let g:test ="Test 6: set linebreak with tab and 1 line as long as screen: should break!" +:let g:test ="Test 4: set linebreak with tab and 1 line as long as screen: should break!" :set nolist linebreak ts=8 :let line="1\t".repeat('a', winwidth(0)-2) :$put =line diff --git a/src/nvim/testdir/test_listlbr.ok b/src/nvim/testdir/test_listlbr.ok index f391d50aea..be323d4dc7 100644 --- a/src/nvim/testdir/test_listlbr.ok +++ b/src/nvim/testdir/test_listlbr.ok @@ -1,38 +1,26 @@ - abcdef hijklmn pqrstuvwxyz 1060ABCDEFGHIJKLMNOP + abcdef hijklmn pqrstuvwxyz_1060ABCDEFGHIJKLMNOP Test 1: set linebreak abcdef +hijklmn -+pqrstuvwxyz 1060ABC ++pqrstuvwxyz_1060ABC +DEFGHIJKLMNOP Test 2: set linebreak + set list ^Iabcdef hijklmn^I -+pqrstuvwxyz 1060ABC ++pqrstuvwxyz_1060ABC +DEFGHIJKLMNOP -Test 3: set linebreak + set list + fancy listchars -▕———abcdef -+hijklmn▕——— -+pqrstuvwxyz␣1060ABC -+DEFGHIJKLMNOPˑ¶ - -Test 4: set linebreak nolist +Test 3: set linebreak nolist abcdef +hijklmn -+pqrstuvwxyz 1060ABC ++pqrstuvwxyz_1060ABC +DEFGHIJKLMNOP - -Test 5: set nolinebreak list -▕———abcdef hijklmn▕— -+pqrstuvwxyz␣1060ABC -+DEFGHIJKLMNOPˑ¶ -¶ 1 aaaaaaaaaaaaaaaaaa -Test 6: set linebreak with tab and 1 line as long as screen: should break! +Test 4: set linebreak with tab and 1 line as long as screen: should break! 1 +aaaaaaaaaaaaaaaaaa ~ diff --git a/src/nvim/testdir/test_listlbr_utf8.in b/src/nvim/testdir/test_listlbr_utf8.in new file mode 100644 index 0000000000..f8888d5332 --- /dev/null +++ b/src/nvim/testdir/test_listlbr_utf8.in @@ -0,0 +1,41 @@ +Test for linebreak and list option in utf-8 mode + +STARTTEST +:so small.vim +:if !exists("+linebreak") | e! test.ok | w! test.out | qa! | endif +:so mbyte.vim +:if &enc !=? 'utf-8'|:e! test.ok|:w! test.out|qa!|endif +:10new|:vsp|:vert resize 20 +:put =\"\tabcdef hijklmn\tpqrstuvwxyz\u00a01060ABCDEFGHIJKLMNOP \" +:norm! zt +:set ts=4 sw=4 sts=4 linebreak sbr=+ wrap +:fu! ScreenChar(width) +: let c='' +: for j in range(1,4) +: for i in range(1,a:width) +: let c.=nr2char(screenchar(j, i)) +: endfor +: let c.="\n" +: endfor +: return c +:endfu +:fu! DoRecordScreen() +: wincmd l +: $put =printf(\"\n%s\", g:test) +: $put =g:line +: wincmd p +:endfu +:let g:test ="Test 1: set linebreak + set list + fancy listchars" +:exe "set linebreak list listchars=nbsp:\u2423,tab:\u2595\u2014,trail:\u02d1,eol:\ub6" +:redraw! +:let line=ScreenChar(winwidth(0)) +:call DoRecordScreen() +:let g:test ="Test 2: set nolinebreak list" +:set list nolinebreak +:redraw! +:let line=ScreenChar(winwidth(0)) +:call DoRecordScreen() +:%w! test.out +:qa! +ENDTEST +dummy text diff --git a/src/nvim/testdir/test_listlbr_utf8.ok b/src/nvim/testdir/test_listlbr_utf8.ok new file mode 100644 index 0000000000..576ccfb401 --- /dev/null +++ b/src/nvim/testdir/test_listlbr_utf8.ok @@ -0,0 +1,14 @@ + + abcdef hijklmn pqrstuvwxyz 1060ABCDEFGHIJKLMNOP + +Test 1: set linebreak + set list + fancy listchars +▕———abcdef ++hijklmn▕——— ++pqrstuvwxyz␣1060ABC ++DEFGHIJKLMNOPˑ¶ + +Test 2: set nolinebreak list +▕———abcdef hijklmn▕— ++pqrstuvwxyz␣1060ABC ++DEFGHIJKLMNOPˑ¶ +¶ diff --git a/src/nvim/version.c b/src/nvim/version.c index 2c4172d6e0..f72c4d6de4 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -225,7 +225,7 @@ static int included_patches[] = { //373, //372, 371, - //370, + 370, //369, //368, //367, -- cgit From 2e1c74586959e1f023d7d708af55258ba91a929c Mon Sep 17 00:00:00 2001 From: Felipe Morales Date: Sat, 16 Aug 2014 15:48:41 -0400 Subject: vim-patch:7.4.388 Problem: With 'linebreak' set and 'list' unset a Tab is not counted properly. (Kent Sibilev) Solution: Check the 'list' option. (Christian Brabandt) --- src/nvim/screen.c | 2 +- src/nvim/testdir/test_listlbr_utf8.in | 11 +++++++++++ src/nvim/testdir/test_listlbr_utf8.ok | 7 +++++++ src/nvim/version.c | 2 +- 4 files changed, 20 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 5eaebfbf7c..811f265902 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -3461,7 +3461,7 @@ win_line ( /* tab amount depends on current column */ tab_len = (int)wp->w_buffer->b_p_ts - vcol % (int)wp->w_buffer->b_p_ts - 1; - if (!wp->w_p_lbr) { + if (!wp->w_p_lbr || !wp->w_p_list) { n_extra = tab_len; } else { char_u *p; diff --git a/src/nvim/testdir/test_listlbr_utf8.in b/src/nvim/testdir/test_listlbr_utf8.in index f8888d5332..ba12adae05 100644 --- a/src/nvim/testdir/test_listlbr_utf8.in +++ b/src/nvim/testdir/test_listlbr_utf8.in @@ -30,11 +30,22 @@ STARTTEST :redraw! :let line=ScreenChar(winwidth(0)) :call DoRecordScreen() +:" :let g:test ="Test 2: set nolinebreak list" :set list nolinebreak :redraw! :let line=ScreenChar(winwidth(0)) :call DoRecordScreen() +:" +:let g:test ="Test 3: set linebreak nolist" +:$put =\"\t*mask = nil;\" +:$ +:norm! zt +:set nolist linebreak +:redraw! +:let line=ScreenChar(winwidth(0)) +:call DoRecordScreen() +:" :%w! test.out :qa! ENDTEST diff --git a/src/nvim/testdir/test_listlbr_utf8.ok b/src/nvim/testdir/test_listlbr_utf8.ok index 576ccfb401..634cf3906d 100644 --- a/src/nvim/testdir/test_listlbr_utf8.ok +++ b/src/nvim/testdir/test_listlbr_utf8.ok @@ -12,3 +12,10 @@ Test 2: set nolinebreak list +pqrstuvwxyz␣1060ABC +DEFGHIJKLMNOPˑ¶ ¶ + *mask = nil; + +Test 3: set linebreak nolist + *mask = nil; +~ +~ +~ diff --git a/src/nvim/version.c b/src/nvim/version.c index f72c4d6de4..6a008c1787 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -207,7 +207,7 @@ static int included_patches[] = { //391, //390, //389, - //388, + 388, //387, //386, //385, -- cgit From 359262d58d7255c695ebf7ee574e444d7cec233d Mon Sep 17 00:00:00 2001 From: Felipe Morales Date: Sat, 16 Aug 2014 15:54:26 -0400 Subject: vim-patch: 7.4.352 Problem: With 'linebreak' a tab causes a missing line break. Solution: Count a tab for what it's worth also for shorter lines. (Christian Brabandt) --- src/nvim/charset.c | 13 +++++++++---- src/nvim/version.c | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/nvim/charset.c b/src/nvim/charset.c index 955f101a61..57c4aec395 100644 --- a/src/nvim/charset.c +++ b/src/nvim/charset.c @@ -972,6 +972,7 @@ 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) { colnr_T col2; + colnr_T col_adj = 0; /* col + screen size of tab */ colnr_T colmax; int added; int mb_added = 0; @@ -991,6 +992,9 @@ int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *he // First get normal size, without 'linebreak' int size = win_chartabsize(wp, s, col); int c = *s; + if (tab_corr) { + col_adj = size - 1; + } // If 'linebreak' set check at a blank before a non-blank if the line // needs a break here @@ -1003,13 +1007,14 @@ int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *he // non-blank after a blank. numberextra = win_col_off(wp); col2 = col; - colmax = (colnr_T)(wp->w_width - numberextra); + colmax = (colnr_T)(wp->w_width - numberextra - col_adj); if (col >= colmax) { - n = colmax + win_col_off2(wp); + colmax += col_adj; + n = colmax + win_col_off2(wp); if (n > 0) { - colmax += (((col - colmax) / n) + 1) * n; + colmax += (((col - colmax) / n) + 1) * n - col_adj; } } @@ -1028,7 +1033,7 @@ int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *he col2 += win_chartabsize(wp, s, col2); if (col2 >= colmax) { /* doesn't fit */ - size = colmax - col; + size = colmax - col + col_adj; tab_corr = FALSE; break; } diff --git a/src/nvim/version.c b/src/nvim/version.c index 6a008c1787..5684a3f8d8 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -243,7 +243,7 @@ static int included_patches[] = { //355, //354, 353, - //352, + 352, //351, //350, //349, -- cgit From 3b0f7fe59392138c886063b09e3cf41b25d53056 Mon Sep 17 00:00:00 2001 From: Felipe Morales Date: Tue, 19 Aug 2014 01:36:33 -0400 Subject: update src/nvim/testdir/Makefile include breakindent and list related tests --- src/nvim/testdir/Makefile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile index a7f9dd8fa1..db88755a01 100644 --- a/src/nvim/testdir/Makefile +++ b/src/nvim/testdir/Makefile @@ -30,8 +30,10 @@ SCRIPTS := test_autoformat_join.out \ test91.out test92.out test93.out test94.out test95.out \ test96.out test97.out test98.out test99.out test100.out \ test101.out test102.out test103.out test104.out test105.out \ - test106.out test107.out \ - test_options.out + test106.out test107.out \ + test_options.out \ + test_listlbr.out test_listlbr_utf8.out \ + test_breakindent.out SCRIPTS_GUI := test16.out -- cgit