wcwidthパッチ、その2

8月14日の記事の続きです。

CJK対応のwcwidth()ができたので、次に行ったのは、UTF-8の環境でAmbiguousな文字のWide/Narrowの切り替えオプションの作成とその対応です。
やったことはオプションの作成と切り替えを行うwcwidth()のラッパー関数の作成およびラッパー関数への置き換えです。
理屈上はこれでうまくいくはずなのですが、どうもうまく機能していません。表示がずれます。デバッグしてみると切り替えとCJK対応wcwidth()の呼び出しはうまくいっています。落ちがある可能性があるので、これから調べるつもりです。
ということで、まだ未解決だったりします。

この問題の原因はわかりました。
cursesライブラリもwcwidth()を呼び出しているので、cursesが求めた文字幅とMuttが求めた文字幅が異なってしまうため、表示がずれていました。
この対策としては、ラッパー関数を作成することをやめて、Mutt内蔵のwcwidth()自体にWide/Narrowの切り替えオプションを組み込んでみました。このようにするとcursesライブラリもMutt内蔵のwcwidth()を使うようになるので、基本的には表示がずれなくなりました。


しかし、まだ一部の文字が出ると表示が乱れます。
この原因はワイド文字関数*1がWideな文字をUnicodeの全角形あるいは似た形のWide文字のコードポイントに変換せずに似た形のNarrow文字のコードポイントに変換しまうことがあるためです。Wide文字の"¢","£"はUnicodeの全角形領域のFFE0, FFE1に変換されていれば問題ありませんが、glibc-2.3.3ではLatin-1領域の00A2,00A3に変換されます。そのため、通常はNarrowとして扱われます。こうなると、その文字のグリフの幅が2桁の場合は、表示上は2桁であるのに内部的には1桁として扱われ、文字の書き換え時に表示が乱れます。
これを解決するためには先日行った"A"(Ambiguous)な文字をWideとして扱うだけでは足らず、"Na"(East Asian Narrow)な文字の一部もWideとして扱う必要があります。これはAnnex #11の定義からするとおかしいのですが、対処療法としてはしかたないでしょう。


以上の対策を行っても、まだ表示が乱れることがあります。今のところ、全角のマイナス"−"があると表示が乱れることがわかっています。原因は先ほどのものと同じです。この"−"はワイド文字関数により"N"(Not East Asian)であるUnicodeの2212に変換されます。Annex #11の定義からするとありえないマッピングです。
もう、どうしたものやらって感じです。
CJKの文字を全てmbrtowc()につっこんで調べるしかないでしょうか?

*1:mbrtowc()とか