aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/getchar.c
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2022-08-16 15:09:59 +0800
committerGitHub <noreply@github.com>2022-08-16 15:09:59 +0800
commita63eea3d238da5c048d0d74e11388425c0c0c3d2 (patch)
tree94a8a120635c0cc2e2567a42330cae5342dd2303 /src/nvim/getchar.c
parent5e98a41872bafc781a75925e0de28c8c7a60889d (diff)
downloadrneovim-a63eea3d238da5c048d0d74e11388425c0c0c3d2.tar.gz
rneovim-a63eea3d238da5c048d0d74e11388425c0c0c3d2.tar.bz2
rneovim-a63eea3d238da5c048d0d74e11388425c0c0c3d2.zip
vim-patch:8.1.2042: the evalfunc.c file is too big (#19792)
Problem: The evalfunc.c file is too big. Solution: Move getchar() and parse_queued_messages() to getchar.c. https://github.com/vim/vim/commit/9c658c9eacbd97e2c071f652a0155f71db94c0f3 Omit parse_queued_messages(): Nvim does not have MESSAGE_QUEUE.
Diffstat (limited to 'src/nvim/getchar.c')
-rw-r--r--src/nvim/getchar.c144
1 files changed, 144 insertions, 0 deletions
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index bc2c440bb1..cd45691a0c 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -17,6 +17,7 @@
#include "nvim/cursor.h"
#include "nvim/edit.h"
#include "nvim/eval.h"
+#include "nvim/eval/typval.h"
#include "nvim/event/loop.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_getln.h"
@@ -1696,6 +1697,149 @@ int char_avail(void)
return retval != NUL;
}
+/// "getchar()" and "getcharstr()" functions
+static void getchar_common(typval_T *argvars, typval_T *rettv)
+ FUNC_ATTR_NONNULL_ALL
+{
+ varnumber_T n;
+ bool error = false;
+
+ no_mapping++;
+ allow_keys++;
+ for (;;) {
+ // Position the cursor. Needed after a message that ends in a space,
+ // or if event processing caused a redraw.
+ ui_cursor_goto(msg_row, msg_col);
+
+ if (argvars[0].v_type == VAR_UNKNOWN) {
+ // getchar(): blocking wait.
+ // TODO(bfredl): deduplicate shared logic with state_enter ?
+ if (!char_avail()) {
+ // flush output before waiting
+ ui_flush();
+ (void)os_inchar(NULL, 0, -1, 0, main_loop.events);
+ if (!multiqueue_empty(main_loop.events)) {
+ state_handle_k_event();
+ continue;
+ }
+ }
+ n = safe_vgetc();
+ } else if (tv_get_number_chk(&argvars[0], &error) == 1) {
+ // getchar(1): only check if char avail
+ n = vpeekc_any();
+ } else if (error || vpeekc_any() == NUL) {
+ // illegal argument or getchar(0) and no char avail: return zero
+ n = 0;
+ } else {
+ // getchar(0) and char avail() != NUL: get a character.
+ // Note that vpeekc_any() returns K_SPECIAL for K_IGNORE.
+ n = safe_vgetc();
+ }
+
+ if (n == K_IGNORE
+ || n == K_MOUSEMOVE
+ || n == K_VER_SCROLLBAR
+ || n == K_HOR_SCROLLBAR) {
+ continue;
+ }
+ break;
+ }
+ no_mapping--;
+ allow_keys--;
+
+ if (!ui_has_messages()) {
+ // redraw the screen after getchar()
+ update_screen(CLEAR);
+ }
+
+ set_vim_var_nr(VV_MOUSE_WIN, 0);
+ set_vim_var_nr(VV_MOUSE_WINID, 0);
+ set_vim_var_nr(VV_MOUSE_LNUM, 0);
+ set_vim_var_nr(VV_MOUSE_COL, 0);
+
+ rettv->vval.v_number = n;
+ if (n != 0 && (IS_SPECIAL(n) || mod_mask != 0)) {
+ char_u temp[10]; // modifier: 3, mbyte-char: 6, NUL: 1
+ int i = 0;
+
+ // Turn a special key into three bytes, plus modifier.
+ if (mod_mask != 0) {
+ temp[i++] = K_SPECIAL;
+ temp[i++] = KS_MODIFIER;
+ temp[i++] = (char_u)mod_mask;
+ }
+ if (IS_SPECIAL(n)) {
+ temp[i++] = K_SPECIAL;
+ temp[i++] = (char_u)K_SECOND(n);
+ temp[i++] = K_THIRD(n);
+ } else {
+ i += utf_char2bytes((int)n, (char *)temp + i);
+ }
+ assert(i < 10);
+ temp[i++] = NUL;
+ rettv->v_type = VAR_STRING;
+ rettv->vval.v_string = (char *)vim_strsave(temp);
+
+ if (is_mouse_key((int)n)) {
+ int row = mouse_row;
+ int col = mouse_col;
+ int grid = mouse_grid;
+ linenr_T lnum;
+ win_T *wp;
+ int winnr = 1;
+
+ if (row >= 0 && col >= 0) {
+ // Find the window at the mouse coordinates and compute the
+ // text position.
+ win_T *const win = mouse_find_win(&grid, &row, &col);
+ if (win == NULL) {
+ return;
+ }
+ (void)mouse_comp_pos(win, &row, &col, &lnum);
+ for (wp = firstwin; wp != win; wp = wp->w_next) {
+ winnr++;
+ }
+ set_vim_var_nr(VV_MOUSE_WIN, winnr);
+ set_vim_var_nr(VV_MOUSE_WINID, wp->handle);
+ set_vim_var_nr(VV_MOUSE_LNUM, lnum);
+ set_vim_var_nr(VV_MOUSE_COL, col + 1);
+ }
+ }
+ }
+}
+
+/// "getchar()" function
+void f_getchar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+{
+ getchar_common(argvars, rettv);
+}
+
+/// "getcharstr()" function
+void f_getcharstr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+{
+ getchar_common(argvars, rettv);
+
+ if (rettv->v_type == VAR_NUMBER) {
+ char temp[7]; // mbyte-char: 6, NUL: 1
+ const varnumber_T n = rettv->vval.v_number;
+ int i = 0;
+
+ if (n != 0) {
+ i += utf_char2bytes((int)n, (char *)temp);
+ }
+ assert(i < 7);
+ temp[i++] = NUL;
+ rettv->v_type = VAR_STRING;
+ rettv->vval.v_string = xstrdup(temp);
+ }
+}
+
+/// "getcharmod()" function
+void f_getcharmod(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+{
+ rettv->vval.v_number = mod_mask;
+}
+
typedef enum {
map_result_fail, // failed, break loop
map_result_get, // get a character from typeahead