Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions call/ScintillaCall.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -2711,6 +2711,10 @@ void ScintillaCall::CopyAllowLine() {
Call(Message::CopyAllowLine);
}

void ScintillaCall::CutAllowLine() {
Call(Message::CutAllowLine);
}

void *ScintillaCall::CharacterPointer() {
return reinterpret_cast<void *>(Call(Message::GetCharacterPointer));
}
Expand Down
7 changes: 7 additions & 0 deletions doc/ScintillaDoc.html
Original file line number Diff line number Diff line change
Expand Up @@ -1852,6 +1852,7 @@ <h2 id="CutCopyAndPaste">Cut, copy and paste</h2>
<a class="message" href="#SCI_COPYRANGE">SCI_COPYRANGE(position start, position end)</a><br />
<a class="message" href="#SCI_COPYTEXT">SCI_COPYTEXT(position length, const char *text)</a><br />
<a class="message" href="#SCI_COPYALLOWLINE">SCI_COPYALLOWLINE</a><br />
<a class="message" href="#SCI_CUTALLOWLINE">SCI_CUTALLOWLINE</a><br />
<a class="message" href="#SCI_SETPASTECONVERTENDINGS">SCI_SETPASTECONVERTENDINGS(bool convert)</a><br />
<a class="message" href="#SCI_GETPASTECONVERTENDINGS">SCI_GETPASTECONVERTENDINGS &rarr; bool</a><br />
<a class="message" href="#SCI_REPLACERECTANGULAR">SCI_REPLACERECTANGULAR(position length, const char *text)</a><br />
Expand All @@ -1863,6 +1864,7 @@ <h2 id="CutCopyAndPaste">Cut, copy and paste</h2>
<b id="SCI_CLEAR">SCI_CLEAR</b><br />
<b id="SCI_CANPASTE">SCI_CANPASTE &rarr; bool</b><br />
<b id="SCI_COPYALLOWLINE">SCI_COPYALLOWLINE</b><br />
<b id="SCI_CUTALLOWLINE">SCI_CUTALLOWLINE</b><br />
These commands perform the standard tasks of cutting and copying data to the clipboard,
pasting from the clipboard into the document, and clearing the document.
<code>SCI_CANPASTE</code> returns non-zero if the document isn't read-only and if the selection
Expand All @@ -1880,6 +1882,11 @@ <h2 id="CutCopyAndPaste">Cut, copy and paste</h2>
<p><code>SCI_COPYALLOWLINE</code> works the same as SCI_COPY except that if the
selection is empty then the current line is copied. On Windows, an extra "MSDEVLineSelect" marker
is added to the clipboard which is then used in <code>SCI_PASTE</code> to paste
the whole line before the current line.</p>

<p><code>SCI_CUTALLOWLINE</code> works the same as SCI_CUT except that if the
selection is empty then the current line is cut. On Windows, an extra "MSDEVLineSelect" marker
is added to the clipboard which is then used in <code>SCI_PASTE</code> to paste
the whole line before the current line.</p>

<b id="SCI_COPYRANGE">SCI_COPYRANGE(position start, position end)</b><br />
Expand Down
1 change: 1 addition & 0 deletions include/Scintilla.h
Original file line number Diff line number Diff line change
Expand Up @@ -976,6 +976,7 @@ typedef sptr_t (*SciFnDirectStatus)(sptr_t ptr, unsigned int iMessage, uptr_t wP
#define SCI_SETLAYOUTTHREADS 2775
#define SCI_GETLAYOUTTHREADS 2776
#define SCI_COPYALLOWLINE 2519
#define SCI_CUTALLOWLINE 2805
#define SCI_GETCHARACTERPOINTER 2520
#define SCI_GETRANGEPOINTER 2643
#define SCI_GETGAPPOSITION 2644
Expand Down
3 changes: 3 additions & 0 deletions include/Scintilla.iface
Original file line number Diff line number Diff line change
Expand Up @@ -2657,6 +2657,9 @@ get int GetLayoutThreads=2776(,)
# Copy the selection, if selection empty copy the line with the caret
fun void CopyAllowLine=2519(,)

# Cut the selection, if selection empty cut the line with the caret
fun void CutAllowLine=2805(,)

# Compact the document buffer and return a read-only pointer to the
# characters in the document.
get pointer GetCharacterPointer=2520(,)
Expand Down
1 change: 1 addition & 0 deletions include/ScintillaCall.h
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,7 @@ class ScintillaCall {
void SetLayoutThreads(int threads);
int LayoutThreads();
void CopyAllowLine();
void CutAllowLine();
void *CharacterPointer();
void *RangePointer(Position start, Position lengthRange);
Position GapPosition();
Expand Down
1 change: 1 addition & 0 deletions include/ScintillaMessages.h
Original file line number Diff line number Diff line change
Expand Up @@ -637,6 +637,7 @@ enum class Message {
SetLayoutThreads = 2775,
GetLayoutThreads = 2776,
CopyAllowLine = 2519,
CutAllowLine = 2805,
GetCharacterPointer = 2520,
GetRangePointer = 2643,
GetGapPosition = 2644,
Expand Down
67 changes: 50 additions & 17 deletions src/Editor.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -2267,6 +2267,21 @@ void Editor::CopyAllowLine() {
CopyToClipboard(selectedText);
}

void Editor::CutAllowLine() {
if (sel.Empty()) {
pdoc->CheckReadOnly();
if (!pdoc->IsReadOnly()) {
SelectionText selectedText;
if (CopyLineRange(&selectedText, false)) {
CopyToClipboard(selectedText);
LineDelete();
}
}
} else {
Cut();
}
}

void Editor::Cut() {
pdoc->CheckReadOnly();
if (!pdoc->IsReadOnly() && !SelectionContainsProtected()) {
Expand Down Expand Up @@ -2959,6 +2974,7 @@ void Editor::NotifyMacroRecord(Message iMessage, uptr_t wParam, sptr_t lParam) {
case Message::PageDownRectExtend:
case Message::SelectionDuplicate:
case Message::CopyAllowLine:
case Message::CutAllowLine:
case Message::VerticalCentreCaret:
case Message::MoveSelectedLinesUp:
case Message::MoveSelectedLinesDown:
Expand Down Expand Up @@ -3081,6 +3097,13 @@ void Editor::ChangeCaseOfSelection(CaseMapping caseMapping) {
}
}

void Editor::LineDelete() {
const Sci::Line line = pdoc->SciLineFromPosition(sel.MainCaret());
const Sci::Position start = pdoc->LineStart(line);
const Sci::Position end = pdoc->LineStart(line + 1);
pdoc->DeleteChars(start, end - start);
}

void Editor::LineTranspose() {
const Sci::Line line = pdoc->SciLineFromPosition(sel.MainCaret());
if (line > 0) {
Expand Down Expand Up @@ -3991,12 +4014,8 @@ int Editor::KeyCommand(Message iMessage) {
SetLastXChosen();
}
break;
case Message::LineDelete: {
const Sci::Line line = pdoc->SciLineFromPosition(sel.MainCaret());
const Sci::Position start = pdoc->LineStart(line);
const Sci::Position end = pdoc->LineStart(line + 1);
pdoc->DeleteChars(start, end - start);
}
case Message::LineDelete:
LineDelete();
break;
case Message::LineTranspose:
LineTranspose();
Expand Down Expand Up @@ -4316,20 +4335,29 @@ std::string Editor::RangeText(Sci::Position start, Sci::Position end) const {
return std::string();
}

bool Editor::CopyLineRange(SelectionText *ss, bool allowProtected) {
const Sci::Line currentLine = pdoc->SciLineFromPosition(sel.MainCaret());
const Sci::Position start = pdoc->LineStart(currentLine);
const Sci::Position end = pdoc->LineEnd(currentLine);

if (allowProtected || !RangeContainsProtected(start, end)) {
std::string text = RangeText(start, end);
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, false, true);
return true;
} else {
return false;
}
}

void Editor::CopySelectionRange(SelectionText *ss, bool allowLineCopy) {
if (sel.Empty()) {
if (allowLineCopy) {
const Sci::Line currentLine = pdoc->SciLineFromPosition(sel.MainCaret());
const Sci::Position start = pdoc->LineStart(currentLine);
const Sci::Position end = pdoc->LineEnd(currentLine);

std::string text = RangeText(start, end);
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, false, true);
CopyLineRange(ss);
}
} else {
std::string text;
Expand Down Expand Up @@ -6183,6 +6211,11 @@ sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) {
CopyAllowLine();
break;

case Message::CutAllowLine:
CutAllowLine();
SetLastXChosen();
break;

case Message::VerticalCentreCaret:
VerticalCentreCaret();
break;
Expand Down
3 changes: 3 additions & 0 deletions src/Editor.h
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,7 @@ class Editor : public EditModel, public DocWatcher {
void PasteRectangular(SelectionPosition pos, const char *ptr, Sci::Position len);
virtual void Copy() = 0;
void CopyAllowLine();
void CutAllowLine();
virtual bool CanPaste();
virtual void Paste() = 0;
void Clear();
Expand Down Expand Up @@ -481,6 +482,7 @@ class Editor : public EditModel, public DocWatcher {
enum class CaseMapping { same, upper, lower };
virtual std::string CaseMapString(const std::string &s, CaseMapping caseMapping);
void ChangeCaseOfSelection(CaseMapping caseMapping);
void LineDelete();
void LineTranspose();
void LineReverse();
void Duplicate(bool forLine);
Expand Down Expand Up @@ -515,6 +517,7 @@ class Editor : public EditModel, public DocWatcher {

virtual void CopyToClipboard(const SelectionText &selectedText) = 0;
std::string RangeText(Sci::Position start, Sci::Position end) const;
bool CopyLineRange(SelectionText *ss, bool allowProtected=true);
void CopySelectionRange(SelectionText *ss, bool allowLineCopy=false);
void CopyRangeToClipboard(Sci::Position start, Sci::Position end);
void CopyText(size_t length, const char *text);
Expand Down
13 changes: 13 additions & 0 deletions test/simpleTests.py
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,19 @@ def testCopyAllowLine(self):
self.ed.EOLMode = lineEndType
self.assertEqual(self.ed.Contents(), b"a1\na1\nb2")

def testCutAllowLine(self):
lineEndType = self.ed.EOLMode
self.ed.EOLMode = self.ed.SC_EOL_LF
self.ed.AddText(5, b"a1\nb2")
self.ed.SetSel(1,1)
self.ed.CutAllowLine()
# Clipboard = "a1\n"
self.assertEqual(self.ed.CanPaste(), 1)
self.ed.SetSel(0, 0)
self.ed.Paste()
self.ed.EOLMode = lineEndType
self.assertEqual(self.ed.Contents(), b"a1\nb2")

def testDuplicate(self):
self.ed.AddText(3, b"1b2")
self.ed.SetSel(1,2)
Expand Down
2 changes: 1 addition & 1 deletion win32/ScintillaWin.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -594,7 +594,7 @@ ScintillaWin::ScintillaWin(HWND hwnd) {
cfColumnSelect = RegisterClipboardType(L"MSDEVColumnSelect");
cfBorlandIDEBlockType = RegisterClipboardType(L"Borland IDE Block Type");

// Likewise for line-copy (copies a full line when no text is selected)
// Likewise for line-copy or line-cut (copies or cuts a full line when no text is selected)
cfLineSelect = RegisterClipboardType(L"MSDEVLineSelect");
cfVSLineTag = RegisterClipboardType(L"VisualStudioEditorOperationsLineCutCopyClipboardTag");
hrOle = E_FAIL;
Expand Down