Unicode の曖昧な文字幅の話

ちょっと色々調べたことをまとめておきます。
「曖昧な文字幅」の話でもあり、「曖昧な」文字幅の話でもあります。間違いとかあるかもしれないのであったら教えてくれるとにはさんが小躍りとかします。


Unicode には、文字ごとに文字幅というのが決まっています。これは、グラフィカルなアプリケーションではあまり重要ではないと思うのですが、コンソールアプリケーションでは非常に重要になってきます。
文字幅にはいくつか種類があるのですが、そのなかに「Ambiguous」という非常に不愉快なものがあって、これは文字幅が「文脈依存」という、まあ常識的に考えてありえないものです。
勿論そういったものが存在する理由はあるのですが、文字幅が曖昧とかぶっちゃけめちゃくちゃ迷惑な話ですね。つけあがるなよ。


多くのソフトウェアでは、この Ambiguous な文字を「1カラム」で計算してしまいます。
(ちゃんと調べてないので不正確な感じですが、 glibc の wcwidth か何かの実装がそうなってしまっているためだと思います。嘘かもしれません。)
現実には Ambiguous な文字というのは、そのほとんどが2カラムを期待しています。
1カラムで表示されると、当然文字は重なってしまいます。困りました。
ということで、場当たり的な解決にしかなっていないのですが、多くの場合パッチを当てることで解決することになります。
このパッチというのが一般的にどういったものかというと「Ambiguous な文字を2カラムで処理する」というものです。
これによって、ひとまずは文字が重なるという問題は解決されることになります。めでたしめでたし。


でまあここで終われたらよかったねーという話なんですが、続きます。
どうやら Ambiguous な文字の中には、1カラムの文字もあるようなのです。
これが、厳密にカラム数を計算する必要のあるアプリケーションで問題になります。
例えば w3m です。


w3m には UL 要素内の LI 要素の表示に使われる記号の中に「•」というものがあります。
(この記号は、フォントによっては表示されないかもしれません。最近 Osaka を使うようになったのですが Osaka では表示されませんでした。もうこんな文字は捨てろということですね!)
これは BULLET と呼ばれる記号で、文字幅は Ambiguous です。パッチを当ててオプションを適切に設定した w3m なら、2カラムで計算されることでしょう。
で、よく見てほしいんですが、これ「•」所謂「半角」に見えると思います。1カラム幅なんですね。しかし w3m はこれを2カラムと解釈してしまう。それの何が問題なのか。
ここで LI 要素内に A 要素があったとします。
http://niha.sakura.ne.jp/bullet01.png
春香さんです。かわいいですね。光ってる部分が実用面で非常に問題なのですが、画像編集基本的にウィンドウズでしかやったことないのに今ウィンドウズマシンがなくって困…
違います!!!!!リンクにカーソルを持っていってみましょう。
http://niha.sakura.ne.jp/bullet02.png
w3m はフォーカスの当たったリンクに下線を引くため再描画しようとします。リンクの位置を計算するためにカラム数を数えますが、ここで「実際のカラム数」とのずれが生じてしまいます。
1カラムの文字を2カラムで計算してしまっているため、実際の位置よりも1カラム後ろから再描画してしまい、ずれが発生してしまうわけですね。
今のところ BULLET 以外の文字ではこういった問題を確認していないのですが、他にもありそうな気がしてドキがムネムネします。


この様な問題が起きるのは Ambiguous な文字を全て2カラム決め打ちしてしまっているためなのですが、何故2カラム決め打ちというような、ぶっちゃけていえばお粗末な話になってしまっているのか。
これはボクの推測なんですが、どのパッチも既に存在した他のパッチを参考に作られていると思うんですね。で、その一番始めにできたパッチというのが「厳密なカラム数の計算が必要でないアプリケーション」に対するものだったんじゃないかなあと考えています。


結論ですが、ボクが言いたいのは「厳密なカラム数を計算するパッチ」を書く必要がある、ということではなく…
そもそも Unicode という統一された規格に関することで、各アプリケーションがパッチを当てないといけないというのは、どう考えても間違っているし、爆発して欲しいし、ニートだって暇じゃないんでこんなことに1週間以上も悩んだりしたくないわけです。
で、ここで「GNU あたりが何か頑張れよ!」って言って終わりたかったんですが、まだきちんと調べてない問題があって、そもそも「フォントによって Ambiguous な文字の文字幅が違う」とか、その辺は大丈夫なんですかね…
冷静に考えると、全ての文字をサポートすることさえ大変なのに、全ての文字でありもしない標準に合わせてカラムを設定するというようなことは、できている気が全くしません。
それどころか、実はボクが見落としているだけで本当は Ambiguous な文字は全て2カラムであるべきで、1カラムとかふざけんなよ爆発しろ!とか…うーん。
全然まとまらない状態で書き始めたのでやっぱりまとまりませんでした。ありがとうございました。
ぶっちゃけ何が本当に問題なのかまだ分かってない気がします。分かってるか分からないし分からないか分からない。


最後に全然関係ない話ですが screen + ncurses で box 使って枠線つけたらずれる理由が全く分からない。
こっちはカラム数の計算間違えるという問題は発生しないはずなので別の理由のはずなのですが、ちょっと調べたくらいだと全く分からないし、いい加減疲れてもううんざりなので誰か分かる人いたら教えてくれてついでにパッチとか設定とか書いてくれると小躍りします。