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