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

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