curses.h

UNIXの話ですが。
昔懐かしいDOSのような、テキストのユーティリティを作る際に楽になるcurses.hをいじって遊んでみた。ちなみに、テキスト処理はPerlでやっちゃえば楽だし、ユーティリティ系ならX上でJava/Swingの方が全然楽ちんなんで、今時あえてC言語でやる意味はほとんどありません。

ご存じの通り、UNIX系のOSのコンソールは基本は「カノニカルモード」で動作しています。コイツ、大昔のキーボード+プリンタという構成のコンソールで動くことまで考えていて、色々な端末(Vt100とかxtermとかdttermとかetc..etc..)入出力にバッファが噛んでたりと、大変素晴らしいのですが、スクリーンどころかウインドウが標準の今はかえってじゃまな代物。1文字入力させたくても、必ずEnterまで入力する必要があったり...と、不便。viとかのフルスクリーンエディタとかだと、DOSの如く画面とキーボードの制御を乗っ取って動作してますよね。それが、ノンカノニカルモードとかRAWモードって奴。でも、全部自分で面倒見なきゃならなくて、とっても大変なのですよ。という事で、curses.hというのが用意されてて、その辺の面倒は引き受けてくれるのらしいのです。

(ちなみに手でRawモードにするには、#include <termios.h>して、tcgetattrとかtcsetattrを呼び出して、とりあえず現在の状態を保存しておいたり、termios構造体のc_lflagフィールドのICANONフラグをオフにしたり、cbreakモードに変更したり...と非常に面倒。その上、Rawモードに変更した後も端末種別毎に制御が必要だったりして...そんなの、手で書いてたらいつまでたっても終わりません。)


Cで書いた例ですが、とりあえずインクルードして、

#include <curses.h>

と思ったのですが、MacOS X 10.4のGCC-4.0だと標準ライブラリに含まれてないようなので、コンパイル時は次のようにgccのオプションでcurses.hを明示します。(LinuxとかSolarisだと問題ないです。)
gcc -o test test.c -lcurses

プログラムの頭でこんな感じで呼び出しておきます。

/* cursesの初期化 */
initscr();
cbreak();
noecho();

おっと、initscr();した後はprintfとかscanfとかは使わないでください。


画面の表示には

カーソル位置を指定
move( cy, cx);
表示
printw("%c", chr);
カーソル位置を指定して表示
mvprintw( cy, cx, "%c", chr);

とかが使えます。

キーの入力は

*c = (char)getch();

とか、1文字ずつ入力になります。けど、Enterキーが不要になるので、スクリーンで操作するアプリが作りたいなら、便利です。

最後に、プログラムを終了するときは

endwin();

をしてください。それ以後、元のコンソールに戻ります。


おおざっぱ過ぎですが、以上の手順でスクリーンとキーボードが自由に使えるようになる...という事らしいです。

これで、テキストのユーティリティ作ったり、古ゲーもどき作ったり出来ますね。

ちなみにPerldocにもioctlの云々が書いてあって、perlでもユーティリティが作れそうです。(そっちは全然知りませんが)

ちなみにcurses.hで懐かしの3D迷路ゲーム作ったのですが、ソース上げられないのでスクリーンショットだけ。


curses.hサンプル画像