Merge pull request #150 from andreas-jonsson/finder_copy2

[ENHANCEMENT] Improve copy found lines to clipboard.
This commit is contained in:
Don HO 2015-06-01 20:54:29 +02:00
commit ed8a51334d
9 changed files with 145 additions and 38 deletions

View File

@ -778,3 +778,50 @@ double stodLocale(const generic_string& str, _locale_t loc, size_t* idx)
*idx = (size_t)(eptr - ptr); *idx = (size_t)(eptr - ptr);
return ans; return ans;
} }
bool str2Clipboard(const generic_string &str2cpy, HWND hwnd)
{
int len2Allocate = (str2cpy.size() + 1) * sizeof(TCHAR);
HGLOBAL hglbCopy = ::GlobalAlloc(GMEM_MOVEABLE, len2Allocate);
if (hglbCopy == NULL)
{
return false;
}
if (!::OpenClipboard(hwnd))
{
::GlobalFree(hglbCopy);
::CloseClipboard();
return false;
}
if (!::EmptyClipboard())
{
::GlobalFree(hglbCopy);
::CloseClipboard();
return false;
}
// Lock the handle and copy the text to the buffer.
TCHAR *pStr = (TCHAR *)::GlobalLock(hglbCopy);
if (pStr == NULL)
{
::GlobalUnlock(hglbCopy);
::GlobalFree(hglbCopy);
::CloseClipboard();
return false;
}
_tcscpy_s(pStr, len2Allocate / sizeof(TCHAR), str2cpy.c_str());
::GlobalUnlock(hglbCopy);
// Place the handle on the clipboard.
unsigned int clipBoardFormat = CF_UNICODETEXT;
if (::SetClipboardData(clipBoardFormat, hglbCopy) == NULL)
{
::GlobalUnlock(hglbCopy);
::GlobalFree(hglbCopy);
::CloseClipboard();
return false;
}
if (!::CloseClipboard())
{
return false;
}
return true;
}

View File

@ -198,4 +198,6 @@ generic_string stringJoin(const std::vector<generic_string>& strings, const gene
generic_string stringTakeWhileAdmissable(const generic_string& input, const generic_string& admissable); generic_string stringTakeWhileAdmissable(const generic_string& input, const generic_string& admissable);
double stodLocale(const generic_string& str, _locale_t loc, size_t* idx = NULL); double stodLocale(const generic_string& str, _locale_t loc, size_t* idx = NULL);
bool str2Clipboard(const generic_string &str2cpy, HWND hwnd);
#endif //M30_IDE_COMMUN_H #endif //M30_IDE_COMMUN_H

View File

@ -1933,7 +1933,7 @@ void Notepad_plus::copyMarkedLines()
globalStr = currentStr; globalStr = currentStr;
} }
} }
str2Cliboard(globalStr.c_str()); str2Cliboard(globalStr);
} }
void Notepad_plus::cutMarkedLines() void Notepad_plus::cutMarkedLines()
@ -1953,7 +1953,7 @@ void Notepad_plus::cutMarkedLines()
} }
} }
_pEditView->execute(SCI_ENDUNDOACTION); _pEditView->execute(SCI_ENDUNDOACTION);
str2Cliboard(globalStr.c_str()); str2Cliboard(globalStr);
} }
void Notepad_plus::deleteMarkedLines(bool isMarked) void Notepad_plus::deleteMarkedLines(bool isMarked)
@ -4555,37 +4555,9 @@ void Notepad_plus::getCurrentOpenedFiles(Session & session, bool includUntitledD
_invisibleEditView.execute(SCI_SETDOCPOINTER, 0, oldDoc); _invisibleEditView.execute(SCI_SETDOCPOINTER, 0, oldDoc);
} }
bool Notepad_plus::str2Cliboard(const TCHAR *str2cpy) bool Notepad_plus::str2Cliboard(const generic_string & str2cpy)
{ {
if (!str2cpy) return str2Clipboard(str2cpy, _pPublicInterface->getHSelf());
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;
} }
//ONLY CALL IN CASE OF EMERGENCY: EXCEPTION //ONLY CALL IN CASE OF EMERGENCY: EXCEPTION

View File

@ -599,7 +599,7 @@ private:
void doSynScorll(HWND hW); void doSynScorll(HWND hW);
void setWorkingDir(const TCHAR *dir); void setWorkingDir(const TCHAR *dir);
bool str2Cliboard(const TCHAR *str2cpy); bool str2Cliboard(const generic_string & str2cpy);
bool bin2Cliboard(const UCHAR *uchar2cpy, size_t length); bool bin2Cliboard(const UCHAR *uchar2cpy, size_t length);
bool getIntegralDockingData(tTbData & dockData, int & iCont, bool & isVisible); bool getIntegralDockingData(tTbData & dockData, int & iCont, bool & isVisible);

View File

@ -676,7 +676,7 @@ void Notepad_plus::command(int id)
{ {
generic_string dir(buf->getFullPathName()); generic_string dir(buf->getFullPathName());
PathRemoveFileSpec(dir); PathRemoveFileSpec(dir);
str2Cliboard(dir.c_str()); str2Cliboard(dir);
} }
else if (id == IDM_EDIT_FILENAMETOCLIP) else if (id == IDM_EDIT_FILENAMETOCLIP)
{ {

View File

@ -2505,6 +2505,75 @@ void Finder::openAll()
} }
} }
bool Finder::isLineActualSearchResult(int line) const
{
const int foldLevel = _scintView.execute(SCI_GETFOLDLEVEL, line) & SC_FOLDLEVELNUMBERMASK;
return foldLevel == SC_FOLDLEVELBASE + 3;
}
generic_string Finder::prepareStringForClipboard(generic_string s) const
{
// 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<int, int> 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<generic_string> 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() void Finder::beginNewFilesSearch()
{ {
//_scintView.execute(SCI_SETLEXER, SCLEX_NULL); //_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 : case NPPM_INTERNAL_SCINTILLAFINFERCOPY :
{ {
_scintView.execute(SCI_COPY); copy();
return TRUE; return TRUE;
} }
@ -2658,10 +2727,10 @@ BOOL CALLBACK Finder::run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam)
tmp.push_back(MenuItemUnit(NPPM_INTERNAL_SCINTILLAFINFERUNCOLLAPSE, TEXT("Uncollapse all"))); tmp.push_back(MenuItemUnit(NPPM_INTERNAL_SCINTILLAFINFERUNCOLLAPSE, TEXT("Uncollapse all")));
tmp.push_back(MenuItemUnit(0, TEXT("Separator"))); tmp.push_back(MenuItemUnit(0, TEXT("Separator")));
tmp.push_back(MenuItemUnit(NPPM_INTERNAL_SCINTILLAFINFERCOPY, TEXT("Copy"))); 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_SCINTILLAFINFERSELECTALL, TEXT("Select all")));
tmp.push_back(MenuItemUnit(NPPM_INTERNAL_SCINTILLAFINFERCLEARALL, TEXT("Clear All"))); tmp.push_back(MenuItemUnit(NPPM_INTERNAL_SCINTILLAFINFERCLEARALL, TEXT("Clear all")));
tmp.push_back(MenuItemUnit(0, TEXT("Separator"))); tmp.push_back(MenuItemUnit(0, TEXT("Separator")));
tmp.push_back(MenuItemUnit(NPPM_INTERNAL_SCINTILLAFINFEROPENALL, TEXT("Open All"))); tmp.push_back(MenuItemUnit(NPPM_INTERNAL_SCINTILLAFINFEROPENALL, TEXT("Open all")));
scintillaContextmenu.create(_hSelf, tmp); scintillaContextmenu.create(_hSelf, tmp);

View File

@ -144,6 +144,7 @@ public:
void setFinderStyle(); void setFinderStyle();
void removeAll(); void removeAll();
void openAll(); void openAll();
void copy();
void beginNewFilesSearch(); void beginNewFilesSearch();
void finishFilesSearch(int count); void finishFilesSearch(int count);
void gotoNextFoundResult(int direction); void gotoNextFoundResult(int direction);
@ -177,6 +178,9 @@ private:
_scintView.execute(SCI_SETREADONLY, isReadOnly); _scintView.execute(SCI_SETREADONLY, isReadOnly);
}; };
bool isLineActualSearchResult(int line) const;
generic_string prepareStringForClipboard(generic_string s) const;
static FoundInfo EmptyFoundInfo; static FoundInfo EmptyFoundInfo;
static SearchResultMarking EmptySearchResultMarking; static SearchResultMarking EmptySearchResultMarking;
}; };

View File

@ -31,6 +31,7 @@
#include "Parameters.h" #include "Parameters.h"
#include "Sorters.h" #include "Sorters.h"
#include "TCHAR.h" #include "TCHAR.h"
#include <memory>
using namespace std; using namespace std;
@ -1913,11 +1914,22 @@ void ScintillaEditView::showCallTip(int startPos, const TCHAR * def)
execute(SCI_CALLTIPSHOW, startPos, LPARAM(defA)); execute(SCI_CALLTIPSHOW, startPos, LPARAM(defA));
} }
generic_string ScintillaEditView::getLine(int lineNumber)
{
int lineLen = execute(SCI_LINELENGTH, lineNumber);
const int bufSize = lineLen + 1;
std::unique_ptr<TCHAR[]> buf = std::make_unique<TCHAR[]>(bufSize);
getLine(lineNumber, buf.get(), bufSize);
return buf.get();
}
void ScintillaEditView::getLine(int lineNumber, TCHAR * line, int lineBufferLen) void ScintillaEditView::getLine(int lineNumber, TCHAR * line, int lineBufferLen)
{ {
WcharMbcsConvertor *wmc = WcharMbcsConvertor::getInstance(); WcharMbcsConvertor *wmc = WcharMbcsConvertor::getInstance();
unsigned int cp = execute(SCI_GETCODEPAGE); unsigned int cp = execute(SCI_GETCODEPAGE);
char *lineA = new char[lineBufferLen]; char *lineA = new char[lineBufferLen];
// From Scintilla documentation for SCI_GETLINE: "The buffer is not terminated by a 0 character."
memset(lineA, '\0', sizeof(char) * lineBufferLen);
execute(SCI_GETLINE, lineNumber, (LPARAM)lineA); execute(SCI_GETLINE, lineNumber, (LPARAM)lineA);
const TCHAR *lineW = wmc->char2wchar(lineA, cp); const TCHAR *lineW = wmc->char2wchar(lineA, cp);
lstrcpyn(line, lineW, lineBufferLen); lstrcpyn(line, lineW, lineBufferLen);

View File

@ -272,6 +272,7 @@ public:
int replaceTargetRegExMode(const TCHAR * re, 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); void showAutoComletion(int lenEntered, const TCHAR * list);
void showCallTip(int startPos, const TCHAR * def); void showCallTip(int startPos, const TCHAR * def);
generic_string getLine(int lineNumber);
void getLine(int lineNumber, TCHAR * line, int lineBufferLen); void getLine(int lineNumber, TCHAR * line, int lineBufferLen);
void addText(int length, const char *buf); void addText(int length, const char *buf);