diff options
| author | bfredl <bjorn.linse@gmail.com> | 2023-01-05 10:41:14 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-01-05 10:41:14 +0100 |
| commit | 85eb564bac167c63eadbd6136406ac4863ee30ee (patch) | |
| tree | 79a1d81956d87986467e4da70b4f9ad53b079040 /src | |
| parent | ae64772a88125153a438a0e9e43d5f6bcb4eeb28 (diff) | |
| parent | 47ba78f89a1f0bba8168b4408bc55a3024d5ab97 (diff) | |
| download | rneovim-85eb564bac167c63eadbd6136406ac4863ee30ee.tar.gz rneovim-85eb564bac167c63eadbd6136406ac4863ee30ee.tar.bz2 rneovim-85eb564bac167c63eadbd6136406ac4863ee30ee.zip | |
Merge pull request #21605 from bfredl/uidvp
The UI Devirtualization Project
Diffstat (limited to 'src')
| -rwxr-xr-x | src/nvim/CMakeLists.txt | 5 | ||||
| -rw-r--r-- | src/nvim/api/ui.c | 108 | ||||
| -rw-r--r-- | src/nvim/api/ui.h | 2 | ||||
| -rw-r--r-- | src/nvim/api/ui_events.in.h | 17 | ||||
| -rw-r--r-- | src/nvim/generators/c_grammar.lua | 2 | ||||
| -rwxr-xr-x | src/nvim/generators/gen_api_ui_events.lua | 31 | ||||
| -rw-r--r-- | src/nvim/highlight.c | 23 | ||||
| -rw-r--r-- | src/nvim/lua/executor.c | 4 | ||||
| -rw-r--r-- | src/nvim/main.c | 8 | ||||
| -rw-r--r-- | src/nvim/memory.c | 1 | ||||
| -rw-r--r-- | src/nvim/tui/tui.c | 1469 | ||||
| -rw-r--r-- | src/nvim/ui.c | 168 | ||||
| -rw-r--r-- | src/nvim/ui.h | 43 | ||||
| -rw-r--r-- | src/nvim/ui_client.c | 41 | ||||
| -rw-r--r-- | src/nvim/ui_client.h | 2 | ||||
| -rw-r--r-- | src/nvim/ui_compositor.c | 133 |
16 files changed, 946 insertions, 1111 deletions
diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 6b92d0caa8..8ac52d8b72 100755 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -36,7 +36,6 @@ set(HEADER_GENERATOR ${GENERATOR_DIR}/gen_declarations.lua) set(GENERATED_INCLUDES_DIR ${PROJECT_BINARY_DIR}/include) set(GENERATED_API_DISPATCH ${GENERATED_DIR}/api/private/dispatch_wrappers.generated.h) set(GENERATED_FUNCS_METADATA ${GENERATED_DIR}/api/private/funcs_metadata.generated.h) -set(GENERATED_UI_EVENTS ${GENERATED_DIR}/ui_events.generated.h) set(GENERATED_UI_EVENTS_CALL ${GENERATED_DIR}/ui_events_call.generated.h) set(GENERATED_UI_EVENTS_REMOTE ${GENERATED_DIR}/ui_events_remote.generated.h) set(GENERATED_UI_EVENTS_CLIENT ${GENERATED_DIR}/ui_events_client.generated.h) @@ -310,14 +309,12 @@ list(APPEND NVIM_GENERATED_SOURCES ) add_custom_command( - OUTPUT ${GENERATED_UI_EVENTS} - ${GENERATED_UI_EVENTS_CALL} + OUTPUT ${GENERATED_UI_EVENTS_CALL} ${GENERATED_UI_EVENTS_REMOTE} ${GENERATED_UI_EVENTS_METADATA} ${GENERATED_UI_EVENTS_CLIENT} COMMAND ${LUA_PRG} ${API_UI_EVENTS_GENERATOR} ${CMAKE_CURRENT_LIST_DIR} ${CMAKE_CURRENT_LIST_DIR}/api/ui_events.in.h - ${GENERATED_UI_EVENTS} ${GENERATED_UI_EVENTS_CALL} ${GENERATED_UI_EVENTS_REMOTE} ${GENERATED_UI_EVENTS_METADATA} diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index e4134133ac..32b294c0ce 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -29,41 +29,6 @@ #include "nvim/vim.h" #include "nvim/window.h" -typedef struct { - uint64_t channel_id; - -#define UI_BUF_SIZE 4096 ///< total buffer size for pending msgpack data. - /// guaranteed size available for each new event (so packing of simple events - /// and the header of grid_line will never fail) -#define EVENT_BUF_SIZE 256 - char buf[UI_BUF_SIZE]; ///< buffer of packed but not yet sent msgpack data - char *buf_wptr; ///< write head of buffer - const char *cur_event; ///< name of current event (might get multiple arglists) - Array call_buf; ///< buffer for constructing a single arg list (max 16 elements!) - - // state for write_cb, while packing a single arglist to msgpack. This - // might fail due to buffer overflow. - size_t pack_totlen; - bool buf_overflow; - char *temp_buf; - - // We start packing the two outermost msgpack arrays before knowing the total - // number of elements. Thus track the location where array size will need - // to be written in the msgpack buffer, once the specific array is finished. - char *nevents_pos; - char *ncalls_pos; - uint32_t nevents; ///< number of distinct events (top-level args to "redraw" - uint32_t ncalls; ///< number of calls made to the current event (plus one for the name!) - bool flushed_events; ///< events where sent to client without "flush" event - - int hl_id; // Current highlight for legacy put event. - Integer cursor_row, cursor_col; // Intended visible cursor position. - - // Position of legacy cursor, used both for drawing and visible user cursor. - Integer client_row, client_col; - bool wildmenu_active; -} UIData; - #define BUF_POS(data) ((size_t)((data)->buf_wptr - (data)->buf)) #ifdef INCLUDE_GENERATED_DECLARATIONS @@ -143,8 +108,6 @@ void remote_ui_disconnect(uint64_t channel_id) UIData *data = ui->data; kv_destroy(data->call_buf); pmap_del(uint64_t)(&connected_uis, channel_id); - xfree(data); - ui->data = NULL; // Flag UI as "stopped". ui_detach_impl(ui, channel_id); xfree(ui); } @@ -204,32 +167,6 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, Dictiona ui->pum_col = -1.0; ui->rgb = true; ui->override = false; - ui->grid_resize = remote_ui_grid_resize; - ui->grid_clear = remote_ui_grid_clear; - ui->grid_cursor_goto = remote_ui_grid_cursor_goto; - ui->mode_info_set = remote_ui_mode_info_set; - ui->update_menu = remote_ui_update_menu; - ui->busy_start = remote_ui_busy_start; - ui->busy_stop = remote_ui_busy_stop; - ui->mouse_on = remote_ui_mouse_on; - ui->mouse_off = remote_ui_mouse_off; - ui->mode_change = remote_ui_mode_change; - ui->grid_scroll = remote_ui_grid_scroll; - ui->hl_attr_define = remote_ui_hl_attr_define; - ui->hl_group_set = remote_ui_hl_group_set; - ui->raw_line = remote_ui_raw_line; - ui->bell = remote_ui_bell; - ui->visual_bell = remote_ui_visual_bell; - ui->default_colors_set = remote_ui_default_colors_set; - ui->flush = remote_ui_flush; - ui->suspend = remote_ui_suspend; - ui->set_title = remote_ui_set_title; - ui->set_icon = remote_ui_set_icon; - ui->option_set = remote_ui_option_set; - ui->msg_set_pos = remote_ui_msg_set_pos; - ui->event = remote_ui_event; - ui->inspect = remote_ui_inspect; - ui->win_viewport = remote_ui_win_viewport; CLEAR_FIELD(ui->ui_ext); @@ -252,7 +189,7 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, Dictiona ui->ui_ext[kUICmdline] = true; } - UIData *data = xmalloc(sizeof(UIData)); + UIData *data = ui->data; data->channel_id = channel_id; data->cur_event = NULL; data->hl_id = 0; @@ -267,7 +204,6 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, Dictiona data->wildmenu_active = false; data->call_buf = (Array)ARRAY_DICT_INIT; kv_ensure_space(data->call_buf, 16); - ui->data = data; pmap_put(uint64_t)(&connected_uis, channel_id, ui); ui_attach_impl(ui, channel_id); @@ -313,6 +249,10 @@ void nvim_ui_detach(uint64_t channel_id, Error *err) remote_ui_disconnect(channel_id); } +// TODO(bfredl): use me to detach a specifc ui from the server +void remote_ui_stop(UI *ui) +{} + void nvim_ui_try_resize(uint64_t channel_id, Integer width, Integer height, Error *err) FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY { @@ -684,7 +624,7 @@ static void push_call(UI *ui, const char *name, Array args) data->ncalls++; } -static void remote_ui_grid_clear(UI *ui, Integer grid) +void remote_ui_grid_clear(UI *ui, Integer grid) { UIData *data = ui->data; Array args = data->call_buf; @@ -695,7 +635,7 @@ static void remote_ui_grid_clear(UI *ui, Integer grid) push_call(ui, name, args); } -static void remote_ui_grid_resize(UI *ui, Integer grid, Integer width, Integer height) +void remote_ui_grid_resize(UI *ui, Integer grid, Integer width, Integer height) { UIData *data = ui->data; Array args = data->call_buf; @@ -708,8 +648,8 @@ static void remote_ui_grid_resize(UI *ui, Integer grid, Integer width, Integer h push_call(ui, name, args); } -static void remote_ui_grid_scroll(UI *ui, Integer grid, Integer top, Integer bot, Integer left, - Integer right, Integer rows, Integer cols) +void remote_ui_grid_scroll(UI *ui, Integer grid, Integer top, Integer bot, Integer left, + Integer right, Integer rows, Integer cols) { UIData *data = ui->data; if (ui->ui_ext[kUILinegrid]) { @@ -745,8 +685,8 @@ static void remote_ui_grid_scroll(UI *ui, Integer grid, Integer top, Integer bot } } -static void remote_ui_default_colors_set(UI *ui, Integer rgb_fg, Integer rgb_bg, Integer rgb_sp, - Integer cterm_fg, Integer cterm_bg) +void remote_ui_default_colors_set(UI *ui, Integer rgb_fg, Integer rgb_bg, Integer rgb_sp, + Integer cterm_fg, Integer cterm_bg) { if (!ui->ui_ext[kUITermColors]) { HL_SET_DEFAULT_COLORS(rgb_fg, rgb_bg, rgb_sp); @@ -776,8 +716,8 @@ static void remote_ui_default_colors_set(UI *ui, Integer rgb_fg, Integer rgb_bg, } } -static void remote_ui_hl_attr_define(UI *ui, Integer id, HlAttrs rgb_attrs, HlAttrs cterm_attrs, - Array info) +void remote_ui_hl_attr_define(UI *ui, Integer id, HlAttrs rgb_attrs, HlAttrs cterm_attrs, + Array info) { if (!ui->ui_ext[kUILinegrid]) { return; @@ -802,7 +742,7 @@ static void remote_ui_hl_attr_define(UI *ui, Integer id, HlAttrs rgb_attrs, HlAt push_call(ui, "hl_attr_define", args); } -static void remote_ui_highlight_set(UI *ui, int id) +void remote_ui_highlight_set(UI *ui, int id) { UIData *data = ui->data; Array args = data->call_buf; @@ -818,7 +758,7 @@ static void remote_ui_highlight_set(UI *ui, int id) } /// "true" cursor used only for input focus -static void remote_ui_grid_cursor_goto(UI *ui, Integer grid, Integer row, Integer col) +void remote_ui_grid_cursor_goto(UI *ui, Integer grid, Integer row, Integer col) { if (ui->ui_ext[kUILinegrid]) { UIData *data = ui->data; @@ -836,7 +776,7 @@ static void remote_ui_grid_cursor_goto(UI *ui, Integer grid, Integer row, Intege } /// emulated cursor used both for drawing and for input focus -static void remote_ui_cursor_goto(UI *ui, Integer row, Integer col) +void remote_ui_cursor_goto(UI *ui, Integer row, Integer col) { UIData *data = ui->data; if (data->client_row == row && data->client_col == col) { @@ -850,7 +790,7 @@ static void remote_ui_cursor_goto(UI *ui, Integer row, Integer col) push_call(ui, "cursor_goto", args); } -static void remote_ui_put(UI *ui, const char *cell) +void remote_ui_put(UI *ui, const char *cell) { UIData *data = ui->data; data->client_col++; @@ -859,9 +799,9 @@ static void remote_ui_put(UI *ui, const char *cell) push_call(ui, "put", args); } -static void remote_ui_raw_line(UI *ui, Integer grid, Integer row, Integer startcol, Integer endcol, - Integer clearcol, Integer clearattr, LineFlags flags, - const schar_T *chunk, const sattr_T *attrs) +void remote_ui_raw_line(UI *ui, Integer grid, Integer row, Integer startcol, Integer endcol, + Integer clearcol, Integer clearattr, LineFlags flags, const schar_T *chunk, + const sattr_T *attrs) { UIData *data = ui->data; if (ui->ui_ext[kUILinegrid]) { @@ -953,7 +893,7 @@ static void remote_ui_raw_line(UI *ui, Integer grid, Integer row, Integer startc /// /// This might happen multiple times before the actual ui_flush, if the /// total redraw size is large! -static void remote_ui_flush_buf(UI *ui) +void remote_ui_flush_buf(UI *ui) { UIData *data = ui->data; if (!data->nevents_pos) { @@ -980,7 +920,7 @@ static void remote_ui_flush_buf(UI *ui) /// /// Clients can know this happened by a final "flush" event at the end of the /// "redraw" batch. -static void remote_ui_flush(UI *ui) +void remote_ui_flush(UI *ui) { UIData *data = ui->data; if (data->nevents > 0 || data->flushed_events) { @@ -1025,7 +965,7 @@ static Array translate_firstarg(UI *ui, Array args, Arena *arena) return new_args; } -static void remote_ui_event(UI *ui, char *name, Array args) +void remote_ui_event(UI *ui, char *name, Array args) { Arena arena = ARENA_EMPTY; UIData *data = ui->data; @@ -1092,7 +1032,7 @@ free_ret: arena_mem_free(arena_finish(&arena)); } -static void remote_ui_inspect(UI *ui, Dictionary *info) +void remote_ui_inspect(UI *ui, Dictionary *info) { UIData *data = ui->data; PUT(*info, "chan", INTEGER_OBJ((Integer)data->channel_id)); diff --git a/src/nvim/api/ui.h b/src/nvim/api/ui.h index bc70406acb..b3fe0fa2bb 100644 --- a/src/nvim/api/ui.h +++ b/src/nvim/api/ui.h @@ -5,8 +5,10 @@ #include "nvim/api/private/defs.h" #include "nvim/map.h" +#include "nvim/ui.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "api/ui.h.generated.h" +# include "ui_events_remote.h.generated.h" #endif #endif // NVIM_API_UI_H diff --git a/src/nvim/api/ui_events.in.h b/src/nvim/api/ui_events.in.h index d5c79272b7..a08e8dbfeb 100644 --- a/src/nvim/api/ui_events.in.h +++ b/src/nvim/api/ui_events.in.h @@ -37,7 +37,7 @@ void set_title(String title) void set_icon(String icon) FUNC_API_SINCE(3); void screenshot(String path) - FUNC_API_SINCE(7) FUNC_API_REMOTE_IMPL; + FUNC_API_SINCE(7); void option_set(String name, Object value) FUNC_API_SINCE(4); // Stop event is not exported as such, represented by EOF in the msgpack stream. @@ -75,7 +75,7 @@ void default_colors_set(Integer rgb_fg, Integer rgb_bg, Integer rgb_sp, Integer void hl_attr_define(Integer id, HlAttrs rgb_attrs, HlAttrs cterm_attrs, Array info) FUNC_API_SINCE(5) FUNC_API_REMOTE_IMPL; void hl_group_set(String name, Integer id) - FUNC_API_SINCE(6); + FUNC_API_SINCE(6) FUNC_API_CLIENT_IGNORE; void grid_resize(Integer grid, Integer width, Integer height) FUNC_API_SINCE(5) FUNC_API_REMOTE_IMPL FUNC_API_COMPOSITOR_IMPL FUNC_API_CLIENT_IMPL; void grid_clear(Integer grid) @@ -97,9 +97,6 @@ void raw_line(Integer grid, Integer row, Integer startcol, Integer endcol, Integ Integer clearattr, LineFlags flags, const schar_T *chunk, const sattr_T *attrs) FUNC_API_NOEXPORT FUNC_API_COMPOSITOR_IMPL; -void event(char *name, Array args) - FUNC_API_NOEXPORT FUNC_API_COMPOSITOR_IMPL; - void win_pos(Integer grid, Window win, Integer startrow, Integer startcol, Integer width, Integer height) FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY; @@ -114,11 +111,11 @@ void win_close(Integer grid) FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY; void msg_set_pos(Integer grid, Integer row, Boolean scrolled, String sep_char) - FUNC_API_SINCE(6) FUNC_API_COMPOSITOR_IMPL; + FUNC_API_SINCE(6) FUNC_API_COMPOSITOR_IMPL FUNC_API_CLIENT_IGNORE; void win_viewport(Integer grid, Window win, Integer topline, Integer botline, Integer curline, Integer curcol, Integer line_count) - FUNC_API_SINCE(7) FUNC_API_BRIDGE_IMPL; + FUNC_API_SINCE(7) FUNC_API_CLIENT_IGNORE; void win_extmark(Integer grid, Window win, Integer ns_id, Integer mark_id, Integer row, Integer col) FUNC_API_SINCE(10) FUNC_API_REMOTE_ONLY; @@ -150,11 +147,11 @@ void cmdline_block_hide(void) FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; void wildmenu_show(Array items) - FUNC_API_SINCE(3) FUNC_API_REMOTE_IMPL; + FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; void wildmenu_select(Integer selected) - FUNC_API_SINCE(3) FUNC_API_REMOTE_IMPL; + FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; void wildmenu_hide(void) - FUNC_API_SINCE(3) FUNC_API_REMOTE_IMPL; + FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; void msg_show(String kind, Array content, Boolean replace_last) FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY; diff --git a/src/nvim/generators/c_grammar.lua b/src/nvim/generators/c_grammar.lua index 3ea5904338..3e89b60b4a 100644 --- a/src/nvim/generators/c_grammar.lua +++ b/src/nvim/generators/c_grammar.lua @@ -49,9 +49,9 @@ local c_proto = Ct( (fill * Cg((P('FUNC_API_LUA_ONLY') * Cc(true)), 'lua_only') ^ -1) * (fill * Cg((P('FUNC_API_CHECK_TEXTLOCK') * Cc(true)), 'check_textlock') ^ -1) * (fill * Cg((P('FUNC_API_REMOTE_IMPL') * Cc(true)), 'remote_impl') ^ -1) * - (fill * Cg((P('FUNC_API_BRIDGE_IMPL') * Cc(true)), 'bridge_impl') ^ -1) * (fill * Cg((P('FUNC_API_COMPOSITOR_IMPL') * Cc(true)), 'compositor_impl') ^ -1) * (fill * Cg((P('FUNC_API_CLIENT_IMPL') * Cc(true)), 'client_impl') ^ -1) * + (fill * Cg((P('FUNC_API_CLIENT_IGNORE') * Cc(true)), 'client_ignore') ^ -1) * fill * P(';') ) diff --git a/src/nvim/generators/gen_api_ui_events.lua b/src/nvim/generators/gen_api_ui_events.lua index c9a2e3ff66..827097f69d 100755 --- a/src/nvim/generators/gen_api_ui_events.lua +++ b/src/nvim/generators/gen_api_ui_events.lua @@ -3,13 +3,12 @@ local mpack = require('mpack') local nvimdir = arg[1] package.path = nvimdir .. '/?.lua;' .. package.path -assert(#arg == 7) +assert(#arg == 6) local input = io.open(arg[2], 'rb') -local proto_output = io.open(arg[3], 'wb') -local call_output = io.open(arg[4], 'wb') -local remote_output = io.open(arg[5], 'wb') -local metadata_output = io.open(arg[6], 'wb') -local client_output = io.open(arg[7], 'wb') +local call_output = io.open(arg[3], 'wb') +local remote_output = io.open(arg[4], 'wb') +local metadata_output = io.open(arg[5], 'wb') +local client_output = io.open(arg[6], 'wb') local c_grammar = require('generators.c_grammar') local events = c_grammar.grammar:match(input:read('*all')) @@ -81,12 +80,9 @@ local function call_ui_event_method(output, ev) end end - output:write(' ui_call_'..ev.name..'(') + output:write(' tui_'..ev.name..'(tui') for j = 1, #ev.parameters do - output:write('arg_'..j) - if j ~= #ev.parameters then - output:write(', ') - end + output:write(', arg_'..j) end output:write(');\n') @@ -104,12 +100,9 @@ for i = 1, #events do ev.since = tonumber(ev.since) if not ev.remote_only then - proto_output:write(' void (*'..ev.name..')') - write_signature(proto_output, ev, 'UI *ui') - proto_output:write(';\n') if not ev.remote_impl and not ev.noexport then - remote_output:write('static void remote_ui_'..ev.name) + remote_output:write('void remote_ui_'..ev.name) write_signature(remote_output, ev, 'UI *ui') remote_output:write('\n{\n') remote_output:write(' UIData *data = ui->data;\n') @@ -130,6 +123,9 @@ for i = 1, #events do call_output:write(' UI_LOG('..ev.name..');\n') call_output:write(' ui_call_event("'..ev.name..'", args);\n') elseif ev.compositor_impl then + call_output:write(' ui_comp_'..ev.name) + write_signature(call_output, ev, '', true) + call_output:write(";\n") call_output:write(' UI_CALL') write_signature(call_output, ev, '!ui->composed, '..ev.name..', ui', true) call_output:write(";\n") @@ -151,14 +147,14 @@ for i = 1, #events do call_output:write("}\n\n") end - if (not ev.remote_only) and (not ev.noexport) and (not ev.client_impl) then + if (not ev.remote_only) and (not ev.noexport) and (not ev.client_impl) and (not ev.client_ignore) then call_ui_event_method(client_output, ev) end end local client_events = {} for _,ev in ipairs(events) do - if (not ev.noexport) and ((not ev.remote_only) or ev.client_impl) then + if (not ev.noexport) and ((not ev.remote_only) or ev.client_impl) and (not ev.client_ignore) then client_events[ev.name] = ev end end @@ -176,7 +172,6 @@ end client_output:write('\n};\n\n') client_output:write(hashfun) -proto_output:close() call_output:close() remote_output:close() client_output:close() diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index 2c55e840f1..c3a259c87d 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -12,6 +12,7 @@ #include "lauxlib.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" +#include "nvim/api/ui.h" #include "nvim/decoration_provider.h" #include "nvim/drawscreen.h" #include "nvim/gettext.h" @@ -128,19 +129,15 @@ static int get_attr_entry(HlEntry entry) /// When a UI connects, we need to send it the table of highlights used so far. void ui_send_all_hls(UI *ui) { - if (ui->hl_attr_define) { - for (size_t i = 1; i < kv_size(attr_entries); i++) { - Array inspect = hl_inspect((int)i); - ui->hl_attr_define(ui, (Integer)i, kv_A(attr_entries, i).attr, - kv_A(attr_entries, i).attr, inspect); - api_free_array(inspect); - } - } - if (ui->hl_group_set) { - for (size_t hlf = 0; hlf < HLF_COUNT; hlf++) { - ui->hl_group_set(ui, cstr_as_string((char *)hlf_names[hlf]), - highlight_attr[hlf]); - } + for (size_t i = 1; i < kv_size(attr_entries); i++) { + Array inspect = hl_inspect((int)i); + remote_ui_hl_attr_define(ui, (Integer)i, kv_A(attr_entries, i).attr, + kv_A(attr_entries, i).attr, inspect); + api_free_array(inspect); + } + for (size_t hlf = 0; hlf < HLF_COUNT; hlf++) { + remote_ui_hl_group_set(ui, cstr_as_string((char *)hlf_names[hlf]), + highlight_attr[hlf]); } } diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index d4e7f3fb2c..34b572f884 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -653,7 +653,7 @@ ok: } LuaRef ui_event_cb = nlua_ref_global(lstate, 3); - ui_comp_add_cb(ns_id, ui_event_cb, ext_widgets); + ui_add_cb(ns_id, ui_event_cb, ext_widgets); return 0; } @@ -667,7 +667,7 @@ static int nlua_ui_detach(lua_State *lstate) return luaL_error(lstate, "invalid ns_id"); } - ui_comp_remove_cb(ns_id); + ui_remove_cb(ns_id); return 0; } diff --git a/src/nvim/main.c b/src/nvim/main.c index b5207f9cf6..b0da7f4500 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -627,11 +627,13 @@ void os_exit(int r) { exiting = true; - if (!ui_client_channel_id) { + if (ui_client_channel_id) { + ui_client_stop(); + } else { ui_flush(); + ui_call_stop(); + ml_close_all(true); // remove all memfiles } - ui_call_stop(); - ml_close_all(true); // remove all memfiles if (!event_teardown() && r == 0) { r = 1; // Exit with error if main_loop did not teardown gracefully. diff --git a/src/nvim/memory.c b/src/nvim/memory.c index a65f45c012..aa8314b23d 100644 --- a/src/nvim/memory.c +++ b/src/nvim/memory.c @@ -834,7 +834,6 @@ void free_all_mem(void) decor_free_all_mem(); ui_free_all_mem(); - ui_comp_free_all_mem(); nlua_free_all_mem(); // should be last, in case earlier free functions deallocates arenas diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index 066567a87f..162f54b6c1 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -1,7 +1,7 @@ // This is an open source non-commercial project. Dear PVS-Studio, please check // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com -// Terminal UI functions. Invoked (by UI_CALL) on the UI process. +// Terminal UI functions. Invoked (by ui_client.c) on the UI process. #include <assert.h> #include <signal.h> @@ -89,7 +89,6 @@ typedef struct { } Rect; struct TUIData { - UI *ui; Loop *loop; unibi_var_t params[9]; char buf[OUTBUF_SIZE]; @@ -158,6 +157,9 @@ struct TUIData { } unibi_ext; char *space_buf; bool stopped; + int width; + int height; + bool rgb; }; static int got_winch = 0; @@ -166,144 +168,113 @@ static bool cursor_style_enabled = false; # include "tui/tui.c.generated.h" #endif -UI *tui_start(void) -{ - UI *ui = xcalloc(1, sizeof(UI)); // Freed by tui_data_destroy(). - ui->stop = tui_stop; - ui->grid_resize = tui_grid_resize; - ui->grid_clear = tui_grid_clear; - ui->grid_cursor_goto = tui_grid_cursor_goto; - ui->mode_info_set = tui_mode_info_set; - ui->update_menu = tui_update_menu; - ui->busy_start = tui_busy_start; - ui->busy_stop = tui_busy_stop; - ui->mouse_on = tui_mouse_on; - ui->mouse_off = tui_mouse_off; - ui->mode_change = tui_mode_change; - ui->grid_scroll = tui_grid_scroll; - ui->hl_attr_define = tui_hl_attr_define; - ui->bell = tui_bell; - ui->visual_bell = tui_visual_bell; - ui->default_colors_set = tui_default_colors_set; - ui->flush = tui_flush; - ui->suspend = tui_suspend; - ui->set_title = tui_set_title; - ui->set_icon = tui_set_icon; - ui->screenshot = tui_screenshot; - ui->option_set = tui_option_set; - ui->raw_line = tui_raw_line; - - CLEAR_FIELD(ui->ui_ext); - ui->ui_ext[kUILinegrid] = true; - ui->ui_ext[kUITermColors] = true; - - TUIData *data = xcalloc(1, sizeof(TUIData)); - ui->data = data; - data->ui = ui; - data->is_starting = true; - data->screenshot = NULL; - data->stopped = false; - data->loop = &main_loop; - kv_init(data->invalid_regions); - signal_watcher_init(data->loop, &data->winch_handle, ui); +TUIData *tui_start(int *width, int *height, char **term) +{ + TUIData *tui = xcalloc(1, sizeof(TUIData)); + tui->is_starting = true; + tui->screenshot = NULL; + tui->stopped = false; + tui->loop = &main_loop; + kv_init(tui->invalid_regions); + signal_watcher_init(tui->loop, &tui->winch_handle, tui); // TODO(bfredl): zero hl is empty, send this explicitly? - kv_push(data->attrs, HLATTRS_INIT); + kv_push(tui->attrs, HLATTRS_INIT); - data->input.tk_ti_hook_fn = tui_tk_ti_getstr; - tinput_init(&data->input, &main_loop); - ugrid_init(&data->grid); - tui_terminal_start(ui); + tui->input.tk_ti_hook_fn = tui_tk_ti_getstr; + tinput_init(&tui->input, &main_loop); + ugrid_init(&tui->grid); + tui_terminal_start(tui); - uv_timer_init(&data->loop->uv, &data->startup_delay_timer); - data->startup_delay_timer.data = ui; - uv_timer_start(&data->startup_delay_timer, after_startup_cb, + uv_timer_init(&tui->loop->uv, &tui->startup_delay_timer); + tui->startup_delay_timer.data = tui; + uv_timer_start(&tui->startup_delay_timer, after_startup_cb, 100, 0); - ui_attach_impl(ui, 0); - - return ui; + loop_poll_events(&main_loop, 1); + *width = tui->width; + *height = tui->height; + *term = tui->term; + return tui; } -void tui_enable_extkeys(TUIData *data) +void tui_enable_extkeys(TUIData *tui) { - TermInput input = data->input; - unibi_term *ut = data->ut; - UI *ui = data->ui; + TermInput input = tui->input; + unibi_term *ut = tui->ut; switch (input.extkeys_type) { case kExtkeysCSIu: - data->unibi_ext.enable_extended_keys = (int)unibi_add_ext_str(ut, "ext.enable_extended_keys", - "\x1b[>1u"); - data->unibi_ext.disable_extended_keys = (int)unibi_add_ext_str(ut, "ext.disable_extended_keys", - "\x1b[<1u"); + tui->unibi_ext.enable_extended_keys = (int)unibi_add_ext_str(ut, "ext.enable_extended_keys", + "\x1b[>1u"); + tui->unibi_ext.disable_extended_keys = (int)unibi_add_ext_str(ut, "ext.disable_extended_keys", + "\x1b[<1u"); break; case kExtkeysXterm: - data->unibi_ext.enable_extended_keys = (int)unibi_add_ext_str(ut, "ext.enable_extended_keys", - "\x1b[>4;2m"); - data->unibi_ext.disable_extended_keys = (int)unibi_add_ext_str(ut, "ext.disable_extended_keys", - "\x1b[>4;0m"); + tui->unibi_ext.enable_extended_keys = (int)unibi_add_ext_str(ut, "ext.enable_extended_keys", + "\x1b[>4;2m"); + tui->unibi_ext.disable_extended_keys = (int)unibi_add_ext_str(ut, "ext.disable_extended_keys", + "\x1b[>4;0m"); break; default: break; } - unibi_out_ext(ui, data->unibi_ext.enable_extended_keys); + unibi_out_ext(tui, tui->unibi_ext.enable_extended_keys); } -static size_t unibi_pre_fmt_str(TUIData *data, unsigned int unibi_index, char *buf, size_t len) +static size_t unibi_pre_fmt_str(TUIData *tui, unsigned int unibi_index, char *buf, size_t len) { - const char *str = unibi_get_str(data->ut, unibi_index); + const char *str = unibi_get_str(tui->ut, unibi_index); if (!str) { return 0U; } - return unibi_run(str, data->params, buf, len); -} - -static void terminfo_start(UI *ui) -{ - TUIData *data = ui->data; - data->scroll_region_is_full_screen = true; - data->bufpos = 0; - data->default_attr = false; - data->can_clear_attr = false; - data->is_invisible = true; - data->want_invisible = false; - data->busy = false; - data->cork = false; - data->overflow = false; - data->set_cursor_color_as_str = false; - data->cursor_color_changed = false; - data->showing_mode = SHAPE_IDX_N; - data->unibi_ext.enable_mouse = -1; - data->unibi_ext.disable_mouse = -1; - data->unibi_ext.enable_mouse_move = -1; - data->unibi_ext.disable_mouse_move = -1; - data->unibi_ext.set_cursor_color = -1; - data->unibi_ext.reset_cursor_color = -1; - data->unibi_ext.enable_bracketed_paste = -1; - data->unibi_ext.disable_bracketed_paste = -1; - data->unibi_ext.enter_strikethrough_mode = -1; - data->unibi_ext.enable_lr_margin = -1; - data->unibi_ext.disable_lr_margin = -1; - data->unibi_ext.enable_focus_reporting = -1; - data->unibi_ext.disable_focus_reporting = -1; - data->unibi_ext.resize_screen = -1; - data->unibi_ext.reset_scroll_region = -1; - data->unibi_ext.set_cursor_style = -1; - data->unibi_ext.reset_cursor_style = -1; - data->unibi_ext.get_bg = -1; - data->unibi_ext.set_underline_color = -1; - data->unibi_ext.enable_extended_keys = -1; - data->unibi_ext.disable_extended_keys = -1; - data->unibi_ext.get_extkeys = -1; - data->out_fd = STDOUT_FILENO; - data->out_isatty = os_isatty(data->out_fd); - data->input.tui_data = data; + return unibi_run(str, tui->params, buf, len); +} + +static void terminfo_start(TUIData *tui) +{ + tui->scroll_region_is_full_screen = true; + tui->bufpos = 0; + tui->default_attr = false; + tui->can_clear_attr = false; + tui->is_invisible = true; + tui->want_invisible = false; + tui->busy = false; + tui->cork = false; + tui->overflow = false; + tui->set_cursor_color_as_str = false; + tui->cursor_color_changed = false; + tui->showing_mode = SHAPE_IDX_N; + tui->unibi_ext.enable_mouse = -1; + tui->unibi_ext.disable_mouse = -1; + tui->unibi_ext.enable_mouse_move = -1; + tui->unibi_ext.disable_mouse_move = -1; + tui->unibi_ext.set_cursor_color = -1; + tui->unibi_ext.reset_cursor_color = -1; + tui->unibi_ext.enable_bracketed_paste = -1; + tui->unibi_ext.disable_bracketed_paste = -1; + tui->unibi_ext.enter_strikethrough_mode = -1; + tui->unibi_ext.enable_lr_margin = -1; + tui->unibi_ext.disable_lr_margin = -1; + tui->unibi_ext.enable_focus_reporting = -1; + tui->unibi_ext.disable_focus_reporting = -1; + tui->unibi_ext.resize_screen = -1; + tui->unibi_ext.reset_scroll_region = -1; + tui->unibi_ext.set_cursor_style = -1; + tui->unibi_ext.reset_cursor_style = -1; + tui->unibi_ext.get_bg = -1; + tui->unibi_ext.set_underline_color = -1; + tui->unibi_ext.enable_extended_keys = -1; + tui->unibi_ext.disable_extended_keys = -1; + tui->unibi_ext.get_extkeys = -1; + tui->out_fd = STDOUT_FILENO; + tui->out_isatty = os_isatty(tui->out_fd); + tui->input.tui_data = tui; const char *term = os_getenv("TERM"); #ifdef MSWIN - os_tty_guess_term(&term, data->out_fd); + os_tty_guess_term(&term, tui->out_fd); os_setenv("TERM", term, 1); // Old os_getenv() pointer is invalid after os_setenv(), fetch it again. term = os_getenv("TERM"); @@ -311,18 +282,15 @@ static void terminfo_start(UI *ui) // Set up unibilium/terminfo. if (term) { - data->ut = unibi_from_term(term); - if (data->ut) { - if (!ui_client_termname) { - ui_client_termname = xstrdup(term); - } - if (!data->term) { - data->term = xstrdup(term); + tui->ut = unibi_from_term(term); + if (tui->ut) { + if (!tui->term) { |