From 8b784fae0a7d15fe51c5a4aea628f1a54523040d Mon Sep 17 00:00:00 2001 From: Alec Murphy Date: Sat, 2 May 2026 17:03:32 -0400 Subject: [PATCH] Everywhere: Use SaphirNode --- Saphir/Class.HC | 24 ++- Saphir/Cmd.HC | 378 ++++++++++++++++++++++++++++++++++++++++------- Saphir/Main.HC | 3 + Saphir/WinMgr.HC | 1 + 4 files changed, 352 insertions(+), 54 deletions(-) diff --git a/Saphir/Class.HC b/Saphir/Class.HC index d59a363..da43766 100644 --- a/Saphir/Class.HC +++ b/Saphir/Class.HC @@ -1,3 +1,5 @@ +#define SAPHIR_NODE_SIG 0x9999baca + class SaphirAttr { I64 fg; I64 bg; @@ -17,15 +19,35 @@ class SaphirCursor : SaphirAttr { class SaphirKeyDev { U64 sys_cbs; U64 null_cbs; -} +}; + +class SaphirRect { + I32 x1; + I32 y1; + I32 x2; + I32 y2; +}; + +class SaphirNode { + U32 sig; + Bool mode; + SaphirRect rect; + I64 count; + I64 index; + U64** child; + SaphirNode* parent_node; +}; class SaphirGlbls { + Bool debug; Bool enabled; Bool blink; SaphirBorder border; SaphirCursor cursor; SaphirAttr status; SaphirKeyDev kd; + SaphirNode* root_node; + SaphirNode* current_node; I64 doc_cursor_state; } saphir; MemSet(&saphir, 0, sizeof(SaphirGlbls)); \ No newline at end of file diff --git a/Saphir/Cmd.HC b/Saphir/Cmd.HC index d5bea74..06df431 100644 --- a/Saphir/Cmd.HC +++ b/Saphir/Cmd.HC @@ -1,6 +1,28 @@ +U0 saphir_debug_info(SaphirRect* rect) +{ + DCFill; + + gr.dc->color = LTPURPLE; + GrRect(gr.dc, 0, 0, 640, 8); + gr.dc->color = WHITE; + GrPrint(gr.dc, 0, 0, "node: 0x%08x, index: %d", saphir.current_node, saphir.current_node->index); + + gr.dc->color = CYAN; + GrLine(gr.dc, 8 * rect->x1, 8 * rect->y1, 8 * rect->x2, 8 * rect->y2); + GrLine(gr.dc, 8 * rect->x1, 8 * rect->y2, 8 * rect->x2, 8 * rect->y1); +} + +Bool saphir_node_validate(SaphirNode* node) +{ + if (!node) { + return FALSE; + } + return node->sig == SAPHIR_NODE_SIG; +} + Bool saphir_task_is_windowed(CTask* task) { - if (!task || task == ac.task) { + if (!task || task == ac.task || task == adam_task) { return FALSE; } if ((task->display_flags & 1 << DISPLAYf_SHOW) && ((task->display_flags & 1 << DISPLAYf_NOT_RAW))) @@ -8,75 +30,325 @@ Bool saphir_task_is_windowed(CTask* task) return FALSE; } -U0 saphir_split_row() +I64 saphir_reflow_step(SaphirNode* node) { - CTask* task1 = sys_focus_task; - CTask* task2 = User; - MemCpy(&task2->win_left, &task1->win_left, 32); - task1->win_bottom = (task1->win_top + task1->win_bottom) / 2; - task2->win_top = task1->win_bottom + 2; + switch (node->mode) { + case 0: + return ((node->rect.y2 - node->rect.y1) / node->count); + case 1: + return ((node->rect.x2 - node->rect.x1) / node->count); + default: + return 0; + } +} + +U0 saphir_reflow_win(CTask* task, SaphirRect* rect) +{ + if (!task || !rect) { + return; + } + task->win_top = rect->y1; + task->win_left = rect->x1; + task->win_bottom = rect->y2; + task->win_right = rect->x2; WinZBufUpdate; } -U0 saphir_split_col() +U0 saphir_remove_child(SaphirNode* node, I64 i) { - CTask* task1 = sys_focus_task; - CTask* task2 = User; - MemCpy(&task2->win_left, &task1->win_left, 32); - task1->win_right = (task1->win_left + task1->win_right) / 2; - task2->win_left = task1->win_right + 2; - WinZBufUpdate; -} - -I64 saphir_win_select_CR(I64 dir) -{ - if (dir & 1) { - return TEXT_COLS + 1; + I64 j; + for (j = i; j < 16; j++) { + node->child[j] = node->child[j + 1]; } - return TEXT_ROWS + 1; -} - -I64 saphir_win_select_XY(I64 wt, I64 wl, I64 dir) -{ - if (dir & 1) { - return wl; + --node->count; + if (node->index == i) { + --node->index; + node->index = MaxI64(0, node->index); } - return wt; } -I64 saphir_win_select_pos(I64 dir) +U0 saphir_destroy_node(SaphirNode* node) { - return 1 - (2 * (dir < SC_CURSOR_RIGHT)); -} - -Bool saphir_task_should_focus(CTask* task1, I64 i, I64 wl, I64 dir) -{ - if (dir & 1) { - return task1->win_left == i; + if (!node) { + return; } - return task1->win_top == i && task1->win_left == wl; + // FIXME: do this cleanly + if (node->child) { + Free(node->child); + } + Free(node); } -U0 saphir_win_select(I64 dir) +Bool saphir_reflow(SaphirNode* node = NULL) { - CTask* task = sys_focus_task; - CTask* task1; - I64 wt = task->win_top; - I64 wl = task->win_left; - I64 i, j, k; + if (!node) { + node = saphir.root_node; + } - i = j = saphir_win_select_pos(dir); - i += saphir_win_select_XY(wt, wl, dir); - k = saphir_win_select_CR(dir); + SaphirNode* tmp_node; + SaphirRect rect; + SaphirRect debug_rect; + MemCpy(&rect, &node->rect, sizeof(SaphirRect)); - for (i = i; i > 0 && i < k; i += j) { - task1 = adam_task->next_task; - while (task1 != adam_task) { - if (saphir_task_is_windowed(task1) && saphir_task_should_focus(task1, i, wl, dir)) { - WinFocus(task1); - return; + // orig_x1, orig_y1 + debug_rect.x1 = rect.x1; + debug_rect.y1 = rect.y1; + + I64 i; + I64 step = saphir_reflow_step(node); + + for (i = 0; i < node->count; i++) { + + switch (node->mode) { + case 0: + rect.y2 = rect.y1 + step; + break; + case 1: + rect.x2 = rect.x1 + step; + break; + default: + PopUpOk("error1 : node->mode invalid"); + "mode: %d\n", node->mode; + Break; + } + + if (saphir_node_validate(node->child[i])) { + tmp_node = node->child[i]; + if (tmp_node->count < 2) { + node->child[i] = tmp_node->child[0]; + saphir_destroy_node(tmp_node); + if (saphir.current_node == tmp_node) { + saphir.current_node = node; + node->index = i; + } + return FALSE; } - task1 = task1->next_task; + MemCpy(&node->child[i](SaphirNode*)->rect, &rect, sizeof(SaphirRect)); + if (saphir.current_node == node && saphir.current_node->index == i) { + saphir.current_node = node->child[i]; + } + if (!saphir_reflow(node->child[i])) { + return FALSE; + } + } else { + if (TaskValidate(node->child[i])) { + saphir_reflow_win(node->child[i], &rect); + if (saphir.current_node == node && saphir.current_node->index == i) { + WinFocus(node->child[i]); + } + WinZBufUpdate; + } else { + saphir_remove_child(node, i); + return FALSE; + } + } + + switch (node->mode) { + case 0: + rect.y1 = rect.y2 + 2; + break; + case 1: + rect.x1 = rect.x2 + 2; + break; + default: + PopUpOk("error2 : node->mode invalid"); + Break; } } + + if (node == saphir.current_node && saphir.debug) { + debug_rect.x2 = rect.x2; + debug_rect.y2 = rect.y2; + saphir_debug_info(&debug_rect); + } + + return TRUE; +} + +U0 saphir_reflow_task_end() +{ + while (!saphir_reflow) + ; +} + +U0 saphir_reflow_task_end_cb() +{ + Spawn(&saphir_reflow_task_end); + Exit; +} + +U0 saphir_rect_set_defaults(SaphirRect* rect) +{ + rect->x1 = 1; + rect->x2 = TEXT_COLS - 2; + rect->y1 = 2; + rect->y2 = TEXT_ROWS - 3; +} + +SaphirNode* saphir_node_alloc(I64 mode = 0) +{ + SaphirNode* node = CAlloc(sizeof(SaphirNode)); + node->child = CAlloc(sizeof(U64*) * 16); + node->mode = mode; + node->sig = SAPHIR_NODE_SIG; + return node; +} + +U0 saphir_node_append_task(SaphirNode* node, CTask* task) +{ + if (!node || !task) { + return; + } + if (node->count && !(node->count % 16)) { + PopUpOk("FIXME: realloc node->child"); + Break; + } + node->child[node->count++] = task; + task->task_end_cb = &saphir_reflow_task_end_cb; +} + +U0 saphir_node_init_root() +{ + saphir.root_node = saphir_node_alloc(1); + saphir_rect_set_defaults(&saphir.root_node->rect); + SaphirNode* node = saphir.root_node; + CTask* task1 = adam_task->next_task; + while (task1 != adam_task) { + if (saphir_task_is_windowed(task1)) { + saphir_node_append_task(node, task1); + } + task1 = task1->next_task; + } +} + +U0 saphir_split_pane(I64 dir) +{ + SaphirNode* node = saphir_node_alloc(dir); + CTask* new_task = User; + + saphir_node_append_task(node, saphir.current_node->child[saphir.current_node->index]); + saphir_node_append_task(node, new_task); + node->parent_node = saphir.current_node; + + saphir.current_node->child[saphir.current_node->index] = node; + saphir.current_node = node; + saphir.current_node->index = 1; // 1= focus the new User task created by splitting + + while (!saphir_reflow) + ; +} + +U0 saphir_split_row() +{ + saphir_split_pane(0); +} +U0 saphir_split_col() +{ + saphir_split_pane(1); +} + +U0 saphir_win_select_up() +{ + SaphirNode* node = saphir.current_node; + if (!node->mode && node->index) { + --node->index; + return; + } + node = node->parent_node; + while (node && node->mode) { + node = node->parent_node; + } + if (node && node->index) { + --node->index; + } + if (node) { + saphir.current_node = node; + } +} + +U0 saphir_win_select_down() +{ + SaphirNode* node = saphir.current_node; + if (!node->mode && node->index < node->count - 1) { + ++node->index; + return; + } + node = node->parent_node; + while (node && node->mode) { + node = node->parent_node; + } + if (node && node->index < node->count - 1) { + ++node->index; + } + if (node) { + saphir.current_node = node; + } +} + +U0 saphir_win_select_left() +{ + SaphirNode* node = saphir.current_node; + if (node->mode && node->index) { + --node->index; + return; + } + node = node->parent_node; + while (node && !node->mode) { + node = node->parent_node; + } + if (node && node->index) { + --node->index; + } + if (node) { + saphir.current_node = node; + } +} + +U0 saphir_win_select_right() +{ + SaphirNode* node = saphir.current_node; + if (node->mode && node->index < node->count - 1) { + ++node->index; + return; + } + node = node->parent_node; + while (node && !node->mode) { + node = node->parent_node; + } + if (node && node->index < node->count - 1) { + ++node->index; + } + if (node) { + saphir.current_node = node; + } +} +U0 saphir_win_select(I64 dir) +{ + switch (dir) { + case SC_CURSOR_UP: + saphir_win_select_up; + break; + case SC_CURSOR_DOWN: + saphir_win_select_down; + break; + case SC_CURSOR_LEFT: + saphir_win_select_left; + break; + case SC_CURSOR_RIGHT: + saphir_win_select_right; + break; + default: + break; + } + while (!saphir_reflow) + ; +} + +U0 saphir_enable() +{ + saphir_node_init_root; + saphir.current_node = saphir.root_node; + saphir.current_node->index = 0; + while (!saphir_reflow) + ; } \ No newline at end of file diff --git a/Saphir/Main.HC b/Saphir/Main.HC index 5c0f92f..2c67467 100644 --- a/Saphir/Main.HC +++ b/Saphir/Main.HC @@ -3,6 +3,9 @@ I64 Saphir(Bool enable = TRUE) if (enable == saphir.enabled) { return enable; } + if (enable) { + saphir_enable; + } fn_patch(&Blink, &saphir_Blink, enable); fn_patch(&DocBorder, &saphir_DocBorder, enable); // fn_patch(&DocBorderLstDraw, &saphir_DocBorderLstDraw, enable); diff --git a/Saphir/WinMgr.HC b/Saphir/WinMgr.HC index 4e371d0..4cb83bb 100644 --- a/Saphir/WinMgr.HC +++ b/Saphir/WinMgr.HC @@ -25,6 +25,7 @@ CDoc* saphir_DocBorder(U64) saphir.doc_cursor_state = 0; } task->win_bottom = MinI64(task->win_bottom, TEXT_ROWS - 3); + task->win_right = MinI64(task->win_right, TEXT_COLS - 2); if (task != sys_focus_task) { return NULL; }