mirror of
https://git.checksum.fail/alec/saphir.git
synced 2026-05-01 18:09:42 +03:00
Compare commits
6 Commits
9946b34455
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c1bfc4ce81 | ||
|
|
868bb9f643 | ||
|
|
b6610916c3 | ||
|
|
edec5d9bb5 | ||
|
|
1e379a1053 | ||
|
|
98b17d20fa |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1 +1,4 @@
|
|||||||
|
.clang-format
|
||||||
.vscode/
|
.vscode/
|
||||||
|
build/
|
||||||
|
scripts/
|
||||||
|
|||||||
11
Defaults.HC
Normal file
11
Defaults.HC
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
/* default configuration */
|
||||||
|
|
||||||
|
saphir.border.focus_bg = saphir.border.bg = saphir.status.bg = BLACK;
|
||||||
|
saphir.border.focus_fg = LTRED;
|
||||||
|
saphir.border.fg = saphir.status.fg = LTGRAY;
|
||||||
|
|
||||||
|
saphir.cursor.bg = CYAN;
|
||||||
|
saphir.cursor.fg = WHITE;
|
||||||
|
|
||||||
|
saphir.blink = TRUE;
|
||||||
|
// saphir.border.list = TRUE;
|
||||||
48
KeyDev.HC
48
KeyDev.HC
@@ -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);
|
|
||||||
13
Load.HC
13
Load.HC
@@ -1,11 +1,12 @@
|
|||||||
/* clang-format off */
|
/* clang-format off */
|
||||||
|
|
||||||
#include "Patch";
|
#include "M:/Saphir/Misc";
|
||||||
#include "Win";
|
#include "M:/Saphir/Class";
|
||||||
#include "KeyDev";
|
#include "M:/Saphir/WinMgr";
|
||||||
#include "Status";
|
#include "M:/Saphir/Cmd";
|
||||||
#include "Saphir";
|
#include "M:/Saphir/KeyDev";
|
||||||
|
#include "M:/Saphir/Main";
|
||||||
|
|
||||||
/* clang-format on */
|
/* clang-format on */
|
||||||
|
|
||||||
WinTileHorz;
|
#include "M:/Defaults";
|
||||||
88
Patch.HC
88
Patch.HC
@@ -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
|
|
||||||
13
README.md
13
README.md
@@ -8,7 +8,9 @@ Tiling window extensions for TempleOS WinMgr
|
|||||||
|
|
||||||
Saphir extends the existing TempleOS WinMgr to provide tiling window functionality, as well as provide some sane defaults to those who prefer a less "blinky" interface.
|
Saphir extends the existing TempleOS WinMgr to provide tiling window functionality, as well as provide some sane defaults to those who prefer a less "blinky" interface.
|
||||||
|
|
||||||
The active window is displayed with `LTRED` border color; inactive windows use `LTGRAY` border color.
|
The default configuration settings are in `Defaults.HC` - these settings can be modified at any time.
|
||||||
|
|
||||||
|
You can toggle Saphir with `Saphir(0);` to revert to existing WinMgr behavior, or run with default arg to re-enable.
|
||||||
|
|
||||||
Cursors are automatically hidden for inactive windows; the active window cursor blinks `CYAN` & `WHITE` instead of `YELLOW` and `BLACK`.
|
Cursors are automatically hidden for inactive windows; the active window cursor blinks `CYAN` & `WHITE` instead of `YELLOW` and `BLACK`.
|
||||||
|
|
||||||
@@ -20,11 +22,12 @@ Saphir does not require you to recompile your Kernel; any changes to existing fu
|
|||||||
|
|
||||||
`#include "Run";`
|
`#include "Run";`
|
||||||
|
|
||||||
# Keyboard shortcuts
|
# Commands
|
||||||
|
|
||||||
`ALT` + arrow keys : navigate windows
|
`CTRL-B` : Prefix
|
||||||
|
|
||||||
`ALT` + `h` : split window horizontal
|
- `%` : Split window horizontally
|
||||||
|
|
||||||
`ALT` + `v` : split window vertical
|
- `"` : Split window vertically
|
||||||
|
|
||||||
|
- `arrow keys` : Select the window in [direction] from the active window
|
||||||
|
|||||||
5
Run.HC
5
Run.HC
@@ -1,3 +1,2 @@
|
|||||||
Adam("StrPrint(Fs->cur_dir, \"/\");\n");
|
Adam("#include \"M:/Load\";\n");
|
||||||
Adam("Fs->cur_dv = Let2Drv('T');\n");
|
XTalkWait(Fs, "Saphir;\n");
|
||||||
AdamFile("Load");
|
|
||||||
19
Saphir.HC
19
Saphir.HC
@@ -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");
|
|
||||||
31
Saphir/Class.HC
Normal file
31
Saphir/Class.HC
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
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;
|
||||||
|
SaphirAttr status;
|
||||||
|
SaphirKeyDev kd;
|
||||||
|
I64 doc_cursor_state;
|
||||||
|
} saphir;
|
||||||
|
MemSet(&saphir, 0, sizeof(SaphirGlbls));
|
||||||
82
Saphir/Cmd.HC
Normal file
82
Saphir/Cmd.HC
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
I64 saphir_win_select_CR(I64 dir)
|
||||||
|
{
|
||||||
|
if (dir & 1) {
|
||||||
|
return TEXT_COLS + 1;
|
||||||
|
}
|
||||||
|
return TEXT_ROWS + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
I64 saphir_win_select_XY(I64 wt, I64 wl, I64 dir)
|
||||||
|
{
|
||||||
|
if (dir & 1) {
|
||||||
|
return wl;
|
||||||
|
}
|
||||||
|
return wt;
|
||||||
|
}
|
||||||
|
|
||||||
|
I64 saphir_win_select_pos(I64 dir)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
return task1->win_top == i && task1->win_left == wl;
|
||||||
|
}
|
||||||
|
|
||||||
|
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, j, k;
|
||||||
|
|
||||||
|
i = j = saphir_win_select_pos(dir);
|
||||||
|
i += saphir_win_select_XY(wt, wl, dir);
|
||||||
|
k = saphir_win_select_CR(dir);
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
task1 = task1->next_task;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
72
Saphir/KeyDev.HC
Normal file
72
Saphir/KeyDev.HC
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
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)
|
||||||
|
{
|
||||||
|
no_warn 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
16
Saphir/Main.HC
Normal file
16
Saphir/Main.HC
Normal file
@@ -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;
|
||||||
|
}
|
||||||
53
Saphir/Misc.HC
Normal file
53
Saphir/Misc.HC
Normal file
@@ -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;
|
||||||
|
}
|
||||||
91
Saphir/WinMgr.HC
Normal file
91
Saphir/WinMgr.HC
Normal file
@@ -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 = saphir.status.bg;
|
||||||
|
GrRect(gr.dc, 0, GR_HEIGHT - 8, GR_WIDTH, 8);
|
||||||
|
gr.dc->color = saphir.status.fg;
|
||||||
|
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;
|
||||||
|
}
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
175
Win.HC
175
Win.HC
@@ -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;
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user