summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlbert Cervin <albert@acervin.com>2022-12-15 18:06:59 +0100
committerAlbert Cervin <albert@acervin.com>2022-12-15 18:06:59 +0100
commitd931b14863838a8dceed8cd95c71a75a271cca6b (patch)
tree64e1afa0b4849628f47f29d5cdb192fd0db63240
parenta73225c9b45e110d315a3fc587a82040ce8c9a13 (diff)
downloaddged-d931b14863838a8dceed8cd95c71a75a271cca6b.tar.gz
dged-d931b14863838a8dceed8cd95c71a75a271cca6b.tar.xz
dged-d931b14863838a8dceed8cd95c71a75a271cca6b.zip
Make minibuffer use an actual buffer
Also fix some issues with inserting multibyte chars.
-rw-r--r--src/buffer.c76
-rw-r--r--src/buffer.h29
-rw-r--r--src/command.c11
-rw-r--r--src/command.h5
-rw-r--r--src/display.c8
-rw-r--r--src/display.h3
-rw-r--r--src/main.c143
-rw-r--r--src/minibuffer.c77
-rw-r--r--src/minibuffer.h22
-rw-r--r--src/text.c10
-rw-r--r--src/text.h5
-rw-r--r--test/buffer.c2
12 files changed, 258 insertions, 133 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();
diff --git a/src/main.c b/src/main.c
index 92e84d1..a1d26e5 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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, &current);
- 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, ...);
diff --git a/src/text.c b/src/text.c
index 952f4ce..97163a5 100644
--- a/src/text.c
+++ b/src/text.c
@@ -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) {
diff --git a/src/text.h b/src/text.h
index 708ef09..e6f681a 100644
--- a/src/text.h
+++ b/src/text.h
@@ -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);
diff --git a/test/buffer.c b/test/buffer.c
index d7d9b0b..42d476c 100644
--- a/test/buffer.c
+++ b/test/buffer.c
@@ -6,7 +6,7 @@
#include <string.h>
void test_move() {
- struct buffer b = buffer_create("test-buffer");
+ struct buffer b = buffer_create("test-buffer", false);
ASSERT(b.dot_col == 0 && b.dot_line == 0,
"Expected dot to be at buffer start");