mirror of
https://github.com/notepad-plus-plus/notepad-plus-plus.git
synced 2025-07-21 12:54:42 +02:00
Make multi-select Copy/Paste behaviour as same as column edit's one
Copy some multi-select texts and paste them make all text glued all together. This commit makes pasted texts separated by EOL, as column selection's Copy/Paste behaviour. Ref: https://github.com/notepad-plus-plus/notepad-plus-plus/issues/14266#issuecomment-1799203336 Close #14338
This commit is contained in:
parent
dadc187dc6
commit
4ff9d77d2b
@ -2276,6 +2276,13 @@ LRESULT Notepad_plus::process(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
case NPPM_INTERNAL_CHECKUNDOREDOSTATE:
|
||||
{
|
||||
checkClipboard();
|
||||
checkUndoState();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
case WM_QUERYENDSESSION:
|
||||
{
|
||||
// app should return TRUE or FALSE immediately upon receiving this message,
|
||||
|
@ -429,8 +429,8 @@ void Notepad_plus::command(int id)
|
||||
GlobalUnlock(hglbLenCopy);
|
||||
|
||||
// Place the handle on the clipboard.
|
||||
UINT f = RegisterClipboardFormat(CF_NPPTEXTLEN);
|
||||
SetClipboardData(f, hglbLenCopy);
|
||||
UINT cf_nppTextLen = RegisterClipboardFormat(CF_NPPTEXTLEN);
|
||||
SetClipboardData(cf_nppTextLen, hglbLenCopy);
|
||||
|
||||
CloseClipboard();
|
||||
|
||||
@ -442,6 +442,17 @@ void Notepad_plus::command(int id)
|
||||
case IDM_EDIT_PASTE:
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(command_mutex);
|
||||
|
||||
size_t numSelections = _pEditView->execute(SCI_GETSELECTIONS);
|
||||
Buffer* buf = getCurrentBuffer();
|
||||
bool isRO = buf->isReadOnly();
|
||||
if (numSelections > 1 && !isRO)
|
||||
{
|
||||
bool isPasteDone = _pEditView->pasteToMultiSelection();
|
||||
if (isPasteDone)
|
||||
return;
|
||||
}
|
||||
|
||||
intptr_t eolMode = _pEditView->execute(SCI_GETEOLMODE);
|
||||
_pEditView->execute(SCI_PASTE);
|
||||
_pEditView->execute(SCI_CONVERTEOLS, eolMode);
|
||||
|
@ -496,6 +496,16 @@ LRESULT ScintillaEditView::scintillaNew_Proc(HWND hwnd, UINT Message, WPARAM wPa
|
||||
::SendMessage(_hParent, WM_NOTIFY, LINKTRIGGERED, reinterpret_cast<LPARAM>(¬ification));
|
||||
|
||||
}
|
||||
else if (wParam == 'V')
|
||||
{
|
||||
if (_isMultiPasteActive)
|
||||
{
|
||||
Buffer* buf = getCurrentBuffer();
|
||||
buf->setUserReadOnly(false);
|
||||
_isMultiPasteActive = false;
|
||||
::SendMessage(_hParent, NPPM_INTERNAL_CHECKUNDOREDOSTATE, 0, 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@ -570,6 +580,30 @@ LRESULT ScintillaEditView::scintillaNew_Proc(HWND hwnd, UINT Message, WPARAM wPa
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'V':
|
||||
{
|
||||
SHORT ctrl = GetKeyState(VK_CONTROL);
|
||||
SHORT alt = GetKeyState(VK_MENU);
|
||||
SHORT shift = GetKeyState(VK_SHIFT);
|
||||
if ((ctrl & 0x8000) && !(alt & 0x8000) && !(shift & 0x8000))
|
||||
{
|
||||
Buffer* buf = getCurrentBuffer();
|
||||
bool isRO = buf->isReadOnly();
|
||||
size_t numSelections = execute(SCI_GETSELECTIONS);
|
||||
if (numSelections > 1 && !isRO)
|
||||
{
|
||||
if (pasteToMultiSelection())
|
||||
{
|
||||
// Hack for preventing the char "SYN" (0x16) from being adding into edit zone
|
||||
buf->setUserReadOnly(true);
|
||||
|
||||
_isMultiPasteActive = true; // It will be set false with WM_KEYUP message
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -4106,7 +4140,7 @@ void ScintillaEditView::changeTextDirection(bool isRTL)
|
||||
}
|
||||
}
|
||||
|
||||
generic_string ScintillaEditView::getEOLString()
|
||||
generic_string ScintillaEditView::getEOLString() const
|
||||
{
|
||||
intptr_t eol_mode = execute(SCI_GETEOLMODE);
|
||||
if (eol_mode == SC_EOL_CRLF)
|
||||
@ -4394,3 +4428,46 @@ void ScintillaEditView::removeAnyDuplicateLines()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ScintillaEditView::pasteToMultiSelection() const
|
||||
{
|
||||
size_t numSelections = execute(SCI_GETSELECTIONS);
|
||||
if (numSelections <= 1)
|
||||
return false;
|
||||
|
||||
// "MSDEVColumnSelect" is column format from Scintilla
|
||||
CLIPFORMAT cfColumnSelect = static_cast<CLIPFORMAT>(::RegisterClipboardFormat(TEXT("MSDEVColumnSelect")));
|
||||
if (IsClipboardFormatAvailable(cfColumnSelect) && OpenClipboard(NULL))
|
||||
{
|
||||
HANDLE clipboardData = ::GetClipboardData(CF_UNICODETEXT);
|
||||
::GlobalSize(clipboardData);
|
||||
LPVOID clipboardDataPtr = ::GlobalLock(clipboardData);
|
||||
if (clipboardDataPtr)
|
||||
{
|
||||
wstring clipboardStr = (const TCHAR*)clipboardDataPtr;
|
||||
::GlobalUnlock(clipboardData);
|
||||
::CloseClipboard();
|
||||
|
||||
vector<wstring> stringArray;
|
||||
stringSplit(clipboardStr, getEOLString(), stringArray);
|
||||
stringArray.erase(stringArray.cend() - 1); // remove the last empty string
|
||||
|
||||
if (numSelections == stringArray.size())
|
||||
{
|
||||
execute(SCI_BEGINUNDOACTION);
|
||||
for (size_t i = 0; i < numSelections; ++i)
|
||||
{
|
||||
LRESULT posStart = execute(SCI_GETSELECTIONNSTART, i);
|
||||
LRESULT posEnd = execute(SCI_GETSELECTIONNEND, i);
|
||||
replaceTarget(stringArray[i].c_str(), posStart, posEnd);
|
||||
posStart += stringArray[i].length();
|
||||
execute(SCI_SETSELECTIONNSTART, i, posStart);
|
||||
execute(SCI_SETSELECTIONNEND, i, posStart);
|
||||
}
|
||||
execute(SCI_ENDUNDOACTION);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -768,7 +768,7 @@ public:
|
||||
(_codepage == CP_JAPANESE) || (_codepage == CP_KOREAN));
|
||||
};
|
||||
void scrollPosToCenter(size_t pos);
|
||||
generic_string getEOLString();
|
||||
generic_string getEOLString() const;
|
||||
void setBorderEdge(bool doWithBorderEdge);
|
||||
void sortLines(size_t fromLine, size_t toLine, ISorter *pSort);
|
||||
void changeTextDirection(bool isRTL);
|
||||
@ -777,6 +777,7 @@ public:
|
||||
void markedTextToClipboard(int indiStyle, bool doAll = false);
|
||||
void removeAnyDuplicateLines();
|
||||
bool expandWordSelection();
|
||||
bool pasteToMultiSelection() const;
|
||||
|
||||
protected:
|
||||
static bool _SciInit;
|
||||
@ -811,8 +812,8 @@ protected:
|
||||
BufferStyleMap _hotspotStyles;
|
||||
|
||||
intptr_t _beginSelectPosition = -1;
|
||||
|
||||
static std::string _defaultCharList;
|
||||
bool _isMultiPasteActive = false;
|
||||
|
||||
//Lexers and Styling
|
||||
void restyleBuffer();
|
||||
|
@ -655,6 +655,7 @@
|
||||
#define NPPM_INTERNAL_NPCLAUNCHSTYLECONF (NOTEPADPLUS_USER_INTERNAL + 74)
|
||||
#define NPPM_INTERNAL_CLOSEDOC (NOTEPADPLUS_USER_INTERNAL + 75)
|
||||
#define NPPM_INTERNAL_EXTERNALLEXERBUFFER (NOTEPADPLUS_USER_INTERNAL + 76)
|
||||
#define NPPM_INTERNAL_CHECKUNDOREDOSTATE (NOTEPADPLUS_USER_INTERNAL + 77)
|
||||
|
||||
// See Notepad_plus_msgs.h
|
||||
//#define NOTEPADPLUS_USER (WM_USER + 1000)
|
||||
|
@ -4337,7 +4337,7 @@ void Editor::CopySelectionRange(SelectionText *ss, bool allowLineCopy) {
|
||||
std::sort(rangesInOrder.begin(), rangesInOrder.end());
|
||||
for (const SelectionRange ¤t : rangesInOrder) {
|
||||
text.append(RangeText(current.Start().Position(), current.End().Position()));
|
||||
if (sel.selType == Selection::SelTypes::rectangle) {
|
||||
if (rangesInOrder.size() > 1) {
|
||||
if (pdoc->eolMode != EndOfLine::Lf)
|
||||
text.push_back('\r');
|
||||
if (pdoc->eolMode != EndOfLine::Cr)
|
||||
@ -4345,7 +4345,7 @@ void Editor::CopySelectionRange(SelectionText *ss, bool allowLineCopy) {
|
||||
}
|
||||
}
|
||||
ss->Copy(text, pdoc->dbcsCodePage,
|
||||
vs.styles[StyleDefault].characterSet, sel.IsRectangular(), sel.selType == Selection::SelTypes::lines);
|
||||
vs.styles[StyleDefault].characterSet, rangesInOrder.size() > 1, sel.selType == Selection::SelTypes::lines);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user