--- t2/libx11-1.6.3/modules/om/generic/omXChar.c 2015-03-09 15:28:45.000000000 -0700 +++ t3/libx11-1.6.3/modules/om/generic/omXChar.c 2016-08-18 21:36:52.257293370 -0700 @@ -356,6 +356,9 @@ return ret; } +extern XlcConv +lcUTF8_update_preferred_charsets(XOC, XlcConv); + XlcConv _XomInitConverter( XOC oc, @@ -399,6 +402,8 @@ return (XlcConv) NULL; } + conv = lcUTF8_update_preferred_charsets(oc, conv); + *convp = conv; return conv; } --- t2/libx11-1.6.3/src/xlibi18n/lcUTF8.c 2015-03-09 15:28:45.000000000 -0700 +++ t3/libx11-1.6.3/src/xlibi18n/lcUTF8.c 2016-08-18 21:41:19.397019737 -0700 @@ -74,10 +74,12 @@ #ifdef HAVE_CONFIG_H #include #endif +#include #include #include "Xlibint.h" #include "XlcPubI.h" #include "XlcGeneric.h" +#include "XomGeneric.h" static XlcConv create_conv( @@ -2390,3 +2392,108 @@ /* Register converters for XlcNFontCharSet */ _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNFontCharSet, open_wcstofcs); } + +// fontset_has_charset checks fontsets in oc for an initialized with the +// provided charset name. If one is found it returns true. +// The purpose is to be able to know if the encoding is in the fontset. +static bool +fontset_has_charset(XOC oc, const char * const charset_name) +{ + FontSet font_set = XOC_GENERIC(oc)->font_set; + const int num = XOC_GENERIC(oc)->font_set_num; + int charset_count = 0; + XlcCharSet * charset_list = NULL; + + if (!charset_name || strlen(charset_name) == 0) { + return false; + } + + for (int i = 0; i < num; i++) { + // If there is no font name then the font isn't loaded. + // See omGeneric.c's create_fontset(). + if (!font_set->font_name) { + font_set++; + continue; + } + + charset_count = font_set->charset_count; + charset_list = font_set->charset_list; + + for (int j = 0; j < charset_count; j++) { + if (strcmp((*charset_list)->encoding_name, charset_name) == 0) { + return true; + } + charset_list++; + } + font_set++; + } + + return false; +} + +XlcConv +lcUTF8_update_preferred_charsets(XOC, XlcConv); + +// lcUTF8_update_preferred_charsets updates the preferred charsets in conv to +// contain only those where the fontsets in oc have a charset. +// Otherwise preferred charsets may include those where our fontset does not +// have a font loaded for the charset, which can lead to problems drawing text. +XlcConv +lcUTF8_update_preferred_charsets(XOC oc, XlcConv conv) +{ + int num_preferred = 0; + XlcConv new_conv = NULL; + Utf8Conv * new_preferred = NULL; + const char * charset_name = NULL; + int i = 0; + + // Count how many preferred charsets there are currently. + // We need to know this to decide how much memory to allocate. + for (Utf8Conv * preferred = (Utf8Conv *) conv->state; + *preferred != NULL; + preferred++) + { + num_preferred++; + } + + // Allocate memory for a whole new XlcConv. + // While we only need to change the Utf8Conv memory, it is all allocated at + // once elsewhere, so do so here as well. + // + // If we filter any then this memory block will be a bit oversized. + // + // num_preferred + 1 so we have space for a NULL record. + new_conv = Xmalloc(sizeof(XlcConvRec) + + sizeof(Utf8Conv) * (num_preferred+1)); + if (!new_conv) { + return NULL; + } + + // Pointer to the Utf8Conv memory. + new_preferred = (Utf8Conv *) (new_conv + sizeof(XlcConvRec)); + + // Filter for charsets that are in our fontset. + for (Utf8Conv * preferred = (Utf8Conv *) conv->state; + *preferred != NULL; + preferred++) + { + charset_name = (*preferred)->name; + + if (!fontset_has_charset(oc, charset_name)) { + continue; + } + + new_preferred[i] = *preferred; + i++; + } + + new_preferred[i] = NULL; + + // Setup the XlcConv record. + // Copy the old one's methods, and set the state to our preferred charsets. + new_conv->methods = conv->methods; + new_conv->state = (XPointer) new_preferred; + + Xfree(conv); + return new_conv; +}