共通デスクトップ環境 プログラマーズ・ガイド (国際化対応編)

ローカライズされたテキストの入力

次に、国際化対応テキストの入力に使用する Xlib とデスクトップの機構について説明します。Motif の Text[Field] ウィジェットを使用している場合、またはテキスト入力に XmIm API を使用している場合は、この節でバックグラウンド情報が提供されます。しかし、この節の説明はアプリケーションの設計やコードの実行には影響しません。文字入力が低レベルの Xlib 呼び出しでキーボードからどのように処理されるかに興味がない場合は、「ローカライズされたテキストのクライアント間通信規約」に進んでください。

Xlib 入力メソッドの概要

この節は、国際化対応テキスト入力に関して使用される用語と概念の定義、また Xlib が提供する機構の、想定されている使用方法の簡単な概要を提供します。

世界の多数の言語が、語を形成するために、記号 (文字) の小規模なセットから成るアルファベットを使用します。アルファベット言語でテキストをコンピュータに入力するために、ユーザは通常アルファベットに対応するキー記号の付いたキーボードを持っています。場合によっては、アルファベット言語のうち少数の文字がキーボードにないことがあります。ラテンアルファベットに基づく言語を話す多くのコンピュータ・ユーザは、英語ベースのキーボードしか持っていません。キーボード上に直接存在しない文字を入力するには、複数のキーを組み合わせて押す必要があります。そのような文字を入力するために、ヨーロッパの入力メソッド、構成入力メソッド、デッドキー入力メソッドなどで知られる多数のアルゴリズムが開発されました。

日本語は、音声記号のセットを持つ言語の一例です。各音声記号は特定の音を表します。日本語には音声記号のセットが 2 つあります (カタカナひらがな)。一般に、カタカナは外来語の表記に使用し、ひらがなは通常の日本語の表記に使用します。この 2 つのシステムはまとめて仮名と呼ばれます。ひらがなは 83 文字、カタカナは 86 文字あります。

韓国語にも、ハングルと呼ばれる音声記号のセットがあります。基礎となる 24 の音声記号 (子音 14、母音 10) は、それぞれが特定の音を表します。1 つの音節は 2 〜 3 の部分から成ります (最初の子音、母音、任意で最後の子音)。ハングルでは、音節をテキスト処理の基本単位として使用することが可能です。たとえば、削除操作は音声記号または音節単位に行うことができます。韓国語のコード・セットにはこのような音節が数千あります。ユーザは、入力したい語の音節を形成する音声記号を入力します。ディスプレイは各音声記号が入力されるにつれて変化するかもしれません。たとえば、ある音節の 2 番目の音声記号が入力されると、1 番目の音声記号の形とサイズが変わることがあります。同様に、3 番目の音声記号が入力されると、前の 2 つの音声記号の形とサイズが変わることがあります。

すべての言語がアルファベットか音声システムだけに頼っているわけではありません。日本語と韓国語を含む一部の言語は、表意文字による記述システムを採用しています。表意文字システムでは、記号の小規模なセットを使用してそれらの記号を組み替えて複数の語を作成するのではなく、それぞれの語が 1 つ (または複数) の一意の記号から成ります。そのような記号は非常に多く、中国語の表意文字システムである漢字では約 50,000 が識別されます。

コンピュータでの表意文字システムの使用には主に 2 つの考慮しなければならない点があります。第一に、日本、中国、韓国の標準コンピュータ文字セットには約 8,000 の文字があり、台湾の場合は 15,000 〜 30,000 の文字があり、そのような文字は、1 文字を表現するのに 2 バイト以上が必要だということです。第 2 に、指定された言語のすべての表意文字を網羅するキーボードを用意することは明らかに不可能であり、したがって、適正な数のキーを持つキーボードを使用できるような文字入力の機構が必要になるということです。通常、そのような入力メソッドは音声体系に基づきますが、文字のグラフィカル属性に基づく方法もあります。

日本では仮名と漢字の両方を使用します。韓国ではハングルと時々ハンジャを使用します。これから、日本、韓国、中国、台湾での表意文字の入力について考察します。

日本では、仮名か英文字のいずれかを入力し、漢字に変換するための範囲を (時には自動的に) 選択します。複数の漢字が同じ音声表現を持つ場合もあります。そのような場合は、文字列を入力すると文字のメニューが表示され、ユーザは適切な候補を選択しなければなりません。選択の必要がない場合やすでに希望する表現である場合は、入力メソッドはただちに置換を実行します。ラテン文字が仮名または漢字に変換されることをローマ字変換と呼びます。

韓国では、通常は韓国語のテキストをハングル形式だけにすることが可能ですが、ハンジャ起源の語はハングルでなくハンジャで記述することを選ぶ人々もいます。ハングルからハンジャへ変換するには、変換の範囲を選択し、そのあとユーザは日本語のところで説明したのと同じ基本的な方法を取ります。

日本と韓国には広く普及した音声学上の記述システムがあるため、それらの国々で表意文字をコンピュータに入力する方法はかなり標準化されています。キーボード・キーには英文字と音声記号が書いてあり、ユーザはその 2 つのセットを切り替えることができます。

中国語の場合は状況が異なります。当局が奨励するピンインと呼ばれる音声システムがありますが、中国語のテキスト入力メソッドには統一されたものがありません。中国語の音声学的な分解 (ピンインその他) を使用するベンダもあれば表意的な分解を使用するベンダもあり、さまざまな処理系とキーボード配列が存在します。知られている手法は約 16 種類ありますが、どれも明確な標準ではありません。

また実際には、繁体字 (伝統的な中国文字) と簡体字という 2 種類の表意文字セットが使用されています。数年前、中華人民共和国は一部の表意文字を簡素化して全体的に無駄を排除するキャンペーンに着手しました。この方針の下に、文字は 5 年ごとに簡素化されます。文字はすでに何回か改訂されており、その結果として規模が縮小して単純になったセットが簡体字を形成しています。

入力メソッドのアーキテクチャ

前の節に示したとおり、数多くの異なる入力メソッドが今日使用されており、それぞれは言語、文化、歴史によって変化します。多くの入力メソッドで共通する機能は、ユーザは複数のキーストロークを入力して 1 つの文字 (または文字のセット) を構成できるということです。キーストロークから文字を構成するプロセスをプリエディットといいます。プリエディットには、複雑なアルゴリズムと、実質的なリソースを含む大規模な辞書が必要です。

入力メソッドには、ユーザに候補を示したり、辞書を表示したりするために、実際のキーストロークをフィードバックする 1 つ以上の領域が必要なことがあります。次に、該当する入力メソッド領域を示します。

ステータス領域

物理的なキーボード上にある発光ダイオード (LED) の論理的な拡張部として使用されます。ユーザにとって重要な入力メソッドの初期状態を表示するためのウィンドウです。ステータス領域は、テキスト・データおよびビットマップまたは、それらの組み合わせから成ります。

プリエディット領域

クライアントがデータを処理する前に使用されている言語のための中間テキストを表示するために使用されます。

補助領域

ポップアップ・メニューと、入力メソッドに必要なダイアログ・ボックスのカスタマイズに使用されます。どの入力メソッドにも複数の補助領域が存在する可能性があります。補助領域は入力メソッドにより、クライアントに依存しないで管理されます。複数の補助領域は、入力メソッドによって管理される別々のダイアログだと見なされます。

プリエディットには、さまざまなユーザの対話形式があります。次に、Xlib がサポートするプリエディット形式を示します。

OnTheSpot

データは直接アプリケーション・ウィンドウに表示されます。アプリケーション・データは、プリエディット・データが挿入点に表示されるように移動されます。

OverTheSpot

データは挿入点上に置かれたプリエディット・ウィンドウに表示されます。

OffTheSpot

プリエディット・ウィンドウはアプリケーション・ウィンドウの内側に表示されますが、挿入点ではありません。しばしば、この型のウィンドウはアプリケーション・ウィンドウの底部に置かれます。

Root

プリエディット・ウィンドウは RootWindow の子です。

移植性の高いアプリケーションには世界中のすべての言語の入力メソッドが必要だとすると、多くのコンピューティング・リソースが必要になります。それを避けるために、Xlib の設計目標は、アプリケーションが別々のプロセスに位置する入力メソッドと通信できるようにすることです。そのようなプロセスを入力サーバといいます。アプリケーションが接続するサーバは、アプリケーション起動時の環境、ユーザの言語、実際に使用されるエンコーディングに依存します。入力メソッドとの接続はロケール依存であると言われます。同様にユーザ依存でもあります。たとえば、ある言語が指定されると、ユーザは入力メソッドのユーザ・インタフェースの形式をある程度選択できます (選択肢がある場合)。

入力サーバの使用は通信のオーバヘッドを暗に意味しますが、アプリケーションは再リンクなしでマイグレーションできます。入力メソッドは、入力サーバへ通信するトークンとして、またはローカルなライブラリとして実現できます。

クライアントが入力メソッドと通信するために使用するアブストラクトは、XIM のデータ型で表されるオペーク・データ構造体です。このデータ構造体は、指定されたディスプレイに入力メソッドを開く XOpenIM() 関数によって返されます。このデータ構造体の以降のオペレーションは、クライアントと入力メソッドの間のすべての通信をカプセル化します。X クライアントが、入力メソッドを使用するためにネットワーキング・ライブラリや自然言語パッケージを使用する必要はありません。

1 つの入力サーバは、1 つ以上のエンコーディング・スキーマをサポートし、1 つ以上の言語に使用することができます。しかし、1 つの入力メソッドから返された複数の文字列は、常に XIM オブジェクトに関連付けられた (単一の) ロケールでエンコードされています。

入力コンテキスト

Xlib は、テキスト入力のマルチスレッド状態を管理する機能を提供します。クライアントが複数のウィンドウを使用していて、各ウィンドウには複数のテキスト入力領域があり、ユーザはそれらをいつでも切り替えられるという可能性もあります。特定の入力スレッドの状態を表すアブストラクトを入力コンテキストといいます。入力コンテキストは Xlib では XIC で表されます。図 5-1 を参照してください。

図 5-1 入力メソッドと入力コンテキスト

Graphic

入力コンテキストは、クライアントと入力メソッドの間の状態、属性、通信のセマンティクスを保存するアブストラクトです。入力コンテキストは、入力メソッド、返される文字列のエンコーディングを指定するロケール、クライアント・ウィンドウ、内部状態の情報、さまざまな配置や表示の特徴の組み合わせです。入力コンテキストの概念は、グラフィック出力用にグラフィック・コンテキスト・アブストラクトが定義した入力にいくらか一致します。

1 つの入力コンテキストは、1 つの入力メソッドに属します。異なる入力コンテキストは、たぶん同じクライアント・ウィンドウで、同一の入力メソッドに関連付けることが可能です。XIC は、XCreateIC() 関数によって作成され、XIM 引き数を指定してそれが存在する間は入力コンテキストを入力メソッドに密接に関連付けます。入力メソッドが XCloseIM() 関数で閉じられる場合、密接に関連付けられていたどの入力コンテキストも再使用できません (入力メソッドを閉じる前に削除されることが望ましいです)。

複数のテキスト入力領域を持つクライアント・ウィンドウの例を考慮し、アプリケーションのプログラマは次の事項を選択できます。

アプリケーション設計者は、アプリケーションのニーズに応じて、入力コンテキストの範囲を単一か複数か選択できます。

キーボード入力

入力メソッドから文字を取得するには、クライアントはその入力メソッドから作成された入力コンテキストと共に XmbLookupString() 関数か XwcLookupString() 関数を呼び出さなければなりません。ロケールとディスプレイの両方とも、開かれたときに入力メソッドに割り当てられ、入力コンテキストはこのロケールとディスプレイを引き継ぎます。XmbLookupString() 関数または XwcLookupString() 関数によって返されるすべての文字列は、そのロケールでエンコードされます。

Xlib フォーカス管理

XmbLookupString() 関数または XwcLookupString() 関数が使用される各テキスト入力領域には、関連付けられた入力コンテキストがあります。

アプリケーションのフォーカスがテキスト入力領域に移動するとき、アプリケーションは、その領域に関連付けられた入力コンテキストに、入力コンテキストのフォーカスを設定しなければなりません。入力コンテキストのフォーカスは、XSetICFocus() 関数を適切な入力コンテキストと共に呼び出すことで設定されます。

また、アプリケーションのフォーカスがテキスト入力領域の外側へ移動するときは、アプリケーションは XUnsetICFocus() 関数を呼び出して、関連付けられた入力コンテキストのフォーカスを設定解除すべきです。最適化のために、XSetICFocus() 関数が 2 つの異なる入力コンテキストで続けて呼び出された場合、2 回目のフォーカス設定の時点で自動的に 1 回目のフォーカスが設定解除されます。


注 -

入力コンテキストの設定と設定解除を正しく行うためには、アプリケーション・レベルのフォーカスの変更を追跡する必要があります。そのようなフォーカスの変更は、必ずしも X サーバのフォーカスの変更に対応しません。


単一の入力コンテキストが複数のテキスト入力領域への入力に使用される場合は、フォーカス・ウィンドウが変更されるたびに、その入力コンテキストのフォーカス・ウィンドウを設定する必要があります。

Xlib ジオメトリ管理

ほとんどの入力メソッドのアーキテクチャにおいて (OnTheSpot は著しい例外ですが)、入力メソッドは自身のデータの表示を行います。より見やすい位置においておくために、入力メソッド領域をクライアント内に埋め込むことが望ましい場合が多くあります。このためには、クライアントが入力メソッドにスペースを割り当てる必要があるかもしれません。Xlib は、クライアントが入力メソッド領域のサイズと位置を提供できるようサポートします。ジオメトリ管理のためにサポートされている入力メソッド領域は、ステータス領域とプリエディット領域です。

入力メソッドウィンドウのジオメトリ管理の元となる基本概念は、クライアント (またはツールキット) と入力メソッドの間で責任を適切に分割することです。責任の分割は次のとおりです。

入力メソッドはクライアントにサイズを提案することはできますが、位置を提案することはできません。入力メソッドがサイズを決定することはなく、指定されたサイズを受け入れなければなりません。

クライアントは、入力メソッドのジオメトリ管理を提供する前に、ジオメトリ管理が必要かどうかを判別しなければなりません。入力メソッドは、XGetIMValues() 関数によって返された XIMStyles 値に XIMPreeditArea() 関数か XIMStatusArea() 関数を設定することにより、ジオメトリ管理の必要性を示します。クライアントは、入力メソッドへジオメトリ管理を提供することを決定するとき、XNInputStyle 値を XIC に設定することにより、その決定を示します。

クライアントが入力メソッドでジオメトリ管理を行うことを確立した後、クライアントはジオメトリを入力メソッドと交渉しなければなりません。ジオメトリは次の手順で交渉されます。

ジオメトリ管理を実行するクライアントは、別の IC 値を設定すると、入力メソッドが希望するジオメトリに影響が出るかもしれないことを知っておく必要があります。たとえば、XNFontSet 値と XNLineSpacing 値は、入力メソッドが希望するジオメトリを変更する可能性があります。クライアントは、必要に応じて入力メソッドのウィンドウのジオメトリを再度ネゴシエートする責任があります。

さらに、入力メソッドがジオメトリ変更を起動するための、ジオメトリ管理コールバックが提供されます。

イベント・フィルタリング

フィルタリング機構により、入力メソッドが、クライアントに透過的に X イベントを取り込めるようになっています。XmbLookupString() 関数または XwcLookupString() 関数を使用しているツールキット (またはクライアント) は、イベント処理機構のある時点で、入力メソッドに必要なイベントが確実に入力メソッドによってフィルタリングされるように、フィルタを呼び出すことになっています。フィルタがない場合、クライアントは、入力メソッドが正しく機能するために必要なイベントを受け取って破棄できます。そのようなイベントの例を次に示します。

クライアントは、XIC の XNFilterEvents 値を取得し、イベント・マスクを持つクライアント・ウィンドウのイベント・マスクに追加することを期待されます。このマスクは 0 である可能性があります。

コールバック

OnTheSpot 入力メソッドが実現される場合、クライアントだけがプリエディット・データを挿入または削除でき、場合により既存のテキストをスクロールできます。つまり、キーストロークのエコーは、入力メソッドのロジックと密接に結合され、クライアント自身によって達成されなければなりません。

キーストロークが入力されると、クライアントは XmbLookupString() 関数か XwcLookupString() 関数を呼び出します。この時点で、OnTheSpot の場合は、プリエディットでのキーストロークのエコーはまだ行われていません。入力文字を処理するクライアントのロジックに戻る前に、検索関数が、新しいキーストロークを挿入するためのエコーを行うロジックを呼び出さなければなりません。これまでに入力されたキーストロークが文字を形成する場合は、入力されたキーストロークは削除される必要があり、構成された文字が返されます。結果として、クライアント・コードによって呼び出されている間、入力メソッドのロジックは戻る前にクライアントにコールバックしなければなりません。クライアント・コード、つまりコールバック・ルーチンは、入力メソッドのロジックから呼び出されます。

入力メソッドのロジックがクライアントにコールバックしなければならない場合が数多くあります。その 1 つ 1 つの場合が、定義済みコールバック・アクションに関連付けられています。クライアントが、各入力コンテキスト別に、どのコールバックがどのアクションで呼び出されるかを指定することが可能です。

また、ステータス情報をフィードバックするためのコールバックと、入力メソッドへのジオメトリ要求を開始するコールバックも提供されます。

X サーバ・キーボード・プロトコル

この節では、サーバとキーボードのグループについて説明します。

keysym は、キーキャップ上の記号のエンコーディングです。サーバの keysym マッピングの目標は、物理的なキーボードの実際のキーキャップを反映することです。ユーザは、xmodmap コマンドを希望する新しいマッピングで実行することにより、キーボードを再定義することができます。

X Version 11 Release 4 (X11R4) では、サーバでのバイリンガル・キーボードの定義が可能です。その機能は次のとおりです。

keysym のリストは、各キー・コードに関連付けられています。対応するキーの記号のセットを説明します。

明示的 void 要素がリストで希望されているときには VoidSymbol 値が使用できます。

リストの最初の 4 つの要素は、2 つの keysym のグループに分かれます。グループ 1 には 1 番目と 2 番目の keysym が含まれ、グループ 2 には 3 番目と 4 番目の keysym が含まれます。各グループ内の 2 番目の要素が NoSymbol の場合は、そのグループは 2 番目の要素が 1 番目の要素と同じであるかのように処理されます。ただし、1 番目の要素が、小文字と大文字両方の形式が定義されたアルファベット keysym K である場合は例外です。そのような場合、グループは、1 番目の要素が小文字形式の K で 2 番目の要素が大文字形式の K であるかのように処理されます。

イベントから keysym を取得するための標準的な規則は、グループ 1 とグループ 2 の keysym しか使用しません。リストのその他の keysym の解釈はここでは指定されません。どのグループを使用するかはモディファイアの状態が決定します。グループ間の切り替えは、MODE SWITCH という名前の keysym でコントロールされ、その keysym をあるキー・コードに接続し、そのキー・コードを Mod1 〜 Mod5 のモディファイアのうちのいずれかに接続することで実行されます。このようなモディファイアを「グループモディファイア」と呼びます。どのキー・コードに対しても、グループ 1 はグループ・モディファイアがオフの時に使用され、グループ 2 はグループモディファイアがオンの時に使用されます。

グループ内で、使用する keysym もやはりモディファイアの状態により決定されます。1 番目の keysym は、Shift モディファイアと Lock モディファイアがオフの時に使用されます。2 番目の keysym は、Shift モディファイアがオンの時、Lock モディファイアがオンの時、2 番目の keysym が大文字のアルファベットの時、または Lock モディファイアがオンで ShiftLock と解釈される時に使用されます。そうでない場合は、Lock モディファイアがオンで CapsLock と解釈される時に、Shift モディファイアの状態は初めて keysym 選択のために適用されます。keysym が小文字のアルファベットの場合は、対応する大文字の keysym が代わりに使用されます。

ジオメトリはベンダ固有の方法で定義されるかもしれませんが、キー上の記号の空間的なジオメトリは、keysym リスト順には定義されません。サーバはキー・コードと keysym 間のマッピングを使用しません。むしろ、サーバはクライアントによる読み書きのためにだけ、マッピングを格納します。

Lock という名前の KeyMask モディファイアは、CapsLock キーか ShiftLock キーのいずれかにマップされますが、どちらにマップされるかは、アプリケーション固有の決定か、ユーザ固有の決定か、あるいはその両方に委ねられます。しかし、対応するキー・コードに関連付けられた keysym に応じて、ユーザがマッピングを決定することをお勧めします。