mirror of
https://git.checksum.fail/alec/saphir.git
synced 2026-06-16 02:49:38 +03:00
Everywhere: Use SaphirNode
This commit is contained in:
+23
-1
@@ -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));
|
||||
+325
-53
@@ -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)
|
||||
;
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user