您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 
 

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