206 lines
No EOL
5.8 KiB
HolyC
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; |