DataMuseum.dk

Presents historical artifacts from the history of:

RegneCentralen RC759 "Piccoline"

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about RegneCentralen RC759 "Piccoline"

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download

⟦361e2d5dd⟧ TextFile

    Length: 25728 (0x6480)
    Types: TextFile
    Names: »XFORM.C«

Derivation

└─⟦33b70227c⟧ Bits:30003931/GEM_Develop_disk_3_CDOS.imd Disketter indleveret af Steffen Jensen (Piccolo/Piccoline)
    └─⟦this⟧ »XFORM.C« 
└─⟦f18477172⟧ Bits:30003931/GEM_Develop_disk_1_CDOS.imd Disketter indleveret af Steffen Jensen (Piccolo/Piccoline)
    └─⟦this⟧ »SAMP\XFORM.C« 

TextFile

/************************************************************************/
/*	File:	xform.c							*/
/************************************************************************/
/*									*/
/*			  +--------------------------+			*/
/*			  ø Digital Research, Inc.   ø			*/
/*			  ø 60 Garden Court	     ø			*/
/*			  ø Monterey, CA.     93940  ø			*/
/*			  +--------------------------+			*/
/*									*/
/*   The  source code  contained in  this listing is a non-copyrighted	*/
/*   work which  can be  freely used.  In applications of  this source	*/
/*   code you  are requested to  acknowledge Digital Research, Inc. as	*/
/*   the originator of this code.					*/
/*									*/
/*   Author:	Chris Keith, Tom Rolander, Tim Oren			*/
/*   PRODUCT:	GEM Sample Application					*/
/*   Module:	xform,  Version 0.1					*/
/*   Version:	March 28, 1985						*/
/*									*/
/*   Update:	Oct. 1, 1985 for 68K by Lowell Webster			*/
/*									*/ 
/************************************************************************/

#include "portab.h"				/* portable coding conv	*/
#include "machine.h"				/* machine depndnt conv	*/
#include "obdefs.h"				/* object definitions	*/
#include "treeaddr.h"				/* tree address macros	*/
#include "gembind.h"				/* gem binding structs	*/
#include "xform.h"				/* xform apl resource	*/
#include "xlib.h"				/* transformation lib	*/

/* user or page coordinate system is IN_COORDS points per inch, with 	*/
/* (0,0) in the upper left corner.					*/

#define IN_COORDS	1024		/* number of user coordinate points */
					/* per inch */
#define PG_WIDTH	10240		/* 8 x 10 inch page */
#define PG_HEIGHT	8192 

#define	ARROW		0
#define	HOUR_GLASS	2
#define	DESK		0
#define END_UPDATE	0
#define	BEG_UPDATE	1

#define WAIT_OUT	1		/* waiting for mouse to go out */
#define WAIT_IN		0		/* waiting for mouse to go in  */

#define MX_COORDS	256
#define MX_FONTS	4
#define MX_FSIZES	8
/*
\f


Page*/
/*----------------------------------------------------------------------*/
GLOBAL WORD	contrlÆ11Å;		/* control inputs		*/
GLOBAL WORD	intinÆ80Å;		/* max string length		*/
GLOBAL WORD	ptsinÆMX_COORDSÅ;	/* polygon fill points		*/
GLOBAL WORD	intoutÆ45Å;		/* open workstation output	*/
GLOBAL WORD	ptsoutÆ12Å;

GLOBAL WORD	wtype = 0x002d ;	/* window type.			*/
GLOBAL WORD	gl_wchar;		/* character width		*/
GLOBAL WORD	gl_hchar;		/* character height		*/
GLOBAL WORD	gl_wbox;		/* box (cell) width		*/
GLOBAL WORD	gl_hbox;		/* box (cell) height		*/
GLOBAL WORD	gl_hspace;		/* height of space between lines*/
GLOBAL WORD	gem_handle;		/* GEM vdi handle		*/
GLOBAL WORD	vdi_handle;		/* xform vdi handle		*/
GLOBAL WORD	work_outÆ57Å;		/* open virt workstation values	*/
GLOBAL GRECT	scrn_area;		/* whole screen area		*/
GLOBAL GRECT	work_area;		/* drawing area of main window  */
GLOBAL WORD	gl_rmsgÆ8Å;		/* message buffer		*/
GLOBAL LONG	ad_rmsg;		/* LONG pointer to message bfr	*/
GLOBAL LONG	gl_menu;		/* menu tree address		*/
GLOBAL WORD	gl_apid;		/* application ID		*/
GLOBAL WORD	gl_xfull;		/* full window 'x'		*/
GLOBAL WORD	gl_yfull;		/* full window 'y'		*/
GLOBAL WORD	gl_wfull;		/* full window 'w'		*/
GLOBAL WORD	gl_hfull;		/* full window 'h'		*/
GLOBAL WORD	scrn_width;		/* screen width in pixels	*/
GLOBAL WORD	scrn_height;		/* screen height in pixels	*/
GLOBAL WORD	scrn_xsize;		/* width of one pixel		*/
GLOBAL WORD	scrn_ysize;		/* height of one pixel		*/
GLOBAL WORD	ev_which;		/* event multi return state(s)	*/
GLOBAL UWORD	mousex, mousey;		/* mouse x,y position		*/
GLOBAL UWORD	bstate, bclicks;	/* button state, & # of clicks	*/
GLOBAL UWORD	kstate, kreturn;	/* key state and keyboard char	*/
GLOBAL WORD	monumber = 5;		/* mouse form number		*/
GLOBAL LONG	mofaddr = 0x0L;		/* mouse form address		*/
					/* xform window title		*/
GLOBAL BYTE	*wdw_title = " Transform Window ";

GLOBAL WORD	sk_length = 0 ;		/* # of points in xform		*/
GLOBAL WORD	sk_dataÆMX_COORDSÅ;	/* xform data points		*/
GLOBAL WORD	xf_whndl;		/* xform window handle		*/
GLOBAL WORD	cur_fit = FULLITEM ;	/* type of transformation in effect */

GLOBAL WORD	evnts ;			/* for sketch event multi	*/
GLOBAL WORD   	m_out ;

GLOBAL WORD	avail_textÆ MX_FONTSÅÆ MX_FSIZES Å ;
GLOBAL WORD	nfonts ;

/*
\f


Page*/

/*----------------------------------------------------------------------*/
    WORD
min(a, b)			/* return min of two values */
    WORD		a, b;
æ
	return( (a < b) ? a : b );
å



/*----------------------------------------------------------------------*/
    WORD
max(a, b)			/* return max of two values */
    WORD		a, b;
æ
	return( (a > b) ? a : b );
å



/*----------------------------------------------------------------------*/
    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) );
å


/*----------------------------------------------------------------------*/
    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);
å


/*----------------------------------------------------------------------*/
    UWORD
inside(x, y, pt)		/* determine if x,y is in rectangle	*/
    UWORD		x, y;
    GRECT		*pt;
æ
	if ( (x >= pt->g_x) && 
	     (y >= pt->g_y) &&
	     (x < pt->g_x + pt->g_w) && 
	     (y < pt->g_y + pt->g_h) )
		return(TRUE);
	else
		return(FALSE);
å /* inside */



/*----------------------------------------------------------------------*/
    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;
å


/*----------------------------------------------------------------------*/
    VOID
do_open(wh, org_x, org_y, x, y, w, h)	/* grow and open specified wdw	*/
    WORD	wh;
    WORD	org_x, org_y;
    WORD	x, y, w, h;
æ
	graf_growbox(org_x, org_y, 21, 21, x, y, w, h);
	wind_open(wh, x, y, w, h);
å


/*----------------------------------------------------------------------*/
    VOID
do_close(wh, org_x, org_y)	/* close and shrink specified window	*/
    WORD	wh;
    WORD	org_x, org_y;
æ
	WORD	x, y, w, h;

	wind_get(wh, WF_CXYWH, &x, &y, &w, &h);
	wind_close(wh);
	graf_shrinkbox(org_x, org_y, 21, 21, x, y, w, h);
å


/*----------------------------------------------------------------------*/
    VOID
get_work()
æ
	wind_get(xf_whndl, WF_WXYWH,
		&work_area.g_x, &work_area.g_y,
		&work_area.g_w, &work_area.g_h);
å /* get_work*/


/*----------------------------------------------------------------------*/
    VOID
do_full(wh)	/* depending on current window state, either make window*/
    WORD	wh; /*   full size -or- return to previous shrunken size */
æ
	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 now so 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);
	å
	else
	æ					/* is not full so make	*/
		/**/				/*   it 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);
	å
    get_work() ;
    set_xform() ;
å


/*----------------------------------------------------------------------*/
    VOID
set_clip(clip_flag, s_area)	/* set clip to specified area	*/
    WORD	clip_flag;
    GRECT	*s_area;
æ
	WORD	pxyÆ4Å;

	grect_to_array(s_area, pxy);
	vs_clip(vdi_handle, clip_flag, pxy);
å


/*----------------------------------------------------------------------*/
    VOID
draw_rect(area)
    GRECT	*area;
æ
    	WORD	pxyÆ10Å;

    	pxyÆ0Å = area->g_x;
    	pxyÆ1Å = area->g_y;
    	pxyÆ2Å = area->g_x + area->g_w - 1;
    	pxyÆ3Å = area->g_y + area->g_h - 1;
    	pxyÆ4Å = pxyÆ2Å;
    	pxyÆ5Å = pxyÆ3Å;
    	pxyÆ3Å = pxyÆ1Å;
    	pxyÆ6Å = pxyÆ0Å;
    	pxyÆ7Å = pxyÆ5Å;
    	pxyÆ8Å = pxyÆ0Å;
    	pxyÆ9Å = pxyÆ1Å;
    	v_pline(vdi_handle, 5, pxy);
å



/*----------------------------------------------------------------------*/
    VOID
hndl_dial(tree, def, x, y, w, h)
    LONG	tree;
    WORD	def;
    WORD	x, y, w, h;
æ
	WORD	xdial, ydial, wdial, hdial ;

	form_center(tree, &xdial, &ydial, &wdial, &hdial);
	form_dial(0, scrn_width/2, scrn_height/2, 0, 0, xdial, ydial, wdial, hdial);
	form_dial(1, scrn_width/2, scrn_height/2, 0, 0, xdial, ydial, wdial, hdial);
	objc_draw(tree, ROOT, MAX_DEPTH, xdial, ydial, wdial, hdial);
	form_do(tree, def) ;
	form_dial(2, scrn_width/2, scrn_height/2, 0, 0, xdial, ydial, wdial, hdial);
	form_dial(3, scrn_width/2, scrn_height/2, 0, 0, xdial, ydial, wdial, hdial);
å

/*------------------------------*/
/*	string_addr		*/
/*------------------------------*/
LONG
string_addr(which)		/* returns a tedinfo LONG string addr	*/
WORD	which;
æ
	LONG	where;

	rsrc_gaddr(R_STRING, which, &where);
	return (where);
å 

/*
\f


Page*/
/************************************************************************/
/****			    Object Tree Manipulation		     ****/
/************************************************************************/



/*----------------------------------------------------------------------*/
    VOID
do_obj(tree, which, bit)	/* set specified bit in object state	*/
    LONG	tree;
    WORD	which, bit;
æ
	WORD	state;

	state = LWGET(OB_STATE(which));
	LWSET(OB_STATE(which), state ø bit);
å



/*----------------------------------------------------------------------*/
    VOID
undo_obj(tree, which, bit)	/* clear specified bit in object state	*/
    LONG	tree;
    WORD	which, bit;
æ
	WORD	state;

	state = LWGET(OB_STATE(which));
	LWSET(OB_STATE(which), state & übit);
å


/*----------------------------------------------------------------------*/
    VOID
sel_obj(tree, which)		/* turn on selected bit of spcfd object	*/
    LONG	tree;
    WORD	which;
æ
	do_obj(tree, which, SELECTED);
å


/*----------------------------------------------------------------------*/
    VOID
desel_obj(tree, which)		/* turn off selected bit of spcfd object*/
    LONG	tree;
    WORD	which;
æ
	undo_obj(tree, which, SELECTED);
å


/*----------------------------------------------------------------------*/
    VOID
objc_xywh(tree, obj, p)		/* get x,y,w,h for specified object	*/
    LONG	tree;
    WORD	obj;
    GRECT	*p;
æ
	objc_offset(tree, obj, &p->g_x, &p->g_y);
	p->g_w = LWGET(OB_WIDTH(obj));
	p->g_h = LWGET(OB_HEIGHT(obj));
å


/*
\f


Page*/
/************************************************************************/
/****			    Menu Handling			     ****/
/************************************************************************/


/*----------------------------------------------------------------------*/
    VOID
do_about()			/* display xform Info... 	*/
æ
	LONG	tree;
	GRECT	box;

	objc_xywh(gl_menu, DESK, &box);
	rsrc_gaddr(R_TREE, ABOUDIAL, &tree);
	hndl_dial(tree, 0, box.g_x, box.g_y, box.g_w, box.g_h);
	desel_obj(tree, ABOUOK);
å

/*----------------------------------------------------------------------*/
    VOID
do_view()
æ
	LONG	tree;
	GRECT	box;

	objc_xywh(gl_menu, DESK, &box);
	rsrc_gaddr(R_TREE, FITDIAL, &tree);
	sel_obj(tree, cur_fit);
	hndl_dial(tree, 0, box.g_x, box.g_y, box.g_w, box.g_h);
	desel_obj(tree, FITOK);
	for ( cur_fit = FULLITEM ; 
	      (!(LWGET( OB_STATE( cur_fit ) ) & SELECTED) ) ; 
	      cur_fit++ )
	    ;
	set_xform() ;
	set_clip( TRUE, &work_area ) ;
	rdr_mesg() ;
å


/*----------------------------------------------------------------------*/
    WORD
hndl_mnu(title, item)
    WORD 	title, item;
æ
	WORD	done;

	done = FALSE;
	switch (item)
	æ
	case ABOUITEM :
		do_about() ;
		break;
	case QUITITEM :
		done = TRUE;
		break;
	case VIEWITEM :
		do_view() ;
		break ;
	å
	menu_tnormal(gl_menu,title,TRUE);
	return (done);
å




/*
\f


Page*/
/************************************************************************/
/****			    Message Handling			     ****/
/************************************************************************/



/*----------------------------------------------------------------------*/
    VOID
st_curr( wdw_hndl )
    WORD	wdw_hndl ;
æ
    wind_set(wdw_hndl, WF_CXYWH, gl_rmsgÆ4Å,gl_rmsgÆ5Å, gl_rmsgÆ6Å, gl_rmsgÆ7Å);
    get_work() ;
    set_xform() ;
å /* st_curr */


/*----------------------------------------------------------------------*/
    /*MLOCAL*/	
    BOOLEAN
hndl_mesag()
æ
	BOOLEAN	done; 
	WORD	wdw_hndl;

	done = FALSE;
	wdw_hndl = gl_rmsgÆ3Å;
	switch( gl_rmsgÆ0Å )
	æ
	case MN_SELECTED:
		done = hndl_mnu(wdw_hndl, gl_rmsgÆ4Å);
		break;
	case WM_REDRAW:
		do_redraw(wdw_hndl, (GRECT *) &gl_rmsgÆ4Å);
		break;
	case WM_TOPPED:
		wind_set(wdw_hndl, WF_TOP, 0, 0, 0, 0);
		break;
	case WM_FULLED:
		do_full(wdw_hndl);
		break;
	case WM_SIZED:
	case WM_MOVED:
		st_curr( wdw_hndl ) ;
		if ( (cur_fit == SVASITEM) øø (cur_fit == IGASITEM) )
		    rdr_mesg() ;
		break;
	å /* switch */
	return(done);
å /* hndl_mesag */


/*----------------------------------------------------------------------*/
/* display background */
    VOID
background()
æ
    WORD	arrayÆ 16 Å ;

    vsf_perimeter( vdi_handle, FALSE ) ;
    vsf_color( vdi_handle, 0 ) ;
    vsf_style( vdi_handle, 1 ) ;
    grect_to_array( &work_area, array ) ;
    v_bar( vdi_handle, array ) ;
å

/*----------------------------------------------------------------------*/
/* set line attribs for drawing grid and sketch.			*/
    VOID
line_atts()
æ
    vswr_mode( vdi_handle, 1 ) ;
    vsl_width( vdi_handle, 1 ) ;
    vsl_type( vdi_handle, 1 ) ;
    vsl_color( vdi_handle, 1 ) ;
    vsl_ends( vdi_handle, 0, 0 ) ;
å /* line_atts */


/*----------------------------------------------------------------------*/
/* draw a 1 inch square (in user units) grid, and the sketch, if any.	*/
    VOID
do_rdraw()
æ
    WORD	ptsÆ MX_COORDS Å ;
    WORD	i ;
    WORD	end ;

    background() ;
    line_atts() ;
    vsl_type( vdi_handle, 3 ) ;
    ptsÆ 1 Å = x_udy_xform( 0 ) ;
    ptsÆ 3 Å = x_udy_xform( PG_HEIGHT ) ;
    for ( i = 0 ; i <= PG_WIDTH ; i += IN_COORDS )
    æ
	ptsÆ 0 Å = ptsÆ 2 Å = x_udx_xform( i ) ;
	v_pline( vdi_handle, 2, pts ) ;
    å   
    ptsÆ 0 Å = x_udx_xform( 0 ) ;
    ptsÆ 2 Å = x_udx_xform( PG_WIDTH ) ;
    for ( i = 0 ; i <= PG_HEIGHT ; i += IN_COORDS )
    æ
	ptsÆ 1 Å = ptsÆ 3 Å = x_udy_xform( i ) ;
	v_pline( vdi_handle, 2, pts ) ;
    å   
    if (sk_length)
    æ
	vsl_type( vdi_handle, 1 ) ;
	i = 0 ;
	end = sk_length * 2 ;
	while (i < end)
	æ
	    ptsÆ i Å = x_udx_xform( sk_dataÆ i Å ) ;
	    i++ ;
	    ptsÆ i Å = x_udy_xform( sk_dataÆ i Å ) ;
	    i++ ;
	å      
	v_pline( vdi_handle, sk_length, pts ) ;
    å
å /* do_rdraw */



#define MS_LENGTH	8
/*----------------------------------------------------------------------*/
    VOID
rdr_mesg()
æ
    WORD	ms_bufÆ MS_LENGTH Å ;

    ms_bufÆ 0 Å = 20 ;
    ms_bufÆ 1 Å = gl_apid ;
    ms_bufÆ 2 Å = 0 ;
    ms_bufÆ 3 Å = xf_whndl ;
    ms_bufÆ 4 Å = work_area.g_x ;
    ms_bufÆ 5 Å = work_area.g_y ;
    ms_bufÆ 6 Å = work_area.g_w ;
    ms_bufÆ 7 Å = work_area.g_h ;
    appl_write( gl_apid, MS_LENGTH * 2, ADDR( ms_buf ) ) ;
å /* rdr_mesg */


/*----------------------------------------------------------------------*/
do_redraw(wh, area)
    WORD	wh;
    GRECT	*area;
æ
	GRECT	box;

	if (wh != xf_whndl)
	    return(FALSE);
	graf_mouse(M_OFF, 0x0L);

	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(area, &box))
		æ
		    set_clip( TRUE, &box ) ;
		    do_rdraw() ;
		å
		wind_get(wh, WF_NEXTXYWH, &box.g_x, &box.g_y, &box.g_w, &box.g_h);
	å
	graf_mouse(M_ON, 0x0L);
å


/*
\f


Page*/
/************************************************************************/
/****			    transformation procs		     ****/

/*----------------------------------------------------------------------*/
    VOID
full_view( zoom )
    WORD	zoom ;
æ
    WORD	w, h ;
    WORD	x, y ;

    wind_calc( 1, wtype, gl_xfull, gl_yfull, gl_wfull, gl_hfull, 
			 &x,   &y,    &w,   &h ) ;
    x_sxform( 0, 0, PG_WIDTH / zoom, PG_HEIGHT / zoom, x, y, w, h ) ;
å /* full_view */


/*----------------------------------------------------------------------*/
/* set transformation according to current fit and work area.		*/
    VOID
set_xform()
æ
    WORD	w, h ;

    switch( cur_fit )
    æ   
	default :
	case FULLITEM : 			/* page to full size window */
	    full_view( 1 ) ;
	    break ;
	case ZOM2ITEM :
	    full_view( 2 ) ;
	    break ;
	case ZOM3ITEM :
	    full_view( 3 ) ;
	    break ;
	case SVASITEM :			/* page to work area, preserve aspect */
	    w = work_area.g_w ;
	    h = work_area.g_h ;
	        x_saspect( PG_WIDTH, PG_HEIGHT, &w, &h, work_out ) ;   
	        x_sxform( 0, 0, PG_WIDTH, PG_HEIGHT,
			work_area.g_x, work_area.g_y, w, h);
	    rdr_mesg();
	    break ;
	case IGASITEM :			/* page to work area, ignore aspect */
	    x_sxform( 0, 0, PG_WIDTH, PG_HEIGHT,
			work_area.g_x, work_area.g_y, 
			work_area.g_w, work_area.g_h ) ;   
            rdr_mesg() ;
	    break ;
    å
å /* set_xform */

/*
\f


Page*/
/************************************************************************/
/****			    Button Handling			     ****/
/************************************************************************/


/*----------------------------------------------------------------------*/
    WORD
sket_evnt_multi()
æ
    WORD	ev ;

    wind_update(BEG_UPDATE);
    ev = evnt_multi( evnts,
	1, 1, 0,          
	1, mousex-4, mousey-4, 8, 8, 
	m_out,
	(UWORD) work_area.g_x, (UWORD) work_area.g_y,
	(UWORD) work_area.g_w, (UWORD) work_area.g_h,
	ad_rmsg,         		
	0, 0,				
	&mousex, &mousey, &bstate, &kstate,
	&kreturn, &bclicks);
    wind_update(END_UPDATE);
    return( ev ) ;
å /* sket_evnt_multi */


/*----------------------------------------------------------------------*/
/* mouse went in or out of window, change evnt_multi params accordingly. */
/* if outside, don't wait on small mouse movement for portion of sketch. */
    VOID
swap_evnt()
æ
    if (evnts & MU_M1)
    æ
	evnts &= üMU_M1 ;
	m_out = WAIT_IN ;;
    å
    else
    æ
	evnts ø= MU_M1 ;
	m_out = WAIT_OUT ;
    å
å /* swap_evnt */


/*----------------------------------------------------------------------*/
    VOID
setup_sketch()
æ
    line_atts() ;
    vsl_type( vdi_handle, 1 ) ;
    evnts = MU_BUTTON ø MU_M1 ø MU_M2 ;
    m_out = WAIT_OUT ;
    if (sk_length != 0)
    æ
    	sk_length = 0 ;
	do_rdraw() ;
    å
    add_pt() ;
å /* setup_sketch */


/*----------------------------------------------------------------------*/
    VOID
add_pt()  
æ
    WORD	index ;

    sk_length++ ; 
    index = (sk_length - 1) * 2 ;
    sk_dataÆ index Å = mousex ;
    sk_dataÆ index + 1 Å = mousey ;
å /* add_pt */


/*----------------------------------------------------------------------*/
/* transform sketch data into user coordinates.				*/
    VOID
xfm_sketch()
æ
    WORD	i ;
    WORD	end ;

    i = 0 ;
    end = sk_length * 2 ;
    while (i < end)
    æ
	sk_dataÆ i Å = x_dux_xform( sk_dataÆ i Å ) ;
	i++ ;
	sk_dataÆ i Å = x_duy_xform( sk_dataÆ i Å ) ;
	i++ ;
    å      
å /* xfm_sketch */


/*----------------------------------------------------------------------*/
    WORD
hndl_button()
æ
    BOOLEAN  	done = FALSE ;
    BOOLEAN	no_ink = FALSE ;
    WORD	ev_which  ;
    WORD	j ;

    if (!inside(mousex, mousey, &work_area))
	return(FALSE);
    setup_sketch() ;
    graf_mouse(M_OFF, 0x0L);
    while (!done) 
    æ
	ev_which = sket_evnt_multi()  ;  
	if (ev_which & MU_M2)
	    swap_evnt() ;
	else if (ev_which & MU_M1)
	æ
    	    add_pt() ;
	    v_pline( vdi_handle, 2, &sk_dataÆ (sk_length - 2) * 2 Å ) ;
	    done = no_ink = (sk_length * 2 >= MX_COORDS) ;
	å
	if (ev_which & MU_BUTTON)
	    done = TRUE ;
    å
    graf_mouse(M_ON, 0x0L);
    if (no_ink)					/* wait for mouse up - dont */
	evnt_button( 1, 1, 0, &j, &j, &j, &j ) ;/* fall into next sketch */
    xfm_sketch() ;
å /* hndl_button */


/*
\f


Page*/
/************************************************************************/
/****			    xform Event Handler		     ****/
/************************************************************************/


/*----------------------------------------------------------------------*/
xf()
æ
	BOOLEAN	done;

	done = FALSE;
	do
	æ
		wind_update(END_UPDATE);
		ev_which = evnt_multi(MU_BUTTON ø MU_MESAG,
		0x02, 0x01, 0x01, 
		0,
		(UWORD) work_area.g_x, (UWORD) work_area.g_y,
		(UWORD) work_area.g_w, (UWORD) work_area.g_h,
		0, 0, 0, 0, 0,
		ad_rmsg, 0, 0, 
		&mousex, &mousey, &bstate, &kstate,
		&kreturn, &bclicks);
		wind_update(BEG_UPDATE);
		if (ev_which & MU_BUTTON)
		    hndl_button() ;
		if (ev_which & MU_MESAG)
		    done = hndl_message() ;
	å while (!done) ;
å
/*
\f


Page*/
/************************************************************************/
/****			    Termination				     ****/
/************************************************************************/



/*----------------------------------------------------------------------*/
xf_term(term_type)
    WORD	term_type;
æ
	switch (term_type)	/* NOTE: all cases fall through		*/
	æ
		case (0 /* normal termination */):
			do_close(xf_whndl, gl_wfull/2, gl_hfull/2);
			wind_delete(xf_whndl);
		case (3):
			menu_bar(gl_menu, FALSE);
		case (2):
			v_clsvwk( vdi_handle );
		case (1):
			wind_update(END_UPDATE);
			appl_exit();
		case (4):
			break;
	å
å

/*
\f


Page*/
/************************************************************************/
/****			    Initialization			     ****/
/************************************************************************/


/*----------------------------------------------------------------------*/
/* set the full width and height to produce a window with an work area	*/
/* aspect ratio of PG_WIDTH x PG_HEIGHT. Use wind_calc to find the 	*/
/* inside of the	*/
/* maximum window and pass those values to set_aspect (along with the	*/
/* screen attibutes) to calculate new inside window values. Then use	*/
/* wind_calc again to get the outside values of the window for		*/
/* wind_set.								*/
    VOID
ini_full()
æ
    WORD	out_w, out_h ;
    WORD	out_x, out_y ;

    wind_calc( 1, wtype, gl_xfull, gl_yfull, gl_wfull, gl_hfull, 
			 &out_x,   &out_y,    &out_w,   &out_h ) ;
    x_saspect( PG_WIDTH, PG_HEIGHT, &out_w, &out_h, work_out ) ;
    wind_calc( 0, wtype, out_x,     out_y,     out_w,     out_h,
			 &gl_xfull, &gl_yfull, &gl_wfull, &gl_hfull ) ;
å /* ini_full */


/*----------------------------------------------------------------------*/
    WORD
xf_init()
æ
	WORD	work_inÆ11Å;
	WORD	i;

	gl_apid = appl_init();			/* initialize libraries	*/
	if (gl_apid == -1)
		return(4);
	wind_update(BEG_UPDATE);
	graf_mouse(HOUR_GLASS, 0x0L);
	if (!rsrc_load( ADDR("xform.RSC") ))
	æ
		graf_mouse(ARROW, 0x0L);
		form_alert(1,
		ADDR("Æ3ÅÆFatal Error !øxform.RSCøFile Not FoundÅÆ Abort Å"));
		return(1);
	å
	/* open virtual workstation */
	for (i=0; i<10; i++)
	æ
		work_inÆiÅ=1;
	å
	work_inÆ10Å=2;

	gem_handle = graf_handle(&gl_wchar,&gl_hchar,&gl_wbox,&gl_hbox);
	vdi_handle = gem_handle;
	v_opnvwk(work_in,&vdi_handle,work_out);

	if (vdi_handle == 0)
		return(1);

	scrn_width = work_outÆ0Å + 1;
	scrn_height = work_outÆ1Å + 1;
	scrn_xsize = work_outÆ3Å;
	scrn_ysize = work_outÆ4Å;

	scrn_area.g_x = 0;
	scrn_area.g_y = 0;
	scrn_area.g_w = scrn_width;
	scrn_area.g_h = scrn_height;

	ad_rmsg = ADDR((BYTE *) &gl_rmsgÆ0Å);

	wind_get(DESK, WF_WXYWH, &gl_xfull, &gl_yfull, &gl_wfull, &gl_hfull);
	/* initialize menu	*/
	rsrc_gaddr(R_TREE, MAINMENU, &gl_menu);
	/* show menu		*/
	menu_bar(gl_menu, TRUE);	

	ini_full() ;
	xf_whndl = wind_create(wtype, gl_xfull, gl_yfull, gl_wfull, gl_hfull);
	if (xf_whndl == -1)
	æ
		form_alert(1, string_addr(NWINDOW));
		return(3);
	å

	graf_mouse(HOUR_GLASS, 0x0L);
	wind_set(xf_whndl, WF_NAME, ADDR(wdw_title), 0, 0);
	do_open(xf_whndl, gl_wfull/2, gl_hfull/2, gl_xfull,
		gl_yfull, gl_wfull, gl_hfull);
	graf_mouse(ARROW,0x0L);
	get_work() ;
	set_xform() ;
	return(0);
å


/*----------------------------------------------------------------------*/
GEMAIN()
æ
	WORD	term_type;

	if (!(term_type = xf_init()))
		xf();
	xf_term(term_type);
å
«eof»