diff options
Diffstat (limited to 'frontends/riscos/search.c')
-rw-r--r-- | frontends/riscos/search.c | 475 |
1 files changed, 475 insertions, 0 deletions
diff --git a/frontends/riscos/search.c b/frontends/riscos/search.c new file mode 100644 index 000000000..989c9aa9e --- /dev/null +++ b/frontends/riscos/search.c @@ -0,0 +1,475 @@ +/* + * Copyright 2004 John M Bell <jmb202@ecs.soton.ac.uk> + * Copyright 2005 Adrian Lees <adrianl@users.sourceforge.net> + * + * 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 <http://www.gnu.org/licenses/>. + */ + +/** + * \file + * Free text search implementation + */ + +#include "utils/config.h" + +#include <ctype.h> +#include <string.h> +#include "oslib/hourglass.h" +#include "oslib/wimp.h" + +#include "utils/log.h" +#include "utils/messages.h" +#include "content/content.h" +#include "content/hlcache.h" +#include "desktop/browser.h" +#include "desktop/gui_search.h" +#include "desktop/browser.h" +#include "desktop/search.h" + +#include "riscos/gui.h" +#include "riscos/dialog.h" +#include "riscos/menus.h" +#include "riscos/wimp.h" +#include "riscos/wimp_event.h" + +#define RECENT_SEARCHES 8 + +struct search_static_data { + char *recent_searches[RECENT_SEARCHES]; + bool search_insert; + struct browser_window *search_window; +}; + +static struct search_static_data search_data = + { { NULL }, false, NULL }; + +static wimp_MENU(RECENT_SEARCHES) menu_recent; +wimp_menu *recent_search_menu = (wimp_menu *)&menu_recent; +#define DEFAULT_FLAGS (wimp_ICON_TEXT | wimp_ICON_FILLED | \ + (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) | \ + (wimp_COLOUR_WHITE << wimp_ICON_BG_COLOUR_SHIFT)) + + +static void ro_gui_search_end(wimp_w w); +static bool ro_gui_search_next(wimp_w w); +static bool ro_gui_search_menu_prepare(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_pointer *pointer); +static bool ro_gui_search_prepare_menu(void); +static bool ro_gui_search_click(wimp_pointer *pointer); +static bool ro_gui_search_keypress(wimp_key *key); +static search_flags_t ro_gui_search_update_flags(void); +static void ro_gui_search_set_forward_state(bool active, void *p); +static void ro_gui_search_set_back_state(bool active, void *p); +static void ro_gui_search_set_status(bool found, void *p); +static void ro_gui_search_set_hourglass(bool active, void *p); +static void ro_gui_search_add_recent(const char *string, void *p); + +static struct gui_search_table search_table = { + ro_gui_search_set_status, + ro_gui_search_set_hourglass, + ro_gui_search_add_recent, + ro_gui_search_set_forward_state, + ro_gui_search_set_back_state, +}; + +struct gui_search_table *riscos_search_table = &search_table; + +void ro_gui_search_init(void) +{ + dialog_search = ro_gui_dialog_create("search"); + ro_gui_wimp_event_register_keypress(dialog_search, + ro_gui_search_keypress); + ro_gui_wimp_event_register_close_window(dialog_search, + ro_gui_search_end); + ro_gui_wimp_event_register_menu_prepare(dialog_search, + ro_gui_search_menu_prepare); + ro_gui_wimp_event_register_menu_gright(dialog_search, + ICON_SEARCH_TEXT, ICON_SEARCH_MENU, + recent_search_menu); + ro_gui_wimp_event_register_text_field(dialog_search, + ICON_SEARCH_STATUS); + ro_gui_wimp_event_register_checkbox(dialog_search, + ICON_SEARCH_CASE_SENSITIVE); + ro_gui_wimp_event_register_mouse_click(dialog_search, + ro_gui_search_click); + ro_gui_wimp_event_register_ok(dialog_search, ICON_SEARCH_FIND_NEXT, + ro_gui_search_next); + ro_gui_wimp_event_register_cancel(dialog_search, ICON_SEARCH_CANCEL); + ro_gui_wimp_event_set_help_prefix(dialog_search, "HelpSearch"); + + recent_search_menu->title_data.indirected_text.text = + (char*)messages_get("Search"); + ro_gui_menu_init_structure(recent_search_menu, RECENT_SEARCHES); +} + +/** + * Wrapper for the pressing of an OK button for wimp_event. + * + * \return false, to indicate the window should not be closed + */ +bool ro_gui_search_next(wimp_w w) +{ + search_data.search_insert = true; + search_flags_t flags = SEARCH_FLAG_FORWARDS | + ro_gui_search_update_flags(); + browser_window_search(search_data.search_window, NULL, flags, + ro_gui_get_icon_string(dialog_search, + ICON_SEARCH_TEXT)); + return false; +} + + +/** + * Callback to prepare menus in the Search dialog. At present, this + * only has to handle the previous search pop-up. + * + * \param w The window handle owning the menu. + * \param i The icon handle owning the menu. + * \param *menu The menu to be prepared. + * \param *pointer The associated mouse click event block, or NULL + * on an Adjust-click re-opening. + * \return true if the event was handled; false if not. + */ + +bool ro_gui_search_menu_prepare(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_pointer *pointer) +{ + if (menu != recent_search_menu || i != ICON_SEARCH_MENU) + return false; + + if (pointer != NULL) + return ro_gui_search_prepare_menu(); + + return true; +} + + +bool ro_gui_search_click(wimp_pointer *pointer) +{ + search_flags_t flags; + switch (pointer->i) { + case ICON_SEARCH_FIND_PREV: + search_data.search_insert = true; + flags = ~SEARCH_FLAG_FORWARDS & + ro_gui_search_update_flags(); + browser_window_search(search_data.search_window, NULL, + flags, + ro_gui_get_icon_string(dialog_search, + ICON_SEARCH_TEXT)); + return true; + case ICON_SEARCH_CASE_SENSITIVE: + flags = SEARCH_FLAG_FORWARDS | + ro_gui_search_update_flags(); + browser_window_search_clear( + search_data.search_window); + browser_window_search(search_data.search_window, NULL, + flags, + ro_gui_get_icon_string(dialog_search, + ICON_SEARCH_TEXT)); + return true; + case ICON_SEARCH_SHOW_ALL: + flags = ro_gui_get_icon_selected_state( + pointer->w, pointer->i) ? + SEARCH_FLAG_SHOWALL : SEARCH_FLAG_NONE; + browser_window_search(search_data.search_window, NULL, + flags, + ro_gui_get_icon_string(dialog_search, + ICON_SEARCH_TEXT)); + return true; + } + return false; +} + +/** + * add search string to recent searches list + * + * front is at liberty how to implement the bare notification + * should normally store a strdup() of the string in + * search_global_data.recent[]; + * core gives no guarantee of the integrity of the const char * + * + * \param search string search pattern + * \param p the pointer sent to search_verify_new() + */ + +void ro_gui_search_add_recent(const char *search, void *p) +{ + char *tmp; + int i; + + if ((search == NULL) || (search[0] == '\0')) + return; + + if (!search_data.search_insert) { + free(search_data.recent_searches[0]); + search_data.recent_searches[0] = strdup(search); + ro_gui_search_prepare_menu(); + return; + } + + if ((search_data.recent_searches[0] != NULL) && + (!strcmp(search_data.recent_searches[0], search))) + return; + + tmp = strdup(search); + if (!tmp) { + ro_warn_user("NoMemory", 0); + return; + } + free(search_data.recent_searches[RECENT_SEARCHES - 1]); + for (i = RECENT_SEARCHES - 1; i > 0; i--) + search_data.recent_searches[i] = search_data.recent_searches[i - 1]; + search_data.recent_searches[0] = tmp; + search_data.search_insert = false; + + ro_gui_set_icon_shaded_state(dialog_search, ICON_SEARCH_MENU, false); + ro_gui_search_prepare_menu(); +} + +bool ro_gui_search_prepare_menu(void) +{ + int i; + int suggestions = 0; + + for (i = 0; i < RECENT_SEARCHES; i++) + if (search_data.recent_searches[i] != NULL) + suggestions++; + + if (suggestions == 0) + return false; + + for (i = 0; i < suggestions; i++) { + recent_search_menu->entries[i].menu_flags &= ~wimp_MENU_LAST; + recent_search_menu->entries[i].data.indirected_text.text = + search_data.recent_searches[i]; + recent_search_menu->entries[i].data.indirected_text.size = + strlen(search_data.recent_searches[i]) + 1; + } + recent_search_menu->entries[suggestions - 1].menu_flags |= + wimp_MENU_LAST; + + return true; +} + +/** + * Determine of the browser window is searchable. + * + * \param bw The browser window to check. + */ +static bool ro_gui_search_bw_searchable(struct browser_window *bw) +{ + hlcache_handle *h; + + assert(bw != NULL); + + h = browser_window_get_content(bw); + + /* only handle html/textplain contents */ + /** \todo Should have content_is_searchable() api */ + if ((!h) || (content_get_type(h) != CONTENT_HTML && + content_get_type(h) != CONTENT_TEXTPLAIN)) + return false; + + return true; +} + + +/** + * Open the search dialog + * + * \param bw the browser window to search + */ +void ro_gui_search_prepare(struct browser_window *bw) +{ + /* only handle searchable contents */ + if (!ro_gui_search_bw_searchable(bw)) + return; + + /* if the search dialogue is reopened over a new window, we may + need to cancel the previous search */ + ro_gui_search_set_forward_state(true, bw); + ro_gui_search_set_back_state(true, bw); + + search_data.search_window = bw; + + ro_gui_set_icon_string(dialog_search, ICON_SEARCH_TEXT, "", true); + ro_gui_set_icon_selected_state(dialog_search, + ICON_SEARCH_CASE_SENSITIVE, false); + ro_gui_set_icon_selected_state(dialog_search, + ICON_SEARCH_SHOW_ALL, false); + + ro_gui_search_set_status(true, NULL); + + ro_gui_wimp_event_memorise(dialog_search); + search_data.search_insert = true; +} + +/** + * Handle keypresses in the search dialog + * + * \param key wimp_key block + * \return true if keypress handled, false otherwise + */ +bool ro_gui_search_keypress(wimp_key *key) +{ + bool state; + search_flags_t flags; + + switch (key->c) { + case 1: { + flags = ro_gui_search_update_flags() + ^ SEARCH_FLAG_SHOWALL; + browser_window_search(search_data.search_window, NULL, + flags, + ro_gui_get_icon_string(dialog_search, + ICON_SEARCH_TEXT)); + } + break; + case 9: /* ctrl i */ + state = ro_gui_get_icon_selected_state(dialog_search, + ICON_SEARCH_CASE_SENSITIVE); + ro_gui_set_icon_selected_state(dialog_search, + ICON_SEARCH_CASE_SENSITIVE, !state); + flags = SEARCH_FLAG_FORWARDS | + ro_gui_search_update_flags(); + browser_window_search(search_data.search_window, NULL, + flags, + ro_gui_get_icon_string(dialog_search, + ICON_SEARCH_TEXT)); + return true; + case IS_WIMP_KEY | wimp_KEY_UP: + search_data.search_insert = true; + flags = ~SEARCH_FLAG_FORWARDS & + ro_gui_search_update_flags(); + browser_window_search(search_data.search_window, NULL, + flags, + ro_gui_get_icon_string(dialog_search, + ICON_SEARCH_TEXT)); + return true; + case IS_WIMP_KEY | wimp_KEY_DOWN: + search_data.search_insert = true; + flags = SEARCH_FLAG_FORWARDS | + ro_gui_search_update_flags(); + browser_window_search(search_data.search_window, NULL, + flags, + ro_gui_get_icon_string(dialog_search, + ICON_SEARCH_TEXT)); + return true; + + default: + if (key->c == 21) { + /* ctrl+u means the user's starting + * a new search */ + browser_window_search_clear( + search_data.search_window); + search_data.search_insert = true; + } + if (key->c == 8 || /* backspace */ + key->c == 21 || /* ctrl u */ + (key->c >= 0x20 && key->c <= 0x7f)) { + flags = SEARCH_FLAG_FORWARDS | + ro_gui_search_update_flags(); + ro_gui_search_set_forward_state(true, + search_data.search_window); + ro_gui_search_set_back_state(true, + search_data.search_window); + browser_window_search(search_data.search_window, + NULL, + flags, + ro_gui_get_icon_string( + dialog_search, + ICON_SEARCH_TEXT)); + return true; + } + break; + } + + return false; +} + +/** + * Ends the search + * \param w the search window handle (not used) + */ +void ro_gui_search_end(wimp_w w) +{ + browser_window_search_clear(search_data.search_window); +} + +/** +* Change the displayed search status. +* \param found search pattern matched in text +* \param p the pointer sent to search_verify_new() / search_create_context() +*/ + +void ro_gui_search_set_status(bool found, void *p) +{ + ro_gui_set_icon_string(dialog_search, ICON_SEARCH_STATUS, found ? "" : + messages_get("NotFound"), true); +} + +/** +* display hourglass while searching +* \param active start/stop indicator +* \param p the pointer sent to search_verify_new() / search_create_context() +*/ + +void ro_gui_search_set_hourglass(bool active, void *p) +{ + if (active) + xhourglass_on(); + + else + xhourglass_off(); +} + +/** +* activate search forwards button in gui +* \param active activate/inactivate +* \param p the pointer sent to search_verify_new() / search_create_context() +*/ + +void ro_gui_search_set_forward_state(bool active, void *p) +{ + ro_gui_set_icon_shaded_state(dialog_search, ICON_SEARCH_FIND_NEXT, + !active); +} + +/** +* activate search forwards button in gui +* \param active activate/inactivate +* \param p the pointer sent to search_verify_new() / search_create_context() +*/ + +void ro_gui_search_set_back_state(bool active, void *p) +{ + ro_gui_set_icon_shaded_state(dialog_search, ICON_SEARCH_FIND_PREV, + !active); +} + +/** +* retrieve state of 'case sensitive', 'show all' checks in gui +*/ +search_flags_t ro_gui_search_update_flags(void) +{ + search_flags_t flags; + flags = 0 | (ro_gui_get_icon_selected_state(dialog_search, + ICON_SEARCH_CASE_SENSITIVE) ? + SEARCH_FLAG_CASE_SENSITIVE : 0) | + (ro_gui_get_icon_selected_state(dialog_search, + ICON_SEARCH_SHOW_ALL) ? SEARCH_FLAG_SHOWALL : 0); + return flags; +} + |