diff options
Diffstat (limited to 'src/nvim/ui.c')
-rw-r--r-- | src/nvim/ui.c | 279 |
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. |