diff options
| author | Albert Cervin <albert@acervin.com> | 2023-07-12 16:20:50 +0200 |
|---|---|---|
| committer | Albert Cervin <albert@acervin.com> | 2023-10-19 22:41:33 +0200 |
| commit | 54c9b4b533210b77be998f458ff96bdc54272f64 (patch) | |
| tree | eb434343bb1083172af50b7372d1e2745af00f8f /src/dged/window.c | |
| parent | 3a8ae83aa13636679c151027cace905fa87ebd8e (diff) | |
| download | dged-54c9b4b533210b77be998f458ff96bdc54272f64.tar.gz dged-54c9b4b533210b77be998f458ff96bdc54272f64.tar.xz dged-54c9b4b533210b77be998f458ff96bdc54272f64.zip | |
big buffer/buffer_view rework
A buffer is only the text and the corresponding operation. A buffer view
holds information about scroll, dot and mark positions. One way to think
about it is that a buffer is stateless whereas a buffer view is stateful.
Diffstat (limited to 'src/dged/window.c')
| -rw-r--r-- | src/dged/window.c | 216 |
1 files changed, 163 insertions, 53 deletions
diff --git a/src/dged/window.c b/src/dged/window.c index e928e42..91b1735 100644 --- a/src/dged/window.c +++ b/src/dged/window.c @@ -1,6 +1,7 @@ #include "binding.h" #include "btree.h" #include "buffer.h" +#include "buffer_view.h" #include "command.h" #include "display.h" #include "minibuffer.h" @@ -30,7 +31,7 @@ BINTREE_ENTRY_TYPE(window_node, struct window); static struct windows { BINTREE(window_node) windows; - struct window_node *active; + struct window *active; struct keymap keymap; } g_windows; @@ -61,7 +62,7 @@ void windows_init(uint32_t height, uint32_t width, .y = 0, }; BINTREE_SET_ROOT(&g_windows.windows, root_window); - g_windows.active = BINTREE_ROOT(&g_windows.windows); + g_windows.active = &BINTREE_VALUE(BINTREE_ROOT(&g_windows.windows)); } static void window_tree_clear_sub(struct window_node *root_node) { @@ -156,54 +157,160 @@ void windows_resize(uint32_t height, uint32_t width) { void windows_update(void *(*frame_alloc)(size_t), uint64_t frame_time) { struct window *w = &g_minibuffer_window; - w->commands = command_list_create(w->height * w->width, frame_alloc, w->x, - w->y, w->buffer_view.buffer->name); - buffer_update(&w->buffer_view, -1, w->width, w->height, w->commands, - frame_time, &w->relline, &w->relcol); + w->x = 0; + w->commands = command_list_create(10, frame_alloc, w->x, w->y, "mb-prompt"); + + // draw the prompt here to make it off-limits for the buffer/buffer view + uint32_t prompt_len = minibuffer_draw_prompt(w->commands); + w->x += prompt_len; + uint32_t width = prompt_len < w->width ? w->width - prompt_len : 1; + + struct command_list *inner_commands = command_list_create( + w->height * width, frame_alloc, w->x, w->y, "bufview-mb"); + + struct buffer_view_update_params p = { + .commands = inner_commands, + .window_id = -1, + .frame_time = frame_time, + .width = width, + .height = w->height, + .window_x = w->x, + .window_y = w->y, + .frame_alloc = frame_alloc, + }; + buffer_view_update(&w->buffer_view, &p); + command_list_draw_command_list(w->commands, inner_commands); if (g_popup_visible) { w = &g_popup_window; - w->commands = command_list_create(w->height * w->width, frame_alloc, w->x, - w->y, w->buffer_view.buffer->name); - buffer_update(&w->buffer_view, -1, w->width, w->height, w->commands, - frame_time, &w->relline, &w->relcol); - } - struct window_node *n = BINTREE_ROOT(&g_windows.windows); - BINTREE_FIRST(n); - uint32_t window_id = 0; - while (n != NULL) { - struct window *w = &BINTREE_VALUE(n); - if (w->type == Window_Buffer) { - w->commands = command_list_create(w->height * w->width, frame_alloc, w->x, - w->y, w->buffer_view.buffer->name); + const uint32_t hpadding = 1; + const uint32_t border_width = 1; + const uint32_t shadow_width = 1; - buffer_update(&w->buffer_view, window_id, w->width, w->height, - w->commands, frame_time, &w->relline, &w->relcol); + bool draw_padding = false, draw_borders = false; - ++window_id; + // first, make sure window fits + struct window *rw = root_window(); + uint32_t w_x = w->x; + uint32_t w_y = w->y; + uint32_t width = w_x + w->width > rw->width ? rw->width - w_x : w->width; + uint32_t height = + w_y + w->height > rw->height ? rw->height - w_y : w->height; + + // is there space for padding? + if (w_x > 1 && w_x + width + hpadding <= rw->width) { + draw_padding = true; + + --w_x; + width += hpadding * 2; } - BINTREE_NEXT(n); + // is there space for borders? + if (w_y > 1 && w_y + height <= rw->height && w_x > 1 && + w_x + width + border_width <= rw->width) { + draw_borders = true; + + w_x -= border_width; + // shift text upward + w_y -= border_width * 2; + height += border_width * 2; + width += border_width * 2; + } + + w->commands = command_list_create(height * width, frame_alloc, w_x, w_y, + "popup-decor"); + uint32_t x = 0, y = 0; + if (draw_borders) { + // top + command_list_draw_repeated(w->commands, x, y, 0x8c94e2, 1); + command_list_draw_repeated(w->commands, x + 1, y, 0x8094e2, + width - (border_width * 2)); + command_list_draw_repeated(w->commands, x + width - 1, y, 0x9094e2, 1); + + // sides + for (uint32_t line = y + 1; line < (height + y - border_width); ++line) { + command_list_draw_repeated(w->commands, x, line, 0x8294e2, + border_width); + command_list_draw_repeated(w->commands, x + width - border_width, line, + 0x8294e2, border_width); + } + + // bottom + command_list_draw_repeated(w->commands, x, y + height - border_width, + 0x9494e2, 1); + command_list_draw_repeated(w->commands, x + 1, y + height - border_width, + 0x8094e2, width - (border_width * 2)); + command_list_draw_repeated(w->commands, x + width - 1, + y + height - border_width, 0x9894e2, 1); + + x += border_width; + y += border_width; + } + + if (draw_padding) { + for (uint32_t line = y; line < w->height + y; ++line) { + command_list_draw_repeated(w->commands, x, line, ' ', hpadding); + command_list_draw_repeated(w->commands, w->width + x + 1, line, ' ', + hpadding); + } + x += border_width; + } + + // shadow + /*command_list_set_index_color_bg(w->commands, 236); + command_list_draw_repeated(w->commands, 1, w->height + vmargins, ' ', + w->width + margins * 2); for (uint32_t line = 1; line < w->height; ++line) { + command_list_draw_repeated(w->commands, w->width + margins * 2, line, ' ', + shadow_width); + }*/ + + struct command_list *inner = command_list_create( + w->height * w->width, frame_alloc, w_x + x, w_y + y, "bufview-popup"); + + struct buffer_view_update_params p = { + .commands = inner, + .window_id = -1, + .frame_time = frame_time, + .width = w->width, + .height = w->height, + .window_x = w_x + x, + .window_y = w_y + y, + .frame_alloc = frame_alloc, + }; + + buffer_view_update(&w->buffer_view, &p); + command_list_draw_command_list(w->commands, inner); } - // clear text props for next frame - n = BINTREE_ROOT(&g_windows.windows); + struct window_node *n = BINTREE_ROOT(&g_windows.windows); BINTREE_FIRST(n); - + uint32_t window_id = 0; while (n != NULL) { struct window *w = &BINTREE_VALUE(n); if (w->type == Window_Buffer) { - buffer_clear_text_properties(w->buffer_view.buffer); + char name[16]; + snprintf(name, 16, "bufview-%s", w->buffer_view.buffer->name); + w->commands = command_list_create(w->height * w->width, frame_alloc, w->x, + w->y, name); + + struct buffer_view_update_params p = { + .commands = w->commands, + .window_id = window_id, + .frame_time = frame_time, + .width = w->width, + .height = w->height, + .window_x = w->x, + .window_y = w->y, + .frame_alloc = frame_alloc, + }; + + buffer_view_update(&w->buffer_view, &p); + ++window_id; } BINTREE_NEXT(n); } - - buffer_clear_text_properties(g_minibuffer_window.buffer_view.buffer); - if (g_popup_visible) { - buffer_clear_text_properties(g_popup_window.buffer_view.buffer); - } } void windows_render(struct display *display) { @@ -238,13 +345,22 @@ struct window_node *find_window(struct window *window) { } void windows_set_active(struct window *window) { + if (window == minibuffer_window()) { + g_windows.active = minibuffer_window(); + return; + } + struct window_node *n = find_window(window); if (n != NULL) { - g_windows.active = n; + g_windows.active = &BINTREE_VALUE(n); } } struct window *window_find_by_buffer(struct buffer *b) { + if (b == window_buffer(minibuffer_window())) { + return minibuffer_window(); + } + struct window_node *n = BINTREE_ROOT(&g_windows.windows); BINTREE_FIRST(n); while (n != NULL) { @@ -259,7 +375,7 @@ struct window *window_find_by_buffer(struct buffer *b) { } struct window *windows_get_active() { - return &BINTREE_VALUE(g_windows.active); + return g_windows.active; } void window_set_buffer(struct window *window, struct buffer *buffer) { @@ -291,19 +407,6 @@ bool window_has_prev_buffer(struct window *window) { return window->prev_buffer != NULL; } -struct buffer_location window_cursor_location(struct window *window) { - return (struct buffer_location){ - .col = window->relcol, - .line = window->relline, - }; -} -struct buffer_location window_absolute_cursor_location(struct window *window) { - return (struct buffer_location){ - .col = window->x + window->relcol, - .line = window->y + window->relline, - }; -} - void window_close(struct window *window) { // do not want to delete last window if (window == root_window()) { @@ -397,8 +500,9 @@ void window_hsplit(struct window *window, struct window **new_window_a, new_window.type = Window_Buffer; new_window.buffer_view = buffer_view_create(w.buffer_view.buffer, true, true); - buffer_goto(&new_window.buffer_view, w.buffer_view.dot.line, - w.buffer_view.dot.col); + buffer_view_goto(&new_window.buffer_view, + (struct location){.line = w.buffer_view.dot.line, + .col = w.buffer_view.dot.col}); new_window.prev_buffer = w.prev_buffer; new_window.x = w.x; new_window.y = w.y + w.height; @@ -439,8 +543,10 @@ void window_vsplit(struct window *window, struct window **new_window_a, new_window.type = Window_Buffer; new_window.buffer_view = buffer_view_create(w.buffer_view.buffer, true, true); - buffer_goto(&new_window.buffer_view, w.buffer_view.dot.line, - w.buffer_view.dot.col); + buffer_view_goto(&new_window.buffer_view, + (struct location){.line = w.buffer_view.dot.line, + .col = w.buffer_view.dot.col}); + new_window.prev_buffer = w.prev_buffer; new_window.x = w.x + w.width; new_window.y = w.y; @@ -507,9 +613,13 @@ struct window *windows_focus(uint32_t id) { return NULL; } -uint32_t window_width(struct window *window) { return window->width; } +uint32_t window_width(const struct window *window) { return window->width; } + +uint32_t window_height(const struct window *window) { return window->height; } -uint32_t window_height(struct window *window) { return window->height; } +struct window_position window_position(const struct window *window) { + return (struct window_position){.x = window->x, .y = window->y}; +} void windows_show_popup(uint32_t row, uint32_t col, uint32_t width, uint32_t height) { |
