]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/MAI/bios_emulator/scitech/src/pm/event.c
* Patch by Thomas Frieden, 13 Nov 2002:
[karo-tx-uboot.git] / board / MAI / bios_emulator / scitech / src / pm / event.c
1 /****************************************************************************
2 *
3 *                   SciTech OS Portability Manager Library
4 *
5 *  ========================================================================
6 *
7 *    The contents of this file are subject to the SciTech MGL Public
8 *    License Version 1.0 (the "License"); you may not use this file
9 *    except in compliance with the License. You may obtain a copy of
10 *    the License at http://www.scitechsoft.com/mgl-license.txt
11 *
12 *    Software distributed under the License is distributed on an
13 *    "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14 *    implied. See the License for the specific language governing
15 *    rights and limitations under the License.
16 *
17 *    The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
18 *
19 *    The Initial Developer of the Original Code is SciTech Software, Inc.
20 *    All Rights Reserved.
21 *
22 *  ========================================================================
23 *
24 * Language:     ANSI C
25 * Environment:  Any
26 *
27 * Description:  Main implementation for the SciTech cross platform event
28 *               library. This module contains all the generic cross platform
29 *               code, and pulls in modules specific to each target OS
30 *               environment.
31 *
32 ****************************************************************************/
33
34 #include "event.h"
35 #include "pmapi.h"
36 #include <time.h>
37 #include <signal.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include "oshdr.h"
42
43 /*--------------------------- Global variables ----------------------------*/
44
45 #define EVENTQSIZE      100     /* Number of events in event queue      */
46 #define JOY_NUM_AXES    4       /* Number of joystick axes supported    */
47
48 static struct {
49     int         mx,my;              /* Current mouse position           */
50     int         head;               /* Head of event queue              */
51     int         tail;               /* Tail of event queue              */
52     int         freeHead;           /* Head of free list                */
53     int         count;              /* No. of items currently in queue  */
54     event_t     evtq[EVENTQSIZE];   /* The queue structure itself       */
55     int         oldMove;            /* Previous movement event          */
56     int         oldKey;             /* Previous key repeat event        */
57     int         oldJoyMove;         /* Previous joystick movement event */
58     int         joyMask;            /* Mask of joystick axes present    */
59     int         joyMin[JOY_NUM_AXES];
60     int         joyCenter[JOY_NUM_AXES];
61     int         joyMax[JOY_NUM_AXES];
62     int         joyPrev[JOY_NUM_AXES];
63     int         joyButState;
64     ulong       doubleClick;
65     ulong       autoRepeat;
66     ulong       autoDelay;
67     ulong       autoTicks;
68     ulong       doubleClickThresh;
69     ulong       firstAuto;
70     int         autoMouse_x;
71     int         autoMouse_y;
72     event_t     downMouse;
73     ulong       keyModifiers;       /* Current keyboard modifiers       */
74     uchar       keyTable[128];      /* Table of key up/down flags       */
75     ibool       allowLEDS;          /* True if LEDS should change       */
76     _EVT_userEventFilter    userEventCallback;
77     _EVT_mouseMoveHandler   mouseMove;
78     _EVT_heartBeatCallback  heartBeat;
79     void                    *heartBeatParams;
80     codepage_t              *codePage;
81     } EVT;
82
83 /*---------------------------- Implementation -----------------------------*/
84
85 #if defined(__REALDOS__) || defined(__SMX32__)
86 /* {secret} */
87 void EVTAPI _EVT_cCodeStart(void) {}
88 #endif
89
90 /* External assembler functions */
91
92 int EVTAPI _EVT_readJoyAxis(int mask,int *axis);
93 int EVTAPI _EVT_readJoyButtons(void);
94
95 /* Forward declaration */
96
97 ulong _EVT_getTicks(void);
98
99 /****************************************************************************
100 PARAMETERS:
101 evt - Event to add to the event queue
102
103 REMARKS:
104 Adds an event to the event queue by tacking it onto the tail of the event
105 queue. This routine assumes that at least one spot is available on the
106 freeList for the event to be inserted.
107
108 NOTE:   Interrupts MUST be OFF while this routine is called to ensure we have
109         mutually exclusive access to our internal data structures for
110         interrupt driven systems (like under DOS).
111 ****************************************************************************/
112 static void addEvent(
113     event_t *evt)
114 {
115     int evtID;
116
117     /* Check for mouse double click events */
118     if (evt->what & EVT_MOUSEEVT) {
119         EVT.autoMouse_x = evt->where_x;
120         EVT.autoMouse_y = evt->where_y;
121         if ((evt->what & EVT_MOUSEDOWN) && !(evt->message & EVT_DBLCLICK)) {
122             /* Determine if the last mouse event was a double click event */
123             uint diff_x = ABS(evt->where_x - EVT.downMouse.where_x);
124             uint diff_y = ABS(evt->where_y - EVT.downMouse.where_y);
125             if ((evt->message == EVT.downMouse.message)
126                 && ((evt->when - EVT.downMouse.when) <= EVT.doubleClick)
127                 && (diff_x <= EVT.doubleClickThresh)
128                 && (diff_y <= EVT.doubleClickThresh)) {
129                 evt->message |= EVT_DBLCLICK;
130                 EVT.downMouse = *evt;
131                 EVT.downMouse.when = 0;
132                 }
133             else
134                 EVT.downMouse = *evt;
135             EVT.autoTicks = _EVT_getTicks();
136             }
137         else if (evt->what & EVT_MOUSEUP) {
138             EVT.downMouse.what = EVT_NULLEVT;
139             EVT.firstAuto = true;
140             }
141         }
142
143     /* Call user supplied callback to modify the event if desired */
144     if (EVT.userEventCallback) {
145         if (!EVT.userEventCallback(evt))
146             return;
147         }
148
149     /* Get spot to place the event from the free list */
150     evtID = EVT.freeHead;
151     EVT.freeHead = EVT.evtq[EVT.freeHead].next;
152
153     /* Add to the EVT.tail of the event queue   */
154     evt->next = -1;
155     evt->prev = EVT.tail;
156     if (EVT.tail != -1)
157         EVT.evtq[EVT.tail].next = evtID;
158     else
159         EVT.head = evtID;
160     EVT.tail = evtID;
161     EVT.evtq[evtID] = *evt;
162     EVT.count++;
163 }
164
165 /****************************************************************************
166 REMARKS:
167 Internal function to initialise the event queue to the empty state.
168 ****************************************************************************/
169 static void initEventQueue(void)
170 {
171     int i;
172
173     /* Build free list, and initialize global data structures */
174     for (i = 0; i < EVENTQSIZE; i++)
175         EVT.evtq[i].next = i+1;
176     EVT.evtq[EVENTQSIZE-1].next = -1;       /* Terminate list           */
177     EVT.count = EVT.freeHead = 0;
178     EVT.head = EVT.tail = -1;
179     EVT.oldMove = -1;
180     EVT.oldKey = -1;
181     EVT.oldJoyMove = -1;
182     EVT.joyButState = 0;
183     EVT.mx = EVT.my = 0;
184     EVT.keyModifiers = 0;
185     EVT.allowLEDS = true;
186
187     /* Set default values for mouse double click and mouse auto events */
188     EVT.doubleClick = 440;
189     EVT.autoRepeat = 55;
190     EVT.autoDelay = 330;
191     EVT.autoTicks = 0;
192     EVT.doubleClickThresh = 5;
193     EVT.firstAuto = true;
194     EVT.autoMouse_x = EVT.autoMouse_y = 0;
195     memset(&EVT.downMouse,0,sizeof(EVT.downMouse));
196
197     /* Setup default pointers for event library */
198     EVT.userEventCallback = NULL;
199     EVT.codePage = &_CP_US_English;
200
201     /* Initialise the joystick module and do basic calibration (which assumes
202      * the joystick is centered.
203      */
204     EVT.joyMask = EVT_joyIsPresent();
205 }
206
207 #if defined(NEED_SCALE_JOY_AXIS) || !defined(USE_OS_JOYSTICK)
208 /****************************************************************************
209 REMARKS:
210 This function scales a joystick axis value to normalised form.
211 ****************************************************************************/
212 static int scaleJoyAxis(
213     int raw,
214     int axis)
215 {
216     int scaled,range;
217
218     /* Make sure the joystick is calibrated properly */
219     if (EVT.joyCenter[axis] - EVT.joyMin[axis] < 5)
220         return raw;
221     if (EVT.joyMax[axis] - EVT.joyCenter[axis] < 5)
222         return raw;
223
224     /* Now scale the coordinates to -128 to 127 */
225     raw -= EVT.joyCenter[axis];
226     if (raw < 0)
227         range = EVT.joyCenter[axis]-EVT.joyMin[axis];
228     else
229         range = EVT.joyMax[axis]-EVT.joyCenter[axis];
230     scaled = (raw * 128) / range;
231     if (scaled < -128)
232         scaled = -128;
233     if (scaled > 127)
234         scaled = 127;
235     return scaled;
236 }
237 #endif
238
239 #if     defined(__SMX32__)
240 #include "smx/event.c"
241 #elif   defined(__RTTARGET__)
242 #include "rttarget/event.c"
243 #elif   defined(__REALDOS__)
244 #include "dos/event.c"
245 #elif   defined(__WINDOWS32__)
246 #include "win32/event.c"
247 #elif   defined(__OS2__)
248 #if     defined(__OS2_PM__)
249 #include "os2pm/event.c"
250 #else
251 #include "os2/event.c"
252 #endif
253 #elif   defined(__LINUX__)
254 #if     defined(__USE_X11__)
255 #include "x11/event.c"
256 #else
257 #include "linux/event.c"
258 #endif
259 #elif   defined(__QNX__)
260 #if     defined(__USE_PHOTON__)
261 #include "photon/event.c"
262 #elif   defined(__USE_X11__)
263 #include "x11/event.c"
264 #else
265 #include "qnx/event.c"
266 #endif
267 #elif   defined(__BEOS__)
268 #include "beos/event.c"
269 #else
270 #error  Event library not ported to this platform yet!
271 #endif
272
273 /*------------------------ Public interface routines ----------------------*/
274
275 /* If USE_OS_JOYSTICK is defined, the OS specific libraries will implement
276  * the joystick code rather than using the generic OS portable version.
277  */
278
279 #ifndef USE_OS_JOYSTICK
280 /****************************************************************************
281 DESCRIPTION:
282 Returns the mask indicating what joystick axes are attached.
283
284 HEADER:
285 event.h
286
287 REMARKS:
288 This function is used to detect the attached joysticks, and determine
289 what axes are present and functioning. This function will re-detect any
290 attached joysticks when it is called, so if the user forgot to attach
291 the joystick when the application started, you can call this function to
292 re-detect any newly attached joysticks.
293
294 SEE ALSO:
295 EVT_joySetLowerRight, EVT_joySetCenter, EVT_joyIsPresent
296 ****************************************************************************/
297 int EVTAPI EVT_joyIsPresent(void)
298 {
299     int mask,i;
300
301     memset(EVT.joyMin,0,sizeof(EVT.joyMin));
302     memset(EVT.joyCenter,0,sizeof(EVT.joyCenter));
303     memset(EVT.joyMax,0,sizeof(EVT.joyMax));
304     memset(EVT.joyPrev,0,sizeof(EVT.joyPrev));
305     EVT.joyButState = 0;
306 #ifdef __LINUX__
307     PM_init();
308 #endif
309     mask = _EVT_readJoyAxis(EVT_JOY_AXIS_ALL,EVT.joyCenter);
310     if (mask) {
311         for (i = 0; i < JOY_NUM_AXES; i++)
312             EVT.joyMax[i] = EVT.joyCenter[i]*2;
313         }
314     return mask;
315 }
316
317 /****************************************************************************
318 DESCRIPTION:
319 Polls the joystick for position and button information.
320
321 HEADER:
322 event.h
323
324 REMARKS:
325 This routine is used to poll analogue joysticks for button and position
326 information. It should be called once for each main loop of the user
327 application, just before processing all pending events via EVT_getNext.
328 All information polled from the joystick will be posted to the event
329 queue for later retrieval.
330
331 Note:   Most analogue joysticks will provide readings that change even
332         though the joystick has not moved. Hence if you call this routine
333         you will likely get an EVT_JOYMOVE event every time through your
334         event loop.
335
336 SEE ALSO:
337 EVT_getNext, EVT_peekNext, EVT_joySetUpperLeft, EVT_joySetLowerRight,
338 EVT_joySetCenter, EVT_joyIsPresent
339 ****************************************************************************/
340 void EVTAPI EVT_pollJoystick(void)
341 {
342     event_t evt;
343     int     i,axis[JOY_NUM_AXES],newButState,mask,moved,ps;
344
345     if (EVT.joyMask) {
346         /* Read joystick axes and post movement events if they have
347          * changed since the last time we polled. Until the events are
348          * actually flushed, we keep modifying the same joystick movement
349          * event, so you won't get multiple movement event
350          */
351         mask = _EVT_readJoyAxis(EVT.joyMask,axis);
352         newButState = _EVT_readJoyButtons();
353         moved = false;
354         for (i = 0; i < JOY_NUM_AXES; i++) {
355             if (mask & (EVT_JOY_AXIS_X1 << i))
356                 axis[i] = scaleJoyAxis(axis[i],i);
357             else
358                 axis[i] = EVT.joyPrev[i];
359             if (axis[i] != EVT.joyPrev[i])
360                 moved = true;
361             }
362         if (moved) {
363             memcpy(EVT.joyPrev,axis,sizeof(EVT.joyPrev));
364             ps = _EVT_disableInt();
365             if (EVT.oldJoyMove != -1) {
366                 /* Modify the existing joystick movement event */
367                 EVT.evtq[EVT.oldJoyMove].message = newButState;
368                 EVT.evtq[EVT.oldJoyMove].where_x = EVT.joyPrev[0];
369                 EVT.evtq[EVT.oldJoyMove].where_y = EVT.joyPrev[1];
370                 EVT.evtq[EVT.oldJoyMove].relative_x = EVT.joyPrev[2];
371                 EVT.evtq[EVT.oldJoyMove].relative_y = EVT.joyPrev[3];
372                 }
373             else if (EVT.count < EVENTQSIZE) {
374                 /* Add a new joystick movement event */
375                 EVT.oldJoyMove = EVT.freeHead;
376                 memset(&evt,0,sizeof(evt));
377                 evt.what = EVT_JOYMOVE;
378                 evt.message = EVT.joyButState;
379                 evt.where_x = EVT.joyPrev[0];
380                 evt.where_y = EVT.joyPrev[1];
381                 evt.relative_x = EVT.joyPrev[2];
382                 evt.relative_y = EVT.joyPrev[3];
383                 addEvent(&evt);
384                 }
385             _EVT_restoreInt(ps);
386             }
387
388         /* Read the joystick buttons, and post events to reflect the change
389          * in state for the joystick buttons.
390          */
391         if (newButState != EVT.joyButState) {
392             if (EVT.count < EVENTQSIZE) {
393                 /* Add a new joystick click event */
394                 ps = _EVT_disableInt();
395                 memset(&evt,0,sizeof(evt));
396                 evt.what = EVT_JOYCLICK;
397                 evt.message = newButState;
398                 EVT.evtq[EVT.oldJoyMove].where_x = EVT.joyPrev[0];
399                 EVT.evtq[EVT.oldJoyMove].where_y = EVT.joyPrev[1];
400                 EVT.evtq[EVT.oldJoyMove].relative_x = EVT.joyPrev[2];
401                 EVT.evtq[EVT.oldJoyMove].relative_y = EVT.joyPrev[3];
402                 addEvent(&evt);
403                 _EVT_restoreInt(ps);
404                 }
405             EVT.joyButState = newButState;
406             }
407         }
408 }
409
410 /****************************************************************************
411 DESCRIPTION:
412 Calibrates the joystick upper left position
413
414 HEADER:
415 event.h
416
417 REMARKS:
418 This function can be used to zero in on better joystick calibration factors,
419 which may work better than the default simplistic calibration (which assumes
420 the joystick is centered when the event library is initialised).
421 To use this function, ask the user to hold the stick in the upper left
422 position and then have them press a key or button. and then call this
423 function. This function will then read the joystick and update the
424 calibration factors.
425
426 Usually, assuming that the stick was centered when the event library was
427 initialized, you really only need to call EVT_joySetLowerRight since the
428 upper left position is usually always 0,0 on most joysticks. However, the
429 safest procedure is to call all three calibration functions.
430
431 SEE ALSO:
432 EVT_joySetUpperLeft, EVT_joySetLowerRight, EVT_joyIsPresent
433 ****************************************************************************/
434 void EVTAPI EVT_joySetUpperLeft(void)
435 {
436     _EVT_readJoyAxis(EVT_JOY_AXIS_ALL,EVT.joyMin);
437 }
438
439 /****************************************************************************
440 DESCRIPTION:
441 Calibrates the joystick lower right position
442
443 HEADER:
444 event.h
445
446 REMARKS:
447 This function can be used to zero in on better joystick calibration factors,
448 which may work better than the default simplistic calibration (which assumes
449 the joystick is centered when the event library is initialised).
450 To use this function, ask the user to hold the stick in the lower right
451 position and then have them press a key or button. and then call this
452 function. This function will then read the joystick and update the
453 calibration factors.
454
455 Usually, assuming that the stick was centered when the event library was
456 initialized, you really only need to call EVT_joySetLowerRight since the
457 upper left position is usually always 0,0 on most joysticks. However, the
458 safest procedure is to call all three calibration functions.
459
460 SEE ALSO:
461 EVT_joySetUpperLeft, EVT_joySetCenter, EVT_joyIsPresent
462 ****************************************************************************/
463 void EVTAPI EVT_joySetLowerRight(void)
464 {
465     _EVT_readJoyAxis(EVT_JOY_AXIS_ALL,EVT.joyMax);
466 }
467
468 /****************************************************************************
469 DESCRIPTION:
470 Calibrates the joystick center position
471
472 HEADER:
473 event.h
474
475 REMARKS:
476 This function can be used to zero in on better joystick calibration factors,
477 which may work better than the default simplistic calibration (which assumes
478 the joystick is centered when the event library is initialised).
479 To use this function, ask the user to hold the stick in the center
480 position and then have them press a key or button. and then call this
481 function. This function will then read the joystick and update the
482 calibration factors.
483
484 Usually, assuming that the stick was centered when the event library was
485 initialized, you really only need to call EVT_joySetLowerRight since the
486 upper left position is usually always 0,0 on most joysticks. However, the
487 safest procedure is to call all three calibration functions.
488
489 SEE ALSO:
490 EVT_joySetUpperLeft, EVT_joySetLowerRight, EVT_joySetCenter
491 ****************************************************************************/
492 void EVTAPI EVT_joySetCenter(void)
493 {
494     _EVT_readJoyAxis(EVT_JOY_AXIS_ALL,EVT.joyCenter);
495 }
496 #endif
497
498 /****************************************************************************
499 DESCRIPTION:
500 Posts a user defined event to the event queue
501
502 HEADER:
503 event.h
504
505 RETURNS:
506 True if event was posted, false if event queue is full.
507
508 PARAMETERS:
509 what        - Type code for message to post
510 message     - Event specific message to post
511 modifiers   - Event specific modifier flags to post
512
513 REMARKS:
514 This routine is used to post user defined events to the event queue.
515
516 SEE ALSO:
517 EVT_flush, EVT_getNext, EVT_peekNext, EVT_halt
518 ****************************************************************************/
519 ibool EVTAPI EVT_post(
520     ulong which,
521     ulong what,
522     ulong message,
523     ulong modifiers)
524 {
525     event_t evt;
526     uint    ps;
527
528     if (EVT.count < EVENTQSIZE) {
529         /* Save information in event record */
530         ps = _EVT_disableInt();
531         evt.which = which;
532         evt.when = _EVT_getTicks();
533         evt.what = what;
534         evt.message = message;
535         evt.modifiers = modifiers;
536         addEvent(&evt);             /* Add to EVT.tail of event queue   */
537         _EVT_restoreInt(ps);
538         return true;
539         }
540     else
541         return false;
542 }
543
544 /****************************************************************************
545 DESCRIPTION:
546 Flushes all events of a specified type from the event queue.
547
548 PARAMETERS:
549 mask    - Mask specifying the types of events that should be removed
550
551 HEADER:
552 event.h
553
554 REMARKS:
555 Flushes (removes) all pending events of the specified type from the event
556 queue. You may combine the masks for different event types with a simple
557 logical OR.
558
559 SEE ALSO:
560 EVT_getNext, EVT_halt, EVT_peekNext
561 ****************************************************************************/
562 void EVTAPI EVT_flush(
563     ulong mask)
564 {
565     event_t evt;
566
567     do {                            /* Flush all events */
568         EVT_getNext(&evt,mask);
569         } while (evt.what != EVT_NULLEVT);
570 }
571
572 /****************************************************************************
573 DESCRIPTION:
574 Halts until and event of the specified type is recieved.
575
576 HEADER:
577 event.h
578
579 PARAMETERS:
580 evt     - Pointer to
581 mask    - Mask specifying the types of events that should be removed
582
583 REMARKS:
584 This functions halts exceution until an event of the specified type is
585 recieved into the event queue. It does not flush the event queue of events
586 before performing the busy loop. However this function does throw away
587 any events other than the ones you have requested via the event mask, to
588 avoid the event queue filling up with unwanted events (like EVT_KEYUP or
589 EVT_MOUSEMOVE events).
590
591 SEE ALSO:
592 EVT_getNext, EVT_flush, EVT_peekNext
593 ****************************************************************************/
594 void EVTAPI EVT_halt(
595     event_t *evt,
596     ulong mask)
597 {
598     do {                            /* Wait for an event    */
599         if (mask & (EVT_JOYEVT))
600             EVT_pollJoystick();
601         EVT_getNext(evt,EVT_EVERYEVT);
602         } while (!(evt->what & mask));
603 }
604
605 /****************************************************************************
606 DESCRIPTION:
607 Peeks at the next pending event in the event queue.
608
609 HEADER:
610 event.h
611
612 RETURNS:
613 True if an event is pending, false if not.
614
615 PARAMETERS:
616 evt     - Pointer to structure to return the event info in
617 mask    - Mask specifying the types of events that should be removed
618
619 REMARKS:
620 Peeks at the next pending event of the specified type in the event queue. The
621 mask parameter is used to specify the type of events to be peeked at, and
622 can be any logical combination of any of the flags defined by the
623 EVT_eventType enumeration.
624
625 In contrast to EVT_getNext, the event is not removed from the event queue.
626 You may combine the masks for different event types with a simple logical OR.
627
628 SEE ALSO:
629 EVT_flush, EVT_getNext, EVT_halt
630 ****************************************************************************/
631 ibool EVTAPI EVT_peekNext(
632     event_t *evt,
633     ulong mask)
634 {
635     int     evtID;
636     uint    ps;
637
638     if (EVT.heartBeat)
639         EVT.heartBeat(EVT.heartBeatParams);
640     _EVT_pumpMessages();                /* Pump all messages into queue */
641     EVT.mouseMove(EVT.mx,EVT.my);       /* Move the mouse cursor        */
642     evt->what = EVT_NULLEVT;            /* Default to null event        */
643     if (EVT.count) {
644         /* It is possible that an event be posted while we are trying
645          * to access the event queue. This would create problems since
646          * we may end up with invalid data for our event queue pointers. To
647          * alleviate this, all interrupts are suspended while we manipulate
648          * our pointers.
649          */
650         ps = _EVT_disableInt();             /* disable interrupts       */
651         for (evtID = EVT.head; evtID != -1; evtID = EVT.evtq[evtID].next) {
652             if (EVT.evtq[evtID].what & mask)
653                 break;                      /* Found an event           */
654             }
655         if (evtID == -1) {
656             _EVT_restoreInt(ps);
657             return false;                   /* Event was not found      */
658             }
659         *evt = EVT.evtq[evtID];                 /* Return the event         */
660         _EVT_restoreInt(ps);
661         if (evt->what & EVT_KEYEVT)
662             _EVT_maskKeyCode(evt);
663         }
664     return evt->what != EVT_NULLEVT;
665 }
666
667 /****************************************************************************
668 DESCRIPTION:
669 Retrieves the next pending event from the event queue.
670
671 PARAMETERS:
672 evt     - Pointer to structure to return the event info in
673 mask    - Mask specifying the types of events that should be removed
674
675 HEADER:
676 event.h
677
678 RETURNS:
679 True if an event was pending, false if not.
680
681 REMARKS:
682 Retrieves the next pending event from the event queue, and stores it in a
683 event_t structure. The mask parameter is used to specify the type of events
684 to be removed, and can be any logical combination of any of the flags defined
685 by the EVT_eventType enumeration.
686
687 The what field of the event contains the event code of the event that was
688 extracted. All application specific events should begin with the EVT_USEREVT
689 code and build from there. Since the event code is stored in an integer,
690 there is a maximum of 32 different event codes that can be distinguished.
691 You can store extra information about the event in the message field to
692 distinguish between events of the same class (for instance the button used in
693 a EVT_MOUSEDOWN event).
694
695 If an event of the specified type was not in the event queue, the what field
696 of the event will be set to NULLEVT, and the return value will return false.
697
698 Note:   You should /always/ use the EVT_EVERYEVT mask for extracting events
699         from your main event loop handler. Using a mask for only a specific
700         type of event for long periods of time will cause the event queue to
701         fill up with events of the type you are ignoring, eventually causing
702         the application to hang when the event queue becomes full.
703
704 SEE ALSO:
705 EVT_flush, EVT_halt, EVT_peekNext
706 ****************************************************************************/
707 ibool EVTAPI EVT_getNext(
708     event_t *evt,
709     ulong mask)
710 {
711     int     evtID,next,prev;
712     uint    ps;
713
714     if (EVT.heartBeat)
715         EVT.heartBeat(EVT.heartBeatParams);
716     _EVT_pumpMessages();                /* Pump all messages into queue */
717     EVT.mouseMove(EVT.mx,EVT.my);       /* Move the mouse cursor        */
718     evt->what = EVT_NULLEVT;            /* Default to null event        */
719     if (EVT.count) {
720         /* It is possible that an event be posted while we are trying
721          * to access the event queue. This would create problems since
722          * we may end up with invalid data for our event queue pointers. To
723          * alleviate this, all interrupts are suspended while we manipulate
724          * our pointers.
725          */
726         ps = _EVT_disableInt();             /* disable interrupts       */
727         for (evtID = EVT.head; evtID != -1; evtID = EVT.evtq[evtID].next) {
728             if (EVT.evtq[evtID].what & mask)
729                 break;                      /* Found an event           */
730             }
731         if (evtID == -1) {
732             _EVT_restoreInt(ps);
733             return false;                   /* Event was not found      */
734             }
735         next = EVT.evtq[evtID].next;
736         prev = EVT.evtq[evtID].prev;
737         if (prev != -1)
738             EVT.evtq[prev].next = next;
739         else
740             EVT.head = next;
741         if (next != -1)
742             EVT.evtq[next].prev = prev;
743         else
744             EVT.tail = prev;
745         *evt = EVT.evtq[evtID];                 /* Return the event         */
746         EVT.evtq[evtID].next = EVT.freeHead;        /* and return to free list  */
747         EVT.freeHead = evtID;
748         EVT.count--;
749         if (evt->what == EVT_MOUSEMOVE)
750             EVT.oldMove = -1;
751         if (evt->what == EVT_KEYREPEAT)
752             EVT.oldKey = -1;
753         if (evt->what == EVT_JOYMOVE)
754             EVT.oldJoyMove = -1;
755         _EVT_restoreInt(ps);                /* enable interrupts        */
756         if (evt->what & EVT_KEYEVT)
757             _EVT_maskKeyCode(evt);
758         }
759
760     /* If there is no event pending, check if we should generate an auto
761      * mouse down event if the mouse is still currently down.
762      */
763     if (evt->what == EVT_NULLEVT && EVT.autoRepeat && (mask & EVT_MOUSEAUTO) && (EVT.downMouse.what & EVT_MOUSEDOWN)) {
764         ulong ticks = _EVT_getTicks();
765         if ((ticks - EVT.autoTicks) >= (EVT.autoRepeat + (EVT.firstAuto ? EVT.autoDelay : 0))) {
766             evt->what = EVT_MOUSEAUTO;
767             evt->message = EVT.downMouse.message;
768             evt->modifiers = EVT.downMouse.modifiers;
769             evt->where_x = EVT.autoMouse_x;
770             evt->where_y = EVT.autoMouse_y;
771             evt->relative_x = 0;
772             evt->relative_y = 0;
773             EVT.autoTicks = evt->when = ticks;
774             EVT.firstAuto = false;
775             }
776         }
777     return evt->what != EVT_NULLEVT;
778 }
779
780 /****************************************************************************
781 DESCRIPTION:
782 Installs a user supplied event filter callback for event handling.
783
784 HEADER:
785 event.h
786
787 PARAMETERS:
788 userEventFilter - Address of user supplied event filter callback
789
790 REMARKS:
791 This function allows the application programmer to install an event filter
792 callback for event handling. Once you install your callback, the MGL
793 event handling routines will call your callback with a pointer to the
794 new event that will be placed into the event queue. Your callback can the
795 modify the contents of the event before it is placed into the queue (for
796 instance adding custom information or perhaps high precision timing
797 information).
798
799 If your callback returns FALSE, the event will be ignore and will not be
800 posted to the event queue. You should always return true from your event
801 callback unless you plan to use the events immediately that they are
802 recieved.
803
804 Note:   Your event callback may be called in response to a hardware
805         interrupt and will be executing in the context of the hardware
806         interrupt handler under MSDOS (ie: keyboard interrupt or mouse
807         interrupt). For this reason the code pages for the callback that
808         you register must be locked in memory with the PM_lockCodePages
809         function. You must also lock down any data pages that your function
810         needs to reference as well.
811
812 Note:   You can also use this filter callback to process events at the
813         time they are activated by the user (ie: when the user hits the
814         key or moves the mouse), but make sure your code runs as fast as
815         possible as it will be executing inside the context of an interrupt
816         handler on some systems.
817
818 SEE ALSO:
819 EVT_getNext, EVT_peekNext
820 ****************************************************************************/
821 void EVTAPI EVT_setUserEventFilter(
822     _EVT_userEventFilter filter)
823 {
824     EVT.userEventCallback = filter;
825 }
826
827 /****************************************************************************
828 DESCRIPTION:
829 Installs a user supplied event heartbeat callback function.
830
831 HEADER:
832 event.h
833
834 PARAMETERS:
835 callback    - Address of user supplied event heartbeat callback
836 params      - Parameters to pass to the event heartbeat function
837
838 REMARKS:
839 This function allows the application programmer to install an event heatbeat
840 function that gets called every time that EVT_getNext or EVT_peekNext
841 is called. This is primarily useful for simulating text mode cursors inside
842 event handling code when running in graphics modes as opposed to hardware
843 text modes.
844
845 SEE ALSO:
846 EVT_getNext, EVT_peekNext, EVT_getHeartBeatCallback
847 ****************************************************************************/
848 void EVTAPI EVT_setHeartBeatCallback(
849     _EVT_heartBeatCallback callback,
850     void *params)
851 {
852     EVT.heartBeat = callback;
853     EVT.heartBeatParams = params;
854 }
855
856
857 /****************************************************************************
858 DESCRIPTION:
859 Returns the current user supplied event heartbeat callback function.
860
861 HEADER:
862 event.h
863
864 PARAMETERS:
865 callback    - Place to store the address of user supplied event heartbeat callback
866 params      - Place to store the parameters to pass to the event heartbeat function
867
868 REMARKS:
869 This function retrieves the current event heatbeat function that gets called
870 every time that EVT_getNext or EVT_peekNext is called.
871
872 SEE ALSO:
873 EVT_getNext, EVT_peekNext, EVT_setHeartBeatCallback
874 ****************************************************************************/
875 void EVTAPI EVT_getHeartBeatCallback(
876     _EVT_heartBeatCallback *callback,
877     void **params)
878 {
879     *callback = EVT.heartBeat;
880     *params = EVT.heartBeatParams;
881 }
882
883 /****************************************************************************
884 DESCRIPTION:
885 Determines if a specified key is currently down.
886
887 PARAMETERS:
888 scanCode    - Scan code to test
889
890 RETURNS:
891 True of the specified key is currently held down.
892
893 HEADER:
894 event.h
895
896 REMARKS:
897 This function determines if a specified key is currently down at the
898 time that the call is made. You simply need to pass in the scan code of
899 the key that you wish to test, and the MGL will tell you if it is currently
900 down or not. The MGL does this by keeping track of the up and down state
901 of all the keys.
902 ****************************************************************************/
903 ibool EVTAPI EVT_isKeyDown(
904     uchar scanCode)
905 {
906     return _EVT_isKeyDown(scanCode);
907 }
908
909 /****************************************************************************
910 DESCRIPTION:
911 Set the mouse position for the event module
912
913 PARAMETERS:
914 x   - X coordinate to move the mouse cursor position to
915 y   - Y coordinate to move the mouse cursor position to
916
917 HEADER:
918 event.h
919
920 REMARKS:
921 This function moves the mouse cursor position for the event module to the
922 specified location.
923
924 SEE ALSO:
925 EVT_getMousePos
926 ****************************************************************************/
927 void EVTAPI EVT_setMousePos(
928     int x,
929     int y)
930 {
931     EVT.mx = x;
932     EVT.my = y;
933     _EVT_setMousePos(&EVT.mx,&EVT.my);
934     EVT.mouseMove(EVT.mx,EVT.my);
935 }
936
937 /****************************************************************************
938 DESCRIPTION:
939 Returns the current mouse cursor location.
940
941 HEADER:
942 event.h
943
944 PARAMETERS:
945 x   - Place to store value for mouse x coordinate (screen coordinates)
946 y   - Place to store value for mouse y coordinate (screen coordinates)
947
948 REMARKS:
949 Obtains the current mouse cursor position in screen coordinates. Normally the
950 mouse cursor location is tracked using the mouse movement events that are
951 posted to the event queue when the mouse moves, however this routine
952 provides an alternative method of polling the mouse cursor location.
953
954 SEE ALSO:
955 EVT_setMousePos
956 ****************************************************************************/
957 void EVTAPI EVT_getMousePos(
958     int *x,
959     int *y)
960 {
961     *x = EVT.mx;
962     *y = EVT.my;
963 }
964
965 /****************************************************************************
966 DESCRIPTION:
967 Returns the currently active code page for translation of keyboard characters.
968
969 HEADER:
970 event.h
971
972 RETURNS:
973 Pointer to the currently active code page translation table.
974
975 REMARKS:
976 This function is returns a pointer to the currently active code page
977 translation table. See EVT_setCodePage for more information.
978
979 SEE ALSO:
980 EVT_setCodePage
981 ****************************************************************************/
982 codepage_t * EVTAPI EVT_getCodePage(void)
983 {
984     return EVT.codePage;
985 }
986
987 /****************************************************************************
988 DESCRIPTION:
989 Sets the currently active code page for translation of keyboard characters.
990
991 HEADER:
992 event.h
993
994 PARAMETERS:
995 page    - New code page to make active
996
997 REMARKS:
998 This function is used to set a new code page translation table that is used
999 to translate virtual scan code values to ASCII characters for different
1000 keyboard configurations. The default is usually US English, although if
1001 possible the PM library will auto-detect the correct code page translation
1002 for the target OS if OS services are available to determine what type of
1003 keyboard is currently attached.
1004
1005 SEE ALSO:
1006 EVT_getCodePage
1007 ****************************************************************************/
1008 void EVTAPI EVT_setCodePage(
1009     codepage_t *page)
1010 {
1011     EVT.codePage = page;
1012 }
1013
1014 /* The following contains fake C prototypes and documentation for the
1015  * macro functions in the event.h header file. These exist soley so
1016  * that DocJet will correctly pull in the documentation for these functions.
1017  */
1018 #ifdef  INCLUDE_DOC_FUNCTIONS
1019
1020 /****************************************************************************
1021 DESCRIPTION:
1022 Macro to extract the ASCII code from a message.
1023
1024 PARAMETERS:
1025 message - Message to extract ASCII code from
1026
1027 RETURNS:
1028 ASCII code extracted from the message.
1029
1030 HEADER:
1031 event.h
1032
1033 REMARKS:
1034 Macro to extract the ASCII code from the message field of the event_t
1035 structure. You pass the message field to the macro as the parameter and
1036 the ASCII code is the result, for example:
1037
1038     event_t EVT.myEvent;
1039     uchar   code;
1040     code = EVT_asciiCode(EVT.myEvent.message);
1041
1042 SEE ALSO:
1043 EVT_scanCode, EVT_repeatCount
1044 ****************************************************************************/
1045 uchar EVT_asciiCode(
1046     ulong message);
1047
1048 /****************************************************************************
1049 DESCRIPTION:
1050 Macro to extract the keyboard scan code from a message.
1051
1052 HEADER:
1053 event.h
1054
1055 PARAMETERS:
1056 message - Message to extract scan code from
1057
1058 RETURNS:
1059 Keyboard scan code extracted from the message.
1060
1061 REMARKS:
1062 Macro to extract the keyboard scan code from the message field of the event
1063 structure. You pass the message field to the macro as the parameter and
1064 the scan code is the result, for example:
1065
1066     event_t EVT.myEvent;
1067     uchar   code;
1068     code = EVT_scanCode(EVT.myEvent.message);
1069
1070 NOTE:   Scan codes in the event library are not really hardware scan codes,
1071         but rather virtual scan codes as generated by a low level keyboard
1072         interface driver. All virtual scan code values are defined by the
1073         EVT_scanCodesType enumeration, and will be identical across all
1074         supports OS'es and platforms.
1075
1076 SEE ALSO:
1077 EVT_asciiCode, EVT_repeatCount
1078 ****************************************************************************/
1079 uchar EVT_scanCode(
1080     ulong message);
1081
1082 /****************************************************************************
1083 DESCRIPTION:
1084 Macro to extract the repeat count from a message.
1085
1086 HEADER:
1087 event.h
1088
1089 PARAMETERS:
1090 message - Message to extract repeat count from
1091
1092 RETURNS:
1093 Repeat count extracted from the message.
1094
1095 REMARKS:
1096 Macro to extract the repeat count from the message field of the event
1097 structure. The repeat count is the number of times that the key repeated
1098 before there was another keyboard event to be place in the queue, and
1099 allows the event handling code to avoid keyboard buffer overflow
1100 conditions when a single key is held down by the user. If you are processing
1101 a key repeat code, you will probably want to check this field to see how
1102 many key repeats you should process for this message.
1103
1104 SEE ALSO:
1105 EVT_asciiCode, EVT_repeatCount
1106 ****************************************************************************/
1107 short EVT_repeatCount(
1108     ulong message);
1109
1110 #endif  /* DOC FUNCTIONS */
1111
1112 #if defined(__REALDOS__) || defined(__SMX32__)
1113 /* {secret} */
1114 void EVTAPI _EVT_cCodeEnd(void) {}
1115 #endif