5 void *(*wt_alloc)(size_t sz) = malloc;
6 void (*wt_free)(void *p) = free;
8 /* one day I may want to allow multiple contexts */
9 static struct wt_context defctx;
10 struct wt_context *wt_curctx_ = &defctx;
12 static unsigned int def_colors[] = {
13 0xf0f0f0, /* font/foreground */
14 0x444444, /* background */
15 0x555555, /* highlight */
16 0x333333, /* shadow */
17 0x403065, /* inactive frame */
18 0x54349c, /* inactive frame highlight */
19 0x221e2c, /* inactive frame shadow */
20 0x8032aa, /* active frame */
21 0xb14de8, /* active frame highlight */
22 0x3b2846, /* active frame shadow */
26 void *wt_zalloc(size_t sz)
28 void *p = wt_alloc(sz);
35 void wt_allocator(void *(*allocfunc)(size_t), void (*freefunc)(void *p))
37 wt_alloc = allocfunc ? allocfunc : malloc;
38 wt_free = freefunc ? freefunc : free;
42 int wt_init(int w, int h, struct wt_graphics *gfx)
45 if(!(wt->root = wt_alloc_widget(0))) {
49 wt_viewport(0, 0, w, h);
56 wt_free_tree(wt->root);
60 struct wt_theme *wt_load_theme(const char *path)
65 void wt_unload_theme(struct wt_theme *theme)
69 static void use_theme(wt_widget *w, struct wt_theme *theme)
74 w->use_theme(w, theme);
77 for(i=0; i<w->num_child; i++) {
78 use_theme(w->child[i], theme);
82 void wt_use_theme(struct wt_theme *theme)
85 use_theme(wt->root, theme);
88 void wt_viewport(int x, int y, int w, int h)
90 wt_rect(&wt->vp, x, y, w, h);
91 wt_move(wt->root, x, y);
92 wt_resize(wt->root, w, h);
95 void wt_graphics(struct wt_graphics *gfx)
100 for(i=0; i<NUM_COLORS; i++) {
101 r = def_colors[i] >> 16;
102 g = (def_colors[i] >> 8) & 0xff;
103 b = def_colors[i] & 0xff;
104 if((wt->colors[i] = gfx->newcolor(r, g, b)) == -1) {
105 wt->colors[i] = i ? wt->colors[i - 1] : 0;
110 void wt_inp_key(int key, int press)
114 void wt_inp_mouse(int bn, int st, int x, int y)
118 void wt_inp_motion(int x, int y)
122 void wt_draw_tree(wt_widget *tree)
127 if(wt->gfx.flags & WT_GFX_NODIRTY) {
128 tree->draw(tree, &wt->gfx);
131 tree->draw(tree, &wt->gfx);
133 if(!tree->parent || !tree->parent->dirty) {
134 /* topmost dirty widget should update rects */
135 if(tree->type == WT_TYPE_WINDOW) {
137 calc_window_rect(&r, tree);
140 wt_add_upd_rect(&tree->rect);
147 for(i=0; i<tree->num_child; i++) {
148 wt_draw_tree(tree->child[i]);
157 wt_draw_tree(wt->root);
165 struct wt_rect *wt_upd_rect(int idx)
167 if(idx < 0 || idx >= wt->num_upd) {
170 return wt->upd + idx;
173 void wt_add_upd_rect(struct wt_rect *r)
178 for(i=0; i<wt->num_upd; i++) {
179 if(wt_rect_overlap(wt->upd + i, r)) {
181 wt->upd[i] = wt->upd[--wt->num_upd];
182 wt_rect_union(&rect, r);
183 wt_add_upd_rect(&rect);
188 /* no overlaps found, add it if there is space, or union with existing if not */
189 if(wt->num_upd >= MAX_UPD_RECTS) {
190 wt_rect_union(wt->upd, r);
192 wt->upd[wt->num_upd++] = *r;
197 void wt_gfx_color(int cidx)
199 wt->gfx.color(wt->colors[cidx]);
202 void wt_gfx_fillrect(struct wt_rect *r)
207 void wt_gfx_fillrect4i(int x, int y, int w, int h)
210 wt_rect(&r, x, y, w, h);
211 wt->gfx.fillrect(&r);
214 void wt_gfx_frame(struct wt_rect *r, int style, int basecol)
216 if((style & FRM_NOFILL) == 0) {
217 wt_gfx_color(basecol);
220 wt_gfx_color(FRMSTYLE(style) == FRM_OUT ? basecol + 2 : basecol + 1);
221 wt_gfx_fillrect4i(r->x + 1, r->y + r->h - 1, r->w - 2, 1);
222 wt_gfx_fillrect4i(r->x + r->w - 1, r->y, 1, r->h);
223 wt_gfx_color(FRMSTYLE(style) == FRM_OUT ? basecol + 1 : basecol + 2);
224 wt_gfx_fillrect4i(r->x + 1, r->y, r->w - 2, 1);
225 wt_gfx_fillrect4i(r->x, r->y, 1, r->h);
228 void wt_gfx_line(int x0, int y0, int x1, int y1)
230 wt->gfx.line(x0, y0, x1, y1);
233 void wt_rect(struct wt_rect *r, int x, int y, int w, int h)
241 void wt_rect_union(struct wt_rect *a, struct wt_rect *b)
248 if(b->x < a->x) a->x = b->x;
249 if(b->y < a->y) a->y = b->y;
250 if(b->x + b->w > x1) x1 = b->x + b->w;
251 if(b->y + b->h > y1) y1 = b->y + b->h;
257 int wt_rect_overlap(struct wt_rect *a, struct wt_rect *b)
259 if(a->x > b->x + b->w) return 0;
260 if(b->x > a->x + a->w) return 0;
261 if(a->y > b->y + b->h) return 0;
262 if(b->y > a->x + a->h) return 0;