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

Last change on this file since 487 was 487, checked in by Jean-Yves Lamoureux, 17 years ago
  • Added Null driver and html3 exporter.
  • Property svn:keywords set to Id
File size: 26.3 KB
Line 
1/*
2 *  libcaca       ASCII-Art library
3 *  Copyright (c) 2002, 2003 Sam Hocevar <sam@zoy.org>
4 *                All Rights Reserved
5 *
6 *  This library is free software; you can redistribute it and/or
7 *  modify it under the terms of the GNU Lesser General Public
8 *  License as published by the Free Software Foundation; either
9 *  version 2 of the License, or (at your option) any later version.
10 *
11 *  This library is distributed in the hope that it will be useful,
12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 *  Lesser General Public License for more details.
15 *
16 *  You should have received a copy of the GNU Lesser General Public
17 *  License along with this library; if not, write to the Free Software
18 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 *  02111-1307  USA
20 */
21
22/** \file event.c
23 *  \version \$Id: event.c 487 2005-06-22 22:06:42Z 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#if defined(USE_NULL)
198    {
199      if(_caca_driver == CACA_DRIVER_NULL)
200        return CACA_EVENT_NONE;
201    }
202#endif
203
204    unsigned int event = _lowlevel_event();
205
206#if defined(USE_SLANG)
207    if(_caca_driver != CACA_DRIVER_SLANG)
208#endif
209#if defined(USE_NCURSES)
210    if(_caca_driver != CACA_DRIVER_NCURSES)
211#endif
212    return event;
213
214#if defined(USE_SLANG) || defined(USE_NCURSES)
215    /* Simulate long keypresses using autorepeat features */
216    ticks = _caca_getticks(&key_timer);
217    last_key_ticks += ticks;
218    autorepeat_ticks += ticks;
219
220    /* Handle autorepeat */
221    if(last_key && autorepeat_ticks > AUTOREPEAT_TRIGGER
222                && autorepeat_ticks > AUTOREPEAT_THRESHOLD
223                && autorepeat_ticks > AUTOREPEAT_RATE)
224    {
225        _push_event(event);
226        autorepeat_ticks -= AUTOREPEAT_RATE;
227        return CACA_EVENT_KEY_PRESS | last_key;
228    }
229
230    /* We are in autorepeat mode and the same key was just pressed, ignore
231     * this event and return the next one by calling ourselves. */
232    if(event == (CACA_EVENT_KEY_PRESS | last_key))
233    {
234        last_key_ticks = 0;
235        return _get_next_event();
236    }
237
238    /* We are in autorepeat mode, but key has expired or a new key was
239     * pressed - store our event and return a key release event first */
240    if(last_key && (last_key_ticks > AUTOREPEAT_THRESHOLD
241                     || (event & CACA_EVENT_KEY_PRESS)))
242    {
243        _push_event(event);
244        event = CACA_EVENT_KEY_RELEASE | last_key;
245        last_key = 0;
246        return event;
247    }
248
249    /* A new key was pressed, enter autorepeat mode */
250    if(event & CACA_EVENT_KEY_PRESS)
251    {
252        last_key_ticks = 0;
253        autorepeat_ticks = 0;
254        last_key = event & 0x00ffffff;
255    }
256
257    return event;
258#endif
259}
260
261static unsigned int _lowlevel_event(void)
262{
263    unsigned int event;
264
265#if defined(USE_SLANG) || defined(USE_NCURSES) || defined(USE_CONIO)
266    event = _pop_event();
267
268    if(event)
269        return event;
270#endif
271
272#if defined(USE_X11)
273    /* The X11 event check routine */
274    if(_caca_driver == CACA_DRIVER_X11)
275    {
276        XEvent xevent;
277        char key;
278
279        while(XCheckWindowEvent(x11_dpy, x11_window, x11_event_mask, &xevent)
280               == True)
281        {
282            KeySym keysym;
283
284            /* Expose event */
285            if(xevent.type == Expose)
286            {
287                XCopyArea(x11_dpy, x11_pixmap, x11_window, x11_gc, 0, 0,
288                          _caca_width * x11_font_width,
289                          _caca_height * x11_font_height, 0, 0);
290                continue;
291            }
292
293            /* Resize event */
294            if(xevent.type == ConfigureNotify)
295            {
296                unsigned int w, h;
297
298                w = (xevent.xconfigure.width + x11_font_width / 3)
299                      / x11_font_width;
300                h = (xevent.xconfigure.height + x11_font_height / 3)
301                      / x11_font_height;
302
303                if(!w || !h || (w == _caca_width && h == _caca_height))
304                    continue;
305
306                x11_new_width = w;
307                x11_new_height = h;
308
309                if(_caca_resize)
310                    continue;
311
312                _caca_resize = 1;
313
314                return CACA_EVENT_RESIZE;
315            }
316
317            /* Check for mouse motion events */
318            if(xevent.type == MotionNotify)
319            {
320                unsigned int newx = xevent.xmotion.x / x11_font_width;
321                unsigned int newy = xevent.xmotion.y / x11_font_height;
322
323                if(newx >= _caca_width)
324                    newx = _caca_width - 1;
325                if(newy >= _caca_height)
326                    newy = _caca_height - 1;
327
328                if(mouse_x == newx && mouse_y == newy)
329                    continue;
330
331                mouse_x = newx;
332                mouse_y = newy;
333
334                return CACA_EVENT_MOUSE_MOTION | (mouse_x << 12) | mouse_y;
335            }
336
337            /* Check for mouse press and release events */
338            if(xevent.type == ButtonPress)
339                return CACA_EVENT_MOUSE_PRESS
340                        | ((XButtonEvent *)&xevent)->button;
341
342            if(xevent.type == ButtonRelease)
343                return CACA_EVENT_MOUSE_RELEASE
344                        | ((XButtonEvent *)&xevent)->button;
345
346            /* Check for key press and release events */
347            if(xevent.type == KeyPress)
348                event |= CACA_EVENT_KEY_PRESS;
349            else if(xevent.type == KeyRelease)
350                event |= CACA_EVENT_KEY_RELEASE;
351            else
352                continue;
353
354            if(XLookupString(&xevent.xkey, &key, 1, NULL, NULL))
355                return event | key;
356
357            keysym = XKeycodeToKeysym(x11_dpy, xevent.xkey.keycode, 0);
358            switch(keysym)
359            {
360            case XK_F1:    return event | CACA_KEY_F1;
361            case XK_F2:    return event | CACA_KEY_F2;
362            case XK_F3:    return event | CACA_KEY_F3;
363            case XK_F4:    return event | CACA_KEY_F4;
364            case XK_F5:    return event | CACA_KEY_F5;
365            case XK_F6:    return event | CACA_KEY_F6;
366            case XK_F7:    return event | CACA_KEY_F7;
367            case XK_F8:    return event | CACA_KEY_F8;
368            case XK_F9:    return event | CACA_KEY_F9;
369            case XK_F10:   return event | CACA_KEY_F10;
370            case XK_F11:   return event | CACA_KEY_F11;
371            case XK_F12:   return event | CACA_KEY_F12;
372            case XK_F13:   return event | CACA_KEY_F13;
373            case XK_F14:   return event | CACA_KEY_F14;
374            case XK_F15:   return event | CACA_KEY_F15;
375            case XK_Left:  return event | CACA_KEY_LEFT;
376            case XK_Right: return event | CACA_KEY_RIGHT;
377            case XK_Up:    return event | CACA_KEY_UP;
378            case XK_Down:  return event | CACA_KEY_DOWN;
379            default:       return CACA_EVENT_NONE;
380            }
381        }
382
383        return CACA_EVENT_NONE;
384    }
385    else
386#endif
387#if defined(USE_NCURSES)
388    if(_caca_driver == CACA_DRIVER_NCURSES)
389    {
390        int intkey;
391
392        if(_caca_resize_event)
393        {
394            _caca_resize_event = 0;
395            _caca_resize = 1;
396            return CACA_EVENT_RESIZE;
397        }
398
399        intkey = getch();
400        if(intkey == ERR)
401            return CACA_EVENT_NONE;
402
403        if(intkey < 0x100)
404        {
405            return CACA_EVENT_KEY_PRESS | intkey;
406        }
407
408        if(intkey == KEY_MOUSE)
409        {
410            MEVENT mevent;
411            getmouse(&mevent);
412
413            switch(mevent.bstate)
414            {
415                case BUTTON1_PRESSED:
416                    _push_event(CACA_EVENT_MOUSE_PRESS | 1);
417                    break;
418                case BUTTON1_RELEASED:
419                    _push_event(CACA_EVENT_MOUSE_RELEASE | 1);
420                    break;
421                case BUTTON1_CLICKED:
422                    _push_event(CACA_EVENT_MOUSE_PRESS | 1);
423                    _push_event(CACA_EVENT_MOUSE_RELEASE | 1);
424                    break;
425                case BUTTON1_DOUBLE_CLICKED:
426                    _push_event(CACA_EVENT_MOUSE_PRESS | 1);
427                    _push_event(CACA_EVENT_MOUSE_RELEASE | 1);
428                    _push_event(CACA_EVENT_MOUSE_PRESS | 1);
429                    _push_event(CACA_EVENT_MOUSE_RELEASE | 1);
430                    break;
431                case BUTTON1_TRIPLE_CLICKED:
432                    _push_event(CACA_EVENT_MOUSE_PRESS | 1);
433                    _push_event(CACA_EVENT_MOUSE_RELEASE | 1);
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                    break;
439                case BUTTON1_RESERVED_EVENT:
440                    break;
441
442                case BUTTON2_PRESSED:
443                    _push_event(CACA_EVENT_MOUSE_PRESS | 2);
444                    break;
445                case BUTTON2_RELEASED:
446                    _push_event(CACA_EVENT_MOUSE_RELEASE | 2);
447                    break;
448                case BUTTON2_CLICKED:
449                    _push_event(CACA_EVENT_MOUSE_PRESS | 2);
450                    _push_event(CACA_EVENT_MOUSE_RELEASE | 2);
451                    break;
452                case BUTTON2_DOUBLE_CLICKED:
453                    _push_event(CACA_EVENT_MOUSE_PRESS | 2);
454                    _push_event(CACA_EVENT_MOUSE_RELEASE | 2);
455                    _push_event(CACA_EVENT_MOUSE_PRESS | 2);
456                    _push_event(CACA_EVENT_MOUSE_RELEASE | 2);
457                    break;
458                case BUTTON2_TRIPLE_CLICKED:
459                    _push_event(CACA_EVENT_MOUSE_PRESS | 2);
460                    _push_event(CACA_EVENT_MOUSE_RELEASE | 2);
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                    break;
466                case BUTTON2_RESERVED_EVENT:
467                    break;
468
469                case BUTTON3_PRESSED:
470                    _push_event(CACA_EVENT_MOUSE_PRESS | 3);
471                    break;
472                case BUTTON3_RELEASED:
473                    _push_event(CACA_EVENT_MOUSE_RELEASE | 3);
474                    break;
475                case BUTTON3_CLICKED:
476                    _push_event(CACA_EVENT_MOUSE_PRESS | 3);
477                    _push_event(CACA_EVENT_MOUSE_RELEASE | 3);
478                    break;
479                case BUTTON3_DOUBLE_CLICKED:
480                    _push_event(CACA_EVENT_MOUSE_PRESS | 3);
481                    _push_event(CACA_EVENT_MOUSE_RELEASE | 3);
482                    _push_event(CACA_EVENT_MOUSE_PRESS | 3);
483                    _push_event(CACA_EVENT_MOUSE_RELEASE | 3);
484                    break;
485                case BUTTON3_TRIPLE_CLICKED:
486                    _push_event(CACA_EVENT_MOUSE_PRESS | 3);
487                    _push_event(CACA_EVENT_MOUSE_RELEASE | 3);
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                    break;
493                case BUTTON3_RESERVED_EVENT:
494                    break;
495
496                case BUTTON4_PRESSED:
497                    _push_event(CACA_EVENT_MOUSE_PRESS | 4);
498                    break;
499                case BUTTON4_RELEASED:
500                    _push_event(CACA_EVENT_MOUSE_RELEASE | 4);
501                    break;
502                case BUTTON4_CLICKED:
503                    _push_event(CACA_EVENT_MOUSE_PRESS | 4);
504                    _push_event(CACA_EVENT_MOUSE_RELEASE | 4);
505                    break;
506                case BUTTON4_DOUBLE_CLICKED:
507                    _push_event(CACA_EVENT_MOUSE_PRESS | 4);
508                    _push_event(CACA_EVENT_MOUSE_RELEASE | 4);
509                    _push_event(CACA_EVENT_MOUSE_PRESS | 4);
510                    _push_event(CACA_EVENT_MOUSE_RELEASE | 4);
511                    break;
512                case BUTTON4_TRIPLE_CLICKED:
513                    _push_event(CACA_EVENT_MOUSE_PRESS | 4);
514                    _push_event(CACA_EVENT_MOUSE_RELEASE | 4);
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                    break;
520                case BUTTON4_RESERVED_EVENT:
521                    break;
522
523                default:
524                    break;
525            }
526
527            if(mouse_x == (unsigned int)mevent.x &&
528               mouse_y == (unsigned int)mevent.y)
529                return _pop_event();
530
531            mouse_x = mevent.x;
532            mouse_y = mevent.y;
533
534            return CACA_EVENT_MOUSE_MOTION | (mouse_x << 12) | mouse_y;
535        }
536
537        event = CACA_EVENT_KEY_PRESS;
538
539        switch(intkey)
540        {
541            case KEY_UP: return event | CACA_KEY_UP;
542            case KEY_DOWN: return event | CACA_KEY_DOWN;
543            case KEY_LEFT: return event | CACA_KEY_LEFT;
544            case KEY_RIGHT: return event | CACA_KEY_RIGHT;
545
546            case KEY_IC: return event | CACA_KEY_INSERT;
547            case KEY_DC: return event | CACA_KEY_DELETE;
548            case KEY_HOME: return event | CACA_KEY_HOME;
549            case KEY_END: return event | CACA_KEY_END;
550            case KEY_PPAGE: return event | CACA_KEY_PAGEUP;
551            case KEY_NPAGE: return event | CACA_KEY_PAGEDOWN;
552
553            case KEY_F(1): return event | CACA_KEY_F1;
554            case KEY_F(2): return event | CACA_KEY_F2;
555            case KEY_F(3): return event | CACA_KEY_F3;
556            case KEY_F(4): return event | CACA_KEY_F4;
557            case KEY_F(5): return event | CACA_KEY_F5;
558            case KEY_F(6): return event | CACA_KEY_F6;
559            case KEY_F(7): return event | CACA_KEY_F7;
560            case KEY_F(8): return event | CACA_KEY_F8;
561            case KEY_F(9): return event | CACA_KEY_F9;
562            case KEY_F(10): return event | CACA_KEY_F10;
563            case KEY_F(11): return event | CACA_KEY_F11;
564            case KEY_F(12): return event | CACA_KEY_F12;
565        }
566
567        return CACA_EVENT_NONE;
568    }
569    else
570#endif
571#if defined(USE_SLANG)
572    if(_caca_driver == CACA_DRIVER_SLANG)
573    {
574        int intkey;
575
576        if(_caca_resize_event)
577        {
578            _caca_resize_event = 0;
579            _caca_resize = 1;
580            return CACA_EVENT_RESIZE;
581        }
582
583        if(!SLang_input_pending(0))
584            return CACA_EVENT_NONE;
585
586        /* We first use SLang_getkey() to see whether Esc was pressed
587         * alone, then (if it wasn't) we unget the key and use SLkp_getkey()
588         * instead, so that escape sequences are interpreted. */
589        intkey = SLang_getkey();
590
591        if(intkey != 0x1b /* Esc */ || SLang_input_pending(0))
592        {
593            SLang_ungetkey(intkey);
594            intkey = SLkp_getkey();
595        }
596
597        /* If the key was ASCII, return it immediately */
598        if(intkey < 0x100)
599        {
600            return CACA_EVENT_KEY_PRESS | intkey;
601        }
602
603        if(intkey == 0x3e9)
604        {
605            int button = (SLang_getkey() - ' ' + 1) & 0xf;
606            unsigned int x = SLang_getkey() - '!';
607            unsigned int y = SLang_getkey() - '!';
608            _push_event(CACA_EVENT_MOUSE_PRESS | button);
609            _push_event(CACA_EVENT_MOUSE_RELEASE | button);
610
611            if(mouse_x == x && mouse_y == y)
612                return _pop_event();
613
614            mouse_x = x;
615            mouse_y = y;
616
617            return CACA_EVENT_MOUSE_MOTION | (mouse_x << 12) | mouse_y;
618        }
619
620        event = CACA_EVENT_KEY_PRESS;
621
622        switch(intkey)
623        {
624            case SL_KEY_UP: return event | CACA_KEY_UP;
625            case SL_KEY_DOWN: return event | CACA_KEY_DOWN;
626            case SL_KEY_LEFT: return event | CACA_KEY_LEFT;
627            case SL_KEY_RIGHT: return event | CACA_KEY_RIGHT;
628
629            case SL_KEY_IC: return event | CACA_KEY_INSERT;
630            case SL_KEY_DELETE: return event | CACA_KEY_DELETE;
631            case SL_KEY_HOME: return event | CACA_KEY_HOME;
632            case SL_KEY_END: return event | CACA_KEY_END;
633            case SL_KEY_PPAGE: return event | CACA_KEY_PAGEUP;
634            case SL_KEY_NPAGE: return event | CACA_KEY_PAGEDOWN;
635
636            case SL_KEY_F(1): return event | CACA_KEY_F1;
637            case SL_KEY_F(2): return event | CACA_KEY_F2;
638            case SL_KEY_F(3): return event | CACA_KEY_F3;
639            case SL_KEY_F(4): return event | CACA_KEY_F4;
640            case SL_KEY_F(5): return event | CACA_KEY_F5;
641            case SL_KEY_F(6): return event | CACA_KEY_F6;
642            case SL_KEY_F(7): return event | CACA_KEY_F7;
643            case SL_KEY_F(8): return event | CACA_KEY_F8;
644            case SL_KEY_F(9): return event | CACA_KEY_F9;
645            case SL_KEY_F(10): return event | CACA_KEY_F10;
646            case SL_KEY_F(11): return event | CACA_KEY_F11;
647            case SL_KEY_F(12): return event | CACA_KEY_F12;
648        }
649
650        return CACA_EVENT_NONE;
651    }
652    else
653#endif
654#if defined(USE_CONIO)
655    if(_caca_driver == CACA_DRIVER_CONIO)
656    {
657        if(!_conio_kbhit())
658            return CACA_EVENT_NONE;
659
660        event = getch();
661        _push_event(CACA_EVENT_KEY_RELEASE | event);
662        return CACA_EVENT_KEY_PRESS | event;
663    }
664    else
665#endif
666#if defined(USE_WIN32)
667    if(_caca_driver == CACA_DRIVER_WIN32)
668    {
669        INPUT_RECORD rec;
670        DWORD num;
671
672        for( ; ; )
673        {
674            GetNumberOfConsoleInputEvents(win32_hin, &num);
675            if(num == 0)
676                break;
677
678            ReadConsoleInput(win32_hin, &rec, 1, &num);
679            if(rec.EventType == KEY_EVENT)
680            {
681                if(rec.Event.KeyEvent.bKeyDown)
682                    event = CACA_EVENT_KEY_PRESS;
683                else
684                    event = CACA_EVENT_KEY_RELEASE;
685
686                if(rec.Event.KeyEvent.uChar.AsciiChar)
687                    return event | rec.Event.KeyEvent.uChar.AsciiChar;
688            }
689
690            if(rec.EventType == MOUSE_EVENT)
691            {
692                if(rec.Event.MouseEvent.dwEventFlags == 0)
693                {
694                    if(rec.Event.MouseEvent.dwButtonState & 0x01)
695                        return CACA_EVENT_MOUSE_PRESS | 0x000001;
696
697                    if(rec.Event.MouseEvent.dwButtonState & 0x02)
698                        return CACA_EVENT_MOUSE_PRESS | 0x000002;
699                }
700                else if(rec.Event.MouseEvent.dwEventFlags == MOUSE_MOVED)
701                {
702                    COORD pos = rec.Event.MouseEvent.dwMousePosition;
703
704                    if(mouse_x == (unsigned int)pos.X &&
705                       mouse_y == (unsigned int)pos.Y)
706                        continue;
707
708                    mouse_x = pos.X;
709                    mouse_y = pos.Y;
710
711                    return CACA_EVENT_MOUSE_MOTION | (mouse_x << 12) | mouse_y;
712                }
713#if 0
714                else if(rec.Event.MouseEvent.dwEventFlags == DOUBLE_CLICK)
715                {
716                    cout << rec.Event.MouseEvent.dwMousePosition.X << "," <<
717                            rec.Event.MouseEvent.dwMousePosition.Y << "  " << flush;
718                }
719                else if(rec.Event.MouseEvent.dwEventFlags == MOUSE_WHEELED)
720                {
721                    SetConsoleCursorPosition(hOut,
722                                             WheelWhere);
723                    if(rec.Event.MouseEvent.dwButtonState & 0xFF000000)
724                        cout << "Down" << flush;
725                    else
726                        cout << "Up  " << flush;
727                }
728#endif
729            }
730
731            /* Unknown event */
732            return CACA_EVENT_NONE;
733        }
734
735        /* No event */
736        return CACA_EVENT_NONE;
737    }
738    else
739#endif
740#if defined(USE_GL)
741      if(_caca_driver == CACA_DRIVER_GL)
742        {
743          glutMainLoopEvent();
744
745          if(gl_resized)
746            {
747              if(!_caca_resize)
748                {
749
750
751                  _caca_resize = 1;
752                  gl_resized=0;
753                  return CACA_EVENT_RESIZE;
754                }
755            }
756
757          if(gl_key!=0)
758            {
759              event |= CACA_EVENT_KEY_PRESS;
760              event |= gl_key;
761              gl_key = 0;
762            }
763
764          if(gl_special_key != 0)
765            {
766              event |= CACA_EVENT_KEY_PRESS;
767     
768              switch(gl_special_key)
769                {
770                case GLUT_KEY_F1 : gl_special_key = 0; return event | CACA_KEY_F1;
771                case GLUT_KEY_F2 : gl_special_key = 0; return event | CACA_KEY_F2;
772                case GLUT_KEY_F3 : gl_special_key = 0; return event | CACA_KEY_F3;
773                case GLUT_KEY_F4 : gl_special_key = 0; return event | CACA_KEY_F4;
774                case GLUT_KEY_F5 : gl_special_key = 0; return event | CACA_KEY_F5;
775                case GLUT_KEY_F6 : gl_special_key = 0; return event | CACA_KEY_F6;
776                case GLUT_KEY_F7 : gl_special_key = 0; return event | CACA_KEY_F7;
777                case GLUT_KEY_F8 : gl_special_key = 0; return event | CACA_KEY_F8;
778                case GLUT_KEY_F9 : gl_special_key = 0; return event | CACA_KEY_F9;
779                case GLUT_KEY_F10  : gl_special_key = 0; return event | CACA_KEY_F10;
780                case GLUT_KEY_F11  : gl_special_key = 0; return event | CACA_KEY_F11;
781                case GLUT_KEY_F12  : gl_special_key = 0; return event | CACA_KEY_F12;
782                case GLUT_KEY_LEFT : gl_special_key = 0; return event | CACA_KEY_LEFT;
783                case GLUT_KEY_RIGHT: gl_special_key = 0; return event | CACA_KEY_RIGHT;
784                case GLUT_KEY_UP   : gl_special_key = 0; return event | CACA_KEY_UP;
785                case GLUT_KEY_DOWN : gl_special_key = 0; return event | CACA_KEY_DOWN;
786                default:       return CACA_EVENT_NONE;
787                }
788            }
789          return event;
790        }
791      else
792#endif
793    {
794        /* Dummy */
795    }
796
797    return CACA_EVENT_NONE;
798}
799
800#if defined(USE_SLANG) || defined(USE_NCURSES) || defined(USE_CONIO)
801static void _push_event(unsigned int event)
802{
803    if(!event || events == EVENTBUF_LEN)
804        return;
805    eventbuf[events] = event;
806    events++;
807}
808
809static unsigned int _pop_event(void)
810{
811    int i;
812    unsigned int event;
813
814    if(events == 0)
815        return CACA_EVENT_NONE;
816
817    event = eventbuf[0];
818    for(i = 1; i < events; i++)
819        eventbuf[i - 1] = eventbuf[i];
820    events--;
821
822    return event;
823}
824#endif
825
Note: See TracBrowser for help on using the repository browser.