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

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