terminfoメモ(libev化)
とりあえず、libevでメインループを置き換えてみる。node.jsで使っているのは、memcacheのlibeventじゃなくてlibevの方だった。
// g++ -o cursor -g cursor.cpp -g -lcurses -lreadline -lev #include <stdlib.h> #include <term.h> #include <curses.h> #include <errno.h> #include <readline/readline.h> #include <ev.h> #include <fcntl.h> class Termios { struct termios save_term; struct termios temp_term; void update() { errno = 0; if(tcsetattr(fileno(stdin), TCSANOW, &temp_term) == -1){ perror("tcsetattr failure"); exit(EXIT_FAILURE); } } public: Termios() { // save term errno = 0; if(tcgetattr(fileno(stdin), &save_term) == -1){ perror("tcgetattr failure"); exit(EXIT_FAILURE); } temp_term=save_term; } ~Termios() { restore(); } void no_canonical() { temp_term.c_iflag &= IGNCR; temp_term.c_oflag &= ONLRET; temp_term.c_lflag &= (~ISIG & ~ICANON & ~ECHO); temp_term.c_cc[VMIN] = 1; temp_term.c_cc[VTIME] = 5; update(); } void restore() { tcsetattr(fileno(stdin), TCSANOW, &save_term); temp_term=save_term; } void echo(bool enable) { if(enable){ temp_term.c_lflag |= ECHO; } else{ temp_term.c_lflag &= ~ECHO; } update(); } }; class Terminfo { public: static void initialize() { if(setupterm(NULL, fileno(stdout), (int *)0) == ERR){ fprintf(stderr,"setupterm failure\n"); exit(EXIT_FAILURE); } cmd("clear"); } static void cmd(const char *cmd) { errno=0; char *parmcmd=tparm(tigetstr(cmd)); if(parmcmd==NULL){ perror("tparm NULL"); exit(EXIT_FAILURE); } tputs(parmcmd, 1, putchar); } }; Termios termios; // all watcher callbacks have a similar signature // this callback is called when data is readable on stdin static void stdin_cb (EV_P_ ev_io *w, int revents) { if(revents & EV_READ){ int c; while((c=getchar())!=EOF){ switch(c) { default: break; case 'q': ev_unloop(EV_A_ EVUNLOOP_ALL); break; case 'h': Terminfo::cmd("cub1"); break; case 'j': Terminfo::cmd("cud1"); break; case 'k': Terminfo::cmd("cuu1"); break; case 'l': Terminfo::cmd("cuf1"); break; case ' ': termios.echo(true); readline("input:"); termios.echo(false); break; } } } } int main(int argc, char **argv) { termios.no_canonical(); Terminfo::initialize(); fcntl(fileno(stdin), F_SETFL, O_NONBLOCK); // setup libev struct ev_loop *loop = EV_DEFAULT; ev_io stdin_watcher; ev_io_init (&stdin_watcher, stdin_cb, fileno(stdin), EV_READ); ev_io_start (loop, &stdin_watcher); // start libev ev_loop(loop, 0); return 0; }