+ rtk_widget *w;
+
+ if(!(w = rtk_create_widget())) {
+ return 0;
+ }
+ if(par) rtk_win_add(par, w);
+ rtk_set_text(w, text);
+ rtk_set_value(w, chk ? 1 : 0);
+ rtk_set_callback(w, cbfunc, 0);
+ return w;
+}
+
+/* --- icon functions --- */
+rtk_iconsheet *rtk_load_iconsheet(const char *fname)
+{
+ rtk_iconsheet *is;
+
+ if(!(is = malloc(sizeof *is))) {
+ return 0;
+ }
+ is->icons = 0;
+
+ if(!(is->pixels = img_load_pixels(fname, &is->width, &is->height, IMG_FMT_RGBA32))) {
+ free(is);
+ return 0;
+ }
+ return is;
+}
+
+void rtk_free_iconsheet(rtk_iconsheet *is)
+{
+ rtk_icon *icon;
+
+ img_free_pixels(is->pixels);
+
+ while(is->icons) {
+ icon = is->icons;
+ is->icons = is->icons->next;
+ free(icon->name);
+ free(icon);
+ }
+ free(is);
+}
+
+rtk_icon *rtk_define_icon(rtk_iconsheet *is, const char *name, int x, int y, int w, int h)
+{
+ rtk_icon *icon;
+
+ if(!(icon = malloc(sizeof *icon))) {
+ return 0;
+ }
+ if(!(icon->name = strdup(name))) {
+ free(icon);
+ return 0;
+ }
+ icon->width = w;
+ icon->height = h;
+ icon->scanlen = is->width;
+ icon->pixels = is->pixels + y * is->width + x;
+ return icon;
+}
+
+#define BEVELSZ 1
+#define PAD 2
+#define OFFS (BEVELSZ + PAD)
+#define CHKBOXSZ (BEVELSZ * 2 + 8)
+
+static void calc_widget_rect(rtk_widget *w, rtk_rect *rect)
+{
+ rtk_rect txrect = {0};
+
+ rect->x = w->any.x;
+ rect->y = w->any.y;
+
+ if(w->any.text) {
+ gfx.textrect(w->any.text, &txrect);
+ }
+
+ switch(w->type) {
+ case RTK_BUTTON:
+ if(w->bn.icon) {
+ rect->width = w->bn.icon->width + OFFS * 2;
+ rect->height = w->bn.icon->height + OFFS * 2;
+ } else {
+ rect->width = txrect.width + OFFS * 2;
+ rect->height = txrect.height + OFFS * 2;
+ }
+ break;
+
+ case RTK_CHECKBOX:
+ rect->width = txrect.width + CHKBOXSZ + OFFS * 2 + PAD;
+ rect->height = txrect.height + OFFS * 2;
+ break;
+
+ case RTK_LABEL:
+ rect->width = txrect.width + PAD * 2;
+ rect->height = txrect.height + PAD * 2;
+ break;
+
+ default:
+ rect->width = rect->height = 0;
+ }
+}
+
+static int need_relayout(rtk_widget *w)
+{
+ rtk_widget *c;
+
+ if(w->any.flags & GEOMCHG) {
+ return 1;
+ }
+
+ if(w->any.type == RTK_WIN) {
+ c = w->win.clist;
+ while(c) {
+ if(need_relayout(c)) {
+ return 1;
+ }
+ c = c->any.next;
+ }
+ }