diff options
author | João Ricardo Lourenço <jorl17.8@gmail.com> | 2009-02-08 16:58:29 -0300 |
---|---|---|
committer | João Ricardo Lourenço <jorl17.8@gmail.com> | 2009-02-08 16:58:29 -0300 |
commit | 31d9389f4d4eed8d3eb4e6f77148fb6ec0c0a37f (patch) | |
tree | 72289bd30fb46650217daecb87c396e851e8dc7a | |
parent | 4e417d3988cff4143da06f438fcd39cb228ed1f9 (diff) |
Implemented "search previous" in string searches
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | dw/findtext.cc | 124 | ||||
-rw-r--r-- | dw/findtext.hh | 10 | ||||
-rw-r--r-- | dw/layout.hh | 4 | ||||
-rw-r--r-- | src/findbar.cc | 31 | ||||
-rw-r--r-- | src/findbar.hh | 3 | ||||
-rw-r--r-- | src/uicmd.cc | 6 | ||||
-rw-r--r-- | src/uicmd.hh | 3 | ||||
-rw-r--r-- | test/dw_find_test.cc | 2 |
9 files changed, 150 insertions, 37 deletions
@@ -9,6 +9,8 @@ dillo-2.1 +- Added support for numeric IPv6 addresses entered into the url bar. - Used the URL authority part instead of stripped default port in HTTP query. Patches: Justus Winter ++- Implemented "search previous" in string searches. + Patch: João Ricardo Lourenço +- Fix for file inputs without values (forms). - Tuned input width a bit. - Cleaned up resource embedding (forms) @@ -50,7 +52,7 @@ dillo-2.1 +- Added the "middle_click_drags_page" dillorc option. Patch: Jorge Arellano Cid, Thomas Orgis +- Set the File menu label to hide when the File menu-button is shown. - - Trying a new iconv() test in configure.in. + - Set a new iconv() test in configure.in. - Allowed the rc parser to skip whitespace around the equal sign. - Fixed the parser not to call Html_tag_close_* functions twice. - Implemented loading of remote CSS Stylesheet. diff --git a/dw/findtext.cc b/dw/findtext.cc index 15de9f16..93564692 100644 --- a/dw/findtext.cc +++ b/dw/findtext.cc @@ -21,6 +21,7 @@ #include "core.hh" +#include "../lout/msg.h" namespace dw { namespace core { @@ -66,7 +67,8 @@ void FindtextState::setWidget (Widget *widget) hlIterator = NULL; } -FindtextState::Result FindtextState::search (const char *key, bool caseSens) +FindtextState::Result FindtextState::search (const char *key, bool caseSens, + bool backwards) { if (!widget || *key == 0) // empty keys are not found return NOT_FOUND; @@ -86,18 +88,25 @@ FindtextState::Result FindtextState::search (const char *key, bool caseSens) if (nexttab) delete[] nexttab; - nexttab = createNexttab (key, caseSens); + nexttab = createNexttab (key, caseSens, backwards); if (iterator) delete iterator; iterator = new CharIterator (widget); - iterator->next (); + + if (backwards) { + /* Go to end */ + while(iterator->next () ) ; + iterator->prev (); //We don't want to be at CharIterator::END. + } else { + iterator->next (); + } } else newKey = false; bool firstTrial = !wasHighlighted || newKey; - if (search0 ()) { + if (search0 (backwards, firstTrial)) { // Highlighlighting is done with a clone. hlIterator = iterator->cloneCharIterator (); for (int i = 0; key[i]; i++) @@ -110,16 +119,21 @@ FindtextState::Result FindtextState::search (const char *key, bool caseSens) iterator->next (); return SUCCESS; } else { - if (firstTrial) + if (firstTrial) { return NOT_FOUND; - else { + } else { // Nothing found anymore, reset the state for the next trial. delete iterator; iterator = new CharIterator (widget); - iterator->next (); - + if (backwards) { + /* Go to end */ + while(iterator->next ()) ; + iterator->prev (); //We don't want to be at CharIterator::END. + } else { + iterator->next (); + } // We expect a success. - Result result2 = search (key, caseSens); + Result result2 = search (key, caseSens, backwards); assert (result2 == SUCCESS); return RESTART; } @@ -138,8 +152,29 @@ void FindtextState::resetSearch () key = NULL; } -int *FindtextState::createNexttab (const char *key, bool caseSens) +/* + * Return a new string: with the reverse of the original. + */ +const char* FindtextState::rev(const char *str) { + if (!str) + return NULL; + + int len = strlen(str); + char *nstr = new char[len+1]; + for (int i = 0; i < len; ++i) + nstr[i] = str[len-1 -i]; + nstr[len] = 0; + + return nstr; +} + +int *FindtextState::createNexttab (const char *needle, bool caseSens, + bool backwards) +{ + const char* key; + + key = (backwards) ? rev(needle) : needle; int i = 0; int j = -1; int l = strlen (key); @@ -156,6 +191,9 @@ int *FindtextState::createNexttab (const char *key, bool caseSens) j = nexttab[j]; } while (i < l - 1); + if (backwards) + delete [] key; + return nexttab; } @@ -179,30 +217,76 @@ bool FindtextState::unhighlight () return false; } -bool FindtextState::search0 () +bool FindtextState::search0 (bool backwards, bool firstTrial) { if (iterator->getChar () == CharIterator::END) return false; - + + bool ret = false; + const char* searchKey = (backwards) ? rev(key) : key; int j = 0; bool nextit = true; int l = strlen (key); + if (backwards && !firstTrial) { + _MSG("Having to do."); + /* Position correctly */ + /* In order to achieve good results (i.e: find a word that ends within + * the previously searched word's limit) we have to position the + * iterator in the semilast character of the previously searched word. + * + * Since we know that if a word was found before it was exactly the + * same word as the one we are searching for now, we can apply the + * following expression: + * + * Where l=length of the key and n=num of positions to move: + * + * n = l - 3 + * + * If n is negative, we have to move backwards, but if it is + * positive, we have to move forward. So, when l>=4, we start moving + * the iterator forward. */ + + if (l==1) { + iterator->prev(); + iterator->prev(); + } else if (l==2) { + iterator->prev(); + } else if (l>=4) { + for (int i=0; i<l-3; i++) { + iterator->next(); + } + } + + } else if (backwards && l==1) { + /* Particular case where we can't find the last character */ + iterator->next(); + } + do { - if (j == -1 || charsEqual (iterator->getChar (), key[j], caseSens)) { + if (j == -1 || charsEqual (iterator->getChar(),searchKey[j],caseSens)) { j++; - nextit = iterator->next (); + nextit = backwards ? iterator->prev () : iterator->next (); } else j = nexttab[j]; } while (nextit && j < l); if (j >= l) { - // Go back to where the word was found. - for (int i = 0; i < l; i++) - iterator->prev (); - return true; - } else - return false; + if (backwards) { + //This is the location of the key + iterator->next(); + } else { + // Go back to where the key was found. + for (int i = 0; i < l; i++) + iterator->prev (); + } + ret = true; + } + + if (backwards) + delete [] searchKey; + + return ret; } } // namespace dw diff --git a/dw/findtext.hh b/dw/findtext.hh index e9fb57c2..83d22bd3 100644 --- a/dw/findtext.hh +++ b/dw/findtext.hh @@ -58,10 +58,12 @@ private: * NULL, when no text is highlighted. */ CharIterator *hlIterator; - - static int *createNexttab (const char *key, bool caseSens); + + static const char* rev(const char* _str); /* Function to reverse a C-string */ + + static int *createNexttab (const char *needle, bool caseSens, bool backwards); bool unhighlight (); - bool search0 (); + bool search0 (bool backwards, bool firstTrial); inline static bool charsEqual (char c1, char c2, bool caseSens) { return caseSens ? c1 == c2 : tolower (c1) == tolower (c2) || @@ -72,7 +74,7 @@ public: ~FindtextState (); void setWidget (Widget *widget); - Result search (const char *key, bool caseSens); + Result search (const char *key, bool caseSens, bool backwards); void resetSearch (); }; diff --git a/dw/layout.hh b/dw/layout.hh index ce9786f1..b66d653f 100644 --- a/dw/layout.hh +++ b/dw/layout.hh @@ -255,8 +255,8 @@ public: emitter.connectLayout (receiver); } /** \brief See dw::core::FindtextState::search. */ - inline FindtextState::Result search (const char *str, bool caseSens) - { return findtextState.search (str, caseSens); } + inline FindtextState::Result search (const char *str, bool caseSens, int backwards) + { return findtextState.search (str, caseSens, backwards); } /** \brief See dw::core::FindtextState::resetSearch. */ inline void resetSearch () { findtextState.resetSearch (); } diff --git a/src/findbar.cc b/src/findbar.cc index 5d1c6245..ea1c80f1 100644 --- a/src/findbar.cc +++ b/src/findbar.cc @@ -63,7 +63,22 @@ void Findbar::search_cb(Widget *, void *vfb) if (key[0] != '\0') a_UIcmd_findtext_search(a_UIcmd_get_bw_by_widget(fb), - key, case_sens); + key, case_sens, false); +} + +/* + * Find previous occurrence of input key + */ +void Findbar::searchBackwards_cb(Widget *, void *vfb) +{ + Findbar *fb = (Findbar *)vfb; + const char *key = fb->i->text(); + bool case_sens = fb->check_btn->value(); + + if (key[0] != '\0') { + a_UIcmd_findtext_search(a_UIcmd_get_bw_by_widget(fb), + key, case_sens, true); + } } /* @@ -96,7 +111,7 @@ Findbar::Findbar(int width, int height) : int button_width = 70; int gap = 2; int border = 2; - int input_width = width - (2 * border + 3 * (button_width + gap)); + int input_width = width - (2 * border + 4 * (button_width + gap)); int x = border; height -= 2 * border; @@ -121,15 +136,23 @@ Findbar::Findbar(int width, int height) : i->clear_tab_to_focus(); i->set_click_to_focus(); - // TODO: search previous would be nice next_btn = new HighlightButton(x, border, button_width, height, "Next"); x += button_width + gap; - next_btn->tooltip("Find next occurrence of the search phrase"); + next_btn->tooltip("Find next occurrence of the search phrase\n" + "shortcut: Enter"); next_btn->add_shortcut(ReturnKey); next_btn->add_shortcut(KeypadEnter); next_btn->callback(search_cb, this); next_btn->clear_tab_to_focus(); + prev_btn= new HighlightButton(x, border, button_width, height, "Previous"); + prev_btn->tooltip("Find previous occurrence of the search phrase\n" + "shortcut: Shift+Enter"); + prev_btn->add_shortcut(SHIFT+ReturnKey); + prev_btn->callback(searchBackwards_cb, this); + prev_btn->clear_tab_to_focus(); + x += button_width + gap; + check_btn = new CheckButton(x, border, 2*button_width, height, "Case-sensitive"); check_btn->clear_tab_to_focus(); diff --git a/src/findbar.hh b/src/findbar.hh index 1e8c8d66..90982ffd 100644 --- a/src/findbar.hh +++ b/src/findbar.hh @@ -16,12 +16,13 @@ using namespace fltk; */ class Findbar : public Group { Button *clrb; - HighlightButton *hide_btn, *next_btn; + HighlightButton *hide_btn, *next_btn, *prev_btn; CheckButton *check_btn; xpmImage *hideImg; Input *i; static void search_cb (Widget *, void *); + static void searchBackwards_cb (Widget *, void *); static void search_cb2 (Widget *, void *); static void hide_cb (Widget *, void *); diff --git a/src/uicmd.cc b/src/uicmd.cc index 75d6336e..620669af 100644 --- a/src/uicmd.cc +++ b/src/uicmd.cc @@ -948,13 +948,13 @@ void a_UIcmd_fullscreen_toggle(BrowserWindow *bw) } /* - * Search for next occurrence of key. + * Search for next/previous occurrence of key. */ -void a_UIcmd_findtext_search(BrowserWindow *bw, const char *key, int case_sens) +void a_UIcmd_findtext_search(BrowserWindow *bw, const char *key, int case_sens, int backwards) { Layout *l = (Layout *)bw->render_layout; - switch (l->search(key, case_sens)) { + switch (l->search(key, case_sens, backwards)) { case FindtextState::RESTART: a_UIcmd_set_msg(bw, "No further occurrences of \"%s\". " "Restarting from the top.", key); diff --git a/src/uicmd.hh b/src/uicmd.hh index ca5b7cc5..b08b4f8d 100644 --- a/src/uicmd.hh +++ b/src/uicmd.hh @@ -34,7 +34,8 @@ void a_UIcmd_book(void *vbw); void a_UIcmd_add_bookmark(BrowserWindow *bw, const DilloUrl *url); void a_UIcmd_fullscreen_toggle(BrowserWindow *bw); void a_UIcmd_findtext_dialog(BrowserWindow *bw); -void a_UIcmd_findtext_search(BrowserWindow *bw,const char *key,int case_sens); +void a_UIcmd_findtext_search(BrowserWindow *bw,const char *key,int case_sens, + int backwards); void a_UIcmd_findtext_reset(BrowserWindow *bw); void a_UIcmd_focus_main_area(BrowserWindow *bw); void a_UIcmd_focus_location(void *vbw); diff --git a/test/dw_find_test.cc b/test/dw_find_test.cc index 651ca653..50f2d1aa 100644 --- a/test/dw_find_test.cc +++ b/test/dw_find_test.cc @@ -44,7 +44,7 @@ static ::fltk::Widget *resultLabel; static void findCallback (::fltk::Widget *widget, void *data) { //switch(layout->search ("worm", true)) { - switch(layout->search ("WORM", false)) { + switch(layout->search ("WORM", false, false)) { case FindtextState::SUCCESS: resultLabel->label("SUCCESS"); break; |