home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C!T ROM 2
/
ctrom_ii_b.zip
/
ctrom_ii_b
/
PROGRAM
/
C
/
CBGRX102
/
EVENTS.DOC
< prev
next >
Wrap
Text File
|
1992-08-12
|
15KB
|
296 lines
EVENT QUEUE LIBRARY
for Turbo C and DJGPP
User's Manual
Written by:
Csaba Biegl
May, 1992
Event Queue Library User's Manual page 2
Abstract
This document describes an event queue library which can be used in Turbo C
and DJGPP programs. The event queue mechanism is interrupt driven and the
queue stores keyboard and mouse events in the order of their arrival. In order
for the mouse services of this library to work an MS compatible mouse driver
has to be installed on the PC.
Introduction -- why event queues?
The "standard" MS-DOS programmer's interface to the keyboard (via DOS or BIOS
calls) and the mouse (via the mouse driver) has a couple of shortcomings --
especially for graphical user interfaces. These are:
∙ No mouse event history: the mouse driver provides some services
for the application program to poll the mouse position, button
states, etc.. These services can be adequate if the application
can afford to spend most of its time in a tight loop waiting for
these events. (For example a graphical editor) However, in
applications which do lengthy computations without user
interaction this method can easily lead to the loss of user
interaction events.
∙ Limited mouse cursor drawing capabilities: the mouse driver does
not support cursor drawing in extended, higher-resolution graphics
modes. The solution is to have the application to draw the cursor
after polling the mouse driver for the current cursor position.
However, in programs which spend a lot of time not waiting for
user input it will lead to long periods when the cursor is frozen.
∙ Limited keyboard buffer size. Unless reprogrammed by the
application the standard BIOS keyboard buffer size is only 16
bytes, which may be insufficient for longer type-ahead sequences.
∙ Missing keyboard modifier keys in the BIOS buffer: the standard
BIOS keyboard services cannot determine the status of keyboard
modifier keys for previously entered keys. (It is possible to
obtain these values at the moment the keystroke is received.)
The interrupt driven event queue library described in this manual attempts to
solve the above problems. It stores all user interaction events (key presses
and mouse button changes) in a FIFO queue together with the status of the
keyboard modifier keys and a time stamp of the event. The size of this queue
is programmable by the application, thus the queue can be large enough to
avoid event loss.
NOTE: although this event queue library is used in the LIBGRX graphics
library, it is in no way attached to LIBGRX. The event queue mechanism can be
used in any Turbo C or DJGPP program.
Event Queue Library User's Manual page 3
Data structures
The application program can obtain the user input events in an 'EventRecord'
structure which is shown below (all of the following declarations and macros
can be found in the include file "eventque.h"):
typedef struct {
unsigned char evt_type; /* event type: 0: keyboard, 1: mouse */
unsigned char evt_kbstat; /* keyboard status (ALT, SHIFT, etc..) */
unsigned char evt_mask; /* mouse event mask */
unsigned char evt_button; /* button status */
unsigned short evt_xpos; /* X coord (or keycode if keybd event) */
unsigned short evt_ypos; /* Y coord */
unsigned long evt_time; /* time stamp of event */
#define evt_keycode evt_xpos /* reuse this slot for keybd events !! */
} EventRecord;
Various macros have been declared to help in decoding the values in the slots
of the event record structure:
/*
* event types
*/
#define EVENT_KEYBD 0
#define EVENT_MOUSE 1
/*
* MOUSE event flag bits (values in the 'evt_mask' slot)
* (also defined in "mousex.h" of the graphics library)
*/
#define M_MOTION 0x001
#define M_LEFT_DOWN 0x002
#define M_LEFT_UP 0x004
#define M_RIGHT_DOWN 0x008
#define M_RIGHT_UP 0x010
#define M_MIDDLE_DOWN 0x020
#define M_MIDDLE_UP 0x040
#define M_BUTTON_DOWN (M_LEFT_DOWN | M_MIDDLE_DOWN | M_RIGHT_DOWN)
#define M_BUTTON_UP (M_LEFT_UP | M_MIDDLE_UP | M_RIGHT_UP)
#define M_BUTTON_CHANGE (M_BUTTON_UP | M_BUTTON_DOWN )
/*
* MOUSE button status bits (in the 'evt_button' slot)
*/
#define M_LEFT 1
#define M_RIGHT 2
#define M_MIDDLE 4
/*
* KEYBOARD status word bits ('evt_kbstat' slot)
* (also defined in "mousex.h" of the graphics library)
Event Queue Library User's Manual page 4
*/
#define KB_RIGHTSHIFT 0x01 /* right shift key depressed */
#define KB_LEFTSHIFT 0x02 /* left shift key depressed */
#define KB_CTRL 0x04 /* CTRL depressed */
#define KB_ALT 0x08 /* ALT depressed */
#define KB_SCROLLOCK 0x10 /* SCROLL LOCK active */
#define KB_NUMLOCK 0x20 /* NUM LOCK active */
#define KB_CAPSLOCK 0x40 /* CAPS LOCK active */
#define KB_INSERT 0x80 /* INSERT state active */
#define KB_SHIFT (KB_LEFTSHIFT | KB_RIGHTSHIFT)
The event queue is just a circular buffer of 'EventRecord' structures with a
header structure as follows:
typedef struct {
unsigned short evq_maxsize; /* max size of event queue */
unsigned short evq_cursize; /* number of events in the queue */
unsigned short evq_rdptr; /* next event to read */
unsigned short evq_wrptr; /* next event to be written */
short evq_xpos; /* current X coordinate of mouse */
short evq_ypos; /* current Y coordinate of mouse */
short evq_xmin; /* minimal mouse X coordinate */
short evq_ymin; /* minimal mouse Y coordinate */
short evq_xmax; /* maximal mouse X coordinate */
short evq_ymax; /* maximal mouse Y coordinate */
short evq_xspeed; /* horizontal speed (mickey/coord) */
short evq_yspeed; /* vertical speed (mickey/coord) */
unsigned short evq_thresh; /* fast movement threshold */
unsigned short evq_accel; /* multiplier for fast move */
unsigned char evq_drawmouse; /* interrupt handler has to draw mouse */
unsigned char evq_moved; /* set if mouse moved */
unsigned char evq_delchar; /* character removed from BIOS buffer */
unsigned char evq_enable; /* event generation control flag */
EventRecord evq_events[1]; /* event buffer space */
} EventQueue;
The event queue circler buffer is allocated by a library function (see next
section). Its size is determined at the time this init function is called.
After initialization the application program receives a pointer to the queue
header structure. NOTE: int the case of 32 bit DJGPP programs the event queue
is allocated in the dos extender area, and a pointer into the low memory area
is returned to the protected mode program.
The first four slots of the event queue header ('evq_maxsize' through
'evq_wrptr') should never be changed by the application program. These are for
queue management and are used by the library internally. The remaining
structure slots of the header can be used to control the mouse and the
generation of events. The 'evq_xpos' and 'evq_ypos' slots contain the current
mouse position. The 'evq_xmin' through 'evq_ymax' slots specify the mouse
coordinate limits. The event queue library uses only the mouse mickey counters
Event Queue Library User's Manual page 5
to calculate the cursor position. The reason for this is that some mouse
drivers perform the rounding of mouse cursor coordinates to the nearest
multiple of eight if they find themselves in a text or unrecognized graphics
mode. The 'evq_xspeed' and 'evq_yspeed' slots control the speed of the mouse.
The mouse mickey count changes are divided by these values before calculating
the cursor position. The 'evq_thresh' and 'evq_accel' slots can be used to
control the ballistic effect: if the cursor changes by more than the threshold
the change is multiplied with the acceleration. NOTE: most mouse drivers
already provide some amount of ballistic effect. The 'evq_drawmouse' flag
controls whether the interrupt-driven mouse event handler updates the mouse
cursor or not. The 'evq_moved' slot is set by the library whenever the mouse
cursor position changes. An application might clear this slot and then monitor
its value to detect a mouse movement.
The 'evq_delchar' slot affects the behavior of the keyboard event generation.
If this slot is set then the key code is removed from the BIOS buffer,
otherwise it is left there (even if an event entry is generated in the queue).
The 'evq_enable' slot can be used to individually enable or disable the
generation of mouse and keyboard events. The desired values for this slot can
be obtained using the EVENT_ENABLE macro:
/*
* set this bit in 'evq_enable' to enable the generation of the corresponding event
* use EVENT_KEYBD or EVENT_MOUSE as argument
*/
#define EVENT_ENABLE(type) (1 << (type))
Library functions
The library contains only the following three functions:
EventQueue *EventQueueInit(int qsize,int ms_stksize,void (*msdraw)(void));
void EventQueueDeInit(void);
int EventQueueNextEvent(EventQueue *q,EventRecord *e);
The 'EventQueueInit' function initializes the queue. The 'qsize' argument
specifies the size of the circular buffer. The 'msdraw' argument is the
function which is used to update the mouse cursor position whenever it
changes. The 'ms_stksize' argument specifies the size of the stack necessary
for the cursor drawing function. If the cursor update function pointer is NULL
the library will not attempt to update the cursor position. Otherwise the
cursor update function should obtain the current mouse coordinates from the
queue header 'evq_xpos' and 'evq_ypos'. If the 'evq_drawmouse' slot is cleared
in the queue header then the mouse cursor drawing function will not be called.
As mouse interrupts can occur at any time, the displaying and erasing of the
mouse cursor should be done with some caution. For display: first the cursor
should be drawn and 'evq_drawmouse' should be set only after this. For erase:
first 'evq_drawmouse' should be cleared and the cursor erased next. The above
sequence assures that no spurious mouse cursor drawing will happen. The
'evq_drawmouse' slot is cleared after the init function returns.
Event Queue Library User's Manual page 6
The 'EventQueueDeInit' function should be called before the termination of the
program. NOTE: it is very important to call this function before program
termination because a call to 'EventQueueInit' hooks some interrupts (the
keyboard interrupt and the mouse driver callback function). If these interrupt
are not reset to their initial values at program exit, the interrupt vectors
will point into the already terminated program -- with disastrous results.
The 'EventQueueNextEvent' function copies the next event entry from the queue
into the event buffer whose address is passed to it as an argument. It returns
a non-zero value if these was an event available, zero otherwise.