From cca844b42a6303282e7536c8834b74ff56140cbf Mon Sep 17 00:00:00 2001 From: pommicket Date: Wed, 9 Aug 2023 19:14:52 -0300 Subject: more pointerizing of buffers, fix memory leaks --- buffer.c | 59 ++++++++++++++++++++++++++++++++--------------------- build.c | 12 +++++------ command.c | 22 ++++++++++---------- find.c | 17 ++++++++------- ide-definitions.c | 6 +++--- ide-rename-symbol.c | 8 ++++---- ide-usages.c | 2 +- main.c | 33 ++++++++++++++++-------------- menu.c | 46 ++++++++++++++++++++--------------------- node.c | 1 + session.c | 23 ++++++++++++--------- ted-internal.h | 20 +++++++++++------- ted.c | 11 +++++----- ted.h | 5 ----- ui.c | 7 +++---- 15 files changed, 148 insertions(+), 124 deletions(-) diff --git a/buffer.c b/buffer.c index 1c33f99..f1e8047 100644 --- a/buffer.c +++ b/buffer.c @@ -34,16 +34,16 @@ bool buffer_has_error(TextBuffer *buffer) { // returns the buffer's last error const char *buffer_get_error(TextBuffer *buffer) { - return buffer->error; + return buffer ? buffer->error : ""; } void buffer_clear_error(TextBuffer *buffer) { *buffer->error = '\0'; } -// set the buffer's error to indicate that we're out of memory +// set error to indicate that we're out of memory static void buffer_out_of_mem(TextBuffer *buffer) { - buffer_error(buffer, "Out of memory."); + ted_error(buffer->ted, "Out of memory."); } @@ -180,15 +180,14 @@ static char *buffer_strdup(TextBuffer *buffer, const char *src) { return dup; } -void buffer_create(TextBuffer *buffer, Ted *ted) { - memset(buffer, 0, sizeof *buffer); +static void buffer_set_up(Ted *ted, TextBuffer *buffer) { buffer->store_undo_events = true; buffer->ted = ted; buffer->settings_idx = -1; } -void line_buffer_create(TextBuffer *buffer, Ted *ted) { - buffer_create(buffer, ted); +static void line_buffer_set_up(Ted *ted, TextBuffer *buffer) { + buffer_set_up(ted, buffer); buffer->is_line_buffer = true; if ((buffer->lines = buffer_calloc(buffer, 1, sizeof *buffer->lines))) { buffer->nlines = 1; @@ -196,6 +195,20 @@ void line_buffer_create(TextBuffer *buffer, Ted *ted) { } } +TextBuffer *buffer_new(Ted *ted) { + TextBuffer *buffer = ted_calloc(ted, 1, sizeof *buffer); + if (!buffer) return NULL; + buffer_set_up(ted, buffer); + return buffer; +} + +TextBuffer *line_buffer_new(Ted *ted) { + TextBuffer *buffer = ted_calloc(ted, 1, sizeof *buffer); + if (!buffer) return NULL; + line_buffer_set_up(ted, buffer); + return buffer; +} + void buffer_pos_validate(TextBuffer *buffer, BufferPos *p) { if (p->line >= buffer->nlines) p->line = buffer->nlines - 1; @@ -803,11 +816,9 @@ static void buffer_line_free(Line *line) { free(line->str); } -void buffer_free(TextBuffer *buffer) { - if (!buffer) return; - - if (!buffer->ted->quit) { // don't send didClose on quit (calling buffer_lsp would actually create a LSP if this is called after destroying all the LSPs which isnt good) - +static void buffer_free_inner(TextBuffer *buffer) { + Ted *ted = buffer->ted; + if (!ted->quit) { // don't send didClose on quit (calling buffer_lsp would actually create a LSP if this is called after destroying all the LSPs which isnt good) LSP *lsp = buffer_lsp(buffer); if (lsp) { buffer_send_lsp_did_close(buffer, lsp, NULL); @@ -832,18 +843,20 @@ void buffer_free(TextBuffer *buffer) { memset(buffer, 0, sizeof *buffer); } +void buffer_free(TextBuffer *buffer) { + if (!buffer) return; + buffer_free_inner(buffer); + free(buffer); +} + void buffer_clear(TextBuffer *buffer) { bool is_line_buffer = buffer->is_line_buffer; Ted *ted = buffer->ted; - char error[sizeof buffer->error]; - memcpy(error, buffer->error, sizeof error); - buffer_free(buffer); - if (is_line_buffer) { - line_buffer_create(buffer, ted); - } else { - buffer_create(buffer, ted); - } - memcpy(buffer->error, error, sizeof error); + buffer_free_inner(buffer); + if (is_line_buffer) + line_buffer_set_up(ted, buffer); + else + buffer_set_up(ted, buffer); } @@ -2650,7 +2663,7 @@ void buffer_paste(TextBuffer *buffer) { // if an error occurs, buffer is left untouched (except for the error field) and the function returns false. Status buffer_load_file(TextBuffer *buffer, const char *path) { if (!unicode_is_valid_utf8(path)) { - buffer_error(buffer, "Path is not valid UTF8."); + buffer_error(buffer, "Path is not valid UTF-8."); return false; } if (!path || !path_is_absolute(path)) { @@ -3154,7 +3167,7 @@ void buffer_render(TextBuffer *buffer, Rect r) { } // change cursor to ibeam when it's hovering over the buffer - if ((!menu_is_any_open(ted) || buffer == &ted->line_buffer) && rect_contains_point(rect4(x1, y1, x2, y2), ted->mouse_pos)) { + if ((!menu_is_any_open(ted) || buffer == ted->line_buffer) && rect_contains_point(rect4(x1, y1, x2, y2), ted->mouse_pos)) { ted->cursor = ted->cursor_ibeam; } diff --git a/build.c b/build.c index c37e2f5..7d6eed7 100644 --- a/build.c +++ b/build.c @@ -16,7 +16,7 @@ void build_stop(Ted *ted) { free(*cmd); } arr_clear(ted->build_queue); - if (ted->active_buffer == &ted->build_buffer) { + if (ted->active_buffer == ted->build_buffer) { ted_switch_to_buffer(ted, NULL); ted_reset_active_buffer(ted); } @@ -47,7 +47,7 @@ static bool build_run_next_command_in_queue(Ted *ted) { if (!error) { ted->building = true; ted->build_shown = true; - TextBuffer *build_buffer = &ted->build_buffer; + TextBuffer *build_buffer = ted->build_buffer; char32_t text[] = {'$', ' '}; buffer_insert_text_at_cursor(build_buffer, str32(text, 2)); buffer_insert_utf8_at_cursor(build_buffer, command); @@ -68,7 +68,7 @@ static bool build_run_next_command_in_queue(Ted *ted) { void build_setup_buffer(Ted *ted) { // new empty build output buffer - TextBuffer *build_buffer = &ted->build_buffer; + TextBuffer *build_buffer = ted->build_buffer; buffer_new_file(build_buffer, NULL); build_buffer->store_undo_events = false; // don't need undo events for build output buffer } @@ -150,7 +150,7 @@ static void build_go_to_error(Ted *ted) { buffer->center_cursor_next_frame = true; // move cursor to error in build output - TextBuffer *build_buffer = &ted->build_buffer; + TextBuffer *build_buffer = ted->build_buffer; BufferPos error_pos = {.line = error.build_output_line, .index = 0}; buffer_cursor_move_to_pos(build_buffer, error_pos); buffer_center_cursor(build_buffer); @@ -201,7 +201,7 @@ static bool is_source_path(char32_t c) { void build_check_for_errors(Ted *ted) { const Settings *settings = ted_active_settings(ted); - TextBuffer *buffer = &ted->build_buffer; + TextBuffer *buffer = ted->build_buffer; arr_clear(ted->build_errors); for (u32 line_idx = 0; line_idx < buffer->nlines; ++line_idx) { String32 line = buffer_get_line(buffer, line_idx); @@ -309,7 +309,7 @@ void build_check_for_errors(Ted *ted) { } void build_frame(Ted *ted, float x1, float y1, float x2, float y2) { - TextBuffer *buffer = &ted->build_buffer; + TextBuffer *buffer = ted->build_buffer; assert(ted->build_shown); char buf[256]; if (ted->building) { diff --git a/command.c b/command.c index e573049..4f14234 100644 --- a/command.c +++ b/command.c @@ -203,14 +203,14 @@ void command_execute_ex(Ted *ted, Command c, const CommandArgument *full_argumen break; case CMD_UP: if (ted->selector_open) selector_up(ted, ted->selector_open, argument); - else if (menu_is_open(ted, MENU_SHELL) && buffer == &ted->line_buffer) + else if (menu_is_open(ted, MENU_SHELL) && buffer == ted->line_buffer) menu_shell_up(ted); else if (buffer) buffer_cursor_move_up(buffer, argument); autocomplete_close(ted); break; case CMD_DOWN: if (ted->selector_open) selector_down(ted, ted->selector_open, argument); - else if (menu_is_open(ted, MENU_SHELL) && buffer == &ted->line_buffer) + else if (menu_is_open(ted, MENU_SHELL) && buffer == ted->line_buffer) menu_shell_down(ted); else if (buffer) buffer_cursor_move_down(buffer, argument); autocomplete_close(ted); @@ -325,11 +325,11 @@ void command_execute_ex(Ted *ted, Command c, const CommandArgument *full_argumen } break; case CMD_TAB: - if (ted->replace && buffer == &ted->find_buffer) { - ted_switch_to_buffer(ted, &ted->replace_buffer); + if (ted->replace && buffer == ted->find_buffer) { + ted_switch_to_buffer(ted, ted->replace_buffer); buffer_select_all(buffer); - } else if (menu_is_open(ted, MENU_COMMAND_SELECTOR) && buffer == &ted->argument_buffer) { - buffer = &ted->line_buffer; + } else if (menu_is_open(ted, MENU_COMMAND_SELECTOR) && buffer == ted->argument_buffer) { + buffer = ted->line_buffer; ted_switch_to_buffer(ted, buffer); buffer_select_all(buffer); } else if (autocomplete_is_open(ted) || autocomplete_has_phantom(ted)) { @@ -342,11 +342,11 @@ void command_execute_ex(Ted *ted, Command c, const CommandArgument *full_argumen } break; case CMD_BACKTAB: - if (ted->replace && buffer == &ted->replace_buffer) { - ted_switch_to_buffer(ted, &ted->find_buffer); + if (ted->replace && buffer == ted->replace_buffer) { + ted_switch_to_buffer(ted, ted->find_buffer); buffer_select_all(buffer); - } else if (menu_is_open(ted, MENU_COMMAND_SELECTOR) && buffer == &ted->line_buffer) { - buffer = &ted->argument_buffer; + } else if (menu_is_open(ted, MENU_COMMAND_SELECTOR) && buffer == ted->line_buffer) { + buffer = ted->argument_buffer; ted_switch_to_buffer(ted, buffer); buffer_select_all(buffer); } else if (buffer) { @@ -359,7 +359,7 @@ void command_execute_ex(Ted *ted, Command c, const CommandArgument *full_argumen case CMD_NEWLINE: case CMD_NEWLINE_BACK: if (ted->find) { - if (buffer == &ted->find_buffer || buffer == &ted->replace_buffer) { + if (buffer == ted->find_buffer || buffer == ted->replace_buffer) { if (c == CMD_NEWLINE) find_next(ted); else diff --git a/find.c b/find.c index 43e11cd..d89fa95 100644 --- a/find.c +++ b/find.c @@ -19,7 +19,9 @@ static u32 find_replace_flags(Ted *ted) { } TextBuffer *find_search_buffer(Ted *ted) { - if (ted->active_buffer && ted->active_buffer != &ted->find_buffer && ted->active_buffer != &ted->replace_buffer) { + if (ted->active_buffer + && ted->active_buffer != ted->find_buffer + && ted->active_buffer != ted->replace_buffer) { return ted->active_buffer; } return ted->prev_active_buffer; @@ -38,7 +40,7 @@ static void ted_error_from_pcre2_error(Ted *ted, int err) { } static bool find_compile_pattern(Ted *ted) { - TextBuffer *find_buffer = &ted->find_buffer; + TextBuffer *find_buffer = ted->find_buffer; String32 term = buffer_get_line(find_buffer, 0); if (term.len) { pcre2_match_data *match_data = pcre2_match_data_create(FIND_MAX_GROUPS, NULL); @@ -143,7 +145,7 @@ static void find_search_line(Ted *ted, u32 line, FindResult **results) { // check if the search term needs to be recompiled void find_update(Ted *ted, bool force) { - TextBuffer *find_buffer = &ted->find_buffer; + TextBuffer *find_buffer = ted->find_buffer; u32 flags = find_compilation_flags(ted); if (!force && !find_buffer->modified // check if pattern has been modified, @@ -234,7 +236,7 @@ static bool find_replace_match(Ted *ted, u32 match_idx) { return false; assert(match.start.line == match.end.line); String32 line = buffer_get_line(buffer, match.start.line); - String32 replacement = buffer_get_line(&ted->replace_buffer, 0); + String32 replacement = buffer_get_line(ted->replace_buffer, 0); // we are currently highlighting the find pattern, let's replace it // get size of buffer needed. @@ -338,7 +340,8 @@ void find_menu_frame(Ted *ted, Rect menu_bounds) { bool const replace = ted->replace; const float line_buffer_height = ted_line_buffer_height(ted); - TextBuffer *buffer = find_search_buffer(ted), *find_buffer = &ted->find_buffer, *replace_buffer = &ted->replace_buffer; + TextBuffer *buffer = find_search_buffer(ted), + *find_buffer = ted->find_buffer, *replace_buffer = ted->replace_buffer; if (!buffer) return; u32 first_rendered_line = buffer_first_rendered_line(buffer); @@ -469,10 +472,10 @@ void find_menu_frame(Ted *ted, Rect menu_bounds) { void find_open(Ted *ted, bool replace) { if (menu_is_any_open(ted)) return; - if (ted->active_buffer == &ted->build_buffer) return; + if (ted->active_buffer == ted->build_buffer) return; if (!ted->find) ted->prev_active_buffer = ted->active_buffer; - ted_switch_to_buffer(ted, &ted->find_buffer); + ted_switch_to_buffer(ted, ted->find_buffer); buffer_select_all(ted->active_buffer); ted->find = true; ted->replace = replace; diff --git a/ide-definitions.c b/ide-definitions.c index ea268e2..57738b1 100644 --- a/ide-definitions.c +++ b/ide-definitions.c @@ -129,7 +129,7 @@ static void definitions_selector_filter_entries(Ted *ted) { Selector *sel = &defs->selector; // create selector entries based on search term - char *search_term = str32_to_utf8_cstr(buffer_get_line(&ted->line_buffer, 0)); + char *search_term = str32_to_utf8_cstr(buffer_get_line(ted->line_buffer, 0)); arr_clear(sel->entries); @@ -245,7 +245,7 @@ void definitions_send_request_if_needed(Ted *ted) { if (!lsp) return; Definitions *defs = &ted->definitions; - char *query = buffer_contents_utf8_alloc(&ted->line_buffer); + char *query = buffer_contents_utf8_alloc(ted->line_buffer); if (defs->last_request_query && strcmp(defs->last_request_query, query) == 0) { free(query); return; // no need to update symbols @@ -273,7 +273,7 @@ static void definitions_selector_open(Ted *ted) { } else { defs->all_definitions = tags_get_symbols(ted); } - ted_switch_to_buffer(ted, &ted->line_buffer); + ted_switch_to_buffer(ted, ted->line_buffer); buffer_select_all(ted->active_buffer); defs->selector.cursor = 0; } diff --git a/ide-rename-symbol.c b/ide-rename-symbol.c index 0ff69e8..344f401 100644 --- a/ide-rename-symbol.c +++ b/ide-rename-symbol.c @@ -41,11 +41,11 @@ void rename_symbol_frame(Ted *ted) { } static void rename_symbol_menu_open(Ted *ted) { - ted_switch_to_buffer(ted, &ted->line_buffer); + ted_switch_to_buffer(ted, ted->line_buffer); } static void rename_symbol_menu_update(Ted *ted) { - TextBuffer *line_buffer = &ted->line_buffer; + TextBuffer *line_buffer = ted->line_buffer; if (line_buffer->line_buffer_submitted) { char *new_name = str32_to_utf8_cstr(buffer_get_line(line_buffer, 0)); rename_symbol_at_cursor(ted, ted->prev_active_buffer, new_name); @@ -104,12 +104,12 @@ static void rename_symbol_menu_render(Ted *ted) { rect_shrink_left(&bounds, text_get_size_vec2(ted->font_bold, text).x + padding); text_render(ted->font_bold); - buffer_render(&ted->line_buffer, bounds); + buffer_render(ted->line_buffer, bounds); } static bool rename_symbol_menu_close(Ted *ted) { rename_symbol_clear(ted); - buffer_clear(&ted->line_buffer); + buffer_clear(ted->line_buffer); return true; } diff --git a/ide-usages.c b/ide-usages.c index ff393f1..435b7a2 100644 --- a/ide-usages.c +++ b/ide-usages.c @@ -47,7 +47,7 @@ void usages_process_lsp_response(Ted *ted, const LSPResponse *response) { LSP *lsp = ted_get_lsp_by_id(ted, usages->last_request.lsp); const LSPResponseReferences *refs = &response->data.references; if (lsp && arr_len(refs->locations)) { - TextBuffer *buffer = &ted->build_buffer; + TextBuffer *buffer = ted->build_buffer; build_setup_buffer(ted); ted->build_shown = true; char last_path[TED_PATH_MAX] = {0}; diff --git a/main.c b/main.c index 5f2739b..ff41cc9 100644 --- a/main.c +++ b/main.c @@ -1,6 +1,5 @@ /* TODO: -- set limit for # of nodes/buffers/tabs - public Node API - public Selector/FileSelector API @@ -520,15 +519,15 @@ int main(int argc, char **argv) { PROFILE_TIME(create_start) { - TextBuffer *lbuffer = &ted->line_buffer; - line_buffer_create(lbuffer, ted); - if (buffer_has_error(lbuffer)) + TextBuffer *lbuffer = ted->line_buffer = line_buffer_new(ted); + if (!lbuffer || buffer_has_error(lbuffer)) die("Error creating line buffer: %s", buffer_get_error(lbuffer)); } - line_buffer_create(&ted->find_buffer, ted); - line_buffer_create(&ted->replace_buffer, ted); - line_buffer_create(&ted->argument_buffer, ted); - buffer_create(&ted->build_buffer, ted); + ted->find_buffer = line_buffer_new(ted); + ted->replace_buffer = line_buffer_new(ted); + ted->argument_buffer = line_buffer_new(ted); + ted->build_buffer = buffer_new(ted); + buffer_new_file(ted->build_buffer, NULL); for (u32 i = 0; i < arr_len(starting_files); ++i) { const char *filename = starting_files[i]; @@ -695,7 +694,7 @@ int main(int argc, char **argv) { } } if (add && ted->build_shown) - if (buffer_handle_click(ted, &ted->build_buffer, pos, times)) // handle build buffer clicks + if (buffer_handle_click(ted, ted->build_buffer, pos, times)) // handle build buffer clicks add = false; } } @@ -1121,7 +1120,11 @@ int main(int argc, char **argv) { #if !NDEBUG for (u16 i = 0; i < arr_len(ted->buffers); ++i) buffer_check_valid(ted->buffers[i]); - buffer_check_valid(&ted->line_buffer); + buffer_check_valid(ted->line_buffer); + buffer_check_valid(ted->argument_buffer); + buffer_check_valid(ted->find_buffer); + buffer_check_valid(ted->replace_buffer); + buffer_check_valid(ted->build_buffer); #endif if (ted->dragging_tab_node) @@ -1229,11 +1232,11 @@ int main(int argc, char **argv) { node_free(*pnode); } arr_clear(ted->nodes); - buffer_free(&ted->line_buffer); - buffer_free(&ted->find_buffer); - buffer_free(&ted->replace_buffer); - buffer_free(&ted->build_buffer); - buffer_free(&ted->argument_buffer); + buffer_free(ted->line_buffer); + buffer_free(ted->find_buffer); + buffer_free(ted->replace_buffer); + buffer_free(ted->build_buffer); + buffer_free(ted->argument_buffer); ted_free_fonts(ted); config_free(ted); macros_free(ted); diff --git a/menu.c b/menu.c index d74762f..c22f8f4 100644 --- a/menu.c +++ b/menu.c @@ -68,7 +68,7 @@ void menu_open_with_context(Ted *ted, const char *menu_name, void *context) { ted_switch_to_buffer(ted, NULL); *ted->warn_overwrite = 0; // clear warn_overwrite - buffer_clear(&ted->line_buffer); + buffer_clear(ted->line_buffer); if (info->open) info->open(ted); } @@ -82,7 +82,7 @@ void menu_escape(Ted *ted) { if (*ted->warn_overwrite) { // just close "are you sure you want to overwrite?" *ted->warn_overwrite = 0; - ted_switch_to_buffer(ted, &ted->line_buffer); + ted_switch_to_buffer(ted, ted->line_buffer); } else { menu_close(ted); } @@ -136,7 +136,7 @@ void menu_render(Ted *ted) { } void menu_shell_move(Ted *ted, int direction) { - TextBuffer *line_buffer = &ted->line_buffer; + TextBuffer *line_buffer = ted->line_buffer; if (line_buffer->modified) { // don't do it if the command has been edited return; @@ -167,7 +167,7 @@ void menu_shell_down(Ted *ted) { } static void open_menu_open(Ted *ted) { - ted_switch_to_buffer(ted, &ted->line_buffer); + ted_switch_to_buffer(ted, ted->line_buffer); ted->file_selector.create_menu = false; } @@ -190,12 +190,12 @@ static void open_menu_render(Ted *ted) { static bool open_menu_close(Ted *ted) { file_selector_free(&ted->file_selector); - buffer_clear(&ted->line_buffer); + buffer_clear(ted->line_buffer); return true; } static void save_as_menu_open(Ted *ted) { - ted_switch_to_buffer(ted, &ted->line_buffer); + ted_switch_to_buffer(ted, ted->line_buffer); ted->file_selector.create_menu = true; } @@ -216,7 +216,7 @@ static void save_as_menu_update(Ted *ted) { case POPUP_NO: // back to the file selector *ted->warn_overwrite = '\0'; - ted_switch_to_buffer(ted, &ted->line_buffer); + ted_switch_to_buffer(ted, ted->line_buffer); break; case POPUP_CANCEL: // close "save as" menu @@ -262,7 +262,7 @@ static void save_as_menu_render(Ted *ted) { static bool save_as_menu_close(Ted *ted) { file_selector_free(&ted->file_selector); - buffer_clear(&ted->line_buffer); + buffer_clear(ted->line_buffer); return true; } @@ -350,8 +350,8 @@ static bool ask_reload_menu_close(Ted *ted) { } static void command_selector_open(Ted *ted) { - ted_switch_to_buffer(ted, &ted->line_buffer); - buffer_insert_char_at_cursor(&ted->argument_buffer, '1'); + ted_switch_to_buffer(ted, ted->line_buffer); + buffer_insert_char_at_cursor(ted->argument_buffer, '1'); Selector *selector = &ted->command_selector; selector->enable_cursor = true; selector->cursor = 0; @@ -360,7 +360,7 @@ static void command_selector_open(Ted *ted) { static void command_selector_update(Ted *ted) { const Settings *settings = ted_active_settings(ted); const u32 *colors = settings->colors; - TextBuffer *line_buffer = &ted->line_buffer; + TextBuffer *line_buffer = ted->line_buffer; Selector *selector = &ted->command_selector; SelectorEntry *entries = selector->entries = calloc(CMD_COUNT, sizeof *selector->entries); char *search_term = str32_to_utf8_cstr(buffer_get_line(line_buffer, 0)); @@ -382,7 +382,7 @@ static void command_selector_update(Ted *ted) { if (chosen_command) { Command c = command_from_str(chosen_command); if (c != CMD_UNKNOWN) { - char *argument = str32_to_utf8_cstr(buffer_get_line(&ted->argument_buffer, 0)), *endp = NULL; + char *argument = str32_to_utf8_cstr(buffer_get_line(ted->argument_buffer, 0)), *endp = NULL; long long arg = 1; bool execute = true; if (*argument) { @@ -420,7 +420,7 @@ static void command_selector_render(Ted *ted) { const char *text = "Argument"; text_utf8(font_bold, text, x1, y1, colors[COLOR_TEXT]); float x = x1 + text_get_size_vec2(font_bold, text).x + padding; - buffer_render(&ted->argument_buffer, rect4(x, y1, x2, y1 + line_buffer_height)); + buffer_render(ted->argument_buffer, rect4(x, y1, x2, y1 + line_buffer_height)); y1 += line_buffer_height + padding; @@ -433,18 +433,18 @@ static void command_selector_render(Ted *ted) { static bool command_selector_close(Ted *ted) { Selector *selector = &ted->command_selector; - buffer_clear(&ted->line_buffer); - buffer_clear(&ted->argument_buffer); + buffer_clear(ted->line_buffer); + buffer_clear(ted->argument_buffer); free(selector->entries); selector->entries = NULL; selector->n_entries = 0; return true; } static void goto_line_menu_open(Ted *ted) { - ted_switch_to_buffer(ted, &ted->line_buffer); + ted_switch_to_buffer(ted, ted->line_buffer); } static void goto_line_menu_update(Ted *ted) { - TextBuffer *line_buffer = &ted->line_buffer; + TextBuffer *line_buffer = ted->line_buffer; char *contents = str32_to_utf8_cstr(buffer_get_line(line_buffer, 0)); char *end; @@ -495,21 +495,21 @@ static void goto_line_menu_render(Ted *ted) { text_render(font_bold); // line buffer - buffer_render(&ted->line_buffer, rect4(x1, y1, x2, y2)); + buffer_render(ted->line_buffer, rect4(x1, y1, x2, y2)); } static bool goto_line_menu_close(Ted *ted) { - buffer_clear(&ted->line_buffer); + buffer_clear(ted->line_buffer); return true; } static void shell_menu_open(Ted *ted) { - ted_switch_to_buffer(ted, &ted->line_buffer); + ted_switch_to_buffer(ted, ted->line_buffer); ted->shell_history_pos = arr_len(ted->shell_history); } static void shell_menu_update(Ted *ted) { - TextBuffer *line_buffer = &ted->line_buffer; + TextBuffer *line_buffer = ted->line_buffer; if (line_buffer->line_buffer_submitted) { char *command = str32_to_utf8_cstr(buffer_get_line(line_buffer, 0)); if (ted->shell_history_pos == arr_len(ted->shell_history) || line_buffer->modified) { @@ -540,11 +540,11 @@ static void shell_menu_render(Ted *ted) { text_utf8(ted->font_bold, text, bounds.pos.x, bounds.pos.y, colors[COLOR_TEXT]); rect_shrink_left(&bounds, text_get_size_vec2(ted->font_bold, text).x + padding); text_render(ted->font_bold); - buffer_render(&ted->line_buffer, bounds); + buffer_render(ted->line_buffer, bounds); } static bool shell_menu_close(Ted *ted) { - buffer_clear(&ted->line_buffer); + buffer_clear(ted->line_buffer); return true; } diff --git a/node.c b/node.c index 51a1422..ccd9936 100644 --- a/node.c +++ b/node.c @@ -148,6 +148,7 @@ void node_close(Ted *ted, Node *node) { } // replace parent with other side of split *parent = *other_side; + free(other_side); arr_remove_item(ted->nodes, other_side); if (was_active) { Node *new_active_node = parent; diff --git a/session.c b/session.c index 58c842d..f84dd09 100644 --- a/session.c +++ b/session.c @@ -173,18 +173,20 @@ static void session_write_node(Ted *ted, FILE *fp, Node *node) { } } -static Status session_read_node(Ted *ted, FILE *fp) { - Node *node = ted_new_node(ted); +static Status session_read_node(Ted *ted, FILE *fp, Node *node) { bool is_split = read_bool(fp); if (is_split) { node->split_pos = clampf(read_float(fp), 0, 1); node->split_vertical = read_bool(fp); u16 split_a_index = read_u16(fp), split_b_index = read_u16(fp); - if (split_a_index == split_b_index || split_a_index >= arr_len(ted->nodes) || split_b_index >= arr_len(ted->nodes)) { + if (split_a_index == split_b_index || split_a_index >= arr_len(ted->nodes) + || split_b_index >= arr_len(ted->nodes)) { return false; } node->split_a = ted->nodes[split_a_index]; node->split_b = ted->nodes[split_b_index]; + if (node->split_a == node || node->split_b == node) + return false; } else { node->active_tab = read_u16(fp); u16 ntabs = clamp_u16(read_u16(fp), 0, TED_MAX_TABS); @@ -218,7 +220,6 @@ static bool session_read_buffer(Ted *ted, FILE *fp) { TextBuffer *buffer = ted_new_buffer(ted); char filename[TED_PATH_MAX] = {0}; read_cstr(fp, filename, sizeof filename); - buffer_create(buffer, ted); if (!buffer_has_error(buffer)) { if (*filename) { if (!buffer_load_file(buffer, filename)) @@ -288,8 +289,11 @@ static void session_read_file(Ted *ted, FILE *fp) { } u16 nnodes = read_u16(fp); - for (u16 i = 0; i < nnodes; ++i) { - if (!session_read_node(ted, fp)) { + for (u16 i = 0; i < nnodes; i++) { + ted_new_node(ted); + } + for (u16 i = 0; i < nnodes; i++) { + if (!session_read_node(ted, fp, ted->nodes[i])) { arr_foreach_ptr(ted->buffers, TextBufferPtr, pbuffer) { buffer_free(*pbuffer); } @@ -312,16 +316,15 @@ static void session_read_file(Ted *ted, FILE *fp) { if (active_buffer_idx == U16_MAX) { ted->active_buffer = NULL; - } else { - if (active_buffer_idx >= arr_len(ted->buffers)) - active_buffer_idx = 0; + } else if (active_buffer_idx < arr_len(ted->buffers)) { ted->active_buffer = ted->buffers[active_buffer_idx]; } - if (nbuffers && !ted->active_buffer) { + if (arr_len(ted->buffers) && !ted->active_buffer) { // set active buffer to something ted->active_buffer = ted->buffers[0]; } + ted_check_for_node_problems(ted); } void session_write(Ted *ted) { diff --git a/ted-internal.h b/ted-internal.h index 38a7dbc..c90499d 100644 --- a/ted-internal.h +++ b/ted-internal.h @@ -22,6 +22,10 @@ #define TED_LSP_MAX 200 /// max number of macros #define TED_MACRO_MAX 256 +/// max number of nodes +#define TED_NODE_MAX 256 +/// max number of buffers +#define TED_BUFFER_MAX 1024 /// Version string #define TED_VERSION_FULL "ted v. " TED_VERSION @@ -460,15 +464,15 @@ struct Ted { FileSelector file_selector; Selector command_selector; /// general-purpose line buffer for inputs -- used for menus - TextBuffer line_buffer; + TextBuffer *line_buffer; /// use for "find" term in find/find+replace - TextBuffer find_buffer; + TextBuffer *find_buffer; /// "replace" for find+replace - TextBuffer replace_buffer; + TextBuffer *replace_buffer; /// buffer for build output (view only) - TextBuffer build_buffer; + TextBuffer *build_buffer; /// used for command selector - TextBuffer argument_buffer; + TextBuffer *argument_buffer; /// time which the cursor error animation started (cursor turns red, e.g. when there's no autocomplete suggestion) double cursor_error_time; /// should start_cwd be searched for files? set to true if the executable isn't "installed" @@ -593,9 +597,11 @@ struct Ted { // === buffer.c === /// create a new empty buffer with no file name -void buffer_create(TextBuffer *buffer, Ted *ted); +TextBuffer *buffer_new(Ted *ted); /// create a new empty line buffer -void line_buffer_create(TextBuffer *buffer, Ted *ted); +TextBuffer *line_buffer_new(Ted *ted); +/// free all resources used by the buffer and the pointer `buffer` itself +void buffer_free(TextBuffer *buffer); /// Does this buffer have an error? bool buffer_has_error(TextBuffer *buffer); /// get buffer error diff --git a/ted.c b/ted.c index aef59fd..dcc2071 100644 --- a/ted.c +++ b/ted.c @@ -491,7 +491,7 @@ void ted_delete_buffer(Ted *ted, TextBuffer *buffer) { } Node *ted_new_node(Ted *ted) { - if (arr_len(ted->nodes) >= 100) { // TODO: constant + if (arr_len(ted->nodes) >= TED_NODE_MAX) { ted_error(ted, "Too many nodes."); return NULL; } @@ -502,13 +502,12 @@ Node *ted_new_node(Ted *ted) { } TextBuffer *ted_new_buffer(Ted *ted) { - if (arr_len(ted->buffers) >= 100) { // TODO: constant + if (arr_len(ted->buffers) >= TED_BUFFER_MAX) { ted_error(ted, "Too many buffers."); return NULL; } - TextBuffer *buffer = ted_calloc(ted, 1, sizeof *buffer); + TextBuffer *buffer = buffer_new(ted); if (!buffer) return NULL; - buffer_create(buffer, ted); arr_add(ted->buffers, buffer); return buffer; } @@ -519,7 +518,9 @@ float ted_line_buffer_height(Ted *ted) { } void ted_node_switch(Ted *ted, Node *node) { - assert(node->tabs); + while (!node->tabs) { + node = node->split_a; + } ted_switch_to_buffer(ted, node->tabs[node->active_tab]); ted->active_node = node; } diff --git a/ted.h b/ted.h index b1108bc..a632d46 100644 --- a/ted.h +++ b/ted.h @@ -428,11 +428,6 @@ size_t buffer_contents_utf8(TextBuffer *buffer, char *out); char *buffer_contents_utf8_alloc(TextBuffer *buffer); /// perform a series of checks to make sure the buffer doesn't have any invalid values void buffer_check_valid(TextBuffer *buffer); -/// free all resources used by the buffer -/// -/// Once a buffer is freed, you can call buffer_create on it again. -/// Does not free the pointer `buffer` (buffer might not have even been allocated with malloc) -void buffer_free(TextBuffer *buffer); /// clear contents, undo history, etc. of a buffer void buffer_clear(TextBuffer *buffer); /// returns the length of the `line_number`th line (0-indexed), diff --git a/ui.c b/ui.c index 2374377..bca2614 100644 --- a/ui.c +++ b/ui.c @@ -74,7 +74,7 @@ void selector_sort_entries_by_name(Selector *s) { char *selector_update(Ted *ted, Selector *s) { char *ret = NULL; - TextBuffer *line_buffer = &ted->line_buffer; + TextBuffer *line_buffer = ted->line_buffer; ted->selector_open = s; for (u32 i = 0; i < s->n_entries; ++i) { @@ -138,7 +138,7 @@ void selector_render(Ted *ted, Selector *s) { // search buffer float line_buffer_height = ted_line_buffer_height(ted); - buffer_render(&ted->line_buffer, rect4(x1, y1, x2, y1 + line_buffer_height)); + buffer_render(ted->line_buffer, rect4(x1, y1, x2, y1 + line_buffer_height)); y1 += line_buffer_height; TextRenderState text_state = text_render_state_default; @@ -335,8 +335,7 @@ static bool file_selector_cd(Ted *ted, FileSelector *fs, const char *path) { } char *file_selector_update(Ted *ted, FileSelector *fs) { - - TextBuffer *line_buffer = &ted->line_buffer; + TextBuffer *line_buffer = ted->line_buffer; String32 search_term32 = buffer_get_line(line_buffer, 0); fs->sel.enable_cursor = !fs->create_menu || search_term32.len == 0; char *const cwd = fs->cwd; -- cgit v1.2.3