From cd9c0998e9849472473e577c4c04906e380896e1 Mon Sep 17 00:00:00 2001 From: Steve Fryatt Date: Sun, 20 Feb 2011 23:16:33 +0000 Subject: Merge branches/stevef/toolbars to trunk. svn path=/trunk/netsurf/; revision=11741 --- riscos/Makefile.target | 18 +- riscos/configure/con_connect.c | 12 +- riscos/configure/con_home.c | 32 +- riscos/configure/con_image.c | 21 +- riscos/configure/con_theme.c | 39 +- riscos/cookies.c | 212 +- riscos/cookies.h | 8 - riscos/dialog.c | 40 +- riscos/dialog.h | 2 +- riscos/global_history.c | 231 +- riscos/global_history.h | 8 - riscos/gui.c | 83 +- riscos/gui.h | 34 +- riscos/gui/button_bar.c | 1231 ++++++++++ riscos/gui/button_bar.h | 314 +++ riscos/gui/throbber.c | 419 ++++ riscos/gui/throbber.h | 144 ++ riscos/gui/url_bar.c | 984 ++++++++ riscos/gui/url_bar.h | 302 +++ riscos/help.c | 43 +- riscos/hotlist.c | 242 +- riscos/hotlist.h | 7 - riscos/iconbar.c | 233 ++ riscos/iconbar.h | 32 + riscos/menus.c | 1559 +------------ riscos/menus.h | 19 +- riscos/plugin.c | 9 +- riscos/print.c | 2 +- riscos/search.c | 59 +- riscos/sslcert.c | 4 +- riscos/textselection.c | 5 +- riscos/theme.c | 1857 ++-------------- riscos/theme.h | 122 +- riscos/toolbar.c | 1770 +++++++++++++++ riscos/toolbar.h | 525 +++++ riscos/treeview.c | 173 +- riscos/treeview.h | 12 +- riscos/uri.c | 1 - riscos/url_complete.c | 218 +- riscos/url_complete.h | 68 +- riscos/url_suggest.c | 71 +- riscos/url_suggest.h | 6 +- riscos/wimp.c | 112 +- riscos/wimp.h | 5 +- riscos/wimp_event.c | 424 +++- riscos/wimp_event.h | 39 +- riscos/window.c | 4811 +++++++++++++++++++++++++++------------- riscos/window.h | 33 + 48 files changed, 10985 insertions(+), 5610 deletions(-) create mode 100644 riscos/gui/button_bar.c create mode 100644 riscos/gui/button_bar.h create mode 100644 riscos/gui/throbber.c create mode 100644 riscos/gui/throbber.h create mode 100644 riscos/gui/url_bar.c create mode 100644 riscos/gui/url_bar.h create mode 100644 riscos/iconbar.c create mode 100644 riscos/iconbar.h create mode 100644 riscos/toolbar.c create mode 100644 riscos/toolbar.h create mode 100644 riscos/window.h (limited to 'riscos') diff --git a/riscos/Makefile.target b/riscos/Makefile.target index 685979d77..f7ba8d895 100644 --- a/riscos/Makefile.target +++ b/riscos/Makefile.target @@ -1,4 +1,4 @@ -# RISC OS Target makefile +# RISC OS Target makefile # ---------------------------------------------------------------------------- # RISC OS target setup @@ -68,13 +68,15 @@ endif S_RISCOS := 401login.c artworks.c assert.c awrender.s bitmap.c buffer.c \ cookies.c configure.c debugwin.c dialog.c download.c draw.c \ filetype.c font.c global_history.c gui.c help.c history.c \ - hotlist.c image.c menus.c message.c palettes.c plotters.c \ - plugin.c print.c query.c save.c save_draw.c save_pdf.c \ - schedule.c search.c searchweb.c sprite.c sslcert.c \ - textarea.c textselection.c theme.c theme_install.c thumbnail.c \ - treeview.c ucstables.c uri.c url_complete.c url_protocol.c \ - url_suggest.c wimp.c wimp_event.c window.c system_colour.c \ - gui/progress_bar.c gui/status_bar.c \ + hotlist.c iconbar.c image.c menus.c message.c palettes.c \ + plotters.c plugin.c print.c query.c save.c save_draw.c \ + save_pdf.c schedule.c search.c searchweb.c sprite.c sslcert.c \ + system_colour.c textarea.c textselection.c theme.c \ + theme_install.c thumbnail.c toolbar.c treeview.c ucstables.c \ + uri.c url_complete.c url_protocol.c url_suggest.c wimp.c \ + wimp_event.c window.c \ + $(addprefix gui/,button_bar.c progress_bar.c status_bar.c \ + throbber.c url_bar.c) \ $(addprefix configure/,con_cache.c con_connect.c con_content.c \ con_fonts.c con_home.c con_image.c con_inter.c con_language.c \ con_memory.c con_secure.c con_theme.c) diff --git a/riscos/configure/con_connect.c b/riscos/configure/con_connect.c index 70236f23a..fd74155bd 100644 --- a/riscos/configure/con_connect.c +++ b/riscos/configure/con_connect.c @@ -60,7 +60,8 @@ static int ro_gui_options_connection_proxy_type(wimp_w w); static void ro_gui_options_connection_default(wimp_pointer *pointer); static bool ro_gui_options_connection_ok(wimp_w w); -static void ro_gui_options_connection_update(wimp_w w, wimp_i i); +static bool ro_gui_options_connection_update(wimp_w w, wimp_i i, wimp_menu *m, + wimp_selection *s, menu_action a); bool ro_gui_options_connection_initialise(wimp_w w) { @@ -88,7 +89,7 @@ bool ro_gui_options_connection_initialise(wimp_w w) option_max_fetchers_per_host); ro_gui_set_icon_integer(w, CONNECTION_CACHE_FETCH_FIELD, option_max_cached_fetch_handles); - ro_gui_options_connection_update(w, -1); + ro_gui_options_connection_update(w, -1, NULL, NULL, NO_ACTION); /* register icons */ ro_gui_wimp_event_register_menu_gright(w, CONNECTION_PROXY_FIELD, @@ -124,7 +125,8 @@ bool ro_gui_options_connection_initialise(wimp_w w) } -void ro_gui_options_connection_update(wimp_w w, wimp_i i) +bool ro_gui_options_connection_update(wimp_w w, wimp_i i, wimp_menu *m, + wimp_selection *s, menu_action a) { int proxy_type; bool host, user; @@ -142,6 +144,8 @@ void ro_gui_options_connection_update(wimp_w w, wimp_i i) ro_gui_set_icon_shaded_state(w, CONNECTION_PROXY_USERNAME, !user); ro_gui_set_icon_shaded_state(w, CONNECTION_PROXY_PASSWORD_LABEL, !user); ro_gui_set_icon_shaded_state(w, CONNECTION_PROXY_PASSWORD, !user); + + return true; } int ro_gui_options_connection_proxy_type(wimp_w w) @@ -169,7 +173,7 @@ void ro_gui_options_connection_default(wimp_pointer *pointer) ro_gui_set_icon_integer(pointer->w, CONNECTION_MAX_FETCH_FIELD, 24); ro_gui_set_icon_integer(pointer->w, CONNECTION_HOST_FETCH_FIELD, 5); ro_gui_set_icon_integer(pointer->w, CONNECTION_CACHE_FETCH_FIELD, 6); - ro_gui_options_connection_update(pointer->w, -1); + ro_gui_options_connection_update(pointer->w, -1, NULL, NULL, NO_ACTION); } bool ro_gui_options_connection_ok(wimp_w w) diff --git a/riscos/configure/con_home.c b/riscos/configure/con_home.c index fbe1b7039..65cc4e39a 100644 --- a/riscos/configure/con_home.c +++ b/riscos/configure/con_home.c @@ -30,7 +30,6 @@ #include "utils/messages.h" #include "utils/utils.h" - #define HOME_URL_FIELD 3 #define HOME_URL_GRIGHT 4 #define HOME_OPEN_STARTUP 5 @@ -40,6 +39,8 @@ static void ro_gui_options_home_default(wimp_pointer *pointer); static bool ro_gui_options_home_ok(wimp_w w); +static bool ro_gui_options_home_menu_prepare(wimp_w w, wimp_i i, + wimp_menu *menu, wimp_pointer *pointer); bool ro_gui_options_home_initialise(wimp_w w) { @@ -53,13 +54,15 @@ bool ro_gui_options_home_initialise(wimp_w w) /* initialise all functions for a newly created window */ ro_gui_wimp_event_register_menu_gright(w, HOME_URL_FIELD, - HOME_URL_GRIGHT, url_suggest_menu); + HOME_URL_GRIGHT, ro_gui_url_suggest_menu); ro_gui_wimp_event_register_checkbox(w, HOME_OPEN_STARTUP); ro_gui_wimp_event_register_button(w, HOME_DEFAULT_BUTTON, ro_gui_options_home_default); ro_gui_wimp_event_register_cancel(w, HOME_CANCEL_BUTTON); ro_gui_wimp_event_register_ok(w, HOME_OK_BUTTON, ro_gui_options_home_ok); + ro_gui_wimp_event_register_menu_prepare(w, + ro_gui_options_home_menu_prepare); ro_gui_wimp_event_set_help_prefix(w, "HelpHomeConfig"); ro_gui_wimp_event_memorise(w); return true; @@ -84,3 +87,28 @@ bool ro_gui_options_home_ok(wimp_w w) ro_gui_save_options(); return true; } + + +/** + * Callback to prepare menus in the Configure Home dialog. At present, this + * only has to handle the URL Suggestion pop-up. + * + * \param w The window handle owning the menu. + * \param i The icon handle owning the menu. + * \param *menu The menu to be prepared. + * \param *pointer The associated mouse click event block, or NULL + * on an Adjust-click re-opening. + * \return true if the event was handled; false if not. + */ + +bool ro_gui_options_home_menu_prepare(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_pointer *pointer) +{ + if (menu != ro_gui_url_suggest_menu || i != HOME_URL_GRIGHT) + return false; + + if (pointer != NULL) + ro_gui_url_suggest_prepare_menu(); + + return true; +} diff --git a/riscos/configure/con_image.c b/riscos/configure/con_image.c index 45925d39b..1cb29a267 100644 --- a/riscos/configure/con_image.c +++ b/riscos/configure/con_image.c @@ -50,8 +50,9 @@ static bool ro_gui_options_image_click(wimp_pointer *pointer); static bool ro_gui_options_image_ok(wimp_w w); static void ro_gui_options_image_redraw(wimp_draw *redraw); -static void ro_gui_options_image_update(wimp_w w, wimp_i i); -static void ro_gui_options_image_read(wimp_w w, unsigned int *bg, +static bool ro_gui_options_image_update(wimp_w w, wimp_i i, wimp_menu *m, + wimp_selection *s, menu_action a); +static void ro_gui_options_image_read(wimp_w w, unsigned int *bg, unsigned int *fg); static void ro_gui_options_update_shading(wimp_w w); @@ -86,7 +87,7 @@ bool ro_gui_options_image_initialise(wimp_w w) image_quality_menu->entries[i]. data.indirected_text.text, true); } - ro_gui_set_icon_decimal(w, IMAGE_SPEED_FIELD, + ro_gui_set_icon_decimal(w, IMAGE_SPEED_FIELD, option_minimum_gif_delay, 2); ro_gui_set_icon_selected_state(w, IMAGE_DISABLE_ANIMATION, !option_animate_images); @@ -127,9 +128,12 @@ void ro_gui_options_image_finalise(wimp_w w) ro_gui_wimp_event_finalise(w); } -void ro_gui_options_image_update(wimp_w w, wimp_i i) +bool ro_gui_options_image_update(wimp_w w, wimp_i i, wimp_menu *m, + wimp_selection *s, menu_action a) { ro_gui_redraw_icon(w, IMAGE_CURRENT_DISPLAY); + + return true; } void ro_gui_options_image_redraw(wimp_draw *redraw) @@ -204,11 +208,11 @@ bool ro_gui_options_image_click(wimp_pointer *pointer) ro_gui_options_image_read(pointer->w, &old_bg, &old_fg); switch (pointer->i) { case IMAGE_DEFAULT_BUTTON: - ro_gui_set_icon_string(pointer->w, + ro_gui_set_icon_string(pointer->w, IMAGE_FOREGROUND_FIELD, image_quality_menu->entries[3]. data.indirected_text.text, true); - ro_gui_set_icon_string(pointer->w, + ro_gui_set_icon_string(pointer->w, IMAGE_BACKGROUND_FIELD, image_quality_menu->entries[2]. data.indirected_text.text, true); @@ -228,7 +232,8 @@ bool ro_gui_options_image_click(wimp_pointer *pointer) ro_gui_options_image_read(pointer->w, &bg, &fg); if ((bg != old_bg) || (fg != old_fg)) - ro_gui_options_image_update(pointer->w, pointer->i); + ro_gui_options_image_update(pointer->w, pointer->i, + NULL, NULL, NO_ACTION); return false; } @@ -247,7 +252,7 @@ void ro_gui_options_update_shading(wimp_w w) bool ro_gui_options_image_ok(wimp_w w) { - ro_gui_options_image_read(w, (unsigned int *) &option_bg_plot_style, + ro_gui_options_image_read(w, (unsigned int *) &option_bg_plot_style, (unsigned int *) &option_fg_plot_style); option_minimum_gif_delay = ro_gui_get_icon_decimal(w, IMAGE_SPEED_FIELD, 2); diff --git a/riscos/configure/con_theme.c b/riscos/configure/con_theme.c index 0954a31e9..a6dc98265 100644 --- a/riscos/configure/con_theme.c +++ b/riscos/configure/con_theme.c @@ -29,6 +29,7 @@ #include "riscos/menus.h" #include "riscos/options.h" #include "riscos/theme.h" +#include "riscos/toolbar.h" #include "riscos/url_complete.h" #include "riscos/wimp.h" #include "riscos/wimp_event.h" @@ -261,11 +262,17 @@ void ro_gui_options_theme_load(void) /* create toolbars for each theme */ theme_count = 0; descriptor = theme_list; - while (descriptor) { + while (descriptor != NULL) { /* try to create a toolbar */ - toolbar = ro_gui_theme_create_toolbar(descriptor, - THEME_BROWSER_TOOLBAR); - if (toolbar) { + toolbar = ro_toolbar_create(descriptor, NULL, + THEME_STYLE_BROWSER_TOOLBAR, + TOOLBAR_FLAGS_DISPLAY, NULL, NULL, NULL); + if (toolbar != NULL) { + ro_toolbar_add_buttons(toolbar, brower_toolbar_buttons, + option_toolbar_browser); + ro_toolbar_add_url(toolbar); + ro_toolbar_add_throbber(toolbar); + ro_toolbar_rebuild(toolbar); toolbar_display = calloc(sizeof(struct toolbar_display), 1); if (!toolbar_display) { LOG(("No memory for calloc()")); @@ -311,21 +318,23 @@ void ro_gui_options_theme_load(void) /* update the toolbar */ item_height = 44 + 44 + 16; if (link->next) item_height += 16; - ro_gui_theme_process_toolbar(link->toolbar, parent_width); - extent.y0 = nested_y - link->toolbar->height - item_height; + ro_toolbar_process(link->toolbar, parent_width, false); + extent.y0 = nested_y - + ro_toolbar_height(link->toolbar) - + item_height; if (link->next) extent.y0 -= 16; if (extent.y0 > min_extent) extent.y0 = min_extent; xwimp_set_extent(theme_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 */ new_icon.icon.extent.x0 = 8; new_icon.icon.extent.x1 = parent_width - 8; new_icon.icon.flags &= ~wimp_ICON_BORDER; new_icon.icon.flags |= wimp_ICON_SPRITE; - new_icon.icon.extent.y1 = nested_y - link->toolbar->height - 8; - new_icon.icon.extent.y0 = nested_y - link->toolbar->height - 52; + new_icon.icon.extent.y1 = nested_y - + ro_toolbar_height(link->toolbar) - 8; + new_icon.icon.extent.y0 = nested_y - + ro_toolbar_height(link->toolbar) - 52; new_icon.icon.data.indirected_text_and_sprite.text = (char *)&link->descriptor->name; new_icon.icon.data.indirected_text_and_sprite.size = @@ -363,10 +372,11 @@ void ro_gui_options_theme_load(void) } /* nest the toolbar window */ - state.w = link->toolbar->toolbar_handle; + state.w = ro_toolbar_get_window(link->toolbar); state.yscroll = 0; state.visible.y1 = nested_y + base_extent; - state.visible.y0 = state.visible.y1 - link->toolbar->height + 2; + state.visible.y0 = state.visible.y1 - + ro_toolbar_height(link->toolbar) + 2; xwimp_open_window_nested(PTR_WIMP_OPEN(&state), theme_pane, wimp_CHILD_LINKS_PARENT_WORK_AREA << wimp_CHILD_BS_EDGE_SHIFT | @@ -374,7 +384,8 @@ void ro_gui_options_theme_load(void) << wimp_CHILD_TS_EDGE_SHIFT); /* continue processing */ - nested_y -= link->toolbar->height + item_height; + nested_y -= ro_toolbar_height(link->toolbar) + + item_height; link = link->next; } @@ -404,7 +415,7 @@ void ro_gui_options_theme_free(void) if (next_toolbar) xwimp_delete_icon(theme_pane, toolbar->icon_number + 2); - ro_gui_theme_destroy_toolbar(toolbar->toolbar); + ro_toolbar_destroy(toolbar->toolbar); free(toolbar); } toolbars = NULL; diff --git a/riscos/cookies.c b/riscos/cookies.c index 5eb2191d2..76c7f4673 100644 --- a/riscos/cookies.c +++ b/riscos/cookies.c @@ -36,7 +36,7 @@ #include "riscos/dialog.h" #include "riscos/menus.h" #include "riscos/options.h" -#include "riscos/theme.h" +#include "riscos/toolbar.h" #include "riscos/treeview.h" #include "riscos/wimp.h" #include "riscos/wimp_event.h" @@ -45,6 +45,22 @@ #include "utils/url.h" #include "utils/utils.h" +static void ro_gui_cookies_toolbar_update_buttons(void); +static void ro_gui_cookies_toolbar_save_buttons(char *config); +static bool ro_gui_cookies_menu_prepare(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_pointer *pointer); +static void ro_gui_cookies_menu_warning(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_selection *selection, menu_action action); +static bool ro_gui_cookies_menu_select(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_selection *selection, menu_action action); +static void ro_gui_cookies_toolbar_click(button_bar_action action); + +struct ro_treeview_callbacks ro_cookies_treeview_callbacks = { + ro_gui_cookies_toolbar_click, + ro_gui_cookies_toolbar_update_buttons, + ro_gui_cookies_toolbar_save_buttons +}; + /* The RISC OS cookie window, toolbar and treeview data. */ static struct ro_cookies_window { @@ -76,21 +92,30 @@ void ro_gui_cookies_postinitialise(void) { /* Create our toolbar. */ - cookies_window.toolbar = ro_gui_theme_create_toolbar(NULL, - THEME_COOKIES_TOOLBAR); - if (cookies_window.toolbar) - ro_gui_theme_attach_toolbar(cookies_window.toolbar, - cookies_window.window); + cookies_window.toolbar = ro_toolbar_create(NULL, cookies_window.window, + THEME_STYLE_COOKIES_TOOLBAR, TOOLBAR_FLAGS_NONE, + ro_treeview_get_toolbar_callbacks(), NULL, + "HelpCookiesToolbar"); + if (cookies_window.toolbar != NULL) { + ro_toolbar_add_buttons(cookies_window.toolbar, + cookies_toolbar_buttons, + option_toolbar_cookies); + ro_toolbar_rebuild(cookies_window.toolbar); + } /* Create the treeview with the window and toolbar. */ cookies_window.tv = ro_treeview_create(cookies_window.window, - cookies_window.toolbar, cookies_get_tree_flags()); + cookies_window.toolbar, &ro_cookies_treeview_callbacks, + cookies_get_tree_flags()); if (cookies_window.tv == NULL) { LOG(("Failed to allocate treeview")); return; } + ro_toolbar_update_client_data(cookies_window.toolbar, + cookies_window.tv); + /* Initialise the cookies into the tree. */ cookies_initialise(ro_treeview_get_tree(cookies_window.tv), @@ -123,14 +148,18 @@ void ro_gui_cookies_postinitialise(void) }; cookies_window.menu = ro_gui_menu_define_menu(&cookies_definition); - ro_gui_wimp_event_register_window_menu(cookies_window.window, - cookies_window.menu, ro_gui_cookies_menu_prepare, - ro_gui_cookies_menu_select, NULL, - ro_gui_cookies_menu_warning, false); + ro_gui_wimp_event_register_menu(cookies_window.window, + cookies_window.menu, false, false); + ro_gui_wimp_event_register_menu_prepare(cookies_window.window, + ro_gui_cookies_menu_prepare); + ro_gui_wimp_event_register_menu_selection(cookies_window.window, + ro_gui_cookies_menu_select); + ro_gui_wimp_event_register_menu_warning(cookies_window.window, + ro_gui_cookies_menu_warning); } /** - * \TODO - Open the cookies window. + * Open the cookies window. * */ @@ -138,111 +167,128 @@ void ro_gui_cookies_open(void) { tree_set_redraw(ro_treeview_get_tree(cookies_window.tv), true); + ro_gui_cookies_toolbar_update_buttons(); + if (!ro_gui_dialog_open_top(cookies_window.window, cookies_window.toolbar, 600, 800)) { ro_treeview_set_origin(cookies_window.tv, 0, - -(ro_gui_theme_toolbar_height( - cookies_window.toolbar))); + -(ro_toolbar_height(cookies_window.toolbar))); } } /** - * Handle Mouse Click events on the toolbar. + * Handle toolbar button clicks. * - * \param *pointer Pointer to the Mouse Click Event block. - * \return Return true if click handled; else false. + * \param action The action to handle */ -bool ro_gui_cookies_toolbar_click(wimp_pointer *pointer) +void ro_gui_cookies_toolbar_click(button_bar_action action) { - if (pointer->buttons == wimp_CLICK_MENU) - return ro_gui_wimp_event_process_window_menu_click(pointer); + switch (action) { + case TOOLBAR_BUTTON_DELETE: + cookies_delete_selected(); + break; - if (cookies_window.toolbar->editor != NULL) { - ro_gui_theme_toolbar_editor_click(cookies_window.toolbar, - pointer); - return true; - } + case TOOLBAR_BUTTON_EXPAND: + cookies_expand_cookies(); + break; - switch (pointer->i) { - case ICON_TOOLBAR_DELETE: - if (pointer->buttons == wimp_CLICK_SELECT) { - cookies_delete_selected(); - return true; - } + case TOOLBAR_BUTTON_COLLAPSE: + cookies_collapse_cookies(); break; - case ICON_TOOLBAR_EXPAND: - if (pointer->buttons == wimp_CLICK_SELECT) { - cookies_expand_cookies(); - return true; - } else if (pointer->buttons == wimp_CLICK_ADJUST) { - cookies_collapse_cookies(); - return true; - } + + case TOOLBAR_BUTTON_OPEN: + cookies_expand_domains(); break; - case ICON_TOOLBAR_OPEN: - if (pointer->buttons == wimp_CLICK_SELECT) { - cookies_expand_domains(); - return true; - } else if (pointer->buttons == wimp_CLICK_ADJUST) { - cookies_collapse_domains(); - return true; - } + + case TOOLBAR_BUTTON_CLOSE: + cookies_collapse_domains(); + break; + + default: break; } +} - return false; + +/** + * Update the button state in the cookies toolbar. + */ + +void ro_gui_cookies_toolbar_update_buttons(void) +{ + ro_toolbar_set_button_shaded_state(cookies_window.toolbar, + TOOLBAR_BUTTON_DELETE, + !ro_treeview_has_selection(cookies_window.tv)); } + +/** + * Save a new button arrangement in the cookies toolbar. + * + * \param *config The new button configuration string. + */ + +void ro_gui_cookies_toolbar_save_buttons(char *config) +{ + if (option_toolbar_cookies != NULL) + free(option_toolbar_cookies); + option_toolbar_cookies = config; + ro_gui_save_options(); +} + + /** * Prepare the cookies menu for opening * - * \param window The window owning the menu. + * \param w The window owning the menu. + * \param i The icon owning the menu. * \param *menu The menu about to be opened. + * \param *pointer Pointer to the relevant wimp event block, or + * NULL for an Adjust click. + * \return true if the event was handled; else false. */ -void ro_gui_cookies_menu_prepare(wimp_w window, wimp_menu *menu) +bool ro_gui_cookies_menu_prepare(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_pointer *pointer) { bool selection; - if (menu != cookies_window.menu && menu != tree_toolbar_menu) - return; + if (menu != cookies_window.menu) + return false; - if (menu == cookies_window.menu) { - selection = ro_treeview_has_selection(cookies_window.tv); + selection = ro_treeview_has_selection(cookies_window.tv); - ro_gui_menu_set_entry_shaded(cookies_window.menu, TREE_SELECTION, - !selection); - ro_gui_menu_set_entry_shaded(cookies_window.menu, TREE_CLEAR_SELECTION, - !selection); - } + ro_gui_menu_set_entry_shaded(cookies_window.menu, + TREE_SELECTION, !selection); + ro_gui_menu_set_entry_shaded(cookies_window.menu, + TREE_CLEAR_SELECTION, !selection); ro_gui_menu_set_entry_shaded(menu, TOOLBAR_BUTTONS, - (cookies_window.toolbar == NULL || - cookies_window.toolbar->editor)); + ro_toolbar_menu_option_shade(cookies_window.toolbar)); ro_gui_menu_set_entry_ticked(menu, TOOLBAR_BUTTONS, - (cookies_window.toolbar != NULL && - (cookies_window.toolbar->display_buttons || - (cookies_window.toolbar->editor)))); + ro_toolbar_menu_buttons_tick(cookies_window.toolbar)); ro_gui_menu_set_entry_shaded(menu, TOOLBAR_EDIT, - cookies_window.toolbar == NULL); + ro_toolbar_menu_edit_shade(cookies_window.toolbar)); ro_gui_menu_set_entry_ticked(menu, TOOLBAR_EDIT, - (cookies_window.toolbar != NULL && - cookies_window.toolbar->editor)); + ro_toolbar_menu_edit_tick(cookies_window.toolbar)); + + return true; } /** * Handle submenu warnings for the cookies menu * - * \param window The window owning the menu. + * \param w The window owning the menu. + * \param i The icon owning the menu. * \param *menu The menu to which the warning applies. * \param *selection The wimp menu selection data. * \param action The selected menu action. */ -void ro_gui_cookies_menu_warning(wimp_w window, wimp_menu *menu, +void ro_gui_cookies_menu_warning(wimp_w w, wimp_i i, wimp_menu *menu, wimp_selection *selection, menu_action action) { /* Do nothing */ @@ -251,14 +297,15 @@ void ro_gui_cookies_menu_warning(wimp_w window, wimp_menu *menu, /** * Handle selections from the cookies menu * - * \param window The window owning the menu. + * \param w The window owning the menu. + * \param i The icon owning the menu. * \param *menu The menu from which the selection was made. * \param *selection The wimp menu selection data. * \param action The selected menu action. * \return true if action accepted; else false. */ -bool ro_gui_cookies_menu_select(wimp_w window, wimp_menu *menu, +bool ro_gui_cookies_menu_select(wimp_w w, wimp_i i, wimp_menu *menu, wimp_selection *selection, menu_action action) { switch (action) { @@ -290,12 +337,12 @@ bool ro_gui_cookies_menu_select(wimp_w window, wimp_menu *menu, cookies_clear_selection(); return true; case TOOLBAR_BUTTONS: - cookies_window.toolbar->display_buttons = - !cookies_window.toolbar->display_buttons; - ro_gui_theme_refresh_toolbar(cookies_window.toolbar); + ro_toolbar_set_display_buttons(cookies_window.toolbar, + !ro_toolbar_get_display_buttons( + cookies_window.toolbar)); return true; case TOOLBAR_EDIT: - ro_gui_theme_toggle_edit(cookies_window.toolbar); + ro_toolbar_toggle_edit(cookies_window.toolbar); return true; default: return false; @@ -304,21 +351,6 @@ bool ro_gui_cookies_menu_select(wimp_w window, wimp_menu *menu, return false; } -/** - * Update the theme details of the cookies window. - * - * \param full_update true to force a full theme change; false to - * refresh the toolbar size. - */ - -void ro_gui_cookies_update_theme(bool full_update) -{ - if (full_update) - ro_treeview_update_theme(cookies_window.tv); - else - ro_treeview_update_toolbar(cookies_window.tv); -} - /** * Check if a particular window handle is the cookies window * diff --git a/riscos/cookies.h b/riscos/cookies.h index 8f46147c4..e55ca0275 100644 --- a/riscos/cookies.h +++ b/riscos/cookies.h @@ -30,16 +30,8 @@ void ro_gui_cookies_preinitialise(void); void ro_gui_cookies_postinitialise(void); bool ro_gui_cookies_check_window(wimp_w window); bool ro_gui_cookies_check_menu(wimp_menu *menu); -bool ro_gui_cookies_toolbar_click(wimp_pointer *pointer); - -void ro_gui_cookies_menu_prepare(wimp_w window, wimp_menu *menu); -bool ro_gui_cookies_menu_select(wimp_w window, wimp_menu *menu, - wimp_selection *selection, menu_action action); -void ro_gui_cookies_menu_warning(wimp_w window, wimp_menu *menu, - wimp_selection *selection, menu_action action); void ro_gui_cookies_open(void); -void ro_gui_cookies_update_theme(bool full_update); #endif diff --git a/riscos/dialog.c b/riscos/dialog.c index b4195a5b7..611b7efc2 100644 --- a/riscos/dialog.c +++ b/riscos/dialog.c @@ -44,7 +44,7 @@ #include "riscos/options.h" #include "riscos/save.h" #include "riscos/sslcert.h" -#include "riscos/theme.h" +#include "riscos/toolbar.h" #include "riscos/url_complete.h" #include "riscos/url_suggest.h" #include "riscos/wimp.h" @@ -86,6 +86,9 @@ static struct { static bool ro_gui_dialog_openurl_apply(wimp_w w); +static bool ro_gui_dialog_open_url_menu_prepare(wimp_w w, wimp_i i, + wimp_menu *menu, wimp_pointer *pointer); + static bool ro_gui_dialog_zoom_apply(wimp_w w); /** @@ -162,10 +165,12 @@ void ro_gui_dialog_init(void) /* open URL */ dialog_openurl = ro_gui_dialog_create("open_url"); ro_gui_wimp_event_register_menu_gright(dialog_openurl, ICON_OPENURL_URL, - ICON_OPENURL_MENU, url_suggest_menu); + ICON_OPENURL_MENU, ro_gui_url_suggest_menu); ro_gui_wimp_event_register_cancel(dialog_openurl, ICON_OPENURL_CANCEL); ro_gui_wimp_event_register_ok(dialog_openurl, ICON_OPENURL_OPEN, ro_gui_dialog_openurl_apply); + ro_gui_wimp_event_register_menu_prepare(dialog_openurl, + ro_gui_dialog_open_url_menu_prepare); ro_gui_wimp_event_set_help_prefix(dialog_openurl, "HelpOpenURL"); /* scale view */ @@ -426,8 +431,8 @@ bool ro_gui_dialog_open_top(wimp_w w, struct toolbar *toolbar, open = state.flags & wimp_WINDOW_OPEN; if (!open) { /* cancel any editing */ - if ((toolbar) && (toolbar->editor)) - ro_gui_theme_toggle_edit(toolbar); + if (ro_toolbar_get_editing(toolbar)) + ro_toolbar_toggle_edit(toolbar); /* move to the centre */ ro_gui_screen_size(&screen_width, &screen_height); @@ -443,7 +448,7 @@ bool ro_gui_dialog_open_top(wimp_w w, struct toolbar *toolbar, state.xscroll = 0; state.yscroll = 0; if (toolbar) - state.yscroll = ro_gui_theme_toolbar_height(toolbar); + state.yscroll = ro_toolbar_height(toolbar); } /* open the window at the top of the stack */ @@ -727,3 +732,28 @@ void ro_gui_dialog_prepare_open_url(void) ICON_OPENURL_MENU, !ro_gui_url_suggest_prepare_menu()); ro_gui_wimp_event_memorise(dialog_openurl); } + + +/** + * Callback to prepare menus in the Open URL dialog. At present, this + * only has to handle the URL Suggestion pop-up. + * + * \param w The window handle owning the menu. + * \param i The icon handle owning the menu. + * \param *menu The menu to be prepared. + * \param *pointer The associated mouse click event block, or NULL + * on an Adjust-click re-opening. + * \return true if the event was handled; false if not. + */ + +bool ro_gui_dialog_open_url_menu_prepare(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_pointer *pointer) +{ + if (menu != ro_gui_url_suggest_menu || i != ICON_OPENURL_MENU) + return false; + + if (pointer != NULL) + return ro_gui_url_suggest_prepare_menu(); + + return true; +} diff --git a/riscos/dialog.h b/riscos/dialog.h index 29c2e5024..5758ad366 100644 --- a/riscos/dialog.h +++ b/riscos/dialog.h @@ -22,7 +22,7 @@ #include #include #include "oslib/wimp.h" -#include "riscos/theme.h" +#include "riscos/toolbar.h" #include "riscos/gui.h" void ro_gui_dialog_init(void); diff --git a/riscos/global_history.c b/riscos/global_history.c index d46600005..28fd107ce 100644 --- a/riscos/global_history.c +++ b/riscos/global_history.c @@ -38,7 +38,7 @@ #include "riscos/menus.h" #include "riscos/options.h" #include "riscos/save.h" -#include "riscos/theme.h" +#include "riscos/toolbar.h" #include "riscos/treeview.h" #include "riscos/wimp.h" #include "riscos/wimp_event.h" @@ -47,6 +47,22 @@ #include "utils/url.h" #include "utils/utils.h" +static void ro_gui_global_history_toolbar_update_buttons(void); +static void ro_gui_global_history_toolbar_save_buttons(char *config); +static bool ro_gui_global_history_menu_prepare(wimp_w w, wimp_i i, + wimp_menu *menu, wimp_pointer *pointer); +static void ro_gui_global_history_menu_warning(wimp_w w, wimp_i i, + wimp_menu *menu, wimp_selection *selection, menu_action action); +static bool ro_gui_global_history_menu_select(wimp_w w, wimp_i i, + wimp_menu *menu, wimp_selection *selection, menu_action action); +static void ro_gui_global_history_toolbar_click(button_bar_action action); + +struct ro_treeview_callbacks ro_global_history_treeview_callbacks = { + ro_gui_global_history_toolbar_click, + ro_gui_global_history_toolbar_update_buttons, + ro_gui_global_history_toolbar_save_buttons +}; + /* The RISC OS global history window, toolbar and treeview data */ static struct ro_global_history_window { @@ -76,26 +92,35 @@ void ro_gui_global_history_preinitialise(void) void ro_gui_global_history_postinitialise(void) { - /* Create our toolbar. */ - global_history_window.toolbar = ro_gui_theme_create_toolbar(NULL, - THEME_HISTORY_TOOLBAR); - if (global_history_window.toolbar) - ro_gui_theme_attach_toolbar(global_history_window.toolbar, - global_history_window.window); + global_history_window.toolbar = ro_toolbar_create(NULL, + global_history_window.window, + THEME_STYLE_GLOBAL_HISTORY_TOOLBAR, TOOLBAR_FLAGS_NONE, + ro_treeview_get_toolbar_callbacks(), NULL, + "HelpGHistoryToolbar"); + if (global_history_window.toolbar != NULL) { + ro_toolbar_add_buttons(global_history_window.toolbar, + global_history_toolbar_buttons, + option_toolbar_history); + ro_toolbar_rebuild(global_history_window.toolbar); + } /* Create the treeview with the window and toolbar. */ global_history_window.tv = ro_treeview_create(global_history_window.window, global_history_window.toolbar, + &ro_global_history_treeview_callbacks, history_global_get_tree_flags()); if (global_history_window.tv == NULL) { LOG(("Failed to allocate treeview")); return; } + ro_toolbar_update_client_data(global_history_window.toolbar, + global_history_window.tv); + /* Initialise the global history into the tree. */ history_global_initialise( @@ -130,11 +155,14 @@ void ro_gui_global_history_postinitialise(void) global_history_window.menu = ro_gui_menu_define_menu( &global_history_definition); - ro_gui_wimp_event_register_window_menu(global_history_window.window, - global_history_window.menu, - ro_gui_global_history_menu_prepare, - ro_gui_global_history_menu_select, NULL, - ro_gui_global_history_menu_warning, false); + ro_gui_wimp_event_register_menu(global_history_window.window, + global_history_window.menu, false, false); + ro_gui_wimp_event_register_menu_prepare(global_history_window.window, + ro_gui_global_history_menu_prepare); + ro_gui_wimp_event_register_menu_selection(global_history_window.window, + ro_gui_global_history_menu_select); + ro_gui_wimp_event_register_menu_warning(global_history_window.window, + ro_gui_global_history_menu_warning); } /** @@ -145,120 +173,143 @@ void ro_gui_global_history_open(void) { tree_set_redraw(ro_treeview_get_tree(global_history_window.tv), true); + ro_gui_global_history_toolbar_update_buttons(); + if (!ro_gui_dialog_open_top(global_history_window.window, global_history_window.toolbar, 600, 800)) { ro_treeview_set_origin(global_history_window.tv, 0, - -(ro_gui_theme_toolbar_height( + -(ro_toolbar_height( global_history_window.toolbar))); } } /** - * Handle Mouse Click events on the toolbar. + * Handle toolbar button clicks. * - * \param *pointer Pointer to the Mouse Click Event block. - * \return Return true if click handled; else false. + * \param action The action to handle */ -bool ro_gui_global_history_toolbar_click(wimp_pointer *pointer) +void ro_gui_global_history_toolbar_click(button_bar_action action) { - if (pointer->buttons == wimp_CLICK_MENU) - return ro_gui_wimp_event_process_window_menu_click(pointer); + switch (action) { + case TOOLBAR_BUTTON_DELETE: + history_global_delete_selected(); + break; - if (global_history_window.toolbar->editor != NULL) { - ro_gui_theme_toolbar_editor_click(global_history_window.toolbar, - pointer); - return true; - } + case TOOLBAR_BUTTON_EXPAND: + history_global_expand_addresses(); + break; - switch (pointer->i) { - case ICON_TOOLBAR_DELETE: - if (pointer->buttons == wimp_CLICK_SELECT) { - history_global_delete_selected(); - return true; - } + case TOOLBAR_BUTTON_COLLAPSE: + history_global_collapse_addresses(); break; - case ICON_TOOLBAR_EXPAND: - if (pointer->buttons == wimp_CLICK_SELECT) { - history_global_expand_addresses(); - return true; - } else if (pointer->buttons == wimp_CLICK_ADJUST) { - history_global_collapse_addresses(); - return true; - } + + case TOOLBAR_BUTTON_OPEN: + history_global_expand_directories(); break; - case ICON_TOOLBAR_OPEN: - if (pointer->buttons == wimp_CLICK_SELECT) { - history_global_expand_directories(); - return true; - } else if (pointer->buttons == wimp_CLICK_ADJUST) { - history_global_collapse_directories(); - return true; - } + + case TOOLBAR_BUTTON_CLOSE: + history_global_collapse_directories(); break; - case ICON_TOOLBAR_LAUNCH: - if (pointer->buttons == wimp_CLICK_SELECT) { - history_global_launch_selected(); - return true; - } + + case TOOLBAR_BUTTON_LAUNCH: + history_global_launch_selected(); + break; + + default: break; } +} - return true; + +/** + * Update the button state in the global history toolbar. + */ + +void ro_gui_global_history_toolbar_update_buttons(void) +{ + ro_toolbar_set_button_shaded_state(global_history_window.toolbar, + TOOLBAR_BUTTON_DELETE, + !ro_treeview_has_selection(global_history_window.tv)); + + ro_toolbar_set_button_shaded_state(global_history_window.toolbar, + TOOLBAR_BUTTON_LAUNCH, + !ro_treeview_has_selection(global_history_window.tv)); +} + + +/** + * Save a new button arrangement in the global history toolbar. + * + * \param *config The new button configuration string. + */ + +void ro_gui_global_history_toolbar_save_buttons(char *config) +{ + if (option_toolbar_history != NULL) + free(option_toolbar_history); + option_toolbar_history = config; + ro_gui_save_options(); } /** * Prepare the global history menu for opening * - * \param window The window owning the menu. + * \param w The window owning the menu. + * \param i The icon owning the menu. * \param *menu The menu about to be opened. + * \param *pointer Pointer to the relevant wimp event block, or + * NULL for an Adjust click. + * \return true if the event was handled; else false. */ -void ro_gui_global_history_menu_prepare(wimp_w window, wimp_menu *menu) +bool ro_gui_global_history_menu_prepare(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_pointer *pointer) { bool selection; - if (menu != global_history_window.menu && menu != tree_toolbar_menu) - return; + if (menu != global_history_window.menu) + return false; - if (menu == global_history_window.menu) { - selection = ro_treeview_has_selection(global_history_window.tv); + selection = ro_treeview_has_selection(global_history_window.tv); - ro_gui_menu_set_entry_shaded(global_history_window.menu, - TREE_SELECTION, !selection); - ro_gui_menu_set_entry_shaded(global_history_window.menu, - TREE_CLEAR_SELECTION, !selection); + ro_gui_menu_set_entry_shaded(global_history_window.menu, + TREE_SELECTION, !selection); + ro_gui_menu_set_entry_shaded(global_history_window.menu, + TREE_CLEAR_SELECTION, !selection); - ro_gui_save_prepare(GUI_SAVE_HISTORY_EXPORT_HTML, - NULL, NULL, NULL, NULL); - } + ro_gui_save_prepare(GUI_SAVE_HISTORY_EXPORT_HTML, + NULL, NULL, NULL, NULL); ro_gui_menu_set_entry_shaded(menu, TOOLBAR_BUTTONS, - (global_history_window.toolbar == NULL || - global_history_window.toolbar->editor)); + ro_toolbar_menu_option_shade( + global_history_window.toolbar)); ro_gui_menu_set_entry_ticked(menu, TOOLBAR_BUTTONS, - (global_history_window.toolbar != NULL && - (global_history_window.toolbar->display_buttons || - (global_history_window.toolbar->editor)))); + ro_toolbar_menu_buttons_tick( + global_history_window.toolbar)); ro_gui_menu_set_entry_shaded(menu, TOOLBAR_EDIT, - global_history_window.toolbar == NULL); + ro_toolbar_menu_edit_shade( + global_history_window.toolbar)); ro_gui_menu_set_entry_ticked(menu, TOOLBAR_EDIT, - (global_history_window.toolbar != NULL && - global_history_window.toolbar->editor)); + ro_toolbar_menu_edit_tick( + global_history_window.toolbar)); + + return true; } /** * Handle submenu warnings for the global_hostory menu * - * \param window The window owning the menu. + * \param w The window owning the menu. + * \param i The icon owning the menu. * \param *menu The menu to which the warning applies. * \param *selection The wimp menu selection data. * \param action The selected menu action. */ -void ro_gui_global_history_menu_warning(wimp_w window, wimp_menu *menu, +void ro_gui_global_history_menu_warning(wimp_w w, wimp_i i, wimp_menu *menu, wimp_selection *selection, menu_action action) { /* Do nothing */ @@ -267,19 +318,20 @@ void ro_gui_global_history_menu_warning(wimp_w window, wimp_menu *menu, /** * Handle selections from the global history menu * - * \param window The window owning the menu. + * \param w The window owning the menu. + * \param i The icon owning the menu. * \param *menu The menu from which the selection was made. * \param *selection The wimp menu selection data. * \param action The selected menu action. * \return true if action accepted; else false. */ -bool ro_gui_global_history_menu_select(wimp_w window, wimp_menu *menu, +bool ro_gui_global_history_menu_select(wimp_w w, wimp_i i, wimp_menu *menu, wimp_selection *selection, menu_action action) { switch (action) { case HISTORY_EXPORT: - ro_gui_dialog_open_persistent(window, dialog_saveas, true); + ro_gui_dialog_open_persistent(w, dialog_saveas, true); return true; case TREE_EXPAND_ALL: history_global_expand_all(); @@ -312,12 +364,12 @@ bool ro_gui_global_history_menu_select(wimp_w window, wimp_menu *menu, history_global_clear_selection(); return true; case TOOLBAR_BUTTONS: - global_history_window.toolbar->display_buttons = - !global_history_window.toolbar->display_buttons; - ro_gui_theme_refresh_toolbar(global_history_window.toolbar); + ro_toolbar_set_display_buttons(global_history_window.toolbar, + !ro_toolbar_get_display_buttons( + global_history_window.toolbar)); return true; case TOOLBAR_EDIT: - ro_gui_theme_toggle_edit(global_history_window.toolbar); + ro_toolbar_toggle_edit(global_history_window.toolbar); return true; default: return false; @@ -326,21 +378,6 @@ bool ro_gui_global_history_menu_select(wimp_w window, wimp_menu *menu, return false; } -/** - * Update the theme details of the global history window. - * - * \param full_update true to force a full theme change; false to - * refresh the toolbar size. - */ - -void ro_gui_global_history_update_theme(bool full_update) -{ - if (full_update) - ro_treeview_update_theme(global_history_window.tv); - else - ro_treeview_update_toolbar(global_history_window.tv); -} - /** * Check if a particular window handle is the global history window * diff --git a/riscos/global_history.h b/riscos/global_history.h index ff06d574b..99ea8c609 100644 --- a/riscos/global_history.h +++ b/riscos/global_history.h @@ -30,16 +30,8 @@ void ro_gui_global_history_preinitialise(void); void ro_gui_global_history_postinitialise(void); void ro_gui_global_history_open(void); void ro_gui_global_history_save(void); -void ro_gui_global_history_update_theme(bool full_update); bool ro_gui_global_history_check_window(wimp_w window); bool ro_gui_global_history_check_menu(wimp_menu *menu); -bool ro_gui_global_history_toolbar_click(wimp_pointer *pointer); - -void ro_gui_global_history_menu_prepare(wimp_w window, wimp_menu *menu); -bool ro_gui_global_history_menu_select(wimp_w window, wimp_menu *menu, - wimp_selection *selection, menu_action action); -void ro_gui_global_history_menu_warning(wimp_w window, wimp_menu *menu, - wimp_selection *selection, menu_action action); #endif diff --git a/riscos/gui.c b/riscos/gui.c index 4d8b5a17c..8ebbc4fe6 100644 --- a/riscos/gui.c +++ b/riscos/gui.c @@ -74,6 +74,7 @@ #include "riscos/gui.h" #include "riscos/help.h" #include "riscos/hotlist.h" +#include "riscos/iconbar.h" #include "riscos/menus.h" #include "riscos/message.h" #include "riscos/options.h" @@ -86,6 +87,7 @@ #include "riscos/sslcert.h" #include "riscos/textselection.h" #include "riscos/theme.h" +#include "riscos/toolbar.h" #include "riscos/treeview.h" #include "riscos/uri.h" #include "riscos/url_protocol.h" @@ -93,6 +95,7 @@ #include "riscos/wimp.h" #include "riscos/wimp_event.h" #include "riscos/wimputils.h" +#include "riscos/window.h" #include "utils/filename.h" #include "utils/log.h" #include "utils/messages.h" @@ -249,7 +252,6 @@ static struct static void ro_gui_create_dirs(void); static void ro_gui_create_dir(char *path); static void ro_gui_choose_language(void); -static void ro_gui_icon_bar_create(void); static void ro_gui_signal(int sig); static void ro_gui_cleanup(void); static void ro_gui_handle_event(wimp_event_no event, wimp_block *block); @@ -257,7 +259,6 @@ static void ro_gui_null_reason_code(void); static void ro_gui_close_window_request(wimp_close *close); static void ro_gui_pointer_leaving_window(wimp_leaving *leaving); static void ro_gui_pointer_entering_window(wimp_entering *entering); -static bool ro_gui_icon_bar_click(wimp_pointer *pointer); static void ro_gui_check_resolvers(void); static void ro_gui_drag_end(wimp_dragged *drag); static void ro_gui_keypress(wimp_key *key); @@ -349,7 +350,7 @@ static void gui_init(int argc, char** argv) option_theme_path = strdup("NetSurf:Themes"); if (!option_theme_save) option_theme_save = strdup(CHOICES_PREFIX "Themes"); - + tree_set_icon_dir(strdup("NetSurf:Resources.Icons")); if (!option_theme || ! option_toolbar_browser || @@ -479,12 +480,16 @@ static void gui_init(int argc, char** argv) ro_gui_query_init(); /* Initialise the history subsystem */ ro_gui_history_init(); + /* Initialise toolbars */ + ro_toolbar_init(); + /* Initialise browser windows */ + ro_gui_window_initialise(); /* Done with the templates file */ wimp_close_template(); - /* Create Iconbar icon */ - ro_gui_icon_bar_create(); + /* Create Iconbar icon and menus */ + ro_gui_iconbar_initialise(); /* Finally, check Inet$Resolvers for sanity */ ro_gui_check_resolvers(); @@ -620,31 +625,6 @@ const char *ro_gui_default_language(void) } -/** - * Create an iconbar icon. - */ - -void ro_gui_icon_bar_create(void) -{ - os_error *error; - - wimp_icon_create icon = { - wimp_ICON_BAR_RIGHT, - { { 0, 0, 68, 68 }, - wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | - (wimp_BUTTON_CLICK << wimp_ICON_BUTTON_TYPE_SHIFT), - { "!netsurf" } } }; - error = xwimp_create_icon(&icon, 0); - if (error) { - LOG(("xwimp_create_icon: 0x%x: %s", - error->errnum, error->errmess)); - die(error->errmess); - } - ro_gui_wimp_event_register_mouse_click(wimp_ICON_BAR, - ro_gui_icon_bar_click); -} - - /** * Warn the user if Inet$Resolvers is not set. */ @@ -1233,43 +1213,6 @@ void ro_gui_pointer_entering_window(wimp_entering *entering) } -/** - * Handle Mouse_Click events on the iconbar icon. - */ - -bool ro_gui_icon_bar_click(wimp_pointer *pointer) -{ - char url[80]; - int key_down = 0; - - if (pointer->buttons == wimp_CLICK_MENU) { - ro_gui_menu_create(iconbar_menu, pointer->pos.x, - 96 + iconbar_menu_height, wimp_ICON_BAR, - true); - - } else if (pointer->buttons == wimp_CLICK_SELECT) { - if (option_homepage_url && option_homepage_url[0]) { - browser_window_create(option_homepage_url, NULL, 0, - true, false); - } else { - snprintf(url, sizeof url, - "file:////Docs/welcome/index_%s", - option_language); - browser_window_create(url, NULL, 0, true, false); - } - - } else if (pointer->buttons == wimp_CLICK_ADJUST) { - xosbyte1(osbyte_SCAN_KEYBOARD, 0 ^ 0x80, 0, &key_down); - if (key_down == 0) - ro_gui_menu_handle_action(pointer->w, HOTLIST_SHOW, - false); - else - ro_gui_debugwin_open(); - } - return true; -} - - /** * Handle User_Drag_Box events. */ @@ -1302,8 +1245,8 @@ void ro_gui_drag_end(wimp_dragged *drag) ro_treeview_drag_end(drag); break; - case GUI_DRAG_TOOLBAR_CONFIG: - ro_gui_theme_toolbar_editor_drag_end(drag); + case GUI_DRAG_BUTTONBAR: + ro_gui_button_bar_drag_end(drag); break; case GUI_DRAG_FRAME: @@ -1376,7 +1319,7 @@ void ro_gui_user_message(wimp_event_no event, wimp_message *message) break; case message_MENUS_DELETED: - ro_gui_menu_closed(true); + ro_gui_menu_closed(); break; case message_CLAIM_ENTITY: diff --git a/riscos/gui.h b/riscos/gui.h index 6bc1991f0..d0e842849 100644 --- a/riscos/gui.h +++ b/riscos/gui.h @@ -67,7 +67,7 @@ extern bool print_active, print_text_black; typedef enum { GUI_DRAG_NONE, GUI_DRAG_SELECTION, GUI_DRAG_DOWNLOAD_SAVE, GUI_DRAG_SAVE, GUI_DRAG_SCROLL, GUI_DRAG_STATUS_RESIZE, - GUI_DRAG_TREEVIEW, GUI_DRAG_TOOLBAR_CONFIG, + GUI_DRAG_TREEVIEW, GUI_DRAG_BUTTONBAR, GUI_DRAG_FRAME } gui_drag_type; extern gui_drag_type gui_current_drag_type; @@ -94,9 +94,6 @@ struct gui_window { char title[256]; /**< Buffer for window title. */ - int throbber; /**< Current frame of throbber animation. */ - int throbtime; /**< Time of last throbber frame. */ - int iconise_icon; /**< ID number of icon when window is iconised */ char validation[12]; /**< Validation string for colours */ @@ -136,26 +133,28 @@ bool ro_gui_download_prequit(void); void ro_gui_401login_init(void); /* in window.c */ +void ro_gui_scroll_request(wimp_scroll *scroll); +bool ro_gui_window_dataload(struct gui_window *g, wimp_message *message); +void ro_gui_window_mouse_at(struct gui_window *g, wimp_pointer *pointer); +void ro_gui_window_iconise(struct gui_window *g, + wimp_full_message_window_info *wi); +void ro_gui_window_scroll_end(struct gui_window *g, wimp_dragged *drag); +void ro_gui_window_frame_resize_end(struct gui_window *g, wimp_dragged *drag); +bool ro_gui_toolbar_dataload(struct gui_window *g, wimp_message *message); +void ro_gui_window_redraw_all(void); +void ro_gui_window_update_boxes(void); +void ro_gui_window_process_reformats(void); void ro_gui_window_quit(void); /* void ro_gui_window_close_all(void); */ #define ro_gui_window_close_all ro_gui_window_quit /* no need for a separate fn */ -void ro_gui_window_update_theme(void); -void ro_gui_window_mouse_at(struct gui_window *g, wimp_pointer *pointer); -bool ro_gui_toolbar_click(wimp_pointer *pointer); void ro_gui_throb(void); +void ro_gui_window_default_options(struct browser_window *bw); struct gui_window *ro_gui_window_lookup(wimp_w window); struct gui_window *ro_gui_toolbar_lookup(wimp_w window); -void ro_gui_scroll_request(wimp_scroll *scroll); bool ro_gui_window_to_window_pos(struct gui_window *g, int x, int y, os_coord *pos); bool ro_gui_window_to_screen_pos(struct gui_window *g, int x, int y, os_coord *pos); -bool ro_gui_window_dataload(struct gui_window *g, wimp_message *message); -bool ro_gui_toolbar_dataload(struct gui_window *g, wimp_message *message); -void ro_gui_window_process_reformats(void); -void ro_gui_window_default_options(struct browser_window *bw); -void ro_gui_window_redraw_all(void); -void ro_gui_window_prepare_navigate_all(void); browser_mouse_state ro_gui_mouse_click_state(wimp_mouse_state buttons, wimp_icon_flags type); browser_mouse_state ro_gui_mouse_drag_state(wimp_mouse_state buttons, @@ -163,12 +162,6 @@ browser_mouse_state ro_gui_mouse_drag_state(wimp_mouse_state buttons, bool ro_gui_shift_pressed(void); bool ro_gui_ctrl_pressed(void); bool ro_gui_alt_pressed(void); -void ro_gui_window_scroll_end(struct gui_window *g, wimp_dragged *drag); -void ro_gui_window_frame_resize_end(struct gui_window *g, wimp_dragged *drag); -void ro_gui_window_iconise(struct gui_window *g, - wimp_full_message_window_info *wi); -bool ro_gui_window_navigate_up(struct gui_window *g, const char *url); -void ro_gui_window_update_boxes(void); /* in history.c */ void ro_gui_history_init(void); @@ -192,7 +185,6 @@ void ro_gui_debugwin_open(void); /* in search.c */ void ro_gui_search_init(void); void ro_gui_search_prepare(struct browser_window *g); -bool ro_gui_search_prepare_menu(void); /* in print.c */ void ro_gui_print_init(void); diff --git a/riscos/gui/button_bar.c b/riscos/gui/button_bar.c new file mode 100644 index 000000000..00e357457 --- /dev/null +++ b/riscos/gui/button_bar.c @@ -0,0 +1,1231 @@ +/* + * Copyright 2004, 2005 Richard Wilson + * Copyright 2011 Stephen Fryatt + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** \file + * Button bars (implementation). + */ + +#include +#include +#include +#include +#include +#include "oslib/dragasprite.h" +#include "oslib/os.h" +#include "oslib/osspriteop.h" +#include "oslib/wimp.h" +#include "oslib/wimpspriteop.h" +#include "riscos/gui/button_bar.h" +#include "riscos/gui.h" +#include "riscos/theme.h" +#include "riscos/wimp.h" +#include "utils/log.h" +#include "utils/utils.h" + +#define BUTTONBAR_SPRITE_NAME_LENGTH 12 +#define BUTTONBAR_VALIDATION_LENGTH 40 + +struct button_bar_button { + wimp_i icon; + bool shaded; + bool separator; + + button_bar_action select_action; + button_bar_action adjust_action; + + int x_pos, y_pos; + int x_size, y_size; + + char sprite[BUTTONBAR_SPRITE_NAME_LENGTH]; + char validation[BUTTONBAR_VALIDATION_LENGTH]; + char opt_key; + const char *help_suffix; + + struct button_bar_button *bar_next; + struct button_bar_button *next; +}; + + +struct button_bar { + /** The applied theme (or NULL to use the default) */ + struct theme_descriptor *theme; + + /** The widget dimensions. */ + int x_min, y_min; + int separator_width; + int vertical_offset; + + bool separators; + + /** The window details and bar position. */ + wimp_w window; + os_box extent; + osspriteop_area *sprites; + int background; + + bool hidden; + + bool edit; + struct button_bar *edit_target; + struct button_bar *edit_source; + void (*edit_refresh)(void *); + void *edit_client_data; + + /** The list of all the defined buttons. */ + + struct button_bar_button *buttons; + + /** The list of the buttons in the current bar. */ + + struct button_bar_button *bar; +}; + +static char null_text_string[] = ""; +static char separator_name[] = "separator"; + +static struct button_bar *drag_start = NULL; +static char drag_opt = '\0'; +static bool drag_separator = false; + +/* + * Private function prototypes. + */ + +static bool ro_gui_button_bar_place_buttons(struct button_bar *button_bar); +static bool ro_gui_button_bar_icon_update(struct button_bar *button_bar); +static bool ro_gui_button_bar_icon_resize(struct button_bar *button_bar); +static void ro_gui_button_bar_sync_editors(struct button_bar *target, + struct button_bar *source); +static struct button_bar_button *ro_gui_button_bar_find_icon( + struct button_bar *button_bar, wimp_i icon); +static struct button_bar_button *ro_gui_button_bar_find_opt_key( + struct button_bar *button_bar, char opt_key); +static struct button_bar_button *ro_gui_button_bar_find_action( + struct button_bar *button_bar, button_bar_action action); +static struct button_bar_button *ro_gui_button_bar_find_coords( + struct button_bar *button_bar, os_coord pos, + bool *separator, bool *right); + +/* This is an exported interface documented in button_bar.h */ + +struct button_bar *ro_gui_button_bar_create(struct theme_descriptor *theme, + const struct button_bar_buttons buttons[]) +{ + struct button_bar *button_bar; + struct button_bar_button *icon, *new_icon; + bool failed; + int def; + + /* Allocate memory. */ + + button_bar = malloc(sizeof(struct button_bar)); + if (button_bar == NULL) { + LOG(("No memory for malloc()")); + return NULL; + } + + /* Set up default parameters. */ + + button_bar->theme = theme; + button_bar->sprites = ro_gui_theme_get_sprites(theme); + button_bar->background = wimp_COLOUR_VERY_LIGHT_GREY; + + button_bar->x_min = -1; + button_bar->y_min = -1; + button_bar->separator_width = 0; + button_bar->vertical_offset = 0; + + button_bar->separators = false; + + button_bar->window = NULL; + + button_bar->hidden = false; + + button_bar->edit = false; + button_bar->edit_target = NULL; + button_bar->edit_source = NULL; + button_bar->edit_refresh = NULL; + button_bar->edit_client_data = NULL; + + button_bar->buttons = NULL; + + /* Process the button icon definitions */ + + icon = NULL; + failed = false; + + for (def = 0; buttons[def].icon != NULL; def++) { + new_icon = malloc(sizeof(struct button_bar_button)); + if (new_icon == NULL) { + failed = true; + break; + } + + if (icon == NULL) { + button_bar->buttons = new_icon; + button_bar->bar = new_icon; + } else { + icon->next = new_icon; + icon->bar_next = new_icon; + } + icon = new_icon; + icon->next = NULL; + icon->bar_next = NULL; + + strncpy(icon->sprite, buttons[def].icon, + BUTTONBAR_SPRITE_NAME_LENGTH); + snprintf(icon->validation, BUTTONBAR_VALIDATION_LENGTH, + "R5;S%s,p%s", icon->sprite, icon->sprite); + + icon->icon = -1; + icon->shaded = false; + icon->separator = false; + + icon->select_action = buttons[def].select; + icon->adjust_action = buttons[def].adjust; + icon->opt_key = buttons[def].opt_key; + icon->help_suffix = buttons[def].help; + } + + /* Add a separator after the last entry. This will be lost if the + * buttons are subsequently set, but is used for the edit source bar. + */ + + if (icon != NULL) + icon->separator = true; + + return button_bar; +} + + +/* This is an exported interface documented in button_bar.h */ + +bool ro_gui_button_bar_link_editor(struct button_bar *target, + struct button_bar *source, void (* refresh)(void *), + void *client_data) +{ + if (target == NULL || source == NULL || + target->edit_target != NULL || + target->edit_source != NULL || + source->edit_target != NULL || + source->edit_source != NULL) + return false; + + target->edit_source = source; + source->edit_target = target; + + /* Store the callback data in the editor bar. */ + + source->edit_refresh = refresh; + source->edit_client_data = client_data; + + return true; +} + + +/* This is an exported interface documented in button_bar.h */ + +bool ro_gui_button_bar_rebuild(struct button_bar *button_bar, + struct theme_descriptor *theme, theme_style style, + wimp_w window, bool edit) +{ + struct button_bar_button *button; + os_error *error; + int height; + + + if (button_bar == NULL) + return false; + + button_bar->theme = theme; + button_bar->window = window; + button_bar->sprites = ro_gui_theme_get_sprites(theme); + button_bar->background = ro_gui_theme_get_style_element(theme, style, + THEME_ELEMENT_BACKGROUND); + + button_bar->edit = edit; + + height = 0; + button_bar->separator_width = 16; + ro_gui_wimp_get_sprite_dimensions(button_bar->sprites, separator_name, + &button_bar->separator_width, &height); + + /* If the separator height is 0, then either the sprite really is + * zero pixels high or the default was used as no sprite was found. + * Either way, we don't have a separator. + */ + + button_bar->separators = (height == 0) ? false : true; + + button = button_bar->buttons; + error = NULL; + + while (button != NULL) { + button->x_size = 0; + button->y_size = 0; + button->icon = -1; + + ro_gui_wimp_get_sprite_dimensions(button_bar->sprites, + button->sprite, + &button->x_size, &button->y_size); + + button = button->next; + } + + if (!ro_gui_button_bar_place_buttons(button_bar)) + return false; + + if (button_bar->edit && button_bar->edit_target != NULL) + ro_gui_button_bar_sync_editors(button_bar->edit_target, + button_bar); + + return ro_gui_button_bar_icon_update(button_bar); +} + + +/* This is an exported interface documented in button_bar.h */ + +bool ro_gui_button_bar_arrange_buttons(struct button_bar *button_bar, + char order[]) +{ + struct button_bar_button *button, *new; + int i; + + if (button_bar == NULL || order == NULL) + return false; + + /* Delete any existing button arrangement. */ + + button_bar->bar = NULL; + + for (button = button_bar->buttons; button != NULL; + button = button->next) { + button->bar_next = NULL; + button->separator = false; + } + + /* Parse the config string and link up the new buttons. */ + + button = NULL; + + for (i = 0; order[i] != '\0'; i++) { + if (order[i] != '|') { + new = ro_gui_button_bar_find_opt_key(button_bar, + order[i]); + + if (new != NULL) { + if (button == NULL) + button_bar->bar = new; + else + button->bar_next = new; + + button = new; + } + } else { + if (button != NULL) + button->separator = true; + } + } + + if (!ro_gui_button_bar_place_buttons(button_bar)) + return false; + + return ro_gui_button_bar_place_buttons(button_bar); +} + +/** + * Place the buttons on a button bar, taking into account the button arrangement + * and the current theme, and update the bar extent details. + * + * \param *button_bar The button bar to update. + * \return true if successful; else false. + */ + +bool ro_gui_button_bar_place_buttons(struct button_bar *button_bar) +{ + struct button_bar_button *button; + int x_pos, y_pos, height; + + if (button_bar == NULL) + return false; + + button = button_bar->bar; + x_pos = 0; + y_pos = 0; + height = 0; + + while (button != NULL) { + button->x_pos = x_pos; + button->y_pos = y_pos; + + x_pos += button->x_size; + if (button->separator) + x_pos += button_bar->separator_width; + + if (button->y_size > height) + height = button->y_size; + + button = button->bar_next; + } + + button_bar->x_min = x_pos; + button_bar->y_min = height; + + return true; +} + + +/* This is an exported interface documented in button_bar.h */ + +void ro_gui_button_bar_destroy(struct button_bar *button_bar) +{ + struct button_bar_button *button; + + if (button_bar == NULL) + return; + + /* Free the button definitions. */ + + while (button_bar->buttons != NULL) { + button = button_bar->buttons; + button_bar->buttons = button->next; + free(button); + } + + free(button_bar); +} + + +/* This is an exported interface documented in button_bar.h */ + +bool ro_gui_button_bar_get_dims(struct button_bar *button_bar, + int *width, int *height) +{ + if (button_bar == NULL) + return false; + + if (button_bar->x_min != -1 && button_bar->y_min != -1) { + if (width != NULL) + *width = button_bar->x_min; + if (height != NULL) + *height = button_bar->y_min; + + return true; + } + + return false; +} + + +/* This is an exported interface documented in button_bar.h */ + +bool ro_gui_button_bar_set_extent(struct button_bar *button_bar, + int x0, int y0, int x1, int y1) +{ + if (button_bar == NULL) + return false; + + if ((x1 - x0) < button_bar->x_min || (y1 - y0) < button_bar->y_min) + return false; + + if (button_bar->extent.x0 == x0 && button_bar->extent.y0 == y0 && + button_bar->extent.x1 == x1 && + button_bar->extent.y1 == y1) + return true; + + /* Redraw the relevant bits of the toolbar. We can't optimise for + * stretching the X-extent, as this probably means the button + * arrangement has changed which necessitates a full redraw anyway. + */ + + if (button_bar->window != NULL) { + xwimp_force_redraw(button_bar->window, + button_bar->extent.x0, button_bar->extent.y0, + button_bar->extent.x1, button_bar->extent.y1); + xwimp_force_redraw(button_bar->window, x0, y0, x1, y1); + } + + button_bar->extent.x0 = x0; + button_bar->extent.y0 = y0; + button_bar->extent.x1 = x1; + button_bar->extent.y1 = y1; + + if ((y1 - y0) > button_bar->y_min) + button_bar->vertical_offset = + ((y1 - y0) - button_bar->y_min) / 2; + else + button_bar->vertical_offset = 0; + + return ro_gui_button_bar_icon_resize(button_bar); +} + + +/** + * Update the icons on a button bar, creating or deleting them from the window + * as necessary. + */ + +bool ro_gui_button_bar_icon_update(struct button_bar *button_bar) +{ + wimp_icon_create icon; + struct button_bar_button *button, *b; + os_error *error; + bool on_bar; + + + if (button_bar == NULL || button_bar->window == NULL) + return (button_bar == NULL) ? false : true; + + button = button_bar->buttons; + + while (button != NULL) { + on_bar = false; + + /* Check if the icon is currently on the bar. */ + + for (b = button_bar->bar; b != NULL; b = b->bar_next) { + if (b == button) { + on_bar = true; + break; + } + } + + if (on_bar && !button_bar->hidden && button->icon == -1) { + icon.w = button_bar->window; + icon.icon.extent.x0 = 0; + icon.icon.extent.y0 = 0; + icon.icon.extent.x1 = 0; + icon.icon.extent.y1 = 0; + icon.icon.flags = wimp_ICON_TEXT | wimp_ICON_SPRITE | + wimp_ICON_INDIRECTED | + wimp_ICON_HCENTRED | + wimp_ICON_VCENTRED | + (button_bar->background + << wimp_ICON_BG_COLOUR_SHIFT); + icon.icon.data.indirected_text.size = 1; + + /* We don't actually shade buttons unless there's no + * editor active or this is the source bar. + */ + + if (button->shaded && (!button_bar->edit || + button_bar->edit_target != NULL)) + icon.icon.flags |= wimp_ICON_SHADED; + + if (button_bar->edit) + icon.icon.flags |= (wimp_BUTTON_CLICK_DRAG << + wimp_ICON_BUTTON_TYPE_SHIFT); + else + icon.icon.flags |= (wimp_BUTTON_CLICK << + wimp_ICON_BUTTON_TYPE_SHIFT); + + icon.icon.data.indirected_text.text = null_text_string; + icon.icon.data.indirected_text.validation = + button->validation; + + error = xwimp_create_icon(&icon, &button->icon); + if (error) { + LOG(("xwimp_create_icon: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + button->icon = -1; + return false; + } + } else if ((!on_bar || button_bar->hidden) + && button->icon != -1) { + error = xwimp_delete_icon(button_bar->window, + button->icon); + if (error != NULL) { + LOG(("xwimp_delete_icon: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return false; + } + + button->icon = -1; + } + + button = button->next; + } + + return ro_gui_button_bar_icon_resize(button_bar); +} + + +/** + * Position the icons in the button bar to take account of the currently + * configured extent. + * + * \param *button_bar The button bar to update. + * \return true if successful; else false. + */ + +bool ro_gui_button_bar_icon_resize(struct button_bar *button_bar) +{ + os_error *error; + struct button_bar_button *button; + + if (button_bar == NULL || button_bar->hidden) + return (button_bar == NULL) ? false : true; + + /* Reposition all the icons. */ + + button = button_bar->bar; + + while (button != NULL) { + if(button->icon != -1) { + error = xwimp_resize_icon(button_bar->window, + button->icon, + button_bar->extent.x0 + button->x_pos, + button_bar->extent.y0 + + button_bar->vertical_offset + + button->y_pos, + button_bar->extent.x0 + button->x_pos + + button->x_size, + button_bar->extent.y0 + + button_bar->vertical_offset + + button->y_pos + + button->y_size); + if (error != NULL) { + LOG(("xwimp_resize_icon: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + button->icon = -1; + return false; + } + } + + button = button->bar_next; + } + + return true; +} + + +/* This is an exported interface documented in button_bar.h */ + +bool ro_gui_button_bar_hide(struct button_bar *button_bar, bool hide) +{ + if (button_bar == NULL || button_bar->hidden == hide) + return (button_bar == NULL) ? false : true; + + button_bar->hidden = hide; + + return ro_gui_button_bar_icon_update(button_bar); +} + + +/* This is an exported interface documented in button_bar.h */ + +bool ro_gui_button_bar_shade_button(struct button_bar *button_bar, + button_bar_action action, bool shaded) +{ + struct button_bar_button *button; + + if (button_bar == NULL) + return false; + + button = ro_gui_button_bar_find_action(button_bar, action); + if (button == NULL) + return false; + + if (button->shaded == shaded) + return true; + + button->shaded = shaded; + + /* We don't actually shade buttons unless there's no editor active + * or this is the source bar. + */ + + if (button->icon != -1 && + (!button_bar->edit || button_bar->edit_target != NULL)) + ro_gui_set_icon_shaded_state(button_bar->window, button->icon, + shaded); + + return true; +} + + +/* This is an exported interface documented in button_bar.h */ + +void ro_gui_button_bar_redraw(struct button_bar *button_bar, + wimp_draw *redraw) +{ + wimp_icon icon; + struct button_bar_button *button; + + /* Test for a valid button bar, and then check that the redraw box + * coincides with the bar's extent. + */ + + if (button_bar == NULL || button_bar->hidden || + (redraw->clip.x0 - (redraw->box.x0 - redraw->xscroll)) + > button_bar->extent.x1 || + (redraw->clip.y0 - (redraw->box.y1 - redraw->yscroll)) + > button_bar->extent.y1 || + (redraw->clip.x1 - (redraw->box.x0 - redraw->xscroll)) + < button_bar->extent.x0 || + (redraw->clip.y1 - (redraw->box.y1 - redraw->yscroll)) + < button_bar->extent.y0 || + (!button_bar->edit && !button_bar->separators)) + return; + + icon.flags = wimp_ICON_SPRITE | wimp_ICON_INDIRECTED | + wimp_ICON_HCENTRED | wimp_ICON_VCENTRED; + if (button_bar->edit) + icon.flags |= wimp_ICON_BORDER | wimp_COLOUR_DARK_GREY << + wimp_ICON_FG_COLOUR_SHIFT; + if (!button_bar->separators) + icon.flags |= wimp_ICON_FILLED | wimp_COLOUR_LIGHT_GREY << + wimp_ICON_BG_COLOUR_SHIFT; + icon.data.indirected_sprite.id = (osspriteop_id) separator_name; + icon.data.indirected_sprite.area = button_bar->sprites; + icon.data.indirected_sprite.size = 12; + icon.extent.y0 = button_bar->extent.y0 + button_bar->vertical_offset; + icon.extent.y1 = icon.extent.y0 + button_bar->y_min; + + for (button = button_bar->bar; button != NULL; + button = button->bar_next) { + if (button->separator) { + icon.extent.x0 = button_bar->extent.x0 + + button->x_pos + button->x_size; + icon.extent.x1 = icon.extent.x0 + + button_bar->separator_width; + xwimp_plot_icon(&icon); + } + } +} + + +/* This is an exported interface documented in button_bar.h */ + +bool ro_gui_button_bar_click(struct button_bar *button_bar, + wimp_pointer *pointer, wimp_window_state *state, + button_bar_action *action) +{ + struct button_bar_button *button; + os_coord pos; + os_box box; + os_error *error; + char *sprite; + + if (button_bar == NULL || button_bar->hidden) + return false; + + /* Check that the click was within our part of the window. */ + + pos.x = pointer->pos.x - state->visible.x0 + state->xscroll; + pos.y = pointer->pos.y - state->visible.y1 + state->yscroll; + + if (pos.x < button_bar->extent.x0 || pos.x > button_bar->extent.x1 || + pos.y < button_bar->extent.y0 || + pos.y > button_bar->extent.y1) + return false; + + if (button_bar->edit && pointer->buttons == wimp_DRAG_SELECT) { + /* This is an editor click, so we need to check for drags on + * icons (buttons) and work area (separators). + */ + + button = ro_gui_button_bar_find_coords(button_bar, pos, + &drag_separator, NULL); + + if (button != NULL && (!button->shaded || drag_separator || + button_bar->edit_source != NULL)) { + gui_current_drag_type = GUI_DRAG_BUTTONBAR; + + drag_start = button_bar; + drag_opt = button->opt_key; + + if (drag_separator) { + box.x0 = pointer->pos.x - + button_bar->separator_width / 2; + box.x1 = box.x0 + button_bar->separator_width; + sprite = separator_name; + } else { + box.x0 = pointer->pos.x - button->x_size / 2; + box.x1 = box.x0 + button->x_size; + sprite = button->sprite; + } + + box.y0 = pointer->pos.y - button->y_size / 2; + box.y1 = box.y0 + button->y_size; + + error = xdragasprite_start(dragasprite_HPOS_CENTRE | + dragasprite_VPOS_CENTRE | + dragasprite_BOUND_SPRITE | + dragasprite_BOUND_TO_WINDOW | + dragasprite_DROP_SHADOW, + button_bar->sprites, + sprite, &box, NULL); + if (error) + LOG(("xdragasprite_start: 0x%x: %s", + error->errnum, error->errmess)); + + return true; + } + + } else if (!button_bar->edit && pointer->i != -1 && + (pointer->buttons == wimp_CLICK_SELECT || + pointer->buttons == wimp_CLICK_ADJUST)) { + /* This isn't an editor click, so we're only interested in + * Select or Adjust clicks that occur on physical icons. + */ + + button = ro_gui_button_bar_find_icon(button_bar, pointer->i); + + if (button != NULL) { + if (action != NULL) { + switch (pointer->buttons) { + case wimp_CLICK_SELECT: + *action = button->select_action; + break; + case wimp_CLICK_ADJUST: + *action = button->adjust_action; + break; + default: + break; + } + } + return true; + } + } + + return false; +} + + +/* This is an exported interface documented in button_bar.h */ + +bool ro_gui_button_bar_help_suffix(struct button_bar *button_bar, wimp_i i, + os_coord *mouse, wimp_window_state *state, + wimp_mouse_state buttons, const char **suffix) +{ + os_coord pos; + struct button_bar_button *button; + + if (button_bar == NULL || button_bar->hidden) + return false; + + /* Check that the click was within our part of the window. */ + + pos.x = mouse->x - state->visible.x0 + state->xscroll; + pos.y = mouse->y - state->visible.y1 + state->yscroll; + + if (pos.x < button_bar->extent.x0 || pos.x > button_bar->extent.x1 || + pos.y < button_bar->extent.y0 || + pos.y > button_bar->extent.y1) + return false; + + /* Look up and return the help suffix assocuated with the button. */ + + button = ro_gui_button_bar_find_icon(button_bar, i); + + if (button != NULL) + *suffix = button->help_suffix; + else + *suffix = ""; + + return true; +} + + +/* This is an exported interface documented in button_bar.h */ + +void ro_gui_button_bar_drag_end(wimp_dragged *drag) +{ + struct button_bar *drag_end = NULL; + struct button_bar *source = NULL, *target = NULL; + struct button_bar_button *button, *drop, *previous; + bool right, separator; + wimp_window_state state; + wimp_pointer pointer; + os_coord pos; + os_error *error; + + xdragasprite_stop(); + gui_current_drag_type = GUI_DRAG_NONE; + + if (drag_start == NULL) + return; + + /* Sort out the window coordinates of the drag end. */ + + error = xwimp_get_pointer_info(&pointer); + if (error) { + LOG(("xwimp_get_pointer_info: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return; + } + + assert(pointer.w = drag_start->window); + + state.w = drag_start->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; + } + + pos.x = pointer.pos.x - state.visible.x0 + state.xscroll; + pos.y = pointer.pos.y - state.visible.y1 + state.yscroll; + + /* Work out the destination bar, and establish source and target. */ + + if (drag_start->edit_target != NULL) { + source = drag_start; + target = drag_start->edit_target; + if (pos.x >= target->extent.x0 && pos.x <= target->extent.x1 && + pos.y >= target->extent.y0 && + pos.y <= target->extent.y1) + drag_end = target; + } else if (drag_start->edit_source != NULL) { + source = drag_start->edit_source; + target = drag_start; + if (pos.x >= target->extent.x0 && pos.x <= target->extent.x1 && + pos.y >= target->extent.y0 && + pos.y <= target->extent.y1) + drag_end = target; + /* drag_end == source and drag_end == NULL are both equivalent + * as far as the following code are concerned, and we don't need + * to identify either case. */ + } + + button = ro_gui_button_bar_find_opt_key(target, drag_opt); + assert(button != NULL); + + /* The drag finished in the target bar, so find out where. */ + + if (drag_end == target) { + drop = ro_gui_button_bar_find_coords(target, pos, + &separator, &right); + } else { + drop = NULL; + } + + /* If the button is dropped on itself, there's no change and it's + * less messy to get out now. + */ + + if (drag_start == target && drag_end == target && button == drop) { + drag_start = NULL; + return; + } + + /* The drag started in the target bar, so remove the dragged button. */ + + if (drag_start == target) { + if (drag_separator) { + button->separator = false; + } else if (target->bar == button) { + target->bar = button->bar_next; + } else { + for (previous = target->bar; previous != NULL && + previous->bar_next != button; + previous = previous->bar_next); + assert(previous != NULL); + previous->bar_next = button->bar_next; + if (button->separator) // ?? + previous->separator = true; // ?? + } + } + + /* The drag ended in the target bar, so add the dragged button in. */ + + if (drop != NULL) { + if (right) { + if (drag_separator) { + drop->separator = true; + } else { + button->bar_next = drop->bar_next; + drop->bar_next = button; + if (drop->separator && !separator) { + drop->separator = false; + button->separator = true; + } else { + button->separator = false; + } + } + } else if (target->bar == drop && !drag_separator) { + button->separator = false; + button->bar_next = target->bar; + target->bar = button; + } else if (target->bar != drop) { + for (previous = target->bar; previous != NULL && + previous->bar_next != drop; + previous = previous->bar_next); + assert(previous != NULL); + + if (drag_separator) { + previous->separator = true; + } else { + if (separator) { + previous->separator = false; + button->separator = true; + } else { + button->separator = false; + } + button->bar_next = previous->bar_next; + previous->bar_next = button; + } + } + } + + /* Reposition the buttons and force our client to update. */ + + ro_gui_button_bar_place_buttons(target); + ro_gui_button_bar_icon_update(target); + ro_gui_button_bar_sync_editors(target, source); + + xwimp_force_redraw(target->window, + target->extent.x0, target->extent.y0, + target->extent.x1, target->extent.y1); + + if (source->edit_refresh != NULL) + source->edit_refresh(source->edit_client_data); + + drag_start = NULL; +} + + +/** + * Synchronise the shading of a button bar editor source bar with the currently + * defined buttons in its target bar. + * + * \param *target The editor target bar. + * \param *source The editor source bar. + */ + +void ro_gui_button_bar_sync_editors(struct button_bar *target, + struct button_bar *source) +{ + struct button_bar_button *sb, *tb; + + if (source == NULL || target == NULL) + return; + + /* Unshade all of the buttons in the source bar. */ + + for (sb = source->bar; sb != NULL; sb = sb->bar_next) + sb->shaded = false; + + /* Step through the target bar and shade each corresponding + * button in the source. + */ + + for (tb = target->bar; tb != NULL; tb = tb->bar_next) { + sb = ro_gui_button_bar_find_opt_key(source, tb->opt_key); + + if (sb != NULL) + sb->shaded = true; + } + + /* Phyically shade the necessary buttons in the toolbar. */ + + for (sb = source->bar; sb != NULL; sb = sb->bar_next) + if (sb->icon != -1) + ro_gui_set_icon_shaded_state(source->window, sb->icon, + sb->shaded); +} + + +/* This is an exported interface documented in button_bar.h */ + +char *ro_gui_button_bar_get_config(struct button_bar *button_bar) +{ + struct button_bar_button *button; + size_t size; + char *config; + int i; + + if (button_bar == NULL) + return NULL; + + for (size = 1, button = button_bar->bar; button != NULL; + button = button->bar_next) { + size++; + if (button->separator) + size++; + } + + config = malloc(size); + if (config == NULL) { + LOG(("No memory for malloc()")); + warn_user("NoMemory", 0); + return NULL; + } + + for (i = 0, button = button_bar->bar; button != NULL; + button = button->bar_next) { + config[i++] = button->opt_key; + if (button->separator) + config[i++] = '|'; + } + + config[i] = '\0'; + + return config; +} + + +/** + * Find a button bar icon definition from an icon handle. + * + * \param *button_bar The button bar to use. + * \param icon The icon handle. + * \return Pointer to the button bar icon, or NULL. + */ + +struct button_bar_button *ro_gui_button_bar_find_icon( + struct button_bar *button_bar, wimp_i icon) +{ + struct button_bar_button *button; + + if (button_bar == NULL || icon == -1) + return NULL; + + button = button_bar->buttons; + + while (button != NULL && button->icon != icon) + button = button->next; + + return button; +} + + +/** + * Find a button bar icon definition from an options key code. + * + * \param *button_bar The button bar to use. + * \param opt_key The option key character code. + * \return Pointer to the button bar icon, or NULL. + */ + +struct button_bar_button *ro_gui_button_bar_find_opt_key( + struct button_bar *button_bar, char opt_key) +{ + struct button_bar_button *button; + + if (button_bar == NULL) + return NULL; + + button = button_bar->buttons; + + while (button != NULL && button->opt_key != opt_key) + button = button->next; + + return button; +} + + +/** + * Find a button bar icon definition from an action code. + * + * \param *button_bar The button bar to use. + * \param action The button action to find. + * \return Pointer to the button bar icon, or NULL. + */ + +struct button_bar_button *ro_gui_button_bar_find_action( + struct button_bar *button_bar, button_bar_action action) +{ + struct button_bar_button *button; + + if (button_bar == NULL) + return NULL; + + button = button_bar->buttons; + + while (button != NULL && + button->select_action != action && + button->adjust_action != action) + button = button->next; + + return button; +} + + +/** + * Find a button bar icon definition from coordinates. + * + * \param *button_bar The button bar to use. + * \param pos The coordinates to find, work area relative. + * \param *separator Returns true if the associated separator was + * matched; else false. + * \param *right Returns true if the coordinates were in the + * right hand side of the target; else false. + * \return Pointer to the button bar icon, or NULL. + */ + +struct button_bar_button *ro_gui_button_bar_find_coords( + struct button_bar *button_bar, os_coord pos, + bool *separator, bool *right) +{ + struct button_bar_button *button; + int x0, y0, x1, y1; + + if (button_bar == NULL) + return NULL; + + button = button_bar->bar; + + while (button != NULL) { + /* Match button extents. */ + + x0 = button_bar->extent.x0 + button->x_pos; + y0 = button_bar->extent.y0 + button->y_pos; + x1 = x0 + button->x_size; + y1 = y0 + button->y_size; + + if (pos.x > x0 && pos.y > y0 && pos.x < x1 && pos.y < y1) { + if (separator != NULL) + *separator = false; + + if (right != NULL) + *right = (pos.x > x0 + button->x_size/2) ? + true : false; + return button; + } + + x0 = x1; + x1 = x0 + button_bar->separator_width; + + /* Match separator extents. */ + + if (pos.x > x0 && pos.y > y0 && pos.x < x1 && pos.y < y1 && + button->separator) { + if (separator != NULL) + *separator = true; + + if (right != NULL) + *right = (x0 + button_bar->separator_width/2) ? + true : false; + return button; + } + + button = button->bar_next; + } + + return NULL; +} + diff --git a/riscos/gui/button_bar.h b/riscos/gui/button_bar.h new file mode 100644 index 000000000..d92428859 --- /dev/null +++ b/riscos/gui/button_bar.h @@ -0,0 +1,314 @@ +/* + * Copyright 2005 Richard Wilson + * Copyright 2011 Stephen Fryatt + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** \file + * Button bars (interface). + */ + +#ifndef _NETSURF_RISCOS_BUTTONBAR_H_ +#define _NETSURF_RISCOS_BUTTONBAR_H_ + +#include +#include "riscos/theme.h" + +/* A list of possible toolbar actions. */ + +typedef enum { + TOOLBAR_BUTTON_NONE = 0, /* Special case: no action */ + TOOLBAR_BUTTON_BACK, + TOOLBAR_BUTTON_BACK_NEW, + TOOLBAR_BUTTON_UP, + TOOLBAR_BUTTON_UP_NEW, + TOOLBAR_BUTTON_FORWARD, + TOOLBAR_BUTTON_FORWARD_NEW, + TOOLBAR_BUTTON_STOP, + TOOLBAR_BUTTON_RELOAD, + TOOLBAR_BUTTON_RELOAD_ALL, + TOOLBAR_BUTTON_HOME, + TOOLBAR_BUTTON_HISTORY_LOCAL, + TOOLBAR_BUTTON_HISTORY_GLOBAL, + TOOLBAR_BUTTON_SAVE_SOURCE, + TOOLBAR_BUTTON_SAVE_COMPLETE, + TOOLBAR_BUTTON_PRINT, + TOOLBAR_BUTTON_BOOKMARK_OPEN, + TOOLBAR_BUTTON_BOOKMARK_ADD, + TOOLBAR_BUTTON_SCALE, + TOOLBAR_BUTTON_SEARCH, + TOOLBAR_BUTTON_DELETE, + TOOLBAR_BUTTON_EXPAND, + TOOLBAR_BUTTON_COLLAPSE, + TOOLBAR_BUTTON_OPEN, + TOOLBAR_BUTTON_CLOSE, + TOOLBAR_BUTTON_LAUNCH, + TOOLBAR_BUTTON_CREATE +} button_bar_action; + +/* Button bar button source definitions. + * + * Help tokens are added to the help prefix for the given toolbar by the + * help system, and correspond to the hard-coded icon numbers that were + * assigned to the different buttons in the original toolbar implementation. + * If the Messages file can be updated, these can change to something more + * meaningful. + */ + +struct button_bar_buttons { + const char *icon; /**< The sprite used for the icon. */ + button_bar_action select; /**< The action for select clicks. */ + button_bar_action adjust; /**< The action for Adjust clicks. */ + const char opt_key; /**< The char used in option strings. */ + const char *help; /**< The interactive help token. */ +}; + +/* \TODO -- Move these to the correct modules. + */ + +static const struct button_bar_buttons brower_toolbar_buttons[] = { + {"back", TOOLBAR_BUTTON_BACK, TOOLBAR_BUTTON_BACK_NEW, '0', "0"}, + {"up", TOOLBAR_BUTTON_UP, TOOLBAR_BUTTON_UP_NEW, 'b', "11"}, + {"forward", TOOLBAR_BUTTON_FORWARD, TOOLBAR_BUTTON_FORWARD_NEW, '1', "1"}, + {"stop", TOOLBAR_BUTTON_STOP, TOOLBAR_BUTTON_NONE, '2', "2"}, + {"reload", TOOLBAR_BUTTON_RELOAD, TOOLBAR_BUTTON_RELOAD_ALL, '3', "3"}, + {"home", TOOLBAR_BUTTON_HOME, TOOLBAR_BUTTON_NONE, '4', "4"}, + {"history", TOOLBAR_BUTTON_HISTORY_LOCAL, TOOLBAR_BUTTON_HISTORY_GLOBAL, '5', "5"}, + {"save", TOOLBAR_BUTTON_SAVE_SOURCE, TOOLBAR_BUTTON_SAVE_COMPLETE, '6', "6"}, + {"print", TOOLBAR_BUTTON_PRINT, TOOLBAR_BUTTON_NONE, '7', "7"}, + {"hotlist", TOOLBAR_BUTTON_BOOKMARK_OPEN, TOOLBAR_BUTTON_BOOKMARK_ADD, '8', "8"}, + {"scale", TOOLBAR_BUTTON_SCALE, TOOLBAR_BUTTON_NONE, '9', "9"}, + {"search", TOOLBAR_BUTTON_SEARCH, TOOLBAR_BUTTON_NONE, 'a', "10"}, + {NULL, TOOLBAR_BUTTON_NONE, TOOLBAR_BUTTON_NONE, '\0', ""} +}; + +static const struct button_bar_buttons cookies_toolbar_buttons[] = { + {"delete", TOOLBAR_BUTTON_DELETE, TOOLBAR_BUTTON_NONE, '0', "0"}, + {"expand", TOOLBAR_BUTTON_EXPAND, TOOLBAR_BUTTON_COLLAPSE, '1', "1"}, + {"open", TOOLBAR_BUTTON_OPEN, TOOLBAR_BUTTON_CLOSE, '2', "2"}, + {NULL, TOOLBAR_BUTTON_NONE, TOOLBAR_BUTTON_NONE, '\0', ""} +}; + +static const struct button_bar_buttons global_history_toolbar_buttons[] = { + {"delete", TOOLBAR_BUTTON_DELETE, TOOLBAR_BUTTON_NONE, '0', "0"}, + {"expand", TOOLBAR_BUTTON_EXPAND, TOOLBAR_BUTTON_COLLAPSE, '1', "1"}, + {"open", TOOLBAR_BUTTON_OPEN, TOOLBAR_BUTTON_CLOSE, '2', "2"}, + {"launch", TOOLBAR_BUTTON_LAUNCH, TOOLBAR_BUTTON_NONE, '3', "3"}, + {NULL, TOOLBAR_BUTTON_NONE, TOOLBAR_BUTTON_NONE, '\0', ""} +}; + +static const struct button_bar_buttons hotlist_toolbar_buttons[] = { + {"delete", TOOLBAR_BUTTON_DELETE, TOOLBAR_BUTTON_NONE, '0', "0"}, + {"expand", TOOLBAR_BUTTON_EXPAND, TOOLBAR_BUTTON_COLLAPSE, '1', "1"}, + {"open", TOOLBAR_BUTTON_OPEN, TOOLBAR_BUTTON_CLOSE, '2', "2"}, + {"launch", TOOLBAR_BUTTON_LAUNCH, TOOLBAR_BUTTON_NONE, '3', "3"}, + {"create", TOOLBAR_BUTTON_CREATE, TOOLBAR_BUTTON_NONE, '4', "4"}, + {NULL, TOOLBAR_BUTTON_NONE, TOOLBAR_BUTTON_NONE, '\0', ""} +}; + +struct button_bar; + + +/** + * Create a new button bar widget. + * + * \param *theme The theme to apply (or NULL for the default). + * \param buttons[] An array of button definitions for the bar. + * \return A button bar handle, or NULL on failure. + */ + +struct button_bar *ro_gui_button_bar_create(struct theme_descriptor *theme, + const struct button_bar_buttons buttons[]); + + +/** + * Link two button bars together: the target being the active bar, and the + * source being the editing bar used to supply valid buttons. The bars are + * checked to ensure that they are not already part of an edit pair, but are + * not checked for button-compatibility. + * + * \param *target The target button bar. + * \param *source The source button bar. + * \return true if successful; else false. + */ + +bool ro_gui_button_bar_link_editor(struct button_bar *target, + struct button_bar *source, void (* refresh)(void *), + void *client_data); + +/** + * Place a button bar into a toolbar window and initialise any theme-specific + * settings. Any previous incarnation of the bar will be forgotten: this + * is for use when a new toolbar is being created, or when a toolbar has been + * deleted and rebuilt following a theme change. + * + * \param *button_bar The button bar to rebuild. + * \param *theme The theme to apply (or NULL for current). + * \param style The theme style to apply. + * \param window The window that the bar is in. + * \param edit The edit mode of the button bar. + * \return true on success; else false. + */ + +bool ro_gui_button_bar_rebuild(struct button_bar *button_bar, + struct theme_descriptor *theme, theme_style style, + wimp_w window, bool edit); + + +/** + * Arrange buttons on a button bar, using an order string to specify the + * required button and separator layout. + * + * \param *button_bar The button bar to update. + * \param order[] The button order configuration string. + * \return true if successful; else false. + */ + +bool ro_gui_button_bar_arrange_buttons(struct button_bar *button_bar, + char order[]); + + +/** + * Destroy a button bar widget. + * + * \param *button_bar The button bar to destroy. + */ + +void ro_gui_button_bar_destroy(struct button_bar *button_bar); + + +/** + * Return the MINIMUM dimensions required by the button bar, in RO units, + * allowing for the current theme. + * + * \param *button_bar The button bar of interest. + * \param *width Return the required width. + * \param *height Return the required height. + * \return true if values are returned; else false. + */ + +bool ro_gui_button_bar_get_dims(struct button_bar *button_bar, + int *width, int *height); + + +/** + * Set or update the dimensions to be used by the button bar, in RO units. + * If these are greater than the minimum required, the button bar will fill + * the extended space; if less, the call will fail. + * + * \param *button_bar The button bar to update. + * \param x0 The minimum X window position. + * \param y0 The minimum Y window position. + * \param x1 The maximum X window position. + * \param y1 The maximum Y window position. + * \return true if size updated; else false. + */ + +bool ro_gui_button_bar_set_extent(struct button_bar *button_bar, + int x0, int y0, int x1, int y1); + + +/** + * Show or hide a button bar. + * + * \param *button_bar The button bar to hide. + * \param hide true to hide the bar; false to show it. + * \return true if successful; else false. + */ + +bool ro_gui_button_bar_hide(struct button_bar *button_bar, bool hide); + + +/** + * Shade or unshade a button in a bar corresponding to the given action. + * + * \param *button_bar The button bar to update. + * \param action The action to update. + * \param shaded true to shade the button; false to unshade. + * \return true if successful; else false. + */ + +bool ro_gui_button_bar_shade_button(struct button_bar *button_bar, + button_bar_action action, bool shaded); + + +/** + * Handle redraw event rectangles in a button bar. + * + * \param *button_bar The button bar to use. + * \param *redraw The Wimp redraw rectangle to process. + */ + +void ro_gui_button_bar_redraw(struct button_bar *button_bar, + wimp_draw *redraw); + + +/** + * Handle mouse clicks in a button bar. + * + * \param *button_bar The button bar to use. + * \param *pointer The Wimp mouse click event data. + * \param *state The toolbar window state. + * \param *action Returns the selected action, or + * TOOLBAR_BUTTON_NONE. + * \return true if the event was handled exclusively; + * else false. + */ + +bool ro_gui_button_bar_click(struct button_bar *button_bar, + wimp_pointer *pointer, wimp_window_state *state, + button_bar_action *action); + + +/** + * Translate mouse data into an interactive help message for a button bar. + * + * \param *button_bar The button bar to process. + * \param i The wimp icon under the pointer. + * \param *mouse The mouse position. + * \param *state The toolbar window state. + * \param buttons The mouse button state. + * \param **suffix Return a help token suffix, or "" for none. + * \return true if handled exclusively; else false. + */ + +bool ro_gui_button_bar_help_suffix(struct button_bar *button_bar, wimp_i i, + os_coord *mouse, wimp_window_state *state, + wimp_mouse_state buttons, const char **suffix); + + +/** + * Terminate a drag event that was initiated by a button bar. + * + * \param *drag The drag event data. + */ + +void ro_gui_button_bar_drag_end(wimp_dragged *drag); + + +/** + * Return a config string reflecting the configured order of buttons + * and spacers. The string is allocated with malloc(), and should be + * free()d after use. + * + * \param *button_bar The button bar of interest. + * \return Pointer to a config string, or NULL on failure. + */ + +char *ro_gui_button_bar_get_config(struct button_bar *button_bar); + +#endif + diff --git a/riscos/gui/throbber.c b/riscos/gui/throbber.c new file mode 100644 index 000000000..05860a923 --- /dev/null +++ b/riscos/gui/throbber.c @@ -0,0 +1,419 @@ +/* + * Copyright 2004, 2005 Richard Wilson + * Copyright 2011 Stephen Fryatt + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** \file + * Throbber (implementation). + */ + +#include +#include +#include +#include +#include +#include +#include "oslib/os.h" +#include "oslib/osspriteop.h" +#include "oslib/wimp.h" +#include "riscos/gui/throbber.h" +#include "riscos/theme.h" +#include "riscos/wimp.h" +#include "utils/log.h" +#include "utils/utils.h" + +#define THROBBER_SPRITE_NAME_LENGTH 12 +#define THROBBER_ANIMATE_INTERVAL 10 + +struct throbber { + /** The applied theme (or NULL to use the default) */ + struct theme_descriptor *theme; + + /** The widget dimensions. */ + int x_min, y_min; + + /** The window and icon details. */ + wimp_w window; + wimp_i icon; + os_box extent; + osspriteop_area *sprites; + bool hidden; + bool shaded; + + /** The animation details. */ + int max_frame; + int current_frame; + os_t last_update; + char sprite_name[THROBBER_SPRITE_NAME_LENGTH]; + bool force_redraw; +}; + +/* + * Private function prototypes. + */ + +static bool ro_gui_throbber_icon_update(struct throbber *throbber); +static bool ro_gui_throbber_icon_resize(struct throbber *throbber); + +/* This is an exported interface documented in throbber.h */ + +struct throbber *ro_gui_throbber_create(struct theme_descriptor *theme) +{ + struct throbber *throbber; + + /* Allocate memory. */ + + throbber = malloc(sizeof(struct throbber)); + if (throbber == NULL) { + LOG(("No memory for malloc()")); + return NULL; + } + + /* Set up default parameters. If reading the throbber theme data + * fails, we give up and return a failure. + */ + + if (!ro_gui_theme_get_throbber_data(theme, &throbber->max_frame, + &throbber->x_min, &throbber->y_min, NULL, + &throbber->force_redraw)) { + free(throbber); + return NULL; + } + + throbber->sprites = ro_gui_theme_get_sprites(theme); + + throbber->theme = theme; + + throbber->extent.x0 = 0; + throbber->extent.y0 = 0; + throbber->extent.x1 = 0; + throbber->extent.y1 = 0; + + throbber->current_frame = 0; + throbber->last_update = 0; + + throbber->window = NULL; + throbber->icon = -1; + + throbber->hidden = false; + throbber->shaded = false; + + return throbber; +} + + +/* This is an exported interface documented in throbber.h */ + +bool ro_gui_throbber_rebuild(struct throbber *throbber, + struct theme_descriptor *theme, theme_style style, + wimp_w window, bool shaded) +{ + if (throbber == NULL) + return false; + + throbber->theme = theme; + throbber->window = window; + throbber->sprites = ro_gui_theme_get_sprites(theme); + + throbber->icon = -1; + + throbber->shaded = shaded; + + strcpy(throbber->sprite_name, "throbber0"); + + if (!ro_gui_theme_get_throbber_data(theme, &throbber->max_frame, + &throbber->x_min, &throbber->y_min, NULL, + &throbber->force_redraw)) { + free(throbber); + return false; + } + + return ro_gui_throbber_icon_update(throbber); +} + + +/* This is an exported interface documented in throbber.h */ + +void ro_gui_throbber_destroy(struct throbber *throbber) +{ + if (throbber == NULL) + return; + + free(throbber); +} + + +/* This is an exported interface documented in throbber.h */ + +bool ro_gui_throbber_get_dims(struct throbber *throbber, + int *width, int *height) +{ + if (throbber == NULL) + return false; + + if (throbber->x_min != -1 && throbber->y_min != -1) { + if (width != NULL) + *width = throbber->x_min; + if (height != NULL) + *height = throbber->y_min; + + return true; + } + + return false; +} + + +/* This is an exported interface documented in throbber.h */ + +bool ro_gui_throbber_set_extent(struct throbber *throbber, + int x0, int y0, int x1, int y1) +{ + if (throbber == NULL) + return false; + + if ((x1 - x0) < throbber->x_min || (y1 - y0) < throbber->y_min) + return false; + + if (throbber->extent.x0 == x0 && throbber->extent.y0 == y0 && + throbber->extent.x1 == x1 && + throbber->extent.y1 == y1) + return true; + + /* Redraw the relevant bits of the toolbar. */ + + if (throbber->window != NULL && throbber->icon != -1) { + xwimp_force_redraw(throbber->window, + throbber->extent.x0, throbber->extent.y0, + throbber->extent.x1, throbber->extent.y1); + xwimp_force_redraw(throbber->window, x0, y0, x1, y1); + } + + /* Update the throbber position */ + + throbber->extent.x0 = x0; + throbber->extent.y0 = y0; + throbber->extent.x1 = x1; + throbber->extent.y1 = y1; + + return ro_gui_throbber_icon_resize(throbber); +} + + +/** + * Create or delete a throbber's icon if required to bring it into sync with + * the current hidden setting. + * + * \param *throbber The throbber to update. + * \return true if successful; else false. + */ + +bool ro_gui_throbber_icon_update(struct throbber *throbber) +{ + wimp_icon_create icon; + os_error *error; + + if (throbber == NULL || throbber->window == NULL) + return false; + + if (!throbber->hidden && throbber->icon == -1) { + icon.w = throbber->window; + icon.icon.extent.x0 = throbber->extent.x0; + icon.icon.extent.y0 = throbber->extent.y0; + icon.icon.extent.x1 = throbber->extent.x1; + icon.icon.extent.y1 = throbber->extent.y1; + icon.icon.flags = wimp_ICON_SPRITE | wimp_ICON_INDIRECTED | + wimp_ICON_HCENTRED | wimp_ICON_VCENTRED; + icon.icon.data.indirected_sprite.id = + (osspriteop_id) throbber->sprite_name; + icon.icon.data.indirected_sprite.area = throbber->sprites; + icon.icon.data.indirected_sprite.size = + THROBBER_SPRITE_NAME_LENGTH; + + error = xwimp_create_icon(&icon, &throbber->icon); + if (error != NULL) { + LOG(("xwimp_create_icon: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + throbber->icon = -1; + return false; + } + + if (!ro_gui_throbber_icon_resize(throbber)) + return false; + } else if (throbber->hidden && throbber->icon != -1) { + error = xwimp_delete_icon(throbber->window, throbber->icon); + if (error != NULL) { + LOG(("xwimp_delete_icon: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return false; + } + + throbber->icon = -1; + } + + if (throbber->icon != -1) + ro_gui_set_icon_shaded_state(throbber->window, + throbber->icon, throbber->shaded); + + return true; +} + + +/** + * Position the icons in the throbber to take account of the currently + * configured extent. + * + * \param *throbber The throbber to update. + * \return true if successful; else false. + */ + +bool ro_gui_throbber_icon_resize(struct throbber *throbber) +{ + os_error *error; + + if (throbber->window == NULL) + return false; + + if (throbber->icon != -1) { + error = xwimp_resize_icon(throbber->window, throbber->icon, + throbber->extent.x0, throbber->extent.y0, + throbber->extent.x1, throbber->extent.y1); + if (error != NULL) { + LOG(("xwimp_resize_icon: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + throbber->icon = -1; + return false; + } + } + + return true; +} + + +/* This is an exported interface documented in throbber.h */ + +bool ro_gui_throbber_hide(struct throbber *throbber, bool hide) +{ + if (throbber == NULL || throbber->hidden == hide) + return (throbber == NULL) ? false : true; + + throbber->hidden = hide; + + return ro_gui_throbber_icon_update(throbber); +} + + +/* This is an exported interface documented in throbber.h */ + +bool ro_gui_throbber_help_suffix(struct throbber *throbber, wimp_i i, + os_coord *mouse, wimp_window_state *state, + wimp_mouse_state buttons, const char **suffix) +{ + os_coord pos; + + if (throbber == NULL || throbber->hidden) + return false; + + /* Check that the click was within our part of the window. */ + + pos.x = mouse->x - state->visible.x0 + state->xscroll; + pos.y = mouse->y - state->visible.y1 + state->yscroll; + + if (pos.x < throbber->extent.x0 || pos.x > throbber->extent.x1 || + pos.y < throbber->extent.y0 || + pos.y > throbber->extent.y1) + return false; + + /* Return a hard-coded icon number that matches the one that was + * always allocated to the throbber in a previous implementation. + * If Messages can be updated, this could be changed. + */ + + if (i == throbber->icon) + *suffix = "16"; + else + *suffix = ""; + + return true; +} + + +/* This is an exported interface documented in throbber.h */ + +bool ro_gui_throbber_animate(struct throbber *throbber) +{ + os_t t; + char sprite_name[THROBBER_SPRITE_NAME_LENGTH]; + + if (throbber == NULL || throbber->hidden) + return (throbber == NULL) ? false : true; + + xos_read_monotonic_time(&t); + + /* Drop out if we're not ready for the next frame, unless this + * call is to start animation from a stopped throbber (ie. if + * the current frame is 0). + */ + + if ((t < (throbber->last_update + THROBBER_ANIMATE_INTERVAL)) && + (throbber->current_frame > 0)) + return true; + + throbber->last_update = t; + throbber->current_frame++; + + if (throbber->current_frame > throbber->max_frame) + throbber->current_frame = 1; + + snprintf(sprite_name, THROBBER_SPRITE_NAME_LENGTH, + "throbber%i", throbber->current_frame); + ro_gui_set_icon_string(throbber->window, throbber->icon, + sprite_name, true); + + if (throbber->force_redraw) + ro_gui_force_redraw_icon(throbber->window, throbber->icon); + + return true; +} + + +/* This is an exported interface documented in throbber.h */ + +bool ro_gui_throbber_stop(struct throbber *throbber) +{ + char sprite_name[THROBBER_SPRITE_NAME_LENGTH]; + + if (throbber == NULL || throbber->hidden || + throbber->current_frame == 0) + return (throbber == FALSE) ? false : true; + + throbber->current_frame = 0; + throbber->last_update = 0; + + strcpy(sprite_name, "throbber0"); + ro_gui_set_icon_string(throbber->window, throbber->icon, + sprite_name, true); + + if (throbber->force_redraw) + ro_gui_force_redraw_icon(throbber->window, throbber->icon); + + return true; +} + diff --git a/riscos/gui/throbber.h b/riscos/gui/throbber.h new file mode 100644 index 000000000..10d39ebfd --- /dev/null +++ b/riscos/gui/throbber.h @@ -0,0 +1,144 @@ +/* + * Copyright 2005 Richard Wilson + * Copyright 2011 Stephen Fryatt + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** \file + * Throbber (interface). + */ + +#ifndef _NETSURF_RISCOS_THROBBER_H_ +#define _NETSURF_RISCOS_THROBBER_H_ + +#include +#include "riscos/theme.h" + +struct throbber; + + +/** + * Create a new throbber widget. + * + * \param *theme The theme to apply (or NULL for the default). + * \return A throbber handle, or NULL on failure. + */ + +struct throbber *ro_gui_throbber_create(struct theme_descriptor *theme); + +/** + * Place a throbber into a toolbar window and initialise any theme-specific + * settings. Any previous incarnation of the throbber will be forgotten: this + * is for use when a new toolbar is being created, or when a toolbar has been + * deleted and rebuilt following a theme change. + * + * \param *throbber The throbber to rebuild. + * \param *theme The theme to apply (or NULL for current). + * \param style The theme style to apply. + * \param window The window that the throbber is in. + * \param shaded true if the bar should be throbber; else false. + * \return true on success; else false. + */ + +bool ro_gui_throbber_rebuild(struct throbber *throbber, + struct theme_descriptor *theme, theme_style style, + wimp_w window, bool shaded); + + +/** + * Destroy a throbber widget. + * + * \param *throbber The throbber to destroy. + */ + +void ro_gui_throbber_destroy(struct throbber *throbber); + + +/** + * Return the MINIMUM dimensions required by the throbber, in RO units, + * allowing for the current theme. + * + * \param *throbber The throbber of interest. + * \param *width Return the required width. + * \param *height Return the required height. + * \return true if values are returned; else false. + */ + +bool ro_gui_throbber_get_dims(struct throbber *throbber, + int *width, int *height); + + +/** + * Set or update the dimensions to be used by the throbber, in RO units. + * If these are greater than the minimum required, the throbber will fill + * the extended space; if less, the call will fail. + * + * \param *throbber The throbber to update. + * \param width The desired width. + * \param height The desired height. + * \return true if size updated; else false. + */ + +bool ro_gui_throbber_set_extent(struct throbber *throbber, + int x0, int y0, int x1, int y1); + + +/** + * Show or hide a throbber. + * + * \param *throbber The throbber to hide. + * \param hide true to hide the throbber; false to show it. + * \return true if successful; else false. + */ + +bool ro_gui_throbber_hide(struct throbber *throbber, bool hide); + + +/** + * Translate mouse data into an interactive help message for the throbber. + * + * \param *throbber The throbber to process. + * \param i The wimp icon under the pointer. + * \param *mouse The mouse position. + * \param *state The toolbar window state. + * \param buttons The mouse button state. + * \param **suffix Return a help token suffix, or "" for none. + * \return true if handled exclusively; else false. + */ + +bool ro_gui_throbber_help_suffix(struct throbber *throbber, wimp_i i, + os_coord *screenpos, wimp_window_state *state, + wimp_mouse_state buttons, const char **suffix); + +/** + * Start or update the amimation of a throbber. + * + * \param *throbber The throbber to amimate. + */ + +bool ro_gui_throbber_animate(struct throbber *throbber); + + +/** + * Stop the amimation of a throbber. + * + * \param *throbber The throbber to amimate. + */ + +bool ro_gui_throbber_stop(struct throbber *throbber); + +#endif + diff --git a/riscos/gui/url_bar.c b/riscos/gui/url_bar.c new file mode 100644 index 000000000..df4e7c06c --- /dev/null +++ b/riscos/gui/url_bar.c @@ -0,0 +1,984 @@ +/* + * Copyright 2004, 2005 Richard Wilson + * Copyright 2011 Stephen Fryatt + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** \file + * URL bars (implementation). + */ + +#include +#include +#include +#include +#include +#include +#include "oslib/os.h" +#include "oslib/osspriteop.h" +#include "oslib/wimp.h" +#include "riscos/gui/url_bar.h" +#include "riscos/theme.h" +#include "riscos/url_suggest.h" +#include "riscos/wimp.h" +#include "riscos/wimp_event.h" +#include "utils/log.h" +#include "utils/utils.h" + +#define URLBAR_HEIGHT 52 +#define URLBAR_FAVICON_WIDTH 52 +#define URLBAR_MIN_WIDTH 52 +#define URLBAR_GRIGHT_GUTTER 8 +#define URLBAR_FAVICON_NAME_LENGTH 12 +#define URLBAR_INITIAL_LENGTH 256 +#define URLBAR_EXTEND_LENGTH 128 +#define URLBAR_FAVICON_SIZE 16 + +struct url_bar { + /** The applied theme (or NULL to use the default) */ + struct theme_descriptor *theme; + + /** The widget dimensions. */ + int x_min, y_min; + + /** The window and icon details. */ + wimp_w window; + os_box extent; + + wimp_i container_icon; + + char favicon_sprite[URLBAR_FAVICON_NAME_LENGTH]; + int favicon_type; + struct hlcache_handle *favicon_content; + os_box favicon_extent; + os_coord favicon_offset; + int favicon_width, favicon_height; + + wimp_i text_icon; + char *text_buffer; + size_t text_size; + + wimp_i suggest_icon; + int suggest_x, suggest_y; + + bool hidden; + bool display; + bool shaded; +}; + +static char text_validation[] = "Pptr_write;KN"; +static char suggest_icon[] = "gright"; +static char suggest_validation[] = "R5;Sgright,pgright"; +static char null_text_string[] = ""; + + +/* + * Private function prototypes. + */ + +static bool ro_gui_url_bar_icon_update(struct url_bar *url_bar); +static bool ro_gui_url_bar_icon_resize(struct url_bar *url_bar, bool full); + +/* This is an exported interface documented in url_bar.h */ + +struct url_bar *ro_gui_url_bar_create(struct theme_descriptor *theme) +{ + struct url_bar *url_bar; + + /* Allocate memory. */ + + url_bar = malloc(sizeof(struct url_bar)); + if (url_bar == NULL) { + LOG(("No memory for malloc()")); + return NULL; + } + + /* Set up default parameters. */ + + url_bar->theme = theme; + + url_bar->display = false; + url_bar->shaded = false; + + url_bar->x_min = URLBAR_FAVICON_WIDTH + URLBAR_MIN_WIDTH; + url_bar->y_min = URLBAR_HEIGHT; + + url_bar->extent.x0 = 0; + url_bar->extent.y0 = 0; + url_bar->extent.x1 = 0; + url_bar->extent.y1 = 0; + + url_bar->window = NULL; + url_bar->container_icon = -1; + url_bar->text_icon = -1; + url_bar->suggest_icon = -1; + + url_bar->favicon_extent.x0 = 0; + url_bar->favicon_extent.y0 = 0; + url_bar->favicon_extent.x1 = 0; + url_bar->favicon_extent.y1 = 0; + url_bar->favicon_width = 0; + url_bar->favicon_height = 0; + url_bar->favicon_content = NULL; + url_bar->favicon_type = 0; + strncpy(url_bar->favicon_sprite, "Ssmall_xxx", + URLBAR_FAVICON_NAME_LENGTH); + + url_bar->text_size = URLBAR_INITIAL_LENGTH; + url_bar->text_buffer = malloc(url_bar->text_size); + strncpy(url_bar->text_buffer, "", url_bar->text_size); + + url_bar->hidden = false; + + return url_bar; +} + + +/* This is an exported interface documented in url_bar.h */ + +bool ro_gui_url_bar_rebuild(struct url_bar *url_bar, + struct theme_descriptor *theme, theme_style style, + wimp_w window, bool display, bool shaded) +{ + if (url_bar == NULL) + return false; + + url_bar->theme = theme; + url_bar->window = window; + + url_bar->display = display; + url_bar->shaded = shaded; + + url_bar->container_icon = -1; + url_bar->text_icon = -1; + url_bar->suggest_icon = -1; + + ro_gui_wimp_get_sprite_dimensions((osspriteop_area *) -1, + suggest_icon, &url_bar->suggest_x, &url_bar->suggest_y); + + url_bar->x_min = URLBAR_FAVICON_WIDTH + URLBAR_MIN_WIDTH + + URLBAR_GRIGHT_GUTTER + url_bar->suggest_x; + url_bar->y_min = (url_bar->suggest_y > URLBAR_HEIGHT) ? + url_bar->suggest_y : URLBAR_HEIGHT; + + return ro_gui_url_bar_icon_update(url_bar); +} + + +/* This is an exported interface documented in url_bar.h */ + +void ro_gui_url_bar_destroy(struct url_bar *url_bar) +{ + if (url_bar == NULL) + return; + + free(url_bar); +} + + +/* This is an exported interface documented in url_bar.h */ + +bool ro_gui_url_bar_get_dims(struct url_bar *url_bar, + int *width, int *height) +{ + if (url_bar == NULL) + return false; + + if (url_bar->x_min != -1 && url_bar->y_min != -1) { + if (width != NULL) + *width = url_bar->x_min; + if (height != NULL) + *height = url_bar->y_min; + + return true; + } + + return false; +} + + +/* This is an exported interface documented in url_bar.h */ + +bool ro_gui_url_bar_set_extent(struct url_bar *url_bar, + int x0, int y0, int x1, int y1) +{ + bool stretch; + + if (url_bar == NULL) + return false; + + if ((x1 - x0) < url_bar->x_min || (y1 - y0) < url_bar->y_min) + return false; + + if (url_bar->extent.x0 == x0 && url_bar->extent.y0 == y0 && + url_bar->extent.x1 == x1 && + url_bar->extent.y1 == y1) + return true; + + /* If it's only the length that changes, less needs to be updated. */ + + stretch = (url_bar->extent.x0 == x0 && url_bar->extent.y0 == y0 && + url_bar->extent.y1 == y1) ? true : false; + + /* Redraw the relevant bits of the toolbar. */ + + if (url_bar->window != NULL && url_bar->container_icon != -1) { + xwimp_force_redraw(url_bar->window, + url_bar->extent.x0 + + (stretch) ? URLBAR_FAVICON_WIDTH : 0, + url_bar->extent.y0, + url_bar->extent.x1, url_bar->extent.y1); + xwimp_force_redraw(url_bar->window, + x0 + (stretch) ? URLBAR_FAVICON_WIDTH : 0, + y0, x1, y1); + } + + /* Reposition the URL bar icons. */ + + url_bar->extent.x0 = x0; + url_bar->extent.y0 = y0; + url_bar->extent.x1 = x1; + url_bar->extent.y1 = y1; + + return ro_gui_url_bar_icon_resize(url_bar, !stretch); +} + + +/** + * Create or delete a URL bar's icons if required to bring it into sync with + * the current hidden setting. + * + * \param *url_bar The URL bar to update. + * \return true if successful; else false. + */ + +bool ro_gui_url_bar_icon_update(struct url_bar *url_bar) +{ + wimp_icon_create icon; + os_error *error; + bool resize; + + if (url_bar == NULL || url_bar->window == NULL) + return false; + + icon.w = url_bar->window; + icon.icon.extent.x0 = 0; + icon.icon.extent.y0 = 0; + icon.icon.extent.x1 = 0; + icon.icon.extent.y1 = 0; + + resize = false; + + /* Create or delete the container icon. */ + + if (!url_bar->hidden && url_bar->container_icon == -1) { + icon.icon.flags = wimp_ICON_BORDER | + (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT); + error = xwimp_create_icon(&icon, &url_bar->container_icon); + if (error != NULL) { + LOG(("xwimp_create_icon: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + url_bar->container_icon = -1; + return false; + } + + resize = true; + } else if (url_bar->hidden && url_bar->container_icon != -1){ + error = xwimp_delete_icon(url_bar->window, + url_bar->container_icon); + if (error != NULL) { + LOG(("xwimp_delete_icon: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return false; + } + + url_bar->container_icon = -1; + } + + /* Create or delete the text icon. */ + + if (!url_bar->hidden && url_bar->text_icon == -1) { + icon.icon.data.indirected_text.text = url_bar->text_buffer; + icon.icon.data.indirected_text.validation = text_validation; + icon.icon.data.indirected_text.size = url_bar->text_size; + icon.icon.flags = wimp_ICON_TEXT | wimp_ICON_INDIRECTED | + wimp_ICON_VCENTRED | wimp_ICON_FILLED | + (wimp_COLOUR_BLACK << + wimp_ICON_FG_COLOUR_SHIFT); + if (url_bar->display) + icon.icon.flags |= (wimp_BUTTON_NEVER << + wimp_ICON_BUTTON_TYPE_SHIFT); + else + icon.icon.flags |= (wimp_BUTTON_WRITE_CLICK_DRAG << + wimp_ICON_BUTTON_TYPE_SHIFT); + error = xwimp_create_icon(&icon, &url_bar->text_icon); + if (error) { + LOG(("xwimp_create_icon: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + url_bar->text_icon = -1; + return false; + } + + resize = true; + } else if (url_bar->hidden && url_bar->text_icon != -1) { + error = xwimp_delete_icon(url_bar->window, + url_bar->text_icon); + if (error != NULL) { + LOG(("xwimp_delete_icon: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return false; + } + + url_bar->text_icon = -1; + } + + /* Create or delete the suggest icon. */ + + if (!url_bar->hidden && url_bar->suggest_icon == -1) { + icon.icon.data.indirected_text.text = null_text_string; + icon.icon.data.indirected_text.size = 1; + icon.icon.data.indirected_text.validation = suggest_validation; + 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); + error = xwimp_create_icon(&icon, &url_bar->suggest_icon); + if (error) { + LOG(("xwimp_create_icon: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return false; + } + + if (!url_bar->display) + ro_gui_wimp_event_register_menu_gright(url_bar->window, + wimp_ICON_WINDOW, url_bar->suggest_icon, + ro_gui_url_suggest_menu); + + if (!ro_gui_url_bar_update_urlsuggest(url_bar)) + return false; + + resize = true; + } else if (url_bar->hidden && url_bar->suggest_icon != -1) { + ro_gui_wimp_event_deregister(url_bar->window, + url_bar->suggest_icon); + error = xwimp_delete_icon(url_bar->window, + url_bar->suggest_icon); + if (error != NULL) { + LOG(("xwimp_delete_icon: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return false; + } + + url_bar->suggest_icon = -1; + } + + /* If any icons were created, resize the bar. */ + + if (resize && !ro_gui_url_bar_icon_resize(url_bar, true)) + return false; + + /* If there are any icons, apply shading as necessary. */ + + if (url_bar->container_icon != -1) + ro_gui_set_icon_shaded_state(url_bar->window, + url_bar->container_icon, url_bar->shaded); + + if (url_bar->text_icon != -1) + ro_gui_set_icon_shaded_state(url_bar->window, + url_bar->text_icon, url_bar->shaded); + + if (url_bar->suggest_icon != -1) + ro_gui_set_icon_shaded_state(url_bar->window, + url_bar->suggest_icon, url_bar->shaded); + + return true; +} + + +/** + * Position the icons in the URL bar to take account of the currently + * configured extent. + * + * \param *url_bar The URL bar to update. + * \param full true to resize everything; false to move only + * the right-hand end of the bar. + * \return true if successful; else false. + */ + +bool ro_gui_url_bar_icon_resize(struct url_bar *url_bar, bool full) +{ + int x0, y0, x1, y1; + int centre; + os_error *error; + os_coord eig = {1, 1}; + wimp_caret caret; + + if (url_bar == NULL || url_bar->window == NULL) + return false; + + /* calculate 1px in OS units */ + ro_convert_pixels_to_os_units(&eig, (os_mode) -1); + + /* The vertical centre line of the widget's extent. */ + + centre = url_bar->extent.y0 + + (url_bar->extent.y1 - url_bar->extent.y0) / 2; + + /* Position the container icon. */ + + if (url_bar->container_icon != -1) { + x0 = url_bar->extent.x0; + x1 = url_bar->extent.x1 - + url_bar->suggest_x - URLBAR_GRIGHT_GUTTER; + + y0 = centre - (URLBAR_HEIGHT / 2); + y1 = y0 + URLBAR_HEIGHT; + + error = xwimp_resize_icon(url_bar->window, + url_bar->container_icon, + x0, y0, x1, y1); + if (error != NULL) { + LOG(("xwimp_resize_icon: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + url_bar->container_icon = -1; + return false; + } + } + + /* Position the URL Suggest icon. */ + + if (url_bar->suggest_icon != -1) { + x0 = url_bar->extent.x1 - url_bar->suggest_x; + x1 = url_bar->extent.x1; + + y0 = centre - (url_bar->suggest_y / 2); + y1 = y0 + url_bar->suggest_y; + + error = xwimp_resize_icon(url_bar->window, + url_bar->suggest_icon, + x0, y0, x1, y1); + if (error != NULL) { + LOG(("xwimp_resize_icon: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + url_bar->suggest_icon = -1; + return false; + } + } + + /* Position the Text icon. */ + + if (url_bar->text_icon != -1) { + x0 = url_bar->extent.x0 + URLBAR_FAVICON_WIDTH; + x1 = url_bar->extent.x1 - eig.x - + url_bar->suggest_x - URLBAR_GRIGHT_GUTTER; + + y0 = centre - (URLBAR_HEIGHT / 2) + eig.y; + y1 = y0 + URLBAR_HEIGHT - 2 * eig.y; + + error = xwimp_resize_icon(url_bar->window, + url_bar->text_icon, + x0, y0, x1, y1); + if (error != NULL) { + LOG(("xwimp_resize_icon: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + url_bar->text_icon = -1; + return false; + } + + if (xwimp_get_caret_position(&caret) == NULL) { + if ((caret.w == url_bar->window) && + (caret.i == url_bar->text_icon)) { + xwimp_set_caret_position(url_bar->window, + url_bar->text_icon, caret.pos.x, + caret.pos.y, -1, caret.index); + } + } + } + + /* Position the Favicon icon. */ + + url_bar->favicon_extent.x0 = url_bar->extent.x0 + eig.x; + url_bar->favicon_extent.x1 = url_bar->extent.x0 + URLBAR_FAVICON_WIDTH; + url_bar->favicon_extent.y0 = centre - (URLBAR_HEIGHT / 2) + eig.y; + url_bar->favicon_extent.y1 = url_bar->favicon_extent.y0 + URLBAR_HEIGHT + - 2 * eig.y; + + return true; +} + + +/* This is an exported interface documented in url_bar.h */ + +bool ro_gui_url_bar_hide(struct url_bar *url_bar, bool hide) +{ + if (url_bar == NULL || url_bar->hidden == hide) + return (url_bar == NULL) ? false : true; + + url_bar->hidden = hide; + + return ro_gui_url_bar_icon_update(url_bar); +} + + +/* This is an exported interface documented in url_bar.h */ + +void ro_gui_url_bar_redraw(struct url_bar *url_bar, wimp_draw *redraw) +{ + wimp_icon icon; + struct rect clip; + + /* Test for a valid URL bar, and then check that the redraw box + * coincides with the bar's favicon extent. + */ + + if (url_bar == NULL || url_bar->hidden || + (redraw->clip.x0 - (redraw->box.x0 - redraw->xscroll)) + > (url_bar->favicon_extent.x1) || + (redraw->clip.y0 - (redraw->box.y1 - redraw->yscroll)) + > url_bar->favicon_extent.y1 || + (redraw->clip.x1 - (redraw->box.x0 - redraw->xscroll)) + < url_bar->favicon_extent.x0 || + (redraw->clip.y1 - (redraw->box.y1 - redraw->yscroll)) + < url_bar->favicon_extent.y0) + return; + + if (url_bar->favicon_content == NULL) { + icon.data.indirected_text.text = null_text_string; + icon.data.indirected_text.validation = url_bar->favicon_sprite; + icon.data.indirected_text.size = 1; + icon.flags = wimp_ICON_TEXT | wimp_ICON_SPRITE | + wimp_ICON_INDIRECTED | wimp_ICON_FILLED | + wimp_ICON_HCENTRED | wimp_ICON_VCENTRED; + icon.extent.x0 = url_bar->favicon_extent.x0; + icon.extent.x1 = url_bar->favicon_extent.x1; + icon.extent.y0 = url_bar->favicon_extent.y0; + icon.extent.y1 = url_bar->favicon_extent.y1; + + xwimp_plot_icon(&icon); + } else { + xwimp_set_colour(wimp_COLOUR_WHITE); + xos_plot(os_MOVE_TO, + (redraw->box.x0 - redraw->xscroll) + + url_bar->favicon_extent.x0, + (redraw->box.y1 - redraw->yscroll) + + url_bar->favicon_extent.y0); + xos_plot(os_PLOT_TO | os_PLOT_RECTANGLE, + (redraw->box.x0 - redraw->xscroll) + + url_bar->favicon_extent.x1, + (redraw->box.y1 - redraw->yscroll) + + url_bar->favicon_extent.y1); + + clip.x0 = (redraw->clip.x0 - ro_plot_origin_x) / 2; + clip.y0 = (ro_plot_origin_y - redraw->clip.y0) / 2; + clip.x1 = (redraw->clip.x1 - ro_plot_origin_x) / 2; + clip.y1 = (ro_plot_origin_y - redraw->clip.y1) / 2; + + content_redraw(url_bar->favicon_content, + (url_bar->favicon_extent.x0 + + url_bar->favicon_offset.x) / 2, + (url_bar->favicon_offset.y - + url_bar->favicon_extent.y1) / 2, + url_bar->favicon_width, url_bar->favicon_height, + &clip, 1, 0); + } +} + + +/* This is an exported interface documented in url_bar.h */ + +bool ro_gui_url_bar_click(struct url_bar *url_bar, + wimp_pointer *pointer, wimp_window_state *state, + url_bar_action *action) +{ + os_coord pos; + + if (url_bar == NULL || url_bar->hidden || + url_bar->display || url_bar->shaded) + return false; + + /* Check that the click was within our part of the window. */ + + pos.x = pointer->pos.x - state->visible.x0 + state->xscroll; + pos.y = pointer->pos.y - state->visible.y1 + state->yscroll; + + if (pos.x < url_bar->extent.x0 || pos.x > url_bar->extent.x1 || + pos.y < url_bar->extent.y0 || + pos.y > url_bar->extent.y1) + return false; + + /* If we find a Select or Adjust drag, check if it originated on the + * URL bar or over the favicon. If either, then return an event. + */ + + if (pointer->buttons == wimp_DRAG_SELECT || + pointer->buttons == wimp_DRAG_ADJUST) { + if (pointer->i == url_bar->text_icon) { + if (action != NULL) + *action = TOOLBAR_URL_DRAG_URL; + return true; + } + + if (pos.x >= url_bar->favicon_extent.x0 && + pos.x <= url_bar->favicon_extent.x1 && + pos.y >= url_bar->favicon_extent.y0 && + pos.y <=url_bar->favicon_extent.y1) { + if (action != NULL) + *action = TOOLBAR_URL_DRAG_FAVICON; + return true; + } + } + + return false; +} + + +/* This is an exported interface documented in url_bar.h */ + +bool ro_gui_url_bar_menu_prepare(struct url_bar *url_bar, wimp_i i, + wimp_menu *menu, wimp_pointer *pointer) +{ + if (url_bar == NULL || url_bar->suggest_icon != i || + menu != ro_gui_url_suggest_menu) + return false; + + if (pointer != NULL) + return ro_gui_url_suggest_prepare_menu(); + + return true; +} + + +/* This is an exported interface documented in url_bar.h */ + +bool ro_gui_url_bar_menu_select(struct url_bar *url_bar, wimp_i i, + wimp_menu *menu, wimp_selection *selection, menu_action action) +{ + const char *url; + struct gui_window *g; + + if (url_bar == NULL || url_bar->suggest_icon != i || + menu != ro_gui_url_suggest_menu) + return false; + + url = ro_gui_url_suggest_get_selection(selection); + g = ro_gui_toolbar_lookup(url_bar->window); + + if (url != NULL && g != NULL && g->bw != NULL) { + gui_window_set_url(g, url); + browser_window_go(g->bw, url, 0, true); + } + + return true; +} + + +/* This is an exported interface documented in url_bar.h */ + +bool ro_gui_url_bar_help_suffix(struct url_bar *url_bar, wimp_i i, + os_coord *mouse, wimp_window_state *state, + wimp_mouse_state buttons, const char **suffix) +{ + os_coord pos; + + if (url_bar == NULL || url_bar->hidden) + return false; + + /* Check that the click was within our part of the window. */ + + pos.x = mouse->x - state->visible.x0 + state->xscroll; + pos.y = mouse->y - state->visible.y1 + state->yscroll; + + if (pos.x < url_bar->extent.x0 || pos.x > url_bar->extent.x1 || + pos.y < url_bar->extent.y0 || + pos.y > url_bar->extent.y1) + return false; + + /* Return hard-coded icon numbers that match the ones that were + * always allocated to the URL bar in a previous implementation. + * If Messages can be updated, this could be changed. + */ + + if (i == url_bar->text_icon) + *suffix = "14"; + else if (i == url_bar->suggest_icon) + *suffix = "15"; + else + *suffix = ""; + + return true; +} + + +/* This is an exported interface documented in url_bar.h */ + +bool ro_gui_url_bar_take_caret(struct url_bar *url_bar) +{ + os_error *error; + + if (url_bar == NULL || url_bar->hidden) + return false; + + error = xwimp_set_caret_position(url_bar->window, url_bar->text_icon, + -1, -1, -1, 0); + if (error) { + LOG(("xwimp_set_caret_position: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + + return false; + } + + return true; +} + + +/* This is an exported interface documented in url_bar.h */ + +void ro_gui_url_bar_set_url(struct url_bar *url_bar, const char *url, + bool is_utf8, bool set_caret) +{ + wimp_caret caret; + os_error *error; + const char *set_url; + + if (url_bar == NULL || url_bar->text_buffer == NULL) + return; + + if (url_bar->text_icon == -1) { + strncpy(url_bar->text_buffer, url, url_bar->text_size); + return; + } + + ro_gui_set_icon_string(url_bar->window, url_bar->text_icon, + url, is_utf8); + + error = xwimp_get_caret_position(&caret); + if (error) { + LOG(("xwimp_get_caret_position: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return; + } + + if (set_caret || (caret.w == url_bar->window && + caret.i == url_bar->text_icon)) { + set_url = ro_gui_get_icon_string(url_bar->window, + url_bar->text_icon); + + error = xwimp_set_caret_position(url_bar->window, + url_bar->text_icon, 0, 0, -1, strlen(set_url)); + if (error) { + LOG(("xwimp_set_caret_position: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + } + } +} + + +/* This is an exported interface documented in url_bar.h */ + +const char *ro_gui_url_bar_get_url(struct url_bar *url_bar) +{ + if (url_bar == NULL) + return NULL; + + return (const char *) url_bar->text_buffer; +} + + +/* This is an exported interface documented in url_bar.h */ + +bool ro_gui_url_bar_get_url_extent(struct url_bar *url_bar, os_box *extent) +{ + wimp_icon_state state; + os_error *error; + + if (url_bar == NULL || url_bar->hidden) + return false; + + if (extent == NULL) + return true; + + state.w = url_bar->window; + state.i = url_bar->container_icon; + error = xwimp_get_icon_state(&state); + if (error) { + LOG(("xwimp_get_icon_state: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return false; + } + + extent->x0 = state.icon.extent.x0; + extent->y0 = state.icon.extent.y0; + extent->x1 = state.icon.extent.x1; + extent->y1 = state.icon.extent.y1; + + return true; +} + + +/* This is an exported interface documented in url_bar.h */ + +bool ro_gui_url_bar_test_for_text_field_click(struct url_bar *url_bar, + wimp_pointer *pointer) +{ + if (url_bar == NULL || url_bar->hidden || pointer == NULL) + return false; + + return (pointer->w == url_bar->window && + pointer->i == url_bar->text_icon) ? true : false; +} + + +/* This is an exported interface documented in url_bar.h */ + +bool ro_gui_url_bar_test_for_text_field_keypress(struct url_bar *url_bar, + wimp_key *key) +{ + if (url_bar == NULL || url_bar->hidden || key == NULL) + return false; + + return (key->w == url_bar->window && + key->i == url_bar->text_icon) ? true : false; +} + + +/* This is an exported interface documented in url_bar.h */ + +bool ro_gui_url_bar_set_site_favicon(struct url_bar *url_bar, + struct hlcache_handle *h) +{ + content_type type = CONTENT_OTHER; + + if (url_bar == NULL) + return false; + + if (h != NULL) + type = content_get_type(h); + + // \TODO -- Maybe test for CONTENT_ICO ??? + + if (type != CONTENT_OTHER && type != CONTENT_UNKNOWN) { + url_bar->favicon_content = h; + url_bar->favicon_width = content_get_width(h); + url_bar->favicon_height = content_get_height(h); + + if (url_bar->favicon_width > URLBAR_FAVICON_SIZE) + url_bar->favicon_width = URLBAR_FAVICON_SIZE; + + if (url_bar->favicon_height > URLBAR_FAVICON_SIZE) + url_bar->favicon_height = URLBAR_FAVICON_SIZE; + + url_bar->favicon_offset.x = ((url_bar->favicon_extent.x1 - + url_bar->favicon_extent.x0) - + (url_bar->favicon_width * 2)) / 2; + url_bar->favicon_offset.y = ((url_bar->favicon_extent.y1 - + url_bar->favicon_extent.y0) - + (url_bar->favicon_height * 2)) / 2; + } else { + url_bar->favicon_content = NULL; + + if (url_bar->favicon_type != 0) + snprintf(url_bar->favicon_sprite, + URLBAR_FAVICON_NAME_LENGTH, + "Ssmall_%.3x", url_bar->favicon_type); + else + snprintf(url_bar->favicon_sprite, + URLBAR_FAVICON_NAME_LENGTH, + "Ssmall_xxx"); + } + + if (!url_bar->hidden) + xwimp_force_redraw(url_bar->window, + url_bar->favicon_extent.x0, + url_bar->favicon_extent.y0, + url_bar->favicon_extent.x1, + url_bar->favicon_extent.y1); + + return true; +} + + +/* This is an exported interface documented in url_bar.h */ + +bool ro_gui_url_bar_set_content_favicon(struct url_bar *url_bar, + struct hlcache_handle *h) +{ + int type = 0; + char sprite[URLBAR_FAVICON_NAME_LENGTH]; + + if (url_bar == NULL) + return false; + + if (h != NULL) + type = ro_content_filetype_from_type(content_get_type(h)); + + if (type != 0) { + snprintf(sprite, URLBAR_FAVICON_NAME_LENGTH, + "small_%.3x", type); + + if (!ro_gui_wimp_sprite_exists(sprite)) + type = 0; + } + + url_bar->favicon_type = type; + + if (url_bar->favicon_content == NULL) { + if (type == 0) + snprintf(url_bar->favicon_sprite, + URLBAR_FAVICON_NAME_LENGTH, "Ssmall_xxx"); + else + snprintf(url_bar->favicon_sprite, + URLBAR_FAVICON_NAME_LENGTH, "S%s", sprite); + + if (!url_bar->hidden) + xwimp_force_redraw(url_bar->window, + url_bar->favicon_extent.x0, + url_bar->favicon_extent.y0, + url_bar->favicon_extent.x1, + url_bar->favicon_extent.y1); + } + + return true; +} + + +/* This is an exported interface documented in url_bar.h */ + +bool ro_gui_url_bar_update_urlsuggest(struct url_bar *url_bar) +{ + if (url_bar == NULL || url_bar->hidden) + return (url_bar == NULL) ? false : true; + + if (url_bar->window != NULL && url_bar->suggest_icon != -1) + ro_gui_set_icon_shaded_state(url_bar->window, + url_bar->suggest_icon, + !ro_gui_url_suggest_get_menu_available()); + + return true; +} + diff --git a/riscos/gui/url_bar.h b/riscos/gui/url_bar.h new file mode 100644 index 000000000..0f5c6bc14 --- /dev/null +++ b/riscos/gui/url_bar.h @@ -0,0 +1,302 @@ +/* + * Copyright 2005 Richard Wilson + * Copyright 2011 Stephen Fryatt + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** \file + * URL bars (interface). + */ + +#ifndef _NETSURF_RISCOS_URLBAR_H_ +#define _NETSURF_RISCOS_URLBAR_H_ + +#include +#include "riscos/menus.h" +#include "riscos/theme.h" + +/* A list of possible URL bar actions. */ + +typedef enum { + TOOLBAR_URL_NONE = 0, /* Special case: no action */ + TOOLBAR_URL_DRAG_URL, + TOOLBAR_URL_DRAG_FAVICON, +} url_bar_action; + +struct url_bar; + +/** + * Create a new url bar widget. + * + * \param *theme The theme to apply (or NULL for the default). + * \return A url bar handle, or NULL on failure. + */ + +struct url_bar *ro_gui_url_bar_create(struct theme_descriptor *theme); + + +/** + * Place a URL bar into a toolbar window and initialise any theme-specific + * settings. Any previous incarnation of the bar will be forgotten: this + * is for use when a new toolbar is being created, or when a toolbar has been + * deleted and rebuilt following a theme change. + * + * \param *url_bar The URL bar to rebuild. + * \param *theme The theme to apply (or NULL for current). + * \param style The theme style to apply. + * \param window The window that the bar is in. + * \param display true if the bar should be for display only. + * \param shaded true if the bar should be shaded; else false. + * \return true on success; else false. + */ + +bool ro_gui_url_bar_rebuild(struct url_bar *url_bar, + struct theme_descriptor *theme, theme_style style, + wimp_w window, bool display, bool shaded); + + +/** + * Destroy a url bar widget. + * + * \param *url_bar The url bar to destroy. + */ + +void ro_gui_url_bar_destroy(struct url_bar *url_bar); + + +/** + * Return the MINIMUM dimensions required by the URL bar, in RO units, + * allowing for the current theme. + * + * \param *url_bar The URL bar of interest. + * \param *width Return the required width. + * \param *height Return the required height. + * \return true if values are returned; else false. + */ + +bool ro_gui_url_bar_get_dims(struct url_bar *url_bar, + int *width, int *height); + + +/** + * Set or update the dimensions to be used by the URL bar, in RO units. + * If these are greater than the minimum required, the URL bar will fill + * the extended space; if less, the call will fail. + * + * \param *url_bar The URL bar to update. + * \param x0 The minimum X window position. + * \param y0 The minimum Y window position. + * \param x1 The maximum X window position. + * \param y1 The maximum Y window position. + * \return true if size updated; else false. + */ + +bool ro_gui_url_bar_set_extent(struct url_bar *url_bar, + int x0, int y0, int x1, int y1); + + +/** + * Show or hide a URL bar. + * + * \param *url_bar The URL bar to hide. + * \param hide true to hide the bar; false to show it. + * \return true if successful; else false. + */ + +bool ro_gui_url_bar_hide(struct url_bar *url_bar, bool hide); + + +/** + * Handle redraw event rectangles in a URL bat. + * + * \param *url_bar The URL bar to use. + * \param *redraw The Wimp redraw rectangle to process. + */ + +void ro_gui_url_bar_redraw(struct url_bar *url_bar, wimp_draw *redraw); + + +/** + * Handle mouse clicks in a URL bar. + * + * \param *url_bar The URL bar to use. + * \param *pointer The Wimp mouse click event data. + * \param *state The toolbar window state. + * \param *action Returns the selected action, or + * TOOLBAR_URL_NONE. + * \return true if the event was handled exclusively; + * else false. + */ + +bool ro_gui_url_bar_click(struct url_bar *url_bar, + wimp_pointer *pointer, wimp_window_state *state, + url_bar_action *action); + + +/** + * Process offered menu prepare events from the parent window. + * + * \param *url_bar The URL bar in question. + * \param i The icon owning the menu. + * \param *menu The menu to be prepared. + * \param *pointer The Wimp Pointer data from the event. + * \return true if the event is claimed; else false. + */ + +bool ro_gui_url_bar_menu_prepare(struct url_bar *url_bar, wimp_i i, + wimp_menu *menu, wimp_pointer *pointer); + + +/** + * Process offered menu select events from the parent window. + * + * \param *url_bar The URL bar in question. + * \param i The icon owning the menu. + * \param *menu The menu to be prepared. + * \param *selection The wimp menu selection data. + * \param action The selected menu action. + * \return true if the event is claimed; else false. + */ + +bool ro_gui_url_bar_menu_select(struct url_bar *url_bar, wimp_i i, + wimp_menu *menu, wimp_selection *selection, menu_action action); + + +/** + * Translate mouse data into an interactive help message for the URL bar. + * + * \param *url_bar The URL bar to process. + * \param i The wimp icon under the pointer. + * \param *mouse The mouse position. + * \param *state The toolbar window state. + * \param buttons The mouse button state. + * \param **suffix Return a help token suffix, or "" for none. + * \return true if handled exclusively; else false. + */ + +bool ro_gui_url_bar_help_suffix(struct url_bar *url_bar, wimp_i i, + os_coord *mouse, wimp_window_state *state, + wimp_mouse_state buttons, const char **suffix); + + +/** + * Give a URL bar input focus. + * + * \param *url_bar The URL bar to give focus to. + * \return true if successful; else false. + */ + +bool ro_gui_url_bar_take_caret(struct url_bar *url_bar); + + +/** + * Set the content of a URL Bar field. + * + * \param *url_bar The URL Bar to update. + * \param *url The new url to insert. + * \param is_utf8 true if the string is in utf8 encoding; false + * if it is in local encoding. + * \param set_caret true if the caret should be placed in the field; + * else false. + */ + +void ro_gui_url_bar_set_url(struct url_bar *url_bar, const char *url, + bool is_utf8, bool set_caret); + + +/** + * Return a pointer to the URL contained in a URL bar. + * + * \param *url_bar The URL Bar to look up the URL from. + * \return Pointer to the URL, or NULL. + */ + +const char *ro_gui_url_bar_get_url(struct url_bar *url_bar); + + +/** + * Return the current work area coordinates of the URL and favicon field's + * bounding box. + * + * \param *url_bar The URL bar to check. + * \param *extent Returns the field extent. + * \return true if successful; else false. + */ + +bool ro_gui_url_bar_get_url_extent(struct url_bar *url_bar, os_box *extent); + + +/** + * Test a pointer click to see if it was in the URL bar's text field. + * + * \param *url_bar The URL Bar to test. + * \param *pointer The pointer event data to test. + * \return true if the click was in the field; else false. + */ + +bool ro_gui_url_bar_test_for_text_field_click(struct url_bar *url_bar, + wimp_pointer *pointer); + + +/** + * Test a keypress to see if it was in the URL bar's text field. + * + * \param *url_bar The URL Bar to test. + * \param *pointer The pointer event data to test. + * \return true if the click was in the field; else false. + */ + +bool ro_gui_url_bar_test_for_text_field_keypress(struct url_bar *url_bar, + wimp_key *key); + + +/** + * Set the favicon to a site supplied favicon image, or remove the image + * and return to using filetype-based icons. + * + * \param *url_bar The URL Bar to update the favicon on. + * \param *h The content to use, or NULL to unset. + * \return true if successful; else false. + */ + +bool ro_gui_url_bar_set_site_favicon(struct url_bar *url_bar, + struct hlcache_handle *h); + + +/** + * Set the favicon to a RISC OS filetype sprite based on the type of the + * supplied content. + * + * \param *url_bar The URL Bar to update the favicon on. + * \param *h The content to use. + * \return true if successful; else false. + */ + +bool ro_gui_url_bar_set_content_favicon(struct url_bar *url_bar, + struct hlcache_handle *h); + + +/** + * Update the state of the URL suggestion pop-up menu icon on a URL bar. + * + * \param *url_bar The URL bar to update. + * \return true if successful; else false. + */ + +bool ro_gui_url_bar_update_urlsuggest(struct url_bar *url_bar); + +#endif + diff --git a/riscos/help.c b/riscos/help.c index 968fcb7c4..6a71fb1ec 100644 --- a/riscos/help.c +++ b/riscos/help.c @@ -33,12 +33,13 @@ #include "riscos/gui.h" #include "riscos/hotlist.h" #include "riscos/help.h" +#include "riscos/iconbar.h" #include "riscos/menus.h" #include "riscos/options.h" -#include "riscos/theme.h" #include "riscos/treeview.h" #include "riscos/wimp.h" #include "riscos/wimp_event.h" +#include "riscos/window.h" #include "utils/messages.h" #include "utils/log.h" #include "utils/utf8.h" @@ -91,18 +92,18 @@ static os_t help_time = 0; */ void ro_gui_interactive_help_request(wimp_message *message) { - char message_token[32]; - char menu_buffer[4]; - wimp_selection menu_tree; - help_full_message_request *message_data; - wimp_w window; - wimp_i icon; - unsigned int index; - bool greyed = false; - wimp_menu *test_menu; - os_error *error; - const char *auto_text; - int i; + char message_token[32]; + char menu_buffer[4]; + wimp_selection menu_tree; + help_full_message_request *message_data; + wimp_w window; + wimp_i icon; + unsigned int index; + bool greyed = false; + wimp_menu *test_menu; + os_error *error; + const char *auto_text, *auto_suffix; + int i; /* check we aren't turned off */ if (!option_interactive_help) @@ -123,9 +124,15 @@ void ro_gui_interactive_help_request(wimp_message *message) /* do the basic window checks */ auto_text = ro_gui_wimp_event_get_help_prefix(window); - if (auto_text) - sprintf(message_token, "%s%i", auto_text, (int)icon); - else if (window == wimp_ICON_BAR) + if (auto_text != NULL) { + auto_suffix = ro_gui_wimp_event_get_help_suffix(window, icon, + &message_data->pos, message_data->buttons); + + if (auto_suffix == NULL) + sprintf(message_token, "%s%i", auto_text, (int)icon); + else + sprintf(message_token, "%s%s", auto_text, auto_suffix); + } else if (window == wimp_ICON_BAR) sprintf(message_token, "HelpIconbar"); else if (ro_gui_hotlist_check_window(message->data.data_xfer.w)) { i = ro_treeview_get_help(message_data); @@ -171,9 +178,9 @@ void ro_gui_interactive_help_request(wimp_message *message) return; /* get the menu prefix */ - if (current_menu == iconbar_menu) + if (ro_gui_iconbar_check_menu(current_menu)) sprintf(message_token, "HelpIconMenu"); - else if (current_menu == browser_menu) + else if (ro_gui_window_check_menu(current_menu)) sprintf(message_token, "HelpBrowserMenu"); else if (ro_gui_hotlist_check_menu(current_menu)) sprintf(message_token, "HelpHotlistMenu"); diff --git a/riscos/hotlist.c b/riscos/hotlist.c index 42976b893..3bb2c59e7 100644 --- a/riscos/hotlist.c +++ b/riscos/hotlist.c @@ -39,7 +39,7 @@ #include "riscos/menus.h" #include "riscos/options.h" #include "riscos/save.h" -#include "riscos/theme.h" +#include "riscos/toolbar.h" #include "riscos/treeview.h" #include "riscos/wimp.h" #include "riscos/wimp_event.h" @@ -48,6 +48,22 @@ #include "utils/utils.h" #include "utils/url.h" +static void ro_gui_hotlist_toolbar_update_buttons(void); +static void ro_gui_hotlist_toolbar_save_buttons(char *config); +static bool ro_gui_hotlist_menu_prepare(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_pointer *pointer); +static void ro_gui_hotlist_menu_warning(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_selection *selection, menu_action action); +static bool ro_gui_hotlist_menu_select(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_selection *selection, menu_action action); +static void ro_gui_hotlist_toolbar_click(button_bar_action action); + +struct ro_treeview_callbacks ro_hotlist_treeview_callbacks = { + ro_gui_hotlist_toolbar_click, + ro_gui_hotlist_toolbar_update_buttons, + ro_gui_hotlist_toolbar_save_buttons +}; + /* The RISC OS hotlist window, toolbar and treeview data. */ static struct ro_hotlist { @@ -79,21 +95,30 @@ void ro_gui_hotlist_postinitialise(void) { /* Create our toolbar. */ - hotlist_window.toolbar = ro_gui_theme_create_toolbar(NULL, - THEME_HOTLIST_TOOLBAR); - if (hotlist_window.toolbar) - ro_gui_theme_attach_toolbar(hotlist_window.toolbar, - hotlist_window.window); + hotlist_window.toolbar = ro_toolbar_create(NULL, hotlist_window.window, + THEME_STYLE_HOTLIST_TOOLBAR, TOOLBAR_FLAGS_NONE, + ro_treeview_get_toolbar_callbacks(), NULL, + "HelpHotToolbar"); + if (hotlist_window.toolbar != NULL) { + ro_toolbar_add_buttons(hotlist_window.toolbar, + hotlist_toolbar_buttons, + option_toolbar_hotlist); + ro_toolbar_rebuild(hotlist_window.toolbar); + } /* Create the treeview with the window and toolbar. */ hotlist_window.tv = ro_treeview_create(hotlist_window.window, - hotlist_window.toolbar, hotlist_get_tree_flags()); + hotlist_window.toolbar, &ro_hotlist_treeview_callbacks, + hotlist_get_tree_flags()); if (hotlist_window.tv == NULL) { LOG(("Failed to allocate treeview")); return; } + ro_toolbar_update_client_data(hotlist_window.toolbar, + hotlist_window.tv); + /* Initialise the hotlist into the tree. */ hotlist_initialise(ro_treeview_get_tree(hotlist_window.tv), @@ -133,10 +158,14 @@ void ro_gui_hotlist_postinitialise(void) hotlist_window.menu = ro_gui_menu_define_menu(&hotlist_definition); - ro_gui_wimp_event_register_window_menu(hotlist_window.window, - hotlist_window.menu, ro_gui_hotlist_menu_prepare, - ro_gui_hotlist_menu_select, NULL, - ro_gui_hotlist_menu_warning, false); + ro_gui_wimp_event_register_menu(hotlist_window.window, + hotlist_window.menu, false, false); + ro_gui_wimp_event_register_menu_prepare(hotlist_window.window, + ro_gui_hotlist_menu_prepare); + ro_gui_wimp_event_register_menu_selection(hotlist_window.window, + ro_gui_hotlist_menu_select); + ro_gui_wimp_event_register_menu_warning(hotlist_window.window, + ro_gui_hotlist_menu_warning); } @@ -149,82 +178,86 @@ void ro_gui_hotlist_open(void) { tree_set_redraw(ro_treeview_get_tree(hotlist_window.tv), true); + ro_gui_hotlist_toolbar_update_buttons(); + if (!ro_gui_dialog_open_top(hotlist_window.window, hotlist_window.toolbar, 600, 800)) { - - xwimp_set_caret_position(hotlist_window.window, -1, -100, -100, 32, -1); -// \todo ro_gui_theme_process_toolbar(hotlist_window.toolbar, -1); ro_treeview_set_origin(hotlist_window.tv, 0, - -(ro_gui_theme_toolbar_height( - hotlist_window.toolbar))); -// ro_gui_tree_stop_edit(tree); -// -// if (tree->root->child) { -// tree_set_node_selected(tree, tree->root, false); -// tree_handle_node_changed(tree, tree->root, -// false, true); -// } + -(ro_toolbar_height(hotlist_window.toolbar))); } } /** - * Handle Mouse Click events on the toolbar. + * Handle toolbar button clicks. * - * \param *pointer Pointer to the Mouse Click Event block. - * \return Return true if click handled; else false. + * \param action The action to handle */ -bool ro_gui_hotlist_toolbar_click(wimp_pointer *pointer) +void ro_gui_hotlist_toolbar_click(button_bar_action action) { - if (pointer->buttons == wimp_CLICK_MENU) - return ro_gui_wimp_event_process_window_menu_click(pointer); + switch (action) { + case TOOLBAR_BUTTON_DELETE: + hotlist_delete_selected(); + break; - if (hotlist_window.toolbar->editor != NULL) { - ro_gui_theme_toolbar_editor_click(hotlist_window.toolbar, - pointer); - return true; - } + case TOOLBAR_BUTTON_EXPAND: + hotlist_expand_addresses(); + break; - switch (pointer->i) { - case ICON_TOOLBAR_DELETE: - if (pointer->buttons == wimp_CLICK_SELECT) { - hotlist_delete_selected(); - return true; - } + case TOOLBAR_BUTTON_COLLAPSE: + hotlist_collapse_addresses(); break; - case ICON_TOOLBAR_EXPAND: - if (pointer->buttons == wimp_CLICK_SELECT) { - hotlist_expand_addresses(); - return true; - } else if (pointer->buttons == wimp_CLICK_ADJUST) { - hotlist_collapse_addresses(); - return true; - } + + case TOOLBAR_BUTTON_OPEN: + hotlist_expand_directories(); break; - case ICON_TOOLBAR_OPEN: - if (pointer->buttons == wimp_CLICK_SELECT) { - hotlist_expand_directories(); - return true; - } else if (pointer->buttons == wimp_CLICK_ADJUST) { - hotlist_collapse_directories(); - return true; - } + + case TOOLBAR_BUTTON_CLOSE: + hotlist_collapse_directories(); break; - case ICON_TOOLBAR_LAUNCH: - if (pointer->buttons == wimp_CLICK_SELECT) { - hotlist_launch_selected(); - return true; - } + + case TOOLBAR_BUTTON_LAUNCH: + hotlist_launch_selected(); break; - case ICON_TOOLBAR_CREATE: - if (pointer->buttons == wimp_CLICK_SELECT) { - hotlist_add_folder(); - return true; - } + + case TOOLBAR_BUTTON_CREATE: + hotlist_add_folder(); + break; + + default: break; } +} - return true; + +/** + * Update the button state in the hotlist toolbar. + */ + +void ro_gui_hotlist_toolbar_update_buttons(void) +{ + ro_toolbar_set_button_shaded_state(hotlist_window.toolbar, + TOOLBAR_BUTTON_DELETE, + !ro_treeview_has_selection(hotlist_window.tv)); + + ro_toolbar_set_button_shaded_state(hotlist_window.toolbar, + TOOLBAR_BUTTON_LAUNCH, + !ro_treeview_has_selection(hotlist_window.tv)); +} + + +/** + * Save a new button arrangement in the hotlist toolbar. + * + * \param *config The new button configuration string. + */ + +void ro_gui_hotlist_toolbar_save_buttons(char *config) +{ + if (option_toolbar_hotlist != NULL) + free(option_toolbar_hotlist); + option_toolbar_hotlist = config; + ro_gui_save_options(); } @@ -233,53 +266,54 @@ bool ro_gui_hotlist_toolbar_click(wimp_pointer *pointer) * * \param window The window owning the menu. * \param *menu The menu about to be opened. + * \param *pointer Pointer to the relevant wimp event block, or + * NULL for an Adjust click. + * \return true if the event was handled; else false. */ -void ro_gui_hotlist_menu_prepare(wimp_w window, wimp_menu *menu) +bool ro_gui_hotlist_menu_prepare(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_pointer *pointer) { bool selection; - if (menu != hotlist_window.menu && menu != tree_toolbar_menu) - return; + if (menu != hotlist_window.menu) + return false; - if (menu == hotlist_window.menu) { - selection = ro_treeview_has_selection(hotlist_window.tv); + selection = ro_treeview_has_selection(hotlist_window.tv); - ro_gui_menu_set_entry_shaded(hotlist_window.menu, - TREE_SELECTION, !selection); - ro_gui_menu_set_entry_shaded(hotlist_window.menu, - TREE_CLEAR_SELECTION, !selection); + ro_gui_menu_set_entry_shaded(hotlist_window.menu, + TREE_SELECTION, !selection); + ro_gui_menu_set_entry_shaded(hotlist_window.menu, + TREE_CLEAR_SELECTION, !selection); - ro_gui_save_prepare(GUI_SAVE_HOTLIST_EXPORT_HTML, - NULL, NULL, NULL, NULL); - } + ro_gui_save_prepare(GUI_SAVE_HOTLIST_EXPORT_HTML, + NULL, NULL, NULL, NULL); ro_gui_menu_set_entry_shaded(menu, TOOLBAR_BUTTONS, - (hotlist_window.toolbar == NULL || - hotlist_window.toolbar->editor != NULL)); + ro_toolbar_menu_option_shade(hotlist_window.toolbar)); ro_gui_menu_set_entry_ticked(menu, TOOLBAR_BUTTONS, - (hotlist_window.toolbar != NULL && - (hotlist_window.toolbar->display_buttons || - (hotlist_window.toolbar->editor != NULL)))); + ro_toolbar_menu_buttons_tick(hotlist_window.toolbar)); ro_gui_menu_set_entry_shaded(menu, TOOLBAR_EDIT, - hotlist_window.toolbar == NULL); + ro_toolbar_menu_edit_shade(hotlist_window.toolbar)); ro_gui_menu_set_entry_ticked(menu, TOOLBAR_EDIT, - (hotlist_window.toolbar != NULL && - hotlist_window.toolbar->editor != NULL)); + ro_toolbar_menu_edit_tick(hotlist_window.toolbar)); + + return true; } /** * Handle submenu warnings for the hotlist menu * - * \param window The window owning the menu. + * \param w The window owning the menu. + * \param i The icon owning the menu. * \param *menu The menu to which the warning applies. * \param *selection The wimp menu selection data. * \param action The selected menu action. */ -void ro_gui_hotlist_menu_warning(wimp_w window, wimp_menu *menu, +void ro_gui_hotlist_menu_warning(wimp_w w, wimp_i i, wimp_menu *menu, wimp_selection *selection, menu_action action) { /* Do nothing */ @@ -288,19 +322,20 @@ void ro_gui_hotlist_menu_warning(wimp_w window, wimp_menu *menu, /** * Handle selections from the hotlist menu * - * \param window The window owning the menu. + * \param w The window owning the menu. + * \param i The icon owning the menu. * \param *menu The menu from which the selection was made. * \param *selection The wimp menu selection data. * \param action The selected menu action. * \return true if action accepted; else false. */ -bool ro_gui_hotlist_menu_select(wimp_w window, wimp_menu *menu, +bool ro_gui_hotlist_menu_select(wimp_w w, wimp_i i, wimp_menu *menu, wimp_selection *selection, menu_action action) { switch (action) { case HOTLIST_EXPORT: - ro_gui_dialog_open_persistent(window, dialog_saveas, true); + ro_gui_dialog_open_persistent(w, dialog_saveas, true); return true; case TREE_NEW_FOLDER: hotlist_add_folder(); @@ -342,12 +377,12 @@ bool ro_gui_hotlist_menu_select(wimp_w window, wimp_menu *menu, hotlist_clear_selection(); return true; case TOOLBAR_BUTTONS: - hotlist_window.toolbar->display_buttons = - !hotlist_window.toolbar->display_buttons; - ro_gui_theme_refresh_toolbar(hotlist_window.toolbar); + ro_toolbar_set_display_buttons(hotlist_window.toolbar, + !ro_toolbar_get_display_buttons( + hotlist_window.toolbar)); return true; case TOOLBAR_EDIT: - ro_gui_theme_toggle_edit(hotlist_window.toolbar); + ro_toolbar_toggle_edit(hotlist_window.toolbar); return true; default: return false; @@ -356,21 +391,6 @@ bool ro_gui_hotlist_menu_select(wimp_w window, wimp_menu *menu, return false; } -/** - * Update the theme details of the hotlist window. - * - * \param full_update true to force a full theme change; false to - * refresh the toolbar size. - */ - -void ro_gui_hotlist_update_theme(bool full_update) -{ - if (full_update) - ro_treeview_update_theme(hotlist_window.tv); - else - ro_treeview_update_toolbar(hotlist_window.tv); -} - /** * Check if a particular window handle is the hotlist window * diff --git a/riscos/hotlist.h b/riscos/hotlist.h index d6126bbd5..e47c140a1 100644 --- a/riscos/hotlist.h +++ b/riscos/hotlist.h @@ -30,15 +30,8 @@ void ro_gui_hotlist_preinitialise(void); void ro_gui_hotlist_postinitialise(void); void ro_gui_hotlist_open(void); void ro_gui_hotlist_save(void); -void ro_gui_hotlist_update_theme(bool full_update); bool ro_gui_hotlist_check_window(wimp_w window); bool ro_gui_hotlist_check_menu(wimp_menu *menu); -bool ro_gui_hotlist_toolbar_click(wimp_pointer *pointer); -void ro_gui_hotlist_menu_prepare(wimp_w window, wimp_menu *menu); -bool ro_gui_hotlist_menu_select(wimp_w window, wimp_menu *menu, - wimp_selection *selection, menu_action action); -void ro_gui_hotlist_menu_warning(wimp_w window, wimp_menu *menu, - wimp_selection *selection, menu_action action); #endif diff --git a/riscos/iconbar.c b/riscos/iconbar.c new file mode 100644 index 000000000..77c05fe23 --- /dev/null +++ b/riscos/iconbar.c @@ -0,0 +1,233 @@ +/* + * Copyright 2010 Stephen Fryatt + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** \file + * Iconbar icon and menus (implementation). + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "oslib/os.h" +#include "oslib/osbyte.h" +#include "oslib/wimp.h" +#include "riscos/configure.h" +#include "riscos/cookies.h" +#include "riscos/dialog.h" +#include "riscos/global_history.h" +#include "riscos/hotlist.h" +#include "riscos/iconbar.h" +#include "riscos/options.h" +#include "riscos/wimp_event.h" +#include "utils/log.h" +#include "utils/utils.h" + +static bool ro_gui_iconbar_click(wimp_pointer *pointer); + +static bool ro_gui_iconbar_menu_select(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_selection *selection, menu_action action); +static void ro_gui_iconbar_menu_warning(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_selection *selection, menu_action action); + + +static wimp_menu *ro_gui_iconbar_menu = NULL; /**< Iconbar menu handle */ + +/** + * Initialise the iconbar menus, create an icon and register the necessary + * handlers to look after them all. + */ + +void ro_gui_iconbar_initialise(void) +{ + os_error *error; + + /* Build the iconbar menu */ + + static const struct ns_menu iconbar_definition = { + "NetSurf", { + { "Info", NO_ACTION, &dialog_info }, + { "AppHelp", HELP_OPEN_CONTENTS, 0 }, + { "Open", BROWSER_NAVIGATE_URL, 0 }, + { "Open.OpenURL", BROWSER_NAVIGATE_URL, &dialog_openurl }, + { "Open.HotlistShow", HOTLIST_SHOW, 0 }, + { "Open.HistGlobal", HISTORY_SHOW_GLOBAL, 0 }, + { "Open.ShowCookies", COOKIES_SHOW, 0 }, + { "Choices", CHOICES_SHOW, 0 }, + { "Quit", APPLICATION_QUIT, 0 }, + {NULL, 0, 0} + } + }; + ro_gui_iconbar_menu = ro_gui_menu_define_menu(&iconbar_definition); + + /* Create an iconbar icon. */ + + wimp_icon_create icon = { + wimp_ICON_BAR_RIGHT, + { { 0, 0, 68, 68 }, + wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | + (wimp_BUTTON_CLICK << wimp_ICON_BUTTON_TYPE_SHIFT), + { "!netsurf" } } }; + error = xwimp_create_icon(&icon, 0); + if (error) { + LOG(("xwimp_create_icon: 0x%x: %s", + error->errnum, error->errmess)); + die(error->errmess); + } + + /* Register handlers to look after clicks and menu actions. */ + + ro_gui_wimp_event_register_mouse_click(wimp_ICON_BAR, + ro_gui_iconbar_click); + + ro_gui_wimp_event_register_menu(wimp_ICON_BAR, ro_gui_iconbar_menu, + true, true); + ro_gui_wimp_event_register_menu_selection(wimp_ICON_BAR, + ro_gui_iconbar_menu_select); + ro_gui_wimp_event_register_menu_warning(wimp_ICON_BAR, + ro_gui_iconbar_menu_warning); +} + + +/** + * Handle Mouse_Click events on the iconbar icon. + * + * \param *pointer The wimp event block to be processed. + * \return true if the event was handled; else false. + */ + +bool ro_gui_iconbar_click(wimp_pointer *pointer) +{ + char url[80]; + int key_down = 0; + + switch (pointer->buttons) { + case wimp_CLICK_SELECT: + if (option_homepage_url && option_homepage_url[0]) { + browser_window_create(option_homepage_url, NULL, 0, + true, false); + } else { + snprintf(url, sizeof url, + "file:////Docs/welcome/index_%s", + option_language); + browser_window_create(url, NULL, 0, true, false); + } + break; + + case wimp_CLICK_ADJUST: + xosbyte1(osbyte_SCAN_KEYBOARD, 0 ^ 0x80, 0, &key_down); + if (key_down == 0) + ro_gui_hotlist_open(); + else + ro_gui_debugwin_open(); + break; + } + + return true; +} + +/** + * Handle submenu warnings for the iconbar menu + * + * \param w The window owning the menu. + * \param i The icon owning the menu. + * \param *menu The menu to which the warning applies. + * \param *selection The wimp menu selection data. + * \param action The selected menu action. + */ + +void ro_gui_iconbar_menu_warning(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_selection *selection, menu_action action) +{ + if (w != wimp_ICON_BAR || i != wimp_ICON_WINDOW) + return; + + switch (action) { + case BROWSER_NAVIGATE_URL: + ro_gui_dialog_prepare_open_url(); + break; + default: + break; + } +} + +/** + * Handle selections from the iconbar menu + * + * \param w The window owning the menu. + * \param i The icon owning the menu. + * \param *selection The wimp menu selection data. + * \param action The selected menu action. + * \return true if action accepted; else false. + */ + +bool ro_gui_iconbar_menu_select(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_selection *selection, menu_action action) +{ + if (w != wimp_ICON_BAR || i != wimp_ICON_WINDOW) + return false; + + switch (action) { + case HELP_OPEN_CONTENTS: + ro_gui_open_help_page("documentation/index"); + return true; + case BROWSER_NAVIGATE_URL: + ro_gui_dialog_prepare_open_url(); + ro_gui_dialog_open_persistent(NULL, dialog_openurl, true); + return true; + case HOTLIST_SHOW: + ro_gui_hotlist_open(); + return true; + case HISTORY_SHOW_GLOBAL: + ro_gui_global_history_open(); + return true; + case COOKIES_SHOW: + ro_gui_cookies_open(); + return true; + case CHOICES_SHOW: + ro_gui_configure_show(); + return true; + case APPLICATION_QUIT: + if (ro_gui_prequit()) { + LOG(("QUIT in response to user request")); + netsurf_quit = true; + } + return true; + default: + return false; + } + + return false; +} + +/** + * Check if a particular menu handle is the iconbar menu + * + * \param *menu The menu in question. + * \return true if this menu is the iconbar menu + */ + +bool ro_gui_iconbar_check_menu(wimp_menu *menu) +{ + return (ro_gui_iconbar_menu == menu) ? true : false; +} + diff --git a/riscos/iconbar.h b/riscos/iconbar.h new file mode 100644 index 000000000..e40f9acd8 --- /dev/null +++ b/riscos/iconbar.h @@ -0,0 +1,32 @@ +/* + * Copyright 2010 Stephen Fryatt + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** \file + * Iconbar icon and menus (interface). + */ + +#include + +#ifndef _NETSURF_RISCOS_ICONBAR_H_ +#define _NETSURF_RISCOS_ICONBAR_H_ + +void ro_gui_iconbar_initialise(void); +bool ro_gui_iconbar_check_menu(wimp_menu *menu); + +#endif + diff --git a/riscos/menus.c b/riscos/menus.c index af16127bc..133aa9d6d 100644 --- a/riscos/menus.c +++ b/riscos/menus.c @@ -57,7 +57,7 @@ #include "riscos/options.h" #include "riscos/save.h" #include "riscos/tinct.h" -#include "riscos/theme.h" +#include "riscos/toolbar.h" #include "riscos/treeview.h" #include "riscos/url_suggest.h" #include "riscos/wimp.h" @@ -93,14 +93,7 @@ static struct menu_definition_entry *ro_gui_menu_find_entry(wimp_menu *menu, menu_action action); static menu_action ro_gui_menu_find_action(wimp_menu *menu, wimp_menu_entry *menu_entry); -static void ro_gui_menu_get_window_details(wimp_w w, struct gui_window **g, - struct browser_window **bw, hlcache_handle **h, - struct toolbar **toolbar, - bool *is_cookies, bool *is_hotlist, bool *is_global_history); static int ro_gui_menu_get_checksum(void); -static void ro_gui_menu_prepare_pageinfo(struct gui_window *g); -static void ro_gui_menu_prepare_objectinfo(hlcache_handle *object, - const char *href); static bool ro_gui_menu_translate(struct menu_definition *menu); @@ -115,27 +108,12 @@ static struct menu_definition *ro_gui_menu_definitions; wimp_menu *current_menu; /** Whether a menu is currently open */ bool current_menu_open = false; -/** Object under menu, or 0 if no object. */ -static hlcache_handle *current_menu_object = 0; -/** URL of link under menu, or 0 if no link. */ -static const char *current_menu_url = 0; -/** Menu of options for form select controls. */ -static wimp_menu *gui_form_select_menu = 0; -/** Form control which gui_form_select_menu is for. */ -static struct form_control *gui_form_select_control; /** Window that owns the current menu */ wimp_w current_menu_window; /** Icon that owns the current menu (only valid for popup menus) */ static wimp_i current_menu_icon; -/** The height of the iconbar menu */ -int iconbar_menu_height = 5 * 44; /** The available menus */ -wimp_menu *iconbar_menu, *browser_menu, *image_quality_menu, - *browser_toolbar_menu, *tree_toolbar_menu, - *proxy_type_menu, *languages_menu; - -static wimp_MENU(URL_SUGGEST_MAX_URLS) url_suggest_menu_block; -wimp_menu *url_suggest_menu = (wimp_menu *) &url_suggest_menu_block; +wimp_menu *image_quality_menu, *proxy_type_menu, *languages_menu; /* the values given in PRM 3-157 for how to check menus/windows are * incorrect so we use a hack of checking if the sub-menu has bit 0 @@ -148,122 +126,6 @@ wimp_menu *url_suggest_menu = (wimp_menu *) &url_suggest_menu_block; */ void ro_gui_menu_init(void) { - /* iconbar menu */ - static const struct ns_menu iconbar_definition = { - "NetSurf", { - { "Info", NO_ACTION, &dialog_info }, - { "AppHelp", HELP_OPEN_CONTENTS, 0 }, - { "Open", BROWSER_NAVIGATE_URL, 0 }, - { "Open.OpenURL", BROWSER_NAVIGATE_URL, &dialog_openurl }, - { "Open.HotlistShow", HOTLIST_SHOW, 0 }, - { "Open.HistGlobal", HISTORY_SHOW_GLOBAL, 0 }, - { "Open.ShowCookies", COOKIES_SHOW, 0 }, - { "Choices", CHOICES_SHOW, 0 }, - { "Quit", APPLICATION_QUIT, 0 }, - {NULL, 0, 0} - } - }; - iconbar_menu = ro_gui_menu_define_menu(&iconbar_definition); - - /* browser menu */ - static const struct ns_menu browser_definition = { - "NetSurf", { - { "Page", BROWSER_PAGE, 0 }, - { "Page.PageInfo",BROWSER_PAGE_INFO, &dialog_pageinfo }, - { "Page.Save", BROWSER_SAVE, &dialog_saveas }, - { "Page.SaveComp", BROWSER_SAVE_COMPLETE, &dialog_saveas }, - { "Page.Export", NO_ACTION, 0 }, -#ifdef WITH_DRAW_EXPORT - { "Page.Export.Draw", BROWSER_EXPORT_DRAW, &dialog_saveas }, -#endif -#ifdef WITH_PDF_EXPORT - { "Page.Export.PDF", BROWSER_EXPORT_PDF, &dialog_saveas }, -#endif - { "Page.Export.Text", BROWSER_EXPORT_TEXT, &dialog_saveas }, - { "Page.SaveURL", NO_ACTION, 0 }, - { "Page.SaveURL.URI", BROWSER_SAVE_URL_URI, &dialog_saveas }, - { "Page.SaveURL.URL", BROWSER_SAVE_URL_URL, &dialog_saveas }, - { "Page.SaveURL.LinkText", BROWSER_SAVE_URL_TEXT, &dialog_saveas }, - { "_Page.Print", BROWSER_PRINT, &dialog_print }, - { "Page.NewWindow", BROWSER_NEW_WINDOW, 0 }, - { "Page.FindText", BROWSER_FIND_TEXT, &dialog_search }, - { "Page.ViewSrc", BROWSER_VIEW_SOURCE, 0 }, - { "Object", BROWSER_OBJECT, 0 }, - { "Object.Object", BROWSER_OBJECT_OBJECT, 0 }, - { "Object.Object.ObjInfo", BROWSER_OBJECT_INFO, &dialog_objinfo }, - { "Object.Object.ObjSave", BROWSER_OBJECT_SAVE, &dialog_saveas }, - { "Object.Object.Export", BROWSER_OBJECT_EXPORT, 0 }, - { "Object.Object.Export.Sprite", BROWSER_OBJECT_EXPORT_SPRITE, &dialog_saveas }, -#ifdef WITH_DRAW_EXPORT - { "Object.Object.Export.ObjDraw", BROWSER_OBJECT_EXPORT_DRAW, &dialog_saveas }, -#endif - { "Object.Object.SaveURL", NO_ACTION, 0 }, - { "Object.Object.SaveURL.URI", BROWSER_OBJECT_SAVE_URL_URI, &dialog_saveas }, - { "Object.Object.SaveURL.URL", BROWSER_OBJECT_SAVE_URL_URL, &dialog_saveas }, - { "Object.Object.SaveURL.LinkText", BROWSER_OBJECT_SAVE_URL_TEXT, &dialog_saveas }, - { "Object.Object.ObjPrint", BROWSER_OBJECT_PRINT, 0 }, - { "Object.Object.ObjReload", BROWSER_OBJECT_RELOAD, 0 }, - { "Object.Link", BROWSER_OBJECT_LINK, 0 }, - { "Object.Link.LinkSave", BROWSER_LINK_SAVE, 0 }, - { "Object.Link.LinkSave.URI", BROWSER_LINK_SAVE_URI, &dialog_saveas }, - { "Object.Link.LinkSave.URL", BROWSER_LINK_SAVE_URL, &dialog_saveas }, - { "Object.Link.LinkSave.LinkText", BROWSER_LINK_SAVE_TEXT, &dialog_saveas }, - { "_Object.Link.LinkDload", BROWSER_LINK_DOWNLOAD, 0 }, - { "Object.Link.LinkNew", BROWSER_LINK_NEW_WINDOW, 0 }, - { "Selection", BROWSER_SELECTION, 0 }, - { "_Selection.SelSave", BROWSER_SELECTION_SAVE, &dialog_saveas }, - { "Selection.Copy", BROWSER_SELECTION_COPY, 0 }, - { "Selection.Cut", BROWSER_SELECTION_CUT, 0 }, - { "_Selection.Paste", BROWSER_SELECTION_PASTE, 0 }, - { "Selection.Clear", BROWSER_SELECTION_CLEAR, 0 }, - { "Selection.SelectAll", BROWSER_SELECTION_ALL, 0 }, - { "Navigate", NO_ACTION, 0 }, - { "Navigate.Home", BROWSER_NAVIGATE_HOME, 0 }, - { "Navigate.Back", BROWSER_NAVIGATE_BACK, 0 }, - { "Navigate.Forward", BROWSER_NAVIGATE_FORWARD, 0 }, - { "_Navigate.UpLevel", BROWSER_NAVIGATE_UP, 0 }, - { "Navigate.Reload", BROWSER_NAVIGATE_RELOAD_ALL, 0 }, - { "Navigate.Stop", BROWSER_NAVIGATE_STOP, 0 }, - { "View", NO_ACTION, 0 }, - { "View.ScaleView", BROWSER_SCALE_VIEW, &dialog_zoom }, - { "View.Images", NO_ACTION, 0 }, - { "View.Images.ForeImg", BROWSER_IMAGES_FOREGROUND, 0 }, - { "View.Images.BackImg", BROWSER_IMAGES_BACKGROUND, 0 }, - { "View.Toolbars", NO_ACTION, 0 }, - { "View.Toolbars.ToolButtons", TOOLBAR_BUTTONS, 0 }, - { "View.Toolbars.ToolAddress", TOOLBAR_ADDRESS_BAR, 0 }, - { "_View.Toolbars.ToolThrob", TOOLBAR_THROBBER, 0 }, - { "View.Toolbars.EditToolbar", TOOLBAR_EDIT, 0 }, - { "_View.Render", NO_ACTION, 0 }, - { "View.Render.RenderAnims", BROWSER_BUFFER_ANIMS, 0 }, - { "View.Render.RenderAll", BROWSER_BUFFER_ALL, 0 }, - { "_View.OptDefault", BROWSER_SAVE_VIEW, 0 }, - { "View.Window", NO_ACTION, 0 }, - { "View.Window.WindowSave", BROWSER_WINDOW_DEFAULT, 0 }, - { "View.Window.WindowStagr", BROWSER_WINDOW_STAGGER, 0 }, - { "_View.Window.WindowSize", BROWSER_WINDOW_COPY, 0 }, - { "View.Window.WindowReset", BROWSER_WINDOW_RESET, 0 }, - { "Utilities", NO_ACTION, 0 }, - { "Utilities.Hotlist", HOTLIST_SHOW, 0 }, - { "Utilities.Hotlist.HotlistAdd", HOTLIST_ADD_URL, 0 }, - { "Utilities.Hotlist.HotlistShow", HOTLIST_SHOW, 0 }, - { "Utilities.History", HISTORY_SHOW_GLOBAL, 0 }, - { "Utilities.History.HistLocal", HISTORY_SHOW_LOCAL, 0 }, - { "Utilities.History.HistGlobal", HISTORY_SHOW_GLOBAL, 0 }, - { "Utilities.Cookies", COOKIES_SHOW, 0 }, - { "Utilities.Cookies.ShowCookies", COOKIES_SHOW, 0 }, - { "Utilities.Cookies.DeleteCookies", COOKIES_DELETE, 0 }, - { "Help", HELP_OPEN_CONTENTS, 0 }, - { "Help.HelpContent", HELP_OPEN_CONTENTS, 0 }, - { "Help.HelpGuide", HELP_OPEN_GUIDE, 0 }, - { "_Help.HelpInfo", HELP_OPEN_INFORMATION, 0 }, - { "_Help.HelpAbout", HELP_OPEN_ABOUT, 0 }, - { "Help.HelpInter", HELP_LAUNCH_INTERACTIVE, 0 }, - {NULL, 0, 0} - } - }; - browser_menu = ro_gui_menu_define_menu(&browser_definition); - /* image quality menu */ static const struct ns_menu images_definition = { "Display", { @@ -276,32 +138,6 @@ void ro_gui_menu_init(void) }; image_quality_menu = ro_gui_menu_define_menu(&images_definition); - /* browser toolbar menu */ - static const struct ns_menu browser_toolbar_definition = { - "Toolbar", { - { "Toolbars", NO_ACTION, 0 }, - { "Toolbars.ToolButtons", TOOLBAR_BUTTONS, 0 }, - { "Toolbars.ToolAddress", TOOLBAR_ADDRESS_BAR, 0 }, - { "Toolbars.ToolThrob", TOOLBAR_THROBBER, 0 }, - { "EditToolbar", TOOLBAR_EDIT, 0 }, - {NULL, 0, 0} - } - }; - browser_toolbar_menu = ro_gui_menu_define_menu( - &browser_toolbar_definition); - - /* tree toolbar menu */ - static const struct ns_menu tree_toolbar_definition = { - "Toolbar", { - { "Toolbars", NO_ACTION, 0 }, - { "Toolbars.ToolButtons", TOOLBAR_BUTTONS, 0 }, - { "EditToolbar", TOOLBAR_EDIT, 0 }, - {NULL, 0, 0} - } - }; - tree_toolbar_menu = ro_gui_menu_define_menu(&tree_toolbar_definition); - - /* proxy menu */ static const struct ns_menu proxy_type_definition = { "ProxyType", { @@ -315,7 +151,7 @@ void ro_gui_menu_init(void) proxy_type_menu = ro_gui_menu_define_menu(&proxy_type_definition); /* special case menus */ - ro_gui_url_suggest_init(url_suggest_menu); + ro_gui_url_suggest_init(); /* Note: This table *must* be kept in sync with the LangNames file */ static const struct ns_menu lang_definition = { @@ -381,16 +217,10 @@ void ro_gui_menu_init(void) * \param x The x position. * \param y The y position. * \param w The window that the menu belongs to. - * \param prepare true if the menu is to be prepared; otherwise - * false (mainly for use by wimp_event module). */ -void ro_gui_menu_create(wimp_menu *menu, int x, int y, wimp_w w, bool prepare) +void ro_gui_menu_create(wimp_menu *menu, int x, int y, wimp_w w) { - struct gui_window *g; os_error *error; - os_coord pos; - int i; - menu_action action; struct menu_definition *definition; /* translate menu, if necessary (this returns quickly @@ -403,62 +233,10 @@ void ro_gui_menu_create(wimp_menu *menu, int x, int y, wimp_w w, bool prepare) } } - /* read the object under the pointer for a new gui_window menu */ - if ((!current_menu) && (menu == browser_menu)) { - hlcache_handle *h; - - g = ro_gui_window_lookup(w); - h = g->bw->current_content; - - if (!ro_gui_window_to_window_pos(g, x, y, &pos)) - return; - current_menu_object = NULL; - current_menu_url = NULL; - if (h) { - switch (content_get_type(h)) { - case CONTENT_HTML: { - struct box *box; - box = box_object_at_point(h, pos.x, - pos.y); - current_menu_object = box ? - box->object : NULL; - box = box_href_at_point(h, pos.x, - pos.y); - current_menu_url = box ? - box->href : NULL; - } - break; - case CONTENT_TEXTPLAIN: - /* no object, no url */ - break; - default: - current_menu_object = h; - break; - } - } - } - /* store the menu characteristics */ current_menu = menu; current_menu_window = w; - current_menu_icon = -1; - - /* prepare the menu state */ - if (menu == url_suggest_menu) { - if (!ro_gui_url_suggest_prepare_menu()) - return; - } else if (menu == recent_search_menu) { - if (!ro_gui_search_prepare_menu()) - return; - } else if (prepare) { - i = 0; - do { - action = ro_gui_menu_find_action(menu, - &menu->entries[i]); - if (action != NO_ACTION) - ro_gui_menu_prepare_action(w, action, false); - } while (!(menu->entries[i++].menu_flags & wimp_MENU_LAST)); - } + current_menu_icon = wimp_ICON_WINDOW; /* create the menu */ current_menu_open = true; @@ -467,7 +245,7 @@ void ro_gui_menu_create(wimp_menu *menu, int x, int y, wimp_w w, bool prepare) LOG(("xwimp_create_menu: 0x%x: %s", error->errnum, error->errmess)); warn_user("MenuError", error->errmess); - ro_gui_menu_closed(true); + ro_gui_menu_closed(); } } @@ -507,42 +285,28 @@ void ro_gui_popup_menu(wimp_menu *menu, wimp_w w, wimp_i i) ro_gui_menu_create(menu, state.visible.x0 + icon_state.icon.extent.x1 + 64, state.visible.y1 + icon_state.icon.extent.y1 - - state.yscroll, w, true); + state.yscroll, w); current_menu_icon = i; } /** * Clean up after a menu has been closed, or forcible close an open menu. - * - * \param cleanup Call any terminating functions (sub-window isn't going to be instantly re-opened) - */ -void ro_gui_menu_closed(bool cleanup) + */ +void ro_gui_menu_closed(void) { - struct gui_window *g; - struct browser_window *bw; - hlcache_handle *h; - struct toolbar *t; os_error *error; - bool is_cookies, is_hotlist, is_global_history; if (current_menu) { - error = xwimp_create_menu(wimp_CLOSE_MENU, 0, 0); if (error) { LOG(("xwimp_create_menu: 0x%x: %s", error->errnum, error->errmess)); warn_user("MenuError", error->errmess); } - ro_gui_menu_get_window_details(current_menu_window, - &g, &bw, &h, &t, - &is_cookies, &is_hotlist, - &is_global_history); - - if (cleanup) { - ro_gui_wimp_event_menus_closed(current_menu_window, - current_menu_icon, current_menu); - } + + ro_gui_wimp_event_menus_closed(current_menu_window, + current_menu_icon, current_menu); current_menu = NULL; } @@ -550,46 +314,43 @@ void ro_gui_menu_closed(bool cleanup) current_menu_window = NULL; current_menu_icon = 0; current_menu_open = false; - gui_form_select_control = NULL; } /** - * The content has changed, reset object references + * Allow the current menu window to change, if the window is deleted and + * recreated while a menu is active on an Adjust-click. + * + * \param from The original window handle. + * \param to The new replacement window handle. */ -void ro_gui_menu_objects_moved(void) + +void ro_gui_menu_window_changed(wimp_w from, wimp_w to) { - gui_form_select_control = NULL; - current_menu_object = NULL; - current_menu_url = NULL; - ro_gui_menu_prepare_action(0, BROWSER_OBJECT, false); - if ((current_menu) && (current_menu == gui_form_select_menu)) - ro_gui_menu_closed(true); + if (from == current_menu_window) + current_menu_window = to; } /** * Handle menu selection. */ + void ro_gui_menu_selection(wimp_selection *selection) { - int i, j; - bool needs_prepare; + int i; //, j; wimp_menu_entry *menu_entry; menu_action action; wimp_pointer pointer; - struct gui_window *g = NULL; - wimp_menu *menu; os_error *error; int previous_menu_icon = current_menu_icon; - char *url; /* if we are using gui_multitask then menu selection events * may be delivered after the menu has been closed. As such, * we simply ignore these events. */ if (!current_menu) - return + return; assert(current_menu_window); @@ -600,51 +361,13 @@ void ro_gui_menu_selection(wimp_selection *selection) entries[selection->items[i]]; action = ro_gui_menu_find_action(current_menu, menu_entry); - /* Deal with the menu action. We first pass it to Wimp_Event to - * handle any automatic menus. If this doesn't recognise the details, - * it is passed on to the code in menus.c. + /* Deal with the menu action. If this manages to re-prepare the + * menu for re-opening, we test for and act on Adjust clicks. */ - needs_prepare = false; - if (!ro_gui_wimp_event_menu_selection(current_menu_window, - current_menu_icon, current_menu, selection, action)) { - - /* perform menu action */ - if (action != NO_ACTION) - ro_gui_menu_handle_action(current_menu_window, - action, false); - - /* perform non-automated actions */ - if (current_menu == url_suggest_menu) { - g = ro_gui_toolbar_lookup(current_menu_window); - if (g) { - url = url_suggest_menu->entries[selection->items[0]]. - data.indirected_text.text; - gui_window_set_url(g, url); - browser_window_go(g->bw, url, 0, true); - } - } else if (current_menu == gui_form_select_menu) { - g = ro_gui_window_lookup(current_menu_window); - assert(g); - - if (selection->items[0] >= 0) { - form_select_process_selection(g->bw->current_content, - gui_form_select_control, - selection->items[0]); - } - } - - /* allow automatic menus to have their data updated */ -// ro_gui_wimp_event_menu_selection(current_menu_window, -// current_menu_icon, current_menu, selection); - - /* Menus not handled by ro_gui_wimp_event_menu_selection() - * will need to be re-prepared before an adjust reopening. - */ - - needs_prepare = true; - } + current_menu_icon, current_menu, selection, action)) + return; /* re-open the menu for Adjust clicks */ error = xwimp_get_pointer_info(&pointer); @@ -652,43 +375,16 @@ void ro_gui_menu_selection(wimp_selection *selection) LOG(("xwimp_get_pointer_info: 0x%x: %s", error->errnum, error->errmess)); warn_user("WimpError", error->errmess); - ro_gui_menu_closed(true); + ro_gui_menu_closed(); return; } if (pointer.buttons != wimp_CLICK_ADJUST) { - ro_gui_menu_closed(true); + ro_gui_menu_closed(); return; } - /* re-prepare all the visible entries */ - if (needs_prepare) { - i = 0; - menu = current_menu; - do { - j = 0; - do { - action = ro_gui_menu_find_action(current_menu, - &menu->entries[j]); - if (action != NO_ACTION) - ro_gui_menu_prepare_action(current_menu_window, - action, false); - } while (!(menu->entries[j++].menu_flags & wimp_MENU_LAST)); - j = selection->items[i++]; - if (j != -1) { - menu = menu->entries[j].sub_menu; - if ((!menu) || (menu == wimp_NO_SUB_MENU)) - break; - } - } while (j != -1); - } - - if (current_menu == gui_form_select_menu) { - assert(g); /* Keep scan-build happy */ - gui_create_form_select_menu(g->bw, gui_form_select_control); - } else - ro_gui_menu_create(current_menu, 0, 0, current_menu_window, true); - + ro_gui_menu_create(current_menu, 0, 0, current_menu_window); current_menu_icon = previous_menu_icon; } @@ -701,7 +397,6 @@ void ro_gui_menu_warning(wimp_message_menu_warning *warning) int i; menu_action action; wimp_menu_entry *menu_entry; - wimp_menu *sub_menu; os_error *error; assert(current_menu); @@ -716,42 +411,31 @@ void ro_gui_menu_warning(wimp_message_menu_warning *warning) entries[warning->selection.items[i]]; action = ro_gui_menu_find_action(current_menu, menu_entry); - /* We only process the menu in the old way if the wimp_event module - * hasn't processed it for us. + /* Process the warning via Wimp_Event, then register the resulting + * submenu with the module. */ - if (!ro_gui_wimp_event_submenu_warning(current_menu_window, + ro_gui_wimp_event_submenu_warning(current_menu_window, current_menu_icon, current_menu, &(warning->selection), - action)) { - if (IS_MENU(menu_entry->sub_menu)) { - ro_gui_wimp_event_register_submenu((wimp_w)0); - sub_menu = menu_entry->sub_menu; - i = 0; - do { - action = ro_gui_menu_find_action(current_menu, - &sub_menu->entries[i]); - if (action != NO_ACTION) - ro_gui_menu_prepare_action(current_menu_window, - action, false); - } while (!(sub_menu->entries[i++].menu_flags & - wimp_MENU_LAST)); - } else { - ro_gui_wimp_event_register_submenu((wimp_w)menu_entry->sub_menu); - action = ro_gui_menu_find_action(current_menu, menu_entry); - if (action != NO_ACTION) - ro_gui_menu_prepare_action(current_menu_window, - action, true); - } - } + action); - /* If this is a dialogue box, remove the close and back icons. */ + if (IS_MENU(menu_entry->sub_menu)) { + ro_gui_wimp_event_register_submenu((wimp_w) 0); + } else { + ro_gui_wimp_event_register_submenu((wimp_w) + menu_entry->sub_menu); - if (!(IS_MENU(menu_entry->sub_menu))) - ro_gui_wimp_update_window_furniture((wimp_w)menu_entry->sub_menu, - wimp_WINDOW_CLOSE_ICON | wimp_WINDOW_BACK_ICON, 0); + /* If this is a dialogue box, remove the close and back icons. + */ + ro_gui_wimp_update_window_furniture((wimp_w) + menu_entry->sub_menu, + wimp_WINDOW_CLOSE_ICON | wimp_WINDOW_BACK_ICON, + 0); + } /* open the sub-menu */ + error = xwimp_create_sub_menu(menu_entry->sub_menu, warning->pos.x, warning->pos.y); if (error) { @@ -761,244 +445,42 @@ void ro_gui_menu_warning(wimp_message_menu_warning *warning) } } - /** - * Update navigate menu status and toolbar icons. + * Update the current menu by sending it a Menu Prepare event through wimp_event + * and then reopening it if the contents has changed. * - * /param gui the gui_window to update + * \param *menu The menu to refresh: if 0, the current menu will be + * refreshed regardless, otherwise it will be refreshed + * only if it matches the supplied handle. */ -void ro_gui_prepare_navigate(struct gui_window *gui) -{ - ro_gui_menu_prepare_action(gui->window, HOTLIST_SHOW, false); - ro_gui_menu_prepare_action(gui->window, BROWSER_NAVIGATE_STOP, false); - ro_gui_menu_prepare_action(gui->window, BROWSER_NAVIGATE_RELOAD_ALL, - false); - ro_gui_menu_prepare_action(gui->window, BROWSER_NAVIGATE_BACK, false); - ro_gui_menu_prepare_action(gui->window, BROWSER_NAVIGATE_FORWARD, - false); - ro_gui_menu_prepare_action(gui->window, BROWSER_NAVIGATE_UP, false); - ro_gui_menu_prepare_action(gui->window, HOTLIST_SHOW, false); - ro_gui_menu_prepare_action(gui->window, BROWSER_SAVE, false); - ro_gui_menu_prepare_action(gui->window, BROWSER_PRINT, false); - ro_gui_menu_prepare_action(gui->window, BROWSER_SCALE_VIEW, false); - ro_gui_menu_prepare_action(gui->window, BROWSER_FIND_TEXT, false); - - if (gui->toolbar) { - ro_gui_set_icon_shaded_state(gui->toolbar->toolbar_handle, - ICON_TOOLBAR_SUGGEST, - !ro_gui_url_suggest_prepare_menu()); - } -} - -/** - * Prepare the page info window for use - * - * \param g the gui_window to set the display icons for - */ -void ro_gui_menu_prepare_pageinfo(struct gui_window *g) -{ - hlcache_handle *h = g->bw->current_content; - char icon_buf[20] = "file_xxx"; - char enc_buf[40]; - char enc_token[10] = "Encoding0"; - const char *icon = icon_buf; - const char *title, *url, *mime; - const char *enc = "-"; - - assert(h); - - title = content_get_title(h); - if (title == NULL) - title = "-"; - url = content_get_url(h); - if (url == NULL) - url = "-"; - mime = content_get_mime_type(h); - if (mime == NULL) - mime = "-"; - - sprintf(icon_buf, "file_%x", ro_content_filetype(h)); - if (!ro_gui_wimp_sprite_exists(icon_buf)) - sprintf(icon_buf, "file_xxx"); - - if (content_get_type(h) == CONTENT_HTML) { - if (html_get_encoding(h)) { - enc_token[8] = '0' + html_get_encoding_source(h); - snprintf(enc_buf, sizeof enc_buf, "%s (%s)", - html_get_encoding(h), - messages_get(enc_token)); - enc = enc_buf; - } else { - enc = messages_get("EncodingUnk"); - } - } - - ro_gui_set_icon_string(dialog_pageinfo, ICON_PAGEINFO_ICON, icon, true); - ro_gui_set_icon_string(dialog_pageinfo, ICON_PAGEINFO_TITLE, title, true); - ro_gui_set_icon_string(dialog_pageinfo, ICON_PAGEINFO_URL, url, true); - ro_gui_set_icon_string(dialog_pageinfo, ICON_PAGEINFO_ENC, enc, true); - ro_gui_set_icon_string(dialog_pageinfo, ICON_PAGEINFO_TYPE, mime, true); -} - - -/** - * Prepare the object info window for use - * - * \param object the object for which information is to be displayed - * \param href corresponding href, if any - */ -void ro_gui_menu_prepare_objectinfo(hlcache_handle *object, const char *href) -{ - char icon_buf[20] = "file_xxx"; - const char *url, *mime; - const char *target = "-"; - - sprintf(icon_buf, "file_%.3x", - ro_content_filetype(object)); - if (!ro_gui_wimp_sprite_exists(icon_buf)) - sprintf(icon_buf, "file_xxx"); - - url = content_get_url(object); - if (url == NULL) - url = "-"; - mime = content_get_mime_type(object); - if (mime == NULL) - mime = "-"; - - if (href) - target = href; - - ro_gui_set_icon_string(dialog_objinfo, ICON_OBJINFO_ICON, icon_buf, true); - ro_gui_set_icon_string(dialog_objinfo, ICON_OBJINFO_URL, url, true); - ro_gui_set_icon_string(dialog_objinfo, ICON_OBJINFO_TARGET, target, true); - ro_gui_set_icon_string(dialog_objinfo, ICON_OBJINFO_TYPE, mime, true); -} - - -/** - * Display a menu of options for a form select control. - * - * \param bw browser window containing form control - * \param control form control of type GADGET_SELECT - */ -void gui_create_form_select_menu(struct browser_window *bw, - struct form_control *control) +void ro_gui_menu_refresh(wimp_menu *menu) { - unsigned int i, entries; - char *text_convert, *temp; - struct form_option *option; - wimp_pointer pointer; + int checksum = 0; os_error *error; - bool reopen = true; - utf8_convert_ret err; - assert(control); - - for (entries = 0, option = control->data.select.items; option; - option = option->next) - entries++; - if (entries == 0) { - ro_gui_menu_closed(true); + if (!current_menu_open) return; - } - if ((gui_form_select_menu) && (control != gui_form_select_control)) { - for (i = 0; ; i++) { - free(gui_form_select_menu->entries[i].data. - indirected_text.text); - if (gui_form_select_menu->entries[i].menu_flags & - wimp_MENU_LAST) - break; - } - free(gui_form_select_menu->title_data.indirected_text.text); - free(gui_form_select_menu); - gui_form_select_menu = 0; - } + checksum = ro_gui_menu_get_checksum(); - if (!gui_form_select_menu) { - reopen = false; - gui_form_select_menu = malloc(wimp_SIZEOF_MENU(entries)); - if (!gui_form_select_menu) { - warn_user("NoMemory", 0); - ro_gui_menu_closed(true); - return; - } - err = utf8_to_local_encoding(messages_get("SelectMenu"), 0, - &text_convert); - if (err != UTF8_CONVERT_OK) { - /* badenc should never happen */ - assert(err != UTF8_CONVERT_BADENC); - LOG(("utf8_to_local_encoding failed")); - warn_user("NoMemory", 0); - ro_gui_menu_closed(true); - return; - } - gui_form_select_menu->title_data.indirected_text.text = - text_convert; - ro_gui_menu_init_structure(gui_form_select_menu, entries); - } + if (!ro_gui_wimp_event_prepare_menu(current_menu_window, + current_menu_icon, current_menu)) + return; - for (i = 0, option = control->data.select.items; option; - i++, option = option->next) { - gui_form_select_menu->entries[i].menu_flags = 0; - if (option->selected) - gui_form_select_menu->entries[i].menu_flags = - wimp_MENU_TICKED; - if (!reopen) { - - /* convert spaces to hard spaces to stop things - * like 'Go Home' being treated as if 'Home' is a - * keyboard shortcut and right aligned in the menu. - */ - - temp = cnv_space2nbsp(option->text); - if (!temp) { - LOG(("cnv_space2nbsp failed")); - warn_user("NoMemory", 0); - ro_gui_menu_closed(true); - return; - } - - err = utf8_to_local_encoding(temp, - 0, &text_convert); - if (err != UTF8_CONVERT_OK) { - /* A bad encoding should never happen, - * so assert this */ - assert(err != UTF8_CONVERT_BADENC); - LOG(("utf8_to_enc failed")); - warn_user("NoMemory", 0); - ro_gui_menu_closed(true); - return; - } - - free(temp); - - gui_form_select_menu->entries[i].data.indirected_text.text = - text_convert; - gui_form_select_menu->entries[i].data.indirected_text.size = - strlen(gui_form_select_menu->entries[i]. - data.indirected_text.text) + 1; + /* \TODO -- Call the menu's event handler here. */ + + if (checksum != ro_gui_menu_get_checksum()) { + error = xwimp_create_menu(current_menu, 0, 0); + if (error) { + LOG(("xwimp_create_menu: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("MenuError", error->errmess); } } +} - gui_form_select_menu->entries[0].menu_flags |= - wimp_MENU_TITLE_INDIRECTED; - gui_form_select_menu->entries[i - 1].menu_flags |= wimp_MENU_LAST; - - error = xwimp_get_pointer_info(&pointer); - if (error) { - LOG(("xwimp_get_pointer_info: 0x%x: %s", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); - ro_gui_menu_closed(true); - return; - } - gui_form_select_control = control; - ro_gui_menu_create(gui_form_select_menu, - pointer.pos.x, pointer.pos.y, bw->window->window, true); -} /** @@ -1344,908 +826,6 @@ void ro_gui_menu_set_entry_ticked(wimp_menu *menu, menu_action action, } -/** - * Handles an action. - * - * \param owner the window to handle the action for - * \param action the action to handle - * \param windows_at_pointer whether to open any windows at the pointer location - */ -bool ro_gui_menu_handle_action(wimp_w owner, menu_action action, - bool windows_at_pointer) -{ - wimp_window_state state; - struct gui_window *g = NULL; - struct browser_window *bw = NULL; - hlcache_handle *h = NULL; - struct toolbar *t = NULL; - os_error *error; - char url[80]; - bool is_cookies, is_hotlist, is_global_history; - - ro_gui_menu_get_window_details(owner, &g, &bw, &h, &t, - &is_cookies, &is_hotlist, &is_global_history); - - switch (action) { - - /* help actions */ - case HELP_OPEN_CONTENTS: - ro_gui_open_help_page("documentation/index"); - return true; - case HELP_OPEN_GUIDE: - ro_gui_open_help_page("documentation/guide"); - return true; - case HELP_OPEN_INFORMATION: - ro_gui_open_help_page("documentation/info"); - return true; - case HELP_OPEN_ABOUT: - ro_gui_open_help_page("about/index"); - return true; - case HELP_LAUNCH_INTERACTIVE: - if (!ro_gui_interactive_help_available()) { - ro_gui_interactive_help_start(); - option_interactive_help = true; - } else { - option_interactive_help = !option_interactive_help; - } - return true; - - /* history actions */ - case HISTORY_SHOW_LOCAL: - if ((!bw) || (!bw->history)) - return false; - ro_gui_history_open(bw, bw->history, - windows_at_pointer); - return true; - case HISTORY_SHOW_GLOBAL: - ro_gui_global_history_open(); - return true; - - /* hotlist actions */ - case HOTLIST_ADD_URL: - if (h == NULL || content_get_url(h) == NULL) - return false; - hotlist_add_page(content_get_url(h)); - return true; - case HOTLIST_SHOW: - ro_gui_hotlist_open(); - return true; - - /* cookies actions */ - case COOKIES_SHOW: - ro_gui_cookies_open(); - return true; - - case COOKIES_DELETE: - cookies_delete_all(); - return true; - - /* page actions */ - case BROWSER_PAGE_INFO: - if (!h) - return false; - ro_gui_menu_prepare_action(owner, action, true); - ro_gui_dialog_open_persistent(g->window, - dialog_pageinfo, windows_at_pointer); - return true; - case BROWSER_PRINT: - if (!h) - return false; - ro_gui_menu_prepare_action(owner, action, true); - ro_gui_dialog_open_persistent(g->window, - dialog_print, windows_at_pointer); - return true; - case BROWSER_NEW_WINDOW: - if (!h) - return false; - browser_window_create(content_get_url(h), bw, 0, false, - false); - return true; - case BROWSER_VIEW_SOURCE: - if (!h) - return false; - ro_gui_view_source(h); - return true; - - /* object actions */ - case BROWSER_OBJECT_INFO: - if (!current_menu_object) - return false; - ro_gui_menu_prepare_action(owner, action, true); - ro_gui_dialog_open_persistent(g->window, - dialog_objinfo, windows_at_pointer); - return true; - case BROWSER_OBJECT_RELOAD: - if (!current_menu_object) - return false; - content_invalidate_reuse_data(current_menu_object); - browser_window_reload(bw, false); - return true; - - /* link actions */ - case BROWSER_LINK_SAVE_URI: - case BROWSER_LINK_SAVE_URL: - case BROWSER_LINK_SAVE_TEXT: - if (!current_menu_url) - return false; - ro_gui_menu_prepare_action(owner, action, true); - ro_gui_dialog_open_persistent(owner, dialog_saveas, - windows_at_pointer); - break; - case BROWSER_LINK_DOWNLOAD: - if (!current_menu_url) - return false; - browser_window_download(bw, current_menu_url, - content_get_url(h)); - break; - case BROWSER_LINK_NEW_WINDOW: - if (!current_menu_url) - return false; - browser_window_create(current_menu_url, bw, - content_get_url(h), true, false); - break; - - /* save actions */ - case BROWSER_OBJECT_SAVE: - case BROWSER_OBJECT_EXPORT_SPRITE: - case BROWSER_OBJECT_EXPORT_DRAW: - h = current_menu_object; - /* Fall through */ - case BROWSER_SAVE: - case BROWSER_SAVE_COMPLETE: - case BROWSER_EXPORT_DRAW: - case BROWSER_EXPORT_PDF: - case BROWSER_EXPORT_TEXT: - case BROWSER_SAVE_URL_URI: - case BROWSER_SAVE_URL_URL: - case BROWSER_SAVE_URL_TEXT: - if (!h) - return false; - /* Fall through */ - ro_gui_menu_prepare_action(owner, action, true); - ro_gui_dialog_open_persistent(owner, dialog_saveas, - windows_at_pointer); - return true; - - /* selection actions */ - case BROWSER_SELECTION_SAVE: - ro_gui_menu_prepare_action(owner, action, true); - ro_gui_dialog_open_persistent(owner, dialog_saveas, - windows_at_pointer); - return true; - case BROWSER_SELECTION_COPY: - browser_window_key_press(bw, KEY_COPY_SELECTION); - break; - case BROWSER_SELECTION_CUT: - browser_window_key_press(bw, KEY_CUT_SELECTION); - return true; - case BROWSER_SELECTION_PASTE: - browser_window_key_press(bw, KEY_PASTE); - return true; - case BROWSER_SELECTION_ALL: - browser_window_key_press(bw, KEY_SELECT_ALL); - break; - case BROWSER_SELECTION_CLEAR: - browser_window_key_press(bw, KEY_CLEAR_SELECTION); - break; - - /* navigation actions */ - case BROWSER_NAVIGATE_HOME: - if (!bw) - return false; - if ((option_homepage_url) && - (option_homepage_url[0])) { - browser_window_go(g->bw, - option_homepage_url, 0, true); - } else { - snprintf(url, sizeof url, - "file:////Docs/welcome/index_%s", - option_language); - browser_window_go(g->bw, url, 0, true); - } - return true; - case BROWSER_NAVIGATE_BACK: - if ((!bw) || (!bw->history)) - return false; - history_back(bw, bw->history); - return true; - case BROWSER_NAVIGATE_FORWARD: - if ((!bw) || (!bw->history)) - return false; - history_forward(bw, bw->history); - return true; - case BROWSER_NAVIGATE_UP: - if ((!bw) || (!h)) - return false; - return ro_gui_window_navigate_up(bw->window, - content_get_url(h)); - case BROWSER_NAVIGATE_RELOAD: - case BROWSER_NAVIGATE_RELOAD_ALL: - if (!bw) - return false; - browser_window_reload(bw, - (action == BROWSER_NAVIGATE_RELOAD_ALL)); - return true; - case BROWSER_NAVIGATE_STOP: - if (!bw) - return false; - browser_window_stop(bw); - return true; - case BROWSER_NAVIGATE_URL: - ro_gui_menu_prepare_action(owner, action, true); - ro_gui_dialog_open_persistent(NULL, dialog_openurl, - windows_at_pointer); - return true; - - /* browser window/display actions */ - case BROWSER_SCALE_VIEW: - if (!h) - return false; - ro_gui_menu_prepare_action(owner, action, true); - ro_gui_dialog_open_persistent(g->window, dialog_zoom, - windows_at_pointer); - return true; - case BROWSER_FIND_TEXT: - if (!h || (content_get_type(h) != CONTENT_TEXTPLAIN && - content_get_type(h) != CONTENT_HTML)) - return false; - ro_gui_menu_prepare_action(owner, action, true); - ro_gui_dialog_open_persistent(g->window, - dialog_search, windows_at_pointer); - return true; - case BROWSER_IMAGES_BACKGROUND: - if (!g) - return false; - g->option.background_images = - !g->option.background_images; - gui_window_redraw_window(g); - return true; - case BROWSER_BUFFER_ANIMS: - if (!g) - return false; - g->option.buffer_animations = - !g->option.buffer_animations; - break; - case BROWSER_BUFFER_ALL: - if (!g) - return false; - g->option.buffer_everything = - !g->option.buffer_everything; - break; - case BROWSER_SAVE_VIEW: - if (!bw) - return false; - ro_gui_window_default_options(bw); - ro_gui_save_options(); - return true; - case BROWSER_WINDOW_DEFAULT: - if (!g) - return false; - ro_gui_screen_size(&option_window_screen_width, - &option_window_screen_height); - state.w = current_menu_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); - } - option_window_x = state.visible.x0; - option_window_y = state.visible.y0; - option_window_width = - state.visible.x1 - state.visible.x0; - option_window_height = - state.visible.y1 - state.visible.y0; - ro_gui_save_options(); - return true; - case BROWSER_WINDOW_STAGGER: - option_window_stagger = !option_window_stagger; - ro_gui_save_options(); - return true; - case BROWSER_WINDOW_COPY: - option_window_size_clone = !option_window_size_clone; - ro_gui_save_options(); - return true; - case BROWSER_WINDOW_RESET: - option_window_screen_width = 0; - option_window_screen_height = 0; - ro_gui_save_options(); - return true; - - /* toolbar actions */ - case TOOLBAR_BUTTONS: - assert(t); - t->display_buttons = !t->display_buttons; - ro_gui_theme_refresh_toolbar(t); - return true; - case TOOLBAR_ADDRESS_BAR: - assert(t); - t->display_url = !t->display_url; - ro_gui_theme_refresh_toolbar(t); - if (t->display_url) - ro_gui_set_caret_first(t->toolbar_handle); - return true; - case TOOLBAR_THROBBER: - assert(t); - t->display_throbber = !t->display_throbber; - ro_gui_theme_refresh_toolbar(t); - return true; - case TOOLBAR_EDIT: - assert(t); - ro_gui_theme_toggle_edit(t); - return true; - - /* misc actions */ - case APPLICATION_QUIT: - if (ro_gui_prequit()) { - LOG(("QUIT in response to user request")); - netsurf_quit = true; - } - return true; - case CHOICES_SHOW: - ro_gui_configure_show(); - return true; - - /* unknown action */ - default: - return false; - } - return false; -} - - -/** - * Prepares an action for use. - * - * \param owner the window to prepare the action for - * \param action the action to prepare - * \param windows whether to update sub-windows - */ -void ro_gui_menu_prepare_action(wimp_w owner, menu_action action, - bool windows) -{ - struct gui_window *g; - struct browser_window *bw; - hlcache_handle *h; - struct toolbar *t; - bool result = false; - int checksum = 0; - os_error *error; - char *parent; - url_func_result res; - bool compare; - bool is_cookies, is_hotlist, is_global_history; - - ro_gui_menu_get_window_details(owner, &g, &bw, &h, &t, - &is_cookies, &is_hotlist, &is_global_history); - if (current_menu_open) - checksum = ro_gui_menu_get_checksum(); - if (!h) { - current_menu_object = NULL; - current_menu_url = NULL; - } - - switch (action) { - - /* help actions */ - case HELP_LAUNCH_INTERACTIVE: - result = ro_gui_interactive_help_available() - && option_interactive_help; - ro_gui_menu_set_entry_ticked(current_menu, - action, result); - ro_gui_save_options(); - break; - - /* history actions */ - case HISTORY_SHOW_LOCAL: - ro_gui_menu_set_entry_shaded(current_menu, action, - (!bw || (!bw->history) || - !(h || history_back_available(bw->history) || - history_forward_available(bw->history)))); - break; - - /* hotlist actions */ - case HOTLIST_ADD_URL: - ro_gui_menu_set_entry_shaded(current_menu, action, - h == NULL); - break; - - /* page actions */ - case BROWSER_PAGE: - ro_gui_menu_set_entry_shaded(current_menu, - action, !h || - (content_get_type(h) != CONTENT_HTML && - content_get_type(h) != CONTENT_TEXTPLAIN)); - break; - case BROWSER_PAGE_INFO: - ro_gui_menu_set_entry_shaded(current_menu, - action, !h); - if ((windows) && (h)) - ro_gui_menu_prepare_pageinfo(g); - break; - case BROWSER_PRINT: - ro_gui_menu_set_entry_shaded(current_menu, - action, !h); - if ((t) && (t->type == THEME_BROWSER_TOOLBAR)) - ro_gui_set_icon_shaded_state( - t->toolbar_handle, - ICON_TOOLBAR_PRINT, !h); - if ((windows) && (h)) - ro_gui_print_prepare(g); - if ((t) && (!t->editor) && - (t->type == THEME_BROWSER_TOOLBAR)) - ro_gui_set_icon_shaded_state( - t->toolbar_handle, - ICON_TOOLBAR_PRINT, !h); - break; - case BROWSER_NEW_WINDOW: - case BROWSER_VIEW_SOURCE: - ro_gui_menu_set_entry_shaded(current_menu, - action, !h); - break; - - /* object actions */ - case BROWSER_OBJECT: - ro_gui_menu_set_entry_shaded(current_menu, action, - !current_menu_object && - !current_menu_url); - break; - - case BROWSER_OBJECT_LINK: - ro_gui_menu_set_entry_shaded(current_menu, action, - !current_menu_url); - break; - - case BROWSER_OBJECT_INFO: - if (windows && current_menu_object) - ro_gui_menu_prepare_objectinfo( - current_menu_object, - current_menu_url); - /* Fall through */ - case BROWSER_OBJECT_RELOAD: - case BROWSER_OBJECT_OBJECT: - ro_gui_menu_set_entry_shaded(current_menu, action, - !current_menu_object); - break; - - case BROWSER_OBJECT_PRINT: - /* not yet implemented */ - ro_gui_menu_set_entry_shaded(current_menu, action, - true); - break; - - /* save actions (browser, hotlist, history) */ - case BROWSER_OBJECT_SAVE: - ro_gui_menu_set_entry_shaded(current_menu, - action, !current_menu_object); - if (windows && current_menu_object) - ro_gui_save_prepare(GUI_SAVE_OBJECT_ORIG, - current_menu_object, - NULL, NULL, NULL); - break; - case BROWSER_OBJECT_EXPORT: - case BROWSER_OBJECT_EXPORT_SPRITE: - case BROWSER_OBJECT_EXPORT_DRAW: { - bool exp_sprite = false; - bool exp_draw = false; - - if (current_menu_object) - h = current_menu_object; - - if (h) { - switch (content_get_type(h)) { -/* \todo - this classification should prob be done in content_() */ - /* bitmap types (Sprite export possible) */ -#ifdef WITH_JPEG - case CONTENT_JPEG: -#endif -#ifdef WITH_MNG - case CONTENT_JNG: - case CONTENT_MNG: -#endif -#ifdef WITH_GIF - case CONTENT_GIF: -#endif -#ifdef WITH_BMP - case CONTENT_BMP: - case CONTENT_ICO: -#endif -#if defined(WITH_MNG) || defined(WITH_PNG) - case CONTENT_PNG: -#endif -#ifdef WITH_SPRITE - case CONTENT_SPRITE: -#endif - exp_sprite = true; - break; - - /* vector types (Draw export possible) */ -#if defined(WITH_NS_SVG) || defined(WITH_RSVG) - case CONTENT_SVG: -#endif -#ifdef WITH_DRAW - case CONTENT_DRAW: -#endif - exp_draw = true; - break; - - default: break; - } - } - - switch (action) { - case BROWSER_OBJECT_EXPORT_SPRITE: - if (!exp_sprite) - h = NULL; - break; - case BROWSER_OBJECT_EXPORT_DRAW: - if (!exp_draw) - h = NULL; - break; - default: - if (!exp_sprite && !exp_draw) - h = NULL; - break; - } - - ro_gui_menu_set_entry_shaded(current_menu, - action, !h); - if ((h) && (windows)) - ro_gui_save_prepare(GUI_SAVE_OBJECT_NATIVE, h, NULL, NULL, NULL); - } - break; - case BROWSER_LINK_SAVE_URI: - case BROWSER_LINK_SAVE_URL: - case BROWSER_LINK_SAVE_TEXT: - ro_gui_menu_set_entry_shaded(current_menu, - action, !current_menu_url); - if (windows && current_menu_url) { - gui_save_type save_type; - switch (action) { - case BROWSER_LINK_SAVE_URI: - save_type = GUI_SAVE_LINK_URI; - break; - case BROWSER_LINK_SAVE_URL: - save_type = GUI_SAVE_LINK_URL; - break; - default: - save_type = GUI_SAVE_LINK_TEXT; - break; - } - ro_gui_save_prepare(save_type, NULL, NULL, - current_menu_url, NULL); - } - break; - - case BROWSER_SELECTION: - /* make menu available if there's anything that /could/ - * be selected */ - ro_gui_menu_set_entry_shaded(current_menu, action, - !h || (content_get_type(h) != CONTENT_HTML && - content_get_type(h) != CONTENT_TEXTPLAIN)); - break; - case BROWSER_SELECTION_SAVE: - if (h && (!bw->sel || !selection_defined(bw->sel))) - h = NULL; - ro_gui_menu_set_entry_shaded(current_menu, action, !h); - if ((h) && (windows)) - ro_gui_save_prepare(GUI_SAVE_TEXT_SELECTION, NULL, bw->sel, NULL, NULL); - break; - case BROWSER_SELECTION_COPY: - ro_gui_menu_set_entry_shaded(current_menu, action, - !(h && bw->sel && selection_defined(bw->sel))); - break; - case BROWSER_SELECTION_CUT: - ro_gui_menu_set_entry_shaded(current_menu, action, - !(h && bw->sel && selection_defined(bw->sel) - && !selection_read_only(bw->sel))); - break; - case BROWSER_SELECTION_PASTE: - ro_gui_menu_set_entry_shaded(current_menu, action, - !(h && bw->paste_callback)); - break; - case BROWSER_SAVE: - ro_gui_menu_set_entry_shaded(current_menu, - action, !h); - if ((h) && (windows)) - ro_gui_save_prepare(GUI_SAVE_SOURCE, h, NULL, NULL, NULL); - if ((t) && (!t->editor) && - (t->type == THEME_BROWSER_TOOLBAR)) - ro_gui_set_icon_shaded_state( - t->toolbar_handle, - ICON_TOOLBAR_SAVE, !h); - break; - case BROWSER_SAVE_COMPLETE: - ro_gui_menu_set_entry_shaded(current_menu, - action, !h); - if ((h) && (windows)) - ro_gui_save_prepare(GUI_SAVE_COMPLETE, h, NULL, NULL, NULL); - break; - case BROWSER_EXPORT_DRAW: - ro_gui_menu_set_entry_shaded(current_menu, - action, !h); - if ((h) && (windows)) - ro_gui_save_prepare(GUI_SAVE_DRAW, h, NULL, NULL, NULL); - break; - case BROWSER_EXPORT_PDF: - ro_gui_menu_set_entry_shaded(current_menu, - action, !h); - if ((h) && (windows)) - ro_gui_save_prepare(GUI_SAVE_PDF, h, NULL, NULL, NULL); - break; - case BROWSER_EXPORT_TEXT: - ro_gui_menu_set_entry_shaded(current_menu, - action, !h); - if ((h) && (windows)) - ro_gui_save_prepare(GUI_SAVE_TEXT, h, NULL, NULL, NULL); - break; - case BROWSER_OBJECT_SAVE_URL_URI: - if (h && content_get_type(h) == CONTENT_HTML) - h = current_menu_object; - /* Fall through */ - case BROWSER_SAVE_URL_URI: - ro_gui_menu_set_entry_shaded(current_menu, - action, !h); - if ((h) && (windows)) - ro_gui_save_prepare(GUI_SAVE_LINK_URI, NULL, - NULL, - content_get_url(h), - content_get_title(h)); - break; - case BROWSER_OBJECT_SAVE_URL_URL: - if (h && content_get_type(h) == CONTENT_HTML) - h = current_menu_object; - /* Fall through */ - case BROWSER_SAVE_URL_URL: - ro_gui_menu_set_entry_shaded(current_menu, - action, !h); - if ((h) && (windows)) - ro_gui_save_prepare(GUI_SAVE_LINK_URL, NULL, - NULL, - content_get_url(h), - content_get_title(h)); - break; - case BROWSER_OBJECT_SAVE_URL_TEXT: - h = current_menu_object; - /* Fall through */ - case BROWSER_SAVE_URL_TEXT: - ro_gui_menu_set_entry_shaded(current_menu, - action, !h); - if ((h) && (windows)) - ro_gui_save_prepare(GUI_SAVE_LINK_TEXT, NULL, - NULL, - content_get_url(h), - content_get_title(h)); - break; - - /* navigation actions */ - case BROWSER_NAVIGATE_BACK: - result = browser_window_back_available(bw); - ro_gui_menu_set_entry_shaded(current_menu, - action, !result); - if ((t) && (!t->editor) && - (t->type == THEME_BROWSER_TOOLBAR)) - ro_gui_set_icon_shaded_state( - t->toolbar_handle, - ICON_TOOLBAR_BACK, !result); - break; - case BROWSER_NAVIGATE_FORWARD: - result = browser_window_forward_available(bw); - ro_gui_menu_set_entry_shaded(current_menu, - action, !result); - if ((t) && (!t->editor) && - (t->type == THEME_BROWSER_TOOLBAR)) - ro_gui_set_icon_shaded_state( - t->toolbar_handle, - ICON_TOOLBAR_FORWARD, !result); - break; - case BROWSER_NAVIGATE_UP: - result = (bw && h); - if (result) { - res = url_parent(content_get_url(h), &parent); - if (res == URL_FUNC_OK) { - res = url_compare(content_get_url(h), - parent, false, - &compare); - if (res == URL_FUNC_OK) - result = !compare; - free(parent); - } else { - result = false; - } - } - ro_gui_menu_set_entry_shaded(current_menu, - action, !result); - if ((t) && (!t->editor) && - (t->type == THEME_BROWSER_TOOLBAR)) - ro_gui_set_icon_shaded_state( - t->toolbar_handle, - ICON_TOOLBAR_UP, !result); - break; - case BROWSER_NAVIGATE_RELOAD: - case BROWSER_NAVIGATE_RELOAD_ALL: - result = browser_window_reload_available(bw); - ro_gui_menu_set_entry_shaded(current_menu, - action, !result); - if ((t) && (!t->editor) && - (t->type == THEME_BROWSER_TOOLBAR)) - ro_gui_set_icon_shaded_state( - t->toolbar_handle, - ICON_TOOLBAR_RELOAD, !result); - break; - case BROWSER_NAVIGATE_STOP: - result = browser_window_stop_available(bw); - ro_gui_menu_set_entry_shaded(current_menu, - action, !result); - if ((t) && (!t->editor) && - (t->type == THEME_BROWSER_TOOLBAR)) - ro_gui_set_icon_shaded_state( - t->toolbar_handle, - ICON_TOOLBAR_STOP, !result); - break; - case BROWSER_NAVIGATE_URL: - if (windows) - ro_gui_dialog_prepare_open_url(); - break; - - /* display actions */ - case BROWSER_SCALE_VIEW: - ro_gui_menu_set_entry_shaded(current_menu, - action, !h); - if ((h) && (windows)) - ro_gui_dialog_prepare_zoom(g); - if ((t) && (!t->editor) && - (t->type == THEME_BROWSER_TOOLBAR)) - ro_gui_set_icon_shaded_state( - t->toolbar_handle, - ICON_TOOLBAR_SCALE, !h); - break; - case BROWSER_FIND_TEXT: - result = !h || (content_get_type(h) != CONTENT_HTML && - content_get_type(h) != CONTENT_TEXTPLAIN); - ro_gui_menu_set_entry_shaded(current_menu, - action, result); - if ((!result) && (windows)) { - ro_gui_search_prepare(g->bw); - } - if ((t) && (!t->editor) && - (t->type == THEME_BROWSER_TOOLBAR)) - ro_gui_set_icon_shaded_state( - t->toolbar_handle, - ICON_TOOLBAR_SEARCH, result); - break; - case BROWSER_IMAGES_FOREGROUND: - ro_gui_menu_set_entry_shaded(current_menu, - action, true); - ro_gui_menu_set_entry_ticked(current_menu, - action, true); - break; - case BROWSER_IMAGES_BACKGROUND: - if (g) - ro_gui_menu_set_entry_ticked(current_menu, - action, g->option.background_images); - break; - case BROWSER_BUFFER_ANIMS: - if (g) { - ro_gui_menu_set_entry_shaded(current_menu, - action, g->option.buffer_everything); - ro_gui_menu_set_entry_ticked(current_menu, - action, - g->option.buffer_animations || - g->option.buffer_everything); - } - break; - case BROWSER_BUFFER_ALL: - if (g) - ro_gui_menu_set_entry_ticked(current_menu, - action, g->option.buffer_everything); - break; - case BROWSER_WINDOW_STAGGER: - ro_gui_menu_set_entry_shaded(current_menu, action, - option_window_screen_width == 0); - ro_gui_menu_set_entry_ticked(current_menu, action, - ((option_window_screen_width == 0) || - option_window_stagger)); - break; - case BROWSER_WINDOW_COPY: - ro_gui_menu_set_entry_ticked(current_menu, action, - option_window_size_clone); - break; - case BROWSER_WINDOW_RESET: - ro_gui_menu_set_entry_shaded(current_menu, action, - option_window_screen_width == 0); - break; - - /* tree actions */ - case TREE_SELECTION: - break; - - /* toolbar actions */ - case TOOLBAR_BUTTONS: - ro_gui_menu_set_entry_shaded(current_menu, - action, (!t || (t->editor))); - ro_gui_menu_set_entry_ticked(current_menu, - action, (t && - ((t->display_buttons) || (t->editor)))); - break; - case TOOLBAR_ADDRESS_BAR: - ro_gui_menu_set_entry_shaded(current_menu, - action, !t); - ro_gui_menu_set_entry_ticked(current_menu, action, - (t && t->display_url)); - break; - case TOOLBAR_THROBBER: - ro_gui_menu_set_entry_shaded(current_menu, - action, !t); - ro_gui_menu_set_entry_ticked(current_menu, action, - (t && t->display_throbber)); - break; - case TOOLBAR_EDIT: - ro_gui_menu_set_entry_shaded(current_menu, - action, !t); - ro_gui_menu_set_entry_ticked(current_menu, action, - (t && t->editor)); - break; - - /* unknown action */ - default: - return; - } - - /* update open menus */ - if ((current_menu_open) && - (checksum != ro_gui_menu_get_checksum())) { - error = xwimp_create_menu(current_menu, 0, 0); - if (error) { - LOG(("xwimp_create_menu: 0x%x: %s", - error->errnum, error->errmess)); - warn_user("MenuError", error->errmess); - } - } -} - - -/** - * Gets various details relating to a window - * - * \param w the window to complete information for - */ -void ro_gui_menu_get_window_details(wimp_w w, struct gui_window **g, - struct browser_window **bw, hlcache_handle **h, - struct toolbar **toolbar, - bool *is_cookies, bool *is_hotlist, bool *is_global_history) -{ - *is_cookies = false; - *is_hotlist = false; - *is_global_history = false; - - *g = ro_gui_window_lookup(w); - - if (*g) { - *bw = (*g)->bw; - *toolbar = (*g)->toolbar; - if (*bw) - *h = (*bw)->current_content; - } else { - *bw = NULL; - *h = NULL; - if (ro_gui_hotlist_check_window(w)) { - *is_hotlist = true; -// *toolbar = treeview_window->toolbar; - } else if (ro_gui_global_history_check_window(w)) { - *is_global_history = true; -// *toolbar = treeview_window->toolbar; - } else if (ro_gui_cookies_check_window(w)) { - *is_cookies = true; -// *toolbar = treeview_window->toolbar; - } else { - *toolbar = NULL; - } - } -} - - /** * Calculates a simple checksum for the current menu state */ @@ -2364,3 +944,4 @@ bool ro_gui_menu_translate(struct menu_definition *menu) return true; } + diff --git a/riscos/menus.h b/riscos/menus.h index 197aee9d1..ef768e96d 100644 --- a/riscos/menus.h +++ b/riscos/menus.h @@ -23,13 +23,9 @@ #include "oslib/wimp.h" #include "riscos/gui.h" -extern wimp_menu *iconbar_menu, *browser_menu, *hotlist_menu, *cookies_menu, - *global_history_menu, *image_quality_menu, - *browser_toolbar_menu, *tree_toolbar_menu, *proxy_type_menu; -extern wimp_menu *languages_menu, *url_suggest_menu; +extern wimp_menu *image_quality_menu, *proxy_type_menu, *languages_menu; extern wimp_menu *current_menu; -extern int iconbar_menu_height; typedef enum { @@ -170,21 +166,16 @@ struct ns_menu { void ro_gui_menu_init(void); -void ro_gui_menu_create(wimp_menu* menu, int x, int y, wimp_w w, bool prepare); -bool ro_gui_menu_handle_action(wimp_w owner, menu_action action, - bool windows_at_pointer); -void ro_gui_menu_prepare_action(wimp_w owner, menu_action action, - bool windows); -void ro_gui_menu_closed(bool cleanup); -void ro_gui_menu_objects_moved(void); +void ro_gui_menu_create(wimp_menu* menu, int x, int y, wimp_w w); +void ro_gui_menu_closed(void); void ro_gui_popup_menu(wimp_menu *menu, wimp_w w, wimp_i i); +void ro_gui_menu_window_changed(wimp_w from, wimp_w to); void ro_gui_menu_selection(wimp_selection* selection); void ro_gui_menu_warning(wimp_message_menu_warning *warning); +void ro_gui_menu_refresh(wimp_menu *menu); void ro_gui_menu_init_structure(wimp_menu *menu, int entries); -void ro_gui_prepare_navigate(struct gui_window *gui); const char *ro_gui_menu_find_menu_entry_key(wimp_menu *menu, const char *translated); - wimp_menu *ro_gui_menu_define_menu(const struct ns_menu *menu); void ro_gui_menu_set_entry_shaded(wimp_menu *menu, menu_action action, bool shaded); diff --git a/riscos/plugin.c b/riscos/plugin.c index 340eaaf3e..19fd2b806 100644 --- a/riscos/plugin.c +++ b/riscos/plugin.c @@ -63,7 +63,7 @@ #include "riscos/gui.h" #include "riscos/options.h" #include "riscos/plugin.h" -#include "riscos/theme.h" +#include "riscos/toolbar.h" #include "utils/log.h" #include "utils/messages.h" #include "utils/url.h" @@ -362,8 +362,7 @@ void plugin_open(struct content *c, struct browser_window *bw, pmo.bbox.x0 = 10; /* avoid toolbar */ - pmo.bbox.y1 = -10 - (bw->window->toolbar ? - bw->window->toolbar->height : 0); + pmo.bbox.y1 = -10 - ro_toolbar_height(bw->window->toolbar); pmo.bbox.x1 = (state.visible.x1 - state.visible.x0) - 10; pmo.bbox.y0 = (state.visible.y0 - state.visible.y1) - 10; } @@ -501,8 +500,8 @@ void plugin_reformat(struct content *c, int width, int height) /* standalone */ x = 10 / 2; /* avoid toolbar */ - y = (10 + (c->data.plugin.bw->window->toolbar ? - c->data.plugin.bw->window->toolbar->height : 0)) / 2; + y = (10 + ro_toolbar_height( + c->data.plugin.bw->window->toolbar0)) / 2; } pmr.size = 52; diff --git a/riscos/print.c b/riscos/print.c index 1a66e7e12..807b12eeb 100644 --- a/riscos/print.c +++ b/riscos/print.c @@ -532,7 +532,7 @@ void ro_print_cleanup(void) print_text_black = false; print_prev_message = 0; print_max_sheets = -1; - ro_gui_menu_closed(true); + ro_gui_menu_closed(); ro_gui_dialog_close(dialog_print); } diff --git a/riscos/search.c b/riscos/search.c index 502a2cb02..ec98b969c 100644 --- a/riscos/search.c +++ b/riscos/search.c @@ -66,6 +66,9 @@ wimp_menu *recent_search_menu = (wimp_menu *)&menu_recent; static void ro_gui_search_end(wimp_w w); static bool ro_gui_search_next(wimp_w w); +static bool ro_gui_search_menu_prepare(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_pointer *pointer); +static bool ro_gui_search_prepare_menu(void); static bool ro_gui_search_click(wimp_pointer *pointer); static bool ro_gui_search_keypress(wimp_key *key); static search_flags_t ro_gui_search_update_flags(void); @@ -90,6 +93,8 @@ void ro_gui_search_init(void) ro_gui_search_keypress); ro_gui_wimp_event_register_close_window(dialog_search, ro_gui_search_end); + ro_gui_wimp_event_register_menu_prepare(dialog_search, + ro_gui_search_menu_prepare); ro_gui_wimp_event_register_menu_gright(dialog_search, ICON_SEARCH_TEXT, ICON_SEARCH_MENU, recent_search_menu); @@ -117,7 +122,7 @@ void ro_gui_search_init(void) bool ro_gui_search_next(wimp_w w) { search_data.search_insert = true; - search_flags_t flags = SEARCH_FLAG_FORWARDS | + search_flags_t flags = SEARCH_FLAG_FORWARDS | ro_gui_search_update_flags(); if (search_verify_new(search_data.search_window, &ro_gui_search_callbacks, NULL)) @@ -127,13 +132,39 @@ bool ro_gui_search_next(wimp_w w) return false; } + +/** + * Callback to prepare menus in the Search dialog. At present, this + * only has to handle the previous search pop-up. + * + * \param w The window handle owning the menu. + * \param i The icon handle owning the menu. + * \param *menu The menu to be prepared. + * \param *pointer The associated mouse click event block, or NULL + * on an Adjust-click re-opening. + * \return true if the event was handled; false if not. + */ + +bool ro_gui_search_menu_prepare(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_pointer *pointer) +{ + if (menu != recent_search_menu || i != ICON_SEARCH_MENU) + return false; + + if (pointer != NULL) + return ro_gui_search_prepare_menu(); + + return true; +} + + bool ro_gui_search_click(wimp_pointer *pointer) { search_flags_t flags; switch (pointer->i) { case ICON_SEARCH_FIND_PREV: search_data.search_insert = true; - flags = ~SEARCH_FLAG_FORWARDS & + flags = ~SEARCH_FLAG_FORWARDS & ro_gui_search_update_flags(); if (search_verify_new(search_data.search_window, &ro_gui_search_callbacks, NULL)) @@ -144,7 +175,7 @@ bool ro_gui_search_click(wimp_pointer *pointer) ICON_SEARCH_TEXT)); return true; case ICON_SEARCH_CASE_SENSITIVE: - flags = SEARCH_FLAG_FORWARDS | + flags = SEARCH_FLAG_FORWARDS | ro_gui_search_update_flags(); if (search_verify_new(search_data.search_window, &ro_gui_search_callbacks, NULL)) @@ -157,7 +188,7 @@ bool ro_gui_search_click(wimp_pointer *pointer) case ICON_SEARCH_SHOW_ALL: if (search_data.search_window->search_context != NULL) search_show_all(ro_gui_get_icon_selected_state( - pointer->w, pointer->i), + pointer->w, pointer->i), search_data.search_window-> search_context); return true; @@ -309,19 +340,19 @@ bool ro_gui_search_keypress(wimp_key *key) ICON_SEARCH_CASE_SENSITIVE); ro_gui_set_icon_selected_state(dialog_search, ICON_SEARCH_CASE_SENSITIVE, !state); - flags = SEARCH_FLAG_FORWARDS | + flags = SEARCH_FLAG_FORWARDS | ro_gui_search_update_flags(); if (search_verify_new(search_data.search_window, &ro_gui_search_callbacks, NULL)) search_step(search_data.search_window-> search_context, flags, ro_gui_get_icon_string( - dialog_search, + dialog_search, ICON_SEARCH_TEXT)); return true; case IS_WIMP_KEY | wimp_KEY_UP: search_data.search_insert = true; - flags = ~SEARCH_FLAG_FORWARDS & + flags = ~SEARCH_FLAG_FORWARDS & ro_gui_search_update_flags(); if (search_verify_new(search_data.search_window, &ro_gui_search_callbacks, NULL)) @@ -333,7 +364,7 @@ bool ro_gui_search_keypress(wimp_key *key) return true; case IS_WIMP_KEY | wimp_KEY_DOWN: search_data.search_insert = true; - flags = SEARCH_FLAG_FORWARDS | + flags = SEARCH_FLAG_FORWARDS | ro_gui_search_update_flags(); if (search_verify_new(search_data.search_window, &ro_gui_search_callbacks, NULL)) @@ -353,7 +384,7 @@ bool ro_gui_search_keypress(wimp_key *key) search_data. search_window-> search_context); - ro_gui_search_set_forward_state(true, + ro_gui_search_set_forward_state(true, search_data.search_window); ro_gui_search_set_back_state(true, search_data.search_window); @@ -362,15 +393,15 @@ bool ro_gui_search_keypress(wimp_key *key) if (key->c == 8 || /* backspace */ key->c == 21 || /* ctrl u */ (key->c >= 0x20 && key->c <= 0x7f)) { - flags = SEARCH_FLAG_FORWARDS | + flags = SEARCH_FLAG_FORWARDS | ro_gui_search_update_flags(); - if (search_data.search_window->search_context + if (search_data.search_window->search_context != NULL) search_destroy_context( search_data. search_window-> search_context); - ro_gui_search_set_forward_state(true, + ro_gui_search_set_forward_state(true, search_data.search_window); ro_gui_search_set_back_state(true, search_data.search_window); @@ -378,7 +409,7 @@ bool ro_gui_search_keypress(wimp_key *key) &ro_gui_search_callbacks, NULL)) search_step(search_data.search_window-> - search_context, flags, + search_context, flags, ro_gui_get_icon_string( dialog_search, ICON_SEARCH_TEXT)); @@ -438,7 +469,7 @@ void ro_gui_search_set_hourglass(bool active, void *p) void ro_gui_search_set_forward_state(bool active, void *p) { - ro_gui_set_icon_shaded_state(dialog_search, ICON_SEARCH_FIND_NEXT, + ro_gui_set_icon_shaded_state(dialog_search, ICON_SEARCH_FIND_NEXT, !active); } diff --git a/riscos/sslcert.c b/riscos/sslcert.c index f2af924a0..f4e4f48b1 100644 --- a/riscos/sslcert.c +++ b/riscos/sslcert.c @@ -149,8 +149,8 @@ void gui_cert_verify(const char *url, /* Create the SSL data and build a tree from it. */ - sslcert_window->tv = ro_treeview_create(sslcert_window->pane, NULL, - sslcert_get_tree_flags()); + sslcert_window->tv = ro_treeview_create(sslcert_window->pane, + NULL, NULL, sslcert_get_tree_flags()); if (sslcert_window->tv == NULL) { LOG(("Failed to allocate treeview")); free(sslcert_window); diff --git a/riscos/textselection.c b/riscos/textselection.c index 07a87e50b..1f3809f50 100644 --- a/riscos/textselection.c +++ b/riscos/textselection.c @@ -30,6 +30,7 @@ #include "desktop/selection.h" #include "desktop/textinput.h" #include "riscos/gui.h" +#include "riscos/menus.h" #include "riscos/message.h" #include "riscos/save.h" #include "riscos/textselection.h" @@ -260,6 +261,8 @@ bool gui_empty_clipboard(void) void gui_clear_selection(struct gui_window *g) { + /* Refresh any open menu, in case it's the browser window menu. */ + ro_gui_menu_refresh(0); } @@ -566,7 +569,7 @@ void ro_gui_selection_dragging(wimp_message *message) bw = g->bw; h = bw->current_content; - if (h && content_get_type(h) == CONTENT_HTML && + if (h && content_get_type(h) == CONTENT_HTML && html_get_box_tree(h)) { struct box *box = html_get_box_tree(h); diff --git a/riscos/theme.c b/riscos/theme.c index 015cf10eb..6b83cad92 100644 --- a/riscos/theme.c +++ b/riscos/theme.c @@ -17,7 +17,7 @@ */ /** \file - * Window themes and toolbars (implementation). + * Window themes (implementation). */ #include @@ -53,83 +53,16 @@ #include "utils/log.h" #include "utils/utils.h" -#define THEME_URL_MEMORY 256 -#define THEME_THROBBER_MEMORY 12 + +/* \TODO -- provide a proper interface for these and make them static again! + */ static struct theme_descriptor *theme_current = NULL; static struct theme_descriptor *theme_descriptors = NULL; -static struct toolbar *theme_toolbar_drag = NULL; -static struct toolbar_icon *theme_toolbar_icon_drag = NULL; -static bool theme_toolbar_editor_drag = false; - -/* these order of the icons must match the numbers defined in riscos/gui.h */ -static const char * theme_browser_icons[] = {"back", "forward", "stop", - "reload", "home", "history", "save", "print", "hotlist", - "scale", "search", "up", NULL}; -static const char * theme_hotlist_icons[] = {"delete", "expand", "open", - "launch", "create", NULL}; -static const char * theme_history_icons[] = {"delete", "expand", "open", - "launch", NULL}; -static const char * theme_cookies_icons[] = {"delete", "expand", "open", - NULL}; static bool ro_gui_theme_add_descriptor(const char *folder, const char *leafname); -static void ro_gui_theme_redraw(wimp_draw *redraw); static void ro_gui_theme_get_available_in_dir(const char *directory); static void ro_gui_theme_free(struct theme_descriptor *descriptor); -static struct toolbar_icon *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); -static void ro_gui_theme_link_toolbar_icon(struct toolbar *toolbar, - struct toolbar_icon *icon, struct toolbar_icon *link, - bool before); -static void ro_gui_theme_delink_toolbar_icon(struct toolbar *toolbar, - struct toolbar_icon *icon); -static struct toolbar_icon *ro_gui_theme_toolbar_get_insert_icon( - struct toolbar *toolbar, int x, int y, bool *before); -static void ro_gui_theme_add_toolbar_icons(struct toolbar *toolbar, - const char* icons[], const char* ident); -static void ro_gui_theme_set_help_prefix(struct toolbar *toolbar); - -/* A basic window for the toolbar and status -*/ -static wimp_window theme_toolbar_window = { - {0, 0, 1, 1}, - 0, - 0, - wimp_TOP, - wimp_WINDOW_NEW_FORMAT | wimp_WINDOW_MOVEABLE | wimp_WINDOW_NO_BOUNDS | - wimp_WINDOW_FURNITURE_WINDOW | - wimp_WINDOW_IGNORE_XEXTENT | wimp_WINDOW_IGNORE_YEXTENT, - 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+ */, - {0, 0, 16384, 16384}, - 0, - 0, - wimpspriteop_AREA, - 1, - 1, - {""}, - 0, - { } -}; - - -/* Shared icon validation -*/ -static char theme_url_validation[] = "Pptr_write;KN"; -static char theme_null_text_string[] = ""; -static char theme_separator_name[] = "separator"; -static char theme_favicon_sprite[12]; - /** * Initialise the theme handler @@ -266,6 +199,155 @@ static void ro_gui_theme_get_available_in_dir(const char *directory) } +/** + * Returns the current theme handle, or NULL if none is set. + * + * \return The theme descriptor handle, or NULL. + */ + +struct theme_descriptor *ro_gui_theme_get_current(void) +{ + return theme_current; +} + + +/** + * Returns a sprite area for use with the given theme. This may return a + * pointer to the wimp sprite pool if a theme area isn't available. + * + * \param *descriptor The theme to use, or NULL for the current. + * \return A pointer to the theme sprite area. + */ + +osspriteop_area *ro_gui_theme_get_sprites(struct theme_descriptor *descriptor) +{ + osspriteop_area *area; + + if (descriptor == NULL) + descriptor = theme_current; + + if (descriptor != NULL && descriptor->theme != NULL) + area = descriptor->theme->sprite_area; + else + area = (osspriteop_area *) 1; + + return area; +} + + +/** + * Returns an interger element from the specified theme, or the current theme + * if the descriptor is NULL. + * + * This is an attempt to abstract the theme data from its clients: it should + * simplify the task of expanding the theme system in the future should this + * be necessary to include other parts of the RISC OS GUI in the theme system. + * + * \param *descriptor The theme to use, or NULL for the current. + * \param style The style to use. + * \param element The style element to return. + * \return The requested value, or 0. + */ + +int ro_gui_theme_get_style_element(struct theme_descriptor *descriptor, + theme_style style, theme_element element) +{ + if (descriptor == NULL) + descriptor = theme_current; + + if (descriptor == NULL) + return 0; + + switch (style) { + case THEME_STYLE_NONE: + switch(element) { + case THEME_ELEMENT_FOREGROUND: + return wimp_COLOUR_BLACK; + case THEME_ELEMENT_BACKGROUND: + return wimp_COLOUR_VERY_LIGHT_GREY; + default: + return 0; + } + break; + + case THEME_STYLE_BROWSER_TOOLBAR: + switch (element) { + case THEME_ELEMENT_FOREGROUND: + return wimp_COLOUR_BLACK; + case THEME_ELEMENT_BACKGROUND: + return descriptor->browser_background; + default: + return 0; + } + break; + + case THEME_STYLE_HOTLIST_TOOLBAR: + case THEME_STYLE_COOKIES_TOOLBAR: + case THEME_STYLE_GLOBAL_HISTORY_TOOLBAR: + switch (element) { + case THEME_ELEMENT_FOREGROUND: + return wimp_COLOUR_BLACK; + case THEME_ELEMENT_BACKGROUND: + return descriptor->hotlist_background; + default: + return 0; + } + break; + + case THEME_STYLE_STATUS_BAR: + switch (element) { + case THEME_ELEMENT_FOREGROUND: + return descriptor->status_foreground; + case THEME_ELEMENT_BACKGROUND: + return descriptor->status_background; + default: + return 0; + } + break; + + default: + return 0; + } +} + +/** + * Returns details of the throbber as defined in a theme. + * + * \param *descriptor The theme of interest (NULL for current). + * \param *frames Return the number of animation frames. + * \param *width Return the throbber width. + * \param *height Return the throbber height. + * \param *right Return the 'locate on right' flag. + * \param *redraw Return the 'forcible redraw' flag. + * \return true if meaningful data has been returned; + * else false. + */ + +bool ro_gui_theme_get_throbber_data(struct theme_descriptor *descriptor, + int *frames, int *width, int *height, + bool *right, bool *redraw) +{ + if (descriptor == NULL) + descriptor = theme_current; + + if (descriptor == NULL || descriptor->theme == NULL) + return false; + + if (frames != NULL) + *frames = descriptor->theme->throbber_frames; + if (width != NULL) + *width = descriptor->theme->throbber_width; + if (height != NULL) + *height = descriptor->theme->throbber_height; + if (right != NULL) + *right = descriptor->throbber_right; + if (redraw != NULL) + *redraw = descriptor->throbber_redraw; + + return true; +} + + /** * Checks a theme is valid and adds it to the current list * @@ -586,11 +668,9 @@ bool ro_gui_theme_apply(struct theme_descriptor *descriptor) theme_previous = theme_current; theme_current = descriptor; - /* apply the theme to all the current windows */ - ro_gui_window_update_theme(); - ro_gui_cookies_update_theme(true); - ro_gui_global_history_update_theme(true); - ro_gui_hotlist_update_theme(true); + /* apply the theme to all the current toolbar-ed windows */ + ro_toolbar_theme_update(); + ro_gui_theme_close(theme_previous, false); return true; } @@ -630,91 +710,6 @@ void ro_gui_theme_close(struct theme_descriptor *descriptor, bool list) } -/** - * Performs the redraw for a toolbar - * - * \param redraw the redraw area - * \param toolbar the toolbar to redraw - */ -void ro_gui_theme_redraw(wimp_draw *redraw) -{ - struct toolbar *toolbar; - struct gui_window *g; - - struct toolbar_icon *icon; - osbool more; - wimp_icon separator_icon; - os_error *error; - bool perform_redraw = false; - - toolbar = (struct toolbar *)ro_gui_wimp_event_get_user_data(redraw->w); - - assert(toolbar); - - /* set the content-type icon */ - g = ro_gui_toolbar_lookup(toolbar->toolbar_handle); - - /* only set type for browser windows */ - sprintf(theme_favicon_sprite, "Ssmall_xxx"); - if (g) { - assert(toolbar->type == THEME_BROWSER_TOOLBAR); - assert(g->bw); - if (g->bw->current_content) { - sprintf(theme_favicon_sprite, "Ssmall_%.3x", - ro_content_filetype_from_type( - content_get_type(g->bw->current_content))); - if (!ro_gui_wimp_sprite_exists(theme_favicon_sprite + 1)) - sprintf(theme_favicon_sprite, "Ssmall_xxx"); - } - } - - /* set up the icon */ - if ((toolbar->descriptor) && (toolbar->descriptor->theme) && - (toolbar->descriptor->theme->sprite_area)) { - const char *name = theme_separator_name; - - separator_icon.flags = wimp_ICON_SPRITE | wimp_ICON_INDIRECTED | - wimp_ICON_HCENTRED | wimp_ICON_VCENTRED; - separator_icon.data.indirected_sprite.id = (osspriteop_id) name; - separator_icon.data.indirected_sprite.area = - toolbar->descriptor->theme->sprite_area; - separator_icon.data.indirected_sprite.size = 12; - separator_icon.extent.y0 = 0; - separator_icon.extent.y1 = toolbar->height; - perform_redraw = true; - } - perform_redraw &= toolbar->display_buttons || toolbar->editor; - if ((toolbar->editor) && (toolbar->editor->toolbar_handle == redraw->w)) - toolbar = toolbar->editor; - - 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) { - 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; - xwimp_plot_icon(&separator_icon); - } - 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; - } - } -} - - /** * Frees any unused theme descriptors. * @@ -757,1543 +752,3 @@ void ro_gui_theme_free(struct theme_descriptor *descriptor) } -/** - * Creates a toolbar. - * - * \param descriptor the theme to use, or NULL for current - * \param type the toolbar type - * \return a new toolbar, or NULL for failure - */ -struct toolbar *ro_gui_theme_create_toolbar(struct theme_descriptor *descriptor, - toolbar_type type) -{ - struct toolbar *toolbar; - - /* Create a new toolbar - */ - 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; - toolbar->descriptor = descriptor; - - /* 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; - ro_gui_theme_add_toolbar_icons(toolbar, - theme_browser_icons, - option_toolbar_browser); - toolbar->suggest = ro_gui_theme_add_toolbar_icon(NULL, - "gright", - ICON_TOOLBAR_SUGGEST); - break; - case THEME_HOTLIST_TOOLBAR: - ro_gui_theme_add_toolbar_icons(toolbar, - theme_hotlist_icons, - option_toolbar_hotlist); - break; - case THEME_HISTORY_TOOLBAR: - ro_gui_theme_add_toolbar_icons(toolbar, - theme_history_icons, - option_toolbar_history); - break; - case THEME_COOKIES_TOOLBAR: - ro_gui_theme_add_toolbar_icons(toolbar, - theme_cookies_icons, - option_toolbar_cookies); - break; - case THEME_BROWSER_EDIT_TOOLBAR: - ro_gui_theme_add_toolbar_icons(toolbar, - theme_browser_icons, - "0123456789ab|"); - break; - case THEME_HOTLIST_EDIT_TOOLBAR: - ro_gui_theme_add_toolbar_icons(toolbar, - theme_hotlist_icons, - "40123|"); - break; - case THEME_HISTORY_EDIT_TOOLBAR: - ro_gui_theme_add_toolbar_icons(toolbar, - theme_history_icons, - "0123|"); - break; - case THEME_COOKIES_EDIT_TOOLBAR: - ro_gui_theme_add_toolbar_icons(toolbar, - theme_cookies_icons, - "012|"); - break; - } - - /* Claim the memory for our Wimp indirection - */ - if (type == THEME_BROWSER_TOOLBAR) { - toolbar->url_buffer = calloc(1, THEME_URL_MEMORY + - THEME_THROBBER_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; - sprintf(toolbar->throbber_buffer, "throbber0"); - } - - /* Apply the desired theme to the toolbar - */ - if (!ro_gui_theme_update_toolbar(descriptor, toolbar)) { - ro_gui_theme_destroy_toolbar(toolbar); - return NULL; - } - toolbar->old_height = ro_gui_theme_toolbar_full_height(toolbar); - return toolbar; -} - - -/** - * Updates a toolbar to use a particular theme. - * The toolbar may be unstable on failure and should be destroyed. - * - * \param descriptor the theme to use, or NULL for current - * \param toolbar the toolbar to update - * \return whether the operation was successful - */ -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; - int width, max_icon; - wimp_icon_flags icon_flags; - struct gui_window *g; - 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)) - sprite_area = toolbar->descriptor->theme->sprite_area; - else - sprite_area = (osspriteop_area *)1; - theme_toolbar_window.sprite_area = sprite_area; - - /* Update the icon sizes - */ - for (toolbar_icon = toolbar->icon; toolbar_icon; - toolbar_icon = toolbar_icon->next) - ro_gui_theme_update_toolbar_icon(toolbar, toolbar_icon); - if (toolbar->suggest) - ro_gui_theme_update_toolbar_icon(toolbar, toolbar->suggest); - - /* Recreate the toolbar window - */ - if (toolbar->descriptor) { - if (toolbar->type == THEME_BROWSER_TOOLBAR) - theme_toolbar_window.work_bg = - toolbar->descriptor->browser_background; - else - theme_toolbar_window.work_bg = - toolbar->descriptor->hotlist_background; - } else { - theme_toolbar_window.work_bg = wimp_COLOUR_VERY_LIGHT_GREY; - } - - theme_toolbar_window.work_flags &= ~wimp_ICON_BUTTON_TYPE; - if ((toolbar->editor) || - (toolbar->type == THEME_HOTLIST_EDIT_TOOLBAR) || - (toolbar->type == THEME_HISTORY_EDIT_TOOLBAR) || - (toolbar->type == THEME_BROWSER_EDIT_TOOLBAR) || - (toolbar->type == THEME_COOKIES_EDIT_TOOLBAR)) - theme_toolbar_window.work_flags |= (wimp_BUTTON_CLICK_DRAG << - wimp_ICON_BUTTON_TYPE_SHIFT); - theme_toolbar_window.sprite_area = sprite_area; - if (toolbar->toolbar_handle) { - error = xwimp_delete_window(toolbar->toolbar_handle); - if (error) - LOG(("xwimp_delete_window: 0x%x: %s", - error->errnum, error->errmess)); - ro_gui_wimp_event_finalise(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; - } - ro_gui_wimp_event_register_redraw_window(toolbar->toolbar_handle, - ro_gui_theme_redraw); - ro_gui_wimp_event_set_user_data(toolbar->toolbar_handle, toolbar); - switch (toolbar->type) { - case THEME_BROWSER_TOOLBAR: - case THEME_BROWSER_EDIT_TOOLBAR: - ro_gui_wimp_event_register_mouse_click(toolbar->toolbar_handle, - ro_gui_toolbar_click); - break; - case THEME_HOTLIST_TOOLBAR: - case THEME_HOTLIST_EDIT_TOOLBAR: - ro_gui_wimp_event_register_mouse_click(toolbar->toolbar_handle, - ro_gui_hotlist_toolbar_click); - ro_gui_wimp_event_register_window_menu(toolbar->toolbar_handle, - tree_toolbar_menu, - ro_gui_hotlist_menu_prepare, - ro_gui_hotlist_menu_select, NULL, - ro_gui_hotlist_menu_warning, false); - break; - case THEME_HISTORY_TOOLBAR: - case THEME_HISTORY_EDIT_TOOLBAR: - ro_gui_wimp_event_register_mouse_click(toolbar->toolbar_handle, - ro_gui_global_history_toolbar_click); - ro_gui_wimp_event_register_window_menu(toolbar->toolbar_handle, - tree_toolbar_menu, - ro_gui_global_history_menu_prepare, - ro_gui_global_history_menu_select, NULL, - ro_gui_global_history_menu_warning, false); - break; - case THEME_COOKIES_TOOLBAR: - case THEME_COOKIES_EDIT_TOOLBAR: - ro_gui_wimp_event_register_mouse_click(toolbar->toolbar_handle, - ro_gui_cookies_toolbar_click); - ro_gui_wimp_event_register_window_menu(toolbar->toolbar_handle, - tree_toolbar_menu, - ro_gui_cookies_menu_prepare, - ro_gui_cookies_menu_select, NULL, - ro_gui_cookies_menu_warning, false); - break; - default: - break; - } - - /* Create the basic icons - */ - if ((toolbar->type == THEME_HOTLIST_TOOLBAR) || - (toolbar->type == THEME_HOTLIST_EDIT_TOOLBAR)) - max_icon = ICON_TOOLBAR_HOTLIST_LAST; - else if ((toolbar->type == THEME_HISTORY_TOOLBAR) || - (toolbar->type == THEME_HISTORY_EDIT_TOOLBAR)) - max_icon = ICON_TOOLBAR_HISTORY_LAST; - else if ((toolbar->type == THEME_COOKIES_TOOLBAR) || - (toolbar->type == THEME_COOKIES_EDIT_TOOLBAR)) - max_icon = ICON_TOOLBAR_COOKIES_LAST; - else - max_icon = ICON_TOOLBAR_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; - if ((toolbar->editor) || - (toolbar->type == THEME_HOTLIST_EDIT_TOOLBAR) || - (toolbar->type == THEME_HISTORY_EDIT_TOOLBAR) || - (toolbar->type == THEME_COOKIES_EDIT_TOOLBAR) || - (toolbar->type == THEME_BROWSER_EDIT_TOOLBAR)) - new_icon.icon.flags |= (wimp_BUTTON_CLICK_DRAG << - wimp_ICON_BUTTON_TYPE_SHIFT); - else - new_icon.icon.flags |= (wimp_BUTTON_CLICK << - wimp_ICON_BUTTON_TYPE_SHIFT); - if (toolbar->descriptor) - new_icon.icon.flags |= (toolbar->descriptor->browser_background - << wimp_ICON_BG_COLOUR_SHIFT); - else - new_icon.icon.flags |= (wimp_COLOUR_VERY_LIGHT_GREY - << wimp_ICON_BG_COLOUR_SHIFT); - icon_flags = new_icon.icon.flags; - - for (int i = 0; i < max_icon; i++) { - new_icon.icon.data.indirected_text.text = - theme_null_text_string; - new_icon.icon.data.indirected_text.validation = - 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) { - /* container for all URL bits (ie border) */ - new_icon.icon.flags = wimp_ICON_BORDER | (wimp_COLOUR_BLACK << - wimp_ICON_FG_COLOUR_SHIFT); - 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; - } - - /* favicon image */ - new_icon.icon.flags = wimp_ICON_TEXT | wimp_ICON_SPRITE | - wimp_ICON_INDIRECTED | wimp_ICON_FILLED | - wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | - (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_favicon_sprite; - 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; - } - - /* Writable text portion */ - new_icon.icon.flags = wimp_ICON_TEXT | wimp_ICON_INDIRECTED | - wimp_ICON_VCENTRED | - 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; - } - - /* Now the URL suggestion icon - */ - new_icon.icon.data.indirected_text.text = - theme_null_text_string; - new_icon.icon.data.indirected_text.size = 1; - new_icon.icon.flags = icon_flags | (wimp_BUTTON_CLICK << - wimp_ICON_BUTTON_TYPE_SHIFT); - if (toolbar->suggest) - new_icon.icon.data.indirected_text.validation = - toolbar->suggest->validation; - else - new_icon.icon.data.indirected_text.validation = - theme_null_text_string; - 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; - } - - /* 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); - - - /* Force a re-processing of the toolbar - */ - width = toolbar->toolbar_current; - toolbar->reformat_buttons = true; - toolbar->toolbar_current = -1; - ro_gui_theme_process_toolbar(toolbar, width); - - /* Keep menus up to date etc - */ - ro_gui_theme_set_help_prefix(toolbar); - switch (toolbar->type) { - case THEME_BROWSER_TOOLBAR: - g = ro_gui_window_lookup(toolbar->parent_handle); - if (g) - ro_gui_prepare_navigate(g); - break; - case THEME_HOTLIST_TOOLBAR: - case THEME_HISTORY_TOOLBAR: - case THEME_COOKIES_TOOLBAR: - ro_gui_menu_prepare_action(toolbar->parent_handle, - TREE_SELECTION, false); - ro_gui_menu_prepare_action(toolbar->parent_handle, - TREE_EXPAND_ALL, false); - break; - default: - break; - } - return true; -} - - -/** - * 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; - int height; - os_error *error; - - if (!toolbar) - return false; - - /* Attach/close the windows - */ - toolbar->parent_handle = parent; - height = ro_gui_theme_toolbar_height(toolbar); - if (height > 0) { - outline.w = parent; - xwimp_get_window_outline(&outline); - 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 - height + 2; - state.xscroll = 0; - state.yscroll = toolbar->height - 2; /* clipped by the WIMP */ - error = xwimp_open_window_nested(PTR_WIMP_OPEN(&state), parent, - wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT - << wimp_CHILD_XORIGIN_SHIFT | - 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_LINKS_PARENT_VISIBLE_TOP_OR_RIGHT - << wimp_CHILD_BS_EDGE_SHIFT | - wimp_CHILD_LINKS_PARENT_VISIBLE_TOP_OR_RIGHT - << wimp_CHILD_RS_EDGE_SHIFT | - wimp_CHILD_LINKS_PARENT_VISIBLE_TOP_OR_RIGHT - << wimp_CHILD_TS_EDGE_SHIFT); - if (error) { - LOG(("xwimp_open_window_nested: 0x%x: %s", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); - return false; - } - if (!toolbar->editor) - return true; - - state.w = toolbar->editor->toolbar_handle; - state.visible.y1 -= toolbar->height; - state.yscroll = toolbar->editor->height - 2; - error = xwimp_open_window_nested(PTR_WIMP_OPEN(&state), - toolbar->toolbar_handle, - wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT - << wimp_CHILD_XORIGIN_SHIFT | - 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_LINKS_PARENT_VISIBLE_TOP_OR_RIGHT - << wimp_CHILD_BS_EDGE_SHIFT | - wimp_CHILD_LINKS_PARENT_VISIBLE_TOP_OR_RIGHT - << wimp_CHILD_RS_EDGE_SHIFT | - wimp_CHILD_LINKS_PARENT_VISIBLE_TOP_OR_RIGHT - << wimp_CHILD_TS_EDGE_SHIFT); - if (error) { - LOG(("xwimp_open_window_nested: 0x%x: %s", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); - return false; - } - return true; - } - - error = xwimp_close_window(toolbar->toolbar_handle); - if (error) { - LOG(("xwimp_close_window: 0x%x: %s", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); - return false; - } - return true; -} - - -/** - * Updates the toolbar to reflect changes to the icon flags and any reformatting - * required due to the change in parent window size. - * - * \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 - */ -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_outline outline; - wimp_window_state state; - int height = -1; - int throbber_x = -1; - int left_edge, right_edge, bottom_edge; - int old_height; - int old_width; - struct toolbar_icon *toolbar_icon; - bool visible_icon = false; - int collapse_height; - int xeig, yeig; - os_coord pixel = {1, 1}; - int top, bottom, right; - - if (!toolbar) - return false; - - old_height = toolbar->height; - old_width = toolbar->toolbar_current; - - /* calculate 1px in OS units */ - ro_convert_pixels_to_os_units(&pixel, (os_mode)-1); - xeig = pixel.x; - yeig = pixel.y; - - /* find the parent window handle if we need to process the status - * window, or the caller has requested we calculate the width ourself */ - if ((toolbar->parent_handle) && (width == -1)) { - 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; - } - if (width == -1) - width = outline.outline.x1 - outline.outline.x0 - 2; - } - - /* Find the parent visible height to clip our toolbar height to - */ - if ((toolbar->toolbar_handle) && (toolbar->parent_handle)) { - /* Get the current state - */ - state.w = toolbar->parent_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; - } - height = state.visible.y1 - state.visible.y0 + 2; - - /* We can't obscure the height of the scroll bar as we - lose the resize icon if we do. - */ - if ((state.flags & wimp_WINDOW_SIZE_ICON) && - !(state.flags & wimp_WINDOW_HSCROLL)) - height -= ro_get_hscroll_height(0) - 2; - - /* Update our position - */ - if (height != toolbar->max_height) { - if ((state.flags & wimp_WINDOW_SIZE_ICON) && - !(state.flags & wimp_WINDOW_HSCROLL) && - (toolbar->height > toolbar->max_height)) - xwimp_force_redraw(toolbar->parent_handle, - 0, -16384, 16384, 16384); - toolbar->max_height = height; - collapse_height = toolbar->height + - (toolbar->editor ? toolbar->editor->height : 0); - ro_gui_theme_attach_toolbar(toolbar, toolbar->parent_handle); - if ((state.flags & wimp_WINDOW_SIZE_ICON) && - !(state.flags & wimp_WINDOW_HSCROLL) && - (collapse_height > toolbar->max_height)) - xwimp_force_redraw(toolbar->parent_handle, - 0, -16384, 16384, 16384); - } - - } - - /* 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->descriptor) && (toolbar->descriptor->theme) && - (toolbar->type == THEME_BROWSER_TOOLBAR) && - (toolbar->display_throbber)) { - if (!toolbar->descriptor->throbber_right) { - throbber_x = left_edge; - left_edge += toolbar->descriptor->theme->throbber_width + 8; - } - toolbar->height = toolbar->descriptor->theme->throbber_height + 8; - } - if ((toolbar->type == THEME_BROWSER_TOOLBAR) && (toolbar->display_url)) { - if (toolbar->height < 52 + 8) - toolbar->height = 52 + 8; - if ((toolbar->suggest) && (toolbar->height < - (toolbar->suggest->height + 8))) - toolbar->height = toolbar->suggest->height + 8; - } - - /* Get the minimum height of the icons - */ - bottom_edge = left_edge; - if ((toolbar->display_buttons || toolbar->editor) && (toolbar->descriptor) && - (toolbar->descriptor->theme)) { - toolbar_icon = toolbar->icon; - while (toolbar_icon) { - if (toolbar_icon->display) { - bottom_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) bottom_edge += 8; - } - - /* Check for minimum widths - */ - if (toolbar->type == THEME_BROWSER_TOOLBAR) { - if (!toolbar->reformat_buttons) left_edge = bottom_edge; - if (toolbar->display_url) { - bottom_edge += 112; - if (toolbar->suggest) - bottom_edge += toolbar->suggest->width + 8; - } - if (bottom_edge > right_edge) - right_edge = bottom_edge; - if ((toolbar->descriptor) && (toolbar->descriptor->theme) && - (toolbar->display_throbber) && - (toolbar->descriptor->throbber_right)) { - bottom_edge += toolbar->descriptor->theme->throbber_width; - if (bottom_edge > right_edge) right_edge = bottom_edge; - throbber_x = right_edge - - toolbar->descriptor->theme->throbber_width; - right_edge -= toolbar->descriptor->theme->throbber_width + 8; - } - } - - if (toolbar->height != 0) - toolbar->height += 2; - if (toolbar->reformat_buttons) { - /* Hide the URL bar if we should - */ - if ((!toolbar->display_url) && - (toolbar->type == THEME_BROWSER_TOOLBAR)) { - if (!xwimp_get_caret_position(&caret)) { - if ((caret.w == toolbar->toolbar_handle) && - (caret.i == ICON_TOOLBAR_URL)) { - if (toolbar->parent_handle) - xwimp_set_caret_position( - toolbar->parent_handle, - wimp_ICON_WINDOW, - -100, -100, 32, -1); - else - xwimp_set_caret_position((wimp_w)-1, - 0, 0, 0, 0, 0); - } - } - xwimp_resize_icon(toolbar->toolbar_handle, ICON_TOOLBAR_SURROUND, - 0, -16384, 0, -16384); - xwimp_resize_icon(toolbar->toolbar_handle, ICON_TOOLBAR_FAVICON, - 0, -16384, 0, -16384); - xwimp_resize_icon(toolbar->toolbar_handle, ICON_TOOLBAR_URL, - 0, -16384, 0, -16384); - xwimp_resize_icon(toolbar->toolbar_handle, ICON_TOOLBAR_SUGGEST, - 0, -16384, 0, -16384); - } else if (toolbar->type == THEME_BROWSER_TOOLBAR) { - 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->editor) && - (toolbar_icon->display) - && (toolbar_icon->width > 0)) { - visible_icon = true; - bottom_edge = (toolbar->height - - toolbar_icon->height) / 2; - toolbar_icon->x = left_edge; - toolbar_icon->y = bottom_edge; - 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; - } - - - if (toolbar->type == THEME_BROWSER_TOOLBAR) { - /* Move the URL bar - */ - if (toolbar->display_url) { - top = (toolbar->height / 2) + 26; - bottom = (toolbar->height / 2) - 26; - if (toolbar->suggest) { - right = right_edge - toolbar->suggest->width - 8; - xwimp_resize_icon(toolbar->toolbar_handle, - ICON_TOOLBAR_SUGGEST, - right_edge - toolbar->suggest->width, - (toolbar->height - toolbar->suggest->height) / 2, - right_edge, - (toolbar->height + toolbar->suggest->height) / 2); - } else { - right = right_edge; - } - xwimp_resize_icon(toolbar->toolbar_handle, ICON_TOOLBAR_URL, - left_edge + 52, - bottom + yeig, - right - xeig, - top - yeig); - xwimp_resize_icon(toolbar->toolbar_handle, ICON_TOOLBAR_FAVICON, - left_edge + xeig, - bottom + yeig, - left_edge + 52, - top - yeig); - xwimp_resize_icon(toolbar->toolbar_handle, ICON_TOOLBAR_SURROUND, - left_edge, - bottom, - right, - top); - xwimp_force_redraw(toolbar->toolbar_handle, - right - xeig, 0, 16384, 16384); - xwimp_force_redraw(toolbar->toolbar_handle, - left_edge, - bottom, - right, - bottom + yeig); - xwimp_force_redraw(toolbar->toolbar_handle, - left_edge, - top - yeig, - right, - top); - 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->descriptor) && (toolbar->descriptor->theme) && - (throbber_x >= 0) && (toolbar->display_throbber)) { - xwimp_resize_icon(toolbar->toolbar_handle, ICON_TOOLBAR_THROBBER, - throbber_x, 0, - throbber_x + toolbar->descriptor->theme->throbber_width, - toolbar->height); - if (toolbar->descriptor->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 { - xwimp_resize_icon(toolbar->toolbar_handle, ICON_TOOLBAR_THROBBER, - 0, -16384, 0, -16384); - } - } - - /* Re-attach to the parent - */ - toolbar->toolbar_current = width; - if (toolbar->reformat_buttons) { - extent.x1 = 16384; - extent.y0 = (toolbar->editor ? -toolbar->editor->height : 0); - extent.y1 = toolbar->height - 2; - xwimp_set_extent(toolbar->toolbar_handle, &extent); - if ((toolbar->parent_handle) && (old_height != toolbar->height)) - ro_gui_theme_attach_toolbar(toolbar, toolbar->parent_handle); - } - toolbar->reformat_buttons = false; - } - return true; -} - - -/** - * Destroys a toolbar and frees any associated memory. - * - * \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; - - /* Destroy our editor - */ - if (toolbar->editor) { - toolbar->editor = NULL; - ro_gui_theme_destroy_toolbar(toolbar->editor); - } - - /* Delete our windows - */ - if (toolbar->toolbar_handle) { - xwimp_delete_window(toolbar->toolbar_handle); - ro_gui_wimp_event_finalise(toolbar->toolbar_handle); - } - /* 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); - } - ro_gui_theme_destroy_toolbar_icon(toolbar->suggest); - free(toolbar); -} - - -/** - * Refresh a toolbar after it has been updated - * - * \param toolbar the toolbar to update - */ -void ro_gui_theme_refresh_toolbar(struct toolbar *toolbar) -{ - assert(toolbar); - - toolbar->reformat_buttons = true; - ro_gui_theme_process_toolbar(toolbar, -1); - if (toolbar->type == THEME_BROWSER_TOOLBAR) { - gui_window_update_extent(ro_gui_window_lookup( - current_menu_window)); - } else if (toolbar->type == THEME_HOTLIST_TOOLBAR) { - ro_gui_hotlist_update_theme(false); - } else if (toolbar->type == THEME_HISTORY_TOOLBAR) { - ro_gui_global_history_update_theme(false); - } else if (toolbar->type == THEME_COOKIES_TOOLBAR) { - ro_gui_cookies_update_theme(false); - } -} - - -/** - * Toggles the toolbar editing mode - * - * \param toolbar the toolbar to toggle editing for - */ -void ro_gui_theme_toggle_edit(struct toolbar *toolbar) -{ - int icons = 0; - struct toolbar_icon *icon; - struct gui_window *g = NULL; - wimp_window_state state; - os_error *error; - char *option; - char hex_no[4]; - - if (!toolbar) - return; - - if ((toolbar->type == THEME_BROWSER_TOOLBAR) && - (toolbar->parent_handle)) - g = ro_gui_window_lookup(toolbar->parent_handle); - - if (toolbar->editor) { - /* save options */ - icons = 0; - for (icon = toolbar->icon; icon; icon = icon->next) - if (icon->display) icons++; - option = calloc(icons + 1, 1); - if (!option) { - LOG(("No memory to save toolbar options")); - warn_user("NoMemory", 0); - } else { - icons = 0; - for (icon = toolbar->icon; icon; icon = icon->next) - if (icon->display) { - if (icon->icon_number == -1) { - option[icons] = '|'; - } else { - sprintf(hex_no, "%x", icon->icon_number); - option[icons] = hex_no[0]; - } - icons++; - } - switch (toolbar->type) { - case THEME_BROWSER_TOOLBAR: - free(option_toolbar_browser); - option_toolbar_browser = option; - break; - case THEME_HOTLIST_TOOLBAR: - free(option_toolbar_hotlist); - option_toolbar_hotlist = option; - break; - case THEME_HISTORY_TOOLBAR: - free(option_toolbar_history); - option_toolbar_history = option; - break; - case THEME_COOKIES_TOOLBAR: - free(option_toolbar_cookies); - option_toolbar_cookies = option; - break; - default: - break; - } - ro_gui_save_options(); - } - - /* turn off editing */ - ro_gui_theme_destroy_toolbar(toolbar->editor); - toolbar->editor = NULL; - ro_gui_theme_update_toolbar(toolbar->descriptor, toolbar); - switch (toolbar->type) { - case THEME_BROWSER_TOOLBAR: - if (g) - gui_window_update_extent(g); - break; - default: - if (toolbar->parent_handle) - xwimp_force_redraw(toolbar->parent_handle, - 0, -16384, 16384, 16384); - break; - } - } else { - /* create/initialise the toolbar editor */ - switch (toolbar->type) { - case THEME_BROWSER_TOOLBAR: - toolbar->editor = ro_gui_theme_create_toolbar( - toolbar->descriptor, - THEME_BROWSER_EDIT_TOOLBAR); - break; - case THEME_HOTLIST_TOOLBAR: - toolbar->editor = ro_gui_theme_create_toolbar( - toolbar->descriptor, - THEME_HOTLIST_EDIT_TOOLBAR); - break; - case THEME_HISTORY_TOOLBAR: - toolbar->editor = ro_gui_theme_create_toolbar( - toolbar->descriptor, - THEME_HISTORY_EDIT_TOOLBAR); - break; - case THEME_COOKIES_TOOLBAR: - toolbar->editor = ro_gui_theme_create_toolbar( - toolbar->descriptor, - THEME_COOKIES_EDIT_TOOLBAR); - break; - default: - return; - } - if (!toolbar->editor) { - LOG(("Unable to create toolbar editor")); - return; - } - ro_gui_wimp_event_set_user_data(toolbar->editor->toolbar_handle, - ro_gui_wimp_event_get_user_data(toolbar->toolbar_handle)); - ro_gui_theme_update_toolbar(toolbar->descriptor, toolbar); - switch (toolbar->type) { - case THEME_BROWSER_TOOLBAR: - if (g) - gui_window_update_extent(g); - break; - default: - if (toolbar->parent_handle) { - state.w = toolbar->parent_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; - } - ro_gui_open_window_request(PTR_WIMP_OPEN(&state)); - xwimp_force_redraw(toolbar->parent_handle, - 0, -16384, 16384, 16384); - } - break; - } - ro_gui_theme_process_toolbar(toolbar, -1); - ro_gui_theme_toolbar_editor_sync(toolbar); - } - ro_gui_theme_set_help_prefix(toolbar); -} - - -/** - * Synchronise a toolbar window with the associated editor. - * - * \param toolbar the toolbar to synchronise - */ -void ro_gui_theme_toolbar_editor_sync(struct toolbar *toolbar) -{ - struct toolbar_icon *icon; - struct toolbar_icon *icon_edit; - - if ((!toolbar) || (!toolbar->editor)) - return; - - for (icon = toolbar->icon; icon; icon = icon->next) - if ((icon->icon_number >= 0) && (icon->width > 0)) - for (icon_edit = toolbar->editor->icon; icon_edit; - icon_edit = icon_edit->next) - if (icon_edit->icon_number == icon->icon_number) - ro_gui_set_icon_shaded_state( - toolbar->editor->toolbar_handle, - icon_edit->icon_number, - icon->display); -} - - -/** - * Handle a toolbar click during an editor session - * - * \param toolbar the base toolbar (ie not editor) to respond to a click for - * \param pointer the WIMP pointer details - */ -void ro_gui_theme_toolbar_editor_click(struct toolbar *toolbar, - wimp_pointer *pointer) { - wimp_window_state state; - os_error *error; - os_box box; - - if (!toolbar->editor) - return; - if ((pointer->buttons != (wimp_CLICK_SELECT << 4)) && - (pointer->buttons != (wimp_CLICK_ADJUST << 4))) - return; - - state.w = pointer->w; - 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; - } - - gui_current_drag_type = GUI_DRAG_TOOLBAR_CONFIG; - theme_toolbar_drag = toolbar; - theme_toolbar_editor_drag = !(pointer->w == toolbar->toolbar_handle); - if (theme_toolbar_editor_drag) - theme_toolbar_icon_drag = - ro_gui_theme_toolbar_get_icon(toolbar->editor, - pointer->pos.x - state.visible.x0, - state.visible.y1 - pointer->pos.y); - else - theme_toolbar_icon_drag = - ro_gui_theme_toolbar_get_icon(toolbar, - pointer->pos.x - state.visible.x0, - state.visible.y1 - pointer->pos.y); - if (!theme_toolbar_icon_drag) - return; - if ((theme_toolbar_icon_drag->icon_number >= 0) && - (pointer->w == toolbar->editor->toolbar_handle) && - (ro_gui_get_icon_shaded_state( - toolbar->editor->toolbar_handle, - theme_toolbar_icon_drag->icon_number))) - return; - - box.x0 = pointer->pos.x - theme_toolbar_icon_drag->width / 2; - box.x1 = box.x0 + theme_toolbar_icon_drag->width; - box.y0 = pointer->pos.y - theme_toolbar_icon_drag->height / 2; - box.y1 = box.y0 + theme_toolbar_icon_drag->height; - error = xdragasprite_start(dragasprite_HPOS_CENTRE | - dragasprite_VPOS_CENTRE | - dragasprite_BOUND_POINTER | - dragasprite_DROP_SHADOW, - toolbar->descriptor->theme->sprite_area, - theme_toolbar_icon_drag->name, &box, 0); - if (error) - LOG(("xdragasprite_start: 0x%x: %s", - error->errnum, error->errmess)); -} - - -/** - * Handle the end of a drag - * - * \param drag the details for the drag end - */ -void ro_gui_theme_toolbar_editor_drag_end(wimp_dragged *drag) -{ - wimp_window_state state; - os_error *error; - wimp_pointer pointer; - struct toolbar_icon *insert_icon; - struct toolbar_icon *local_icon = NULL; - struct toolbar_icon *icon; - bool before = false; - - if ((!theme_toolbar_drag) || (!theme_toolbar_icon_drag) || - (!theme_toolbar_drag->editor)) - return; - - error = xwimp_get_pointer_info(&pointer); - if (error) { - LOG(("xwimp_get_pointer_info: 0x%x: %s", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); - return; - } - - if (pointer.w == theme_toolbar_drag->toolbar_handle) { - /* drag from editor or toolbar to toolbar */ - state.w = pointer.w; - 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; - } - insert_icon = ro_gui_theme_toolbar_get_insert_icon( - theme_toolbar_drag, - pointer.pos.x - state.visible.x0, - state.visible.y1 - pointer.pos.y, &before); - if (theme_toolbar_icon_drag->icon_number == -1) { - if (theme_toolbar_editor_drag) { - theme_toolbar_icon_drag = - ro_gui_theme_add_toolbar_icon( - theme_toolbar_drag, - NULL, -1); - ro_gui_theme_update_toolbar_icon( - theme_toolbar_drag, - theme_toolbar_icon_drag); - } - /* move the separator */ - if (theme_toolbar_icon_drag != insert_icon) { - ro_gui_theme_delink_toolbar_icon( - theme_toolbar_drag, - theme_toolbar_icon_drag); - ro_gui_theme_link_toolbar_icon( - theme_toolbar_drag, - theme_toolbar_icon_drag, - insert_icon, before); - } - } else { - /* move/enable the icon */ - for (icon = theme_toolbar_drag->icon; icon; - icon = icon->next) - if (theme_toolbar_icon_drag->icon_number == - icon->icon_number) - local_icon = icon; - if (!local_icon) - return; - if (local_icon != insert_icon) { - ro_gui_theme_delink_toolbar_icon( - theme_toolbar_drag, local_icon); - ro_gui_theme_link_toolbar_icon( - theme_toolbar_drag, local_icon, - insert_icon, before); - } - local_icon->display = true; - } - } else if ((pointer.w == theme_toolbar_drag->editor->toolbar_handle) && - (!theme_toolbar_editor_drag)) { - /* drag from toolbar to editor */ - if (theme_toolbar_icon_drag->icon_number == -1) { - /* delete separators */ - ro_gui_theme_delink_toolbar_icon(theme_toolbar_drag, - theme_toolbar_icon_drag); - ro_gui_theme_destroy_toolbar_icon( - theme_toolbar_icon_drag); - } else { - /* hide icons */ - theme_toolbar_icon_drag->display = false; - } - } - theme_toolbar_drag->reformat_buttons = true; - ro_gui_theme_process_toolbar(theme_toolbar_drag, -1); - ro_gui_theme_toolbar_editor_sync(theme_toolbar_drag); -} - - -/** - * Adds a toolbar icon to the end of a toolbar - * - * \param toolbar the toolbar to add the icon to the end of (or NULL) - * \param name the icon name, or NULL for a separator - * \param icon_number RISC OS wimp icon number for the icon (not separators) - */ -struct toolbar_icon *ro_gui_theme_add_toolbar_icon(struct toolbar *toolbar, - const char *name, int icon_number) -{ - struct toolbar_icon *toolbar_icon; - struct toolbar_icon *link_icon; - - /* Separators are really a sprite called "separator" - */ - if (name == NULL) { - name = "separator"; - icon_number = -1; - } - - /* 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 NULL; - } - - /* 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) { - 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; - } - } - return 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 = {0, 0}; - os_mode mode; - os_error *error = NULL; - int default_width = 0; - osspriteop_area *sprite_area = NULL; - - /* 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->descriptor) && (toolbar->descriptor->theme)) - sprite_area = toolbar->descriptor->theme->sprite_area; - - /* Get the sprite details */ - if (sprite_area) - error = xosspriteop_read_sprite_info(osspriteop_USER_AREA, - sprite_area, (osspriteop_id)icon->name, - &dimensions.x, &dimensions.y, 0, &mode); - - /* fallback to Wimp pool, if necessary */ - if (error || sprite_area == NULL) - error = xwimpspriteop_read_sprite_info(icon->name, - &dimensions.x, &dimensions.y, 0, &mode); - - /* Give up, if both failed */ - 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); -} - - -/** - * Links a toolbar icon - * - * \param icon the toolbar icon to link - */ -void ro_gui_theme_link_toolbar_icon(struct toolbar *toolbar, - struct toolbar_icon *icon, struct toolbar_icon *link, - bool before) -{ - struct toolbar_icon *temp; - assert(toolbar); - assert(icon); - assert(icon != link); - - /* no icon set, no link icon, or insert at head of list */ - if ((!toolbar->icon) || (!link) || - (before && (toolbar->icon == link))) { - if (toolbar->icon != icon) { - icon->next = toolbar->icon; - toolbar->icon = icon; - } - return; - } - - if (before) { - for (temp = toolbar->icon; temp; temp = temp->next) - if (temp->next == link) { - temp->next = icon; - icon->next = link; - return; - } - } else { - icon->next = link->next; - link->next = icon; - } -} - -/** - * Delinks a toolbar icon - * - * \param icon the toolbar icon to delink - */ -void ro_gui_theme_delink_toolbar_icon(struct toolbar *toolbar, - struct toolbar_icon *icon) -{ - struct toolbar_icon *link; - assert(toolbar); - assert(icon); - - if (toolbar->icon == icon) { - toolbar->icon = icon->next; - icon->next = NULL; - return; - } - - for (link = toolbar->icon; link; link = link->next) - if (link->next == icon) { - link->next = icon->next; - icon->next = NULL; - return; - } -} - - -/** - * 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 - * \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; - - for (icon = toolbar->icon; icon; icon = icon->next) - if ((icon->display) && (icon->width > 0) && - (icon->x <= x) && (icon->y <= y) && - (icon->x + icon->width > x) && - (icon->y + icon->height > y)) - return icon; - return NULL; -} - - -/** - * Returns the toolbar icon closest to the specified position, and whether the - * position is before (left) or after (right) of it. - * - * \param toolbar the toolbar to examine - * \param x the x co-ordinate to check - * \param y the y co-ordinate to check - * \return the toolbar icon closest to the specified position, or NULL - */ -struct toolbar_icon *ro_gui_theme_toolbar_get_insert_icon( - struct toolbar *toolbar, int x, int y, bool *before) -{ - struct toolbar_icon *match = NULL; - struct toolbar_icon *icon; - int closest = 65536; - int distance; - - if (!toolbar->icon) - return NULL; - - for (icon = toolbar->icon; icon; icon = icon->next) { - if ((icon->display) && (icon->width > 0)) { - distance = icon->x + icon->width / 2 - x; - if (distance < 0) - distance = -distance; - if (distance < closest) { - closest = distance; - match = icon; - *before = (icon->x + icon->width / 2 - x) > 0; - } - } - } - return match; -} - - -/** - * Sets up a toolbar with icons according to an identifier string - */ -void ro_gui_theme_add_toolbar_icons(struct toolbar *toolbar, - const char* icons[], const char* ident) -{ - struct toolbar_icon *icon; - int index = 0; - int number = 0; - char hex_no[4]; - - /* step 1: add all main icons in their correct state */ - while (icons[index]) { - icon = ro_gui_theme_add_toolbar_icon(toolbar, icons[index], - index); - sprintf(hex_no, "%x", index); - if ((icon) && (!strchr(ident, hex_no[0]))) - icon->display = false; - index++; - } - - /* step 2: re-order and add separators */ - index = strlen(ident); - while (index--) { - if (ident[index] == '|') { - icon = ro_gui_theme_add_toolbar_icon(NULL, NULL, -1); - if (icon) - ro_gui_theme_link_toolbar_icon(toolbar, icon, - NULL, NULL); - } else { - hex_no[0] = ident[index]; - hex_no[1] = '\0'; - number = strtol(hex_no, NULL, 16); - for (icon = toolbar->icon; icon; icon = icon->next) - if (icon->icon_number == number) { - ro_gui_theme_delink_toolbar_icon( - toolbar, icon); - ro_gui_theme_link_toolbar_icon(toolbar, - icon, NULL, NULL); - } - } - } -} - - -/** - * Sets the correct help prefix for a toolbar - */ -void ro_gui_theme_set_help_prefix(struct toolbar *toolbar) -{ - if (toolbar->editor) { - ro_gui_wimp_event_set_help_prefix(toolbar->toolbar_handle, - "HelpEditToolbar"); - return; - } - switch (toolbar->type) { - case THEME_BROWSER_TOOLBAR: - ro_gui_wimp_event_set_help_prefix(toolbar->toolbar_handle, - "HelpToolbar"); - break; - case THEME_HOTLIST_TOOLBAR: - ro_gui_wimp_event_set_help_prefix(toolbar->toolbar_handle, - "HelpHotToolbar"); - break; - case THEME_HISTORY_TOOLBAR: - ro_gui_wimp_event_set_help_prefix(toolbar->toolbar_handle, - "HelpGHistToolbar"); - break; - case THEME_COOKIES_TOOLBAR: - ro_gui_wimp_event_set_help_prefix(toolbar->toolbar_handle, - "HelpCookiesToolbar"); - break; - case THEME_BROWSER_EDIT_TOOLBAR: - case THEME_HOTLIST_EDIT_TOOLBAR: - case THEME_HISTORY_EDIT_TOOLBAR: - case THEME_COOKIES_EDIT_TOOLBAR: - ro_gui_wimp_event_set_help_prefix(toolbar->toolbar_handle, - "HelpEditToolbar"); - break; - } -} - -int ro_gui_theme_height_change(struct toolbar *toolbar) -{ - int height, cur_height; - - cur_height = ro_gui_theme_toolbar_full_height(toolbar); - height = toolbar->old_height - cur_height; - toolbar->old_height = cur_height; - return height; -} diff --git a/riscos/theme.h b/riscos/theme.h index eb96d2c6b..4a4ba1cb2 100644 --- a/riscos/theme.h +++ b/riscos/theme.h @@ -17,60 +17,32 @@ */ /** \file - * Window themes and toolbars (interface). + * Window themes(interface). */ #include +#include "oslib/osspriteop.h" #ifndef _NETSURF_RISCOS_THEME_H_ #define _NETSURF_RISCOS_THEME_H_ -/* icon numbers for browser toolbars */ -#define ICON_TOOLBAR_BACK 0 -#define ICON_TOOLBAR_FORWARD 1 -#define ICON_TOOLBAR_STOP 2 -#define ICON_TOOLBAR_RELOAD 3 -#define ICON_TOOLBAR_HOME 4 -#define ICON_TOOLBAR_HISTORY 5 -#define ICON_TOOLBAR_SAVE 6 -#define ICON_TOOLBAR_PRINT 7 -#define ICON_TOOLBAR_BOOKMARK 8 -#define ICON_TOOLBAR_SCALE 9 -#define ICON_TOOLBAR_SEARCH 10 -#define ICON_TOOLBAR_UP 11 -#define ICON_TOOLBAR_LAST 12 -#define ICON_TOOLBAR_SURROUND 12 // Must be after highest toolbar icon -#define ICON_TOOLBAR_FAVICON 13 -#define ICON_TOOLBAR_URL 14 -#define ICON_TOOLBAR_SUGGEST 15 -#define ICON_TOOLBAR_THROBBER 16 +/** Theme styles, collecting groups of attributes for different locations. */ -/* icon numbers for hotlist/history toolbars */ -#define ICON_TOOLBAR_DELETE 0 -#define ICON_TOOLBAR_EXPAND 1 -#define ICON_TOOLBAR_OPEN 2 -#define ICON_TOOLBAR_COOKIES_LAST 4 -#define ICON_TOOLBAR_LAUNCH 3 -#define ICON_TOOLBAR_HISTORY_LAST 4 -#define ICON_TOOLBAR_CREATE 4 // must be after last history icon -#define ICON_TOOLBAR_HOTLIST_LAST 5 +typedef enum { + THEME_STYLE_NONE = 0, + THEME_STYLE_BROWSER_TOOLBAR, + THEME_STYLE_HOTLIST_TOOLBAR, + THEME_STYLE_COOKIES_TOOLBAR, + THEME_STYLE_GLOBAL_HISTORY_TOOLBAR, + THEME_STYLE_STATUS_BAR +} theme_style; -/* editing toolbar separator number */ -#define ICON_TOOLBAR_SEPARATOR_BROWSER 11 -#define ICON_TOOLBAR_SEPARATOR_HOTLIST 5 -#define ICON_TOOLBAR_SEPARATOR_HISTORY 4 -#define ICON_TOOLBAR_SEPARATOR_COOKIES 3 +/** Theme elements, which belong to styles. */ typedef enum { - THEME_BROWSER_TOOLBAR, - THEME_HOTLIST_TOOLBAR, - THEME_HISTORY_TOOLBAR, - THEME_COOKIES_TOOLBAR, - THEME_BROWSER_EDIT_TOOLBAR, - THEME_HOTLIST_EDIT_TOOLBAR, - THEME_HISTORY_EDIT_TOOLBAR, - THEME_COOKIES_EDIT_TOOLBAR -} toolbar_type; + THEME_ELEMENT_FOREGROUND, + THEME_ELEMENT_BACKGROUND +} theme_element; struct theme_file_header { unsigned int magic_value; @@ -89,18 +61,6 @@ struct theme_file_header { unsigned int decompressed_sprite_size; }; -struct toolbar_icon { - int icon_number; /**< wimp icon number */ - bool display; /**< whether to display the icon */ - int x; /**< icon x position (valid only when displayed) */ - int y; /**< icon y position (valid only when displayed) */ - 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 theme { osspriteop_area *sprite_area; /**< sprite area for theme */ int throbber_width; /**< width of the throbber */ @@ -109,26 +69,6 @@ struct theme { int users; /**< number of users for the theme */ }; -struct toolbar { - bool display_buttons; /**< display standard buttons */ - bool display_url; /**< display URL bar (if applicable) */ - bool display_throbber; /**< display throbber (if applicable) */ - int toolbar_current; /**< the size of the toolbar window in OS units */ - int height; /**< vertical extent of the toolbar (read only) */ - int max_height; /**< allowed vertical extent (read only) */ - int old_height; /**< height on last test (read only) */ - wimp_w toolbar_handle; /**< toolbar window handle */ - 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) */ - struct toolbar_icon *icon; /**< first toolbar icon (read only) */ - struct toolbar_icon *suggest; /**< suggestion toolbar icon (read only) */ - struct theme_descriptor *descriptor; /**< theme descriptor (read only) */ - toolbar_type type; /**< toolbar type (read only) */ - struct toolbar *editor; /**< toolbar editor */ -}; - struct theme_descriptor { char *leafname; /**< theme leafname */ char *filename; /**< theme filename */ @@ -151,33 +91,19 @@ void ro_gui_theme_initialise(void); void ro_gui_theme_finalise(void); struct theme_descriptor *ro_gui_theme_find(const char *leafname); struct theme_descriptor *ro_gui_theme_get_available(void); +struct theme_descriptor *ro_gui_theme_get_current(void); +osspriteop_area *ro_gui_theme_get_sprites(struct theme_descriptor *descriptor); +int ro_gui_theme_get_style_element(struct theme_descriptor *descriptor, + theme_style style, theme_element element); +bool ro_gui_theme_get_throbber_data(struct theme_descriptor *descriptor, + int *frames, int *width, int *height, + bool *right, bool *redraw); + 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); 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); -bool ro_gui_theme_process_toolbar(struct toolbar *toolbar, int width); -void ro_gui_theme_destroy_toolbar(struct toolbar *toolbar); -void ro_gui_theme_refresh_toolbar(struct toolbar *toolbar); - -void ro_gui_theme_toggle_edit(struct toolbar *toolbar); -void ro_gui_theme_toolbar_editor_sync(struct toolbar *toolbar); -void ro_gui_theme_toolbar_editor_click(struct toolbar *toolbar, wimp_pointer *pointer); -void ro_gui_theme_toolbar_editor_drag_end(wimp_dragged *drag); - -int ro_gui_theme_height_change(struct toolbar *toolbar); - -struct toolbar_icon *ro_gui_theme_toolbar_get_icon(struct toolbar *toolbar, int x, int y); - -#define ro_gui_theme_toolbar_height(toolbar) (toolbar->height + \ - (toolbar->editor ? toolbar->editor->height : 0) > toolbar->max_height ? \ - toolbar->max_height : toolbar->height + \ - (toolbar->editor ? toolbar->editor->height : 0)) -#define ro_gui_theme_toolbar_full_height(toolbar) (toolbar->height + \ - (toolbar->editor ? toolbar->editor->height : 0)) #endif + diff --git a/riscos/toolbar.c b/riscos/toolbar.c new file mode 100644 index 000000000..374650d46 --- /dev/null +++ b/riscos/toolbar.c @@ -0,0 +1,1770 @@ +/* + * Copyright 2004, 2005 Richard Wilson + * Copyright 2010, 2011 Stephen Fryatt + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** \file + * Window toolbars (implementation). + */ + +#include +#include +#include +#include +#include +#include "oslib/dragasprite.h" +#include "oslib/os.h" +#include "oslib/osgbpb.h" +#include "oslib/osfile.h" +#include "oslib/osfind.h" +#include "oslib/osspriteop.h" +#include "oslib/wimpspriteop.h" +#include "oslib/squash.h" +#include "oslib/wimp.h" +#include "oslib/wimpextend.h" +#include "oslib/wimpspriteop.h" +#include "content/content.h" +#include "desktop/gui.h" +#include "desktop/plotters.h" +#include "riscos/cookies.h" +#include "riscos/dialog.h" +#include "riscos/global_history.h" +#include "riscos/gui.h" +#include "riscos/gui/button_bar.h" +#include "riscos/gui/throbber.h" +#include "riscos/gui/url_bar.h" +#include "riscos/hotlist.h" +#include "riscos/menus.h" +#include "riscos/options.h" +#include "riscos/save.h" +#include "riscos/theme.h" +#include "riscos/toolbar.h" +#include "riscos/treeview.h" +#include "riscos/url_complete.h" +#include "riscos/wimp.h" +#include "riscos/wimp_event.h" +#include "riscos/wimputils.h" +#include "riscos/window.h" +#include "utils/log.h" +#include "utils/utils.h" + + +#define TOOLBAR_WIDGET_GUTTER 8 + +/* Toolbar rows used to index into the arrays of row-specific data. + */ + +#define TOOLBAR_ROW_TOP 0 +#define TOOLBAR_ROW_DIV1 1 +#define TOOLBAR_ROW_EDIT 2 +#define TOOLBAR_MAX_ROWS 3 + +/* The toolbar data structure. + */ + +struct toolbar { + /** Bar details. */ + struct theme_descriptor *theme; + theme_style style; + toolbar_flags flags; + + int current_width, current_height; + int full_width, full_height; + int clip_width, clip_height; + + /** Toolbar and parent window handles. */ + wimp_w toolbar_handle; + wimp_w parent_handle; + + /** Row locations and sizes. */ + int row_y0[TOOLBAR_MAX_ROWS]; + int row_y1[TOOLBAR_MAX_ROWS]; + + /** Details for the button bar. */ + struct button_bar *buttons; + bool buttons_display; + os_coord buttons_size; + + /** Details for the URL bar. */ + struct url_bar *url; + bool url_display; + os_coord url_size; + + /** Details for the throbber. */ + struct throbber *throbber; + bool throbber_display; + bool throbber_right; + os_coord throbber_size; + + /** Client callback data. */ + const struct toolbar_callbacks *callbacks; + void *client_data; + + /** Details for the toolbar editor. */ + wimp_i editor_div1; + struct button_bar *editor; + os_coord editor_size; + + bool editing; + + /** Interactive help data. */ + + const char *help_prefix; + + /** The next bar in the toolbar list. */ + struct toolbar *next; +}; + + +/* Global variables for the toolbar module. + */ + +/** The list of defined toolbars. */ +static struct toolbar *ro_toolbar_bars = NULL; + +/** The Toolber Menu */ +wimp_menu *toolbar_menu; + + +/* A basic window definition for the toolbar and status bar. + */ + +static wimp_window ro_toolbar_window = { + {0, 0, 1, 1}, + 0, + 0, + wimp_TOP, + wimp_WINDOW_NEW_FORMAT | wimp_WINDOW_MOVEABLE | wimp_WINDOW_NO_BOUNDS | + wimp_WINDOW_FURNITURE_WINDOW | + wimp_WINDOW_IGNORE_XEXTENT | wimp_WINDOW_IGNORE_YEXTENT, + 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+ */, + {0, 0, 16384, 16384}, + 0, + wimp_BUTTON_CLICK_DRAG << wimp_ICON_BUTTON_TYPE_SHIFT, + wimpspriteop_AREA, + 1, + 1, + {""}, + 0, + { } +}; + +static char ro_toolbar_null_string[] = ""; +static char ro_toolbar_line_validation[] = "R2"; + +/* + * Private function prototypes. + */ + +static void ro_toolbar_update_current_widgets(struct toolbar *toolbar); +static void ro_toolbar_refresh_widget_dimensions(struct toolbar *toolbar); +static void ro_toolbar_reformat_widgets(struct toolbar *toolbar); + +static void ro_toolbar_redraw(wimp_draw *redraw); +static bool ro_toolbar_click(wimp_pointer *pointer); +static bool ro_toolbar_keypress(wimp_key *key); +static bool ro_toolbar_menu_prepare(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_pointer *pointer); +static void ro_toolbar_menu_warning(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_selection *selection, menu_action action); +static bool ro_toolbar_menu_select(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_selection *selection, menu_action action); +static const char *ro_toolbar_get_help_suffix(wimp_w w, wimp_i i, os_coord *pos, + wimp_mouse_state buttons); + +static void ro_toolbar_update_buttons(struct toolbar *toolbar); + + +/* This is an exported interface documented in toolbar.h */ + +void ro_toolbar_init(void) +{ + /* browser toolbar menu */ + static const struct ns_menu toolbar_definition = { + "Toolbar", { + { "Toolbars", NO_ACTION, 0 }, + { "Toolbars.ToolButtons", TOOLBAR_BUTTONS, 0 }, + { "Toolbars.ToolAddress", TOOLBAR_ADDRESS_BAR, 0 }, + { "Toolbars.ToolThrob", TOOLBAR_THROBBER, 0 }, + { "EditToolbar", TOOLBAR_EDIT, 0 }, + {NULL, 0, 0} + } + }; + toolbar_menu = ro_gui_menu_define_menu( + &toolbar_definition); +} + + +/* This is an exported interface documented in toolbar.h */ + +struct toolbar *ro_toolbar_create(struct theme_descriptor *descriptor, + wimp_w parent, theme_style style, toolbar_flags bar_flags, + const struct toolbar_callbacks *callbacks, void *client_data, + const char *help) +{ + struct toolbar *toolbar; + + /* Allocate memory for the bar and link it into the list of bars. */ + + toolbar = calloc(sizeof(struct toolbar), 1); + if (toolbar == NULL) { + LOG(("No memory for malloc()")); + warn_user("NoMemory", 0); + return NULL; + } + + toolbar->next = ro_toolbar_bars; + ro_toolbar_bars = toolbar; + + /* Store the supplied settings. */ + + toolbar->flags = bar_flags; + toolbar->theme = descriptor; + toolbar->style = style; + toolbar->parent_handle = parent; + toolbar->callbacks = callbacks; + toolbar->client_data = client_data; + + /* Set up the internal widgets: initially, there are none. */ + + toolbar->buttons = NULL; + toolbar->buttons_display = false; + + toolbar->url = NULL; + toolbar->url_display = false; + + toolbar->throbber = NULL; + toolbar->throbber_display = false; + + /* Set up the bar editor. */ + + toolbar->editor = NULL; + toolbar->editor_div1 = -1; + + toolbar->editing = false; + + toolbar->help_prefix = help; + + return toolbar; +} + + +/* This is an exported interface documented in toolbar.h */ + +bool ro_toolbar_add_buttons(struct toolbar *toolbar, + const struct button_bar_buttons buttons[], char *button_order) +{ + if (toolbar == NULL) + return false; + + if (toolbar->buttons != NULL) + return false; + + toolbar->buttons = ro_gui_button_bar_create(toolbar->theme, buttons); + if (toolbar->buttons != NULL) { + toolbar->buttons_display = true; + ro_gui_button_bar_arrange_buttons(toolbar->buttons, + button_order); + } + + toolbar->editor = ro_gui_button_bar_create(toolbar->theme, buttons); + if (toolbar->editor != NULL) + ro_gui_button_bar_hide(toolbar->editor, !toolbar->editing); + + if (toolbar->buttons != NULL && toolbar->editor != NULL) + if (!ro_gui_button_bar_link_editor(toolbar->buttons, + toolbar->editor, + (void (*)(void *)) + ro_toolbar_update_current_widgets, + toolbar)) + return false; + + return (toolbar->buttons == NULL || toolbar->editor == NULL) ? + false : true; +} + + +/* This is an exported interface documented in toolbar.h */ + +bool ro_toolbar_add_throbber(struct toolbar *toolbar) +{ + if (toolbar == NULL) + return false; + + if (toolbar->throbber != NULL) + return false; + + toolbar->throbber = ro_gui_throbber_create(toolbar->theme); + + if (toolbar->throbber != NULL) + toolbar->throbber_display = true; + + return (toolbar->throbber == NULL) ? false : true; +} + + +/* This is an exported interface documented in toolbar.h */ + +bool ro_toolbar_add_url(struct toolbar *toolbar) +{ + if (toolbar == NULL) + return false; + + if (toolbar->url != NULL) + return false; + + toolbar->url = ro_gui_url_bar_create(toolbar->theme); + + if (toolbar->url != NULL) + toolbar->url_display = true; + + return (toolbar->url == NULL) ? false : true; +} + + +/* This is an exported interface documented in toolbar.h */ + +bool ro_toolbar_rebuild(struct toolbar *toolbar) +{ + os_error *error; + wimp_icon_create icon; + wimp_w old_window = NULL; + + if (toolbar == NULL) + return false; + + /* Start to set up the toolbar window. */ + + ro_toolbar_window.sprite_area = + ro_gui_theme_get_sprites(toolbar->theme); + ro_toolbar_window.work_bg = + ro_gui_theme_get_style_element(toolbar->theme, + toolbar->style, THEME_ELEMENT_BACKGROUND); + + /* Delete any existing toolbar window... */ + + if (toolbar->toolbar_handle != NULL) { + old_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; + } + + /* ...and create a new window. */ + + error = xwimp_create_window(&ro_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; + } + + /* Set up the toolbar's event handlers. Only set the user activity- + * related callbacks if the bar isn't for display purposes. If the + * toolbar is being recreated, simply transfer the handlers across + * from the old, now-deleted window. + */ + + if (old_window == NULL) { + ro_gui_wimp_event_register_redraw_window( + toolbar->toolbar_handle, ro_toolbar_redraw); + ro_gui_wimp_event_set_user_data(toolbar->toolbar_handle, + toolbar); + + if (!(toolbar->flags & TOOLBAR_FLAGS_DISPLAY)) { + ro_gui_wimp_event_register_mouse_click( + toolbar->toolbar_handle, + ro_toolbar_click); + ro_gui_wimp_event_register_keypress( + toolbar->toolbar_handle, + ro_toolbar_keypress); + ro_gui_wimp_event_register_menu_prepare( + toolbar->toolbar_handle, + ro_toolbar_menu_prepare); + ro_gui_wimp_event_register_menu_warning( + toolbar->toolbar_handle, + ro_toolbar_menu_warning); + ro_gui_wimp_event_register_menu_selection( + toolbar->toolbar_handle, + ro_toolbar_menu_select); + ro_gui_wimp_event_register_menu(toolbar->toolbar_handle, + toolbar_menu, true, false); + ro_gui_wimp_event_register_help_suffix( + toolbar->toolbar_handle, + ro_toolbar_get_help_suffix); + } + } else { + ro_gui_wimp_event_transfer(old_window, toolbar->toolbar_handle); + } + + /* The help prefix changes from edit to non-edit more. */ + + ro_gui_wimp_event_set_help_prefix(toolbar->toolbar_handle, + (toolbar->editing) ? + "HelpEditToolbar" : toolbar->help_prefix); + + /* Place the widgets into the new bar, using the new theme. + * + * \TODO -- If any widgets fail to rebuild, then we currently just + * carry on without them. Not sure if the whole bar + * rebuild should fail here? + */ + + if (toolbar->throbber != NULL) { + if (!ro_gui_throbber_rebuild(toolbar->throbber, toolbar->theme, + toolbar->style, toolbar->toolbar_handle, + toolbar->editing)) { + ro_gui_throbber_destroy(toolbar->throbber); + toolbar->throbber = NULL; + } + + ro_gui_theme_get_throbber_data(toolbar->theme, NULL, NULL, NULL, + &toolbar->throbber_right, NULL); + } + + if (toolbar->buttons != NULL) { + if (!ro_gui_button_bar_rebuild(toolbar->buttons, toolbar->theme, + toolbar->style, toolbar->toolbar_handle, + toolbar->editing)) { + ro_gui_button_bar_destroy(toolbar->buttons); + toolbar->buttons = NULL; + } + } + + if (toolbar->editor != NULL) { + if (!ro_gui_button_bar_rebuild(toolbar->editor, toolbar->theme, + toolbar->style, toolbar->toolbar_handle, + toolbar->editing)) { + ro_gui_button_bar_destroy(toolbar->editor); + toolbar->editor = NULL; + } + } + + if (toolbar->url != NULL) { + if (!ro_gui_url_bar_rebuild(toolbar->url, toolbar->theme, + toolbar->style, toolbar->toolbar_handle, + toolbar->flags & TOOLBAR_FLAGS_DISPLAY, + toolbar->editing)) { + ro_gui_url_bar_destroy(toolbar->url); + toolbar->url = NULL; + } + } + + /* If this is an editor, add in a divider icon and the editor + * button bar. + */ + + if (toolbar->editing) { + icon.w = toolbar->toolbar_handle; + icon.icon.flags = wimp_ICON_TEXT | wimp_ICON_INDIRECTED | + wimp_ICON_VCENTRED | wimp_ICON_BORDER | + (wimp_COLOUR_BLACK << + wimp_ICON_FG_COLOUR_SHIFT) | + (wimp_COLOUR_VERY_LIGHT_GREY << + wimp_ICON_BG_COLOUR_SHIFT); + icon.icon.extent.x0 = 0; + icon.icon.extent.x1 = 0; + icon.icon.extent.y1 = 0; + icon.icon.extent.y0 = 0; + icon.icon.data.indirected_text.text = ro_toolbar_null_string; + icon.icon.data.indirected_text.validation = + ro_toolbar_line_validation; + icon.icon.data.indirected_text.size = 1; + error = xwimp_create_icon(&icon, &toolbar->editor_div1); + if (error) { + LOG(("xwimp_create_icon: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + toolbar->editor_div1 = -1; + } + } + + /* Establish the required dimensions to fit the widgets, then + * reflow the bar contents. + */ + + ro_toolbar_refresh_widget_dimensions(toolbar); + + ro_toolbar_process(toolbar, -1, true); + + if (toolbar->parent_handle != NULL) + ro_toolbar_attach(toolbar, toolbar->parent_handle); + + ro_toolbar_update_buttons(toolbar); + + return true; +} + + +/* This is an exported interface documented in toolbar.h */ + +bool ro_toolbar_attach(struct toolbar *toolbar, wimp_w parent) +{ + wimp_outline outline; + wimp_window_state state; + os_error *error; + + if (toolbar == NULL || toolbar->toolbar_handle == NULL) + return false; + + toolbar->parent_handle = parent; + + /* Only try to attach the toolbar if there's any of it visible to + * matter. + */ + + if (toolbar->current_height > 0) { + outline.w = parent; + xwimp_get_window_outline(&outline); + 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 + 2 - + toolbar->current_height; + state.xscroll = 0; + state.yscroll = 0; + error = xwimp_open_window_nested(PTR_WIMP_OPEN(&state), parent, + wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT + << wimp_CHILD_XORIGIN_SHIFT | + 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_LINKS_PARENT_VISIBLE_TOP_OR_RIGHT + << wimp_CHILD_BS_EDGE_SHIFT | + wimp_CHILD_LINKS_PARENT_VISIBLE_TOP_OR_RIGHT + << wimp_CHILD_RS_EDGE_SHIFT | + wimp_CHILD_LINKS_PARENT_VISIBLE_TOP_OR_RIGHT + << wimp_CHILD_TS_EDGE_SHIFT); + if (error) { + LOG(("xwimp_open_window_nested: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return false; + } + + return true; + } + + error = xwimp_close_window(toolbar->toolbar_handle); + if (error) { + LOG(("xwimp_close_window: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return false; + } + return true; +} + + +/* This is an exported interface documented in toolbar.h */ + +bool ro_toolbar_process(struct toolbar *toolbar, int width, bool reformat) +{ + os_error *error; + wimp_outline outline; + wimp_window_state state; + int old_height, old_width; + int xeig, yeig; + os_coord pixel = {1, 1}; + + if (!toolbar) + return false; + + old_height = toolbar->current_height; + old_width = toolbar->current_width; + + /* calculate 1px in OS units */ + + ro_convert_pixels_to_os_units(&pixel, (os_mode)-1); + xeig = pixel.x; + yeig = pixel.y; + + /* Measure the parent window width if the caller has asked us to + * calculate the clip width ourselves. Otherwise, if a clip width + * has been specified, set the clip to that. + */ + + if ((toolbar->parent_handle != NULL) && (width == -1)) { + 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; + } + + toolbar->clip_width = outline.outline.x1 - + outline.outline.x0 - 2; + toolbar->current_width = toolbar->clip_width; + } else if (width != -1) { + toolbar->clip_width = width; + toolbar->current_width = toolbar->clip_width; + } + + /* Find the parent visible height to clip our toolbar height to + */ + + if (toolbar->parent_handle != NULL) { + state.w = toolbar->parent_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; + } + + toolbar->clip_height = state.visible.y1 - state.visible.y0 + 2; + + /* We can't obscure the height of the scroll bar as we + * lose the resize icon if we do. + */ + + if (toolbar->clip_height >= toolbar->full_height) + toolbar->current_height = toolbar->full_height; + else + toolbar->current_height = toolbar->clip_height; + + /* Update our position + */ + if (old_height != toolbar->current_height) + ro_toolbar_attach(toolbar, toolbar->parent_handle); + } else { + toolbar->clip_height = toolbar->full_height; + toolbar->current_height = toolbar->full_height; + } + + /* Reflow the widgets into the toolbar if the dimensions have + * changed or we have been asked to anyway. */ + + if (toolbar->current_width != old_width || reformat) + ro_toolbar_reformat_widgets(toolbar); + + return true; +} + + +/** + * Update the widgets currently on view in a toolbar. This can be used + * generally, but is primarily offered to widgets as a way for them + * to force an update. + * + * \param *toolbar The toolbar to update. + */ + +void ro_toolbar_update_current_widgets(struct toolbar *toolbar) +{ + int old_height; + + if (toolbar == NULL) + return; + + old_height = toolbar->full_height; + + ro_toolbar_refresh_widget_dimensions(toolbar); + ro_toolbar_reformat_widgets(toolbar); + + /* If the toolbar height has changed, we need to tell the client. */ + + if (toolbar->full_height != old_height) + ro_toolbar_refresh(toolbar); +} + + +/** + * Get the minimum dimenstions required by the toolbar widgets after + * these have changed. The minimum dimensions are assumed not to change + * unless we change theme (ie. we rebuild the bar) or we knowingly + * alter a widget (eg. we add or remove button-bar buttons). + * + * + * \param *toolbar The toolbar to refresh. + */ + +void ro_toolbar_refresh_widget_dimensions(struct toolbar *toolbar) +{ + int width, height; + int row_width, row_height; + + if (toolbar == NULL) + return; + + /* Process the toolbar editor and any associated divider rows. + */ + + if (toolbar->editor != NULL && toolbar->editing) { + width = 0; + height = 0; + ro_gui_button_bar_get_dims(toolbar->editor, &width, &height); + + toolbar->editor_size.x = width; + toolbar->editor_size.y = height; + + toolbar->row_y0[TOOLBAR_ROW_EDIT] = TOOLBAR_WIDGET_GUTTER; + toolbar->row_y1[TOOLBAR_ROW_EDIT] = TOOLBAR_WIDGET_GUTTER + + height; + + toolbar->row_y0[TOOLBAR_ROW_DIV1] = TOOLBAR_WIDGET_GUTTER + + toolbar->row_y1[TOOLBAR_ROW_EDIT]; + toolbar->row_y1[TOOLBAR_ROW_DIV1] = 8 + + toolbar->row_y0[TOOLBAR_ROW_DIV1]; + } else { + toolbar->editor_size.x = 0; + toolbar->editor_size.y = 0; + + toolbar->row_y0[TOOLBAR_ROW_EDIT] = 0; + toolbar->row_y1[TOOLBAR_ROW_EDIT] = 0; + toolbar->row_y0[TOOLBAR_ROW_DIV1] = 0; + toolbar->row_y1[TOOLBAR_ROW_DIV1] = 0; + } + + /* Process the top row icons. */ + + row_width = 0; + row_height = 0; + + /* If the editor is active, any button bar if forced into view. */ + + if (toolbar->buttons != NULL && + (toolbar->buttons_display || toolbar->editing)) { + width = 0; + height = 0; + ro_gui_button_bar_get_dims(toolbar->buttons, &width, &height); + + row_width += width; + toolbar->buttons_size.x = width; + toolbar->buttons_size.y = height; + + if (height > row_height) + row_height = height; + } else { + toolbar->buttons_size.x = 0; + toolbar->buttons_size.y = 0; + } + + if (toolbar->url != NULL && toolbar->url_display) { + width = 0; + height = 0; + ro_gui_url_bar_get_dims(toolbar->url, &width, &height); + + if (row_width > 0) + row_width += TOOLBAR_WIDGET_GUTTER; + row_width += width; + + toolbar->url_size.x = width; + toolbar->url_size.y = height; + + if (height > row_height) + row_height = height; + } else { + toolbar->url_size.x = 0; + toolbar->url_size.y = 0; + } + + if (toolbar->throbber != NULL && toolbar->throbber_display) { + width = 0; + height = 0; + ro_gui_throbber_get_dims(toolbar->throbber, &width, &height); + + if (row_width > 0) + row_width += TOOLBAR_WIDGET_GUTTER; + row_width += width; + + toolbar->throbber_size.x = width; + toolbar->throbber_size.y = height; + + if (height > row_height) + row_height = height; + } else { + toolbar->throbber_size.x = 0; + toolbar->throbber_size.y = 0; + } + + if (row_height > 0) { + toolbar->row_y0[TOOLBAR_ROW_TOP] = TOOLBAR_WIDGET_GUTTER + + toolbar->row_y1[TOOLBAR_ROW_DIV1]; + toolbar->row_y1[TOOLBAR_ROW_TOP] = row_height + + toolbar->row_y0[TOOLBAR_ROW_TOP]; + } else { + toolbar->row_y0[TOOLBAR_ROW_TOP] = 0; + toolbar->row_y1[TOOLBAR_ROW_TOP] = 0; + } + + /* Establish the full dimensions of the bar. + * + * \TODO -- This currently assumes an "all or nothing" approach to + * the editor bar, and will need reworking once we have to + * worry about tab bars. + */ + + if (toolbar->row_y1[TOOLBAR_ROW_TOP] > 0) { + toolbar->full_height = toolbar->row_y1[TOOLBAR_ROW_TOP] + + TOOLBAR_WIDGET_GUTTER; + } else { + toolbar->full_height = 0; + } + toolbar->full_width = 2 * TOOLBAR_WIDGET_GUTTER + + (row_width > toolbar->editor_size.x) ? + row_width : toolbar->editor_size.x; +} + + +/** + * Reformat (reflow) the widgets into the toolbar, based on the toolbar size + * and the previously calculated widget dimensions. + * + * \param *toolbar The toolbar to reformat. + */ + +void ro_toolbar_reformat_widgets(struct toolbar *toolbar) +{ + int left_margin, right_margin; + + left_margin = TOOLBAR_WIDGET_GUTTER; + right_margin = toolbar->clip_width - TOOLBAR_WIDGET_GUTTER; + + /* Flow the toolbar editor row, which will be a fixed with and + * may alter the right margin. + */ + + if (toolbar->editor != NULL && toolbar->editing) { + if (right_margin < left_margin + toolbar->editor_size.x) + right_margin = left_margin + toolbar->editor_size.x; + + ro_gui_button_bar_set_extent(toolbar->editor, + left_margin, + toolbar->row_y0[TOOLBAR_ROW_EDIT], + left_margin + toolbar->editor_size.x, + toolbar->row_y1[TOOLBAR_ROW_EDIT]); + + if (toolbar->editor_div1 != -1) + xwimp_resize_icon(toolbar->toolbar_handle, + toolbar->editor_div1, -8, + toolbar->row_y0[TOOLBAR_ROW_DIV1], + toolbar->clip_width + 8, + toolbar->row_y1[TOOLBAR_ROW_DIV1]); + } + + /* Flow the top row. */ + + if (toolbar->throbber != NULL && toolbar->throbber_display) { + if (toolbar->throbber_right) { + right_margin -= (toolbar->throbber_size.x + + TOOLBAR_WIDGET_GUTTER); + } else { + ro_gui_throbber_set_extent(toolbar->throbber, + left_margin, + toolbar->row_y0[TOOLBAR_ROW_TOP], + left_margin + toolbar->throbber_size.x, + toolbar->row_y1[TOOLBAR_ROW_TOP]); + left_margin += (toolbar->throbber_size.x + + TOOLBAR_WIDGET_GUTTER); + } + } + + if (toolbar->buttons != NULL && + (toolbar->buttons_display || toolbar->editing)) { + if (right_margin < left_margin + toolbar->buttons_size.x) + right_margin = left_margin + toolbar->buttons_size.x; + + ro_gui_button_bar_set_extent(toolbar->buttons, + left_margin, + toolbar->row_y0[TOOLBAR_ROW_TOP], + left_margin + toolbar->buttons_size.x, + toolbar->row_y1[TOOLBAR_ROW_TOP]); + left_margin += (toolbar->buttons_size.x + + TOOLBAR_WIDGET_GUTTER); + } + + if (toolbar->url != NULL && toolbar->url_display) { + if (right_margin < left_margin + toolbar->url_size.x) + right_margin = left_margin + toolbar->url_size.x; + + ro_gui_url_bar_set_extent(toolbar->url, + left_margin, + toolbar->row_y0[TOOLBAR_ROW_TOP], + right_margin, + toolbar->row_y1[TOOLBAR_ROW_TOP]); + + left_margin = right_margin + TOOLBAR_WIDGET_GUTTER; + } + + if (toolbar->throbber != NULL && toolbar->throbber_display && + toolbar->throbber_right) { + left_margin = right_margin + TOOLBAR_WIDGET_GUTTER; + ro_gui_throbber_set_extent(toolbar->throbber, + left_margin, + toolbar->row_y0[TOOLBAR_ROW_TOP], + left_margin + toolbar->throbber_size.x, + toolbar->row_y1[TOOLBAR_ROW_TOP]); + } + +} + + +/* This is an exported interface documented in toolbar.h */ + +void ro_toolbar_destroy(struct toolbar *toolbar) +{ + struct toolbar *bar; + + if (toolbar == NULL) + return; + + LOG(("Destroying toolbar 0x%x", (unsigned int) toolbar)); + + /* Destroy the widgets. */ + + if (toolbar->buttons != NULL) + ro_gui_button_bar_destroy(toolbar->buttons); + + if (toolbar->editor != NULL) + ro_gui_button_bar_destroy(toolbar->editor); + + if (toolbar->url != NULL) + ro_gui_url_bar_destroy(toolbar->url); + + if (toolbar->throbber != NULL) + ro_gui_throbber_destroy(toolbar->throbber); + + /* Delete the toolbar window. */ + + if (toolbar->toolbar_handle != NULL) { + xwimp_delete_window(toolbar->toolbar_handle); + ro_gui_wimp_event_finalise(toolbar->toolbar_handle); + } + + /* Remove the bar from the list and free the memory. + */ + + if (ro_toolbar_bars == toolbar) { + ro_toolbar_bars = toolbar->next; + } else { + for (bar = ro_toolbar_bars; bar != NULL && bar->next != toolbar; + bar = bar->next); + + if (bar->next == toolbar) + bar->next = toolbar->next; + } + + free(toolbar); + +} + + +/** + * Handle redraw request events for a toolbar workarea. + * + * \param *redraw The redraw block for the event. + */ + +void ro_toolbar_redraw(wimp_draw *redraw) +{ + struct toolbar *toolbar; + osbool more; + os_error *error; + + toolbar = (struct toolbar *)ro_gui_wimp_event_get_user_data(redraw->w); + + assert(toolbar != NULL); + + plot = ro_plotters; + ro_plot_set_scale(1.0); + + 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_plot_origin_x = redraw->box.x0 - redraw->xscroll; + ro_plot_origin_y = redraw->box.y1 - redraw->yscroll; + + if (toolbar->buttons != NULL && toolbar->buttons_display) + ro_gui_button_bar_redraw(toolbar->buttons, redraw); + + if (toolbar->editor != NULL && toolbar->editing) + ro_gui_button_bar_redraw(toolbar->editor, redraw); + + if (toolbar->url != NULL && toolbar->url_display) + ro_gui_url_bar_redraw(toolbar->url, 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; + } + } +} + + +/** + * Process clicks on a toolbar, passing details on to clients where necessary. + * + * \param *pointer The wimp mouse click event. + * \return True if the event was handled; else false. + */ + +bool ro_toolbar_click(wimp_pointer *pointer) +{ + struct toolbar *toolbar; + union toolbar_action action; + wimp_window_state state; + os_error *error; + + toolbar = (struct toolbar *) + ro_gui_wimp_event_get_user_data(pointer->w); + + if (toolbar == NULL) + return false; + + assert(pointer->w == toolbar->toolbar_handle); + + state.w = toolbar->toolbar_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; + } + + /* If the click wasn't in the URL Bar's text field, then it will + * need to close any URL Complete window that is open. + * + * \TODO -- This should really move into the URL Bar module, as + * URL Complete is really an extension to that. + */ + + if (toolbar->url != NULL && toolbar->url_display && + !ro_gui_url_bar_test_for_text_field_click(toolbar->url, + pointer)) + ro_gui_url_complete_close(); + + /* Pass the click around the toolbar widgets. */ + + if (toolbar->buttons != NULL && + (toolbar->buttons_display || toolbar->editing) && + ro_gui_button_bar_click(toolbar->buttons, pointer, + &state, &action.button)) { + if (action.button != TOOLBAR_BUTTON_NONE && + !toolbar->editing && + toolbar->callbacks != NULL && + toolbar->callbacks->user_action != NULL) + toolbar->callbacks->user_action(toolbar->client_data, + TOOLBAR_ACTION_BUTTON, action); + return true; + } + + if (toolbar->url != NULL && toolbar->url_display && + ro_gui_url_bar_click(toolbar->url, pointer, + &state, &action.url)) { + if (action.url != TOOLBAR_URL_NONE && + !toolbar->editing && + toolbar->callbacks != NULL && + toolbar->callbacks->user_action != NULL) + toolbar->callbacks->user_action(toolbar->client_data, + TOOLBAR_ACTION_URL, action); + return true; + } + + if (toolbar->editor != NULL && toolbar->editing && + ro_gui_button_bar_click(toolbar->editor, pointer, + &state, &action.button)) { + return true; + } + + /* Nothing else has handled this, so try passing it to the + * URL Complete module. + * + * \TODO -- This should really move into the URL Bar module, as + * URL Complete is really an extension to that. + */ + + if (toolbar->url != NULL && toolbar->url_display && + ro_gui_url_bar_test_for_text_field_click(toolbar->url, + pointer)) { + ro_gui_url_complete_start(toolbar); + return true; + } + + return false; +} + + +/** + * Process keypresses in a toolbar, passing details on to clients where + * necessary. + * + * \param *key The wimp key press event. + * \return True if the event was handled; else false. + */ + +bool ro_toolbar_keypress(wimp_key *key) +{ + struct toolbar *toolbar; + + toolbar = (struct toolbar *) ro_gui_wimp_event_get_user_data(key->w); + + if (toolbar == NULL) + return false; + + /* If the caret is in the URL bar, ask the URL Complete module if it + * wants to handle the keypress. + * + * \TODO -- This should really move into the URL Bar module, as + * URL Complete is really an extension to that. + */ + + if (toolbar->url != NULL && toolbar->url_display && + ro_gui_url_bar_test_for_text_field_keypress( + toolbar->url, key) && + ro_gui_url_complete_keypress(toolbar, key->c)) + return true; + + /* Otherwsie, pass the keypress on to the client. */ + + if (toolbar->callbacks->user_action != NULL) + toolbar->callbacks->key_press(toolbar->client_data, key); + + return true; +} + + +/** + * Prepare the toolbar menu for (re-)opening + * + * \param w The window owning the menu. + * \param i The icon owning the menu. + * \param *menu The menu about to be opened. + * \param *pointer Pointer to the relevant wimp event block, or + * NULL for an Adjust click. + * \return true if the event was handled; else false. + */ + +bool ro_toolbar_menu_prepare(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_pointer *pointer) +{ + struct toolbar *toolbar; + + toolbar = (struct toolbar *) ro_gui_wimp_event_get_user_data(w); + + if (toolbar == NULL) + return false; + + /* Pass the event on to potentially interested widgets. */ + + if (toolbar->url != NULL && ro_gui_url_bar_menu_prepare(toolbar->url, + i, menu, pointer)) + return true; + + /* Try to process the event as a toolbar menu. */ + + if (menu != toolbar_menu) + return false; + + /* Shade menu entries according to the state of the window and object + * under the pointer. + */ + + /* Toolbar (Sub)Menu */ + + ro_gui_menu_set_entry_shaded(menu, TOOLBAR_EDIT, + ro_toolbar_menu_edit_shade(toolbar)); + ro_gui_menu_set_entry_ticked(menu, TOOLBAR_EDIT, + ro_toolbar_menu_edit_tick(toolbar)); + + ro_gui_menu_set_entry_shaded(menu, TOOLBAR_BUTTONS, + ro_toolbar_menu_option_shade(toolbar) || + toolbar->buttons == NULL); + ro_gui_menu_set_entry_ticked(menu, TOOLBAR_BUTTONS, + ro_toolbar_menu_buttons_tick(toolbar) && + toolbar->buttons != NULL); + + ro_gui_menu_set_entry_shaded(menu, TOOLBAR_ADDRESS_BAR, + ro_toolbar_menu_edit_shade(toolbar) || + toolbar->url == NULL); + ro_gui_menu_set_entry_ticked(menu, TOOLBAR_ADDRESS_BAR, + ro_toolbar_menu_url_tick(toolbar) && + toolbar->url != NULL); + + ro_gui_menu_set_entry_shaded(menu, TOOLBAR_THROBBER, + ro_toolbar_menu_edit_shade(toolbar) || + toolbar->throbber == NULL); + ro_gui_menu_set_entry_ticked(menu, TOOLBAR_THROBBER, + ro_toolbar_menu_throbber_tick(toolbar) && + toolbar->throbber != NULL); + + return true; +} + + +/** + * Handle submenu warnings for the toolbar menu + * + * \param w The window owning the menu. + * \param i The icon owning the menu. + * \param *menu The menu to which the warning applies. + * \param *selection The wimp menu selection data. + * \param action The selected menu action. + */ + +void ro_toolbar_menu_warning(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_selection *selection, menu_action action) +{ + /* Do nothing */ +} + + +/** + * Handle selections from the toolbar menu + * + * \param w The window owning the menu. + * \param i The icon owning the menu. + * \param *menu The menu from which the selection was made. + * \param *selection The wimp menu selection data. + * \param action The selected menu action. + * \return true if action accepted; else false. + */ + +bool ro_toolbar_menu_select(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_selection *selection, menu_action action) +{ + struct toolbar *toolbar; + + toolbar = (struct toolbar *) ro_gui_wimp_event_get_user_data(w); + + if (toolbar == NULL) + return false; + + /* Pass the event on to potentially interested widgets. */ + + if (toolbar->url != NULL && ro_gui_url_bar_menu_select(toolbar->url, + i, menu, selection, action)) + return true; + + /* Try to process the event as a toolbar menu. */ + + if (menu != toolbar_menu) + return false; + + switch (action) { + case TOOLBAR_BUTTONS: + ro_toolbar_set_display_buttons(toolbar, + !ro_toolbar_get_display_buttons(toolbar)); + break; + case TOOLBAR_ADDRESS_BAR: + ro_toolbar_set_display_url(toolbar, + !ro_toolbar_get_display_url(toolbar)); + if (ro_toolbar_get_display_url(toolbar)) + ro_toolbar_take_caret(toolbar); + break; + case TOOLBAR_THROBBER: + ro_toolbar_set_display_throbber(toolbar, + !ro_toolbar_get_display_throbber(toolbar)); + break; + case TOOLBAR_EDIT: + ro_toolbar_toggle_edit(toolbar); + break; + default: + return false; + } + + return true; +} + + +/** + * Translate the contents of a message_HELP_REQUEST into a suffix for a + * NetSurf message token. The help system will then add this to whatever + * prefix the current toolbar has registered with WimpEvent. + * + * \param w The window handle under the mouse. + * \param i The icon handle under the mouse. + * \param *pos The mouse position. + * \param buttons The mouse button state. + * \return The required help token suffix. + */ + +const char *ro_toolbar_get_help_suffix(wimp_w w, wimp_i i, os_coord *pos, + wimp_mouse_state buttons) +{ + struct toolbar *toolbar; + wimp_window_state state; + os_error *error; + const char *suffix; + + toolbar = (struct toolbar *) ro_gui_wimp_event_get_user_data(w); + + if (toolbar == NULL || toolbar->toolbar_handle != w) + return NULL; + + state.w = toolbar->toolbar_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 NULL; + } + + /* Pass the help request around the toolbar widgets. */ + + if (toolbar->throbber != NULL && toolbar->throbber_display && + ro_gui_throbber_help_suffix(toolbar->throbber, i, + pos, &state, buttons, &suffix)) + return suffix; + + if (toolbar->url != NULL && toolbar->url_display && + ro_gui_url_bar_help_suffix(toolbar->url, i, + pos, &state, buttons, &suffix)) + return suffix; + + if (toolbar->buttons != NULL && toolbar->buttons_display && + ro_gui_button_bar_help_suffix(toolbar->buttons, i, + pos, &state, buttons, &suffix)) + return suffix; + + return ""; +} + + +/* This is an exported interface documented in toolbar.h */ + +void ro_toolbar_update_client_data(struct toolbar *toolbar, void *client_data) +{ + if (toolbar != NULL) + toolbar->client_data = client_data; +} + + +/* This is an exported interface documented in toolbar.h */ + +void ro_toolbar_update_all_buttons(void) +{ + struct toolbar *bar; + + bar = ro_toolbar_bars; + while (bar != NULL) { + ro_toolbar_update_buttons(bar); + + bar = bar->next; + } +} + + +/** + * Update the state of a toolbar's buttons. + * + * \param toolbar the toolbar to update + */ + +void ro_toolbar_update_buttons(struct toolbar *toolbar) +{ + assert(toolbar != NULL); + + if (toolbar->callbacks != NULL && + toolbar->callbacks->update_buttons != NULL) + toolbar->callbacks->update_buttons(toolbar->client_data); +} + +/* This is an exported interface documented in toolbar.h */ + +void ro_toolbar_refresh(struct toolbar *toolbar) +{ + assert(toolbar != NULL); + + ro_toolbar_process(toolbar, -1, true); + if (toolbar->callbacks != NULL && + toolbar->callbacks->change_size != NULL) + toolbar->callbacks->change_size(toolbar->client_data); + + if (toolbar->toolbar_handle != NULL) + xwimp_force_redraw(toolbar->toolbar_handle, 0, 0, + toolbar->current_width, + toolbar->current_height); +} + + +/* This is an exported interface documented in toolbar.h */ + +void ro_toolbar_theme_update(void) +{ + struct toolbar *bar, *next; + bool ok; + + bar = ro_toolbar_bars; + while (bar != NULL) { + /* Take the next bar address now, as *bar may become invalid + * during the update process (if an update fails and + * ro_toolbar_destroy() is called) and we don't want to lose + * the link to the rest of the chain. + */ + + next = bar->next; + + /* Only process the bar if the theme is set to the default. + * Otherwise, it's up to the owner to do whatever they need + * to do for themselves. + */ + + if (bar->theme == NULL) { + ok = ro_toolbar_rebuild(bar); + + if (!ok) + ro_toolbar_destroy(bar); + } else { + ok = true; + } + + if (bar->callbacks != NULL && + bar->callbacks->theme_update != NULL) + bar->callbacks->theme_update(bar->client_data, ok); + + bar = next; + } +} + + +/* This is an exported interface documented in toolbar.h */ + +struct toolbar *ro_toolbar_parent_window_lookup(wimp_w w) +{ + struct toolbar *toolbar; + + toolbar = ro_toolbar_bars; + while (toolbar != NULL && toolbar->parent_handle != w) + toolbar = toolbar->next; + + return toolbar; +} + + +/* This is an exported interface documented in toolbar.h */ + +struct toolbar *ro_toolbar_window_lookup(wimp_w w) +{ + struct toolbar *toolbar; + + toolbar = ro_toolbar_bars; + while (toolbar != NULL && toolbar->toolbar_handle != w) + toolbar = toolbar->next; + + return toolbar; +} + + +/* This is an exported interface documented in toolbar.h */ + +wimp_w ro_toolbar_get_parent_window(struct toolbar *toolbar) +{ + return (toolbar != NULL) ? toolbar->parent_handle : 0; +} + + +/* This is an exported interface documented in toolbar.h */ + +wimp_w ro_toolbar_get_window(struct toolbar *toolbar) +{ + return (toolbar != NULL) ? toolbar->toolbar_handle : 0; +} + + +/* This is an exported interface documented in toolbar.h */ + +int ro_toolbar_height(struct toolbar *toolbar) +{ + return (toolbar == NULL) ? 0 : toolbar->current_height; +} + + +/* This is an exported interface documented in toolbar.h */ + +int ro_toolbar_full_height(struct toolbar *toolbar) +{ + return (toolbar == NULL) ? 0 : toolbar->full_height; +} + + +/* This is an exported interface documented in toolbar.h */ + +void ro_toolbar_start_throbbing(struct toolbar *toolbar) +{ + if (toolbar != NULL && toolbar->throbber != NULL) + ro_gui_throbber_animate(toolbar->throbber); +} + + +/* This is an exported interface documented in toolbar.h */ + +void ro_toolbar_stop_throbbing(struct toolbar *toolbar) +{ + if (toolbar != NULL && toolbar->throbber != NULL) + ro_gui_throbber_stop(toolbar->throbber); +} + + +/* This is an exported interface documented in toolbar.h */ + +void ro_toolbar_throb(struct toolbar *toolbar) +{ + if (toolbar != NULL && toolbar->throbber != NULL) + ro_gui_throbber_animate(toolbar->throbber); +} + + +/* This is an exported interface documented in toolbar.h */ + +bool ro_toolbar_set_button_order(struct toolbar *toolbar, char order[]) +{ + if (toolbar == NULL || toolbar->buttons == NULL) + return false; + + if (!ro_gui_button_bar_arrange_buttons(toolbar->buttons, order)) + return false; + + ro_toolbar_refresh_widget_dimensions(toolbar); + + return ro_toolbar_process(toolbar, -1, true); +} + + +/* This is an exported interface documented in toolbar.h */ + +void ro_toolbar_set_button_shaded_state(struct toolbar *toolbar, + button_bar_action action, bool shaded) +{ + if (toolbar == NULL && toolbar->buttons == NULL) + return; + + ro_gui_button_bar_shade_button(toolbar->buttons, action, shaded); +} + + +/* This is an exported interface documented in toolbar.h */ + +bool ro_toolbar_take_caret(struct toolbar *toolbar) +{ + if (toolbar == NULL || toolbar->url == NULL || !toolbar->url_display) + return false; + + return ro_gui_url_bar_take_caret(toolbar->url); +} + + +/* This is an exported interface documented in toolbar.h */ + +void ro_toolbar_set_url(struct toolbar *toolbar, const char *url, + bool is_utf8, bool set_caret) +{ + if (toolbar != NULL && toolbar->url != NULL) + ro_gui_url_bar_set_url(toolbar->url, url, is_utf8, set_caret); +} + + +/* This is an exported interface documented in toolbar.h */ + +const char *ro_toolbar_get_url(struct toolbar *toolbar) +{ + if (toolbar == NULL || toolbar->url == NULL) + return NULL; + + return ro_gui_url_bar_get_url(toolbar->url); +} + + +/* This is an exported interface documented in toolbar.h */ + +bool ro_toolbar_get_url_field_extent(struct toolbar *toolbar, os_box *extent) +{ + if (toolbar == NULL || toolbar->url == NULL) + return false; + + if (extent == NULL) + return true; + + return ro_gui_url_bar_get_url_extent(toolbar->url, extent); +} + + +/* This is an exported interface documented in toolbar.h */ + +void ro_toolbar_set_site_favicon(struct toolbar *toolbar, + struct hlcache_handle *h) +{ + if (toolbar == NULL || toolbar->url == NULL) + return; + + ro_gui_url_bar_set_site_favicon(toolbar->url, h); +} + + +/* This is an exported interface documented in toolbar.h */ + +void ro_toolbar_set_content_favicon(struct toolbar *toolbar, + struct hlcache_handle *h) +{ + if (toolbar == NULL || toolbar->url == NULL) + return; + + ro_gui_url_bar_set_content_favicon(toolbar->url, h); +} + + +/* This is an exported interface documented in toolbar.h */ + +void ro_toolbar_update_urlsuggest(struct toolbar *toolbar) +{ + if (toolbar != NULL && toolbar->url != NULL) + return; + + ro_gui_url_bar_update_urlsuggest(toolbar->url); +} + + +/* This is an exported interface documented in toolbar.h */ + +void ro_toolbar_set_display_buttons(struct toolbar *toolbar, bool display) +{ + if (toolbar == NULL || toolbar->buttons == NULL) + return; + + toolbar->buttons_display = display; + ro_gui_button_bar_hide(toolbar->buttons, !display); + ro_toolbar_refresh_widget_dimensions(toolbar); + ro_toolbar_refresh(toolbar); +} + + +/* This is an exported interface documented in toolbar.h */ + +void ro_toolbar_set_display_url(struct toolbar *toolbar, bool display) +{ + if (toolbar == NULL || toolbar->url == NULL) + return; + + toolbar->url_display = display; + ro_gui_url_bar_hide(toolbar->url, !display); + ro_toolbar_refresh_widget_dimensions(toolbar); + ro_toolbar_refresh(toolbar); +} + + +/* This is an exported interface documented in toolbar.h */ + +void ro_toolbar_set_display_throbber(struct toolbar *toolbar, bool display) +{ + if (toolbar == NULL || toolbar->throbber == NULL) + return; + + toolbar->throbber_display = display; + ro_gui_throbber_hide(toolbar->throbber, !display); + ro_toolbar_refresh_widget_dimensions(toolbar); + ro_toolbar_refresh(toolbar); +} + + +/* This is an exported interface documented in toolbar.h */ + +bool ro_toolbar_get_display_buttons(struct toolbar *toolbar) +{ + return (toolbar == NULL || toolbar->buttons == NULL) ? + false : toolbar->buttons_display; +} + + +/* This is an exported interface documented in toolbar.h */ + +bool ro_toolbar_get_display_url(struct toolbar *toolbar) +{ + return (toolbar == NULL || toolbar->url == NULL) ? + false : toolbar->url_display; +} + + +/* This is an exported interface documented in toolbar.h */ + +bool ro_toolbar_get_display_throbber(struct toolbar *toolbar) +{ + return (toolbar == NULL || toolbar->throbber == NULL) ? + false : toolbar->throbber_display; +} + + +/* This is an exported interface documented in toolbar.h */ + +bool ro_toolbar_get_editing(struct toolbar *toolbar) +{ + return (toolbar == NULL || !toolbar->editing) ? false : true; +} + + +/* This is an exported interface documented in toolbar.h */ + +bool ro_toolbar_toggle_edit(struct toolbar *toolbar) +{ + char *new_buttons; + + if (toolbar == NULL || toolbar->editor == NULL) + return false; + + toolbar->editing = !toolbar->editing; + + ro_gui_button_bar_hide(toolbar->editor, !toolbar->editing); + ro_gui_button_bar_hide(toolbar->buttons, + !toolbar->buttons_display && !toolbar->editing); + + if (!ro_toolbar_rebuild(toolbar)) { + ro_toolbar_destroy(toolbar); + return false; + } + + ro_toolbar_refresh(toolbar); + + /* If there's a callback registered and an edit has finished, + * tell out client what the new button state is. + */ + + if (!toolbar->editing && toolbar->buttons != NULL && + toolbar->callbacks != NULL && + toolbar->callbacks->save_buttons != NULL) { + new_buttons = ro_gui_button_bar_get_config(toolbar->buttons); + toolbar->callbacks->save_buttons(toolbar->client_data, + new_buttons); + } + + return true; +} + diff --git a/riscos/toolbar.h b/riscos/toolbar.h new file mode 100644 index 000000000..c2e22cf39 --- /dev/null +++ b/riscos/toolbar.h @@ -0,0 +1,525 @@ +/* + * Copyright 2005 Richard Wilson + * Copyright 2010, 2011 Stephen Fryatt + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** \file + * Window toolbars (interface). + */ + +#include +#include "riscos/theme.h" +#include "riscos/gui/button_bar.h" +#include "riscos/gui/throbber.h" +#include "riscos/gui/url_bar.h" + +#ifndef _NETSURF_RISCOS_TOOLBAR_H_ +#define _NETSURF_RISCOS_TOOLBAR_H_ + +typedef enum { + TOOLBAR_FLAGS_NONE = 0x00, + TOOLBAR_FLAGS_DISPLAY = 0x01, + TOOLBAR_FLAGS_EDIT = 0x02, +} toolbar_flags; + +/** + * Widget action types that the toolbar can pass on to clients. + */ + +typedef enum { + TOOLBAR_ACTION_NONE = 0, + TOOLBAR_ACTION_BUTTON, + TOOLBAR_ACTION_URL +} toolbar_action_type; + +/** + * Union to hold the different widget action data that can be passed + * from widget via toolbar to client. + */ + +union toolbar_action { + button_bar_action button; + url_bar_action url; +}; + +struct toolbar; + +struct toolbar_callbacks { + /** Call on theme update */ + void (*theme_update)(void *, bool); + + /** Call on bar size change */ + void (*change_size)(void *); + + /** Call to update button states */ + void (*update_buttons)(void *); + + /** Call to handle user actions */ + void (*user_action)(void *, toolbar_action_type, union toolbar_action); + + /** Call to handle keypresses. */ + void (*key_press)(void *, wimp_key *); + + /** Call on change to button order. */ + void (*save_buttons)(void *, char *); +}; + + +#define ro_toolbar_menu_option_shade(toolbar) \ + (((toolbar) == NULL) || ro_toolbar_get_editing(toolbar)) + +#define ro_toolbar_menu_buttons_tick(toolbar) \ + (ro_toolbar_get_display_buttons(toolbar) || \ + ro_toolbar_get_editing(toolbar)) + +#define ro_toolbar_menu_url_tick(toolbar) \ + (ro_toolbar_get_display_url(toolbar)) + +#define ro_toolbar_menu_throbber_tick(toolbar) \ + (ro_toolbar_get_display_throbber(toolbar)) + +#define ro_toolbar_menu_edit_shade(toolbar) ((toolbar) == NULL) + +#define ro_toolbar_menu_edit_tick(toolbar) (ro_toolbar_get_editing(toolbar)) + + +/* The new toolbar API */ + + +/** + * Initialise the RISC OS toolbar widget. + */ + +void ro_toolbar_init(void); + + +/** + * Create a new toolbar, ready to have widgets added and to be attached to + * a window. If a parent window is supplied, then the toolbar module will + * handle the window attachments; if NULL, it is up to the client to sort this + * out for itself. + * + * \param *descriptor The theme to apply, or NULL for the default. + * \param parent The window to attach the toolbar to, or NULL. + * \param style The theme style to apply. + * \param bar_flags Toolbar flags for the new bar. + * \param *callbacks A client callback block, or NULL for none. + * \param *client_data A data pointer to pass to callbacks, or NULL. + * \param *help The Help token prefix for interactive help. + * \return The handle of the new bar, or NULL on failure. + */ + +struct toolbar *ro_toolbar_create(struct theme_descriptor *descriptor, + wimp_w parent, theme_style style, toolbar_flags bar_flags, + const struct toolbar_callbacks *callbacks, void *client_data, + const char *help); + + +/** + * Add a button bar to a toolbar, and configure the buttons. + * + * \param *toolbar The toolbar to take the button bar. + * \param buttons[] The button definitions. + * \param *button_order The initial button order to use. + * \return true if the action completed; else false. + */ + +bool ro_toolbar_add_buttons(struct toolbar *toolbar, + const struct button_bar_buttons buttons[], char *button_order); + + +/** + * Add a throbber to a toolbar. + * + * \param *toolbar The toolbar to take the throbber. + * \return true if the action completed; else false. + */ + +bool ro_toolbar_add_throbber(struct toolbar *toolbar); + + +/** + * Add a URL bar to a toolbar. + * + * \param *toolbar The toolbar to take the URL bar. + * \return true if the action completed; else false. + */ + +bool ro_toolbar_add_url(struct toolbar *toolbar); + + +/** + * (Re-)build a toolbar to use the specified (or current) theme. If false + * is returned, the toolbar may not be complete and should be deleted. + * + * \param *toolbar The toolbar to rebuild. + * \return true if the action was successful; else false. + */ + +bool ro_toolbar_rebuild(struct toolbar *toolbar); + + +/** + * Attach or re-attach a toolbar to its parent window. + * + * \param *toolbar The toolbar to attach. + * \param parent The window to attach the toolbar to. + * \return true if the operation succeeded; else false. + */ + +bool ro_toolbar_attach(struct toolbar *toolbar, wimp_w parent); + + +/** + * Process a toolbar, updating its contents for a size or content change. + * + * \param *toolbar The toolbar to update. + * \param width The width to reformat to, or -1 to use parent. + * \param reformat true to force a widget reflow; else false. + * \return true if the operation succeeded; else false. + */ + +bool ro_toolbar_process(struct toolbar *toolbar, int width, bool reformat); + + +/** + * Destroy a toolbar after use. + * + * \param *toolbar The toolbar to destroy. + */ + +void ro_toolbar_destroy(struct toolbar *toolbar); + + +/** + * Change the client data associated with a toolbar's callbacks. + * + * \param *toolbar the toolbar whose data is to be updated. + * \param *client_data the new client data, or NULL for none. + */ + +void ro_toolbar_update_client_data(struct toolbar *toolbar, void *client_data); + + +/** + * Force the update of all toolbars buttons to reflect the current state. + */ + +void ro_toolbar_update_all_buttons(void); + + +/** + * Refresh a toolbar after it has been updated + * + * \param toolbar the toolbar to update + */ + +void ro_toolbar_refresh(struct toolbar *toolbar); + + +/** + * Force the update of all toolbars to reflect the application of a new theme. + */ + +void ro_toolbar_theme_update(void); + + +/** + * Find the toolbar associated with a given RO window handle. + * + * \param w the window handle to look up. + * \return the toolbar handle, or NULL if a match wasn't found. + */ + +struct toolbar *ro_toolbar_parent_window_lookup(wimp_w w); + + +/** + * Find the toolbar using a given RO window handle for its pane. + * + * \param w the window (pane) handle to look up. + * \return the toolbar handle, or NULL if a match wasn't found. + */ + +struct toolbar *ro_toolbar_window_lookup(wimp_w w); + + +/** + * Return the RO window handle of the parent window for a toolbar. + * + * \param *toolbar the toolbar to look up. + * \return the RO window handle of the parent. + */ + +wimp_w ro_toolbar_get_parent_window(struct toolbar *toolbar); + + +/** + * Return the RO window handle of a toolbar. + * + * \param *toolbar the toolbar to look up. + * \return the RO window handle of the bar. + */ + +wimp_w ro_toolbar_get_window(struct toolbar *toolbar); + + +/** + * Return the current height of a toolbar, allowing for available window + * space. + * + * \param *toolbar The toolbar of interest. + * \return The current toolbar height in OS units. + */ + +int ro_toolbar_height(struct toolbar *toolbar); + + +/** + * Return the full height that a toolbar could grow to, if space is available. + * + * \param *toolbar The toolbar of interest. + * \return The full toolbar height in OS units. + */ + +int ro_toolbar_full_height(struct toolbar *toolbar); + + +/** + * Starts a toolbar throbber, if there is one active. + * + * \param *toolbar the toolbar to start throbbing. + */ + +void ro_toolbar_start_throbbing(struct toolbar *toolbar); + + +/** + * Stops a toolbar throbber, if there is one active. + * + * \param *toolbar the toolbar to stop throbbing. + */ + +void ro_toolbar_stop_throbbing(struct toolbar *toolbar); + + +/** + * Animate a toolbar throbber, if there is one active. + * + * \param *toolbar the toolbar to throb. + */ + +void ro_toolbar_throb(struct toolbar *toolbar); + +/** + * Change the arrangement of buttons and spacers on a button bar within a + * toolbar. + * + * \param *toolbar The toolbar to change. + * \param order[] The new button configuration. + * \return true of the order was updated; else false. + */ + +bool ro_toolbar_set_button_order(struct toolbar *toolbar, char order[]); + + +/** + * Set the shaded state of a toolbar button. + * + * \param *toolbar the toolbar to update. + * \param action the button action to update. + * \param shaded true if the button should be shaded; else false. + */ + +void ro_toolbar_set_button_shaded_state(struct toolbar *toolbar, + button_bar_action action, bool shaded); + +/** + * Give a toolbar input focus, placing the caret into the URL bar if one is + * present. Currently a toolbar can only accept focus if it has a URL bar. + * + * \param *toolbar The toolbar to take the caret. + * \return true if the caret was taken; else false. + */ + +bool ro_toolbar_take_caret(struct toolbar *toolbar); + + +/** + * Set the content of a toolbar's URL field. + * + * \param *toolbar the toolbar to update. + * \param *url the new url to insert. + * \param is_utf8 true if the string is in utf8 encoding; false + * if it is in local encoding. + * \param set_caret true if the caret should be placed in the field; + * else false. + */ + +void ro_toolbar_set_url(struct toolbar *toolbar, const char *url, + bool is_utf8, bool set_caret); + + +/** + * Return a pointer to the URL contained in a browser toolbar. If the toolbar + * doesn't have a URL field, then NULL is returned instead. + * + * \param *toolbar The toolbar to look up the URL from. + * \return pointer to the URL, or NULL. + */ + +const char *ro_toolbar_get_url(struct toolbar *toolbar); + + +/** + * Return the current work area coordinates of the URL and favicon field's + * bounding box. + * + * \param *toolbar The toolbar to look up. + * \param *extent Return the coordinates. + * \return true if successful; else false. + */ + +bool ro_toolbar_get_url_field_extent(struct toolbar *toolbar, os_box *extent); + + +/** + * Update the favicon in a browser window toolbar to the supplied content, or + * revert to using filetype-based icons. + * + * \param *toolbar The toolbar to refresh. + * \param *h The new favicon to use, or NULL for none. + */ + +void ro_toolbar_set_site_favicon(struct toolbar *toolbar, + struct hlcache_handle *h); + + +/** + * Update the favicon in a browser window toolbar to reflect the RISC OS + * filetype of the supplied content. If the toolbar currently has a + * site favicon set, then this call will be ignored. + * + * \param *toolbar The toolbar to refresh. + * \param *h The page content to reflect. + */ + +void ro_toolbar_set_content_favicon(struct toolbar *toolbar, + struct hlcache_handle *h); + + +/** + * Update the state of the URL suggestion pop-up menu icon on a toolbar. + * + * \param *toolbar The toolbar to update. + */ + +void ro_toolbar_update_urlsuggest(struct toolbar *toolbar); + + +/** + * Set the display button bar state for a toolbar. + * + * \param *toolbar the toolbar to update. + * \param display true to display the button bar; else false. + */ + +void ro_toolbar_set_display_buttons(struct toolbar *toolbar, bool display); + + +/** + * Set the display URL bar state for a toolbar. + * + * \param *toolbar the toolbar to update. + * \param display true to display the URL bar; else false. + */ + +void ro_toolbar_set_display_url(struct toolbar *toolbar, bool display); + + +/** + * Set the display throbber state for a toolbar. + * + * \param *toolbar the toolbar to update. + * \param display true to display the throbber; else false. + */ + +void ro_toolbar_set_display_throbber(struct toolbar *toolbar, bool display); + + +/** + * Return true or false depending on whether the given toolbar is set to + * display the button bar. + * + * \param *toolbar the toolbar of interest. + * \return true if the toolbar exists and the button bar is + * shown; else false. + */ + +bool ro_toolbar_get_display_buttons(struct toolbar *toolbar); + + +/** + * Return true or false depending on whether the given toolbar is set to + * display the URL bar. + * + * \param *toolbar the toolbar of interest. + * \return true if the toolbar exists and the URL bar is + * shown; else false. + */ + +bool ro_toolbar_get_display_url(struct toolbar *toolbar); + + +/** + * Return true or false depending on whether the given toolbar is set to + * display the throbber. + * + * \param *toolbar the toolbar of interest. + * \return true if the toolbar exists and the throbber is + * shown; else false. + */ + +bool ro_toolbar_get_display_throbber(struct toolbar *toolbar); + + +/** + * Return true or false depending on whether the given toolbar is currently + * being edited. + * + * \param *toolbar the toolbar of interest. + * \return true if the toolbar exists and is beng edited; + * else false. + */ + +bool ro_toolbar_get_editing(struct toolbar *toolbar); + + +/** + * Toggle toolbar edit mode on the given toolbar. Only a button bar can be + * edited, so edit mode can only be toggled if there's an editor button + * bar defined. + * + * \param *toolbar The toolbar to be toggled. + * \return true if the action was successful; false if + * the action failed and the toolbar was destroyed. + */ + +bool ro_toolbar_toggle_edit(struct toolbar *toolbar); + +#endif + diff --git a/riscos/treeview.c b/riscos/treeview.c index afd636519..78bf9f0b4 100644 --- a/riscos/treeview.c +++ b/riscos/treeview.c @@ -46,7 +46,7 @@ #include "riscos/gui.h" #include "riscos/image.h" #include "riscos/menus.h" -#include "riscos/theme.h" +#include "riscos/toolbar.h" #include "riscos/tinct.h" #include "riscos/textarea.h" #include "riscos/treeview.h" @@ -87,6 +87,7 @@ struct ro_treeview int y; /*< Y coordinate of drag start */ } drag_start; tree_drag_type drag; /*< The current drag type for the tree */ + struct ro_treeview_callbacks *callbacks; /*< Callback handlers */ }; static void ro_treeview_redraw_request(int x, int y, int width, int height, @@ -109,6 +110,13 @@ static bool ro_treeview_keypress(wimp_key *key); static void ro_treeview_set_window_extent(ro_treeview *tv, int width, int height); +static void ro_treeview_update_theme(void *data, bool ok); +static void ro_treeview_update_toolbar(void *data); +static void ro_treeview_button_update(void *data); +static void ro_treeview_save_toolbar_buttons(void *data, char *config); +static void ro_treeview_button_click(void *data, + toolbar_action_type action_type, union toolbar_action action); + static const struct treeview_table ro_tree_callbacks = { ro_treeview_redraw_request, ro_treeview_resized, @@ -116,18 +124,29 @@ static const struct treeview_table ro_tree_callbacks = { ro_treeview_get_window_dimensions }; +static const struct toolbar_callbacks ro_treeview_toolbar_callbacks = { + ro_treeview_update_theme, + ro_treeview_update_toolbar, + ro_treeview_button_update, + ro_treeview_button_click, + NULL, /* No toolbar keypress handler */ + ro_treeview_save_toolbar_buttons +}; + + /** * Create a RISC OS GUI implementation of a treeview tree. * * \param window The window to create the tree in. * \param *toolbar A toolbar to attach to the window. + * \param *callbacks Callbacks to service the treeview. * \param flags The treeview flags. * * \return The RISC OS treeview pointer. */ ro_treeview *ro_treeview_create(wimp_w window, struct toolbar *toolbar, - unsigned int flags) + struct ro_treeview_callbacks *callbacks, unsigned int flags) { ro_treeview *tv; @@ -166,6 +185,10 @@ ro_treeview *ro_treeview_create(wimp_w window, struct toolbar *toolbar, tv->drag = TREE_NO_DRAG; + /* Record the callback info. */ + + tv->callbacks = callbacks; + /* Register wimp events to handle the supplied window. */ ro_gui_wimp_event_register_redraw_window(tv->w, ro_treeview_redraw); @@ -193,6 +216,18 @@ void ro_treeview_destroy(ro_treeview *tv) free(tv); } +/** + * Return a pointer to a toolbar callbacks structure with the handlers to be + * used by any treeview window toolbars. + * + * \return A pointer to the callback structure. + */ + +const struct toolbar_callbacks *ro_treeview_get_toolbar_callbacks(void) +{ + return &ro_treeview_toolbar_callbacks; +} + /** * Change the redraw origin of a treeview tree in RISC OS graphics units. * @@ -702,7 +737,7 @@ static void ro_treeview_open(wimp_open *open) } if (tv->tb) - ro_gui_theme_process_toolbar(tv->tb, -1); + ro_toolbar_process(tv->tb, -1, false); } @@ -786,10 +821,16 @@ static bool ro_treeview_mouse_click(wimp_pointer *pointer) if (tv->drag == TREE_SELECT_DRAG || tv->drag == TREE_MOVE_DRAG) ro_treeview_drag_start(tv, pointer, &state); + + + if (tv->callbacks != NULL && + tv->callbacks->toolbar_button_update != NULL) + tv->callbacks->toolbar_button_update(); } /* We assume that the owning module will have attached a window menu - * to our parent window. If it hasn't, this call will quietly fail. + * to our parent window with the auto flag unset (so that we can fudge + * the selection above). If it hasn't, this call will quietly fail. */ if (pointer->buttons == wimp_CLICK_MENU) @@ -860,6 +901,10 @@ void ro_treeview_mouse_at(wimp_pointer *pointer) tv->drag_start.y, xpos, ypos); tv->drag = TREE_NO_DRAG; } + + if (tv->callbacks != NULL && + tv->callbacks->toolbar_button_update != NULL) + tv->callbacks->toolbar_button_update(); } @@ -884,7 +929,7 @@ static void ro_treeview_drag_start(ro_treeview *tv, wimp_pointer *pointer, drag.bbox.y0 = state->visible.y0; drag.bbox.x1 = state->visible.x1; drag.bbox.y1 = state->visible.y1 - - ro_gui_theme_toolbar_height(tv->tb); + ro_toolbar_height(tv->tb); switch (tv->drag) { case TREE_SELECT_DRAG: @@ -922,7 +967,7 @@ static void ro_treeview_drag_start(ro_treeview *tv, wimp_pointer *pointer, auto_scroll.pause_zone_sizes.y0 = 80; auto_scroll.pause_zone_sizes.x1 = 80; auto_scroll.pause_zone_sizes.y1 = 80 + - ro_gui_theme_toolbar_height(tv->tb); + ro_toolbar_height(tv->tb); auto_scroll.pause_duration = 0; auto_scroll.state_change = (void *) 1; @@ -1038,8 +1083,14 @@ static bool ro_treeview_keypress(wimp_key *key) } if (!(c & IS_WIMP_KEY)) { - if (tree_keypress(tv->tree, c)) + if (tree_keypress(tv->tree, c)) { + if (tv->callbacks && + tv->callbacks->toolbar_button_update + != NULL) + tv->callbacks->toolbar_button_update(); + return true; + } } return false; @@ -1049,23 +1100,20 @@ static bool ro_treeview_keypress(wimp_key *key) /** * Update a treeview to use a new theme. * - * \param *tv Pointer to the treeview to update. + * \param *data Pointer to the treeview to update. + * \param ok true if the bar still exists; else false. */ -void ro_treeview_update_theme(ro_treeview *tv) +void ro_treeview_update_theme(void *data, bool ok) { - if (tv != NULL && tv->tb != NULL){ - /* \todo -- Check for toolbar editing here. */ + ro_treeview *tv = (ro_treeview *) data; - if (!ro_gui_theme_update_toolbar(NULL, tv->tb)) { - ro_gui_theme_destroy_toolbar(tv->tb); + if (tv != NULL && tv->tb != NULL){ + if (ok) { + ro_treeview_update_toolbar(tv); + } else { tv->tb = NULL; } - - /* \todo -- Check for toolbar editing here. */ - - ro_gui_theme_attach_toolbar(tv->tb, tv->w); - ro_treeview_update_toolbar(tv); } } @@ -1073,33 +1121,86 @@ void ro_treeview_update_theme(ro_treeview *tv) /** * Change the size of a treeview's toolbar and redraw the window. * - * \param *tv The treeview to update. + * \param *data The treeview to update. */ -void ro_treeview_update_toolbar(ro_treeview *tv) +void ro_treeview_update_toolbar(void *data) { + ro_treeview *tv = (ro_treeview *) data; + + if (tv != NULL && tv->tb != NULL) { ro_treeview_set_origin(tv, 0, - -(ro_gui_theme_toolbar_height(tv->tb))); + -(ro_toolbar_height(tv->tb))); xwimp_force_redraw(tv->w, 0, tv->extent.y, tv->extent.x, 0); + } +} + + +/** + * Update the toolbar icons in a treeview window's toolbar. As we're just + * an intermediate widget, we pass the details on down the chain. + * + * \param *data The treeview owning the toolbar. + */ +void ro_treeview_button_update(void *data) +{ + ro_treeview *tv = (ro_treeview *) data; + + if (tv == NULL || tv->callbacks == NULL) + return; + + if (tv->callbacks->toolbar_button_update != NULL) + tv->callbacks->toolbar_button_update(); +} + + +/** + * Save a new button configuration from a treeview window's toolbar. As + * we're just an intermediate widget, we pass the details on. + * + * \param *data The treeview owning the toolbar. + * \param *config The new button config string. + */ + +void ro_treeview_save_toolbar_buttons(void *data, char *config) +{ + ro_treeview *tv = (ro_treeview *) data; + + if (tv == NULL || tv->callbacks == NULL) + return; + + if (tv->callbacks->toolbar_button_save != NULL) + tv->callbacks->toolbar_button_save(config); +} + + +/** + * Process clicks on buttons in a treeview window's toolbar. As we're just + * an intermediate widget, we just pass the details on down the chain. + * + * \param *data The treeview owning the click. + * \param action_type The action type to be handled. + * \param action The action to handle. + */ + +void ro_treeview_button_click(void *data, + toolbar_action_type action_type, union toolbar_action action) +{ + ro_treeview *tv = (ro_treeview *) data; + + if (tv == NULL || tv->callbacks == NULL || + action_type != TOOLBAR_ACTION_BUTTON) + return; + + if (tv->callbacks->toolbar_button_click != NULL) + tv->callbacks->toolbar_button_click(action.button); + + if (tv->callbacks->toolbar_button_update != NULL) + tv->callbacks->toolbar_button_update(); } -#if 0 - if ((tree) && (tree->toolbar)) { - if (tree->toolbar->editor) - if (!ro_gui_theme_update_toolbar(NULL, tree->toolbar->editor)) - tree->toolbar->editor = NULL; - if (!ro_gui_theme_update_toolbar(NULL, tree->toolbar)) { - ro_gui_theme_destroy_toolbar(tree->toolbar); - tree->toolbar = NULL; - } - ro_gui_theme_toolbar_editor_sync(tree->toolbar); - ro_gui_theme_attach_toolbar(tree->toolbar, (wimp_w)tree->handle); - tree_resized(tree); - xwimp_force_redraw((wimp_w)tree->handle, 0, -16384, 16384, 16384); - } -#endif /** * Return a token identifying the interactive help message for a given cursor diff --git a/riscos/treeview.h b/riscos/treeview.h index 7f4da9074..54919522b 100644 --- a/riscos/treeview.h +++ b/riscos/treeview.h @@ -29,6 +29,7 @@ #include #include "desktop/tree.h" +#include "riscos/toolbar.h" /* defined in front end code */ extern const char tree_directory_icon_name[]; @@ -36,13 +37,16 @@ extern const char tree_content_icon_name[]; typedef struct ro_treeview ro_treeview; -struct ro_treeview_table { - void (*open_menu)(wimp_pointer *pointer); +struct ro_treeview_callbacks { + void (*toolbar_button_click)(button_bar_action action); + void (*toolbar_button_update)(void); + void (*toolbar_button_save)(char *); }; ro_treeview *ro_treeview_create(wimp_w window, struct toolbar *toolbar, - unsigned int flags); + struct ro_treeview_callbacks *callbacks, unsigned int flags); void ro_treeview_destroy(ro_treeview *tv); +const struct toolbar_callbacks *ro_treeview_get_toolbar_callbacks(void); struct tree *ro_treeview_get_tree(ro_treeview *tv); wimp_w ro_treeview_get_window(ro_treeview *tv); @@ -51,8 +55,6 @@ bool ro_treeview_has_selection(ro_treeview *tv); void ro_treeview_set_origin(ro_treeview *tv, int x, int y); void ro_treeview_mouse_at(wimp_pointer *pointer); void ro_treeview_drag_end(wimp_dragged *drag); -void ro_treeview_update_theme(ro_treeview *tv); -void ro_treeview_update_toolbar(ro_treeview *tv); int ro_treeview_get_help(help_full_message_request *message_data); #endif diff --git a/riscos/uri.c b/riscos/uri.c index 44cac853b..0a2dcbbd1 100644 --- a/riscos/uri.c +++ b/riscos/uri.c @@ -27,7 +27,6 @@ #include "utils/config.h" #include "content/fetch.h" #include "desktop/browser.h" -#include "riscos/theme.h" #include "desktop/gui.h" #include "riscos/gui.h" #include "riscos/uri.h" diff --git a/riscos/url_complete.c b/riscos/url_complete.c index 9649c5604..98820b7a3 100644 --- a/riscos/url_complete.c +++ b/riscos/url_complete.c @@ -31,7 +31,7 @@ #include "riscos/global_history.h" #include "riscos/gui.h" #include "riscos/options.h" -#include "riscos/theme.h" +#include "riscos/toolbar.h" #include "riscos/url_complete.h" #include "riscos/wimp.h" #include "riscos/wimp_event.h" @@ -62,59 +62,59 @@ static int mouse_y; static bool url_complete_callback(const char *url, const struct url_data *data); -/** - * Should be called when the caret is placed into a URL completion icon. - * - * \param g the gui_window to initialise URL completion for - */ -void ro_gui_url_complete_start(struct gui_window *g) + +/* This is an exported interface documented in url_complete.h */ + +void ro_gui_url_complete_start(struct toolbar *toolbar) { - const char *url; + const char *url; + wimp_w parent; + + assert(toolbar != NULL); + parent = ro_toolbar_get_parent_window(toolbar); - if ((!g->toolbar) || (!g->toolbar->display_url) || - (g->window == url_complete_parent)) + if (!ro_toolbar_get_display_url(toolbar) || + (parent == url_complete_parent)) return; - ro_gui_url_complete_close(NULL, 0); - url = ro_gui_get_icon_string(g->toolbar->toolbar_handle, - ICON_TOOLBAR_URL); + ro_gui_url_complete_close(); + url = ro_toolbar_get_url(toolbar); url_complete_matched_string = strdup(url); if (url_complete_matched_string) - url_complete_parent = g->window; + url_complete_parent = parent; } -/** - * Handles a keypress for URL completion - * - * \param g the gui_window to update - * \param key the key pressed (as UTF32 code or wimp key + bit31 set) - * \return true to indicate keypress handled, false otherwise - */ -bool ro_gui_url_complete_keypress(struct gui_window *g, uint32_t key) +/* This is an exported interface documented in url_complete.h */ + +bool ro_gui_url_complete_keypress(struct toolbar *toolbar, uint32_t key) { - wimp_window_state state; - char *match_url; - const char *url; - int i, lines; - int old_selection; - int height; - os_error *error; - bool currently_open; + wimp_w parent; + wimp_window_state state; + char *match_url; + const char *url; + int i, lines; + int old_selection; + int height; + os_error *error; + bool currently_open; + + assert(toolbar != NULL); + parent = ro_toolbar_get_parent_window(toolbar); /* we must have a toolbar/url bar */ - if ((!g->toolbar) || (!g->toolbar->display_url) || + if (!ro_toolbar_get_display_url(toolbar) || (!option_url_suggestion)) { - ro_gui_url_complete_close(NULL, 0); + ro_gui_url_complete_close(); return false; } /* if we are currently active elsewhere, remove the previous window */ - currently_open = ((g->window == url_complete_parent) && + currently_open = ((parent == url_complete_parent) && (url_complete_matches_available > 0)); - if (g->window != url_complete_parent) - ro_gui_url_complete_close(NULL, 0); + if (parent != url_complete_parent) + ro_gui_url_complete_close(); /* forcibly open on down keys */ if ((!currently_open) && (url_complete_matched_string)) { @@ -129,12 +129,11 @@ bool ro_gui_url_complete_keypress(struct gui_window *g, uint32_t key) /* get the text to match */ - url_complete_parent = g->window; - url = ro_gui_get_icon_string(g->toolbar->toolbar_handle, - ICON_TOOLBAR_URL); - match_url = strdup(url); - if (!match_url) { - ro_gui_url_complete_close(NULL, 0); + url_complete_parent = parent; + url = ro_toolbar_get_url(toolbar); + match_url = (url != NULL) ? strdup(url) : NULL; + if (match_url == NULL) { + ro_gui_url_complete_close(); return false; } @@ -181,7 +180,7 @@ bool ro_gui_url_complete_keypress(struct gui_window *g, uint32_t key) if (!url_complete_matches) { url_complete_matches = malloc(64 * sizeof(char *)); if (!url_complete_matches) { - ro_gui_url_complete_close(NULL, 0); + ro_gui_url_complete_close(); return false; } url_complete_matches_allocated = 64; @@ -195,12 +194,12 @@ bool ro_gui_url_complete_keypress(struct gui_window *g, uint32_t key) urldb_iterate_partial(match_url, url_complete_callback); if ((url_complete_memory_exhausted) || (url_complete_matches_available == 0)) { - ro_gui_url_complete_close(NULL, 0); + ro_gui_url_complete_close(); return false; } /* update the window */ - state.w = g->window; + state.w = parent; error = xwimp_get_window_state(&state); if (error) { LOG(("xwimp_get_window_state: 0x%x: %s", @@ -209,7 +208,7 @@ bool ro_gui_url_complete_keypress(struct gui_window *g, uint32_t key) return false; } url_complete_matches_reset = true; - ro_gui_url_complete_resize(g, PTR_WIMP_OPEN(&state)); + ro_gui_url_complete_resize(toolbar, PTR_WIMP_OPEN(&state)); url_complete_matches_reset = false; /* redraw the relevant bits of the window */ @@ -300,14 +299,13 @@ bool ro_gui_url_complete_keypress(struct gui_window *g, uint32_t key) } if (url_complete_matches_selection == -1) { - ro_gui_set_icon_string(g->toolbar->toolbar_handle, - ICON_TOOLBAR_URL, - url_complete_original_url, true); + ro_toolbar_set_url(toolbar, + url_complete_original_url, true, false); } else { - ro_gui_set_icon_string(g->toolbar->toolbar_handle, - ICON_TOOLBAR_URL, + ro_toolbar_set_url(toolbar, url_complete_matches[ - url_complete_matches_selection], true); + url_complete_matches_selection], + true, false); free(url_complete_matched_string); url_complete_matched_string = strdup(url_complete_matches[ url_complete_matches_selection]); @@ -343,6 +341,7 @@ bool ro_gui_url_complete_keypress(struct gui_window *g, uint32_t key) return true; } + /** * Callback function for urldb_iterate_partial * @@ -350,6 +349,7 @@ bool ro_gui_url_complete_keypress(struct gui_window *g, uint32_t key) * \param data Data associated with URL * \return true to continue iteration, false otherwise */ + bool url_complete_callback(const char *url, const struct url_data *data) { const char **array_extend; @@ -379,21 +379,18 @@ bool url_complete_callback(const char *url, const struct url_data *data) return true; } -/** - * Move and resize the url completion window to match the toolbar. - * - * \param g the gui_window to update - * \param open the wimp_open request (updated on exit) - */ -void ro_gui_url_complete_resize(struct gui_window *g, wimp_open *open) + +/* This is an exported interface documented in url_complete.h */ + +void ro_gui_url_complete_resize(struct toolbar *toolbar, wimp_open *open) { - os_box extent = { 0, 0, 0, 0 }; - wimp_icon_state url_state; - wimp_window_state toolbar_state; - wimp_window_state state; - os_error *error; - int lines; - int scroll_v = 0; + os_box extent = { 0, 0, 0, 0 }; + os_box url_extent; + wimp_window_state toolbar_state; + wimp_window_state state; + os_error *error; + int lines; + int scroll_v = 0; /* only react to our window */ if (open->w != url_complete_parent) @@ -401,10 +398,10 @@ void ro_gui_url_complete_resize(struct gui_window *g, wimp_open *open) /* if there is no toolbar, or there is no URL bar shown, * or there are no URL matches, close it */ - if ((!g->toolbar) || (!g->toolbar->display_url) || + if (!ro_toolbar_get_display_url(toolbar) || (!url_complete_matches) || (url_complete_matches_available == 0)) { - ro_gui_url_complete_close(NULL, 0); + ro_gui_url_complete_close(); return; } @@ -422,7 +419,7 @@ void ro_gui_url_complete_resize(struct gui_window *g, wimp_open *open) state.yscroll = 0; /* move the window to the correct position */ - toolbar_state.w = g->toolbar->toolbar_handle; + toolbar_state.w = ro_toolbar_get_window(toolbar); error = xwimp_get_window_state(&toolbar_state); if (error) { LOG(("xwimp_get_window_state: 0x%x: %s", @@ -431,13 +428,8 @@ void ro_gui_url_complete_resize(struct gui_window *g, wimp_open *open) return; } - url_state.w = g->toolbar->toolbar_handle; - url_state.i = ICON_TOOLBAR_SURROUND; - error = xwimp_get_icon_state(&url_state); - if (error) { - LOG(("xwimp_get_window_state: 0x%x: %s", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); + if (!ro_toolbar_get_url_field_extent(toolbar, &url_extent)) { + LOG(("Failed to read URL field extent.")); return; } @@ -460,10 +452,9 @@ void ro_gui_url_complete_resize(struct gui_window *g, wimp_open *open) scroll_v = ro_get_vscroll_width(NULL) - 2; state.flags |= wimp_WINDOW_VSCROLL; } - state.visible.x0 = open->visible.x0 + 2 + url_state.icon.extent.x0; - state.visible.x1 = open->visible.x0 - 2 + - url_state.icon.extent.x1 - scroll_v; - state.visible.y1 = open->visible.y1 - url_state.icon.extent.y1 + 2; + state.visible.x0 = open->visible.x0 + 2 + url_extent.x0; + state.visible.x1 = open->visible.x0 - 2 + url_extent.x1 - scroll_v; + state.visible.y1 = open->visible.y1 - url_extent.y1 + 2; state.visible.y0 = state.visible.y1 - (lines * 44); if (state.visible.x1 + scroll_v > toolbar_state.visible.x1) state.visible.x1 = toolbar_state.visible.x1 - scroll_v; @@ -488,23 +479,21 @@ void ro_gui_url_complete_resize(struct gui_window *g, wimp_open *open) } -/** - * Try to close the current url completion window - * - * \param g the gui_window the user clicked on (or NULL to forcibly close) - * \param i the icon the user clicked on to prompt the close - * \return whether the window was closed - */ -bool ro_gui_url_complete_close(struct gui_window *g, wimp_i i) +/* This is an exported interface documented in url_complete.h */ + +bool ro_gui_url_complete_close(void) { - os_error *error; - bool currently_open; + os_error *error; + bool currently_open; - if ((g && (i == ICON_TOOLBAR_URL) && - (g->window == url_complete_parent))) - return false; + /* There used to be a check here to see if the icon clicked was the + * URL text field in the toolbar. Since this only applied to clicks + * originating from the toolbar module following the restructuring, + * and this check was better done within the toolbar, it has been + * removed from this function and the associated parameters removed. + */ - currently_open = ((url_complete_parent) && + currently_open = ((url_complete_parent != NULL) && (url_complete_matches_available > 0)); free(url_complete_matches); @@ -530,11 +519,8 @@ bool ro_gui_url_complete_close(struct gui_window *g, wimp_i i) } -/** - * Redraws a section of the URL completion window - * - * \param redraw the area to redraw - */ +/* This is an exported interface documented in url_complete.h */ + void ro_gui_url_complete_redraw(wimp_draw *redraw) { osbool more; @@ -633,11 +619,8 @@ void ro_gui_url_complete_redraw(wimp_draw *redraw) } -/** - * Handle mouse movement over the URL completion window. - * - * \param pointer the pointer state - */ +/* This is an exported interface documented in url_complete.h */ + void ro_gui_url_complete_mouse_at(wimp_pointer *pointer) { wimp_mouse_state current; @@ -649,12 +632,8 @@ void ro_gui_url_complete_mouse_at(wimp_pointer *pointer) } -/** - * Handle mouse clicks in the URL completion window. - * - * \param pointer the pointer state - * \return whether the click was handled - */ +/* This is an exported interface documented in url_complete.h */ + bool ro_gui_url_complete_click(wimp_pointer *pointer) { wimp_window_state state; @@ -685,9 +664,7 @@ bool ro_gui_url_complete_click(wimp_pointer *pointer) g = ro_gui_window_lookup(url_complete_parent); if (!g) return false; - url = ro_gui_get_icon_string( - g->toolbar->toolbar_handle, - ICON_TOOLBAR_URL); + url = ro_toolbar_get_url(g->toolbar); free(url_complete_original_url); url_complete_original_url = strdup(url); if (!url_complete_original_url) @@ -722,10 +699,10 @@ bool ro_gui_url_complete_click(wimp_pointer *pointer) /* Select sets the text and launches */ if (pointer->buttons == wimp_CLICK_SELECT) { - ro_gui_set_icon_string(g->toolbar->toolbar_handle, - ICON_TOOLBAR_URL, + ro_toolbar_set_url(g->toolbar, url_complete_matches[ - url_complete_matches_selection], true); + url_complete_matches_selection], + true, false); /** \todo The interaction of components here is hideous */ /* Do NOT make any attempt to use any of the global url @@ -740,15 +717,16 @@ bool ro_gui_url_complete_click(wimp_pointer *pointer) url_complete_matches[ url_complete_matches_selection], 0, true); - ro_gui_url_complete_close(NULL, 0); + ro_gui_url_complete_close(); /* Adjust just sets the text */ } else if (pointer->buttons == wimp_CLICK_ADJUST) { - ro_gui_set_icon_string(g->toolbar->toolbar_handle, - ICON_TOOLBAR_URL, + ro_toolbar_set_url(g->toolbar, url_complete_matches[ - url_complete_matches_selection], true); - ro_gui_url_complete_keypress(g, 0); + url_complete_matches_selection], + true, false); + ro_gui_url_complete_keypress(g->toolbar, 0); } return true; } + diff --git a/riscos/url_complete.h b/riscos/url_complete.h index 299135791..12f640086 100644 --- a/riscos/url_complete.h +++ b/riscos/url_complete.h @@ -29,12 +29,72 @@ struct gui_window; -void ro_gui_url_complete_start(struct gui_window *g); -bool ro_gui_url_complete_keypress(struct gui_window *g, uint32_t key); -void ro_gui_url_complete_resize(struct gui_window *g, wimp_open *open); -bool ro_gui_url_complete_close(struct gui_window *g, wimp_i i); +/** + * Should be called when the caret is placed into a URL completion icon. + * + * \param *toolbar The toolbar to initialise URL completion for. + */ + +void ro_gui_url_complete_start(struct toolbar *toolbar); + + +/** + * Handles a keypress for URL completion + * + * \param *toolbar The toolbar to be updated. + * \param key the key pressed (as UTF32 code or + * wimp key + bit31 set) + * \return true to indicate keypress handled; else false. + */ + +bool ro_gui_url_complete_keypress(struct toolbar *toolbar, uint32_t key); + + +/** + * Move and resize the url completion window to match the toolbar. + * + * \param *toolbar The toolbar to update + * \param *open the wimp_open request (updated on exit) + */ + +void ro_gui_url_complete_resize(struct toolbar *toolbar, wimp_open *open); + + +/** + * Try to close the current url completion window + * + * \return whether the window was closed + */ + +bool ro_gui_url_complete_close(void); + + +/** + * Redraws a section of the URL completion window + * + * \param redraw the area to redraw + */ + void ro_gui_url_complete_redraw(wimp_draw *redraw); + + +/** + * Handle mouse movement over the URL completion window. + * + * \param pointer the pointer state + */ + void ro_gui_url_complete_mouse_at(wimp_pointer *pointer); + + +/** + * Handle mouse clicks in the URL completion window. + * + * \param pointer the pointer state + * \return whether the click was handled + */ + bool ro_gui_url_complete_click(wimp_pointer *pointer); #endif + diff --git a/riscos/url_suggest.c b/riscos/url_suggest.c index 82ca5520c..be766e1bd 100644 --- a/riscos/url_suggest.c +++ b/riscos/url_suggest.c @@ -34,28 +34,29 @@ struct url_suggest_item { struct url_suggest_item *next; /*< The next URL in the list. */ }; -static bool url_suggest_callback(const char *url, const struct url_data *data); +static bool ro_gui_url_suggest_callback(const char *url, + const struct url_data *data); -static wimp_menu *suggest_menu; static int suggest_entries; static time_t suggest_time; static struct url_suggest_item *suggest_list; +static wimp_MENU(URL_SUGGEST_MAX_URLS) url_suggest_menu_block; +wimp_menu *ro_gui_url_suggest_menu = (wimp_menu *) &url_suggest_menu_block; + + /** - * Initialise the URL suggestion menu. A menu block which must be set to - * contain URL_SUGGEST_MAX_URLS entries is passed in. + * Initialise the URL suggestion menu. This MUST be called before anything + * tries to use the URL menu. * - * /param *menu The menu to use as the suggestion menu. * /return true if initialisation was OK; else false. */ -bool ro_gui_url_suggest_init(wimp_menu *menu) +bool ro_gui_url_suggest_init(void) { - suggest_menu = menu; - - suggest_menu->title_data.indirected_text.text = + ro_gui_url_suggest_menu->title_data.indirected_text.text = (char *) messages_get("URLSuggest"); - ro_gui_menu_init_structure((wimp_menu *) suggest_menu, + ro_gui_menu_init_structure((wimp_menu *) ro_gui_url_suggest_menu, URL_SUGGEST_MAX_URLS); suggest_entries = 0; @@ -64,6 +65,21 @@ bool ro_gui_url_suggest_init(wimp_menu *menu) } +/** + * Check if there is a URL suggestion menu available for use. + * + * \TODO -- Ideally this should be able to decide if there's a menu + * available without actually having to build it all. + * + * /return true if the menu has entries; else false. + */ + +bool ro_gui_url_suggest_get_menu_available(void) +{ + return ro_gui_url_suggest_prepare_menu(); +} + + /** * Builds the URL suggestion menu. This is called by ro_gui_menu_create() when * it is asked to display the url_suggest_menu. @@ -82,7 +98,7 @@ bool ro_gui_url_suggest_prepare_menu(void) suggest_list = NULL; suggest_time = time(NULL); - urldb_iterate_entries(url_suggest_callback); + urldb_iterate_entries(ro_gui_url_suggest_callback); /* If any menu entries were found, put them into the menu. The list * is in reverse order, last to first, so the menu is filled backwards. @@ -100,10 +116,12 @@ bool ro_gui_url_suggest_prepare_menu(void) while (list != NULL && i > 0) { i--; - suggest_menu->entries[i].menu_flags = 0; - suggest_menu->entries[i].data.indirected_text.text = + ro_gui_url_suggest_menu->entries[i].menu_flags = 0; + ro_gui_url_suggest_menu-> + entries[i].data.indirected_text.text = (char *) list->url; - suggest_menu->entries[i].data.indirected_text.size = + ro_gui_url_suggest_menu-> + entries[i].data.indirected_text.size = strlen(list->url) + 1; next = list->next; @@ -113,9 +131,10 @@ bool ro_gui_url_suggest_prepare_menu(void) assert(i == 0); - suggest_menu->entries[0].menu_flags |= + ro_gui_url_suggest_menu->entries[0].menu_flags |= wimp_MENU_TITLE_INDIRECTED; - suggest_menu->entries[suggest_entries - 1].menu_flags |= + ro_gui_url_suggest_menu-> + entries[suggest_entries - 1].menu_flags |= wimp_MENU_LAST; return true; @@ -133,7 +152,7 @@ bool ro_gui_url_suggest_prepare_menu(void) * \return true to continue iteration, false otherwise */ -bool url_suggest_callback(const char *url, const struct url_data *data) +bool ro_gui_url_suggest_callback(const char *url, const struct url_data *data) { int count; unsigned int weight; @@ -193,3 +212,21 @@ bool url_suggest_callback(const char *url, const struct url_data *data) return true; } + +/** + * Process a selection from the URL Suggest menu. + * + * \param *selection The menu selection. + * \return Pointer to the URL that was selected, or NULL for none. + */ + +const char *ro_gui_url_suggest_get_selection(wimp_selection *selection) +{ + const char *url = NULL; + + if (selection->items[0] >= 0) + url = ro_gui_url_suggest_menu->entries[selection->items[0]]. + data.indirected_text.text; + + return url; +} diff --git a/riscos/url_suggest.h b/riscos/url_suggest.h index d13b7d89a..738cb9bf7 100644 --- a/riscos/url_suggest.h +++ b/riscos/url_suggest.h @@ -27,8 +27,12 @@ #define URL_SUGGEST_MAX_URLS 16 -bool ro_gui_url_suggest_init(wimp_menu *menu); +extern wimp_menu *ro_gui_url_suggest_menu; + +bool ro_gui_url_suggest_init(void); +bool ro_gui_url_suggest_get_menu_available(void); bool ro_gui_url_suggest_prepare_menu(void); +const char *ro_gui_url_suggest_get_selection(wimp_selection *selection); #endif diff --git a/riscos/wimp.c b/riscos/wimp.c index 71443afb4..6043b6791 100644 --- a/riscos/wimp.c +++ b/riscos/wimp.c @@ -36,7 +36,6 @@ #include "desktop/gui.h" #include "riscos/gui.h" #include "riscos/oslib_pre7.h" -#include "riscos/theme.h" #include "riscos/wimp.h" #include "utils/log.h" #include "utils/utf8.h" @@ -545,6 +544,71 @@ bool ro_gui_get_icon_shaded_state(wimp_w w, wimp_i i) } +/** + * Set the deleted state of an icon. + * + * \param w window handle + * \param i icon handle + * \param state shaded state + */ +void ro_gui_set_icon_deleted_state(wimp_w w, wimp_i i, bool state) +{ + wimp_caret caret; + os_error *error; + + /* update the state */ + if (ro_gui_get_icon_deleted_state(w, i) == state) + return; + error = xwimp_set_icon_state(w, i, + (state ? wimp_ICON_DELETED : 0), wimp_ICON_DELETED); + if (error) { + LOG(("xwimp_get_icon_state: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + } + if (!state) + return; + + /* ensure the caret is not in a shaded icon */ + error = xwimp_get_caret_position(&caret); + if (error) { + LOG(("xwimp_get_caret_position: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return; + } + if ((caret.w != w) || (caret.i != i)) + return; + /* move the caret to the first avaiable writable */ + if (ro_gui_set_caret_first(w)) + return; + /* lose the caret */ + error = xwimp_set_caret_position((wimp_w)-1, (wimp_i)-1, -1, -1, -1, -1); + if (error) { + LOG(("xwimp_set_caret_position: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return; + } +} + + +/** + * Gets the deleted state of an icon. + * + * \param w window handle + * \param i icon handle + */ +bool ro_gui_get_icon_deleted_state(wimp_w w, wimp_i i) +{ + wimp_icon_state ic; + ic.w = w; + ic.i = i; + xwimp_get_icon_state(&ic); + return (ic.icon.flags & wimp_ICON_DELETED) != 0; +} + + /** * Set the button type of an icon. * @@ -840,6 +904,52 @@ os_error *ro_gui_wimp_get_sprite(const char *name, osspriteop_header **sprite) } +/** + * Get the dimensions of a sprite + * + * \param *area The sprite area to use. + * \param *sprite Pointer to the sprite name. + * \param *width Return the sprite width. + * \param *height Return the sprite height. + * \return true if successful; else false. + */ + +bool ro_gui_wimp_get_sprite_dimensions(osspriteop_area *area, char *sprite, + int *width, int *height) +{ + os_error *error = NULL; + os_mode mode; + os_coord dimensions; + + dimensions.x = 0; + dimensions.y = 0; + + if (area != (osspriteop_area *) -1) + error = xosspriteop_read_sprite_info(osspriteop_USER_AREA, + area, (osspriteop_id) sprite, + &dimensions.x, &dimensions.y, 0, &mode); + + if (error != NULL || area == (osspriteop_area *) -1) + error = xwimpspriteop_read_sprite_info(sprite, + &dimensions.x, &dimensions.y, 0, &mode); + + if (error == NULL) { + ro_convert_pixels_to_os_units(&dimensions, mode); + if (width != NULL) + *width = dimensions.x; + if (height != NULL) + *height = dimensions.y; + } else 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 false; + } + + return true; +} + + /** * Performs simple user redraw for a window. * diff --git a/riscos/wimp.h b/riscos/wimp.h index a1672ae67..cd30fc7e5 100644 --- a/riscos/wimp.h +++ b/riscos/wimp.h @@ -54,6 +54,8 @@ 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_deleted_state(wimp_w w, wimp_i i, bool state); +bool ro_gui_get_icon_deleted_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_icon_sprite(wimp_w w, wimp_i i, osspriteop_area *area, const char *name); @@ -64,7 +66,8 @@ void ro_gui_open_window_centre(wimp_w parent, wimp_w child); osspriteop_area *ro_gui_load_sprite_file(const char *pathname); bool ro_gui_wimp_sprite_exists(const char *sprite); os_error *ro_gui_wimp_get_sprite(const char *name, osspriteop_header **sprite); - +bool ro_gui_wimp_get_sprite_dimensions(osspriteop_area *area, char *sprite, + int *width, int *height); 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, diff --git a/riscos/wimp_event.c b/riscos/wimp_event.c index 43011a0e6..384a5258e 100644 --- a/riscos/wimp_event.c +++ b/riscos/wimp_event.c @@ -1,6 +1,6 @@ /* * Copyright 2005 Richard Wilson - * Copyright 2010 Stephen Fryatt + * Copyright 2010, 2011 Stephen Fryatt * * This file is part of NetSurf, http://www.netsurf-browser.org/ * @@ -95,16 +95,19 @@ struct event_window { void (*open_window)(wimp_open *open); void (*close_window)(wimp_w w); void (*redraw_window)(wimp_draw *redraw); - void (*menu_selection)(wimp_w w, wimp_i i); + bool (*menu_prepare)(wimp_w w, wimp_i i, wimp_menu *m, + wimp_pointer *p); + bool (*menu_selection)(wimp_w w, wimp_i i, wimp_menu *m, + wimp_selection *s, menu_action a); + void (*menu_warning)(wimp_w w, wimp_i i, wimp_menu *m, + wimp_selection *s, menu_action a); + void (*menu_close)(wimp_w w, wimp_i i, wimp_menu *m); wimp_menu *window_menu; bool window_menu_auto; - void (*window_menu_prepare)(wimp_w w, wimp_menu *m); - bool (*window_menu_selection)(wimp_w w, wimp_menu *m, - wimp_selection *s, menu_action action); - void (*window_menu_close)(wimp_w w, wimp_menu *m); - void (*window_menu_warning)(wimp_w w, wimp_menu *m, - wimp_selection *s, menu_action action); + bool window_menu_iconbar; const char *help_prefix; + const char *(*get_help_suffix)(wimp_w w, wimp_i i, os_coord *pos, + wimp_mouse_state buttons); void *user_data; struct icon_event *first; struct event_window *next; @@ -117,7 +120,7 @@ static struct event_window *ro_gui_wimp_event_get_window(wimp_w w); static struct event_window *ro_gui_wimp_event_find_window(wimp_w w); static struct icon_event *ro_gui_wimp_event_get_event(wimp_w w, wimp_i i, event_type type); -static void ro_gui_wimp_event_prepare_menu(wimp_w w, struct icon_event *event); +static void ro_gui_wimp_event_prepare_gright_menu(wimp_w w, struct icon_event *event); static struct event_window *ro_gui_wimp_event_remove_window(wimp_w w); static struct event_window *ro_gui_wimp_event_windows[WIN_HASH_SIZE]; @@ -243,6 +246,40 @@ bool ro_gui_wimp_event_validate(wimp_w w) return true; } +/** + * Transfer event data from one window to another. This can be used as an + * alternative to ro_gui_wimp_event_finalise() and re-registering, if + * events need to continue across a change of window handle. + * + * All aspects of the registered events MUST remain the same in the new + * window! + * + * \param from The current window, which is to be deleted. + * \param to The window to which the events should transfer. + * \return true on success; false for an unknown window. + */ + +bool ro_gui_wimp_event_transfer(wimp_w from, wimp_w to) +{ + struct event_window *window; + int h; + + LOG(("Transferring all events from window 0x%x to window 0x%x", + (unsigned int) from, (unsigned int) to)); + + window = ro_gui_wimp_event_remove_window(from); + if (window == NULL || window->w != from) + return false; + + h = WIN_HASH(to); + window->w = to; + window->next = ro_gui_wimp_event_windows[h]; + ro_gui_wimp_event_windows[h] = window; + + ro_gui_menu_window_changed(from, to); + + return true; +} /** * Free any resources associated with a window. @@ -279,6 +316,61 @@ void ro_gui_wimp_event_finalise(wimp_w w) } +/** + * Free any resources associated with a specific icon in a window. + * + * \param w The window containing the icon. + * \param i The icon to free resources for. + */ + +void ro_gui_wimp_event_deregister(wimp_w w, wimp_i i) +{ + struct event_window *window; + struct icon_event *event, *parent, *child; + + LOG(("Removing all events for window 0x%x, icon %d", + (unsigned int)w, (int)i)); + window = ro_gui_wimp_event_get_window(w); + if (!window) + return; + + /* Remove any events that apply to the given icon. */ + + event = window->first; + parent = NULL; + + while (event != NULL) { + child = event->next; + + if (event->i == i) { + LOG(("Removing event 0x%x", (unsigned int) event)); + + if (parent == NULL) + window->first = child; + else + parent->next = child; + + switch (event->type) { + case EVENT_NUMERIC_FIELD: + case EVENT_TEXT_FIELD: + if (event->previous_value.textual) + free(event->previous_value.textual); + event->previous_value.textual = NULL; + break; + default: + break; + } + + free(event); + } else { + parent = event; + } + + event = child; + } +} + + /** * Set the associated help prefix for a given window. * @@ -315,6 +407,45 @@ const char *ro_gui_wimp_event_get_help_prefix(wimp_w w) } +/** + * Register a handler to decode help suffixes for a given window. + * + */ + +bool ro_gui_wimp_event_register_help_suffix(wimp_w w, + const char *(*get_help_suffix)(wimp_w w, wimp_i i, + os_coord *pos, wimp_mouse_state buttons)) +{ + struct event_window *window; + + window = ro_gui_wimp_event_get_window(w); + if (!window) + return false; + window->get_help_suffix = get_help_suffix; + return true; +} + + +/** + * Get the associated help suffix. + * + * \param w The window to get the suffix for + * \return The associated prefix, or NULL + */ + +const char *ro_gui_wimp_event_get_help_suffix(wimp_w w, wimp_i i, + os_coord *pos, wimp_mouse_state buttons) +{ + struct event_window *window; + + window = ro_gui_wimp_event_find_window(w); + if (window == NULL || window->get_help_suffix == NULL) + return NULL; + + return window->get_help_suffix(w, i, pos, buttons); +} + + /** * Sets the user data associated with a window. * @@ -371,7 +502,8 @@ void *ro_gui_wimp_event_get_user_data(wimp_w w) * \param menu the menu that has been selected * \param selection the selection information * \param action the menu action info from menus.c - * \return true if the event was handled, false otherwise + * \return true if the menu is OK for an Adjust re-open; + * else false. */ bool ro_gui_wimp_event_menu_selection(wimp_w w, wimp_i i, wimp_menu *menu, wimp_selection *selection, menu_action action) @@ -384,32 +516,33 @@ bool ro_gui_wimp_event_menu_selection(wimp_w w, wimp_i i, wimp_menu *menu, wimp_caret caret; wimp_icon_state ic; unsigned int button_type; + bool prepared; window = ro_gui_wimp_event_find_window(w); - if (!window) + if (window == NULL) return false; /* Start by looking for an icon event that matches. If there isn't one, - * then check to see if there is a window menu and associated - * selection handler available instead. + * then return details for an unconnected menu. It's up to the + * event recipient to sort out if this is a window menu or not, based + * on the menu handle passed back. */ for (event = window->first; event; event = event->next) if ((event->type == EVENT_MENU_GRIGHT) && (event->i == i)) break; if (!event) { - if ((window->window_menu) && (window->window_menu == menu) - && (window->window_menu_selection)) { - window->window_menu_selection(w, menu, - selection, action); + if (window->menu_selection) + window->menu_selection(window->w, wimp_ICON_WINDOW, + menu, selection, action); + + /* Prepare the menu pending a possible Adjust click. */ + if (window->menu_prepare) + if (!window->menu_prepare(window->w, wimp_ICON_WINDOW, + menu, NULL)) + return false; - /* Prepare the menu pending a possible Adjust click. */ - if (window->window_menu_prepare) - window->window_menu_prepare(w, menu); - return true; - } else { - return false; - } + return true; } menu_entry = &menu->entries[selection->items[0]]; @@ -423,9 +556,15 @@ bool ro_gui_wimp_event_menu_selection(wimp_w w, wimp_i i, wimp_menu *menu, ro_gui_set_icon_string(window->w, event->data.menu_gright.field, menu_entry->data.indirected_text.text, false); - ro_gui_wimp_event_prepare_menu(window->w, event); if (window->menu_selection) - window->menu_selection(window->w, event->i); + window->menu_selection(window->w, event->i, menu, + selection, action); + prepared = true; + if (window->menu_prepare) + prepared = window->menu_prepare(window->w, event->i, + menu, NULL); + if (prepared) + ro_gui_wimp_event_prepare_gright_menu(window->w, event); /* set the caret for writable icons and send a CTRL+U keypress to * stimulate activity if needed */ @@ -441,7 +580,7 @@ bool ro_gui_wimp_event_menu_selection(wimp_w w, wimp_i i, wimp_menu *menu, button_type = (ic.icon.flags & wimp_ICON_BUTTON_TYPE) >> wimp_ICON_BUTTON_TYPE_SHIFT; if ((button_type != wimp_BUTTON_WRITABLE) && (button_type != wimp_BUTTON_WRITE_CLICK_DRAG)) - return true; + return prepared; error = xwimp_get_caret_position(&caret); if (error) { LOG(("xwimp_get_caret_position: 0x%x: %s", @@ -463,7 +602,7 @@ bool ro_gui_wimp_event_menu_selection(wimp_w w, wimp_i i, wimp_menu *menu, key.c = 21; // ctrl+u window->keypress(&key); } - return true; + return prepared; } @@ -493,6 +632,7 @@ bool ro_gui_wimp_event_mouse_click(wimp_pointer *pointer) wimp_window_state open; wimp_caret caret; os_error *error; + bool prepared; w = pointer->w; window = ro_gui_wimp_event_find_window(w); @@ -500,7 +640,9 @@ bool ro_gui_wimp_event_mouse_click(wimp_pointer *pointer) return false; /* Menu clicks take priority if there is an auto menu defined. */ - if ((window->window_menu) && (window->window_menu_auto)) { + if ((pointer->buttons == wimp_CLICK_MENU) && + (window->window_menu != NULL) && + (window->window_menu_auto)) { ro_gui_wimp_event_process_window_menu_click(pointer); return true; } @@ -574,7 +716,7 @@ bool ro_gui_wimp_event_mouse_click(wimp_pointer *pointer) } ro_gui_dialog_add_persistent(current_menu_window, pointer->w); - ro_gui_menu_closed(false); + ro_gui_menu_closed(); gui_poll(true); error = xwimp_open_window(PTR_WIMP_OPEN(&open)); if (error) { @@ -596,8 +738,15 @@ bool ro_gui_wimp_event_mouse_click(wimp_pointer *pointer) } } /* display the menu */ - ro_gui_wimp_event_prepare_menu(pointer->w, event); - ro_gui_popup_menu(event->data.menu_gright.menu, pointer->w, pointer->i); + + prepared = true; + if (window->menu_prepare != NULL) + prepared = window->menu_prepare(pointer->w, pointer->i, + event->data.menu_gright.menu, pointer); + if (prepared) { + ro_gui_wimp_event_prepare_gright_menu(pointer->w, event); + ro_gui_popup_menu(event->data.menu_gright.menu, pointer->w, pointer->i); + } break; case EVENT_CHECKBOX: break; @@ -617,7 +766,7 @@ bool ro_gui_wimp_event_mouse_click(wimp_pointer *pointer) if (pointer->buttons & wimp_CLICK_SELECT) { ro_gui_dialog_close(pointer->w); ro_gui_wimp_event_close_window(pointer->w); - ro_gui_menu_closed(true); + ro_gui_menu_closed(); } else { ro_gui_wimp_event_restore(pointer->w); } @@ -636,7 +785,7 @@ bool ro_gui_wimp_event_mouse_click(wimp_pointer *pointer) * /param w the window owning the menu * /param event the icon event owning the menu */ -void ro_gui_wimp_event_prepare_menu(wimp_w w, struct icon_event *event) +void ro_gui_wimp_event_prepare_gright_menu(wimp_w w, struct icon_event *event) { int i; const char *text; @@ -699,7 +848,7 @@ void ro_gui_wimp_event_ok_click(struct event_window *window, if (state & wimp_CLICK_SELECT) { ro_gui_dialog_close(window->w); ro_gui_wimp_event_close_window(window->w); - ro_gui_menu_closed(true); + ro_gui_menu_closed(); } else { ro_gui_wimp_event_memorise(window->w); } @@ -863,7 +1012,7 @@ bool ro_gui_wimp_event_keypress(wimp_key *key) } } } else { - k.c |= (1u<<31); + k.c |= IS_WIMP_KEY; } /* registered routines take priority */ @@ -894,7 +1043,7 @@ bool ro_gui_wimp_event_keypress(wimp_key *key) return false; ro_gui_dialog_close(key->w); ro_gui_wimp_event_close_window(key->w); - ro_gui_menu_closed(true); + ro_gui_menu_closed(); return true; /* Return performs the OK action */ case wimp_KEY_RETURN: @@ -975,23 +1124,102 @@ bool ro_gui_wimp_event_redraw_window(wimp_draw *redraw) bool ro_gui_wimp_event_process_window_menu_click(wimp_pointer *pointer) { - struct event_window *window; + struct event_window *window; + int xpos, ypos, line_height, gap_height, entry; window = ro_gui_wimp_event_find_window(pointer->w); if ((window) && (window->window_menu) && (pointer->buttons == wimp_CLICK_MENU)) { - if (window->window_menu_prepare) - window->window_menu_prepare(window->w, - window->window_menu); + if (window->menu_prepare) + if (!window->menu_prepare(window->w, wimp_ICON_WINDOW, + window->window_menu, pointer)) + return false; - ro_gui_menu_create(window->window_menu, - pointer->pos.x, pointer->pos.y, - window->w, false); + if (window->window_menu_iconbar) { + xpos = pointer->pos.x; + ypos = 96; + + line_height = window->window_menu->height + + window->window_menu->gap; + gap_height = 24; /* The fixed dotted line height */ + + entry = 0; + do { + ypos += line_height; + if ((window->window_menu-> + entries[entry].menu_flags & + wimp_MENU_SEPARATE) != 0) + ypos += gap_height; + } while ((window->window_menu-> + entries[entry++].menu_flags & + wimp_MENU_LAST) == 0); + } else { + xpos = pointer->pos.x; + ypos = pointer->pos.y; + } + + ro_gui_menu_create(window->window_menu, xpos, ypos, window->w); return true; } return false; } + +/** + * Trigger a window's Prepare Menu event. + * + * \param w The window to use. + * \param i The icon to use. + * \param *menu The menu handle to use. + * \return true if the affected menu was prepared OK; else + * false. + */ + +bool ro_gui_wimp_event_prepare_menu(wimp_w w, wimp_i i, wimp_menu *menu) +{ + struct event_window *window; + + window = ro_gui_wimp_event_find_window(w); + if (window == NULL) + return false; + + if (window->menu_prepare) + return window->menu_prepare(w, i, menu, NULL); + + /* The menu is always OK if there's no event handler. */ + + return true; +} + +/** + * Register a window menu to be (semi-)automatically handled. + * + * \param w The window to attach the menu to. + * \param *m The menu to be attached. + * \param menu_auto true if the menu should be opened autimatically + * on Menu clicks with no task intervention; false + * to pass clicks to the window's Mouse Event + * handler and leave that to pass the menu click + * back to us for handling and menu opening. + * \param bool_position_ibar true if the menu should open in an iconbar + * position; false to open at the pointer. + * \return true if the menu was registed ok; else false. + */ + +bool ro_gui_wimp_event_register_menu(wimp_w w, wimp_menu *m, + bool menu_auto, bool position_ibar) +{ + struct event_window *window; + + window = ro_gui_wimp_event_get_window(w); + if (!window) + return false; + window->window_menu = m; + window->window_menu_auto = menu_auto; + window->window_menu_iconbar = position_ibar; + return true; +} + /** * Register a numeric field to be automatically handled */ @@ -1227,11 +1455,40 @@ bool ro_gui_wimp_event_register_redraw_window(wimp_w w, return true; } + +/** + * Register a function to be called before a menu is (re-)opened. + * + * \param *w The window for which events should be returned. + * \param *callback A function to be called beofre the menu is + * (re-)opened. + * \return true if the menu was registed ok; else false. + */ +bool ro_gui_wimp_event_register_menu_prepare(wimp_w w, + bool (*callback)(wimp_w w, wimp_i i, wimp_menu *m, + wimp_pointer *p)) +{ + struct event_window *window; + + window = ro_gui_wimp_event_get_window(w); + if (!window) + return false; + window->menu_prepare = callback; + return true; +} + + /** * Register a function to be called following a menu selection. + * + * \param *w The window for which events should be returned. + * \param *callback A function to be called when a selection is + * made. + * \return true if the menu was registed ok; else false. */ bool ro_gui_wimp_event_register_menu_selection(wimp_w w, - void (*callback)(wimp_w w, wimp_i i)) + bool (*callback)(wimp_w w, wimp_i i, wimp_menu *m, + wimp_selection *s, menu_action a)) { struct event_window *window; @@ -1242,32 +1499,45 @@ bool ro_gui_wimp_event_register_menu_selection(wimp_w w, return true; } + /** - * Register a set of functions to be called to handle a window menu. + * Register a function to be called when a sub-menu warning is received. * - * \param + * \param *w The window for which events should be returned. + * \param *callback A function to be called whenever a submenu + * warning is received for the menu. + * \return true if the menu was registed ok; else false. */ +bool ro_gui_wimp_event_register_menu_warning(wimp_w w, + void (*callback)(wimp_w w, wimp_i i, wimp_menu *m, + wimp_selection *s, menu_action a)) +{ + struct event_window *window; + + window = ro_gui_wimp_event_get_window(w); + if (!window) + return false; + window->menu_warning = callback; + return true; +} -bool ro_gui_wimp_event_register_window_menu(wimp_w w, wimp_menu *m, - void (*callback_prepare)(wimp_w w, wimp_menu *m), - bool (*callback_selection)(wimp_w w, wimp_menu *m, - wimp_selection *s, menu_action action), - void (*callback_close)(wimp_w w, wimp_menu *m), - void (*callback_warning)(wimp_w w, wimp_menu *m, - wimp_selection *s, menu_action action), - bool menu_auto) + +/** + * Register a function to be called before a menu is finally closed. + * + * \param *w The window for which events should be returned. + * \param *callback A function to be called when the menu is closed. + * \return true if the menu was registed ok; else false. + */ +bool ro_gui_wimp_event_register_menu_close(wimp_w w, + void (*callback)(wimp_w w, wimp_i i, wimp_menu *m)) { struct event_window *window; window = ro_gui_wimp_event_get_window(w); if (!window) return false; - window->window_menu = m; - window->window_menu_prepare = callback_prepare; - window->window_menu_selection = callback_selection; - window->window_menu_close = callback_close; - window->window_menu_warning = callback_warning; - window->window_menu_auto = menu_auto; + window->menu_close = callback; return true; } @@ -1408,20 +1678,29 @@ bool ro_gui_wimp_event_submenu_warning(wimp_w w, wimp_i i, wimp_menu *menu, for (event = window->first; event; event = event->next) if ((event->type == EVENT_MENU_GRIGHT) && (event->i == i)) break; - if (event) + if (event) { + if (window->menu_close != NULL && + event->type == EVENT_MENU_GRIGHT && + event->data.menu_gright.menu == menu) { + window->menu_close(w, i, menu); + return true; + } + return false; + } /* If the warning is for a window menu, then pass the event on to it. */ if ((window->window_menu) && (window->window_menu == menu)) { - if (window->window_menu_warning) { - window->window_menu_warning(w, menu, selection, action); + if (window->menu_warning) { + window->menu_warning(w, wimp_ICON_WINDOW, menu, + selection, action); return true; } } return false; -} +} /** * Handle menus being closed. This is called from ro_gui_menu_closed(), in @@ -1440,8 +1719,8 @@ void ro_gui_wimp_event_menus_closed(wimp_w w, wimp_i i, wimp_menu *menu) ro_gui_wimp_event_register_submenu(0); /* Process the event for any window menus. Find the window data, then - * try and match to an icon event. If we can, then there isn't anything - * to do. + * try and match to an icon event. If we can, then GRight menus are + * sent the event; otherwise, we do nothing. */ window = ro_gui_wimp_event_find_window(w); @@ -1451,14 +1730,19 @@ void ro_gui_wimp_event_menus_closed(wimp_w w, wimp_i i, wimp_menu *menu) for (event = window->first; event; event = event->next) if ((event->type == EVENT_MENU_GRIGHT) && (event->i == i)) break; - if (event) + if (event) { + if (window->menu_close != NULL && + event->type == EVENT_MENU_GRIGHT && + event->data.menu_gright.menu == menu) + window->menu_close(w, i, menu); return; + } /* If the close is for a window menu, then pass the event on to it. */ if ((window->window_menu) && (window->window_menu == menu) && - (window->window_menu_close)) - window->window_menu_close(w, menu); + (window->menu_close)) + window->menu_close(w, wimp_ICON_WINDOW, menu); } /** diff --git a/riscos/wimp_event.h b/riscos/wimp_event.h index 54ae95ae5..f232291d8 100644 --- a/riscos/wimp_event.h +++ b/riscos/wimp_event.h @@ -1,6 +1,6 @@ /* * Copyright 2005 Richard Wilson - * Copyright 2010 Stephen Fryatt + * Copyright 2010, 2011 Stephen Fryatt * * This file is part of NetSurf, http://www.netsurf-browser.org/ * @@ -31,7 +31,7 @@ #include #include #include "oslib/os.h" -#include "oslib/wimp.h" +#include "oslib/wimp.h" #include "riscos/menus.h" #define IS_WIMP_KEY (1u<<31) @@ -39,10 +39,17 @@ bool ro_gui_wimp_event_memorise(wimp_w w); bool ro_gui_wimp_event_restore(wimp_w w); bool ro_gui_wimp_event_validate(wimp_w w); +bool ro_gui_wimp_event_transfer(wimp_w from, wimp_w to); void ro_gui_wimp_event_finalise(wimp_w w); +void ro_gui_wimp_event_deregister(wimp_w w, wimp_i i); bool ro_gui_wimp_event_set_help_prefix(wimp_w w, const char *help_prefix); const char *ro_gui_wimp_event_get_help_prefix(wimp_w w); +bool ro_gui_wimp_event_register_help_suffix(wimp_w w, + const char *(*get_help_suffix)(wimp_w w, wimp_i i, + os_coord *pos, wimp_mouse_state buttons)); +const char *ro_gui_wimp_event_get_help_suffix(wimp_w w, wimp_i i, + os_coord *pos, wimp_mouse_state buttons); bool ro_gui_wimp_event_set_user_data(wimp_w w, void *user); void *ro_gui_wimp_event_get_user_data(wimp_w w); @@ -52,10 +59,13 @@ bool ro_gui_wimp_event_mouse_click(wimp_pointer *pointer); bool ro_gui_wimp_event_keypress(wimp_key *key); bool ro_gui_wimp_event_open_window(wimp_open *open); bool ro_gui_wimp_event_close_window(wimp_w w); -bool ro_gui_wimp_event_redraw_window(wimp_draw *redraw); - +bool ro_gui_wimp_event_redraw_window(wimp_draw *redraw); + bool ro_gui_wimp_event_process_window_menu_click(wimp_pointer *pointer); +bool ro_gui_wimp_event_prepare_menu(wimp_w w, wimp_i i, wimp_menu *menu); +bool ro_gui_wimp_event_register_menu(wimp_w w, wimp_menu *m, + bool menu_auto, bool position_ibar); bool ro_gui_wimp_event_register_numeric_field(wimp_w w, wimp_i i, wimp_i up, wimp_i down, int min, int max, int stepping, int decimal_places); @@ -80,18 +90,19 @@ bool ro_gui_wimp_event_register_close_window(wimp_w w, void (*callback)(wimp_w w)); bool ro_gui_wimp_event_register_redraw_window(wimp_w w, void (*callback)(wimp_draw *redraw)); +bool ro_gui_wimp_event_register_menu_prepare(wimp_w w, + bool (*callback)(wimp_w w, wimp_i i, wimp_menu *m, + wimp_pointer *p)); bool ro_gui_wimp_event_register_menu_selection(wimp_w w, - void (*callback)(wimp_w w, wimp_i i)); -bool ro_gui_wimp_event_register_window_menu(wimp_w w, wimp_menu *m, - void (*callback_prepare)(wimp_w w, wimp_menu *m), - bool (*callback_selection)(wimp_w w, wimp_menu *m, - wimp_selection *s, menu_action action), - void (*callback_close)(wimp_w w, wimp_menu *m), - void (*callback_warning)(wimp_w w, wimp_menu *m, - wimp_selection *s, menu_action action), - bool menu_auto); + bool (*callback)(wimp_w w, wimp_i i, wimp_menu *m, + wimp_selection *s, menu_action a)); +bool ro_gui_wimp_event_register_menu_warning(wimp_w w, + void (*callback)(wimp_w w, wimp_i i, wimp_menu *m, + wimp_selection *s, menu_action a)); +bool ro_gui_wimp_event_register_menu_close(wimp_w w, + void (*callback)(wimp_w w, wimp_i i, wimp_menu *m)); -bool ro_gui_wimp_event_submenu_warning(wimp_w w, wimp_i i, wimp_menu *menu, +bool ro_gui_wimp_event_submenu_warning(wimp_w w, wimp_i i, wimp_menu *menu, wimp_selection *selection, menu_action action); void ro_gui_wimp_event_menus_closed(wimp_w w, wimp_i i, wimp_menu *menu); void ro_gui_wimp_event_register_submenu(wimp_w w); diff --git a/riscos/window.c b/riscos/window.c index 1aa2a82f2..3f07e793d 100644 --- a/riscos/window.c +++ b/riscos/window.c @@ -5,7 +5,7 @@ * Copyright 2004 Andrew Timmins * Copyright 2005 Richard Wilson * Copyright 2005 Adrian Lees - * Copyright 2010 Stephen Fryatt + * Copyright 2010, 2011 Stephen Fryatt * * This file is part of NetSurf, http://www.netsurf-browser.org/ * @@ -46,9 +46,13 @@ #include "content/urldb.h" #include "css/css.h" #include "desktop/browser.h" +#include "desktop/cookies.h" #include "desktop/frames.h" +#include "desktop/history_core.h" +#include "desktop/hotlist.h" #include "desktop/mouse.h" #include "desktop/plotters.h" +#include "desktop/selection.h" #include "desktop/textinput.h" #include "desktop/thumbnail.h" #include "desktop/tree.h" @@ -57,21 +61,26 @@ #include "render/form.h" #include "riscos/bitmap.h" #include "riscos/buffer.h" +#include "riscos/cookies.h" #include "riscos/dialog.h" #include "riscos/global_history.h" #include "riscos/gui.h" #include "riscos/gui/status_bar.h" +#include "riscos/help.h" +#include "riscos/hotlist.h" #include "riscos/menus.h" #include "riscos/options.h" #include "riscos/oslib_pre7.h" #include "riscos/save.h" #include "riscos/sprite.h" -#include "riscos/theme.h" +#include "riscos/toolbar.h" #include "riscos/thumbnail.h" #include "riscos/url_complete.h" +#include "riscos/url_suggest.h" #include "riscos/wimp.h" #include "riscos/wimp_event.h" #include "riscos/wimputils.h" +#include "riscos/window.h" #include "utils/log.h" #include "utils/talloc.h" #include "utils/url.h" @@ -79,6 +88,66 @@ #include "utils/utils.h" #include "utils/messages.h" + +static void gui_window_set_extent(struct gui_window *g, int width, int height); + +static void ro_gui_window_redraw(wimp_draw *redraw); +static void ro_gui_window_open(wimp_open *open); +static void ro_gui_window_close(wimp_w w); +static bool ro_gui_window_click(wimp_pointer *mouse); +static bool ro_gui_window_keypress(wimp_key *key); +static void ro_gui_window_toolbar_keypress(void *data, wimp_key *key); +static void ro_gui_window_handle_local_keypress(struct gui_window *g, + wimp_key *key, bool is_toolbar); +static bool ro_gui_window_menu_prepare(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_pointer *pointer); +static void ro_gui_window_menu_warning(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_selection *selection, menu_action action); +static bool ro_gui_window_menu_select(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_selection *selection, menu_action action); +static void ro_gui_window_menu_close(wimp_w w, wimp_i i, wimp_menu *menu); + +static void ro_gui_window_toolbar_click(void *data, + toolbar_action_type action_type, union toolbar_action action); + +static bool ro_gui_window_content_export_types(hlcache_handle *h, + bool *export_draw, bool *export_sprite); +static bool ro_gui_window_up_available(struct browser_window *bw); +static void ro_gui_window_prepare_pageinfo(struct gui_window *g); +static void ro_gui_window_prepare_objectinfo(hlcache_handle *object, + const char *href); + +static void ro_gui_window_launch_url(struct gui_window *g, const char *url); +static bool ro_gui_window_navigate_up(struct gui_window *g, const char *url); +static void ro_gui_window_action_home(struct gui_window *g); +static void ro_gui_window_action_new_window(struct gui_window *g); +static void ro_gui_window_action_local_history(struct gui_window *g); +static void ro_gui_window_action_navigate_back_new(struct gui_window *g); +static void ro_gui_window_action_navigate_forward_new(struct gui_window *g); +static void ro_gui_window_action_save(struct gui_window *g, + gui_save_type save_type); +static void ro_gui_window_action_search(struct gui_window *g); +static void ro_gui_window_action_zoom(struct gui_window *g); +static void ro_gui_window_action_add_bookmark(struct gui_window *g); +static void ro_gui_window_action_print(struct gui_window *g); +static void ro_gui_window_action_page_info(struct gui_window *g); + +static void ro_gui_window_remove_update_boxes(struct gui_window *g); +static void ro_gui_window_update_toolbar_buttons(struct gui_window *g); +static void ro_gui_window_update_toolbar(void *data); +static void ro_gui_window_save_toolbar_buttons(void *data, char *config); +static void ro_gui_window_update_theme(void *data, bool ok); + +static bool ro_gui_window_import_text(struct gui_window *g, + const char *filename, bool toolbar); +static void ro_gui_window_clone_options(struct browser_window *new_bw, + struct browser_window *old_bw); + +static bool ro_gui_window_prepare_form_select_menu(struct browser_window *bw, + struct form_control *control); +static void ro_gui_window_process_form_select_menu(struct gui_window *g, + wimp_selection *selection); + #ifndef wimp_KEY_END #define wimp_KEY_END wimp_KEY_COPY #endif @@ -99,17 +168,25 @@ static bool mouse_drag_select; static bool mouse_drag_adjust; /** List of all browser windows. */ -static struct gui_window *window_list = 0; +static struct gui_window *window_list = 0; /** GUI window which is being redrawn. Valid only during redraw. */ -struct gui_window *ro_gui_current_redraw_gui; +struct gui_window *ro_gui_current_redraw_gui; +/** Form control which gui_form_select_menu is for. */ +static struct form_control *gui_form_select_control; +/** The browser window menu handle. */ +static wimp_menu *ro_gui_browser_window_menu = NULL; +/** Menu of options for form select controls. */ +static wimp_menu *gui_form_select_menu = NULL; +/** Object under menu, or 0 if no object. */ +static hlcache_handle *current_menu_object = 0; +/** URL of link under menu, or 0 if no link. */ +static const char *current_menu_url = 0; static float scale_snap_to[] = {0.10, 0.125, 0.25, 0.333, 0.5, 0.75, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0, 8.0, 12.0, 16.0}; #define SCALE_SNAP_TO_SIZE (sizeof scale_snap_to) / (sizeof(float)) - - /** An entry in ro_gui_pointer_table. */ struct ro_gui_pointer_entry { bool wimp_area; /** The pointer is in the Wimp's sprite area. */ @@ -142,20 +219,6 @@ struct ro_gui_pointer_entry ro_gui_pointer_table[] = { { false, "ptr_progress", 0, 0 }, }; - -static void ro_gui_window_remove_update_boxes(struct gui_window *g); -static void gui_window_set_extent(struct gui_window *g, int width, int height); -static void ro_gui_window_open(wimp_open *open); -static void ro_gui_window_close(wimp_w w); -static void ro_gui_window_redraw(wimp_draw *redraw); -static bool ro_gui_window_click(wimp_pointer *mouse); -static bool ro_gui_window_keypress(wimp_key *key); -static void ro_gui_window_launch_url(struct gui_window *g, const char *url); -static void ro_gui_window_clone_options(struct browser_window *new_bw, - struct browser_window *old_bw); -static bool ro_gui_window_import_text(struct gui_window *g, - const char *filename, bool toolbar); - struct update_box { int x0; int y0; @@ -170,6 +233,129 @@ struct update_box { struct update_box *pending_updates; #define MARGIN 4 +static const struct toolbar_callbacks ro_gui_window_toolbar_callbacks = { + ro_gui_window_update_theme, + ro_gui_window_update_toolbar, + (void (*)(void *)) ro_gui_window_update_toolbar_buttons, + ro_gui_window_toolbar_click, + ro_gui_window_toolbar_keypress, + ro_gui_window_save_toolbar_buttons +}; + + +/** + * Initialise the browser window module and its menus. + */ + +void ro_gui_window_initialise(void) +{ + /* Build the browser window menu. */ + + static const struct ns_menu browser_definition = { + "NetSurf", { + { "Page", BROWSER_PAGE, 0 }, + { "Page.PageInfo",BROWSER_PAGE_INFO, &dialog_pageinfo }, + { "Page.Save", BROWSER_SAVE, &dialog_saveas }, + { "Page.SaveComp", BROWSER_SAVE_COMPLETE, &dialog_saveas }, + { "Page.Export", NO_ACTION, 0 }, +#ifdef WITH_DRAW_EXPORT + { "Page.Export.Draw", BROWSER_EXPORT_DRAW, &dialog_saveas }, +#endif +#ifdef WITH_PDF_EXPORT + { "Page.Export.PDF", BROWSER_EXPORT_PDF, &dialog_saveas }, +#endif + { "Page.Export.Text", BROWSER_EXPORT_TEXT, &dialog_saveas }, + { "Page.SaveURL", NO_ACTION, 0 }, + { "Page.SaveURL.URI", BROWSER_SAVE_URL_URI, &dialog_saveas }, + { "Page.SaveURL.URL", BROWSER_SAVE_URL_URL, &dialog_saveas }, + { "Page.SaveURL.LinkText", BROWSER_SAVE_URL_TEXT, &dialog_saveas }, + { "_Page.Print", BROWSER_PRINT, &dialog_print }, + { "Page.NewWindow", BROWSER_NEW_WINDOW, 0 }, + { "Page.FindText", BROWSER_FIND_TEXT, &dialog_search }, + { "Page.ViewSrc", BROWSER_VIEW_SOURCE, 0 }, + { "Object", BROWSER_OBJECT, 0 }, + { "Object.Object", BROWSER_OBJECT_OBJECT, 0 }, + { "Object.Object.ObjInfo", BROWSER_OBJECT_INFO, &dialog_objinfo }, + { "Object.Object.ObjSave", BROWSER_OBJECT_SAVE, &dialog_saveas }, + { "Object.Object.Export", BROWSER_OBJECT_EXPORT, 0 }, + { "Object.Object.Export.Sprite", BROWSER_OBJECT_EXPORT_SPRITE, &dialog_saveas }, +#ifdef WITH_DRAW_EXPORT + { "Object.Object.Export.ObjDraw", BROWSER_OBJECT_EXPORT_DRAW, &dialog_saveas }, +#endif + { "Object.Object.SaveURL", NO_ACTION, 0 }, + { "Object.Object.SaveURL.URI", BROWSER_OBJECT_SAVE_URL_URI, &dialog_saveas }, + { "Object.Object.SaveURL.URL", BROWSER_OBJECT_SAVE_URL_URL, &dialog_saveas }, + { "Object.Object.SaveURL.LinkText", BROWSER_OBJECT_SAVE_URL_TEXT, &dialog_saveas }, + { "Object.Object.ObjPrint", BROWSER_OBJECT_PRINT, 0 }, + { "Object.Object.ObjReload", BROWSER_OBJECT_RELOAD, 0 }, + { "Object.Link", BROWSER_OBJECT_LINK, 0 }, + { "Object.Link.LinkSave", BROWSER_LINK_SAVE, 0 }, + { "Object.Link.LinkSave.URI", BROWSER_LINK_SAVE_URI, &dialog_saveas }, + { "Object.Link.LinkSave.URL", BROWSER_LINK_SAVE_URL, &dialog_saveas }, + { "Object.Link.LinkSave.LinkText", BROWSER_LINK_SAVE_TEXT, &dialog_saveas }, + { "_Object.Link.LinkDload", BROWSER_LINK_DOWNLOAD, 0 }, + { "Object.Link.LinkNew", BROWSER_LINK_NEW_WINDOW, 0 }, + { "Selection", BROWSER_SELECTION, 0 }, + { "_Selection.SelSave", BROWSER_SELECTION_SAVE, &dialog_saveas }, + { "Selection.Copy", BROWSER_SELECTION_COPY, 0 }, + { "Selection.Cut", BROWSER_SELECTION_CUT, 0 }, + { "_Selection.Paste", BROWSER_SELECTION_PASTE, 0 }, + { "Selection.Clear", BROWSER_SELECTION_CLEAR, 0 }, + { "Selection.SelectAll", BROWSER_SELECTION_ALL, 0 }, + { "Navigate", NO_ACTION, 0 }, + { "Navigate.Home", BROWSER_NAVIGATE_HOME, 0 }, + { "Navigate.Back", BROWSER_NAVIGATE_BACK, 0 }, + { "Navigate.Forward", BROWSER_NAVIGATE_FORWARD, 0 }, + { "_Navigate.UpLevel", BROWSER_NAVIGATE_UP, 0 }, + { "Navigate.Reload", BROWSER_NAVIGATE_RELOAD_ALL, 0 }, + { "Navigate.Stop", BROWSER_NAVIGATE_STOP, 0 }, + { "View", NO_ACTION, 0 }, + { "View.ScaleView", BROWSER_SCALE_VIEW, &dialog_zoom }, + { "View.Images", NO_ACTION, 0 }, + { "View.Images.ForeImg", BROWSER_IMAGES_FOREGROUND, 0 }, + { "View.Images.BackImg", BROWSER_IMAGES_BACKGROUND, 0 }, + { "View.Toolbars", NO_ACTION, 0 }, + { "View.Toolbars.ToolButtons", TOOLBAR_BUTTONS, 0 }, + { "View.Toolbars.ToolAddress", TOOLBAR_ADDRESS_BAR, 0 }, + { "_View.Toolbars.ToolThrob", TOOLBAR_THROBBER, 0 }, + { "View.Toolbars.EditToolbar", TOOLBAR_EDIT, 0 }, + { "_View.Render", NO_ACTION, 0 }, + { "View.Render.RenderAnims", BROWSER_BUFFER_ANIMS, 0 }, + { "View.Render.RenderAll", BROWSER_BUFFER_ALL, 0 }, + { "_View.OptDefault", BROWSER_SAVE_VIEW, 0 }, + { "View.Window", NO_ACTION, 0 }, + { "View.Window.WindowSave", BROWSER_WINDOW_DEFAULT, 0 }, + { "View.Window.WindowStagr", BROWSER_WINDOW_STAGGER, 0 }, + { "_View.Window.WindowSize", BROWSER_WINDOW_COPY, 0 }, + { "View.Window.WindowReset", BROWSER_WINDOW_RESET, 0 }, + { "Utilities", NO_ACTION, 0 }, + { "Utilities.Hotlist", HOTLIST_SHOW, 0 }, + { "Utilities.Hotlist.HotlistAdd", HOTLIST_ADD_URL, 0 }, + { "Utilities.Hotlist.HotlistShow", HOTLIST_SHOW, 0 }, + { "Utilities.History", HISTORY_SHOW_GLOBAL, 0 }, + { "Utilities.History.HistLocal", HISTORY_SHOW_LOCAL, 0 }, + { "Utilities.History.HistGlobal", HISTORY_SHOW_GLOBAL, 0 }, + { "Utilities.Cookies", COOKIES_SHOW, 0 }, + { "Utilities.Cookies.ShowCookies", COOKIES_SHOW, 0 }, + { "Utilities.Cookies.DeleteCookies", COOKIES_DELETE, 0 }, + { "Help", HELP_OPEN_CONTENTS, 0 }, + { "Help.HelpContent", HELP_OPEN_CONTENTS, 0 }, + { "Help.HelpGuide", HELP_OPEN_GUIDE, 0 }, + { "_Help.HelpInfo", HELP_OPEN_INFORMATION, 0 }, + { "_Help.HelpAbout", HELP_OPEN_ABOUT, 0 }, + { "Help.HelpInter", HELP_LAUNCH_INTERACTIVE, 0 }, + {NULL, 0, 0} + } + }; + ro_gui_browser_window_menu = + ro_gui_menu_define_menu(&browser_definition); + +} + + +/* + * Interface With Core + */ /** * Create and open a new browser window. @@ -203,8 +389,6 @@ struct gui_window *gui_create_browser_window(struct browser_window *bw, g->old_height = 0; g->update_extent = true; strcpy(g->title, "NetSurf"); - g->throbber = 0; - g->throbtime = 0; g->iconise_icon = -1; /* Set the window position */ @@ -365,27 +549,47 @@ struct gui_window *gui_create_browser_window(struct browser_window *bw, /* Add in a toolbar and status bar */ if (bw->browser_window_type == BROWSER_WINDOW_NORMAL) { g->status_bar = ro_gui_status_bar_create(g->window, option_toolbar_status_width); - g->toolbar = ro_gui_theme_create_toolbar(NULL, THEME_BROWSER_TOOLBAR); - ro_gui_theme_attach_toolbar(g->toolbar, g->window); + g->toolbar = ro_toolbar_create(NULL, g->window, + THEME_STYLE_BROWSER_TOOLBAR, TOOLBAR_FLAGS_NONE, + &ro_gui_window_toolbar_callbacks, g, + "HelpToolbar"); + if (g->toolbar != NULL) { + ro_toolbar_add_buttons(g->toolbar, + brower_toolbar_buttons, + option_toolbar_browser); + ro_toolbar_add_url(g->toolbar); + ro_toolbar_add_throbber(g->toolbar); + ro_toolbar_rebuild(g->toolbar); + } } else { g->toolbar = NULL; } - /* Set the window options */ - bw->window = g; - ro_gui_window_clone_options(bw, clone); - ro_gui_prepare_navigate(g); - - /* Register event handlers */ + /* Register event handlers. Do this quickly, as some of the things + * that follow will indirectly look up our user data: this MUST + * be set first! + */ ro_gui_wimp_event_set_user_data(g->window, g); ro_gui_wimp_event_register_open_window(g->window, ro_gui_window_open); ro_gui_wimp_event_register_close_window(g->window, ro_gui_window_close); ro_gui_wimp_event_register_redraw_window(g->window, ro_gui_window_redraw); ro_gui_wimp_event_register_keypress(g->window, ro_gui_window_keypress); - if (g->toolbar) - ro_gui_wimp_event_register_keypress(g->toolbar->toolbar_handle, - ro_gui_window_keypress); ro_gui_wimp_event_register_mouse_click(g->window, ro_gui_window_click); + ro_gui_wimp_event_register_menu(g->window, ro_gui_browser_window_menu, + true, false); + ro_gui_wimp_event_register_menu_prepare(g->window, + ro_gui_window_menu_prepare); + ro_gui_wimp_event_register_menu_selection(g->window, + ro_gui_window_menu_select); + ro_gui_wimp_event_register_menu_warning(g->window, + ro_gui_window_menu_warning); + ro_gui_wimp_event_register_menu_close(g->window, + ro_gui_window_menu_close); + + /* Set the window options */ + bw->window = g; + ro_gui_window_clone_options(bw, clone); + ro_gui_window_update_toolbar_buttons(g); /* Open the window at the top of the stack */ state.w = g->window; @@ -417,17 +621,9 @@ struct gui_window *gui_create_browser_window(struct browser_window *bw, /* Claim the caret for top-level windows */ if (bw->browser_window_type == BROWSER_WINDOW_NORMAL) { - if (g->toolbar && g->toolbar->display_url) { - error = xwimp_set_caret_position( - g->toolbar->toolbar_handle, - ICON_TOOLBAR_URL, -1, -1, -1, 0); - ro_gui_url_complete_start(g); - if (error) { - LOG(("xwimp_set_caret_position: 0x%x: %s", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); - } - } else + if (ro_toolbar_take_caret(g->toolbar)) + ro_gui_url_complete_start(g->toolbar); + else gui_window_place_caret(g, -100, -100, 0); } return g; @@ -463,15 +659,15 @@ void gui_window_destroy(struct gui_window *g) /* destroy toolbar */ if (g->toolbar) - ro_gui_theme_destroy_toolbar(g->toolbar); + ro_toolbar_destroy(g->toolbar); if (g->status_bar) ro_gui_status_bar_destroy(g->status_bar); w = g->window; - ro_gui_url_complete_close(NULL, 0); + ro_gui_url_complete_close(); ro_gui_dialog_close_persistent(w); if (current_menu_window == w) - ro_gui_menu_closed(true); + ro_gui_menu_closed(); ro_gui_window_remove_update_boxes(g); /* delete window */ @@ -659,7 +855,7 @@ bool gui_window_get_scroll(struct gui_window *g, int *sx, int *sy) } if (g->toolbar) - toolbar_height = ro_gui_theme_toolbar_full_height(g->toolbar); + toolbar_height = ro_toolbar_full_height(g->toolbar); *sx = state.xscroll / (2 * g->bw->scale); *sy = -(state.yscroll - toolbar_height) / (2 * g->bw->scale); return true; @@ -693,7 +889,7 @@ void gui_window_set_scroll(struct gui_window *g, int sx, int sy) state.xscroll = sx * 2 * g->bw->scale; state.yscroll = -sy * 2 * g->bw->scale; if (g->toolbar) - state.yscroll += ro_gui_theme_toolbar_full_height(g->toolbar); + state.yscroll += ro_toolbar_full_height(g->toolbar); ro_gui_window_open(PTR_WIMP_OPEN(&state)); } @@ -728,7 +924,7 @@ void gui_window_scroll_visible(struct gui_window *g, int x0, int y0, int x1, int } if (g->toolbar) - toolbar_height = ro_gui_theme_toolbar_full_height(g->toolbar); + toolbar_height = ro_toolbar_full_height(g->toolbar); x0 = x0 * 2 * g->bw->scale; y0 = y0 * 2 * g->bw->scale; @@ -898,25 +1094,27 @@ void gui_window_get_dimensions(struct gui_window *g, int *width, int *height, bo /** - * Update the extent of the inside of a browser window to that of the current content. + * Update the extent of the inside of a browser window to that of the + * current content. * - * \param g gui_window to update the extent of + * \param g gui_window to update the extent of */ void gui_window_update_extent(struct gui_window *g) { - os_error *error; - wimp_window_state state; - bool update; - unsigned int flags; - int scroll = 0; + os_error *error; + wimp_window_info info; + wimp_window_state state; + bool update; + unsigned int flags; + int scroll = 0; assert(g); - state.w = g->window; - error = xwimp_get_window_state(&state); + info.w = g->window; + error = xwimp_get_window_info_header_only(&info); if (error) { - LOG(("xwimp_get_window_state: 0x%x: %s", + LOG(("xwimp_get_window_info_header_only: 0x%x: %s", error->errnum, error->errmess)); warn_user("WimpError", error->errmess); return; @@ -924,15 +1122,15 @@ void gui_window_update_extent(struct gui_window *g) /* scroll on toolbar height change */ if (g->toolbar) { - scroll = ro_gui_theme_height_change(g->toolbar); - state.yscroll -= scroll; + scroll = ro_toolbar_height(g->toolbar) - info.extent.y1; + info.yscroll += scroll; } /* only allow a further reformat if we've gained/lost scrollbars */ - flags = state.flags & (wimp_WINDOW_HSCROLL | wimp_WINDOW_VSCROLL); + flags = info.flags & (wimp_WINDOW_HSCROLL | wimp_WINDOW_VSCROLL); update = g->bw->reformat_pending; g->update_extent = true; - ro_gui_window_open(PTR_WIMP_OPEN(&state)); + ro_gui_window_open(PTR_WIMP_OPEN(&info)); state.w = g->window; error = xwimp_get_window_state(&state); @@ -1033,41 +1231,11 @@ void gui_window_hide_pointer(struct gui_window *g) void gui_window_set_url(struct gui_window *g, const char *url) { - wimp_caret caret; - os_error *error; - const char *toolbar_url; - if (!g->toolbar) return; - ro_gui_set_icon_string(g->toolbar->toolbar_handle, - ICON_TOOLBAR_URL, url, true); - ro_gui_force_redraw_icon(g->toolbar->toolbar_handle, - ICON_TOOLBAR_FAVICON); - - /* if the caret is in the address bar, move it to the end */ - error = xwimp_get_caret_position(&caret); - if (error) { - LOG(("xwimp_get_caret_position: 0x%x: %s", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); - return; - } - - if (!(caret.w == g->toolbar->toolbar_handle && - 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(toolbar_url)); - if (error) { - LOG(("xwimp_set_caret_position: 0x%x: %s", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); - } - ro_gui_url_complete_start(g); + ro_toolbar_set_url(g->toolbar, url, true, false); + ro_gui_url_complete_start(g->toolbar); } @@ -1079,10 +1247,10 @@ void gui_window_set_url(struct gui_window *g, const char *url) void gui_window_start_throbber(struct gui_window *g) { - ro_gui_menu_objects_moved(); - ro_gui_prepare_navigate(g); - xos_read_monotonic_time(&g->throbtime); - g->throbber = 0; + ro_gui_window_update_toolbar_buttons(g); + ro_gui_menu_refresh(ro_gui_browser_window_menu); + if (g->toolbar != NULL) + ro_toolbar_start_throbbing(g->toolbar); } @@ -1095,24 +1263,22 @@ 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; - if (g->toolbar) { - strcpy(throb_buf, "throbber0"); - ro_gui_set_icon_string(g->toolbar->toolbar_handle, - ICON_TOOLBAR_THROBBER, throb_buf, true); - if ((g->toolbar->descriptor) && (g->toolbar->descriptor->throbber_redraw)) - ro_gui_force_redraw_icon(g->toolbar->toolbar_handle, - ICON_TOOLBAR_THROBBER); - } + ro_gui_window_update_toolbar_buttons(g); + ro_gui_menu_refresh(ro_gui_browser_window_menu); + if (g->toolbar != NULL) + ro_toolbar_stop_throbbing(g->toolbar); } /** * set favicon */ + void gui_window_set_icon(struct gui_window *g, hlcache_handle *icon) { + if (g == NULL || g->toolbar == NULL) + return; + + ro_toolbar_set_site_favicon(g->toolbar, icon); } /** @@ -1185,9 +1351,10 @@ void gui_window_remove_caret(struct gui_window *g) void gui_window_new_content(struct gui_window *g) { - ro_gui_menu_objects_moved(); - ro_gui_prepare_navigate(g); + ro_gui_menu_refresh(ro_gui_browser_window_menu); + ro_gui_window_update_toolbar_buttons(g); ro_gui_dialog_close_persistent(g->window); + ro_toolbar_set_content_favicon(g->toolbar, g->bw->current_content); } @@ -1233,7 +1400,7 @@ bool gui_window_scroll_start(struct gui_window *g) drag.bbox.y1 = drag.bbox.y0 + (height - (info.visible.y1 - info.visible.y0)); if (g->toolbar) { - int tbar_height = ro_gui_theme_toolbar_full_height(g->toolbar); + int tbar_height = ro_toolbar_full_height(g->toolbar); drag.bbox.y0 -= tbar_height; drag.bbox.y1 -= tbar_height; } @@ -1339,7 +1506,7 @@ bool gui_window_frame_resize_start(struct gui_window *g) /* convert to screen co-ordinates */ top = browser_window_owner(bw); if (top->window->toolbar) - toolbar_height = ro_gui_theme_toolbar_full_height(top->window->toolbar); + toolbar_height = ro_toolbar_full_height(top->window->toolbar); state.w = top->window->window; error = xwimp_get_window_state(&state); if (error) { @@ -1422,16 +1589,111 @@ void gui_window_set_scale(struct gui_window *g, float scale) /** - * Redraws the content for all windows. + * Updates a windows extent. + * + * \param g the gui_window to update + * \param width the minimum width, or -1 to use window width + * \param height the minimum height, or -1 to use window height */ -void ro_gui_window_redraw_all(void) +void gui_window_set_extent(struct gui_window *g, int width, int height) { - struct gui_window *g; - for (g = window_list; g; g = g->next) - gui_window_redraw_window(g); + int screen_width; + int toolbar_height = 0; + hlcache_handle *h; + wimp_window_state state; + os_error *error; + + h = g->bw->current_content; + if (g->toolbar) + toolbar_height = ro_toolbar_full_height(g->toolbar); + + /* get the current state */ + if ((height == -1) || (width == -1)) { + 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; + } + if (width == -1) + width = state.visible.x1 - state.visible.x0; + if (height == -1) { + height = state.visible.y1 - state.visible.y0; + height -= toolbar_height; + } + } + + /* the top-level framed window is a total pain. to get it to maximise + * to the top of the screen we need to fake it having a suitably large + * extent */ + if (g->bw->children && + (g->bw->browser_window_type == BROWSER_WINDOW_NORMAL)) { + ro_gui_screen_size(&screen_width, &height); + if (g->toolbar) + height -= ro_toolbar_full_height(g->toolbar); + height -= ro_get_hscroll_height(g->window); + height -= ro_get_title_height(g->window); + } + if (h) { + width = max(width, content_get_width(h) * 2 * g->bw->scale); + height = max(height, content_get_height(h) * 2 * g->bw->scale); + } + os_box extent = { 0, -height, width, toolbar_height }; + error = xwimp_set_extent(g->window, &extent); + if (error) { + LOG(("xwimp_set_extent: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return; + } +} + + +/** + * Display a menu of options for a form select control. + * + * \param bw browser window containing form control + * \param control form control of type GADGET_SELECT + */ + +void gui_create_form_select_menu(struct browser_window *bw, + struct form_control *control) +{ + os_error *error; + wimp_pointer pointer; + + /* The first time the menu is opened, control bypasses the normal + * Menu Prepare event and so we prepare here. On any re-opens, + * ro_gui_window_prepare_form_select_menu() is called from the + * normal wimp event. + */ + + if (!ro_gui_window_prepare_form_select_menu(bw, control)) + return; + + error = xwimp_get_pointer_info(&pointer); + if (error) { + LOG(("xwimp_get_pointer_info: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + ro_gui_menu_closed(); + return; + } + + gui_form_select_control = control; + ro_gui_menu_create(gui_form_select_menu, + pointer.pos.x, pointer.pos.y, bw->window->window); } + +/* + * RISC OS Wimp Event Handlers + */ + + /** * Handle a Redraw_Window_Request for a browser window. */ @@ -1512,264 +1774,52 @@ void ro_gui_window_redraw(wimp_draw *redraw) } - /** - * Remove all pending update boxes for a window - * - * \param g gui_window + * Open a window using the given wimp_open, handling toolbars and resizing. */ -void ro_gui_window_remove_update_boxes(struct gui_window *g) { - struct update_box *cur; - for (cur = pending_updates; cur != NULL; cur = cur->next) { - if (cur->g == g) - cur->g = NULL; - } -} +void ro_gui_window_open(wimp_open *open) +{ + struct gui_window *g = (struct gui_window *)ro_gui_wimp_event_get_user_data(open->w); + int width = open->visible.x1 - open->visible.x0; + int height = open->visible.y1 - open->visible.y0; + int size, fheight, fwidth, toolbar_height = 0; + bool no_vscroll, no_hscroll; + float new_scale = 0; + hlcache_handle *h; + wimp_window_state state; + os_error *error; + wimp_w parent; + bits linkage; + if (open->next == wimp_TOP && g->iconise_icon >= 0) { + /* window is no longer iconised, release its sprite number */ + iconise_used[g->iconise_icon] = false; + g->iconise_icon = -1; + } -/** - * Redraw any pending update boxes. - */ -void ro_gui_window_update_boxes(void) { - osbool more; - bool use_buffer; - wimp_draw update; - struct rect clip; - os_error *error; - struct update_box *cur; - struct gui_window *g; - const union content_msg_data *data; + h = g->bw->current_content; - for (cur = pending_updates; cur != NULL; cur = cur->next) { - g = cur->g; - if (!g) - continue; + /* get the current flags/nesting state */ + state.w = g->window; + error = xwimp_get_window_state_and_nesting(&state, &parent, &linkage); + if (error) { + LOG(("xwimp_get_window_state: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return; + } - data = &cur->data; - use_buffer = cur->use_buffer; + /* account for toolbar height, if present */ + if (g->toolbar) + toolbar_height = ro_toolbar_full_height(g->toolbar); + height -= toolbar_height; - update.w = g->window; - update.box.x0 = cur->x0; - update.box.y0 = cur->y0; - update.box.x1 = cur->x1; - update.box.y1 = cur->y1; - - error = xwimp_update_window(&update, &more); - if (error) { - LOG(("xwimp_update_window: 0x%x: %s", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); - continue; - } - - /* Set the current redraw gui_window to get options from */ - ro_gui_current_redraw_gui = g; - current_redraw_browser = g->bw; - - plot = ro_plotters; - ro_plot_origin_x = update.box.x0 - update.xscroll; - ro_plot_origin_y = update.box.y1 - update.yscroll; - ro_plot_set_scale(g->bw->scale); - - while (more) { - clip.x0 = (update.clip.x0 - ro_plot_origin_x) / 2; - clip.y0 = (ro_plot_origin_y - update.clip.y1) / 2; - clip.x1 = (update.clip.x1 - ro_plot_origin_x) / 2; - clip.y1 = (ro_plot_origin_y - update.clip.y0) / 2; - - if (use_buffer) - ro_gui_buffer_open(&update); - - browser_window_redraw(g->bw, 0, 0, &clip); - - if (use_buffer) - ro_gui_buffer_close(); - - error = xwimp_get_rectangle(&update, &more); - /* RISC OS 3.7 returns an error here if enough buffer - * was claimed to cause a new dynamic area to be - * created. It doesn't actually stop anything working, - * so we mask it out for now until a better fix is - * found. This appears to be a bug in RISC OS. */ - if (error && !(use_buffer && - error->errnum == error_WIMP_GET_RECT)) { - LOG(("xwimp_get_rectangle: 0x%x: %s", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); - ro_gui_current_redraw_gui = NULL; - current_redraw_browser = NULL; - continue; - } - } - - /* Reset the current redraw gui_window to prevent - * thumbnails from retaining options */ - ro_gui_current_redraw_gui = NULL; - current_redraw_browser = NULL; - } - while (pending_updates) { - cur = pending_updates; - pending_updates = pending_updates->next; - free(cur); - } - -} - - -/** - * Launch a new url in the given window. - * - * \param g gui_window to update - * \param url url to be launched - */ - -void ro_gui_window_launch_url(struct gui_window *g, const char *url) -{ - url_func_result res; - char *url_norm; - - ro_gui_url_complete_close(NULL, 0); - res = url_normalize(url, &url_norm); - if (res == URL_FUNC_OK) { - gui_window_set_url(g, url_norm); - browser_window_go(g->bw, url_norm, 0, true); - free(url_norm); - } -} - - -/** - * Forces all windows to be set to the current theme - */ -void ro_gui_window_update_theme(void) { - struct gui_window *g; - for (g = window_list; g; g = g->next) { - if (g->toolbar) { - if (g->toolbar->editor) - if (!ro_gui_theme_update_toolbar(NULL, g->toolbar->editor)) - g->toolbar->editor = NULL; - if (!ro_gui_theme_update_toolbar(NULL, g->toolbar)) { - ro_gui_theme_destroy_toolbar(g->toolbar); - g->toolbar = NULL; - } - ro_gui_theme_toolbar_editor_sync(g->toolbar); - gui_window_update_extent(g); - } - } -} - - -/** - * Updates a windows extent. - * - * \param g the gui_window to update - * \param width the minimum width, or -1 to use window width - * \param height the minimum height, or -1 to use window height - */ - -void gui_window_set_extent(struct gui_window *g, int width, int height) -{ - int screen_width; - int toolbar_height = 0; - hlcache_handle *h; - wimp_window_state state; - os_error *error; - - h = g->bw->current_content; - if (g->toolbar) - toolbar_height = ro_gui_theme_toolbar_full_height(g->toolbar); - - /* get the current state */ - if ((height == -1) || (width == -1)) { - 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; - } - if (width == -1) - width = state.visible.x1 - state.visible.x0; - if (height == -1) { - height = state.visible.y1 - state.visible.y0; - height -= toolbar_height; - } - } - - /* the top-level framed window is a total pain. to get it to maximise - * to the top of the screen we need to fake it having a suitably large - * extent */ - if (g->bw->children && - (g->bw->browser_window_type == BROWSER_WINDOW_NORMAL)) { - ro_gui_screen_size(&screen_width, &height); - if (g->toolbar) - height -= ro_gui_theme_toolbar_full_height(g->toolbar); - height -= ro_get_hscroll_height(g->window); - height -= ro_get_title_height(g->window); - } - if (h) { - width = max(width, content_get_width(h) * 2 * g->bw->scale); - height = max(height, content_get_height(h) * 2 * g->bw->scale); - } - os_box extent = { 0, -height, width, toolbar_height }; - error = xwimp_set_extent(g->window, &extent); - if (error) { - LOG(("xwimp_set_extent: 0x%x: %s", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); - return; - } -} - - -/** - * Open a window using the given wimp_open, handling toolbars and resizing. - */ - -void ro_gui_window_open(wimp_open *open) -{ - struct gui_window *g = (struct gui_window *)ro_gui_wimp_event_get_user_data(open->w); - int width = open->visible.x1 - open->visible.x0; - int height = open->visible.y1 - open->visible.y0; - int size, fheight, fwidth, toolbar_height = 0; - bool no_vscroll, no_hscroll; - float new_scale = 0; - hlcache_handle *h; - wimp_window_state state; - os_error *error; - wimp_w parent; - bits linkage; - - if (open->next == wimp_TOP && g->iconise_icon >= 0) { - /* window is no longer iconised, release its sprite number */ - iconise_used[g->iconise_icon] = false; - g->iconise_icon = -1; - } - - h = g->bw->current_content; - - /* get the current flags/nesting state */ - state.w = g->window; - error = xwimp_get_window_state_and_nesting(&state, &parent, &linkage); - if (error) { - LOG(("xwimp_get_window_state: 0x%x: %s", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); - return; - } - - /* account for toolbar height, if present */ - if (g->toolbar) - toolbar_height = ro_gui_theme_toolbar_full_height(g->toolbar); - height -= toolbar_height; - - /* work with the state from now on so we can modify flags */ - state.visible = open->visible; - state.xscroll = open->xscroll; - state.yscroll = open->yscroll; - state.next = open->next; + /* work with the state from now on so we can modify flags */ + state.visible = open->visible; + state.xscroll = open->xscroll; + state.yscroll = open->yscroll; + state.next = open->next; /* handle 'auto' scroll bars' and non-fitting scrollbar removal */ if ((g->bw->scrolling == SCROLLING_AUTO) || @@ -1871,7 +1921,7 @@ void ro_gui_window_open(wimp_open *open) } /* first resize stops any flickering by making the URL window on top */ - ro_gui_url_complete_resize(g, PTR_WIMP_OPEN(&state)); + ro_gui_url_complete_resize(g->toolbar, PTR_WIMP_OPEN(&state)); error = xwimp_open_window_nested_with_flags(&state, parent, linkage); if (error) { @@ -1885,9 +1935,9 @@ void ro_gui_window_open(wimp_open *open) if (g->status_bar) ro_gui_status_bar_resize(g->status_bar); if (g->toolbar) { - ro_gui_theme_process_toolbar(g->toolbar, -1); + ro_toolbar_process(g->toolbar, -1, false); /* second resize updates to the new URL bar width */ - ro_gui_url_complete_resize(g, open); + ro_gui_url_complete_resize(g->toolbar, open); } /* set the new scale from a ctrl-resize. this must be done at the end as @@ -1901,7 +1951,9 @@ void ro_gui_window_open(wimp_open *open) /** * Handle wimp closing event */ -void ro_gui_window_close(wimp_w w) { + +void ro_gui_window_close(wimp_w w) +{ struct gui_window *g = (struct gui_window *)ro_gui_wimp_event_get_user_data(w); wimp_pointer pointer; os_error *error; @@ -1950,9 +2002,11 @@ void ro_gui_window_close(wimp_w w) { } else { /* this is pointless if we are about to close the * window */ - if (!destroy) - ro_gui_menu_handle_action(w, - BROWSER_NAVIGATE_UP, true); + if (!destroy && g->bw != NULL && + g->bw->current_content != NULL) + ro_gui_window_navigate_up(g->bw->window, + content_get_url( + g->bw->current_content)); } } else @@ -1964,606 +2018,347 @@ void ro_gui_window_close(wimp_w w) { /** - * Destroy all browser windows. + * Handle Mouse_Click events in a browser window. This should never see + * Menu clicks, as these will be routed to the menu handlers. + * + * \param *pointer details of mouse click + * \return true if click handled, false otherwise */ -void ro_gui_window_quit(void) +bool ro_gui_window_click(wimp_pointer *pointer) { - struct gui_window *cur; + struct gui_window *g; + os_coord pos; - while (window_list) { - cur = window_list; - window_list = window_list->next; + /* We should never see Menu clicks. */ - /* framesets and iframes are destroyed by their parents */ - if (!cur->bw->parent) - browser_window_destroy(cur->bw); - } -} + if (pointer->buttons == wimp_CLICK_MENU) + return false; + g = (struct gui_window *) ro_gui_wimp_event_get_user_data(pointer->w); -/** - * Animate the "throbbers" of all browser windows. - */ + /* try to close url-completion */ + ro_gui_url_complete_close(); -void ro_gui_throb(void) -{ - os_t t; - struct gui_window *g, *top_g; - struct browser_window *top; - char throb_buf[12]; + /* set input focus */ + if (pointer->buttons == wimp_CLICK_SELECT || + pointer->buttons == wimp_CLICK_ADJUST) + gui_window_place_caret(g, -100, -100, 0); - xos_read_monotonic_time(&t); + if (ro_gui_window_to_window_pos(g, pointer->pos.x, pointer->pos.y, &pos)) + browser_window_mouse_click(g->bw, + ro_gui_mouse_click_state(pointer->buttons, + wimp_BUTTON_CLICK_DRAG), + pos.x, pos.y); - for (g = window_list; g; g = g->next) { - if (!g->bw->throbbing) - continue; - for (top = g->bw; top->parent; top = top->parent); - top_g = top->window; - if (!top_g->toolbar || !top_g->toolbar->display_throbber || - !top_g->toolbar->descriptor || - !top_g->toolbar->descriptor->theme || - (t < top_g->throbtime + 10)) - continue; - top_g->throbtime = t; - top_g->throbber++; - if (top_g->toolbar->descriptor->theme->throbber_frames < top_g->throbber) - top_g->throbber = 1; - sprintf(throb_buf, "throbber%i", top_g->throbber); - ro_gui_set_icon_string(top_g->toolbar->toolbar_handle, - ICON_TOOLBAR_THROBBER, throb_buf, true); - if (top_g->toolbar->descriptor->throbber_redraw) - ro_gui_force_redraw_icon(top_g->toolbar->toolbar_handle, - ICON_TOOLBAR_THROBBER); - } + return true; } /** - * Convert a RISC OS window handle to a gui_window. - * - * \param w RISC OS window handle - * \return pointer to a structure if found, 0 otherwise + * Process Key_Pressed events in a browser window. */ -struct gui_window *ro_gui_window_lookup(wimp_w window) +bool ro_gui_window_keypress(wimp_key *key) { - struct gui_window *g; - for (g = window_list; g; g = g->next) - if (g->window == window) - return g; - return 0; -} + struct gui_window *g; + hlcache_handle *h; + os_error *error; + wimp_pointer pointer; + uint32_t c = (uint32_t) key->c; + + g = (struct gui_window *) ro_gui_wimp_event_get_user_data(key->w); + if (g == NULL) + return false; + h = g->bw->current_content; -/** - * Convert a toolbar RISC OS window handle to a gui_window. - * - * \param w RISC OS window handle of a toolbar - * \return pointer to a structure if found, 0 otherwise - */ - -struct gui_window *ro_gui_toolbar_lookup(wimp_w window) -{ - struct gui_window *g; - for (g = window_list; g; g = g->next) { - if ((g->toolbar) && ((g->toolbar->toolbar_handle == window) || - ((g->toolbar->editor) && - (g->toolbar->editor->toolbar_handle == window)))) - return g; - } - return 0; -} - - -/** - * Handle pointer movements in a browser window. - * - * \param g browser window that the pointer is in - * \param pointer new mouse position - */ - -void ro_gui_window_mouse_at(struct gui_window *g, wimp_pointer *pointer) -{ - os_coord pos; - - if (ro_gui_window_to_window_pos(g, pointer->pos.x, pointer->pos.y, &pos)) - browser_window_mouse_track(g->bw, - ro_gui_mouse_drag_state(pointer->buttons, - wimp_BUTTON_CLICK_DRAG), - pos.x, pos.y); -} - - -/** - * Process Mouse_Click events in a toolbar. - */ - -bool ro_gui_toolbar_click(wimp_pointer *pointer) -{ - struct gui_window *g = ro_gui_toolbar_lookup(pointer->w); - struct browser_window *new_bw; - - /* toolbars in the options window have no gui_window */ - if (!g) - return true; - - /* try to close url-completion */ - ro_gui_url_complete_close(g, pointer->i); - - /* Handle Menu clicks */ - if (pointer->buttons == wimp_CLICK_MENU) { - ro_gui_menu_create(browser_toolbar_menu, pointer->pos.x, - pointer->pos.y, g->window, true); - return true; - } - - /* Handle toolbar edits */ - if ((g->toolbar->editor) && (pointer->i < ICON_TOOLBAR_URL)) { - ro_gui_theme_toolbar_editor_click(g->toolbar, pointer); - return true; + error = xwimp_get_pointer_info(&pointer); + if (error) { + LOG(("xwimp_get_pointer_info: 0x%x: %s\n", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return false; } - /* Handle the buttons appropriately */ - switch (pointer->i) { - case ICON_TOOLBAR_BACK: - if (pointer->buttons == wimp_CLICK_ADJUST) { - new_bw = browser_window_create(NULL, - g->bw, NULL, false, false); - ro_gui_menu_handle_action( - new_bw->window->window, - BROWSER_NAVIGATE_BACK, true); - } else { - ro_gui_menu_handle_action(g->window, - BROWSER_NAVIGATE_BACK, true); - } - break; - - case ICON_TOOLBAR_FORWARD: - if (pointer->buttons == wimp_CLICK_ADJUST) { - new_bw = browser_window_create(NULL, - g->bw, NULL, false, false); - ro_gui_menu_handle_action( - new_bw->window->window, - BROWSER_NAVIGATE_FORWARD, true); - } else { - ro_gui_menu_handle_action(g->window, - BROWSER_NAVIGATE_FORWARD, true); - } - break; + /* First send the key to the browser window, eg. form fields. */ - case ICON_TOOLBAR_STOP: - ro_gui_menu_handle_action(g->window, - BROWSER_NAVIGATE_STOP, true); - break; + if ((unsigned)c < 0x20 || (0x7f <= c && c <= 0x9f) || + (c & IS_WIMP_KEY)) { + /* Munge control keys into unused control chars */ + /* We can't map onto 1->26 (reserved for ctrl+ + That leaves 27->31 and 128->159 */ + switch (c & ~IS_WIMP_KEY) { + case wimp_KEY_TAB: c = 9; break; + case wimp_KEY_SHIFT | wimp_KEY_TAB: c = 11; break; - case ICON_TOOLBAR_RELOAD: - if (pointer->buttons == wimp_CLICK_SELECT) - ro_gui_menu_handle_action(g->window, - BROWSER_NAVIGATE_RELOAD, true); - else if (pointer->buttons == wimp_CLICK_ADJUST) - ro_gui_menu_handle_action(g->window, - BROWSER_NAVIGATE_RELOAD_ALL, - true); + /* cursor movement keys */ + case wimp_KEY_HOME: + case wimp_KEY_CONTROL | wimp_KEY_LEFT: + c = KEY_LINE_START; break; - - case ICON_TOOLBAR_HISTORY: - if (pointer->buttons == wimp_CLICK_SELECT) - ro_gui_menu_handle_action(g->window, - HISTORY_SHOW_LOCAL, true); + case wimp_KEY_END: + if (os_version >= RISCOS5) + c = KEY_LINE_END; else - ro_gui_menu_handle_action(g->window, - HISTORY_SHOW_GLOBAL, true); + c = KEY_DELETE_RIGHT; break; - case ICON_TOOLBAR_HOME: - ro_gui_menu_handle_action(g->window, - BROWSER_NAVIGATE_HOME, true); + case wimp_KEY_CONTROL | wimp_KEY_RIGHT: c = KEY_LINE_END; break; + case wimp_KEY_CONTROL | wimp_KEY_UP: c = KEY_TEXT_START; break; + case wimp_KEY_CONTROL | wimp_KEY_DOWN: c = KEY_TEXT_END; break; + case wimp_KEY_SHIFT | wimp_KEY_LEFT: c = KEY_WORD_LEFT ; break; + case wimp_KEY_SHIFT | wimp_KEY_RIGHT: c = KEY_WORD_RIGHT; break; + case wimp_KEY_SHIFT | wimp_KEY_UP: c = KEY_PAGE_UP; break; + case wimp_KEY_SHIFT | wimp_KEY_DOWN: c = KEY_PAGE_DOWN; break; + case wimp_KEY_LEFT: c = KEY_LEFT; break; + case wimp_KEY_RIGHT: c = KEY_RIGHT; break; + case wimp_KEY_UP: c = KEY_UP; break; + case wimp_KEY_DOWN: c = KEY_DOWN; break; + + /* editing */ + case wimp_KEY_CONTROL | wimp_KEY_END: + c = KEY_DELETE_LINE_END; break; - case ICON_TOOLBAR_SEARCH: - ro_gui_menu_handle_action(g->window, - BROWSER_FIND_TEXT, true); - break; - case ICON_TOOLBAR_SCALE: - ro_gui_menu_handle_action(g->window, - BROWSER_SCALE_VIEW, true); + case wimp_KEY_DELETE: + if (ro_gui_ctrl_pressed()) + c = KEY_DELETE_LINE_START; + else if (os_version < RISCOS5) + c = KEY_DELETE_LEFT; break; - case ICON_TOOLBAR_BOOKMARK: - if (pointer->buttons == wimp_CLICK_ADJUST) - ro_gui_menu_handle_action(g->window, - HOTLIST_ADD_URL, true); - else - ro_gui_menu_handle_action(g->window, - HOTLIST_SHOW, true); + default: break; + } + } - case ICON_TOOLBAR_SAVE: - if (pointer->buttons == wimp_CLICK_ADJUST) - ro_gui_menu_handle_action(g->window, - BROWSER_SAVE_COMPLETE, true); - else - ro_gui_menu_handle_action(g->window, - BROWSER_SAVE, true); - break; - case ICON_TOOLBAR_PRINT: - ro_gui_menu_handle_action(g->window, - BROWSER_PRINT, true); - break; - case ICON_TOOLBAR_UP: - if (pointer->buttons == wimp_CLICK_ADJUST) { - if (g->bw && g->bw->current_content) { - hlcache_handle *h = - g->bw->current_content; - new_bw = browser_window_create(NULL, - g->bw, NULL, false, - false); - /* do it without loading the content - * into the new window */ - ro_gui_window_navigate_up( - new_bw->window, - content_get_url(h)); - } - } else { - ro_gui_menu_handle_action(g->window, - BROWSER_NAVIGATE_UP, true); - } - break; - case ICON_TOOLBAR_URL: - if (pointer->buttons & - (wimp_DRAG_SELECT | wimp_DRAG_ADJUST)) { - if (g->bw->current_content) { - hlcache_handle *h = - g->bw->current_content; - gui_save_type save_type; - - if (ro_gui_shift_pressed()) - save_type = GUI_SAVE_LINK_URL; - else - save_type = GUI_SAVE_LINK_TEXT; - - ro_gui_drag_save_link(save_type, - content_get_url(h), - content_get_title(h), - g); - } - } - else - ro_gui_url_complete_start(g); - break; - case ICON_TOOLBAR_SUGGEST: - ro_gui_popup_menu(url_suggest_menu, - g->toolbar->toolbar_handle, - ICON_TOOLBAR_SUGGEST); - break; + if (!(c & IS_WIMP_KEY)) { + if (browser_window_key_press(g->bw, c)) + return true; } + + ro_gui_window_handle_local_keypress(g, key, false); + return true; } /** - * Handle Mouse_Click events in a browser window. + * Callback handler for keypresses within browser window toolbars. * - * \param pointer details of mouse click - * \return true if click handled, false otherwise + * \param *data Client data, pointing to the GUI Window. + * \param *key The keypress data. */ -bool ro_gui_window_click(wimp_pointer *pointer) +void ro_gui_window_toolbar_keypress(void *data, wimp_key *key) { - struct gui_window *g; - os_coord pos; - - g = (struct gui_window *)ro_gui_wimp_event_get_user_data(pointer->w); - - /* try to close url-completion */ - ro_gui_url_complete_close(g, pointer->i); - - /* set input focus */ - if (pointer->buttons == wimp_CLICK_SELECT || - pointer->buttons == wimp_CLICK_ADJUST) - gui_window_place_caret(g, -100, -100, 0); + struct gui_window *g = (struct gui_window *) data; - if (pointer->buttons == wimp_CLICK_MENU) { - ro_gui_menu_create(browser_menu, pointer->pos.x, pointer->pos.y, pointer->w, true); - } else { - if (ro_gui_window_to_window_pos(g, pointer->pos.x, pointer->pos.y, &pos)) - browser_window_mouse_click(g->bw, - ro_gui_mouse_click_state(pointer->buttons, - wimp_BUTTON_CLICK_DRAG), - pos.x, pos.y); - } - return true; + if (g != NULL) + ro_gui_window_handle_local_keypress(g, key, true); } /** - * Process Key_Pressed events in a browser window. + * Handle keypresses within the RISC OS GUI: this is to be called after the + * core has been given a chance to act, or on keypresses in the toolbar where + * the core doesn't get involved. + * + * \param *g The gui window to which the keypress applies. + * \param *key The keypress data. + * \param is_toolbar true if the keypress is from a toolbar; + * else false. */ -bool ro_gui_window_keypress(wimp_key *key) +void ro_gui_window_handle_local_keypress(struct gui_window *g, wimp_key *key, + bool is_toolbar) { - struct gui_window *g; - bool toolbar; - hlcache_handle *h; - wimp_window_state state; - int y; - const char *toolbar_url; - os_error *error; - wimp_pointer pointer; - float scale; - uint32_t c = (uint32_t) key->c; - - /* Find gui window */ - if ((g = ro_gui_window_lookup(key->w)) != NULL) { - toolbar = false; - } else if ((g = ro_gui_toolbar_lookup(key->w)) != NULL) { - toolbar = true; - } else { - /* nothing to do with us */ - return false; - } + hlcache_handle *h; + wimp_window_state state; + int y; + const char *toolbar_url; + os_error *error; + float scale; + uint32_t c = (uint32_t) key->c; + + if (g == NULL) + return; h = g->bw->current_content; - error = xwimp_get_pointer_info(&pointer); - if (error) { - LOG(("xwimp_get_pointer_info: 0x%x: %s\n", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); - return false; - } + switch (c) { + case IS_WIMP_KEY + wimp_KEY_F1: /* Help. */ + ro_gui_open_help_page("documentation/index"); + return; - /* First send the key to the browser window, eg. form fields. */ - if (!toolbar) { - if ((unsigned)c < 0x20 || (0x7f <= c && c <= 0x9f) || - (c & IS_WIMP_KEY)) { - /* Munge control keys into unused control chars */ - /* We can't map onto 1->26 (reserved for ctrl+ - That leaves 27->31 and 128->159 */ - switch (c & ~IS_WIMP_KEY) { - case wimp_KEY_TAB: c = 9; break; - case wimp_KEY_SHIFT | wimp_KEY_TAB: c = 11; break; - - /* cursor movement keys */ - case wimp_KEY_HOME: - case wimp_KEY_CONTROL | wimp_KEY_LEFT: - c = KEY_LINE_START; - break; - case wimp_KEY_END: - if (os_version >= RISCOS5) - c = KEY_LINE_END; - else - c = KEY_DELETE_RIGHT; - break; - case wimp_KEY_CONTROL | wimp_KEY_RIGHT: c = KEY_LINE_END; break; - case wimp_KEY_CONTROL | wimp_KEY_UP: c = KEY_TEXT_START; break; - case wimp_KEY_CONTROL | wimp_KEY_DOWN: c = KEY_TEXT_END; break; - case wimp_KEY_SHIFT | wimp_KEY_LEFT: c = KEY_WORD_LEFT ; break; - case wimp_KEY_SHIFT | wimp_KEY_RIGHT: c = KEY_WORD_RIGHT; break; - case wimp_KEY_SHIFT | wimp_KEY_UP: c = KEY_PAGE_UP; break; - case wimp_KEY_SHIFT | wimp_KEY_DOWN: c = KEY_PAGE_DOWN; break; - case wimp_KEY_LEFT: c = KEY_LEFT; break; - case wimp_KEY_RIGHT: c = KEY_RIGHT; break; - case wimp_KEY_UP: c = KEY_UP; break; - case wimp_KEY_DOWN: c = KEY_DOWN; break; - - /* editing */ - case wimp_KEY_CONTROL | wimp_KEY_END: - c = KEY_DELETE_LINE_END; - break; - case wimp_KEY_DELETE: - if (ro_gui_ctrl_pressed()) - c = KEY_DELETE_LINE_START; - else if (os_version < RISCOS5) - c = KEY_DELETE_LEFT; - break; + case IS_WIMP_KEY + wimp_KEY_CONTROL + wimp_KEY_F1: + ro_gui_window_action_page_info(g); + return; - default: - break; - } - } + case IS_WIMP_KEY + wimp_KEY_F2: + if (g->toolbar == NULL) + return; + ro_gui_url_complete_close(); + ro_toolbar_set_url(g->toolbar, "www.", true, true); + ro_gui_url_complete_start(g->toolbar); + ro_gui_url_complete_keypress(g->toolbar, wimp_KEY_DOWN); + return; - if (!(c & IS_WIMP_KEY)) { - if (browser_window_key_press(g->bw, c)) - return true; - } + case IS_WIMP_KEY + wimp_KEY_CONTROL + wimp_KEY_F2: + /* Close window. */ + ro_gui_url_complete_close(); + browser_window_destroy(g->bw); + return; - /* Reset c to incoming character / key code - * as we may have corrupted it above */ - c = (uint32_t) key->c; - } + case 19: /* Ctrl + S */ + case IS_WIMP_KEY + wimp_KEY_F3: + ro_gui_window_action_save(g, GUI_SAVE_SOURCE); + return; - switch (c) { - case IS_WIMP_KEY + wimp_KEY_F1: /* Help. */ - return ro_gui_menu_handle_action(g->window, - HELP_OPEN_CONTENTS, false); + case IS_WIMP_KEY + wimp_KEY_CONTROL + wimp_KEY_F3: + ro_gui_window_action_save(g, GUI_SAVE_TEXT); + return; - case IS_WIMP_KEY + wimp_KEY_CONTROL + wimp_KEY_F1: - return ro_gui_menu_handle_action(g->window, - BROWSER_PAGE_INFO, false); + case IS_WIMP_KEY + wimp_KEY_SHIFT + wimp_KEY_F3: + ro_gui_window_action_save(g, GUI_SAVE_COMPLETE); + return; - case IS_WIMP_KEY + wimp_KEY_F2: - if (!g->toolbar) - return false; - ro_gui_url_complete_close(NULL, 0); - ro_gui_set_icon_string(g->toolbar->toolbar_handle, - ICON_TOOLBAR_URL, "www.", true); - xwimp_set_caret_position(g->toolbar->toolbar_handle, - ICON_TOOLBAR_URL, 0, 0, -1, 4); - ro_gui_url_complete_start(g); - ro_gui_url_complete_keypress(g, wimp_KEY_DOWN); - return true; + case IS_WIMP_KEY + wimp_KEY_CONTROL + wimp_KEY_SHIFT + wimp_KEY_F3: + ro_gui_window_action_save(g, GUI_SAVE_DRAW); + return; - case IS_WIMP_KEY + wimp_KEY_CONTROL + wimp_KEY_F2: - /* Close window. */ - ro_gui_url_complete_close(NULL, 0); - browser_window_destroy(g->bw); - return true; + case 6: /* Ctrl + F */ + case IS_WIMP_KEY + wimp_KEY_F4: /* Search */ + ro_gui_window_action_search(g); + return; - case 19: /* Ctrl + S */ - case IS_WIMP_KEY + wimp_KEY_F3: - return ro_gui_menu_handle_action(g->window, - BROWSER_SAVE, false); - - case IS_WIMP_KEY + wimp_KEY_CONTROL + wimp_KEY_F3: - return ro_gui_menu_handle_action(g->window, - BROWSER_EXPORT_TEXT, false); - - case IS_WIMP_KEY + wimp_KEY_SHIFT + wimp_KEY_F3: - return ro_gui_menu_handle_action(g->window, - BROWSER_SAVE_COMPLETE, false); - - case IS_WIMP_KEY + wimp_KEY_CONTROL + wimp_KEY_SHIFT + - wimp_KEY_F3: - return ro_gui_menu_handle_action(g->window, - BROWSER_EXPORT_DRAW, false); - - case 6: /* Ctrl + F */ - case IS_WIMP_KEY + wimp_KEY_F4: /* Search */ - return ro_gui_menu_handle_action(g->window, - BROWSER_FIND_TEXT, false); - - case IS_WIMP_KEY + wimp_KEY_F5: /* Reload */ - return ro_gui_menu_handle_action(g->window, - BROWSER_NAVIGATE_RELOAD, false); - - case 18: /* Ctrl+R (Full reload) */ - case IS_WIMP_KEY + wimp_KEY_CONTROL + wimp_KEY_F5: - /* Full reload */ - return ro_gui_menu_handle_action(g->window, - BROWSER_NAVIGATE_RELOAD_ALL, false); - - case IS_WIMP_KEY + wimp_KEY_F6: /* Hotlist */ - return ro_gui_menu_handle_action(g->window, - HOTLIST_SHOW, false); - - case IS_WIMP_KEY + wimp_KEY_F7: /* Show local history */ - return ro_gui_menu_handle_action(g->window, - HISTORY_SHOW_LOCAL, false); - - case IS_WIMP_KEY + wimp_KEY_CONTROL + wimp_KEY_F7: - /* Show global history */ - return ro_gui_menu_handle_action(g->window, - HISTORY_SHOW_GLOBAL, false); - - case IS_WIMP_KEY + wimp_KEY_F8: /* View source */ - ro_gui_view_source(h); - return true; + case IS_WIMP_KEY + wimp_KEY_F5: /* Reload */ + if (g->bw != NULL) + browser_window_reload(g->bw, false); + return; - case IS_WIMP_KEY + wimp_KEY_F9: - /* Dump content for debugging. */ - ro_gui_dump_content(h); - return true; + case 18: /* Ctrl+R (Full reload) */ + case IS_WIMP_KEY + wimp_KEY_CONTROL + wimp_KEY_F5: + if (g->bw != NULL) + browser_window_reload(g->bw, true); + return; - case IS_WIMP_KEY + wimp_KEY_CONTROL + wimp_KEY_F9: - urldb_dump(); - return true; + case IS_WIMP_KEY + wimp_KEY_F6: /* Hotlist */ + ro_gui_hotlist_open(); + return; - case IS_WIMP_KEY + wimp_KEY_CONTROL + wimp_KEY_SHIFT + - wimp_KEY_F9: - talloc_report_full(0, stderr); - return true; + case IS_WIMP_KEY + wimp_KEY_F7: /* Show local history */ + ro_gui_window_action_local_history(g); + return; - case IS_WIMP_KEY + wimp_KEY_F11: /* Zoom */ - return ro_gui_menu_handle_action(g->window, - BROWSER_SCALE_VIEW, false); + case IS_WIMP_KEY + wimp_KEY_CONTROL + wimp_KEY_F7: + /* Show global history */ + ro_gui_global_history_open(); + return; - case IS_WIMP_KEY + wimp_KEY_SHIFT + wimp_KEY_F11: - /* Toggle display of box outlines. */ - html_redraw_debug = !html_redraw_debug; - gui_window_redraw_window(g); - return true; + case IS_WIMP_KEY + wimp_KEY_F8: /* View source */ + ro_gui_view_source(h); + return; - case wimp_KEY_RETURN: - if (!toolbar) - break; - toolbar_url = ro_gui_get_icon_string( - g->toolbar->toolbar_handle, - ICON_TOOLBAR_URL); - ro_gui_window_launch_url(g, toolbar_url); - return true; + case IS_WIMP_KEY + wimp_KEY_F9: + /* Dump content for debugging. */ + ro_gui_dump_content(h); + return; - case wimp_KEY_ESCAPE: - if (ro_gui_url_complete_close(NULL, 0)) { - ro_gui_url_complete_start(g); - return true; - } - return ro_gui_menu_handle_action(g->window, - BROWSER_NAVIGATE_STOP, false); + case IS_WIMP_KEY + wimp_KEY_CONTROL + wimp_KEY_F9: + urldb_dump(); + return; - case 8: /* CTRL+H / Backspace */ - if (toolbar) - return ro_gui_url_complete_keypress(g, c); - break; + case IS_WIMP_KEY + wimp_KEY_CONTROL + wimp_KEY_SHIFT + wimp_KEY_F9: + talloc_report_full(0, stderr); + return; - case 14: /* CTRL+N */ - return ro_gui_menu_handle_action(g->window, - BROWSER_NEW_WINDOW, false); + case IS_WIMP_KEY + wimp_KEY_F11: /* Zoom */ + ro_gui_window_action_zoom(g); + return; - case 17: /* CTRL+Q (Zoom out) */ - case 23: /* CTRL+W (Zoom in) */ - if (!h) - break; - scale = g->bw->scale; - if (ro_gui_shift_pressed() && c == 17) - scale = g->bw->scale - 0.1; - else if (ro_gui_shift_pressed() && c == 23) - scale = g->bw->scale + 0.1; - else if (c == 17) { - for (int i = SCALE_SNAP_TO_SIZE - 1; - i >= 0; i--) - if (scale_snap_to[i] < - g->bw->scale) { - scale = scale_snap_to[i]; - break; - } - } else { - for (unsigned int i = 0; - i < SCALE_SNAP_TO_SIZE; i++) - if (scale_snap_to[i] > - g->bw->scale) { - scale = scale_snap_to[i]; - break; - } - } - if (scale < scale_snap_to[0]) - scale = scale_snap_to[0]; - if (scale > scale_snap_to[SCALE_SNAP_TO_SIZE - 1]) - scale = scale_snap_to[SCALE_SNAP_TO_SIZE - 1]; - if (g->bw->scale != scale) { - browser_window_set_scale(g->bw, scale, true); -// g->reformat_pending = true; -// if ((h) && (content_get_type(h) != CONTENT_HTML)) -// browser_window_update(g->bw, false); -// browser_reformat_pending = true; - } - return true; + case IS_WIMP_KEY + wimp_KEY_SHIFT + wimp_KEY_F11: + /* Toggle display of box outlines. */ + html_redraw_debug = !html_redraw_debug; + gui_window_redraw_window(g); + return; - case IS_WIMP_KEY + wimp_KEY_PRINT: - return ro_gui_menu_handle_action(g->window, - BROWSER_PRINT, false); + case wimp_KEY_RETURN: + if (is_toolbar) { + toolbar_url = ro_toolbar_get_url(g->toolbar); + if (toolbar_url != NULL) + ro_gui_window_launch_url(g, toolbar_url); + } + return; - case IS_WIMP_KEY | wimp_KEY_LEFT: - case IS_WIMP_KEY | wimp_KEY_RIGHT: - case IS_WIMP_KEY | wimp_KEY_CONTROL | wimp_KEY_LEFT: - case IS_WIMP_KEY | wimp_KEY_CONTROL | wimp_KEY_RIGHT: - if (toolbar) - return false; - break; - case IS_WIMP_KEY + wimp_KEY_UP: - case IS_WIMP_KEY + wimp_KEY_DOWN: - case IS_WIMP_KEY + wimp_KEY_PAGE_UP: - case IS_WIMP_KEY + wimp_KEY_PAGE_DOWN: - case wimp_KEY_HOME: - case IS_WIMP_KEY | wimp_KEY_CONTROL | wimp_KEY_UP: - case IS_WIMP_KEY + wimp_KEY_END: - case IS_WIMP_KEY | wimp_KEY_CONTROL | wimp_KEY_DOWN: - if (toolbar) - return ro_gui_url_complete_keypress(g, c); + case wimp_KEY_ESCAPE: + if (ro_gui_url_complete_close()) { + ro_gui_url_complete_start(g->toolbar); + return; + } + + if (g->bw != NULL) + browser_window_stop(g->bw); + return; + + case 14: /* CTRL+N */ + ro_gui_window_action_new_window(g); + return; + + case 17: /* CTRL+Q (Zoom out) */ + case 23: /* CTRL+W (Zoom in) */ + if (!h) break; - default: - if (toolbar) - return ro_gui_url_complete_keypress(g, c); - return false; + scale = g->bw->scale; + if (ro_gui_shift_pressed() && c == 17) + scale = g->bw->scale - 0.1; + else if (ro_gui_shift_pressed() && c == 23) + scale = g->bw->scale + 0.1; + else if (c == 17) { + for (int i = SCALE_SNAP_TO_SIZE - 1; i >= 0; i--) + if (scale_snap_to[i] < g->bw->scale) { + scale = scale_snap_to[i]; + break; + } + } else { + for (unsigned int i = 0; i < SCALE_SNAP_TO_SIZE; i++) + if (scale_snap_to[i] > g->bw->scale) { + scale = scale_snap_to[i]; + break; + } + } + if (scale < scale_snap_to[0]) + scale = scale_snap_to[0]; + if (scale > scale_snap_to[SCALE_SNAP_TO_SIZE - 1]) + scale = scale_snap_to[SCALE_SNAP_TO_SIZE - 1]; + if (g->bw->scale != scale) { + browser_window_set_scale(g->bw, scale, true); +// g->reformat_pending = true; +// if ((h) && (content_get_type(h) != CONTENT_HTML)) +// browser_window_update(g->bw, false); +// browser_reformat_pending = true; + } + return; + + case IS_WIMP_KEY + wimp_KEY_PRINT: + ro_gui_window_action_print(g); + return; + + case IS_WIMP_KEY | wimp_KEY_LEFT: + case IS_WIMP_KEY | wimp_KEY_RIGHT: + case IS_WIMP_KEY | wimp_KEY_CONTROL | wimp_KEY_LEFT: + case IS_WIMP_KEY | wimp_KEY_CONTROL | wimp_KEY_RIGHT: + if (is_toolbar) + return; + break; + case IS_WIMP_KEY + wimp_KEY_UP: + case IS_WIMP_KEY + wimp_KEY_DOWN: + case IS_WIMP_KEY + wimp_KEY_PAGE_UP: + case IS_WIMP_KEY + wimp_KEY_PAGE_DOWN: + case wimp_KEY_HOME: + case IS_WIMP_KEY | wimp_KEY_CONTROL | wimp_KEY_UP: + case IS_WIMP_KEY + wimp_KEY_END: + default: + break; } state.w = g->window; @@ -2571,12 +2366,12 @@ bool ro_gui_window_keypress(wimp_key *key) if (error) { LOG(("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess)); - return true; + return; } y = state.visible.y1 - state.visible.y0 - 32; if (g->toolbar) - y -= ro_gui_theme_toolbar_full_height(g->toolbar); + y -= ro_toolbar_full_height(g->toolbar); switch (c) { case IS_WIMP_KEY | wimp_KEY_LEFT: @@ -2618,646 +2413,2235 @@ bool ro_gui_window_keypress(wimp_key *key) LOG(("xwimp_open_window: 0x%x: %s", error->errnum, error->errmess)); } - - return true; } /** - * Process Scroll_Request events. + * Prepare the browser window menu for (re-)opening + * + * \param w The window owning the menu. + * \param i The icon owning the menu. + * \param *menu The menu about to be opened. + * \param *pointer Pointer to the relevant wimp event block, or + * NULL for an Adjust click. + * \return true if the event was handled; else false. */ -void ro_gui_scroll_request(wimp_scroll *scroll) + +bool ro_gui_window_menu_prepare(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_pointer *pointer) { - struct gui_window *g = ro_gui_window_lookup(scroll->w); + struct gui_window *g; + struct browser_window *bw; + hlcache_handle *h; + struct toolbar *toolbar; + bool export_sprite, export_draw; + os_coord pos; + + g = (struct gui_window *) ro_gui_wimp_event_get_user_data(w); + toolbar = g->toolbar; + bw = g->bw; + h = bw->current_content; - if (g && g->bw->current_content && ro_gui_shift_pressed()) { - /* extended scroll request with shift held down; change zoom */ - float scale, inc; + /* If this is the form select menu, handle it now and then exit. + * Otherwise, carry on to the main browser window menu. + */ - if (scroll->ymin & 3) - inc = 0.02; /* RO5 sends the msg 5 times; - * don't ask me why */ - else - inc = (1 << (ABS(scroll->ymin)>>2)) / 20.0F; + if (menu == gui_form_select_menu) { + return ro_gui_window_prepare_form_select_menu(g->bw, + gui_form_select_control); + } - if (scroll->ymin > 0) { - scale = g->bw->scale + inc; - if (scale > scale_snap_to[SCALE_SNAP_TO_SIZE - 1]) - scale = scale_snap_to[SCALE_SNAP_TO_SIZE - 1]; - } else { - scale = g->bw->scale - inc; - if (scale < scale_snap_to[0]) - scale = scale_snap_to[0]; - } - if (g->bw->scale != scale) - browser_window_set_scale(g->bw, scale, true); - } else { - int x = scroll->visible.x1 - scroll->visible.x0 - 32; - int y = scroll->visible.y1 - scroll->visible.y0 - 32; - os_error *error; + if (menu != ro_gui_browser_window_menu) + return false; - if (g && g->toolbar) - y -= ro_gui_theme_toolbar_full_height(g->toolbar); + /* If this is a new opening for the browser window menu (ie. not for a + * toolbar menu), get details of the object under the pointer. + */ - switch (scroll->xmin) { - case wimp_SCROLL_PAGE_LEFT: - scroll->xscroll -= x; + if (pointer != NULL && g->window == w) { + ro_gui_url_complete_close(); + + current_menu_object = NULL; + current_menu_url = NULL; + + if (h != NULL && + ro_gui_window_to_window_pos(g, pointer->pos.x, + pointer->pos.y, &pos)) { + switch (content_get_type(h)) { + case CONTENT_HTML: { + struct box *box; + box = box_object_at_point(h, pos.x, pos.y); + current_menu_object = box ? box->object : NULL; + box = box_href_at_point(h, pos.x, pos.y); + current_menu_url = box ? box->href : NULL; + } break; - case wimp_SCROLL_COLUMN_LEFT: - scroll->xscroll -= 32; - break; - case wimp_SCROLL_COLUMN_RIGHT: - scroll->xscroll += 32; - break; - case wimp_SCROLL_PAGE_RIGHT: - scroll->xscroll += x; + case CONTENT_TEXTPLAIN: + /* no object, no url */ break; default: - scroll->xscroll += (x * (scroll->xmin>>2)) >> 2; + current_menu_object = h; break; + } } + } - switch (scroll->ymin) { - case wimp_SCROLL_PAGE_UP: - scroll->yscroll += y; - break; - case wimp_SCROLL_LINE_UP: - scroll->yscroll += 32; - break; - case wimp_SCROLL_LINE_DOWN: - scroll->yscroll -= 32; - break; - case wimp_SCROLL_PAGE_DOWN: - scroll->yscroll -= y; - break; - default: - scroll->yscroll += (y * (scroll->ymin>>2)) >> 2; - break; - } + /* Shade menu entries according to the state of the window and object + * under the pointer. + */ - error = xwimp_open_window((wimp_open *) scroll); - if (error) { - LOG(("xwimp_open_window: 0x%x: %s", - error->errnum, error->errmess)); - } - } -} + /* Toolbar (Sub)Menu */ + ro_gui_menu_set_entry_shaded(menu, TOOLBAR_BUTTONS, + ro_toolbar_menu_option_shade(toolbar)); + ro_gui_menu_set_entry_ticked(menu, TOOLBAR_BUTTONS, + ro_toolbar_menu_buttons_tick(toolbar)); -/** - * Convert x,y screen co-ordinates into window co-ordinates. - * - * \param g gui window - * \param x x ordinate - * \param y y ordinate - * \param pos receives position in window co-ordinatates - * \return true iff conversion successful - */ + ro_gui_menu_set_entry_shaded(menu, TOOLBAR_ADDRESS_BAR, + ro_toolbar_menu_edit_shade(toolbar)); + ro_gui_menu_set_entry_ticked(menu, TOOLBAR_ADDRESS_BAR, + ro_toolbar_menu_url_tick(toolbar)); -bool ro_gui_window_to_window_pos(struct gui_window *g, int x, int y, - os_coord *pos) -{ - wimp_window_state state; - os_error *error; + ro_gui_menu_set_entry_shaded(menu, TOOLBAR_THROBBER, + ro_toolbar_menu_edit_shade(toolbar)); + ro_gui_menu_set_entry_ticked(menu, TOOLBAR_THROBBER, + ro_toolbar_menu_throbber_tick(toolbar)); - assert(g); + ro_gui_menu_set_entry_shaded(menu, TOOLBAR_EDIT, + ro_toolbar_menu_edit_shade(toolbar)); + ro_gui_menu_set_entry_ticked(menu, TOOLBAR_EDIT, + ro_toolbar_menu_edit_tick(toolbar)); - 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 false; - } - pos->x = (x - (state.visible.x0 - state.xscroll)) / 2 / g->bw->scale; - pos->y = ((state.visible.y1 - state.yscroll) - y) / 2 / g->bw->scale; - return true; -} + /* Page Submenu */ + ro_gui_menu_set_entry_shaded(menu, BROWSER_PAGE, h == NULL || + (content_get_type(h) != CONTENT_HTML && + content_get_type(h) != CONTENT_TEXTPLAIN)); -/** - * Convert x,y window co-ordinates into screen co-ordinates. - * - * \param g gui window - * \param x x ordinate - * \param y y ordinate - * \param pos receives position in screen co-ordinatates - * \return true iff conversion successful - */ + ro_gui_menu_set_entry_shaded(menu, BROWSER_PAGE_INFO, h == NULL); -bool ro_gui_window_to_screen_pos(struct gui_window *g, int x, int y, - os_coord *pos) -{ - wimp_window_state state; - os_error *error; + ro_gui_menu_set_entry_shaded(menu, BROWSER_PRINT, h == NULL); - assert(g); + ro_gui_menu_set_entry_shaded(menu, BROWSER_NEW_WINDOW, h == NULL); - 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 false; - } - pos->x = (x * 2 * g->bw->scale) + (state.visible.x0 - state.xscroll); - pos->y = (state.visible.y1 - state.yscroll) - (y * 2 * g->bw->scale); - return true; -} + ro_gui_menu_set_entry_shaded(menu, BROWSER_FIND_TEXT, + h == NULL || (content_get_type(h) != CONTENT_HTML && + content_get_type(h) != CONTENT_TEXTPLAIN)); -/** - * Handle Message_DataLoad (file dragged in) for a window. - * - * \param g window - * \param message Message_DataLoad block - * \return true if the load was processed - * - * If the file was dragged into a form file input, it is used as the value. - */ + ro_gui_menu_set_entry_shaded(menu, BROWSER_VIEW_SOURCE, h == NULL); -bool ro_gui_window_dataload(struct gui_window *g, wimp_message *message) -{ - struct box *box; - struct box *file_box = 0; - struct box *text_box = 0; - struct browser_window *bw = g->bw; - hlcache_handle *h; - int box_x, box_y; - os_error *error; - os_coord pos; + ro_gui_menu_set_entry_shaded(menu, BROWSER_SAVE_URL_URI, h == NULL); + ro_gui_menu_set_entry_shaded(menu, BROWSER_SAVE_URL_URL, h == NULL); + ro_gui_menu_set_entry_shaded(menu, BROWSER_SAVE_URL_TEXT, h == NULL); - h = bw->current_content; + ro_gui_menu_set_entry_shaded(menu, BROWSER_SAVE, h == NULL); + ro_gui_menu_set_entry_shaded(menu, BROWSER_SAVE_COMPLETE, h == NULL); + ro_gui_menu_set_entry_shaded(menu, BROWSER_EXPORT_DRAW, h == NULL); + ro_gui_menu_set_entry_shaded(menu, BROWSER_EXPORT_PDF, h == NULL); + ro_gui_menu_set_entry_shaded(menu, BROWSER_EXPORT_TEXT, h == NULL); - /* HTML content only. */ - if (!bw->current_content || content_get_type(h) != CONTENT_HTML) - return false; + ro_gui_menu_set_entry_shaded(menu, BROWSER_LINK_SAVE_URI, + !current_menu_url); + ro_gui_menu_set_entry_shaded(menu, BROWSER_LINK_SAVE_URL, + !current_menu_url); + ro_gui_menu_set_entry_shaded(menu, BROWSER_LINK_SAVE_TEXT, + !current_menu_url); - /* Ignore directories etc. */ - if (0x1000 <= message->data.data_xfer.file_type) - return false; - if (!ro_gui_window_to_window_pos(g, message->data.data_xfer.pos.x, - message->data.data_xfer.pos.y, &pos)) - return false; - box = html_get_box_tree(h); + /* Object Submenu */ - /* Consider the margins of the html page now */ - box_x = box->margin[LEFT]; - box_y = box->margin[TOP]; + ro_gui_menu_set_entry_shaded(menu, BROWSER_OBJECT, + current_menu_object == NULL && + current_menu_url == NULL); - while ((box = box_at_point(box, pos.x, pos.y, &box_x, &box_y, &h))) { - if (box->style && css_computed_visibility(box->style) == - CSS_VISIBILITY_HIDDEN) - continue; + ro_gui_menu_set_entry_shaded(menu, BROWSER_OBJECT_LINK, + current_menu_url == NULL); - if (box->gadget) { - switch (box->gadget->type) { - case GADGET_FILE: - file_box = box; - break; + ro_gui_menu_set_entry_shaded(menu, BROWSER_OBJECT_INFO, + current_menu_object == NULL); + ro_gui_menu_set_entry_shaded(menu, BROWSER_OBJECT_RELOAD, + current_menu_object == NULL); + ro_gui_menu_set_entry_shaded(menu, BROWSER_OBJECT_OBJECT, + current_menu_object == NULL); - case GADGET_TEXTBOX: - case GADGET_TEXTAREA: - case GADGET_PASSWORD: - text_box = box; - break; + ro_gui_menu_set_entry_shaded(menu, BROWSER_OBJECT_PRINT, true); + /* Not yet implemented */ - default: /* appease compiler */ - break; - } - } - } + ro_gui_menu_set_entry_shaded(menu, BROWSER_OBJECT_SAVE, + current_menu_object == NULL); - if (!file_box && !text_box) - return false; + ro_gui_menu_set_entry_shaded(menu, BROWSER_OBJECT_SAVE_URL_URI, + current_menu_object == NULL); + ro_gui_menu_set_entry_shaded(menu, BROWSER_OBJECT_SAVE_URL_URL, + current_menu_object == NULL); + ro_gui_menu_set_entry_shaded(menu, BROWSER_OBJECT_SAVE_URL_TEXT, + current_menu_object == NULL); - if (file_box) { - utf8_convert_ret ret; - char *utf8_fn; + if (current_menu_object != NULL) + ro_gui_window_content_export_types(current_menu_object, + &export_draw, &export_sprite); + else + ro_gui_window_content_export_types(h, + &export_draw, &export_sprite); - ret = utf8_from_local_encoding( - message->data.data_xfer.file_name, 0, - &utf8_fn); - if (ret != UTF8_CONVERT_OK) { - /* A bad encoding should never happen */ - assert(ret != UTF8_CONVERT_BADENC); - LOG(("utf8_from_local_encoding failed")); - /* Load was for us - just no memory */ - return true; - } + ro_gui_menu_set_entry_shaded(menu, BROWSER_OBJECT_EXPORT, + (h == NULL && current_menu_object == NULL) + || !(export_sprite || export_draw)); - /* Found: update form input. */ - free(file_box->gadget->value); - file_box->gadget->value = utf8_fn; + ro_gui_menu_set_entry_shaded(menu, BROWSER_OBJECT_EXPORT_SPRITE, + (h == NULL && current_menu_object == NULL) + || !export_sprite); - /* Redraw box. */ - box_coords(file_box, &pos.x, &pos.y); - gui_window_redraw(bw->window, pos.x, pos.y, - pos.x + file_box->width, - pos.y + file_box->height); - } else { + ro_gui_menu_set_entry_shaded(menu, BROWSER_OBJECT_EXPORT_DRAW, + (h == NULL && current_menu_object == NULL) + || !export_draw); - const char *filename = message->data.data_xfer.file_name; - browser_window_mouse_click(g->bw, BROWSER_MOUSE_PRESS_1, pos.x, pos.y); + /* Selection Submenu */ - if (!ro_gui_window_import_text(g, filename, false)) - return true; /* it was for us, it just didn't work! */ - } + ro_gui_menu_set_entry_shaded(menu, BROWSER_SELECTION, + h == NULL || (content_get_type(h) != CONTENT_HTML && + content_get_type(h) != CONTENT_TEXTPLAIN)); + /* make menu available if there's anything that /could/ + * be selected */ - /* send DataLoadAck */ - message->action = message_DATA_LOAD_ACK; - message->your_ref = message->my_ref; - error = xwimp_send_message(wimp_USER_MESSAGE, message, message->sender); - if (error) { - LOG(("xwimp_send_message: 0x%x: %s\n", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); - } + ro_gui_menu_set_entry_shaded(menu, BROWSER_SELECTION_SAVE, h == NULL || + bw->sel == NULL || !selection_defined(bw->sel)); - return true; -} + ro_gui_menu_set_entry_shaded(menu, BROWSER_SELECTION_COPY, h == NULL || + bw->sel == NULL || !selection_defined(bw->sel)); + ro_gui_menu_set_entry_shaded(menu, BROWSER_SELECTION_CUT, h == NULL || + bw->sel == NULL || !selection_defined(bw->sel) || + selection_read_only(bw->sel)); -/** - * Handle Message_DataLoad (file dragged in) for a toolbar - * - * \param g window - * \param message Message_DataLoad block - * \return true if the load was processed - */ + ro_gui_menu_set_entry_shaded(menu, BROWSER_SELECTION_PASTE, + h == NULL || bw->paste_callback == NULL); -bool ro_gui_toolbar_dataload(struct gui_window *g, wimp_message *message) -{ - if (message->data.data_xfer.file_type == osfile_TYPE_TEXT && - ro_gui_window_import_text(g, message->data.data_xfer.file_name, true)) { + ro_gui_menu_set_entry_shaded(menu, BROWSER_SELECTION_CLEAR, h == NULL || + bw->sel == NULL || !selection_defined(bw->sel)); - os_error *error; - /* send DataLoadAck */ - message->action = message_DATA_LOAD_ACK; - message->your_ref = message->my_ref; - error = xwimp_send_message(wimp_USER_MESSAGE, message, message->sender); - if (error) { - LOG(("xwimp_send_message: 0x%x: %s\n", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); - } - return true; - } - return false; -} + /* Navigate Submenu */ + ro_gui_menu_set_entry_shaded(menu, BROWSER_NAVIGATE_BACK, + !browser_window_back_available(bw)); -/** - * Process pending reformats - */ + ro_gui_menu_set_entry_shaded(menu, BROWSER_NAVIGATE_FORWARD, + !browser_window_forward_available(bw)); -void ro_gui_window_process_reformats(void) -{ - struct gui_window *g; + ro_gui_menu_set_entry_shaded(menu, BROWSER_NAVIGATE_RELOAD_ALL, + !browser_window_reload_available(bw)); - browser_reformat_pending = false; - for (g = window_list; g; g = g->next) { - if (!g->bw->reformat_pending) - continue; - g->bw->reformat_pending = false; - browser_window_reformat(g->bw, - g->old_width / 2, - g->old_height / 2); - } -} + ro_gui_menu_set_entry_shaded(menu, BROWSER_NAVIGATE_STOP, + !browser_window_stop_available(bw)); + ro_gui_menu_set_entry_shaded(menu, BROWSER_NAVIGATE_UP, + !ro_gui_window_up_available(bw)); -/** - * Clones a browser window's options. - * - * \param new_bw the new browser window - * \param old_bw the browser window to clone from, or NULL for default - */ -void ro_gui_window_clone_options(struct browser_window *new_bw, - struct browser_window *old_bw) { - struct gui_window *old_gui = NULL; - struct gui_window *new_gui; - assert(new_bw); + /* View Submenu */ - /* Get our GUIs - */ - new_gui = new_bw->window; + ro_gui_menu_set_entry_shaded(menu, BROWSER_IMAGES_FOREGROUND, true); + ro_gui_menu_set_entry_ticked(menu, BROWSER_IMAGES_FOREGROUND, true); + /* Not yet implemented. */ - if (old_bw) - old_gui = old_bw->window; + ro_gui_menu_set_entry_ticked(menu, BROWSER_IMAGES_BACKGROUND, + g != NULL && g->option.background_images); - /* Clone the basic options - */ - if (!old_gui) { - new_bw->scale = ((float)option_scale) / 100; - new_gui->option.background_images = option_background_images; - new_gui->option.buffer_animations = option_buffer_animations; - new_gui->option.buffer_everything = option_buffer_everything; - } else { - new_gui->option = old_gui->option; - } + ro_gui_menu_set_entry_shaded(menu, BROWSER_BUFFER_ANIMS, + g == NULL || g->option.buffer_everything); + ro_gui_menu_set_entry_ticked(menu, BROWSER_BUFFER_ANIMS, g != NULL && + (g->option.buffer_animations || + g->option.buffer_everything)); - /* Set up the toolbar - */ - if (new_gui->toolbar) { - 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; - if ((old_gui) && (old_gui->toolbar)) { - 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; - new_gui->toolbar->reformat_buttons = true; - ro_gui_theme_process_toolbar(new_gui->toolbar, -1); - } - } -} + ro_gui_menu_set_entry_shaded(menu, BROWSER_BUFFER_ALL, g == NULL); + ro_gui_menu_set_entry_ticked(menu, BROWSER_BUFFER_ALL, + g != NULL && g->option.buffer_everything); + ro_gui_menu_set_entry_shaded(menu, BROWSER_SCALE_VIEW, h == NULL); -/** - * Makes a browser window's options the default. - * - * \param bw the browser window to read options from - */ + ro_gui_menu_set_entry_shaded(menu, BROWSER_WINDOW_STAGGER, + option_window_screen_width == 0); + ro_gui_menu_set_entry_ticked(menu, BROWSER_WINDOW_STAGGER, + ((option_window_screen_width == 0) || + option_window_stagger)); -void ro_gui_window_default_options(struct browser_window *bw) { - struct gui_window *gui; + ro_gui_menu_set_entry_ticked(menu, BROWSER_WINDOW_COPY, + option_window_size_clone); - assert(bw); + ro_gui_menu_set_entry_shaded(menu, BROWSER_WINDOW_RESET, + option_window_screen_width == 0); - /* Get our GUI - */ - gui = bw->window; - if (!gui) return; - /* Save the basic options - */ - option_scale = bw->scale * 100; - option_buffer_animations = gui->option.buffer_animations; - option_buffer_everything = gui->option.buffer_everything; + /* Utilities Submenu */ - /* Set up the toolbar - */ - if (gui->toolbar) { - option_toolbar_show_buttons = gui->toolbar->display_buttons; - option_toolbar_show_address = gui->toolbar->display_url; - option_toolbar_show_throbber = gui->toolbar->display_throbber; - } - if (gui->status_bar) - option_toolbar_status_width = ro_gui_status_bar_get_width(gui->status_bar); -} + ro_gui_menu_set_entry_shaded(menu, HOTLIST_ADD_URL, h == NULL); + ro_gui_menu_set_entry_shaded(menu, HISTORY_SHOW_LOCAL, + (bw == NULL || (bw->history == NULL) || + !(h != NULL || history_back_available(bw->history) || + history_forward_available(bw->history)))); + /* Help Submenu */ -/** - * Updates the navigation controls for all toolbars; - * - * \param g the gui_window to launch the URL into - * \param url the URL to launch, or NULL to simply update the suggestion icon - */ -void ro_gui_window_prepare_navigate_all(void) { - struct gui_window *g; + ro_gui_menu_set_entry_ticked(menu, HELP_LAUNCH_INTERACTIVE, + ro_gui_interactive_help_available() && + option_interactive_help); - for (g = window_list; g; g = g->next) - ro_gui_prepare_navigate(g); + return true; } /** - * Returns the state of the mouse buttons and modifiers keys for a - * mouse action, suitable for passing to the OS-independent - * browser window/ treeview/ etc code. + * Handle submenu warnings for a browser window menu * - * \param buttons Wimp button state. - * \param type Wimp work-area/icon type for decoding. - * \return NetSurf core button state. + * \param w The window owning the menu. + * \param i The icon owning the menu. + * \param *menu The menu to which the warning applies. + * \param *selection The wimp menu selection data. + * \param action The selected menu action. */ -browser_mouse_state ro_gui_mouse_click_state(wimp_mouse_state buttons, - wimp_icon_flags type) +void ro_gui_window_menu_warning(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_selection *selection, menu_action action) { - browser_mouse_state state = 0; /* Blank state with nothing set */ + struct gui_window *g; + struct browser_window *bw; + hlcache_handle *h; + struct toolbar *toolbar; + bool export; - switch (type) { - case wimp_BUTTON_CLICK_DRAG: /* Used for browser window */ - /* Handle single clicks. */ + if (menu != ro_gui_browser_window_menu) + return; - /* We fire core PRESS and CLICK events together for "action on - * press" behaviour. */ - if (buttons & (wimp_CLICK_SELECT)) /* Select click */ - state |= BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_CLICK_1; - if (buttons & (wimp_CLICK_ADJUST)) /* Adjust click */ - state |= BROWSER_MOUSE_PRESS_2 | BROWSER_MOUSE_CLICK_2; + g = (struct gui_window *) ro_gui_wimp_event_get_user_data(w); + toolbar = g->toolbar; + bw = g->bw; + h = bw->current_content; + + switch (action) { + case BROWSER_PAGE_INFO: + if (h != NULL) + ro_gui_window_prepare_pageinfo(g); break; - case wimp_BUTTON_DOUBLE_CLICK_DRAG: /* Used for treeview window */ - /* Handle single and double clicks. */ - /* Single clicks: Fire PRESS and CLICK events together - * for "action on press" behaviour. */ - if (buttons & (wimp_SINGLE_SELECT)) /* Select single click */ - state |= BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_CLICK_1; - if (buttons & (wimp_SINGLE_ADJUST)) /* Adjust single click */ - state |= BROWSER_MOUSE_PRESS_2 | BROWSER_MOUSE_CLICK_2; + case BROWSER_FIND_TEXT: + if (h != NULL && (content_get_type(h) == CONTENT_HTML || + content_get_type(h) == CONTENT_TEXTPLAIN)) + ro_gui_search_prepare(g->bw); + break; - /* Double clicks: Fire PRESS, CLICK, and DOUBLE_CLICK - * events together for "action on 2nd press" behaviour. */ - if (buttons & (wimp_DOUBLE_SELECT)) /* Select double click */ - state |= BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_CLICK_1 | - BROWSER_MOUSE_DOUBLE_CLICK; - if (buttons & (wimp_DOUBLE_ADJUST)) /* Adjust double click */ - state |= BROWSER_MOUSE_PRESS_2 | BROWSER_MOUSE_CLICK_2 | - BROWSER_MOUSE_DOUBLE_CLICK; + case BROWSER_SCALE_VIEW: + if (h != NULL) + ro_gui_dialog_prepare_zoom(g); break; - } - /* Check if a drag has started */ - if (buttons & (wimp_DRAG_SELECT)) { - /* A drag was _started_ with Select; Fire DRAG_1. */ - state |= BROWSER_MOUSE_DRAG_1; - mouse_drag_select = true; - } - if (buttons & (wimp_DRAG_ADJUST)) { - /* A drag was _started_ with Adjust; Fire DRAG_2. */ - state |= BROWSER_MOUSE_DRAG_2; - mouse_drag_adjust = true; - } + case BROWSER_PRINT: + if (h != NULL) + ro_gui_print_prepare(g); + break; - /* Set modifier key state */ - if (ro_gui_shift_pressed()) state |= BROWSER_MOUSE_MOD_1; - if (ro_gui_ctrl_pressed()) state |= BROWSER_MOUSE_MOD_2; - if (ro_gui_alt_pressed()) state |= BROWSER_MOUSE_MOD_3; + case BROWSER_OBJECT_INFO: + if (current_menu_object != NULL) + ro_gui_window_prepare_objectinfo(current_menu_object, + current_menu_url); + break; - return state; -} + case BROWSER_OBJECT_SAVE: + if (current_menu_object != NULL) + ro_gui_save_prepare(GUI_SAVE_OBJECT_ORIG, + current_menu_object, NULL, NULL, NULL); + break; -/** - * Returns the state of the mouse buttons and modifiers keys whilst - * dragging, for passing to the OS-independent browser window/ treeview/ - * etc code - * - * \param buttons Wimp button state. - * \param type Wimp work-area/icon type for decoding. - * \return NetSurf core button state. - */ + case BROWSER_SELECTION_SAVE: + if (h != NULL) + ro_gui_save_prepare(GUI_SAVE_TEXT_SELECTION, NULL, + bw->sel, NULL, NULL); + break; -browser_mouse_state ro_gui_mouse_drag_state(wimp_mouse_state buttons, - wimp_icon_flags type) -{ - browser_mouse_state state = 0; /* Blank state with nothing set */ + case BROWSER_SAVE_URL_URI: + if (h != NULL) + ro_gui_save_prepare(GUI_SAVE_LINK_URI, NULL, NULL, + content_get_url(h), + content_get_title(h)); + break; - /* If mouse buttons aren't held, turn off drags */ - if (!(buttons & (wimp_CLICK_SELECT) || buttons & (wimp_CLICK_ADJUST))) { - mouse_drag_select = false; - mouse_drag_adjust = false; - } + case BROWSER_SAVE_URL_URL: + if (h != NULL) + ro_gui_save_prepare(GUI_SAVE_LINK_URL, NULL, NULL, + content_get_url(h), + content_get_title(h)); + break; - /* If there's a drag happening, set DRAG_ON and record which button - * the drag is happening with, i.e. HOLDING_1 or HOLDING_2 */ - if (mouse_drag_select) { - state |= BROWSER_MOUSE_DRAG_ON | BROWSER_MOUSE_HOLDING_1; - } - if (mouse_drag_adjust) { - state |= BROWSER_MOUSE_DRAG_ON | BROWSER_MOUSE_HOLDING_2; - } + case BROWSER_SAVE_URL_TEXT: + if (h != NULL) + ro_gui_save_prepare(GUI_SAVE_LINK_TEXT, NULL, NULL, + content_get_url(h), + content_get_title(h)); + break; - /* Set modifier key state */ - if (ro_gui_shift_pressed()) state |= BROWSER_MOUSE_MOD_1; - if (ro_gui_ctrl_pressed()) state |= BROWSER_MOUSE_MOD_2; - if (ro_gui_alt_pressed()) state |= BROWSER_MOUSE_MOD_3; + case BROWSER_OBJECT_SAVE_URL_URI: + if (current_menu_object != NULL) + ro_gui_save_prepare(GUI_SAVE_LINK_URI, NULL, NULL, + content_get_url(current_menu_object), + content_get_title(current_menu_object)); + break; - return state; -} + case BROWSER_OBJECT_SAVE_URL_URL: + if (current_menu_object != NULL) + ro_gui_save_prepare(GUI_SAVE_LINK_URL, NULL, NULL, + content_get_url(current_menu_object), + content_get_title(current_menu_object)); + break; + case BROWSER_OBJECT_SAVE_URL_TEXT: + if (current_menu_object != NULL) + ro_gui_save_prepare(GUI_SAVE_LINK_TEXT, NULL, NULL, + content_get_url(current_menu_object), + content_get_title(current_menu_object)); + break; -/** - * Returns true iff one or more Shift keys is held down - */ + case BROWSER_SAVE: + if (h != NULL) + ro_gui_save_prepare(GUI_SAVE_SOURCE, h, NULL, NULL, NULL); + break; -bool ro_gui_shift_pressed(void) -{ - int shift = 0; - xosbyte1(osbyte_SCAN_KEYBOARD, 0 ^ 0x80, 0, &shift); - return (shift == 0xff); -} + case BROWSER_SAVE_COMPLETE: + if (h != NULL) + ro_gui_save_prepare(GUI_SAVE_COMPLETE, h, NULL, NULL, NULL); + break; + case BROWSER_EXPORT_DRAW: + if (h != NULL) + ro_gui_save_prepare(GUI_SAVE_DRAW, h, NULL, NULL, NULL); + break; -/** - * Returns true iff one or more Ctrl keys is held down - */ + case BROWSER_EXPORT_PDF: + if (h != NULL) + ro_gui_save_prepare(GUI_SAVE_PDF, h, NULL, NULL, NULL); + break; -bool ro_gui_ctrl_pressed(void) -{ - int ctrl = 0; - xosbyte1(osbyte_SCAN_KEYBOARD, 1 ^ 0x80, 0, &ctrl); - return (ctrl == 0xff); -} + case BROWSER_EXPORT_TEXT: + if (h != NULL) + ro_gui_save_prepare(GUI_SAVE_TEXT, h, NULL, NULL, NULL); + break; + case BROWSER_LINK_SAVE_URI: + if (current_menu_url != NULL) + ro_gui_save_prepare(GUI_SAVE_LINK_URI, NULL, NULL, + current_menu_url, NULL); + break; -/** - * Returns true iff one or more Alt keys is held down - */ + case BROWSER_LINK_SAVE_URL: + if (current_menu_url != NULL) + ro_gui_save_prepare(GUI_SAVE_LINK_URL, NULL, NULL, + current_menu_url, NULL); + break; -bool ro_gui_alt_pressed(void) -{ - int alt = 0; - xosbyte1(osbyte_SCAN_KEYBOARD, 2 ^ 0x80, 0, &alt); - return (alt == 0xff); + case BROWSER_LINK_SAVE_TEXT: + if (current_menu_url != NULL) + ro_gui_save_prepare(GUI_SAVE_LINK_TEXT, NULL, NULL, + current_menu_url, NULL); + break; + + case BROWSER_OBJECT_EXPORT_SPRITE: + if (current_menu_object != NULL) { + ro_gui_window_content_export_types(current_menu_object, + NULL, &export); + + if (export) + ro_gui_save_prepare(GUI_SAVE_OBJECT_NATIVE, + current_menu_object, + NULL, NULL, NULL); + } else if (h != NULL) { + ro_gui_window_content_export_types(h, NULL, &export); + + if (export) + ro_gui_save_prepare(GUI_SAVE_OBJECT_NATIVE, + h, NULL, NULL, NULL); + } + break; + + case BROWSER_OBJECT_EXPORT_DRAW: + if (current_menu_object != NULL) { + ro_gui_window_content_export_types(current_menu_object, + &export, NULL); + + if (export) + ro_gui_save_prepare(GUI_SAVE_OBJECT_NATIVE, + current_menu_object, + NULL, NULL, NULL); + } else if (h != NULL) { + ro_gui_window_content_export_types(h, &export, NULL); + + if (export) + ro_gui_save_prepare(GUI_SAVE_OBJECT_NATIVE, + h, NULL, NULL, NULL); + } + break; + + default: + break; + } } /** - * Completes scrolling of a browser window + * Handle selections from a browser window menu * - * \param g gui window + * \param w The window owning the menu. + * \param i The icon owning the menu. + * \param *menu The menu from which the selection was made. + * \param *selection The wimp menu selection data. + * \param action The selected menu action. + * \return true if action accepted; else false. */ -void ro_gui_window_scroll_end(struct gui_window *g, wimp_dragged *drag) +bool ro_gui_window_menu_select(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_selection *selection, menu_action action) { - wimp_pointer pointer; - os_error *error; - os_coord pos; + struct gui_window *g; + struct browser_window *bw; + hlcache_handle *h; + struct toolbar *toolbar; + wimp_window_state state; + os_error *error; + + g = (struct gui_window *) ro_gui_wimp_event_get_user_data(w); + toolbar = g->toolbar; + bw = g->bw; + h = bw->current_content; - gui_current_drag_type = GUI_DRAG_NONE; - if (!g) - return; + /* If this is a form menu from the core, handle it now and then exit. + * Otherwise, carry on to the main browser window menu. + */ - error = xwimp_drag_box((wimp_drag*)-1); - if (error) { - LOG(("xwimp_drag_box: 0x%x : %s", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); - } + if (menu == gui_form_select_menu && w == g->window) { + ro_gui_window_process_form_select_menu(g, selection); - error = xwimp_get_pointer_info(&pointer); - if (error) { - LOG(("xwimp_get_pointer_info 0x%x : %s", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); - return; + return true; } - error = xwimpspriteop_set_pointer_shape("ptr_default", 0x31, 0, 0, 0, 0); - if (error) { - LOG(("xwimpspriteop_set_pointer_shape: 0x%x: %s", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); - } + /* We're now safe to assume that this is either the browser or + * toolbar window menu. + */ - if (ro_gui_window_to_window_pos(g, drag->final.x0, drag->final.y0, &pos)) - browser_window_mouse_drag_end(g->bw, - ro_gui_mouse_click_state(pointer.buttons, - wimp_BUTTON_CLICK_DRAG), - pos.x, pos.y); -} + switch (action) { + /* help actions */ + case HELP_OPEN_CONTENTS: + ro_gui_open_help_page("documentation/index"); + break; + case HELP_OPEN_GUIDE: + ro_gui_open_help_page("documentation/guide"); + break; + case HELP_OPEN_INFORMATION: + ro_gui_open_help_page("documentation/info"); + break; + case HELP_OPEN_ABOUT: + ro_gui_open_help_page("about/index"); + break; + case HELP_LAUNCH_INTERACTIVE: + if (!ro_gui_interactive_help_available()) { + ro_gui_interactive_help_start(); + option_interactive_help = true; + } else { + option_interactive_help = !option_interactive_help; + } + break; -/** - * Completes resizing of a browser frame - * - * \param g gui window - */ + /* history actions */ + case HISTORY_SHOW_LOCAL: + ro_gui_window_action_local_history(g); + break; + case HISTORY_SHOW_GLOBAL: + ro_gui_global_history_open(); + break; -void ro_gui_window_frame_resize_end(struct gui_window *g, wimp_dragged *drag) -{ - /* our clean-up is the same as for page scrolling */ - ro_gui_window_scroll_end(g, drag); -} + /* hotlist actions */ + case HOTLIST_ADD_URL: + ro_gui_window_action_add_bookmark(g); + break; + case HOTLIST_SHOW: + ro_gui_hotlist_open(); + break; -/** - * Import text file into window or its toolbar - * - * \param g gui window containing textarea - * \param filename pathname of file to be imported - * \param toolbar true iff imported to toolbar rather than main window - * \return true iff successful - */ + /* cookies actions */ + case COOKIES_SHOW: + ro_gui_cookies_open(); + break; -bool ro_gui_window_import_text(struct gui_window *g, const char *filename, - bool toolbar) -{ - fileswitch_object_type obj_type; - os_error *error; - char *buf, *utf8_buf; - int size; - utf8_convert_ret ret; + case COOKIES_DELETE: + cookies_delete_all(); + break; - error = xosfile_read_stamped(filename, &obj_type, NULL, NULL, - &size, NULL, NULL); - if (error) { - LOG(("xosfile_read_stamped: 0x%x:%s", - error->errnum, error->errmess)); - warn_user("FileError", error->errmess); - return true; /* was for us, but it didn't work! */ - } + /* page actions */ + case BROWSER_PAGE_INFO: + ro_gui_window_action_page_info(g); + break; + case BROWSER_PRINT: + ro_gui_window_action_print(g); + break; + case BROWSER_NEW_WINDOW: + ro_gui_window_action_new_window(g); + break; + case BROWSER_VIEW_SOURCE: + if (h != NULL) + ro_gui_view_source(h); + break; + + /* object actions */ + case BROWSER_OBJECT_INFO: + if (current_menu_object != NULL) { + ro_gui_window_prepare_objectinfo(current_menu_object, + current_menu_url); + ro_gui_dialog_open_persistent(g->window, + dialog_objinfo, false); + } + break; + case BROWSER_OBJECT_RELOAD: + if (current_menu_object != NULL) { + content_invalidate_reuse_data(current_menu_object); + browser_window_reload(bw, false); + } + break; + + /* link actions */ + case BROWSER_LINK_SAVE_URI: + if (current_menu_url != NULL) { + ro_gui_save_prepare(GUI_SAVE_LINK_URI, NULL, NULL, + current_menu_url, NULL); + ro_gui_dialog_open_persistent(g->window, dialog_saveas, + false); + } + break; + case BROWSER_LINK_SAVE_URL: + if (current_menu_url != NULL) { + ro_gui_save_prepare(GUI_SAVE_LINK_URL, NULL, NULL, + current_menu_url, NULL); + ro_gui_dialog_open_persistent(g->window, dialog_saveas, + false); + } + break; + case BROWSER_LINK_SAVE_TEXT: + if (current_menu_url != NULL) { + ro_gui_save_prepare(GUI_SAVE_LINK_TEXT, NULL, NULL, + current_menu_url, NULL); + ro_gui_dialog_open_persistent(g->window, dialog_saveas, + false); + } + break; + case BROWSER_LINK_DOWNLOAD: + if (current_menu_url != NULL) + browser_window_download(bw, current_menu_url, + content_get_url(h)); + break; + case BROWSER_LINK_NEW_WINDOW: + if (current_menu_url != NULL) + browser_window_create(current_menu_url, bw, + content_get_url(h), true, false); + break; + + /* save actions */ + case BROWSER_OBJECT_SAVE: + if (current_menu_object != NULL) { + ro_gui_save_prepare(GUI_SAVE_OBJECT_ORIG, + current_menu_object, NULL, NULL, NULL); + ro_gui_dialog_open_persistent(g->window, dialog_saveas, + false); + } + break; + case BROWSER_OBJECT_EXPORT_SPRITE: + if (current_menu_object != NULL) { + ro_gui_save_prepare(GUI_SAVE_OBJECT_NATIVE, + current_menu_object, NULL, NULL, NULL); + ro_gui_dialog_open_persistent(g->window, dialog_saveas, + false); + } + break; + case BROWSER_OBJECT_EXPORT_DRAW: + if (current_menu_object != NULL) { + ro_gui_save_prepare(GUI_SAVE_OBJECT_NATIVE, + current_menu_object, NULL, NULL, NULL); + ro_gui_dialog_open_persistent(g->window, dialog_saveas, + false); + } + break; + case BROWSER_SAVE: + ro_gui_window_action_save(g, GUI_SAVE_SOURCE); + break; + case BROWSER_SAVE_COMPLETE: + ro_gui_window_action_save(g, GUI_SAVE_COMPLETE); + break; + case BROWSER_EXPORT_DRAW: + ro_gui_window_action_save(g, GUI_SAVE_DRAW); + break; + case BROWSER_EXPORT_PDF: + ro_gui_window_action_save(g, GUI_SAVE_PDF); + break; + case BROWSER_EXPORT_TEXT: + ro_gui_window_action_save(g, GUI_SAVE_TEXT); + break; + case BROWSER_SAVE_URL_URI: + ro_gui_window_action_save(g, GUI_SAVE_LINK_URI); + break; + case BROWSER_SAVE_URL_URL: + ro_gui_window_action_save(g, GUI_SAVE_LINK_URL); + break; + case BROWSER_SAVE_URL_TEXT: + ro_gui_window_action_save(g, GUI_SAVE_LINK_TEXT); + break; + + /* selection actions */ + case BROWSER_SELECTION_SAVE: + if (h != NULL) { + ro_gui_save_prepare(GUI_SAVE_TEXT_SELECTION, NULL, + bw->sel, NULL, NULL); + ro_gui_dialog_open_persistent(g->window, dialog_saveas, + false); + } + break; + case BROWSER_SELECTION_COPY: + browser_window_key_press(bw, KEY_COPY_SELECTION); + break; + case BROWSER_SELECTION_CUT: + browser_window_key_press(bw, KEY_CUT_SELECTION); + break; + case BROWSER_SELECTION_PASTE: + browser_window_key_press(bw, KEY_PASTE); + break; + case BROWSER_SELECTION_ALL: + browser_window_key_press(bw, KEY_SELECT_ALL); + break; + case BROWSER_SELECTION_CLEAR: + browser_window_key_press(bw, KEY_CLEAR_SELECTION); + break; + + /* navigation actions */ + case BROWSER_NAVIGATE_HOME: + ro_gui_window_action_home(g); + break; + case BROWSER_NAVIGATE_BACK: + if (bw != NULL && bw->history != NULL) + history_back(bw, bw->history); + break; + case BROWSER_NAVIGATE_FORWARD: + if (bw != NULL && bw->history != NULL) + history_forward(bw, bw->history); + break; + case BROWSER_NAVIGATE_UP: + if (bw != NULL && h != NULL) + ro_gui_window_navigate_up(bw->window, + content_get_url(h)); + break; + case BROWSER_NAVIGATE_RELOAD_ALL: + if (bw != NULL) + browser_window_reload(bw, true); + break; + case BROWSER_NAVIGATE_STOP: + if (bw != NULL) + browser_window_stop(bw); + break; + + /* browser window/display actions */ + case BROWSER_SCALE_VIEW: + ro_gui_window_action_zoom(g); + break; + case BROWSER_FIND_TEXT: + ro_gui_window_action_search(g); + break; + case BROWSER_IMAGES_BACKGROUND: + if (g != NULL) { + g->option.background_images = + !g->option.background_images; + gui_window_redraw_window(g); + } + break; + case BROWSER_BUFFER_ANIMS: + if (g != NULL) + g->option.buffer_animations = + !g->option.buffer_animations; + break; + case BROWSER_BUFFER_ALL: + if (g != NULL) + g->option.buffer_everything = + !g->option.buffer_everything; + break; + case BROWSER_SAVE_VIEW: + if (bw != NULL) { + ro_gui_window_default_options(bw); + ro_gui_save_options(); + } + break; + case BROWSER_WINDOW_DEFAULT: + if (g != NULL) { + ro_gui_screen_size(&option_window_screen_width, + &option_window_screen_height); + state.w = w; + 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); + } + option_window_x = state.visible.x0; + option_window_y = state.visible.y0; + option_window_width = + state.visible.x1 - state.visible.x0; + option_window_height = + state.visible.y1 - state.visible.y0; + ro_gui_save_options(); + } + break; + case BROWSER_WINDOW_STAGGER: + option_window_stagger = !option_window_stagger; + ro_gui_save_options(); + break; + case BROWSER_WINDOW_COPY: + option_window_size_clone = !option_window_size_clone; + ro_gui_save_options(); + break; + case BROWSER_WINDOW_RESET: + option_window_screen_width = 0; + option_window_screen_height = 0; + ro_gui_save_options(); + break; + + /* toolbar actions */ + case TOOLBAR_BUTTONS: + assert(toolbar); + ro_toolbar_set_display_buttons(toolbar, + !ro_toolbar_get_display_buttons(toolbar)); + break; + case TOOLBAR_ADDRESS_BAR: + assert(toolbar); + ro_toolbar_set_display_url(toolbar, + !ro_toolbar_get_display_url(toolbar)); + if (ro_toolbar_get_display_url(toolbar)) + ro_toolbar_take_caret(toolbar); + break; + case TOOLBAR_THROBBER: + assert(toolbar); + ro_toolbar_set_display_throbber(toolbar, + !ro_toolbar_get_display_throbber(toolbar)); + break; + case TOOLBAR_EDIT: + assert(toolbar); + ro_toolbar_toggle_edit(toolbar); + break; + + default: + return false; + } + + return true; +} + + +/** + * Handle the closure of a browser window menu + * + * \param w The window owning the menu. + * \param i The icon owning the menu. + * \param *menu The menu that is being closed. + */ + +void ro_gui_window_menu_close(wimp_w w, wimp_i i, wimp_menu *menu) +{ + if (menu == ro_gui_browser_window_menu) { + current_menu_object = NULL; + current_menu_url = NULL; + } else if (menu == gui_form_select_menu) { + gui_form_select_control = NULL; + } +} + + +/** + * Process Scroll_Request events. + * + * \TODO -- This handles Scroll Events for all windows, not just browser + * windows. Either it needs to move somewhere else, or the + * code needs to be split and Scroll Events dispatched via the + * Wimp_Event module. Currently it doesn't properly handle + * events affecting treeview windows, anyway. + */ + +void ro_gui_scroll_request(wimp_scroll *scroll) +{ + struct gui_window *g = ro_gui_window_lookup(scroll->w); + struct toolbar *toolbar; + + if (g && g->bw->current_content && ro_gui_shift_pressed()) { + /* extended scroll request with shift held down; change zoom */ + float scale, inc; + + if (scroll->ymin & 3) + inc = 0.02; /* RO5 sends the msg 5 times; + * don't ask me why */ + else + inc = (1 << (ABS(scroll->ymin)>>2)) / 20.0F; + + if (scroll->ymin > 0) { + scale = g->bw->scale + inc; + if (scale > scale_snap_to[SCALE_SNAP_TO_SIZE - 1]) + scale = scale_snap_to[SCALE_SNAP_TO_SIZE - 1]; + } else { + scale = g->bw->scale - inc; + if (scale < scale_snap_to[0]) + scale = scale_snap_to[0]; + } + if (g->bw->scale != scale) + browser_window_set_scale(g->bw, scale, true); + } else { + int x = scroll->visible.x1 - scroll->visible.x0 - 32; + int y = scroll->visible.y1 - scroll->visible.y0 - 32; + os_error *error; + + /* This has to handle all windows, not just browser ones. */ + toolbar = ro_toolbar_parent_window_lookup(scroll->w); + assert(g == NULL || g->toolbar == NULL || + g->toolbar == toolbar); + if (toolbar != NULL) + y -= ro_toolbar_full_height(toolbar); + + switch (scroll->xmin) { + case wimp_SCROLL_PAGE_LEFT: + scroll->xscroll -= x; + break; + case wimp_SCROLL_COLUMN_LEFT: + scroll->xscroll -= 32; + break; + case wimp_SCROLL_COLUMN_RIGHT: + scroll->xscroll += 32; + break; + case wimp_SCROLL_PAGE_RIGHT: + scroll->xscroll += x; + break; + default: + scroll->xscroll += (x * (scroll->xmin>>2)) >> 2; + break; + } + + switch (scroll->ymin) { + case wimp_SCROLL_PAGE_UP: + scroll->yscroll += y; + break; + case wimp_SCROLL_LINE_UP: + scroll->yscroll += 32; + break; + case wimp_SCROLL_LINE_DOWN: + scroll->yscroll -= 32; + break; + case wimp_SCROLL_PAGE_DOWN: + scroll->yscroll -= y; + break; + default: + scroll->yscroll += (y * (scroll->ymin>>2)) >> 2; + break; + } + + error = xwimp_open_window((wimp_open *) scroll); + if (error) { + LOG(("xwimp_open_window: 0x%x: %s", + error->errnum, error->errmess)); + } + } +} + + +/** + * Handle Message_DataLoad (file dragged in) for a window. + * + * \param g window + * \param message Message_DataLoad block + * \return true if the load was processed + * + * If the file was dragged into a form file input, it is used as the value. + */ + +bool ro_gui_window_dataload(struct gui_window *g, wimp_message *message) +{ + struct box *box; + struct box *file_box = 0; + struct box *text_box = 0; + struct browser_window *bw = g->bw; + hlcache_handle *h; + int box_x, box_y; + os_error *error; + os_coord pos; + + h = bw->current_content; + + /* HTML content only. */ + if (!bw->current_content || content_get_type(h) != CONTENT_HTML) + return false; + + /* Ignore directories etc. */ + if (0x1000 <= message->data.data_xfer.file_type) + return false; + + if (!ro_gui_window_to_window_pos(g, message->data.data_xfer.pos.x, + message->data.data_xfer.pos.y, &pos)) + return false; + + box = html_get_box_tree(h); + + /* Consider the margins of the html page now */ + box_x = box->margin[LEFT]; + box_y = box->margin[TOP]; + + while ((box = box_at_point(box, pos.x, pos.y, &box_x, &box_y, &h))) { + if (box->style && css_computed_visibility(box->style) == + CSS_VISIBILITY_HIDDEN) + continue; + + if (box->gadget) { + switch (box->gadget->type) { + case GADGET_FILE: + file_box = box; + break; + + case GADGET_TEXTBOX: + case GADGET_TEXTAREA: + case GADGET_PASSWORD: + text_box = box; + break; + + default: /* appease compiler */ + break; + } + } + } + + if (!file_box && !text_box) + return false; + + if (file_box) { + utf8_convert_ret ret; + char *utf8_fn; + + ret = utf8_from_local_encoding( + message->data.data_xfer.file_name, 0, + &utf8_fn); + if (ret != UTF8_CONVERT_OK) { + /* A bad encoding should never happen */ + assert(ret != UTF8_CONVERT_BADENC); + LOG(("utf8_from_local_encoding failed")); + /* Load was for us - just no memory */ + return true; + } + + /* Found: update form input. */ + free(file_box->gadget->value); + file_box->gadget->value = utf8_fn; + + /* Redraw box. */ + box_coords(file_box, &pos.x, &pos.y); + gui_window_redraw(bw->window, pos.x, pos.y, + pos.x + file_box->width, + pos.y + file_box->height); + } else { + + const char *filename = message->data.data_xfer.file_name; + + browser_window_mouse_click(g->bw, BROWSER_MOUSE_PRESS_1, pos.x, pos.y); + + if (!ro_gui_window_import_text(g, filename, false)) + return true; /* it was for us, it just didn't work! */ + } + + /* send DataLoadAck */ + message->action = message_DATA_LOAD_ACK; + message->your_ref = message->my_ref; + error = xwimp_send_message(wimp_USER_MESSAGE, message, message->sender); + if (error) { + LOG(("xwimp_send_message: 0x%x: %s\n", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + } + + return true; +} + + +/** + * Handle pointer movements in a browser window. + * + * \param g browser window that the pointer is in + * \param pointer new mouse position + */ + +void ro_gui_window_mouse_at(struct gui_window *g, wimp_pointer *pointer) +{ + os_coord pos; + + if (ro_gui_window_to_window_pos(g, pointer->pos.x, pointer->pos.y, &pos)) + browser_window_mouse_track(g->bw, + ro_gui_mouse_drag_state(pointer->buttons, + wimp_BUTTON_CLICK_DRAG), + pos.x, pos.y); +} + + +/** + * Window is being iconised. Create a suitable thumbnail sprite + * (which, sadly, must be in the Wimp sprite pool), and return + * the sprite name and truncated title to the iconiser + * + * \param g the gui window being iconised + * \param wi the WindowInfo message from the iconiser + */ + +void ro_gui_window_iconise(struct gui_window *g, + wimp_full_message_window_info *wi) +{ + /* sadly there is no 'legal' way to get the sprite into + * the Wimp sprite pool other than via a filing system */ + const char *temp_fname = "Pipe:$._tmpfile"; + struct browser_window *bw = g->bw; + osspriteop_header *overlay = NULL; + osspriteop_header *sprite_header; + struct bitmap *bitmap; + osspriteop_area *area; + int width = 34, height = 34; + hlcache_handle *h; + os_error *error; + int len, id; + + assert(bw); + + h = bw->current_content; + if (!h) return; + + /* if an overlay sprite is defined, locate it and gets its dimensions + * so that we can produce a thumbnail with the same dimensions */ + if (!ro_gui_wimp_get_sprite("ic_netsfxx", &overlay)) { + error = xosspriteop_read_sprite_info(osspriteop_PTR, + (osspriteop_area *)0x100, + (osspriteop_id)overlay, &width, &height, NULL, + NULL); + if (error) { + LOG(("xosspriteop_read_sprite_info: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("MiscError", error->errmess); + overlay = NULL; + } + else if (sprite_bpp(overlay) != 8) { + LOG(("overlay sprite is not 8bpp")); + overlay = NULL; + } + } + + /* create the thumbnail sprite */ + bitmap = bitmap_create(width, height, BITMAP_NEW | BITMAP_OPAQUE | + BITMAP_CLEAR_MEMORY); + if (!bitmap) { + LOG(("Thumbnail initialisation failed.")); + return; + } + thumbnail_create(h, bitmap, NULL); + if (overlay) + bitmap_overlay_sprite(bitmap, overlay); + area = thumbnail_convert_8bpp(bitmap); + bitmap_destroy(bitmap); + if (!area) { + LOG(("Thumbnail conversion failed.")); + return; + } + + /* choose a suitable sprite name */ + id = 0; + while (iconise_used[id]) + if ((unsigned)++id >= NOF_ELEMENTS(iconise_used)) { + id = iconise_next; + if ((unsigned)++iconise_next >= + NOF_ELEMENTS(iconise_used)) + iconise_next = 0; + break; + } + + sprite_header = (osspriteop_header *)(area + 1); + len = sprintf(sprite_header->name, "ic_netsf%.2d", id); + + error = xosspriteop_save_sprite_file(osspriteop_USER_AREA, + area, temp_fname); + if (error) { + LOG(("xosspriteop_save_sprite_file: 0x%x:%s", + error->errnum, error->errmess)); + warn_user("MiscError", error->errmess); + free(area); + return; + } + + error = xwimpspriteop_merge_sprite_file(temp_fname); + if (error) { + LOG(("xwimpspriteop_merge_sprite_file: 0x%x:%s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + remove(temp_fname); + free(area); + return; + } + + memcpy(wi->sprite_name, sprite_header->name + 3, len - 2); /* inc NUL */ + strncpy(wi->title, g->title, sizeof(wi->title)); + wi->title[sizeof(wi->title) - 1] = '\0'; + + if (wimptextop_string_width(wi->title, 0) > 182) { + /* work around bug in Pinboard where it will fail to display + * the icon if the text is very wide */ + if (strlen(wi->title) > 10) + wi->title[10] = '\0'; /* pinboard does this anyway */ + while (wimptextop_string_width(wi->title, 0) > 182) + wi->title[strlen(wi->title) - 1] = '\0'; + } + + wi->size = sizeof(wimp_full_message_window_info); + wi->your_ref = wi->my_ref; + error = xwimp_send_message(wimp_USER_MESSAGE, (wimp_message*)wi, + wi->sender); + if (error) { + LOG(("xwimp_send_message: 0x%x:%s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + } + else { + g->iconise_icon = id; + iconise_used[id] = true; + } + + free(area); +} + + +/** + * Completes scrolling of a browser window + * + * \param g gui window + */ + +void ro_gui_window_scroll_end(struct gui_window *g, wimp_dragged *drag) +{ + wimp_pointer pointer; + os_error *error; + os_coord pos; + + gui_current_drag_type = GUI_DRAG_NONE; + if (!g) + return; + + error = xwimp_drag_box((wimp_drag*)-1); + if (error) { + LOG(("xwimp_drag_box: 0x%x : %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + } + + error = xwimp_get_pointer_info(&pointer); + if (error) { + LOG(("xwimp_get_pointer_info 0x%x : %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return; + } + + error = xwimpspriteop_set_pointer_shape("ptr_default", 0x31, 0, 0, 0, 0); + if (error) { + LOG(("xwimpspriteop_set_pointer_shape: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + } + + if (ro_gui_window_to_window_pos(g, drag->final.x0, drag->final.y0, &pos)) + browser_window_mouse_drag_end(g->bw, + ro_gui_mouse_click_state(pointer.buttons, + wimp_BUTTON_CLICK_DRAG), + pos.x, pos.y); +} + + +/** + * Completes resizing of a browser frame + * + * \param g gui window + */ + +void ro_gui_window_frame_resize_end(struct gui_window *g, wimp_dragged *drag) +{ + /* our clean-up is the same as for page scrolling */ + ro_gui_window_scroll_end(g, drag); +} + + +/** + * Process Mouse_Click events in a toolbar's button bar. This does not handle + * other clicks in a toolbar: these are handled by the toolbar module itself. + * + * \param *data The GUI window associated with the click. + * \param action_type The action type to be handled. + * \param action The action to process. + */ + +void ro_gui_window_toolbar_click(void *data, + toolbar_action_type action_type, union toolbar_action action) +{ + struct gui_window *g = data; + struct browser_window *new_bw; + gui_save_type save_type; + + if (g == NULL) + return; + + + if (action_type == TOOLBAR_ACTION_URL && + action.url == TOOLBAR_URL_DRAG_URL) { + if (g->bw->current_content) { + hlcache_handle *h = g->bw->current_content; + + if (ro_gui_shift_pressed()) + save_type = GUI_SAVE_LINK_URL; + else + save_type = GUI_SAVE_LINK_TEXT; + + ro_gui_drag_save_link(save_type, content_get_url(h), + content_get_title(h), g); + } + + return; + } + + + /* By now, the only valid action left is a button click. If it isn't + * one of those, give up. + */ + + if (action_type != TOOLBAR_ACTION_BUTTON) + return; + + switch (action.button) { + case TOOLBAR_BUTTON_BACK: + if (g->bw != NULL && g->bw->history != NULL) + history_back(g->bw, g->bw->history); + break; + + case TOOLBAR_BUTTON_BACK_NEW: + ro_gui_window_action_navigate_back_new(g); + break; + + case TOOLBAR_BUTTON_FORWARD: + if (g->bw != NULL && g->bw->history != NULL) + history_forward(g->bw, g->bw->history); + break; + + case TOOLBAR_BUTTON_FORWARD_NEW: + ro_gui_window_action_navigate_forward_new(g); + break; + + case TOOLBAR_BUTTON_STOP: + if (g->bw != NULL) + browser_window_stop(g->bw); + break; + + case TOOLBAR_BUTTON_RELOAD: + if (g->bw != NULL) + browser_window_reload(g->bw, false); + break; + + case TOOLBAR_BUTTON_RELOAD_ALL: + if (g->bw != NULL) + browser_window_reload(g->bw, true); + break; + + case TOOLBAR_BUTTON_HISTORY_LOCAL: + ro_gui_window_action_local_history(g); + break; + + case TOOLBAR_BUTTON_HISTORY_GLOBAL: + ro_gui_global_history_open(); + break; + + case TOOLBAR_BUTTON_HOME: + ro_gui_window_action_home(g); + break; + + case TOOLBAR_BUTTON_SEARCH: + ro_gui_window_action_search(g); + break; + + case TOOLBAR_BUTTON_SCALE: + ro_gui_window_action_zoom(g); + break; + + case TOOLBAR_BUTTON_BOOKMARK_OPEN: + ro_gui_hotlist_open(); + break; + + case TOOLBAR_BUTTON_BOOKMARK_ADD: + ro_gui_window_action_add_bookmark(g); + break; + + case TOOLBAR_BUTTON_SAVE_SOURCE: + ro_gui_window_action_save(g, GUI_SAVE_SOURCE); + break; + + case TOOLBAR_BUTTON_SAVE_COMPLETE: + ro_gui_window_action_save(g, GUI_SAVE_COMPLETE); + break; + + case TOOLBAR_BUTTON_PRINT: + ro_gui_window_action_print(g); + break; + + case TOOLBAR_BUTTON_UP: + if (g->bw != NULL && g->bw->current_content != NULL) + ro_gui_window_navigate_up(g->bw->window, + content_get_url(g->bw->current_content)); + break; + + case TOOLBAR_BUTTON_UP_NEW: + if (g->bw && g->bw->current_content) { + hlcache_handle *h = g->bw->current_content; + new_bw = browser_window_create(NULL, + g->bw, NULL, false, + false); + /* do it without loading the content + * into the new window */ + ro_gui_window_navigate_up(new_bw->window, + content_get_url(h)); + } + break; + + default: + break; + } + + ro_gui_window_update_toolbar_buttons(g); +} + + +/** + * Handle Message_DataLoad (file dragged in) for a toolbar + * + * \TODO -- This belongs in the toolbar module, and should be moved there + * once the module is able to usefully handle its own events. + * + * \param g window + * \param message Message_DataLoad block + * \return true if the load was processed + */ + +bool ro_gui_toolbar_dataload(struct gui_window *g, wimp_message *message) +{ + if (message->data.data_xfer.file_type == osfile_TYPE_TEXT && + ro_gui_window_import_text(g, message->data.data_xfer.file_name, true)) { + + os_error *error; + + /* send DataLoadAck */ + message->action = message_DATA_LOAD_ACK; + message->your_ref = message->my_ref; + error = xwimp_send_message(wimp_USER_MESSAGE, message, message->sender); + if (error) { + LOG(("xwimp_send_message: 0x%x: %s\n", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + } + return true; + } + return false; +} + + +/* + * Helper code for the Wimp Event Handlers. + */ + +/** + * Check if a particular menu handle is a browser window menu + * + * \param *menu The menu in question. + * \return true if this menu is a browser window menu + */ + +bool ro_gui_window_check_menu(wimp_menu *menu) +{ + return (ro_gui_browser_window_menu == menu) ? true : false; +} + + +/** + * Return boolean flags to show what RISC OS types we can sensibly convert + * the given object into. + * + * \TODO -- This should probably be somewhere else but in window.c, and + * should probably even be done in content_(). + * + * \param *h The object to test. + * \param *export_draw true on exit if a drawfile would be possible. + * \param *export_sprite true on exit if a sprite would be possible. + * \return true if valid data is returned; else false. + */ + +bool ro_gui_window_content_export_types(hlcache_handle *h, + bool *export_draw, bool *export_sprite) +{ + bool found_type = false; + + if (export_draw != NULL) + *export_draw = false; + if (export_sprite != NULL) + *export_sprite = false; + + if (h != NULL) { + switch (content_get_type(h)) { + /* bitmap types (Sprite export possible) */ +#ifdef WITH_JPEG + case CONTENT_JPEG: +#endif +#ifdef WITH_MNG + case CONTENT_JNG: + case CONTENT_MNG: +#endif +#ifdef WITH_GIF + case CONTENT_GIF: +#endif +#ifdef WITH_BMP + case CONTENT_BMP: + case CONTENT_ICO: +#endif +#if defined(WITH_MNG) || defined(WITH_PNG) + case CONTENT_PNG: +#endif +#ifdef WITH_SPRITE + case CONTENT_SPRITE: +#endif + found_type = true; + if (export_sprite != NULL) + *export_sprite = true; + break; + + /* vector types (Draw export possible) */ +#if defined(WITH_NS_SVG) || defined(WITH_RSVG) + case CONTENT_SVG: +#endif +#ifdef WITH_DRAW + case CONTENT_DRAW: +#endif + found_type = true; + if (export_draw != NULL) + *export_draw = true; + break; + + default: + break; + } + } + + return found_type; +} + + +/** + * Return true if a browser window can navigate upwards. + * + * \TODO -- This should probably be somewhere else but in window.c. + * + * \param *bw the browser window to test. + * \return true if navigation up is possible; else false. + */ + +bool ro_gui_window_up_available(struct browser_window *bw) +{ + bool result = false, compare; + char *parent; + url_func_result res; + + if (bw != NULL && bw->current_content != NULL) { + res = url_parent(content_get_url(bw->current_content), &parent); + + if (res == URL_FUNC_OK) { + res = url_compare(content_get_url(bw->current_content), + parent, false, &compare); + if (res == URL_FUNC_OK) + result = !compare; + free(parent); + } else { + result = false; + } + } + + return result; +} + + +/** + * Prepare the page info window for use. + * + * \param *g The GUI window block to use. + */ + +void ro_gui_window_prepare_pageinfo(struct gui_window *g) +{ + hlcache_handle *h = g->bw->current_content; + char icon_buf[20] = "file_xxx"; + char enc_buf[40]; + char enc_token[10] = "Encoding0"; + const char *icon = icon_buf; + const char *title, *url, *mime; + const char *enc = "-"; + + assert(h); + + title = content_get_title(h); + if (title == NULL) + title = "-"; + url = content_get_url(h); + if (url == NULL) + url = "-"; + mime = content_get_mime_type(h); + if (mime == NULL) + mime = "-"; + + sprintf(icon_buf, "file_%x", ro_content_filetype(h)); + if (!ro_gui_wimp_sprite_exists(icon_buf)) + sprintf(icon_buf, "file_xxx"); + + if (content_get_type(h) == CONTENT_HTML) { + if (html_get_encoding(h)) { + enc_token[8] = '0' + html_get_encoding_source(h); + snprintf(enc_buf, sizeof enc_buf, "%s (%s)", + html_get_encoding(h), + messages_get(enc_token)); + enc = enc_buf; + } else { + enc = messages_get("EncodingUnk"); + } + } + + ro_gui_set_icon_string(dialog_pageinfo, ICON_PAGEINFO_ICON, + icon, true); + ro_gui_set_icon_string(dialog_pageinfo, ICON_PAGEINFO_TITLE, + title, true); + ro_gui_set_icon_string(dialog_pageinfo, ICON_PAGEINFO_URL, + url, true); + ro_gui_set_icon_string(dialog_pageinfo, ICON_PAGEINFO_ENC, + enc, true); + ro_gui_set_icon_string(dialog_pageinfo, ICON_PAGEINFO_TYPE, + mime, true); +} + + +/** + * Prepare the object info window for use + * + * \param *object the object for which information is to be displayed + * \param *href corresponding href, if any + */ + +void ro_gui_window_prepare_objectinfo(hlcache_handle *object, const char *href) +{ + char icon_buf[20] = "file_xxx"; + const char *url, *mime; + const char *target = "-"; + + sprintf(icon_buf, "file_%.3x", + ro_content_filetype(object)); + if (!ro_gui_wimp_sprite_exists(icon_buf)) + sprintf(icon_buf, "file_xxx"); + + url = content_get_url(object); + if (url == NULL) + url = "-"; + mime = content_get_mime_type(object); + if (mime == NULL) + mime = "-"; + + if (href) + target = href; + + ro_gui_set_icon_string(dialog_objinfo, ICON_OBJINFO_ICON, + icon_buf, true); + ro_gui_set_icon_string(dialog_objinfo, ICON_OBJINFO_URL, + url, true); + ro_gui_set_icon_string(dialog_objinfo, ICON_OBJINFO_TARGET, + target, true); + ro_gui_set_icon_string(dialog_objinfo, ICON_OBJINFO_TYPE, + mime, true); +} + + +/* + * User Actions in the browser window + */ + +/** + * Launch a new url in the given window. + * + * \param g gui_window to update + * \param url url to be launched + */ + +void ro_gui_window_launch_url(struct gui_window *g, const char *url) +{ + url_func_result res; + char *url_norm; + + ro_gui_url_complete_close(); + res = url_normalize(url, &url_norm); + if (res == URL_FUNC_OK) { + gui_window_set_url(g, url_norm); + browser_window_go(g->bw, url_norm, 0, true); + free(url_norm); + } +} + + +/** + * Navigate up one level + * + * \param g the gui_window to open the parent link in + * \param url the URL to open the parent of + */ +bool ro_gui_window_navigate_up(struct gui_window *g, const char *url) { + char *parent; + url_func_result res; + bool compare; + + if (!g || (!g->bw)) + return false; + + res = url_parent(url, &parent); + if (res == URL_FUNC_OK) { + res = url_compare(url, parent, false, &compare); + if ((res == URL_FUNC_OK) && !compare) + browser_window_go(g->bw, parent, 0, true); + free(parent); + } + return true; +} + + +/** + * Perform a Navigate Home action on a browser window. + * + * \param *g The browser window to act on. + */ + +void ro_gui_window_action_home(struct gui_window *g) +{ + char url[80]; + + if (g == NULL || g->bw == NULL) + return; + + if ((option_homepage_url) && (option_homepage_url[0])) { + browser_window_go(g->bw, option_homepage_url, 0, true); + } else { + snprintf(url, sizeof url, + "file:////Docs/welcome/index_%s", + option_language); + browser_window_go(g->bw, url, 0, true); + } +} + + +/** + * Navigate back from a browser window into a new window. + * + * \param *g The browser window to act on. + */ + +void ro_gui_window_action_navigate_back_new(struct gui_window *g) +{ + struct browser_window *new_bw; + + if (g == NULL || g->bw == NULL) + return; + + new_bw = browser_window_create(NULL, g->bw, NULL, false, false); + + if (new_bw != NULL && new_bw->history != NULL) + history_back(new_bw, new_bw->history); +} + + +/** + * Navigate forward from a browser window into a new window. + * + * \param *g The browser window to act on. + */ + +void ro_gui_window_action_navigate_forward_new(struct gui_window *g) +{ + struct browser_window *new_bw; + + if (g == NULL || g->bw == NULL) + return; + + new_bw = browser_window_create(NULL, g->bw, NULL, false, false); + + if (new_bw != NULL && new_bw->history != NULL) + history_forward(new_bw, new_bw->history); +} + + +/** + * Open a new browser window. + * + * \param *g The browser window to act on. + */ + +void ro_gui_window_action_new_window(struct gui_window *g) +{ + if (g == NULL || g->bw == NULL || g->bw->current_content == NULL) + return; + + browser_window_create(content_get_url(g->bw->current_content), g->bw, + 0, false, false); +} + + +/** + * Open a local history pane for a browser window. + * + * \param *g The browser window to act on. + */ + +void ro_gui_window_action_local_history(struct gui_window *g) +{ + if (g != NULL && g->bw != NULL && g->bw->history != NULL) + ro_gui_history_open(g->bw, g->bw->history, true); +} + + +/** + * Open a save dialogue for a browser window contents. + * + * \param *g The browser window to act on. + * \param save_type The type of save to open. + */ + +void ro_gui_window_action_save(struct gui_window *g, gui_save_type save_type) +{ + if (g == NULL || g->bw == NULL || g->bw->current_content == NULL) + return; + + ro_gui_save_prepare(save_type, g->bw->current_content, + NULL, NULL, NULL); + ro_gui_dialog_open_persistent(g->window, dialog_saveas, true); +} + + +/** + * Open a text search dialogue for a browser window. + * + * \param *g The browser window to act on. + */ + +void ro_gui_window_action_search(struct gui_window *g) +{ + if (g == NULL || g->bw == NULL || g->bw->current_content == NULL || + (content_get_type(g->bw->current_content) != + CONTENT_HTML && + content_get_type(g->bw->current_content) != + CONTENT_TEXTPLAIN)) + return; + + ro_gui_search_prepare(g->bw); + ro_gui_dialog_open_persistent(g->window, dialog_search, true); +} + + +/** + * Open a zoom dialogue for a browser window. + * + * \param *g The browser window to act on. + */ + +void ro_gui_window_action_zoom(struct gui_window *g) +{ + if (g == NULL) + return; + + ro_gui_dialog_prepare_zoom(g); + ro_gui_dialog_open_persistent(g->window, dialog_zoom, true); +} + + +/** + * Add a hotlist entry for a browser window. + * + * \param *g The browser window to act on. + */ + +void ro_gui_window_action_add_bookmark(struct gui_window *g) +{ + if (g == NULL || g->bw == NULL || g->bw->current_content == NULL || + content_get_url(g->bw->current_content) == NULL) + return; + + hotlist_add_page(content_get_url(g->bw->current_content)); +} + + +/** + * Open a print dialogue for a browser window. + * + * \param *g The browser window to act on. + */ + +void ro_gui_window_action_print(struct gui_window *g) +{ + if (g == NULL) + return; + + ro_gui_print_prepare(g); + ro_gui_dialog_open_persistent(g->window, dialog_print, true); +} + + +/** + * Open a page info box for a browser window. + * + * \param *g The browser window to act on. + */ + +void ro_gui_window_action_page_info(struct gui_window *g) +{ + if (g == NULL || g->bw == NULL || g->bw->current_content == NULL) + return; + + ro_gui_window_prepare_pageinfo(g); + ro_gui_dialog_open_persistent(g->window, dialog_pageinfo, false); +} + + +/* + * Window and Toolbar Redraw and Update + */ + +/** + * Redraws the content for all windows. + */ + +void ro_gui_window_redraw_all(void) +{ + struct gui_window *g; + for (g = window_list; g; g = g->next) + gui_window_redraw_window(g); +} + + +/** + * Remove all pending update boxes for a window + * + * \param g gui_window + */ +void ro_gui_window_remove_update_boxes(struct gui_window *g) +{ + struct update_box *cur; + + for (cur = pending_updates; cur != NULL; cur = cur->next) { + if (cur->g == g) + cur->g = NULL; + } +} + + +/** + * Redraw any pending update boxes. + */ +void ro_gui_window_update_boxes(void) +{ + osbool more; + bool use_buffer; + wimp_draw update; + struct rect clip; + os_error *error; + struct update_box *cur; + struct gui_window *g; + const union content_msg_data *data; + + for (cur = pending_updates; cur != NULL; cur = cur->next) { + g = cur->g; + if (!g) + continue; + + data = &cur->data; + use_buffer = cur->use_buffer; + + update.w = g->window; + update.box.x0 = cur->x0; + update.box.y0 = cur->y0; + update.box.x1 = cur->x1; + update.box.y1 = cur->y1; + + error = xwimp_update_window(&update, &more); + if (error) { + LOG(("xwimp_update_window: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + continue; + } + + /* Set the current redraw gui_window to get options from */ + ro_gui_current_redraw_gui = g; + current_redraw_browser = g->bw; + + plot = ro_plotters; + ro_plot_origin_x = update.box.x0 - update.xscroll; + ro_plot_origin_y = update.box.y1 - update.yscroll; + ro_plot_set_scale(g->bw->scale); + + while (more) { + clip.x0 = (update.clip.x0 - ro_plot_origin_x) / 2; + clip.y0 = (ro_plot_origin_y - update.clip.y1) / 2; + clip.x1 = (update.clip.x1 - ro_plot_origin_x) / 2; + clip.y1 = (ro_plot_origin_y - update.clip.y0) / 2; + + if (use_buffer) + ro_gui_buffer_open(&update); + + browser_window_redraw(g->bw, 0, 0, &clip); + + if (use_buffer) + ro_gui_buffer_close(); + + error = xwimp_get_rectangle(&update, &more); + /* RISC OS 3.7 returns an error here if enough buffer + * was claimed to cause a new dynamic area to be + * created. It doesn't actually stop anything working, + * so we mask it out for now until a better fix is + * found. This appears to be a bug in RISC OS. */ + if (error && !(use_buffer && + error->errnum == error_WIMP_GET_RECT)) { + LOG(("xwimp_get_rectangle: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + ro_gui_current_redraw_gui = NULL; + current_redraw_browser = NULL; + continue; + } + } + + /* Reset the current redraw gui_window to prevent + * thumbnails from retaining options */ + ro_gui_current_redraw_gui = NULL; + current_redraw_browser = NULL; + } + while (pending_updates) { + cur = pending_updates; + pending_updates = pending_updates->next; + free(cur); + } +} + + +/** + * Process pending reformats + */ + +void ro_gui_window_process_reformats(void) +{ + struct gui_window *g; + + browser_reformat_pending = false; + for (g = window_list; g; g = g->next) { + if (!g->bw->reformat_pending) + continue; + g->bw->reformat_pending = false; + browser_window_reformat(g->bw, + g->old_width / 2, + g->old_height / 2); + } +} + + +/** + * Destroy all browser windows. + */ + +void ro_gui_window_quit(void) +{ + struct gui_window *cur; + + while (window_list) { + cur = window_list; + window_list = window_list->next; + + /* framesets and iframes are destroyed by their parents */ + if (!cur->bw->parent) + browser_window_destroy(cur->bw); + } +} + + +/** + * Animate the "throbbers" of all browser windows. + */ + +void ro_gui_throb(void) +{ + struct gui_window *g; + struct browser_window *top; + + for (g = window_list; g; g = g->next) { + if (!g->bw->throbbing) + continue; + for (top = g->bw; top->parent; top = top->parent); + if (top->window != NULL && top->window->toolbar != NULL) + ro_toolbar_throb(top->window->toolbar); + } +} + + +/** + * Update the toolbar buttons for a given browser window to reflect the + * current state of its contents. + * + * Note that the parameters to this function are arranged so that it can be + * supplied to the toolbar module as an button state update callback. + * + * \param *g The browser window to update. + */ + +void ro_gui_window_update_toolbar_buttons(struct gui_window *g) +{ + struct browser_window *bw; + hlcache_handle *h; + struct toolbar *toolbar; + + if (g == NULL || g->toolbar == NULL) + return; + + bw = g->bw; + h = bw->current_content; + toolbar = g->toolbar; + + ro_toolbar_set_button_shaded_state(toolbar, TOOLBAR_BUTTON_RELOAD, + !browser_window_reload_available(bw)); + + ro_toolbar_set_button_shaded_state(toolbar, TOOLBAR_BUTTON_STOP, + !browser_window_stop_available(bw)); + + ro_toolbar_set_button_shaded_state(toolbar, TOOLBAR_BUTTON_BACK, + !browser_window_back_available(bw)); + + ro_toolbar_set_button_shaded_state(toolbar, TOOLBAR_BUTTON_FORWARD, + !browser_window_forward_available(bw)); + + ro_toolbar_set_button_shaded_state(toolbar, TOOLBAR_BUTTON_UP, + !ro_gui_window_up_available(bw)); + + ro_toolbar_set_button_shaded_state(toolbar, TOOLBAR_BUTTON_SEARCH, + h == NULL || (content_get_type(h) != CONTENT_HTML && + content_get_type(h) != CONTENT_TEXTPLAIN)); + + ro_toolbar_set_button_shaded_state(toolbar, TOOLBAR_BUTTON_SCALE, + h == NULL); + + ro_toolbar_set_button_shaded_state(toolbar, TOOLBAR_BUTTON_PRINT, + h == NULL); + + ro_toolbar_set_button_shaded_state(toolbar, TOOLBAR_BUTTON_SAVE_SOURCE, + h == NULL); + + ro_toolbar_update_urlsuggest(toolbar); +} + + +/** + * Update a window to reflect a change in toolbar size: used as a callback by + * the toolbar module when a toolbar height changes. + * + * \param *data void pointer the window's gui_window struct + */ + +void ro_gui_window_update_toolbar(void *data) +{ + struct gui_window *g = (struct gui_window *) data; + + if (g != NULL) + gui_window_update_extent(g); +} + + +/** + * Save a new toolbar button configuration: used as a callback by the toolbar + * module when a buttonbar edit has finished. + * + * \param *data void pointer to the window's gui_window struct + * \param *config pointer to a malloc()'d button config string. + */ + +void ro_gui_window_save_toolbar_buttons(void *data, char *config) +{ + if (option_toolbar_browser != NULL) + free(option_toolbar_browser); + option_toolbar_browser = config; + ro_gui_save_options(); +} + + +/** + * Update a window and its toolbar to reflect a new theme: used as a callback + * by the toolbar module when a theme change affects a toolbar. + * + * \param *data void pointer to the window's gui_window struct + * \param ok true if the bar still exists; else false. + */ + +void ro_gui_window_update_theme(void *data, bool ok) +{ + struct gui_window *g = (struct gui_window *) data; + + if (g != NULL && g->toolbar != NULL) { + if (ok) { + gui_window_update_extent(g); + } else { + g->toolbar = NULL; + } + } +} + + +/* + * General Window Support + */ + +/** + * Import text file into window or its toolbar + * + * \param g gui window containing textarea + * \param filename pathname of file to be imported + * \param toolbar true iff imported to toolbar rather than main window + * \return true iff successful + */ + +bool ro_gui_window_import_text(struct gui_window *g, const char *filename, + bool toolbar) +{ + fileswitch_object_type obj_type; + os_error *error; + char *buf, *utf8_buf; + int size; + utf8_convert_ret ret; + + error = xosfile_read_stamped(filename, &obj_type, NULL, NULL, + &size, NULL, NULL); + if (error) { + LOG(("xosfile_read_stamped: 0x%x:%s", + error->errnum, error->errmess)); + warn_user("FileError", error->errmess); + return true; /* was for us, but it didn't work! */ + } buf = malloc(size); if (!buf) { @@ -3299,169 +4683,510 @@ bool ro_gui_window_import_text(struct gui_window *g, const char *filename, p += utf8_next(p, ep - p, 0); *p = '\0'; - if (p > sp) - ro_gui_window_launch_url(g, sp); - } - else - browser_window_paste_text(g->bw, utf8_buf, size, true); + if (p > sp) + ro_gui_window_launch_url(g, sp); + } + else + browser_window_paste_text(g->bw, utf8_buf, size, true); + + free(buf); + free(utf8_buf); + return true; +} + + +/** + * Clones a browser window's options. + * + * \param new_bw the new browser window + * \param old_bw the browser window to clone from, or NULL for default + */ + +void ro_gui_window_clone_options(struct browser_window *new_bw, + struct browser_window *old_bw) +{ + struct gui_window *old_gui = NULL; + struct gui_window *new_gui; + + assert(new_bw); + + /* Get our GUIs + */ + new_gui = new_bw->window; + + if (old_bw) + old_gui = old_bw->window; + + /* Clone the basic options + */ + if (!old_gui) { + new_bw->scale = ((float)option_scale) / 100; + new_gui->option.background_images = option_background_images; + new_gui->option.buffer_animations = option_buffer_animations; + new_gui->option.buffer_everything = option_buffer_everything; + } else { + new_gui->option = old_gui->option; + } + + /* Set up the toolbar + */ + if (new_gui->toolbar) { + ro_toolbar_set_display_buttons(new_gui->toolbar, + option_toolbar_show_buttons); + ro_toolbar_set_display_url(new_gui->toolbar, + option_toolbar_show_address); + ro_toolbar_set_display_throbber(new_gui->toolbar, + option_toolbar_show_throbber); + if ((old_gui) && (old_gui->toolbar)) { + ro_toolbar_set_display_buttons(new_gui->toolbar, + ro_toolbar_get_display_buttons( + old_gui->toolbar)); + ro_toolbar_set_display_url(new_gui->toolbar, + ro_toolbar_get_display_url( + old_gui->toolbar)); + ro_toolbar_set_display_throbber(new_gui->toolbar, + ro_toolbar_get_display_throbber( + old_gui->toolbar)); + ro_toolbar_process(new_gui->toolbar, -1, true); + } + } +} + + +/** + * Makes a browser window's options the default. + * + * \param bw the browser window to read options from + */ + +void ro_gui_window_default_options(struct browser_window *bw) +{ + struct gui_window *gui; + + assert(bw); + + /* Get our GUI + */ + gui = bw->window; + if (!gui) return; + + /* Save the basic options + */ + option_scale = bw->scale * 100; + option_buffer_animations = gui->option.buffer_animations; + option_buffer_everything = gui->option.buffer_everything; + + /* Set up the toolbar + */ + if (gui->toolbar != NULL) { + option_toolbar_show_buttons = + ro_toolbar_get_display_buttons(gui->toolbar); + option_toolbar_show_address = + ro_toolbar_get_display_url(gui->toolbar); + option_toolbar_show_throbber = + ro_toolbar_get_display_throbber(gui->toolbar); + } + if (gui->status_bar != NULL) + option_toolbar_status_width = + ro_gui_status_bar_get_width(gui->status_bar); +} + + +/* + * Custom Menu Support + */ + +/** + * Prepare or reprepare a form select menu, setting up the menu handle + * global in the process. + * + * \param *bw The browser window to contain the menu. + * \param *control The form control needing a menu. + * \return true if the menu is OK to be opened; else false. + */ + +bool ro_gui_window_prepare_form_select_menu(struct browser_window *bw, + struct form_control *control) +{ + unsigned int i, entries; + char *text_convert, *temp; + struct form_option *option; + bool reopen = true; + utf8_convert_ret err; + + assert(control); + + for (entries = 0, option = control->data.select.items; option; + option = option->next) + entries++; + if (entries == 0) { + ro_gui_menu_closed(); + return false; + } + + if ((gui_form_select_menu) && (control != gui_form_select_control)) { + for (i = 0; ; i++) { + free(gui_form_select_menu->entries[i].data. + indirected_text.text); + if (gui_form_select_menu->entries[i].menu_flags & + wimp_MENU_LAST) + break; + } + free(gui_form_select_menu->title_data.indirected_text.text); + free(gui_form_select_menu); + gui_form_select_menu = 0; + } + + if (!gui_form_select_menu) { + reopen = false; + gui_form_select_menu = malloc(wimp_SIZEOF_MENU(entries)); + if (!gui_form_select_menu) { + warn_user("NoMemory", 0); + ro_gui_menu_closed(); + return false; + } + err = utf8_to_local_encoding(messages_get("SelectMenu"), 0, + &text_convert); + if (err != UTF8_CONVERT_OK) { + /* badenc should never happen */ + assert(err != UTF8_CONVERT_BADENC); + LOG(("utf8_to_local_encoding failed")); + warn_user("NoMemory", 0); + ro_gui_menu_closed(); + return false; + } + gui_form_select_menu->title_data.indirected_text.text = + text_convert; + ro_gui_menu_init_structure(gui_form_select_menu, entries); + } + + for (i = 0, option = control->data.select.items; option; + i++, option = option->next) { + gui_form_select_menu->entries[i].menu_flags = 0; + if (option->selected) + gui_form_select_menu->entries[i].menu_flags = + wimp_MENU_TICKED; + if (!reopen) { + + /* convert spaces to hard spaces to stop things + * like 'Go Home' being treated as if 'Home' is a + * keyboard shortcut and right aligned in the menu. + */ + + temp = cnv_space2nbsp(option->text); + if (!temp) { + LOG(("cnv_space2nbsp failed")); + warn_user("NoMemory", 0); + ro_gui_menu_closed(); + return false; + } + + err = utf8_to_local_encoding(temp, + 0, &text_convert); + if (err != UTF8_CONVERT_OK) { + /* A bad encoding should never happen, + * so assert this */ + assert(err != UTF8_CONVERT_BADENC); + LOG(("utf8_to_enc failed")); + warn_user("NoMemory", 0); + ro_gui_menu_closed(); + return false; + } + + free(temp); + + gui_form_select_menu->entries[i].data.indirected_text.text = + text_convert; + gui_form_select_menu->entries[i].data.indirected_text.size = + strlen(gui_form_select_menu->entries[i]. + data.indirected_text.text) + 1; + } + } + + gui_form_select_menu->entries[0].menu_flags |= + wimp_MENU_TITLE_INDIRECTED; + gui_form_select_menu->entries[i - 1].menu_flags |= wimp_MENU_LAST; + + return true; +} + +/** + * Process selections from a form select menu, passing them back to the core. + * + * \param *g The browser window affected by the menu. + * \param *selection The menu selection. + */ + +void ro_gui_window_process_form_select_menu(struct gui_window *g, + wimp_selection *selection) +{ + assert(g != NULL); + + if (selection->items[0] >= 0) + form_select_process_selection(g->bw->current_content, + gui_form_select_control, + selection->items[0]); +} + + +/* + * Window and Toolbar Lookup + */ + +/** + * Convert a RISC OS window handle to a gui_window. + * + * \param w RISC OS window handle + * \return pointer to a structure if found, 0 otherwise + */ + +struct gui_window *ro_gui_window_lookup(wimp_w window) +{ + struct gui_window *g; + for (g = window_list; g; g = g->next) + if (g->window == window) + return g; + return 0; +} + + +/** + * Convert a toolbar RISC OS window handle to a gui_window. + * + * \param w RISC OS window handle of a toolbar + * \return pointer to a structure if found, 0 otherwise + */ + +struct gui_window *ro_gui_toolbar_lookup(wimp_w window) +{ + struct gui_window *g = NULL; + struct toolbar *toolbar; + wimp_w parent; + + toolbar = ro_toolbar_window_lookup(window); + + if (toolbar != NULL) { + parent = ro_toolbar_get_parent_window(toolbar); + g = ro_gui_window_lookup(parent); + } + + return g; +} + + +/* + * Core to RISC OS Conversions + */ + +/** + * Convert x,y screen co-ordinates into window co-ordinates. + * + * \param g gui window + * \param x x ordinate + * \param y y ordinate + * \param pos receives position in window co-ordinatates + * \return true iff conversion successful + */ + +bool ro_gui_window_to_window_pos(struct gui_window *g, int x, int y, + os_coord *pos) +{ + wimp_window_state state; + os_error *error; + + assert(g); + + 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 false; + } + pos->x = (x - (state.visible.x0 - state.xscroll)) / 2 / g->bw->scale; + pos->y = ((state.visible.y1 - state.yscroll) - y) / 2 / g->bw->scale; + return true; +} + + +/** + * Convert x,y window co-ordinates into screen co-ordinates. + * + * \param g gui window + * \param x x ordinate + * \param y y ordinate + * \param pos receives position in screen co-ordinatates + * \return true iff conversion successful + */ + +bool ro_gui_window_to_screen_pos(struct gui_window *g, int x, int y, + os_coord *pos) +{ + wimp_window_state state; + os_error *error; + + assert(g); - free(buf); - free(utf8_buf); + 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 false; + } + pos->x = (x * 2 * g->bw->scale) + (state.visible.x0 - state.xscroll); + pos->y = (state.visible.y1 - state.yscroll) - (y * 2 * g->bw->scale); return true; } +/* + * Miscellaneous Functions + * + * \TODO -- These items might well belong elsewhere. + */ + /** - * Window is being iconised. Create a suitable thumbnail sprite - * (which, sadly, must be in the Wimp sprite pool), and return - * the sprite name and truncated title to the iconiser + * Returns the state of the mouse buttons and modifiers keys for a + * mouse action, suitable for passing to the OS-independent + * browser window/ treeview/ etc code. * - * \param g the gui window being iconised - * \param wi the WindowInfo message from the iconiser + * \param buttons Wimp button state. + * \param type Wimp work-area/icon type for decoding. + * \return NetSurf core button state. */ -void ro_gui_window_iconise(struct gui_window *g, - wimp_full_message_window_info *wi) +browser_mouse_state ro_gui_mouse_click_state(wimp_mouse_state buttons, + wimp_icon_flags type) { - /* sadly there is no 'legal' way to get the sprite into - * the Wimp sprite pool other than via a filing system */ - const char *temp_fname = "Pipe:$._tmpfile"; - struct browser_window *bw = g->bw; - osspriteop_header *overlay = NULL; - osspriteop_header *sprite_header; - struct bitmap *bitmap; - osspriteop_area *area; - int width = 34, height = 34; - hlcache_handle *h; - os_error *error; - int len, id; + browser_mouse_state state = 0; /* Blank state with nothing set */ - assert(bw); + switch (type) { + case wimp_BUTTON_CLICK_DRAG: /* Used for browser window */ + /* Handle single clicks. */ - h = bw->current_content; - if (!h) return; + /* We fire core PRESS and CLICK events together for "action on + * press" behaviour. */ + if (buttons & (wimp_CLICK_SELECT)) /* Select click */ + state |= BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_CLICK_1; + if (buttons & (wimp_CLICK_ADJUST)) /* Adjust click */ + state |= BROWSER_MOUSE_PRESS_2 | BROWSER_MOUSE_CLICK_2; + break; + case wimp_BUTTON_DOUBLE_CLICK_DRAG: /* Used for treeview window */ + /* Handle single and double clicks. */ - /* if an overlay sprite is defined, locate it and gets its dimensions - * so that we can produce a thumbnail with the same dimensions */ - if (!ro_gui_wimp_get_sprite("ic_netsfxx", &overlay)) { - error = xosspriteop_read_sprite_info(osspriteop_PTR, - (osspriteop_area *)0x100, - (osspriteop_id)overlay, &width, &height, NULL, - NULL); - if (error) { - LOG(("xosspriteop_read_sprite_info: 0x%x: %s", - error->errnum, error->errmess)); - warn_user("MiscError", error->errmess); - overlay = NULL; - } - else if (sprite_bpp(overlay) != 8) { - LOG(("overlay sprite is not 8bpp")); - overlay = NULL; - } + /* Single clicks: Fire PRESS and CLICK events together + * for "action on press" behaviour. */ + if (buttons & (wimp_SINGLE_SELECT)) /* Select single click */ + state |= BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_CLICK_1; + if (buttons & (wimp_SINGLE_ADJUST)) /* Adjust single click */ + state |= BROWSER_MOUSE_PRESS_2 | BROWSER_MOUSE_CLICK_2; + + /* Double clicks: Fire PRESS, CLICK, and DOUBLE_CLICK + * events together for "action on 2nd press" behaviour. */ + if (buttons & (wimp_DOUBLE_SELECT)) /* Select double click */ + state |= BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_CLICK_1 | + BROWSER_MOUSE_DOUBLE_CLICK; + if (buttons & (wimp_DOUBLE_ADJUST)) /* Adjust double click */ + state |= BROWSER_MOUSE_PRESS_2 | BROWSER_MOUSE_CLICK_2 | + BROWSER_MOUSE_DOUBLE_CLICK; + break; } - /* create the thumbnail sprite */ - bitmap = bitmap_create(width, height, BITMAP_NEW | BITMAP_OPAQUE | - BITMAP_CLEAR_MEMORY); - if (!bitmap) { - LOG(("Thumbnail initialisation failed.")); - return; + /* Check if a drag has started */ + if (buttons & (wimp_DRAG_SELECT)) { + /* A drag was _started_ with Select; Fire DRAG_1. */ + state |= BROWSER_MOUSE_DRAG_1; + mouse_drag_select = true; } - thumbnail_create(h, bitmap, NULL); - if (overlay) - bitmap_overlay_sprite(bitmap, overlay); - area = thumbnail_convert_8bpp(bitmap); - bitmap_destroy(bitmap); - if (!area) { - LOG(("Thumbnail conversion failed.")); - return; + if (buttons & (wimp_DRAG_ADJUST)) { + /* A drag was _started_ with Adjust; Fire DRAG_2. */ + state |= BROWSER_MOUSE_DRAG_2; + mouse_drag_adjust = true; } - /* choose a suitable sprite name */ - id = 0; - while (iconise_used[id]) - if ((unsigned)++id >= NOF_ELEMENTS(iconise_used)) { - id = iconise_next; - if ((unsigned)++iconise_next >= - NOF_ELEMENTS(iconise_used)) - iconise_next = 0; - break; - } + /* Set modifier key state */ + if (ro_gui_shift_pressed()) state |= BROWSER_MOUSE_MOD_1; + if (ro_gui_ctrl_pressed()) state |= BROWSER_MOUSE_MOD_2; + if (ro_gui_alt_pressed()) state |= BROWSER_MOUSE_MOD_3; - sprite_header = (osspriteop_header *)(area + 1); - len = sprintf(sprite_header->name, "ic_netsf%.2d", id); + return state; +} - error = xosspriteop_save_sprite_file(osspriteop_USER_AREA, - area, temp_fname); - if (error) { - LOG(("xosspriteop_save_sprite_file: 0x%x:%s", - error->errnum, error->errmess)); - warn_user("MiscError", error->errmess); - free(area); - return; - } - error = xwimpspriteop_merge_sprite_file(temp_fname); - if (error) { - LOG(("xwimpspriteop_merge_sprite_file: 0x%x:%s", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); - remove(temp_fname); - free(area); - return; - } +/** + * Returns the state of the mouse buttons and modifiers keys whilst + * dragging, for passing to the OS-independent browser window/ treeview/ + * etc code + * + * \param buttons Wimp button state. + * \param type Wimp work-area/icon type for decoding. + * \return NetSurf core button state. + */ - memcpy(wi->sprite_name, sprite_header->name + 3, len - 2); /* inc NUL */ - strncpy(wi->title, g->title, sizeof(wi->title)); - wi->title[sizeof(wi->title) - 1] = '\0'; +browser_mouse_state ro_gui_mouse_drag_state(wimp_mouse_state buttons, + wimp_icon_flags type) +{ + browser_mouse_state state = 0; /* Blank state with nothing set */ - if (wimptextop_string_width(wi->title, 0) > 182) { - /* work around bug in Pinboard where it will fail to display - * the icon if the text is very wide */ - if (strlen(wi->title) > 10) - wi->title[10] = '\0'; /* pinboard does this anyway */ - while (wimptextop_string_width(wi->title, 0) > 182) - wi->title[strlen(wi->title) - 1] = '\0'; + /* If mouse buttons aren't held, turn off drags */ + if (!(buttons & (wimp_CLICK_SELECT) || buttons & (wimp_CLICK_ADJUST))) { + mouse_drag_select = false; + mouse_drag_adjust = false; } - wi->size = sizeof(wimp_full_message_window_info); - wi->your_ref = wi->my_ref; - error = xwimp_send_message(wimp_USER_MESSAGE, (wimp_message*)wi, - wi->sender); - if (error) { - LOG(("xwimp_send_message: 0x%x:%s", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); + /* If there's a drag happening, set DRAG_ON and record which button + * the drag is happening with, i.e. HOLDING_1 or HOLDING_2 */ + if (mouse_drag_select) { + state |= BROWSER_MOUSE_DRAG_ON | BROWSER_MOUSE_HOLDING_1; } - else { - g->iconise_icon = id; - iconise_used[id] = true; + if (mouse_drag_adjust) { + state |= BROWSER_MOUSE_DRAG_ON | BROWSER_MOUSE_HOLDING_2; } - free(area); + /* Set modifier key state */ + if (ro_gui_shift_pressed()) state |= BROWSER_MOUSE_MOD_1; + if (ro_gui_ctrl_pressed()) state |= BROWSER_MOUSE_MOD_2; + if (ro_gui_alt_pressed()) state |= BROWSER_MOUSE_MOD_3; + + return state; } /** - * Navigate up one level - * - * \param g the gui_window to open the parent link in - * \param url the URL to open the parent of + * Returns true iff one or more Shift keys is held down */ -bool ro_gui_window_navigate_up(struct gui_window *g, const char *url) { - char *parent; - url_func_result res; - bool compare; - if (!g || (!g->bw)) - return false; +bool ro_gui_shift_pressed(void) +{ + int shift = 0; + xosbyte1(osbyte_SCAN_KEYBOARD, 0 ^ 0x80, 0, &shift); + return (shift == 0xff); +} - res = url_parent(url, &parent); - if (res == URL_FUNC_OK) { - res = url_compare(url, parent, false, &compare); - if ((res == URL_FUNC_OK) && !compare) - browser_window_go(g->bw, parent, 0, true); - free(parent); - } - return true; + +/** + * Returns true iff one or more Ctrl keys is held down + */ + +bool ro_gui_ctrl_pressed(void) +{ + int ctrl = 0; + xosbyte1(osbyte_SCAN_KEYBOARD, 1 ^ 0x80, 0, &ctrl); + return (ctrl == 0xff); +} + + +/** + * Returns true iff one or more Alt keys is held down + */ + +bool ro_gui_alt_pressed(void) +{ + int alt = 0; + xosbyte1(osbyte_SCAN_KEYBOARD, 2 ^ 0x80, 0, &alt); + return (alt == 0xff); } + diff --git a/riscos/window.h b/riscos/window.h new file mode 100644 index 000000000..adbd999f9 --- /dev/null +++ b/riscos/window.h @@ -0,0 +1,33 @@ +/* + * Copyright 2010, 2011 Stephen Fryatt + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** \file + * Browser window handling (interface). + */ + +#include + +#ifndef _NETSURF_RISCOS_WINDOW_H_ +#define _NETSURF_RISCOS_WINDOW_H_ + +void ro_gui_window_initialise(void); + +bool ro_gui_window_check_menu(wimp_menu *menu); + +#endif + -- cgit v1.2.3