CUIでいろいろと。
実験第二用に、ためしに作ったcurses*1のプログラム。0行目に入力欄があって、2行目以降に文字列が下に流れていくだけ。これをチャットに改造しようかと。
コンパイルは、
cc curses_test.c -lcurses
で。
参考にしたのはここら辺。http://publib16.boulder.ibm.com/pseries/Ja_JP/aixprggd/genprogc/mastertoc.htm#ToC_17
ここも使えそう。http://docs.hp.com/ja/B2355-90858/curses.5.html
#include <time.h> #include <sys/select.h> #include <curses.h> #define BUFSIZE 1024 #define OUTPUT_LINE 2 // 表示領域の最初の行。( 0〜(LINES-1) ) void output_line( char * str ){ int x, y; getyx( stdscr, y, x ); // 元の位置を覚えておく。 move( OUTPUT_LINE, 0 ); insertln( ); addstr( "> " ); addstr( str ); move( y, x ); // 元の位置に戻す。 } void reset_input_area( ){ move( 0, 0 ); deleteln( ); // 1度消して、 insertln( ); // 新しく追加。 addstr( "< " ); } // キーボードからの入力。 void input_keybord( char * buf, int * buf_len, int * loop ){ int c; c = getch( ); if( c == '\n' ){ // 改行の場合。 buf[ *buf_len ] = '\0'; // 終了条件チェック。 if( ( strcmp( buf, "." ) == 0 ) || ( strcasecmp( buf, "q" ) == 0 ) || ( strcasecmp( buf, "quit" ) == 0 ) || ( strcasecmp( buf, "exit" ) == 0 ) ){ *loop = 0; return; } // 出力。 output_line( buf ); *buf_len = 0; // buf[]を空に。 // 入力欄クリア。 reset_input_area( ); }else if( c == KEY_DOWN ){ // keypad をtrueにしないとこない。 *loop = 0; }else if( c == KEY_BACKSPACE ){ delch( ); (*buf_len)--; if( *buf_len < 0 ) *buf_len = 0; }else if( ( c == '' ) || // '^'+'D'じゃなくて、'C-d'。 ( c == '!' ) ){ output_line( "!" ); *loop = 0; }else if( c == '' ){ reset_input_area( ); buf[ *buf_len ] = '\0'; addstr( buf ); }else{ // その他の文字。 if(0){ //test char buf[1024]; sprintf( buf, "0x%02X", c ); output_line( buf ); } if( BUFSIZE - 1 <= *buf_len ) return; // bufがいっぱいだったらそのまま捨てる。 if( c > 0xff ) return; // その他の特殊キーだったら捨てる。 buf[ (*buf_len)++ ] = c; } } main(){ char buf[ BUFSIZE ]; int buf_len = 0; time_t time_now; const int stdin_fd = 0; // = fileno( stdin ) fd_set input_fds; struct timeval sleep; int r_select; int i; int loop; initscr( ); // cursesの初期化。 cbreak( ); // いらないけどなんとなく。 echo( ); // いらないけどなんとなく。 keypad( stdscr, TRUE ); // (0行目の次の)1行目に線を引く。 for( i = 0; i < COLS; i++ ){ mvaddch( 1, i, ACS_HLINE ); // 横線を引く。 } reset_input_area( ); refresh( ); sleep.tv_sec = 0; sleep.tv_usec = 0; loop = 1; while( loop ){ FD_ZERO( &input_fds ); FD_SET( stdin_fd, &input_fds ); r_select = select( 1, &input_fds, NULL, NULL, &sleep ); if( r_select > 0 ){ // 入力がある。 if( FD_ISSET( stdin_fd, &input_fds ) ){ // キーボードからの入力。 input_keybord( buf, &buf_len, &loop ); } }else if( r_select == 0 ){ // 時間切れ。 time_now = time( NULL ); output_line( ctime( &time_now ) ); sleep.tv_sec = 1; sleep.tv_usec = 0; } refresh( ); } // end while( loop ) endwin( ); // cursesの終了。 }
xとyの順番が普通と逆なのがややこしいなぁ。y行目のx文字目って感じか。
BackSpaceがいやな感じ。うまいことやってくれないのかなぁ。nocbreak()とかやったら、echoされなくなるし。なんでよ。
最近、前一文字削除はC-hを使ってたので、BackSpaceのキーと動作が違うことに気づかんかった。
C-z と C-c は使える。C-h, C-j, C-m, C-iも。C-tはscreen、C-oはxkeymacsで乗っ取ってるのでわからん。
いい終了方法が思いつかなかった。C-dあたりかな、とも思うんだけど。
*1:ところでcursesって、どうよむの? あ、wikipediaにあるじゃん。カーシスだってさ。http://ja.wikipedia.org/wiki/Curses