mirror of
https://github.com/JannisHeydemann/BoredOS.git
synced 2026-05-30 02:16:58 +00:00
BrewOS 1.40 Beta
BrewOS 1.31 > BrewOS 1.40 Brewkernel 2.3.0 Alpha > Brewkernel 2.3.1 Beta This update is a feature focused update. It features loads of quality of life and major UX improvements. New features: -Drag and drop for files and applications (shortcuts for apps can be made by dragging an app from the start menu into the desktop) -Customizable desktop (auto align, snap to grid -Recycle bin (rm in the CMD skips this)
This commit is contained in:
@@ -35,8 +35,8 @@ static void about_paint(Window *win) {
|
||||
|
||||
// Version info
|
||||
draw_string(offset_x, offset_y + 105, "BrewOS", COLOR_BLACK);
|
||||
draw_string(offset_x, offset_y + 120, "BrewOS Version 1.30", COLOR_BLACK);
|
||||
draw_string(offset_x, offset_y + 135, "Kernel Version 2.3.0", COLOR_BLACK);
|
||||
draw_string(offset_x, offset_y + 120, "BrewOS Version 1.40", COLOR_BLACK);
|
||||
draw_string(offset_x, offset_y + 135, "Kernel Version 2.3.1", COLOR_BLACK);
|
||||
|
||||
// Copyright
|
||||
draw_string(offset_x, offset_y + 150, "(C) 2026 boreddevnl.", COLOR_BLACK);
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
|
||||
void cli_cmd_brewver(char *args) {
|
||||
(void)args;
|
||||
cli_write("BrewOS v1.30 Alpha\n");
|
||||
cli_write("BrewOS Kernel V2.3.0 Pre-Alpha\n");
|
||||
cli_write("BrewOS v1.40 Beta\n");
|
||||
cli_write("BrewOS Kernel V2.3.1 Beta\n");
|
||||
}
|
||||
|
||||
193
src/kernel/cmd.c
193
src/kernel/cmd.c
@@ -158,8 +158,6 @@ static void cmd_set_line_content(const char *str) {
|
||||
}
|
||||
}
|
||||
|
||||
// Manual and license pages are now in the individual command files
|
||||
|
||||
// --- Terminal Emulation ---
|
||||
|
||||
static void cmd_scroll_up() {
|
||||
@@ -293,8 +291,8 @@ void pager_wrap_content(const char **lines, int count) {
|
||||
int chunk_len = remaining;
|
||||
if (chunk_len > CMD_COLS) chunk_len = CMD_COLS;
|
||||
|
||||
// If we are cutting a word, backtrack to last space
|
||||
if (chunk_len < remaining) { // Only check if we are actually wrapping
|
||||
// If cutting a word, backtrack to last space
|
||||
if (chunk_len < remaining) { // Only check if actually wrapping
|
||||
int split_point = chunk_len;
|
||||
while (split_point > 0 && line[processed + split_point] != ' ') {
|
||||
split_point--;
|
||||
@@ -328,6 +326,45 @@ void pager_set_mode(void) {
|
||||
current_mode = MODE_PAGER;
|
||||
}
|
||||
|
||||
// Internal LS command to avoid stack overflow in external module
|
||||
static void internal_cmd_ls(char *args) {
|
||||
char path[256];
|
||||
if (args && *args) {
|
||||
int i=0;
|
||||
while(args[i] && i < 255) { path[i] = args[i]; i++; }
|
||||
path[i] = 0;
|
||||
} else {
|
||||
path[0] = '.'; path[1] = 0;
|
||||
}
|
||||
|
||||
int max_files = 64;
|
||||
FAT32_FileInfo *files = (FAT32_FileInfo*)kmalloc(max_files * sizeof(FAT32_FileInfo));
|
||||
if (!files) {
|
||||
cmd_write("Error: Out of memory\n");
|
||||
return;
|
||||
}
|
||||
|
||||
int count = fat32_list_directory(path, files, max_files);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (files[i].is_directory) {
|
||||
cmd_write("[DIR] ");
|
||||
} else {
|
||||
cmd_write("[FILE] ");
|
||||
}
|
||||
|
||||
cmd_write(files[i].name);
|
||||
if (!files[i].is_directory) {
|
||||
cmd_write(" ");
|
||||
cmd_write_int(files[i].size);
|
||||
cmd_write("b");
|
||||
}
|
||||
cmd_write("\n");
|
||||
}
|
||||
|
||||
kfree(files);
|
||||
}
|
||||
|
||||
// --- Commands (now delegated to cli_apps/) ---
|
||||
|
||||
// Command dispatch table
|
||||
@@ -374,8 +411,8 @@ static const CommandEntry commands[] = {
|
||||
{"cd", cli_cmd_cd},
|
||||
{"PWD", cli_cmd_pwd},
|
||||
{"pwd", cli_cmd_pwd},
|
||||
{"LS", cli_cmd_ls},
|
||||
{"ls", cli_cmd_ls},
|
||||
{"LS", internal_cmd_ls},
|
||||
{"ls", internal_cmd_ls},
|
||||
{"MKDIR", cli_cmd_mkdir},
|
||||
{"mkdir", cli_cmd_mkdir},
|
||||
{"RM", cli_cmd_rm},
|
||||
@@ -895,12 +932,26 @@ void cmd_reset(void) {
|
||||
}
|
||||
|
||||
static void create_test_files(void) {
|
||||
fat32_mkdir("Documents");
|
||||
fat32_mkdir("Projects");
|
||||
fat32_mkdir("Documents/Important");
|
||||
fat32_mkdir("Apps");
|
||||
if (!fat32_exists("Documents")) fat32_mkdir("Documents");
|
||||
if (!fat32_exists("Projects")) fat32_mkdir("Projects");
|
||||
if (!fat32_exists("Documents/Important")) fat32_mkdir("Documents/Important");
|
||||
if (!fat32_exists("Apps")) fat32_mkdir("Apps");
|
||||
if (!fat32_exists("Desktop")) fat32_mkdir("Desktop");
|
||||
if (!fat32_exists("RecycleBin")) fat32_mkdir("RecycleBin");
|
||||
|
||||
FAT32_FileHandle *fh = fat32_open("README.md", "w");
|
||||
// Create Desktop Shortcuts
|
||||
FAT32_FileHandle *fh;
|
||||
fh = fat32_open("Desktop/Explorer.shortcut", "w"); if(fh) fat32_close(fh);
|
||||
fh = fat32_open("Desktop/Notepad.shortcut", "w"); if(fh) fat32_close(fh);
|
||||
fh = fat32_open("Desktop/Calculator.shortcut", "w"); if(fh) fat32_close(fh);
|
||||
fh = fat32_open("Desktop/Minesweeper.shortcut", "w"); if(fh) fat32_close(fh);
|
||||
fh = fat32_open("Desktop/Control Panel.shortcut", "w"); if(fh) fat32_close(fh);
|
||||
fh = fat32_open("Desktop/Terminal.shortcut", "w"); if(fh) fat32_close(fh);
|
||||
fh = fat32_open("Desktop/About.shortcut", "w"); if(fh) fat32_close(fh);
|
||||
fh = fat32_open("Desktop/Recycle Bin.shortcut", "w"); if(fh) fat32_close(fh);
|
||||
|
||||
// Always try to write README to ensure content exists
|
||||
fh = fat32_open("README.md", "w");
|
||||
if (fh) {
|
||||
const char *content =
|
||||
"# Brew OS 1.01 Alpha\n\n"
|
||||
@@ -992,8 +1043,8 @@ static void create_test_files(void) {
|
||||
"The above attribution requirements are informational and intended to\n"
|
||||
"ensure proper credit is given. They do not alter or supersede the\n"
|
||||
"terms of the GNU General Public License (GPL), which governs this work.\n";
|
||||
fat32_write(fh, (void *)content, cmd_strlen(content));
|
||||
fat32_close(fh);
|
||||
fat32_write(fh, (void *)content, cmd_strlen(content));
|
||||
fat32_close(fh);
|
||||
}
|
||||
|
||||
fh = fat32_open("Apps/README.md", "w");
|
||||
@@ -1001,7 +1052,7 @@ static void create_test_files(void) {
|
||||
const char *content =
|
||||
"# All compiled C files in this directory are openable from any other directory by typing in the name of the compiled file by typing in the name of the compiled file.\n\n"
|
||||
"The c file 'wordofgod.c' contains a C program similar to one in TempleOS, which Terry A. Davis (RIP) saw as 'words from god' telling him what to do with his kernel.\n"
|
||||
"I made this file as a tribute to him, as he also inspired me to create this project in '24. If you want to run it you simply do cc (or compc) wordofgod.c and then run ./wordofgod \n";
|
||||
"I made this file as a tribute to him, as he also inspired me to create this project in '24. If you want to run it you simply do cc (or compc) wordgod.c and then run ./wordgod \n";
|
||||
fat32_write(fh, (void *)content, cmd_strlen(content));
|
||||
fat32_close(fh);
|
||||
}
|
||||
@@ -1024,74 +1075,60 @@ static void create_test_files(void) {
|
||||
|
||||
fh = fat32_open("Apps/wordofgod.c", "w");
|
||||
if (fh) {
|
||||
char *h = "int main(){int l;l=malloc(1200);";
|
||||
fat32_write(fh, h, cmd_strlen(h));
|
||||
char *w1 = "poke(l+0,\"In \");poke(l+4,\"the \");poke(l+8,\"beginning \");poke(l+12,\"God \");poke(l+16,\"created \");poke(l+20,\"heaven \");poke(l+24,\"and \");poke(l+28,\"earth \");poke(l+32,\"light \");poke(l+36,\"darkness \");";
|
||||
fat32_write(fh, w1, cmd_strlen(w1));
|
||||
char *w2 = "poke(l+40,\"day \");poke(l+44,\"night \");poke(l+48,\"waters \");poke(l+52,\"firmament \");poke(l+56,\"evening \");poke(l+60,\"morning \");poke(l+64,\"land \");poke(l+68,\"seas \");poke(l+72,\"grass \");poke(l+76,\"herb \");";
|
||||
fat32_write(fh, w2, cmd_strlen(w2));
|
||||
char *w3 = "poke(l+80,\"seed \");poke(l+84,\"fruit \");poke(l+88,\"tree \");poke(l+92,\"sun \");poke(l+96,\"moon \");poke(l+100,\"stars \");poke(l+104,\"signs \");poke(l+108,\"seasons \");poke(l+112,\"days \");poke(l+116,\"years \");";
|
||||
fat32_write(fh, w3, cmd_strlen(w3));
|
||||
char *w4 = "poke(l+120,\"creature \");poke(l+124,\"life \");poke(l+128,\"fowl \");poke(l+132,\"whales \");poke(l+136,\"cattle \");poke(l+140,\"creeping \");poke(l+144,\"beast \");poke(l+148,\"man \");poke(l+152,\"image \");poke(l+156,\"likeness \");";
|
||||
fat32_write(fh, w4, cmd_strlen(w4));
|
||||
char *w5 = "poke(l+160,\"dominion \");poke(l+164,\"fish \");poke(l+168,\"air \");poke(l+172,\"every \");poke(l+176,\"CIA \");poke(l+180,\"meat \");poke(l+184,\"holy \");poke(l+188,\"rest \");poke(l+192,\"dust \");poke(l+196,\"breath \");";
|
||||
fat32_write(fh, w5, cmd_strlen(w5));
|
||||
char *w6 = "poke(l+200,\"soul \");poke(l+204,\"garden \");poke(l+208,\"east \");poke(l+212,\"Eden \");poke(l+216,\"ground \");poke(l+220,\"sight \");poke(l+224,\"good \");poke(l+228,\"evil \");poke(l+232,\"river \");poke(l+236,\"gold \");";
|
||||
fat32_write(fh, w6, cmd_strlen(w6));
|
||||
char *w7 = "poke(l+240,\"stone \");poke(l+244,\"woman \");poke(l+248,\"wife \");poke(l+252,\"flesh \");poke(l+256,\"bone \");poke(l+260,\"naked \");poke(l+264,\"serpent \");poke(l+268,\"subtle \");poke(l+272,\"eat \");poke(l+276,\"eyes \");";
|
||||
fat32_write(fh, w7, cmd_strlen(w7));
|
||||
char *w8 = "poke(l+280,\"wise \");poke(l+284,\"cool \");poke(l+288,\"voice \");poke(l+292,\"fear \");poke(l+296,\"hid \");poke(l+300,\"cursed \");poke(l+304,\"belly \");poke(l+308,\"enmity \");poke(l+312,\"sorrow \");poke(l+316,\"conception \");";
|
||||
fat32_write(fh, w8, cmd_strlen(w8));
|
||||
char *w9 = "poke(l+320,\"children \");poke(l+324,\"desire \");poke(l+328,\"husband \");poke(l+332,\"thorns \");poke(l+336,\"thistles \");poke(l+340,\"sweat \");poke(l+344,\"bread \");poke(l+348,\"mother \");poke(l+352,\"skin \");poke(l+356,\"coats \");";
|
||||
fat32_write(fh, w9, cmd_strlen(w9));
|
||||
char *w10 = "poke(l+360,\"cherubims \");poke(l+364,\"sword \");poke(l+368,\"gate \");poke(l+372,\"offering \");poke(l+376,\"respect \");poke(l+380,\"sin \");poke(l+384,\"door \");poke(l+388,\"blood \");poke(l+392,\"brother \");poke(l+396,\"keeper \");";
|
||||
fat32_write(fh, w10, cmd_strlen(w10));
|
||||
char *w11 = "poke(l+400,\"voice \");poke(l+404,\"heard \");poke(l+408,\"walking \");poke(l+412,\"cool \");poke(l+416,\"day \");poke(l+420,\"where \");poke(l+424,\"art \");poke(l+428,\"thou \");poke(l+432,\"told \");poke(l+436,\"thee \");";
|
||||
fat32_write(fh, w11, cmd_strlen(w11));
|
||||
char *w12 = "poke(l+440,\"hast \");poke(l+444,\"eaten \");poke(l+448,\"tree \");poke(l+452,\"whereof \");poke(l+456,\"commanded \");poke(l+460,\"shouldest \");poke(l+464,\"not \");poke(l+468,\"eat \");poke(l+472,\"gave \");poke(l+476,\"me \");";
|
||||
fat32_write(fh, w12, cmd_strlen(w12));
|
||||
char *w13 = "poke(l+480,\"beguiled \");poke(l+484,\"belly \");poke(l+488,\"go \");poke(l+492,\"dust \");poke(l+496,\"shalt \");poke(l+500,\"eat \");poke(l+504,\"days \");poke(l+508,\"life \");poke(l+512,\"put \");poke(l+516,\"enmity \");";
|
||||
fat32_write(fh, w13, cmd_strlen(w13));
|
||||
char *w14 = "poke(l+520,\"between \");poke(l+524,\"seed \");poke(l+528,\"bruise \");poke(l+532,\"head \");poke(l+536,\"heel \");poke(l+540,\"multiply \");poke(l+544,\"sorrow \");poke(l+548,\"conception \");poke(l+552,\"forth \");poke(l+556,\"children \");";
|
||||
fat32_write(fh, w14, cmd_strlen(w14));
|
||||
char *w15 = "poke(l+560,\"desire \");poke(l+564,\"rule \");poke(l+568,\"over \");poke(l+572,\"sake \");poke(l+576,\"sweat \");poke(l+580,\"face \");poke(l+584,\"till \");poke(l+588,\"return \");poke(l+592,\"ground \");poke(l+596,\"taken \");";
|
||||
fat32_write(fh, w15, cmd_strlen(w15));
|
||||
char *w16 = "poke(l+600,\"mother \");poke(l+604,\"living \");poke(l+608,\"coats \");poke(l+612,\"skins \");poke(l+616,\"clothed \");poke(l+620,\"become \");poke(l+624,\"one \");poke(l+628,\"us \");poke(l+632,\"know \");poke(l+636,\"good \");";
|
||||
fat32_write(fh, w16, cmd_strlen(w16));
|
||||
char *w17 = "poke(l+640,\"evil \");poke(l+644,\"lest \");poke(l+648,\"put \");poke(l+652,\"hand \");poke(l+656,\"take \");poke(l+660,\"live \");poke(l+664,\"ever \");poke(l+668,\"sent \");poke(l+672,\"garden \");poke(l+676,\"eden \");";
|
||||
fat32_write(fh, w17, cmd_strlen(w17));
|
||||
char *w18 = "poke(l+680,\"flaming \");poke(l+684,\"sword \");poke(l+688,\"turned \");poke(l+692,\"way \");poke(l+696,\"knew \");poke(l+700,\"conceived \");poke(l+704,\"bare \");poke(l+708,\"cain \");poke(l+712,\"said \");poke(l+716,\"gotten \");";
|
||||
fat32_write(fh, w18, cmd_strlen(w18));
|
||||
char *w19 = "poke(l+720,\"lord \");poke(l+724,\"again \");poke(l+728,\"abel \");poke(l+732,\"sheep \");poke(l+736,\"tiller \");poke(l+740,\"process \");poke(l+744,\"time \");poke(l+748,\"pass \");poke(l+752,\"brought \");poke(l+756,\"fruit \");";
|
||||
fat32_write(fh, w19, cmd_strlen(w19));
|
||||
char *w20 = "poke(l+760,\"offering \");poke(l+764,\"firstlings \");poke(l+768,\"flock \");poke(l+772,\"fat \");poke(l+776,\"thereof \");poke(l+780,\"respect \");poke(l+784,\"wroth \");poke(l+788,\"countenance \");poke(l+792,\"fallen \");poke(l+796,\"well \");";
|
||||
fat32_write(fh, w20, cmd_strlen(w20));
|
||||
char *w21 = "poke(l+800,\"accepted \");poke(l+804,\"not \");poke(l+808,\"sin \");poke(l+812,\"lieth \");poke(l+816,\"door \");poke(l+820,\"unto \");poke(l+824,\"rule \");poke(l+828,\"talked \");poke(l+832,\"field \");poke(l+836,\"rose \");";
|
||||
fat32_write(fh, w21, cmd_strlen(w21));
|
||||
char *w22 = "poke(l+840,\"slew \");poke(l+844,\"done \");poke(l+848,\"crieth \");poke(l+852,\"mouth \");poke(l+856,\"receive \");poke(l+860,\"strength \");poke(l+864,\"fugitive \");poke(l+868,\"vagabond \");poke(l+872,\"punishment \");poke(l+876,\"greater \");";
|
||||
fat32_write(fh, w22, cmd_strlen(w22));
|
||||
char *w23 = "poke(l+880,\"bear \");poke(l+884,\"driven \");poke(l+888,\"hid \");poke(l+892,\"findeth \");poke(l+896,\"slay \");poke(l+900,\"vengeance \");poke(l+904,\"sevenfold \");poke(l+908,\"mark \");poke(l+912,\"finding \");poke(l+916,\"kill \");";
|
||||
fat32_write(fh, w23, cmd_strlen(w23));
|
||||
char *w24 = "poke(l+920,\"presence \");poke(l+924,\"dwelt \");poke(l+928,\"nod \");poke(l+932,\"enoch \");poke(l+936,\"city \");poke(l+940,\"irad \");poke(l+944,\"mehujael \");poke(l+948,\"methusael \");poke(l+952,\"lamech \");poke(l+956,\"adah \");";
|
||||
fat32_write(fh, w24, cmd_strlen(w24));
|
||||
char *w25 = "poke(l+960,\"zillah \");poke(l+964,\"jabal \");poke(l+968,\"tent \");poke(l+972,\"cattle \");poke(l+976,\"jubal \");poke(l+980,\"harp \");poke(l+984,\"organ \");poke(l+988,\"tubalcain \");poke(l+992,\"brass \");poke(l+996,\"iron \");";
|
||||
fat32_write(fh, w25, cmd_strlen(w25));
|
||||
char *w26 = "poke(l+1000,\"naamah \");poke(l+1004,\"wives \");poke(l+1008,\"hear \");poke(l+1012,\"speech \");poke(l+1016,\"hearken \");poke(l+1020,\"young \");poke(l+1024,\"hurt \");poke(l+1028,\"wounding \");poke(l+1032,\"avenged \");poke(l+1036,\"seventy \");";
|
||||
fat32_write(fh, w26, cmd_strlen(w26));
|
||||
char *w27 = "poke(l+1040,\"seth \");poke(l+1044,\"appointed \");poke(l+1048,\"enos \");poke(l+1052,\"began \");poke(l+1056,\"call \");poke(l+1060,\"name \");poke(l+1064,\"generations \");poke(l+1068,\"adam \");poke(l+1072,\"likeness \");poke(l+1076,\"blessed \");";
|
||||
fat32_write(fh, w27, cmd_strlen(w27));
|
||||
char *w28 = "poke(l+1080,\"begat \");poke(l+1084,\"sons \");poke(l+1088,\"daughters \");poke(l+1092,\"lived \");poke(l+1096,\"died \");poke(l+1100,\"cainan \");poke(l+1104,\"mahalaleel \");poke(l+1108,\"jared \");poke(l+1112,\"walked \");poke(l+1116,\"three \");";
|
||||
fat32_write(fh, w28, cmd_strlen(w28));
|
||||
char *w29 = "poke(l+1120,\"hundred \");poke(l+1124,\"sixty \");poke(l+1128,\"five \");poke(l+1132,\"methuselah \");poke(l+1136,\"lamech \");poke(l+1140,\"noah \");poke(l+1144,\"comfort \");poke(l+1148,\"work \");poke(l+1152,\"toil \");poke(l+1156,\"hands \");";
|
||||
fat32_write(fh, w29, cmd_strlen(w29));
|
||||
char *w30 = "poke(l+1160,\"shem \");poke(l+1164,\"ham \");poke(l+1168,\"japheth \");poke(l+1172,\"men \");poke(l+1176,\"daughters \");poke(l+1180,\"born \");poke(l+1184,\"fair \");poke(l+1188,\"chose \");poke(l+1192,\"spirit \");poke(l+1196,\"strive \");";
|
||||
fat32_write(fh, w30, cmd_strlen(w30));
|
||||
char *e = "int c;int r;r=abs(rand());r=r-(r/5)*5;c=14+r;int i;i=0;while(i<c){int x;x=abs(rand());x=x-(x/300)*300;int w;w=peek(l+x*4);print_str(w);i=i+1;}nl();}";
|
||||
fat32_write(fh, e, cmd_strlen(e));
|
||||
// Buffer the entire file content to write in one go
|
||||
// This prevents issues with multiple small writes causing truncation
|
||||
char *buf = (char*)kmalloc(8192);
|
||||
if (buf) {
|
||||
int p = 0;
|
||||
const char *strs[] = {
|
||||
"int main(){int l;l=malloc(1200);",
|
||||
"poke(l+0,\"In \");poke(l+4,\"the \");poke(l+8,\"beginning \");poke(l+12,\"God \");poke(l+16,\"created \");poke(l+20,\"heaven \");poke(l+24,\"and \");poke(l+28,\"earth \");poke(l+32,\"light \");poke(l+36,\"darkness \");",
|
||||
"poke(l+40,\"day \");poke(l+44,\"night \");poke(l+48,\"waters \");poke(l+52,\"firmament \");poke(l+56,\"evening \");poke(l+60,\"morning \");poke(l+64,\"land \");poke(l+68,\"seas \");poke(l+72,\"grass \");poke(l+76,\"herb \");",
|
||||
"poke(l+80,\"seed \");poke(l+84,\"fruit \");poke(l+88,\"tree \");poke(l+92,\"sun \");poke(l+96,\"moon \");poke(l+100,\"stars \");poke(l+104,\"signs \");poke(l+108,\"seasons \");poke(l+112,\"days \");poke(l+116,\"years \");",
|
||||
"poke(l+120,\"creature \");poke(l+124,\"life \");poke(l+128,\"fowl \");poke(l+132,\"whales \");poke(l+136,\"cattle \");poke(l+140,\"creeping \");poke(l+144,\"beast \");poke(l+148,\"man \");poke(l+152,\"image \");poke(l+156,\"likeness \");",
|
||||
"poke(l+160,\"dominion \");poke(l+164,\"fish \");poke(l+168,\"air \");poke(l+172,\"every \");poke(l+176,\"CIA \");poke(l+180,\"meat \");poke(l+184,\"holy \");poke(l+188,\"rest \");poke(l+192,\"dust \");poke(l+196,\"breath \");",
|
||||
"poke(l+200,\"soul \");poke(l+204,\"garden \");poke(l+208,\"east \");poke(l+212,\"Eden \");poke(l+216,\"ground \");poke(l+220,\"sight \");poke(l+224,\"good \");poke(l+228,\"evil \");poke(l+232,\"river \");poke(l+236,\"gold \");",
|
||||
"poke(l+240,\"stone \");poke(l+244,\"woman \");poke(l+248,\"wife \");poke(l+252,\"flesh \");poke(l+256,\"bone \");poke(l+260,\"naked \");poke(l+264,\"serpent \");poke(l+268,\"subtle \");poke(l+272,\"eat \");poke(l+276,\"eyes \");",
|
||||
"poke(l+280,\"wise \");poke(l+284,\"cool \");poke(l+288,\"voice \");poke(l+292,\"fear \");poke(l+296,\"hid \");poke(l+300,\"cursed \");poke(l+304,\"belly \");poke(l+308,\"enmity \");poke(l+312,\"sorrow \");poke(l+316,\"conception \");",
|
||||
"poke(l+320,\"children \");poke(l+324,\"desire \");poke(l+328,\"husband \");poke(l+332,\"thorns \");poke(l+336,\"thistles \");poke(l+340,\"sweat \");poke(l+344,\"bread \");poke(l+348,\"mother \");poke(l+352,\"skin \");poke(l+356,\"coats \");",
|
||||
"poke(l+360,\"cherubims \");poke(l+364,\"sword \");poke(l+368,\"gate \");poke(l+372,\"offering \");poke(l+376,\"respect \");poke(l+380,\"sin \");poke(l+384,\"door \");poke(l+388,\"blood \");poke(l+392,\"brother \");poke(l+396,\"keeper \");",
|
||||
"poke(l+400,\"voice \");poke(l+404,\"heard \");poke(l+408,\"walking \");poke(l+412,\"cool \");poke(l+416,\"day \");poke(l+420,\"where \");poke(l+424,\"art \");poke(l+428,\"thou \");poke(l+432,\"told \");poke(l+436,\"thee \");",
|
||||
"poke(l+440,\"hast \");poke(l+444,\"eaten \");poke(l+448,\"tree \");poke(l+452,\"whereof \");poke(l+456,\"commanded \");poke(l+460,\"shouldest \");poke(l+464,\"not \");poke(l+468,\"eat \");poke(l+472,\"gave \");poke(l+476,\"me \");",
|
||||
"poke(l+480,\"beguiled \");poke(l+484,\"belly \");poke(l+488,\"go \");poke(l+492,\"dust \");poke(l+496,\"shalt \");poke(l+500,\"eat \");poke(l+504,\"days \");poke(l+508,\"life \");poke(l+512,\"put \");poke(l+516,\"enmity \");",
|
||||
"poke(l+520,\"between \");poke(l+524,\"seed \");poke(l+528,\"bruise \");poke(l+532,\"head \");poke(l+536,\"heel \");poke(l+540,\"multiply \");poke(l+544,\"sorrow \");poke(l+548,\"conception \");poke(l+552,\"forth \");poke(l+556,\"children \");",
|
||||
"poke(l+560,\"desire \");poke(l+564,\"rule \");poke(l+568,\"over \");poke(l+572,\"sake \");poke(l+576,\"sweat \");poke(l+580,\"face \");poke(l+584,\"till \");poke(l+588,\"return \");poke(l+592,\"ground \");poke(l+596,\"taken \");",
|
||||
"poke(l+600,\"mother \");poke(l+604,\"living \");poke(l+608,\"coats \");poke(l+612,\"skins \");poke(l+616,\"clothed \");poke(l+620,\"become \");poke(l+624,\"one \");poke(l+628,\"us \");poke(l+632,\"know \");poke(l+636,\"good \");",
|
||||
"poke(l+640,\"evil \");poke(l+644,\"lest \");poke(l+648,\"put \");poke(l+652,\"hand \");poke(l+656,\"take \");poke(l+660,\"live \");poke(l+664,\"ever \");poke(l+668,\"sent \");poke(l+672,\"garden \");poke(l+676,\"eden \");",
|
||||
"poke(l+680,\"flaming \");poke(l+684,\"sword \");poke(l+688,\"turned \");poke(l+692,\"way \");poke(l+696,\"knew \");poke(l+700,\"conceived \");poke(l+704,\"bare \");poke(l+708,\"cain \");poke(l+712,\"said \");poke(l+716,\"gotten \");",
|
||||
"poke(l+720,\"lord \");poke(l+724,\"again \");poke(l+728,\"abel \");poke(l+732,\"sheep \");poke(l+736,\"tiller \");poke(l+740,\"process \");poke(l+744,\"time \");poke(l+748,\"pass \");poke(l+752,\"brought \");poke(l+756,\"fruit \");",
|
||||
"poke(l+760,\"offering \");poke(l+764,\"firstlings \");poke(l+768,\"flock \");poke(l+772,\"fat \");poke(l+776,\"thereof \");poke(l+780,\"respect \");poke(l+784,\"wroth \");poke(l+788,\"countenance \");poke(l+792,\"fallen \");poke(l+796,\"well \");",
|
||||
"poke(l+800,\"accepted \");poke(l+804,\"not \");poke(l+808,\"sin \");poke(l+812,\"lieth \");poke(l+816,\"door \");poke(l+820,\"unto \");poke(l+824,\"rule \");poke(l+828,\"talked \");poke(l+832,\"field \");poke(l+836,\"rose \");",
|
||||
"poke(l+840,\"slew \");poke(l+844,\"done \");poke(l+848,\"crieth \");poke(l+852,\"mouth \");poke(l+856,\"receive \");poke(l+860,\"strength \");poke(l+864,\"fugitive \");poke(l+868,\"vagabond \");poke(l+872,\"punishment \");poke(l+876,\"greater \");",
|
||||
"poke(l+880,\"bear \");poke(l+884,\"driven \");poke(l+888,\"hid \");poke(l+892,\"findeth \");poke(l+896,\"slay \");poke(l+900,\"vengeance \");poke(l+904,\"sevenfold \");poke(l+908,\"mark \");poke(l+912,\"finding \");poke(l+916,\"kill \");",
|
||||
"poke(l+920,\"presence \");poke(l+924,\"dwelt \");poke(l+928,\"nod \");poke(l+932,\"enoch \");poke(l+936,\"city \");poke(l+940,\"irad \");poke(l+944,\"mehujael \");poke(l+948,\"methusael \");poke(l+952,\"lamech \");poke(l+956,\"adah \");",
|
||||
"poke(l+960,\"zillah \");poke(l+964,\"jabal \");poke(l+968,\"tent \");poke(l+972,\"cattle \");poke(l+976,\"jubal \");poke(l+980,\"harp \");poke(l+984,\"organ \");poke(l+988,\"tubalcain \");poke(l+992,\"brass \");poke(l+996,\"iron \");",
|
||||
"poke(l+1000,\"naamah \");poke(l+1004,\"wives \");poke(l+1008,\"hear \");poke(l+1012,\"speech \");poke(l+1016,\"hearken \");poke(l+1020,\"young \");poke(l+1024,\"hurt \");poke(l+1028,\"wounding \");poke(l+1032,\"avenged \");poke(l+1036,\"seventy \");",
|
||||
"poke(l+1040,\"seth \");poke(l+1044,\"appointed \");poke(l+1048,\"enos \");poke(l+1052,\"began \");poke(l+1056,\"call \");poke(l+1060,\"name \");poke(l+1064,\"generations \");poke(l+1068,\"adam \");poke(l+1072,\"likeness \");poke(l+1076,\"blessed \");",
|
||||
"poke(l+1080,\"begat \");poke(l+1084,\"sons \");poke(l+1088,\"daughters \");poke(l+1092,\"lived \");poke(l+1096,\"died \");poke(l+1100,\"cainan \");poke(l+1104,\"mahalaleel \");poke(l+1108,\"jared \");poke(l+1112,\"walked \");poke(l+1116,\"three \");",
|
||||
"poke(l+1120,\"hundred \");poke(l+1124,\"sixty \");poke(l+1128,\"five \");poke(l+1132,\"methuselah \");poke(l+1136,\"lamech \");poke(l+1140,\"noah \");poke(l+1144,\"comfort \");poke(l+1148,\"work \");poke(l+1152,\"toil \");poke(l+1156,\"hands \");",
|
||||
"poke(l+1160,\"shem \");poke(l+1164,\"ham \");poke(l+1168,\"japheth \");poke(l+1172,\"men \");poke(l+1176,\"daughters \");poke(l+1180,\"born \");poke(l+1184,\"fair \");poke(l+1188,\"chose \");poke(l+1192,\"spirit \");poke(l+1196,\"strive \");",
|
||||
"int c;int r;r=abs(rand());r=r-(r/5)*5;c=14+r;int i;i=0;while(i<c){int x;x=abs(rand());x=x-(x/300)*300;int w;w=peek(l+x*4);print_str(w);i=i+1;}nl();}",
|
||||
NULL
|
||||
};
|
||||
|
||||
for (int i = 0; strs[i]; i++) {
|
||||
const char *s = strs[i];
|
||||
while (*s && p < 8191) buf[p++] = *s++;
|
||||
}
|
||||
|
||||
fat32_write(fh, buf, p);
|
||||
kfree(buf);
|
||||
}
|
||||
fat32_close(fh);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void cmd_init(void) {
|
||||
fat32_init(); // Init FAT32 filesystem
|
||||
create_test_files();
|
||||
|
||||
@@ -17,6 +17,7 @@ Window win_control_panel;
|
||||
#define VIEW_MAIN 0
|
||||
#define VIEW_WALLPAPER 1
|
||||
#define VIEW_NETWORK 2
|
||||
#define VIEW_DESKTOP 3
|
||||
|
||||
static int current_view = VIEW_MAIN;
|
||||
static char rgb_r[4] = "";
|
||||
@@ -197,6 +198,16 @@ static void control_panel_paint_main(Window *win) {
|
||||
draw_rect(offset_x + 23, net_offset_y + 5, 1, 11, 0xFFFFFFFF);
|
||||
|
||||
draw_string(offset_x + 40, net_offset_y + 8, "Network", 0xFF000000);
|
||||
|
||||
// Draw Desktop Settings Icon
|
||||
int desk_offset_y = net_offset_y + 35;
|
||||
// Folder icon style
|
||||
draw_rect(offset_x + 5, desk_offset_y + 2, 12, 4, COLOR_LTGRAY);
|
||||
draw_rect(offset_x + 5, desk_offset_y + 2, 12, 1, COLOR_BLACK);
|
||||
draw_rect(offset_x + 5, desk_offset_y + 6, 24, 14, 0xFFE0C060); // Tan folder
|
||||
draw_rect(offset_x + 5, desk_offset_y + 6, 24, 1, COLOR_BLACK);
|
||||
draw_rect(offset_x + 5, desk_offset_y + 6, 1, 14, COLOR_BLACK);
|
||||
draw_string(offset_x + 40, desk_offset_y + 8, "Desktop", 0xFF000000);
|
||||
}
|
||||
|
||||
static void control_panel_paint_wallpaper(Window *win) {
|
||||
@@ -409,6 +420,54 @@ static void control_panel_paint_network(Window *win) {
|
||||
draw_button(offset_x, section_y, 80, 22, "Send", false);
|
||||
}
|
||||
|
||||
static void control_panel_paint_desktop(Window *win) {
|
||||
int offset_x = win->x + 8;
|
||||
int offset_y = win->y + 30;
|
||||
|
||||
// Back button
|
||||
draw_string(offset_x, offset_y, "< Back", 0xFF000080);
|
||||
draw_string(offset_x, offset_y + 25, "Desktop Settings:", 0xFF000000);
|
||||
|
||||
int section_y = offset_y + 50;
|
||||
|
||||
// Snap to Grid
|
||||
draw_rect(offset_x, section_y, 15, 15, 0xFFFFFFFF);
|
||||
draw_rect(offset_x, section_y, 15, 1, COLOR_BLACK);
|
||||
draw_rect(offset_x, section_y, 1, 15, COLOR_BLACK);
|
||||
draw_rect(offset_x + 14, section_y, 1, 15, COLOR_BLACK);
|
||||
draw_rect(offset_x, section_y + 14, 15, 1, COLOR_BLACK);
|
||||
if (desktop_snap_to_grid) draw_string(offset_x + 3, section_y + 3, "X", COLOR_BLACK);
|
||||
draw_string(offset_x + 25, section_y + 3, "Snap to Grid", COLOR_BLACK);
|
||||
|
||||
// Auto Align
|
||||
section_y += 25;
|
||||
draw_rect(offset_x, section_y, 15, 15, 0xFFFFFFFF);
|
||||
draw_rect(offset_x, section_y, 15, 1, COLOR_BLACK);
|
||||
draw_rect(offset_x, section_y, 1, 15, COLOR_BLACK);
|
||||
draw_rect(offset_x + 14, section_y, 1, 15, COLOR_BLACK);
|
||||
draw_rect(offset_x, section_y + 14, 15, 1, COLOR_BLACK);
|
||||
if (desktop_auto_align) draw_string(offset_x + 3, section_y + 3, "X", COLOR_BLACK);
|
||||
draw_string(offset_x + 25, section_y + 3, "Auto Align Icons", COLOR_BLACK);
|
||||
|
||||
// Max Rows
|
||||
section_y += 25;
|
||||
draw_string(offset_x, section_y + 3, "Apps per column:", COLOR_BLACK);
|
||||
draw_button(offset_x + 130, section_y, 20, 20, "-", false);
|
||||
char num[4]; num[0] = '0' + (desktop_max_rows_per_col / 10); num[1] = '0' + (desktop_max_rows_per_col % 10); num[2] = 0;
|
||||
if (num[0] == '0') { num[0] = num[1]; num[1] = 0; }
|
||||
draw_string(offset_x + 160, section_y + 5, num, COLOR_BLACK);
|
||||
draw_button(offset_x + 180, section_y, 20, 20, "+", false);
|
||||
|
||||
// Max Cols
|
||||
section_y += 25;
|
||||
draw_string(offset_x, section_y + 3, "Columns:", COLOR_BLACK);
|
||||
draw_button(offset_x + 130, section_y, 20, 20, "-", false);
|
||||
char num_c[4]; num_c[0] = '0' + (desktop_max_cols / 10); num_c[1] = '0' + (desktop_max_cols % 10); num_c[2] = 0;
|
||||
if (num_c[0] == '0') { num_c[0] = num_c[1]; num_c[1] = 0; }
|
||||
draw_string(offset_x + 160, section_y + 5, num_c, COLOR_BLACK);
|
||||
draw_button(offset_x + 180, section_y, 20, 20, "+", false);
|
||||
}
|
||||
|
||||
static void control_panel_paint(Window *win) {
|
||||
if (current_view == VIEW_MAIN) {
|
||||
control_panel_paint_main(win);
|
||||
@@ -416,6 +475,8 @@ static void control_panel_paint(Window *win) {
|
||||
control_panel_paint_wallpaper(win);
|
||||
} else if (current_view == VIEW_NETWORK) {
|
||||
control_panel_paint_network(win);
|
||||
} else if (current_view == VIEW_DESKTOP) {
|
||||
control_panel_paint_desktop(win);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -440,6 +501,13 @@ static void control_panel_handle_click(Window *win, int x, int y) {
|
||||
current_view = VIEW_NETWORK;
|
||||
focused_field = -1;
|
||||
}
|
||||
|
||||
// Check desktop button
|
||||
int desk_offset_y = net_offset_y + 35;
|
||||
if (x >= offset_x + 5 && x < offset_x + 120 &&
|
||||
y >= desk_offset_y && y < desk_offset_y + 25) {
|
||||
current_view = VIEW_DESKTOP;
|
||||
}
|
||||
} else if (current_view == VIEW_WALLPAPER) {
|
||||
int offset_x = 8;
|
||||
int offset_y = 30;
|
||||
@@ -727,6 +795,73 @@ static void control_panel_handle_click(Window *win, int x, int y) {
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else if (current_view == VIEW_DESKTOP) {
|
||||
int offset_x = 8;
|
||||
int offset_y = 30;
|
||||
|
||||
// Back button
|
||||
if (x >= offset_x && x < offset_x + 40 && y >= offset_y && y < offset_y + 15) {
|
||||
current_view = VIEW_MAIN;
|
||||
return;
|
||||
}
|
||||
|
||||
int section_y = offset_y + 50;
|
||||
// Snap toggle
|
||||
if (x >= offset_x && x < offset_x + 150 && y >= section_y && y < section_y + 20) {
|
||||
desktop_snap_to_grid = !desktop_snap_to_grid;
|
||||
// If Snap is turned OFF, Auto Align must be OFF
|
||||
if (!desktop_snap_to_grid) {
|
||||
desktop_auto_align = false;
|
||||
}
|
||||
wm_refresh_desktop();
|
||||
return;
|
||||
}
|
||||
|
||||
// Auto Align toggle
|
||||
section_y += 25;
|
||||
if (x >= offset_x && x < offset_x + 150 && y >= section_y && y < section_y + 20) {
|
||||
desktop_auto_align = !desktop_auto_align;
|
||||
// If Auto Align is turned ON, Snap must be ON
|
||||
if (desktop_auto_align) {
|
||||
desktop_snap_to_grid = true;
|
||||
}
|
||||
wm_refresh_desktop();
|
||||
return;
|
||||
}
|
||||
|
||||
// Rows adjust
|
||||
section_y += 25;
|
||||
if (x >= offset_x + 130 && x < offset_x + 150 && y >= section_y && y < section_y + 20) {
|
||||
if (desktop_max_rows_per_col > 1) {
|
||||
if (desktop_max_cols * (desktop_max_rows_per_col - 1) < wm_get_desktop_icon_count()) {
|
||||
wm_show_message("Error", "Cannot reduce rows: too many files!");
|
||||
} else {
|
||||
desktop_max_rows_per_col--;
|
||||
wm_refresh_desktop();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (x >= offset_x + 180 && x < offset_x + 200 && y >= section_y && y < section_y + 20) {
|
||||
if (desktop_max_rows_per_col < 15) desktop_max_rows_per_col++;
|
||||
wm_refresh_desktop();
|
||||
}
|
||||
|
||||
// Cols adjust
|
||||
section_y += 25;
|
||||
if (x >= offset_x + 130 && x < offset_x + 150 && y >= section_y && y < section_y + 20) {
|
||||
if (desktop_max_cols > 1) {
|
||||
if ((desktop_max_cols - 1) * desktop_max_rows_per_col < wm_get_desktop_icon_count()) {
|
||||
wm_show_message("Error", "Cannot reduce cols: too many files!");
|
||||
} else {
|
||||
desktop_max_cols--;
|
||||
wm_refresh_desktop();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (x >= offset_x + 180 && x < offset_x + 200 && y >= section_y && y < section_y + 20) {
|
||||
if (desktop_max_cols < 20) desktop_max_cols++;
|
||||
wm_refresh_desktop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -12,5 +12,25 @@ extern Window win_markdown;
|
||||
|
||||
void explorer_init(void);
|
||||
void explorer_reset(void);
|
||||
void explorer_refresh(void);
|
||||
void explorer_clear_click_state(void);
|
||||
|
||||
// Drag and Drop support
|
||||
bool explorer_get_file_at(int screen_x, int screen_y, char *out_path, bool *is_dir);
|
||||
void explorer_import_file(const char *source_path);
|
||||
void explorer_import_file_to(const char *source_path, const char *dest_dir);
|
||||
|
||||
// Clipboard
|
||||
void explorer_clipboard_copy(const char *path);
|
||||
void explorer_clipboard_cut(const char *path);
|
||||
void explorer_clipboard_paste(const char *dest_dir);
|
||||
bool explorer_clipboard_has_content(void);
|
||||
|
||||
// File Operations
|
||||
bool explorer_delete_permanently(const char *path);
|
||||
bool explorer_delete_recursive(const char *path);
|
||||
void explorer_create_shortcut(const char *target_path);
|
||||
|
||||
void explorer_open_directory(const char *path);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -29,6 +29,7 @@ static FileEntry files[MAX_FILES];
|
||||
static uint32_t next_cluster = 3; // Start after reserved clusters 0, 1, 2
|
||||
static FAT32_FileHandle open_handles[MAX_OPEN_HANDLES];
|
||||
static char current_dir[FAT32_MAX_PATH] = "/";
|
||||
static int desktop_file_limit = -1;
|
||||
|
||||
// === Helper Functions ===
|
||||
|
||||
@@ -208,6 +209,34 @@ static uint32_t allocate_cluster(void) {
|
||||
return cluster;
|
||||
}
|
||||
|
||||
// Check desktop limit
|
||||
static bool check_desktop_limit(const char *normalized_path) {
|
||||
if (desktop_file_limit < 0) return true;
|
||||
|
||||
// Check if path is directly in /Desktop (not subfolder)
|
||||
// Path should start with /Desktop/ and have no other slashes
|
||||
if (fs_strlen(normalized_path) > 9 &&
|
||||
normalized_path[0] == '/' &&
|
||||
normalized_path[1] == 'D' && normalized_path[2] == 'e' &&
|
||||
normalized_path[3] == 's' && normalized_path[4] == 'k' &&
|
||||
normalized_path[5] == 't' && normalized_path[6] == 'o' &&
|
||||
normalized_path[7] == 'p' && normalized_path[8] == '/') {
|
||||
|
||||
// Check for subfolders
|
||||
const char *p = normalized_path + 9;
|
||||
while (*p) {
|
||||
if (*p == '/') return true; // Subfolder, allow
|
||||
p++;
|
||||
}
|
||||
|
||||
// Count files in /Desktop
|
||||
FAT32_FileInfo info[256]; // Temp buffer
|
||||
int count = fat32_list_directory("/Desktop", info, 256);
|
||||
if (count >= desktop_file_limit) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// === Public API ===
|
||||
|
||||
void fat32_init(void) {
|
||||
@@ -235,6 +264,10 @@ void fat32_init(void) {
|
||||
current_dir[1] = 0;
|
||||
}
|
||||
|
||||
void fat32_set_desktop_limit(int limit) {
|
||||
desktop_file_limit = limit;
|
||||
}
|
||||
|
||||
FAT32_FileHandle* fat32_open(const char *path, const char *mode) {
|
||||
char normalized[FAT32_MAX_PATH];
|
||||
fat32_normalize_path(path, normalized);
|
||||
@@ -249,6 +282,10 @@ FAT32_FileHandle* fat32_open(const char *path, const char *mode) {
|
||||
} else if (mode[0] == 'w' || (mode[0] == 'a')) {
|
||||
// Write/append mode - create if not exists
|
||||
if (!entry) {
|
||||
if (!check_desktop_limit(normalized)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
entry = find_free_entry();
|
||||
if (!entry) return NULL;
|
||||
|
||||
@@ -355,7 +392,7 @@ int fat32_write(FAT32_FileHandle *handle, const void *buffer, int size) {
|
||||
int bytes_written = 0;
|
||||
const uint8_t *buf = (const uint8_t *)buffer;
|
||||
|
||||
// Check if we are at a cluster boundary from a previous write
|
||||
// Check for cluster boundary from a previous write
|
||||
if (handle->position > 0 && (handle->position % FAT32_CLUSTER_SIZE) == 0) {
|
||||
uint32_t next = fat_table[handle->cluster];
|
||||
if (next >= 0xFFFFFFF8) {
|
||||
@@ -441,6 +478,10 @@ bool fat32_mkdir(const char *path) {
|
||||
return false; // Already exists
|
||||
}
|
||||
|
||||
if (!check_desktop_limit(normalized)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FileEntry *entry = find_free_entry();
|
||||
if (!entry) return false;
|
||||
|
||||
|
||||
@@ -83,6 +83,8 @@ typedef struct {
|
||||
uint32_t size; // File size
|
||||
uint32_t mode; // 0=read, 1=write, 2=append
|
||||
bool valid; // Is this handle valid?
|
||||
uint32_t dir_sector; // Sector containing the directory entry
|
||||
uint32_t dir_offset; // Offset within that sector
|
||||
} FAT32_FileHandle;
|
||||
|
||||
// Directory Entry Info (for listing)
|
||||
@@ -124,4 +126,7 @@ void fat32_get_current_dir(char *buffer, int size);
|
||||
// Utilities
|
||||
void fat32_normalize_path(const char *path, char *normalized);
|
||||
|
||||
// Desktop Limit
|
||||
void fat32_set_desktop_limit(int limit);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -14,12 +14,16 @@ static bool g_use_pattern = false;
|
||||
static DirtyRect g_dirty = {0, 0, 0, 0, false};
|
||||
|
||||
// Double buffering - allocate a back buffer
|
||||
// Max screen size: 2048x2048 @ 32bpp = 16MB, but we'll allocate for common sizes
|
||||
// Max screen size: 2048x2048 @ 32bpp = 16MB, but allocate for common sizes
|
||||
// Using a simple approach: allocate max size buffer
|
||||
#define MAX_FB_WIDTH 2048
|
||||
#define MAX_FB_HEIGHT 2048
|
||||
static uint32_t g_back_buffer[MAX_FB_WIDTH * MAX_FB_HEIGHT] __attribute__((aligned(4096)));
|
||||
|
||||
// Clipping state
|
||||
static int g_clip_x = 0, g_clip_y = 0, g_clip_w = 0, g_clip_h = 0;
|
||||
static bool g_clip_enabled = false;
|
||||
|
||||
void graphics_init(struct limine_framebuffer *fb) {
|
||||
g_fb = fb;
|
||||
g_dirty.active = false;
|
||||
@@ -106,6 +110,13 @@ void put_pixel(int x, int y, uint32_t color) {
|
||||
if (!g_fb) return;
|
||||
if (x < 0 || x >= (int)g_fb->width || y < 0 || y >= (int)g_fb->height) return;
|
||||
|
||||
if (g_clip_enabled) {
|
||||
if (x < g_clip_x || x >= g_clip_x + g_clip_w ||
|
||||
y < g_clip_y || y >= g_clip_y + g_clip_h) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw to back buffer
|
||||
uint32_t pixel_offset = y * g_fb->width + x;
|
||||
g_back_buffer[pixel_offset] = color;
|
||||
@@ -208,3 +219,15 @@ void graphics_flip_buffer(void) {
|
||||
dst += g_fb->pitch;
|
||||
}
|
||||
}
|
||||
|
||||
void graphics_set_clipping(int x, int y, int w, int h) {
|
||||
g_clip_x = x;
|
||||
g_clip_y = y;
|
||||
g_clip_w = w;
|
||||
g_clip_h = h;
|
||||
g_clip_enabled = true;
|
||||
}
|
||||
|
||||
void graphics_clear_clipping(void) {
|
||||
g_clip_enabled = false;
|
||||
}
|
||||
|
||||
@@ -34,4 +34,8 @@ void graphics_clear_dirty(void);
|
||||
void graphics_flip_buffer(void);
|
||||
void graphics_clear_back_buffer(uint32_t color);
|
||||
|
||||
// Clipping
|
||||
void graphics_set_clipping(int x, int y, int w, int h);
|
||||
void graphics_clear_clipping(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -47,10 +47,6 @@ static void pic_remap(void) {
|
||||
outb(0x21, 0x01); io_wait();
|
||||
outb(0xA1, 0x01); io_wait();
|
||||
|
||||
// Restore masks (but verify we don't mask IRQ 1 and 12)
|
||||
// Actually, simple OSs often just mask everything except what they want.
|
||||
// Let's unmask IRQ 1 (Keyboard) and IRQ 12 (Mouse) explicitly and mask others.
|
||||
// 0xFD = 1111 1101 (IRQ 1 unmasked)
|
||||
// 0xEF = 1110 1111 (IRQ 12 (4 on slave) unmasked)
|
||||
|
||||
outb(0x21, 0xF9); // Unmask Keyboard (IRQ1) and Cascade (IRQ2)
|
||||
|
||||
@@ -49,9 +49,6 @@ static void hcf(void) {
|
||||
void kmain(void) {
|
||||
platform_init();
|
||||
// 1. Graphics Init
|
||||
if (LIMINE_BASE_REVISION_SUPPORTED == false) {
|
||||
// Warning
|
||||
}
|
||||
|
||||
if (framebuffer_request.response == NULL || framebuffer_request.response->framebuffer_count < 1) {
|
||||
hcf();
|
||||
|
||||
@@ -66,7 +66,6 @@ static int md_strncpy(char *dest, const char *src, int n) {
|
||||
static int md_strcmp(const char *s1, const char *s2) {
|
||||
(void)s1; // Suppress unused warning
|
||||
(void)s2; // Suppress unused warning
|
||||
// Reserved for future use
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -74,7 +73,6 @@ static int md_strcmp(const char *s1, const char *s2) {
|
||||
static bool md_starts_with(const char *str, const char *pattern) {
|
||||
(void)str; // Suppress unused warning
|
||||
(void)pattern; // Suppress unused warning
|
||||
// Reserved for future use
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -289,7 +289,7 @@ MemStats memory_get_stats(void) {
|
||||
void memory_print_stats(void) {
|
||||
MemStats stats = memory_get_stats();
|
||||
|
||||
// We need to use the CLI write functions - declare them as extern
|
||||
// Use CLI write functions - declare as extern
|
||||
extern void cmd_write(const char *str);
|
||||
extern void cmd_write_int(int n);
|
||||
extern void cmd_putchar(char c);
|
||||
|
||||
@@ -222,8 +222,6 @@ int ipv4_send_packet(const ipv4_address_t* dest_ip,uint8_t protocol,const void*
|
||||
} else {
|
||||
int ok=arp_lookup(&target_ip,&dest_mac);
|
||||
if(ok!=0){
|
||||
// ARP failed, maybe broadcast? Or fail?
|
||||
// For now, keep existing behavior of broadcasting if ARP fails
|
||||
for(int i=0;i<6;i++) dest_mac.bytes[i]=0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,7 +162,7 @@ static void vm_syscall(int id) {
|
||||
break;
|
||||
}
|
||||
case SYS_STRCAT: {
|
||||
// Not implemented in cli_utils, skip
|
||||
// Not implemented in cli_utils
|
||||
pop(); pop(); push(0);
|
||||
break;
|
||||
}
|
||||
@@ -188,8 +188,7 @@ static void vm_syscall(int id) {
|
||||
}
|
||||
// Simplified Heap (using top of memory growing down?)
|
||||
// For now, static allocation or mapped.
|
||||
// Let's implement a dummy malloc that returns an index into memory
|
||||
// Starting at 1024 (reserve first 1K for globals)
|
||||
// Dummy malloc that returns an index into memory starting at 1024
|
||||
case SYS_MALLOC: {
|
||||
int size = pop();
|
||||
int res = vm_heap_ptr;
|
||||
@@ -317,8 +316,8 @@ static void vm_syscall(int id) {
|
||||
push(0);
|
||||
break;
|
||||
}
|
||||
case SYS_EXEC: pop(); push(-1); break; // Not impl
|
||||
case SYS_SYSTEM: pop(); push(-1); break; // Not impl
|
||||
case SYS_EXEC: pop(); push(-1); break;
|
||||
case SYS_SYSTEM: pop(); push(-1); break;
|
||||
|
||||
// --- New Builtins ---
|
||||
case SYS_ISALNUM: {
|
||||
@@ -601,7 +600,6 @@ int vm_exec(const uint8_t *code, int code_size) {
|
||||
break;
|
||||
}
|
||||
case OP_POP:
|
||||
// cmd_write("DEBUG: POP\n");
|
||||
pop();
|
||||
break;
|
||||
default:
|
||||
|
||||
1225
src/kernel/wm.c
1225
src/kernel/wm.c
File diff suppressed because it is too large
Load Diff
@@ -51,7 +51,10 @@ void wm_process_input(void);
|
||||
void wm_mark_dirty(int x, int y, int w, int h);
|
||||
void wm_refresh(void);
|
||||
void wm_paint(void);
|
||||
void wm_refresh_desktop(void);
|
||||
void wm_timer_tick(void);
|
||||
int wm_get_desktop_icon_count(void);
|
||||
void wm_show_message(const char *title, const char *message);
|
||||
|
||||
// Hook for external rendering (e.g. VM overlay)
|
||||
extern void (*wm_custom_paint_hook)(void);
|
||||
@@ -59,5 +62,21 @@ extern void (*wm_custom_paint_hook)(void);
|
||||
// Drawing helpers
|
||||
void draw_bevel_rect(int x, int y, int w, int h, bool sunken);
|
||||
void draw_button(int x, int y, int w, int h, const char *text, bool pressed);
|
||||
void draw_icon(int x, int y, const char *label);
|
||||
void draw_folder_icon(int x, int y, const char *label);
|
||||
void draw_document_icon(int x, int y, const char *label);
|
||||
void draw_notepad_icon(int x, int y, const char *label);
|
||||
void draw_calculator_icon(int x, int y, const char *label);
|
||||
void draw_terminal_icon(int x, int y, const char *label);
|
||||
void draw_minesweeper_icon(int x, int y, const char *label);
|
||||
void draw_control_panel_icon(int x, int y, const char *label);
|
||||
void draw_about_icon(int x, int y, const char *label);
|
||||
void draw_recycle_bin_icon(int x, int y, const char *label);
|
||||
|
||||
// Desktop Settings
|
||||
extern bool desktop_snap_to_grid;
|
||||
extern bool desktop_auto_align;
|
||||
extern int desktop_max_rows_per_col;
|
||||
extern int desktop_max_cols;
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user