diff options
Diffstat (limited to 'examples/dte/screen-window.c')
| -rw-r--r-- | examples/dte/screen-window.c | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/examples/dte/screen-window.c b/examples/dte/screen-window.c new file mode 100644 index 0000000..aa3a96f --- /dev/null +++ b/examples/dte/screen-window.c @@ -0,0 +1,130 @@ +#include "screen.h" + +static void print_separator(Window *window, void *ud) +{ + Terminal *term = ud; + TermOutputBuffer *obuf = &term->obuf; + if (window->x + window->w == term->width) { + return; + } + for (int y = 0, h = window->h; y < h; y++) { + term_move_cursor(obuf, window->x + window->w, window->y + y); + term_add_byte(obuf, '|'); + } +} + +static void update_separators(Terminal *term, const ColorScheme *colors, const Frame *frame) +{ + set_builtin_color(term, colors, BC_STATUSLINE); + frame_for_each_window(frame, print_separator, term); +} + +static void update_line_numbers(Terminal *term, const ColorScheme *colors, Window *window, bool force) +{ + const View *view = window->view; + size_t lines = view->buffer->nl; + int x = window->x; + + calculate_line_numbers(window); + long first = view->vy + 1; + long last = MIN(view->vy + window->edit_h, lines); + + if ( + !force + && window->line_numbers.first == first + && window->line_numbers.last == last + ) { + return; + } + + window->line_numbers.first = first; + window->line_numbers.last = last; + + TermOutputBuffer *obuf = &term->obuf; + char buf[DECIMAL_STR_MAX(unsigned long) + 1]; + size_t width = window->line_numbers.width; + BUG_ON(width > sizeof(buf)); + BUG_ON(width < LINE_NUMBERS_MIN_WIDTH); + term_output_reset(term, window->x, window->w, 0); + set_builtin_color(term, colors, BC_LINENUMBER); + + for (int y = 0, h = window->edit_h, edit_y = window->edit_y; y < h; y++) { + unsigned long line = view->vy + y + 1; + memset(buf, ' ', width); + if (line <= lines) { + size_t i = width - 2; + do { + buf[i--] = (line % 10) + '0'; + } while (line /= 10); + } + term_move_cursor(obuf, x, edit_y + y); + term_add_bytes(obuf, buf, width); + } +} + +static void update_window_full(Window *window, void* UNUSED_ARG(data)) +{ + EditorState *e = window->editor; + View *view = window->view; + view_update_cursor_x(view); + view_update_cursor_y(view); + view_update(view, e->options.scroll_margin); + if (e->options.tab_bar) { + print_tabbar(&e->terminal, &e->colors, window); + } + if (e->options.show_line_numbers) { + update_line_numbers(&e->terminal, &e->colors, window, true); + } + update_range(e, view, view->vy, view->vy + window->edit_h); + update_status_line(window); +} + +void update_all_windows(EditorState *e) +{ + update_window_sizes(&e->terminal, e->root_frame); + frame_for_each_window(e->root_frame, update_window_full, NULL); + update_separators(&e->terminal, &e->colors, e->root_frame); +} + +static void update_window(EditorState *e, Window *window) +{ + if (e->options.tab_bar && window->update_tabbar) { + print_tabbar(&e->terminal, &e->colors, window); + } + + const View *view = window->view; + if (e->options.show_line_numbers) { + // Force updating lines numbers if all lines changed + bool force = (view->buffer->changed_line_max == LONG_MAX); + update_line_numbers(&e->terminal, &e->colors, window, force); + } + + long y1 = MAX(view->buffer->changed_line_min, view->vy); + long y2 = MIN(view->buffer->changed_line_max, view->vy + window->edit_h - 1); + update_range(e, view, y1, y2 + 1); + update_status_line(window); +} + +// Update all visible views containing this buffer +void update_buffer_windows(EditorState *e, const Buffer *buffer) +{ + const View *current_view = e->view; + for (size_t i = 0, n = buffer->views.count; i < n; i++) { + View *view = buffer->views.ptrs[i]; + if (view != view->window->view) { + // Not visible + continue; + } + if (view != current_view) { + // Restore cursor + view->cursor.blk = BLOCK(view->buffer->blocks.next); + block_iter_goto_offset(&view->cursor, view->saved_cursor_offset); + + // These have already been updated for current view + view_update_cursor_x(view); + view_update_cursor_y(view); + view_update(view, e->options.scroll_margin); + } + update_window(e, view->window); + } +} |
