[net.micro.atari16] Progem 15/16 part 2 of 2

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