home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Interactive Guide
/
c-cplusplus-interactive-guide.iso
/
c_ref
/
csource4
/
277_01
/
hp.c
< prev
next >
Wrap
Text File
|
1988-11-15
|
8KB
|
372 lines
/*
* hp.c
* output driver for HP7470A plotter
* copyright 1988 Ronald Florence
*
* revision of plotter.c (published PC Tech Journal 11/86)
* Tek4014 files (2/87)
* Accu-Weather maps (3/88)
* env "PLOTTER", extended status read, cpu scaling (6/88)
*/
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <termio.h>
#include <signal.h>
#define TEK4 0x1 /* option flags */
#define TEKPTS 0x2
#define SCALED 0x4
#define DEBUG 0x8
/* 80 char buffer, xon/xoff */
#define HPONLINE "\33.(\33.I80;;17:\33.N;19:"
#define HPOFFLINE "SP0;PU0,0;\33.)"
#define HPSTAT "\33.O"
#define HPABORT "\33.K"
#define HPGLERR "OE;"
#define HPRSERR "\33.E"
#define LOCK "/tmp/LCK.."
#define ERR(a,b) fprintf(stderr, "\rhp: "), fprintf(stderr, a, b)
char *title,
*plotdev,
lock[sizeof(LOCK) + 5] = LOCK,
*usage[] = {
"usage: hp [-t|p|T] [-l line] [-s speed] [-h title] [file]",
" -t Tek 4014 file",
" -p xmin, ymin, xmax, ymax before points",
" -T points scaled to 4096 x 3120",
" -l default stdout or environment \"PLOTTER\"",
" -s default 9600 baud",
" -h centered heading",
0
};
FILE *plr = stdin,
*plw = stdout,
*fi = stdin;
int fd = 1,
speed = 9600,
opt_flag,
die(),
quit();
double xm,
ym,
xscale,
yscale;
struct termio old;
main(argc, argv)
int argc;
char **argv;
{
int hperr, alrmint();
char buf[BUFSIZ];
FILE *tty = NULL;
scanarg(argc, argv);
signal(SIGQUIT, quit); /* trap del & quit */
signal(SIGINT, quit);
signal(SIGALRM, alrmint);
setline(); /* lock & set line */
if (!(opt_flag & DEBUG)) /* wake up the plotter and query status */
{
fputs(HPONLINE, plw);
try_again:
alarm(5);
do
hperr = readhp(HPSTAT);
while (hperr < 0 || hperr > 40);
alarm(0);
if (hperr & 0x30)
{
if (!tty)
tty = fopen("/dev/tty", "r");
if (!plotdev)
fputs("\33.)", plw);
ERR("press Return when plotter is ready ", NULL);
getc(tty);
if (!plotdev)
fputs(HPONLINE, plw);
goto try_again;
}
}
fputs("IN", plw); /* initialize */
if (title)
heading();
fputs("SP1", plw); /* pen 1 */
if (opt_flag & TEK4) /* Tek 4014 pic */
{
scale();
tekdecode(fi);
}
else /* points */
if (opt_flag & (SCALED | TEKPTS))
rd_points();
else /* HP-GL instructions */
while (fgets(buf, sizeof buf, fi) != NULL)
fputs(buf, plw);
if (!(opt_flag & DEBUG)) /* check for problems */
{
alarm(60);
if (hperr = readhp(HPGLERR))
ERR("HP-GL error = %d\n", hperr);
if (hperr = readhp(HPRSERR))
ERR("rs232 error = %d\n", hperr);
alarm(0);
fputs(HPOFFLINE, plw);
}
die();
}
heading()
{
int tx = 5150, ty = 7350; /* arbitrary */
fprintf(plw, "SP2SI.30,.48PU%d,%d", tx, ty);
fprintf(plw, "CP-%d,0", strlen(title)/2);
fprintf(plw, "LB%s\003", title);
}
scale()
{
int delta,
px1 = 250, /* HP7470 boundary points */
px2 = 10250,
py1 = 279,
py2 = 7479;
double ar,
xmin = 0.0, /* default Tek 4014 scaling */
ymin = 0.0,
xmax = 4096.0,
ymax = 3120.0,
dx = px2 - px1, /* HP aspect parameters */
dy = py2 - py1;
if (opt_flag & SCALED) /* read scaling points */
{
if (fscanf(fi, "%lf%lf%lf%lf", &xmin,&ymin,&xmax,&ymax) == EOF)
quit();
if (xmin >= xmax || ymin >= ymax)
ERR("invalid scaling points\n", NULL), quit();
}
ar = (xmax - xmin) / (ymax - ymin); /* calculate aspect */
if (ar < dx / dy)
{
delta = (dx - ar * dy) * 0.5;
px1 += delta;
px2 -= delta;
}
else
{
delta = (dy - dx / ar) * 0.5;
py1 += delta;
py2 -= delta;
}
fprintf(plw, "IP%d,%d,%d,%d", px1, py1, px2, py2); /* set boundary */
xm = (px2 - px1) / (xmax - xmin); /* scalars for points */
ym = (py2 - py1) / (ymax - ymin);
xscale = px1 - xmin * xm;
yscale = py1 - ymin * ym;
}
rd_points()
{
register hx, hy;
int first = 1;
double rx, ry;
scale();
while (fscanf(fi, "%lf%lf", &rx, &ry) != EOF)
{
hx = xm * rx + xscale;
hy = ym * ry + yscale;
if (!first)
fprintf(",%d,%d", hx, hy);
else if (first == 1)
{
fprintf(plw, "PU%d,%d", hx, hy);
first++;
}
else if (first == 2)
{
fprintf(plw, "PD%d,%d", hx, hy);
first = 0;
}
}
fputs("PU", plw);
}
alrmint()
{
fputs(HPOFFLINE, plw);
ERR("no response from plotter\n", NULL);
die();
}
die()
{
if (!plotdev) /* reset the line */
ioctl(fd, TCSETA, &old);
else if (unlink(lock) == -1) /* remove the lock */
ERR("cannot unlink %s\n", lock);
exit(0);
}
quit()
{
fputs(HPABORT, plw);
fputs(HPOFFLINE, plw);
die();
}
scanarg(argc, argv)
int argc;
char **argv;
{
extern int optind;
extern char *optarg;
int i;
char **cp, *strdup(), *getenv();
plotdev = getenv("PLOTTER");
while ((i = getopt(argc, argv, "s:dTl:tph:?")) != EOF)
switch (i)
{
case 's' :
speed = atoi(optarg);
break;
case 'd' :
plotdev = NULL;
opt_flag |= DEBUG;
break;
case 'l' :
plotdev = optarg;
break;
case 't' :
if (opt_flag & (SCALED | TEKPTS))
errx();
opt_flag |= TEK4;
break;
case 'p' :
if (opt_flag & (TEK4 | TEKPTS))
errx();
opt_flag |= SCALED;
break;
case 'T' :
if (opt_flag & (TEK4 | SCALED))
errx();
opt_flag |= TEKPTS;
break;
case 'h' :
title = strdup(optarg);
break;
case '?' :
for (cp = usage; *cp; ++cp)
fprintf(stderr, "%s\n", *cp);
exit(1);
}
if (argc > 1 && argc != optind)
if ((fi = fopen(argv[optind], "r")) == NULL)
ERR("can't find %s\n", argv[optind]), exit(1);
}
errx()
{
ERR("incompatible options\n", NULL);
exit(1);
}
setline()
{
struct termio term;
char dvc[5], *strchr();
int BAUD,
ld;
switch (speed)
{
case 300:
BAUD = B300;
break;
case 1200:
BAUD = B1200;
break;
case 2400:
BAUD = B2400;
break;
case 4800:
BAUD = B4800;
break;
case 9600:
BAUD = B9600;
break;
default:
ERR("invalid speed", NULL);
die();
}
if (plotdev) /* parse the name of the device */
{
if (strncmp(plotdev, "/dev/", 5))
{
strcpy(dvc, plotdev);
strcpy(plotdev, "/dev/");
strcat(plotdev, dvc);
}
else
strcpy(dvc, strchr(plotdev, 't'));
strcat(lock, dvc);
if (!access(lock, 0))
ERR("%s is locked\n", dvc), exit(1);
if ((fd = open(plotdev, O_RDWR | O_NDELAY)) < 0)
ERR("can't open %s\n", plotdev), exit(1);
if ((ld = creat(lock, 0644)) < 0)
ERR("can't create %s\n", lock), exit(1);
close(ld);
}
else /* save line parameters */
ioctl(fd, TCGETA, &old);
ioctl(fd, TCGETA, &term);
term.c_cflag &= ~CBAUD;
term.c_cflag |= BAUD | CLOCAL;
term.c_lflag &= ~ECHO;
term.c_iflag |= ICRNL | IXON | BRKINT;
term.c_cc[VMIN] = 1;
term.c_cc[VTIME] = 0;
ioctl(fd, TCSETAF, &term);
if (plotdev)
{
plr = fopen(plotdev, "r");
plw = fopen(plotdev, "w");
}
}
readhp(query)
char *query;
{
int hperr;
fputs(query, plw);
if (fscanf(plr, "%d", &hperr) == EOF)
alrmint();
return(hperr);
}