From 08eef76a0167c17a9d20c569d7c8fce1e195f2ed Mon Sep 17 00:00:00 2001 From: dwk Date: Wed, 7 May 2008 16:45:42 -0400 Subject: [PATCH] Minor changes, mostly to documentation. Several bug fixes. In the README file: - Converted reference to xuni version 1.0.0 to 0.3.0 - Updated the website for xuni from theprogrammingsite to SourceForge - Added mention of git instead of svn - Re-worded "garbage collector" and the "ANSI standard" paragraph Changes to source code: - Made get_angle() take a pointer to the tag, simplifying it somewhat - Added binary_insertion_sort() to utility.c - This replaces the bulk of memory_find_data() - It could make () easier in the future - Removed the very old and commented-out print_sizes() from xuni.c - Experimented with alternative ways to rescale text to the right ratios - get_real_pos() now takes a double instead of an int - Removed the currently-unused wtype_t::type (and the one reference to it) Bug fixes: - Added validate_xuni_structure(), which detects when: - No root widget is present (which is currently a fatal error) - No themes have been loaded (this should use a default theme -- with primitives?) - parse_resource() used to segfault when no resource files could be loaded - Failing to load an XML resource file is no longer marked as a fatal error Doxygen documentation: - gui.c (new: 3 functions) - utility.c (new: 1 function) - font.c (modified: 1 function) - widget.c (new: 4 functions) Changes to XML resource files: - Removed old, spurious element from editor.xml - Added test widgets to gui/editor.xml, such as a grid checkbox Other changes: - Simplified filecount.sh -- it no longer uses perl, just a flag to make --- README | 25 +++++++++++---------- editor.xml | 4 ---- filecount.sh | 2 +- gui/data/options.xml | 9 ++++++++ src/graphics.c | 1 + src/gui.c | 46 ++++++++++++++++++++++++++++++++++----- src/loop.c | 3 +++ src/memory.c | 24 +++++++++++++++++--- src/resource/resource.c | 2 +- src/test/main.c | 2 +- src/utility.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++ src/utility.h | 3 +++ src/widget/font.c | 20 +++++++++++++---- src/widget/widgets.c | 54 ++++++++++++++++++++++++++++++++++++++++----- src/widget/widgets.h | 10 +++++---- src/xuni.c | 58 +++++++++++++++++++++---------------------------- 16 files changed, 246 insertions(+), 72 deletions(-) diff --git a/README b/README index 594373a..9bae5bb 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -This is the README for xuni version 1.0.0. +This is the README for xuni version 0.3.0. === Contents - About @@ -25,9 +25,9 @@ addition to the SDL, along with expat. xuni supports many features, including: - Coordinates as percentages of the parent widget - Coordinates as mathematical expressions (like "100 / 3") [1] - - Garbage collection (really just a reference counter) - No required external resource files (except XML data) [2] - Portable code [3] + - Reference counting - Rescalable widgets, images, text -- almost everything - Screen updates when states of widgets change (optional) - Theming support @@ -41,10 +41,11 @@ xuni supports many features, including: will still run. The exceptions to this, of course, are the XML data files -- without those xuni has nothing to display. -[3] xuni does not use any features outside of ANSI C99, and can be compiled as -C89 by commenting out the line in version.h that defines "VERSION_STDC_C99". -xuni has been tested by the author under 32- and 64-bit Debian GNU/Linux, -along with Windows 98, XP, and (32-bit) Vista. +[3] Besides its dependencies on various libraries, of course, xuni does not use +any features outside of ANSI C99, and can be compiled as C89 by commenting out +the line in version.h that defines "VERSION_STDC_C99". xuni has been tested by +the author under 32- and 64-bit Debian GNU/Linux, along with Windows 98, XP, +and (32-bit) Vista, as well as under Wine. --- Disclaimers Note that support for these features may not work with certain releases. It's @@ -64,8 +65,8 @@ however, there are precious few comments. --- Programs Doxygen is used to generate documentation from documentation comments in the -source code. Subversion is used for version control (although the repository -is not hosted online just yet). yacc/bison is used to parse calc.y. +source code. Subversion was used for version control, and now git is used. +yacc/bison is used to parse calc.y. --- Artwork The neat xuni logo, the cloud backgrounds, menuhover and all other green @@ -81,16 +82,18 @@ The amazing astronomy background pictures are all from NASA. --- Notes - Function pointers are used in many different places, for callbacks etc. - Unions of pointer types are preferred to void pointers at the moment - - Though xuni is quite tied to the SDL, it is not tied to expat or even - to XML resource files + - Though xuni is quite tied to the SDL, it is not tied to expat (as the mxml + implementation shows) or even to XML resource files - All memory management is handled by memory.c, unless one can guarantee that there will only be one pointer to a block of memory -- for example, if the same function allocates and frees the memory - Speed is usually considered more important than memory efficiency + - Flexibility is often considered most important of all === Contact At the time of this writing, xuni can be obtained from: - http://dwks.theprogrammingsite.com/myprogs/xuni.htm + http://xuni.sourceforge.net/ +The same site has a message board where you can post thoughts about xuni. You can reach the author by email at dwks at theprogrammingsite period com. diff --git a/editor.xml b/editor.xml index 2320606..dad795e 100644 --- a/editor.xml +++ b/editor.xml @@ -13,9 +13,5 @@ gui/icon.bmp - - alienglow - - gui/editor.xml diff --git a/filecount.sh b/filecount.sh index 8502970..fc4d38c 100755 --- a/filecount.sh +++ b/filecount.sh @@ -1,4 +1,4 @@ #!/bin/sh -make wc | perl -ne 'print if(++$n>1)' | head -n -1 | wc -l +make -s wc | head -n -1 | wc -l diff --git a/gui/data/options.xml b/gui/data/options.xml index 911a2b6..8c01121 100644 --- a/gui/data/options.xml +++ b/gui/data/options.xml @@ -205,6 +205,15 @@ 100.0 / 15 * 3 + + font combo 100 - 100 / 16 - 100.0 / 4 diff --git a/src/graphics.c b/src/graphics.c index ace9838..06646f8 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -90,6 +90,7 @@ void init_sdl_libraries(struct smode_t *smode, const char *icon) { SDL_EnableUNICODE(0); if(TTF_Init() < 0) { + /* !!! this doesn't have to be a fatal error */ log_message(ERROR_TYPE_FATAL, 0, __FILE__, __LINE__, "Can't init SDL_ttf: %s", TTF_GetError()); } diff --git a/src/gui.c b/src/gui.c index 33263c8..4289b8f 100644 --- a/src/gui.c +++ b/src/gui.c @@ -171,6 +171,17 @@ void edit_del_char(struct widget_edit_t *edit) { edit->len --; } +/*! Clears the sel member of the widget \a widget and all of its child + widgets. Returns true if a repaint will be required; i.e., if any widget + that had its sel member set to false was originally true. (If this was the + case, a widget will have changed from selected to not selected, and a + repaint would be necessary.) + + \param widget The widget at the top of the tree of widgets to clear the + sel members of. + \return True if a repaint is needed, that is, if any widget had a sel + member set to true. +*/ int clear_widget_sel(struct widget_t *widget) { size_t x; int repaint = 0; @@ -397,14 +408,21 @@ static enum widget_type_t get_widget_type(const char *find) { return (enum widget_type_t)type; } +/*! Returns the value of the angle stored in \a list. \a list should contain + the text representing the angle as well as an optional tag "unit", which + should be either "degrees" or "radians" and specifies the unit type of the + original angle. Note that the returned value is always in radians, no + matter what the original angle's unit type was. + + \param list The resource tag to get the angle from. + \return The angle, in radians, that was represented in \a list. +*/ static double get_angle(struct resource_list_t *list) { double angle; - struct resource_list_t *anglep; const char *unit; - anglep = first_resource_tag(list, "angle"); - unit = find_resource_text(anglep, "unit"); - angle = get_expression_value(first_resource_text(anglep), 0); + unit = find_resource_text(list, "unit"); + angle = get_expression_value(first_resource_text(list), 0); if(unit) { if(!strcmp(unit, "degrees")) angle = degrees_to_radians(angle); @@ -507,6 +525,23 @@ static enum scrollbar_use_t get_scrollbar_use(const char *name) { return index; } +/*! Calls the right initialization function for a widget of type \a type. + Passes the data found in the resource structure \a list on to the + initialization functions. + + Note that it would be difficult to replace this switch with an array of + function pointers or some such structure, because the initialization + functions all take different parameters. + + \param xuni A pointer to the main xuni structure. + \param widget The widget to initialize. This should have been allocated + by allocate_widget(), and its position should have been initialized + by init_widget_pos(), prior to calling this function. However, this + widget will be a generic widget, without its type set. + \param type The type of the widget \a widget. + \param list The resource file structure from which to obtain the data to + initialize the widget \a widget with. +*/ static void init_resource_widget(struct xuni_t *xuni, struct widget_t *widget, enum widget_type_t type, struct resource_list_t *list) { @@ -533,7 +568,8 @@ static void init_resource_widget(struct xuni_t *xuni, struct widget_t *widget, init_font(widget, find_resource_text(list, "path")); break; case WIDGET_IMAGE: - init_image(widget, find_resource_text(list, "path"), get_angle(list), + init_image(widget, find_resource_text(list, "path"), + get_angle(first_resource_tag(list, "angle")), IMAGE_LOAD_FREE, IMAGE_RESCALE_LAZY); break; case WIDGET_IMAGE_TILE: diff --git a/src/loop.c b/src/loop.c index faf9cf5..eeea04a 100644 --- a/src/loop.c +++ b/src/loop.c @@ -529,6 +529,9 @@ static int process_event(SDL_Event *event, panel_type_t *mode, case SDL_ACTIVEEVENT: if(focus_changed(xuni->smode, SDL_APPACTIVE | SDL_APPINPUTFOCUS)) { if(xuni->smode->focus) { + /*int x, y; + SDL_GetMouseState(&x, &y); + printf("activated: %i,%i\n", x, y);*/ /* !!! this is only for the cursor */ set_loop_caption(*mode, xuni); repaint = 1; diff --git a/src/memory.c b/src/memory.c index e9e0497..7a9b408 100644 --- a/src/memory.c +++ b/src/memory.c @@ -12,6 +12,7 @@ #include #include "memory.h" #include "error.h" +#include "utility.h" /* A minimalistic implementation which never frees any memory, save when realloc()'ing a block to a smaller size. @@ -55,7 +56,8 @@ void *xuni_memory_resize_func(void *data, size_t size, const char *func) { return realloc(data, size); } -void xuni_memory_add_block_func(void *data, const char *func) { +void xuni_memory_add_block_func(void *data, const char *func, + enum xuni_memory_block_type_t type) { } @@ -117,6 +119,7 @@ struct xuni_memory_t { /*! List of all dynamically allocated blocks of memory. */ static struct xuni_memory_t memory = {0, 0, 0, 0}; +static int memory_find_data_compare(void *data, size_t n, void *find); static int memory_find_data(void *data, size_t *pos); static int memory_find_last_data(void *data, size_t *pos); static void memory_increase_blocks(void); @@ -128,8 +131,18 @@ static void xuni_memory_free_block(void *data, static void print_block(size_t x); -/*! Finds the position in which \a data is located in in memory structure, or, - if it is not present, the "closest" place. The closest place is the +static int memory_find_data_compare(void *data, size_t n, void *find) { + void *a = find; + void *b = ((struct xuni_memory_p_t *)data)[n].data; + + if(a < b) return -1; + else if(a > b) return 1; + + return 0; +} + +/*! Finds the position in which \a data is located in the memory structure, + or, if it is not present, the "closest" place. The closest place is the position of the last element that is smaller than \a data. It is used as a parameter to memory_insert_data(). @@ -141,6 +154,10 @@ static void print_block(size_t x); set. */ static int memory_find_data(void *data, size_t *pos) { +#if 1 + return binary_insertion_sort(memory.data, memory.n, data, pos, + memory_find_data_compare); +#else size_t mid = (size_t)-1, first = 0, last = memory.n - 1; *pos = 0; @@ -170,6 +187,7 @@ static int memory_find_data(void *data, size_t *pos) { } return 0; +#endif } static int memory_find_last_data(void *data, size_t *pos) { diff --git a/src/resource/resource.c b/src/resource/resource.c index 7e49f4e..d112a21 100644 --- a/src/resource/resource.c +++ b/src/resource/resource.c @@ -99,7 +99,7 @@ int parse_resource(struct resource_data_t *resource, const char *filename) { parse_resource_filename(resource, filename); list = resource->data.tag->list; - if(list->n && list->data[list->n - 1]->type == RESOURCE_TAG) { + if(list && list->n && list->data[list->n - 1]->type == RESOURCE_TAG) { char *path = xuni_memory_duplicate_string_len(filename, filename_path_length(filename)); diff --git a/src/test/main.c b/src/test/main.c index 74b3cc7..4833bf4 100644 --- a/src/test/main.c +++ b/src/test/main.c @@ -111,7 +111,7 @@ static void load_resource(struct resource_t *settings) { init_resource(settings); if(parse_resource(settings->data, SETTINGS_FILE)) { - log_message(ERROR_TYPE_FATAL, 0, __FILE__, __LINE__, + log_message(ERROR_TYPE_RESOURCE, 0, __FILE__, __LINE__, "Failed to load resource \"%s\"", SETTINGS_FILE); } } diff --git a/src/utility.c b/src/utility.c index d08b5c7..2258185 100644 --- a/src/utility.c +++ b/src/utility.c @@ -68,3 +68,58 @@ double degrees_to_radians(double angle) { double radians_to_degrees(double angle) { return angle * 180.0 / CONSTANT_PI; } + +/*! Finds the position in which \a find is located in the array \a data, or, + if it is not present, the "closest" place. The closest place is the + position of the last element that is smaller than \a find. It is used as + the place to insert the element \a find. + + Useful for binary insertion sorts. + + \param data The array of elements to search for \a find for. + \param n The number of elements in \a data. + \param find The memory block to search for. + \param pos Set to the actual or closest position of \a data within the + memory structure. + \param compare The function to call to compare two elements in \a data. + Must return a negative number, 0, or a positive number based on the + parameters, just like \c strcmp(). + \return True if \a find is actually present in \a data, false otherwise. + Note that if \a find is not present, \a pos will still be set. +*/ +int binary_insertion_sort(void *data, size_t n, void *find, size_t *pos, + int (*compare)(void *data, size_t n, void *find)) { + + size_t mid = (size_t)-1, first = 0, last = n - 1; + int c = -1; + + *pos = 0; + + if(!n) return 0; + + while(first <= last && last != (size_t)-1) { + mid = (first + last) / 2; + + c = (*compare)(data, mid, find); + + if(c < 0) { + last = mid - 1; + } + else if(c > 0) { + first = mid + 1; + } + else { + *pos = mid; + return 1; + } + } + + if(c < 0) { + *pos = mid; + } + else { + *pos = mid + 1; + } + + return 0; +} diff --git a/src/utility.h b/src/utility.h index c80132a..d180f90 100644 --- a/src/utility.h +++ b/src/utility.h @@ -29,4 +29,7 @@ size_t string_to_index(const struct string_index_t *str, size_t n, double degrees_to_radians(double angle); double radians_to_degrees(double angle); +int binary_insertion_sort(void *data, size_t n, void *find, size_t *pos, + int (*compare)(void *data, size_t n, void *find)); + #endif diff --git a/src/widget/font.c b/src/widget/font.c index 2735f0b..e504146 100644 --- a/src/widget/font.c +++ b/src/widget/font.c @@ -159,6 +159,7 @@ static void rescale_font(struct xuni_t *xuni, struct widget_t *widget) { } double get_font_ratio(struct xuni_t *xuni) { + return 1.0; return (xuni->smode->screen->w / (double)xuni->smode->screen->h) / (4.0 / 3.0); } @@ -166,9 +167,9 @@ double get_font_ratio(struct xuni_t *xuni) { /*! Picks a reasonable font size for the current screen resolution, according to the following formula: point-size = round(min(screen-width / ratio, screen-height) / 30.0) - \param smode The current screen resolution that xuni is using. - \return The right font size for the current screen resolution, as given by - \a smode. + \param xuni Contains information about the current screen resolution that + xuni is using. + \return The right font size for the current screen resolution. */ static int pick_font_point(struct xuni_t *xuni) { double ratio = get_font_ratio(xuni); @@ -265,8 +266,19 @@ SDL_Surface *render_text(struct xuni_t *xuni, struct widget_t *widget, if(!unrescaled || fabs(ratio - 1.0) < 0.001) return unrescaled; +#if 0 xratio = (ratio > 1.0) ? ratio : 1.0; - yratio = (ratio < 1.0) ? 1.0 / ratio : 1.0; + yratio = (ratio < 1.0) ? /*1.0 /*/ ratio : 1.0; +#else + if(ratio > 1.0) { + xratio = ratio; + yratio = 1.0; + } + else { + xratio = ratio; + yratio = 1.0 / ratio; + } +#endif #if 0 rescaled = zoomSurface(unrescaled, diff --git a/src/widget/widgets.c b/src/widget/widgets.c index d59c8c0..fd6f915 100644 --- a/src/widget/widgets.c +++ b/src/widget/widgets.c @@ -20,11 +20,11 @@ static void reposition_widget_pack(struct xuni_t *xuni, struct widget_t *widget); static void reposition_widget_nonrec(struct xuni_t *xuni, struct widget_t *widget); -static void reposition_widget(struct xuni_t *xuni, struct widget_t *widget); -static void rescale_widget(struct xuni_t *xuni, struct widget_t *widget); -static void paint_widget(struct xuni_t *xuni, struct widget_t *widget); static void free_widget(struct xuni_t *xuni, struct widget_t *widget); static void update_text_widget(struct xuni_t *xuni, struct widget_t *widget); +static void paint_widget(struct xuni_t *xuni, struct widget_t *widget); +static void reposition_widget(struct xuni_t *xuni, struct widget_t *widget); +static void rescale_widget(struct xuni_t *xuni, struct widget_t *widget); void delete_widget(struct xuni_t *xuni, struct panel_t *panel, size_t n) { free_widget(xuni, panel->widget[n]); @@ -319,6 +319,14 @@ struct widget_t *widget_nameid_access(struct widget_t *widget, size_t n) { return 0; } +/*! Starting at \a widget, follows a series of nameids. This is a private + implementation, used by widget_nameid_follow(). It takes a \c va_list + parameter instead of "...". + + \param widget The widget to start searching from. + \param arg The series of nameids to follow, starting at \a widget. + \return The widget that was eventually found, if any, or NULL otherwise. +*/ static struct widget_t *widget_nameid_follow_va(struct widget_t *widget, va_list arg) { @@ -477,6 +485,18 @@ void widget_event(struct xuni_t *xuni, struct widget_t *widget, sizeof(function) / sizeof(*function)); } +/*! Sends a widget event to all subwidgets of \a widget, but not to \a widget + itself. + + Useful in generic widget event handlers to pass on an event to subwidgets. + + \param xuni A pointer to the main xuni structure. Passed on to the widget + event handling functions. + \param widget The widget for which to send a widget event to all the + subwidgets of. + \param event The widget event type to send to the composing widgets of + \a widget. +*/ void widget_compose_event(struct xuni_t *xuni, struct widget_t *widget, enum widget_event_t event) { @@ -545,7 +565,7 @@ static void set_pos_pack_top(struct xuni_t *xuni, struct widget_t *widget) { } } -int get_real_pos(double scale, double basereal) { +int get_real_pos(double scale, int basereal) { return (int)((scale / 100.0) * basereal); } @@ -710,6 +730,11 @@ void init_wtype(struct xuni_t *xuni, struct wtype_array_t *wtype) { register_widget_type(xuni, "theme", WIDGET_THEME, theme_widget_event); } +/*! Frees the memory allocated for a wtype_array_t structure. Used by + free_xuni() to free the structure of that type that is a memory of struct + xuni_t. + \param wtype The structure to free the memory for. +*/ void free_wtype(struct wtype_array_t *wtype) { xuni_memory_free(wtype->type); } @@ -723,7 +748,7 @@ void register_widget_type(struct xuni_t *xuni, const char *name, size_t type, (xuni->wtype->types + 1) * sizeof(*xuni->wtype->type)); wtype = &xuni->wtype->type[xuni->wtype->types ++]; wtype->name = name; - wtype->type = type; + /*wtype->type = type;*/ wtype->handler = handler; } @@ -759,6 +784,25 @@ void call_widget_event_func(struct xuni_t *xuni, struct widget_t *widget, } } +/*! Makes sure that the widget \a widget is of type \a type. If it isn't, + raises an error message and returns nonzero. + + Used where a specific widget type is expected, such as for widget event + handler functions. + + \param xuni A pointer to the main xuni structure. The wtype member of this + structure is used to determine the names of widgets, if the widget + \a widget did not match the expected type. + \param widget The widget to examine. Should be of type \a type. + \param type The type that the widget \a widget ought to be. + \param file The file in which the calling function is located. Should be + \c __FILE__. (Used to report widget type mismatches.) + \param line The line number that this function was called from. Should be + \c __LINE__. (Used when the widget \a widget did not match the + expected type.) + \return Zero if the widget \a widget is of the expected type \a type, + nonzero otherwise. +*/ int assert_widget_type(struct xuni_t *xuni, struct widget_t *widget, size_t type, const char *file, int line) { diff --git a/src/widget/widgets.h b/src/widget/widgets.h index a22f359..134c051 100644 --- a/src/widget/widgets.h +++ b/src/widget/widgets.h @@ -7,8 +7,7 @@ /*! The type of a widget. - The order of these enumerated values affects the following arrays: - - \c get_widget_type_name::wtype[] + The order of these enumerated values should not matter. */ enum widget_type_t { WIDGET_NONE = -1, @@ -121,6 +120,9 @@ enum widget_event_t { WIDGET_EVENT_PAINT, WIDGET_EVENT_REPOSITION, WIDGET_EVENT_RESCALE, + /*WIDGET_EVENT_ACTIVATE, + WIDGET_EVENT_REVERT, + WIDGET_EVENT_DEACTIVATE,*/ WIDGET_EVENTS }; @@ -132,7 +134,7 @@ typedef void (*widget_event_func_t)(struct xuni_t *xuni, struct wtype_t { const char *name; - size_t type; + /*size_t type;*/ widget_event_handler_t handler; }; @@ -251,7 +253,7 @@ void widget_event(struct xuni_t *xuni, struct widget_t *widget, enum widget_event_t event); void widget_compose_event(struct xuni_t *xuni, struct widget_t *widget, enum widget_event_t event); -int get_real_pos(double scale, double basereal); +int get_real_pos(double scale, int basereal); void init_wtype(struct xuni_t *xuni, struct wtype_array_t *wtype); void free_wtype(struct wtype_array_t *wtype); diff --git a/src/xuni.c b/src/xuni.c index cfb3101..1d53682 100644 --- a/src/xuni.c +++ b/src/xuni.c @@ -51,6 +51,7 @@ #include "SDL.h" +#include "error.h" #include "graphics.h" #include "gui.h" #include "loop.h" @@ -59,39 +60,7 @@ #include "version.h" #include "xuni.h" -#if 0 -void print_sizes(void) { - printf("print_sizes(): size of various data types:\n"); - printf(" struct widget_t: %lu\n", - (unsigned long)sizeof(struct widget_t)); - printf(" struct pos_t: %lu\n", - (unsigned long)sizeof(struct pos_t)); - printf(" struct clip_pos_t: %lu\n", - (unsigned long)sizeof(struct clip_pos_t)); - printf(" composite widget_t: %lu\n", - (unsigned long)(sizeof(struct widget_t) + sizeof(struct pos_t) - + sizeof(struct clip_pos_t))); - - printf("\nIndividual widgets:\n"); - - printf(" struct image_t: %lu\n", - (unsigned long)sizeof(struct image_t)); - printf(" struct label_t: %lu\n", - (unsigned long)sizeof(struct label_t)); - printf(" struct box_t: %lu\n", - (unsigned long)sizeof(struct box_t)); - printf(" struct button_t: %lu\n", - (unsigned long)sizeof(struct button_t)); - printf(" struct checkbox_t: %lu\n", - (unsigned long)sizeof(struct checkbox_t)); - printf(" struct textbox_t: %lu\n", - (unsigned long)sizeof(struct textbox_t)); - printf(" struct listbox_t: %lu\n", - (unsigned long)sizeof(struct listbox_t)); - printf(" struct panel_t: %lu\n", - (unsigned long)sizeof(struct panel_t)); -} -#endif +static void validate_xuni_structure(struct xuni_t *xuni); /*! Dynamically allocates enough memory for a xuni_t structure. The memory is uninitialized. init_xuni() must eventually be called on the returned @@ -110,6 +79,27 @@ struct xuni_t *allocate_xuni(void) { return xuni; } +/*! Makes sure that the xuni_t structure \a xuni can be executed, i.e. has a + root widget. + + Also checks to see if any themes were loaded. If not, this is not a fatal + error, but still warrants an informative message, because xuni will not + look very good once it is running. + + \param xuni The xuni structure to check for a root widget etc. +*/ +static void validate_xuni_structure(struct xuni_t *xuni) { + if(!xuni->gui->widget) { + log_message(ERROR_TYPE_FATAL, 0, __FILE__, __LINE__, + "No root widget"); + exit(1); + } + else if(!xuni->theme->current) { + log_message(ERROR_TYPE_RESOURCE, 0, __FILE__, __LINE__, + "No themes loaded"); + } +} + /*! Initializes a xuni_t structure, after a resource_t structure has been created, perhaps by reading data from an XML file. This should be the first function called on a newly allocated xuni_t structure. @@ -130,6 +120,8 @@ void init_xuni(struct xuni_t *xuni, struct resource_t *settings, init_theme_structure(xuni->theme); load_resource_widgets(xuni, &xuni->gui->widget, settings->data); + + validate_xuni_structure(xuni); } /*! Frees the memory allocated for a xuni_t structure (\a xuni). This includes -- 2.11.4.GIT