diff options
Diffstat (limited to 'gtk/PlatGTK.cxx')
-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); } } |