.!****************************************************************************
.! 
.! ANTIC PUBLISHING INC., COPYRIGHT 1985.  REPRINTED BY PERMISSION.
.!
.! ** Professional GEM ** by Tim Oren
.!
.! Proff File by ST enthusiasts at
.! Case Western Reserve University
.! Cleveland, Ohio
.! uucp : decvax!cwruecmp!bammi
.! csnet: bammi@case
.! arpa : bammi%case@csnet-relay
.! compuserve: 71515,155
.!
.!****************************************************************************
.!
.!			Begin Appendix 1
.!
.!***************************************************************************
.!
.!
.AP I Sample Code for Part II
/* >>>>>>>>>>>>>>>>>>>>>>>>> Sample Redraw Code <<<<<<<<<<<<<<<<<<<<<<<<<<< */

VOID
do_redraw(wh, area)		/* wh = window handle from msg[3] */
WORD	wh;		/* area = pointer to redraw rect- */
GRECT	*area;		/*   tangle in msg[4] thru msg[7] */
{
	GRECT	box;
	
	graf_mouse(M_OFF, 0x0L);
	wind_update(BEG_UPDATE);
	
	wind_get(wh, WF_FIRSTXYWH, &box.g_x, &box.g_y, &box.g_w, &box.g_h);
	while ( box.g_w && box.g_h )
	{
		if (rc_intersect(full, &box))	  /* Full is entire screen */
		    if (rc_intersect(area, &box))
		    {
			    if (wh == w1_handle)	  /* Test for window 1 handle */
			    {		  /* AES redraw example	      */
				    objc_draw(w1_tree, ROOT, MAX_DEPTH, box.g_x, 
					      box.g_y, box.g_w, box.g_h);
			    }
			    else if (wh == w2_handle) /* Test for window 2 handle */
			    {		  /* VDI redraw example	      */
				    set_clip(TRUE, &box);
				    /*  Put VDI drawing calls here */
			    }
			    /* add more windows here */
		    }
		wind_get(wh, WF_NEXTXYWH, &box.g_x, &box.g_y, &box.g_w, 
			 &box.g_h);
	}
	
	wind_update(END_UPDATE);
	graf_mouse(M_ON, 0x0L);
}
.bp
/* >>>>>>>>>>>>>>>>>>>>>>>> Utilities used in do_redraw <<<<<<<<<<<<<<<<<<<< */

VOID
set_clip(clip_flag, area)	/* set clip to specified area	*/
WORD	clip_flag;
GRECT	*area;
{
	WORD	pxy[4];
	
	grect_to_array(area, pxy);
	vs_clip(vdi_handle, clip_flag, pxy);
}

VOID
grect_to_array(area, array)	/* convert x,y,w,h to upr lt x,y and	*/
GRECT	*area;		/*		      lwr rt x,y	*/
WORD	*array;
{
	*array++ = area->g_x;
	*array++ = area->g_y;
	*array++ = area->g_x + area->g_w - 1;
	*array = area->g_y + area->g_h - 1;
}

WORD
rc_intersect(p1, p2)		/* compute intersect of two rectangles	*/
GRECT	*p1, *p2;
{
	WORD	tx, ty, tw, th;
	
	tw = min(p2->g_x + p2->g_w, p1->g_x + p1->g_w);
	th = min(p2->g_y + p2->g_h, p1->g_y + p1->g_h);
	tx = max(p2->g_x, p1->g_x);
	ty = max(p2->g_y, p1->g_y);
	p2->g_x = tx;
	p2->g_y = ty;
	p2->g_w = tw - tx;
	p2->g_h = th - ty;
	return( (tw > tx) && (th > ty) );
}
.bp
/* >>>>>>>>>>>>>>>>>>>>>>> "Self-redraw" Utility <<<<<<<<<<<<<<<<<<<<<<<<< */

VOID
send_redraw(wh, p)
WORD	wh;
GRECT	*p;
{
	WORD	msg[8];
	
	msg[0] = WM_REDRAW;		/* Defined in GEMBIND.H	    */
	msg[1] = gl_apid;		/* As returned by appl_init */
	msg[2] = 0;
	msg[3] = wh;			/* Handle of window to redraw */
	msg[4] = p->g_x;
	msg[5] = p->g_y;
	msg[6] = p->g_w;
	msg[7] = p->g_h;
	appl_write(gl_apid, 16, &msg);	/* Use ADDR(msg) for portability */
}
.bp
/* >>>>>>>>>>>>>>>>>>>> Utilities for Window Requests <<<<<<<<<<<<<<<<<< */

VOID
rc_constrain(pc, pt)
GRECT		*pc;
GRECT		*pt;
{
	if (pt->g_x < pc->g_x)
	    pt->g_x = pc->g_x;
	if (pt->g_y < pc->g_y)
	    pt->g_y = pc->g_y;
	if ((pt->g_x + pt->g_w) > (pc->g_x + pc->g_w))
	    pt->g_x = (pc->g_x + pc->g_w) - pt->g_w;
	if ((pt->g_y + pt->g_h) > (pc->g_y + pc->g_h))
	    pt->g_y = (pc->g_y + pc->g_h) - pt->g_h;
}

WORD
align(x,n)		/* Snap position x to an n-bit grid         */ 
WORD 	x, n;   /* Use n = 16 for horizontal word alignment */
{
	x += (n >> 2) - 1;		/* Round and... */
	x = n * (x / n);		/* remove residue */
	return (x);
}	
.bp
/* >>>>>>>>>>>>>>>>>>>>>>> Window full utility <<<<<<<<<<<<<<<<<<<<<<< */

VOID
hndl_full(wh)		/* depending on current window state, make window    */
WORD	wh;	/*   full size -or- return to previous shrunken size */
{		/* graf_ calls are optional special effects.	     */
	GRECT	prev;
	GRECT	curr;
	GRECT	full;
	
	wind_get(wh, WF_CXYWH, &curr.g_x, &curr.g_y, &curr.g_w, &curr.g_h);
	wind_get(wh, WF_PXYWH, &prev.g_x, &prev.g_y, &prev.g_w, &prev.g_h);
	wind_get(wh, WF_FXYWH, &full.g_x, &full.g_y, &full.g_w, &full.g_h);
	if ( rc_equal(&curr, &full) )
	{		/* Is full, change to previous 		*/
		graf_shrinkbox(prev.g_x, prev.g_y, prev.g_w, prev.g_h,
			       full.g_x, full.g_y, full.g_w, full.g_h);
		wind_set(wh, WF_CXYWH, prev.g_x, prev.g_y, prev.g_w, prev.g_h);
		/* put send_redraw here if you need it */
	}
	else
	{		/* is not full, so set to full		*/
		graf_growbox(curr.g_x, curr.g_y, curr.g_w, curr.g_h,
			     full.g_x, full.g_y, full.g_w, full.g_h);
		wind_set(wh, WF_CXYWH, full.g_x, full.g_y, full.g_w, full.g_h);
	}
}

WORD
rc_equal(p1, p2)		/* tests for two rectangles equal	*/
GRECT	*p1, *p2;
{
	if ((p1->g_x != p2->g_x) ||
	    (p1->g_y != p2->g_y) ||
	    (p1->g_w != p2->g_w) ||
	    (p1->g_h != p2->g_h))
	    return(FALSE);
	return(TRUE);
}
.!
.!****************************************************************************
.!
.!			End Appendix 1
.!
.!****************************************************************************
