【转】ReactOS的中文本地化

来源:互联网 发布:c语言定义define 编辑:程序博客网 时间:2024/06/05 17:16

[分析环境reactos0.3.1 ,i386体系]

ReactOS的中文本地化

(类似Windows操作系统源代码分析)

1 什么是ReactOS

1996年,一群开源软件开发者启动了一个名为 FreeWin95 的项目,旨在实现一个 Windows 95 的克隆操作系统。这个项目当时只停留在关于系统实现的讨论上。
到了1997年末,项目依旧没有进展。开发成员呼吁重新开始这个项目,而实现的目标也改为 Windows NT 系统,同时项目名称命名为 ReactOS(react 反抗)。1998年2月ReactOS项目正式启动,开始开发系统内核和基本的驱动程序。
ReactOS一直与WINE(另一个开源项目)紧密合作,让ReactOS随着WINE在Win32 API项目的发展而发展。Wine的DLL因其大多可以在ReactOS和Wine之间共同使用而被受关注。为此双方致力于兼容问题,务求令余下的少量 DLL 也能为 ReactOS 所用
ReactOS的目标是实现一个基于windows架构的免费并且开源的操作系统,提供对已存在的windows应用和驱动软件支持,简单的说就是在Microsoft Windows上开发的应用(二进制文件)或基于windows(目前是windows2000以下)开发的驱动不需要任何从新编译就可以运行在ReactOS上。以下是我对ReactOS的一些中文支持的截图
 

2什么是Wine

Wine (Wine Is Not an Emulator) 是一个Windows应用程序接口(API)库,作为一个Windows程序和Linux之间的桥梁可运行在X和UNIX 之上的一套Windows 3。x 和 WindowsAPIs的实现。它是一个Windows兼容层。
用通俗的话说,就是一个Windows模拟器,这个层即提供了两套方案来实现在Unix上模拟windows平台特性,第一种方法是将居于windows得源代码与Wine提供的居于UNIX的开发工具包(Winelib)从新编译产生一个新的可以在Unix下运行的二进制文件。第二种方法是利用Wine提供的程序加载器,该加载器允许不用任何修改Windows 3.1/95/NT的二进制文件运行在Intel Unix及其衍生版本下。Wine可以工作在绝大多数的UNIX版本下,包括Linux, FreeBSD, 和 Solaris。

3 两者的区别

不要将ReactOS想象成一个将类Unix系统与Wine的整合,作为Wine它主要是提供一些Windows APIs的上层模拟。而这些上层APIs的低层调用被Wine做了移花接木,转到了X windwo或者是Unix的调用。但是ReactOS则不同,由于两个项目都是开源的,所以ReactOS将部分Wine的代码作了移植,而为上层APIs服务的低层函数调用则完全由自己实现,并且这些调用规则也完全与Microsoft Windows低层调用兼容。ReactOS并非是居于Unix及其衍生版本的。

4 中文本地化需要解决的问题

中文需要解决的问题不仅仅是汉字的显示,更重要的是要解决字符的编码得问题,先从ASCII说起。ASCII是用来表示英文字符的一种编码规范,每个ASCII字符占用1个字节(8bits) 因此,ASCII编码可以表示的最大字符数是256,而中文的字符范围却大大的超过了这个范围。因此用一个字节来表示是远远不够的。
因此中国推出了自己的汉字编码。GB2312它是国家标准但不是国际标准,因为台湾有一个Big5编码标准,很多编码和GB是相同的,这样就会产生同一个文字在不同编码下被解释成不同的汉字。


4.1 什么是Unicode

上面的问题并仅仅是在汉字的编码上产生的问题,在不同的地区不同的文字下都会出现这个问题。
于是,Unicode诞生了,Unicode有两套标准,一套叫UCS-2(Unicode-16),用2个字节为字符编码,另一套叫UCS-4(Unicode-32),用4个字节为字符编码。 以目前常用的UCS-2为例,它可以表示的字符数为2^16=65535,基本上可以容纳所有的欧美字符和绝大部分的亚洲字符 。在Unicode里,所有的字符被一视同仁。汉字不再使用“两个扩展ASCII”,而是使用“1个Unicode”。而ReactOS的内部完全采用Unicode这种编码。因此给中文的实现打下了良好的基础。也就是说目前的主要任务就放在了汉字的显示上。


4.2 语言和区域设置

ReactOS为适应不同地区和语言的用户以及键盘布局在注册表中设立了一个键值,用于表示用户所在的地区。(主要还是和Microsoft Windows兼容)
在系统初始化过程中会查询注册表文件用于确定系统当前所在的区域和默认的输入语言,并且根据这个配置信息来确定创建线程时的区域信息,则这个线程中的区域信息又决定了如何查找应用程序中和语言相关的资源信息。

在注册表中有几个键值是用来确定系统所在的区域,当操作系统启动后,这些设置将保存在系统的一些全局变量中,利用这些变量的值系统可以确定当启动一个应用程序时如何加载系统地缺省语言的资源文件。比如如果区域被设置成了美国地区则某个gLocale全局变量的值就是0x 00000409,如果区域是中国则该值为0x00000804,不过就目前的ReactOS 0.3.1版来说还是不要修改安装注册表文件中的设置。因为会导致系统在引导时失败。直接修改代码可以让系统暂时实现比较安全的中文显示,不过这是非标准的做法,以后的版本可能直接修改注册表会更方便。

找到位于(ntoskrnl/ex)的Locale.c这个文件它包含了系统和区域语言相关的函数
这个文件中包含了reactos缺省的区域

/* System IDs: EN_US */
LCID PsDefaultSystemLocaleId = 0x00000409; //chinese 0x00000804
LANGID PsInstallUILanguageId = LANGIDFROMLCID(0x00000409);

/* UI/Thread IDs: Same as system */
LANGID PsDefaultUILanguageId = 0x00000409; //chinese 0x00000804
LCID PsDefaultThreadLocaleId = LANGIDFROMLCID(0x00000409);

修改了上面的信息后,你基本上就不用屏蔽掉非中文资源文件,这时的应用程序会更具具体的环境来显示不同的语言。(一个应用程序是可以包含很多不同语言的资源文件的)

4.3 中文显示

4.3.1 关于字体文件freetype(truetype)

在解决中文编码后,中文的显示相对来说就要简单多了,无非就是根据中文编码查找相应的字库文件,然后将字库文件中的文字信息显示出来。
在windows中,字体的显示使用了一种叫TrueType(轮廓字体的一种)的字体文件,这种字体是设备无关字体,按轮廓存储它们可以任意调整高度,而且打印出来的效果和屏幕上显示的完全相同。
不过TrueType是必须付费的,因此不可能用在一个免费的系统中,好在GNU的开放项目中有一个叫做FreeType的项目它提供了一套TrueType的完整支持。
在中文版的windows中,系统的缺省字体是一种字体名叫“宋体&新宋体”的字体文件,在windows 2000以后这个文件的文件名叫simsun.ttc,在windows98里叫simsun.ttf,需要解释的是ttc是一种包含了多种ttf字体的集合,在这里我们需要的是ttf格式的字体文件,还需要注意的是微软的ttf文件也是有版权的,并且授权协议也不是GPL的形式,因此是不能作为Reactos的一部分来发布的,去找一种类似simsun.ttf的免费中文字体来试验一下ReactOS的中文显示,找到以后把他放入到ReactOS_root/media/fonts文件夹中,如果你不想修改太多的配置文件,我建议以相同的名字替换掉这个文件夹中已经存在的一个字体文件比如courb.ttf。


4.3.2 缺省的系统字体(系统库存字体对象)

在Windows GDI中存在作一些库存GDI对象,这些库存GDI对象中有一部分是库存的字体对象,库存字体对象的作用有一部分是为了系统本身不会平凡的创建字体而占用过多的资源。对于库存字体对象,仅仅需要调用GetStockObject()函数就可以取出库存字体,然后再调用SelectObject()将字体对象选入指定的设备就可以,对于中文版的ReactOS应该建立的缺省的库存字体应该是一个中文的ttf字体,因此还必须修改缺省的库存字体,而且当用户调用GetDCEx是系统需要创建一个DC这个DC会初始化一些缺省的DC信息,如:
这个文件在[ReactOS_Root/subsystems/win32/win32k/objects]下的文件找到以下文件stockobj.c编辑缺省的SystemFont库存字体对象,这个代码将在系统初始化时建立系统的库存能字体:
static LOGFONTW SystemFont =
{ 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GB2312_CHARSET,
 OUT_STRING_PRECIS, CLIP_STROKE_PRECIS, PROOF_QUALITY, VARIABLE_PITCH | FF_SWISS, L"simsun" }; //中文字体名,该字体必须复制到ReactOS_Root/media/fonts文件夹下,具体的字体名称不一定是simsun,要看你复制的这个ttf文件包含的字体叫什么名字。

通过这样的修改后,系统建立的就是一个支持中文的缺省的库存GDI字体对象,所有的缺省操作都将是用这个字体输出。

4.3.3 系统中可替代的字体

当用户调用CreateFont()或CreateFontIndirect()函数指定一个字体名,系统会先查找注册表中的“可替代字体名列表”如果指定的字体名存在于这个“可替代字体名列表”中,则系统会自动将替代这个指定的指定的字体名,在ReactOS的注册表中这个“可替代字体名列表”位于:ReactOS_Root/Boot/bootdata/hivesft.inf中,
HKLM,"SOFTWARE/Microsoft/Windows NT/CurrentVersion/SysFontSubstitutes处,这里列出里用于替代的字体名。如用“MS Shell Dlg”来创建一个逻辑字体,则会被替代成这里指定的字体名。


4.3.4 标题、菜单、按钮中文显示

同样在注册表中可以管理如窗口标题、菜单、按钮等的中文显示,即采用何种字体,字体的大小,颜色等各式。在ReactOS的注册表中位于一下键值部分。
文件在ReactOS_Root/boot/bootdata/hivedef.inf,编辑这个文件的
HKCU, "Control Panel/Desktop/WindowMetrics部分可以修改相对的GUI元素的逻辑字体属性。不过这些数值修改起来有点麻烦,因为是采用二进制的形式表示一个LOGFONTW的结构中各个字段。
理论上讲只要把各个GUI元素如标题条的LOGFONTW结构的lfFaceName修改成中文TTF的字体名如:“simsun”就可以在标题中显示中文,不过这样修改后依然不能显示中文。


4.3.5 ReactOS v0.3.1中存在的问题

对于上面的那个问题我在目前的v0.3.1版中找到了答案。看下面的代码:
文件是Misc.c (位于ReactOS_Root/subsystems/win32/win32k/ntuser下) 编辑这个文件找到
IntGetFontMetricSetting函数,这个函数在系统绘制标题等GUI元素的文字时调用。该函数的目的是查找绘制这些GUI元素时需要的字体信息,不过目前好像有点问题就是它在调用RtlQueryRegistryValues()查询注册表字体信息是返回的Status总是一个FALSE这样就导致了它总是调用之后的字体缺省操作,这就是为什么会在某些窗口的菜单或按钮上看见类似“□□□□”的显示。其实看见“□□□□”符号反而可以证明你已经在显示中文了,只是在这个字体文件中没有找到这个文字而用了“□”符号做缺省替代。
RtlCopyMemory(font, &DefaultFont, sizeof(LOGFONTW));
因此中文化还要将这里改称如下的中文字体名
static LOGFONTW DefaultFont = { 12, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, GB2312_CHARSET, OUT_STRING_PRECIS,CLIP_STROKE_PRECIS, PROOF_QUALITY, VARIABLE_PITCH | FF_SWISS, L"simsun" }; //具体的字体名称不一定是simsun,要看你复制的这个ttf文件包含的字体叫什么名字。
这样一来即使任何操作都将产生中文的逻辑字体。



4.4 输入法

最后是输入法,中文输入法决定了系统是否支持中文的关键,因为即使是所有的显示都可以是中文,但是如果不支持中文的输入,那么说是一个中文的系统也是大打折扣,目前的ReactOS还没有任何的中文输入法,不过在ReactOS的代码中已经可以看见和IME(Input Method Editor)相关的部分,ReactOS是一个开源的项目,还需要大家的支持,也许ReactOS的中文输入法将会由你来创造。


[如需转载请注明出处:(雄)blog.csdn.net/mickey139]