aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJustin M. Keyes <justinkz@gmail.com>2015-01-12 10:13:51 -0500
committerJustin M. Keyes <justinkz@gmail.com>2015-01-12 10:13:51 -0500
commit4c55c34efaabaa151391edf59c59a14411a79d8c (patch)
tree47e1caa73bf442035dc3a929c866c27df778dc2b /src
parentc53852a244fd78bcf11e37ddc94e8a847e80062a (diff)
parent62c1daffe028185030d0d8e95dc2c6532457b4fa (diff)
downloadrneovim-4c55c34efaabaa151391edf59c59a14411a79d8c.tar.gz
rneovim-4c55c34efaabaa151391edf59c59a14411a79d8c.tar.bz2
rneovim-4c55c34efaabaa151391edf59c59a14411a79d8c.zip
Merge pull request #1657 from tarruda/abstract-ui-fixes
[WIP] "abstract_ui" fixes and improvements
Diffstat (limited to 'src')
-rw-r--r--src/nvim/edit.c3
-rw-r--r--src/nvim/eval.c2
-rw-r--r--src/nvim/ex_docmd.c13
-rw-r--r--src/nvim/globals.h3
-rw-r--r--src/nvim/main.c4
-rw-r--r--src/nvim/msgpack_rpc/channel.c43
-rw-r--r--src/nvim/msgpack_rpc/remote_ui.c96
-rw-r--r--src/nvim/os/input.c10
-rw-r--r--src/nvim/os/shell.c12
-rw-r--r--src/nvim/screen.c13
-rw-r--r--src/nvim/syntax.c28
-rw-r--r--src/nvim/term.c16
-rw-r--r--src/nvim/ui.c120
-rw-r--r--src/nvim/ui.h6
14 files changed, 225 insertions, 144 deletions
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index e1a1fb18fa..89696410c9 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -2294,8 +2294,7 @@ static int pum_wanted(void)
return FALSE;
/* The display looks bad on a B&W display. */
- if (t_colors < 8
- )
+ if (!abstract_ui && t_colors < 8)
return FALSE;
return TRUE;
}
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index d60ce2de73..1dba3cd1e5 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -14440,7 +14440,7 @@ static void f_synIDattr(typval_T *argvars, typval_T *rettv)
if (modec != 't' && modec != 'c' && modec != 'g')
modec = 0; /* replace invalid with current */
} else {
- if (t_colors > 1)
+ if (abstract_ui || t_colors > 1)
modec = 'c';
else
modec = 't';
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 3661a65b11..b794ced428 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -71,6 +71,7 @@
#include "nvim/os/time.h"
#include "nvim/ex_cmds_defs.h"
#include "nvim/mouse.h"
+#include "nvim/msgpack_rpc/channel.h"
static int quitmore = 0;
static int ex_pressedreturn = FALSE;
@@ -5398,10 +5399,16 @@ static void ex_stop(exarg_T *eap)
/*
* Disallow suspending for "rvim".
*/
- if (!check_restricted()
- ) {
- if (!eap->forceit)
+ if (!check_restricted()) {
+ if (!eap->forceit) {
autowrite_all();
+ }
+
+ if (abstract_ui) {
+ channel_close(last_message_source);
+ return;
+ }
+
windgoto((int)Rows - 1, 0);
out_char('\n');
out_flush();
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 11a7e9ecac..854dd33552 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -1245,6 +1245,9 @@ EXTERN int curr_tmode INIT(= TMODE_COOK); /* contains current terminal mode */
EXTERN bool embedded_mode INIT(= false);
// Using the "abstract_ui" termcap
EXTERN bool abstract_ui INIT(= false);
+// Id of the last channel sent a message to nvim. Used to determine the target
+// of channel-specific actions such as suspending
+EXTERN uint64_t last_message_source INIT(= 0);
/// Used to track the status of external functions.
/// Currently only used for iconv().
diff --git a/src/nvim/main.c b/src/nvim/main.c
index 1f6c8ddc81..5e9fde67f5 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -281,9 +281,7 @@ int main(int argc, char **argv)
event_init();
- if (abstract_ui) {
- t_colors = 256;
- } else {
+ if (!abstract_ui) {
// Print a warning if stdout is not a terminal TODO(tarruda): Remove this
// check once the new terminal UI is implemented
check_tty(&params);
diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c
index 4c35cce09a..f2db65c605 100644
--- a/src/nvim/msgpack_rpc/channel.c
+++ b/src/nvim/msgpack_rpc/channel.c
@@ -45,6 +45,7 @@ typedef struct {
typedef struct {
uint64_t id;
+ size_t pending_requests;
PMap(cstr_t) *subscribed_events;
bool is_job, closed;
msgpack_unpacker *unpacker;
@@ -83,7 +84,6 @@ static uint64_t next_id = 1;
static PMap(uint64_t) *channels = NULL;
static PMap(cstr_t) *event_strings = NULL;
static msgpack_sbuffer out_buffer;
-static size_t pending_requests = 0;
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "msgpack_rpc/channel.c.generated.h"
@@ -103,14 +103,7 @@ void channel_init(void)
}
if (abstract_ui) {
- // Add handler for "attach_ui"
remote_ui_init();
- String method = cstr_as_string("attach_ui");
- MsgpackRpcRequestHandler handler = {.fn = remote_ui_attach, .defer = true};
- msgpack_rpc_add_method_handler(method, handler);
- method = cstr_as_string("detach_ui");
- handler.fn = remote_ui_detach;
- msgpack_rpc_add_method_handler(method, handler);
}
}
@@ -200,20 +193,21 @@ bool channel_send_event(uint64_t id, char *name, Array args)
return false;
}
- if (pending_requests) {
- DelayedNotification p = {
- .channel = channel,
- .method = cstr_to_string(name),
- .args = args
- };
- // Pending request, queue the notification for sending later
- *kl_pushp(DelayedNotification, delayed_notifications) = p;
- } else {
- if (channel) {
- send_event(channel, name, args);
+ if (channel) {
+ if (channel->pending_requests) {
+ DelayedNotification p = {
+ .channel = channel,
+ .method = cstr_to_string(name),
+ .args = args
+ };
+ // Pending request, queue the notification for sending later
+ *kl_pushp(DelayedNotification, delayed_notifications) = p;
} else {
- broadcast_event(name, args);
+ send_event(channel, name, args);
}
+ } else {
+ // TODO(tarruda): Implement event broadcasting in vimscript
+ broadcast_event(name, args);
}
return true;
@@ -246,10 +240,10 @@ Object channel_send_call(uint64_t id,
// Push the frame
ChannelCallFrame frame = {request_id, false, false, NIL};
kv_push(ChannelCallFrame *, channel->call_stack, &frame);
- pending_requests++;
+ channel->pending_requests++;
event_poll_until(-1, frame.returned);
(void)kv_pop(channel->call_stack);
- pending_requests--;
+ channel->pending_requests--;
if (frame.errored) {
api_set_error(err, Exception, "%s", frame.result.data.string.data);
@@ -261,7 +255,7 @@ Object channel_send_call(uint64_t id,
free_channel(channel);
}
- if (!pending_requests) {
+ if (!channel->pending_requests) {
send_delayed_notifications();
}
@@ -492,6 +486,7 @@ static void on_request_event(Event event)
{
RequestEvent *e = event.data;
Channel *channel = e->channel;
+ last_message_source = channel->id;
MsgpackRpcRequestHandler handler = e->handler;
Array args = e->args;
uint64_t request_id = e->request_id;
@@ -644,6 +639,7 @@ static void close_channel(Channel *channel)
uv_handle_t *handle = (uv_handle_t *)channel->data.streams.uv;
if (handle) {
uv_close(handle, close_cb);
+ free_channel(channel);
} else {
event_push((Event) { .handler = on_stdio_close }, false);
}
@@ -687,6 +683,7 @@ static Channel *register_channel(void)
rv->closed = false;
rv->unpacker = msgpack_unpacker_new(MSGPACK_UNPACKER_INIT_BUFFER_SIZE);
rv->id = next_id++;
+ rv->pending_requests = 0;
rv->subscribed_events = pmap_new(cstr_t)();
rv->next_request_id = 1;
kv_init(rv->call_stack);
diff --git a/src/nvim/msgpack_rpc/remote_ui.c b/src/nvim/msgpack_rpc/remote_ui.c
index f980a77b4c..4db9c71ebb 100644
--- a/src/nvim/msgpack_rpc/remote_ui.c
+++ b/src/nvim/msgpack_rpc/remote_ui.c
@@ -26,18 +26,44 @@ static PMap(uint64_t) *connected_uis = NULL;
void remote_ui_init(void)
{
connected_uis = pmap_new(uint64_t)();
+ // Add handler for "attach_ui"
+ String method = cstr_as_string("ui_attach");
+ MsgpackRpcRequestHandler handler = {.fn = remote_ui_attach, .defer = false};
+ msgpack_rpc_add_method_handler(method, handler);
+ method = cstr_as_string("ui_detach");
+ handler.fn = remote_ui_detach;
+ msgpack_rpc_add_method_handler(method, handler);
+ method = cstr_as_string("ui_try_resize");
+ handler.fn = remote_ui_try_resize;
+ msgpack_rpc_add_method_handler(method, handler);
}
-Object remote_ui_attach(uint64_t channel_id, uint64_t request_id, Array args,
- Error *error)
+void remote_ui_disconnect(uint64_t channel_id)
+{
+ UI *ui = pmap_get(uint64_t)(connected_uis, channel_id);
+ if (!ui) {
+ return;
+ }
+ UIData *data = ui->data;
+ // destroy pending screen updates
+ api_free_array(data->buffer);
+ pmap_del(uint64_t)(connected_uis, channel_id);
+ free(ui->data);
+ ui_detach(ui);
+ free(ui);
+}
+
+static Object remote_ui_attach(uint64_t channel_id, uint64_t request_id,
+ Array args, Error *error)
{
if (pmap_has(uint64_t)(connected_uis, channel_id)) {
api_set_error(error, Exception, _("UI already attached for channel"));
return NIL;
}
- if (args.size != 2 || args.items[0].type != kObjectTypeInteger
+ if (args.size != 3 || args.items[0].type != kObjectTypeInteger
|| args.items[1].type != kObjectTypeInteger
+ || args.items[2].type != kObjectTypeBoolean
|| args.items[0].data.integer <= 0 || args.items[1].data.integer <= 0) {
api_set_error(error, Validation,
_("Arguments must be a pair of positive integers "
@@ -50,6 +76,7 @@ Object remote_ui_attach(uint64_t channel_id, uint64_t request_id, Array args,
UI *ui = xcalloc(1, sizeof(UI));
ui->width = (int)args.items[0].data.integer;
ui->height = (int)args.items[1].data.integer;
+ ui->rgb = args.items[2].data.boolean;
ui->data = data;
ui->resize = remote_ui_resize;
ui->clear = remote_ui_clear;
@@ -67,16 +94,16 @@ Object remote_ui_attach(uint64_t channel_id, uint64_t request_id, Array args,
ui->put = remote_ui_put;
ui->bell = remote_ui_bell;
ui->visual_bell = remote_ui_visual_bell;
+ ui->update_fg = remote_ui_update_fg;
+ ui->update_bg = remote_ui_update_bg;
ui->flush = remote_ui_flush;
- ui->suspend = remote_ui_suspend;
pmap_put(uint64_t)(connected_uis, channel_id, ui);
ui_attach(ui);
-
return NIL;
}
-Object remote_ui_detach(uint64_t channel_id, uint64_t request_id, Array args,
- Error *error)
+static Object remote_ui_detach(uint64_t channel_id, uint64_t request_id,
+ Array args, Error *error)
{
if (!pmap_has(uint64_t)(connected_uis, channel_id)) {
api_set_error(error, Exception, _("UI is not attached for channel"));
@@ -86,21 +113,30 @@ Object remote_ui_detach(uint64_t channel_id, uint64_t request_id, Array args,
return NIL;
}
-void remote_ui_disconnect(uint64_t channel_id)
+static Object remote_ui_try_resize(uint64_t channel_id, uint64_t request_id,
+ Array args, Error *error)
{
- UI *ui = pmap_get(uint64_t)(connected_uis, channel_id);
- if (!ui) {
- return;
+ if (!pmap_has(uint64_t)(connected_uis, channel_id)) {
+ api_set_error(error, Exception, _("UI is not attached for channel"));
}
- UIData *data = ui->data;
- // destroy pending screen updates
- api_free_array(data->buffer);
- pmap_del(uint64_t)(connected_uis, channel_id);
- free(ui->data);
- ui_detach(ui);
- free(ui);
+
+ if (args.size != 2 || args.items[0].type != kObjectTypeInteger
+ || args.items[1].type != kObjectTypeInteger
+ || args.items[0].data.integer <= 0 || args.items[1].data.integer <= 0) {
+ api_set_error(error, Validation,
+ _("Arguments must be a pair of positive integers "
+ "representing the remote screen width/height"));
+ return NIL;
+ }
+
+ UI *ui = pmap_get(uint64_t)(connected_uis, channel_id);
+ ui->width = (int)args.items[0].data.integer;
+ ui->height = (int)args.items[1].data.integer;
+ ui_refresh();
+ return NIL;
}
+
static void push_call(UI *ui, char *name, Array args)
{
Array call = ARRAY_DICT_INIT;
@@ -214,10 +250,6 @@ static void remote_ui_highlight_set(UI *ui, HlAttrs attrs)
PUT(hl, "bold", BOOLEAN_OBJ(true));
}
- if (attrs.standout) {
- PUT(hl, "standout", BOOLEAN_OBJ(true));
- }
-
if (attrs.underline) {
PUT(hl, "underline", BOOLEAN_OBJ(true));
}
@@ -266,15 +298,23 @@ static void remote_ui_visual_bell(UI *ui)
push_call(ui, "visual_bell", args);
}
-static void remote_ui_flush(UI *ui)
+static void remote_ui_update_fg(UI *ui, int fg)
{
- UIData *data = ui->data;
- channel_send_event(data->channel_id, "redraw", data->buffer);
- data->buffer = (Array)ARRAY_DICT_INIT;
+ Array args = ARRAY_DICT_INIT;
+ ADD(args, INTEGER_OBJ(fg));
+ push_call(ui, "update_fg", args);
}
-static void remote_ui_suspend(UI *ui)
+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_flush(UI *ui)
{
UIData *data = ui->data;
- remote_ui_disconnect(data->channel_id);
+ channel_send_event(data->channel_id, "redraw", data->buffer);
+ data->buffer = (Array)ARRAY_DICT_INIT;
}
diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c
index c0d588f4ef..130e239a34 100644
--- a/src/nvim/os/input.c
+++ b/src/nvim/os/input.c
@@ -187,14 +187,20 @@ size_t input_enqueue(String keys)
unsigned int new_size = trans_special((uint8_t **)&ptr, buf, false);
if (!new_size) {
+ if (*ptr == '<') {
+ // Invalid key sequence, skip until the next '>' or until *end
+ do {
+ ptr++;
+ } while (ptr < end && *ptr != '>');
+ ptr++;
+ continue;
+ }
// copy the character unmodified
*buf = (uint8_t)*ptr++;
new_size = 1;
}
new_size = handle_mouse_event(&ptr, buf, new_size);
- // TODO(tarruda): Don't produce past unclosed '<' characters, except if
- // there's a lot of characters after the '<'
rbuffer_write(input_buffer, (char *)buf, new_size);
}
diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c
index d0f8442768..d481d6af56 100644
--- a/src/nvim/os/shell.c
+++ b/src/nvim/os/shell.c
@@ -24,7 +24,6 @@
#include "nvim/option_defs.h"
#include "nvim/charset.h"
#include "nvim/strings.h"
-#include "nvim/ui.h"
#define DYNAMIC_BUFFER_INIT {NULL, 0, 0}
@@ -414,6 +413,7 @@ static size_t write_output(char *output, size_t remaining, bool to_buffer,
char *start = output;
size_t off = 0;
+ int lastrow = (int)Rows - 1;
while (off < remaining) {
if (output[off] == NL) {
// Insert the line
@@ -421,10 +421,8 @@ static size_t write_output(char *output, size_t remaining, bool to_buffer,
if (to_buffer) {
ml_append(curwin->w_cursor.lnum++, (char_u *)output, 0, false);
} else {
- // pending data from the output buffer has been flushed to the screen,
- // safe to call ui_write directly
- ui_write((char_u *)output, (int)off);
- ui_write((char_u *)"\r\n", 2);
+ screen_del_lines(0, 0, 1, (int)Rows, true, NULL);
+ screen_puts_len((char_u *)output, (int)off, lastrow, 0, 0);
}
size_t skip = off + 1;
output += skip;
@@ -448,8 +446,8 @@ static size_t write_output(char *output, size_t remaining, bool to_buffer,
// remember that the NL was missing
curbuf->b_no_eol_lnum = curwin->w_cursor.lnum;
} else {
- ui_write((char_u *)output, (int)remaining);
- ui_write((char_u *)"\r\n", 2);
+ screen_del_lines(0, 0, 1, (int)Rows, true, NULL);
+ screen_puts_len((char_u *)output, (int)remaining, lastrow, 0, 0);
}
output += remaining;
} else if (to_buffer) {
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index 855c09619e..b593d5a687 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -4548,7 +4548,7 @@ static void screen_line(int row, int coloff, int endcol, int clear_width, int rl
int c;
c = fillchar_vsep(&hl);
- if (ScreenLines[off_to] != c
+ if (ScreenLines[off_to] != ((schar_T)c)
|| (enc_utf8 && (int)ScreenLinesUC[off_to]
!= (c >= 0x80 ? c : 0))
|| ScreenAttrs[off_to] != hl) {
@@ -6150,8 +6150,7 @@ void screen_fill(int start_row, int end_row, int start_col, int end_col, int c1,
return;
/* it's a "normal" terminal when not in a GUI or cterm */
- norm_term = (
- t_colors <= 1);
+ norm_term = (!abstract_ui && t_colors <= 1);
for (row = start_row; row < end_row; ++row) {
if (has_mbyte
) {
@@ -6675,7 +6674,7 @@ static void linecopy(int to, int from, win_T *wp)
*/
int can_clear(char_u *p)
{
- return *p != NUL && (t_colors <= 1
+ return *p != NUL && ((!abstract_ui && t_colors <= 1)
|| cterm_normal_bg_color == 0 || *T_UT != NUL);
}
@@ -7702,8 +7701,7 @@ static void draw_tabline(void)
int attr_fill = hl_attr(HLF_TPF);
char_u *p;
int room;
- int use_sep_chars = (t_colors < 8
- );
+ int use_sep_chars = !abstract_ui && t_colors < 8;
redraw_tabline = FALSE;
@@ -8188,6 +8186,9 @@ void screen_resize(int width, int height, int mustset)
check_shellsize();
if (abstract_ui) {
+ // Clear the output buffer to ensure UIs don't receive redraw command meant
+ // for invalid screen sizes.
+ out_buf_clear();
ui_resize(width, height);
} else {
mch_set_shellsize();
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index 4e2be0cd44..80dc99d6e7 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -45,6 +45,7 @@
#include "nvim/strings.h"
#include "nvim/syntax_defs.h"
#include "nvim/term.h"
+#include "nvim/ui.h"
#include "nvim/os/os.h"
#include "nvim/os/time.h"
@@ -5983,7 +5984,7 @@ init_highlight (
* With 8 colors brown is equal to yellow, need to use black for Search fg
* to avoid Statement highlighted text disappears.
* Clear the attributes, needed when changing the t_Co value. */
- if (t_colors > 8)
+ if (abstract_ui || t_colors > 8)
do_highlight(
(char_u *)(*p_bg == 'l'
? "Visual cterm=NONE ctermbg=LightGrey"
@@ -6036,6 +6037,7 @@ int load_colors(char_u *name)
apply_autocmds(EVENT_COLORSCHEME, name, curbuf->b_fname, FALSE, curbuf);
recursive = FALSE;
+ ui_refresh();
return retval;
}
@@ -6431,7 +6433,9 @@ do_highlight (
/* Use the _16 table to check if its a valid color name. */
color = color_numbers_16[i];
if (color >= 0) {
- if (t_colors == 8) {
+ if (abstract_ui) {
+ color = color_numbers_256[i];
+ } else if (t_colors == 8) {
/* t_Co is 8: use the 8 colors table */
#if defined(__QNXNTO__)
color = color_numbers_8_qansi[i];
@@ -6448,8 +6452,7 @@ do_highlight (
HL_TABLE()[idx].sg_cterm &= ~HL_BOLD;
}
color &= 7; /* truncate to 8 colors */
- } else if (t_colors == 16 || t_colors == 88
- || t_colors == 256) {
+ } else if (t_colors == 16 || t_colors == 88 || t_colors == 256) {
/*
* Guess: if the termcap entry ends in 'm', it is
* probably an xterm-like terminal. Use the changed
@@ -6496,7 +6499,7 @@ do_highlight (
if (color >= 0) {
if (termcap_active)
term_bg_color(color);
- if (t_colors < 16)
+ if (!abstract_ui && t_colors < 16)
i = (color == 0 || color == 4);
else
i = (color < 7 || color == 8);
@@ -6642,6 +6645,10 @@ do_highlight (
if (is_normal_group) {
HL_TABLE()[idx].sg_term_attr = 0;
HL_TABLE()[idx].sg_cterm_attr = 0;
+ if (abstract_ui) {
+ // If the normal group has changed, it is simpler to refresh every UI
+ ui_refresh();
+ }
} else
set_hl_attr(idx);
HL_TABLE()[idx].sg_scriptID = current_SID;
@@ -6870,7 +6877,7 @@ int hl_combine_attr(int char_attr, int prim_attr)
if (char_attr <= HL_ALL && prim_attr <= HL_ALL)
return char_attr | prim_attr;
- if (t_colors > 1) {
+ if (abstract_ui || t_colors > 1) {
if (char_attr > HL_ALL)
char_aep = syn_cterm_attr2entry(char_attr);
if (char_aep != NULL)
@@ -6934,7 +6941,7 @@ int syn_attr2attr(int attr)
{
attrentry_T *aep;
- if (t_colors > 1)
+ if (abstract_ui || t_colors > 1)
aep = syn_cterm_attr2entry(attr);
else
aep = syn_term_attr2entry(attr);
@@ -7204,9 +7211,10 @@ set_hl_attr (
* For the color term mode: If there are other than "normal"
* highlighting attributes, need to allocate an attr number.
*/
- if (sgp->sg_cterm_fg == 0 && sgp->sg_cterm_bg == 0)
+ if (sgp->sg_cterm_fg == 0 && sgp->sg_cterm_bg == 0
+ && sgp->sg_rgb_fg == -1 && sgp->sg_rgb_bg == -1) {
sgp->sg_cterm_attr = sgp->sg_cterm;
- else {
+ } else {
at_en.ae_attr = abstract_ui ? sgp->sg_gui : sgp->sg_cterm;
at_en.ae_u.cterm.fg_color = sgp->sg_cterm_fg;
at_en.ae_u.cterm.bg_color = sgp->sg_cterm_bg;
@@ -7361,7 +7369,7 @@ int syn_id2attr(int hl_id)
hl_id = syn_get_final_id(hl_id);
sgp = &HL_TABLE()[hl_id - 1]; /* index is ID minus one */
- if (t_colors > 1)
+ if (abstract_ui || t_colors > 1)
attr = sgp->sg_cterm_attr;
else
attr = sgp->sg_term_attr;
diff --git a/src/nvim/term.c b/src/nvim/term.c
index b7c30300b0..1169435a4f 100644
--- a/src/nvim/term.c
+++ b/src/nvim/term.c
@@ -170,6 +170,7 @@ static struct builtin_term builtin_termcaps[] =
{(int)KS_DL, "\033|d"},
{(int)KS_CDL, "\033|%p1%dD"},
{(int)KS_CS, "\033|%p1%d;%p2%dR"},
+ {(int)KS_CSV, "\033|%p1%d;%p2%dV"},
{(int)KS_CL, "\033|C"},
// attributes switched on with 'h', off with * 'H'
{(int)KS_ME, "\033|31H"}, // HL_ALL
@@ -1817,17 +1818,20 @@ void term_write(char_u *s, size_t len)
static char_u out_buf[OUT_SIZE + 1];
static int out_pos = 0; /* number of chars in out_buf */
+// Clear the output buffer
+void out_buf_clear(void)
+{
+ out_pos = 0;
+}
+
/*
* out_flush(): flush the output buffer
*/
void out_flush(void)
{
- if (out_pos != 0) {
- /* set out_pos to 0 before ui_write, to avoid recursiveness */
- int len = out_pos;
- out_pos = 0;
- ui_write(out_buf, len);
- }
+ int len = out_pos;
+ out_pos = 0;
+ ui_write(out_buf, len);
}
/*
diff --git a/src/nvim/ui.c b/src/nvim/ui.c
index 25d6a81960..71960e8a63 100644
--- a/src/nvim/ui.c
+++ b/src/nvim/ui.c
@@ -60,11 +60,8 @@ static struct {
int top, bot, left, right;
} sr;
static int current_highlight_mask = 0;
-static HlAttrs current_attrs = {
- false, false, false, false, false, false, -1, -1
-};
static bool cursor_enabled = true;
-static int height = INT_MAX, width = INT_MAX;
+static int height, width;
// This set of macros allow us to use UI_CALL to invoke any function on
// registered UI instances. The functions can have 0-5 arguments(configurable
@@ -98,6 +95,10 @@ void ui_write(uint8_t *s, int len)
return;
}
+ if (!len) {
+ return;
+ }
+
char_u *tofree = NULL;
if (output_conv.vc_type != CONV_NONE) {
@@ -120,9 +121,7 @@ void ui_write(uint8_t *s, int len)
*/
void ui_suspend(void)
{
- if (abstract_ui) {
- UI_CALL(suspend);
- } else {
+ if (!abstract_ui) {
mch_suspend();
}
}
@@ -165,8 +164,31 @@ void ui_cursor_shape(void)
}
}
-void ui_resize(int width, int height)
+void ui_refresh(void)
+{
+ if (!ui_count) {
+ return;
+ }
+
+ int width = INT_MAX, height = INT_MAX;
+
+ for (size_t i = 0; i < ui_count; i++) {
+ UI *ui = uis[i];
+ width = ui->width < width ? ui->width : width;
+ height = ui->height < height ? ui->height : height;
+ }
+
+ screen_resize(width, height, true);
+}
+
+void ui_resize(int new_width, int new_height)
{
+ width = new_width;
+ height = new_height;
+
+ UI_CALL(update_fg, (ui->rgb ? normal_fg : cterm_normal_fg_color - 1));
+ UI_CALL(update_bg, (ui->rgb ? normal_bg : cterm_normal_bg_color - 1));
+
sr.top = 0;
sr.bot = height - 1;
sr.left = 0;
@@ -240,7 +262,7 @@ void ui_attach(UI *ui)
}
uis[ui_count++] = ui;
- resized(ui);
+ ui_refresh();
}
void ui_detach(UI *ui)
@@ -267,17 +289,8 @@ void ui_detach(UI *ui)
ui_count--;
- if (ui->width == width || ui->height == height) {
- // It is possible that the UI being detached had the smallest screen,
- // so check for the new minimum dimensions
- width = height = INT_MAX;
- for (size_t i = 0; i < ui_count; i++) {
- check_dimensions(uis[i]);
- }
- }
-
if (ui_count) {
- screen_resize(width, height, true);
+ ui_refresh();
}
}
@@ -295,8 +308,7 @@ static void highlight_start(int mask)
return;
}
- set_highlight_args(current_highlight_mask, &current_attrs);
- UI_CALL(highlight_set, current_attrs);
+ set_highlight_args(current_highlight_mask);
}
static void highlight_stop(int mask)
@@ -309,12 +321,12 @@ static void highlight_stop(int mask)
current_highlight_mask &= ~mask;
}
- set_highlight_args(current_highlight_mask, &current_attrs);
- UI_CALL(highlight_set, current_attrs);
+ set_highlight_args(current_highlight_mask);
}
-static void set_highlight_args(int mask, HlAttrs *attrs)
+static void set_highlight_args(int mask)
{
+ HlAttrs rgb_attrs = { false, false, false, false, false, -1, -1 };
attrentry_T *aep = NULL;
if (mask > HL_ALL) {
@@ -322,18 +334,40 @@ static void set_highlight_args(int mask, HlAttrs *attrs)
mask = aep ? aep->ae_attr : 0;
}
- attrs->bold = mask & HL_BOLD;
- attrs->standout = mask & HL_STANDOUT;
- attrs->underline = mask & HL_UNDERLINE;
- attrs->undercurl = mask & HL_UNDERCURL;
- attrs->italic = mask & HL_ITALIC;
- attrs->reverse = mask & HL_INVERSE;
- attrs->foreground = aep && aep->fg_color >= 0 ? aep->fg_color : normal_fg;
- attrs->background = aep && aep->bg_color >= 0 ? aep->bg_color : normal_bg;
+ rgb_attrs.bold = mask & HL_BOLD;
+ rgb_attrs.underline = mask & HL_UNDERLINE;
+ rgb_attrs.undercurl = mask & HL_UNDERCURL;
+ rgb_attrs.italic = mask & HL_ITALIC;
+ rgb_attrs.reverse = mask & (HL_INVERSE | HL_STANDOUT);
+ HlAttrs cterm_attrs = rgb_attrs;
+
+ if (aep) {
+ if (aep->fg_color != normal_fg) {
+ rgb_attrs.foreground = aep->fg_color;
+ }
+
+ if (aep->bg_color != normal_bg) {
+ rgb_attrs.background = aep->bg_color;
+ }
+
+ if (cterm_normal_fg_color != aep->ae_u.cterm.fg_color) {
+ cterm_attrs.foreground = aep->ae_u.cterm.fg_color - 1;
+ }
+
+ if (cterm_normal_bg_color != aep->ae_u.cterm.bg_color) {
+ cterm_attrs.background = aep->ae_u.cterm.bg_color - 1;
+ }
+ }
+
+ UI_CALL(highlight_set, (ui->rgb ? rgb_attrs : cterm_attrs));
}
static void parse_abstract_ui_codes(uint8_t *ptr, int len)
{
+ if (!ui_count) {
+ return;
+ }
+
int arg1 = 0, arg2 = 0;
uint8_t *end = ptr + len, *p, c;
bool update_cursor = false;
@@ -444,6 +478,9 @@ static void parse_abstract_ui_codes(uint8_t *ptr, int len)
UI_CALL(put, NULL, 0);
col++;
}
+ if (col >= width) {
+ ui_linefeed();
+ }
p += clen;
}
ptr = p;
@@ -457,25 +494,6 @@ static void parse_abstract_ui_codes(uint8_t *ptr, int len)
UI_CALL(flush);
}
-static void resized(UI *ui)
-{
- check_dimensions(ui);
- screen_resize(width, height, true);
-}
-
-static void check_dimensions(UI *ui)
-{
- // The internal screen dimensions are always the minimum required to fit on
- // all connected screens
- if (ui->width < width) {
- width = ui->width;
- }
-
- if (ui->height < height) {
- height = ui->height;
- }
-}
-
static void ui_linefeed(void)
{
int new_col = 0;
diff --git a/src/nvim/ui.h b/src/nvim/ui.h
index d0933055cc..3d3e2f4ffc 100644
--- a/src/nvim/ui.h
+++ b/src/nvim/ui.h
@@ -6,13 +6,14 @@
#include <stdint.h>
typedef struct {
- bool bold, standout, underline, undercurl, italic, reverse;
+ bool bold, underline, undercurl, italic, reverse;
int foreground, background;
} HlAttrs;
typedef struct ui_t UI;
struct ui_t {
+ bool rgb;
int width, height;
void *data;
void (*resize)(UI *ui, int rows, int columns);
@@ -32,7 +33,8 @@ struct ui_t {
void (*bell)(UI *ui);
void (*visual_bell)(UI *ui);
void (*flush)(UI *ui);
- void (*suspend)(UI *ui);
+ void (*update_fg)(UI *ui, int fg);
+ void (*update_bg)(UI *ui, int bg);
};
#ifdef INCLUDE_GENERATED_DECLARATIONS