diff --git a/src/newifc/alltests.c b/src/newifc/alltests.c index d05957c4d1ea13133b35e1e28eeb51b9a9c83af3..b1ef0c1c38b2736a66a0bd3b7d1b84bbab533a70 100644 --- a/src/newifc/alltests.c +++ b/src/newifc/alltests.c @@ -2,13 +2,15 @@ #include "CuTest.h" -CuSuite* root_window_get_test_suite(); +void test_root_window(CuTest *ct); +void test_label(CuTest *ct); void RunAllTests(void) { CuString *output = CuStringNew(); CuSuite* suite = CuSuiteNew(); - CuSuiteAddSuite(suite, root_window_get_test_suite()); + SUITE_ADD_TEST(suite, test_root_window); + SUITE_ADD_TEST(suite, test_label); CuSuiteRun(suite); CuSuiteSummary(suite, output); diff --git a/src/newifc/genapi.c b/src/newifc/genapi.c index 815cb7dfd0820b9fb66b0b13ad3de16ebc657281..635eea4243693576bcfa50003461ffd192b50342 100644 --- a/src/newifc/genapi.c +++ b/src/newifc/genapi.c @@ -17,6 +17,7 @@ struct objtype_info { const struct objtype_info objtypes[] = { {"root_window", 0}, + {"label", 1}, }; enum attribute_types { @@ -58,36 +59,41 @@ struct attribute_info { enum attribute_types type; enum attribute_impl impl; int read_only; + int no_event; }; const struct attribute_info attributes[] = { - {"bottomchild", NI_attr_type_NewIfcObj, attr_impl_global, 1}, - {"child_height", NI_attr_type_uint16_t, attr_impl_global, 1}, - {"child_width", NI_attr_type_uint16_t, attr_impl_global, 1}, - {"child_xpos", NI_attr_type_uint16_t, attr_impl_global, 1}, - {"child_ypos", NI_attr_type_uint16_t, attr_impl_global, 1}, - {"fill_character", NI_attr_type_uint32_t, attr_impl_global, 0}, - {"fill_character_colour", NI_attr_type_uint32_t, attr_impl_global, 0}, - {"fill_colour", NI_attr_type_uint32_t, attr_impl_global, 0}, - {"fill_font", NI_attr_type_uint8_t, attr_impl_global, 0}, - {"focus", NI_attr_type_bool, attr_impl_global_custom_setter, 0}, - {"height", NI_attr_type_uint16_t, attr_impl_global, 0}, - {"hidden", NI_attr_type_bool, attr_impl_global, 1}, - {"higherpeer", NI_attr_type_NewIfcObj, attr_impl_global, 1}, - {"last_error", NI_attr_type_NI_err, attr_impl_global, 1}, - {"locked", NI_attr_type_bool, attr_impl_root, 0}, - {"locked_by_me", NI_attr_type_bool, attr_impl_root, 1}, - {"lowerpeer", NI_attr_type_NewIfcObj, attr_impl_global, 1}, - {"min_height", NI_attr_type_uint16_t, attr_impl_global, 1}, - {"min_width", NI_attr_type_uint16_t, attr_impl_global, 1}, - {"parent", NI_attr_type_NewIfcObj, attr_impl_global, 1}, - {"root", NI_attr_type_NewIfcObj, attr_impl_global, 1}, - {"topchild", NI_attr_type_NewIfcObj, attr_impl_global, 1}, - {"type", NI_attr_type_NewIfc_object, attr_impl_global, 1}, - {"width", NI_attr_type_uint16_t, attr_impl_global, 0}, - {"xpos", NI_attr_type_uint16_t, attr_impl_global, 0}, - {"ypos", NI_attr_type_uint16_t, attr_impl_global, 0}, + {"bg_colour", NI_attr_type_uint32_t, attr_impl_global, 0, 0}, + {"bottomchild", NI_attr_type_NewIfcObj, attr_impl_global, 1, 0}, + {"child_height", NI_attr_type_uint16_t, attr_impl_global, 1, 0}, + {"child_width", NI_attr_type_uint16_t, attr_impl_global, 1, 0}, + {"child_xpos", NI_attr_type_uint16_t, attr_impl_global, 1, 0}, + {"child_ypos", NI_attr_type_uint16_t, attr_impl_global, 1, 0}, + {"fg_colour", NI_attr_type_uint32_t, attr_impl_global, 0, 0}, + {"fill_character", NI_attr_type_uint8_t, attr_impl_global, 0, 0}, + {"fill_character_colour", NI_attr_type_uint32_t, attr_impl_global, 0, 0}, + {"fill_colour", NI_attr_type_uint32_t, attr_impl_global, 0, 0}, + {"fill_font", NI_attr_type_uint8_t, attr_impl_global, 0, 0}, + {"focus", NI_attr_type_bool, attr_impl_global_custom_setter, 0, 0}, + {"font", NI_attr_type_uint8_t, attr_impl_global, 0, 0}, + {"height", NI_attr_type_uint16_t, attr_impl_global, 0, 0}, + {"hidden", NI_attr_type_bool, attr_impl_global, 1, 0}, + {"higherpeer", NI_attr_type_NewIfcObj, attr_impl_global, 1, 0}, + {"last_error", NI_attr_type_NI_err, attr_impl_global, 1, 0}, + {"locked", NI_attr_type_bool, attr_impl_root, 0, 1}, + {"locked_by_me", NI_attr_type_bool, attr_impl_root, 1, 1}, + {"lowerpeer", NI_attr_type_NewIfcObj, attr_impl_global, 1, 0}, + {"min_height", NI_attr_type_uint16_t, attr_impl_global, 1, 0}, + {"min_width", NI_attr_type_uint16_t, attr_impl_global, 1, 0}, + {"parent", NI_attr_type_NewIfcObj, attr_impl_global, 1, 0}, + {"root", NI_attr_type_NewIfcObj, attr_impl_global, 1, 0}, + {"text", NI_attr_type_charptr, attr_impl_object, 0, 0}, + {"topchild", NI_attr_type_NewIfcObj, attr_impl_global, 1, 0}, + {"type", NI_attr_type_NewIfc_object, attr_impl_global, 1, 0}, + {"width", NI_attr_type_uint16_t, attr_impl_global, 0, 0}, + {"xpos", NI_attr_type_uint16_t, attr_impl_global, 0, 0}, + {"ypos", NI_attr_type_uint16_t, attr_impl_global, 0, 0}, }; struct attribute_alias { @@ -98,6 +104,8 @@ struct attribute_alias { const struct attribute_alias aliases[] = { {"fill_colour", "fill_color"}, {"fill_character_colour", "fill_character_color"}, + {"fg_colour", "fg_color"}, + {"bg_colour", "bg_color"}, }; struct error_info { @@ -154,17 +162,19 @@ attribute_functions(size_t i, FILE *c_code, const char *alias) " NI_err ret;\n" " if (obj == NULL)\n" " return NewIfc_error_invalid_arg;\n" - " if (NI_set_locked(obj, true)) {\n" - " ret = call_%s_change_handlers(obj, NewIfc_%s, value);\n" - " if (ret != NewIfc_error_none)\n" - " return ret;\n" - " ret = obj->set(obj, NewIfc_%s, value);\n" + " if (NI_set_locked(obj, true)) {\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" + " if (ret != NewIfc_error_none)\n" + " return ret;\n", type_str[attributes[i].type].var_name, attributes[i].name); + } + fprintf(c_code, " ret = obj->set(obj, NewIfc_%s, value);\n" " NI_set_locked(obj, false);\n" " }\n" " else\n" " ret = NewIfc_error_lock_failed;\n" " return ret;\n" - "}\n\n", alias, type_str[attributes[i].type].type, type_str[attributes[i].type].var_name, attributes[i].name, attributes[i].name); + "}\n\n", attributes[i].name); } fprintf(c_code, "NI_err\n" @@ -190,8 +200,13 @@ attribute_functions(size_t i, FILE *c_code, const char *alias) " NI_err ret;\n" " if (obj == NULL)\n" " return NewIfc_error_invalid_arg;\n" - " if (NI_set_locked(obj, true)) {\n" - " ret = obj->set(obj, NewIfc_%s, value);\n" + " if (NI_set_locked(obj, true)) {\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" + " if (ret != NewIfc_error_none)\n" + " return ret;\n", type_str[attributes[i].type].var_name, attributes[i].name); + } + fprintf(c_code, " ret = obj->set(obj, NewIfc_%s, value);\n" " if (ret != NewIfc_error_none && obj->last_error != NewIfc_error_not_implemented) {\n" " obj->%s = value;\n" " obj->last_error = NewIfc_error_none;\n" @@ -201,7 +216,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", attributes[i].name, attributes[i].name); } // Fall-through @@ -250,27 +265,29 @@ attribute_functions(size_t i, FILE *c_code, const char *alias) "}\n\n", alias, type_str[attributes[i].type].type, attributes[i].name); break; } - fprintf(c_code, "NI_err\n" - "NI_add_%s_handler(NewIfcObj obj, NI_err (*handler)(NewIfcObj obj, %s newval, void *cbdata), void *cbdata)\n" - "{\n" - " NI_err ret;\n" - " if (obj == NULL || handler == NULL)\n" - " return NewIfc_error_invalid_arg;\n" - " if (NI_set_locked(obj, true)) {\n" - " struct NewIfc_handler *h = malloc(sizeof(struct NewIfc_handler));\n" - " if (h == NULL)\n" - " return NewIfc_error_allocation_failure;\n" - " h->on_%s_change = handler;\n" - " h->cbdata = cbdata;\n" - " h->event = NewIfc_on_%s_change;\n" - " h->next = NULL;\n" - " ret = NI_install_handler(obj, h);\n" - " NI_set_locked(obj, false);\n" - " }\n" - " else\n" - " ret = NewIfc_error_lock_failed;\n" - " return ret;\n" - "}\n\n", alias, type_str[attributes[i].type].type, type_str[attributes[i].type].var_name, attributes[i].name); + if (!attributes[i].no_event) { + fprintf(c_code, "NI_err\n" + "NI_add_%s_handler(NewIfcObj obj, NI_err (*handler)(NewIfcObj obj, %s newval, void *cbdata), void *cbdata)\n" + "{\n" + " NI_err ret;\n" + " if (obj == NULL || handler == NULL)\n" + " return NewIfc_error_invalid_arg;\n" + " if (NI_set_locked(obj, true)) {\n" + " struct NewIfc_handler *h = malloc(sizeof(struct NewIfc_handler));\n" + " if (h == NULL)\n" + " return NewIfc_error_allocation_failure;\n" + " h->on_%s_change = handler;\n" + " h->cbdata = cbdata;\n" + " h->event = NewIfc_on_%s_change;\n" + " h->next = NULL;\n" + " ret = NI_install_handler(obj, h);\n" + " NI_set_locked(obj, false);\n" + " }\n" + " else\n" + " ret = NewIfc_error_lock_failed;\n" + " return ret;\n" + "}\n\n", alias, type_str[attributes[i].type].type, type_str[attributes[i].type].var_name, attributes[i].name); + } } int @@ -318,21 +335,21 @@ main(int argc, char **argv) fputs("#define NI_TRANSPARENT UINT32_MAX\n" "#define NI_BLACK UINT32_C(0)\n" - "#define NI_BLUE UINT32_C(0x0000A8)\n" - "#define NI_GREEN UINT32_C(0x00A800)\n" - "#define NI_CYAN UINT32_C(0x00A8A8)\n" - "#define NI_RED UINT32_C(0xA80000)\n" - "#define NI_MAGENTA UINT32_C(0xA800A8)\n" - "#define NI_BROWN UINT32_C(0xA85400)\n" - "#define NI_LIGHTGRAY UINT32_C(0xA8A8A8)\n" - "#define NI_DARKGRAY UINT32_C(0x545454)\n" - "#define NI_LIGHTBLUE UINT32_C(0x5454FF)\n" - "#define NI_LIGHTGREEN UINT32_C(0x54FF54)\n" - "#define NI_LIGHTCYAN UINT32_C(0x54FFFF)\n" - "#define NI_LIGHTRED UINT32_C(0xFF5454)\n" - "#define NI_LIGHTMAGENTA UINT32_C(0xFF54FF)\n" - "#define NI_YELLOW UINT32_C(0xFFFF54)\n" - "#define NI_WHITE UINT32_C(0xFFFFFF)\n\n", header); + "#define NI_BLUE UINT32_C(0x800000A8)\n" + "#define NI_GREEN UINT32_C(0x8000A800)\n" + "#define NI_CYAN UINT32_C(0x8000A8A8)\n" + "#define NI_RED UINT32_C(0x80A80000)\n" + "#define NI_MAGENTA UINT32_C(0x80A800A8)\n" + "#define NI_BROWN UINT32_C(0x80A85400)\n" + "#define NI_LIGHTGRAY UINT32_C(0x80A8A8A8)\n" + "#define NI_DARKGRAY UINT32_C(0x80545454)\n" + "#define NI_LIGHTBLUE UINT32_C(0x805454FF)\n" + "#define NI_LIGHTGREEN UINT32_C(0x8054FF54)\n" + "#define NI_LIGHTCYAN UINT32_C(0x8054FFFF)\n" + "#define NI_LIGHTRED UINT32_C(0x80FF5454)\n" + "#define NI_LIGHTMAGENTA UINT32_C(0x80FF54FF)\n" + "#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("NI_err NI_create(enum NewIfc_object obj, NewIfcObj parent, NewIfcObj *newobj);\n", header); @@ -342,9 +359,10 @@ main(int argc, char **argv) nitems = sizeof(attributes) / sizeof(attributes[0]); for (i = 0; i < nitems; i++) { if (!attributes[i].read_only) { - fprintf(header, "NI_err NI_add_%s_handler(NewIfcObj obj, NI_err (*handler)(NewIfcObj obj, %s newval, void *cbdata), void *cbdata);\n", attributes[i].name, type_str[attributes[i].type].type); fprintf(header, "NI_err NI_set_%s(NewIfcObj obj, %s value);\n", attributes[i].name, type_str[attributes[i].type].type); } + if (!attributes[i].no_event) + fprintf(header, "NI_err NI_add_%s_handler(NewIfcObj obj, NI_err (*handler)(NewIfcObj obj, %s newval, void *cbdata), void *cbdata);\n", attributes[i].name, type_str[attributes[i].type].type); fprintf(header, "NI_err NI_get_%s(NewIfcObj obj, %s* value);\n", attributes[i].name, type_str[attributes[i].type].type); } nitems = sizeof(aliases) / sizeof(aliases[0]); @@ -353,7 +371,8 @@ main(int argc, char **argv) if (!attributes[a].read_only) { fprintf(header, "NI_err NI_set_%s(NewIfcObj obj, %s value);\n", aliases[i].alias_name, type_str[attributes[a].type].type); } - fprintf(header, "NI_err NI_add_%s_handler(NewIfcObj obj, NI_err (*handler)(NewIfcObj obj, %s newval, void *cbdata), void *cbdata);\n", aliases[i].alias_name, type_str[attributes[a].type].type); + if (!attributes[i].no_event) + fprintf(header, "NI_err NI_add_%s_handler(NewIfcObj obj, NI_err (*handler)(NewIfcObj obj, %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); } fputs("\n#endif\n", header); @@ -372,6 +391,8 @@ main(int argc, char **argv) fputs("#ifndef NEWIFC_INTERNAL_H\n" "#define NEWIFC_INTERNAL_H\n\n", internal_header); + fputs("#include \"ciolib.h\"\n\n", internal_header); + fputs("enum NewIfc_event_handlers {\n", internal_header); nitems = sizeof(attributes) / sizeof(attributes[0]); for (i = 0; i < nitems; i++) { @@ -399,10 +420,21 @@ main(int argc, char **argv) " enum NewIfc_event_handlers event;\n" "};\n\n", internal_header); + fputs("struct NewIfc_render_context {\n" + " struct vmem_cell *vmem;\n" + " uint16_t dwidth;\n" + " uint16_t dheight;\n" + " uint16_t width;\n" + " uint16_t height;\n" + " uint16_t xpos;\n" + " uint16_t ypos;\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" " struct NewIfc_handler **handlers;\n" " NewIfcObj root;\n" " NewIfcObj parent;\n" @@ -413,6 +445,8 @@ main(int argc, char **argv) " size_t handlers_sz;\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" " NI_err last_error;\n" " uint16_t height;\n" @@ -427,6 +461,7 @@ main(int argc, char **argv) " uint16_t child_ypos;\n" " uint8_t fill_character;\n" " uint8_t fill_font;\n" + " uint8_t font;\n" " unsigned focus:1;\n" " unsigned hidden:1;\n" "};\n\n", internal_header); @@ -454,9 +489,11 @@ main(int argc, char **argv) fputs("#include \"newifc.h\"\n", c_code); fputs("#include \"newifc_internal.h\"\n", c_code); fputs("#include \"internal_macros.h\"\n", c_code); + fputs("\n", c_code); + nitems = sizeof(objtypes) / sizeof(objtypes[0]); for (i = 0; i < nitems; i++) { - fprintf(c_code, "#include \"%s.c\"\n", objtypes[i].name); + fprintf(c_code, "static NI_err NewIFC_%s(NewIfcObj parent, NewIfcObj *newobj);\n", objtypes[i].name); } fputs("\n", c_code); @@ -484,7 +521,7 @@ main(int argc, char **argv) " break;\n" " }\n", c_code); } - fprintf(c_code, " ret = NewIFC_%s(newobj);\n" + fprintf(c_code, " ret = NewIFC_%s(parent, newobj);\n" " if (ret != NewIfc_error_none) {\n" " break;\n" " }\n" @@ -517,6 +554,17 @@ main(int argc, char **argv) fputs("#include \"newifc_nongen.c\"\n\n", c_code); + fputs("static NI_err\n" + "NI_copy_globals(NewIfcObj dst, NewIfcObj src)\n" + "{\n", c_code); + nitems = sizeof(attributes) / sizeof(attributes[0]); + for (i = 0; i < nitems; i++) { + if (attributes[i].impl == attr_impl_global || attributes[i].impl == attr_impl_global_custom_setter) + fprintf(c_code," dst->%s = src->%s;\n", attributes[i].name, attributes[i].name); + } + fputs(" return NewIfc_error_none;\n" + "}\n\n", c_code); + nitems = sizeof(type_str) / sizeof(type_str[0]); for (i = 0; i < nitems; i++) { fprintf(c_code, "NI_err\n" @@ -549,6 +597,11 @@ main(int argc, char **argv) } fputs("#include \"newifc_nongen_after.c\"\n\n", c_code); + nitems = sizeof(objtypes) / sizeof(objtypes[0]); + for (i = 0; i < nitems; i++) { + fprintf(c_code, "#include \"%s.c\"\n", objtypes[i].name); + } + fputs("\n", c_code); fclose(c_code); } diff --git a/src/newifc/internal_macros.h b/src/newifc/internal_macros.h index d8eb769e83fc947a20128c0c1cd183dfec31f815..aa9481babfd918cf14347aace4c0cd4fd986c7eb 100644 --- a/src/newifc/internal_macros.h +++ b/src/newifc/internal_macros.h @@ -17,7 +17,7 @@ st->field = va_arg(ap, uint16_t); \ } while(0); -#define SET_STRING(st, field, sz_field) do { \ +#define SET_STRING(st, field) do { \ buf = strdup(va_arg(ap, const char *)); \ if (buf == NULL) { \ st->api.last_error = NewIfc_error_allocation_failure; \ @@ -25,7 +25,6 @@ } \ free(st->field); \ st->field = buf; \ - st->sz_field = strlen(st->field); \ } while(0) diff --git a/src/newifc/label.c b/src/newifc/label.c new file mode 100644 index 0000000000000000000000000000000000000000..a6c17b29b34ea413e7aa01d86bf67a2de8065e93 --- /dev/null +++ b/src/newifc/label.c @@ -0,0 +1,190 @@ +#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" + +#include "internal_macros.h" + +#ifdef BUILD_TESTS +#include "CuTest.h" +#endif + +struct label { + struct newifc_api api; + char *text; +}; + +static NI_err +label_set(NewIfcObj obj, int attr, ...) +{ + struct label *l = (struct label *)obj; + SET_VARS; + + l->api.last_error = NewIfc_error_none; + va_start(ap, attr); + switch (attr) { + case NewIfc_text: + SET_STRING(l, text); + break; + default: + l->api.last_error = NewIfc_error_not_implemented; + break; + } + va_end(ap); + + return l->api.last_error; +} + +static NI_err +label_get(NewIfcObj obj, int attr, ...) +{ + struct label *l = (struct label *)obj; + GET_VARS; + + l->api.last_error = NewIfc_error_none; + va_start(ap, attr); + switch (attr) { + case NewIfc_text: + GET_STRING(l, text); + break; + default: + l->api.last_error = NewIfc_error_not_implemented; + break; + } + + return l->api.last_error; +} + +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) +{ + size_t sz = 0; + struct label *l = (struct label *) obj; + if (l->text) + sz = strlen(l->text); + // TODO: Ensure text fits... + size_t c = ctx->ypos * ctx->dwidth + ctx->xpos; + for (size_t i = 0; i < sz; i++, c++) { + if (obj->bg_colour != NI_TRANSPARENT) + ctx->vmem[c].bg = obj->bg_colour; + if (obj->fg_colour != NI_TRANSPARENT) { + ctx->vmem[c].fg = obj->fg_colour; + ctx->vmem[c].font = obj->font; + ctx->vmem[c].ch = l->text[i]; + } + } + return NewIfc_error_none; +} + +static NI_err +NewIFC_label(NewIfcObj parent, NewIfcObj *newobj) +{ + struct label **newl = (struct label **)newobj; + + if (parent == NULL) + return NewIfc_error_invalid_arg; + *newl = calloc(1, sizeof(struct label)); + + if (*newl == NULL) + return NewIfc_error_allocation_failure; + (*newl)->text = strdup(""); + if ((*newl)->text == NULL) { + free(*newl); + return NewIfc_error_allocation_failure; + } + NI_copy_globals(&((*newl)->api), parent); + (*newl)->api.get = &label_get; + (*newl)->api.set = &label_set; + (*newl)->api.copy = &label_copy; + (*newl)->api.do_render = &label_do_render; + (*newl)->api.last_error = NewIfc_error_none; + (*newl)->api.child_ypos = 0; + (*newl)->api.child_xpos = 0; + (*newl)->api.child_width = 0; + (*newl)->api.child_height = 0; + // TODO: This is only needed by the unit tests... + (*newl)->api.root = parent->root; + parent->bottomchild = parent->topchild = (NewIfcObj)*newl; + (*newl)->api.root = parent->root; + (*newl)->api.parent = parent; + (*newl)->api.width = 0; + (*newl)->api.height = 1; + (*newl)->api.min_width = 0; + (*newl)->api.min_height = 1; + return NewIfc_error_none; +} + +#ifdef BUILD_TESTS + +void test_label(CuTest *ct) +{ + bool b; + char *s; + NewIfcObj obj; + NewIfcObj robj; + static const char *new_title = "New Title"; + struct vmem_cell cells; + + CuAssertTrue(ct, NewIFC_root_window(NULL, &robj) == NewIfc_error_none); + CuAssertTrue(ct, NewIFC_label(robj, &obj) == NewIfc_error_none); + CuAssertPtrNotNull(ct, obj); + CuAssertPtrNotNull(ct, obj->get); + CuAssertPtrNotNull(ct, obj->set); + CuAssertPtrNotNull(ct, obj->copy); + CuAssertTrue(ct, obj->last_error == NewIfc_error_none); + CuAssertTrue(ct, obj->width == 0); + CuAssertTrue(ct, obj->height == 1); + CuAssertTrue(ct, obj->min_width == 0); + CuAssertTrue(ct, obj->min_height == 1); + CuAssertTrue(ct, obj->last_error == NewIfc_error_none); + CuAssertTrue(ct, obj->focus == true); + CuAssertTrue(ct, obj->get(obj, NewIfc_text, &s) == NewIfc_error_none && strcmp(s, "") == 0); + CuAssertTrue(ct, obj->last_error == NewIfc_error_none); + + CuAssertTrue(ct, obj->last_error == NewIfc_error_none); + CuAssertTrue(ct, obj->set(obj, NewIfc_text, new_title) == NewIfc_error_none); + CuAssertTrue(ct, obj->last_error == NewIfc_error_none); + + CuAssertTrue(ct, obj->get(obj, NewIfc_text, &s) == NewIfc_error_none && strcmp(s, new_title) == 0); + CuAssertTrue(ct, obj->last_error == NewIfc_error_none); + + CuAssertTrue(ct, robj->do_render(robj, NULL) == NewIfc_error_none); + size_t sz = strlen(new_title); + for (size_t i = 0; i < sz; i++) { + ciolib_vmem_gettext(i+1,1,i+1,1,&cells); + CuAssertTrue(ct, cells.ch == new_title[i]); + CuAssertTrue(ct, cells.fg == obj->fg_colour); + CuAssertTrue(ct, cells.bg == obj->bg_colour); + CuAssertTrue(ct, cells.font == obj->font); + } +} + +#endif diff --git a/src/newifc/newifc_nongen.c b/src/newifc/newifc_nongen.c index f07ba84fce676c03bec4bad3612a1918ac9ad5f2..b3a45db2759611831664f70ae5f84fbe4baa0794 100644 --- a/src/newifc/newifc_nongen.c +++ b/src/newifc/newifc_nongen.c @@ -1,3 +1,5 @@ +#include <stdlib.h> + #include "newifc.h" NI_err diff --git a/src/newifc/root_window.c b/src/newifc/root_window.c index 81d284ac219a9ed50009021d1313950c047bce3f..45717554d5dd1eaa2551831a0ba5d06328933505 100644 --- a/src/newifc/root_window.c +++ b/src/newifc/root_window.c @@ -24,7 +24,6 @@ struct root_window { struct vmem_cell *display; pthread_mutex_t mtx; unsigned locks; - unsigned dirty:1; }; struct rw_recalc_child_cb_params { @@ -146,31 +145,110 @@ rw_copy(NewIfcObj old, NewIfcObj *newobj) } static NI_err -rw_render(NewIfcObj obj, uint16_t xpos, uint16_t ypos, uint16_t width, uint16_t height) +call_render_handlers(NewIfcObj obj) { - struct root_window *rw = (struct root_window *)obj; - size_t sz = rw->api.width; - sz *= rw->api.height; - if (rw->api.fill_colour != NI_TRANSPARENT || rw->api.fill_character_colour != NI_TRANSPARENT) { - for (size_t c = 0; c < sz; c++) { - // TODO: No way to generate legacy attribute from colour. - if (rw->api.fill_colour != NI_TRANSPARENT) - rw->display[c].bg = rw->api.fill_colour; - if (rw->api.fill_character_colour != NI_TRANSPARENT) { - rw->display[c].fg = rw->api.fill_character_colour; - rw->display[c].ch = rw->api.fill_character; - if (ciolib_checkfont(rw->api.fill_font)) - rw->display[c].font = rw->api.fill_font; + enum NewIfc_event_handlers hval = NewIfc_on_render; + if (obj->handlers == NULL) + return NewIfc_error_none; + struct NewIfc_handler **head = bsearch(&hval, obj->handlers, obj->handlers_sz, sizeof(obj->handlers[0]), handler_bsearch_compar); + if (head == NULL) + return NewIfc_error_none; + struct NewIfc_handler *h = *head; + while (h != NULL) { + NI_err ret = h->on_render(obj, h->cbdata); + if (ret != NewIfc_error_none) + return ret; + h = h->next; + } + return NewIfc_error_none; +} + +static NI_err +rw_do_render_recurse(NewIfcObj obj, struct NewIfc_render_context *ctx) +{ + int16_t oxpos, oypos, owidth, oheight; + NI_err ret = call_render_handlers(obj); + if (ret != NewIfc_error_none) + return ret; + + // Fill background + if (obj->fill_colour != NI_TRANSPARENT || obj->fill_character_colour != NI_TRANSPARENT) { + size_t c; + for (size_t y = 0; y < obj->child_height; y++) { + c = (y + ctx->ypos + obj->child_ypos) * ctx->dwidth; + for (size_t x = 0; x < obj->child_width; x++) { + if (obj->fill_colour != NI_TRANSPARENT) + ctx->vmem[c].bg = obj->fill_colour; + if (obj->fill_character_colour != NI_TRANSPARENT) { + ctx->vmem[c].fg = obj->fill_character_colour; + ctx->vmem[c].ch = obj->fill_character; + if (ciolib_checkfont(obj->fill_font)) + ctx->vmem[c].font = obj->fill_font; + } } } } + if (obj->root != obj) + obj->do_render(obj, ctx); + + owidth = ctx->width; + oheight = ctx->height; + oxpos = ctx->xpos; + oypos = ctx->ypos; + ctx->width = obj->child_width; + ctx->height = obj->child_height; + assert(ctx->xpos >= obj->xpos); + ctx->xpos -= obj->xpos; + assert(ctx->ypos >= obj->ypos); + ctx->ypos -= obj->ypos; + + // Recurse children + if (obj->bottomchild) { + ret = rw_do_render_recurse(obj->bottomchild, ctx); + if (ret != NewIfc_error_none) + return ret; + } + ctx->width = owidth; + ctx->height = oheight; + ctx->xpos = oxpos; + ctx->ypos = oypos; + // Recurse peers + if (obj->higherpeer) { + ret = rw_do_render_recurse(obj->higherpeer, ctx); + if (ret != NewIfc_error_none) + return ret; + } + return NewIfc_error_none; +} + +static NI_err +rw_do_render(NewIfcObj obj, struct NewIfc_render_context *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, + .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); + } + return ret; } static NI_err -NewIFC_root_window(NewIfcObj *newobj) +NewIFC_root_window(NewIfcObj parent, NewIfcObj *newobj) { struct root_window **newrw = (struct root_window **)newobj; + if (parent != NULL) + return NewIfc_error_invalid_arg; *newrw = calloc(1, sizeof(struct root_window)); if (*newrw == NULL) @@ -183,6 +261,10 @@ NewIFC_root_window(NewIfcObj *newobj) // TODO: This is only needed by the unit tests... (*newrw)->api.root = *newobj; (*newrw)->api.focus = true; + (*newrw)->api.do_render = &rw_do_render; + (*newrw)->api.fg_colour = NI_LIGHTGRAY; + (*newrw)->api.bg_colour = NI_BLACK; + (*newrw)->api.font = 0; (*newrw)->mtx = pthread_mutex_initializer_np(true); struct text_info ti; @@ -219,7 +301,7 @@ void test_root_window(CuTest *ct) NewIfcObj obj; static const char *new_title = "New Title"; - CuAssertTrue(ct, !NewIFC_root_window(&obj)); + CuAssertTrue(ct, NewIFC_root_window(NULL, &obj) == NewIfc_error_none); CuAssertPtrNotNull(ct, obj); CuAssertPtrNotNull(ct, obj->get); CuAssertPtrNotNull(ct, obj->set); @@ -235,6 +317,9 @@ void test_root_window(CuTest *ct) CuAssertTrue(ct, obj->last_error == NewIfc_error_none); CuAssertTrue(ct, obj->get(obj, NewIfc_locked_by_me, &b) == NewIfc_error_none && !b); CuAssertTrue(ct, obj->last_error == NewIfc_error_none); + CuAssertTrue(ct, obj->fg_colour == NI_LIGHTGRAY); + CuAssertTrue(ct, obj->bg_colour == NI_BLACK); + CuAssertTrue(ct, obj->font == 0); CuAssertTrue(ct, obj->last_error == NewIfc_error_none); CuAssertTrue(ct, obj->set(obj, NewIfc_locked, false) == NewIfc_error_lock_failed); @@ -254,12 +339,8 @@ void test_root_window(CuTest *ct) CuAssertTrue(ct, obj->last_error == NewIfc_error_lock_failed); CuAssertTrue(ct, obj->get(obj, NewIfc_locked_by_me, &b) == NewIfc_error_none && !b); CuAssertTrue(ct, obj->last_error == NewIfc_error_none); -} -CuSuite* root_window_get_test_suite() { - CuSuite* suite = CuSuiteNew(); - SUITE_ADD_TEST(suite, test_root_window); - return suite; + CuAssertTrue(ct, obj->do_render(obj, NULL) == NewIfc_error_none); } #endif