libcはld(1)によって暗黙的にリンクされます、この場合リンク順は一番最後になります。
お、そうだったのか。それで上書きしてもリンカが文句言わないのか。
ここ数日の「めもがき」のおかげで、やっとこの問題の意味がわかってきました。 感謝感激。もう一度よく読み直そうっと。
Unicode では「>>」みたいな文字が二種類あるようで(「≫」226b と「》」300b だったかな)、 w3m を UTF-8 環境で動かすと、(フォントによって違うとは思うけど)、 226b が幅 1 で問題なく使えるのに対して、300b も幅 1 になって、 セキュmemo などが少し気持ち悪くなる。 最初の表示は大丈夫っぽいんだけど、カーソルを合わせると誤差が出てくる。
ほんとはうちのフォントとか mlterm がおかしくて w3m が正しいのかもしれないけど、 これを追ってみる。
最初これは mlterm の問題だろうと思って ChangeLog を見てみたんだけど、 xterm との互換性のために ambiguous 幅じゃなくて wide にした、とかいう記録があった。
それに vim では UTF-8 でも EUC-JP でも問題なく扱える。
だから w3m の問題だと思って、こっちを調べる。
まず addstr とか addch のあたりから追って、wtf_width というものがアヤシイと思った。 これは WTF_WIDTH_MAP という配列を見るだけのもの。 そして WTF_WIDTH_MAP は最初の 1 バイトだけで幅を判断するというものだった。
gdb で見ると、300b は 88 80 e0 8b (0210 0200 0340 0213) というバイト列のようで、この 88 (0210) の部分だけってことだ。 でも 226b も最初は 88 (0210) なので、困っちゃうなあ。 そもそもどうして 300b がこんな 4 バイトになるのか。 UTF-8 のファイルを hexdump してみると e3 80 8b (0343 0200 0213) みたいだぞ。
で、とりあえず wtf_width マクロの時点で 88 80 e0 8b (0210 0200 0340 0213) に 2 を返すように細工してみたら、うまくいった。
だからあとはちゃんと 88 80 e0 8b (0210 0200 0340 0213) の意味を解析しなくては。 おそらく 1 バイトがフラグのようなもの、次が UTF-8 と共通、また 1 バイトフラグ、UTF-8 共通、ということだろう。88 (0210, 0b010001000) とか e0 (0340, 0b011100000) ね。
と思ってたら libwc/wtf.h に
#define WTF_C_WCS16 0x88
って書いてあるじゃん。
そして wcs16_to_wtf(0x300b) を見てみると……おお、確かに 80 e0 8b になる。 だから最初の 88 (WTF_C_WCS16) に、もうちょっとフラグを足せないか考えればいいんだな。
と、ここまで来て、libwc/map/ucs_wide.map をいじったらすぐに直ってしまった。 あれ〜? 最初にやったときは駄目だったのになあ。
あ、でも最初に ucs_wide.map をいじったときは libwc だけ作り直したっけ。そうか。
--- libwc/map/ucs_wide.map~ Tue Jan 23 21:34:35 2007 +++ libwc/map/ucs_wide.map Tue Jan 23 22:46:26 2007 @@ -1,10 +1,9 @@ -#define N_ucs_wide_map 10 +#define N_ucs_wide_map 9 static wc_map ucs_wide_map[ N_ucs_wide_map ] = { { 0x1100, 0x115F }, - { 0x2E80, 0x3009 }, - { 0x300C, 0x3019 }, + { 0x2E80, 0x3019 }, { 0x301C, 0x303E }, { 0x3040, 0xA4CF }, { 0xAC00, 0xD7A3 },