aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/ui.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/ui.c')
-rw-r--r--src/nvim/ui.c279
1 files changed, 75 insertions, 204 deletions
diff --git a/src/nvim/ui.c b/src/nvim/ui.c
index 3b632ace41..0c69e94e5d 100644
--- a/src/nvim/ui.c
+++ b/src/nvim/ui.c
@@ -32,7 +32,7 @@
#include "nvim/os/signal.h"
#include "nvim/popupmnu.h"
#include "nvim/screen.h"
-#include "nvim/syntax.h"
+#include "nvim/highlight.h"
#include "nvim/window.h"
#include "nvim/cursor_shape.h"
#ifdef FEAT_TUI
@@ -52,14 +52,11 @@ static UI *uis[MAX_UI_COUNT];
static bool ui_ext[kUIExtCount] = { 0 };
static size_t ui_count = 0;
static int row = 0, col = 0;
-static struct {
- int top, bot, left, right;
-} sr;
-static int current_attr_code = -1;
static bool pending_cursor_update = false;
static int busy = 0;
-static int height, width;
-static int old_mode_idx = -1;
+static int mode_idx = SHAPE_IDX_N;
+static bool pending_mode_info_update = false;
+static bool pending_mode_update = false;
#if MIN_LOG_LEVEL > DEBUG_LOG_LEVEL
# define UI_LOG(funname, ...)
@@ -72,10 +69,10 @@ static char uilog_last_event[1024] = { 0 };
uilog_seen++; \
} else { \
if (uilog_seen > 0) { \
- do_log(DEBUG_LOG_LEVEL, "UI: ", NULL, -1, true, \
+ logmsg(DEBUG_LOG_LEVEL, "UI: ", NULL, -1, true, \
"%s (+%zu times...)", uilog_last_event, uilog_seen); \
} \
- do_log(DEBUG_LOG_LEVEL, "UI: ", NULL, -1, true, STR(funname)); \
+ logmsg(DEBUG_LOG_LEVEL, "UI: ", NULL, -1, true, STR(funname)); \
uilog_seen = 0; \
xstrlcpy(uilog_last_event, STR(funname), sizeof(uilog_last_event)); \
} \
@@ -83,13 +80,12 @@ static char uilog_last_event[1024] = { 0 };
#endif
// UI_CALL invokes a function on all registered UI instances. The functions can
-// have 0-5 arguments (configurable by SELECT_NTH).
+// have 0-10 arguments (configurable by SELECT_NTH).
//
// See http://stackoverflow.com/a/11172679 for how it works.
#ifdef _MSC_VER
# define UI_CALL(funname, ...) \
do { \
- flush_cursor_update(); \
UI_LOG(funname, 0); \
for (size_t i = 0; i < ui_count; i++) { \
UI *ui = uis[i]; \
@@ -99,7 +95,6 @@ static char uilog_last_event[1024] = { 0 };
#else
# define UI_CALL(...) \
do { \
- flush_cursor_update(); \
UI_LOG(__VA_ARGS__, 0); \
for (size_t i = 0; i < ui_count; i++) { \
UI *ui = uis[i]; \
@@ -107,9 +102,9 @@ static char uilog_last_event[1024] = { 0 };
} \
} while (0)
#endif
-#define CNT(...) SELECT_NTH(__VA_ARGS__, MORE, MORE, MORE, \
- MORE, MORE, ZERO, ignore)
-#define SELECT_NTH(a1, a2, a3, a4, a5, a6, a7, ...) a7
+#define CNT(...) SELECT_NTH(__VA_ARGS__, MORE, MORE, MORE, MORE, MORE, \
+ MORE, MORE, MORE, MORE, ZERO, ignore)
+#define SELECT_NTH(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, ...) a11
#define UI_CALL_HELPER(c, ...) UI_CALL_HELPER2(c, __VA_ARGS__)
// Resolves to UI_CALL_MORE or UI_CALL_ZERO.
#define UI_CALL_HELPER2(c, ...) UI_CALL_##c(__VA_ARGS__)
@@ -172,66 +167,6 @@ void ui_event(char *name, Array args)
}
-/// Converts an HlAttrs into Dictionary
-///
-/// @param[in] aep data to convert
-/// @param use_rgb use 'gui*' settings if true, else resorts to 'cterm*'
-Dictionary hlattrs2dict(const HlAttrs *aep, bool use_rgb)
-{
- assert(aep);
- Dictionary hl = ARRAY_DICT_INIT;
- int mask = use_rgb ? aep->rgb_ae_attr : aep->cterm_ae_attr;
-
- if (mask & HL_BOLD) {
- PUT(hl, "bold", BOOLEAN_OBJ(true));
- }
-
- if (mask & HL_STANDOUT) {
- PUT(hl, "standout", BOOLEAN_OBJ(true));
- }
-
- if (mask & HL_UNDERLINE) {
- PUT(hl, "underline", BOOLEAN_OBJ(true));
- }
-
- if (mask & HL_UNDERCURL) {
- PUT(hl, "undercurl", BOOLEAN_OBJ(true));
- }
-
- if (mask & HL_ITALIC) {
- PUT(hl, "italic", BOOLEAN_OBJ(true));
- }
-
- if (mask & HL_INVERSE) {
- PUT(hl, "reverse", BOOLEAN_OBJ(true));
- }
-
-
- if (use_rgb) {
- if (aep->rgb_fg_color != -1) {
- PUT(hl, "foreground", INTEGER_OBJ(aep->rgb_fg_color));
- }
-
- if (aep->rgb_bg_color != -1) {
- PUT(hl, "background", INTEGER_OBJ(aep->rgb_bg_color));
- }
-
- if (aep->rgb_sp_color != -1) {
- PUT(hl, "special", INTEGER_OBJ(aep->rgb_sp_color));
- }
- } else {
- if (cterm_normal_fg_color != aep->cterm_fg_color) {
- PUT(hl, "foreground", INTEGER_OBJ(aep->cterm_fg_color - 1));
- }
-
- if (cterm_normal_bg_color != aep->cterm_bg_color) {
- PUT(hl, "background", INTEGER_OBJ(aep->cterm_bg_color - 1));
- }
- }
-
- return hl;
-}
-
void ui_refresh(void)
{
if (!ui_active()) {
@@ -259,6 +194,9 @@ void ui_refresh(void)
}
row = col = 0;
+ pending_cursor_update = true;
+
+ ui_default_colors_set();
int save_p_lz = p_lz;
p_lz = false; // convince redrawing() to return true ...
@@ -267,13 +205,14 @@ void ui_refresh(void)
for (UIExtension i = 0; (int)i < kUIExtCount; i++) {
ui_ext[i] = ext_widgets[i];
- ui_call_option_set(cstr_as_string((char *)ui_ext_names[i]),
- BOOLEAN_OBJ(ext_widgets[i]));
+ if (i < kUIGlobalCount) {
+ ui_call_option_set(cstr_as_string((char *)ui_ext_names[i]),
+ BOOLEAN_OBJ(ext_widgets[i]));
+ }
}
ui_mode_info_set();
- old_mode_idx = -1;
+ pending_mode_update = true;
ui_cursor_shape();
- current_attr_code = -1;
}
static void ui_refresh_event(void **argv)
@@ -286,25 +225,15 @@ void ui_schedule_refresh(void)
loop_schedule(&main_loop, event_create(ui_refresh_event, 0));
}
-void ui_resize(int new_width, int new_height)
+void ui_resize(int width, int height)
{
- width = new_width;
- height = new_height;
+ ui_call_grid_resize(1, width, height);
+}
- // TODO(bfredl): update default colors when they changed, NOT on resize.
+void ui_default_colors_set(void)
+{
ui_call_default_colors_set(normal_fg, normal_bg, normal_sp,
cterm_normal_fg_color, cterm_normal_bg_color);
-
- // Deprecated:
- 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));
- UI_CALL(update_sp, (ui->rgb ? normal_sp : -1));
-
- sr.top = 0;
- sr.bot = height - 1;
- sr.left = 0;
- sr.right = width - 1;
- ui_call_resize(width, height);
}
void ui_busy_start(void)
@@ -329,6 +258,18 @@ void ui_attach_impl(UI *ui)
uis[ui_count++] = ui;
ui_refresh_options();
+
+ for (UIExtension i = kUIGlobalCount; (int)i < kUIExtCount; i++) {
+ ui_set_ext_option(ui, i, ui->ui_ext[i]);
+ }
+
+ bool sent = false;
+ if (ui->ui_ext[kUIHlState]) {
+ sent = highlight_use_hlstate();
+ }
+ if (!sent) {
+ ui_send_all_hls(ui);
+ }
ui_refresh();
}
@@ -362,97 +303,35 @@ void ui_detach_impl(UI *ui)
}
}
-// Set scrolling region for window 'wp'.
-// The region starts 'off' lines from the start of the window.
-// Also set the vertical scroll region for a vertically split window. Always
-// the full width of the window, excluding the vertical separator.
-void ui_set_scroll_region(win_T *wp, int off)
+void ui_set_ext_option(UI *ui, UIExtension ext, bool active)
{
- sr.top = wp->w_winrow + off;
- sr.bot = wp->w_winrow + wp->w_height - 1;
-
- if (wp->w_width != Columns) {
- sr.left = wp->w_wincol;
- sr.right = wp->w_wincol + wp->w_width - 1;
- }
-
- ui_call_set_scroll_region(sr.top, sr.bot, sr.left, sr.right);
-}
-
-// Reset scrolling region to the whole screen.
-void ui_reset_scroll_region(void)
-{
- sr.top = 0;
- sr.bot = (int)Rows - 1;
- sr.left = 0;
- sr.right = (int)Columns - 1;
- ui_call_set_scroll_region(sr.top, sr.bot, sr.left, sr.right);
-}
-
-void ui_set_highlight(int attr_code)
-{
- if (current_attr_code == attr_code) {
+ if (ext < kUIGlobalCount) {
+ ui_refresh();
return;
}
- current_attr_code = attr_code;
-
- HlAttrs attrs = HLATTRS_INIT;
-
- if (attr_code != 0) {
- HlAttrs *aep = syn_cterm_attr2entry(attr_code);
- if (aep) {
- attrs = *aep;
- }
+ if (ui->option_set) {
+ ui->option_set(ui, cstr_as_string((char *)ui_ext_names[ext]),
+ BOOLEAN_OBJ(active));
}
-
- UI_CALL(highlight_set, attrs);
}
-void ui_clear_highlight(void)
+void ui_line(int row, int startcol, int endcol, int clearcol, int clearattr,
+ bool wrap)
{
- ui_set_highlight(0);
-}
-
-void ui_puts(uint8_t *str)
-{
- uint8_t *p = str;
- uint8_t c;
-
- while ((c = *p)) {
- if (c < 0x20) {
- abort();
- }
-
- size_t clen = (size_t)mb_ptr2len(p);
- 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((String)STRING_INIT);
- col++;
- }
- if (utf_ambiguous_width(utf_ptr2char(p))) {
- pending_cursor_update = true;
- }
- if (col >= width) {
- ui_linefeed();
- }
- p += clen;
-
- if (p_wd) { // 'writedelay': flush & delay each time.
- ui_flush();
- uint64_t wd = (uint64_t)labs(p_wd);
- os_microdelay(wd * 1000u, true);
- }
+ size_t off = LineOffset[row]+(size_t)startcol;
+ UI_CALL(raw_line, 1, row, startcol, endcol, clearcol, clearattr, wrap,
+ (const schar_T *)ScreenLines+off, (const sattr_T *)ScreenAttrs+off);
+ if (p_wd) { // 'writedelay': flush & delay each time.
+ int old_row = row, old_col = col;
+ // If'writedelay is active, we set the cursor to highlight what was drawn
+ ui_cursor_goto(row, MIN(clearcol, (int)Columns-1));
+ ui_flush();
+ uint64_t wd = (uint64_t)labs(p_wd);
+ os_microdelay(wd * 1000u, true);
+ ui_cursor_goto(old_row, old_col);
}
}
-void ui_putc(uint8_t c)
-{
- uint8_t buf[2] = {c, 0};
- ui_puts(buf);
-}
-
void ui_cursor_goto(int new_row, int new_col)
{
if (new_row == row && new_col == col) {
@@ -465,10 +344,7 @@ void ui_cursor_goto(int new_row, int new_col)
void ui_mode_info_set(void)
{
- Array style = mode_style_array();
- bool enabled = (*p_guicursor != NUL);
- ui_call_mode_info_set(enabled, style);
- api_free_array(style);
+ pending_mode_info_update = true;
}
int ui_current_row(void)
@@ -484,30 +360,26 @@ int ui_current_col(void)
void ui_flush(void)
{
cmdline_ui_flush();
- ui_call_flush();
-}
-
-
-void ui_linefeed(void)
-{
- int new_col = 0;
- int new_row = row;
- if (new_row < sr.bot) {
- new_row++;
- } else {
- ui_call_scroll(1);
- }
- ui_cursor_goto(new_row, new_col);
-}
-
-static void flush_cursor_update(void)
-{
if (pending_cursor_update) {
+ ui_call_grid_cursor_goto(1, row, col);
pending_cursor_update = false;
- ui_call_cursor_goto(row, col);
}
+ if (pending_mode_info_update) {
+ Array style = mode_style_array();
+ bool enabled = (*p_guicursor != NUL);
+ ui_call_mode_info_set(enabled, style);
+ api_free_array(style);
+ pending_mode_info_update = false;
+ }
+ if (pending_mode_update) {
+ char *full_name = shape_table[mode_idx].full_name;
+ ui_call_mode_change(cstr_as_string(full_name), mode_idx);
+ pending_mode_update = false;
+ }
+ ui_call_flush();
}
+
/// Check if current mode has changed.
/// May update the shape of the cursor.
void ui_cursor_shape(void)
@@ -515,14 +387,13 @@ void ui_cursor_shape(void)
if (!full_screen) {
return;
}
- int mode_idx = cursor_get_mode_idx();
+ int new_mode_idx = cursor_get_mode_idx();
- if (old_mode_idx != mode_idx) {
- old_mode_idx = mode_idx;
- char *full_name = shape_table[mode_idx].full_name;
- ui_call_mode_change(cstr_as_string(full_name), mode_idx);
+ if (new_mode_idx != mode_idx) {
+ mode_idx = new_mode_idx;
+ pending_mode_update = true;
}
- conceal_check_cursur_line();
+ conceal_check_cursor_line();
}
/// Returns true if `widget` is externalized.