No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 
 
 
 

806 líneas
27 KiB

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