#ifndef lint static char *rcs = "$Header: gf.c,v 1.1 88/01/15 13:04:05 simpson Rel $"; #endif /* $Log: gf.c,v $ * Revision 1.1 88/01/15 13:04:05 simpson * initial release * * Revision 0.1 87/12/11 18:30:56 simpson * beta test * */ #include #include #include #include #include #include #include "constants.h" #include "fontnode.h" enum linetypes { dotted, solid, longdashed, shortdashed, dotdashed }; char *Whoami; /* argv[0] */ int X, Y; int PortraitFont = 1204; int LandscapeFont = 1217; int curx, cury, lowx, lowy, highx, highy; double scalefactor; enum linetypes linetype = solid; extern char *User; extern char *Host; extern Boolean Accounting; extern int NumPages; extern FILE *Accting; main(argc, argv) int argc; char *argv[]; { extern int optind; extern char *optarg; PROFILE_VALUE *v, *getbindingvalue(); struct sigvec SigStruct; int c, callcleanup(); int xi, yi, x0, y0, x1, y1, r; char s[256]; void sanestate(), openpl(), move(), line(), label(), erase(), point(), cont(), space(), arc(), circle(), linemod(), closepl(), getstring(); void cleanup(); Whoami = argv[0]; while ((c = getopt(argc, argv, "x:y:n:h:w:l:")) != EOF) switch (c) { case 'x': X = atoi(optarg); break; case 'y': Y = atoi(optarg); break; case 'l': case 'w': break; case 'n': User = optarg; break; case 'h': Host = optarg; break; case '?': exit(2); } if (optind < argc) { Accounting = TRUE; if (!(Accting = fopen(argv[optind], "a"))) { fprintf(stderr,"%s: cannot open accounting file %s\r\n", Whoami, argv[optind]); Accounting = FALSE; } } if (X > 2550) { if ((v = getbindingvalue("landscapefont")) && v->class == PROFILE_INTEGER) LandscapeFont = v->value.i; } else if ((v = getbindingvalue("portraitfont")) && v->class == PROFILE_INTEGER) PortraitFont = v->value.i; SigStruct.sv_handler = callcleanup; SigStruct.sv_mask = 0; SigStruct.sv_onstack = 0; (void)sigvec(SIGINT, &SigStruct, (struct sigvec *)NULL); openpl(); while ((c = getchar()) != EOF) switch (c) { case 'm': xi = getsi(stdin); yi = getsi(stdin); move(xi,yi); break; case 'l': x0 = getsi(stdin); y0 = getsi(stdin); x1 = getsi(stdin); y1 = getsi(stdin); line(x0,y0,x1,y1); break; case 't': getstring(s,stdin); label(s); break; case 'e': erase(); break; case 'p': xi = getsi(stdin); yi = getsi(stdin); point(xi,yi); break; case 'n': xi = getsi(stdin); yi = getsi(stdin); cont(xi,yi); break; case 's': x0 = getsi(stdin); y0 = getsi(stdin); x1 = getsi(stdin); y1 = getsi(stdin); space(x0,y0,x1,y1); break; case 'a': xi = getsi(stdin); yi = getsi(stdin); x0 = getsi(stdin); y0 = getsi(stdin); x1 = getsi(stdin); y1 = getsi(stdin); arc(xi,yi,x0,y0,x1,y1); break; case 'c': xi = getsi(stdin); yi = getsi(stdin); r = getsi(stdin); circle(xi,yi,r); break; case 'f': getstring(s,stdin); linemod(s); break; } (void)sigblock(SIGINT); closepl(); fputs(QUICON, stdout); cleanup((struct FontNode *)NULL, SUCCEED); } callcleanup() { void cleanup(); closepl(); fputs(QUICON, stdout); cleanup((struct FontNode *)NULL, SUCCEED); } void openpl() { fputs(QUICON, stdout); if (X > 2550) fputs(LANDSCAPE, stdout); else fputs(PORTRAIT, stdout); printf("%s00000", SYNTAX); printf("%s00000%05d", INITMARGVERT, X > 2550 ? (int)(8.5 * 1000) : 11 * 1000); printf("%s00000%05d", INITMARGHORZ, X > 2550 ? 11 * 1000 : (int)(8.5 * 1000)); printf("%s%d%s", DEFFONT, X > 2550 ? LandscapeFont : PortraitFont, ENDCMD); fputs(FREEOFF, stdout); fputs(VECTORON, stdout); } void move(x, y) int x, y; { curx = x; cury = y; } void line(x1, y1, x2, y2) int x1, y1, x2, y2; { fputs(VECTORON, stdout); fputs("^V", stdout); switch (linetype) { case dotted: printf("2"); break; case shortdashed: printf("4"); break; case longdashed: printf("6"); break; case dotdashed: printf("7"); break; default: printf("0"); break; } /* end switch */ printf("^U%05d:%05d", (int)((x1 - lowx) * scalefactor / 300.0 * 1000.0), (int)(((X > 2550 ? 8.5 : 11) - ((y1 - lowy) * scalefactor / 300.0)) * 1000.0)); printf("^D%05d:%05d", (int)((x2 - lowx) * scalefactor / 300.0 * 1000.0), (int)(((X > 2550 ? 8.5 : 11) - ((y2 - lowy) * scalefactor / 300.0)) * 1000.0)); fputs(VECTOROFF, stdout); curx = x2, cury = y2; } void label(s) char *s; { double scale; char *ptr; /* Each character is assumed to be 54 units wide without scaling. Since the QMS fonts are proportional make sure that they are typeset in the right place. The minimum width can be 45 dots (a 'W' in font 1204) so adjust "scale" in case scalefactor would make the width smaller than this. 54*x = 45 x = 45/54 = 0.833333 */ scale = scalefactor; if (scale < 0.833333) scale = 0.833333; for (ptr = s; *ptr != '\0' && *ptr != '\n'; ptr++) { printf("\r^IV%05d", (int)(((X > 2550 ? 8.5 : 11) - (cury - lowy) * scalefactor / 300.0) * 1000.0)); printf("%s-00170", JUSTIFYRELATIVE); printf("^IH%05d", (int)((curx - lowx) * scalefactor / 300.0 * 1000.0)); if (ptr - s > 0) printf("%s+%05d", TABRELATIVE, (int)(54 * (ptr - s) * scale / 300.0 * 1000.0)); (void)putchar(*ptr); } } void erase() { NumPages++; putchar('\r'); fputs(FORMFEED, stdout); } void point(x, y) { printf("^IH%05d", (int)((((curx - lowx) * scalefactor - 5.0) / 300.0) * 1000.0)); printf("^IV%05d", (int)(((X > 2550 ? 8.5 : 11) - ((cury - lowy) * scalefactor - 5.0) / 300.0) * 1000.0)); printf("%s0003300033", LINE); curx = x; cury = y; } void cont(x, y) int x, y; { fputs(VECTORON, stdout); fputs("^V", stdout); switch (linetype) { case dotted: printf("2"); break; case shortdashed: printf("4"); break; case longdashed: printf("6"); break; case dotdashed: printf("7"); break; default: printf("0"); break; } /* end switch */ printf("^U%05d:%05d", (int)((curx - lowx) * scalefactor / 300.0 * 1000.0), (int)(((X > 2550 ? 8.5 : 11) - ((cury - lowy) * scalefactor / 300.0)) * 1000.0)); printf("^D%05d:%05d", (int)((x - lowx) * scalefactor / 300.0 * 1000.0), (int)(((X > 2550 ? 8.5 : 11.0) - ((y - lowy) * scalefactor / 300.0)) * 1000.0)); fputs(VECTOROFF, stdout); curx = x, cury = y; } void space(x0, y0, x1, y1) int x0, y0, x1, y1; { double xscale, yscale; lowx = x0; highx = x1; lowy = y0; highy = y1; /* Pick smallest scale factor (x or y) and use it. Don't scale different * x and y directions or the image will become distorted. */ xscale = (double)X / (highx - lowx); yscale = (double)Y / (highy - lowy); if (xscale > yscale) scalefactor = yscale > 1.0 ? 1.0 : yscale; else scalefactor = xscale > 1.0 ? 1.0 : xscale; } void arc(x, y, x0, y0, x1, y1) { double dx, dy, startangle, endangle; fputs(DECIMALARC, stdout); printf("+%05d+%05d", (int)((x - lowx) * scalefactor / 300.0 * 1000.0), (int)(((X > 2550 ? 8.5 : 11.0) - ((y - lowy) * scalefactor / 300.0)) * 1000.0)); printf("%05d", (int)(sqrt(pow((double)x0 - x, 2.0) + /* radius */ pow((double)y0 - y, 2.0)) * scalefactor / 300.0 * 1000.0)); dx = x0 - x; dy = y0 - y; if (dx == 0.0) startangle = dy > 0.0 ? 90.0 : -90.0; else startangle = atan2(dy, dx) / PI * 180.0; if (startangle < 0.0) startangle += 360.0; startangle = 1000.0 - (startangle / 360.0 * 1000.0); if (startangle == 1000.0) /* QMS only takes 3 digits */ startangle = 999.0; dx = x1 - x; dy = y1 - y; if (dx == 0.0) endangle = dy > 0.0 ? 90.0 : -90.0; else endangle = atan2(dy, dx) / PI * 180.0; if (endangle < 0.0) endangle += 360.0; endangle = 1000.0 - (endangle / 360.0 * 1000.0); if (endangle == 1000.0) endangle = 999.0; /* Since the QMS draws clockwise, reverse points */ printf("%03d%03d", (int)endangle, (int)startangle); fputs("04", stdout); fputs(ENDCMD, stdout); } void circle(x, y, r) int x, y, r; { arc(x, y, x + r, y, x - r, y); arc(x, y, x - r, y, x + r, y); } void linemod(s) char *s; { int stringlen; char *index(); if (index(s, '\n')) stringlen = s - index(s, '\n'); else stringlen = 100; if (EQN(s, "dotted", stringlen)) linetype = dotted; else if (EQN(s, "dotdashed", stringlen)) linetype = dotdashed; else if (EQN(s, "longdashed", stringlen)) linetype = longdashed; else if (EQN(s, "shortdashed", stringlen)) linetype = shortdashed; else linetype = solid; } void closepl() { NumPages++; (void)putchar('\r'); fputs(FORMFEED, stdout); fputs(QUICOFF, stdout); } /* Get an integer stored in 2 ascii bytes */ int getsi(fin) FILE *fin; { short a, b; if ((b = getc(fin)) == EOF) return(EOF); if ((a = getc(fin)) == EOF) return(EOF); a <<= 8; return a | b; } void getstring(s, fin) char *s; FILE *fin; { for (; *s = getc(fin); s++) if (*s == '\n') break; *s = '\0'; }