aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornyamatongwe <devnull@localhost>2008-01-19 04:19:36 +0000
committernyamatongwe <devnull@localhost>2008-01-19 04:19:36 +0000
commit4663b7ffe215ea47902a467e26f4e6b40435f58d (patch)
treefd44fd40feef2aa1412b06a3832af8212ba6f252
parent541f13e28956050f2111c873dc7afeeaed981ef9 (diff)
downloadscintilla-mirror-4663b7ffe215ea47902a467e26f4e6b40435f58d.tar.gz
CopyAllowLine from 280Z28 / Sam Harwell that reproduces Visual Studio's
behaviour when performing copy on an empty selection copies the current line.
-rw-r--r--doc/ScintillaDoc.html7
-rw-r--r--doc/ScintillaHistory.html3
-rw-r--r--gtk/ScintillaGTK.cxx14
-rw-r--r--include/Scintilla.h1
-rw-r--r--include/Scintilla.iface3
-rw-r--r--src/Editor.cxx52
-rw-r--r--src/Editor.h20
-rw-r--r--win32/ScintillaWin.cxx49
8 files changed, 114 insertions, 35 deletions
diff --git a/doc/ScintillaDoc.html b/doc/ScintillaDoc.html
index 8361977cf..02553bda6 100644
--- a/doc/ScintillaDoc.html
+++ b/doc/ScintillaDoc.html
@@ -822,6 +822,7 @@ struct TextToFind {
<a class="message" href="#SCI_COPYRANGE">SCI_COPYRANGE(int start, int end)</a><br />
<a class="message" href="#SCI_COPYTEXT">SCI_COPYTEXT(int length,
const char *text)</a><br />
+ <a class="message" href="#SCI_COPYALLOWLINE">SCI_COPYALLOWLINE</a><br />
<a class="message" href="#SCI_SETPASTECONVERTENDINGS">SCI_SETPASTECONVERTENDINGS(bool convert)</a><br />
<a class="message" href="#SCI_GETPASTECONVERTENDINGS">SCI_GETPASTECONVERTENDINGS</a><br />
</code>
@@ -831,6 +832,7 @@ struct TextToFind {
<b id="SCI_PASTE">SCI_PASTE</b><br />
<b id="SCI_CLEAR">SCI_CLEAR</b><br />
<b id="SCI_CANPASTE">SCI_CANPASTE</b><br />
+ <b id="SCI_COPYALLOWLINE">SCI_COPYALLOWLINE</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
@@ -845,6 +847,11 @@ struct TextToFind {
the destination and source applications. Data from SCI_PASTE will not arrive in the
document immediately.</p>
+ <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>
+
<b id="SCI_COPYRANGE">SCI_COPYRANGE(int start, int end)</b><br />
<b id="SCI_COPYTEXT">SCI_COPYTEXT(int length, const char *text)</b><br />
<p><code>SCI_COPYRANGE</code> copies a range of text from the document to
diff --git a/doc/ScintillaHistory.html b/doc/ScintillaHistory.html
index 587987ce5..3fc9d32a3 100644
--- a/doc/ScintillaHistory.html
+++ b/doc/ScintillaHistory.html
@@ -305,12 +305,13 @@
<td>Dmitry Maslov</td>
<td>chupakabra</td>
<td>Juan Carlos Arevalo Baeza</td>
- </tr>
</tr><tr>
<td>Nick Treleaven</td>
<td>Stephen Stagg</td>
<td>Jean-Paul Iribarren</td>
<td>Tim Gerundt</td>
+ </tr><tr>
+ <td>Sam Harwell</td>
</tr>
</table>
<p>
diff --git a/gtk/ScintillaGTK.cxx b/gtk/ScintillaGTK.cxx
index 75e7a343f..0cd045b47 100644
--- a/gtk/ScintillaGTK.cxx
+++ b/gtk/ScintillaGTK.cxx
@@ -1412,7 +1412,7 @@ void ScintillaGTK::GetGtkSelectionText(GtkSelectionData *selectionData, Selectio
if ((selectionType != GDK_TARGET_STRING) && (selectionType != atomUTF8)) {
char *empty = new char[1];
empty[0] = '\0';
- selText.Set(empty, 0, SC_CP_UTF8, 0, false);
+ selText.Set(empty, 0, SC_CP_UTF8, 0, false, false);
return;
}
@@ -1431,16 +1431,16 @@ void ScintillaGTK::GetGtkSelectionText(GtkSelectionData *selectionData, Selectio
// Unknown encoding so assume in Latin1
char *destPrevious = dest;
dest = UTF8FromLatin1(dest, len);
- selText.Set(dest, len, SC_CP_UTF8, 0, selText.rectangular);
+ selText.Set(dest, len, SC_CP_UTF8, 0, selText.rectangular, false);
delete []destPrevious;
} else {
// Assume buffer is in same encoding as selection
selText.Set(dest, len, pdoc->dbcsCodePage,
- vs.styles[STYLE_DEFAULT].characterSet, isRectangular);
+ vs.styles[STYLE_DEFAULT].characterSet, isRectangular, false);
}
} else { // UTF-8
dest = Document::TransformLineEnds(&len, data, len, pdoc->eolMode);
- selText.Set(dest, len, SC_CP_UTF8, 0, isRectangular);
+ selText.Set(dest, len, SC_CP_UTF8, 0, isRectangular, false);
#ifdef USE_CONVERTER
const char *charSetBuffer = CharacterSetID();
if (!IsUnicodeMode() && *charSetBuffer) {
@@ -1448,7 +1448,7 @@ void ScintillaGTK::GetGtkSelectionText(GtkSelectionData *selectionData, Selectio
// Convert to locale
dest = ConvertText(&len, selText.s, selText.len, charSetBuffer, "UTF-8", true);
selText.Set(dest, len, pdoc->dbcsCodePage,
- vs.styles[STYLE_DEFAULT].characterSet, selText.rectangular);
+ vs.styles[STYLE_DEFAULT].characterSet, selText.rectangular, false);
}
#endif
}
@@ -1519,7 +1519,7 @@ void ScintillaGTK::GetSelection(GtkSelectionData *selection_data, guint info, Se
int tmpstr_len;
char *tmpstr = Document::TransformLineEnds(&tmpstr_len, text->s, text->len, SC_EOL_LF);
newline_normalized = new SelectionText();
- newline_normalized->Set(tmpstr, tmpstr_len, SC_CP_UTF8, 0, text->rectangular);
+ newline_normalized->Set(tmpstr, tmpstr_len, SC_CP_UTF8, 0, text->rectangular, false);
text = newline_normalized;
}
#endif
@@ -1533,7 +1533,7 @@ void ScintillaGTK::GetSelection(GtkSelectionData *selection_data, guint info, Se
int new_len;
char* tmputf = ConvertText(&new_len, text->s, text->len, "UTF-8", charSet, false);
converted = new SelectionText();
- converted->Set(tmputf, new_len, SC_CP_UTF8, 0, text->rectangular);
+ converted->Set(tmputf, new_len, SC_CP_UTF8, 0, text->rectangular, false);
text = converted;
}
}
diff --git a/include/Scintilla.h b/include/Scintilla.h
index aa7c6e1be..ac32f40d8 100644
--- a/include/Scintilla.h
+++ b/include/Scintilla.h
@@ -667,6 +667,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SCI_INDICATOREND 2509
#define SCI_SETPOSITIONCACHE 2514
#define SCI_GETPOSITIONCACHE 2515
+#define SCI_COPYALLOWLINE 2519
#define SCI_STARTRECORD 3001
#define SCI_STOPRECORD 3002
#define SCI_SETLEXER 4001
diff --git a/include/Scintilla.iface b/include/Scintilla.iface
index cabbbbb82..f847f7d13 100644
--- a/include/Scintilla.iface
+++ b/include/Scintilla.iface
@@ -1797,6 +1797,9 @@ set void SetPositionCache=2514(int size,)
# How many entries are allocated to the position cache?
get int GetPositionCache=2515(,)
+# Copy the selection, if selection empty copy the line with the caret
+fun void CopyAllowLine=2519(,)
+
# Start notifying the container of all key presses and commands.
fun void StartRecord=3001(,)
diff --git a/src/Editor.cxx b/src/Editor.cxx
index 02ca0058f..1eaf8f92e 100644
--- a/src/Editor.cxx
+++ b/src/Editor.cxx
@@ -1400,7 +1400,7 @@ void Editor::LinesJoin() {
}
}
-const char *StringFromEOLMode(int eolMode) {
+const char *Editor::StringFromEOLMode(int eolMode) {
if (eolMode == SC_EOL_CRLF) {
return "\r\n";
} else if (eolMode == SC_EOL_CR) {
@@ -3494,6 +3494,12 @@ void Editor::ClearDocumentStyle() {
pdoc->ClearLevels();
}
+void Editor::CopyAllowLine() {
+ SelectionText selectedText;
+ CopySelectionRange(&selectedText, true);
+ CopyToClipboard(selectedText);
+}
+
void Editor::Cut() {
pdoc->CheckReadOnly();
if (!pdoc->IsReadOnly() && !SelectionContainsProtected()) {
@@ -4044,6 +4050,7 @@ void Editor::NotifyMacroRecord(unsigned int iMessage, uptr_t wParam, sptr_t lPar
case SCI_PAGEUPRECTEXTEND:
case SCI_PAGEDOWNRECTEXTEND:
case SCI_SELECTIONDUPLICATE:
+ case SCI_COPYALLOWLINE:
break;
// Filter out all others like display changes. Also, newlines are redundant
@@ -4910,14 +4917,37 @@ char *Editor::CopyRange(int start, int end) {
return text;
}
-void Editor::CopySelectionFromRange(SelectionText *ss, int start, int end) {
- ss->Set(CopyRange(start, end), end - start + 1,
- pdoc->dbcsCodePage, vs.styles[STYLE_DEFAULT].characterSet, false);
+void Editor::CopySelectionFromRange(SelectionText *ss, bool allowLineCopy, int start, int end) {
+ bool isLine = allowLineCopy && (start == end);
+ if (isLine) {
+ int currentLine = pdoc->LineFromPosition(currentPos);
+ start = pdoc->LineStart(currentLine);
+ end = pdoc->LineEnd(currentLine);
+
+ char *text = CopyRange(start, end);
+ int textLen = text ? strlen(text) : 0;
+ // include room for \r\n\0
+ textLen += 3;
+ char *textWithEndl = new char[textLen];
+ textWithEndl[0] = '\0';
+ if (text)
+ strncat(textWithEndl, text, textLen);
+ if (pdoc->eolMode != SC_EOL_LF)
+ strncat(textWithEndl, "\r", textLen);
+ if (pdoc->eolMode != SC_EOL_CR)
+ strncat(textWithEndl, "\n", textLen);
+ ss->Set(textWithEndl, strlen(textWithEndl),
+ pdoc->dbcsCodePage, vs.styles[STYLE_DEFAULT].characterSet, false, true);
+ delete []text;
+ } else {
+ ss->Set(CopyRange(start, end), end - start + 1,
+ pdoc->dbcsCodePage, vs.styles[STYLE_DEFAULT].characterSet, false, false);
+ }
}
-void Editor::CopySelectionRange(SelectionText *ss) {
+void Editor::CopySelectionRange(SelectionText *ss, bool allowLineCopy) {
if (selType == selStream) {
- CopySelectionFromRange(ss, SelectionStart(), SelectionEnd());
+ CopySelectionFromRange(ss, allowLineCopy, SelectionStart(), SelectionEnd());
} else {
char *text = 0;
int size = 0;
@@ -4955,7 +4985,7 @@ void Editor::CopySelectionRange(SelectionText *ss) {
}
}
ss->Set(text, size + 1, pdoc->dbcsCodePage,
- vs.styles[STYLE_DEFAULT].characterSet, selType == selRectangle);
+ vs.styles[STYLE_DEFAULT].characterSet, selType == selRectangle, selType == selLines);
}
}
@@ -4964,14 +4994,14 @@ void Editor::CopyRangeToClipboard(int start, int end) {
end = pdoc->ClampPositionIntoDocument(end);
SelectionText selectedText;
selectedText.Set(CopyRange(start, end), end - start + 1,
- pdoc->dbcsCodePage, vs.styles[STYLE_DEFAULT].characterSet, false);
+ pdoc->dbcsCodePage, vs.styles[STYLE_DEFAULT].characterSet, false, false);
CopyToClipboard(selectedText);
}
void Editor::CopyText(int length, const char *text) {
SelectionText selectedText;
selectedText.Copy(text, length + 1,
- pdoc->dbcsCodePage, vs.styles[STYLE_DEFAULT].characterSet, false);
+ pdoc->dbcsCodePage, vs.styles[STYLE_DEFAULT].characterSet, false, false);
CopyToClipboard(selectedText);
}
@@ -5948,6 +5978,10 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
Copy();
break;
+ case SCI_COPYALLOWLINE:
+ CopyAllowLine();
+ break;
+
case SCI_COPYRANGE:
CopyRangeToClipboard(wParam, lParam);
break;
diff --git a/src/Editor.h b/src/Editor.h
index 049cc373f..ee3db99b3 100644
--- a/src/Editor.h
+++ b/src/Editor.h
@@ -54,16 +54,17 @@ public:
char *s;
int len;
bool rectangular;
+ bool lineCopy;
int codePage;
int characterSet;
- SelectionText() : s(0), len(0), rectangular(false), codePage(0), characterSet(0) {}
+ SelectionText() : s(0), len(0), rectangular(false), lineCopy(false), codePage(0), characterSet(0) {}
~SelectionText() {
Free();
}
void Free() {
- Set(0, 0, 0, 0, false);
+ Set(0, 0, 0, 0, false, false);
}
- void Set(char *s_, int len_, int codePage_, int characterSet_, bool rectangular_) {
+ void Set(char *s_, int len_, int codePage_, int characterSet_, bool rectangular_, bool lineCopy_) {
delete []s;
s = s_;
if (s)
@@ -73,8 +74,9 @@ public:
codePage = codePage_;
characterSet = characterSet_;
rectangular = rectangular_;
+ lineCopy = lineCopy_;
}
- void Copy(const char *s_, int len_, int codePage_, int characterSet_, bool rectangular_) {
+ void Copy(const char *s_, int len_, int codePage_, int characterSet_, bool rectangular_, bool lineCopy_) {
delete []s;
s = new char[len_];
if (s) {
@@ -88,9 +90,10 @@ public:
codePage = codePage_;
characterSet = characterSet_;
rectangular = rectangular_;
+ lineCopy = lineCopy_;
}
void Copy(const SelectionText &other) {
- Copy(other.s, other.len, other.codePage, other.characterSet, other.rectangular);
+ Copy(other.s, other.len, other.codePage, other.characterSet, other.rectangular, other.lineCopy);
}
};
@@ -342,6 +345,7 @@ protected: // ScintillaBase subclass needs access to much of Editor
void Cut();
void PasteRectangular(int pos, const char *ptr, int len);
virtual void Copy() = 0;
+ virtual void CopyAllowLine();
virtual bool CanPaste();
virtual void Paste() = 0;
void Clear();
@@ -406,8 +410,8 @@ protected: // ScintillaBase subclass needs access to much of Editor
virtual void CopyToClipboard(const SelectionText &selectedText) = 0;
char *CopyRange(int start, int end);
- void CopySelectionFromRange(SelectionText *ss, int start, int end);
- void CopySelectionRange(SelectionText *ss);
+ void CopySelectionFromRange(SelectionText *ss, bool allowLineCopy, int start, int end);
+ void CopySelectionRange(SelectionText *ss, bool allowLineCopy=false);
void CopyRangeToClipboard(int start, int end);
void CopyText(int length, const char *text);
void SetDragPosition(int newPos);
@@ -460,6 +464,8 @@ protected: // ScintillaBase subclass needs access to much of Editor
void StyleSetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
sptr_t StyleGetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
+ static const char *StringFromEOLMode(int eolMode);
+
public:
// Public so the COM thunks can access it.
bool IsUnicodeMode() const;
diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx
index 1ee30d444..fda84759d 100644
--- a/win32/ScintillaWin.cxx
+++ b/win32/ScintillaWin.cxx
@@ -157,6 +157,7 @@ class ScintillaWin :
bool hasOKText;
CLIPFORMAT cfColumnSelect;
+ CLIPFORMAT cfLineSelect;
HRESULT hrOle;
DropSource ds;
@@ -205,6 +206,7 @@ class ScintillaWin :
virtual void NotifyParent(SCNotification scn);
virtual void NotifyDoubleClick(Point pt, bool shift, bool ctrl, bool alt);
virtual void Copy();
+ virtual void CopyAllowLine();
virtual bool CanPaste();
virtual void Paste();
virtual void CreateCallTipWindow(PRectangle rc);
@@ -231,7 +233,7 @@ class ScintillaWin :
virtual bool GetScrollInfo(int nBar, LPSCROLLINFO lpsi);
void ChangeScrollPos(int barType, int pos);
- void InsertPasteText(const char *text, int len, int selStart, bool isRectangular);
+ void InsertPasteText(const char *text, int len, int selStart, bool isRectangular, bool isLine);
public:
// Public for benefit of Scintilla_DirectFunction
@@ -298,6 +300,10 @@ ScintillaWin::ScintillaWin(HWND hwnd) {
cfColumnSelect = static_cast<CLIPFORMAT>(
::RegisterClipboardFormat(TEXT("MSDEVColumnSelect")));
+ // Likewise for line-copy (copies a full line when no text is selected)
+ cfLineSelect = static_cast<CLIPFORMAT>(
+ ::RegisterClipboardFormat(TEXT("MSDEVLineSelect")));
+
hrOle = E_FAIL;
wMain = hwnd;
@@ -1234,6 +1240,12 @@ void ScintillaWin::Copy() {
}
}
+void ScintillaWin::CopyAllowLine() {
+ SelectionText selectedText;
+ CopySelectionRange(&selectedText, true);
+ CopyToClipboard(selectedText);
+}
+
bool ScintillaWin::CanPaste() {
if (!Editor::CanPaste())
return false;
@@ -1283,22 +1295,32 @@ public:
}
};
-void ScintillaWin::InsertPasteText(const char *text, int len, int selStart, bool isRectangular) {
+void ScintillaWin::InsertPasteText(const char *text, int len, int selStart, bool isRectangular, bool isLine) {
if (isRectangular) {
PasteRectangular(selStart, text, len);
} else {
+ char *convertedText = 0;
if (convertPastes) {
// Convert line endings of the paste into our local line-endings mode
- char *convertedString = Document::TransformLineEnds(&len, text, len, pdoc->eolMode);
- if (pdoc->InsertString(currentPos, convertedString, len)) {
- SetEmptySelection(currentPos + len);
+ convertedText = Document::TransformLineEnds(&len, text, len, pdoc->eolMode);
+ text = convertedText;
+ }
+ if (isLine) {
+ int insertPos = pdoc->LineStart(pdoc->LineFromPosition(currentPos));
+ pdoc->InsertString(insertPos, text, len);
+ // add the newline if necessary
+ if ((len > 0) && (text[len-1] != '\n' && text[len-1] != '\r')) {
+ const char *endline = StringFromEOLMode(pdoc->eolMode);
+ pdoc->InsertString(insertPos + len, endline, strlen(endline));
+ len += strlen(endline);
}
- delete []convertedString;
- } else {
- if (pdoc->InsertString(currentPos, text, len)) {
+ if (currentPos == insertPos) {
SetEmptySelection(currentPos + len);
}
+ } else if (pdoc->InsertString(currentPos, text, len)) {
+ SetEmptySelection(currentPos + len);
}
+ delete []convertedText;
}
}
@@ -1306,6 +1328,7 @@ void ScintillaWin::Paste() {
if (!::OpenClipboard(MainHWND()))
return;
pdoc->BeginUndoAction();
+ bool isLine = SelectionEmpty() && (::IsClipboardFormatAvailable(cfLineSelect) != 0);
ClearSelection();
int selStart = SelectionStart();
bool isRectangular = ::IsClipboardFormatAvailable(cfColumnSelect) != 0;
@@ -1340,7 +1363,7 @@ void ScintillaWin::Paste() {
}
if (putf) {
- InsertPasteText(putf, len, selStart, isRectangular);
+ InsertPasteText(putf, len, selStart, isRectangular, isLine);
delete []putf;
}
}
@@ -1375,11 +1398,11 @@ void ScintillaWin::Paste() {
delete []uptr;
if (putf) {
- InsertPasteText(putf, mlen, selStart, isRectangular);
+ InsertPasteText(putf, mlen, selStart, isRectangular, isLine);
delete []putf;
}
} else {
- InsertPasteText(ptr, len, selStart, isRectangular);
+ InsertPasteText(ptr, len, selStart, isRectangular, isLine);
}
}
memSelection.Unlock();
@@ -1871,6 +1894,10 @@ void ScintillaWin::CopyToClipboard(const SelectionText &selectedText) {
::SetClipboardData(cfColumnSelect, 0);
}
+ if (selectedText.lineCopy) {
+ ::SetClipboardData(cfLineSelect, 0);
+ }
+
::CloseClipboard();
}