Add k3Menu source
This commit is contained in:
parent
93b885cb43
commit
2a6a931894
73
luma/wm/immdraw.h
Normal file
73
luma/wm/immdraw.h
Normal file
@ -0,0 +1,73 @@
|
||||
#pragma once
|
||||
|
||||
#include"../vid/api.h"
|
||||
#include"../sys.h"
|
||||
|
||||
extern void *VidLink;
|
||||
|
||||
static inline void immdraw_font_draw(uint16_t x, uint16_t y, uint16_t w, size_t txtlen, const char *txt, uint8_t align) {
|
||||
LumaVidCommand *cmd = VidLink;
|
||||
|
||||
cmd->op = LUMA_VID_COMMAND_SET_COLOR_FLAT;
|
||||
cmd->colorFlat.r = 0x00;
|
||||
cmd->colorFlat.g = 0x00;
|
||||
cmd->colorFlat.b = 0x00;
|
||||
cmd = (LumaVidCommand*) ((uintptr_t) cmd + sizeof(cmd->colorFlat));
|
||||
|
||||
cmd->op = LUMA_VID_COMMAND_TEXT;
|
||||
cmd->text.x = x;
|
||||
cmd->text.y = y;
|
||||
cmd->text.wall = x + w;
|
||||
cmd->text.align = align;
|
||||
cmd->text.len = txtlen;
|
||||
std_copy(cmd->text.data, txt, txtlen);
|
||||
cmd = (LumaVidCommand*) ((uintptr_t) cmd + sizeof(cmd->text) + txtlen);
|
||||
|
||||
cmd->op = LUMA_VID_COMMAND_END;
|
||||
|
||||
memory_barrier();
|
||||
sys_signal_send(VidLink, -1);
|
||||
sys_signal_wait(VidLink, NULL);
|
||||
}
|
||||
|
||||
static inline void immdraw_fill_rect(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint8_t r, uint8_t g, uint8_t b) {
|
||||
LumaVidCommand *cmd = VidLink;
|
||||
|
||||
cmd->op = LUMA_VID_COMMAND_SET_COLOR_FLAT;
|
||||
cmd->colorFlat.r = r;
|
||||
cmd->colorFlat.g = g;
|
||||
cmd->colorFlat.b = b;
|
||||
cmd = (LumaVidCommand*) ((uintptr_t) cmd + sizeof(cmd->colorFlat));
|
||||
|
||||
cmd->op = LUMA_VID_COMMAND_RECT;
|
||||
cmd->rect.x1 = x;
|
||||
cmd->rect.x2 = x + w - 1;
|
||||
cmd->rect.y1 = y;
|
||||
cmd->rect.y2 = y + h - 1;
|
||||
cmd = (LumaVidCommand*) ((uintptr_t) cmd + sizeof(cmd->rect));
|
||||
|
||||
cmd->op = LUMA_VID_COMMAND_END;
|
||||
|
||||
memory_barrier();
|
||||
sys_signal_send(VidLink, -1);
|
||||
sys_signal_wait(VidLink, NULL);
|
||||
}
|
||||
|
||||
static inline void immdraw_text_extent(size_t txtlen, const uint8_t *txt, size_t wall, uint16_t *w, uint16_t *h) {
|
||||
LumaVidCommand *cmd = VidLink;
|
||||
|
||||
cmd->op = LUMA_VID_COMMAND_TEXT_EXTENT;
|
||||
cmd->textExtent.wall = wall;
|
||||
cmd->textExtent.len = txtlen;
|
||||
std_copy(cmd->textExtent.data, txt, txtlen);
|
||||
cmd = (LumaVidCommand*) ((uintptr_t) cmd + sizeof(cmd->textExtent) + txtlen);
|
||||
|
||||
cmd->op = LUMA_VID_COMMAND_END;
|
||||
|
||||
memory_barrier();
|
||||
sys_signal_send(VidLink, -1);
|
||||
sys_signal_wait(VidLink, NULL);
|
||||
|
||||
*w = cmd->textExtent.w;
|
||||
*h = cmd->textExtent.h;
|
||||
}
|
373
luma/wm/k3menu.c
Normal file
373
luma/wm/k3menu.c
Normal file
@ -0,0 +1,373 @@
|
||||
#include"k3menu.h"
|
||||
|
||||
#include"immdraw.h"
|
||||
#include"../ps2/api.h"
|
||||
#include"tiny.h"
|
||||
#define memset __builtin_memset
|
||||
#define memcpy __builtin_memcpy
|
||||
|
||||
void k3MenuSetBounds_(struct k3MObj *this, int16_t x, int16_t y, int16_t w, int16_t h) {
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
this->w = w;
|
||||
this->h = h;
|
||||
}
|
||||
|
||||
static bool event_send_nonrecur(struct k3MEvent *ev) {
|
||||
bool handled = false;
|
||||
for(size_t i = 0; i < ev->target->handlerCount; i++) {
|
||||
struct k3MEventHandler *h = &ev->target->handlers[i];
|
||||
|
||||
if(h->code == ev->code || h->code == k3M_EVENT_ALL) {
|
||||
if(h->callback(ev, h->ud)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
int k3MRegisterEventHandler_(struct k3MObj *obj, uint16_t evcode, k3MEventHandlerFunc callback, uint8_t *ud, size_t udSize) {
|
||||
if(ud && udSize > k3M_USERDATA_SIZE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
obj->handlers = realloc(obj->handlers, sizeof(*obj->handlers) * ++obj->handlerCount);
|
||||
|
||||
obj->handlers[obj->handlerCount - 1].code = evcode;
|
||||
obj->handlers[obj->handlerCount - 1].callback = callback;
|
||||
if(ud) {
|
||||
memcpy(obj->handlers[obj->handlerCount - 1].ud, ud, udSize);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool k3MEventSend(struct k3MEvent *ev) {
|
||||
while(!event_send_nonrecur(ev)) {
|
||||
if(ev->kind == k3M_EVENTKIND_DIRECT) {
|
||||
return false;
|
||||
} else if(ev->kind == k3M_EVENTKIND_BUBBLE) {
|
||||
ev->target = ev->target->parent;
|
||||
|
||||
if(ev->target == ev->original || !ev->target) {
|
||||
return false;
|
||||
}
|
||||
} else if(ev->kind == k3M_EVENTKIND_CAPTURE) {
|
||||
struct k3MObj *parent = ev->target;
|
||||
|
||||
for(size_t i = 0; i < parent->childCount; i++) {
|
||||
if(!parent->children[i]->invisible) {
|
||||
ev->target = parent->children[i];
|
||||
|
||||
if(k3MEventSend(ev)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void obj_draw(struct k3MObj *this) {
|
||||
struct k3MProperty *borderRadiusProp = k3MFindProperty(this, k3M_PROP_BORDER_RADIUS, false);
|
||||
//float borderRadius = borderRadiusProp ? borderRadiusProp->si[0] : 0;
|
||||
|
||||
struct k3MProperty *bgColorProp = k3MFindProperty(this, k3M_PROP_BG_COLOR, false);
|
||||
|
||||
uint8_t r = 0, g = 0, b = 0, a = 0;
|
||||
if(bgColorProp) {
|
||||
r = bgColorProp->si[0];
|
||||
g = bgColorProp->si[1];
|
||||
b = bgColorProp->si[2];
|
||||
a = bgColorProp->si[3];
|
||||
}
|
||||
|
||||
if(a != 0) {
|
||||
immdraw_fill_rect(this->x, this->y, this->w, this->h, r, g, b);
|
||||
}
|
||||
}
|
||||
|
||||
static bool label_draw(struct k3MEvent *ev, uint8_t *ud) {
|
||||
struct k3MLabel *this = (void*) ev->target;
|
||||
|
||||
obj_draw((void*) this);
|
||||
|
||||
if(this->txt) {
|
||||
immdraw_font_draw(this->x, this->y, this->w, strlen(this->txt), this->txt, LUMA_VID_TEXT_ALIGN_CENTER);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
struct k3MLabel *k3MLabel(struct k3Font *font, uint32_t sz, const char *txt) {
|
||||
struct k3MLabel *ret = calloc(1, sizeof(*ret));
|
||||
ret->font = font;
|
||||
ret->sz = sz;
|
||||
ret->txt = txt;
|
||||
|
||||
k3MRegisterEventHandler(ret, k3M_EVENT_DRAW, label_draw, NULL, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int k3MRemoveChild(struct k3MObj *parent, struct k3MObj *child) {
|
||||
for(size_t i = 0; i < parent->childCount; i++) {
|
||||
if(parent->children[i] == child) {
|
||||
memcpy(&parent->children[i], &parent->children[i + 1], sizeof(*parent->children) * (parent->childCount - i - 1));
|
||||
|
||||
parent->childCount--;
|
||||
|
||||
child->parent = NULL;
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void k3MAddChild(struct k3MObj *parent, struct k3MObj *child) {
|
||||
if(child->parent) {
|
||||
k3MRemoveChild(child->parent, child);
|
||||
}
|
||||
|
||||
parent->children = realloc(parent->children, sizeof(*parent->children) * (++parent->childCount));
|
||||
parent->children[parent->childCount - 1] = child;
|
||||
|
||||
child->parent = parent;
|
||||
|
||||
if(parent->layout) {
|
||||
parent->layout(parent);
|
||||
}
|
||||
}
|
||||
|
||||
void k3MOverrideProperty(struct k3MObj *obj, struct k3MProperty n) {
|
||||
struct k3MProperty *o = k3MFindProperty(obj, n.type, true);
|
||||
|
||||
if(!o) {
|
||||
obj->properties = realloc(obj->properties, ++obj->propertyCount * sizeof(*obj->properties));
|
||||
o = &obj->properties[obj->propertyCount - 1];
|
||||
}
|
||||
|
||||
memcpy(o, &n, sizeof(n));
|
||||
}
|
||||
|
||||
struct k3MProperty *k3MFindProperty(struct k3MObj *obj, enum k3MPropertyType t, bool direct) {
|
||||
for(size_t i = 0; i < obj->propertyCount; i++) {
|
||||
if(obj->properties[i].type == t) {
|
||||
return &obj->properties[i];
|
||||
}
|
||||
}
|
||||
if(direct || !obj->parent) {
|
||||
return NULL;
|
||||
}
|
||||
return k3MFindProperty(obj->parent, t, direct);
|
||||
}
|
||||
|
||||
static bool screen_ev(struct k3MEvent *ev, uint8_t *ud) {
|
||||
struct k3MScreen *this = (void*) ev->target;
|
||||
|
||||
if(ev->code == k3M_EVENT_MOUSE_PRESS || ev->code == k3M_EVENT_MOUSE_RELEASE || ev->code == k3M_EVENT_MOUSE_MOTION) {
|
||||
struct k3MObj *innermost = (void*) this;
|
||||
|
||||
while(innermost->childCount != 0) {
|
||||
|
||||
bool foundInner = false;
|
||||
|
||||
for(intmax_t i = innermost->childCount - 1; i >= 0; i--) {
|
||||
|
||||
struct k3MObj *child = innermost->children[i];
|
||||
|
||||
if(!child->invisible && ev->mouse.x >= child->x && ev->mouse.x < child->x + child->w && ev->mouse.y >= child->y && ev->mouse.y < child->y + child->h) {
|
||||
|
||||
innermost = child;
|
||||
foundInner = true;
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(!foundInner) {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(innermost != this->lastHover) {
|
||||
this->lastHover->hovered = false;
|
||||
innermost->hovered = true;
|
||||
this->lastHover = innermost;
|
||||
}
|
||||
|
||||
if(innermost != (void*) this) {
|
||||
|
||||
if(ev->code == k3M_EVENT_MOUSE_PRESS) {
|
||||
this->keyboardFocus = innermost;
|
||||
}
|
||||
|
||||
ev->kind = k3M_EVENTKIND_BUBBLE;
|
||||
ev->target = innermost;
|
||||
k3MEventSend(ev);
|
||||
|
||||
if(ev->code == k3M_EVENT_MOUSE_RELEASE) {
|
||||
ev->code = k3M_EVENT_MOUSE_CLICK;
|
||||
|
||||
ev->kind = k3M_EVENTKIND_DIRECT;
|
||||
ev->target = innermost;
|
||||
k3MEventSend(ev);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
} else if(ev->code == k3M_EVENT_KEY_PRESS || ev->code == k3M_EVENT_KEY_RELEASE || ev->code == k3M_EVENT_INPUT) {
|
||||
if(this->keyboardFocus) {
|
||||
ev->kind = k3M_EVENTKIND_BUBBLE;
|
||||
ev->target = (void*) this->keyboardFocus;
|
||||
asm volatile("xchg %%bx, %%bx":::);
|
||||
k3MEventSend(ev);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
ev->kind = k3M_EVENTKIND_CAPTURE;
|
||||
for(intmax_t i = this->childCount; i --> 0;) {
|
||||
if(!this->children[i]->invisible) {
|
||||
ev->target = this->children[i];
|
||||
if(k3MEventSend(ev)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
struct k3MScreen *k3MScreen() {
|
||||
struct k3MScreen *ret = calloc(1, sizeof(*ret));
|
||||
|
||||
ret->lastHover = (void*) ret;
|
||||
|
||||
k3MRegisterEventHandler(ret, k3M_EVENT_ALL, screen_ev, NULL, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool textbutton_draw(struct k3MEvent *ev, uint8_t *ud) {
|
||||
struct k3MTextButton *this = (void*) ev->target;
|
||||
|
||||
obj_draw((void*) this);
|
||||
|
||||
if(this->txt) {
|
||||
//struct k3RectF txtsz;
|
||||
//k3FontSz(this->font, this->sz, this->txt, &txtsz);
|
||||
|
||||
//k3FontDraw(this->font, this->x + this->w / 2 - txtsz.w / 2, this->y, this->sz, this->txt, (vec4) {
|
||||
// 1 - 0.8 * this->disabled, 1 - 0.8 * this->disabled, 1 - 0.8 * this->disabled, 1});
|
||||
|
||||
int top = 1, right = 1, bottom = 1, left = 1;
|
||||
|
||||
struct k3MProperty *marginProp = k3MFindProperty(this, k3M_PROP_MARGIN, false);
|
||||
if(marginProp) {
|
||||
top = marginProp->si[0];
|
||||
right = marginProp->si[1];
|
||||
bottom = marginProp->si[2];
|
||||
left = marginProp->si[3];
|
||||
}
|
||||
|
||||
immdraw_font_draw(this->x + top, this->y + left, this->w - left - right, strlen(this->txt), this->txt, LUMA_VID_TEXT_ALIGN_CENTER);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
struct k3MTextButton *k3MTextButton(struct k3Font *font, uint32_t sz, const char *txt) {
|
||||
struct k3MTextButton *ret = calloc(1, sizeof(*ret));
|
||||
|
||||
ret->font = font;
|
||||
ret->sz = sz;
|
||||
ret->txt = txt;
|
||||
|
||||
k3MRegisterEventHandler(ret, k3M_EVENT_DRAW, textbutton_draw, NULL, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool textinput_draw(struct k3MEvent *ev, uint8_t *ud) {
|
||||
struct k3MTextInput *this = (void*) ev->target;
|
||||
|
||||
obj_draw((void*) this);
|
||||
|
||||
if(this->txt) {
|
||||
int isPlaceholder = strlen(this->txt) == 0;
|
||||
const char *txt = isPlaceholder ? this->placeholder : this->txt;
|
||||
|
||||
//struct k3RectF txtsz;
|
||||
//immdraw_font_getsize(this->font, this->sz, txt, &txtsz);
|
||||
|
||||
immdraw_font_draw(this->x + 2, this->y + 2, this->w, strlen(txt), txt, LUMA_VID_TEXT_ALIGN_LEFT);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
static bool textinput_key(struct k3MEvent *ev, uint8_t *ud) {
|
||||
struct k3MTextInput *this = (void*) ev->target;
|
||||
|
||||
if(ev->key.num == LK_BACKSPACE && ev->code != k3M_EVENT_KEY_RELEASE) {
|
||||
char *last = k3UTF8LastCodepointZ(this->txt);
|
||||
if(last) {
|
||||
*last = 0;
|
||||
}
|
||||
} else if(ev->key.num == LK_ENTER && ev->code == k3M_EVENT_KEY_PRESS) {
|
||||
struct k3MEvent newev = {
|
||||
.code = k3M_EVENT_COMPLETE,
|
||||
.kind = k3M_EVENTKIND_DIRECT,
|
||||
|
||||
.original = (void*) this,
|
||||
.target = (void*) this,
|
||||
};
|
||||
|
||||
k3MEventSend(&newev);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
static bool textinput_char(struct k3MEvent *ev, uint8_t *ud) {
|
||||
struct k3MTextInput *this = (void*) ev->target;
|
||||
|
||||
size_t len = strlen(this->txt);
|
||||
|
||||
this->txt = realloc(this->txt, len + 5);
|
||||
len += k3UTF8Encode(ev->input.code, this->txt + len);
|
||||
this->txt[len] = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
struct k3MTextInput *k3MTextInput(struct k3Font *font, uint32_t sz, const char *placeholder, const char *txt) {
|
||||
struct k3MTextInput *ret = calloc(1, sizeof(*ret));
|
||||
|
||||
ret->font = font;
|
||||
ret->sz = sz;
|
||||
ret->placeholder = placeholder ? placeholder : "";
|
||||
ret->txt = strdup(txt ? txt : "");
|
||||
|
||||
k3MRegisterEventHandler(ret, k3M_EVENT_DRAW, textinput_draw, NULL, 0);
|
||||
k3MRegisterEventHandler(ret, k3M_EVENT_KEY_PRESS, textinput_key, NULL, 0);
|
||||
k3MRegisterEventHandler(ret, k3M_EVENT_KEY_RELEASE, textinput_key, NULL, 0);
|
||||
k3MRegisterEventHandler(ret, k3M_EVENT_INPUT, textinput_char, NULL, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct k3MObj *k3MObj() {
|
||||
struct k3MObj *ret = calloc(1, sizeof(*ret));
|
||||
return ret;
|
||||
}
|
207
luma/wm/k3menu.h
Normal file
207
luma/wm/k3menu.h
Normal file
@ -0,0 +1,207 @@
|
||||
#pragma once
|
||||
|
||||
#include<stdint.h>
|
||||
#include<stdbool.h>
|
||||
#include<stddef.h>
|
||||
#include"tiny.h"
|
||||
|
||||
struct k3Font;
|
||||
struct k3MObj;
|
||||
|
||||
#define k3M_EVENT_MOUSE_ENTER 0
|
||||
#define k3M_EVENT_MOUSE_MOTION 1
|
||||
#define k3M_EVENT_MOUSE_LEAVE 2
|
||||
#define k3M_EVENT_MOUSE_PRESS 3
|
||||
#define k3M_EVENT_MOUSE_RELEASE 4
|
||||
#define k3M_EVENT_MOUSE_CLICK 5
|
||||
#define k3M_EVENT_KEY_PRESS 6
|
||||
#define k3M_EVENT_KEY_RELEASE 7
|
||||
#define k3M_EVENT_INPUT 8
|
||||
#define k3M_EVENT_DRAW 9
|
||||
#define k3M_EVENT_COMPLETE 10
|
||||
#define k3M_EVENT_ALL 11
|
||||
|
||||
#define k3M_MOUSE_BUTTON_0 0
|
||||
#define k3M_MOUSE_BUTTON_1 1
|
||||
#define k3M_MOUSE_BUTTON_2 2
|
||||
|
||||
#define k3M_EVENTKIND_DIRECT 0
|
||||
#define k3M_EVENTKIND_CAPTURE 1
|
||||
#define k3M_EVENTKIND_BUBBLE 2
|
||||
|
||||
#define k3M_USERDATA_SIZE 16
|
||||
|
||||
#include"../std.h"
|
||||
|
||||
struct k3MEvent {
|
||||
uint16_t code;
|
||||
|
||||
uint8_t kind;
|
||||
|
||||
struct k3MObj *original;
|
||||
struct k3MObj *target;
|
||||
|
||||
union {
|
||||
struct {
|
||||
int button;
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
} mouse;
|
||||
struct {
|
||||
uint32_t num;
|
||||
} key;
|
||||
struct {
|
||||
uint32_t code;
|
||||
} input;
|
||||
};
|
||||
};
|
||||
|
||||
typedef bool(*k3MEventHandlerFunc)(struct k3MEvent*, uint8_t *ud);
|
||||
|
||||
typedef struct k3MEventHandler {
|
||||
uint8_t ud[k3M_USERDATA_SIZE];
|
||||
k3MEventHandlerFunc callback;
|
||||
uint16_t code;
|
||||
} k3MEventHandler;
|
||||
|
||||
enum k3MPropertyType {
|
||||
k3M_PROP_BG_COLOR,
|
||||
k3M_PROP_BORDER_RADIUS,
|
||||
k3M_PROP_MARGIN,
|
||||
};
|
||||
struct k3MProperty {
|
||||
enum k3MPropertyType type;
|
||||
union {
|
||||
intmax_t si[4];
|
||||
void *ptr;
|
||||
uint8_t buf[32];
|
||||
};
|
||||
};
|
||||
|
||||
typedef void(*k3MLayout)(struct k3MObj*);
|
||||
|
||||
struct k3MObj {
|
||||
struct k3MObj *parent;
|
||||
|
||||
k3MLayout layout;
|
||||
|
||||
size_t childCount;
|
||||
struct k3MObj **children;
|
||||
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
int16_t w;
|
||||
int16_t h;
|
||||
|
||||
bool invisible, hovered, disabled;
|
||||
|
||||
k3MEventHandler *handlers;
|
||||
size_t handlerCount;
|
||||
|
||||
struct k3MProperty *properties;
|
||||
size_t propertyCount;
|
||||
};
|
||||
struct k3MObj *k3MObj();
|
||||
|
||||
#define k3MenuSetBounds(a, x, y, w, h) k3MenuSetBounds_((struct k3MObj*) (a), (x), (y), (w), (h))
|
||||
void k3MenuSetBounds_(struct k3MObj *this, int16_t x, int16_t y, int16_t w, int16_t h);
|
||||
|
||||
#define k3MRegisterEventHandler(a, c, cb, ud, udsz) k3MRegisterEventHandler_((struct k3MObj*) (a), (c), (cb), (ud), (udsz))
|
||||
int k3MRegisterEventHandler_(struct k3MObj *obj, uint16_t evcode, k3MEventHandlerFunc callback, uint8_t *ud, size_t udSize);
|
||||
|
||||
bool k3MEventSend(struct k3MEvent *ev);
|
||||
|
||||
int k3MRemoveChild(struct k3MObj *parent, struct k3MObj *child);
|
||||
void k3MAddChild(struct k3MObj *parent, struct k3MObj *child);
|
||||
|
||||
void k3MOverrideProperty(struct k3MObj *obj, struct k3MProperty);
|
||||
struct k3MProperty *k3MFindProperty(struct k3MObj *obj, enum k3MPropertyType, bool direct);
|
||||
|
||||
struct k3MLabel {
|
||||
struct k3MObj;
|
||||
|
||||
struct k3Font *font;
|
||||
uint32_t sz;
|
||||
char *txt;
|
||||
};
|
||||
struct k3MLabel *k3MLabel(struct k3Font *font, uint32_t millipts, const char *txt);
|
||||
|
||||
struct k3MScreen {
|
||||
struct k3MObj;
|
||||
|
||||
struct k3MObj *keyboardFocus;
|
||||
struct k3MObj *lastHover;
|
||||
};
|
||||
struct k3MScreen *k3MScreen();
|
||||
|
||||
struct k3MTextButton {
|
||||
struct k3MObj;
|
||||
|
||||
struct k3Font *font;
|
||||
uint32_t sz;
|
||||
char *txt;
|
||||
};
|
||||
struct k3MTextButton *k3MTextButton(struct k3Font *font, uint32_t millipts, const char *txt);
|
||||
|
||||
struct k3MTextInput {
|
||||
struct k3MObj;
|
||||
|
||||
struct k3Font *font;
|
||||
uint32_t sz;
|
||||
|
||||
char *placeholder;
|
||||
|
||||
char *txt;
|
||||
};
|
||||
struct k3MTextInput *k3MTextInput(struct k3Font *font, uint32_t millipts, const char *placeholder, const char *txt);
|
||||
|
||||
static inline int k3UTF8Encode(uint32_t cp, uint8_t ret[static 4]) {
|
||||
if(cp < 0x80) {
|
||||
ret[0] = cp;
|
||||
return 1;
|
||||
} else if(cp < 0x800) {
|
||||
ret[0] = 192 | (cp >> 6);
|
||||
ret[1] = 128 | (cp & 63);
|
||||
return 2;
|
||||
} else if(cp < 0x10000) {
|
||||
ret[0] = 224 | (cp >> 12);
|
||||
ret[1] = 128 | ((cp >> 6) & 63);
|
||||
ret[2] = 128 | (cp & 63);
|
||||
return 3;
|
||||
} else if(cp < 0x110000) {
|
||||
ret[0] = 240 | (cp >> 18);
|
||||
ret[1] = 128 | ((cp >> 12) & 63);
|
||||
ret[2] = 128 | ((cp >> 6) & 63);
|
||||
ret[3] = 128 | (cp & 63);
|
||||
return 4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline size_t strlen(const char *str) {
|
||||
size_t sz = 0;
|
||||
while(*str) {
|
||||
sz++;
|
||||
str++;
|
||||
}
|
||||
return sz;
|
||||
}
|
||||
|
||||
static inline const char *k3UTF8LastCodepointZ(const char *txt) {
|
||||
size_t len = strlen(txt);
|
||||
while(len--) {
|
||||
if((txt[len] & 0xC0) != 0x80) {
|
||||
return &txt[len];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline char *strdup(const char *s) {
|
||||
size_t len = strlen(s);
|
||||
char *d = tiny_malloc(len + 1);
|
||||
d[len] = '\0';
|
||||
__builtin_memcpy(d, s, len);
|
||||
return d;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user