1*16551Sslatteng /* @(#)graphics3.c	1.4	05/29/84
211953Sslatteng  *
311953Sslatteng  * Copyright -C- 1982 Barry S. Roitblat
411953Sslatteng  *
511953Sslatteng  *      This file contains additional routines for implementing graphics
611953Sslatteng  * primitives for the gremlin picture editor
711953Sslatteng  */
811953Sslatteng 
911953Sslatteng #include "gremlin.h"
1011953Sslatteng #include <sys/types.h>
1111953Sslatteng #include <sys/timeb.h>
1211953Sslatteng #include <signal.h>
13*16551Sslatteng #include <sys/time.h>
1411953Sslatteng 
1511953Sslatteng /* imports from graphics1.c */
1611953Sslatteng 
1711953Sslatteng extern GRsetwmask();
1811953Sslatteng extern int curx, cury, rmask;
1911953Sslatteng extern FILE *display;
2011953Sslatteng extern GRClear();
2111953Sslatteng 
2211953Sslatteng /* library routines */
2311953Sslatteng 
2411953Sslatteng extern ftime();
2511953Sslatteng 
GREnableTablet()2611953Sslatteng GREnableTablet()
2711953Sslatteng 
2811953Sslatteng /*---------------------------------------------------------
2911953Sslatteng  *	This routine enables the graphics tablet.
3011953Sslatteng  *
3111953Sslatteng  *	Results: None.
3211953Sslatteng  *
3311953Sslatteng  *	Side Effects:
3411953Sslatteng  *	The tablet cursor is enabled on the AED.  This will cause characters
3511953Sslatteng  *	to be sent over the serial line whenever a button on the cursor is
3611953Sslatteng  *	pushed.  After calling this routine, the routine GrGetButton may
3711953Sslatteng  *	be called to wait for the next button to be pushed.
3811953Sslatteng  *
3911953Sslatteng  *	Design:
4011953Sslatteng  *	Note:  the AED really messes up with the cursor, because it
4111953Sslatteng  *	continually overwrites CAP with cursor coordinates.  Thus the
4211953Sslatteng  *	cursor must disabled before doing ANYTHING to the AED.
4311953Sslatteng  *---------------------------------------------------------
4411953Sslatteng  */
4511953Sslatteng 
4611953Sslatteng {
4711953Sslatteng     GRsetwmask(127);   /* don't write cursor on grid layer */
4811953Sslatteng     fputs("3:", display);
4911953Sslatteng     (void) fflush(display);
5011953Sslatteng }
5111953Sslatteng 
GRDisableTablet()5211953Sslatteng GRDisableTablet()
5311953Sslatteng 
5411953Sslatteng /*---------------------------------------------------------
5511953Sslatteng  *	This routine disables the graphics tablet so that other things may
5611953Sslatteng  *	be done with the AED.
5711953Sslatteng  *
5811953Sslatteng  *	Results:	None.
5911953Sslatteng  *	Side Effects:	The tablet is disabled.
6011953Sslatteng  *---------------------------------------------------------
6111953Sslatteng  */
6211953Sslatteng 
6311953Sslatteng {
6411953Sslatteng     putc('3', display);
6511953Sslatteng     putc('\0', display);
6611953Sslatteng     (void) fflush(display);
6711953Sslatteng     curx = cury = -1;
6811953Sslatteng }
6911953Sslatteng 
7011975Sslatteng 
7111953Sslatteng #define MINTIME 100        /* 100 milliseconds */
7211953Sslatteng 
7311953Sslatteng int
GRGetButton(stream,px,py)7411953Sslatteng GRGetButton(stream, px, py)
7511953Sslatteng FILE *stream;			/* File from which AED chars. can be read */
7611953Sslatteng int *px;			/* Address of a word to hold x-coordinate */
7711953Sslatteng int *py;			/* Address of word to hold y-coorinate */
7811953Sslatteng 
7911953Sslatteng /*---------------------------------------------------------
8011953Sslatteng  *	This routine waits for cursor input.
8111953Sslatteng  *
8211953Sslatteng  *	Results:
8311953Sslatteng  *	The return value is the number of the button that was pushed.
8411953Sslatteng  *	If an error occurs while reading from the stream, -1 is returned.
8511953Sslatteng  *
8611953Sslatteng  *	Side Effects:
8711953Sslatteng  *	The integers pointed to by px and py are filled in with the
8811953Sslatteng  *	x- and y-coordinates of the cursor at the time the button
8911953Sslatteng  *	was pushed.
9011953Sslatteng  *
9111953Sslatteng  *	Design:
9211953Sslatteng  *	This is tricky.  The AED apparently sends bogus button data at
9311953Sslatteng  *	random times.  It can usually be distinguished by the presence
9411953Sslatteng  *	of an illegal button number.  We must pick out such data and throw
9511953Sslatteng  *	it away.
9611953Sslatteng  *
9711953Sslatteng  *	For systems up to 4.1BSD (characterized by the presence of the
9811953Sslatteng  *	SIGTINT signal) the routine waits for cursor input.
9911953Sslatteng  *	For 4.2BSD and beyond, the routine gives an error of -4 if input
10011953Sslatteng  *	is not immediately available (it expects to be called only when
10111953Sslatteng  *	input is available).
10211953Sslatteng  *---------------------------------------------------------
10311953Sslatteng  */
10411953Sslatteng 
10511953Sslatteng {
10611953Sslatteng     int button;
10711988Sslatteng     struct timeval selectpoll;
10811953Sslatteng     static unsigned long time, lastime = 0;
10911953Sslatteng     struct timeb tp;
11011953Sslatteng     static char line1[100];
11111953Sslatteng 
11211988Sslatteng     selectpoll.tv_sec = 0l;
11311988Sslatteng     selectpoll.tv_usec = 0l;
11411953Sslatteng     while (TRUE)
11511953Sslatteng     {
11611953Sslatteng 
11711953Sslatteng #ifndef SIGTINT
11811953Sslatteng         button = 1 << fileno(stream);
11911988Sslatteng         if (select(20, &button, 0, 0, &selectpoll) <= 0) return -4;
12011953Sslatteng #endif
12111953Sslatteng 
12211953Sslatteng 	if (fgets(line1, 99, stream) == NULL) return -1;
12311953Sslatteng 	if (line1[0] != ':') continue;
12411953Sslatteng 	(void) sscanf(&(line1[1]), "%d", &button);
12511953Sslatteng 	if (fgets(line1, 99, stream) == NULL) return -2;
12611953Sslatteng 	(void) sscanf (line1, "%d", px);
12711953Sslatteng 	if (fgets(line1, 99, stream) == NULL) return -3;
12811953Sslatteng 	(void) sscanf (line1, "%d", py);
12911953Sslatteng 
13011953Sslatteng             /* wait for minimum duration before accepting   */
13111953Sslatteng             /* new button to debounce the cursor            */
13211953Sslatteng 
13311953Sslatteng         ftime(&tp);
13411953Sslatteng         time = 1000 * tp.time + tp.millitm;
13511953Sslatteng         if ((time - lastime) < MINTIME ) continue;
13611953Sslatteng         lastime = time;
13711953Sslatteng 
13811953Sslatteng 	if (button == 2) return 1;
13911953Sslatteng 	if (button == 4) return 2;
14011953Sslatteng 	if (button == 8) return 3;
14111953Sslatteng 	if (button == 1) return 0;
14211953Sslatteng     }
14311953Sslatteng }
14411953Sslatteng 
14511953Sslatteng 
14611975Sslatteng 
GRSetGrid(x1,y1,x2,y2,size)14711953Sslatteng GRSetGrid(x1, y1, x2, y2, size)
14811953Sslatteng int x1, y1, x2, y2, size;
14911953Sslatteng /*
15011953Sslatteng  *      This routine sets the grid  according to the paramaters
15111953Sslatteng  * (lower left and upper right corners, and spacing) supplied.  The
15211953Sslatteng  * grid is written to the appropriate memory plane but will not be
15311953Sslatteng  * displayed unless that plane has been (Read) enabled.
15411953Sslatteng  */
15511953Sslatteng 
15611953Sslatteng {
15711953Sslatteng 	int i, start;
15811953Sslatteng 	POINT end1, end2;
15911953Sslatteng 
16011953Sslatteng 	GRClear(gridmask);
16111953Sslatteng 	GRsetwmask(gridmask);
16211953Sslatteng 	end1.y = (float) y1;
16311953Sslatteng 	end2.y = (float) y2;
16411953Sslatteng 	start  = ((x1 + size - 1) - ((x1 + size - 1) % size));
16511953Sslatteng 
16611953Sslatteng 	     /* start forces the lines to be drawn on pixel
16711953Sslatteng                 boundaries evenly divisible by size           */
16811953Sslatteng 
16911953Sslatteng 	for (i=start; i<=x2; i+=size)
17011953Sslatteng 	{
17111953Sslatteng 		end1.x = end2.x = (float) i;
17211953Sslatteng 		GRVector(&end1, &end2, gridstyle);
17311953Sslatteng 	}  /* end for */;
17411953Sslatteng 	end1.x = (float) x1;
17511953Sslatteng 	end2.x = (float) x2;
17611953Sslatteng 	start  = ((y1 + size - 1) - ((y1 + size - 1) % size));
17711953Sslatteng 	for (i=start; i<=y2; i+=size)
17811953Sslatteng 	{
17911953Sslatteng 		end1.y = end2.y = (float) i;
18011953Sslatteng 		GRVector(&end1, &end2, gridstyle);
18111953Sslatteng 	}  /* end for */;
18211953Sslatteng }  /* end SetGrid */;
18311953Sslatteng 
18411953Sslatteng 
GRSetRead(mask)18511953Sslatteng GRSetRead(mask)
18611953Sslatteng int mask;
18711953Sslatteng /*
18811953Sslatteng  *      This routine sets the read mask.
18911953Sslatteng  */
19011953Sslatteng 
19111953Sslatteng {
19211953Sslatteng #ifndef FASTIO
19311953Sslatteng 	char s1[3], s2[3], s3[3], s4[3];
19411953Sslatteng #endif
19511953Sslatteng 
19611953Sslatteng 	rmask = mask;
19711953Sslatteng 
19811953Sslatteng #ifndef FASTIO
19911953Sslatteng 	GRchex(rmask,s1,2);
20011953Sslatteng 	GRchex(rmask1,s2,2);
20111953Sslatteng 	GRchex(rmask2,s3,2);
20211953Sslatteng 	GRchex(rmask3,s4,2);
20311953Sslatteng 	fprintf(display,"M%s%s%s%s", s1, s2, s3, s4);
20411953Sslatteng #else
20511953Sslatteng 	putc('M',display);
20611953Sslatteng 	putc(rmask,display);
20711953Sslatteng 	putc(rmask1,display);
20811953Sslatteng 	putc(rmask2,display);
20911953Sslatteng 	putc(rmask3,display);
21011953Sslatteng #endif
21111953Sslatteng 
21211953Sslatteng 	(void) fflush(display);
21311953Sslatteng }  /* end SetRead */
21411953Sslatteng 
21511975Sslatteng 
GRDisplayGrid()21611953Sslatteng GRDisplayGrid()
21711953Sslatteng /*
21811953Sslatteng  *      This routine displays the grid created by setgrid by enabling
21911953Sslatteng  * the appropriate read layer.
22011953Sslatteng  */
22111953Sslatteng 
22211953Sslatteng {
22311953Sslatteng 	GRSetRead(rmask | gridmask);
22411953Sslatteng }  /* end DisplayGrid */
22511953Sslatteng 
GRBlankGrid()22611953Sslatteng GRBlankGrid()
22711953Sslatteng /*
22811953Sslatteng  *      This routine assures that the grid is not displayed by
22911953Sslatteng  * setting the read mask to disable the grid layer.
23011953Sslatteng  */
23111953Sslatteng 
23211953Sslatteng {
23311953Sslatteng 
23411953Sslatteng 	GRSetRead(rmask & ~gridmask);
23511953Sslatteng }  /* end BlankGrid */
23611953Sslatteng 
237