The Man Who Fell From The Wrong Side Of The Sky:2010年3月2日分

[最新版] [一覧] [前月] [今月] [翌月]

2010/3/2(Tue)

[NetBSD] libedit I18N への道(その5.1)

昨日の補足再び、sh(1)でhistoryが切り詰められてしまう問題ですが、既に第3回でヒントが出てましたな。
el_gets(3)は IGNORE_EXTCHARS を使い el_wgets(3) の挙動を変更することで実装されてるという件。

eln.c

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引数で返してる文字列の幅がワイド文字数のままのオカン。

read.c

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^)/


[ホームへ] [ページトップへ]