summaryrefslogtreecommitdiff
path: root/node.c
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2023-08-09 12:24:40 -0300
committerpommicket <pommicket@gmail.com>2023-08-09 12:25:33 -0300
commit310faf5d70b8a65c83c013a31ab87d9d3f301767 (patch)
tree9e48b8afad2651de90e6b4e74ac9b96d94968fbd /node.c
parent17e65f8dd57762a2e79aeb79a5c0fb69849c07f9 (diff)
new node/buffer system, needs more testing
Diffstat (limited to 'node.c')
-rw-r--r--node.c179
1 files changed, 80 insertions, 99 deletions
diff --git a/node.c b/node.c
index 6acbfa8..51a1422 100644
--- a/node.c
+++ b/node.c
@@ -10,8 +10,8 @@ static void node_switch_to_tab(Ted *ted, Node *node, u16 new_tab_index) {
if (node == ted->active_node) {
// switch active buffer
assert(node->tabs);
- u16 buffer_idx = node->tabs[new_tab_index];
- ted_switch_to_buffer(ted, &ted->buffers[buffer_idx]);
+ TextBuffer *buffer = node->tabs[new_tab_index];
+ ted_switch_to_buffer(ted, buffer);
}
}
@@ -41,130 +41,124 @@ void node_tabs_swap(Node *node, i32 tab1i, i32 tab2i) {
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];
+ TextBuffer *temp = node->tabs[tab1];
node->tabs[tab1] = node->tabs[tab2];
- node->tabs[tab2] = tmp;
+ node->tabs[tab2] = temp;
}
void node_free(Node *node) {
arr_free(node->tabs);
memset(node, 0, sizeof *node);
+ free(node);
}
-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];
- if (!node->tabs) {
- if (node->split_a == node_idx || node->split_b == node_idx)
- return i;
- }
+Node *node_parent(Ted *ted, Node *child) {
+ if (!child)
+ return NULL;
+ arr_foreach_ptr(ted->nodes, NodePtr, pnode) {
+ Node *node = *pnode;
+ if (!node->tabs) {
+ if (node->split_a == child || node->split_b == child)
+ return node;
}
}
- return -1;
+ return NULL;
}
// the root has depth 0, and a child node has 1 more than its parent's depth.
-static u8 node_depth(Ted *ted, i32 node_idx) {
+static u8 node_depth(Ted *ted, Node *node) {
u8 depth = 0;
- while (node_idx != -1) {
- node_idx = node_parent(ted, node_idx);
+ while (node) {
+ node = node_parent(ted, node);
++depth;
}
return depth;
}
void node_join(Ted *ted, Node *node) {
- i32 parent_idx = node_parent(ted, (u16)(node - ted->nodes));
- if (parent_idx >= 0) {
- Node *parent = &ted->nodes[parent_idx];
- Node *a = &ted->nodes[parent->split_a];
- Node *b = &ted->nodes[parent->split_b];
+ Node *parent = node_parent(ted, node);
+ if (parent) {
+ Node *a = parent->split_a;
+ Node *b = parent->split_b;
if (a->tabs && b->tabs) {
if (ted->active_node == a || ted->active_node == b) {
ted->active_node = parent;
}
- arr_foreach_ptr(a->tabs, u16, tab) {
+ arr_foreach_ptr(a->tabs, TextBufferPtr, tab) {
arr_add(parent->tabs, *tab);
}
- arr_foreach_ptr(b->tabs, u16, tab) {
+ arr_foreach_ptr(b->tabs, TextBufferPtr, tab) {
arr_add(parent->tabs, *tab);
}
if (!parent->tabs) {
ted_out_of_mem(ted);
+ return;
+ }
+
+ parent->split_a = NULL;
+ parent->split_b = NULL;
+ if (node == a) {
+ parent->active_tab = a->active_tab;
} else {
- if (node == a) {
- parent->active_tab = a->active_tab;
- } else {
- parent->active_tab = (u16)arr_len(a->tabs) + b->active_tab;
- }
- node_free(a);
- node_free(b);
- ted->nodes_used[parent->split_a] = false;
- ted->nodes_used[parent->split_b] = false;
- // this isn't really needed since parent->tabs is not NULL anymore.
- parent->split_a = 0;
- parent->split_b = 0;
+ parent->active_tab = (u16)arr_len(a->tabs) + b->active_tab;
}
+ node_free(a);
+ node_free(b);
+ arr_remove_item(ted->nodes, a);
+ arr_remove_item(ted->nodes, b);
+
}
}
}
-void node_close(Ted *ted, i32 node_idx) {
+void node_close(Ted *ted, Node *node) {
ted->dragging_tab_node = NULL;
ted->resizing_split = NULL;
- if (node_idx < 0 || node_idx >= TED_MAX_NODES) {
+ if (!node) {
return;
}
- if (!ted->nodes_used[node_idx]) {
- return;
- }
- i32 parent_idx = node_parent(ted, node_idx);
- ted->nodes_used[node_idx] = false;
-
- Node *node = &ted->nodes[node_idx];
+
+
+ Node *parent = node_parent(ted, node);
bool was_active = ted->active_node == node;
// delete all associated buffers
- arr_foreach_ptr(node->tabs, u16, tab) {
- u16 buffer_index = *tab;
- ted_delete_buffer(ted, buffer_index);
+ arr_foreach_ptr(node->tabs, TextBufferPtr, tab) {
+ TextBuffer *buffer = *tab;
+ ted_delete_buffer(ted, buffer);
}
node_free(node);
- if (parent_idx < 0) {
+ if (!parent) {
// 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];
if (parent->tabs) {
assert(0); // this node's parent should be a split node
return;
}
- u16 other_side;
- if (node_idx == parent->split_a) {
+ Node *other_side;
+ if (node == parent->split_a) {
other_side = parent->split_b;
} else {
- assert(node_idx == parent->split_b);
+ assert(node == 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;
+ *parent = *other_side;
+ arr_remove_item(ted->nodes, other_side);
if (was_active) {
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];
+ new_active_node = new_active_node->split_a;
ted_node_switch(ted, new_active_node);
}
}
+
+ arr_remove_item(ted->nodes, node);
}
@@ -179,14 +173,14 @@ bool node_tab_close(Ted *ted, Node *node, i32 index) {
if (ntabs == 1) {
// only 1 tab left, just close the node
- node_close(ted, (u16)(node - ted->nodes));
+ node_close(ted, node);
return false;
} else {
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];
+ TextBuffer *buffer = node->tabs[index];
// remove tab from array
arr_remove(node->tabs, (size_t)index);
- ted_delete_buffer(ted, buffer_index);
+ ted_delete_buffer(ted, buffer);
ntabs = (u16)arr_len(node->tabs); // update ntabs
assert(ntabs);
@@ -196,7 +190,7 @@ bool node_tab_close(Ted *ted, Node *node, i32 index) {
node->active_tab = clamp_u16(node->active_tab, 0, ntabs - 1);
if (was_active) {
// fix active buffer if necessary
- ted_switch_to_buffer(ted, &ted->buffers[node->tabs[node->active_tab]]);
+ ted_switch_to_buffer(ted, node->tabs[node->active_tab]);
}
return true;
}
@@ -240,7 +234,7 @@ void node_frame(Ted *ted, Node *node, Rect r) {
if (tab_index <= arr_len(node->tabs)) {
Node *drag_node = ted->dragging_tab_node;
u16 drag_index = ted->dragging_tab_idx;
- u16 tab = drag_node->tabs[drag_index];
+ TextBuffer *tab = drag_node->tabs[drag_index];
// remove the old tab
arr_remove(drag_node->tabs, drag_index);
@@ -253,7 +247,7 @@ void node_frame(Ted *ted, Node *node, Rect r) {
arr_insert(node->tabs, tab_index, tab);
if (arr_len(drag_node->tabs) == 0) {
// removed the last tab from a node; close it
- node_close(ted, (u16)(drag_node - ted->nodes));
+ node_close(ted, drag_node);
} else {
// make sure active tab is valid
drag_node->active_tab = clamp_u16(drag_node->active_tab, 0, (u16)arr_len(drag_node->tabs) - 1);
@@ -261,7 +255,7 @@ void node_frame(Ted *ted, Node *node, Rect r) {
ted->dragging_tab_node = NULL; // stop dragging
// switch to this buffer
- ted_switch_to_buffer(ted, &ted->buffers[tab]);
+ ted_switch_to_buffer(ted, tab);
}
}
}
@@ -271,8 +265,7 @@ void node_frame(Ted *ted, Node *node, Rect r) {
if (rect_contains_point(tab_bar_rect, click->pos)) {
u16 tab_index = (u16)((click->pos.x - r.pos.x) / tab_width);
if (tab_index < arr_len(node->tabs)) {
- u16 buffer_idx = node->tabs[tab_index];
- TextBuffer *buffer = &ted->buffers[buffer_idx];
+ TextBuffer *buffer = node->tabs[tab_index];
// close that tab
if (buffer_unsaved_changes(buffer)) {
// make sure unsaved changes dialog is opened
@@ -292,7 +285,7 @@ void node_frame(Ted *ted, Node *node, Rect r) {
TextRenderState text_state = text_render_state_default;
for (u16 i = 0; i < ntabs; ++i) {
- TextBuffer *buffer = &ted->buffers[node->tabs[i]];
+ TextBuffer *buffer = node->tabs[i];
char tab_title[256];
const char *filename = buffer_display_filename(buffer);
Rect tab_rect = rect_xywh(r.pos.x + tab_width * i, r.pos.y, tab_width, tab_bar_height);
@@ -340,9 +333,7 @@ void node_frame(Ted *ted, Node *node, Rect r) {
text_render(font);
}
- u16 buffer_index = node->tabs[node->active_tab];
- TextBuffer *buffer = &ted->buffers[buffer_index];
- assert(ted->buffers_used[buffer_index]);
+ TextBuffer *buffer = node->tabs[node->active_tab];
Rect buffer_rect = r;
buffer_rect.pos.y += tab_bar_height;
@@ -355,8 +346,7 @@ void node_frame(Ted *ted, Node *node, Rect r) {
} else {
float padding = settings->padding;
// this node is a split
- Node *a = &ted->nodes[node->split_a];
- Node *b = &ted->nodes[node->split_b];
+ Node *a = node->split_a, *b = node->split_b;
Rect r1 = r, r2 = r;
SDL_Cursor *resize_cursor = node->split_vertical ? ted->cursor_resize_v : ted->cursor_resize_h;
if (node == ted->resizing_split) {
@@ -399,14 +389,12 @@ void node_frame(Ted *ted, Node *node, Rect r) {
}
void node_split(Ted *ted, Node *node, bool vertical) {
- if (node_depth(ted, (u16)(node - ted->nodes)) >= 4) return; // prevent splitting too deep
+ if (node_depth(ted, node) >= 4) return; // prevent splitting too deep
if (arr_len(node->tabs) > 1) { // need at least 2 tabs to split
- i32 left_idx = ted_new_node(ted);
- i32 right_idx = ted_new_node(ted);
- if (left_idx >= 0 && right_idx >= 0) {
- Node *left = &ted->nodes[left_idx];
- Node *right = &ted->nodes[right_idx];
+ Node *left = ted_new_node(ted);
+ Node *right = ted_new_node(ted);
+ if (left && right) {
u16 active_tab = node->active_tab;
// put active tab on the right
arr_add(right->tabs, node->tabs[active_tab]);
@@ -418,38 +406,31 @@ void node_split(Ted *ted, Node *node, bool vertical) {
}
arr_clear(node->tabs);
- node->split_a = (u16)left_idx;
- node->split_b = (u16)right_idx;
+ node->split_a = left;
+ node->split_b = right;
node->split_vertical = vertical;
node->split_pos = 0.5f;
if (node == ted->active_node)
- ted_node_switch(ted, &ted->nodes[right_idx]);
+ ted_node_switch(ted, right);
}
}
}
void node_split_switch(Ted *ted) {
- assert(ted->active_node);
- u16 active_node_idx = (u16)(ted->active_node - ted->nodes);
- i32 parent_idx = node_parent(ted, active_node_idx);
- if (parent_idx < 0) return;
- Node *parent = &ted->nodes[parent_idx];
- if (parent) {
- if (parent->split_a == active_node_idx) {
- ted_node_switch(ted, &ted->nodes[parent->split_b]);
- } else {
- ted_node_switch(ted, &ted->nodes[parent->split_a]);
- }
+ Node *parent = node_parent(ted, ted->active_node);
+ if (!parent) return;
+ if (parent->split_a == ted->active_node) {
+ ted_node_switch(ted, parent->split_b);
+ } else {
+ ted_node_switch(ted, parent->split_a);
}
}
void node_split_swap(Ted *ted) {
assert(ted->active_node);
- u16 active_node_idx = (u16)(ted->active_node - ted->nodes);
- i32 parent_idx = node_parent(ted, active_node_idx);
- if (parent_idx < 0) return;
- Node *parent = &ted->nodes[parent_idx];
- u16 temp = parent->split_a;
+ Node *parent = node_parent(ted, ted->active_node);
+ if (!parent) return;
+ Node *temp = parent->split_a;
parent->split_a = parent->split_b;
parent->split_b = temp;
}