[NEW_FEATURE] Enhance "Find in all opened files" and "Find in files" features.
git-svn-id: svn://svn.tuxfamily.org/svnroot/notepadplus/repository@410 f5eea248-9336-0410-98b8-ebc06183d4e3
This commit is contained in:
parent
7d2eb78375
commit
7705e0b571
|
@ -268,6 +268,38 @@ const wchar_t * WcharMbcsConvertor::char2wchar(const char * mbcs2Convert, UINT c
|
|||
return _wideCharStr;
|
||||
}
|
||||
|
||||
// "mstart" and "mend" are pointers to indexes in mbcs2Convert,
|
||||
// which are converted to the corresponding indexes in the returned wchar_t string.
|
||||
const wchar_t * WcharMbcsConvertor::char2wchar(const char * mbcs2Convert, UINT codepage, int *mstart, int *mend)
|
||||
{
|
||||
if (!_wideCharStr)
|
||||
{
|
||||
_wideCharStr = new wchar_t[initSize];
|
||||
_wideCharAllocLen = initSize;
|
||||
}
|
||||
|
||||
int len = MultiByteToWideChar(codepage, 0, mbcs2Convert, -1, _wideCharStr, 0);
|
||||
if (len > 0)
|
||||
{
|
||||
if (len > int(_wideCharAllocLen))
|
||||
{
|
||||
delete [] _wideCharStr;
|
||||
_wideCharAllocLen = len;
|
||||
_wideCharStr = new wchar_t[_wideCharAllocLen];
|
||||
}
|
||||
MultiByteToWideChar(codepage, 0, mbcs2Convert, -1, _wideCharStr, len);
|
||||
*mstart = MultiByteToWideChar(codepage, 0, mbcs2Convert, *mstart, _wideCharStr, 0);
|
||||
*mend = MultiByteToWideChar(codepage, 0, mbcs2Convert, *mend, _wideCharStr, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
_wideCharStr[0] = 0;
|
||||
*mstart = 0;
|
||||
*mend = 0;
|
||||
}
|
||||
return _wideCharStr;
|
||||
}
|
||||
|
||||
const char * WcharMbcsConvertor::wchar2char(const wchar_t * wcharStr2Convert, UINT codepage)
|
||||
{
|
||||
if (!_multiByteStr)
|
||||
|
|
|
@ -107,6 +107,7 @@ public:
|
|||
static void destroyInstance() {delete _pSelf;};
|
||||
|
||||
const wchar_t * char2wchar(const char* mbStr, UINT codepage);
|
||||
const wchar_t * char2wchar(const char * mbcs2Convert, UINT codepage, int *mstart, int *mend);
|
||||
const char * wchar2char(const wchar_t* wcStr, UINT codepage);
|
||||
|
||||
protected:
|
||||
|
|
|
@ -1426,9 +1426,9 @@ bool Notepad_plus::replaceAllFiles() {
|
|||
if (nbTotal < 0)
|
||||
lstrcpy(result, TEXT("The regular expression to search is formed badly"));
|
||||
else
|
||||
wsprintf(result, TEXT("%d occurrences were replaced."), nbTotal);
|
||||
wsprintf(result, TEXT("%d occurrences replaced."), nbTotal);
|
||||
|
||||
::MessageBox(_hSelf, result, TEXT(""), MB_OK);
|
||||
::printStr(result);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1570,6 +1570,12 @@ DWORD WINAPI AsyncCancelFindInFiles(LPVOID NppHWND)
|
|||
|
||||
bool Notepad_plus::replaceInFiles()
|
||||
{
|
||||
const TCHAR *dir2Search = _findReplaceDlg.getDir2Search();
|
||||
if (!dir2Search[0] || !::PathFileExists(dir2Search))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isRecursive = _findReplaceDlg.isRecursive();
|
||||
bool isInHiddenDir = _findReplaceDlg.isInHiddenDir();
|
||||
int nbTotal = 0;
|
||||
|
@ -1577,15 +1583,9 @@ bool Notepad_plus::replaceInFiles()
|
|||
ScintillaEditView *pOldView = _pEditView;
|
||||
_pEditView = &_invisibleEditView;
|
||||
Document oldDoc = _invisibleEditView.execute(SCI_GETDOCPOINTER);
|
||||
|
||||
const TCHAR *dir2Search = _findReplaceDlg.getDir2Search();
|
||||
|
||||
if (!dir2Search[0] || !::PathFileExists(dir2Search))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
HANDLE CancelThreadHandle = ::CreateThread(NULL, 0, AsyncCancelFindInFiles, _hSelf, 0, NULL);
|
||||
Buffer * oldBuf = _invisibleEditView.getCurrentBuffer(); //for manually setting the buffer, so notifications can be handled properly
|
||||
Buffer * pBuf = NULL;
|
||||
HANDLE CancelThreadHandle = NULL;
|
||||
|
||||
vector<generic_string> patterns2Match;
|
||||
if (_findReplaceDlg.getFilters() == TEXT(""))
|
||||
|
@ -1595,6 +1595,9 @@ bool Notepad_plus::replaceInFiles()
|
|||
|
||||
getMatchedFileNames(dir2Search, patterns2Match, fileNames, isRecursive, isInHiddenDir);
|
||||
|
||||
if (fileNames.size() > 1)
|
||||
CancelThreadHandle = ::CreateThread(NULL, 0, AsyncCancelFindInFiles, _hSelf, 0, NULL);
|
||||
|
||||
bool dontClose = false;
|
||||
for (size_t i = 0 ; i < fileNames.size() ; i++)
|
||||
{
|
||||
|
@ -1617,6 +1620,7 @@ bool Notepad_plus::replaceInFiles()
|
|||
Buffer * pBuf = MainFileManager->getBufferByID(id);
|
||||
_invisibleEditView.execute(SCI_SETDOCPOINTER, 0, pBuf->getDocument());
|
||||
_invisibleEditView.execute(SCI_SETCODEPAGE, pBuf->getUnicodeMode() == uni8Bit ? 0 : SC_CP_UTF8);
|
||||
_invisibleEditView._currentBuffer = pBuf;
|
||||
|
||||
int nbReplaced = _findReplaceDlg.processAll(ProcessReplaceAll, NULL, NULL, true, fileNames.at(i).c_str());
|
||||
nbTotal += nbReplaced;
|
||||
|
@ -1630,9 +1634,11 @@ bool Notepad_plus::replaceInFiles()
|
|||
}
|
||||
}
|
||||
|
||||
TerminateThread(CancelThreadHandle, 0);
|
||||
if (CancelThreadHandle)
|
||||
TerminateThread(CancelThreadHandle, 0);
|
||||
|
||||
_invisibleEditView.execute(SCI_SETDOCPOINTER, 0, oldDoc);
|
||||
_invisibleEditView._currentBuffer = oldBuf;
|
||||
_pEditView = pOldView;
|
||||
|
||||
TCHAR msg[128];
|
||||
|
@ -1644,17 +1650,6 @@ bool Notepad_plus::replaceInFiles()
|
|||
|
||||
bool Notepad_plus::findInFiles()
|
||||
{
|
||||
bool isRecursive = _findReplaceDlg.isRecursive();
|
||||
bool isInHiddenDir = _findReplaceDlg.isInHiddenDir();
|
||||
int nbTotal = 0;
|
||||
|
||||
ScintillaEditView *pOldView = _pEditView;
|
||||
_pEditView = &_invisibleEditView;
|
||||
Document oldDoc = _invisibleEditView.execute(SCI_GETDOCPOINTER);
|
||||
|
||||
if (!_findReplaceDlg.isFinderEmpty())
|
||||
_findReplaceDlg.clearFinder();
|
||||
|
||||
const TCHAR *dir2Search = _findReplaceDlg.getDir2Search();
|
||||
|
||||
if (!dir2Search[0] || !::PathFileExists(dir2Search))
|
||||
|
@ -1662,7 +1657,13 @@ bool Notepad_plus::findInFiles()
|
|||
return false;
|
||||
}
|
||||
|
||||
HANDLE CancelThreadHandle = ::CreateThread(NULL, 0, AsyncCancelFindInFiles, _hSelf, 0, NULL);
|
||||
bool isRecursive = _findReplaceDlg.isRecursive();
|
||||
bool isInHiddenDir = _findReplaceDlg.isInHiddenDir();
|
||||
int nbTotal = 0;
|
||||
ScintillaEditView *pOldView = _pEditView;
|
||||
_pEditView = &_invisibleEditView;
|
||||
Document oldDoc = _invisibleEditView.execute(SCI_GETDOCPOINTER);
|
||||
HANDLE CancelThreadHandle = NULL;
|
||||
|
||||
vector<generic_string> patterns2Match;
|
||||
if (_findReplaceDlg.getFilters() == TEXT(""))
|
||||
|
@ -1670,15 +1671,12 @@ bool Notepad_plus::findInFiles()
|
|||
_findReplaceDlg.getPatterns(patterns2Match);
|
||||
vector<generic_string> fileNames;
|
||||
|
||||
_findReplaceDlg.putFindResultStr(TEXT("Scanning files to search..."));
|
||||
_findReplaceDlg.refresh();
|
||||
|
||||
getMatchedFileNames(dir2Search, patterns2Match, fileNames, isRecursive, isInHiddenDir);
|
||||
|
||||
TCHAR msg[128];
|
||||
wsprintf(msg, TEXT("Found %d matching files"), fileNames.size());
|
||||
_findReplaceDlg.putFindResultStr((const TCHAR*)msg);
|
||||
_findReplaceDlg.refresh();
|
||||
if (fileNames.size() > 1)
|
||||
CancelThreadHandle = ::CreateThread(NULL, 0, AsyncCancelFindInFiles, _hSelf, 0, NULL);
|
||||
|
||||
_findReplaceDlg.beginNewFilesSearch();
|
||||
|
||||
bool dontClose = false;
|
||||
for (size_t i = 0 ; i < fileNames.size() ; i++)
|
||||
|
@ -1703,25 +1701,22 @@ bool Notepad_plus::findInFiles()
|
|||
_invisibleEditView.execute(SCI_SETDOCPOINTER, 0, pBuf->getDocument());
|
||||
_invisibleEditView.execute(SCI_SETCODEPAGE, pBuf->getUnicodeMode() == uni8Bit ? 0 : SC_CP_UTF8);
|
||||
|
||||
generic_string str = TEXT("File: ");
|
||||
str += fileNames.at(i);
|
||||
_findReplaceDlg.putFindResultStr(str.c_str());
|
||||
|
||||
nbTotal += _findReplaceDlg.processAll(ProcessFindAll, NULL, NULL, true, fileNames.at(i).c_str());
|
||||
if (!dontClose)
|
||||
MainFileManager->closeBuffer(id, _pEditView);
|
||||
}
|
||||
}
|
||||
|
||||
TerminateThread(CancelThreadHandle, 0);
|
||||
if (CancelThreadHandle)
|
||||
TerminateThread(CancelThreadHandle, 0);
|
||||
|
||||
_findReplaceDlg.finishFilesSearch(nbTotal);
|
||||
|
||||
_invisibleEditView.execute(SCI_SETDOCPOINTER, 0, oldDoc);
|
||||
_pEditView = pOldView;
|
||||
|
||||
wsprintf(msg, TEXT("%d hits"), nbTotal);
|
||||
_findReplaceDlg.putFindResultStr((const TCHAR *)&msg);
|
||||
_findReplaceDlg.refresh();
|
||||
|
||||
_findReplaceDlg.putFindResult(nbTotal);
|
||||
if (nbTotal) _findReplaceDlg.display(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1737,10 +1732,7 @@ bool Notepad_plus::findInOpenedFiles()
|
|||
|
||||
const bool isEntireDoc = true;
|
||||
|
||||
if (!_findReplaceDlg.isFinderEmpty())
|
||||
_findReplaceDlg.clearFinder();
|
||||
|
||||
_findReplaceDlg.setSearchWord2Finder();
|
||||
_findReplaceDlg.beginNewFilesSearch();
|
||||
|
||||
if (_mainWindowStatus & WindowMainActive)
|
||||
{
|
||||
|
@ -1764,10 +1756,13 @@ bool Notepad_plus::findInOpenedFiles()
|
|||
}
|
||||
}
|
||||
|
||||
_findReplaceDlg.finishFilesSearch(nbTotal);
|
||||
|
||||
_invisibleEditView.execute(SCI_SETDOCPOINTER, 0, oldDoc);
|
||||
_pEditView = pOldView;
|
||||
|
||||
_findReplaceDlg.putFindResult(nbTotal);
|
||||
if (nbTotal) _findReplaceDlg.display(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -7079,8 +7074,7 @@ LRESULT Notepad_plus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPa
|
|||
|
||||
case WM_FINDINFILES :
|
||||
{
|
||||
findInFiles();
|
||||
return TRUE;
|
||||
return findInFiles();
|
||||
}
|
||||
|
||||
case WM_REPLACEINFILES :
|
||||
|
|
|
@ -318,7 +318,7 @@ BEGIN
|
|||
MENUITEM SEPARATOR
|
||||
MENUITEM "Go to another view", IDM_VIEW_GOTO_ANOTHER_VIEW
|
||||
MENUITEM "Clone to another view", IDM_VIEW_CLONE_TO_ANOTHER_VIEW
|
||||
MENUITEM "Focus on other view", IDM_VIEW_SWITCHTO_OTHER_VIEW // working, but no need in menu
|
||||
MENUITEM "Focus on other view", IDM_VIEW_SWITCHTO_OTHER_VIEW
|
||||
MENUITEM "Go to new instance", IDM_VIEW_GOTO_NEW_INSTANCE
|
||||
MENUITEM "Open in new instance", IDM_VIEW_LOAD_IN_NEW_INSTANCE
|
||||
MENUITEM SEPARATOR
|
||||
|
|
|
@ -147,6 +147,8 @@ void Searching::displaySectionCentered(int posStart, int posEnd, ScintillaEditVi
|
|||
pEditView->execute(SCI_SETANCHOR, posStart);
|
||||
}
|
||||
|
||||
LONG FindReplaceDlg::originalFinderProc = NULL;
|
||||
|
||||
void FindReplaceDlg::addText2Combo(const TCHAR * txt2add, HWND hCombo, bool isUTF8)
|
||||
{
|
||||
if (!hCombo) return;
|
||||
|
@ -378,87 +380,154 @@ void FindReplaceDlg::updateCombos()
|
|||
updateCombo(IDFINDWHAT);
|
||||
}
|
||||
|
||||
FoundInfo Finder::EmptyFoundInfo(0, 0, TEXT(""));
|
||||
SearchResultMarking Finder::EmptySearchResultMarking;
|
||||
|
||||
bool Finder::notify(SCNotification *notification)
|
||||
{
|
||||
switch (notification->nmhdr.code)
|
||||
{
|
||||
case SCN_MARGINCLICK:
|
||||
{
|
||||
if (notification->margin == ScintillaEditView::_SC_MARGE_FOLDER)
|
||||
{
|
||||
_scintView.marginClick(notification->position, notification->modifiers);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SCN_DOUBLECLICK :
|
||||
{
|
||||
try {
|
||||
int currentPos = _scintView.execute(SCI_GETCURRENTPOS);
|
||||
if (currentPos)
|
||||
{
|
||||
TCHAR prevChar = (TCHAR)_scintView.execute(SCI_GETCHARAT, currentPos - 1);
|
||||
if (prevChar == 0x0A)
|
||||
currentPos -= 2;
|
||||
}
|
||||
case SCN_DOUBLECLICK:
|
||||
// remove selection from the finder
|
||||
int pos = notification->position;
|
||||
if (pos == INVALID_POSITION)
|
||||
pos = _scintView.execute(SCI_GETLINEENDPOSITION, notification->line);
|
||||
_scintView.execute(SCI_SETSEL, pos, pos);
|
||||
|
||||
GotoFoundLine();
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Finder::GotoFoundLine()
|
||||
{
|
||||
int currentPos = _scintView.execute(SCI_GETCURRENTPOS);
|
||||
int lno = _scintView.execute(SCI_LINEFROMPOSITION, currentPos);
|
||||
int start = _scintView.execute(SCI_POSITIONFROMLINE, lno);
|
||||
int end = _scintView.execute(SCI_GETLINEENDPOSITION, lno);
|
||||
if (start + 2 >= end) return; // avoid empty lines
|
||||
|
||||
if (_scintView.execute(SCI_GETFOLDLEVEL, lno) & SC_FOLDLEVELHEADERFLAG)
|
||||
{
|
||||
_scintView.execute(SCI_TOGGLEFOLD, lno);
|
||||
_scintView.execute(SCI_SETCURRENTPOS, start);
|
||||
_scintView.execute(SCI_SETANCHOR, start);
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
// in getInfo() method the previous line is renew as current for next call
|
||||
const FoundInfo &fInfo = getInfo(lno);
|
||||
const FoundInfo fInfo = *(_pMainFoundInfos->begin() + lno);
|
||||
|
||||
int markedLine = getCurrentMarkedLine();
|
||||
|
||||
// now we clean the previous mark
|
||||
if (markedLine != -1)
|
||||
(*_ppEditView)->execute(SCI_MARKERDELETE, markedLine, MARK_BOOKMARK);
|
||||
|
||||
// After cleaning the previous mark, we can swich to another document
|
||||
|
||||
int cmd = getMode()==FILES_IN_DIR?WM_DOOPEN:NPPM_SWITCHTOFILE;
|
||||
|
||||
::SendMessage(::GetParent(_hParent), cmd, 0, (LPARAM)fInfo._fullPath.c_str());
|
||||
// Switch to another document
|
||||
::SendMessage(::GetParent(_hParent), WM_DOOPEN, 0, (LPARAM)fInfo._fullPath.c_str());
|
||||
Searching::displaySectionCentered(fInfo._start, fInfo._end, *_ppEditView);
|
||||
|
||||
// we set the current mark here
|
||||
int nb = (*_ppEditView)->getCurrentLineNumber();
|
||||
setCurrentMarkedLine(nb);
|
||||
(*_ppEditView)->execute(SCI_MARKERADD, nb, MARK_BOOKMARK);
|
||||
|
||||
// Then we colourise the double clicked line
|
||||
setFinderStyle();
|
||||
_scintView.showMargin(ScintillaEditView::_SC_MARGE_FOLDER, true);
|
||||
_scintView.execute(SCI_SETLEXER, SCLEX_NULL);
|
||||
_scintView.execute(SCI_STYLESETEOLFILLED, SCE_SEARCHRESULT_KWORD3, true);
|
||||
|
||||
//
|
||||
_scintView.execute(SCI_SETLEXER, SCLEX_NULL); // yuval - this line causes a bug!!! (last line suddenly belongs to file level header instead of having level=0x400)
|
||||
// later it affects DeleteResult and gotoNextFoundResult (assertions)!!
|
||||
_scintView.execute(SCI_STYLESETEOLFILLED, SCE_SEARCHRESULT_HIGHLIGHT_LINE, true);
|
||||
_scintView.execute(SCI_STARTSTYLING, start, STYLING_MASK);
|
||||
_scintView.execute(SCI_SETSTYLING, end - start + 2, SCE_SEARCHRESULT_KWORD3);
|
||||
_scintView.execute(SCI_SETSTYLING, end - start + 2, SCE_SEARCHRESULT_HIGHLIGHT_LINE);
|
||||
_scintView.execute(SCI_COLOURISE, start, end + 1);
|
||||
_scintView.execute(SCI_SETCURRENTPOS, start);
|
||||
_scintView.execute(SCI_SETANCHOR, start);
|
||||
return true;
|
||||
}
|
||||
|
||||
} catch(...){
|
||||
printStr(TEXT("SCN_DOUBLECLICK problem"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
void Finder::DeleteResult()
|
||||
{
|
||||
int currentPos = _scintView.execute(SCI_GETCURRENTPOS); // yniq - add handling deletion of multiple lines?
|
||||
|
||||
default :
|
||||
break;
|
||||
int lno = _scintView.execute(SCI_LINEFROMPOSITION, currentPos);
|
||||
int start = _scintView.execute(SCI_POSITIONFROMLINE, lno);
|
||||
int end = _scintView.execute(SCI_GETLINEENDPOSITION, lno);
|
||||
if (start + 2 >= end) return; // avoid empty lines
|
||||
|
||||
if (_scintView.execute(SCI_GETFOLDLEVEL, lno) & SC_FOLDLEVELHEADERFLAG) // delete a folder
|
||||
{
|
||||
int endline = _scintView.execute(SCI_GETLASTCHILD, lno, -1) + 1;
|
||||
assert((size_t) endline <= _pMainFoundInfos->size());
|
||||
|
||||
_pMainFoundInfos->erase(_pMainFoundInfos->begin() + lno, _pMainFoundInfos->begin() + endline); // remove found info
|
||||
_pMainMarkings->erase(_pMainMarkings->begin() + lno, _pMainMarkings->begin() + endline);
|
||||
|
||||
int end = _scintView.execute(SCI_POSITIONFROMLINE, endline);
|
||||
_scintView.execute(SCI_SETSEL, start, end);
|
||||
setFinderReadOnly(false);
|
||||
_scintView.execute(SCI_CLEAR);
|
||||
setFinderReadOnly(true);
|
||||
}
|
||||
else // delete one line
|
||||
{
|
||||
assert((size_t) lno < _pMainFoundInfos->size());
|
||||
|
||||
_pMainFoundInfos->erase(_pMainFoundInfos->begin() + lno); // remove found info
|
||||
_pMainMarkings->erase(_pMainMarkings->begin() + lno);
|
||||
|
||||
setFinderReadOnly(false);
|
||||
_scintView.execute(SCI_LINEDELETE);
|
||||
setFinderReadOnly(true);
|
||||
}
|
||||
_MarkingsStruct._length = _pMainMarkings->size();
|
||||
|
||||
assert(_pMainFoundInfos->size() == _pMainMarkings->size());
|
||||
assert(_scintView.execute(SCI_GETLINECOUNT) == _pMainFoundInfos->size() + 1);
|
||||
}
|
||||
|
||||
void Finder::gotoNextFoundResult(int direction)
|
||||
{
|
||||
int increment = direction < 0 ? -1 : 1;
|
||||
int currentPos = _scintView.execute(SCI_GETCURRENTPOS);
|
||||
int lno = _scintView.execute(SCI_LINEFROMPOSITION, currentPos);
|
||||
int total_lines = _scintView.execute(SCI_GETLINECOUNT);
|
||||
if (total_lines <= 1) return;
|
||||
|
||||
if (lno == total_lines - 1) lno--; // last line doesn't belong to any search, use last search
|
||||
|
||||
int init_lno = lno;
|
||||
int max_lno = _scintView.execute(SCI_GETLASTCHILD, lno, searchHeaderLevel);
|
||||
|
||||
assert(max_lno <= total_lines - 2);
|
||||
|
||||
// get the line number of the current search (searchHeaderLevel)
|
||||
int level = _scintView.execute(SCI_GETFOLDLEVEL, lno) & SC_FOLDLEVELNUMBERMASK;
|
||||
int min_lno = lno;
|
||||
while (level-- >= fileHeaderLevel)
|
||||
{
|
||||
min_lno = _scintView.execute(SCI_GETFOLDPARENT, min_lno);
|
||||
assert(min_lno >= 0);
|
||||
}
|
||||
|
||||
if (min_lno < 0) min_lno = lno; // when lno is a search header line // yuval - remove this?
|
||||
|
||||
assert(min_lno <= max_lno);
|
||||
|
||||
lno += increment;
|
||||
|
||||
if (lno > max_lno) lno = min_lno;
|
||||
else if (lno < min_lno) lno = max_lno;
|
||||
|
||||
while (_scintView.execute(SCI_GETFOLDLEVEL, lno) & SC_FOLDLEVELHEADERFLAG)
|
||||
{
|
||||
lno += increment;
|
||||
if (lno > max_lno) lno = min_lno;
|
||||
else if (lno < min_lno) lno = max_lno;
|
||||
if (lno == init_lno) break;
|
||||
}
|
||||
|
||||
if ((_scintView.execute(SCI_GETFOLDLEVEL, lno) & SC_FOLDLEVELHEADERFLAG) == 0)
|
||||
{
|
||||
int start = _scintView.execute(SCI_POSITIONFROMLINE, lno);
|
||||
_scintView.execute(SCI_SETSEL, start, start);
|
||||
_scintView.execute(SCI_ENSUREVISIBLE, lno);
|
||||
_scintView.execute(SCI_SCROLLCARET);
|
||||
|
||||
GotoFoundLine();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -861,6 +930,7 @@ BOOL CALLBACK FindReplaceDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM lP
|
|||
default :
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
|
@ -1219,7 +1289,10 @@ int FindReplaceDlg::processRange(ProcessOperation op, const TCHAR *txt2find, con
|
|||
if (nbChar > 1024 - 3)
|
||||
lend = lstart + 1020;
|
||||
|
||||
(*_ppEditView)->getGenericText(lineBuf, lstart, lend);
|
||||
int start_mark = targetStart - lstart;
|
||||
int end_mark = targetEnd - lstart;
|
||||
|
||||
(*_ppEditView)->getGenericText(lineBuf, lstart, lend, &start_mark, &end_mark);
|
||||
generic_string line;
|
||||
#ifdef UNICODE
|
||||
line = lineBuf;
|
||||
|
@ -1236,7 +1309,10 @@ int FindReplaceDlg::processRange(ProcessOperation op, const TCHAR *txt2find, con
|
|||
line = lineBuf;
|
||||
#endif
|
||||
line += TEXT("\r\n");
|
||||
_pFinder->add(FoundInfo(targetStart, targetEnd, line.c_str(), fileName, _pFinder->_lineCounter), lineNumber + 1);
|
||||
SearchResultMarking srm;
|
||||
srm._start = start_mark;
|
||||
srm._end = end_mark;
|
||||
_pFinder->add(FoundInfo(targetStart, targetEnd, fileName), srm, line.c_str(), lineNumber + 1);
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -1312,6 +1388,9 @@ int FindReplaceDlg::processRange(ProcessOperation op, const TCHAR *txt2find, con
|
|||
delete [] pTextFind;
|
||||
delete [] pTextReplace;
|
||||
|
||||
if (nbProcessed > 0 && op == ProcessFindAll)
|
||||
_pFinder->addFileHitCount(nbProcessed);
|
||||
|
||||
return nbProcessed;
|
||||
}
|
||||
|
||||
|
@ -1329,7 +1408,8 @@ void FindReplaceDlg::findAllIn(InWhat op)
|
|||
_pFinder->init(_hInst, _hSelf, _ppEditView);
|
||||
|
||||
tTbData data = {0};
|
||||
_pFinder->create(&data);
|
||||
_pFinder->create(&data, false);
|
||||
::SendMessage(_hParent, NPPM_MODELESSDIALOG, MODELESSDIALOGREMOVE, (WPARAM)_pFinder->getHSelf());
|
||||
// define the default docking behaviour
|
||||
data.uMask = DWS_DF_CONT_BOTTOM | DWS_ICONTAB | DWS_ADDINFO;
|
||||
data.hIconTab = (HICON)::LoadImage(_hInst, MAKEINTRESOURCE(IDI_FIND_RESULT_ICON), IMAGE_ICON, 0, 0, LR_LOADMAP3DCOLORS | LR_LOADTRANSPARENT);
|
||||
|
@ -1343,16 +1423,24 @@ void FindReplaceDlg::findAllIn(InWhat op)
|
|||
::SendMessage(_hParent, NPPM_DMMREGASDCKDLG, 0, (LPARAM)&data);
|
||||
|
||||
_pFinder->_scintView.init(_hInst, _pFinder->getHSelf());
|
||||
|
||||
// Subclass the ScintillaEditView for the Finder (Scintilla doesn't notify all key presses)
|
||||
originalFinderProc = SetWindowLong( _pFinder->_scintView.getHSelf(), GWL_WNDPROC, (LONG) finderProc);
|
||||
|
||||
_pFinder->_scintView.performGlobalStyles();
|
||||
_pFinder->setFinderReadOnly(true);
|
||||
_pFinder->_scintView.execute(SCI_SETCODEPAGE, SC_CP_UTF8);
|
||||
_pFinder->_scintView.execute(SCI_SETCODEPAGE, SC_CP_DBCS);
|
||||
_pFinder->_scintView.execute(SCI_USEPOPUP, FALSE);
|
||||
_pFinder->_scintView.execute(SCI_SETUNDOCOLLECTION, false); //dont store any undo information
|
||||
_pFinder->_scintView.execute(SCI_SETCARETLINEVISIBLE, 1);
|
||||
_pFinder->_scintView.showMargin(ScintillaEditView::_SC_MARGE_FOLDER, true);
|
||||
|
||||
//_statusBar.init(_hInst, _hSelf, 0);
|
||||
RECT findRect;
|
||||
|
||||
//const int scintEditInitHeight = 130;
|
||||
char ptrword[sizeof(void*)*2+1];
|
||||
sprintf(ptrword, "%p", &_pFinder->_MarkingsStruct);
|
||||
_pFinder->_scintView.execute(SCI_SETKEYWORDS, 0, (LPARAM) ptrword);
|
||||
|
||||
// get the width of FindDlg
|
||||
RECT findRect;
|
||||
::GetWindowRect(_pFinder->getHSelf(), &findRect);
|
||||
|
||||
// overwrite some default settings
|
||||
|
@ -1363,25 +1451,21 @@ void FindReplaceDlg::findAllIn(InWhat op)
|
|||
_pFinder->display();
|
||||
}
|
||||
_pFinder->setFinderStyle();
|
||||
_pFinder->setMode(op);
|
||||
|
||||
::SendMessage(_pFinder->getHSelf(), WM_SIZE, 0, 0);
|
||||
if (op == ALL_OPEN_DOCS)
|
||||
::SendMessage(_hParent, WM_FINDALL_INOPENEDDOC, 0, 0);
|
||||
else if (op == FILES_IN_DIR)
|
||||
::SendMessage(_hParent, WM_FINDINFILES, 0, 0);
|
||||
|
||||
refresh();
|
||||
}
|
||||
|
||||
void FindReplaceDlg::putFindResultStr(const TCHAR *text)
|
||||
{
|
||||
wsprintf(_findAllResultStr, TEXT("%s"), text);
|
||||
}
|
||||
|
||||
void FindReplaceDlg::refresh()
|
||||
{
|
||||
::SendMessage(_hParent, NPPM_DMMSHOW, 0, (LPARAM)_pFinder->getHSelf());
|
||||
if (::SendMessage(_hParent, (op==ALL_OPEN_DOCS)?WM_FINDALL_INOPENEDDOC:WM_FINDINFILES, 0, 0))
|
||||
{
|
||||
wsprintf(_findAllResultStr, TEXT("%d hits"), _findAllResult);
|
||||
if (_findAllResult)
|
||||
{
|
||||
focusOnFinder();
|
||||
}
|
||||
else
|
||||
getFocus(); // no hits
|
||||
}
|
||||
else // error - search folder doesn't exist
|
||||
::SendMessage(_hSelf, WM_NEXTDLGCTL, (WPARAM)::GetDlgItem(_hSelf, IDD_FINDINFILES_DIR_COMBO), TRUE);
|
||||
}
|
||||
|
||||
void FindReplaceDlg::enableReplaceFunc(bool isEnable)
|
||||
|
@ -1480,12 +1564,11 @@ void Finder::setFinderStyle()
|
|||
styleDefault._colorStyle = COLORSTYLE_ALL; //All colors set
|
||||
_scintView.setStyle(styleDefault);
|
||||
}
|
||||
|
||||
_scintView.execute(SCI_STYLECLEARALL);
|
||||
_scintView.execute(SCI_SETSTYLEBITS, 5);
|
||||
_scintView.setSearchResultLexer();
|
||||
_scintView.execute(SCI_COLOURISE, 0, -1);
|
||||
_scintView.execute(SCI_SETEOLMODE, SC_EOL_LF);
|
||||
_scintView.execute(SCI_SETEOLMODE, SC_EOL_CRLF);
|
||||
}
|
||||
|
||||
BOOL CALLBACK Finder::run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam)
|
||||
|
@ -1520,9 +1603,15 @@ BOOL CALLBACK Finder::run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
case NPPM_INTERNAL_SCINTILLAFINFERCLEARALL:
|
||||
{
|
||||
removeAll();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
default :
|
||||
{
|
||||
break;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1540,6 +1629,7 @@ BOOL CALLBACK Finder::run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam)
|
|||
tmp.push_back(MenuItemUnit(0, TEXT("Separator")));
|
||||
tmp.push_back(MenuItemUnit(NPPM_INTERNAL_SCINTILLAFINFERCOPY, TEXT("Copy")));
|
||||
tmp.push_back(MenuItemUnit(NPPM_INTERNAL_SCINTILLAFINFERSELECTALL, TEXT("Select All")));
|
||||
tmp.push_back(MenuItemUnit(NPPM_INTERNAL_SCINTILLAFINFERCLEARALL, TEXT("Clear All")));
|
||||
|
||||
scintillaContextmenu.create(_hSelf, tmp);
|
||||
|
||||
|
|
|
@ -39,13 +39,11 @@ enum DIALOG_TYPE {FIND_DLG, REPLACE_DLG, FINDINFILES_DLG};
|
|||
enum InWhat{ALL_OPEN_DOCS, FILES_IN_DIR};
|
||||
|
||||
struct FoundInfo {
|
||||
FoundInfo(int start, int end, const TCHAR *foundLine, const TCHAR *fullPath, size_t lineNum)
|
||||
: _start(start), _end(end), _foundLine(foundLine), _fullPath(fullPath), _scintLineNumber(lineNum){};
|
||||
FoundInfo(int start, int end, const TCHAR *fullPath)
|
||||
: _start(start), _end(end), _fullPath(fullPath) {};
|
||||
int _start;
|
||||
int _end;
|
||||
std::generic_string _foundLine;
|
||||
std::generic_string _fullPath;
|
||||
size_t _scintLineNumber;
|
||||
};
|
||||
|
||||
struct TargetRange {
|
||||
|
@ -88,7 +86,10 @@ private:
|
|||
class Finder : public DockingDlgInterface {
|
||||
friend class FindReplaceDlg;
|
||||
public:
|
||||
Finder() : DockingDlgInterface(IDD_FINDRESULT), _markedLine(-1), _lineCounter(0) {};
|
||||
Finder() : DockingDlgInterface(IDD_FINDRESULT), _pMainFoundInfos(&_foundInfos1), _pMainMarkings(&_markings1) {
|
||||
_MarkingsStruct._length = 0;
|
||||
_MarkingsStruct._markings = NULL;
|
||||
};
|
||||
|
||||
~Finder() {
|
||||
_scintView.destroy();
|
||||
|
@ -98,100 +99,152 @@ public:
|
|||
_ppEditView = ppEditView;
|
||||
};
|
||||
|
||||
void addFileNameTitle(const TCHAR * fileName) {
|
||||
generic_string str = TEXT("[");
|
||||
str += fileName;
|
||||
str += TEXT("]\n");
|
||||
void addSearchLine(const TCHAR *searchName) {
|
||||
generic_string str = TEXT("Search \"");
|
||||
str += searchName;
|
||||
str += TEXT("\"\r\n");
|
||||
|
||||
setFinderReadOnly(false);
|
||||
_scintView.appandGenericText(str.c_str());
|
||||
_scintView.addGenericText(str.c_str());
|
||||
setFinderReadOnly(true);
|
||||
_lineCounter++;
|
||||
_lastSearchHeaderPos = _scintView.execute(SCI_GETCURRENTPOS) - 2;
|
||||
|
||||
_pMainFoundInfos->push_back(EmptyFoundInfo);
|
||||
_pMainMarkings->push_back(EmptySearchResultMarking);
|
||||
};
|
||||
|
||||
void add(FoundInfo fi, int lineNb) {
|
||||
_foundInfos.push_back(fi);
|
||||
std::generic_string str = TEXT("Line ");
|
||||
void addFileNameTitle(const TCHAR * fileName) {
|
||||
generic_string str = TEXT(" ");
|
||||
str += fileName;
|
||||
str += TEXT("\r\n");
|
||||
|
||||
setFinderReadOnly(false);
|
||||
_scintView.addGenericText(str.c_str());
|
||||
setFinderReadOnly(true);
|
||||
_lastFileHeaderPos = _scintView.execute(SCI_GETCURRENTPOS) - 2;
|
||||
|
||||
_pMainFoundInfos->push_back(EmptyFoundInfo);
|
||||
_pMainMarkings->push_back(EmptySearchResultMarking);
|
||||
};
|
||||
|
||||
void addFileHitCount(int count) {
|
||||
TCHAR text[20];
|
||||
wsprintf(text, TEXT(" (%i hits)"), count);
|
||||
setFinderReadOnly(false);
|
||||
_scintView.insertGenericTextFrom(_lastFileHeaderPos, text);
|
||||
setFinderReadOnly(true);
|
||||
nFoundFiles++;
|
||||
};
|
||||
|
||||
void addSearchHitCount(int count) {
|
||||
TCHAR text[50];
|
||||
wsprintf(text, TEXT(" (%i hits in %i files)"), count, nFoundFiles);
|
||||
setFinderReadOnly(false);
|
||||
_scintView.insertGenericTextFrom(_lastSearchHeaderPos, text);
|
||||
setFinderReadOnly(true);
|
||||
};
|
||||
|
||||
|
||||
void add(FoundInfo fi, SearchResultMarking mi, const TCHAR* foundline, int lineNb) {
|
||||
_pMainFoundInfos->push_back(fi);
|
||||
_pMainMarkings->push_back(mi);
|
||||
std::generic_string str = TEXT("\tLine ");
|
||||
|
||||
TCHAR lnb[16];
|
||||
wsprintf(lnb, TEXT("%d"), lineNb);
|
||||
str += lnb;
|
||||
str += TEXT(" : ");
|
||||
str += fi._foundLine;
|
||||
str += TEXT(": ");
|
||||
str += foundline;
|
||||
|
||||
size_t len = str.length();
|
||||
if (len >= SC_SEARCHRESULT_LINEBUFFERMAXLENGTH)
|
||||
if (str.length() >= SC_SEARCHRESULT_LINEBUFFERMAXLENGTH)
|
||||
{
|
||||
const TCHAR * endOfLongLine = TEXT("...\r\n");
|
||||
str = str.substr(0, SC_SEARCHRESULT_LINEBUFFERMAXLENGTH - lstrlen(endOfLongLine) - 1);
|
||||
str += endOfLongLine;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make sure we have EOL. We might not have one for example when searching in non-text files.
|
||||
// This can happen because Scintilla line endings (\n) are not the same as
|
||||
// string line endings (\0). In this case we will see only a part of the line
|
||||
// in the find result window.
|
||||
if (str[len-1] != '\n')
|
||||
str += TEXT("\n");
|
||||
}
|
||||
setFinderReadOnly(false);
|
||||
_scintView.appandGenericText(str.c_str());
|
||||
_scintView.addGenericText(str.c_str());
|
||||
setFinderReadOnly(true);
|
||||
_lineCounter++;
|
||||
};
|
||||
|
||||
void setFinderStyle();
|
||||
|
||||
void removeAll() {
|
||||
_markedLine = -1;
|
||||
_foundInfos.clear();
|
||||
_pMainFoundInfos->clear();
|
||||
_pMainMarkings->clear();
|
||||
setFinderReadOnly(false);
|
||||
_scintView.execute(SCI_CLEARALL);
|
||||
setFinderReadOnly(true);
|
||||
_lineCounter = 0;
|
||||
};
|
||||
|
||||
FoundInfo & getInfo(int curLineNum) {
|
||||
int nbInfo = _foundInfos.size();
|
||||
void beginNewFilesSearch() {
|
||||
_scintView.execute(SCI_SETLEXER, SCLEX_NULL);
|
||||
|
||||
for (size_t i = (nbInfo <= curLineNum)?nbInfo -1:curLineNum ; i > 0 ; i--)
|
||||
{
|
||||
if (_foundInfos[i]._scintLineNumber == curLineNum)
|
||||
return _foundInfos[i];
|
||||
}
|
||||
return _foundInfos[0]; // should never be reached
|
||||
_scintView.execute(SCI_SETCURRENTPOS, 0);
|
||||
_pMainFoundInfos = _pMainFoundInfos == &_foundInfos1 ? &_foundInfos2 : &_foundInfos1;
|
||||
_pMainMarkings = _pMainMarkings == &_markings1 ? &_markings2 : &_markings1;
|
||||
nFoundFiles = 0;
|
||||
|
||||
// fold all old searches (1st level only)
|
||||
_scintView.collapse(searchHeaderLevel - SC_FOLDLEVELBASE, fold_collapse);
|
||||
};
|
||||
|
||||
bool isEmpty() const {
|
||||
return _foundInfos.empty();
|
||||
void finishFilesSearch(int count) {
|
||||
std::vector<FoundInfo>* _pOldFoundInfos;
|
||||
std::vector<SearchResultMarking>* _pOldMarkings;
|
||||
_pOldFoundInfos = _pMainFoundInfos == &_foundInfos1 ? &_foundInfos2 : &_foundInfos1;
|
||||
_pOldMarkings = _pMainMarkings == &_markings1 ? &_markings2 : &_markings1;
|
||||
|
||||
_pOldFoundInfos->insert(_pOldFoundInfos->begin(), _pMainFoundInfos->begin(), _pMainFoundInfos->end());
|
||||
_pOldMarkings->insert(_pOldMarkings->begin(), _pMainMarkings->begin(), _pMainMarkings->end());
|
||||
_pMainFoundInfos->clear();
|
||||
_pMainMarkings->clear();
|
||||
_pMainFoundInfos = _pOldFoundInfos;
|
||||
_pMainMarkings = _pOldMarkings;
|
||||
|
||||
_MarkingsStruct._length = _pMainMarkings->size();
|
||||
_MarkingsStruct._markings = &((*_pMainMarkings)[0]);
|
||||
|
||||
addSearchHitCount(count);
|
||||
_scintView.execute(SCI_SETSEL, 0, 0);
|
||||
|
||||
_scintView.execute(SCI_SETLEXER, SCLEX_SEARCHRESULT);
|
||||
};
|
||||
|
||||
int getCurrentMarkedLine() const {return _markedLine;};
|
||||
void setCurrentMarkedLine(int line) {_markedLine = line;};
|
||||
InWhat getMode() const {return _mode;};
|
||||
void setMode(InWhat mode) {_mode = mode;};
|
||||
|
||||
void setSearchWord(const TCHAR *word2search) {
|
||||
_scintView.setHiLiteResultWords(word2search);
|
||||
};
|
||||
|
||||
void gotoNextFoundResult(int direction);
|
||||
void GotoFoundLine();
|
||||
void DeleteResult();
|
||||
|
||||
protected :
|
||||
virtual BOOL CALLBACK run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam);
|
||||
bool notify(SCNotification *notification);
|
||||
|
||||
private:
|
||||
|
||||
enum { searchHeaderLevel = SC_FOLDLEVELBASE + 1, fileHeaderLevel, resultLevel };
|
||||
|
||||
ScintillaEditView **_ppEditView;
|
||||
std::vector<FoundInfo> _foundInfos;
|
||||
std::vector<FoundInfo> _foundInfos1;
|
||||
std::vector<FoundInfo> _foundInfos2;
|
||||
std::vector<FoundInfo>* _pMainFoundInfos;
|
||||
std::vector<SearchResultMarking> _markings1;
|
||||
std::vector<SearchResultMarking> _markings2;
|
||||
std::vector<SearchResultMarking>* _pMainMarkings;
|
||||
SearchResultMarkings _MarkingsStruct;
|
||||
|
||||
ScintillaEditView _scintView;
|
||||
int _markedLine;
|
||||
InWhat _mode;
|
||||
size_t _lineCounter;
|
||||
unsigned int nFoundFiles;
|
||||
|
||||
int _lastFileHeaderPos;
|
||||
int _lastSearchHeaderPos;
|
||||
|
||||
void setFinderReadOnly(bool isReadOnly) {
|
||||
_scintView.execute(SCI_SETREADONLY, isReadOnly);
|
||||
};
|
||||
|
||||
static FoundInfo EmptyFoundInfo;
|
||||
static SearchResultMarking EmptySearchResultMarking;
|
||||
};
|
||||
|
||||
//FindReplaceDialog: standard find/replace window
|
||||
|
@ -275,27 +328,11 @@ public :
|
|||
}
|
||||
::SendMessage(hCombo, CB_SETEDITSEL, 0, MAKELPARAM(0, -1)); // select all text - fast edit
|
||||
}
|
||||
|
||||
bool isFinderEmpty() const {
|
||||
return _pFinder->isEmpty();
|
||||
};
|
||||
|
||||
void clearFinder() {
|
||||
_pFinder->removeAll();
|
||||
};
|
||||
void gotoNextFoundResult(int direction = 0) {if (_pFinder) _pFinder->gotoNextFoundResult(direction);};
|
||||
|
||||
void putFindResult(int result) {
|
||||
_findAllResult = result;
|
||||
};
|
||||
void putFindResultStr(const TCHAR *text);
|
||||
|
||||
void refresh();
|
||||
|
||||
void setSearchWord2Finder(){
|
||||
generic_string str2Search = getText2search();
|
||||
_pFinder->setSearchWord(str2Search.c_str());
|
||||
};
|
||||
|
||||
const TCHAR * getDir2Search() const {return _directory.c_str();};
|
||||
|
||||
void getPatterns(vector<generic_string> & patternVect);
|
||||
|
@ -333,11 +370,49 @@ public :
|
|||
tie.pszText = (TCHAR *)name2change;
|
||||
TabCtrl_SetItem(_tab.getHSelf(), index, &tie);
|
||||
}
|
||||
void beginNewFilesSearch()
|
||||
{
|
||||
_pFinder->beginNewFilesSearch();
|
||||
bool isUnicode = (*_ppEditView)->getCurrentBuffer()->getUnicodeMode() != uni8Bit;
|
||||
_pFinder->addSearchLine(getText2search().c_str());
|
||||
}
|
||||
|
||||
void finishFilesSearch(int count)
|
||||
{
|
||||
_pFinder->finishFilesSearch(count);
|
||||
}
|
||||
|
||||
void focusOnFinder() {
|
||||
// Show finder and set focus
|
||||
if (_pFinder) {
|
||||
::SendMessage(_hParent, NPPM_DMMSHOW, 0, (LPARAM)_pFinder->getHSelf());
|
||||
_pFinder->_scintView.getFocus();
|
||||
}
|
||||
};
|
||||
|
||||
protected :
|
||||
virtual BOOL CALLBACK run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam);
|
||||
void addText2Combo(const TCHAR * txt2add, HWND comboID, bool isUTF8 = false);
|
||||
generic_string getTextFromCombo(HWND hCombo, bool isUnicode = false) const;
|
||||
static LONG originalFinderProc;
|
||||
|
||||
// Window procedure for the finder
|
||||
static LRESULT FAR PASCAL finderProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (message == WM_KEYDOWN && (wParam == VK_DELETE || wParam == VK_RETURN))
|
||||
{
|
||||
ScintillaEditView *pScint = (ScintillaEditView *)(::GetWindowLongPtr(hwnd, GWL_USERDATA));
|
||||
Finder *pFinder = (Finder *)(::GetWindowLongPtr(pScint->getHParent(), GWL_USERDATA));
|
||||
if (wParam == VK_RETURN)
|
||||
pFinder->GotoFoundLine();
|
||||
else // VK_DELETE
|
||||
pFinder->DeleteResult();
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
// Call default (original) window procedure
|
||||
return CallWindowProc((WNDPROC) originalFinderProc, hwnd, message, wParam, lParam);
|
||||
}
|
||||
|
||||
private :
|
||||
DIALOG_TYPE _currentStatus;
|
||||
|
@ -390,7 +465,7 @@ private :
|
|||
void setDefaultButton(int nID)
|
||||
{
|
||||
#if 0
|
||||
// Where is a problem when you:
|
||||
// There is a problem when you:
|
||||
// 1. open the find dialog
|
||||
// 2. press the "close" buttom
|
||||
// 3. open it again
|
||||
|
|
|
@ -1451,6 +1451,23 @@ void ScintillaEditView::getGenericText(TCHAR *dest, int start, int end) const
|
|||
#endif
|
||||
}
|
||||
|
||||
// "mstart" and "mend" are pointers to indexes in the read string,
|
||||
// which are converted to the corresponding indexes in the returned TCHAR string.
|
||||
void ScintillaEditView::getGenericText(TCHAR *dest, int start, int end, int *mstart, int *mend) const
|
||||
{
|
||||
#ifdef UNICODE
|
||||
WcharMbcsConvertor *wmc = WcharMbcsConvertor::getInstance();
|
||||
char *destA = new char[end - start + 1];
|
||||
getText(destA, start, end);
|
||||
unsigned int cp = execute(SCI_GETCODEPAGE);
|
||||
const TCHAR *destW = wmc->char2wchar(destA, cp, mstart, mend);
|
||||
lstrcpy(dest, destW);
|
||||
delete [] destA;
|
||||
#else
|
||||
getText(dest, start, end);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ScintillaEditView::insertGenericTextFrom(int position, const TCHAR *text2insert) const
|
||||
{
|
||||
#ifdef UNICODE
|
||||
|
@ -1530,6 +1547,18 @@ void ScintillaEditView::appandGenericText(const TCHAR * text2Append) const
|
|||
#endif
|
||||
}
|
||||
|
||||
void ScintillaEditView::addGenericText(const TCHAR * text2Append) const
|
||||
{
|
||||
#ifdef UNICODE
|
||||
WcharMbcsConvertor *wmc = WcharMbcsConvertor::getInstance();
|
||||
unsigned int cp = execute(SCI_GETCODEPAGE);
|
||||
const char *text2AppendA =wmc->wchar2char(text2Append, cp);
|
||||
execute(SCI_ADDTEXT, strlen(text2AppendA), (LPARAM)text2AppendA);
|
||||
#else
|
||||
execute(SCI_ADDTEXT, strlen(text2AppendA), (LPARAM)text2AppendA);
|
||||
#endif
|
||||
}
|
||||
|
||||
int ScintillaEditView::replaceTarget(const TCHAR * str2replace, int fromTargetPos, int toTargetPos) const
|
||||
{
|
||||
if (fromTargetPos != -1 || toTargetPos != -1)
|
||||
|
|
|
@ -167,6 +167,7 @@ public:
|
|||
|
||||
void getText(char *dest, int start, int end) const;
|
||||
void getGenericText(TCHAR *dest, int start, int end) const;
|
||||
void getGenericText(TCHAR *dest, int start, int end, int *mstart, int *mend) const;
|
||||
void insertGenericTextFrom(int position, const TCHAR *text2insert) const;
|
||||
void replaceSelWith(const char * replaceText);
|
||||
|
||||
|
@ -179,6 +180,7 @@ public:
|
|||
TCHAR * getGenericSelectedText(TCHAR * txt, int size, bool expand = true);
|
||||
int searchInTarget(const TCHAR * Text2Find, int fromPos, int toPos) const;
|
||||
void appandGenericText(const TCHAR * text2Append) const;
|
||||
void addGenericText(const TCHAR * text2Append) const;
|
||||
int replaceTarget(const TCHAR * str2replace, int fromTargetPos = -1, int toTargetPos = -1) const;
|
||||
int replaceTargetRegExMode(const TCHAR * re, int fromTargetPos = -1, int toTargetPos = -1) const;
|
||||
void showAutoComletion(int lenEntered, const TCHAR * list);
|
||||
|
@ -701,8 +703,9 @@ protected:
|
|||
};
|
||||
|
||||
void setSearchResultLexer() {
|
||||
execute(SCI_STYLESETEOLFILLED, SCE_SEARCHRESULT_HEARDER, true);
|
||||
setLexer(SCLEX_SEARCHRESULT, L_SEARCHRESULT, LIST_1 | LIST_2 | LIST_3);
|
||||
execute(SCI_STYLESETEOLFILLED, SCE_SEARCHRESULT_FILE_HEADER, true);
|
||||
execute(SCI_STYLESETEOLFILLED, SCE_SEARCHRESULT_SEARCH_HEADER, true);
|
||||
setLexer(SCLEX_SEARCHRESULT, L_SEARCHRESULT, 0);
|
||||
};
|
||||
|
||||
bool isNeededFolderMarge(LangType typeDoc) const {
|
||||
|
|
|
@ -302,6 +302,8 @@
|
|||
#define NPPM_INTERNAL_CANCEL_FIND_IN_FILES (NOTEPADPLUS_USER_INTERNAL + 24)
|
||||
#define NPPM_INTERNAL_RELOADNATIVELANG (NOTEPADPLUS_USER_INTERNAL + 25)
|
||||
#define NPPM_INTERNAL_PLUGINSHORTCUTMOTIFIED (NOTEPADPLUS_USER_INTERNAL + 26)
|
||||
#define NPPM_INTERNAL_SCINTILLAFINFERCLEARALL (NOTEPADPLUS_USER_INTERNAL + 27)
|
||||
|
||||
// See Notepad_plus_msgs.h
|
||||
//#define NOTEPADPLUS_USER (WM_USER + 1000)
|
||||
|
||||
|
|
|
@ -14,5 +14,7 @@
|
|||
<Command name="Wikipedia Search" Ctrl="no" Alt="yes" Shift="no" Key="114">http://en.wikipedia.org/wiki/Special:Search?search=$(CURRENT_WORD)</Command>
|
||||
<Command name="open file" Ctrl="no" Alt="yes" Shift="no" Key="116">$(NPP_DIRECTORY)\notepad++.exe $(CURRENT_WORD)</Command>
|
||||
<Command name="open in another instance" Ctrl="no" Alt="yes" Shift="no" Key="117">$(NPP_DIRECTORY)\notepad++.exe $(CURRENT_WORD) -nosession -multiInst</Command>
|
||||
<Command name="Open containing folder" Ctrl="no" Alt="no" Shift="no" Key="0">explorer $(CURRENT_DIRECTORY)</Command>
|
||||
<Command name="Open current dir cmd" Ctrl="no" Alt="no" Shift="no" Key="0">cmd /K cd $(CURRENT_DIRECTORY)</Command>
|
||||
</UserDefinedCommands>
|
||||
</NotepadPlus>
|
||||
|
|
|
@ -689,12 +689,11 @@
|
|||
</LexerType>
|
||||
<LexerType name="searchResult" desc="Search result" ext="">
|
||||
<WordsStyle name="DEFAULT" styleID="0" fgColor="000000" bgColor="FFFFFF" fontName="" fontStyle="0" fontSize="" />
|
||||
<WordsStyle name="SELECTED LINE" styleID="6" fgColor="FFFF80" bgColor="0000FF" fontName="" fontStyle="1" fontSize="" />
|
||||
<WordsStyle name="HEARDER" styleID="1" fgColor="008000" bgColor="D5FFD5" fontName="" fontStyle="1" fontSize="" />
|
||||
<WordsStyle name="NUMBER" styleID="2" fgColor="FF0000" bgColor="FFFFFF" fontName="" fontStyle="0" fontSize="" />
|
||||
<WordsStyle name="HIT WORD" styleID="3" fgColor="FF0000" bgColor="FFFF80" fontName="" fontStyle="4" fontSize="" />
|
||||
<WordsStyle name="KEYWORD1" styleID="4" fgColor="0000FF" bgColor="FFFFFF" fontName="" fontStyle="1" fontSize="" keywordClass="instre2">if else for while</WordsStyle>
|
||||
<WordsStyle name="KEYWORD2" styleID="5" fgColor="0080FF" bgColor="FFFFFF" fontName="" fontStyle="0" fontSize="" keywordClass="type1">bool long int char</WordsStyle>
|
||||
<WordsStyle name="SEARCH HEADER" styleID="1" fgColor="000080" bgColor="BBBBFF" fontName="" fontStyle="1" fontSize="" />
|
||||
<WordsStyle name="FILE HEADER" styleID="2" fgColor="008000" bgColor="D5FFD5" fontName="" fontStyle="1" fontSize="" />
|
||||
<WordsStyle name="LINE NUMBER" styleID="3" fgColor="FF0000" bgColor="FFFFFF" fontName="" fontStyle="0" fontSize="" />
|
||||
<WordsStyle name="HIT WORD" styleID="4" fgColor="FF0000" bgColor="FFFFBF" fontName="" fontStyle="0" fontSize="" />
|
||||
<WordsStyle name="SELECTED LINE" styleID="5" fgColor="FFFF80" bgColor="000080" fontName="" fontStyle="0" fontSize="" />
|
||||
</LexerType>
|
||||
</LexerStyles>
|
||||
<GlobalStyles>
|
||||
|
|
|
@ -290,6 +290,10 @@
|
|||
RelativePath="..\src\lastRecentFileList.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\MISC\Exception\MiniDumper.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\Notepad_plus.cpp"
|
||||
>
|
||||
|
@ -583,6 +587,10 @@
|
|||
RelativePath="..\src\menuCmdID.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\MISC\Exception\MiniDumper.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\Notepad_plus.h"
|
||||
>
|
||||
|
|
|
@ -170,12 +170,11 @@
|
|||
#define SCE_D_COMMENTDOCKEYWORDERROR 17
|
||||
|
||||
#define SCE_SEARCHRESULT_DEFAULT 0
|
||||
#define SCE_SEARCHRESULT_HEARDER 1
|
||||
#define SCE_SEARCHRESULT_NUMBER 2
|
||||
#define SCE_SEARCHRESULT_WORD2SEARCH 3
|
||||
#define SCE_SEARCHRESULT_KWORD1 4
|
||||
#define SCE_SEARCHRESULT_KWORD2 5
|
||||
#define SCE_SEARCHRESULT_KWORD3 6
|
||||
#define SCE_SEARCHRESULT_SEARCH_HEADER 1
|
||||
#define SCE_SEARCHRESULT_FILE_HEADER 2
|
||||
#define SCE_SEARCHRESULT_LINE_NUMBER 3
|
||||
#define SCE_SEARCHRESULT_WORD2SEARCH 4
|
||||
#define SCE_SEARCHRESULT_HIGHLIGHT_LINE 5
|
||||
|
||||
#define SCE_OBJC_DIRECTIVE 20
|
||||
#define SCE_OBJC_QUALIFIER 21
|
||||
|
|
|
@ -828,6 +828,16 @@ struct SCNotification {
|
|||
int y; // SCN_DWELLSTART, SCN_DWELLEND
|
||||
};
|
||||
|
||||
struct SearchResultMarking {
|
||||
long _start;
|
||||
long _end;
|
||||
};
|
||||
|
||||
struct SearchResultMarkings {
|
||||
long _length;
|
||||
SearchResultMarking *_markings;
|
||||
};
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <vector>
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
|
@ -33,6 +34,10 @@
|
|||
#include "Scintilla.h"
|
||||
#include "SciLexer.h"
|
||||
|
||||
// The following definitions are a copy of the ones in FindReplaceDlg.h
|
||||
static enum { searchHeaderLevel = SC_FOLDLEVELBASE + 1, fileHeaderLevel, resultLevel };
|
||||
|
||||
|
||||
static inline bool AtEOL(Accessor &styler, unsigned int i) {
|
||||
return (styler[i] == '\n') ||
|
||||
((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n'));
|
||||
|
@ -42,143 +47,78 @@ static const char * const emptyWordListDesc[] = {
|
|||
0
|
||||
};
|
||||
|
||||
inline bool isSpaceChar(char ch) {
|
||||
return ((ch == ' ') || (ch == ' '));
|
||||
};
|
||||
|
||||
// return value : false if the end of line is reached, otherwise true
|
||||
inline bool eatWhiteSpaces(const char *line, unsigned int & pos) {
|
||||
if (pos >= strlen(line)) return false;
|
||||
|
||||
//int i = pos;
|
||||
for ( ; line[pos] && isSpaceChar(line[pos]) ; pos++);
|
||||
|
||||
return (pos < strlen(line));
|
||||
};
|
||||
|
||||
static void ColouriseSearchResultLine(WordList *keywordlists[], char *lineBuffer, unsigned int lengthLine, unsigned int startLine, unsigned int endPos, Accessor &styler)
|
||||
static void ColouriseSearchResultLine(SearchResultMarkings* pMarkings, char *lineBuffer, unsigned int lengthLine, unsigned int startLine, unsigned int endPos, Accessor &styler, int linenum)
|
||||
{
|
||||
|
||||
// startLine and endPos are the absolute positions.
|
||||
|
||||
WordList &word2Search = *keywordlists[0];
|
||||
WordList &keywords1 = *keywordlists[1];
|
||||
WordList &keywords2 = *keywordlists[2];
|
||||
WordList &keywords3 = *keywordlists[3];
|
||||
|
||||
if (lineBuffer[0] == '[')
|
||||
if (lineBuffer[0] == ' ') // file header
|
||||
{
|
||||
styler.ColourTo(endPos, SCE_SEARCHRESULT_HEARDER);
|
||||
}
|
||||
else
|
||||
styler.ColourTo(endPos, SCE_SEARCHRESULT_FILE_HEADER);
|
||||
}
|
||||
else if (lineBuffer[0] == 'S') // search header
|
||||
{
|
||||
styler.ColourTo(endPos, SCE_SEARCHRESULT_SEARCH_HEADER);
|
||||
}
|
||||
else // line info
|
||||
{
|
||||
const unsigned int firstTokenLen = 4;
|
||||
unsigned int currentPos;
|
||||
|
||||
PLATFORM_ASSERT(lengthLine >= firstTokenLen + 2);
|
||||
|
||||
styler.ColourTo(startLine + firstTokenLen, SCE_SEARCHRESULT_DEFAULT);
|
||||
|
||||
unsigned int currentPos = firstTokenLen;
|
||||
for ( ; lineBuffer[currentPos] != ':' ; currentPos++);
|
||||
styler.ColourTo(startLine + currentPos - 1, SCE_SEARCHRESULT_NUMBER);
|
||||
for (currentPos = firstTokenLen; lineBuffer[currentPos] != ':' ; currentPos++) PLATFORM_ASSERT(currentPos < lengthLine);
|
||||
styler.ColourTo(startLine + currentPos - 1, SCE_SEARCHRESULT_LINE_NUMBER);
|
||||
|
||||
|
||||
//StyleContext sc(startPos, length, initStyle, styler);
|
||||
int currentStat = SCE_SEARCHRESULT_DEFAULT;
|
||||
|
||||
PLATFORM_ASSERT(linenum < pMarkings->_length);
|
||||
SearchResultMarking mi = pMarkings->_markings[linenum];
|
||||
|
||||
const int maxWordSize = 4096;
|
||||
char word[maxWordSize];
|
||||
|
||||
bool isEndReached = eatWhiteSpaces(lineBuffer, currentPos);
|
||||
currentPos += 2; // skip ": "
|
||||
unsigned int match_start = startLine + currentPos + mi._start - 1;
|
||||
unsigned int match_end = startLine + currentPos + mi._end - 1;
|
||||
|
||||
styler.ColourTo(startLine + currentPos - 1, SCE_SEARCHRESULT_DEFAULT);
|
||||
|
||||
while (currentPos < lengthLine)
|
||||
{
|
||||
for (int j = 0 ; j < maxWordSize ; currentPos++, j++)
|
||||
{
|
||||
|
||||
if (currentPos >= lengthLine)
|
||||
{
|
||||
isEndReached = true;
|
||||
break;
|
||||
}
|
||||
|
||||
char ch = lineBuffer[currentPos];
|
||||
|
||||
if ((ch == ' ') || (ch == 0x0A) || (ch == 0x0D))
|
||||
{
|
||||
if (j == 0)
|
||||
goto end;
|
||||
|
||||
word[j] = '\0';
|
||||
|
||||
if ((word2Search) && (word2Search.InList(word)))
|
||||
{
|
||||
currentStat = SCE_SEARCHRESULT_WORD2SEARCH;
|
||||
}
|
||||
else if ((keywords1) && (keywords1.InList(word)))
|
||||
{
|
||||
currentStat = SCE_SEARCHRESULT_KWORD1;
|
||||
}
|
||||
else if ((keywords2) && (keywords2.InList(word)))
|
||||
{
|
||||
currentStat = SCE_SEARCHRESULT_KWORD2;
|
||||
}
|
||||
else if ((keywords3) && (keywords3.InList(word)))
|
||||
{
|
||||
currentStat = SCE_SEARCHRESULT_KWORD3;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentStat = SCE_SEARCHRESULT_DEFAULT;
|
||||
}
|
||||
styler.ColourTo(startLine + currentPos - 1, currentStat);
|
||||
currentStat = SCE_SEARCHRESULT_DEFAULT;
|
||||
|
||||
isEndReached = !eatWhiteSpaces(lineBuffer, currentPos);
|
||||
break;
|
||||
}
|
||||
else
|
||||
word[j] = ch;
|
||||
}
|
||||
|
||||
if (isEndReached)
|
||||
{
|
||||
styler.ColourTo(endPos, SCE_SEARCHRESULT_DEFAULT);
|
||||
}
|
||||
else
|
||||
{
|
||||
styler.ColourTo(startLine + currentPos - 1, currentStat);
|
||||
}
|
||||
if (match_start <= endPos) {
|
||||
styler.ColourTo(match_start, SCE_SEARCHRESULT_DEFAULT);
|
||||
if (match_end <= endPos)
|
||||
styler.ColourTo(match_end, SCE_SEARCHRESULT_WORD2SEARCH);
|
||||
else
|
||||
currentStat = SCE_SEARCHRESULT_WORD2SEARCH;
|
||||
}
|
||||
end :
|
||||
styler.ColourTo(endPos, SCE_SEARCHRESULT_DEFAULT);
|
||||
styler.ColourTo(endPos, currentStat);
|
||||
}
|
||||
}
|
||||
|
||||
static void ColouriseSearchResultDoc(unsigned int startPos, int length, int, WordList *keywordlists[], Accessor &styler) {
|
||||
|
||||
char lineBuffer[SC_SEARCHRESULT_LINEBUFFERMAXLENGTH];
|
||||
styler.StartAt(startPos);
|
||||
styler.StartSegment(startPos);
|
||||
unsigned int linePos = 0;
|
||||
unsigned int startLine = startPos;
|
||||
|
||||
SearchResultMarkings* pMarkings = NULL;
|
||||
sscanf(keywordlists[0]->words[0], "%p", &pMarkings);
|
||||
PLATFORM_ASSERT(pMarkings);
|
||||
|
||||
for (unsigned int i = startPos; i < startPos + length; i++) {
|
||||
lineBuffer[linePos++] = styler[i];
|
||||
if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
|
||||
// End of line (or of line buffer) met, colourise it
|
||||
lineBuffer[linePos] = '\0';
|
||||
ColouriseSearchResultLine(keywordlists, lineBuffer, linePos, startLine, i, styler);
|
||||
ColouriseSearchResultLine(pMarkings, lineBuffer, linePos, startLine, i, styler, styler.GetLine(startLine));
|
||||
linePos = 0;
|
||||
startLine = i + 1;
|
||||
while (!AtEOL(styler, i)) i++;
|
||||
}
|
||||
}
|
||||
if (linePos > 0) { // Last line does not have ending characters
|
||||
ColouriseSearchResultLine(keywordlists, lineBuffer, linePos, startLine, startPos + length - 1, styler);
|
||||
ColouriseSearchResultLine(pMarkings, lineBuffer, linePos, startLine, startPos + length - 1, styler, styler.GetLine(startLine));
|
||||
}
|
||||
}
|
||||
|
||||
// adaption by ksc, using the "} else {" trick of 1.53
|
||||
// 030721
|
||||
static void FoldSearchResultDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
|
||||
bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
|
||||
|
||||
|
@ -188,7 +128,7 @@ static void FoldSearchResultDoc(unsigned int startPos, int length, int, WordList
|
|||
|
||||
char chNext = styler[startPos];
|
||||
int styleNext = styler.StyleAt(startPos);
|
||||
bool headerPoint = false;
|
||||
int headerPoint = 0;
|
||||
int lev;
|
||||
|
||||
for (unsigned int i = startPos; i < endPos; i++) {
|
||||
|
@ -199,57 +139,32 @@ static void FoldSearchResultDoc(unsigned int startPos, int length, int, WordList
|
|||
styleNext = styler.StyleAt(i + 1);
|
||||
bool atEOL = (ch == '\n') || (ch == '\r' && chNext != '\n');
|
||||
|
||||
if (style == SCE_SEARCHRESULT_HEARDER)
|
||||
if (style == SCE_SEARCHRESULT_FILE_HEADER)
|
||||
{
|
||||
headerPoint = true;
|
||||
headerPoint = fileHeaderLevel;
|
||||
}
|
||||
else if (style == SCE_SEARCHRESULT_SEARCH_HEADER)
|
||||
{
|
||||
headerPoint = searchHeaderLevel;
|
||||
}
|
||||
|
||||
if (atEOL) {
|
||||
lev = SC_FOLDLEVELBASE;
|
||||
lev = headerPoint ? SC_FOLDLEVELHEADERFLAG + headerPoint : resultLevel;
|
||||
headerPoint = 0;
|
||||
|
||||
if (lineCurrent > 0) {
|
||||
int levelPrevious = styler.LevelAt(lineCurrent - 1);
|
||||
|
||||
if (levelPrevious & SC_FOLDLEVELHEADERFLAG) {
|
||||
lev = SC_FOLDLEVELBASE + 1;
|
||||
} else {
|
||||
lev = levelPrevious & SC_FOLDLEVELNUMBERMASK;
|
||||
}
|
||||
}
|
||||
|
||||
if (headerPoint) {
|
||||
lev = SC_FOLDLEVELBASE;
|
||||
}
|
||||
if (visibleChars == 0 && foldCompact)
|
||||
lev |= SC_FOLDLEVELWHITEFLAG;
|
||||
|
||||
if (headerPoint) {
|
||||
lev |= SC_FOLDLEVELHEADERFLAG;
|
||||
}
|
||||
if (lev != styler.LevelAt(lineCurrent)) {
|
||||
styler.SetLevel(lineCurrent, lev);
|
||||
}
|
||||
|
||||
lineCurrent++;
|
||||
visibleChars = 0;
|
||||
headerPoint = false;
|
||||
}
|
||||
if (!isspacechar(ch))
|
||||
visibleChars++;
|
||||
}
|
||||
|
||||
if (lineCurrent > 0) {
|
||||
int levelPrevious = styler.LevelAt(lineCurrent - 1);
|
||||
if (levelPrevious & SC_FOLDLEVELHEADERFLAG) {
|
||||
lev = SC_FOLDLEVELBASE + 1;
|
||||
} else {
|
||||
lev = levelPrevious & SC_FOLDLEVELNUMBERMASK;
|
||||
}
|
||||
} else {
|
||||
lev = SC_FOLDLEVELBASE;
|
||||
}
|
||||
int flagsNext = styler.LevelAt(lineCurrent);
|
||||
styler.SetLevel(lineCurrent, lev | flagsNext & ~SC_FOLDLEVELNUMBERMASK);
|
||||
styler.SetLevel(lineCurrent, SC_FOLDLEVELBASE);
|
||||
}
|
||||
|
||||
LexerModule lmSearchResult(SCLEX_SEARCHRESULT, ColouriseSearchResultDoc, "searchResult", FoldSearchResultDoc, emptyWordListDesc);
|
||||
|
|
Loading…
Reference in New Issue