diff options
| -rw-r--r-- | gtk/PlatGTK.cxx | 46 | ||||
| -rw-r--r-- | gtk/ScintillaGTK.cxx | 110 | ||||
| -rw-r--r-- | src/Editor.cxx | 14 | ||||
| -rw-r--r-- | src/Editor.h | 17 | 
4 files changed, 100 insertions, 87 deletions
| diff --git a/gtk/PlatGTK.cxx b/gtk/PlatGTK.cxx index 330810883..eaecb8de0 100644 --- a/gtk/PlatGTK.cxx +++ b/gtk/PlatGTK.cxx @@ -1026,8 +1026,25 @@ static size_t UTF8Len(char ch) {  		return 3;  } +char *UTF8FromLatin1(const char *s, int &len) { +	char *utfForm = new char[len*2+1]; +	size_t lenU = 0; +	for (int i=0;i<len;i++) { +		unsigned int uch = static_cast<unsigned char>(s[i]); +		if (uch < 0x80) { +			utfForm[lenU++] = uch; +		} else { +			utfForm[lenU++] = static_cast<char>(0xC0 | (uch >> 6)); +			utfForm[lenU++] = static_cast<char>(0x80 | (uch & 0x3f)); +		} +	} +	utfForm[lenU] = '\0'; +	len = lenU; +	return utfForm; +} +  #ifdef USE_PANGO -static char *UTF8FromIconv(const Converter &conv, const char *s, int len) { +static char *UTF8FromIconv(const Converter &conv, const char *s, int &len) {  	if (conv) {  		char *utfForm = new char[len*3+1];  		char *pin = const_cast<char *>(s); @@ -1037,6 +1054,7 @@ static char *UTF8FromIconv(const Converter &conv, const char *s, int len) {  		size_t conversions = conv.Convert(&pin, &inLeft, &pout, &outLeft);  		if (conversions != ((size_t)(-1))) {  			*pout = '\0'; +			len = pout - utfForm;  			return utfForm;  		}  		delete []utfForm; @@ -1061,22 +1079,6 @@ static size_t MultiByteLenFromIconv(const Converter &conv, const char *s, size_t  	return 1;  } -static char *UTF8FromLatin1(const char *s, int len) { -	char *utfForm = new char[len*2+1]; -	size_t lenU = 0; -	for (int i=0;i<len;i++) { -		unsigned int uch = static_cast<unsigned char>(s[i]); -		if (uch < 0x80) { -			utfForm[lenU++] = uch; -		} else { -			utfForm[lenU++] = static_cast<char>(0xC0 | (uch >> 6)); -			utfForm[lenU++] = static_cast<char>(0x80 | (uch & 0x3f)); -		} -	} -	utfForm[lenU] = '\0'; -	return utfForm; -} -  static char *UTF8FromGdkWChar(GdkWChar *wctext, int wclen) {  	char *utfForm = new char[wclen*3+1];	// Maximum of 3 UTF-8 bytes per character  	size_t lenU = 0; @@ -1097,7 +1099,7 @@ static char *UTF8FromGdkWChar(GdkWChar *wctext, int wclen) {  	return utfForm;  } -static char *UTF8FromDBCS(const char *s, int len) { +static char *UTF8FromDBCS(const char *s, int &len) {  	GdkWChar *wctext = new GdkWChar[len + 1];  	GdkWChar *wcp = wctext;  	int wclen = gdk_mbstowcs(wcp, s, len); @@ -1110,6 +1112,7 @@ static char *UTF8FromDBCS(const char *s, int len) {  	char *utfForm = UTF8FromGdkWChar(wctext, wclen);  	delete []wctext; +	len = strlen(utfForm);  	return utfForm;  } @@ -1156,7 +1159,7 @@ void SurfaceImpl::DrawTextBase(PRectangle rc, Font &font_, int ybase, const char  				if (!utfForm) {	// iconv and DBCS failed so treat as Latin1  					utfForm = UTF8FromLatin1(s, len);  				} -				pango_layout_set_text(layout, utfForm, strlen(utfForm)); +				pango_layout_set_text(layout, utfForm, len);  			}  			pango_layout_set_font_description(layout, PFont(font_)->pfd);  			PangoLayoutLine *pll = pango_layout_get_line(layout,0); @@ -1311,7 +1314,7 @@ void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positi  					if (!utfForm) {  						utfForm = UTF8FromLatin1(s, len);  					} -					pango_layout_set_text(layout, utfForm, strlen(utfForm)); +					pango_layout_set_text(layout, utfForm, len);  					int i = 0;  					PangoLayoutIter *iter = pango_layout_get_iter (layout);  					while (pango_layout_iter_next_cluster (iter)) { @@ -1412,8 +1415,7 @@ int SurfaceImpl::WidthText(Font &font_, const char *s, int len) {  				if (!utfForm) {	// g_locale_to_utf8 failed so treat as Latin1  					utfForm = UTF8FromLatin1(s, len);  				} -				pango_layout_set_text(layout, utfForm, strlen(utfForm)); -				len = strlen(utfForm); +				pango_layout_set_text(layout, utfForm, len);  			}  			PangoLayoutLine *pangoLine = pango_layout_get_line(layout, 0);  			pango_layout_line_get_extents(pangoLine, NULL, &pos); diff --git a/gtk/ScintillaGTK.cxx b/gtk/ScintillaGTK.cxx index 8a9dc283d..5194ec101 100644 --- a/gtk/ScintillaGTK.cxx +++ b/gtk/ScintillaGTK.cxx @@ -72,6 +72,8 @@  #pragma warning(disable: 4505)  #endif +extern char *UTF8FromLatin1(const char *s, int &len); +  class ScintillaGTK : public ScintillaBase {  	_ScintillaObject *sci;  	Window wText; @@ -727,9 +729,10 @@ void ScintillaGTK::DisplayCursor(Window::Cursor c) {  void ScintillaGTK::StartDrag() {  	dragWasDropped = false;  	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", 0, TARGET_TEXT }, +	    // { "COMPOUND_TEXT", 0, TARGET_COMPOUND_TEXT },  	};  	static const gint n_targets = sizeof(targets) / sizeof(targets[0]);  	GtkTargetList *tl = gtk_target_list_new(targets, n_targets); @@ -1134,7 +1137,7 @@ int ScintillaGTK::KeyDefault(int key, int modifiers) {  void ScintillaGTK::CopyToClipboard(const SelectionText &selectedText) {  #if GTK_MAJOR_VERSION == 1 -	copyText.Copy(selectedText.s, selectedText.len, selectedText.characterSet); +	copyText.Copy(selectedText);  	gtk_selection_owner_set(GTK_WIDGET(PWidget(wMain)),  				atomClipboard,  				GDK_CURRENT_TIME); @@ -1145,7 +1148,7 @@ void ScintillaGTK::CopyToClipboard(const SelectionText &selectedText) {  		return;  	SelectionText *clipText = new SelectionText(); -	clipText->Copy(selectedText.s, selectedText.len, selectedText.characterSet); +	clipText->Copy(selectedText);  	gtk_clipboard_set_with_data(clipBoard, clipboardTargets, nClipboardTargets,  				    ClipboardGetSelection, ClipboardClearSelection, clipText); @@ -1246,19 +1249,19 @@ void ScintillaGTK::ClaimSelection() {  		primarySelection = true;  		gtk_selection_owner_set(GTK_WIDGET(PWidget(wMain)),  		                        GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME); -		primary.Set(0, 0, 0); +		primary.Free();  	} 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, 0); +		primary.Free();  	}  }  #ifdef USE_CONVERTER -static char *ConvertText(size_t *lenResult, char *s, size_t len, const char *charSetDest, const char *charSetSource) { +static char *ConvertText(int *lenResult, char *s, size_t len, const char *charSetDest, const char *charSetSource) {  	*lenResult = 0;  	char *destForm = 0;  	Converter conv(charSetDest, charSetSource); @@ -1270,7 +1273,7 @@ static char *ConvertText(size_t *lenResult, char *s, size_t len, const char *cha  		size_t outLeft = len*3+1;  		size_t conversions = conv.Convert(&pin, &inLeft, &pout, &outLeft);  		if (conversions == ((size_t)(-1))) { -fprintf(stderr, "iconv failed for %s\n", static_cast<char *>(s)); +fprintf(stderr, "iconv %s->%s failed for %s\n", charSetSource, charSetDest, static_cast<char *>(s));  			delete []destForm;  			destForm = 0;  		} else { @@ -1292,7 +1295,7 @@ fprintf(stderr, "iconv failed for %s\n", static_cast<char *>(s));  // Convert line endings for a piece of text to a particular mode.  // Stop at len or when a NUL is found. -char *ConvertLineEnds(size_t *pLenOut, const char *s, size_t len, int eolMode) { +char *ConvertLineEnds(int *pLenOut, const char *s, size_t len, int eolMode) {  	char *dest = new char[2 * len + 1];  	const char *sptr = s;  	char *dptr = dest; @@ -1323,14 +1326,14 @@ 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(GtkSelectionData *selectionData, SelectionText &selText) {  	char *data = reinterpret_cast<char *>(selectionData->data); -	size_t len = selectionData->length; +	int len = selectionData->length;  	GdkAtom selectionType = selectionData->type;  	// Return empty string if selection is not a string  	if ((selectionType != GDK_TARGET_STRING) && (selectionType != atomUTF8)) {  		char *empty = new char[1];  		empty[0] = '\0'; -		selText.Set(empty, 0, SC_CP_UTF8); +		selText.Set(empty, 0, SC_CP_UTF8, 0, false);  		return;  	} @@ -1342,48 +1345,34 @@ void ScintillaGTK::GetGtkSelectionText(GtkSelectionData *selectionData, Selectio  	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); -	if (selectionType == GDK_TARGET_STRING) -		selText.Set(dest, len, pdoc->dbcsCodePage, isRectangular); -	else -		selText.Set(dest, len, SC_CP_UTF8, isRectangular); -#endif - -#ifdef USE_CONVERTER -	// Possible character set conversion -	const char *charSetBuffer = CharacterSetID(); -	if (*charSetBuffer) { +	if (selectionType == GDK_TARGET_STRING) { +		dest = ConvertLineEnds(&len, data, len, pdoc->eolMode);  		if (IsUnicodeMode()) { -			if (selText.characterSet != SC_CP_UTF8) { -				// Convert to UTF-8 -//fprintf(stderr, "Convert to UTF-8 from %s\n", charSetBuffer); -				dest = ConvertText(&len, selText.s, selText.len, "UTF-8", charSetBuffer); -				selText.Set(dest, len, SC_CP_UTF8, selText.rectangular); -			} +			// Unknown encoding so assume in Latin1 +			char *destPrevious = dest; +			dest = UTF8FromLatin1(dest, len); +			selText.Set(dest, len, SC_CP_UTF8, 0, selText.rectangular); +			delete []destPrevious;  		} else { -			if (selText.characterSet == SC_CP_UTF8) { -//fprintf(stderr, "Convert to locale %s\n", charSetBuffer); +			// Assume buffer is in same encoding as selection +			selText.Set(dest, len, pdoc->dbcsCodePage, +				vs.styles[STYLE_DEFAULT].characterSet, isRectangular); +		} +	} else {	// UTF-8 +		dest = ConvertLineEnds(&len, data, len, pdoc->eolMode); +		selText.Set(dest, len, SC_CP_UTF8, 0, isRectangular); +#ifdef USE_CONVERTER +		const char *charSetBuffer = CharacterSetID(); +		if (!IsUnicodeMode() && *charSetBuffer) { +//fprintf(stderr, "Convert to locale %s\n", CharacterSetID());  				// Convert to locale  				dest = ConvertText(&len, selText.s, selText.len, charSetBuffer, "UTF-8"); -				selText.Set(dest, len, pdoc->dbcsCodePage, selText.rectangular); -			} +				selText.Set(dest, len, pdoc->dbcsCodePage, +					vs.styles[STYLE_DEFAULT].characterSet, selText.rectangular);  		} -	}  #endif +	}  }  void ScintillaGTK::ReceivedSelection(GtkSelectionData *selection_data) { @@ -1437,14 +1426,16 @@ void ScintillaGTK::ReceivedDrop(GtkSelectionData *selection_data) {  void ScintillaGTK::GetSelection(GtkSelectionData *selection_data, guint info, SelectionText *text) {  #if GTK_MAJOR_VERSION >= 2 -	(void)info;	// Parameter unused on GTK+ 2  	// Convert text to utf8 if it isn't already -	if (text->characterSet != SC_CP_UTF8) { +	SelectionText *converted = 0; +	if ((text->codePage != SC_CP_UTF8) && (info == TARGET_UTF8_STRING)) {  		const char *charSet = ::CharacterSetID(text->characterSet);  		if (*charSet) { -			size_t new_len; +			int new_len;  			char* tmputf = ConvertText(&new_len, text->s, text->len, "UTF-8", charSet); -			text->Set(tmputf, new_len, SC_CP_UTF8, text->rectangular); +			converted = new SelectionText(); +			converted->Set(tmputf, new_len, SC_CP_UTF8, 0, text->rectangular); +			text = converted;  		}  	} @@ -1461,7 +1452,14 @@ void ScintillaGTK::GetSelection(GtkSelectionData *selection_data, guint info, Se  		len++;  #endif -	gtk_selection_data_set_text(selection_data, text->s, len); +	if (info == TARGET_UTF8_STRING) { +		gtk_selection_data_set_text(selection_data, text->s, len); +	} else { +		gtk_selection_data_set(selection_data, +			static_cast<GdkAtom>(GDK_SELECTION_TYPE_STRING), +			8, reinterpret_cast<unsigned char *>(text->s), len); +	} +	delete converted;  #else /* Gtk 1 */  	char *selBuffer = text->s; @@ -1471,26 +1469,26 @@ void ScintillaGTK::GetSelection(GtkSelectionData *selection_data, guint info, Se  	// Many native win32 programs require \n line endings,  	 // so make a copy of the clip text now with newlines converted -	size_t new_len; +	int 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); +		int len = strlen(selBuffer);  #ifdef USE_CONVERTER  		// Possible character set conversion  		const char *charSetBuffer = ::CharacterSetID(text->characterSet);  		if (info == TARGET_UTF8_STRING) {  			//fprintf(stderr, "Copy to clipboard as UTF-8\n"); -			if (text->characterSet != SC_CP_UTF8) { +			if (text->codePage != 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 (text->characterSet == SC_CP_UTF8) { +			if (text->codePage == SC_CP_UTF8) {  	//fprintf(stderr, "Convert to locale %s\n", charSetBuffer);  				// Convert to locale  				tmputf = ConvertText(&len, selBuffer, len, charSetBuffer, "UTF-8"); @@ -1550,7 +1548,7 @@ void ScintillaGTK::UnclaimSelection(GdkEventSelection *selection_event) {  	if (selection_event->selection == GDK_SELECTION_PRIMARY) {  		//Platform::DebugPrintf("UnclaimPrimarySelection\n");  		if (!OwnPrimarySelection()) { -			primary.Set(0, 0, 0); +			primary.Free();  			primarySelection = false;  			FullPaint();  		} diff --git a/src/Editor.cxx b/src/Editor.cxx index 4b1c6691d..7bafb3fff 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -4631,7 +4631,8 @@ char *Editor::CopyRange(int start, int end) {  }  void Editor::CopySelectionFromRange(SelectionText *ss, int start, int end) { -	ss->Set(CopyRange(start, end), end - start + 1, pdoc->dbcsCodePage, false); +	ss->Set(CopyRange(start, end), end - start + 1,  +		pdoc->dbcsCodePage, vs.styles[STYLE_DEFAULT].characterSet, false);  }  void Editor::CopySelectionRange(SelectionText *ss) { @@ -4673,7 +4674,8 @@ void Editor::CopySelectionRange(SelectionText *ss) {  				text[size] = '\0';  			}  		} - 		ss->Set(text, size + 1, pdoc->dbcsCodePage, selType == selRectangle); + 		ss->Set(text, size + 1, pdoc->dbcsCodePage,  +			vs.styles[STYLE_DEFAULT].characterSet, selType == selRectangle);  	}  } @@ -4681,13 +4683,15 @@ void Editor::CopyRangeToClipboard(int start, int end) {  	start = pdoc->ClampPositionIntoDocument(start);  	end = pdoc->ClampPositionIntoDocument(end);  	SelectionText selectedText; -	selectedText.Set(CopyRange(start, end), end - start + 1, pdoc->dbcsCodePage); +	selectedText.Set(CopyRange(start, end), end - start + 1,  +		pdoc->dbcsCodePage, vs.styles[STYLE_DEFAULT].characterSet, false);  	CopyToClipboard(selectedText);  }  void Editor::CopyText(int length, const char *text) {  	SelectionText selectedText; -	selectedText.Copy(text, length, pdoc->dbcsCodePage); +	selectedText.Copy(text, length,  +		pdoc->dbcsCodePage, vs.styles[STYLE_DEFAULT].characterSet, false);  	CopyToClipboard(selectedText);  } @@ -5161,7 +5165,7 @@ void Editor::ButtonUp(Point pt, unsigned int curTime, bool ctrl) {  					} else {  						SetEmptySelection(newPos);  					} -					drag.Set(0, 0, 0); +					drag.Free();  				}  				selectionType = selChar;  			} diff --git a/src/Editor.h b/src/Editor.h index 76635e658..9e9af0ec1 100644 --- a/src/Editor.h +++ b/src/Editor.h @@ -134,22 +134,27 @@ public:  	char *s;  	int len;  	bool rectangular; +	int codePage;  	int characterSet; -	SelectionText() : s(0), len(0), rectangular(false), characterSet(0) {} +	SelectionText() : s(0), len(0), rectangular(false), codePage(0), characterSet(0) {}  	~SelectionText() { -		Set(0, 0, 0); +		Free();  	} -	void Set(char *s_, int len_, int characterSet_, bool rectangular_=false) { +	void Free() { +		Set(0, 0, 0, 0, false); +	} +	void Set(char *s_, int len_, int codePage_, int characterSet_, bool rectangular_) {  		delete []s;  		s = s_;  		if (s)  			len = len_;  		else  			len = 0; +		codePage = codePage_;  		characterSet = characterSet_;  		rectangular = rectangular_;  	} -	void Copy(const char *s_, int len_, int characterSet_, bool rectangular_=false) { +	void Copy(const char *s_, int len_, int codePage_, int characterSet_, bool rectangular_) {  		delete []s;  		s = new char[len_];  		if (s) { @@ -160,9 +165,13 @@ public:  		} else {  			len = 0;  		} +		codePage = codePage_;  		characterSet = characterSet_;  		rectangular = rectangular_;  	} +	void Copy(const SelectionText &other) { +		Copy(other.s, other.len, other.codePage, other.characterSet, other.rectangular); +	}  };  /** | 
