Skip to content

Commit

Permalink
Make multi-select Copy/Paste behaviour as same as column edit's one
Browse files Browse the repository at this point in the history
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: notepad-plus-plus#14266 (comment)

Close notepad-plus-plus#14338
  • Loading branch information
donho committed Nov 10, 2023
1 parent dadc187 commit 4ff9d77
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 7 deletions.
7 changes: 7 additions & 0 deletions PowerEditor/src/NppBigSwitch.cpp
Expand Up @@ -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,
Expand Down
15 changes: 13 additions & 2 deletions PowerEditor/src/NppCommands.cpp
Expand Up @@ -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();

Expand All @@ -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);
Expand Down
79 changes: 78 additions & 1 deletion PowerEditor/src/ScintillaComponent/ScintillaEditView.cpp
Expand Up @@ -496,6 +496,16 @@ LRESULT ScintillaEditView::scintillaNew_Proc(HWND hwnd, UINT Message, WPARAM wPa
::SendMessage(_hParent, WM_NOTIFY, LINKTRIGGERED, reinterpret_cast<LPARAM>(&notification));

}
else if (wParam == 'V')
{
if (_isMultiPasteActive)
{
Buffer* buf = getCurrentBuffer();
buf->setUserReadOnly(false);
_isMultiPasteActive = false;
::SendMessage(_hParent, NPPM_INTERNAL_CHECKUNDOREDOSTATE, 0, 0);
}
}
break;
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
}
5 changes: 3 additions & 2 deletions PowerEditor/src/ScintillaComponent/ScintillaEditView.h
Expand Up @@ -768,7 +768,7 @@ friend class Finder;
(_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);
Expand All @@ -777,6 +777,7 @@ friend class Finder;
void markedTextToClipboard(int indiStyle, bool doAll = false);
void removeAnyDuplicateLines();
bool expandWordSelection();
bool pasteToMultiSelection() const;

protected:
static bool _SciInit;
Expand Down Expand Up @@ -811,8 +812,8 @@ friend class Finder;
BufferStyleMap _hotspotStyles;

intptr_t _beginSelectPosition = -1;

static std::string _defaultCharList;
bool _isMultiPasteActive = false;

//Lexers and Styling
void restyleBuffer();
Expand Down
1 change: 1 addition & 0 deletions PowerEditor/src/resource.h
Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions scintilla/src/Editor.cxx
Expand Up @@ -4337,15 +4337,15 @@ void Editor::CopySelectionRange(SelectionText *ss, bool allowLineCopy) {
std::sort(rangesInOrder.begin(), rangesInOrder.end());
for (const SelectionRange &current : 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)
text.push_back('\n');
}
}
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);
}
}

Expand Down

0 comments on commit 4ff9d77

Please sign in to comment.