diff options
Diffstat (limited to 'src/nvim/terminal.c')
| -rw-r--r-- | src/nvim/terminal.c | 153 |
1 files changed, 67 insertions, 86 deletions
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c index ffe650f416..d8d529d0f6 100644 --- a/src/nvim/terminal.c +++ b/src/nvim/terminal.c @@ -374,6 +374,7 @@ void terminal_enter(void) TerminalState state, *s = &state; memset(s, 0, sizeof(TerminalState)); s->term = buf->terminal; + stop_insert_mode = false; // Ensure the terminal is properly sized. Ideally window size management // code should always have resized the terminal already, but check here to @@ -400,9 +401,9 @@ void terminal_enter(void) showmode(); curwin->w_redr_status = true; // For mode() in statusline. #8323 ui_busy_start(); - redraw(false); s->state.execute = terminal_execute; + s->state.check = terminal_check; state_enter(&s->state); restart_edit = 0; @@ -415,8 +416,10 @@ void terminal_enter(void) // draw the unfocused cursor invalidate_terminal(s->term, s->term->cursor.row, s->term->cursor.row + 1); + if (curbuf->terminal == s->term && !s->close) { + terminal_check_cursor(); + } unshowmode(true); - redraw(curbuf->handle != s->term->buf_handle); ui_busy_stop(); if (s->close) { bool wipe = s->term->buf_handle != 0; @@ -427,6 +430,45 @@ void terminal_enter(void) } } +static void terminal_check_cursor(void) +{ + Terminal *term = curbuf->terminal; + curwin->w_wrow = term->cursor.row; + curwin->w_wcol = term->cursor.col + win_col_off(curwin); + curwin->w_cursor.lnum = MIN(curbuf->b_ml.ml_line_count, + row_to_linenr(term, term->cursor.row)); + // Nudge cursor when returning to normal-mode. + int off = is_focused(term) ? 0 : (curwin->w_p_rl ? 1 : -1); + curwin->w_cursor.col = MAX(0, term->cursor.col + win_col_off(curwin) + off); + curwin->w_cursor.coladd = 0; + mb_check_adjust_col(curwin); +} + +// Function executed before each iteration of terminal mode. +// Return: +// 1 if the iteration should continue normally +// 0 if the main loop must exit +static int terminal_check(VimState *state) +{ + if (stop_insert_mode) { + return 0; + } + + terminal_check_cursor(); + + if (must_redraw) { + update_screen(0); + } + + if (need_maketitle) { // Update title in terminal-mode. #7248 + maketitle(); + } + + setcursor(); + ui_flush(); + return 1; +} + static int terminal_execute(VimState *state, int key) { TerminalState *s = (TerminalState *)state; @@ -878,15 +920,20 @@ static VTermKey convert_key(int key, VTermModifier *statep) case K_KINS: return VTERM_KEY_KP_0; case K_K1: FALLTHROUGH; case K_KEND: return VTERM_KEY_KP_1; - case K_K2: return VTERM_KEY_KP_2; + case K_K2: FALLTHROUGH; + case K_KDOWN: return VTERM_KEY_KP_2; case K_K3: FALLTHROUGH; case K_KPAGEDOWN: return VTERM_KEY_KP_3; - case K_K4: return VTERM_KEY_KP_4; - case K_K5: return VTERM_KEY_KP_5; - case K_K6: return VTERM_KEY_KP_6; + case K_K4: FALLTHROUGH; + case K_KLEFT: return VTERM_KEY_KP_4; + case K_K5: FALLTHROUGH; + case K_KORIGIN: return VTERM_KEY_KP_5; + case K_K6: FALLTHROUGH; + case K_KRIGHT: return VTERM_KEY_KP_6; case K_K7: FALLTHROUGH; case K_KHOME: return VTERM_KEY_KP_7; - case K_K8: return VTERM_KEY_KP_8; + case K_K8: FALLTHROUGH; + case K_KUP: return VTERM_KEY_KP_8; case K_K9: FALLTHROUGH; case K_KPAGEUP: return VTERM_KEY_KP_9; case K_KDEL: FALLTHROUGH; @@ -977,6 +1024,9 @@ static bool send_mouse_event(Terminal *term, int c) { int row = mouse_row, col = mouse_col, grid = mouse_grid; win_T *mouse_win = mouse_find_win(&grid, &row, &col); + if (mouse_win == NULL) { + goto end; + } if (term->forward_mouse && mouse_win->w_buffer->terminal == term) { // event in the terminal window and mouse events was enabled by the @@ -1024,6 +1074,7 @@ static bool send_mouse_event(Terminal *term, int c) return mouse_win == curwin; } +end: ins_char_typebuf(c); return true; } @@ -1128,11 +1179,7 @@ static void refresh_terminal(Terminal *term) static void refresh_timer_cb(TimeWatcher *watcher, void *data) { refresh_pending = false; - if (exiting // Cannot redraw (requires event loop) during teardown/exit. - || (State & CMDPREVIEW) - // WM_LIST (^D) is not redrawn, unlike the normal wildmenu. So we must - // skip redraws to keep it visible. - || wild_menu_showing == WM_LIST) { + if (exiting) { // Cannot redraw (requires event loop) during teardown/exit. return; } Terminal *term; @@ -1142,12 +1189,8 @@ static void refresh_timer_cb(TimeWatcher *watcher, void *data) map_foreach(invalidated_terminals, term, stub, { refresh_terminal(term); }); - bool any_visible = is_term_visible(); pmap_clear(ptr_t)(invalidated_terminals); unblock_autocmds(); - if (any_visible) { - redraw(true); - } } static void refresh_size(Terminal *term, buf_T *buf) @@ -1261,61 +1304,6 @@ static void refresh_screen(Terminal *term, buf_T *buf) term->invalid_end = -1; } -/// @return true if any invalidated terminal buffer is visible to the user -static bool is_term_visible(void) -{ - FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { - if (wp->w_buffer->terminal - && pmap_has(ptr_t)(invalidated_terminals, wp->w_buffer->terminal)) { - return true; - } - } - return false; -} - -static void redraw(bool restore_cursor) -{ - Terminal *term = curbuf->terminal; - if (!term) { - restore_cursor = true; - } - - int save_row = 0; - int save_col = 0; - if (restore_cursor) { - // save the current row/col to restore after updating screen when not - // focused - save_row = ui_current_row(); - save_col = ui_current_col(); - } - block_autocmds(); - - if (must_redraw) { - update_screen(0); - } - - if (need_maketitle) { // Update title in terminal-mode. #7248 - maketitle(); - } - - if (restore_cursor) { - ui_cursor_goto(save_row, save_col); - } else if (term) { - curwin->w_wrow = term->cursor.row; - curwin->w_wcol = term->cursor.col + win_col_off(curwin); - curwin->w_cursor.lnum = MIN(curbuf->b_ml.ml_line_count, - row_to_linenr(term, term->cursor.row)); - // Nudge cursor when returning to normal-mode. - int off = is_focused(term) ? 0 : (curwin->w_p_rl ? 1 : -1); - curwin->w_cursor.col = MAX(0, term->cursor.col + win_col_off(curwin) + off); - curwin->w_cursor.coladd = 0; - mb_check_adjust_col(curwin); - } - - unblock_autocmds(); - ui_flush(); -} - static void adjust_topline(Terminal *term, buf_T *buf, long added) { FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { @@ -1351,23 +1339,16 @@ static bool is_focused(Terminal *term) return State & TERM_FOCUS && curbuf->terminal == term; } -#define GET_CONFIG_VALUE(k, o) \ - do { \ - Error err = ERROR_INIT; \ - /* Only called from terminal_open where curbuf->terminal is the */ \ - /* context */ \ - o = dict_get_value(curbuf->b_vars, cstr_as_string(k), &err); \ - api_clear_error(&err); \ - if (o.type == kObjectTypeNil) { \ - o = dict_get_value(&globvardict, cstr_as_string(k), &err); \ - api_clear_error(&err); \ - } \ - } while (0) - static char *get_config_string(char *key) { - Object obj; - GET_CONFIG_VALUE(key, obj); + Error err = ERROR_INIT; + // Only called from terminal_open where curbuf->terminal is the context. + Object obj = dict_get_value(curbuf->b_vars, cstr_as_string(key), &err); + api_clear_error(&err); + if (obj.type == kObjectTypeNil) { + obj = dict_get_value(&globvardict, cstr_as_string(key), &err); + api_clear_error(&err); + } if (obj.type == kObjectTypeString) { return obj.data.string.data; } |
