You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

835 line
27 KiB

  1. /*
  2. * libcaca ASCII-Art library
  3. * Copyright (c) 2002, 2003 Sam Hocevar <sam@zoy.org>
  4. * All Rights Reserved
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  19. * 02111-1307 USA
  20. */
  21. /** \file event.c
  22. * \version \$Id$
  23. * \author Sam Hocevar <sam@zoy.org>
  24. * \brief Event handling
  25. *
  26. * This file contains event handling functions for keyboard and mouse input.
  27. */
  28. #include "config.h"
  29. #if defined(USE_SLANG)
  30. # if defined(HAVE_SLANG_SLANG_H)
  31. # include <slang/slang.h>
  32. # else
  33. # include <slang.h>
  34. # endif
  35. #endif
  36. #if defined(USE_NCURSES)
  37. # if defined(HAVE_NCURSES_H)
  38. # include <ncurses.h>
  39. # else
  40. # include <curses.h>
  41. # endif
  42. #endif
  43. #if defined(USE_CONIO)
  44. # include <conio.h>
  45. #endif
  46. #if defined(USE_X11)
  47. # include <X11/Xlib.h>
  48. # include <X11/Xutil.h>
  49. # include <X11/keysym.h>
  50. #endif
  51. #if defined(USE_WIN32)
  52. # include <windows.h>
  53. #endif
  54. #if defined(USE_GL)
  55. #include <GL/gl.h>
  56. #include <GL/glut.h>
  57. extern int gl_special_key;
  58. extern unsigned char gl_key;
  59. extern unsigned char gl_resized;
  60. extern float gl_font_width;
  61. extern float gl_font_height;
  62. extern int gl_new_width;
  63. extern int gl_new_height;
  64. extern unsigned char gl_mouse_changed, gl_mouse_clicked;
  65. extern unsigned int gl_mouse_x, gl_mouse_y;
  66. extern unsigned int gl_mouse_button, gl_mouse_state;
  67. #endif
  68. #include "caca.h"
  69. #include "caca_internals.h"
  70. static unsigned int _get_next_event(void);
  71. static unsigned int _lowlevel_event(void);
  72. #if defined(USE_SLANG) || defined(USE_NCURSES) || defined(USE_CONIO)
  73. static void _push_event(unsigned int);
  74. static unsigned int _pop_event(void);
  75. #endif
  76. #if !defined(_DOXYGEN_SKIP_ME)
  77. #define EVENTBUF_LEN 10
  78. #endif
  79. #if defined(USE_SLANG) || defined(USE_NCURSES) || defined(USE_CONIO)
  80. static unsigned int eventbuf[EVENTBUF_LEN];
  81. static int events = 0;
  82. #endif
  83. static unsigned int mouse_x = 0, mouse_y = 0;
  84. #if !defined(_DOXYGEN_SKIP_ME)
  85. /* If no new key was pressed after AUTOREPEAT_THRESHOLD usec, assume the
  86. * key was released */
  87. #define AUTOREPEAT_THRESHOLD 200000
  88. /* Start repeating key after AUTOREPEAT_TRIGGER usec and send keypress
  89. * events every AUTOREPEAT_RATE usec. */
  90. #define AUTOREPEAT_TRIGGER 300000
  91. #define AUTOREPEAT_RATE 100000
  92. #endif
  93. /** \brief Get the next mouse or keyboard input event.
  94. *
  95. * This function polls the event queue for mouse or keyboard events matching
  96. * the event mask and returns the first matching event. Non-matching events
  97. * are discarded. \c event_mask must have a non-zero value. This function is
  98. * non-blocking and returns zero if no more events are pending in the queue.
  99. * See also caca_wait_event() for a blocking version of this function.
  100. *
  101. * \param event_mask Bitmask of requested events.
  102. * \return The next matching event in the queue, or 0 if no event is pending.
  103. */
  104. unsigned int caca_get_event(unsigned int event_mask)
  105. {
  106. if(!event_mask)
  107. return CACA_EVENT_NONE;
  108. for( ; ; )
  109. {
  110. unsigned int event = _get_next_event();
  111. if(!event || event & event_mask)
  112. return event;
  113. }
  114. }
  115. /** \brief Wait for the next mouse or keyboard input event.
  116. *
  117. * This function returns the first mouse or keyboard event in the queue
  118. * that matches the event mask. If no event is pending, it blocks until a
  119. * matching event is received. \c event_mask must have a non-zero value.
  120. * See also caca_get_event() for a non-blocking version of this function.
  121. *
  122. * \param event_mask Bitmask of requested events.
  123. * \return The next event in the queue.
  124. */
  125. unsigned int caca_wait_event(unsigned int event_mask)
  126. {
  127. if(!event_mask)
  128. return CACA_EVENT_NONE;
  129. for( ; ; )
  130. {
  131. unsigned int event = _get_next_event();
  132. if(event & event_mask)
  133. return event;
  134. _caca_sleep(10000);
  135. }
  136. }
  137. /** \brief Return the X mouse coordinate.
  138. *
  139. * This function returns the X coordinate of the mouse position last time
  140. * it was detected. This function is not reliable if the ncurses or S-Lang
  141. * drivers are being used, because mouse position is only detected when
  142. * the mouse is clicked. Other drivers such as X11 work well.
  143. *
  144. * \return The X mouse coordinate.
  145. */
  146. unsigned int caca_get_mouse_x(void)
  147. {
  148. if(mouse_x >= _caca_width)
  149. mouse_x = _caca_width - 1;
  150. return mouse_x;
  151. }
  152. /** \brief Return the Y mouse coordinate.
  153. *
  154. * This function returns the Y coordinate of the mouse position last time
  155. * it was detected. This function is not reliable if the ncurses or S-Lang
  156. * drivers are being used, because mouse position is only detected when
  157. * the mouse is clicked. Other drivers such as X11 work well.
  158. *
  159. * \return The Y mouse coordinate.
  160. */
  161. unsigned int caca_get_mouse_y(void)
  162. {
  163. if(mouse_y >= _caca_height)
  164. mouse_y = _caca_height - 1;
  165. return mouse_y;
  166. }
  167. /*
  168. * XXX: The following functions are local.
  169. */
  170. static unsigned int _get_next_event(void)
  171. {
  172. #if defined(USE_SLANG) || defined(USE_NCURSES)
  173. static struct caca_timer key_timer = CACA_TIMER_INITIALIZER;
  174. static unsigned int last_key_ticks = 0;
  175. static unsigned int autorepeat_ticks = 0;
  176. static unsigned int last_key = 0;
  177. unsigned int ticks;
  178. #endif
  179. unsigned int event;
  180. #if defined(USE_NULL)
  181. if(_caca_driver == CACA_DRIVER_NULL)
  182. return CACA_EVENT_NONE;
  183. #endif
  184. event = _lowlevel_event();
  185. #if defined(USE_SLANG)
  186. if(_caca_driver != CACA_DRIVER_SLANG)
  187. #endif
  188. #if defined(USE_NCURSES)
  189. if(_caca_driver != CACA_DRIVER_NCURSES)
  190. #endif
  191. return event;
  192. #if defined(USE_SLANG) || defined(USE_NCURSES)
  193. /* Simulate long keypresses using autorepeat features */
  194. ticks = _caca_getticks(&key_timer);
  195. last_key_ticks += ticks;
  196. autorepeat_ticks += ticks;
  197. /* Handle autorepeat */
  198. if(last_key && autorepeat_ticks > AUTOREPEAT_TRIGGER
  199. && autorepeat_ticks > AUTOREPEAT_THRESHOLD
  200. && autorepeat_ticks > AUTOREPEAT_RATE)
  201. {
  202. _push_event(event);
  203. autorepeat_ticks -= AUTOREPEAT_RATE;
  204. return CACA_EVENT_KEY_PRESS | last_key;
  205. }
  206. /* We are in autorepeat mode and the same key was just pressed, ignore
  207. * this event and return the next one by calling ourselves. */
  208. if(event == (CACA_EVENT_KEY_PRESS | last_key))
  209. {
  210. last_key_ticks = 0;
  211. return _get_next_event();
  212. }
  213. /* We are in autorepeat mode, but key has expired or a new key was
  214. * pressed - store our event and return a key release event first */
  215. if(last_key && (last_key_ticks > AUTOREPEAT_THRESHOLD
  216. || (event & CACA_EVENT_KEY_PRESS)))
  217. {
  218. _push_event(event);
  219. event = CACA_EVENT_KEY_RELEASE | last_key;
  220. last_key = 0;
  221. return event;
  222. }
  223. /* A new key was pressed, enter autorepeat mode */
  224. if(event & CACA_EVENT_KEY_PRESS)
  225. {
  226. last_key_ticks = 0;
  227. autorepeat_ticks = 0;
  228. last_key = event & 0x00ffffff;
  229. }
  230. return event;
  231. #endif
  232. }
  233. static unsigned int _lowlevel_event(void)
  234. {
  235. unsigned int event;
  236. #if defined(USE_SLANG) || defined(USE_NCURSES) || defined(USE_CONIO)
  237. event = _pop_event();
  238. if(event)
  239. return event;
  240. #endif
  241. #if defined(USE_X11)
  242. /* The X11 event check routine */
  243. if(_caca_driver == CACA_DRIVER_X11)
  244. {
  245. XEvent xevent;
  246. char key;
  247. while(XCheckWindowEvent(x11_dpy, x11_window, x11_event_mask, &xevent)
  248. == True)
  249. {
  250. KeySym keysym;
  251. /* Expose event */
  252. if(xevent.type == Expose)
  253. {
  254. XCopyArea(x11_dpy, x11_pixmap, x11_window, x11_gc, 0, 0,
  255. _caca_width * x11_font_width,
  256. _caca_height * x11_font_height, 0, 0);
  257. continue;
  258. }
  259. /* Resize event */
  260. if(xevent.type == ConfigureNotify)
  261. {
  262. unsigned int w, h;
  263. w = (xevent.xconfigure.width + x11_font_width / 3)
  264. / x11_font_width;
  265. h = (xevent.xconfigure.height + x11_font_height / 3)
  266. / x11_font_height;
  267. if(!w || !h || (w == _caca_width && h == _caca_height))
  268. continue;
  269. x11_new_width = w;
  270. x11_new_height = h;
  271. if(_caca_resize)
  272. continue;
  273. _caca_resize = 1;
  274. return CACA_EVENT_RESIZE;
  275. }
  276. /* Check for mouse motion events */
  277. if(xevent.type == MotionNotify)
  278. {
  279. unsigned int newx = xevent.xmotion.x / x11_font_width;
  280. unsigned int newy = xevent.xmotion.y / x11_font_height;
  281. if(newx >= _caca_width)
  282. newx = _caca_width - 1;
  283. if(newy >= _caca_height)
  284. newy = _caca_height - 1;
  285. if(mouse_x == newx && mouse_y == newy)
  286. continue;
  287. mouse_x = newx;
  288. mouse_y = newy;
  289. return CACA_EVENT_MOUSE_MOTION | (mouse_x << 12) | mouse_y;
  290. }
  291. /* Check for mouse press and release events */
  292. if(xevent.type == ButtonPress)
  293. return CACA_EVENT_MOUSE_PRESS
  294. | ((XButtonEvent *)&xevent)->button;
  295. if(xevent.type == ButtonRelease)
  296. return CACA_EVENT_MOUSE_RELEASE
  297. | ((XButtonEvent *)&xevent)->button;
  298. /* Check for key press and release events */
  299. if(xevent.type == KeyPress)
  300. event |= CACA_EVENT_KEY_PRESS;
  301. else if(xevent.type == KeyRelease)
  302. event |= CACA_EVENT_KEY_RELEASE;
  303. else
  304. continue;
  305. if(XLookupString(&xevent.xkey, &key, 1, NULL, NULL))
  306. return event | key;
  307. keysym = XKeycodeToKeysym(x11_dpy, xevent.xkey.keycode, 0);
  308. switch(keysym)
  309. {
  310. case XK_F1: return event | CACA_KEY_F1;
  311. case XK_F2: return event | CACA_KEY_F2;
  312. case XK_F3: return event | CACA_KEY_F3;
  313. case XK_F4: return event | CACA_KEY_F4;
  314. case XK_F5: return event | CACA_KEY_F5;
  315. case XK_F6: return event | CACA_KEY_F6;
  316. case XK_F7: return event | CACA_KEY_F7;
  317. case XK_F8: return event | CACA_KEY_F8;
  318. case XK_F9: return event | CACA_KEY_F9;
  319. case XK_F10: return event | CACA_KEY_F10;
  320. case XK_F11: return event | CACA_KEY_F11;
  321. case XK_F12: return event | CACA_KEY_F12;
  322. case XK_F13: return event | CACA_KEY_F13;
  323. case XK_F14: return event | CACA_KEY_F14;
  324. case XK_F15: return event | CACA_KEY_F15;
  325. case XK_Left: return event | CACA_KEY_LEFT;
  326. case XK_Right: return event | CACA_KEY_RIGHT;
  327. case XK_Up: return event | CACA_KEY_UP;
  328. case XK_Down: return event | CACA_KEY_DOWN;
  329. default: return CACA_EVENT_NONE;
  330. }
  331. }
  332. return CACA_EVENT_NONE;
  333. }
  334. else
  335. #endif
  336. #if defined(USE_NCURSES)
  337. if(_caca_driver == CACA_DRIVER_NCURSES)
  338. {
  339. int intkey;
  340. if(_caca_resize_event)
  341. {
  342. _caca_resize_event = 0;
  343. _caca_resize = 1;
  344. return CACA_EVENT_RESIZE;
  345. }
  346. intkey = getch();
  347. if(intkey == ERR)
  348. return CACA_EVENT_NONE;
  349. if(intkey < 0x100)
  350. {
  351. return CACA_EVENT_KEY_PRESS | intkey;
  352. }
  353. if(intkey == KEY_MOUSE)
  354. {
  355. MEVENT mevent;
  356. getmouse(&mevent);
  357. switch(mevent.bstate)
  358. {
  359. case BUTTON1_PRESSED:
  360. _push_event(CACA_EVENT_MOUSE_PRESS | 1);
  361. break;
  362. case BUTTON1_RELEASED:
  363. _push_event(CACA_EVENT_MOUSE_RELEASE | 1);
  364. break;
  365. case BUTTON1_CLICKED:
  366. _push_event(CACA_EVENT_MOUSE_PRESS | 1);
  367. _push_event(CACA_EVENT_MOUSE_RELEASE | 1);
  368. break;
  369. case BUTTON1_DOUBLE_CLICKED:
  370. _push_event(CACA_EVENT_MOUSE_PRESS | 1);
  371. _push_event(CACA_EVENT_MOUSE_RELEASE | 1);
  372. _push_event(CACA_EVENT_MOUSE_PRESS | 1);
  373. _push_event(CACA_EVENT_MOUSE_RELEASE | 1);
  374. break;
  375. case BUTTON1_TRIPLE_CLICKED:
  376. _push_event(CACA_EVENT_MOUSE_PRESS | 1);
  377. _push_event(CACA_EVENT_MOUSE_RELEASE | 1);
  378. _push_event(CACA_EVENT_MOUSE_PRESS | 1);
  379. _push_event(CACA_EVENT_MOUSE_RELEASE | 1);
  380. _push_event(CACA_EVENT_MOUSE_PRESS | 1);
  381. _push_event(CACA_EVENT_MOUSE_RELEASE | 1);
  382. break;
  383. case BUTTON1_RESERVED_EVENT:
  384. break;
  385. case BUTTON2_PRESSED:
  386. _push_event(CACA_EVENT_MOUSE_PRESS | 2);
  387. break;
  388. case BUTTON2_RELEASED:
  389. _push_event(CACA_EVENT_MOUSE_RELEASE | 2);
  390. break;
  391. case BUTTON2_CLICKED:
  392. _push_event(CACA_EVENT_MOUSE_PRESS | 2);
  393. _push_event(CACA_EVENT_MOUSE_RELEASE | 2);
  394. break;
  395. case BUTTON2_DOUBLE_CLICKED:
  396. _push_event(CACA_EVENT_MOUSE_PRESS | 2);
  397. _push_event(CACA_EVENT_MOUSE_RELEASE | 2);
  398. _push_event(CACA_EVENT_MOUSE_PRESS | 2);
  399. _push_event(CACA_EVENT_MOUSE_RELEASE | 2);
  400. break;
  401. case BUTTON2_TRIPLE_CLICKED:
  402. _push_event(CACA_EVENT_MOUSE_PRESS | 2);
  403. _push_event(CACA_EVENT_MOUSE_RELEASE | 2);
  404. _push_event(CACA_EVENT_MOUSE_PRESS | 2);
  405. _push_event(CACA_EVENT_MOUSE_RELEASE | 2);
  406. _push_event(CACA_EVENT_MOUSE_PRESS | 2);
  407. _push_event(CACA_EVENT_MOUSE_RELEASE | 2);
  408. break;
  409. case BUTTON2_RESERVED_EVENT:
  410. break;
  411. case BUTTON3_PRESSED:
  412. _push_event(CACA_EVENT_MOUSE_PRESS | 3);
  413. break;
  414. case BUTTON3_RELEASED:
  415. _push_event(CACA_EVENT_MOUSE_RELEASE | 3);
  416. break;
  417. case BUTTON3_CLICKED:
  418. _push_event(CACA_EVENT_MOUSE_PRESS | 3);
  419. _push_event(CACA_EVENT_MOUSE_RELEASE | 3);
  420. break;
  421. case BUTTON3_DOUBLE_CLICKED:
  422. _push_event(CACA_EVENT_MOUSE_PRESS | 3);
  423. _push_event(CACA_EVENT_MOUSE_RELEASE | 3);
  424. _push_event(CACA_EVENT_MOUSE_PRESS | 3);
  425. _push_event(CACA_EVENT_MOUSE_RELEASE | 3);
  426. break;
  427. case BUTTON3_TRIPLE_CLICKED:
  428. _push_event(CACA_EVENT_MOUSE_PRESS | 3);
  429. _push_event(CACA_EVENT_MOUSE_RELEASE | 3);
  430. _push_event(CACA_EVENT_MOUSE_PRESS | 3);
  431. _push_event(CACA_EVENT_MOUSE_RELEASE | 3);
  432. _push_event(CACA_EVENT_MOUSE_PRESS | 3);
  433. _push_event(CACA_EVENT_MOUSE_RELEASE | 3);
  434. break;
  435. case BUTTON3_RESERVED_EVENT:
  436. break;
  437. case BUTTON4_PRESSED:
  438. _push_event(CACA_EVENT_MOUSE_PRESS | 4);
  439. break;
  440. case BUTTON4_RELEASED:
  441. _push_event(CACA_EVENT_MOUSE_RELEASE | 4);
  442. break;
  443. case BUTTON4_CLICKED:
  444. _push_event(CACA_EVENT_MOUSE_PRESS | 4);
  445. _push_event(CACA_EVENT_MOUSE_RELEASE | 4);
  446. break;
  447. case BUTTON4_DOUBLE_CLICKED:
  448. _push_event(CACA_EVENT_MOUSE_PRESS | 4);
  449. _push_event(CACA_EVENT_MOUSE_RELEASE | 4);
  450. _push_event(CACA_EVENT_MOUSE_PRESS | 4);
  451. _push_event(CACA_EVENT_MOUSE_RELEASE | 4);
  452. break;
  453. case BUTTON4_TRIPLE_CLICKED:
  454. _push_event(CACA_EVENT_MOUSE_PRESS | 4);
  455. _push_event(CACA_EVENT_MOUSE_RELEASE | 4);
  456. _push_event(CACA_EVENT_MOUSE_PRESS | 4);
  457. _push_event(CACA_EVENT_MOUSE_RELEASE | 4);
  458. _push_event(CACA_EVENT_MOUSE_PRESS | 4);
  459. _push_event(CACA_EVENT_MOUSE_RELEASE | 4);
  460. break;
  461. case BUTTON4_RESERVED_EVENT:
  462. break;
  463. default:
  464. break;
  465. }
  466. if(mouse_x == (unsigned int)mevent.x &&
  467. mouse_y == (unsigned int)mevent.y)
  468. return _pop_event();
  469. mouse_x = mevent.x;
  470. mouse_y = mevent.y;
  471. return CACA_EVENT_MOUSE_MOTION | (mouse_x << 12) | mouse_y;
  472. }
  473. event = CACA_EVENT_KEY_PRESS;
  474. switch(intkey)
  475. {
  476. case KEY_UP: return event | CACA_KEY_UP;
  477. case KEY_DOWN: return event | CACA_KEY_DOWN;
  478. case KEY_LEFT: return event | CACA_KEY_LEFT;
  479. case KEY_RIGHT: return event | CACA_KEY_RIGHT;
  480. case KEY_IC: return event | CACA_KEY_INSERT;
  481. case KEY_DC: return event | CACA_KEY_DELETE;
  482. case KEY_HOME: return event | CACA_KEY_HOME;
  483. case KEY_END: return event | CACA_KEY_END;
  484. case KEY_PPAGE: return event | CACA_KEY_PAGEUP;
  485. case KEY_NPAGE: return event | CACA_KEY_PAGEDOWN;
  486. case KEY_F(1): return event | CACA_KEY_F1;
  487. case KEY_F(2): return event | CACA_KEY_F2;
  488. case KEY_F(3): return event | CACA_KEY_F3;
  489. case KEY_F(4): return event | CACA_KEY_F4;
  490. case KEY_F(5): return event | CACA_KEY_F5;
  491. case KEY_F(6): return event | CACA_KEY_F6;
  492. case KEY_F(7): return event | CACA_KEY_F7;
  493. case KEY_F(8): return event | CACA_KEY_F8;
  494. case KEY_F(9): return event | CACA_KEY_F9;
  495. case KEY_F(10): return event | CACA_KEY_F10;
  496. case KEY_F(11): return event | CACA_KEY_F11;
  497. case KEY_F(12): return event | CACA_KEY_F12;
  498. }
  499. return CACA_EVENT_NONE;
  500. }
  501. else
  502. #endif
  503. #if defined(USE_SLANG)
  504. if(_caca_driver == CACA_DRIVER_SLANG)
  505. {
  506. int intkey;
  507. if(_caca_resize_event)
  508. {
  509. _caca_resize_event = 0;
  510. _caca_resize = 1;
  511. return CACA_EVENT_RESIZE;
  512. }
  513. if(!SLang_input_pending(0))
  514. return CACA_EVENT_NONE;
  515. /* We first use SLang_getkey() to see whether Esc was pressed
  516. * alone, then (if it wasn't) we unget the key and use SLkp_getkey()
  517. * instead, so that escape sequences are interpreted. */
  518. intkey = SLang_getkey();
  519. if(intkey != 0x1b /* Esc */ || SLang_input_pending(0))
  520. {
  521. SLang_ungetkey(intkey);
  522. intkey = SLkp_getkey();
  523. }
  524. /* If the key was ASCII, return it immediately */
  525. if(intkey < 0x100)
  526. {
  527. return CACA_EVENT_KEY_PRESS | intkey;
  528. }
  529. if(intkey == 0x3e9)
  530. {
  531. int button = (SLang_getkey() - ' ' + 1) & 0xf;
  532. unsigned int x = SLang_getkey() - '!';
  533. unsigned int y = SLang_getkey() - '!';
  534. _push_event(CACA_EVENT_MOUSE_PRESS | button);
  535. _push_event(CACA_EVENT_MOUSE_RELEASE | button);
  536. if(mouse_x == x && mouse_y == y)
  537. return _pop_event();
  538. mouse_x = x;
  539. mouse_y = y;
  540. return CACA_EVENT_MOUSE_MOTION | (mouse_x << 12) | mouse_y;
  541. }
  542. event = CACA_EVENT_KEY_PRESS;
  543. switch(intkey)
  544. {
  545. case SL_KEY_UP: return event | CACA_KEY_UP;
  546. case SL_KEY_DOWN: return event | CACA_KEY_DOWN;
  547. case SL_KEY_LEFT: return event | CACA_KEY_LEFT;
  548. case SL_KEY_RIGHT: return event | CACA_KEY_RIGHT;
  549. case SL_KEY_IC: return event | CACA_KEY_INSERT;
  550. case SL_KEY_DELETE: return event | CACA_KEY_DELETE;
  551. case SL_KEY_HOME: return event | CACA_KEY_HOME;
  552. case SL_KEY_END: return event | CACA_KEY_END;
  553. case SL_KEY_PPAGE: return event | CACA_KEY_PAGEUP;
  554. case SL_KEY_NPAGE: return event | CACA_KEY_PAGEDOWN;
  555. case SL_KEY_F(1): return event | CACA_KEY_F1;
  556. case SL_KEY_F(2): return event | CACA_KEY_F2;
  557. case SL_KEY_F(3): return event | CACA_KEY_F3;
  558. case SL_KEY_F(4): return event | CACA_KEY_F4;
  559. case SL_KEY_F(5): return event | CACA_KEY_F5;
  560. case SL_KEY_F(6): return event | CACA_KEY_F6;
  561. case SL_KEY_F(7): return event | CACA_KEY_F7;
  562. case SL_KEY_F(8): return event | CACA_KEY_F8;
  563. case SL_KEY_F(9): return event | CACA_KEY_F9;
  564. case SL_KEY_F(10): return event | CACA_KEY_F10;
  565. case SL_KEY_F(11): return event | CACA_KEY_F11;
  566. case SL_KEY_F(12): return event | CACA_KEY_F12;
  567. }
  568. return CACA_EVENT_NONE;
  569. }
  570. else
  571. #endif
  572. #if defined(USE_CONIO)
  573. if(_caca_driver == CACA_DRIVER_CONIO)
  574. {
  575. if(!_conio_kbhit())
  576. return CACA_EVENT_NONE;
  577. event = getch();
  578. _push_event(CACA_EVENT_KEY_RELEASE | event);
  579. return CACA_EVENT_KEY_PRESS | event;
  580. }
  581. else
  582. #endif
  583. #if defined(USE_WIN32)
  584. if(_caca_driver == CACA_DRIVER_WIN32)
  585. {
  586. INPUT_RECORD rec;
  587. DWORD num;
  588. for( ; ; )
  589. {
  590. GetNumberOfConsoleInputEvents(win32_hin, &num);
  591. if(num == 0)
  592. break;
  593. ReadConsoleInput(win32_hin, &rec, 1, &num);
  594. if(rec.EventType == KEY_EVENT)
  595. {
  596. if(rec.Event.KeyEvent.bKeyDown)
  597. event = CACA_EVENT_KEY_PRESS;
  598. else
  599. event = CACA_EVENT_KEY_RELEASE;
  600. if(rec.Event.KeyEvent.uChar.AsciiChar)
  601. return event | rec.Event.KeyEvent.uChar.AsciiChar;
  602. }
  603. if(rec.EventType == MOUSE_EVENT)
  604. {
  605. if(rec.Event.MouseEvent.dwEventFlags == 0)
  606. {
  607. if(rec.Event.MouseEvent.dwButtonState & 0x01)
  608. return CACA_EVENT_MOUSE_PRESS | 0x000001;
  609. if(rec.Event.MouseEvent.dwButtonState & 0x02)
  610. return CACA_EVENT_MOUSE_PRESS | 0x000002;
  611. }
  612. else if(rec.Event.MouseEvent.dwEventFlags == MOUSE_MOVED)
  613. {
  614. COORD pos = rec.Event.MouseEvent.dwMousePosition;
  615. if(mouse_x == (unsigned int)pos.X &&
  616. mouse_y == (unsigned int)pos.Y)
  617. continue;
  618. mouse_x = pos.X;
  619. mouse_y = pos.Y;
  620. return CACA_EVENT_MOUSE_MOTION | (mouse_x << 12) | mouse_y;
  621. }
  622. #if 0
  623. else if(rec.Event.MouseEvent.dwEventFlags == DOUBLE_CLICK)
  624. {
  625. cout << rec.Event.MouseEvent.dwMousePosition.X << "," <<
  626. rec.Event.MouseEvent.dwMousePosition.Y << " " << flush;
  627. }
  628. else if(rec.Event.MouseEvent.dwEventFlags == MOUSE_WHEELED)
  629. {
  630. SetConsoleCursorPosition(hOut,
  631. WheelWhere);
  632. if(rec.Event.MouseEvent.dwButtonState & 0xFF000000)
  633. cout << "Down" << flush;
  634. else
  635. cout << "Up " << flush;
  636. }
  637. #endif
  638. }
  639. /* Unknown event */
  640. return CACA_EVENT_NONE;
  641. }
  642. /* No event */
  643. return CACA_EVENT_NONE;
  644. }
  645. else
  646. #endif
  647. #if defined(USE_GL)
  648. if(_caca_driver == CACA_DRIVER_GL)
  649. {
  650. glutMainLoopEvent();
  651. if(gl_resized && !_caca_resize)
  652. {
  653. _caca_resize = 1;
  654. gl_resized = 0;
  655. return CACA_EVENT_RESIZE;
  656. }
  657. if(gl_mouse_changed)
  658. {
  659. if(gl_mouse_clicked)
  660. {
  661. event|= CACA_EVENT_MOUSE_PRESS | gl_mouse_button;
  662. gl_mouse_clicked=0;
  663. }
  664. mouse_x = gl_mouse_x;
  665. mouse_y = gl_mouse_y;
  666. event |= CACA_EVENT_MOUSE_MOTION | (mouse_x << 12) | mouse_y;
  667. gl_mouse_changed = 0;
  668. }
  669. if(gl_key != 0)
  670. {
  671. event |= CACA_EVENT_KEY_PRESS;
  672. event |= gl_key;
  673. gl_key = 0;
  674. }
  675. if(gl_special_key != 0)
  676. {
  677. event |= CACA_EVENT_KEY_PRESS;
  678. switch(gl_special_key)
  679. {
  680. case GLUT_KEY_F1 : gl_special_key = 0; return event | CACA_KEY_F1;
  681. case GLUT_KEY_F2 : gl_special_key = 0; return event | CACA_KEY_F2;
  682. case GLUT_KEY_F3 : gl_special_key = 0; return event | CACA_KEY_F3;
  683. case GLUT_KEY_F4 : gl_special_key = 0; return event | CACA_KEY_F4;
  684. case GLUT_KEY_F5 : gl_special_key = 0; return event | CACA_KEY_F5;
  685. case GLUT_KEY_F6 : gl_special_key = 0; return event | CACA_KEY_F6;
  686. case GLUT_KEY_F7 : gl_special_key = 0; return event | CACA_KEY_F7;
  687. case GLUT_KEY_F8 : gl_special_key = 0; return event | CACA_KEY_F8;
  688. case GLUT_KEY_F9 : gl_special_key = 0; return event | CACA_KEY_F9;
  689. case GLUT_KEY_F10: gl_special_key = 0; return event | CACA_KEY_F10;
  690. case GLUT_KEY_F11: gl_special_key = 0; return event | CACA_KEY_F11;
  691. case GLUT_KEY_F12: gl_special_key = 0; return event | CACA_KEY_F12;
  692. case GLUT_KEY_LEFT : gl_special_key = 0; return event | CACA_KEY_LEFT;
  693. case GLUT_KEY_RIGHT: gl_special_key = 0; return event | CACA_KEY_RIGHT;
  694. case GLUT_KEY_UP : gl_special_key = 0; return event | CACA_KEY_UP;
  695. case GLUT_KEY_DOWN : gl_special_key = 0; return event | CACA_KEY_DOWN;
  696. default: return CACA_EVENT_NONE;
  697. }
  698. }
  699. return event;
  700. }
  701. else
  702. #endif
  703. {
  704. /* Dummy */
  705. }
  706. return CACA_EVENT_NONE;
  707. }
  708. #if defined(USE_SLANG) || defined(USE_NCURSES) || defined(USE_CONIO)
  709. static void _push_event(unsigned int event)
  710. {
  711. if(!event || events == EVENTBUF_LEN)
  712. return;
  713. eventbuf[events] = event;
  714. events++;
  715. }
  716. static unsigned int _pop_event(void)
  717. {
  718. int i;
  719. unsigned int event;
  720. if(events == 0)
  721. return CACA_EVENT_NONE;
  722. event = eventbuf[0];
  723. for(i = 1; i < events; i++)
  724. eventbuf[i - 1] = eventbuf[i];
  725. events--;
  726. return event;
  727. }
  728. #endif