ここでは、M17N データベースで提供される各データのフォーマットを解説す る。
関数 mdatabase_load() は、第一タグが Mchartable か Mcharset で ない限り、タグで指定されたデータをプロパティリストの形で返す。返される プロパティリストのキーはMinteger, Msymbol, Mtext, Mplist に限る。値の型はキーによって曖昧性なく 決定される。キーが Minteger ならば値は整数値であり、キーが Msymbol なら値はシンボル、Mtext ならば M-text、 Mplist ならばプロパティリストである。
プロパティリストを示すためにはさまざまな表現形式が可能である。たとえば (K1:V1, K2:V2, ..., Kn:Vn) という形で、最初のK1 と V1、二つ目 のキーと値がK2 と V2 といったプロパティリストを表現することもできる。 しかし、m17n データベースで用いられるプロパティリストのタイプはかなり 限定されているので、もっと単純な表現形式を用いることができる。
これ以降、プロパティリストの示すためには S 式に類似した表現を用いる。 (実際 m17n ライブラリのデフォルトのデータベースローダはこの表現で書か れたデータファイルを読むように設計されている。)
この表現形式は 1 ないしそれ以上の 要素 (element) からなる。個々 の要素はプロパティすなわちプロパティリストの一つの要素を表す。
要素間は 1 ないしそれ以上の 空白 (whitespace) すなわちスペース (code 32)、タブ (code 9)、改行 (code 10) のいずれかで区切られる。セミ コロン(;) で始まる行はコメントである。
各プロパティのキーと値は、要素のタイプに基づいて以下のように決定される。
整数
正規表現-?[0-9]+ または0[xX][0-9A-Fa-f]+ に合致する 要素は、キーがMintegerであるプロパティを示す。最初の正規表現 と合致するものは 10 進の整数、後の正規表現と合致するものは 16 進の整数 と解釈し、その解釈の結果がプロパティの値である。
たとえば、要素 0xA0 は10 進で 160 を値とするプロパティである。
シンボル
正規表現[^-0-9(]([^\()]|\.)+ に合致する要素は、キーが Msymbolであるプロパティを示す。要素中の \t, \n, \r, \e はそれぞれ、タブ (code 9)、改 行 (code 10)、復帰(code 13)、エスケープ (code 27) に置き換えられる。バッ クスラッシュに続く他の文字はそれ自身と解釈される。プロパティの値は、結 果として得られる文字列を名前として持つシンボルである。
たとえば、要素 abc\ def は "abc def" を名前として持つシンボル を値とするプロパティである。
MTEXT
正規表現 "([^"]|\")*" に合致する要素は、キー Mtext であるプロパティを示す。上記のバックスラッシュによるエスケープはここで も有効である。さらに、要素中の正規表現 \[xX][0-9A-Fa-f][0-9A-Fa-f] に合致する部分は、16進で解釈した 結果に置き換えられる。
バックスラッシュエスケープを処理した上で、ダブルクオートにはさまれたバ イト列をUTF-8 列として解釈し、M-text にデコードする。この M-text がプ ロパティの値である。
PLIST
対応する括弧にはさまれた 0 個以上の要素はMplist をキーとする プロパティを示す。括弧の前後の空白は取り除かれる。プロパティの値は、プ ロパティリストであり、その括弧内の各要素を再帰的に解釈した結果である。
データのプロパティリストフォーマットの説明では、BNF風の記法が用いられ る。この記法では、非終端は大文字(間に'-'が入ってもよい) で、終端は " で囲って表される。特別な非終端 INTEGER, SYMBOL, MTEXT, PLIST はそれぞれ対応するプロパティを意味する。
次の単純な形式のプロパティリストに読み込まれる、データベースのデータの 一例を示す:
DATA-FORMAT ::=
[ INTEGER | SYMBOL | MTEXT | FUNC ] *
FUNC ::=
'(' FUNC-NAME FUNC-ARG * ')'
FUNC-NAME ::=
SYMBOL
FUNC-ARG ::=
INTEGER | SYMBOL | MTEXT | '(' FUNC-ARG ')'
たとえば、次のテキストを含むデータファイルは上の文法に合致する:
abc 123 (pqr 0xff) "m\"text" (_\\_ ("string" xyz) -456)
そして次のようなプロパティリストとして読み込まれる:
第1要素: キー: Msymbol, 値: abc
第2要素: キー: Minteger, 値: 123
第3要素: キー: Mplist, 値: 次の要素からなるプロパティリスト
第1要素: キー Msymbol, 値: pgr
第2要素: キー Minteger, 値: 255
第4要素: キー: Mtext, 値: m"text
第5要素: キー: Mplist, 値: 次の要素からなるプロパティリスト
第1要素: キー: Msymbol, 値: _\_
第2要素: キー: Mplist, 値: 次の要素からなるプロパティリスト
第1要素: キー: Mtext, 値: string
第2要素: キー: Msymbol, 値: xyz
第3要素: キー: Minteger, 値: -456
m17n ライブラリは、m17nデータベースのタグ<charset-list>のついたデータ から、文字セット定義のリストをロードする。このデータは以下のフォーマッ トのプロパティリストとしてロードされる。
CHARSET-LIST ::= DEFINITION *
DEFINITION ::= '(' NAME ( KEY VALUE ) * ')'
NAME ::= SYMBOL
KEY ::= SYMBOL
VALUE ::= SYMBOL | INTEGER | MTEXT | PLIST
NAME は定義する文字セットの名前である。
KEY と VALUE のペアは、関数 mchar_define_charset() に2番目の引 数 plist の各要素として与えられるプロパティである。
mdbGeneral(5), mchar_define_charset()
m17n ライブラリは、初期化の際 m17n データベースのタグ <coding-list> のついたデータからコード系定義のリストをロードする。このデータは以下の フォーマットのプロパティリストとしてロードされる。
CODING-LIST ::= DEFINITION *
DEFINITION ::= '(' NAME ( KEY VALUE ) * ')'
NAME ::= SYMBOL
KEY ::= SYMBOL
VALUE ::= SYMBOL | INTEGER | MTEXT | PLIST
NAME は定義するコード系の名前である。
KEY と VALUE のペアは、関数 mchar_define_coding() に2番目の引 数として与えられるプロパティである。
mdbGeneral(5), mconv_define_coding()
m17n ライブラリは初期化の際、m17n データベース中のデータ定義のリストを 各データベースディレクトリ中の "mdb.dir" という名前を持つファイルからロー ドする。このファイルにおけるプロパティリストのフォーマットは以下である。
MDB-DIR ::= DEFINITION *
DEFINITION ::= '(' TAG0 [ TAG1 [ TAG2 [ TAG3 ] ] ] FILE [ VERSION ]')'
TAGn ::= SYMBOL
FILE ::= MTEXT
VERSION ::= MTEXT
TAG0 が `charset' でも `char-table' でもなく、TAGn (n > 0) がシンボル `*' ならば、FILE にワイルドカードが含まれて良い。そしてシェルが用いる規 則によって FILE とマッチするすべてのファイルがデータベースファイルのター ゲットとなる。この際、各ファイルは実際の TAGn の値を与える SELF-DEFINITION を持たなくてはならない。SELF-DEFINITION は以下の形式の プロパティリストの要素である。
SELF-DEFINITION ::= '(' TAG0 TAG1 TAG2 TAG3 [ VERSION ] ')'
たとえば、データベースディレクトリが下のファイルを含むとしよう。
zh-py.mim: (input-method zh py) ... ko-han2.mim: (input-method ko han2) ...
この時 "mdb.dir" 中の以下の行
(input-method zh py "zh-py.mim") (input-method ko han2 "ko-han2.mim")
はこの一行に短縮できる。
(input-method * "*.mim")
VERSION は 最低必要な m17n ライブラリのバージョン番号を示す。フォー マットは "XX.YY.ZZ" であり、XX はメジャーバージョン番号、YY はマイナー バージョン番号、ZZ はパッチレベルである。
単純なスクリプトの場合、表示エンジンは選択したフォントのエンコーディン グに応じて文字コードをグリフコードに一文字ずつ変換する。しかし、複雑な レイアウトを要求する文書、たとえばタイやインド系のスクリプトなどの場合、 1対1の変換では不十分である。複数の文字が一つのリガチャとして描かれたり、 2次元的にずらした位置に描かなくてはならないグリフがあったりする。
このような複雑なスクリプトを処理するため、m17n ライブラリはフォントレ イアウトテーブル (短縮して FLT と呼ぶことにする) を用いる。FLT ドライ バは FLT を解釈し、文字列を表示エンジンに渡すことのできるグリフ列に変 換する。
FLT は OpenType Layout Table に見られる情報 (CMAP, GSUB, and GPOS) に 加えて、文字列から書記素 (grapheme) クラスタを抽出したり、クラスタ内で 文字を並べ変えたりするための情報を持つことができる。
FLT は 1 つ以上の変換ステージが続いたものである。各ステージでコード列 は別のものに変換され、次のステージに読まれる。列の長さはステージ毎に異 なることがある。コード列の各要素は以下の整数値の属性を持つ。
コード
変換の最初のステージでは、元の文字列の文字コード。最後のステージでは、 表示エンジンに渡されるグリフコード。それ以外では中間的なグリフコード。
カテゴリ
そのステージの CATEGORY-TABLE で定義されたか、以前のステージで定義さ れ上書きされていないカテゴリーコード。
結合規則
0 でなければ、この(中間)グリフを前のものとどう結合するかを指定する。
左パディングフラグ
0 でなければ、表示関数にこの(中間)グリフの前にスペースを挿入して、前 のグリフと重ならないようにするよう指示する。
右パディングフラグ
0 でなければ、表示関数にこの(中間)グリフの後にスペースを挿入して、後 のグリフと重ならないようにするよう指示する。
レイアウトエンジンがテキストを描く際には、まずテキストの各文字に対して それぞれフォントとFLT を決定する。同じフォントと FLT を用いる部分文字列 に関して、レイアウトエンジンは対応する中間的なグリフの列を生成する。中 間的なグリフコードの各要素は、コードの属性として対応する文字コード、他 の属性として 0 を持つ。この列はFLT の最初のステージで現行の ラン (部 分列) として処理される。
各ステージは以下のように働く。
まずこのステージに CATEGORY-TABLE があれば、現行のランのすべてのグ リフのカテゴリが更新される。カテゴリの無いグリフがあれば、ランはそのグ リフの前で終る。
次にこのステージのコードオフセット、結合規則、左パディングフラグが 0 に初期化される。
次いで、このステージの最初の変換規則が現行のランに適用される。
最後に現行のランは新しく作られた(中間)グリフ列に置き換えられる。
m17n ライブラリ は m17n データベースからタグ <font, layouter, FLT-NAME> を用いて FLT をロードする。FLT のデータのフォーマットは以下の通り:
FONT-LAYOUT-TABLE ::= FLT-DECLARATION ? STAGE0 STAGE *
FLT-DECLARATION ::= '(' 'font' 'layouter' NAME nil PROP * ')'
NAME ::= SYMBOL
PROP :: = VERSION | FONT
VERSION ::= '(' 'version' MTEXT ')'
FONT ::= '(' 'font' FONT-SPEC ')'
FONT-SPEC ::=
'(' [[ FOUNDRY FAMILY
[ WEIGHT [ STYLE [ STRETCH [ ADSTYLE ]]]]]
REGISTRY ]
[ OTF-SPEC ] [ LANG-SPEC ] ')'
STAGE0 ::= CATEGORY-TABLE GENERATOR
STAGE ::= CATEGORY-TABLE ? GENERATOR
CATEGORY-TABLE ::= '(' 'category' CATEGORY-SPEC + ')'
CATEGORY-SPEC ::= '(' CODE CATEGORY ')'
| '(' CODE CODE CATEGORY ')'
CODE ::= INTEGER
CATEGORY ::= INTEGER
CATEGORY-SPEC の定義中で、 CODE はグリフコード CATEGORY は大 文字あるいは小文字の ASCII code、すなわち 'A', ... 'Z', 'a', .. 'z' の いずれかである。
CATEGORY-SPEC の最初の形式は、CATEGORY をコード CODE を持つグ リフに割り当て、二つ目の形式は CATEGORY を二つの CODE の間のコー ドを持つグリフに割り当てる。
GENERATOR ::= '(' 'generator' RULE MACRO-DEF * ')'
RULE ::= REGEXP-BLOCK | MATCH-BLOCK | SUBST-BLOCK | COND-BLOCK
FONT-FACILITY-BLOCK | DIRECT-CODE | COMBINING-SPEC | OTF-SPEC
| PREDEFINED-RULE | MACRO-NAME
MACOR-DEF ::= '(' MACRO-NAME RULE + ')'
各 RULE は、消費するグリフと生成するグリフを指定する。「消費された」 グリフは現行のランから取り除かれる。ルールは状況によっては失敗する。明 示的に失敗と書かれている場合をのぞき、成功とみなす。
DIRECT-CODE ::= INTEGER
このルールはグリフを消費せず、以下の属性を持つグリフを生成する。
INTEGER にデフォルトのコードオフセットを足したもの グリフ生成後、デフォルトのコードオフセット、結合規則, 左パディングフラ グ はすべて 0 にリセットされる。
PREDEFINED-RULE ::= '=' | '*' | '<' | '>' | '|' | '[' | ']'
これらは以下のように働く。
=
現行のランの最初のグリフを消費し、同じグリフを生成する。現行のランが空 ならば失敗する。
*
前のルールを繰り返し実行する。前のルールが失敗すれば、何もせず失敗する。
<
書記素クラスタの始めを示す。
>
書記素クラスタの終りを示す。
@[
この規則はデフォルトの左パディングフラグを 1 にする。グリフの消費や生 成はしない。
@]
この規則は最近生成されたグリフの右パディングフラグを 1 にする。グリフ の消費や生成はしない。
|
グリフを消費せず、カテゴリが ' ' で他の属性が 0 である特別なグリフを生 成する。この規則だけがこの特別なグリフを生成する。
REGEXP-BLOCK ::= '(' REGEXP RULE * ')'
REGEXP ::= MTEXT
MTEXT は現行のランのカテゴリ列に合致すべき正規表現である。合致すれ ば、この規則は一時的に現行のランを合致した部分だけに限定した上で、RULE を実行する。合致した部分はこの規則によって消費される。
括弧のついた部分表現があれば、RULE の中に出現するかもしれない MATCH-BLOCK によって使用するために記録される。
合致する部分が無ければ、この規則は失敗する。
MATCH-BLOCK ::= '(' MATCH-INDEX RULE * ')'
MATCH-INDEX ::= INTEGER
MATCH-INDEX は直前の REGEXP-BLOCK によって記録された部分表現を指 定する整数である。このような部分表現があれば、この規則は一時的に現行の ランを合致した部分表現だけに限定した上で、RULE を実行する。合致した 部分はこの規則によって消費される。
合致する部分が無ければ、この規則は失敗する。
この規則がステージの最初の規則である場合は、MATCH-INDEX は 0 でなく てはならない。この場合ラン全体に合致することになる。
SUBST-BLOCK ::= '(' SOURCE-PATTERN RULE * ')'
SOURCE-PATTERN ::= '(' CODE + ')'
| (' 'range' CODE CODE ')'
現行のランのコード列が SOURCE-PATTERN と合致すれば、この規則は一時 的に現行のランを合致した部分だけに限定した上で、RULE を実行する。 合致した部分は消費される。
SOURCE-PATTERN の最初の形式は、合致するグリフコードの列を指定する。 この場合、この規則はデフォルトのコードオフセットを 0 にリセットする。
二つめの形式は、コード列の最初のグリフコードの範囲を指定する。この場合、 この規則はデフォルトのコードオフセットを最初のグリフコードから範囲を指 定する初めの CODE を引いたものに設定する。
合致する部分が無ければ、この規則は失敗する。
FONT-FACILITY-BLOCK ::= '(' FONT-FACILITY RULE * ')'
FONT-FACILITY = '(' 'font-facility' CODE * ')'
| '(' 'font-facility' FONT-SPEC ')'
現在のフォントが CODE のグリフを持っているか、FONT-SPEC と合致す れば、この規則は成功し、RULE を実行する。そうでなければ、この規則は 失敗する。
COND-BLOCK ::= '(' 'cond' RULE + ')'
この規則は RULE を順に、どれかが成功するまで実行する。どのルールも 成功しなければ、この規則は失敗する。そうでなければ成功である。
OTF-SPEC ::= SYMBOL
OTF-SPEC は、OTF ドライバへの指示を指定する名前を持つシンボルである。 名前は以下の文法に従う。
OTF-SPEC-NAME ::= ':otf=' SCRIPT LANGSYS ? GSUB-FEATURES ? GPOS-FEATURES ? SCRIPT ::= SYMBOL LANGSYS ::= '/' SYMBOL GSUB-FEATURES ::= '=' FEATURE-LIST ? GPOS-FEATURES ::= '+' FEATURE-LIST ? FEATURE-LIST ::= ( SYMBOL ',' ) * [ SYMBOL | '*' ]
各 SYMBOL は OpenType specification 中でのタグ名を指定する。
SCRIPT については、SYMBOL はスクリプトタグ名を表す。(Devanagari は deva など。)
LANGSYS の場合は、SYMBOL は言語システムタグ名を指定する。LANGSYS が省略されれば、デフォルトの言語システムテーブルが使用される。
GSUB-FEATURES では、 FEATURE LIST 中の各 SYMBOL は 適用する GSUB feature タグ名を指定する。'*' は残りすべての feature を指定するた めに最後の要素として用いることができる。 SYMBOL の前に'~' がついて おり、最後の要素が '*' ならば、SYMBOL は適用するfeature から除かれ る。SYMBOL が指定されていなければ、GSUB feature は適用されない。GSUB-FEATURES 自体が省略されればすべての GSUB feature が適用される。
GPOS-FEATURES の指定は GSUB-FEATURES の場合と同様である。
全てのタグ名は ASCII の表示可能文字4つからなること。
OpenType の指定方法については次のページを参照のこと。
<http://www.microsoft.com/typography/otspec/default.htm>
COMBINING ::= SYMBOL
COMBINING は、 次のグリフを前のものとどう結合するかの指示を名前とし て持つシンボルである。このルールはデフォルトの結合規則をシンボル名固有 の整数コードにセットする。名前は以下の文法に従う。
COMBINING-NAME ::= VPOS HPOS OFFSET VPOS HPOS
VPOS ::= 't' | 'c' | 'b' | 'B'
HPOS ::= 'l' | 'c' | 'r'
OFFSET :: = '.' | XOFF | YOFF XOFF ?
XOFF ::= ('<' | '>') INTEGER ?
YOFF ::= ('+' | '-') INTEGER ?
VPOS と HPOS は次のように垂直、水平位置を指定する。
POINT VPOS HPOS
----- ---- ----
0----1----2 <---- top 0 t l
| | 1 t c
| | 2 t r
| | 3 B l
9 10 11 <---- center 4 B c
| | 5 B r
--3----4----5-- <-- baseline 6 b l
| | 7 b c
6----7----8 <---- bottom 8 b r
9 c l
| | | 10 c c
left center right 11 c r
左の図はあるグリフの 12 の参照点を 0 から 11 までの数字で示している。 四角形 0-6-8-2 はグリフの表示領域であり、位置3, 4, 5 はベースライン上 にある。 9 と 11 はそれぞれ線0-6 と 2-8 の中心である。1, 10, 4, 7 はそ れぞれ線1-2, 3-5, 9-11, 6-8 の中心である。
右の表は、各参照点がVPOS と HPOS の組合せによってどのように指定 されるかを示している。
COMBINING-NAME の定義中の最初の VPOS と HPOS は、前のグリフの 参照点を、二つ目の VPOS と HPOS は次のグリフの参照点を指定する。 次のグリフはこの二個の参照点が重なるように描かれる。
OFFSET は重なりか他の詳細を指定する。'.' であれば、参照点二つは同じ 位置にある。
XOFF は、次のグリフの参照点の X 座標を、前の参照点からどれほど右 ('<') あるいは左 ('>') へずらすか指定する。
YOFF は、次のグリフの参照点の Y 座標を、前の参照点からどれほど上 ('+') あるいは下 ('-') へずらすか指定する。
どちらの場合にも、INTEGER はフォントサイズの何%ずらすかを示す値で ある。すなわち、もし INTEGER が 10 ならばフォントサイズの10% (1/10) ずらすことになる。 INTEGER が省略された場合には、5 が指定されたもの とする。
次のグリフが前のグリフに結合されると、それらは一つの結合グリフとして扱 われる。
MACRO-NAME ::= SYMBOL
MACRO-NAME は MACRO-DEF のいずれかに現われるシンボルであり、対応 するRULE の列に展開される。
ここまでは、特定のフォントで描かれる各文字/グリフ列が文脈自由であるこ と、すなわち前後のグリフに影響されないことを前提としてきた。これは、列 S1 がフォントF1 によって描かれ、先行する列 S0 が常にフォント F0 を要求 する場合には正しい。
列 S0 S1 現行のフォント F0 F1 利用可能なフォント F0 F1
しかし時には、列を明確に区切ることができない場合もある。先行する列 S0 が F0 だけでなく F1 でも描けるとしよう。
列 S0 S1 現行のフォント F0 F1 利用可能なフォント F0,F1 F1
この場合、先行する S0 を描くために使われたグリフが S1 のグリフの生成に 影響を与えることもある。そこで S1 の処理の際にすでに処理の終った S0 に 関する情報にアクセスする必要がある。最初のステージ(このステージのみ) の生成規則は、処理済みの部分へアクセスする特別な正規表現を許している。
"RE0 RE1"
RE0 と RE1 は先行の列 S0 と後続の列 S1 にそれぞれ対応する正規表 現である。
二つの正規表現の間のスペースに注意。これは特別なカテゴリ ' ' を示して いる (上記参照) 。この正規表現はフォント F1 を使用するグリフ生成規則に 属しており、したがって RE1 だけでなくRE0 も F1 用のカテゴリを用いて表 現されなければならない。つまり、先行する列S0 が F1 用のカテゴリで表せ ない場合には(上の最初の例のように) このパターンを持つ生成規則には合致 しない。
mdbGeneral(5), FLTs provided by the m17n database
m17n ライブラリは、m17n データベースから <font, encoding> タグによっ て個々のフォントのエンコーディングに関する情報をロードする。このデータ は以下のフォーマットのプロパティリストとしてロードされる。
FONT-ENCODING ::= PER-FONT *
PER-FONT ::= '(' FONT-SPEC ENCODING [ REPERTORY ] ')'
FONT-SPEC ::=
'(' [ FOUNDRY FAMILY
[ WEIGHT [ STYLE [ STRETCH [ ADSTYLE ]]]]]
REGISTRY ')'
ENCODING ::= SYMBOL
FONT-SPEC はフォントのプロパティを指定する。FOUNDRY から REGISTRY はフォントの Mfoundry から Mregistry プロパティに対応するシ ンボルである。各プロパティの意味については フォント 参照。
たとえばこの FONT-SPEC:
(nil alice0\ lao iso8859-1)
はフォントのファミリ名が "alice0 lao" でレジストリが "iso8859-1" であ るすべてのフォントに適用できる。
ENCODING は文字セットを示すシンボルである。FONT-SPEC に合致する フォントは、その文字セットの全文字をサポートし、その文字セットによって 文字コードはそのフォントの対応するグリフコードにマップされる。
REPERTORY は文字セットを示すシンボルか "nil" である。省略した場合は、 ENCODING を REPERTORY に指定したのと同じ意味になる。"nil" でなけ れば、文字セットはフォントのレパートリ、すなわちサポートする文字を示す。 そうでなければ、特定の文字がそのフォントでサポートされているかどうかは 個々のフォントドライバに問い合わせる。
いわゆるユニコードフォント (レジストリは "iso10646-1") については、普 通ユニコード文字の一部しかサポートしていないため、REPERTORY を "nil" にすることが望ましい。
In some case, a font contains incorrect information about its size (typically in the case of a hacked TrueType font), which results in a bad text layout when such a font is used in combination with the other fonts. To overcome this problem, the m17n library loads information about font-size adjustment from the m17n database by the tags <font, resize>. The data is loaded as a plist of this format.
FONT-SIZE-ADJUSTMENT ::= PER-FONT *
PER-FONT ::= '(' FONT-SPEC ADJUST-RATIO ')'
FONT-SPEC ::=
'(' [ FOUNDRY FAMILY
[ WEIGHT [ STYLE [ STRETCH [ ADSTYLE ]]]]]
REGISTRY ')'
ADJUST-RATIO ::= INTEGER
FONT-SPEC is to specify properties of a font. FOUNDRY to REGISTRY are symbols corresponding to Mfoundry to Mregistry property of a font. See フォント for the meaning of each property.
ADJUST-RATIO is an integer number specifying by percentage how much the font-size must be adjusted. For instance, this PER-FONT:
((devanagari-cdac) 150)
instructs the font handler of the m17n library to open a font of 1.5 times bigger than a requested size on opening a font whose registry is "devanagari-cdac".
m17n ライブラリは、m17n データベースから <fontset, FONTSET-NAME> タ グによってフォントセットの定義をロードする。このデータは以下のフォーマッ トのプロパティリストとしてロードされる。
FONTSET ::= PER-SCRIPT * PER-CHARSET * FALLBACK *
PER-SCRIPT ::= '(' SCRIPT PER-LANGUAGE + ')'
PER-LANGUAGE ::= '(' LANGUAGE FONT-SPEC-ELEMENT + ')'
PER-CHARSET ::= '(' CHARSET FONT-SPEC-ELEMENT + ')'
FALLBACK ::= FONT-SPEC-ELEMENT
FONT-SPEC-ELEMENT ::= '(' FONT-SPEC [ FLT-NAME ] ')'
FONT-SPEC ::=
'(' [ FOUNDRY FAMILY
[ WEIGHT [ STYLE [ STRETCH [ ADSTYLE ]]]]]
REGISTRY ')'
SCRIPT はスクリプト名 (e.g. latin, han) を示すシンボルか nilであ る。LANGUAGE はISO 639 に定義された言語名コード (e.g. ja, zh) であ る2文字のシンボルか nil である。
FONT-SPEC はフォントのプロパティを指定する。FOUNDRY から REGISTRY はフォントの Mfoundry から Mregistry プロパティに対応するシ ンボルである。各プロパティの意味については フォント 参照。
FLT-NAME はフォントレイアウトテーブルの名前である。(フォントレイアウトテーブル).
これは PER_SCRIPT の例である。
(han
(ja
((jisx0208.1983-0)))
(zh
((gb2312.1980-0)))
(nil
((big5-0))))
これによってフォントセレクタは、"han" 文字 (つまりMscript プロパティ が 'han' である文字)のうち、文字の M-text 中での Mlanguage テキストプ ロパティが "ja" でありその文字がフォントのレパートリーに含まれていれも のについては、レジストリが"jisx0208.1983-0" であるフォントを使うことを 指示される。そうでなければ、レジストリが "gb2312.1980-0" や"big5-0" で あるものが試される。"han" 文字に Mlanguage テキストプロパティが無けれ ば、3つとも試される。
フォント選択の詳細については関数 mdraw_text() 参照。
m17n ライブラリは、m17n データベースから動的にロードできる入力メソッド ドライバを提供している。(入力メソッド (基本部分) 参照。 ).
ここでは入力メソッド定義のデータフォーマットを説明する。
以下のデータフォーマットによって入力メソッドが定義される。ドライバはファ イルやストリームから定義をロードし、プロパティリストの形式に変換する。
INPUT-METHOD ::=
IM-DECLARATION ? DESCRIPTION ? TITLE ?
VARIABLE-LIST ? COMMAND-LIST ? MODULE-LIST ?
MACRO-LIST ? MAP-LIST ? STATE-LIST ?
IM-DECLARATION ::= '(' 'input-method' LANGUAGE NAME EXTRA-ID ? VERSION ? ')'
VERSION ::= '(' 'version' VERSION-NUMBER ')'
DESCRIPTION ::= '(' 'description' [ MTEXT-OR-GETTEXT | nil] ')'
VARIABLE-LIST ::= '(' 'variable' VARIABLE-DECLARATION * ')'
COMMAND-LIST ::= '(' 'command' COMMAND-DECLARATION * ')'
TITLE ::= '(' 'title' TITLE-TEXT ')'
VARIABLE-DECLARATION ::=
'(' VAR-NAME [ MTEXT-OR-GETTEXT | nil ] VALUE VALUE-CANDIDATE * ')'
COMMAND-DECLARATION ::=
'(' CMD-NAME [ MTEXT-OR-GETTEXT | nil ] KEYSEQ * ')'
MTEXT-OR-GETTEXT ::=
[ MTEXT | '(' '_' MTEXT ')']
LANGUAGE ::= SYMBOL
NAME ::= SYMBOL
EXTRA-ID ::= SYMBOL
VERSION ::= MTEXT
IM-DESCRIPTION ::= MTEXT
VAR-NAME ::= SYMBOL
VAR-DESCRIPTION ::= MTEXT
VALUE ::= MTEXT | SYMBOL | INTEGER
VALUE-CANDIDATE ::= VALUE | '(' RANGE-FROM RANGE-TO ')'
RANGE-FROM ::= INTEGER
RANGE-TO ::= INTEGER
CMD-NAME ::= SYMBOL
CMD-DESCRIPTION ::= MTEXT
TITLE-TEXT ::= MTEXT
IM-DECLARATION はこの入力メソッドの言語と名前を指定する。
LANGUAGE が t の場合、この入力メソッドは複数の言語で利用される。
NAME が nil の場合、この入力メソッドは単独で用いられるものではな く、他の入力メソッドから利用することを想定している。この場合、入力メ ソッドを特定するために EXTRA-ID が必要である。
VERSION はこの入力メソッドが必要とする m17n ライブラリの最小バージョ ンを指定する。フォーマットは "XX.YY.ZZ" であり、XX はメジャーバージョ ン、 YY はマイナーバージョン、ZZ はパッチレベルを表す。
DESCRIPTION はこの入力メソッドの説明を MTEXT-OR-GETTEXT で指定す る。もしこれが2番目の形式を取っていれば、 MTEXT は現在のロケールに 従って "gettext" によって翻訳される(翻訳文が提供されている場合)。
TITLE-TEXT はこの入力メソッドが有効な時、スクリーン上に表示されるテ キストである。
"global.mim" という特別なファイルがあり、共通する変数やコマンドが定義さ れている。入力メソッドドライバは毎回このファイルをロードし、他の入力メ ソッドはここで定義された変数やコマンドを継承できる。
VARIABLE-DECLARATION はこの入力メソッドで使用される変数を宣言する。 変数をデフォルト値に初期化したり、ユーザがカスタマイズしたりする場合に は、ここで宣言されなくてはならない。この宣言は二通りに利用される。一つ めは新しい変数を導入するためであり、この場合 VALUE は省略できない。 もう一つは "global.mim" で宣言された変数を継承し、違ったデフォルト値を 指定したり、この入力メソッド用にカスタマイズ可能にしたりするためである。 この場合には VALUE は省略できる。
COMMAND-DECLARATION はこの入力メソッドで使用されるコマンドを宣言する。 コマンドをデフォルトキーシーケンスに割り当てたり、ユーザがカスタマイズ したりする場合には、ここで宣言されなくてはならない。VARIABLE-DECLARATION 同様、この宣言は二通りに利用される。一つめは新しい コマンドを導入するためであり、この場合 KEYSEQ は省略できない。もう一 つは "global.mim" で宣言されたコマンドを継承し、違ったキーバインディン グを指定したり、この入力メソッド用にカスタマイズ可能にしたりするためで ある。この場合には KEYSEQ は省略できる。
MODULE-LIST ::= '(' 'module' MODULE * ')'
MODULE ::= '(' MODULE-NAME FUNCTION * ')'
MODULE-NAME ::= SYMBOL
FUNCTION ::= SYMBOL
各 MODULE は外部モジュール (動的ライブラリ) の名前とそのモジュールが 公開している関数名を宣言する。FUNCTION が "init" という名前であれば、 この入力メソッド用の入力コンテクストが生成される際に、デフォルトの引数 (CALL の節参照) のみとともに呼ばれる。 FUNCTION が "fini" という 名前を持てば, 入力コンテクストが破壊される際に、デフォルトの引数のみと ともに呼ばれる。
MACRO-LIST ::= MACRO-INCLUSION ? '(' 'macro' MACRO * ')' MACRO-INCLUSION ?
MACRO ::= '(' MACRO-NAME MACRO-ACTION * ')'
MACRO-NAME ::= SYMBOL
MACRO-ACTION ::= ACTION
TAGS ::= `(` LANGUAGE NAME EXTRA-ID ? `)`
MACRO-INCLUSION ::= '(' 'include' TAGS 'macro' MACRO-NAME ? ')'
MACRO-INCLUSION は、TAGS で指定される他の入力メソッドからマクロを 読み込む。MACRO-NAME が与えられていなければ、全てのマクロを読む。
MAP-LIST ::= MAP-INCLUSION ? '(' 'map' MAP * ')' MAP-INCLUSION ?
MAP ::= '(' MAP-NAME RULE * ')'
MAP-NAME ::= SYMBOL
RULE ::= '(' KEYSEQ MAP-ACTION * ')'
KEYSEQ ::= MTEXT | '(' [ SYMBOL | INTEGER ] * ')'
MAP-INCLUSION ::= '(' 'include' TAGS 'map' MAP-NAME ? ')'
入力メソッドがそれ単体で利用されることがなく常に他の入力メソッドに読 み込まれて用いられる場合には、MAP-LIST は省略できる。
MAP-NAME 定義中の SYMBOL は、 t あるいは nil であってはな らない。
KEYSEQ 定義中の MTEXT は、キーボードから生成できる文字で構成され る。すなわち MTEXT は通常 ASCII 文字のみを含む。しかし、入力メソッド がたとえば西ヨーロッパ用キーボードを使うことを想定したものであれば、MTEXT は Latin-1 文字を含んでもよい。
KEYSEQ 定義中の SYMBOL は、関数 minput_event_to_key() の戻り値で なくてはならない。X ウィンドウシステムの元では、 xev コマンドを用い て値を簡単にチェックできる。たとえば、 リターンキー、バックスペースキー、 キーパッドの0のキーなどは、それぞれ(Return) , (BackSpace) , (KP_0) としてあらわされる。シフト、コントロール、メタ、アルト、スーパー、 ハイパーも押されている場合には、それぞれS- , C- , M- , A- , s- , H- が 前にこの順に置かれる。したがって "リターンキーをシフトしてメタしてハイ
パーしたもの" は(S-M-H-Return) である。"a をシフト" から "z をシフト
" までは、単に A から Z として表されることに注意。したがって、 "a をシ
フトしてメタしてハイパーしたもの" は (M-H-A) となる。
KEYSEQ 定義中の INTEGER は、有効な文字コードでなくてはならない。
MAP-INCLUSION は、TAGS で指定される他の入力メソッドからマップを読 み込む。MAP-NAME が与えられていなければ、全てのマップを読む。
MAP-ACTION ::= ACTION
ACTION ::= INSERT | DELETE | SELECT | MOVE | MARK
| SHOW | HIDE | PUSHBACK | POP | UNDO
| COMMIT | UNHANDLE | SHIFT | CALL
| SET | IF | COND | '(' MACRO-NAME ')'
PREDEFINED-SYMBOL ::=
'@0' | '@1' | '@2' | '@3' | '@4'
| '@5' | '@6' | '@7' | '@8' | '@9'
| '@<' | '@=' | '@>' | '@-' | '@+' | '@[' | '@]'
| '@@'
| '@-0' | '@-N' | '@+N'
STATE-LIST ::= STATE-INCUSION ? '(' 'state' STATE * ')' STATE-INCUSION ?
STATE ::= '(' STATE-NAME [ STATE-TITLE-TEXT ] BRANCH * ')'
STATE-NAME ::= SYMBOL
STATE-TITLE-TEXT ::= MTEXT
BRANCH ::= '(' MAP-NAME BRANCH-ACTION * ')'
| '(' nil BRANCH-ACTION * ')'
| '(' t BRANCH-ACTION * ')'
STATE-INCLUSION ::= '(' 'include' TAGS 'state' STATE-NAME ? ')'
入力メソッドがそれ単体で利用されることがなく常に他の入力メソッドに読 み込まれて用いられる場合には、STATE-LIST は省略できる。
STATE-INCLUSION は、TAGS で指定される他の入力メソッドからステート を読み込む。STATE--NAME が与えられていなければ、すべてのステートを読 む。
STATE-TITLE-TEXT は、もし指定されていれば、入力メソッドがこの 状態にある時スクリーン上に表示されるテキストである。省略された場合には TITLE-TEXT が用いられる。
BRANCH の第一の形式では、MAP-NAME は MAP に現われるものでなく てはならない。この場合、MAP-NAME の KEYSEQ の一つに合致するキー列 がタイプされれば、 BRANCH-ACTION が実行される。
BRANCH の第二の形式では、その時点の状態のいずれの BRANCH にも合致 しないキー列がタイプされれば、BRANCH-ACTIONが実行される。
nil で始まる BRANCH がなく、入力されたキー列がその時点でのいずれの BRANCH にも合致しない場合には、入力メソッドは初期状態に遷移する。
BRANCH の第三の形式では、その状態に移動した時点で BRANCH-ACTION が実行される。もし初期状態であれば、入力メソッドの入力コンテクストを生 成した時点で BRANCH-ACTION を実行する。
BRANCH-ACTION ::= ACTION
入力メソッドはシンボルのリストを二つ持つ。
マーカリスト
マーカは preediting テキスト中での文字位置を示すシンボルである。MARK アクションはマーカを特定の位置に設定する。MOVE と DELETE ア クションはマーカの位置を参照する。
変数リスト
変数は整数の値を持つシンボルである。値はSET アクションによって設定さ れ、SET, INSERT, IF に参照される。すべての変数の初期値は(暗黙 に) 0 である。
各 PREDEFINED-SYMBOL はマーカとして用いられた場合特別な意味を持つ。
@0, @1, @2, @3, @4, @5, @6, @7, @8, @9
それぞれ 0 番目から 9 番目の位置
@<, @=, @>
最初の、今の、最後の位置
@-, @+
前の、次の位置
@[, @]
候補リストが変化する際の前と次の位置
PREDEFINED-SYMBOL のいくつかは、 SELECT アクション中で候補のイン デックスとして用いられた際特別な意味を持つ。
@<, @=, @>
現在の候補グループ中での最初の、今の、最後の候補
@-
前候補。今の候補が今の候補グループ中での最初のものであれば、前の候補グ ループの最後の候補。
@+
次候補。今の候補が今の候補グループ中での最後のものであれば、次の候補グ ループの最初の候補。
@[, @]
それぞれ前と後の候補グループ中で、今の候補と同じ候補インデックスを持つ もの。
また、これも特別な意味を持つ。
@@
その時点で処理されているキーの数。
以下はサラウンドテキスト処理に用いられる。
@-0
サラウンドテキストがサポートされていれば -1 、そうでなければ -2 。
@-N
ここで N は正の整数である。この変数の値は、プリエデット中の現在の位 置から N 文字前の文字である。もしプリエディット中で先行する文字がM (M<N) 文字しかなければ、その値は入力スポットから数えて (N-M) 文字前の文 字となる。delete アクションの引数として用いられた場合、この変数は削 除する文字数を指定する。
@+N
ここで N は正の整数である。この変数の値は、プリエデット中の現在の位 置から N 文字後の文字である。もしプリエディット中で後続する文字がM (M<N) 文字しかなければ、その値は入力スポットから数えて (N-M) 文字後の文 字となる。delete アクションの引数として用いられた場合、この変数は削 除する文字数を指定する。
各アクションの引数と振舞いは以下の通り。
INSERT ::= '(' 'insert' MTEXT ')'
| MTEXT
| INTEGER
| '(' 'insert' SYMBOL ')'
| '(' 'insert' '(' CANDIDATES * ')' ')'
| '(' CANDIDATES * ')'
CANDIDATES ::= MTEXT | '(' MTEXT * ')'
第一、第二の形式は MTEXT を現在の位置の前に挿入する。
第三の形式は、文字 INTEGER を現在の位置の前に挿入する。
第四の形式は、SYMBOL を変数として扱い、その値が正しい文字コードであ れば現在の位置の前に挿入する。
第五、第六の形式では、CANDIDATES は候補グループを表し、CANDIDATES の各要素が候補を表す。つまりCANDIDATES が M-text であれば、 候補はそのM-text 中の文字であり、CANDIDATES が M-text のリストであれ ば、候補はそれらの M-text である。
これらの形式は現在の位置の直前に最初の候補を挿入する。挿入された文字列 には、候補のリストと現在選択されている候補を指す情報が付加されている。
挿入によってマーカの位置は自動的に変更される。
DELETE ::= '(' 'delete' SYMBOL ')'
| '(' 'delete' INTEGER ')'
第一の形式は SYMBOL をマーカとして、マーカと現在の位置の間の文字を 削除する。
第二の形式は INTEGER を文字位置として、その文字位置と現在の位置の間 の文字を削除する。
削除によってマーカの位置は自動的に変更される。
SELECT ::= '(' 'select' PREDEFINED-SYMBOL ')'
| '(' 'select' INTEGER ')'
| '(' 'select' SYMBOL ')'
このアクションはまず、現在の位置の直前の文字が、候補リストが付加されて いる文字列に属すかどうかを調べる。そうであれば、その文字列を引数によっ て指定された候補に入れ換える。
第一の形式では PREDEFINED-SYMBOL を前述の候補インデックスとして扱い、 それによって候補リスト中の新しい候補が指定される。
第二の形式では INTEGER は候補インデックスであり、候補リスト中の新し い候補を指定する。
第三の形式では SYMBOL は整数の値を持たなければならず、その値が候補イ ンデックスとして取り扱われる。
SHOW ::= '(show)'
このアクションは、入力メソッドドライバに現在の位置の前にある文字列に付 加されている候補リストを示すように指示する。
HIDE ::= '(hide)'
このアクションは、入力メソッドドライバに現在示されている候補リストを隠 すように指示する。
MOVE ::= '(' 'move' SYMBOL ')'
| '(' 'move' INTEGER ')'
第一の形式は SYMBOL をマーカとして、それを新しい現在の位置とする。
第二の形式は INTEGER を文字位置として、その位置を新しい現在の位置と する。
MARK ::= '(' 'mark' SYMBOL ')'
このアクションは SYMBOL をマーカとして、それを現在の位置に設定する。 SYMBOL は PREDEFINED-SYMBOL であってはならない。
PUSHBACK :: = '(' 'pushback' INTEGER ')'
| '(' 'pushback' KEYSEQ ')'
第一の形式は、INTEGER の値が正ならば最新の INTEGER 個のキーイベン トをイベントキューに差し戻す。0 ならばすべてのキーイベントを差し戻す。
第二の形式は、KEYSEQ 中のキーをイベントキューに差し戻す。
POP ::= '(' 'pop' ')'
このアクションはまだ処理されていない最初のイベントをイベントキューから 取り出し破棄する。
UNDO :: = '(' 'undo' [ INTEGER | SYMBOL ] ')'
引数が無い場合、このアクションは最新の二つのキーイベント、すなわちこの コマンドによって引き起こされたものとその直前のもの、をキャンセルする。
整数値の引数 NUM がある場合、それは正か負であり 0 であってはならない。 正ならば最新のものから数えて NUM 個目のイベントをキャンセルする。負なら ば最新の(- NUM) 個のイベントをキャンセルする。
シンボルの引数がある場合、それは整数に帰着されなくてはならず、その値が 上記の正数値引数の場合と同様に取り扱われる。
COMMIT :: = '(commit)'
このアクションは現在の preediting テキストをコミットする。
UNHANDLE :: = '(unhandle)'
このアクションは現在の preediting テキストをコミットし、最新のキーを未 処理として返す。
SHIFT :: = '(' 'shift' STATE-NAME ')'
STATE-NAME が t ならば、このアクションは現在の状態を一つ前の状態 に遷移させる。そうでなければ STATE-NAME で表される状態に遷移させる。 後者の場合には、STATE-NAME は STATE-LIST に現われるものでなくては ならない。
CALL ::= '(' 'call' MODULE-NAME FUNCTION ARG * ')'
ARG ::= INTEGER | SYMBOL | MTEXT | PLIST
このアクションは外部モジュール MODULE-NAME の関数 FUNCTION を呼 ぶ。MODULE-NAME と FUNCTION は MODULE-LIST に現われるものでな くてはならない。
関数は (MPlist *) 型の引数とともに呼ばれる。最初の要素のキーは Mt で あり、その値はMInputContext 型のオブジェクトへのポインタである。第二 の要素のキーはMsymbol であり、値は現在の状態名である。 ARGs は三つ 目以降の要素の値として用いられる。それらの要素のキーは自動的に決定され る。ARG が整数値ならば対応するキーは Minteger であり、ARG がシ ンボルならば、対応するキーは Msymbol、などのように。
関数は NULL を返すか、または行うべきアクションのリストを表す (MPlist ) 型の値を返さなくてはならない。
SET ::= '(' CMD SYMBOL1 EXPRESSION ')'
CMD ::= 'set' | 'add' | 'sub' | 'mul' | 'div'
EXPRESSION ::= INTEGER | SYMBOL2 | '(' OPERAND EXPRESSION * ')'
OPERAND ::= '+' | '-' | '*' | '/' | '|' | '&' | '!'
| '=' | '<' | '>' | '<=' | '>='
このアクションは SYMBOL1 と SYMBOL2 を変数として、SYMBOL1 の 値を以下のように設定する。
CMD が 'set' ならば、SYMBOL1 の値を EXPRESSION の値に設定する。
CMD が 'add' ならば、SYMBOL1 の値を EXPRESSION の値だけ増やす。
CMD が 'sub' ならば、SYMBOL1 の値を EXPRESSION の値だけ減らす。
CMD が 'mul' ならば、SYMBOL1 の値を EXPRESSION の値を掛けたも のにする。
CMD が 'div' ならば、SYMBOL1 の値を EXPRESSION の値で割ったも のにする。
IF ::= '(' CONDITION ACTION-LIST1 ACTION-LIST2 ? ')'
CONDITION ::= [ '=' | '<' | '>' | '<=' | '>=' ] EXPRESSION1 EXPRESSION2
ACTION-LIST1 ::= '(' ACTION * ')'
ACTION-LIST2 ::= '(' ACTION * ')'
このアクションは、 CONDITION が真であれば ACTION-LIST1 を実行し、 そうでなければ ACTION-LIST2 を (もしあれば) 実行する。
SYMBOL1 と SYMBOL2 は変数として扱われる。
COND ::= '(' 'cond' [ '(' EXPRESSION ACTION * ') ] * ')'
このアクションは対応する EXPRESSION が 0 でない値をとる最初のアクショ ン ACTION を実行する。