/* output filter for tektronics 4010-graphics files to generate postscript
 * files.  This does a simple-minded byte by byte translation to predefined
 * PS routines, contained in a prolog file.
 * Defaults:
 * input:	stdin
 * output:	stdout
 * prolog:	~msf/tek2ps/tek2ps.pro
 * prolog defines:
 * m = moveto
 * l = rlineto
 * r = rmoveto
 * s = stroke
 * n = newpath
 * v = newpath moveto {rlineto} repeat stroke
 */

/* modified Aug 1997 by M. Thompson:  use "arcn" instead of "arc" for
 *  PTPLT mode; use "outfile" since redefining "stdout" no longer works */

/* modified Mar 1997 by M. Thompson:  add command line option "-l" to
 *  set the line style; rearrange, clean up indents, use arrays for
 *  font sizes and line types; fix graph-rotate calculation */

/* modified Oct 1996 by M. Thompson:  permit ML comand inside a graphics
 *  mode sequence */

/* modified May 1996 by M. Thompson:  use EP macro at end of page to
 *  permit 6-up printing */

/* modified Aug 1994 by M. Thompson:  process "Mac circles" (DA) and
 *  handle filled panels */

/* modified July 1993 by Ren Richmond:  process tektronix 4105 commands
 *  (LT,MR,MC,LP,LE,MW) via case CMD41; added command line option "-w"
 *  to set the line width */

/* modified June 1993 by D. Ernst: handle Postscript special chars
 *  via the function IsSpecial */

#include <stdio.h>
#include <ctype.h>
#include "tek41.h"

extern char	*optarg;
extern int	optidx;
extern double	atof();
extern int	atoi();
extern void	exit();
extern int	tekopt();
int	oldmode,mode=ALPHA;
int	nesc;
char	escs[100];	/* escape sequence buffer */
int	cx=0, cy=YDIM-CHUGEY;
int	tsizex, tsizey;
int	leftmargin=0;
float	angle=0.;
int	HiY=0,LoY=0,BY=0;
int	HiX=0,LoX=0,BX=0;
int	ncx,ncy;
int	num_vector = (-1);
int	gotLoY=FALSE,gotLoX=FALSE;
int	color [8][3] = {	/* assumes black background */
	{1,1,1},	/* black - prints as white */
	{0,0,0},	/* white - prints as black */
	{1,0,0},	/* red   */
	{0,1,0},	/* green */
	{0,0,1},	/* blue  */
	{0,1,1},	/* cyan  */
	{1,0,1},	/* magenta */
	{1,1,0}};	/* yellow */
int	igc_line=1;	/* line color */
int	igc_text=1;	/* text color */
int	igc_panel=0;	/* panel color */
int	rgb_all=(-1);	/* color override */
int	font_num = (-1);
char	*fonts[4] = {"FntH","FntL","FntM","FntS"};
int	xsize[4] = {CHUGEX, CLARGEX, CMEDX, CSMALLX};
int	ysize[4] = {CHUGEY, CLARGEY, CMEDY, CSMALLY};
int	font_defined[4] = {TRUE, FALSE, FALSE, FALSE};
char	*font_defs[4] = {"DFntH", "DFntL", "DFntM", "DFntS"};
double	scale_factor=1.0;
int	widthscale=0;
int	linestyle=(-1);
char	*vects[8] = {"NV", "DV", "DDV", "SDV", "LDV", "NV", "NV", "NV"};
int	visi;	/* visibility */
int	debug=FALSE, pr_on_er=FALSE;
int	ccnt=0;	/* input character count (debug tool) */

FILE *outfile;

void do_file(FILE *infile);
void xy_param(int c);
void end_vector(int mymode);
void mov_down();
void mov_right();
int iscontrol(int c);
int decode_int(char **bufp);
void escs_text(char *str, int lenstr);
void setlinewidth(int linewidth, int widthscale);
void setfont (int newfont);
int IsSpecial (char d);


main(int argc, char *argv[])  {

/* #ifndef lint
static charsccsid[]=" @(#)t2p.c	1.10 tek2ps (Copyright) M. Fischbein  Commercial reproduction prohibited; non-profit reproduction and distribution encouraged.";
#endif */


static char	def_pro[]="TEK2PS_PRO";
char	*pro_fn = def_pro;
FILE	*pro_fp, *infile = stdin;
int    c;

/* 07/11/00 CAL: moved inside main, since Linux gcc would not compile
   outfile = stdout;

/* first, parse command line */
    while ((c = tekopt (argc, argv, "o:p:e:s:w:l:c:de:")) != EOF) {
	switch ( c ) {
	case 'o' :	/* use specified output file */

	    outfile = fopen(optarg, "w");
	    if( outfile == NULL ) {
		fprintf(stderr, "Can't open output file %s\n", optarg);
		exit(1);
	    }
	    break;

	case 'p' :	/* use custom prolog */
	    pro_fn = optarg;
	    break;

	case 'd' :	/* toggle debugging */
	    if (debug)
		debug = FALSE;
	    else
		debug = TRUE;
	    break;

	case 'e':	/* turn on print-before-erase */
			/* and erase-after-print */
	    pr_on_er = TRUE;
	    break;

	case 's':	/* set scale option */
	    scale_factor = atof(optarg)/100.;
	    break;

	case 'w':	/* line width scale option */
	    widthscale = atoi(optarg);
	    break;

	case 'l':	/* line style (solid,dash) option */
	    linestyle = atoi(optarg);
	    break;

	case 'c':	/* color override */
	    rgb_all = atoi(optarg);
	    break;

	default:
	    fprintf(stderr, "Usage: %s [-p prologfile] [-de] [input]\n", argv[0]);
	
	}
    }

    /* copy the prolog file */
    if( (pro_fp = fopen(pro_fn, "r")) == NULL) {
	fprintf(stderr, "Can't open prolog file %s\n", pro_fn);
	exit(1);
    }
    while ((c = getc(pro_fp)) != EOF) {
	putc((char) c, outfile);
    }
    fclose(pro_fp);
	/* init the font size */
	setfont(0);		/* default size */

    /* check for named file (loop if more than one) */
    do {
	if (optidx < argc) {
	    if ((infile = fopen( argv[optidx], "r")) == NULL) {
	    fprintf(stderr, "Can't open input file %s\n", argv[optidx]);
	    exit(1);
	    }
	}
	/* check for scale factor */
	if (scale_factor != 1.0) {
	    /* I know floating pt equality is a bad idea, but if
	     * the option is not present I explicity initialize to 1.0,
	     * so the bit pattern should be identical portably */
	    fprintf(outfile,"%f %f scale\n", scale_factor, scale_factor);
	}

	/* set color once if rgb_all switch set */
	if (rgb_all>=0) {
	    fprintf(outfile,"%d %d %d setrgbcolor \n",
	    color[rgb_all][0],color[rgb_all][1],color[rgb_all][2]);
	}

	do_file(infile);
    } while ( ++optidx < argc );
}


void do_file(FILE *infile)  {

int	c,c2;
char	*bufp;
int	beamon;
int	lenstr;
int	power;	/* 4105 numbers stored as mant, power */
int	height,width;
int	drawbound,fillarc;
int	arc_start,arc_end,diam;
int	linewidth=0;
int	vectype;

/*  read a byte and figure out what to do about it */
while ((c = getc(infile)) != EOF) {
    ccnt++;
    switch ( mode ) {

    case ALPHA:		/* start of ALPHA mode */
	if (isgraph((char) c)) {
			/* normal printing char */
	    if (IsSpecial( (char) c) )
		fprintf(outfile,"(\\%c) %d %d PR\n", (char) c, cx, cy);
	    else
		fprintf(outfile,"(%c) %d %d PR\n", (char) c, cx, cy);
	    mov_right();
	    break;
	}
	if (iscontrol( c ))	/* print control character */
	    break;

	switch ( c ) {		/* tek control characters */
	case ( GS ):
	    mode = GRAPH;
	    num_vector = -1;
	    break;

	case ( RS ):
	    mode = INCRE;
	    break;

	case ( FS ):
	    mode = PTPLT;
	    break;

	case ( US ):	/* put in ALPHA mode, already there */
	    break;

	case ( ESC ):
	    oldmode = ALPHA;
	    mode = LCEMD;
	    break;

	default :
	    if (debug)
		fprintf(stderr, "Unknown ALPHA mode character 0x%02x\n", c);
	}	/* end of tek control chars in ALPHA mode */

	break;	/* end of ALPHA mode */

    case PTPLT:
    case GRAPH:		/* start of GRAPH mode */
	if ((char) c > US) {	/* first, handle vector case */
	    xy_param(c);
	    break;
	}
				/* non-vector characters */
	switch ( c ) {
	case ( NUL ):	/* padding */
	case ( SYN ):	/* padding */
	case ( BEL ):	/* ignore */
	    break;

	case ( LF ):
	    end_vector(mode);
	    cy -= tsizey;
	    fprintf(outfile,"%d %d m\n",cx,cy);
	    break;

	case ( CR ):
	    mode = ALPHA;
	    leftmargin = 0;
	    break;

	case ( RS ):
	    mode = INCRE;
	    break;

	case ( FS ):
	    if (debug)
		fprintf(stderr,"special point plot not implemented\n");
	    mode = PTPLT;
	    break;

	case ( GS ):
	    end_vector(mode);
	    break;

	case ( US ):
	    mode = ALPHA;
	    break;

	case ( ESC ):
	    mode = LCEMD;
	    break;

	default :
	    if (debug)
		fprintf(stderr, "Unknown GRAPH mode character 0x%02x\n", c);
	}	/* end of non-vector char in GRAPH mode */

	oldmode = GRAPH;
	if ((mode != oldmode) && (num_vector >= 0))
	    end_vector(oldmode);

	break;	/* end of GRAPH mode */

    case INCRE:
	/* could do with bit masking and check for control, */
	/* but this is is simpler. (Let the compiler work). */
	switch ( c ) {
	case ( 32 ):
	    fprintf(outfile,"stroke %d %d m\n", cx, cy);
	    beamon = FALSE;
	    break;

	case ( 80 ):
	    fprintf(outfile,"%d %d m\n", cx, cy);
	    beamon = TRUE;
	    break;

	case ( 68 ):	/* N */
	    if (++cy > YDIM) cy = YDIM;
	    if (beamon) fprintf(outfile,"%d %d lineto\n", cx, cy);
	    break;
	
	case ( 69 ):	/* NE */
	    if (++cy > YDIM) cy = YDIM;
	    if (++cx > XDIM) cx = XDIM;
	    if (beamon) fprintf(outfile,"%d %d lineto\n", cx, cy);
	    break;

	case ( 65 ):	/* E */
	    if (++cx > XDIM) cx = XDIM;
	    if (beamon) fprintf(outfile,"%d %d lineto\n", cx, cy);
	    break;

	case ( 73 ):	/* SE */
	    if (--cy < 0) cy = 0;
	    if (++cx > XDIM) cx = XDIM;
	    if (beamon) fprintf(outfile,"%d %d lineto\n", cx, cy);
	    break;

	case ( 72 ):	/* S */
	    if (--cy < 0) cy = 0;
	    if (beamon) fprintf(outfile,"%d %d lineto\n", cx, cy);
	    break;

	case ( 74 ):	/* SW */
	    if (--cy < 0) cy = 0;
	    if (--cx < 0) cx = 0;
	    if (beamon) fprintf(outfile,"%d %d lineto\n", cx, cy);
	    break;

	case ( 66 ):	/* W */
	    if (--cx < 0) cx = 0;
	    if (beamon) fprintf(outfile,"%d %d lineto\n", cx, cy);
	    break;

	case ( 70 ):	/* NW */
	    if (++cy > YDIM) cy = YDIM;
	    if (--cx < 0) cx = 0;
	    if (beamon) fprintf(outfile,"%d %d lineto\n", cx, cy);
	    break;

	case ( ESC ):
	    if (beamon) fprintf(outfile,"stroke %d %d m\n", cx, cy);
	    oldmode = INCRE;
	    mode = LCEMD;
	    break;

	case ( FS ):
	    if (beamon) fprintf(outfile,"stroke %d %d m\n", cx, cy);
	    mode = PTPLT;
	    break;

	case ( GS ):
	    if (beamon) fprintf(outfile,"stroke %d %d m\n", cx, cy);
	    mode = GRAPH;
	    num_vector = -1;
	    break;

	case ( RS ):
	    break;

	case ( US ):
	    if (beamon) fprintf(outfile,"stroke %d %d m\n", cx, cy);
	    mode = ALPHA;
	    break;

	default:
	    if (debug)
		fprintf(stderr,"Unknown incremental mode character 0x%02x\n", c);
	}	/* end of INCR switch */

	break;	/* end of INCREmental mode */

    case LCEMD:		/* start of LCEMD mode - 4014 escape mode */
	if ((c=='%') || ((c>='A') && (c<='Z'))) {
	    escs[0]=c;		/* 4105 command <ESC>aa */
	    nesc=1;
	    c2=0;
	    mode = CMD41;
	    break;
	}

	if (iscontrol(c)) {
	    mode = ALPHA;

	} else if ((c > 95) && (c < 117)) {
	    if ((char) c & 0x08)	/* set z axis = linewidth */
		linewidth=1;
	    else
		linewidth=0;
	    setlinewidth(linewidth,widthscale);
	
	    vectype = c & 0x07;		/* set vector type */
	    if (linestyle >= 0) vectype = linestyle;
	    if (vectype > 7) vectype = 7;
	    fprintf(outfile,"%s\n",vects[vectype]);

	} else if ((c>='8') && (c<=';')) {	/* "89:;" */
	    setfont ( c - (int)'8');	/* set char size */

	} else {
	switch ( c ) {
	case ( GS ):
	    mode = GRAPH;
	    num_vector = -1;
	    break;

	case ( LF ):
	case ( CR ):
	case ( DEL ):
	    break;

	case ( ESC ):
	    ungetc( (char) ESC, infile);
	    break;

	case ( ETB ):	/* make copy: print & start new page */
	    end_vector(oldmode);
	    if (pr_on_er) {
		fprintf(outfile, "NP\n");
		if (scale_factor != 1.0)
		    fprintf(outfile,"%f %f scale\n", scale_factor, scale_factor);
	    } else
		fprintf(outfile, "copypage\n");
	    fprintf(outfile, "%d DP\n", tsizey);
	    cx = 0; cy = YDIM - tsizey;
	    break;

	case ( SO ):
	case ( SI ):
	    if (debug)
		fprintf(stderr, "No alternate character set implemented\n");
	    break;

	case ( CAN ):
	case ( SUB ):
	case ( ENQ ):
	    if (debug)
		fprintf(stderr, "GIN and BYPASS  modes not implemented\n");
	    break;

	case ( '?' ):
	    /* ungetc( (char) DEL, infile); */
	    break;

	default :
	    if (debug)
		fprintf(stderr, "Unknown LCE mode character 0x%02x ignored\n", c);
	}	/* end of LCE mode switch */
	}
	if (mode==LCEMD) mode = oldmode;

	break;	/* end of LCEMD mode */

    case CMD41:		/* start of CMD41 mode */
	if ( (escs[0]=='M') && (c>95) ) {	/* embedded ML command */
	    ungetc( (char) c, infile);
	    num_vector = 0;
	    mode = GRAPH;
	    c = 0;
	}

	if (c >=' ' ){
	    if (nesc >= 100) {
	        fprintf(stderr, "CMD41 buffer overflow\n");
	        exit(1);
	    }
	    escs[nesc++] = c;
	    break;
	}

	c2 = escs[0]<<8 | escs[1];
	bufp = &escs[2];

	switch ( c2 ) {
	case ('L'<<8 | 'T'):		/* Graphic-Text Command */
	    lenstr = decode_int(&bufp);
	    escs_text(bufp, lenstr);
	    break;

	case ('L'<<8 | 'P'):		/* Begin-Panel Boundary */
	    if (c==GS) {	/* ignore GS within panel */
		c=0;
		break;
	    }

	    num_vector = -1;
	    do {
		xy_param(*bufp++);
	    } while (gotLoX=FALSE);

	    drawbound = decode_int(&bufp);
	    while (bufp < &escs[nesc]) {
		xy_param(*bufp++);
	    }
	    break;

	case ('L'<<8 | 'E'):		/* End-Panel-Boundary command */
	    fprintf(outfile,"closepath\n");
	    /* ? if (!drawbound) just fill */
	    if (igc_panel == 0)	/* outline, no fill */
		fprintf(outfile,"%d %d %d v\n",num_vector,cx,cy);
	    else	/* outline with fill */
		fprintf(outfile,"%d %d %d vf\n",num_vector,cx,cy);
	    num_vector = -1;
	    break;

	case ('L'<<8 | 'V'):		/* Set visibility */
	    visi = decode_int(&bufp);
	    break;

	case ('M'<<8 | 'R'):		/* Set-Graphtext-Rotation */
	    angle = (float)decode_int(&bufp);
	    power = decode_int(&bufp);
	    while (power>0) {
		angle *= 10.;
		power--;
	    }
	    break;

	case ('M'<<8 | 'C'):		/* Set-Graphtext-Size */
	    width = decode_int(&bufp);
	    height = decode_int(&bufp);

	    if ((height>=55) && (height<65)) {		/* 8 case */
		setfont(0);
	    } else if (height>=45) {		/* 9 case */
		setfont(1);
	    } else if (height>=30) {		/* : case */
		setfont(2);
	    } else if (height>=20) {		/* ; case */
		setfont(3);
	    }
	    break;

	case ('D'<<8 | 'A'):		/* Draw-ARC */
	    fillarc = decode_int(&bufp);	/* 1=frame, 2=fill, 3=both */
	    arc_start = decode_int(&bufp);
	    arc_end = decode_int(&bufp);
	    diam = decode_int(&bufp);
	    fprintf(outfile,"n %d %d %d %d %d arc\n",
	    cx, cy, diam, arc_start, arc_end);
	    if (fillarc==3)	/* outline with fill */
		fprintf(outfile,"gsave fill grestore s\n");
	    else			/* outline, no fill */
		fprintf(outfile,"s\n");
	    break;

	case ('M'<<8 | 'W'):		/* Set-Line-Width */
	    /* lineswitch =1 --> wide line */
	    /* lineswitch =0 --> narrow default */
	    linewidth = decode_int(&bufp);
	    setlinewidth(linewidth,widthscale);
	    break;

	case ('M'<<8 | 'L'):		/* Set-Line-Index */
	    igc_line = decode_int(&bufp);
	    if (igc_line<1) igc_line=1;
	    if (igc_line>7) igc_line=7;
	    if (rgb_all<0) {
		fprintf(outfile,"%d %d %d setrgbcolor \n",
		color[igc_line][0],color[igc_line][1],
		color[igc_line][2]);
	    }
	    break;

	case ('M'<<8 | 'T'):		/* Set-Text-Index */
	    igc_text = decode_int(&bufp);
	    if (igc_text<1) igc_text=1;
	    if (igc_text>7) igc_text=7;
	    break;

	case ('M'<<8 | 'P'):		/* Set-Panel-color */
	    igc_panel = -decode_int(&bufp);
	    break;

	case ('%'<<8 | '!'):		/* select code */
	    visi = decode_int(&bufp);
	    if (visi==8) mode = ALPHA;	/* 4105 <-> 4014 */
	    break;

	}	/* end of C2 switch */

	switch ( c ) {		/* char after 4105 command */
	case ( GS ):
	    mode = GRAPH;
	    num_vector = -1;
	    break;
	case ( US ):
	    mode = ALPHA;
	    break;
	case ( ESC ):
	    mode = LCEMD;
	    break;
	case ( FS ):
	    mode = PTPLT;
	    break;
	}

	break;	/* end of CMD41 mode */

    default:
	if (debug)
	    fprintf(stderr, "Unknown major mode %d\n", mode);

    }		/* end of mode switch */
    }		/* end of main input loop */

    /* complete any unfinished output */
    if (cx != 0 || cy != YDIM - tsizey) {
	end_vector(mode);
	fprintf(outfile,"EP\n");
    }
}

/* decode escs bytes into tektronix integer */
void xy_param(int c)  {

    if( (char) c < '@') {	/* High byte y*/
	if (gotLoY) {	/* must be HiX */
	    HiX = (c & 0x1f) << 7;
	} else {	/* must be HiY */
	    HiY = (c & 0x1f) << 7;
	}
    }  else if ((char) c < '`') {	/* Lo X: plot */
	gotLoY = FALSE;
	gotLoX = TRUE;
	LoX = (c & 0x1f) <<2 ;
	/* now actually do a plot */
	if (num_vector > 99) {	/* draw line so far */
	    fprintf(outfile,"%d %d %d v\n",num_vector,ncx,ncy);
	    num_vector = 0;
	}
	ncx = HiX + LoX + BX;
	ncy = HiY + LoY + BY;
	if (num_vector < 0) {	/* move to start line */
	    if (!(mode==GRAPH)||(mode==CMD41) ){
		fprintf(outfile,"%d %d m\n",ncx,ncy);
	    }
	    num_vector = 0;
	} else {		/* make line segment */
	    if ((mode==GRAPH)||(mode==CMD41)) {
		fprintf(outfile,"%d %d\n", cx-ncx, cy-ncy);
	    } else {		/* mode == PTPLT */
		fprintf(outfile,"n %d %d 2 0 360 arc s\n", ncx,ncy);
		num_vector = -1;
	    }
	    num_vector++;
	}
	cx = ncx;
	cy = ncy;

    } else {	/* Lo Y or extra byte */
	if (gotLoY) {	/* previous LoY => extra byte */
	    BX = (LoY & 0x0c) >> 2;
	    BY = (LoY & 0x30) >> 4;
	    LoY = (c & 0x1f) << 2;
	} else {	/* assume is LoY */
	    LoY = (c & 0x1f) << 2;
	    gotLoY = TRUE;
	}
    }
}	/* ends xy_param */

/* print string in escs */
void end_vector(int mymode)  {

    if (num_vector >= 0) {
	if (mymode == GRAPH) {
	    if (num_vector > 0)	/* draw */
	        fprintf(outfile,"%d %d %d v\n", num_vector,ncx,ncy);
	    else			/* move */
	        fprintf(outfile,"%d %d m\n",ncx,ncy);
	} else {		/* mode == PTPLT */
	    fprintf(outfile,"s\n");
	}
	num_vector = -1;
    }
}

/* move text cursor down one character */
void mov_down()  {

    if ((cy -= tsizey) < 0) {
	cy = YDIM - tsizey;
	leftmargin = leftmargin ? 0 : XDIM/2;
    }
    cx = leftmargin;
}

/* move text cursor one character to the right */
void mov_right()  {

    if ((cx += tsizex) > XDIM) {
	mov_down();
    }
}

/* process ASCII control chars in ALPHA mode */
int iscontrol(int c)  {
    int isctrl;

    isctrl = FALSE;
    switch ( c ) {	/* start of print control chars */
	case ( HT ):
	case ( SPACE ):
	    mov_right();
	    isctrl = TRUE;
	    break;

	case ( CR ):
	case ( LF ):
	    mov_down();
	    isctrl = TRUE;
	    break;

	case ( BS ):
	    if ((cx -= tsizex) < 0)
		cx = XDIM;
	    isctrl = TRUE;
	    break;

	case ( VT ):
	    if ((cy += tsizey) > YDIM)
		cy = 0;
	    isctrl = TRUE;
	    break;

	case ( FF ):	/* erase */
	    end_vector(oldmode);
	    if (pr_on_er) {
		fprintf(outfile, "NP\n");
		if (scale_factor != 1.0)
		fprintf(outfile,"%f %f scale\n", scale_factor, scale_factor);
	    }
	    pr_on_er = TRUE;
	    fprintf(outfile, "%d DP\n", tsizey);
	    cx = 0; cy = YDIM - tsizey;
	    isctrl = TRUE;
	    break;

	case ( BEL ):
	case ( SYN ):	/* padding character, ignore*/
	case ( NUL ):	/* padding character, ignore*/
	    isctrl = TRUE;
	    break;
	}	/* end of print control chars */
    return(isctrl);
}

/* set line width */
int decode_int(char **bufp)  {
    int intval=0;

    while (**bufp & 0x40) {	/* if 0x40 then high order digit */
	intval <<= 6;		/* 0x40 */
	intval += **bufp & 0x3f;	/* add in new digit */
	(*bufp)++;
    }
    intval <<= 4;		/* low order digit */
    intval += **bufp & 0x0f;
    if ((**bufp&0x10)==0)	/* 0x10 set for positive numbers */
	intval *= -1;
    (*bufp)++;
    return(intval);
}

/* convert to x,y coordinates in graph mode */
void escs_text(char *str, int lenstr)  {
    char c, *cp;

    fprintf(outfile,"gsave \n");
    if (rgb_all<0) {
	fprintf(outfile,"%d %d %d setrgbcolor \n",color[igc_text][0],
	    color[igc_text][1],color[igc_text][2]);
    }
    fprintf(outfile,"%f rotate\n(", angle);
    for (cp=str; cp<str+lenstr; cp++) {
	if (IsSpecial(c = (*cp)))
	    fprintf(outfile,"\\%c",c);
	else
	    fprintf(outfile,"%c",c);
    }
    fprintf(outfile,") show\ngrestore\n");
}

/* set the line width */
void setlinewidth(int linewidth, int widthscale)  {

    if (linewidth==0)
	if (widthscale==0)
		/* default narrow line from prologue file */
	    fprintf(outfile,"FZ \n");
	else {
		/* wide line scaled by command line option */
		/*    (linewidth arbitarily set at 1)    */
	    linewidth = 1 * widthscale;
	    fprintf(outfile,"%d setlinewidth \n",linewidth);
	}
    else	/* linewidth = 1 */
	if (widthscale==0)
		/* default wide line from prologue file */
	    fprintf(outfile,"DZ \n");
	else {
		/* wide line scaled by command line option */
		/*    (linewidth arbitarily set at 3)    */
	    linewidth = 3 * widthscale;
	    fprintf(outfile,"%d setlinewidth \n",linewidth);
	}
}

/* set the font (size) */
void setfont (int newfont)  {

    if ( !font_defined[newfont] ) {
	fprintf(outfile,"%s\n",font_defs[newfont]);
	font_defined[newfont] = TRUE;
    }
    if (newfont != font_num)
	fprintf(outfile, "%s setfont\n",fonts[newfont]);
    tsizex = xsize[newfont];
    tsizey = ysize[newfont];
    font_num = newfont;
}

/* Is it a PS special char? */
int IsSpecial (char d)  {
    static char v[] = "()<>{}[]/%\\";
    char *p ;

    p = v ;
    while( *p && (*p !=d)) ++p ;
    return (*p == d);
}
