入り口に戻る

原文はこちら。
翻訳にあたって、オープンソースグループ・ジャパンのMIT ライセンスの訳を参考にした。

## The Input Method Protocol(日本語訳)

#### (入力メソッド・プロトコル)

### X Consortium Standard

### Masahiko Narita

FUJITSU Limited.

### Hideki Hiura

SunSoft, Inc.

X Version 11, Release 7.7

Version 1.0

Copyright © 1993, 1994 FUJITSU LIMITED, Oracle and/or its affiliates

Permission to use, copy and distribute this documentation for any purpose and without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. Fujitsu and Sun Microsystems make no representation about the suitability for any purpose of the information in this document. This documentation is provided as is without express implied warranty.

(訳)

(本文書を使用、複写、および頒布することは、目的を問わず無償で許可する。但し、上記の著作権表示および本許諾表示を全ての複製に記載しなければならない。Fujitsu および Sun Microsystems は、本文書に含まれる情報のいかなる目的への適切性についても、何ら表明を行わない。本文書は現状のままで、明示または暗黙の保証もなく提供される。)(訳註：上記の英文の最後の文の「without express implied warranty.」は「without express or implied warranty.」として訳した。)

Copyright © 1993, 1994 X Consortium

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Except as contained in this notice, the name of the X Consortium shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the X Consortium.

X Window System is a trademark of The Open Group.

(訳)

(本ソフトウェアおよび関連する文書のファイル（以下「ソフトウェア」）の複製を取得した全ての人物に対し、以下の条件に従うことを前提に、ソフトウェアを無制限に扱うことを無償で許可する。これには、ソフトウェアの複製を使用、複製、改変、結合、公開、頒布、再許諾、および/または販売する権利、およびソフトウェアを提供する人物に同様の行為を許可する権利が含まれるが、これらに限定されない。)

(上記の著作権表示および本許諾表示を、ソフトウェアの全ての複製または実質的な部分に記載するものとする。)

(ソフトウェアは「現状有姿」で提供され、明示的であるか黙示的であるかを問わず、いかなる種類の保証も行われない。ここでいう保証には、商品性、特定目的への適合性、および権利の非侵害性に関する保証も含まれるが、これらに限定されるものではない。THE X CONSORTIUM は、契約、不法行為、またはその他の行為であるかを問わず、ソフトウェアまたはソフトウェアの使用もしくはその他に取り扱いに起因または関連して生じるいかなる請求、損害賠償、その他の責任について、一切の責任を負わない。)

(X Consortium の名称は、この表示に記載されている場合を除き、X Consortium の事前の書面による承認を得ずに、宣伝であろうとその他の形であろうと、ソフトウェアの販売を促進するもの、またはソフトウェアの使用その他の扱いを奨励するものに使用してはならない。)

(X Window System は The Open Group の商標である。)

本文書は、IM(Input Method)ライブラリと IM サーバとの間のプロトコルを定めている。このプロトコルは、国際化されたテキスト入力をやり取りするためのものである。またこのプロトコルは、特定の言語、特定の入力メソッドに依存せず、且つ IM ライブラリと IM サーバの間の通信に使われる伝送制御層(transport layer)の中の特定のものにも依存せず、client-server モデルを採用している。このプロトコルによって、ユーザは、stand-along な分散型環境においても、あらゆるアプリケーションで自分のお気に入りの入力メソッドを使えるようになる。(訳註：「stand-along」とは？複数のアプリケーション実行マシンが併存するという意味か？要確認)

## 序論

### 射程

X Window System バージョン 11 リリース 5 における国際化によって新たな共通 API が用意された。この API を使用することで、アプリケーションの開発者は、移植可能な国際化されたプログラムを作ったり、様々な言語(母語)の要求、様々な地域の慣習、様々な文字列符号化形式にプログラムを適合させたりすることができる(これを「ローカリゼーション」(特定地域化)という)。国際化の仕組みの１つとして、X11R5 では国際化されたテキスト入力のための関数インターフェイスを定義している。これが XIM (X Input Method、X 入力メソッド)である。

IM (Input Method、入力メソッド)の実装に client-server モデルを使うとすれば、クライアントとサーバの間には何らかのプロトコルが存在しなければならない。しかしながら、入力メソッド・ライブラリ(IM ライブラリ)と入力メソッドサーバ(IM サーバ)とを相互接続するのに用いるプロトコルについては、X11R5 には一切記述が無い(ちなみにアプリケーションは入力メソッド・ライブラリと繋がる)。そのため、アプリケーションの開発者は開発企業独自の入力メソッドに頼らざるを得ず、ユーザの入力メソッドの選択肢は限定され、さらには開発者が移植可能なアプリケーションを作るのも難しくなっていた。この文書では Input Method Protocol(入力メソッド・プロトコル)について説明する。このプロトコルは、 上記の問題の解決、及び入力メソッド(既存のもの及び将来のもの)の要件の記述を目的として、X11R6 に向けて開発されたものである。

Input Method Protocol(入力メソッド・プロトコル)は、IM ライブラリと IM サーバとの間の通信に使う伝送制御層(transport layer)から独立している。したがって、入力メソッド・プロトコルは、どのようなプロセス間通信機構(たとえば TCP/IP や X プロトコル)でもその基礎とすることができる。

加えて、本プロトコルは、将来の機能の拡張にも対応できる(たとえば入力モデルの型を変更するといった機能)。

### 背景

ある言語においては、テキスト入力は他の言語よりもとても簡単なものである。英語の場合、管理しやすい大きさの文字集合を用い、入力はキーボードの該当するキーを押すだけか、あるいは大文字や特別な文字を入力するために Shift キーと一緒に該当キーを押すだけである。

もっと大きな文字集合を持っていたり、アクセントのような修飾記号を持っている言語もある。そのような言語では、テキストを入力するために特別なキーの組み合わせを加える必要がある。こうした入力メソッドで必要になる可能性があるのは「デッド・キー」(dead-keys)や「Compose キー」(compose-keys、合成キー)である。デッド・キーや合成キーは、それらに続けてキーの諸々の組み合わせを打ち込むことで、諸々の文字を生成するものである。

表意文字を用いる言語のテキスト入力は、上記のものほど単純ではない。表意文字を用いた言語では、各文字は、単語を発音するための音声を表すのではなく、実際の対象そのものを表している。そして、この種の言語では文字の数が増え続ける可能性がある。日本語の場合、大抵のテキスト入力メソッドでは先ず表音文字(の集合に含まれる文字)を入力し、次いで入力メソッドが辞書を使って変換候補となる象形文字の相当物を探し出す(象形文字の候補が複数あることもある)。その後、入力メソッドは候補となる文字をユーザに提示し、ユーザがそこから選べるようにする。

日本語では、かな文字(表音記号)もしくはローマ字を打ち込み、それから漢字に変換する領域を選択する。複数の漢字が同一の音声表記を持つことがあり得るのだが、入力された文字列がそうだった場合、文字群(変換候補)のメニュー(menu)が表示されるので、ユーザは適当なものを１つ選ばなければならない。選択が不要な場合、あるいは変換の嗜好が既に確立されている場合、入力メソッドは直接置換を実行する。

そうした複雑な入力メソッドは次の３つのものを提供しなければならない。即ち、ステータス情報(Status Area、ステータス表示領域)、テキストを入力し編集する空間(Preedit Area、前編集領域、まえへんしゅうりょういき)、及びメニュー/選択肢の提示(Auxiliary Area、補助領域)の３つである。IM ライブラリと IM サーバとの間のやり取りを定めるプロトコルの大部分には、これらの IM 領域の操作が関わっている。この種の入力メソッドの大きさと複雑さのゆえに、また、言語やロケール毎に入力メソッドが大きく異なるがゆえに、入力メソッドは通常別個のプロセスとして実装される。そしてこのようなプロセスは、同一コンピュータ上または同一ネットワーク上の多数のクライアントに対してサービスを提供することができる。

### 入力メソッドのスタイル(対話型)

X11 の国際化機構には、次の４つの種類の入力メソッドが用意されている。

- on-the-spot: | クライアント・アプリケーションは、IM サーバの指図に従って、テキスト挿入位置に全ての前編集データを表示する。クライアントは、コールバック関数(前編集の間に入力メソッドが呼び出すもの)を登録する。
- off-the-spot: | クライアント・アプリケーションは、前編集データを表示するためのウィンドウ群を入力メソッドに提供し、入力メソッドはそこに前編集データを直接表示する。
- over-the-spot: | 入力メソッドは、自力でテキスト挿入位置にウィンドウを拵え、そこに(自力で)前編集データを表示する。
- root-window: | 入力メソッドは、全ての前編集データをスクリーン上の独立した領域(入力メソッド専用のウィンドウに含まれる領域)に表示する。

クライアント・アプリケーションは、IM サーバが対応していて利用可能である入力メソッド(の対話型)の中から(使用するものを)選ばなければならず、また、入力メソッドが必要とする表示領域とコールバックとを用意しなければならない。

## 構成(Architecture)

### 実装のモデル(Implementation Model)

X ウィンドウ・システム環境においては、入力メソッドの実装モデルとして、次の２つの典型的な構成モデル(architectural model)を使用することができる。

- クライアント/サーバ・モデル： | 独立したプロセス(即ち IM サーバ)が入力を処理し、前編集・変換・文字列確定を手引き(handle)する。アプリケーション内の IM ライブラリは、IM サーバのクライアントとなり、IM サーバから確定文字列を受け取るだけである。
- ライブラリ・モデル： | 全ての入力は、アプリケーション内部の IM ライブラリによって処理される。イベントの処理は IM ライブラリの内部で完結し、独立した IM サーバ・プロセスは必須でない。

複雑な前編集を必要とする言語(アジアの言語など)の場合、大抵はクライアント/サーバ型 IM モデルを利用して実装する。デッド・キーや合成キー(compose key)の処理しか必要としない他の言語(ヨーロッパの言語など)の場合、ライブラリ・モデルを利用して実装する。

この文書では、主にクライアント/サーバ型 IM モデルと、IM ライブラリ(クライアント)・IM サーバ間の通信に使用するプロトコルとについて論じる。

### IM の構造(Structure of IM)

クライアントが IM サーバに接続する場合あるいは接続を切断する場合、クライアントと IM サーバの間で接続を開く操作あるいは閉じる操作が行われる。

IM は、クライアントのロケールとロケール修飾子(locale modifier)を設定することによって、XOpenIM() の実行時に指定することができる。IM には作成時点のロケールが記憶されるため、XOpenIM() を(ロケールとロケール修飾子の設定を変更して)複数回呼び出すことで、複数の言語に対応することができる。

また、利用可能な IM の型(type)(訳註：XIMStyle、対話型)は XGetIMValues() を使って取得することができる。

クライアントは、通常、複数の(テキスト)入力欄を持つ。Xlib には「Input Context」(IC)(入力コンテクスト)と呼ばれる型が備わっており、これを使って個々の入力欄を管理することができる。IC は、XIM を指定して XCreateIC() を使用することで作成することができる。また IC は、XDestroyIC() を使って破棄することができる。

IC を使うと、各入力欄に対して、XIM が対応している IM の型(対話型)を指定することができる。そのため、各入力欄で異なる型の IM を扱うことができる。

最も重要な点は、IM サーバからクライアントへ送られる確定文字列のような情報が各 IC に基いてやり取りされるということである。

各 IC がそれぞれ１つの入力欄に対応しているので、フォーカスのある入力欄は XSetICFocus() を使って IM サーバに知らせるものとする。(フォーカスを変更するために XUnsetICFocus() も使用することができる。)

### イベント処理のモデル

既存の入力メソッドには、フロントエンド方式(FrontEnd method)に対応しているもの、バックエンド方式(BackEnd method)に対応しているもの、あるいは両方に対応しているものが存在する。本プロトコルでは、特にバックエンド方式を標準のメソッドとして扱っているが、フロントエンド方式もオプションの IM サーバ拡張として利用できるようになっている。

フロントエンド方式とバックエンド方式の違いは、イベントを IM サーバへ配送するやり方にある。(Fig. 1 参照)

#### バックエンド方式

バックエンド方式においては、クライアント・ウィンドウの入力イベントは常に先ず IM ライブラリに送られ、それから IM ライブラリが同イベントを IM サーバへと渡すことになる。イベントは配送された順番で続けて処理されるため、IM ライブラリと IM サーバの間の同期の問題は起こり得ない。

この方式を使う場合、IM ライブラリは、(「イベントの流れの制御(1)」で説明するイベント・フロー制御方式の必要に応じて) 全ての KeyPress イベントと KeyRelease イベントを IM サーバへ転送し、(「イベントの濾過」で述べる形で) IM サーバと同期をとる。

#### フロントエンド方式

フロントエンド方式においては、クライアント・ウィンドウの入力イベントは X サーバによって IM サーバと IM ライブラリの両方に直接配送される。したがって、こちらの方式の方が前編集の際の対話の効率が良くなる(とりわけ次の場合などにはそうである。即ち、IM サーバがユーザのワークステーション上でローカルに実行されており、クライアント・アプリケーションが比較的遅いネットワークの先にある別のワークステーションで実行されている場合などである)。

しかしながら、フロントエンド方式では、IM サーバが処理するキー・イベントと、クライアントが処理する他のイベントとの間で同期の問題が起こる可能性がある。そして、この種の同期の問題が起きると、キー・イベントが失われたり重複したりしてしまう可能性がある。それゆえ、バックエンド方式を主たる方式として規定し、フロントエンド方式は実行効率を追求するための拡張として利用できるようにしてある(詳しくは「周知の拡張」を参照)。

イベントの流れ

### イベントの流れの制御(1)

このプロトコルでは、IM ライブラリと IM サーバの間の通信のために、イベント・フロー方式を２つ規定している(Static 方式と Dynamic 方式である)。

「Static」イベント・フロー(静的イベント・フロー)では、入力イベントは常にクライアントから IM サーバへ送る必要がある。

一方、「Dynamic」イベント・フロー(動的イベント・フロー)では、処理(変換)する必要がある入力イベントだけをクライアントから IM サーバへ送ればよい。

例えば、ASCII 文字と漢字が混じった文字列を入力する場合、ASCII 文字は IM サーバで処理する必要が無いため、それらのキー・イベントを IM サーバへ送る必要は無い。これに対して、漢字を作るのに必要なキー・イベントは IM サーバへ送らなければならない。

それゆえ、動的イベント・フローを採用することで、X サーバとクライアントと IM サーバとの間のリクエストの数を大きく減らすことができ、また、コンテクストの切り替えの回数も減らすことができ、結果として実行効率が向上する。IM サーバは、動的イベント・フローにおけるイベントの流れを切り替えるために(訳註：切り替えるためのキーを登録するために)、`XIM_REGISTER_TRIGGERKEYS` メッセージを送信することができる。

この手続きのプロトコルは、「イベントの流れの制御(2)」で説明している。

## 標準予備接続の規約

IM サーバは、IM サーバの名簿が入ったプロパティ(スクリーン番号 0 のルート・ウィンドウにある「`XIM_SERVERS`」プロパティ)に対して、ATOM による名前を用いて自身の識別名(symbolic name)を登録するべきである。このプロパティには ATOM のリストを入れることが可能であり、各 ATOM は利用可能な IM サーバの１つ１つを表す。IM サーバの名前には POSIX Portable Filename Character Set の文字しか使用できない。ある IM サーバが動いているかを知るには、その(IM サーバの)アトム名のセレクションに所有者が存在するかどうかを確かめればよい。この IM サーバのアドレスを知るには、同セレクションをセレクション・ターゲット「`TRANSPORT`」に変換すればよい。これによって文字列形式のトランスポート・アドレスが返ってくる。この IM サーバが対応しているロケールを知るには、上記のセレクションをセレクション・ターゲット「`LOCALES`」に変換すればよい。これによって、対応しているロケール群の名前を纏めたものが(X/Open が定めた構文・形式で)返ってくる。

プロパティ「`XIM_SERVERS`」の中に複数の ATOM が発見された場合にどの IM サーバを用いるかを決める方法は、X モディファイア(修飾子)の「`im`」カテゴリによって IM サーバの名前が与えられていなければ、「最初に合ったものを採用する」方法(first fit)による。

`TRANSPORT` ターゲットへの変換によって、その伝送方式特有の形式を持つ名前(transport-specific name)をアドレス情報として取り出すことができる。伝送方式特有の名前のために複数の書式が予め登録されており、それらは「伝送方式一覧」に纏められている。伝送方式特有の名前(の形式)が追加され、新たに X Consortium に登録される可能性もある。

X 接続を欠く環境や X ウィンドウ・システムを使用しない IM サーバにおいては、IM サーバへの予備接続の規約(手続き)は X ウィンドウ・システムの外側に用意されるであろう(例えば、Name Service (名前解決サービス)を使用して)。

## プロトコル

以下で記述するプロトコルは、「(1)双方向にやり取りされ、且つ(2)同期を取る、もしくは非同期の(3)リクエストとリプライとエラー」から成るモデルを用いており、X ウィンドウ・システム・プロトコル本体の第２章で概説されているものと同じ構文規約を用いて規定されている。(参考文献[1])

### リクエスト・パケットの基礎部分の書式

この章では、クライアントと IM サーバとの間でやり取りすることができるリクエストについて説明する。

リクエスト・パケットの基礎部分であるヘッダの書式は次の通り。

              major-opcode:               CARD8
              minor-opcode:               CARD8
              length:                     CARD16

MAJOR-OPCODE (主たる命令コード)は、このパケットがどのコア・リクエスト(このプロトコルに基くリクエスト)を表すものなのか、あるいはどの拡張パッケージを表すものなのかを指定する。MAJOR-OPCODE (の値)がコア・リクエストの主命令コードに該当するものである場合、MINOR-OPCODE には８ビットのリクエスト特有データが入る(MINOR-OPCODE を使用しないリクエストであれば値 0 が入る)。MAJOR-OPCODE (の値)がコア・リクエストの主命令コードに該当しない場合、MAJOR-OPCODE と MINOR-OPCODE は `XIM_QUERY_EXTENSION` メッセージによって定まる(4.7 節「利用可能な拡張プロトコルの目録を要求する」を参照)。LENGTH フィールドは、ヘッダの後に続く要素の個数(４バイト単位)を表す。ヘッダの後ろに続くデータが存在しない場合、LENGTH フィールドの値は 0 となる。

### 各種のデータ型

X の IM サーバ・プロトコル本体においては、以下のデータ型を使用する。

    BITMASK16
         CARD16
    BITMASK32
         CARD32
    PADDING FORMAT
         N は何らかの式であり、Pad(N) は N を４の倍数に揃えるために加えるべきバイトの数である。
         (訳註：原文のHTML版では文末の「multiple of four.」が缺落。X11R6.3の配布版に同梱されていた xim.ms に基き修正。)

              Pad(N) = (4 - (N mod 4)) mod 4

    LPCE
      1          「Latin Portable Character Encoding」の符号化方式で表される
                 「X Portable Character Set」に含まれる文字１つ

    STRING
         2     n              次の「文字列」の長さ(単位はバイト)
         n     LISTofLPCE     文字列
         p                    unused, p=Pad(2+n)

    STR
         1     n              次の「名前」の長さ(単位はバイト)
         n     STRING8        名前

    XIMATTR
         2     CARD16         属性の ID (*1)
         2     CARD16         属性値の型 (*2)
         2     n              次の im-attribute の長さ
         n     STRING8        im-attribute
         p                    unused, p = Pad(2+n)

    im-attribute フィールドには、XNQueryInputStyle のような XIM の属性値が入る。

    XICATTR
         2     CARD16         属性の ID (*1)
         2     CARD16         属性値の型 (*2)
         2     n              次の ic-attribute の長さ
         n     STRING8        ic-attribute
         p                    unused, p = Pad(2+n)

(*1)
  XIMATTR と XICATTR は設定の段階で使用されるものである。一方、XIMATTRIBUTE と XICATTRIBUTE は、それぞれの属性 ID が IM サーバと IM ライブラリに認識された後に使用されるものである。

(*2)
  属性値の型は次のように定義されている。

値 | データ | 形式 |  |
#0 | Separator of NestedList | -----(*3) |  |
#1 | byte data | CARD8 |  |
#2 | word data | CARD16 |  |
#3 | long data | CARD32 |  |
#4 | char data | STRING8 |  |
#5 | Window | CARD32 |  |
#10 | XIMStyles | 2 | n | XIMStyle のリストの要素数
|  | 2 |  | unused
|  | n | CARD32 | XIMStyle list
#11 | XRectangle | 2 | INT16 | X
|  | 2 | INT16 | Y
|  | 2 | CARD16 | width
|  | 2 | CARD16 | height
#12 | XPoint | 2 | INT16 | X
|  | 2 | INT16 | Y
#13 | XFontSet | 2 | n | Base font name のリストの長さ
|  | n | STRING8 | Base font name list
|  | p |  | unused, p = Pad(2+n)
#15 | XIMHotKeyTriggers | 4 | n | XIMTRIGGERKEY のリストの要素数 (*4)
|  | n | XIMTRIGGERKEY | XIMHotkeyTrigger list
|  | n | XIMHOTKEYSTATE | HotKey の処理状態
#17 | XIMStringConversion | XIMSTRCONVTEXT |  |
#18 | XIMPreeditState | XIMPREEDITSTATE |  |
#19 | XIMResetState | XIMRESETSTATE |  |
#x7fff | NestedList | ----- |  |

(*3)
  NestedList の区切りを表す IC の値は次のように定義されている。

      #define   XNSeparatorofNestedList   "separatorofNestedList"

  XNSeparatorofNestedList の定義は X Consortium に登録されており、他の用途に使うことはできない。

(*4) LISTofFOO
  LISTofFOO という形式の型名は、FOO 型の要素の可算リストを表す。長さを表すフィールドの大きさ(size)は様々であり(FOO と同じ大きさでなければいけないわけではない)、場合によっては明示されない。

    XIMTRIGGERKEY
         4     CARD32       キーシンボル
         4     CARD32       修飾キー
         4     CARD32       修飾キーのマスク

    ENCODINGINFO
         2     n            次の encoding info の長さ
         n     STRING8      encoding info
         p                  unused, p=Pad(2+n)

    EXT
         1     CARD8        拡張の major-opcode
         1     CARD8        拡張の minor-opcode
         2     n            次の extension name の長さ
         n     STRING8      extension name
         p                  unused, p = Pad(n)

    XIMATTRIBUTE
         2     CARD16       属性の ID
         2     n            次の value の長さ
         n                  value
         p                  unused, p = Pad(n)

    XICATTRIBUTE
         2     CARD16       属性の ID
         2     n            次の value の長さ
         n                  value
         p                  unused, p = Pad(n)

    XIMSTRCONVTEXT
         2    CARD16                      XIMStringConversionFeedback
              #x0000001                   XIMStringConversionLeftEdge
              #x0000002                   XIMStringConversionRightEdge
              #x0000004                   XIMStringConversionTopEdge
              #x0000008                   XIMStringConversionBottomEdge
              #x0000010                   XIMStringConversionConcealed (訳註：Xlib.h に基き修正)
              #x0000020                   XIMStringConversionWrapped
         2     n                          次の retrieved string の長さ(単位はバイト)
         n     STRING8                    retrieved string
         p                                unused, p = Pad(n)
         2     m                          feedback array の長さ(単位はバイト)
         2                                unused
         m     LISTofXIMSTRCONVFEEDBACK   feedback array(*1)

(*1)
  このフィールドは将来のために予約されている。

    XIMFEEDBACK
         4    CARD32       XIMFeedback
              #x000001     XIMReverse
              #x000002     XIMUnderline
              #x000004     XIMHighlight
              #x000008     XIMPrimary
              #x000010     XIMSecondary
              #x000020     XIMTertiary
              #x000040     XIMVisibleToForward
              #x000080     XIMVisibleToBackward
              #x000100     XIMVisibleCenter

    XIMHOTKEYSTATE
         4    CARD32       XIMHotKeyState
              #x0000001    XIMHotKeyStateON
              #x0000002    XIMHotKeyStateOFF

    XIMPREEDITSTATE
         4    CARD32       XIMPreeditState
              #x0000001    XIMPreeditEnable
              #x0000002    XIMPreeditDisable

    XIMRESETSTATE
         4    CARD32       XIMResetState
              #x0000001    XIMInitialState
              #x0000002    XIMPreserveState

### エラーの通知

IM サーバと IM ライブラリの両者は、データの処理の途中で何らかのエラーが発生した場合には、本来送るはずだったリプライ・メッセージの代わりに `XIM_ERROR` メッセージを返す。

１つのリクエストに付き１つしかエラーは発生しない。リクエストの処理の最中に複数のエラー発生条件が成立した場合、どのエラーを返すのかは実装依存である。

    XIM_ERROR (IM Server <--> IM library)
              2     CARD16          input-method-ID
              2     CARD16          input-context-ID
              2     BITMASK16       flag (*1)
                    #0000           Input-Method-ID と Input-Context-ID の両方が無効
                    #0001           Input-Method-ID は有効
                    #0002           Input-Context-ID は有効
              2     CARD16          Error Code
                    #1              BadAlloc
                    #2              BadStyle
                    #3              BadClientWindow
                    #4              BadFocusWindow
                    #5              BadArea
                    #6              BadSpotLocation
                    #7              BadColormap
                    #8              BadAtom
                    #9              BadPixel
                    #10             BadPixmap
                    #11             BadName
                    #12             BadCursor
                    #13             BadProtocol
                    #14             BadForeground
                    #15             BadBackground
                    #16             LocaleNotSupported
                    #999            BadSomething (*2)
              2     n               「エラー詳細」の長さ(単位はバイト)
              2     CARD16          「エラーの詳細」の型 (*3)
              n     STRING8         エラー詳細 (*4)
              p                     unused, p = Pad(n)

(*1)
  IM が作成されるまでは、Input-Method-ID も Input-Context-ID も無効である。IC が作成されるまでは、 Input-Method-ID だけが有効である。その後は、Input-Method-ID も Input-Context-ID も有効である。
(*2)
  不特定のエラー、例えば「言語エンジンが死んでいる」など。
(*3)
  このフィールドは将来のために予約されている。
(*4)
  開発企業が定める、詳しいエラー・メッセージ。

### 接続の確立

`XIM_CONNECT` メッセージは、接続を確立するためのリクエストである。この接続は、相互にやり取りを行うことができる(mutually-understood)仮想ストリームを用いるものである。(訳註：X Font Service Protocolによると、「mutually-understood virtual stream connection」とは、例えばTCP/IPやDECnetのような方式の接続のことをいうらしい。)

    XIM_CONNECT (IM library -> IM Server)
         1                      バイト順
               #x42             MSB first
               #x6c             LSB first
         1                      未使用
         2     CARD16           client-major-protocol-version (*1)
         2     CARD16           client-minor-protocol-version (*1)
         2     CARD16           次の client-auth-protocol-names の要素数
         n     LISTofSTRING     client-auth-protocol-names

(*1)
  クライアントが対応している IM プロトコルの版を表す。

クライアントは、接続における最初のメッセージとして、`XIM_CONNECT` メッセージを送信しなければならない。メッセージ中のリストは、このメッセージを受け取った IM サーバ(訳註：原文は「the sending IM Server」)が実施すべき認証プロトコルの名前を記載したものである。クライアントが認証を必要としない場合、このリストの指定は省いてもよい。(訳註：クライントは、自分が対応できる認証プロトコルを申告する。)

`XIM_AUTH_REQUIRED` メッセージを使用すると、認証プロトコルの名前と同プロトコル用のデータを送信することができる。

    XIM_AUTH_REQUIRED (IM library <--> IM Server)
         1     CARD8              auth-protocol-index
         3                        unused
         2     n                  認証データの長さ
         2                        unused
         n     <varies>     認証データ
         p                        unused, p = Pad(n)

auth-protocol (認証プロトコル)は、`XIM_CONNECT` メッセージもしくは `XIM_AUTH_SETUP` メッセージで受け取った名前リストの要素番号で指定する。プロトコル用のデータが必要であれば、それも送信する。

IM ライブラリは、IM サーバの認証を行う場合、`XIM_AUTH_REQUIRED` メッセージへの返答として `XIM_AUTH_REPLY` メッセージを送信する。

    XIM_AUTH_REPLY (IM library -> IM Server)
         2     n                 認証データの長さ
         2                       unused
         n     <varies>      認証データ
         p                       unused, p = Pad(n)
         (訳註：原文では「認証データの長さ」と「unused」とを２個づつ送ることになっていたので、これを修正。)

認証データは、使用している認証プロトコル特有のものである。

`XIM_AUTH_NEXT` メッセージによって、更なる認証データを送信するよう要求する。

    XIM_AUTH_NEXT (IM library <--> IM Server)
         2     n                 認証データの長さ
         2                       unused
         n     <varies>      認証データ
         p                       unused, p = Pad(n)

認証データは、使用している認証プロトコル特有のものである。

IM サーバは、クライアントの認証を行うために `XIM_AUTH_SETUP` メッセージを送信する。

    XIM_AUTH_SETUP (IM Server -> IM library)
         2     CARD16           server-auth-protocol-names の数(訳註：原文は「client-auth-protocol-names」)
         2                      unused
         n     LISTofSTRING     server-auth-protocol-names

メッセージ中のリストは、クライアントが実施すべき認証プロトコルの名前を記載したものである。(訳註：サーバは、自分が対応している認証プロトコル群をクライアントに申告する。)

`XIM_AUTH_NG` メッセージによって、接続の終了を要求する。

    XIM_AUTH_NG (IM library <--> IM Server)

IM サーバは、`XIM_CONNECT` メッセージもしくは `XIM_AUTH_REQUIRED` メッセージへの返答として、`XIM_CONNECT_REPLY` メッセージを送信する。

    XIM_CONNECT_REPLY (IM Server -> IM library)
         2     CARD16     server-major-protocol-version (*1)
         2     CARD16     server-minor-protocol-version (*1)

(*1)
  IM サーバが対応している IM プロトコルの版番号を表す。本文書では、上位の版番号は 1、下位の版番号は 0 である。

クライアントと IM サーバの状態遷移表を以下に記す。

クライアントの状態遷移

init_status: | 許認可機能を使用する -> client_ask 許認可機能を使用しない -> client_no_check
start: | `XIM_CONNECT` を送信 client_ask 状態であれば -> client_wait1 client_no_check 状態であれば、client-auth-protocol-names は省いてもよい -> client_wait2
client_wait1: | `XIM_AUTH_REQUIRED` を受信 -> client_check <それ以外>を受信 -> client_NG
client_check: | これ以上の認証データのやり取りが不要であれば、`XIM_AUTH_REPLY` を送信 -> client_wait2 認証データに問題が無ければ、`XIM_AUTH_NEXT` を送信 -> client_wait1 認証データに問題があれば、`XIM_AUTH_NG` を送信 -> このプロトコルの手続きを打ち切る
client_wait2: | `XIM_CONNECT_REPLY` を受信 -> connect (接続状態へ) `XIM_AUTH_SETUP` を受信 -> client_more `XIM_AUTH_NEXT` を受信 -> client_more `XIM_AUTH_NG` を受信 -> このプロトコルの手続きを打ち切る <上記のもの以外> を受信 -> client_NG
client_more: | `XIM_AUTH_REQUIRED` を送信 -> client_wait2
client_NG: | `XIM_AUTH_NG` を送信 -> このプロトコルの手続きを打ち切る

IM サーバの状態遷移

init_status: | 許認可機能を使用する -> server_ask 許認可機能を使用しない -> server_no_check
start: | `XIM_CONNECT` を受信 -> start2 <それ以外> を受信 -> server_NG
start2: | client_ask 状態であれば、`XIM_AUTH_REQUIRED` を送信 -> server_wait1 client_no_check 状態であり且つ server_ask 状態であれば、`XIM_AUTH_SETUP` を送信 -> server_wait2 client_no_check 状態であり且つ server_no_check 状態であれば、`XIM_CONNECT_REPLY` を送信 -> connect (接続状態へ)
server_wait1: | `XIM_AUTH_REPLY` を受信 -> server2 `XIM_AUTH_NEXT` を受信 -> server_more <上記のもの以外> を受信 -> server_NG
server_more | `XIM_AUTH_REQUIRED` を送信 -> server_wait1
server2 | server_ask 状態であれば、`XIM_AUTH_SETUP` を送信 -> server_wait2 server_no_check 状態であれば、 `XIM_CONNECT_REPLY` を送信 -> connect (接続状態へ)
server_wait2 | `XIM_AUTH_REQUIRED` を受信 -> server_check <それ以外> を受信 -> server_NG
server_check | これ以上認証データが存在しない場合、`XIM_CONNECT_REPLY` を送信 -> connect (接続状態へ) 認証データに問題があれば、`XIM_AUTH_NG` を送信 -> このプロトコルの手続きを打ち切る 認証データに問題が無ければ、`XIM_AUTH_NEXT` を送信 -> server_wait2
server_NG | `XIM_AUTH_NG` を送信 -> このプロトコルの手続きを打ち切る

`XIM_DISCONNECT` メッセージによって、接続(相互にやり取りを行うことができる(mutually-understood)仮想ストリームを用いたもの)の終了を要求する。

    XIM_DISCONNECT (IM library -> IM Server)

`XIM_DISCONNECT` は、同期を取るリクエストである。IM ライブラリは、`XIM_DISCONNECT_REPLY` パケットまたは `XIM_ERROR` パケットを受信するまで待機するものとする。

    XIM_DISCONNECT_REPLY (IM Server -> IM library)

`XIM_OPEN` は、IM ライブラリと IM サーバの間に論理的な接続を確立することを要求するものである。

    XIM_OPEN (IM library -> IM Server)
         n     STR     ロケール名
         p             unused, p = Pad(n)

`XIM_OPEN` は、同期を取るリクエストである。IM ライブラリは、`XIM_OPEN_REPLY` パケットまたは `XIM_ERROR` パケットを受信するまで待機するものとする。

    XIM_OPEN_REPLY (IM Server -> IM library)
         2     CARD16             input-method-ID
         2     n                  「利用できる IM 属性」の長さ(単位はバイト)
         n     LISTofXIMATTR      利用できる IM 属性
         2     m                  「利用できる IC 属性」の長さ(単位はバイト)
         2     CARD16             unused
         m     LISTofXICATTR      利用できる IC 属性

`XIM_OPEN_REPLY` メッセージは、利用可能な全ての IM 属性と IC 属性(の ID)を返す。戻り値は LISTofXIMATTR と LISTofXICATTR に格納される。これらの IM 属性及びIC 属性の ID 群を用いることで、 ネットワークを通して転送しなければならないデータの量を減らすことができる。また、上記の ID 群を用いることで、IM ライブラリは、このセッション(session)においてどのような種類の IM/IC 属性が使用可能なのか、及びどのデータ型がやり取りされるのかを知ることができる。これによって IM サーバの提供者やアプリケーションの開発者は、Xlib に変更を加えることなく、新たな IM/IC 属性の導入を伴うような IM システム機能を実装できるようになる。NestedList の区切りを表す IC 属性値は、LISTofXICATTR の中に含めなければならない。

`XIM_CLOSE` メッセージは、IM ライブラリと IM サーバとの間の論理的な接続を終了することを要求するものである。

    XIM_CLOSE (IM library -> IM Server)
         2     CARD16     input-method-ID
         2                unused

`XIM_CLOSE` は、同期を取るリクエストである。IM ライブラリは、`XIM_CLOSE_REPLY` パケットまたは `XIM_ERROR` パケットを受信するまで待機するものとする。

    XIM_CLOSE_REPLY (IM Server -> IM library)
         2     CARD16     input-method-ID
         2                unused

### イベントの流れの制御(2)

IM サーバは、イベントが IM サーバに送られてくるようにするために、IM ライブラリに対して `XIM_SET_EVENT_MASK` メッセージを送信しなければならない。なぜかというと、IM ライブラリは初期状態では如何なるイベントも IM サーバへ送信しないからである。このプロトコル・メッセージにおいて IM サーバは、IM ライブラリが転送するべき X イベントを表すマスクと、IM ライブラリが同期を取るべき X イベントのマスクとを指定する。

    XIM_SET_EVENT_MASK (IM Server -> IM library)
         2     CARD16        input-method-ID
         2     CARD16        input-context-ID
         4     EVENTMASK     forward-event-mask (*1)
         4     EVENTMASK     synchronous-event-mask (*2)

(*1)
  IM ライブラリが IM サーバへ転送するべきイベント全てを指定。
(*2)
  IM ライブラリが同期フラグを ON にして転送するべきイベントを指定。

`XIM_SET_EVENT_MASK` は、同期を取らない(asynchronous)リクエストである。イベント・マスクは、設定直後から有効となり、別の `XIM_SET_EVENT_MASK` メッセージによって変更されるまで有効なままである。input-context-ID に 0 が設定してある場合、input-method-ID (の入力メソッドの次文で述べる IC) のイベント・マスクのデフォルト値は、そのリクエストで指定した値へと変更される。このデフォルト値は、個別に値を指定されていない IC の値として使用されることになる。

動的イベント・フロー方式を使用する場合、IM サーバは、IM ライブラリへ先に `XIM_REGISTER_TRIGGERKEYS` メッセージを送信してから `XIM_OPEN_REPLY` メッセージを送信する。先に `XIM_REGISTER_TRIGGERKEYS` メッセージが送られない場合、IM ライブラリ側では IM サーバが静的イベント・フロー方式を用いるものと仮定してしまってよい。

    XIM_REGISTER_TRIGGERKEYS (IM Server -> IM library)
         2     CARD16                  input-method-ID
         2                             unused
         4     n                       「on-key のリスト」の長さ(単位はバイト)
         n     LISTofXIMTRIGGERKEY     on-key のリスト
         4     m                       「off-key のリスト」の長さ(単位はバイト)
         m     LISTofXIMTRIGGERKEY     off-key のリスト

`XIM_REGISTER_TRIGGERKEYS` は、同期を取らないリクエストである。IM サーバは、このメッセージを用いて「on-key」と「off-key」のリストを IM ライブラリに通知する。

IM ライブラリは、`XIM_TRIGGER_NOTIFY` メッセージを用いることで、「on-key」または「off-key」に該当するキーのイベントが発生したことを IM サーバに通知する。

    XIM_TRIGGER_NOTIFY (IM library -> IM Server)
         2     CARD16           input-method-ID
         2     CARD16           input-context-ID
         4     CARD32           flag
               #0               「on-key」のリスト
               #1               「off-key」のリスト
         4     CARD32           キーのリスト中の要素番号(index)
         4     EVENTMASK        client-select-event-mask (*1)

(*1)
  現在 IM ライブラリが XSelectInput によって選択しているイベント群を表す。

`XIM_TRIGGER_NOTIFY` は、同期を取るリクエストである。IM ライブラリは、`XIM_TRIGGER_NOTIFY_REPLY` パケットまたは `XIM_ERROR` パケットを受信するまで待機するものとする。

    XIM_TRIGGER_NOTIFY_REPLY (IM Server -> IM library)
         2     CARD16     input-method-ID
         2     CARD16     input-context-ID

### 符号化方式の交渉

`XIM_ENCODING_NEGOTIATION` メッセージは、通信経路上の送受信においてどの符号化方式を用いるのかを決定するよう要求するものである。交渉が失敗に終わった場合の予備のデフォルト符号化方式は Portable Character Encoding である。

    XIM_ENCODING_NEGOTIATION (IM library -> IM Server)
         2     CARD16                 input-method-ID
         2     n                      符号化方式の(名前による)リストの長さ(単位はバイト)
         n     LISTofSTR              IM ライブラリが対応している符号化方式のリスト
         p                            unused, p = Pad(n)
         2     m                      符号化方式の(詳細データによる)リストの長さ(単位はバイト)
         2                            unused
         m     LISTofENCODINGINFO     IM ライブラリが対応している符号化方式のリスト

IM サーバは、IM ライブラリが送ってきたリストの中から符号化方式を１つ選ばなければならない。符号化方式の要素番号として -1 が選択された場合、交渉が失敗したことを意味する。この場合、予備のデフォルト符号化方式が使用される。`XIM_ENCODING_NEGOTIATION` メッセージは、XOpenIM() を通じて `XIM_OPEN` メッセージを送信した後に発行しなければならない。符号化方式の名前は X Consortium に登録することができる。

`XIM_ENCODING_NEGOTIATION` は、同期を取るリクエストである。IM ライブラリは、`XIM_ENCODING_NEGOTIATION_REPLY` パケットまたは `XIM_ERROR` パケットを受信するまで待機するものとする。

    XIM_ENCODING_NEGOTIATION_REPLY (IM Server -> IM library)
         2     CARD16     input-method-ID
         2     CARD16     選択された符号化方式のリストの種類
               #0         名前によるリスト
               #1         詳細データによるリスト
         2     INT16      選択された符号化方式の要素番号。
         2                unused

### 利用可能な拡張プロトコルの目録を要求する

`XIM_QUERY_EXTENSION` メッセージは、IM サーバ(クライアントが現在接続しているもの)が対応している IM 拡張(のリスト)を問い合わせるためのものである。

    XIM_QUERY_EXTENSION (IM library -> IM Server)
         2     CARD16        input-method-ID
         2     n             次の「IM ライブラリが対応している拡張のリスト」の長さ(単位はバイト)
         n     LISTofSTR     IM ライブラリが対応している拡張のリスト
         p                   unused, p = Pad(n)

利用可能な拡張の例は、FrontEnd (フロントエンド方式)である。このメッセージは、XOpenIM() を通じて `XIM_OPEN` メッセージを送信した後に発行しなければならない。

n の値が 0 である場合、IM ライブラリは IM サーバが対応している拡張全ての情報を取り寄せようとしている。

n の値が 0 でない場合、IM ライブラリは、リストで指定した拡張群に IM サーバが対応しているかどうかを問い合わせている。

クライアントがある拡張のリクエストを使用した場合、同クライアントが予め `XIM_QUERY_EXTENSION` メッセージを発行して同拡張について問い合わせをしていなかったのであれば、IM サーバは `BadProtocol` エラーで応じる。IM サーバは、未知の MAJOR-OPCODE や MINOR-OPCODE を持つリクエストに出会した場合、`BadProtocol` エラーで応じる。

`XIM_QUERY_EXTENSION` は、同期を取るリクエストである。IM ライブラリは、`XIM_QUERY_EXTENSION_REPLY` パケットもしくは `XIM_ERROR` パケットのどちらかを受け取るまで待つべきである。

    XIM_QUERY_EXTENSION_REPLY (IM Server -> IM library)
         2     CARD16      input-method-ID
         2     n           次の「IM ライブラリと IM サーバの両方が対応している拡張のリスト」の長さ(単位はバイト)
         n     LISTofEXT   IM ライブラリと IM サーバの両方が対応している拡張のリスト

`XIM_QUERY_EXTENSION_REPLY` メッセージは、IM ライブラリと IM サーバの両方が対応している拡張のリストを返すものである。`XIM_QUERY_EXTENSION` で指定されたリストが NULL であった場合、IM サーバは自身が対応している拡張全てを載せたリストを返す。`XIM_QUERY_EXTENSION` で指定されたリストが NULL でなかった場合、IM サーバは、同リストに含まれている拡張の中の、自身が対応しているものの目録を返す。

長さが 0 の文字列は、拡張の名前として有効なものではない。IM ライブラリは、拡張リストとして返ってきた文字列の中の長さが 0 の文字列を全て無視するべきである。IM ライブラリは、IM サーバが対応していないリクエストを使用してはいけない。

### IM の属性値を設定する

`XIM_SET_IM_VALUES` は、IM の属性群を設定することを要求するものである。

    XIM_SET_IM_VALUES (IM library -> IM Server)
         2     CARD16                 input-method-ID
         2     n                      im-attributes の長さ(単位はバイト)
         n     LISTofXIMATTRIBUTE     im-attributes

`XIM_SET_IM_VALUES` メッセージの中の im-attributes は、LISTofXIMATTRIBUTE 型で指定されるものであり、設定すべき属性群を表す。`XIM_OPEN_REPLY` メッセージで返された属性以外のものは指定しないものとする。

`XIM_SET_IM_VALUES` は、同期を取るリクエストである。IM ライブラリは、`XIM_SET_IM_VALUES_REPLY` パケットまたは `XIM_ERROR` パケットを受信するまで待機するものとする。なぜかというと、`XIM_ERROR` メッセージが返された場合、IM ライブラリはエラー属性(訳註：属性を順次設定していった時に最初にエラーが起きた属性？：要確認)を受け取るに違いないからである。

    XIM_SET_IM_VALUES_REPLY (IM Server -> IM library)
         2     CARD16     input-method-ID
         2                unused

`XIM_SET_IM_VALUES_REPLY` メッセージは input-method-ID を返すので、これによって複数の IM からのリプライ(返答)を見分けることができる。

### IM の属性値を取得する

`XIM_GET_IM_VALUES` は、現在接続している IM サーバが保持している IM 属性群の値を問い合わせるものである。

    XIM_GET_IM_VALUES (IM library -> IM Server)
         2     CARD16           input-method-ID
         2     n                im-attribute-id の長さ(単位はバイト)
         n     LISTofCARD16     im-attribute-id
         p                      unused, p=Pad(n)

`XIM_GET_IM_VALUES` は、同期を取るリクエストである。IM ライブラリは、`XIM_GET_IM_VALUES_REPLY` パケットまたは `XIM_ERROR` パケットを受信するまで待機するものとする。

    XIM_GET_IM_VALUES_REPLY (IM Server -> IM library)
         2     CARD16                 input-method-ID
         2     n                      返ってきた im-attributes の長さ(単位はバイト)
         n     LISTofXIMATTRIBUTE     返ってきた im-attributes

IM サーバは、`XIM_GET_IM_VALUES_REPLY` メッセージを使って IM 属性群の値を返す。返ってきた im-attribute のリストにおける属性値の並び順は、`XIM_GET_IM_VALUES` メッセージで渡したリストの中での(対応する属性 ID の)順序と一致する。

### IC を作成する

`XIM_CREATE_IC` メッセージは、IC を１つ作成するよう要求するものである。

    XIM_CREATE_IC (IM library -> IM Server)
         2     CARD16                 input-method-ID
         2     n                      ic-attributes の長さ(単位はバイト)
         n     LISTofXICATTRIBUTE     ic-attributes

input-context-ID は、`XIM_CREATE_IC` メッセージでクライアントが指定するものではなく、クライアント(IC)を識別するために IM サーバが指定するものである。また、input-context-ID の値は、0 には設定しないものとする。

`XIM_CREATE_IC` は、同期を取るリクエストであり、input-context-ID を返す。IM ライブラリは、`XIM_CREATE_IC_REPLY` パケットまたは `XIM_ERROR` パケットを受信するまで待機するものとする。

    XIM_CREATE_IC_REPLY (IM Server -> IM library)
         2     CARD16     input-method-ID
         2     CARD16     input-context-ID

### IC を破棄する

`XIM_DESTROY_IC` メッセージは、指定した IC の破棄を要求するものである。

    XIM_DESTROY_IC (IM library -> IM Server)
         2     CARD16     input-method-ID
         2     CARD16     input-context-ID

`XIM_DESTROY_IC` は、同期を取るリクエストである。IM ライブラリは、`XIM_DESTROY_IC_REPLY` メッセージを受信するまで自身のリソースを解放しないものとする。なぜかというと、`XIM_DESTROY_IC` メッセージの結果として `XIM_PREEDIT_DRAW` や `XIM_PREEDIT_DONE` といったコールバック・パケットが発生する可能性があるからである。

    XIM_DESTROY_IC_REPLY (IM Server -> IM library)
         2     CARD16     input-method-ID
         2     CARD16     input-context-ID

### IC の属性値を設定する

`XIM_SET_IC_VALUES` メッセージは、IC の属性群を設定することを要求するものである。

    XIM_SET_IC_VALUES (IM library -> IM Server)
         2     CARD16                 input-method-ID
         2     CARD16                 input-context-ID
         2     n                      ic-attributes の長さ(単位はバイト)
         2                            unused
         n     LISTofXICATTRIBUTE     ic-attributes

`XIM_SET_IC_VALUES` の中の ic-attributes は、LISTofXICATTRIBUTE 型を用いて指定されるものであり、設定すべき属性群を表す。`XIM_OPEN_REPLY` メッセージで返ってきた属性以外のものは指定しないものとする。

`XIM_SET_IC_VALUES` は、同期を取るリクエストである。IM ライブラリは、`XIM_SET_IC_VALUES_REPLY` パケットまたは `XIM_ERROR` パケットを受信するまで待機するものとする。なぜかというと、`XIM_ERROR` メッセージが返ってきた場合、IM ライブラリはエラー属性(訳註：属性を順次設定していった時に最初にエラーが起きた属性？：要確認)を受け取るに違いないからである。

    XIM_SET_IC_VALUES_REPLY (IM Server -> IM library)
         2     CARD16     input-method-ID
         2     CARD16     input-context-ID

### IC の属性値を取得する

`XIM_GET_IC_VALUES` メッセージは、現在接続している IM サーバが保持している IC の属性値を問い合わせるものである。

    XIM_GET_IC_VALUES (IM library -> IM Server)
         2     CARD16           input-method-ID
         2     CARD16           input-context-ID
         2     n                ic-attribute-id のリストの長さ(単位はバイト)
         n     LISTofCARD16     ic-attribute-id
         p                      unused, p=Pad(2+n)

LISTofCARD16 において NestedList の区切りを表す ic-attribute-id が現れた場合、先頭の入れ籠リストが終わったことを意味する。

`XIM_GET_IC_VALUES` は、同期を取るリクエストであり、指定した属性群のそれぞれに属性値を付して返すものである(訳註：XIM_GET_IC_VALUES_REPLY で返る XICATTRIBUTE には、属性の ID と値が入っている)。IM ライブラリは、`XIM_GET_IC_VALUES_REPLY` パケットまたは `XIM_ERROR` パケットを受信するまで待機するものとする。

    XIM_GET_IC_VALUES_REPLY (IM Server -> IM library)
         2     CARD16                 input-method-ID
         2     CARD16                 input-context-ID
         2     n                      ic-attribute の長さ(単位はバイト)
         2                            unused
         n     LISTofXICATTRIBUTE     ic-attribute

### IC のフォーカスを設定する

`XIM_SET_IC_FOCUS` メッセージは、指定した IC へフォーカスを設定するよう要求するものである。

    XIM_SET_IC_FOCUS (IM library -> IM Server)
         2     CARD16     input-method-ID
         2     CARD16     input-context-ID

`XIM_SET_IC_FOCUS` は、同期を取らないリクエストである。

### IC のフォーカスを外す

`XIM_UNSET_IC_FOCUS` メッセージは、フォーカスのある IC からフォーカスを外す(unset)よう要求するものである。

    XIM_UNSET_IC_FOCUS (IM library -> IM Server)
         2     CARD16     input-method-ID
         2     CARD16     input-context-ID

`XIM_UNSET_IC_FOCUS` は、同期を取らないリクエストである。

### イベントを濾過する

イベントの濾過機能の主たる用途は、バックエンド方式において入力メソッドが X イベントを(クライアントに対して)透過的に捕捉できるようにすることである。

X イベントは `XIM_FORWARD_EVENT` メッセージによって転送される。このメッセージは、同期を取って処理することもできるし、同期を取らずに処理することもできる。要求者(このメッセージの発行者)が同期フラグを立てていた場合、受信者は、全てのデータの処理が完了したとき、`XIM_SYNC_REPLY` メッセージを要求者に送り返さなければならない。

バックエンド方式におけるプロトコルの流れ

バックエンド方式を用いる場合、プロトコル(のメッセージ)の流れ方は、「同期」の観点から２つに分類できる。この分類は、`XIM_SET_EVENT_MASK` メッセージの synchronous-event-mask に基いて決まる。１つは on-demand-synchronous 方式(オン・デマンド同期方式、サーバの要求を受けて同期を取る方式)、もう１つは full-synchronous 方式(常時同期方式、クライアント側から常時同期を要求)と呼ばれる。

オン・デマンド同期方式では、IM ライブラリは `XIM_FORWARD_EVENT` メッセージや `XIM_COMMIT` メッセージを常に同期リクエストとして受信する。IM サーバもまた、入力サービスの状態に矛盾が生じないように、次の２種類のメッセージは同期を取る形で処理する必要がある。そのメッセージとは即ち、先のメッセージに対する IM ライブラリからの返答と、何らかのイベントによって IM サーバが IM ライブラリに対して `XIM_FORWARD_EVENT` メッセージや `XIM_COMMIT` メッセージを送ったときに IM ライブラリが後から送ってくる `XIM_FORWARD_EVENT` メッセージ(訳註：先行の同期処理中に送られてきた返答ではないメッセージ)である。IM ライブラリは、同期リクエストを受信した後にアプリケーションから制御を取り戻した場合、他のイベントの処理に先立って同期リクエストに返答する。この時、IM サーバは、IM ライブラリから送られた `XIM_FORWARD_EVENT` メッセージをブロックし、返答(リプライ)を受信してからこのメッセージを処理する。しかしながら、IM サーバは、他のプロトコルは何時でも処理することができる。

常時同期方式では、IM ライブラリは `XIM_FORWARD_EVENT` メッセージを常に同期リクエストとして IM サーバへ送信する。それゆえ、このメッセージ対する IM サーバからの返答は、同 `XIM_FORWARD_EVENT` メッセージとそれに対して送られる `XIM_SYNC_REPLY` メッセージとの間に行われることになる。IM サーバは、`XIM_FORWARD_EVENT` メッセージあるいは `XIM_COMMIT` メッセージを送信する場合、同期フラグを OFF に設定するものとする。なぜかというと、同期の手続きは後続の `XIM_SYNC_REPLY` メッセージによって完成させることができるからである。

次の図は、最も単純なプロトコルの流れを描いたものであり、前編集の操作で使われるキー・イベントだけを扱っている。

(訳註：下の図は、どちらもオン・デマンドの同期方式である。)

プロトコルの流れの参考図１

次の図は、複雑なプロトコルの流れを描いたものであり、複数のフォーカス・ウィンドウが登場し、ボタン押下イベント及びキー・イベントを扱っている。また、この図では、キー・イベントとボタン押下イベントを切っ掛けとして、アプリケーションがフォーカスを移動させている。

プロトコルの流れの参考図２

    XIM_FORWARD_EVENT (IM library <--> IM Server)
         2     CARD16         input-method-ID
         2     CARD16         input-context-ID
         2     BITMASK16      flag
               #0001          synchronous (同期フラグ)
               #0002          filtering を要求(*1)
               #0004          lookupstring を要求(*2)
         2     CARD16         通し番号
               XEVENT         X イベント

(*1)
  受信者がイベントを濾過する(filter)べきであること、及び前編集が起こる可能性があることを表す。
(*2)
  受信者が「lookup string」しか行わないようにするべきであることを表す。IM サーバに期待されているのは、キー・イベントを最良の候補へ変換する処理を１回行うことだけである。このビットは、「前編集状態」の状態(訳註：前編集の有効・無効？)に影響を与える可能性がある(例えば、デッド・キーの符号列の構成(原文：compose of dead key sequences：訳註：要確認))。

XEVENT の形式(format)は X プロトコルのイベントの形式(以下 xEvent と表記)と同じである。xEvent の通し番号の値は XEvent 構造体の xany.serial の下位１６ビットにすぎないで(訳註：X プロトコル「イベントの書式」参照)、上位１６ビットは「通し番号」(INT16)(訳註：上の XIM_FORWARD_EVENT の説明の「2 CARD16 通し番号」のところ)を使って送信する。

`XIM_FORWARD_EVENT` メッセージは、IM がイベントを濾過(filter)できるようにするべく、IM ライブラリから IM サーバへイベントを転送するのに使用される。また、このメッセージは、IM ライブラリから送られてきたイベントを濾過によって取り除かなかった場合に、そうしたイベント群を IM サーバから IM ライブラリへ転送するのにも使用される。同期フラグが立っていない `XIM_FORWARD_EVENT` メッセージを受け取った IM サーバは、同期フラグを設定する(立たせる)ものとする。「filtering を要求」と「lookupstring を要求」の両方のフラグが立っていた場合、同一のイベントに対して濾過と lookup の両方を実施するものとする。

### IM サーバと同期を取る

`XIM_SYNC` メッセージは、IM ライブラリと IM サーバとを同期させるよう要求するものである。

    XIM_SYNC (IM library <--> IM Server)
         2     CARD16     input-method-ID
         2     CARD16     input-context-ID

この同期の手続きは、IM ライブラリの側からでも IM サーバの側からでも提起することができる。`XIM_SYNC` メッセージを受け取った側は、返答する前に全ての XIM リクエストを処理するものとする。input-context-ID は、IM ライブラリと IM サーバの同期が行われる IC を識別するために必要なものである。

    XIM_SYNC_REPLY (IM Server <--> IM library)
         2     CARD16     input-method-ID
         2     CARD16     input-context-ID

`XIM_FORWARD_EVENT` メッセージ、`XIM_COMMIT` メッセージ、あるいはその他のメッセージを受け取った側は、それらのメッセージの synchronous フラグが立っていた場合、返答する前に全ての XIM リクエストを処理するものとし、先に受け取ったメッセージへの返答として `XIM_SYNC_REPLY` メッセージを送信するものとする。

### 確定文字列(committed string)を送信する

IM サーバは、文字列を確定させたとき、「確定文字列」か「KeySym のリスト」の一方もしくは両方を `XIM_COMMIT` メッセージを用いて送信する。

    XIM_COMMIT (IM Server -> IM library)
         2     CARD16          input-method-ID
         2     CARD16          input-context-ID
         2     BITMASK16       flag
               #0001           synchronous
               #0002           XLookupChars
               #0004           XLookupKeySym
               #0006           XLookupBoth = XLookupChars | XLookupKeySym

フラグが XLookupKeySym である場合、この後に次の引数が続く。

         2                unused
         4     KEYSYM     KeySym

フラグが XLookupChars である場合、後ろに次の引数が続く。

         2     m              確定文字列の長さ(単位はバイト)
         m     LISTofBYTE     確定文字列
         p                    unused, p = Pad(m)

フラグが XLookupBoth である場合、後ろに次の引数が続く。

         2                    unused
         4     KEYSYM         KeySym
         2     n              確定文字列の長さ(単位はバイト)
         n     LISTofBYTE     確定文字列
         p                    unused, p = Pad(2+n)

同期フラグの立っていない `XIM_COMMIT` メッセージを受け取った IM ライブラリは、(以降のメッセージで)同期フラグを立たせるものとする。(原文：「The IM Server which receives XIM_COMMIT message without synchronous bit should set synchronous bit.」：訳註：IM サーバが `XIM_COMMIT` を受け取ることは無さそう。IM サーバの部分を IM ライブラリに変更。)

### IC をリセットする

`XIM_RESET_IC` メッセージは、IM サーバ内の IC の状態をリセットすることを要求するものである。

    XIM_RESET_IC (IM library -> IM Server)
         2     CARD16     input-method-ID
         2     CARD16     input-context-ID

`XIM_RESET_IC` は、同期を取るリクエストである。IM ライブラリは、`XIM_RESET_IC_REPLY` パケットまたは `XIM_ERROR` パケットを受信するまで待機するものとする。

    XIM_RESET_IC_REPLY (IM Server -> IM library)
         2     CARD16         input-method-ID
         2     CARD16         input-context-ID
         2     n              前編集文字列の長さ(単位はバイト)
         n     LISTofBYTE     前編集文字列
         p                    unused, p = Pad(2+n)

`XIM_RESET_IC_REPLY` メッセージは、複数ある IC の中、どの IC からのリプライ(返答)なのかを識別できるように、input-context-ID を返す。

### コールバック

XIMStyle に XIMPreeditArea あるいは XIMStatusArea が設定されている場合、XIMGeometryCallback を使用することができる。また、XIMPreeditCallback と XIMStatusCallback の片方あるいは両方が設定されている場合、対応するコールバックを使用することができる。

如何なるコールバック・リクエストも、その前に IM クライアントから IM サーバへ送られてきていたリクエストへの応答として、IM サーバから IM クライアントへ同期を取らずに(非同期的に)送ることができる。

IM サーバがあるコールバック・リクエストを送信するにあたって、それ以前に IM クライアントから送られてきていたリクエストに対して同期を取る必要がある場合、IM サーバは同コールバック・リクエストを送信してから先行のリクエストに返答する。

#### ジオメトリを交渉する

IM サーバは、XIMStyle に XIMPreeditArea あるいは XIMStatusArea が設定されている場合、`XIM_GEOMETRY` メッセージを送信してジオメトリの交渉を開始する。

    XIM_GEOMETRY (IM Server -> IM library)
         2     CARD16     input-method-ID
         2     CARD16     input-context-ID

複数の入力欄が１つの IC を共有している場合であっても、フォーカス・ウィンドウは常にただ１つしか存在しない。

#### 文字列を１つ変換する

    XIM_STR_CONVERSION (IM Server -> IM library)
         2     CARD16     input-method-ID
         2     CARD16     input-context-ID
         2     CARD16     XIMStringConversionPosition
         2                unused
         4     CARD32     XIMCaretDirection
               #0         XIMForwardChar
               #1         XIMBackwardChar
               #2         XIMForwardWord
               #3         XIMBackwardWord
               #4         XIMCaretUp
               #5         XIMCaretDown
               #6         XIMNextLine
               #7         XIMCPreviousLine
               #8         XIMLineStart
               #9         XIMLineEnd
               #10        XIMAbsolutePosition
               #11        XIMDontChange
         2     CARD16     factor
         2     CARD16     XIMStringConversionOperation
               #0001      XIMStringConversionSubstitution
               #0002      XIMStringConversionRetrieval
         2     INT16      XIMStringConversionType にこの長さ(単位はバイト)を掛ける

(訳註：XIMStringConversionType には次の値がある。X11R7.7/lib/libX11-1.5.0/include/X11/Xlib.h より、
#define XIMStringConversionBuffer (0x0001)
#define XIMStringConversionLine (0x0002)
#define XIMStringConversionWord (0x0003)
#define XIMStringConversionChar (0x0004)
：訳註ここまで)

`XIM_STR_CONVERSION` メッセージは、IM サーバ側から文字列の変換を開始するのに使用することができる。

    XIM_STR_CONVERSION_REPLY (IM library -> IM Server)
         2     CARD16             input-method-ID
         2     CARD16             input-context-ID
         4     CARD32             XIMStringConversionFeedback
               XIMSTRCONVTEXT     XIMStringConversionText

`XIM_STR_CONVERSION_REPLY` メッセージは、変換するべき文字列とフィードバック情報の配列とを返すものである。

#### 前編集のコールバック

IM サーバは、`XIM_PREEDIT_START` メッセージを送信することによって XIMPreeditStartCallback 関数を呼び出す。

    XIM_PREEDIT_START (IM Server -> IM library)
         2     CARD16     input-method-ID
         2     CARD16     input-context-ID

このメッセージに対する返答は、同期を取って送信しなければならない。このメッセージに対するリプライ(返答)によって、コールバック関数の戻り値を IM サーバへ転送する。

    XIM_PREEDIT_START_REPLY (IM library -> IM Server)
         2     CARD16     input-method-ID
         2     CARD16     input-context-ID
         4     INT32     戻り値

`XIM_PREEDIT_START_REPLY` メッセージは、複数ある IC の中、どの IC からのリプライ(返答)なのかを識別できるように、input-context-ID を返す。「戻り値」には、XIMPreeditStartCallback 関数の戻り値が入っている。

IM サーバは、`XIM_PREEDIT_DRAW` メッセージを送信することによって XIMPreeditDrawCallback 関数を呼び出す。

    XIM_PREEDIT_DRAW (IM Server -> IM library)
         2     CARD16                input-method-ID
         2     CARD16                input-context-ID
         4     INT32                 caret (訳註：前編集文字列の中でのキャレット(カーソル)の位置)
         4     INT32                 chg_first (訳註：変更される部分の先頭の位置)
         4     INT32                 chg_length (訳註：変更される部分の文字数)
         4     BITMASK32             status
               #x0000001             no string
               #x0000002             no feedback
         2     n                     前編集文字列の長さ
         n     STRING8               前編集文字列
         p                           unused, p = Pad(2+n)
         2     m                     feedback array の長さ(単位はバイト)
         2                           unused
         m     LISTofXIMFEEDBACK     feedback array

３つのフィールド「caret」「chg_first」「chg_length」は、XIMPreeditDrawCallbackStruct 構造体(訳註：定義は X11R7.7/lib/libX11-1.5.0/include/X11/Xlib.h にある)の同名のフィールドに対応する。「status」フィールドの「no string」のビットが立っている場合、XIMPreeditDrawCallbackStruct 構造体の text フィールドの値は NULL である。「status」フィールドの「no feedback」のビットが立っている場合、XIMPreeditDrawCallbackStruct 構造体の text フィールドの中の feedback フィールドの値は NULL である(訳註：text フィールドは XIMText 型のポインタ)。これらのビットが立っていない場合、「前編集文字列」には表示するべき前編集文字列が入っており、「feedback array」にはフィードバック情報が入っている(訳註：フィードバック情報の意味は「XIMFEEDBACK」のところを参照)。

IM サーバは、`XIM_PREEDIT_CARET` メッセージを送信することによって PreeditCaretCallback 関数を呼び出す。

    XIM_PREEDIT_CARET (IM Server -> IM library)
         2     CARD16     input-method-ID
         2     CARD16     input-context-ID
         4     INT32      位置
         4     CARD32     方向
               #0         XIMForwardChar
               #1         XIMBackwardChar
               #2         XIMForwardWord
               #3         XIMBackwardWord
               #4         XIMCaretUp
               #5         XIMCaretDown
               #6         XIMNextLine
               #7         XIMCPreviousLine
               #8         XIMLineStart
               #9         XIMLineEnd
               #10        XIMAbsolutePosition
               #11        XIMDontChange
         4     CARD32     style
               #0         XIMInvisible
               #1         XIMCPrimary
               #2         XIMSecondary

各エントリは、XIMPreeditCaretCallbackStruct 構造体の同名のフィールドに対応する。このコールバックはキャレット(カーソル)の位置を設定するものなので、そのリプライは同期を取って送信しなければならない。

    XIM_PREEDIT_CARET_REPLY (IM library -> IM Server)
         2     CARD16     input-method-ID
         2     CARD16     input-context-ID
         4     CARD32     位置

「位置」は、コールバック関数の呼び出しが終わった後に同関数から返ってきた値である。

IM サーバは、`XIM_PREEDIT_DONE` メッセージを送信することによって XIMPreeditDoneCallback 関数を呼び出す。

    XIM_PREEDIT_DONE (IM Server -> IM library)
         2     CARD16     input-method-ID
         2     CARD16     input-context-ID

#### 前編集の状態の通知

    XIM_PREEDITSTATE (IM Server -> IM Library)
         2     CARD16        input-method-ID
         2     CARD16        input-context-ID
         4     BITMASK32     XIMPreeditState
               #x0000000     XIMPreeditUnknown
               #x0000001     XIMPreeditEnable
               #x0000002     XIMPreeditDisable

`XIM_PREEDITSTATE` メッセージを使用することによって XIMPreeditStateNotifyCallback 関数を呼び出す。

#### 状態表示領域のコールバック(Status Callbacks)

IM サーバは、`XIM_STATUS_START` メッセージを送信することによって XIMStatusStartCallback 関数を呼び出す。

    XIM_STATUS_START (IM Server -> IM library)
         2     CARD16     input-method-ID
         2     CARD16     input-context-ID

IM サーバは、`XIM_STATUS_DRAW` メッセージを送信することによって XIMStatusDrawCallback 関数を呼び出す。

    XIM_STATUS_DRAW (IM Server -> IM library)
         2     CARD16     input-method-ID
         2     CARD16     input-context-ID
         4     CARD32     型
               #0         XIMTextType
               #1         XIMBitmapType

「型」が XIMTextType であれば、この後に次の引数が続く。

         4     BITMASK32            status
               #x0000001            no string
               #x0000002            no feedback
         2     n                    status string の長さ
         n     STRING8              status string
         p                          unused, p = Pad(2+n)
         2     m                    feedback array の長さ(単位はバイト)
         2                          unused
         m     LISTofXIMFEEDBACK    feedback array

「型」が XIMBitmapType である場合、後ろに次の引数が続く。

         4     PIXMAP     pixmap data

「型」のフィールドは、XIMStatusDrawCallbackStruct 構造体の「type」フィールドに対応する。

IM サーバは、`XIM_STATUS_DONE` メッセージを送信することによって XIMStatusDoneCallback 関数を呼び出す。

    XIM_STATUS_DONE (IM Server -> IM library)
         2     CARD16     input-method-ID
         2     CARD16     input-context-ID

## 謝辞

本文書は、MIT X Consortium の国際化作業部会(i18n working group)の支援の下に為された、数年に渡る議論と試行錯誤との結晶である。本文書が集団で作り上げた成果であるとはいっても、誤りや遺漏があれば、それらの責任は著者にある。

MIT X Consortium の国際化作業部会のメンバー全員にお礼を申し上げる。以下に挙げる方々(アルファベット順)には、IM プロトコルの設計に貢献してくれたことに対して、特別な感謝の念を表明したい。Hector Chan、Takashi Fujiwara、Yoshio Horiuchi、Makoto Inada、Hiromu Inukai、Mickael Kung、Seiji Kuwari、Franky Ling、Hiroyuki Machida、Hiroyuki Miyamoto、Frank Rojas、Bob Scheifler、Makiko Shimamura、Shoji Sugiyama、Hidetoshi Tajima、Masaki Takeuchi、Makoto Wakamatsu、Masaki Wakao、Nobuyuki Tanaka、Shigeru Yamada、Katsuhisa Yano、Jinsoo Yoon。

## 参考文献

X Window System Protocol Version 11. Robert W. Scheifler.

Xlib - C Language X Interface". Robert W. Scheifler.

## A. 周知の拡張

拡張を追加してその拡張命令コード(extention opcode)とパケット名(例えば `XIM_EXT_SET_EVENT_MASK`)を X Consortium に登録することができる。以下に挙げるのは、良く知られた(commonly well-known)拡張パケットである。

(1) イベントの処理方法を操作する拡張

`XIM_EXT_SET_EVENT_MASK` メッセージは、IM ライブラリが従うべきイベント・マスク一式を指定するものである。

    XIM_EXT_SET_EVENT_MASK (IM Server -> IM library)
         2     CARD16        input-method-ID
         2     CARD16        input-context-ID
         4     EVENTMASK     filter-event-mask (*1)
         4     EVENTMASK     intercept-event-mask (*2)
         4     EVENTMASK     select-event-mask (*3)
         4     EVENTMASK     forward-event-mask (*4)
         4     EVENTMASK     synchronous-event-mask (*5)

(*1)
  このマスクは、IM ライブラリが XFilterEvent を使って無視するべきイベントを指定する。
(*2)
  このマスクは、IM ライブラリが XSelectInput を使って選択を解除するべきイベントを指定する。
(*3)
  このマスクは、IM ライブラリが XSelectInput を使って選択するべきイベントを指定する。
(*4)
  このマスクは、IM ライブラリが IM サーバへ転送するべきイベント全てを指定する。
(*5)
  このマスクは、IM ライブラリが同期フラグを ON にして転送するべきイベントを指定する。

IM ライブラリは、IM サーバに対して `XIM_SYNC_REPLY` メッセージで返答しなければならない。このリクエストは、IC が作成された後に使用可能となる。

(2) 実行効率を向上させる拡張

以下のリクエストを使って実行効率の向上を図ることができる。

`XIM_EXT_FORWARD_KEYEVENT` メッセージは、`XIM_FORWARD_EVENT` メッセージの代わりに使用することができる。

    XIM_EXT_FORWARD_KEYEVENT (IM Server <--> IM library)
         2     CARD16     input-method-ID
         2     CARD16     input-context-ID
         2     BITMASK16     flag
              #0001     synchronous
         2     CARD16     sequence number(通し番号)
         1     BYTE     xEvent.u.u.type
         1     BYTE     keycode
         2     CARD16     state
         4     CARD32     time
         4     CARD32     window

`XIM_EXT_MOVE` メッセージを `XIM_SET_IC_VALUES` メッセージの代わりに用いて、スポットの位置(spot location)を変更することができる。これが有効となるのは、クライアントが XIMPreeditPosition フラグを設定している場合に限られる。

    XIM_EXT_MOVE (IM library -> IM Server)
         2     CARD16     input-method-ID
         2     CARD16     input-context-ID
         2     INT16     X
         2     INT16     Y

`XIM_EXT_MOVE` メッセージは、同期を取らないリクエストである。

## B. 伝送方式一覧

各伝送方式専用の IM サーバ・アドレスの書式の目録が登録されている。

次の書式によって、`XIM_SERVERS` プロパティに含まれる ATOM と、同プロパティをセレクション・ターゲット「LOCALES」あるいは「TRANSPORT」に変換するリクエストで得られる文字列とを表す。

         "{category=[value,...]}..."

現在、以下の区分(category)が登録されている。

    server;: IM サーバの名前 (XIM_SERVERS に使用)
    locale;: XPG4 ロケール名 (LOCALES)
    transport;: 伝送方式特有の名前 (TRANSPORT)

伝送方式特有の名前のために予め登録してある書式は以下の通り。

`TCP/IP 方式の名前`

システム内部のドメイン名には、次の構文を用いるものとする。

    <local name>  ::= "local/"<hostname>":"<pathname>

この構文における <pathname> は、ソケット・アドレスの経路名である。

複数の IM サーバを同時に実行できるように、IM サーバの名前を <pathname> に設定するものとする。

インターネットのドメイン名には、次の構文を用いるものとする。

    <TCP name>  ::=  "tcp/"<hostname>":"<ipportnumber>

この構文における <hostname> は、識別名(例えば expo.lcs.mit.edu)または数字とピリオドによる名前(例えば 18.30.0.212)である。<ipportnumber> は、IM サーバが接続を待ち受けているポートである。例を挙げる。

    tcp/expo.lcs.mit.edu:8012
    tcp/18.30.0.212:7890

`DECnet 方式の名前`

DECnet の名前には、次の構文を用いるものとする。

    <DECnet name>  ::=  "decnet/"<nodename>"::IMSERVER$"<objname>

この構文における <nodename> は、識別名(例えば SRVNOD)または数字とピリオドから成る形式の DECnet アドレス(例えば 44.70)である。<objname> は、通常の大文字小文字を区別しない DECnet オブジェクト名である。例を挙げる。

    DECNET/SRVNOD::IMSERVER$DEFAULT
    decnet/44.70::IMSERVER$other

`X 方式の名前`

X の名前には、次の構文を用いるものとする。

    <X name>  ::=  "X/"

１つの区分(category)に複数の値が存在する場合、値は設定されている順序で評価される。

## C. プロトコルの番号

`主たるプロトコルの番号`

    XIM_CONNECT                                  #001
    XIM_CONNECT_REPLY                            #002
    XIM_DISCONNECT                               #003
    XIM_DISCONNECT_REPLY                         #004

    XIM_AUTH_REQUIRED                            #010
    XIM_AUTH_REPLY                               #011
    XIM_AUTH_NEXT                                #012
    XIM_AUTH_SETUP                               #013
    XIM_AUTH_NG                                  #014

    XIM_ERROR                                    #020

    XIM_OPEN                                     #030
    XIM_OPEN_REPLY                               #031
    XIM_CLOSE                                    #032
    XIM_CLOSE_REPLY                              #033
    XIM_REGISTER_TRIGGERKEYS                     #034
    XIM_TRIGGER_NOTIFY                           #035
    XIM_TRIGGER_NOTIFY_REPLY                     #036
    XIM_SET_EVENT_MASK                           #037
    XIM_ENCODING_NEGOTIATION                     #038
    XIM_ENCODING_NEGOTIATION_REPLY               #039
    XIM_QUERY_EXTENSION                          #040
    XIM_QUERY_EXTENSION_REPLY                    #041
    XIM_SET_IM_VALUES                            #042
    XIM_SET_IM_VALUES_REPLY                      #043
    XIM_GET_IM_VALUES                            #044
    XIM_GET_IM_VALUES_REPLY                      #045

    XIM_CREATE_IC                                #050
    XIM_CREATE_IC_REPLY                          #051
    XIM_DESTROY_IC                               #052
    XIM_DESTROY_IC_REPLY                         #053
    XIM_SET_IC_VALUES                            #054
    XIM_SET_IC_VALUES_REPLY                      #055
    XIM_GET_IC_VALUES                            #056
    XIM_GET_IC_VALUES_REPLY                      #057
    XIM_SET_IC_FOCUS                             #058
    XIM_UNSET_IC_FOCUS                           #059
    XIM_FORWARD_EVENT                            #060
    XIM_SYNC                                     #061
    XIM_SYNC_REPLY                               #062
    XIM_COMMIT                                   #063
    XIM_RESET_IC                                 #064
    XIM_RESET_IC_REPLY                           #065

    XIM_GEOMETRY                                 #070
    XIM_STR_CONVERSION                           #071
    XIM_STR_CONVERSION_REPLY                     #072
    XIM_PREEDIT_START                            #073
    XIM_PREEDIT_START_REPLY                      #074
    XIM_PREEDIT_DRAW                             #075
    XIM_PREEDIT_CARET                            #076
    XIM_PREEDIT_CARET_REPLY                      #077
    XIM_PREEDIT_DONE                             #078
    XIM_STATUS_START                             #079
    XIM_STATUS_DRAW                              #080
    XIM_STATUS_DONE                              #081
    XIM_PREEDITSTATE                             #082

(*)
  IM サーバの拡張プロトコルの番号は、#128 より大きくするものとする。

## D. 実装の技法

(1) フロントエンド方式

フロントエンド方式は、様々な面で信頼性を損ねるのと引き換えに実行速度を上げる方式であると考えられている。

フロントエンド方式を使用するためには、IM ライブラリは、フロントエンド拡張が利用可能かどうかを IM サーバに問い合わせなければならない。問い合わせは `XIM_QUERY_EXTENSION` メッセージを用いて行う。IM サーバは、`XIM_QUERY_EXTENSION_REPLY` メッセージで返答した後は、intercept-event-mask、forward-event-mask、及び synchronous-event-mask の値が設定された `XIM_EXT_SET_EVENT_MASK` メッセージを送信することができる。

フロントエンド方式は、IM サーバが `XIM_EXT_SET_EVENT_MASK` メッセージを利用する方法に応じて、２通りのやり方で実装することができる。

１つ目のやり方は、前編集の状態に応じて入力マスク(input mask：訳註：IM ライブラリと IM サーバがどのイベントを受け取るのか)と filter-event-mask の両方を更新するというものである。次の図は、静的イベント・フローを用いた場合のプロトコルの手続きの例である。

イベントの流れ

前編集のモード(訳註：ON か OFF か)と無関係に最大の実行効率を追求するために、IM サーバは、次の参考プロトコル手続きのように、動的イベント・フローを使用することができる。

イベントの流れ

この方式では、intercept-event-mask と select-event-mask を状況に応じて更新することによって、XIM プロトコルの通信量を劇的に減らすことができる。このやり方では、実行効率向上と引き換えに、特定の状況でキー・イベントの紛失や順序の混乱が発生し得る。例えば、ユーザがキーボードをとても速く叩いて、次のような入力を行ったような場合に発生し得る。

<前編集を ON にするキー>「何らかの文字列」<前編集を OFF にするキー>「別の文字列」

なぜそのようなことが起きるのかというと、この方式では前編集の ON と OFF を切り替えるときに IM サーバと Xlib の両方において入力マスクを更新する必要あり、２つのクライアントが入力マスクの更新要求を同時に発行したときにそれらのリクエストが効果を生ずるまでには時間差があるからである。

フロントエンド方式の実装のもう１つのやり方は、前編集の状態(訳註：前編集が ON か OFF か)に応じて filter-event-mask は更新するけれども、入力マスクは更新しないというものである。IM サーバは、`XIM_REGISTER_TRIGGERKEYS` メッセージによって、前編集を ON にするキーのリストと OFF にするキーのリストの両方を登録しなければならない。この方式では、IM サーバと IM クライアントの両者が同一のクライアント・ウィンドウに対して同じイベント群を選択する。それらのイベントが IM サーバと IM クライアントの両者に配送されるようにするためである。前編集の ON と OFF の状態は、キー・イベントが濾過で取り除かれるか否かによって表される。プロトコルの手続きの参考図を挙げる。

<<静的イベント・フローを使用する場合>>

イベントの流れ

<<動的イベント・フローを使用する場合>>

イベントの流れ

この方式では、前編集の ON と OFF を切り替えるときの時間差の問題は発生しない。けれども、実行速度の向上の度合いは上述の方式ほどには優れない。

一般に、フロントエンド方式では、GrabKey プロトコル・リクエストや、イベント・マスクを変更するための ChangeWindowAttribute プロトコル・リクエストなどの幾つかの X プロトコル(リクエスト)に関して、何らかの同期(の仕組み)が必要となる。これは、フロントエンド方式が X の主要部分であるイベント配送機構に依存しているからである。同期を考慮していない X プロトコル・バインディングでは、IM クライアントと IM サーバとの間に同期の齟齬が生じ得る。

(2) 伝送制御層(Transport Layer)

Xlib の XIM の実装は、別々の機能を持つ３つ層から成る。３つの層とは、プロトコル層、インターフェイス層、伝送制御層(transport layer)である。層分けの狙いは、プロトコルが伝送制御層の実装に左右されないようすることである。各層の機能は次の通り。

プロトコル層 | この層は、XIM の機能全般を実装したものであり、IM サーバと通信する必要があるときはインターフェイス層の機能を呼び出す。
インターフェイス層 | この層は、伝送制御層の実装をプロトコル層から切り離すものである。別の言い方をすると、この層は、伝送制御層の機能を使用するための、実装に依存しないフック(仕掛けhook)である。
伝送制御層(transport layer) | この層は、IM サーバとの実際のデータ通信を行うものである。データ通信は、transporter (伝送層伝送機構)と呼ばれる機能一式によって為される。

インターフェイス層と伝送制御層のおかげで、X プロトコル、TCP/IP、DECnet、STREAMS (訳注：原文は STREAM 要確認)といった様々な通信経路を利用できるようになる。以下に挙げるのは、X 接続を使用する伝送層伝送機構の実装例である。ソケット伝送を用いる伝送層伝送機構については、「xtrans」を参照(訳註："xtrans"とは「X Transport Interface」のことか？要確認)。

XIM 伝送機構(transport mechanism)のための X 伝送接続を開始する時には、Xlib の XIM の中または IM サーバの中に２つのウィンドウを作成しなければならない。Xlib と IM サーバは、この２つのウィンドウを経由して ClientMessage イベントとウィンドウ・プロパティとを使用することで、XIM 伝送のやり取りを行う。以降の記述においては、Xlib が作成したウィンドウのことを「クライアント側通信ウィンドウ」と呼び、IM サーバが作成したウィンドウのことを「IMS 側通信ウィンドウ」と呼ぶことにする。

接続

接続を確立するために通信ウィンドウを１つ作成する。下表のイベント形式を持つ ClientMessage が XIM_SERVERS セレクション(訳註：原文は「XIM_SERVER」)の所有者ウィンドウへ送信される。このセレクションは IM サーバが作成したものである。

アトム XIM_SERVERS (訳註：原文は「XIM_SERVER」)については「The Input Method Protocol」(訳註：この HTML 文書の主部)を参照。

表 D.1. IMS ウィンドウへ送信される ClientMessage

構造体のメンバ | 内容
--- | ---
int | type | ClientMessage
u_long | serial | X ウィンドウ・システムが設定
Bool | send_event | X ウィンドウ・システムが設定
Display | *display | 接続するディスプレイ
Window | window | IMS Window ID
Atom | message_type | XInternAtom(display, "_XIM_XCONNECT", False)
int | format | 32
long | data.l[0] | クライアント側通信ウィンドウの ID
long | data.l[1] | client-major-transport-version (*1)
long | data.l[2] | client-major-transport-version (*1)

接続を確立するために(IM サーバ側通信ウィンドウを知らせるために)、IM サーバは下表のイベント形式の ClientMessage をクライアント側通信ウィンドウへ送信する。

表 D.2. IM サーバが送信する ClientMessage

構造体のメンバ | 内容
--- | ---
int | type | ClientMessage
u_long | serial | X Window System が設定
Bool | send_event | X Window System が設定
Display | *display | 接続するディスプレイ
Window | window | クライアント側通信ウィンドウの ID
Atom | message_type | XInternAtom(display, "_XIM_XCONNECT", False)
int | format | 32
long | data.l[0] | IMS 側通信ウィンドウの ID
long | data.l[1] | server-major-transport-version (*1)
long | data.l[2] | server-minor-transport-version (*1)
long | data.l[3] | ClientMessage と Property とを見分けるための閾値 (*2)

(*1) 以下「major/minor-transport-version」について述べる。

読み書きの方法(read/write method：データの受け渡しの方法)は、major-transport-version と minor-transport-version の組み合わせによって、次の表のように定まる。

表 D.3. 読み書きの方式(read/write method)と major/minor-transport-version の関係

Transport-version | read/write (データの受け渡し)の方式
--- | ---
major(上位) | minor(下位) |
0 | 0 | only-CM & Property-with-CM
1 | only-CM & multi-CM
2 | only-CM & multi-CM & Property-with-CM
1 | 0 | PropertyNotify
2 | 0 | only-CM & PropertyNotify
1 | only-CM & multi-CM & PropertyNotify

only-CM | ： | データは ClientMessage １つを使って送られる
multi-CM | ： | データは複数の ClientMessage を使って送られる
Property-with-CM | ： | データはプロパティに書き込まれ、同プロパティのアトムが ClientMessage 経由で送られる
PropertyNotify | ： | データはプロパティに書き込まれ、同プロパティのアトムが PropertyNotify 経由で送られる

major/minor-transport-version を決める手順は以下の通り。

- クライアントは IM サーバに対し major-transport-version 及び minor-transport-version として 0 を送る。クライアントは、表 D-3 に挙げた方式全てに対応していなければならない。クライアントは将来、上に挙げたもの以外の方式を使用するために、major-transport-version あるいは minor-transport-version として別の数値を送ることができるかもしれない。

- IM サーバは、自身の major-transport-version 及び minor-transport-version の数値をクライアントへ送る。クライアントは、IM サーバが指定した方式を用いてデータを送信する。

- major-transport-version と minor-transport-version の数値が取得できない場合は、取得できなかったものの値は 0 であると見做す。

(*2) 以下「ClientMessage と Property とを見分けるための閾値」について述べる。

データが multi-CM (複数の ClientMessage)とプロパティの両方を使って送られて来る場合、ClientMessage とプロパティを見分けるための閾値を指定する。データのサイズがこの閾値より小さければ、そのデータは multi-CM (あるいは only-CM)経由で送られて来るものである。また、データのサイズがこの閾値より大きければ、同データはプロパティ経由で送られて来るものである。

read/write (読み書きの方式)

X ウィンドウ・システムにおいては、データは ClientMessage またはウィンドウ・プロパティを使って転送される。

以下、クライアントから IM サーバへ向かうデータの形式について述べる。

ClientMessage の形式

データが ClientMessage イベントを通じて送られる場合、同イベントの形式は次の表の通りである。

表 D.4. ClientMessage イベントの形式 (最初もしくは中間のものの場合)

構造体のメンバ | 内容
--- | ---
int | type | ClientMessage
u_long | serial | X ウィンドウ・システムが設定
Bool | send_event | X ウィンドウ・システムが設定
Display | *display | 接続するディスプレイ
Window | window | IMS 側通信ウィンドウの ID
Atom | message_type | XInternAtom(display, "_XIM_MOREDATA", False)
int | format | 8
char | data.b[20] | (受け渡されるデータread/write DATA : 20 byte)

表 D.5. ClientMessage イベントの形式 (１つだけの場合もしくは最後のものの場合)

構造体のメンバ | 内容
--- | ---
int | type | ClientMessage
u_long | serial | X ウィンドウ・システムが設定
Bool | send_event | X ウィンドウ・システムが設定
Display | *display | 接続するディスプレイ
Window | window | IMS 側通信ウィンドウの ID
Atom | message_type | XInternAtom(display, "_XIM_PROTOCOL", False)
int | format | 8
char | data.b[20] | (受け渡されるデータread/write DATA : MAX 20 byte) (*1)

(*1) データの大きさが２０バイトより小さい場合、データの中の利用可能な箇所以外の部分は 0 でなければならない。

プロパティの形式

大きなデータの場合、効率を考えてデータはウィンドウ・プロパティ経由で送ることになる。プロパティを知らせる方法には次の２つのものがあり、transport-version によってどちらの方法を使うのかが決まる。

- 関数 XChangeProperty を用いてクライアント側通信ウィンドウにデータを格納し、格納したデータのアトム(訳註：データを格納したプロパティのアトム)を ClientMessage イベント経由で IM サーバに通知する。

- 関数 XChangeProperty を用いてクライアント側通信ウィンドウにデータを格納し、格納したデータのアトム(訳註：データを格納したプロパティのアトム)を PropertyNotify イベント経由で IM サーバに通知する。

この XChangeProperty の引数は次の通り。

表 D.6. XChangeProperty のリクエストの形式

引数 | 内容
--- | ---
Display | *display | 接続するディスプレイ
Window | window | IMS 側通信ウィンドウの ID
Atom | property | 読み書きを行うプロパティのアトム (*1)
Atom | type | XA_STRING
int | format | 8
int | mode | PropModeAppend
u_char | *data | 受け渡される DATA
int | nelements | DATA の長さ

(*1) 読み書きを行うプロパティのアトム(read/write property ATOM)は、次のような文字列に対して `XInternAtom` を使用することで割り当てられる。

「_clientXXX」

クライアントは引数 mode に PropModeAppend を指定してプロパティの変更を行い、IM サーバは削除モード(即ち delete = True)(訳註：XGetWindowProperty の引数 delete に True を指定)でこのプロパティを読み込む。

アトムが ClientMessage イベント経由で通知された場合の ClientMessage の形式は次の通り。

表 D.7. プロパティのアトムを送るための ClientMessage イベントの形式

構造体のメンバ | 内容
--- | ---
int | type | ClientMessage
u_long | serial | X ウィンドウ・システムが設定
Bool | send_event | X ウィンドウ・システムが設定
Display | *display | 接続するディスプレイ
Window | window | IMS 側通信ウィンドウの ID
Atom | message_type | XInternAtom(display, "_XIM_PROTOCOL", False)
int | format | 32
long | data.l[0] | 読み書きを行うプロパティのアトムの長さ
long | data.l[1] | 読み書きを行うプロパティのアトム

以下、IM サーバからクライアントへ向かうデータの形式について述べる。

ClientMessage の形式

ClientMessage の形式は次の通り。

表 D.8. ClientMessage イベントの形式 (最初もしくは中間のものの場合)

構造体のメンバ | 内容
--- | ---
int | type | ClientMessage
u_long | serial | X ウィンドウ・システムが設定
Bool | send_event | X ウィンドウ・システムが設定
Display | *display | 接続するディスプレイ
Window | window | クライアント側通信ウィンドウの ID
Atom | message_type | XInternAtom(display, "_XIM_MOREDATA", False)
int | format | 8
char | data.b[20] | (受け渡されるデータread/write DATA : 20 byte)

表 D.9. ClientMessage イベントの形式 (１つだけの場合もしくは最後のものの場合)

構造体のメンバ | 内容
--- | ---
int | type | ClientMessage
u_long | serial | X ウィンドウ・システムが設定
Bool | send_event | X ウィンドウ・システムが設定
Display | *display | 接続するディスプレイ
Window | window | クライアント側通信ウィンドウの ID
Atom | message_type | XInternAtom(display, "_XIM_PROTOCOL", False)
int | format | 8
char | data.b[20] | (受け渡されるデータread/write DATA : MAX 20 byte) (*1)

(*1) データの大きさが２０バイトより小さい場合、データの中の利用可能な箇所以外の部分は 0 でなければならない。

プロパティの形式

大きなデータの場合、効率を考えてデータはウィンドウ・プロパティ経由で送ることになる。プロパティを知らせる方法には次の２つのものがあり、transport-version によってどちらの方法を使うのかが決まる。

- 関数 XChangeProperty を用いて IMS 側通信ウィンドウ(のプロパティ)にデータを格納し、このプロパティのアトムを ClientMessage イベント経由で送信する(訳註：クライアントへ送信する)。

- 関数 XChangeProperty を用いて IMS 側通信ウィンドウ(のプロパティ)にデータを格納し、このプロパティのアトムを PropertyNotify イベント経由で送信する(訳註：クライアントへ送信する)。

この XChangeProperty の引数は次の通り。

表 D.10. XChangeProperty リクエストの形式

引数 | 内容
--- | ---
Display | *display | 接続するディスプレイ
Window | window | クライアント側通信ウィンドウの ID
Atom | property | 読み書きを行うプロパティのアトム (*1)
Atom | type | XA_STRING
int | format | 8
int | mode | PropModeAppend
u_char | *data | 受け渡される DATA
int | nelements | DATA の長さ

(*1) 読み書きを行うプロパティのアトムの割り当てには何らかの文字列を必要とするが、この文字列からアトムを割り当てる作業はクライアントによって行われるのではなく、`XInternAtom` によって行われる。(原文：The read/write property ATOM allocates some strings, which are not allocated by the client, by XInternAtom. 訳註：XInternAtom は指定された文字列を使って３２ビットの識別子を割り当てる。原文の意味がいまひとつ理解できない。)

IM サーバは引数 mode に PropModeAppend を指定してプロパティの変更を行い、クライアントは削除モード(即ち delete = True)(訳註：XGetWindowProperty の引数 delete に True を指定)でこのプロパティを読み込む。

アトムが ClientMessage イベント経由で通知された場合の ClientMessage の形式は次の通り。

表 D.11. プロパティのアトムを送るための ClientMessage イベントの形式

構造体のメンバ | 内容
--- | ---
int | type | ClientMessage
u_long | serial | X ウィンドウ・システムが設定
Bool | send_event | X ウィンドウ・システムが設定
Display | *display | 接続するディスプレイ
Window | window | クライアント側通信ウィンドウの ID
Atom | message_type | XInternAtom(display, "_XIM_PROTOCOL", False)
int | format | 32
long | data.l[0] | 読み書きを行うプロパティのアトムの長さ
long | data.l[1] | 読み書きを行うプロパティのアトム

接続を閉じる

クライアントが IM サーバとの接続を断つ場合、終了関数(shutdown function)は通信ウィンドウのプロパティの解放その他の作業を行うものとする。

入り口に戻る