diff options
-rw-r--r-- | main.c | 5 | ||||
-rw-r--r-- | node.c | 53 | ||||
-rw-r--r-- | ted.c | 1 | ||||
-rw-r--r-- | ted.h | 1 |
4 files changed, 49 insertions, 11 deletions
@@ -1,5 +1,5 @@ // @TODO: -// - get ctrl+w to work properly +// - Ctrl+j = :join // - split depth limit // - resize split (i.e. change split_pos) @@ -332,7 +332,6 @@ int main(int argc, char **argv) { u16 node_index = (u16)ted_new_node(ted); assert(node_index == 0); Node *node = ted->active_node = &ted->nodes[node_index]; - ted->root = node; node->tabs = NULL; arr_add(node->tabs, 0); @@ -611,7 +610,7 @@ int main(int argc, char **argv) { if (ted->active_node) { float const padding = settings->padding; float x1 = padding, y = window_height-padding, x2 = window_width-padding; - Node *node = ted->root; + Node *node = &ted->nodes[0]; if (ted->find) { float y2 = y; y -= find_menu_height(ted); @@ -32,8 +32,24 @@ static void node_free(Node *node) { memset(node, 0, sizeof *node); } -static void node_close(Ted *ted, Node *node) { - // @TODO(split) +// returns index of parent in ted->nodes, or -1 if this is the root node. +static i32 node_parent(Ted *ted, u16 node_idx) { + for (u16 i = 0; i < TED_MAX_NODES; ++i) { + if (ted->nodes_used[i]) { + Node *node = &ted->nodes[i]; + if (!node->tabs) { + if (node->split_a == node_idx || node->split_b == node_idx) + return i; + } + } + } + return -1; +} + +static void node_close(Ted *ted, u16 node_idx) { + assert(node_idx < TED_MAX_NODES); + assert(ted->nodes_used[node_idx]); + Node *node = &ted->nodes[node_idx]; // delete all associated buffers arr_foreach_ptr(node->tabs, u16, tab) { @@ -42,12 +58,35 @@ static void node_close(Ted *ted, Node *node) { } node_free(node); + ted->nodes_used[node_idx] = false; - u16 node_index = (u16)(node - ted->nodes); - assert(node_index < TED_MAX_NODES); - ted->nodes_used[node_index] = false; - if (ted->active_node == node) { + i32 parent_idx = node_parent(ted, node_idx); + if (parent_idx < 0) { + // no parent; this must be the root node ted->active_node = NULL; + } else { + // turn parent from split node into tab node + Node *parent = &ted->nodes[parent_idx]; + assert(!parent->tabs); + u16 other_side; + if (node_idx == parent->split_a) { + other_side = parent->split_b; + } else { + assert(node_idx == parent->split_b); + other_side = parent->split_a; + } + // replace parent with other side of split + *parent = ted->nodes[other_side]; + + ted->nodes_used[other_side] = false; + if (ted->active_node == node) { + Node *new_active_node = parent; + // make sure we don't set the active node to a split + while (!new_active_node->tabs) + new_active_node = &ted->nodes[new_active_node->split_a]; + ted->active_node = new_active_node; + ted->active_buffer = &ted->buffers[ted->active_node->tabs[ted->active_node->active_tab]]; + } } } @@ -58,7 +97,7 @@ static bool node_tab_close(Ted *ted, Node *node, u16 index) { assert(index < ntabs); if (ntabs == 1) { // only 1 tab left, just close the node - node_close(ted, node); + node_close(ted, (u16)(node - ted->nodes)); return false; } else { u16 buffer_index = node->tabs[index]; @@ -119,6 +119,7 @@ static i32 ted_new_node(Ted *ted) { bool *nodes_used = ted->nodes_used; for (i32 i = 0; i < TED_MAX_NODES; ++i) { if (!nodes_used[i]) { + memset(&ted->nodes[i], 0, sizeof ted->nodes[i]); // zero new node nodes_used[i] = true; return i; } @@ -236,7 +236,6 @@ typedef struct Ted { // while a menu or something is open, there is no active buffer. when the menu is closed, // the old active buffer needs to be restored. that's what this stores. TextBuffer *prev_active_buffer; - Node *root; Node *active_node; Settings settings; float window_width, window_height; |