Dillo v3.1.1-46-g8a360e32
Loading...
Searching...
No Matches
findtext.cc
Go to the documentation of this file.
1/*
2 * Dillo Widget
3 *
4 * Copyright 2005-2007 Sebastian Geerken <sgeerken@dillo.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20
21
22#include "core.hh"
23#include "dlib/dlib.h"
24#include "../lout/debug.hh"
25#include "../lout/msg.h"
26
27namespace dw {
28namespace core {
29
31{
32 DBG_OBJ_CREATE ("dw::core::FindtextState");
33
34 key = NULL;
35 nexttab = NULL;
36 widget = NULL;
37 iterator = NULL;
38 hlIterator = NULL;
39}
40
42{
43 if (key)
44 free(key);
45 if (nexttab)
46 delete[] nexttab;
47 if (iterator)
48 delete iterator;
49 if (hlIterator)
50 delete hlIterator;
51
53}
54
56{
57 this->widget = widget;
58
59 // A widget change will restart the search.
60 if (key)
61 free(key);
62 key = NULL;
63 if (nexttab)
64 delete[] nexttab;
65 nexttab = NULL;
66
67 if (iterator)
68 delete iterator;
69 iterator = NULL;
70 if (hlIterator)
71 delete hlIterator;
72 hlIterator = NULL;
73}
74
75FindtextState::Result FindtextState::search (const char *key, bool caseSens,
76 bool backwards)
77{
78 if (!widget || *key == 0) // empty keys are not found
79 return NOT_FOUND;
80
81 bool wasHighlighted = unhighlight ();
82 bool newKey;
83
84 // If the key (or the widget) changes (including case sensitivity),
85 // the search is started from the beginning.
86 if (this->key == NULL || this->caseSens != caseSens ||
87 strcmp (this->key, key) != 0) {
88 newKey = true;
89 if (this->key)
90 free(this->key);
91 this->key = dStrdup (key);
92 this->caseSens = caseSens;
93
94 if (nexttab)
95 delete[] nexttab;
96 nexttab = createNexttab (key, caseSens, backwards);
97
98 if (iterator)
99 delete iterator;
100 iterator = new CharIterator (widget, true);
101
102 if (backwards) {
103 /* Go to end */
104 while (iterator->next () ) ;
105 iterator->prev (); //We don't want to be at CharIterator::END.
106 } else {
107 iterator->next ();
108 }
109 } else
110 newKey = false;
111
112 bool firstTrial = !wasHighlighted || newKey;
113
114 if (search0 (backwards, firstTrial)) {
115 // Highlighting is done with a clone.
117 for (int i = 0; key[i]; i++)
118 hlIterator->next ();
122
123 // The search will continue from the word after the found position.
124 iterator->next ();
125 return SUCCESS;
126 } else {
127 if (firstTrial) {
128 return NOT_FOUND;
129 } else {
130 // Nothing found anymore, reset the state for the next trial.
131 delete iterator;
132 iterator = new CharIterator (widget, true);
133 if (backwards) {
134 /* Go to end */
135 while (iterator->next ()) ;
136 iterator->prev (); //We don't want to be at CharIterator::END.
137 } else {
138 iterator->next ();
139 }
140 // We expect a success.
141 Result result2 = search (key, caseSens, backwards);
142 assert (result2 == SUCCESS);
143 return RESTART;
144 }
145 }
146}
147
152{
153 unhighlight ();
154
155 if (key)
156 free(key);
157 key = NULL;
158}
159
160/*
161 * Return a new string: with the reverse of the original.
162 */
163const char* FindtextState::rev(const char *str)
164{
165 if (!str)
166 return NULL;
167
168 int len = strlen(str);
169 char *nstr = new char[len+1];
170 for (int i = 0; i < len; ++i)
171 nstr[i] = str[len-1 -i];
172 nstr[len] = 0;
173
174 return nstr;
175}
176
177int *FindtextState::createNexttab (const char *needle, bool caseSens,
178 bool backwards)
179{
180 const char* key;
181
182 key = (backwards) ? rev(needle) : needle;
183 int i = 0;
184 int j = -1;
185 int l = strlen (key);
186 int *nexttab = new int[l + 1]; // + 1 is necessary for l == 1 case
187 nexttab[0] = -1;
188
189 do {
190 if (j == -1 || charsEqual (key[i], key[j], caseSens)) {
191 i++;
192 j++;
193 nexttab[i] = j;
194 //_MSG ("nexttab[%d] = %d\n", i, j);
195 } else
196 j = nexttab[j];
197 } while (i < l - 1);
198
199 if (backwards)
200 delete [] key;
201
202 return nexttab;
203}
204
209{
210 if (hlIterator) {
212 for (int i = 0; key[i]; i++)
213 start->prev ();
214
216 delete start;
217 delete hlIterator;
218 hlIterator = NULL;
219
220 return true;
221 } else
222 return false;
223}
224
225bool FindtextState::search0 (bool backwards, bool firstTrial)
226{
228 return false;
229
230 bool ret = false;
231 const char* searchKey = (backwards) ? rev(key) : key;
232 int j = 0;
233 bool nextit = true;
234 int l = strlen (key);
235
236 if (backwards && !firstTrial) {
237 _MSG("Having to do.");
238 /* Position correctly */
239 /* In order to achieve good results (i.e: find a word that ends within
240 * the previously searched word's limit) we have to position the
241 * iterator in the semilast character of the previously searched word.
242 *
243 * Since we know that if a word was found before it was exactly the
244 * same word as the one we are searching for now, we can apply the
245 * following expression:
246 *
247 * Where l=length of the key and n=num of positions to move:
248 *
249 * n = l - 3
250 *
251 * If n is negative, we have to move backwards, but if it is
252 * positive, we have to move forward. So, when l>=4, we start moving
253 * the iterator forward. */
254
255 if (l==1) {
256 iterator->prev();
257 iterator->prev();
258 } else if (l==2) {
259 iterator->prev();
260 } else if (l>=4) {
261 for (int i=0; i<l-3; i++) {
262 iterator->next();
263 }
264 }
265
266 } else if (backwards && l==1) {
267 /* Particular case where we can't find the last character */
268 iterator->next();
269 }
270
271 do {
272 if (j == -1 || charsEqual (iterator->getChar(),searchKey[j],caseSens)) {
273 j++;
274 nextit = backwards ? iterator->prev () : iterator->next ();
275 } else
276 j = nexttab[j];
277 } while (nextit && j < l);
278
279 if (j >= l) {
280 if (backwards) {
281 //This is the location of the key
282 iterator->next();
283 } else {
284 // Go back to where the key was found.
285 for (int i = 0; i < l; i++)
286 iterator->prev ();
287 }
288 ret = true;
289 }
290
291 if (backwards)
292 delete [] searchKey;
293
294 return ret;
295}
296
297} // namespace core
298} // namespace dw
#define _MSG(...)
Definition bookmarks.c:45
static void highlight(CharIterator *it1, CharIterator *it2, HighlightLayer layer)
Definition iterator.cc:857
CharIterator * cloneCharIterator()
Definition iterator.hh:253
static void unhighlight(CharIterator *it1, CharIterator *it2, HighlightLayer layer)
Definition iterator.cc:887
static void scrollTo(CharIterator *it1, CharIterator *it2, HPosition hpos, VPosition vpos)
Definition iterator.hh:260
static int * createNexttab(const char *needle, bool caseSens, bool backwards)
Definition findtext.cc:177
CharIterator * hlIterator
The position from where the characters are highlighted.
Definition findtext.hh:60
int * nexttab
The table used for KMP search.
Definition findtext.hh:43
void resetSearch()
This method is called when the user closes the "find text" dialog.
Definition findtext.cc:151
bool search0(bool backwards, bool firstTrial)
Definition findtext.cc:225
@ SUCCESS
The next occurrence of the pattern has been found.
Definition findtext.hh:18
@ NOT_FOUND
The patten does not at all occur in the text.
Definition findtext.hh:27
@ RESTART
There is no further occurrence of the pattern, instead, the first occurrence has been selected.
Definition findtext.hh:24
Result search(const char *key, bool caseSens, bool backwards)
Definition findtext.cc:75
CharIterator * iterator
The position from where the next search will start.
Definition findtext.hh:53
bool unhighlight()
Unhighlight, and return whether a region was highlighted.
Definition findtext.cc:208
static bool charsEqual(char c1, char c2, bool caseSens)
Definition findtext.hh:68
static const char * rev(const char *_str)
Definition findtext.cc:163
char * key
The key used for the last search.
Definition findtext.hh:37
bool caseSens
Whether the last search was case sensitive.
Definition findtext.hh:40
void setWidget(Widget *widget)
Definition findtext.cc:55
Widget * widget
The top of the widget tree, in which the search is done.
Definition findtext.hh:50
The base class of all dillo widgets.
Definition widget.hh:44
#define DBG_OBJ_DELETE()
#define DBG_OBJ_CREATE(klass)
char * dStrdup(const char *s)
Definition dlib.c:77
@ HIGHLIGHT_FINDTEXT
Definition types.hh:45
@ VPOS_CENTER
Definition types.hh:28
@ HPOS_INTO_VIEW
Definition types.hh:20
Dw is in this namespace, or sub namespaces of this one.