From bf57d852ae2ee7c647557c087cc1da95a0305cb4 Mon Sep 17 00:00:00 2001 From: Richard Wilson Date: Mon, 30 Aug 2004 21:03:48 +0000 Subject: [project @ 2004-08-30 21:03:48 by rjw] Reworking of themes and toolbars. svn path=/import/netsurf/; revision=1254 --- !NetSurf/!Sprites22,ff9 | Bin 13020 -> 19724 bytes !NetSurf/Resources/en/Templates,fec | Bin 8908 -> 8908 bytes !NetSurf/Resources/fr/Templates,fec | Bin 9042 -> 9042 bytes makefile | 2 +- riscos.mk | 2 +- riscos/dialog.c | 406 +++++----- riscos/gui.c | 39 +- riscos/gui.h | 10 +- riscos/help.c | 2 +- riscos/hotlist.c | 4 +- riscos/htmlredraw.c | 2 +- riscos/menus.c | 42 +- riscos/options.h | 4 +- riscos/theme.c | 1451 +++++++++++++++++++++++++++-------- riscos/theme.h | 108 ++- riscos/wimp.c | 22 +- riscos/wimp.h | 4 + riscos/window.c | 157 ++-- 18 files changed, 1595 insertions(+), 660 deletions(-) diff --git a/!NetSurf/!Sprites22,ff9 b/!NetSurf/!Sprites22,ff9 index 1aba72e95..80372b3ae 100644 Binary files a/!NetSurf/!Sprites22,ff9 and b/!NetSurf/!Sprites22,ff9 differ diff --git a/!NetSurf/Resources/en/Templates,fec b/!NetSurf/Resources/en/Templates,fec index 8f637ae40..01a9280bd 100644 Binary files a/!NetSurf/Resources/en/Templates,fec and b/!NetSurf/Resources/en/Templates,fec differ diff --git a/!NetSurf/Resources/fr/Templates,fec b/!NetSurf/Resources/fr/Templates,fec index 14aa4b72c..eed7972f6 100644 Binary files a/!NetSurf/Resources/fr/Templates,fec and b/!NetSurf/Resources/fr/Templates,fec differ diff --git a/makefile b/makefile index 31489ee10..ecefa1770 100644 --- a/makefile +++ b/makefile @@ -31,7 +31,7 @@ OBJECTS_RISCOS += 401login.o debugwin.o \ jpeg.o menus.o mng.o mouseactions.o plugin.o print.o \ save.o save_complete.o save_draw.o save_text.o \ schedule.o search.o sprite.o textselection.o theme.o thumbnail.o \ - toolbar.o ufont.o uri.o url_protocol.o wimp.o window.o # riscos/ + ufont.o uri.o url_protocol.o wimp.o window.o # riscos/ # OBJECTS_RISCOS += memdebug.o OBJECTS_NCOS = $(OBJECTS_RISCOS) diff --git a/riscos.mk b/riscos.mk index 65aac2a8f..36e7ceae5 100644 --- a/riscos.mk +++ b/riscos.mk @@ -6,7 +6,7 @@ PLATFORM_CFLAGS_DEBUG = -INSLibs:include -IOSLib: LDFLAGS_RISCOS = NSLibs:lib/libxml2 NSLibs:lib/libz NSLibs:lib/libcurl \ NSLibs:lib/libssl NSLibs:lib/libcrypto NSLibs:lib/libares \ - NSLibs:lib/libmng NSLibs:lib/liblcms NSLibs:lib/libjpeg OSLib:o.oslib32 + NSLibs:lib/libmng NSLibs:lib/libjpeg OSLib:o.oslib32 LDFLAGS_SMALL = NSLibs:lib/libxml2 NSLibs:lib/libz NSLibs:lib/libcurl \ NSLibs:lib/libares NSLibs:lib/libmng \ NSLibs:lib/libjpeg OSLib:o.oslib32 diff --git a/riscos/dialog.c b/riscos/dialog.c index 04782f532..943954b8d 100644 --- a/riscos/dialog.c +++ b/riscos/dialog.c @@ -32,6 +32,8 @@ */ #define MAX_PERSISTANT 8 + + wimp_w dialog_info, dialog_saveas, dialog_config, dialog_config_br, dialog_config_prox, dialog_config_th, download_template, #ifdef WITH_AUTH @@ -45,17 +47,30 @@ static int ro_gui_choices_font_size; static int ro_gui_choices_font_min_size; static bool ro_gui_choices_http_proxy; static int ro_gui_choices_http_proxy_auth; -static char *theme_choice = 0; -static struct theme_entry *theme_list = 0; -static unsigned int theme_list_entries = 0; static int config_br_icon = -1; static const char *ro_gui_choices_lang = 0; static const char *ro_gui_choices_alang = 0; + +struct toolbar_display { + struct toolbar *toolbar; + struct theme_descriptor *descriptor; + int icon_number; + struct toolbar_display *next; +}; + +static struct theme_descriptor *theme_choice = NULL; +static struct theme_descriptor *theme_list = NULL; +static int theme_count = 0; +static struct toolbar_display *toolbars = NULL; +static char theme_radio_validation[] = "Sradiooff,radioon\0"; + + static const char *ro_gui_proxy_auth_name[] = { "ProxyNone", "ProxyBasic", "ProxyNTLM" }; + /* A simple mapping of parent and child */ static struct { @@ -72,12 +87,14 @@ static void ro_gui_dialog_click_config_prox(wimp_pointer *pointer); static void ro_gui_dialog_config_proxy_update(void); static void ro_gui_dialog_click_config_th(wimp_pointer *pointer); static void ro_gui_dialog_click_config_th_pane(wimp_pointer *pointer); -static void ro_gui_redraw_config_th_pane_plot(wimp_draw *redraw); static void ro_gui_dialog_click_zoom(wimp_pointer *pointer); static void ro_gui_dialog_reset_zoom(void); static void ro_gui_dialog_click_warning(wimp_pointer *pointer); static const char *language_name(const char *code); -static struct theme_entry *ro_gui_theme_entry(int index); + +static void ro_gui_dialog_load_themes(void); +static void ro_gui_dialog_free_themes(void); + /** * Load and create dialogs from template file. @@ -483,13 +500,8 @@ void ro_gui_dialog_config_prepare(void) ro_gui_dialog_config_proxy_update(); /* themes pane */ - free(theme_choice); - theme_choice = 0; - if (option_theme) - theme_choice = strdup(option_theme); - if (theme_list) - ro_theme_free(theme_list); - theme_list = ro_theme_list(&theme_list_entries); + ro_gui_dialog_load_themes(); + theme_choice = ro_gui_theme_find(option_theme); } @@ -497,8 +509,7 @@ void ro_gui_dialog_config_prepare(void) * Set the current options to the settings in the choices panes. */ -void ro_gui_dialog_config_set(void) -{ +void ro_gui_dialog_config_set(void) { /* browser pane */ option_font_size = ro_gui_choices_font_size; option_font_min_size = ro_gui_choices_font_min_size; @@ -537,8 +548,14 @@ void ro_gui_dialog_config_set(void) ICON_CONFIG_PROX_AUTHPASS)); /* theme pane */ - free(option_theme); - option_theme = strdup(theme_choice); + if (option_theme) { + free(option_theme); + option_theme = NULL; + } + if (theme_choice) { + option_theme = strdup(theme_choice->filename); + ro_gui_theme_apply(theme_choice); + } } @@ -554,16 +571,16 @@ void ro_gui_dialog_click_config(wimp_pointer *pointer) ro_gui_save_options(); if (pointer->buttons == wimp_CLICK_SELECT) { ro_gui_dialog_close(dialog_config); - if (theme_list) { - ro_theme_free(theme_list); - theme_list = 0; - } + ro_gui_dialog_free_themes(); } break; case ICON_CONFIG_CANCEL: - if (pointer->buttons == wimp_CLICK_SELECT) + if (pointer->buttons == wimp_CLICK_SELECT) { ro_gui_dialog_close(dialog_config); - ro_gui_dialog_config_prepare(); + ro_gui_dialog_free_themes(); + } else { + ro_gui_dialog_config_prepare(); + } break; case ICON_CONFIG_BROWSER: /* set selected state of radio icon to prevent @@ -809,172 +826,24 @@ void ro_gui_dialog_click_config_th(wimp_pointer *pointer) /** * Handle clicks in the scrolling Theme Choices list pane. */ +void ro_gui_dialog_click_config_th_pane(wimp_pointer *pointer) { + struct toolbar_display *link; + int i = pointer->i; + if (i < 0) return; -void ro_gui_dialog_click_config_th_pane(wimp_pointer *pointer) -{ - unsigned int i, y; - wimp_window_state state; - os_error *error; - - state.w = dialog_config_th_pane; - 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; - } - - y = -(pointer->pos.y - (state.visible.y1 - state.yscroll)) / - THEME_HEIGHT; - - if (!theme_list || theme_list_entries <= y) - return; - - if (theme_choice && strcmp(theme_choice, ro_gui_theme_entry(y)->name) == 0) - return; - - if (theme_choice) { - for (i = 0; i != theme_list_entries && - strcmp(theme_choice, ro_gui_theme_entry(i)->name); i++) - ; - if (i != theme_list_entries) { - error = xwimp_force_redraw(dialog_config_th_pane, - 0, -i * THEME_HEIGHT - THEME_HEIGHT - 2, - THEME_WIDTH, -i * THEME_HEIGHT + 2); - if (error) { - LOG(("xwimp_force_redraw: 0x%x: %s", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); - return; - } - } - } - - free(theme_choice); - theme_choice = strdup(ro_gui_theme_entry(y)->name); - - error = xwimp_force_redraw(dialog_config_th_pane, - 0, -y * THEME_HEIGHT - THEME_HEIGHT - 2, - THEME_WIDTH, -y * THEME_HEIGHT + 2); - if (error) { - LOG(("xwimp_force_redraw: 0x%x: %s", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); - return; - } -} - -struct theme_entry *ro_gui_theme_entry(int index) { - struct theme_entry *entry = theme_list; - for (int i = 0; i < index; i++) entry = entry->next; - return entry; -} - -/** - * Redraw the scrolling Theme Choices list pane. - */ - -void ro_gui_redraw_config_th_pane(wimp_draw *redraw) -{ - osbool more; - os_error *error; - - error = xwimp_redraw_window(redraw, &more); - if (error) { - LOG(("xwimp_redraw_window: 0x%x: %s", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); - return; - } - while (more) { - ro_gui_redraw_config_th_pane_plot(redraw); - error = xwimp_get_rectangle(redraw, &more); - if (error) { - LOG(("xwimp_get_rectangle: 0x%x: %s", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); - return; - } - } -} - - -/** - * Redraw the scrolling Theme Choices list pane. - */ - -void ro_gui_redraw_config_th_pane_plot(wimp_draw *redraw) -{ - unsigned int i, j; - int x0 = redraw->box.x0 - redraw->xscroll; - int y0 = redraw->box.y1 - redraw->yscroll; - int x; - static char sprite[][10] = { "back", "forward", "stop", "reload", - "history", "scale", "save" }; - wimp_icon icon; - os_error *error = 0; - - icon.flags = wimp_ICON_SPRITE | wimp_ICON_HCENTRED | - wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED; - - for (i = 0; i != theme_list_entries; i++) { - error = xwimptextop_set_colour(os_COLOUR_BLACK, - os_COLOUR_VERY_LIGHT_GREY); - if (error) - break; - - /* plot background for selected theme */ - if (theme_choice && - strcmp(ro_gui_theme_entry(i)->name, theme_choice) == 0) { - error = xcolourtrans_set_gcol(os_COLOUR_LIGHT_GREY, - 0, os_ACTION_OVERWRITE, 0, 0); - if (error) - break; - error = xos_plot(os_MOVE_TO, x0, y0 - i * THEME_HEIGHT); - if (error) - break; - error = xos_plot(os_PLOT_RECTANGLE | os_PLOT_BY, - THEME_WIDTH, -THEME_HEIGHT); - if (error) - break; - error = xwimptextop_set_colour(os_COLOUR_BLACK, - os_COLOUR_LIGHT_GREY); - if (error) - break; - } - - /* icons */ - if (ro_gui_theme_entry(i)->sprite_area) { - icon.extent.y0 = -i * THEME_HEIGHT - THEME_HEIGHT; - icon.extent.y1 = -i * THEME_HEIGHT; - icon.data.indirected_sprite.area = ro_gui_theme_entry(i)->sprite_area; - icon.data.indirected_sprite.size = 12; - for (j = 0, x = 0; j != sizeof sprite / sizeof sprite[0]; j++) { - icon.extent.x0 = x; - icon.extent.x1 = x + 50; - icon.data.indirected_sprite.id = - (osspriteop_id) sprite[j]; - error = xwimp_plot_icon(&icon); - if (error) - break; - x += 50; - } - } - if (error) - break; - - /* theme name */ - error = xwimptextop_paint(0, ro_gui_theme_entry(i)->name, - x0 + 400, - y0 - i * THEME_HEIGHT - THEME_HEIGHT / 2); - if (error) - break; - } - - if (error) { - LOG(("0x%x: %s", error->errnum, error->errmess)); - warn_user("MiscError", error->errmess); + /* Set the clicked theme as selected + */ + link = toolbars; + while (link) { + if (link->icon_number == i) { + theme_choice = link->descriptor; + ro_gui_set_icon_selected_state(dialog_config_th_pane, + link->icon_number, true); + } else { + ro_gui_set_icon_selected_state(dialog_config_th_pane, + link->icon_number, false); + } + link = link->next; } } @@ -1114,3 +983,166 @@ const char *language_name(const char *code) key[6] = code[1]; return messages_get(key); } + + +/** + * Loads and nests all available themes in the theme pane. + */ +void ro_gui_dialog_load_themes(void) { + os_error *error; + os_box extent = { 0, 0, 0, 0 }; + struct theme_descriptor *descriptor; + struct toolbar_display *link; + struct toolbar_display *toolbar_display; + struct toolbar *toolbar; + wimp_icon_create new_icon; + wimp_window_state state; + int parent_width, nested_y, min_extent, base_extent; + + /* Delete our old list and get/open a new one + */ + ro_gui_dialog_free_themes(); + theme_list = ro_gui_theme_get_available(); + ro_gui_theme_open(theme_list, true); + theme_choice = ro_gui_theme_find(option_theme); + + /* Create toolbars for each theme + */ + theme_count = 0; + descriptor = theme_list; + while (descriptor) { + /* Try to create a toolbar + */ + toolbar = ro_gui_theme_create_toolbar(descriptor, THEME_BROWSER_TOOLBAR); + if (toolbar) { + toolbar_display = calloc(sizeof(struct toolbar_display), 1); + if (!toolbar_display) { + LOG(("No memory for calloc()")); + warn_user("NoMemory", 0); + return; + } + toolbar_display->toolbar = toolbar; + toolbar_display->descriptor = descriptor; + if (!toolbars) { + toolbars = toolbar_display; + } else { + link = toolbars; + while (link->next) link = link->next; + link->next = toolbar_display; + } + theme_count++; + } + descriptor = descriptor->next; + } + + /* Nest the toolbars + */ + state.w = dialog_config_th_pane; + 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; + } + parent_width = state.visible.x1 - state.visible.x0; + min_extent = state.visible.y0 - state.visible.y1; + nested_y = 0; + base_extent = state.visible.y1; + extent.x1 = parent_width; + link = toolbars; + new_icon.w = dialog_config_th_pane; + new_icon.icon.extent.x0 = 0; + new_icon.icon.extent.x1 = parent_width; + new_icon.icon.flags = wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_INDIRECTED | + wimp_ICON_VCENTRED | + (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) | + (wimp_COLOUR_VERY_LIGHT_GREY << wimp_ICON_BG_COLOUR_SHIFT) | + (wimp_BUTTON_RADIO << wimp_ICON_BUTTON_TYPE_SHIFT) | + (1 << wimp_ICON_ESG_SHIFT); + new_icon.icon.data.indirected_text_and_sprite.validation = + theme_radio_validation; + while (link) { + /* Update the toolbar and extent + */ + ro_gui_theme_process_toolbar(link->toolbar, parent_width); + extent.y0 = nested_y - link->toolbar->height - 48; + if (link->next) extent.y0 -= 16; + if (extent.y0 > min_extent) extent.y0 = min_extent; + xwimp_set_extent(dialog_config_th_pane, &extent); + + /* Create the descriptor icon + */ + new_icon.icon.extent.y1 = nested_y - link->toolbar->height; + new_icon.icon.extent.y0 = nested_y - link->toolbar->height - 48; + new_icon.icon.data.indirected_text_and_sprite.text = + link->descriptor->filename; + new_icon.icon.data.indirected_text_and_sprite.size = + strlen(link->descriptor->filename) + 1; + xwimp_create_icon(&new_icon, &link->icon_number); + + /* Nest the toolbar window + */ + state.w = link->toolbar->toolbar_handle; + state.visible.y1 = nested_y + base_extent; + state.visible.y0 = state.visible.y1 - link->toolbar->height + 2; + xwimp_open_window_nested((wimp_open *)&state, dialog_config_th_pane, + wimp_CHILD_LINKS_PARENT_WORK_AREA + << wimp_CHILD_XORIGIN_SHIFT | + wimp_CHILD_LINKS_PARENT_WORK_AREA + << wimp_CHILD_YORIGIN_SHIFT | + wimp_CHILD_LINKS_PARENT_WORK_AREA + << wimp_CHILD_LS_EDGE_SHIFT | + wimp_CHILD_LINKS_PARENT_WORK_AREA + << wimp_CHILD_BS_EDGE_SHIFT | + wimp_CHILD_LINKS_PARENT_WORK_AREA + << wimp_CHILD_RS_EDGE_SHIFT | + wimp_CHILD_LINKS_PARENT_WORK_AREA + << wimp_CHILD_TS_EDGE_SHIFT); + + /* Continue processing + */ + nested_y -= link->toolbar->height + 48 + 16; + link = link->next; + } + + /* Set the current theme as selected + */ + link = toolbars; + while (link) { + if (link->descriptor == theme_choice) { + ro_gui_set_icon_selected_state(dialog_config_th_pane, + link->icon_number, true); + break; + } + link = link->next; + } +} + + +/** + * Removes and closes all themes in the theme pane. + */ +void ro_gui_dialog_free_themes(void) { + struct toolbar_display *toolbar; + struct toolbar_display *next_toolbar; + + /* Free all our toolbars + */ + next_toolbar = toolbars; + while ((toolbar = next_toolbar) != NULL) { + xwimp_delete_icon(dialog_config_th_pane, toolbar->icon_number); + ro_gui_theme_destroy_toolbar(toolbar->toolbar); + next_toolbar = toolbar->next; + free(toolbar); + } + toolbars = NULL; + + /* Close all our themes + */ + if (theme_list) ro_gui_theme_close(theme_list, true); + theme_list = NULL; + theme_count = 0; + theme_choice = NULL; +} + diff --git a/riscos/gui.c b/riscos/gui.c index 732adb472..8d4d340a6 100644 --- a/riscos/gui.c +++ b/riscos/gui.c @@ -49,7 +49,6 @@ #endif #include "netsurf/riscos/save_complete.h" #include "netsurf/riscos/theme.h" -#include "netsurf/riscos/toolbar.h" #ifdef WITH_URI #include "netsurf/riscos/uri.h" #endif @@ -61,7 +60,6 @@ #include "netsurf/utils/messages.h" #include "netsurf/utils/utils.h" - const char *__dynamic_da_name = "NetSurf"; /**< For UnixLib. */ int __feature_imagefs_is_file = 1; /**< For UnixLib. */ /* default filename handling */ @@ -172,10 +170,9 @@ static char *ro_path_to_url(const char *path); void gui_init(int argc, char** argv) { char path[40]; - char theme_fname[256]; os_error *error; int length; - struct theme_entry *theme; + struct theme_descriptor *descriptor = NULL; xhourglass_start(1); @@ -222,23 +219,15 @@ void gui_init(int argc, char** argv) if (getenv("NetSurf$Start_URI_Handler")) xwimp_start_task("Desktop", 0); - if (option_theme != NULL) { - if ((length = snprintf(theme_fname, sizeof(theme_fname), - ".Themes.%s", option_theme)) >= 0 - && length < (int)sizeof(theme_fname) - /* check if theme directory exists */ - && !is_dir(theme_fname)) { - free(option_theme); - option_theme = NULL; - } - } - if (option_theme == NULL) - strcpy(theme_fname, ".Themes.Default"); - theme = ro_theme_load(theme_fname); - if (theme == NULL) - LOG(("Unable to load default theme")); - ro_theme_apply(theme); + /* Load our chosen theme + */ + ro_gui_theme_initialise(); + descriptor = ro_gui_theme_find(option_theme); + if (!descriptor) descriptor = ro_gui_theme_find("Default"); + ro_gui_theme_apply(descriptor); + /* Open the templates + */ if ((length = snprintf(path, sizeof(path), ".Resources.%s.Templates", option_language)) < 0 || length >= (int)sizeof(path)) @@ -684,9 +673,7 @@ void ro_gui_redraw_window_request(wimp_draw *redraw) osbool more; os_error *error; - if (redraw->w == dialog_config_th_pane) - ro_gui_redraw_config_th_pane(redraw); - else if (redraw->w == history_window) + if (redraw->w == history_window) ro_gui_history_redraw(redraw); else if (redraw->w == hotlist_window) ro_gui_hotlist_redraw(redraw); @@ -737,10 +724,8 @@ void ro_gui_open_window_request(wimp_open *open) } g = ro_gui_status_lookup(open->w); - if (g && g->toolbar) { - g->toolbar->resize_status = 1; - ro_theme_resize_toolbar(g->toolbar, g->window); - } + if (g && g->toolbar) + ro_gui_theme_resize_toolbar_status(g->toolbar); } } diff --git a/riscos/gui.h b/riscos/gui.h index 8a825257c..5c9c0c653 100644 --- a/riscos/gui.h +++ b/riscos/gui.h @@ -75,12 +75,9 @@ struct gui_window { int old_width; /**< Width when last opened / os units. */ int old_height; /**< Height when last opened / os units. */ - char status[256]; /**< Buffer for status bar. */ char title[256]; /**< Buffer for window title. */ - char url[256]; /**< Buffer for url entry field. */ int throbber; /**< Current frame of throbber animation. */ - char throb_buf[12]; /**< Buffer for throbber sprite name. */ int throbtime; /**< Time of last throbber frame. */ /** Options. */ @@ -132,7 +129,6 @@ void ro_gui_dialog_click(wimp_pointer *pointer); void ro_gui_save_options(void); bool ro_gui_dialog_keypress(wimp_key *key); void ro_gui_dialog_close(wimp_w close); -void ro_gui_redraw_config_th_pane(wimp_draw *redraw); void ro_gui_menu_prepare_hotlist(void); void ro_gui_dialog_open_config(void); void ro_gui_dialog_proxyauth_menu_selection(int item); @@ -167,6 +163,8 @@ bool ro_gui_401login_keypress(wimp_key *key); /* in window.c */ void ro_gui_window_quit(void); void ro_gui_window_click(struct gui_window *g, wimp_pointer *mouse); +void ro_gui_window_update_theme(void); +void ro_gui_window_update_dimensions(struct gui_window *g, int yscroll); void ro_gui_window_open(struct gui_window *g, wimp_open *open); void ro_gui_window_redraw(struct gui_window *g, wimp_draw *redraw); void ro_gui_window_mouse_at(struct gui_window *g, wimp_pointer *pointer); @@ -281,8 +279,8 @@ bool ro_gui_print_keypress(wimp_key *key); #define ICON_TOOLBAR_HOTLIST_LAST 6 /* icon numbers for toolbar status window */ -#define ICON_STATUS_TEXT 0 -#define ICON_STATUS_RESIZE 1 +#define ICON_STATUS_RESIZE 0 +#define ICON_STATUS_TEXT 1 #define ICON_CONFIG_SAVE 0 #define ICON_CONFIG_CANCEL 1 diff --git a/riscos/help.c b/riscos/help.c index 6a7f7a696..22fc5b09b 100644 --- a/riscos/help.c +++ b/riscos/help.c @@ -18,7 +18,7 @@ #include "oslib/wimp.h" #include "netsurf/riscos/gui.h" #include "netsurf/riscos/help.h" -#include "netsurf/riscos/toolbar.h" +#include "netsurf/riscos/theme.h" #include "netsurf/riscos/wimp.h" #include "netsurf/utils/messages.h" #include "netsurf/utils/log.h" diff --git a/riscos/hotlist.c b/riscos/hotlist.c index de91fbad7..fad751306 100644 --- a/riscos/hotlist.c +++ b/riscos/hotlist.c @@ -25,7 +25,6 @@ #include "netsurf/riscos/gui.h" #include "netsurf/riscos/theme.h" #include "netsurf/riscos/tinct.h" -#include "netsurf/riscos/toolbar.h" #include "netsurf/riscos/wimp.h" #include "netsurf/utils/log.h" #include "netsurf/utils/messages.h" @@ -303,7 +302,8 @@ void ro_gui_hotlist_init(void) { /* Create our toolbar */ - ro_theme_create_hotlist_toolbar(); + hotlist_toolbar = ro_gui_theme_create_toolbar(NULL, THEME_HOTLIST_TOOLBAR); + ro_gui_theme_attach_toolbar(hotlist_toolbar, hotlist_window); /* Update the extent */ diff --git a/riscos/htmlredraw.c b/riscos/htmlredraw.c index b9e47cd00..2a29d8eca 100644 --- a/riscos/htmlredraw.c +++ b/riscos/htmlredraw.c @@ -28,7 +28,7 @@ #include "netsurf/riscos/gui.h" #include "netsurf/riscos/image.h" #include "netsurf/riscos/options.h" -#include "netsurf/riscos/toolbar.h" +#include "netsurf/riscos/theme.h" #include "netsurf/riscos/ufont.h" #include "netsurf/riscos/wimp.h" #include "netsurf/utils/log.h" diff --git a/riscos/menus.c b/riscos/menus.c index 9505331e0..1a8005bf0 100644 --- a/riscos/menus.c +++ b/riscos/menus.c @@ -25,7 +25,6 @@ #include "netsurf/riscos/help.h" #include "netsurf/riscos/options.h" #include "netsurf/riscos/theme.h" -#include "netsurf/riscos/toolbar.h" #include "netsurf/riscos/wimp.h" #include "netsurf/utils/log.h" #include "netsurf/utils/messages.h" @@ -657,6 +656,7 @@ void ro_gui_menu_selection(wimp_selection *selection) wimp_pointer pointer; wimp_window_state state; os_error *error; + int height; wimp_get_pointer_info(&pointer); @@ -757,7 +757,7 @@ void ro_gui_menu_selection(wimp_selection *selection) case 5: /* Print */ break; case 6: /* New window */ - browser_window_create(current_gui->url, current_gui->bw); + browser_window_create(current_gui->bw->current_content->url, current_gui->bw); break; case 7: /* Page source */ ro_gui_view_source(c); @@ -851,29 +851,27 @@ void ro_gui_menu_selection(wimp_selection *selection) case 2: /* Toolbars -> */ switch (selection->items[2]) { case 0: - current_gui->toolbar->standard_buttons = - !current_gui->toolbar->standard_buttons; + current_gui->toolbar->display_buttons = + !current_gui->toolbar->display_buttons; break; case 1: - current_gui->toolbar->url_bar = - !current_gui->toolbar->url_bar; + current_gui->toolbar->display_url = + !current_gui->toolbar->display_url; break; case 2: - current_gui->toolbar->throbber = - !current_gui->toolbar->throbber; + current_gui->toolbar->display_throbber = + !current_gui->toolbar->display_throbber; break; case 3: - current_gui->toolbar->status_window = - !current_gui->toolbar->status_window; - } - if (ro_theme_update_toolbar(current_gui->toolbar, - current_gui->window) || true) { - wimp_window_state state; - state.w = current_gui->window; - wimp_get_window_state(&state); - current_gui->old_height = 0xffffffff; - ro_gui_window_open(current_gui, (wimp_open *)&state); + current_gui->toolbar->display_status = + !current_gui->toolbar->display_status; } + current_gui->toolbar->reformat_buttons = true; + height = current_gui->toolbar->height; + ro_gui_theme_process_toolbar(current_gui->toolbar, -1); + if (height != current_gui->toolbar->height) + ro_gui_window_update_dimensions(current_gui, + height - current_gui->toolbar->height); ro_gui_menu_prepare_toolbars(); break; case 3: /* Render -> */ @@ -1497,10 +1495,10 @@ static void ro_gui_menu_prepare_toolbars(void) { browser_toolbar_menu->entries[index].icon_flags &= ~wimp_ICON_SHADED; browser_toolbar_menu->entries[index].menu_flags &= ~wimp_MENU_TICKED; } - if (toolbar->standard_buttons) browser_toolbar_menu->entries[0].menu_flags |= wimp_MENU_TICKED; - if (toolbar->url_bar) browser_toolbar_menu->entries[1].menu_flags |= wimp_MENU_TICKED; - if (toolbar->throbber) browser_toolbar_menu->entries[2].menu_flags |= wimp_MENU_TICKED; - if (toolbar->status_window) browser_toolbar_menu->entries[3].menu_flags |= wimp_MENU_TICKED; + if (toolbar->display_buttons) browser_toolbar_menu->entries[0].menu_flags |= wimp_MENU_TICKED; + if (toolbar->display_url) browser_toolbar_menu->entries[1].menu_flags |= wimp_MENU_TICKED; + if (toolbar->display_throbber) browser_toolbar_menu->entries[2].menu_flags |= wimp_MENU_TICKED; + if (toolbar->display_status) browser_toolbar_menu->entries[3].menu_flags |= wimp_MENU_TICKED; } else { for (index = 0; index < 4; index++) { browser_toolbar_menu->entries[index].icon_flags |= wimp_ICON_SHADED; diff --git a/riscos/options.h b/riscos/options.h index 34e2b837a..7ea9c3560 100644 --- a/riscos/options.h +++ b/riscos/options.h @@ -60,7 +60,7 @@ bool option_thumbnail_32bpp = true;\ int option_thumbnail_oversampling = 0;\ bool option_history_tooltip = true; \ int option_scale = 100; \ -int option_toolbar_status_width = 640; \ +int option_toolbar_status_width = 5000; \ bool option_toolbar_show_status = true; \ bool option_toolbar_show_buttons = true; \ bool option_toolbar_show_address = true; \ @@ -95,7 +95,7 @@ bool option_plugins = false; { "history_tooltip", OPTION_BOOL, &option_history_tooltip }, \ { "scale", OPTION_INTEGER, &option_scale }, \ { "toolbar_show_status", OPTION_BOOL, &option_toolbar_show_status }, \ -{ "toolbar_status_width", OPTION_INTEGER, &option_toolbar_status_width }, \ +{ "toolbar_status_size", OPTION_INTEGER, &option_toolbar_status_width }, \ { "toolbar_show_buttons", OPTION_BOOL, &option_toolbar_show_buttons }, \ { "toolbar_show_address", OPTION_BOOL, &option_toolbar_show_address }, \ { "toolbar_show_throbber", OPTION_BOOL, &option_toolbar_show_throbber }, \ 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 - * Copyright 2003 James Bursa + * http://www.opensource.org/licenses/gpl-license * Copyright 2004 Richard Wilson - * Copyright 2004 Andrew Timmins */ /** \file - * Toolbar themes (implementation). + * Window themes and toolbars (implementation). */ #include #include #include +#include #include #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); +} diff --git a/riscos/theme.h b/riscos/theme.h index 8c06be5fb..c0c2394dc 100644 --- a/riscos/theme.h +++ b/riscos/theme.h @@ -2,49 +2,93 @@ * 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 - * Copyright 2003 James Bursa * Copyright 2004 Richard Wilson */ /** \file - * Toolbar themes (interface). - * - * A theme consists of a simple sprite file. There is one current theme, which - * is changed by ro_theme_load(). A toolbar can then be created and manipulated. + * Window themes and toolbars (interface). */ +#include + #ifndef _NETSURF_RISCOS_THEME_H_ #define _NETSURF_RISCOS_THEME_H_ -#include "oslib/osspriteop.h" -#include "netsurf/desktop/gui.h" - -struct toolbar; - -struct theme_entry { - char *name; /**< theme name */ - char *author; /**< theme author */ - osspriteop_area *sprite_area; /**< sprite area for theme */ - int throbber_width; /**< width of the throbber */ - int throbber_height; /**< height of the throbber */ - int throbber_frames; /**< frames of animation for the throbber */ - int browser_background; /**< background colour of browser toolbar */ - int hotlist_background; /**< background colour of hotlist toolbar */ - int status_background; /**< background colour of status window */ - int status_foreground; /**< colour of status window text */ - bool default_settings; /**< no theme was loaded, defaults used */ - struct theme_entry *next; /**< next entry in theme list */ +typedef enum { + THEME_BROWSER_TOOLBAR, + THEME_HOTLIST_TOOLBAR +} toolbar_type; + + +struct toolbar_icon { + int icon_number; /**< wimp icon number */ + bool display; /**< whether to display the icon */ + int width; /**< icon width */ + int height; /**< icon height */ + char name[12]; /**< icon name */ + char validation[40]; /**< validation string */ + struct toolbar_icon *next; /**< next toolbar icon, or NULL for no more */ +}; + +struct toolbar { + int status_width; /**< status width percentage * 100 */ + bool display_buttons; /**< display standard buttons */ + bool display_url; /**< display URL bar (if applicable) */ + bool display_throbber; /**< display throbber (if applicable) */ + bool display_status; /**< display status bar (if applicable) */ + int status_current; /**< the size of the status window in OS units */ + int toolbar_current; /**< the size of the toolbar window in OS units */ + int height; /**< vertical extent of the toolbar (read only) */ + wimp_w toolbar_handle; /**< toolbar window handle */ + wimp_w status_handle; /**< status window handle (if applicable) */ + wimp_w parent_handle; /**< parent window handle (read only) */ + bool reformat_buttons; /**< buttons need reformatting */ + char *url_buffer; /**< buffer for status text (read only) */ + char *throbber_buffer; /**< buffer for status text (read only) */ + char *status_buffer; /**< buffer for status text (read only) */ + struct toolbar_icon *icon; /**< first toolbar icon (read only) */ + struct theme *theme; /**< themem or NULL for no theme (read only) */ + toolbar_type type; /**< toolbar type (read only) */ +}; + + +struct theme { + char *details; /**< theme details */ + char *author; /**< theme author */ + osspriteop_area *sprite_area; /**< sprite area for theme */ + bool throbber_right; /**< throbber is on the right (left otherwise) */ + int throbber_width; /**< width of the throbber */ + int throbber_height; /**< height of the throbber */ + int throbber_frames; /**< frames of animation for the throbber */ + int browser_background; /**< background colour of browser toolbar */ + int hotlist_background; /**< background colour of hotlist toolbar */ + int status_background; /**< background colour of status window */ + int status_foreground; /**< colour of status window text */ + int users; /**< number of users for the theme */ +}; +struct theme_descriptor { + char *filename; /**< theme filename */ + struct theme *theme; /**< corresponding theme (must be opened) */ + struct theme_descriptor *previous; /**< previous descriptor in the list */ + struct theme_descriptor *next; /**< next descriptor in the list */ }; -void ro_theme_apply(struct theme_entry *theme); -struct theme_entry *ro_theme_load(char *pathname); -void ro_theme_create_browser_toolbar(struct gui_window *g); -void ro_theme_create_hotlist_toolbar(void); -int ro_theme_update_toolbar(struct toolbar *toolbar, wimp_w window); -int ro_theme_resize_toolbar(struct toolbar *toolbar, wimp_w window); -struct theme_entry *ro_theme_list(unsigned int *entries); -void ro_theme_free(struct theme_entry *theme); +void ro_gui_theme_initialise(void); +void ro_gui_theme_finalise(void); +struct theme_descriptor *ro_gui_theme_find(const char *filename); +struct theme_descriptor *ro_gui_theme_get_available(void); + +bool ro_gui_theme_open(struct theme_descriptor *descriptor, bool list); +bool ro_gui_theme_apply(struct theme_descriptor *descriptor); +void ro_gui_theme_close(struct theme_descriptor *descriptor, bool list); + +struct toolbar *ro_gui_theme_create_toolbar(struct theme_descriptor *descriptor, toolbar_type type); +bool ro_gui_theme_update_toolbar(struct theme_descriptor *descriptor, struct toolbar *toolbar); +bool ro_gui_theme_attach_toolbar(struct toolbar *toolbar, wimp_w parent); +void ro_gui_theme_resize_toolbar_status(struct toolbar *toolbar); +bool ro_gui_theme_process_toolbar(struct toolbar *toolbar, int width); +void ro_gui_theme_destroy_toolbar(struct toolbar *toolbar); + #endif diff --git a/riscos/wimp.c b/riscos/wimp.c index 4c8981ac5..b178b848d 100644 --- a/riscos/wimp.c +++ b/riscos/wimp.c @@ -39,6 +39,7 @@ int ro_get_hscroll_height(wimp_w w) { /* Read the hscroll height */ + if (!w) w = dialog_debug; furniture_sizes.w = w; furniture_sizes.border_widths.y0 = 38; xwimpextend_get_furniture_sizes(&furniture_sizes); @@ -66,6 +67,7 @@ int ro_get_vscroll_width(wimp_w w) { /* Read the hscroll height */ + if (!w) w = dialog_debug; furniture_sizes.w = w; furniture_sizes.border_widths.x1 = 38; xwimpextend_get_furniture_sizes(&furniture_sizes); @@ -214,7 +216,8 @@ void ro_gui_set_icon_integer(wimp_w w, wimp_i i, int value) { * \param i icon handle * \param state selected state */ -#define ro_gui_set_icon_selected_state(w, i, state) xwimp_set_icon_state(w, i, (state ? wimp_ICON_SELECTED : 0), wimp_ICON_SELECTED) +#define ro_gui_set_icon_selected_state(w, i, state) \ + xwimp_set_icon_state(w, i, (state ? wimp_ICON_SELECTED : 0), wimp_ICON_SELECTED) /** @@ -239,7 +242,8 @@ bool ro_gui_get_icon_selected_state(wimp_w w, wimp_i i) { * \param i icon handle * \param state selected state */ -#define ro_gui_set_icon_shaded_state(w, i, state) xwimp_set_icon_state(w, i, (state ? wimp_ICON_SHADED : 0), wimp_ICON_SHADED) +#define ro_gui_set_icon_shaded_state(w, i, state) \ + xwimp_set_icon_state(w, i, (state ? wimp_ICON_SHADED : 0), wimp_ICON_SHADED) /** @@ -331,7 +335,13 @@ void ro_gui_set_caret_first(wimp_w w) { button = (state.icon.flags >> wimp_ICON_BUTTON_TYPE_SHIFT) & 0xf; if ((button == wimp_BUTTON_WRITE_CLICK_DRAG) || (button == wimp_BUTTON_WRITABLE)) { - xwimp_set_caret_position(w, icon, 0, 0, -1, strlen(state.icon.data.indirected_text.text)); + error = xwimp_set_caret_position(w, icon, 0, 0, -1, + strlen(state.icon.data.indirected_text.text)); + if (error) { + LOG(("xwimp_set_caret_position: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + } return; } } @@ -475,7 +485,7 @@ bool ro_gui_wimp_sprite_exists(const char *sprite) * * \param parent parent window * \param pane pane to open in parent window - * \param offset offset of top-left of pane from top-left of parent + * \param offset inset of pane from parent */ void ro_gui_open_pane(wimp_w parent, wimp_w pane, int offset) @@ -493,6 +503,8 @@ void ro_gui_open_pane(wimp_w parent, wimp_w pane, int offset) } state.w = pane; state.visible.x0 += offset; + state.visible.x1 -= offset; + state.visible.y0 += offset; state.visible.y1 -= offset; state.xscroll = 0; state.yscroll = 0; @@ -503,7 +515,7 @@ void ro_gui_open_pane(wimp_w parent, wimp_w pane, int offset) wimp_CHILD_LINKS_PARENT_VISIBLE_TOP_OR_RIGHT << wimp_CHILD_YORIGIN_SHIFT | wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT - << wimp_CHILD_LS_EDGE_SHIFT | + << wimp_CHILD_LS_EDGE_SHIFT | wimp_CHILD_LINKS_PARENT_VISIBLE_TOP_OR_RIGHT << wimp_CHILD_BS_EDGE_SHIFT | wimp_CHILD_LINKS_PARENT_VISIBLE_TOP_OR_RIGHT diff --git a/riscos/wimp.h b/riscos/wimp.h index d26fccdfe..53848064d 100644 --- a/riscos/wimp.h +++ b/riscos/wimp.h @@ -49,4 +49,8 @@ osspriteop_area *ro_gui_load_sprite_file(const char *pathname); bool ro_gui_wimp_sprite_exists(const char *sprite); void ro_gui_open_pane(wimp_w parent, wimp_w pane, int offset); + +wimp_w ro_gui_set_window_background_colour(wimp_w window, wimp_colour background); +void ro_gui_set_icon_colours(wimp_w window, wimp_i icon, + wimp_colour foreground, wimp_colour background); #endif diff --git a/riscos/window.c b/riscos/window.c index aec6bd8da..f6dce705d 100644 --- a/riscos/window.c +++ b/riscos/window.c @@ -30,7 +30,6 @@ #include "netsurf/riscos/options.h" #include "netsurf/riscos/theme.h" #include "netsurf/riscos/thumbnail.h" -#include "netsurf/riscos/toolbar.h" #include "netsurf/riscos/wimp.h" #include "netsurf/utils/log.h" #include "netsurf/utils/url.h" @@ -79,11 +78,8 @@ struct gui_window *gui_create_browser_window(struct browser_window *bw, g->reformat_pending = false; g->old_width = 0; g->old_height = 0; - strcpy(g->status, ""); strcpy(g->title, "NetSurf"); - strcpy(g->url, ""); g->throbber = 0; - strcpy(g->throb_buf, "throbber0"); g->throbtime = 0; /* Set the window position @@ -202,6 +198,10 @@ struct gui_window *gui_create_browser_window(struct browser_window *bw, window.title_data.indirected_text.validation = (char *) -1; window.title_data.indirected_text.size = 255; window.icon_count = 0; + if (open_centred) { + scroll_width = ro_get_vscroll_width(g->window); + window.visible.x0 -= scroll_width; + } error = xwimp_create_window(&window, &g->window); if (error) { @@ -212,8 +212,6 @@ struct gui_window *gui_create_browser_window(struct browser_window *bw, return 0; } - ro_theme_create_browser_toolbar(g); - g->prev = 0; g->next = window_list; if (window_list) @@ -221,10 +219,16 @@ struct gui_window *gui_create_browser_window(struct browser_window *bw, window_list = g; window_count++; + /* Add in a toolbar + */ + g->toolbar = ro_gui_theme_create_toolbar(NULL, THEME_BROWSER_TOOLBAR); + ro_gui_theme_attach_toolbar(g->toolbar, g->window); + /* Set the window options */ bw->window = g; ro_gui_window_clone_options(bw, clone); + ro_gui_prepare_navigate(g); /* Open the window */ @@ -237,22 +241,15 @@ struct gui_window *gui_create_browser_window(struct browser_window *bw, return g; } - /* Only fix the centralisation if we've opened the window centred - */ - if (open_centred) { - scroll_width = ro_get_vscroll_width(g->window); - state.visible.x0 -= scroll_width; - } - /* Open the window at the top of the stack */ state.next = wimp_TOP; ro_gui_window_open(g, (wimp_open*)&state); - ro_gui_prepare_navigate(g); + /* Set the caret position to the URL bar */ - if (g->toolbar && g->toolbar->url_bar) + if (g->toolbar && g->toolbar->display_url) error = xwimp_set_caret_position( g->toolbar->toolbar_handle, ICON_TOOLBAR_URL, -1, -1, -1, 0); @@ -291,7 +288,7 @@ void gui_window_destroy(struct gui_window *g) if (g->next) g->next->prev = g->prev; - ro_toolbar_destroy(g->toolbar); + ro_gui_theme_destroy_toolbar(g->toolbar); /* delete window */ error = xwimp_delete_window(g->window); @@ -715,9 +712,8 @@ void gui_window_set_extent(struct gui_window *g, int width, int height) void gui_window_set_status(struct gui_window *g, const char *text) { - if (!g->toolbar) + if ((!g->toolbar) || (!g->toolbar->status_handle)) return; - ro_gui_set_icon_string(g->toolbar->status_handle, ICON_STATUS_TEXT, text); } @@ -734,6 +730,7 @@ void gui_window_set_url(struct gui_window *g, const char *url) { wimp_caret caret; os_error *error; + char *toolbar_url; if (!g->toolbar) return; @@ -754,8 +751,10 @@ void gui_window_set_url(struct gui_window *g, const char *url) caret.i == ICON_TOOLBAR_URL)) return; + toolbar_url = ro_gui_get_icon_string(g->toolbar->toolbar_handle, + ICON_TOOLBAR_URL); error = xwimp_set_caret_position(g->toolbar->toolbar_handle, - ICON_TOOLBAR_URL, 0, 0, -1, (int) strlen(g->url)); + ICON_TOOLBAR_URL, 0, 0, -1, (int)strlen(toolbar_url)); if (error) { LOG(("xwimp_set_caret_position: 0x%x: %s", error->errnum, error->errmess)); @@ -764,6 +763,65 @@ void gui_window_set_url(struct gui_window *g, const char *url) } +/** + * Forces all windows to be set to the current theme + * + * /param g the gui window to update + */ +void ro_gui_window_update_theme(void) { + int height; + struct gui_window *g; + for (g = window_list; g; g = g->next) { + if (g->toolbar) { + height = g->toolbar->height; + if (!ro_gui_theme_update_toolbar(NULL, g->toolbar)) { + ro_gui_theme_destroy_toolbar(g->toolbar); + g->toolbar = NULL; + if (height != 0) + ro_gui_window_update_dimensions(g, height); + } else { + if (height != g->toolbar->height) + ro_gui_window_update_dimensions(g, height - + g->toolbar->height); + } + ro_gui_prepare_navigate(g); + } + } + if (hotlist_toolbar) { + if (!ro_gui_theme_update_toolbar(NULL, hotlist_toolbar)) { + ro_gui_theme_destroy_toolbar(hotlist_toolbar); + hotlist_toolbar = NULL; + } + xwimp_force_redraw(hotlist_window, 0, -16384, 16384, 16384); + } + +} + + +/** + * Forces the windows extent to be updated + * + * /param g the gui window to update + * /param yscroll an amount to scroll the vertical scroll bar by + */ +void ro_gui_window_update_dimensions(struct gui_window *g, int yscroll) { + os_error *error; + wimp_window_state state; + if (!g) return; + state.w = g->window; + 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; + } + state.yscroll -= yscroll; + g->old_height = -1; + ro_gui_window_open(g, (wimp_open *)&state); +/* gui_window_redraw_window(g); */ +} + /** * Open a window using the given wimp_open, handling toolbars and resizing. */ @@ -866,7 +924,7 @@ void ro_gui_window_open(struct gui_window *g, wimp_open *open) } if (g->toolbar) - ro_theme_resize_toolbar(g->toolbar, g->window); + ro_gui_theme_process_toolbar(g->toolbar, -1); } @@ -878,21 +936,21 @@ void ro_gui_throb(void) { os_t t; struct gui_window *g; + char throb_buf[12]; xos_read_monotonic_time(&t); for (g = window_list; g; g = g->next) { - if (!g->bw->throbbing || !g->toolbar || (g->toolbar->throbber_frames == 0)) - continue; - if (t < g->throbtime + 10) + if (!g->bw->throbbing || !g->toolbar || !g->toolbar->display_throbber || + !g->toolbar->theme || (t < g->throbtime + 10)) continue; g->throbtime = t; g->throbber++; - if (g->toolbar->throbber_frames < g->throbber) - g->throbber = 0; - sprintf(g->throb_buf, "throbber%i", g->throbber); - ro_gui_redraw_icon(g->toolbar->toolbar_handle, - ICON_TOOLBAR_THROBBER); + if (g->toolbar->theme->throbber_frames < g->throbber) + g->throbber = 1; + sprintf(throb_buf, "throbber%i", g->throbber); + ro_gui_set_icon_string(g->toolbar->toolbar_handle, + ICON_TOOLBAR_THROBBER, throb_buf); } } @@ -1174,10 +1232,14 @@ void gui_window_start_throbber(struct gui_window *g) void gui_window_stop_throbber(struct gui_window *g) { + char throb_buf[12]; ro_gui_prepare_navigate(g); g->throbber = 0; - strcpy(g->throb_buf, "throbber0"); - ro_gui_redraw_icon(g->toolbar->toolbar_handle, ICON_TOOLBAR_THROBBER); + if (g->toolbar) { + strcpy(throb_buf, "throbber0"); + ro_gui_set_icon_string(g->toolbar->toolbar_handle, + ICON_TOOLBAR_THROBBER, throb_buf); + } } @@ -1240,6 +1302,7 @@ bool ro_gui_window_keypress(struct gui_window *g, int key, bool toolbar) wimp_window_state state; int y; char *url; + char *toolbar_url; os_error *error; wimp_pointer pointer; url_func_result res; @@ -1369,7 +1432,9 @@ bool ro_gui_window_keypress(struct gui_window *g, int key, bool toolbar) case wimp_KEY_RETURN: if (!toolbar) break; - res = url_normalize(g->url, &url); + toolbar_url = ro_gui_get_icon_string(g->toolbar->toolbar_handle, + ICON_TOOLBAR_URL); + res = url_normalize(toolbar_url, &url); if (res == URL_FUNC_OK) { gui_window_set_url(g, url); browser_window_go(g->bw, url); @@ -1383,7 +1448,8 @@ bool ro_gui_window_keypress(struct gui_window *g, int key, bool toolbar) case 14: /* CTRL+N */ current_gui = g; - browser_window_create(g->url, g->bw); + browser_window_create(current_gui->bw->current_content->url, + current_gui->bw); return true; case 18: /* CTRL+R */ browser_window_reload(g->bw, false); @@ -1680,18 +1746,19 @@ void ro_gui_window_clone_options(struct browser_window *new_bw, if (new_gui->toolbar) { if ((old_gui) && (old_gui->toolbar)) { new_gui->toolbar->status_width = old_gui->toolbar->status_width; - new_gui->toolbar->status_window = old_gui->toolbar->status_window; - new_gui->toolbar->standard_buttons = old_gui->toolbar->standard_buttons; - new_gui->toolbar->url_bar = old_gui->toolbar->url_bar; - new_gui->toolbar->throbber = old_gui->toolbar->throbber; + new_gui->toolbar->display_status = old_gui->toolbar->display_status; + new_gui->toolbar->display_buttons = old_gui->toolbar->display_buttons; + new_gui->toolbar->display_url = old_gui->toolbar->display_url; + new_gui->toolbar->display_throbber = old_gui->toolbar->display_throbber; } else { new_gui->toolbar->status_width = option_toolbar_status_width; - new_gui->toolbar->status_window = option_toolbar_show_status; - new_gui->toolbar->standard_buttons = option_toolbar_show_buttons; - new_gui->toolbar->url_bar = option_toolbar_show_address; - new_gui->toolbar->throbber = option_toolbar_show_throbber; + new_gui->toolbar->display_status = option_toolbar_show_status; + new_gui->toolbar->display_buttons = option_toolbar_show_buttons; + new_gui->toolbar->display_url = option_toolbar_show_address; + new_gui->toolbar->display_throbber = option_toolbar_show_throbber; } - ro_theme_update_toolbar(new_gui->toolbar, new_gui->window); + new_gui->toolbar->reformat_buttons = true; + ro_gui_theme_process_toolbar(new_gui->toolbar, -1); } } @@ -1726,10 +1793,10 @@ void ro_gui_window_default_options(struct browser_window *bw) { */ if (gui->toolbar) { option_toolbar_status_width = gui->toolbar->status_width; - option_toolbar_show_status = gui->toolbar->status_window; - option_toolbar_show_buttons = gui->toolbar->standard_buttons; - option_toolbar_show_address = gui->toolbar->url_bar; - option_toolbar_show_throbber = gui->toolbar->throbber; + option_toolbar_show_status = gui->toolbar->display_status; + option_toolbar_show_buttons = gui->toolbar->display_buttons; + option_toolbar_show_address = gui->toolbar->display_url; + option_toolbar_show_throbber = gui->toolbar->display_throbber; } } -- cgit v1.2.3