source: libcaca/trunk/src/event.c @ 349

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