From f9afc00d15f934d8509f3eeb7c62b01ca84ca204 Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Tue, 9 Feb 2021 09:37:41 -0500 Subject: improve buffer_unsaved_changes so that making an edit then undoing it doesn't count as making a change --- buffer.c | 23 ++++++++++++----------- ted.h | 5 ++++- ui.c | 27 +++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 12 deletions(-) diff --git a/buffer.c b/buffer.c index 33ae6be..7cb1208 100644 --- a/buffer.c +++ b/buffer.c @@ -34,6 +34,9 @@ static void buffer_clear_redo_history(TextBuffer *buffer) { buffer_edit_free(edit); } arr_clear(buffer->redo_history); + // if the write pos is in the redo history, + if (buffer->undo_history_write_pos > arr_len(buffer->undo_history)) + buffer->undo_history_write_pos = U32_MAX; // get rid of it } static void buffer_clear_undo_history(TextBuffer *buffer) { @@ -41,8 +44,13 @@ static void buffer_clear_undo_history(TextBuffer *buffer) { buffer_edit_free(edit); } arr_clear(buffer->undo_history); + buffer->undo_history_write_pos = U32_MAX; } +static void buffer_clear_undo_redo(TextBuffer *buffer) { + buffer_clear_undo_history(buffer); + buffer_clear_redo_history(buffer); +} bool buffer_empty(TextBuffer *buffer) { return buffer->nlines == 1 && buffer->lines[0].len == 0; @@ -56,12 +64,6 @@ bool buffer_is_untitled(TextBuffer *buffer) { return streq(buffer->filename, TED_UNTITLED); } -// clear all undo and redo events -void buffer_clear_undo_redo(TextBuffer *buffer) { - buffer_clear_undo_history(buffer); - buffer_clear_redo_history(buffer); -} - // add this edit to the undo history static void buffer_append_edit(TextBuffer *buffer, BufferEdit const *edit) { // whenever an edit is made, clear the redo history @@ -138,7 +140,7 @@ static bool buffer_pos_valid(TextBuffer *buffer, BufferPos p) { bool buffer_unsaved_changes(TextBuffer *buffer) { if (buffer_is_untitled(buffer) && buffer_empty(buffer)) return false; // don't worry about empty untitled buffers - return buffer->modified; + return arr_len(buffer->undo_history) != buffer->undo_history_write_pos; } // code point at position. @@ -1885,11 +1887,10 @@ bool buffer_save(TextBuffer *buffer) { if (!buffer_haserr(buffer)) buffer_seterr(buffer, "Couldn't close file %s.", buffer->filename); } - bool success = !buffer_haserr(buffer); - if (success) { - buffer->modified = false; - } buffer->last_write_time = time_last_modified(buffer->filename); + bool success = !buffer_haserr(buffer); + if (success) + buffer->undo_history_write_pos = arr_len(buffer->undo_history); return success; } else { buffer_seterr(buffer, "Couldn't open file %s for writing: %s.", buffer->filename, strerror(errno)); diff --git a/ted.h b/ted.h index 5b8d5c6..7d7f7c7 100644 --- a/ted.h +++ b/ted.h @@ -131,11 +131,14 @@ typedef struct { bool is_line_buffer; // "line buffers" are buffers which can only have one line of text (used for inputs) bool selection; bool store_undo_events; // set to false to disable undo events - bool modified; // has the buffer been modified since it was loaded/saved? + // This is set to true whenever a change is made to the buffer, and never set to false by buffer_ functions. + // (Distinct from buffer_unsaved_changes) + bool modified; float x1, y1, x2, y2; u32 nlines; u32 lines_capacity; + u32 undo_history_write_pos; // where in the undo history was the last write? used by buffer_unsaved_changes u32 longest_line_on_screen; // length of the longest line on screen. used to determine how far right we can scroll. // to cache syntax highlighting properly, it is important to keep track of the diff --git a/ui.c b/ui.c index 49c0dc8..b743d82 100644 --- a/ui.c +++ b/ui.c @@ -582,6 +582,7 @@ static void popup_render(Ted *ted, u32 options, char const *title, char const *b text_get_size(font_bold, title, &title_size.x, &title_size.y); v2 title_pos = v2_sub(V2(window_width * 0.5f, y), V2(title_size.x * 0.5f, 0)); text_utf8(font_bold, title, title_pos.x, title_pos.y, colors[COLOR_TEXT]); + text_render(font_bold); // body text float text_x1 = rect_x1(r) + padding; @@ -598,3 +599,29 @@ static void popup_render(Ted *ted, u32 options, char const *title, char const *b text_render(font); } + +static void checkbox_frame(Ted *ted, bool *value, char const *label, v2 pos) { + Font *font = ted->font; + float char_height = text_font_char_height(font); + float checkbox_size = char_height; + Settings const *settings = &ted->settings; + u32 const *colors = settings->colors; + + Rect checkbox_rect = rect(pos, V2(checkbox_size, checkbox_size)); + + for (u32 i = 0; i < ted->nmouse_clicks[SDL_BUTTON_LEFT]; ++i) { + if (rect_contains_point(checkbox_rect, ted->mouse_clicks[SDL_BUTTON_LEFT][i])) { + *value = !*value; + } + } + + if (*value) + gl_geometry_rect(checkbox_rect, colors[COLOR_TEXT]); + else + gl_geometry_rect_border(checkbox_rect, 1, colors[COLOR_TEXT]); + v2 text_pos = v2_add(pos, V2(checkbox_size, 0)); + text_utf8(font, label, text_pos.x, text_pos.y, colors[COLOR_TEXT]); + + gl_geometry_draw(); + text_render(font); +} -- cgit v1.2.3