- ベストアンサー
LinuxでCursesライブラリを使って半角カナが制御できない
- Linux Red Hat 6.1を使用して、cursesライブラリを使ってウィザードを作成していますが、半角カナの扱いで問題が発生しています。
- mvprintw()関数を使用して仮想画面に文字を書き込む際、半角カナの表示位置が正常にならない現象が発生しています。
- ktermのライン数を変更すると、半角カナの表示位置の問題が一時的に解消されることがわかりましたが、その原因や他の解決策は分かりません。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
OKとなる場合、「ア」の行を書いたあと、「イ」を書く座標を明 示的に指定してジャンプしているので、問題なく表示されています。 これに対して、NGとなる場合、「ア」を10個書いたあと、1行下 に移動("LF" = 0A)し、20桁左に移動("ESC [ 2 0 D" = 1B 5B 32 30 44)しています。 半角カナを10個書いて20桁左に行くので、戻りすぎてしまい、表示 がおかしくなるようです。curses が、半角カナが1桁分の幅しかな いことを認識していないということですね。 なぜ、kterm の大きさや座標の微妙な差で、結果に違いがあるのか というと、curses は、同じ表示になるなら、なるべく短い出力を 出すように工夫するからです。ちょっとした出力文字数の差で、違 うやり方を選択するので、偶然うまく行ったりいかなかったりする わけです。(もっとも、本当に最適かどうかはわかりません。この 例では、どの場合でも、直接座標を指定するのは文字数的に損して る気がします。) linux の JE というパッケージに、日本語化された pcurses とい うのが入っているらしいですが、詳しくは知りません。日本語化さ れたといっても、半角カナが扱えない可能性も高いです。 もし、これを入れてみてもだめなら、半角カナにはこだわらない方 がいいかと思います。あるいは、curses をやめて、termcap を直 接いじるかですね。
その他の回答 (1)
- punchan_jp
- ベストアンサー率55% (155/280)
半角カナでなく、ASCII 文字なら問題ないのでしょうか? 出力する文字コードと kterm の文字コードの設定として 何を使っているでしょうか? EUC を使っているとすると、半角カナは2バイトで表現されますから、 ちゃんと日本語化された curses でないと正しく扱えないかもしれません。 あとは、kterm のバグが考えられますが、この場合、script コマンドによって curses がどのような出力をしているかの生の情報を収集できます。 script を起動して、すぐ問題のコマンドを動かし、おかしくなっ た時点ですぐ終了させて、script も exit で抜けておきます。 そうすれば、typescript というファイルに、それまでに出力され たバイト列が生成されます。これを適当な方法で解析してください。 うまくいく場合といかない場合の両方を調べて比較するといいかもしれません。 このファイルが巨大でなければ、cat -vt してここに掲載してもらえれば、 調べてみますけど。
補足
punchan_jp さん、回答ありがとうございました。 ご質問に対してお答えします。 #長くなっちゃったけど大丈夫かなぁ。。。 >半角カナでなく、ASCII 文字なら問題ないのでしょうか? ・ASCII 文字、全角文字なら問題ありません。 >出力する文字コードと kterm の文字コードの設定として >何を使っているでしょうか? ・出力コードはEUCです。 kterm の文字コードの設定というのは、LANG、LC_ALL のことで いいのでしょうか。 どちらも ja_JP.ujis となっていました。 >EUC を使っているとすると、半角カナは2バイトで表現されますから、 >ちゃんと日本語化された curses でないと正しく扱えないかもしれません。 ・データは2バイトですが、1バイト分で表示されています。 ちゃんと日本語化された curses ライブラリかどうか判断することは できますか? 6.1 でのリンクは以下のようになっていました。 libcurses.so -> libncurses.so libncurses.so -> libncurses.so.4 libncurses.so.4 -> libncurses.so.4.2 libncurses.so.4.2 : (1999 Sep 24 274985byte) ちなみに 6.2 でも同じ現象になりました。 実体は libncurses.so.4.0 (2000 Mar 7 262884 byte) でした。 >あとは、kterm のバグが考えられますが、この場合、script コマンドによって >curses がどのような出力をしているかの生の情報を収集できます。 >script を起動して、すぐ問題のコマンドを動かし、おかしくなっ >た時点ですぐ終了させて、script も exit で抜けておきます。 >そうすれば、typescript というファイルに、それまでに出力され >たバイト列が生成されます。これを適当な方法で解析してください。 >うまくいく場合といかない場合の両方を調べて比較するといいかもしれません。 参考までに、簡単なプログラムを以下に載せておきます。 -------------------- ここから -------------------- #include <curses.h> main() { char tbl_1[80]; char tbl_2[80]; int cnt, cnt2; int mojiCnt = 10; initscr(); clear(); memset(tbl_1, '\0', 80); memset(tbl_2, '\0', 80); for (cnt = 0, cnt2 = 0; cnt < mojiCnt; cnt++) { tbl_1[cnt2] = 0x8E; tbl_2[cnt2] = 0x8E; cnt2++; tbl_1[cnt2] = 0xB1; tbl_2[cnt2] = 0xB2; cnt2++; } mvprintw(10, 16, "%s", tbl_1); mvprintw(11, 16, "%s", tbl_2); refresh(); endwin(); } -------------------- ここまで -------------------- 質問を出した後、いろいろ試しましたが、以下の条件が影響すると わかりました。 ・書き出すY座標 ・表示する文字数 ・kterm のライン数 プログラムで、文字数(mojiCnt)、Y座標(mvprintw 関数の第2パラメータ)を 変更したり、kterm のライン数を変えてテストしました。 例えば上記プログラムは、ライン数:24、カラム:80 の kterm で実行すると NGですが、ライン数を 25 にするとOKでした。 また、ライン数:24、カラム:80 のままで、座標を (10,15) と (11,15) と したらOKでした。 データ長にも影響しているらしく、各行2文字ずつ表示した場合、Y座標が 2以下ならOKで、3以上がNGでした。 各行3文字の場合は、Y座標が3以下がOKで、4以上だとNGでした。 (ライン数:24、カラム:80) Windows のマシンから「TeraTerm」というソフトで telnet して試しましたが 同じ現象が発生しました。 この場合は、LANG、ロケールは ja_JP.eucJP です。 なので curses の問題だとは思うのですが、原因が全く推測できません。 >このファイルが巨大でなければ、cat -vt してここに掲載してもらえれば、 >調べてみますけど。 お時間が許されるならば、よろしくお願いします。 以下が cat の結果とダンプデータです。 cat の結果をファイルに落として vi で見たところ、NGとなった (1) の 場合は1行目の表示と2行目の表示のデータの部分は別の行となっていましたが OKの場合は1行目の表示と2行目の表示のデータの部分は同じ行として つながっていました。 ダンプデータを見ると確かに (1) は 1行目のデータの後ろに 0x0A の 改行コードがあり、(2)、(3) では0x0A の改行コードがありませんでした。 (1)上記プログラムを実行(ライン数:24、カラム:80) 結果=>NG <cat -vt データ> [nabe@upsx3 testkana]$ cat -vt type16-24 M-%M-9M-%M-/M-%M-jM-%M-WM-%M-HM-$M-O Wed Apr 4 15:47:27 2001 M-$M-KM-3M-+M-;M-OM-$M-7M-$M-^M-$M-7M-$M-?[nabe@upsx3 testkana]$ a.out^M ^[7^[[?47h^[[1;24r^[[m^[[4l^[[H^[[2J^[[11;17HM-^NM-1M-^NM-1M-^NM-1M-^NM-1M-^NM-1M-^NM-1M-^NM-1M-^NM-1M-^NM-1M-^NM-1 ^[[20DM-^NM-2M-^NM-2M-^NM-2M-^NM-2M-^NM-2M-^NM-2M-^NM-2M-^NM-2M-^NM-2M-^NM-2^[[24;1H^[[2J^[[?47l^[8^M^[[?1l^[>[nabe@upsx3 testkana]$ exit^M exit^M M-%M-9M-%M-/M-%M-jM-%M-WM-%M-HM-$M-O Wed Apr 4 15:47:45 2001 M-$M-KM-=M-*M-NM-;M-$M-7M-$M-^M-$M-7M-$M-?[nabe@upsx3 testkana]$ <ダンプデータ> 00000000 A5 B9 A5 AF A5 EA A5 D7 A5 C8 A4 CF 20 57 65 64 00000010 20 41 70 72 20 20 34 20 31 35 3A 34 37 3A 32 37 00000020 20 32 30 30 31 0A 20 A4 CB B3 AB BB CF A4 B7 A4 00000030 DE A4 B7 A4 BF 5B 6E 61 62 65 40 75 70 73 78 33 00000040 20 74 65 73 74 6B 61 6E 61 5D 24 20 61 2E 6F 75 00000050 74 0D 0A 1B 37 1B 5B 3F 34 37 68 1B 5B 31 3B 32 00000060 34 72 1B 5B 6D 1B 5B 34 6C 1B 5B 48 1B 5B 32 4A 00000070 1B 5B 31 31 3B 31 37 48 8E B1 8E B1 8E B1 8E B1 00000080 8E B1 8E B1 8E B1 8E B1 8E B1 8E B1 0A 1B 5B 32 00000090 30 44 8E B2 8E B2 8E B2 8E B2 8E B2 8E B2 8E B2 000000A0 8E B2 8E B2 8E B2 1B 5B 32 34 3B 31 48 1B 5B 32 000000B0 4A 1B 5B 3F 34 37 6C 1B 38 0D 1B 5B 3F 31 6C 1B 000000C0 3E 5B 6E 61 62 65 40 75 70 73 78 33 20 74 65 73 000000D0 74 6B 61 6E 61 5D 24 20 65 78 69 74 0D 0A 65 78 000000E0 69 74 0D 0A 0A A5 B9 A5 AF A5 EA A5 D7 A5 C8 A4 000000F0 CF 20 57 65 64 20 41 70 72 20 20 34 20 31 35 3A 00000100 34 37 3A 34 35 20 32 30 30 31 0A 20 A4 CB BD AA 00000110 CE BB A4 B7 A4 DE A4 B7 A4 BF (2)上記プログラムを実行(ライン数:25、カラム:80) 結果=>OK <cat -vt データ> [nabe@upsx3 testkana]$ cat -vt type16-25 M-%M-9M-%M-/M-%M-jM-%M-WM-%M-HM-$M-O Wed Apr 4 15:49:58 2001 M-$M-KM-3M-+M-;M-OM-$M-7M-$M-^M-$M-7M-$M-?[nabe@upsx3 testkana]$ a.out^M ^[7^[[?47h^[[1;25r^[[m^[[4l^[[H^[[2J^[[11;17HM-^NM-1M-^NM-1M-^NM-1M-^NM-1M-^NM-1M-^NM-1M-^NM-1M-^NM-1M-^NM-1M-^NM-1^[[12;17HM-^NM-2M-^NM-2M-^NM-2M-^NM-2M-^NM-2M-^NM-2M-^NM-2M-^NM-2M-^NM-2M-^NM-2^[[25;1H^[[2J^[[?47l^[8^M^[[?1l^[>[nabe@upsx3testkana]$ exit^M exit^M M-%M-9M-%M-/M-%M-jM-%M-WM-%M-HM-$M-O Wed Apr 4 15:50:13 2001 M-$M-KM-=M-*M-NM-;M-$M-7M-$M-^M-$M-7M-$M-?[nabe@upsx3 testkana]$ <ダンプデータ> 00000000 A5 B9 A5 AF A5 EA A5 D7 A5 C8 A4 CF 20 57 65 64 00000010 20 41 70 72 20 20 34 20 31 35 3A 34 39 3A 35 38 00000020 20 32 30 30 31 0A 20 A4 CB B3 AB BB CF A4 B7 A4 00000030 DE A4 B7 A4 BF 5B 6E 61 62 65 40 75 70 73 78 33 00000040 20 74 65 73 74 6B 61 6E 61 5D 24 20 61 2E 6F 75 00000050 74 0D 0A 1B 37 1B 5B 3F 34 37 68 1B 5B 31 3B 32 00000060 35 72 1B 5B 6D 1B 5B 34 6C 1B 5B 48 1B 5B 32 4A 00000070 1B 5B 31 31 3B 31 37 48 8E B1 8E B1 8E B1 8E B1 00000080 8E B1 8E B1 8E B1 8E B1 8E B1 8E B1 1B 5B 31 32 00000090 3B 31 37 48 8E B2 8E B2 8E B2 8E B2 8E B2 8E B2 000000A0 8E B2 8E B2 8E B2 8E B2 1B 5B 32 35 3B 31 48 1B 000000B0 5B 32 4A 1B 5B 3F 34 37 6C 1B 38 0D 1B 5B 3F 31 000000C0 6C 1B 3E 5B 6E 61 62 65 40 75 70 73 78 33 20 74 000000D0 65 73 74 6B 61 6E 61 5D 24 20 65 78 69 74 0D 0A 000000E0 65 78 69 74 0D 0A 0A A5 B9 A5 AF A5 EA A5 D7 A5 000000F0 C8 A4 CF 20 57 65 64 20 41 70 72 20 20 34 20 31 00000100 35 3A 35 30 3A 31 33 20 32 30 30 31 0A 20 A4 CB 00000110 BD AA CE BB A4 B7 A4 DE A4 B7 A4 BF (3)上記プログラムを (10,15) (11,15) から書き出すように修正して実行 (ライン数:24、カラム:80) 結果=>OK <cat -vt データ> [nabe@upsx3 testkana]$ cat -vt type15-24 M-%M-9M-%M-/M-%M-jM-%M-WM-%M-HM-$M-O Wed Apr 4 15:51:54 2001 M-$M-KM-3M-+M-;M-OM-$M-7M-$M-^M-$M-7M-$M-?[nabe@upsx3 testkana]$ a.out^M ^[7^[[?47h^[[1;24r^[[m^[[4l^[[H^[[2J^[[11;16HM-^NM-1M-^NM-1M-^NM-1M-^NM-1M-^NM-1M-^NM-1M-^NM-1M-^NM-1M-^NM-1M-^NM-1^[[12;16HM-^NM-2M-^NM-2M-^NM-2M-^NM-2M-^NM-2M-^NM-2M-^NM-2M-^NM-2M-^NM-2M-^NM-2^[[24;1H^[[2J^[[?47l^[8^M^[[?1l^[>[nabe@upsx3testkana]$ exit^M exit^M M-%M-9M-%M-/M-%M-jM-%M-WM-%M-HM-$M-O Wed Apr 4 15:52:05 2001 M-$M-KM-=M-*M-NM-;M-$M-7M-$M-^M-$M-7M-$M-?[nabe@upsx3 testkana]$ <ダンプデータ> 00000000 A5 B9 A5 AF A5 EA A5 D7 A5 C8 A4 CF 20 57 65 64 00000010 20 41 70 72 20 20 34 20 31 35 3A 35 31 3A 35 34 00000020 20 32 30 30 31 0A 20 A4 CB B3 AB BB CF A4 B7 A4 00000030 DE A4 B7 A4 BF 5B 6E 61 62 65 40 75 70 73 78 33 00000040 20 74 65 73 74 6B 61 6E 61 5D 24 20 61 2E 6F 75 00000050 74 0D 0A 1B 37 1B 5B 3F 34 37 68 1B 5B 31 3B 32 00000060 34 72 1B 5B 6D 1B 5B 34 6C 1B 5B 48 1B 5B 32 4A 00000070 1B 5B 31 31 3B 31 36 48 8E B1 8E B1 8E B1 8E B1 00000080 8E B1 8E B1 8E B1 8E B1 8E B1 8E B1 1B 5B 31 32 00000090 3B 31 36 48 8E B2 8E B2 8E B2 8E B2 8E B2 8E B2 000000A0 8E B2 8E B2 8E B2 8E B2 1B 5B 32 34 3B 31 48 1B 000000B0 5B 32 4A 1B 5B 3F 34 37 6C 1B 38 0D 1B 5B 3F 31 000000C0 6C 1B 3E 5B 6E 61 62 65 40 75 70 73 78 33 20 74 000000D0 65 73 74 6B 61 6E 61 5D 24 20 65 78 69 74 0D 0A 000000E0 65 78 69 74 0D 0A 0A A5 B9 A5 AF A5 EA A5 D7 A5 000000F0 C8 A4 CF 20 57 65 64 20 41 70 72 20 20 34 20 31 00000100 35 3A 35 32 3A 30 35 20 32 30 30 31 0A 20 A4 CB 00000110 BD AA CE BB A4 B7 A4 DE A4 B7 A4 BF 以上
補足
punchan_jp さん、解析、アドバイスありがとうございました。 とても参考になりました。 原因がわからなかったためモヤモヤしていましたが、原因がわかって すっきりしました。 私の方もいろいろ試したところ、なんとか回避できそうです。 curses が明示的に座標にジャンプする/しないの条件はわからないのですが、 行の最後で改行コードを入れるとOKみたいです。 実際のコードでは、半角カナのデータを仮想画面に書いた後 mvprintw(x, (COLS - 1), "\n"); としました。 で、refresh() 関数で物理画面に描画すれば乱れませんでした。 ただし、半角カナのデータの最後に「\n」を付加した場合は駄目でした。 あと、refresh() 前に move() 関数でカーソル移動させるとカーソル位置が 乱れてしまいました。 カーソル移動は物理描画後にしました。 UNIX、Linux では半角カナを使わないのがいいんですが、どうしても 使わなきゃいけなかったので苦労しました。。。 本当にご協力ありがとうございました。 感謝します。