diff options
| author | Albert Cervin <albert@acervin.com> | 2022-12-15 18:06:59 +0100 |
|---|---|---|
| committer | Albert Cervin <albert@acervin.com> | 2022-12-15 18:06:59 +0100 |
| commit | d931b14863838a8dceed8cd95c71a75a271cca6b (patch) | |
| tree | 64e1afa0b4849628f47f29d5cdb192fd0db63240 /src | |
| parent | a73225c9b45e110d315a3fc587a82040ce8c9a13 (diff) | |
| download | dged-d931b14863838a8dceed8cd95c71a75a271cca6b.tar.gz dged-d931b14863838a8dceed8cd95c71a75a271cca6b.tar.xz dged-d931b14863838a8dceed8cd95c71a75a271cca6b.zip | |
Make minibuffer use an actual buffer
Also fix some issues with inserting multibyte chars.
Diffstat (limited to 'src')
| -rw-r--r-- | src/buffer.c | 76 | ||||
| -rw-r--r-- | src/buffer.h | 29 | ||||
| -rw-r--r-- | src/command.c | 11 | ||||
| -rw-r--r-- | src/command.h | 5 | ||||
| -rw-r--r-- | src/display.c | 8 | ||||
| -rw-r--r-- | src/display.h | 3 | ||||
| -rw-r--r-- | src/main.c | 143 | ||||
| -rw-r--r-- | src/minibuffer.c | 77 | ||||
| -rw-r--r-- | src/minibuffer.h | 22 | ||||
| -rw-r--r-- | src/text.c | 10 | ||||
| -rw-r--r-- | src/text.h | 5 |
11 files changed, 257 insertions, 132 deletions
diff --git a/src/buffer.c b/src/buffer.c index 14d1b32..4e955e6 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -1,7 +1,5 @@ #include "buffer.h" #include "binding.h" -#include "bits/stdint-intn.h" -#include "bits/stdint-uintn.h" #include "display.h" #include "minibuffer.h" #include "reactor.h" @@ -14,18 +12,22 @@ #include <time.h> #include <unistd.h> -struct buffer buffer_create(const char *name) { +struct buffer buffer_create(const char *name, bool modeline) { struct buffer b = (struct buffer){.filename = NULL, .name = name, .text = text_create(10), .dot_col = 0, .dot_line = 0, - .modeline_buf = (uint8_t *)malloc(1024), + .modeline_buf = modeline ? (uint8_t *)malloc(1024) : NULL, .keymaps = calloc(10, sizeof(struct keymap)), .nkeymaps = 1, .scroll_col = 0, .scroll_line = 0, + .npre_update_hooks = 0, + .pre_update_hooks = {0}, + .npost_update_hooks = 0, + .post_update_hooks = {0}, .nkeymaps_max = 10}; b.keymaps[0] = keymap_create("buffer-default", 128); @@ -55,6 +57,16 @@ void buffer_destroy(struct buffer *buffer) { free(buffer->text); } +void buffer_clear(struct buffer *buffer) { + text_clear(buffer->text); + buffer->dot_col = buffer->dot_line = 0; +} + +bool buffer_is_empty(struct buffer *buffer) { + return text_num_lines(buffer->text) == 0 && + text_line_size(buffer->text, 0) == 0; +} + uint32_t buffer_keymaps(struct buffer *buffer, struct keymap **keymaps_out) { *keymaps_out = buffer->keymaps; return buffer->nkeymaps; @@ -127,7 +139,7 @@ void buffer_end_of_line(struct buffer *buffer) { void buffer_beginning_of_line(struct buffer *buffer) { buffer->dot_col = 0; } struct buffer buffer_from_file(const char *filename, struct reactor *reactor) { - struct buffer b = buffer_create(filename); + struct buffer b = buffer_create(filename, true); b.filename = filename; if (access(b.filename, F_OK) == 0) { FILE *file = fopen(filename, "r"); @@ -192,6 +204,29 @@ void buffer_newline(struct buffer *buffer) { buffer_add_text(buffer, (uint8_t *)"\n", 1); } +uint32_t buffer_add_pre_update_hook(struct buffer *buffer, + pre_update_hook hook) { + buffer->pre_update_hooks[buffer->npre_update_hooks] = hook; + ++buffer->npre_update_hooks; + + return buffer->npre_update_hooks - 1; +} +uint32_t buffer_add_post_update_hook(struct buffer *buffer, + post_update_hook hook) { + buffer->post_update_hooks[buffer->npost_update_hooks] = hook; + ++buffer->npost_update_hooks; + + return buffer->npost_update_hooks - 1; +} + +void buffer_remove_pre_update_hook(struct buffer *buffer, uint32_t hook_id) { + // TODO: is it needed? +} + +void buffer_remove_post_update_hook(struct buffer *buffer, uint32_t hook_id) { + // TODO: is it needed? +} + bool modeline_update(struct buffer *buffer, uint32_t width, uint64_t frame_time) { char buf[width * 4]; @@ -263,13 +298,29 @@ void to_relative(struct buffer *buffer, uint32_t line, uint32_t col, *rel_line = (int64_t)line - (int64_t)buffer->scroll_line; } +void buffer_relative_dot_pos(struct buffer *buffer, uint32_t *relline, + uint32_t *relcol) { + int64_t rel_col, rel_line; + to_relative(buffer, buffer->dot_line, buffer->dot_col, &rel_line, &rel_col); + + *relline = rel_line < 0 ? 0 : (uint32_t)rel_line; + *relcol = rel_col < 0 ? 0 : (uint32_t)rel_col; +} + struct buffer_update buffer_update(struct buffer *buffer, uint32_t width, uint32_t height, alloc_fn frame_alloc, - struct reactor *reactor, uint64_t frame_time) { + if (width == 0 || height == 0) { + return (struct buffer_update){.cmds = NULL, .ncmds = 0}; + } + + for (uint32_t hooki = 0; hooki < buffer->npre_update_hooks; ++hooki) { + buffer->pre_update_hooks[hooki](buffer); + } + // reserve space for modeline - uint32_t bufheight = height - 1; + uint32_t bufheight = buffer->modeline_buf != NULL ? height - 1 : height; int64_t rel_line, rel_col; to_relative(buffer, buffer->dot_line, buffer->dot_col, &rel_line, &rel_col); @@ -312,7 +363,8 @@ struct buffer_update buffer_update(struct buffer *buffer, uint32_t width, ++ncmds; } - if (modeline_update(buffer, width, frame_time)) { + if (buffer->modeline_buf != NULL && + modeline_update(buffer, width, frame_time)) { cmds[ncmds] = (struct render_cmd){ .col = 0, .row = bufheight, @@ -322,12 +374,12 @@ struct buffer_update buffer_update(struct buffer *buffer, uint32_t width, ++ncmds; } + for (uint32_t hooki = 0; hooki < buffer->npost_update_hooks; ++hooki) { + buffer->post_update_hooks[hooki](buffer); + } + struct buffer_update upd = (struct buffer_update){.cmds = cmds, .ncmds = ncmds}; - int64_t new_line, new_col; - to_relative(buffer, buffer->dot_line, buffer->dot_col, &new_line, &new_col); - upd.dot_line = (uint32_t)new_line; - upd.dot_col = (uint32_t)new_col; return upd; } diff --git a/src/buffer.h b/src/buffer.h index 92cc353..e20e40a 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -8,6 +8,9 @@ struct keymap; struct reactor; +typedef void (*pre_update_hook)(struct buffer *); +typedef void (*post_update_hook)(struct buffer *); + struct buffer { const char *name; const char *filename; @@ -26,24 +29,29 @@ struct buffer { uint32_t scroll_line; uint32_t scroll_col; + + pre_update_hook pre_update_hooks[32]; + uint32_t npre_update_hooks; + post_update_hook post_update_hooks[32]; + uint32_t npost_update_hooks; }; struct buffer_update { struct render_cmd *cmds; uint64_t ncmds; - uint32_t dot_col; - uint32_t dot_line; }; typedef void *(alloc_fn)(size_t); -struct buffer buffer_create(const char *name); +struct buffer buffer_create(const char *name, bool modeline); void buffer_destroy(struct buffer *buffer); uint32_t buffer_keymaps(struct buffer *buffer, struct keymap **keymaps_out); void buffer_add_keymap(struct buffer *buffer, struct keymap *keymap); int buffer_add_text(struct buffer *buffer, uint8_t *text, uint32_t nbytes); +void buffer_clear(struct buffer *buffer); +bool buffer_is_empty(struct buffer *buffer); void buffer_forward_delete_char(struct buffer *buffer); void buffer_backward_delete_char(struct buffer *buffer); @@ -55,18 +63,21 @@ void buffer_end_of_line(struct buffer *buffer); void buffer_beginning_of_line(struct buffer *buffer); void buffer_newline(struct buffer *buffer); -uint32_t buffer_add_pre_update_hook(struct buffer *buffer); -uint32_t buffer_add_post_update_hook(struct buffer *buffer); -uint32_t buffer_remove_pre_update_hook(struct buffer *buffer, uint32_t hook_id); -uint32_t buffer_remove_post_update_hook(struct buffer *buffer, - uint32_t hook_id); +void buffer_relative_dot_pos(struct buffer *buffer, uint32_t *relline, + uint32_t *relcol); + +uint32_t buffer_add_pre_update_hook(struct buffer *buffer, + pre_update_hook hook); +uint32_t buffer_add_post_update_hook(struct buffer *buffer, + post_update_hook hook); +void buffer_remove_pre_update_hook(struct buffer *buffer, uint32_t hook_id); +void buffer_remove_post_update_hook(struct buffer *buffer, uint32_t hook_id); struct buffer buffer_from_file(const char *filename, struct reactor *reactor); void buffer_to_file(struct buffer *buffer); struct buffer_update buffer_update(struct buffer *buffer, uint32_t width, uint32_t height, alloc_fn frame_alloc, - struct reactor *reactor, uint64_t frame_time); // commands diff --git a/src/command.c b/src/command.c index 4b233b2..fcf53e2 100644 --- a/src/command.c +++ b/src/command.c @@ -64,3 +64,14 @@ struct command *lookup_command_by_hash(struct commands *commands, return NULL; } + +int32_t execute_command(struct command *command, struct buffer *current_buffer, + int argc, const char *argv[]) { + + command->fn((struct command_ctx){.current_buffer = current_buffer, + .userdata = command->userdata}, + argc, argv); + + // TODO + return 0; +} diff --git a/src/command.h b/src/command.h index 3e3bbfb..b02c74a 100644 --- a/src/command.h +++ b/src/command.h @@ -4,6 +4,7 @@ struct buffer; struct command_ctx { struct buffer *current_buffer; + void *userdata; }; typedef void (*command_fn)(struct command_ctx ctx, int argc, @@ -12,6 +13,7 @@ typedef void (*command_fn)(struct command_ctx ctx, int argc, struct command { const char *name; command_fn fn; + void *userdata; }; struct hashed_command { @@ -32,6 +34,9 @@ uint32_t register_command(struct commands *commands, struct command *command); void register_commands(struct commands *command_list, struct command *commands, uint32_t ncommands); +int32_t execute_command(struct command *command, struct buffer *current_buffer, + int argc, const char *argv[]); + uint32_t hash_command_name(const char *name); struct command *lookup_command(struct commands *commands, const char *name); diff --git a/src/display.c b/src/display.c index 7f35907..b382ea1 100644 --- a/src/display.c +++ b/src/display.c @@ -87,12 +87,14 @@ void delete_to_eol() { void display_update(struct display *display, struct render_cmd_buf *cmd_bufs, uint32_t ncmd_bufs, uint32_t currow, uint32_t curcol) { for (uint32_t bufi = 0; bufi < ncmd_bufs; ++bufi) { - uint64_t ncmds = cmd_bufs[bufi].ncmds; - struct render_cmd *cmds = cmd_bufs[bufi].cmds; + struct render_cmd_buf *buf = &cmd_bufs[bufi]; + uint64_t ncmds = buf->ncmds; + struct render_cmd *cmds = buf->cmds; for (uint64_t cmdi = 0; cmdi < ncmds; ++cmdi) { struct render_cmd *cmd = &cmds[cmdi]; - display_move_cursor(display, cmd->row, cmd->col); + display_move_cursor(display, cmd->row + buf->yoffset, + cmd->col + buf->xoffset); putbytes(cmd->data, cmd->len); delete_to_eol(); } diff --git a/src/display.h b/src/display.h index 1132dd8..088a487 100644 --- a/src/display.h +++ b/src/display.h @@ -18,9 +18,10 @@ struct render_cmd { }; struct render_cmd_buf { - char source[16]; struct render_cmd *cmds; uint64_t ncmds; + uint32_t xoffset; + uint32_t yoffset; }; struct display display_create(); @@ -1,4 +1,3 @@ -#include <assert.h> #include <locale.h> #include <signal.h> #include <stdbool.h> @@ -52,15 +51,20 @@ void _abort(struct command_ctx ctx, int argc, const char *argv[]) { } void unimplemented_command(struct command_ctx ctx, int argc, - const char *argv[]) {} + const char *argv[]) { + minibuffer_echo("TODO: %s is not implemented", (const char *)ctx.userdata); +} void exit_editor(struct command_ctx ctx, int argc, const char *argv[]) { terminate(); } -static struct command GLOBAL_COMMANDS[] = { - {.name = "find-file", .fn = unimplemented_command}, - {.name = "abort", .fn = _abort}, - {.name = "exit", .fn = exit_editor}}; +static struct command GLOBAL_COMMANDS[] = {{ + .name = "find-file", + .fn = unimplemented_command, + .userdata = (void *)"find-file", + }, + {.name = "abort", .fn = _abort}, + {.name = "exit", .fn = exit_editor}}; uint64_t calc_frame_time_ns(struct timespec *timers, uint32_t num_timer_pairs) { uint64_t total = 0; @@ -76,6 +80,41 @@ uint64_t calc_frame_time_ns(struct timespec *timers, uint32_t num_timer_pairs) { return total; } +struct buffers { + // TODO: more buffers + struct buffer buffers[32]; + uint32_t nbuffers; +}; + +struct window { + uint32_t x; + uint32_t y; + uint32_t width; + uint32_t height; + struct buffer *buffer; +}; + +struct buffer_update window_update_buffer(struct window *window, + uint64_t frame_time) { + return buffer_update(window->buffer, window->width, window->height, + frame_alloc, frame_time); +} + +void buffers_init(struct buffers *buffers) { buffers->nbuffers = 0; } + +void buffers_add(struct buffers *buffers, struct buffer buffer) { + buffers->buffers[buffers->nbuffers] = buffer; + ++buffers->nbuffers; +} + +void buffers_destroy(struct buffers *buffers) { + for (uint32_t bufi = 0; bufi < buffers->nbuffers; ++bufi) { + buffer_destroy(&buffers->buffers[bufi]); + } + + buffers->nbuffers = 0; +} + int main(int argc, char *argv[]) { const char *filename = NULL; if (argc >= 1) { @@ -111,18 +150,21 @@ int main(int argc, char *argv[]) { struct keymap ctrlx_map = keymap_create("c-x", 32); struct binding global_binds[] = { PREFIX(Ctrl, 'X', &ctrlx_map), + BINDING(Ctrl, 'G', "abort"), }; struct binding ctrlx_bindings[] = { BINDING(Ctrl, 'C', "exit"), - BINDING(Ctrl, 'G', "abort"), BINDING(Ctrl, 'S', "buffer-write-to-file"), + BINDING(Ctrl, 'F', "find-file"), }; keymap_bind_keys(&global_keymap, global_binds, sizeof(global_binds) / sizeof(global_binds[0])); keymap_bind_keys(&ctrlx_map, ctrlx_bindings, sizeof(ctrlx_bindings) / sizeof(ctrlx_bindings[0])); - struct buffer curbuf = buffer_create("welcome"); + struct buffers buflist = {0}; + buffers_init(&buflist); + struct buffer curbuf = buffer_create("welcome", true); if (filename != NULL) { curbuf = buffer_from_file(filename, &reactor); } else { @@ -130,41 +172,68 @@ int main(int argc, char *argv[]) { buffer_add_text(&curbuf, (uint8_t *)welcome_txt, strlen(welcome_txt)); } - minibuffer_init(display.height - 1); + buffers_add(&buflist, curbuf); + + // one main window + struct window main_window = (struct window){ + .buffer = &curbuf, + .height = display.height - 1, + .width = display.width, + .x = 0, + .y = 0, + }; + + // and one for the minibuffer + struct buffer minibuffer = buffer_create("minibuffer", false); + buffers_add(&buflist, minibuffer); + + minibuffer_init(&minibuffer); + struct window minibuffer_window = (struct window){ + .buffer = &minibuffer, + .x = 0, + .y = display.height - 1, + .height = 1, + .width = display.width, + }; struct timespec buffer_begin, buffer_end, display_begin, display_end, keyboard_begin, keyboard_end; uint64_t frame_time = 0; - struct render_cmd_buf render_bufs[2] = { - {.source = "minibuffer"}, - {.source = "buffer"}, + struct render_cmd_buf render_bufs[2] = {0}; + + struct window *windows[2] = { + &minibuffer_window, + &main_window, }; + // TODO: not always + struct window *active_window = &main_window; + while (running) { clock_gettime(CLOCK_MONOTONIC, &buffer_begin); - // update minibuffer - struct minibuffer_update minibuf_upd = minibuffer_update(frame_alloc); - render_bufs[0].cmds = minibuf_upd.cmds; - render_bufs[0].ncmds = minibuf_upd.ncmds; - - // update current buffer - struct buffer_update buf_upd = - buffer_update(&curbuf, display.width, display.height - 1, frame_alloc, - &reactor, frame_time); - render_bufs[1].cmds = buf_upd.cmds; - render_bufs[1].ncmds = buf_upd.ncmds; + // update windows + uint32_t dot_line = 0, dot_col = 0; + for (uint32_t windowi = 0; windowi < 2; ++windowi) { + struct window *win = windows[windowi]; + struct buffer_update buf_upd = window_update_buffer(win, frame_time); + render_bufs[windowi].cmds = buf_upd.cmds; + render_bufs[windowi].ncmds = buf_upd.ncmds; + render_bufs[windowi].xoffset = win->x; + render_bufs[windowi].yoffset = win->y; + } clock_gettime(CLOCK_MONOTONIC, &buffer_end); // update screen clock_gettime(CLOCK_MONOTONIC, &display_begin); + uint32_t relline, relcol; + buffer_relative_dot_pos(active_window->buffer, &relline, &relcol); if (render_bufs[0].ncmds > 0 || render_bufs[1].ncmds > 0) { - display_update(&display, render_bufs, 2, buf_upd.dot_line, - buf_upd.dot_col); + display_update(&display, render_bufs, 2, relline, relcol); } clock_gettime(CLOCK_MONOTONIC, &display_end); @@ -175,6 +244,10 @@ int main(int argc, char *argv[]) { struct keymap *local_keymaps = NULL; uint32_t nbuffer_keymaps = buffer_keymaps(&curbuf, &local_keymaps); struct keyboard_update kbd_upd = keyboard_update(&kbd, &reactor); + + // buffer up chars to handle utf-8 "correctly" + uint8_t chars[kbd_upd.nkeys]; + uint8_t nchars; for (uint32_t ki = 0; ki < kbd_upd.nkeys; ++ki) { struct key *k = &kbd_upd.keys[ki]; @@ -190,11 +263,13 @@ int main(int argc, char *argv[]) { } if (res.found) { + if (nchars > 0) { + buffer_add_text(active_window->buffer, chars, nchars); + nchars = 0; + } switch (res.type) { case BindingType_Command: { - const char *argv[] = {}; - res.command->fn((struct command_ctx){.current_buffer = &curbuf}, 0, - argv); + execute_command(res.command, active_window->buffer, 0, NULL); current_keymap = NULL; break; } @@ -207,12 +282,21 @@ int main(int argc, char *argv[]) { } } } else if (current_keymap != NULL) { + if (nchars > 0) { + buffer_add_text(active_window->buffer, chars, nchars); + nchars = 0; + } minibuffer_echo_timeout(4, "key is not bound!"); current_keymap = NULL; } else { - buffer_add_text(&curbuf, &k->c, 1); + chars[nchars] = k->c; + ++nchars; } } + if (nchars > 0) { + buffer_add_text(active_window->buffer, chars, nchars); + nchars = 0; + } clock_gettime(CLOCK_MONOTONIC, &keyboard_end); // calculate frame time @@ -223,6 +307,7 @@ int main(int argc, char *argv[]) { frame_allocator_clear(&frame_allocator); } + buffers_destroy(&buflist); display_clear(&display); display_destroy(&display); keymap_destroy(&global_keymap); diff --git a/src/minibuffer.c b/src/minibuffer.c index 4e6e3b7..649413b 100644 --- a/src/minibuffer.c +++ b/src/minibuffer.c @@ -1,77 +1,38 @@ #include "minibuffer.h" +#include "buffer.h" #include "display.h" #include <stdarg.h> #include <stdio.h> #include <stdlib.h> -static struct minibuffer g_minibuffer = {0}; - -void minibuffer_init(uint32_t row) { - g_minibuffer.buffer = malloc(4096); - g_minibuffer.capacity = 4096; - g_minibuffer.nbytes = 0; - g_minibuffer.row = row; - g_minibuffer.dirty = false; -} - -void minibuffer_destroy() { - free(g_minibuffer.buffer); - g_minibuffer.capacity = 0; - g_minibuffer.dirty = false; -} - -struct minibuffer_update minibuffer_update(alloc_fn frame_alloc) { - // TODO: multiline - if (g_minibuffer.nbytes == 0 && !g_minibuffer.dirty) { - return (struct minibuffer_update){.cmds = NULL, .ncmds = 0}; - } +static struct minibuffer { + struct buffer *buffer; + struct timespec expires; +} g_minibuffer = {0}; +void update(struct buffer *buffer) { struct timespec current; clock_gettime(CLOCK_MONOTONIC, ¤t); - if (current.tv_sec < g_minibuffer.expires.tv_sec) { - struct render_cmd *cmds = - (struct render_cmd *)frame_alloc(sizeof(struct render_cmd)); - - cmds[0].col = 0; - cmds[0].row = g_minibuffer.row; - cmds[0].data = g_minibuffer.buffer; - cmds[0].len = g_minibuffer.nbytes; - - g_minibuffer.dirty = false; - - return (struct minibuffer_update){ - .cmds = cmds, - .ncmds = 1, - }; - } else { - g_minibuffer.nbytes = 0; - g_minibuffer.dirty = false; - // send a clear draw command - struct render_cmd *cmds = - (struct render_cmd *)frame_alloc(sizeof(struct render_cmd)); - - cmds[0].col = 0; - cmds[0].row = g_minibuffer.row; - cmds[0].data = NULL; - cmds[0].len = 0; - - return (struct minibuffer_update){ - .cmds = cmds, - .ncmds = 1, - }; + if (current.tv_sec >= g_minibuffer.expires.tv_sec) { + buffer_clear(buffer); } } +void minibuffer_init(struct buffer *buffer) { + g_minibuffer.buffer = buffer; + buffer_add_pre_update_hook(g_minibuffer.buffer, update); +} + void echo(uint32_t timeout, const char *fmt, va_list args) { - size_t nbytes = - vsnprintf((char *)g_minibuffer.buffer, g_minibuffer.capacity, fmt, args); + char buff[2048]; + size_t nbytes = vsnprintf(buff, 2048, fmt, args); // vsnprintf returns how many characters it would have wanted to write in case // of overflow - g_minibuffer.nbytes = - nbytes > g_minibuffer.capacity ? g_minibuffer.capacity : nbytes; - g_minibuffer.dirty = true; + buffer_clear(g_minibuffer.buffer); + buffer_add_text(g_minibuffer.buffer, (uint8_t *)buff, + nbytes > 2048 ? 2048 : nbytes); clock_gettime(CLOCK_MONOTONIC, &g_minibuffer.expires); g_minibuffer.expires.tv_sec += timeout; @@ -91,5 +52,5 @@ void minibuffer_echo_timeout(uint32_t timeout, const char *fmt, ...) { va_end(args); } -bool minibuffer_displaying() { return g_minibuffer.nbytes > 0; } +bool minibuffer_displaying() { return !buffer_is_empty(g_minibuffer.buffer); } void minibuffer_clear() { g_minibuffer.expires.tv_nsec = 0; } diff --git a/src/minibuffer.h b/src/minibuffer.h index 55eeb7e..9bdde8f 100644 --- a/src/minibuffer.h +++ b/src/minibuffer.h @@ -3,26 +3,8 @@ #include <stdint.h> #include <time.h> -struct minibuffer_update { - struct render_cmd *cmds; - uint64_t ncmds; -}; - -struct minibuffer { - uint8_t *buffer; - uint32_t capacity; - uint32_t nbytes; - uint32_t row; - bool dirty; - struct timespec expires; -}; - -typedef void *(alloc_fn)(size_t); - -void minibuffer_init(uint32_t row); -void minibuffer_destroy(); - -struct minibuffer_update minibuffer_update(alloc_fn frame_alloc); +struct buffer; +void minibuffer_init(struct buffer *buffer); void minibuffer_echo(const char *fmt, ...); void minibuffer_echo_timeout(uint32_t timeout, const char *fmt, ...); @@ -48,6 +48,16 @@ void text_destroy(struct text *text) { free(text->lines); } +void text_clear(struct text *text) { + for (uint32_t li = 0; li < text->nlines; ++li) { + text->lines[li].flags = 0; + text->lines[li].nbytes = 0; + text->lines[li].nchars = 0; + } + + text->nlines = 1; +} + // given `char_idx` as a character index, return the byte index uint32_t charidx_to_byteidx(struct line *line, uint32_t char_idx) { if (char_idx > line->nchars) { @@ -10,6 +10,11 @@ struct render_cmd; struct text *text_create(uint32_t initial_capacity); void text_destroy(struct text *text); +/** + * Clear the text without reclaiming memory + */ +void text_clear(struct text *text); + void text_append(struct text *text, uint32_t line, uint32_t col, uint8_t *bytes, uint32_t nbytes, uint32_t *lines_added, uint32_t *cols_added); |
