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

Last change on this file since 536 was 536, checked in by Sam Hocevar, 15 years ago
  • Moved stuff around to differenciate between libcucul and libcaca.
  • Property svn:keywords set to Id
File size: 26.8 KB
RevLine 
[35]1/*
[268]2 *  libcaca       ASCII-Art library
[527]3 *  Copyright (c) 2002-2006 Sam Hocevar <sam@zoy.org>
[268]4 *                All Rights Reserved
[35]5 *
[268]6 *  This library is free software; you can redistribute it and/or
[522]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.
[35]10 */
[17]11
[345]12/** \file event.c
[268]13 *  \version \$Id: event.c 536 2006-03-06 20:57:14Z sam $
14 *  \author Sam Hocevar <sam@zoy.org>
[298]15 *  \brief Event handling
[205]16 *
[268]17 *  This file contains event handling functions for keyboard and mouse input.
[205]18 */
19
[63]20#include "config.h"
21
[524]22#if defined(HAVE_INTTYPES_H) || defined(_DOXYGEN_SKIP_ME)
23#   include <inttypes.h>
24#else
25typedef unsigned char uint8_t;
26#endif
27
[159]28#if defined(USE_SLANG)
[309]29#   if defined(HAVE_SLANG_SLANG_H)
30#       include <slang/slang.h>
31#   else
32#       include <slang.h>
33#   endif
[265]34#endif
35#if defined(USE_NCURSES)
[361]36#   if defined(HAVE_NCURSES_H)
37#       include <ncurses.h>
38#   else
39#       include <curses.h>
40#   endif
[265]41#endif
42#if defined(USE_CONIO)
[155]43#   include <conio.h>
[265]44#endif
45#if defined(USE_X11)
[251]46#   include <X11/Xlib.h>
47#   include <X11/Xutil.h>
[269]48#   include <X11/keysym.h>
[147]49#endif
[335]50#if defined(USE_WIN32)
51#   include <windows.h>
52#endif
[483]53#if defined(USE_GL)
54#include <GL/gl.h>
55#include <GL/glut.h>
[512]56#include <GL/freeglut_ext.h>
[483]57#endif
[527]58
[524]59#include "cucul.h"
60#include "cucul_internals.h"
[185]61#include "caca.h"
62#include "caca_internals.h"
[17]63
[524]64static unsigned int _get_next_event(caca_t *kk);
65static unsigned int _lowlevel_event(caca_t *kk);
[336]66#if defined(USE_SLANG) || defined(USE_NCURSES) || defined(USE_CONIO)
[329]67static void _push_event(unsigned int);
68static unsigned int _pop_event(void);
[336]69#endif
[199]70
[322]71#if !defined(_DOXYGEN_SKIP_ME)
[329]72#define EVENTBUF_LEN 10
[322]73#endif
[336]74#if defined(USE_SLANG) || defined(USE_NCURSES) || defined(USE_CONIO)
[329]75static unsigned int eventbuf[EVENTBUF_LEN];
76static int events = 0;
[336]77#endif
[198]78
[347]79static unsigned int mouse_x = 0, mouse_y = 0;
80
[331]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
[268]91/** \brief Get the next mouse or keyboard input event.
[257]92 *
[316]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
[332]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.
[268]98 *
[316]99 * \param event_mask Bitmask of requested events.
100 * \return The next matching event in the queue, or 0 if no event is pending.
[257]101 */
[524]102unsigned int caca_get_event(caca_t *kk, unsigned int event_mask)
[79]103{
[332]104    if(!event_mask)
105        return CACA_EVENT_NONE;
106
[316]107    for( ; ; )
108    {
[524]109        unsigned int event = _get_next_event(kk);
[316]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
[332]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.
[316]122 *
123 *  \param event_mask Bitmask of requested events.
124 *  \return The next event in the queue.
125 */
[524]126unsigned int caca_wait_event(caca_t *kk, unsigned int event_mask)
[316]127{
[332]128    if(!event_mask)
129        return CACA_EVENT_NONE;
130
[316]131    for( ; ; )
132    {
[524]133        unsigned int event = _get_next_event(kk);
[316]134
135        if(event & event_mask)
136            return event;
137
[335]138        _caca_sleep(10000);
[316]139    }
140}
141
[347]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 */
[524]151unsigned int caca_get_mouse_x(caca_t *kk)
[347]152{
[524]153    if(mouse_x >= kk->qq->width)
154        mouse_x = kk->qq->width - 1;
[351]155
[347]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 */
[524]168unsigned int caca_get_mouse_y(caca_t *kk)
[347]169{
[524]170    if(mouse_y >= kk->qq->height)
171        mouse_y = kk->qq->height - 1;
[351]172
[347]173    return mouse_y;
174}
175
[316]176/*
177 * XXX: The following functions are local.
178 */
179
[524]180static unsigned int _get_next_event(caca_t *kk)
[316]181{
[331]182#if defined(USE_SLANG) || defined(USE_NCURSES)
183    unsigned int ticks;
[498]184#endif
[494]185    unsigned int event;
[487]186
[524]187    event = _lowlevel_event(kk);
[331]188
189#if defined(USE_SLANG)
[524]190    if(kk->driver != CACA_DRIVER_SLANG)
[331]191#endif
192#if defined(USE_NCURSES)
[524]193    if(kk->driver != CACA_DRIVER_NCURSES)
[331]194#endif
195    return event;
196
197#if defined(USE_SLANG) || defined(USE_NCURSES)
198    /* Simulate long keypresses using autorepeat features */
[527]199    ticks = _caca_getticks(&kk->events.key_timer);
200    kk->events.last_key_ticks += ticks;
201    kk->events.autorepeat_ticks += ticks;
[331]202
203    /* Handle autorepeat */
[527]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)
[331]208    {
209        _push_event(event);
[527]210        kk->events.autorepeat_ticks -= AUTOREPEAT_RATE;
211        return CACA_EVENT_KEY_PRESS | kk->events.last_key;
[331]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. */
[527]216    if(event == (CACA_EVENT_KEY_PRESS | kk->events.last_key))
[331]217    {
[527]218        kk->events.last_key_ticks = 0;
[524]219        return _get_next_event(kk);
[331]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 */
[527]224    if(kk->events.last_key
225          && (kk->events.last_key_ticks > AUTOREPEAT_THRESHOLD
226               || (event & CACA_EVENT_KEY_PRESS)))
[331]227    {
228        _push_event(event);
[527]229        event = CACA_EVENT_KEY_RELEASE | kk->events.last_key;
230        kk->events.last_key = 0;
[331]231        return event;
232    }
233
234    /* A new key was pressed, enter autorepeat mode */
235    if(event & CACA_EVENT_KEY_PRESS)
236    {
[527]237        kk->events.last_key_ticks = 0;
238        kk->events.autorepeat_ticks = 0;
239        kk->events.last_key = event & 0x00ffffff;
[331]240    }
241
242    return event;
243#endif
244}
245
[524]246static unsigned int _lowlevel_event(caca_t *kk)
[331]247{
[336]248    unsigned int event;
[198]249
[336]250#if defined(USE_SLANG) || defined(USE_NCURSES) || defined(USE_CONIO)
251    event = _pop_event();
252
[329]253    if(event)
254        return event;
[336]255#endif
[329]256
[287]257#if defined(USE_X11)
[316]258    /* The X11 event check routine */
[524]259    if(kk->driver == CACA_DRIVER_X11)
[287]260    {
261        XEvent xevent;
262        char key;
263
[524]264        while(XCheckWindowEvent(kk->x11.dpy, kk->x11.window, kk->x11.event_mask, &xevent)
[287]265               == True)
266        {
267            KeySym keysym;
268
[353]269            /* Expose event */
270            if(xevent.type == Expose)
271            {
[527]272                XCopyArea(kk->x11.dpy, kk->x11.pixmap,
273                          kk->x11.window, kk->x11.gc, 0, 0,
[524]274                          kk->qq->width * kk->x11.font_width,
275                          kk->qq->height * kk->x11.font_height, 0, 0);
[353]276                continue;
277            }
278
[347]279            /* Resize event */
280            if(xevent.type == ConfigureNotify)
281            {
[353]282                unsigned int w, h;
[347]283
[524]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;
[353]288
[524]289                if(!w || !h || (w == kk->qq->width && h == kk->qq->height))
[347]290                    continue;
291
[524]292                kk->x11.new_width = w;
293                kk->x11.new_height = h;
[347]294
[527]295                /* If we are already resizing, ignore the new signal */
[524]296                if(kk->resize)
[349]297                    continue;
298
[524]299                kk->resize = 1;
[349]300
[347]301                return CACA_EVENT_RESIZE;
302            }
303
[316]304            /* Check for mouse motion events */
[287]305            if(xevent.type == MotionNotify)
306            {
[524]307                unsigned int newx = xevent.xmotion.x / kk->x11.font_width;
308                unsigned int newy = xevent.xmotion.y / kk->x11.font_height;
[287]309
[524]310                if(newx >= kk->qq->width)
311                    newx = kk->qq->width - 1;
312                if(newy >= kk->qq->height)
313                    newy = kk->qq->height - 1;
[287]314
[347]315                if(mouse_x == newx && mouse_y == newy)
[325]316                    continue;
317
[347]318                mouse_x = newx;
319                mouse_y = newy;
[287]320
[347]321                return CACA_EVENT_MOUSE_MOTION | (mouse_x << 12) | mouse_y;
[287]322            }
323
[316]324            /* Check for mouse press and release events */
[287]325            if(xevent.type == ButtonPress)
[324]326                return CACA_EVENT_MOUSE_PRESS
327                        | ((XButtonEvent *)&xevent)->button;
[287]328
[314]329            if(xevent.type == ButtonRelease)
[324]330                return CACA_EVENT_MOUSE_RELEASE
331                        | ((XButtonEvent *)&xevent)->button;
[287]332
[316]333            /* Check for key press and release events */
[287]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
[316]339                continue;
[287]340
341            if(XLookupString(&xevent.xkey, &key, 1, NULL, NULL))
342                return event | key;
343
[524]344            keysym = XKeycodeToKeysym(kk->x11.dpy, xevent.xkey.keycode, 0);
[287]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;
[332]366            default:       return CACA_EVENT_NONE;
[287]367            }
368        }
369
[332]370        return CACA_EVENT_NONE;
[287]371    }
[329]372    else
[287]373#endif
[213]374#if defined(USE_NCURSES)
[524]375    if(kk->driver == CACA_DRIVER_NCURSES)
[213]376    {
[349]377        int intkey;
378
[524]379        if(kk->resize_event)
[349]380        {
[524]381            kk->resize_event = 0;
382            kk->resize = 1;
[349]383            return CACA_EVENT_RESIZE;
384        }
385
386        intkey = getch();
[329]387        if(intkey == ERR)
[332]388            return CACA_EVENT_NONE;
[329]389
390        if(intkey < 0x100)
[265]391        {
[329]392            return CACA_EVENT_KEY_PRESS | intkey;
393        }
394
395        if(intkey == KEY_MOUSE)
396        {
[265]397            MEVENT mevent;
398            getmouse(&mevent);
[324]399
400            switch(mevent.bstate)
401            {
402                case BUTTON1_PRESSED:
[329]403                    _push_event(CACA_EVENT_MOUSE_PRESS | 1);
[324]404                    break;
405                case BUTTON1_RELEASED:
[329]406                    _push_event(CACA_EVENT_MOUSE_RELEASE | 1);
[324]407                    break;
408                case BUTTON1_CLICKED:
[329]409                    _push_event(CACA_EVENT_MOUSE_PRESS | 1);
410                    _push_event(CACA_EVENT_MOUSE_RELEASE | 1);
[324]411                    break;
412                case BUTTON1_DOUBLE_CLICKED:
[329]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);
[324]417                    break;
418                case BUTTON1_TRIPLE_CLICKED:
[329]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);
[324]425                    break;
426                case BUTTON1_RESERVED_EVENT:
427                    break;
428
429                case BUTTON2_PRESSED:
[329]430                    _push_event(CACA_EVENT_MOUSE_PRESS | 2);
[324]431                    break;
432                case BUTTON2_RELEASED:
[329]433                    _push_event(CACA_EVENT_MOUSE_RELEASE | 2);
[324]434                    break;
435                case BUTTON2_CLICKED:
[329]436                    _push_event(CACA_EVENT_MOUSE_PRESS | 2);
437                    _push_event(CACA_EVENT_MOUSE_RELEASE | 2);
[324]438                    break;
439                case BUTTON2_DOUBLE_CLICKED:
[329]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);
[324]444                    break;
445                case BUTTON2_TRIPLE_CLICKED:
[329]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);
[324]452                    break;
453                case BUTTON2_RESERVED_EVENT:
454                    break;
455
456                case BUTTON3_PRESSED:
[329]457                    _push_event(CACA_EVENT_MOUSE_PRESS | 3);
[324]458                    break;
459                case BUTTON3_RELEASED:
[329]460                    _push_event(CACA_EVENT_MOUSE_RELEASE | 3);
[324]461                    break;
462                case BUTTON3_CLICKED:
[329]463                    _push_event(CACA_EVENT_MOUSE_PRESS | 3);
464                    _push_event(CACA_EVENT_MOUSE_RELEASE | 3);
[324]465                    break;
466                case BUTTON3_DOUBLE_CLICKED:
[329]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);
[324]471                    break;
472                case BUTTON3_TRIPLE_CLICKED:
[329]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);
[324]479                    break;
480                case BUTTON3_RESERVED_EVENT:
481                    break;
482
483                case BUTTON4_PRESSED:
[329]484                    _push_event(CACA_EVENT_MOUSE_PRESS | 4);
[324]485                    break;
486                case BUTTON4_RELEASED:
[329]487                    _push_event(CACA_EVENT_MOUSE_RELEASE | 4);
[324]488                    break;
489                case BUTTON4_CLICKED:
[329]490                    _push_event(CACA_EVENT_MOUSE_PRESS | 4);
491                    _push_event(CACA_EVENT_MOUSE_RELEASE | 4);
[324]492                    break;
493                case BUTTON4_DOUBLE_CLICKED:
[329]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);
[324]498                    break;
499                case BUTTON4_TRIPLE_CLICKED:
[329]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);
[324]506                    break;
507                case BUTTON4_RESERVED_EVENT:
508                    break;
509
510                default:
511                    break;
512            }
513
[347]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;
[265]522        }
[198]523
[332]524        event = CACA_EVENT_KEY_PRESS;
525
[329]526        switch(intkey)
[265]527        {
[332]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;
[213]532
[332]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;
[265]552        }
[198]553
[332]554        return CACA_EVENT_NONE;
[213]555    }
[329]556    else
[213]557#endif
[329]558#if defined(USE_SLANG)
[524]559    if(kk->driver == CACA_DRIVER_SLANG)
[329]560    {
561        int intkey;
[213]562
[524]563        if(kk->resize_event)
[349]564        {
[524]565            kk->resize_event = 0;
566            kk->resize = 1;
[349]567            return CACA_EVENT_RESIZE;
568        }
569
[329]570        if(!SLang_input_pending(0))
[332]571            return CACA_EVENT_NONE;
[273]572
[332]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();
[213]577
[332]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 */
[329]585        if(intkey < 0x100)
586        {
587            return CACA_EVENT_KEY_PRESS | intkey;
588        }
[213]589
[329]590        if(intkey == 0x3e9)
591        {
592            int button = (SLang_getkey() - ' ' + 1) & 0xf;
[347]593            unsigned int x = SLang_getkey() - '!';
594            unsigned int y = SLang_getkey() - '!';
[329]595            _push_event(CACA_EVENT_MOUSE_PRESS | button);
596            _push_event(CACA_EVENT_MOUSE_RELEASE | button);
[347]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;
[329]605        }
[213]606
[332]607        event = CACA_EVENT_KEY_PRESS;
608
[329]609        switch(intkey)
610        {
[332]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;
[329]615
[332]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;
[329]635        }
636
[332]637        return CACA_EVENT_NONE;
[198]638    }
[329]639    else
640#endif
641#if defined(USE_CONIO)
[524]642    if(kk->driver == CACA_DRIVER_CONIO)
[198]643    {
[329]644        if(!_conio_kbhit())
[332]645            return CACA_EVENT_NONE;
[324]646
[329]647        event = getch();
648        _push_event(CACA_EVENT_KEY_RELEASE | event);
[324]649        return CACA_EVENT_KEY_PRESS | event;
[213]650    }
[329]651    else
652#endif
[335]653#if defined(USE_WIN32)
[524]654    if(kk->driver == CACA_DRIVER_WIN32)
[213]655    {
[336]656        INPUT_RECORD rec;
657        DWORD num;
658
[347]659        for( ; ; )
[336]660        {
[347]661            GetNumberOfConsoleInputEvents(win32_hin, &num);
662            if(num == 0)
663                break;
[336]664
[347]665            ReadConsoleInput(win32_hin, &rec, 1, &num);
666            if(rec.EventType == KEY_EVENT)
[336]667            {
[347]668                if(rec.Event.KeyEvent.bKeyDown)
669                    event = CACA_EVENT_KEY_PRESS;
670                else
671                    event = CACA_EVENT_KEY_RELEASE;
[336]672
[347]673                if(rec.Event.KeyEvent.uChar.AsciiChar)
674                    return event | rec.Event.KeyEvent.uChar.AsciiChar;
[336]675            }
[347]676
677            if(rec.EventType == MOUSE_EVENT)
[336]678            {
[347]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                }
[336]700#if 0
[347]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
[336]716            }
[347]717
718            /* Unknown event */
719            return CACA_EVENT_NONE;
[336]720        }
721
[347]722        /* No event */
[335]723        return CACA_EVENT_NONE;
724    }
725    else
726#endif
[483]727#if defined(USE_GL)
[524]728    if(kk->driver == CACA_DRIVER_GL)
[494]729    {
730        glutMainLoopEvent();
[483]731
[527]732        if(kk->gl.resized && !kk->resize)
[494]733        {
[524]734            kk->resize = 1;
[527]735            kk->gl.resized = 0;
[494]736            return CACA_EVENT_RESIZE;
737        }
[483]738
[527]739        if(kk->gl.mouse_changed)
[494]740        {
[527]741            if(kk->gl.mouse_clicked)
[494]742            {
[527]743                event|= CACA_EVENT_MOUSE_PRESS | kk->gl.mouse_button;
744                kk->gl.mouse_clicked=0;
[494]745            }
[527]746            mouse_x = kk->gl.mouse_x;
747            mouse_y = kk->gl.mouse_y;
[494]748            event |= CACA_EVENT_MOUSE_MOTION | (mouse_x << 12) | mouse_y;
[527]749            kk->gl.mouse_changed = 0;
[494]750        }
751
[527]752        if(kk->gl.key != 0)
[494]753        {
754            event |= CACA_EVENT_KEY_PRESS;
[527]755            event |= kk->gl.key;
756            kk->gl.key = 0;
[520]757            return event;
[494]758        }
759
[527]760        if(kk->gl.special_key != 0)
[494]761        {
762            event |= CACA_EVENT_KEY_PRESS;
[483]763     
[527]764            switch(kk->gl.special_key)
[494]765            {
[527]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;
[494]782                default: return CACA_EVENT_NONE;
783            }
784        }
[520]785        return CACA_EVENT_NONE;
[494]786    }
787    else
[483]788#endif
[335]789    {
[329]790        /* Dummy */
[198]791    }
792
[332]793    return CACA_EVENT_NONE;
[198]794}
795
[336]796#if defined(USE_SLANG) || defined(USE_NCURSES) || defined(USE_CONIO)
[329]797static void _push_event(unsigned int event)
[199]798{
[357]799    if(!event || events == EVENTBUF_LEN)
[213]800        return;
[329]801    eventbuf[events] = event;
802    events++;
[199]803}
804
[329]805static unsigned int _pop_event(void)
[199]806{
[213]807    int i;
[329]808    unsigned int event;
[213]809
[329]810    if(events == 0)
[332]811        return CACA_EVENT_NONE;
[199]812
[329]813    event = eventbuf[0];
814    for(i = 1; i < events; i++)
815        eventbuf[i - 1] = eventbuf[i];
816    events--;
[251]817
[329]818    return event;
[199]819}
[336]820#endif
[199]821
Note: See TracBrowser for help on using the repository browser.