aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjörn Linse <bjorn.linse@gmail.com>2017-04-17 11:32:14 +0200
committerBjörn Linse <bjorn.linse@gmail.com>2017-04-21 12:32:38 +0200
commit9cdbbd49825561d642705990a2704b2241cf0584 (patch)
tree57c43ed070d90091d6d759c50ecfec2c6341a3aa
parent14b1becb5466003a65fa6be0517352abb7bc0f42 (diff)
downloadrneovim-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.c23
-rw-r--r--src/nvim/cursor_shape.c35
-rw-r--r--src/nvim/cursor_shape.h3
-rw-r--r--src/nvim/ex_getln.c16
-rw-r--r--src/nvim/mouse.c1
-rw-r--r--src/nvim/tui/tui.c60
-rw-r--r--src/nvim/ui.c31
-rw-r--r--src/nvim/ui.h2
-rw-r--r--src/nvim/ui_bridge.c4
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)
{