/*
* HyperSearchRequest.java - HyperSearch request, run in I/O thread
* :tabSize=4:indentSize=4:noTabs=false:
* :folding=explicit:collapseFolds=1:
*
* Copyright (C) 1998, 1999, 2000, 2001, 2002 Slava Pestov
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.gjt.sp.jedit.search;
//{{{ Imports
import javax.swing.tree.*;
import javax.swing.*;
import org.gjt.sp.jedit.textarea.Selection;
import org.gjt.sp.jedit.textarea.JEditTextArea;
import org.gjt.sp.jedit.Buffer;
import org.gjt.sp.jedit.GUIUtilities;
import org.gjt.sp.jedit.jEdit;
import org.gjt.sp.jedit.View;
import org.gjt.sp.util.*;
//}}}
/**
* HyperSearch results window.
* @author Slava Pestov
* @version $Id: HyperSearchRequest.java 23224 2013-09-30 20:51:42Z shlomy $
*/
class HyperSearchRequest extends Task
{
//{{{ HyperSearchRequest constructor
HyperSearchRequest(View view, SearchMatcher matcher,
HyperSearchResults results, Selection[] selection)
{
this.view = view;
this.matcher = matcher;
this.results = results;
searchString = SearchAndReplace.getSearchString();
rootSearchNode = new DefaultMutableTreeNode(new HyperSearchOperationNode(searchString, matcher));
this.selection = selection;
} //}}}
//{{{ run() method
@Override
public void _run()
{
setStatus(jEdit.getProperty("hypersearch-status"));
SearchFileSet fileset = SearchAndReplace.getSearchFileSet();
String[] files = fileset.getFiles(view);
if(files == null || files.length == 0)
{
ThreadUtilities.runInDispatchThread(new Runnable()
{
public void run()
{
GUIUtilities.error(view,"empty-fileset",null);
results.searchDone(rootSearchNode);
}
});
return;
}
setMaximum(fileset.getFileCount(view));
// to minimize synchronization and stuff like that, we only
// show a status message at most twice a second
// initially zero, so that we always show the first message
String searchingCaption = jEdit.getProperty("hypersearch-results.searching",
new String[] { SearchAndReplace.getSearchString() }) + ' ';
try
{
if(selection != null)
{
Buffer buffer = view.getBuffer();
searchInSelection(buffer);
}
else
{
int current = 0;
long lastStatusTime = 0L;
int resultCount = 0;
boolean asked = false;
int maxResults = jEdit.getIntegerProperty("hypersearch.maxWarningResults");
for(int i = 0; i < files.length; i++)
{
if(Thread.currentThread().isInterrupted())
{
Log.log(Log.MESSAGE, this, "Search stopped by user action (stop button)");
break;
}
if (!asked && resultCount > maxResults && maxResults != 0)
{
Log.log(Log.DEBUG, this, "Search in progress, " + resultCount +
" occurrences found, asking the user to stop");
asked = true;
int ret = GUIUtilities.confirm(view, "hypersearch.tooManyResults",
new Object[]{resultCount},
JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE);
if (ret == JOptionPane.YES_OPTION)
{
Log.log(Log.MESSAGE, this, "Search stopped by user action");
break;
}
}
String file = files[i];
current++;
long currentTime = System.currentTimeMillis();
if(currentTime - lastStatusTime > 250L)
{
setValue(current);
lastStatusTime = currentTime;
results.setSearchStatus(searchingCaption + file);
}
Buffer buffer = jEdit.openTemporary(null,null,file,false);
if(buffer != null)
{
// Wait for the buffer to load
if(!buffer.isLoaded())
TaskManager.instance.waitForIoTasks();
resultCount += doHyperSearch(buffer, 0, buffer.getLength());
}
}
Log.log(Log.MESSAGE, this, resultCount +" OCCURENCES");
}
}
catch(final Exception e)
{
Log.log(Log.ERROR,this,e);
ThreadUtilities.runInDispatchThread(new Runnable()
{
public void run()
{
SearchAndReplace.handleError(view,e);
}
});
}
finally
{
ThreadUtilities.runInDispatchThread(new Runnable()
{
public void run()
{
results.searchDone(rootSearchNode, selectNode);
}
});
}
} //}}}
//{{{ Private members
//{{{ Instance variables
private final View view;
private final SearchMatcher matcher;
private final HyperSearchResults results;
private final DefaultMutableTreeNode rootSearchNode;
private final Selection[] selection;
private final String searchString;
private DefaultMutableTreeNode selectNode;
//}}}
//{{{ searchInSelection() method
private int searchInSelection(Buffer buffer) throws Exception
{
setCancellable(false);
int resultCount = 0;
try
{
buffer.readLock();
for (Selection s : selection)
{
if (s instanceof Selection.Rect)
{
for (int j = s.getStartLine(); j <= s.getEndLine(); j++)
{
resultCount += doHyperSearch(buffer, s.getStart(buffer, j),
s.getEnd(buffer, j));
}
}
else
{
resultCount += doHyperSearch(buffer, s.getStart(), s.getEnd());
}
}
}
finally
{
buffer.readUnlock();
}
setCancellable(true);
return resultCount;
} //}}}
//{{{ doHyperSearch() method
private int doHyperSearch(Buffer buffer, int start, int end)
throws Exception
{
if(matcher instanceof BoyerMooreSearchMatcher)
setCancellable(true);
else
setCancellable(false);
HyperSearchFileNode hyperSearchFileNode = new HyperSearchFileNode(buffer.getPath());
DefaultMutableTreeNode bufferNode = new DefaultMutableTreeNode(hyperSearchFileNode);
int resultCount = doHyperSearch(buffer,start,end,bufferNode);
hyperSearchFileNode.setCount(resultCount);
if(resultCount != 0)
rootSearchNode.insert(bufferNode,rootSearchNode.getChildCount());
setCancellable(true);
return resultCount;
} //}}}
//{{{ doHyperSearch() method
private int doHyperSearch(Buffer buffer, int start, int end,
DefaultMutableTreeNode bufferNode)
{
if(matcher.wholeWord)
{
buffer.setMode();
String noWordSep = buffer.getStringProperty("noWordSep");
matcher.setNoWordSep(noWordSep);
}
int resultCount = 0;
JEditTextArea textArea = jEdit.getActiveView().getTextArea();
int caretLine = textArea.getBuffer() == buffer ? textArea.getCaretLine() : -1;
try
{
buffer.readLock();
boolean endOfLine = buffer.getLineEndOffset(
buffer.getLineOfOffset(end)) - 1 == end;
int offset = start;
HyperSearchResult lastResult = null;
for(int counter = 0; ; counter++)
{
boolean startOfLine = buffer.getLineStartOffset(
buffer.getLineOfOffset(offset)) == offset;
SearchMatcher.Match match = null;
try {
match = matcher.nextMatch(
buffer.getSegment(offset, end - offset),
startOfLine,endOfLine,counter == 0,
false);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
if(match == null)
break;
int newLine = buffer.getLineOfOffset(
offset + match.start);
if(lastResult == null || lastResult.line != newLine)
{
lastResult = new HyperSearchResult(
buffer,newLine);
DefaultMutableTreeNode child = new DefaultMutableTreeNode(
lastResult, false);
if (lastResult.line == caretLine)
selectNode = child;
bufferNode.add(child);
}
lastResult.addOccur(offset + match.start,
offset + match.end);
offset += match.end;
resultCount++;
}
}
finally
{
buffer.readUnlock();
}
return resultCount;
} //}}}
//}}}
}