erythros/Applications/OS/Terminal.app/Run.HC

206 lines
No EOL
5.8 KiB
HolyC

Gui.App();
Window* win = Compositor.CreateWindow(18, 62, 684, 474, WIN_FLAGS_DEFAULT);
Gui.Window.EnableAlphaChannel(win);
Gui.Window.SetOpacity(win, 224);
Gui.Window.SetIcon(win, Image.FileToContext2D("Icon.png"));
Gui.Window.SetTitle(win, "Terminal");
TerminalWidget* active_term = NULL;
@shell* sh = NULL;
U0 @terminal_keypress_callback(Window* win, I64 key)
{
if (!active_term || Compositor.active_win != win)
return;
I64 i;
U8 send_key[4];
MemSetU32(&send_key, 0, 1);
switch (key) {
case SC_CURSOR_UP:
send_key[0] = '\x1b';
send_key[1] = '[';
send_key[2] = 'A';
break;
case SC_CURSOR_DOWN:
send_key[0] = '\x1b';
send_key[1] = '[';
send_key[2] = 'B';
break;
case SC_CURSOR_LEFT:
send_key[0] = '\x1b';
send_key[1] = '[';
send_key[2] = 'D';
break;
case SC_CURSOR_RIGHT:
send_key[0] = '\x1b';
send_key[1] = '[';
send_key[2] = 'C';
break;
case SC_DELETE:
send_key[0] = 21;
break;
case SC_BACKSPACE:
send_key[0] = 8;
break;
case SC_TAB:
send_key[0] = 9;
break;
case SC_ENTER:
send_key[0] = 10;
break;
case SC_HOME:
send_key[0] = 22;
break;
case SC_END:
send_key[0] = 23;
break;
case SC_PAGE_UP:
send_key[0] = 24;
break;
case SC_PAGE_DOWN:
send_key[0] = 25;
break;
case SC_ESC:
send_key[0] = 27;
break;
case 0x02 ... 0x0D:
case 0x10 ... 0x1B:
case 0x1E ... 0x29:
case 0x2B ... 0x35:
case 0x39:
if (!KeyDown(SC_SHIFT)) {
if (KeyDown(SC_CTRL)) {
switch (key) {
case Char2ScanCode('c'):
send_key[0] = 0x03;
sh->break = TRUE;
break;
default:
break;
}
} else {
send_key[0] = NORMAL_KEY_SCAN_DECODE_TABLE(U8*)[key];
}
} else {
if (key == 0x39) // Handle TempleOS SHIFT-SPACE character.
send_key[0] = ' ';
else {
if (KeyDown(SC_CTRL)) {
// terminal copy paste handling
} else {
send_key[0] = SHIFT_KEY_SCAN_DECODE_TABLE(U8*)[key];
}
}
};
break;
default:
return;
break;
}
for (i = 0; i < 4; i++)
if (send_key[i] && active_term->output)
FifoU8Ins(active_term->output, send_key[i]);
}
TerminalWidget* t = Gui.CreateWidget(win, WIDGET_TYPE_TERMINAL, 0, 0, 120, 120);
t->pointer = Compositor.theme.pointer.text;
VerticalScrollBarWidget* vscroll = Gui.CreateWidget(win, WIDGET_TYPE_VERT_SCROLLBAR, 0, 0, 16, 128);
vscroll->height = 128;
Context2DWidget* status = Gui.CreateWidget(win, WIDGET_TYPE_CONTEXT2D, 0, 0, Display.Width(), 44);
status->ctx = NewContext2D(Display.Width(), 44);
status->ctx->fill(Color(204, 204, 204, win->opacity));
U0 @terminal_create_new_instance()
{
U32 init_bg_color = t->color.background;
init_bg_color.u8[3] = win->opacity;
t->backing_store->fill(init_bg_color);
active_term = t;
sh = @shell_new;
sh->session = &Compositor.session;
t->output = sh->input;
sh->output = t->input;
}
U0 window_close(Window* win)
{
if (sh)
if (sh->task && sh->exit)
Free(sh);
if (win == Compositor.active_win)
Gui.Window.SetFocus(Compositor.GetWindowByTitle("Wallpaper"));
Compositor.UnregisterForGlobalInputEvents(win);
Compositor.DestroyWindow(win);
Kill(app_event_loop);
}
U0 @terminal_vscroll_change(Widget*)
{
I64 i = 0;
I64 max_scroll = vscroll->height - 32;
F64 f1 = (ToF64(max_scroll) / ToF64(t->cursor.y + t->max.y - 2));
while (vscroll->scroll > ToI64(i * f1))
i++;
t->scroll.y = i;
t->refresh = TRUE;
Gui.Window.Refresh(win);
}
U0 Main()
{
Compositor.RegisterForGlobalInputEvents(win);
Gui.Window.SetCallback(win, "keypress", &@terminal_keypress_callback);
Gui.Widget.SetCallback(vscroll, "change", &@terminal_vscroll_change);
I64 prev_width = -1;
I64 prev_height = -1;
I64 prev_max_x = -1;
I64 prev_max_y = -1;
F64 f1;
Gui.Window.SetFocus(win);
Gui.Window.SetCallback(win, "close", &window_close);
@terminal_create_new_instance;
while (win) {
// FIXME: This should be event-driven...
if (win->width != prev_width || win->height != prev_height) {
win->width = 3 + RoundI64(win->width, 8);
win->height = RoundI64(win->height, 16);
prev_width = win->width;
prev_height = win->height;
if (active_term) {
active_term->width = win->width;
active_term->height = win->height;
}
status->y = win->height - 44;
goto terminal_update_vscroll;
}
if (prev_max_x != t->max.x || prev_max_y != t->max.y) {
terminal_update_vscroll:
if (!t->max.y) {
vscroll->x = Display.Width(); // Hide
} else {
vscroll->x = win->width - vscroll->width - 9;
vscroll->height = win->height - 44;
f1 = (ToF64(t->size.rows) / ToF64(1 + t->cursor.y + t->max.y));
vscroll->length = ToI64((vscroll->height - 32) * f1);
vscroll->scroll = vscroll->height;
}
prev_max_x = t->max.x;
prev_max_y = t->max.y;
// System.Log(Fs, "vscroll->scroll: %d", vscroll->scroll);
Gui.Window.Refresh(win);
}
if (FifoU8Cnt(active_term->input))
Gui.Window.Refresh(win);
if (sh->exit) {
win->callback.close(win);
return;
}
Sleep(10);
}
}
Main;