让你的X11支持中日韩文字

(由于我的X11不支持中文locale,所以我就一篇探寻,一边写了这篇帖子)

我的操作系统是FreeBSD 6.0,X11是cvsup中的最新版

gtk_set_locale溯源

由于我的gtk老是报告说"locale not supported by C library",我决定仔细的调试下看问题出在哪里。首先,gtk程序一般都要先调用gtk_set_locale()函数,然后gtk_set_locale调用gdk_set_locale,gtk_set_locale调用setlocale,XSetlocaleModifiers,XSupportLocale,由于我的setlocale没有问题,所以我就向Xlib进发。

在lcWrap.c中找到了XSupportLocale,XSupportLocale调用_XlcCurrentLC(),如果_XlcCurrentLC()返回NULL,就代表失败,于是XSupportLocale返回false;

_XlcCurrentLC()调用_XOpenLC((char *) NULL),然后关闭last_lcd, 并设置静态变量last_lcd为_XOpenLC的返回值。但是这个_XOpenLC函数就比较复杂了。_XOpenLC首先调用name=setlocale (LC_CTYPE, (char *)NULL)获得当前的LC_CTYPE设置,然后如果在配置文件中没有定义X_LOCALE 这个宏参数,那么需要调用_XlcMapOSLocaleName将setlocale的返回值translate一下。(在BSD上这是需要的)._XlcMapOSLocaleName返回的依然是原来的name,或者是原来name的一个子字符串。

然后下面加一把锁子。因为这里需要访问并修改静态全局变量lcd_list.

首先先在lcd_list中查找name,如果找到,把这个lcd的引用计数加1,并解锁返回。

如果没有找到。就看静态变量loader_list是否为NULL,是NULL的话就调用_XlcInitLoader();

loader_list其实一个是一个很简单的链表。每个元素里面包含一个类型为XLCdLoadProc的函数指针。这是它的函数原型

typedef XLCd (*XLCdLoadProc)( 
    const char*         name 
)

然后将我们前面通过setlocale获得的name作为参数传递给loader_list中的每一个函数并调用。如果返回值不为NULL,算是找到了。就初始化一个XLCdList元素并把它插入到现在的lcd_list的开头。否则返回NULL,代表失败。然后我们看这个loader_list是从哪里来的。

loader_list在lcInit中初始化。在这里我发现了一个很有趣的事情。如果在配置文件中定义了USE_DYNAMIC_LC,那么X11静态编译的时候是不会把default loader,generic loader,UTF8 loader之类的编译进源代码中的。如果没有定义USE_DYNAMIC_LC,那么这些会编译进去。并,查看是否定义了X_LOCALE(又是这个奇妙的东西),只有在定义了它的前提下,才会打开中日韩的支持!!! 明显,BSD的默认配置文件中是没有定义它的。在Xorg的默认设置中,只有darwin,linux,cygwin,lynx,os2,sgi中是打开了这个支持的。是不是因为BSD的用户不多所以测试不够所以为了谨慎它就没有打开?

我在FreeeBSD.cf的末尾加上了一行

#define X_LOCALE  YES

然后重新编译

(就在写完这篇帖子后,死机了,我的硬盘不堪重负又坏了,这次是一大片坏区,直接的结果是/usr/libexec这个文件夹没有了。已经根本无法启动shell。阿门!我的确没有钱买第二块硬盘啊)

此博客中的热门博文

少写代码,多读别人写的代码

在windows下使用llvm+clang

tensorflow distributed runtime初窥