From f3bef9fdcb3faa9e13d2510cdebf38f0ea9c77ef Mon Sep 17 00:00:00 2001 From: John Mark Bell Date: Thu, 5 Aug 2004 22:03:56 +0000 Subject: [project @ 2004-08-05 22:03:56 by jmb] Tidy up and bugfix search implementation svn path=/import/netsurf/; revision=1183 --- riscos/dialog.c | 33 ++------ riscos/gui.h | 5 +- riscos/search.c | 259 +++++++++++++++++++++++++++++++++++++++----------------- riscos/window.c | 3 +- 4 files changed, 192 insertions(+), 108 deletions(-) diff --git a/riscos/dialog.c b/riscos/dialog.c index d98cf1127..64b70e5f0 100644 --- a/riscos/dialog.c +++ b/riscos/dialog.c @@ -346,8 +346,11 @@ void ro_gui_dialog_close_persistant(wimp_w parent) { bool ro_gui_dialog_keypress(wimp_key *key) { wimp_pointer pointer; - int i; +#ifdef WITH_SEARCH + if (key->w == dialog_search) + return ro_gui_search_keypress(key); +#endif if (key->c == wimp_KEY_ESCAPE) { ro_gui_dialog_close(key->w); return true; @@ -361,25 +364,12 @@ bool ro_gui_dialog_keypress(wimp_key *key) ro_gui_hotlist_dialog_click(&pointer); return true; } - else if (key->w == dialog_search) { - pointer.w = key->w; - pointer.i = ICON_SEARCH_FIND; - pointer.buttons = wimp_CLICK_SELECT; - for (i = 0; i < MAX_PERSISTANT; i++) { - if (persistant_dialog[i].dialog == - dialog_search) { - ro_gui_search_click(&pointer, - persistant_dialog[i].parent); - break; - } - } - return true; - } } #ifdef WITH_AUTH if (key->w == dialog_401li) return ro_gui_401login_keypress(key); #endif + return false; } @@ -390,8 +380,6 @@ bool ro_gui_dialog_keypress(wimp_key *key) void ro_gui_dialog_click(wimp_pointer *pointer) { - int i; - if (pointer->buttons == wimp_CLICK_MENU) return; @@ -415,15 +403,8 @@ void ro_gui_dialog_click(wimp_pointer *pointer) ro_gui_dialog_click_warning(pointer); else if ((pointer->w == dialog_folder) || (pointer->w == dialog_entry)) ro_gui_hotlist_dialog_click(pointer); - else if (pointer->w == dialog_search) { - for (i = 0; i < MAX_PERSISTANT; i++) { - if (persistant_dialog[i].dialog == dialog_search) { - ro_gui_search_click(pointer, - persistant_dialog[i].parent); - break; - } - } - } + else if (pointer->w == dialog_search) + ro_gui_search_click(pointer); } diff --git a/riscos/gui.h b/riscos/gui.h index d16cfed86..0a2c4bf3c 100644 --- a/riscos/gui.h +++ b/riscos/gui.h @@ -239,8 +239,9 @@ void ro_gui_debugwin_close(void); void ro_gui_debugwin_redraw(wimp_draw *redraw); /* in search.c */ -void ro_gui_search_click(wimp_pointer *pointer, wimp_w parent); -void ro_gui_search_prepare(void); +void ro_gui_search_open(struct gui_window *g, int x, int y, bool sub_menu, bool keypress); +void ro_gui_search_click(wimp_pointer *pointer); +bool ro_gui_search_keypress(wimp_key *key); /* toolbar types */ #define TOOLBAR_BROWSER 0 diff --git a/riscos/search.c b/riscos/search.c index 9dc46299a..54f4d9b0c 100644 --- a/riscos/search.c +++ b/riscos/search.c @@ -5,6 +5,10 @@ * Copyright 2004 John M Bell */ +/** \file + * Free text search (implementation) + */ + #include #include "oslib/wimp.h" @@ -29,30 +33,71 @@ struct list_entry { struct list_entry *next; }; +static struct gui_window *search_current_window = 0; + static char *search_string = 0; -static struct list_entry head = { 0, 0, 0 }; -static struct list_entry *found = &head; -static struct list_entry *current = 0; -static struct gui_window *w = 0; -static bool prev_from_top = false; -static bool prev_case_sens = false; - -static void do_search(struct gui_window *g, char *string, bool from_top, bool case_sens, bool forwards); +static struct list_entry search_head = { 0, 0, 0 }; +static struct list_entry *search_found = &search_head; +static struct list_entry *search_current = 0; +static struct gui_window *search_w = 0; +static bool search_prev_from_top = false; +static bool search_prev_case_sens = false; + +static void start_search(void); +static void end_search(void); +static void do_search(char *string, bool from_top, bool case_sens, bool forwards); static bool find_occurrences(char *string, struct box *cur, bool case_sens); static char * strcasestr(char *s1, char *s2); +/** + * Open the search dialog + * + * \param g the gui window to search + * \param x x position, for sub_menu true only + * \param y y position, for sub_menu true only + * \param sub_menu open as a sub_menu, otherwise persistent + * \param keypress whether opened by a keypress or not + */ +void ro_gui_search_open(struct gui_window *g, int x, int y, bool sub_menu, bool keypress) +{ + os_error *e; + + assert(g != NULL); + + search_current_window = g; + + ro_gui_set_icon_string(dialog_search, ICON_SEARCH_TEXT, ""); + ro_gui_set_icon_selected_state(dialog_search, ICON_SEARCH_FORWARDS, + true); + ro_gui_set_icon_selected_state(dialog_search, ICON_SEARCH_BACKWARDS, + false); + ro_gui_set_icon_selected_state(dialog_search, ICON_SEARCH_START, + false); + ro_gui_set_icon_selected_state(dialog_search, + ICON_SEARCH_CASE_SENSITIVE, false); + + if (sub_menu) { + e = xwimp_create_sub_menu((wimp_menu *) dialog_search, x, y); + if (e) { + LOG(("xwimp_create_sub_menu: 0x%x: %s", + e->errnum, e->errmess)); + warn_user("MenuError", e->errmess); + } + } + else { + ro_gui_dialog_open_persistant(g->window, dialog_search, !keypress); + } +} + /** * Handle clicks in the search dialog * * \param pointer wimp_pointer block * \param parent The parent window of this persistent dialog */ -void ro_gui_search_click(wimp_pointer *pointer, wimp_w parent) +void ro_gui_search_click(wimp_pointer *pointer) { - struct gui_window *g; - char *string; - if (pointer->buttons == wimp_CLICK_MENU) return; @@ -65,52 +110,115 @@ void ro_gui_search_click(wimp_pointer *pointer, wimp_w parent) pointer->i, true); break; case ICON_SEARCH_FIND: - g = ro_gui_window_lookup(parent); - string = ro_gui_get_icon_string(pointer->w, - ICON_SEARCH_TEXT); - if (!g || strlen(string) == 0) - return; - do_search(g, string, - ro_gui_get_icon_selected_state(pointer->w, - ICON_SEARCH_START), - ro_gui_get_icon_selected_state(pointer->w, - ICON_SEARCH_CASE_SENSITIVE), - ro_gui_get_icon_selected_state(pointer->w, - ICON_SEARCH_FORWARDS)); + start_search(); break; case ICON_SEARCH_CANCEL: - ro_gui_dialog_close(dialog_search); + end_search(); break; } } /** - * Prepare the search dialog for display + * Handle keypresses in the search dialog + * + * \param key wimp_key block + * \return true if keypress handled, false otherwise */ -void ro_gui_search_prepare(void) +bool ro_gui_search_keypress(wimp_key *key) { - ro_gui_set_icon_string(dialog_search, ICON_SEARCH_TEXT, ""); - ro_gui_set_icon_selected_state(dialog_search, ICON_SEARCH_FORWARDS, - true); - ro_gui_set_icon_selected_state(dialog_search, ICON_SEARCH_BACKWARDS, - false); - ro_gui_set_icon_selected_state(dialog_search, ICON_SEARCH_START, - false); - ro_gui_set_icon_selected_state(dialog_search, - ICON_SEARCH_CASE_SENSITIVE, false); + bool state; + + switch (key->c) { + case 2: /* ctrl b */ + ro_gui_set_icon_selected_state(dialog_search, ICON_SEARCH_FORWARDS, false); + ro_gui_set_icon_selected_state(dialog_search, ICON_SEARCH_BACKWARDS, true); + return true; + case 6: /* ctrl f */ + ro_gui_set_icon_selected_state(dialog_search, ICON_SEARCH_FORWARDS, true); + ro_gui_set_icon_selected_state(dialog_search, ICON_SEARCH_BACKWARDS, false); + return true; + 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); + return true; + case 19: /* ctrl s */ + state = ro_gui_get_icon_selected_state(dialog_search, ICON_SEARCH_START); + ro_gui_set_icon_selected_state(dialog_search, ICON_SEARCH_START, !state); + + return true; + case wimp_KEY_RETURN: + start_search(); + return true; + case wimp_KEY_ESCAPE: + end_search(); + return true; + } + + return false; +} + +/** + * Begins the search process + */ +void start_search(void) +{ + char *string; + + string = ro_gui_get_icon_string(dialog_search, ICON_SEARCH_TEXT); + if (strlen(string) == 0) + return; + do_search(string, + ro_gui_get_icon_selected_state(dialog_search, + ICON_SEARCH_START), + ro_gui_get_icon_selected_state(dialog_search, + ICON_SEARCH_CASE_SENSITIVE), + ro_gui_get_icon_selected_state(dialog_search, + ICON_SEARCH_FORWARDS)); +} + +/** + * Ends the search process, invalidating all global state and + * freeing the list of found boxes + */ +void end_search(void) +{ + struct list_entry *a, *b; + + search_current_window = 0; + + if (search_string) + free(search_string); + search_string = 0; + + for (a = search_found->next; a; a = b) { + b = a->next; + free(a); + } + search_found->prev = 0; + search_found->next = 0; + + search_current = 0; + + search_w = 0; + + search_prev_from_top = false; + search_prev_case_sens = false; + + /* and close the window */ + xwimp_create_menu((wimp_menu *)-1, 0, 0); + ro_gui_dialog_close(dialog_search); } /** * Search for a string in the box tree * - * \param g gui_window which contains content to search * \param string the string to search for * \param from_top whether to display results from the top of the page, or * the current scroll position * \param case_sens whether to perform a case sensitive search * \param forwards direction to search in */ -void do_search(struct gui_window *g, char *string, bool from_top, bool case_sens, bool forwards) +void do_search(char *string, bool from_top, bool case_sens, bool forwards) { struct content *c; struct box *box; @@ -118,10 +226,10 @@ void do_search(struct gui_window *g, char *string, bool from_top, bool case_sens int x,y; bool new = false; - if (!g) + if (!search_current_window) return; - c = g->bw->current_content; + c = search_current_window->bw->current_content; /* only handle html contents */ if (c->type != CONTENT_HTML) @@ -135,43 +243,45 @@ void do_search(struct gui_window *g, char *string, bool from_top, bool case_sens // LOG(("'%s' - '%s' (%p, %p) %p (%d, %d) (%d, %d) %d", search_string, string, w, g, found->next, prev_from_top, from_top, prev_case_sens, case_sens, forwards)); /* check if we need to start a new search or continue an old one */ - if (!search_string || !w || g != w || !found->next || - prev_from_top != from_top || prev_case_sens != case_sens || + if (!search_string || !search_w || + search_current_window != search_w || !search_found->next || + search_prev_from_top != from_top || + search_prev_case_sens != case_sens || (case_sens && strcmp(string, search_string) != 0) || (!case_sens && strcasecmp(string, search_string) != 0)) { if (search_string) free(search_string); search_string = strdup(string); - current = 0; - for (a = found->next; a; a = b) { + search_current = 0; + for (a = search_found->next; a; a = b) { b = a->next; free(a); } - found->prev = 0; - found->next = 0; + search_found->prev = 0; + search_found->next = 0; if (!find_occurrences(string, box, case_sens)) { - for (a = found->next; a; a = b) { + for (a = search_found->next; a; a = b) { b = a->next; free(a); } - found->prev = 0; - found->next = 0; + search_found->prev = 0; + search_found->next = 0; return; } new = true; - w = g; - prev_from_top = from_top; - prev_case_sens = case_sens; + search_w = search_current_window; + search_prev_from_top = from_top; + search_prev_case_sens = case_sens; } // LOG(("%d %p %p (%p, %p)", new, found->next, current, current->prev, current->next)); - if (!found->next) + if (!search_found->next) return; if (new && from_top) { /* new search, beginning at the top of the page */ - current = found->next; + search_current = search_found->next; } else if (new) { /* new search, beginning from user's current scroll @@ -179,7 +289,7 @@ void do_search(struct gui_window *g, char *string, bool from_top, bool case_sens wimp_window_state state; os_error *error; - state.w = g->window; + state.w = search_current_window->window; error = xwimp_get_window_state(&state); if (error) { LOG(("xwimp_get_window_state: 0x%x: %s", @@ -188,7 +298,7 @@ void do_search(struct gui_window *g, char *string, bool from_top, bool case_sens return; } - for (a = found->next; a; a = a->next) { + for (a = search_found->next; a; a = a->next) { box_coords(a->box, &x, &y); LOG(("%d, %d", y, state.yscroll / 2)); if (forwards && -y <= state.yscroll / 2) @@ -198,27 +308,27 @@ void do_search(struct gui_window *g, char *string, bool from_top, bool case_sens } if (a) - current = a; + search_current = a; else return; } else { /* continued search in the direction specified */ - if (forwards && current && current->next) { - current = current->next; + if (forwards && search_current && search_current->next) { + search_current = search_current->next; } - else if (!forwards && current && current->prev) { - current = current->prev; + else if (!forwards && search_current && search_current->prev) { + search_current = search_current->prev; } } - if (!current) + if (!search_current) return; /* get box position and jump to it */ - box_coords(current->box, &x, &y); + box_coords(search_current->box, &x, &y); // LOG(("%p (%d, %d)", current, x, y)); - gui_window_set_scroll(g, x, y); + gui_window_set_scroll(search_current_window, x, y); } @@ -253,26 +363,19 @@ bool find_occurrences(char *string, struct box *cur, bool case_sens) } entry->box = cur; entry->next = 0; - entry->prev = found->prev; - if (!found->prev) - found->next = entry; + entry->prev = search_found->prev; + if (!search_found->prev) + search_found->next = entry; else - found->prev->next = entry; - found->prev = entry; + search_found->prev->next = entry; + search_found->prev = entry; } } /* and recurse */ for (a = cur->children; a; a = a->next) { - if (a->type != BOX_FLOAT_LEFT && a->type != BOX_FLOAT_RIGHT) - if (!find_occurrences(string, a, case_sens)) - return false; - } - - for (a = cur->float_children; a; a = a->next_float) { - if (a->type != BOX_FLOAT_LEFT && a->type != BOX_FLOAT_RIGHT) - if (!find_occurrences(string, a, case_sens)) - return false; + if (!find_occurrences(string, a, case_sens)) + return false; } return true; diff --git a/riscos/window.c b/riscos/window.c index 39d21f8d5..9373a57c2 100644 --- a/riscos/window.c +++ b/riscos/window.c @@ -1266,8 +1266,7 @@ bool ro_gui_window_keypress(struct gui_window *g, int key, bool toolbar) return true; case wimp_KEY_F4: /* Search */ - ro_gui_search_prepare(); - ro_gui_dialog_open_persistant(g->window, dialog_search, false); + ro_gui_search_open(g, 0, 0, false, true); return true; case wimp_KEY_F5: /* Refresh. */ -- cgit v1.2.3