diff options
author | Björn Linse <bjorn.linse@gmail.com> | 2017-04-17 11:32:14 +0200 |
---|---|---|
committer | Björn Linse <bjorn.linse@gmail.com> | 2017-04-21 12:32:38 +0200 |
commit | 9cdbbd49825561d642705990a2704b2241cf0584 (patch) | |
tree | 57c43ed070d90091d6d759c50ecfec2c6341a3aa | |
parent | 14b1becb5466003a65fa6be0517352abb7bc0f42 (diff) | |
download | rneovim-9cdbbd49825561d642705990a2704b2241cf0584.tar.gz rneovim-9cdbbd49825561d642705990a2704b2241cf0584.tar.bz2 rneovim-9cdbbd49825561d642705990a2704b2241cf0584.zip |
ui: support more cursor shape modes
throttle unneccessary cursor shape events
-rw-r--r-- | src/nvim/api/ui.c | 23 | ||||
-rw-r--r-- | src/nvim/cursor_shape.c | 35 | ||||
-rw-r--r-- | src/nvim/cursor_shape.h | 3 | ||||
-rw-r--r-- | src/nvim/ex_getln.c | 16 | ||||
-rw-r--r-- | src/nvim/mouse.c | 1 | ||||
-rw-r--r-- | src/nvim/tui/tui.c | 60 | ||||
-rw-r--r-- | src/nvim/ui.c | 31 | ||||
-rw-r--r-- | src/nvim/ui.h | 2 | ||||
-rw-r--r-- | src/nvim/ui_bridge.c | 4 |
9 files changed, 93 insertions, 82 deletions
diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index de60339e5f..0053050717 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -266,19 +266,14 @@ static void remote_ui_mouse_off(UI *ui) push_call(ui, "mouse_off", args); } -static void remote_ui_mode_change(UI *ui, int mode) +static void remote_ui_mode_change(UI *ui, int mode_idx) { Array args = ARRAY_DICT_INIT; - if (mode == INSERT) { - ADD(args, STRING_OBJ(cstr_to_string("insert"))); - } else if (mode == REPLACE) { - ADD(args, STRING_OBJ(cstr_to_string("replace"))); - } else if (mode == CMDLINE) { - ADD(args, STRING_OBJ(cstr_to_string("cmdline"))); - } else { - assert(mode == NORMAL); - ADD(args, STRING_OBJ(cstr_to_string("normal"))); - } + + char *full_name = shape_table[mode_idx].full_name; + ADD(args, STRING_OBJ(cstr_to_string(full_name))); + + ADD(args, INTEGER_OBJ(mode_idx)); push_call(ui, "mode_change", args); } @@ -393,8 +388,10 @@ static void remote_ui_update_sp(UI *ui, int sp) static void remote_ui_flush(UI *ui) { UIData *data = ui->data; - channel_send_event(data->channel_id, "redraw", data->buffer); - data->buffer = (Array)ARRAY_DICT_INIT; + if (data->buffer.size > 0) { + channel_send_event(data->channel_id, "redraw", data->buffer); + data->buffer = (Array)ARRAY_DICT_INIT; + } } static void remote_ui_suspend(UI *ui) diff --git a/src/nvim/cursor_shape.c b/src/nvim/cursor_shape.c index 34ee53bf75..57dc241c54 100644 --- a/src/nvim/cursor_shape.c +++ b/src/nvim/cursor_shape.c @@ -11,7 +11,7 @@ #include "nvim/ui.h" /// Handling of cursor and mouse pointer shapes in various modes. -static cursorentry_T shape_table[SHAPE_IDX_COUNT] = +cursorentry_T shape_table[SHAPE_IDX_COUNT] = { // Values are set by 'guicursor' and 'mouseshape'. // Adjust the SHAPE_IDX_ defines when changing this! @@ -63,6 +63,7 @@ Dictionary cursor_shape_dict(void) PUT(dic, "id_lm", INTEGER_OBJ(cur->id_lm)); } PUT(dic, "short_name", STRING_OBJ(cstr_to_string(cur->name))); + PUT(dic, "mode_idx", INTEGER_OBJ(i)); PUT(all, cur->full_name, DICTIONARY_OBJ(dic)); } @@ -260,3 +261,35 @@ int cursor_mode_str2int(const char *mode) return -1; } + +/// Return the index into shape_table[] for the current mode. +int cursor_get_mode_idx(void) +{ + if (State == SHOWMATCH) { + return SHAPE_IDX_SM; + } else if (State & VREPLACE_FLAG) { + return SHAPE_IDX_R; + } else if (State & REPLACE_FLAG) { + return SHAPE_IDX_R; + } else if (State & INSERT) { + return SHAPE_IDX_I; + } else if (State & CMDLINE) { + if (cmdline_at_end()) { + return SHAPE_IDX_C; + } else if (cmdline_overstrike()) { + return SHAPE_IDX_CR; + } else { + return SHAPE_IDX_CI; + } + } else if (finish_op) { + return SHAPE_IDX_O; + } else if (VIsual_active) { + if (*p_sel == 'e') { + return SHAPE_IDX_VE; + } else { + return SHAPE_IDX_V; + } + } else { + return SHAPE_IDX_N; + } +} diff --git a/src/nvim/cursor_shape.h b/src/nvim/cursor_shape.h index 7cf65cba3c..2c466603f0 100644 --- a/src/nvim/cursor_shape.h +++ b/src/nvim/cursor_shape.h @@ -25,7 +25,7 @@ SHAPE_IDX_MORE = 14, ///< Hit-return or More SHAPE_IDX_MOREL = 15, ///< Hit-return or More in last line SHAPE_IDX_SM = 16, ///< showing matching paren SHAPE_IDX_COUNT = 17 -} MouseMode; +} ModeShape; typedef enum { SHAPE_BLOCK = 0, ///< block cursor @@ -53,6 +53,7 @@ typedef struct cursor_entry { char used_for; ///< SHAPE_MOUSE and/or SHAPE_CURSOR } cursorentry_T; +extern cursorentry_T shape_table[SHAPE_IDX_COUNT]; #ifdef INCLUDE_GENERATED_DECLARATIONS # include "cursor_shape.h.generated.h" diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 0b6036ace9..5d228e7492 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -351,6 +351,7 @@ static int command_line_check(VimState *state) quit_more = false; // reset after CTRL-D which had a more-prompt cursorcmd(); // set the cursor on the right spot + ui_cursor_shape(); return 1; } @@ -2092,6 +2093,18 @@ redraw: return (char_u *)line_ga.ga_data; } +bool cmdline_overstrike(void) +{ + return ccline.overstrike; +} + + +/// Return true if the cursor is at the end of the cmdline. +bool cmdline_at_end(void) +{ + return (ccline.cmdpos >= ccline.cmdlen); +} + /* * Allocate a new command line buffer. * Assigns the new buffer to ccline.cmdbuff and ccline.cmdbufflen. @@ -2262,6 +2275,7 @@ void putcmdline(int c, int shift) draw_cmdline(ccline.cmdpos, ccline.cmdlen - ccline.cmdpos); msg_no_more = FALSE; cursorcmd(); + ui_cursor_shape(); } /* @@ -2281,6 +2295,7 @@ void unputcmdline(void) draw_cmdline(ccline.cmdpos, 1); msg_no_more = FALSE; cursorcmd(); + ui_cursor_shape(); } /* @@ -2598,6 +2613,7 @@ void redrawcmdline(void) compute_cmdrow(); redrawcmd(); cursorcmd(); + ui_cursor_shape(); } static void redrawcmdprompt(void) diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c index 2ebe199f47..0029f364da 100644 --- a/src/nvim/mouse.c +++ b/src/nvim/mouse.c @@ -456,6 +456,7 @@ void setmouse(void) { int checkfor; + ui_cursor_shape(); /* be quick when mouse is off */ if (*p_mouse == NUL) diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index f34f5f1bc4..3498e8f4e7 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -73,7 +73,7 @@ typedef struct { bool busy; cursorentry_T cursor_shapes[SHAPE_IDX_COUNT]; HlAttrs print_attrs; - int showing_mode; + ModeShape showing_mode; struct { int enable_mouse, disable_mouse; int enable_bracketed_paste, disable_bracketed_paste; @@ -131,7 +131,7 @@ static void terminfo_start(UI *ui) data->can_use_terminal_scroll = true; data->bufpos = 0; data->bufsize = sizeof(data->buf) - CNORM_COMMAND_MAX_SIZE; - data->showing_mode = 0; + data->showing_mode = SHAPE_IDX_N; data->unibi_ext.enable_mouse = -1; data->unibi_ext.disable_mouse = -1; data->unibi_ext.set_cursor_color = -1; @@ -173,7 +173,7 @@ static void terminfo_stop(UI *ui) { TUIData *data = ui->data; // Destroy output stuff - tui_mode_change(ui, NORMAL); + tui_mode_change(ui, SHAPE_IDX_N); tui_mouse_off(ui); unibi_out(ui, unibi_exit_attribute_mode); // cursor should be set to normal before exiting alternate screen @@ -451,7 +451,7 @@ CursorShape tui_cursor_decode_shape(const char *shape_str) return shape; } -static cursorentry_T decode_cursor_entry(Dictionary args) +static cursorentry_T decode_cursor_entry(Dictionary args, int *mode_idx) { cursorentry_T r; @@ -467,6 +467,8 @@ static cursorentry_T decode_cursor_entry(Dictionary args) r.blinkoff = (int)value.data.integer; } else if (strequal(key, "hl_id")) { r.id = (int)value.data.integer; + } else if (strequal(key, "mode_idx")) { + *mode_idx = (int)value.data.integer; } } return r; @@ -484,15 +486,15 @@ static void tui_cursor_style_set(UI *ui, bool enabled, Dictionary args) // Keys: as defined by `shape_table`. for (size_t i = 0; i < args.size; i++) { char *mode_name = args.items[i].key.data; - const int mode_id = cursor_mode_str2int(mode_name); - assert(mode_id >= 0); - cursorentry_T r = decode_cursor_entry(args.items[i].value.data.dictionary); + int mode_idx; + cursorentry_T r = decode_cursor_entry(args.items[i].value.data.dictionary, + &mode_idx); + assert(mode_idx >= 0); r.full_name = mode_name; - data->cursor_shapes[mode_id] = r; + data->cursor_shapes[mode_idx] = r; } - MouseMode cursor_mode = tui_mode2cursor(data->showing_mode); - tui_set_cursor(ui, cursor_mode); + tui_set_mode(ui, data->showing_mode); } static void tui_update_menu(UI *ui) @@ -529,7 +531,7 @@ static void tui_mouse_off(UI *ui) } /// @param mode one of SHAPE_XXX -static void tui_set_cursor(UI *ui, MouseMode mode) +static void tui_set_mode(UI *ui, ModeShape mode) { if (!cursor_style_enabled) { return; @@ -584,42 +586,12 @@ static void tui_set_cursor(UI *ui, MouseMode mode) } } -/// Returns cursor mode from edit mode -static MouseMode tui_mode2cursor(int mode) -{ - switch (mode) { - case INSERT: return SHAPE_IDX_I; - case CMDLINE: return SHAPE_IDX_C; - case REPLACE: return SHAPE_IDX_R; - case NORMAL: - default: return SHAPE_IDX_N; - } -} - /// @param mode editor mode -static void tui_mode_change(UI *ui, int mode) +static void tui_mode_change(UI *ui, int mode_idx) { TUIData *data = ui->data; - - if (mode == INSERT) { - if (data->showing_mode != INSERT) { - tui_set_cursor(ui, SHAPE_IDX_I); - } - } else if (mode == CMDLINE) { - if (data->showing_mode != CMDLINE) { - tui_set_cursor(ui, SHAPE_IDX_C); - } - } else if (mode == REPLACE) { - if (data->showing_mode != REPLACE) { - tui_set_cursor(ui, SHAPE_IDX_R); - } - } else { - assert(mode == NORMAL); - if (data->showing_mode != NORMAL) { - tui_set_cursor(ui, SHAPE_IDX_N); - } - } - data->showing_mode = mode; + tui_set_mode(ui, (ModeShape)mode_idx); + data->showing_mode = (ModeShape)mode_idx; } static void tui_set_scroll_region(UI *ui, int top, int bot, int left, diff --git a/src/nvim/ui.c b/src/nvim/ui.c index 28f71b7ef2..8c5e579301 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -53,6 +53,7 @@ static int current_attr_code = 0; static bool pending_cursor_update = false; static int busy = 0; static int height, width; +static int old_mode_idx = -1; // UI_CALL invokes a function on all registered UI instances. The functions can // have 0-5 arguments (configurable by SELECT_NTH). @@ -150,12 +151,6 @@ void ui_event(char *name, Array args) } } -// May update the shape of the cursor. -void ui_cursor_shape(void) -{ - ui_mode_change(); -} - void ui_refresh(void) { if (!ui_active()) { @@ -181,6 +176,8 @@ void ui_refresh(void) screen_resize(width, height); pum_set_external(pum_external); ui_cursor_style_set(); + old_mode_idx = -1; + ui_cursor_shape(); } static void ui_refresh_event(void **argv) @@ -541,25 +538,19 @@ static void flush_cursor_update(void) } } -// Notify that the current mode has changed. Can be used to change cursor -// shape, for example. -static void ui_mode_change(void) +/// Check if current mode has changed. +/// May update the shape of the cursor. +void ui_cursor_shape(void) { - int mode; if (!full_screen) { return; } - // Get a simple UI mode out of State. - if ((State & REPLACE) == REPLACE) { - mode = REPLACE; - } else if (State & INSERT) { - mode = INSERT; - } else if (State & CMDLINE) { - mode = CMDLINE; - } else { - mode = NORMAL; + int mode_idx = cursor_get_mode_idx(); + + if (old_mode_idx != mode_idx) { + old_mode_idx = mode_idx; + UI_CALL(mode_change, mode_idx); } - UI_CALL(mode_change, mode); conceal_check_cursur_line(); } diff --git a/src/nvim/ui.h b/src/nvim/ui.h index 8ffc5a45a6..d63ceb106c 100644 --- a/src/nvim/ui.h +++ b/src/nvim/ui.h @@ -28,7 +28,7 @@ struct ui_t { void (*busy_stop)(UI *ui); void (*mouse_on)(UI *ui); void (*mouse_off)(UI *ui); - void (*mode_change)(UI *ui, int mode); + void (*mode_change)(UI *ui, int mode_idx); void (*set_scroll_region)(UI *ui, int top, int bot, int left, int right); void (*scroll)(UI *ui, int count); void (*highlight_set)(UI *ui, HlAttrs attrs); diff --git a/src/nvim/ui_bridge.c b/src/nvim/ui_bridge.c index 9f780663ac..59942fb2cb 100644 --- a/src/nvim/ui_bridge.c +++ b/src/nvim/ui_bridge.c @@ -249,9 +249,9 @@ static void ui_bridge_mouse_off_event(void **argv) ui->mouse_off(ui); } -static void ui_bridge_mode_change(UI *b, int mode) +static void ui_bridge_mode_change(UI *b, int mode_idx) { - UI_CALL(b, mode_change, 2, b, INT2PTR(mode)); + UI_CALL(b, mode_change, 2, b, INT2PTR(mode_idx)); } static void ui_bridge_mode_change_event(void **argv) { |