diff --git a/Defaults.HC b/Defaults.HC new file mode 100644 index 0000000..5c44ec6 --- /dev/null +++ b/Defaults.HC @@ -0,0 +1,11 @@ +/* default configuration */ + +saphir.border.focus_bg = saphir.border.bg = BLACK; +saphir.border.focus_fg = LTRED; +saphir.border.fg = LTGRAY; + +saphir.cursor.bg = CYAN; +saphir.cursor.fg = WHITE; + +saphir.blink = TRUE; +// saphir.border.list = TRUE; \ No newline at end of file diff --git a/KeyDev.HC b/KeyDev.HC deleted file mode 100644 index e8fded3..0000000 --- a/KeyDev.HC +++ /dev/null @@ -1,48 +0,0 @@ -U0 @saphir_key_nop() {} - -Bool @saphir_put_key(I64 ch, I64 sc) { - if (sc & SCF_ALT && !(sc & SCF_CTRL)) { - switch (ch) { - case 0: - switch (sc.u8[0]) { - case SC_CURSOR_UP: - @saphir_win_select(SAPHIR_WIN_UP); - return TRUE; - case SC_CURSOR_DOWN: - @saphir_win_select(SAPHIR_WIN_DOWN); - return TRUE; - case SC_CURSOR_LEFT: - @saphir_win_select(SAPHIR_WIN_LEFT); - return TRUE; - case SC_CURSOR_RIGHT: - @saphir_win_select(SAPHIR_WIN_RIGHT); - return TRUE; - } - break; - case 'h': - @saphir_split_horz; - return TRUE; - break; - case 'v': - @saphir_split_vert; - return TRUE; - break; - } - } - return FALSE; -} - -U64 @tos_fp_cbs_enabled = - keydev.fp_ctrl_alt_cbs; // Save pointer to TempleOS system-wide (CTRL-ALT) - // callbacks - -U64 @tos_fp_cbs_disabled = CAlloc(0xD0); -keydev.fp_ctrl_alt_cbs = - @tos_fp_cbs_disabled; // Disable TempleOS system-wide (CTRL-ALT) callbacks - -// FIXME: Ideally, we would add a new KeyDev here, but since we need to override -// the HomeKeyPlugIns, we will need to patch MyKeyDev instead. - -// KeyDevAdd(&@saphir_put_key, &MyPutS, 0x10000000, -// TRUE); // Enable Saphir keyboard shortcuts -@function_patch(&MyPutKey, &@saphir_put_key); diff --git a/Load.HC b/Load.HC index 91c3cc6..8052635 100644 --- a/Load.HC +++ b/Load.HC @@ -1,11 +1,12 @@ /* clang-format off */ -#include "Patch"; -#include "Win"; -#include "KeyDev"; -#include "Status"; -#include "Saphir"; +#include "M:/Saphir/Misc"; +#include "M:/Saphir/Class"; +#include "M:/Saphir/WinMgr"; +#include "M:/Saphir/Cmd"; +#include "M:/Saphir/KeyDev"; +#include "M:/Saphir/Main"; /* clang-format on */ -WinTileHorz; \ No newline at end of file +#include "M:/Defaults"; \ No newline at end of file diff --git a/Patch.HC b/Patch.HC deleted file mode 100644 index 6f6549a..0000000 --- a/Patch.HC +++ /dev/null @@ -1,88 +0,0 @@ -U0 @function_patch(U32 from, U32 to) { - *(from(U8 *)) = 0xE9; - *((from + 1)(I32 *)) = to - from - 5; -} - -U0 @gr_update_text_bg2() { - I64 reg RSI *dst = gr.dc2->body, reg R13 c, row, col, num_rows = TEXT_ROWS, - num_cols = TEXT_COLS, i, j, cur_ch, - reg R12 w1 = gr.dc2->width_internal, w2 = -7 * w1 + 8, - w3 = 7 * w1, w4 = 0; - U32 *src = gr.text_base; - Bool blink_flag = Blink; - U8 *dst2 = dst; - - if (gr.pan_text_x || gr.hide_col) { - gr.pan_text_x = ClampI64(gr.pan_text_x, -7, 7); - j = AbsI64(gr.pan_text_x) / FONT_WIDTH + 1; - num_cols -= j; - if (gr.pan_text_x < 0) { - src += j; - i = FONT_WIDTH * j + gr.pan_text_x; - } else - i = gr.pan_text_x; - dst2 = dst(U8 *) + i; - w4 = j; - w3 += j * FONT_WIDTH; - - j *= FONT_WIDTH; - dst(U8 *) = gr.dc2->body; - for (row = num_rows * FONT_HEIGHT; row--;) { - for (col = i; col--;) - *dst(U8 *)++ = 0; - dst(U8 *) += w1 - i - j; - for (col = j; col--;) - *dst(U8 *)++ = 0; - } - } - dst = dst2; - - if (gr.pan_text_y || gr.hide_row) { - gr.pan_text_y = ClampI64(gr.pan_text_y, -7, 7); - j = AbsI64(gr.pan_text_y) / FONT_HEIGHT + 1; - num_rows -= j; - if (gr.pan_text_y < 0) { - src += w1 / FONT_WIDTH * j; - i = w1 * (FONT_HEIGHT * j + gr.pan_text_y); - } else - i = w1 * gr.pan_text_y; - dst2 = dst(U8 *) + i; - - j *= w1 * FONT_HEIGHT; - dst(U8 *) = gr.dc2->body; - for (row = i; row--;) - *dst(U8 *)++ = 0; - dst(U8 *) = - gr.dc2->body + TEXT_ROWS * TEXT_COLS * FONT_HEIGHT * FONT_WIDTH - j; - for (row = j; row--;) - *dst(U8 *)++ = 0; - } - dst = dst2; - - for (row = num_rows; row--;) { - for (col = num_cols; col--;) { - cur_ch = *src++; - if (cur_ch & (ATTRF_SEL | ATTRF_INVERT | ATTRF_BLINK)) { - if (cur_ch & ATTRF_SEL) - cur_ch.u8[1] = cur_ch.u8[1] ^ 0xFF; - if (cur_ch & ATTRF_INVERT) - cur_ch.u8[1] = cur_ch.u8[1] << 4 + cur_ch.u8[1] >> 4; - if (cur_ch & ATTRF_BLINK && blink_flag) - cur_ch.u8[1] = 0x30; - else - cur_ch.u8[1] = 0xFF; - } - c = gr.to_8_colors[cur_ch.u8[1] >> 4]; - MOV U64[RSI], R13 ADD RSI, R12 MOV U64[RSI], R13 ADD RSI, - R12 MOV U64[RSI], R13 ADD RSI, R12 MOV U64[RSI], R13 ADD RSI, - R12 MOV U64[RSI], R13 ADD RSI, R12 MOV U64[RSI], R13 ADD RSI, - R12 MOV U64[RSI], R13 ADD RSI, R12 MOV U64[RSI], R13 dst(U8 *) += w2; - } - src += w4; - dst(U8 *) += w3; - } -} - -@function_patch(&GrUpdateTextBG, - &@gr_update_text_bg2); // Patch GrUpdateTextBG to make cursor - // blinking less irritating \ No newline at end of file diff --git a/Run.HC b/Run.HC index 6d2bfee..62de68f 100644 --- a/Run.HC +++ b/Run.HC @@ -1,3 +1,2 @@ -Adam("StrPrint(Fs->cur_dir, \"/\");\n"); -Adam("Fs->cur_dv = Let2Drv('T');\n"); -AdamFile("Load"); \ No newline at end of file +Adam("#include \"M:/Load\";\n"); +XTalkWait(Fs, "Saphir;\n"); \ No newline at end of file diff --git a/Saphir.HC b/Saphir.HC deleted file mode 100644 index 4059d07..0000000 --- a/Saphir.HC +++ /dev/null @@ -1,19 +0,0 @@ -U0 SaphirTask() { - I64 count; - I64 i; - CTask *task; - while (1) { - count = @windowed_task_count; - for (i = 0; i < count; i++) { - task = @windowed_task_index(i); - @set_border_doc_for_win(task); - @set_cursor_for_focused_win(task); - @draw_saphir_border_for_win(task); - @ensure_win_no_overlap_status_bar(task); - } - @update_status_bar; - Sleep(1); - } -} - -Spawn(&SaphirTask, , "Saphir"); \ No newline at end of file diff --git a/Saphir/Class.HC b/Saphir/Class.HC new file mode 100644 index 0000000..19aa3d2 --- /dev/null +++ b/Saphir/Class.HC @@ -0,0 +1,30 @@ +class SaphirAttr { + I64 fg; + I64 bg; +}; + +class SaphirBorder : SaphirAttr { + I64 focus_fg; + I64 focus_bg; + Bool list; +}; + +class SaphirCursor : SaphirAttr { + // Bool blink; + U64 stub; +}; + +class SaphirKeyDev { + U64 sys_cbs; + U64 null_cbs; +} + +class SaphirGlbls { + Bool enabled; + Bool blink; + SaphirBorder border; + SaphirCursor cursor; + SaphirKeyDev kd; + 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 new file mode 100644 index 0000000..c4391d3 --- /dev/null +++ b/Saphir/Cmd.HC @@ -0,0 +1,93 @@ +Bool saphir_task_is_windowed(CTask* task) +{ + if (!task || task == ac.task) { + return FALSE; + } + if ((task->display_flags & 1 << DISPLAYf_SHOW) && ((task->display_flags & 1 << DISPLAYf_NOT_RAW))) + return TRUE; + return FALSE; +} + +U0 saphir_split_row() +{ + 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; + WinZBufUpdate; +} + +U0 saphir_split_col() +{ + 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; +} + +U0 saphir_win_select(I64 dir) +{ + CTask* task = sys_focus_task; + CTask* task1; + I64 wt = task->win_top; + I64 wl = task->win_left; + I64 i; + I64 j; + + switch (dir) { + case SC_CURSOR_UP: + i = wt - 1; + j = -1; + break; + case SC_CURSOR_DOWN: + i = wt + 1; + j = 1; + break; + case SC_CURSOR_LEFT: + i = wl - 1; + j = -1; + break; + case SC_CURSOR_RIGHT: + i = wl + 1; + j = 1; + break; + } + + switch (dir) { + case SC_CURSOR_UP: + case SC_CURSOR_DOWN: + for (i = i; i > 0 && i < TEXT_ROWS + 1; i += j) { + task1 = adam_task->next_task; + while (task1 != adam_task) { + if (saphir_task_is_windowed(task1)) { + if (task1->win_top == i && task1->win_left == wl) { + WinFocus(task1); + return; + } + } + task1 = task1->next_task; + } + } + break; + case SC_CURSOR_LEFT: + case SC_CURSOR_RIGHT: + for (i = i; i > 0 && i < TEXT_COLS + 1; i += j) { + task1 = adam_task->next_task; + while (task1 != adam_task) { + if (saphir_task_is_windowed(task1)) { + if (task1->win_left == i) { + WinFocus(task1); + return; + } + } + task1 = task1->next_task; + } + } + break; + default: + break; + } +} \ No newline at end of file diff --git a/Saphir/KeyDev.HC b/Saphir/KeyDev.HC new file mode 100644 index 0000000..2668684 --- /dev/null +++ b/Saphir/KeyDev.HC @@ -0,0 +1,71 @@ +saphir.kd.sys_cbs = keydev.fp_ctrl_alt_cbs; +saphir.kd.null_cbs = CAlloc(0xd0); + +I64 saphir_get_char() +{ + I64 sc = NULL; + I64 ch = NULL; + do { + ch = GetKey(&sc, 0, 0); + if (!ch) { + switch (sc & 0xff) { + case SC_CURSOR_UP: + case SC_CURSOR_DOWN: + case SC_CURSOR_LEFT: + case SC_CURSOR_RIGHT: + return ((sc & 0xff) << 8); + default: + break; + } + } + } while (!ch); + return ch; +} + +U0 saphir_handle_prefix_cmd() +{ + I64 ch = saphir_get_char; + switch (ch >> 8) { + case SC_CURSOR_UP: + case SC_CURSOR_DOWN: + case SC_CURSOR_LEFT: + case SC_CURSOR_RIGHT: + saphir_win_select(ch >> 8); + return; + default: + break; + } + switch (ch & 0xff) { + case '%': + saphir_split_col; + return; + case '"': + saphir_split_row; + return; + default: + break; + } +} + +Bool saphir_MyPutKey(I64 ch, I64 sc) +{ + switch (ch) { + case CH_CTRLB: + saphir_handle_prefix_cmd; + return TRUE; + } + return FALSE; +} + +U0 saphir_keydev(Bool enable) +{ + fn_patch(&MyPutKey, &saphir_MyPutKey, enable); + switch (enable) { + case 0: + keydev.fp_ctrl_alt_cbs = saphir.kd.sys_cbs; + return; + default: + keydev.fp_ctrl_alt_cbs = saphir.kd.null_cbs; + return; + } +} \ No newline at end of file diff --git a/Saphir/Main.HC b/Saphir/Main.HC new file mode 100644 index 0000000..5c0f92f --- /dev/null +++ b/Saphir/Main.HC @@ -0,0 +1,16 @@ +I64 Saphir(Bool enable = TRUE) +{ + if (enable == saphir.enabled) { + return enable; + } + fn_patch(&Blink, &saphir_Blink, enable); + fn_patch(&DocBorder, &saphir_DocBorder, enable); + // fn_patch(&DocBorderLstDraw, &saphir_DocBorderLstDraw, enable); + fn_patch(&DrvTextAttrGet, &saphir_DrvTextAttrGet, enable); + saphir_cursor(enable); + saphir_keydev(enable); + if (!enable) { + DCFill; + } + saphir.enabled = enable; +} \ No newline at end of file diff --git a/Saphir/Misc.HC b/Saphir/Misc.HC new file mode 100644 index 0000000..435cbe0 --- /dev/null +++ b/Saphir/Misc.HC @@ -0,0 +1,53 @@ +#define FN_MAXNUM 32 + +class FunctionIndex { + U64 addr; + U64 prologue; +} fn_index[FN_MAXNUM]; +MemSet(fn_index, 0, sizeof(FunctionIndex)); + +I64 fn_restore(U32 from) +{ + if (!from) { + return -1; + } + + I64 i; + for (i = 0; i < FN_MAXNUM; i++) { + if (fn_index[i].addr == from) { + MemCpy(fn_index[i].addr, &fn_index[i].prologue, 8); + fn_index[i].addr = fn_index[i].prologue = 0; + return 0; + } + } + return -1; +} + +I64 fn_patch(U32 from, U32 to, Bool patch = TRUE) +{ + if (!from || !to) { + return -1; + } + if (!patch) { + return fn_restore(from); + } + + I64 i = 0; + while (i < FN_MAXNUM && fn_index[i].addr) { + if (fn_index[i].addr == from) { + // Function already patched + return -1; + } + ++i; + } + if (i >= FN_MAXNUM) { + // Maximum entires reached + return -1; + } + + fn_index[i].addr = from; + MemCpy(&fn_index[i].prologue, from, 8); + *(from(U8*)) = 0xE9; + *((from + 1)(I32*)) = to - from - 5; + return 0; +} \ No newline at end of file diff --git a/Saphir/WinMgr.HC b/Saphir/WinMgr.HC new file mode 100644 index 0000000..807a7e3 --- /dev/null +++ b/Saphir/WinMgr.HC @@ -0,0 +1,91 @@ +#define SAPHIR_CURSOR_PATCH_ADDR &DocRecalc + 0x2c62 + +U0 saphir_update_cursor() +{ + U16 res = 0xb4; + res |= ((saphir.cursor.fg & 0xf) << 4 | (saphir.cursor.bg & 0xf)) << 8; + MemCpy(SAPHIR_CURSOR_PATCH_ADDR, &res, 2); + MemSet(SAPHIR_CURSOR_PATCH_ADDR + 0x02, 0x90, 3); +} + +CDoc* saphir_DocBorder(U64) +{ + U64 addr = Caller; + if (addr >= &DocEd && addr <= (&DocEd + sizeof(DocEd))) { + asm { + MOV RAX, &DocBorder + ADD RAX, 6 + JMP RAX + } + } + + CTask* task = sys_task_being_scrn_updated; + if (saphir.doc_cursor_state) { + task->display_doc->flags = saphir.doc_cursor_state; + saphir.doc_cursor_state = 0; + } + task->win_bottom = MinI64(task->win_bottom, TEXT_ROWS - 3); + if (task != sys_focus_task) { + return NULL; + } + if (ac.task) { + Kill(ac.task); + ac.task = NULL; + } + saphir_update_cursor; + gr.dc->color = BLACK; + GrRect(gr.dc, 0, GR_HEIGHT - 8, GR_WIDTH, 8); + gr.dc->color = LTGRAY; + GrPrint(gr.dc, 0, GR_HEIGHT - 8, "[0x%08x] %s", task, + task->task_title); + + return NULL; +} + +U8 saphir_DrvTextAttrGet(U64) +{ + U64 addr = Caller; + if (addr >= &DrvRep && addr <= (&DrvRep + sizeof(DrvRep))) { + asm { + MOV RAX, &DrvTextAttrGet + ADD RAX, 6 + POP R11 + JMP RAX + } + } + if (addr >= &TaskInit && addr <= (&TaskInit + sizeof(TaskInit))) { + return NULL; + } + + if (sys_focus_task == sys_task_being_scrn_updated) { + return (saphir.border.focus_bg & 0xf) << 4 | (saphir.border.focus_fg & 0xf); + } + if (!saphir.doc_cursor_state) { + saphir.doc_cursor_state = sys_task_being_scrn_updated->display_doc->flags; + DocCursor(, sys_task_being_scrn_updated->display_doc); + } + return (saphir.border.bg & 0xf) << 4 | (saphir.border.fg & 0xf); +} + +U0 saphir_cursor(Bool enable) +{ + switch (enable) { + case 0: + MemCpy(SAPHIR_CURSOR_PATCH_ADDR, &saphir.cursor.stub, 8); + return; + default: + MemCpy(&saphir.cursor.stub, SAPHIR_CURSOR_PATCH_ADDR, 8); + saphir_update_cursor; + return; + } +} + +Bool saphir_Blink(F64 Hz = 2.5) +{ + if (!saphir.blink) { + return 1; + } + if (!Hz) + return 0; + return ToI64(cnts.jiffies * 2 * Hz / JIFFY_FREQ) & 1; +} \ No newline at end of file diff --git a/Status.HC b/Status.HC deleted file mode 100644 index dc4142b..0000000 --- a/Status.HC +++ /dev/null @@ -1,7 +0,0 @@ -U0 @update_status_bar() { - gr.dc->color = BLACK; - GrRect(gr.dc, 0, GR_HEIGHT - 8, GR_WIDTH, 8); - gr.dc->color = LTGRAY; - GrPrint(gr.dc, 0, GR_HEIGHT - 8, "[0x%08x] %s", sys_focus_task, - sys_focus_task->task_title); -} \ No newline at end of file diff --git a/Win.HC b/Win.HC deleted file mode 100644 index 4227787..0000000 --- a/Win.HC +++ /dev/null @@ -1,175 +0,0 @@ -#define SAPHIR_WIN_UP 0 -#define SAPHIR_WIN_DOWN 1 -#define SAPHIR_WIN_LEFT 2 -#define SAPHIR_WIN_RIGHT 3 - -CDoc *SAPHIR_BORDER_DOC = DocNew; - -CTask *@is_task_windowed(CTask *task) { - if ((task->display_flags & 1 << DISPLAYf_SHOW) && - ((task->display_flags & 1 << DISPLAYf_NOT_RAW))) - return task; - return NULL; -} - -I64 @windowed_task_count() { - CTask *task; - I64 count = 0; - task = adam_task->next_task; - while (task != adam_task) { - if (@is_task_windowed(task)) - count++; - task = task->next_task; - } - return count; -} - -CTask *@windowed_task_index(I64 index) { - CTask *task; - I64 count = 0; - task = adam_task->next_task; - while (task != adam_task) { - if (@is_task_windowed(task)) { - if (count == index) - return task; - count++; - } - task = task->next_task; - } - return NULL; -} - -U0 @set_border_doc_for_win(CTask *task) { - task->border_doc = SAPHIR_BORDER_DOC; -} - -U0 @draw_saphir_border_for_win(CTask *task) { - I64 color = LTGRAY; - if (task == sys_focus_task) - color = LTRED; - I64 x; - I64 y; - I64 wl = task->win_left - 1; - I64 wr = task->win_right + 1; - I64 wt = task->win_top - 1; - I64 wb = task->win_bottom + 1; - for (x = wl; x < wr + 1; x++) { - gr.text_base[(wt * TEXT_COLS) + x].u8[1] = color; - gr.text_base[(wb * TEXT_COLS) + x].u8[1] = color; - } - for (y = wt; y < wb + 1; y++) { - gr.text_base[(y * TEXT_COLS) + wl].u8[1] = color; - gr.text_base[(y * TEXT_COLS) + wr].u8[1] = color; - } -} - -U0 @ensure_win_no_overlap_status_bar(CTask *task) { - task->win_bottom = MinI64(task->win_bottom, TEXT_ROWS - 3); -} - -U0 @set_cursor_for_focused_win(CTask *task) { - if (task == sys_focus_task) { - task->put_doc->flags &= ~(1 << DOCf_HIDE_CURSOR); - } else { - task->put_doc->flags |= (1 << DOCf_HIDE_CURSOR); - } -} - -U0 @saphir_win_select(I64 dir) { - CTask *task = sys_focus_task; - I64 wt = task->win_top; - I64 wl = task->win_left; - I64 i; - I64 j; - - switch (dir) { - case SAPHIR_WIN_UP: - i = wt - 1; - j = -1; - break; - case SAPHIR_WIN_DOWN: - i = wt + 1; - j = 1; - break; - case SAPHIR_WIN_LEFT: - i = wl - 1; - j = -1; - break; - case SAPHIR_WIN_RIGHT: - i = wl + 1; - j = 1; - break; - } - - CTask *task1; - - switch (dir) { - case SAPHIR_WIN_UP: - case SAPHIR_WIN_DOWN: - for (i = i; i > 0 && i < TEXT_ROWS + 1; i += j) { - task1 = adam_task->next_task; - while (task1 != adam_task) { - if (@is_task_windowed(task1)) { - if (task1->win_top == i && task1->win_left == wl) { - WinFocus(task1); - return; - } - } - task1 = task1->next_task; - } - } - break; - case SAPHIR_WIN_LEFT: - case SAPHIR_WIN_RIGHT: - for (i = i; i > 0 && i < TEXT_COLS + 1; i += j) { - task1 = adam_task->next_task; - while (task1 != adam_task) { - if (@is_task_windowed(task1)) { - if (task1->win_left == i) { - WinFocus(task1); - return; - } - } - task1 = task1->next_task; - } - } - break; - default: - break; - } -} - -U0 @saphir_split_horz() { - CTask *task1 = sys_focus_task; - I64 wt = task1->win_top; - I64 wl = task1->win_left; - I64 wb = task1->win_bottom; - I64 wr = task1->win_right; - - task1->win_bottom = wb / 2; - - CTask *task2 = User; - task2->win_top = (wb / 2) + 2; - task2->win_bottom = wb; - task2->win_left = wl; - task2->win_right = wr; - - WinZBufUpdate; -} - -U0 @saphir_split_vert() { - CTask *task1 = sys_focus_task; - I64 wt = task1->win_top; - I64 wb = task1->win_bottom; - I64 wr = task1->win_right; - - task1->win_right = wr / 2; - - CTask *task2 = User; - task2->win_top = wt; - task2->win_bottom = wb; - task2->win_left = (wr / 2) + 2; - task2->win_right = wr; - - WinZBufUpdate; -} \ No newline at end of file