2011年7月18日月曜日

xterm UTF-8文字幅

最近の xterm は UTF-8 に対応していて、-mk_width-cjk_width オプションで文字幅を切り換えることができます。実は xterm は特にオプションで指定しなかった場合には libc ロケールの文字幅を使用します。前回に GNU libc のロケール文字幅を変更する方法を紹介しました。

ということは、これで xterm での文字幅もバッチリということですね。
LANG環境変数に合わせてCJK文字幅や日本語互換文字幅も使えるはず。
・・・あれ?
・・・・使えるはず?!?
・・・・・何で?何で?
・・・・・・なぜか駄目でした。うーむ。

で source を確認したところ「罫線(line drawing)が全角の場合、そのロケールは信頼できないので、ロケールの文字幅は使用しない」という処理が入っていました。何ってこった。(Solaris のロケールが常に 2を返すので無効にするためらしいです。)

日本語処理系では伝統的に罫線は全角なんだよー。わかれよー。変なことすんなよー。

ということで余計な処理を無効にするために #ifdef でコメントアウトしてしまいました。以下のパッチを当てることで、フォント設定さえ適切なら xterm で ロケールの文字幅が使えるようになります。

--- xterm-269.orig/util.c 2011-02-17 09:28:45.000000000 +0900
+++ xterm-269/util.c 2011-06-17 10:59:16.922977037 +0900
@@ -3881,6 +3881,7 @@
     wchar_t n;
     int oops = 0;
 
+#ifdef __sun
     for (n = 21; n <= 25; ++n) {
  int code = (int) dec2ucs((unsigned) n);
  int system_code = wcwidth(code);
@@ -3899,6 +3900,7 @@
      break;
  }
     }
+#endif
 
     for (n = 0; n < (wchar_t) samplesize; ++n) {
  int system_code = wcwidth(n);

2011年7月15日金曜日

GNU libc UTF-8文字幅

最近は linux でもファイル名やディレクトリ名に日本語を使うことも多くなってきているようです。個人的にはファイル名にASCII文字以外を使用したくはないのですが、添附メールでもらったりとか、MS-Windows や Macintosh のファイル共有など色々と必要となる場面があります。

このような日本語の文字や記号をファイル名に使用している場合 ls などの表示桁がズレてしまうという経験をしている人も多いのではないかと思います。

これは UTF-8ロケール等で ls の認識している文字幅と、端末が認識している文字幅が異っていることが原因です。端末の文字幅設定の変更方法はそれぞれご存知かと思いますが、ls などの一般コマンド使用する文字幅が変更できることはあまり知られていないようです。

ls などの一般コマンドは libc のロケール機能を使って文字幅を決定しています。linux ならば GNU libc ということになります。この libc の文字幅は localedef コマンドを使用して定義することができます。標準の定義ファイルが /usr/share/i18n/charmap/UTF-8 にあるので、このファイルをコピーして編集して、localedef コマンドに与えることにより文字幅を変更できます。

以下サンプルとして、私の使用している文字定義ファイルを置いておきますのでダウンロードして試してみてください。

ダウンロード: glibc-UTF-8-width.tar.gz

使い方等は「もっと読むで」で

2011年7月10日日曜日

kterm, jless, screen パッチ更新

kterm, jless, screen の UTF-8/JIS X 0213 パッチに対して emacs-23 の旧JIS(JIS C 6226-1978)の扱いに対応させるための互換マッピングを追加しました。合わせて jless のバグの修正と、kterm の UTF-8 によるコピー&ペーストに対応させるためのパッチを入れておきました。

ダウンロード: kterm-6.2.0.ext06.patch.gz

ダウンロード: less-382-iso262.ext03.patch.gz

ダウンロード: screen-4.0.3.ext02.patch.gz

kterm/X11 における UTF-8 によるコピー&ペーストは色々と互換性の問題もあって敢えて外していたのですが、最近は内部がunicodeアプリケーションが多いので、利便性も考えて実験的に対応してみました。UTF-8といっても例によって日本語にのみ対応です。

2011年7月5日火曜日

emacs 23 jisx0213-2000マッピング問題

Emacs-23.3 では JIS X 0213 の 2000年版と2004年版の両方に対応しているのだが、ちょっとした問題があるようです。Emacs では JIS X 0213 の実装として以下の character-set が定義されています。

  • japanese-jisx0213-1 (2000年版の1面)
  • japanese-jisx0213-a (2004年で1面に追加された文字)
  • japanese-jisx0213.2004-1 (2004年版の1面)
  • japanese-jisx0213-2 (2000年版の2面、2004年と2面も同じ)

ということで jisx0213-1 + jisx0213-a = jisx0213.2004-1 という関係になっています。なっているはずです。なってないと困ります。 ....... でもなっていません(泣)。

emacs-23.3 では何故か jisx0213.1 = jisx0213.2004-1 になってしまっています。japanese-jisx0213-a が何のためにあるのかわからない状態です。

実際問題としては2004年で追加された文字はった11文字だし、EUC-JIS-2004 や Shift_JIS-2004 や UTF-8 で扱う時に差ははないので普通に使っていて問題になることは少ないと思いますが、、ISO-2022系の文字コードを使用した時に2004年版にしかないはずの文字が2000年版用のシケーンス ESC $ ( O で出力されてしまうという問題があって気付きました。

elisp の部分の実装は良い感じなのでバイナリに問題があるのだろうということで、ソースを確認したところ2000年版の変換表(JISX2131.map)に2004年の追加文字が誤って紛れ込んでいるようなので、取り除くことにしました。以下そのパッチです。

diff -urN emacs-23.3.orig/etc/charsets/JISX2131.map emacs-23.3/etc/charsets/JISX2131.map
--- emacs-23.3.orig/etc/charsets/JISX2131.map 2010-10-13 07:43:12.000000000 +0900
+++ emacs-23.3/etc/charsets/JISX2131.map 2011-06-14 10:19:22.143109803 +0900
@@ -1157,7 +1157,6 @@
 0x2d79 0x22BF
 0x2d7d 0x2756
 0x2d7e 0x261E
-0x2e21 0x4FF1
 0x2e22 0x0002000B
 0x2e23 0x3402
 0x2e24 0x4E28
@@ -1344,7 +1343,6 @@
 0x2f7b 0x000218BD
 0x2f7c 0x5B19
 0x2f7d 0x5B25
-0x2f7e 0x525D
 0x3021 0x4E9C
 0x3022 0x5516
 0x3023 0x5A03
@@ -4310,7 +4308,6 @@
 0x4f51 0x6E7E
 0x4f52 0x7897
 0x4f53 0x8155
-0x4f54 0x00020B9F
 0x4f55 0x5B41
 0x4f56 0x5B56
 0x4f57 0x5B7D
@@ -4352,7 +4349,6 @@
 0x4f7b 0x5DA7
 0x4f7c 0x5DB8
 0x4f7d 0x5DCB
-0x4f7e 0x541E
 0x5021 0x5F0C
 0x5022 0x4E10
 0x5023 0x4E15
@@ -7743,7 +7739,6 @@
 0x7424 0x7464
 0x7425 0x51DC
 0x7426 0x7199
-0x7427 0x5653
 0x7428 0x5DE2
 0x7429 0x5E14
 0x742a 0x5E18
@@ -8766,8 +8761,3 @@
 0x7e77 0x9F94
 0x7e78 0x9F97
 0x7e79 0x9FA2
-0x7e7a 0x59F8
-0x7e7b 0x5C5B
-0x7e7c 0x5E77
-0x7e7d 0x7626
-0x7e7e 0x7E6B

emacs 23 旧JIS (jisc6226)

今までのブログの記事は、過去に作成したパッチとかを引っぱり出してきて、まとめ直しているものが主なのですが、今回は最近に気付いた話です。

文字コード ISO-2022-JP で書かれた昔のメールを emacs23 を使って加工していて UTF-8 でセーブしようとした時に、うまく変換できない文字があってセーブできないことに気付いたのが事の発端です。少し調べてみるとJIS C 6226-1978 (いわゆる旧JIS)の文字の中に Unicode に変換できない文字があるらしいことがわかりました。

何でこんなことになってるんだということで、さらに調べたとこと emacs23 では JIS と Unicode の変換表で旧JIS(JIS C 6226-1978)と新JIS(JIS X 0208-1983/1990)では異なるマッピングを使っていることが判明しました。旧JISと新JISでは、かなり文字の字形が変更されているため厳密に扱おうとすれば異なるマッピングが必要となるのはその通りなのですが、互換性の問題から大抵のアプリケーションやライブラリでは旧JISと新JISは同じ文字として扱い、特殊な対応を入れているもので第一水準と第二水準を入れ換えられた二十数文字への対応を行うくらいだったのですが。

Emacs-23 は真面目に字形対応してしまったらしい。何てことをしてくれたんだ...
いや、誉めるべきか、貶すべきか悩ましい。漢字の字形の Unicode的な扱いとしては正しいと思うのだけど、また独自の JIS ⇔ Unicode 変換表が増えたことになるわけで。

で、話を元に戻して旧JISからUnicodeに変換できない文字だが、source を調べたところ旧JISからUnicodeへの対応表は昔に京大の安岡先生が作成された表を元にしているみたいなのだが、Unicodeの基本統合漢字だけが対象になっていて、拡張漢字A,Bなどが対象になっていないせいか変換先が未定義なままになっている文字があることが原因みたい。

とりあえず、旧JISでは異なる変換表を使うという主旨を尊重して抜けている部分を補完するとしたら以下のような感じだろうか。あと JIS 1区32点のバックスラッシュ(全角扱い)が ASCII の 0x5C (半角扱い)に変換されるのは文字幅的に嬉しくないのでついでに変更をしておこう。

diff -urN emacs-23.3.orig/etc/charsets/JISC6226.map emacs-23.3/etc/charsets/JISC6226.map
--- emacs-23.3.orig/etc/charsets/JISC6226.map 2010-10-13 07:43:12.000000000 +0900
+++ emacs-23.3/etc/charsets/JISC6226.map 2011-06-14 10:09:40.212292788 +0900
@@ -31,7 +31,7 @@
 0x213D 0x2014
 0x213E 0x2010
 0x213F 0xFF0F
-0x2140 0x005C
+0x2140 0xFF3C
 0x2141 0x301C
 0x2142 0x2016
 0x2143 0xFF5C
@@ -862,6 +862,7 @@
 0x343F 0x6B53
 0x3440 0x6C57
 0x3441 0x6F22
+0x3442 0x3D4E
 0x3443 0x704C
 0x3444 0x74B0
 0x3445 0x7518
@@ -1155,6 +1156,7 @@
 0x374B 0x6842
 0x374C 0x6E13
 0x374D 0x7566
+0x374E 0x25874
 0x374F 0x7CFB
 0x3750 0x7D4C
 0x3751 0x7D99
@@ -1176,6 +1178,7 @@
 0x3761 0x621F
 0x3762 0x6483
 0x3763 0x6FC0
+0x3764 0x28EF6
 0x3765 0x6841
 0x3766 0x5091
 0x3767 0x6B20
@@ -3537,6 +3540,7 @@
 0x513A 0x5140
 0x513B 0x5152
 0x513C 0x514C
+0x513D 0x5154
 0x513E 0x5162
 0x513F 0x7AF8
 0x5140 0x5169
@@ -6458,6 +6462,7 @@
 0x7042 0x970F
 0x7043 0x9716
 0x7044 0x9719
+0x7045 0x9724
 0x7046 0x972A
 0x7047 0x9730
 0x7048 0x9739

2011年7月4日月曜日

emacs 23.3 shift-jis-2004 自動認識問題

文字コードの設定はこれで完璧とか言いながら使っていたのだが、どうも shift-jis-2004 で第四水準の漢字を使用していると文字コードの自動認識に失敗する。elisp的には問題なさそうなので C のソースコードを追いかけてみました。

その結果、Cの文字コード認識の部分のバグらしいことが判明しました。SJISの文字認識の部分へ必要なコーディング・システム情報が渡されていない模様。

とりあえず簡単な一行パッチだけどこれで治ります。

diff -urN emacs-23.3.orig/src/coding.c emacs-23.3/src/coding.c
--- emacs-23.3.orig/src/coding.c 2011-01-09 02:45:14.000000000 +0900
+++ emacs-23.3/src/coding.c 2011-06-14 10:04:41.998645428 +0900
@@ -6501,6 +6501,7 @@
   {
     category = coding_priorities[i];
     this = coding_categories + category;
+    coding->id = this->id;
     if (this->id < 0)
       {
         /* No coding system of this category is defined.  */

2011年7月1日金曜日

emacs 23 (ja-compatible.el)

これまでの Emacs-23 用の日本語設定を一つにまとめて以下のファイルにしています。良ければダウンロードして試してみてください。

ダウンロード: ja-compatible.el

使い方ですが、このファイルを load-path の通った場所に置いて、UTF-8 メインの場合は ~/.emacs.el に以下のように書いてみてください。
;;      for japanese
(toggle-enable-multibyte-characters 1)
(set-language-environment "Japanese")
(load "ja-compatible")

;; set default coding system
(setq default-buffer-file-coding-system 'utf-8-ja)
(set-default-coding-systems 'utf-8-ja-unix)
(set-terminal-coding-system 'utf-8-ja-unix)
(set-keyboard-coding-system 'utf-8-ja-unix)
(set-file-name-coding-system 'utf-8-ja-unix)
(set-selection-coding-system 'ctext)
(setq sendmail-coding-system 'iso-2022-jp)
EUC-JP系をメインに使用している場合には、上記の utf-8-ja-unix の所を euc-jp-compatible-unix に変更します。

2011年6月30日木曜日

emacs 23 (その7)

EUC-JP系の文字コードには、EUC-JP と EUC-JIS-2004/EUC-JISX0213 があり、これらは本質的に異った文字集合ですので互換性がありません。 ASCII および JIS 第一水準、第二水準の範囲ではほぼ同じになっていますが、補助漢字の部分、と第三、第四水準の部分には互換性がありません。

個人的に EUC-JP で書かれたファイルと、EUC-JIS-2004 で書かれたファイルの両方ともに、それなりの数を保有しているため、その区別が問題になっています。酷いものになる一つのファイルの中に EUC-JP と EUC-JIS-2004 の文字が混在してしまっています。(そももかな漢字変換用の辞書の .skk-jisyo からして混在になちゃってたりして。) JIS X 0213 が補助漢字(JIS X 0212)を包含してくてれいれば良かったんですけどね。

補助漢字にしか存在しない文字もあるため、規格的に言えば正しくないのでしょうが、EUC-JP と EUC-JIS-2004 を同時に扱う互換エンコーディングを定義することにしました。

emacs 23 (その6)

次は Emacs-23 で UTF-8 を使う場合や、文字コードの変換をする場合のマッピングの問題について考えます。マッピング問題は主に Microsoft の CP932 環境と、それ以外の環境で Unicode と JIS の間のマッピングが異なることが原因になっています。(他にも OS ごとに細々とした違いがあるのですが)。

Emacs-23 にはこの問題に対応するために japanese-ucs-jis-to-cp932-map, japanese-ucs-cp932-to-jis-map という二つの変換テーブルが定義されています。これをうまく使えば CP932 との変換表の違いを吸収することができます。

ただこの表はあくまで JIS X 0208 と Microsoft CP932 の違い定義しているようで、JIS X 0213 については考慮されておらず、そのまま使用してしまうと、JIS 第三水準にある「チルダ」が第1水準の「波ダッシュ」に変換されてしまうなど、いくつかの文字で不具合がでます。

ということで、この表も自分用に再定義することにします。ついでに GNU libc や Apple MacOS などで(過去に?)使用されていた変換表の差分も吸収しておきます。

2011年6月29日水曜日

emacs 23 (その5)

前回に unicode の合字を全部 OFF としましたが。JIS X 0213 には合字を用いないと unicode で表現できない文字が25文字ほどあります。今回はこれについての対応を考えます。

emacs 23.3 のデフォルトでは、これらの文字については JIS X 0213 から unicode(内部コード)への変換は行われていないようです。EUC-JIS-2004 などにより、これらの文字を読み込んだ場合には、unicode に変換されず外字的な扱いでそのまま内部に保管されます。逆に unicode でこれらの文字に相当する文字組み合わせがあった場合も EUC-JIS-2004 に変換することはできずセーブ不能な文字が含まれているとしてエラーにます。

これに対応するために Emacs の日本語環境には jisx0213-to-unicode, unicode-to-jisx0213 という変換テーブルがデフォルトで定義されいます。これを使えばうまくいくはず....

だったのですが....... この変換表 translate-region などでは、きちんと使用できるのですが、なぜか文字コードの translation-table に設定しても正常に動かないという問題があります。バグか仕様の変更に対応できていないか何かだと思われます。

ということで、このテーブルは個人環境で再定義してしまうことにしました。続きのところに書いておきます。

2011年6月27日月曜日

emacs 23 (その4)

次は特殊な文字を無効化します。Unicode には Combining Character といって複数の文字を合わせて合字を作る機能があります。ドイツ語とかで A と ¨(うむらうと)を合わせて Ä (A Umlaut) を作成するとか、もっと複雑なアラビア系の文字やインド系の文字で使用されます。

JIS X 0213 にはこの unicode の合字に対応するダイアクリティカルマーク等が含まれていますが、日本語を扱う時には(ほとんど)不要な機能ですので OFF にしてしまいましょう。以下の設定で全バッファで合字の機能を OFF にできます。
(global-auto-composition-mode 0)
実は他にも特殊な機能を持った2文字があります。
  • JIS第3水準 09区02点 U+00A0 NO BREAK SPACE
  • JIS第3水準 09区09点 U+00AD SOFT HYPHEN
欧文(ISO 8859 や Unicode)ではそれぞれ、「改行禁止の空白」、「行末に来た時だけ可視化されるハイフン」という意味になりますす。Emacs ではこの2文字を特殊な扱いをします。

端末上で使用した場合には半角/全角の問題などで表示が崩れる原因になることもあるので、これらも単なる全角の文字として扱うことにします。
(setq nobreak-char-display nil)
この設定を見つけるのには苦労しました。OFF にする機能はあると思ったのですが、その変数名がわからなくて、思わず c の source から探してしまいました。

2011年6月25日土曜日

emacs 23 (その3)

次は文字幅を設定することにします。emacs は文字ごとに文字幅をコンフィグが可能な設計になっていて、例えば
(aset char-width-table ?♡ 2)
のようにすればハートマーク "♡" の文字幅が 2 に設定できます。ユニコードの番号を使用して以下のよに設定することも可能です。
(aset char-width-table #x2661 2)
この例だと同じく ♡ U+2661 の文字幅が 2 になります。

この方法で一文字づつ詳細に設定していくこもできますが、便利な仕組みが準備されています。例えば
(setq cjk-char-width-table-list
  '((ja_JP nil (japanese-jisx0213.2004-1 (#x2121 . #x2D7E))
               (japanese-jisx0212 (#x2121 . #x2F7E))
               (cp932-2-byte (#x8140 . #x879F)))
    (zh_CN nil (chinese-gb2312 (#x2121 . #x297E)))
    (zh_HK nil (big5-hkscs (#xA140 . #xA3FE) (#xC6A0 . #xC8FE)))
    (zh_TW nil (big5 (#xA140 . #xA3FE))
               (chinese-cns11643-1 (#x2121 . #x427E)))
    (ko_KR nil (korean-ksc5601 (#x2121 . #x2C7E)))
    (CJK   nil (japanese-jisx0213.2004-1 (#x2121 . #x2D7E))
               (japanese-jisx0212 (#x2121 . #x2F7E))
               (cp932-2-byte (#x8140 . #x879F))
               (chinese-gb2312 (#x2121 . #x297E))
               (big5-hkscs (#xA140 . #xA3FE) (#xC6A0 . #xC8FE))
               (big5 (#xA140 . #xA3FE))
               (chinese-cns11643-1 (#x2121 . #x427E))
               (korean-ksc5601 (#x2121 . #x2C7E)))
    (none  nil)))

(use-cjk-char-width-table 'ja_JP)
のような設定で書いておけば JIS X 0213 と JIS X 0212 の全ての文字が全角になります。(JIS X 0213 は JIS X 0208 を包含しているので当然、第一、第二水準も全角になります)。

互換性に気を使った非常に良いやり方ですね。さすがです。一方でユニコード規定での CJK 文字幅を実現するのは面倒なのですが。

この設定で文字コードの範囲指定が全文字(2121〜7E7E)でなく中途半端な数字で終っているのは漢字はデフォルトで全角なので、先頭に非漢字の部分だけを指定してやれば良いからです。数を少なくすることで少しでも起動速度が速くなることを期待しています。(第四水準の指定をしていないのも同じ理由です。第四水準には漢字しかないので)。


これだけで終らないところが悩ましい.... 続く。

2011年6月24日金曜日

emacs 23 (その2)

とりあえず、日本語の文字処理を修正する前に emacs の基本的な設定をしておく。

私は Emacs を端末の中で使用するできるだけシンプルなエディタとして使用したいので余計な機能は極力削っておく。起動メッセージも、メニューも、カラーも、カーソル位置もいらない。

(setq inhibit-startup-echo-area-message "username")
(setq inhibit-startup-screen t)
(setq initial-scratch-message nil)
(setq next-screen-context-lines 3)
(setq line-move-visual nil)
(setq transient-mark-mode nil)
(setq line-number-mode nil)
(setq next-line-add-newlines nil)
(global-font-lock-mode 0)
(menu-bar-mode 0)
(tool-bar-mode 0)
(scroll-bar-mode 0)
(tty-color-clear)

(setq enable-recursive-minibuffers t)
(put 'narrow-to-region 'disabled nil)
(put 'narrow-to-page 'disabled nil)
(put 'upcase-region 'disabled nil)
(put 'downcase-region 'disabled nil)

(add-hook 'after-change-major-mode-hook
          (lambda () (if (string= major-mode "fundamental-mode")
                         (local-set-key "\t" 'self-insert-command))))

とりあえず、こんなものだろうか。
何か忘れている気がするけど、まあいいか。

2011年6月22日水曜日

emacs 23 (その1)

次は Emacs の話にしよう。

emacs-23 から内部コードが基本的にユニコードになりました。実際にはユニコードと従来の文字集合の両方を内部コードとして持って扱うことができる設計になっているようです。文字の幅も柔軟な設計になっているみたい。

さすが Emacs と言いたいところですが、少しは問題が出ます。その内容と私が取った対策などを順次説明してみようかと思います。

まずは基本通り日本語環境を設定してみる。私はほとんど ssh でログインして端末エミュレータの中で emacs -nw で使用しているので、X のフォントの設定とかは特に気にしなくても大丈夫。UTF-8 を使うとしたら基本はこんな感じかな?

(toggle-enable-multibyte-characters 1)
(set-language-environment "Japanese")
(set-default-coding-systems 'utf-8)
(set-terminal-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
(set-file-name-coding-system 'utf-8)
(set-selection-coding-system 'ctext)
(setq sendmail-coding-system 'iso-2022-jp)
JIS X 0213 を使うのならば 'utf-8 の所を 'euc-jis-2004 にすれば良いはず。

結果これだけでも、それなりに使えるのだけど、デフォルトでは文字幅がやっぱり変だな。他にも、いくつか気になる所がある。

ということで続く。

2011年6月20日月曜日

GNU screen JIS X 0213/UTF-8 拡張パッチの内部実装

説明ではくて単な愚痴ですが、パッチが何故がぐちゃぐちゃなのかを書いておきます。

GNU screen は最近は更新はされていないようですが、既に UTF-8 にも ISO-2022/EUC/SJIS にも対応しているので JIS X 0213 に対応させるのも簡単だろうという軽い気持ちで作業を始めたのですが、色々と大変なことに。

2011年6月19日日曜日

screen JIS X 0213/UTF-8拡張パッチの使い方

文字コードに eucjp を指定した場合には EUC-JP, EUC-JISX0213, EUC-JIS-2004 から自動判別されます。

文字コードに sjis を指定した場合には Shift_JIS, Shift_JISX0213, Shift-JIS-2004 から自動判別されます。

文字コードに iso7 を指定すると ISO-2022 7bit 方式で JIS X 0213 が使えます。

もちろん今まで通り文字コード utf8 も使えますが、基本面(BMP)以外の文字も使えるように拡張しています。utfwidth コマンドで文字幅を指定可能してください。

utfwidth normal …… Unicode の基本文字幅。
utfwidth cjk …… Unicode の CJK 文字幅。
utfwidth ja …… 日本語互換文字幅(eucjp や sjis と同じ幅になる)。

おまけで cp932 という文字コードも指定できるようにしました。

GNU screen の文字コード指定

パッチの使い方を説明する前に GNU screen の文字コードについて簡単におさらい。GNU screen では2種類に場所に文字コードを指定できます。

1種類目は screen のウィンドウごとに持っている文字コードです。ウィンドウというのは screen 個々の画面のことで中で動いているシェル/プログラムが使用する文字コードだと思えばわかり易かな。ctrl-a ctrl-c とかで新規に作成して ctrl-a ctrl-n とかで切り換えるやつです。(emacs や shell との相性が悪いので当然キーは ctrl-a から別のものに変えていますが、いちおうデフォルトの ctrl-a で説明)。スクリーンはウィンドウごとに別々の文字コード指定できます。ctrl-a : encoding utf8 とかすればそのウィンドウの文字コードを変更できます。ウィンドウの文字コードのデフォルトは ~/.screenrc に defencoding で指定します。

2種類目は端末文字コードです。これは screen に接続している端末エミュレータ文字コードで、使用しているや xterm の putty とかの文字コードになります。ウィンドウと端末の文字コードが異なる場合には screen は文字コードの変換をしながら入出力を行います。例えば ssh でログインした先のサーバが UTF-8環境で、使用している端末エミュレータが EUC-JP の場合には ctrl-a : encoding utf8 eucjp とすることで、表示は UTF-8 ⇒ EUC-JP 変換され、キー入力は EUC-JP ⇒ UTF-8 変換されます。

ctrl-a : encoding . eucjp とすることで端末側の文字コードだけを変更することもでます(ドットが重要)。デフォルトは screen -x で接続する時に環境変数LANGや termcap等から取得されます。

知っておくと異った文字コード環境で作業する時に便利です。

GNU screen JIS X 0213 /UTF-8 拡張パッチ

GNU screen に JIS X 0213 の対応を追加するパッチです。その絡みで UTF-8 で基本面以外の文字も使えるように拡張しています。ついでに CP932 にも対応してみました。

何というか場当たり的な修正を繰り返してきた結果の、ぐちゃぐちゃパッチなので公開しようかどうか悩んだのですが、ついでなので公開してしまいます。(読んでて気持ちが悪くなっても責任は持てません。)

ダウンロード: screen-4.0.3.ext01.patch.gz

注意: いろいろバグが残っている気がします。ベータ版とかそんな気分で使用してください。

2011年6月18日土曜日

jless utf-8 パッチ 使い方

特に使い方を説明する必要もないかもしれませんが、今まで通り環境変数で

JLESSCHARSET=japanese-euc

として使用すれば、入力が UTF-8 の場合も自動判別して EUC-JP に変換して表示します。同様な感じで

JLESSCHARSET=japanese-utf8

とかすれば入力の日本語文字コードを自動判別して UTF-8 に変換して表示します。
他に環境変数 JLESSUTFWIDTH という機能を追加してユニコードの文字幅を変更できるようにしました。

JLESSUTFWIDTH=normal …… ユニコードの通常文字幅
JLESSUTFWIDTH=cjk …… ユニコードのCJK字幅
JLESSUTFWIDTH=ja …… 日本語の互換文字幅(EUCやSJIと同じ幅)

mlterm や xterm で使用する場合は設定によって normal や cjk を、先の kterm パッチと併用する場合には ja を指定しておくと良いでしょう。
その他の細かい点が気になる人は README.ext.jp を読んでください。

このパッチを作成した理由ですが、UTF-8 とその他の日本語文字コードを同時に使いたい時は PAGER として lv とかを使っている人が多いのかと思います。
私はもう手が less の多機能に慣れてしまっているので、less と jless を状況によって使い分けたりしていたのですが面倒になったのでパッチを作成しました。
あと前に書いユニコードの文字幅問題があって、オリジナルの less は UTF-8 の文字幅として、ユニコードの通常文字幅のみを前提にしていという問題に対応したいといのもありました。

jless utf-8 パッチ

jless の UTF-8 対応パッチです。jam-less とか less ISO パッチとか呼ばれているものに UTF-8 (で日本語)を処理する機能を追加するためのパッチです。less-382-iso262 パッチを当てた後に適用してください。

本家の less の方で UTF-8 対応が進んでいるので、jless の方もそのうち対応されるだろうと思って期待して待っていたのですが、しばらく更新が止まっているようなので個人用のものを公開します。これは個人的に利用する目的で作成したクイック・ハック・パッチの寄せ集めなので、あんまり綺麗な実装にはなっていませんが当面の実用には便利だと思います。

おまけで Microsoft CP932 にも簡易対応させています。

ダウンロード: less-382-iso262.ext02.patch.gz

kterm JIS X 0213/UTF-8 パッチ、使い方(2)

タイトルは「使い方」とか大袈裟ですが、実際は説明しなくても使い方はわかるかと思います。-km オプションもしくは Xresource や Ctrlキー+マウス中ボタンの VT Options メニューから文字コードが選択できます。

主な特徴としては
  • euc を選択した場合は EUC-JP, EUC-JISX0213, EUC-JIS-2004 から自動判別を行います。
  • sjis を選択した場合は Shift_JIS, Shift_JISX0213, Shift_JIS-2004 から自動判別します。
  • utf-8 を選択した場合には UTF-8 に簡易対応します。対応している文字は日本語(JIS)と ISO-8859 の文字のみです。(注意: ISO-8859 の文字は多くが全角扱いされます。)
  • Unicodeとの変換表は iconv 等のものではなく内部に持っている独自のものを使用します。他の環境(特にCP932)との互換性やJISとUnicodeの unify 規準の違いを吸収するために多対一対応になっています。
  • Unicodeの文字合成には原則として対応していませんが、アイヌ語表記用の半濁点付きカナなどの合成でしか表現できない一部の JIS X 0213 の文字についてのみ合成可能になっています。
  • 今のところユニコードの文字のコピー&ペーストには対応していません。
  • 今のとこ中国(GB)、韓国(CNS)、台湾(KSC)の文字や欧米の文字コードには未対応です。
以上、ktermについてはこんなものかな。

kterm JIS X 0213/UTF-8 パッチ、使い方(1)

ということで前置きが随分と長くなりましたが、ユニコードの表示文字幅として
  1. normal: ユニコードの標準文字幅
  2. cjk: ユニコードのCJK文字幅
  3. ja: 日本語の過去互換文字幅
の三種類が使えると良さそうという判断のもとに、1) と 2)については xterm や mlterm などの各種端末エミュレータが使用できるので 3)を実現することを考えました。

実現したい点を整理すると
  1. 最低限日本語(JIS)の文字 と ISO-8859 がUTF8で表現できればOK、別にユニコード完全対応したいわけではない。
  2. JIS X 0213 をサポートするためにユニコードの拡張漢字面の対応も必要。
  3. 文字符号は EUC-JIS-2004, Shift_JIS-2004, ISO-2022-7bit, UTF-8 を使いたい。
  4. 日本語(JIS X 0208, 0212, 0213)の文字は全て全角幅として扱う、フォントも今のまま使いたい、文字コードごとにフォントが変るのはいや。
  5. ユニコードの文字合成とか右書きとかの機能は不要。というかプレーンテキストに変な機能はあっちゃ駄目。
  6. でも JIS X 0203 のアイヌ用のカナなどを表現するための最低限の文字合成の対応が必要。(←この辺がかなりワガママ)
であっさり kterm で SJIS を扱っているような感じで UTF-8 文字符号に簡易対応させれば実現できることに気付きました。内部表現をユニコードに変更したりせず今のま ISO-2022形式で持つことにより、文字幅やフォントをそのまま使えます。

パッチを作成して個人的にバグを取りながら使用していました。作成してから大分たちますが、他にも使いたい人がいるかもと思いたち公開することにしました。

利用文字コードを EUC/SJIS/UTF8 の間で変更しても文字幅が変化しないので、それらを併用している人には便利だと思いますので使ってみてください。

2011年6月17日金曜日

ユニコードの文字幅問題(6)

この文字幅問題にどのような対応方法があるか考えてみた。

案1) GNU libc 等の文字マッピングを変更して、CP932 のように全角扱いの文字へ変換するようにする。

例外もあるが、ほぼJIS規格に沿っている glibc のマッピングを変更するには筋か違う。変更するとしてもポンド記号とかの JIS X 0208 (第一水準)の文字はよくても、将棋駒などのJIS X 0213 (第三水準)の文字は対応する全角文字がないので、そもそも無理。


案2) Unicode Consortium に働きかけて Ambiguous な大量に文字を増やしてもらう。

これは難しい。技術的には合理的な案だと思うけど政治的な問題として、ユニコードの利用を推進する人たちに、(彼らから見たら)少数利用者のためだけの他の文字コードとの互換規定を入れてもらうのは無理筋。

案3) 過去のことはきっぱり忘れて、全ての文字がユニコード指定の文字幅だと思って UTF-8 を使う。

まさに未来に生きる感じで、これができれば問題はないのだけど、現在 UTF-8 以外にも EUC-JIS-2004、ISO-2022-JP、SJIS(CP932) などの文字コードを併用していてる状況では難しい。個人的に JIS X 0213 の文章を大量に作ちゃったのが致命的...

案4) ユニコードや UTF-8 のことはきっぱり忘れて EUC-JIS-2004 とかを使い続ける。

逆に過去に生きる感じ。オープンソースの素晴しいところはサポートがなくても自分で何とかできる点で、死ぬまで今のまま使い続けるのも何とかなるかもしれない。でもとても無駄な努力な気がする。

案5) アプリケーションで複数の文字コードと文字幅を使える状況を準備して、状況に合わせて使い分ける。特に文字コードを併用するために EUC や SJIS と同じ幅で表示できる UTF-8 環境を整備しておく。

結局は、この案5)の方法しかないという判断になりました。

ユニコードの文字幅問題(5)

JIS X 0213 の第一、第三水準および JIS X 0212の非漢字についてユニコードによる East Asain Width に基いて文字幅をまとめてみました。(ブラウザのフォントによっては全部の文字は表示されないかもしれません。)


2011年6月16日木曜日

ユニコードの文字幅問題(4) 将棋駒

やっぱり文章を書くの苦手だな。言いたことをうまくまとめることができない。

ユニコードの文字幅問題にはその他にも JIS X 0213 (第三水準、第四水準)との互換性の問題があります。JIS第三水準として多数の記号類やラテン文字が追加されたのですが、ユニコードの文字幅表はあくまでも過去との互換のためのものなので、2000年に発行された JIS X 0213 の文字については全く考慮されていません。

このため色々と悲しいことが発生します。例えば「将棋駒(☖☗)」の記号は本来(全角の)漢数字や数字とともに使用して「☗4七銀」のように棋譜を示すのに使うはずの記号ですが端末上ではこの文字は半角扱いになってしまいます。

他にもトランプのマークがスペード(♤♠)、ハート(♡♥)、クラブ(♧♣)は全角なのに、ダイヤモンド(♢♦)だけは半角だとか、ローマ数字の i から x は全角なのに xi と xii だけ半角になったり、全角罫線と同時に使用することが前提の歯科記号が半角だったり色々と変てこなな状況になります。アルファベットまわりは半角と全角が入り混ってどうしようもない感じに。

結局各国の文字とそのユニコードへのマッピング表の違いによる問題なので完璧な解決方法はなさそうです。とりあえず JIS X 0213 まわりの文字幅問題を「将棋駒」の文字幅問題と呼んでます。

2011年6月14日火曜日

ユニコードの文字幅問題(3) ポンド記号

Unicode の文字幅が規定されましたが文字幅の互換性問題は解決しませんでした。

ユニコード対応の端末エミュレータでCJK互換文字幅を指定してやることにより、ほとんどの文字は適切な文字幅になるのですが、問題が残ります。きちんと確認していませんが MS-Windows で CP932 から移行する場合には大丈夫のようです。しかし私の使用している Linux ではうまくいきません。

この直接の原因は JIS の文字コードと、Unicode の文字の変換表が複数あることによります。CP932 の変換表では積極的に互換文字を使用するのに対して、Linux等で使用している変換表では「互換文字はできるだけ使用しない」というユニコードの規定に従って、ASCII や JIS X 0201 と重複している文字のみ互換文字を使用する方針になっています。ところが、全角幅指定されているのは互換文字だけで基本文字の方は Narrow 固定になっています。

例を上げると JIS X 0208 の01区82点にある(ポンド記号)は Microsoft の変換表では U+FFE1 FULLWIDTH POUND SIGN にマッピングされるのに対して、Linux では U+00A3 POUND SIGN にマッピングされているのですが、U+00A3 は Narrow(半角)扱いになります。同様の問題を持つ文字に「(セント記号)」や「(マイナス)」があります。

このように「互換文字」に「相互変換を維持する目的でのみ使用し、できる限り使用しない文字」と「全角など特定の文字幅属性を持った特殊文字」の2種類の矛盾した属性を持たせているというユニコード自身の本質的な問題に起因しているようです。

この問題を私は「ポンド記号」文字幅問題と呼んでいます。

2011年6月11日土曜日

ユニコードの文字幅問題(2)

ユニコード文字を端末エミュレータで表示する時にどのような文字幅で表示するべきか?

これに対してユニコードとして出された回答がUnicode Standard Annex #11 East Asian Widthという規定になります。

これはあくまで東アジアの過去の(legacy)文字符号と相互運用するための規定なので全ての文字に対して有用であるわけではありませんが、おおざっぱに言えばユニコードの文字全てに対して以下の方針で Wide(全角)か Narrow(半角)かを指定したものになります。

・漢字、ひらがな、カタカナなどの東アジアの文字は Wide (普通はASCIIの二倍の幅を持つ)。
・通常の文字と互換文字としての「全角変種(Fullwidth)」の両方が存在している場合には、通常の文字を Narrow で互換文字を全角。
・通常の文字と互換文字としての「半角変種(Halfwidth)」の両方が存在している場合には、通常の文字を Wide もしくは Ambiguous、互換文字を半角。
・過去の文字コードとの互換性から東アジアの文字符号に含まれている場合にはAmbigous
・原則とてそれ以外の文字は全てNeutral

Neutral というのは必ずしも Narrow という意味ではありませんが、習慣的に全て Narrow として実装されます。Ambiguous というのは東アジア(CJK)の文字と一緒に使用する場合には Wide で、それ以外で使用する場合は Narrow にするとい意味になります。

過去との互換性のためのかなり現実的な規定です。これによって、現実的なユニコードの端末エミュレータによる日本語表記が可能になりました。

さあ、これで全て解決でしょうか?

2011年6月10日金曜日

ユニコードの文字幅問題(1)

KTerm の UTF-8 パッチを作成した理由ですが、“ユニコードの文字幅問題”に個人的な解決をはかるためです。“ユニコードの文字幅問題”というのは、それほど正確な呼び方ではないのですが、便宜的にそう呼んでいます。

まあ、その辺もあるので最初に背景の説明など。

ご存知かと思いますが、文字集合および文字コードというのは、それぞれの文字を集めて一覧にしたもので本質的に文字の幅を規定するものではありません。文字幅を持っているのはあくまでも「フォント」になります。

日本語の端末装置や端末エミューレータでは、漢字などの2バイト文字集合の縦横の長さがほぼ等しい正方形の「全角フォント」で、ASCIIやJIS X 0201のような1バイト文字集合の文字を幅が漢字の半分の「半角フォント」で表示するのがデファクトスタンダードになっていました。

EUC-JP や Shift_JIS のような文字符号化では ASCIIなど1バイトで表現される文字と、JIS X 0208などの2バイトで表現される文字を同時に使用できるようになっていたため各文字に対して、その文字が所属していた文字集合によって文字ごとに幅が決まるためにあたかも文字ごとに文字幅が決まっているかのような状態になっていました。

ユニコードの出現によってこの伝統的な文字幅の扱いが問題になってきています。ユニコードは既存の全部の文字を同じ一つの文字集合として扱うものなので、基本面だけで2バイト、拡張面までいれると3バイト以上の文字集合になります。

さて端末エミュレータで表示する文字幅はどのようにすべきだろうか?

kterm JIS X 0213/UTF-8 パッチ

kterm に EUC-JIS-2004, Shift-JIS-2004, UTF-8 の対応を追加するパッチです。
今さら kterm の利用者は少ないかもしれませんが、個人的な需要があって作成しました。
詳細は別エントリーにします。

置き場所に悩んだのだけど、パッチは試しに Google Docs に置いて公開。

ダウンロード: kterm-6.2.0.ext05.patch.gz

2011年6月9日木曜日

とりあえず

いろいろ手元に変なパッチとか、設定とかあるので公開用にブログを設置してみた。あんまり役に立たないものばかりな気もするけど、もしかしたら誰かの参考になれば幸い。

定期的に投稿する気力ネタもないので、気が向いた時にのみ何か書くつもり。
検索した時に引っかかれば幸い。