Not the last, I want to document Image functions too (but I need to try).
Please, I want to know if you found things not OK.
* Mouse event handling
All mouse services need the presence of a mouse. An application can test whether a mouse is available by calling the function:
int GrMouseDetect(void);
which will return zero if no mouse (or mouse driver) is present, non-zero otherwise. The mouse must be initialized by calling one (and only one) of these functions:
void GrMouseInit(void); void GrMouseInitN(int queue_size);
'GrMouseInit' sets a event queue (see below) size to 'GR_M_QUEU_SIZE' (128). A user supply event queue size can be set calling 'GrMouseInitN' instead.
It is a good practice to call 'GrMouseUnInit' before exiting the program. This will restore any interrupt vectors hooked by the program to their original values.
void GrMouseUnInit(void);
The mouse can be controlled with the following functions:
void GrMouseSetSpeed(int spmult,int spdiv); void GrMouseSetAccel(int thresh,int accel); void GrMouseSetLimits(int x1,int y1,int x2,int y2); void GrMouseGetLimits(int *x1,int *y1,int *x2,int *y2); void GrMouseWarp(int x,int y);
The library calculates the mouse position only from the mouse mickey counters. (To avoid the limit and 'rounding to the next multiple of eight' problem with some mouse driver when it finds itself in a graphics mode unknown to it.) The parameters to the 'GrMouseSetSpeed' function specify how coordinate changes are obtained from mickey counter changes, multipling by 'spmult' and dividing by 'spdiv'. In high resolution graphics modes the value of one just works fine, in low resolution modes (320x200 or similar) it is best set the 'spdiv' to two or three. (Of course, it also depends on the sensitivity the mouse.) The 'GrMouseSetAccel' function is used to control the ballistic effect: if a mouse coordinate changes between two samplings by more than the 'thresh' parameter, the change is multiplied by the 'accel' parameter. NOTE: some mouse drivers perform similar calculations before reporting the coordinates in mickeys. In this case the acceleration done by the library will be additional to the one already performed by the mouse driver. The limits of the mouse movement can be set (passed limits will be clipped to the screen) with 'GrMouseSetLimits' (default is the whole screen) and the current limits can be obtained with 'GrMouseGetLimits'. 'GrMouseWarp' sets the mouse cursor to the specified position.
As typical mouse drivers do not know how to draw mouse cursors in high resolution graphics modes, the mouse cursor is drawn by the library. The mouse cursor can be set with:
void GrMouseSetCursor(GrCursor *cursor); void GrMouseSetColors(GrColor fg,GrColor bg);
'GrMouseSetColors' uses an internal arrow pattern, the color 'fg' will be used as the interior of it and 'bg' will be the border. The current mouse cursor can be obtained with:
GrCursor *GrMouseGetCursor(void);
The mouse cursor can be displayed/erased with:
void GrMouseDisplayCursor(void); void GrMouseEraseCursor(void);
The mouse cursor can be left permanently displayed. All graphics primitives except for the few non-clipping functions check for conflicts with the mouse cursor and erase it before the drawing if necessary. Of course, it may be more efficient to erase the cursor manually before a long drawing sequence and redraw it after completion. The library provides an alternative pair of calls for this purpose which will erase the cursor only if it interferes with the drawing:
int GrMouseBlock(GrContext *c,int x1,int y1,int x2,int y2); void GrMouseUnBlock(int return_value_from_GrMouseBlock);
'GrMouseBlock' should be passed the context in which the drawing will take place (the usual convention of NULL meaning the current context is supported) and the limits of the affected area. It will erase the cursor only if it interferes with the drawing. When the drawing is finished 'GrMouseUnBlock' must be called with the argument returned by 'GrMouseBlock'.
The status of the mouse cursor can be obtained with calling 'GrMouseCursorIsDisplayed'. This function will return non-zero if the cursor is displayed, zero if it is erased.
int GrMouseCursorIsDisplayed(void);
The library supports (beside the simple cursor drawing) three types of "rubberband" attached to the mouse cursor. The 'GrMouseSetCursorMode' function is used to select the cursor drawing mode.
void GrMouseSetCursorMode(int mode,...);
The parameter 'mode' can have the following values:
#define GR_M_CUR_NORMAL 0 /* MOUSE CURSOR modes: just the cursor */ #define GR_M_CUR_RUBBER 1 /* rect. rubber band (XOR-d to the screen) */ #define GR_M_CUR_LINE 2 /* line attached to the cursor */ #define GR_M_CUR_BOX 3 /* rectangular box dragged by the cursor */
'GrMouseSetCursorMode' takes different parameters depending on the cursor drawing mode selected. The accepted call formats are:
GrMouseSetCursorMode(M_CUR_NORMAL); GrMouseSetCursorMode(M_CUR_RUBBER,xanchor,yanchor,GrColor); GrMouseSetCursorMode(M_CUR_LINE,xanchor,yanchor,GrColor); GrMouseSetCursorMode(M_CUR_BOX,dx1,dy1,dx2,dy2,GrColor);
The anchor parameters for the rubberband and rubberline modes specify a fixed screen location to which the other corner of the primitive is bound. The 'dx1' through 'dy2' parameters define the offsets of the corners of the dragged box from the hotpoint of the mouse cursor. The color value passed is always XOR-ed to the screen, i.e. if an application wants the rubberband to appear in a given color on a given background then it has to pass the XOR of these two colors to 'GrMouseSetCursorMode'.
The 'GrMouseGetEvent' function is used to obtain the next mouse or keyboard event. It takes a flag with various bits encoding the type of event needed. It returns the event in a 'GrMouseEvent' structure. The relevant declarations from "grx20.h":
void GrMouseGetEvent(int flags,GrMouseEvent *event);
typedef struct _GR_mouseEvent { /* mouse event buffer structure */ int flags; /* event type flags (see above) */ int x,y; /* mouse coordinates */ int buttons; /* mouse button state */ int key; /* key code from keyboard */ int kbstat; /* keybd status (ALT, CTRL, etc..) */ long dtime; /* time since last event (msec) */ } GrMouseEvent;
The event structure has been extended with a keyboard status word (thus a program can check for combinations like ALT-<left mousebutton press>) and a time stamp which can be used to check for double clicks, etc... The following macros have been defined in "grx20.h" to help in creating the control flag for 'GrMouseGetEvent' and decoding the various bits in the event structure:
#define GR_M_MOTION 0x001 /* mouse event flag bits */ #define GR_M_LEFT_DOWN 0x002 #define GR_M_LEFT_UP 0x004 #define GR_M_RIGHT_DOWN 0x008 #define GR_M_RIGHT_UP 0x010 #define GR_M_MIDDLE_DOWN 0x020 #define GR_M_MIDDLE_UP 0x040 #define GR_M_BUTTON_DOWN (GR_M_LEFT_DOWN | GR_M_MIDDLE_DOWN | \ GR_M_RIGHT_DOWN) #define GR_M_BUTTON_UP (GR_M_LEFT_UP | GR_M_MIDDLE_UP | \ GR_M_RIGHT_UP) #define GR_M_BUTTON_CHANGE (GR_M_BUTTON_UP | GR_M_BUTTON_DOWN )
#define GR_M_LEFT 1 /* mouse button index bits */ #define GR_M_RIGHT 2 #define GR_M_MIDDLE 4
#define GR_M_KEYPRESS 0x080 /* other event flag bits */ #define GR_M_POLL 0x100 #define GR_M_NOPAINT 0x200 #define GR_M_EVENT (GR_M_MOTION | GR_M_KEYPRESS | \ GR_M_BUTTON_DOWN | GR_M_BUTTON_UP)
'GrMouseGetEvent' will display the mouse cursor if it was previously erased and the 'GR_M_NOPAINT' bit is not set in the flag passed to it. In this case it will also erase the cursor after an event has been obtained.
'GrMouseGetEvent' block until a event is produced, except if the 'GR_M_POLL' bit is set in the falg passed to it.
Another version of GetEvent:
void GrMouseGetEventT(int flags,GrMouseEvent *event,long timout_msecs);
can be istructed to wait timout_msec for the presence of an event. Note that event->dtime is only valid if any event occured (event->flags !=0) otherwise it's set as -1. Additionally event timing is real world time even in X11 && Linux.
If there are one or more events waiting the function:
int GrMousePendingEvent(void);
returns non-zero value.
The generation of mouse and keyboard events can be individually enabled or disabled (by passing a non-zero or zero, respectively, value in the corresponding 'enable_XX' parameter) by calling:
void MouseEventEnable(int enable_kb,int enable_ms);
Note that 'GrMouseInit' set both by default.