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

Last change on this file since 483 was 483, checked in by Jean-Yves Lamoureux, 17 years ago

OpenGL support.

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