8 #include "../graphics.h"
14 static struct widget_t
*widget_nameid_follow_va(struct widget_t
*widget
,
17 static void set_default_pos(struct widget_t
*widget
);
18 static void set_pos_pack_top(struct xuni_t
*xuni
, struct widget_t
*widget
);
19 static void reposition_widget_pack(struct xuni_t
*xuni
,
20 struct widget_t
*widget
);
21 static void reposition_widget_nonrec(struct xuni_t
*xuni
,
22 struct widget_t
*widget
);
23 static void free_widget(struct xuni_t
*xuni
, struct widget_t
*widget
);
24 static void update_text_widget(struct xuni_t
*xuni
, struct widget_t
*widget
);
25 static void paint_widget(struct xuni_t
*xuni
, struct widget_t
*widget
);
26 static void reposition_widget(struct xuni_t
*xuni
, struct widget_t
*widget
);
27 static void rescale_widget(struct xuni_t
*xuni
, struct widget_t
*widget
);
29 static int widget_type_compare(void *data
, size_t n
, void *find
);
31 void delete_widget(struct xuni_t
*xuni
, struct panel_t
*panel
, size_t n
) {
32 free_widget(xuni
, panel
->widget
[n
]);
34 if(n
+ 1 < panel
->widgets
) {
35 memmove(panel
->widget
+ n
, panel
->widget
+ n
+ 1,
36 (panel
->widgets
- n
- 1) * sizeof(*panel
->widget
));
40 panel
->widget
= xuni_memory_resize(panel
->widget
, panel
->widgets
41 * sizeof(*panel
->widget
));
44 void delete_widget_pointer(struct xuni_t
*xuni
, struct widget_t
*widget
) {
50 for(x
= 0; x
< widget
->base
->compose
->widgets
; x
++) {
51 if(widget
== widget
->base
->compose
->widget
[x
]) {
52 delete_widget(xuni
, widget
->base
->compose
, x
);
57 else free_widget(xuni
, widget
);
60 void add_widget(struct panel_t
*panel
, struct widget_t
*widget
) {
61 panel
->widget
= xuni_memory_resize(panel
->widget
, (panel
->widgets
+ 1)
62 * sizeof(*panel
->widget
));
63 panel
->widget
[panel
->widgets
] = widget
;
67 void add_allocate_widget(struct widget_t
*base
, char *name
) {
68 add_widget(base
->compose
, allocate_widget(name
, base
));
71 void add_allocate_widget_compose(struct widget_t
*base
, char *name
) {
72 if(!base
->compose
) base
->compose
= allocate_panel(base
);
74 add_allocate_widget(base
, name
);
77 struct panel_t
*allocate_panel(struct widget_t
*base
) {
78 struct panel_t
*panel
;
80 panel
= xuni_memory_allocate(sizeof(*panel
));
88 /*! Returns a new, dynamically allocated widget. The widget's name becomes
89 \a name and its parent widget (widget_t::base) is set to \a base.
90 Otherwise, the widget is initialized to default values.
92 This function should be followed immediately by a call to init_*() to
93 initialize an instance of a specific type of widget; otherwise the widget
94 is virtually useless, with a type of WIDGET_NONE.
96 \param name The name of the new widget.
97 \param base The parent widget of the new widget.
98 \return The newly allocated widget.
100 struct widget_t
*allocate_widget(char *name
, struct widget_t
*base
) {
101 struct widget_t
*widget
= xuni_memory_allocate(sizeof(*widget
));
103 /*widget->p.all = xuni_memory_allocate(sizeof_widget_structure(type));*/
104 /*widget->p.all = 0;*/
107 widget
->id
= (size_t)-1;
109 widget
->type
= WIDGET_NONE
;
114 widget
->visibility
= WIDGET_VISIBILITY_ALL
;
116 widget
->selwidget
= 0;
124 void init_widget_pos(struct widget_t
*widget
, double x
, double y
,
125 double w
, double h
, enum pos_pack_t pack
) {
128 widget
->pos
= xuni_memory_allocate(sizeof(*widget
->pos
));
131 widget
->pos
->pack
= pack
;
133 widget
->pos
->scale
.x
= x
;
134 widget
->pos
->scale
.y
= y
;
135 widget
->pos
->scale
.w
= w
;
136 widget
->pos
->scale
.h
= h
;
138 widget
->pos
->clip
= 0;
140 /* widget->pos->real.* set by rescale_widget() */
143 void clear_widget_clip(struct xuni_t
*xuni
, struct widget_t
*widget
) {
146 if(widget
->pos
->clip
) {
147 widget
->pos
->clip
->xoff
= 0;
148 widget
->pos
->clip
->yoff
= 0;
149 widget
->pos
->clip
->xclip
= 0;
150 widget
->pos
->clip
->yclip
= 0;
152 reposition_widget_pack(xuni
, widget
);
154 /* !!! should this be before the above call or not? */
155 widget
->pos
->clip
->wclip
= widget
->pos
->real
.w
;
156 widget
->pos
->clip
->hclip
= widget
->pos
->real
.h
;
160 void add_panel_clip(struct xuni_t
*xuni
, struct widget_t
*widget
,
161 int xoff
, int yoff
, int xclip
, int yclip
, int wclip
, int hclip
) {
165 if(!widget
->pos
->clip
) {
166 widget
->pos
->clip
= xuni_memory_allocate(sizeof(*widget
->pos
->clip
));
167 clear_widget_clip(xuni
, widget
);
170 if(widget
&& widget
->compose
) {
171 for(x
= 0; x
< widget
->compose
->widgets
; x
++) {
172 add_widget_clip(xuni
, widget
->compose
->widget
[x
], xoff
, yoff
,
173 xclip
, yclip
, wclip
, hclip
);
178 void add_widget_clip_nonrec(struct xuni_t
*xuni
, struct widget_t
*widget
,
179 int xoff
, int yoff
, int xclip
, int yclip
, int wclip
, int hclip
) {
183 if(!widget
->pos
->clip
) {
184 widget
->pos
->clip
= xuni_memory_allocate(sizeof(*widget
->pos
->clip
));
185 clear_widget_clip(xuni
, widget
);
188 /*widget->pos->clip->xoff += xoff;
189 widget->pos->clip->yoff += yoff;*/
190 widget
->pos
->clip
->xclip
+= xclip
;
191 widget
->pos
->clip
->yclip
+= yclip
;
192 widget
->pos
->clip
->wclip
+= wclip
;
193 widget
->pos
->clip
->hclip
+= hclip
;
195 widget
->pos
->real
.x
+= xoff
;
196 widget
->pos
->real
.y
+= yoff
;
197 /*widget->pos->real.w += xclip;
198 widget->pos->real.h += yclip;*/
199 /* !!! need to do something with wclip and hclip, too */
201 /*printf("add_widget_clip(): \"%s\" = (%i,%i) (%i,%i,%i,%i)",
202 widget->base->name, xoff, yoff, xclip, yclip, wclip, hclip);
203 printf(" -> (%i,%i) (%i,%i,%i,%i)\n",
204 widget->pos->clip->xoff,
205 widget->pos->clip->yoff,
206 widget->pos->clip->xclip,
207 widget->pos->clip->yclip,
208 widget->pos->clip->wclip,
209 widget->pos->clip->hclip);*/
212 void add_widget_clip(struct xuni_t
*xuni
, struct widget_t
*widget
,
213 int xoff
, int yoff
, int xclip
, int yclip
, int wclip
, int hclip
) {
219 add_widget_clip_nonrec(xuni
, widget
,
220 xoff
, yoff
, xclip
, yclip
, wclip
, hclip
);
222 if(widget
->compose
) {
223 for(x
= 0; x
< widget
->compose
->widgets
; x
++) {
224 add_widget_clip(xuni
, widget
->compose
->widget
[x
], xoff
, yoff
,
229 /*printf("add_widget_clip(): \"%s\" = (%i,%i) (%i,%i,%i,%i)",
230 widget->base->name, xoff, yoff, xclip, yclip, wclip, hclip);
231 printf(" -> (%i,%i) (%i,%i,%i,%i)\n",
232 widget->pos->clip->xoff,
233 widget->pos->clip->yoff,
234 widget->pos->clip->xclip,
235 widget->pos->clip->yclip,
236 widget->pos->clip->wclip,
237 widget->pos->clip->hclip);*/
240 void add_widget_accelerator(struct xuni_t
*xuni
, struct widget_t
*panel
,
241 struct widget_t
*widget
, SDLKey key
, SDLMod mod
) {
243 struct panel_data_t
*data
;
245 if(!panel
|| panel
->type
!= WIDGET_PANEL
|| !panel
->p
.panel
) {
246 printf("*** add_widget_accelerator() called with invalid widget:\n");
247 print_widget_backtrace(xuni
, widget
);
251 data
= panel
->p
.panel
;
254 data
->accel
= xuni_memory_allocate(sizeof(*data
->accel
));
255 data
->accel
->key
= 0;
259 data
->accel
->key
= xuni_memory_resize(data
->accel
->key
,
260 (data
->accel
->n
+ 1) * sizeof(*data
->accel
->key
));
261 data
->accel
->key
[data
->accel
->n
].key
.sym
= key
;
262 data
->accel
->key
[data
->accel
->n
].key
.mod
= mod
;
263 data
->accel
->key
[data
->accel
->n
].widget
= widget
;
268 /*! Returns the last compose widget of \a widget.
270 This is frequently used in the widget initialization functions to refer
271 to the last sub-widget added.
273 \param widget The widget for which to return the last compose widget.
274 \return The last compose widget of \a widget, or NULL if the widget does
275 not have any sub-widgets.
277 struct widget_t
*last_compose_widget(struct widget_t
*widget
) {
278 if(!widget
->compose
|| !widget
->compose
->widgets
) return 0;
280 return widget
->compose
->widget
[widget
->compose
->widgets
- 1];
283 /*struct widget_t *compose_access_widget(struct widget_t *widget, size_t n) {
284 if(!widget || !widget->compose || n >= widget->compose->widgets) return 0;
286 return widget->compose->widget[n];
289 size_t get_compose_widgets(struct widget_t *widget) {
290 if(!widget || !widget->compose) return 0;
292 return widget->compose->widgets;
295 /*! Searches \a widget for the registered nameid \a n.
296 \param widget The widget to search for the nameid \a n. Should be a panel
298 \param n The nameid to search \a widget for.
299 \return The widget for the nameid \a n, or zero the nameid was not found.
300 Also returns zero if \a widget is not of type panel or theme, or if
303 struct widget_t
*widget_nameid_access(struct widget_t
*widget
, size_t n
) {
304 if(!widget
) return 0;
306 if(widget
->type
== WIDGET_PANEL
) {
307 if(widget
->p
.panel
->nameid
308 && n
< widget
->p
.panel
->nameid
->widgets
) {
310 return widget
->p
.panel
->nameid
->widget
[n
].widget
;
313 else if(widget
->type
== WIDGET_THEME
) {
314 if(widget
->p
.theme
->nameid
315 && n
< widget
->p
.theme
->nameid
->widgets
) {
317 return widget
->p
.theme
->nameid
->widget
[n
].widget
;
324 /*! Starting at \a widget, follows a series of nameids. This is a private
325 implementation, used by widget_nameid_follow(). It takes a \c va_list
326 parameter instead of "...".
328 \param widget The widget to start searching from.
329 \param arg The series of nameids to follow, starting at \a widget.
330 \return The widget that was eventually found, if any, or NULL otherwise.
332 static struct widget_t
*widget_nameid_follow_va(struct widget_t
*widget
,
337 while((id
= va_arg(arg
, size_t)) != (size_t)-1) {
338 widget
= widget_nameid_access(widget
, id
);
339 if(!widget
) return 0;
345 /*! Starting at \a widget, follows a series of nameids. The series must be
346 terminated with (size_t)-1.
348 Equivalent to multiple calls to widget_nameid_access().
350 \param widget The widget to start searching for the first nameid. Should
351 be a panel or theme widget.
352 \param ... The series of nameids to follow, terminated with (size_t)-1.
353 \return The widget specified by all of the nameids, if found, or NULL
356 struct widget_t
*widget_nameid_follow(struct widget_t
*widget
, ...) {
357 struct widget_t
*found
;
360 va_start(arg
, widget
);
361 found
= widget_nameid_follow_va(widget
, arg
);
367 /*! Returns true if the widget \a search is equal to \a widget or one of its
369 \param search The widget to search for.
370 \param widget The widget to search through, following base pointers until
371 the root widget is reached.
372 \return True if the widget \a search was found in the widget path that
375 int widget_is_parent(struct widget_t
*search
, struct widget_t
*widget
) {
377 if(search
== widget
) return 1;
378 widget
= widget
->base
;
384 /*! Returns true if \a string and \a len characters of \a buffer match. This
385 function is sort of like strncmp() -- however, it compares the lengths of
386 the strings before comparing their contents. This means that a calls like
387 widget_name_match("some", "some", 5)
388 widget_name_match("something", "some", 4)
389 will not return true, even though they would for strncmp().
391 This function is used for matching widget names, unsurprisingly. \a string
392 can contain the name of a widget, say "xuni", and \a buffer can contain a
393 path to a widget, say "xuni/etc", and this function will be able to match
396 \param string The widget name to look for at the beginning of \a buffer.
397 \param buffer The widget path in which to look at the first \a len
398 characters, and to compare with \a string.
399 \param len The number of characters in \a buffer that should be
400 considered. The length of \a string must also equal this value for a
402 \return True if a match was found, false otherwise.
404 int widget_name_match(const char *string
, const char *buffer
, size_t len
) {
405 if(!string
|| !buffer
) return 0;
407 return strlen(string
) == len
&& !strncmp(string
, buffer
, len
);
410 /*! Searches for the widget specified by \a name, with respect to \a widget.
412 \a name is not just the name of a widget. It can also contain slashes to
413 specify child widgets; ".." to specify the parent widget; and "." to
414 specify the current widget \a widget. (An empty string also specifies
417 Note: this function currently does not handle double slashes (like
418 "this//that"). (They are treated as widgets with empty names.) Nor does it
419 support backslashes, just slashes.
421 \param widget The widget to start searching from.
422 \param name The path to the widget that is being sought.
423 \return The widget specified by \a name starting at \a widget, if found,
426 struct widget_t
*find_widget(struct widget_t
*widget
, const char *name
) {
431 if(!name
|| !widget
) return 0;
434 for(end
= name
; *end
&& *end
!= '/'; end
++);
436 if(widget_name_match(".", name
, end
- name
)) {
437 if(!*end
) return widget
;
443 if(widget_name_match("..", name
, end
- name
)) {
444 if(!*end
) return widget
->base
;
445 return find_widget(widget
->base
, end
+ 1);
448 if(widget
->compose
) {
449 for(x
= 0; x
< widget
->compose
->widgets
; x
++) {
450 if(widget_name_match(widget
->compose
->widget
[x
]->name
,
453 if(!*end
) return widget
->compose
->widget
[x
];
454 p
= find_widget(widget
->compose
->widget
[x
], end
+ 1);
463 /*! Sends an event of type \a event to the widget \a widget.
465 The event is passed through several functions before finally being handled
466 by {widget}_widget_event() (e.g., button_widget_event()), which usually
467 defers to {event}_{widget}() (e.g., rescale_button()).
469 \param xuni A pointer to the main xuni_t structure.
470 \param widget The widget to send the event to.
471 \param event The type of event to send to the widget.
473 void widget_event(struct xuni_t
*xuni
, struct widget_t
*widget
,
474 enum widget_event_t event
) {
476 static void (*function
[])(struct xuni_t
*xuni
, struct widget_t
*widget
)
486 call_widget_event_func(xuni
, widget
, event
, function
,
487 sizeof(function
) / sizeof(*function
));
490 /*! Sends a widget event to all subwidgets of \a widget, but not to \a widget
493 Useful in generic widget event handlers to pass on an event to subwidgets.
495 \param xuni A pointer to the main xuni structure. Passed on to the widget
496 event handling functions.
497 \param widget The widget for which to send a widget event to all the
499 \param event The widget event type to send to the composing widgets of
502 void widget_compose_event(struct xuni_t
*xuni
, struct widget_t
*widget
,
503 enum widget_event_t event
) {
507 if(!widget
->compose
) return;
509 for(x
= 0; x
< widget
->compose
->widgets
; x
++) {
510 widget_event(xuni
, widget
->compose
->widget
[x
], event
);
514 static void set_default_pos(struct widget_t
*widget
) {
515 if(!widget
|| !widget
->pos
) return;
517 widget
->pos
->real
.x
= 0;
518 widget
->pos
->real
.y
= 0;
519 widget
->pos
->real
.w
= 0;
520 widget
->pos
->real
.h
= 0;
523 static void set_pos_pack_top(struct xuni_t
*xuni
, struct widget_t
*widget
) {
524 struct widget_t
*prev
;
529 widget
->pos
->real
.w
= 0;
530 widget
->pos
->real
.h
= 0;
532 if(!widget
->base
|| !widget
->base
->pos
) {
533 set_default_pos(widget
);
537 for(x
= 0; x
< widget
->base
->compose
->widgets
; x
++) {
538 if(widget
== widget
->base
->compose
->widget
[x
]) break;
541 widget
->pos
->real
.x
= widget
->base
->pos
->real
.x
;
542 widget
->pos
->real
.y
= widget
->base
->pos
->real
.y
;
545 prev
= widget
->base
->compose
->widget
[x
- 1];
547 if(prev
->type
== WIDGET_LABEL
) {
548 if(prev
->p
.label
->label
) {
550 = prev
->pos
->real
.y
+ prev
->p
.label
->label
->h
;
553 printf("Error: widget's prev label not set: %lu; prev:\n",
555 print_inline_widget_backtrace(prev
);
557 widget
->pos
->real
.y
= prev
->pos
->real
.y
;
560 /*else if(prev->pos) {
561 widget->pos->real.y += prev->pos->scale.y / 100.0 * smode->height;
564 printf("*** Can't pack after widgets of type \"%s\"\n",
565 get_widget_type_name(xuni
, prev
->type
));
570 int get_real_pos(double scale
, int basereal
) {
571 return (int)((scale
/ 100.0) * basereal
);
574 static void reposition_widget_pack(struct xuni_t
*xuni
,
575 struct widget_t
*widget
) {
577 if(!widget
->pos
) return;
579 switch(widget
->pos
->pack
) {
581 if(widget
->base
&& widget
->base
->pos
) {
582 /*printf("using base: (%i,%i) by (%i,%i)\n",
583 widget->base->pos->real.x, widget->base->pos->real.y,
584 widget->base->pos->real.w, widget->base->pos->real.h);*/
585 widget
->pos
->real
.x
= get_real_pos(
586 widget
->pos
->scale
.x
, widget
->base
->pos
->real
.w
)
587 + widget
->base
->pos
->real
.x
;
588 widget
->pos
->real
.y
= get_real_pos(
589 widget
->pos
->scale
.y
, widget
->base
->pos
->real
.h
)
590 + widget
->base
->pos
->real
.y
;
592 widget
->pos
->real
.w
= get_real_pos(
593 widget
->pos
->scale
.w
, widget
->base
->pos
->real
.w
);
594 widget
->pos
->real
.h
= get_real_pos(
595 widget
->pos
->scale
.h
, widget
->base
->pos
->real
.h
);
598 /*puts("(no base)");*/
600 = widget
->pos
->scale
.x
/ 100.0 * xuni
->smode
->width
;
602 = widget
->pos
->scale
.y
/ 100.0 * xuni
->smode
->height
;
604 = widget
->pos
->scale
.w
/ 100.0 * xuni
->smode
->width
;
606 = widget
->pos
->scale
.h
/ 100.0 * xuni
->smode
->height
;
609 /*printf("%20s: (%i,%i) by (%i,%i)\n", widget->name,
610 widget->pos->real.x, widget->pos->real.y,
611 widget->pos->real.w, widget->pos->real.h);*/
615 set_pos_pack_top(xuni
, widget
);
619 printf("*** Invalid pos pack type: %i\n", (int)widget
->pos
->pack
);
623 /* !!! temporarily fixes the "listbox scroll problem" */
624 if(widget
->type
== WIDGET_LABEL
&& !widget
->pos
->scale
.w
625 && !widget
->pos
->scale
.h
&& widget
->p
.label
->label
) {
627 widget
->pos
->real
.w
= widget
->p
.label
->label
->w
;
628 widget
->pos
->real
.h
= widget
->p
.label
->label
->h
;
632 if(widget
->base
&& widget
->base
->pos
) {
633 widget
->pos
->real
.x
+= widget
->base
->pos
->real
.x
;
634 widget
->pos
->real
.y
+= widget
->base
->pos
->real
.y
;
639 static void reposition_widget_nonrec(struct xuni_t
*xuni
,
640 struct widget_t
*widget
) {
642 clear_widget_clip(xuni
, widget
);
644 call_widget_event(xuni
, widget
, WIDGET_EVENT_REPOSITION
);
647 static void reposition_widget(struct xuni_t
*xuni
, struct widget_t
*widget
) {
650 reposition_widget_pack(xuni
, widget
);
652 widget_compose_event(xuni
, widget
, WIDGET_EVENT_REPOSITION
);
654 reposition_widget_nonrec(xuni
, widget
);
657 static void rescale_widget(struct xuni_t
*xuni
, struct widget_t
*widget
) {
660 reposition_widget_pack(xuni
, widget
);
662 widget_compose_event(xuni
, widget
, WIDGET_EVENT_RESCALE
);
664 reposition_widget_nonrec(xuni
, widget
);
666 if(widget
->type
!= WIDGET_PANEL
) {
667 call_widget_event(xuni
, widget
, WIDGET_EVENT_RESCALE
);
671 static void paint_widget(struct xuni_t
*xuni
, struct widget_t
*widget
) {
674 if(widget
->visibility
& WIDGET_VISIBILITY_VISIBLE
) {
675 call_widget_event(xuni
, widget
, WIDGET_EVENT_PAINT
);
677 if(widget
->repaint
) {
683 static void update_text_widget(struct xuni_t
*xuni
, struct widget_t
*widget
) {
686 call_widget_event(xuni
, widget
, WIDGET_EVENT_UPDATE_TEXT
);
688 widget_compose_event(xuni
, widget
, WIDGET_EVENT_UPDATE_TEXT
);
691 static void free_widget(struct xuni_t
*xuni
, struct widget_t
*widget
) {
694 if(!xuni_memory_decrement(widget
)) return;
696 call_widget_event(xuni
, widget
, WIDGET_EVENT_FREE
);
699 xuni_memory_free(widget
->pos
->clip
);
700 xuni_memory_free(widget
->pos
);
703 free_panel(xuni
, widget
->compose
);
708 void init_wtype(struct xuni_t
*xuni
, struct wtype_array_t
*wtype
) {
712 register_widget_type(xuni
, "box", WIDGET_BOX
, box_widget_event
);
713 register_widget_type(xuni
, "button", WIDGET_BUTTON
, button_widget_event
);
714 register_widget_type(xuni
,
715 "checkbox", WIDGET_CHECKBOX
, checkbox_widget_event
);
716 register_widget_type(xuni
,
717 "combobox", WIDGET_COMBOBOX
, combobox_widget_event
);
718 register_widget_type(xuni
, "font", WIDGET_FONT
, font_widget_event
);
719 register_widget_type(xuni
, "image", WIDGET_IMAGE
, image_widget_event
);
720 register_widget_type(xuni
,
721 "image tile", WIDGET_IMAGE_TILE
, image_tile_widget_event
);
722 register_widget_type(xuni
, "label", WIDGET_LABEL
, label_widget_event
);
723 register_widget_type(xuni
,
724 "listbox", WIDGET_LISTBOX
, listbox_widget_event
);
725 register_widget_type(xuni
, "panel", WIDGET_PANEL
, panel_widget_event
);
726 register_widget_type(xuni
,
727 "scrollbar", WIDGET_SCROLLBAR
, scrollbar_widget_event
);
728 register_widget_type(xuni
,
729 "textarea", WIDGET_TEXTAREA
, textarea_widget_event
);
730 register_widget_type(xuni
,
731 "textbox", WIDGET_TEXTBOX
, textbox_widget_event
);
732 register_widget_type(xuni
, "theme", WIDGET_THEME
, theme_widget_event
);
735 /*! Frees the memory allocated for a wtype_array_t structure. Used by
736 free_xuni() to free the structure of that type that is a memory of struct
738 \param wtype The structure to free the memory for.
740 void free_wtype(struct wtype_array_t
*wtype
) {
741 xuni_memory_free(wtype
->type
);
744 static int widget_type_compare(void *data
, size_t n
, void *find
) {
745 struct wtype_t
*array
= data
;
746 const char *a
= find
;
747 const char *b
= array
[n
].name
;
752 void register_widget_type(struct xuni_t
*xuni
, const char *name
, size_t type
,
753 widget_event_handler_t handler
) {
757 if(binary_insertion_sort(xuni
->wtype
->type
, xuni
->wtype
->types
,
758 name
, &pos
, widget_type_compare
)) {
760 log_message(ERROR_TYPE_DATASTRUCT
, 0, __FILE__
, __LINE__
,
761 "Adding duplicate widget type \"%s\"", name
);
765 xuni
->wtype
->type
= xuni_memory_resize(xuni
->wtype
->type
,
766 (xuni
->wtype
->types
+ 1) * sizeof(*xuni
->wtype
->type
));
767 memmove(xuni
->wtype
->type
+ pos
+ 1, xuni
->wtype
->type
+ pos
,
768 (xuni
->wtype
->types
- pos
) * sizeof(*xuni
->wtype
->type
));
769 xuni
->wtype
->types
++;
771 xuni
->wtype
->type
[pos
].name
= name
;
772 xuni
->wtype
->type
[pos
].handler
= handler
;
775 void call_widget_event(struct xuni_t
*xuni
, struct widget_t
*widget
,
776 enum widget_event_t type
) {
778 /* The first condition is not strictly necessary, being encompassed by the
779 second one as it is, but it is included for clarity.
781 if(widget
->type
== (size_t)-1 || widget
->type
>= xuni
->wtype
->types
) {
782 log_message(ERROR_TYPE_WARNING
, 0, __FILE__
, __LINE__
,
783 "Invalid or unregistered widget type: %i\n", (int)widget
->type
);
787 xuni
->wtype
->type
[widget
->type
].handler(xuni
, widget
, type
);
790 void call_widget_event_func(struct xuni_t
*xuni
, struct widget_t
*widget
,
791 enum widget_event_t event
, widget_event_func_t function
[],
794 if(event
>= functions
) {
795 log_message(ERROR_TYPE_LOOKUP_TABLE
, 0, __FILE__
, __LINE__
,
796 "\"%s\": supports %lu events, tried to access [%lu]\n",
797 xuni
->wtype
->type
[widget
->type
].name
,
798 (unsigned long)functions
, (unsigned long)event
);
802 if(function
[event
]) {
803 (*function
[event
])(xuni
, widget
);
807 /*! Makes sure that the widget \a widget is of type \a type. If it isn't,
808 raises an error message and returns nonzero.
810 Used where a specific widget type is expected, such as for widget event
813 \param xuni A pointer to the main xuni structure. The wtype member of this
814 structure is used to determine the names of widgets, if the widget
815 \a widget did not match the expected type.
816 \param widget The widget to examine. Should be of type \a type.
817 \param type The type that the widget \a widget ought to be.
818 \param file The file in which the calling function is located. Should be
819 \c __FILE__. (Used to report widget type mismatches.)
820 \param line The line number that this function was called from. Should be
821 \c __LINE__. (Used when the widget \a widget did not match the
823 \return Zero if the widget \a widget is of the expected type \a type,
826 int assert_widget_type(struct xuni_t
*xuni
, struct widget_t
*widget
,
827 size_t type
, const char *file
, int line
) {
829 if(widget
->type
!= type
) {
830 log_message(ERROR_TYPE_DATASTRUCT
, 0, file
, line
,
831 "Widget type mismatch: expected type %s, got type %s",
832 get_widget_type_name(xuni
, type
),
833 get_widget_type_name(xuni
, widget
->type
));
841 /*! Returns the visibility of \a widget, AND'ed with \a visibility. This means
842 that the return value will be \a visibility if all of the OR'd visibility
843 types in \a visibility are true.
845 \param widget The widget to check for the visibilities in \a visibility.
846 \param visibility The visibilities to check \a widget for.
847 \return The visibility of the widget \a widget AND'ed with \a visibility.
849 int get_widget_visibility(struct widget_t
*widget
,
850 enum widget_visibility_t visibility
) {
852 if(!widget
) return 0;
854 return widget
->visibility
& visibility
;
857 /*! Sets or unsets the visibility of the widget \a widget.
858 \param widget The widget for which to set or unset the visibility of.
859 \param visibility An OR'd value of widget_visibility_ts, describing what
860 visibility type should be set or unset.
861 \param set True or false, to set or unset the visibility \a visibility.
863 void set_widget_visibility(struct widget_t
*widget
,
864 enum widget_visibility_t visibility
, int set
) {
869 widget
->visibility
|= visibility
;
872 widget
->visibility
&= ~visibility
;