mirror of
https://github.com/neovim/neovim.git
synced 2024-12-24 13:15:09 -07:00
Merge pull request #8915 from rickyz/line_wrapping
Fix terminal line wrapping detection in the TUI.
This commit is contained in:
commit
c5790d9189
@ -424,7 +424,8 @@ static void remote_ui_put(UI *ui, const char *cell)
|
||||
static void remote_ui_raw_line(UI *ui, Integer grid, Integer row,
|
||||
Integer startcol, Integer endcol,
|
||||
Integer clearcol, Integer clearattr,
|
||||
const schar_T *chunk, const sattr_T *attrs)
|
||||
Boolean wrap, const schar_T *chunk,
|
||||
const sattr_T *attrs)
|
||||
{
|
||||
UIData *data = ui->data;
|
||||
if (ui->ui_ext[kUINewgrid]) {
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#define EVENT_HANDLER_MAX_ARGC 9
|
||||
#define EVENT_HANDLER_MAX_ARGC 10
|
||||
|
||||
typedef void (*argv_callback)(void **argv);
|
||||
typedef struct message {
|
||||
|
@ -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) {
|
||||
@ -3989,7 +3989,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++;
|
||||
|
||||
/*
|
||||
@ -4197,8 +4197,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;
|
||||
@ -4225,28 +4239,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) {
|
||||
@ -4312,9 +4304,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;
|
||||
@ -4475,7 +4469,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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5435,7 +5429,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;
|
||||
}
|
||||
@ -5794,7 +5789,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1191,7 +1191,8 @@ static void tui_option_set(UI *ui, String name, Object value)
|
||||
|
||||
static void tui_raw_line(UI *ui, Integer g, Integer linerow, Integer startcol,
|
||||
Integer endcol, Integer clearcol, Integer clearattr,
|
||||
const schar_T *chunk, const sattr_T *attrs)
|
||||
Boolean wrap, const schar_T *chunk,
|
||||
const sattr_T *attrs)
|
||||
{
|
||||
TUIData *data = ui->data;
|
||||
UGrid *grid = &data->grid;
|
||||
@ -1212,6 +1213,21 @@ static void tui_raw_line(UI *ui, Integer g, Integer linerow, Integer startcol,
|
||||
clear_region(ui, (int)linerow, (int)linerow, (int)endcol, (int)clearcol-1,
|
||||
cl_attrs);
|
||||
}
|
||||
|
||||
if (wrap && ui->width == grid->width && linerow + 1 < grid->height) {
|
||||
// Only do line wrapping if the grid width is equal to the terminal
|
||||
// width and the line continuation is within the grid.
|
||||
|
||||
if (endcol != grid->width) {
|
||||
// Print the last cell of the row, if we haven't already done so.
|
||||
cursor_goto(ui, (int)linerow, grid->width - 1);
|
||||
print_cell(ui, &grid->cells[linerow][grid->width - 1]);
|
||||
}
|
||||
|
||||
// Wrap the cursor over to the next line. The next line will be
|
||||
// printed immediately without an intervening newline.
|
||||
final_column_wrap(ui);
|
||||
}
|
||||
}
|
||||
|
||||
static void invalidate(UI *ui, int top, int bot, int left, int right)
|
||||
|
@ -80,7 +80,7 @@ static char uilog_last_event[1024] = { 0 };
|
||||
#endif
|
||||
|
||||
// UI_CALL invokes a function on all registered UI instances. The functions can
|
||||
// have 0-5 arguments (configurable by SELECT_NTH).
|
||||
// have 0-10 arguments (configurable by SELECT_NTH).
|
||||
//
|
||||
// See http://stackoverflow.com/a/11172679 for how it works.
|
||||
#ifdef _MSC_VER
|
||||
@ -102,9 +102,9 @@ static char uilog_last_event[1024] = { 0 };
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
#define CNT(...) SELECT_NTH(__VA_ARGS__, MORE, MORE, MORE, \
|
||||
MORE, MORE, MORE, MORE, MORE, ZERO, ignore)
|
||||
#define SELECT_NTH(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, ...) a10
|
||||
#define CNT(...) SELECT_NTH(__VA_ARGS__, MORE, MORE, MORE, MORE, MORE, \
|
||||
MORE, MORE, MORE, MORE, ZERO, ignore)
|
||||
#define SELECT_NTH(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, ...) a11
|
||||
#define UI_CALL_HELPER(c, ...) UI_CALL_HELPER2(c, __VA_ARGS__)
|
||||
// Resolves to UI_CALL_MORE or UI_CALL_ZERO.
|
||||
#define UI_CALL_HELPER2(c, ...) UI_CALL_##c(__VA_ARGS__)
|
||||
@ -315,10 +315,11 @@ void ui_set_ext_option(UI *ui, UIExtension ext, bool active)
|
||||
}
|
||||
}
|
||||
|
||||
void ui_line(int row, int startcol, int endcol, int clearcol, int clearattr)
|
||||
void ui_line(int row, int startcol, int endcol, int clearcol, int clearattr,
|
||||
bool wrap)
|
||||
{
|
||||
size_t off = LineOffset[row]+(size_t)startcol;
|
||||
UI_CALL(raw_line, 1, row, startcol, endcol, clearcol, clearattr,
|
||||
UI_CALL(raw_line, 1, row, startcol, endcol, clearcol, clearattr, wrap,
|
||||
(const schar_T *)ScreenLines+off, (const sattr_T *)ScreenAttrs+off);
|
||||
if (p_wd) { // 'writedelay': flush & delay each time.
|
||||
int old_row = row, old_col = col;
|
||||
@ -341,32 +342,6 @@ void ui_cursor_goto(int new_row, int new_col)
|
||||
pending_cursor_update = true;
|
||||
}
|
||||
|
||||
void ui_add_linewrap(int row)
|
||||
{
|
||||
// TODO(bfredl): check that this actually still works
|
||||
// and move to TUI module in that case.
|
||||
#if 0
|
||||
// First make sure we are at the end of the screen line,
|
||||
// then output the same character again to let the
|
||||
// terminal know about the wrap. If the terminal doesn't
|
||||
// auto-wrap, we overwrite the character.
|
||||
if (ui_current_col() != Columns) {
|
||||
screen_char(LineOffset[row] + (unsigned)Columns - 1, row,
|
||||
(int)(Columns - 1));
|
||||
}
|
||||
|
||||
// When there is a multi-byte character, just output a
|
||||
// space to keep it simple. */
|
||||
if (ScreenLines[LineOffset[row] + (Columns - 1)][1] != 0) {
|
||||
ui_putc(' ');
|
||||
} else {
|
||||
ui_puts(ScreenLines[LineOffset[row] + (Columns - 1)]);
|
||||
}
|
||||
// force a redraw of the first char on the next line
|
||||
ScreenAttrs[LineOffset[row+1]] = (sattr_T)-1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void ui_mode_info_set(void)
|
||||
{
|
||||
pending_mode_info_update = true;
|
||||
|
@ -47,7 +47,7 @@ struct ui_t {
|
||||
// in to the public grid_line format.
|
||||
void (*raw_line)(UI *ui, Integer grid, Integer row, Integer startcol,
|
||||
Integer endcol, Integer clearcol, Integer clearattr,
|
||||
const schar_T *chunk, const sattr_T *attrs);
|
||||
Boolean wrap, const schar_T *chunk, const sattr_T *attrs);
|
||||
void (*event)(UI *ui, char *name, Array args, bool *args_consumed);
|
||||
void (*stop)(UI *ui);
|
||||
void (*inspect)(UI *ui, Dictionary *info);
|
||||
|
@ -152,24 +152,24 @@ static void ui_bridge_raw_line_event(void **argv)
|
||||
UI *ui = UI(argv[0]);
|
||||
ui->raw_line(ui, PTR2INT(argv[1]), PTR2INT(argv[2]), PTR2INT(argv[3]),
|
||||
PTR2INT(argv[4]), PTR2INT(argv[5]), PTR2INT(argv[6]),
|
||||
argv[7], argv[8]);
|
||||
xfree(argv[7]);
|
||||
PTR2INT(argv[7]), argv[8], argv[9]);
|
||||
xfree(argv[8]);
|
||||
xfree(argv[9]);
|
||||
}
|
||||
static void ui_bridge_raw_line(UI *ui, Integer grid, Integer row,
|
||||
Integer startcol, Integer endcol,
|
||||
Integer clearcol, Integer clearattr,
|
||||
const schar_T *chunk, const sattr_T *attrs)
|
||||
Boolean wrap, const schar_T *chunk,
|
||||
const sattr_T *attrs)
|
||||
{
|
||||
size_t ncol = (size_t)(endcol-startcol);
|
||||
schar_T *c = xmemdup(chunk, ncol * sizeof(schar_T));
|
||||
sattr_T *hl = xmemdup(attrs, ncol * sizeof(sattr_T));
|
||||
UI_BRIDGE_CALL(ui, raw_line, 9, ui, INT2PTR(grid), INT2PTR(row),
|
||||
UI_BRIDGE_CALL(ui, raw_line, 10, ui, INT2PTR(grid), INT2PTR(row),
|
||||
INT2PTR(startcol), INT2PTR(endcol), INT2PTR(clearcol),
|
||||
INT2PTR(clearattr), c, hl);
|
||||
INT2PTR(clearattr), INT2PTR(wrap), c, hl);
|
||||
}
|
||||
|
||||
|
||||
static void ui_bridge_suspend(UI *b)
|
||||
{
|
||||
UIBridgeData *data = (UIBridgeData *)b;
|
||||
|
Loading…
Reference in New Issue
Block a user