Skip to content
Snippets Groups Projects
Commit 56b4d817 authored by Deucе's avatar Deucе :ok_hand_tone4:
Browse files

A bunch of broken NewIfc stuff, but I want to push, so need to

commit it.

Also, a couple new patches for a previous commit that I apparently
hadn't added.
parent 1885e59a
No related branches found
No related tags found
No related merge requests found
--- context/ctx_hsha2.c.orig 2024-02-03 23:52:01.086437000 -0500
+++ context/ctx_hsha2.c 2024-02-04 00:00:35.711741000 -0500
@@ -285,7 +285,7 @@
/* Hash data using HMAC-SHA2 */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
-static int hmac( INOUT_PTR CONTEXT_INFO *contextInfoPtr,
+static int hello_netbsd_users_hmac( INOUT_PTR CONTEXT_INFO *contextInfoPtr,
IN_BUFFER( noBytes ) BYTE *buffer,
IN_LENGTH_Z int noBytes )
{
@@ -476,12 +476,12 @@
static const CAPABILITY_INFO capabilityInfoHMACSHA384 = {
CRYPT_ALGO_SHA2, bitsToBytes( 384 ), "HMAC-SHA384", 11,
bitsToBytes( 64 ), bitsToBytes( 128 ), CRYPT_MAX_KEYSIZE,
- selfTest, getInfo, NULL, NULL, initKey, NULL, hmac, hmac
+ selfTest, getInfo, NULL, NULL, initKey, NULL, hello_netbsd_users_hmac, hello_netbsd_users_hmac
};
static const CAPABILITY_INFO capabilityInfoHMACSHA512 = {
CRYPT_ALGO_SHA2, bitsToBytes( 512 ), "HMAC-SHA512", 11,
bitsToBytes( 64 ), bitsToBytes( 128 ), CRYPT_MAX_KEYSIZE,
- selfTest, getInfo, NULL, NULL, initKey, NULL, hmac, hmac
+ selfTest, getInfo, NULL, NULL, initKey, NULL, hello_netbsd_users_hmac, hello_netbsd_users_hmac
};
/* Switch to the appropriate variant of SHA-2. Note that the
@@ -528,7 +528,7 @@
static const CAPABILITY_INFO capabilityInfo = {
CRYPT_ALGO_HMAC_SHA2, bitsToBytes( 256 ), "HMAC-SHA2", 9,
MIN_KEYSIZE, bitsToBytes( 256 ), CRYPT_MAX_KEYSIZE,
- selfTest, getInfo, NULL, initParams, initKey, NULL, hmac, hmac
+ selfTest, getInfo, NULL, initParams, initKey, NULL, hello_netbsd_users_hmac, hello_netbsd_users_hmac
};
CHECK_RETVAL_PTR_NONNULL \
--- random/unix.c.orig 2023-06-15 21:31:00.000000000 -0400
+++ random/unix.c 2024-02-04 00:09:42.916028000 -0500
@@ -560,8 +560,10 @@
/* IPv4 routing table */
{ 6, { CTL_NET, AF_ROUTE, 0, AF_INET6, NET_RT_DUMP, 0 }, 5 },
/* IPv6 routing table */
+#ifdef RTF_LLINFO
{ 6, { CTL_NET, AF_ROUTE, 0, AF_INET, NET_RT_FLAGS, RTF_LLINFO }, 5 },
/* ARP cache */
+#endif
/* VM info */
#ifdef VM_LOADAVG
@@ -747,7 +749,7 @@
/* BSD-specific polling using getfsstat() */
-#if defined( __FreeBSD__ ) || defined( __NetBSD__ ) || \
+#if defined( __FreeBSD__ ) || \
defined( __OpenBSD__ ) || defined( __APPLE__ )
#define USE_GETFSSTAT
......@@ -25,9 +25,7 @@ newifc.c: genapi
newifc.h: newifc.c
root_window.o: newifc.h
newifc.o: newifc.c root_window.c
newifc.o: newifc.c root_window.c label.c sizer.c sizer_cell.c
libnewifc.a: libnewifc.a(newifc.o)
ranlib $@
......
......@@ -22,6 +22,8 @@ void RunAllTests(void) {
int
main(int argc, char **argv) {
(void)argc;
(void)argv;
RunAllTests();
return 0;
}
......@@ -18,6 +18,8 @@ const struct objtype_info
objtypes[] = {
{"root_window", 0},
{"label", 1},
{"sizer", 1},
{"sizer_cell", 1},
};
enum attribute_types {
......@@ -29,6 +31,8 @@ enum attribute_types {
NI_attr_type_charptr,
NI_attr_type_NewIfc_object,
NI_attr_type_NewIfc_align,
NI_attr_type_int32_t,
NI_attr_type_voidptr_t,
};
struct type_str_values {
......@@ -45,6 +49,8 @@ struct type_str_values type_str[] = {
{"char *", "char_ptr"},
{"enum NewIfc_object", "obj_enum"},
{"enum NewIfc_alignment", "align_enum"},
{"int32_t", "int32"},
{"void *", "void_ptr"},
};
enum attribute_impl {
......@@ -56,6 +62,7 @@ enum attribute_impl {
struct attribute_info {
const char *name;
const char *member_name;
enum attribute_types type;
enum attribute_impl impl;
int read_only;
......@@ -65,40 +72,45 @@ struct attribute_info {
const struct attribute_info
attributes[] = {
{"align", NI_attr_type_NewIfc_align, attr_impl_global, 0, 0, 1},
{"bg_colour", NI_attr_type_uint32_t, attr_impl_global, 0, 0, 1},
{"bottom_child", NI_attr_type_NewIfcObj, attr_impl_global, 1, 0, 0},
{"bottom_pad", NI_attr_type_uint16_t, attr_impl_global, 0, 0, 0},
{"child_height", NI_attr_type_uint16_t, attr_impl_global, 1, 0, 0},
{"child_width", NI_attr_type_uint16_t, attr_impl_global, 1, 0, 0},
{"child_xpos", NI_attr_type_uint16_t, attr_impl_global, 1, 0, 0},
{"child_ypos", NI_attr_type_uint16_t, attr_impl_global, 1, 0, 0},
{"fg_colour", NI_attr_type_uint32_t, attr_impl_global, 0, 0, 1},
{"fill_character", NI_attr_type_uint8_t, attr_impl_global, 0, 0, 1},
{"fill_character_colour", NI_attr_type_uint32_t, attr_impl_global, 0, 0, 1},
{"fill_colour", NI_attr_type_uint32_t, attr_impl_global, 0, 0, 1},
{"fill_font", NI_attr_type_uint8_t, attr_impl_global, 0, 0, 1},
{"focus", NI_attr_type_bool, attr_impl_global_custom_setter, 0, 0, 0},
{"font", NI_attr_type_uint8_t, attr_impl_global, 0, 0, 1},
{"height", NI_attr_type_uint16_t, attr_impl_global, 0, 0, 0},
{"hidden", NI_attr_type_bool, attr_impl_global, 1, 0, 1},
{"higher_peer", NI_attr_type_NewIfcObj, attr_impl_global, 1, 0, 0},
{"locked", NI_attr_type_bool, attr_impl_root, 0, 1, 0},
{"locked_by_me", NI_attr_type_bool, attr_impl_root, 1, 1, 0},
{"lower_peer", NI_attr_type_NewIfcObj, attr_impl_global, 1, 0, 0},
{"left_pad", NI_attr_type_uint16_t, attr_impl_global, 0, 0, 0},
{"min_height", NI_attr_type_uint16_t, attr_impl_global, 1, 0, 0},
{"min_width", NI_attr_type_uint16_t, attr_impl_global, 1, 0, 0},
{"parent", NI_attr_type_NewIfcObj, attr_impl_global, 1, 0, 0},
{"right_pad", NI_attr_type_uint16_t, attr_impl_global, 0, 0, 0},
{"root", NI_attr_type_NewIfcObj, attr_impl_global, 1, 0, 1},
{"text", NI_attr_type_charptr, attr_impl_object, 0, 0, 0},
{"top_pad", NI_attr_type_uint16_t, attr_impl_global, 0, 0, 0},
{"top_child", NI_attr_type_NewIfcObj, attr_impl_global, 1, 0, 0},
{"type", NI_attr_type_NewIfc_object, attr_impl_global, 1, 0, 0},
{"width", NI_attr_type_uint16_t, attr_impl_global, 0, 0, 0},
{"xpos", NI_attr_type_uint16_t, attr_impl_global, 0, 0, 0},
{"ypos", NI_attr_type_uint16_t, attr_impl_global, 0, 0, 0},
{"align", NULL, NI_attr_type_NewIfc_align, attr_impl_global, 0, 0, 1},
{"bg_colour", NULL, NI_attr_type_uint32_t, attr_impl_global, 0, 0, 1},
{"bottom_child", NULL, NI_attr_type_NewIfcObj, attr_impl_global, 1, 0, 0},
{"bottom_pad", NULL, NI_attr_type_uint16_t, attr_impl_global, 0, 0, 0},
{"child_height", NULL, NI_attr_type_uint16_t, attr_impl_global, 1, 0, 0},
{"child_width", NULL, NI_attr_type_uint16_t, attr_impl_global, 1, 0, 0},
{"child_xpos", NULL, NI_attr_type_uint16_t, attr_impl_global, 1, 0, 0},
{"child_ypos", NULL, NI_attr_type_uint16_t, attr_impl_global, 1, 0, 0},
{"fg_colour", NULL, NI_attr_type_uint32_t, attr_impl_global, 0, 0, 1},
{"fill_character", NULL, NI_attr_type_uint8_t, attr_impl_global, 0, 0, 1},
{"fill_character_colour", NULL, NI_attr_type_uint32_t, attr_impl_global, 0, 0, 1},
{"fill_colour", NULL, NI_attr_type_uint32_t, attr_impl_global, 0, 0, 1},
{"fill_font", NULL, NI_attr_type_uint8_t, attr_impl_global, 0, 0, 1},
{"focus", NULL, NI_attr_type_bool, attr_impl_global_custom_setter, 0, 0, 0},
{"font", NULL, NI_attr_type_uint8_t, attr_impl_global, 0, 0, 1},
{"group_size", NULL, NI_attr_type_uint8_t, attr_impl_object, 0, 0, 0},
{"height", NULL, NI_attr_type_int32_t, attr_impl_global_custom_setter, 0, 0, 0},
{"hidden", NULL, NI_attr_type_bool, attr_impl_global, 1, 0, 1},
{"higher_peer", NULL, NI_attr_type_NewIfcObj, attr_impl_global, 1, 0, 0},
{"layout_width", "layout_size.width", NI_attr_type_uint16_t, attr_impl_global, 1, 0, 0},
{"layout_height", "layout_size.height", NI_attr_type_uint16_t, attr_impl_global, 1, 0, 0},
{"locked", NULL, NI_attr_type_bool, attr_impl_root, 0, 1, 0},
{"locked_by_me", NULL, NI_attr_type_bool, attr_impl_root, 1, 1, 0},
{"lower_peer", NULL, NI_attr_type_NewIfcObj, attr_impl_global, 1, 0, 0},
{"left_pad", NULL, NI_attr_type_uint16_t, attr_impl_global, 0, 0, 0},
{"min_height", NULL, NI_attr_type_uint16_t, attr_impl_global, 1, 0, 0},
{"min_width", NULL, NI_attr_type_uint16_t, attr_impl_global, 1, 0, 0},
{"parent", NULL, NI_attr_type_NewIfcObj, attr_impl_global, 1, 0, 0},
{"right_pad", NULL, NI_attr_type_uint16_t, attr_impl_global, 0, 0, 0},
{"root", NULL, NI_attr_type_NewIfcObj, attr_impl_global, 1, 0, 1},
{"text", NULL, NI_attr_type_charptr, attr_impl_object, 0, 0, 0},
{"top_pad", NULL, NI_attr_type_uint16_t, attr_impl_global, 0, 0, 0},
{"top_child", NULL, NI_attr_type_NewIfcObj, attr_impl_global, 1, 0, 0},
{"type", NULL, NI_attr_type_NewIfc_object, attr_impl_global, 1, 0, 0},
{"user_data", NULL, NI_attr_type_voidptr_t, attr_impl_global, 0, 0, 0},
{"weight", NULL, NI_attr_type_uint8_t, attr_impl_object, 0, 0, 0},
{"width", NULL, NI_attr_type_int32_t, attr_impl_global_custom_setter, 0, 0, 0},
{"xpos", NULL, NI_attr_type_uint16_t, attr_impl_global, 0, 0, 0},
{"ypos", NULL, NI_attr_type_uint16_t, attr_impl_global, 0, 0, 0},
};
struct attribute_alias {
......@@ -135,15 +147,26 @@ error_inf[] = {
struct handler_info {
const char *name;
const char *prototype;
const char *args;
const char *params;
};
const struct handler_info
extra_handlers[] = {
{"on_render", "NI_err (*on_render)(NewIfcObj obj, void *cbdata)"},
{"on_destroy", "NI_err (*on_destroy)(NewIfcObj obj, void *cbdata)"},
{"on_key", "NI_err (*on_key)(NewIfcObj obj, uint16_t scancode)"},
{"on_layout_minsize", "NI_err (*on_layout_minsize)(NewIfcObj obj, void *cbdata)", NULL, NULL},
{"on_layout_size", "NI_err (*on_layout_size)(NewIfcObj obj, void *cbdata)", NULL, NULL},
{"on_render", "NI_err (*on_render)(NewIfcObj obj, void *cbdata)", NULL, NULL},
{"on_destroy", "NI_err (*on_destroy)(NewIfcObj obj, void *cbdata)", NULL, NULL},
{"on_key", "NI_err (*on_key)(NewIfcObj obj, uint16_t scancode, void *cbdata)", ", uint16_t scancode", ", scancode"},
};
const char *member_name(size_t idx)
{
if (attributes[idx].member_name == NULL)
return attributes[idx].name;
return attributes[idx].member_name;
}
size_t
find_attribute(const char *name)
{
......@@ -169,7 +192,7 @@ attribute_functions(size_t i, FILE *c_code, const char *alias)
" return NewIfc_error_invalid_arg;\n"
" if (NI_set_locked(obj, true) == NewIfc_error_none) {\n", alias, type_str[attributes[i].type].type);
if (!attributes[i].no_event) {
fprintf(c_code, " ret = call_%s_change_handlers(obj, NewIfc_%s, value);\n"
fprintf(c_code, " ret = call_%s_change_handlers(obj, NewIfc_%s_handler, value);\n"
" if (ret != NewIfc_error_none) {\n"
" NI_set_locked(obj, false);\n"
" return ret;\n"
......@@ -201,14 +224,14 @@ attribute_functions(size_t i, FILE *c_code, const char *alias)
"}\n\n", alias, type_str[attributes[i].type].type, attributes[i].name);
break;
case attr_impl_global:
fprintf(c_code, "%s NI_err\n"
fprintf(c_code, "%sNI_err\n"
"NI_set_%s(NewIfcObj obj, const %s value) {\n"
" NI_err ret;\n"
" if (obj == NULL)\n"
" return NewIfc_error_invalid_arg;\n"
" if (NI_set_locked(obj, true) == NewIfc_error_none) {\n", attributes[i].read_only ? "static " : "", alias, type_str[attributes[i].type].type);
if (!attributes[i].no_event) {
fprintf(c_code, " ret = call_%s_change_handlers(obj, NewIfc_%s, value);\n"
fprintf(c_code, " ret = call_%s_change_handlers(obj, NewIfc_%s_handler, value);\n"
" if (ret != NewIfc_error_none) {\n"
" NI_set_locked(obj, false);\n"
" return ret;\n"
......@@ -224,7 +247,7 @@ attribute_functions(size_t i, FILE *c_code, const char *alias)
" else\n"
" ret = NewIfc_error_lock_failed;\n"
" return ret;\n"
"}\n\n", attributes[i].name, attributes[i].name);
"}\n\n", attributes[i].name, member_name(i));
// Fall-through
case attr_impl_global_custom_setter:
......@@ -246,7 +269,7 @@ attribute_functions(size_t i, FILE *c_code, const char *alias)
" else\n"
" ret = NewIfc_error_lock_failed;\n"
" return ret;\n"
"}\n\n", alias, type_str[attributes[i].type].type, attributes[i].name, attributes[i].name);
"}\n\n", alias, type_str[attributes[i].type].type, attributes[i].name, member_name(i));
break;
case attr_impl_root:
if (!attributes[i].read_only) {
......@@ -306,6 +329,8 @@ main(int argc, char **argv)
size_t nitems;
size_t i;
(void)argc;
(void)argv;
header = fopen("newifc.h", "w");
if (header == NULL) {
perror("Opening header");
......@@ -372,7 +397,9 @@ main(int argc, char **argv)
"#define NI_YELLOW UINT32_C(0x80FFFF54)\n"
"#define NI_WHITE UINT32_C(0x80FFFFFF)\n\n", header);
fputs("NI_err NI_copy(NewIfcObj obj, NewIfcObj *newobj);\n", header);
fputs("#define NI_GROW -1\n"
"#define NI_SHRINK -2\n", header);
fputs("NI_err NI_create(enum NewIfc_object obj, NewIfcObj parent, NewIfcObj *newobj);\n", header);
fputs("NI_err NI_destroy(NewIfcObj obj);\n", header);
fputs("NI_err NI_error(NewIfcObj obj);\n", header);
......@@ -403,6 +430,10 @@ main(int argc, char **argv)
fprintf(header, "NI_err NI_add_%s_handler(NewIfcObj obj, NI_err (*handler)(NewIfcObj obj, const %s newval, void *cbdata), void *cbdata);\n", aliases[i].alias_name, type_str[attributes[a].type].type);
fprintf(header, "NI_err NI_get_%s(NewIfcObj obj, %s* value);\n", aliases[i].alias_name, type_str[attributes[a].type].type);
}
nitems = sizeof(extra_handlers) / sizeof(extra_handlers[0]);
for (i = 0; i < nitems; i++) {
fprintf(header, "NI_err NI_add_%s_handler(NewIfcObj obj, %s);\n", extra_handlers[i].name, extra_handlers[i].prototype);
}
fputs("\n#endif\n", header);
fclose(header);
......@@ -458,10 +489,14 @@ main(int argc, char **argv)
" uint16_t ypos;\n"
"};\n\n", internal_header);
fputs("struct lo_size {\n"
" uint16_t width;\n"
" uint16_t height;\n"
"};\n\n", internal_header);
fputs("struct newifc_api {\n"
" NI_err (*set)(NewIfcObj niobj, const int attr, ...);\n"
" NI_err (*get)(NewIfcObj niobj, const int attr, ...);\n"
" NI_err (*copy)(NewIfcObj obj, NewIfcObj *newobj);\n"
" NI_err (*do_render)(NewIfcObj obj, struct NewIfc_render_context *ctx);\n"
" NI_err (*destroy)(NewIfcObj obj);\n"
" struct NewIfc_handler **handlers;\n"
......@@ -471,15 +506,18 @@ main(int argc, char **argv)
" NewIfcObj lower_peer;\n"
" NewIfcObj top_child;\n"
" NewIfcObj bottom_child;\n"
" void * user_data;\n"
" size_t handlers_sz;\n"
" struct lo_size layout_min_size;\n"
" struct lo_size layout_size;\n"
" uint32_t fill_character_colour;\n"
" uint32_t fill_colour;\n"
" uint32_t fg_colour;\n"
" uint32_t bg_colour;\n"
" enum NewIfc_object type;\n"
" enum NewIfc_alignment align;\n"
" uint16_t height;\n"
" uint16_t width;\n"
" int32_t height;\n"
" int32_t width;\n"
" uint16_t min_height;\n"
" uint16_t min_width;\n"
" uint16_t xpos;\n"
......@@ -506,6 +544,17 @@ main(int argc, char **argv)
}
fputs("};\n\n", internal_header);
fputs("enum NewIfc_handler_type {\n", internal_header);
nitems = sizeof(attributes) / sizeof(attributes[0]);
for (i = 0; i < nitems; i++) {
fprintf(internal_header, " NewIfc_%s_handler,\n", attributes[i].name);
}
nitems = sizeof(extra_handlers) / sizeof(extra_handlers[0]);
for (i = 0; i < nitems; i++) {
fprintf(internal_header, " NewIfc_%s_handler,\n", extra_handlers[i].name);
}
fputs("};\n\n", internal_header);
nitems = sizeof(attributes) / sizeof(attributes[0]);
for (i = 0; i < nitems; i++) {
if (attributes[i].read_only && attributes[i].impl == attr_impl_global) {
......@@ -515,6 +564,15 @@ main(int argc, char **argv)
fputs("static NI_err NI_copy_globals(NewIfcObj dst, NewIfcObj src);\n", internal_header);
nitems = sizeof(type_str) / sizeof(type_str[0]);
for (i = 0; i < nitems; i++) {
fprintf(internal_header, "static NI_err call_%s_change_handlers(NewIfcObj obj, enum NewIfc_handler_type type, const %s newval);\n", type_str[i].var_name, type_str[i].type);
}
nitems = sizeof(extra_handlers) / sizeof(extra_handlers[0]);
for (i = 0; i < nitems; i++) {
fprintf(internal_header, "static NI_err call_%s_handlers(NewIfcObj obj, enum NewIfc_handler_type type%s);\n", extra_handlers[i].name, extra_handlers[i].args ? extra_handlers[i].args : "");
}
fputs("\n", internal_header);
fputs("#endif\n", internal_header);
fclose(internal_header);
......@@ -582,7 +640,7 @@ main(int argc, char **argv)
for (i = 0; i < nitems; i++) {
if (attributes[i].impl == attr_impl_global || attributes[i].impl == attr_impl_global_custom_setter) {
if (attributes[i].inherit)
fprintf(c_code," dst->%s = src->%s;\n", attributes[i].name, attributes[i].name);
fprintf(c_code," dst->%s = src->%s;\n", member_name(i), member_name(i));
}
}
fputs(" return NewIfc_error_none;\n"
......@@ -591,7 +649,7 @@ main(int argc, char **argv)
nitems = sizeof(type_str) / sizeof(type_str[0]);
for (i = 0; i < nitems; i++) {
fprintf(c_code, "static NI_err\n"
"call_%s_change_handlers(NewIfcObj obj, enum NewIfc_attribute type, const %s newval)\n"
"call_%s_change_handlers(NewIfcObj obj, enum NewIfc_handler_type type, const %s newval)\n"
"{\n"
" if (obj->handlers == NULL)\n"
" return NewIfc_error_none;\n"
......@@ -609,6 +667,27 @@ main(int argc, char **argv)
"}\n\n", type_str[i].var_name, type_str[i].type, type_str[i].var_name);
}
nitems = sizeof(extra_handlers) / sizeof(extra_handlers[0]);
for (i = 0; i < nitems; i++) {
fprintf(c_code, "static NI_err\n"
"call_%s_handlers(NewIfcObj obj, enum NewIfc_handler_type type%s)\n"
"{\n"
" if (obj->handlers == NULL)\n"
" return NewIfc_error_none;\n"
" struct NewIfc_handler **head = bsearch(&type, obj->handlers, obj->handlers_sz, sizeof(obj->handlers[0]), handler_bsearch_compar);\n"
" if (head == NULL)\n"
" return NewIfc_error_none;\n"
" struct NewIfc_handler *h = *head;\n"
" while (h != NULL) {\n"
" NI_err ret = h->%s(obj%s, h->cbdata);\n"
" if (ret != NewIfc_error_none)\n"
" return ret;\n"
" h = h->next;\n"
" }\n"
" return NewIfc_error_none;\n"
"}\n\n", extra_handlers[i].name, extra_handlers[i].args ? extra_handlers[i].args : "", extra_handlers[i].name, extra_handlers[i].params ? extra_handlers[i].params : "");
}
nitems = sizeof(attributes) / sizeof(attributes[0]);
for (i = 0; i < nitems; i++) {
attribute_functions(i, c_code, attributes[i].name);
......
......@@ -46,7 +46,6 @@ label_set(NewIfcObj obj, int attr, ...)
}
free(l->text);
l->text = buf;
obj->min_width = sz;
break;
default:
ret = NewIfc_error_not_implemented;
......@@ -77,26 +76,6 @@ label_get(NewIfcObj obj, int attr, ...)
return ret;
}
static NI_err
label_copy(NewIfcObj old, NewIfcObj *newobj)
{
struct label **newl = (struct label **)newobj;
struct label *oldl = (struct label *)old;
*newl = malloc(sizeof(struct label));
if (*newl == NULL)
return NewIfc_error_allocation_failure;
memcpy(*newl, oldl, sizeof(struct label));
assert(oldl->text);
(*newl)->text = strdup(oldl->text);
if ((*newl)->text == NULL) {
free(*newl);
return NewIfc_error_allocation_failure;
}
return NewIfc_error_none;
}
static NI_err
label_do_render(NewIfcObj obj, struct NewIfc_render_context *ctx)
{
......@@ -148,7 +127,7 @@ NewIFC_label(NewIfcObj parent, NewIfcObj *newobj)
newl = calloc(1, sizeof(struct label));
if (newl == NULL)
return NewIfc_error_allocation_failure;
NI_err ret = NI_setup_globals(newl, parent);
NI_err ret = NI_setup_globals(&newl->api, parent);
if (ret != NewIfc_error_none) {
free(newl);
return ret;
......@@ -160,10 +139,9 @@ NewIFC_label(NewIfcObj parent, NewIfcObj *newobj)
}
newl->api.get = &label_get;
newl->api.set = &label_set;
newl->api.copy = &label_copy;
newl->api.do_render = &label_do_render;
newl->api.destroy = &label_destroy;
ret = NI_set_min_height(newl, 1);
ret = NI_set_min_height(&newl->api, 1);
if (ret != NewIfc_error_none) {
free(newl->text);
free(newl);
......@@ -193,10 +171,9 @@ void test_label(CuTest *ct)
CuAssertPtrNotNull(ct, obj);
CuAssertPtrNotNull(ct, obj->get);
CuAssertPtrNotNull(ct, obj->set);
CuAssertPtrNotNull(ct, obj->copy);
CuAssertPtrNotNull(ct, obj->do_render);
CuAssertTrue(ct, obj->width == 80);
CuAssertTrue(ct, obj->height == 25);
CuAssertTrue(ct, obj->width == NI_GROW);
CuAssertTrue(ct, obj->height == NI_GROW);
CuAssertTrue(ct, obj->min_width == 0);
CuAssertTrue(ct, obj->min_height == 1);
CuAssertTrue(ct, obj->focus == false);
......
......@@ -2,33 +2,6 @@
#include "newifc.h"
NI_err
NI_copy(NewIfcObj obj, NewIfcObj *newobj) {
if (newobj == NULL) {
return NewIfc_error_invalid_arg;
}
*newobj = NULL;
if (obj == NULL) {
return NewIfc_error_invalid_arg;
}
NI_err ret = NewIfc_error_none;
if (NI_set_locked(obj, true)) {
ret = obj->copy(obj, newobj);
if (ret == NewIfc_error_none) {
(*newobj)->root = NULL;
(*newobj)->parent = NULL;
(*newobj)->higher_peer = NULL;
(*newobj)->lower_peer = NULL;
(*newobj)->top_child = NULL;
(*newobj)->bottom_child = NULL;
}
NI_set_locked(obj, false);
}
else
ret = NewIfc_error_lock_failed;
return ret;
}
static NI_err
NI_walk_children_recurse(NewIfcObj obj, bool top_down, NI_err (*cb)(NewIfcObj obj, void *cb_data), void *cbdata)
{
......@@ -120,7 +93,7 @@ NI_install_handler(NewIfcObj obj, struct NewIfc_handler *handler)
// would be best, but even a linear search for it would likely be
// better.
size_t new_sz = obj->handlers_sz + 1;
struct NewIfc_handler ***na = realloc(obj->handlers, new_sz * sizeof(obj->handlers[0]));
struct NewIfc_handler **na = realloc(obj->handlers, new_sz * sizeof(obj->handlers[0]));
if (na == NULL)
return NewIfc_error_allocation_failure;
obj->handlers = na;
......@@ -162,7 +135,7 @@ NI_inner_width(NewIfcObj obj, uint16_t *width)
*width = 0;
return NewIfc_error_invalid_arg;
}
uint32_t both = (uint32_t)obj->left_pad + obj->right_pad;
int32_t both = (int32_t)obj->left_pad + obj->right_pad;
if (both > obj->width) {
*width = 0;
return NewIfc_error_wont_fit;
......@@ -180,7 +153,7 @@ NI_inner_height(NewIfcObj obj, uint16_t *height)
*height = 0;
return NewIfc_error_invalid_arg;
}
uint32_t both = (uint32_t)obj->top_pad + obj->bottom_pad;
int32_t both = (int32_t)obj->top_pad + obj->bottom_pad;
if (both > obj->height) {
*height = 0;
return NewIfc_error_wont_fit;
......@@ -256,36 +229,36 @@ NI_get_top_left(NewIfcObj obj, uint16_t width, uint16_t height, uint16_t *xpos,
*ypos = 0;
break;
case NewIfc_align_top_middle:
*xpos = (obj->width - width) / 2;
*xpos = (obj->layout_size.width - width) / 2;
*ypos = 0;
break;
case NewIfc_align_top_right:
*xpos = obj->width - width;
*xpos = obj->layout_size.width - width;
*ypos = 0;
break;
case NewIfc_align_middle_left:
*xpos = 0;
*ypos = (obj->height - height) / 2;
*ypos = (obj->layout_size.height - height) / 2;
break;
case NewIfc_align_middle:
*xpos = (obj->width - width) / 2;
*ypos = (obj->height - height) / 2;
*xpos = (obj->layout_size.width - width) / 2;
*ypos = (obj->layout_size.height - height) / 2;
break;
case NewIfc_align_middle_right:
*xpos = obj->width - width;
*ypos = (obj->height - height) / 2;
*xpos = obj->layout_size.width - width;
*ypos = (obj->layout_size.height - height) / 2;
break;
case NewIfc_align_bottom_left:
*xpos = 0;
*ypos = obj->height - height;
*ypos = obj->layout_size.height - height;
break;
case NewIfc_align_bottom_middle:
*xpos = (obj->width - width) / 2;
*ypos = obj->height - height;
*xpos = (obj->layout_size.width - width) / 2;
*ypos = obj->layout_size.height - height;
break;
case NewIfc_align_bottom_right:
*xpos = obj->width - width;
*ypos = obj->height - height;
*xpos = obj->layout_size.width - width;
*ypos = obj->layout_size.height - height;
break;
}
return NewIfc_error_none;
......@@ -352,20 +325,72 @@ NI_check_new_min_width(NewIfcObj obj, uint16_t new_width, void *cbdata)
uint16_t old_width;
NI_err ret;
(void)cbdata;
ret = NI_get_min_width(obj, &old_width);
if (ret != NewIfc_error_none)
return ret;
// Lowering min width is always fine.
if (new_width <= old_width)
if (new_width <= old_width) {
if (new_width >= 0 && obj->width == NI_SHRINK)
NI_set_layout_width(obj, new_width);
return NewIfc_error_none;
}
// If there's no parent, it's fine
if (obj->parent == NULL) {
if (new_width >= 0 && obj->width == NI_SHRINK)
NI_set_layout_width(obj, new_width);
return NewIfc_error_none;
if (obj->parent != NULL) {
}
else {
// If it fits in the parent, it's fine
if (obj->parent->child_width >= new_width)
if (obj->parent->child_width >= new_width) {
if (new_width >= 0 && obj->width == NI_SHRINK)
NI_set_layout_width(obj, new_width);
return NewIfc_error_none;
}
}
// Now, we know it doesn't fit where it is without adjusting
// *something* we need a way to know if layout would succeed
// with this new value... very tricky.
// TODO
return NewIfc_error_wont_fit;
}
// Lowering a min width/height is always fine.
// Raising a min width/height MAY NOT BE fine.
static NI_err
NI_check_new_min_height(NewIfcObj obj, uint16_t new_height, void *cbdata)
{
uint16_t old_height;
NI_err ret;
(void)cbdata;
ret = NI_get_min_height(obj, &old_height);
if (ret != NewIfc_error_none)
return ret;
// Lowering min height is always fine.
if (new_height <= old_height) {
if (new_height >= 0 && obj->height == NI_SHRINK)
NI_set_layout_height(obj, new_height);
return NewIfc_error_none;
}
if (obj->parent == NULL) {
if (new_height >= 0 && obj->height == NI_SHRINK)
NI_set_layout_height(obj, new_height);
return NewIfc_error_none;
}
else {
// If it fits in the parent, it's fine
if (obj->parent->child_height >= new_height) {
if (new_height >= 0 && obj->height == NI_SHRINK)
NI_set_layout_height(obj, new_height);
return NewIfc_error_none;
}
}
// Now, we know it doesn't fit where it is without adjusting
// *something* we need a way to know if layout would succeed
// with this new value... very tricky.
// TODO
return NewIfc_error_wont_fit;
}
......@@ -384,12 +409,16 @@ NI_setup_globals(NewIfcObj obj, NewIfcObj parent)
parent->top_child = obj;
if (parent->bottom_child == NULL)
parent->bottom_child = obj;
obj->width = parent->child_width;
obj->height = parent->child_height;
obj->width = NI_GROW;
obj->height = NI_GROW;
ret = NI_add_min_width_handler(obj, NI_check_new_min_width, NULL);
ret = NI_add_min_height_handler(obj, NI_check_new_min_height, NULL);
}
else
else {
obj->root = obj;
ret = NI_add_min_width_handler(obj, NI_check_new_min_width, NULL);
ret = NI_add_min_height_handler(obj, NI_check_new_min_height, NULL);
}
return NewIfc_error_none;
}
......@@ -410,3 +439,214 @@ set_vmem_cell(struct vmem_cell *cell, uint32_t fg, uint32_t bg, uint8_t ch, uint
la |= (cell->legacy_attr & 0x80);
cell->legacy_attr = la;
}
NI_err
NI_set_width(NewIfcObj obj, const int32_t value) {
NI_err ret;
if (obj == NULL)
return NewIfc_error_invalid_arg;
if (value > UINT16_MAX || (value < 0 && value != NI_GROW && value != NI_SHRINK))
return NewIfc_error_out_of_range;
if (NI_set_locked(obj, true) == NewIfc_error_none) {
ret = call_int32_change_handlers(obj, NewIfc_width, value);
if (ret != NewIfc_error_none) {
NI_set_locked(obj, false);
return ret;
}
ret = obj->set(obj, NewIfc_width, value);
if (ret == NewIfc_error_not_implemented) {
obj->width = value;
if (value >= 0)
NI_set_min_width(obj, obj->width);
if (obj->parent && value == NI_GROW)
NI_set_layout_width(obj, obj->parent->child_width - obj->xpos);
else if (value >= 0)
NI_set_layout_width(obj, value);
ret = NewIfc_error_none;
}
NI_set_locked(obj, false);
}
else
ret = NewIfc_error_lock_failed;
return ret;
}
NI_err
NI_set_height(NewIfcObj obj, const int32_t value) {
NI_err ret;
if (obj == NULL)
return NewIfc_error_invalid_arg;
if (value > UINT16_MAX || (value < 0 && value != NI_GROW && value != NI_SHRINK))
return NewIfc_error_out_of_range;
if (NI_set_locked(obj, true) == NewIfc_error_none) {
ret = call_int32_change_handlers(obj, NewIfc_height, value);
if (ret != NewIfc_error_none) {
NI_set_locked(obj, false);
return ret;
}
ret = obj->set(obj, NewIfc_height, value);
if (ret == NewIfc_error_not_implemented) {
obj->height = value;
if (value >= 0)
NI_set_min_height(obj, obj->height);
if (obj->parent && (value == NI_GROW || value >= 0))
NI_set_layout_height(obj, obj->parent->child_height - obj->ypos);
else if (value >= 0)
NI_set_layout_height(obj, value);
ret = NewIfc_error_none;
}
NI_set_locked(obj, false);
}
else
ret = NewIfc_error_lock_failed;
return ret;
}
static NI_err do_layout_set_minsize_recurse(NewIfcObj obj, struct lo_size *ms);
static NI_err
do_layout_recurse_nonnull(NewIfcObj obj, struct lo_size *ms)
{
if (obj)
return do_layout_set_minsize_recurse(obj->lower_peer, ms);
return NewIfc_error_none;
}
static NI_err
do_layout_set_minsize_recurse(NewIfcObj obj, struct lo_size *pms)
{
NI_err ret;
uint32_t news;
ret = do_layout_recurse_nonnull(obj->lower_peer, pms);
if (ret == NewIfc_error_none) {
memset(&obj->layout_min_size, 0, sizeof(obj->layout_min_size));
do_layout_recurse_nonnull(obj->top_child, &obj->layout_min_size);
}
if (ret != NewIfc_error_none)
return ret;
// This assumes the difference between width and child_width is a constant
if (obj->child_width) {
news = (uint32_t)obj->layout_min_size.width + (obj->layout_size.width - obj->child_width);
if (news > UINT16_MAX)
return NewIfc_error_wont_fit;
if (news > obj->layout_min_size.width)
obj->layout_min_size.width = news;
}
// This assumes the difference between height and child_height is a constant
if (obj->child_height) {
news = (uint32_t)obj->layout_min_size.height + (obj->layout_size.height - obj->child_height);
if (news > UINT16_MAX)
return NewIfc_error_wont_fit;
if (news > obj->layout_min_size.height)
obj->layout_min_size.height = news;
}
if (obj->min_width > obj->layout_min_size.width)
obj->layout_min_size.width = obj->min_width;
if (obj->min_height > obj->layout_min_size.height)
obj->layout_min_size.height = obj->min_height;
news = (uint32_t)obj->layout_min_size.width + obj->left_pad + obj->right_pad + obj->xpos;
if (news > UINT16_MAX)
return NewIfc_error_wont_fit;
if (news > pms->width)
pms->width = news;
news = (uint32_t)obj->layout_min_size.height + obj->left_pad + obj->right_pad + obj->ypos;
if (news > UINT16_MAX)
return NewIfc_error_wont_fit;
if (news > pms->height)
pms->height = news;
return NewIfc_error_none;
}
static NI_err
do_layout_set_size_recurse(NewIfcObj obj)
{
NI_err ret;
// First, we do ourself...
if (obj->width == NI_SHRINK) {
ret = NI_set_layout_width(obj, obj->layout_min_size.width);
if (ret != NewIfc_error_none)
return ret;
}
else if (obj->width == NI_GROW) {
if (obj->parent == NULL)
return NewIfc_error_needs_parent;
if (obj->parent->child_width < obj->xpos)
return NewIfc_error_wont_fit;
ret = NI_set_layout_width(obj, obj->parent->child_width - obj->xpos);
if (ret != NewIfc_error_none)
return ret;
}
else {
if (obj->parent->child_width < obj->width)
return NewIfc_error_wont_fit;
}
if (obj->height == NI_SHRINK) {
ret = NI_set_layout_height(obj, obj->layout_min_size.height);
if (ret != NewIfc_error_none)
return ret;
}
else if (obj->height == NI_GROW) {
if (obj->parent == NULL)
return NewIfc_error_needs_parent;
if (obj->parent->child_height < obj->xpos)
return NewIfc_error_wont_fit;
ret = NI_set_layout_height(obj, obj->parent->child_height - obj->xpos);
if (ret != NewIfc_error_none)
return ret;
}
else {
if (obj->parent->child_height < obj->height)
return NewIfc_error_wont_fit;
}
// Then, recurse peers
if (obj->higher_peer) {
ret = do_layout_set_size_recurse(obj->higher_peer);
if (ret != NewIfc_error_none)
return ret;
}
// And finally, recurse children
if (obj->bottom_child) {
ret = do_layout_set_size_recurse(obj->bottom_child);
if (ret != NewIfc_error_none)
return ret;
}
return NewIfc_error_none;
}
/*
* This walks up from every leaf, updating min width and min height, then
* walks *down* from root setting width and height (and adjusting sizers).
* It is expected that this can fail with NewIFc_error_wont_fit as it will
* be called immediately after a min_size change anywhere in the tree.
*
* The caller will restore the old value then call this again, which will
* presumably work.
*/
NI_err
NI_do_layout(NewIfcObj obj)
{
NI_err ret;
// Walk up setting minwidth and minheight
memset(&obj->root->layout_min_size, 0, sizeof(obj->root->layout_min_size));
ret = do_layout_set_minsize_recurse(obj->root, &obj->root->layout_min_size);
if (ret != NewIfc_error_none)
return ret;
// Walk down setting layout width and height.
ret = do_layout_set_size_recurse(obj->root);
if (ret != NewIfc_error_none)
return ret;
return NewIfc_error_none;
}
......@@ -126,32 +126,6 @@ rw_get(NewIfcObj obj, int attr, ...)
return ret;
}
static NI_err
rw_copy(NewIfcObj old, NewIfcObj *newobj)
{
struct root_window **newrw = (struct root_window **)newobj;
struct root_window *oldrw = (struct root_window *)old;
*newrw = malloc(sizeof(struct root_window));
if (*newrw == NULL) {
return NewIfc_error_allocation_failure;
}
memcpy(*newrw, old, sizeof(struct root_window));
(*newrw)->mtx = pthread_mutex_initializer_np(true);
(*newrw)->locks = 0;
size_t cells = (*newrw)->api.width;
cells *= (*newrw)->api.height;
(*newrw)->display = malloc(sizeof(struct vmem_cell) * cells);
if ((*newrw)->display == NULL) {
free(*newrw);
*newrw = NULL;
return NewIfc_error_allocation_failure;
}
memcpy((*newrw)->display, oldrw->display, sizeof(struct vmem_cell) * cells);
return NewIfc_error_none;
}
static NI_err
call_render_handlers(NewIfcObj obj)
{
......@@ -175,6 +149,8 @@ static NI_err
rw_do_render_recurse(NewIfcObj obj, struct NewIfc_render_context *ctx)
{
int16_t oxpos, oypos, owidth, oheight;
if (obj->hidden)
return NewIfc_error_none;
NI_err ret = call_render_handlers(obj);
if (ret != NewIfc_error_none)
return ret;
......@@ -198,10 +174,10 @@ rw_do_render_recurse(NewIfcObj obj, struct NewIfc_render_context *ctx)
// Fill padding
if (obj->top_pad || obj->bottom_pad || obj->left_pad || obj->right_pad) {
size_t c;
for (size_t y = 0; y < obj->height; y++) {
if ((y < obj->top_pad) || (y >= (obj->height - obj->bottom_pad))) {
for (size_t y = 0; y < obj->layout_size.height; y++) {
if ((y < obj->top_pad) || (y >= (obj->layout_size.height - obj->bottom_pad))) {
c = (y + ctx->ypos + obj->ypos) * ctx->dwidth;
for (size_t x = 0; x < obj->width; x++) {
for (size_t x = 0; x < obj->layout_size.width; x++) {
set_vmem_cell(&ctx->vmem[c], obj->fg_colour, obj->bg_colour, ' ', obj->font);
c++;
}
......@@ -216,7 +192,7 @@ rw_do_render_recurse(NewIfcObj obj, struct NewIfc_render_context *ctx)
}
if (obj->right_pad) {
c = (y + ctx->ypos + obj->ypos) * ctx->dwidth;
c += obj->width;
c += obj->layout_size.width;
c -= obj->right_pad;
for (size_t x = 0; x < obj->right_pad; x++) {
set_vmem_cell(&ctx->vmem[c], obj->fg_colour, obj->bg_colour, ' ', obj->font);
......@@ -233,8 +209,8 @@ rw_do_render_recurse(NewIfcObj obj, struct NewIfc_render_context *ctx)
oypos = ctx->ypos;
// Calculate this objects internal render rectangle (inside of padding)
ctx->width = obj->width - (obj->left_pad + obj->right_pad);
ctx->height = obj->height - (obj->top_pad + obj->bottom_pad);
ctx->width = obj->layout_size.width - (obj->left_pad + obj->right_pad);
ctx->height = obj->layout_size.height - (obj->top_pad + obj->bottom_pad);
ctx->xpos += obj->left_pad;
ctx->ypos += obj->top_pad;
// And render it
......@@ -279,20 +255,21 @@ rw_do_render_recurse(NewIfcObj obj, struct NewIfc_render_context *ctx)
static NI_err
rw_do_render(NewIfcObj obj, struct NewIfc_render_context *nullctx)
{
(void)nullctx;
struct root_window *rw = (struct root_window *) obj;
struct NewIfc_render_context ctx = {
.vmem = rw->display,
.dwidth = obj->width,
.dheight = obj->height,
.width = obj->width,
.height = obj->height,
.dwidth = obj->layout_size.width,
.dheight = obj->layout_size.height,
.width = obj->layout_size.width,
.height = obj->layout_size.height,
.xpos = 0,
.ypos = 0,
};
NI_err ret = rw_do_render_recurse(obj, &ctx);
if (ret == NewIfc_error_none) {
struct root_window *rw = (struct root_window *)obj;
ciolib_vmem_puttext(obj->xpos + 1, obj->ypos + 1, obj->width + obj->xpos, obj->height + obj->ypos, rw->display);
ciolib_vmem_puttext(obj->xpos + 1, obj->ypos + 1, obj->layout_size.width + obj->xpos, obj->layout_size.height + obj->ypos, rw->display);
}
return ret;
}
......@@ -321,8 +298,14 @@ NewIFC_root_window(NewIfcObj parent, NewIfcObj *newobj)
*newrw = calloc(1, sizeof(struct root_window));
if (*newrw == NULL)
return NewIfc_error_allocation_failure;
(*newrw)->mtx = pthread_mutex_initializer_np(true);
(*newrw)->api.get = rw_get;
(*newrw)->api.set = rw_set;
(*newrw)->api.do_render = &rw_do_render;
(*newrw)->api.destroy = rw_destroy;
ret = NI_setup_globals(*newobj, parent);
if (ret != NewIfc_error_none) {
pthread_mutex_destroy(&(*newrw)->mtx);
free(*newrw);
return ret;
}
......@@ -331,25 +314,18 @@ NewIFC_root_window(NewIfcObj parent, NewIfcObj *newobj)
int cf = ciolib_getfont(0);
if (cf < 0)
cf = 0;
(*newrw)->api.get = rw_get;
(*newrw)->api.set = rw_set;
(*newrw)->api.copy = rw_copy;
(*newrw)->api.do_render = &rw_do_render;
(*newrw)->api.destroy = rw_destroy;
(*newrw)->api.focus = true;
(*newrw)->api.fg_colour = ciolib_fg;
(*newrw)->api.bg_colour = ciolib_bg;
(*newrw)->api.font = cf;
(*newrw)->api.width = ti.screenwidth;
(*newrw)->api.height = ti.screenheight;
(*newrw)->api.child_width = ti.screenwidth;
(*newrw)->api.child_height = ti.screenheight;
(*newrw)->api.fill_character = ' ';
(*newrw)->api.fill_colour = ciolib_bg;
(*newrw)->api.fill_character_colour = ciolib_fg;
(*newrw)->api.fill_font = cf;
(*newrw)->mtx = pthread_mutex_initializer_np(true);
NI_set_focus(&(*newrw)->api, true);
NI_set_fg_color(&(*newrw)->api, ciolib_fg);
NI_set_bg_color(&(*newrw)->api, ciolib_bg);
NI_set_font(&(*newrw)->api, cf);
NI_set_width(&(*newrw)->api, ti.screenwidth);
NI_set_height(&(*newrw)->api, ti.screenheight);
NI_set_child_width(&(*newrw)->api, ti.screenwidth);
NI_set_child_height(&(*newrw)->api, ti.screenheight);
NI_set_fill_character(&(*newrw)->api, ' ');
NI_set_fill_colour(&(*newrw)->api, ciolib_bg);
NI_set_fill_character_colour(&(*newrw)->api, ciolib_fg);
NI_set_fill_font(&(*newrw)->api, cf);
size_t cells = ti.screenwidth;
cells *= ti.screenheight;
......@@ -375,12 +351,11 @@ void test_root_window(CuTest *ct)
CuAssertPtrNotNull(ct, obj);
CuAssertPtrNotNull(ct, obj->get);
CuAssertPtrNotNull(ct, obj->set);
CuAssertPtrNotNull(ct, obj->copy);
CuAssertPtrNotNull(ct, obj->do_render);
CuAssertTrue(ct, obj->width == 80);
CuAssertTrue(ct, obj->height == 25);
CuAssertTrue(ct, obj->min_width == 0);
CuAssertTrue(ct, obj->min_height == 0);
CuAssertTrue(ct, obj->min_width == 80);
CuAssertTrue(ct, obj->min_height == 25);
CuAssertTrue(ct, obj->focus == true);
CuAssertTrue(ct, obj->get(obj, NewIfc_locked, &b) == NewIfc_error_none && !b);
CuAssertTrue(ct, obj->get(obj, NewIfc_locked_by_me, &b) == NewIfc_error_none && !b);
......
#include <assert.h>
#include <stdarg.h>
#include <stdlib.h> // malloc()/free()
#define CIOLIB_NO_MACROS
#include "ciolib.h"
#include "genwrap.h"
#include "strwrap.h"
#include "threadwrap.h"
#include "newifc.h"
#include "newifc_internal.h"
#ifdef BUILD_TESTS
#include "CuTest.h"
#endif
struct sizer {
struct newifc_api api;
uint8_t *weights;
uint8_t group_size;
};
static size_t
count_children(NewIfcObj obj)
{
size_t ret = 0;
for (obj = obj->top_child; obj; obj = obj->lower_peer)
ret++;
return ret;
}
static NI_err
sizer_set(NewIfcObj obj, int attr, ...)
{
struct sizer *s = (struct sizer *)obj;
NI_err ret = NewIfc_error_none;
va_list ap;
size_t c;
size_t idx;
uint8_t olds;
uint8_t *neww;
va_start(ap, attr);
switch (attr) {
case NewIfc_group_size:
olds = s->group_size;
s->group_size = va_arg(ap, int);
if (s->group_size == 0) {
s->group_size = olds;
return NewIfc_error_out_of_range;
}
neww = realloc(s->weights, s->group_size * sizeof(s->weights[0]));
if (neww == NULL) {
s->group_size = olds;
return NewIfc_error_allocation_failure;
}
s->weights = neww;
if (s->group_size > olds) {
for (uint8_t i = olds; i < s->group_size; i++)
s->weights[i] = 0;
}
// TODO: Trigger new layout
break;
case NewIfc_weight:
c = count_children(obj);
idx = c % s->group_size;
s->weights[idx] = va_arg(ap, int);
break;
default:
ret = NewIfc_error_not_implemented;
break;
}
va_end(ap);
return ret;
}
static NI_err
sizer_get(NewIfcObj obj, int attr, ...)
{
struct sizer *s = (struct sizer *)obj;
NI_err ret = NewIfc_error_none;
va_list ap;
size_t c;
size_t idx;
va_start(ap, attr);
switch (attr) {
case NewIfc_group_size:
*(va_arg(ap, bool *)) = s->group_size;
break;
case NewIfc_weight:
c = count_children(obj);
idx = c % s->group_size;
*(va_arg(ap, uint8_t *)) = s->weights[idx];
break;
default:
ret = NewIfc_error_not_implemented;
break;
}
return ret;
}
static NI_err
sizer_do_render(NewIfcObj obj, struct NewIfc_render_context *ctx)
{
(void)obj;
(void)ctx;
return NewIfc_error_none;
}
static NI_err
sizer_destroy(NewIfcObj newobj)
{
struct sizer *s = (struct sizer *)newobj;
if (s == NULL)
return NewIfc_error_invalid_arg;
free(s);
return NewIfc_error_none;
}
static NI_err
sizer_resize_width_cb(NewIfcObj obj, const uint16_t newval, void *width)
{
struct sizer *s = (struct sizer *)obj;
size_t idx;
size_t weight = 0;
size_t max_weight = 0;
uint16_t w[s->group_size];
NewIfcObj c;
memset(w, 0, sizeof(w));
// Collect min sizes of children
for (c = s->api.top_child; c; c = c->lower_peer) {
idx = (idx + 1) % s->group_size;
if (c->min_width > w[idx])
w[idx] = c->min_width;
}
// Distribute extra space by weight
size_t remain = newval;
for (idx = 0; idx < s->group_size; idx++) {
if (w[idx] > remain)
return NewIfc_error_wont_fit;
remain -= w[idx];
if (s->weights[idx] > max_weight)
max_weight = s->weights[idx];
}
if (max_weight) {
while (remain) {
if (weight == 0)
weight = max_weight;
for (idx = 0; idx < s->group_size; idx++) {
if (weight <= s->weights[idx]) {
w[idx]++;
remain--;
if (remain == 0)
break;
}
}
weight--;
}
}
// TODO: Store in magic place which is named child_width, but knows what column it's in :(
}
static NI_err
NewIFC_sizer(NewIfcObj parent, NewIfcObj *newobj)
{
struct sizer *news;
if (newobj == NULL)
return NewIfc_error_invalid_arg;
*newobj = NULL;
news = calloc(1, sizeof(struct sizer));
if (news == NULL)
return NewIfc_error_allocation_failure;
NI_err ret = NI_setup_globals(&news->api, parent);
if (ret != NewIfc_error_none) {
free(news);
return ret;
}
news->api.get = &sizer_get;
news->api.set = &sizer_set;
news->api.do_render = &sizer_do_render;
news->api.destroy = &sizer_destroy;
news->group_size = 1;
news->weights = calloc(1, sizeof(news->weights[0]));
if (news->weights == NULL) {
free(news);
return NewIfc_error_allocation_failure;
}
*newobj = (NewIfcObj)news;
return NewIfc_error_none;
}
#ifdef BUILD_TESTS
void test_sizer(CuTest *ct)
{
// TODO: Write tests...
}
#endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment