diff --git a/examples/demo.c b/examples/demo.c index 8af1e27..b19fb7d 100644 --- a/examples/demo.c +++ b/examples/demo.c @@ -122,7 +122,7 @@ fprintf(stderr, "w %i, h %i, stride %i\n", bufx, bufy, bufpitch); else if(event & CACA_EVENT_KEY_PRESS) { handle_key: - switch(event & 0xff) + switch(event & 0xffff) { case 'q': case 'Q': diff --git a/src/caca.c b/src/caca.c index d3cae94..9037382 100644 --- a/src/caca.c +++ b/src/caca.c @@ -60,6 +60,7 @@ char *_caca_empty_line; char *_caca_scratch_line; #if defined(USE_NCURSES) +static mmask_t oldmask; int _caca_attr[16]; #endif @@ -124,6 +125,7 @@ int caca_init(void) #elif defined(USE_NCURSES) int i; + mmask_t newmask; initscr(); keypad(stdscr, TRUE); @@ -133,6 +135,9 @@ int caca_init(void) nodelay(stdscr, TRUE); curs_set(0); + newmask = ALL_MOUSE_EVENTS; + mousemask(newmask, &oldmask); + start_color(); init_pair(1 + CACA_COLOR_BLACK, COLOR_BLACK, COLOR_BLACK); @@ -306,6 +311,7 @@ void caca_end(void) SLang_reset_tty(); SLsmg_reset_smg(); #elif defined(USE_NCURSES) + mousemask(oldmask, NULL); curs_set(1); endwin(); #elif defined(USE_CONIO) diff --git a/src/caca.h b/src/caca.h index a1a2243..c70540d 100644 --- a/src/caca.h +++ b/src/caca.h @@ -145,7 +145,7 @@ void caca_end(void); /* * Events */ -int caca_get_event(void); +unsigned int caca_get_event(void); /* * Character graphics diff --git a/src/io.c b/src/io.c index c4fccab..3796cbd 100644 --- a/src/io.c +++ b/src/io.c @@ -42,137 +42,166 @@ #include "caca.h" #include "caca_internals.h" -static void _push_key(unsigned char); -static unsigned char _pop_key(void); -static unsigned char _read_key(void); +static void _push_key(unsigned int); +static unsigned int _pop_key(void); +static unsigned int _read_key(void); -static unsigned char back[5] = {0, 0, 0, 0, 0}; +#define KEY_BUFLEN 10 +static unsigned int keybuf[KEY_BUFLEN + 1]; /* zero-terminated */ +static int keys = 0; -int caca_get_event(void) +unsigned int caca_get_event(void) { - unsigned char key[6]; + unsigned int event = 0; - /* If there were legacy keys, pop them */ - key[0] = _pop_key(); - if(key[0]) - return CACA_EVENT_KEY_PRESS | key[0]; + /* Read all available key events */ + while(keys < KEY_BUFLEN) + { + unsigned int key = _read_key(); + if(!key) + break; + _push_key(key); + } - key[0] = _read_key(); - if(!key[0]) + if(!keys) return 0; - if(key[0] != 0x1b) - return CACA_EVENT_KEY_PRESS | key[0]; +#if defined(USE_NCURSES) + if(keybuf[0] == KEY_MOUSE) + { + MEVENT mevent; + _pop_key(); + getmouse(&mevent); - /* - * Handle escape sequences - */ + event |= (1) << 16; + event |= (mevent.x) << 8; + event |= (mevent.y) << 0; - key[1] = _read_key(); - if(!key[1]) - return CACA_EVENT_KEY_PRESS | key[0]; + return CACA_EVENT_MOUSE_CLICK | event; + } - key[2] = _read_key(); - if(!key[2]) + switch(keybuf[0]) { - _push_key(key[1]); - return CACA_EVENT_KEY_PRESS | key[0]; + case KEY_UP: event = CACA_EVENT_KEY_PRESS | CACA_KEY_UP; break; + case KEY_DOWN: event = CACA_EVENT_KEY_PRESS | CACA_KEY_DOWN; break; + case KEY_LEFT: event = CACA_EVENT_KEY_PRESS | CACA_KEY_LEFT; break; + case KEY_RIGHT: event = CACA_EVENT_KEY_PRESS | CACA_KEY_RIGHT; break; + + case KEY_F(1): event = CACA_EVENT_KEY_PRESS | CACA_KEY_F1; break; + case KEY_F(2): event = CACA_EVENT_KEY_PRESS | CACA_KEY_F2; break; + case KEY_F(3): event = CACA_EVENT_KEY_PRESS | CACA_KEY_F3; break; + case KEY_F(4): event = CACA_EVENT_KEY_PRESS | CACA_KEY_F4; break; + case KEY_F(5): event = CACA_EVENT_KEY_PRESS | CACA_KEY_F5; break; + case KEY_F(6): event = CACA_EVENT_KEY_PRESS | CACA_KEY_F6; break; + case KEY_F(7): event = CACA_EVENT_KEY_PRESS | CACA_KEY_F7; break; + case KEY_F(8): event = CACA_EVENT_KEY_PRESS | CACA_KEY_F8; break; + case KEY_F(9): event = CACA_EVENT_KEY_PRESS | CACA_KEY_F9; break; + case KEY_F(10): event = CACA_EVENT_KEY_PRESS | CACA_KEY_F10; break; + case KEY_F(11): event = CACA_EVENT_KEY_PRESS | CACA_KEY_F11; break; + case KEY_F(12): event = CACA_EVENT_KEY_PRESS | CACA_KEY_F12; break; } - if(key[1] == 'O') + if(event) { - /* ^[OP ^[OQ ^[OR ^[OS */ - switch(key[2]) - { - case 'P': return CACA_EVENT_KEY_PRESS | CACA_KEY_F1; - case 'Q': return CACA_EVENT_KEY_PRESS | CACA_KEY_F2; - case 'R': return CACA_EVENT_KEY_PRESS | CACA_KEY_F3; - case 'S': return CACA_EVENT_KEY_PRESS | CACA_KEY_F4; - } + _pop_key(); + return event; } - else if(key[1] == '[') - { - /* ^[[A ^[[B ^[[C ^[[D */ - switch(key[2]) - { - case 'A': return CACA_EVENT_KEY_PRESS | CACA_KEY_UP; - case 'B': return CACA_EVENT_KEY_PRESS | CACA_KEY_DOWN; - case 'C': return CACA_EVENT_KEY_PRESS | CACA_KEY_RIGHT; - case 'D': return CACA_EVENT_KEY_PRESS | CACA_KEY_LEFT; - } +#endif - key[3] = _read_key(); - key[4] = _read_key(); + if(keybuf[0] != '\x1b') + return CACA_EVENT_KEY_PRESS | _pop_key(); - /* ^[[Mxxx */ - if(key[2] == 'M') - { - int event = CACA_EVENT_MOUSE_CLICK; - - key[5] = _read_key(); + /* + * Handle known escape sequences + */ - event |= (int)(key[3] - ' ') << 16; - event |= (int)(key[4] - '!') << 8; - event |= (int)(key[5] - '!') << 0; + _pop_key(); - return event; - } + if(keybuf[0] == 'O' && keybuf[1] >= 'P' && keybuf[1] <= 'S') + { + /* ^[OP ^[OQ ^[OR ^[OS */ + static unsigned int keylist[] = + { CACA_KEY_F1, CACA_KEY_F2, CACA_KEY_F3, CACA_KEY_F4 }; + _pop_key(); + return CACA_EVENT_KEY_PRESS | keylist[_pop_key() - 'P']; + } + else if(keybuf[0] == '[' && keybuf[1] >= 'A' && keybuf[1] <= 'D') + { + /* ^[[A ^[[B ^[[C ^[[D */ + static unsigned int keylist[] = + { CACA_KEY_UP, CACA_KEY_DOWN, CACA_KEY_RIGHT, CACA_KEY_LEFT }; + _pop_key(); + return CACA_EVENT_KEY_PRESS | keylist[_pop_key() - 'A']; + } + else if(keybuf[0] == '[' && keybuf[1] == 'M' && + keybuf[2] && keybuf[3] && keybuf[3]) + { + /* ^[[Mxxx */ + _pop_key(); + _pop_key(); + event |= (_pop_key() - ' ') << 16; + event |= (_pop_key() - '!') << 8; + event |= (_pop_key() - '!') << 0; + return CACA_EVENT_MOUSE_CLICK | event; + } + else if(keybuf[0] == '[' && keybuf[1] == '1' && keybuf[3] == '~' && + keybuf[2] >= '5' && keybuf[2] != '6' && keybuf[2] <= '9') + { /* ^[[15~ ^[[17~ ^[[18~ ^[[19~ */ - if(key[2] == '1' && key[4] == '~') - switch(key[3]) - { - case '5': return CACA_EVENT_KEY_PRESS | CACA_KEY_F5; - case '7': return CACA_EVENT_KEY_PRESS | CACA_KEY_F6; - case '8': return CACA_EVENT_KEY_PRESS | CACA_KEY_F7; - case '9': return CACA_EVENT_KEY_PRESS | CACA_KEY_F8; - } - + static unsigned int keylist[] = + { CACA_KEY_F5, 0, CACA_KEY_F6, CACA_KEY_F7, CACA_KEY_F8 }; + _pop_key(); + _pop_key(); + event = CACA_EVENT_KEY_PRESS | keylist[_pop_key() - '5']; + _pop_key(); + return event; + } + else if(keybuf[0] == '[' && keybuf[1] == '2' && keybuf[3] == '~' && + keybuf[2] >= '0' && keybuf[2] != '2' && keybuf[2] <= '4') + { /* ^[[20~ ^[[21~ ^[[23~ ^[[24~ */ - if(key[2] == '2' && key[4] == '~') - switch(key[3]) - { - case '0': return CACA_EVENT_KEY_PRESS | CACA_KEY_F9; - case '1': return CACA_EVENT_KEY_PRESS | CACA_KEY_F10; - case '3': return CACA_EVENT_KEY_PRESS | CACA_KEY_F11; - case '4': return CACA_EVENT_KEY_PRESS | CACA_KEY_F12; - } - - _push_key(key[4]); - _push_key(key[3]); + static unsigned int keylist[] = + { CACA_KEY_F9, CACA_KEY_F10, 0, CACA_KEY_F11, CACA_KEY_F12 }; + _pop_key(); + _pop_key(); + event = CACA_EVENT_KEY_PRESS | keylist[_pop_key() - '0']; + _pop_key(); + return event; } - /* Unknown escape sequence: return each key one after the other */ - _push_key(key[2]); - _push_key(key[1]); - return CACA_EVENT_KEY_PRESS | key[0]; +caca_printf(0,0, "unknown esc sequence %2x %2x %2x %2x %2x\n", '\x1b', keybuf[0], keybuf[1], keybuf[2], keybuf[3]); + /* Unknown escape sequence: return the ESC key */ + return CACA_EVENT_KEY_PRESS | '\x1b'; } -static void _push_key(unsigned char key) +static void _push_key(unsigned int key) { - back[4] = back[3]; - back[3] = back[2]; - back[2] = back[1]; - back[1] = back[0]; - back[0] = key; + if(keys == KEY_BUFLEN) + return; + keybuf[keys] = key; + keys++; + keybuf[keys] = 0; } -static unsigned char _pop_key(void) +static unsigned int _pop_key(void) { - unsigned char key = back[0]; - back[0] = back[1]; - back[1] = back[2]; - back[2] = back[3]; - back[3] = back[4]; + int i; + unsigned int key = keybuf[0]; + keys--; + for(i = 0; i < keys; i++) + keybuf[i] = keybuf[i + 1]; + keybuf[keys] = 0; + return key; } -static unsigned char _read_key(void) +static unsigned int _read_key(void) { #if defined(USE_SLANG) return SLang_input_pending(0) ? SLang_getkey() : 0; #elif defined(USE_NCURSES) - unsigned char key = getch(); + int key = getch(); return (key == ERR) ? 0 : key; #elif defined(USE_CONIO) return _conio_kbhit() ? getch() : 0;