diff options
| -rw-r--r-- | gtk/ScintillaGTK.cxx | 119 | 
1 files changed, 70 insertions, 49 deletions
| diff --git a/gtk/ScintillaGTK.cxx b/gtk/ScintillaGTK.cxx index 36e392be6..9aecb5829 100644 --- a/gtk/ScintillaGTK.cxx +++ b/gtk/ScintillaGTK.cxx @@ -126,6 +126,7 @@ private:  	virtual void AddToPopUp(const char *label, int cmd = 0, bool enabled = true);  	bool OwnPrimarySelection();  	virtual void ClaimSelection(); +	char *GetGtkSelectionText(const GtkSelectionData *selectionData, unsigned int *len, bool *isRectangular);  	void ReceivedSelection(GtkSelectionData *selection_data);  	void ReceivedDrop(GtkSelectionData *selection_data);  	void GetSelection(GtkSelectionData *selection_data, guint info, SelectionText *selected); @@ -859,55 +860,81 @@ void ScintillaGTK::ClaimSelection() {  	}  } +char *ScintillaGTK::GetGtkSelectionText(const GtkSelectionData *selectionData,  +	unsigned int* len, bool* isRectangular) { +	char *dest; +	unsigned int i; +	const char *sptr; +	char *dptr; + +	// Return empty string if selection is not a string +	if (selectionData->type != GDK_TARGET_STRING) { +		dest = new char[1]; +		strcpy(dest, ""); +		*isRectangular = false; +		*len = 0; +		return dest; +	} + +	// Need to convert to correct newline form for this file: win32gtk *always* returns  +	// only \n line delimiter from clipboard, and linux/unix gtk may also not send the  +	// form that matches the document (this is probably not effectively standardized by X) +	dest = new char[(2 * static_cast<unsigned int>(selectionData->length)) + 1]; +	sptr = reinterpret_cast<const char *>(selectionData->data); +	dptr = dest; +	for (i = 0; i < static_cast<unsigned int>(selectionData->length) && *sptr != '\0'; i++) { +		if (*sptr == '\n' || *sptr == '\r') { +			if (pdoc->eolMode == SC_EOL_CR) { +				*dptr++ = '\r'; +			} +			else if (pdoc->eolMode == SC_EOL_LF) { +				*dptr++ = '\n'; +			} +			else { // pdoc->eolMode == SC_EOL_CRLF +				*dptr++ = '\r'; +				*dptr++ = '\n'; +			} +			if (*sptr == '\r' && i+1 < static_cast<unsigned int>(selectionData->length) && *(sptr+1) == '\n') { +				i++; +				sptr++; +			} +			sptr++; +		} +		else { +			*dptr++ = *sptr++; +		} +	} +	*dptr++ = '\0'; + +	*len = (dptr - dest) - 1; + +	// Check for "\n\0" ending to string indicating that selection is rectangular +#if PLAT_GTK_WIN32 +	*isRectangular = ::IsClipboardFormatAvailable(cfColumnSelect) != 0; +#else +	*isRectangular = ((selectionData->length > 2) && +			  (selectionData->data[selectionData->length - 1] == 0 && +			   selectionData->data[selectionData->length - 2] == '\n')); +#endif +	return dest;			      +} +  void ScintillaGTK::ReceivedSelection(GtkSelectionData *selection_data) {  	if (selection_data->type == GDK_TARGET_STRING) {  		//Platform::DebugPrintf("Received String Selection %x %d\n", selection_data->selection, selection_data->length);  		if (((selection_data->selection == clipboard_atom) ||  		        (selection_data->selection == GDK_SELECTION_PRIMARY)) &&  		        (selection_data->length > 0)) { -			char *ptr = reinterpret_cast<char *>(selection_data->data); -			unsigned int len = selection_data->length; -			unsigned int i; -			for (i = 0; i < static_cast<unsigned int>(selection_data->length); i++) { -				if ((len == static_cast<unsigned int>(selection_data->length)) && (0 == ptr[i])) -					len = i; -			}                      -#if PLAT_GTK_WIN32 -			/* Need to convert \n to correct newline form for this file as win32gtk always returns */ -			/* only \n line delimiter from clipboard */ -			char *tmpstr = new char [2 * len]; -			char *dptr = tmpstr; -			char *sptr = ptr; -			unsigned int newlen = len;                      -			for (i = 0; i < len; i++) { -				if (*sptr == '\n') { -					if (pdoc->eolMode != SC_EOL_LF) -						*dptr++ = '\r'; -					if (pdoc->eolMode != SC_EOL_CR) -						*dptr++ = '\n'; -					if (pdoc->eolMode == SC_EOL_CRLF) -						newlen++; -					sptr++; -				} -				else { -					*dptr++ = *sptr++; -				} -			} -			ptr = tmpstr; -			len = newlen; -#endif +			unsigned int len; +			bool isRectangular; +			char *ptr = GetGtkSelectionText(selection_data, &len, &isRectangular); +  			pdoc->BeginUndoAction();  			int selStart = SelectionStart();  			if (selection_data->selection != GDK_SELECTION_PRIMARY) {  				ClearSelection();  			} -			// Check for "\n\0" ending to string indicating that selection is rectangular -#if PLAT_GTK_WIN32 -			bool isRectangular = ::IsClipboardFormatAvailable(cfColumnSelect) != 0; -#else -			bool isRectangular = ((selection_data->length > 1) && -			                      (ptr[selection_data->length - 1] == 0 && ptr[selection_data->length - 2] == '\n')); -#endif +  			if (isRectangular) {  				PasteRectangular(selStart, ptr, len);  			} else { @@ -915,9 +942,7 @@ void ScintillaGTK::ReceivedSelection(GtkSelectionData *selection_data) {  				SetEmptySelection(currentPos + len);  			}  			pdoc->EndUndoAction(); -#if PLAT_GTK_WIN32 -			delete []tmpstr; -#endif +			delete []ptr;  		}  	}  	Redraw(); @@ -927,15 +952,11 @@ void ScintillaGTK::ReceivedDrop(GtkSelectionData *selection_data) {  	dragWasDropped = true;  	if (selection_data->type == GDK_TARGET_STRING) {  		if (selection_data->length > 0) { -			char *ptr = reinterpret_cast<char *>(selection_data->data); -			// 3rd argument is false because the deletion of the moved data is handle by GetSelection -#if PLAT_GTK_WIN32 -			bool isRectangular = ::IsClipboardFormatAvailable(cfColumnSelect) != 0; -#else -			bool isRectangular = ((selection_data->length > 1) && -			                      (ptr[selection_data->length - 1] == 0 && ptr[selection_data->length - 2] == '\n')); -#endif +			unsigned int len; +			bool isRectangular; +			char *ptr = GetGtkSelectionText(selection_data, &len, &isRectangular);  			DropAt(posDrop, ptr, false, isRectangular); +			delete []ptr;  		}  	} else {  		char *ptr = reinterpret_cast<char *>(selection_data->data); | 
