From 422df9008913857667ff20bf3ec295c1839cbc45 Mon Sep 17 00:00:00 2001 From: Richard Wilson Date: Sun, 23 Jan 2005 16:09:05 +0000 Subject: [project @ 2005-01-23 16:09:05 by rjw] Further work on theme installing svn path=/import/netsurf/; revision=1463 --- !NetSurf/Resources/Theme,ffd | Bin 0 -> 19681 bytes !NetSurf/Resources/de/Messages | 2 + !NetSurf/Resources/en/Messages | 2 + !NetSurf/Resources/fr/Messages | 2 + content/fetch.c | 4 +- riscos/dialog.c | 7 +- riscos/gui.c | 22 +-- riscos/gui.h | 4 +- riscos/theme.c | 316 +++++++++++++++++++++-------------------- riscos/theme.h | 20 +++ riscos/theme_install.c | 140 ++++++++++++++++-- riscos/wimp.c | 52 ++++++- riscos/wimp.h | 2 + riscos/window.c | 12 +- 14 files changed, 403 insertions(+), 182 deletions(-) create mode 100644 !NetSurf/Resources/Theme,ffd diff --git a/!NetSurf/Resources/Theme,ffd b/!NetSurf/Resources/Theme,ffd new file mode 100644 index 000000000..f49d6f8c4 Binary files /dev/null and b/!NetSurf/Resources/Theme,ffd differ diff --git a/!NetSurf/Resources/de/Messages b/!NetSurf/Resources/de/Messages index d50ef9412..ff83b18d7 100644 --- a/!NetSurf/Resources/de/Messages +++ b/!NetSurf/Resources/de/Messages @@ -266,6 +266,8 @@ EncodingUnk:Unknown ThemeInstActive:A theme is currently being downloaded or installed. Please wait for it to finish or cancel it before installing more themes. ThemeInstDown:Please wait for the theme to download. +ThemeInvalid:The downloaded theme is invalid or requires a newer version of NetSurf. +ThemeInstall:Would you like to install the theme '%s' by %s? # Interactive help HelpToolbar0:Schaltet zurück auf die zuvor dargestellte Seite.|MDer Inhalt wird dabei nicht aktualisiert. diff --git a/!NetSurf/Resources/en/Messages b/!NetSurf/Resources/en/Messages index 60e1c4257..e6c51d413 100644 --- a/!NetSurf/Resources/en/Messages +++ b/!NetSurf/Resources/en/Messages @@ -266,6 +266,8 @@ EncodingUnk:Unknown ThemeInstActive:A theme is currently being downloaded or installed. Please wait for it to finish or cancel it before installing more themes. ThemeInstDown:Please wait for the theme to download. +ThemeInvalid:The downloaded theme is invalid or requires a newer version of NetSurf. +ThemeInstall:Would you like to install the theme '%s' by %s? # Interactive help HelpToolbar0:\Tback button.|M\Straverse back one page in the history tree.|MDoes not resubmit form information. diff --git a/!NetSurf/Resources/fr/Messages b/!NetSurf/Resources/fr/Messages index c426d645e..8510c5ea3 100644 --- a/!NetSurf/Resources/fr/Messages +++ b/!NetSurf/Resources/fr/Messages @@ -266,6 +266,8 @@ EncodingUnk:Unknown ThemeInstActive:A theme is currently being downloaded or installed. Please wait for it to finish or cancel it before installing more themes. ThemeInstDown:Please wait for the theme to download. +ThemeInvalid:The downloaded theme is invalid or requires a newer version of NetSurf. +ThemeInstall:Would you like to install the theme '%s' by %s? # Interactive help HelpToolbar0:\Tle bouton de retour.|M\Srevenir d'une page en arrière dans l'historique.|MNe renvoie pas l'information de formulaire. diff --git a/content/fetch.c b/content/fetch.c index e6b998a88..cbd64a0e8 100644 --- a/content/fetch.c +++ b/content/fetch.c @@ -38,6 +38,9 @@ #ifdef WITH_POST #include "netsurf/render/form.h" #endif +#ifdef riscos +#include "netsurf/riscos/gui.h" +#endif #include "netsurf/utils/log.h" #include "netsurf/utils/messages.h" #include "netsurf/utils/url.h" @@ -99,7 +102,6 @@ static struct curl_httppost *fetch_post_convert(struct form_successful_control * #ifdef riscos static char * ca_bundle; /**< SSL certificate bundle filename. */ -extern const char * const NETSURF_DIR; #endif diff --git a/riscos/dialog.c b/riscos/dialog.c index f55cb7b55..c6cb54fc7 100644 --- a/riscos/dialog.c +++ b/riscos/dialog.c @@ -139,6 +139,7 @@ void ro_gui_dialog_init(void) dialog_print = ro_gui_dialog_create("print"); dialog_config_font = ro_gui_dialog_create("config_font"); dialog_config_image = ro_gui_dialog_create("config_img"); + dialog_theme_install = ro_gui_dialog_create("theme_inst"); } @@ -455,6 +456,8 @@ void ro_gui_dialog_click(wimp_pointer *pointer) #endif else if (pointer->w == dialog_config_font) ro_gui_dialog_click_config_font(pointer); + else if (pointer->w == dialog_theme_install) + ro_gui_theme_install_click(pointer); } /** @@ -1004,7 +1007,7 @@ void ro_gui_dialog_click_config_th(wimp_pointer *pointer) { switch (pointer->i) { case ICON_CONFIG_TH_MANAGE: - os_cli("Filer_OpenDir " THEMES_DIR); + os_cli("Filer_OpenDir Choices:WWW.NetSurf.Themes"); break; case ICON_CONFIG_TH_GET: browser_window_create( @@ -1419,6 +1422,8 @@ void ro_gui_dialog_load_themes(void) { if (link->next) extent.y0 -= 16; if (extent.y0 > min_extent) extent.y0 = min_extent; xwimp_set_extent(dialog_config_th_pane, &extent); + ro_gui_set_icon_button_type(link->toolbar->toolbar_handle, + ICON_TOOLBAR_URL, wimp_BUTTON_NEVER); /* Create the descriptor icons and separator line */ diff --git a/riscos/gui.c b/riscos/gui.c index f7e8fa12c..9545ba458 100644 --- a/riscos/gui.c +++ b/riscos/gui.c @@ -68,7 +68,7 @@ int __feature_imagefs_is_file = 1; /**< For UnixLib. */ int __riscosify_control = __RISCOSIFY_NO_SUFFIX | __RISCOSIFY_NO_REVERSE_SUFFIX; -char *NETSURF_DIR; +const char * NETSURF_DIR; char *default_stylesheet_url; char *adblock_stylesheet_url; @@ -175,6 +175,7 @@ static char *ro_path_to_url(const char *path); void gui_init(int argc, char** argv) { + char theme_path[256]; char path[40]; os_error *error; int length; @@ -232,13 +233,6 @@ void gui_init(int argc, char** argv) if (getenv("NetSurf$Start_URI_Handler")) xwimp_start_task("Desktop", 0); - /* Load our chosen theme - */ - ro_gui_theme_initialise(); - descriptor = ro_gui_theme_find(option_theme); - if (!descriptor) descriptor = ro_gui_theme_find("NetSurf"); - ro_gui_theme_apply(descriptor); - /* Open the templates */ if ((length = snprintf(path, sizeof(path), @@ -258,12 +252,22 @@ void gui_init(int argc, char** argv) ro_gui_401login_init(); #endif ro_gui_history_init(); - ro_gui_theme_install_init(); wimp_close_template(); ro_gui_sprites_init(); ro_gui_tree_initialise(); /* must be done after sprite loading */ ro_gui_hotlist_initialise(); + /* Load our chosen theme + */ + ro_gui_theme_initialise(); + descriptor = ro_gui_theme_find(option_theme); + if (!descriptor) { + snprintf(theme_path, 256, "%s.Resources.Theme", NETSURF_DIR); + theme_path[255] = '\0'; + descriptor = ro_gui_theme_find(theme_path); + } + ro_gui_theme_apply(descriptor); + /* We don't create an Iconbar icon on NCOS */ #ifndef ncos ro_gui_icon_bar_create(); diff --git a/riscos/gui.h b/riscos/gui.h index 0d25890bc..8d78b411f 100644 --- a/riscos/gui.h +++ b/riscos/gui.h @@ -21,7 +21,7 @@ #include "netsurf/desktop/options.h" #include "netsurf/desktop/tree.h" -#define THEMES_DIR ".Themes" +extern const char * NETSURF_DIR; struct toolbar; struct plotter_table; @@ -252,7 +252,7 @@ extern int ro_plot_origin_y; void ro_plot_set_scale(float scale); /* in theme_install.c */ -void ro_gui_theme_install_init(void); +void ro_gui_theme_install_click(wimp_pointer *pointer); /* toolbar types */ #define TOOLBAR_BROWSER 0 diff --git a/riscos/theme.c b/riscos/theme.c index 648460f10..2d7750e82 100644 --- a/riscos/theme.c +++ b/riscos/theme.c @@ -2,7 +2,7 @@ * 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 2004 Richard Wilson + * Copyright 2004, 2005 Richard Wilson */ /** \file @@ -30,32 +30,14 @@ #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 -struct theme_file_header { - unsigned int magic_value; - unsigned int parser_version; - char name[32]; - char author[64]; - char browser_bg; - char hotlist_bg; - char status_bg; - char status_fg; - char throbber_left; - char future_expansion_1; - char future_expansion_2; - char future_expansion_3; - unsigned int compressed_sprite_size; - unsigned int decompressed_sprite_size; -}; - - static struct theme_descriptor *theme_current = NULL; static struct theme_descriptor *theme_descriptors = NULL; +static void ro_gui_theme_get_available_in_dir(const char *directory); 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); @@ -104,6 +86,9 @@ static char theme_separator_name[] = "separator\0"; void ro_gui_theme_initialise(void) { /* Get an initial theme list */ + xosfile_create_dir(".WWW", 0); + xosfile_create_dir(".WWW.NetSurf", 0); + xosfile_create_dir(".WWW.NetSurf.Themes", 0); theme_descriptors = ro_gui_theme_get_available(); } @@ -153,10 +138,58 @@ struct theme_descriptor *ro_gui_theme_find(const char *filename) { * \return the requested theme_descriptor, or NULL if not found */ struct theme_descriptor *ro_gui_theme_get_available(void) { - struct theme_file_header file_header; struct theme_descriptor *current; struct theme_descriptor *test; char pathname[256]; + + /* Close any descriptors we've got so far + */ + ro_gui_theme_free(theme_descriptors, true); + + /* Open a variety of directories + */ + snprintf(pathname, 256, "%s.Resources", NETSURF_DIR); + pathname[255] = '\0'; + ro_gui_theme_get_available_in_dir(pathname); + ro_gui_theme_get_available_in_dir("Choices:WWW.NetSurf.Themes"); + + /* Sort alphabetically in a very rubbish way + */ + if ((theme_descriptors) && (theme_descriptors->next)) { + current = theme_descriptors; + while ((test = current->next)) { + if (strcmp(current->name, test->name) > 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; + + current = test->previous; + if (!current) current = test; + } else { + current = current->next; + } + } + while (theme_descriptors->previous) + theme_descriptors = theme_descriptors->previous; + } + return theme_descriptors; +} + + +/** + * Adds the themes in a directory to the global cache. + * + * \param directory the directory to scan + */ +static void ro_gui_theme_get_available_in_dir(const char *directory) { + struct theme_file_header file_header; + struct theme_descriptor *current; + char pathname[256]; int context = 0; int read_count; osgbpb_INFO(100) info; @@ -164,21 +197,19 @@ struct theme_descriptor *ro_gui_theme_get_available(void) { os_fw file_handle; os_error *error; - /* Close any descriptors we've got so far - */ - ro_gui_theme_free(theme_descriptors, true); - /* Create a new set */ while (context != -1) { /* Get the next entry */ - error = xosgbpb_dir_entries_info(THEMES_DIR, + error = xosgbpb_dir_entries_info(directory, (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)); + if (error->errnum == 0xd6) /* no such dir */ + return; warn_user("MiscError", error->errmess); break; } @@ -188,15 +219,15 @@ struct theme_descriptor *ro_gui_theme_get_available(void) { if (read_count == 0) continue; - /* Only process files + /* Get our full filename */ - if ((info.obj_type == fileswitch_IS_FILE) && (!ro_gui_theme_find(info.name))) { + snprintf(pathname, sizeof pathname, "%s.%s", + directory, info.name); + pathname[sizeof pathname - 1] = 0; - /* Get our full filename - */ - snprintf(pathname, sizeof pathname, "%s.%s", - THEMES_DIR, info.name); - pathname[sizeof pathname - 1] = 0; + /* Only process files + */ + if ((info.obj_type == fileswitch_IS_FILE) && (!ro_gui_theme_find(pathname))) { /* Get the header */ @@ -222,12 +253,6 @@ struct theme_descriptor *ro_gui_theme_get_available(void) { if (output_left > 0) continue; /* should try to read more? */ - /* Check we are a valid theme - */ - if ((file_header.magic_value != 0x4d54534e) || - (file_header.parser_version > 1)) - continue; - /* Create a new theme descriptor */ current = (struct theme_descriptor *)calloc(1, @@ -235,27 +260,24 @@ struct theme_descriptor *ro_gui_theme_get_available(void) { if (!current) { LOG(("calloc failed")); warn_user("NoMemory", 0); - return theme_descriptors; + return; } - current->filename = malloc(strlen(info.name) + 1); + + if (!ro_gui_theme_read_file_header(current, &file_header)) { + free(current); + continue; + } + + current->filename = malloc(strlen(pathname) + 1); if (!current->filename) { LOG(("malloc failed")); warn_user("NoMemory", 0); free(current); - return theme_descriptors; + return; } - strcpy(current->filename, info.name); - strcpy(current->name, file_header.name); - strcpy(current->author, file_header.author); - current->browser_background = file_header.browser_bg; - current->hotlist_background = file_header.hotlist_bg; - current->status_background = file_header.status_bg; - current->status_foreground = file_header.status_fg; - current->throbber_right = (file_header.throbber_left == 0x00); - current->decompressed_size = file_header.decompressed_sprite_size; - current->compressed_size = file_header.compressed_sprite_size; - - /* Link in our new descriptor alphabetically + strcpy(current->filename, pathname); + + /* Link in our new descriptor */ if (theme_descriptors) { current->next = theme_descriptors; @@ -264,32 +286,40 @@ struct theme_descriptor *ro_gui_theme_get_available(void) { theme_descriptors = current; } } +} - /* Sort alphabetically in a very rubbish way - */ - if (theme_descriptors->next) { - current = theme_descriptors; - while ((test = current->next)) { - if (strcmp(current->name, test->name) > 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; - current = test->previous; - if (!current) current = test; - } else { - current = current->next; - } - } - while (theme_descriptors->previous) - theme_descriptors = theme_descriptors->previous; +/** + * Fills in the basic details for a descriptor from a file header. + * The filename string is not set. + * + * \param descriptor the descriptor to set up + * \param file_header the header to read from + * \return false for a badly formed theme, true otherwise + */ +bool ro_gui_theme_read_file_header(struct theme_descriptor *descriptor, + struct theme_file_header *file_header) { + + if ((file_header->magic_value != 0x4d54534e) || + (file_header->parser_version > 2)) + return false; + + strcpy(descriptor->name, file_header->name); + strcpy(descriptor->author, file_header->author); + descriptor->browser_background = file_header->browser_bg; + descriptor->hotlist_background = file_header->hotlist_bg; + descriptor->status_background = file_header->status_bg; + descriptor->status_foreground = file_header->status_fg; + descriptor->decompressed_size = file_header->decompressed_sprite_size; + descriptor->compressed_size = file_header->compressed_sprite_size; + if (file_header->parser_version >= 2) { + descriptor->throbber_right = !(file_header->theme_flags & (1 << 0)); + descriptor->throbber_redraw = file_header->theme_flags & (1 << 1); + } else { + descriptor->throbber_right = (file_header->theme_flags == 0x00); + descriptor->throbber_redraw = true; } - return theme_descriptors; + return true; } @@ -306,17 +336,17 @@ bool ro_gui_theme_open(struct theme_descriptor *descriptor, bool list) { os_coord dimensions; os_mode mode; os_error *error; - char pathname[256]; + char sprite_name[16]; bool result = true; int i, n; int workspace_size, file_size; char *raw_data, *workspace; osspriteop_area *decompressed; - + /* If we are freeing the whole of the list then we need to start at the first descriptor. */ - if (list) { + if (list && descriptor) { while (descriptor->previous) descriptor = descriptor->previous; } @@ -338,17 +368,11 @@ bool ro_gui_theme_open(struct theme_descriptor *descriptor, bool list) { } descriptor->theme->users = 1; - /* Get our full filename - */ - snprintf(pathname, sizeof pathname, "%s.%s", - THEMES_DIR, descriptor->filename); - pathname[sizeof pathname - 1] = 0; - /* Load the file. We use a goto to exit from here on in as using a continue leaves us in an infinite loop - it's nasty, and really should be rewritten properly. */ - error = xosfile_read_stamped_no_path(pathname, + error = xosfile_read_stamped_no_path(descriptor->filename, &obj_type, 0, 0, &file_size, 0, 0); if (error) { LOG(("xosfile_read_stamped_no_path: 0x%x: %s", @@ -364,7 +388,7 @@ bool ro_gui_theme_open(struct theme_descriptor *descriptor, bool list) { warn_user("NoMemory", 0); return false; } - error = xosfile_load_stamped_no_path(pathname, (byte *)raw_data, + error = xosfile_load_stamped_no_path(descriptor->filename, (byte *)raw_data, 0, 0, 0, 0, 0); if (error) { free(raw_data); @@ -410,7 +434,7 @@ bool ro_gui_theme_open(struct theme_descriptor *descriptor, bool list) { goto ro_gui_theme_open_continue; } if (status != 0) { - free(decompressed); + free(decompressed); goto ro_gui_theme_open_continue; } descriptor->theme->sprite_area = decompressed; @@ -419,14 +443,14 @@ bool ro_gui_theme_open(struct theme_descriptor *descriptor, bool list) { 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) { + xosspriteop_return_name(osspriteop_USER_AREA, + descriptor->theme->sprite_area, sprite_name, 16, i, 0); + if (strncmp(sprite_name, "throbber", 8) == 0) { /* Get the max sprite width/height */ xosspriteop_read_sprite_info(osspriteop_USER_AREA, descriptor->theme->sprite_area, - (osspriteop_id)pathname, + (osspriteop_id)sprite_name, &dimensions.x, &dimensions.y, (osbool *)0, &mode); ro_convert_pixels_to_os_units(&dimensions, mode); @@ -437,22 +461,21 @@ bool ro_gui_theme_open(struct theme_descriptor *descriptor, bool list) { /* Get the throbber number */ - n = atoi(pathname + 8); + n = atoi(sprite_name + 8); if (descriptor->theme->throbber_frames < n) descriptor->theme->throbber_frames = n; } - } + } } - ro_gui_theme_open_continue: + /* Loop or return depending on whether the entire list is to be processed. */ - if (list) { + if (list && descriptor) descriptor = descriptor->next; - } else { + else return result; - } } return result; } @@ -569,16 +592,14 @@ void ro_gui_theme_redraw(struct toolbar *toolbar, wimp_draw *redraw) { perform_redraw &= toolbar->display_buttons; while (more) { - if (perform_redraw) { - for (icon = toolbar->icon; icon; icon = icon->next) { - if ((icon->icon_number == -1) && (icon->display)) { + if (perform_redraw) { + for (icon = toolbar->icon; icon; icon = icon->next) { + if ((icon->icon_number == -1) && (icon->display)) { separator_icon.extent.x0 = icon->x; separator_icon.extent.x1 = icon->x + icon->width; wimp_plot_icon(&separator_icon); } } - - } more = wimp_get_rectangle(redraw); } @@ -602,22 +623,17 @@ void ro_gui_theme_free(struct theme_descriptor *descriptor, bool list) { /* 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; - } + while ((list) && (descriptor->previous)) + descriptor = descriptor->previous; /* 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) @@ -627,20 +643,17 @@ void ro_gui_theme_free(struct theme_descriptor *descriptor, bool list) { */ if (theme_descriptors == descriptor) theme_descriptors = next_descriptor; + /* Release any memory */ free(descriptor->filename); free(descriptor); } - /* Loop or return depending on whether the entire list - is to be processed. - */ - if (list) { + if (list) descriptor = next_descriptor; - } else { + else return; - } } } @@ -741,36 +754,31 @@ bool ro_gui_theme_update_toolbar(struct theme_descriptor *descriptor, struct too os_error *error; osspriteop_area *sprite_area; struct toolbar_icon *toolbar_icon; - int width; + int width, max_icon; if (!toolbar) return false; /* Set the theme and window sprite area */ if (!descriptor) descriptor = theme_current; toolbar->descriptor = descriptor; - if ((toolbar->descriptor) && (toolbar->descriptor->theme)) { + if ((toolbar->descriptor) && (toolbar->descriptor->theme)) sprite_area = toolbar->descriptor->theme->sprite_area; - } else { + else sprite_area = (osspriteop_area *)1; - } theme_toolbar_window.sprite_area = sprite_area; /* Update the icon sizes */ - toolbar_icon = toolbar->icon; - while (toolbar_icon) { + for (toolbar_icon = toolbar->icon; toolbar_icon; toolbar_icon = toolbar_icon->next) ro_gui_theme_update_toolbar_icon(toolbar, toolbar_icon); - toolbar_icon = toolbar_icon->next; - } /* Recreate the toolbar window */ if (toolbar->descriptor) { - if (toolbar->type == THEME_BROWSER_TOOLBAR) { + if (toolbar->type == THEME_BROWSER_TOOLBAR) theme_toolbar_window.work_bg = toolbar->descriptor->browser_background; - } else { + else theme_toolbar_window.work_bg = toolbar->descriptor->hotlist_background; - } } else { theme_toolbar_window.work_bg = wimp_COLOUR_VERY_LIGHT_GREY; } @@ -780,8 +788,12 @@ bool ro_gui_theme_update_toolbar(struct theme_descriptor *descriptor, struct too theme_toolbar_window.ymin = 1; theme_toolbar_window.extent.x1 = 16384; theme_toolbar_window.extent.y1 = 16384; + theme_toolbar_window.sprite_area = sprite_area; if (toolbar->toolbar_handle) { - xwimp_delete_window(toolbar->toolbar_handle); + error = xwimp_delete_window(toolbar->toolbar_handle); + if (error) + LOG(("xwimp_delete_window: 0x%x: %s", + error->errnum, error->errmess)); toolbar->toolbar_handle = NULL; } error = xwimp_create_window(&theme_toolbar_window, &toolbar->toolbar_handle); @@ -793,22 +805,24 @@ bool ro_gui_theme_update_toolbar(struct theme_descriptor *descriptor, struct too } /* Create the basic icons - */ - int max_icon = ICON_TOOLBAR_URL; - if (toolbar->type == THEME_HOTLIST_TOOLBAR) max_icon = ICON_TOOLBAR_HOTLIST_LAST; + */ + if (toolbar->type == THEME_HOTLIST_TOOLBAR) + max_icon = ICON_TOOLBAR_HOTLIST_LAST; + else + max_icon = ICON_TOOLBAR_URL; 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->descriptor) { + if (toolbar->descriptor) new_icon.icon.flags |= (toolbar->descriptor->browser_background << wimp_ICON_BG_COLOUR_SHIFT); - } else { + 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; @@ -876,11 +890,10 @@ bool ro_gui_theme_update_toolbar(struct theme_descriptor *descriptor, struct too xwimp_delete_window(toolbar->status_handle); toolbar->status_handle = NULL; } - if (toolbar->descriptor) { + if (toolbar->descriptor) theme_toolbar_window.work_bg = toolbar->descriptor->status_background; - } else { + else theme_toolbar_window.work_bg = wimp_COLOUR_VERY_LIGHT_GREY; - } theme_toolbar_window.flags &= ~wimp_WINDOW_NO_BOUNDS; theme_toolbar_window.flags |= wimp_WINDOW_AUTO_REDRAW; theme_toolbar_window.xmin = 12; @@ -915,15 +928,14 @@ bool ro_gui_theme_update_toolbar(struct theme_descriptor *descriptor, struct too /* And finally our status display icon */ new_icon.icon.flags = wimp_ICON_TEXT | wimp_ICON_INDIRECTED | wimp_ICON_VCENTRED; - if (toolbar->descriptor) { + if (toolbar->descriptor) new_icon.icon.flags |= (toolbar->descriptor->status_foreground << wimp_ICON_FG_COLOUR_SHIFT) | (toolbar->descriptor->status_background << wimp_ICON_BG_COLOUR_SHIFT); - } else { + 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; @@ -1187,7 +1199,7 @@ bool ro_gui_theme_process_toolbar(struct toolbar *toolbar, int width) { while (toolbar_icon) { if ((toolbar->display_buttons) && (toolbar_icon->display) && (toolbar_icon->width > 0)) { - visible_icon = true; + visible_icon = true; bottom_edge = (toolbar->height - toolbar_icon->height) / 2; toolbar_icon->x = left_edge; @@ -1256,11 +1268,11 @@ bool ro_gui_theme_process_toolbar(struct toolbar *toolbar, int width) { */ toolbar->toolbar_current = width; if (toolbar->reformat_buttons) { - extent.x1 = 16384; - extent.y0 = 0; - extent.y1 = toolbar->height; - xwimp_set_extent(toolbar->toolbar_handle, &extent); - if ((parent) && (old_height != toolbar->height)) { + extent.x1 = 16384; + extent.y0 = 0; + extent.y1 = toolbar->height; + xwimp_set_extent(toolbar->toolbar_handle, &extent); + if ((parent) && (old_height != toolbar->height)) { ro_gui_theme_attach_toolbar(toolbar, parent); } } @@ -1384,7 +1396,7 @@ void ro_gui_theme_destroy_toolbar(struct toolbar *toolbar) { * Adds a toolbar icon to the end of a toolbar * * \param toolbar the toolbar to add the icon to the end of - * \param name the icon name, or NULL for a separator + * \param name the icon name, or NULL for a separator * \param icon_number the RISC OS Wimp icon number for the icon (not used for separators) */ void ro_gui_theme_add_toolbar_icon(struct toolbar *toolbar, const char *name, int icon_number) { @@ -1488,13 +1500,13 @@ void ro_gui_theme_destroy_toolbar_icon(struct toolbar_icon *icon) { * Returns the toolbar icon at a specified position * * \param toolbar the toolbar to examine - * \param x the x co-ordinate to check - * \param y the y co-ordinate to check + * \param x the x co-ordinate to check + * \param y the y co-ordinate to check * \return the toolbar icon at the specified position, or NULL for no icon */ struct toolbar_icon *ro_gui_theme_toolbar_get_icon(struct toolbar *toolbar, int x, int y) { - struct toolbar_icon *icon; - icon = toolbar->icon; + struct toolbar_icon *icon; + icon = toolbar->icon; /* FINISH ME */ return NULL; } diff --git a/riscos/theme.h b/riscos/theme.h index 1f6e90b2e..aa8061a78 100644 --- a/riscos/theme.h +++ b/riscos/theme.h @@ -19,6 +19,23 @@ typedef enum { THEME_HOTLIST_TOOLBAR } toolbar_type; +struct theme_file_header { + unsigned int magic_value; + unsigned int parser_version; + char name[32]; + char author[64]; + char browser_bg; + char hotlist_bg; + char status_bg; + char status_fg; + char theme_flags; + char future_expansion_1; + char future_expansion_2; + char future_expansion_3; + unsigned int compressed_sprite_size; + unsigned int decompressed_sprite_size; +}; + struct toolbar_icon { int icon_number; /**< wimp icon number */ bool display; /**< whether to display the icon */ @@ -70,6 +87,7 @@ struct theme_descriptor { int status_background; /**< background colour of status window */ int status_foreground; /**< colour of status window text */ bool throbber_right; /**< throbber is on the right (left otherwise) */ + bool throbber_redraw; /**< throbber requires forcible updating */ unsigned int decompressed_size; /**< decompressed sprite size */ unsigned int compressed_size; /**< compressed sprite size */ struct theme *theme; /**< corresponding theme (must be opened) */ @@ -81,6 +99,8 @@ 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_read_file_header(struct theme_descriptor *descriptor, + struct theme_file_header *file_header); bool ro_gui_theme_open(struct theme_descriptor *descriptor, bool list); bool ro_gui_theme_apply(struct theme_descriptor *descriptor); diff --git a/riscos/theme_install.c b/riscos/theme_install.c index 75991f47f..b1b733b2f 100644 --- a/riscos/theme_install.c +++ b/riscos/theme_install.c @@ -11,18 +11,24 @@ #include #include +#include "oslib/osfile.h" #include "netsurf/content/content.h" #include "netsurf/desktop/browser.h" #include "netsurf/riscos/gui.h" +#include "netsurf/riscos/options.h" +#include "netsurf/riscos/theme.h" #include "netsurf/riscos/wimp.h" #include "netsurf/utils/messages.h" +#include "netsurf/utils/url.h" #include "netsurf/utils/utils.h" -static bool theme_install_active = false; +static bool theme_install_active; +static struct content *theme_install_content = NULL; +static struct theme_descriptor theme_install_descriptor; wimp_w dialog_theme_install; - +static void theme_install_close(void); void theme_install_callback(content_msg msg, struct content *c, void *p1, void *p2, union content_msg_data data); @@ -64,25 +70,49 @@ void theme_install_start(struct content *c) void theme_install_callback(content_msg msg, struct content *c, void *p1, void *p2, union content_msg_data data) { + char txt_buffer[256]; + bool error = false; + int author_indent = 0; + switch (msg) { case CONTENT_MSG_READY: break; case CONTENT_MSG_DONE: - /** \todo: parse the theme data, extract name & author, - * and ask the user if they want to install */ + theme_install_content = c; + if ((c->source_size < sizeof(struct theme_file_header)) || + (!ro_gui_theme_read_file_header(&theme_install_descriptor, + (struct theme_file_header *)c->source_data))) + error = true; + else if (c->source_size - sizeof(struct theme_file_header) != + theme_install_descriptor.compressed_size) + error = true; + + if (error) { + warn_user("ThemeInvalid", 0); + theme_install_close(); + break; + } + + /* remove '© ' from the start of the data */ + if (theme_install_descriptor.author[0] == '©') + author_indent++; + while (theme_install_descriptor.author[author_indent] == ' ') + author_indent++; + snprintf(txt_buffer, 256, messages_get("ThemeInstall"), + theme_install_descriptor.name, + &theme_install_descriptor.author[author_indent]); + txt_buffer[255] = '\0'; ro_gui_set_icon_string(dialog_theme_install, ICON_THEME_INSTALL_MESSAGE, - "Would you like to install the theme " - "\"x\" by y?"); + txt_buffer); ro_gui_set_icon_shaded_state(dialog_theme_install, ICON_THEME_INSTALL_INSTALL, false); break; case CONTENT_MSG_ERROR: - ro_gui_dialog_close(dialog_theme_install); + theme_install_close(); warn_user(data.error, 0); - theme_install_active = false; break; case CONTENT_MSG_STATUS: @@ -102,10 +132,96 @@ void theme_install_callback(content_msg msg, struct content *c, /** - * Create theme install window. + * Handle clicks in the theme install window */ +void ro_gui_theme_install_click(wimp_pointer *pointer) { + os_error *error; + fileswitch_object_type obj_type; + char theme_save[256]; + char theme_leaf[256]; + char *theme_file; + int theme_number = 1; + bool theme_found; + struct theme_descriptor *theme_install; + + switch (pointer->i) { + case ICON_THEME_INSTALL_INSTALL: + if (theme_install_content) { + if (url_nice(theme_install_descriptor.name, &theme_file) != URL_FUNC_OK) { + warn_user("ThemeInstallErr", 0); + theme_install_close(); + return; + } + theme_found = false; + while (!theme_found) { + if (theme_number == 1) + snprintf(theme_leaf, 256, + "WWW.NetSurf.Themes.%s", + theme_file); + else + snprintf(theme_leaf, 256, + "WWW.NetSurf.Themes.%s%i", + theme_file, theme_number); + theme_leaf[255] = '\0'; + theme_number++; + snprintf(theme_save, 256, + ".%s", + theme_leaf); + theme_save[255] = '\0'; + error = xosfile_read_stamped(theme_save, + &obj_type, 0, 0, 0, 0, 0); + if (error) { + warn_user("ThemeInstallErr", 0); + theme_install_close(); + free(theme_file); + return; + } + theme_found = (obj_type == osfile_NOT_FOUND); + } + free(theme_file); + error = xosfile_save_stamped(theme_save, 0xffd, + theme_install_content->source_data, + theme_install_content->source_data + + theme_install_content->source_size); + if (error) { + warn_user("ThemeInstallErr", 0); + theme_install_close(); + return; + } + /* apply theme only on Select clicks */ + if (pointer->buttons == wimp_CLICK_SELECT) { + ro_gui_theme_get_available(); + snprintf(theme_save, 256, "Choices:%s", theme_leaf); + theme_save[255] = '\0'; + theme_install = ro_gui_theme_find(theme_save); + if ((!theme_install) || + (!ro_gui_theme_apply(theme_install))) { + warn_user("ThemeApplyErr", 0); + } else { + theme_file = strdup(theme_save); + if (!theme_file) { + warn_user("NoMemory", 0); + } else { + free(option_theme); + option_theme = theme_file; + } + } + } + theme_install_close(); + } + break; + case ICON_THEME_INSTALL_CANCEL: + if (pointer->buttons == wimp_CLICK_ADJUST) + break; + theme_install_close(); + break; + } +} -void ro_gui_theme_install_init(void) -{ - dialog_theme_install = ro_gui_dialog_create("theme_inst"); +static void theme_install_close(void) { + theme_install_active = false; + if (theme_install_content) + content_close(theme_install_content); + theme_install_content = NULL; + ro_gui_dialog_close(dialog_theme_install); } diff --git a/riscos/wimp.c b/riscos/wimp.c index 012cdd6fb..a9e2a29d4 100644 --- a/riscos/wimp.c +++ b/riscos/wimp.c @@ -127,6 +127,37 @@ void ro_convert_pixels_to_os_units(os_coord *pixels, os_mode mode) { #define ro_gui_redraw_icon(w, i) xwimp_set_icon_state(w, i, 0, 0) +/** + * Forces an icon to be redrawn entirely (ie not just updated). + * + * \param w window handle + * \param i icon handle + */ +void ro_gui_force_redraw_icon(wimp_w w, wimp_i i) { + wimp_icon_state ic; + os_error *error; + + /* Get the icon data + */ + ic.w = w; + ic.i = i; + error = xwimp_get_icon_state(&ic); + if (error) { + LOG(("xwimp_get_icon_state: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return; + } + error = xwimp_force_redraw(w, ic.icon.extent.x0, ic.icon.extent.y0, + ic.icon.extent.x1, ic.icon.extent.y1); + if (error) { + LOG(("xwimp_force_redraw: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + } +} + + /** * Read the contents of an icon. * @@ -222,7 +253,7 @@ void ro_gui_set_icon_selected_state(wimp_w w, wimp_i i, bool state) { error = xwimp_set_icon_state(w, i, (state ? wimp_ICON_SELECTED : 0), wimp_ICON_SELECTED); if (error) { - LOG(("xwimp_get_icon_state: 0x%x: %s", + LOG(("xwimp_set_icon_state: 0x%x: %s", error->errnum, error->errmess)); warn_user("WimpError", error->errmess); } @@ -285,6 +316,25 @@ bool ro_gui_get_icon_shaded_state(wimp_w w, wimp_i i) { } +/** + * Set the button type of an icon. + * + * \param w window handle + * \param i icon handle + * \param type button type + */ +void ro_gui_set_icon_button_type(wimp_w w, wimp_i i, int type) { + os_error *error; + error = xwimp_set_icon_state(w, i, wimp_ICON_BUTTON_TYPE, + (type << wimp_ICON_BUTTON_TYPE_SHIFT)); + if (error) { + LOG(("xwimp_set_icon_state: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + } +} + + /** * Set a window title (does *not* redraw the title) * diff --git a/riscos/wimp.h b/riscos/wimp.h index 744917efb..b0ab4c7df 100644 --- a/riscos/wimp.h +++ b/riscos/wimp.h @@ -34,6 +34,7 @@ void ro_convert_os_units_to_pixels(os_coord *os_units, os_mode mode); void ro_convert_pixels_to_os_units(os_coord *pixels, os_mode mode); #define ro_gui_redraw_icon(w, i) xwimp_set_icon_state(w, i, 0, 0) +void ro_gui_force_redraw_icon(wimp_w w, wimp_i i); char *ro_gui_get_icon_string(wimp_w w, wimp_i i); void ro_gui_set_icon_string(wimp_w w, wimp_i i, const char *text); void ro_gui_set_icon_integer(wimp_w w, wimp_i i, int value); @@ -41,6 +42,7 @@ void ro_gui_set_icon_selected_state(wimp_w w, wimp_i i, bool state); bool ro_gui_get_icon_selected_state(wimp_w w, wimp_i i); void ro_gui_set_icon_shaded_state(wimp_w w, wimp_i i, bool state); bool ro_gui_get_icon_shaded_state(wimp_w w, wimp_i i); +void ro_gui_set_icon_button_type(wimp_w w, wimp_i i, int type); void ro_gui_set_window_title(wimp_w w, const char *title); void ro_gui_set_caret_first(wimp_w w); void ro_gui_open_window_centre(wimp_w parent, wimp_w child); diff --git a/riscos/window.c b/riscos/window.c index cdf98130b..2bbd46e9f 100644 --- a/riscos/window.c +++ b/riscos/window.c @@ -444,9 +444,8 @@ void ro_gui_window_redraw(struct gui_window *g, wimp_draw *redraw) return; } while (more) { - if (ro_gui_current_redraw_gui->option.buffer_everything) { + if (ro_gui_current_redraw_gui->option.buffer_everything) ro_gui_buffer_open(redraw); - } if (clear_background) { error = xcolourtrans_set_gcol(os_COLOUR_WHITE, colourtrans_SET_BG, @@ -472,9 +471,8 @@ void ro_gui_window_redraw(struct gui_window *g, wimp_draw *redraw) g->option.scale, 0xFFFFFF); } - if (ro_gui_current_redraw_gui->option.buffer_everything) { + if (ro_gui_current_redraw_gui->option.buffer_everything) ro_gui_buffer_close(); - } error = xwimp_get_rectangle(redraw, &more); /* RISC OS 3.7 returns an error here if enough buffer was claimed to cause a new dynamic area to be created. It @@ -1002,6 +1000,9 @@ void ro_gui_throb(void) sprintf(throb_buf, "throbber%i", g->throbber); ro_gui_set_icon_string(g->toolbar->toolbar_handle, ICON_TOOLBAR_THROBBER, throb_buf); + if (g->toolbar->descriptor->throbber_redraw) + ro_gui_force_redraw_icon(g->toolbar->toolbar_handle, + ICON_TOOLBAR_THROBBER); } } @@ -1316,6 +1317,9 @@ void gui_window_stop_throbber(struct gui_window *g) strcpy(throb_buf, "throbber0"); ro_gui_set_icon_string(g->toolbar->toolbar_handle, ICON_TOOLBAR_THROBBER, throb_buf); + if ((g->toolbar->descriptor) && (g->toolbar->descriptor->throbber_redraw)) + ro_gui_force_redraw_icon(g->toolbar->toolbar_handle, + ICON_TOOLBAR_THROBBER); } } -- cgit v1.2.3