国際化対応言語環境の利用ガイド

第 6 章 CTL: Complex Text Layout

CTL (Complex Text Layout) 拡張機能により、アラビア語、ヘブライ語、タイ語など、論理テキスト表現と物理テキスト表現の間の複雑な変換が必要な言語を Motif API で用いることができます。CTL Motif では文字の整形 (合字、区別的発音符、セグメントの順序の決定など) を行なうことができます。また、静的および動的なテキストウィジェットがサポートされています。さらに、テキストの方向を選択したり (右から左または左から右)、動的なテキストウイジェットにタブを使用したりすることができます。テキストのレンダリングはレンディション層を通じて処理されるので、その他のウィジェットライブラリの CTL サポートへの拡張は容易です。

CTL の概要

CTL 機能を利用するには、PLS (Portable Layout Services) ライブラリおよび適切な言語エンジンを用意する必要があります。 CTL は言語エンジンとのインタフェースとして PLS を使い、レンダリングを実行する前に言語エンジンを使ってテキストを変換します。 CTL をサポートするアプリケーションは、CTL のマニュアルに指定されているリソースをあらかじめインクルードする必要があります。

XomCTL でサポートされる、言語の複雑な整形および再配置機能について、以下に具体的に示します。これらの機能は、ロケールごとに異なる PLS モジュールの行う変換を通じて提供されます。

CTL アーキテクチャの概要

図 6–1 に CTL アーキテクチャの構成を示します。表の上に位置する Dt アプリケーションは Motif CTL 機能を用いてテキストのレンダリングを行います。これを受けて、Motif はロケールに固有の言語エンジンと PLS 経由でインタフェースし、位置の変更、数値の整形などの操作を行います。

目的のロケールに固有のエンジンを追加すれば、CTL アーキテクチャに新しい言語をサポートさせることができます。つまり、Motif や Dt アプリケーションを変更することなくタイ語やベトナム語がサポートされます。

図 6–1 CTL アーキテクチャ

Graphic

X ベースのアプリケーションに対する CTL サポート

X ベースの端末エミュレータなど、純粋な X Windows アプリケーションは、XomCTL (X Library Output Module における Complex Text Layout サポート) を通して CTL サポートを使用することができます。XomCTL では、X11 のダムフォントサポートを始め、Open Source XI18N 実装のすべての機能を使用できます。

新しい XOC リソース

Solaris 9 環境では、次の XOC リソースが提供されます。

XNText

CTL 操作を行うためのテキストバッファを設定します。

XNTextLayoutNumGlyphs

テキストバッファにテキストのグリフがいくつあるかを知らせます。

XNTextLayoutModifier

Motif の XmNLayoutModifier と同じ

XNTextLayoutProperty

PLS Property (input-to-output および output-to-input) と同じ

XNTextLayoutMapInpToOut

PLS Property (input-to-output および output-to-input) と同じ

XNTextLayoutMapOutToInp

PLS Property (input-to-output および output-to-input) と同じ

これらのリソースの説明は、 X/Open または PLS Portable Layout Services の仕様に記載されています。

CTL 技術をサポートするための Motif の変更点

CTL 技術は、Motif の次の変更によってサポートされています。

XmNlayoutDirection

オブジェクトの配置を制御します。

XmStringDirection

文字列の文字を表示する方向を指定します。

XmRendition

新しい擬似リソースを XmRendition に追加します。

XmText および XmTextField

XmRendition に関連付けられたテキストのレイアウト動作に影響を及ぼします。

XmTextFieldGetLayoutModifier

レンディションレイアウトオブジェクトのレイアウト修飾子文字列を返します。

XmTextGetLayoutModifier

ウィジェットに関連付けられたレンディションの現在のレイアウトオブジェクト設定の値を返します。

XmTextFieldSetLayoutModifier

レンディションに関連付けられたレイアウトオブジェクトのレイアウト識別子値を設定します。

XmTextSetLayoutModifier

ウィジェットに関連付けられたレンディションのレイアウトオブジェクト設定を変更します。

XmStringDirectionCreate

合成文字列を作成します。

XmNlayoutDirection

XmNlayoutDirection リソース [XmNlayoutDirection の概要 (特に、XmStringDirectionXmNlayoutDirection の関係) については、 『Motif Programmer's Guide (Release 2.1)』のセクション 11.3 を参照してください。] は、オブジェクトレイアウトを制御します。このリソースは、LayoutObject の方向の値を次のように使用します。

レイアウト方向の決定

XmNlayoutDirection XmDEFAULT_DIRECTION として指定されている場合、ウィジェットのレイアウトの方向は作成時に支配的な擬似 XOC により設定されます。 動的テキスト (XmText および XmTextField) では、ウィジェットに使用されている XmRendition に関連付けられた擬似 XOC が支配的擬似 XOC になります。 静的テキスト (XmListXmLabelXmLabelG) のレイアウト方向は、方向の指定されている最初の合成文字列コンポーネントに基づいて設定されます。次の 2 通りのいずれかで指定します。

直接的に指定

コンポーネントの種類が XmSTRING_COMPONENT_LAYOUT_PUSH または XmSTRING_COMPONENT_DIRECTION の場合

間接的に指定

コンポーネントの種類が XmSTRING_COMPONENT_LOCALE_TEXT XmSTRING_COMPONENT_WIDECHAR_TEXT、または XmSTRING_COMPONENT_TEXT の場合。コンポーネントに関連付けられた XmRendition および LayoutObject から設定

XmNlayoutDirectionXmDEFAULT_DIRECTION として設定されていない場合、XmNlayoutModifier @ls orientation の値がレイアウト修飾子文字列に明示的に指定されていなければ、XmNlayoutDirection の値は XOC およびその LayoutObject に受け渡されます。

XmNlayoutDirectionXmNlayoutModifier @ls orientation の両方の値が明示的に指定されている場合、上記の動作の中間になります。ウィジェットオブジェクトのレイアウトは XmNlayoutDirection により制御され、レイアウトの変換は XmNlayoutModifier @ls orientation の値により制御されます。

詳細については、『CAE Specification: Portable Layout Services: Context-dependent and Directional Text』 (The Open Group: Feb 1997; ISBN 1-85912-142-X; document number C616) を参照してください。 このマニュアルでは、コンテキストに依存する双方向のテキスト変換を、既存の POSIX ロケールモデルに対する論理拡張として処理するときに使用する、移植可能な機能について説明しています。複合テキスト言語 (Complex-text languages) をサポートしたいシステムプログラマまたはアプリケーションプログラマを対象としています。

XmStringDirection

XmStringDirection は、文字列に含まれる各文字の表示方向を指定するデータ形式です。

XmNlayoutDirection リソースは、文字列の方向を指定するコンポーネントを持たないすべての複合文字列 (XmString) に対してデフォルトのレンダリング方向を設定します。したがって、 XmNlayoutDirection リソースに対して適切な値を設定するだけで、レイアウト方向を設定できます。複合文字列の各コンポーネントの方向を指定する必要はありません。アプリケーションにおいて XmString がレンダリングされる場合、その文字列が方向 (XmStringDirection) を明示して作成されたかどうかが確認されます。 方向コンポーネントが存在しなければ、アプリケーションは XmNlayoutDirection リソースの値から現在のウィジェットを確かめ、その値を XmString のデフォルトのレンダリング方向として使用します。

XmRendition

CTL により、以下に示す新しい擬似リソースが XmRendition に追加されました。

表 6–1 XmRendition の新しいリソース

名前 

クラス/タイプ 

アクセス 

デフォルト値 

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 引数を指定します。このリソースは、この XmRendition に関連付けられた XOC に関連付けられた Layout Object の作成に使用されます。この文字列の構文およびセマンティクスについては、レイアウトサービス m_create_layout() の仕様を参照してください。Layout Modifier Orientation の出力値と XmNlayoutDirection ウィジェットリソースの相互作用については、上述の XmNfontType の説明を参照してください。

XmNlayoutModifier

この XmRendition の XOC とともに使用されるレイアウトオブジェクトに受け渡されるレイアウト値を指定します 。この文字列の構文およびセマンティクスについては、『CAE Specification』を参照してください。

XmRendition{Retrieve,Update} を用いてこのリソースを設定すると、文字列はこのレンディションに関連付けられた XOC に関連付けられたレイアウトオブジェクトに受け渡されます。レイアウトサービスは以上の手続きにより動的に構成されます。 OrientationContextTypeOfTextTextShaping、または 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 の 標準の Text および TextField では、論理的順序と物理的順序は区別されません。「次 (next)」および「前方 (forward)」は「右へ」を意味し、「前 (previous)」および「後方 (backward)」は「左へ」を意味します。 一方、CSText ではこれらは区別されており、物理名だけを用いる一連の動作が新たに定義されています。これらには、left-character()、たとえば、delete-right-word() などがあります。これらの処理ルーチンはすべてウィジェットの XmNlayoutDirection に依存するように定義されていて、適切な「次の - (next -)」または「前の - (previous -)」の動作が呼び出されます。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

このウィジェットに対して使用される XmRendition のレンディションタグを指定します。XmRenditionXmNrenderTable リソースに含まれます。

XmNalignment

ウィジェット内で使用されるテキストの揃え方を指定します。XmALIGNMENT_END XmALIGNMENT_CENTER だけがサポートされています。

XmNeditPolicy

ウィジェットに対して使用される編集の基準を XmEDIT_LOGICAL または XmEDIT_VISUAL として指定します。 XmEDIT_VISUAL を指定すると、選択、カーソル移動、および削除は視覚的に行われます。 このリソースを設定すると、同時に標準のキーボード操作の変換規則および削除イベントも、新しい「視覚的」な動作リストまたは既存の論理動作に変更されます。

文字の向き決定動作ルーチン

forward-cell()backward-cell() は、指定された方向にある文字の向きの問い合わせを行います。たとえば、方向が左から右ならば、対応する形式として next-/forward- または previous-/ backward- が呼び出されます。

文字の向き決定の追加動作

Layout Services 変換の OutToInp および Property バッファ (入れ子のレベル用) を使用して、文字の向きを決定します。 したがって、ウィジェットの動作は各ロケール固有の変換に依存します。OutToInpProperty バッファの情報が正しくないと、ウィジェットが予想外の動作を行うことがあります。特に、Property バッファの情報は大きく影響します。ロケール固有のモジュールがこの仕様の適用範囲から外れている場合、同じテキスト、アプリケーション、リソース値、および LayoutObject 構成に対して行われる双方向の編集動作が、プラットフォームによって異なる場合があります。

ビジュアルモードの動作はセルベースの動作を表示します。論理モードの動作は論理的な文字ベースの動作を生じます。たとえば、delete-right-character() 操作では、ディスプレイセルに対応した入力バッファの文字が削除されます。つまり、LayoutObject 変換の「プロパティ」バイトの「新しいセルのインジケータ」が 1 に設定されている入力バッファの文字 1 個、および「新しいセルのインジケータ」 [Property バッファの詳細については、『CAE Specification 』の m_transform_layout() の仕様を参照してください。] が 0 である後続のすべての文字が消去されます。

同様に、backward-character() では入力バッファ内で挿入点が 1 つ前に移動します。これに伴い、カーソルは出力バッファ内で関連付けられた文字に対応する表示上の位置に再描画されます。これは、複合表示セル上を移動するにはキーストロークを繰り返す必要があることを意味します。つまり、「新しいセルのインジケータ」が 0 の入力バッファ文字 (区別的発音符または合字) を横切って挿入点が移動するため、カーソルの表示位置は実際には変化しません。

このことは、削除動作が論理/入力バッファ側から実行されるか、物理的/出力側の表示セルレベルから実行されることを意味します。入力バッファと出力バッファの間には 1 対 1 の対応関係が存在しないため、綿密な意味での 1 文字単位の削除モードは存在しません。たとえば、1 つの物理文字が論理文字の一部分だけを表しているような場合が考えられます。

XmText 動作ルーチン

XmText の動作ルーチンを以下に示します。

left-character(extend)

XmNeditPolicyXmEDIT_LOGICAL で、引数なしで呼び出された場合、挿入カーソルは 1 論理文字分だけ前に移動します。挿入カーソルが行の先頭にある場合、1 つ前の行があればその行の最後の論理文字に移動します。1 つ前の行が存在しない場合には、カーソル位置は変化しません。

XmNeditPolicyXmEDIT_VISUAL ならば、カーソルは 1 つ左に移動します。挿入カーソルが行の先頭にある場合、1 つ前の行があればその行の最後の論理文字に移動します。

extend 引数を指定して left-character() が呼び出されると、現在の選択範囲を延長させながら、引数なしの場合と同じように挿入カーソルを移動します。

left-character() 動作は、reason の値として XmCR_MOVING_INSERT_CURSOR を用いて XmNmotionVerifyCallback プロシージャを呼び出します。extend 引数を指定して呼び出された場合、XmNgainPrimaryCallback プロシージャが呼び出されることがあります。詳細については、『Motif Programmer's Reference』のコールバックに関する説明を参照してください。

right-character(extend)

XmNeditPolicyXmEDIT_LOGICAL で、引数なしで呼び出された場合、挿入カーソルを 1 論理文字分だけ次に移動します。挿入カーソルが行の論理的な最後尾にある場合、次の行があればその行の論理的な先頭に挿入カーソルを移動します。

XmNeditPolicyXmEDIT_VISUAL ならば、カーソルは 1 つ右に移動します。挿入カーソルが行末にある場合、次の行があればその行の先頭に移動します。

extend 引数を指定して 呼び出された場合、現在の選択範囲を延長させながら、引数なしの場合と同じように挿入カーソルを移動します。

right-character() 動作は、reason の値として XmCR_MOVING_INSERT_CURSOR を用いて XmNmotionVerifyCallback プロシージャを呼び出します。extend 引数を指定して呼び出される場合、XmNgainPrimaryCallback プロシージャが呼び出される場合があります。詳細については、『Motif Programmer's Reference』のコールバックに関する説明を参照してください。

right-word(extend)

XmNeditPolicyXmEDIT_LOGICAL で、引数なしで呼び出された場合、挿入カーソルは次の論理ワードの開始位置に移動します。次の論理ワードが存在しない場合には、現在のワードの論理的な最後尾に挿入カーソルを移動します。挿入カーソルが行の論理的な最後尾にあるか、行の論理的な最後のワード内にある場合、挿入カーソルは次の行の論理的な先頭ワードに移動します。次の行が存在しない場合、挿入カーソルは現在のワードの論理的な最後尾に移動します。

XmNeditPolicyXmEDIT_VISUAL で、right-word() が引数なしで呼び出された場合、右側または行末以降の最初の白い空白文字の後の、白以外の最初の空白文字に挿入カーソルを移動します。

extend 引数を指定して 呼び出された場合、現在の選択範囲を延長させながら、引数なしの場合と同じように挿入カーソルを移動します。

left-character() 動作は、reason の値として XmCR_MOVING_INSERT_CURSOR を用いて XmNmotionVerifyCallback プロシージャを呼び出します。extend 引数を指定して呼び出される場合、XmNgainPrimaryCallback プロシージャが呼び出される場合があります。詳細については、『Motif Programmer's Reference』のコールバックに関する説明を参照してください。

delete-left-character()

XmNeditPolicyXmEDIT_LOGICAL ならば、delete-previous-char() と同じです。XmNeditPolicyXmEDIT_VISUAL ならば、次のようになります。すなわち、通常モードで範囲が選択されている場合は、選択された部分が削除されます。範囲が選択されていない場合は、挿入カーソルの左側の 1 文字が削除されます。 追加モードで、選択されている範囲がある場合は、カーソルは選択範囲から切り離されず、XmNpendingDelete が True に設定され、選択された部分が削除されます。範囲が選択されていない場合は、挿入カーソルの左側の 1 文字が削除されます。 結果が選択内容に影響を与える場合があります。

delete-left-character() 動作は、reason の値として XmCR_MODIFYING_TEXT_VALUE を用いて XmNmodifyVerifyCallback プロシージャを呼び出します。また、 reason の値として XmCR_VALUE_CHANGED を用いて XmNvalueChangedCallback プロシージャを呼び出します。

delete-right-character()

XmNeditPolicyXmEDIT_VISUAL ならば、delete-next-character() と同じです。XmNeditPolicyXmEDIT_VISUAL ならば、次のようになります。すなわち、通常モードで範囲が選択されている場合は、選択された部分が削除されます。範囲が選択されていない場合は、挿入カーソルの右側の 1 文字が削除されます。 追加モードで、選択されている範囲がある場合は、カーソルは選択範囲から切り離されず、XmNpendingDelete が True に設定され、選択された部分が削除されます。範囲が選択されていない場合は、挿入カーソルの右側の 1 文字が削除されます。 結果が選択内容に影響を与える場合があります。

delete-right-character() 動作は、reason の値として XmCR_MODIFYING_TEXT_VALUE を用いて XmNmodifyVerify-Callback プロシージャを呼び出します。また、reason の値として XmCR_VALUE_CHANGED を用いて XmNvalue-ChangedCallback プロシージャを呼び出します。

文字合成、合字、区別的発音符などをサポートするため、セルベースのルーチンが提供されています。 つまり、1 個のプレゼンテーションセルを占有する 1 個のグリフを用いて、複数の文字を表すことができます。

XmText セルの動作ルーチンを以下に示します。

backward-cell(extend)

1 セル分、挿入カーソルを前に移動します。XmNeditPolicy XmEDIT_LOGICAL ならば、現在のセルよりも論理的に 1 つ前のセルの先頭に挿入カーソルが移動します。1 つ前のセルが存在しない場合には、挿入カーソルは現在のセルの先頭に移動します。

XmNeditPolicyXmEDIT_VISUAL ならば、カーソルはその左側のセルの先頭に移動します。prev-cell() 動作は、reason の値として XmCR_MOVING_INSERT_CURSOR を用いて XmNmotionVerifyCallback プロシージャを呼び出します。また、extend 引数を指定して呼び出された場合、 XmNgainPrimaryCallback プロシージャへの呼び出しが発生する場合があります。詳細については、『Motif Programmer's Reference』のコールバックに関する説明を参照してください。

forward-cell(extend)

論理的な次のセルの始点に挿入カーソルを移動します。1 つ前のセルが存在しない場合には、現在のセルの最後尾にカーソルを移動します。 XmNeditPolicyXmEDIT_LOGICAL ならば、次のセルにカーソルを移動します。

XmNeditPolicyXmEDIT_VISUAL ならば、カーソルはその右側のセルの先頭に移動します。右側にセルが存在しない場合、カーソルは現在のセルの最後尾に移動します。forward-cell() 動作は、reason の値として XmCR_MOVING_INSERT_CURSOR を用いて XmNmotionVerifyCallback プロシージャを呼び出します。また、extend 引数を指定して呼び出された場合、 XmNgainPrimaryCallback プロシージャへの呼び出しが発生する場合があります。詳細については、『Motif Programmer's Reference』のコールバックに関する説明を参照してください。

XmTextFieldGetLayoutModifier

XmTextFieldGetLayoutModifier() はレイアウト修飾子の文字列を返します。返された文字列はレンディションに用いられるレイアウトオブジェクトの状態を示します。

XmTextFieldGetLayoutModifier() の構文は次のとおりです。

#include <Xm/TextF.h> String XmTextFieldGetLayoutModifier(Widget widget)

XmTextFieldGetLayoutModifier() は、ウィジェットに関連付けられたレンディションに関連して、現在のレイアウトオブジェクトに設定されている値を読み込みます。レイアウトオブジェクト修飾子の値が簡易関数を用いて変更された場合、XmTextFieldGetLayoutModifier 関数は、変更された値だけでなく、レイアウトオブジェクトに関するすべての状態を返します。

XmTextFieldGetLayoutModifier() はレイアウトオブジェクト修飾子の値を文字列として返します。

XmTextGetLayoutModifier

XmTextGetLayoutModifier() はレイアウト修飾子の文字列を返します。返された文字列はレンディションに用いられるレイアウトオブジェクトの状態を示します。

XmTextGetLayoutModifier() の構文は次のとおりです。

#include <Xm/Text.h>String XmTextGetLayoutModifier(Widget widget)

XmTextGetLayoutModifier は、ウィジェットに関連付けられたレンディションに関連して、現在のレイアウトオブジェクトに設定されている値を読み込みます。レイアウトオブジェクト修飾子の値が簡易関数を用いて変更された場合、XmTextGetLayoutModifier 関数は、変更された値だけでなく、レイアウトオブジェクトに関するすべての状態を返します。

XmTextGetLayoutModifier はレイアウトオブジェクト修飾子の値を文字列として返します。

XmTextFieldSetLayoutModifier

XmTextFieldSetLayoutModifier() 関数を設定することにより、レイアウト修飾子の値を設定して、レンディションに用いられるレイアウトオブジェクトの状態を変更することができます。

XmTextFieldSetLayoutModifier() の構文は次のとおりです。

#include <Xm/TextF.h>void XmTextFieldSetLayoutModifier(Widget widget ,string layout_modifier)

XmTextFieldSetLayoutModifier、ウィジェットに関連付けされたレンディションに関連して、レイアウトオブジェクトの設定値を変更します。レイイアウトオブジェクトの修飾子の値が簡易関数を用いて変更された場合、入力パラメータに指定された属性だけが変更されます。その他の属性は影響を受けません。

XmTextSetLayoutModifier

XmTextSetLayoutModifier() 関数を設定することにより、レイアウト修飾子の値を設定して、レンディションに用いられるレイアウトオブジェクトの状態を変更することができます。

XmTextSetLayoutModifier() の構文は次のとおりです。

#include <Xm/Text.h>void XmTextSetLayoutModifier(Widget widget ,string layout_modifier)

XmTextSetLayoutModifier は、ウィジェットに関連付けされたレンディションに関連して、レイアウトオブジェクトの設定値を変更します。レイアウトオブジェクトの修飾子の値が簡易関数を用いて変更された場合、入力パラメータに指定された属性だけが変更されます。その他の属性は影響を受けません。

XmStringDirectionCreate

XmStringDirectionCreate は、複合文字列を作成します。

XmTextSetLayoutModifier() の構文は次のとおりです。

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

XmStringDirectionCreate は1 個のコンポーネントを持つ複合文字列を、方向を指定して作成します。文字列の方向を指定するコンポーネントを持たない複合文字列 (XmString) については、 XmNlayoutDirection リソースによりデフォルトのレンダリング方向が設定されています。つまり、XmNlayoutDirection リソースに適切な値を設定するだけで、レイアウト方向を設定することができます。特定の方向コンポーネントを持つ複合文字列を作成する必要はありません。 アプリケーションにおいて XmString をレンダリングする場合、目的の文字列が (XmStringDirection) に方向を明示的に指定して作成されているかどうかを確認する必要があります。方向コンポーネントを持たない場合、アプリケーションは現在のウィジェットに対する XmNlayoutDirection リソースの値を確認して、その値を XmString のデフォルトのレンダリング方向として使用する必要があります。

UIL 引数

次の表に、UIL の引数を示します。

表 6–3 UIL
 UIL 引数の名前 引数の型

XmNlayoutAttrObject

String 

XmNlayoutModifier

String 

XmNrenditionTag

String 

XmNalignment

Integer 

XmNeditPolicy

Integer 

CTL アプリケーションの開発

この節では、CTL アプリケーションの開発方法について説明します。

レイアウトの方向

複合文字列の方向は、左から右に記述される言語 (英語、スペイン語、フランス語、ドイツ語など) の場合と同様に、右から左に記述される言語 (ヘブライ語、アラビア語など) の場合にも利用可能なデータ構造で保管されます。 Motif アプリケーションでは、VendorShell または MenuShell から XmNlayoutDirection リソースを使用してレイアウト方向を設定できます。また、マネージャおよびプリミティブウィジェット (および Gadgets) も XmNlayoutDirection リソースを持ちます。デフォルト値は、同じリソースを持つもっとも近い先祖から継承されます。

XmText ウィジェットに関しては、垂直方向も指定する必要があります。layoutDirectionXmRIGHT_TO_LEFT を設定すると、文字列の方向は右から左に設定されますが、カーソルは真下に移動します。垂直方向が重要で、上から下を希望する場合には、XmRIGHT_TO_LEFT_TOP_TO_BOTTOM を指定します。これにより、コンポーネントは希望通りまず右から左に、続いて上から下へレイアウトされます。

さらに、XmText および TextFieldウィジェットの動作は、XmRenditionXmNalignment および XmNlayoutModifier リソースにも依存します。 これらのリソースおよび XmNlayoutDirection は、Text ウィジェットのレイアウト動作を制御します。このことを図 6–2 で説明します。

図で使用する入力文字列は次の通りです。

Graphic

この図の左下のカラムに、XmNlayoutModifier の文字列 @ls orientation= に設定される値を示します。

図 6–2 レイアウト方向

Graphic

図に示すとおり、XmNAlignment はレイアウト方向に関連してテキストを右フラッシュするか左フラッシュするかを指定します。 XmNlayoutModifier はテキストをセグメントに分割して、向きの値に従って左から右、または右から左に並べ直します。たとえば、XmNlayoutDirectionXmRIGHT_TO_LEFT で、XmNAlignment の値が XmALIGNMENT_BEGINNING ならば、文字列は右フラッシュされます。

レンディションの作成

以下に示すプログラム例では、「ArabicShaped」というタグを持つ Rendition を使用して、XmNlabelString のタイプが XmCHARSET_TEXT XmLabel が作成されます。Rendition の作成には、「ar」(アラビア語ロケールのロケール名に対応) の XmNlayoutAttrObject が使用されます。また、その出力バッファには Numerals の値として NUMERALS_CONTEXTUALを、ShapeCharset の値として「 unicode-3.0」をそれぞれ指定するレイアウト修飾子文字列が使用されています。

ロケール固有のレイアウトモジュールにより、物理文字の出力バッファ内の入力テキストは 16 ビットUnicode 3.0 コードセットを使用して変換されます。レイアウトロケールが明示的に指定されているため、ランタイムのロケール設定とは関係なく、このテキストは適切にレンダリングされます。下の例では入力テキストは ISO8859–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);

レンディションの編集

以下に示すプログラム例では、TextField ウィジェットと RenderTable が 1 個の Rendition により作成されます。擬似リソース XmNlayoutAttrObject および 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 リソースに適した文字列を指定します。

この行により、指定に従って 1 つまたは複数のレンディションを含む最初のレンダーテーブルが作成されます。レンディションは指定されたタグに添付されます。

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

以下の例では、XmRendition に関連付けられた CTL リソースのうち、リソースファイルを使用して設定できるものを紹介します。レイアウトオブジェクトを有効にするには、 fontTypeFONT_IS_XOC に設定されている必要があります。@ls を使って指定された layoutModifier はレンディションオブジェクトによりレイアウトオブジェクトに受け渡されます。

layoutModifier を使ってレイアウトオブジェクト上に設定可能なリソースの完全な一覧については、『CAE Specification: Portable Layout Services: Context-dependent and Directional Text』(The Open Group: Feb 1997; ISBN 1-85912-142-X; document number C616) を参照してください。

アプリケーションにおけるレンダーテーブルの作成

レンダーテーブルを作成するには、テーブルを構成するレンディションがアプリケーションプログラムにより少なくとも 1 個は作成されている必要があります。XmRenderTableAddRenditions() 関数は新しいレンディションをレンダーテーブルに追加します。新しいレンダーテーブルを作成するには、既存のレンダーテーブル名の代わりに NULL を引数に指定して XmRenderTableAddRenditions() 関数を使用します。

以下に示すプログラム例では、XmNfontTypeXmFONT_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*(文字 0 の幅) によりタブの幅が計算されます。

タブは、表示される複合文字列の左マージンからの距離として測定されます。この距離は、レイアウト方向が右から左の場合は、右マージンから測定されます。タブにより挿入される空白文字は、レイアウト方向の指定 (XmNlayoutDirection ) に従ってテキストの右側または左側に挿入されます。どちら側に挿入されるかはテキストの方向 (たとえばアラビア語の場合は右から左、英語の場合は左から右) には依存しません

タブに続くテキストの位置は常にタブストップの位置に揃えられます。タブストップはウィジェットの始点から計算されます。この始点の位置は XmNlayoutDirection に依存します。タブの動作、およびテキストの方向性や XmNlayoutDirection との関連性について、次の図に示します。

この図で用いた入力は abc\tdef\tgh です。

図 6–3 タブ動作

Graphic

マウスによる選択

プライマリーセレクションにはマウスの左ボタンを使用します。このボタンを押すと現在選択されている内容が選択解除され、ボタンが押された時点におけるカーソル位置に挿入カーソルとアンカーが移動します。左ボタンを押しながらマウスをドラッグすると、アンカーの位置からポインタの位置までの間のテキストがすべて選択され、範囲外にあるすべてのテキストが選択解除されます。

選択されたテキストはリソース XmNeditPolicy に依存します。このリソースは、 XmEDIT_LOGICAL または XmEDIT_VISUAL に設定できます。XmNeditPolicyXmEDIT_LOGICAL に設定され、選択されたテキストが双方向ならば、選択されたテキストは個別のセグメントの集合体として表示されます。したがって、視覚的になめらかな表示にはなりません。 これは、論理バッファ内のテキストが表示内容と 1 対 1 で対応していないためです。

その結果、双方向テキストの論理文字の連続したバッファのレンダリング結果は、画面上でなめらかに連続した文字にはなりません。一方、XmNeditPolicy XmEDIT_VISUAL に設定されると、表示上、選択されたテキストはなめらかになりますが、論理バッファ内では個別のセグメントとして保存されている可能性があります。したがって、双方向テキストに対して一連の選択、削除、挿入操作を同じカーソル位置で実行しても、結果が同じ文字列にならない場合があります。

キーボードによる選択

マウスで実行可能な選択に関連した操作は、キーボードショートカットを使用して実行することもできます。テキストを選択するには Shift と矢印キーを組み合わせます。

選択されたテキストはリソース XmNeditPolicy に依存します。このリソースは XmEDIT_LOGICAL または XmEDIT_VISUAL に設定できます。XmNeditPolicy XmEDIT_LOGICAL に設定され、選択されたテキストが双方向ならば、選択されたテキストは視覚的になめらかな表示にはなりません。これは、論理バッファ内のテキストが表示内容と 1 対 1 で対応していないためです。その結果、双方向テキストの論理文字の連続したバッファのレンダリング結果は、画面上でなめらかに連続した文字にはなりません。

一方、XmNeditPolicyXmEDIT_VISUAL に設定されると、表示上、選択されたテキストはなめらかになりますが、論理バッファ内では個別のセグメントとして保存されている可能性があります。したがって、双方向テキストに対して一連の選択、削除、挿入操作を同じカーソル位置で実行しても、結果が同じ文字列にはなりません。

テキストのリソースおよびジオメトリ

ジオメトリに関連するテキストリソースは、次のとおりです。

移植に関する注意事項

CTL (Complex Text Layout) 対応の機能が組み込まれた新しい Motif ライブラリは /usr/dt/lib/libXm.so.4 に保管されています。libXm.so.3 をアプリケーションのリンク先に指定した場合、CTL は利用できません。アプリケーションのリンク先ライブラリを表示するには、ldd app_name と入力します。既存のアプリケーションを移植して CTL に対応させるには、以下の手順に従います。

  1. Makefile -DSUN_CTL を追加します。このフラグは重要で、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\