From 6173bb0e6c3bf51cd463f7bc4f725429d9087b2b Mon Sep 17 00:00:00 2001 From: John Mark Bell Date: Tue, 5 Oct 2010 19:14:46 +0000 Subject: Merge treeview-redux to trunk svn path=/trunk/netsurf/; revision=10865 --- riscos/configure/con_home.c | 6 +- riscos/cookies.c | 346 +++++--- riscos/cookies.h | 10 +- riscos/dialog.c | 76 +- riscos/global_history.c | 534 +++++------ riscos/global_history.h | 12 +- riscos/gui.c | 81 +- riscos/gui.h | 17 +- riscos/help.c | 28 +- riscos/hotlist.c | 540 ++++++------ riscos/hotlist.h | 36 + riscos/menus.c | 682 +++++---------- riscos/menus.h | 20 + riscos/save.c | 14 +- riscos/sslcert.c | 515 +++++------ riscos/sslcert.h | 32 + riscos/textselection.c | 25 +- riscos/theme.c | 28 +- riscos/treeview.c | 2044 ++++++++++++++++--------------------------- riscos/treeview.h | 49 +- riscos/url_complete.c | 6 +- riscos/url_suggest.c | 200 +++++ riscos/url_suggest.h | 34 + riscos/wimp_event.c | 203 ++++- riscos/wimp_event.h | 22 +- riscos/window.c | 78 +- 26 files changed, 2575 insertions(+), 3063 deletions(-) create mode 100644 riscos/hotlist.h create mode 100644 riscos/sslcert.h create mode 100644 riscos/url_suggest.c create mode 100644 riscos/url_suggest.h (limited to 'riscos') diff --git a/riscos/configure/con_home.c b/riscos/configure/con_home.c index afced9557..fbe1b7039 100644 --- a/riscos/configure/con_home.c +++ b/riscos/configure/con_home.c @@ -22,6 +22,7 @@ #include "riscos/gui.h" #include "riscos/menus.h" #include "riscos/options.h" +#include "riscos/url_suggest.h" #include "riscos/wimp.h" #include "riscos/wimp_event.h" #include "riscos/configure.h" @@ -42,16 +43,13 @@ static bool ro_gui_options_home_ok(wimp_w w); bool ro_gui_options_home_initialise(wimp_w w) { - int suggestions; - /* set the current values */ ro_gui_set_icon_string(w, HOME_URL_FIELD, option_homepage_url ? option_homepage_url : "", true); ro_gui_set_icon_selected_state(w, HOME_OPEN_STARTUP, option_open_browser_at_startup); - global_history_get_recent(&suggestions); ro_gui_set_icon_shaded_state(w, - HOME_URL_GRIGHT, (suggestions <= 0)); + HOME_URL_GRIGHT, !ro_gui_url_suggest_prepare_menu()); /* initialise all functions for a newly created window */ ro_gui_wimp_event_register_menu_gright(w, HOME_URL_FIELD, diff --git a/riscos/cookies.c b/riscos/cookies.c index 312f2e479..b0c035adc 100644 --- a/riscos/cookies.c +++ b/riscos/cookies.c @@ -1,5 +1,6 @@ /* * Copyright 2006 Richard Wilson + * Copyright 2010 Stephen Fryatt * * This file is part of NetSurf, http://www.netsurf-browser.org/ * @@ -44,174 +45,243 @@ #include "utils/url.h" #include "utils/utils.h" -static bool ro_gui_cookies_click(wimp_pointer *pointer); -static struct node *ro_gui_cookies_find(const char *url); +static void ro_gui_cookies_menu_prepare(wimp_w window, wimp_menu *menu); +static bool ro_gui_cookies_menu_select(wimp_w window, wimp_menu *menu, + wimp_selection *selection, menu_action action); +static void ro_gui_cookies_menu_warning(wimp_w window, wimp_menu *menu, + wimp_selection *selection, menu_action action); -/* The history window, toolbar and plot origins */ -static wimp_w cookies_window; -struct tree *cookies_tree; -static bool cookies_init; +/* The RISC OS cookie window, toolbar and treeview data. */ + +static struct ro_cookies_window { + wimp_w window; + struct toolbar *toolbar; + ro_treeview *tv; + wimp_menu *menu; +} cookies_window; /** - * Initialise cookies tree + * Pre-Initialise the cookies tree. This is called for things that + * need to be done at the gui_init() stage, such as loading templates. */ -void ro_gui_cookies_initialise(void) + +void ro_gui_cookies_preinitialise(void) { - /* create our window */ - cookies_window = ro_gui_dialog_create("tree"); - ro_gui_set_window_title(cookies_window, + /* Create our window. */ + + cookies_window.window = ro_gui_dialog_create("tree"); + ro_gui_set_window_title(cookies_window.window, messages_get("Cookies")); - ro_gui_wimp_event_register_redraw_window(cookies_window, - ro_gui_tree_redraw); - ro_gui_wimp_event_register_open_window(cookies_window, - ro_gui_tree_open); - ro_gui_wimp_event_register_mouse_click(cookies_window, - ro_gui_cookies_click); - - /* Create an empty tree */ - cookies_tree = calloc(sizeof(struct tree), 1); - if (!cookies_tree) { - warn_user("NoMemory", 0); - return; - } - cookies_tree->root = tree_create_folder_node(NULL, "Root"); - if (!cookies_tree->root) { - warn_user("NoMemory", 0); - free(cookies_tree); - cookies_tree = NULL; +} + +/** + * Initialise cookies tree, at the gui_init2() stage. + */ + +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); + + /* Create the treeview with the window and toolbar. */ + + cookies_window.tv = ro_treeview_create(cookies_window.window, + cookies_window.toolbar, cookies_get_tree_flags()); + if (cookies_window.tv == NULL) { + LOG(("Failed to allocate treeview")); return; } - cookies_tree->root->expanded = true; - cookies_tree->handle = (int)cookies_window; - cookies_tree->movable = false; - cookies_tree->no_drag = true; - ro_gui_wimp_event_set_user_data(cookies_window, - cookies_tree); - ro_gui_wimp_event_register_keypress(cookies_window, - ro_gui_tree_keypress); - - /* Create our toolbar */ - cookies_tree->toolbar = ro_gui_theme_create_toolbar(NULL, - THEME_COOKIES_TOOLBAR); - if (cookies_tree->toolbar) - ro_gui_theme_attach_toolbar(cookies_tree->toolbar, - cookies_window); - - cookies_init = true; - urldb_iterate_cookies(cookies_update); - cookies_init = false; - tree_initialise(cookies_tree); + + /* Initialise the cookies into the tree. */ + + cookies_initialise(ro_treeview_get_tree(cookies_window.tv)); + + + /* Build the cookies window menu. */ + + static const struct ns_menu cookies_definition = { + "Cookies", { + { "Cookies", NO_ACTION, 0 }, + { "Cookies.Expand", TREE_EXPAND_ALL, 0 }, + { "Cookies.Expand.All", TREE_EXPAND_ALL, 0 }, + { "Cookies.Expand.Folders", TREE_EXPAND_FOLDERS, 0 }, + { "Cookies.Expand.Links", TREE_EXPAND_LINKS, 0 }, + { "Cookies.Collapse", TREE_COLLAPSE_ALL, 0 }, + { "Cookies.Collapse.All", TREE_COLLAPSE_ALL, 0 }, + { "Cookies.Collapse.Folders", TREE_COLLAPSE_FOLDERS, 0 }, + { "Cookies.Collapse.Links", TREE_COLLAPSE_LINKS, 0 }, + { "Cookies.Toolbars", NO_ACTION, 0 }, + { "_Cookies.Toolbars.ToolButtons", TOOLBAR_BUTTONS, 0 }, + { "Cookies.Toolbars.EditToolbar",TOOLBAR_EDIT, 0 }, + { "Selection", TREE_SELECTION, 0 }, + { "Selection.Delete", TREE_SELECTION_DELETE, 0 }, + { "SelectAll", TREE_SELECT_ALL, 0 }, + { "Clear", TREE_CLEAR_SELECTION, 0 }, + {NULL, 0, 0} + } + }; + 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); } +/** + * \TODO - Open the cookies window. + * + */ + +void ro_gui_cookies_open(void) +{ + tree_set_redraw(ro_treeview_get_tree(cookies_window.tv), true); + + 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))); + } +} /** - * Respond to a mouse click + * Prepare the cookies menu for opening * - * \param pointer the pointer state - * \return true to indicate click handled + * \param window The window owning the menu. + * \param *menu The menu about to be opened. */ -bool ro_gui_cookies_click(wimp_pointer *pointer) + +void ro_gui_cookies_menu_prepare(wimp_w window, wimp_menu *menu) { - ro_gui_tree_click(pointer, cookies_tree); - if (pointer->buttons == wimp_CLICK_MENU) - ro_gui_menu_create(cookies_menu, pointer->pos.x, - pointer->pos.y, pointer->w); - else - ro_gui_menu_prepare_action(pointer->w, TREE_SELECTION, false); - return true; + bool selection; + + 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, TOOLBAR_BUTTONS, + (cookies_window.toolbar == NULL || + cookies_window.toolbar->editor)); + ro_gui_menu_set_entry_ticked(cookies_window.menu, TOOLBAR_BUTTONS, + (cookies_window.toolbar != NULL && + (cookies_window.toolbar->display_buttons || + (cookies_window.toolbar->editor)))); + + ro_gui_menu_set_entry_shaded(cookies_window.menu, TOOLBAR_EDIT, + cookies_window.toolbar == NULL); + ro_gui_menu_set_entry_ticked(cookies_window.menu, TOOLBAR_EDIT, + (cookies_window.toolbar != NULL && + cookies_window.toolbar->editor)); } +/** + * Handle submenu warnings for the cookies menu + * + * \param window The window 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, + wimp_selection *selection, menu_action action) +{ + /* Do nothing */ +} /** - * Perform cookie addition + * Handle selections from the cookies menu * - * \param data Cookie data for a domain, or NULL - * \return true (for urldb_iterate_entries) + * \param window The window 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 cookies_update(const char *domain, const struct cookie_data *data) + +bool ro_gui_cookies_menu_select(wimp_w window, wimp_menu *menu, + wimp_selection *selection, menu_action action) { - struct node *parent; - struct node *node = NULL; - struct node *child; - struct node *add; - const struct cookie_data *cookie = NULL; - bool expanded; - - assert(domain); - - /* check if we're a domain, and add get the first cookie */ - if (data) - for (cookie = data; cookie->prev; cookie = cookie->prev); - - if (!cookies_init) { - node = ro_gui_cookies_find(domain); - if (node) { - /* mark as deleted so we don't remove the cookies */ - expanded = node->expanded; - for (child = node->child; child; child = child->next) - child->deleted = true; - if (node->child) - tree_delete_node(cookies_tree, node->child, - true); - /* deleting will have contracted our node */ - node->expanded = expanded; - } - if (!data) { - if (!node) - return true; - tree_delete_node(cookies_tree, node, false); - tree_handle_node_changed(cookies_tree, - cookies_tree->root, true, false); - return true; - } + switch (action) { + case TREE_EXPAND_ALL: + cookies_expand_all(); + return true; + case TREE_EXPAND_FOLDERS: + cookies_expand_domains(); + return true; + case TREE_EXPAND_LINKS: + cookies_expand_cookies(); + return true; + case TREE_COLLAPSE_ALL: + cookies_collapse_all(); + return true; + case TREE_COLLAPSE_FOLDERS: + cookies_collapse_domains(); + return true; + case TREE_COLLAPSE_LINKS: + cookies_collapse_cookies(); + return true; + case TREE_SELECTION_DELETE: + cookies_delete_selected(); + return true; + case TREE_SELECT_ALL: + cookies_select_all(); + return true; + case TREE_CLEAR_SELECTION: + cookies_clear_selection(); + return true; + default: + return false; } - if (!node) { - for (parent = cookies_tree->root->child; parent; - parent = parent->next) { - if (strcmp(domain, parent->data.text) == 0) - break; - } - if (!parent) { - node = tree_create_folder_node(cookies_tree->root, - domain); - } else { - node = parent; - } - } - if (!node) - return true; - node->editable = false; + return false; +} - for (; cookie; cookie = cookie->next) { - add = tree_create_cookie_node(node, cookie); - if (add && !cookies_init) - tree_handle_node_changed(cookies_tree, add, - true, false); - } - if (!cookies_init) { - tree_handle_node_changed(cookies_tree, node, - true, false); - tree_redraw_area(cookies_tree, - node->box.x - NODE_INSTEP, - 0, NODE_INSTEP, 16384); - } - return true; +/** + * Update the theme details of the cookies window. + */ + +void ro_gui_cookies_update_theme(void) +{ + ro_treeview_update_theme(cookies_window.tv); } /** - * Find an entry in the cookie tree + * Check if a particular window handle is the cookies window * - * \param url The URL to find - * \return Pointer to node, or NULL if not found + * \param window the window in question + * \return true if this window is the cookies */ -struct node *ro_gui_cookies_find(const char *url) + +bool ro_gui_cookies_check_window(wimp_w window) { - struct node *node; +/* SF if (cookies_window.w == window) + return true; + else*/ + return false; +} - for (node = cookies_tree->root->child; node; node = node->next) { - if (!strcmp(url, node->data.text)) - return node; - } - return NULL; +/** + * Check if a particular menu handle is the cookies menu + * + * \param *menu The menu in question. + * \return true if this menu is the cookies menu + */ + +bool ro_gui_cookies_check_menu(wimp_menu *menu) +{ + if (cookies_window.menu == menu) + return true; + else + return false; } + diff --git a/riscos/cookies.h b/riscos/cookies.h index b6dbe7bc6..3539ed9a0 100644 --- a/riscos/cookies.h +++ b/riscos/cookies.h @@ -1,5 +1,6 @@ /* * Copyright 2006 Richard Wilson + * Copyright 2010 Stephen Fryatt * * This file is part of NetSurf, http://www.netsurf-browser.org/ * @@ -23,6 +24,13 @@ #ifndef _NETSURF_RISCOS_COOKIES_H_ #define _NETSURF_RISCOS_COOKIES_H_ -void ro_gui_cookies_initialise(void); +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); + +void ro_gui_cookies_open(void); +void ro_gui_cookies_update_theme(void); #endif + diff --git a/riscos/dialog.c b/riscos/dialog.c index f0520eb73..b4195a5b7 100644 --- a/riscos/dialog.c +++ b/riscos/dialog.c @@ -39,11 +39,14 @@ #include "riscos/dialog.h" #include "riscos/global_history.h" #include "riscos/gui.h" +#include "riscos/hotlist.h" #include "riscos/menus.h" #include "riscos/options.h" #include "riscos/save.h" +#include "riscos/sslcert.h" #include "riscos/theme.h" #include "riscos/url_complete.h" +#include "riscos/url_suggest.h" #include "riscos/wimp.h" #include "riscos/wimp_event.h" #include "riscos/wimputils.h" @@ -106,18 +109,6 @@ void ro_gui_dialog_init(void) /* 401 login window */ ro_gui_401login_init(); - /* certificate verification window */ - ro_gui_cert_init(); - - /* hotlist window */ - ro_gui_hotlist_initialise(); - - /* global history window */ - ro_gui_global_history_initialise(); - - /* cookies window */ - ro_gui_cookies_initialise(); - /* theme installation */ dialog_theme_install = ro_gui_dialog_create("theme_inst"); ro_gui_wimp_event_register_cancel(dialog_theme_install, @@ -150,24 +141,6 @@ void ro_gui_dialog_init(void) dialog_objinfo = ro_gui_dialog_create("objectinfo"); ro_gui_wimp_event_set_help_prefix(dialog_objinfo, "HelpObjInfo"); - /* hotlist folder editing */ - dialog_folder = ro_gui_dialog_create("new_folder"); - ro_gui_wimp_event_register_text_field(dialog_folder, ICON_FOLDER_NAME); - ro_gui_wimp_event_register_cancel(dialog_folder, ICON_FOLDER_CANCEL); - ro_gui_wimp_event_register_ok(dialog_folder, ICON_FOLDER_OK, - ro_gui_hotlist_dialog_apply); - ro_gui_wimp_event_set_help_prefix(dialog_folder, "HelpHotFolder"); - - /* hotlist entry editing */ - dialog_entry = ro_gui_dialog_create("new_entry"); - ro_gui_wimp_event_register_text_field(dialog_entry, ICON_ENTRY_NAME); - ro_gui_wimp_event_register_menu_gright(dialog_entry, ICON_ENTRY_URL, - ICON_ENTRY_RECENT, url_suggest_menu); - ro_gui_wimp_event_register_cancel(dialog_entry, ICON_ENTRY_CANCEL); - ro_gui_wimp_event_register_ok(dialog_entry, ICON_ENTRY_OK, - ro_gui_hotlist_dialog_apply); - ro_gui_wimp_event_set_help_prefix(dialog_entry, "HelpHotEntry"); - /* save as */ dialog_saveas = ro_gui_saveas_create("saveas"); ro_gui_wimp_event_register_button(dialog_saveas, ICON_SAVE_ICON, @@ -204,6 +177,22 @@ void ro_gui_dialog_init(void) ro_gui_wimp_event_register_ok(dialog_zoom, ICON_ZOOM_OK, ro_gui_dialog_zoom_apply); ro_gui_wimp_event_set_help_prefix(dialog_zoom, "HelpScaleView"); + + /* Treeview initialisation has moved to the end, to allow any + * associated dialogues to be set up first. + */ + + /* certificate verification window */ + ro_gui_cert_preinitialise(); + + /* hotlist window */ + ro_gui_hotlist_preinitialise(); + + /* global history window */ + ro_gui_global_history_preinitialise(); + + /* cookies window */ + ro_gui_cookies_preinitialise(); } @@ -638,15 +627,25 @@ void ro_gui_dialog_add_persistent(wimp_w parent, wimp_w w) { */ void ro_gui_dialog_close_persistent(wimp_w parent) { - int i; - - /* Check our mappings - */ + int i; + wimp_w w; + + /* Check our mappings. + * + * The window handle is copied into w before proceeding, as + * ro_gui_dialog_close() will NULL persistent_dialog[i].dialog as + * part of the closing process. This would mean that the subsequent + * event dispatch would fail. (These events are logged to allow + * side effects to be investigated -- this code hasn't worked before). + */ for (i = 0; i < MAX_PERSISTENT; i++) { if (persistent_dialog[i].parent == parent && persistent_dialog[i].dialog != NULL) { - ro_gui_dialog_close(persistent_dialog[i].dialog); - ro_gui_wimp_event_close_window(persistent_dialog[i].dialog); + w = persistent_dialog[i].dialog; + ro_gui_dialog_close(w); + if (ro_gui_wimp_event_close_window(w)) + LOG(("Persistent dialog close event: 0x%x", + (unsigned) w)); persistent_dialog[i].parent = NULL; persistent_dialog[i].dialog = NULL; } @@ -710,7 +709,6 @@ bool ro_gui_dialog_openurl_apply(wimp_w w) { res = url_normalize(url, &url2); if (res == URL_FUNC_OK) { browser_window_create(url2, 0, 0, true, false); - global_history_add_recent(url2); free(url2); return true; } @@ -724,10 +722,8 @@ bool ro_gui_dialog_openurl_apply(wimp_w w) { void ro_gui_dialog_prepare_open_url(void) { - int suggestions; ro_gui_set_icon_string(dialog_openurl, ICON_OPENURL_URL, "", true); - global_history_get_recent(&suggestions); ro_gui_set_icon_shaded_state(dialog_openurl, - ICON_OPENURL_MENU, (suggestions <= 0)); + ICON_OPENURL_MENU, !ro_gui_url_suggest_prepare_menu()); ro_gui_wimp_event_memorise(dialog_openurl); } diff --git a/riscos/global_history.c b/riscos/global_history.c index 5cccae0b4..e9f5ea6ad 100644 --- a/riscos/global_history.c +++ b/riscos/global_history.c @@ -1,5 +1,6 @@ /* * Copyright 2005 Richard Wilson + * Copyright 2010 Stephen Fryatt * * This file is part of NetSurf, http://www.netsurf-browser.org/ * @@ -29,12 +30,14 @@ #include "oslib/wimp.h" #include "oslib/wimpspriteop.h" #include "content/urldb.h" +#include "desktop/history_global_core.h" #include "desktop/tree.h" #include "riscos/dialog.h" #include "riscos/global_history.h" #include "riscos/gui.h" #include "riscos/menus.h" #include "riscos/options.h" +#include "riscos/save.h" #include "riscos/theme.h" #include "riscos/treeview.h" #include "riscos/wimp.h" @@ -44,401 +47,260 @@ #include "utils/url.h" #include "utils/utils.h" -#define MAXIMUM_URL_LENGTH 1024 -#define MAXIMUM_BASE_NODES 16 +static void ro_gui_global_history_menu_prepare(wimp_w window, wimp_menu *menu); +static bool ro_gui_global_history_menu_select(wimp_w window, wimp_menu *menu, + wimp_selection *selection, menu_action action); +static void ro_gui_global_history_menu_warning(wimp_w window, wimp_menu *menu, + wimp_selection *selection, menu_action action); -static struct node *global_history_base_node[MAXIMUM_BASE_NODES]; -static int global_history_base_node_time[MAXIMUM_BASE_NODES]; -static int global_history_base_node_count = 0; +/* The RISC OS global history window, toolbar and treeview data */ -static char *global_history_recent_url[GLOBAL_HISTORY_RECENT_URLS]; -static int global_history_recent_count = 0; - -static bool global_history_init; - -static bool ro_gui_global_history_click(wimp_pointer *pointer); -static void ro_gui_global_history_initialise_nodes(void); -static void ro_gui_global_history_initialise_node(const char *title, - time_t base, int days_back); -static struct node *ro_gui_global_history_find(const char *url); -static bool global_history_add_internal(const char *url, - const struct url_data *data); - -/* The history window, toolbar and plot origins */ -static wimp_w global_history_window; -struct tree *global_history_tree; +static struct ro_global_history_window { + wimp_w window; + struct toolbar *toolbar; + ro_treeview *tv; + wimp_menu *menu; +} global_history_window; /** - * Initialise global history tree + * Pre-Initialise the global history tree. This is called for things that + * need to be done at the gui_init() stage, such as loading templates. */ -void ro_gui_global_history_initialise(void) + +void ro_gui_global_history_preinitialise(void) { - char s[MAXIMUM_URL_LENGTH]; - FILE *fp; + /* Create our window. */ - /* create our window */ - global_history_window = ro_gui_dialog_create("tree"); - ro_gui_set_window_title(global_history_window, + global_history_window.window = ro_gui_dialog_create("tree"); + ro_gui_set_window_title(global_history_window.window, messages_get("GlobalHistory")); - ro_gui_wimp_event_register_redraw_window(global_history_window, - ro_gui_tree_redraw); - ro_gui_wimp_event_register_open_window(global_history_window, - ro_gui_tree_open); - ro_gui_wimp_event_register_mouse_click(global_history_window, - ro_gui_global_history_click); - - /* Create an empty tree */ - global_history_tree = calloc(sizeof(struct tree), 1); - if (!global_history_tree) { - warn_user("NoMemory", 0); - return; - } - global_history_tree->root = tree_create_folder_node(NULL, "Root"); - if (!global_history_tree->root) { - warn_user("NoMemory", 0); - free(global_history_tree); - global_history_tree = NULL; - return; - } - global_history_tree->root->expanded = true; - ro_gui_global_history_initialise_nodes(); - global_history_tree->handle = (int)global_history_window; - global_history_tree->movable = false; - ro_gui_wimp_event_set_user_data(global_history_window, - global_history_tree); - ro_gui_wimp_event_register_keypress(global_history_window, - ro_gui_tree_keypress); - - /* Create our toolbar */ - global_history_tree->toolbar = ro_gui_theme_create_toolbar(NULL, - THEME_HISTORY_TOOLBAR); - if (global_history_tree->toolbar) - ro_gui_theme_attach_toolbar(global_history_tree->toolbar, - global_history_window); - - /* load recent URLs */ - fp = fopen(option_recent_path, "r"); - if (!fp) - LOG(("Failed to open file '%s' for reading", - option_recent_path)); - else { - while (fgets(s, MAXIMUM_URL_LENGTH, fp)) { - if (s[strlen(s) - 1] == '\n') - s[strlen(s) - 1] = '\0'; - global_history_add_recent(s); - } - fclose(fp); - } - - global_history_init = true; - urldb_iterate_entries(global_history_add_internal); - global_history_init = false; - tree_initialise(global_history_tree); } /** - * Initialises the base nodes + * Initialise global history tree, at the gui_init2() stage. */ -void ro_gui_global_history_initialise_nodes(void) -{ - struct tm *full_time; - time_t t; - int weekday; - int i; - - /* get the current time */ - t = time(NULL); - if (t == -1) - return; - /* get the time at the start of today */ - full_time = localtime(&t); - weekday = full_time->tm_wday; - full_time->tm_sec = 0; - full_time->tm_min = 0; - full_time->tm_hour = 0; - t = mktime(full_time); - if (t == -1) - return; +void ro_gui_global_history_postinitialise(void) +{ - ro_gui_global_history_initialise_node(messages_get("DateToday"), t, 0); - if (weekday > 0) - ro_gui_global_history_initialise_node( - messages_get("DateYesterday"), t, -1); - for (i = 2; i <= weekday; i++) - ro_gui_global_history_initialise_node(NULL, t, -i); - ro_gui_global_history_initialise_node(messages_get("Date1Week"), - t, -weekday - 7); - ro_gui_global_history_initialise_node(messages_get("Date2Week"), - t, -weekday - 14); - ro_gui_global_history_initialise_node(messages_get("Date3Week"), - t, -weekday - 21); -} + /* Create our toolbar. */ -/** - * Create and initialise a node - */ -void ro_gui_global_history_initialise_node(const char *title, - time_t base, int days_back) -{ - struct tm *full_time; - char buffer[64]; - struct node *node; - - base += days_back * 60 * 60 * 24; - if (!title) { - full_time = localtime(&base); - strftime((char *)&buffer, (size_t)64, "%A", full_time); - node = tree_create_folder_node(NULL, buffer); - } else - node = tree_create_folder_node(NULL, title); - - if (!node) + 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); + + /* Create the treeview with the window and toolbar. */ + + global_history_window.tv = + ro_treeview_create(global_history_window.window, + global_history_window.toolbar, + history_global_get_tree_flags()); + if (global_history_window.tv == NULL) { + LOG(("Failed to allocate treeview")); return; + } - node->retain_in_memory = true; - node->deleted = true; - node->editable = false; - global_history_base_node[global_history_base_node_count] = node; - global_history_base_node_time[global_history_base_node_count] = base; - global_history_base_node_count++; + /* Initialise the global history into the tree. */ + + history_global_initialise( + ro_treeview_get_tree(global_history_window.tv)); + + /* Build the global history window menu. */ + + static const struct ns_menu global_history_definition = { + "History", { + { "History", NO_ACTION, 0 }, + { "_History.Export", HISTORY_EXPORT, &dialog_saveas }, + { "History.Expand", TREE_EXPAND_ALL, 0 }, + { "History.Expand.All", TREE_EXPAND_ALL, 0 }, + { "History.Expand.Folders", TREE_EXPAND_FOLDERS, 0 }, + { "History.Expand.Links", TREE_EXPAND_LINKS, 0 }, + { "History.Collapse", TREE_COLLAPSE_ALL, 0 }, + { "History.Collapse.All", TREE_COLLAPSE_ALL, 0 }, + { "History.Collapse.Folders", TREE_COLLAPSE_FOLDERS, 0 }, + { "History.Collapse.Links", TREE_COLLAPSE_LINKS, 0 }, + { "History.Toolbars", NO_ACTION, 0 }, + { "_History.Toolbars.ToolButtons", TOOLBAR_BUTTONS, 0 }, + { "History.Toolbars.EditToolbar",TOOLBAR_EDIT, 0 }, + { "Selection", TREE_SELECTION, 0 }, + { "Selection.Launch", TREE_SELECTION_LAUNCH, 0 }, + { "Selection.Delete", TREE_SELECTION_DELETE, 0 }, + { "SelectAll", TREE_SELECT_ALL, 0 }, + { "Clear", TREE_CLEAR_SELECTION, 0 }, + {NULL, 0, 0} + } + }; + 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); } - /** - * Saves the global history's recent URL data. + * Open the global history window. */ -void ro_gui_global_history_save(void) + +void ro_gui_global_history_open(void) { - FILE *fp; - int i; - - /* save recent URLs */ - fp = fopen(option_recent_save, "w"); - if (!fp) - LOG(("Failed to open file '%s' for writing", - option_recent_save)); - else { - for (i = global_history_recent_count - 1; i >= 0; i--) - if (strlen(global_history_recent_url[i]) < - MAXIMUM_URL_LENGTH) - fprintf(fp, "%s\n", - global_history_recent_url[i]); - fclose(fp); + tree_set_redraw(ro_treeview_get_tree(global_history_window.tv), true); + + 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( + global_history_window.toolbar))); } } - /** - * Respond to a mouse click + * Prepare the global history menu for opening * - * \param pointer the pointer state - * \return true to indicate click handled + * \param window The window owning the menu. + * \param *menu The menu about to be opened. */ -bool ro_gui_global_history_click(wimp_pointer *pointer) + +void ro_gui_global_history_menu_prepare(wimp_w window, wimp_menu *menu) { - ro_gui_tree_click(pointer, global_history_tree); - if (pointer->buttons == wimp_CLICK_MENU) - ro_gui_menu_create(global_history_menu, pointer->pos.x, - pointer->pos.y, pointer->w); - else - ro_gui_menu_prepare_action(pointer->w, TREE_SELECTION, false); - return true; + bool selection; + + 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, + TOOLBAR_BUTTONS, + (global_history_window.toolbar == NULL || + global_history_window.toolbar->editor)); + ro_gui_menu_set_entry_ticked(global_history_window.menu, + TOOLBAR_BUTTONS, + (global_history_window.toolbar != NULL && + (global_history_window.toolbar->display_buttons || + (global_history_window.toolbar->editor)))); + + ro_gui_menu_set_entry_shaded(global_history_window.menu, TOOLBAR_EDIT, + global_history_window.toolbar == NULL); + ro_gui_menu_set_entry_ticked(global_history_window.menu, TOOLBAR_EDIT, + (global_history_window.toolbar != NULL && + global_history_window.toolbar->editor)); + + ro_gui_save_prepare(GUI_SAVE_HISTORY_EXPORT_HTML, + NULL, NULL, NULL, NULL); } - /** - * Adds to the global history + * Handle submenu warnings for the global_hostory menu * - * \param url The URL to add + * \param window The window 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 global_history_add(const char *url) -{ - const struct url_data *data; - data = urldb_get_url_data(url); - if (!data) - return; - - global_history_add_internal(url, data); +void ro_gui_global_history_menu_warning(wimp_w window, wimp_menu *menu, + wimp_selection *selection, menu_action action) +{ + /* Do nothing */ } /** - * Internal routine to actually perform global history addition + * Handle selections from the global history menu * - * \param url The URL to add - * \param data URL data associated with URL - * \return true (for urldb_iterate_entries) + * \param window The window 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 global_history_add_internal(const char *url, - const struct url_data *data) -{ - int i, j; - struct node *parent = NULL; - struct node *link; - struct node *node; - bool before = false; - int visit_date; - - assert(url && data); - - visit_date = data->last_visit; - - /* find parent node */ - for (i = 0; i < global_history_base_node_count; i++) { - if (global_history_base_node_time[i] <= visit_date) { - parent = global_history_base_node[i]; - break; - } - } - /* the entry is too old to care about */ - if (!parent) +bool ro_gui_global_history_menu_select(wimp_w window, wimp_menu *menu, + wimp_selection *selection, menu_action action) +{ + switch (action) { + case HISTORY_EXPORT: + ro_gui_dialog_open_persistent(window, dialog_saveas, true); return true; - - if (parent->deleted) { - /* parent was deleted, so find place to insert it */ - link = global_history_tree->root; - - for (j = global_history_base_node_count - 1; j >= 0; j--) { - if (!global_history_base_node[j]->deleted && - global_history_base_node_time[j] > - global_history_base_node_time[i]) { - link = global_history_base_node[j]; - before = true; - break; - } - } - - tree_set_node_selected(global_history_tree, - parent, false); - tree_set_node_expanded(global_history_tree, - parent, false); - tree_link_node(link, parent, before); - - if (!global_history_init) { - tree_recalculate_node(global_history_tree, parent, true); - tree_recalculate_node_positions(global_history_tree, - global_history_tree->root); - tree_redraw_area(global_history_tree, - 0, 0, 16384, 16384); - } - } - - /* find any previous occurance */ - if (!global_history_init) { - node = ro_gui_global_history_find(url); - if (node) { - /* \todo: calculate old/new positions and redraw - * only the relevant portion */ - tree_redraw_area(global_history_tree, - 0, 0, 16384, 16384); - tree_update_URL_node(node, url, data); - tree_delink_node(node); - tree_link_node(parent, node, false); - tree_handle_node_changed(global_history_tree, - node, false, true); -/* ro_gui_tree_scroll_visible(hotlist_tree, - &node->data); -*/ return true; - } - } - - /* Add the node at the bottom */ - node = tree_create_URL_node_shared(parent, url, data); - if ((!global_history_init) && (node)) { - tree_redraw_area(global_history_tree, - node->box.x - NODE_INSTEP, - 0, NODE_INSTEP, 16384); - tree_handle_node_changed(global_history_tree, node, - true, false); + case TREE_EXPAND_ALL: + history_global_expand_all(); + return true; + case TREE_EXPAND_FOLDERS: + history_global_expand_directories(); + return true; + case TREE_EXPAND_LINKS: + history_global_expand_addresses(); + return true; + case TREE_COLLAPSE_ALL: + history_global_collapse_all(); + return true; + case TREE_COLLAPSE_FOLDERS: + history_global_collapse_directories(); + return true; + case TREE_COLLAPSE_LINKS: + history_global_collapse_addresses(); + return true; + case TREE_SELECTION_LAUNCH: + history_global_launch_selected(); + return true; + case TREE_SELECTION_DELETE: + history_global_delete_selected(); + return true; + case TREE_SELECT_ALL: + history_global_select_all(); + return true; + case TREE_CLEAR_SELECTION: + history_global_clear_selection(); + return true; + default: + return false; } - return true; + return false; } /** - * Find an entry in the global history - * - * \param url The URL to find - * \return Pointer to node, or NULL if not found + * Update the theme details of the global history window. */ -struct node *ro_gui_global_history_find(const char *url) + +void ro_gui_global_history_update_theme(void) { - int i; - struct node *node; - struct node_element *element; - - for (i = 0; i < global_history_base_node_count; i++) { - if (!global_history_base_node[i]->deleted) { - for (node = global_history_base_node[i]->child; - node; node = node->next) { - element = tree_find_element(node, - TREE_ELEMENT_URL); - if ((element) && !strcmp(url, element->text)) - return node; - } - } - } - return NULL; + ro_treeview_update_theme(global_history_window.tv); } - /** - * Adds an URL to the recently used list + * Check if a particular window handle is the global history window * - * \param url the URL to add (copied) + * \param window the window in question + * \return true if this window is the global history */ -void global_history_add_recent(const char *url) -{ - int i; - int j = -1; - char *current; - - /* try to find a string already there */ - for (i = 0; i < global_history_recent_count; i++) - if (global_history_recent_url[i] && - !strcmp(global_history_recent_url[i], url)) - j = i; - - /* already at head of list */ - if (j == 0) - return; - if (j < 0) { - /* add to head of list */ - free(global_history_recent_url[ - GLOBAL_HISTORY_RECENT_URLS - 1]); - memmove(&global_history_recent_url[1], - &global_history_recent_url[0], - (GLOBAL_HISTORY_RECENT_URLS - 1) * - sizeof(char *)); - global_history_recent_url[0] = strdup(url); - global_history_recent_count++; - if (global_history_recent_count > GLOBAL_HISTORY_RECENT_URLS) - global_history_recent_count = - GLOBAL_HISTORY_RECENT_URLS; - if (global_history_recent_count == 1) - ro_gui_window_prepare_navigate_all(); - } else { - /* move to head of list */ - current = global_history_recent_url[j]; - for (i = j; i > 0; i--) - global_history_recent_url[i] = - global_history_recent_url[i - 1]; - global_history_recent_url[0] = current; - } +bool ro_gui_global_history_check_window(wimp_w window) +{ +/* if (global_history_window.w == window) + return true; + else*/ + return false; } - /** - * Gets details of the currently used URL list. + * Check if a particular menu handle is the global history menu * - * \param count set to the current number of entries in the URL array on exit - * \return the current URL array + * \param *menu The menu in question. + * \return true if this menu is the global history menu */ -char **global_history_get_recent(int *count) + +bool ro_gui_global_history_check_menu(wimp_menu *menu) { - *count = global_history_recent_count; - return global_history_recent_url; + if (global_history_window.menu == menu) + return true; + else + return false; } + diff --git a/riscos/global_history.h b/riscos/global_history.h index 170cdaaca..951836d5d 100644 --- a/riscos/global_history.h +++ b/riscos/global_history.h @@ -1,5 +1,6 @@ /* * Copyright 2005 Richard Wilson + * Copyright 2010 Stephen Fryatt * * This file is part of NetSurf, http://www.netsurf-browser.org/ * @@ -23,10 +24,13 @@ #ifndef _NETSURF_RISCOS_GLOBALHISTORY_H_ #define _NETSURF_RISCOS_GLOBALHISTORY_H_ -#define GLOBAL_HISTORY_RECENT_URLS 16 - -void ro_gui_global_history_initialise(void); +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(void); +bool ro_gui_global_history_check_window(wimp_w window); +bool ro_gui_global_history_check_menu(wimp_menu *menu); #endif + diff --git a/riscos/gui.c b/riscos/gui.c index 18a092c80..6968bb04f 100644 --- a/riscos/gui.c +++ b/riscos/gui.c @@ -55,20 +55,26 @@ #include "content/content.h" #include "content/hlcache.h" #include "content/urldb.h" +#include "desktop/cookies.h" #include "desktop/gui.h" +#include "desktop/history_global_core.h" +#include "desktop/hotlist.h" #include "desktop/netsurf.h" #include "desktop/options.h" #include "desktop/save_complete.h" #include "desktop/tree.h" +#include "desktop/tree_url_node.h" #include "render/box.h" #include "render/font.h" #include "render/html.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/help.h" +#include "riscos/hotlist.h" #include "riscos/menus.h" #include "riscos/message.h" #include "riscos/options.h" @@ -78,6 +84,7 @@ #include "riscos/print.h" #include "riscos/query.h" #include "riscos/save.h" +#include "riscos/sslcert.h" #include "riscos/textselection.h" #include "riscos/theme.h" #include "riscos/treeview.h" @@ -184,7 +191,7 @@ static struct { } prev_sigs; /** Accepted wimp user messages. */ -static ns_wimp_message_list task_messages = { +static ns_wimp_message_list task_messages = { message_HELP_REQUEST, { message_DATA_SAVE, @@ -347,6 +354,8 @@ 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"); + if (!option_tree_icons_dir) + option_tree_icons_dir = strdup("NetSurf:Resources.Icons"); if (!option_theme || ! option_toolbar_browser || !option_toolbar_hotlist || !option_toolbar_history || @@ -355,7 +364,7 @@ static void gui_init(int argc, char** argv) !option_url_save || !option_hotlist_path || !option_hotlist_save || !option_recent_path || !option_recent_save || !option_theme_path || - !option_theme_save) + !option_theme_save || !option_tree_icons_dir) die("Failed initialising string options"); /* Create our choices directories */ @@ -394,7 +403,7 @@ static void gui_init(int argc, char** argv) default_stylesheet_url = strdup("file:///NetSurf:/Resources/CSS"); quirks_stylesheet_url = strdup("file:///NetSurf:/Resources/Quirks"); adblock_stylesheet_url = strdup("file:///NetSurf:/Resources/AdBlock"); - if (!default_stylesheet_url || !quirks_stylesheet_url || + if (!default_stylesheet_url || !quirks_stylesheet_url || !adblock_stylesheet_url) die("Failed initialising string constants."); @@ -479,9 +488,6 @@ static void gui_init(int argc, char** argv) /* Done with the templates file */ wimp_close_template(); - /* Initialise tree views (must be after UI sprites are loaded) */ - ro_gui_tree_initialise(); - /* Create Iconbar icon */ ro_gui_icon_bar_create(); @@ -670,6 +676,21 @@ static void gui_init2(int argc, char** argv) char *url = 0; bool open_window = option_open_browser_at_startup; + /* Complete initialisation of the treeview modules. */ + + /* certificate verification window */ + ro_gui_cert_postinitialise(); + + /* hotlist window */ + ro_gui_hotlist_postinitialise(); + + /* global history window */ + ro_gui_global_history_postinitialise(); + + /* cookies window */ + ro_gui_cookies_postinitialise(); + + /* parse command-line arguments */ if (argc == 2) { LOG(("parameters: '%s'", argv[1])); @@ -781,8 +802,9 @@ void gui_quit(void) urldb_save_cookies(option_cookie_jar); urldb_save(option_url_save); ro_gui_window_quit(); - ro_gui_global_history_save(); - ro_gui_hotlist_save(); + history_global_cleanup(); + cookies_cleanup(); + hotlist_cleanup(option_hotlist_save); ro_gui_saveas_quit(); rufl_quit(); free(gui_sprites); @@ -1109,6 +1131,9 @@ void ro_gui_null_reason_code(void) // break; default: + if (ro_gui_hotlist_check_window(gui_track_wimp_w)) + ro_treeview_mouse_at(gui_track_wimp_w, + &pointer); if (gui_track_wimp_w == history_window) ro_gui_history_mouse_at(&pointer); if (gui_track_wimp_w == dialog_url_complete) @@ -1203,8 +1228,10 @@ void ro_gui_pointer_entering_window(wimp_entering *entering) default: gui_track_wimp_w = entering->w; gui_track_gui_window = ro_gui_window_lookup(entering->w); - gui_track = gui_track_gui_window || gui_track_wimp_w == history_window || - gui_track_wimp_w == dialog_url_complete; + gui_track = gui_track_gui_window || + gui_track_wimp_w == history_window || + gui_track_wimp_w == dialog_url_complete || + ro_gui_hotlist_check_window(gui_track_wimp_w); break; } } @@ -1275,11 +1302,11 @@ void ro_gui_drag_end(wimp_dragged *drag) break; case GUI_DRAG_TREE_SELECT: - ro_gui_tree_selection_drag_end(drag); +// ro_gui_tree_selection_drag_end(drag); break; case GUI_DRAG_TREE_MOVE: - ro_gui_tree_move_drag_end(drag); +// ro_gui_tree_move_drag_end(drag); break; case GUI_DRAG_TOOLBAR_CONFIG: @@ -1485,12 +1512,7 @@ void ro_msg_dataload(wimp_message *message) char *url = 0; char *title = NULL; struct gui_window *g; - struct node *node; - struct node *link; os_error *error; - int x, y; - bool before; - const struct url_data *data; g = ro_gui_window_lookup(message->data.data_xfer.w); if (g) { @@ -1551,28 +1573,9 @@ void ro_msg_dataload(wimp_message *message) if (g) { browser_window_go(g->bw, url, 0, true); - } else if ((hotlist_tree) && ((wimp_w)hotlist_tree->handle == - message->data.data_xfer.w)) { - data = urldb_get_url_data(url); - if (!data) { - urldb_add_url(url); - urldb_set_url_persistence(url, true); - data = urldb_get_url_data(url); - } - if (data) { - ro_gui_tree_get_tree_coordinates(hotlist_tree, - message->data.data_xfer.pos.x, - message->data.data_xfer.pos.y, - &x, &y); - link = tree_get_link_details(hotlist_tree, x, y, &before); - node = tree_create_URL_node(NULL, url, data, title); - tree_link_node(link, node, before); - tree_handle_node_changed(hotlist_tree, node, false, true); - tree_redraw_area(hotlist_tree, node->box.x - NODE_INSTEP, 0, - NODE_INSTEP, 16384); - if ((!title) && (!data->title)) - ro_gui_tree_start_edit(hotlist_tree, &node->data, NULL); - } +// } else if (ro_gui_hotlist_check_window(message->data.data_xfer.w)) { +// /* Drop URL into hotlist */ +// ro_gui_hotlist_url_drop(message, url); } else { browser_window_create(url, 0, 0, true, false); } diff --git a/riscos/gui.h b/riscos/gui.h index 101eedac2..c400494f8 100644 --- a/riscos/gui.h +++ b/riscos/gui.h @@ -64,7 +64,6 @@ extern bool gui_redraw_debug; extern osspriteop_area *gui_sprites; extern bool dialog_folder_add, dialog_entry_add, hotlist_insert; extern bool print_active, print_text_black; -extern struct tree *hotlist_tree, *global_history_tree, *cookies_tree; typedef enum { GUI_DRAG_NONE, GUI_DRAG_SELECTION, GUI_DRAG_DOWNLOAD_SAVE, GUI_DRAG_SAVE, GUI_DRAG_SCROLL, GUI_DRAG_STATUS_RESIZE, @@ -136,10 +135,6 @@ bool ro_gui_download_prequit(void); /* in 401login.c */ void ro_gui_401login_init(void); -/* in sslcert.c */ -void ro_gui_cert_init(void); -void ro_gui_cert_open(struct tree *tree, struct node *node); - /* in window.c */ void ro_gui_window_quit(void); /* void ro_gui_window_close_all(void); */ @@ -161,7 +156,10 @@ 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); +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, + wimp_icon_flags type); bool ro_gui_shift_pressed(void); bool ro_gui_ctrl_pressed(void); bool ro_gui_alt_pressed(void); @@ -178,13 +176,6 @@ void ro_gui_history_open(struct browser_window *bw, struct history *history, bool pointer); void ro_gui_history_mouse_at(wimp_pointer *pointer); -/* in hotlist.c */ -void ro_gui_hotlist_initialise(void); -void ro_gui_hotlist_save(void); -void ro_gui_hotlist_prepare_folder_dialog(struct node *node); -void ro_gui_hotlist_prepare_entry_dialog(struct node *node); -bool ro_gui_hotlist_dialog_apply(wimp_w w); - /* in filetype.c */ int ro_content_filetype(struct hlcache_handle *c); int ro_content_filetype_from_type(content_type type); diff --git a/riscos/help.c b/riscos/help.c index 6d5efe974..968fcb7c4 100644 --- a/riscos/help.c +++ b/riscos/help.c @@ -28,7 +28,10 @@ #include "oslib/taskmanager.h" #include "oslib/wimp.h" #include "desktop/tree.h" +#include "riscos/cookies.h" +#include "riscos/global_history.h" #include "riscos/gui.h" +#include "riscos/hotlist.h" #include "riscos/help.h" #include "riscos/menus.h" #include "riscos/options.h" @@ -100,7 +103,7 @@ void ro_gui_interactive_help_request(wimp_message *message) os_error *error; const char *auto_text; int i; - + /* check we aren't turned off */ if (!option_interactive_help) return; @@ -124,18 +127,17 @@ void ro_gui_interactive_help_request(wimp_message *message) sprintf(message_token, "%s%i", auto_text, (int)icon); else if (window == wimp_ICON_BAR) sprintf(message_token, "HelpIconbar"); - else if ((hotlist_tree) && (window == (wimp_w)hotlist_tree->handle)) { - i = ro_gui_tree_help(message_data->pos.x, message_data->pos.y); + else if (ro_gui_hotlist_check_window(message->data.data_xfer.w)) { + i = ro_treeview_get_help(message_data); sprintf(message_token, (i >= 0) ? "HelpTree%i" :"HelpHotlist%i", i); - } else if ((global_history_tree) && - (window == (wimp_w)global_history_tree->handle)) { - i = ro_gui_tree_help(message_data->pos.x, message_data->pos.y); + } else if (ro_gui_global_history_check_window( + message->data.data_xfer.w)) { + i = ro_treeview_get_help(message_data); sprintf(message_token, (i >= 0) ? "HelpTree%i" :"HelpGHistory%i", i); - } else if ((cookies_tree) && - (window == (wimp_w)cookies_tree->handle)) { - i = ro_gui_tree_help(message_data->pos.x, message_data->pos.y); + } else if (ro_gui_cookies_check_window(message->data.data_xfer.w)) { + i = ro_treeview_get_help(message_data); sprintf(message_token, (i >= 0) ? "HelpTree%i" :"HelpCookies%i", i); } else if (ro_gui_window_lookup(window) != NULL) @@ -173,11 +175,11 @@ void ro_gui_interactive_help_request(wimp_message *message) sprintf(message_token, "HelpIconMenu"); else if (current_menu == browser_menu) sprintf(message_token, "HelpBrowserMenu"); - else if (current_menu == hotlist_menu) + else if (ro_gui_hotlist_check_menu(current_menu)) sprintf(message_token, "HelpHotlistMenu"); - else if (current_menu == global_history_menu) + else if (ro_gui_global_history_check_menu(current_menu)) sprintf(message_token, "HelpGHistoryMenu"); - else if (current_menu == cookies_menu) + else if (ro_gui_cookies_check_menu(current_menu)) sprintf(message_token, "HelpCookiesMenu"); else return; @@ -323,7 +325,7 @@ void ro_gui_interactive_help_start(void) char *help_start; wimp_t task = 0; os_error *error; - + /* don't launch a second copy of anything */ if (ro_gui_interactive_help_available()) return; diff --git a/riscos/hotlist.c b/riscos/hotlist.c index dd611b691..6e2d176cc 100644 --- a/riscos/hotlist.c +++ b/riscos/hotlist.c @@ -1,5 +1,6 @@ /* * Copyright 2004, 2005 Richard Wilson + * Copyright 2010 Stephen Fryatt * * This file is part of NetSurf, http://www.netsurf-browser.org/ * @@ -31,10 +32,13 @@ #include "content/content.h" #include "content/hlcache.h" #include "content/urldb.h" +#include "desktop/hotlist.h" #include "desktop/tree.h" #include "riscos/dialog.h" +#include "riscos/hotlist.h" #include "riscos/menus.h" #include "riscos/options.h" +#include "riscos/save.h" #include "riscos/theme.h" #include "riscos/treeview.h" #include "riscos/wimp.h" @@ -44,350 +48,300 @@ #include "utils/utils.h" #include "utils/url.h" +static void ro_gui_hotlist_menu_prepare(wimp_w window, wimp_menu *menu); +static bool ro_gui_hotlist_menu_select(wimp_w window, wimp_menu *menu, + wimp_selection *selection, menu_action action); +static void ro_gui_hotlist_menu_warning(wimp_w window, wimp_menu *menu, + wimp_selection *selection, menu_action action); -static void ro_gui_hotlist_visited(hlcache_handle *c, struct tree *tree, - struct node *node); -static bool ro_gui_hotlist_click(wimp_pointer *pointer); - - -/* The hotlist window, toolbar and plot origins -*/ -static wimp_w hotlist_window; -struct tree *hotlist_tree; - -/* Whether the editing facilities are for add so that we know how - to reset the dialog boxes on a adjust-cancel and the action to - perform on ok. -*/ -struct node *dialog_folder_node; -struct node *dialog_entry_node; - -static const struct { - const char *url; - const char *msg_key; -} default_entries[] = { - { "http://www.netsurf-browser.org/", "HotlistHomepage" }, - { "http://www.netsurf-browser.org/downloads/riscos/testbuilds", "HotlistTestBuild" }, - { "http://www.netsurf-browser.org/documentation", "HotlistDocumentation" }, - { "http://sourceforge.net/tracker/?atid=464312&group_id=51719", - "HotlistBugTracker" }, - { "http://sourceforge.net/tracker/?atid=464315&group_id=51719", - "HotlistFeatureRequest" } -}; -#define ENTRIES_COUNT (sizeof(default_entries) / sizeof(default_entries[0])) - -void ro_gui_hotlist_initialise(void) +/* The RISC OS hotlist window, toolbar and treeview data. */ + +static struct ro_hotlist { + wimp_w window; /*< The hotlist RO window handle. */ + struct toolbar *toolbar; /*< The hotlist toolbar handle. */ + ro_treeview *tv; /*< The hotlist treeview handle. */ + wimp_menu *menu; /*< The hotlist window menu. */ +} hotlist_window; + +/** + * Pre-Initialise the hotlist tree. This is called for things that need to + * be done at the gui_init() stage, such as loading templates. + */ + +void ro_gui_hotlist_preinitialise(void) { - FILE *fp; - struct node *node; - const struct url_data *data; + /* Create our window. */ - /* create our window */ - hotlist_window = ro_gui_dialog_create("tree"); - ro_gui_set_window_title(hotlist_window, + hotlist_window.window = ro_gui_dialog_create("tree"); + ro_gui_set_window_title(hotlist_window.window, messages_get("Hotlist")); - ro_gui_wimp_event_register_redraw_window(hotlist_window, - ro_gui_tree_redraw); - ro_gui_wimp_event_register_open_window(hotlist_window, - ro_gui_tree_open); - ro_gui_wimp_event_register_mouse_click(hotlist_window, - ro_gui_hotlist_click); - - /* Either load or create a hotlist - */ - fp = fopen(option_hotlist_path, "r"); - if (!fp) { - int i; - - hotlist_tree = calloc(sizeof(struct tree), 1); - if (!hotlist_tree) { - warn_user("NoMemory", 0); - return; - } - hotlist_tree->root = tree_create_folder_node(NULL, "Root"); - if (!hotlist_tree->root) { - warn_user("NoMemory", 0); - free(hotlist_tree); - hotlist_tree = NULL; - return; - } - hotlist_tree->root->expanded = true; - node = tree_create_folder_node(hotlist_tree->root, "NetSurf"); - if (!node) - node = hotlist_tree->root; - - for (i = 0; i != ENTRIES_COUNT; i++) { - data = urldb_get_url_data(default_entries[i].url); - if (!data) { - urldb_add_url(default_entries[i].url); - urldb_set_url_persistence( - default_entries[i].url, - true); - data = urldb_get_url_data( - default_entries[i].url); - } - if (data) { - tree_create_URL_node(node, - default_entries[i].url, data, - messages_get(default_entries[i].msg_key)); - } - } - tree_initialise(hotlist_tree); - } else { - fclose(fp); - hotlist_tree = options_load_tree(option_hotlist_path); - } - if (!hotlist_tree) return; - hotlist_tree->handle = (int)hotlist_window; - hotlist_tree->movable = true; - ro_gui_wimp_event_set_user_data(hotlist_window, hotlist_tree); - ro_gui_wimp_event_register_keypress(hotlist_window, - ro_gui_tree_keypress); - - /* Create our toolbar - */ - hotlist_tree->toolbar = ro_gui_theme_create_toolbar(NULL, - THEME_HOTLIST_TOOLBAR); - if (hotlist_tree->toolbar) - ro_gui_theme_attach_toolbar(hotlist_tree->toolbar, - hotlist_window); } - /** - * Perform a save to the default file + * Initialise the hotlist tree, at the gui_init2() stage. */ -void ro_gui_hotlist_save(void) + +void ro_gui_hotlist_postinitialise(void) { - os_error *error; + /* Create our toolbar. */ - if (!hotlist_tree) + 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); + + /* Create the treeview with the window and toolbar. */ + + hotlist_window.tv = ro_treeview_create(hotlist_window.window, + hotlist_window.toolbar, hotlist_get_tree_flags()); + if (hotlist_window.tv == NULL) { + LOG(("Failed to allocate treeview")); return; + } - /* Save to our file - */ - options_save_tree(hotlist_tree, option_hotlist_save, - "NetSurf hotlist"); - error = xosfile_set_type(option_hotlist_save, 0xfaf); - if (error) - LOG(("xosfile_set_type: 0x%x: %s", - error->errnum, error->errmess)); + /* Initialise the hotlist into the tree. */ + + hotlist_initialise(ro_treeview_get_tree(hotlist_window.tv), + option_hotlist_path); + + + /* Build the hotlist window menu. */ + + static const struct ns_menu hotlist_definition = { + "Hotlist", { + { "Hotlist", NO_ACTION, 0 }, + { "Hotlist.New", NO_ACTION, 0 }, + { "Hotlist.New.Folder", TREE_NEW_FOLDER, 0 }, + { "Hotlist.New.Link", TREE_NEW_LINK, 0 }, + { "_Hotlist.Export", HOTLIST_EXPORT, &dialog_saveas }, + { "Hotlist.Expand", TREE_EXPAND_ALL, 0 }, + { "Hotlist.Expand.All", TREE_EXPAND_ALL, 0 }, + { "Hotlist.Expand.Folders", TREE_EXPAND_FOLDERS, 0 }, + { "Hotlist.Expand.Links", TREE_EXPAND_LINKS, 0 }, + { "Hotlist.Collapse", TREE_COLLAPSE_ALL, 0 }, + { "Hotlist.Collapse.All", TREE_COLLAPSE_ALL, 0 }, + { "Hotlist.Collapse.Folders", TREE_COLLAPSE_FOLDERS, 0 }, + { "Hotlist.Collapse.Links", TREE_COLLAPSE_LINKS, 0 }, + { "Hotlist.Toolbars", NO_ACTION, 0 }, + { "_Hotlist.Toolbars.ToolButtons", TOOLBAR_BUTTONS, 0 }, + { "Hotlist.Toolbars.EditToolbar", TOOLBAR_EDIT, 0 }, + { "Selection", TREE_SELECTION, 0 }, + { "Selection.Edit", TREE_SELECTION_EDIT, 0 }, + { "Selection.Launch", TREE_SELECTION_LAUNCH, 0 }, + { "Selection.Delete", TREE_SELECTION_DELETE, 0 }, + { "SelectAll", TREE_SELECT_ALL, 0 }, + { "Clear", TREE_CLEAR_SELECTION, 0 }, + {NULL, 0, 0} + } + }; + + 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); } /** - * Respond to a mouse click + * Open the hotlist window. * - * \param pointer the pointer state */ -bool ro_gui_hotlist_click(wimp_pointer *pointer) + +void ro_gui_hotlist_open(void) { - ro_gui_tree_click(pointer, hotlist_tree); - if (pointer->buttons == wimp_CLICK_MENU) - ro_gui_menu_create(hotlist_menu, pointer->pos.x, - pointer->pos.y, pointer->w); - else - ro_gui_menu_prepare_action(pointer->w, TREE_SELECTION, false); - return true; + tree_set_redraw(ro_treeview_get_tree(hotlist_window.tv), true); + + 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); +// } + } } - /** - * Informs the hotlist that some content has been visited + * Prepare the hotlist menu for opening * - * \param content the content visited + * \param window The window owning the menu. + * \param *menu The menu about to be opened. */ -void hotlist_visited(hlcache_handle *c) + +void ro_gui_hotlist_menu_prepare(wimp_w window, wimp_menu *menu) { - if ((!c) || (!content_get_url(c)) || (!hotlist_tree)) - return; - ro_gui_hotlist_visited(c, hotlist_tree, hotlist_tree->root); + bool selection; + + 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, TOOLBAR_BUTTONS, + (hotlist_window.toolbar == NULL || + hotlist_window.toolbar->editor)); + ro_gui_menu_set_entry_ticked(hotlist_window.menu, TOOLBAR_BUTTONS, + (hotlist_window.toolbar != NULL && + (hotlist_window.toolbar->display_buttons || + hotlist_window.toolbar->editor))); + + ro_gui_menu_set_entry_shaded(hotlist_window.menu, TOOLBAR_EDIT, + hotlist_window.toolbar == NULL); + ro_gui_menu_set_entry_ticked(hotlist_window.menu, TOOLBAR_EDIT, + (hotlist_window.toolbar != NULL && + hotlist_window.toolbar->editor)); + + ro_gui_save_prepare(GUI_SAVE_HOTLIST_EXPORT_HTML, + NULL, NULL, NULL, NULL); } - /** - * Informs the hotlist that some content has been visited + * Handle submenu warnings for the hotlist menu * - * \param content the content visited - * \param tree the tree to find the URL data from - * \param node the node to update siblings and children of + * \param window The window 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_visited(hlcache_handle *c, struct tree *tree, - struct node *node) + +void ro_gui_hotlist_menu_warning(wimp_w window, wimp_menu *menu, + wimp_selection *selection, menu_action action) { - struct node_element *element; - - for (; node; node = node->next) { - if (!node->folder) { - element = tree_find_element(node, TREE_ELEMENT_URL); - if ((element) && (!strcmp(element->text, - content_get_url(c)))) { - tree_update_URL_node(node, content_get_url(c), - NULL); - tree_handle_node_changed(tree, node, true, - false); - } - } - if (node->child) - ro_gui_hotlist_visited(c, tree, node->child); - } + /* Do nothing */ } - /** - * Prepares the folder dialog contents for a node + * Handle selections from the hotlist menu * - * \param node the node to prepare the dialogue for, or NULL + * \param window The window 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_hotlist_prepare_folder_dialog(struct node *node) + +bool ro_gui_hotlist_menu_select(wimp_w window, wimp_menu *menu, + wimp_selection *selection, menu_action action) { - const char *name; - const char *title; - - dialog_folder_node = node; - if (node) { - title = messages_get("EditFolder"); - name = node->data.text; - } else { - title = messages_get("NewFolder"); - name = messages_get("Folder"); + switch (action) { + case HOTLIST_EXPORT: + ro_gui_dialog_open_persistent(window, dialog_saveas, true); + return true; + case TREE_NEW_FOLDER: + hotlist_add_folder(); + return true; + case TREE_NEW_LINK: + hotlist_add_entry(); + return true; + case TREE_EXPAND_ALL: + hotlist_expand_all(); + return true; + case TREE_EXPAND_FOLDERS: + hotlist_expand_directories(); + return true; + case TREE_EXPAND_LINKS: + hotlist_expand_addresses(); + return true; + case TREE_COLLAPSE_ALL: + hotlist_collapse_all(); + return true; + case TREE_COLLAPSE_FOLDERS: + hotlist_collapse_directories(); + return true; + case TREE_COLLAPSE_LINKS: + hotlist_collapse_addresses(); + return true; + case TREE_SELECTION_EDIT: + hotlist_edit_selected(); + return true; + case TREE_SELECTION_LAUNCH: + hotlist_launch_selected(); + return true; + case TREE_SELECTION_DELETE: + hotlist_delete_selected(); + return true; + case TREE_SELECT_ALL: + hotlist_select_all(); + return true; + case TREE_CLEAR_SELECTION: + hotlist_clear_selection(); + return true; + default: + return false; } - ro_gui_set_window_title(dialog_folder, title); - ro_gui_set_icon_string(dialog_folder, ICON_FOLDER_NAME, name, true); - ro_gui_wimp_event_memorise(dialog_folder); -} + return false; +} /** - * Prepares the entry dialog contents for a node - * - * \param node the node to prepare the dialogue for, or NULL + * Update the theme details of the hotlist window. */ -void ro_gui_hotlist_prepare_entry_dialog(struct node *node) + +void ro_gui_hotlist_update_theme(void) { - struct node_element *element; - const char *name; - const char *title; - const char *url = ""; - - dialog_entry_node = node; - if (node) { - title = messages_get("EditLink"); - name = node->data.text; - if ((element = tree_find_element(node, TREE_ELEMENT_URL))) - url = element->text; - } else { - title = messages_get("NewLink"); - name = messages_get("Link"); - } - ro_gui_set_window_title(dialog_entry, title); - ro_gui_set_icon_string(dialog_entry, ICON_ENTRY_NAME, name, true); - ro_gui_set_icon_string(dialog_entry, ICON_ENTRY_URL, url, true); - ro_gui_wimp_event_memorise(dialog_entry); + ro_treeview_update_theme(hotlist_window.tv); } - /** - * Apply the settings of dialog window (folder/entry edit) + * Check if a particular window handle is the hotlist window * - * \param w the window to apply + * \param window The window in question + * \return true if this window is the hotlist */ -bool ro_gui_hotlist_dialog_apply(wimp_w w) +bool ro_gui_hotlist_check_window(wimp_w window) { - struct node_element *element; - struct node *node; - const char *icon; - char *title; - char *url = NULL; - url_func_result res; - const struct url_data *data; - - /* get our data */ - if (w == dialog_entry) { - icon = ro_gui_get_icon_string(w, ICON_ENTRY_URL); - - res = url_normalize(icon, &url); - if (res != URL_FUNC_OK) { - warn_user(res == URL_FUNC_FAILED ? "NoURLError" - : "NoMemory", 0); - return false; - } + if (hotlist_window.window == window) + return true; + else + return false; +} - icon = ro_gui_get_icon_string(w, ICON_ENTRY_NAME); - while (isspace(*icon)) - icon++; - title = strdup(icon); +/** + * Check if a particular menu handle is the hotlist menu + * + * \param *menu The menu in question. + * \return true if this menu is the hotlist menu + */ - node = dialog_entry_node; - } else { - icon = ro_gui_get_icon_string(w, ICON_FOLDER_NAME); - while (isspace(*icon)) - icon++; - title = strdup(icon); +bool ro_gui_hotlist_check_menu(wimp_menu *menu) +{ + if (hotlist_window.menu == menu) + return true; + else + return false; +} - node = dialog_folder_node; - } +#if 0 +/** + * Handle URL dropped on hotlist + * + * \param message the wimp message we're acting on + * \param url the URL to add + */ +void ro_gui_hotlist_url_drop(wimp_message *message, const char *url) +{ + int x, y; + if (hotlist_window.window != message->data.data_xfer.w) + return; - if (title != NULL) - strip(title); - - /* check for lack of text */ - if (title == NULL || title[0] == '\0') { - if (title == NULL) - warn_user("NoMemory", 0); - else if (title[0] == '\0') - warn_user("NoNameError", 0); - free(url); - free(title); - node = NULL; - return false; - } - ro_gui_set_icon_string(w, url ? ICON_ENTRY_NAME : ICON_FOLDER_NAME, - title, false); - - /* update/insert our data */ - if (!node) { - if (url) { - data = urldb_get_url_data(url); - if (!data) { - urldb_add_url(url); - urldb_set_url_persistence(url, true); - data = urldb_get_url_data(url); - } - if (!data) { - free(url); - free(title); - return false; - } - if (!data->title) - urldb_set_url_title(url, title); - node = dialog_entry_node = tree_create_URL_node( - hotlist_tree->root, url, data, title); - - } else { - node = dialog_folder_node = tree_create_folder_node( - hotlist_tree->root, title); - } - free(url); - free(title); - if (!node) { - warn_user("NoMemory", 0); - return false; - } - tree_handle_node_changed(hotlist_tree, node, true, false); - ro_gui_tree_scroll_visible(hotlist_tree, &node->data); - tree_redraw_area(hotlist_tree, node->box.x - NODE_INSTEP, - 0, NODE_INSTEP, 16384); - } else { - element = tree_find_element(node, TREE_ELEMENT_URL); - if (element) { - free((void *)element->text); - element->text = url; - ro_gui_set_icon_string(w, ICON_ENTRY_URL, url, true); - } - free((void *)node->data.text); - node->data.text = title; - tree_handle_node_changed(hotlist_tree, node, true, false); - } - return true; + ro_gui_tree_get_tree_coordinates(hotlist_window.tree, + message->data.data_xfer.pos.x, + message->data.data_xfer.pos.y, + &x, &y); + hotlist_add_page_xy(url, x, y); } +#endif + diff --git a/riscos/hotlist.h b/riscos/hotlist.h new file mode 100644 index 000000000..e416b2124 --- /dev/null +++ b/riscos/hotlist.h @@ -0,0 +1,36 @@ +/* + * Copyright 2006 Richard Wilson + * 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 + * Hotlist (interface). + */ + +#ifndef _NETSURF_RISCOS_HOTLIST_H_ +#define _NETSURF_RISCOS_HOTLIST_H_ + +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(void); +bool ro_gui_hotlist_check_window(wimp_w window); +bool ro_gui_hotlist_check_menu(wimp_menu *menu); + +#endif + diff --git a/riscos/menus.c b/riscos/menus.c index da0a686ad..39e1a4c03 100644 --- a/riscos/menus.c +++ b/riscos/menus.c @@ -34,9 +34,12 @@ #include "content/content.h" #include "content/hlcache.h" #include "content/urldb.h" +#include "desktop/cookies.h" #include "desktop/browser.h" #include "desktop/gui.h" +#include "desktop/history_global_core.h" #include "desktop/history_core.h" +#include "desktop/hotlist.h" #include "desktop/netsurf.h" #include "desktop/selection.h" #include "desktop/textinput.h" @@ -49,12 +52,14 @@ #include "riscos/gui.h" #include "riscos/global_history.h" #include "riscos/help.h" +#include "riscos/hotlist.h" #include "riscos/menus.h" #include "riscos/options.h" #include "riscos/save.h" #include "riscos/tinct.h" #include "riscos/theme.h" #include "riscos/treeview.h" +#include "riscos/url_suggest.h" #include "riscos/wimp.h" #include "riscos/wimp_event.h" #include "utils/log.h" @@ -63,18 +68,6 @@ #include "utils/utils.h" #include "utils/utf8.h" - -struct ns_menu_entry { - const char *text; /**< menu text (from messages) */ - menu_action action; /**< associated action */ - wimp_w *sub_window; /**< sub-window if any */ -}; - -struct ns_menu { - const char *title; - struct ns_menu_entry entries[]; -}; - struct menu_definition_entry { menu_action action; /**< menu action */ wimp_menu_entry *menu_entry; /**< corresponding menu entry */ @@ -91,7 +84,6 @@ struct menu_definition { }; -static wimp_menu *ro_gui_menu_define_menu(const struct ns_menu *menu); static void ro_gui_menu_define_menu_add(struct menu_definition *definition, const struct ns_menu *menu, int depth, wimp_menu_entry *parent_entry, @@ -101,15 +93,11 @@ 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_set_entry_shaded(wimp_menu *menu, menu_action action, - bool shaded); -static void ro_gui_menu_set_entry_ticked(wimp_menu *menu, menu_action action, - bool ticked); 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, struct tree **tree); + struct toolbar **toolbar, + bool *is_cookies, bool *is_hotlist, bool *is_global_history); static int ro_gui_menu_get_checksum(void); -static bool ro_gui_menu_prepare_url_suggest(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); @@ -143,12 +131,12 @@ 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, *hotlist_menu, *global_history_menu, *cookies_menu, - *image_quality_menu, *browser_toolbar_menu, - *tree_toolbar_menu, *proxy_type_menu, *languages_menu; -/** URL suggestion menu */ -static wimp_MENU(GLOBAL_HISTORY_RECENT_URLS) url_suggest; -wimp_menu *url_suggest_menu = (wimp_menu *)&url_suggest; +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; /* 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 @@ -277,94 +265,6 @@ void ro_gui_menu_init(void) }; browser_menu = ro_gui_menu_define_menu(&browser_definition); - /* hotlist menu */ - static wimp_w one = (wimp_w) 1; - static const struct ns_menu hotlist_definition = { - "Hotlist", { - { "Hotlist", NO_ACTION, 0 }, - { "Hotlist.New", NO_ACTION, 0 }, - { "Hotlist.New.Folder", TREE_NEW_FOLDER, &dialog_folder }, - { "Hotlist.New.Link", TREE_NEW_LINK, &dialog_entry }, - { "_Hotlist.Export", HOTLIST_EXPORT, &dialog_saveas }, - { "Hotlist.Expand", TREE_EXPAND_ALL, 0 }, - { "Hotlist.Expand.All", TREE_EXPAND_ALL, 0 }, - { "Hotlist.Expand.Folders", TREE_EXPAND_FOLDERS, 0 }, - { "Hotlist.Expand.Links", TREE_EXPAND_LINKS, 0 }, - { "Hotlist.Collapse", TREE_COLLAPSE_ALL, 0 }, - { "Hotlist.Collapse.All", TREE_COLLAPSE_ALL, 0 }, - { "Hotlist.Collapse.Folders", TREE_COLLAPSE_FOLDERS, 0 }, - { "Hotlist.Collapse.Links", TREE_COLLAPSE_LINKS, 0 }, - { "Hotlist.Toolbars", NO_ACTION, 0 }, - { "_Hotlist.Toolbars.ToolButtons", TOOLBAR_BUTTONS, 0 }, - { "Hotlist.Toolbars.EditToolbar", TOOLBAR_EDIT, 0 }, - { "Selection", TREE_SELECTION, 0 }, - /* We want a window, but it changes depending upon - * context. Therefore, ensure that the structure is - * created so that we can dynamically modify the - * actual item presented. We do this by creating a - * fake wimp_w with the value 1, which indicates a - * window handle as opposed to a submenu. */ - { "Selection.Edit", TREE_SELECTION_EDIT, &one }, - { "Selection.Launch", TREE_SELECTION_LAUNCH, 0 }, - { "Selection.Delete", TREE_SELECTION_DELETE, 0 }, - { "SelectAll", TREE_SELECT_ALL, 0 }, - { "Clear", TREE_CLEAR_SELECTION, 0 }, - {NULL, 0, 0} - } - }; - hotlist_menu = ro_gui_menu_define_menu(&hotlist_definition); - - /* history menu */ - static const struct ns_menu global_history_definition = { - "History", { - { "History", NO_ACTION, 0 }, - { "_History.Export", HISTORY_EXPORT, &dialog_saveas }, - { "History.Expand", TREE_EXPAND_ALL, 0 }, - { "History.Expand.All", TREE_EXPAND_ALL, 0 }, - { "History.Expand.Folders", TREE_EXPAND_FOLDERS, 0 }, - { "History.Expand.Links", TREE_EXPAND_LINKS, 0 }, - { "History.Collapse", TREE_COLLAPSE_ALL, 0 }, - { "History.Collapse.All", TREE_COLLAPSE_ALL, 0 }, - { "History.Collapse.Folders", TREE_COLLAPSE_FOLDERS, 0 }, - { "History.Collapse.Links", TREE_COLLAPSE_LINKS, 0 }, - { "History.Toolbars", NO_ACTION, 0 }, - { "_History.Toolbars.ToolButtons", TOOLBAR_BUTTONS, 0 }, - { "History.Toolbars.EditToolbar",TOOLBAR_EDIT, 0 }, - { "Selection", TREE_SELECTION, 0 }, - { "Selection.Launch", TREE_SELECTION_LAUNCH, 0 }, - { "Selection.Delete", TREE_SELECTION_DELETE, 0 }, - { "SelectAll", TREE_SELECT_ALL, 0 }, - { "Clear", TREE_CLEAR_SELECTION, 0 }, - {NULL, 0, 0} - } - }; - global_history_menu = ro_gui_menu_define_menu( - &global_history_definition); - - /* history menu */ - static const struct ns_menu cookies_definition = { - "Cookies", { - { "Cookies", NO_ACTION, 0 }, - { "Cookies.Expand", TREE_EXPAND_ALL, 0 }, - { "Cookies.Expand.All", TREE_EXPAND_ALL, 0 }, - { "Cookies.Expand.Folders", TREE_EXPAND_FOLDERS, 0 }, - { "Cookies.Expand.Links", TREE_EXPAND_LINKS, 0 }, - { "Cookies.Collapse", TREE_COLLAPSE_ALL, 0 }, - { "Cookies.Collapse.All", TREE_COLLAPSE_ALL, 0 }, - { "Cookies.Collapse.Folders", TREE_COLLAPSE_FOLDERS, 0 }, - { "Cookies.Collapse.Links", TREE_COLLAPSE_LINKS, 0 }, - { "Cookies.Toolbars", NO_ACTION, 0 }, - { "_Cookies.Toolbars.ToolButtons", TOOLBAR_BUTTONS, 0 }, - { "Cookies.Toolbars.EditToolbar",TOOLBAR_EDIT, 0 }, - { "Selection", TREE_SELECTION, 0 }, - { "Selection.Delete", TREE_SELECTION_DELETE, 0 }, - { "SelectAll", TREE_SELECT_ALL, 0 }, - { "Clear", TREE_CLEAR_SELECTION, 0 }, - {NULL, 0, 0} - } - }; - cookies_menu = ro_gui_menu_define_menu(&cookies_definition); - /* image quality menu */ static const struct ns_menu images_definition = { "Display", { @@ -415,9 +315,7 @@ void ro_gui_menu_init(void) proxy_type_menu = ro_gui_menu_define_menu(&proxy_type_definition); /* special case menus */ - url_suggest_menu->title_data.indirected_text.text = - (char *) messages_get("URLSuggest"); - ro_gui_menu_init_structure(url_suggest_menu, GLOBAL_HISTORY_RECENT_URLS); + ro_gui_url_suggest_init(url_suggest_menu); /* Note: This table *must* be kept in sync with the LangNames file */ static const struct ns_menu lang_definition = { @@ -540,7 +438,7 @@ void ro_gui_menu_create(wimp_menu *menu, int x, int y, wimp_w w) /* prepare the menu state */ if (menu == url_suggest_menu) { - if (!ro_gui_menu_prepare_url_suggest()) + if (!ro_gui_url_suggest_prepare_menu()) return; } else if (menu == recent_search_menu) { if (!ro_gui_search_prepare_menu()) @@ -618,8 +516,8 @@ void ro_gui_menu_closed(bool cleanup) struct browser_window *bw; hlcache_handle *h; struct toolbar *t; - struct tree *tree; os_error *error; + bool is_cookies, is_hotlist, is_global_history; if (current_menu) { @@ -630,15 +528,16 @@ void ro_gui_menu_closed(bool cleanup) warn_user("MenuError", error->errmess); } ro_gui_menu_get_window_details(current_menu_window, - &g, &bw, &h, &t, &tree); - current_menu = NULL; + &g, &bw, &h, &t, + &is_cookies, &is_hotlist, + &is_global_history); if (cleanup) { - ro_gui_wimp_event_menus_closed(); - - if (tree) - ro_gui_tree_menu_closed(tree); + ro_gui_wimp_event_menus_closed(current_menu_window, + current_menu_icon, current_menu); } + + current_menu = NULL; } current_menu_window = NULL; @@ -668,15 +567,16 @@ void ro_gui_menu_objects_moved(void) */ void ro_gui_menu_selection(wimp_selection *selection) { - 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; + int i, j; + bool needs_prepare; + 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, @@ -686,41 +586,58 @@ void ro_gui_menu_selection(wimp_selection *selection) assert(current_menu_window); - /* get the menu entry and associated action */ + /* get the menu entry and associated action and definition */ menu_entry = ¤t_menu->entries[selection->items[0]]; for (i = 1; selection->items[i] != -1; i++) menu_entry = &menu_entry->sub_menu-> entries[selection->items[i]]; action = ro_gui_menu_find_action(current_menu, menu_entry); - /* 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); - global_history_add_recent(url); - } - } 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]); + /* 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. + */ + + 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); + /* 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; + } /* re-open the menu for Adjust clicks */ error = xwimp_get_pointer_info(&pointer); @@ -738,24 +655,26 @@ void ro_gui_menu_selection(wimp_selection *selection) } /* re-prepare all the visible entries */ - i = 0; - menu = current_menu; - do { - j = 0; + if (needs_prepare) { + i = 0; + menu = current_menu; 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); + 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 */ @@ -788,28 +707,42 @@ void ro_gui_menu_warning(wimp_message_menu_warning *warning) for (i = 1; warning->selection.items[i] != -1; i++) menu_entry = &menu_entry->sub_menu-> entries[warning->selection.items[i]]; + action = ro_gui_menu_find_action(current_menu, menu_entry); - 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]); + /* We only process the menu in the old way if the wimp_event module + * hasn't processed it for us. + */ + + if (!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, 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); - /* remove the close icon */ + action, true); + } + } + + /* If this is a dialogue box, remove the close and back icons. */ + + 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); - } + /* open the sub-menu */ error = xwimp_create_sub_menu(menu_entry->sub_menu, @@ -829,55 +762,37 @@ void ro_gui_menu_warning(wimp_message_menu_warning *warning) */ void ro_gui_menu_refresh_toolbar(struct toolbar *toolbar) { +// struct treeview_window *treeview_window; 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) { - tree_resized(hotlist_tree); - xwimp_force_redraw((wimp_w)hotlist_tree->handle, - 0,-16384, 16384, 16384); - } else if (toolbar->type == THEME_HISTORY_TOOLBAR) { - tree_resized(global_history_tree); - xwimp_force_redraw((wimp_w)global_history_tree->handle, - 0,-16384, 16384, 16384); - } else if (toolbar->type == THEME_COOKIES_TOOLBAR) { - tree_resized(cookies_tree); - xwimp_force_redraw((wimp_w)cookies_tree->handle, - 0,-16384, 16384, 16384); + gui_window_update_extent(ro_gui_window_lookup( + current_menu_window)); +// } else if (toolbar->type == THEME_HOTLIST_TOOLBAR) { +// treeview_window = ro_gui_hotlist_get(); +// /* TODO: FIX THIS */ +// /* tree_resized(treeview_window->tree); */ +// xwimp_force_redraw(treeview_window->window, +// 0,-16384, 16384, 16384); +// } else if (toolbar->type == THEME_HISTORY_TOOLBAR) { +// treeview_window = ro_gui_global_history_get(); +// /* TODO: FIX THIS */ +// /* tree_resized(treeview_window->tree); */ +// xwimp_force_redraw(treeview_window->window, +// 0,-16384, 16384, 16384); +// } else if (toolbar->type == THEME_COOKIES_TOOLBAR) { +// treeview_window = ro_gui_cookies_get(); +// /* TODO: FIX THIS */ +// /* tree_resized(treeview_window->tree); */ +// xwimp_force_redraw(treeview_window->window, +// 0,-16384, 16384, 16384); } } -/** - * Builds the URL suggestion menu - */ -bool ro_gui_menu_prepare_url_suggest(void) { - char **suggest_text; - int suggestions; - int i; - - suggest_text = global_history_get_recent(&suggestions); - if (suggestions < 1) - return false; - - for (i = 0; i < suggestions; i++) { - url_suggest_menu->entries[i].menu_flags = 0; - url_suggest_menu->entries[i].data.indirected_text.text = - suggest_text[i]; - url_suggest_menu->entries[i].data.indirected_text.size = - strlen(suggest_text[i]) + 1; - } - - url_suggest_menu->entries[0].menu_flags |= wimp_MENU_TITLE_INDIRECTED; - url_suggest_menu->entries[suggestions - 1].menu_flags |= wimp_MENU_LAST; - return true; -} - - /** * Update navigate menu status and toolbar icons. * @@ -885,8 +800,6 @@ bool ro_gui_menu_prepare_url_suggest(void) { */ void ro_gui_prepare_navigate(struct gui_window *gui) { - int suggestions; - 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, @@ -902,9 +815,9 @@ void ro_gui_prepare_navigate(struct gui_window *gui) ro_gui_menu_prepare_action(gui->window, BROWSER_FIND_TEXT, false); if (gui->toolbar) { - global_history_get_recent(&suggestions); ro_gui_set_icon_shaded_state(gui->toolbar->toolbar_handle, - ICON_TOOLBAR_SUGGEST, (suggestions <= 0)); + ICON_TOOLBAR_SUGGEST, + !ro_gui_url_suggest_prepare_menu()); } } @@ -1122,8 +1035,10 @@ void gui_create_form_select_menu(struct browser_window *bw, /** * Creates a wimp_menu and adds it to the list to handle actions for. * - * \param menu the data to create the menu with - * \return the menu created, or NULL on failure + * \param *menu The data to create the menu with + * \param *callbacks A callback table for the menu (NULL if to be + * handled in the 'old-fashined way' by menus.c). + * \return The menu created, or NULL on failure */ wimp_menu *ro_gui_menu_define_menu(const struct ns_menu *menu) { @@ -1475,13 +1390,12 @@ bool ro_gui_menu_handle_action(wimp_w owner, menu_action action, struct browser_window *bw = NULL; hlcache_handle *h = NULL; struct toolbar *t = NULL; - struct tree *tree; - struct node *node; os_error *error; char url[80]; - const struct url_data *data; + bool is_cookies, is_hotlist, is_global_history; - ro_gui_menu_get_window_details(owner, &g, &bw, &h, &t, &tree); + ro_gui_menu_get_window_details(owner, &g, &bw, &h, &t, + &is_cookies, &is_hotlist, &is_global_history); switch (action) { @@ -1515,42 +1429,26 @@ bool ro_gui_menu_handle_action(wimp_w owner, menu_action action, windows_at_pointer); return true; case HISTORY_SHOW_GLOBAL: - ro_gui_tree_show(global_history_tree); + ro_gui_global_history_open(); return true; /* hotlist actions */ case HOTLIST_ADD_URL: - if ((!hotlist_tree) || (!h) || (!content_get_url(h))) + if (h == NULL || content_get_url(h) == NULL) return false; - data = urldb_get_url_data(content_get_url(h)); - if (data) { - node = tree_create_URL_node(hotlist_tree->root, - content_get_url(h), - data, data->title); - if (node) { - tree_redraw_area(hotlist_tree, - node->box.x - NODE_INSTEP, 0, - NODE_INSTEP, 16384); - tree_handle_node_changed(hotlist_tree, - node, false, true); - ro_gui_tree_scroll_visible(hotlist_tree, - &node->data); - ro_gui_hotlist_save(); - } - } + hotlist_add_page(content_get_url(h)); return true; case HOTLIST_SHOW: - ro_gui_tree_show(hotlist_tree); + ro_gui_hotlist_open(); return true; /* cookies actions */ case COOKIES_SHOW: - ro_gui_tree_show(cookies_tree); + ro_gui_cookies_open(); return true; case COOKIES_DELETE: - if (cookies_tree->root->child) - tree_delete_node(cookies_tree, cookies_tree->root->child, true); + cookies_delete_all(); return true; /* page actions */ @@ -1635,8 +1533,6 @@ bool ro_gui_menu_handle_action(wimp_w owner, menu_action action, if (!h) return false; /* Fall through */ - case HOTLIST_EXPORT: - case HISTORY_EXPORT: ro_gui_menu_prepare_action(owner, action, true); ro_gui_dialog_open_persistent(owner, dialog_saveas, windows_at_pointer); @@ -1788,61 +1684,6 @@ bool ro_gui_menu_handle_action(wimp_w owner, menu_action action, ro_gui_save_options(); return true; - /* tree actions */ - case TREE_NEW_FOLDER: - ro_gui_menu_prepare_action(owner, action, true); - ro_gui_dialog_open_persistent((wimp_w)tree->handle, - dialog_folder, windows_at_pointer); - return true; - case TREE_NEW_LINK: - ro_gui_menu_prepare_action(owner, action, true); - ro_gui_dialog_open_persistent((wimp_w)tree->handle, - dialog_entry, windows_at_pointer); - return true; - case TREE_EXPAND_ALL: - case TREE_EXPAND_FOLDERS: - case TREE_EXPAND_LINKS: - tree_handle_expansion(tree, tree->root, true, - (action != TREE_EXPAND_LINKS), - (action != TREE_EXPAND_FOLDERS)); - return true; - case TREE_COLLAPSE_ALL: - case TREE_COLLAPSE_FOLDERS: - case TREE_COLLAPSE_LINKS: - tree_handle_expansion(tree, tree->root, false, - (action != TREE_COLLAPSE_LINKS), - (action != TREE_COLLAPSE_FOLDERS)); - return true; - case TREE_SELECTION_EDIT: - return true; - case TREE_SELECTION_LAUNCH: - ro_gui_tree_launch_selected(tree); - return true; - case TREE_SELECTION_DELETE: - ro_gui_tree_stop_edit(tree); - tree_delete_selected_nodes(tree, tree->root); - if (tree == hotlist_tree) - ro_gui_hotlist_save(); - ro_gui_menu_prepare_action(owner, TREE_CLEAR_SELECTION, true); - ro_gui_menu_prepare_action(owner, TREE_SELECTION, true); - return true; - case TREE_SELECT_ALL: - ro_gui_tree_stop_edit(tree); - if (tree->root->child) { - tree->temp_selection = NULL; - tree_set_node_selected(tree, tree->root, true); - } - ro_gui_menu_prepare_action(owner, TREE_CLEAR_SELECTION, true); - ro_gui_menu_prepare_action(owner, TREE_SELECTION, true); - return true; - case TREE_CLEAR_SELECTION: - tree->temp_selection = NULL; - ro_gui_tree_stop_edit(tree); - tree_set_node_selected(tree, tree->root, false); - ro_gui_menu_prepare_action(owner, TREE_CLEAR_SELECTION, true); - ro_gui_menu_prepare_action(owner, TREE_SELECTION, true); - return true; - /* toolbar actions */ case TOOLBAR_BUTTONS: assert(t); @@ -1895,21 +1736,20 @@ bool ro_gui_menu_handle_action(wimp_w owner, menu_action action, void ro_gui_menu_prepare_action(wimp_w owner, menu_action action, bool windows) { - struct menu_definition_entry *entry; struct gui_window *g; struct browser_window *bw; hlcache_handle *h; struct toolbar *t; - struct tree *tree; - struct node *node; 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, &tree); + 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) { @@ -1935,35 +1775,11 @@ void ro_gui_menu_prepare_action(wimp_w owner, menu_action action, !(h || history_back_available(bw->history) || history_forward_available(bw->history)))); break; - case HISTORY_SHOW_GLOBAL: - ro_gui_menu_set_entry_shaded(current_menu, action, - !global_history_tree); - break; /* hotlist actions */ case HOTLIST_ADD_URL: ro_gui_menu_set_entry_shaded(current_menu, action, - (!h || !hotlist_tree)); - break; - case HOTLIST_SHOW: - ro_gui_menu_set_entry_shaded(current_menu, action, - !hotlist_tree); - if ((t) && (!t->editor) && - (t->type == THEME_BROWSER_TOOLBAR)) - ro_gui_set_icon_shaded_state( - t->toolbar_handle, - ICON_TOOLBAR_BOOKMARK, - !hotlist_tree); - break; - - /* cookies actions */ - case COOKIES_SHOW: - ro_gui_menu_set_entry_shaded(current_menu, action, - !cookies_tree); - break; - case COOKIES_DELETE: - ro_gui_menu_set_entry_shaded(current_menu, action, - !(cookies_tree && cookies_tree->root->child)); + h == NULL); break; /* page actions */ @@ -2003,7 +1819,8 @@ void ro_gui_menu_prepare_action(wimp_w owner, menu_action action, /* object actions */ case BROWSER_OBJECT: ro_gui_menu_set_entry_shaded(current_menu, action, - !current_menu_object && !current_menu_url); + !current_menu_object && + !current_menu_url); break; case BROWSER_OBJECT_LINK: @@ -2013,7 +1830,8 @@ void ro_gui_menu_prepare_action(wimp_w owner, menu_action action, case BROWSER_OBJECT_INFO: if (windows && current_menu_object) - ro_gui_menu_prepare_objectinfo(current_menu_object, + ro_gui_menu_prepare_objectinfo( + current_menu_object, current_menu_url); /* Fall through */ case BROWSER_OBJECT_RELOAD: @@ -2024,7 +1842,8 @@ void ro_gui_menu_prepare_action(wimp_w owner, menu_action action, case BROWSER_OBJECT_PRINT: /* not yet implemented */ - ro_gui_menu_set_entry_shaded(current_menu, action, true); + ro_gui_menu_set_entry_shaded(current_menu, action, + true); break; /* save actions (browser, hotlist, history) */ @@ -2032,7 +1851,8 @@ void ro_gui_menu_prepare_action(wimp_w owner, menu_action action, 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, + ro_gui_save_prepare(GUI_SAVE_OBJECT_ORIG, + current_menu_object, NULL, NULL, NULL); break; case BROWSER_OBJECT_EXPORT: @@ -2047,41 +1867,41 @@ void ro_gui_menu_prepare_action(wimp_w owner, menu_action action, if (h) { switch (content_get_type(h)) { /* \todo - this classification should prob be done in content_() */ - /* bitmap types (Sprite export possible) */ + /* bitmap types (Sprite export possible) */ #ifdef WITH_JPEG - case CONTENT_JPEG: + case CONTENT_JPEG: #endif #ifdef WITH_MNG - case CONTENT_JNG: - case CONTENT_MNG: + case CONTENT_JNG: + case CONTENT_MNG: #endif #ifdef WITH_GIF - case CONTENT_GIF: + case CONTENT_GIF: #endif #ifdef WITH_BMP - case CONTENT_BMP: - case CONTENT_ICO: + case CONTENT_BMP: + case CONTENT_ICO: #endif #if defined(WITH_MNG) || defined(WITH_PNG) - case CONTENT_PNG: + case CONTENT_PNG: #endif #ifdef WITH_SPRITE - case CONTENT_SPRITE: + case CONTENT_SPRITE: #endif - exp_sprite = true; - break; + exp_sprite = true; + break; - /* vector types (Draw export possible) */ + /* vector types (Draw export possible) */ #if defined(WITH_NS_SVG) || defined(WITH_RSVG) - case CONTENT_SVG: + case CONTENT_SVG: #endif #ifdef WITH_DRAW - case CONTENT_DRAW: + case CONTENT_DRAW: #endif - exp_draw = true; - break; + exp_draw = true; + break; - default: break; + default: break; } } @@ -2229,16 +2049,6 @@ void ro_gui_menu_prepare_action(wimp_w owner, menu_action action, content_get_url(h), content_get_title(h)); break; - case HOTLIST_EXPORT: - if ((tree) && (windows)) - ro_gui_save_prepare(GUI_SAVE_HOTLIST_EXPORT_HTML, - NULL, NULL, NULL, NULL); - break; - case HISTORY_EXPORT: - if ((tree) && (windows)) - ro_gui_save_prepare(GUI_SAVE_HISTORY_EXPORT_HTML, - NULL, NULL, NULL, NULL); - break; /* navigation actions */ case BROWSER_NAVIGATE_BACK: @@ -2379,82 +2189,7 @@ void ro_gui_menu_prepare_action(wimp_w owner, menu_action action, break; /* tree actions */ - case TREE_NEW_FOLDER: - ro_gui_hotlist_prepare_folder_dialog(NULL); - break; - case TREE_NEW_LINK: - ro_gui_hotlist_prepare_entry_dialog(NULL); - break; - case TREE_EXPAND_ALL: - case TREE_EXPAND_FOLDERS: - case TREE_EXPAND_LINKS: - case TREE_COLLAPSE_ALL: - case TREE_COLLAPSE_FOLDERS: - case TREE_COLLAPSE_LINKS: - if ((tree) && (tree->root)) { - ro_gui_menu_set_entry_shaded(current_menu, - action, !tree->root->child); - - if ((t) && (!t->editor) && (t->type != - THEME_BROWSER_TOOLBAR)) { - ro_gui_set_icon_shaded_state( - t->toolbar_handle, - ICON_TOOLBAR_EXPAND, - !tree->root->child); - ro_gui_set_icon_shaded_state( - t->toolbar_handle, - ICON_TOOLBAR_OPEN, - !tree->root->child); - } - } - break; case TREE_SELECTION: - if ((!tree) || (!tree->root)) - break; - if (tree->root->child) - result = tree_has_selection(tree->root->child); - 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_DELETE, !result); - ro_gui_set_icon_shaded_state( - t->toolbar_handle, - ICON_TOOLBAR_LAUNCH, !result); - } - break; - case TREE_SELECTION_EDIT: - node = tree_get_selected_node(tree->root); - entry = ro_gui_menu_find_entry(current_menu, action); - if ((!node) || (!entry)) - break; - if (node->folder) { - entry->menu_entry->sub_menu = - (wimp_menu *)dialog_folder; - if (windows) - ro_gui_hotlist_prepare_folder_dialog(node); - } else { - entry->menu_entry->sub_menu = - (wimp_menu *)dialog_entry; - if (windows) - ro_gui_hotlist_prepare_entry_dialog(node); - } - break; - case TREE_SELECTION_LAUNCH: - case TREE_SELECTION_DELETE: - case TREE_CLEAR_SELECTION: - if ((!tree) || (!tree->root)) - break; - if (tree->root->child) - result = tree_has_selection(tree->root->child); - ro_gui_menu_set_entry_shaded(current_menu, - action, !result); - break; - case TREE_SELECT_ALL: - ro_gui_menu_set_entry_shaded(current_menu, action, - !tree->root->child); break; /* toolbar actions */ @@ -2509,31 +2244,35 @@ void ro_gui_menu_prepare_action(wimp_w owner, menu_action action, */ void ro_gui_menu_get_window_details(wimp_w w, struct gui_window **g, struct browser_window **bw, hlcache_handle **h, - struct toolbar **toolbar, struct tree **tree) + 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; - *tree = NULL; } else { *bw = NULL; *h = NULL; - if ((hotlist_tree) && (w == (wimp_w)hotlist_tree->handle)) - *tree = hotlist_tree; - else if ((global_history_tree) && - (w == (wimp_w)global_history_tree->handle)) - *tree = global_history_tree; - else if ((cookies_tree) && (w == (wimp_w)cookies_tree->handle)) - *tree = cookies_tree; - else - *tree = NULL; - if (*tree) - *toolbar = (*tree)->toolbar; - else + 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; + } } } @@ -2595,6 +2334,7 @@ bool ro_gui_menu_translate(struct menu_definition *menu) char *translated; utf8_convert_ret err; + /* read current alphabet */ error = xosbyte1(osbyte_ALPHABET_NUMBER, 127, 0, &alphabet); if (error) { diff --git a/riscos/menus.h b/riscos/menus.h index ec72cbf83..7cb6a4c3f 100644 --- a/riscos/menus.h +++ b/riscos/menus.h @@ -155,6 +155,20 @@ typedef enum { } menu_action; +/* Menu entry structures for use when defining menus. */ + +struct ns_menu_entry { + const char *text; /**< menu text (from messages) */ + menu_action action; /**< associated action */ + wimp_w *sub_window; /**< sub-window if any */ +}; + +struct ns_menu { + const char *title; + struct ns_menu_entry entries[]; +}; + + void ro_gui_menu_init(void); void ro_gui_menu_create(wimp_menu* menu, int x, int y, wimp_w w); bool ro_gui_menu_handle_action(wimp_w owner, menu_action action, @@ -171,4 +185,10 @@ 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); +void ro_gui_menu_set_entry_ticked(wimp_menu *menu, menu_action action, + bool ticked); + #endif diff --git a/riscos/save.c b/riscos/save.c index a222b6df9..2430c13aa 100644 --- a/riscos/save.c +++ b/riscos/save.c @@ -37,6 +37,8 @@ #include "oslib/wimpspriteop.h" #include "content/content.h" #include "content/hlcache.h" +#include "desktop/hotlist.h" +#include "desktop/history_global_core.h" #include "desktop/netsurf.h" #include "desktop/save_complete.h" #include "desktop/save_text.h" @@ -630,9 +632,9 @@ void ro_gui_save_drag_end(wimp_dragged *drag) while (!dest_ok && (box = box_at_point(box, pos.x, pos.y, &box_x, &box_y, &h))) { - if (box->style && + if (box->style && css_computed_visibility( - box->style) == + box->style) == CSS_VISIBILITY_HIDDEN) continue; @@ -897,8 +899,7 @@ bool ro_gui_save_content(hlcache_handle *h, char *path, bool force_overwrite) LINK_TEXT, path); case GUI_SAVE_HOTLIST_EXPORT_HTML: - if (!options_save_tree(hotlist_tree, path, - "NetSurf hotlist")) + if (!hotlist_export(path)) return false; error = xosfile_set_type(path, 0xfaf); if (error) @@ -906,8 +907,7 @@ bool ro_gui_save_content(hlcache_handle *h, char *path, bool force_overwrite) error->errnum, error->errmess)); break; case GUI_SAVE_HISTORY_EXPORT_HTML: - if (!options_save_tree(global_history_tree, path, - "NetSurf history")) + if (!history_global_export(path)) return false; error = xosfile_set_type(path, 0xfaf); if (error) @@ -1346,7 +1346,7 @@ void ro_gui_save_set_state(hlcache_handle *h, gui_save_type save_type, } /* leafname */ - if (url && url_nice(url, &nice, option_strip_extensions) == + if (url && url_nice(url, &nice, option_strip_extensions) == URL_FUNC_OK) { for (i = 0; nice[i]; i++) { if (nice[i] == '.') diff --git a/riscos/sslcert.c b/riscos/sslcert.c index 5c77f31d5..990c2501c 100644 --- a/riscos/sslcert.c +++ b/riscos/sslcert.c @@ -1,5 +1,6 @@ /* * Copyright 2006 John M Bell + * Copyright 2010 Stephen Fryatt * * This file is part of NetSurf, http://www.netsurf-browser.org/ * @@ -32,9 +33,11 @@ #include "content/fetch.h" #include "content/urldb.h" #include "desktop/browser.h" +#include "desktop/sslcert.h" #include "desktop/gui.h" #include "desktop/tree.h" #include "riscos/dialog.h" +#include "riscos/sslcert.h" #include "riscos/textarea.h" #include "riscos/treeview.h" #include "riscos/wimp.h" @@ -47,50 +50,36 @@ #define ICON_SSL_REJECT 3 #define ICON_SSL_ACCEPT 4 -#define ICON_CERT_VERSION 3 -#define ICON_CERT_VALID_FROM 5 -#define ICON_CERT_TYPE 7 -#define ICON_CERT_VALID_TO 9 -#define ICON_CERT_SERIAL 11 -#define ICON_CERT_ISSUER 13 -#define ICON_CERT_SUBJECT 15 - -static wimp_window *dialog_tree_template; -static wimp_window *dialog_cert_template; -static wimp_window *dialog_display_template; - -struct session_data { - struct session_cert *certs; - unsigned long num; - char *url; - struct tree *tree; - - nserror (*cb)(bool proceed, void *pw); - void *cbpw; -}; -struct session_cert { - char version[16], valid_from[32], valid_to[32], type[8], serial[32]; - char *issuer_t; - char *subject_t; - uintptr_t issuer; - uintptr_t subject; +static wimp_window *ro_gui_cert_dialog_template; +static wimp_window *ro_gui_cert_tree_template; + +struct ro_sslcert +{ + wimp_w window; + wimp_w pane; + ro_treeview *tv; + struct sslcert_session_data *data; }; -static bool ro_gui_cert_click(wimp_pointer *pointer); -static void ro_gui_cert_close(wimp_w w); -static bool ro_gui_cert_apply(wimp_w w); +static void ro_gui_cert_accept(wimp_pointer *pointer); +static void ro_gui_cert_reject(wimp_pointer *pointer); +static void ro_gui_cert_close_window(wimp_w w); +static void ro_gui_cert_release_window(struct ro_sslcert *s); /** - * Load the cert window template + * Load and initialise the certificate window template */ -void ro_gui_cert_init(void) +void ro_gui_cert_preinitialise(void) { - dialog_tree_template = ro_gui_dialog_load_template("tree"); - dialog_cert_template = ro_gui_dialog_load_template("sslcert"); - dialog_display_template = ro_gui_dialog_load_template("ssldisplay"); + /* Load templates for the SSL windows and adjust the tree window + * flags to suit. + */ + + ro_gui_cert_dialog_template = ro_gui_dialog_load_template("sslcert"); + ro_gui_cert_tree_template = ro_gui_dialog_load_template("tree"); - dialog_tree_template->flags &= ~(wimp_WINDOW_MOVEABLE | + ro_gui_cert_tree_template->flags &= ~(wimp_WINDOW_MOVEABLE | wimp_WINDOW_BACK_ICON | wimp_WINDOW_CLOSE_ICON | wimp_WINDOW_TITLE_ICON | @@ -98,170 +87,170 @@ void ro_gui_cert_init(void) wimp_WINDOW_TOGGLE_ICON); } +/** + * Load and initialise the certificate window template + */ + +void ro_gui_cert_postinitialise(void) +{ + /* Initialise the SSL module. */ + + sslcert_init(); +} + /** * Open the certificate verification dialog + * + * \param *bw The browser window owning the certificates. + * \param *c The content data corresponding to the + * certificates. + * \param *certs The certificate details. + * \param num The number of certificates included. */ void gui_cert_verify(const char *url, const struct ssl_cert_info *certs, unsigned long num, nserror (*cb)(bool proceed, void *pw), void *cbpw) { - wimp_w w; - wimp_w ssl_w; - const struct ssl_cert_info *from; - struct session_cert *to; - struct session_data *data; - struct tree *tree; - struct node *node; - wimp_window_state state; - wimp_icon_state istate; - os_error *error; - long i; + struct ro_sslcert *sslcert_window; + wimp_window_state state; + wimp_icon_state istate; + wimp_window_info info; + os_error *error; + bool set_extent; assert(certs); - /* copy the certificate information */ - data = calloc(1, sizeof(struct session_data)); - if (!data) { - warn_user("NoMemory", 0); + sslcert_window = malloc(sizeof(struct ro_sslcert)); + if (sslcert_window == NULL) { + LOG(("Failed to allocate memory for SSL Cert Dialog")); return; } - data->url = strdup(url); - if (!data->url) { - free(data); - warn_user("NoMemory", 0); - return; - } - data->cb = cb; - data->cbpw = cbpw; - data->num = num; - data->certs = calloc(num, sizeof(struct session_cert)); - if (!data->certs) { - free(data->url); - free(data); - warn_user("NoMemory", 0); - return; - } - for (i = 0; i < (long)num; i++) { - to = &data->certs[i]; - from = &certs[i]; - to->subject_t = strdup(from->subject); - to->issuer_t = strdup(from->issuer); - if ((!to->subject_t) || (!to->issuer_t)) { - for (; i >= 0; i--) { - to = &data->certs[i]; - free(to->subject_t); - free(to->issuer_t); - } - free(data->certs); - free(data->url); - free(data); - warn_user("NoMemory", 0); - return; - } - snprintf(to->version, sizeof data->certs->version, "%ld", - from->version); - snprintf(to->valid_from, sizeof data->certs->valid_from, "%s", - from->not_before); - snprintf(to->type, sizeof data->certs->type, "%d", - from->cert_type); - snprintf(to->valid_to, sizeof data->certs->valid_to, "%s", - from->not_after); - snprintf(to->serial, sizeof data->certs->serial, "%ld", - from->serial); - } - /* create the SSL window */ - error = xwimp_create_window(dialog_cert_template, &ssl_w); + /* Create the SSL window and its pane. */ + + error = xwimp_create_window(ro_gui_cert_dialog_template, + &(sslcert_window->window)); if (error) { - free(data->certs); - free(data->url); - free(data); LOG(("xwimp_create_window: 0x%x: %s", error->errnum, error->errmess)); + free(sslcert_window); return; } - /* automated SSL window event handling */ - ro_gui_wimp_event_set_user_data(ssl_w, data); - ro_gui_wimp_event_register_cancel(ssl_w, ICON_SSL_REJECT); - ro_gui_wimp_event_register_ok(ssl_w, ICON_SSL_ACCEPT, ro_gui_cert_apply); - ro_gui_dialog_open_persistent(NULL, ssl_w, false); - - /* create a tree window (styled as a list) */ - error = xwimp_create_window(dialog_tree_template, &w); + error = xwimp_create_window(ro_gui_cert_tree_template, + &(sslcert_window->pane)); if (error) { - ro_gui_cert_close(ssl_w); LOG(("xwimp_create_window: 0x%x: %s", error->errnum, error->errmess)); + free(sslcert_window); return; } - tree = calloc(sizeof(struct tree), 1); - if (!tree) { - ro_gui_cert_close(ssl_w); - warn_user("NoMemory", 0); + + /* Create the SSL data and build a tree from it. */ + + sslcert_window->tv = ro_treeview_create(sslcert_window->pane, NULL, + sslcert_get_tree_flags()); + if (sslcert_window->tv == NULL) { + LOG(("Failed to allocate treeview")); + free(sslcert_window); return; } - tree->root = tree_create_folder_node(NULL, "Root"); - if (!tree->root) { - ro_gui_cert_close(ssl_w); - warn_user("NoMemory", 0); - free(tree); - tree = NULL; + + sslcert_window->data = sslcert_create_session_data(num, url, cb, cbpw); + sslcert_load_tree(ro_treeview_get_tree(sslcert_window->tv), + certs, sslcert_window->data); + + tree_set_redraw(ro_treeview_get_tree(sslcert_window->tv), true); + + /* Set up the certificate window event handling. + * + * (The action buttons are registered as button events, not OK and + * Cancel, as both need to carry out actions.) + */ + + ro_gui_wimp_event_set_user_data(sslcert_window->window, sslcert_window); + ro_gui_wimp_event_register_close_window(sslcert_window->window, + ro_gui_cert_close_window); + ro_gui_wimp_event_register_button(sslcert_window->window, + ICON_SSL_REJECT, ro_gui_cert_reject); + ro_gui_wimp_event_register_button(sslcert_window->window, + ICON_SSL_ACCEPT, ro_gui_cert_accept); + + ro_gui_dialog_open_persistent(NULL, sslcert_window->window, false); + + /* Nest the tree window inside the pane window. To do this, we: + * - Get the current pane extent, + * - Get the parent window position and the location of the pane- + * locating icon inside it, + * - Set the visible area of the pane to suit, + * - Check that the pane extents are OK for this visible area, and + * increase them if necessary, + * - Before finally opening the pane as a nested part of the parent. + */ + + info.w = sslcert_window->pane; + error = xwimp_get_window_info_header_only(&info); + if (error) { + ro_gui_cert_release_window(sslcert_window); + LOG(("xwimp_get_window_info: 0x%x: %s", + error->errnum, error->errmess)); return; } - tree->root->expanded = true; - tree->handle = (int)w; - tree->movable = false; - tree->no_drag = true; - tree->no_vscroll = true; - tree->no_furniture = true; - tree->single_selection = true; - data->tree = tree; - - /* put the SSL names in the tree */ - for (i = 0; i < (long)num; i++) { - node = tree_create_leaf_node(tree->root, certs[i].subject); - if (node) { - node->data.data = TREE_ELEMENT_SSL; - tree_set_node_sprite(node, "small_xxx", "small_xxx"); - } - } - - /* automated treeview event handling */ - ro_gui_wimp_event_set_user_data(w, tree); - ro_gui_wimp_event_register_keypress(w, ro_gui_tree_keypress); - ro_gui_wimp_event_register_redraw_window(w, ro_gui_tree_redraw); - ro_gui_wimp_event_register_open_window(w, ro_gui_tree_open); - ro_gui_wimp_event_register_close_window(w, ro_gui_wimp_event_finalise); - ro_gui_wimp_event_register_mouse_click(w, ro_gui_cert_click); - /* nest the tree window inside the pane window */ - state.w = ssl_w; + state.w = sslcert_window->window; error = xwimp_get_window_state(&state); if (error) { - ro_gui_cert_close(ssl_w); + ro_gui_cert_release_window(sslcert_window); LOG(("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess)); return; } - istate.w = ssl_w; + istate.w = sslcert_window->window; istate.i = ICON_SSL_PANE; error = xwimp_get_icon_state(&istate); if (error) { - ro_gui_cert_close(ssl_w); + ro_gui_cert_release_window(sslcert_window); LOG(("xwimp_get_icon_state: 0x%x: %s", error->errnum, error->errmess)); return; } - state.w = w; + + state.w = sslcert_window->pane; state.visible.x1 = state.visible.x0 + istate.icon.extent.x1 - 20 - - ro_get_vscroll_width(w); + ro_get_vscroll_width(sslcert_window->pane); state.visible.x0 += istate.icon.extent.x0 + 20; state.visible.y0 = state.visible.y1 + istate.icon.extent.y0 + 20; state.visible.y1 += istate.icon.extent.y1 - 32; - error = xwimp_open_window_nested(PTR_WIMP_OPEN(&state), ssl_w, + + set_extent = false; + + if ((info.extent.x1 - info.extent.x0) < + (state.visible.x1 - state.visible.x0)) { + info.extent.x0 = 0; + info.extent.x1 = state.visible.x1 - state.visible.x0; + set_extent = true; + } + if ((info.extent.y1 - info.extent.y0) < + (state.visible.y1 - state.visible.y0)) { + info.extent.y1 = 0; + info.extent.x1 = state.visible.y0 - state.visible.y1; + set_extent = true; + } + + if (set_extent) { + error = xwimp_set_extent(sslcert_window->pane, &(info.extent)); + if (error) { + ro_gui_cert_release_window(sslcert_window); + LOG(("xwimp_set_extent: 0x%x: %s", + error->errnum, error->errmess)); + return; + } + } + + error = xwimp_open_window_nested(PTR_WIMP_OPEN(&state), + sslcert_window->window, wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT << wimp_CHILD_XORIGIN_SHIFT | wimp_CHILD_LINKS_PARENT_VISIBLE_TOP_OR_RIGHT @@ -271,192 +260,100 @@ void gui_cert_verify(const char *url, wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT << wimp_CHILD_RS_EDGE_SHIFT); if (error) { - ro_gui_cert_close(ssl_w); + ro_gui_cert_release_window(sslcert_window); LOG(("xwimp_open_window_nested: 0x%x: %s", error->errnum, error->errmess)); + ro_gui_cert_release_window(sslcert_window); return; } - tree_initialise(tree); } -void ro_gui_cert_open(struct tree *tree, struct node *node) -{ - struct node *n; - struct session_data *data; - struct session_cert *session; - wimp_window_state state; - wimp_w child; - wimp_w parent; - wimp_w w; - unsigned long i; - os_error *error; - - assert(tree->root); +/** + * Handle acceptance of certificate via event callback. + * + * \param *pointer The wimp pointer block. + */ - /* firstly we need to get our node index in the list */ - for (n = tree->root->child, i = 0; n; i++, n = n->next) - if (n == node) - break; - assert(n); +void ro_gui_cert_accept(wimp_pointer *pointer) +{ + struct ro_sslcert *s; - /* now we get the handle of our list window */ - child = (wimp_w)tree->handle; - assert(child); + s = (struct ro_sslcert *) ro_gui_wimp_event_get_user_data(pointer->w); - /* now we can get the linked parent handle */ - state.w = child; - error = xwimp_get_window_state_and_nesting(&state, &parent, 0); - if (error) { - LOG(("xwimp_get_window_state: 0x%x: %s", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); - return; - } - assert(parent); - - /* from this we can get our session data */ - data = (struct session_data *)ro_gui_wimp_event_get_user_data(parent); - assert(data); - assert(data->tree == tree); - - /* and finally the nodes session certificate data */ - session = &data->certs[i]; - assert(session); - - dialog_display_template->icons[ICON_CERT_VERSION].data.indirected_text.text = session->version; - dialog_display_template->icons[ICON_CERT_VERSION].data.indirected_text.size = strlen(session->version) + 1; - dialog_display_template->icons[ICON_CERT_VALID_FROM].data.indirected_text.text = session->valid_from; - dialog_display_template->icons[ICON_CERT_VALID_FROM].data.indirected_text.size = strlen(session->valid_from) + 1; - dialog_display_template->icons[ICON_CERT_TYPE].data.indirected_text.text = session->type; - dialog_display_template->icons[ICON_CERT_TYPE].data.indirected_text.size = strlen(session->type) + 1; - dialog_display_template->icons[ICON_CERT_VALID_TO].data.indirected_text.text = session->valid_to; - dialog_display_template->icons[ICON_CERT_VALID_TO].data.indirected_text.size = strlen(session->valid_to) + 1; - dialog_display_template->icons[ICON_CERT_SERIAL].data.indirected_text.text = session->serial; - dialog_display_template->icons[ICON_CERT_SERIAL].data.indirected_text.size = strlen(session->serial) + 1; - - error = xwimp_create_window(dialog_display_template, &w); - if (error) { - LOG(("xwimp_create_window: 0x%x: %s", - error->errnum, error->errmess)); - free(session); - warn_user("MiscError", error->errmess); - return; + if (s != NULL) { + sslcert_accept(s->data); + ro_gui_dialog_close(s->window); + ro_gui_cert_release_window(s); } - if (session->issuer) - ro_textarea_destroy(session->issuer); - session->issuer = ro_textarea_create(w, ICON_CERT_ISSUER, - TEXTAREA_MULTILINE | TEXTAREA_READONLY, - ro_gui_desktop_font_family, ro_gui_desktop_font_size, - ro_gui_desktop_font_style); - if (!session->issuer) { - xwimp_delete_window(w); - warn_user("NoMemory", 0); - return; - } - if (!ro_textarea_set_text(session->issuer, session->issuer_t)) { - ro_textarea_destroy(session->issuer); - xwimp_delete_window(w); - warn_user("NoMemory", 0); - return; - } - - if (session->subject) - ro_textarea_destroy(session->subject); - session->subject = ro_textarea_create(w, ICON_CERT_SUBJECT, - TEXTAREA_MULTILINE | TEXTAREA_READONLY, - ro_gui_desktop_font_family, ro_gui_desktop_font_size, - ro_gui_desktop_font_style); - if (!session->subject) { - ro_textarea_destroy(session->issuer); - xwimp_delete_window(w); - warn_user("NoMemory", 0); - return; - } - if (!ro_textarea_set_text(session->subject, session->subject_t)) { - ro_textarea_destroy(session->subject); - ro_textarea_destroy(session->issuer); - xwimp_delete_window(w); - warn_user("NoMemory", 0); - return; - } - ro_gui_wimp_event_register_close_window(w, ro_gui_wimp_event_finalise); - ro_gui_dialog_open_persistent(parent, w, false); } /** - * Handle closing of certificate verification dialog + * Handle rejection of certificate via event callback. + * + * \param w The wimp pointer block. */ -void ro_gui_cert_close(wimp_w w) -{ - struct session_data *data; - os_error *error; - unsigned long i; - data = (struct session_data *)ro_gui_wimp_event_get_user_data(w); - assert(data); +void ro_gui_cert_reject(wimp_pointer *pointer) +{ + struct ro_sslcert *s; - /* If we didn't accept the certificate, send failure response */ - if (data->cb != NULL) - data->cb(false, data->cbpw); + s = (struct ro_sslcert *) ro_gui_wimp_event_get_user_data(pointer->w); - for (i = 0; i < data->num; i++) { - if (data->certs[i].subject) - ro_textarea_destroy(data->certs[i].subject); - if (data->certs[i].issuer) - ro_textarea_destroy(data->certs[i].issuer); - } - free(data->certs); - free(data->url); - if (data->tree) { - tree_delete_node(data->tree, data->tree->root, false); - ro_gui_dialog_close((wimp_w)data->tree->handle); - error = xwimp_delete_window((wimp_w)data->tree->handle); - if (error) { - LOG(("xwimp_delete_window: 0x%x:%s", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); - } - ro_gui_wimp_event_finalise((wimp_w)data->tree->handle); - free(data->tree); + if (s != NULL) { + sslcert_reject(s->data); + ro_gui_dialog_close(s->window); + ro_gui_cert_release_window(s); } - free(data); +} - ro_gui_dialog_close(w); - error = xwimp_delete_window(w); - if (error) { - LOG(("xwimp_delete_window: 0x%x:%s", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); - } +/** + * Callback to handle the closure of the SSL dialogue by other means. + * + * \param w The window being closed. + */ +static void ro_gui_cert_close_window(wimp_w w) +{ + struct ro_sslcert *s; + + s = (struct ro_sslcert *) ro_gui_wimp_event_get_user_data(w); + + if (s != NULL) + ro_gui_cert_release_window(s); } /** - * Handle acceptance of certificate + * Handle closing of the RISC OS certificate verification dialog, deleting + * the windows and freeing up the treeview and data block. + * + * \param *s The data block associated with the dialogue. */ -bool ro_gui_cert_apply(wimp_w w) -{ - struct session_data *session; - session = (struct session_data *)ro_gui_wimp_event_get_user_data(w); - assert(session); +void ro_gui_cert_release_window(struct ro_sslcert *s) +{ + os_error *error; - urldb_set_cert_permissions(session->url, true); - session->cb(true, session->cbpw); + if (s == NULL) + return; - /* Flag that we sent response by invalidating callback details */ - session->cb = NULL; - session->cbpw = NULL; + LOG(("Releasing SSL data: 0x%x", (unsigned) s)); - return true; -} + ro_gui_wimp_event_finalise(s->window); + ro_treeview_destroy(s->tv); -bool ro_gui_cert_click(wimp_pointer *pointer) -{ - struct tree *tree; + error = xwimp_delete_window(s->window); + if (error) { + LOG(("xwimp_delete_window: 0x%x:%s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + } + error = xwimp_delete_window(s->pane); + if (error) { + LOG(("xwimp_delete_window: 0x%x:%s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + } - tree = (struct tree *)ro_gui_wimp_event_get_user_data(pointer->w); - ro_gui_tree_click(pointer, tree); - return true; + free(s); } diff --git a/riscos/sslcert.h b/riscos/sslcert.h new file mode 100644 index 000000000..7fba9d3f2 --- /dev/null +++ b/riscos/sslcert.h @@ -0,0 +1,32 @@ +/* + * Copyright 2006 Richard Wilson + * 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 + * SSL certificate viewer (interface). + */ + +#ifndef _NETSURF_RISCOS_SSLCERT_H_ +#define _NETSURF_RISCOS_SSLCERT_H_ + +void ro_gui_cert_preinitialise(void); +void ro_gui_cert_postinitialise(void); +void ro_gui_cert_open(struct tree *tree, struct node *node); + +#endif + diff --git a/riscos/textselection.c b/riscos/textselection.c index 659169741..369346ca0 100644 --- a/riscos/textselection.c +++ b/riscos/textselection.c @@ -183,7 +183,8 @@ void ro_gui_selection_drag_end(struct gui_window *g, wimp_dragged *drag) 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), + ro_gui_mouse_click_state(pointer.buttons, + wimp_BUTTON_CLICK_DRAG), pos.x, pos.y); } @@ -542,8 +543,8 @@ void ro_gui_selection_dragging(wimp_message *message) int box_x = 0; int box_y = 0; - /* with autoscrolling, we will probably need to remember the - * gui_window and override the drag->w window handle which + /* with autoscrolling, we will probably need to remember the + * gui_window and override the drag->w window handle which * could be any window on the desktop */ g = ro_gui_window_lookup(drag->w); @@ -566,14 +567,14 @@ void ro_gui_selection_dragging(wimp_message *message) html_get_box_tree(h)) { struct box *box = html_get_box_tree(h); - while ((box = box_at_point(box, pos.x, pos.y, + while ((box = box_at_point(box, pos.x, pos.y, &box_x, &box_y, &h))) { - if (box->style && - css_computed_visibility(box->style) == + if (box->style && + css_computed_visibility(box->style) == CSS_VISIBILITY_HIDDEN) continue; - if (box->gadget && + if (box->gadget && box->gadget->type == GADGET_TEXTAREA) { textarea = box; gadget_box_x = box_x; @@ -594,10 +595,10 @@ void ro_gui_selection_dragging(wimp_message *message) gui_window_set_pointer(g, GUI_POINTER_CARET); text_box = textarea_get_position(textarea, pos.x - gadget_box_x, - pos.y - gadget_box_y, + pos.y - gadget_box_y, &char_offset, &pixel_offset); - caret_set_position(&ghost_caret, bw, text_box, + caret_set_position(&ghost_caret, bw, text_box, char_offset, pixel_offset); drag_claimed = true; @@ -613,16 +614,16 @@ void ro_gui_selection_dragging(wimp_message *message) wimp_full_message_drag_claim claim; os_error *error; - claim.size = + claim.size = offsetof(wimp_full_message_drag_claim, file_types) + 8; claim.your_ref = drag->my_ref; claim.action = message_DRAG_CLAIM; - claim.flags = wimp_DRAG_CLAIM_POINTER_CHANGED | + claim.flags = wimp_DRAG_CLAIM_POINTER_CHANGED | wimp_DRAG_CLAIM_SUPPRESS_DRAGBOX; claim.file_types[0] = osfile_TYPE_TEXT; claim.file_types[1] = ~0; - error = xwimp_send_message(wimp_USER_MESSAGE, + error = xwimp_send_message(wimp_USER_MESSAGE, (wimp_message *) &claim, drag->sender); if (error) { LOG(("xwimp_send_message: 0x%x: %s", diff --git a/riscos/theme.c b/riscos/theme.c index 648399e9f..3f142cdd3 100644 --- a/riscos/theme.c +++ b/riscos/theme.c @@ -38,8 +38,11 @@ #include "oslib/wimpspriteop.h" #include "content/content.h" #include "desktop/gui.h" +#include "riscos/cookies.h" #include "riscos/dialog.h" +#include "riscos/global_history.h" #include "riscos/gui.h" +#include "riscos/hotlist.h" #include "riscos/menus.h" #include "riscos/options.h" #include "riscos/theme.h" @@ -585,9 +588,9 @@ bool ro_gui_theme_apply(struct theme_descriptor *descriptor) /* apply the theme to all the current windows */ ro_gui_window_update_theme(); - ro_gui_tree_update_theme(hotlist_tree); - ro_gui_tree_update_theme(global_history_tree); - ro_gui_tree_update_theme(cookies_tree); + ro_gui_cookies_update_theme(); + ro_gui_global_history_update_theme(); + ro_gui_hotlist_update_theme(); ro_gui_theme_close(theme_previous, false); return true; } @@ -944,14 +947,16 @@ bool ro_gui_theme_update_toolbar(struct theme_descriptor *descriptor, ro_gui_wimp_event_register_mouse_click(toolbar->toolbar_handle, ro_gui_toolbar_click); break; - case THEME_HOTLIST_TOOLBAR: - case THEME_HOTLIST_EDIT_TOOLBAR: - case THEME_HISTORY_TOOLBAR: - case THEME_HISTORY_EDIT_TOOLBAR: - case THEME_COOKIES_TOOLBAR: - case THEME_COOKIES_EDIT_TOOLBAR: - ro_gui_wimp_event_register_mouse_click(toolbar->toolbar_handle, - ro_gui_tree_toolbar_click); + case THEME_HOTLIST_TOOLBAR: + case THEME_HOTLIST_EDIT_TOOLBAR: + case THEME_HISTORY_TOOLBAR: + case THEME_HISTORY_EDIT_TOOLBAR: + case THEME_COOKIES_TOOLBAR: + case THEME_COOKIES_EDIT_TOOLBAR: + ro_gui_wimp_event_register_mouse_click(toolbar->toolbar_handle, + ro_gui_treeview_toolbar_click); + break; + default: break; } @@ -1322,6 +1327,7 @@ bool ro_gui_theme_process_toolbar(struct toolbar *toolbar, int width) xwimp_force_redraw(toolbar->parent_handle, 0, -16384, 16384, 16384); } + } /* Reformat the buttons starting with the throbber diff --git a/riscos/treeview.c b/riscos/treeview.c index ef23c5e3e..c992fdda7 100644 --- a/riscos/treeview.c +++ b/riscos/treeview.c @@ -1,5 +1,6 @@ /* * Copyright 2005 Richard Wilson + * Copyright 2010 Stephen Fryatt * * This file is part of NetSurf, http://www.netsurf-browser.org/ * @@ -20,6 +21,8 @@ * Generic tree handling (implementation). */ +#include + #include #include #include @@ -35,7 +38,9 @@ #include "content/urldb.h" #include "desktop/browser.h" #include "desktop/plotters.h" +#include "desktop/textinput.h" #include "desktop/tree.h" +#include "desktop/tree_url_node.h" #include "riscos/bitmap.h" #include "riscos/dialog.h" #include "riscos/gui.h" @@ -56,1379 +61,746 @@ #define wimp_KEY_END wimp_KEY_COPY #endif -#define TREE_EXPAND 0 -#define TREE_COLLAPSE 1 - - -static bool ro_gui_tree_initialise_sprite(const char *name, int number); -static void ro_gui_tree_launch_selected_node(struct tree *tree, struct node *node, bool all); -static bool ro_gui_tree_launch_node(struct tree *tree, struct node *node); -static void tree_handle_node_changed_callback(void *p); - - -/* an array of sprite addresses for Tinct */ -static char *ro_gui_tree_sprites[2]; - -/* origin adjustment */ -static int ro_gui_tree_origin_x; -static int ro_gui_tree_origin_y; - -/* element drawing */ -static wimp_icon ro_gui_tree_icon; -static char ro_gui_tree_icon_validation[24]; -static char ro_gui_tree_icon_null[] = ""; +/** \todo Ugh! */ +const char tree_directory_icon_name[] = "directory.png"; +const char tree_content_icon_name[] = "content.png"; -/* dragging information */ -static struct tree *ro_gui_tree_current_drag_tree; -static wimp_mouse_state ro_gui_tree_current_drag_buttons; - -/* editing information */ -static wimp_icon_create ro_gui_tree_edit_icon; - -/* dragging information */ -static char ro_gui_tree_drag_name[12]; - -/* callback update */ -struct node_update { - struct tree *tree; - struct node *node; -}; - - -/** - * Performs any initialisation for tree rendering - */ -bool ro_gui_tree_initialise(void) +struct ro_treeview { - if (ro_gui_tree_initialise_sprite("expand", TREE_EXPAND) || - ro_gui_tree_initialise_sprite("collapse", TREE_COLLAPSE)) - return false; - - ro_gui_tree_edit_icon.icon.flags = wimp_ICON_TEXT | wimp_ICON_INDIRECTED | - wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_BORDER | - (wimp_COLOUR_WHITE << wimp_ICON_BG_COLOUR_SHIFT) | - (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) | - (wimp_BUTTON_WRITABLE << wimp_ICON_BUTTON_TYPE_SHIFT); - ro_gui_tree_edit_icon.icon.data.indirected_text.validation = - ro_gui_tree_icon_null; - ro_gui_tree_edit_icon.icon.data.indirected_text.size = 256; - - return true; -} + struct tree *tree; /*< Pointer to treeview tree block. */ + wimp_w w; /*< RO Window Handle for tree window. */ + struct toolbar *tb; /*< Pointer to toolbar block. */ + struct { + int x; /*< X origin of tree, to RO work area. */ + int y; /*< Y origin of tree, to RO work area. */ + } origin; + struct { + int x; /*< X dimension of the tree, in RO units. */ + int y; /*< Y dimension of the tree, in RO units. */ + } size; /* (Dimensions are 0 until set correctly). */ + struct { + int x; /*< X extent of the window, in RO units. */ + int y; /*< Y extent of the window, in RO units. */ + } extent; /* (Extents are 0 until set correctly). */ + struct { + int x; /*< X coordinate of drag start */ + int y; /*< Y coordinate of drag start */ + } drag_start; + bool drag; /*< True if there's a drag going on */ +}; +static void ro_treeview_redraw_request(int x, int y, int width, int height, + void *pw); +static void ro_treeview_resized(struct tree *tree, int width, int height, + void *pw); +static void ro_treeview_scroll_visible(int y, int height, void *pw); +static void ro_treeview_get_window_dimensions(int *width, int *height, + void *pw); + +static void ro_treeview_redraw(wimp_draw *redraw); +static void ro_treeview_redraw_loop(wimp_draw *redraw, ro_treeview *tv, + osbool more); +static void ro_treeview_open(wimp_open *open); +static bool ro_treeview_mouse_click(wimp_pointer *pointer); +static bool ro_treeview_keypress(wimp_key *key); + +static void ro_treeview_set_window_extent(ro_treeview *tv, + int width, int height); + +static const struct treeview_table ro_tree_callbacks = { + ro_treeview_redraw_request, + ro_treeview_resized, + ro_treeview_scroll_visible, + ro_treeview_get_window_dimensions +}; /** - * Initialise a sprite for use with Tinct + * 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 flags The treeview flags. * - * \param name the name of the sprite - * \param number the sprite cache number - * \return whether an error occurred during initialisation + * \return The RISC OS treeview pointer. */ -bool ro_gui_tree_initialise_sprite(const char *name, int number) -{ - char icon_name[12]; - const char *icon = icon_name; - os_error *error; - - snprintf(icon_name, sizeof(icon_name), "tr_%s", name); - - error = xosspriteop_select_sprite(osspriteop_USER_AREA, gui_sprites, - (osspriteop_id) icon, - (osspriteop_header **) &ro_gui_tree_sprites[number]); - if (error) { - warn_user("MiscError", error->errmess); - LOG(("Failed to find sprite 'tr_%s'", name)); - return true; - } - return false; -} +ro_treeview *ro_treeview_create(wimp_w window, struct toolbar *toolbar, + unsigned int flags) +{ + ro_treeview *tv; + /* Claim memory for the treeview block, and create a tree. */ -/** - * Informs the current window manager that an area requires updating. - * - * \param tree the tree that is requesting a redraw - * \param x the x co-ordinate of the redraw area - * \param y the y co-ordinate of the redraw area - * \param width the width of the redraw area - * \param height the height of the redraw area - */ -void tree_redraw_area(struct tree *tree, int x, int y, int width, int height) -{ - os_error *error; + tv = malloc(sizeof(ro_treeview)); + if (tv == NULL) + return NULL; - assert(tree); - assert(tree->handle); + tv->w = window; + tv->tb = toolbar; - if (tree->toolbar) - y += ro_gui_theme_toolbar_height(tree->toolbar); - error = xwimp_force_redraw((wimp_w)tree->handle, tree->offset_x + x - 2, - -tree->offset_y - y - height, tree->offset_x + x + width + 4, - -tree->offset_y - y); - if (error) { - LOG(("xwimp_force_redraw: 0x%x: %s", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); + tv->tree = tree_create(flags, &ro_tree_callbacks, tv); + if (tv->tree == NULL) { + free(tv); + return NULL; } -} + /* Set the tree redraw origin at a default 0,0 RO units. */ -/** - * Draws a line. - * - * \param tree the tree to draw a line for - * \param x the x co-ordinate - * \param x the y co-ordinate - * \param x the width of the line - * \param x the height of the line - */ -void tree_draw_line(int x, int y, int width, int height) -{ - os_error *error; - int y0, y1; + tv->origin.x = 0; + tv->origin.y = 0; - /* stop the 16-bit co-ordinate system from causing redraw errors */ - y1 = ro_gui_tree_origin_y - y; - if (y1 < 0) - return; - y0 = y1 - height; - if (y0 > 16384) - return; - if (y0 < 0) - y0 = 0; - if (y1 > 16384) - y1 = 16384; + /* Set the tree size as 0,0 to indicate that we don't know. */ - error = xcolourtrans_set_gcol((os_colour)0x88888800, 0, os_ACTION_OVERWRITE, - 0, 0); - if (error) { - LOG(("xcolourtrans_set_gcol: 0x%x: %s", - error->errnum, error->errmess)); - warn_user("MiscError", error->errmess); - return; - } - error = xos_plot(os_MOVE_TO, ro_gui_tree_origin_x + x, y0); - if (!error) - xos_plot(os_PLOT_TO, ro_gui_tree_origin_x + x + width, y1); - if (error) { - LOG(("xos_plot: 0x%x: %s", - error->errnum, error->errmess)); - warn_user("MiscError", error->errmess); - return; - } -} + tv->size.x = 0; + tv->size.y = 0; + /* Set the tree window extent to 0,0, to indicate that we + * don't know. */ -/** - * Draws an element, including any expansion icons - * - * \param tree the tree to draw an element for - * \param element the element to draw - */ -void tree_draw_node_element(struct tree *tree, struct node_element *element) -{ - os_error *error; - int toolbar_height = 0; - struct node_element *url_element; - const struct bitmap *bitmap = NULL; - struct node_update *update; - const uint8_t *frame; - rufl_code code; - int x0, y0, x1, y1; - bool selected = false; - colour bg, c; - - assert(tree); - assert(element); - assert(element->parent); - - if (tree->toolbar) - toolbar_height = ro_gui_theme_toolbar_height(tree->toolbar); - - x0 = ro_gui_tree_origin_x + element->box.x; - x1 = x0 + element->box.width; - y1 = ro_gui_tree_origin_y - element->box.y; - y0 = y1 - element->box.height; - if (&element->parent->data == element) - if (element->parent->selected) - selected = true; - - - switch (element->type) { - case NODE_ELEMENT_TEXT_PLUS_SPRITE: - assert(element->sprite); - - ro_gui_tree_icon.flags = wimp_ICON_INDIRECTED | wimp_ICON_VCENTRED; - if (selected) - ro_gui_tree_icon.flags |= wimp_ICON_SELECTED; - ro_gui_tree_icon.extent.x0 = tree->offset_x + element->box.x; - ro_gui_tree_icon.extent.y1 = -tree->offset_y - element->box.y - - toolbar_height; - ro_gui_tree_icon.extent.x1 = ro_gui_tree_icon.extent.x0 + - NODE_INSTEP; - ro_gui_tree_icon.extent.y0 = -tree->offset_y - element->box.y - - element->box.height - toolbar_height; - ro_gui_tree_icon.flags |= wimp_ICON_TEXT | wimp_ICON_SPRITE; - ro_gui_tree_icon.data.indirected_text_and_sprite.text = - ro_gui_tree_icon_null; - ro_gui_tree_icon.data.indirected_text_and_sprite.validation = - ro_gui_tree_icon_validation; - ro_gui_tree_icon.data.indirected_text_and_sprite.size = 1; - if (element->parent->expanded) { - sprintf(ro_gui_tree_icon_validation, "S%s", - element->sprite->expanded_name); - } else { - sprintf(ro_gui_tree_icon_validation, "S%s", - element->sprite->name); - } - error = xwimp_plot_icon(&ro_gui_tree_icon); - if (error) { - LOG(("xwimp_plot_icon: 0x%x: %s", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); - } - x0 += NODE_INSTEP; + tv->extent.x = 0; + tv->extent.y = 0; - /* fall through */ - case NODE_ELEMENT_TEXT: - assert(element->text); + /* Set that there is no drag opperation at the moment */ - if (element == tree->editing) - return; + tv->drag = false; - if (ro_gui_tree_icon.flags & wimp_ICON_SELECTED) - ro_gui_tree_icon.flags |= wimp_ICON_FILLED; - if (selected) { - error = xcolourtrans_set_gcol((os_colour)0x00000000, 0, - os_ACTION_OVERWRITE, 0, 0); - if (error) { - LOG(("xcolourtrans_set_gcol: 0x%x: %s", - error->errnum, error->errmess)); - warn_user("MiscError", error->errmess); - return; - } - error = xos_plot(os_MOVE_TO, x0, y0); - if (!error) - error = xos_plot(os_PLOT_RECTANGLE | os_PLOT_TO, x1-1, y1-1); - if (error) { - LOG(("xos_plot: 0x%x: %s", - error->errnum, error->errmess)); - warn_user("MiscError", error->errmess); - return; - } - bg = 0x0000000; - c = 0x00eeeeee; - } else { - bg = 0x00ffffff; - c = 0x00000000; - } - error = xcolourtrans_set_font_colours(font_CURRENT, - bg << 8, c << 8, 14, 0, 0, 0); - if (error) { - LOG(("xcolourtrans_set_font_colours: 0x%x: %s", - error->errnum, error->errmess)); - return; - } - code = rufl_paint(ro_gui_desktop_font_family, ro_gui_desktop_font_style, - ro_gui_desktop_font_size, - element->text, strlen(element->text), - x0 + 8, y0 + 10, - rufl_BLEND_FONT); - if (code != rufl_OK) { - if (code == rufl_FONT_MANAGER_ERROR) - LOG(("rufl_paint: rufl_FONT_MANAGER_ERROR: 0x%x: %s", - rufl_fm_error->errnum, - rufl_fm_error->errmess)); - else - LOG(("rufl_paint: 0x%x", code)); - } - break; - case NODE_ELEMENT_THUMBNAIL: - url_element = tree_find_element(element->parent, TREE_ELEMENT_URL); - if (url_element) - bitmap = urldb_get_thumbnail(url_element->text); - if (bitmap) { - frame = bitmap_get_buffer((struct bitmap *) bitmap); - if (!frame) - urldb_set_thumbnail(url_element->text, NULL); - if ((!frame) || (element->box.width == 0)) { - update = calloc(sizeof(struct node_update), 1); - if (!update) - return; - update->tree = tree; - update->node = element->parent; - schedule(0, tree_handle_node_changed_callback, - update); - return; - } - image_redraw(bitmap->sprite_area, - ro_gui_tree_origin_x + element->box.x + 2, - ro_gui_tree_origin_y - element->box.y, - bitmap->width, bitmap->height, - bitmap->width, bitmap->height, - 0xffffff, - false, false, false, - IMAGE_PLOT_TINCT_OPAQUE); - if (!tree->no_furniture) { - tree_draw_line(element->box.x, - element->box.y, - element->box.width - 1, - 0); - tree_draw_line(element->box.x, - element->box.y, - 0, - element->box.height - 3); - tree_draw_line(element->box.x, - element->box.y + element->box.height - 3, - element->box.width - 1, - 0); - tree_draw_line(element->box.x + element->box.width - 1, - element->box.y, - 0, - element->box.height - 3); - } - } - break; - } -} + /* Register wimp events to handle the supplied window. */ + ro_gui_wimp_event_register_redraw_window(tv->w, ro_treeview_redraw); + ro_gui_wimp_event_register_open_window(tv->w, ro_treeview_open); + ro_gui_wimp_event_register_mouse_click(tv->w, ro_treeview_mouse_click); + ro_gui_wimp_event_register_keypress(tv->w, ro_treeview_keypress); + ro_gui_wimp_event_set_user_data(tv->w, tv); -void tree_handle_node_changed_callback(void *p) -{ - struct node_update *update = p; + /* \todo Register wimp events to handle the supplied toolbar? */ - tree_handle_node_changed(update->tree, update->node, true, false); - free(update); + return tv; } - /** - * Draws an elements expansion icon + * Delete a RISC OS GUI implementation of a treeview tree. The window is + * *not* destroyed -- this must be done by the caller. * - * \param tree the tree to draw the expansion for - * \param element the element to draw the expansion for + * \param tv The RISC OS treeview to delete. */ -void tree_draw_node_expansion(struct tree *tree, struct node *node) -{ - unsigned int type; - assert(tree); - assert(node); +void ro_treeview_destroy(ro_treeview *tv) +{ + ro_gui_wimp_event_finalise(tv->w); - if ((node->child) || (node->data.next)) { - if (node->expanded) { - type = TREE_COLLAPSE; - } else { - type = TREE_EXPAND; - } - _swix(Tinct_Plot, _IN(2) | _IN(3) | _IN(4) | _IN(7), - ro_gui_tree_sprites[type], - ro_gui_tree_origin_x + node->box.x - - (NODE_INSTEP / 2) - 8, - ro_gui_tree_origin_y - node->box.y - - (TREE_TEXT_HEIGHT / 2) - 8, - tinct_BILINEAR_FILTER); + tree_delete(tv->tree); - } + free(tv); } - /** - * Sets the origin variables to the correct values for a specified tree + * Change the redraw origin of a treeview tree in RISC OS graphics units. * - * \param tree the tree to set the origin for + * \param *tv The ro_treeview object to update. + * \param x The X position, in terms of the RO window work area. + * \param y The Y position, in terms of the RO window work area. + * + * \todo -- this probably needs a rework. */ -void tree_initialise_redraw(struct tree *tree) -{ - os_error *error; - wimp_window_state state; - assert(tree->handle); - - state.w = (wimp_w)tree->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); +void ro_treeview_set_origin(ro_treeview *tv, int x, int y) +{ + if (tv != NULL) { + tv->origin.x = x; + tv->origin.y = y; + + /* Assuming that we know how big the tree currently is, then + * adjust the window work area extent to match. If we don't, + * then presumably the tree isn't in an open window yet and + * a subsequent Open Window Event should pick it up. + */ + + if (tv->size.x != 0 && tv->size.y != 0) + ro_treeview_set_window_extent(tv, + tv->origin.x + tv->size.x, + tv->origin.y + tv->size.y); } - - ro_gui_tree_origin_x = state.visible.x0 - state.xscroll + tree->offset_x; - ro_gui_tree_origin_y = state.visible.y1 - state.yscroll - tree->offset_y; - if (tree->toolbar) - ro_gui_tree_origin_y -= ro_gui_theme_toolbar_height(tree->toolbar); } - /** - * Recalculates the dimensions of a node element. + * Return details of the tree block associated with an ro_treeview object. * - * \param element the element to recalculate + * \param *tv The ro_treeview object of interest. + * \return A pointer to the associated tree block. */ -void tree_recalculate_node_element(struct node_element *element) + +struct tree *ro_treeview_get_tree(ro_treeview *tv) { - const struct bitmap *bitmap = NULL; - struct node_element *url_element; - rufl_code code; - - assert(element); - - switch (element->type) { - case NODE_ELEMENT_TEXT_PLUS_SPRITE: - assert(element->sprite); - case NODE_ELEMENT_TEXT: - assert(element->text); - code = rufl_width(ro_gui_desktop_font_family, ro_gui_desktop_font_style, - ro_gui_desktop_font_size, - element->text, strlen(element->text), - &element->box.width); - if (code != rufl_OK) { - if (code == rufl_FONT_MANAGER_ERROR) - LOG(("rufl_width: rufl_FONT_MANAGER_ERROR: 0x%x: %s", - rufl_fm_error->errnum, - rufl_fm_error->errmess)); - else - LOG(("rufl_width: 0x%x", code)); - } - element->box.width += 16; - element->box.height = TREE_TEXT_HEIGHT; - if (element->type == NODE_ELEMENT_TEXT_PLUS_SPRITE) - element->box.width += NODE_INSTEP; - break; - case NODE_ELEMENT_THUMBNAIL: - url_element = tree_find_element(element->parent, TREE_ELEMENT_URL); - if (url_element) - bitmap = urldb_get_thumbnail(url_element->text); - if (bitmap) { -/* if ((bitmap->width == 0) && (bitmap->height == 0)) - frame = bitmap_get_buffer(bitmap); - element->box.width = bitmap->width * 2 + 2; - element->box.height = bitmap->height * 2 + 4; -*/ element->box.width = THUMBNAIL_WIDTH * 2 + 2; - element->box.height = THUMBNAIL_HEIGHT * 2 + 4; - } else { - element->box.width = 0; - element->box.height = 0; - } - } + return (tv != NULL) ? (tv->tree) : (NULL); } - /** - * Sets a node element as having a specific sprite. + * Return details of the RISC OS window handle associated with an + * ro_treeview object. * - * \param node the node to update - * \param sprite the sprite to use - * \param selected the expanded sprite name to use + * \param *tv The ro_treeview object of interest. + * \return The associated RISC OS window handle. */ -void tree_set_node_sprite(struct node *node, const char *sprite, - const char *expanded) + +wimp_w ro_treeview_get_window(ro_treeview *tv) { - assert(node); - assert(sprite); - assert(expanded); - - node->data.sprite = calloc(sizeof(struct node_sprite), 1); - if (!node->data.sprite) return; - node->data.type = NODE_ELEMENT_TEXT_PLUS_SPRITE; - node->data.sprite->area = (osspriteop_area *)1; - sprintf(node->data.sprite->name, sprite); - sprintf(node->data.sprite->expanded_name, expanded); + return (tv != NULL) ? (tv->w) : (NULL); } - /** - * Sets a node element as having a folder sprite + * Return an indication of whether the supplied treeview object contains a + * selection. * - * \param node the node to update + * \param *tv The ro_treeview object of interest. + * \return true if there is a selection in the tree; else false. */ -void tree_set_node_sprite_folder(struct node *node) -{ - assert(node->folder); - tree_set_node_sprite(node, "small_dir", "small_diro"); +bool ro_treeview_has_selection(ro_treeview *tv) +{ + if (tv != NULL) + return tree_node_has_selection(tree_get_root(tv->tree)); + else + return false; } - /** - * Updates the node details for a URL node. - * The internal node dimensions are not updated. + * Callback to force a redraw of part of the treeview window. * - * \param node the node to update - * \param url the URL - * \param data the data the node is linked to, or NULL for unlinked data + * \param x Min X Coordinate of area to be redrawn. + * \param y Min Y Coordinate of area to be redrawn. + * \param width Width of area to be redrawn. + * \param height Height of area to be redrawn. + * \param pw The treeview object to be redrawn. */ -void tree_update_URL_node(struct node *node, - const char *url, const struct url_data *data) + +void ro_treeview_redraw_request(int x, int y, int width, int height, + void *pw) { - struct node_element *element; - char buffer[256]; + if (pw != NULL) { + ro_treeview *tv = (ro_treeview *) pw; + os_error *error; + wimp_draw update; + osbool more; - assert(node); + /* The scale can't be changed; it's always 1:1. */ - element = tree_find_element(node, TREE_ELEMENT_URL); - if (!element) - return; - if (data) { - /* node is linked, update */ - assert(!node->editable); - if (!data->title) - urldb_set_url_title(url, url); + plot = ro_plotters; + ro_plot_set_scale(1.0); - if (!data->title) - return; + update.w = tv->w; + update.box.x0 = (2 * x) + tv->origin.x; + update.box.y0 = (-2 * (y + height)) + tv->origin.y; + update.box.x1 = (2 * (x + width)) + tv->origin.x; + update.box.y1 = (-2 * y) + tv->origin.y; - node->data.text = data->title; - } else { - /* node is not linked, find data */ - assert(node->editable); - data = urldb_get_url_data(element->text); - if (!data) + error = xwimp_update_window(&update, &more); + if (error) { + LOG(("xwimp_update_window: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); return; - } - - if (element) { - sprintf(buffer, "small_%.3x", ro_content_filetype_from_type(data->type)); - if (ro_gui_wimp_sprite_exists(buffer)) - tree_set_node_sprite(node, buffer, buffer); - else - tree_set_node_sprite(node, "small_xxx", "small_xxx"); - } - - element = tree_find_element(node, TREE_ELEMENT_LAST_VISIT); - if (element) { - snprintf(buffer, 256, messages_get("TreeLast"), - (data->last_visit > 0) ? - ctime((time_t *)&data->last_visit) : - messages_get("TreeUnknown")); - if (data->last_visit > 0) - buffer[strlen(buffer) - 1] = '\0'; - free((void *)element->text); - element->text = strdup(buffer); - } - - element = tree_find_element(node, TREE_ELEMENT_VISITS); - if (element) { - snprintf(buffer, 256, messages_get("TreeVisits"), - data->visits); - free((void *)element->text); - element->text = strdup(buffer); + } + ro_treeview_redraw_loop(&update, tv, more); } } - - /** - * Updates the tree owner following a tree resize + * Pass RISC OS redraw events on to the treeview widget. * - * \param tree the tree to update the owner of + * \param *redraw Pointer to Redraw Event block. */ -void tree_resized(struct tree *tree) + +void ro_treeview_redraw(wimp_draw *redraw) { - os_error *error; - wimp_window_state state; + osbool more; + os_error *error; + ro_treeview *tv; + + tv = (ro_treeview *) ro_gui_wimp_event_get_user_data(redraw->w); + if (tv == NULL) { + LOG(("NULL treeview block for window: 0x%x", + (unsigned int) redraw->w)); + /* Don't return, as not servicing redraw events isn't a good + * idea. The following code must handle (tv == NULL) + * gracefully while clearing the redraw queue. + */ + } - assert(tree->handle); + /* The scale can't be changed; it's always 1:1. */ + plot = ro_plotters; + ro_plot_set_scale(1.0); - state.w = (wimp_w)tree->handle; - error = xwimp_get_window_state(&state); + error = xwimp_redraw_window(redraw, &more); if (error) { - LOG(("xwimp_get_window_state: 0x%x: %s", + LOG(("xwimp_redraw_window: 0x%x: %s", error->errnum, error->errmess)); warn_user("WimpError", error->errmess); return; } - if (state.flags & wimp_WINDOW_OPEN) - ro_gui_tree_open(PTR_WIMP_OPEN(&state)); -} + ro_treeview_redraw_loop(redraw, tv, more); +} /** - * Redraws a tree window + * Redraw a treeview window, once the initial readraw block has been collected. * - * \param redraw the area to redraw - * \param tree the tree to redraw + * /param *redraw Pointer to redraw block. + * /param *tv The treeview object being redrawn. + * /param more Flag to show if more actions are required. */ -void ro_gui_tree_redraw(wimp_draw *redraw) -{ - struct tree *tree; - osbool more; - int clip_x0, clip_x1, clip_y0, clip_y1, origin_x, origin_y; - - tree = (struct tree *)ro_gui_wimp_event_get_user_data(redraw->w); - assert(tree); +void ro_treeview_redraw_loop(wimp_draw *redraw, ro_treeview *tv, osbool more) +{ + os_error *error; - more = wimp_redraw_window(redraw); while (more) { - clip_x0 = redraw->clip.x0; - clip_y0 = redraw->clip.y0; - clip_x1 = redraw->clip.x1; - clip_y1 = redraw->clip.y1; - origin_x = redraw->box.x0 - redraw->xscroll; - origin_y = redraw->box.y1 - redraw->yscroll; - if (tree->toolbar) - origin_y -= ro_gui_theme_toolbar_height(tree->toolbar); - tree_draw(tree, clip_x0 - origin_x - tree->offset_x, - origin_y - clip_y1 - tree->offset_y, - clip_x1 - clip_x0, clip_y1 - clip_y0); - more = wimp_get_rectangle(redraw); + ro_plot_origin_x = redraw->box.x0 - redraw->xscroll; + ro_plot_origin_y = redraw->box.y1 - redraw->yscroll; + + if (tv != NULL && tv->tree != NULL) { + tree_draw(tv->tree, tv->origin.x/2, -(tv->origin.y/2), + (redraw->clip.x0 + -(ro_plot_origin_x+tv->origin.x))/2, + ((ro_plot_origin_y+tv->origin.y) + -redraw->clip.y1)/2, + (redraw->clip.x1 - redraw->clip.x0)/2, + (redraw->clip.y1 - redraw->clip.y0)/2); + } + + error = xwimp_get_rectangle(redraw, &more); + if (error) { + LOG(("xwimp_redraw_window: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return; + } } } - /** - * Handles a mouse click for a tree + * Callback to notify us of a new overall tree size. * - * \param pointer the pointer state - * \param tree the tree to handle a click for - * \return whether the click was handled + * \param tree The tree being resized. + * \param width The new width of the window. + * \param height The new height of the window. + * \param *pw The treeview object to be resized. */ -bool ro_gui_tree_click(wimp_pointer *pointer, struct tree *tree) -{ - bool furniture; - struct node *node; - struct node *last; - struct node_element *element; - int x, y; - int alt_pressed = 0; - wimp_window_state state; - wimp_caret caret; - wimp_drag drag; - wimp_auto_scroll_info scroll; - os_error *error; - os_box box = { pointer->pos.x - 34, pointer->pos.y - 34, - pointer->pos.x + 34, pointer->pos.y + 34 }; - - assert(tree); - assert(tree->root); - - /* gain the input focus when required */ - state.w = (wimp_w)tree->handle; - error = xwimp_get_window_state(&state); - if (error) - LOG(("xwimp_get_window_state: 0x%x: %s", - error->errnum, error->errmess)); - error = xwimp_get_caret_position(&caret); - if (error) - LOG(("xwimp_get_caret_position: 0x%x: %s", - error->errnum, error->errmess)); - if (((pointer->buttons == (wimp_CLICK_SELECT << 8)) || - (pointer->buttons == (wimp_CLICK_ADJUST << 8))) && - (caret.w != state.w)) { - error = xwimp_set_caret_position((wimp_w)tree->handle, -1, -100, - -100, 32, -1); - if (error) - LOG(("xwimp_set_caret_position: 0x%x: %s", - error->errnum, error->errmess)); - } - - if (!tree->root->child) - return true; - - tree_initialise_redraw(tree); - x = pointer->pos.x - ro_gui_tree_origin_x; - y = ro_gui_tree_origin_y - pointer->pos.y; - element = tree_get_node_element_at(tree->root->child, x, y, &furniture); +void ro_treeview_resized(struct tree *tree, int width, int height, + void *pw) +{ + if (pw != NULL) { + ro_treeview *tv = (ro_treeview *) pw; - /* stop editing for anything but a drag */ - if ((tree->editing) && (pointer->i != tree->edit_handle) && - (pointer->buttons != (wimp_CLICK_SELECT << 4))) - ro_gui_tree_stop_edit(tree); + /* Store the width and height in terms of RISC OS work area. */ - /* handle a menu click */ - if (pointer->buttons == wimp_CLICK_MENU) { - if ((!element) || (!tree->root->child) || - (tree_has_selection(tree->root->child))) - return true; + tv->size.x = width * 2; + tv->size.y = -(height * 2); - node = element->parent; - tree->temp_selection = node; - node->selected = true; - tree_handle_node_element_changed(tree, &node->data); - return true; + /* Resize the window. */ + ro_treeview_set_window_extent(tv, tv->size.x, tv->size.y); } +} - /* no item either means cancel selection on (select) click or a drag */ - if (!element) { - if (tree->single_selection) { - tree_set_node_selected(tree, tree->root->child, false); - return true; - } - if ((pointer->buttons == (wimp_CLICK_SELECT << 4)) || - (pointer->buttons == (wimp_CLICK_SELECT << 8))) - tree_set_node_selected(tree, tree->root->child, false); - if ((pointer->buttons == (wimp_CLICK_SELECT << 4)) || - (pointer->buttons == (wimp_CLICK_ADJUST << 4))) { - - scroll.w = (wimp_w)tree->handle; - scroll.pause_zone_sizes.y0 = 80; - scroll.pause_zone_sizes.y1 = 80; - if (tree->toolbar) - scroll.pause_zone_sizes.y1 += - ro_gui_theme_toolbar_height(tree->toolbar); - scroll.pause_duration = 0; - scroll.state_change = (void *)0; - error = xwimp_auto_scroll(wimp_AUTO_SCROLL_ENABLE_VERTICAL, - &scroll, 0); - if (error) - LOG(("xwimp_auto_scroll: 0x%x: %s", - error->errnum, error->errmess)); - - gui_current_drag_type = GUI_DRAG_TREE_SELECT; - ro_gui_tree_current_drag_tree = tree; - ro_gui_tree_current_drag_buttons = pointer->buttons; - - drag.w = (wimp_w)tree->handle; - drag.type = wimp_DRAG_USER_RUBBER; - drag.initial.x0 = pointer->pos.x; - drag.initial.x1 = pointer->pos.x; - drag.initial.y0 = pointer->pos.y; - drag.initial.y1 = pointer->pos.y; - drag.bbox.x0 = state.visible.x0; - drag.bbox.x1 = state.visible.x1; - drag.bbox.y0 = -16384;//state.visible.y0; - drag.bbox.y1 = 16384;//state.visible.y1 - tree->offset_y; - error = xwimp_drag_box_with_flags(&drag, - wimp_DRAG_BOX_KEEP_IN_LINE | - wimp_DRAG_BOX_CLIP); - if (error) - LOG(("xwimp_drag_box_with_flags: 0x%x: %s", - error->errnum, error->errmess)); +/** + * Callback to request that a section of the tree is scrolled into view. + * + * \param y The Y coordinate of top of the area in NS units. + * \param height The height of the area in NS units. + * \param *pw The treeview object affected. + */ +void ro_treeview_scroll_visible(int y, int height, void *pw) +{ + if (pw != NULL) { + ro_treeview *tv = (ro_treeview *) pw; + os_error *error; + wimp_window_state state; + int visible_t, visible_b; + int request_t, request_b; + + state.w = tv->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; } - return true; - } - node = element->parent; - - /* click on furniture or double click on folder toggles node expansion */ - if (((furniture) && ((pointer->buttons == wimp_CLICK_SELECT << 8) || - (pointer->buttons == wimp_CLICK_ADJUST << 8) || - (pointer->buttons == wimp_CLICK_SELECT) || - (pointer->buttons == wimp_CLICK_ADJUST))) || - ((!furniture) && (node->child) && - ((pointer->buttons == wimp_CLICK_SELECT) || - (pointer->buttons == wimp_CLICK_ADJUST)))) { - node->expanded = !node->expanded; - if (!furniture) - node->selected = false; - tree_handle_node_changed(tree, node, false, true); - - /* find the last child node if expanded */ - last = node; - if ((last->child) && (last->expanded)) { - last = last->child; - while ((last->next) || ((last->child) && (last->expanded))) { - if (last->next) - last = last->next; - else - last = last->child; - } - } - /* scroll to the bottom element then back to the top */ - element = &last->data; - if (last->expanded) - for (; element->next; element = element->next); - ro_gui_tree_scroll_visible(tree, element); - ro_gui_tree_scroll_visible(tree, &node->data); - return true; - } + /* Work out top and bottom of both the currently visible and + * the required areas, in terms of the RO work area. + */ - /* no use for any other furniture click */ - if (furniture) - return true; - - /* single/double alt+click starts editing */ - if ((node->editable) && (!tree->editing) && - ((element->data == TREE_ELEMENT_URL) || - (element->data == TREE_ELEMENT_TITLE)) && - ((pointer->buttons == wimp_CLICK_SELECT) || - (pointer->buttons == (wimp_CLICK_SELECT << 8)))) { - xosbyte1(osbyte_SCAN_KEYBOARD, 2 ^ 0x80, 0, &alt_pressed); - if (alt_pressed == 0xff) { - ro_gui_tree_start_edit(tree, element, pointer); - return true; - } - } + visible_t = state.yscroll; + visible_b = state.yscroll + - (state.visible.y1 - state.visible.y0); - /* double click starts launches the leaf */ - if ((pointer->buttons == wimp_CLICK_SELECT) || - (pointer->buttons == wimp_CLICK_ADJUST)) { - if (!ro_gui_tree_launch_node(tree, node)) - return false; - if (pointer->buttons == wimp_CLICK_ADJUST) - ro_gui_dialog_close((wimp_w)tree->handle); - return true; - } + request_t = -(2 * y);// - tv->origin.y; + request_b = -(2 * (y + height));// - tv->origin.y; - /* single click (select) cancels current selection and selects item */ - if ((pointer->buttons == (wimp_CLICK_SELECT << 8)) || - ((pointer->buttons == (wimp_CLICK_ADJUST << 8)) && - (tree->single_selection))) { - if (!node->selected) { - tree_set_node_selected(tree, tree->root->child, false); - node->selected = true; - tree_handle_node_element_changed(tree, &node->data); - } - return true; - } + /* If the area is outside the visible window, then scroll it + * in to view. + */ - /* single click (adjust) toggles item selection */ - if (pointer->buttons == (wimp_CLICK_ADJUST << 8)) { - node->selected = !node->selected; - tree_handle_node_element_changed(tree, &node->data); - return true; - } + if (request_t > visible_t || request_b < visible_b) { + if (request_t > visible_t) { + state.yscroll = request_t; + } else if (request_b < visible_b) { + state.yscroll = request_b + tv->origin.y + + (state.visible.y1 - state.visible.y0); - /* drag starts a drag operation */ - if ((!tree->editing) && ((pointer->buttons == (wimp_CLICK_SELECT << 4)) || - (pointer->buttons == (wimp_CLICK_ADJUST << 4)))) { - if (tree->no_drag) - return true; + /* If the required area is bigger than the + * visible extent, then align to the top and + * let the bottom disappear out of view. + */ - if (!node->selected) { - node->selected = true; - tree_handle_node_element_changed(tree, &node->data); - } + if (state.yscroll < request_t) + state.yscroll = request_t; + } - scroll.w = (wimp_w)tree->handle; - scroll.pause_zone_sizes.y0 = 80; - scroll.pause_zone_sizes.y1 = 80; - if (tree->toolbar) - scroll.pause_zone_sizes.y1 += - ro_gui_theme_toolbar_height(tree->toolbar); - scroll.pause_duration = -1; - scroll.state_change = (void *)0; - error = xwimp_auto_scroll(wimp_AUTO_SCROLL_ENABLE_VERTICAL, - &scroll, 0); - if (error) - LOG(("xwimp_auto_scroll: 0x%x: %s", - error->errnum, error->errmess)); - - gui_current_drag_type = GUI_DRAG_TREE_MOVE; - ro_gui_tree_current_drag_tree = tree; - ro_gui_tree_current_drag_buttons = pointer->buttons; - - node = tree_get_selected_node(tree->root); - if (node) { - if (node->folder) { - if ((node->expanded) && - (ro_gui_wimp_sprite_exists("directoryo"))) - sprintf(ro_gui_tree_drag_name, "directoryo"); - else - sprintf(ro_gui_tree_drag_name, "directory"); - } else { - /* small_xxx -> file_xxx */ - sprintf(ro_gui_tree_drag_name, "file_%s", - node->data.sprite->name + 6); - if (!ro_gui_wimp_sprite_exists(ro_gui_tree_drag_name)) - sprintf(ro_gui_tree_drag_name, "file_xxx"); + error = xwimp_open_window((wimp_open *) &state); + if (error) { + LOG(("xwimp_open_window: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return; } - } else { - sprintf(ro_gui_tree_drag_name, "package"); } - - error = xdragasprite_start(dragasprite_HPOS_CENTRE | - dragasprite_VPOS_CENTRE | - dragasprite_BOUND_POINTER | - dragasprite_DROP_SHADOW, - (osspriteop_area *) 1, - ro_gui_tree_drag_name, &box, 0); - if (error) - LOG(("xdragasprite_start: 0x%x: %s", - error->errnum, error->errmess)); - return true; } - - - return false; } - /** - * Handles a menu closed event + * Callback to return the tree window dimensions to the treeview system. * - * \param tree the tree to handle the event for + * \param *width Return the window width. + * \param *height Return the window height. + * \param *pw The treeview object to use. */ -void ro_gui_tree_menu_closed(struct tree *tree) + +void ro_treeview_get_window_dimensions(int *width, int *height, + void *pw) { - assert(tree); - - if (tree->temp_selection) { - tree->temp_selection->selected = false; - tree_handle_node_element_changed(tree, &tree->temp_selection->data); - tree->temp_selection = NULL; - ro_gui_menu_prepare_action((wimp_w)tree->handle, TREE_SELECTION, false); - ro_gui_menu_prepare_action((wimp_w)tree->handle, TREE_EXPAND_ALL, false); + if (pw != NULL && (width != NULL || height != NULL)) { + ro_treeview *tv = (ro_treeview *) pw; + os_error *error; + wimp_window_state state; + + state.w = tv->w; + error = xwimp_get_window_state(&state); + if (error) { + LOG(("xwimp_get_window_info_header_only: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return; + } + + if (width != NULL) + *width = (state.visible.x1 - state.visible.x0) / 2; + + if (height != NULL) + *height = (state.visible.y1 - state.visible.y0) / 2; } } - /** - * Respond to a mouse click for a tree (hotlist or history) toolbar + * Resize the RISC OS window extent of a treeview. * - * \param pointer the pointer state + * \param *tv The RISC OS treeview object to resize. + * \param width The new width of the work area, in RO units. + * \param height The new height of the work area, in RO units. */ -bool ro_gui_tree_toolbar_click(wimp_pointer* pointer) + +void ro_treeview_set_window_extent(ro_treeview *tv, int width, int height) { - struct node *node; + if (tv != NULL) { + os_error *error; + os_box extent; + wimp_window_state state; + int new_x, new_y; + int visible_x, visible_y; + int new_x_scroll, new_y_scroll; - struct toolbar *toolbar = - (struct toolbar *)ro_gui_wimp_event_get_user_data(pointer->w); - assert(toolbar); - struct tree *tree = - (struct tree *)ro_gui_wimp_event_get_user_data(toolbar->parent_handle); - assert(tree); + /* Calculate the new window extents, in RISC OS units. */ - ro_gui_tree_stop_edit(tree); + new_x = width + tv->origin.x; + new_y = height + tv->origin.y; - if (pointer->buttons == wimp_CLICK_MENU) { - ro_gui_menu_create(tree_toolbar_menu, pointer->pos.x, - pointer->pos.y, (wimp_w)tree->handle); - return true; - } + /* Get details of the existing window, and start to sanity + * check the new extents. + */ - if (tree->toolbar->editor) { - ro_gui_theme_toolbar_editor_click(tree->toolbar, pointer); - return true; - } + state.w = tv->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; + } - switch (pointer->i) { - case ICON_TOOLBAR_CREATE: - node = tree_create_folder_node(tree->root, - messages_get("TreeNewFolder")); - tree_redraw_area(tree, node->box.x - NODE_INSTEP, - 0, NODE_INSTEP, 16384); - tree_handle_node_changed(tree, node, false, true); - ro_gui_tree_start_edit(tree, &node->data, NULL); - break; - case ICON_TOOLBAR_OPEN: - tree_handle_expansion(tree, tree->root, - (pointer->buttons == wimp_CLICK_SELECT), - true, false); - break; - case ICON_TOOLBAR_EXPAND: - tree_handle_expansion(tree, tree->root, - (pointer->buttons == wimp_CLICK_SELECT), - false, true); - break; - case ICON_TOOLBAR_DELETE: - ro_gui_menu_handle_action((wimp_w)tree->handle, - TREE_SELECTION_DELETE, false); - break; - case ICON_TOOLBAR_LAUNCH: - ro_gui_menu_handle_action((wimp_w)tree->handle, - TREE_SELECTION_LAUNCH, false); - break; - } - return true; -} + /* If the extent is smaller than the current visible area, + * then extend it so that it matches the visible area. + */ + if (new_x < (state.visible.x1 - state.visible.x0)) + new_x = state.visible.x1 - state.visible.x0; -/** - * Starts an editing session - * - * \param tree the tree to start editing for - * \param element the element to edit - * \param pointer the pointer data to use for caret positioning (or NULL) - */ -void ro_gui_tree_start_edit(struct tree *tree, struct node_element *element, - wimp_pointer *pointer) -{ - os_error *error; - struct node *parent; - int toolbar_height = 0; - - assert(tree); - assert(element); - - if (tree->editing) - ro_gui_tree_stop_edit(tree); - if (tree->toolbar) - toolbar_height = ro_gui_theme_toolbar_height(tree->toolbar); - - parent = element->parent; - if (&parent->data == element) - parent = parent->parent; - for (; parent; parent = parent->parent) { - if (!parent->expanded) { - parent->expanded = true; - tree_handle_node_changed(tree, parent, false, true); - } - } + if (new_y > (state.visible.y0 - state.visible.y1)) + new_y = state.visible.y0 - state.visible.y1; - tree->editing = element; - ro_gui_tree_edit_icon.w = (wimp_w)tree->handle; - ro_gui_tree_edit_icon.icon.extent.x0 = tree->offset_x + element->box.x - 2; - ro_gui_tree_edit_icon.icon.extent.x1 = tree->offset_x + - element->box.x + element->box.width + 2; - ro_gui_tree_edit_icon.icon.extent.y1 = -tree->offset_y - toolbar_height - - element->box.y; - ro_gui_tree_edit_icon.icon.extent.y0 = -tree->offset_y - toolbar_height - - element->box.y - element->box.height; - if (element->type == NODE_ELEMENT_TEXT_PLUS_SPRITE) - ro_gui_tree_edit_icon.icon.extent.x0 += NODE_INSTEP; - ro_gui_tree_edit_icon.icon.data.indirected_text.text = - (char *) element->text; - error = xwimp_create_icon(&ro_gui_tree_edit_icon, - (wimp_i *)&tree->edit_handle); - if (error) - LOG(("xwimp_create_icon: 0x%x: %s", - error->errnum, error->errmess)); + /* Calculate the maximum visible coordinates of the existing + * window. + */ - tree->textarea_handle = ro_textarea_create((wimp_w)tree->handle, - (wimp_i)tree->edit_handle, 0, ro_gui_desktop_font_family, - ro_gui_desktop_font_size, - ro_gui_desktop_font_style); - if (!tree->textarea_handle) { - ro_gui_tree_stop_edit(tree); - return; - } - ro_textarea_set_text(tree->textarea_handle, element->text); - if (pointer) - ro_textarea_set_caret_xy(tree->textarea_handle, - pointer->pos.x, pointer->pos.y); - else - ro_textarea_set_caret(tree->textarea_handle, - strlen(element->text)); + visible_x = state.xscroll + + (state.visible.x1 - state.visible.x0); + visible_y = state.yscroll + + (state.visible.y0 - state.visible.y1); - tree_handle_node_element_changed(tree, element); - ro_gui_tree_scroll_visible(tree, element); -} + /* If the window is currently open, and the exising visible + * area is bigger than the new extent, then we need to reopen + * the window in an appropriare position before setting the + * new extent. + */ + if ((state.flags & wimp_WINDOW_OPEN) && + (visible_x > new_x || visible_y < new_y)) { + new_x_scroll = state.xscroll; + new_y_scroll = state.yscroll; -/** - * Stops any current editing session - * - * \param tree the tree to stop editing for - */ -void ro_gui_tree_stop_edit(struct tree *tree) -{ - os_error *error; + if (visible_x > new_x) + new_x_scroll = new_x - (state.visible.x1 + - state.visible.x0); - assert(tree); + if (visible_y < new_y) + new_y_scroll = new_y - (state.visible.y0 + - state.visible.y1); - if (!tree->editing) return; + if (new_x_scroll < 0) { + state.visible.x1 -= new_x_scroll; + state.xscroll = 0; + } else { + state.xscroll = new_x_scroll; + } - if (tree->textarea_handle) { - ro_textarea_destroy(tree->textarea_handle); - tree->textarea_handle = 0; - } - error = xwimp_delete_icon((wimp_w)tree->handle, (wimp_i)tree->edit_handle); - if (error) - LOG(("xwimp_delete_icon: 0x%x: %s", - error->errnum, error->errmess)); - tree_handle_node_element_changed(tree, tree->editing); - tree->editing = NULL; - - error = xwimp_set_caret_position((wimp_w)tree->handle, -1, -100, - -100, 32, -1); - if (error) - LOG(("xwimp_set_caret_position: 0x%x: %s", - error->errnum, error->errmess)); - tree_recalculate_size(tree); -} + if (new_y_scroll > 0) { + state.visible.y0 += new_y_scroll; + state.yscroll = 0; + } else { + state.yscroll = new_y_scroll; + } + error = xwimp_open_window((wimp_open *) &state); + if (error) { + LOG(("xwimp_get_window_state: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return; + } -/** - * Scrolls the tree to make an element visible - * - * \param tree the tree to scroll - * \param element the element to display - */ -void ro_gui_tree_scroll_visible(struct tree *tree, struct node_element *element) -{ - wimp_window_state state; - int x0, x1, y0, y1; - os_error *error; - int toolbar_height = 0; + /* \todo -- Not sure if we need to reattach the + * toolbar here: the nested wimp seems to take care + * of it for us? + */ + } - assert(element); + /* Now that the new extent fits into the visible window, we + * can resize the work area. If we succeed, the values are + * recorded to save having to ask the Wimp for them + * each time. + */ - if (tree->toolbar) - toolbar_height = ro_gui_theme_toolbar_height(tree->toolbar); + extent.x0 = 0; + extent.y0 = new_y; + extent.x1 = new_x; + extent.y1 = 0; - state.w = (wimp_w)tree->handle; - error = xwimp_get_window_state(&state); - if (error) - LOG(("xwimp_get_window_state: 0x%x: %s", - error->errnum, error->errmess)); - if (!(state.flags & wimp_WINDOW_OPEN)) - return; - x0 = state.xscroll; - y0 = -state.yscroll; - x1 = x0 + state.visible.x1 - state.visible.x0 - tree->offset_x; - y1 = y0 - state.visible.y0 + state.visible.y1 - tree->offset_y - toolbar_height; - - state.yscroll = state.visible.y1 - state.visible.y0 - tree->offset_y - - toolbar_height - y1; - if ((element->box.y >= y0) && (element->box.y + element->box.height <= y1)) - return; - if (element->box.y < y0) - state.yscroll = -element->box.y; - if (element->box.y + element->box.height > y1) - state.yscroll = state.visible.y1 - state.visible.y0 - - tree->offset_y - toolbar_height - - (element->box.y + element->box.height); - ro_gui_tree_open(PTR_WIMP_OPEN(&state)); -} + error = xwimp_set_extent(tv->w, &extent); + if (error) { + LOG(("xwimp_set_extent: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return; + } + tv->extent.x = new_x; + tv->extent.y = new_y; + } +} /** - * Shows the a tree window. + * Handle RISC OS Window Open events for a treeview window. + * + * \param *open Pointer to the Window Open Event block. */ -void ro_gui_tree_show(struct tree *tree) + +static void ro_treeview_open(wimp_open *open) { - struct toolbar *toolbar; - - /* we may have failed to initialise */ - if (!tree) return; - toolbar = tree->toolbar; - - /* handle first time opening */ - if (!ro_gui_dialog_open_top((wimp_w)tree->handle, toolbar, 600, 800)) { - 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_treeview *tv; + os_error *error; + os_box extent; + int width, height; + + tv = (ro_treeview *) ro_gui_wimp_event_get_user_data(open->w); + if (tv == NULL) { + LOG(("NULL treeview block for window: ox%x", + (unsigned int) open->w)); + return; } - /* set the caret position */ - xwimp_set_caret_position((wimp_w)tree->handle, -1, -100, -100, 32, -1); -} + /* Calculate the window work area. It must be at least the same as + * the current visible area of the window, and needs to contain the + * tree as defined by size.x + offset.x and size.y + offset.y (note + * that the offset.y should be set to cover any toolbar, so we can + * ignore the size of that). + */ + width = open->visible.x1 - open->visible.x0; + height = open->visible.y0 - open->visible.y1; -/** - * Handles a window open request - * - * \param open the window state - */ -void ro_gui_tree_open(wimp_open *open) -{ - struct tree *tree; - os_error *error; - int width; - int height; - int toolbar_height = 0; - bool vscroll; + if (tv->size.x != 0 && width < (tv->origin.x + tv->size.x)) + width = (tv->origin.x + tv->size.x); - tree = (struct tree *)ro_gui_wimp_event_get_user_data(open->w); + if (tv->size.y != 0 && height > (tv->size.y + tv->origin.y)) + height = (tv->size.y + tv->origin.y); - if (!tree) - return; - if (tree->toolbar) - toolbar_height = ro_gui_theme_toolbar_height(tree->toolbar); + if (width != tv->extent.x || height != tv->extent.y) { + extent.x0 = 0; + extent.y0 = height; + extent.x1 = width; + extent.y1 = 0; - width = open->visible.x1 - open->visible.x0; - if (width < (tree->offset_x + tree->width)) - width = tree->offset_x + tree->width; - height = open->visible.y1 - open->visible.y0; - if (height < (tree->offset_y + toolbar_height + tree->height)) - height = tree->offset_y + toolbar_height + tree->height; - - if ((height != tree->window_height) || (width != tree->window_width)) { - os_box extent = { 0, -height, width, 0}; - error = xwimp_set_extent((wimp_w)tree->handle, &extent); + error = xwimp_set_extent(tv->w, &extent); if (error) { LOG(("xwimp_set_extent: 0x%x: %s", error->errnum, error->errmess)); warn_user("WimpError", error->errmess); + return; } - /* hide the scroll bar? */ - if ((tree->no_vscroll) && (height != tree->window_height)) { - vscroll = (tree->height > height); - if (ro_gui_wimp_check_window_furniture(open->w, - wimp_WINDOW_VSCROLL) != vscroll) { - ro_gui_wimp_update_window_furniture(open->w, - 0, wimp_WINDOW_VSCROLL); - if (vscroll) - open->visible.x1 -= ro_get_vscroll_width(open->w); - else - open->visible.x1 += ro_get_vscroll_width(open->w); - } - } - - tree->window_width = width; - tree->window_height = height; + tv->extent.x = width; + tv->extent.y = height; } + /* \todo -- Might need to add vertical scrollbar hiding back in here? */ + error = xwimp_open_window(open); if (error) { LOG(("xwimp_open_window: 0x%x: %s", error->errnum, error->errmess)); warn_user("WimpError", error->errmess); } - if (tree->toolbar) - ro_gui_theme_process_toolbar(tree->toolbar, -1); - ro_gui_menu_prepare_action((wimp_w)tree->handle, TREE_SELECTION, false); - ro_gui_menu_prepare_action((wimp_w)tree->handle, TREE_EXPAND_ALL, false); + + if (tv->tb) + ro_gui_theme_process_toolbar(tv->tb, -1); } /** - * Handles a keypress for a tree + * Pass RISC OS Mouse Click events on to the treeview widget. * - * \param key the key pressed - * \param tree the tree to handle a keypress for - * \return whether the key was processed + * \param *pointer Pointer to the Mouse Click Event block. + * \return Return true if click handled; else false. */ -bool ro_gui_tree_keypress(wimp_key *key) + +static bool ro_treeview_mouse_click(wimp_pointer *pointer) { - wimp_window_state state; - int y; - char *new_string; - struct tree *tree; - int strlen; - os_error *error; - - tree = (struct tree *)ro_gui_wimp_event_get_user_data(key->w); - if (!tree) + os_error *error; + ro_treeview *tv; + wimp_window_state state; + int xpos, ypos; + browser_mouse_state mouse; + + tv = (ro_treeview *) ro_gui_wimp_event_get_user_data(pointer->w); + if (tv == NULL) { + LOG(("NULL treeview block for window: 0x%x", + (unsigned int) pointer->w)); return false; - - /* Handle basic keys - */ - switch (key->c) { - case 1: /* CTRL+A */ - ro_gui_menu_handle_action((wimp_w)tree->handle, - TREE_SELECT_ALL, false); - return true; - case 24: /* CTRL+X */ - ro_gui_menu_handle_action((wimp_w)tree->handle, - TREE_SELECTION_DELETE, false); - return true; - case 26: /* CTRL+Z */ - ro_gui_menu_handle_action((wimp_w)tree->handle, - TREE_CLEAR_SELECTION, false); - return true; - case wimp_KEY_RETURN: - if ((tree->editing) && (tree->textarea_handle)) { - strlen = ro_textarea_get_text( - tree->textarea_handle, - NULL, 0); - if (strlen == -1) { - ro_gui_tree_stop_edit(tree); - return true; - } - new_string = malloc(strlen); - if (!new_string) { - ro_gui_tree_stop_edit(tree); - LOG(("No memory for malloc()")); - warn_user("NoMemory", 0); - return true; - } - ro_textarea_get_text(tree->textarea_handle, - new_string, strlen); - free((void *)tree->editing->text); - tree->editing->text = new_string; - ro_gui_tree_stop_edit(tree); - tree_recalculate_size(tree); - } else { - ro_gui_tree_launch_selected(tree); - } - return true; - case wimp_KEY_ESCAPE: - if (tree->editing) { - ro_gui_tree_stop_edit(tree); - } else { - /* \todo cancel drags etc. */ - } - return true; - - 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 IS_WIMP_KEY | 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: - break; - default: - return false; } - /* keyboard scrolling */ - state.w = (wimp_w)tree->handle; + state.w = tv->w; error = xwimp_get_window_state(&state); if (error) { LOG(("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess)); - return true; + warn_user("WimpError", error->errmess); + return false; } - y = state.visible.y1 - state.visible.y0 - TREE_TEXT_HEIGHT; - if (tree->toolbar) - y -= ro_gui_theme_toolbar_full_height(tree->toolbar); + /* Convert the returned mouse coordinates into NetSurf's internal + * units. + */ - switch (key->c) { - case IS_WIMP_KEY | wimp_KEY_UP: -/* if ((state.yscroll % TREE_TEXT_HEIGHT) != 0) - state.yscroll -= (state.yscroll % TREE_TEXT_HEIGHT); - else -*/ state.yscroll += TREE_TEXT_HEIGHT; - break; - case IS_WIMP_KEY | wimp_KEY_DOWN: -/* if (((state.yscroll + y) % TREE_TEXT_HEIGHT) != 0) - state.yscroll -= ((state.yscroll + y) % TREE_TEXT_HEIGHT); - else -*/ state.yscroll -= TREE_TEXT_HEIGHT; - break; - case IS_WIMP_KEY | wimp_KEY_PAGE_UP: - state.yscroll += y; - break; - case IS_WIMP_KEY | wimp_KEY_PAGE_DOWN: - state.yscroll -= y; - break; - case IS_WIMP_KEY | wimp_KEY_HOME: - case IS_WIMP_KEY | wimp_KEY_CONTROL | wimp_KEY_UP: - state.yscroll = 0x10000000; - break; - case IS_WIMP_KEY | wimp_KEY_END: - case IS_WIMP_KEY | wimp_KEY_CONTROL | wimp_KEY_DOWN: - state.yscroll = -0x10000000; - break; - } + xpos = ((pointer->pos.x - state.visible.x0) + + state.xscroll - tv->origin.x) / 2; + ypos = ((state.visible.y1 - pointer->pos.y) - + state.yscroll + tv->origin.y) / 2; - error = xwimp_open_window(PTR_WIMP_OPEN(&state)); - if (error) { - LOG(("xwimp_open_window: 0x%x: %s", - error->errnum, error->errmess)); + /* Start to process the mouse click. + * + * Select and Adjust are processed normally. To get filer-like operation + * with selections, Menu clicks are passed to the treeview first as + * Select if there are no selected nodes in the tree. + */ + + mouse = 0; + + if (pointer->buttons == wimp_CLICK_MENU) { + if (!tree_node_has_selection(tree_get_root(tv->tree))) + mouse |= BROWSER_MOUSE_CLICK_1; + } else { + mouse = ro_gui_mouse_click_state(pointer->buttons, + wimp_BUTTON_DOUBLE_CLICK_DRAG); + + /* Record drag start */ + if (mouse & (BROWSER_MOUSE_DRAG_1 | BROWSER_MOUSE_DRAG_2)) { + tv->drag_start.x = xpos; + tv->drag_start.y = ypos; + tv->drag = true; + } + + if (mouse & (BROWSER_MOUSE_CLICK_1 | BROWSER_MOUSE_MOD_2)) + xwimp_set_caret_position(tv->w, -1, -100, -100, 32, -1); } + if (mouse != 0) + tree_mouse_action(tv->tree, mouse, xpos, ypos); + + /* 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. + */ + + if (pointer->buttons == wimp_CLICK_MENU) + ro_gui_wimp_event_process_window_menu_click(pointer); + return true; } - /** - * Handles the completion of a selection drag (GUI_DRAG_TREE_SELECT) + * Track the mouse under Null Polls from the wimp, to support dragging. * - * \param drag the drag box information + * \param w Window handle currently under the mouse. + * \param *pointer Pointer to a Wimp Pointer block. */ -void ro_gui_tree_selection_drag_end(wimp_dragged *drag) + +void ro_treeview_mouse_at(wimp_w w, wimp_pointer *pointer) { - wimp_window_state state; - wimp_auto_scroll_info scroll; - os_error *error; - int x0, y0, x1, y1; - int toolbar_height = 0; - - if (ro_gui_tree_current_drag_tree->toolbar) - toolbar_height = ro_gui_theme_toolbar_height( - ro_gui_tree_current_drag_tree->toolbar); - - scroll.w = (wimp_w)ro_gui_tree_current_drag_tree->handle; - error = xwimp_auto_scroll(0, &scroll, 0); - if (error) - LOG(("xwimp_auto_scroll: 0x%x: %s", error->errnum, error->errmess)); - - state.w = (wimp_w)ro_gui_tree_current_drag_tree->handle; + os_error *error; + ro_treeview *tv; + wimp_window_state state; + int xpos, ypos; + browser_mouse_state mouse; + + tv = (ro_treeview *) ro_gui_wimp_event_get_user_data(pointer->w); + if (tv == NULL) { + LOG(("NULL treeview block for window: 0x%x", + (unsigned int) pointer->w)); + return; + } + + state.w = tv->w; error = xwimp_get_window_state(&state); if (error) { LOG(("xwimp_get_window_state: 0x%x: %s", @@ -1437,177 +809,177 @@ void ro_gui_tree_selection_drag_end(wimp_dragged *drag) return; } - x0 = drag->final.x0 - state.visible.x0 - state.xscroll + - ro_gui_tree_current_drag_tree->offset_x; - y0 = state.visible.y1 - state.yscroll - drag->final.y0 - - ro_gui_tree_current_drag_tree->offset_y - toolbar_height; - x1 = drag->final.x1 - state.visible.x0 - state.xscroll + - ro_gui_tree_current_drag_tree->offset_x; - y1 = state.visible.y1 - state.yscroll - drag->final.y1 - - ro_gui_tree_current_drag_tree->offset_y - toolbar_height; - tree_handle_selection_area(ro_gui_tree_current_drag_tree, x0, y0, - x1 - x0, y1 - y0, - (ro_gui_tree_current_drag_buttons == (wimp_CLICK_ADJUST << 4))); - ro_gui_menu_prepare_action((wimp_w)ro_gui_tree_current_drag_tree->handle, - TREE_SELECTION, false); - ro_gui_menu_prepare_action((wimp_w)ro_gui_tree_current_drag_tree->handle, - TREE_EXPAND_ALL, false); -} + /* Convert the returned mouse coordinates into NetSurf's internal + * units. + */ + xpos = ((pointer->pos.x - state.visible.x0) + + state.xscroll - tv->origin.x) / 2; + ypos = ((state.visible.y1 - pointer->pos.y) - + state.yscroll + tv->origin.y) / 2; -/** - * Converts screen co-ordinates to tree ones - * - * \param tree the tree to calculate for - * \param x the screen x co-ordinate - * \param x the screen y co-ordinate - * \param tree_x updated to the tree x co-ordinate - * \param tree_y updated to the tree y co-ordinate - */ -void ro_gui_tree_get_tree_coordinates(struct tree *tree, int x, int y, - int *tree_x, int *tree_y) { - wimp_window_state state; - os_error *error; + /* Start to process the mouse click. */ + + mouse = 0; + + if (!(pointer->buttons & (wimp_CLICK_MENU))) { + mouse = ro_gui_mouse_drag_state(pointer->buttons, + wimp_BUTTON_DOUBLE_CLICK_DRAG); + if (mouse != 0) + tree_mouse_action(tv->tree, mouse, xpos, ypos); + + /* Check if drag ended and tell core */ + if (tv->drag && !(mouse & BROWSER_MOUSE_DRAG_ON)) { + tree_drag_end(tv->tree, mouse, tv->drag_start.x, + tv->drag_start.y, xpos, ypos); + tv->drag = false; + } - state.w = (wimp_w)tree->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; } - *tree_x = x - state.visible.x0 - state.xscroll + tree->offset_x; - *tree_y = state.visible.y1 - state.yscroll - y - tree->offset_y; - if (tree->toolbar) - *tree_y -= ro_gui_theme_toolbar_height(tree->toolbar); } - /** - * Handles the completion of a move drag (GUI_DRAG_TREE_MOVE) + * Pass RISC OS keypress events on to the treeview widget. * - * \param drag the drag box information + * \param *key Pointer to the Key Pressed Event block. + * \return Return true if keypress handled; else false. */ -void ro_gui_tree_move_drag_end(wimp_dragged *drag) + +static bool ro_treeview_keypress(wimp_key *key) { - struct gui_window *g; - wimp_pointer pointer; - wimp_auto_scroll_info scroll; - os_error *error; - struct node *node; - struct node *single; - struct node_element *element; - bool before; - int x, y; - - scroll.w = (wimp_w)ro_gui_tree_current_drag_tree->handle; - error = xwimp_auto_scroll(0, &scroll, 0); - if (error) - LOG(("xwimp_auto_scroll: 0x%x: %s", error->errnum, 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; + ro_treeview *tv; + uint32_t c; + + tv = (ro_treeview *) ro_gui_wimp_event_get_user_data(key->w); + if (tv == NULL) { + LOG(("NULL treeview block for window: 0x%x", + (unsigned int) key->w)); + return false; } - if (pointer.w != (wimp_w)ro_gui_tree_current_drag_tree->handle) { - /* try to drop into a browser window */ - single = tree_get_selected_node(ro_gui_tree_current_drag_tree->root->child); - element = tree_find_element(single, TREE_ELEMENT_URL); - if (!element) - return; - if (single) { - /* \todo:send datasave for element */ - g = ro_gui_window_lookup(pointer.w); - if (g) - browser_window_go(g->bw, element->text, 0, true); - return; - } else { - /* \todo:update save.c to handle multiple concurrent saves */ + c = (uint32_t) key->c; + + 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; + + default: + break; } - return; } - /* internal drag */ - if (!ro_gui_tree_current_drag_tree->movable) - return; - ro_gui_tree_get_tree_coordinates(ro_gui_tree_current_drag_tree, - drag->final.x0 + 34, drag->final.y0 + 34, &x, &y); - node = tree_get_link_details(ro_gui_tree_current_drag_tree, x, y, &before); - tree_move_selected_nodes(ro_gui_tree_current_drag_tree, node, before); -} + if (!(c & IS_WIMP_KEY)) { + if (tree_keypress(tv->tree, c)) + return true; + } + return false; +} -/** - * Launches all selected nodes. +/** Respond to a mouse click on a treeview toolbar. * - * \param tree the tree to launch all selected nodes for + * \param pointer Pointer to the MouseClick Event block. + * \return true if the event was handled; else false. */ -void ro_gui_tree_launch_selected(struct tree *tree) + +bool ro_gui_treeview_toolbar_click(wimp_pointer *pointer) { - assert(tree); + struct toolbar *tb; + ro_treeview *tv; - if (tree->root->child) - ro_gui_tree_launch_selected_node(tree, tree->root->child, false); -} + tb = (struct toolbar *) ro_gui_wimp_event_get_user_data(pointer->w); + if (tb == NULL) { + LOG(("NULL toolbar block for window: 0x%x", + (unsigned int) pointer->w)); + return false; + } + tv = (ro_treeview *) ro_gui_wimp_event_get_user_data(tb->parent_handle); + if (tv == NULL) { + LOG(("NULL treeview block for parent window: 0x%x", + (unsigned int) tb->parent_handle)); + return false; + } + + /* \todo -- Handle menu clicks here... */ + + /* \todo -- Deal with the editor here... */ + + switch (pointer->i) { -/** - * Launches all selected nodes. - * - * \param node the node to launch all selected nodes for - */ -void ro_gui_tree_launch_selected_node(struct tree *tree, struct node *node, - bool all) -{ - for (; node; node = node->next) { - if (((node->selected) || (all)) && (!node->folder)) - ro_gui_tree_launch_node(tree, node); - if ((node->child) && ((node->expanded) || (node->selected) | (all))) - ro_gui_tree_launch_selected_node(tree, node->child, - (node->selected) | (all)); } -} + return true; +} /** - * Launches a node using all known methods. + * Update a treeview to use a new theme. * - * \param node the node to launch - * \return whether the node could be launched + * \param *tv Pointer to the treeview to update. */ -bool ro_gui_tree_launch_node(struct tree *tree, struct node *node) + +void ro_treeview_update_theme(ro_treeview *tv) { - struct node_element *element; + if (tv != NULL && tv->tb != NULL){ + /* \todo -- Check for toolbar editing here. */ - assert(node); + if (!ro_gui_theme_update_toolbar(NULL, tv->tb)) { + ro_gui_theme_destroy_toolbar(tv->tb); + tv->tb = NULL; + } - element = tree_find_element(node, TREE_ELEMENT_URL); - if (element) { - browser_window_create(element->text, NULL, 0, true, false); - return true; - } + /* \todo -- Check for toolbar editing here. */ - element = tree_find_element(node, TREE_ELEMENT_SSL); - if (element) { - ro_gui_cert_open(tree, node); - return true; - } + ro_gui_theme_attach_toolbar(tv->tb, tv->w); + ro_treeview_set_origin(tv, 0, + -(ro_gui_theme_toolbar_height(tv->tb))); - return false; + xwimp_force_redraw(tv->w, 0, tv->extent.y, tv->extent.x, 0); + } } -int ro_gui_tree_help(int x, int y) -{ - return -1; -} -void ro_gui_tree_update_theme(struct tree *tree) -{ +#if 0 if ((tree) && (tree->toolbar)) { if (tree->toolbar->editor) if (!ro_gui_theme_update_toolbar(NULL, tree->toolbar->editor)) @@ -1621,4 +993,70 @@ void ro_gui_tree_update_theme(struct tree *tree) 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 + * position. + * + * Currently this is inimplemented. + * + * \param *message_data Pointer to the Wimp's help message block. + * \return Token value (-1 indicates no help available). + */ + +int ro_treeview_get_help(help_full_message_request *message_data) +{ + return -1; +} + +/** + * Convert a content type into an icon name. + * + * \todo -- Currently we don't have any icons apart from the default. + * + * \param *buffer A buffer to return the icon name + * \param type The content type to return an icon name for. + */ + +void tree_icon_name_from_content_type(char *buffer, content_type type) +{ + switch (type) { + case CONTENT_HTML: + case CONTENT_TEXTPLAIN: + case CONTENT_CSS: +#if defined(WITH_MNG) || defined(WITH_PNG) + case CONTENT_PNG: +#endif +#ifdef WITH_MNG + case CONTENT_JNG: + case CONTENT_MNG: +#endif +#ifdef WITH_JPEG + case CONTENT_JPEG: +#endif +#ifdef WITH_GIF + case CONTENT_GIF: +#endif +#ifdef WITH_BMP + case CONTENT_BMP: + case CONTENT_ICO: +#endif +#ifdef WITH_SPRITE + case CONTENT_SPRITE: +#endif +#ifdef WITH_DRAW + case CONTENT_DRAW: +#endif +#ifdef WITH_ARTWORKS + case CONTENT_ARTWORKS: +#endif +#ifdef WITH_NS_SVG + case CONTENT_SVG: +#endif + default: + sprintf(buffer, tree_content_icon_name); + break; + } } + diff --git a/riscos/treeview.h b/riscos/treeview.h index df718fc7a..7aa129e1b 100644 --- a/riscos/treeview.h +++ b/riscos/treeview.h @@ -1,5 +1,6 @@ /* * Copyright 2004 Richard Wilson + * Copyright 2010 Stephen Fryatt * * This file is part of NetSurf, http://www.netsurf-browser.org/ * @@ -24,38 +25,30 @@ #define _NETSURF_RISCOS_TREEVIEW_H_ #include -#include "oslib/osspriteop.h" -#include "oslib/wimp.h" +#include +#include + #include "desktop/tree.h" -#include "image/bitmap.h" -#define TREE_TEXT_HEIGHT 40 -#define TREE_SPRITE_WIDTH 40 /* text plus sprite entries only */ +typedef struct ro_treeview ro_treeview; -struct node_sprite { - osspriteop_area *area; - char name[12]; - char expanded_name[12]; +struct ro_treeview_table { + void (*open_menu)(wimp_pointer *pointer); }; -bool ro_gui_tree_initialise(void); -void ro_gui_tree_redraw(wimp_draw *redraw); -bool ro_gui_tree_click(wimp_pointer *pointer, struct tree *tree); -void ro_gui_tree_menu_closed(struct tree *tree); -bool ro_gui_tree_toolbar_click(wimp_pointer* pointer); -void ro_gui_tree_stop_edit(struct tree *tree); -void ro_gui_tree_open(wimp_open *open); -void ro_gui_tree_show(struct tree *tree); -bool ro_gui_tree_keypress(wimp_key *key); -void ro_gui_tree_selection_drag_end(wimp_dragged *drag); -void ro_gui_tree_move_drag_end(wimp_dragged *drag); -void ro_gui_tree_launch_selected(struct tree *tree); -void ro_gui_tree_start_edit(struct tree *tree, struct node_element *element, - wimp_pointer *pointer); -void ro_gui_tree_scroll_visible(struct tree *tree, struct node_element *element); -void ro_gui_tree_get_tree_coordinates(struct tree *tree, int x, int y, - int *tree_x, int *tree_y); -int ro_gui_tree_help(int x, int y); -void ro_gui_tree_update_theme(struct tree *tree); +ro_treeview *ro_treeview_create(wimp_w window, struct toolbar *toolbar, + unsigned int flags); +void ro_treeview_destroy(ro_treeview *tv); + +struct tree *ro_treeview_get_tree(ro_treeview *tv); +wimp_w ro_treeview_get_window(ro_treeview *tv); +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_w w, wimp_pointer *pointer); +bool ro_gui_treeview_toolbar_click(wimp_pointer *pointer); +void ro_treeview_update_theme(ro_treeview *tv); +int ro_treeview_get_help(help_full_message_request *message_data); #endif + diff --git a/riscos/url_complete.c b/riscos/url_complete.c index 580417a16..9649c5604 100644 --- a/riscos/url_complete.c +++ b/riscos/url_complete.c @@ -149,7 +149,7 @@ bool ro_gui_url_complete_keypress(struct gui_window *g, uint32_t key) if (url_complete_matches) { for (i = 0; i < MAXIMUM_VISIBLE_LINES; i++) { if (i < lines) { - url_complete_redraw[i] = + url_complete_redraw[i] = url_complete_matches[i]; } else { url_complete_redraw[i] = NULL; @@ -726,15 +726,13 @@ bool ro_gui_url_complete_click(wimp_pointer *pointer) ICON_TOOLBAR_URL, url_complete_matches[ url_complete_matches_selection], true); - global_history_add_recent(url_complete_matches[ - url_complete_matches_selection]); /** \todo The interaction of components here is hideous */ /* Do NOT make any attempt to use any of the global url * completion variables after this call to browser_window_go. * They will be invalidated by (at least): * + gui_window_set_url - * + destruction of (i)frames within the current page + * + destruction of (i)frames within the current page * Any attempt to use them will probably result in a crash. */ diff --git a/riscos/url_suggest.c b/riscos/url_suggest.c new file mode 100644 index 000000000..7a17c79a0 --- /dev/null +++ b/riscos/url_suggest.c @@ -0,0 +1,200 @@ +/* + * 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 + * URL Suggestion Menu (implementation). + */ + +#include +#include "oslib/wimp.h" +#include "content/content_type.h" +#include "content/urldb.h" +#include "riscos/menus.h" +#include "riscos/url_suggest.h" +#include "utils/messages.h" + +struct url_suggest_item { + const char *url; /*< The URL being stored. */ + unsigned int weight; /*< A weight assigned to the URL. */ + 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 wimp_menu *suggest_menu; +static int suggest_entries; +static time_t suggest_time; +static struct url_suggest_item *suggest_list; + +/** + * Initialise the URL suggestion menu. A menu block which must be set to + * contain URL_SUGGEST_MAX_URLS entries is passed in. + * + * /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) +{ + suggest_menu = menu; + + suggest_menu->title_data.indirected_text.text = + (char *) messages_get("URLSuggest"); + ro_gui_menu_init_structure((wimp_menu *) suggest_menu, + URL_SUGGEST_MAX_URLS); + + suggest_entries = 0; + + return true; +} + + +/** + * Builds the URL suggestion menu. This is called by ro_gui_menu_create() when + * it is asked to display the url_suggest_menu. + * + * /return true if the menu has entries; else false. + */ + +bool ro_gui_url_suggest_prepare_menu(void) +{ + int i; + struct url_suggest_item *list, *next; + + /* Fetch the URLs we want to include from URLdb. */ + + suggest_entries = 0; + suggest_list = NULL; + suggest_time = time(NULL); + + urldb_iterate_entries(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. + * Entries from the list are freed as we go. + */ + + assert(suggest_entries <= URL_SUGGEST_MAX_URLS); + + if (suggest_entries > 0) { + i = suggest_entries; + + list = suggest_list; + suggest_list = NULL; + + while (list != NULL && i > 0) { + i--; + + suggest_menu->entries[i].menu_flags = 0; + suggest_menu->entries[i].data.indirected_text.text = + (char *) list->url; + suggest_menu->entries[i].data.indirected_text.size = + strlen(list->url) + 1; + + next = list->next; + free(list); + list = next; + } + + /* If i hasn't reached 0, then something went wrong -- get + * out now! + */ + + if (i > 0) + return false; + + suggest_menu->entries[0].menu_flags |= + wimp_MENU_TITLE_INDIRECTED; + suggest_menu->entries[suggest_entries - 1].menu_flags |= + wimp_MENU_LAST; + + return true; + } + + return false; +} + + +/** + * Callback function for urldb_iterate_entries + * + * \param url URL which matches + * \param data Data associated with URL + * \return true to continue iteration, false otherwise + */ + +bool url_suggest_callback(const char *url, const struct url_data *data) +{ + int count; + unsigned int weight; + struct url_suggest_item **list, *new, *old; + + /* Ignore unvisited URLs, and those that don't apply to HTML or Text. */ + + if (data->visits <= 0 ||(data->type != CONTENT_HTML && + data->type != CONTENT_TEXTPLAIN)) + return true; + + /* Calculate a weight for the URL. */ + + weight = (suggest_time - data->last_visit) / data->visits; + + /* Hunt through those URLs already found to see if we want to add + * this one. Smaller weights carry higher priority. + * + * The list is sorted into reverse order, so that lowest weight + * items are nearest the head. Therefore, items are dropped from + * the head, making things simpler. + */ + + list = &suggest_list; + count = 0; + + while (*list != NULL && weight < (*list)->weight) { + list = &((*list)->next); + count++; + } + + if (count > 0 || suggest_entries < URL_SUGGEST_MAX_URLS) { + new = (struct url_suggest_item *) + malloc(sizeof(struct url_suggest_item)); + + if (new != NULL) { + suggest_entries++; + new->url = url; + new->weight = weight; + new->next = *list; + + *list = new; + } + } + + /* If adding the URL gave us too many menu items, drop the lowest + * priority ones until the list is the right length again. + */ + + while (suggest_list != NULL && suggest_entries > URL_SUGGEST_MAX_URLS) { + old = suggest_list; + suggest_list = suggest_list->next; + free(old); + suggest_entries--; + } + + return true; +} + diff --git a/riscos/url_suggest.h b/riscos/url_suggest.h new file mode 100644 index 000000000..d13b7d89a --- /dev/null +++ b/riscos/url_suggest.h @@ -0,0 +1,34 @@ +/* + * 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 + * URL Suggestion Menu (interface). + */ + +#ifndef _NETSURF_RISCOS_URL_SUGGEST_H_ +#define _NETSURF_RISCOS_URL_SUGGEST_H_ + +#include "oslib/wimp.h" + +#define URL_SUGGEST_MAX_URLS 16 + +bool ro_gui_url_suggest_init(wimp_menu *menu); +bool ro_gui_url_suggest_prepare_menu(void); + +#endif + diff --git a/riscos/wimp_event.c b/riscos/wimp_event.c index 4d14b1f0a..5d1f725f4 100644 --- a/riscos/wimp_event.c +++ b/riscos/wimp_event.c @@ -1,5 +1,6 @@ /* * Copyright 2005 Richard Wilson + * Copyright 2010 Stephen Fryatt * * This file is part of NetSurf, http://www.netsurf-browser.org/ * @@ -95,6 +96,14 @@ struct event_window { void (*close_window)(wimp_w w); void (*redraw_window)(wimp_draw *redraw); void (*menu_selection)(wimp_w w, wimp_i i); + 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); const char *help_prefix; void *user_data; struct icon_event *first; @@ -345,14 +354,27 @@ void *ro_gui_wimp_event_get_user_data(wimp_w w) /** * Handles a menu selection event. * + * (At present, this is tied to being called from menus.c and relies on that + * module decoding the menu into an action code. If menus.c loses its + * menu handling in the future, such decoding might need to move here.) + * + * The order of execution is: + * + * 1. Try to match the menu to a pop-up menu. If successful, handle it as + * this. + * 2. Try to match the menu to a window menu. If successful, pass control to + * the menu's registered _select handler. + * 3. Return event as unhandled. + * * \param w the window to owning the menu * \param i the icon owning the menu * \param menu the menu that has been selected * \param selection the selection information - * \return true if the event was handled, false otherwise + * \param action the menu action info from menus.c + * \return true if the event was handled, false otherwise */ bool ro_gui_wimp_event_menu_selection(wimp_w w, wimp_i i, wimp_menu *menu, - wimp_selection *selection) + wimp_selection *selection, menu_action action) { struct event_window *window; struct icon_event *event; @@ -367,11 +389,28 @@ bool ro_gui_wimp_event_menu_selection(wimp_w w, wimp_i i, wimp_menu *menu, if (!window) 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. + */ + for (event = window->first; event; event = event->next) if ((event->type == EVENT_MENU_GRIGHT) && (event->i == i)) break; - if (!event) - return false; + if (!event) { + if ((window->window_menu) && (window->window_menu == menu) + && (window->window_menu_selection)) { + window->window_menu_selection(w, menu, + selection, action); + + /* Prepare the menu pending a possible Adjust click. */ + if (window->window_menu_prepare) + window->window_menu_prepare(w, menu); + return true; + } else { + return false; + } + } menu_entry = &menu->entries[selection->items[0]]; for (i = 1; selection->items[i] != -1; i++) @@ -433,10 +472,12 @@ bool ro_gui_wimp_event_menu_selection(wimp_w w, wimp_i i, wimp_menu *menu, * * The order of execution is: * - * 1. Any registered mouse_click routine (see ro_gui_wimp_register_mouse_click()) - * 2. If the current icon is not registered with a type then it is assumed that no + * 1. If a menu click, and the window has an automatic window menu, this is + * processed immediately. + * 2. Any registered mouse_click routine (see ro_gui_wimp_register_mouse_click()) + * 3. If the current icon is not registered with a type then it is assumed that no * action is necessary, and the click is deemed to have been handled. - * 3. If the registered mouse_click routine returned false, or there was no registered + * 4. If the registered mouse_click routine returned false, or there was no registered * routine then the automated action for the registered icon type is performed * * \param pointer the current pointer state @@ -458,7 +499,13 @@ bool ro_gui_wimp_event_mouse_click(wimp_pointer *pointer) if (!window) return false; - /* registered routines take priority */ + /* Menu clicks take priority if there is an auto menu defined. */ + if ((window->window_menu) && (window->window_menu_auto)) { + ro_gui_wimp_event_process_window_menu_click(pointer); + return true; + } + + /* registered routines take next priority */ if ((window->mouse_click) && (window->mouse_click(pointer))) return true; @@ -918,6 +965,32 @@ bool ro_gui_wimp_event_redraw_window(wimp_draw *redraw) } +/** + * Process a Menu click in a window, by checking for a registered window + * menu and opening it if one is found. + * + * \param *p The pointer block from the mouse click event. + * \return true if the click was actioned; else false. + */ + +bool ro_gui_wimp_event_process_window_menu_click(wimp_pointer *pointer) +{ + struct event_window *window; + + 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); + + ro_gui_menu_create(window->window_menu, + pointer->pos.x, pointer->pos.y, window->w); + return true; + } + return false; +} + /** * Register a numeric field to be automatically handled */ @@ -1168,9 +1241,39 @@ 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. + * + * \param + */ + +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) +{ + 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; + return true; +} + /** - * Finds the event data associated with a given window handle, or creates a new one. + * Finds the event data associated with a given window handle, or creates a + * new one. * * \param w the window to find data for */ @@ -1273,12 +1376,88 @@ struct icon_event *ro_gui_wimp_event_get_event(wimp_w w, wimp_i i, return event; } +/* Handle sumbenu warnings. This is called from ro_gui_menu_warning(), and + * returns to that function to have the submenu opened correctly. + * + * \param w the window to owning the menu + * \param i the icon owning the menu + * \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 + */ + +bool ro_gui_wimp_event_submenu_warning(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_selection *selection, menu_action action) +{ + struct event_window *window; + struct icon_event *event; + + 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. + */ + + window = ro_gui_wimp_event_find_window(w); + if (!window) + return false; + + for (event = window->first; event; event = event->next) + if ((event->type == EVENT_MENU_GRIGHT) && (event->i == i)) + break; + if (event) + 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); + return true; + } + } + + return false; +} + /** - * Handle menus being closed + * Handle menus being closed. This is called from ro_gui_menu_closed(), in + * every scenario when one of our own menus is open. + * + * \param w the window to owning the menu + * \param i the icon owning the menu + * \param menu the menu that has been selected */ -void ro_gui_wimp_event_menus_closed(void) + +void ro_gui_wimp_event_menus_closed(wimp_w w, wimp_i i, wimp_menu *menu) { - ro_gui_wimp_event_register_submenu(0); + struct event_window *window; + struct icon_event *event; + + 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. + */ + + window = ro_gui_wimp_event_find_window(w); + if (!window) + return; + + for (event = window->first; event; event = event->next) + if ((event->type == EVENT_MENU_GRIGHT) && (event->i == i)) + break; + if (event) + 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); } /** diff --git a/riscos/wimp_event.h b/riscos/wimp_event.h index e8ae7842f..54ae95ae5 100644 --- a/riscos/wimp_event.h +++ b/riscos/wimp_event.h @@ -1,5 +1,6 @@ /* * Copyright 2005 Richard Wilson + * Copyright 2010 Stephen Fryatt * * This file is part of NetSurf, http://www.netsurf-browser.org/ * @@ -30,7 +31,8 @@ #include #include #include "oslib/os.h" -#include "oslib/wimp.h" +#include "oslib/wimp.h" +#include "riscos/menus.h" #define IS_WIMP_KEY (1u<<31) @@ -45,12 +47,14 @@ bool ro_gui_wimp_event_set_user_data(wimp_w w, void *user); void *ro_gui_wimp_event_get_user_data(wimp_w w); bool ro_gui_wimp_event_menu_selection(wimp_w w, wimp_i i, wimp_menu *menu, - wimp_selection *selection); + wimp_selection *selection, menu_action action); 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_register_numeric_field(wimp_w w, wimp_i i, wimp_i up, wimp_i down, int min, int max, int stepping, @@ -78,8 +82,18 @@ bool ro_gui_wimp_event_register_redraw_window(wimp_w w, void (*callback)(wimp_draw *redraw)); 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); -void ro_gui_wimp_event_menus_closed(void); +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); #endif diff --git a/riscos/window.c b/riscos/window.c index 198563059..55bdb11d6 100644 --- a/riscos/window.c +++ b/riscos/window.c @@ -5,6 +5,7 @@ * Copyright 2004 Andrew Timmins * Copyright 2005 Richard Wilson * Copyright 2005 Adrian Lees + * Copyright 2010 Stephen Fryatt * * This file is part of NetSurf, http://www.netsurf-browser.org/ * @@ -150,7 +151,6 @@ 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 browser_mouse_state ro_gui_mouse_drag_state(wimp_mouse_state buttons); static bool ro_gui_window_import_text(struct gui_window *g, const char *filename, bool toolbar); @@ -398,7 +398,7 @@ struct gui_window *gui_create_browser_window(struct browser_window *bw, state.next = wimp_TOP; if (bw->parent) { top = browser_window_owner(bw); - error = xwimp_open_window_nested(PTR_WIMP_OPEN(&state), + error = xwimp_open_window_nested(PTR_WIMP_OPEN(&state), top->window->window, wimp_CHILD_LINKS_PARENT_WORK_AREA << wimp_CHILD_XORIGIN_SHIFT | @@ -1110,7 +1110,7 @@ void gui_window_stop_throbber(struct gui_window *g) * set favicon */ void gui_window_set_icon(struct gui_window *g, hlcache_handle *icon) -{ +{ } /** @@ -1688,7 +1688,6 @@ void ro_gui_window_launch_url(struct gui_window *g, const char *url) if (res == URL_FUNC_OK) { gui_window_set_url(g, url_norm); browser_window_go(g->bw, url_norm, 0, true); - global_history_add_recent(url_norm); free(url_norm); } } @@ -2124,7 +2123,8 @@ void ro_gui_window_mouse_at(struct gui_window *g, wimp_pointer *pointer) 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), + ro_gui_mouse_drag_state(pointer->buttons, + wimp_BUTTON_CLICK_DRAG), pos.x, pos.y); } @@ -2321,7 +2321,8 @@ bool ro_gui_window_click(wimp_pointer *pointer) } 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), + ro_gui_mouse_click_state(pointer->buttons, + wimp_BUTTON_CLICK_DRAG), pos.x, pos.y); } return true; @@ -3088,17 +3089,35 @@ void ro_gui_window_prepare_navigate_all(void) { /** * Returns the state of the mouse buttons and modifiers keys for a * click/release action, suitable for passing to the OS-independent - * browser window code + * browser window/ treeview/ etc code. + * + * \param buttons Wimp button state. + * \param type Wimp work-area/icon type for decoding. + * \return NetSurf core button state. */ -browser_mouse_state ro_gui_mouse_click_state(wimp_mouse_state buttons) +browser_mouse_state ro_gui_mouse_click_state(wimp_mouse_state buttons, + wimp_icon_flags type) { browser_mouse_state state = 0; - if (buttons & (wimp_CLICK_SELECT)) - state |= BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_CLICK_1; - if (buttons & (wimp_CLICK_ADJUST)) - state |= BROWSER_MOUSE_PRESS_2 | BROWSER_MOUSE_CLICK_2; + switch (type) { + case wimp_BUTTON_CLICK_DRAG: + if (buttons & (wimp_CLICK_SELECT)) + state |= BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_CLICK_1; + if (buttons & (wimp_CLICK_ADJUST)) + state |= BROWSER_MOUSE_PRESS_2 | BROWSER_MOUSE_CLICK_2; + break; + case wimp_BUTTON_DOUBLE_CLICK_DRAG: + if (buttons & (wimp_SINGLE_SELECT)) + state |= BROWSER_MOUSE_CLICK_1; + if (buttons & (wimp_SINGLE_ADJUST)) + state |= BROWSER_MOUSE_CLICK_2; + if (buttons & (wimp_DOUBLE_SELECT)) + state |= BROWSER_MOUSE_CLICK_1 | + BROWSER_MOUSE_DOUBLE_CLICK; + break; + } if (buttons & (wimp_DRAG_SELECT)) { state |= BROWSER_MOUSE_DRAG_1; @@ -3111,30 +3130,46 @@ browser_mouse_state ro_gui_mouse_click_state(wimp_mouse_state buttons) 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; } - /** * Returns the state of the mouse buttons and modifiers keys whilst - * dragging, for passing to the OS-independent browser window code + * 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. */ -browser_mouse_state ro_gui_mouse_drag_state(wimp_mouse_state buttons) +browser_mouse_state ro_gui_mouse_drag_state(wimp_mouse_state buttons, + wimp_icon_flags type) { browser_mouse_state state = 0; + switch (type) { + case wimp_BUTTON_CLICK_DRAG: + case wimp_BUTTON_DOUBLE_CLICK_DRAG: + if (buttons & (wimp_CLICK_SELECT)) + state |= BROWSER_MOUSE_HOLDING_1; + if (buttons & (wimp_CLICK_ADJUST)) + state |= BROWSER_MOUSE_HOLDING_2; - if (buttons & (wimp_CLICK_SELECT)) state |= BROWSER_MOUSE_HOLDING_1; - if (buttons & (wimp_CLICK_ADJUST)) state |= BROWSER_MOUSE_HOLDING_2; + if (!(buttons & (wimp_CLICK_SELECT) || + buttons & (wimp_CLICK_ADJUST))) + mouse_drag = false; + break; + } - if (!(buttons & (wimp_CLICK_SELECT) || buttons & (wimp_CLICK_ADJUST))) - mouse_drag = false; - if (mouse_drag) state |= BROWSER_MOUSE_DRAG_ON; + if (mouse_drag) + state |= BROWSER_MOUSE_DRAG_ON; 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; } @@ -3216,7 +3251,8 @@ void ro_gui_window_scroll_end(struct gui_window *g, wimp_dragged *drag) 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), + ro_gui_mouse_click_state(pointer.buttons, + wimp_BUTTON_CLICK_DRAG), pos.x, pos.y); } -- cgit v1.2.3