001: /*
002: * HyperSearchRequest.java - HyperSearch request, run in I/O thread
003: * :tabSize=8:indentSize=8:noTabs=false:
004: * :folding=explicit:collapseFolds=1:
005: *
006: * Copyright (C) 1998, 1999, 2000, 2001, 2002 Slava Pestov
007: *
008: * This program is free software; you can redistribute it and/or
009: * modify it under the terms of the GNU General Public License
010: * as published by the Free Software Foundation; either version 2
011: * of the License, or any later version.
012: *
013: * This program is distributed in the hope that it will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016: * GNU General Public License for more details.
017: *
018: * You should have received a copy of the GNU General Public License
019: * along with this program; if not, write to the Free Software
020: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
021: */
022:
023: package org.gjt.sp.jedit.search;
024:
025: //{{{ Imports
026: import javax.swing.text.Segment;
027: import javax.swing.tree.*;
028: import javax.swing.*;
029:
030: import org.gjt.sp.jedit.textarea.Selection;
031: import org.gjt.sp.jedit.textarea.JEditTextArea;
032: import org.gjt.sp.jedit.io.VFSManager;
033: import org.gjt.sp.jedit.Buffer;
034: import org.gjt.sp.jedit.GUIUtilities;
035: import org.gjt.sp.jedit.jEdit;
036: import org.gjt.sp.jedit.View;
037: import org.gjt.sp.util.*;
038:
039: //}}}
040:
041: /**
042: * HyperSearch results window.
043: * @author Slava Pestov
044: * @version $Id: HyperSearchRequest.java 10835 2007-10-07 19:13:47Z kpouer $
045: */
046: class HyperSearchRequest extends WorkRequest {
047: //{{{ HyperSearchRequest constructor
048: HyperSearchRequest(View view, SearchMatcher matcher,
049: HyperSearchResults results, Selection[] selection) {
050: this .view = view;
051: this .matcher = matcher;
052:
053: this .results = results;
054: searchString = SearchAndReplace.getSearchString();
055: rootSearchNode = new DefaultMutableTreeNode(
056: new HyperSearchOperationNode(searchString, matcher));
057:
058: this .selection = selection;
059: } //}}}
060:
061: //{{{ run() method
062: public void run() {
063: setStatus(jEdit.getProperty("hypersearch-status"));
064:
065: SearchFileSet fileset = SearchAndReplace.getSearchFileSet();
066: String[] files = fileset.getFiles(view);
067: if (files == null || files.length == 0) {
068: SwingUtilities.invokeLater(new Runnable() {
069: public void run() {
070: GUIUtilities.error(view, "empty-fileset", null);
071: results.searchDone(rootSearchNode);
072: }
073: });
074: return;
075: }
076:
077: setMaximum(fileset.getFileCount(view));
078:
079: // to minimise synchronization and stuff like that, we only
080: // show a status message at most twice a second
081:
082: // initially zero, so that we always show the first message
083: String searchingCaption = jEdit
084: .getProperty("hypersearch-results.searching") + ' ';
085: try {
086: if (selection != null) {
087: Buffer buffer = view.getBuffer();
088:
089: searchInSelection(buffer);
090: } else {
091: int current = 0;
092:
093: long lastStatusTime = 0;
094: int resultCount = 0;
095: boolean asked = false;
096: int maxResults = jEdit
097: .getIntegerProperty("hypersearch.maxWarningResults");
098: loop: for (int i = 0; i < files.length; i++) {
099: if (!asked && resultCount > maxResults
100: && maxResults != 0) {
101: Log
102: .log(
103: Log.DEBUG,
104: this ,
105: "Search in progress, "
106: + resultCount
107: + " occurrences found, asking the user to stop");
108: asked = true;
109: int ret = GUIUtilities.confirm(view,
110: "hypersearch.tooManyResults",
111: new Object[] { resultCount },
112: JOptionPane.YES_NO_OPTION,
113: JOptionPane.QUESTION_MESSAGE);
114: if (ret == JOptionPane.YES_OPTION) {
115: Log.log(Log.MESSAGE, this ,
116: "Search stopped by user action");
117: break;
118: }
119: }
120: String file = files[i];
121: current++;
122:
123: long currentTime = System.currentTimeMillis();
124: if (currentTime - lastStatusTime > 250) {
125: setValue(current);
126: lastStatusTime = currentTime;
127: results
128: .setSearchStatus(searchingCaption
129: + file);
130: }
131:
132: Buffer buffer = jEdit.openTemporary(null, null,
133: file, false);
134: if (buffer == null)
135: continue loop;
136:
137: resultCount += doHyperSearch(buffer, 0, buffer
138: .getLength());
139: }
140: Log.log(Log.MESSAGE, this , resultCount + " OCCURENCES");
141: }
142: } catch (final Exception e) {
143: Log.log(Log.ERROR, this , e);
144: SwingUtilities.invokeLater(new Runnable() {
145: public void run() {
146: SearchAndReplace.handleError(view, e);
147: }
148: });
149: } catch (WorkThread.Abort a) {
150: } finally {
151: VFSManager.runInAWTThread(new Runnable() {
152: public void run() {
153: results.searchDone(rootSearchNode, selectNode);
154: }
155: });
156: }
157: } //}}}
158:
159: //{{{ Private members
160:
161: //{{{ Instance variables
162: private View view;
163: private SearchMatcher matcher;
164: private HyperSearchResults results;
165: private DefaultMutableTreeNode rootSearchNode;
166: private Selection[] selection;
167: private String searchString;
168: private DefaultMutableTreeNode selectNode;
169:
170: //}}}
171:
172: //{{{ searchInSelection() method
173: private int searchInSelection(Buffer buffer) throws Exception {
174: setAbortable(false);
175:
176: int resultCount = 0;
177:
178: try {
179: buffer.readLock();
180:
181: for (int i = 0; i < selection.length; i++) {
182: Selection s = selection[i];
183: if (s instanceof Selection.Rect) {
184: for (int j = s.getStartLine(); j <= s.getEndLine(); j++) {
185: resultCount += doHyperSearch(buffer, s
186: .getStart(buffer, j), s.getEnd(buffer,
187: j));
188: }
189: } else {
190: resultCount += doHyperSearch(buffer, s.getStart(),
191: s.getEnd());
192: }
193: }
194: } finally {
195: buffer.readUnlock();
196: }
197:
198: setAbortable(true);
199:
200: return resultCount;
201: } //}}}
202:
203: //{{{ doHyperSearch() method
204: private int doHyperSearch(Buffer buffer, int start, int end)
205: throws Exception {
206: setAbortable(false);
207:
208: HyperSearchFileNode hyperSearchFileNode = new HyperSearchFileNode(
209: buffer.getPath());
210: DefaultMutableTreeNode bufferNode = new DefaultMutableTreeNode(
211: hyperSearchFileNode);
212:
213: int resultCount = doHyperSearch(buffer, start, end, bufferNode);
214: hyperSearchFileNode.setCount(resultCount);
215: if (resultCount != 0)
216: rootSearchNode.insert(bufferNode, rootSearchNode
217: .getChildCount());
218:
219: setAbortable(true);
220:
221: return resultCount;
222: } //}}}
223:
224: //{{{ doHyperSearch() method
225: private int doHyperSearch(Buffer buffer, int start, int end,
226: DefaultMutableTreeNode bufferNode) {
227: int resultCount = 0;
228: JEditTextArea textArea = jEdit.getActiveView().getTextArea();
229: int caretLine = textArea.getBuffer() == buffer ? textArea
230: .getCaretLine() : -1;
231: try {
232: buffer.readLock();
233:
234: boolean endOfLine = buffer.getLineEndOffset(buffer
235: .getLineOfOffset(end)) - 1 == end;
236:
237: Segment text = new Segment();
238: int offset = start;
239:
240: HyperSearchResult lastResult = null;
241:
242: loop: for (int counter = 0;; counter++) {
243: boolean startOfLine = buffer.getLineStartOffset(buffer
244: .getLineOfOffset(offset)) == offset;
245:
246: buffer.getText(offset, end - offset, text);
247: SearchMatcher.Match match = matcher.nextMatch(
248: new SegmentCharSequence(text, false),
249: startOfLine, endOfLine, counter == 0, false);
250: if (match == null)
251: break loop;
252:
253: int newLine = buffer.getLineOfOffset(offset
254: + match.start);
255: if (lastResult == null || lastResult.line != newLine) {
256: lastResult = new HyperSearchResult(buffer, newLine);
257: DefaultMutableTreeNode child = new DefaultMutableTreeNode(
258: lastResult, false);
259: if (lastResult.line == caretLine)
260: selectNode = child;
261: bufferNode.add(child);
262: }
263:
264: lastResult.addOccur(offset + match.start, offset
265: + match.end);
266:
267: offset += match.end;
268: if (matcher.isMatchingEOL()) {
269: if (offset < buffer.getLength())
270: offset += 1;
271: else
272: break loop;
273: }
274:
275: resultCount++;
276: }
277: } finally {
278: buffer.readUnlock();
279: }
280:
281: return resultCount;
282: } //}}}
283:
284: //}}}
285: }
|