summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--base.h4
-rw-r--r--buffer.c2
-rw-r--r--command.c9
-rw-r--r--main.c2
-rw-r--r--node.c60
-rw-r--r--ted-internal.h27
-rw-r--r--ted.c18
-rw-r--r--ted.h56
8 files changed, 103 insertions, 75 deletions
diff --git a/base.h b/base.h
index 9aba28a..be4031e 100644
--- a/base.h
+++ b/base.h
@@ -81,6 +81,10 @@ typedef int64_t i64;
// (for i8 and i16, you can use %d)
#define I32_FMT "%" PRId32
#define I64_FMT "%" PRId64
+#define I8_MIN ((i8)0x80)
+#define I16_MIN ((i16)0x8000)
+#define I32_MIN ((i32)0x80000000)
+#define I64_MIN ((i64)0x8000000000000000)
#define I8_MAX 0x7f
#define I16_MAX 0x7fff
#define I32_MAX 0x7fffffff
diff --git a/buffer.c b/buffer.c
index bc1e6da..64d9024 100644
--- a/buffer.c
+++ b/buffer.c
@@ -2836,7 +2836,7 @@ bool buffer_save(TextBuffer *buffer) {
buffer->undo_history_write_pos = arr_len(buffer->undo_history);
if (buffer->path && str_has_suffix(path_filename(buffer->path), "ted.cfg")
&& buffer_settings(buffer)->auto_reload_config) {
- ted_load_configs(buffer->ted, true);
+ ted_reload_configs(buffer->ted);
}
}
return success;
diff --git a/command.c b/command.c
index 9abdcbf..65ca61f 100644
--- a/command.c
+++ b/command.c
@@ -591,13 +591,16 @@ void command_execute_ex(Ted *ted, Command c, const CommandArgument *full_argumen
}
} break;
case CMD_TAB_NEXT:
- if (node) node_tab_next(ted, node, argument);
+ if (node && argument > I32_MIN && argument < I32_MAX)
+ node_tab_next(ted, node, (i32)argument);
break;
case CMD_TAB_PREV:
- if (node) node_tab_prev(ted, node, argument);
+ if (node && argument > I32_MIN && argument < I32_MAX)
+ node_tab_prev(ted, node, (i32)argument);
break;
case CMD_TAB_SWITCH:
- if (node) node_tab_switch(ted, node, argument);
+ if (node && argument > I32_MIN && argument < I32_MAX)
+ node_tab_switch(ted, node, (i32)argument);
break;
case CMD_TAB_MOVE_LEFT: {
u16 active_tab = node->active_tab;
diff --git a/main.c b/main.c
index 03820a5..3c23958 100644
--- a/main.c
+++ b/main.c
@@ -511,7 +511,7 @@ int main(int argc, char **argv) {
PROFILE_TIME(configs_start)
- ted_load_configs(ted, false);
+ ted_load_configs(ted);
PROFILE_TIME(configs_end)
PROFILE_TIME(fonts_start)
diff --git a/node.c b/node.c
index e4fd043..ac452e9 100644
--- a/node.c
+++ b/node.c
@@ -2,7 +2,10 @@
#include "ted-internal.h"
-void node_switch_to_tab(Ted *ted, Node *node, u16 new_tab_index) {
+static void node_switch_to_tab(Ted *ted, Node *node, u16 new_tab_index) {
+ if (new_tab_index >= arr_len(node->tabs))
+ return;
+
node->active_tab = new_tab_index;
if (node == ted->active_node) {
// switch active buffer
@@ -13,26 +16,29 @@ void node_switch_to_tab(Ted *ted, Node *node, u16 new_tab_index) {
}
// move n tabs to the right
-void node_tab_next(Ted *ted, Node *node, i64 n) {
- assert(node->tabs);
+void node_tab_next(Ted *ted, Node *node, i32 n) {
u16 ntabs = (u16)arr_len(node->tabs);
- u16 tab_idx = (u16)mod_i64(node->active_tab + n, ntabs);
+ if (!ntabs) return;
+ u16 tab_idx = (u16)mod_i64((i64)node->active_tab + n, ntabs);
node_switch_to_tab(ted, node, tab_idx);
}
-void node_tab_prev(Ted *ted, Node *node, i64 n) {
+void node_tab_prev(Ted *ted, Node *node, i32 n) {
node_tab_next(ted, node, -n);
}
-void node_tab_switch(Ted *ted, Node *node, i64 tab) {
+void node_tab_switch(Ted *ted, Node *node, i32 tab) {
assert(node->tabs);
- if (tab < arr_len(node->tabs)) {
+ if (tab >= 0 && tab < (i32)arr_len(node->tabs)) {
node_switch_to_tab(ted, node, (u16)tab);
}
}
-void node_tabs_swap(Node *node, u16 tab1, u16 tab2) {
- assert(tab1 < arr_len(node->tabs) && tab2 < arr_len(node->tabs));
+void node_tabs_swap(Node *node, i32 tab1i, i32 tab2i) {
+ if (tab1i < 0 || tab1i >= (i32)arr_len(node->tabs) || tab2i < 0 || tab2i >= (i32)arr_len(node->tabs))
+ return;
+
+ u16 tab1 = (u16)tab1i, tab2 = (u16)tab2i;
if (node->active_tab == tab1) node->active_tab = tab2;
else if (node->active_tab == tab2) node->active_tab = tab1;
u16 tmp = node->tabs[tab1];
@@ -45,9 +51,10 @@ void node_free(Node *node) {
memset(node, 0, sizeof *node);
}
-i32 node_parent(Ted *ted, u16 node_idx) {
- bool *nodes_used = ted->nodes_used;
- assert(node_idx < TED_MAX_NODES && nodes_used[node_idx]);
+i32 node_parent(Ted *ted, i32 node_idx) {
+ const bool *nodes_used = ted->nodes_used;
+ if (node_idx < 0 || node_idx >= TED_MAX_NODES || !nodes_used[node_idx])
+ return -1;
for (u16 i = 0; i < TED_MAX_NODES; ++i) {
if (nodes_used[i]) {
Node *node = &ted->nodes[i];
@@ -61,16 +68,11 @@ i32 node_parent(Ted *ted, u16 node_idx) {
}
// the root has depth 0, and a child node has 1 more than its parent's depth.
-static u8 node_depth(Ted *ted, u16 node_idx) {
+static u8 node_depth(Ted *ted, i32 node_idx) {
u8 depth = 0;
- while (1) {
- i32 parent = node_parent(ted, node_idx);
- if (parent < 0) {
- break;
- } else {
- node_idx = (u16)parent;
- depth += 1;
- }
+ while (node_idx != -1) {
+ node_idx = node_parent(ted, node_idx);
+ ++depth;
}
return depth;
}
@@ -111,15 +113,13 @@ void node_join(Ted *ted, Node *node) {
}
}
-void node_close(Ted *ted, u16 node_idx) {
+void node_close(Ted *ted, i32 node_idx) {
ted->dragging_tab_node = NULL;
ted->resizing_split = NULL;
- if (node_idx >= TED_MAX_NODES) {
- assert(0);
+ if (node_idx < 0 || node_idx >= TED_MAX_NODES) {
return;
}
if (!ted->nodes_used[node_idx]) {
- assert(0);
return;
}
i32 parent_idx = node_parent(ted, node_idx);
@@ -168,11 +168,15 @@ void node_close(Ted *ted, u16 node_idx) {
}
-bool node_tab_close(Ted *ted, Node *node, u16 index) {
+bool node_tab_close(Ted *ted, Node *node, i32 index) {
ted->dragging_tab_node = NULL;
u16 ntabs = (u16)arr_len(node->tabs);
- assert(index < ntabs);
+
+ if (index < 0 || index >= ntabs) {
+ return false;
+ }
+
if (ntabs == 1) {
// only 1 tab left, just close the node
node_close(ted, (u16)(node - ted->nodes));
@@ -181,7 +185,7 @@ bool node_tab_close(Ted *ted, Node *node, u16 index) {
bool was_active = ted->active_node == node; // ted->active_node will be set to NULL when the active buffer is deleted.
u16 buffer_index = node->tabs[index];
// remove tab from array
- arr_remove(node->tabs, index);
+ arr_remove(node->tabs, (size_t)index);
ted_delete_buffer(ted, buffer_index);
ntabs = (u16)arr_len(node->tabs); // update ntabs
diff --git a/ted-internal.h b/ted-internal.h
index 8357155..11bdbcf 100644
--- a/ted-internal.h
+++ b/ted-internal.h
@@ -792,6 +792,25 @@ void usages_quit(Ted *ted);
// === macro.c ===
void macro_add(Ted *ted, Command command, const CommandArgument *argument);
+void macros_free(Ted *ted);
+
+// === menu.c ===
+void menu_update(Ted *ted);
+void menu_render(Ted *ted);
+/// move to next/previous command
+void menu_shell_move(Ted *ted, int direction);
+/// move to previous command
+void menu_shell_up(Ted *ted);
+/// move to next command
+void menu_shell_down(Ted *ted);
+
+// === node.c ===
+void node_free(Node *node);
+void node_frame(Ted *ted, Node *node, Rect r);
+
+// === syntax.c ===
+/// free up resources used by `syntax.c`
+void syntax_quit(void);
// === tags.c ===
/// get all tags in the tags file as SymbolInfos.
@@ -807,5 +826,13 @@ void ted_go_to_lsp_document_position(Ted *ted, LSP *lsp, LSPDocumentPosition pos
void ted_cancel_lsp_request(Ted *ted, LSPServerRequestID *request);
/// convert LSPWindowMessageType to MessageType
MessageType ted_message_type_from_lsp(LSPWindowMessageType type);
+/// Returns the index of an available node, or -1 if none are available
+i32 ted_new_node(Ted *ted);
+/// check for orphaned nodes and node cycles
+void ted_check_for_node_problems(Ted *ted);
+/// load ted configuration
+void ted_load_configs(Ted *ted);
+/// get colors to use for message box
+void ted_color_settings_for_message_type(MessageType type, ColorSetting *bg_color, ColorSetting *border_color);
#endif // TED_INTERNAL_H_
diff --git a/ted.c b/ted.c
index c623f0a..ea28f13 100644
--- a/ted.c
+++ b/ted.c
@@ -471,7 +471,7 @@ void ted_reset_active_buffer(Ted *ted) {
}
-i32 ted_new_buffer(Ted *ted) {
+static i32 ted_new_buffer(Ted *ted) {
bool *buffers_used = ted->buffers_used;
for (i32 i = 1; // start from 1, so as not to use the null buffer
i < TED_MAX_BUFFERS; ++i) {
@@ -678,8 +678,7 @@ void ted_reload_all(Ted *ted) {
}
// load/reload configs
-void ted_load_configs(Ted *ted, bool reloading) {
- if (reloading) config_free(ted);
+void ted_load_configs(Ted *ted) {
// copy global config to local config
char local_config_filename[TED_PATH_MAX];
@@ -708,12 +707,13 @@ void ted_load_configs(Ted *ted, bool reloading) {
config_read(ted, &parts, start_cwd_filename);
}
config_parse(ted, &parts);
-
-
- if (reloading) {
- // reset text size
- ted_load_fonts(ted);
- }
+}
+
+void ted_reload_configs(Ted *ted) {
+ config_free(ted);
+ ted_load_configs(ted);
+ // reset text size
+ ted_load_fonts(ted);
}
void ted_press_key(Ted *ted, SDL_Keycode keycode, SDL_Keymod modifier) {
diff --git a/ted.h b/ted.h
index 96e7b88..10e1bca 100644
--- a/ted.h
+++ b/ted.h
@@ -773,7 +773,6 @@ void usages_find(Ted *ted);
void macro_start_recording(Ted *ted, u32 index);
void macro_stop_recording(Ted *ted);
void macro_execute(Ted *ted, u32 index);
-void macros_free(Ted *ted);
// === menu.c ===
void menu_close(Ted *ted);
@@ -784,38 +783,39 @@ void menu_escape(Ted *ted);
float menu_get_width(Ted *ted);
/// get rectangle which menu takes up
Rect menu_rect(Ted *ted);
-void menu_update(Ted *ted);
-void menu_render(Ted *ted);
-/// move to next/previous command
-void menu_shell_move(Ted *ted, int direction);
-/// move to previous command
-void menu_shell_up(Ted *ted);
-/// move to next command
-void menu_shell_down(Ted *ted);
// === node.c ===
-void node_switch_to_tab(Ted *ted, Node *node, u16 new_tab_index);
/// go to the `n`th next tab (e.g. `n=1` goes to the next tab)
/// going past the end of the tabs will "wrap around" to the first one.
-void node_tab_next(Ted *ted, Node *node, i64 n);
+///
+/// if `node` is a split, nothing happens.
+void node_tab_next(Ted *ted, Node *node, i32 n);
/// go to the `n`th previous tab (e.g. `n=1` goes to the previous tab)
/// going before the first tab will "wrap around" to the last one.
-void node_tab_prev(Ted *ted, Node *node, i64 n);
-/// switch to a specific tab. if `tab` is out of range, nothing happens.
-void node_tab_switch(Ted *ted, Node *node, i64 tab);
+///
+/// if `node` is a split, nothing happens.
+void node_tab_prev(Ted *ted, Node *node, i32 n);
+/// switch to a specific tab.
+///
+/// if `tab` is out of range or `node` is a split, nothing happens.
+void node_tab_switch(Ted *ted, Node *node, i32 tab);
/// swap the position of two tabs
-void node_tabs_swap(Node *node, u16 tab1, u16 tab2);
-void node_free(Node *node);
+///
+/// if `node` is a split or either index is out of range, nothing happens.
+void node_tabs_swap(Node *node, i32 tab1, i32 tab2);
/// returns index of parent in ted->nodes, or -1 if this is the root node.
-i32 node_parent(Ted *ted, u16 node_idx);
+i32 node_parent(Ted *ted, i32 node_idx);
/// join this node with its sibling
void node_join(Ted *ted, Node *node);
/// close a node, WITHOUT checking for unsaved changes
-void node_close(Ted *ted, u16 node_idx);
+///
+/// does nothing if node_idx is out of range
+void node_close(Ted *ted, i32 node_idx);
/// close tab, WITHOUT checking for unsaved changes!
/// returns true if the node is still open
-bool node_tab_close(Ted *ted, Node *node, u16 index);
-void node_frame(Ted *ted, Node *node, Rect r);
+///
+/// does nothing and returns false if node_idx is out of range
+bool node_tab_close(Ted *ted, Node *node, i32 index);
/// make a split
void node_split(Ted *ted, Node *node, bool vertical);
/// switch to the other side of the current split.
@@ -842,7 +842,7 @@ Language language_from_str(const char *str);
const char *language_to_str(Language language);
/// get the color setting associated with the given syntax highlighting type
ColorSetting syntax_char_type_to_color_setting(SyntaxCharType t);
-/// returns ')' for '(', etc., or 0 if c is not an opening bracket
+/// returns ')' for '(', '[' for ']', etc., or 0 if c is not a bracket
char32_t syntax_matching_bracket(Language lang, char32_t c);
/// returns true for opening brackets, false for closing brackets/non-brackets
bool syntax_is_opening_bracket(Language lang, char32_t c);
@@ -851,8 +851,6 @@ bool syntax_is_opening_bracket(Language lang, char32_t c);
/// To highlight multiple lines, start out with a zeroed SyntaxState, and pass a pointer to it each time.
/// You can set char_types to NULL if you just want to advance the state, and don't care about the character types.
void syntax_highlight(SyntaxState *state, Language lang, const char32_t *line, u32 line_len, SyntaxCharType *char_types);
-/// free up resources used by syntax.c
-void syntax_quit(void);
// === tags.c ===
void tags_generate(Ted *ted, bool run_in_build_window);
@@ -954,10 +952,6 @@ bool ted_open_file(Ted *ted, const char *filename);
/// if `filename` is NULL, this creates an untitled buffer.
/// returns true on success.
bool ted_new_file(Ted *ted, const char *filename);
-/// returns the index of an available buffer, or -1 if none are available
-i32 ted_new_buffer(Ted *ted);
-/// Returns the index of an available node, or -1 if none are available
-i32 ted_new_node(Ted *ted);
/// Opposite of ted_new_buffer
/// Make sure you set active_buffer to something else if you delete it!
void ted_delete_buffer(Ted *ted, u16 index);
@@ -968,8 +962,8 @@ bool ted_save_all(Ted *ted);
void ted_switch_to_buffer(Ted *ted, TextBuffer *buffer);
/// switch to this node
void ted_node_switch(Ted *ted, Node *node);
-/// load ted.cfg files
-void ted_load_configs(Ted *ted, bool reloading);
+/// reload ted configuration
+void ted_reload_configs(Ted *ted);
/// handle a key press
void ted_press_key(Ted *ted, i32 keycode, u32 modifier);
/// get the buffer and buffer position where the mouse is.
@@ -979,10 +973,6 @@ Status ted_get_mouse_buffer_pos(Ted *ted, TextBuffer **pbuffer, BufferPos *ppos)
void ted_flash_error_cursor(Ted *ted);
/// how tall is a line buffer?
float ted_line_buffer_height(Ted *ted);
-/// check for orphaned nodes and node cycles
-void ted_check_for_node_problems(Ted *ted);
-/// get colors to use for message box
-void ted_color_settings_for_message_type(MessageType type, ColorSetting *bg_color, ColorSetting *border_color);
// === ui.c ===
/// move selector cursor up by `n` entries