refactor(ui): remove outdated UI vs UIData distinction

Just some basic spring cleaning.

In the distant past, not all UI:s where remote UI:s. They still aren't,
but both of the "UI" and "UIData" structs are now only for remote UI:s.
Thus join them as "RemoteUI".
This commit is contained in:
bfredl
2024-03-08 09:15:21 +01:00
parent 55c9e2c96e
commit e534ec47db
6 changed files with 168 additions and 193 deletions

View File

@@ -39,7 +39,7 @@
#include "nvim/types_defs.h" #include "nvim/types_defs.h"
#include "nvim/ui.h" #include "nvim/ui.h"
#define BUF_POS(data) ((size_t)((data)->packer.ptr - (data)->packer.startptr)) #define BUF_POS(ui) ((size_t)((ui)->packer.ptr - (ui)->packer.startptr))
#ifdef INCLUDE_GENERATED_DECLARATIONS #ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/ui.c.generated.h" # include "api/ui.c.generated.h"
@@ -64,19 +64,18 @@ static void mpack_str_small(char **buf, const char *str, size_t len)
*buf += len; *buf += len;
} }
static void remote_ui_destroy(UI *ui) static void remote_ui_destroy(RemoteUI *ui)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_ALL
{ {
UIData *data = ui->data; kv_destroy(ui->call_buf);
kv_destroy(data->call_buf); xfree(ui->packer.startptr);
xfree(data->packer.startptr);
XFREE_CLEAR(ui->term_name); XFREE_CLEAR(ui->term_name);
xfree(ui); xfree(ui);
} }
void remote_ui_disconnect(uint64_t channel_id) void remote_ui_disconnect(uint64_t channel_id)
{ {
UI *ui = pmap_get(uint64_t)(&connected_uis, channel_id); RemoteUI *ui = pmap_get(uint64_t)(&connected_uis, channel_id);
if (!ui) { if (!ui) {
return; return;
} }
@@ -88,7 +87,7 @@ void remote_ui_disconnect(uint64_t channel_id)
#ifdef EXITFREE #ifdef EXITFREE
void remote_ui_free_all_mem(void) void remote_ui_free_all_mem(void)
{ {
UI *ui; RemoteUI *ui;
map_foreach_value(&connected_uis, ui, { map_foreach_value(&connected_uis, ui, {
remote_ui_destroy(ui); remote_ui_destroy(ui);
}); });
@@ -146,7 +145,7 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, Dictiona
"Expected width > 0 and height > 0"); "Expected width > 0 and height > 0");
return; return;
} }
UI *ui = xcalloc(1, sizeof(UI)); RemoteUI *ui = xcalloc(1, sizeof(RemoteUI));
ui->width = (int)width; ui->width = (int)width;
ui->height = (int)height; ui->height = (int)height;
ui->pum_row = -1.0; ui->pum_row = -1.0;
@@ -173,27 +172,26 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, Dictiona
ui->ui_ext[kUICmdline] = true; ui->ui_ext[kUICmdline] = true;
} }
UIData *data = ui->data; ui->channel_id = channel_id;
data->channel_id = channel_id; ui->cur_event = NULL;
data->cur_event = NULL; ui->hl_id = 0;
data->hl_id = 0; ui->client_col = -1;
data->client_col = -1; ui->nevents_pos = NULL;
data->nevents_pos = NULL; ui->nevents = 0;
data->nevents = 0; ui->flushed_events = false;
data->flushed_events = false; ui->ncalls_pos = NULL;
data->ncalls_pos = NULL; ui->ncalls = 0;
data->ncalls = 0; ui->ncells_pending = 0;
data->ncells_pending = 0; ui->packer = (PackerBuffer) {
data->packer = (PackerBuffer) {
.startptr = NULL, .startptr = NULL,
.ptr = NULL, .ptr = NULL,
.endptr = NULL, .endptr = NULL,
.packer_flush = ui_flush_callback, .packer_flush = ui_flush_callback,
.anydata = data, .anydata = ui,
}; };
data->wildmenu_active = false; ui->wildmenu_active = false;
data->call_buf = (Array)ARRAY_DICT_INIT; ui->call_buf = (Array)ARRAY_DICT_INIT;
kv_ensure_space(data->call_buf, 16); kv_ensure_space(ui->call_buf, 16);
pmap_put(uint64_t)(&connected_uis, channel_id, ui); pmap_put(uint64_t)(&connected_uis, channel_id, ui);
ui_attach_impl(ui, channel_id); ui_attach_impl(ui, channel_id);
@@ -245,7 +243,7 @@ void nvim_ui_detach(uint64_t channel_id, Error *err)
} }
// TODO(bfredl): use me to detach a specific ui from the server // TODO(bfredl): use me to detach a specific ui from the server
void remote_ui_stop(UI *ui) void remote_ui_stop(RemoteUI *ui)
{ {
} }
@@ -264,7 +262,7 @@ void nvim_ui_try_resize(uint64_t channel_id, Integer width, Integer height, Erro
return; return;
} }
UI *ui = pmap_get(uint64_t)(&connected_uis, channel_id); RemoteUI *ui = pmap_get(uint64_t)(&connected_uis, channel_id);
ui->width = (int)width; ui->width = (int)width;
ui->height = (int)height; ui->height = (int)height;
ui_refresh(); ui_refresh();
@@ -278,12 +276,12 @@ void nvim_ui_set_option(uint64_t channel_id, String name, Object value, Error *e
"UI not attached to channel: %" PRId64, channel_id); "UI not attached to channel: %" PRId64, channel_id);
return; return;
} }
UI *ui = pmap_get(uint64_t)(&connected_uis, channel_id); RemoteUI *ui = pmap_get(uint64_t)(&connected_uis, channel_id);
ui_set_option(ui, false, name, value, error); ui_set_option(ui, false, name, value, error);
} }
static void ui_set_option(UI *ui, bool init, String name, Object value, Error *err) static void ui_set_option(RemoteUI *ui, bool init, String name, Object value, Error *err)
{ {
if (strequal(name.data, "override")) { if (strequal(name.data, "override")) {
VALIDATE_T("override", kObjectTypeBoolean, value.type, { VALIDATE_T("override", kObjectTypeBoolean, value.type, {
@@ -431,7 +429,7 @@ void nvim_ui_pum_set_height(uint64_t channel_id, Integer height, Error *err)
return; return;
} }
UI *ui = pmap_get(uint64_t)(&connected_uis, channel_id); RemoteUI *ui = pmap_get(uint64_t)(&connected_uis, channel_id);
if (!ui->ui_ext[kUIPopupmenu]) { if (!ui->ui_ext[kUIPopupmenu]) {
api_set_error(err, kErrorTypeValidation, api_set_error(err, kErrorTypeValidation,
"It must support the ext_popupmenu option"); "It must support the ext_popupmenu option");
@@ -467,7 +465,7 @@ void nvim_ui_pum_set_bounds(uint64_t channel_id, Float width, Float height, Floa
return; return;
} }
UI *ui = pmap_get(uint64_t)(&connected_uis, channel_id); RemoteUI *ui = pmap_get(uint64_t)(&connected_uis, channel_id);
if (!ui->ui_ext[kUIPopupmenu]) { if (!ui->ui_ext[kUIPopupmenu]) {
api_set_error(err, kErrorTypeValidation, api_set_error(err, kErrorTypeValidation,
"UI must support the ext_popupmenu option"); "UI must support the ext_popupmenu option");
@@ -516,78 +514,75 @@ void nvim_ui_term_event(uint64_t channel_id, String event, Object value, Error *
} }
} }
static void flush_event(UIData *data) static void flush_event(RemoteUI *ui)
{ {
if (data->cur_event) { if (ui->cur_event) {
mpack_w2(&data->ncalls_pos, 1 + data->ncalls); mpack_w2(&ui->ncalls_pos, 1 + ui->ncalls);
data->cur_event = NULL; ui->cur_event = NULL;
data->ncalls_pos = NULL; ui->ncalls_pos = NULL;
data->ncalls = 0; ui->ncalls = 0;
} }
} }
static void ui_alloc_buf(UIData *data) static void ui_alloc_buf(RemoteUI *ui)
{ {
data->packer.startptr = alloc_block(); ui->packer.startptr = alloc_block();
data->packer.ptr = data->packer.startptr; ui->packer.ptr = ui->packer.startptr;
data->packer.endptr = data->packer.startptr + UI_BUF_SIZE; ui->packer.endptr = ui->packer.startptr + UI_BUF_SIZE;
} }
static void prepare_call(UI *ui, const char *name) static void prepare_call(RemoteUI *ui, const char *name)
{ {
UIData *data = ui->data; if (ui->packer.startptr && BUF_POS(ui) > UI_BUF_SIZE - EVENT_BUF_SIZE) {
if (data->packer.startptr && BUF_POS(data) > UI_BUF_SIZE - EVENT_BUF_SIZE) { ui_flush_buf(ui);
ui_flush_buf(data);
} }
if (data->packer.startptr == NULL) { if (ui->packer.startptr == NULL) {
ui_alloc_buf(data); ui_alloc_buf(ui);
} }
// To optimize data transfer(especially for "grid_line"), we bundle adjacent // To optimize data transfer(especially for "grid_line"), we bundle adjacent
// calls to same method together, so only add a new call entry if the last // calls to same method together, so only add a new call entry if the last
// method call is different from "name" // method call is different from "name"
if (!data->cur_event || !strequal(data->cur_event, name)) { if (!ui->cur_event || !strequal(ui->cur_event, name)) {
char **buf = &data->packer.ptr; char **buf = &ui->packer.ptr;
if (!data->nevents_pos) { if (!ui->nevents_pos) {
// [2, "redraw", [...]] // [2, "redraw", [...]]
mpack_array(buf, 3); mpack_array(buf, 3);
mpack_uint(buf, 2); mpack_uint(buf, 2);
mpack_str_small(buf, S_LEN("redraw")); mpack_str_small(buf, S_LEN("redraw"));
data->nevents_pos = mpack_array_dyn16(buf); ui->nevents_pos = mpack_array_dyn16(buf);
assert(data->cur_event == NULL); assert(ui->cur_event == NULL);
} }
flush_event(data); flush_event(ui);
data->cur_event = name; ui->cur_event = name;
data->ncalls_pos = mpack_array_dyn16(buf); ui->ncalls_pos = mpack_array_dyn16(buf);
mpack_str_small(buf, name, strlen(name)); mpack_str_small(buf, name, strlen(name));
data->nevents++; ui->nevents++;
data->ncalls = 1; ui->ncalls = 1;
} else { } else {
data->ncalls++; ui->ncalls++;
} }
} }
/// Pushes data into UI.UIData, to be consumed later by remote_ui_flush(). /// Pushes data into RemoteUI, to be consumed later by remote_ui_flush().
static void push_call(UI *ui, const char *name, Array args) static void push_call(RemoteUI *ui, const char *name, Array args)
{ {
UIData *data = ui->data;
prepare_call(ui, name); prepare_call(ui, name);
mpack_object_array(args, &data->packer); mpack_object_array(args, &ui->packer);
} }
static void ui_flush_callback(PackerBuffer *packer) static void ui_flush_callback(PackerBuffer *packer)
{ {
UIData *data = packer->anydata; RemoteUI *ui = packer->anydata;
ui_flush_buf(data); ui_flush_buf(ui);
ui_alloc_buf(data); ui_alloc_buf(ui);
} }
void remote_ui_grid_clear(UI *ui, Integer grid) void remote_ui_grid_clear(RemoteUI *ui, Integer grid)
{ {
UIData *data = ui->data; Array args = ui->call_buf;
Array args = data->call_buf;
if (ui->ui_ext[kUILinegrid]) { if (ui->ui_ext[kUILinegrid]) {
ADD_C(args, INTEGER_OBJ(grid)); ADD_C(args, INTEGER_OBJ(grid));
} }
@@ -595,14 +590,13 @@ void remote_ui_grid_clear(UI *ui, Integer grid)
push_call(ui, name, args); push_call(ui, name, args);
} }
void remote_ui_grid_resize(UI *ui, Integer grid, Integer width, Integer height) void remote_ui_grid_resize(RemoteUI *ui, Integer grid, Integer width, Integer height)
{ {
UIData *data = ui->data; Array args = ui->call_buf;
Array args = data->call_buf;
if (ui->ui_ext[kUILinegrid]) { if (ui->ui_ext[kUILinegrid]) {
ADD_C(args, INTEGER_OBJ(grid)); ADD_C(args, INTEGER_OBJ(grid));
} else { } else {
data->client_col = -1; // force cursor update ui->client_col = -1; // force cursor update
} }
ADD_C(args, INTEGER_OBJ(width)); ADD_C(args, INTEGER_OBJ(width));
ADD_C(args, INTEGER_OBJ(height)); ADD_C(args, INTEGER_OBJ(height));
@@ -610,12 +604,11 @@ void remote_ui_grid_resize(UI *ui, Integer grid, Integer width, Integer height)
push_call(ui, name, args); push_call(ui, name, args);
} }
void remote_ui_grid_scroll(UI *ui, Integer grid, Integer top, Integer bot, Integer left, void remote_ui_grid_scroll(RemoteUI *ui, Integer grid, Integer top, Integer bot, Integer left,
Integer right, Integer rows, Integer cols) Integer right, Integer rows, Integer cols)
{ {
UIData *data = ui->data;
if (ui->ui_ext[kUILinegrid]) { if (ui->ui_ext[kUILinegrid]) {
Array args = data->call_buf; Array args = ui->call_buf;
ADD_C(args, INTEGER_OBJ(grid)); ADD_C(args, INTEGER_OBJ(grid));
ADD_C(args, INTEGER_OBJ(top)); ADD_C(args, INTEGER_OBJ(top));
ADD_C(args, INTEGER_OBJ(bot)); ADD_C(args, INTEGER_OBJ(bot));
@@ -625,20 +618,20 @@ void remote_ui_grid_scroll(UI *ui, Integer grid, Integer top, Integer bot, Integ
ADD_C(args, INTEGER_OBJ(cols)); ADD_C(args, INTEGER_OBJ(cols));
push_call(ui, "grid_scroll", args); push_call(ui, "grid_scroll", args);
} else { } else {
Array args = data->call_buf; Array args = ui->call_buf;
ADD_C(args, INTEGER_OBJ(top)); ADD_C(args, INTEGER_OBJ(top));
ADD_C(args, INTEGER_OBJ(bot - 1)); ADD_C(args, INTEGER_OBJ(bot - 1));
ADD_C(args, INTEGER_OBJ(left)); ADD_C(args, INTEGER_OBJ(left));
ADD_C(args, INTEGER_OBJ(right - 1)); ADD_C(args, INTEGER_OBJ(right - 1));
push_call(ui, "set_scroll_region", args); push_call(ui, "set_scroll_region", args);
args = data->call_buf; args = ui->call_buf;
ADD_C(args, INTEGER_OBJ(rows)); ADD_C(args, INTEGER_OBJ(rows));
push_call(ui, "scroll", args); push_call(ui, "scroll", args);
// some clients have "clear" being affected by scroll region, // some clients have "clear" being affected by scroll region,
// so reset it. // so reset it.
args = data->call_buf; args = ui->call_buf;
ADD_C(args, INTEGER_OBJ(0)); ADD_C(args, INTEGER_OBJ(0));
ADD_C(args, INTEGER_OBJ(ui->height - 1)); ADD_C(args, INTEGER_OBJ(ui->height - 1));
ADD_C(args, INTEGER_OBJ(0)); ADD_C(args, INTEGER_OBJ(0));
@@ -647,14 +640,13 @@ void remote_ui_grid_scroll(UI *ui, Integer grid, Integer top, Integer bot, Integ
} }
} }
void remote_ui_default_colors_set(UI *ui, Integer rgb_fg, Integer rgb_bg, Integer rgb_sp, void remote_ui_default_colors_set(RemoteUI *ui, Integer rgb_fg, Integer rgb_bg, Integer rgb_sp,
Integer cterm_fg, Integer cterm_bg) Integer cterm_fg, Integer cterm_bg)
{ {
if (!ui->ui_ext[kUITermColors]) { if (!ui->ui_ext[kUITermColors]) {
HL_SET_DEFAULT_COLORS(rgb_fg, rgb_bg, rgb_sp); HL_SET_DEFAULT_COLORS(rgb_fg, rgb_bg, rgb_sp);
} }
UIData *data = ui->data; Array args = ui->call_buf;
Array args = data->call_buf;
ADD_C(args, INTEGER_OBJ(rgb_fg)); ADD_C(args, INTEGER_OBJ(rgb_fg));
ADD_C(args, INTEGER_OBJ(rgb_bg)); ADD_C(args, INTEGER_OBJ(rgb_bg));
ADD_C(args, INTEGER_OBJ(rgb_sp)); ADD_C(args, INTEGER_OBJ(rgb_sp));
@@ -664,29 +656,28 @@ void remote_ui_default_colors_set(UI *ui, Integer rgb_fg, Integer rgb_bg, Intege
// Deprecated // Deprecated
if (!ui->ui_ext[kUILinegrid]) { if (!ui->ui_ext[kUILinegrid]) {
args = data->call_buf; args = ui->call_buf;
ADD_C(args, INTEGER_OBJ(ui->rgb ? rgb_fg : cterm_fg - 1)); ADD_C(args, INTEGER_OBJ(ui->rgb ? rgb_fg : cterm_fg - 1));
push_call(ui, "update_fg", args); push_call(ui, "update_fg", args);
args = data->call_buf; args = ui->call_buf;
ADD_C(args, INTEGER_OBJ(ui->rgb ? rgb_bg : cterm_bg - 1)); ADD_C(args, INTEGER_OBJ(ui->rgb ? rgb_bg : cterm_bg - 1));
push_call(ui, "update_bg", args); push_call(ui, "update_bg", args);
args = data->call_buf; args = ui->call_buf;
ADD_C(args, INTEGER_OBJ(ui->rgb ? rgb_sp : -1)); ADD_C(args, INTEGER_OBJ(ui->rgb ? rgb_sp : -1));
push_call(ui, "update_sp", args); push_call(ui, "update_sp", args);
} }
} }
void remote_ui_hl_attr_define(UI *ui, Integer id, HlAttrs rgb_attrs, HlAttrs cterm_attrs, void remote_ui_hl_attr_define(RemoteUI *ui, Integer id, HlAttrs rgb_attrs, HlAttrs cterm_attrs,
Array info) Array info)
{ {
if (!ui->ui_ext[kUILinegrid]) { if (!ui->ui_ext[kUILinegrid]) {
return; return;
} }
UIData *data = ui->data; Array args = ui->call_buf;
Array args = data->call_buf;
ADD_C(args, INTEGER_OBJ(id)); ADD_C(args, INTEGER_OBJ(id));
MAXSIZE_TEMP_DICT(rgb, HLATTRS_DICT_SIZE); MAXSIZE_TEMP_DICT(rgb, HLATTRS_DICT_SIZE);
MAXSIZE_TEMP_DICT(cterm, HLATTRS_DICT_SIZE); MAXSIZE_TEMP_DICT(cterm, HLATTRS_DICT_SIZE);
@@ -712,15 +703,14 @@ void remote_ui_hl_attr_define(UI *ui, Integer id, HlAttrs rgb_attrs, HlAttrs cte
push_call(ui, "hl_attr_define", args); push_call(ui, "hl_attr_define", args);
} }
void remote_ui_highlight_set(UI *ui, int id) void remote_ui_highlight_set(RemoteUI *ui, int id)
{ {
UIData *data = ui->data; Array args = ui->call_buf;
Array args = data->call_buf;
if (data->hl_id == id) { if (ui->hl_id == id) {
return; return;
} }
data->hl_id = id; ui->hl_id = id;
MAXSIZE_TEMP_DICT(dict, HLATTRS_DICT_SIZE); MAXSIZE_TEMP_DICT(dict, HLATTRS_DICT_SIZE);
hlattrs2dict(&dict, NULL, syn_attr2entry(id), ui->rgb, false); hlattrs2dict(&dict, NULL, syn_attr2entry(id), ui->rgb, false);
ADD_C(args, DICTIONARY_OBJ(dict)); ADD_C(args, DICTIONARY_OBJ(dict));
@@ -728,48 +718,44 @@ void remote_ui_highlight_set(UI *ui, int id)
} }
/// "true" cursor used only for input focus /// "true" cursor used only for input focus
void remote_ui_grid_cursor_goto(UI *ui, Integer grid, Integer row, Integer col) void remote_ui_grid_cursor_goto(RemoteUI *ui, Integer grid, Integer row, Integer col)
{ {
if (ui->ui_ext[kUILinegrid]) { if (ui->ui_ext[kUILinegrid]) {
UIData *data = ui->data; Array args = ui->call_buf;
Array args = data->call_buf;
ADD_C(args, INTEGER_OBJ(grid)); ADD_C(args, INTEGER_OBJ(grid));
ADD_C(args, INTEGER_OBJ(row)); ADD_C(args, INTEGER_OBJ(row));
ADD_C(args, INTEGER_OBJ(col)); ADD_C(args, INTEGER_OBJ(col));
push_call(ui, "grid_cursor_goto", args); push_call(ui, "grid_cursor_goto", args);
} else { } else {
UIData *data = ui->data; ui->cursor_row = row;
data->cursor_row = row; ui->cursor_col = col;
data->cursor_col = col;
remote_ui_cursor_goto(ui, row, col); remote_ui_cursor_goto(ui, row, col);
} }
} }
/// emulated cursor used both for drawing and for input focus /// emulated cursor used both for drawing and for input focus
void remote_ui_cursor_goto(UI *ui, Integer row, Integer col) void remote_ui_cursor_goto(RemoteUI *ui, Integer row, Integer col)
{ {
UIData *data = ui->data; if (ui->client_row == row && ui->client_col == col) {
if (data->client_row == row && data->client_col == col) {
return; return;
} }
data->client_row = row; ui->client_row = row;
data->client_col = col; ui->client_col = col;
Array args = data->call_buf; Array args = ui->call_buf;
ADD_C(args, INTEGER_OBJ(row)); ADD_C(args, INTEGER_OBJ(row));
ADD_C(args, INTEGER_OBJ(col)); ADD_C(args, INTEGER_OBJ(col));
push_call(ui, "cursor_goto", args); push_call(ui, "cursor_goto", args);
} }
void remote_ui_put(UI *ui, const char *cell) void remote_ui_put(RemoteUI *ui, const char *cell)
{ {
UIData *data = ui->data; ui->client_col++;
data->client_col++; Array args = ui->call_buf;
Array args = data->call_buf;
ADD_C(args, CSTR_AS_OBJ(cell)); ADD_C(args, CSTR_AS_OBJ(cell));
push_call(ui, "put", args); push_call(ui, "put", args);
} }
void remote_ui_raw_line(UI *ui, Integer grid, Integer row, Integer startcol, Integer endcol, void remote_ui_raw_line(RemoteUI *ui, Integer grid, Integer row, Integer startcol, Integer endcol,
Integer clearcol, Integer clearattr, LineFlags flags, const schar_T *chunk, Integer clearcol, Integer clearattr, LineFlags flags, const schar_T *chunk,
const sattr_T *attrs) const sattr_T *attrs)
{ {
@@ -777,11 +763,10 @@ void remote_ui_raw_line(UI *ui, Integer grid, Integer row, Integer startcol, Int
// to not only use FIXSTR (only up to 0x20 bytes) // to not only use FIXSTR (only up to 0x20 bytes)
STATIC_ASSERT(MAX_SCHAR_SIZE - 1 < 0x20, "SCHAR doesn't fit in fixstr"); STATIC_ASSERT(MAX_SCHAR_SIZE - 1 < 0x20, "SCHAR doesn't fit in fixstr");
UIData *data = ui->data;
if (ui->ui_ext[kUILinegrid]) { if (ui->ui_ext[kUILinegrid]) {
prepare_call(ui, "grid_line"); prepare_call(ui, "grid_line");
char **buf = &data->packer.ptr; char **buf = &ui->packer.ptr;
mpack_array(buf, 5); mpack_array(buf, 5);
mpack_uint(buf, (uint32_t)grid); mpack_uint(buf, (uint32_t)grid);
mpack_uint(buf, (uint32_t)row); mpack_uint(buf, (uint32_t)row);
@@ -796,7 +781,7 @@ void remote_ui_raw_line(UI *ui, Integer grid, Integer row, Integer startcol, Int
for (size_t i = 0; i < ncells; i++) { for (size_t i = 0; i < ncells; i++) {
repeat++; repeat++;
if (i == ncells - 1 || attrs[i] != attrs[i + 1] || chunk[i] != chunk[i + 1]) { if (i == ncells - 1 || attrs[i] != attrs[i + 1] || chunk[i] != chunk[i + 1]) {
if (UI_BUF_SIZE - BUF_POS(data) < 2 * (1 + 2 + sizeof(schar_T) + 5 + 5) + 1) { if (UI_BUF_SIZE - BUF_POS(ui) < 2 * (1 + 2 + sizeof(schar_T) + 5 + 5) + 1) {
// close to overflowing the redraw buffer. finish this event, // close to overflowing the redraw buffer. finish this event,
// flush, and start a new "grid_line" event at the current position. // flush, and start a new "grid_line" event at the current position.
// For simplicity leave place for the final "clear" element // For simplicity leave place for the final "clear" element
@@ -805,7 +790,7 @@ void remote_ui_raw_line(UI *ui, Integer grid, Integer row, Integer startcol, Int
// We only ever set the wrap field on the final "grid_line" event for the line. // We only ever set the wrap field on the final "grid_line" event for the line.
mpack_bool(buf, false); mpack_bool(buf, false);
ui_flush_buf(data); ui_flush_buf(ui);
prepare_call(ui, "grid_line"); prepare_call(ui, "grid_line");
mpack_array(buf, 5); mpack_array(buf, 5);
@@ -828,7 +813,7 @@ void remote_ui_raw_line(UI *ui, Integer grid, Integer row, Integer startcol, Int
mpack_uint(buf, repeat); mpack_uint(buf, repeat);
} }
} }
data->ncells_pending += MIN(repeat, 2); ui->ncells_pending += MIN(repeat, 2);
last_hl = attrs[i]; last_hl = attrs[i];
repeat = 0; repeat = 0;
was_space = chunk[i] == schar_from_ascii(' '); was_space = chunk[i] == schar_from_ascii(' ');
@@ -838,7 +823,7 @@ void remote_ui_raw_line(UI *ui, Integer grid, Integer row, Integer startcol, Int
// no more cells to clear, so there is no ambiguity about what to clear. // no more cells to clear, so there is no ambiguity about what to clear.
if (endcol < clearcol || was_space) { if (endcol < clearcol || was_space) {
nelem++; nelem++;
data->ncells_pending += 1; ui->ncells_pending += 1;
mpack_array(buf, 3); mpack_array(buf, 3);
mpack_str_small(buf, S_LEN(" ")); mpack_str_small(buf, S_LEN(" "));
mpack_uint(buf, (uint32_t)clearattr); mpack_uint(buf, (uint32_t)clearattr);
@@ -847,9 +832,9 @@ void remote_ui_raw_line(UI *ui, Integer grid, Integer row, Integer startcol, Int
mpack_w2(&lenpos, nelem); mpack_w2(&lenpos, nelem);
mpack_bool(buf, flags & kLineFlagWrap); mpack_bool(buf, flags & kLineFlagWrap);
if (data->ncells_pending > 500) { if (ui->ncells_pending > 500) {
// pass off cells to UI to let it start processing them // pass off cells to UI to let it start processing them
ui_flush_buf(data); ui_flush_buf(ui);
} }
} else { } else {
for (int i = 0; i < endcol - startcol; i++) { for (int i = 0; i < endcol - startcol; i++) {
@@ -859,7 +844,7 @@ void remote_ui_raw_line(UI *ui, Integer grid, Integer row, Integer startcol, Int
schar_get(sc_buf, chunk[i]); schar_get(sc_buf, chunk[i]);
remote_ui_put(ui, sc_buf); remote_ui_put(ui, sc_buf);
if (utf_ambiguous_width(utf_ptr2char(sc_buf))) { if (utf_ambiguous_width(utf_ptr2char(sc_buf))) {
data->client_col = -1; // force cursor update ui->client_col = -1; // force cursor update
} }
} }
if (endcol < clearcol) { if (endcol < clearcol) {
@@ -883,48 +868,47 @@ void remote_ui_raw_line(UI *ui, Integer grid, Integer row, Integer startcol, Int
/// ///
/// This might happen multiple times before the actual ui_flush, if the /// This might happen multiple times before the actual ui_flush, if the
/// total redraw size is large! /// total redraw size is large!
static void ui_flush_buf(UIData *data) static void ui_flush_buf(RemoteUI *ui)
{ {
if (!data->packer.startptr || !BUF_POS(data)) { if (!ui->packer.startptr || !BUF_POS(ui)) {
return; return;
} }
flush_event(data); flush_event(ui);
if (data->nevents_pos != NULL) { if (ui->nevents_pos != NULL) {
mpack_w2(&data->nevents_pos, data->nevents); mpack_w2(&ui->nevents_pos, ui->nevents);
data->nevents = 0; ui->nevents = 0;
data->nevents_pos = NULL; ui->nevents_pos = NULL;
} }
WBuffer *buf = wstream_new_buffer(data->packer.startptr, BUF_POS(data), 1, free_block); WBuffer *buf = wstream_new_buffer(ui->packer.startptr, BUF_POS(ui), 1, free_block);
rpc_write_raw(data->channel_id, buf); rpc_write_raw(ui->channel_id, buf);
data->packer.startptr = NULL; ui->packer.startptr = NULL;
data->packer.ptr = NULL; ui->packer.ptr = NULL;
// we have sent events to the client, but possibly not yet the final "flush" event. // we have sent events to the client, but possibly not yet the final "flush" event.
data->flushed_events = true; ui->flushed_events = true;
data->ncells_pending = 0; ui->ncells_pending = 0;
} }
/// An intentional flush (vsync) when Nvim is finished redrawing the screen /// An intentional flush (vsync) when Nvim is finished redrawing the screen
/// ///
/// Clients can know this happened by a final "flush" event at the end of the /// Clients can know this happened by a final "flush" event at the end of the
/// "redraw" batch. /// "redraw" batch.
void remote_ui_flush(UI *ui) void remote_ui_flush(RemoteUI *ui)
{ {
UIData *data = ui->data; if (ui->nevents > 0 || ui->flushed_events) {
if (data->nevents > 0 || data->flushed_events) {
if (!ui->ui_ext[kUILinegrid]) { if (!ui->ui_ext[kUILinegrid]) {
remote_ui_cursor_goto(ui, data->cursor_row, data->cursor_col); remote_ui_cursor_goto(ui, ui->cursor_row, ui->cursor_col);
} }
push_call(ui, "flush", (Array)ARRAY_DICT_INIT); push_call(ui, "flush", (Array)ARRAY_DICT_INIT);
ui_flush_buf(data); ui_flush_buf(ui);
data->flushed_events = false; ui->flushed_events = false;
} }
} }
static Array translate_contents(UI *ui, Array contents, Arena *arena) static Array translate_contents(RemoteUI *ui, Array contents, Arena *arena)
{ {
Array new_contents = arena_array(arena, contents.size); Array new_contents = arena_array(arena, contents.size);
for (size_t i = 0; i < contents.size; i++) { for (size_t i = 0; i < contents.size; i++) {
@@ -944,7 +928,7 @@ static Array translate_contents(UI *ui, Array contents, Arena *arena)
return new_contents; return new_contents;
} }
static Array translate_firstarg(UI *ui, Array args, Arena *arena) static Array translate_firstarg(RemoteUI *ui, Array args, Arena *arena)
{ {
Array new_args = arena_array(arena, args.size); Array new_args = arena_array(arena, args.size);
Array contents = args.items[0].data.array; Array contents = args.items[0].data.array;
@@ -956,10 +940,9 @@ static Array translate_firstarg(UI *ui, Array args, Arena *arena)
return new_args; return new_args;
} }
void remote_ui_event(UI *ui, char *name, Array args) void remote_ui_event(RemoteUI *ui, char *name, Array args)
{ {
Arena arena = ARENA_EMPTY; Arena arena = ARENA_EMPTY;
UIData *data = ui->data;
if (!ui->ui_ext[kUILinegrid]) { if (!ui->ui_ext[kUILinegrid]) {
// the representation of highlights in cmdline changed, translate back // the representation of highlights in cmdline changed, translate back
// never consumes args // never consumes args
@@ -968,7 +951,7 @@ void remote_ui_event(UI *ui, char *name, Array args)
push_call(ui, name, new_args); push_call(ui, name, new_args);
goto free_ret; goto free_ret;
} else if (strequal(name, "cmdline_block_show")) { } else if (strequal(name, "cmdline_block_show")) {
Array new_args = data->call_buf; Array new_args = ui->call_buf;
Array block = args.items[0].data.array; Array block = args.items[0].data.array;
Array new_block = arena_array(&arena, block.size); Array new_block = arena_array(&arena, block.size);
for (size_t i = 0; i < block.size; i++) { for (size_t i = 0; i < block.size; i++) {
@@ -987,10 +970,10 @@ void remote_ui_event(UI *ui, char *name, Array args)
// Back-compat: translate popupmenu_xx to legacy wildmenu_xx. // Back-compat: translate popupmenu_xx to legacy wildmenu_xx.
if (ui->ui_ext[kUIWildmenu]) { if (ui->ui_ext[kUIWildmenu]) {
if (strequal(name, "popupmenu_show")) { if (strequal(name, "popupmenu_show")) {
data->wildmenu_active = (args.items[4].data.integer == -1) ui->wildmenu_active = (args.items[4].data.integer == -1)
|| !ui->ui_ext[kUIPopupmenu]; || !ui->ui_ext[kUIPopupmenu];
if (data->wildmenu_active) { if (ui->wildmenu_active) {
Array new_args = data->call_buf; Array new_args = ui->call_buf;
Array items = args.items[0].data.array; Array items = args.items[0].data.array;
Array new_items = arena_array(&arena, items.size); Array new_items = arena_array(&arena, items.size);
for (size_t i = 0; i < items.size; i++) { for (size_t i = 0; i < items.size; i++) {
@@ -999,18 +982,18 @@ void remote_ui_event(UI *ui, char *name, Array args)
ADD_C(new_args, ARRAY_OBJ(new_items)); ADD_C(new_args, ARRAY_OBJ(new_items));
push_call(ui, "wildmenu_show", new_args); push_call(ui, "wildmenu_show", new_args);
if (args.items[1].data.integer != -1) { if (args.items[1].data.integer != -1) {
Array new_args2 = data->call_buf; Array new_args2 = ui->call_buf;
ADD_C(new_args2, args.items[1]); ADD_C(new_args2, args.items[1]);
push_call(ui, "wildmenu_select", new_args2); push_call(ui, "wildmenu_select", new_args2);
} }
goto free_ret; goto free_ret;
} }
} else if (strequal(name, "popupmenu_select")) { } else if (strequal(name, "popupmenu_select")) {
if (data->wildmenu_active) { if (ui->wildmenu_active) {
name = "wildmenu_select"; name = "wildmenu_select";
} }
} else if (strequal(name, "popupmenu_hide")) { } else if (strequal(name, "popupmenu_hide")) {
if (data->wildmenu_active) { if (ui->wildmenu_active) {
name = "wildmenu_hide"; name = "wildmenu_hide";
} }
} }

View File

@@ -110,10 +110,9 @@ for i = 1, #events do
if not ev.remote_only then if not ev.remote_only then
if not ev.remote_impl and not ev.noexport then if not ev.remote_impl and not ev.noexport then
remote_output:write('void remote_ui_' .. ev.name) remote_output:write('void remote_ui_' .. ev.name)
write_signature(remote_output, ev, 'UI *ui') write_signature(remote_output, ev, 'RemoteUI *ui')
remote_output:write('\n{\n') remote_output:write('\n{\n')
remote_output:write(' UIData *data = ui->data;\n') remote_output:write(' Array args = ui->call_buf;\n')
remote_output:write(' Array args = data->call_buf;\n')
write_arglist(remote_output, ev) write_arglist(remote_output, ev)
remote_output:write(' push_call(ui, "' .. ev.name .. '", args);\n') remote_output:write(' push_call(ui, "' .. ev.name .. '", args);\n')
remote_output:write('}\n\n') remote_output:write('}\n\n')

View File

@@ -127,7 +127,7 @@ retry: {}
} }
/// When a UI connects, we need to send it the table of highlights used so far. /// When a UI connects, we need to send it the table of highlights used so far.
void ui_send_all_hls(UI *ui) void ui_send_all_hls(RemoteUI *ui)
{ {
for (size_t i = 1; i < set_size(&attr_entries); i++) { for (size_t i = 1; i < set_size(&attr_entries); i++) {
Arena arena = ARENA_EMPTY; Arena arena = ARENA_EMPTY;

View File

@@ -53,7 +53,7 @@ typedef struct {
#define MAX_UI_COUNT 16 #define MAX_UI_COUNT 16
static UI *uis[MAX_UI_COUNT]; static RemoteUI *uis[MAX_UI_COUNT];
static bool ui_ext[kUIExtCount] = { 0 }; static bool ui_ext[kUIExtCount] = { 0 };
static size_t ui_count = 0; static size_t ui_count = 0;
static int ui_mode_idx = SHAPE_IDX_N; static int ui_mode_idx = SHAPE_IDX_N;
@@ -108,7 +108,7 @@ static void ui_log(const char *funname)
do { \ do { \
bool any_call = false; \ bool any_call = false; \
for (size_t i = 0; i < ui_count; i++) { \ for (size_t i = 0; i < ui_count; i++) { \
UI *ui = uis[i]; \ RemoteUI *ui = uis[i]; \
if ((cond)) { \ if ((cond)) { \
remote_ui_##funname(__VA_ARGS__); \ remote_ui_##funname(__VA_ARGS__); \
any_call = true; \ any_call = true; \
@@ -212,7 +212,7 @@ void ui_refresh(void)
bool inclusive = ui_override(); bool inclusive = ui_override();
for (size_t i = 0; i < ui_count; i++) { for (size_t i = 0; i < ui_count; i++) {
UI *ui = uis[i]; RemoteUI *ui = uis[i];
width = MIN(ui->width, width); width = MIN(ui->width, width);
height = MIN(ui->height, height); height = MIN(ui->height, height);
for (UIExtension j = 0; (int)j < kUIExtCount; j++) { for (UIExtension j = 0; (int)j < kUIExtCount; j++) {
@@ -367,12 +367,11 @@ void vim_beep(unsigned val)
void do_autocmd_uienter_all(void) void do_autocmd_uienter_all(void)
{ {
for (size_t i = 0; i < ui_count; i++) { for (size_t i = 0; i < ui_count; i++) {
UIData *data = uis[i]->data; do_autocmd_uienter(uis[i]->channel_id, true);
do_autocmd_uienter(data->channel_id, true);
} }
} }
void ui_attach_impl(UI *ui, uint64_t chanid) void ui_attach_impl(RemoteUI *ui, uint64_t chanid)
{ {
if (ui_count == MAX_UI_COUNT) { if (ui_count == MAX_UI_COUNT) {
abort(); abort();
@@ -408,7 +407,7 @@ void ui_attach_impl(UI *ui, uint64_t chanid)
do_autocmd_uienter(chanid, true); do_autocmd_uienter(chanid, true);
} }
void ui_detach_impl(UI *ui, uint64_t chanid) void ui_detach_impl(RemoteUI *ui, uint64_t chanid)
{ {
size_t shift_index = MAX_UI_COUNT; size_t shift_index = MAX_UI_COUNT;
@@ -444,7 +443,7 @@ void ui_detach_impl(UI *ui, uint64_t chanid)
do_autocmd_uienter(chanid, false); do_autocmd_uienter(chanid, false);
} }
void ui_set_ext_option(UI *ui, UIExtension ext, bool active) void ui_set_ext_option(RemoteUI *ui, UIExtension ext, bool active)
{ {
if (ext < kUIGlobalCount) { if (ext < kUIGlobalCount) {
ui_refresh(); ui_refresh();
@@ -649,7 +648,7 @@ Array ui_array(Arena *arena)
{ {
Array all_uis = arena_array(arena, ui_count); Array all_uis = arena_array(arena, ui_count);
for (size_t i = 0; i < ui_count; i++) { for (size_t i = 0; i < ui_count; i++) {
UI *ui = uis[i]; RemoteUI *ui = uis[i];
Dictionary info = arena_dict(arena, 10 + kUIExtCount); Dictionary info = arena_dict(arena, 10 + kUIExtCount);
PUT_C(info, "width", INTEGER_OBJ(ui->width)); PUT_C(info, "width", INTEGER_OBJ(ui->width));
PUT_C(info, "height", INTEGER_OBJ(ui->height)); PUT_C(info, "height", INTEGER_OBJ(ui->height));
@@ -671,7 +670,7 @@ Array ui_array(Arena *arena)
PUT_C(info, (char *)ui_ext_names[j], BOOLEAN_OBJ(ui->ui_ext[j])); PUT_C(info, (char *)ui_ext_names[j], BOOLEAN_OBJ(ui->ui_ext[j]));
} }
} }
PUT_C(info, "chan", INTEGER_OBJ((Integer)ui->data->channel_id)); PUT_C(info, "chan", INTEGER_OBJ((Integer)ui->channel_id));
ADD_C(all_uis, DICTIONARY_OBJ(info)); ADD_C(all_uis, DICTIONARY_OBJ(info));
} }

View File

@@ -79,13 +79,13 @@ void ui_comp_syn_init(void)
dbghl_recompose = syn_check_group(S_LEN("RedrawDebugRecompose")); dbghl_recompose = syn_check_group(S_LEN("RedrawDebugRecompose"));
} }
void ui_comp_attach(UI *ui) void ui_comp_attach(RemoteUI *ui)
{ {
composed_uis++; composed_uis++;
ui->composed = true; ui->composed = true;
} }
void ui_comp_detach(UI *ui) void ui_comp_detach(RemoteUI *ui)
{ {
composed_uis--; composed_uis--;
if (composed_uis == 0) { if (composed_uis == 0) {

View File

@@ -30,9 +30,28 @@ enum {
typedef int LineFlags; typedef int LineFlags;
typedef struct ui_t UI;
typedef struct { typedef struct {
bool rgb;
bool override; ///< Force highest-requested UI capabilities.
bool composed;
bool ui_ext[kUIExtCount]; ///< Externalized UI capabilities.
int width;
int height;
int pum_nlines; /// actual nr. lines shown in PUM
bool pum_pos; /// UI reports back pum position?
double pum_row;
double pum_col;
double pum_height;
double pum_width;
// TUI fields.
char *term_name;
char *term_background; ///< Deprecated. No longer needed since background color detection happens
///< in Lua. To be removed in a future release.
int term_colors;
bool stdin_tty;
bool stdout_tty;
uint64_t channel_id; uint64_t channel_id;
#define UI_BUF_SIZE ARENA_BLOCK_SIZE ///< total buffer size for pending msgpack data. #define UI_BUF_SIZE ARENA_BLOCK_SIZE ///< total buffer size for pending msgpack data.
@@ -40,6 +59,7 @@ typedef struct {
/// and the header of grid_line will never fail) /// and the header of grid_line will never fail)
#define EVENT_BUF_SIZE 256 #define EVENT_BUF_SIZE 256
// Fields related to packing
PackerBuffer packer; PackerBuffer packer;
const char *cur_event; ///< name of current event (might get multiple arglists) const char *cur_event; ///< name of current event (might get multiple arglists)
@@ -62,33 +82,7 @@ typedef struct {
// Position of legacy cursor, used both for drawing and visible user cursor. // Position of legacy cursor, used both for drawing and visible user cursor.
Integer client_row, client_col; Integer client_row, client_col;
bool wildmenu_active; bool wildmenu_active;
} UIData; } RemoteUI;
struct ui_t {
bool rgb;
bool override; ///< Force highest-requested UI capabilities.
bool composed;
bool ui_ext[kUIExtCount]; ///< Externalized UI capabilities.
int width;
int height;
int pum_nlines; /// actual nr. lines shown in PUM
bool pum_pos; /// UI reports back pum position?
double pum_row;
double pum_col;
double pum_height;
double pum_width;
// TUI fields.
char *term_name;
char *term_background; ///< Deprecated. No longer needed since background color detection happens
///< in Lua. To be removed in a future release.
int term_colors;
bool stdin_tty;
bool stdout_tty;
// TODO(bfredl): integrate into struct!
UIData data[1];
};
typedef struct { typedef struct {
const char *name; const char *name;