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

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