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.
 
 
 
 
 
 

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