ラベル emacs の投稿を表示しています。 すべての投稿を表示
ラベル emacs の投稿を表示しています。 すべての投稿を表示

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 (その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 にすれば良いはず。

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

ということで続く。