diff options
author | Jonathan de Boyne Pollard <postmaster@localhost> | 2017-05-22 21:41:27 +0100 |
---|---|---|
committer | Justin M. Keyes <justinkz@gmail.com> | 2017-05-23 21:55:15 +0200 |
commit | 133ae5eeeff3b83e1a3e6da35b57dcdfb92287b0 (patch) | |
tree | cfdb7533ea9659a5ca96b071f69cf3705b28734d /src | |
parent | 0de7b17d03e2de18adcc9e7db27483160c4ac052 (diff) | |
download | rneovim-133ae5eeeff3b83e1a3e6da35b57dcdfb92287b0.tar.gz rneovim-133ae5eeeff3b83e1a3e6da35b57dcdfb92287b0.tar.bz2 rneovim-133ae5eeeff3b83e1a3e6da35b57dcdfb92287b0.zip |
tui: Improve scrolling mechanism.
Respect the BGE flag from terminfo rather than guessing that it is
always off. Emit DECLRMM and DECSLRM (or equivalent) to properly define
the scroll rectangle.
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/tui/tui.c | 108 |
1 files changed, 93 insertions, 15 deletions
diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index 5614a1738f..736d50ee8b 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -83,6 +83,9 @@ typedef struct { kvec_t(Rect) invalid_regions; int out_fd; bool scroll_region_is_full_screen; + bool can_change_scroll_region; + bool can_set_lr_margin; + bool can_set_left_right_margin; bool mouse_enabled; bool busy; cursorentry_T cursor_shapes[SHAPE_IDX_COUNT]; @@ -92,6 +95,7 @@ typedef struct { struct { int enable_mouse, disable_mouse; int enable_bracketed_paste, disable_bracketed_paste; + int enable_lr_margin, disable_lr_margin; int set_rgb_foreground, set_rgb_background; int set_cursor_color; int enable_focus_reporting, disable_focus_reporting; @@ -157,6 +161,8 @@ static void terminfo_start(UI *ui) data->unibi_ext.set_cursor_color = -1; data->unibi_ext.enable_bracketed_paste = -1; data->unibi_ext.disable_bracketed_paste = -1; + data->unibi_ext.enable_lr_margin = -1; + data->unibi_ext.disable_lr_margin = -1; data->unibi_ext.enable_focus_reporting = -1; data->unibi_ext.disable_focus_reporting = -1; data->unibi_ext.resize_screen = -1; @@ -171,6 +177,13 @@ static void terminfo_start(UI *ui) data->ut = unibi_dummy(); } fix_terminfo(data); + data->can_change_scroll_region = + !!unibi_get_str(data->ut, unibi_change_scroll_region); + data->can_set_lr_margin = + !!unibi_get_str(data->ut, unibi_set_lr_margin); + data->can_set_left_right_margin = + !!unibi_get_str(data->ut, unibi_set_left_margin_parm) + && !!unibi_get_str(data->ut, unibi_set_right_margin_parm); // Set 't_Co' from the result of unibilium & fix_terminfo. t_colors = unibi_get_num(data->ut, unibi_max_colors); // Enter alternate screen and clear @@ -426,9 +439,46 @@ static void clear_region(UI *ui, int top, int bot, int left, int right) unibi_goto(ui, grid->row, grid->col); } +static bool can_use_scroll(UI * ui) +{ + TUIData *data = ui->data; + UGrid *grid = &data->grid; + + return data->scroll_region_is_full_screen + || (data->can_change_scroll_region + && ((grid->left == 0 && grid->right == ui->width - 1) + || data->can_set_lr_margin + || data->can_set_left_right_margin)); +} + +static void set_scroll_region(UI *ui) +{ + TUIData *data = ui->data; + UGrid *grid = &data->grid; + + data->params[0].i = grid->top; + data->params[1].i = grid->bot; + unibi_out(ui, unibi_change_scroll_region); + if (grid->left != 0 || grid->right != ui->width - 1) { + unibi_out(ui, data->unibi_ext.enable_lr_margin); + if (data->can_set_lr_margin) { + data->params[0].i = grid->left; + data->params[1].i = grid->right; + unibi_out(ui, unibi_set_lr_margin); + } else { + data->params[0].i = grid->left; + unibi_out(ui, unibi_set_left_margin_parm); + data->params[0].i = grid->right; + unibi_out(ui, unibi_set_right_margin_parm); + } + } + unibi_goto(ui, grid->row, grid->col); +} + static void reset_scroll_region(UI *ui) { TUIData *data = ui->data; + UGrid *grid = &data->grid; if (0 <= data->unibi_ext.reset_scroll_region) { unibi_out(ui, data->unibi_ext.reset_scroll_region); @@ -437,6 +487,20 @@ static void reset_scroll_region(UI *ui) data->params[1].i = ui->height - 1; unibi_out(ui, unibi_change_scroll_region); } + if (grid->left != 0 || grid->right != ui->width - 1) { + if (data->can_set_lr_margin) { + data->params[0].i = 0; + data->params[1].i = ui->width - 1; + unibi_out(ui, unibi_set_lr_margin); + } else { + data->params[0].i = 0; + unibi_out(ui, unibi_set_left_margin_parm); + data->params[0].i = ui->width - 1; + unibi_out(ui, unibi_set_right_margin_parm); + } + unibi_out(ui, data->unibi_ext.disable_lr_margin); + } + unibi_goto(ui, grid->row, grid->col); } static void tui_resize(UI *ui, Integer width, Integer height) @@ -650,19 +714,22 @@ static void tui_scroll(UI *ui, Integer count) int clear_top, clear_bot; ugrid_scroll(grid, (int)count, &clear_top, &clear_bot); - if (data->scroll_region_is_full_screen || 0 <= unibi_change_scroll_region) { + if (can_use_scroll(ui)) { + bool scroll_clears_to_current_colour = + unibi_get_bool(data->ut, unibi_back_color_erase); + // Change terminal scroll region and move cursor to the top if (!data->scroll_region_is_full_screen) { - data->params[0].i = grid->top; - data->params[1].i = grid->bot; - unibi_out(ui, unibi_change_scroll_region); + set_scroll_region(ui); } unibi_goto(ui, grid->top, grid->left); // also set default color attributes or some terminals can become funny - HlAttrs clear_attrs = EMPTY_ATTRS; - clear_attrs.foreground = grid->fg; - clear_attrs.background = grid->bg; - update_attrs(ui, clear_attrs); + if (scroll_clears_to_current_colour) { + HlAttrs clear_attrs = EMPTY_ATTRS; + clear_attrs.foreground = grid->fg; + clear_attrs.background = grid->bg; + update_attrs(ui, clear_attrs); + } if (count > 0) { if (count == 1) { @@ -686,11 +753,9 @@ static void tui_scroll(UI *ui, Integer count) } unibi_goto(ui, grid->row, grid->col); - if (grid->bg != -1) { - // Update the cleared area of the terminal if its builtin scrolling - // facility was used and the background color is not the default. This is - // required because scrolling may leave wrong background in the cleared - // area. + if (!scroll_clears_to_current_colour) { + // This is required because scrolling will leave wrong background in the + // cleared area on non-bge terminals. clear_region(ui, clear_top, clear_bot, grid->left, grid->right); } } else { @@ -1025,13 +1090,21 @@ static void fix_terminfo(TUIData *data) unibi_set_if_empty(ut, unibi_cursor_invisible, "\x1b[?25l"); unibi_set_if_empty(ut, unibi_flash_screen, "\x1b[?5h$<100/>\x1b[?5l"); unibi_set_if_empty(ut, unibi_exit_attribute_mode, "\x1b(B\x1b[m"); + unibi_set_if_empty(ut, unibi_set_tb_margin, "\x1b[%i%p1%d;%p2%dr"); + unibi_set_if_empty(ut, unibi_set_lr_margin, "\x1b[%i%p1%d;%p2%ds"); + unibi_set_if_empty(ut, unibi_set_left_margin_parm, "\x1b[%i%p1%ds"); + unibi_set_if_empty(ut, unibi_set_right_margin_parm, "\x1b[%i;%p2%ds"); unibi_set_if_empty(ut, unibi_change_scroll_region, "\x1b[%i%p1%d;%p2%dr"); unibi_set_if_empty(ut, unibi_clear_screen, "\x1b[H\x1b[2J"); unibi_set_if_empty(ut, unibi_from_status_line, "\x07"); - data->unibi_ext.reset_scroll_region = (int)unibi_add_ext_str(ut, NULL, - "\x1b[r"); + unibi_set_bool(ut, unibi_back_color_erase, true); } + data->unibi_ext.enable_lr_margin = (int)unibi_add_ext_str(ut, NULL, + "\x1b[?69h"); + data->unibi_ext.disable_lr_margin = (int)unibi_add_ext_str(ut, NULL, + "\x1b[?69l"); + data->unibi_ext.enable_bracketed_paste = (int)unibi_add_ext_str(ut, NULL, "\x1b[?2004h"); data->unibi_ext.disable_bracketed_paste = (int)unibi_add_ext_str(ut, NULL, @@ -1068,6 +1141,11 @@ static void fix_terminfo(TUIData *data) "\x1b[8;%p1%d;%p2%dt"); } + if (data->term == kTermXTerm || data->term == kTermRxvt) { + data->unibi_ext.reset_scroll_region = (int)unibi_add_ext_str(ut, NULL, + "\x1b[r"); + } + end: // Fill some empty slots with common terminal strings if (data->term == kTermiTerm) { |