summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--buffer.c59
-rw-r--r--build.c12
-rw-r--r--command.c22
-rw-r--r--find.c17
-rw-r--r--ide-definitions.c6
-rw-r--r--ide-rename-symbol.c8
-rw-r--r--ide-usages.c2
-rw-r--r--main.c33
-rw-r--r--menu.c46
-rw-r--r--node.c1
-rw-r--r--session.c23
-rw-r--r--ted-internal.h20
-rw-r--r--ted.c11
-rw-r--r--ted.h5
-rw-r--r--ui.c7
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;