From 7705e0b5719d14cfea1be3fe8648402ebe2ac7d5 Mon Sep 17 00:00:00 2001 From: donho Date: Wed, 4 Feb 2009 01:06:38 +0000 Subject: [PATCH] [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 --- PowerEditor/src/MISC/Common/Common.cpp | 32 +++ PowerEditor/src/MISC/Common/Common.h | 1 + PowerEditor/src/Notepad_plus.cpp | 86 +++---- PowerEditor/src/Notepad_plus.rc | 2 +- .../src/ScitillaComponent/FindReplaceDlg.cpp | 242 ++++++++++++------ .../src/ScitillaComponent/FindReplaceDlg.h | 219 ++++++++++------ .../ScitillaComponent/ScintillaEditView.cpp | 29 +++ .../src/ScitillaComponent/ScintillaEditView.h | 7 +- PowerEditor/src/resource.h | 2 + PowerEditor/src/shortcuts.xml | 2 + PowerEditor/src/stylers.model.xml | 11 +- PowerEditor/visual.net/notepadPlus.vcproj | 8 + scintilla/include/SciLexer.h | 11 +- scintilla/include/Scintilla.h | 10 + scintilla/src/LexSearchResult.cxx | 185 ++++--------- 15 files changed, 503 insertions(+), 344 deletions(-) diff --git a/PowerEditor/src/MISC/Common/Common.cpp b/PowerEditor/src/MISC/Common/Common.cpp index 20e165373..2aa5308ec 100644 --- a/PowerEditor/src/MISC/Common/Common.cpp +++ b/PowerEditor/src/MISC/Common/Common.cpp @@ -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) diff --git a/PowerEditor/src/MISC/Common/Common.h b/PowerEditor/src/MISC/Common/Common.h index 231d7c2df..c65bec745 100644 --- a/PowerEditor/src/MISC/Common/Common.h +++ b/PowerEditor/src/MISC/Common/Common.h @@ -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: diff --git a/PowerEditor/src/Notepad_plus.cpp b/PowerEditor/src/Notepad_plus.cpp index fd86c30c3..9259390c8 100644 --- a/PowerEditor/src/Notepad_plus.cpp +++ b/PowerEditor/src/Notepad_plus.cpp @@ -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 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 patterns2Match; if (_findReplaceDlg.getFilters() == TEXT("")) @@ -1670,15 +1671,12 @@ bool Notepad_plus::findInFiles() _findReplaceDlg.getPatterns(patterns2Match); vector 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 : diff --git a/PowerEditor/src/Notepad_plus.rc b/PowerEditor/src/Notepad_plus.rc index 66daf539b..eb75e3c28 100644 --- a/PowerEditor/src/Notepad_plus.rc +++ b/PowerEditor/src/Notepad_plus.rc @@ -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 diff --git a/PowerEditor/src/ScitillaComponent/FindReplaceDlg.cpp b/PowerEditor/src/ScitillaComponent/FindReplaceDlg.cpp index fbd86a87c..6f65c05fb 100644 --- a/PowerEditor/src/ScitillaComponent/FindReplaceDlg.cpp +++ b/PowerEditor/src/ScitillaComponent/FindReplaceDlg.cpp @@ -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); diff --git a/PowerEditor/src/ScitillaComponent/FindReplaceDlg.h b/PowerEditor/src/ScitillaComponent/FindReplaceDlg.h index 3343d23bd..b7522e491 100644 --- a/PowerEditor/src/ScitillaComponent/FindReplaceDlg.h +++ b/PowerEditor/src/ScitillaComponent/FindReplaceDlg.h @@ -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* _pOldFoundInfos; + std::vector* _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 _foundInfos; + std::vector _foundInfos1; + std::vector _foundInfos2; + std::vector* _pMainFoundInfos; + std::vector _markings1; + std::vector _markings2; + std::vector* _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 & 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 diff --git a/PowerEditor/src/ScitillaComponent/ScintillaEditView.cpp b/PowerEditor/src/ScitillaComponent/ScintillaEditView.cpp index 5ec2e6810..b8303ca76 100644 --- a/PowerEditor/src/ScitillaComponent/ScintillaEditView.cpp +++ b/PowerEditor/src/ScitillaComponent/ScintillaEditView.cpp @@ -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) diff --git a/PowerEditor/src/ScitillaComponent/ScintillaEditView.h b/PowerEditor/src/ScitillaComponent/ScintillaEditView.h index 75602fe58..25763f8f8 100644 --- a/PowerEditor/src/ScitillaComponent/ScintillaEditView.h +++ b/PowerEditor/src/ScitillaComponent/ScintillaEditView.h @@ -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 { diff --git a/PowerEditor/src/resource.h b/PowerEditor/src/resource.h index 3e541fe20..0f1b70f36 100644 --- a/PowerEditor/src/resource.h +++ b/PowerEditor/src/resource.h @@ -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) diff --git a/PowerEditor/src/shortcuts.xml b/PowerEditor/src/shortcuts.xml index 4555cd5fb..c343f3c68 100644 --- a/PowerEditor/src/shortcuts.xml +++ b/PowerEditor/src/shortcuts.xml @@ -14,5 +14,7 @@ http://en.wikipedia.org/wiki/Special:Search?search=$(CURRENT_WORD) $(NPP_DIRECTORY)\notepad++.exe $(CURRENT_WORD) $(NPP_DIRECTORY)\notepad++.exe $(CURRENT_WORD) -nosession -multiInst + explorer $(CURRENT_DIRECTORY) + cmd /K cd $(CURRENT_DIRECTORY) diff --git a/PowerEditor/src/stylers.model.xml b/PowerEditor/src/stylers.model.xml index fea784818..eaf9c76d0 100644 --- a/PowerEditor/src/stylers.model.xml +++ b/PowerEditor/src/stylers.model.xml @@ -689,12 +689,11 @@ - - - - - if else for while - bool long int char + + + + + diff --git a/PowerEditor/visual.net/notepadPlus.vcproj b/PowerEditor/visual.net/notepadPlus.vcproj index bd94064d5..9fb2adfaa 100644 --- a/PowerEditor/visual.net/notepadPlus.vcproj +++ b/PowerEditor/visual.net/notepadPlus.vcproj @@ -290,6 +290,10 @@ RelativePath="..\src\lastRecentFileList.cpp" > + + @@ -583,6 +587,10 @@ RelativePath="..\src\menuCmdID.h" > + + diff --git a/scintilla/include/SciLexer.h b/scintilla/include/SciLexer.h index 87b899edb..e2fcac7ef 100644 --- a/scintilla/include/SciLexer.h +++ b/scintilla/include/SciLexer.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 diff --git a/scintilla/include/Scintilla.h b/scintilla/include/Scintilla.h index ef889410b..62a6cc574 100644 --- a/scintilla/include/Scintilla.h +++ b/scintilla/include/Scintilla.h @@ -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 diff --git a/scintilla/src/LexSearchResult.cxx b/scintilla/src/LexSearchResult.cxx index c3b16b067..9f917082b 100644 --- a/scintilla/src/LexSearchResult.cxx +++ b/scintilla/src/LexSearchResult.cxx @@ -24,6 +24,7 @@ #include #include #include +#include #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);