source: libcaca/branches/0.9/src/event.c @ 3583

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