diff options
Diffstat (limited to 'examples/dte/screen.c')
| -rw-r--r-- | examples/dte/screen.c | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/examples/dte/screen.c b/examples/dte/screen.c new file mode 100644 index 0000000..22bbf69 --- /dev/null +++ b/examples/dte/screen.c @@ -0,0 +1,211 @@ +#include <string.h> +#include "screen.h" +#include "frame.h" +#include "terminal/cursor.h" +#include "terminal/ioctl.h" +#include "util/log.h" + +void set_color(Terminal *term, const ColorScheme *colors, const TermColor *color) +{ + TermColor tmp = *color; + // NOTE: -2 (keep) is treated as -1 (default) + if (tmp.fg < 0) { + tmp.fg = colors->builtin[BC_DEFAULT].fg; + } + if (tmp.bg < 0) { + tmp.bg = colors->builtin[BC_DEFAULT].bg; + } + if (same_color(&tmp, &term->obuf.color)) { + return; + } + term_set_color(term, &tmp); +} + +void set_builtin_color(Terminal *term, const ColorScheme *colors, BuiltinColorEnum c) +{ + set_color(term, colors, &colors->builtin[c]); +} + +static void update_cursor_style(EditorState *e) +{ + CursorInputMode mode; + switch (e->input_mode) { + case INPUT_NORMAL: + if (e->buffer->options.overwrite) { + mode = CURSOR_MODE_OVERWRITE; + } else { + mode = CURSOR_MODE_INSERT; + } + break; + case INPUT_COMMAND: + case INPUT_SEARCH: + mode = CURSOR_MODE_CMDLINE; + break; + default: + BUG("unhandled input mode"); + return; + } + + TermCursorStyle style = e->cursor_styles[mode]; + TermCursorStyle def = e->cursor_styles[CURSOR_MODE_DEFAULT]; + if (style.type == CURSOR_KEEP) { + style.type = def.type; + } + if (style.color == COLOR_KEEP) { + style.color = def.color; + } + + e->cursor_style_changed = false; + if (!same_cursor(&style, &e->terminal.obuf.cursor_style)) { + term_set_cursor_style(&e->terminal, style); + } +} + +void update_term_title(Terminal *term, const Buffer *buffer, bool set_window_title) +{ + if (!set_window_title || !(term->features & TFLAG_SET_WINDOW_TITLE)) { + return; + } + + // FIXME: title must not contain control characters + TermOutputBuffer *obuf = &term->obuf; + const char *filename = buffer_filename(buffer); + term_add_literal(obuf, "\033]2;"); + term_add_bytes(obuf, filename, strlen(filename)); + term_add_byte(obuf, ' '); + term_add_byte(obuf, buffer_modified(buffer) ? '+' : '-'); + term_add_literal(obuf, " dte\033\\"); +} + +void mask_color(TermColor *color, const TermColor *over) +{ + if (over->fg != COLOR_KEEP) { + color->fg = over->fg; + } + if (over->bg != COLOR_KEEP) { + color->bg = over->bg; + } + if (!(over->attr & ATTR_KEEP)) { + color->attr = over->attr; + } +} + +void restore_cursor(EditorState *e) +{ + unsigned int x, y; + switch (e->input_mode) { + case INPUT_NORMAL: + x = e->window->edit_x + e->view->cx_display - e->view->vx; + y = e->window->edit_y + e->view->cy - e->view->vy; + break; + case INPUT_COMMAND: + case INPUT_SEARCH: + x = e->cmdline_x; + y = e->terminal.height - 1; + break; + default: + BUG("unhandled input mode"); + } + term_move_cursor(&e->terminal.obuf, x, y); +} + +static void clear_update_tabbar(Window *window, void* UNUSED_ARG(data)) +{ + window->update_tabbar = false; +} + +void end_update(EditorState *e) +{ + Terminal *term = &e->terminal; + restore_cursor(e); + term_show_cursor(term); + term_end_sync_update(term); + term_output_flush(&term->obuf); + + e->buffer->changed_line_min = LONG_MAX; + e->buffer->changed_line_max = -1; + frame_for_each_window(e->root_frame, clear_update_tabbar, NULL); +} + +void start_update(Terminal *term) +{ + term_begin_sync_update(term); + term_hide_cursor(term); +} + +void update_window_sizes(Terminal *term, Frame *frame) +{ + set_frame_size(frame, term->width, term->height - 1); + update_window_coordinates(frame); +} + +void update_screen_size(Terminal *term, Frame *root_frame) +{ + unsigned int width, height; + if (!term_get_size(&width, &height)) { + return; + } + + // TODO: remove minimum width/height and instead make update_screen() + // do something sensible when the terminal dimensions are tiny + term->width = MAX(width, 3); + term->height = MAX(height, 3); + + update_window_sizes(term, root_frame); + LOG_INFO("terminal size: %ux%u", width, height); +} + +NOINLINE +void normal_update(EditorState *e) +{ + Terminal *term = &e->terminal; + start_update(term); + update_term_title(term, e->buffer, e->options.set_window_title); + update_all_windows(e); + update_command_line(e); + update_cursor_style(e); + end_update(e); +} + +void update_screen(EditorState *e, const ScreenState *s) +{ + if (e->everything_changed) { + e->everything_changed = false; + normal_update(e); + return; + } + + Buffer *buffer = e->buffer; + View *view = e->view; + view_update_cursor_x(view); + view_update_cursor_y(view); + view_update(view, e->options.scroll_margin); + + if (s->id == buffer->id) { + if (s->vx != view->vx || s->vy != view->vy) { + mark_all_lines_changed(buffer); + } else { + // Because of trailing whitespace highlighting and highlighting + // current line in different color, the lines cy (old cursor y) and + // view->cy need to be updated. Always update at least current line. + buffer_mark_lines_changed(buffer, s->cy, view->cy); + } + if (s->is_modified != buffer_modified(buffer)) { + mark_buffer_tabbars_changed(buffer); + } + } else { + e->window->update_tabbar = true; + mark_all_lines_changed(buffer); + } + + start_update(&e->terminal); + if (e->window->update_tabbar) { + update_term_title(&e->terminal, e->buffer, e->options.set_window_title); + } + update_buffer_windows(e, buffer); + update_command_line(e); + if (e->cursor_style_changed) { + update_cursor_style(e); + } + end_update(e); +} |
