diff options
Diffstat (limited to 'gtk/resources.c')
-rw-r--r-- | gtk/resources.c | 286 |
1 files changed, 285 insertions, 1 deletions
diff --git a/gtk/resources.c b/gtk/resources.c index e6ad951b8..d4e8b2056 100644 --- a/gtk/resources.c +++ b/gtk/resources.c @@ -20,11 +20,20 @@ * \file * Implementation of gtk builtin resource handling. * - * \todo resource handling in gtk3 has switched to using GResource + * This presents a unified interface to the rest of the codebase to + * obtain resources. Note this is not anything to do with the resource + * scheme handling beyond possibly providing the underlying data. + * */ +#include <stdlib.h> +#include <string.h> #include <gtk/gtk.h> +#include "utils/log.h" +#include "utils/filepath.h" + +#include "gtk/compat.h" #include "gtk/resources.h" #ifdef __GNUC__ @@ -33,6 +42,41 @@ extern const guint8 menu_cursor_pixdata[] __attribute__ ((__aligned__ (4))); extern const guint8 menu_cursor_pixdata[]; #endif +enum nsgtk_resource_type_e { + NSGTK_RESOURCE_FILE, + NSGTK_RESOURCE_BUILTIN, +}; + +struct nsgtk_resource_s { + const char *name; + unsigned int len; + enum nsgtk_resource_type_e type; + char *path; +}; + +static struct nsgtk_resource_s ui_resource[] = { + { "netsurf", 7, NSGTK_RESOURCE_FILE, NULL }, + { "tabcontents", 10, NSGTK_RESOURCE_FILE, NULL }, + { "password", 8, NSGTK_RESOURCE_FILE, NULL }, + { "login", 5, NSGTK_RESOURCE_FILE, NULL }, + { "ssl", 3, NSGTK_RESOURCE_FILE, NULL }, + { "toolbar", 7, NSGTK_RESOURCE_FILE, NULL }, + { "downloads", 9, NSGTK_RESOURCE_FILE, NULL }, + { "history", 7, NSGTK_RESOURCE_FILE, NULL }, + { "options", 7, NSGTK_RESOURCE_FILE, NULL }, + { "hotlist", 7, NSGTK_RESOURCE_FILE, NULL }, + { "cookies", 7, NSGTK_RESOURCE_FILE, NULL }, + { "viewdata", 8, NSGTK_RESOURCE_FILE, NULL }, + { "warning", 7, NSGTK_RESOURCE_FILE, NULL }, + { NULL, 0, NSGTK_RESOURCE_FILE, NULL }, +}; + +static struct nsgtk_resource_s gen_resource[] = { + { "favicon.png", 11, NSGTK_RESOURCE_FILE, NULL }, + { NULL, 0, NSGTK_RESOURCE_FILE, NULL }, +}; + +/* exported interface documented in gtk/resources.h */ GdkCursor *nsgtk_create_menu_cursor(void) { GdkCursor *cursor = NULL; @@ -44,3 +88,243 @@ GdkCursor *nsgtk_create_menu_cursor(void) return cursor; } + + +/* + * locate a resource + * + * The way GTK accesses resource files has changed greatly between + * releases. This initilises the interface that hides all the + * implementation details from the rest of the code. + * + * If the GResource is not enabled or the item cannot be found in the + * compiled in resources the files will be loaded directly from disc + * instead. + * + * \param respath A string vector containing the valid resource search paths + * \param ui_res A resource entry to initialise + */ +static nserror +init_resource(char **respath, struct nsgtk_resource_s *resource) +{ + int resnamelen; + char *resname; + +#ifdef WITH_GRESOURCE + gboolean present; + + resnamelen = snprintf(NULL, 0, "/org/netsurf/%s", resource->name); + + resname = malloc(resnamelen + 1); + if (resname == NULL) { + return NSERROR_NOMEM; + } + snprintf(resname, resnamelen + 1, "/org/netsurf/%s", resource->name); + + present = g_resources_get_info(resname, + G_RESOURCE_LOOKUP_FLAGS_NONE, + NULL, NULL, NULL); + if (present == TRUE) { + /* found an entry in the resources */ + resource->path = resname; + resource->type = NSGTK_RESOURCE_BUILTIN; + LOG("Found gresource path %s", resource->path); + return NSERROR_OK; + } + LOG("gresource \"%s\" not found", resname); + free(resname); +#endif + + resname = filepath_find(respath, resource->name); + if (resname == NULL) { + LOG("Unable to find resource %s on resource path", + resource->name); + return NSERROR_NOT_FOUND; + } + + /* found an entry on the path */ + resource->path = resname; + resource->type = NSGTK_RESOURCE_FILE; + + LOG("Found file resource path %s", resource->path); + return NSERROR_OK; +} + +/* + * locate a ui resource + * + * UI resources need their resource name changing to account for gtk versions + * + * \param respath A string vector containing the valid resource search paths + * \param ui_res A resource entry to initialise + */ +static nserror init_ui_resource(char **respath, struct nsgtk_resource_s *ui_res) +{ +#if GTK_CHECK_VERSION(3,0,0) + int gtkv = 3; +#else + int gtkv = 2; +#endif + int resnamelen; + char *resname; + struct nsgtk_resource_s resource; + nserror res; + + resnamelen = ui_res->len + 10; /* allow for the expanded ui name */ + + resname = malloc(resnamelen); + if (resname == NULL) { + return NSERROR_NOMEM; + } + snprintf(resname, resnamelen, "%s.gtk%d.ui", ui_res->name, gtkv); + resource.name = resname; + resource.len = ui_res->len; + resource.path = NULL; + + res = init_resource(respath, &resource); + + ui_res->path = resource.path; + ui_res->type = resource.type; + + free(resname); + + return res; +} + +#define SHOW_GRESOURCE + +/** + * Initialise UI resource table + * + */ +nserror nsgtk_init_resources(char **respath) +{ + struct nsgtk_resource_s *resource; + nserror res; + +#ifdef SHOW_GRESOURCE + const char *nspath = "/org/netsurf"; + char **reslist; + char **cur; + GError* gerror = NULL; + reslist = g_resources_enumerate_children(nspath,G_RESOURCE_LOOKUP_FLAGS_NONE, &gerror); + if (gerror) { + LOG("gerror %s", gerror->message); + g_error_free(gerror); + + } else { + cur = reslist; + while (cur != NULL && *cur != NULL) { + LOG("gres %s", *cur); + cur++; + } + g_strfreev(reslist); + } +#endif + + /* walk the ui resource table and initialise all its members */ + resource = &ui_resource[0]; + while (resource->name != NULL) { + res = init_ui_resource(respath, resource); + if (res != NSERROR_OK) { + return res; + } + resource++; + } + + /* walk the general resource table and initialise all its members */ + resource = &gen_resource[0]; + while (resource->name != NULL) { + res = init_resource(respath, resource); + if (res != NSERROR_OK) { + return res; + } + resource++; + } + + + return NSERROR_OK; +} + +static struct nsgtk_resource_s * +find_resource_from_name(const char *resname, struct nsgtk_resource_s *resource) +{ + /* find resource from name */ + while ((resource->name != NULL) && + ((resname[0] != resource->name[0]) || + (strncmp(resource->name, resname, resource->len) != 0))) { + resource++; + } + return resource; +} + +/* exported interface documented in gtk/resources.h */ +nserror +nsgdk_pixbuf_new_from_resname(const char *resname, GdkPixbuf **pixbuf_out) +{ + struct nsgtk_resource_s *resource; + GdkPixbuf *new_pixbuf; + GError* error = NULL; + + resource = find_resource_from_name(resname, &gen_resource[0]); + if (resource->name == NULL) { + return NSERROR_NOT_FOUND; + } + + if (resource->type == NSGTK_RESOURCE_FILE) { + new_pixbuf = gdk_pixbuf_new_from_file(resource->path, &error); + } else { + new_pixbuf = gdk_pixbuf_new_from_resource(resource->path, &error); + } + if (new_pixbuf == NULL) { + LOG("Unable to create pixbuf from file for %s with path %s \"%s\"", + resource->name, resource->path, error->message); + g_error_free(error); + return NSERROR_INIT_FAILED; + } + *pixbuf_out = new_pixbuf; + + return NSERROR_OK; +} + +/* exported interface documented in gtk/resources.h */ +nserror +nsgtk_builder_new_from_resname(const char *resname, GtkBuilder **builder_out) +{ + GtkBuilder *new_builder; + struct nsgtk_resource_s *ui_res; + GError* error = NULL; + + ui_res = find_resource_from_name(resname, &ui_resource[0]); + if (ui_res->name == NULL) { + return NSERROR_NOT_FOUND; + } + + new_builder = gtk_builder_new(); + + if (ui_res->type == NSGTK_RESOURCE_FILE) { + if (!gtk_builder_add_from_file(new_builder, + ui_res->path, + &error)) { + LOG("Unable to add UI builder from file for %s with path %s \"%s\"", + ui_res->name, ui_res->path, error->message); + g_error_free(error); + g_object_unref(G_OBJECT(new_builder)); + return NSERROR_INIT_FAILED; + } + } else { + if (!nsgtk_builder_add_from_resource(new_builder, + ui_res->path, + &error)) { + LOG("Unable to add UI builder from resource for %s with path %s \"%s\"", + ui_res->name, ui_res->path, error->message); + g_error_free(error); + g_object_unref(G_OBJECT(new_builder)); + return NSERROR_INIT_FAILED; + } + } + + *builder_out = new_builder; + + return NSERROR_OK; +} |