mirror of
https://git.checksum.fail/alec/saphir.git
synced 2026-06-16 02:49:38 +03:00
361 lines
8.2 KiB
HolyC
361 lines
8.2 KiB
HolyC
extern I64 Saphir(Bool enable = TRUE);
|
|
|
|
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 || task == adam_task) {
|
|
return FALSE;
|
|
}
|
|
if ((task->display_flags & 1 << DISPLAYf_SHOW) && ((task->display_flags & 1 << DISPLAYf_NOT_RAW)))
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
I64 saphir_reflow_step(SaphirNode* node)
|
|
{
|
|
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_remove_child(SaphirNode* node, I64 i)
|
|
{
|
|
I64 j;
|
|
for (j = i; j < 16; j++) {
|
|
node->child[j] = node->child[j + 1];
|
|
}
|
|
--node->count;
|
|
if (node->index == i) {
|
|
--node->index;
|
|
node->index = MaxI64(0, node->index);
|
|
}
|
|
}
|
|
|
|
U0 saphir_destroy_node(SaphirNode* node)
|
|
{
|
|
if (!node) {
|
|
return;
|
|
}
|
|
// FIXME: do this cleanly
|
|
if (node->child) {
|
|
Free(node->child);
|
|
}
|
|
Free(node);
|
|
}
|
|
|
|
Bool saphir_reflow(SaphirNode* node = NULL)
|
|
{
|
|
if (!node) {
|
|
node = saphir.root_node;
|
|
}
|
|
|
|
SaphirNode* tmp_node;
|
|
SaphirRect rect;
|
|
SaphirRect debug_rect;
|
|
MemCpy(&rect, &node->rect, sizeof(SaphirRect));
|
|
|
|
// 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;
|
|
}
|
|
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()
|
|
{
|
|
if (saphir.current_node == saphir.root_node && saphir.current_node->count == 1) {
|
|
Saphir(0);
|
|
return;
|
|
}
|
|
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)
|
|
;
|
|
}
|