国际语言环境指南

第 6 章 复杂文本布局

复杂文本布局 (CTL) 扩展使得 Motif API 能够支持某些写入系统,这些写入系统要求在逻辑和物理文本表示之间进行复杂变换,如阿拉伯语、希伯来语和泰语所要求的变换。CTL Motif 提供了字符成形,如连字、音调符号和段排序,并且支持静态和动态文本小部件的变换。它还支持从右到左和从左到右的文本定向以及动态文本小部件的制表。由于文本绘制是通过绘制层处理的,因此可以很容易地扩展其它小部件库以支持 CTL。

CTL 技术概述

要充分利用这些新特征,用户必须有可移植布局服务 (PLS) 库和适当的语言引擎。CTL 使用 PLS 作为语言引擎的接口,并在显示文本前使用语言引擎变换文本。支持 CTL 的应用程序必须包含附加的资源,请见 CTL 文档中的说明。

具体说来,XomCTL 支持下列复杂语言成形 和重新整理特征(这些特征是由基础的与语言环境有关的 PLS 模块变换提供的):

CTL 体系结构概述

CTL 体系结构 的组织如 图形 6–1 中所示。 堆栈顶部的 Dt Apps 使用 Motif CTL 功能来绘制文本。而 Motif 则使用 PLS 与特定语言环境的语言引擎交互,并执行变换以支持位置变化、数字成形等等。

CTL 体系结构被设计成通过添加新的特定于语言环境的引擎来支持新的语言。换句话说,无须改变 Motif 或 Dt Apps 即可添加对泰语和越南语的支持。

图形 6–1 CTL 体系结构

Graphic

对基于 X 库的应用程序的 CTL 支持

XomCTL(X 库输出模块中的复杂文本布局支持)允许所有的纯粹 X Windows 应用程序(如基于 X 的终端仿真器)具有 CTL 支持。XomCTL 提供了包括 X11 哑字体支持在内的具有完全特色的 Open Source XI18N 实现。

新的 XOC 资源

Solaris 9 环境提供了下列 XOC 资源:

XNText

使用户能够设置需要在其中执行 CTL 操作的文本缓冲区。

XNTextLayoutNumGlyphs

为文本缓冲区中的文本提供字型数目。

XNTextLayoutModifier

与 XmNLayoutModifier 或 Motif 相同。

XNTextLayoutProperty

与PLS 特性相同(输入至输出和输出至输入)。

XNTextLayoutMapInpToOut

与PLS 特性相同(输入至输出和输出至输入)。

XNTextLayoutMapOutToInp

与PLS 特性相同(输入至输出和输出至输入)。

这些特征的描述可以从 X/Open 或PLS 可移植布局服务的规范中获得。

支持 CTL 技术的 Motif 更改

下列 Motif 更改支持 CTL 技术。

XmNlayoutDirection

控制对象布局。

XmStringDirection

指定系统显示字符串中的字符的方向。

XmRendition

将新的伪资源添加到 XmRendition

XmTextXmTextField

影响与 XmRendition关联的文本的布局行为。

XmTextFieldGetLayoutModifier

返回绘制布局对象的布局修饰符字符串。

XmTextGetLayoutModifier

返回与小部件关联的绘制的当前布局对象设置值。

XmTextFieldSetLayoutModifier

设置与其绘制关联的布局对象的布局修饰符值。

XmTextSetLayoutModifier

修改与小部件关联的绘制的布局对象设置。

XmStringDirectionCreate

创建复合字符串。

XmNlayoutDirection

XmNlayoutDirection 资源 [有关 XmNlayoutDirection 的概述,尤其是对 XmStringDirectionXmNlayoutDirection 之间交互的说明,请参见 Motif《程序员指南》(2.1 版 )的 11.3 节。] 控制对象布局。它以如下所述的方式同 LayoutObject 的定向值进行交互。

确定布局方向

如果将 XmNlayoutDirection 指定为 XmDEFAULT_DIRECTION,则小部件的布局方向在创建时从主导伪 XOC 进行设置。对于动态文本(XmTextXmTextField),主导伪 XOC 是与用于小部件的 XmRendition 关联的伪 XOC。对于静态文本 (XmListXmLabelXmLabelG),布局方向从指定方向的第一个复合字符串组件设置。此规范以下列两种方式之一发生:

直接

组件类型为 XmSTRING_COMPONENT_LAYOUT_PUSHXmSTRING_COMPONENT_DIRECTION.

间接

组件类型为 XmSTRING_COMPONENT_LOCALE_TEXT XmSTRING_COMPONENT_WIDECHAR_TEXTXmSTRING_COMPONENT_TEXT,它们都来自组件的关联 XmRendition 和关联 LayoutObject

如果未将 XmNlayoutDirection 指定为 XmDEFAULT_DIRECTION,并且未在布局修饰符字符串中显式指定 XmNlayoutModifier @ls orientation 值,则 XmNlayoutDirection 值将传递给 XOC 及其 LayoutObject

如果同时显式指定了 XmNlayoutDirectionXmNlayoutModifier @ls orientation ,则行为将混合在一起。XmNlayoutDirection 控制小部件对象布局,而 XmNlayoutModifier @ls orientation 值控制布局变换。

请参见《CAE 规范:可移植布局服务:依赖于上下文的定向文本》。开放组:1997 年 2 月; ISBN 1-85912-142-X;文档号码 C616 — 对用于处理依赖于上下文的双向文本转换的可移植功能的说明,这些功能是对现有 POSIX 语言环境模型的扩展。 该文档适用于希望为复杂文本语言提供支持的系统和应用程序程序员。

XmStringDirection

XmStringDirection 是用于指定系统显示字符串字符的方向的数据类型。

XmNlayoutDirection 资源为任何不包含用于指定字符串方向的组件的复合字符串 (XmString) 设置缺省绘制方向。因此,要设置布局方向,您需要为 XmNlayoutDirection 资源设置适当值。 不需要创建具有特定方向组件的复合字符串。当应用程序绘制 XmString 时,该应用程序应查看所创建的字符串是否具有显式方向 (XmStringDirection)。如果没有方向组件,应用程序应检查当前小部件的 XmNlayoutDirection 资源的值并使用该值作为 XmString 的缺省绘制方向。

XmRendition

CTL 将新的伪资源添加到下表中列出的 XmRendition

表 6–1 XmRendition 中的新资源

名称c 

类/类型 

存取 

缺省值c 

XmNfontType

XmCFontType/XmFontType

CSG 

XmAS_IS

XmNlayoutAttrObject

XmClayoutAttrObject/String

CG 

NULL

XmNlayoutModifier

XmClayoutModifier/String

CSG 

NULL

XmNfontType

指定“绘制”字体对象的类型。对于 CTL,此资源的值必须是 XmFONT_IS_XOC 值。 如果该值不匹配,则 XmNlayoutAttrObjectXmNlayoutModifier 资源将被忽略。

如果此资源的值是 XmFont_IS_XOC,并且未指定 XmNfont 资源,则 XmNfontName 资源的值将在创建时在 XmNlayoutAttrObject 资源所指定的语言环境或当前语言环境中转换成 XOC 对象。 此外, XmNlayoutModifier 资源的值被传递到任何与该 XOC 关联的布局对象

XmNlayoutAttrObject

指定布局 AttrObject 参数。 该资源用于创建与该 XOC(它与此 XmRendition 关联)关联的布局对象。有关该字符串的语法和语义,请参考布局服务 m_create_layout() 规范。有关“布局修饰符定向”输出值和 XmNlayoutDirection 小部件资源间交互作用的说明,请参见 XmNfontType 的描述。

XmNlayoutModifier

指定要传递给与该 XmRendition 的 XOC 一起使用的布局对象的布局值。 有关该字符串的语法和语义,请参见《CAE 规范》。

使用 XmRendition{Retrieve,Update} 设置该资源可将该字符串传递给与此绘制的关联 XOL 相关联的布局对象。这是用于动态配置布局服务的机制。如果 OrientationContext TypeOfTextTextShaping ShapeCharset 发生更改,则可能会导致不可预测的行为。

附加布局行为

XmNlayoutModifier 影响与 XmRendition 关联的文本的布局行为。 例如,如果数字的布局缺省处理是 NUMERALS_NOMINAL,则用户可以通过将XmNlayoutModifier 设置为 @ls numerals=nominal:national@ls numerals=:national 而更改为 NUMERALS_NATIONAL

布局值可分为下列几个组:

XmTextXmTextField

Xm CTL 扩展了 XmTextXmTextField,方法是模仿 Motif 2.0 CSText 小部件, 添加一组以可视方式运行的相似的移动和删除操作。标准 Motif 2.1 TextTextField 不区分逻辑和物理顺序:下一个向前 意为 “向右”,而上一个向后 意为“向左” CSText,然而,请进行适当的区分并定义一组具有严格物理名称的新操作(例如,left-character ()delete-right-word()等等)。所有这些操作例程均被定义为对小部件的 XmNlayoutDirection 敏感,并可调用适当的下一个上一个 操作。 Xm CTL 扩展比 CSText 扩展稍微复杂一些。 Xm CTL 扩展对小部件的全局定向不敏感,但是对伪 XOC 所确定的光标周围物理字符的特定方向性(包括中性稳定性)敏感。

还有一个新的资源,用于控制选择策略、提供绘制标签以及控制对齐方式。

新 Xm CTL 操作集合大致是 {Move,Delete,Kill} 乘以 {Left,Right} 乘以 {Character,Word} 的向量积,如下所示。

表 6–2 Xm CTL 中的新资源

名称  

类/类型  

存取  

缺省值  

XmNrenditionTag

XmCRenditionTag/XmRString

CSG  

XmFONTLIST_DEFAULT_TAG

XmNalignment

XmCAlignment/XmRAlignment

CSG  

XmALIGNMENT_BEGINNING

XmNeditPolicy

XmCEditPolicy/XmREditPolicy

CSG  

XmEDIT_LOGICAL

XmNrenditionTag

指定位于 XmNrenderTable 资源中(用于此小部件)的XmRendition 的绘制标签。

XmNalignment

指定此小部件中使用的文本对齐方式。 仅支持 XmALIGNMENT_END XmALIGNMENT_CENTER

XmNeditPolicy

指定此小部件使用的编辑策略(XmEDIT_LOGICAL XmEDIT_VISUAL)。 如果指定 XmEDIT_VISUAL ,则选择、光标移动和删除将以可视形式进行。 设置该资源还可将标准键盘移动和删除事件的转换更改为新的“可视”操作列表或现有的逻辑操作。

字符定向操作例程

forward-cell()backward-cell() 操作在指定的方向中查询字符的定向。 如果方向是从左向右,则它们调用相应的下一个/向前上一个/向后 变量:

字符定向附加行为

这些操作通过使用布局服务变换 OutToInpProperty 缓冲区(对于嵌套级)来确定字符的定向。 因而,小部件的行为取决于语言环境的特定变换。 如果 OutToInp (尤其是 Property 缓冲区)中的信息不准确,则小部件可能会产生意外行为。 此外,由于语言环境特定的模块处于该规范的范围之外,相同文本、应用程序、资源值和 LayoutObject 配置的双向编辑行为可能因平台的不同而不同。

可视模式操作导致显示基于单元的行为。逻辑模式操作导致基于字符的逻辑行为。 例如,delete-right-character() 操作删除与显示单元相对应的输入缓冲区字符。 即,一个 LayoutObject 变换 “特性”字节“新单元指示器”为 1 的输入缓冲区字符,以及“新单元指示器” [有关 Property 缓冲区的详细信息,请参见《CAE 规范 》中的 m_transform_layout() 规范。] 为 0 的所有后继字符。

同样,对于 backward-character(),插入点在输入缓冲区中向后移动一个字符,光标被在与关联的输出缓冲区字符相对应的可视位置重新绘制。 这意味着需要进行若干次击键以在复合显示单元中移动;当插入点在“新单元指示器”是 0 的输入缓冲区字符(即音调符号或连字片段)中移动时,光标并不实际更改显示位置。

这意味着删除操作或者从逻辑/输入缓冲区端执行,或者从物理/输出端的显示单元级执行。 没有严格的、物理的逐字符删除模式,因为在输入和输出缓冲区之间不存在一对一的对应关系。 例如,给定的物理字符只能代表逻辑字符片断。

XmText 操作例程

下表描述 XmText 操作例程。

left-character(extend)

如果 XmNeditPolicyXmEDIT_LOGICAL 并且被不带参数调用,则插入光标在逻辑上向后移动一个字符。 如果插入光标位于行首,则它将移动到上一行(如果存在的话)的最后一个逻辑字符。 否则,插入光标位置不变。

如果 XmNeditPolicyXmEDIT_VISUAL,则光标移动到光标位置的左侧。 如果插入光标位于行首,则它将移动到上一行(如果存在的话)的结尾字符。

如果使用 extend 参数调用 left-character() ,则插入光标就象没有参数时一样移动,并扩展当前所选内容。

left-character() 操作使用原因值 XmCR_MOVING_INSERT_CURSOR 生成对 XmNmotionVerifyCallback 过程的调用。 如果使用 extend 参数调用,则该操作可以生成对 XmNgainPrimaryCallback 过程的调用。 有关详细信息,请参见《Motif 程序员参考》中的回调说明。

right-character(extend)

如果 XmNeditPolicyXmEDIT_LOGICAL 并且被不带参数调用,则它将插入光标逻辑地向前移动一个字符。 如果插入光标位于行的逻辑结尾处,则它将插入光标移动到下一行(如果存在的话)的逻辑开始处。

如果 XmNeditPolicyXmEDIT_VISUAL,则光标移动到该光标位置的右侧。 如果插入光标位于行尾,则它将插入光标移动到下一行(如果存在的话)的开始处。

如果使用 extend 参数调用,则它将象没有参数一样移动插入光标并扩展当前所选内容。

right-character() 操作使用原因值 XmCR_MOVING_INSERT_CURSOR 生成对 XmNmotionVerifyCallback 过程的调用。 如果使用 extend 参数进行调用,则可生成对 XmNgainPrimaryCallback 过程的调用。 有关详细信息,请参见 Motif 程序员参考 中的回调说明。

right-word(extend)

如果 XmNeditPolicyXmEDIT_LOGICAL 并且被不带任何参数调用,则它将插入光标移动到逻辑后继字(如果存在的话)的逻辑开始处;否则,它移动到当前字的逻辑结尾处。 如果插入光标位于行的逻辑结尾处或该行的最后一个逻辑字时,它将光标移动到下一行(如果存在的话)的第一个逻辑字;否则,它移动到当前字的逻辑结尾处。

如果 XmNeditPolicyXmEDIT_VISUAL 并被不带参数调用,则它将插入光标移动到行尾右侧或后面的第一个空格字符后的第一个非空格字符处。

如果使用 extend 参数进行调用,则它将象不带参数调用一样移动插入光标,并扩展当前所选内容。

left-word() 操作使用原因值 XmCR_MOVING_INSERT_CURSOR 生成对 XmNmotionVerifyCallback 过程的调用。 如果使用 extend 参数调用,则可以生成对 XmNgainPrimaryCallback 过程的调用。 有关详细信息,请参阅 Motif 程序员参考 中的回调说明。

delete-left-character()

如果 XmNeditPolicyXmEDIT_LOGICAL,它等效于 delete-previous-char()。 如果 XmNeditPolicyXmEDIT_VISUAL,则在标准模式下,如果有一个非空选择,则它将删除该选择;否则它将删除插入光标左侧的字符。 在添加模式下,如果有一个非空选择,光标未离开所选内容,并且 XmNpendingDelete 被设置为真,则它将删除该选择;否则,它将删除插入光标左侧的字符。 这可能会影响选择。

delete-left-character() 操作使用原因值 XmCR_MODIFYING_TEXT_VALUE 生成对 XmNmodifyVerifyCallback 过程的调用,并且使用原因值 XmCR_VALUE_CHANGED 生成对 XmNvalueChangedCallback 过程的调用。

delete-right-character()

如果 XmNeditPolicyXmEDIT_VISUAL,则它等效于 delete-next-character()。如果 XmNeditPolicyXmEDIT_VISUAL,则在标准模式下,如果有一个非空选择,则它将删除该选择;否则,它删除插入光标右侧的字符。 在添加模式中,如果有一个非空选择,并且光标未离开所选内容,则将 XmNpendingDelete 设置为真,并删除该选择;否则,将删除插入光标右侧的字符。 这可能会对选项造成影响。

delete-right-character() 操作使用原因值 XmCR_MODIFYING_TEXT_VALUE 生成对 XmNmodifyVerify-Callback 过程的调用,并且使用原因值 XmCR_VALUE_CHANGED 生成对XmNvalue-ChangedCallback 过程的调用。

实现了一些基于单元的例程以支持字符组合、连字和音调符号。 换句话说,两个或多个字符可以被占用一个表示单元的单个字形表示。

XmText 单元操作例程如下所示:

backward-cell(extend)

将插入光标向后移动一个单元。 如果 XmNeditPolicy XmEDIT_LOGICAL,则将插入光标移动到逻辑上位于当前单元之前的那个单元(如果存在的话)的开始处。否则,将其移动到当前单元的开始处。

如果 XmNeditPolicyXmEDIT_VISUAL,则光标移动到光标左侧单元(如果它存在的话)的开始处。 prev-cell() 操作使用原因值 XmCR_MOVING_INSERT_CURSOR 生成对 XmNmotionVerifyCallback 过程的调用。 如果使用 extend 参数进行调用,则可以生成对 XmNgainPrimaryCallback 过程的调用。 有关详细信息,请参阅 Motif 程序员参考 中的回调说明。

forward-cell(extend)

将插入光标移动到下一个逻辑单元(如果存在的话)的开始处。否则将它移动到该单元的结尾处。 如果 XmNeditPolicyXmEDIT_LOGICAL,则光标向前移动一个单元。

如果 XmNeditPolicyXmEDIT_VISUAL,则光标移动到该光标位置右侧单元的开始处(如果该单元存在的话)。否则,光标移动到当前单元的结尾处。forward-cell() 操作使用原因值 XmCR_MOVING_INSERT_CURSOR 生成对 XmNmotionVerifyCallback 过程的调用。 如果使用 extend 参数进行调用,则可以生成对 XmNgainPrimaryCallback 过程的调用。 有关详细信息,请参阅 Motif 程序员参考 中的回调说明。

XmTextFieldGetLayoutModifier

XmTextFieldGetLayoutModifier() 返回一个布局修饰符字符串,它反映了与其绘制关联的布局对象的状态。

XmTextFieldGetLayoutModifier() 的语法是:

#include <Xm/TextF.h> String XmTextFieldGetLayoutModifier( 小部件 小部件)

XmTextFieldGetLayoutModifier() 存取与小部件关联的绘制的当前布局对象设置值。当使用公用函数更改布局对象修饰符的值时,XmTextFieldGetLayoutModifier 函数返回布局对象的完整状态,而不仅仅返回更改后的值。

XmTextFieldGetLayoutModifier() 以字符串值的形式返回布局对象修饰符值。

XmTextGetLayoutModifier

XmTextGetLayoutModifier() 返回一个布局修饰符字符串,它反映了与其绘制关联的布局对象的状态。

XmTextGetLayoutModifier() 的语法是:

#include <Xm/Text.h>String XmTextGetLayoutModifier( 小部件 小部件 )

XmTextGetLayoutModifier 存取与小部件关联的绘制的当前布局对象设置值。当使用公用函数更改布局对象修饰符值时, XmTextGetLayoutModifier 函数返回布局对象的完整状态,而不仅仅返回更改后的值。

XmTextGetLayoutModifier 以字符串值的形式返回布局对象修饰符值。

XmTextFieldSetLayoutModifier

XmTextFieldSetLayoutModifier() 设置布局修饰符值,这会更改与其绘制关联的布局对象的行为。

XmTextFieldSetLayoutModifier() 的语法是:

#include <Xm/TextF.h>void XmTextFieldSetLayoutModifier( 小部件 小部件 ,string layout_modifier)

XmTextFieldSetLayoutModifier 修改与小部件相关联的绘制的布局对象设置。 当使用该公用函数设置布局对象修饰符值时,只有在输入参数中指定的属性被更改;其余属性保持不变。

XmTextSetLayoutModifier

XmTextSetLayoutModifier() 设置布局修饰符值,这会更改与其绘制关联的布局对象的行为。

XmTextSetLayoutModifier() 的语法是:

#include <Xm/Text.h>void XmTextSetLayoutModifier( 小部件 小部件 ,string layout_modifier)

XmTextSetLayoutModifier 修改与小部件关联的绘制的布局对象设置。 当布局对象修饰符值使用该公共函数设置时,只有输入参数中指定的属性被更改; 其余属性保持不变。

XmStringDirectionCreate

XmStringDirectionCreate 用于创建复合字符串。

XmTextSetLayoutModifier() 的语法是:

#include <Xm/Xm.h>XmString XmStringDirectionCreate( 方向) XmStringDirection 方向

XmStringDirectionCreate 创建一个具有单个组件(一个具有给定值的方向)的复合字符串。 另一方面,XmNlayoutDirection 资源为任何不具有指定其方向的组件的复合字符串 (XmString) 设置缺省绘制方向。 因此,要设置布局方向,您需要做的全部事情就是为 XmNlayoutDirection 资源设置适当的值。 您不需要创建具有特定方向组件的复合字符串。当应用程序绘制 XmString 时,它应查看所创建的字符串是否具有显式方向 (XmStringDirection)。 如果没有方向组件,应用程序应该检查当前小部件的 XmNlayoutDirection 资源的值并使用该值作为 XmString 的缺省绘制方向。

UIL Arguments

下表显示了 UIL 参数。

表 6–3 UIL
 UIL 参数名称 参数类型

XmNlayoutAttrObject

字符串 

XmNlayoutModifier

字符串 

XmNrenditionTag

字符串 

XmNalignment

整数 

XmNeditPolicy

整数 

如何开发 CTL 应用程序

以下部分说明如何开发 CTL 应用程序。

布局方向

复合字符串的方向被存储起来,以便使数据结构对于描述从左到右的语言(如英语、西班牙语、法语和德语)的文本或者从右到左的语言(如希伯来语和阿拉伯语)的文本同样有用。在 Motif 应用程序中,可以使用 VendorShell 或 MenuShell 中的 XmNlayoutDirection 资源来设置布局方向。管理器和原始小部件(以及小配件)也具有 XmNlayoutDirection 资源。缺省值从具有相同资源的最近的祖先继承。

对于 XmText 小部件,还必须指定垂直方向。将 layoutDirection 设置为 XmRIGHT_TO_LEFT 会使字符串方向成为从右到左,而光标则垂直向下移动。如果垂直方向很重要,并且需要从上到下对齐,那么请一定指定 XmRIGHT_TO_LEFT_TOP_TO_BOTTOM ,它指定组件先从右到左排列,再从上到下排列,从而得到所需要的行为。

此外,XmText TextField小部件的行为受 XmRenditionXmNalignment XmNlayoutModifier 资源的影响。这些资源与 XmNlayoutDirection 共同控制文本小部件的布局行为。图形 6–2 中阐释了此行为。

该图中使用的输入字符串是:

Graphic

下图的 XmNlayoutModifier 字符串 @ls orientation= 设置值如左列中所示。

图形 6–2 布局方向

Graphic

如插图所示,XmNAlignment 规定文本是否与布局方向一起右对齐或左对齐。 XmNlayoutModifier 将文本分成多段,并根据定向值将它们从左到右或从右到左排列。换句话说,如果 XmNlayoutDirectionXmRIGHT_TO_LEFT ,并且 XmNAlignment 值是 XmALIGNMENT_BEGINNING ,则该字符串右对齐。

创建绘制

下面的代码使用 Rendition(其标记为“ArabicShaped”)来创建 XmLabel(其 XmNlabelString 属于 XmCHARSET_TEXT 类型)。Rendition 是用 “ar” (对应于阿拉伯语语言环境的语言环境名称)的 XmNlayoutAttrObject 和布局修饰符字符串(为输出缓冲区指定 NUMERALS_CONTEXTUALNumerals 值和 “unicode-3.0.” 的 ShapeCharset 值)创建的

语言环境的特定布局模块将其输入文本转移到使用 16 位 Unicode 3.0 代码集编码的物理字符的输出缓冲区 。由于已经指定了显式布局语言环境,因此此文本能够独立于运行时语言环境设置正确绘制。 在此示例中,用 ISO 8859–6 对输入进行编码。

int n;
Arg args[10];
Widget w;
XmString labelString;
XmRendition rendition;
XmStringTag renditionTag;
XmRenderTable renderTable;
      /* alef lam baa noon taa - iso8859-6 */
labelString = XmStringGenerate("\307\344\310\346\312\", NULL
			                          XmCHARSET_TEXT, "ArabicShaped");
w = XtVaCreateManagedWidget("a label", xmLabelWidgetClass, parent,
                             XmNlabelString, labelString,
		                          XmNlabelType, XmSTRING,
                             NULL);
n = 0;
XtSetArg(args[n], XmNfontName, "-*-*-medium-r-normal-*-24-*-*-*-*-*-*");
      n++;
XtSetArg(args[n], XmNfontType, XmFONT_IS_XOC); n++;
XtSetArg(args[n], XmNlayoutAttrObject, "ar"); n++;
XtSetArg(args[n], XmNlayoutModifier, 
          "@ls numerals=:contextual, shapecharset=iso8859-6"); n++;
renditionTag = (XmStringTag) "ArabicShaped";
rendition = XmRenditionCreate(w, renditionTag, argcs
s, n);
renderTable = 
    XmRenderTableAddRenditions(NULL, &rendition, 1, XmREPLACE_MERGE);
XtVaSetValues(w, XmNrenderTable, renderTable, NULL);

编辑绘制

下面的代码用单个 Rendition 创建 TextField 小部件和 RenderTableXmNlayoutAttrObject XmNlayoutModifier 伪资源均未指定,因此缺省为 NULL。 该值意味着与 Rendition 关联的布局对象属于缺省语言环境(如果有的话)。

要使此示例正常工作,该语言环境必须设置为其代码集是 ISO 8859-6 并且特定于该语言环境的布局模块可支持 IMPLICIT_BASIC 算法的语言环境。Rendition LayoutObjectImplicitAlg 值已通过 RenditionXmNlayoutModifier 伪资源进行了修改。

int n;
Arg args[10];
Widget w;
	XmRendition rendition;
XmStringTag renditionTag;
XmRenderTable renderTable;
w = XmCreateTextField(parent, "text field", args, 0);
n = 0;
	XtSetArg(args[n], XmNfontName, "-*-*-medium-r-normal-*-24-*-*-*-*-*-*-*");
     n++;
	XtSetArg(args[n], XmNfontType, XmFONT_IS_XOC); n++;
renditionTag = (XmStringTag) "ArabicShaped";
rendition = XmRenditionCreate(w, renditionTag, args, n);
renderTable = 
    XmRenderTableAddRenditions(NULL, &rendition, 1, XmREPLACE_MERGE);
XtVaSetValues(w, XmNrenderTable, renderTable, NULL);
	....
n = 0;
XtSetArg(args[n], XmNlayoutModifier, "@ls implicitalg=basic");
     n++;
XmRenditionUpdate(rendition, args, n);

在资源文件中创建绘制表

对于正确国际化的应用程序,应在其资源文件中指定 Rendition 和绘制表。在文件中指定了绘制表后,程序二进制代码就与给定语言环境的特定需要无关,从而能够轻松地进行定制以满足本地需要。

绘制表是用以下语法在资源文件中指定的: resource_spec:[tag[, tag]*]

其中 tag 表示适用于某个绘制的 XmNtag 资源的某个字符串。

该行将按指定要求创建包含一个或多个绘制的绘制表。这些绘制被附加到指定的标记上:

resource_spec[*|.] rendition[*|.]resource_name:

以下示例阐释了与 XmRendition 相关的 CTL 资源,这些资源可用资源文件来设置。 fontType 必须设置为 FONT_IS_XOC 才能使布局对象生效。使用 @ls 指定的 layoutModifier 通过绘制对象传递给布局对象。

有关可使用 layoutModifier 在布局对象上设置的完整资源列表,请参见《CAE 规范: 可移植布局服务: 与上下文有关的定向文本》,开放组: 1997 年 2 月; ISBN 1-85912-142-X; 文档号 C616。

在应用程序中创建绘制表

在创建绘制表之前,应用程序必须至少先创建一个属于该表的绘制。顾名思义, XmRenderTableAddRenditions() 函数也用于使用新的绘制补充绘制表。要创建新的绘制表,请使用 NULL 参数调用 XmRenderTableAddRenditions() 函数来替换现有的绘制表。

以下代码将使用在将 XmNfontType 设置为 XmFONT_IS_XOC 时创建的绘制来创建一个绘制表。

int n;
Arg args[10];
Widget w;
XmString labelString;
XmRendition rendition;
XmStringTag renditionTag;
XmRenderTable renderTable;
      /* alef lam baa noon taa - iso8859-6 */
labelString = XmStringGenerate("\307\344\310\346\312\", NULL
			                           XmCHARSET_TEXT, "ArabicShaped");
w = XtVaCreateManagedWidget("a label", xmLabelWidgetClass, parent,
                            XmNlabelString, labelString,
		                         XmNlabelType, XmSTRING,
                            NULL);
n = 0;
XtSetArg(args[n], XmNfontName, "-*-*-medium-r-normal-*-24-*-*-*-*-*-*-*");
     n++;
XtSetArg(args[n], XmNfontType, XmFONT_IS_XOC); n++;
XtSetArg(args[n], XmNlayoutAttrObject, "ar"); n++;
XtSetArg(args[n], XmNlayoutModifier, 
          "@ls numerals=nominal:contextual, shapecharset=iso8859-6"); n++;
renditionTag = (XmStringTag) "ArabicShaped";
rendition = XmRenditionCreate(w, renditionTag, args, n);
renderTable = 
    XmRenderTableAddRenditions(NULL, &rendition, 1, XmREPLACE);
XtVaSetValues(w, XmNrenderTable, renderTable, NULL);

水平制表符

为控制文本的位置,复合字符串可包含几个制表符字符。为了在显示时对这些字符进行解码,一个小部件将指向实际用于该复合字符串的绘制,并找到一个制表停止位置列表。但是,动态小部件 TextField XmText 并不使用该绘制的制表符资源。它们使用 8*(width of character 0) 公式来计算制表符宽度。

制表符度量值是与复合字符串显示的左边界的距离。如果布局方向是从右向左的,则该距离从右边界开始度量。无论文本方向如何(阿拉伯语从右向左或英语从左向右),制表符都按布局方向 (XmNlayoutDirection ) 的指定要求向右或向左插入空格。

制表符后面的文本总是在制表停止位置处对齐。制表停止位置从小部件的起始处算起,而小部件的起始处又受到 XmNlayoutDirection 的影响。 下图阐释了制表符的行为及其与文本的方向性和小部件的 XmNlayoutDirection 的交互作用。

此说明的输入是 abc\tdef\tgh

图形 6–3 制表符行为

Graphic

鼠标选定

用户用鼠标按钮 1 创建一个主选定。 按下此按钮将撤消选定全部现有的选定,并将插入光标和锚点移到文本中按下按钮的位置上。按住鼠标按钮 1 并拖动它,可以选择锚点和指针位置之间的所有文本,并撤消选定此范围外的任何文本。

选定的文本受资源 XmNeditPolicy 影响,而后者可设置为 XmEDIT_LOGICALXmEDIT_VISUAL。如果 XmNeditPolicy 设置为 XmEDIT_LOGICAL,并且选定的文本是双向的,则选定的文本从视觉上将是不连续的,而是多个文本段的集合。这是因为逻辑缓冲区中的文本与显示内容之间没有一对一的对应关系。

因此,双向文本的逻辑字符的连续缓冲区在绘制时不能产生连续的字符流。与此相反,如果 XmNeditPolicy 设置为 XmEDIT_VISUAL,则选定文本在视觉上可能是连续的,而在逻辑缓冲区中却是分段的。因此,在同一个光标点处选定、删除和插入双向文本的顺序操作不会产生同一个字符串。

键盘选定

用鼠标进行的选定操作也可以使用键盘来完成。可以使用 Shift-arrow 键的组合来选定文本。

选定的文本受资源 XmNeditPolicy 影响,而后者可设置为 XmEDIT_LOGICAL XmEDIT_VISUAL。 如果 XmNeditPolicy 设置为 XmEDIT_LOGICAL,并且选定的文本是双向的,则选定的文本在视觉上将是不连续的。由于逻辑缓冲区中的文本与显示内容之间没有一对一的关系,因此双向文本中的逻辑字符的连续缓冲区在绘制时不能产生连续的字符流。

与此相反,如果 XmNeditPolicy 设置为 XmEDIT_VISUAL,则选定的文本在视觉上可能是连续的,而在逻辑缓冲区中却是分段的。因此,在同一个光标点处按选定、删除和插入双向文本的顺序操作不会产生同一个字符串。

文本资源和几何图形

与几何图形相关的文本资源如下所示:

移植说明

为复杂文本布局 (CTL) 启用的新 Motif 库位于 /usr/dt/lib/libXm.so.4 中。 如果您的应用程序链接到 libXm.so.3,那么它不支持 CTL。 ldd app_name 显示应用程序链接到的库。 要移植现有的应用程序以启用 CTL,需要执行以下步骤。

  1. -DSUN_CTL 添加到您的 Makefile 中。 该标志很重要,它包括支持 CTL 所需的数据结构。这应在编译期间进行设置。

  2. 重新编译现有的应用程序。这一重新编译将自动与 CTL 启用的 Motif 库 libXm.so.4 进行链接

  3. XmText.translations 资源添加到应用程序资源文件中。如果没有这些资源,语言环境的布局引擎将不能启动。

  4. 请参考附加在您的文档中的应用程序样例。


注意:

fontName 资源中使用您的语言环境中提供的并适用于您的语言环境的字体名称。


例如,如果您希望在 XmTextField XmText 小部件中进行基于单元的字符移动(泰语),请按以下方式设置相应小部件的平移:

XmText.translations: #override \n\

<Key>osfRight:forward-cell() \n\

<Key>osfLeft:backward-cell() \n\

<Key>osfDelete:delete-next-cell() \n\

<Key>osfBackSpace:delete-previous-cell() \n\