diff options
author | nyamatongwe <devnull@localhost> | 2008-01-19 04:19:36 +0000 |
---|---|---|
committer | nyamatongwe <devnull@localhost> | 2008-01-19 04:19:36 +0000 |
commit | 4663b7ffe215ea47902a467e26f4e6b40435f58d (patch) | |
tree | fd44fd40feef2aa1412b06a3832af8212ba6f252 | |
parent | 541f13e28956050f2111c873dc7afeeaed981ef9 (diff) | |
download | scintilla-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.html | 7 | ||||
-rw-r--r-- | doc/ScintillaHistory.html | 3 | ||||
-rw-r--r-- | gtk/ScintillaGTK.cxx | 14 | ||||
-rw-r--r-- | include/Scintilla.h | 1 | ||||
-rw-r--r-- | include/Scintilla.iface | 3 | ||||
-rw-r--r-- | src/Editor.cxx | 52 | ||||
-rw-r--r-- | src/Editor.h | 20 | ||||
-rw-r--r-- | win32/ScintillaWin.cxx | 49 |
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(); } |