diff --git a/src/newifc/genapi.c b/src/newifc/genapi.c index f7556741b332dd09b974a893dbd5e93ca5d8eb4c..140701fc75be8e2c10f9c48b2ca3bddb88e894ea 100644 --- a/src/newifc/genapi.c +++ b/src/newifc/genapi.c @@ -33,6 +33,11 @@ struct attribute_info { const struct attribute_info attributes[] = { + {"child_height", "uint16_t", attr_impl_global, 1}, + {"child_width", "uint16_t", attr_impl_global, 1}, + {"child_xpos", "uint16_t", attr_impl_global, 1}, + {"child_ypos", "uint16_t", attr_impl_global, 1}, + {"dirty", "bool", attr_impl_root, 1}, {"height", "uint16_t", attr_impl_global, 0}, {"locked", "bool", attr_impl_root, 0}, {"locked_by_me", "bool", attr_impl_root, 1}, @@ -41,6 +46,8 @@ attributes[] = { {"title", "const char *", attr_impl_object, 0}, {"transparent", "bool", attr_impl_object, 0}, {"width", "uint16_t", attr_impl_global, 0}, + {"xpos", "uint16_t", attr_impl_global, 0}, + {"ypos", "uint16_t", attr_impl_global, 0}, }; struct error_info { @@ -55,6 +62,7 @@ error_inf[] = { {"error_not_implemented"}, {"error_lock_failed"}, {"error_needs_parent"}, + {"error_wont_fit"}, }; int @@ -100,6 +108,7 @@ main(int argc, char **argv) fputs("NewIfcObj NI_copy(NewIfcObj obj);\n", header); fputs("NewIfcObj NI_create(enum NewIfc_object obj, NewIfcObj parent);\n", header); fputs("enum NewIfc_error NI_error(NewIfcObj obj);\n\n", header); + fputs("bool NI_walk_children(NewIfcObj obj, bool (*cb)(NewIfcObj obj, void *cb_data), void *cbdata);\n", header); nitems = sizeof(attributes) / sizeof(attributes[0]); for (i = 0; i < nitems; i++) { @@ -133,10 +142,16 @@ main(int argc, char **argv) "\tNewIfcObj lowerpeer;\n" "\tNewIfcObj topchild;\n" "\tNewIfcObj bottomchild;\n" - "\tuint16_t height;\n" - "\tuint16_t width;\n" "\tenum NewIfc_object type;\n" "\tenum NewIfc_error last_error;\n" + "\tuint16_t height;\n" + "\tuint16_t width;\n" + "\tuint16_t xpos;\n" + "\tuint16_t ypos;\n" + "\tuint16_t child_height;\n" + "\tuint16_t child_width;\n" + "\tuint16_t child_xpos;\n" + "\tuint16_t child_ypos;\n" "};\n\n", internal_header); fputs("enum NewIfc_attribute {\n", internal_header); @@ -214,16 +229,7 @@ main(int argc, char **argv) "\treturn ret;\n" "};\n\n", c_code); - fputs("NewIfcObj\n" - "NI_copy(NewIfcObj obj) {\n" - "\treturn obj->copy(obj);\n" - "}\n\n", c_code); - - fputs("enum NewIfc_error\n" - "NI_error(NewIfcObj obj)\n" - "{\n" - "\treturn obj->last_error;\n" - "}\n\n", c_code); + fputs("#include \"newifc_nongen.c\"\n\n", c_code); nitems = sizeof(attributes) / sizeof(attributes[0]); for (i = 0; i < nitems; i++) { @@ -261,38 +267,48 @@ main(int argc, char **argv) "NI_set_%s(NewIfcObj obj, %s value) {\n" "\tbool ret;\n" "\tif (NI_set_locked(obj, true)) {\n" - "\t\tobj->%s = value;\n" + "\t\tif ((!obj->set(obj, NewIfc_%s, value)) && obj->last_error != NewIfc_error_not_implemented) {\n" + "\t\t\tobj->%s = value;\n" + "\t\t\tobj->last_error = NewIfc_error_none;\n" + "\t\t}\n" "\t\tNI_set_locked(obj, false);\n" "\t}\n" "\telse\n" "\t\tret = false;\n" "\treturn ret;\n" - "}\n\n", attributes[i].name, attributes[i].type, attributes[i].name); + "}\n\n", attributes[i].name, attributes[i].type, attributes[i].name, attributes[i].name); } fprintf(c_code, "bool\n" - "NI_get_%s(NewIfcObj obj, %s* value) {\n" - "\tbool ret;\n" - "\tif (NI_set_locked(obj, true)) {\n" - "\t\t*value = obj->%s;\n" + "NI_get_%s(NewIfcObj obj, %s* value) {\n" + "\tbool ret;\n" + "\tif (NI_set_locked(obj, true)) {\n" + "\t\tif ((!obj->get(obj, NewIfc_%s, value)) && obj->last_error != NewIfc_error_not_implemented) {\n" + "\t\t\t*value = obj->%s;\n" + "\t\t\tobj->last_error = NewIfc_error_none;\n" + "\t\t}\n" "\t\tNI_set_locked(obj, false);\n" "\t}\n" "\telse\n" "\t\tret = false;\n" "\treturn ret;\n" - "}\n\n", attributes[i].name, attributes[i].type, attributes[i].name); + "}\n\n", attributes[i].name, attributes[i].type, attributes[i].name, attributes[i].name); break; case attr_impl_root: if (!attributes[i].read_only) { fprintf(c_code, "bool\n" "NI_set_%s(NewIfcObj obj, %s value) {\n" - "\treturn obj->root->set(obj, NewIfc_%s, value);\n" + "\tbool ret = obj->root->set(obj, NewIfc_%s, value);\n" + "\tobj->last_error = obj->root->last_error;\n" + "\treturn ret;\n" "}\n\n", attributes[i].name, attributes[i].type, attributes[i].name); } fprintf(c_code, "bool\n" "NI_get_%s(NewIfcObj obj, %s* value) {\n" - "\treturn obj->root->get(obj, NewIfc_%s, value);\n" + "\tbool ret = obj->root->get(obj, NewIfc_%s, value);\n" + "\tobj->last_error = obj->root->last_error;\n" + "\treturn ret;\n" "}\n\n", attributes[i].name, attributes[i].type, attributes[i].name); break; } diff --git a/src/newifc/newifc_nongen.c b/src/newifc/newifc_nongen.c new file mode 100644 index 0000000000000000000000000000000000000000..126c272d8d69871f3997d3fb2ec7a219b5f6dc39 --- /dev/null +++ b/src/newifc/newifc_nongen.c @@ -0,0 +1,39 @@ +NewIfcObj +NI_copy(NewIfcObj obj) { + return obj->copy(obj); +} + +enum NewIfc_error +NI_error(NewIfcObj obj) +{ + return obj->last_error; +} + +static bool +NI_walk_children_recurse(NewIfcObj obj, bool (*cb)(NewIfcObj obj, void *cb_data), void *cbdata) +{ + if (!obj) + return true; + if (!cb(obj, cbdata)) + return false; + if (obj->bottomchild != NULL) { + if (!NI_walk_children_recurse(obj->bottomchild, cb, cbdata)) + return false; + } + if (!obj->higherpeer) + return true; + return NI_walk_children_recurse(obj->higherpeer, cb, cbdata); +} + +bool +NI_walk_children(NewIfcObj obj, bool (*cb)(NewIfcObj obj, void *cb_data), void *cbdata) +{ + bool ret; + if (NI_set_locked(obj, true)) { + NI_walk_children_recurse(obj->bottomchild, cb, cbdata); + NI_set_locked(obj, false); + } + else + ret = false; + return ret; +} diff --git a/src/newifc/root_window.c b/src/newifc/root_window.c index 8e25098f128179fbbfc2fba02151f5d869b48be6..26cdbf375aa791f0e2dcbd45bd68d2974f59781d 100644 --- a/src/newifc/root_window.c +++ b/src/newifc/root_window.c @@ -26,8 +26,53 @@ struct root_window { unsigned transparent:1; unsigned show_title:1; unsigned help:1; + unsigned dirty:1; +}; + +struct rw_recalc_child_cb_params { + uint16_t height; + uint16_t width; }; +static bool +rw_recalc_child_cb(NewIfcObj obj, void *cbdata) +{ + struct rw_recalc_child_cb_params *nsz = cbdata; + + if (obj->height > nsz->height) + return false; + if (obj->width > nsz->width) + return false; + return true; +} + +static void +rw_recalc_child(struct root_window *rw, uint16_t height, uint16_t width) +{ + uint16_t losty = 0; + struct rw_recalc_child_cb_params nsz = {height, width}; + + if (rw->show_title) { + nsz.height--; + losty++; + } + if (rw->help) { + nsz.height--; + losty++; + } + if (losty > height) { + rw->api.last_error = NewIfc_error_wont_fit; + return; + } + if (!NI_walk_children((NewIfcObj)rw, rw_recalc_child_cb, &nsz)) { + rw->api.last_error = NewIfc_error_wont_fit; + return; + } + rw->api.child_height = nsz.height; + rw->api.child_ypos = rw->show_title ? 1 : 0; + return; +} + static bool rw_set(NewIfcObj obj, int attr, ...) { @@ -45,9 +90,17 @@ rw_set(NewIfcObj obj, int attr, ...) break; case NewIfc_show_help: SET_BOOL(rw, help); + rw_recalc_child(rw, rw->api.height, rw->api.width); break; case NewIfc_title: SET_STRING(rw, title, title_sz); + rw_recalc_child(rw, rw->api.height, rw->api.width); + break; + case NewIfc_height: + rw_recalc_child(rw, va_arg(ap, int), rw->api.width); + break; + case NewIfc_width: + rw_recalc_child(rw, rw->api.height, va_arg(ap, int)); break; case NewIfc_locked: if (va_arg(ap, int)) { @@ -176,6 +229,12 @@ NewIFC_root_window(void) ret->api.last_error = NewIfc_error_none; ret->api.width = 80; ret->api.height = 25; + ret->api.xpos = 0; + ret->api.ypos = 0; + ret->api.child_xpos = 0; + ret->api.child_ypos = 1; + ret->api.child_width = 80; + ret->api.child_height = 23; ret->transparent = false; ret->show_title = true; ret->help = true;