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

第 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 アーキテクチャ

この図については、前の本文中で説明しています。

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

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

XOC リソース

最新の Solaris 環境では、次の 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 の仕様に記載されています。

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

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

XmNlayoutDirection

オブジェクトの配置を制御する

XmStringDirection

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

XmRendition

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

XmText および XmTextField

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

XmTextFieldGetLayoutModifier

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

XmTextGetLayoutModifier

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

XmTextFieldSetLayoutModifier

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

XmTextSetLayoutModifier

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

XmStringDirectionCreate

合成文字列を作成する

XmNlayoutDirection リソース

XmNlayoutDirection リソース はオブジェクトレイアウトを制御します。このリソースは、LayoutObject の方向の値を次のように使用します。

XmNlayoutDirection の概要 (特に、XmStringDirectionXmNlayoutDirection の関係) については、 『Motif Programmer's Guide (Release 2.1)』の 11.3 節を参照してください。

レイアウト方向の決定

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

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_ENDXmALIGNMENT_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 個、および「新しいセルのインジケータ」が 0 である後続のすべての文字が消去されます。

Property バッファの詳細については、『CAE Specification 』の m_transform_layout() の仕様を参照してください。

同様に、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 引数を指定して 呼び出された場合、XmNeditPolicy は、現在の選択範囲を延長させながら、引数なしの場合と同じように挿入カーソルを移動します。

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 セル分、挿入カーソルを前に移動します。XmNeditPolicyXmEDIT_LOGICAL ならば、現在のセルよりも論理的に 1 つ前のセルの先頭に挿入カーソルが移動します。1 つ前のセルが存在しない場合には、挿入カーソルは現在のセルの先頭に移動します。

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

forward-cell(extend)

論理的な次のセルの始点に挿入カーソルを移動します。次のセルが存在しない場合には、現在のセルの最後尾にカーソルを移動します。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 \
widgetstring 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 個のコンポーネントを持つ複合文字列を、方向を指定して作成します。一方、XmNlayoutDirection リソースは、文字列の方向を指定するコンポーネントを持たないすべての複合文字列 (XmString) に対してデフォルトのレンダリング方向を設定します。したがって、XmNlayoutDirection リソースに対して適切な値を設定するだけで、レイアウト方向を設定できます。特定の方向コンポーネントを持つ複合文字列を作成する必要はありません。

アプリケーションにおいて XmString がレンダリングされる場合、その文字列が方向 (XmStringDirection) を明示して作成されたかどうかが確認されます。アプリケーションに方向コンポーネントが提供されない場合、アプリケーションは XmNlayoutDirection リソースの値から現在のウィジェットを確かめ、その値を XmString のデフォルトのレンダリング方向として使用します。

UIL 引数

次の表に、UIL 引数の名前と型を示します。

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

XmNlayoutAttrObject

文字列 

XmNlayoutModifier

文字列 

XmNrenditionTag

文字列 

XmNalignment

整数 

XmNeditPolicy

整数 

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

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

レイアウト方向の制御

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

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

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

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

この図は、英語およびアラビア語文字の双方向テキストのレイアウトを同一の行上に示しています。

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

図 6–2 レイアウト方向

図は、左から右へのテキストおよび右から左へのテキストに対する始めと終わりのそろえ方を示しています。

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


例 6–1 レンディションの作成

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

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


例 6–2 レンディションの編集

以下に示すプログラム例では、TextField ウィジェットとレンダーテーブルが 1 個の レンディション により作成されます。擬似リソース XmNlayoutAttrObject および XmNlayoutModifier は両方とも未指定の状態になっているため、デフォルト値 NULL が使用されます。このことはレンディションに関連付けされたレイアウトオブジェクトが存在する場合、それがデフォルトロケールのものであることを示しています。

サンプルプログラムが正しく機能するためには、使用するロケールのコードセットが ISO 8859-6 で、ロケール固有のレイアウトモードが IMPLICIT_BASIC アルゴリズムをサポートしている必要があります。コード例では、レンディションの LayoutObjectImplicitAlg 値がレンディションの XmNlayoutModifier 擬似リソース経由で変更されています。

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);

リソースファイルのレンダーテーブルの作成

適切に国際化されたアプリケーションではレンディションおよびレンダーテーブルを、リソースファイルに指定すべきです。レンダーテーブルがファイルとして指定される場合、プログラムの実行ファイルはロケールごとの特定の要求に依存しなくなるため、ロケールの要求に応じて簡単にカスタマイズを行うことができます。

レンダーテーブルをリソースファイルとして指定する場合、次の構文が用いられます。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) を参照してください。


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

レンダーテーブルを作成するには、テーブルを構成するレンディションがアプリケーションプログラムにより少なくとも 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 タブ動作

図は、左から右へのテキスおよび右から左へのテキストでのタブの表示を示しています。

マウスによる選択

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

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

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

キーボードによる選択

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

選択されたテキストはリソース XmNeditPolicy に依存します。このリソースは XmEDIT_LOGICAL または XmEDIT_VISUAL に設定できます。XmNeditPolicyXmEDIT_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\