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.
 
 
 
 
 
 

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