『tm における文字 code の取り扱いについて』 by 守岡 知彦 1996年7月18日 * charset 取り扱いに関する基本原則 tm では原則として MIME で定められた charset 機構に基づいて文字 code を取り扱う。これを実現するために、message を表示するための buffer (preview buffer; cooked buffer) の他に生の(即ち、code 変換されておら ず network code のままの)message が入った buffer (original article buffer, raw buffer) を用いることとする。この条件が満たされれば、base64 や quoted-printable 等の encode を行なっていない場合でも、1つの message に複数の文字 code を混在させることができる。 しかしながら、現実には幾つかの問題が存在する。1つは非 MIME message の取り扱いであり、もう一つは上記のような方法をとることが困難な MUA を 利用する場合である。非 MIME message に対しては、tm は default の charset を仮定することで対処している。後者の問題に関しては MUA 毎に code 変換 program を設定し、raw buffer を作成することが困難な MUA の場 合、7bit, 8bit, binary のような encode されていない message の charset による code 変換をやめるようにすることで対処している。 以下、実際の機構に関して説明する。 * 文字 code の取り扱いに関する layer 構造 tm は [[E (4) user interface layer (tm) (3) non-interactive MIME feature layer (tm) (2) MIME encoding layer (MEL) / utility function layer (tl) (1) emu API layer (0) (API of emacs variants) ]]E という5層構造になっているが、文字 code の取り扱いも同様である。 第1層である emu API で全ての emacs variant で利用可能な基本関数を提 供し、第3層で tm-view で利用するための基本的な機能を実現し、第4層で その界面を定義する。 * 文字 code に関する emu API の機能 EMACS には、元来、文字という概念は存在しなかった。よって、それを扱う ための機能は存在しなかった。 emacs の世界に文字 code という概念を持ち込んだのは NEmacs である(多 分(^_^;)。NEmacs は `JIS', `EUC', `Shift JIS'(および無変換)という3 種類の『漢字 code』を導入した。そして、これを数値で表現した。 NEmacs は日本語(の subset)しか扱う必要がなかったので高々3種類の文 字 code が使えれば十分であったが、これを多言語化した MULE ではより多数 の文字 code が扱うことが要求され、また、user が文字 code を定義できる ことも必要であった。このため、数値ではなく、先頭と末尾に `*' を付けた 自己評価形式の定数で表現される coding-system という概念が導入された。 XEmacs に mule 機能を導入しようとした人達は自己評価形式の定数の代わ りに coding-system を表す新たな型を導入することにした。また、この型に 対応する名前を symbol で与えた。このため、coding-system を表す大量の定 数は一掃された。 このように、現存する emacs variants の間では文字 code の表現法はさま ざまである。もともと、emu はこの分野でもっとも機能の高い MULE をお手本 にこれの機能を emulate する関数を各 emacs variant に対して定義する方法 を採ったが、MULE を元に EMACS/MULE 統合版や XEmacs/mule が生まれるに従 い、coding-system 機能をそのまま使うのは得策ではないと判断するに至った。 代わりにより抽象度の高い MIME charset に関する API を用意することにし た。 MIME charset は文字 code を表すものであり、MULE でいうところの leading-char や EMACS/MULE や XEmacs/mule でいうところの charset に相 当するものではなく、mule の coding-system に相当する機能である。実際、 mule の coding-system の名前と MIME charset の名前は共通するものも少な くない。 MIME charset の表現の仕方として、emu API では XEmacs/mule と同様、 symbol を用いることにした。MULE のような変数を使うと束縛に関する check が必要であるが、symbol ではこのような check は不要である。また、将来的 に、XEmacs/mule の方法に統合されることを期待する意味もある。実際、 XEmacs/mule と emu API の間の gap は少なく、将来、全ての MIME charset が XEmacs/mule の coding-system として定義されれば、emu としてこれを用 意する必要はなくなるだろう。 さて、以下では実際の機能を解説する。 [変数] charsets-mime-charset-alist Key 部に charset の list, value 部に mime-charset をとる連想リ スト。関数 charsets-to-mime-charset や関数 detect-mime-charset-region がこの変数を参照する。 [変数] default-mime-charset 変数 charsets-mime-charset-alist で定義されていない charset の list に対してつける MIME charset を示す。関数 charsets-to-mime-charset や関数 detect-mime-charset-region が この変数を参照する。 [関数] charsets-to-mime-charset CHARSETS charset の list `CHARSETS' に対応する MIME charset を返す。 [関数] detect-mime-charset-region start end `START' と `END' で囲まれた領域に対応する MIME charset を返す。 [関数] encode-mime-charset-region START END CHARSET `START' と `END' で囲まれた領域を MIME charset `CHARSET' で encode する。 [関数] encode-mime-charset-string STRING CHARSET 文字列 `STRING' を MIME charset `CHARSET' で encode する。 [関数] decode-mime-charset-string STRING CHARSET 文字列 `STRING' を MIME charset `CHARSET' で decode する。 * 文字 code に関する tm の実装 もし、素直に charset を実現するだけなら emu API をそのまま使えば良い のだが、実際には VM や RMAIL(および昔の GNUS, Gnus)といった raw buffer を実現しにくい MUA では charset に対応することが困難である。こ のため、tm-view はこのような MUA では純粋な意味での raw buffer の実現 を諦め original article buffer 中に既に charset に依らずに code 変換し た message を入れることを認めている。 よって、以下の2種類の code 変換関数を使い分ける必要がある。 [関数] mime-charset/decode-buffer charset &optional encoding current buffer を MIME charset `charset' で内部 code に変換す る。この関数は `encoding' に依らず必ず code 変換を行なう。 [関数] mime-charset/maybe-decode-buffer charset &optional encoding `encoding' が nil, "7bit", "8bit", "binary" 以外の時、即ち、 ASCII printable な encode が施されている時のみ、実際に、 current buffer を MIME charset `charset' で内部 code に変換す る。それ以外の時は、何もしない。 * 文字 code に関する tm の界面 MUA によって文字 code を使い分けるために tm はここで述べるような界面 を提供する。 [変数] mime-viewer/code-converter-alist この変数は key 部を major-mode, value 部を code 変換関数とする 連想 list である。これを用いて各 MUA 毎の code 変換関数を設定 する。code 変換関数は全節で述べた実装を用いること。 [変数] mime::article/code-converter method で用いられる code 変換関数を指定するための original article buffer の buffer local 変数である。変数 `mime-viewer/code-converter-alist' よりも高い優先度で参照され る。 [関数] mime-preview/decode-text-buffer charset encoding MIME charset `charset', MIME encoding `encoding' で符号化され た current buffer を decode する。code 変換は変数 `mime::article/code-converter' および `mime-viewer/code-converter-alist' を参照して得られた関数によっ て実行される。 * 文字 code 関係の関数の使い方の指針 tm-view の method がある content をある charset, encoding に従って decode する場合は関数 mime-preview/decode-text-buffer を用いることとす る。 tm-view の method において、ある content に対して再帰的に preview buffer を作成するような場合で、変数 mime::article/code-converter を設 定する必要がある場合は、関数 mime-charset/decode-buffer および mime-charset/maybe-decode-buffer を用いることとする。 それ以外の場合において、実際に code 変換を行なうような場合は、emu API の機能を用いることとする。