diff options
-rw-r--r-- | scripts/gen_ui_events.lua | 183 | ||||
-rw-r--r-- | scripts/genmsgpack.lua | 1 | ||||
-rw-r--r-- | src/nvim/CMakeLists.txt | 29 | ||||
-rw-r--r-- | src/nvim/api/private/helpers.c | 29 | ||||
-rw-r--r-- | src/nvim/api/ui.c | 156 | ||||
-rw-r--r-- | src/nvim/api/ui_events.in.h | 42 | ||||
-rw-r--r-- | src/nvim/tui/tui.c | 53 | ||||
-rw-r--r-- | src/nvim/ui.c | 17 | ||||
-rw-r--r-- | src/nvim/ui.h | 30 | ||||
-rw-r--r-- | src/nvim/ui_bridge.c | 248 |
10 files changed, 325 insertions, 463 deletions
diff --git a/scripts/gen_ui_events.lua b/scripts/gen_ui_events.lua new file mode 100644 index 0000000000..ab5a8655fe --- /dev/null +++ b/scripts/gen_ui_events.lua @@ -0,0 +1,183 @@ +lpeg = require('lpeg') +mpack = require('mpack') + +-- TODO: reduce copying +-- lpeg grammar for building api metadata from a set of header files. It +-- ignores comments and preprocessor commands and parses a very small subset +-- of C prototypes with a limited set of types +P, R, S = lpeg.P, lpeg.R, lpeg.S +C, Ct, Cc, Cg = lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.Cg + +any = P(1) -- (consume one character) +letter = R('az', 'AZ') + S('_$') +num = R('09') +alpha = letter + num +nl = P('\r\n') + P('\n') +not_nl = any - nl +ws = S(' \t') + nl +fill = ws ^ 0 +c_comment = P('//') * (not_nl ^ 0) +c_preproc = P('#') * (not_nl ^ 0) +typed_container = + (P('ArrayOf(') + P('DictionaryOf(')) * ((any - P(')')) ^ 1) * P(')') +c_id = ( + typed_container + + (letter * (alpha ^ 0)) +) +c_void = P('void') +c_param_type = ( + ((P('Error') * fill * P('*') * fill) * Cc('error')) + + (C(c_id) * (ws ^ 1)) + ) +c_type = (C(c_void) * (ws ^ 1)) + c_param_type +c_param = Ct(c_param_type * C(c_id)) +c_param_list = c_param * (fill * (P(',') * fill * c_param) ^ 0) +c_params = Ct(c_void + c_param_list) +c_proto = Ct( + Cg(c_type, 'return_type') * Cg(c_id, 'name') * + fill * P('(') * fill * Cg(c_params, 'parameters') * fill * P(')') * + Cg(Cc(false), 'async') * + (fill * Cg((P('FUNC_API_SINCE(') * C(num ^ 1)) * P(')'), 'since') ^ -1) * + (fill * Cg((P('REMOTE_ONLY') * Cc(true)), 'remote_only') ^ -1) * + (fill * Cg((P('REMOTE_IMPL') * Cc(true)), 'remote_impl') ^ -1) * + (fill * Cg((P('BRIDGE_IMPL') * Cc(true)), 'bridge_impl') ^ -1) * + fill * P(';') + ) +grammar = Ct((c_proto + c_comment + c_preproc + ws) ^ 1) + + +-- we need at least 4 arguments since the last two are output files +assert(#arg == 6) +input = io.open(arg[2], 'rb') +proto_output = io.open(arg[3], 'wb') +call_output = io.open(arg[4], 'wb') +remote_output = io.open(arg[5], 'wb') +bridge_output = io.open(arg[6], 'wb') + +functions = {} + +local events = grammar:match(input:read('*all')) + +function write_signature(output, ev, prefix, notype) + output:write('('..prefix) + if prefix == "" and #ev.parameters == 0 then + output:write('void') + end + for j = 1, #ev.parameters do + if j > 1 or prefix ~= '' then + output:write(', ') + end + local param = ev.parameters[j] + if not notype then + output:write(param[1]..' ') + end + output:write(param[2]) + end + output:write(')') +end + +function write_arglist(output, ev, need_copy) + output:write(' Array args = ARRAY_DICT_INIT;\n') + for j = 1, #ev.parameters do + local param = ev.parameters[j] + local kind = string.upper(param[1]) + local do_copy = need_copy and (kind == "ARRAY" or kind == "DICTIONARY" or kind == "STRING") + output:write(' ADD(args, ') + if do_copy then + output:write('copy_object(') + end + output:write(kind..'_OBJ('..param[2]..')') + if do_copy then + output:write(')') + end + output:write(');\n') + end +end + +for i = 1, #events do + ev = events[i] + assert(ev.return_type == 'void') + + 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 then + remote_output:write('static void remote_ui_'..ev.name) + write_signature(remote_output, ev, 'UI *ui') + remote_output:write('\n{\n') + write_arglist(remote_output, ev, true) + remote_output:write(' push_call(ui, "'..ev.name..'", args);\n') + remote_output:write('}\n\n') + end + + if not ev.bridge_impl then + + send, argv, recv, recv_argv, recv_cleanup = '', '', '', '', '' + argc = 1 + for j = 1, #ev.parameters do + local param = ev.parameters[j] + copy = 'copy_'..param[2] + if param[1] == 'String' then + send = send..' String copy_'..param[2]..' = copy_string('..param[2]..');\n' + argv = argv..', '..copy..'.data, INT2PTR('..copy..'.size)' + recv = (recv..' String '..param[2].. + ' = (String){.data = argv['..argc..'],'.. + '.size = (size_t)argv['..(argc+1)..']};\n') + recv_argv = recv_argv..', '..param[2] + recv_cleanup = recv_cleanup..' api_free_string('..param[2]..');\n' + argc = argc+2 + elseif param[1] == 'Array' then + send = send..' Array copy_'..param[2]..' = copy_array('..param[2]..');\n' + argv = argv..', '..copy..'.items, INT2PTR('..copy..'.size)' + recv = (recv..' Array '..param[2].. + ' = (Array){.items = argv['..argc..'],'.. + '.size = (size_t)argv['..(argc+1)..']};\n') + recv_argv = recv_argv..', '..param[2] + recv_cleanup = recv_cleanup..' api_free_array('..param[2]..');\n' + argc = argc+2 + elseif param[1] == 'Integer' or param[1] == 'Boolean' then + argv = argv..', INT2PTR('..param[2]..')' + recv_argv = recv_argv..', PTR2INT(argv['..argc..'])' + argc = argc+1 + else + assert(false) + end + end + bridge_output:write('static void ui_bridge_'..ev.name.. + '_event(void **argv)\n{\n') + bridge_output:write(' UI *ui = UI(argv[0]);\n') + bridge_output:write(recv) + bridge_output:write(' ui->'..ev.name..'(ui'..recv_argv..');\n') + bridge_output:write(recv_cleanup) + bridge_output:write('}\n\n') + + bridge_output:write('static void ui_bridge_'..ev.name) + write_signature(bridge_output, ev, 'UI *ui') + bridge_output:write('\n{\n') + bridge_output:write(send) + bridge_output:write(' UI_CALL(ui, '..ev.name..', '..argc..', ui'..argv..');\n}\n') + end + end + + call_output:write('void ui_call_'..ev.name) + write_signature(call_output, ev, '') + call_output:write('\n{\n') + if ev.remote_only then + write_arglist(call_output, ev, false) + call_output:write(' ui_event("'..ev.name..'", args);\n') + else + call_output:write(' UI_CALL') + write_signature(call_output, ev, ev.name, true) + call_output:write(";\n") + end + call_output:write("}\n\n") + +end + + + +proto_output:close() +call_output:close() +remote_output:close() diff --git a/scripts/genmsgpack.lua b/scripts/genmsgpack.lua index 86a051fb4c..c16a844586 100644 --- a/scripts/genmsgpack.lua +++ b/scripts/genmsgpack.lua @@ -87,6 +87,7 @@ for i = 6, #arg do headers[#headers + 1] = parts[#parts - 1]..'/'..parts[#parts] local input = io.open(full_path, 'rb') + local tmp = grammar:match(input:read('*all')) for i = 1, #tmp do local fn = tmp[i] diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 8deeff4654..94d1c00de9 100644 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -13,6 +13,7 @@ endif() set(TOUCHES_DIR ${PROJECT_BINARY_DIR}/touches) set(GENERATED_DIR ${PROJECT_BINARY_DIR}/src/nvim/auto) set(MSGPACK_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/genmsgpack.lua) +set(API_UI_EVENTS_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/gen_api_ui_events.lua) set(API_METADATA ${PROJECT_BINARY_DIR}/api_metadata.mpack) set(FUNCS_DATA ${PROJECT_BINARY_DIR}/funcs_data.mpack) set(MSGPACK_LUA_C_BINDINGS ${GENERATED_DIR}/msgpack_lua_c_bindings.generated.c) @@ -20,6 +21,10 @@ set(HEADER_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/gendeclarations.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_BRIDGE ${GENERATED_DIR}/ui_events_bridge.generated.h) set(GENERATED_EX_CMDS_ENUM ${GENERATED_INCLUDES_DIR}/ex_cmds_enum.generated.h) set(GENERATED_EX_CMDS_DEFS ${GENERATED_DIR}/ex_cmds_defs.generated.h) set(GENERATED_FUNCS ${GENERATED_DIR}/funcs.generated.h) @@ -49,6 +54,7 @@ set(LINT_SUPPRESSES_INSTALL_SCRIPT "${PROJECT_SOURCE_DIR}/cmake/InstallClintErro file(GLOB UNICODE_FILES ${UNICODE_DIR}/*.txt) file(GLOB API_HEADERS api/*.h) +list(REMOVE_ITEM API_HEADERS ${CMAKE_CURRENT_LIST_DIR}/api/ui_events.in.h) file(GLOB MSGPACK_RPC_HEADERS msgpack_rpc/*.h) include_directories(${GENERATED_DIR}) @@ -185,7 +191,11 @@ endfunction() # These lists must be mutually exclusive. foreach(sfile ${NVIM_SOURCES} "${CMAKE_CURRENT_LIST_DIR}/regexp_nfa.c" - ${GENERATED_API_DISPATCH}) + ${GENERATED_API_DISPATCH} + "${GENERATED_UI_EVENTS_CALL}" + "${GENERATED_UI_EVENTS_REMOTE}" + "${GENERATED_UI_EVENTS_BRIDGE}" + ) get_filename_component(full_d ${sfile} PATH) file(RELATIVE_PATH d "${CMAKE_CURRENT_LIST_DIR}" "${full_d}") if(${d} MATCHES "^[.][.]|auto/") @@ -253,6 +263,21 @@ list(APPEND NVIM_GENERATED_SOURCES "${MSGPACK_LUA_C_BINDINGS}" ) +add_custom_command(OUTPUT ${GENERATED_UI_EVENTS} + ${GENERATED_UI_EVENTS_CALL} + ${GENERATED_UI_EVENTS_REMOTE} + ${GENERATED_UI_EVENTS_BRIDGE} + 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_BRIDGE} + DEPENDS + ${API_UI_EVENTS_GENERATOR} + ${CMAKE_CURRENT_LIST_DIR}/api/ui_events.in.h +) + list(APPEND NVIM_GENERATED_FOR_HEADERS "${GENERATED_EX_CMDS_ENUM}" "${GENERATED_EVENTS_ENUM}" @@ -518,7 +543,7 @@ set(NO_SINGLE_CHECK_HEADERS foreach(hfile ${NVIM_HEADERS}) get_test_target(test-includes "${hfile}" relative_path texe) - if(NOT ${hfile} MATCHES "[.]c[.]h$") + if(NOT ${hfile} MATCHES "[.](c|in)[.]h$") set(tsource "${GENERATED_DIR}/${relative_path}.test-include.c") write_file("${tsource}" "#include \"${hfile}\"\nint main(int argc, char **argv) { return 0; }") add_executable( diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index 4cc4b600d5..361570bff4 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -885,6 +885,24 @@ static void init_type_metadata(Dictionary *metadata) PUT(*metadata, "types", DICTIONARY_OBJ(types)); } +String copy_string(String str) +{ + if (str.data != NULL) { + return (String){ .data = xmemdupz(str.data, str.size), .size = str.size }; + } else { + return (String)STRING_INIT; + } +} + +Array copy_array(Array array) +{ + Array rv = ARRAY_DICT_INIT; + for (size_t i = 0; i < array.size; i++) { + ADD(rv, copy_object(array.items[i])); + } + return rv; +} + /// Creates a deep clone of an object Object copy_object(Object obj) { @@ -896,15 +914,10 @@ Object copy_object(Object obj) return obj; case kObjectTypeString: - return STRING_OBJ(cstr_to_string(obj.data.string.data)); + return STRING_OBJ(copy_string(obj.data.string)); - case kObjectTypeArray: { - Array rv = ARRAY_DICT_INIT; - for (size_t i = 0; i < obj.data.array.size; i++) { - ADD(rv, copy_object(obj.data.array.items[i])); - } - return ARRAY_OBJ(rv); - } + case kObjectTypeArray: + return ARRAY_OBJ(copy_array(obj.data.array)); case kObjectTypeDictionary: { Dictionary rv = ARRAY_DICT_INIT; diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index 3c0e8bc049..29d077da82 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -19,6 +19,7 @@ #ifdef INCLUDE_GENERATED_DECLARATIONS # include "api/ui.c.generated.h" +# include "ui_events_remote.generated.h" #endif typedef struct { @@ -236,100 +237,6 @@ static void push_call(UI *ui, char *name, Array args) kv_A(data->buffer, kv_size(data->buffer) - 1).data.array = call; } -static void remote_ui_resize(UI *ui, int width, int height) -{ - Array args = ARRAY_DICT_INIT; - ADD(args, INTEGER_OBJ(width)); - ADD(args, INTEGER_OBJ(height)); - push_call(ui, "resize", args); -} - -static void remote_ui_clear(UI *ui) -{ - Array args = ARRAY_DICT_INIT; - push_call(ui, "clear", args); -} - -static void remote_ui_eol_clear(UI *ui) -{ - Array args = ARRAY_DICT_INIT; - push_call(ui, "eol_clear", args); -} - -static void remote_ui_cursor_goto(UI *ui, int row, int col) -{ - Array args = ARRAY_DICT_INIT; - ADD(args, INTEGER_OBJ(row)); - ADD(args, INTEGER_OBJ(col)); - push_call(ui, "cursor_goto", args); -} - -static void remote_ui_update_menu(UI *ui) -{ - Array args = ARRAY_DICT_INIT; - push_call(ui, "update_menu", args); -} - -static void remote_ui_busy_start(UI *ui) -{ - Array args = ARRAY_DICT_INIT; - push_call(ui, "busy_start", args); -} - -static void remote_ui_busy_stop(UI *ui) -{ - Array args = ARRAY_DICT_INIT; - push_call(ui, "busy_stop", args); -} - -static void remote_ui_mouse_on(UI *ui) -{ - Array args = ARRAY_DICT_INIT; - push_call(ui, "mouse_on", args); -} - -static void remote_ui_mouse_off(UI *ui) -{ - Array args = ARRAY_DICT_INIT; - push_call(ui, "mouse_off", args); -} - -static void remote_ui_mode_change(UI *ui, int mode_idx) -{ - Array args = ARRAY_DICT_INIT; - - 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); -} - -static void remote_ui_set_scroll_region(UI *ui, int top, int bot, int left, - int right) -{ - Array args = ARRAY_DICT_INIT; - ADD(args, INTEGER_OBJ(top)); - ADD(args, INTEGER_OBJ(bot)); - ADD(args, INTEGER_OBJ(left)); - ADD(args, INTEGER_OBJ(right)); - push_call(ui, "set_scroll_region", args); -} - -static void remote_ui_scroll(UI *ui, int count) -{ - Array args = ARRAY_DICT_INIT; - ADD(args, INTEGER_OBJ(count)); - push_call(ui, "scroll", args); -} - -static void remote_ui_mode_info_set(UI *ui, bool guicursor_enabled, Array data) -{ - Array args = ARRAY_DICT_INIT; - ADD(args, BOOLEAN_OBJ(guicursor_enabled)); - ADD(args, copy_object(ARRAY_OBJ(data))); - push_call(ui, "mode_info_set", args); -} static void remote_ui_highlight_set(UI *ui, HlAttrs attrs) { @@ -372,47 +279,6 @@ static void remote_ui_highlight_set(UI *ui, HlAttrs attrs) push_call(ui, "highlight_set", args); } -static void remote_ui_put(UI *ui, uint8_t *data, size_t size) -{ - Array args = ARRAY_DICT_INIT; - String str = { .data = xmemdupz(data, size), .size = size }; - ADD(args, STRING_OBJ(str)); - push_call(ui, "put", args); -} - -static void remote_ui_bell(UI *ui) -{ - Array args = ARRAY_DICT_INIT; - push_call(ui, "bell", args); -} - -static void remote_ui_visual_bell(UI *ui) -{ - Array args = ARRAY_DICT_INIT; - push_call(ui, "visual_bell", args); -} - -static void remote_ui_update_fg(UI *ui, int fg) -{ - Array args = ARRAY_DICT_INIT; - ADD(args, INTEGER_OBJ(fg)); - push_call(ui, "update_fg", args); -} - -static void remote_ui_update_bg(UI *ui, int bg) -{ - Array args = ARRAY_DICT_INIT; - ADD(args, INTEGER_OBJ(bg)); - push_call(ui, "update_bg", args); -} - -static void remote_ui_update_sp(UI *ui, int sp) -{ - Array args = ARRAY_DICT_INIT; - ADD(args, INTEGER_OBJ(sp)); - push_call(ui, "update_sp", args); -} - static void remote_ui_flush(UI *ui) { UIData *data = ui->data; @@ -422,26 +288,6 @@ static void remote_ui_flush(UI *ui) } } -static void remote_ui_suspend(UI *ui) -{ - Array args = ARRAY_DICT_INIT; - push_call(ui, "suspend", args); -} - -static void remote_ui_set_title(UI *ui, char *title) -{ - Array args = ARRAY_DICT_INIT; - ADD(args, STRING_OBJ(cstr_to_string(title))); - push_call(ui, "set_title", args); -} - -static void remote_ui_set_icon(UI *ui, char *icon) -{ - Array args = ARRAY_DICT_INIT; - ADD(args, STRING_OBJ(cstr_to_string(icon))); - push_call(ui, "set_icon", args); -} - static void remote_ui_event(UI *ui, char *name, Array args, bool *args_consumed) { Array my_args = ARRAY_DICT_INIT; diff --git a/src/nvim/api/ui_events.in.h b/src/nvim/api/ui_events.in.h new file mode 100644 index 0000000000..e1ff3dfc9d --- /dev/null +++ b/src/nvim/api/ui_events.in.h @@ -0,0 +1,42 @@ +#ifndef NVIM_API_UI_EVENTS_IN_H +#define NVIM_API_UI_EVENTS_IN_H + +// This file is not compiled, just parsed for definitons +#ifdef INCLUDE_GENERATED_DECLARATIONS +#error "don't include this file, include nvim/ui.h" +#endif + +#include "nvim/api/private/defs.h" +#include "nvim/func_attr.h" +#include "nvim/ui.h" + +void resize(Integer rows, Integer columns); +void clear(void); +void eol_clear(void); +void cursor_goto(Integer row, Integer col); +void mode_info_set(Boolean enabled, Array cursor_styles); +void update_menu(void); +void busy_start(void); +void busy_stop(void); +void mouse_on(void); +void mouse_off(void); +void mode_change(String mode, Integer mode_idx); +void set_scroll_region(Integer top, Integer bot, Integer left, Integer right); +void scroll(Integer count); +void highlight_set(HlAttrs attrs) REMOTE_IMPL BRIDGE_IMPL; +void put(String str); +void bell(void); +void visual_bell(void); +void flush(void) REMOTE_IMPL; +void update_fg(Integer fg); +void update_bg(Integer bg); +void update_sp(Integer sp); +void suspend(void) BRIDGE_IMPL; +void set_title(String title); +void set_icon(String icon); + +void popupmenu_show(Array items, Integer selected, Integer row, Integer col) REMOTE_ONLY; +void popupmenu_hide(void) REMOTE_ONLY; +void popupmenu_select(Integer selected) REMOTE_ONLY; + +#endif // NVIM_API_UI_EVENTS_IN_H diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index 399d6c74ca..4a81b32199 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -187,7 +187,7 @@ static void terminfo_stop(UI *ui) { TUIData *data = ui->data; // Destroy output stuff - tui_mode_change(ui, SHAPE_IDX_N); + tui_mode_change(ui, (String)STRING_INIT, SHAPE_IDX_N); tui_mouse_off(ui); unibi_out(ui, unibi_exit_attribute_mode); // cursor should be set to normal before exiting alternate screen @@ -417,14 +417,14 @@ static void clear_region(UI *ui, int top, int bot, int left, int right) unibi_goto(ui, grid->row, grid->col); } -static void tui_resize(UI *ui, int width, int height) +static void tui_resize(UI *ui, Integer width, Integer height) { TUIData *data = ui->data; - ugrid_resize(&data->grid, width, height); + ugrid_resize(&data->grid, (int)width, (int)height); if (!got_winch) { // Try to resize the terminal window. char r[16]; // enough for 9999x9999 - snprintf(r, sizeof(r), "\x1b[8;%d;%dt", height, width); + snprintf(r, sizeof(r), "\x1b[8;%d;%dt", (int)height, (int)width); out(ui, r, strlen(r)); } else { // Already handled the SIGWINCH signal; avoid double-resize. got_winch = false; @@ -447,11 +447,11 @@ static void tui_eol_clear(UI *ui) clear_region(ui, grid->row, grid->row, grid->col, grid->right); } -static void tui_cursor_goto(UI *ui, int row, int col) +static void tui_cursor_goto(UI *ui, Integer row, Integer col) { TUIData *data = ui->data; - ugrid_goto(&data->grid, row, col); - unibi_goto(ui, row, col); + ugrid_goto(&data->grid, (int)row, (int)col); + unibi_goto(ui, (int)row, (int)col); } CursorShape tui_cursor_decode_shape(const char *shape_str) @@ -599,30 +599,31 @@ static void tui_set_mode(UI *ui, ModeShape mode) } /// @param mode editor mode -static void tui_mode_change(UI *ui, int mode_idx) +static void tui_mode_change(UI *ui, String mode, Integer mode_idx) { TUIData *data = ui->data; 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, - int right) +static void tui_set_scroll_region(UI *ui, Integer top, Integer bot, + Integer left, Integer right) { TUIData *data = ui->data; - ugrid_set_scroll_region(&data->grid, top, bot, left, right); + ugrid_set_scroll_region(&data->grid, (int)top, (int)bot, + (int)left, (int)right); data->can_use_terminal_scroll = left == 0 && right == ui->width - 1 && ((top == 0 && bot == ui->height - 1) || unibi_get_str(data->ut, unibi_change_scroll_region)); } -static void tui_scroll(UI *ui, int count) +static void tui_scroll(UI *ui, Integer count) { TUIData *data = ui->data; UGrid *grid = &data->grid; int clear_top, clear_bot; - ugrid_scroll(grid, count, &clear_top, &clear_bot); + ugrid_scroll(grid, (int)count, &clear_top, &clear_bot); if (data->can_use_terminal_scroll) { // Change terminal scroll region and move cursor to the top @@ -642,7 +643,7 @@ static void tui_scroll(UI *ui, int count) if (count == 1) { unibi_out(ui, unibi_delete_line); } else { - data->params[0].i = count; + data->params[0].i = (int)count; unibi_out(ui, unibi_parm_delete_line); } } @@ -652,7 +653,7 @@ static void tui_scroll(UI *ui, int count) if (count == -1) { unibi_out(ui, unibi_insert_line); } else { - data->params[0].i = -count; + data->params[0].i = -(int)count; unibi_out(ui, unibi_parm_insert_line); } } @@ -683,10 +684,10 @@ static void tui_highlight_set(UI *ui, HlAttrs attrs) ((TUIData *)ui->data)->grid.attrs = attrs; } -static void tui_put(UI *ui, uint8_t *text, size_t size) +static void tui_put(UI *ui, String text) { TUIData *data = ui->data; - print_cell(ui, ugrid_put(&data->grid, text, size)); + print_cell(ui, ugrid_put(&data->grid, (uint8_t *)text.data, text.size)); } static void tui_bell(UI *ui) @@ -699,17 +700,17 @@ static void tui_visual_bell(UI *ui) unibi_out(ui, unibi_flash_screen); } -static void tui_update_fg(UI *ui, int fg) +static void tui_update_fg(UI *ui, Integer fg) { - ((TUIData *)ui->data)->grid.fg = fg; + ((TUIData *)ui->data)->grid.fg = (int)fg; } -static void tui_update_bg(UI *ui, int bg) +static void tui_update_bg(UI *ui, Integer bg) { - ((TUIData *)ui->data)->grid.bg = bg; + ((TUIData *)ui->data)->grid.bg = (int)bg; } -static void tui_update_sp(UI *ui, int sp) +static void tui_update_sp(UI *ui, Integer sp) { // Do nothing; 'special' color is for GUI only } @@ -784,19 +785,19 @@ static void tui_suspend(UI *ui) #endif } -static void tui_set_title(UI *ui, char *title) +static void tui_set_title(UI *ui, String title) { TUIData *data = ui->data; - if (!(title && unibi_get_str(data->ut, unibi_to_status_line) + if (!(title.data && unibi_get_str(data->ut, unibi_to_status_line) && unibi_get_str(data->ut, unibi_from_status_line))) { return; } unibi_out(ui, unibi_to_status_line); - out(ui, title, strlen(title)); + out(ui, title.data, title.size); unibi_out(ui, unibi_from_status_line); } -static void tui_set_icon(UI *ui, char *icon) +static void tui_set_icon(UI *ui, String icon) { } diff --git a/src/nvim/ui.c b/src/nvim/ui.c index 924a4192bc..ec59f96d87 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -89,6 +89,10 @@ static int old_mode_idx = -1; #define UI_CALL_MORE(method, ...) if (ui->method) ui->method(ui, __VA_ARGS__) #define UI_CALL_ZERO(method) if (ui->method) ui->method(ui) +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "ui_events_call.generated.h" +#endif + void ui_builtin_start(void) { #ifdef FEAT_TUI @@ -136,13 +140,13 @@ void ui_suspend(void) void ui_set_title(char *title) { - UI_CALL(set_title, title); + ui_call_set_title(cstr_as_string(title)); UI_CALL(flush); } void ui_set_icon(char *icon) { - UI_CALL(set_icon, icon); + ui_call_set_icon(cstr_as_string(icon)); UI_CALL(flush); } @@ -390,7 +394,7 @@ void ui_mode_info_set(void) { Array style = mode_style_array(); bool enabled = (*p_guicursor != NUL); - UI_CALL(mode_info_set, enabled, style); + ui_call_mode_info_set(enabled, style); api_free_array(style); } @@ -420,11 +424,11 @@ static void send_output(uint8_t **ptr) while (*p >= 0x20) { size_t clen = (size_t)mb_ptr2len(p); - UI_CALL(put, p, (size_t)clen); + ui_call_put((String){.data = (char *)p, .size = clen}); col++; if (mb_ptr2cells(p) > 1) { // double cell character, blank the next cell - UI_CALL(put, NULL, 0); + ui_call_put((String)STRING_INIT); col++; } if (utf_ambiguous_width(utf_ptr2char(p))) { @@ -560,7 +564,8 @@ void ui_cursor_shape(void) if (old_mode_idx != mode_idx) { old_mode_idx = mode_idx; - UI_CALL(mode_change, mode_idx); + char *full_name = shape_table[mode_idx].full_name; + ui_call_mode_change(cstr_as_string(full_name), mode_idx); } conceal_check_cursur_line(); } diff --git a/src/nvim/ui.h b/src/nvim/ui.h index 9338ab3ea3..064f77fee1 100644 --- a/src/nvim/ui.h +++ b/src/nvim/ui.h @@ -28,35 +28,17 @@ struct ui_t { bool ui_ext[UI_WIDGETS]; ///< Externalized widgets int width, height; void *data; - void (*resize)(UI *ui, int rows, int columns); - void (*clear)(UI *ui); - void (*eol_clear)(UI *ui); - void (*cursor_goto)(UI *ui, int row, int col); - void (*mode_info_set)(UI *ui, bool enabled, Array cursor_styles); - void (*update_menu)(UI *ui); - void (*busy_start)(UI *ui); - void (*busy_stop)(UI *ui); - void (*mouse_on)(UI *ui); - void (*mouse_off)(UI *ui); - 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); - void (*put)(UI *ui, uint8_t *str, size_t len); - void (*bell)(UI *ui); - void (*visual_bell)(UI *ui); - void (*flush)(UI *ui); - void (*update_fg)(UI *ui, int fg); - void (*update_bg)(UI *ui, int bg); - void (*update_sp)(UI *ui, int sp); - void (*suspend)(UI *ui); - void (*set_title)(UI *ui, char *title); - void (*set_icon)(UI *ui, char *icon); + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "ui_events.generated.h" +#endif + void (*event)(UI *ui, char *name, Array args, bool *args_consumed); void (*stop)(UI *ui); }; #ifdef INCLUDE_GENERATED_DECLARATIONS # include "ui.h.generated.h" +# include "ui_events_call.h.generated.h" #endif #endif // NVIM_UI_H diff --git a/src/nvim/ui_bridge.c b/src/nvim/ui_bridge.c index d790770892..0165db7c0c 100644 --- a/src/nvim/ui_bridge.c +++ b/src/nvim/ui_bridge.c @@ -49,8 +49,12 @@ static argv_callback uilog_event = NULL; event_create(ui_bridge_##name##_event, argc, __VA_ARGS__), UI(ui)) #endif -#define INT2PTR(i) ((void *)(uintptr_t)i) -#define PTR2INT(p) ((int)(uintptr_t)p) +#define INT2PTR(i) ((void *)(intptr_t)i) +#define PTR2INT(p) ((Integer)(intptr_t)p) + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "ui_events_bridge.generated.h" +#endif UI *ui_bridge_attach(UI *ui, ui_main_fn ui_main, event_scheduler scheduler) { @@ -146,148 +150,6 @@ static void ui_bridge_stop_event(void **argv) ui->stop(ui); } -static void ui_bridge_resize(UI *b, int width, int height) -{ - UI_CALL(b, resize, 3, b, INT2PTR(width), INT2PTR(height)); -} -static void ui_bridge_resize_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->resize(ui, PTR2INT(argv[1]), PTR2INT(argv[2])); -} - -static void ui_bridge_clear(UI *b) -{ - UI_CALL(b, clear, 1, b); -} -static void ui_bridge_clear_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->clear(ui); -} - -static void ui_bridge_eol_clear(UI *b) -{ - UI_CALL(b, eol_clear, 1, b); -} -static void ui_bridge_eol_clear_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->eol_clear(ui); -} - -static void ui_bridge_cursor_goto(UI *b, int row, int col) -{ - UI_CALL(b, cursor_goto, 3, b, INT2PTR(row), INT2PTR(col)); -} -static void ui_bridge_cursor_goto_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->cursor_goto(ui, PTR2INT(argv[1]), PTR2INT(argv[2])); -} - -static void ui_bridge_mode_info_set(UI *b, bool enabled, Array modes) -{ - bool *enabledp = xmalloc(sizeof(*enabledp)); - Object *modesp = xmalloc(sizeof(*modesp)); - *enabledp = enabled; - *modesp = copy_object(ARRAY_OBJ(modes)); - UI_CALL(b, mode_info_set, 3, b, enabledp, modesp); -} -static void ui_bridge_mode_info_set_event(void **argv) -{ - UI *ui = UI(argv[0]); - bool *enabled = argv[1]; - Object *modes = argv[2]; - ui->mode_info_set(ui, *enabled, modes->data.array); - xfree(enabled); - api_free_object(*modes); - xfree(modes); -} - -static void ui_bridge_update_menu(UI *b) -{ - UI_CALL(b, update_menu, 1, b); -} -static void ui_bridge_update_menu_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->update_menu(ui); -} - -static void ui_bridge_busy_start(UI *b) -{ - UI_CALL(b, busy_start, 1, b); -} -static void ui_bridge_busy_start_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->busy_start(ui); -} - -static void ui_bridge_busy_stop(UI *b) -{ - UI_CALL(b, busy_stop, 1, b); -} -static void ui_bridge_busy_stop_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->busy_stop(ui); -} - -static void ui_bridge_mouse_on(UI *b) -{ - UI_CALL(b, mouse_on, 1, b); -} -static void ui_bridge_mouse_on_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->mouse_on(ui); -} - -static void ui_bridge_mouse_off(UI *b) -{ - UI_CALL(b, mouse_off, 1, b); -} -static void ui_bridge_mouse_off_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->mouse_off(ui); -} - -static void ui_bridge_mode_change(UI *b, int mode_idx) -{ - UI_CALL(b, mode_change, 2, b, INT2PTR(mode_idx)); -} -static void ui_bridge_mode_change_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->mode_change(ui, PTR2INT(argv[1])); -} - -static void ui_bridge_set_scroll_region(UI *b, int top, int bot, int left, - int right) -{ - UI_CALL(b, set_scroll_region, 5, b, INT2PTR(top), INT2PTR(bot), - INT2PTR(left), INT2PTR(right)); -} -static void ui_bridge_set_scroll_region_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->set_scroll_region(ui, PTR2INT(argv[1]), PTR2INT(argv[2]), - PTR2INT(argv[3]), PTR2INT(argv[4])); -} - -static void ui_bridge_scroll(UI *b, int count) -{ - UI_CALL(b, scroll, 2, b, INT2PTR(count)); -} -static void ui_bridge_scroll_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->scroll(ui, PTR2INT(argv[1])); -} - static void ui_bridge_highlight_set(UI *b, HlAttrs attrs) { HlAttrs *a = xmalloc(sizeof(HlAttrs)); @@ -301,82 +163,6 @@ static void ui_bridge_highlight_set_event(void **argv) xfree(argv[1]); } -static void ui_bridge_put(UI *b, uint8_t *text, size_t size) -{ - uint8_t *t = NULL; - if (text) { - t = xmalloc(sizeof(((UCell *)0)->data)); - memcpy(t, text, size); - } - UI_CALL(b, put, 3, b, t, INT2PTR(size)); -} -static void ui_bridge_put_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->put(ui, (uint8_t *)argv[1], (size_t)(uintptr_t)argv[2]); - xfree(argv[1]); -} - -static void ui_bridge_bell(UI *b) -{ - UI_CALL(b, bell, 1, b); -} -static void ui_bridge_bell_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->bell(ui); -} - -static void ui_bridge_visual_bell(UI *b) -{ - UI_CALL(b, visual_bell, 1, b); -} -static void ui_bridge_visual_bell_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->visual_bell(ui); -} - -static void ui_bridge_update_fg(UI *b, int fg) -{ - UI_CALL(b, update_fg, 2, b, INT2PTR(fg)); -} -static void ui_bridge_update_fg_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->update_fg(ui, PTR2INT(argv[1])); -} - -static void ui_bridge_update_bg(UI *b, int bg) -{ - UI_CALL(b, update_bg, 2, b, INT2PTR(bg)); -} -static void ui_bridge_update_bg_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->update_bg(ui, PTR2INT(argv[1])); -} - -static void ui_bridge_update_sp(UI *b, int sp) -{ - UI_CALL(b, update_sp, 2, b, INT2PTR(sp)); -} -static void ui_bridge_update_sp_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->update_sp(ui, PTR2INT(argv[1])); -} - -static void ui_bridge_flush(UI *b) -{ - UI_CALL(b, flush, 1, b); -} -static void ui_bridge_flush_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->flush(ui); -} - static void ui_bridge_suspend(UI *b) { UIBridgeData *data = (UIBridgeData *)b; @@ -394,25 +180,3 @@ static void ui_bridge_suspend_event(void **argv) UI *ui = UI(argv[0]); ui->suspend(ui); } - -static void ui_bridge_set_title(UI *b, char *title) -{ - UI_CALL(b, set_title, 2, b, title ? xstrdup(title) : NULL); -} -static void ui_bridge_set_title_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->set_title(ui, argv[1]); - xfree(argv[1]); -} - -static void ui_bridge_set_icon(UI *b, char *icon) -{ - UI_CALL(b, set_icon, 2, b, icon ? xstrdup(icon) : NULL); -} -static void ui_bridge_set_icon_event(void **argv) -{ - UI *ui = UI(argv[0]); - ui->set_icon(ui, argv[1]); - xfree(argv[1]); -} |