mirror of https://git.mastrix.org/lda/Mastrix
A lot of stuff...
This commit is contained in:
parent
07ae5a8566
commit
55395ec2cf
|
@ -11,6 +11,7 @@ include(Fxconv)
|
|||
find_package(Gint 2.9 REQUIRED)
|
||||
find_package(JustUI 1.3.0 REQUIRED)
|
||||
find_package(LibImg 2.1 REQUIRED)
|
||||
find_package(cPNG 1.5.30 REQUIRED)
|
||||
|
||||
AUX_SOURCE_DIRECTORY(src SOURCES)
|
||||
# Shared assets, fx-9860G-only assets and fx-CG-50-only assets
|
||||
|
@ -31,6 +32,7 @@ set(ASSETS_cg
|
|||
assets-cg/file.png
|
||||
assets-cg/tweak.png
|
||||
assets-cg/tbold.png
|
||||
assets-cg/bouncer.png
|
||||
assets-cg/mastrix-print.png
|
||||
)
|
||||
|
||||
|
@ -38,9 +40,10 @@ fxconv_declare_assets(${ASSETS} ${ASSETS_fx} ${ASSETS_cg} WITH_METADATA)
|
|||
|
||||
add_executable(mastrix ${SOURCES} ${ASSETS} ${ASSETS_${FXSDK_PLATFORM}})
|
||||
include_directories(src/include)
|
||||
target_compile_options(mastrix PRIVATE -Wall -Wextra -O0 -g)
|
||||
target_compile_options(mastrix PRIVATE -Wall -Wextra -O0 -g -finstrument-functions)
|
||||
target_link_libraries(mastrix Gint::Gint JustUI::JustUI LibImg::LibImg)
|
||||
|
||||
|
||||
if("${FXSDK_PLATFORM_LONG}" STREQUAL fx9860G)
|
||||
# honestly i dont have an fx-9860G to test with.
|
||||
generate_g1a(TARGET mastrix OUTPUT "MyAddin.g1a"
|
||||
|
|
6
TODO
6
TODO
|
@ -1,2 +1,4 @@
|
|||
Bug at 8c215e86, apparently related to jwidget_remove_child, when scrolling up it seems...
|
||||
It happens early on, must be a BAD CHECK.
|
||||
- Commands (and a catalog system)
|
||||
- Save user info to be loaded later
|
||||
- Custom reactions
|
||||
- ????
|
||||
|
|
|
@ -10,6 +10,9 @@ hourglass.png:
|
|||
file.png:
|
||||
type: bopti-image
|
||||
name: fileicon
|
||||
bouncer.png:
|
||||
type: bopti-image
|
||||
name: bouncer
|
||||
|
||||
cc.png:
|
||||
type: font
|
||||
|
@ -25,7 +28,7 @@ tweak.png:
|
|||
tbold.png:
|
||||
type: font
|
||||
charset: print
|
||||
grid.size: 10x21
|
||||
grid.size: 8x18
|
||||
name: terminus_strong
|
||||
|
||||
|
||||
|
|
18
src/array.c
18
src/array.c
|
@ -65,6 +65,24 @@ void utils_array_set(array_t *arr, size_t idx, void *val)
|
|||
|
||||
arr->list[idx] = val;
|
||||
}
|
||||
void utils_array_pop(array_t *arr)
|
||||
{
|
||||
void **newe;
|
||||
if (!arr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (arr->capacity <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Remove the latest element */
|
||||
arr->capacity--;
|
||||
newe = malloc(sizeof(void *) * arr->capacity);
|
||||
memcpy(newe, arr->list, sizeof(void *) * arr->capacity);
|
||||
arr->list = newe;
|
||||
}
|
||||
|
||||
void utils_free_array(array_t *arr)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,198 @@
|
|||
/*#include <utils.h>*/
|
||||
|
||||
#include <gint/display.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#define PI 3.14152
|
||||
|
||||
/* Converts a value to a blurhash */
|
||||
uint8_t table[256] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,62,63,64,0,0,0,0,65,66,67,68,69,0,0,1,2,3,4,5,6,7,8,9,70,71,0,72,0,73,74,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,75,0,76,77,78,0,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,79,80,81,82,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
|
||||
/* Reads a blurhash number */
|
||||
static uint32_t read_number(char *str, size_t n)
|
||||
{
|
||||
uint32_t v = 0;
|
||||
size_t i;
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
char c = str[i];
|
||||
if (!c)
|
||||
{
|
||||
break;
|
||||
}
|
||||
v += table[c];
|
||||
v *= 83;
|
||||
}
|
||||
v /= 83;
|
||||
return v;
|
||||
}
|
||||
|
||||
uint16_t gco(char *coeff, int i, int j, int nx, int ny)
|
||||
{
|
||||
size_t offset;
|
||||
uint16_t v;
|
||||
if (i == 0 && j == 0)
|
||||
{
|
||||
/* It isn't my job to manage the DC */
|
||||
return 0;
|
||||
}
|
||||
offset = ((nx * j + i) * 2) + 2;
|
||||
v = read_number(coeff + offset, 2);
|
||||
return v;
|
||||
}
|
||||
float ch_to_float(uint8_t coeff, uint8_t max)
|
||||
{
|
||||
int s = coeff < 9 ? -1 : 1;
|
||||
float max_float = (max + 1) / 166.0;
|
||||
float coeff_float = s * powf((coeff - 9) / 9.0, 2);
|
||||
|
||||
return coeff_float * max_float;
|
||||
}
|
||||
|
||||
typedef struct rgb {
|
||||
float r, g, b;
|
||||
} rgb_t;
|
||||
|
||||
rgb_t ac_coeff_to_color(uint16_t coeff, uint8_t max)
|
||||
{
|
||||
uint8_t r, g, b;
|
||||
float fr, fg, fb;
|
||||
|
||||
r = (coeff / (19*19)) % 19;
|
||||
g = (coeff / 19 ) % 19;
|
||||
b = (coeff ) % 19;
|
||||
|
||||
fr = ch_to_float(r, max);
|
||||
fg = ch_to_float(g, max);
|
||||
fb = ch_to_float(b, max);
|
||||
|
||||
return (rgb_t) { .r = fr, .g = fg, .b = fb };
|
||||
}
|
||||
/* stolen lol */
|
||||
static inline float to_linear(int value)
|
||||
{
|
||||
float v = (float)value / 255;
|
||||
if(v <= 0.04045) return v / 12.92;
|
||||
else return powf((v + 0.055) / 1.055, 2.4);
|
||||
}
|
||||
static inline int to_srgb(float value)
|
||||
{
|
||||
float v = fmaxf(0, fminf(1, value));
|
||||
if(v <= 0.0031308) return v * 12.92 * 255 + 0.5;
|
||||
else return (1.055 * powf(v, 1 / 2.4) - 0.055) * 255 + 0.5;
|
||||
}
|
||||
|
||||
rgb_t dc_coeff_to_color(uint32_t srgb, uint8_t max)
|
||||
{
|
||||
float fr, fg, fb;
|
||||
|
||||
fr = to_linear(((srgb >> (8 * 2)) & 0xFF));
|
||||
fg = to_linear(((srgb >> (8 * 1)) & 0xFF));
|
||||
fb = to_linear(((srgb >> (8 * 0)) & 0xFF));
|
||||
|
||||
return (rgb_t) { .r = fr, .g = fg, .b = fb };
|
||||
}
|
||||
|
||||
uint16_t *utils_decode_blurhash(char *str, int *ow, int *oh)
|
||||
{
|
||||
uint16_t *buf;
|
||||
rgb_t *coeffs;
|
||||
rgb_t *colors;
|
||||
|
||||
uint8_t component;
|
||||
uint8_t nx, ny;
|
||||
|
||||
uint8_t max_ac;
|
||||
|
||||
size_t x, y;
|
||||
size_t i, j;
|
||||
if (!str)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
component = read_number(str, 1);
|
||||
ny = (component / 9) + 1;
|
||||
nx = (component % 9) + 1;
|
||||
|
||||
if (*ow == 0) *ow = nx;
|
||||
if (*oh == 0) *oh = nx;
|
||||
|
||||
str += 1;
|
||||
|
||||
max_ac = read_number(str, 1);
|
||||
str += 1;
|
||||
|
||||
/* Setup coefficients */
|
||||
coeffs = malloc(nx * ny * sizeof(rgb_t));
|
||||
for (j = 0; j < ny; j++)
|
||||
{
|
||||
for (i = 0; i < nx; i++)
|
||||
{
|
||||
uint16_t c;
|
||||
if (i == 0 && j == 0)
|
||||
{
|
||||
/* DC coeff */
|
||||
coeffs[0] = dc_coeff_to_color(read_number(str, 4), max_ac);
|
||||
continue;
|
||||
}
|
||||
c = gco(str, i, j, nx, ny);
|
||||
coeffs[j * nx + i] = ac_coeff_to_color(c, max_ac);
|
||||
}
|
||||
}
|
||||
|
||||
/* Now, it's math time. */
|
||||
|
||||
colors = malloc((*ow) * (*oh) * sizeof(rgb_t));
|
||||
for (y = 0; y < *oh; y++)
|
||||
{
|
||||
for (x = 0; x < *ow; x++)
|
||||
{
|
||||
size_t i, j;
|
||||
rgb_t rgb = { .r = 0., .g = 0., .b = 0. };
|
||||
/* Comical amount of nesting */
|
||||
for (j = 0; j < ny; j++)
|
||||
{
|
||||
for (i = 0; i < nx; i++)
|
||||
{
|
||||
rgb_t cij = coeffs[j * nx + i];
|
||||
float k = cosf(((float)x * i * PI)/ *ow) * cosf((y * j * PI)/ *oh);
|
||||
rgb.r += cij.r * k;
|
||||
rgb.g += cij.g * k;
|
||||
rgb.b += cij.b * k;
|
||||
}
|
||||
}
|
||||
colors[y * *ow + x] = rgb;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
buf = malloc(nx * ny * sizeof(uint16_t));
|
||||
/* WRITE to buf */
|
||||
for (y = 0; y < *oh; y++)
|
||||
{
|
||||
for (x = 0; x < *ow; x++)
|
||||
{
|
||||
rgb_t c = colors[y * *ow + x];
|
||||
uint8_t cr, cg, cb;
|
||||
|
||||
cr = to_srgb(c.r);
|
||||
cg = to_srgb(c.g);
|
||||
cb = to_srgb(c.b);
|
||||
|
||||
buf[y * *ow + x] = C_RGB(
|
||||
(31 * cr)/255,
|
||||
(31 * cg)/255,
|
||||
(31 * cb)/255
|
||||
);
|
||||
}
|
||||
}
|
||||
free(coeffs);
|
||||
free(colors);
|
||||
return buf;
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
#include <command.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <utils.h>
|
||||
|
||||
command_t *command_parse(char *str)
|
||||
{
|
||||
command_t *ret;
|
||||
char *name, *argstart;
|
||||
|
||||
if (!str)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if (*str != '/')
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* TODO */
|
||||
str++;
|
||||
argstart = str;
|
||||
while (*str != ' ' && *str)
|
||||
{
|
||||
str++;
|
||||
}
|
||||
if (argstart == str)
|
||||
{
|
||||
/* Empty name, give up. */
|
||||
return NULL;
|
||||
}
|
||||
name = malloc((size_t) (str - argstart) + 1);
|
||||
memcpy(name, argstart, (size_t) (str - argstart));
|
||||
name[(size_t) (str - argstart)] = '\0';
|
||||
|
||||
while (*str)
|
||||
{
|
||||
while (*str != ' ' && *str)
|
||||
{
|
||||
str++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
void command_free(command_t *c)
|
||||
{
|
||||
size_t i;
|
||||
if (!c)
|
||||
{
|
||||
return;
|
||||
}
|
||||
free(c->command);
|
||||
for (i = 0; i < utils_array_size(c->arguments); i++)
|
||||
{
|
||||
free(utils_array_get(c->arguments, i));
|
||||
}
|
||||
utils_free_array(c->arguments);
|
||||
free(c);
|
||||
}
|
|
@ -0,0 +1,152 @@
|
|||
/* Debugging */
|
||||
#include <dbg.h>
|
||||
|
||||
#include <gint/drivers/keydev.h>
|
||||
#include <gint/usb-ff-bulk.h>
|
||||
#include <gint/hardware.h>
|
||||
#include <gint/keyboard.h>
|
||||
#include <gint/display.h>
|
||||
#include <gint/gint.h>
|
||||
#include <gint/exc.h>
|
||||
#include <gint/usb.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <info.h>
|
||||
|
||||
volatile static uintptr_t *stacktrace = NULL;
|
||||
volatile static size_t idx = 0;
|
||||
volatile static size_t allocated = 0;
|
||||
|
||||
static const char *dbg_to_str(uint32_t code)
|
||||
{
|
||||
/* Stolen from gint */
|
||||
|
||||
const char *name = "";
|
||||
if(code == 0x040) name = "TLB miss (nonexisting address) on read";
|
||||
if(code == 0x060) name = "TLB miss (nonexisting address) on write";
|
||||
if(code == 0x0e0) name = "Read address error (probably alignment)";
|
||||
if(code == 0x100) name = "Write address error (probably alignment)";
|
||||
if(code == 0x160) name = "Unconditional trap";
|
||||
if(code == 0x180) name = "Illegal instruction";
|
||||
if(code == 0x1a0) name = "Illegal delay slot instruction";
|
||||
|
||||
/* Custom gint codes for convenience */
|
||||
if(code == 0x1020) name = "DMA address error";
|
||||
if(code == 0x1040) name = "Add-in not fully mapped (too large)";
|
||||
if(code == 0x1060) name = "Memory initialization failed (heap)";
|
||||
if(code == 0x1080) name = "Stack overflow during world switch";
|
||||
|
||||
return name;
|
||||
}
|
||||
static void __attribute__((noreturn,no_instrument_function)) dbg_panic(uint32_t code)
|
||||
{
|
||||
uint32_t TEA, TRA;
|
||||
uint32_t PC;
|
||||
uint32_t SGR = 0xffffffff;
|
||||
uint32_t *long_vram;
|
||||
|
||||
const char *name;
|
||||
|
||||
TEA = *(volatile uint32_t *)0xff00000c;
|
||||
TRA = *(volatile uint32_t *)0xff000020 >> 2;
|
||||
|
||||
__asm__("stc spc, %0" : "=r"(PC));
|
||||
|
||||
if(isSH4()) __asm__("stc sgr, %0" : "=r"(SGR));
|
||||
|
||||
name = dbg_to_str(code);
|
||||
|
||||
/* Display to the user */
|
||||
dclear(C_WHITE);
|
||||
dtext(1, 1, C_BLACK, MASTRIX_NAME " has crashed.");
|
||||
/* gint trick */
|
||||
long_vram = (void *)gint_vram;
|
||||
for(int i = 0; i < 198 * 16; i++) long_vram[i] = ~long_vram[i];
|
||||
|
||||
dprint(10, 22, C_BLACK, name);
|
||||
dprint(1, 44, C_BLACK, "PC: %08x", PC);
|
||||
dprint(1, 55, C_BLACK, "TEA: %08x", TEA);
|
||||
dprint(1, 66, C_BLACK, "TRA: %#x", TRA);
|
||||
if (usb_is_open())
|
||||
{
|
||||
dprint(1, 88, C_BLACK, "Sending trace over USB.");
|
||||
}
|
||||
dupdate();
|
||||
|
||||
/* Send trace over USB */
|
||||
if (usb_is_open())
|
||||
{
|
||||
int out = usb_ff_bulk_output();
|
||||
usb_fxlink_header_t header;
|
||||
|
||||
stacktrace[idx++] = (uintptr_t) PC;
|
||||
usb_fxlink_fill_header(
|
||||
&header,
|
||||
"dbg", "crash",
|
||||
idx * sizeof(uintptr_t)
|
||||
);
|
||||
usb_write_sync(out, &header, sizeof(usb_fxlink_header_t), false);
|
||||
usb_write_sync(out, stacktrace, idx * sizeof(uintptr_t), false);
|
||||
usb_commit_sync(out);
|
||||
/* We aren't going to wait for anything here. */
|
||||
}
|
||||
|
||||
|
||||
dbg_end();
|
||||
while (true);
|
||||
}
|
||||
|
||||
void dbg_init(void)
|
||||
{
|
||||
allocated = 4096;
|
||||
stacktrace = malloc(allocated * sizeof(uintptr_t));
|
||||
gint_panic_set(dbg_panic);
|
||||
}
|
||||
void dbg_end(void)
|
||||
{
|
||||
if (!stacktrace)
|
||||
{
|
||||
return;
|
||||
}
|
||||
free((void *) stacktrace);
|
||||
gint_panic_set(NULL);
|
||||
}
|
||||
void *dbg_get(size_t off)
|
||||
{
|
||||
size_t loc = idx - off;
|
||||
if (off > idx)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return (void *) stacktrace[loc];
|
||||
}
|
||||
void __attribute__((no_instrument_function)) __cyg_profile_func_enter(void *this, void *callee)
|
||||
{
|
||||
if (!stacktrace)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (idx >= allocated)
|
||||
{
|
||||
/* TODO: Reallocate */
|
||||
return;
|
||||
}
|
||||
stacktrace[idx++] = (uintptr_t) this;
|
||||
}
|
||||
void __attribute__((no_instrument_function)) __cyg_profile_func_exit(void *this, void *callee)
|
||||
{
|
||||
if (!stacktrace)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (idx <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
stacktrace[--idx] = (uintptr_t) NULL;
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
#include <gint/display.h>
|
||||
#include <gint/image.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
extern bopti_image_t const bouncer;
|
||||
|
||||
void easter_dvd_frame(const char *str)
|
||||
{
|
||||
static int x = -100, y = -100;
|
||||
static int dx = 10, dy = 8;
|
||||
int w = bouncer.width, h = bouncer.height;
|
||||
|
||||
if (x == -100 && y == -100)
|
||||
{
|
||||
x = rand() % DWIDTH;
|
||||
y = rand() % DHEIGHT;
|
||||
}
|
||||
|
||||
x += dx;
|
||||
y += dy;
|
||||
if (x > DWIDTH - w) dx *= -1;
|
||||
if (x < 0) dx *= -1;
|
||||
if (y > DHEIGHT - h) dy *= -1;
|
||||
if (y < 0) dy *= -1;
|
||||
|
||||
dclear(C_BLACK);
|
||||
dtext(1, 1, C_WHITE, str);
|
||||
dimage(x, y, &bouncer);
|
||||
dupdate();
|
||||
}
|
186
src/event_ui.c
186
src/event_ui.c
|
@ -16,37 +16,36 @@ extern bopti_image_t fileicon;
|
|||
extern font_t terminus_weak;
|
||||
extern font_t terminus_strong;
|
||||
|
||||
static void *render_span(void *p, struct DomElement *dom)
|
||||
typedef struct dom_state {
|
||||
bool italic, bold;
|
||||
int bg, fg;
|
||||
} dom_state_t;
|
||||
static void *render_span(void *p, struct DomElement *dom, dom_state_t state)
|
||||
{
|
||||
jlabel *label;
|
||||
|
||||
label = jlabel_create("", p);
|
||||
jlabel_asprintf(label, "%s", dom->textNode);
|
||||
if (state.italic)
|
||||
{
|
||||
jlabel_set_font(label, &terminus_weak);
|
||||
}
|
||||
if (state.bold)
|
||||
{
|
||||
jlabel_set_font(label, &terminus_strong);
|
||||
}
|
||||
if (state.bg != C_NONE)
|
||||
{
|
||||
jwidget_set_background(label, state.bg);
|
||||
}
|
||||
if (state.fg != C_NONE)
|
||||
{
|
||||
jlabel_set_text_color(label, state.fg);
|
||||
}
|
||||
return label;
|
||||
}
|
||||
static void *render_i(void *p, struct DomElement *dom)
|
||||
static jwidget *parse_msg_body_dom(void *p, struct DomElement *dom, dom_state_t s)
|
||||
{
|
||||
jlabel *label;
|
||||
|
||||
label = jlabel_create("", p);
|
||||
jlabel_asprintf(label, "%s", dom->textNode);
|
||||
jlabel_set_font(label, &terminus_weak);
|
||||
return label;
|
||||
}
|
||||
static void *render_strong(void *p, struct DomElement *dom)
|
||||
{
|
||||
jlabel *label;
|
||||
|
||||
label = jlabel_create("", p);
|
||||
jlabel_asprintf(label, "%s", dom->textNode);
|
||||
jlabel_set_font(label, &terminus_strong);
|
||||
return label;
|
||||
}
|
||||
static jwidget *parse_msg_body_html(void *p, char *html)
|
||||
{
|
||||
struct el_t *top;
|
||||
struct DomElement *dom;
|
||||
char *contained, *cpy;
|
||||
size_t i;
|
||||
jwidget *container = jwidget_create(p);
|
||||
jwidget *line;
|
||||
|
@ -57,6 +56,100 @@ static jwidget *parse_msg_body_html(void *p, char *html)
|
|||
jlayout_set_hbox(line)->spacing = 1;
|
||||
jwidget_set_stretch(line, 1, 0, false);
|
||||
|
||||
for (i = 0; i < dom->childnum; i++)
|
||||
{
|
||||
struct DomElement *item = dom->children[i];
|
||||
if (!strcmp(item->tagName, "span"))
|
||||
{
|
||||
render_span(line, item, s);
|
||||
}
|
||||
else if (!strcmp(item->tagName, "u"))
|
||||
{
|
||||
jwidget *box = jwidget_create(line);
|
||||
jwidget *ul;
|
||||
jwidget *l;
|
||||
jlayout_set_vbox(box)->spacing = 1;
|
||||
jwidget_set_stretch(box, 1, 0, false);
|
||||
l = parse_msg_body_dom(box, item, s);
|
||||
ul = jwidget_create(box);
|
||||
jwidget_set_stretch(ul, 1, 0, false); /* TODO: Make ul *work* */
|
||||
jwidget_set_stretch(l, 1, 0, false);
|
||||
jwidget_set_minimum_width(ul, l->w);
|
||||
log_text("%s: size=%d", __func__, l->w);
|
||||
jwidget_set_minimum_height(ul, 1);
|
||||
jwidget_set_maximum_height(ul, 1);
|
||||
jwidget_set_border(ul, J_BORDER_SOLID, 1, C_BLACK);
|
||||
}
|
||||
else if(!strcmp(item->tagName, "i") ||
|
||||
!strcmp(item->tagName, "em"))
|
||||
{
|
||||
dom_state_t sc = s;
|
||||
sc.italic = true;
|
||||
parse_msg_body_dom(line, item, sc);
|
||||
}
|
||||
else if (!strcmp(item->tagName, "code"))
|
||||
{
|
||||
dom_state_t sc = s;
|
||||
sc.italic = true;
|
||||
sc.bg = GRAY;
|
||||
sc.fg = C_RGB(31, 24, 25);
|
||||
|
||||
parse_msg_body_dom(line, item, sc);
|
||||
}
|
||||
else if (!strcmp(item->tagName, "strong"))
|
||||
{
|
||||
dom_state_t sc = s;
|
||||
sc.bold = true;
|
||||
parse_msg_body_dom(line, item, sc);
|
||||
}
|
||||
else if (!strcmp(item->tagName, "p"))
|
||||
{
|
||||
parse_msg_body_dom(line, item, s);
|
||||
line = jwidget_create(container);
|
||||
jlayout_set_hbox(line)->spacing = 1;
|
||||
}
|
||||
else if (!strcmp(item->tagName, "h1"))
|
||||
{
|
||||
void *w;
|
||||
dom_state_t sc = s;
|
||||
|
||||
sc.bold = true;
|
||||
sc.fg = GRAY;
|
||||
w = parse_msg_body_dom(line, item, sc);
|
||||
|
||||
line = jwidget_create(container);
|
||||
jlayout_set_hbox(line)->spacing = 1;
|
||||
jwidget_set_stretch(line, 1, 0, false);
|
||||
|
||||
parse_msg_body_dom(line, item, s);
|
||||
}
|
||||
else if (!strcmp(item->tagName, "br"))
|
||||
{
|
||||
size_t j;
|
||||
line = jwidget_create(container);
|
||||
jlayout_set_hbox(line)->spacing = 1;
|
||||
jwidget_set_stretch(line, 1, 0, false);
|
||||
parse_msg_body_dom(line, item, s);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return container;
|
||||
}
|
||||
static jwidget *parse_msg_body_html(void *p, char *html)
|
||||
{
|
||||
struct el_t *top;
|
||||
struct DomElement *dom;
|
||||
char *contained, *cpy;
|
||||
jwidget *container;
|
||||
size_t i;
|
||||
dom_state_t def = {
|
||||
.bg = C_NONE, .fg = C_NONE,
|
||||
.bold = false, .italic = false
|
||||
};
|
||||
|
||||
contained = utils_strcat("<html>", html);
|
||||
cpy = contained;
|
||||
contained = utils_strcat(contained, "</html>");
|
||||
|
@ -71,50 +164,13 @@ static jwidget *parse_msg_body_html(void *p, char *html)
|
|||
dom = top->dom;
|
||||
|
||||
/* Actually manage the HTML */
|
||||
for (i = 0; i < dom->childnum; i++)
|
||||
container = parse_msg_body_dom(p, dom, def);
|
||||
if (!container)
|
||||
{
|
||||
struct DomElement *item = dom->children[i];
|
||||
if (!strcmp(item->tagName, "span"))
|
||||
{
|
||||
render_span(line, item);
|
||||
}
|
||||
if (!strcmp(item->tagName, "i") ||
|
||||
!strcmp(item->tagName, "em"))
|
||||
{
|
||||
render_i(line, item->children[0]);
|
||||
}
|
||||
if (!strcmp(item->tagName, "code"))
|
||||
{
|
||||
jlabel *l = render_i(line, item->children[0]);
|
||||
log_text("%s: %d children", item->childnum);
|
||||
jwidget_set_background(l, GRAY);
|
||||
jlabel_set_text_color(l, C_RGB(31, 24, 25));
|
||||
}
|
||||
if (!strcmp(item->tagName, "strong"))
|
||||
{
|
||||
render_strong(line, item->children[0]);
|
||||
}
|
||||
if (!strcmp(item->tagName, "h1"))
|
||||
{
|
||||
jlabel *w = render_strong(line, item->children[0]);
|
||||
jlabel_set_text_color(w, GRAY);
|
||||
|
||||
line = jwidget_create(container);
|
||||
jlayout_set_hbox(line)->spacing = 1;
|
||||
jwidget_set_stretch(line, 1, 0, false);
|
||||
}
|
||||
if (!strcmp(item->tagName, "br"))
|
||||
{
|
||||
|
||||
line = jwidget_create(container);
|
||||
jlayout_set_hbox(line)->spacing = 1;
|
||||
jwidget_set_stretch(line, 1, 0, false);
|
||||
|
||||
jlabel *l = jlabel_create("go brrrr", line);
|
||||
jlabel_asprintf(l, "%d/%d %d", i + 1, dom->childnum, item->childnum);
|
||||
}
|
||||
free(contained);
|
||||
html_clear();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
free(contained);
|
||||
html_clear();
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef MATRIX_COMMAND_H
|
||||
#define MATRIX_COMMAND_H
|
||||
|
||||
#include <utils.h>
|
||||
|
||||
/* TODO */
|
||||
typedef struct command {
|
||||
char *command;
|
||||
|
||||
array_t *arguments;
|
||||
} command_t;
|
||||
|
||||
extern command_t *command_parse(char *);
|
||||
extern void command_free(command_t *);
|
||||
#endif
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef MATRIX_DBG_H
|
||||
#define MATRIX_DBG_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
extern void dbg_init(void);
|
||||
extern void * dbg_get(size_t);
|
||||
extern void dbg_end(void);
|
||||
|
||||
#endif
|
|
@ -2,5 +2,6 @@
|
|||
#define MATRIX_EASTERS_H
|
||||
|
||||
extern void easter_goda(void);
|
||||
extern void easter_dvd_frame(const char *);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -18,6 +18,6 @@
|
|||
#define MASTRIX_PLAT "(unknown)"
|
||||
#endif
|
||||
|
||||
#define MASTRIX_UA (MASTRIX_NAME " " MASTRIX_VERS " (" MASTRIX_VERS ")")
|
||||
#define MASTRIX_UA MASTRIX_NAME " " MASTRIX_VERS " (" MASTRIX_VERS ")"
|
||||
|
||||
#endif
|
||||
|
|
|
@ -111,4 +111,5 @@ extern void matrix_show_event(m_room_t *, m_user_t *, m_event_t *, jwidget *);
|
|||
|
||||
|
||||
extern char *matrix_send_file(m_user_t *, char *, char *);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -55,6 +55,8 @@ typedef struct ui_screen {
|
|||
screen_setup_t init;
|
||||
screen_focus_t on_focus;
|
||||
screen_event_t on_event;
|
||||
|
||||
void (*end)(struct ui_screen *that);
|
||||
} ui_screen_t;
|
||||
|
||||
extern ui_session_t * ui_create_session(void);
|
||||
|
@ -69,7 +71,7 @@ extern void *ui_get_data(ui_session_t *, char *);
|
|||
extern void ui_add_data(ui_session_t *, char *, void *, end_value);
|
||||
extern void ui_session_loop(ui_session_t *);
|
||||
extern bool ui_manage_event(ui_session_t *, jevent);
|
||||
extern void ui_destroy_session(ui_session_t *);
|
||||
extern void ui_destroy_screen(ui_session_t *);
|
||||
|
||||
/* == EXTRA JUSTUI TYPES == */
|
||||
struct jmlist;
|
||||
|
@ -108,10 +110,12 @@ extern uint16_t JMLIST_ITEM_NOP;
|
|||
extern jmlist *jmlist_create(void *, jmlist_set_widget, jmlist_free_data);
|
||||
extern int jmlist_selected(jmlist *);
|
||||
extern int jmlist_add_item(jmlist *, void *);
|
||||
extern int jmlist_prepend_item(jmlist *, void *);
|
||||
extern int jmlist_select(jmlist *, int);
|
||||
extern bool jmlist_scroll(jmlist *, jrect);
|
||||
extern jrect jmlist_scrolled(jmlist *, jrect);
|
||||
|
||||
extern jpainted *ui_image(void *, const bopti_image_t *);
|
||||
extern jpainted *ui_blurhash(void *, char *);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <justui/jscene.h>
|
||||
|
||||
extern void * ui_infos_init(ui_screen_t *that);
|
||||
extern void * ui_infos_event(ui_screen_t *that, jevent e);
|
||||
|
||||
extern void * ui_login_init(ui_screen_t *that);
|
||||
extern void * ui_login_focus(ui_screen_t *that);
|
||||
|
|
|
@ -33,6 +33,7 @@ extern void utils_array_shift(array_t *, size_t);
|
|||
extern size_t utils_array_size(array_t *);
|
||||
extern void * utils_array_get(array_t *, size_t);
|
||||
extern void utils_array_set(array_t *, size_t, void *);
|
||||
extern void utils_array_pop(array_t *);
|
||||
extern void utils_free_array(array_t *);
|
||||
|
||||
typedef struct json_value json_value_t;
|
||||
|
@ -65,4 +66,6 @@ extern json_value_t * utils_boolean_as_json(bool);
|
|||
extern json_value_t * utils_null_as_json(void);
|
||||
|
||||
extern hashmap_t *utils_json_copy(hashmap_t *);
|
||||
|
||||
extern uint16_t *utils_decode_blurhash(char *, int *, int *);
|
||||
#endif
|
||||
|
|
37
src/jmlist.c
37
src/jmlist.c
|
@ -33,6 +33,7 @@ jmlist *jmlist_create(void *parent, jmlist_set_widget set, jmlist_free_data f)
|
|||
|
||||
list->box = jwidget_create(list->frame);
|
||||
jlayout_set_vbox(list->box)->spacing = 1;
|
||||
jwidget_set_maximum_width(list->box, DWIDTH);
|
||||
|
||||
list->arr = utils_new_array();
|
||||
list->selected = -1;
|
||||
|
@ -76,9 +77,32 @@ int jmlist_add_item(jmlist *list, void *data)
|
|||
|
||||
return idx;
|
||||
}
|
||||
int jmlist_prepend_item(jmlist *list, void *data)
|
||||
{
|
||||
jmlist_item *item;
|
||||
if (!list)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
item = malloc(sizeof(jmlist_item));
|
||||
item->data = data;
|
||||
item->widget = jwidget_create(list->box);
|
||||
item->owner = list;
|
||||
|
||||
utils_array_shift(list->arr, 1);
|
||||
utils_array_set(list->arr, 0, item);
|
||||
list->set(item, 0);
|
||||
list->offset_x = -(jwidget_full_width(list->box));
|
||||
|
||||
jwidget_emit(list, (jevent){ .type = JMLIST_ITEM_ADDED });
|
||||
|
||||
return 0;
|
||||
}
|
||||
int jmlist_select(jmlist *list, int idx)
|
||||
{
|
||||
jmlist_item *item;
|
||||
size_t oidx;
|
||||
|
||||
if (!list)
|
||||
{
|
||||
|
@ -90,7 +114,9 @@ int jmlist_select(jmlist *list, int idx)
|
|||
if (item && item->widget)
|
||||
{
|
||||
jwidget *w = item->widget;
|
||||
log_text("%s: unselecting", __func__);
|
||||
jwidget_set_background(w, C_NONE);
|
||||
log_text("%s: unselected", __func__);
|
||||
}
|
||||
if (idx >= utils_array_size(list->arr))
|
||||
{
|
||||
|
@ -101,11 +127,20 @@ int jmlist_select(jmlist *list, int idx)
|
|||
idx = 0;
|
||||
}
|
||||
|
||||
log_text("%s: getting", __func__);
|
||||
item = utils_array_get(list->arr, idx);
|
||||
if (!item)
|
||||
{
|
||||
log_text("%s: got %d items", __func__, utils_array_size(list->arr));
|
||||
return list->selected;
|
||||
}
|
||||
log_text("%s: got", __func__);
|
||||
|
||||
|
||||
list->selected = idx;
|
||||
log_text("%s: setting bg %p %d", __func__, item, idx);
|
||||
jwidget_set_background(item->widget, C_RGB(1, 19, 27));
|
||||
log_text("%s: set bg %p", __func__, item);
|
||||
|
||||
jmlist_scroll(
|
||||
list,
|
||||
|
@ -116,7 +151,9 @@ int jmlist_select(jmlist *list, int idx)
|
|||
.h = jwidget_full_height(item->widget)
|
||||
}
|
||||
);
|
||||
log_text("%s: scrolled", __func__);
|
||||
jwidget_emit(list, (jevent){ .type = JMLIST_ITEM_CHANGE });
|
||||
log_text("%s: emitted", __func__);
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
|
23
src/json.c
23
src/json.c
|
@ -558,6 +558,7 @@ static json_value_t *parse_null(json_parser_t *parser)
|
|||
|
||||
return utils_null_as_json();
|
||||
}
|
||||
|
||||
static json_value_t *parse_array(json_parser_t *parser)
|
||||
{
|
||||
#define get_token_off() utils_array_get(\
|
||||
|
@ -630,6 +631,15 @@ fail:
|
|||
#undef get_token_off
|
||||
}
|
||||
|
||||
/* Under arrest (failed parsing an array midsync)
|
||||
* The suspect was seen freeing hashmap data(so a failure)
|
||||
* and then crashing everything.
|
||||
*
|
||||
* This is probably a big "oops, uninitialised variable" moment.
|
||||
*
|
||||
* I however, can't see a scenario where the object parsing would
|
||||
* fail with an *uninitialised* hashmap instantly like in the
|
||||
* traces. :/ */
|
||||
static json_value_t *parse_object(json_parser_t *parser)
|
||||
{
|
||||
#define get_token_off() utils_array_get(\
|
||||
|
@ -638,10 +648,7 @@ static json_value_t *parse_object(json_parser_t *parser)
|
|||
)
|
||||
json_parser_t copy;
|
||||
json_token_t *token;
|
||||
array_t *arr;
|
||||
hashmap_t *hm;
|
||||
|
||||
size_t i = 0;
|
||||
hashmap_t *hm = NULL;
|
||||
|
||||
bool except = true;
|
||||
bool first_time = true;
|
||||
|
@ -659,15 +666,11 @@ static json_value_t *parse_object(json_parser_t *parser)
|
|||
token = get_token_off();
|
||||
if (!token || token->type != JSON_TOK_LCB)
|
||||
{
|
||||
if (token->type == JSON_TOK_STRING)
|
||||
{
|
||||
}
|
||||
if (token->type == JSON_TOK_NUMBER)
|
||||
{
|
||||
}
|
||||
/* ???? */
|
||||
return NULL;
|
||||
}
|
||||
hm = utils_new_hashmap();
|
||||
/* ???? */
|
||||
while ((token = get_token_off()) && token->type != JSON_TOK_RCB)
|
||||
{
|
||||
if (!except)
|
||||
|
|
36
src/main.c
36
src/main.c
|
@ -1,7 +1,10 @@
|
|||
#include <gint/display.h>
|
||||
#include <gint/keyboard.h>
|
||||
#include <gint/usb-ff-bulk.h>
|
||||
#include <gint/keyboard.h>
|
||||
#include <gint/hardware.h>
|
||||
#include <gint/display.h>
|
||||
#include <gint/kmalloc.h>
|
||||
#include <gint/usb.h>
|
||||
#include <gint/rtc.h>
|
||||
#include <gint/fs.h>
|
||||
|
||||
#include <justui/jscene.h>
|
||||
|
@ -14,6 +17,7 @@
|
|||
#include <ui_generators.h>
|
||||
#include <info.h>
|
||||
#include <usb.h>
|
||||
#include <dbg.h>
|
||||
#include <ui.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
@ -62,6 +66,32 @@ int main(void)
|
|||
int in, out;
|
||||
usb_fxlink_header_t reply;
|
||||
|
||||
uint8_t major, minor;
|
||||
short int tmp;
|
||||
|
||||
uint32_t self_addr = (uintptr_t) main;
|
||||
uint32_t top_addr = self_addr & 0xFF000000;
|
||||
|
||||
/* Can we use extra memory? Check if this is an fx-CG50 and
|
||||
* that main isn't in that segment */
|
||||
srand(rtc_ticks());
|
||||
if (gint[HWCALC] == HWCALC_FXCG50 && top_addr != 0x8C000000)
|
||||
{
|
||||
static kmalloc_arena_t extRAM = { 0 };
|
||||
extRAM.name = "extram";
|
||||
extRAM.is_default = true;
|
||||
extRAM.start = (void*) 0x8c200000;
|
||||
extRAM.end = (void*) 0x8c500000; // 4MB
|
||||
|
||||
kmalloc_init_arena(&extRAM, true);
|
||||
kmalloc_add_arena(&extRAM);
|
||||
|
||||
dclear(C_GREEN);
|
||||
dtext(1, 1, C_WHITE, "Ma's Trix will take extra memory.");
|
||||
dupdate();
|
||||
getkey();
|
||||
}
|
||||
|
||||
|
||||
dclear(C_WHITE);
|
||||
dtext(1, 1, C_BLACK, "Waiting for USB link...");
|
||||
|
@ -70,6 +100,7 @@ int main(void)
|
|||
usb_init(&out, &in);
|
||||
|
||||
story_of_usb_comm(); /* Greet the user over USB */
|
||||
dbg_init();
|
||||
|
||||
/* Set UI up... */
|
||||
ui = ui_create_session();
|
||||
|
@ -84,6 +115,7 @@ int main(void)
|
|||
|
||||
end:
|
||||
/* End everything... */
|
||||
dbg_end();
|
||||
usb_close();
|
||||
//ui_destroy_session(ui);
|
||||
return 1;
|
||||
|
|
76
src/ui.c
76
src/ui.c
|
@ -4,6 +4,8 @@
|
|||
#include <gint/keyboard.h>
|
||||
#include <gint/timer.h>
|
||||
|
||||
#include <libimg.h>
|
||||
|
||||
#include <justui/jscene.h>
|
||||
#include <justui/jinput.h>
|
||||
#include <justui/jfkeys.h>
|
||||
|
@ -45,7 +47,7 @@ ui_session_t *ui_create_session(void)
|
|||
ret->stack = jwidget_create(ret->justui_screen);
|
||||
jlayout_set_stack(ret->stack);
|
||||
jwidget_set_padding(ret->stack, 0, 0, 0, 0);
|
||||
jwidget_set_stretch(ret->stack, 1, 1, false);
|
||||
jwidget_set_stretch(ret->stack, 1, 1, true);
|
||||
|
||||
ret->waiting = false;
|
||||
|
||||
|
@ -131,6 +133,7 @@ bool ui_manage_event(ui_session_t *ui, jevent e)
|
|||
widget = screen->on_event(screen, e);
|
||||
if (widget)
|
||||
{
|
||||
/* This lil' fella has an unusual tendency to crash. */
|
||||
jscene_set_focused_widget(ui->justui_screen, widget);
|
||||
return true;
|
||||
}
|
||||
|
@ -178,8 +181,42 @@ ui_screen_t * ui_new_screen(screen_setup_t setup, screen_focus_t focus,
|
|||
ret->on_focus = focus;
|
||||
ret->on_event = event;
|
||||
|
||||
ret->end = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
void ui_destroy_screen(ui_session_t *ui)
|
||||
{
|
||||
ui_screen_t *screen;
|
||||
if (!ui)
|
||||
{
|
||||
return;
|
||||
}
|
||||
screen = utils_array_get(ui->screens, ui->current_screen);
|
||||
if (screen->end)
|
||||
{
|
||||
screen->end(screen);
|
||||
}
|
||||
utils_array_pop(ui->screens);
|
||||
free(screen);
|
||||
ui->current_screen--;
|
||||
|
||||
|
||||
screen = utils_array_get(ui->screens, ui->current_screen);
|
||||
if (screen->on_focus)
|
||||
{
|
||||
void *w = screen->on_focus(screen);
|
||||
if (w)
|
||||
{
|
||||
jscene_show_and_focus(ui->justui_screen, w);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
dclear(C_WHITE);
|
||||
jscene_render(ui->justui_screen);
|
||||
dupdate();
|
||||
}
|
||||
|
||||
static void draw_image(int x, int y, const bopti_image_t *img)
|
||||
{
|
||||
|
@ -202,3 +239,40 @@ jpainted *ui_image(void *parent, const bopti_image_t *img)
|
|||
|
||||
return ret;
|
||||
}
|
||||
#define SCALE 20
|
||||
static void draw_blur(int x, int y, char *bh)
|
||||
{
|
||||
int w = 0, h = 0;
|
||||
size_t xp, yp;
|
||||
uint16_t *colors = utils_decode_blurhash(bh, &w, &h);
|
||||
|
||||
for (yp = 0; yp < h; yp++)
|
||||
{
|
||||
for (xp = 0; xp < w; xp++)
|
||||
{
|
||||
uint16_t c = colors[yp * w + xp];
|
||||
drect(
|
||||
xp * SCALE + x, yp * SCALE + y,
|
||||
xp * SCALE + SCALE, yp * SCALE + SCALE,
|
||||
c
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
free(colors);
|
||||
}
|
||||
jpainted *ui_blurhash(void *p, char *bh)
|
||||
{
|
||||
int w = 0, h = 0;
|
||||
uint16_t *nothing;
|
||||
|
||||
nothing = utils_decode_blurhash(bh, &w, &h);
|
||||
free(nothing);
|
||||
return jpainted_create(
|
||||
draw_blur,
|
||||
(j_arg_t) (void *) bh,
|
||||
w * SCALE, h * SCALE,
|
||||
p
|
||||
);
|
||||
}
|
||||
|
|
|
@ -13,24 +13,33 @@
|
|||
|
||||
#include <matrix.h>
|
||||
#include <utils.h>
|
||||
#include <info.h>
|
||||
|
||||
const char *infos =
|
||||
"= Ma's Trix\n"
|
||||
"= Ma's Trix\n"
|
||||
"A half decent [matrix] client.\n\n\n"
|
||||
"LICENSE: \n"
|
||||
"- TBD lol\n\n"
|
||||
"- CeCILL\n\n"
|
||||
|
||||
"WRITTEN BY: \n"
|
||||
"- LDA <@lda:a.freetards.xyz>\n"
|
||||
"(pssht KONTRIBUTORS, put your contacts here!)\n\n"
|
||||
|
||||
"THANKS TO: \n"
|
||||
"- Lephe for writing gint, fxlink, libimg and other tools\n"
|
||||
"- Lephe for writing gint, fxlink, libimg, WebCalc and other tools\n"
|
||||
"- ari.lt for offering the mastrix.org domain for free!\n"
|
||||
"- The [matrix] Foundation for providing its specification to "
|
||||
"the public\n"
|
||||
"- dav for adding Ma's Trix onto the matrix wiki even though he "
|
||||
"wasnt supposed to when he did it since i didnt release it\n"
|
||||
"- Various other open-source contributors "
|
||||
"for additional software used to create Ma's Trix\n";
|
||||
"for additional software used to create Ma's Trix\n"
|
||||
"- plate, just come back please :(\n\n"
|
||||
"FUN STUFF (press F1 to exit): \n"
|
||||
"- Program name: " MASTRIX_NAME "\n"
|
||||
"- Program version: " MASTRIX_VERS "\n"
|
||||
"- Intended platform: " MASTRIX_PLAT "\n"
|
||||
"- User-Agent string: " MASTRIX_UA "\n";
|
||||
void * ui_infos_init(ui_screen_t *that)
|
||||
{
|
||||
jframe *info_frame;
|
||||
|
@ -45,3 +54,11 @@ void * ui_infos_init(ui_screen_t *that)
|
|||
|
||||
return info_frame;
|
||||
}
|
||||
void * ui_infos_event(ui_screen_t *that, jevent e)
|
||||
{
|
||||
if (e.key.type == KEYEV_UP && e.key.key == KEY_F1)
|
||||
{
|
||||
ui_destroy_screen(that->owner);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <easters.h>
|
||||
#include <matrix.h>
|
||||
#include <utils.h>
|
||||
#include <log.h>
|
||||
|
||||
|
||||
extern const bopti_image_t mastrix;
|
||||
|
@ -206,9 +207,13 @@ void * ui_login_event(ui_screen_t *that, jevent e)
|
|||
user->device_id
|
||||
);
|
||||
|
||||
log_text("%s: attempting initial sync", __func__);
|
||||
matrix_initial_sync(user);
|
||||
log_text("%s: attempted initial sync, loading room list", __func__);
|
||||
rooms = ui_new_screen(ui_rooms_init, ui_rooms_focus, ui_rooms_event);
|
||||
log_text("%s: adding screen", __func__);
|
||||
ui_add_screen(that->owner, rooms);
|
||||
log_text("%s: added screen", __func__);
|
||||
|
||||
return NULL; /* TODO: Change screen, since we're logged in */
|
||||
}
|
||||
|
|
137
src/ui_room.c
137
src/ui_room.c
|
@ -10,12 +10,12 @@
|
|||
#include <justui/jframe.h>
|
||||
#include <justui/jfkeys.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <matrix.h>
|
||||
#include <utils.h>
|
||||
#include <log.h>
|
||||
#include <usb.h>
|
||||
|
||||
typedef struct ui_room_extra {
|
||||
|
@ -25,6 +25,7 @@ typedef struct ui_room_extra {
|
|||
jwidget *tl_widget;
|
||||
jfkeys *jfk;
|
||||
jmlist *timeline;
|
||||
jmlist *charpick;
|
||||
jfileselect *file;
|
||||
|
||||
m_room_t *room;
|
||||
|
@ -48,6 +49,31 @@ typedef struct item_extra {
|
|||
ui_room_extra_t *extra;
|
||||
} item_extra_t;
|
||||
|
||||
static void ui_room_act(item_extra_t *ie)
|
||||
{
|
||||
ui_room_extra_t *extra = ie->extra;
|
||||
m_event_t *event = ie->event;
|
||||
|
||||
if (strcmp(event->type, "m.room.message"))
|
||||
{
|
||||
/* Do not interact over non-messages for now */
|
||||
return;
|
||||
}
|
||||
/* TODO: Act upon the event(downloading/...) */
|
||||
}
|
||||
|
||||
static void set_chr(jmlist_item *item, int idx)
|
||||
{
|
||||
char c = idx + ' ';
|
||||
jlabel *label;
|
||||
jwidget_set_stretch(item->widget, 1, 0, false);
|
||||
jlayout_set_vbox(item->widget)->spacing = 1;
|
||||
jwidget_set_background(item->widget, C_WHITE);
|
||||
|
||||
label = jlabel_create("", item->widget);
|
||||
jlabel_asprintf(label, "%c", c);
|
||||
jwidget_set_background(label, C_WHITE);
|
||||
}
|
||||
static void set(jmlist_item *item, int idx)
|
||||
{
|
||||
item_extra_t *ie = item->data;
|
||||
|
@ -63,6 +89,13 @@ static void set(jmlist_item *item, int idx)
|
|||
|
||||
matrix_show_event(extra->room, extra->user, e, item->widget);
|
||||
}
|
||||
static void screen_free(ui_screen_t *that)
|
||||
{
|
||||
ui_room_extra_t *extra = that->data;
|
||||
jwidget_destroy(extra->main);
|
||||
timer_stop(extra->timer_id);
|
||||
free(that->data);
|
||||
}
|
||||
|
||||
void * ui_room_init(ui_screen_t *that)
|
||||
{
|
||||
|
@ -87,6 +120,8 @@ void * ui_room_init(ui_screen_t *that)
|
|||
jwidget_set_padding(main, 0, 0, 0, 0);
|
||||
jwidget_set_stretch(main, 15, 15, false);
|
||||
|
||||
that->end = screen_free;
|
||||
|
||||
user = that->owner->user;
|
||||
room = that->owner->room;
|
||||
|
||||
|
@ -119,7 +154,6 @@ void * ui_room_init(ui_screen_t *that)
|
|||
|
||||
|
||||
|
||||
/* TODO: Regularly update history, somehow */
|
||||
that->data = extra;
|
||||
that->owner->waiting = true;
|
||||
matrix_update_room_history(user, room, NULL, 20);
|
||||
|
@ -131,7 +165,7 @@ void * ui_room_init(ui_screen_t *that)
|
|||
jwidget_set_stretch(type_message, 1, 0, false);
|
||||
jwidget_set_border(type_message, J_BORDER_SOLID, 1, C_BLACK);
|
||||
|
||||
jfk = jfkeys_create("@MESG;@ROOM;/FILE;;;@EXIT", main);
|
||||
jfk = jfkeys_create("@MESG;@ROOM;/FILE;;#CHR;@EXIT", main);
|
||||
jwidget_set_stretch(jfk, 1, 0, false);
|
||||
|
||||
{
|
||||
|
@ -144,6 +178,7 @@ void * ui_room_init(ui_screen_t *that)
|
|||
extra->jfk = jfk;
|
||||
extra->on_timeline = true;
|
||||
extra->file = NULL;
|
||||
extra->charpick = NULL;
|
||||
|
||||
extra->timer_id = timer_configure(
|
||||
TIMER_ANY,
|
||||
|
@ -176,29 +211,23 @@ void * ui_room_init(ui_screen_t *that)
|
|||
static void ui_update_history(ui_screen_t *that)
|
||||
{
|
||||
ui_room_extra_t *extra = that->data;
|
||||
size_t size, i;
|
||||
size_t lidx, i, size;
|
||||
|
||||
lidx = /*utils_array_size(extra->room->timeline)*/0;
|
||||
matrix_update_room_history(extra->user, extra->room, NULL, 5);
|
||||
|
||||
jwidget_destroy(extra->timeline);
|
||||
jwidget_destroy(extra->file);
|
||||
|
||||
jwidget_set_padding(extra->tl_widget, 1, 1, 1, 1);
|
||||
jwidget_set_stretch(extra->tl_widget, 1, 1, false);
|
||||
|
||||
|
||||
|
||||
extra->timeline = jmlist_create(extra->tl_widget, set, NULL);
|
||||
|
||||
extra->file = jfileselect_create(extra->tl_widget);
|
||||
jwidget_set_stretch(extra->file, 1, 1, false);
|
||||
jwidget_set_background(extra->file, C_WHITE);
|
||||
|
||||
jwidget_set_stretch(extra->timeline, 1, 1, false);
|
||||
|
||||
|
||||
size = utils_array_size(extra->room->timeline);
|
||||
for (i = 0; i < size; i++)
|
||||
for (i = lidx; i < size; i++)
|
||||
{
|
||||
m_event_t *e = utils_array_get(extra->room->timeline, size - i - 1);
|
||||
item_extra_t *ie = malloc(sizeof(item_extra_t));
|
||||
|
@ -207,10 +236,12 @@ static void ui_update_history(ui_screen_t *that)
|
|||
ie->event = e;
|
||||
ie->screen = that;
|
||||
ie->extra = extra;
|
||||
/*jmlist_prepend_item(extra->timeline, ie);*/
|
||||
jmlist_add_item(extra->timeline, ie);
|
||||
}
|
||||
|
||||
jmlist_select(extra->timeline, 1);
|
||||
|
||||
return;
|
||||
}
|
||||
#include <string.h>
|
||||
void emit(void *w0, jevent e)
|
||||
|
@ -249,15 +280,10 @@ static int timer_cb(ui_screen_t *that)
|
|||
((ui_room_extra_t *) that->data)->flag1 = false;
|
||||
return TIMER_CONTINUE;
|
||||
}
|
||||
static void * ui_file_event(ui_screen_t *that, jevent e, bool first)
|
||||
static void * ui_file_event(ui_screen_t *that, jevent e)
|
||||
{
|
||||
ui_room_extra_t *extra = that->data;
|
||||
/* Yeah, different bit of code */
|
||||
if (first)
|
||||
{
|
||||
jfileselect_browse(extra->file, "/");
|
||||
return NULL;
|
||||
}
|
||||
if (e.type == JFILESELECT_VALIDATED)
|
||||
{
|
||||
hashmap_t *msg;
|
||||
|
@ -266,9 +292,7 @@ static void * ui_file_event(ui_screen_t *that, jevent e, bool first)
|
|||
|
||||
path = (char *) jfileselect_selected_file(extra->file);
|
||||
base = utils_basename(path);
|
||||
log_text("%s: path='%s' basename='%s'", __func__, path, base);
|
||||
mxc = matrix_send_file(extra->user, path, NULL);
|
||||
log_text("%s: mxc='%s'", __func__, mxc);
|
||||
|
||||
msg = utils_new_hashmap();
|
||||
|
||||
|
@ -291,11 +315,46 @@ static void * ui_file_event(ui_screen_t *that, jevent e, bool first)
|
|||
return extra->timeline;
|
||||
}
|
||||
return extra->file;
|
||||
}
|
||||
static void * ui_char_event(ui_screen_t *that, jevent e)
|
||||
{
|
||||
ui_room_extra_t *extra = that->data;
|
||||
if (e.type == JMLIST_ITEM_CHOSEN)
|
||||
{
|
||||
char c = jmlist_selected(extra->charpick) + ' ';
|
||||
char cp[2] = { c, '\0' };
|
||||
char *input = utils_strcat(extra->input->text, cp);
|
||||
free(extra->input->text);
|
||||
extra->input->text = input;
|
||||
extra->input->size++;
|
||||
extra->input->widget.dirty = 1;
|
||||
|
||||
jwidget_destroy(extra->charpick);
|
||||
extra->charpick = NULL;
|
||||
return extra->input;
|
||||
}
|
||||
return extra->charpick;
|
||||
}
|
||||
void * ui_room_event(ui_screen_t *that, jevent e)
|
||||
{
|
||||
ui_room_extra_t *extra = that->data;
|
||||
if (extra->charpick)
|
||||
{
|
||||
return ui_char_event(that, e);
|
||||
}
|
||||
if (e.type == JMLIST_ITEM_CHOSEN && !extra->file)
|
||||
{
|
||||
/* TODO */
|
||||
int selected = jmlist_selected(extra->timeline);
|
||||
item_extra_t *ie = utils_array_get(extra->timeline->arr, selected);
|
||||
|
||||
if (!ie)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
ui_room_act(ie);
|
||||
return NULL;
|
||||
}
|
||||
if (e.type == JMLIST_ITEM_CHANGE && !extra->file)
|
||||
{
|
||||
int selected = jmlist_selected(extra->timeline);
|
||||
|
@ -318,7 +377,6 @@ void * ui_room_event(ui_screen_t *that, jevent e)
|
|||
uint8_t code = extra->input->mode;
|
||||
jrect rect;
|
||||
|
||||
log_text("%s: NOPd", __func__);
|
||||
|
||||
e = utils_array_get(extra->room->timeline, 0);
|
||||
|
||||
|
@ -360,6 +418,7 @@ void * ui_room_event(ui_screen_t *that, jevent e)
|
|||
hashmap_t *msg = utils_new_hashmap();
|
||||
m_event_t *e;
|
||||
|
||||
|
||||
utils_hashmap_set(
|
||||
msg,
|
||||
"body",
|
||||
|
@ -403,14 +462,16 @@ void * ui_room_event(ui_screen_t *that, jevent e)
|
|||
}
|
||||
if (e.key.key == KEY_F3 && e.key.type == KEYEV_UP && !extra->file)
|
||||
{
|
||||
/* TODO: Add a floating filebrowser */
|
||||
int null;
|
||||
extra->file = jfileselect_create(that->widget);
|
||||
|
||||
jwidget_set_floating(extra->file, true);
|
||||
jwidget_set_background(extra->file, C_WHITE);
|
||||
jwidget_set_minimum_size(extra->file, DWIDTH, DHEIGHT);
|
||||
jwidget_set_maximum_size(extra->file, DWIDTH, DHEIGHT);
|
||||
jwidget_set_maximum_size(
|
||||
extra->file,
|
||||
extra->tl_widget->w, extra->tl_widget->h
|
||||
);
|
||||
jwidget_set_minimum_size(extra->file, DWIDTH, DHEIGHT - 30);
|
||||
|
||||
jfileselect_set_show_file_size(extra->file, true);
|
||||
jlayout_get_stack(extra->tl_widget)->active = 1;
|
||||
|
@ -421,9 +482,33 @@ void * ui_room_event(ui_screen_t *that, jevent e)
|
|||
(void) null;
|
||||
return extra->file;
|
||||
}
|
||||
if (e.key.key == KEY_F5 && e.key.type == KEYEV_UP && !extra->file)
|
||||
{
|
||||
char i;
|
||||
extra->charpick = jmlist_create(that->widget, set_chr, NULL);
|
||||
for (i = ' '; i < 0x7F; i++)
|
||||
{
|
||||
jmlist_add_item(extra->charpick, (void *) ((uintptr_t) i));
|
||||
}
|
||||
|
||||
jwidget_set_floating(extra->charpick, true);
|
||||
jwidget_set_background(extra->charpick, C_WHITE);
|
||||
jwidget_set_maximum_size(
|
||||
extra->charpick,
|
||||
extra->tl_widget->w, extra->tl_widget->h
|
||||
);
|
||||
jwidget_set_minimum_size(extra->charpick, DWIDTH, DHEIGHT - 35);
|
||||
jmlist_select(extra->charpick, 1);
|
||||
return extra->charpick;
|
||||
}
|
||||
if (e.key.key == KEY_F6 && e.key.type == KEYEV_UP && !extra->file)
|
||||
{
|
||||
ui_destroy_screen(that->owner);
|
||||
return NULL;
|
||||
}
|
||||
if (extra->file)
|
||||
{
|
||||
return ui_file_event(that, e, false);
|
||||
return ui_file_event(that, e);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
#include <ui_generators.h>
|
||||
#include <matrix.h>
|
||||
#include <utils.h>
|
||||
#include <log.h>
|
||||
|
||||
typedef struct ui_userroom {
|
||||
m_user_t *user;
|
||||
|
@ -89,6 +88,7 @@ void * ui_rooms_init(ui_screen_t *that)
|
|||
jmlist *rooms_list;
|
||||
jwidget *wid;
|
||||
jlabel *rooms_text;
|
||||
jfkeys *jfk;
|
||||
|
||||
hashmap_t *rooms;
|
||||
|
||||
|
@ -123,6 +123,9 @@ void * ui_rooms_init(ui_screen_t *that)
|
|||
jwidget_set_padding(rooms_list, 1, 1, 1, 1);
|
||||
jwidget_set_stretch(rooms_list, 15, 15, false);
|
||||
|
||||
jfk = jfkeys_create("/INFOS;@DIR;;;#ACC;#JOIN", wid);
|
||||
jwidget_set_stretch(jfk, 1, 0, false);
|
||||
|
||||
that->data = rooms_list;
|
||||
|
||||
jmlist_select(rooms_list, 0);
|
||||
|
@ -144,6 +147,30 @@ void * ui_rooms_event(ui_screen_t *that, jevent e)
|
|||
|
||||
chat = ui_new_screen(ui_room_init, NULL, ui_room_event);
|
||||
ui_add_screen(that->owner, chat);
|
||||
return NULL;
|
||||
}
|
||||
if (e.key.key == KEY_F1)
|
||||
{
|
||||
ui_screen_t *infos;
|
||||
infos = ui_new_screen(ui_infos_init, NULL, ui_infos_event);
|
||||
ui_add_screen(that->owner, infos);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
if (e.key.key == KEY_F2 && e.key.type == KEY_UP)
|
||||
{
|
||||
/* TODO: Room directory screen */
|
||||
return NULL;
|
||||
}
|
||||
if (e.key.key == KEY_F5 && e.key.type == KEY_UP)
|
||||
{
|
||||
/* TODO: Account information screen */
|
||||
return NULL;
|
||||
}
|
||||
if (e.key.key == KEY_F6 && e.key.type == KEY_UP)
|
||||
{
|
||||
/* TODO: Room join screen */
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
24
src/usb.c
24
src/usb.c
|
@ -12,6 +12,8 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <easters.h>
|
||||
|
||||
void usb_init(int *out, int *in)
|
||||
{
|
||||
timeout_t tm;
|
||||
|
@ -20,18 +22,34 @@ void usb_init(int *out, int *in)
|
|||
usb_open(intf, GINT_CALL_NULL);
|
||||
tm = timeout_make_ms(10 * 1000);
|
||||
|
||||
while (!usb_is_open() && !timeout_elapsed(&tm));
|
||||
while (!usb_is_open() && !timeout_elapsed(&tm))
|
||||
{
|
||||
timeout_t tm1 = timeout_make_ms(66);
|
||||
easter_dvd_frame(
|
||||
"Uplinking with USB (run mastrix on your PC now)..."
|
||||
);
|
||||
while (!timeout_elapsed(&tm1));
|
||||
}
|
||||
|
||||
if (!usb_is_open())
|
||||
{
|
||||
char *str = "Couldn't open USB: timeout.";
|
||||
dclear(C_RED);
|
||||
dtext_opt(
|
||||
0, 0, C_WHITE, C_RED, DTEXT_CENTER, DTEXT_MIDDLE,
|
||||
DWIDTH / 2, DHEIGHT / 2,
|
||||
C_WHITE, C_RED,
|
||||
DTEXT_CENTER, DTEXT_MIDDLE,
|
||||
str, strlen(str)
|
||||
);
|
||||
dupdate();
|
||||
while (true) getkey();
|
||||
while (true)
|
||||
{
|
||||
key_event_t e = getkey();
|
||||
if (e.alpha && e.key == KEY_F1)
|
||||
{
|
||||
easter_goda();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*out = usb_ff_bulk_output();
|
||||
|
|
Loading…
Reference in New Issue