diff options
| -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();  } | 
