diff --git a/PowerEditor/src/MISC/Common/Common.cpp b/PowerEditor/src/MISC/Common/Common.cpp index e5236475..eb6e8ece 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 519de712..22572d9c 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 1d455312..7b63f764 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 289624bf..1279b3fa 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 3d21ee18..280afc29 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 97922c18..1e206a9b 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 eb2f34c1..f218b83e 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);