Begin move to k3Menu

This commit is contained in:
Mid 2025-07-06 17:58:57 +03:00
parent c4d808833a
commit 93b885cb43
12 changed files with 410 additions and 547 deletions

View File

@ -199,37 +199,6 @@ foundStart:
return len; return len;
} }
static inline void pr(int c) {
asm volatile("outb %%al, $0xE9" :: "a"(c) :);
}
static inline void pri(size_t num) {
char buf[16] = {};
int i = 16;
do {
buf[--i] = num % 10;
num /= 10;
} while(num);
for(; i < 16; i++) {
pr(buf[i] + '0');
}
}
static inline void prs(const Str16 *str) {
for(int i = 0; i < str->len; i++) {
pr(str->data[i]);
}
}
static inline void prcs(const char *str) {
while(*str) {
pr(*str);
str++;
}
}
// I don't like this. // I don't like this.
// Biggest ugly by far is how it operates in 512-byte chunks, even though lean_read_inode already handles unaligned access // Biggest ugly by far is how it operates in 512-byte chunks, even though lean_read_inode already handles unaligned access
uint64_t find_child(const struct INode *node, const Str16 *name) { uint64_t find_child(const struct INode *node, const Str16 *name) {

View File

@ -74,6 +74,34 @@ static inline unsigned char std_bytecomp(size_t len, const void *one_, const voi
#define std_min(a, b) ({__typeof__(a) _a = (a); __typeof__(b) _b = (b); _a<_b?_a:_b;}) #define std_min(a, b) ({__typeof__(a) _a = (a); __typeof__(b) _b = (b); _a<_b?_a:_b;})
#define std_max(a, b) ({__typeof__(a) _a = (a); __typeof__(b) _b = (b); _a>_b?_a:_b;}) #define std_max(a, b) ({__typeof__(a) _a = (a); __typeof__(b) _b = (b); _a>_b?_a:_b;})
static inline void pr(int c) {
asm volatile("outb %%al, $0xE9" :: "a"(c) :);
}
static inline void pri(size_t num) {
char buf[16] = {};
int i = 16;
do {
buf[--i] = num % 10;
num /= 10;
} while(num);
for(; i < 16; i++) {
pr(buf[i] + '0');
}
}
static inline void prs(const Str16 *str) {
for(int i = 0; i < str->len; i++) {
pr(str->data[i]);
}
}
static inline void prcs(const char *str) {
while(*str) {
pr(*str);
str++;
}
}
//#define S16_ARG(str) ((Str16*) &(struct {uint16_t len; char content[sizeof(str) - 1]}) {sizeof(str) - 1, (str)}) //#define S16_ARG(str) ((Str16*) &(struct {uint16_t len; char content[sizeof(str) - 1]}) {sizeof(str) - 1, (str)})
#endif #endif

View File

@ -4,8 +4,13 @@
#include<stdint.h> #include<stdint.h>
typedef enum { typedef enum {
LUMA_VID_COMMAND_END = 0, LUMA_VID_COMMAND_CLEAR = 1, LUMA_VID_COMMAND_RECT = 2, LUMA_VID_COMMAND_IMAGE = 3, LUMA_VID_COMMAND_IMAGE_NEW = 4, LUMA_VID_COMMAND_SET_COLOR_FLAT = 5, LUMA_VID_COMMAND_END = 0, LUMA_VID_COMMAND_CLEAR = 1,
LUMA_VID_COMMAND_SET_COLOR_GRAD = 6, LUMA_VID_COMMAND_IMAGE_DEL = 7, LUMA_VID_COMMAND_TEXT = 8, LUMA_VID_COMMAND_NEW_COLOR_FLAT = 9, LUMA_VID_COMMAND_NEW_COLOR_GRAD = 10, LUMA_VID_COMMAND_IMAGE_WRITE = 11, LUMA_VID_COMMAND_RECT = 2, LUMA_VID_COMMAND_IMAGE = 3,
LUMA_VID_COMMAND_IMAGE_NEW = 4, LUMA_VID_COMMAND_SET_COLOR_FLAT = 5,
LUMA_VID_COMMAND_SET_COLOR_GRAD = 6, LUMA_VID_COMMAND_IMAGE_DEL = 7,
LUMA_VID_COMMAND_TEXT = 8, LUMA_VID_COMMAND_NEW_COLOR_FLAT = 9,
LUMA_VID_COMMAND_NEW_COLOR_GRAD = 10, LUMA_VID_COMMAND_IMAGE_WRITE = 11,
LUMA_VID_COMMAND_TEXT_EXTENT = 12
} LumaVidCommandOp; } LumaVidCommandOp;
typedef enum { typedef enum {
@ -19,6 +24,12 @@ typedef enum {
LUMA_VID_ALIGN_BOTTOM_RIGHT = 3, LUMA_VID_ALIGN_BOTTOM_RIGHT = 3,
} LumaVidAlign; } LumaVidAlign;
typedef enum {
LUMA_VID_TEXT_ALIGN_LEFT = 0,
LUMA_VID_TEXT_ALIGN_CENTER = 1,
LUMA_VID_TEXT_ALIGN_RIGHT = 2,
} LumaVidTextAlign;
typedef union { typedef union {
uint8_t op; uint8_t op;
struct { struct {
@ -73,6 +84,7 @@ typedef union {
uint16_t x; uint16_t x;
uint16_t len; uint16_t len;
uint16_t wall; uint16_t wall;
uint8_t align;
uint8_t data[]; uint8_t data[];
} __attribute__((packed)) text; } __attribute__((packed)) text;
struct { struct {
@ -83,6 +95,14 @@ typedef union {
uint16_t len; uint16_t len;
uint8_t data[]; uint8_t data[];
} __attribute__((packed)) imageWrite; } __attribute__((packed)) imageWrite;
struct {
uint8_t op;
uint16_t h;
uint16_t w;
uint16_t len;
uint16_t wall;
uint8_t data[];
} __attribute__((packed)) textExtent;
} __attribute__((packed)) LumaVidCommand; } __attribute__((packed)) LumaVidCommand;
#endif #endif

View File

@ -129,10 +129,7 @@ __attribute__((optimize("Ofast"))) static void image(Image *img, uint16_t subX,
} }
} }
__attribute__((optimize("Ofast"))) static void text(const char *str, size_t len, uint16_t x, uint16_t y, uint16_t wall) { static const uint8_t font[] = {
if(wall <= x) wall = 320;
static const uint8_t font[] = {
0x20, 0x31, 0x95, 0x00, 0x21, 0x17, 0x15, 0x5f, 0x22, 0x32, 0x15, 0x2d, 0x20, 0x31, 0x95, 0x00, 0x21, 0x17, 0x15, 0x5f, 0x22, 0x32, 0x15, 0x2d,
0x23, 0x47, 0x15, 0xaa, 0xaf, 0x5f, 0x05, 0x24, 0x48, 0x15, 0x5e, 0x65, 0x23, 0x47, 0x15, 0xaa, 0xaf, 0x5f, 0x05, 0x24, 0x48, 0x15, 0x5e, 0x65,
0xcc, 0x47, 0x25, 0x57, 0x15, 0x6b, 0x1d, 0xc2, 0xb5, 0x06, 0x26, 0x57, 0xcc, 0x47, 0x25, 0x57, 0x15, 0x6b, 0x1d, 0xc2, 0xb5, 0x06, 0x26, 0x57,
@ -183,9 +180,9 @@ __attribute__((optimize("Ofast"))) static void text(const char *str, size_t len,
0x79, 0x47, 0x35, 0xa9, 0x4a, 0x44, 0x03, 0x7a, 0x45, 0x35, 0x4f, 0x12, 0x79, 0x47, 0x35, 0xa9, 0x4a, 0x44, 0x03, 0x7a, 0x45, 0x35, 0x4f, 0x12,
0x0f, 0x7b, 0x39, 0x15, 0x94, 0x14, 0x49, 0x04, 0x7c, 0x18, 0x15, 0xff, 0x0f, 0x7b, 0x39, 0x15, 0x94, 0x14, 0x49, 0x04, 0x7c, 0x18, 0x15, 0xff,
0x7d, 0x39, 0x15, 0x91, 0x44, 0x49, 0x01, 0x7e, 0x52, 0x45, 0x36, 0x01 0x7d, 0x39, 0x15, 0x91, 0x44, 0x49, 0x01, 0x7e, 0x52, 0x45, 0x36, 0x01
}; };
const uint8_t *find(char c) { const uint8_t *find(char c) {
const uint8_t *a = font; const uint8_t *a = font;
while(a - font < sizeof(font)) { while(a - font < sizeof(font)) {
if(*a == c) { if(*a == c) {
@ -195,17 +192,49 @@ __attribute__((optimize("Ofast"))) static void text(const char *str, size_t len,
} }
} }
return NULL; return NULL;
}
__attribute__((optimize("Ofast"))) static void line_extent(const char **strp, size_t len, size_t wall, uint16_t *w, uint16_t *h) {
*w = 0;
*h = 13;
const char *str = *strp;
while(len--) {
if(*str == 10) {
str++;
*strp = str;
return;
} }
const uint8_t *data = find(*(str++));
if(data == NULL) continue;
uint8_t width = data[2] & 0x0F;
if(*w + width >= wall) {
if(*w != 0) {
str--;
}
*strp = str;
return;
}
*w += width;
}
*strp = str;
}
__attribute__((optimize("Ofast"))) static void text_line(const char *str, size_t len, uint16_t x, uint16_t y, uint16_t wall) {
if(wall <= x) wall = 320;
uint16_t startX = x; uint16_t startX = x;
int col = colorFunc(0, 0); int col = colorFunc(0, 0);
while(len--) { while(len--) {
if(*str == 10) { if(*str == 10) {
str++; return;
x = startX;
y += 13;
continue;
} }
const uint8_t *data = find(*(str++)); const uint8_t *data = find(*(str++));
@ -216,8 +245,8 @@ __attribute__((optimize("Ofast"))) static void text(const char *str, size_t len,
uint8_t width = data[2] & 0x0F; uint8_t width = data[2] & 0x0F;
if(x + width >= wall) { if(x + width >= wall) {
x = startX;
y += 13; y += 13;
return;
} }
for(int ix = 0; ix < (data[1] >> 4); ix++) { for(int ix = 0; ix < (data[1] >> 4); ix++) {
@ -234,6 +263,53 @@ __attribute__((optimize("Ofast"))) static void text(const char *str, size_t len,
} }
} }
__attribute__((optimize("Ofast"))) static void text_extent(const char *str, size_t len, size_t wall, uint16_t *w, uint16_t *h) {
*w = 0;
*h = 0;
const char *str2 = str;
while(len) {
uint16_t lineWidth = 0, lineHeight = 0;
line_extent(&str2, len, wall, &lineWidth, &lineHeight);
len = str + len - str2;
if(*w < lineWidth) {
*w = lineWidth;
}
*h += lineHeight;
}
}
__attribute__((optimize("Ofast"))) static void text(const char *str, size_t len, uint16_t x, uint16_t y, uint16_t wall, uint8_t align) {
if(wall <= x) wall = 320;
uint16_t lineW, lineH;
while(len) {
const char *lineEnd = str;
line_extent(&lineEnd, len, wall, &lineW, &lineH);
if(align == LUMA_VID_TEXT_ALIGN_LEFT) {
text_line(str, len, x, y, wall);
} else if(align == LUMA_VID_TEXT_ALIGN_CENTER) {
text_line(str, len, (wall + x) / 2 - lineW / 2, y, wall);
} else if(align == LUMA_VID_TEXT_ALIGN_RIGHT) {
text_line(str, len, wall - lineW, y, wall);
}
if(lineEnd == str) {
break;
}
len = str + len - lineEnd;
str = lineEnd;
y += lineH;
}
}
static void compileCommandList(uint8_t *src, uint8_t *dst) { static void compileCommandList(uint8_t *src, uint8_t *dst) {
size_t len = 0; size_t len = 0;
while(1) { while(1) {
@ -410,6 +486,9 @@ static void compileCommandList(uint8_t *src, uint8_t *dst) {
} else if(cmd->op == LUMA_VID_COMMAND_IMAGE_DEL) { } else if(cmd->op == LUMA_VID_COMMAND_IMAGE_DEL) {
src += sizeof(cmd->imageDel); src += sizeof(cmd->imageDel);
} else if(cmd->op == LUMA_VID_COMMAND_TEXT) { } else if(cmd->op == LUMA_VID_COMMAND_TEXT) {
dst[len++] = 0x68;
*((uint32_t*) &dst[len]) = cmd->text.align;
len += 4;
dst[len++] = 0x68; dst[len++] = 0x68;
*((uint32_t*) &dst[len]) = cmd->text.wall; *((uint32_t*) &dst[len]) = cmd->text.wall;
len += 4; len += 4;
@ -435,7 +514,7 @@ static void compileCommandList(uint8_t *src, uint8_t *dst) {
len += cmd->text.len; len += cmd->text.len;
dst[len++] = 0x83; /* add esp, imm8 */ dst[len++] = 0x83; /* add esp, imm8 */
dst[len++] = 0xC4; dst[len++] = 0xC4;
dst[len++] = 0x14; dst[len++] = 0x18;
src += sizeof(cmd->text) + cmd->text.len; src += sizeof(cmd->text) + cmd->text.len;
} else if(cmd->op == LUMA_VID_COMMAND_NEW_COLOR_FLAT) { } else if(cmd->op == LUMA_VID_COMMAND_NEW_COLOR_FLAT) {
MiniCol minicol = ((cmd->colorFlat.r & ~7) << 8) | ((cmd->colorFlat.g & ~3) << 3) | (cmd->colorFlat.b >> 3); MiniCol minicol = ((cmd->colorFlat.r & ~7) << 8) | ((cmd->colorFlat.g & ~3) << 3) | (cmd->colorFlat.b >> 3);
@ -452,6 +531,12 @@ static void compileCommandList(uint8_t *src, uint8_t *dst) {
} }
q_reavg(); q_reavg();
src += sizeof(cmd->colorGrad); src += sizeof(cmd->colorGrad);
} else if(cmd->op == LUMA_VID_COMMAND_TEXT_EXTENT) {
uint16_t w, h;
text_extent(cmd->textExtent.data, cmd->textExtent.len, cmd->textExtent.wall, &w, &h);
cmd->textExtent.w = w;
cmd->textExtent.h = h;
src += sizeof(cmd->textExtent) + cmd->textExtent.len;
} }
} }
} }

View File

@ -10,4 +10,4 @@ mod: $(OBJECTS)
../../build/wm/%.o: %.c ../../build/wm/%.o: %.c
mkdir -p $(@D) mkdir -p $(@D)
i386-elf-gcc -march=i386 -Isrc -Os -pie -nodefaultlibs -nostdlib -nostartfiles -DEEBIE_MEMSET=__builtin_memset -fms-extensions -fomit-frame-pointer -c -o $@ -ffreestanding -mgeneral-regs-only -std=gnu11 -Wall $< i386-elf-gcc -march=i386 -Isrc -Os -pie -nodefaultlibs -nostdlib -nostartfiles -DEEBIE_MEMSET=__builtin_memset -Dmalloc=tiny_malloc -Dcalloc=tiny_calloc -Dfree=tiny_free -Drealloc=tiny_realloc -fms-extensions -fomit-frame-pointer -c -o $@ -ffreestanding -mgeneral-regs-only -std=gnu11 -Wall $<

View File

@ -13,38 +13,6 @@ void ebml_reader_init(EBMLReader *this) {
static uint64_t VARINT_MASKS[] = {0, 0x80L, 0xC000L, 0xE00000L, 0xF0000000L, 0xF800000000L, 0xFC0000000000L, 0xFE000000000000L, 0L}; static uint64_t VARINT_MASKS[] = {0, 0x80L, 0xC000L, 0xE00000L, 0xF0000000L, 0xF800000000L, 0xFC0000000000L, 0xFE000000000000L, 0L};
#include"../../std.h"
static inline void pr(int c) {
asm volatile("outb %%al, $0xE9" :: "a"(c) :);
}
static inline void pri(size_t num) {
char buf[25] = {};
int i = 16;
do {
buf[--i] = num % 10;
num /= 10;
} while(num);
for(; i < 16; i++) {
pr(buf[i] + '0');
}
}
static inline void prs(const Str16 *str) {
for(int i = 0; i < str->len; i++) {
pr(str->data[i]);
}
}
static inline void prcs(const char *str) {
while(*str) {
pr(*str);
str++;
}
}
#define I(x) ((uint64_t)(x)) #define I(x) ((uint64_t)(x))
static int read_varint(const uint8_t *data, size_t length, uint64_t *result) { static int read_varint(const uint8_t *data, size_t length, uint64_t *result) {
if(data[0] & 0x80) { if(data[0] & 0x80) {

View File

@ -8,7 +8,7 @@
#define dynstr16_ends_with(ds16, cstr) (((ds16)->len < sizeof(cstr) - 1) ? 0 : !std_bytecomp(sizeof(cstr) - 1, (cstr), (ds16)->data + (ds16)->len - sizeof(cstr) + 1)) #define dynstr16_ends_with(ds16, cstr) (((ds16)->len < sizeof(cstr) - 1) ? 0 : !std_bytecomp(sizeof(cstr) - 1, (cstr), (ds16)->data + (ds16)->len - sizeof(cstr) + 1))
struct Ctx { /*struct Ctx {
Str16 *cd; Str16 *cd;
size_t cdSize; size_t cdSize;
} ; } ;
@ -190,12 +190,12 @@ static int files_window_back_cmd(void *ud, const DynStr16 *cmdline) {
update_listing(w); update_listing(w);
return 1; return 1;
} }*/
void FilesWindowCreate() { void FilesWindowCreate() {
if(!is_free_space()) return; if(!is_free_space()) return;
struct GList *list = glist_new(0, 0, 0, 0); /*struct GList *list = glist_new(0, 0, 0, 0);
static const char name[] = "File Explorer"; static const char name[] = "File Explorer";
struct GWindow *w = gwindow_new(0, 0, 0, 0, g_dynstr16_new(sizeof(name) - 1, sizeof(name) - 1, name), (struct GObj*) list, 0); struct GWindow *w = gwindow_new(0, 0, 0, 0, g_dynstr16_new(sizeof(name) - 1, sizeof(name) - 1, name), (struct GObj*) list, 0);
@ -215,5 +215,5 @@ void FilesWindowCreate() {
static const char backcmd[] = "back"; static const char backcmd[] = "back";
gwindow_regcmd(w, g_str16_new(sizeof(backcmd) - 1, backcmd), w, files_window_back_cmd); gwindow_regcmd(w, g_str16_new(sizeof(backcmd) - 1, backcmd), w, files_window_back_cmd);
add_window(w); add_window(w);*/
} }

View File

@ -12,6 +12,7 @@
#include"logserver.h" #include"logserver.h"
#include"progdb.h" #include"progdb.h"
#include"io.h" #include"io.h"
#include"k3menu.h"
asm("modentry:\n" asm("modentry:\n"
"mov $stack + 2048, %esp\n" "mov $stack + 2048, %esp\n"
@ -24,37 +25,6 @@ char stack[2048];
void *VidLink; void *VidLink;
void *FSLink; void *FSLink;
static inline void pr(int c) {
asm volatile("outb %%al, $0xE9" :: "a"(c) :);
}
static inline void pri(size_t num) {
char buf[16] = {};
int i = 16;
do {
buf[--i] = num % 10;
num /= 10;
} while(num);
for(; i < 16; i++) {
pr(buf[i] + '0');
}
}
static inline void prs(const Str16 *str) {
for(int i = 0; i < str->len; i++) {
pr(str->data[i]);
}
}
static inline void prcs(const char *str) {
while(*str) {
pr(*str);
str++;
}
}
void initvid(int col) { void initvid(int col) {
static uint8_t logo[] = { static uint8_t logo[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00,
@ -275,241 +245,106 @@ void drawdesk(int x, int y, int w, int h) {
sys_signal_wait(VidLink, NULL); sys_signal_wait(VidLink, NULL);
} }
struct GContainer *ui; struct k3MScreen *ui;
struct k3MTextInput *cmdline;
struct GObj *windowTree; struct WindowTree {
struct WTreeNode *windowTreeRoot; bool split;
struct WTreeNode *windowTreeFocus; union {
struct GWindow gw;
struct GText *cmdline; struct {
struct WindowTree *a;
struct WindowTree *b;
} sub;
};
};
struct WindowTree *windowTree = NULL;
static void focus_next() { static void focus_next() {
if(windowTreeFocus->window) { }
windowTreeFocus->window->focus = 0;
static int dirtyX1 = INT32_MAX;
static int dirtyX2 = INT32_MIN;
static int dirtyY1 = INT32_MAX;
static int dirtyY2 = INT32_MIN;
void dirty(int x1, int y1, int w, int h) {
int x2 = x1 + w;
int y2 = y1 + h;
if(dirtyX1 > x1) {
dirtyX1 = x1;
} }
if(windowTreeFocus->parent) { if(dirtyX2 < x2) {
if(windowTreeFocus->parent->first == windowTreeFocus) { dirtyX2 = x2;
windowTreeFocus = windowTreeFocus->parent->second; }
} else if(windowTreeFocus->parent->second == windowTreeFocus) {
if(windowTreeFocus->parent->parent) { if(dirtyY1 > y1) {
windowTreeFocus = windowTreeFocus->parent->parent->second; dirtyY1 = y1;
}
if(dirtyY2 < y2) {
dirtyY2 = y2;
}
}
static struct WindowTree *find_free_space(struct WindowTree *wt) {
if(wt->split) {
if(!wt->sub.a) {
wt->sub.a = tiny_calloc(1, sizeof(*wt->sub.a));
return wt->sub.a;
} else { } else {
windowTreeFocus = windowTreeRoot; wt = find_free_space(wt->sub.a);
} if(wt) return wt;
while(!windowTreeFocus->window) {
windowTreeFocus = windowTreeFocus->first;
}
}
} }
if(windowTreeFocus->window) { if(!wt->sub.b) {
windowTreeFocus->window->focus = 1; wt->sub.b = tiny_calloc(1, sizeof(*wt->sub.b));
} return wt->sub.b;
}
static KeyReactFunc baseinputonkey;
static void inputonkey(struct GObj *_, struct GKeyEvent ev) {
if(ev.scancode == LK_ENTER) {
struct GText *t = (void*) _;
perform(t->data);
t->data->len = 0;
cmdline->focus ^= 1;
windowTree->focus ^= 1;
dirty_obj(_);
} else { } else {
baseinputonkey(_, ev); wt = find_free_space(wt->sub.b);
if(wt) return wt;
} }
} else if(wt->gw.whole == NULL) {
return wt;
}
return NULL;
} }
static void wtree_render_recur(struct WTreeNode *node) { struct GWindow *add_window(const char *titleText) {
if(node->window) { struct WindowTree *wt = find_free_space(windowTree);
if(node->window->onRender) {
node->window->onRender((struct GObj*) node->window);
}
} else {
if(node->first) wtree_render_recur(node->first);
if(node->second) wtree_render_recur(node->second);
}
}
static void wtree_render(struct GObj *this) {
wtree_render_recur(windowTreeRoot);
}
static void wtree_key(struct GObj *this, struct GKeyEvent ev) {
if(this->focus == 0) return;
if(windowTreeFocus && windowTreeFocus->window && windowTreeFocus->window->onKey) { if(!wt) return NULL;
windowTreeFocus->window->onKey((struct GObj*) windowTreeFocus->window, ev);
}
}
static void wtree_fitter_recur(struct WTreeNode *node, uint16_t x, uint16_t y, uint16_t w, uint16_t h) {
if(node->window) {
node->window->x = x;
node->window->y = y;
node->window->w = w;
node->window->h = h;
node->window->fitter((struct GObj*) node->window);
} else {
if(node->vertical) {
if(node->first) {
wtree_fitter_recur(node->first, x, y, w, h / 2);
}
if(node->second) {
wtree_fitter_recur(node->second, x, y + h / 2, w, h / 2);
}
} else {
if(node->first) {
wtree_fitter_recur(node->first, x, y, w / 2, h);
}
if(node->second) {
wtree_fitter_recur(node->second, x + w / 2, y, w / 2, h);
}
}
}
}
static void wtree_fitter(struct GObj *_) {
wtree_fitter_recur(windowTreeRoot, windowTree->x, windowTree->y, windowTree->w, windowTree->h);
}
static void wtree_destroy_recur(struct WTreeNode *node) {
if(node->window) node->window->destroy((struct GObj*) node->window);
else {
if(node->first) wtree_destroy_recur(node->first);
if(node->second) wtree_destroy_recur(node->second);
}
}
static void wtree_destroy(struct GObj *_) {
wtree_destroy_recur(windowTreeRoot);
tiny_free(_);
}
static void init_ui() {
// Contains window tree and command bar
ui = gcont_new(0, 0, 320, 240, NULL);
// Contains windows std_w8(wt, 0, sizeof(*wt));
windowTree = tiny_calloc(sizeof(*windowTree), 1);
windowTree->onRender = wtree_render;
windowTree->onKey = wtree_key;
windowTree->destroy = wtree_destroy;
windowTree->fitter = wtree_fitter;
windowTree->x = windowTree->y = 0;
windowTree->w = 320;
windowTree->h = 226;
windowTree->focus = 0;
windowTreeRoot = tiny_calloc(sizeof(*windowTreeRoot), 1); struct GWindow *gw = &wt->gw;
windowTreeRoot->vertical = 0;
windowTreeRoot->window = NULL;
windowTreeRoot->parent = NULL;
windowTreeRoot->first = NULL;
windowTreeRoot->second = NULL;
windowTreeFocus = windowTreeRoot;
gcont_add(ui, 0, (struct GObj*) windowTree); gw->whole = k3MObj();
k3MenuSetBounds(gw->whole, 0, 0, 320, 224);
static const char asdf[] = "Enter command, e.g. help"; gw->title = k3MLabel(NULL, 14, titleText);
cmdline = gtext_new(0, 226, 320, 14, g_dynstr16_new(sizeof(asdf) - 1, sizeof(asdf) - 1, asdf), NULL); k3MenuSetBounds(gw->title, 0, 0, 320, 16);
baseinputonkey = cmdline->onKey; k3MAddChild(gw->whole, gw->title);
cmdline->onKey = inputonkey;
cmdline->focus = 1;
gcont_add(ui, 0, (struct GObj*) cmdline); gw->panel = k3MObj();
k3MenuSetBounds(gw->panel, 0, 0, 320, 224);
k3MAddChild(gw->whole, gw->panel);
ui->focus = 1; k3MAddChild(ui, gw->whole);
return gw;
} }
int add_window(struct GWindow *w) {
if(!windowTreeFocus) {
return 0;
}
if(windowTreeFocus && windowTreeFocus->window) {
windowTreeFocus->window->focus = 0;
}
if(!windowTreeFocus->window) {
windowTreeFocus->window = w;
} else {
struct WTreeNode *top = tiny_calloc(sizeof(*top), 1);
struct WTreeNode *second = tiny_calloc(sizeof(*second), 1);
top->vertical = windowTreeFocus->parent ? !windowTreeFocus->parent->vertical : 0;
top->window = NULL;
top->parent = windowTreeFocus->parent;
top->first = windowTreeFocus;
top->second = second;
second->window = w;
second->parent = top;
windowTreeFocus->parent = top;
if(top->parent) {
if(top->parent->first == windowTreeFocus) {
top->parent->first = top;
} else if(top->parent->second == windowTreeFocus) {
top->parent->second = top;
} else {
// wtf
}
} else {
windowTreeRoot = top;
}
windowTreeFocus = second;
}
windowTreeFocus->window->focus = 1;
windowTree->fitter(windowTree);
return 1;
}
int is_free_space() { int is_free_space() {
return 1; return 1;
} }
static void destroy_window() { static void destroy_window() {
if(!windowTreeFocus) return;
if(windowTreeFocus->window) {
windowTreeFocus->window->focus = 0;
windowTreeFocus->window->destroy((struct GObj*) windowTreeFocus->window);
windowTreeFocus->window = NULL;
if(windowTreeFocus->parent) {
struct WTreeNode *parent = windowTreeFocus->parent;
struct WTreeNode *other = NULL;
if(parent->first == windowTreeFocus) {
other = parent->second;
} else if(parent->second == windowTreeFocus) {
other = parent->first;
}
other->parent = parent->parent;
std_copy(parent, other, sizeof(struct WTreeNode));
tiny_free(windowTreeFocus);
windowTreeFocus = parent;
}
}
if(windowTreeFocus->window) {
windowTreeFocus->window->focus = 1;
}
windowTree->fitter(windowTree);
} }
// Next lexicographical permutation of windows
static void permute() { static void permute() {
// TODO. // TODO: Next lexicographical permutation of windows
} }
static size_t path_size(Str16 *p) { static size_t path_size(Str16 *p) {
@ -811,33 +646,63 @@ static void load_programs() {
tiny_free(png); tiny_free(png);
} }
static int dirtyX1 = INT32_MAX; void dirty_obj(struct k3MObj *o) {
static int dirtyX2 = INT32_MIN; dirty(o->x, o->y, o->w, o->h);
static int dirtyY1 = INT32_MAX;
static int dirtyY2 = INT32_MIN;
void dirty(int x1, int y1, int w, int h) {
int x2 = x1 + w;
int y2 = y1 + h;
if(dirtyX1 > x1) {
dirtyX1 = x1;
}
if(dirtyX2 < x2) {
dirtyX2 = x2;
}
if(dirtyY1 > y1) {
dirtyY1 = y1;
}
if(dirtyY2 < y2) {
dirtyY2 = y2;
}
} }
void dirty_obj(struct GObj *o) { bool input_enter(struct k3MEvent *ev, uint8_t *ud) {
dirty(o->x, o->y, o->w, o->h); DynStr16 *ds16 = tiny_malloc(sizeof(*ds16) + strlen(cmdline->txt));
ds16->cap = strlen(cmdline->txt);
ds16->len = ds16->cap;
std_copy(ds16->data, cmdline->txt, ds16->len);
perform(ds16);
tiny_free(ds16);
cmdline->txt[0] = '\0';
return true;
}
static void init_ui() {
windowTree = tiny_calloc(1, sizeof(*windowTree));
ui = k3MScreen();
ui->x = 0;
ui->y = 0;
ui->w = 320;
ui->h = 240;
cmdline = k3MTextInput(NULL, 14, "Enter command...", "");
cmdline->x = 0;
cmdline->y = 226;
cmdline->w = 320;
cmdline->h = 14;
k3MRegisterEventHandler(cmdline, k3M_EVENT_COMPLETE, input_enter, NULL, 0);
k3MAddChild(ui, cmdline);
ui->keyboardFocus = (struct k3MObj*) cmdline;
}
uint32_t scancode_to_codepoint(bool shift, uint8_t scancode) {
uint32_t ret = 0;
if(scancode >= LK_A && scancode <= LK_Z) {
ret = scancode - LK_A + (shift ? 'A' : 'a');
} else if(scancode == LK_SPACE) {
ret = ' ';
} else if(scancode >= LK_0 && scancode <= LK_9) {
ret = scancode - LK_0 + '0';
} else if(scancode == LK_SLASH) {
ret = '/';
} else if(scancode == LK_COMMA) {
ret = ',';
} else if(scancode == LK_PERIOD) {
ret = '.';
}
return ret;
} }
void startc() { void startc() {
@ -877,7 +742,14 @@ void startc() {
drawdesk(0, 0, 320, 240); drawdesk(0, 0, 320, 240);
ui->onRender((struct GObj*) ui); {
struct k3MEvent ev = {
.original = ui,
.target = ui,
.code = k3M_EVENT_DRAW,
};
k3MEventSend(&ev);
}
while(1) { while(1) {
KEvent kev; KEvent kev;
@ -919,7 +791,29 @@ void startc() {
focus_next(); focus_next();
} }
} else { } else {
ui->onKey((struct GObj*) ui, (struct GKeyEvent) {.scancode = keyBuf[keyBufIndex].scancode, .press = keyBuf[keyBufIndex].flag == KEYEV_FLAG_PRESS, .shift = shift, .alt = alt}); struct k3MEvent ev;
ev = (struct k3MEvent) {
.original = (void*) ui,
.target = (void*) ui,
.code = (keyBuf[keyBufIndex].flag == KEYEV_FLAG_PRESS) ? k3M_EVENT_KEY_PRESS : k3M_EVENT_KEY_RELEASE,
.key = { .num = keyBuf[keyBufIndex].scancode },
};
k3MEventSend(&ev);
if(keyBuf[keyBufIndex].flag == KEYEV_FLAG_PRESS) {
uint32_t codepoint = scancode_to_codepoint(shift, keyBuf[keyBufIndex].scancode);
ev = (struct k3MEvent) {
.original = (void*) ui,
.target = (void*) ui,
.code = k3M_EVENT_INPUT,
.input = { .code = codepoint },
};
k3MEventSend(&ev);
}
} }
if(keyBuf[keyBufIndex].scancode == LK_LEFT_SHIFT) { if(keyBuf[keyBufIndex].scancode == LK_LEFT_SHIFT) {
@ -943,8 +837,8 @@ void startc() {
alt &= ~ALT_LEFT; alt &= ~ALT_LEFT;
if(sysNothingElseWasPressed) { if(sysNothingElseWasPressed) {
cmdline->focus ^= 1; //cmdline->focus ^= 1;
windowTree->focus ^= 1; //windowTree->focus ^= 1;
} }
} }
} else if(keyBuf[keyBufIndex].scancode == LK_LEFT_SYS) { } else if(keyBuf[keyBufIndex].scancode == LK_LEFT_SYS) {
@ -968,7 +862,13 @@ void startc() {
dirtyY1 = INT32_MAX; dirtyY1 = INT32_MAX;
dirtyY2 = INT32_MIN; dirtyY2 = INT32_MIN;
} }
ui->onRender((struct GObj*) ui);
struct k3MEvent ev = {
.original = ui,
.target = ui,
.code = k3M_EVENT_DRAW,
};
k3MEventSend(&ev);
} }
memory_barrier(); memory_barrier();

View File

@ -9,37 +9,7 @@
#include"tiny.h" #include"tiny.h"
#include"io.h" #include"io.h"
#include"fileswindow.h" #include"fileswindow.h"
#include"k3menu.h"
static inline void pr(int c) {
asm volatile("outb %%al, $0xE9" :: "a"(c) :);
}
static inline void pri(size_t num) {
char buf[16] = {};
int i = 16;
do {
buf[--i] = num % 10;
num /= 10;
} while(num);
for(; i < 16; i++) {
pr(buf[i] + '0');
}
}
static inline void prs(const Str16 *str) {
for(int i = 0; i < str->len; i++) {
pr(str->data[i]);
}
}
static inline void prcs(const char *str) {
while(*str) {
pr(*str);
str++;
}
}
__attribute__((optimize("Ofast"))) static void b2hex(uint8_t b, char *ret) { __attribute__((optimize("Ofast"))) static void b2hex(uint8_t b, char *ret) {
uint8_t top = b >> 4; uint8_t top = b >> 4;
@ -52,24 +22,32 @@ __attribute__((optimize("Ofast"))) static void b2hex(uint8_t b, char *ret) {
static void show_help_window() { static void show_help_window() {
if(!is_free_space()) return; if(!is_free_space()) return;
static const char txt[] = "Luma's interface is designed around the keyboard. In fact, you are unlikely to find any use for a mouse except in niche cases.\n\nTurn to the command bar below by pressing the System (Sys) key. Start off by exploring Luma's software by entering \"list\" or your filesystem with \"files\".\n\nSys+H and Sys+V split the desktop to fit more windows. Use Sys+Escape to close windows or remove free space. Sys+P moves windows around."; /*static const char txt[] = "Luma's interface is designed around the keyboard. In fact, you are unlikely to find any use for a mouse except in niche cases.\n\nTurn to the command bar below by pressing the System (Sys) key. Start off by exploring Luma's software by entering \"list\" or your filesystem with \"files\".\n\nSys+H and Sys+V split the desktop to fit more windows. Use Sys+Escape to close windows or remove free space. Sys+P moves windows around.";
struct GLabel *l = glabel_new(0, 0, 0, 0, g_dynstr16_new(sizeof(txt) - 1, sizeof(txt) - 1, txt), 1); struct GLabel *l = glabel_new(0, 0, 0, 0, g_dynstr16_new(sizeof(txt) - 1, sizeof(txt) - 1, txt), 1);
static const char name[] = "Welcome to Luma"; static const char name[] = "Welcome to Luma";
struct GWindow *w = gwindow_new(0, 0, 0, 0, g_dynstr16_new(sizeof(name) - 1, sizeof(name) - 1, name), (struct GObj*) l, 0); struct GWindow *w = gwindow_new(0, 0, 0, 0, g_dynstr16_new(sizeof(name) - 1, sizeof(name) - 1, name), (struct GObj*) l, 0);
add_window(w); add_window(w);*/
struct GWindow *gw = add_window("Welcome to Luma");
struct k3MLabel *lbl = k3MLabel(NULL, 14, "Luma's interface is designed around the keyboard. In fact, you are unlikely to find any use for a mouse except in niche cases.\n\nTurn to the command bar below by pressing the System (Sys) key. Start off by exploring Luma's software by entering \"list\" or your filesystem with \"files\".\n\nSys+H and Sys+V split the desktop to fit more windows. Use Sys+Escape to close windows or remove free space. Sys+P moves windows around.");
k3MenuSetBounds(lbl, 0, 20, 320, 204);
k3MAddChild(gw->panel, lbl);
dirty_obj(gw->whole);
} }
static void show_log_window() { static void show_log_window() {
if(!is_free_space()) return; if(!is_free_space()) return;
struct GLabel *l = glabel_new(0, 0, 0, 0, log_get(), 0); /*struct GLabel *l = glabel_new(0, 0, 0, 0, log_get(), 0);
static const char name[] = "System Logs"; static const char name[] = "System Logs";
struct GWindow *w = gwindow_new(0, 0, 0, 0, g_dynstr16_new(sizeof(name) - 1, sizeof(name) - 1, name), (struct GObj*) l, 0); struct GWindow *w = gwindow_new(0, 0, 0, 0, g_dynstr16_new(sizeof(name) - 1, sizeof(name) - 1, name), (struct GObj*) l, 0);
add_window(w); add_window(w);*/
} }
static void e9(const char *buf, size_t len) { static void e9(const char *buf, size_t len) {
@ -301,7 +279,7 @@ void perform(DynStr16 *cmd) {
show_log_window(); show_log_window();
} else if(cmd->len > 2 && cmd->data[0] == 'g' && cmd->data[1] == 'o' && cmd->data[2] == ' ') { } else if(cmd->len > 2 && cmd->data[0] == 'g' && cmd->data[1] == 'o' && cmd->data[2] == ' ') {
attempt_program_launch(cmd->data + 3, cmd->len - 3); attempt_program_launch(cmd->data + 3, cmd->len - 3);
} else if(windowTreeFocus && windowTreeFocus->window) { } /*else if(windowTreeFocus && windowTreeFocus->window) {
uint8_t *space = (uint8_t*) std_bytefind(cmd->len, (char*) cmd->data, ' '); uint8_t *space = (uint8_t*) std_bytefind(cmd->len, (char*) cmd->data, ' ');
size_t end = space ? space - cmd->data : cmd->len; size_t end = space ? space - cmd->data : cmd->len;
@ -318,7 +296,7 @@ void perform(DynStr16 *cmd) {
break; break;
} }
} else { }*/ else {
// Failed. // Failed.
} }
} }

View File

@ -7,7 +7,7 @@
#include"logserver.h" #include"logserver.h"
static void gtext_render(struct GObj *_) { /*static void gtext_render(struct GObj *_) {
struct GText *this = (void*) _; struct GText *this = (void*) _;
LumaVidCommand *cmd = VidLink; LumaVidCommand *cmd = VidLink;
@ -444,7 +444,7 @@ void glist_clear(struct GList *this) {
tiny_free(this->children); tiny_free(this->children);
this->children = NULL; this->children = NULL;
this->cursor = 0; this->cursor = 0;
} }*/
DynStr16 *g_dynstr16_new(uint16_t cap, uint16_t len, const void *data) { DynStr16 *g_dynstr16_new(uint16_t cap, uint16_t len, const void *data) {
DynStr16 *ret = tiny_malloc(sizeof(*ret) + cap); DynStr16 *ret = tiny_malloc(sizeof(*ret) + cap);

View File

@ -2,11 +2,7 @@
#include"../std.h" #include"../std.h"
#include"../ps2/api.h" #include"../ps2/api.h"
#include"k3menu.h"
typedef uint16_t Coord;
struct GObj;
struct GContainer;
#define SHIFT_LEFT 1 #define SHIFT_LEFT 1
#define SHIFT_RIGHT 2 #define SHIFT_RIGHT 2
@ -14,58 +10,6 @@ struct GContainer;
#define ALT_RIGHT 2 #define ALT_RIGHT 2
#define SYS_LEFT 1 #define SYS_LEFT 1
#define SYS_RIGHT 2 #define SYS_RIGHT 2
struct GKeyEvent {
uint8_t scancode;
uint8_t press;
uint8_t shift;
uint8_t alt;
uint8_t sys;
};
typedef void(*RenderFunc)(struct GObj*);
typedef void(*KeyReactFunc)(struct GObj*, struct GKeyEvent);
typedef void(*FitterFunc)(struct GObj*);
typedef void(*DestroyFunc)(struct GObj*);
struct GObj {
RenderFunc onRender;
KeyReactFunc onKey;
DestroyFunc destroy;
FitterFunc fitter;
Coord x, y;
Coord w, h;
uint8_t focus;
void *ud;
};
struct GText {
struct GObj;
DynStr16 *placeholder;
DynStr16 *data;
};
struct GText *gtext_new(Coord x, Coord y, Coord w, Coord h, DynStr16 *placeholder, DynStr16 *str);
typedef uint8_t GContainerChildMeta;
struct GContainerChild {
GContainerChildMeta meta;
struct GObj *obj;
};
struct GContainer {
struct GObj;
size_t childCount;
struct GContainerChild *children;
uint8_t meta;
};
struct GContainer *gcont_new(Coord x, Coord y, Coord w, Coord h, FitterFunc fitter);
int gcont_add(struct GContainer*, GContainerChildMeta, struct GObj*);
void gcont_set(struct GContainer*, size_t index, GContainerChildMeta, struct GObj*);
void gcont_del(struct GContainer*, size_t index);
void gcont_splitter_v(struct GObj*);
void gcont_splitter_h(struct GObj*);
typedef int(*GCMDFunc)(void*, const DynStr16 *line); typedef int(*GCMDFunc)(void*, const DynStr16 *line);
struct Command { struct Command {
@ -78,44 +22,14 @@ struct CommandList {
struct Command *array; struct Command *array;
}; };
struct GWindow { /*struct GWindow {
struct GObj; struct k3MObj;
DynStr16 *name; DynStr16 *name;
struct GObj *child;
size_t owner; size_t owner;
struct CommandList cmds; struct CommandList cmds;
}; };
struct GWindow *gwindow_new(Coord x, Coord y, Coord w, Coord h, DynStr16 *name, struct GObj *child, size_t owner); int gwindow_regcmd(struct GWindow*, Str16 *cmd, void *ud, GCMDFunc handler);*/
int gwindow_regcmd(struct GWindow*, Str16 *cmd, void *ud, GCMDFunc handler);
struct GLabel {
struct GObj;
DynStr16 *data;
int owned;
};
struct GLabel *glabel_new(Coord x, Coord y, Coord w, Coord h, DynStr16 *data, int owned);
struct GListChild {
DynStr16 *text;
void *ud;
uint8_t selected;
};
struct GList {
struct GObj;
size_t childCount;
struct GListChild *children;
size_t cursor;
};
struct GList *glist_new(Coord x, Coord y, Coord w, Coord h);
int glist_add(struct GList*, DynStr16*, void *ud);
void glist_clear(struct GList*);
DynStr16 *g_dynstr16_new(uint16_t cap, uint16_t len, const void *data); DynStr16 *g_dynstr16_new(uint16_t cap, uint16_t len, const void *data);
DynStr16 *g_dynstr16_append(DynStr16*, uint16_t len, const void *data); DynStr16 *g_dynstr16_append(DynStr16*, uint16_t len, const void *data);

View File

@ -5,17 +5,18 @@
extern void *FSLink; extern void *FSLink;
extern void *VidLink; extern void *VidLink;
struct WTreeNode { struct GWindow {
char vertical; struct k3MObj *whole;
struct GWindow *window; struct k3MLabel *title;
struct WTreeNode *parent; struct k3MObj *panel;
struct WTreeNode *first;
struct WTreeNode *second; // k3Menu only supports one "focused" element per k3MScreen,
}; // but we want to save these when people Alt+Tab
extern struct WTreeNode *windowTreeFocus; struct k3MObj *focus;
};
struct GWindow *add_window(const char *title);
int add_window(struct GWindow *w);
int is_free_space(); int is_free_space();
void dirty(int x, int y, int w, int h); void dirty(int x, int y, int w, int h);
void dirty_obj(struct GObj*); void dirty_obj(struct k3MObj*);