diff options
Diffstat (limited to 'gtk')
| -rw-r--r-- | gtk/PlatGTK.cxx | 124 | 
1 files changed, 115 insertions, 9 deletions
| diff --git a/gtk/PlatGTK.cxx b/gtk/PlatGTK.cxx index 58dbd742a..ebf949566 100644 --- a/gtk/PlatGTK.cxx +++ b/gtk/PlatGTK.cxx @@ -232,6 +232,18 @@ static const char *CharacterSetName(int characterSet) {  	}  } +static bool IsDBCSCharacterSet(int characterSet) { +	switch (characterSet) { +	case SC_CHARSET_GB2312: +	case SC_CHARSET_HANGUL: +	case SC_CHARSET_SHIFTJIS: +	case SC_CHARSET_CHINESEBIG5: +		return true; +	default: +		return false; +	} +} +  static void GenerateFontSpecStrings(const char *fontName, int characterSet,                                      char *foundary, int foundary_len,                                      char *faceName, int faceName_len, @@ -384,6 +396,14 @@ void FontCached::ReleaseId(FontID id_) {  	FontMutexUnlock();  } +static FontID LoadFontOrSet(const char *fontspec, int characterSet) { +	if (IsDBCSCharacterSet(characterSet)) { +		return gdk_fontset_load(fontspec); +	} else { +		return gdk_font_load(fontspec); +	} +} +  FontID FontCached::CreateNewFont(const char *fontName, int characterSet,                                   int size, bool bold, bool italic) {  	char fontset[1024]; @@ -401,7 +421,7 @@ FontID FontCached::CreateNewFont(const char *fontName, int characterSet,  	// If name of the font begins with a '-', assume, that it is  	// a full fontspec.  	if (fontName[0] == '-') { -		if (strchr(fontName, ',')) { +		if (strchr(fontName, ',') || IsDBCSCharacterSet(characterSet)) {  			newid = gdk_fontset_load(fontName);  		} else {  			newid = gdk_font_load(fontName); @@ -409,7 +429,8 @@ FontID FontCached::CreateNewFont(const char *fontName, int characterSet,  		if (!newid) {  			// Font not available so substitute a reasonable code font  			// iso8859 appears to only allow western characters. -			newid = gdk_font_load("-*-*-*-*-*-*-*-*-*-*-*-*-iso8859-*"); +			newid = LoadFontOrSet("-*-*-*-*-*-*-*-*-*-*-*-*-iso8859-*", +				characterSet);  		}  		return newid;  	} @@ -502,7 +523,7 @@ FontID FontCached::CreateNewFont(const char *fontName, int characterSet,  	         italic ? "-i" : "-r",  	         size * 10,  	         charset); -	newid = gdk_font_load(fontspec); +	newid = LoadFontOrSet(fontspec, characterSet);  	if (!newid) {  		// some fonts have oblique, not italic  		snprintf(fontspec, @@ -513,7 +534,7 @@ FontID FontCached::CreateNewFont(const char *fontName, int characterSet,  		         italic ? "-o" : "-r",  		         size * 10,  		         charset); -		newid = gdk_font_load(fontspec); +		newid = LoadFontOrSet(fontspec, characterSet);  	}  	if (!newid) {  		snprintf(fontspec, @@ -526,7 +547,8 @@ FontID FontCached::CreateNewFont(const char *fontName, int characterSet,  	if (!newid) {  		// Font not available so substitute a reasonable code font  		// iso8859 appears to only allow western characters. -		newid = gdk_font_load("-*-*-*-*-*-*-*-*-*-*-*-*-iso8859-*"); +		newid = LoadFontOrSet("-*-*-*-*-*-*-*-*-*-*-*-*-iso8859-*", +			characterSet);  	}  	return newid;  } @@ -548,6 +570,7 @@ void Font::Release() {  class SurfaceImpl : public Surface {  	bool unicodeMode; +	bool dbcsMode;  	GdkDrawable *drawable;  	GdkGC *gc;  	GdkPixmap *ppixmap; @@ -595,10 +618,12 @@ public:  	void FlushCachedState();  	void SetUnicodeMode(bool unicodeMode_); +	void SetDBCSMode(int codePage);  }; -SurfaceImpl::SurfaceImpl() : unicodeMode(false), drawable(0), gc(0), ppixmap(0), -x(0), y(0), inited(false), createdGC(false) {} +SurfaceImpl::SurfaceImpl() : unicodeMode(false), dbcsMode(false), drawable(0), gc(0), ppixmap(0), +x(0), y(0), inited(false), createdGC(false) { +}  SurfaceImpl::~SurfaceImpl() {  	Release(); @@ -822,6 +847,40 @@ void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const ch  				}  				wcp += lenDraw;  			} +		} else if (dbcsMode) { +			GdkWChar wctext[MAX_US_LEN]; +			GdkWChar *wcp = (GdkWChar *) & wctext; +			int wclen = gdk_mbstowcs(wcp, s, MAX_US_LEN); + +			/* In the annoying case when non-locale chars +			 * in the line. +			 * e.g. latin1 chars in Japanese locale */ +			if (wclen < 1) { +				while ((len > 0) && (x < maxCoordinate)) { +					int lenDraw = Platform::Minimum(len, segmentLength); +					gdk_draw_text(drawable, PFont(font_), gc, +					              x, ybase, s, lenDraw); +					len -= lenDraw; +					if (len > 0) { +						x += gdk_text_width(PFont(font_), s, lenDraw); +					} +					s += lenDraw; +				} +			} else { +				wctext[wclen] = L'\0'; +				int lenDraw; +				while ((wclen > 0) && (x < maxCoordinate)) { +					lenDraw = Platform::Minimum(wclen, segmentLength); +					gdk_draw_text_wc(drawable, PFont(font_), gc, +					                 x, ybase, wcp, lenDraw); +					wclen -= lenDraw; +					if (wclen > 0) { +						x += gdk_text_width_wc(PFont(font_), +						                       wcp, lenDraw); +					} +					wcp += lenDraw; + 				} +			}  		} else {  			while ((len > 0) && (x < maxCoordinate)) {  				int lenDraw = Platform::Minimum(len, segmentLength); @@ -882,6 +941,49 @@ void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positi  			while (i < static_cast<size_t>(len)) {  				positions[i++] = lastPos;  			} +		} else if (dbcsMode) { +			GdkWChar wctext[MAX_US_LEN]; +			size_t wclen = (size_t)gdk_mbstowcs(wctext, s, MAX_US_LEN); +			/* In the annoying case when non-locale chars +			 * in the line. +			 * e.g. latin1 chars in Japanese locale */ +			if( (int)wclen < 1 ) { +				for (int i = 0; i < len; i++) { +					int width = gdk_char_width(gf, s[i]); +					totalWidth += width; +					positions[i] = totalWidth; +				} +			} else { +				wctext[wclen] = L'\0'; +				int poses[MAX_US_LEN]; +				size_t i; +				for (i = 0; i < wclen; i++) { +					int width = gdk_char_width_wc(gf, wctext[i]); +					totalWidth += width; +					poses[i] = totalWidth; +				} +				size_t ui = 0; +				i = 0; +				for (ui = 0; ui< wclen; ui++) { +					GdkWChar wch[2]; +					wch[0] = wctext[ui]; +					wch[1] = L'\0'; +					gchar* mbstr = gdk_wcstombs(wch); +					if (mbstr == NULL || *mbstr == '\0') +						g_error("mbs broken\n"); +					for(int j=0; j<(int)strlen(mbstr); j++) { +						positions[i++] = poses[ui]; +					} +					if( mbstr != NULL ) +						g_free(mbstr); +				} +				int lastPos = 0; +				if (i > 0) +					lastPos = positions[i - 1]; +				while (i < static_cast<size_t>(len)) { +					positions[i++] = lastPos; +				} +			}  		} else {  			for (int i = 0; i < len; i++) {  				int width = gdk_char_width(gf, s[i]); @@ -1009,6 +1111,10 @@ void SurfaceImpl::SetUnicodeMode(bool unicodeMode_) {  	unicodeMode = unicodeMode_;  } +void SurfaceImpl::SetDBCSMode(int codePage) { +	dbcsMode = codePage == SC_CP_DBCS; +} +  Surface *Surface::Allocate() {  	return new SurfaceImpl;  } @@ -1361,7 +1467,7 @@ static void init_pixmap(ListImage *list_image, GtkWidget *window) {  	if (list_image->bitmap)  		gdk_bitmap_unref(list_image->bitmap);  	list_image->bitmap = NULL; -		 +  	list_image->pixmap = gdk_pixmap_colormap_create_from_xpm_d(NULL  	             , gtk_widget_get_colormap(window), &(list_image->bitmap), NULL  	             , (gchar **) xpm_lineform); @@ -1476,7 +1582,7 @@ void ListBoxX::RegisterImage(int type, const char *xpm_data) {  	} else {  		list_image = g_new0(ListImage, 1);  		list_image->xpm_data = xpm_data; -		g_hash_table_insert((GHashTable *) pixhash, GINT_TO_POINTER(type),  +		g_hash_table_insert((GHashTable *) pixhash, GINT_TO_POINTER(type),  			(gpointer) list_image);  	}  } | 
