diff options
| -rw-r--r-- | event-basic.c | 2 | ||||
| -rw-r--r-- | main.c | 6 | ||||
| -rw-r--r-- | ui-terminal-curses.c | 42 | ||||
| -rw-r--r-- | ui-terminal-vt100.c | 46 | ||||
| -rw-r--r-- | ui-terminal.c | 170 | ||||
| -rw-r--r-- | ui-terminal.h | 9 | ||||
| -rw-r--r-- | ui.h | 107 | ||||
| -rw-r--r-- | view.h | 12 | ||||
| -rw-r--r-- | vis-cmds.c | 18 | ||||
| -rw-r--r-- | vis-lua.c | 12 | ||||
| -rw-r--r-- | vis-prompt.c | 6 | ||||
| -rw-r--r-- | vis.c | 66 | ||||
| -rw-r--r-- | vis.h | 25 |
13 files changed, 188 insertions, 333 deletions
diff --git a/event-basic.c b/event-basic.c index 6d298b5..cb2d2c1 100644 --- a/event-basic.c +++ b/event-basic.c @@ -6,7 +6,7 @@ bool vis_event_emit(Vis *vis, enum VisEvents id, ...) { if (!vis->initialized) { vis->initialized = true; - vis->ui->init(vis->ui, vis); + ui_init(vis->ui, vis); } va_list ap; @@ -10,7 +10,7 @@ #include <sys/stat.h> #include <sys/types.h> -#include "ui-terminal.h" +#include "ui.h" #include "vis.h" #include "vis-lua.h" #include "text-util.h" @@ -1229,7 +1229,7 @@ static const char *macro_replay(Vis *vis, const char *keys, const Arg *arg) { } static const char *suspend(Vis *vis, const char *keys, const Arg *arg) { - vis_suspend(vis); + ui_terminal_suspend(vis->ui); return keys; } @@ -2214,7 +2214,7 @@ static void signal_handler(int signum, siginfo_t *siginfo, void *context) { } int main(int argc, char *argv[]) { - vis = vis_new(ui_term_new()); + vis = vis_new(ui_terminal_new()); if (!vis) return EXIT_FAILURE; diff --git a/ui-terminal-curses.c b/ui-terminal-curses.c index b89d9b5..2b4a6fd 100644 --- a/ui-terminal-curses.c +++ b/ui-terminal-curses.c @@ -4,18 +4,6 @@ #define UI_TERMKEY_FLAGS (TERMKEY_FLAG_UTF8|TERMKEY_FLAG_NOTERMIOS) -#define ui_term_backend_init ui_curses_init -#define ui_term_backend_blit ui_curses_blit -#define ui_term_backend_clear ui_curses_clear -#define ui_term_backend_colors ui_curses_colors -#define ui_term_backend_resize ui_curses_resize -#define ui_term_backend_restore ui_curses_restore -#define ui_term_backend_save ui_curses_save -#define ui_term_backend_new ui_curses_new -#define ui_term_backend_resume ui_curses_resume -#define ui_term_backend_suspend ui_curses_suspend -#define ui_term_backend_free ui_curses_free - #define CELL_COLOR_BLACK COLOR_BLACK #define CELL_COLOR_RED COLOR_RED #define CELL_COLOR_GREEN COLOR_GREEN @@ -85,7 +73,7 @@ static void undo_palette(void) } /* Work out the nearest color from the 256 color set, or perhaps exactly. */ -static CellColor color_rgb(UiTerm *ui, uint8_t r, uint8_t g, uint8_t b) +static CellColor color_rgb(Ui *ui, uint8_t r, uint8_t g, uint8_t b) { static short color_clobber_idx = 0; static uint32_t clobbering_colors[MAX_COLOR_CLOBBER]; @@ -163,7 +151,7 @@ static CellColor color_rgb(UiTerm *ui, uint8_t r, uint8_t g, uint8_t b) return i; } -static CellColor color_terminal(UiTerm *ui, uint8_t index) { +static CellColor color_terminal(Ui *ui, uint8_t index) { return index; } @@ -227,7 +215,7 @@ static inline attr_t style_to_attr(CellStyle *style) { return style->attr | COLOR_PAIR(color_pair_get(style->fg, style->bg)); } -static void ui_curses_blit(UiTerm *tui) { +static void ui_term_backend_blit(Ui *tui) { int w = tui->width, h = tui->height; Cell *cell = tui->cells; for (int y = 0; y < h; y++) { @@ -242,16 +230,16 @@ static void ui_curses_blit(UiTerm *tui) { doupdate(); } -static void ui_curses_clear(UiTerm *tui) { +static void ui_term_backend_clear(Ui *tui) { clear(); } -static bool ui_curses_resize(UiTerm *tui, int width, int height) { +static bool ui_term_backend_resize(Ui *tui, int width, int height) { return resizeterm(height, width) == OK && wresize(stdscr, height, width) == OK; } -static void ui_curses_save(UiTerm *tui, bool fscr) { +static void ui_term_backend_save(Ui *tui, bool fscr) { curs_set(1); if (fscr) { def_prog_mode(); @@ -261,17 +249,17 @@ static void ui_curses_save(UiTerm *tui, bool fscr) { } } -static void ui_curses_restore(UiTerm *tui) { +static void ui_term_backend_restore(Ui *tui) { reset_prog_mode(); wclear(stdscr); curs_set(0); } -static int ui_curses_colors(Ui *ui) { +int ui_terminal_colors(void) { return COLORS; } -static bool ui_curses_init(UiTerm *tui, char *term) { +static bool ui_term_backend_init(Ui *tui, char *term) { if (!newterm(term, stderr, stdin)) { snprintf(tui->info, sizeof(tui->info), "Warning: unknown term `%s'", term); if (!newterm(strstr(term, "-256color") ? "xterm-256color" : "xterm", stderr, stdin)) @@ -288,19 +276,19 @@ static bool ui_curses_init(UiTerm *tui, char *term) { return true; } -static UiTerm *ui_curses_new(void) { - return calloc(1, sizeof(UiTerm)); +static Ui *ui_term_backend_new(void) { + return calloc(1, sizeof(Ui)); } -static void ui_curses_resume(UiTerm *term) { } +void ui_terminal_resume(Ui *term) { } -static void ui_curses_suspend(UiTerm *term) { +static void ui_term_backend_suspend(Ui *term) { if (change_colors == 1) undo_palette(); } -static void ui_curses_free(UiTerm *term) { - ui_curses_suspend(term); +static void ui_term_backend_free(Ui *term) { + ui_term_backend_suspend(term); endwin(); } diff --git a/ui-terminal-vt100.c b/ui-terminal-vt100.c index 565313f..dffc235 100644 --- a/ui-terminal-vt100.c +++ b/ui-terminal-vt100.c @@ -41,18 +41,6 @@ #define UI_TERMKEY_FLAGS TERMKEY_FLAG_UTF8 -#define ui_term_backend_init ui_vt100_init -#define ui_term_backend_blit ui_vt100_blit -#define ui_term_backend_clear ui_vt100_clear -#define ui_term_backend_colors ui_vt100_colors -#define ui_term_backend_resize ui_vt100_resize -#define ui_term_backend_save ui_vt100_save -#define ui_term_backend_restore ui_vt100_restore -#define ui_term_backend_suspend ui_vt100_suspend -#define ui_term_backend_resume ui_vt100_resume -#define ui_term_backend_new ui_vt100_new -#define ui_term_backend_free ui_vt100_free - #define CELL_COLOR_BLACK { .index = 0 } #define CELL_COLOR_RED { .index = 1 } #define CELL_COLOR_GREEN { .index = 2 } @@ -72,7 +60,7 @@ #define CELL_ATTR_DIM (1 << 5) typedef struct { - UiTerm uiterm; + Ui uiterm; Buffer buf; } UiVt100; @@ -82,11 +70,11 @@ static inline bool cell_color_equal(CellColor c1, CellColor c2) { return c1.r == c2.r && c1.g == c2.g && c1.b == c2.b; } -static CellColor color_rgb(UiTerm *ui, uint8_t r, uint8_t g, uint8_t b) { +static CellColor color_rgb(Ui *ui, uint8_t r, uint8_t g, uint8_t b) { return (CellColor){ .r = r, .g = g, .b = b, .index = (uint8_t)-1 }; } -static CellColor color_terminal(UiTerm *ui, uint8_t index) { +static CellColor color_terminal(Ui *ui, uint8_t index) { return (CellColor){ .r = 0, .g = 0, .b = 0, .index = index }; } @@ -108,7 +96,7 @@ static void cursor_visible(bool visible) { output_literal(visible ? "\x1b[?25h" : "\x1b[?25l"); } -static void ui_vt100_blit(UiTerm *tui) { +static void ui_term_backend_blit(Ui *tui) { Buffer *buf = &((UiVt100*)tui)->buf; buffer_clear(buf); CellAttr attr = CELL_ATTR_NORMAL; @@ -174,54 +162,54 @@ static void ui_vt100_blit(UiTerm *tui) { output(buffer_content(buf), buffer_length0(buf)); } -static void ui_vt100_clear(UiTerm *tui) { } +static void ui_term_backend_clear(Ui *tui) { } -static bool ui_vt100_resize(UiTerm *tui, int width, int height) { +static bool ui_term_backend_resize(Ui *tui, int width, int height) { return true; } -static void ui_vt100_save(UiTerm *tui, bool fscr) { +static void ui_term_backend_save(Ui *tui, bool fscr) { cursor_visible(true); } -static void ui_vt100_restore(UiTerm *tui) { +static void ui_term_backend_restore(Ui *tui) { cursor_visible(false); } -static int ui_vt100_colors(Ui *ui) { +int ui_terminal_colors(void) { char *term = getenv("TERM"); return (term && strstr(term, "-256color")) ? 256 : 16; } -static void ui_vt100_suspend(UiTerm *tui) { +static void ui_term_backend_suspend(Ui *tui) { if (!tui->termkey) return; termkey_stop(tui->termkey); cursor_visible(true); screen_alternate(false); } -static void ui_vt100_resume(UiTerm *tui) { +void ui_terminal_resume(Ui *tui) { screen_alternate(true); cursor_visible(false); termkey_start(tui->termkey); } -static bool ui_vt100_init(UiTerm *tui, char *term) { - ui_vt100_resume(tui); +static bool ui_term_backend_init(Ui *tui, char *term) { + ui_terminal_resume(tui); return true; } -static UiTerm *ui_vt100_new(void) { +static Ui *ui_term_backend_new(void) { UiVt100 *vtui = calloc(1, sizeof *vtui); if (!vtui) return NULL; buffer_init(&vtui->buf); - return (UiTerm*)vtui; + return (Ui*)vtui; } -static void ui_vt100_free(UiTerm *tui) { +static void ui_term_backend_free(Ui *tui) { UiVt100 *vtui = (UiVt100*)tui; - ui_vt100_suspend(tui); + ui_term_backend_suspend(tui); buffer_release(&vtui->buf); } diff --git a/ui-terminal.c b/ui-terminal.c index 9aaac7d..048ba7f 100644 --- a/ui-terminal.c +++ b/ui-terminal.c @@ -13,7 +13,6 @@ #include <termios.h> #include <errno.h> -#include "ui-terminal.h" #include "vis.h" #include "vis-core.h" #include "text.h" @@ -30,26 +29,6 @@ #define debug(...) do { } while (0) #endif -#define MAX_WIDTH 1024 -#define MAX_HEIGHT 1024 - -struct UiTerm { - Ui ui; /* generic ui interface, has to be the first struct member */ - Vis *vis; /* editor instance to which this ui belongs */ - UiWin *windows; /* all windows managed by this ui */ - UiWin *selwin; /* the currently selected layout */ - char info[MAX_WIDTH]; /* info message displayed at the bottom of the screen */ - int width, height; /* terminal dimensions available for all windows */ - enum UiLayout layout; /* whether windows are displayed horizontally or vertically */ - TermKey *termkey; /* libtermkey instance to handle keyboard input (stdin or /dev/tty) */ - size_t ids; /* bit mask of in use window ids */ - size_t styles_size; /* #bytes allocated for styles array */ - CellStyle *styles; /* each window has UI_STYLE_MAX different style definitions */ - size_t cells_size; /* #bytes allocated for 2D grid (grows only) */ - Cell *cells; /* 2D grid of cells, at least as large as current terminal size */ - bool doupdate; /* Whether to update the screen after refreshing contents */ -}; - #if CONFIG_CURSES #include "ui-terminal-curses.c" #else @@ -59,16 +38,15 @@ struct UiTerm { /* helper macro for handling UiTerm.cells */ #define CELL_AT_POS(UI, X, Y) (((UI)->cells) + (X) + ((Y) * (UI)->width)); -__attribute__((noreturn)) static void ui_die(Ui *ui, const char *msg, va_list ap) { - UiTerm *tui = (UiTerm*)ui; - ui_term_backend_free(tui); +void ui_die(Ui *tui, const char *msg, va_list ap) { + ui_terminal_free(tui); if (tui->termkey) termkey_stop(tui->termkey); vfprintf(stderr, msg, ap); exit(EXIT_FAILURE); } -__attribute__((noreturn)) static void ui_die_msg(Ui *ui, const char *msg, ...) { +static void ui_die_msg(Ui *ui, const char *msg, ...) { va_list ap; va_start(ap, msg); ui_die(ui, msg, ap); @@ -89,7 +67,7 @@ static void ui_window_move(UiWin *win, int x, int y) { win->y = y; } -static bool color_fromstring(UiTerm *ui, CellColor *color, const char *s) +static bool color_fromstring(Ui *ui, CellColor *color, const char *s) { if (!s) return false; @@ -138,7 +116,7 @@ static bool color_fromstring(UiTerm *ui, CellColor *color, const char *s) } bool ui_style_define(UiWin *win, int id, const char *style) { - UiTerm *tui = win->ui; + Ui *tui = win->ui; if (id >= UI_STYLE_MAX) return false; if (!style) @@ -190,7 +168,7 @@ bool ui_style_define(UiWin *win, int id, const char *style) { return true; } -static void ui_draw_line(UiTerm *tui, int x, int y, char c, enum UiStyle style_id) { +static void ui_draw_line(Ui *tui, int x, int y, char c, enum UiStyle style_id) { if (x < 0 || x >= tui->width || y < 0 || y >= tui->height) return; CellStyle style = tui->styles[style_id]; @@ -203,7 +181,7 @@ static void ui_draw_line(UiTerm *tui, int x, int y, char c, enum UiStyle style_i } } -static void ui_draw_string(UiTerm *tui, int x, int y, const char *str, UiWin *win, enum UiStyle style_id) { +static void ui_draw_string(Ui *tui, int x, int y, const char *str, UiWin *win, enum UiStyle style_id) { debug("draw-string: [%d][%d]\n", y, x); if (x < 0 || x >= tui->width || y < 0 || y >= tui->height) return; @@ -225,7 +203,7 @@ static void ui_draw_string(UiTerm *tui, int x, int y, const char *str, UiWin *wi } static void ui_window_draw(UiWin *win) { - UiTerm *ui = win->ui; + Ui *ui = win->ui; View *view = win->win->view; int width = win->width, height = win->height; const Line *line = view->topline; @@ -276,7 +254,7 @@ static void ui_window_draw(UiWin *win) { } void ui_window_style_set(UiWin *win, Cell *cell, enum UiStyle id) { - UiTerm *tui = win->ui; + Ui *tui = win->ui; CellStyle set, style = tui->styles[win->id * UI_STYLE_MAX + id]; if (id == UI_STYLE_DEFAULT) { @@ -292,7 +270,7 @@ void ui_window_style_set(UiWin *win, Cell *cell, enum UiStyle id) { } bool ui_window_style_set_pos(UiWin *win, int x, int y, enum UiStyle id) { - UiTerm *tui = win->ui; + Ui *tui = win->ui; if (x < 0 || y < 0 || y >= win->height || x >= win->width) { return false; } @@ -304,14 +282,13 @@ bool ui_window_style_set_pos(UiWin *win, int x, int y, enum UiStyle id) { void ui_window_status(UiWin *win, const char *status) { if (!(win->options & UI_OPTION_STATUSBAR)) return; - UiTerm *ui = win->ui; + Ui *ui = win->ui; enum UiStyle style = ui->selwin == win ? UI_STYLE_STATUS_FOCUSED : UI_STYLE_STATUS; ui_draw_string(ui, win->x, win->y + win->height - 1, status, win, style); } -static void ui_arrange(Ui *ui, enum UiLayout layout) { +void ui_arrange(Ui *tui, enum UiLayout layout) { debug("ui-arrange\n"); - UiTerm *tui = (UiTerm*)ui; tui->layout = layout; int n = 0, m = !!tui->info[0], x = 0, y = 0; for (UiWin *win = tui->windows; win; win = win->next) { @@ -360,32 +337,24 @@ static void ui_arrange(Ui *ui, enum UiLayout layout) { } } -static void ui_doupdates(Ui *ui, bool doupdate) { - UiTerm *tui = (UiTerm*)ui; - tui->doupdate = doupdate; -} - -static void ui_draw(Ui *ui) { +void ui_draw(Ui *tui) { debug("ui-draw\n"); - UiTerm *tui = (UiTerm*)ui; - ui_arrange(ui, tui->layout); + ui_arrange(tui, tui->layout); for (UiWin *win = tui->windows; win; win = win->next) - ui_window_draw((UiWin*)win); + ui_window_draw(win); if (tui->info[0]) ui_draw_string(tui, 0, tui->height-1, tui->info, NULL, UI_STYLE_INFO); vis_event_emit(tui->vis, VIS_EVENT_UI_DRAW); ui_term_backend_blit(tui); } -static void ui_redraw(Ui *ui) { - UiTerm *tui = (UiTerm*)ui; +void ui_redraw(Ui *tui) { ui_term_backend_clear(tui); for (UiWin *win = tui->windows; win; win = win->next) win->win->view->need_update = true; } -static void ui_resize(Ui *ui) { - UiTerm *tui = (UiTerm*)ui; +void ui_resize(Ui *tui) { struct winsize ws; int width = 80, height = 24; @@ -396,8 +365,8 @@ static void ui_resize(Ui *ui) { height = ws.ws_row; } - width = MIN(width, MAX_WIDTH); - height = MIN(height, MAX_HEIGHT); + width = MIN(width, UI_MAX_WIDTH); + height = MIN(height, UI_MAX_HEIGHT); if (!ui_term_backend_resize(tui, width, height)) return; @@ -414,10 +383,10 @@ static void ui_resize(Ui *ui) { tui->height = height; } -static void ui_window_free(UiWin *win) { +void ui_window_free(UiWin *win) { if (!win) return; - UiTerm *tui = win->ui; + Ui *tui = win->ui; if (win->prev) win->prev->next = win->next; if (win->next) @@ -431,7 +400,7 @@ static void ui_window_free(UiWin *win) { free(win); } -static void ui_window_focus(UiWin *new) { +void ui_window_focus(UiWin *new) { UiWin *old = new->ui->selwin; if (new->options & UI_OPTION_STATUSBAR) new->ui->selwin = new; @@ -444,7 +413,7 @@ void ui_window_options_set(UiWin *win, enum UiOption options) { win->options = options; if (options & UI_OPTION_ONELINE) { /* move the new window to the end of the list */ - UiTerm *tui = win->ui; + Ui *tui = win->ui; UiWin *last = tui->windows; while (last->next) last = last->next; @@ -460,13 +429,13 @@ void ui_window_options_set(UiWin *win, enum UiOption options) { win->next = NULL; } } - ui_draw((Ui*)win->ui); + ui_draw(win->ui); } -static void ui_window_swap(UiWin *a, UiWin *b) { +void ui_window_swap(UiWin *a, UiWin *b) { if (a == b || !a || !b) return; - UiTerm *tui = a->ui; + Ui *tui = a->ui; UiWin *tmp = a->next; a->next = b->next; b->next = tmp; @@ -491,8 +460,7 @@ static void ui_window_swap(UiWin *a, UiWin *b) { ui_window_focus(a); } -static UiWin *ui_window_new(Ui *ui, Win *w, enum UiOption options) { - UiTerm *tui = (UiTerm*)ui; +UiWin *ui_window_new(Ui *tui, Win *w, enum UiOption options) { /* get rightmost zero bit, i.e. highest available id */ size_t bit = ~tui->ids & (tui->ids + 1); size_t id = 0; @@ -544,19 +512,17 @@ static UiWin *ui_window_new(Ui *ui, Win *w, enum UiOption options) { options &= ~UI_OPTION_LINE_NUMBERS_ABSOLUTE; } - ui_window_options_set((UiWin*)win, options); + ui_window_options_set(win, options); return win; } -static void ui_info(Ui *ui, const char *msg, va_list ap) { - UiTerm *tui = (UiTerm*)ui; +void ui_info_show(Ui *tui, const char *msg, va_list ap) { ui_draw_line(tui, 0, tui->height-1, ' ', UI_STYLE_INFO); vsnprintf(tui->info, sizeof(tui->info), msg, ap); } -static void ui_info_hide(Ui *ui) { - UiTerm *tui = (UiTerm*)ui; +void ui_info_hide(Ui *tui) { if (tui->info[0]) tui->info[0] = '\0'; } @@ -580,31 +546,19 @@ static TermKey *ui_termkey_reopen(Ui *ui, int fd) { return ui_termkey_new(fd); } -static TermKey *ui_termkey_get(Ui *ui) { - UiTerm *tui = (UiTerm*)ui; - return tui->termkey; -} - -static void ui_suspend(Ui *ui) { - UiTerm *tui = (UiTerm*)ui; +void ui_terminal_suspend(Ui *tui) { ui_term_backend_suspend(tui); kill(0, SIGTSTP); } -static void ui_resume(Ui *ui) { - UiTerm *tui = (UiTerm*)ui; - ui_term_backend_resume(tui); -} - -static bool ui_getkey(Ui *ui, TermKeyKey *key) { - UiTerm *tui = (UiTerm*)ui; +bool ui_getkey(Ui *tui, TermKeyKey *key) { TermKeyResult ret = termkey_getkey(tui->termkey, key); if (ret == TERMKEY_RES_EOF) { termkey_destroy(tui->termkey); errno = 0; - if (!(tui->termkey = ui_termkey_reopen(ui, STDIN_FILENO))) - ui_die_msg(ui, "Failed to re-open stdin as /dev/tty: %s\n", errno != 0 ? strerror(errno) : ""); + if (!(tui->termkey = ui_termkey_reopen(tui, STDIN_FILENO))) + ui_die_msg(tui, "Failed to re-open stdin as /dev/tty: %s\n", errno != 0 ? strerror(errno) : ""); return false; } @@ -619,20 +573,17 @@ static bool ui_getkey(Ui *ui, TermKeyKey *key) { return ret == TERMKEY_RES_KEY; } -static void ui_terminal_save(Ui *ui, bool fscr) { - UiTerm *tui = (UiTerm*)ui; +void ui_terminal_save(Ui *tui, bool fscr) { ui_term_backend_save(tui, fscr); termkey_stop(tui->termkey); } -static void ui_terminal_restore(Ui *ui) { - UiTerm *tui = (UiTerm*)ui; +void ui_terminal_restore(Ui *tui) { termkey_start(tui->termkey); ui_term_backend_restore(tui); } -static bool ui_init(Ui *ui, Vis *vis) { - UiTerm *tui = (UiTerm*)ui; +bool ui_init(Ui *tui, Vis *vis) { tui->vis = vis; setlocale(LC_CTYPE, ""); @@ -648,7 +599,7 @@ static bool ui_init(Ui *ui, Vis *vis) { /* work around libtermkey bug which fails if stdin is /dev/null */ if (errno == EBADF) { errno = 0; - if (!(tui->termkey = ui_termkey_reopen(ui, STDIN_FILENO)) && errno == ENXIO) + if (!(tui->termkey = ui_termkey_reopen(tui, STDIN_FILENO)) && errno == ENXIO) tui->termkey = termkey_new_abstract(term, UI_TERMKEY_FLAGS); } if (!tui->termkey) @@ -657,24 +608,19 @@ static bool ui_init(Ui *ui, Vis *vis) { if (!ui_term_backend_init(tui, term)) goto err; - ui_resize(ui); + ui_resize(tui); return true; err: - ui_die_msg(ui, "Failed to start curses interface: %s\n", errno != 0 ? strerror(errno) : ""); + ui_die_msg(tui, "Failed to start curses interface: %s\n", errno != 0 ? strerror(errno) : ""); return false; } -enum UiLayout ui_layout_get(Ui *ui) { - UiTerm *tui = (UiTerm *)ui; - return tui->layout; -} - -Ui *ui_term_new(void) { +Ui *ui_terminal_new(void) { size_t styles_size = UI_STYLE_MAX * sizeof(CellStyle); CellStyle *styles = calloc(1, styles_size); if (!styles) return NULL; - UiTerm *tui = ui_term_backend_new(); + Ui *tui = ui_term_backend_new(); if (!tui) { free(styles); return NULL; @@ -682,40 +628,14 @@ Ui *ui_term_new(void) { tui->styles_size = styles_size; tui->styles = styles; tui->doupdate = true; - Ui *ui = (Ui*)tui; - *ui = (Ui) { - .init = ui_init, - .free = ui_term_free, - .termkey_get = ui_termkey_get, - .suspend = ui_suspend, - .resume = ui_resume, - .resize = ui_resize, - .window_new = ui_window_new, - .window_free = ui_window_free, - .window_focus = ui_window_focus, - .window_swap = ui_window_swap, - .draw = ui_draw, - .redraw = ui_redraw, - .arrange = ui_arrange, - .doupdates = ui_doupdates, - .die = ui_die, - .info = ui_info, - .info_hide = ui_info_hide, - .getkey = ui_getkey, - .terminal_save = ui_terminal_save, - .terminal_restore = ui_terminal_restore, - .colors = ui_term_backend_colors, - }; - - return ui; + return tui; } -void ui_term_free(Ui *ui) { - UiTerm *tui = (UiTerm*)ui; +void ui_terminal_free(Ui *tui) { if (!tui) return; while (tui->windows) - ui_window_free((UiWin*)tui->windows); + ui_window_free(tui->windows); ui_term_backend_free(tui); if (tui->termkey) termkey_destroy(tui->termkey); diff --git a/ui-terminal.h b/ui-terminal.h deleted file mode 100644 index 45286ab..0000000 --- a/ui-terminal.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef UI_TERMINAL_H -#define UI_TERMINAL_H - -#include "ui.h" - -Ui *ui_term_new(void); -void ui_term_free(Ui*); - -#endif @@ -10,9 +10,8 @@ /* enable large file optimization for files containing lines longer than: */ #define UI_LARGE_FILE_LINE_SIZE (1 << 16) -typedef struct Ui Ui; -typedef struct UiWin UiWin; -typedef struct UiTerm UiTerm; +#define UI_MAX_WIDTH 1024 +#define UI_MAX_HEIGHT 1024 enum UiLayout { UI_LAYOUT_HORIZONTAL, @@ -68,52 +67,82 @@ typedef struct { CellColor fg, bg; } CellStyle; +typedef struct { + char data[16]; /* utf8 encoded character displayed in this cell (might be more than + one Unicode codepoint. might also not be the same as in the + underlying text, for example tabs get expanded */ + size_t len; /* number of bytes the character displayed in this cell uses, for + characters which use more than 1 column to display, their length + is stored in the leftmost cell whereas all following cells + occupied by the same character have a length of 0. */ + int width; /* display width i.e. number of columns occupied by this character */ + CellStyle style; /* colors and attributes used to display this cell */ +} Cell; + +struct Ui; +struct Win; +typedef struct UiWin { + struct Ui *ui; /* ui which manages this window */ + struct Win *win; /* editor window being displayed */ + int id; /* unique identifier for this window */ + int width, height; /* window dimension including status bar */ + int x, y; /* window position */ + int sidebar_width; /* width of the sidebar showing line numbers etc. */ + struct UiWin *next, *prev; /* pointers to neighbouring windows */ + enum UiOption options; /* display settings for this window */ +} UiWin; + +struct Vis; +typedef struct Ui { + struct Vis *vis; /* editor instance to which this ui belongs */ + UiWin *windows; /* all windows managed by this ui */ + UiWin *selwin; /* the currently selected layout */ + char info[UI_MAX_WIDTH]; /* info message displayed at the bottom of the screen */ + int width, height; /* terminal dimensions available for all windows */ + enum UiLayout layout; /* whether windows are displayed horizontally or vertically */ + TermKey *termkey; /* libtermkey instance to handle keyboard input (stdin or /dev/tty) */ + size_t ids; /* bit mask of in use window ids */ + size_t styles_size; /* #bytes allocated for styles array */ + CellStyle *styles; /* each window has UI_STYLE_MAX different style definitions */ + size_t cells_size; /* #bytes allocated for 2D grid (grows only) */ + Cell *cells; /* 2D grid of cells, at least as large as current terminal size */ + bool doupdate; /* Whether to update the screen after refreshing contents */ +} Ui; + +#include "view.h" #include "vis.h" #include "text.h" -#include "view.h" -struct Ui { - bool (*init)(Ui*, Vis*); - void (*free)(Ui*); - void (*resize)(Ui*); - UiWin* (*window_new)(Ui*, Win*, enum UiOption); - void (*window_free)(UiWin*); - void (*window_focus)(UiWin*); - void (*window_swap)(UiWin*, UiWin*); - void (*die)(Ui*, const char *msg, va_list ap) __attribute__((noreturn)); - void (*info)(Ui*, const char *msg, va_list ap); - void (*info_hide)(Ui*); - void (*arrange)(Ui*, enum UiLayout); - void (*draw)(Ui*); - void (*redraw)(Ui*); - void (*suspend)(Ui*); - void (*resume)(Ui*); - void (*doupdates)(Ui*, bool); - bool (*getkey)(Ui*, TermKeyKey*); - void (*terminal_save)(Ui*, bool fscr); - void (*terminal_restore)(Ui*); - TermKey* (*termkey_get)(Ui*); - int (*colors)(Ui*); -}; +#define UI_OPTIONS_GET(ui) ((ui) ? (ui)->options : 0) -struct UiWin { - UiTerm *ui; /* ui which manages this window */ - Win *win; /* editor window being displayed */ - int id; /* unique identifier for this window */ - int width, height; /* window dimension including status bar */ - int x, y; /* window position */ - int sidebar_width; /* width of the sidebar showing line numbers etc. */ - UiWin *next, *prev; /* pointers to neighbouring windows */ - enum UiOption options; /* display settings for this window */ -}; +Ui *ui_terminal_new(void); +int ui_terminal_colors(void); +void ui_terminal_free(Ui*); +void ui_terminal_restore(Ui*); +void ui_terminal_resume(Ui*); +void ui_terminal_save(Ui*, bool fscr); +void ui_terminal_suspend(Ui*); -#define UI_OPTIONS_GET(ui) ((ui) ? (ui)->options : 0) +__attribute__((noreturn)) void ui_die(Ui *, const char *, va_list); +bool ui_init(Ui *, Vis *); +void ui_arrange(Ui*, enum UiLayout); +void ui_draw(Ui*); +void ui_info_hide(Ui *); +void ui_info_show(Ui *, const char *, va_list); +void ui_redraw(Ui*); +void ui_resize(Ui*); + +UiWin *ui_window_new(Ui *, Win *, enum UiOption); +void ui_window_focus(UiWin *); +void ui_window_free(UiWin *); +void ui_window_swap(UiWin *, UiWin *); + +bool ui_getkey(Ui *, TermKeyKey *); bool ui_style_define(UiWin *win, int id, const char *style); bool ui_window_style_set_pos(UiWin *win, int x, int y, enum UiStyle id); void ui_window_style_set(UiWin *win, Cell *cell, enum UiStyle id); -enum UiLayout ui_layout_get(Ui *ui); void ui_window_options_set(UiWin *win, enum UiOption options); void ui_window_status(UiWin *win, const char *status); @@ -26,18 +26,6 @@ typedef struct { Mark cursor; } SelectionRegion; -typedef struct { - char data[16]; /* utf8 encoded character displayed in this cell (might be more than - one Unicode codepoint. might also not be the same as in the - underlying text, for example tabs get expanded */ - size_t len; /* number of bytes the character displayed in this cell uses, for - characters which use more than 1 column to display, their length - is stored in the leftmost cell whereas all following cells - occupied by the same character have a length of 0. */ - int width; /* display width i.e. number of columns occupied by this character */ - CellStyle style; /* colors and attributes used to display this cell */ -} Cell; - typedef struct Line Line; struct Line { /* a line on the screen, *not* in the file */ Line *prev, *next; /* pointer to neighbouring screen lines */ @@ -125,10 +125,6 @@ static bool cmd_user(Vis *vis, Win *win, Command *cmd, const char *argv[], Selec return user && user->func(vis, win, user->data, cmd->flags == '!', argv, sel, range); } -static void windows_arrange(Vis *vis, enum UiLayout layout) { - vis->ui->arrange(vis->ui, layout); -} - void vis_shell_set(Vis *vis, const char *new_shell) { char *shell = strdup(new_shell); if (!shell) { @@ -250,7 +246,7 @@ static bool cmd_set(Vis *vis, Win *win, Command *cmd, const char *argv[], Select break; case OPTION_ESCDELAY: { - TermKey *termkey = vis->ui->termkey_get(vis->ui); + TermKey *termkey = vis->ui->termkey; termkey_set_waittime(termkey, arg.i); break; } @@ -358,7 +354,7 @@ static bool cmd_set(Vis *vis, Win *win, Command *cmd, const char *argv[], Select vis_info_show(vis, "Invalid layout `%s', expected 'h' or 'v'", arg.s); return false; } - windows_arrange(vis, layout); + ui_arrange(vis->ui, layout); break; } case OPTION_IGNORECASE: @@ -546,7 +542,7 @@ static bool cmd_split(Vis *vis, Win *win, Command *cmd, const char *argv[], Sele if (!win) return false; enum UiOption options = UI_OPTIONS_GET(win->view->ui); - windows_arrange(vis, UI_LAYOUT_HORIZONTAL); + ui_arrange(vis->ui, UI_LAYOUT_HORIZONTAL); if (!argv[1]) return vis_window_split(win); bool ret = openfiles(vis, &argv[1]); @@ -559,7 +555,7 @@ static bool cmd_vsplit(Vis *vis, Win *win, Command *cmd, const char *argv[], Sel if (!win) return false; enum UiOption options = UI_OPTIONS_GET(win->view->ui); - windows_arrange(vis, UI_LAYOUT_VERTICAL); + ui_arrange(vis->ui, UI_LAYOUT_VERTICAL); if (!argv[1]) return vis_window_split(win); bool ret = openfiles(vis, &argv[1]); @@ -569,12 +565,12 @@ static bool cmd_vsplit(Vis *vis, Win *win, Command *cmd, const char *argv[], Sel } static bool cmd_new(Vis *vis, Win *win, Command *cmd, const char *argv[], Selection *sel, Filerange *range) { - windows_arrange(vis, UI_LAYOUT_HORIZONTAL); + ui_arrange(vis->ui, UI_LAYOUT_HORIZONTAL); return vis_window_new(vis, NULL); } static bool cmd_vnew(Vis *vis, Win *win, Command *cmd, const char *argv[], Selection *sel, Filerange *range) { - windows_arrange(vis, UI_LAYOUT_VERTICAL); + ui_arrange(vis->ui, UI_LAYOUT_VERTICAL); return vis_window_new(vis, NULL); } @@ -779,7 +775,7 @@ static void print_symbolic_keys(Vis *vis, Text *txt) { TERMKEY_SYM_KPEQUALS, }; - TermKey *termkey = vis->ui->termkey_get(vis->ui); + TermKey *termkey = vis->ui->termkey; text_appendf(txt, " ␣ (a literal \" \" space symbol must be used to refer to <Space>)\n"); for (size_t i = 0; i < LENGTH(keys); i++) { text_appendf(txt, " <%s>\n", termkey_get_keyname(termkey, keys[i])); @@ -1429,7 +1429,7 @@ static int vis_options_assign(Vis *vis, lua_State *L, const char *key, int next) } else if (strcmp(key, "changecolors") == 0) { vis->change_colors = lua_toboolean(L, next); } else if (strcmp(key, "escdelay") == 0) { - TermKey *tk = vis->ui->termkey_get(vis->ui); + TermKey *tk = vis->ui->termkey; termkey_set_waittime(tk, luaL_checkint(L, next)); } else if (strcmp(key, "ignorecase") == 0 || strcmp(key, "ic") == 0) { vis->ignorecase = lua_toboolean(L, next); @@ -1570,7 +1570,7 @@ static int vis_options_index(lua_State *L) { lua_pushboolean(L, vis->change_colors); return 1; } else if (strcmp(key, "escdelay") == 0) { - TermKey *tk = vis->ui->termkey_get(vis->ui); + TermKey *tk = vis->ui->termkey; lua_pushunsigned(L, termkey_get_waittime(tk)); return 1; } else if (strcmp(key, "ignorecase") == 0 || strcmp(key, "ic") == 0) { @@ -1633,7 +1633,7 @@ static int ui_index(lua_State *L) { const char *key = lua_tostring(L, 2); if (strcmp(key, "layout") == 0) { - lua_pushunsigned(L, ui_layout_get(ui)); + lua_pushunsigned(L, ui->layout); return 1; } } @@ -1648,7 +1648,7 @@ static int ui_newindex(lua_State *L) { const char *key = lua_tostring(L, 2); if (strcmp(key, "layout") == 0) { - ui->arrange(ui, luaL_checkint(L, 3)); + ui_arrange(ui, luaL_checkint(L, 3)); return 0; } } @@ -3260,7 +3260,7 @@ static void vis_lua_init(Vis *vis) { obj_type_new(L, VIS_LUA_TYPE_UI); luaL_setfuncs(L, ui_funcs, 0); - lua_pushunsigned(L, vis->ui->colors(vis->ui)); + lua_pushunsigned(L, ui_terminal_colors()); lua_setfield(L, -2, "colors"); lua_newtable(L); static const struct { @@ -3612,7 +3612,7 @@ static void vis_lua_ui_draw(Vis *vis) { bool vis_event_emit(Vis *vis, enum VisEvents id, ...) { if (!vis->initialized) { vis->initialized = true; - vis->ui->init(vis->ui, vis); + ui_init(vis->ui, vis); vis_lua_init(vis); } diff --git a/vis-prompt.c b/vis-prompt.c index 6dbe69c..474a32c 100644 --- a/vis-prompt.c +++ b/vis-prompt.c @@ -182,14 +182,10 @@ void vis_prompt_show(Vis *vis, const char *title) { void vis_info_show(Vis *vis, const char *msg, ...) { va_list ap; va_start(ap, msg); - vis->ui->info(vis->ui, msg, ap); + ui_info_show(vis->ui, msg, ap); va_end(ap); } -void vis_info_hide(Vis *vis) { - vis->ui->info_hide(vis->ui); -} - void vis_message_show(Vis *vis, const char *msg) { if (!msg) return; @@ -203,7 +203,7 @@ static void window_free(Win *win) { other->parent = NULL; } if (vis->ui) - vis->ui->window_free(win->ui); + ui_window_free(win->ui); view_free(win->view); for (size_t i = 0; i < LENGTH(win->modes); i++) map_free(win->modes[i].bindings); @@ -382,7 +382,7 @@ Win *window_new_file(Vis *vis, File *file, enum UiOption options) { win->file = file; win->view = view_new(file->text); win->expandtab = false; - win->ui = vis->ui->window_new(vis->ui, win, options); + win->ui = ui_window_new(vis->ui, win, options); if (!win->view || !win->ui) { window_free(win); return NULL; @@ -397,7 +397,7 @@ Win *window_new_file(Vis *vis, File *file, enum UiOption options) { win->next = vis->windows; vis->windows = win; vis->win = win; - vis->ui->window_focus(win->ui); + ui_window_focus(win->ui); for (size_t i = 0; i < LENGTH(win->modes); i++) win->modes[i].parent = &vis_modes[i]; vis_event_emit(vis, VIS_EVENT_WIN_OPEN, win); @@ -434,7 +434,7 @@ bool vis_window_change_file(Win *win, const char* filename) { } bool vis_window_split(Win *original) { - vis_doupdates(original->vis, false); + original->vis->ui->doupdate = false; Win *win = window_new_file(original->vis, original->file, UI_OPTION_STATUSBAR); if (!win) return false; @@ -447,7 +447,7 @@ bool vis_window_split(Win *original) { win->file = original->file; view_options_set(win->view, UI_OPTIONS_GET(original->view->ui)); view_cursors_to(win->view->selection, view_cursor_get(original->view)); - vis_doupdates(win->vis, true); + win->vis->ui->doupdate = true; return true; } @@ -456,7 +456,7 @@ void vis_window_focus(Win *win) { return; Vis *vis = win->vis; vis->win = win; - vis->ui->window_focus(win->ui); + ui_window_focus(win->ui); } void vis_window_next(Vis *vis) { @@ -482,37 +482,21 @@ void vis_draw(Vis *vis) { } void vis_redraw(Vis *vis) { - vis->ui->redraw(vis->ui); - vis_update(vis); -} - -void vis_update(Vis *vis) { - vis->ui->draw(vis->ui); -} - -void vis_suspend(Vis *vis) { - vis->ui->suspend(vis->ui); -} - -void vis_resume(Vis *vis) { - vis->ui->resume(vis->ui); -} - -void vis_doupdates(Vis *vis, bool doupdate) { - vis->ui->doupdates(vis->ui, doupdate); + ui_redraw(vis->ui); + ui_draw(vis->ui); } bool vis_window_new(Vis *vis, const char *filename) { File *file = file_new(vis, filename, false); if (!file) return false; - vis_doupdates(vis, false); + vis->ui->doupdate = false; Win *win = window_new_file(vis, file, UI_OPTION_STATUSBAR|UI_OPTION_SYMBOL_EOF); if (!win) { file_free(vis, file); return false; } - vis_doupdates(vis, true); + vis->ui->doupdate = true; return true; } @@ -554,7 +538,7 @@ void vis_window_swap(Win *a, Win *b) { vis->windows = b; else if (vis->windows == b) vis->windows = a; - vis->ui->window_swap(a->ui, b->ui); + ui_window_swap(a->ui, b->ui); if (vis->win == a) vis_window_focus(b); else if (vis->win == b) @@ -579,7 +563,7 @@ void vis_window_close(Win *win) { vis->message_window = NULL; window_free(win); if (vis->win) - vis->ui->window_focus(vis->win->ui); + ui_window_focus(vis->win->ui); vis_draw(vis); } @@ -645,7 +629,7 @@ void vis_free(Vis *vis) { file_free(vis, vis->error_file); for (int i = 0; i < LENGTH(vis->registers); i++) register_release(&vis->registers[i]); - vis->ui->free(vis->ui); + ui_terminal_free(vis->ui); if (vis->usercmds) { const char *name; while (map_first(vis->usercmds, &name) && vis_cmd_unregister(vis, name)); @@ -976,7 +960,7 @@ void vis_cancel(Vis *vis) { void vis_die(Vis *vis, const char *msg, ...) { va_list ap; va_start(ap, msg); - vis->ui->die(vis->ui, msg, ap); + ui_die(vis->ui, msg, ap); va_end(ap); } @@ -984,7 +968,7 @@ const char *vis_keys_next(Vis *vis, const char *keys) { if (!keys || !*keys) return NULL; TermKeyKey key; - TermKey *termkey = vis->ui->termkey_get(vis->ui); + TermKey *termkey = vis->ui->termkey; const char *next = NULL; /* first try to parse a special key of the form <Key> */ if (*keys == '<' && keys[1] && (next = termkey_strpkey(termkey, keys+1, &key, TERMKEY_FORMAT_VIM)) && *next == '>') @@ -1012,7 +996,7 @@ long vis_keys_codepoint(Vis *vis, const char *keys) { long codepoint = -1; const char *next; TermKeyKey key; - TermKey *termkey = vis->ui->termkey_get(vis->ui); + TermKey *termkey = vis->ui->termkey; if (!keys[0]) return -1; @@ -1205,9 +1189,9 @@ static void vis_keys_push(Vis *vis, const char *input, size_t pos, bool record) static const char *getkey(Vis *vis) { TermKeyKey key = { 0 }; - if (!vis->ui->getkey(vis->ui, &key)) + if (!ui_getkey(vis->ui, &key)) return NULL; - vis_info_hide(vis); + ui_info_hide(vis->ui); bool use_keymap = vis->mode->id != VIS_MODE_INSERT && vis->mode->id != VIS_MODE_REPLACE && !vis->keymap_disabled; @@ -1221,7 +1205,7 @@ static const char *getkey(Vis *vis) { } } - TermKey *termkey = vis->ui->termkey_get(vis->ui); + TermKey *termkey = vis->ui->termkey; if (key.type == TERMKEY_TYPE_UNKNOWN_CSI) { long args[18]; size_t nargs; @@ -1315,16 +1299,16 @@ int vis_run(Vis *vis) { } if (vis->resume) { - vis_resume(vis); + ui_terminal_resume(vis->ui); vis->resume = false; } if (vis->need_resize) { - vis->ui->resize(vis->ui); + ui_resize(vis->ui); vis->need_resize = false; } - vis_update(vis); + ui_draw(vis->ui); idle.tv_sec = vis->mode->idle_timeout; int r = pselect(vis_process_before_tick(&fds) + 1, &fds, NULL, NULL, timeout, &emptyset); @@ -1344,7 +1328,7 @@ int vis_run(Vis *vis) { continue; } - TermKey *termkey = vis->ui->termkey_get(vis->ui); + TermKey *termkey = vis->ui->termkey; termkey_advisereadable(termkey); const char *key; @@ -1640,7 +1624,7 @@ int vis_pipe(Vis *vis, File *file, Filerange *range, const char *argv[], return -1; } - vis->ui->terminal_save(vis->ui, fullscreen); + ui_terminal_save(vis->ui, fullscreen); pid_t pid = fork(); if (pid == -1) { @@ -1834,7 +1818,7 @@ err: sigaction(SIGTERM, &sigterm_old, NULL); vis->interrupted = false; - vis->ui->terminal_restore(vis->ui); + ui_terminal_restore(vis->ui); if (WIFEXITED(status)) return WEXITSTATUS(status); @@ -110,27 +110,6 @@ void vis_exit(Vis*, int status); void vis_die(Vis*, const char *msg, ...) __attribute__((noreturn,format(printf, 2, 3))); /** - * Temporarily suspend the editor process. - * @rst - * .. note:: This function will generate a ``SIGTSTP`` signal. - * @endrst - **/ -void vis_suspend(Vis*); -/** - * Resume editor process. - * @rst - * .. note:: This function is usually called in response to a ``SIGCONT`` signal. - * @endrst - */ -void vis_resume(Vis*); -/** - * Set doupdate flag. - * @rst - * .. note:: Prevent flickering in curses by delaying window updates. - * @endrst - */ -void vis_doupdates(Vis*, bool); -/** * Inform the editor core that a signal occurred. * @return Whether the signal was handled. * @rst @@ -162,8 +141,6 @@ bool vis_interrupt_requested(Vis*); void vis_draw(Vis*); /** Completely redraw user interface. */ void vis_redraw(Vis*); -/** Blit user interface state to output device. */ -void vis_update(Vis*); /** * @} * @defgroup vis_windows @@ -226,8 +203,6 @@ void vis_prompt_show(Vis*, const char *title); * @endrst */ void vis_info_show(Vis*, const char *msg, ...) __attribute__((format(printf, 2, 3))); -/** Hide informational message. */ -void vis_info_hide(Vis*); /** Display arbitrary long message in a dedicated window. */ void vis_message_show(Vis*, const char *msg); |
