diff options
Diffstat (limited to 'dw')
-rw-r--r-- | dw/findtext.cc | 124 | ||||
-rw-r--r-- | dw/findtext.hh | 10 | ||||
-rw-r--r-- | dw/layout.hh | 4 |
3 files changed, 112 insertions, 26 deletions
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 (); } |