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