From d6081a5f3785fe0565900fc4c7f6ce1a78e5c6ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20J=C3=B6nsson?= Date: Mon, 1 Jun 2015 18:39:22 +0200 Subject: [PATCH] Improve copy functionality in find results window Just copy the actual results, without the additional formatting with line and file name. It respects the hierarchy in the results, i.e. you can copy all results from a search operation, or from a specific file, or just the lines you selected. --- PowerEditor/src/MISC/Common/Common.cpp | 33 +++++++++ PowerEditor/src/MISC/Common/Common.h | 2 + PowerEditor/src/Notepad_plus.cpp | 30 +------- .../src/ScitillaComponent/FindReplaceDlg.cpp | 71 ++++++++++++++++++- .../src/ScitillaComponent/FindReplaceDlg.h | 4 ++ .../ScitillaComponent/ScintillaEditView.cpp | 10 +++ .../src/ScitillaComponent/ScintillaEditView.h | 1 + 7 files changed, 121 insertions(+), 30 deletions(-) diff --git a/PowerEditor/src/MISC/Common/Common.cpp b/PowerEditor/src/MISC/Common/Common.cpp index e52364751..eb6e8ece9 100644 --- a/PowerEditor/src/MISC/Common/Common.cpp +++ b/PowerEditor/src/MISC/Common/Common.cpp @@ -777,4 +777,37 @@ double stodLocale(const generic_string& str, _locale_t loc, size_t* idx) if (idx != NULL) *idx = (size_t)(eptr - ptr); return ans; +} + +bool str2Clipboard(const TCHAR *str2cpy, HWND hwnd) +{ + if (!str2cpy) + return false; + + int len2Allocate = lstrlen(str2cpy) + 1; + len2Allocate *= sizeof(TCHAR); + unsigned int cilpboardFormat = CF_TEXT; + + cilpboardFormat = CF_UNICODETEXT; + + HGLOBAL hglbCopy = ::GlobalAlloc(GMEM_MOVEABLE, len2Allocate); + if (hglbCopy == NULL) + { + return false; + } + + if (!::OpenClipboard(hwnd)) //_pPublicInterface->getHSelf())) + return false; + + ::EmptyClipboard(); + + // Lock the handle and copy the text to the buffer. + TCHAR *pStr = (TCHAR *)::GlobalLock(hglbCopy); + lstrcpy(pStr, str2cpy); + ::GlobalUnlock(hglbCopy); + + // Place the handle on the clipboard. + ::SetClipboardData(cilpboardFormat, hglbCopy); + ::CloseClipboard(); + return true; } \ No newline at end of file diff --git a/PowerEditor/src/MISC/Common/Common.h b/PowerEditor/src/MISC/Common/Common.h index 519de7123..22572d9c0 100644 --- a/PowerEditor/src/MISC/Common/Common.h +++ b/PowerEditor/src/MISC/Common/Common.h @@ -198,4 +198,6 @@ generic_string stringJoin(const std::vector& strings, const gene generic_string stringTakeWhileAdmissable(const generic_string& input, const generic_string& admissable); double stodLocale(const generic_string& str, _locale_t loc, size_t* idx = NULL); +bool str2Clipboard(const TCHAR *str2cpy, HWND hwnd); + #endif //M30_IDE_COMMUN_H diff --git a/PowerEditor/src/Notepad_plus.cpp b/PowerEditor/src/Notepad_plus.cpp index 1d455312e..7b63f764a 100644 --- a/PowerEditor/src/Notepad_plus.cpp +++ b/PowerEditor/src/Notepad_plus.cpp @@ -4557,35 +4557,7 @@ void Notepad_plus::getCurrentOpenedFiles(Session & session, bool includUntitledD bool Notepad_plus::str2Cliboard(const TCHAR *str2cpy) { - if (!str2cpy) - return false; - - int len2Allocate = lstrlen(str2cpy) + 1; - len2Allocate *= sizeof(TCHAR); - unsigned int cilpboardFormat = CF_TEXT; - - cilpboardFormat = CF_UNICODETEXT; - - HGLOBAL hglbCopy = ::GlobalAlloc(GMEM_MOVEABLE, len2Allocate); - if (hglbCopy == NULL) - { - return false; - } - - if (!::OpenClipboard(_pPublicInterface->getHSelf())) - return false; - - ::EmptyClipboard(); - - // Lock the handle and copy the text to the buffer. - TCHAR *pStr = (TCHAR *)::GlobalLock(hglbCopy); - lstrcpy(pStr, str2cpy); - ::GlobalUnlock(hglbCopy); - - // Place the handle on the clipboard. - ::SetClipboardData(cilpboardFormat, hglbCopy); - ::CloseClipboard(); - return true; + return str2Clipboard(str2cpy, _pPublicInterface->getHSelf()); } //ONLY CALL IN CASE OF EMERGENCY: EXCEPTION diff --git a/PowerEditor/src/ScitillaComponent/FindReplaceDlg.cpp b/PowerEditor/src/ScitillaComponent/FindReplaceDlg.cpp index 289624bf2..1279b3fa0 100644 --- a/PowerEditor/src/ScitillaComponent/FindReplaceDlg.cpp +++ b/PowerEditor/src/ScitillaComponent/FindReplaceDlg.cpp @@ -2505,6 +2505,75 @@ void Finder::openAll() } } +bool Finder::isLineActualSearchResult(int line) +{ + const int foldLevel = _scintView.execute(SCI_GETFOLDLEVEL, line) & SC_FOLDLEVELNUMBERMASK; + return foldLevel == SC_FOLDLEVELBASE + 3; +} + +generic_string Finder::prepareStringForClipboard(generic_string s) +{ + // Input: a string like "\tLine 3: search result". + // Output: "search result" + s = stringReplace(s, TEXT("\r"), TEXT("")); + s = stringReplace(s, TEXT("\n"), TEXT("")); + const unsigned int firstColon = s.find(TEXT(':')); + if (firstColon == std::string::npos) + { + // Should never happen. + assert(false); + return s; + } + else + { + // Plus 2 in order to deal with ": ". + return s.substr(2 + firstColon); + } +} + +void Finder::copy() +{ + size_t fromLine, toLine; + { + const int selStart = _scintView.execute(SCI_GETSELECTIONSTART); + const int selEnd = _scintView.execute(SCI_GETSELECTIONEND); + const bool hasSelection = selStart != selEnd; + const pair lineRange = _scintView.getSelectionLinesRange(); + if (hasSelection && lineRange.first != lineRange.second) + { + fromLine = lineRange.first; + toLine = lineRange.second; + } + else + { + // Abuse fold levels to find out which lines to copy to clipboard. + // We get the current line and then the next line which has a smaller fold level (SCI_GETLASTCHILD). + // Then we loop all lines between them and determine which actually contain search results. + fromLine = _scintView.getCurrentLineNumber(); + const int selectedLineFoldLevel = _scintView.execute(SCI_GETFOLDLEVEL, fromLine) & SC_FOLDLEVELNUMBERMASK; + toLine = _scintView.execute(SCI_GETLASTCHILD, fromLine, selectedLineFoldLevel); + } + } + + std::vector lines; + for (size_t line = fromLine; line <= toLine; ++line) + { + if (isLineActualSearchResult(line)) + { + lines.push_back(prepareStringForClipboard(_scintView.getLine(line))); + } + } + const generic_string toClipboard = stringJoin(lines, TEXT("\r\n")); + if (!toClipboard.empty()) + { + if (!str2Clipboard(toClipboard.c_str(), _hSelf)) + { + assert(false); + ::MessageBox(NULL, TEXT("Error placing text in clipboard."), TEXT("Notepad++"), MB_ICONINFORMATION); + } + } +} + void Finder::beginNewFilesSearch() { //_scintView.execute(SCI_SETLEXER, SCLEX_NULL); @@ -2617,7 +2686,7 @@ BOOL CALLBACK Finder::run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam) case NPPM_INTERNAL_SCINTILLAFINFERCOPY : { - _scintView.execute(SCI_COPY); + copy(); return TRUE; } diff --git a/PowerEditor/src/ScitillaComponent/FindReplaceDlg.h b/PowerEditor/src/ScitillaComponent/FindReplaceDlg.h index 3d21ee182..280afc292 100644 --- a/PowerEditor/src/ScitillaComponent/FindReplaceDlg.h +++ b/PowerEditor/src/ScitillaComponent/FindReplaceDlg.h @@ -144,6 +144,7 @@ public: void setFinderStyle(); void removeAll(); void openAll(); + void copy(); void beginNewFilesSearch(); void finishFilesSearch(int count); void gotoNextFoundResult(int direction); @@ -177,6 +178,9 @@ private: _scintView.execute(SCI_SETREADONLY, isReadOnly); }; + bool isLineActualSearchResult(int line); + generic_string prepareStringForClipboard(generic_string s); + static FoundInfo EmptyFoundInfo; static SearchResultMarking EmptySearchResultMarking; }; diff --git a/PowerEditor/src/ScitillaComponent/ScintillaEditView.cpp b/PowerEditor/src/ScitillaComponent/ScintillaEditView.cpp index 97922c189..1e206a9b5 100644 --- a/PowerEditor/src/ScitillaComponent/ScintillaEditView.cpp +++ b/PowerEditor/src/ScitillaComponent/ScintillaEditView.cpp @@ -31,6 +31,7 @@ #include "Parameters.h" #include "Sorters.h" #include "TCHAR.h" +#include using namespace std; @@ -1913,6 +1914,15 @@ void ScintillaEditView::showCallTip(int startPos, const TCHAR * def) execute(SCI_CALLTIPSHOW, startPos, LPARAM(defA)); } +generic_string ScintillaEditView::getLine(int lineNumber) +{ + int lineLen = execute(SCI_LINELENGTH, lineNumber); + const int bufSize = lineLen; + std::unique_ptr buf = std::make_unique(bufSize); + getLine(lineNumber, buf.get(), bufSize); + return buf.get(); +} + void ScintillaEditView::getLine(int lineNumber, TCHAR * line, int lineBufferLen) { WcharMbcsConvertor *wmc = WcharMbcsConvertor::getInstance(); diff --git a/PowerEditor/src/ScitillaComponent/ScintillaEditView.h b/PowerEditor/src/ScitillaComponent/ScintillaEditView.h index eb2f34c1f..f218b83eb 100644 --- a/PowerEditor/src/ScitillaComponent/ScintillaEditView.h +++ b/PowerEditor/src/ScitillaComponent/ScintillaEditView.h @@ -272,6 +272,7 @@ public: int replaceTargetRegExMode(const TCHAR * re, int fromTargetPos = -1, int toTargetPos = -1) const; void showAutoComletion(int lenEntered, const TCHAR * list); void showCallTip(int startPos, const TCHAR * def); + generic_string getLine(int lineNumber); void getLine(int lineNumber, TCHAR * line, int lineBufferLen); void addText(int length, const char *buf);