Emacs23(以降) と 曖昧幅文字(East asian ambiguous)

Emacs23 以降の Unicode の曖昧幅文字取り扱いについてのメモです。


曖昧幅文字とは

環境によって、幅が1だったり、2だったりする文字のことで、具体的には、「○」とか「×」とか「α」とかそんな文字を指します。
CJK 環境だと、2 と解釈して欲しいけれども、それ以外の環境は、1と解釈して欲しかったりする文字です。


一覧としては、以下の URL のテキストで、A とついているものがそれにあたります。

Emacs23 での扱い

使っている環境に依存します。具体的には、以下の2つに依存します。
# 23 と書いてありますは、主に 24 で確認しています。やっている事は同じはずです。

  • 環境変数 LC_ALL、LC_CTYPE、LANG に何を設定しているか
  • set-language-environment で何を設定しているか

用は、自分の環境が CJK っぽい環境に設定されていると、曖昧幅文字が2となるように Emacs 側がやってくれます。
日本語 (Japanese) に環境を設定すると、以下のような感じです。

(set-language-environment "Japanese")
(char-width ?α)                        ; => 2 (#o2, #x2)
(char-width ?▽)                        ; => 2 (#o2, #x2)
(char-width ?×)                        ; => 2 (#o2, #x2)
(char-width ?○)                        ; => 2 (#o2, #x2)

英語 (English) に設定していると以下のような感じです。

(set-language-environment "English")
(char-width ?α)                         ; => 1 (#o1, #x1)
(char-width ?▽)                         ; => 1 (#o1, #x1)
(char-width ?×)                         ; => 1 (#o1, #x1)
(char-width ?○)                         ; => 1 (#o1, #x1)

上記と違って、もし set-language-environment で言語環境が設定されていなかった場合、Emacs は前述の3つの環境変数から、起動した環境が何なんのかを推定します。
例えば、環境変数 LANG に ja_JP.UTF-8 となっていた場合、以下のような処理で Japanese 環境であり、UTF-8 だと判断されます。

;; 言語環境
(locale-name-match (locale-translate "ja_JP.UTF-8")
                   locale-language-names) ; => ("Japanese" euc-jp)
;; 文字コード
(locale-name-match (locale-translate "ja_JP.UTF-8")
                   locale-charset-language-names) ; => "UTF-8"

これらは Emacs の起動時に呼ばれる関数 command-line 関数内で set-locale-environment という関数が呼ばれ、その中で自動で行われています。
# よって、LC_ALL= LC_CTYPE= LANG= emacs -Q とかやって起動すると、英語環境で Emacs が起動します。


また、set-language-environment が設定された場合、どこでどのように設定しているかについては、
LinuxEmacs 24 ならは,/usr/local/share/emacs/24.0.50/lisp/language/ 以下にある elisp に書かれています。
日本語環境だと、具体的には、以下のようになります。

  1. (get-language-info "Japanese" 'setup-function) で言語毎のセットアップ関数の取得。
  2. 取得したセットアップ関数の funcall (実行)。
  3. セットアップ関数内で文字幅表の更新を行う関数を呼び出す。

elisp 部分を抜粋すると以下のような感じです。

;; 1. セットアップ関数の取得
(get-language-info "Japanese" 'setup-function) ; => setup-japanese-environment-internal

;; 2. setup-japanese-environment-internal の実行
(defun setup-japanese-environment-internal ()
  ;; By default, we use 'japanese-iso-8bit for file names.  But, the
  ;; following prefer-coding-system will override it.
  (if (memq system-type '(windows-nt ms-dos cygwin))
      (prefer-coding-system 'japanese-shift-jis)
    (prefer-coding-system 'japanese-iso-8bit))
  (use-cjk-char-width-table 'ja_JP))

;; 3. use-cjk-char-width-table の実行
(use-cjk-char-width-table 'ja_JP)

上記のように use-cjk-char-width-table の実行に言語環境をつけており、日本語、中国語、韓国語別に文字幅の設定を行っています。
use-cjk-char-width-table 関数内では、以下のリストが参照され、曖昧幅文字に2が設定されます。

(defvar cjk-char-width-table-list
  '((ja_JP nil (japanese-jisx0208 (#x2121 . #x287E))
	       (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)))))

全ての曖昧幅の文字を2に設定するのであれば、この方の行っている設定を真似すればよいかもしれません。


見た目上の長さ

上記のように、言語環境さえ設定していれば、曖昧幅の文字は自動で2でしくれますが、見た目上はそうなっていなかったりします。
例えば、VL ゴシックの場合、このように見えます。

α が半角っぽく見えます。ただ、文字自体は、Emacs ではちゃんと幅2の文字であると認識されています。
これは、フォントが文字の幅をどうように扱うかであり、Emacs からどのくらい幅で見せるかを設定するという事はおそらくできないと思います。
# Emacs からできるとしたら、文字の大きさを変えるという事だけで、幅だけ変えるはおそらくできないように思います。
# もし、できるならやり方教えて下さいm(_ _)m


フォントの幅については、以下のブログの方が書かれているように、fontforge を使えば、確認や修正ができるようです。

  • ttp://d.hatena.ne.jp/tmtms/20091204/1259930572

なお、現在表示されている文字のフォントが何かを知るためには、その文字の上で、C-u C-x = とすれば分かります。


対処法としては、以下のどれかだと思います。

  • あきらめる
  • 文字毎にフォントを変えて頑張って対処する
  • 曖昧幅の文字が半角の倍の幅で見えるフォントを使う
  • フォント自体を改造してしまう。

どれを採用するかは好みになるんでしょうか…。



というような感じで以前調べた事をまとめてみました。
何か間違いがあったら、教えて頂けると嬉しいです。

更新時刻

  • 2011/3/27/22:20