summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2020-12-20 20:25:55 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2020-12-20 20:25:55 -0500
commit4f5cee291bb3a5e06a63dc28bf3757c9af49c250 (patch)
tree705b189e1e6efc931108d9786a6bbc0824cd6063
parent143bbfc133e1a189c9f99cfffe41c4397b677f39 (diff)
more undo
-rw-r--r--buffer.c113
1 files changed, 22 insertions, 91 deletions
diff --git a/buffer.c b/buffer.c
index d8cb6fe..54c6dbe 100644
--- a/buffer.c
+++ b/buffer.c
@@ -18,18 +18,17 @@ typedef struct {
} Line;
typedef enum {
- BUFFER_EDIT_DELETE_LINE, // line = line #, prev_str = contents of line before it was deleted
- BUFFER_EDIT_INSERT_LINE, // line = line #
- BUFFER_EDIT_CHANGE_LINE // line = line #, prev_str = contents of line before change
+ BUFFER_EDIT_DELETE_TEXT, // text = deleted text, text_len = length of text deleted, pos = where text was deleted (first character)
+ BUFFER_EDIT_INSERT_TEXT // text unused, text_len = length of text inserted, pos = where text was inserted (first character)
+ // (we don't need to know what text was inserted for BUFFER_EDIT_INSERT_TEXT, since it'll be right there)
} BufferEditType;
typedef struct BufferEdit {
- u8 type;
- bool join_with_next;
- u32 prev_str_len;
- u32 line;
struct BufferEdit *next;
- char32_t prev_str[];
+ BufferEditType type;
+ BufferPos pos;
+ u32 text_len;
+ char32_t text[];
} BufferEdit;
typedef struct {
@@ -74,8 +73,8 @@ void buffer_create(TextBuffer *buffer, Font *font) {
}
// this is a macro so we get -Wformat warnings
-#define buffer_seterr(buffer, fmt, ...) \
- snprintf(buffer->error, sizeof buffer->error - 1, fmt, ##__VA_ARGS__)
+#define buffer_seterr(buffer, ...) \
+ snprintf(buffer->error, sizeof buffer->error - 1, __VA_ARGS__)
bool buffer_haserr(TextBuffer *buffer) {
return buffer->error[0] != '\0';
@@ -108,43 +107,17 @@ static void *buffer_realloc(TextBuffer *buffer, void *p, size_t new_size) {
return ret;
}
-static WarnUnusedResult BufferEdit *buffer_edit_delete_line(TextBuffer *buffer, u32 line, char32_t const *prev_str, u32 prev_str_len, bool join_with_next) {
- BufferEdit *e = buffer_calloc(buffer, 1, sizeof *e + prev_str_len * sizeof *prev_str);
- if (e) {
- e->type = BUFFER_EDIT_DELETE_LINE;
- e->line = line;
- e->join_with_next = join_with_next;
- e->prev_str_len = prev_str_len;
- memcpy(e->prev_str, prev_str, prev_str_len * sizeof *prev_str);
- }
- return e;
+// functions for creating buffer edits:
+// call these before you make an edit to keep an undo event
+static WarnUnusedResult BufferEdit *buffer_edit_delete_text(TextBuffer *buffer, BufferPos start, u32 len) {
+ // @TODO
}
-static WarnUnusedResult BufferEdit *buffer_edit_insert_line(TextBuffer *buffer, u32 line, bool join_with_next) {
- BufferEdit *e = buffer_calloc(buffer, 1, sizeof *e);
- if (e) {
- e->type = BUFFER_EDIT_INSERT_LINE;
- e->line = line;
- e->join_with_next = join_with_next;
- }
- return e;
-}
-static WarnUnusedResult BufferEdit *buffer_edit_change_line(TextBuffer *buffer, u32 line, char32_t const *prev_str, u32 prev_str_len, bool join_with_next) {
- BufferEdit *e = buffer_calloc(buffer, 1, sizeof *e + prev_str_len * sizeof *prev_str);
- if (e) {
- e->type = BUFFER_EDIT_CHANGE_LINE;
- e->line = line;
- e->join_with_next = join_with_next;
- e->prev_str_len = prev_str_len;
- memcpy(e->prev_str, prev_str, prev_str_len * sizeof *prev_str);
- }
- return e;
-}
// grow capacity of line to at least minimum_capacity
// returns true if allocation was succesful
-static Status buffer_line_grow(TextBuffer *buffer, Line *line, u32 minimum_capacity) {
+static Status buffer_line_set_min_capacity(TextBuffer *buffer, Line *line, u32 minimum_capacity) {
while (line->capacity < minimum_capacity) {
// double capacity of line
u32 new_capacity = line->capacity == 0 ? 4 : line->capacity * 2;
@@ -167,7 +140,7 @@ static Status buffer_line_grow(TextBuffer *buffer, Line *line, u32 minimum_capac
// grow capacity of buffer->lines array
// returns true if successful
-static Status buffer_lines_grow(TextBuffer *buffer, u32 minimum_capacity) {
+static Status buffer_lines_set_min_capacity(TextBuffer *buffer, u32 minimum_capacity) {
while (minimum_capacity >= buffer->lines_capacity) {
// allocate more lines
u32 new_capacity = buffer->lines_capacity * 2;
@@ -185,7 +158,7 @@ static Status buffer_lines_grow(TextBuffer *buffer, u32 minimum_capacity) {
}
static void buffer_line_append_char(TextBuffer *buffer, Line *line, char32_t c) {
- if (buffer_line_grow(buffer, line, line->len + 1))
+ if (buffer_line_set_min_capacity(buffer, line, line->len + 1))
line->str[line->len++] = c;
}
@@ -258,7 +231,7 @@ Status buffer_load_file(TextBuffer *buffer, char const *filename) {
}
}
if (c == U'\n') {
- if (buffer_lines_grow(buffer, buffer->nlines + 1))
+ if (buffer_lines_set_min_capacity(buffer, buffer->nlines + 1))
++buffer->nlines;
} else {
u32 line_idx = buffer->nlines - 1;
@@ -865,7 +838,7 @@ i64 buffer_cursor_move_right_words(TextBuffer *buffer, i64 nwords) {
static void buffer_insert_lines(TextBuffer *buffer, u32 where, u32 number) {
u32 old_nlines = buffer->nlines;
u32 new_nlines = old_nlines + number;
- if (buffer_lines_grow(buffer, new_nlines)) {
+ if (buffer_lines_set_min_capacity(buffer, new_nlines)) {
assert(where <= old_nlines);
// make space for new lines
memmove(buffer->lines + where + (new_nlines - old_nlines),
@@ -892,7 +865,7 @@ BufferPos buffer_insert_text_at_pos(TextBuffer *buffer, BufferPos pos, String32
Line *last_line = &buffer->lines[line_idx + n_added_lines];
u32 chars_moved = line->len - index;
if (chars_moved) {
- if (buffer_line_grow(buffer, last_line, chars_moved)) {
+ if (buffer_line_set_min_capacity(buffer, last_line, chars_moved)) {
memcpy(last_line->str, line->str + index, chars_moved * sizeof(char32_t));
line->len -= chars_moved;
last_line->len += chars_moved;
@@ -906,7 +879,7 @@ BufferPos buffer_insert_text_at_pos(TextBuffer *buffer, BufferPos pos, String32
u32 old_len = line->len;
u32 new_len = old_len + text_line_len;
if (new_len > old_len) { // handles both overflow and empty text lines
- if (buffer_line_grow(buffer, line, new_len)) {
+ if (buffer_line_set_min_capacity(buffer, line, new_len)) {
// make space for text
memmove(line->str + index + (new_len - old_len),
line->str + index,
@@ -967,7 +940,7 @@ static void buffer_shorten(TextBuffer *buffer, u32 new_nlines) {
// delete `nlines` lines starting from index `first_line_idx`
void buffer_delete_lines(TextBuffer *buffer, u32 first_line_idx, u32 nlines) {
assert(first_line_idx < buffer->nlines);
- assert(first_line_idx+nlines < buffer->nlines);
+ assert(first_line_idx+nlines <= buffer->nlines);
Line *first_line = &buffer->lines[first_line_idx];
Line *end = first_line + nlines;
@@ -998,7 +971,7 @@ void buffer_delete_chars_at_pos(TextBuffer *buffer, BufferPos pos, i64 nchars) {
} else {
// join last_line to line.
u32 last_line_chars_left = (u32)(last_line->len - nchars);
- if (buffer_line_grow(buffer, line, line->len + last_line_chars_left)) {
+ if (buffer_line_set_min_capacity(buffer, line, line->len + last_line_chars_left)) {
memcpy(line->str + line->len, last_line->str, last_line_chars_left * sizeof(char32_t));
line->len += last_line_chars_left;
}
@@ -1065,45 +1038,3 @@ void buffer_backspace_words_at_cursor(TextBuffer *buffer, i64 nwords) {
buffer_backspace_words_at_pos(buffer, &buffer->cursor_pos, nwords);
}
-static void buffer_undo(TextBuffer *buffer, i64 ntimes) {
- for (i64 i = 0; i < ntimes; ++i) {
- bool join_with_next;
- do {
- BufferEdit *edit = buffer->undo_history;
- join_with_next = edit->join_with_next; // should the next edit be undone along with this one?
- BufferEdit *inverse = NULL;
- switch (edit->type) {
- case BUFFER_EDIT_DELETE_LINE: {
- // let's re-insert that line
- buffer_insert_lines(buffer, edit->line, 1);
- BufferPos pos = {.line = edit->line, .index = 0};
- String32 str = {edit->prev_str_len, edit->prev_str};
- buffer_insert_text_at_pos(buffer, pos, str);
- inverse = buffer_edit_insert_line(buffer, edit->line, join_with_next);
- } break;
- case BUFFER_EDIT_INSERT_LINE: {
- Line *line = &buffer->lines[edit->line];
- inverse = buffer_edit_delete_line(buffer, edit->line, line->str, line->len, join_with_next);
- // delete that line
- buffer_delete_lines(buffer, edit->line, 1);
- } break;
- case BUFFER_EDIT_CHANGE_LINE: {
- Line *line = &buffer->lines[edit->line];
- inverse = buffer_edit_change_line(buffer, edit->line, line->str, line->len, join_with_next);
- if (buffer_line_grow(buffer, line, edit->prev_str_len)) {
- line->len = edit->prev_str_len;
- memcpy(line->str, edit->prev_str, edit->prev_str_len * sizeof(char32_t));
- }
- } break;
- }
-
- assert(inverse);
- buffer->undo_history = edit->next;
- inverse->next = buffer->redo_history;
- buffer->redo_history = inverse;
-
- free(edit);
- } while (join_with_next);
- }
-}
-