Meta: Add files to repository
This commit is contained in:
parent
80a0428b66
commit
39198164cd
1029 changed files with 78311 additions and 0 deletions
1112
System/Core/Compositor.HC
Normal file
1112
System/Core/Compositor.HC
Normal file
File diff suppressed because it is too large
Load diff
3
System/Core/FileSystem.HC
Normal file
3
System/Core/FileSystem.HC
Normal file
|
@ -0,0 +1,3 @@
|
|||
|
||||
|
||||
"filesystem ";
|
67
System/Core/Menu.HC
Normal file
67
System/Core/Menu.HC
Normal file
|
@ -0,0 +1,67 @@
|
|||
// Core component for Menu functions
|
||||
|
||||
#define MENU_ITEM_MIN_HEIGHT 24
|
||||
#define MENU_ITEM_MIN_WIDTH 256
|
||||
|
||||
I64 @menu_get_items_count(Window* win)
|
||||
{
|
||||
I64 count = 0;
|
||||
@window_widgets_list* wl = win->widget;
|
||||
while (wl) {
|
||||
if (wl->widget) {
|
||||
if (wl->widget->type == WIDGET_TYPE_MENU_ITEM)
|
||||
count++;
|
||||
}
|
||||
wl = wl->next;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
MenuItemWidget* @menu_add_item(Window* win, U8* text, Context2D* icon,
|
||||
U64 callback, U8* path = NULL,
|
||||
Window* submenu = NULL)
|
||||
{
|
||||
I64 items_count = @menu_get_items_count(win);
|
||||
win->height = 8;
|
||||
win->height += MENU_ITEM_MIN_HEIGHT * (items_count + 1);
|
||||
MenuItemWidget* item = Gui.CreateWidget(
|
||||
win, WIDGET_TYPE_MENU_ITEM, 0, MENU_ITEM_MIN_HEIGHT * items_count,
|
||||
MENU_ITEM_MIN_WIDTH, MENU_ITEM_MIN_HEIGHT);
|
||||
Gui.Widget.SetText(item, text);
|
||||
if (icon)
|
||||
item->icon = icon;
|
||||
if (path)
|
||||
item->path = StrNew(path);
|
||||
if (submenu)
|
||||
item->submenu = submenu;
|
||||
if (callback)
|
||||
Gui.Widget.SetCallback(item, "clicked", callback);
|
||||
return item;
|
||||
}
|
||||
|
||||
Window* @menu_new(U8* title = NULL)
|
||||
{
|
||||
Window* menu = Compositor.CreateWindow(
|
||||
0, 0, MENU_ITEM_MIN_WIDTH, MENU_ITEM_MIN_HEIGHT,
|
||||
WIN_FLAGS_NOHILIGHT | WIN_FLAGS_SKIP | WIN_FLAGS_MENU);
|
||||
Gui.Window.Hide(menu);
|
||||
if (title)
|
||||
Gui.Window.SetTitle(menu, title);
|
||||
else
|
||||
Gui.Window.SetTitle(menu, "");
|
||||
return menu;
|
||||
}
|
||||
|
||||
class @menu
|
||||
{
|
||||
MenuItemWidget* (*AddItem)(Window* win, U8* text, Context2D* icon,
|
||||
U64 callback, U8* path = NULL,
|
||||
Window* submenu = NULL);
|
||||
Window* (*New)(U8* title);
|
||||
};
|
||||
|
||||
@menu Menu;
|
||||
Menu.AddItem = &@menu_add_item;
|
||||
Menu.New = &@menu_new;
|
||||
|
||||
"menu ";
|
108
System/Core/MessageBox.HC
Normal file
108
System/Core/MessageBox.HC
Normal file
|
@ -0,0 +1,108 @@
|
|||
// Core component for MessageBox functions
|
||||
|
||||
Context2D* MESSAGEBOX_ICON_ERR = Image.FileToContext2D(
|
||||
"/Media/Themes/Umami/Icon/status/messagebox_critical.png");
|
||||
Context2D* MESSAGEBOX_ICON_INFO = Image.FileToContext2D("/Media/Themes/Umami/Icon/status/messagebox_info.png");
|
||||
Context2D* MESSAGEBOX_ICON_WARN = Image.FileToContext2D(
|
||||
"/Media/Themes/Umami/Icon/status/messagebox_warning.png");
|
||||
|
||||
Context2D* MESSAGEBOX_WIN_ICON_ERR = Image.FileToContext2D(
|
||||
"/Media/Themes/Umami/Icon/status/messagebox_critical_16x16.png");
|
||||
Context2D* MESSAGEBOX_WIN_ICON_INFO = Image.FileToContext2D(
|
||||
"/Media/Themes/Umami/Icon/status/messagebox_info_16x16.png");
|
||||
Context2D* MESSAGEBOX_WIN_ICON_WARN = Image.FileToContext2D(
|
||||
"/Media/Themes/Umami/Icon/status/messagebox_warning_16x16.png");
|
||||
|
||||
#define MESSAGEBOX_TYPE_ALERT 0
|
||||
#define MESSAGEBOX_TYPE_ERROR 1
|
||||
#define MESSAGEBOX_TYPE_INFO 2
|
||||
|
||||
U0 @messagebox_close_window(Window* window)
|
||||
{
|
||||
Compositor.DestroyWindow(window);
|
||||
}
|
||||
U0 @messagebox_close_widget(Widget* widget)
|
||||
{
|
||||
Compositor.DestroyWindow(widget->parent_win);
|
||||
}
|
||||
|
||||
U0 @messagebox_msg(U8* str, I64 type, Context2D* win_icon, Context2D* icon,
|
||||
U8* options = NULL, U64 callback = NULL)
|
||||
{
|
||||
U64 flags = WIN_FLAGS_MOVABLE | WIN_FLAGS_ICON | WIN_FLAGS_TITLE_BAR | WIN_FLAGS_CLOSE_BUTTON;
|
||||
Window* win = Compositor.CreateWindow(0, 0, 320, 192, flags);
|
||||
Gui.Window.SetIcon(win, win_icon);
|
||||
switch (type) {
|
||||
case MESSAGEBOX_TYPE_ALERT:
|
||||
Gui.Window.SetTitle(win, "Alert");
|
||||
break;
|
||||
case MESSAGEBOX_TYPE_ERROR:
|
||||
Gui.Window.SetTitle(win, "Error");
|
||||
break;
|
||||
case MESSAGEBOX_TYPE_INFO:
|
||||
Gui.Window.SetTitle(win, "Info");
|
||||
break;
|
||||
}
|
||||
Context2DWidget* ctx_icon = Gui.CreateWidget(win, WIDGET_TYPE_CONTEXT2D, 8, 16, 24, 24);
|
||||
ctx_icon->ctx = icon;
|
||||
TextLabelWidget* lbl_text = Gui.CreateWidget(win, WIDGET_TYPE_LABEL, 40, 16, 192, 96);
|
||||
ButtonWidget* btn_ok = NULL;
|
||||
ButtonWidget* btn_cancel = NULL;
|
||||
|
||||
Gui.Widget.SetText(lbl_text, str);
|
||||
Gui.Window.SetCallback(win, "close", callback);
|
||||
|
||||
if (options) {
|
||||
btn_ok = Gui.CreateWidget(win, WIDGET_TYPE_BUTTON, (win->width / 2) - 80,
|
||||
win->height - 60, 64, 24);
|
||||
btn_cancel = Gui.CreateWidget(win, WIDGET_TYPE_BUTTON, (win->width / 2) + 16,
|
||||
win->height - 60, 64, 24);
|
||||
Gui.Widget.SetText(btn_ok, " OK ");
|
||||
Gui.Widget.SetText(btn_cancel, " Cancel ");
|
||||
Gui.Widget.SetCallback(btn_ok, "clicked", callback);
|
||||
Gui.Widget.SetCallback(btn_cancel, "clicked", callback);
|
||||
btn_ok->tag = TRUE;
|
||||
btn_cancel->tag = FALSE;
|
||||
} else {
|
||||
btn_ok = Gui.CreateWidget(win, WIDGET_TYPE_BUTTON, (win->width / 2) - 32,
|
||||
win->height - 60, 64, 24);
|
||||
Gui.Widget.SetText(btn_ok, " OK ");
|
||||
Gui.Widget.SetCallback(btn_ok, "clicked", callback);
|
||||
btn_ok->tag = TRUE;
|
||||
}
|
||||
|
||||
Gui.Window.Center(win);
|
||||
Gui.Window.SetFocus(win);
|
||||
}
|
||||
|
||||
U0 @messagebox_alert(U8* str, U8* options = NULL, U64 callback = NULL)
|
||||
{
|
||||
@messagebox_msg(str, MESSAGEBOX_TYPE_ALERT, MESSAGEBOX_WIN_ICON_WARN,
|
||||
MESSAGEBOX_ICON_WARN, options, callback);
|
||||
}
|
||||
|
||||
U0 @messagebox_error(U8* str, U8* options = NULL, U64 callback = NULL)
|
||||
{
|
||||
@messagebox_msg(str, MESSAGEBOX_TYPE_ERROR, MESSAGEBOX_WIN_ICON_ERR,
|
||||
MESSAGEBOX_ICON_ERR, options, callback);
|
||||
}
|
||||
|
||||
U0 @messagebox_info(U8* str, U8* options = NULL, U64 callback = NULL)
|
||||
{
|
||||
@messagebox_msg(str, MESSAGEBOX_TYPE_INFO, MESSAGEBOX_WIN_ICON_INFO,
|
||||
MESSAGEBOX_ICON_INFO, options, callback);
|
||||
}
|
||||
|
||||
class @messagebox
|
||||
{
|
||||
U0* (*Alert)(U8* str, U8* options = NULL, U64 callback = NULL);
|
||||
U0* (*Error)(U8* str, U8* options = NULL, U64 callback = NULL);
|
||||
U0* (*Info)(U8* str, U8* options = NULL, U64 callback = NULL);
|
||||
};
|
||||
|
||||
@messagebox MessageBox;
|
||||
MessageBox.Alert = &@messagebox_alert;
|
||||
MessageBox.Error = &@messagebox_error;
|
||||
MessageBox.Info = &@messagebox_info;
|
||||
|
||||
"messagebox ";
|
79
System/Core/Scheduler.HC
Normal file
79
System/Core/Scheduler.HC
Normal file
|
@ -0,0 +1,79 @@
|
|||
/* clang-format off */
|
||||
|
||||
U0 @scheduler_restore_page_table(U64 i) {
|
||||
U64 reg R15 _pt = i.u32[1];
|
||||
if (_pt) { // Use CTask's page table entries
|
||||
asm {
|
||||
MOV RAX, R15
|
||||
MOV_CR3_RAX
|
||||
}
|
||||
} else { // Use identity mapping
|
||||
asm {
|
||||
MOV EAX, [MEM_PML4]
|
||||
MOV_CR3_RAX
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
asm {
|
||||
ERYTHROS_TASK_CONTEXT_RESTORE_START::
|
||||
XOR RAX,RAX
|
||||
INC U64 GS:CCPU.swap_cnter[RAX]
|
||||
MOV RSI,FS:CTask.addr[RAX]
|
||||
BT U32 CTask.rflags[RSI],RFLAGf_INT
|
||||
JNC @@05
|
||||
BTS U32 GS:CCPU.cpu_flags[RAX],CPUf_RAN_A_TASK
|
||||
@@05: BT U64 CTask.task_flags[RSI],TASKf_DISABLE_BPTS
|
||||
JC @@15
|
||||
MOV RDX,U64 CTask.bpt_lst[RSI]
|
||||
@@10: TEST RDX,RDX
|
||||
JZ @@15
|
||||
MOV RDI,U64 CBpt.addr[RDX]
|
||||
MOV U8 [RDI],OC_BPT
|
||||
MOV RDX,U64 CBpt.next[RDX]
|
||||
JMP @@10
|
||||
|
||||
@@15: INC U64 CTask.swap_cnter[RSI]
|
||||
|
||||
MOV RAX, U64 CTask.user_data[RSI]
|
||||
PUSH RAX
|
||||
CALL I32 &@scheduler_restore_page_table
|
||||
|
||||
MOV RAX,U64 CTask.fpu_mmx[RSI]
|
||||
FXRSTOR U64 [RAX]
|
||||
|
||||
MOV RAX,RSP
|
||||
LEA RSP,U64 CTask.rcx[RSI]
|
||||
POP RCX
|
||||
POP RDX
|
||||
POP RBX
|
||||
POP RBP
|
||||
POP RDI
|
||||
POP R8
|
||||
POP R9
|
||||
POP R10
|
||||
POP R11
|
||||
POP R12
|
||||
POP R13
|
||||
POP R14
|
||||
POP R15
|
||||
MOV RSP,RAX
|
||||
|
||||
MOV RAX,U64 CTask.rax[RSI]
|
||||
PUSH CGDT.ds
|
||||
PUSH U64 CTask.rsp[RSI]
|
||||
PUSH U64 CTask.rflags[RSI]
|
||||
PUSH CGDT.cs64
|
||||
PUSH U64 CTask.rip[RSI]
|
||||
MOV RSI,U64 CTask.rsi[RSI]
|
||||
IRET
|
||||
ERYTHROS_TASK_CONTEXT_RESTORE_END::
|
||||
NOP
|
||||
//************************************
|
||||
}
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
Function.Patch(_TASK_CONTEXT_RESTORE, ERYTHROS_TASK_CONTEXT_RESTORE_START);
|
||||
|
||||
"scheduler ";
|
282
System/Core/Shell.HC
Normal file
282
System/Core/Shell.HC
Normal file
|
@ -0,0 +1,282 @@
|
|||
#define SHELL_OPTS_ERR_INVALID_OPT -1
|
||||
#define SHELL_OPTS_ERR_EXTRA_OPD -2
|
||||
|
||||
U0 @shell_free_args(I64 argc, U8** argv)
|
||||
{
|
||||
I64 i;
|
||||
for (i = 0; i < argc; i++)
|
||||
Free(argv[i]);
|
||||
if (argv)
|
||||
Free(argv);
|
||||
}
|
||||
|
||||
U8** @shell_parse_args(@shell* sh, U8* str,
|
||||
I64* argc)
|
||||
{ // Return argc, argv from str.
|
||||
Bool quoted = FALSE;
|
||||
I64 _argc = 0;
|
||||
U8** _argv = NULL;
|
||||
U8** _tmp = CAlloc(sizeof(U64) * StrLen(str));
|
||||
I64 i = 0;
|
||||
I64 s = 0;
|
||||
I64 len;
|
||||
while (i < StrLen(str) + 1) {
|
||||
switch (str[i]) {
|
||||
case 0:
|
||||
case ' ':
|
||||
if (!quoted) {
|
||||
len = (str + i) - (str + s - 1);
|
||||
if (str[i - 1] == '"')
|
||||
len--;
|
||||
if (len - 1) {
|
||||
_tmp[_argc] = CAlloc(len);
|
||||
MemCpy(_tmp[_argc], str + s, len - 1);
|
||||
_argc++;
|
||||
}
|
||||
s = i + 1;
|
||||
}
|
||||
break;
|
||||
case '"':
|
||||
quoted = !quoted;
|
||||
if (quoted)
|
||||
s = i + 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
*argc = _argc;
|
||||
_argv = CAlloc(sizeof(U64) * _argc);
|
||||
MemCpy(_argv, _tmp, sizeof(U64) * _argc);
|
||||
Free(_tmp);
|
||||
return _argv;
|
||||
}
|
||||
|
||||
I64 @shell_parse_opts(@shell* sh, U8* op_lst, I64 argc, U8** argv, I64* flags,
|
||||
U64* op_err, Bool ignore_extra_opd = FALSE)
|
||||
{
|
||||
I64 i, j;
|
||||
U8 op_chr[2];
|
||||
op_chr[1] = 0;
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (argv[i][0] == '-') {
|
||||
for (j = 1; j < StrLen(argv[i]); j++) {
|
||||
op_chr[0] = argv[i][j];
|
||||
if (StrFind(&op_chr, op_lst))
|
||||
*flags |= 1 << (StrFind(&op_chr, op_lst) - op_lst);
|
||||
else {
|
||||
*op_err = StrNew(&op_chr);
|
||||
return SHELL_OPTS_ERR_INVALID_OPT;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!ignore_extra_opd) {
|
||||
*op_err = StrNew(argv[i]);
|
||||
return SHELL_OPTS_ERR_EXTRA_OPD;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
U8* @shell_expand_relative_path(@shell* sh, U8* path)
|
||||
{
|
||||
if (!path || !sh)
|
||||
return NULL;
|
||||
if (StrLen(path) < 1)
|
||||
return NULL;
|
||||
switch (path[0]) {
|
||||
case '/':
|
||||
return StrNew(path);
|
||||
break;
|
||||
default:
|
||||
U8* abs_path = CAlloc(StrLen(path) + StrLen(&sh->cwd) + 4);
|
||||
StrPrint(abs_path, "%s/%s", &sh->cwd, path);
|
||||
return abs_path;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
U8* @shell_get_env_var(@shell* sh, U8* key)
|
||||
{
|
||||
@shell_env_var* var = sh->env->next;
|
||||
while (var) {
|
||||
if (StrLen(&var->key) && StrLen(&var->value))
|
||||
if (!StrCmp(&var->key, key))
|
||||
return &var->value;
|
||||
var = var->next;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
U0 @shell_set_env_var(@shell* sh, U8* key, U8* value)
|
||||
{
|
||||
if (!sh || !key || !value)
|
||||
return;
|
||||
@shell_env_var* var = sh->env->next;
|
||||
while (var->next) {
|
||||
if (!StrCmp(&var->key, key)) {
|
||||
StrCpy(&var->value, value);
|
||||
return;
|
||||
}
|
||||
var = var->next;
|
||||
}
|
||||
@shell_env_var* new = CAlloc(sizeof(@shell_env_var));
|
||||
StrCpy(&new->key, key);
|
||||
StrCpy(&new->value, value);
|
||||
new->prev = var;
|
||||
var->next = new;
|
||||
}
|
||||
|
||||
U0 @shell_unset_env_var(@shell* sh, U8* key)
|
||||
{
|
||||
@shell_env_var* var = sh->env->next;
|
||||
@shell_env_var* prev = NULL;
|
||||
@shell_env_var* next = NULL;
|
||||
while (var) {
|
||||
if (!StrCmp(&var->key, key)) {
|
||||
prev = var->prev;
|
||||
next = var->next;
|
||||
if (prev)
|
||||
prev->next = next;
|
||||
if (next)
|
||||
next->prev = prev;
|
||||
Free(var);
|
||||
return;
|
||||
}
|
||||
var = var->next;
|
||||
}
|
||||
}
|
||||
|
||||
U0 @shell_history_append(@shell* sh, U8* str)
|
||||
{
|
||||
if (!sh || !str)
|
||||
return;
|
||||
if (!StrCmp(str, ""))
|
||||
return;
|
||||
I64 i;
|
||||
sh->history.entries[sh->history.pos] = StrNew(str);
|
||||
sh->history.pos++;
|
||||
if (sh->history.pos > SHELL_HISTORY_LIMIT - 1) {
|
||||
Free(sh->history.entries[0]);
|
||||
for (i = 0; i < SHELL_HISTORY_LIMIT; i++)
|
||||
sh->history.entries[i] = sh->history.entries[i + 1];
|
||||
sh->history.pos--;
|
||||
}
|
||||
}
|
||||
|
||||
U0 @shell_process_args(@shell* sh, I64 argc, U8** argv)
|
||||
{
|
||||
if (argc < 1 || !argv)
|
||||
return;
|
||||
I64 i;
|
||||
U8 buf[256];
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (argv[i][0] == '\d') {
|
||||
switch (argv[i][1]) {
|
||||
case '?':
|
||||
Free(argv[i]);
|
||||
StrPrint(&buf, "%d", sh->answer);
|
||||
argv[i] = StrNew(&buf);
|
||||
break;
|
||||
case '0':
|
||||
Free(argv[i]);
|
||||
argv[i] = StrNew("esh");
|
||||
break;
|
||||
default:
|
||||
Free(argv[i]);
|
||||
argv[i] = StrNew(@shell_get_env_var(sh, argv[i] + 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!StrCmp(argv[i], "~")) {
|
||||
Free(argv[i]);
|
||||
argv[i] = StrNew(&sh->session->home);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
U0 @shell_update_prompts(@shell* sh)
|
||||
{
|
||||
U8 buf[512];
|
||||
U8 buf2[512];
|
||||
StrCpy(&buf, &sh->cwd);
|
||||
StrPrint(buf2, "/home/%s", &sh->session->user.name);
|
||||
if (!StrCmp(&buf, &buf2))
|
||||
StrCpy(&buf, "~");
|
||||
else
|
||||
StrCpy(&buf, StrLastOcc(&buf, "/") + 1);
|
||||
StrPrint(&sh->PS1, "[%s@%s %s]\d ", &sh->session->user.name,
|
||||
&sh->session->hostname, &buf);
|
||||
}
|
||||
|
||||
I64 @shell_input_loop(@shell* sh)
|
||||
{
|
||||
CHashFun* cmd;
|
||||
I64 argc;
|
||||
U8** argv;
|
||||
U8 buf[4096];
|
||||
Bool exit = FALSE;
|
||||
I64 i;
|
||||
I64 (*@shell_exec)(@shell* sh, I64 argc, U8** argv);
|
||||
|
||||
while (!exit) {
|
||||
|
||||
@shell_update_prompts(sh);
|
||||
Stdio.WriteLine(sh, &sh->PS1);
|
||||
Stdio.ReadLine(sh, &buf);
|
||||
|
||||
@shell_history_append(sh, &buf);
|
||||
argv = @shell_parse_args(sh, &buf, &argc);
|
||||
|
||||
if (argc) {
|
||||
if (!StrCmp(argv[0], "exit")) {
|
||||
exit = TRUE;
|
||||
goto @shell_exit;
|
||||
}
|
||||
@shell_process_args(sh, argc, argv);
|
||||
StrPrint(&buf, "@shell_cmd_%s", argv[0]);
|
||||
cmd = HashFind(&buf, adam_task->hash_table, HTT_FUN);
|
||||
if (cmd) {
|
||||
@shell_exec = cmd->exe_addr;
|
||||
sh->answer = @shell_exec(sh, argc, argv);
|
||||
sh->break = FALSE;
|
||||
FifoU8Flush(sh->input);
|
||||
} else {
|
||||
StrPrint(&buf, "%s: command not found\n", argv[0]);
|
||||
Stdio.WriteLine(sh, &buf);
|
||||
sh->answer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@shell_exit : @shell_free_args(argc, argv);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
U0 @shell_instance(@shell* sh)
|
||||
{
|
||||
@shell_input_loop(sh);
|
||||
sh->exit = TRUE;
|
||||
}
|
||||
|
||||
U0 @shell_init(@shell* sh)
|
||||
{
|
||||
sh->env = CAlloc(sizeof(@shell_env_var));
|
||||
sh->history.limit = SHELL_HISTORY_LIMIT;
|
||||
sh->history.pos = 0;
|
||||
sh->history.entries = CAlloc(sizeof(U64) * SHELL_HISTORY_LIMIT);
|
||||
sh->input = FifoU8New(SHELL_INPUT_FIFO_SIZE);
|
||||
sh->task = Spawn(&@shell_instance, sh);
|
||||
}
|
||||
|
||||
@shell* @shell_new(Bool headless = FALSE)
|
||||
{
|
||||
@shell* sh = CAlloc(sizeof(@shell));
|
||||
if (!headless)
|
||||
@shell_init(sh);
|
||||
StrCpy(&sh->cwd, &Compositor.session.home);
|
||||
return sh;
|
||||
}
|
||||
|
||||
"shell ";
|
13
System/Core/ShellCommands.HC
Normal file
13
System/Core/ShellCommands.HC
Normal file
|
@ -0,0 +1,13 @@
|
|||
extern I64 @systemstarter_open(@shell* sh, I64 argc, U8** argv);
|
||||
|
||||
CDirEntry* sc_de = FilesFind("M:/System/Shell/Commands/*.HC");
|
||||
CDirEntry* sc_de2 = sc_de;
|
||||
while (sc_de2) {
|
||||
if (!(!StrCmp(sc_de2->name, ".") && !StrCmp(sc_de2->name, ".."))) {
|
||||
ExeDoc(DocRead(sc_de2->full_name));
|
||||
}
|
||||
sc_de2 = sc_de2->next;
|
||||
}
|
||||
DirTreeDel(sc_de);
|
||||
|
||||
"shellcommands ";
|
214
System/Core/SystemStarter.HC
Normal file
214
System/Core/SystemStarter.HC
Normal file
|
@ -0,0 +1,214 @@
|
|||
#define SYSSTART_MSG_NULL 0
|
||||
#define SYSSTART_MSG_SPAWN 1
|
||||
#define SYSSTART_MSG_KILL 2
|
||||
|
||||
class @systemtask
|
||||
{
|
||||
U8* path;
|
||||
U8* name;
|
||||
};
|
||||
|
||||
class @systemstarter
|
||||
{
|
||||
CTask* task;
|
||||
U0 (*CreateTask)(U8* path, U8* name);
|
||||
U0 (*Init)();
|
||||
U0 (*Spawn)(U8* path, U8* name);
|
||||
U0 (*Task)();
|
||||
};
|
||||
|
||||
@systemstarter SystemStarter;
|
||||
|
||||
U32 @systemstarter_ext(U8* path)
|
||||
{
|
||||
U32 res = NULL;
|
||||
U8* ext = FileSystem.GetFileExtension(path);
|
||||
MemCpy(&res, ext, StrLen(ext));
|
||||
return res;
|
||||
}
|
||||
|
||||
U0 @systemstarter_init() { }
|
||||
|
||||
I64 @systemstarter_open(@shell* sh, I64 argc, U8** argv)
|
||||
{
|
||||
U8 buf[512];
|
||||
U8* path = @shell_expand_relative_path(sh, argv[1]);
|
||||
if (!FileSystem.PathExists(path)) {
|
||||
Stdio.WriteLine(sh, "error: path does not exist: ");
|
||||
Stdio.WriteLine(sh, path);
|
||||
Stdio.WriteLine(sh, "\n");
|
||||
Free(path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (@systemstarter_ext(path)) {
|
||||
case 'app':
|
||||
StrCpy(&buf, "");
|
||||
String.Append(&buf, "I64 @exe_doc_buf_size = NULL; ");
|
||||
String.Append(&buf,
|
||||
"U8 *@exe_doc_buf = FileSystem.ReadFile(\"%s/Run.HC\", "
|
||||
"&@exe_doc_buf_size); ",
|
||||
path);
|
||||
String.Append(&buf, "ExePutS(@exe_doc_buf); ");
|
||||
String.Append(&buf, "Free(@exe_doc_buf); ");
|
||||
// System.Log(Fs, &buf);
|
||||
CTask* task = User;
|
||||
TaskExe(task, NULL, "Raw(ON);\n", 0);
|
||||
TaskExe(task, NULL, &buf, 0);
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
Stdio.WriteLine(sh, "error: unknown or unsupported file type.\n");
|
||||
// Free(path);
|
||||
return 1;
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
U0 @systemstarter_spawn(U8* path, U8* name)
|
||||
{
|
||||
CTask* task = Spawn(&UserCmdLine);
|
||||
Sleep(Rand * 100);
|
||||
U8 change_path_str[512];
|
||||
StrPrint(task->task_name, name);
|
||||
StrPrint(change_path_str, "Cd(\"%s\");\n", path);
|
||||
TaskExe(task, NULL, "Raw(ON);\n", 0);
|
||||
TaskExe(task, NULL, change_path_str, 0);
|
||||
TaskExe(task, NULL, "ExeFile(\"Run.HC\");\n", 0);
|
||||
Sleep(Rand * 100);
|
||||
}
|
||||
|
||||
U0 @systemstarter_load_applets()
|
||||
{
|
||||
U8 applet_name[512];
|
||||
CDirEntry* de = FilesFind("M:/Applets/*.applet");
|
||||
CDirEntry* tmpde = de;
|
||||
while (tmpde) {
|
||||
StrCpy(&applet_name, StrLastOcc(tmpde->full_name, "/") + 1);
|
||||
*(StrFirstOcc(&applet_name, ".")) = NULL;
|
||||
SystemStarter.Spawn(tmpde->full_name, &applet_name);
|
||||
tmpde = tmpde->next;
|
||||
}
|
||||
DirTreeDel(de);
|
||||
}
|
||||
|
||||
U0 @systemstarter_play_user_startup_sound()
|
||||
{
|
||||
U8 path[512];
|
||||
StrPrint(&path, "/home/%s/.sounds/startup.wav",
|
||||
&Compositor.session.user.name);
|
||||
U8** argv = CAlloc(sizeof(U64) * 2);
|
||||
argv[0] = "aplay";
|
||||
argv[1] = &path;
|
||||
@shell* sh = @shell_new(TRUE);
|
||||
sh->session = &Compositor.session;
|
||||
//@shell_cmd_aplay(sh, 2, argv);
|
||||
Free(sh);
|
||||
}
|
||||
|
||||
U0 @systemstarter_set_user_wallpaper()
|
||||
{
|
||||
U8 path[512];
|
||||
StrPrint(&path, "/home/%s/.wallpaper/wallpaper.png",
|
||||
&Compositor.session.user.name);
|
||||
U8** argv = CAlloc(sizeof(U64) * 2);
|
||||
argv[0] = "wpset";
|
||||
argv[1] = &path;
|
||||
//@shell_cmd_wpset(NULL, 2, argv);
|
||||
}
|
||||
|
||||
U0 @systemstarter_user_startup()
|
||||
{
|
||||
// Set User wallpaper
|
||||
@systemstarter_set_user_wallpaper();
|
||||
|
||||
// Play User startup sound
|
||||
@systemstarter_play_user_startup_sound();
|
||||
}
|
||||
|
||||
U0 @systemstarter_startup()
|
||||
{
|
||||
|
||||
// Set user-specific startup preferences
|
||||
Spawn(&@systemstarter_user_startup);
|
||||
|
||||
// Initialize Clipboard
|
||||
Clipboard.Init();
|
||||
|
||||
// Spawn Clipboard Task
|
||||
Spawn(Clipboard.Task, , "Clipboard", T(mp_cnt > 3, 2, 1));
|
||||
|
||||
// Initialize SystemTray
|
||||
SystemTray.Init();
|
||||
|
||||
// Spawn SystemTray Task
|
||||
Spawn(SystemTray.Task, , "SystemTray", T(mp_cnt > 3, 2, 1));
|
||||
|
||||
SystemStarter.Spawn("M:/Applications/OS/Wallpaper.app", "Wallpaper");
|
||||
SystemStarter.Spawn("M:/Applications/OS/MenuBar.app", "MenuBar");
|
||||
SystemStarter.Spawn("M:/Applications/OS/TaskSwitcher.app",
|
||||
"TaskSwitcher");
|
||||
|
||||
// Load SystemTray Applets
|
||||
@systemstarter_load_applets;
|
||||
}
|
||||
|
||||
U0 @systemstarter_ipc_queue_process()
|
||||
{
|
||||
IpcMessage* msg;
|
||||
@systemtask* st = NULL;
|
||||
msg = Ipc.MsgRecv();
|
||||
if (msg) {
|
||||
switch (msg->type) {
|
||||
case SYSSTART_MSG_SPAWN:
|
||||
if (msg->payload) {
|
||||
st = msg->payload;
|
||||
if (st->path && st->name) {
|
||||
SystemStarter.Spawn(st->path, st->name);
|
||||
System.Log(Fs, "Received message ← CreateTask (%s)", st->name);
|
||||
Free(st->name);
|
||||
Free(st->path);
|
||||
}
|
||||
Free(st);
|
||||
}
|
||||
break;
|
||||
case SYSSTART_MSG_KILL:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
Free(msg);
|
||||
}
|
||||
}
|
||||
|
||||
U0 @systemstarter_task()
|
||||
{
|
||||
Ipc.InitQueue(Fs);
|
||||
System.Log(Fs, "Task running at 0x%08x", Fs);
|
||||
SystemStarter.task = Fs;
|
||||
Spawn(&@systemstarter_startup, , , T(mp_cnt, 1, 0));
|
||||
|
||||
while (1) {
|
||||
@systemstarter_ipc_queue_process;
|
||||
Sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
U0 @systemstarter_create_task(U8* path, U8* name)
|
||||
{
|
||||
@systemtask* st = CAlloc(sizeof(@systemtask));
|
||||
IpcMessage* msg = CAlloc(sizeof(IpcMessage));
|
||||
st->path = StrNew(path);
|
||||
st->name = StrNew(name);
|
||||
msg->client = NULL;
|
||||
msg->type = SYSSTART_MSG_SPAWN;
|
||||
msg->payload = st;
|
||||
Ipc.MsgSend(SystemStarter.task, msg);
|
||||
}
|
||||
|
||||
SystemStarter.CreateTask = &@systemstarter_create_task;
|
||||
SystemStarter.Init = &@systemstarter_init;
|
||||
SystemStarter.Spawn = &@systemstarter_spawn;
|
||||
SystemStarter.Task = &@systemstarter_task;
|
||||
|
||||
"systemstarter ";
|
139
System/Core/SystemTray.HC
Normal file
139
System/Core/SystemTray.HC
Normal file
|
@ -0,0 +1,139 @@
|
|||
#define SYSTRAY_MSG_NULL 0x0
|
||||
#define SYSTRAY_MSG_REGISTER 0x1
|
||||
#define SYSTRAY_MSG_UNREGISTER 0x2
|
||||
|
||||
class @systemtray
|
||||
{
|
||||
CTask* task;
|
||||
@window_widgets_list* item;
|
||||
U0 (*Init)();
|
||||
U0 (*Task)();
|
||||
Context2DWidget* (*RegisterItem)();
|
||||
U0 (*UnregisterItem)(Widget* widget);
|
||||
U0 (*SetIcon)(Context2DWidget* widget, U8* path);
|
||||
};
|
||||
|
||||
@systemtray SystemTray;
|
||||
|
||||
U0 @systemtray_register_item(I64 addr)
|
||||
{
|
||||
Context2DWidget* item = Gui.CreateWidget(
|
||||
Compositor.menubar.win, WIDGET_TYPE_CONTEXT2D, -24, 0, 24, 24);
|
||||
item->ctx = NewContext2D(item->width, item->height);
|
||||
Fill2D(item->ctx, Color(0, 0, 0, 0));
|
||||
MemSetI64(addr, item, 1);
|
||||
}
|
||||
|
||||
U0 @systemtray_unregister_item(Widget* item)
|
||||
{
|
||||
IpcMessage* msg = CAlloc(sizeof(IpcMessage));
|
||||
msg->client = NULL;
|
||||
msg->type = CPZ_MSG_WIN_WIDGET_DESTROY;
|
||||
msg->payload = item;
|
||||
System.Log(Fs, "Sent message → WidgetDestroy");
|
||||
Ipc.MsgSend(Compositor.menubar.task, msg);
|
||||
}
|
||||
|
||||
U0 @systemtray_reindex_items()
|
||||
{
|
||||
I64 x = Display.Width() - 100;
|
||||
@window_widgets_list* item = Compositor.menubar.win->widget;
|
||||
while (item->next)
|
||||
item = item->next;
|
||||
while (item->widget->type == WIDGET_TYPE_CONTEXT2D) {
|
||||
x -= item->widget->width + 4;
|
||||
item->widget->x = x;
|
||||
item = item->prev;
|
||||
}
|
||||
Gui.Window.Refresh(Compositor.menubar.win);
|
||||
}
|
||||
|
||||
U0 @systemtray_ipc_queue_process()
|
||||
{
|
||||
IpcMessage* msg;
|
||||
msg = Ipc.MsgRecv();
|
||||
if (msg) {
|
||||
switch (msg->type) {
|
||||
case SYSTRAY_MSG_REGISTER:
|
||||
@systemtray_register_item(msg->payload);
|
||||
@systemtray_reindex_items;
|
||||
break;
|
||||
case SYSTRAY_MSG_UNREGISTER:
|
||||
@systemtray_unregister_item(msg->payload);
|
||||
@systemtray_reindex_items;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
Free(msg);
|
||||
}
|
||||
}
|
||||
|
||||
U0 @systemtray_init() { }
|
||||
|
||||
U0 @systemtray_task()
|
||||
{
|
||||
Ipc.InitQueue(Fs);
|
||||
SystemTray.task = Fs;
|
||||
System.Log(Fs, "Task running at 0x%08x", Fs);
|
||||
while (!Compositor.menubar.win) // Wait for instance
|
||||
Sleep(1);
|
||||
while (1) {
|
||||
@systemtray_ipc_queue_process();
|
||||
Sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
Context2DWidget* @systemtray_client_register_item()
|
||||
{
|
||||
Context2DWidget* item = NULL;
|
||||
IpcMessage* msg = CAlloc(sizeof(IpcMessage));
|
||||
msg->client = NULL;
|
||||
msg->type = SYSTRAY_MSG_REGISTER;
|
||||
msg->payload = &item;
|
||||
System.Log(Fs, "Sent message → SystrayRegisterItem");
|
||||
Ipc.MsgSend(SystemTray.task, msg);
|
||||
while (!item)
|
||||
Sleep(1);
|
||||
return item;
|
||||
}
|
||||
|
||||
U0 @systemtray_client_unregister_item(Widget* item)
|
||||
{
|
||||
IpcMessage* msg = CAlloc(sizeof(IpcMessage));
|
||||
msg->client = NULL;
|
||||
msg->type = SYSTRAY_MSG_UNREGISTER;
|
||||
msg->payload = item;
|
||||
System.Log(Fs, "Sent message → SystrayUnRegisterItem");
|
||||
Ipc.MsgSend(SystemTray.task, msg);
|
||||
while (item->type)
|
||||
Sleep(1);
|
||||
@systemtray_reindex_items;
|
||||
}
|
||||
|
||||
U0 @systemtray_set_icon(Context2DWidget* widget, U8* path)
|
||||
{
|
||||
if (!widget || !path)
|
||||
return;
|
||||
U8 full_path[512];
|
||||
if (2 == 3) // FIXME
|
||||
StrCpy(&full_path, path);
|
||||
else {
|
||||
StrCpy(&full_path, "M:/Media/Themes/Umami/Icon/");
|
||||
String.Append(&full_path, path);
|
||||
}
|
||||
if (!FileFind(&full_path))
|
||||
return;
|
||||
Context2D* icon = Image.FileToContext2D(&full_path);
|
||||
CopyRect2D(widget->ctx, 0, 0, icon);
|
||||
DelContext2D(icon);
|
||||
Gui.Window.Refresh(Compositor.menubar.win);
|
||||
}
|
||||
|
||||
SystemTray.Init = &@systemtray_init;
|
||||
SystemTray.RegisterItem = &@systemtray_client_register_item;
|
||||
SystemTray.SetIcon = &@systemtray_set_icon;
|
||||
SystemTray.Task = &@systemtray_task;
|
||||
SystemTray.UnregisterItem = &@systemtray_client_unregister_item;
|
||||
|
||||
"systemtray ";
|
Loading…
Add table
Add a link
Reference in a new issue