diff --git a/src/caca.h b/src/caca.h index d1cb0e3..a8617c5 100644 --- a/src/caca.h +++ b/src/caca.h @@ -191,11 +191,29 @@ enum caca_event */ enum caca_key { + CACA_KEY_UNKNOWN = 0, /**< Unknown key. */ + + /* The following keys have ASCII equivalents */ + CACA_KEY_BACKSPACE = 8, /**< The backspace key. */ + CACA_KEY_TAB = 9, /**< The tabulation key. */ + CACA_KEY_RETURN = 13, /**< The return key. */ + CACA_KEY_PAUSE = 19, /**< The pause key. */ + CACA_KEY_ESCAPE = 27, /**< The escape key. */ + CACA_KEY_DELETE = 127, /**< The delete key. */ + + /* The following keys do not have ASCII equivalents but have been + * chosen to match the SDL equivalents */ CACA_KEY_UP = 273, /**< The up arrow key. */ CACA_KEY_DOWN = 274, /**< The down arrow key. */ CACA_KEY_LEFT = 275, /**< The left arrow key. */ CACA_KEY_RIGHT = 276, /**< The right arrow key. */ + CACA_KEY_INSERT = 277, /**< The insert key. */ + CACA_KEY_HOME = 278, /**< The home key. */ + CACA_KEY_END = 279, /**< The end key. */ + CACA_KEY_PAGEUP = 280, /**< The page up key. */ + CACA_KEY_PAGEDOWN = 281, /**< The page down key. */ + CACA_KEY_F1 = 282, /**< The F1 key. */ CACA_KEY_F2 = 283, /**< The F2 key. */ CACA_KEY_F3 = 284, /**< The F3 key. */ diff --git a/src/graphics.c b/src/graphics.c index 95adcb3..dba8700 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -632,6 +632,9 @@ int _caca_init_graphics(void) return -1; } + memset(x11_char, 0, _caca_width * _caca_height * sizeof(int)); + memset(x11_attr, 0, _caca_width * _caca_height * sizeof(int)); + x11_dpy = XOpenDisplay(NULL); if(x11_dpy == NULL) { diff --git a/src/io.c b/src/io.c index 4bf9a3d..3ef068c 100644 --- a/src/io.c +++ b/src/io.c @@ -78,15 +78,18 @@ static int events = 0; * * This function polls the event queue for mouse or keyboard events matching * the event mask and returns the first matching event. Non-matching events - * are discarded. It is non-blocking and returns zero if no more events are - * pending in the queue. See also caca_wait_event() for a blocking version - * of this function. + * are discarded. \c event_mask must have a non-zero value. This function is + * non-blocking and returns zero if no more events are pending in the queue. + * See also caca_wait_event() for a blocking version of this function. * * \param event_mask Bitmask of requested events. * \return The next matching event in the queue, or 0 if no event is pending. */ unsigned int caca_get_event(unsigned int event_mask) { + if(!event_mask) + return CACA_EVENT_NONE; + for( ; ; ) { unsigned int event = _get_next_event(); @@ -100,14 +103,17 @@ unsigned int caca_get_event(unsigned int event_mask) * * This function returns the first mouse or keyboard event in the queue * that matches the event mask. If no event is pending, it blocks until a - * matching event is received. See also caca_get_event() for a non-blocking - * version of this function. + * matching event is received. \c event_mask must have a non-zero value. + * See also caca_get_event() for a non-blocking version of this function. * * \param event_mask Bitmask of requested events. * \return The next event in the queue. */ unsigned int caca_wait_event(unsigned int event_mask) { + if(!event_mask) + return CACA_EVENT_NONE; + for( ; ; ) { unsigned int event = _get_next_event(); @@ -279,11 +285,11 @@ static unsigned int _lowlevel_event(void) case XK_Right: return event | CACA_KEY_RIGHT; case XK_Up: return event | CACA_KEY_UP; case XK_Down: return event | CACA_KEY_DOWN; - default: return 0; + default: return CACA_EVENT_NONE; } } - return 0; + return CACA_EVENT_NONE; } else #endif @@ -292,7 +298,7 @@ static unsigned int _lowlevel_event(void) { int intkey = getch(); if(intkey == ERR) - return 0; + return CACA_EVENT_NONE; if(intkey < 0x100) { @@ -421,28 +427,37 @@ static unsigned int _lowlevel_event(void) return CACA_EVENT_MOUSE_MOTION | (mevent.x << 12) | mevent.y; } + event = CACA_EVENT_KEY_PRESS; + switch(intkey) { - case KEY_UP: event = CACA_KEY_UP; break; - case KEY_DOWN: event = CACA_KEY_DOWN; break; - case KEY_LEFT: event = CACA_KEY_LEFT; break; - case KEY_RIGHT: event = CACA_KEY_RIGHT; break; - - case KEY_F(1): event = CACA_KEY_F1; break; - case KEY_F(2): event = CACA_KEY_F2; break; - case KEY_F(3): event = CACA_KEY_F3; break; - case KEY_F(4): event = CACA_KEY_F4; break; - case KEY_F(5): event = CACA_KEY_F5; break; - case KEY_F(6): event = CACA_KEY_F6; break; - case KEY_F(7): event = CACA_KEY_F7; break; - case KEY_F(8): event = CACA_KEY_F8; break; - case KEY_F(9): event = CACA_KEY_F9; break; - case KEY_F(10): event = CACA_KEY_F10; break; - case KEY_F(11): event = CACA_KEY_F11; break; - case KEY_F(12): event = CACA_KEY_F12; break; + case KEY_UP: return event | CACA_KEY_UP; + case KEY_DOWN: return event | CACA_KEY_DOWN; + case KEY_LEFT: return event | CACA_KEY_LEFT; + case KEY_RIGHT: return event | CACA_KEY_RIGHT; + + case KEY_IC: return event | CACA_KEY_INSERT; + case KEY_DC: return event | CACA_KEY_DELETE; + case KEY_HOME: return event | CACA_KEY_HOME; + case KEY_END: return event | CACA_KEY_END; + case KEY_PPAGE: return event | CACA_KEY_PAGEUP; + case KEY_NPAGE: return event | CACA_KEY_PAGEDOWN; + + case KEY_F(1): return event | CACA_KEY_F1; + case KEY_F(2): return event | CACA_KEY_F2; + case KEY_F(3): return event | CACA_KEY_F3; + case KEY_F(4): return event | CACA_KEY_F4; + case KEY_F(5): return event | CACA_KEY_F5; + case KEY_F(6): return event | CACA_KEY_F6; + case KEY_F(7): return event | CACA_KEY_F7; + case KEY_F(8): return event | CACA_KEY_F8; + case KEY_F(9): return event | CACA_KEY_F9; + case KEY_F(10): return event | CACA_KEY_F10; + case KEY_F(11): return event | CACA_KEY_F11; + case KEY_F(12): return event | CACA_KEY_F12; } - return CACA_EVENT_KEY_PRESS | event; + return CACA_EVENT_NONE; } else #endif @@ -452,10 +467,20 @@ static unsigned int _lowlevel_event(void) int intkey; if(!SLang_input_pending(0)) - return 0; + return CACA_EVENT_NONE; - intkey = SLkp_getkey(); + /* We first use SLang_getkey() to see whether Esc was pressed + * alone, then (if it wasn't) we unget the key and use SLkp_getkey() + * instead, so that escape sequences are interpreted. */ + intkey = SLang_getkey(); + if(intkey != 0x1b /* Esc */ || SLang_input_pending(0)) + { + SLang_ungetkey(intkey); + intkey = SLkp_getkey(); + } + + /* If the key was ASCII, return it immediately */ if(intkey < 0x100) { return CACA_EVENT_KEY_PRESS | intkey; @@ -471,28 +496,37 @@ static unsigned int _lowlevel_event(void) return CACA_EVENT_MOUSE_MOTION | (x << 12) | (y << 0); } + event = CACA_EVENT_KEY_PRESS; + switch(intkey) { - case SL_KEY_UP: event = CACA_KEY_UP; break; - case SL_KEY_DOWN: event = CACA_KEY_DOWN; break; - case SL_KEY_LEFT: event = CACA_KEY_LEFT; break; - case SL_KEY_RIGHT: event = CACA_KEY_RIGHT; break; - - case SL_KEY_F(1): event = CACA_KEY_F1; break; - case SL_KEY_F(2): event = CACA_KEY_F2; break; - case SL_KEY_F(3): event = CACA_KEY_F3; break; - case SL_KEY_F(4): event = CACA_KEY_F4; break; - case SL_KEY_F(5): event = CACA_KEY_F5; break; - case SL_KEY_F(6): event = CACA_KEY_F6; break; - case SL_KEY_F(7): event = CACA_KEY_F7; break; - case SL_KEY_F(8): event = CACA_KEY_F8; break; - case SL_KEY_F(9): event = CACA_KEY_F9; break; - case SL_KEY_F(10): event = CACA_KEY_F10; break; - case SL_KEY_F(11): event = CACA_KEY_F11; break; - case SL_KEY_F(12): event = CACA_KEY_F12; break; + case SL_KEY_UP: return event | CACA_KEY_UP; + case SL_KEY_DOWN: return event | CACA_KEY_DOWN; + case SL_KEY_LEFT: return event | CACA_KEY_LEFT; + case SL_KEY_RIGHT: return event | CACA_KEY_RIGHT; + + case SL_KEY_IC: return event | CACA_KEY_INSERT; + case SL_KEY_DELETE: return event | CACA_KEY_DELETE; + case SL_KEY_HOME: return event | CACA_KEY_HOME; + case SL_KEY_END: return event | CACA_KEY_END; + case SL_KEY_PPAGE: return event | CACA_KEY_PAGEUP; + case SL_KEY_NPAGE: return event | CACA_KEY_PAGEDOWN; + + case SL_KEY_F(1): return event | CACA_KEY_F1; + case SL_KEY_F(2): return event | CACA_KEY_F2; + case SL_KEY_F(3): return event | CACA_KEY_F3; + case SL_KEY_F(4): return event | CACA_KEY_F4; + case SL_KEY_F(5): return event | CACA_KEY_F5; + case SL_KEY_F(6): return event | CACA_KEY_F6; + case SL_KEY_F(7): return event | CACA_KEY_F7; + case SL_KEY_F(8): return event | CACA_KEY_F8; + case SL_KEY_F(9): return event | CACA_KEY_F9; + case SL_KEY_F(10): return event | CACA_KEY_F10; + case SL_KEY_F(11): return event | CACA_KEY_F11; + case SL_KEY_F(12): return event | CACA_KEY_F12; } - return CACA_EVENT_KEY_PRESS | event; + return CACA_EVENT_NONE; } else #endif @@ -500,7 +534,7 @@ static unsigned int _lowlevel_event(void) if(_caca_driver == CACA_DRIVER_CONIO) { if(!_conio_kbhit()) - return 0; + return CACA_EVENT_NONE; event = getch(); _push_event(CACA_EVENT_KEY_RELEASE | event); @@ -512,7 +546,7 @@ static unsigned int _lowlevel_event(void) /* Dummy */ } - return 0; + return CACA_EVENT_NONE; } static void _push_event(unsigned int event) @@ -529,7 +563,7 @@ static unsigned int _pop_event(void) unsigned int event; if(events == 0) - return 0; + return CACA_EVENT_NONE; event = eventbuf[0]; for(i = 1; i < events; i++) diff --git a/test/event.c b/test/event.c index 7238354..4022bad 100644 --- a/test/event.c +++ b/test/event.c @@ -38,18 +38,22 @@ int main(int argc, char **argv) if(caca_init()) return 1; + h = caca_get_height() - 1; + caca_set_color(CACA_COLOR_WHITE, CACA_COLOR_BLUE); caca_draw_line(0, 0, caca_get_width() - 1, 0, ' '); - caca_refresh(); + caca_draw_line(0, h, caca_get_width() - 1, h, ' '); + caca_putstr(0, h, "type \"quit\" to exit"); - h = caca_get_height(); + caca_refresh(); events = malloc(h * sizeof(int)); memset(events, 0, h * sizeof(int)); - for(quit = 0; !quit; ) + for(quit = 0; quit < 4; ) { + static char const * quit_string[] = { "", "q", "qu", "qui", "quit" }; unsigned int event = caca_wait_event(CACA_EVENT_ANY); if(!event) @@ -57,9 +61,18 @@ int main(int argc, char **argv) do { - /* q quits */ - if(event == (CACA_EVENT_KEY_PRESS | 'q')) - quit = 1; + /* "quit" quits */ + if(event & CACA_EVENT_KEY_PRESS) + { + int key = event & ~CACA_EVENT_KEY_PRESS; + if((key == 'q' && quit == 0) || (key == 'u' && quit == 1) + || (key == 'i' && quit == 2) || (key == 't' && quit == 3)) + quit++; + else if(key == 'q') + quit = 1; + else + quit = 0; + } memmove(events + 1, events, (h - 1) * sizeof(int)); events[0] = event; @@ -75,6 +88,9 @@ int main(int argc, char **argv) caca_draw_line(0, 0, caca_get_width() - 1, 0, ' '); print_event(0, 0, events[0]); + caca_draw_line(0, h, caca_get_width() - 1, h, ' '); + caca_printf(0, h, "type \"quit\" to exit: %s", quit_string[quit]); + /* Print previous events */ caca_set_color(CACA_COLOR_WHITE, CACA_COLOR_BLACK); for(i = 1; i < h && events[i]; i++)