summaryrefslogtreecommitdiff
path: root/riscos/theme.c
diff options
context:
space:
mode:
Diffstat (limited to 'riscos/theme.c')
-rw-r--r--riscos/theme.c1451
1 files changed, 1123 insertions, 328 deletions
diff --git a/riscos/theme.c b/riscos/theme.c
index 941bdbbbc..517bbe114 100644
--- a/riscos/theme.c
+++ b/riscos/theme.c
@@ -1,307 +1,823 @@
/*
* This file is part of NetSurf, http://netsurf.sourceforge.net/
* Licensed under the GNU General Public License,
- * http://www.opensource.org/licenses/gpl-license
- * Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
- * Copyright 2003 James Bursa <bursa@users.sourceforge.net>
+ * http://www.opensource.org/licenses/gpl-license
* Copyright 2004 Richard Wilson <not_ginger_matt@users.sourceforge.net>
- * Copyright 2004 Andrew Timmins <atimmins@blueyonder.co.uk>
*/
/** \file
- * Toolbar themes (implementation).
+ * Window themes and toolbars (implementation).
*/
#include <alloca.h>
#include <assert.h>
#include <stdio.h>
+#include <stdbool.h>
#include <string.h>
#include "oslib/os.h"
#include "oslib/osgbpb.h"
#include "oslib/osfile.h"
#include "oslib/osspriteop.h"
#include "oslib/wimp.h"
+#include "oslib/wimpextend.h"
#include "oslib/wimpspriteop.h"
#include "netsurf/riscos/gui.h"
#include "netsurf/riscos/theme.h"
-#include "netsurf/riscos/toolbar.h"
#include "netsurf/riscos/wimp.h"
-#include "netsurf/utils/utils.h"
#include "netsurf/utils/log.h"
+#include "netsurf/utils/utils.h"
+
+
+#define THEME_URL_MEMORY 256
+#define THEME_THROBBER_MEMORY 12
+#define THEME_STATUS_MEMORY 256
+
+
+static struct theme_descriptor *theme_current = NULL;
+static struct theme_descriptor *theme_descriptors = NULL;
+
+static void ro_gui_theme_free(struct theme_descriptor *descriptor, bool list);
+static void ro_gui_theme_add_toolbar_icon(struct toolbar *toolbar, const char *name, int icon_number);
+static void ro_gui_theme_update_toolbar_icon(struct toolbar *toolbar, struct toolbar_icon *icon);
+static void ro_gui_theme_destroy_toolbar_icon(struct toolbar_icon *icon);
+
+
+/* A basic window for the toolbar and status
+*/
+static wimp_window theme_toolbar_window = {
+ {0, 0, 16384, 16384},
+ 0,
+ 0,
+ wimp_TOP,
+ wimp_WINDOW_NEW_FORMAT | wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW |
+ wimp_WINDOW_FURNITURE_WINDOW,
+ wimp_COLOUR_BLACK,
+ wimp_COLOUR_LIGHT_GREY,
+ wimp_COLOUR_LIGHT_GREY,
+ wimp_COLOUR_VERY_LIGHT_GREY,
+ wimp_COLOUR_DARK_GREY,
+ wimp_COLOUR_MID_LIGHT_GREY,
+ wimp_COLOUR_CREAM,
+ wimp_WINDOW_NEVER3D | 0x16u /* RISC OS 5.03+ - greyed icons detected for interactive help */,
+ {0, 0, 16384, 16384},
+ 0,
+ 0,
+ wimpspriteop_AREA,
+ 12,
+ 1,
+ {""},
+ 0,
+ { }
+};
+
-/* Current theme
+/* Shared icon validation
*/
-static struct theme_entry *ro_theme_current = NULL;
+static char theme_url_validation[] = "Pptr_write\0";
+static char theme_resize_validation[] = "R1;Pptr_lr,8,6\0";
+static char theme_null_text_string[] = "\0";
/**
- * Apply the current theme
- *
- * /param theme the theme to apply
+ * Initialise the theme handler
*/
-void ro_theme_apply(struct theme_entry *theme) {
-#ifdef WITH_KIOSK_THEMES
- char *kioskfilename = alloca(strlen(THEMES_DIR) + strlen(theme->name) + 16);
-#endif
-
- /* Release any previous theme
+void ro_gui_theme_initialise(void) {
+ /* Get an initial theme list
*/
- if (ro_theme_current) ro_theme_free(ro_theme_current);
+ theme_descriptors = ro_gui_theme_get_available();
+}
- /* Set the current theme
+
+/**
+ * Finalise the theme handler
+ */
+void ro_gui_theme_finalise(void) {
+ /* Free all closed descriptors
*/
- ro_theme_current = theme;
+ ro_gui_theme_close(theme_current, false);
+ ro_gui_theme_free(theme_descriptors, true);
+}
- /* Load the window furniture if using Kiosk Themes
- *
- * Yes I know this is one serious hack!
- * I'll do something a little more "realistic" when I've
- * finished various other bits... Right now it works.
- */
-#ifdef WITH_KIOSK_THEMES
- sprintf(kioskfilename, "%s.%s.!SetTheme", THEMES_DIR, theme->name);
- xos_cli(kioskfilename);
-#endif
- /* todo: update all current windows */
+/**
+ * Finds a theme from the cached values.
+ *
+ * The returned theme is only guaranteed to be valid until the next call
+ * to ro_gui_theme_get_available() unless it has been opened using
+ * ro_gui_theme_open().
+ *
+ * \param filename the filename of the theme_descriptor to return
+ * \return the requested theme_descriptor, or NULL if not found
+ */
+struct theme_descriptor *ro_gui_theme_find(const char *filename) {
+ struct theme_descriptor *descriptor;
+
+ /* Check for bad filename
+ */
+ if (!filename) return NULL;
+
+ /* Work through until we find our required filename
+ */
+ descriptor = theme_descriptors;
+ while (descriptor) {
+ if (!strcmp(filename, descriptor->filename)) return descriptor;
+ descriptor = descriptor->next;
+ }
+ return NULL;
}
/**
- * Load a theme from a directory.
+ * Reads and caches the currently available themes.
*
- * Ideally, the directory should contain a Sprite file and a Text options file.
- * If the path is invalid, or neither of these are present then a default theme
- * is returned with no icons present.
+ * \return the requested theme_descriptor, or NULL if not found
*/
-
-struct theme_entry *ro_theme_load(char *pathname) {
- osbool mask;
- os_mode mode;
- os_coord dimensions;
- int size, i, n;
- char *filename = alloca(strlen(pathname) + 16);
- char *name;
+struct theme_descriptor *ro_gui_theme_get_available(void) {
+ struct theme_descriptor *current;
+ struct theme_descriptor *test;
+ char pathname[256];
+ int context = 0;
+ int read_count;
+ osgbpb_INFO(100) info;
fileswitch_object_type obj_type;
- struct theme_entry *theme;
os_error *error;
- /* Get some memory for the theme
- */
- theme = (struct theme_entry *)calloc(1, sizeof(struct theme_entry));
- if (!theme) {
- LOG(("Failed to claim memory to hold theme."));
- warn_user("NoMemory", 0);
- return NULL;
- }
- theme->default_settings = true;
-
- /* Load the sprites
+ /* Close any descriptors we've got so far
*/
- sprintf(filename, "%s.Sprites", pathname);
- xosfile_read_no_path(filename, &obj_type, 0, 0, &size, 0);
+ ro_gui_theme_free(theme_descriptors, true);
- /* Claim memory for a sprite file if we have one
+ /* Create a new set
*/
- if (obj_type & fileswitch_IS_FILE) theme->sprite_area = malloc(size + 16);
+ while (context != -1) {
+ /* Get the next entry
+ */
+ error = xosgbpb_dir_entries_info(THEMES_DIR,
+ (osgbpb_info_list *) &info, 1, context,
+ sizeof(info), 0, &read_count, &context);
+ if (error) {
+ LOG(("xosgbpb_dir_entries_info: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("MiscError", error->errmess);
+ break;
+ }
+
+ /* Check if we've read anything
+ */
+ if (read_count == 0)
+ continue;
+
+ /* Only process files
+ */
+ if ((info.obj_type == fileswitch_IS_DIR) && (!ro_gui_theme_find(info.name))) {
+ /* Get our full filename
+ */
+ snprintf(pathname, sizeof pathname, "%s.%s.Sprites",
+ THEMES_DIR, info.name);
+ pathname[sizeof pathname - 1] = 0;
+
+ /* Check for sprites file
+ */
+ error = xosfile_read_stamped_no_path(pathname,
+ &obj_type, (bits *)0, (bits *)0, (int *)0,
+ (fileswitch_attr *)0, (bits *)0);
+ if (error) {
+ LOG(("xosfile_read_stamped_no_path: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("MiscError", error->errmess);
+ } else if (obj_type == fileswitch_IS_FILE) {
- /* Load the sprite file if we have any memory
+ /* Create a new theme descriptor
+ */
+ current = (struct theme_descriptor *)calloc(1,
+ sizeof(struct theme_descriptor));
+ if (!current) {
+ LOG(("calloc failed"));
+ warn_user("NoMemory", 0);
+ return theme_descriptors;
+ }
+ current->filename = malloc(strlen(info.name) + 1);
+ if (!current->filename) {
+ LOG(("malloc failed"));
+ warn_user("NoMemory", 0);
+ free(current);
+ return theme_descriptors;
+ }
+ strcpy(current->filename, info.name);
+
+ /* Link in our new descriptor alphabetically
+ */
+ if (theme_descriptors) {
+ current->next = theme_descriptors;
+ theme_descriptors->previous = current;
+ }
+ theme_descriptors = current;
+ }
+ }
+ }
+
+ /* Sort alphabetically in a very rubbish way
*/
- if (theme->sprite_area) {
+ if (theme_descriptors->next) {
+ current = theme_descriptors;
+ while ((test = current->next)) {
+ if (strcmp(current->filename, test->filename) > 0) {
+ current->next->previous = current->previous;
+ if (current->previous)
+ current->previous->next = current->next;
+ current->next = test->next;
+ test->next = current;
+ current->previous = test;
+ if (current->next)
+ current->next->previous = current;
- /* Initialise then load
- */
- theme->sprite_area->size = size + 16;
- theme->sprite_area->sprite_count = 0;
- theme->sprite_area->first = 16;
- theme->sprite_area->used = 16;
- xosspriteop_clear_sprites(osspriteop_USER_AREA, theme->sprite_area);
- error = xosspriteop_load_sprite_file(osspriteop_USER_AREA, theme->sprite_area,
- filename);
- if (error) {
- free(theme->sprite_area);
- theme->sprite_area = NULL;
+ current = test->previous;
+ if (!current) current = test;
+ } else {
+ current = current->next;
+ }
}
+ while (theme_descriptors->previous)
+ theme_descriptors = theme_descriptors->previous;
}
+ return theme_descriptors;
+}
- /* Get the throbber details
+
+/**
+ * Opens a theme ready for use.
+ *
+ * \param descriptor the theme_descriptor to open
+ * \param list whether to open all themes in the list
+ * \return whether the operation was successful
+ */
+bool ro_gui_theme_open(struct theme_descriptor *descriptor, bool list) {
+ os_coord dimensions;
+ os_mode mode;
+ char pathname[256];
+ bool result = true;
+ int i, n;
+
+ /* If we are freeing the whole of the list then we need to
+ start at the first descriptor.
*/
- if (theme->sprite_area) {
- /* We aren't default
- */
- theme->default_settings = false;
+ if (list) {
+ while (descriptor->previous) descriptor = descriptor->previous;
+ }
- /* Find the highest sprite called 'throbber%i', and get the maximum
- dimensions for all 'thobber%i' icons. We use the filename buffer
- as the temporary spritename buffer as it is guaranteed to be at
- least 12 bytes (max sprite name size).
+ /* Open the themes
+ */
+ while (descriptor) {
+ /* If we are already loaded, increase the usage count
*/
- for (i = 1; i <= theme->sprite_area->sprite_count; i++) {
- osspriteop_return_name(osspriteop_USER_AREA,
- theme->sprite_area, filename, 12, i);
- if (strncmp(filename, "throbber", 8) == 0) {
- /* Get the max sprite width/height
- */
- xosspriteop_read_sprite_info(osspriteop_USER_AREA,
- theme->sprite_area, (osspriteop_id)filename,
- &dimensions.x, &dimensions.y, &mask, &mode);
- ro_convert_pixels_to_os_units(&dimensions, mode);
- if (dimensions.x > theme->throbber_width)
- theme->throbber_width = dimensions.x;
- if (dimensions.y > theme->throbber_height)
- theme->throbber_height = dimensions.y;
-
- /* Get the throbber number
- */
- n = atoi(filename + 8);
- if (theme->throbber_frames < n) theme->throbber_frames = n;
+ if (descriptor->theme) {
+ descriptor->theme->users = descriptor->theme->users + 1;
+ } else {
+ /* Create a new theme
+ */
+ descriptor->theme = (struct theme *)calloc(1, sizeof(struct theme));
+ if (!descriptor->theme) {
+ LOG(("calloc failed"));
+ warn_user("NoMemory", 0);
+ return false;
+ }
+ descriptor->theme->users = 1;
+
+ /* Get our full filename
+ */
+ snprintf(pathname, sizeof pathname, "%s.%s.Sprites",
+ THEMES_DIR, descriptor->filename);
+ pathname[sizeof pathname - 1] = 0;
+
+ /* Load the sprites
+ */
+ descriptor->theme->sprite_area = ro_gui_load_sprite_file(pathname);
+ if (!descriptor->theme->sprite_area) {
+ result = false;
+ free(descriptor->theme);
+ descriptor->theme = NULL;
+ continue;
}
+
+ /* Find the highest sprite called 'throbber%i', and get the maximum
+ dimensions for all 'thobber%i' icons.
+ */
+ for (i = 1; i <= descriptor->theme->sprite_area->sprite_count; i++) {
+ osspriteop_return_name(osspriteop_USER_AREA,
+ descriptor->theme->sprite_area, pathname, 12, i);
+ if (strncmp(pathname, "throbber", 8) == 0) {
+ /* Get the max sprite width/height
+ */
+ xosspriteop_read_sprite_info(osspriteop_USER_AREA,
+ descriptor->theme->sprite_area,
+ (osspriteop_id)pathname,
+ &dimensions.x, &dimensions.y,
+ (osbool *)0, &mode);
+ ro_convert_pixels_to_os_units(&dimensions, mode);
+ if (dimensions.x > descriptor->theme->throbber_width)
+ descriptor->theme->throbber_width = dimensions.x;
+ if (dimensions.y > descriptor->theme->throbber_height)
+ descriptor->theme->throbber_height = dimensions.y;
+
+ /* Get the throbber number
+ */
+ n = atoi(pathname + 8);
+ if (descriptor->theme->throbber_frames < n)
+ descriptor->theme->throbber_frames = n;
+ }
+ }
+
+ /* Load the options
+ */
+ descriptor->theme->throbber_right = true;
+ descriptor->theme->browser_background = wimp_COLOUR_VERY_LIGHT_GREY;
+ descriptor->theme->hotlist_background = wimp_COLOUR_VERY_LIGHT_GREY;
+ descriptor->theme->status_background = wimp_COLOUR_VERY_LIGHT_GREY;
+ descriptor->theme->status_foreground = wimp_COLOUR_BLACK;
+// FINISH ME - NEEDS FINAL FILE FORMAT DECIDING
}
+
+ /* Loop or return depending on whether the entire list
+ is to be processed.
+ */
+ if (list) {
+ descriptor = descriptor->next;
+ } else {
+ return result;
+ }
}
+ return result;
+}
+
+
+/**
+ * Applies the theme to all current windows and subsequent ones.
+ *
+ * \param descriptor the theme_descriptor to open
+ * \return whether the operation was successful
+ */
+bool ro_gui_theme_apply(struct theme_descriptor *descriptor) {
+ struct theme_descriptor *theme_previous;
- /* Copy name.
+ /* Check if the theme is already applied
*/
- name = strrchr(pathname, '.');
- if (name) {
- theme->name = strdup(name+1);
- if (!theme->name) {
- warn_user("NoMemory", 0);
- ro_theme_free(theme);
- return NULL;
- }
- }
- else {
- LOG(("failed to extract theme name from pathname"));
- warn_user("MiscError", "Unable to acquire theme name");
- ro_theme_free(theme);
- return NULL;
+ if (descriptor == theme_current) return true;
+
+ /* Re-open the new-theme and release the current theme
+ */
+ if (!ro_gui_theme_open(descriptor, false)) {
+ /* The error has already been reported
+ */
+ return false;
}
-
- /* Load the options
+ theme_previous = theme_current;
+ theme_current = descriptor;
+
+ /* Apply the theme to all the current windows
*/
- theme->browser_background = wimp_COLOUR_VERY_LIGHT_GREY;
- theme->hotlist_background = wimp_COLOUR_VERY_LIGHT_GREY;
- theme->status_background = wimp_COLOUR_VERY_LIGHT_GREY;
- theme->status_foreground = wimp_COLOUR_BLACK;
- /* todo: impement option loading */
-
- /* Return our new theme
+ ro_gui_window_update_theme();
+
+ /* Release the previous theme
*/
- return theme;
+ ro_gui_theme_close(theme_previous, false);
+ return true;
}
/**
- * Create a toolbar from the current theme for a browser window.
+ * Closes a theme after use.
*
- * The buffers url_buffer and status_buffer must be at least 256 bytes each,
- * throbber_buffer at least 12 bytes;
+ * \param descriptor the theme_descriptor to close
+ * \param list whether to open all themes in the list
+ * \return whether the operation was successful
*/
-void ro_theme_create_browser_toolbar(struct gui_window *g) {
- struct toolbar *toolbar;
+void ro_gui_theme_close(struct theme_descriptor *descriptor, bool list) {
- /* Destroy any previous toolbar (paranoia)
+ /* We might not have created any descriptors yet to close.
*/
- if (g->toolbar) {
- ro_toolbar_destroy(g->toolbar);
- g->toolbar = NULL;
+ if (!descriptor) return;
+
+ /* If we are freeing the whole of the list then we need to
+ start at the first descriptor.
+ */
+ if (list) {
+ while (descriptor->previous) descriptor = descriptor->previous;
+ }
+
+ /* Close the themes
+ */
+ while (descriptor) {
+ /* Lower the theme usage count
+ */
+ if (descriptor->theme) {
+ descriptor->theme->users = descriptor->theme->users - 1;
+ if (descriptor->theme->users <= 0) {
+ free(descriptor->theme->sprite_area);
+ free(descriptor->theme->author);
+ free(descriptor->theme->details);
+ free(descriptor->theme);
+ descriptor->theme = NULL;
+ }
+ }
+
+ /* Loop or return depending on whether the entire list
+ is to be processed.
+ */
+ if (list) {
+ descriptor = descriptor->next;
+ } else {
+ return;
+ }
}
- /* Create a toolbar
- */
- toolbar = ro_toolbar_create(ro_theme_current, g->url, g->status,
- g->throb_buf, TOOLBAR_BROWSER);
- if (toolbar == NULL) return;
+}
+
- /* Set up the default status width
- */
- toolbar->status_width = 640;
+/**
+ * Frees any unused theme descriptors.
+ *
+ * \param descriptor the theme_descriptor to free
+ * \param list whether to open all themes in the list
+ * \return whether the operation was successful
+ */
+void ro_gui_theme_free(struct theme_descriptor *descriptor, bool list) {
+ struct theme_descriptor *next_descriptor;
+
+ /* We might not have created any descriptors yet to close.
+ */
+ if (!descriptor) return;
+
+ /* If we are freeing the whole of the list then we need to
+ start at the first descriptor.
+ */
+ if (list) {
+ while (descriptor->previous) descriptor = descriptor->previous;
+ }
- /* Store our toolbar
- */
- g->toolbar = toolbar;
+ /* Close the themes
+ */
+ while (descriptor) {
+ /* Remember where we are going next
+ */
+ next_descriptor = descriptor->next;
+
+ /* If we have no loaded theme then we can kill the descriptor
+ */
+ if (!descriptor->theme) {
+ /* De-link the descriptor
+ */
+ if (descriptor->previous)
+ descriptor->previous->next = descriptor->next;
+ if (descriptor->next)
+ descriptor->next->previous = descriptor->previous;
+
+ /* Keep the cached list in sync
+ */
+ if (theme_descriptors == descriptor)
+ theme_descriptors = next_descriptor;
+ /* Release any memory
+ */
+ free(descriptor->filename);
+ free(descriptor);
+ }
- /* Update the toolbar
- */
- ro_theme_update_toolbar(toolbar, g->window);
+ /* Loop or return depending on whether the entire list
+ is to be processed.
+ */
+ if (list) {
+ descriptor = next_descriptor;
+ } else {
+ return;
+ }
+ }
}
/**
- * Create a toolbar from the current theme for a hotlist window.
+ * Creates a toolbar.
*
- * The buffers url_buffer and status_buffer must be at least 256 bytes each,
- * throbber_buffer at least 12 bytes;
+ * \param descriptor the theme to use, or NULL for current
+ * \param type the toolbar type
+ * \return a new toolbar, or NULL for failure
*/
-void ro_theme_create_hotlist_toolbar(void) {
- struct toolbar *toolbar;
+struct toolbar *ro_gui_theme_create_toolbar(struct theme_descriptor *descriptor, toolbar_type type) {
+ struct toolbar *toolbar;
- /* Destroy any previous toolbar (paranoia)
+ /* Create a new toolbar
*/
- if (hotlist_toolbar) {
- ro_toolbar_destroy(hotlist_toolbar);
- hotlist_toolbar = NULL;
+ toolbar = calloc(sizeof(struct toolbar), 1);
+ if (!toolbar) {
+ LOG(("No memory for malloc()"));
+ warn_user("NoMemory", 0);
+ return NULL;
}
+ toolbar->type = type;
+
+ /* Store the theme
+ */
+ if (!descriptor) descriptor = theme_current;
+ if (descriptor) toolbar->theme = descriptor->theme;
- /* Create a toolbar
- */
- toolbar = ro_toolbar_create(ro_theme_current, NULL, NULL,
- NULL, TOOLBAR_HOTLIST);
- if (toolbar == NULL) return;
-
- /* Store our toolbar
- */
- hotlist_toolbar = toolbar;
+ /* Apply the default settings
+ */
+ toolbar->display_buttons = true;
+ toolbar->toolbar_current = 16384;
+ switch (type) {
+ case THEME_BROWSER_TOOLBAR:
+ toolbar->display_url = true;
+ toolbar->display_throbber = true;
+ toolbar->display_status = true;
+ ro_gui_theme_add_toolbar_icon(toolbar, "back", ICON_TOOLBAR_BACK);
+ ro_gui_theme_add_toolbar_icon(toolbar, "forward", ICON_TOOLBAR_FORWARD);
+ ro_gui_theme_add_toolbar_icon(toolbar, "stop", ICON_TOOLBAR_STOP);
+ ro_gui_theme_add_toolbar_icon(toolbar, "reload", ICON_TOOLBAR_RELOAD);
+ ro_gui_theme_add_toolbar_icon(toolbar, "home", ICON_TOOLBAR_HOME);
+ ro_gui_theme_add_toolbar_icon(toolbar, NULL, -1);
+ ro_gui_theme_add_toolbar_icon(toolbar, "search", ICON_TOOLBAR_SEARCH);
+ ro_gui_theme_add_toolbar_icon(toolbar, "history", ICON_TOOLBAR_HISTORY);
+ ro_gui_theme_add_toolbar_icon(toolbar, "scale", ICON_TOOLBAR_SCALE);
+ ro_gui_theme_add_toolbar_icon(toolbar, NULL, -1);
+ ro_gui_theme_add_toolbar_icon(toolbar, "mark", ICON_TOOLBAR_BOOKMARK);
+ ro_gui_theme_add_toolbar_icon(toolbar, "save", ICON_TOOLBAR_SAVE);
+ ro_gui_theme_add_toolbar_icon(toolbar, "print", ICON_TOOLBAR_PRINT);
+ break;
+ case THEME_HOTLIST_TOOLBAR:
+ ro_gui_theme_add_toolbar_icon(toolbar, "create", ICON_TOOLBAR_CREATE);
+ ro_gui_theme_add_toolbar_icon(toolbar, "delete", ICON_TOOLBAR_DELETE);
+ ro_gui_theme_add_toolbar_icon(toolbar, "launch", ICON_TOOLBAR_LAUNCH);
+ ro_gui_theme_add_toolbar_icon(toolbar, NULL, -1);
+ ro_gui_theme_add_toolbar_icon(toolbar, "open", ICON_TOOLBAR_OPEN);
+ ro_gui_theme_add_toolbar_icon(toolbar, "expand", ICON_TOOLBAR_EXPAND);
+ break;
+ }
+
+ /* Claim the memory for our Wimp indirection
+ */
+ if (type == THEME_BROWSER_TOOLBAR) {
+ toolbar->url_buffer = calloc(1, THEME_URL_MEMORY + THEME_THROBBER_MEMORY +
+ THEME_STATUS_MEMORY);
+ if (!toolbar->url_buffer) {
+ LOG(("No memory for calloc()"));
+ ro_gui_theme_destroy_toolbar(toolbar);
+ return NULL;
+ }
+ toolbar->throbber_buffer = toolbar->url_buffer + THEME_URL_MEMORY;
+ toolbar->status_buffer = toolbar->throbber_buffer + THEME_THROBBER_MEMORY;
+ sprintf(toolbar->throbber_buffer, "throbber0");
+ }
- /* Update the toolbar
- */
- ro_theme_update_toolbar(toolbar, hotlist_window);
+ /* Apply the desired theme to the toolbar
+ */
+ if (!ro_gui_theme_update_toolbar(descriptor, toolbar)) {
+ ro_gui_theme_destroy_toolbar(toolbar);
+ return NULL;
+ }
+ return toolbar;
}
-
/**
- * Updates any toolbar flags (eg closes windows, hides icons etc)
+ * Updates a toolbar to use a particular theme.
+ * The toolbar may be unstable on failure and should be destroyed.
*
- * \return non-zero if the toolbar height has changed
+ * \param descriptor the theme to use, or NULL for current
+ * \param toolbar the toolbar to update
+ * \return whether the operation was successful
*/
-int ro_theme_update_toolbar(struct toolbar *toolbar, wimp_w window) {
- wimp_outline outline;
- wimp_window_state state;
- int return_value = 0;
-
- /* Set an update as pending
+bool ro_gui_theme_update_toolbar(struct theme_descriptor *descriptor, struct toolbar *toolbar) {
+ wimp_icon_create new_icon;
+ os_error *error;
+ osspriteop_area *sprite_area;
+ struct toolbar_icon *toolbar_icon;
+ if (!toolbar) return false;
+
+ /* Set the theme and window sprite area
+ */
+ if (!descriptor) descriptor = theme_current;
+ if (descriptor) {
+ toolbar->theme = descriptor->theme;
+ } else {
+ toolbar->theme = NULL;
+ }
+ if (toolbar->theme) {
+ sprite_area = toolbar->theme->sprite_area;
+ } else {
+ sprite_area = (osspriteop_area *)1;
+ }
+ theme_toolbar_window.sprite_area = sprite_area;
+
+ /* Update the icon sizes
+ */
+ toolbar_icon = toolbar->icon;
+ while (toolbar_icon) {
+ ro_gui_theme_update_toolbar_icon(toolbar, toolbar_icon);
+ toolbar_icon = toolbar_icon->next;
+ }
+
+ /* Recreate the toolbar window
*/
- toolbar->update_pending = true;
+ if (toolbar->theme) {
+ if (toolbar->type == THEME_BROWSER_TOOLBAR) {
+ theme_toolbar_window.work_bg = toolbar->theme->browser_background;
+ } else {
+ theme_toolbar_window.work_bg = toolbar->theme->hotlist_background;
+ }
+ } else {
+ theme_toolbar_window.work_bg = wimp_COLOUR_VERY_LIGHT_GREY;
+ }
+ theme_toolbar_window.flags |= wimp_WINDOW_NO_BOUNDS;
+ theme_toolbar_window.xmin = 1;
+ theme_toolbar_window.ymin = 1;
+ theme_toolbar_window.extent.x1 = 16384;
+ theme_toolbar_window.extent.y1 = 16384;
+ if (toolbar->toolbar_handle) {
+ xwimp_delete_window(toolbar->toolbar_handle);
+ toolbar->toolbar_handle = NULL;
+ }
+ error = xwimp_create_window(&theme_toolbar_window, &toolbar->toolbar_handle);
+ if (error) {
+ LOG(("xwimp_create_window: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ return false;
+ }
+
+ /* Create the basic icons
+ */
+ int max_icon = ICON_TOOLBAR_URL;
+ if (toolbar->type == THEME_HOTLIST_TOOLBAR) max_icon = ICON_TOOLBAR_HOTLIST_LAST;
+ new_icon.w = toolbar->toolbar_handle;
+ new_icon.icon.data.indirected_text.size = 1;
+ new_icon.icon.flags = wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_INDIRECTED |
+ wimp_ICON_HCENTRED | wimp_ICON_VCENTRED |
+ (wimp_BUTTON_CLICK << wimp_ICON_BUTTON_TYPE_SHIFT);
+ if (toolbar->theme) {
+ new_icon.icon.flags |= (toolbar->theme->browser_background
+ << wimp_ICON_BG_COLOUR_SHIFT);
+ } else {
+ new_icon.icon.flags |= (wimp_COLOUR_VERY_LIGHT_GREY
+ << wimp_ICON_BG_COLOUR_SHIFT);
+ }
+ for (int i = 0; i < max_icon; i++) {
+ new_icon.icon.data.indirected_text.text = theme_null_text_string;
+ toolbar_icon = toolbar->icon;
+ while (toolbar_icon) {
+ if (toolbar_icon->icon_number == i) {
+ new_icon.icon.data.indirected_text.validation =
+ toolbar_icon->validation;
+ break;
+ } else {
+ toolbar_icon = toolbar_icon->next;
+ }
+ }
+ error = xwimp_create_icon(&new_icon, 0);
+ if (error) {
+ LOG(("xwimp_create_icon: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ return false;
+ }
+ }
+
+ /* Create the URL/throbber icons
+ */
+ if (toolbar->type == THEME_BROWSER_TOOLBAR) {
+ new_icon.icon.flags = wimp_ICON_TEXT | wimp_ICON_INDIRECTED | wimp_ICON_VCENTRED |
+ wimp_ICON_BORDER | wimp_ICON_FILLED |
+ (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) |
+ (wimp_BUTTON_WRITE_CLICK_DRAG << wimp_ICON_BUTTON_TYPE_SHIFT);
+ new_icon.icon.data.indirected_text.text = toolbar->url_buffer;
+ new_icon.icon.data.indirected_text.validation = theme_url_validation;
+ new_icon.icon.data.indirected_text.size = THEME_URL_MEMORY;
+ error = xwimp_create_icon(&new_icon, 0);
+ if (error) {
+ LOG(("xwimp_create_icon: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ return false;
+ }
- /* Close the status window if we should, or resize it
- */
- if (toolbar->status_window) {
+ /* Now the throbber
+ */
+ new_icon.icon.flags = wimp_ICON_SPRITE | wimp_ICON_INDIRECTED | wimp_ICON_HCENTRED |
+ wimp_ICON_VCENTRED;
+ new_icon.icon.data.indirected_sprite.id = (osspriteop_id)toolbar->throbber_buffer;
+ new_icon.icon.data.indirected_sprite.area = sprite_area;
+ new_icon.icon.data.indirected_sprite.size = THEME_THROBBER_MEMORY;
+ error = xwimp_create_icon(&new_icon, 0);
+ if (error) {
+ LOG(("xwimp_create_icon: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ return false;
+ }
+ }
+ if (toolbar->parent_handle) {
+ ro_gui_theme_attach_toolbar(toolbar, toolbar->parent_handle);
+ }
+
+ /* Recreate the status window
+ */
+ if (toolbar->type == THEME_BROWSER_TOOLBAR) {
+ /* Delete the old window and create a new one
+ */
+ if (toolbar->status_handle) {
+ xwimp_delete_window(toolbar->status_handle);
+ toolbar->status_handle = NULL;
+ }
+ if (toolbar->theme) {
+ theme_toolbar_window.work_bg = toolbar->theme->status_background;
+ } else {
+ theme_toolbar_window.work_bg = wimp_COLOUR_VERY_LIGHT_GREY;
+ }
+ theme_toolbar_window.flags &= ~wimp_WINDOW_NO_BOUNDS;
+ theme_toolbar_window.xmin = 12;
+ theme_toolbar_window.ymin = ro_get_hscroll_height((wimp_w)0) - 4;
+ theme_toolbar_window.extent.y1 = theme_toolbar_window.ymin;
+ error = xwimp_create_window(&theme_toolbar_window, &toolbar->status_handle);
+ if (error) {
+ LOG(("xwimp_create_window: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ return false;
+ }
+
+ /* Create the status resize icon
+ */
+ new_icon.w = toolbar->status_handle;
+ new_icon.icon.flags = wimp_ICON_TEXT | wimp_ICON_INDIRECTED |
+ wimp_ICON_BORDER | wimp_ICON_FILLED |
+ (wimp_COLOUR_LIGHT_GREY << wimp_ICON_BG_COLOUR_SHIFT) |
+ (wimp_BUTTON_CLICK_DRAG << wimp_ICON_BUTTON_TYPE_SHIFT);
+ new_icon.icon.data.indirected_text.text = theme_null_text_string;
+ new_icon.icon.data.indirected_text.validation = theme_resize_validation;
+ new_icon.icon.data.indirected_text.size = 1;
+ error = xwimp_create_icon(&new_icon, 0);
+ if (error) {
+ LOG(("xwimp_create_icon: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ return false;
+ }
- /* Update the status height
- */
- ro_toolbar_resize_status(toolbar, ro_get_hscroll_height(window) - 2);
- } else {
- xwimp_close_window(toolbar->status_handle);
- }
+ /* And finally our status display icon
+ */
+ new_icon.icon.flags = wimp_ICON_TEXT | wimp_ICON_INDIRECTED | wimp_ICON_VCENTRED;
+ if (toolbar->theme) {
+ new_icon.icon.flags |=
+ (toolbar->theme->status_foreground << wimp_ICON_FG_COLOUR_SHIFT) |
+ (toolbar->theme->status_background << wimp_ICON_BG_COLOUR_SHIFT);
+ } else {
+ new_icon.icon.flags |=
+ (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) |
+ (wimp_COLOUR_VERY_LIGHT_GREY << wimp_ICON_BG_COLOUR_SHIFT);
+ }
+ new_icon.icon.data.indirected_text.text = toolbar->status_buffer;
+ new_icon.icon.data.indirected_text.validation = theme_null_text_string;
+ new_icon.icon.data.indirected_text.size = THEME_STATUS_MEMORY;
+ error = xwimp_create_icon(&new_icon, 0);
+ if (error) {
+ LOG(("xwimp_create_icon: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ return false;
+ }
- /* Update the toolbar height
+ }
+
+ /* Force a re-processing of the toolbar
*/
- return_value = ro_theme_resize_toolbar(toolbar, window);
+ toolbar->reformat_buttons = true;
+ toolbar->status_current = -1;
+ ro_gui_theme_process_toolbar(toolbar, toolbar->toolbar_current);
+ return true;
+}
- /* Open/close the toolbar
+
+/**
+ * Attaches a toolbar to a window.
+ *
+ * \param toolbar the toolbar to update
+ * \param parent the window to contain the toolbar
+ * \return whether the operation was successful
+ */
+bool ro_gui_theme_attach_toolbar(struct toolbar *toolbar, wimp_w parent) {
+ wimp_outline outline;
+ wimp_window_state state;
+ if (!toolbar) return false;
+
+ /* Attach/close the window
*/
+ toolbar->parent_handle = parent;
if (toolbar->height > 0) {
- outline.w = window;
+ outline.w = parent;
xwimp_get_window_outline(&outline);
- state.w = window;
+ state.w = parent;
xwimp_get_window_state(&state);
state.w = toolbar->toolbar_handle;
state.visible.x1 = outline.outline.x1 - 2;
state.visible.y0 = state.visible.y1 - toolbar->height + 2;
state.xscroll = 0;
state.yscroll = 0;
- state.next = wimp_TOP;
- xwimp_open_window_nested((wimp_open *)&state, window,
+ xwimp_open_window_nested((wimp_open *)&state, parent,
wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
<< wimp_CHILD_XORIGIN_SHIFT |
wimp_CHILD_LINKS_PARENT_VISIBLE_TOP_OR_RIGHT
@@ -315,172 +831,451 @@ int ro_theme_update_toolbar(struct toolbar *toolbar, wimp_w window) {
wimp_CHILD_LINKS_PARENT_VISIBLE_TOP_OR_RIGHT
<< wimp_CHILD_TS_EDGE_SHIFT);
} else {
- xwimp_close_window(toolbar->toolbar_handle);
+ xwimp_close_window(toolbar->toolbar_handle);
}
-
- /* Return
- */
- return return_value;
+ return true;
}
/**
- * Resize the status and toolbar windows.
+ * Updates the toolbars status bar settings to reflect the current size
*
- * \return non-zero if the toolbar height has changed
+ * \param toolbar the toolbar to update
*/
-int ro_theme_resize_toolbar(struct toolbar *toolbar, wimp_w window) {
- os_box extent = { 0, 0, 0, 0 };
+void ro_gui_theme_resize_toolbar_status(struct toolbar *toolbar) {
+ os_error *error;
wimp_outline outline;
- wimp_outline status_outline;
wimp_window_state state;
- int width, status_width;
- int return_value = 0;
-
- /* Paranoia
- */
- if (toolbar == NULL) return 0;
-
- /* Get the toolbar width
- */
- outline.w = window;
- if (xwimp_get_window_outline(&outline)) return 0;
- width = outline.outline.x1 - outline.outline.x0 - 2;
-
- /* Reformat if we should
- */
- if ((toolbar->width != width) || (toolbar->resize_status) || (toolbar->update_pending)) {
- if ((toolbar->resize_status) && (toolbar->status_handle)) {
- status_outline.w = toolbar->status_handle;
- if (xwimp_get_window_outline(&status_outline)) return 0;
- toolbar->status_width = width -
- (status_outline.outline.x1 - status_outline.outline.x0 - 4);
- toolbar->resize_status = 0;
- } else if (toolbar->status_handle) {
- /* Update the extent of the status window
- */
- state.w = window;
- if (xwimp_get_window_state(&state)) return 0;
- extent.x1 = state.visible.x1 - state.visible.x0;
- extent.y1 = toolbar->status_height - 2;
- xwimp_set_extent(toolbar->status_handle, &extent);
-
- /* Re-open the status window as we can't use the nested
- wimp to manage everything as it would keep extending
- the size incorrectly.
- */
- status_width = width - toolbar->status_width;
- if (status_width < 12) status_width = 12;
- if (toolbar->status_window) {
- state.w = toolbar->status_handle;
- state.xscroll = 0;
- state.yscroll = 0;
- state.next = wimp_TOP;
- state.visible.x0 = outline.outline.x0;
- state.visible.x1 = outline.outline.x0 + status_width;
- state.visible.y0 = outline.outline.y0 - toolbar->status_height;
- state.visible.y1 = outline.outline.y0 - 2;
- xwimp_open_window_nested((wimp_open *) &state, window,
- wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
- << wimp_CHILD_XORIGIN_SHIFT |
- wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
- << wimp_CHILD_YORIGIN_SHIFT |
- wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
- << wimp_CHILD_LS_EDGE_SHIFT |
- wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
- << wimp_CHILD_BS_EDGE_SHIFT |
- wimp_CHILD_LINKS_PARENT_VISIBLE_TOP_OR_RIGHT
- << wimp_CHILD_RS_EDGE_SHIFT |
- wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
- << wimp_CHILD_TS_EDGE_SHIFT);
- } else {
- if (toolbar->update_pending) {
- xwimp_close_window(toolbar->status_handle);
- }
- }
- }
+ wimp_w parent = NULL;
+ int parent_size, status_size;
+ if ((!toolbar) || (!toolbar->parent_handle)) return;
+
+ /* Get the width to scale to
+ */
+ parent = toolbar->parent_handle;
+ outline.w = toolbar->parent_handle;
+ error = xwimp_get_window_outline(&outline);
+ if (error) {
+ LOG(("xwimp_get_window_outline: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ return;
+ }
+ parent_size = outline.outline.x1 - outline.outline.x0 - ro_get_vscroll_width(parent) - 2;
- /* Resize the toolbar
- */
- return ro_toolbar_reformat(toolbar, width);
+ /* Get the current size
+ */
+ state.w = toolbar->status_handle;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG(("xwimp_get_window_state: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ return;
}
- return return_value;
+ status_size = state.visible.x1 - state.visible.x0;
+
+ /* Store the new size
+ */
+ toolbar->status_width = (10000 * status_size) / parent_size;
+ if (toolbar->status_width > 10000) toolbar->status_width = 10000;
+ ro_gui_theme_process_toolbar(toolbar, -1);
}
/**
- * Make a list of available themes.
+ * Updates the toolbar to reflect changes to the icon flags and any reformatting
+ * required due to the change in parent window size.
*
- * \return a forwardly link list of available themes
+ * \param toolbar the toolbar to update
+ * \param width a specific width to resize to, or -1 to use parent width
+ * \return whether the operation was successful
*/
-
-struct theme_entry *ro_theme_list(unsigned int *entries) {
- char pathname[256];
- int context = 0;
- int read_count;
- struct theme_entry *first = NULL;
- struct theme_entry *last = NULL;
- struct theme_entry *theme = NULL;
- osgbpb_INFO(100) info;
+bool ro_gui_theme_process_toolbar(struct toolbar *toolbar, int width) {
+ wimp_caret caret;
+ os_box extent = { 0, 0, 0, 0 };
os_error *error;
+ wimp_w parent = NULL;
+ wimp_outline outline;
+ wimp_window_state state;
+ int throbber_x = -1;
+ int status_max;
+ int left_edge, right_edge, bottom_edge;
+ int status_size = 0;
+ int status_height = 0;
+ if (!toolbar) return false;
+ int old_height = toolbar->height;
+ int old_width = toolbar->toolbar_current;
+ struct toolbar_icon *toolbar_icon;
+ bool visible_icon = false;
+
+ /* Find the parent window handle if we need to process the status window,
+ or the caller has requested we calculate the width ourself.
+ */
+ if ((width == -1) || ((toolbar->status_handle) && (toolbar->display_status))) {
+ parent = toolbar->parent_handle;
+
+ /* Get the window outline width
+ */
+ if (width == -1) {
+ if (!parent) return false;
+ outline.w = toolbar->parent_handle;
+ error = xwimp_get_window_outline(&outline);
+ if (error) {
+ LOG(("xwimp_get_window_outline: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ return false;
+ }
+ width = outline.outline.x1 - outline.outline.x0 - 2;
+ }
+ }
+
+ /* Reformat the buttons starting with the throbber
+ */
+ if ((width != old_width) || (toolbar->reformat_buttons)) {
+ left_edge = 6;
+ right_edge = width - 8;
+ toolbar->height = 0;
+ if ((toolbar->theme) && (toolbar->type == THEME_BROWSER_TOOLBAR) &&
+ (toolbar->display_throbber)) {
+ if (!toolbar->theme->throbber_right) {
+ throbber_x = left_edge;
+ left_edge += toolbar->theme->throbber_width + 8;
+ }
+ toolbar->height = toolbar->theme->throbber_height + 8;
+ }
+ if ((toolbar->type == THEME_BROWSER_TOOLBAR) && (toolbar->display_url)) {
+ if (toolbar->height < 52 + 8) toolbar->height = 52 + 8;
+ }
- *entries = 0;
- while (context != -1) {
- error = xosgbpb_dir_entries_info(THEMES_DIR,
- (osgbpb_info_list *) &info, 1, context,
- sizeof(info), 0, &read_count, &context);
- if (error) {
- LOG(("xosgbpb_dir_entries_info: 0x%x: %s",
- error->errnum, error->errmess));
- warn_user("MiscError", error->errmess);
- ro_theme_free(first);
- *entries = 0;
- return NULL;
+ /* Get the minimum height of the icons
+ */
+ if (toolbar->display_buttons) {
+ toolbar_icon = toolbar->icon;
+ while (toolbar_icon) {
+ if (toolbar_icon->display) {
+ if (!toolbar->reformat_buttons) {
+ left_edge += toolbar_icon->width;
+ visible_icon = true;
+ }
+ if ((toolbar_icon->height != 0) &&
+ (toolbar->height < toolbar_icon->height + 8)) {
+ toolbar->height = toolbar_icon->height + 8;
+ }
+ }
+ toolbar_icon = toolbar_icon->next;
+ }
+ if (visible_icon) left_edge += 8;
+ }
+
+ /* Check for minimum widths
+ */
+ if (toolbar->type == THEME_BROWSER_TOOLBAR) {
+ bottom_edge = left_edge;
+ if (toolbar->display_url) bottom_edge += 32;
+ if (bottom_edge > right_edge) right_edge = bottom_edge;
+ if ((toolbar->theme) && (toolbar->display_throbber) &&
+ (toolbar->theme->throbber_right)) {
+ bottom_edge += toolbar->theme->throbber_width;
+ if (bottom_edge > right_edge) right_edge = bottom_edge;
+ throbber_x = right_edge - toolbar->theme->throbber_width;
+ right_edge -= toolbar->theme->throbber_width + 8;
+ }
}
- if (read_count == 0)
- continue;
+ if (toolbar->reformat_buttons) {
+ /* Hide the URL bar if we should
+ */
+ if (!toolbar->display_url) {
+ if (!xwimp_get_caret_position(&caret)) {
+ if ((caret.w == toolbar->toolbar_handle) &&
+ (caret.i == ICON_TOOLBAR_URL))
+ xwimp_set_caret_position((wimp_w)-1, 0, 0, 0, 0, 0);
+ }
+ xwimp_resize_icon(toolbar->toolbar_handle, ICON_TOOLBAR_URL,
+ 0, -16384, 0, -16384);
+ }
+ ro_gui_set_icon_shaded_state(toolbar->toolbar_handle, ICON_TOOLBAR_URL,
+ !toolbar->display_url);
+ xwimp_force_redraw(toolbar->toolbar_handle,
+ 0, 0, 16384, 16384);
+
+ /* Move the buttons
+ */
+ toolbar_icon = toolbar->icon;
+ while (toolbar_icon) {
+ if ((toolbar->display_buttons) && (toolbar_icon->display)
+ && (toolbar_icon->width > 0)) {
+ visible_icon = true;
+ bottom_edge = (toolbar->height -
+ toolbar_icon->height) / 2;
+ xwimp_resize_icon(toolbar->toolbar_handle,
+ toolbar_icon->icon_number,
+ left_edge, bottom_edge,
+ left_edge + toolbar_icon->width,
+ bottom_edge + toolbar_icon->height);
+ left_edge += toolbar_icon->width;
+ } else {
+ xwimp_resize_icon(toolbar->toolbar_handle,
+ toolbar_icon->icon_number,
+ 0, -16384, 0, -16384);
+ }
+ toolbar_icon = toolbar_icon->next;
+ }
+ if (visible_icon) left_edge += 8;
+ }
- /* Get our directory name
- */
- snprintf(pathname, sizeof pathname, "%s.%s",
- THEMES_DIR, info.name);
- pathname[sizeof pathname - 1] = 0;
- /* Load the theme and link it in
- */
- theme = ro_theme_load(pathname);
- if (theme && !(theme->default_settings)) {
- if (first) {
- last->next = theme;
+ if (toolbar->height != 0) toolbar->height += 2;
+ if (toolbar->type == THEME_BROWSER_TOOLBAR) {
+ /* Move the URL bar
+ */
+ if (toolbar->display_url) {
+ xwimp_resize_icon(toolbar->toolbar_handle, ICON_TOOLBAR_URL,
+ left_edge, (toolbar->height / 2) - 26,
+ right_edge, (toolbar->height / 2) + 26);
+ xwimp_force_redraw(toolbar->toolbar_handle,
+ right_edge, 0, 16384, 16384);
+ if (!xwimp_get_caret_position(&caret)) {
+ if ((caret.w == toolbar->toolbar_handle) &&
+ (caret.i == ICON_TOOLBAR_URL)) {
+ xwimp_set_caret_position(toolbar->toolbar_handle,
+ ICON_TOOLBAR_URL,
+ caret.pos.x, caret.pos.y,
+ -1, caret.index);
+ }
+ }
+ ro_gui_redraw_icon(toolbar->toolbar_handle, ICON_TOOLBAR_URL);
+ }
+
+ /* Move the throbber
+ */
+ if ((toolbar->theme) && (throbber_x >= 0) && (toolbar->display_throbber)) {
+ xwimp_resize_icon(toolbar->toolbar_handle, ICON_TOOLBAR_THROBBER,
+ throbber_x, 0,
+ throbber_x + toolbar->theme->throbber_width, toolbar->height);
+ if (toolbar->theme->throbber_right)
+ xwimp_force_redraw(toolbar->toolbar_handle,
+ old_width - width + throbber_x, 0, 16384, 16384);
+ xwimp_force_redraw(toolbar->toolbar_handle,
+ throbber_x, 0, 16384, 16384);
+
} else {
- first = theme;
+ xwimp_resize_icon(toolbar->toolbar_handle, ICON_TOOLBAR_THROBBER,
+ 0, -16384, 0, -16384);
}
- last = theme;
- *entries = *entries + 1;
+ }
+
+ /* Re-attach to the parent
+ */
+ toolbar->toolbar_current = width;
+ if ((toolbar->reformat_buttons) && (parent) && (old_height != toolbar->height)) {
+ ro_gui_theme_attach_toolbar(toolbar, parent);
+ }
+ toolbar->reformat_buttons = false;
+ }
+
+ /* Reformat the status bar
+ */
+ if ((toolbar->status_handle) && (parent)) {
+ /* Get the current state
+ */
+ state.w = toolbar->status_handle;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG(("xwimp_get_window_state: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ return false;
+ }
+
+ /* Open or close the window
+ */
+ if (!toolbar->display_status) {
+ if (state.flags & wimp_WINDOW_OPEN)
+ xwimp_close_window(toolbar->status_handle);
} else {
- if (theme) ro_theme_free(theme);
+ /* Get the status bar height/width
+ */
+ status_max = width - ro_get_vscroll_width(parent);
+ status_size = (status_max * toolbar->status_width) / 10000;
+ if (status_size < 12) status_size = 12;
+ status_height = ro_get_hscroll_height(parent) - 2;
+
+ /* Update the extent
+ */
+ extent.x1 = status_max;
+ extent.y1 = status_height - 2;
+ xwimp_set_extent(toolbar->status_handle, &extent);
+
+ /* Re-open the window
+ */
+ state.w = toolbar->status_handle;
+ state.xscroll = 0;
+ state.yscroll = 0;
+ state.next = wimp_TOP;
+ state.visible.x0 = outline.outline.x0;
+ state.visible.x1 = outline.outline.x0 + status_size;
+ state.visible.y0 = outline.outline.y0 - status_height;
+ state.visible.y1 = outline.outline.y0 - 2;
+ xwimp_open_window_nested((wimp_open *)&state, parent,
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_XORIGIN_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_YORIGIN_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_LS_EDGE_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_BS_EDGE_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_RS_EDGE_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_TS_EDGE_SHIFT);
+
+ /* Resize and redraw the icons
+ */
+ status_size = state.visible.x1 - state.visible.x0;
+ if (status_size != toolbar->status_current) {
+ xwimp_resize_icon(toolbar->status_handle, ICON_STATUS_TEXT,
+ 0, 0,
+ status_size - 12, status_height - 2);
+ xwimp_resize_icon(toolbar->status_handle, ICON_STATUS_RESIZE,
+ status_size - 12, 0,
+ status_size, status_height - 2);
+ xwimp_force_redraw(toolbar->status_handle,
+ toolbar->status_current - 12, 0,
+ status_size - 12, status_height - 2);
+ xwimp_force_redraw(toolbar->status_handle,
+ status_size - 12, 0,
+ status_size, status_height - 2);
+ toolbar->status_current = status_size;
+ }
}
}
- return first;
+ return true;
}
/**
- * Free a linked list of themes.
+ * Destroys a toolbar and frees any associated memory.
*
- * \param theme the list of themes to free
+ * \param toolbar the toolbar to destroy
*/
+void ro_gui_theme_destroy_toolbar(struct toolbar *toolbar) {
+ struct toolbar_icon *icon;
+ struct toolbar_icon *next_icon;
+ if (!toolbar) return;
+
+ /* Delete our windows
+ */
+ if (toolbar->toolbar_handle)
+ xwimp_delete_window(toolbar->toolbar_handle);
+ if (toolbar->status_handle)
+ xwimp_delete_window(toolbar->status_handle);
-void ro_theme_free(struct theme_entry *theme) {
- struct theme_entry *next;
- while (theme) {
- free(theme->name);
- free(theme->author);
- free(theme->sprite_area);
- next = theme->next;
- free(theme);
- theme = next;
+ /* Free the Wimp buffer (we only created one for them all)
+ */
+ free(toolbar->url_buffer);
+
+ /* Free all the icons
+ */
+ next_icon = toolbar->icon;
+ while ((icon = next_icon) != NULL) {
+ next_icon = icon->next;
+ ro_gui_theme_destroy_toolbar_icon(icon);
+ }
+ free(toolbar);
+}
+
+void ro_gui_theme_add_toolbar_icon(struct toolbar *toolbar, const char *name, int icon_number) {
+ if (!toolbar) return;
+ struct toolbar_icon *toolbar_icon;
+ struct toolbar_icon *link_icon;
+
+ /* Separators are really a sprite called "separator"
+ */
+ if (name == NULL) name = "separator";
+
+ /* Create a new toolbar
+ */
+ toolbar_icon = calloc(sizeof(struct toolbar_icon), 1);
+ if (!toolbar_icon) {
+ LOG(("No memory for malloc()"));
+ warn_user("NoMemory", 0);
+ return;
+ }
+
+ /* Set up and link in the icon
+ */
+ sprintf(toolbar_icon->name, name);
+ sprintf(toolbar_icon->validation, "R5;S%s,p%s", name, name);
+ toolbar_icon->icon_number = icon_number;
+ toolbar_icon->display = true;
+ if (!toolbar->icon) {
+ toolbar->icon = toolbar_icon;
+ } else {
+ link_icon = toolbar->icon;
+ while (link_icon->next) link_icon = link_icon->next;
+ link_icon->next = toolbar_icon;
}
}
+
+/**
+ * Updates a toolbar icon with respect to the associated sprite.
+ *
+ * \param icon the toolbar icon to update
+ */
+void ro_gui_theme_update_toolbar_icon(struct toolbar *toolbar, struct toolbar_icon *icon) {
+ os_coord dimensions;
+ os_mode mode;
+ os_error *error;
+ int default_width = 0;
+
+ /* Separators default to a width of 16
+ */
+ if (icon->icon_number == -1) default_width = 16;
+
+ /* Handle no theme/no sprite area
+ */
+ if (!toolbar) return;
+ if ((!toolbar->theme) || (!toolbar->theme->sprite_area)) {
+ icon->width = default_width;
+ icon->height = 0;
+ return;
+ }
+
+ /* Get the sprite details
+ */
+ error = xosspriteop_read_sprite_info(osspriteop_USER_AREA,
+ toolbar->theme->sprite_area, (osspriteop_id)icon->name,
+ &dimensions.x, &dimensions.y, 0, &mode);
+ if (error) {
+ icon->width = default_width;
+ icon->height = 0;
+ if (error->errnum != error_SPRITE_OP_DOESNT_EXIST) {
+ LOG(("xosspriteop_read_sprite_info: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("MiscError", error->errmess);
+ }
+ return;
+ }
+
+ /* Store the details
+ */
+ ro_convert_pixels_to_os_units(&dimensions, mode);
+ icon->width = dimensions.x;
+ icon->height = dimensions.y;
+}
+
+
+/**
+ * Destroys a toolbar icon and frees any associated memory.
+ * The icon is not removed from any linked list.
+ *
+ * \param icon the toolbar icon to destroy
+ */
+void ro_gui_theme_destroy_toolbar_icon(struct toolbar_icon *icon) {
+ free(icon);
+}