bammi@cwruecmp.UUCP (08/10/86)
#!/bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #!/bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # wind16.prf # apndx12.prf # gemcl16.dfn.uue # gemcl16.rsc.uue # gemcl16.rsh # This archive created: Sat Aug 9 17:31:43 1986 # By: Jwahar R. Bammi () export PATH; PATH=/bin:$PATH echo shar: extracting "'wind16.prf'" '(16490 characters)' if test -f 'wind16.prf' then echo shar: over-writing existing file "'wind16.prf'" fi sed 's/^X//' << \SHAR_EOF > 'wind16.prf' X.!**************************************************************************** X.! X.! ANTIC PUBLISHING INC., COPYRIGHT 1985. REPRINTED BY PERMISSION. X.! X.! ** Professional GEM ** by Tim Oren X.! X.! Proff File by ST enthusiasts at X.! Case Western Reserve University X.! Cleveland, Ohio X.! uucp : decvax!cwruecmp!bammi X.! csnet: bammi@case X.! arpa : bammi%case@csnet-relay X.! compuserve: 71515,155 X.! X.!**************************************************************************** X.! X.! X.!**************************************************************************** X.! X.! Begin Part 16 X.! X.!**************************************************************************** X.! X.PART XVI Interface Potpourri #1 X.PP XThis issue of ST PRO GEM, number 16 in the series, presents Xcode implementing several user interface techniques: progress Xindicators, rubber boxes, and draggable boxes with mouse sensitive Xtargets. The code also includes some utility routines for Xhandling resources, event calls, and VDI line drawing. X.PP XThe downloads for this column are available on DL3 of the XATARI16 SIG: PCS-58. Note the plural - in addition to the usual C Xsources stored in GMCL16.C, the files GMCL16.RSC, GMCL16.DFN, XGMCL16.H, and GMCL16.RSH are a template resource for building Xprogress boxes. GMCL16.RSC is the resource binary, and GMCL16.H Xis its symbol binding file, to be used with GMCL16.C. The RSH Xfile is a C image of the resource - you would need STCREATE to Xregenerate it. X.PP XGMCL16.DFN is the binary symbol file for the resource. It is Xin the format used by the NEW ST Resource Construction Set. If Xyou are a developer, you should download this new version from DL7 Xof PCS-57. It fixes a number of bugs, and has a much faster user Xinterface. X.SH MAKING PROGRESS. XThe need for feedback in interface designs Xhas been discussed in previous columns. One instance which is Xoften necessary is the so-called progress indicator. A progress Xindicator is used when your application is doing a long operation. XIt shows that the function is continuing satisfactorily, and is Xnot hung in a loop. When possible, it also gives an indication of Xthe fraction of the operation which has been completed. The Xthermometer bars on the Desktop format and copy operations are Xexamples. X.PP XThe sample code shows two types of progress indicator. Both Xare built within the structure of a dialog resource. The first Xtype uses a variable line of text to describe each phase of an Xoperation as it occurs. The rewriting of the text provides action Xon the screen; the fact that it is different each time gives Xreassurance that the program is not hung. The second type of Xindicator is the thermometer bar. This is more useful when the Xoperation is uniform, allowing you to estimate the fraction Xcompleted. Let's look at the code. X.PP XThe routines beg_prog() and end_prog() are common to the two Xtypes. The code is very similar to the standard dialog handling Xprocedure, but is broken into two parts. Beg_prog() assumes that Xthe progress indicator box is defined by a dialog tree named XPROGRESS. Such a tree is provided in GMCL16.RSC. Beg_prog() Xmakes the usual calls to center and draw the box. The rectangle Xcomputed in the centering operation is stored via a GRECT pointer Xpassed in the parameter. This rectangle compensates for the Xoutline around the box, and must be supplied to end_prog() when Xthe operation is complete. X.PP XThe first version of set_prog() in the download implements Xthe changing text progress indicator. It looks in a tree labelled XSTRINGS for the object number which is passed as a parameter. It Xis assumed that this object is a G_STRING. The address of the new Xtext is loaded from the object's ob_spec field. (For those with Xthe new RCS, it would be easy to alter this routine to use free Xstrings. Simply replace the first two lines with: X.sp X.ce Xrsrc_gaddr(R_STRING, strno, &saddr); X.sp Xand supply parameters which are the names of strings in a FRSTR Xbox.) X.PP XOnce the new text is found, the set_text() utility is called Xto update the TEDINFO attached to object PLINE in the PROGRESS Xtree. Set_text() will insert the new text address in te_ptext, Xand the new text length in te_txtlen. Disp_obj() is then used to Xredraw only the rectangle belonging to PLINE. X.PP XPLINE must be defined as a G_BOXTEXT object with a solid Xwhite background, and with the CENTERED attribute set. It must Xextend entirely across the progress box. This guarantees that the Xprevious text will be covered over, and the new text will be Xcentered in the box. X.PP XThe second version of set_prog() implements the thermometer Xbar progress indicator. The PROGRESS tree also includes an object XPROBOX which defines the outline of the thermometer. It is a XG_BOX object with a solid white background, and a one-outside Xborder. The object PROBAR is nested inside it, with the left Xedges matching. PROBAR is also a G_BOX, with a solid red Xbackground and a one-outside border as well. Set_prog() creates Xthe thermometer effect by growing and redrawing PROBAR. X.PP XSet_prog() requires two parameters. Maxc is an estimate of Xthe total duration of the operation, in arbitrary units. Value is Xthe (new) amount completed, in the same units. Set_prog performs Xtwo operations. First, it computes the fraction value/maxc, and Xsets PROBAR to that fraction of the width of PROBOX. Second, it Xcomputes the rectangle which is the difference between the old and Xnew widths of PROBAR, and redraws only that part of the progress Xbox. This prevents an annoying flash on the screen when the Xindicator is updated. X.PP XThese two types of progress indicators have been presented in Xseparate routines for convenience in explanation. You can easily Xcombine them in a single procedure to create an indicator with Xboth effects. X.PP XThe final progress indicator routine is called esc_prog(). XDuring many lengthy operations is desirable to provide an abort Xoption to the user. Esc_prog() lets you do this by polling the Xkeyboard for an escape (ESC) character. A zero timer value is Xused to guarantee an immediate return if no character is found. XCharacters other than escape are ignored. X.PP XEsc_prog() returns TRUE if an abort is requested, and FALSE Xif the operation is to continue. In your application, you can Xeither pair calls to set_prog() and esc_prog(), or recode Xset_prog() to automatically make the abort check. In any case, Xyou should add an information line to the progress box, telling Xthe user how the operation may be halted. X.PP XOf course, this type of progress indicator is not the only Xoption available on the ST. Other ideas such as changing window Xtitles, or displaying a succession of differing icons are equally Xvalid. Sometimes the nature of your application may suggest an Xalternate metaphor. For instance, the progress of recalculating a Xspreadsheet might be indicated by darkening successive columns in Xa miniature image of the sheet. Occasionally, the computing Xoperation is visual itself, and will not require an explicit Xindicator. An example is redisplaying objects in a 2D or X3D drawing program. X.SH BOXED IN. XThe second part of the download implements two Xtypes of user interaction using the mouse. The first creates a X"rubber box" on the screen, that is, a box whose size is Xcontrolled by moving the mouse. This is similar to the AES Xgraf_rubberbox call, but allows the box to move in any direction Xfrom its origin, while the GEM function only allows movement to Xthe lower right. X.PP XThe second technique allows the user to drag the outline of a Xbox around the screen using the mouse. Again, this is similar to Xthe AES graf_dragbox call, but this version is augmented with code Xwhich "hotspots" selectable objects when the mouse and object pass Xover them. These routines are another illustration of the usage Xof the evnt_multi function, and its combination with VDI drawing Xto create new interaction techniques. X.PP XThe "rubber box" subroutine is called fourway_box(). Its Xparameters are the current VDI handle (NOT a window handle!), and Xtwo GRECT pointers. The first GRECT must have its g_x and g_y Xinitialized with the fixed point of the rubber box. The second XGRECT contains an outer bound box for the stretching action. X.PP XFourway_box() begins by setting the VDI drawing mode and Xcolor. The exclusive or, black combination guarantees that Xredrawing a figure twice in the same location will exactly erase Xit. Next, the routine asserts the mouse control flag. This stops Xthe window manager from tracking the mouse, with the effect that Xmenus will not drop down during the operation. X.PP XThe fixed coordinates are saved in the variables ox and oy, Xand an initial mouse reading is obtained with graf_mkstate. At Xthis point, the event loop is entered. X.PP XAt each iteration, the loop finds the upper left most of the Xfixed vertex and the current mouse position, and updates the Xtracking GRECT accordingly. A call to the utility rc_intersect() Xis used to restrict the size of the rubber box to the given Xlimiting rectangle. Note that if you need a lower limit to the Xsize of the rubber box, it can be achieved by adding another GRECT Xpointer "lower" to the parameter list, and using the call X.sp X.ce Xrc_union(lower, rubber); X.sp XThis works because the union operation selects the larger of two Xrectangles if they are nested. X.PP XRub_wait() will be described in detail below. Its returns Xare the new mouse position, and an indication of the current mouse Xbutton state. If the button remains down, the loop continues. XWhen the button is released, the rubber box terminates, since it Xis a "spring-loaded" modal operation. Before ending, Xfourway_box() returns mouse control to the window manager. The Xreturn from the routine is found in the rubber GRECT, and is the Xfinal extent of the box. X.PP XRub_wait() is a utility used by both box techniques. Its Xpurpose is to do one step of the box animation, and wait for a Xmouse movement, or the release of the button. Rub_wait() Xpreserves the state of the screen. X.PP XThe first action is to draw an exclusive or'ed dotted line Xbox at the given rectangle. Next, rub_wait() calls evnt_multi to Xwait for the mouse button to come up, or the mouse to move out of Xa one pixel rectangle. When the event is detected, the same code Xis used to remove the box. A value of TRUE is returned if the Xmouse button is still down; the curious logical construction is Xnecessary since BOTH events could occur at once. X.PP XA short examination of the vdi_xbox() code is also useful. XAfter converting the rectangle to polyline format, the vdi_xline() Xroutine is called. Vdi_xline draws a dotted line, but does not Xuse the VDI line style attribute. This is avoided because the VDI Xhas problems with corner points when drawing styled lines in XOR Xmode. Instead, a selection is made from a set of user defined Xline styles, based on the direction of the stroke, and the Xodd/evenness of the starting horizontal pixel. This assures that Xthe figure will be exactly erasable. X.SH HOT STUFF? XThe drag box routine is more subtle, because care Xis needed to correctly synchronize the movement of the mouse Xcursor and the box, and the highlighting of target objects. The Xparameters vdi_handle and limit are identical to those in Xfourway_box(). The GRECT pointed to by box contains the width and Xheight of the movable box when hot_dragbox() is entered. On exit Xit also contains the last x,y coordinates of the box. The Xvariable tree is a pointer to the root of a resource tree defining Xthe hot spots for the drag operation. Only objects tagged XSELECTABLE are hotspotted. Hot_dragbox() returns the number of Xsuch an object if the box is "dropped" on it, otherwise a NIL is Xreturned. X.PP XInitialization proceeds as above, until the graf_mkstate Xcall. Here is the first potential synchronization problem. If Xthe user moves the mouse very quickly after initiating the drag, Xit may already be outside the box by the time graf_mkstate samples Xthe position. The min/max operations given lock the box onto the Xcursor, no matter where it has strayed. The mouse/box offsets, ox Xand oy, will remain constant for the rest of the operation. X.PP XHover_obj will contain the number of the object which is Xcurrently highlighted. It is initialized to NIL, indicating no Xobject is currently marked. Hot_dragbox() now enters a loop with Xtermination conditions identical to the rubber box. X.PP XThe current desired position of the box is computed by Xsubtracting the box/mouse offset from the current mouse position. XThe rc_constrain() call ensures that the box will not leave the Xbounding rectangle. Note that rc_intersect would not work here - Xit would alter the size of the draggable box, rather than X"nudging" it back into the bounds. X.PP XUpon return from rub_wait(), a number of conditions must be Xchecked to determine the correct object to highlight, if any. XFirst, we must make sure that the mouse is actually within the Xlegal bounds. If not, there may be an ambiguous selection, with Xthe mouse over one object and the box over another. We choose to Xdo nothing in this case, and set hover_obj to NIL. If the mouse Xis in bounds, objc_find looks for a target object. If one exists, Xit must be SELECTABLE, or it is forced to NIL. X.PP X Next the new object, stored in ret_obj, is compared to the Xold highlighted object, in hover_obj. If they are different, a Xswitch must be made. Since either could be NIL, a check is Xnecessary before calling obj_toggle to invert/reinvert the screen Ximage of the object. When the loop is complete, the final Xhover_obj is returned to normal state before its number is Xreturned. X.PP XYou may notice that this method of highlighting objects is Xdifferent from the incremental tree descent and rectangles method Xpresented in column 13. While not as efficient, the objc_find Xtechnique is simpler to code and may be adequate for many uses. XIf your program will make heavy use of the drag box routine, or Xwill have large trees of target objects, you may wish to Xintegrate the incremental hotspotting algorithm with Xhot_dragbox(). This would be simple to do; just use evnt_multi's Xsecond mouse rectangle for the states associated with the hot- Xspotter. The single pixel rectangles would have to remain, in Xorder to maintain the animation effects. X.SH A FEW CHANGES. XThe observant may have noticed that the Xpromised code for popup menus did not make it into this column. XInstead, it will appear in column 18 along with more "graphics Xpotpourri" and feedback replies. The intervening installment, Xnumber 17, will present and document the source code for a Xcomplete IBM/Atari GEM Resource conversion program. This will Xappear concurrently with Mark Skapinker's article on IBM/ST GEM Xconversions in the second issue of START. While this program Xwill be of direct use to only a minority of ST developers, it will Xcontain utility code useful to all, as well as demonstrations of Xdialog handling and the internal structure of resources. X.PP XFinally, you may also notice that the so-called portability Xmacros have disappeared from the download. Indeed, they are gone Xfor good. Since the beginning of this column, the growth of the XST GEM developer community has outstripped that on the PC. It no Xlonger seems appropriate to inconvenience ST developers and Xviolate standard C syntax for the sake of Intel's design flaws. XThose who still need compatibility with the PC may achieve it by Xcompiling under Intel large model, or by writing "sed" scripts to Xtranslate (tree+obj)->ob_spec and the like to their macro Xequivalents. X.! X.! X.!***************************************************************************** X.!* * X.!* End Part 16 * X.!* * X.!***************************************************************************** SHAR_EOF if test 16490 -ne "`wc -c 'wind16.prf'`" then echo shar: error transmitting "'wind16.prf'" '(should have been 16490 characters)' fi echo shar: extracting "'apndx12.prf'" '(10133 characters)' if test -f 'apndx12.prf' then echo shar: over-writing existing file "'apndx12.prf'" fi sed 's/^X//' << \SHAR_EOF > 'apndx12.prf' X.!**************************************************************************** X.! X.! ANTIC PUBLISHING INC., COPYRIGHT 1985. REPRINTED BY PERMISSION. X.! X.! ** Professional GEM ** by Tim Oren X.! X.! Proff File by ST enthusiasts at X.! Case Western Reserve University X.! Cleveland, Ohio X.! uucp : decvax!cwruecmp!bammi X.! csnet: bammi@case X.! arpa : bammi%case@csnet-relay X.! compuserve: 71515,155 X.! X.!**************************************************************************** X.! X.! Begin Appendix XII X.! X.!*************************************************************************** X.! X.! X.AP XII Sample Code for Part XVI X /***** GEMCL16.H *****/ X X#define PROGRESS 0 /* TREE */ X#define PLINE 2 /* OBJECT in TREE #0 */ X#define PROBOX 3 /* OBJECT in TREE #0 */ X#define PROBAR 4 /* OBJECT in TREE #0 */ X#define STRINGS 1 /* TREE */ X#define P1 1 /* OBJECT in TREE #1 */ X#define P2 2 /* OBJECT in TREE #1 */ X#define PN 3 /* OBJECT in TREE #1 */ X.bp X /***** GEMCL16.C ******/ X /* >>>>>>>>>>>>>>>>>>> Progress box setup and cleanup <<<<<<<<<<<<<<<<<<< */ X X/*------------------------------*/ X/* beg_prog */ X/*------------------------------*/ X VOID Xbeg_prog(rect) X GRECT *rect; X { X OBJECT *tree; X WORD xdial, ydial, wdial, hdial; X X rsrc_gaddr(R_TREE, PROGRESS, &tree); X form_center(tree, &rect->g_x, &rect->g_y, &rect->g_w, &rect->g_h); X form_dial(0, 0, 0, 0, 0, rect->g_x, rect->g_y, X rect->g_w, rect->g_h); X objc_draw(tree, ROOT, MAX_DEPTH, rect->g_x, rect->g_y, X rect->g_w, rect->g_h); X } X X/*------------------------------*/ X/* end_prog */ X/*------------------------------*/ X VOID Xend_prog(rect) X GRECT *rect; X { X form_dial(3, 0, 0, 0, 0, rect->g_x, rect->g_y, rect->g_w, rect->g_h); X } X.bp X/* >>>>>>>>>>>>>>>>>>>> Text line progress indicator <<<<<<<<<<<<<<<<<<<<<<< */ X X/*------------------------------*/ X/* set_prog */ X/*------------------------------*/ X VOID Xset_prog(strno) X UWORD strno; X { X OBJECT *tree; X BYTE *saddr; X X rsrc_gaddr(R_TREE, STRINGS, &tree); X saddr = (BYTE *) (tree + strno)->ob_spec; X rsrc_gaddr(R_TREE, PROGRESS, &tree); X set_text(tree, PLINE, saddr); X disp_obj(tree, PLINE); X } X X.bp X/* >>>>>>>>>>>>>>>>>>>> Moving bar progress indicator <<<<<<<<<<<<<<<<<<<<<< */ X X/*------------------------------*/ X/* set_prog */ X/*------------------------------*/ X VOID Xset_prog(value, maxc) X WORD value, maxc; X { X WORD wnew, wold; X OBJECT *tree; X GRECT box; X X rsrc_gaddr(R_TREE, PROGRESS, &tree); X wold = (tree + PROBOX)->ob_width - 1; /* Take border into account */ X wnew = wold + 1; X if (maxc) X wnew = max(1, ((LONG) value * (LONG) wnew) / maxc); X (tree + PROBAR)->ob_width = wnew; X if (value) X { X objc_xywh(tree, PROBAR, &box); X box.g_x += wold; box.g_w -= wold; X objc_draw(tree, ROOT, MAX_DEPTH, box.g_x, box.g_y, X box.g_w, box.g_h); X } X } X.bp X/* >>>>>>>>>>>>>>>>>>>> Progress indicator check for abort <<<<<<<<<<<<<<<< */ X X/*------------------------------*/ X/* esc_prog */ X/*------------------------------*/ X WORD Xesc_prog() X { X WORD which, kr; X WORD mx, my, mb, ks, br; /* Not used, but needed */ X X FOREVER X { X which = evnt_multi(MU_KEYBD | MU_TIMER, X 0, 0, 0, X 0, 0, 0, 0, 0, X 0, 0, 0, 0, 0, X 0L, X 0, 0, /* Zero timer delay */ X &mx, &my, &mb, &ks, &kr, &br); X X if (which & MU_KEYBD) X { X if ((kr & 0xff) == 0x1B) /* ESC? */ X return (TRUE); /* else try again */ X } X else /* if (which & MU_TIMER) */ X return (FALSE); X } X X return (TRUE); /* Keeps lint happy */ X } X X.bp X /* >>>>>>>>>>>>>>>>>>>>>>> Progress subroutines <<<<<<<<<<<<<<<<<<<<<<< */ X X VOID Xset_text(tree, obj, str) X OBJECT *tree; X BYTE *str; X WORD obj; X { X TEDINFO *obspec; X X obspec = (TEDINFO *) (tree + obj)->ob_spec; /* Get TEDINFO address */ X obspec->te_ptext = str; /* Set new text pointer */ X obspec->te_txtlen = strlen(str); /* Set new length */ X } X X VOID Xdisp_obj(tree, obj) X OBJECT *tree; X WORD obj; X { X GRECT box; X X objc_xywh(tree, obj, &box); X objc_draw(tree, ROOT, MAX_DEPTH, box.g_x, box.g_y, X box.g_w, box.g_h); X } X X VOID Xobjc_xywh(tree, obj, p) /* get x,y,w,h for specified object */ X OBJECT *tree; X WORD obj; X GRECT *p; X { X objc_offset(tree, obj, &p->g_x, &p->g_y); X p->g_w = (tree + obj)->ob_width; X p->g_h = (tree + obj)->ob_height; X } X.bp X /* >>>>>>>>>>>>>>>>>>>>>> Box mover examples <<<<<<<<<<<<<<<<<<<<<<<<<< */ X/*------------------------------*/ X/* fourway_box */ X/*------------------------------*/ X VOID Xfourway_box(vdi_handle, rubber, limit) X WORD vdi_handle; X GRECT *rubber, *limit; X { X UWORD ox, oy, mx, my, foo, down; X X vswr_mode(vdi_handle, MD_XOR); /* Set VDI modes for box */ X vsl_color(vdi_handle, BLACK); X wind_update(BEG_MCTRL); /* Capture mouse */ X X ox = rubber->g_x; oy = rubber->g_y; /* Save off input corner */ X graf_mkstate(&mx, &my, &foo, &foo); /* Initialize mouse posn */ X do { X rubber->g_x = min(ox, mx); /* Choose UL corner */ X rubber->g_y = min(oy, my); X rubber->g_w = max(ox, mx) - rubber->g_x + 1; X rubber->g_h = max(oy, my) - rubber->g_y + 1; X rc_intersect(limit, rubber); /* Lock into limit rect */ X down = rub_wait(vdi_handle, rubber, &mx, &my); X } while (down); X X wind_update(END_MCTRL); /* Release mouse to GEM */ X } X.bp X/*------------------------------*/ X/* hot_dragbox */ X/*------------------------------*/ X WORD Xhot_dragbox(vdi_handle, box, limit, tree) X WORD vdi_handle; X GRECT *box, *limit; X OBJECT *tree; X { X UWORD ox, oy, mx, my, foo, down; X WORD hover_obj, ret_obj; X X vswr_mode(vdi_handle, MD_XOR); /* Set VDI modes for box */ X vsl_color(vdi_handle, BLACK); X wind_update(BEG_MCTRL); /* Capture mouse */ X graf_mkstate(&mx, &my, &foo, &foo); /* Initialize mouse posn */ X ox = min(box->g_w, max(0, mx - box->g_x) ); X oy = min(box->g_h, max(0, my - box->g_y) ); X hover_obj = NIL; X X do { X box->g_x = mx - ox; X box->g_y = my - oy; X rc_constrain(limit, box); /* Lock into limit rect */ X X down = rub_wait(vdi_handle, box, &mx, &my); X X if (!inside(mx, my, limit)) X ret_obj = NIL; X else X { X ret_obj = objc_find(tree, ROOT, NIL, mx, my); X if (ret_obj != NIL) X if ( !(SELECTABLE & (tree + ret_obj)->ob_flags) ) X ret_obj = NIL; X } X if (ret_obj != hover_obj) X { X if (hover_obj != NIL) X objc_toggle(tree, hover_obj); X hover_obj = ret_obj; X if (hover_obj != NIL) X objc_toggle(tree, hover_obj); X } X } while (down); X X wind_update(END_MCTRL); /* Release mouse to GEM */ X if (hover_obj != NIL) X objc_toggle(tree, hover_obj); X return (hover_obj); X } X.bp X/*------------------------------*/ X/* rub_wait */ X/*------------------------------*/ X WORD Xrub_wait(vdi_handle, box, mx, my) X WORD vdi_handle; X GRECT *box; X WORD *mx, *my; X { X WORD which, kr; X WORD mb, ks, br; /* Not used, but needed */ X X graf_mouse(M_OFF, 0x0L); X vdi_xbox(vdi_handle, box); /* Draw waiting box */ X graf_mouse(M_ON, 0x0L); X X which = evnt_multi(MU_BUTTON | MU_M1, X 0x01, 0x01, 0x00, /* Wait for button up */ X TRUE, *mx, *my, 1, 1, /* or mouse move */ X 0, 0, 0, 0, 0, X 0L, X 0, 0, X mx, my, &mb, &ks, &kr, &br); X X graf_mouse(M_OFF, 0x0L); X vdi_xbox(vdi_handle, box); /* Take down waiting box */ X graf_mouse(M_ON, 0x0L); X X return (!(which & MU_BUTTON)); /* TRUE if still dragging */ X } X.bp X/* >>>>>>>>>>>>>>>>>>>>>>>> Box Mover Utilities <<<<<<<<<<<<<<<<<<<<<<<<< */ X X VOID Xobjc_toggle(tree, obj) X OBJECT *tree; X WORD obj; X { X WORD state, newstate; X GRECT root, ob_rect; X X objc_xywh(tree, ROOT, &root); X newstate = (tree + obj)->ob_state ^ SELECTED; X objc_change(tree, obj, 0, root.g_x, root.g_y, X root.g_w, root.g_h, newstate, 1); X } X X VOID Xvdi_xbox(vdi_handle, pt) X WORD vdi_handle; X GRECT *pt; X { X WORD pxy[10]; X X vdi_bxpts(pt, pxy); X vdi_xline(vdi_handle, 5, pxy); X } X X.bp X VOID Xvdi_bxpts(pt, pxy) X GRECT *pt; X WORD *pxy; X { X pxy[0] = pt->g_x; X pxy[1] = pt->g_y; X pxy[2] = pt->g_x + pt->g_w - 1; X pxy[3] = pt->g_y; X pxy[4] = pt->g_x + pt->g_w - 1; X pxy[5] = pt->g_y + pt->g_h - 1; X pxy[6] = pt->g_x; X pxy[7] = pt->g_y + pt->g_h - 1; X pxy[8] = pt->g_x; X pxy[9] = pt->g_y; X } X XMLOCAL WORD hztltbl[2] = { 0x5555, 0xaaaa }; XMLOCAL WORD verttbl[4] = { 0x5555, 0xaaaa, 0xaaaa, 0x5555 }; X X VOID Xvdi_xline(vdi_handle, ptscount, ppoints) X WORD vdi_handle, ptscount, *ppoints; X { X WORD *linexy,i; X WORD st; X X for ( i = 1; i < ptscount; i++ ) X { X if ( *ppoints == *(ppoints + 2) ) X { X st = verttbl[( (( *ppoints) & 1) | X ((*(ppoints + 1) & 1 ) << 1))]; X } X else X { X linexy = ( *ppoints < *( ppoints + 2 )) ? X ppoints : ppoints + 2; X st = hztltbl[( *(linexy + 1) & 1)]; X } X X vsl_udsty(vdi_handle, st); X vsl_type(vdi_handle, 7); X v_pline(vdi_handle, 2, ppoints); X ppoints += 2; X } X X vsl_type(vdi_handle, 1); X } X.bp X WORD Xrc_intersect(p1, p2) /* compute intersect of two rectangles */ X GRECT *p1, *p2; X { X WORD tx, ty, tw, th; X X tw = min(p2->g_x + p2->g_w, p1->g_x + p1->g_w); X th = min(p2->g_y + p2->g_h, p1->g_y + p1->g_h); X tx = max(p2->g_x, p1->g_x); X ty = max(p2->g_y, p1->g_y); X p2->g_x = tx; X p2->g_y = ty; X p2->g_w = tw - tx; X p2->g_h = th - ty; X return( (tw > tx) && (th > ty) ); X } X.bp X VOID Xrc_union(p1, p2) X GRECT *p1, *p2; X { X WORD tx, ty, tw, th; X X tw = max(p1->g_x + p1->g_w, p2->g_x + p2->g_w); X th = max(p1->g_y + p1->g_h, p2->g_y + p2->g_h); X tx = min(p1->g_x, p2->g_x); X ty = min(p1->g_y, p2->g_y); X p2->g_x = tx; X p2->g_y = ty; X p2->g_w = tw - tx; X p2->g_h = th - ty; X } X X VOID Xrc_constrain(pc, pt) X GRECT *pc; X GRECT *pt; X { X if (pt->g_x < pc->g_x) X pt->g_x = pc->g_x; X if (pt->g_y < pc->g_y) X pt->g_y = pc->g_y; X if ((pt->g_x + pt->g_w) > (pc->g_x + pc->g_w)) X pt->g_x = (pc->g_x + pc->g_w) - pt->g_w; X if ((pt->g_y + pt->g_h) > (pc->g_y + pc->g_h)) X pt->g_y = (pc->g_y + pc->g_h) - pt->g_h; X } X.bp X BOOLEAN Xinside(x, y, pt) /* determine if x,y is in rectangle */ X UWORD x, y; X GRECT *pt; X { X if ( (x >= pt->g_x) && (y >= pt->g_y) && X (x < pt->g_x + pt->g_w) && (y < pt->g_y + pt->g_h) ) X return(TRUE); X else X return(FALSE); X } /* inside */ X.! X.!**************************************************************************** X.! X.! End Appendix 12 X.! X.!**************************************************************************** SHAR_EOF if test 10133 -ne "`wc -c 'apndx12.prf'`" then echo shar: error transmitting "'apndx12.prf'" '(should have been 10133 characters)' fi echo shar: extracting "'gemcl16.dfn.uue'" '(206 characters)' if test -f 'gemcl16.dfn.uue' then echo shar: over-writing existing file "'gemcl16.dfn.uue'" fi sed 's/^X//' << \SHAR_EOF > 'gemcl16.dfn.uue' Xbegin 666 gemcl16.dfn XM"`````,`4%)/1U)%4U,```(```%03$E.10```````P```5!23T)/6``````$ XM```!4%)/0D%2``````$``P!35%))3D=3`````0$``5`Q```````````"`0`! XF4#(```````````,!``%03@``````````&AH:&AH:&AH:&AH:&AH` X` Xend SHAR_EOF if test 206 -ne "`wc -c 'gemcl16.dfn.uue'`" then echo shar: error transmitting "'gemcl16.dfn.uue'" '(should have been 206 characters)' fi echo shar: extracting "'gemcl16.rsc.uue'" '(558 characters)' if test -f 'gemcl16.rsc.uue' then echo shar: over-writing existing file "'gemcl16.rsc.uue'" fi sed 's/^X//' << \SHAR_EOF > 'gemcl16.rsc.uue' Xbegin 666 gemcl16.rsc XM````H`"$`(0`A````"0`A````7@`"0`"``$```````````&`4V%M<&QE(%!R XM;V=R97-S($)O>`!687)I86)L92!497AT($QI;F4```!0<F]G<F5S<R!%=F5N XM="!/;F4`4')O9W)E<W,@179E;G0@5'=O`%!R;V=R97-S($5V96YT($X````` XM.````$L```!,``,`!@`"$X```/__`!,``?__``$``P`4````$``"$0`````` XM`"D`"``"_____P`<`````````"0`"P`!`!,``0`#_____P`5`````````(0` XM```#`"D``0````0`!``4``````#_$7```P`%`"(``0`#_____P`4`"````#_ XM$7(```````8``?__``$``P`4````$``"$0```````!L`!P`"_____P`<```` XM`````$T``@`!`!(``0`#_____P`<`````````&```@`#`!(``0``_____P`< X8`"```````',``@`%`!(``0```*````$8 X` Xend SHAR_EOF if test 558 -ne "`wc -c 'gemcl16.rsc.uue'`" then echo shar: error transmitting "'gemcl16.rsc.uue'" '(should have been 558 characters)' fi echo shar: extracting "'gemcl16.rsh'" '(1208 characters)' if test -f 'gemcl16.rsh' then echo shar: over-writing existing file "'gemcl16.rsh'" fi sed 's/^X//' << \SHAR_EOF > 'gemcl16.rsh' X#define T0OBJ 0 X#define T1OBJ 5 X#define FREEBB 0 X#define FREEIMG 0 X#define FREESTR 7 X XBYTE *rs_strings[] = { X"Sample Progress Box", X"Variable Text Line", X"", X"", X"Progress Event One", X"Progress Event Two", X"Progress Event N"}; X XLONG rs_frstr[] = { X0}; X XBITBLK rs_bitblk[] = { X0}; X XLONG rs_frimg[] = { X0}; X XICONBLK rs_iconblk[] = { X0}; X XTEDINFO rs_tedinfo[] = { X1L, 2L, 3L, 3, 6, 2, 0x1380, 0x0, -1, 19,1}; X XOBJECT rs_object[] = { X-1, 1, 3, G_BOX, NONE, OUTLINED, 0x21100L, 0,0, 41,8, X2, -1, -1, G_STRING, NONE, NORMAL, 0x0L, 11,1, 19,1, X3, -1, -1, G_TEXT, NONE, NORMAL, 0x0L, 0,3, 41,1, X0, 4, 4, G_BOX, NONE, NORMAL, 0xFF1170L, 3,5, 34,1, X3, -1, -1, G_BOX, LASTOB, NORMAL, 0xFF1172L, 0,0, 6,1, X-1, 1, 3, G_BOX, NONE, OUTLINED, 0x21100L, 0,0, 27,7, X2, -1, -1, G_STRING, NONE, NORMAL, 0x4L, 2,1, 18,1, X3, -1, -1, G_STRING, NONE, NORMAL, 0x5L, 2,3, 18,1, X0, -1, -1, G_STRING, LASTOB, NORMAL, 0x6L, 2,5, 18,1}; X XLONG rs_trindex[] = { X0L, X5L}; X Xstruct foobar { X WORD dummy; X WORD *image; X } rs_imdope[] = { X0}; X X#define NUM_STRINGS 7 X#define NUM_FRSTR 0 X#define NUM_IMAGES 0 X#define NUM_BB 0 X#define NUM_FRIMG 0 X#define NUM_IB 0 X#define NUM_TI 1 X#define NUM_OBS 9 X#define NUM_TREE 2 X XBYTE pname[] = "GMCL16.RSC"; SHAR_EOF if test 1208 -ne "`wc -c 'gemcl16.rsh'`" then echo shar: error transmitting "'gemcl16.rsh'" '(should have been 1208 characters)' fi # End of shell archive exit 0 -- Jwahar R. Bammi Usenet: .....!decvax!cwruecmp!bammi CSnet: bammi@case Arpa: bammi%case@csnet-relay CompuServe: 71515,155