/*
* tek2eepic - convert Tektronix 4015 escape sequences to EEPIC for
* inclusion of graphs in LaTeX documents.
*
* Based largely on Tek2ps written by:
* Edward Moy
* Academic Computing Services
* University of California
* Berkeley, CA 94720
*
[email protected]
* ucbvax!opal!edmoy
* and modified by:
* Mic Kaczmarczik
* User Services Digital Support Group
* Computation Center
* University of Texas at Austin
* Austin, TX 78712
*
[email protected]
* ...!ihnp4!seismo!ut-sally!ut-ngp!mic
* and by:
* Bryon Hance
* User Services VAX/VMS Support
* Computation Center
* University of Texas at Austin
* Austin, TX 78712
*
*
* Tek2eepic written by:
* Atul K. Chhabra
* Dept. of Electrical & Computer Engineering
* University of Cincinnati
* Cincinnati, OH 45221-0030
*
[email protected]
* Feb 25, 1989
*
* Requires Tekparse.h and Tekparsetable.c, which is part of the
* xterm 6.6* distribution.
*
* Tektronix alphanumerics are currently not supported.
*
*/
#include "Tekparse.h"
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#define COURIER (10. / 6.) /* ratio of height to width */
#define DEF_HEIGHT 4.9
#define DEF_WIDTH 6.5
#define FALSE 0
#define MAXPATH 35
#define EPINCHES 300
#define S_H 010
#define S_W 04
#define TRUE 1
#define UNITLENGTH 0.0033
#define UNITLINETHICKNESS 0.014
/* Tek defines */
#define BEL 07
#define CANCEL 030
#define DASHEDLINE 2
#define DOTTEDLINE 1
#define EAST 01
#define ETX 03
#define LARGEFONT 0
#define LINEMASK 07
#define LONGDASHEDLINE 4
#define MARGIN1 0
#define MARGIN2 1
#define MAX_PTS 150
#define MAX_VTX 300
#define NAK 025
#define NORTH 04
#define PENDOWN 1
#define PENUP 0
#define SHORTDASHEDLINE 3
#define SMALLFONT 3
#define SOLIDLINE 0
#define SOUTH 010
#define TEKBOTTOMPAD 24
#define TEKFULLHEIGHT (TEKHEIGHT + TEKTOPPAD + TEKBOTTOMPAD)
#define TEKFULLWIDTH (TEKWIDTH + TEKPAD)
#define TEKHEIGHT 3072
#define TEKHOME ((TekChar[fontsize].nlines - 1)\
* TekChar[fontsize].vsize)
#define TEKNUMFONTS 4
#define TEKPAD 58
#define TEKTOPPAD 34
#define TEKWIDTH 4096
#define THREEFONT 2
#define TWOFONT 1
#define WEST 02
#ifdef TOPS20
/* Make global identifiers unique to 6 (uppercase) characters */
#define Tpushback Tpshbck
#define TCursorUp TCUp
#define TCursorDown TCDown
#define TCursorBack TCBack
#define TCursorForward TCForward
#define cur_X curXXX
#define cur_Y curYYX
#define psprolog2 pspr2
#endif
#define GOOD 0 /* good exit status */
#ifdef VMS
#define rindex strrchr
#include <ssdef.h>
#undef GOOD
#define GOOD SS$_NORMAL
#endif
#define MIN(x,y) ((x) < (y) ? (x) : (y))
#define MAX(x,y) ((x) > (y) ? (x) : (y))
int Tbcnt = 0;
char Tbuffer[BUFSIZ];
char *Tbptr = Tbuffer;
char Tpushb[BUFSIZ];
char *Tpushback = Tpushb;
/* use comma operator so these macros act like one line (hack!!!) */
#define TekFlush() fputs("\n", stdout), nplot = 0
#define TekMove(x,y) cur_X = (x), cur_Y = (y)
#define input() Tinput()
#define unput(c) *Tpushback++ = (c)
static struct Tek_Char {
int hsize; /* in Tek units */
int vsize; /* in Tek units */
int charsperline;
int nlines;
} TekChar[TEKNUMFONTS] = {
{56, 88, 74, 35}, /* large */
{51, 82, 81, 38}, /* #2 */
{34, 53, 121, 58}, /* #3 */
{31, 48, 133, 64}, /* small */
};
static int cur_X;
static int cur_Y;
static int cur_x;
static int cur_y;
static double sx, sy;
static int ep_x, ep_y;
static int fontsize;
static lastfont = -1;
static int linetype;
static int margin;
static int noerase = FALSE;
static double penscale = 1.0;
static int ignorefirst = FALSE;
static int pageno = 1;
static int nplot;
static int pen;
static int infd = 0;
static double w, h;
static int min_x = 5000, max_x = -5000;
static int min_y = 5000, max_y = -5000;
extern int Talptable[];
extern int Tbestable[];
extern int Tbyptable[];
extern int Tesctable[];
extern int Tipltable[];
extern int Tplttable[];
extern int Tpttable[];
extern int Tspttable[];
static int *curstate = Talptable;
static int *Tparsestate = Talptable;
char *myname;
main(argc, argv)
int argc;
char **argv;
{
register int set = 0;
register double scale, temp;
char *rindex();
if(myname = rindex(*argv, '/'))
myname++;
else
myname = *argv;
for(argc--, argv++ ; argc > 0 && **argv == '-' ; argc--, argv++)
switch((*argv)[1]) {
case 'o':
if (argc < 2)
Usage();
if (freopen(*++argv,"w",stdout) == NULL) {
fprintf(stderr,"%s: can't open %s\n",
myname,*argv);
exit(1);
}
argc--;
break;
case 'w':
if(argc < 2)
Usage();
w = atof(*++argv);
argc--;
set |= S_W;
break;
case 'h':
if(argc < 2)
Usage();
h = atof(*++argv);
argc--;
set |= S_H;
break;
case 'i': /* ignore *first* PAGE */
ignorefirst = TRUE;
break;
case 'n': /* scale the pen nib */
if (argc < 2)
Usage();
penscale = atof(*++argv);
argc--;
break;
case 'p': /* Don't erase on PAGE */
noerase = TRUE;
break;
default:
Usage();
}
init(set);
if(argc > 1)
Usage();
if((argc == 1) && ((infd = open(*argv, 0)) < 0)) {
fprintf(stderr, "%s: can't open %s\n", myname, *argv);
exit(1);
}
cur_X = 0;
cur_Y = TEKHOME;
Tekparse();
}
Usage()
{
fprintf(stderr,"Usage: %s [-inp] [-o file] [-w #] [-h #] [file ...]\n",
myname);
exit(1);
}
char ephead[] = "\
%% tek2eepic version 1.0 (Feb 24, 1989)\n\
%% Written by: Atul Chhabra, University of Cincinnati\n\
%% (
[email protected])\n\
%%\n\
";
char epprolog[] = "\
\\setlength{\\unitlength}{%fin}\n\
\\begin{picture}(%d,%d)(0,0)\n\
\\allinethickness{%fin}\n\
";
/*
char psfont[] =
"/f%d {/Courier findfont [%.2f 0 0 %d 0 0] makefont setfont} def\n";
*/
init(set)
int set;
{
printf (ephead);
switch(set & (S_W | S_H)) {
case 0:
w = DEF_WIDTH;
h = DEF_HEIGHT;
break;
case S_W:
h = w * TEKFULLHEIGHT / TEKFULLWIDTH;
break;
case S_H:
w = h * TEKFULLWIDTH / TEKFULLHEIGHT;
break;
}
sx = EPINCHES * w / TEKFULLWIDTH;
sy = EPINCHES * h / TEKFULLHEIGHT;
printf (epprolog, UNITLENGTH,
((int) (w * EPINCHES)), ((int) (h * EPINCHES)),
UNITLINETHICKNESS * penscale);
}
Tekparse()
{
register int c, x, y;
register char *cp;
char text[BUFSIZ];
for( ; ; )
switch(Tparsestate[c = input()]) {
case CASE_REPORT: /* report address */
case CASE_VT_MODE: /* special return to vt102 mode */
case CASE_BEL: /* BEL */
case CASE_COPY: /* make copy */
case CASE_CURSTATE:
Tparsestate = curstate; /* clear bypass condition */
break;
case CASE_SPT_STATE: /* Enter Special Point Plot mode */
Tparsestate = curstate = Tspttable;
break;
case CASE_GIN: /* Do Tek GIN mode */
Tparsestate = Tbyptable; /* Bypass mode */
break;
case CASE_BS: /* BS */
Tparsestate = curstate; /* clear bypass condition */
TCursorBack();
break;
case CASE_PT_STATE: /* Enter Tek Point Plot mode */
Tparsestate = curstate = Tpttable;
break;
case CASE_PLT_STATE: /* Enter Tek Plot mode */
Tparsestate = curstate = Tplttable;
if((c = input()) == BEL)
pen = PENDOWN;
else {
unput(c);
pen = PENUP;
}
break;
case CASE_TAB: /* HT */
Tparsestate = curstate; /* clear bypass condition */
TCursorForward();
break;
case CASE_IPL_STATE: /* Enter Tek Incremental Plot mode */
Tparsestate = curstate = Tipltable;
break;
case CASE_ALP_STATE: /* Enter Tek Alpha mode */
/* if in one of graphics states, move alpha cursor */
if(nplot > 0) /* flush line Tbuffer */
TekFlush();
Tparsestate = curstate = Talptable;
break;
case CASE_UP: /* cursor up */
Tparsestate = curstate; /* clear bypass condition */
TCursorUp();
break;
case CASE_PAGE: /* Page Function */
TekPage(); /* clear bypass condition */
break;
case CASE_BES_STATE: /* Byp: an escape char */
Tparsestate = Tbestable;
break;
case CASE_BYP_STATE: /* set bypass condition */
Tparsestate = Tbyptable;
break;
case CASE_IGNORE: /* Esc: totally ignore CR, ESC, LF, ~ */
break;
case CASE_ASCII: /* Select ASCII char set */
/* ignore for now */
Tparsestate = curstate;
break;
case CASE_APL: /* Select APL char set */
/* ignore for now */
Tparsestate = curstate;
break;
case CASE_CHAR_SIZE: /* character size selector */
fontsize = c & 03;
Tparsestate = curstate;
break;
case CASE_BEAM_VEC: /* beam and vector selector */
/* only line types */
if((c &= LINEMASK) != linetype) {
if(nplot > 0)
TekFlush();
linetype = c;
}
Tparsestate = curstate;
break;
case CASE_PENUP: /* Ipl: penup */
pen = PENUP;
break;
case CASE_PENDOWN: /* Ipl: pendown */
pen = PENDOWN;
break;
case CASE_IPL_POINT: /* Ipl: point */
x = cur_X;
y = cur_Y;
if(c & NORTH)
y++;
else if(c & SOUTH)
y--;
if(c & EAST)
x++;
else if(c & WEST)
x--;
if(pen == PENDOWN)
TekDraw(x, y);
else
TekMove(x, y);
break;
case CASE_PLT_VEC: /* Plt: vector */
unput(c);
if(getpoint()) {
if(pen == PENDOWN)
TekDraw(cur_x, cur_y);
else
TekMove(cur_x, cur_y);
pen = PENDOWN;
}
break;
case CASE_PT_POINT: /* Pt: point */
unput(c);
if(getpoint()) {
TekMove(cur_x, cur_y);
TekDraw(cur_x, cur_y);
}
break;
case CASE_SPT_POINT: /* Spt: point */
/* ignore intensity character in c */
if(getpoint()) {
TekMove(cur_x, cur_y);
TekDraw(cur_x, cur_y);
}
break;
case CASE_CR: /* CR */
if(nplot > 0) /* flush line Tbuffer */
TekFlush();
cur_X = margin == MARGIN1 ? 0 :
TEKWIDTH / 2;
Tparsestate = curstate = Talptable;
break;
case CASE_ESC_STATE: /* ESC */
Tparsestate = Tesctable;
break;
case CASE_LF: /* LF */
TCursorDown();
break;
case CASE_SP: /* SP */
TCursorForward();
break;
case CASE_PRINT: /* printable character */
if(lastfont != fontsize)
lastfont = fontsize;
/*
printf("f%d\n", lastfont = fontsize);
printf("%d %d (", cur_X, y = cur_Y);
*/
cp = text;
x = sizeof(text) - 1;
unput(c);
while(x-- > 0 && y == cur_Y) {
if(!isprint(c = input())) {
unput(c);
break;
}
if(c == '(' || c == ')' || c == '\\') {
if(x <= 0) {
unput(c);
break;
}
*cp++ = '\\';
x--;
}
*cp++ = c;
TCursorForward();
}
*cp = 0;
/*
printf("%s) p\n", text);
*/
break;
case CASE_OSC: /* do osc escape */
while(!iscntrl(input())); /* ignore */
Tparsestate = curstate;
break;
}
}
Tinput()
{
register int c;
if(Tpushback > Tpushb)
return(*--Tpushback);
again:
if(Tbcnt-- <= 0) {
if((Tbcnt = read(infd, Tbptr = Tbuffer, BUFSIZ)) <= 0) {
fputs("\n\\end{picture}\n\n\n",stdout);
printf("%%\\begin{picture}(%d,%d)(%d,%d)\n",
max_x-min_x, max_y-min_y, min_x, min_y);
exit(1);
}
Tbcnt--;
}
if(!(c = (*Tbptr++ & 0177)))
goto again;
return(c);
}
TekPage()
{
/* if ignorefirst is TRUE, totally ignore first PAGE command */
if (ignorefirst) {
ignorefirst = FALSE;
return;
}
pageno++;
if(noerase)
TekFlush();
else {
fputs("\n\\end{picture}\n\n\n",stdout);
printf("%% xsize=%d ysize=%d xpos=%d ypos=%d\n",
max_x-min_x, max_y-min_y, min_x, min_y);
printf(epprolog, UNITLENGTH,
((int) (w * EPINCHES)), ((int) (h * EPINCHES)),
UNITLINETHICKNESS * penscale);
}
cur_X = 0;
cur_Y = TEKHOME;
}
#define EXTRABITS 017
#define FIVEBITS 037
#define HIBITS (FIVEBITS << SHIFTHI)
#define LOBITS (FIVEBITS << SHIFTLO)
#define SHIFTHI 7
#define SHIFTLO 2
#define TWOBITS 03
getpoint()
{
register int c, x, y, e, lo_y = 0;
x = cur_x;
y = cur_y;
for( ; ; ) {
if((c = input()) < ' ') { /* control character */
if (c == '\n' || c == '\r' || c == '\0')
continue; /* ignore CR, LF */
unput(c);
return(0);
}
if(c < '@') { /* Hi X or Hi Y */
if(lo_y) { /* seen a Lo Y, so this must be Hi X */
x &= ~HIBITS;
x |= (c & FIVEBITS) << SHIFTHI;
continue;
}
/* else Hi Y */
y &= ~HIBITS;
y |= (c & FIVEBITS) << SHIFTHI;
continue;
}
if(c < '`') { /* Lo X */
x &= ~LOBITS;
x |= (c & FIVEBITS) << SHIFTLO;
cur_x = x;
cur_y = y;
return(1); /* OK */
}
/* else Lo Y */
if(lo_y) { /* seen a Lo Y, so other must be extra bits */
e = (y >> SHIFTLO) & EXTRABITS;
x &= ~TWOBITS;
x |= e & TWOBITS;
y &= ~TWOBITS;
y |= (e >> SHIFTLO) & TWOBITS;
}
y &= ~LOBITS;
y |= (c & FIVEBITS) << SHIFTLO;
lo_y++;
}
}
TCursorBack()
{
register struct Tek_Char *t;
register int x, l;
x = (cur_X -= (t = &TekChar[fontsize])->hsize);
if(margin == MARGIN1 && x < 0 || margin == MARGIN2
&& x < TEKWIDTH / 2) {
if((l = (cur_Y + (t->vsize - 1)) / t->vsize + 1) >=
t->nlines) {
margin = !margin;
l = 0;
}
cur_Y = l * t->vsize;
cur_X = (t->charsperline - 1) * t->hsize;
}
}
TCursorForward()
{
register struct Tek_Char *t;
register int l;
if((cur_X += (t = &TekChar[fontsize])->hsize) > TEKWIDTH) {
if((l = cur_Y / t->vsize - 1) < 0) {
margin = !margin;
l = t->nlines - 1;
}
cur_Y = l * t->vsize;
cur_X = margin == MARGIN1 ? 0 : TEKWIDTH / 2;
}
}
TCursorUp()
{
register struct Tek_Char *t;
register int l;
t = &TekChar[fontsize];
if((l = (cur_Y + (t->vsize - 1)) / t->vsize + 1) >= t->nlines) {
l = 0;
if((margin = !margin) != MARGIN1) {
if(cur_X < TEKWIDTH / 2)
cur_X += TEKWIDTH / 2;
} else if(cur_X >= TEKWIDTH / 2)
cur_X -= TEKWIDTH / 2;
}
cur_Y = l * t->vsize;
}
TCursorDown()
{
register struct Tek_Char *t;
register int l;
t = &TekChar[fontsize];
if((l = cur_Y / t->vsize - 1) < 0) {
l = t->nlines - 1;
if((margin = !margin) != MARGIN1) {
if(cur_X < TEKWIDTH / 2)
cur_X += TEKWIDTH / 2;
} else if(cur_X >= TEKWIDTH / 2)
cur_X -= TEKWIDTH / 2;
}
cur_Y = l * t->vsize;
}
TekDraw (x, y)
int x, y;
{
static int lastx = -1, lasty = -1;
if((nplot == 0) || (nplot >= MAXPATH) || (lastx != cur_X) ||
(lasty != cur_Y)) {
if(nplot > 0)
TekFlush();
switch(linetype){
case 0:
printf("\\path");
break;
case 1:
printf("\\dottedline{6}");
break;
case 2:
printf("\\drawline[-50]");
break;
case 3:
printf("\\dashline{12}[3]");
break;
case 4:
printf("\\dashline[-30]{12}[3]");
break;
default:
printf("\\path");
break;
}
min_x = MIN(min_x, ((int) (sx * cur_X)));
max_x = MAX(max_x, ((int) (sx * cur_X)));
min_y = MIN(min_y, ((int) (sy * cur_Y)));
max_y = MAX(max_y, ((int) (sy * cur_Y)));
printf("(%d,%d)", ((int) (sx * cur_X)), ((int) (sy * cur_Y)));
nplot = 1;
}
lastx = cur_X = x;
lasty = cur_Y = y;
min_x = MIN(min_x, ((int) (sx * x)));
max_x = MAX(max_x, ((int) (sx * x)));
min_y = MIN(min_y, ((int) (sy * y)));
max_y = MAX(max_y, ((int) (sy * y)));
printf("(%d,%d)", ((int) (sx * x)), ((int) (sy * y)));
nplot++;
}