pTeX を UTF-8 入力に対応させる試み(5) †UTF-8対応(4) までと機能的にはほぼ同じですが、 一段落したので情報をまとめ直します。 (が、詳細には立ち入らないので UTF-8対応(3) などもご覧下さい。) 新しい話題には [new!] の目印をつけておきます。 ptexenc ライブラリ †ptexenc は、pTeX のあちこちに出てくる文字コード変換に関するルーチンを抜き出して、 ライブラリとして独立させたものです。 pTeX などから用いるにはパッチが必要です。 アスキーさんのオリジナルの pTeX の扱える文字コードは、 JIS X 0208, EUC, SJIS の3種類です。 また、外部ファイルの文字コードと、 内部処理の文字コードの組合せに強い制約があります (→漢字コードについて)。 そこで ptexenc は、文字コードを柔軟に扱える拡張もしておきました。 特徴をまとめると以下のようになります。
コンパイルオプションと環境変数 †ディフォルトの文字コードは、コンパイル時に ./configure の "--with-ptexenc=UTF8" のようなオプションで指定します。 これは実行時の環境変数 PTEX_KANJI_ENC や、 コマンドへの "--kanji" オプションで上書きすることができます。 jmpost は tex コマンドや pdvitomp コマンドを下請けに呼び出しますが、 jmpost に "--kanji" オプションを指定しても、下請けに引き継がれません。 このような場合には PTEX_KANJI_ENC を用いるのが便利です。 PTEX_IN_FILTER に、フルパスのコマンドが書いてあれば、 入力ファイルをこのフィルタを経由して読み込みます。 "/usr/bin/nkf -j" などを登録すれば、入力ファイルの文字コードが何であっても 処理できるので、便利です。 [new!] なお、"--kanji" オプションを指定するとこのフィルタは働かないようにしました。 フィルタの出力する文字コードは ./configure で指定したもの、あるいは PTEX_KANJI_ENC で指定したものに 合わせておきます。 ("--kanji" オプションとの整合性はもう気にしなくて大丈夫です。) JIS にしておくと無条件に読み込めるので安全ではありますが、 UTF-8 のきわどい文字 (BOM つきや合字のあるもの)をちゃんと通すには、 受け渡しも UTF-8、しかも nkf は 2.0.7 あたりの新しいものを使う必要があります。 TeX 関連ツール一般にあてはまることですが、 環境変数に書けるものは、 $TEXMF/web2c/texmf.cnf にも書くことができます。 特に、システムのディフォルトは texmf.cnf に書くのが標準的で、 環境変数はディフォルトを上書きする場合に用いられます。 PTEX_IN_FILTER はもちろん texmf.cnf にも書けるのですが、 残念ながら PTEX_KANJI_ENC は内部処理の都合で texmf.cnf を 参照しないのでご注意下さい。 文字コード変換ぐらい自前のフィルタで変換しておけば... †PTEX_IN_FILTER や --kanji=utf8 を使わずとも、TeX ソースの文字コードぐらい、 自分でスクリプトを書いて変換すれば十分だと思っている人も多いでしょう。 しかしそれでは、ちょっと込み入った状況になるだけでかなり面倒なことになります。
自分の手元だけで使い方を制限して、それなりに動かすことは可能でしょうが、 一般的な解決手法としては、 はやり PTEX_IN_FILTER や --kanji= の出番になると思います。 内部コードと fmt ファイル †TeX には、決まりきったスタイルファイルの読み込みを 高速化する機構があります。 スタイルファイルを読み込んだ時点で、 内部の変数の状態をファイルに書き出します。 次に起動するときにはこの書き出したファイルだけを読み込み、 スタイルファイルを読み込んだかのように動き出します。 内部の変数をダンプしたものが platex.fmt のようなファイルです。 hoge.fmt は内部の文字コードによって変化するため、 ptex-3.1.10 の場合は EUC 用と SJIS 用の2種類を生成し、 platex コマンドからはこのどちらかを用いていました。 ptetex3 では、2005年6月からこの二つの fmt を積極的に用いるため、 platex-euc, platex-sjis のようなコマンドを追加していました。 内部コード、外部ファイル共に EUC の platex-euc と、 同じく共に SJIS の platex-sjis です。 しかしながら ptexenc の拡張で、 内部と外部で文字コードを揃える必要がなくなったので、 この仕様は過剰になってきました。 実際、"platex-euc --kanji=sjis" と "platex-sjis" の動作の違いを知る人は、 ほんのわずかでしょう。 [new!]
そこで、ptetex3 ではもう一度仕様を変更して、
生成する fmt は一種類のみ、platex-euc などのコマンドも廃止して、
"platex --kanji=sjis" のようにオプションで文字コードを指定して
もらうことに この変更を行うと、これまではシンボリックリンクや $TEXMF/aliases を 駆使して platex-euc と platex が同じ働きをするようにしてましたが、 これが不要になり、 $TEXMF/web2c/fmtutil.cnf の記述もシンプルになります。 なお、jmpost にも fmt がありますが、 読み込むスタイルファイルに日本語が入ってないのでしょうか、 内部コードが変わっても fmt は同一のようです。 ptex の内部文字コードによる動作の違い †platex-sjis コマンドは、SJIS のファイルをタイプセットするために
用いていた人がほとんどでしょう。
しかしながら platex-euc コマンドでも --kanji=sjis オプションを付ければ
同じことが可能になりました。
従って、platex-sjis と platex-euc の本質的な違いは、
内部処理の文字コードにあることになります。
以下では、廃止 "platex-euc --kanji=sjis" と "platex-sjis" の出力の違いは、 ほんのわずかですが存在します。 ですからアスキーさんも動作を統一させられないのでしょう。 これとは対照的に、jbibtex や mendex の内部動作は元々 EUC の一通りですし、 jmpost などのツールは内部動作がどちらでも出力結果は同一のはずです。 問題があるのは ptex コマンドだけであろうと思います。 ptetex3 では fmt、つまりは platex の内部コードを(以前の pTeX のように)
一種類のみに hyperref を用いた PDF の日本語しおり †hyperref を用いると、生成される DVI が内部コードによって異なります。 dvipdfmx で PDF を作る場合には、この違いを吸収するために "pdf:tounicode EUC-UCS2" のような記述が必要です。 (→ps2pdf/dvipdfmx で日本語 PDF を作る) "platex-euc --kanji=sjis" なら EUC-UCS2、 "platex-sjis" なら 90ms-RKSJ-UCS2 を書きます。 ここに書く文字コードには誤解が多いので強調しておきます。 外部ファイルの文字コードを書くべきだとお思いの方が多いでしょうが、 実は内部コードを書きます。 それが証拠に platex-utf8 でも EUC-UCS2 と書きます。 以下のように、自動判定させている場合は常に正しく動きます。 \usepackage[dvipdfm,bookmarks=true,bookmarksnumbered=true,% bookmarkstype=toc]{hyperref} \ifnum 42146=\euc"A4A2 \AtBeginDvi{\special{pdf:tounicode EUC-UCS2}}\else \AtBeginDvi{\special{pdf:tounicode 90ms-RKSJ-UCS2}}\fi ちなみに、dvips + ps2pdf で PDF を作るならば、むしろ話は単純です。 PS を ps2pdf に通す前に、松本隆太郎氏の hyperrefと日本語 の convert-euc.txt のようなものを用いることになるでしょうが、 こちらは platex-euc であれば --kanji にかかわらず EUC 動作をさせればよいです。 ソースに細工をしておく必要はありません。 文字集合の範囲 †アスキーさんが意図されているかどうかは不明ですが、 ptex は 内部 SJIS のほうが多くの文字集合を扱えます。 数は少ないながらもこれを利用したパッケージがあります。 (→JIS X 0213への道) この恩恵にあずかるためには、 もちろん ptex の内部コードを SJIS にしておく必要がありますが、 普段の入出力は EUC のほうが便利という場面も多いでしょう。 そのためには ./configure 時に SJIS を指定し、 環境変数 PTEX_KANJI_ENC に EUC をセットしておけばよいです。 もちろん、広い文字集合の入ったファイルは SJIS で書いておき、 "platex --kanji=sjis" でタイプセットしなければなりません。 こうした場合、nkf との併用でうまく処理できるかどうかは自信がありません。 また当然ながら、はみ出した文字は jbibtex や mendex では扱えません。 カテゴリコード表の統一 †[new!] 通常のユーザには不要な情報で、 直接は ptexenc とも関係のない話題ですが、 ptex 用のパッチの中で実現したことなので、ここに書いておくことにします。 ptex 内部に、カテゴリコード(文字の属性)を決めるテーブルがありますが、 内部コードに応じて、EUC 用と SJIS 用の2種類が存在します。 つまり、2つのテーブルを同じ動きになるよう注意深く作ってあるというわけです。 2つのテーブルの存在は、そうそう中身を変更するものでもないため、 特にこれまで問題になることもなかったようです。 しかしながら、ptexenc により内部コードによる場合分けがほとんど消滅したため、 このテーブル作成ルーチンが最後に残った大きな場合分け処理となりました。 アスキーさんの解説 にも「2バイト文字のカテゴリコードを変更することはできません。」 とあり、EUC と SJIS での動作の違いが制約になっているように思えます。 (もっともユーザレベルでこのテーブルを変更する場面はほとんどないはずですが。) 気になっていたところに ttk 氏が upTeX でテーブルを統一した実装を公開されたので、 ほぼそのまま取り込ませていただきました。 ただし、ある意味で以前との互換性を失う改造であるのも事実です。 テーブルを変更している数少ないマクロ(前述の JIS X 0213への道 が該当)は、動かなくなっていると思われます。 また、fmt は生成しなおす必要があります。 [qa:47726] もご覧下さい。 UTF-8 対応の意味 †ここでの UTF-8 対応は、 過去との互換性を最大限に確保することを目標としています。 つまり、EUC や SJIS で書かれたソースを UTF-8 に変換しても、 まったく同じ出力が得られることを目指しています。 UTF-8 テキストでは、直接表記できる文字集合が増えましたが、 直接のサポートは行いません。 このため、多言語処理のために \usepackage[utf8]{inputenc} を用いる場合に、例えば latex で処理すれば \textsection と等価になる「§」が、 platex --kanji=utf8 では全角文字となってしまいます。 これはこれで避けようがないと思います。 最近気づいたのですが、pTeX に「\西暦」のマクロが存在するように、 「\α」というマクロも定義できてしまいます。 こういうものの互換性を確保するには、 やはりキリル文字も全角として扱うしかないであろうと思います。 ところで、UTF/OTF パッケージと inputenc を組み合わせると、 JIS 第1,2水準にない文字を直接表記することも不可能ではありません。 発案しておきながらも、うまい方法とは思ってなくて、 XeTeX や upTeX のようなちゃんとした Unicode 処理のできるものが よいと思っています。
普及状況 †一連の UTF-8 対応は、ptetex3 だけでなく、 既に角藤氏の W32TeX にも採用されています。 Vine Linux 4.0/4.1 の TeX も、ptetex3 がベースになっているので、 当然のように UTF-8 対応が入っています。 (ライブラリ化する前の初期のものですが。) [改訂第4版]LaTeX2e 美文書作成入門 でも大きく取り上げていただきました。 それなりに普及してきていると思います。 ptexenc は kpathsea から独立させたため、 例えば TeX Live で用いることも簡単になったと思います。 dvips/xdvi などの DVI ware からも ptexenc を使って欲しいと思っているのですが、 これにはもうしばらく時間がかかりそうです。 ご意見をどうぞ †
|