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 | |
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.
-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) { |