KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > armedbear > j > Search


1 /*
2  * Search.java
3  *
4  * Copyright (C) 1998-2004 Peter Graves
5  * $Id: Search.java,v 1.9 2004/09/05 20:01:33 piso Exp $
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */

21
22 package org.armedbear.j;
23
24 import gnu.regexp.RE;
25 import gnu.regexp.REException;
26 import gnu.regexp.REMatch;
27
28 public class Search implements Cloneable JavaDoc
29 {
30     private String JavaDoc pattern;
31     private String JavaDoc lowerCasePattern;
32     private int patternLength;
33
34     private RE re;
35     private REMatch match;
36
37     private boolean ignoreCase;
38     private boolean wholeWordsOnly;
39     private boolean regularExpression;
40     private boolean isMultilinePattern;
41     private boolean restrictToSelection;
42
43     private Region region;
44
45     public Search()
46     {
47         setPattern(new String JavaDoc());
48     }
49
50     public Search(String JavaDoc pattern, boolean ignoreCase, boolean wholeWordsOnly)
51     {
52         setPattern(pattern);
53         this.ignoreCase = ignoreCase;
54         this.wholeWordsOnly = wholeWordsOnly;
55     }
56
57     public final String JavaDoc getPattern()
58     {
59         return pattern;
60     }
61
62     public final void setPattern(String JavaDoc s)
63     {
64         if (s != null) {
65             pattern = s;
66             lowerCasePattern = s.toLowerCase();
67             patternLength = s.length();
68         } else {
69             pattern = lowerCasePattern = "";
70             patternLength = 0;
71         }
72     }
73
74     public final void appendCharToPattern(char c)
75     {
76         pattern += c;
77         lowerCasePattern = pattern.toLowerCase();
78         ++patternLength;
79     }
80
81     public final int getPatternLength()
82     {
83         return patternLength;
84     }
85
86     public final String JavaDoc getLowerCasePattern()
87     {
88         return lowerCasePattern;
89     }
90
91     public final RE getRE()
92     {
93         return re;
94     }
95
96     public final void setRE(RE re)
97     {
98         this.re = re;
99     }
100
101     public final REMatch getMatch()
102     {
103         return match;
104     }
105
106     public final boolean ignoreCase()
107     {
108         return ignoreCase;
109     }
110
111     public final void setIgnoreCase(boolean b)
112     {
113         ignoreCase = b;
114     }
115
116     public final boolean wholeWordsOnly()
117     {
118         return wholeWordsOnly;
119     }
120
121     public final void setWholeWordsOnly(boolean b)
122     {
123         wholeWordsOnly = b;
124     }
125
126     public final boolean isRegularExpression()
127     {
128         return regularExpression;
129     }
130
131     public final void setRegularExpression(boolean b)
132     {
133         regularExpression = b;
134     }
135
136     public final boolean isMultilinePattern()
137     {
138         return isMultilinePattern;
139     }
140
141     public final void setMultiline(boolean b)
142     {
143         isMultilinePattern = b;
144     }
145
146     public final boolean restrictToSelection()
147     {
148         return restrictToSelection;
149     }
150
151     public final void setRestrictToSelection(boolean b)
152     {
153         restrictToSelection = b;
154     }
155
156     public final Region getRegion()
157     {
158         return region;
159     }
160
161     public final void setRegion(Region r)
162     {
163         region = r;
164     }
165
166     protected Position findInBuffer(Buffer buffer)
167     {
168         return find(buffer, new Position(buffer.getFirstLine(), 0));
169     }
170
171     public final Position find(Buffer buffer, Position start)
172     {
173         return regularExpression ? findRegExp(buffer, start) : findString(buffer, start);
174     }
175
176     public final Position reverseFind(Buffer buffer, Position start)
177     {
178         if (regularExpression) {
179             if (isMultilinePattern)
180                 return reverseFindMultilineRegExp(buffer, start);
181             else
182                 return reverseFindRegExp(buffer, start);
183         } else
184             return reverseFindString(buffer, start);
185     }
186
187     public final Position find(Mode mode, Position start)
188     {
189         return regularExpression ? findRegExp(mode, start) : findString(mode, start);
190     }
191
192     public final Position findInLine(Mode mode, Position start)
193     {
194         if (regularExpression)
195             return findRegExpInLine(mode, start.getLine(), start.getOffset(),
196                 start.getLineLength());
197         else
198             return findStringInLine(mode, start.getLine(), start.getOffset(),
199                 start.getLineLength());
200     }
201
202     public final boolean find(String JavaDoc s)
203     {
204         return regularExpression ? findRegExp(s) : findString(s);
205     }
206
207     public final boolean findDelimited(String JavaDoc s, Mode mode)
208     {
209         return regularExpression ? findRegExpDelimited(s, mode) : findStringDelimited(s, mode);
210     }
211
212     // Search is restricted to region if restrictToSelection is true and
213
// region is not null.
214
public final Position findString(Buffer buffer, Position start)
215     {
216         return findString(buffer.getMode(), start);
217     }
218
219     // Search is restricted to region if restrictToSelection is true and
220
// region is not null.
221
private Position findString(Mode mode, Position start)
222     {
223         Debug.assertTrue(lowerCasePattern.equals(pattern.toLowerCase()));
224         Debug.assertTrue(patternLength == pattern.length());
225         Line line = start.getLine();
226         int begin = start.getOffset();
227         Line endLine;
228         if (restrictToSelection && region != null)
229             endLine = region.getEndLine();
230         else
231             endLine = null;
232         Position pos = null;
233         while (line != endLine) {
234             pos = findStringInLine(mode, line, begin, line.length());
235             if (pos != null)
236                 return pos;
237             line = line.next();
238             begin = 0;
239         }
240         if (line != null) {
241             // End line of region.
242
pos = findStringInLine(mode, line, begin, region.getEnd().getOffset());
243         }
244         return pos;
245     }
246
247     // Region is ignored.
248
public Position findString(Buffer buffer, Position start, boolean wrapBuffer)
249     {
250         Debug.assertTrue(lowerCasePattern.equals(pattern.toLowerCase()));
251         Debug.assertTrue(patternLength == pattern.length());
252         Mode mode = buffer.getMode();
253         Line line = start.getLine();
254         int begin = start.getOffset();
255         while (line != null) {
256             Position pos = findStringInLine(mode, line, begin, line.length());
257             if (pos != null)
258                 return pos;
259             line = line.next();
260             begin = 0;
261         }
262         if (wrapBuffer) {
263             line = buffer.getFirstLine();
264             Line endLine = start.getNextLine();
265             while (line != endLine) {
266                 Position pos = findStringInLine(mode, line, 0, line.length());
267                 if (pos != null)
268                     return pos;
269                 line = line.next();
270             }
271         }
272         return null;
273     }
274
275     private Position findStringInLine(Mode mode, Line line, int begin, int end)
276     {
277         String JavaDoc toBeSearched;
278         if (end < line.length())
279             toBeSearched = line.substring(0, end);
280         else
281             toBeSearched = line.getText();
282         int index = begin;
283         int limit = end - patternLength;
284         while (index <= limit) {
285             if (ignoreCase)
286                 index = toBeSearched.toLowerCase().indexOf(lowerCasePattern, index);
287             else
288                 index = toBeSearched.indexOf(pattern, index);
289             if (index < 0)
290                 break;
291             Position pos = new Position(line, index);
292             if (!wholeWordsOnly || Utilities.isDelimited(mode, pos, patternLength))
293                 return pos;
294             ++index;
295         }
296         return null;
297     }
298
299     private boolean findString(String JavaDoc s)
300     {
301         Debug.assertTrue(patternLength == pattern.length());
302         int index = 0;
303         int limit = s.length() - patternLength;
304         while (index <= limit) {
305             if (ignoreCase)
306                 index = s.toLowerCase().indexOf(lowerCasePattern, index);
307             else
308                 index = s.indexOf(pattern, index);
309             if (index < 0)
310                 break;
311             if (!wholeWordsOnly || Utilities.isDelimited(s, index, patternLength))
312                 return true;
313             ++index;
314         }
315         return false;
316     }
317
318     private boolean findStringDelimited(String JavaDoc s, Mode mode)
319     {
320         Debug.assertTrue(wholeWordsOnly);
321         Debug.assertTrue(patternLength == pattern.length());
322         int index = 0;
323         int limit = s.length() - patternLength;
324         while (index <= limit) {
325             if (ignoreCase)
326                 index = s.toLowerCase().indexOf(lowerCasePattern, index);
327             else
328                 index = s.indexOf(pattern, index);
329             if (index < 0)
330                 break;
331             if (Utilities.isDelimited(s, index, patternLength, mode))
332                 return true;
333             ++index;
334         }
335         return false;
336     }
337
338     // Region is ignored.
339
public Position reverseFindString(Buffer buffer, Position start)
340     {
341         Debug.assertTrue(lowerCasePattern.equals(pattern.toLowerCase()));
342         Debug.assertTrue(patternLength == pattern.length());
343         Line line = start.getLine();
344         Position pos = reverseFindStringInLine(buffer, line, 0, start.getOffset());
345         if (pos != null)
346             return pos;
347         line = line.previous();
348         while (line != null) {
349             pos = reverseFindStringInLine(buffer, line, 0, line.length());
350             if (pos != null)
351                 return pos;
352             line = line.previous();
353         }
354         return null;
355     }
356
357     private Position reverseFindStringInLine(Buffer buffer, Line line, int begin, int end)
358     {
359         int index = end;
360         while (index >= begin) {
361             if (ignoreCase)
362                 index = line.getText().toLowerCase().lastIndexOf(lowerCasePattern, index);
363             else
364                 index = line.getText().lastIndexOf(pattern, index);
365             if (index < 0)
366                 break;
367             Position pos = new Position(line, index);
368             if (!wholeWordsOnly || Utilities.isDelimited(buffer, pos, patternLength))
369                 return pos;
370             --index;
371         }
372         return null;
373     }
374
375     // Search is restricted to region if restrictToSelection is true and
376
// region is not null.
377
public final Position findRegExp(Buffer buffer, Position start)
378     {
379         if (isMultilinePattern)
380             return findMultilineRegExp(buffer, start);
381         else
382             return findRegExp(buffer.getMode(), start);
383     }
384
385     public void setREFromPattern() throws REException
386     {
387         int cflags = 0;
388         if (isMultilinePattern)
389             cflags |= RE.REG_MULTILINE;
390         if (ignoreCase)
391             cflags |= RE.REG_ICASE;
392         re = new RE(pattern, cflags);
393     }
394
395     // Search is restricted to region if restrictToSelection is true and
396
// region is not null.
397
private Position findMultilineRegExp(Buffer buffer, Position start)
398     {
399         if (re == null) {
400             try {
401                 setREFromPattern();
402             }
403             catch (Throwable JavaDoc t) {
404                 Log.error(t);
405                 return null;
406             }
407         }
408         final String JavaDoc s = buffer.getText();
409         int startIndex = buffer.getAbsoluteOffset(start);
410         int endIndex = -1;
411         if (restrictToSelection && region != null)
412             endIndex = buffer.getAbsoluteOffset(region.getEnd());
413         while (true) {
414             match = findMatch(s, startIndex, endIndex);
415             if (match == null)
416                 return null;
417             if (!wholeWordsOnly)
418                 break;
419             if (Utilities.isDelimited(buffer.getMode(), s,
420                 match.getStartIndex(), match.getEndIndex()))
421                 break;
422             startIndex = match.getStartIndex() + 1;
423         }
424         return buffer.getPosition(match.getStartIndex());
425     }
426
427     private Position reverseFindMultilineRegExp(Buffer buffer, Position start)
428     {
429         if (re == null) {
430             try {
431                 setREFromPattern();
432             }
433             catch (Throwable JavaDoc t) {
434                 Log.error(t);
435                 return null;
436             }
437         }
438         int startIndex = 0;
439         int endIndex = buffer.getAbsoluteOffset(start);
440         final String JavaDoc s = buffer.getText().substring(0, endIndex);
441         REMatch lastMatch = null;
442         while (true) {
443             match = findMatch(s, startIndex, -1);
444             if (match == null)
445                 break;
446             if (!wholeWordsOnly)
447                 lastMatch = match;
448             else if (Utilities.isDelimited(buffer.getMode(), s,
449                                              match.getStartIndex(),
450                                              match.getEndIndex()))
451                 lastMatch = match;
452             startIndex = match.getStartIndex() + 1;
453         }
454         if (lastMatch == null)
455             return null;
456         match = lastMatch;
457         return buffer.getPosition(match.getStartIndex());
458     }
459
460     // Search is restricted to region if endIndex >= 0.
461
private REMatch findMatch(String JavaDoc s, int startIndex, int endIndex)
462     {
463         REMatch m = re.getMatch(s, startIndex);
464         if (m == null)
465             return null; // Not found at all.
466
if (endIndex >= 0 && m.getEndIndex() > endIndex)
467             return null; // Match extends past end of selected region.
468
return m;
469     }
470
471     // Search is restricted to region if restrictToSelection is true and
472
// region is not null.
473
private Position findRegExp(Mode mode, Position start)
474     {
475         if (re == null) {
476             try {
477                 setREFromPattern();
478             }
479             catch (Throwable JavaDoc t) {
480                 Log.error(t);
481                 return null;
482             }
483         }
484         match = null;
485         Line line = start.getLine();
486         int begin = start.getOffset();
487         Line endLine;
488         if (restrictToSelection && region != null)
489             endLine = region.getEndLine();
490         else
491             endLine = null;
492         Position pos = null;
493         while (line != endLine) {
494             pos = findRegExpInLine(mode, line, begin, line.length());
495             if (pos != null)
496                 return pos;
497             line = line.next();
498             begin = 0;
499         }
500         if (line != null) {
501             // End line of region.
502
pos = findRegExpInLine(mode, line, begin, region.getEndOffset());
503         }
504         return pos;
505     }
506
507     private Position findRegExpInLine(Mode mode, Line line, int begin, int end)
508     {
509         String JavaDoc toBeSearched;
510         if (end < line.length())
511             toBeSearched = line.substring(0, end);
512         else
513             toBeSearched = line.getText();
514         int index = begin;
515         int limit = toBeSearched.length();
516         while (index <= limit) {
517             match = re.getMatch(toBeSearched, index);
518             if (match == null)
519                 break;
520             Position pos = new Position(line, match.getStartIndex());
521             if (!wholeWordsOnly || Utilities.isDelimited(mode, pos, match.toString().length()))
522                 return pos;
523             index = match.getStartIndex() + 1;
524         }
525         return null;
526     }
527
528     private boolean findRegExp(String JavaDoc toBeSearched)
529     {
530         int index = 0;
531         int limit = toBeSearched.length();
532         while (index <= limit) {
533             match = re.getMatch(toBeSearched, index);
534             if (match == null)
535                 break;
536             if (!wholeWordsOnly || Utilities.isDelimited(toBeSearched, match.getStartIndex(), match.toString().length()))
537                 return true;
538             index = match.getStartIndex() + 1;
539         }
540         return false;
541     }
542
543     private boolean findRegExpDelimited(String JavaDoc s, Mode mode)
544     {
545         Debug.assertTrue(wholeWordsOnly);
546         int index = 0;
547         int limit = s.length();
548         while (index <= limit) {
549             match = re.getMatch(s, index);
550             if (match == null)
551                 break;
552             if (Utilities.isDelimited(s, match.getStartIndex(), match.toString().length(), mode))
553                 return true;
554             index = match.getStartIndex() + 1;
555         }
556         return false;
557     }
558
559     // Region is ignored.
560
public Position reverseFindRegExp(Buffer buffer, Position start)
561     {
562         if (re == null) {
563             try {
564                 re = new RE(pattern, ignoreCase ? RE.REG_ICASE : 0);
565             }
566             catch (Throwable JavaDoc t) {
567                 Log.error(t);
568                 return null;
569             }
570         }
571         Line line = start.getLine();
572         match = null;
573         Position pos = reverseFindRegExpInLine(buffer, line, 0, start.getOffset());
574         if (pos != null)
575             return pos;
576         line = line.previous();
577         while (line != null) {
578             pos = reverseFindRegExpInLine(buffer, line, 0, line.length());
579             if (pos != null)
580                 return pos;
581             line = line.previous();
582         }
583         return null;
584     }
585
586     private Position reverseFindRegExpInLine(Buffer buffer, Line line, int begin, int end)
587     {
588         int index = end;
589         while (index >= begin) {
590             match = re.getMatch(line.getText(), index);
591             if (match != null && match.getStartIndex() <= end) {
592                 Position pos = new Position(line, match.getStartIndex());
593                 if (!wholeWordsOnly || Utilities.isDelimited(buffer, pos, match.toString().length()))
594                     return pos;
595             }
596             --index;
597         }
598         return null;
599     }
600
601     public void notFound(Editor editor)
602     {
603         FastStringBuffer sb = new FastStringBuffer();
604         if (regularExpression)
605             sb.append("Regular expression ");
606         sb.append('"');
607         sb.append(pattern);
608         sb.append("\" not found");
609         editor.status(sb.toString());
610     }
611
612     public boolean equals(Object JavaDoc object)
613     {
614         if (this == object)
615             return true;
616         if (object instanceof Search) {
617             Search search = (Search) object;
618             if (pattern == null) {
619                 if (search.pattern != null)
620                     return false;
621             } else {
622                 // pattern != null
623
if (!pattern.equals(search.pattern))
624                     return false;
625             }
626             if (ignoreCase != search.ignoreCase)
627                 return false;
628             if (wholeWordsOnly != search.wholeWordsOnly)
629                 return false;
630             if (regularExpression != search.regularExpression)
631                 return false;
632             if (restrictToSelection != search.restrictToSelection)
633                 return false;
634             // Passed all tests.
635
return true;
636         }
637         return false;
638     }
639
640     public Object JavaDoc clone()
641     {
642         try {
643             return super.clone();
644         }
645         catch (CloneNotSupportedException JavaDoc e) {
646             throw new InternalError JavaDoc(e.toString());
647         }
648     }
649 }
650
Popular Tags