/* * 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 * edmoy@opal.Berkeley.EDU * ucbvax!opal!edmoy * and modified by: * Mic Kaczmarczik * User Services Digital Support Group * Computation Center * University of Texas at Austin * Austin, TX 78712 * mic@ngp.utexas.edu * ...!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 * achhabra@ucesp1.ece.uc.edu * 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 #include #include #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 #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\ %% (achhabra@ucesp1.ece.uc.edu)\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++; }