source: libcaca/trunk/caca/event.c @ 536

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