2010/03/02(Tue)
○[NetBSD] libedit I18N への道(その5.1)
昨日の補足再び、sh(1)でhistoryが切り詰められてしまう問題ですが、既に第3回でヒントが出てましたな。
el_gets(3)は IGNORE_EXTCHARS を使い el_wgets(3) の挙動を変更することで実装されてるという件。
72 public const char *
73 el_gets(EditLine *el, int *nread)
74 {
75 const wchar_t *tmp;
76
77 el->el_flags |= IGNORE_EXTCHARS;
78 tmp = el_wgets(el, nread);
79 el->el_flags &= ~IGNORE_EXTCHARS;
80 return ct_encode_string(tmp, &el->el_lgcyconv);
81 }
ここで第2引数で返してる文字列の幅がワイド文字数のままのオカン。
504 *nread = (int)(el->el_line.cursor - el->el_line.buffer);
505 goto done;
ズコー、IGNORE_EXTCHARS をセットした意味ないじゃんよこれwww
まー el_line ではワイド文字で持ってるんで、どうしても el_wgets(3) の中では計算できないのは確か。
手堅く修正するのであれば ct_encode_string() のIFを弄って、ワイド文字→マルチバイトに変換された
バイト数を返すように修正する鹿、なのですがもう正直 eln.c を一から書き直したい衝動がゴゴゴゴゴ。
まぁ本格対応の前に暫定fixを入れてみる。
Index: eln.c
===================================================================
RCS file: /cvsroot/src/lib/libedit/eln.c,v
retrieving revision 1.6
diff -u -r1.6 eln.c
--- eln.c 20 Jan 2010 01:15:52 -0000 1.6
+++ eln.c 2 Mar 2010 14:54:17 -0000
@@ -73,11 +73,15 @@
el_gets(EditLine *el, int *nread)
{
const wchar_t *tmp;
+ const char *s;
el->el_flags |= IGNORE_EXTCHARS;
tmp = el_wgets(el, nread);
el->el_flags &= ~IGNORE_EXTCHARS;
- return ct_encode_string(tmp, &el->el_lgcyconv);
+ s = ct_encode_string(tmp, &el->el_lgcyconv);
+ if (nread != NULL)
+ *nread = strlen(s);
+ return s;
}
これで実行してみると
vmware$ LANG=ja_JP.eucJP sh
vmware$ set -o vi
vmware$ <ESC> v
あいうえお
~
~
~
:w!
vmware$
あいうえお: not found
vmware$
うまくいきました\(^o^)/