25 Years of Programming
An open source source for C, C++, OWL, BASIC, MDB, XLS, DOT, and more...
Home   Projects   Up   Sitemap   Search   Blog   Forum+Chat   About Us   Privacy   Terms of Use   Feedback   FAQ   Images   Services   Ads   Donate   Humor
/*	EDIT.C 		5-24-93 	
Copyright (C)1993 Steven Whitney.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
Version 2 as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

H-100 GRAPHICS SCREEN (BITMAP) EDITOR.
6-8-93 INCORPORATED ALL FEATURES FROM PROGRAM SCALER.C 
6-9-93 WHEN LOADED FILE IS ROTATED, IT AUTOMATICALLY LANDS ON SCREEN 
6-10-93 CAN USE PAGE 2 FOR LOADING FILES AND AS A SCRATCHPAD 
10-31-93 exec("command.com") doesn't work: scrolling destroys pg.2
11-24-93 paint now allows multiple border colors
12-3-93	(e)xcept option for border colors
12-5-93 supports new pset()
	drawing lines with 'xpset' still doesn't work properly because
	the ends of 2 line segments actually overlap at their intersection
12-25-93 read/write graphics area to disk
5-2-94	moved painting into dopaint(), with tile or spray
5-9-94	allows entry of xstep, ystep

LIST OF THINGS TO DO:

add color at (x,y) to status line display
add ^C abort to Fill (must do it in box()), and add to circle()

allow entry of angle of x/y, while keeping drawn line length the same in
all directions (?).

move code out of cases in main() & into functions: especially case 'g'
get file, and case '|' change paint border - move border setting into
dopaint(), but leave border defined in main() so status line can show it.

ADD GOTO X3Y3 SO YOU CAN RETURN TO A PLACE YOU WERE AT AND SAVED
ADD MACROS AND MACROS WITH A REPETITION COUNT.  (SEE NET.C)
	FOR REP. COUNT, MOVE MOST OF MAIN() INTO PARSE(),
	IN MAIN, ASSIGN A STRING OF CHARS TO DESIRED FUNCTION KEY(S),
	THEN PICK OFF THE CHARS FROM THE STRING AND SEND TO PARSE().
ALLOW CURSOR TO *SHOW* WHERE TO BEGIN LOADED FILE.

NOTES:

-->THIS PROGRAM PROBABLY USES MOST OR ALL OF THE FUNCTIONS FROM MY GRAPHICS FUNCTION LIBRARIES.  
--Some of the operations are overly ambitious for the H100, and can take several minutes to complete. 


*/
#include "stdio.h"
							/*	H100 keyboard keycodes */
							/* UNSHIFTED KEYPAD */
#define	KEY1	0xB1
#define	KEY2	0xB2
#define	KEY3	0xB3
#define	KEY4	0xB4
#define	KEY5	0xB5
#define	KEY6	0xB6
#define	KEY7	0xB7
#define	KEY8	0xB8
#define	KEY9	0xB9
							/* SHIFTED KEYPAD */
#define SHIFTKEY0	0xF0
#define	SHIFTKEY1	0xF1
#define	SHIFTKEY2	0xF2
#define	SHIFTKEY3	0xF3
#define	SHIFTKEY4	0xF4
#define	SHIFTKEY5	0xF5
#define	SHIFTKEY6	0xF6
#define	SHIFTKEY7	0xF7
#define	SHIFTKEY8	0xF8
							/* ARROW KEYS */
#define	UP		0xA5
#define	DOWN	0xA6
#define	LEFT	0xA8
#define	RIGHT	0xA7
							/* SHIFTED ARROW KEYS */
#define	SHIFTUP		0xE5
#define	SHIFTDOWN	0xE6
#define	SHIFTLEFT	0xE8
#define	SHIFTRIGHT	0xE7
							/* OTHER KEYPAD KEYS */
#define	KEYPERIOD	0xAE
#define	KEYMINUS	0xAD
#define	HOME		0xA9
#define	SHIFTHOME	0xE9
#define ENTER		0x8D
							/* OTHER KEYS */
#define	F1			0x97
#define F2			0x98
#define F3			0x99
#define F4			0x9A
#define F9			0x9F
#define HELP		0x95							
							/* VRAM SEGMENTS */
#define	BLUE		0xC000
#define	RED			0xD000
#define	GREEN		0xE000

/* ----------------------------------------------------------------------- */
/*	GLOBAL DATA */
/* ----------------------------------------------------------------------- */
char gbuf[2160];		/* HOLDS GRAPHICS CONTENTS OF LINE 25 */
struct areadesc			/* DESCRIPTION OF AREA OF SCREEN STORED TO BUFFER */
{
	char *address;		/* POINTER TO START OF ALLOCATED CHAR ARRAY */
	int xspan;			/* X AXIS (WIDTH), IN PIXELS */
	int yspan;			/* Y AXIS (HEIGHT), IN PIXELS */
} area;
						/* LIST OF THE DISPLAYED H100 SCAN LINES */
unsigned scanline[225] =
{
0,1,2,3,4,5,6,7,8,16,17,18,19,20,21,22,23,24,32,33,34,35,36,37,38,39,40,
48,49,50,51,52,53,54,55,56,64,65,66,67,68,69,70,71,72,80,81,82,83,84,85,
86,87,88,96,97,98,99,100,101,102,103,104,112,113,114,115,116,117,118,119,
120,128,129,130,131,132,133,134,135,136,144,145,146,147,148,149,150,151,
152,160,161,162,163,164,165,166,167,168,176,177,178,179,180,181,182,183,
184,192,193,194,195,196,197,198,199,200,208,209,210,211,212,213,214,215,
216,224,225,226,227,228,229,230,231,232,240,241,242,243,244,245,246,247,
248,256,257,258,259,260,261,262,263,264,272,273,274,275,276,277,278,279,
280,288,289,290,291,292,293,294,295,296,304,305,306,307,308,309,310,311,
312,320,321,322,323,324,325,326,327,328,336,337,338,339,340,341,342,343,
344,352,353,354,355,356,357,358,359,360,368,369,370,371,372,373,374,375,
376,384,385,386,387,388,389,390,391,392
};

/* -------------------------------------------------------------- */
/*	clrscr() 	ERASES ENTIRE SCREEN, INCLUDING LINE 25 */
/* -------------------------------------------------------------- */
void clrscr()		
{
locate(25,1); puts("\033E");	/* CLEAR 25TH LINE */
locate(1,1); puts("\033E");		/* CLEAR REST OF SCREEN */
return;							/* must leave on line 1 for drawhelp() */
}

/* -------------------------------------------------------------- */
/*	NEGPLANE()	6-8-93 */
/*	INVERTS VRAM DATA IN ONE OF THE COLOR PLANES */
/*	INPUT IS CHAR = G,R,B OR A FOR ALL */
/*	RETURNS: VOID */
/*	10-31-93 USING SCANLINES[] MADE 2 SEC. (20%) IMPROVEMENT */
/*	12-8-93 using _lmove brought 63% speed improvement */
/* -------------------------------------------------------------- */
void negplane(ch)
char ch;
{
int j, k;
unsigned segment, dataseg;
char *offset, buf[80];

dataseg = _showds();
switch(tolower(ch))
{						
	case 'b':
		segment = BLUE;
		break;	
	case 'r':
		segment = RED;
		break;
	case 'a':						/* all: first DO blue AND RED */
		negplane('b');
		if(csts() == 3)				/* ^C = don't do any more */
			return;			
		negplane('r');	
		if(csts() == 3)
			return;
	case 'g':						/* then FALL THROUGH FOR green */
		segment = GREEN;
		break;	
	default:
		return;
		break;
}
for(j = 0 ; j < 225 ; j++)			/* FOR EACH SCAN LINE, */
{
	offset = scanline[j] * 128;			/* OFFSET OF 1ST BYTE OF THE LINE */
	_lmove(80,offset,segment,buf,dataseg);	/* move 80 bytes to local buf */
	for(k = 0 ; k < 80 ; k++)				/* INVERT them all */
		buf[k] = ~(buf[k]);					
	_lmove(80,buf,dataseg,offset,segment);	/* move back to vram */
}			
return;
}					/* end negplane() */

/* ----------------------------------------------------------------------- */
/*	GETS INPUT FILE NAME FROM USER */
/* ----------------------------------------------------------------------- */
void inpnam(fnam)					
char *fnam;
{								
puts("\033y5File name (include .ZIC/.ZED) (CR=quit): ");	/* CURSOR ON */
scanf("%50s",fnam);
strupr(fnam);						/* TO UPPER FOR LATER DISPLAY */
puts("\033x5");						/* CURSOR OFF */
return;
}

/* -------------------------------------------------------------- */
/*	GETAREA() SAVES AREA OF SCREEN TO MEMORY FOR RELOCATION */
/*	EACH PIXEL IS SAVED AS A BYTE IN A CHAR ARRAY WITH A VALUE 0-7 */
/*	WASTEFUL OF MEMORY, BUT IT WORKS */
/*	RETURNS TRUE IF SUCCEED, FALSE IF OFFSCREEN OR TOO LARGE TO STORE */
/* -------------------------------------------------------------- */
int getarea(x1,y1,x2,y2)
int x1, y1, x2, y2;			/* 0 TO 639 AND 0 TO 224 */
{
int i, j;						/* COUNTERS */
char *p;						/* POINTER INTO ALLOCATED ARRAY */
								/* CHARS ARE BEING USED AS SHORT INTEGERS */

if((x1 < 0) || (x1 > 639) || (x2 < 0) || (x2 > 639))
	return(FALSE);
if((y1 < 0) || (y1 > 224) || (y2 < 0) || (y2 > 224))
	return(FALSE);
	

if(area->address)				/* IF BUFFER ALREADY IN USE, */
	free(area->address);		/* FREE IT FOR REUSE */

if(y1 > y2)	{i = y1; y1 = y2; y2 = i;}		/* Y1 = LOW, Y2 = HIGH */
if(x1 > x2)	{i = x1; x1 = x2; x2 = i;}		/* X1 = LOW, X2 = HIGH */

area->yspan = y2 - y1 + 1;				/* AREA HEIGHT */
area->xspan = x2 - x1 + 1;				/* AREA WIDTH */	

/* if area is too big, instead of failing, could save to disk and somehow */
/* flag that it's on disk:  make 1st char of area->address = 255? */

if(((long)(area->xspan)*(long)(area->yspan)) > 65535)
	return(FALSE);
if(!(area->address = malloc(area->yspan * area->xspan)))
	return(FALSE);

p = area->address;
for(i = y1 ; i <= y2 ; i++)				
	for(j = x1 ; j <= x2 ; j++)
		*(p++) = (char)pset(j,i,'s',0);
return(TRUE);	
}

/* -------------------------------------------------------------- */
/*	PUTAREA() COPIES AREA FROM MEMORY TO SCREEN DISPLAY */
/*	returns TRUE if successful, FALSE if not */  
/*	12-25-93 ok if area runs off screen edges */
/* -------------------------------------------------------------- */
int putarea(x0,y0,psetmode)
int x0, y0;			/* UPPER LEFT CORNER OF WHERE TO PLACE AREA */
char psetmode;		/* (P)SET, (X)PSET, OR (O)PSET */
{
int x, y, highx, highy;
char *p;

if(!(p = area->address))				/* NOTHING THERE TO PUT */
	return(FALSE);				
							/* could test 1st char of area->address */
							/* if it's 255, get area from disk */
highx = x0 + area->xspan;
highy = y0 + area->yspan;

for(y = y0 ; y < highy ; y++)			
	for(x = x0 ; x < highx ; x++)		
		pset(x,y,psetmode,*(p++));
return(TRUE);
}

/* -------------------------------------------------------------- */
/*	writearea()	writes graphics area to disk in format: */
/*	width,height\n, then a series of (width*height) chars: */
/*	color at x1,y1, color at x2,y1, etc. (x varies fastest) */
/*	chars are numeric 0-7, could easily be ascii '0'-'7' */
/*	undecided which is best.  text editor could edit ascii file */
/*	returns TRUE if successful, FALSE if not */
/* -------------------------------------------------------------- */
int writearea(filename)
char *filename;
{
unsigned charcount;		/* limits file size to 65535, 1 fwrite chunk */
FILE *outfile;			
char *p;				/* 2nd pointer to area chars */

if(!(p = area->address))			/* NOTHING THERE TO write */
	return(FALSE);	
if(!(outfile = fopen(filename,"w")))
	return(FALSE);
if(fprintf(outfile,"%d,%d\n",area->xspan,area->yspan) == ERR)
	return(FALSE);

charcount = (area->xspan) * (area->yspan);
if(fwrite(p,1,charcount,outfile) != charcount)
	return(FALSE);
if(fclose(outfile) == ERR)
	return(FALSE);
return(TRUE);
}

/* -------------------------------------------------------------- */
/*	readarea()	reads graphics area from disk */
/*	returns TRUE if succeed, FALSE if fail */
/* -------------------------------------------------------------- */
int readarea(filename)
char *filename;
{
int width, height;
unsigned i;
FILE *infile;

if(area->address)				/* IF BUFFER ALREADY IN USE, */
	free(area->address);		/* FREE IT FOR REUSE */

if(!(infile = fopen(filename,"r")))
	return(FALSE);
if(fscanf(infile,"%d,%d\n",&width,&height) != 2)
	return(FALSE);

area->xspan = width;
area->yspan = height;

if(((long)(area->xspan)*(long)(area->yspan)) > 65535)
	return(FALSE);
i = (area->xspan) * (area->yspan);
if(!(area->address = malloc(i)))
	return(FALSE);

if(fread(area->address,1,i,infile) != i)
	return(FALSE);
fclose(infile);
return(TRUE);
}

/* -------------------------------------------------------------- */
/*	curblink()	blinks the "+" cursor on/off */
/* -------------------------------------------------------------- */
void curblink(x,y)
int x, y;
{
pset(x-3,y,'x',7);
pset(x-2,y,'x',7);
pset(x-1,y,'x',7);
pset(x,y,'x',7); 
pset(x+1,y,'x',7);
pset(x+2,y,'x',7);
pset(x+3,y,'x',7);
pset(x,y+3,'x',7);
pset(x,y+2,'x',7);
pset(x,y+1,'x',7);
pset(x,y-1,'x',7);
pset(x,y-2,'x',7);
pset(x,y-3,'x',7);
return;
}

/* -------------------------------------------------------------- */
/*	drawhelp() displays help screen */
/* -------------------------------------------------------------- */
void drawhelp()
{
clrscr();
puts("\033m70Keypad: \033m201-4,6-9 \033m40Move Cursor  \033m20. \033m40double cursor step  \033m20SHIFT 0-7 \033m40En/Disable planes\n");
puts("        \033m205 \033m40Toggle Draw/Move   \033m20- \033m401/2 cursor step     \033m20SHIFT-8   \033m40Save SCREEN.ZED\n");
puts("        \033m20HOME \033m40center screen   \033m20ARROWS \033m40move 1 dot     \033m20U \033m40(Undo)  Load SCREEN.ZED\n");
puts("        \033m20SHIFT-HOME \033m40top left  \033m20SHIFT-ARROWS \033m40to edges \033m20# \033m40Toggle AUTOZEDSAVE\n");
puts("\n");
puts("\033m70Keyboard: \033m200-7 \033m40Set Color   \033m20= \033m40GOTO new xy   \033m20HELP \033m40HELP   \033m20Q   \033m40QUIT program\n");
puts("\033m20B  \033m40BOX xy - x1y1          \033m20! \033m40AREA SAVE                 \033m20S   \033m40STATUS of variables\n");
puts("\033m20F  \033m40FILL box xy - x1y1     \033m20@ \033m40AREA PUT  \033m20F2 \033m40PUT Mode     \033m20ESC \033m40SAVE xy as x1y1\n");
puts("\033m20L  \033m40LINE xy - x1y1         \033m20| \033m40Set Paint BORDER          \033m20G   \033m40GET disk file\n");
puts("\033m20C  \033m40CIRCLE x1y1 to xy      \033m20P \033m40PAINT area                \033m20Z   \033m40.ZED screen save\n");
puts("\n");
puts("\033m20F1  \033m40Save X for OVAL       \033m20- \033m40Darken by 1 color         \033m20N \033m40Invert a color plane\n");
puts("\033m20ESC \033m40Save Y for OVAL       \033m20+ \033m40Lighten by 1 color        \033m20R \033m40Rotate color planes\n");
puts("\033m20O   \033m40Draw OVAL             \033m20E \033m40Enhance contrast          \033m20* \033m40Clear screen\n");
puts("                          \033m20A \033m40Average dot colors (uses pg.2 as scratch)\n");
puts("\n");
puts("\033m20^T \033m40Change TEXT fore/back colors  \033m20~ \033m40FLIP screen        \033m20D \033m40Delete a file\n");
puts("\033m20T  \033m40Enter TEXT to SAVE buffer\n");
puts("\033m20F3 \033m40Save graphics area to disk    \033m20F4 \033m40Read graphics area from disk\n");
puts("\n");
puts("\033m30Press any key to return to edit screen...");
setcolor(7,0);
return;
}

/* -------------------------------------------------------------- */
/*	SCALFIL()  */
/*	LOADS FILE FROM DISK, PERFORMS SCALING, ROTATION, TRANSLATION */
/*	RETURNS TRUE IF SUCCEED, FALSE IF FAIL */
/* -------------------------------------------------------------- */
int scalfil(fnam,xfactor,yfactor,theta,phi,color,xtrans,ytrans,psetmode)
char *fnam;									/* FILE NAME TO USE */
double xfactor, yfactor, theta, phi;
int color, xtrans, ytrans;
char psetmode;
{
char *buf, *buftwo;
double a, b, c, d;
FILE *infile;
int i, x, y, z, plotx, ploty;
char userquit = FALSE;
	

a = xfactor * cos(theta);	/* CONVERT TO RECTANGULAR */
b = -yfactor * sin(phi);	/* TRY INVERTING YFACTOR SOMETIME */
c = xfactor * sin(theta);	/* BECAUSE AS IT IS, PROGRAM INTERPRETS */
d = yfactor * cos(phi);		/* ANGLES BACKWARDS: + IS CLOCKWISE */

if((infile = fopen(fnam,"r")) == NULL) return(FALSE);
if(!(buf = calloc(18000,1))) return(FALSE);
for(color = 4 ; color >= 1 ; color--)
{
	if(color == 3) continue;			/* ONLY G, R, B */
	if(fread(buf,1,18000,infile) == 0)	/* READ AS MANY PLANES AS EXIST */
		break;							/* NO ERROR FOR SHORT FILE */
										/* WILL JUST SHOW WHAT WAS THERE */
	buftwo = buf;						/* SET SECONDARY POINTER */
	for(i = 0 ; i < 18000 ; i++)		/* RUN THRU ENTIRE BUFFER */
	{
		if(csts() == 3)			/* ALLOW USER ABORT WITH CONTROL-C */
		{
			ci();				/* DISCARD THE CHARACTER */
			userquit = TRUE;	/* SET FLAG TO BREAK OUT OF OUTER FOR LOOP */
			break;				/* BREAK OUT OF THIS FOR LOOP */
		}
		if(z = (int)(*buftwo))			/* BYPASS ALL IF NO BITS ON */
		{
				/* -319 AND -112 REFERENCE ENTIRE IMAGE TO SCREEN CENTER, */
				/* SO ROTATION OCCURS AROUND THE CENTER.  HOWEVER,  */
				/* THEY MUST BE RE-REFERENCED TO ACTUAL SCREEN for PSET() */
				/* IF -319 AND -112 AREN'T THERE, ENTIRE SCREEN ROTATES */
				/* AROUND THE UPPER LEFTHAND CORNER */
									/* JUST DO THESE CALCS ONCE, FOR SPEED */
			x = (i%80) * 8 - 319;	/* ADDRESS OF LEFTMOST BIT */
			y = (int)(i/80) - 112;	/* 80 BYTES PER LINE */

			/* TEST IF EACH BIT IS ON */
			if(z & 128)		
			{
				plotx=(int)(a*(double)x+b*(double)y)+xtrans;
				ploty=(int)(c*(double)x+d*(double)y)+ytrans;
				pset(plotx + 319,ploty + 112,psetmode,color);
			}
			if(z & 64)
			{
				plotx=(int)(a*(double)(x+1)+b*(double)y)+xtrans;
				ploty=(int)(c*(double)(x+1)+d*(double)y)+ytrans;
				pset(plotx + 319,ploty + 112,psetmode,color);
			}
			if(z & 32)
			{
				plotx=(int)(a*(double)(x+2)+b*(double)y)+xtrans;
				ploty=(int)(c*(double)(x+2)+d*(double)y)+ytrans;
				pset(plotx + 319,ploty + 112,psetmode,color);
			}
			if(z & 16)
			{
				plotx=(int)(a*(double)(x+3)+b*(double)y)+xtrans;
				ploty=(int)(c*(double)(x+3)+d*(double)y)+ytrans;
				pset(plotx + 319,ploty + 112,psetmode,color);
			}
			if(z & 8)
			{
				plotx=(int)(a*(double)(x+4)+b*(double)y)+xtrans;
				ploty=(int)(c*(double)(x+4)+d*(double)y)+ytrans;
				pset(plotx + 319,ploty + 112,psetmode,color);
			}
			if(z & 4)
			{
				plotx=(int)(a*(double)(x+5)+b*(double)y)+xtrans;
				ploty=(int)(c*(double)(x+5)+d*(double)y)+ytrans;
				pset(plotx + 319,ploty + 112,psetmode,color);
			}
			if(z & 2)
			{
				plotx=(int)(a*(double)(x+6)+b*(double)y)+xtrans;
				ploty=(int)(c*(double)(x+6)+d*(double)y)+ytrans;
				pset(plotx + 319,ploty + 112,psetmode,color);
			}
			if(z & 1)
			{
				plotx=(int)(a*(double)(x+7)+b*(double)y)+xtrans;
				ploty=(int)(c*(double)(x+7)+d*(double)y)+ytrans;
				pset(plotx + 319,ploty + 112,psetmode,color);
			}
		}			/* END IF(Z) */
		buftwo++;
	}				/* END FOR(I=1 TO 18000) */
	if(userquit)	/* IF USER TYPED CONTROL-C, */
		break;		/* BREAK OUT OF COLORS LOOP TO RETURN FROM FUNCTION */
}					/* END FOR(COLORS) */
fclose(infile);
free(buf);
return(TRUE);
}

/* -------------------------------------------------------------- */
/*	avgcolor()	within an area, convert each point to the */
/*	average color of itself and its 4 neighboring points */
/*	(was 8, but it was too slow) */
/*	uses good rounding method for integer arithmetic */
/*	add (number/2) to number before doing division.  if original division */
/*	would have left a remainder of (n/2) or greater, (.5), now when */
/*	it's truncated, it will be to nearest whole number (rounded) */
/*	check entire program library for places to use this */
/*	could try different averaging methods: median, mode, weighted */
/*	or choose highest or lowest of neighboring colors */
/* -------------------------------------------------------------- */
void avgcolor(startx,starty,endx,endy)
int startx, starty, endx, endy;			
{
int h, i, j, color, count;
char autorot;		
char ch = '\0';

save25th(gbuf);	
erase25th();				
puts("\033y5");						/* CURSOR ON */
puts("Enter repetition count: ");
scanf("%d\n",&count);
erase25th();
puts("Rotate colors an extra time between passes (y/n)? ");
autorot = tolower((char)getchar());
if(autorot == 'n')				/* anything else is true */
	autorot = FALSE;
erase25th();
puts("^C aborts mid-pass, ^D aborts at end of current pass.  Any key...");
ci();
puts("\033x5");						/* CURSOR OFF */
put25th(gbuf);	
for(h = 0 ; h < count ; h++)
{
	if(!zedsave())					/* save current page */
	{
		puts("\007");
		return;			/* redo the transfer without zedsave() */
	}
	flipcpu();						/* flip to alt page */
	zedload("SCREEN.ZED");			/* copy it to the other page */
	for(j = starty ; j <= endy ; j++)			/* y axis */
	{
		if(csts())							/* ^C quits */
		{
			ch = ci();
			if(ch == 3)
			{
				flipcpu();				/* back to orig page */
				return;
			}
		}
		for(i = startx ; i <= endx ; i++)		/* x axis */
		{						/* average neighboring pts, offscreen = 0 */
			color = MAX(pset(i,j-1,'s',0),0) + MAX(pset(i-1,j,'s',0),0) +
					MAX(pset(i,j,'s',0),0) + MAX(pset(i+1,j,'s',0),0) +
					MAX(pset(i,j+1,'s',0),0);	
			flipcpu();						/* to orig page */
			pset(i,j,'p',(color+2)/5);		/* set point */
			flipcpu();						/* to alt page */
		}			/* end x axis (i) */
	}				/* end y axis (j) */
	flipcpu();						/* to orig page */
	for(i = 0 ; i < 3 ; i++)
	{
		rotplanes();
		for(j = 0 ; j < 15000 ; j++);		/* delay loop */
	}
	if(ch == 4)						/* ^D aborts at end of pass */
		break;
	if(autorot)
		rotplanes();		/* extra rotation to avoid pattern stagnation */
}					/* end for(repetition count h) */
return;
}					/* end avgcolor() */

/* -------------------------------------------------------------- */
/*	dopaint()	execute paint command */
/*	IF paint FAILS, IT JUST LEAVES SOME UNPAINTED */
/* -------------------------------------------------------------- */
void dopaint(x,y,border)
int x, y;
char *border;
{
char ch, buf[40];
static char paintcolors[40];	/* colors to paint with */
static int tile = TRUE;			/* whether to use regular paint tiling */
								/* if false, random spray painting is used */
save25th(gbuf);		
do
{
	erase25th();
	printf("Paint color(s) to use or CR for <%s>: ",paintcolors);
	gets(buf);
	if(strlen(buf))
		strcpy(paintcolors,buf);
}
while(!strlen(paintcolors));	/* there must be something in paintcolors */
erase25th();
printf("<T>ile or <S>pray, CR for %s: ",tile?"<TILE>":"<SPRAY>");
ch = tolower((char)getchar());
if(ch == 't') tile = TRUE;
if(ch == 's') tile = FALSE;
put25th(gbuf);
if(!paint(x,y,paintcolors,border,tile))		
	put25th(gbuf);			/* overwrite paint's error msg */
return;
}

/* -------------------------------------------------------------- */
/*	adjustcolor()	handles contrast commands: +, -, enhance */
/* -------------------------------------------------------------- */
void adjustcolor(x,y,x1,y1,mode)
int x, y, x1, y1;
char mode;
{
int i, j, colorfound;

switch(mode)
{
	case '-':								/* REDUCE ALL COLORS BY 1 */
	case '+':								/* INCREASE ALL COLORS BY 1 */
		for(j = y1 ; j <= y ; j++)		
		{
			for(i = x1 ; i <= x ; i++)	
				pset(i,j,mode,0);
			if(csts() == 3)
				break;
		}
		break;				

	case 'e':								/* ENHANCE CONTRAST */
		for(j = y1 ; j <= y ; j++)
		{
			for(i = x1 ; i <= x ; i++)		
			{
				colorfound = pset(i,j,'s',0);
				if(colorfound > 4)				/* LEAVES GREEN UNCHANGED */
					pset(i,j,'p',MIN(colorfound+1,7));
				else
					if(colorfound < 4)
						pset(i,j,'p',MAX(colorfound-1,0));
			}
			if(csts() == 3)
				break;
		}
		break;				
}						/* end switch */
return;
}					/* end adjustcolor() */

/* -------------------------------------------------------------- */
/*	setsteps()	adjust xstep, ystep */
/* -------------------------------------------------------------- */
void setsteps(xstep,ystep)
int *xstep, *ystep;
{
char buf[20];

save25th(gbuf);		
erase25th();
puts("Enter XSTEP YSTEP or CR for no change: ");
gets(buf);
if(strlen(buf))
{
	sscanf(buf,"%d %d",xstep,ystep);				/* already pointers */
	*ystep = (int)((double)(*ystep) * 0.48046875 + .5);
}
put25th(gbuf);
return;
}

/* -------------------------------------------------------------- */
/*	main() */
/* -------------------------------------------------------------- */
main(argc,argv)
int	argc;
char **argv;
{
char vidportinit;			/* SETTING FOUND AT VIDEO PORT */
char ch, ch2;				/* USER INPUT */
char fnam[51];				/* HOLDS FILE NAMES */
int foreground, background;	/* FOREGROUND, BACKGROUND TEXT COLORS */
char border[9];				/* BORDER string FOR PAINT COMMAND */
int i, j, k;				/* COUNTERS */
int x, y;					/* COORDINATES OF CURRENT CURSOR LOCATION */
int x1, y1;					/* 1ST SET OF SAVED COORDINATES */
int x2, y2;					/* USED FOR DRAWING AFTER CURSOR MOVEMENT */
int x3, y3;					/* USED FOR DRAWING OVALS */
int draw = FALSE;			/* MODE: CURSOR DRAWS OR JUST MOVES */
int autosave = FALSE;		/* WHETHER TO ZEDSAVE() BEFORE EACH ACTION */
							/* (ALLOWS ANY CHANGE TO BE UNDONE) */
int helpthere;				/* WHETHER HELP SCREEN IS IN PAGE 2 */
							/* ONLY SET FALSE BY A FILE LOAD */
							/* IF USER ERASES SCREEN, MUST LOAD FOR HELP */
int flip;					/* WHETHER TO USE PAGE 2 FOR LOADED IMAGE */
int xstep, ystep;			/* DISTANCE CURSOR MOVES WITH EACH STEP */
int color = 4;				/* COLOR TO DRAW IN */
char psetmode = 'p';		/* X,P,O = PSET MODE  */
char drawdir = 0;			/* keypad key of direction of last draw command */
int radius;					/* RADIUS OF CIRCLE TO DRAW */
int xtrans, ytrans;			/* COORDINATE TRANSLATIONS WHEN LOADING FILE */
double xrange, yrange;		/* USED IN DRAWING CIRCLE */
double xfactor, yfactor;	/* SCALING FACTORS */
double theta, phi;			/* ANGLES USED IN ROTATING IMAGE */

freeall(1024);

puts("\033z\033x1\033x5");	/* RESET TERM., ENABLE 25TH LINE, CURSOR OFF */
puts("\033y?");				/* DISABLE H100 KEY EXPANSION */
_outb(0x78,0xD8);			/* ENABLE ALL PLANES */

flipcpu();					/* GO TO PAGE 2 */
flipcrtc();
drawhelp();				/* CREATE HELP SCREEN */
/* CI();	*/			/* THIS IS THE 'ANY CHAR' DRAWHELP ASKS FOR */
						/* OMIT ON PGM ENTRY */
flipcpu();				/* RETURN TO PAGE 1 */
flipcrtc();
helpthere = TRUE;	
locate(25,1);

x1 = y1 = x2 = y2 = x3 = y3 = 0;
strcpy(border,"0");					/* initial border is black */
area->address = 0;				/* INDICATES THAT IT HASN'T BEEN USED YET */
xstep = 16;
ystep = (int)((double)xstep * 0.48046875 + .5);
x = 320;
y = 112;

if(argc > 1)				/* EDIT FILENAME NOW ALLOWED */
	zedload(argv[1]);

curblink(x,y);
while(1)					/* DO FOREVER. EXIT IS IN LOOP */
{
	ch = tolower(ci());		/* wait for user input */
	curblink(x,y);	/* turn cursor off during any activity */

	if((autosave) && (ch != 'u'))		/* ALLOW LAST ACTION TO BE UNDONE */
		if(!zedsave())
			puts("\007");				/* WARN OF FAILURE */

	switch(ch)
	{							
						/* UNSHIFTED KEYPAD NUMBERS USED AS ARROW KEYS */
		case(KEY8):									/* 8 up */
		case 18:				/* ^R */
			x2 = x; y2 = y;
			y -= ystep;
			if(draw)
			{
				if(psetmode == 'x')
					if(drawdir == 2)				/* direction reversed, */
						pset(x2,y2,'x',color);		/* so set previous endpoint */
				line(x,y+1,x2,y2,psetmode,color);
			}
			drawdir = 8;
			break;

		case(KEY2):									/* 2 down */
		case 3:					/* ^C */
			x2 = x; y2 = y;
			y += ystep;
			if(draw)
			{
				if(psetmode == 'x')
					if(drawdir == 8)
						pset(x2,y2,'x',color);
				line(x,y-1,x2,y2,psetmode,color);
			}
			drawdir = 2;
			break;

		case(KEY6):									/* 6 right */
		case 6:						/* ^F */
			x2 = x; y2 = y;
			x += xstep;
			if(draw)
			{
				if(psetmode == 'x')
					if(drawdir == 4)
						pset(x2,y2,'x',color);
				line(x-1,y,x2,y2,psetmode,color);
			}
			drawdir = 6;
			break;

		case(KEY4):									/* 4 left */
		case 1:					/* ^A */
			x2 = x; y2 = y;
			x -= xstep;
			if(draw)
			{
				if(psetmode == 'x')
					if(drawdir == 6)
						pset(x2,y2,'x',color);
				line(x+1,y,x2,y2,psetmode,color);
			}
			drawdir = 4;
			break;

		case(KEY3):									/* 3 down-right */
			x2 = x; y2 = y;
			x += xstep;
			y += ystep;
			if(draw)
			{
				if(psetmode == 'x')
					if(drawdir == 7)
						pset(x2,y2,'x',color);
				line(x,y,x2,y2,psetmode,color);
			}
			drawdir = 3;
			break;

		case(KEY7):									/* 7 up-left */
			x2 = x; y2 = y;
			x -= xstep;
			y -= ystep;
			if(draw)
			{
				if(psetmode == 'x')
					if(drawdir == 3)
						pset(x2,y2,'x',color);
				line(x,y,x2,y2,psetmode,color);
			}
			drawdir = 7;
			break;

		case(KEY9):									/* 9 up-right */
			x2 = x; y2 = y;
			x += xstep;
			y -= ystep;
			if(draw)
			{
				if(psetmode == 'x')
					if(drawdir == 1)
						pset(x2,y2,'x',color);
				line(x,y,x2,y2,psetmode,color);
			}
			drawdir = 9;
			break;

		case(KEY1):									/* 1 down-left */
			x2 = x; y2 = y;
			x -= xstep;
			y += ystep;
			if(draw)
			{
				if(psetmode == 'x')
					if(drawdir == 9)
						pset(x2,y2,'x',color);
				line(x,y,x2,y2,psetmode,color);
			}
			drawdir = 1;
			break;
										/* ACTUAL ARROW KEYS STEP 1 DOT */
										/* BUT DON'T CHANGE THE STEP */
		case(UP):									/* UP */
		case 5:						/* ^E */
			x2 = x; y2 = y;
			y--;
			if(draw)
				pset(x,y,psetmode,color);
			break;

		case(DOWN):									/* DOWN */
			case 24:						/* ^X */
			x2 = x; y2 = y;
			y++;
			if(draw)
				pset(x,y,psetmode,color);
			break;

		case(RIGHT):									/* RIGHT */
		case 4:								/* ^D */
			x2 = x; y2 = y;
			x++;
			if(draw)
				pset(x,y,psetmode,color);
			break;

		case(LEFT):									/* LEFT */
		case 19:							/* ^S */
			x2 = x; y2 = y;
			x--;
			if(draw)
				pset(x,y,psetmode,color);
			break;
									/* SHIFT ARROWS MOVE TO SCREEN EDGES */
		case(SHIFTLEFT):								/* CENTER LEFT EDGE */
			x2 = x; y2 = y;
			x = 0; y = 112;
			if(draw)
				line(x,y,x2,y2,psetmode,color);
			break;

		case(SHIFTRIGHT):						/* CENTER RIGHT EDGE */
			x2 = x; y2 = y;
			x = 639; y = 112;
			if(draw)
				line(x,y,x2,y2,psetmode,color);
			break;

		case(SHIFTDOWN):						/* CENTER BOTTOM EDGE */
			x2 = x; y2 = y;
			x = 320; y = 224;
			if(draw)
				line(x,y,x2,y2,psetmode,color);
			break;

		case(SHIFTUP):								/* CENTER TOP EDGE */
			x2 = x; y2 = y;
			x = 320; y = 0;
			if(draw)
				line(x,y,x2,y2,psetmode,color);
			break;

		case(KEYPERIOD): 					/* KEYPAD PERIOD DOUBLES STEPs */
			xstep *= 2;
			ystep *= 2;
			break;
	

		case(KEYMINUS):						/* KEYPAD MINUS HALVES STEPs */
			xstep = MAX(((xstep + 1)/ 2),1);		/* rounded */
			ystep = MAX(((ystep + 1)/ 2),1);
			break;
	

		case(ENTER):						/* specify xstep, ystep */
			setsteps(&xstep,&ystep);
			break;

		case(HOME):						/* HOME GOES TO CENTER OF SCREEN */
			x2 = x; y2 = y;
			x = 320; y = 112;
			if(draw)
				line(x,y,x2,y2,psetmode,color);
			break;

		case(SHIFTHOME):					/* SHIFT HOME GOES TO TOP LEFT CORNER */
			x2 = x; y2 = y;
			x = 0; y = 0;
			if(draw)
				line(x,y,x2,y2,psetmode,color);
			break;

		/* KEYBOARD NUMBERS CHANGE COLOR */
		case '0': color = 0; break;		/* 0 = BLACK */
		case '1': color = 1; break;		/* 1 = BLUE */
		case '2': color = 2; break;		/* 2 = RED */
		case '3': color = 3; break;		/* 3 = MAGENTA */
		case '4': color = 4; break;		/* 4 = GREEN */
		case '5': color = 5; break;		/* 5 = CYAN */
		case '6': color = 6; break;		/* 6 = YELLOW */
		case '7': color = 7; break;		/* 7 = WHITE */

/* maybe change this to goto x1,y1 */
		case '=':						/* = EQUALS MEANS GOTO X Y */
			save25th(gbuf);			/* seldom used */
			x2 = x; y2 = y;
			do
			{
				erase25th();
				puts("GOTO: Enter x y (space between): ");
			}
			while(scanf("%d %d",&x,&y) != 2);
			put25th(gbuf);
			if(draw)
				line(x,y,x2,y2,psetmode,color);
			break;

		case 27:						/* ESCAPE: SAVE COORDINATES */
			x1 = x;
			y1 = y;
			break;	
		

		case 'l':							/* DRAW LINE FROM SAVED POINT */
			line(x1,y1,x,y,psetmode,color);			/* TO CURSOR */
			break;
	

		case 'b':							/* DRAW A BOX */
			box(x1,y1,x,y,psetmode,color,FALSE);
			break;

		case 'f':							/* FILL A BOX WITH A COLOR */
			box(x1,y1,x,y,psetmode,color,TRUE);
			break;

		case 'c':						/* DRAW CIRCLE CENTERED AT CURSOR */
										/* xpset mode should only be used */
										/* for testing.  then use pset */
			xrange = (double)(x1 - x);		/* RADIUS = CURSOR TO X1Y1 */
			yrange = 2.081300813 * (double)(y1 - y);   /* 1./.48046875 */
			radius = (int)(sqrt(xrange * xrange + yrange * yrange) + .5);
			circle(x,y,radius,psetmode,color,1.);	
			break;							
		

		case 'o':						/* DRAW OVAL */
			xrange = (double)(abs(x3 - x));
			yrange = (double)(abs(y1 - y));
			if(xrange >= yrange)
			{							/* HORIZ. MEAS. IN X UNITS */
				yrange *= 2.081300813;	
				circle(x,y,(int)xrange,psetmode,color,(yrange/xrange));
			}
			else
			{							/* VERT. MEAS. IN Y UNITS */
				xrange /= 2.081300813;
				circle(x,y,(int)yrange,psetmode,color,(yrange/xrange));	
			}
			break;			

		case(F1):						/* FUNCTION KEY F1 SAVES X3Y3 */
			x3 = x; y3 = y;
			break;

		case(KEY5):						/* KEYPAD 5 TOGGLES DRAW/MOVE MODE */
			draw = !draw;
			break;
		

		case '#':						/* POUND SIGN TOGGLES AUTOSAVE */
			autosave = !autosave;
			break;

		case(HELP):						/* HELP KEY DISPLAYS HELP PAGE */
			vidportinit = _inb(0xD8);	/* SAVE PORT SETTING */
			_outb(0x78,0xD8);			/* ENABLE ALL PLANES */
			restorepg1();				/* MAKE SURE WE START ON PAGE 1 */
			flipcpu();	
			flipcrtc();					/* GO TO PAGE 2 */
			if(!helpthere)
			{
				drawhelp();				/* IF ERASED, REDRAW SCREEN */
				helpthere = TRUE;
			}
			ci();
			flipcpu();					/* RETURN TO PAGE 1 */
			flipcrtc();				
			_outb(vidportinit,0xD8);	/* RESTORE VIDEO PORT */
			break;

		case 's':						/* STATUS DISPLAY */
			save25th(gbuf);
			erase25th();
			printf("x%d y%d x1=%d y1=%d mode:%c pset:%c save:%c c:%d bor:%s steps:x%d y%d",
				x,y,x1,y1,(draw?'D':'M'),toupper(psetmode),(autosave?'T':'F'),
				color,border,xstep,ystep);
			ci();
			put25th(gbuf);
			break;
		

		case(SHIFTKEY8):				/* SHIFT-KEYPAD 8 AUTO-ZEDSAVE */
			if(!zedsave()) puts("\007");
			break;

		case 'z':							/* ZEDSAVE */
			do
			{
				save25th(gbuf);					/* SAVE GRAPHICS */
				erase25th();					/* ERASE & LOCATE */
				inpnam(fnam);					/* GET FILE NAME */
				put25th(gbuf);					/* RESTORE GRAPHICS */
				if(!zedsave()) puts("\007");	/* SAVE THE SCREEN */
			}			 /* FILE NAME EXISTS? (but abort if user enters CR) */
			while((strlen(fnam)) && (rename("SCREEN.ZED",fnam) == ERR)); 
			break;

		case 'g':							/* GET A DISK FILE */
			save25th(gbuf);					/* SAVE LINE 25 GRAPHICS */
			flip = FALSE;
			erase25th();
			inpnam(fnam);					/* GET FILE NAME */
			if(!strlen(fnam))		/* nothing entered, abort */
			{
				put25th(gbuf);
				break;
			}
			erase25th();
			puts("\033y5Use Page 2? y/n: ");
			if(tolower(ci()) == 'y')
				flip = TRUE;

			erase25th();					/* CLEAR & REPOS. CURSOR */
			puts("ZEDLOAD? (overwrites current screen) y/n: ");
			if(tolower(ci()) == 'y')
			{
				erase25th();
				puts("\033x5");			/* CURSOR OFF */
				put25th(gbuf);			/* RESTORE GRAPHICS */
				if(flip)
				{
					restorepg1();			/* MAKE SURE WE'RE ON PAGE 1 */
					flipcpu();				/* FLIP TO PAGE 2 */
					flipcrtc();				/* FLIP */
					helpthere = FALSE;		/* HELP HAS BEEN ERASED */
				}
				zedload(fnam);
				if(flip)
				{
					flipcpu();				/* RETURN TO PAGE 1 */
					flipcrtc();				
				}
				break;
			}
			erase25th();
			puts("Enter X and Y rotation (space between): ");
			scanf("%lf %lf",&theta,&phi);
			theta *= .0174532925;			/* TO RADIANS, NEG. IS OK */
			phi *= .0174532925;			

			erase25th();
			puts("Enter X and Y scaling factors (space between): ");
			scanf("%lf %lf",&xfactor,&yfactor);

			erase25th();
			puts("Enter X and Y translation factors (space between): ");	
			scanf("%d %d",&xtrans,&ytrans);

			put25th(gbuf);
			locate(25,1);							/* REST CURSOR AT BOTTOM */
			puts("\033x5");							/* AND TURN IT OFF */
			if(flip)
			{
				restorepg1();			/* MAKE SURE WE'RE ON PAGE 1 */
				flipcpu();				/* FLIP */
				flipcrtc();				/* FLIP */
				helpthere = FALSE;		/* HELP HAS BEEN ERASED */
			}
			if(!scalfil(fnam,xfactor,yfactor,theta,phi,color,xtrans,ytrans,psetmode))
			{
				save25th(gbuf);
				erase25th();
				puts("File not found or Not enough memory (free up the get-area)");
				ci();
				put25th(gbuf);
			}	
			if(flip)
			{
				flipcpu();				/* RETURN TO PAGE 1 */
				flipcrtc();
			}
			break;

		case 'u':							/* "UNDO" WORKS ONLY IF */
			zedload("SCREEN.ZED");			/* SHIFT-KEYPAD 8 IS USED */
			break;							/* FREQUENTLY */

		case '!':							/* AREA SAVE */
			if(!getarea(x1,y1,x,y))
			{
				save25th(gbuf);
				erase25th();
				puts("\007SAVE FAILED - X or Y off screen or area too big");
				ci();
				put25th(gbuf);
			}
			break;

		case '@':							/* AREA PUT */
			putarea(x,y,psetmode);
			break;

		case(0x14):				/* CONTROL-T CHANGE TEXT COLOR */
			save25th(gbuf);
			do
			{
				erase25th();
				puts("Enter foreground background (space between): ");
			}
			while(scanf("%d %d",&foreground,&background) != 2);
			setcolor(foreground,background);
			put25th(gbuf);
			break;

		case 't':							/* ENTER TEXT LINE */
			save25th(gbuf);					/* AND AUTOMATICALLY */
			erase25th();					/* SAVE TO STORED AREA */
			gets(fnam);
			getarea(0,216,639,224);			/* SAVE LAST 9 SCAN LINES */
			put25th(gbuf);
			break;

		case '|':							/* SET PAINT BORDER */
			save25th(gbuf);
			erase25th();
			puts("Enter border color(s) 0-7 or E(xcept), no spaces: ");
			scanf("%s",border);
			border[8] = '\0';			/* terminate in case too long */
			strlwr(border);				/* won't affect digits */
			put25th(gbuf);				/* must put before reading point! */
			if(index(border,'e'))		/* all colors are border */
			{							/* except color at cursor loc. */
				k = 0;
				i = pset(x,y,'s',0);
				for(j = 0 ; j < 8 ; j++)
					if(j != i)
						border[k++] = (char)(j + 0x30);
				border[k] = '\0';
			}
			break;

		case 'p':				/* PAINT AN AREA (only works in pset mode) */
			dopaint(x,y,border);
			break;							

		case '*':							/* CLEAR SCREEN */
			clrscr();
			break;
							/* SHIFTED KEYPAD NUMBERS */
							/* THESE DON'T CHANGE DATA, ONLY DISABLE PLANES */
							/* AND PLANES CAN BE WRITTEN TO WHILE OFF */
									

		case(SHIFTKEY0): _outb(0x7F,0xD8); break;	/* BLACK (BLANK SCREEN) */
		case(SHIFTKEY1): _outb(0x7B,0xD8); break;	/* BLUE */
		case(SHIFTKEY2): _outb(0x7E,0xD8); break;	/* RED */
		case(SHIFTKEY3): _outb(0x7A,0xD8); break;	/* BLUE,RED,MAGENTA */
		case(SHIFTKEY4): _outb(0x7D,0xD8); break;	/* GREEN */
		case(SHIFTKEY5): _outb(0x79,0xD8); break;	/* GREEN,BLUE,CYAN */
		case(SHIFTKEY6): _outb(0x7C,0xD8); break;	/* RED,GREEN,YELLOW */
		case(SHIFTKEY7): _outb(0x78,0xD8); break;	/* WHITE:ALL ENABLED */

		case 'n':							/* CREATE NEGATIVE IMAGE */
			save25th(gbuf);					/* OF 1 or all PLANEs */
			erase25th();	
			puts("Invert <B>lue, <R>ed, <G>reen, or <A>ll? ");
			ch2 = ci();
			put25th(gbuf);
			negplane(ch2);
			break;				

		case '-':								/* DARKEN IMAGE */
		case '+':								/* LIGHTEN IMAGE */
		case 'e':								/* enhance contrast */
			adjustcolor(x,y,x1,y1,ch);
			break;

		case 'r':								/* ROTATE COLOR PLANES */
			rotplanes();
			break;				

		case '~':					/* TILDE FLIPS BETWEEN PAGES 1 AND 2 */
			flipcpu();
			flipcrtc();
			break;

		case 'q':
			save25th(gbuf);			
			erase25th();	
			puts("Press ESC to exit ");	/* ALLOW USER TO CHANGE MIND */
			ch2 = ci();
			if(ch2 == 27)
			{
				restorepg1();
				puts("\033z");
				exit(0);
			}
			put25th(gbuf);				
			break;
								

		case 'd':				/* DELETE A FILE TO MAKE ROOM */
			save25th(gbuf);		/* ZEDSAVE FAILS IF DISK FULL */		
			erase25th();				
			puts("\033y5");				/* CURSOR ON */
			puts("File to delete: ");
			gets(fnam);		
			unlink(fnam);
			puts("\033x5");				/* CURSOR OFF */
			put25th(gbuf);	
			break;

		case(F2):				/* CHANGE X,O,P PUTAREA() MODE */
			save25th(gbuf);		
			erase25th();				
			do
			{
				puts("PUT mode (p,x,o): ");
				psetmode = tolower((char)getchar());	
			}
			while(!index("xpo",psetmode));
			put25th(gbuf);				
			break;

		case(F3):				/* save graphics area to disk */
			save25th(gbuf);	
			erase25th();				
			puts("\033y5");				/* CURSOR ON */
			puts("Filename for area save (c/r aborts): ");
			gets(fnam);		
			puts("\033x5");				/* CURSOR OFF */
			if(strlen(fnam))
				writearea(fnam);
			put25th(gbuf);	
			break;

		case(F4):				/* read graphics area from disk */
			save25th(gbuf);	
			erase25th();				
			puts("\033y5");				/* CURSOR ON */
			puts("Filename containing graphics area (c/r aborts): ");
			gets(fnam);		
			puts("\033x5");				/* CURSOR OFF */
			if(strlen(fnam))
				readarea(fnam);
			put25th(gbuf);	
			break;

		case 'a':					/* average color values */
			avgcolor(x1,y1,x,y);
			break;

		default:
			break;
	}					/* END SWITCH */
	curblink(x,y);		/* cursor back on while idle */
}						/* END WHILE */
}						/* END MAIN */

 

 

Valid HTML 4.01 Transitional Valid CSS
View content labeling at ICRA.
Copyright ©2008 Steven Whitney. Last modified 02/27/2008.