h37513
s 01295/00000/00000
d D 1.1 83/03/15 21:13:26 tes 1 0
c date and time created 83/03/15 21:13:26 by tes
e
u
4
U
t
T
I 1
/****************************************************************
* cs.c -- the first half of the Control Systems Artist I	*
* driver.							*
*								*
*	copyright (C) Graphic Software Systems, Inc.		*
*		All Rights Reserved				*
****************************************************************/
 
int DEBUG=0;
#include "ratdef.c"
#include "csmit.c"
#include "gdc.c"
#include "ddcom.c"
#include "font.c"
#include "csconst.c"
#include "gksdef.c"
 
#ifdef TEST
/************************ test routines **********************************/
static int ctl[100],pti[100],pto[100],ini[400],ino[900];
 
main()
{
int i,ls,dm;
int col,sca,rot;
float x,y,t,x1,y1;
char st[100];
 
	strcpy(st,"fghijklmnop ###");
 
	DEBUG=0;
	ctl[OPCODE]=OPEN_WORKSTATION;
	ddcsa1();
	ndmktp=3; /* set default marker type */
	ndclrm=1;
 
	for (dm=DMreplace; dm<=DMblank; dm++) {
 
		ctl[OPCODE]=SET_WRITING_MODE;
		ini[1]=dm;
		ddcsa1();
 
		ctl[OPCODE]=CLEAR_WORKSTATION;
		ddcsa1();
 
		for (i=0; i<=255; i++) ini[i+1]=(i+((i >> 4)*sca)) & 0x0F;
		ctl[4]=256;
		ctl[6]=7;
		ctl[7]=7;
		ctl[8]=7;
		ctl[9]=1;
		pti[1]=200;
		pti[2]=200;
		pti[3]=700;
		pti[4]=500;
		ctl[OPCODE]=CELL_ARRAY;
		ddcsa1();
 
		ctl[OPCODE]=CHAR_HEIGHT;
		ctl[2]=1;
		pti[1]=0;
		pti[2]=30;
		ddcsa1();
 
		col=dm-1;
		for (rot=0; rot<3600; rot += 450) {
			ctl[OPCODE]=TEXT_COLOR;
			ini[1]=col;
			ddcsa1();
 
			ctl[OPCODE]=LINE_COLOR;
			ini[1]=col;
			ddcsa1();
 
			ctl[OPCODE]=FILL_COLOR_INDEX;
			ini[1]=col;
			ddcsa1();
 
			ctl[OPCODE]=FILL_INTERIOR_STYLE;
			ini[1]=(col*5) % 4;
			ddcsa1();
 
			ctl[OPCODE]=FILL_STYLE_INDEX;
			ini[1]=(col*11) % FILLPATS + 1;
			ddcsa1();
 
			col=(col<MXCOLOR)?col+1:1;
 
			ctl[OPCODE]=CHAR_UP_VECTOR;
			ini[1]=rot;
			ddcsa1();
 
			ctl[OPCODE]=TEXT;
			ctl[2]=1;
			for (ls=0; st[ls]; ls++) ini[ls+1]=st[ls];
			ctl[4]=ls;
			pti[1]=480;
			pti[2]=360;
			ddcsa1();
 
			sca=20;
			ctl[OPCODE]=LINE;
			ctl[VERTICES_IN]=3;
			pti[1]=480+chDx[ndtxrt]*sca*60/7;
			pti[2]=360-chDy[ndtxrt]*sca*60/7;
			pti[3]=480;
			pti[4]=360;
			pti[5]=480+chDy[ndtxrt]*sca;
			pti[6]=360+chDx[ndtxrt]*sca;
			ddcsa1();
 
 
			ctl[OPCODE]=GDP;
			ctl[6]=BAR;
			ctl[VERTICES_IN]=2;
			pti[1]=rot/6;
			pti[2]=100;
			pti[3]=pti[1]+100;
			pti[4]=150+rot/12;
			ddcsa1();
		}
	sca=ttyin(); /* wait */
	}
	ctl[1]=INQ_CELL_ARRAY;
	ctl[4]=700;
	ctl[6]=25;
	ctl[7]=25;
	pti[1]=470;
	pti[2]=350;
	pti[3]=490;
	pti[4]=470;
	ddcsa1();
	printf("\ncell array: %d,%d\n",ctl[8],ctl[9]);
	for (i=1; i<=700; i++) {
		printf("%3d",ino[i]);
		if (!(i % 25)) printf("\n");
	}	
 
	ctl[OPCODE]=ESCAPE;
	ctl[6]=EXIT_GRAPHICS_MODE;
	ddcsa1();
 
	ctl[OPCODE]=ESCAPE;
	ctl[6]=ERASEEOS;
	ddcsa1();
 
	ctl[OPCODE]=ESCAPE;
	ctl[6]=DIRECT_CURSOR_ADDRESS;
	ini[1]=12;
	ini[2]=40;
	ddcsa1();
 
	ctl[OPCODE]=ESCAPE;
	ctl[6]=OUTPUT_CURSOR_ADDRESSABLE_TEXT;
	strcpy(st,"input some points...");
	for (ls=0; st[ls]; ls++) ini[ls+1]=st[ls];
	ctl[4]=ls;
	ddcsa1();
 
	ctl[OPCODE]=ESCAPE;
	ctl[6]=ENTER_GRAPHICS_MODE;
	ddcsa1();
 
	ctl[OPCODE]=MARKER_SCALE;
	ctl[VERTICES_IN]=1;
	pti[1]=0;
	pti[2]=20;
	ddcsa1();
 
	ctl[OPCODE]=SET_WRITING_MODE;
	ini[1]=DMover;
	ddcsa1();
 
	pti[1]=500;
	pti[2]=400;
	while(1) {
		ctl[OPCODE]=INPUT_LOCATOR;
		ctl[2]=1;
		ini[1]=1;
		ddcsa1();
 
		ctl[OPCODE]=MARKER_TYPE;
		ini[1]=(sca++) % MKTYPES;
		ddcsa1();
 
		ctl[OPCODE]=MARKER;
		ctl[VERTICES_IN]=1;
		pti[3]=pto[1];
		pti[4]=pto[2];
		ddcsa1();
 
		ctl[OPCODE]=LINE;
		ctl[VERTICES_IN]=2;
		ddcsa1();
 
		pti[1]=pto[1];
		pti[2]=pto[2];
	}
}
 
dpr(s,v)
char *s;
int v;
{
	printf("%s:%d(%4x) ",s,v,v);
}
 
dpr2(s,v1,v2)
char *s;
int v1,v2;
{
	printf("%s:[%d]=%d ",s,v1,v2);
}
 
int getctl(i) int i; {
	if (DEBUG) dpr2("getctl",i,ctl[i]);
	return(ctl[i]);
}
 
int getini(i) int i; {
	if (DEBUG) dpr2("getini",i,ini[i]);
	return(ini[i]);
}
 
int getpti(i) int i; {
	if (DEBUG) dpr2("getpti",i,pti[i]);
	return(pti[i]);
}
 
putctl(i,n) int i,n; {
	if (DEBUG) dpr2("putctl",i,n);
	ctl[i]=n;
}
 
putino(i,n) int i,n; {
	if (DEBUG) dpr2("putino",i,n);
	ino[i]=n;
}
 
putpto(i,n) int i,n; {
	if (DEBUG) dpr2("putpto",i,n);
	pto[i]=n;
}
 
/****************************************************************/
#endif
 
ddcsa1(/*ctl[],ini[],pti[],ino[],pto[]*/)
/****************************************************************
* Function:  Device driver for the Control Systems Artist I
*
* Input Parameters:
*	ctl: control array -- accessed with a function
*		n=getctl(j) because of addressing constraints
*	ini: integer input array -- accessed with n=getini(j)
*	pti: point input array -- accessed with x=getpti(j)
*
* Output Parameters:
*	ctl: on output, accessed with putctl(j,n)
*	ino: integer output array -- accessed with putino(j,n)
*	pto: point output array -- accessed with putpto(j,n)
*
* Routines called:
*	getctl - parameter interface routine; see above
*	getini -- ditto
*	getpti -- ditto
*	putctl -- ditto
*	putino -- ditto
*	putpto -- ditto
*	CSxxxx -- do GKS function xxxx on the CS hardware
*	gimnmx -- constrain an input value between two limits
****************************************************************/
{
int i;
	putctl(3,0);		/* assume no points returned */
	switch (getctl(OPCODE)) {
		case OPEN_WORKSTATION: CSopen(); break;
		case CLOSE_WORKSTATION: /* nothing to close */ break;
		case CLEAR_WORKSTATION: CSclear(); break;
		case UPDATE_WORKSTATION: /* always updated */ break;
		case ESCAPE: CSescape(); break;
		case LINE: CSline(0); break;
		case MARKER: CSmarker(); break;
		case TEXT: CStext(); break;
		case FILL_AREA: CSline(1); break;
		case CELL_ARRAY: CScellArray(); break;
		case GDP: CSgdp(); break;
 
		case CHAR_HEIGHT:
				/* valid text heights are multiples of seven
				   pixels. Find the nearest one, then compute
				   the relevant stuff to send back. Value is
				   stored in 7220 0..15 space. */
				ndtxsz=gimnmx(getpti(2)/7-1,0,15);
				putctl(3,2); /* return two points */
				putpto(1,5*(ndtxsz+1));
				putpto(2,7*(ndtxsz+1));
				putpto(3,6*(ndtxsz+1));
				putpto(4,8*(ndtxsz+1));
				break;
 
		case CHAR_UP_VECTOR:
				/* this next statement takes the text angle
				   (in tenths of degrees) and rounds it into
				   a 0..7 7220 text direction, where 0 is down,
				   2 is right ... */
				ndtxrt=((getini(1)+900)/450) & 0x07;
				putino(1,((ndtxrt-2) & 0x07)*450);
				break;
 
		case COLOR_REPRESENTATION: /* nothing */ break;
 
		case LINE_TYPE:
				ndlntp=getini(1);
				if ((ndlntp<1) || (ndlntp>LNTYPES)) ndlntp=1;
				putino(1,ndlntp);
				break;
 
		case LINE_WIDTH:
				putctl(3,1);
				putpto(1,1);
				putpto(2,0);
				break;
 
		case LINE_COLOR:
				ndclrl=gimnmx(getini(1),0,MXCOLOR);
				putino(1,ndclrl);
				break;
 
		case MARKER_TYPE:
				/* marker type is an index into an array
				   in the CSmarker routine. */
				ndmktp=getini(1);
				if ((ndmktp<1) || (ndmktp>MKTYPES)) ndmktp=3;
				putino(1,ndmktp);
				break;
 
		case MARKER_SCALE:
				/* marker scales are multiples of five
				   pixels. The value stored is the 7220
				   text scale to use when displaying the
				   marker. */
				ndmkht=gimnmx(getpti(2)/5-1,0,15);
				putctl(3,1); /* return actual scale */
				putpto(1,0);
				putpto(2,5*(ndmkht+1));
				break;
 
		case MARKER_COLOR:
				ndclrm=gimnmx(getini(1),0,MXCOLOR);
				putino(1,ndclrm);
				break;
 
		case TEXT_FONT: putino(1,1); break;
 
		case TEXT_COLOR:
				ndclrt=gimnmx(getini(1),0,MXCOLOR);
				putino(1,ndclrt);
				break;
 
		case FILL_INTERIOR_STYLE:
				ndfstl=getini(1);
				if ((ndfstl<HOLLOW) || (ndfstl>HATCH))
					ndfstl=HOLLOW;
				putino(1,ndfstl);
				break;
 
		case FILL_STYLE_INDEX:
				ndflpt=getini(1);
				if ((ndflpt<1) || (ndflpt>FILLPATS)) ndflpt=1;
				putino(1,ndflpt);
				break;
 
		case FILL_COLOR_INDEX:
				ndclrf=gimnmx(getini(1),0,MXCOLOR);
				putino(1,ndclrf);
				break;
 
		case INQ_COLOR_REPRESENTATION:
				i=getini(1);
				if ((i<0) || (i>MXCOLOR)) putpto(1,-1);
				else {
					putpto(1,i);
					putpto(2,redMap[i]);
					putpto(3,greenMap[i]);
					putpto(4,blueMap[i]);
				}
				break;
		case INQ_CELL_ARRAY: CSinqCellArray(); break;
		case INPUT_LOCATOR: CSlocator(); break;
		case INPUT_VALUATOR: /* can't do it */ break;
		case INPUT_CHOICE: CSchoice(); break;
		case INPUT_STRING: CSstring(); break;
		case SET_WRITING_MODE:
				ndwrmd=getini(1);
				if ((ndwrmd<DMreplace) || (ndwrmd>DMblank))
					ndwrmd=DMreplace;
				putino(1,ndwrmd);
				break;
 
		case SET_INPUT_MODE:
				/* only one mode avaliable */
				putino (0, REQUEST);
				break;
	}
}
 
CSescape()
/****************************************************************
* Function: Execute escape codes for the CS
*
* Input Parameters:
*	ctl: control array
*
* Input Globals:
*	alpharow, alphacol -- location of alpha cursor
*
* Output Globals:
*	alpharow, alphacol -- location of alpha cursor
*
* Routines called:
*	putino -- output integer parameter
*	ttysot -- output string to tty
*	ttyout -- output character to tty
*	gimnmx -- bounds check
****************************************************************/
{
int i,k;
char c;
 
static char curup[]  = { ESC, BIGA };
static char curdwn[] = { ESC, BIGB };
static char currgt[] = { ESC, BIGC };
static char curlft[] = { ESC, BIGD };
static char curhom[] = { ESC, BIGH };
static char erscrn[] = { ESC, BIGJ };
static char erslin[] = { ESC, BIGK };
static char poscur[] = { ESC, BIGY };
static char revon[]  = { ESC, LETB, ACCENT, ESC ,LETC, LETG };
static char revoff[] = { ESC, LETB, LETG, ESC, LETC, ACCENT };
 
	switch (getctl(6)) {
		case INQ_ADDRESSABLE_CELLS:
			putino(1,24);		/* 24 rows */
			putino(2,80);		/* 80 cols */
			break;
 
		case EXIT_GRAPHICS_MODE:
			ttysot(2,curhom);	/* home alpha cursor */
 
			alpharow = 1;
			alphacol = 1;
			break;
 
		case ENTER_GRAPHICS_MODE:
			break;
 
		case CURSOR_UP:
			alpharow = gimnmx (++alpharow, 1, 24);
			ttysot (2, curup);
			break;
 
		case CURSOR_DOWN:
			alpharow = gimnmx (--alpharow, 1, 24);
			ttysot (2, curdwn);
			break;
 
		case CURSOR_RIGHT:
			alphacol = gimnmx (++alphacol, 1, 80);
			ttysot (2, currgt);
			break;
 
		case CURSOR_LEFT:
			alphacol = gimnmx (--alphacol, 1, 80);
			ttysot (2, curlft);
			break;
 
		case HOME_CURSOR:
			ttysot (2, curhom);
			alpharow = 1;
			alphacol = 1;
			break;
 
		case ERASEEOS:
			ttysot (2, erslin);
			if (alpharow <= 23) { /* not at bottom of screen yet */
				ttysot (2, poscur); /* position cursor at.. */
				ttyout (alpharow + 31); /* start of line */
				ttyout (BLANK); /* (1 + 31) */
				for (i=alpharow+1; i<=24; i++) {
					ttysot (2, curdwn); /* move down */
					ttysot (2, erslin); /* erase to EOL */
				}
				ttysot (2, poscur); /* move back to ... */
				ttyout (alpharow + 31); /* original location */
				ttyout (alphacol + 31);
			}
			break;
 
		case ERASEEOL:
			ttysot (2, erslin);
			break;
 
		case DIRECT_CURSOR_ADDRESS:
			ttysot (2, poscur);
			i = gimnmx (getini (1), 1, 24);  /* set the row */
			alpharow = i;
			ttyout (i+31);
			i = gimnmx (getini (2), 1, 80);  /* set the column */
			alphacol = i;
			ttyout (i+31);
			break;
 
		case OUTPUT_CURSOR_ADDRESSABLE_TEXT:
			k = getctl (4);  /* get character count */
			for (i=1; i<=k; i++) {
				c = getini (i);
				ttyout (c); /* ttyout takes char parameters */
			}
			break;
 
		case REV_ON:
			ttysot (6, revon);
			break;
 
		case REV_OFF:
			ttysot (6, revoff);
			break;
 
		case INQ_CURRENT_CURSOR_ADDRESS:
			putino (1, alpharow);
			putino (2, alphacol);
			break;
 
		case INQ_TABLET_STATUS:
			putino(1,0);
			break;
	}
}
 
CSgdp()
/****************************************************************
* Function: Execute Generalized Drawing Primitives for the CS
*
* Input Parameters:
*	ctl: control array
*
* Routines called:
*	(to be defined)
****************************************************************/
{
	switch (getctl(6)) {
		case BAR: CSbar(); break;
		case ARC: /* can't do function */ break;
		case PIE_SLICE: /* nope */ break;
		case CIRCLE: /* nada */ break;
		case PRINT_GRAPHIC_CHARACTERS: /* sorry */ break;
	}
}
 
CSbar()
/****************************************************************
* Function: Display a rectangle, with the 7220
*
* Input Parameters:
*	pti[1..4]: the corners of the rectangle, device coord.
*
* Input Globals:
*	ndfstl: one of HOLLOW, SOLID, PATTERN, HATCH.
*	ndflpt: which pattern to use.
*	ndclrf: the color to display in.
*	ndwrmd: the way to put pixels up -- DMreplace ... DMxor
*
* Output Parameters:
*	none
*
* Routines Called:
*	drawRect -- put up a rectangle
****************************************************************/
{
int loX,loY,hiX,hiY,t;
	loX=getpti(1);
	loY=MAXY-getpti(2); /* 7220 Y coordinates reversed */
	hiX=getpti(3);
	hiY=MAXY-getpti(4);
	if (loX>hiX) {t=hiX; hiX=loX; loX=t;}
	if (loY>hiY) {t=hiY; hiY=loY; loY=t;}
	if (ndfstl == HOLLOW) {
		/* set linestyle */
		putList((PARAMC | 8),2,&lineStyles[0]);
		lineDraw(loX,loY,loX,hiY,ndclrf,ndwrmd);
		lineDraw(loX,hiY,hiX,hiY,ndclrf,ndwrmd);
		lineDraw(hiX,hiY,hiX,loY,ndclrf,ndwrmd);
		lineDraw(hiX,loY,loX,loY,ndclrf,ndwrmd);
	}
	else {
		drawRect(loX,loY,hiX,hiY,ndfstl,ndflpt,ndclrf,ndwrmd);
	}
}
 
CSopen()
/****************************************************************
* Function: open workstation.  The configuration constants were
*	invented for the Mitsubishi hi-res monitor.
*
* Input Parameters:
*	csmit.c -- Mitsubishi monitor setup parameters
*	ctl array -- nothing important
*
* Output Parameters:
*	ctl array -- lengths of parameters
*	ino array -- lots of good stuff about device
*	pto array -- more goodies
*
* Routines Called:
*	putCmd -- send command to 7220
*	putParam -- send parameter byte
*	putConfig -- send byte to board (who knows where)
****************************************************************/
{
int i,word;
int *ip;
 
	/* initialize global state variables */
	ndclrf=gimnmx(getini(10),0,MXCOLOR);	/* current fill area color */
	ndclrl=gimnmx(getini(3),0,MXCOLOR);	/* current line color */
	ndclrm=gimnmx(getini(5),0,MXCOLOR);	/* current marker color */
	ndclrt=gimnmx(getini(7),0,MXCOLOR);	/* current text color */
	ndflpt=1;				/* fill area pattern */
	ndfstl=gimnmx(getini(8),0,3);		/* fill interior style */
	ndlntp=gimnmx(getini(12),1,LNTYPES);	/* line type (style) */
	ndmktp=gimnmx(getini(4),1,MKTYPES);	/* marker type (style) */
	ndmkht=0;		/* current marker height 0..15, 7220 style */
	ndtxrt=2;		/* current text rotation 0..7, 7220 style */
	ndtxsz=0;		/* current text size -- 0..15, 7220 style */
	ndwrmd=DMreplace;	/* current writing mode */
 
	/* set up hardware on the CS board */
	putConfig(0);
 
	/* reset 7220 */
	putCmd(RESETC);
 
	/* blank display */
	putCmd(BCTRLC);
 
	/* set up sync mode */
	putCmd(SYNCC);
	putParam(GRAFMODE | LACEMODE | DRAWRETRACE | DYNAMIC);
	putParam(PTCH-2);	/* 7220 needs active words per line - 2 */
	putParam(((VS << 5) & 0xE0) | ((HS-1) & 0x1F));
	putParam((((HFP-1) << 2) & 0xFC) | ((VS >> 3) & 0x03));
	putParam((HBP-1) & 0x3F);
	putParam(VFP & 0x3F);
	putParam(AL & 0xFF);
	putParam(((VBP << 2) & 0xFC) | ((AL >> 8) & 0x03));
 
	/* vertical sync mode */
	putCmd(VSYNCC | VSMASTER);
 
	/* zoom parameters */
	putZoom(0xFF);	/* board has (unspecified) zoom parameter */
	putCmd(ZOOMC);
	putParam(0);
 
	/* enable display */
	putCmd(BCTRLC | ENABLE);
 
	/* set parameter RAM (why?) */
	putCmd(PARAMC | 0);
	putParam(0);
	putParam(0);
	putParam((LEN << 4) & 0xF0);
	putParam((LEN >> 4) & 0x3F);
 
	/* set up cursor (why?) */
	moveCursor(0,0,0);
 
	/* set up cursor characteristics (why?) */
	putCmd(CCHARC);
	putParam(0x80);
	putParam(0xE1);
	putParam(0x13);
 
	/* set pitch */
	putCmd(PITCHC);
	putParam(PTCH);
 
	/* initialize figure (why?) */
	putCmd(FIGSC);
	putParam(0);
	putParam(0);
	putParam(0);
 
	/* initialize mask (why?) */
	putCmd(MASKC);
	putParam(0xFF);
	putParam(0xFF);
 
	/* start the 7220 */
	putCmd(STARTC);
 
	/* send parameters back to GSS Kernel */
	putctl(3,6);		/* number of point outputs */
	putctl(5,45);		/* number of integer outputs */
 
	ip=iniino;
	for (i=1; i<=45; i++) putino(i,*ip++); /* send out integer data */
 
	ip=inipto;
	for (i=1; i<=12; i++) putpto(i,*ip++); /* point output data */
 
	ttysot(90,inikeys);	/* initialize function and arrow keys */
}
 
CSclear()
/****************************************************************
* Function: clear the display
*
* Input Parameters:
*	none
*
* Input Globals:
*	none
*
* Output Parameters:
*	none
*
* Routines Called:
*	putCmd -- output a 7220 command byte
*	putParam -- output a 7220 parameter byte
*	moveCursor -- move the 7220 cursor position
****************************************************************/
{
int plane,y;
 
	/* blank display for speed */
	putCmd(BCTRLC);
 
	for (plane=0; plane<=3; plane++) {
		for (y=0; y<=LEN; y=y+200) {
			moveCursor(0,y,plane);
 
			putCmd(FIGSC);
			putParam(FIGCHAR | 2); /* character mode, right */
			putParam((200*PTCH-1) & 0xFF); /* reset 200 lines */
			putParam(((200*PTCH-1) >> 8) & 0xFF);
 
			/* reset all sixteen bits */
			putCmd(MASKC);
			putParam(0xFF);
			putParam(0xFF);
 
			putCmd(WDATC | WORD | RESET);
			putParam(0xFF);
			putParam(0xFF);
		}
	}
	/* re-enable display */
	putCmd(BCTRLC | ENABLE);
}
		
CSline(close)
int close;
/****************************************************************
* Function: draw a polyline on the CS Artist I. Observe line
*	style, line color, drawing mode.
*
* Input Parameters:
*	close -- TRUE if the closing line should also be drawn
*	ctl[2] -- number of points
*	pti[] -- input points
*
* Input Globals:
*	ndclrl -- current line color
*	ndlntp -- current line type (style)
*
* Output Parameters:
*	none
*
* Routines Called:
*	getctl -- get a value from the ctl array
*	getpti -- get a value from the pti array
*	putList -- send a command and parameter list
*	lineDraw -- put a line on the screen
****************************************************************/
{
int i,top;
int x1,x2,y1,y2;
 
	/* set linestyle */
	putList((PARAMC | 8),2,&lineStyles[ndlntp*2-2]);
 
	top=2*getctl(VERTICES_IN)-3;	/* scan thru all coordinate pairs */
	for (i=1; i<=top; i=i+2) {
		x1=getpti(i);
		y1=MAXY-getpti(i+1);	/* invert y for 7220 */
		x2=getpti(i+2);
		y2=MAXY-getpti(i+3);
		lineDraw(x1,y1,x2,y2,ndclrl,ndwrmd);
	}
	if (close) {
		x1=getpti(top+2);
		y1=MAXY-getpti(top+3);	/* invert y for 7220 */
		x2=getpti(1);
		y2=MAXY-getpti(2);
		lineDraw(x1,y1,x2,y2,ndclrl,ndwrmd);
	}
}
 
CSmarker()
/****************************************************************
* Function: output polymarkers on the CS Artist I. Observe marker
*	color, scale, type, drawing mode.
*
* Input Parameters:
*	ctl[2] -- number of markers to display
*	pti[] -- points to place markers
*
* Input Globals:
*	ndclrm -- current marker color
*	ndmktp -- current marker type (1..MKTYPES)
*	ndmkht -- marker height, 0..15 ala 7220
*	ndwrmd -- current writing mode
*
* Output Parameters:
*	none
*
* Routines Called:
*	getctl -- get a value from the ctl array
*	getpti -- get a value from the pti array
*	putCmd -- output a 7220 command byte
*	putParam -- output a 7220 parameter byte
*	charDraw -- do an individual character
****************************************************************/
{
int x,y,dx,dy;
int pt,ptMax;
		   /* describe markers, center offsets */
static char mk[MKTYPES]  = {'.', '+', '*', 'o', 'x'};
static int mkDx[MKTYPES] = { 4,   5,   6,   5,   5 };
static int mkDy[MKTYPES] = { 4,   9,   9,   7,   7 };
 
	putCmd(ZOOMC);  /* set text scale in 7220 */
	putParam(ndmkht);
 
	dx = ((ndmkht+1)*mkDx[ndmktp-1])>>1; /* move marker center to point */
	dy = ((ndmkht+1)*mkDy[ndmktp-1])>>1;
 
	ptMax=getctl(2)*2-1;
	for (pt=1; pt<=ptMax; pt += 2) {
 
		x=getpti(pt);
		y=MAXY-getpti(pt+1);	/* invert y -- 7220 (0,0) is at top */
 
		charDraw(mk[ndmktp-1],x-dx,y+dy,ndclrm,2,ndwrmd);
	}
	putCmd(ZOOMC);  /* set text scale back to normal */
	putParam(0);
}
 
CStext()
/****************************************************************
* Function: output text on the CS Artist I. Observe text color,
*	scale, rotation, drawing mode.
*
* Input Parameters:
*	ctl[2] -- number of characters
*	ini[] -- characters, ADE
*	pti[1..2] -- starting point
*
* Input Globals:
*	ndclrt -- current text color
*	ndtxrt -- current text rotation
*	ndtxsz -- text size, 0..15
*	ndwrmd -- current writing mode
*
* Output Parameters:
*	none
*
* Routines Called:
*	getctl -- get a value from the ctl array
*	getpti -- get a value from the pti array
*	putCmd -- output a 7220 command byte
*	putParam -- output a 7220 parameter byte
*	charDraw -- do an individual character
****************************************************************/
{
int x,y,dx,dy,size,pixel;
int ch,chMax;
 
	if (ndtxrt & 0x01) size=ndtxsz*7/10; /* remove sqr(2) factor from... */
	else		   size=ndtxsz;      /* ... 45 degree text */
	putCmd(ZOOMC);  /* set text scale in 7220 */
	putParam(size);
	pixel=size+1; /* character pixels are this size */
	size=pixel*6; /* number of pixels between characters */
 
	/* find rise and run of text in 7220 space */
	dx=size*chDx[ndtxrt];
	dy=size*chDy[ndtxrt];
 
	x=getpti(1);
	y=MAXY-getpti(2);	/* invert y -- 7220 (0,0) is at top */
 
	x=x-pixel*chDy[ndtxrt];	/* adjust one pixel down for descenders */
	y=y+pixel*chDx[ndtxrt];
 
 
	chMax=getctl(4);
	for (ch=1; ch<=chMax; ch++) {
 
		charDraw(getini(ch),x,y,ndclrt,ndtxrt,ndwrmd);
 
		x += dx;  /* update cursor position */
		y += dy;
	}
	putCmd(ZOOMC);  /* set text scale back to normal */
	putParam(0);
}
 
CScellArray()
/****************************************************************
* Function: present a cell array on the Artist I hardware.
*
* Input Parameters:
*	ctl[4] -- length of color index array
*	ctl[6] -- length of each row in color index array
*	ctl[7] -- number of elements used in each row
*	ctl[8] -- number of rows in color index array
*	ctl[9] -- pixel operation to be performed:
*			0 = clear
*			1 = set
*			2 = or
*			3 = and
*			4 = xor
*	ini[] -- color index array, stored by row
*	pti[1..2] -- lower left corner, device coordinates
*	pti[3..4] -- upper right corner
*
* Input Globals:
*	none
*
* Output Parameters:
*	none
*
* Routines Called:
*	getctl -- get a value from the ctl array
*	getpti -- get a value from the pti array
*	drawRect -- do a rectangle
****************************************************************/
{
int rowInc,colMax,rowMax;
int loX,loY,hiX,hiY;
int mode,dx,dy;
int llX,llY,urX,urY;
int row,col,cell;
	rowInc=getctl(6);
	colMax=getctl(7);
	rowMax=getctl(8);
	loX=getpti(1);
	loY=getpti(2);
	hiX=getpti(3);
	hiY=getpti(4);
	mode=getctl(9);
	dx=hiX-loX;
	dy=hiY-loY;
	urY=MAXY-hiY;	/* adjust for 7220 origin */
	for (row=0; row<rowMax; row++) { /* do rows from top down */
		llY=MAXY-(hiY-(row+1)*dy/rowMax);
		/* don't overlap rectangles */
		if ((row<rowMax-1) && (dy>rowMax)) llY++;
		cell=row*rowInc+1;
		llX=loX;
		for (col=0; col<colMax; col++) {
			urX=(col+1)*dx/colMax+loX;
			if ((col<colMax-1) && (dx>colMax)) urX--;
			/* remember to draw rectangle with the corners
			   correctly identified -- 7220 origin causes Y values
			   to flip */
			drawRect(llX,urY,urX,llY,SOLID,0,getini(cell),mode);
			cell++;
			llX=urX;
		}
		urY=llY;
	}
}
 
CSinqCellArray()
/****************************************************************
* Function: return the contents of a pixel array on the display
*
* Input Parameters:
*	ctl[4] -- length of color index array
*	ctl[6] -- length of each row in color index array
*	ctl[7] -- number of rows in color index array
*	pti[1..2] -- lower left corner, device coordinates
*	pti[3..4] -- upper right corner
*
* Input Globals:
*	none
*
* Output Parameters:
*	ctl[8] -- number of elements used in each row
*	ctl[9] -- number of rows used in color index array
*	ctl[10] -- invalid value flag: 0--> ok, 1--> some invalid
*	ino[] -- color index array, stored by row
*
* Routines Called:
*	getPixel -- determine pixel color inside rectangle
****************************************************************/
{
int arrMax,colMax,rowMax;
int loX,loY,hiX,hiY;
int dx,dy;
int llX,llY,urX,urY;
int row,col,cell;
	arrMax=getctl(4);
	colMax=getctl(6);
	rowMax=getctl(7);
	loX=getpti(1);
	loY=getpti(2);
	hiX=getpti(3);
	hiY=getpti(4);
	dx=hiX-loX;
	dy=hiY-loY;
	urY=MAXY-hiY;	/* adjust for 7220 origin */
	for (row=0; row<rowMax; row++) { /* do rows from top down */
		llY=MAXY-(hiY-(row+1)*dy/rowMax);
		/* don't overlap rectangle coverage */
		if ((row<rowMax-1) && (dy>rowMax)) llY++;
		cell=row*colMax+1;
		llX=loX;
		for (col=0; col<colMax; col++) {
			urX=(col+1)*dx/colMax+loX;
			if ((col<colMax-1) && (dx>colMax)) urX--;
			if (cell>arrMax) break; /* don't exceed bounds */
			putino(cell,ninvmp[getPixel(llX,urY,urX,llY)]);
			cell++;
			llX=urX;
		}
		urY=llY;
	}
	putctl(8,colMax);
	putctl(9,rowMax);
	putctl(10,0); /* no invalid pixels */
}
 
int getPixel(loX,loY,hiX,hiY)
int loX,loY,hiX,hiY;
/****************************************************************
* Function: find an appropriate color for the inside of the
*		named rectamgle
*
* Input Parameters:
*	loX..hiY: the area to explore, in 7220 coordinates
*
* Output Parameters:
*	function value -- the hardware color most commonly seen
*		in the named area
*
* Routines Called:
*	get16 -- get a word from a bit plane
****************************************************************/
{
int x,y,i;
int plane,rot,pixel;
unsigned words[4],get16();
 
	y=(loY+hiY)>>1;
	x=(loX+hiX)>>1;	/* use center of rectangle as representative pixel */
 
	for (plane=0; plane<=3; plane++) words[plane]=get16(x,y,plane);
	pixel=0;
	rot=x & 0x000F;
	for (plane=3; plane>=0; plane--) {
		pixel=(pixel<<1) | ((words[plane]>>rot) & 1);
	}
	return(pixel);
}
 
CSlocator()
/****************************************************************
* Function: do a locator input function
*
* Input Parameters:
*	ini[1] -- locator device number:
*			1 = default
*			2 = crosshair
*			3 = tablet
*			4 = joystick
*			5 = lightpen (some potential here)
*			6 = plotter
*			7 = mouse
*			8 = trackball
*			9 and greater = workstation dependent
*	pti[1..2] -- initial coordinates of cursor, device units
*
* Input Globals:
*	none
*
* Output Parameters:
*	ctl[3] -- number of output vertices = 1
*	ctl[5] -- status: 0-->failed, >0-->ok
*	ino[1] -- terminator (key pressed)
*	pto[1..2] -- point returned
*
* Routines Called:
*	lineDraw -- do a line on the screen
*	gimnmx -- bounds enforcer
*	ttyin -- get a keyboard character
*	ttyinw -- the same, but don't wait for it
****************************************************************/
{
int i,x,y,xold,yold,incr;
int done,xlo,ylo,xhi,yhi;
int c,itemp;
#define UP_ARROW 'A'
#define DOWN_ARROW 'B'
#define RIGHT_ARROW 'C'
#define LEFT_ARROW 'D'
#define CHANGE_RATE 'R'
#define FAST_RATE 10
#define SLOW_RATE 1
	putctl (5, NONE);	/* Initialize status to not successful */
	i = getini (1);		/*  Check locator device for validity */
	if (i != 1 && i != 2) return; /* default or crosshairs only */
 
	x = getpti (1);		/* Get initial point for GIN */
	y = getpti (2);
 
	incr = FAST_RATE;	/* Initialize cursor increment to fast */
 
	done = NO;
	do {
 
		/* determine endpoints of crosshair */
		xlo = gimnmx (x - 100, 0, MAXX);
		ylo = gimnmx (y - 100, 0, MAXY);
		xhi = gimnmx (x + 100, 0, MAXX);
		yhi = gimnmx (y + 100, 0, MAXY);
 
		/* draw crosshair in yellow (5) using xor writing mode */
		putList((PARAMC | 8),2,&lineStyles[0]); /* set solid line */
		lineDraw(xlo,MAXY-y,xhi,MAXY-y,5,DMxor);
		lineDraw(x,MAXY-ylo,x,MAXY-yhi,5,DMxor);
 
		xold = x;	/* save x,y coordinate of cursor */
		yold = y;
 
		ttyin (&c);	/* read a character */
		itemp = c & 0xff;
		if (itemp == ESC) {	/* check for special key */
			ttyinw (&c);	/* get char if one available */
			if (c != -1) itemp = c & 0xff;
		}
 
		switch (itemp) {	/* update status based on keystroke */
 
		case UP_ARROW:
			y += incr;
			break;
 
		case DOWN_ARROW:
			y -= incr;
			break;
 
		case LEFT_ARROW:
			x -= incr;
			break;
 
		case RIGHT_ARROW:
			x += incr;
			break;
 
		case CHANGE_RATE:
			if (incr == FAST_RATE) incr = SLOW_RATE;
			else                   incr = FAST_RATE;
			break;
 
		default:	/* non cursor movement key struck */
			done = YES;
			break;
		}
 
		/* make sure cursor still on screen */
		x = gimnmx (x, 0, MAXX);
		y = gimnmx (y, 0, MAXY);
 
		/* remove cursor at current position */
		putList((PARAMC | 8),2,&lineStyles[0]); /* set solid line */
		lineDraw(xlo,MAXY-yold,xhi,MAXY-yold,5,DMxor);
		lineDraw(xold,MAXY-ylo,xold,MAXY-yhi,5,DMxor);
 
	} while (! done);
 
	putctl (5, 1);          /* Set successful flag  */
	putctl (3, 1);          /* Set the number of output vertices  */
	putpto (1, x);          /* Return the locator point */
	putpto (2, y);
	putino (1, itemp);      /* Return the locator input character */
}
 
CSchoice()
/****************************************************************
* Function: do a choice input function
*
* Input Parameters:
*	ini[1] -- choice device number:
*			1 = default
*			2 = function key
*			3 and greater = workstation dependent
*	ini[2] -- initial choice number
*
* Input Globals:
*	none
*
* Output Parameters:
*	ctl[3] -- number of output vertices = 1
*	ctl[5] -- status: 0-->failed, >0-->ok
*	ino[1] -- choice number
*
* Routines Called:
*	ttyin -- get a keyboard character
*	ttyinw -- the same, but don't wait for it
****************************************************************/
{
int i,itemp;
char c;
	putctl (5, NO);		/* Assume invalid choice */
	putino (1, getini (1));
	ttyin (&c);		/* Get a character */
	itemp = c & 0xff;
	if (itemp == ESC) {	/* Char was function key lead in   */
		ttyinw (&c);	/* Get next char if one available  */
		i = c & 0xff;
		if (i >= LETP && i <= LETY) {	/* Valid function key */
			/* Map p-z to 1-10 */
			putino (1, i - 111);	/* Return value */
			putctl (5, YES);	/* Valid choice */
		}
	}
}
 
CSstring()
/****************************************************************
* Function: do a string input function
*
* Input Parameters:
*	ini[1] -- choice device number:
*			1 = default (keyboard)
*	ini[2] -- maximum string length
*	ini[3] -- echo mode: 0-->don't, 1-->do echo
*
* Input Globals:
*	none
*
* Output Parameters:
*	ctl[3] -- 0
*	ctl[5] -- length of output string, zero if failed
*	ino[] -- returned string, ADE
*
* Routines Called:
*	ttyin -- get a keyboard character
*	ttyout -- put a character onto the IBM monitor
****************************************************************/
{
int i,k,itemp,echo;
char c;
	if (getini (1) != 1) {       /* Check for valid string device */
		putctl (5, 0);
		return;
	}
	i = 0;
	echo = getini(3);
	k = getini (2);				/* Save maximum size */
	do {
		ttyin (&c);			/* Get a character  */
		itemp = c & 0xff;
 
		if ((itemp == NEWLINE) || (itemp == CR)) {
			if (echo) {
				ttyout(CR);
				ttyout(LF);
			}
			break;
		}
		else if (i <= k) { /* only stuff if less than the max */
			if (echo) ttyout(c);
			i++;
			putino (i, itemp);
		}
	} while (i <=k);
	putctl (5, i);                     /* Return request status */
}
E 1
