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

Last change on this file since 524 was 524, checked in by Sam Hocevar, 15 years ago

A new low-level text management library (canvas for ultrafast compositing

of unicode letters) is now separated from the higher level rendering and I/O
(that is, libcaca). This commit totally breaks the API, but once everything
is polished I will think about source-level backward compatibility. Most
drivers are broken, but X11 still sorta works.

The new design is much more object-oriented and allows having several

active renderers at the same time, changing renderers on the fly, and more
important, having no renderer at all (useful for converters, or when you
want to do your own renderer).

And in case you are still wondering, the libcucul acronym has "Unicode"

because I want to support at least a subset of Unicode. There are awesome
glyphs in it, including the ones inherited from Codepage 437 such as
"gray 25%" that are used in DOS and Win32 ANSI art.

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