diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2021-01-28 16:22:49 -0500 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2021-01-28 16:22:49 -0500 |
commit | 238f3ecc526600d5c18fead7820469719027b07c (patch) | |
tree | d84cd6606be4a81e32f8f0634aeb924b0457e5f8 | |
parent | 5b90057859cd38b284573460460ab27bd108aa0e (diff) |
got file selector to behave better
-rw-r--r-- | buffer.c | 36 | ||||
-rw-r--r-- | command.c | 8 | ||||
-rw-r--r-- | config.c | 4 | ||||
-rw-r--r-- | main.c | 11 | ||||
-rw-r--r-- | math.c | 10 | ||||
-rw-r--r-- | menu.c | 10 | ||||
-rw-r--r-- | ted-base.c | 1 | ||||
-rw-r--r-- | ted.cfg | 3 | ||||
-rw-r--r-- | ted.h | 2 | ||||
-rw-r--r-- | ui.c | 37 |
10 files changed, 83 insertions, 39 deletions
@@ -43,6 +43,11 @@ static void buffer_clear_undo_history(TextBuffer *buffer) { arr_clear(buffer->undo_history); } + +bool buffer_empty(TextBuffer *buffer) { + return buffer->nlines == 1 && buffer->lines[0].len == 0; +} + // clear all undo and redo events void buffer_clear_undo_redo(TextBuffer *buffer) { buffer_clear_undo_history(buffer); @@ -632,16 +637,17 @@ void buffer_new_file(TextBuffer *buffer, char const *filename) { } bool buffer_save(TextBuffer *buffer) { - if (buffer->filename) { + if (!buffer->is_line_buffer && buffer->filename) { FILE *out = fopen(buffer->filename, "wb"); if (out) { - bool success = true; for (Line *line = buffer->lines, *end = line + buffer->nlines; line != end; ++line) { for (char32_t *p = line->str, *p_end = p + line->len; p != p_end; ++p) { char utf8[4] = {0}; size_t bytes = unicode_utf32_to_utf8(utf8, *p); if (bytes != (size_t)-1) { - fwrite(utf8, 1, bytes, out); + if (fwrite(utf8, 1, bytes, out) != bytes) { + buffer_seterr(buffer, "Couldn't write to %s.", buffer->filename); + } } } @@ -649,14 +655,21 @@ bool buffer_save(TextBuffer *buffer) { putc('\n', out); } } - if (ferror(out)) success = false; - if (fclose(out) != 0) success = false; + if (ferror(out)) { + if (!buffer_haserr(buffer)) + buffer_seterr(buffer, "Couldn't write to %s.", buffer->filename); + } + if (fclose(out) != 0) { + if (!buffer_haserr(buffer)) + buffer_seterr(buffer, "Couldn't close file %s.", buffer->filename); + } + bool success = !buffer_haserr(buffer); if (success) { buffer->modified = false; } return success; } else { - buffer_seterr(buffer, "Couldn't write to file %s.", buffer->filename); + buffer_seterr(buffer, "Couldn't open file %s for writing: %s.", buffer->filename, strerror(errno)); return false; } } else { @@ -667,9 +680,16 @@ bool buffer_save(TextBuffer *buffer) { // save, but with a different file name bool buffer_save_as(TextBuffer *buffer, char const *new_filename) { - free(buffer->filename); + char *prev_filename = buffer->filename; if ((buffer->filename = buffer_strdup(buffer, new_filename))) { - return buffer_save(buffer); + if (buffer_save(buffer)) { + free(prev_filename); + return true; + } else { + free(buffer->filename); + buffer->filename = prev_filename; + return false; + } } else { return false; } @@ -101,7 +101,8 @@ void command_execute(Ted *ted, Command c, i64 argument) { buffer_insert_char_at_cursor(buffer, '\t'); break; case CMD_NEWLINE: - if (buffer->is_line_buffer) { + if (!buffer) { + } else if (buffer->is_line_buffer) { switch (ted->menu) { case MENU_NONE: assert(0); @@ -192,9 +193,4 @@ void command_execute(Ted *ted, Command c, i64 argument) { } break; } - - if (buffer && buffer_haserr(buffer)) { - ted_seterr_to_buferr(ted, buffer); - buffer_clearerr(buffer); - } } @@ -81,6 +81,8 @@ static u32 config_parse_key_combo(ConfigReader *cfg, char const *str) { {"Period", 0, SDL_SCANCODE_PERIOD, 0}, {"Semicolon", 0, SDL_SCANCODE_SEMICOLON, 0}, {"Slash", 0, SDL_SCANCODE_SLASH, 0}, + {"Enter", 0, SDL_SCANCODE_RETURN, 0}, + {"Keypad Return", 0, SDL_SCANCODE_KP_ENTER, 0}, {"Exclaim", "Exclamation Mark", SDL_SCANCODE_1, 1}, {"!", 0, SDL_SCANCODE_1, 1}, {"At", "@", SDL_SCANCODE_2, 1}, @@ -103,7 +105,7 @@ static u32 config_parse_key_combo(ConfigReader *cfg, char const *str) { {"Greater Than", ">", SDL_SCANCODE_PERIOD, 1}, {"Question Mark", "?", SDL_SCANCODE_SLASH, 1}, {"Question", 0, SDL_SCANCODE_SLASH, 1}, - {"Tilde", "~", SDL_SCANCODE_GRAVE, 1} + {"Tilde", "~", SDL_SCANCODE_GRAVE, 1}, }; // @OPTIMIZE: sort key_names (and split keyname1/2); do a binary search @@ -1,10 +1,6 @@ // @TODO: -// - warn on: -// - overwrite (from save as menu) -// - file selector: -// - tab to set search term to selected // - tabs, split -// - when closing tabs, warn on unsaved changes +// - when closing tabs/window, warn on unsaved changes // - Windows installation #include "base.h" no_warn_start @@ -467,6 +463,11 @@ int main(int argc, char **argv) { menu_render(ted, menu); } + if (buffer_haserr(&ted->main_buffer)) { + ted_seterr_to_buferr(ted, &ted->main_buffer); + buffer_clearerr(&ted->main_buffer); + } + // check if there's a new error if (ted_haserr(ted)) { ted->error_time = time_get_seconds(); @@ -112,6 +112,16 @@ static i64 mod_i64(i64 a, i64 b) { return ret; } +static i64 abs_i64(i64 x) { + return x < 0 ? -x : +x; +} + +static i64 sgn_i64(i64 x) { + if (x < 0) return -1; + if (x > 0) return +1; + return 0; +} + static float sgnf(float x) { if (x < 0) return -1; if (x > 0) return +1; @@ -60,12 +60,14 @@ static void menu_update(Ted *ted, Menu menu) { case POPUP_NONE: // no option selected break; - case POPUP_YES: + case POPUP_YES: { // overwrite it! - if (ted->prev_active_buffer) - buffer_save_as(ted->prev_active_buffer, ted->warn_overwrite); + TextBuffer *buffer = ted->prev_active_buffer; + if (buffer) { + buffer_save_as(buffer, ted->warn_overwrite); + } menu_close(ted, true); - break; + } break; case POPUP_NO: // back to the file selector *ted->warn_overwrite = '\0'; @@ -96,7 +96,6 @@ static WarnUnusedResult TextBuffer *ted_open_file(Ted *ted, char const *filename ted->active_buffer = open_to; return open_to; } else { - ted_seterr_to_buferr(ted, open_to); return NULL; } } @@ -48,7 +48,8 @@ Ctrl+a = :select-all # insertion Tab = :tab -Return = :newline +Enter = :newline +Keypad Enter = :newline # deletion Delete = :delete @@ -91,7 +91,7 @@ typedef struct { typedef struct { Rect bounds; u32 n_entries; - u32 selected; // which FileEntry is currently selected + u32 selected; float scroll; FileEntry *entries; char cwd[TED_PATH_MAX]; @@ -57,23 +57,32 @@ static void file_selector_clear_entries(FileSelector *fs) { fs->n_entries = 0; } +// returns true if there are any directory entries +static bool file_selector_any_directories(FileSelector const *fs) { + FileEntry const *entries = fs->entries; + for (u32 i = 0, n_entries = fs->n_entries; i < n_entries; ++i) { + if (entries[i].type == FS_DIRECTORY) + return true; + } + return false; +} + static void file_selector_free(FileSelector *fs) { file_selector_clear_entries(fs); memset(fs, 0, sizeof *fs); } static void file_selector_up(Ted const *ted, FileSelector *fs, i64 n) { - i64 selected = fs->selected - n; - selected = mod_i64(selected, fs->n_entries); - fs->selected = (u32)selected; + if (fs->n_entries == 0) { + // can't do anything + return; + } + fs->selected = (u32)mod_i64(fs->selected - n, fs->n_entries); file_selector_scroll_to_selected(ted, fs); } static void file_selector_down(Ted const *ted, FileSelector *fs, i64 n) { - i64 selected = fs->selected + n; - selected = mod_i64(selected, fs->n_entries); - fs->selected = (u32)selected; - file_selector_scroll_to_selected(ted, fs); + file_selector_up(ted, fs, -n); } static int qsort_file_entry_cmp(void const *av, void const *bv, void *search_termv) { @@ -214,6 +223,7 @@ static Status file_selector_cd_(Ted const *ted, FileSelector *fs, char const *pa // returns false if this path doesn't exist or isn't a directory static bool file_selector_cd(Ted const *ted, FileSelector *fs, char const *path) { fs->selected = 0; + fs->scroll = 0; return file_selector_cd_(ted, fs, path, 0); } @@ -267,9 +277,6 @@ static char *file_selector_update(Ted *ted, FileSelector *fs) { char *search_term = search_term32.len ? str32_to_utf8_cstr(search_term32) : NULL; - bool submitted = fs->submitted; - fs->submitted = false; - for (u32 i = 0; i < fs->n_entries; ++i) { Rect r = {0}; FileEntry *entry = &fs->entries[i]; @@ -298,9 +305,13 @@ static char *file_selector_update(Ted *ted, FileSelector *fs) { } + bool submitted = fs->submitted; + fs->submitted = false; + // user pressed enter in search bar if (submitted) { - if (fs->create_menu) { + if (fs->create_menu && search_term) { + // user typed in file name to save as char path[TED_PATH_MAX]; strbuf_printf(path, "%s%s%s", cwd, cwd[strlen(cwd)-1] == PATH_SEPARATOR ? "" : PATH_SEPARATOR_STR, search_term); free(search_term); @@ -430,7 +441,9 @@ static void file_selector_render(Ted *ted, FileSelector *fs) { Rect r; if (file_selector_entry_pos(ted, fs, i, &r)) { rect_clip_to_rect(&r, text_bounds); - if (rect_contains_point(r, ted->mouse_pos) || fs->selected == i) { + if (rect_contains_point(r, ted->mouse_pos) || + ((!fs->create_menu || buffer_empty(&ted->line_buffer)) // only highlight selected for create menus if there is no search term (because that will be the name of the file) + && fs->selected == i)) { glBegin(GL_QUADS); gl_color_rgba(colors[COLOR_MENU_HL]); rect_render(r); |