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

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