home *** CD-ROM | disk | FTP | other *** search
/ Archive Magazine 1996 / ARCHIVE_96.iso / discs / mag_discs / volume_8 / issue_06 / risc_os / cpane < prev    next >
Text File  |  1988-12-14  |  6KB  |  196 lines

  1. /*
  2.  * Example program fragment in C to demonstrate handling of pane windows
  3.  * It should not be used as it stands, but instead should be used as a model
  4.  * of what to do.
  5.  */
  6.  
  7. typedef struct {
  8.   int errnum;
  9.   char errmess[252];
  10. } os_error;
  11.  
  12. typedef struct {
  13.   int handle, x0,y0,x1,y1,scx,scy, bhandle;
  14. } wimp_openstr;
  15.  
  16. typedef struct {
  17.   int handle, x0,y0,x1,y1,scx,scy, bhandle, flags;
  18. } wimp_wstate;
  19.  
  20. typedef int wimp_w;        /* window handle */
  21.  
  22. typedef enum {
  23.   wimp_ENULL = 0,
  24.   wimp_EREDRAW = 1,
  25.   wimp_EOPEN = 2,
  26.   wimp_ECLOSE = 3,
  27.   wimp_EPTRLEAVING = 4,
  28.   wimp_EPTRENTERING = 5,
  29.   /* etc. */
  30. } wimp_eventcode;
  31.  
  32. typedef union {
  33.   wimp_redrawstr redraw;
  34.   wimp_openstr open;
  35.   wimp_w close;
  36.   wimp_w ptrleaving;
  37.   wimp_w ptrentering;
  38.  /* etc. */
  39. } wimp_eventstr;
  40.  
  41. /*
  42.  * These functions communicate with the Wimp
  43.  * Their specifications should be fairly obvious
  44.  */
  45.  
  46. extern os_error * wimp_openwindow(wimp_openstr * openblk);
  47. extern os_error * wimp_closewindow(wimp_w handle);
  48. extern os_error * wimp_getwindowstate(wimp_w handle, wimp_wstate * result);
  49. extern os_error * wimp_poll(wimp_eventstr * e, wimp_eventcode * result);
  50. extern void wimp_reporterror(os_error * err, int flags, char * taskname);
  51.  
  52. /*
  53.  * Example Wimp task.
  54.  * This is by no means complete - it just deals with the pane window problem
  55.  */
  56.  
  57. int main(void)
  58. {
  59.   os _error * err;
  60.   wimp_eventstr event;
  61.   wimp_eventcode reason;
  62.  
  63.   /*
  64.    * call Wimp_Initialise etc. and create windows
  65.    */
  66.  
  67.   /* simplified polling loop */
  68.  
  69.   do {
  70.     if (err != NULL) wimp_reporterror(err,1,"The task name");
  71.     err = wimp_poll(&event, &reason);
  72.  
  73.     if (err == NULL) {
  74.       switch(reason) {
  75.  
  76.         /*  etc. */
  77.  
  78.         case wimp_EOPEN: err = event_openwindow(&event.open);
  79.                                  break;
  80.  
  81.         case wimp_ECLOSE: err = event_closewindow(event.close);
  82.  
  83.         /*  etc. */
  84.       }
  85.     }
  86.   } while (1);    /* program exits when message 0 is sent to it */
  87.  
  88.   return(0);
  89. }
  90.  
  91.  
  92. /*
  93.  * The 'tool' window contains the main scrolling work area
  94.  * The 'pane' window sits on top of it, moving wherever the tool window goes
  95.  *
  96.  * For simplicity, 'tool' = handle of only tool window
  97.  *                 'pane' = handle of only pane window
  98.  *
  99.  * The code below should should the basic algorithm.
  100.  * Here is a 'plain English' description of why it does what it does:
  101.  *
  102.  *    We want to open the pane window on top of the tool window, using the
  103.  *    coordinates of where the tool ends up (not necessarily the same as
  104.  *    where it is asked to open, because of bounding constraints).
  105.  *
  106.  *    Thus we would like to open the tool window first, then read off its
  107.  *    coordinates and bhandle (using wimp_getwindowstate) and open the pane
  108.  *    with suitable coordinate modifications.
  109.  *
  110.  *    Unfortunately this results in the pane window typically being redrawn
  111.  *    continuously as the window is dragged round the screen, since the tool
  112.  *    is first opened above the pane, and then the pane is opened above the
  113.  *    tool.
  114.  *
  115.  *    The first check, then, is to open the tool window behind the pane, if
  116.  *    it turns out that it is to be opened just above it.
  117.  *
  118.  *    The next problem is that since the two windows are 'sliding' over one
  119.  *    another as they move, it is likely that a small strip of the tool
  120.  *    window next to the pane window will have to be redrawn quite often, as
  121.  *    it is slightly obscured by the pane window before reappearing as the
  122.  *    pane window's position is updated.
  123.  *
  124.  *    The cure for this is to open the pane window first if the tool window
  125.  *    is moving in the direction of the pane.  This eliminates unnecessary
  126.  *    redraws of the tool window, which can be extremely important if the
  127.  *    contents of the tool window are complicated.  Note that since the
  128.  *    final coordinates of the tool window are not known for sure until
  129.  *    after it has been opened itself, it is still necessary to open the
  130.  *    pane window after the tool window has been opened (but this does not
  131.  *    usually cause any overhead at all).
  132.  *
  133.  *    Finally, an extra check has to be made for the case where the tool
  134.  *    window is 'sent to the back', since the bhandle setting here is equal
  135.  *    to -2, rather than to the handle of the rearmost window on the
  136.  *    screen.  Thus, when the pane window is opened after the tool window,
  137.  *    it must not use the bhandle of -2, since this would cause it to be
  138.  *    opened behind the tool window!  The solution is to read back the
  139.  *    actual bhandle of the tool window by calling wimp_getwindowstate.
  140.  */
  141.  
  142. /* Note: the following routine does not check all error cases, in the
  143.  * interests of clarity - but any 'proper' program should check for errors
  144.  * correctly.
  145.  */
  146.  
  147. os_error * event_openwindow(wimp_openstr * open)
  148. {
  149.   wimp_wstate panestate;
  150.   wimp_wstate toolstate;
  151.  
  152.   if (open->handle == tool) {
  153.     wimp_getwindowstate(pane, &panestate);
  154.     if (panestate.bhandle == open->bhandle) open->bhandle = pane;
  155.     wimp_getwindowstate(tool, &toolstate);
  156.     if (open->y1 > toolstate.y1) openpane(open, pane); /* open pane first */
  157.     wimp_openwindow(open);               /* coords written back into block */
  158.     if (open->bhandle == -2) {
  159.       wimp_getwindowstate(tool, &toolstate);           /* sent to the back */
  160.       open->bhandle = toolstate.bhandle;
  161.     }
  162.     return(openpane(open));                            /* open pane again */
  163.   } else {
  164.     return(wimp_openwindow(open));                     /* normal window */
  165.   }
  166. }
  167.  
  168.  
  169. /*
  170.  * This code opens a pane window at the top of a tool window
  171.  * It is sometimes called twice when opening a pane, to make sure that the
  172.  * coords are correct.
  173.  */
  174.  
  175. os_error * openpane(wimp_openstr *open, wimp_w panehandle)
  176. {
  177.   wimp_openstr o;
  178.  
  179.   o.handle = panehandle;
  180.   o.x0 = open->x0;
  181.   o.y0 = open->y1 - 100;   /* assume pane window height = 100 OS units */
  182.   o.x1 = open->x1;
  183.   o.y1 = open->y1;
  184.   o.scx = open->scx;       /* scroll sideways in step with tool window */
  185.   o.scy = 0;               /* don't scroll vertically! */
  186.   o.bhandle = open->bhandle;
  187.   return(wimp_openwindow(&o));
  188. }
  189.  
  190.  
  191. os_error * event_closewindow(wimp_w handle)
  192. {
  193.   if (handle == tool) wimp_closewindow(pane);  /* close pane as well */
  194.   return(wimp_closewindow(handle));
  195. }
  196.