25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.
 
 
 
 
 
 

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