JustUI/src/jfkeys.c

239 lines
5.3 KiB
C

#include <justui/jfkeys.h>
#include <justui/jwidget-api.h>
#include <gint/defs/attributes.h>
#include <gint/std/stdlib.h>
#include <gint/std/string.h>
/* Type identified for jfkeys */
static int jfkeys_type_id = -1;
#ifdef FX9860G
jfkeys *jfkeys_create(bopti_image_t const *img, void *parent)
{
if(jfkeys_type_id < 0) return NULL;
jfkeys *f = malloc(sizeof *f);
jwidget_init(&f->widget, jfkeys_type_id, parent);
jfkeys_set(f, img);
return f;
}
void jfkeys_set(jfkeys *f, bopti_image_t const *img)
{
f->img = img;
f->level = 0;
f->widget.update = true;
}
#endif /* FX9860G */
#ifdef FXCG50
jfkeys *jfkeys_create(char const *labels, void *parent)
{
if(jfkeys_type_id < 0) return NULL;
jfkeys *f = malloc(sizeof *f);
jwidget_init(&f->widget, jfkeys_type_id, parent);
jfkeys_set(f, labels);
for(int i = 0; i < 6; i++) f->overrides[i] = NULL;
f->bg_color = C_BLACK;
f->bg_special_color = C_WHITE;
f->text_color = C_WHITE;
f->text_special_color = C_BLACK;
f->font = dfont_default();
return f;
}
void jfkeys_set(jfkeys *f, char const *labels)
{
f->labels = labels;
f->level = 0;
f->widget.update = true;
}
/* get_level(): Find the level inside a function definition */
static char const *get_level(char const *labels, int level)
{
/* Navigate to level */
while(level > 0) {
labels = strchrnul(labels, '|');
labels += (*labels == '|');
level--;
}
return (*labels == 0) ? NULL : labels;
}
/* get_label(): Find a key within a level */
static char const *get_label(char const *level, int key, size_t *len)
{
int current_key = 0;
while(current_key <= key) {
/* We reached the end of the level without finding the key */
if(*level == 0 || *level == '|') return NULL;
/* Next entry */
if(*level == ';') {
current_key++;
level++;
continue;
}
/* Found contents */
if(current_key == key) {
*len = 0;
while(level[*len] != ';' && level[*len] != '|' && level[*len])
(*len)++;
return level;
}
level++;
}
return NULL;
}
#endif /* FXCG50 */
//---
// Polymorphic widget operations
//---
static void jfkeys_poly_csize(void *f0)
{
jfkeys *f = f0;
#ifdef FX9860G
f->widget.w = 128;
f->widget.h = 8;
#endif
#ifdef FXCG50
f->widget.w = 396;
f->widget.h = 17;
#endif
}
static void jfkeys_poly_render(void *f0, int base_x, int y)
{
jfkeys *f = f0;
#ifdef FX9860G
dsubimage(base_x, y, f->img, 0, 9*f->level, f->img->width, 8, DIMAGE_NONE);
#endif
#ifdef FXCG50
font_t const *old_font = dfont(f->font);
char const *level = get_level(f->labels, f->level);
if(!level) return;
for(int position = 0; position < 6; position++) {
size_t length = 0;
char const *text = NULL;
#ifdef FXCG50
text = f->overrides[position];
#endif
if(!text) text = get_label(level, position, &length);
if(!text || (*text != '.' && *text != '/' && *text != '@'
&& *text != '#')) continue;
int x = base_x + 4 + 65 * position;
int w = 63;
int color = (text[0] == '#') ? f->text_special_color : f->text_color;
if(text[0] == '.') {
drect(x, y, x + w - 1, y + 14, f->bg_color);
}
if(text[0] == '@') {
dline(x + 1, y, x + w - 2, y, f->bg_color);
dline(x + 1, y + 14, x + w - 2, y + 14, f->bg_color);
drect(x, y + 1, x + w - 1, y + 13, f->bg_color);
}
if(text[0] == '/') {
dline(x + 1, y, x + w - 2, y, f->bg_color);
drect(x, y + 1, x + w - 1, y + 9, f->bg_color);
dline(x, y + 10, x + w - 2, y + 10, f->bg_color);
dline(x, y + 11, x + w - 3, y + 11, f->bg_color);
dline(x, y + 12, x + w - 4, y + 12, f->bg_color);
dline(x, y + 13, x + w - 5, y + 13, f->bg_color);
dline(x, y + 14, x + w - 6, y + 14, f->bg_color);
}
if(text[0] == '#') {
dline(x + 1, y, x + w - 2, y, f->bg_color);
dline(x + 1, y + 14, x + w - 2, y + 14, f->bg_color);
drect(x, y + 1, x + 1, y + 13, f->bg_color);
drect(x + w - 2, y + 1, x + w - 1, y + 13, f->bg_color);
drect(x + 2, y + 1, x + w - 3, y + 13, f->bg_special_color);
}
dtext_opt(x + (w >> 1), y + 3, color, C_NONE, DTEXT_CENTER, DTEXT_TOP,
text + 1, length - 1);
}
dfont(old_font);
#endif /* FXCG50 */
}
int jfkeys_level(jfkeys *f)
{
return f->level;
}
void jfkeys_set_level(jfkeys *f, int level)
{
if(f->level == level) return;
f->level = level;
f->widget.update = 1;
}
char const *jfkeys_override(GUNUSED jfkeys *keys, GUNUSED int key)
{
#ifdef FXCG50
if(key < 1 || key > 6) return NULL;
return keys->overrides[key - 1];
#endif
return NULL;
}
void jfkeys_set_override(GUNUSED jfkeys *keys, GUNUSED int key,
GUNUSED char const *override)
{
#ifdef FXCG50
if(key < 1 || key > 6) return;
keys->overrides[key - 1] = override;
#endif
}
void jfkeys_set_color(GUNUSED jfkeys *keys, GUNUSED int bg,
GUNUSED int bg_special, GUNUSED int text, GUNUSED int text_special)
{
#ifdef FXCG50
keys->bg_color = bg;
keys->bg_special_color = bg_special;
keys->text_color = text;
keys->text_special_color = text_special;
#endif
}
void jfkeys_set_font(GUNUSED jfkeys *keys, GUNUSED font_t const *font)
{
#ifdef FXCG50
keys->font = font;
#endif
}
/* jfkeys type definition */
static jwidget_poly type_jfkeys = {
.name = "jfkeys",
.csize = jfkeys_poly_csize,
.layout = NULL,
.render = jfkeys_poly_render,
.event = NULL,
.destroy = NULL,
};
/* Type registration */
__attribute__((constructor(1005)))
static void j_register_jfkeys(void)
{
jfkeys_type_id = j_register_widget(&type_jfkeys, "jwidget");
}