diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2023-01-25 18:31:31 +0000 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2023-01-25 18:31:31 +0000 |
commit | 9243becbedbb6a1592208051f8fa2b090dcc5e7d (patch) | |
tree | 607c2a862ec3f4399b8766383f6f8e04c4aa43b4 /src/nvim/ui.c | |
parent | 9e40b6e9e1bc67f2d856adb837ee64dd0e25b717 (diff) | |
parent | 3c48d3c83fc21dbc0841f9210f04bdb073d73cd1 (diff) | |
download | rneovim-9243becbedbb6a1592208051f8fa2b090dcc5e7d.tar.gz rneovim-9243becbedbb6a1592208051f8fa2b090dcc5e7d.tar.bz2 rneovim-9243becbedbb6a1592208051f8fa2b090dcc5e7d.zip |
Merge remote-tracking branch 'upstream/master' into usermarksusermarks
Diffstat (limited to 'src/nvim/ui.c')
-rw-r--r-- | src/nvim/ui.c | 266 |
1 files changed, 154 insertions, 112 deletions
diff --git a/src/nvim/ui.c b/src/nvim/ui.c index da671a3ad1..9f1cb87eb0 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -2,47 +2,40 @@ // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com #include <assert.h> -#include <inttypes.h> #include <limits.h> #include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <stdlib.h> #include <string.h> +#include "klib/kvec.h" +#include "nvim/api/private/helpers.h" +#include "nvim/api/ui.h" #include "nvim/ascii.h" #include "nvim/autocmd.h" -#include "nvim/charset.h" -#include "nvim/cursor.h" +#include "nvim/buffer_defs.h" #include "nvim/cursor_shape.h" -#include "nvim/diff.h" #include "nvim/drawscreen.h" -#include "nvim/event/loop.h" #include "nvim/ex_getln.h" -#include "nvim/fold.h" -#include "nvim/garray.h" +#include "nvim/gettext.h" +#include "nvim/globals.h" #include "nvim/grid.h" #include "nvim/highlight.h" +#include "nvim/highlight_defs.h" #include "nvim/log.h" -#include "nvim/main.h" -#include "nvim/mbyte.h" +#include "nvim/lua/executor.h" +#include "nvim/map.h" #include "nvim/memory.h" -#include "nvim/move.h" -#include "nvim/msgpack_rpc/channel.h" -#include "nvim/normal.h" +#include "nvim/message.h" #include "nvim/option.h" -#include "nvim/os/input.h" -#include "nvim/os/signal.h" #include "nvim/os/time.h" -#include "nvim/os_unix.h" -#include "nvim/popupmenu.h" +#include "nvim/strings.h" #include "nvim/ui.h" +#include "nvim/ui_client.h" #include "nvim/ui_compositor.h" #include "nvim/vim.h" #include "nvim/window.h" -#ifdef FEAT_TUI -# include "nvim/tui/tui.h" -#else -# include "nvim/msgpack_rpc/server.h" -#endif -#include "nvim/api/private/helpers.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "ui.c.generated.h" @@ -61,6 +54,9 @@ static bool pending_mode_info_update = false; static bool pending_mode_update = false; static handle_T cursor_grid_handle = DEFAULT_GRID_HANDLE; +static PMap(uint32_t) ui_event_cbs = MAP_INIT; +bool ui_cb_ext[kUIExtCount]; ///< Internalized UI capabilities. + static bool has_mouse = false; static int pending_has_mouse = -1; @@ -102,8 +98,8 @@ static char uilog_last_event[1024] = { 0 }; bool any_call = false; \ for (size_t i = 0; i < ui_count; i++) { \ UI *ui = uis[i]; \ - if (ui->funname && (cond)) { \ - ui->funname(__VA_ARGS__); \ + if ((cond)) { \ + remote_ui_##funname(__VA_ARGS__); \ any_call = true; \ } \ } \ @@ -116,10 +112,6 @@ static char uilog_last_event[1024] = { 0 }; # include "ui_events_call.generated.h" #endif -#ifndef EXITFREE -# undef entered_free_all_mem -#endif - void ui_init(void) { default_grid.handle = 1; @@ -128,36 +120,25 @@ void ui_init(void) kv_ensure_space(call_buf, 16); } +#ifdef EXITFREE void ui_free_all_mem(void) { kv_destroy(call_buf); -} -void ui_builtin_start(void) -{ -#ifdef FEAT_TUI - tui_start(); -#else - fprintf(stderr, "Nvim headless-mode started.\n"); - size_t len; - char **addrs = server_address_list(&len); - if (addrs != NULL) { - fprintf(stderr, "Listening on:\n"); - for (size_t i = 0; i < len; i++) { - fprintf(stderr, "\t%s\n", addrs[i]); - } - xfree(addrs); - } - fprintf(stderr, "Press CTRL+C to exit.\n"); -#endif + UIEventCallback *event_cb; + map_foreach_value(&ui_event_cbs, event_cb, { + free_ui_event_callback(event_cb); + }) + pmap_destroy(uint32_t)(&ui_event_cbs); } +#endif bool ui_rgb_attached(void) { if (!headless_mode && p_tgc) { return true; } - for (size_t i = 1; i < ui_count; i++) { + for (size_t i = 0; i < ui_count; i++) { if (uis[i]->rgb) { return true; } @@ -168,7 +149,7 @@ bool ui_rgb_attached(void) /// Returns true if any UI requested `override=true`. bool ui_override(void) { - for (size_t i = 1; i < ui_count; i++) { + for (size_t i = 0; i < ui_count; i++) { if (uis[i]->override) { return true; } @@ -178,17 +159,21 @@ bool ui_override(void) bool ui_active(void) { - return ui_count > 1; + return ui_count > 0; } void ui_refresh(void) { + if (ui_client_channel_id) { + abort(); + } + if (!ui_active()) { return; } if (updating_screen) { - deferred_refresh_event(NULL); + ui_schedule_refresh(); return; } @@ -212,6 +197,9 @@ void ui_refresh(void) pending_cursor_update = true; for (UIExtension i = 0; (int)i < kUIExtCount; i++) { + if (i < kUIGlobalCount) { + ext_widgets[i] |= ui_cb_ext[i]; + } ui_ext[i] = ext_widgets[i]; if (i < kUIGlobalCount) { ui_call_option_set(cstr_as_string((char *)ui_ext_names[i]), @@ -221,20 +209,13 @@ void ui_refresh(void) ui_default_colors_set(); - if (!ui_client_channel_id) { - int save_p_lz = p_lz; - p_lz = false; // convince redrawing() to return true ... - screen_resize(width, height); - p_lz = save_p_lz; - } else { - Array args = ARRAY_DICT_INIT; - ADD(args, INTEGER_OBJ((int)width)); - ADD(args, INTEGER_OBJ((int)height)); - rpc_send_event(ui_client_channel_id, "nvim_ui_try_resize", args); - } + int save_p_lz = p_lz; + p_lz = false; // convince redrawing() to return true ... + screen_resize(width, height); + p_lz = save_p_lz; if (ext_widgets[kUIMessages]) { - p_ch = 0; + set_option_value("cmdheight", 0L, NULL, 0); command_height(); } ui_mode_info_set(); @@ -246,7 +227,7 @@ void ui_refresh(void) int ui_pum_get_height(void) { int pum_height = 0; - for (size_t i = 1; i < ui_count; i++) { + for (size_t i = 0; i < ui_count; i++) { int ui_pum_height = uis[i]->pum_nlines; if (ui_pum_height) { pum_height = @@ -258,7 +239,7 @@ int ui_pum_get_height(void) bool ui_pum_get_pos(double *pwidth, double *pheight, double *prow, double *pcol) { - for (size_t i = 1; i < ui_count; i++) { + for (size_t i = 0; i < ui_count; i++) { if (!uis[i]->pum_pos) { continue; } @@ -278,10 +259,6 @@ static void ui_refresh_event(void **argv) void ui_schedule_refresh(void) { - loop_schedule_fast(&main_loop, event_create(deferred_refresh_event, 0)); -} -static void deferred_refresh_event(void **argv) -{ multiqueue_put(resize_events, ui_refresh_event, 0); } @@ -312,34 +289,36 @@ void vim_beep(unsigned val) { called_vim_beep = true; - if (emsg_silent == 0) { - if (!((bo_flags & val) || (bo_flags & BO_ALL))) { - static int beeps = 0; - static uint64_t start_time = 0; + if (emsg_silent != 0 || in_assert_fails) { + return; + } - // Only beep up to three times per half a second, - // otherwise a sequence of beeps would freeze Vim. - if (start_time == 0 || os_hrtime() - start_time > 500000000u) { - beeps = 0; - start_time = os_hrtime(); - } - beeps++; - if (beeps <= 3) { - if (p_vb) { - ui_call_visual_bell(); - } else { - ui_call_bell(); - } + if (!((bo_flags & val) || (bo_flags & BO_ALL))) { + static int beeps = 0; + static uint64_t start_time = 0; + + // Only beep up to three times per half a second, + // otherwise a sequence of beeps would freeze Vim. + if (start_time == 0 || os_hrtime() - start_time > 500000000U) { + beeps = 0; + start_time = os_hrtime(); + } + beeps++; + if (beeps <= 3) { + if (p_vb) { + ui_call_visual_bell(); + } else { + ui_call_bell(); } } + } - // When 'debug' contains "beep" produce a message. If we are sourcing - // a script or executing a function give the user a hint where the beep - // comes from. - if (vim_strchr((char *)p_debug, 'e') != NULL) { - msg_source(HL_ATTR(HLF_W)); - msg_attr(_("Beep!"), HL_ATTR(HLF_W)); - } + // When 'debug' contains "beep" produce a message. If we are sourcing + // a script or executing a function give the user a hint where the beep + // comes from. + if (vim_strchr(p_debug, 'e') != NULL) { + msg_source(HL_ATTR(HLF_W)); + msg_attr(_("Beep!"), HL_ATTR(HLF_W)); } } @@ -369,10 +348,7 @@ void ui_attach_impl(UI *ui, uint64_t chanid) } ui_refresh(); - bool is_compositor = (ui == uis[0]); - if (!is_compositor) { - do_autocmd_uienter(chanid, true); - } + do_autocmd_uienter(chanid, true); } void ui_detach_impl(UI *ui, uint64_t chanid) @@ -417,9 +393,9 @@ void ui_set_ext_option(UI *ui, UIExtension ext, bool active) ui_refresh(); return; } - if (ui->option_set && (ui_ext_names[ext][0] != '_' || active)) { - ui->option_set(ui, cstr_as_string((char *)ui_ext_names[ext]), - BOOLEAN_OBJ(active)); + if (ui_ext_names[ext][0] != '_' || active) { + remote_ui_option_set(ui, cstr_as_string((char *)ui_ext_names[ext]), + BOOLEAN_OBJ(active)); } if (ext == kUITermColors) { ui_default_colors_set(); @@ -449,7 +425,7 @@ void ui_line(ScreenGrid *grid, int row, int startcol, int endcol, int clearcol, MIN(clearcol, (int)grid->cols - 1)); ui_call_flush(); uint64_t wd = (uint64_t)labs(p_wd); - os_microdelay(wd * 1000u, true); + os_microdelay(wd * 1000U, true); pending_cursor_update = true; // restore the cursor later } } @@ -503,11 +479,12 @@ handle_T ui_cursor_grid(void) void ui_flush(void) { + assert(!ui_client_channel_id); if (!ui_active()) { return; } cmdline_ui_flush(); - win_ui_flush(); + win_ui_flush(false); msg_ext_ui_flush(); msg_scroll_flush(); @@ -517,11 +494,10 @@ void ui_flush(void) } if (pending_mode_info_update) { Arena arena = ARENA_EMPTY; - arena_start(&arena, &ui_ext_fixblk); Array style = mode_style_array(&arena); bool enabled = (*p_guicursor != NUL); ui_call_mode_info_set(enabled, style); - arena_mem_free(arena_finish(&arena), &ui_ext_fixblk); + arena_mem_free(arena_finish(&arena)); pending_mode_info_update = false; } if (pending_mode_update && !starting) { @@ -566,7 +542,7 @@ void ui_check_mouse(void) // - 'a' is in 'mouse' and "c" is in MOUSE_A, or // - the current buffer is a help file and 'h' is in 'mouse' and we are in a // normal editing mode (not at hit-return message). - for (char_u *p = p_mouse; *p; p++) { + for (char *p = p_mouse; *p; p++) { switch (*p) { case 'a': if (vim_strchr(MOUSE_A, checkfor) != NULL) { @@ -612,16 +588,10 @@ bool ui_has(UIExtension ext) return ui_ext[ext]; } -/// Returns true if the UI has messages area. -bool ui_has_messages(void) -{ - return p_ch > 0 || ui_has(kUIMessages); -} - Array ui_array(void) { Array all_uis = ARRAY_DICT_INIT; - for (size_t i = 1; i < ui_count; i++) { + for (size_t i = 0; i < ui_count; i++) { UI *ui = uis[i]; Dictionary info = ARRAY_DICT_INIT; PUT(info, "width", INTEGER_OBJ(ui->width)); @@ -633,7 +603,7 @@ Array ui_array(void) PUT(info, ui_ext_names[j], BOOLEAN_OBJ(ui->ui_ext[j])); } } - ui->inspect(ui, &info); + remote_ui_inspect(ui, &info); ADD(all_uis, DICTIONARY_OBJ(info)); } return all_uis; @@ -666,3 +636,75 @@ void ui_grid_resize(handle_T grid_handle, int width, int height, Error *error) win_set_inner_size(wp, true); } } + +void ui_call_event(char *name, Array args) +{ + UIEventCallback *event_cb; + bool handled = false; + map_foreach_value(&ui_event_cbs, event_cb, { + Error err = ERROR_INIT; + Object res = nlua_call_ref(event_cb->cb, name, args, false, &err); + if (res.type == kObjectTypeBoolean && res.data.boolean == true) { + handled = true; + } + if (ERROR_SET(&err)) { + ELOG("Error while executing ui_comp_event callback: %s", err.msg); + } + api_clear_error(&err); + }) + + if (!handled) { + UI_CALL(true, event, ui, name, args); + } +} + +void ui_cb_update_ext(void) +{ + memset(ui_cb_ext, 0, ARRAY_SIZE(ui_cb_ext)); + + for (size_t i = 0; i < kUIGlobalCount; i++) { + UIEventCallback *event_cb; + + map_foreach_value(&ui_event_cbs, event_cb, { + if (event_cb->ext_widgets[i]) { + ui_cb_ext[i] = true; + break; + } + }) + } +} + +void free_ui_event_callback(UIEventCallback *event_cb) +{ + api_free_luaref(event_cb->cb); + xfree(event_cb); +} + +void ui_add_cb(uint32_t ns_id, LuaRef cb, bool *ext_widgets) +{ + UIEventCallback *event_cb = xcalloc(1, sizeof(UIEventCallback)); + event_cb->cb = cb; + memcpy(event_cb->ext_widgets, ext_widgets, ARRAY_SIZE(event_cb->ext_widgets)); + if (event_cb->ext_widgets[kUIMessages]) { + event_cb->ext_widgets[kUICmdline] = true; + } + + UIEventCallback **item = (UIEventCallback **)pmap_ref(uint32_t)(&ui_event_cbs, ns_id, true); + if (*item) { + free_ui_event_callback(*item); + } + *item = event_cb; + + ui_cb_update_ext(); + ui_refresh(); +} + +void ui_remove_cb(uint32_t ns_id) +{ + if (pmap_has(uint32_t)(&ui_event_cbs, ns_id)) { + free_ui_event_callback(pmap_get(uint32_t)(&ui_event_cbs, ns_id)); + pmap_del(uint32_t)(&ui_event_cbs, ns_id); + } + ui_cb_update_ext(); + ui_refresh(); +} |