diff options
author | Ricky Zhou <ricky@rzhou.org> | 2018-08-25 15:07:52 -0700 |
---|---|---|
committer | Ricky Zhou <ricky@rzhou.org> | 2018-09-03 03:25:02 -0700 |
commit | 8fd3725cc8d54bced0a8fe1474986d93e9ef0b5b (patch) | |
tree | 30370753fb95186f9259db5809bff30f13453634 /src/nvim/screen.c | |
parent | 7ff63fcdc0ba1ce2b8500641f3742d5ada68d496 (diff) | |
download | rneovim-8fd3725cc8d54bced0a8fe1474986d93e9ef0b5b.tar.gz rneovim-8fd3725cc8d54bced0a8fe1474986d93e9ef0b5b.tar.bz2 rneovim-8fd3725cc8d54bced0a8fe1474986d93e9ef0b5b.zip |
tui: Hint wrapped lines to terminals.
Previously, when neovim would wrap a line across multiple lines,
terminal emulators could not detect that the lines represent a single
wrapped line as opposed to several separate lines. As a result, many
terminals' selection/copying functionality would treat a wrapped line as
several newline-delimited lines.
Fix this by reenabling a "special trick" from Vim. When a line is
wrapped, write the last character of that line followed by the first
character of the next line to the terminal. This hints to the terminal
that the next line is a continuation of the current line.
Extends the raw_line event with a "wrap" parameter which controls when
to do wrap hinting.
Diffstat (limited to 'src/nvim/screen.c')
-rw-r--r-- | src/nvim/screen.c | 57 |
1 files changed, 26 insertions, 31 deletions
diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 91840026a5..59e0ec2193 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -2012,7 +2012,7 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T } screen_line(row + wp->w_winrow, wp->w_wincol, wp->w_width, - wp->w_width, false, wp, wp->w_hl_attr_normal); + wp->w_width, false, wp, wp->w_hl_attr_normal, false); /* * Update w_cline_height and w_cline_folded if the cursor line was @@ -2900,7 +2900,7 @@ win_line ( && filler_todo <= 0 ) { screen_line(screen_row, wp->w_wincol, col, -wp->w_width, wp->w_p_rl, wp, - wp->w_hl_attr_normal); + wp->w_hl_attr_normal, false); // Pretend we have finished updating the window. Except when // 'cursorcolumn' is set. if (wp->w_p_cuc) { @@ -3996,7 +3996,7 @@ win_line ( } } screen_line(screen_row, wp->w_wincol, col, wp->w_width, wp->w_p_rl, wp, - wp->w_hl_attr_normal); + wp->w_hl_attr_normal, false); row++; /* @@ -4204,8 +4204,22 @@ win_line ( || (wp->w_p_list && lcs_eol != NUL && p_extra != at_end_str) || (n_extra != 0 && (c_extra != NUL || *p_extra != NUL))) ) { + bool wrap = wp->w_p_wrap // Wrapping enabled. + && filler_todo <= 0 // Not drawing diff filler lines. + && lcs_eol_one != -1 // Haven't printed the lcs_eol character. + && row != endrow - 1 // Not the last line being displayed. + && wp->w_width == Columns // Window spans the width of the screen. + && !wp->w_p_rl; // Not right-to-left. screen_line(screen_row, wp->w_wincol, col - boguscols, - wp->w_width, wp->w_p_rl, wp, wp->w_hl_attr_normal); + wp->w_width, wp->w_p_rl, wp, wp->w_hl_attr_normal, wrap); + if (wrap) { + // Force a redraw of the first column of the next line. + ScreenAttrs[LineOffset[screen_row + 1]] = -1; + + // Remember that the line wraps, used for modeless copy. + LineWraps[screen_row] = true; + } + boguscols = 0; ++row; ++screen_row; @@ -4232,28 +4246,6 @@ win_line ( break; } - if (ui_current_row() == screen_row - 1 - && filler_todo <= 0 - && wp->w_width == Columns) { - /* Remember that the line wraps, used for modeless copy. */ - LineWraps[screen_row - 1] = TRUE; - - // Special trick to make copy/paste of wrapped lines work with - // xterm/screen: write an extra character beyond the end of - // the line. This will work with all terminal types - // (regardless of the xn,am settings). - // Only do this if the cursor is on the current line - // (something has been written in it). - // Don't do this for double-width characters. - // Don't do this for a window not at the right screen border. - if (utf_off2cells(LineOffset[screen_row], - LineOffset[screen_row] + screen_Columns) != 2 - && utf_off2cells(LineOffset[screen_row - 1] + (int)Columns - 2, - LineOffset[screen_row] + screen_Columns) != 2) { - ui_add_linewrap(screen_row - 1); - } - } - col = 0; off = (unsigned)(current_ScreenLine - ScreenLines); if (wp->w_p_rl) { @@ -4319,9 +4311,11 @@ static int char_needs_redraw(int off_from, int off_to, int cols) * "rlflag" is TRUE in a rightleft window: * When TRUE and "clear_width" > 0, clear columns 0 to "endcol" * When FALSE and "clear_width" > 0, clear columns "endcol" to "clear_width" + * If "wrap" is true, then hint to the UI that "row" contains a line + * which has wrapped into the next row. */ -static void screen_line(int row, int coloff, int endcol, - int clear_width, int rlflag, win_T *wp, int bg_attr) +static void screen_line(int row, int coloff, int endcol, int clear_width, + int rlflag, win_T *wp, int bg_attr, bool wrap) { unsigned off_from; unsigned off_to; @@ -4482,7 +4476,7 @@ static void screen_line(int row, int coloff, int endcol, } if (clear_end > start_dirty) { ui_line(row, coloff+start_dirty, coloff+end_dirty, coloff+clear_end, - bg_attr); + bg_attr, wrap); } } @@ -5442,7 +5436,8 @@ void screen_puts_line_flush(bool set_cursor) if (set_cursor) { ui_cursor_goto(put_dirty_row, put_dirty_last); } - ui_line(put_dirty_row, put_dirty_first, put_dirty_last, put_dirty_last, 0); + ui_line(put_dirty_row, put_dirty_first, put_dirty_last, put_dirty_last, 0, + false); put_dirty_first = -1; put_dirty_last = 0; } @@ -5801,7 +5796,7 @@ void screen_fill(int start_row, int end_row, int start_col, int end_col, int c1, put_dirty_last = MAX(put_dirty_last, dirty_last); } else { int last = c2 != ' ' ? dirty_last : dirty_first + (c1 != ' '); - ui_line(row, dirty_first, last, dirty_last, attr); + ui_line(row, dirty_first, last, dirty_last, attr, false); } } |