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

Add alignment and destruction

parent 1dfff945
No related branches found
No related tags found
No related merge requests found
Pipeline #5464 passed
......@@ -29,6 +29,7 @@ enum attribute_types {
NI_attr_type_bool,
NI_attr_type_charptr,
NI_attr_type_NewIfc_object,
NI_attr_type_NewIfc_align,
};
struct type_str_values {
......@@ -45,6 +46,7 @@ struct type_str_values type_str[] = {
{"bool", "bool"},
{"char *", "char_ptr"},
{"enum NewIfc_object", "obj_enum"},
{"enum NewIfc_alignment", "align_enum"},
};
enum attribute_impl {
......@@ -60,39 +62,45 @@ struct attribute_info {
enum attribute_impl impl;
int read_only;
int no_event;
int inherit;
};
const struct attribute_info
attributes[] = {
{"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},
{"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},
{"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},
};
struct attribute_alias {
......@@ -336,6 +344,20 @@ main(int argc, char **argv)
}
fputs("};\n\n", header);
fputs("enum NewIfc_alignment {\n"
" NewIfc_align_top_left,\n"
" NewIfc_align_top_middle,\n"
" NewIfc_align_top_right,\n"
" NewIfc_align_middle_left,\n"
" NewIfc_align_centre,\n"
" NewIfc_align_center = NewIfc_align_centre,\n"
" NewIfc_align_middle = NewIfc_align_centre,\n"
" NewIfc_align_middle_right,\n"
" NewIfc_align_bottom_left,\n"
" NewIfc_align_bottom_middle,\n"
" NewIfc_align_bottom_right,\n"
"};\n\n", header);
fputs("#define NI_TRANSPARENT UINT32_MAX\n"
"#define NI_BLACK UINT32_C(0)\n"
"#define NI_BLUE UINT32_C(0x800000A8)\n"
......@@ -356,8 +378,15 @@ main(int argc, char **argv)
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);
fputs("NI_err NI_destroy(NewIfcObj obj);\n", header);
fputs("NI_err NI_error(NewIfcObj obj);\n", header);
fputs("NI_err NI_walk_children(NewIfcObj obj, bool top_down, NI_err (*cb)(NewIfcObj obj, void *cb_data), void *cbdata);\n\n", header);
fputs("NI_err NI_inner_width(NewIfcObj obj, uint16_t *width);\n", header);
fputs("NI_err NI_inner_height(NewIfcObj obj, uint16_t *hright);\n", header);
fputs("NI_err NI_inner_xpos(NewIfcObj obj, uint16_t *xpos);\n", header);
fputs("NI_err NI_inner_ypos(NewIfcObj obj, uint16_t *ypos);\n", header);
fputs("NI_err NI_inner_size(NewIfcObj obj, uint16_t *width, uint16_t *height);\n", header);
fputs("NI_err NI_inner_size_pos(NewIfcObj obj, uint16_t *width, uint16_t *height, uint16_t *xpos, uint16_t *ypos);\n", header);
nitems = sizeof(attributes) / sizeof(attributes[0]);
for (i = 0; i < nitems; i++) {
......@@ -438,19 +467,21 @@ main(int argc, char **argv)
" 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"
" NewIfcObj root;\n"
" NewIfcObj parent;\n"
" NewIfcObj higherpeer;\n"
" NewIfcObj lowerpeer;\n"
" NewIfcObj topchild;\n"
" NewIfcObj bottomchild;\n"
" NewIfcObj higher_peer;\n"
" NewIfcObj lower_peer;\n"
" NewIfcObj top_child;\n"
" NewIfcObj bottom_child;\n"
" 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"
" enum NewIfc_alignment align;\n"
" uint16_t height;\n"
" uint16_t width;\n"
" uint16_t min_height;\n"
......@@ -461,6 +492,10 @@ main(int argc, char **argv)
" uint16_t child_width;\n"
" uint16_t child_xpos;\n"
" uint16_t child_ypos;\n"
" uint16_t left_pad;\n"
" uint16_t right_pad;\n"
" uint16_t bottom_pad;\n"
" uint16_t top_pad;\n"
" uint8_t fill_character;\n"
" uint8_t fill_font;\n"
" uint8_t font;\n"
......@@ -478,7 +513,6 @@ main(int argc, char **argv)
fputs("#endif\n", internal_header);
fclose(internal_header);
c_code = fopen("newifc.c", "w");
if (c_code == NULL) {
perror("Opening c source");
......@@ -532,22 +566,22 @@ main(int argc, char **argv)
fputs(" }\n"
" if (ret == NewIfc_error_none) {\n"
" (*newobj)->parent = parent;\n"
" (*newobj)->higherpeer = NULL;\n"
" (*newobj)->topchild = NULL;\n"
" (*newobj)->bottomchild = NULL;\n"
" (*newobj)->higher_peer = NULL;\n"
" (*newobj)->top_child = NULL;\n"
" (*newobj)->bottom_child = NULL;\n"
" (*newobj)->handlers = NULL;\n"
" (*newobj)->handlers_sz = 0;\n"
" if (parent) {\n"
" (*newobj)->root = parent->root;\n"
" (*newobj)->lowerpeer = parent->topchild;\n"
" parent->topchild = *newobj;\n"
" if (parent->bottomchild == NULL) {\n"
" parent->bottomchild = *newobj;\n"
" (*newobj)->lower_peer = parent->top_child;\n"
" parent->top_child = *newobj;\n"
" if (parent->bottom_child == NULL) {\n"
" parent->bottom_child = *newobj;\n"
" }\n"
" }\n"
" else {\n"
" (*newobj)->root = *newobj;\n"
" (*newobj)->lowerpeer = NULL;\n"
" (*newobj)->lower_peer = NULL;\n"
" }\n"
" }\n"
" return ret;\n"
......@@ -560,8 +594,10 @@ main(int argc, char **argv)
"{\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);
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);
}
}
fputs(" return NewIfc_error_none;\n"
"}\n\n", c_code);
......
......@@ -91,32 +91,57 @@ label_copy(NewIfcObj old, NewIfcObj *newobj)
static NI_err
label_do_render(NewIfcObj obj, struct NewIfc_render_context *ctx)
{
size_t sz = 0;
size_t tsz = 0;
uint16_t xpos, ypos;
struct label *l = (struct label *) obj;
if (l->text)
sz = strlen(l->text);
tsz = strlen(l->text);
NI_err ret = NI_get_top_left(obj, tsz, 1, &xpos, &ypos);
ypos -= ctx->ypos;
xpos -= ctx->xpos;
if (ret != NewIfc_error_none)
return ret;
// 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];
for (size_t y = 0; y < ctx->height; y++) {
size_t c = (ctx->ypos + y) * ctx->dwidth + ctx->xpos;
for (size_t x = 0; x < ctx->width; x++, c++) {
if (l->api.bg_colour != NI_TRANSPARENT)
ctx->vmem[c].bg = l->api.bg_colour;
if (l->api.fg_colour != NI_TRANSPARENT) {
ctx->vmem[c].fg = l->api.fg_colour;
ctx->vmem[c].font = l->api.font;
if (y == ypos && x >= xpos && x < xpos + tsz)
ctx->vmem[c].ch = l->text[x - xpos];
else
ctx->vmem[c].ch = ' ';
}
}
}
return NewIfc_error_none;
}
static NI_err
label_destroy(NewIfcObj newobj)
{
struct label *l = (struct label *)newobj;
if (l == NULL)
return NewIfc_error_invalid_arg;
free(l->text);
free(l);
return NewIfc_error_none;
}
static NI_err
NewIFC_label(NewIfcObj parent, NewIfcObj *newobj)
{
struct label **newl = (struct label **)newobj;
if (parent == NULL)
if (parent == NULL || newobj == NULL)
return NewIfc_error_invalid_arg;
*newl = calloc(1, sizeof(struct label));
if (parent->child_height < 1)
return NewIfc_error_wont_fit;
(*newl) = calloc(1, sizeof(struct label));
if (*newl == NULL)
return NewIfc_error_allocation_failure;
......@@ -130,19 +155,20 @@ NewIFC_label(NewIfcObj parent, NewIfcObj *newobj)
(*newl)->api.set = &label_set;
(*newl)->api.copy = &label_copy;
(*newl)->api.do_render = &label_do_render;
(*newl)->api.destroy = &label_destroy;
(*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 = parent->child_width;
(*newl)->api.height = 1;
(*newl)->api.height = parent->child_height;
(*newl)->api.min_width = 0;
(*newl)->api.min_height = 1;
(*newl)->api.left_pad = 0;
(*newl)->api.right_pad = 0;
(*newl)->api.top_pad = 0;
(*newl)->api.bottom_pad = 0;
return NewIfc_error_none;
}
......@@ -151,24 +177,28 @@ NewIFC_label(NewIfcObj parent, NewIfcObj *newobj)
void test_label(CuTest *ct)
{
char *s;
NewIfcObj obj;
NewIfcObj robj;
NewIfcObj obj = NULL;
NewIfcObj robj = NULL;
static const char *new_title = "New Title";
struct vmem_cell cells;
CuAssertTrue(ct, NewIFC_root_window(NULL, &robj) == NewIfc_error_none);
CuAssertPtrNotNull(ct, robj);
CuAssertTrue(ct, NewIFC_label(robj, &obj) == NewIfc_error_none);
obj->root = robj;
obj->parent = robj;
robj->top_child = obj;
robj->bottom_child = obj;
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 == 1);
CuAssertTrue(ct, obj->height == 25);
CuAssertTrue(ct, obj->min_width == 0);
CuAssertTrue(ct, obj->min_height == 1);
CuAssertTrue(ct, obj->focus == true);
CuAssertTrue(ct, obj->focus == false);
CuAssertTrue(ct, obj->get(obj, NewIfc_text, &s) == NewIfc_error_none && strcmp(s, "") == 0);
CuAssertTrue(ct, obj->set(obj, NewIfc_text, new_title) == NewIfc_error_none);
......@@ -184,6 +214,8 @@ void test_label(CuTest *ct)
CuAssertTrue(ct, cells.bg == obj->bg_colour);
CuAssertTrue(ct, cells.font == obj->font);
}
CuAssertTrue(ct, obj->destroy(obj) == NewIfc_error_none);
CuAssertTrue(ct, robj->destroy(robj) == NewIfc_error_none);
}
#endif
......@@ -17,10 +17,10 @@ NI_copy(NewIfcObj obj, NewIfcObj *newobj) {
if (ret == NewIfc_error_none) {
(*newobj)->root = NULL;
(*newobj)->parent = NULL;
(*newobj)->higherpeer = NULL;
(*newobj)->lowerpeer = NULL;
(*newobj)->topchild = NULL;
(*newobj)->bottomchild = NULL;
(*newobj)->higher_peer = NULL;
(*newobj)->lower_peer = NULL;
(*newobj)->top_child = NULL;
(*newobj)->bottom_child = NULL;
}
NI_set_locked(obj, false);
}
......@@ -41,9 +41,9 @@ NI_walk_children_recurse(NewIfcObj obj, bool top_down, NI_err (*cb)(NewIfcObj ob
if (err != NewIfc_error_none)
return err;
if (top_down)
nobj = obj->topchild;
nobj = obj->top_child;
else
nobj = obj->bottomchild;
nobj = obj->bottom_child;
if (nobj != NULL) {
err = NI_walk_children_recurse(nobj, top_down, cb, cbdata);
......@@ -51,9 +51,9 @@ NI_walk_children_recurse(NewIfcObj obj, bool top_down, NI_err (*cb)(NewIfcObj ob
return err;
}
if (top_down)
nobj = obj->lowerpeer;
nobj = obj->lower_peer;
else
nobj = obj->higherpeer;
nobj = obj->higher_peer;
if (!nobj)
return NewIfc_error_none;
......@@ -74,7 +74,7 @@ NI_walk_children(NewIfcObj obj, bool top_down, NI_err (*cb)(NewIfcObj obj, void
return NewIfc_error_invalid_arg;
ret = NI_set_locked(obj, true);
if (ret == NewIfc_error_none) {
ret = NI_walk_children_recurse(obj->bottomchild, top_down, cb, cbdata);
ret = NI_walk_children_recurse(top_down ? obj->top_child : obj->bottom_child, top_down, cb, cbdata);
NI_set_locked(obj, false);
}
else
......@@ -151,3 +151,194 @@ NI_resize(NewIfcObj obj, uint16_t width, uint16_t height)
return NewIfc_error_none;
}
NI_err
NI_inner_width(NewIfcObj obj, uint16_t *width)
{
if (width == NULL)
return NewIfc_error_invalid_arg;
if (obj == NULL) {
*width = 0;
return NewIfc_error_invalid_arg;
}
uint32_t both = (uint32_t)obj->left_pad + obj->right_pad;
if (both > obj->width) {
*width = 0;
return NewIfc_error_wont_fit;
}
*width = obj->width - obj->left_pad - obj->right_pad;
return NewIfc_error_none;
}
NI_err
NI_inner_height(NewIfcObj obj, uint16_t *height)
{
if (height == NULL)
return NewIfc_error_invalid_arg;
if (obj == NULL) {
*height = 0;
return NewIfc_error_invalid_arg;
}
uint32_t both = (uint32_t)obj->top_pad + obj->bottom_pad;
if (both > obj->height) {
*height = 0;
return NewIfc_error_wont_fit;
}
*height = obj->height - obj->top_pad - obj->bottom_pad;
return NewIfc_error_none;
}
NI_err
NI_inner_xpos(NewIfcObj obj, uint16_t *xpos)
{
if (xpos == NULL)
return NewIfc_error_invalid_arg;
if (obj == NULL) {
*xpos = 0;
return NewIfc_error_invalid_arg;
}
*xpos = obj->xpos + obj->left_pad;
return NewIfc_error_none;
}
NI_err
NI_inner_ypos(NewIfcObj obj, uint16_t *ypos)
{
if (ypos == NULL)
return NewIfc_error_invalid_arg;
if (obj == NULL) {
*ypos = 0;
return NewIfc_error_invalid_arg;
}
*ypos = obj->ypos + obj->top_pad;
return NewIfc_error_none;
}
NI_err
NI_inner_size(NewIfcObj obj, uint16_t *width, uint16_t *height)
{
NI_err ret;
ret = NI_inner_width(obj, width);
if (ret != NewIfc_error_none)
return ret;
ret = NI_inner_height(obj, height);
if (ret != NewIfc_error_none)
return ret;
return NewIfc_error_none;
}
NI_err
NI_inner_size_pos(NewIfcObj obj, uint16_t *width, uint16_t *height, uint16_t *xpos, uint16_t *ypos)
{
NI_err ret;
ret = NI_inner_width(obj, width);
if (ret != NewIfc_error_none)
return ret;
ret = NI_inner_height(obj, height);
if (ret != NewIfc_error_none)
return ret;
ret = NI_inner_xpos(obj, xpos);
if (ret != NewIfc_error_none)
return ret;
ret = NI_inner_ypos(obj, ypos);
if (ret != NewIfc_error_none)
return ret;
return NewIfc_error_none;
}
static NI_err
NI_get_top_left(NewIfcObj obj, uint16_t width, uint16_t height, uint16_t *xpos, uint16_t *ypos)
{
switch(obj->align) {
case NewIfc_align_top_left:
*xpos = 0;
*ypos = 0;
break;
case NewIfc_align_top_middle:
*xpos = (obj->width - width) / 2;
*ypos = 0;
break;
case NewIfc_align_top_right:
*xpos = obj->width - width;
*ypos = 0;
break;
case NewIfc_align_middle_left:
*xpos = 0;
*ypos = (obj->height - height) / 2;
break;
case NewIfc_align_middle:
*xpos = (obj->width - width) / 2;
*ypos = (obj->height - height) / 2;
break;
case NewIfc_align_middle_right:
*xpos = obj->width - width;
*ypos = (obj->height - height) / 2;
break;
case NewIfc_align_bottom_left:
*xpos = 0;
*ypos = obj->height - height;
break;
case NewIfc_align_bottom_middle:
*xpos = (obj->width - width) / 2;
*ypos = obj->height - height;
break;
case NewIfc_align_bottom_right:
*xpos = obj->width - width;
*ypos = obj->height - height;
break;
}
return NewIfc_error_none;
}
static NI_err
call_destroy_handlers(NewIfcObj obj)
{
enum NewIfc_event_handlers hval = NewIfc_on_destroy;
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
NI_destroy_recurse(NewIfcObj obj, bool top)
{
// Recurse children and peers...
if (obj->bottom_child != NULL)
NI_destroy_recurse(obj->bottom_child, false);
if (!top) {
if (obj->higher_peer != NULL)
NI_destroy_recurse(obj->higher_peer, false);
}
// Ignore return value... you can't stop this train.
call_destroy_handlers(obj);
obj->destroy(obj);
return NewIfc_error_none;
}
NI_err
NI_destroy(NewIfcObj obj)
{
// Remove from parent/peer lists
if (obj->higher_peer)
obj->higher_peer->lower_peer = obj->lower_peer;
if (obj->lower_peer)
obj->lower_peer->higher_peer = obj->higher_peer;
if (obj->parent) {
if (obj->parent->top_child == obj)
obj->parent->top_child = obj->lower_peer;
if (obj->parent->bottom_child == obj)
obj->parent->bottom_child = obj->higher_peer;
}
NI_err ret = NI_destroy_recurse(obj, true);
return ret;
}
......@@ -197,13 +197,69 @@ rw_do_render_recurse(NewIfcObj obj, struct NewIfc_render_context *ctx)
}
}
}
if (obj->root != obj)
obj->do_render(obj, 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))) {
c = (y + ctx->ypos + obj->ypos) * ctx->dwidth;
for (size_t x = 0; x < obj->width; x++) {
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].ch = ' ';
if (ciolib_checkfont(obj->font))
ctx->vmem[c].font = obj->font;
}
c++;
}
}
else {
if (obj->left_pad) {
c = (y + ctx->ypos + obj->ypos) * ctx->dwidth;
for (size_t x = 0; x < obj->left_pad; x++) {
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].ch = ' ';
if (ciolib_checkfont(obj->font))
ctx->vmem[c].font = obj->font;
}
c++;
}
}
if (obj->right_pad) {
c = (y + ctx->ypos + obj->ypos) * ctx->dwidth;
c += obj->width;
c -= obj->right_pad;
for (size_t x = 0; x < obj->right_pad; x++) {
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].ch = ' ';
if (ciolib_checkfont(obj->font))
ctx->vmem[c].font = obj->font;
}
c++;
}
}
}
}
}
owidth = ctx->width;
oheight = ctx->height;
oxpos = ctx->xpos;
oypos = ctx->ypos;
ctx->width = obj->width - (obj->left_pad + obj->right_pad);
ctx->height = obj->height - (obj->top_pad + obj->bottom_pad);
ctx->xpos += obj->left_pad;
ctx->ypos += obj->top_pad;
if (obj->root != obj)
obj->do_render(obj, ctx);
ctx->width = obj->child_width;
ctx->height = obj->child_height;
assert(ctx->xpos >= obj->xpos);
......@@ -212,8 +268,8 @@ rw_do_render_recurse(NewIfcObj obj, struct NewIfc_render_context *ctx)
ctx->ypos -= obj->ypos;
// Recurse children
if (obj->bottomchild) {
ret = rw_do_render_recurse(obj->bottomchild, ctx);
if (obj->bottom_child) {
ret = rw_do_render_recurse(obj->bottom_child, ctx);
if (ret != NewIfc_error_none)
return ret;
}
......@@ -222,8 +278,8 @@ rw_do_render_recurse(NewIfcObj obj, struct NewIfc_render_context *ctx)
ctx->xpos = oxpos;
ctx->ypos = oypos;
// Recurse peers
if (obj->higherpeer) {
ret = rw_do_render_recurse(obj->higherpeer, ctx);
if (obj->higher_peer) {
ret = rw_do_render_recurse(obj->higher_peer, ctx);
if (ret != NewIfc_error_none)
return ret;
}
......@@ -251,12 +307,25 @@ rw_do_render(NewIfcObj obj, struct NewIfc_render_context *nullctx)
return ret;
}
static NI_err
rw_destroy(NewIfcObj obj)
{
struct root_window *newrw = (struct root_window *)obj;
if (obj == NULL)
return NewIfc_error_invalid_arg;
free(newrw->display);
pthread_mutex_destroy(&newrw->mtx);
free(newrw);
return NewIfc_error_none;
}
static NI_err
NewIFC_root_window(NewIfcObj parent, NewIfcObj *newobj)
{
struct root_window **newrw = (struct root_window **)newobj;
if (parent != NULL)
if (parent != NULL || newobj == NULL)
return NewIfc_error_invalid_arg;
*newrw = calloc(1, sizeof(struct root_window));
......@@ -265,6 +334,7 @@ NewIFC_root_window(NewIfcObj parent, NewIfcObj *newobj)
(*newrw)->api.get = rw_get;
(*newrw)->api.set = rw_set;
(*newrw)->api.copy = rw_copy;
(*newrw)->api.destroy = rw_destroy;
// TODO: This is only needed by the unit tests...
(*newrw)->api.root = *newobj;
(*newrw)->api.focus = true;
......@@ -304,7 +374,7 @@ NewIFC_root_window(NewIfcObj parent, NewIfcObj *newobj)
void test_root_window(CuTest *ct)
{
bool b;
NewIfcObj obj;
NewIfcObj obj = NULL;
CuAssertTrue(ct, NewIFC_root_window(NULL, &obj) == NewIfc_error_none);
CuAssertPtrNotNull(ct, obj);
......@@ -334,6 +404,7 @@ void test_root_window(CuTest *ct)
CuAssertTrue(ct, obj->get(obj, NewIfc_locked_by_me, &b) == NewIfc_error_none && !b);
CuAssertTrue(ct, obj->do_render(obj, NULL) == NewIfc_error_none);
CuAssertTrue(ct, obj->destroy(obj) == NewIfc_error_none);
}
#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