diff options
Diffstat (limited to 'gtk/ScintillaGTK.cxx')
| -rw-r--r-- | gtk/ScintillaGTK.cxx | 233 | 
1 files changed, 160 insertions, 73 deletions
diff --git a/gtk/ScintillaGTK.cxx b/gtk/ScintillaGTK.cxx index b066ab7b2..d75072d27 100644 --- a/gtk/ScintillaGTK.cxx +++ b/gtk/ScintillaGTK.cxx @@ -79,7 +79,9 @@ class ScintillaGTK : public ScintillaBase {  	int scrollBarHeight;  	// Because clipboard access is asynchronous, copyText is created by Copy +#if GTK_MAJOR_VERSION == 1  	SelectionText copyText; +#endif  	SelectionText primary; @@ -90,10 +92,10 @@ class ScintillaGTK : public ScintillaBase {  	GtkWidgetClass *parentClass; -	GdkAtom atomClipboard; +	static GdkAtom atomClipboard; +	static GdkAtom atomUTF8; +	static GdkAtom atomString;  	GdkAtom atomSought; -	GdkAtom atomUTF8; -	GdkAtom atomString;  #if PLAT_GTK_WIN32  	CLIPFORMAT cfColumnSelect; @@ -162,10 +164,15 @@ private:  	virtual void AddToPopUp(const char *label, int cmd = 0, bool enabled = true);  	bool OwnPrimarySelection();  	virtual void ClaimSelection(); -	void GetGtkSelectionText(const GtkSelectionData *selectionData, SelectionText &selText); +	void GetGtkSelectionText(GtkSelectionData *selectionData, SelectionText &selText);  	void ReceivedSelection(GtkSelectionData *selection_data);  	void ReceivedDrop(GtkSelectionData *selection_data); -	void GetSelection(GtkSelectionData *selection_data, guint info, SelectionText *selected); +	static void GetSelection(GtkSelectionData *selection_data, guint info, SelectionText *selected); +#if GTK_MAJOR_VERSION >= 2 +	static void ClipboardGetSelection(GtkClipboard* clip, GtkSelectionData *selection_data, guint info, void *data); +	static void ClipboardClearSelection(GtkClipboard* clip, void *data); +#endif +  	void UnclaimSelection(GdkEventSelection *selection_event);  	void Resize(int width, int height); @@ -262,6 +269,19 @@ enum {      TARGET_UTF8_STRING  }; +GdkAtom ScintillaGTK::atomClipboard = GDK_NONE; +GdkAtom ScintillaGTK::atomUTF8 = GDK_NONE; +GdkAtom ScintillaGTK::atomString = GDK_NONE; + +static const GtkTargetEntry clipboardTargets[] = { +	{ "UTF8_STRING", 0, TARGET_UTF8_STRING }, +	{ "STRING", 0, TARGET_STRING }, +//	    { "TEXT", 0, TARGET_TEXT }, +//	    { "COMPOUND_TEXT", 0, TARGET_COMPOUND_TEXT }, +	{ "text/uri-list", 0, 0 }, +}; +static const gint nClipboardTargets = sizeof(clipboardTargets) / sizeof(clipboardTargets[0]); +  static GtkWidget *PWidget(Window &w) {  	return reinterpret_cast<GtkWidget *>(w.GetID());  } @@ -289,11 +309,6 @@ ScintillaGTK::ScintillaGTK(_ScintillaObject *sci_) :  	sci = sci_;  	wMain = GTK_WIDGET(sci); -	atomClipboard = GDK_NONE; -	atomSought = GDK_NONE; -	atomUTF8 = GDK_NONE; -	atomString = GDK_NONE; -  #if PLAT_GTK_WIN32   	// There does not seem to be a real standard for indicating that the clipboard  	// contains a rectangular selection, so copy Developer Studio. @@ -678,27 +693,23 @@ void ScintillaGTK::Initialise() {  	gtk_widget_grab_focus(PWidget(wMain)); -	static const GtkTargetEntry targets[] = { -	    { "UTF8_STRING", 0, TARGET_UTF8_STRING }, -	    { "STRING", 0, TARGET_STRING }, -//	    { "TEXT", 0, TARGET_TEXT }, -//	    { "COMPOUND_TEXT", 0, TARGET_COMPOUND_TEXT }, -	    { "text/uri-list", 0, 0 }, -	}; -	static const gint n_targets = sizeof(targets) / sizeof(targets[0]); -  	gtk_selection_add_targets(GTK_WIDGET(PWidget(wMain)), GDK_SELECTION_PRIMARY, -	                          targets, n_targets); +	                          clipboardTargets, nClipboardTargets); -	atomClipboard = gdk_atom_intern("CLIPBOARD", FALSE); -	atomUTF8 = gdk_atom_intern("UTF8_STRING", FALSE); -	atomString = gdk_atom_intern("STRING", FALSE); +	if (atomClipboard == GDK_NONE) +		atomClipboard = gdk_atom_intern("CLIPBOARD", FALSE); +	if (atomUTF8 == GDK_NONE) +		atomUTF8 = gdk_atom_intern("UTF8_STRING", FALSE); +	if (atomString == GDK_NONE) +		atomString = gdk_atom_intern("STRING", FALSE); +#if GTK_MAJOR_VERSION == 1  	gtk_selection_add_targets(GTK_WIDGET(PWidget(wMain)), atomClipboard, -	                          targets, n_targets); +	                          clipboardTargets, nClipboardTargets); +#endif  	gtk_drag_dest_set(GTK_WIDGET(PWidget(wMain)), -	                  GTK_DEST_DEFAULT_ALL, targets, n_targets, +	                  GTK_DEST_DEFAULT_ALL, clipboardTargets, nClipboardTargets,  	                  static_cast<GdkDragAction>(GDK_ACTION_COPY | GDK_ACTION_MOVE));  	SetTicking(true); @@ -1125,18 +1136,46 @@ int ScintillaGTK::KeyDefault(int key, int modifiers) {  }  void ScintillaGTK::CopyToClipboard(const SelectionText &selectedText) { -	copyText.Copy(selectedText.s, selectedText.len); +#if GTK_MAJOR_VERSION == 1 +	copyText.Copy(selectedText.s, selectedText.len, selectedText.characterSet);  	gtk_selection_owner_set(GTK_WIDGET(PWidget(wMain)),  				atomClipboard,  				GDK_CURRENT_TIME); +#else +	GtkClipboard *clipBoard; +	clipBoard = gtk_widget_get_clipboard(GTK_WIDGET(PWidget(wMain)), atomClipboard); +	if (clipBoard == NULL) // Occurs if widget isn't in a toplevel +		return; + +	SelectionText *clipText = new SelectionText(); +	clipText->Copy(selectedText.s, selectedText.len, selectedText.characterSet); + +	gtk_clipboard_set_with_data(clipBoard, clipboardTargets, nClipboardTargets, +				    ClipboardGetSelection, ClipboardClearSelection, clipText); + +#endif  }  void ScintillaGTK::Copy() {  	if (currentPos != anchor) { +#if GTK_MAJOR_VERSION == 1  		CopySelectionRange(©Text);  		gtk_selection_owner_set(GTK_WIDGET(PWidget(wMain)),  		                        atomClipboard,  		                        GDK_CURRENT_TIME); +#else +		GtkClipboard *clipBoard; +		clipBoard = gtk_widget_get_clipboard(GTK_WIDGET(PWidget(wMain)), atomClipboard); +		if (clipBoard == NULL) // Occurs if widget isn't in a toplevel +			return; + +		SelectionText *clipText = new SelectionText(); +		CopySelectionRange(clipText); + +		gtk_clipboard_set_with_data(clipBoard, clipboardTargets, nClipboardTargets, +					    ClipboardGetSelection, ClipboardClearSelection, clipText); + +#endif  #if PLAT_GTK_WIN32  		if (selType == selRectangle) {  			::OpenClipboard(NULL); @@ -1210,14 +1249,14 @@ void ScintillaGTK::ClaimSelection() {  		primarySelection = true;  		gtk_selection_owner_set(GTK_WIDGET(PWidget(wMain)),  		                        GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME); -		primary.Set(0, 0); +		primary.Set(0, 0, 0);  	} else if (OwnPrimarySelection()) {  		primarySelection = true;  		if (primary.s == NULL)  			gtk_selection_owner_set(NULL, GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME);  	} else {  		primarySelection = false; -		primary.Set(0, 0); +		primary.Set(0, 0, 0);  	}  } @@ -1285,7 +1324,7 @@ char *ConvertLineEnds(size_t *pLenOut, const char *s, size_t len, int eolMode) {  }  // Detect rectangular text, convert line ends to current mode, convert from or to UTF-8 -void ScintillaGTK::GetGtkSelectionText(const GtkSelectionData *selectionData, SelectionText &selText) { +void ScintillaGTK::GetGtkSelectionText(GtkSelectionData *selectionData, SelectionText &selText) {  	char *data = reinterpret_cast<char *>(selectionData->data);  	size_t len = selectionData->length;  	GdkAtom selectionType = selectionData->type; @@ -1294,35 +1333,56 @@ void ScintillaGTK::GetGtkSelectionText(const GtkSelectionData *selectionData, Se  	if ((selectionType != GDK_TARGET_STRING) && (selectionType != atomUTF8)) {  		char *empty = new char[1];  		empty[0] = '\0'; -		selText.Set(empty,0); +		selText.Set(empty, 0, SC_CP_UTF8);  		return;  	}  	// Check for "\n\0" ending to string indicating that selection is rectangular -	bool isRectangular = ((len > 2) && (data[len - 1] == 0 && data[len - 2] == '\n')); -	// 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) +	bool isRectangular; +#if PLAT_GTK_WIN32 +	isRectangular = ::IsClipboardFormatAvailable(cfColumnSelect) != 0; +#else +	isRectangular = ((len > 2) && (data[len - 1] == 0 && data[len - 2] == '\n')); +#endif + +#if GTK_MAJOR_VERSION >= 2 +	char *dest; +	char *utf8 = reinterpret_cast<char*>(gtk_selection_data_get_text(selectionData)); +	if (utf8 != NULL) { +		dest = ConvertLineEnds(&len, utf8, strlen(utf8), pdoc->eolMode); +		g_free(utf8); +	} +	else { +		dest = new char[1]; +		dest[0] = '\0'; +		len = 0; +	} +	selText.Set(dest, len, SC_CP_UTF8, isRectangular); +#else  	char *dest = ConvertLineEnds(&len, data, len, pdoc->eolMode); -	selText.Set(dest, len, isRectangular); +	if (selectionType == GDK_TARGET_STRING) +		selText.Set(dest, len, pdoc->dbcsCodePage, isRectangular); +	else +		selText.Set(dest, len, SC_CP_UTF8, isRectangular); +#endif  #if !PLAT_GTK_WIN32  	// Possible character set conversion  	const char *charSetBuffer = CharacterSetID();  	if (*charSetBuffer) {  		if (IsUnicodeMode()) { -			if (selectionType == GDK_TARGET_STRING) { +			if (selText.characterSet != SC_CP_UTF8) {  				// Convert to UTF-8  //fprintf(stderr, "Convert to UTF-8 from %s\n", charSetBuffer); -				dest = ConvertText(&len, dest, len, "UTF-8", charSetBuffer); -				selText.Set(dest, len, isRectangular); +				dest = ConvertText(&len, selText.s, selText.len, "UTF-8", charSetBuffer); +				selText.Set(dest, len, SC_CP_UTF8, selText.rectangular);  			}  		} else { -			if (selectionType == atomUTF8) { +			if (selText.characterSet == SC_CP_UTF8) {  //fprintf(stderr, "Convert to locale %s\n", charSetBuffer);  				// Convert to locale -				dest = ConvertText(&len, dest, len, charSetBuffer, "UTF-8"); -				selText.Set(dest, len, isRectangular); +				dest = ConvertText(&len, selText.s, selText.len, charSetBuffer, "UTF-8"); +				selText.Set(dest, len, pdoc->dbcsCodePage, selText.rectangular);  			}  		}  	} @@ -1340,9 +1400,6 @@ void ScintillaGTK::ReceivedSelection(GtkSelectionData *selection_data) {  			((selection_data->type == GDK_TARGET_STRING) || (selection_data->type == atomUTF8))) {  			SelectionText selText;  			GetGtkSelectionText(selection_data, selText); -#if PLAT_GTK_WIN32 -			selText.rectangular = ::IsClipboardFormatAvailable(cfColumnSelect) != 0; -#endif  			pdoc->BeginUndoAction();  			int selStart = SelectionStart(); @@ -1379,53 +1436,61 @@ void ScintillaGTK::ReceivedDrop(GtkSelectionData *selection_data) {  	Redraw();  } + +  void ScintillaGTK::GetSelection(GtkSelectionData *selection_data, guint info, SelectionText *text) { -	if (selection_data->selection == GDK_SELECTION_PRIMARY) { -		if (primary.s == NULL) { -			CopySelectionRange(&primary); -		} -		text = &primary; -	} +#if GTK_MAJOR_VERSION >= 2 +	// Convert text to utf8 if it isn't already +	if (text->characterSet != SC_CP_UTF8) { +		const char *charSet = ::CharacterSetID(text->characterSet); +		size_t new_len; +		char* tmputf = ConvertText(&new_len, text->s, text->len, "UTF-8", charSet); +		text->Set(tmputf, new_len, SC_CP_UTF8, text->rectangular); +	} + +	// Here is a somewhat evil kludge. +	// As I can not work out how to store data on the clipboard in multiple formats +	// and need some way to mark the clipping as being stream or rectangular, +	// the terminating \0 is included in the length for rectangular clippings. +	// All other tested aplications behave benignly by ignoring the \0. +	// The #if is here because on Windows cfColumnSelect clip entry is used +	// instead as standard indicator of rectangularness (so no need to kludge) +	int len = strlen(text->s); +#if PLAT_GTK_WIN32 == 0 +	if (text->rectangular) +		len++; +#endif +	gtk_selection_data_set_text(selection_data, text->s, len); + +#else /* Gtk 1 */  	char *selBuffer = text->s;  #if PLAT_GTK_WIN32 -	// win32gtk requires \n delimited lines and doesn't work right with -	// other line formats, so make a copy of the clip text now with -	// newlines converted -	char *tmpstr = new char[text->len + 1]; -	char *sptr = selBuffer; -	char *dptr = tmpstr; -	while (*sptr != '\0') { -		if (pdoc->eolMode == SC_EOL_CR && *sptr == '\r') { -			*dptr++ = '\n'; -			sptr++; -		} else if (pdoc->eolMode != SC_EOL_CR && *sptr == '\r') { -			sptr++; -		} else { -			*dptr++ = *sptr++; -		} -	} -	*dptr = '\0'; + +	// Many native win32 programs require \n line endings, +	 // so make a copy of the clip text now with newlines converted + +	size_t new_len; +	char *tmpstr = ConvertLineEnds(&new_len, selBuffer, text->len, SC_EOL_LF);  	selBuffer = tmpstr;  #endif -  	char *tmputf = 0;  	if ((info == TARGET_UTF8_STRING) || (info == TARGET_STRING)) {  		size_t len = strlen(selBuffer);  #if !PLAT_GTK_WIN32  		// Possible character set conversion -		const char *charSetBuffer = CharacterSetID(); +		const char *charSetBuffer = ::CharacterSetID(text->characterSet);  		if (info == TARGET_UTF8_STRING) {  			//fprintf(stderr, "Copy to clipboard as UTF-8\n"); -			if (!IsUnicodeMode()) { +			if (text->characterSet != SC_CP_UTF8) {  				// Convert to UTF-8  	//fprintf(stderr, "Convert to UTF-8 from %s\n", charSetBuffer);  				tmputf = ConvertText(&len, selBuffer, len, "UTF-8", charSetBuffer);  				selBuffer = tmputf;  			}  		} else if (info == TARGET_STRING) { -			if (IsUnicodeMode()) { +			if (text->characterSet == SC_CP_UTF8) {  	//fprintf(stderr, "Convert to locale %s\n", charSetBuffer);  				// Convert to locale  				tmputf = ConvertText(&len, selBuffer, len, charSetBuffer, "UTF-8"); @@ -1466,14 +1531,26 @@ void ScintillaGTK::GetSelection(GtkSelectionData *selection_data, guint info, Se  #if PLAT_GTK_WIN32  	delete []tmpstr;  #endif +#endif /* Gtk >= 2 */ +} + +#if GTK_MAJOR_VERSION >= 2 +void ScintillaGTK::ClipboardGetSelection(GtkClipboard *, GtkSelectionData *selection_data, guint info, void *data) { +	GetSelection(selection_data, info, static_cast<SelectionText*>(data));  } +void ScintillaGTK::ClipboardClearSelection(GtkClipboard *, void *data) { +	SelectionText *obj = static_cast<SelectionText*>(data); +	delete obj; +} +#endif +  void ScintillaGTK::UnclaimSelection(GdkEventSelection *selection_event) {  	//Platform::DebugPrintf("UnclaimSelection\n");  	if (selection_event->selection == GDK_SELECTION_PRIMARY) {  		//Platform::DebugPrintf("UnclaimPrimarySelection\n");  		if (!OwnPrimarySelection()) { -			primary.Set(0, 0); +			primary.Set(0, 0, 0);  			primarySelection = false;  			FullPaint();  		} @@ -2104,7 +2181,17 @@ void ScintillaGTK::SelectionGet(GtkWidget *widget,                                  GtkSelectionData *selection_data, guint info, guint) {  	ScintillaGTK *sciThis = ScintillaFromWidget(widget);  	//Platform::DebugPrintf("Selection get\n"); -	sciThis->GetSelection(selection_data, info, &sciThis->copyText); +	if (selection_data->selection == GDK_SELECTION_PRIMARY) { +		if (sciThis->primary.s == NULL) { +			sciThis->CopySelectionRange(&sciThis->primary); +		} +		sciThis->GetSelection(selection_data, info, &sciThis->primary); +	} +#if GTK_MAJOR_VERSION == 1 /* Gtk 2+ uses GtkClipboard for non-primary selections. */ +	else { +		sciThis->GetSelection(selection_data, info, &sciThis->copyText); +	} +#endif  }  gint ScintillaGTK::SelectionClear(GtkWidget *widget, GdkEventSelection *selection_event) {  | 
