/*
- Example program fragment in C to demonstrate handling of pane windows
- It should not be used as it stands, but instead should be used as a model
- of what to do.
*/
typedef struct {
int errnum;
char errmess[252];
} os_error;
typedef struct {
int handle, x0,y0,x1,y1,scx,scy, bhandle;
} wimp_openstr;
typedef struct {
int handle, x0,y0,x1,y1,scx,scy, bhandle, flags;
} wimp_wstate;
typedef int wimp_w; /* window handle */
typedef enum {
wimp_ENULL = 0,
wimp_EREDRAW = 1,
wimp_EOPEN = 2,
wimp_ECLOSE = 3,
wimp_EPTRLEAVING = 4,
wimp_EPTRENTERING = 5,
/* etc. */
} wimp_eventcode;
typedef union {
wimp_redrawstr redraw;
wimp_openstr open;
wimp_w close;
wimp_w ptrleaving;
wimp_w ptrentering;
/* etc. */
} wimp_eventstr;
/*
- These functions communicate with the Wimp
- Their specifications should be fairly obvious
*/
extern os_error * wimp_openwindow(wimp_openstr * openblk);
extern os_error * wimp_closewindow(wimp_w handle);
extern os_error * wimp_getwindowstate(wimp_w handle, wimp_wstate * result);
extern os_error * wimp_poll(wimp_eventstr * e, wimp_eventcode * result);
extern void wimp_reporterror(os_error * err, int flags, char * taskname);
/*
- Example Wimp task.
- This is by no means complete - it just deals with the pane window problem
*/
int main(void)
{
os _error * err;
wimp_eventstr event;
wimp_eventcode reason;
/*
- call Wimp_Initialise etc. and create windows
*/
/* simplified polling loop */
do {
if (err != NULL) wimp_reporterror(err,1,"The task name");
err = wimp_poll(&event, &reason);
if (err == NULL) {
switch(reason) {
/* etc. */
case wimp_EOPEN: err = event_openwindow(&event.open);
break;
case wimp_ECLOSE: err = event_closewindow(event.close);
/* etc. */
}
}
} while (1); /* program exits when message 0 is sent to it */
return(0);
}
/*
- The 'tool' window contains the main scrolling work area
- The 'pane' window sits on top of it, moving wherever the tool window goes
*
- For simplicity, 'tool' = handle of only tool window
- 'pane' = handle of only pane window
*
- The code below should should the basic algorithm.
- Here is a 'plain English' description of why it does what it does:
*
- We want to open the pane window on top of the tool window, using the
- coordinates of where the tool ends up (not necessarily the same as
- where it is asked to open, because of bounding constraints).
*
- Thus we would like to open the tool window first, then read off its
- coordinates and bhandle (using wimp_getwindowstate) and open the pane
- with suitable coordinate modifications.
*
- Unfortunately this results in the pane window typically being redrawn
- continuously as the window is dragged round the screen, since the tool
- is first opened above the pane, and then the pane is opened above the
- tool.
*
- The first check, then, is to open the tool window behind the pane, if
- it turns out that it is to be opened just above it.
*
- The next problem is that since the two windows are 'sliding' over one
- another as they move, it is likely that a small strip of the tool
- window next to the pane window will have to be redrawn quite often, as
- it is slightly obscured by the pane window before reappearing as the
- pane window's position is updated.
*
- The cure for this is to open the pane window first if the tool window
- is moving in the direction of the pane. This eliminates unnecessary
- redraws of the tool window, which can be extremely important if the
- contents of the tool window are complicated. Note that since the
- final coordinates of the tool window are not known for sure until
- after it has been opened itself, it is still necessary to open the
- pane window after the tool window has been opened (but this does not
- usually cause any overhead at all).
*
- Finally, an extra check has to be made for the case where the tool
- window is 'sent to the back', since the bhandle setting here is equal
- to -2, rather than to the handle of the rearmost window on the
- screen. Thus, when the pane window is opened after the tool window,
- it must not use the bhandle of -2, since this would cause it to be
- opened behind the tool window! The solution is to read back the
- actual bhandle of the tool window by calling wimp_getwindowstate.
*/
/* Note: the following routine does not check all error cases, in the
- interests of clarity - but any 'proper' program should check for errors
- correctly.
*/
os_error * event_openwindow(wimp_openstr * open)
{
wimp_wstate panestate;
wimp_wstate toolstate;
if (open->handle == tool) {
wimp_getwindowstate(pane, &panestate);
if (panestate.bhandle == open->bhandle) open->bhandle = pane;
wimp_getwindowstate(tool, &toolstate);
if (open->y1 > toolstate.y1) openpane(open, pane); /* open pane first */
wimp_openwindow(open); /* coords written back into block */
if (open->bhandle == -2) {
wimp_getwindowstate(tool, &toolstate); /* sent to the back */
open->bhandle = toolstate.bhandle;
}
return(openpane(open)); /* open pane again */
} else {
return(wimp_openwindow(open)); /* normal window */
}
}
/*
- This code opens a pane window at the top of a tool window
- It is sometimes called twice when opening a pane, to make sure that the
- coords are correct.
*/
os_error * openpane(wimp_openstr *open, wimp_w panehandle)
{
wimp_openstr o;
o.handle = panehandle;
o.x0 = open->x0;
o.y0 = open->y1 - 100; /* assume pane window height = 100 OS units */
o.x1 = open->x1;
o.y1 = open->y1;
o.scx = open->scx; /* scroll sideways in step with tool window */
o.scy = 0; /* don't scroll vertically! */
o.bhandle = open->bhandle;
return(wimp_openwindow(&o));
}
os_error * event_closewindow(wimp_w handle)
{
if (handle == tool) wimp_closewindow(pane); /* close pane as well */
return(wimp_closewindow(handle));
}