DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T t

⟦45e83df26⟧ TextFile

    Length: 52084 (0xcb74)
    Types: TextFile
    Names: »term.c«

Derivation

└─⟦52210d11f⟧ Bits:30007239 EUUGD2: TeX 3 1992-12
    └─⟦c319c2751⟧ »unix3.0/TeX3.0.tar.Z« 
        └─⟦036c765ac⟧ 
            └─⟦this⟧ »TeX3.0/TeXcontrib/gnutex/term.c« 

TextFile

/*
 *
 *    G N U P L O T  --  term.c
 *
 *  Copyright (C) 1986 Colin Kelley, Thomas Williams
 *
 *  You may use this code as you wish if credit is given and this message
 *  is retained.
 *
 *  Please e-mail any useful additions to vu-vlsi!plot so they may be
 *  included in later releases.
 *
 *  This file should be edited with 4-column tabs!  (:set ts=4 sw=4 in vi)
 */
/*
 * Modifications for LaTeX and other support by David Kotz, 1988.
 * Department of Computer Science, Duke University, Durham, NC 27706.
 * Mail to dfk@cs.duke.edu.
 */
/*  modified 1/14/89 for Microsoft C5.1 by JDM (mcdonald@uxe.cso.uiuc.edu)
 */
/*
 * Modification for direct Imagen output (but retaining many of the
 * LaTeX extensions) by Paul E. McKenney, 1989.
 * Information Science and Technology Division, SRI International,
 * 333 Ravenswood Ave, Menlo Park, CA 94025.
 * Mail to mckenney@sri.com.
 */
/*
 * Modification for Fig code output by Micah Beck, 1989
 * Department of Computer Science, Cornell University
 */
#include <stdio.h>
#include "plot.h"

#define NICE_LINE		0
#define POINT_TYPES		6

#ifdef MSDOS
int PC_color = 7;
#include <dos.h>
#include <graph.h>
#endif

extern FILE *outfile;
extern BOOLEAN term_init;
extern int term;

extern BOOLEAN clipping;

extern char input_line[];
extern struct lexical_unit token[];
extern struct termentry term_tbl[];

#ifdef PC
static int pattern[] = {0xffff, 0x0f0f, 0xffff, 0x3333, 0x3f3f};

#ifdef CORONA
char screen[65535];
#endif /* CORONA */

int mask;
static int graphics_on = FALSE;
int startx, starty;

#define EGA_XMAX 640
#define EGA_YMAX 350

#define EGA_XLAST (EGA_XMAX - 1)
#define EGA_YLAST (EGA_YMAX - 1)

#define EGA_VCHAR 14
#define EGA_HCHAR 8
#define EGA_VTIC 5
#define EGA_HTIC 5


#define CGA_XMAX 640
#define CGA_YMAX 200

#define CGA_XLAST (CGA_XMAX - 1)
#define CGA_YLAST (CGA_YMAX - 1)

#define CGA_VCHAR 8
#define CGA_HCHAR 8
#define CGA_VTIC 3
#define CGA_HTIC 3

#ifdef CORONA
#define COR_XMAX 640
#define COR_YMAX 325

#define COR_XLAST (COR_XMAX - 1)
#define COR_YLAST (COR_YMAX - 1)

#define COR_VCHAR 13
#define COR_HCHAR 8
#define COR_VTIC 4
#define COR_HTIC 4
#endif /* CORONA */
#endif /* PC */

/*
 * general point routine
 */
line_and_point(x,y,number)
int x,y,number;
{
	/* temporary(?) kludge to allow terminals with bad linetypes 
		to make nice marks */

	(*term_tbl[term].linetype)(NICE_LINE);
	do_point(x,y,number);
}

do_point(x,y,number)
int x,y;
int number;
{
register struct termentry *t;
register int htic,vtic;

	t = &term_tbl[term];

    /* do just a DOT? */
    if (number == -1) {
	   (*t->move)(x,y);
	   (*t->vector)(x,y);
	   return;
    }

	number %= POINT_TYPES;
	htic = (t->h_tic/2);	/* should be in term_tbl[] in later version */
	vtic = (t->v_tic/2);	

	if (clipping && (x < t->h_tic || y < t->v_tic || x >= t->xmax-t->h_tic ||
		y >= t->ymax-t->v_tic) ) 
		return;				/* add clipping in later version !!! */

	switch(number) {
		case 0: /* do diamond */ 
				(*t->move)(x-htic,y);
				(*t->vector)(x,y-vtic);
				(*t->vector)(x+htic,y);
				(*t->vector)(x,y+vtic);
				(*t->vector)(x-htic,y);
				(*t->move)(x,y);
				(*t->vector)(x,y);
				break;
		case 1: /* do plus */ 
				(*t->move)(x-htic,y);
				(*t->vector)(x+htic,y);
				(*t->move)(x,y-vtic);
				(*t->vector)(x,y+vtic);
				(*t->move)(x,y); /* DFK */
				break;
		case 2: /* do box */ 
				(*t->move)(x-htic,y-vtic);
				(*t->vector)(x+htic,y-vtic);
				(*t->vector)(x+htic,y+vtic);
				(*t->vector)(x-htic,y+vtic);
				(*t->vector)(x-htic,y-vtic);
				(*t->move)(x,y);
				(*t->vector)(x,y);
				break;
		case 3: /* do X */ 
				(*t->move)(x-htic,y-vtic);
				(*t->vector)(x+htic,y+vtic);
				(*t->move)(x-htic,y+vtic);
				(*t->vector)(x+htic,y-vtic);
				(*t->move)(x,y); /* DFK */
				break;
		case 4: /* do triangle */ 
				(*t->move)(x,y+(4*vtic/3));
				(*t->vector)(x-(4*htic/3),y-(2*vtic/3));
				(*t->vector)(x+(4*htic/3),y-(2*vtic/3));
				(*t->vector)(x,y+(4*vtic/3));
				(*t->move)(x,y);
				(*t->vector)(x,y);
				break;
		case 5: /* do star */ 
				(*t->move)(x-htic,y);
				(*t->vector)(x+htic,y);
				(*t->move)(x,y-vtic);
				(*t->vector)(x,y+vtic);
				(*t->move)(x-htic,y-vtic);
				(*t->vector)(x+htic,y+vtic);
				(*t->move)(x-htic,y+vtic);
				(*t->vector)(x+htic,y-vtic);
				(*t->move)(x,y); /* DFK */
				break;
	}
}



#define AED_XMAX 768
#define AED_YMAX 575

#define AED_XLAST (AED_XMAX - 1)
#define AED_YLAST (AED_YMAX - 1)

#define AED_VCHAR	13
#define AED_HCHAR	8
#define AED_VTIC	8
#define AED_HTIC	7




#define HP75_XMAX 6000
#define HP75_YMAX 6000

#define HP75_XLAST (HP75_XMAX - 1)
#define HP75_YLAST (HP75_XMAX - 1)

/* HP75_VCHAR, HP75_HCHAR  are not used */
#define HP75_VCHAR	(HP75_YMAX/20)	
#define HP75_HCHAR	(HP75_XMAX/20)		
#define HP75_VTIC	(HP75_YMAX/70)		
#define HP75_HTIC	(HP75_XMAX/75)		




#define REGISXMAX 800             
#define REGISYMAX 440

#define REGISXLAST (REGISXMAX - 1)
#define REGISYLAST (REGISYMAX - 1)

#define REGISVCHAR		20  	
#define REGISHCHAR		8		
#define REGISVTIC		8
#define REGISHTIC		6



#define QMS_XMAX 9000
#define QMS_YMAX 6000

#define QMS_XLAST (QMS_XMAX - 1)
#define QMS_YLAST (QMS_YMAX - 1)

#define QMS_VCHAR		120
#define QMS_HCHAR		75
#define QMS_VTIC		70
#define QMS_HTIC		70




#define TEK40XMAX 1024
#define TEK40YMAX 780

#define TEK40XLAST (TEK40XMAX - 1)
#define TEK40YLAST (TEK40YMAX - 1)

#define TEK40VCHAR 	25
#define TEK40HCHAR		14
#define TEK40VTIC		11
#define TEK40HTIC		11	

#define HALFTEK40XMAX 780
#define HALFTEK40YMAX 512
#define HALFTEK40XMID 390
#define HALFTEK40YMID 256
#define HALFTEK40XLAST (HALFTEK40XMAX - 1)
#define HALFTEK40YLAST (HALFTEK40YMAX - 1)

#define HALFTEK40VCHAR 	25
#define HALFTEK40HCHAR		14
#define HALFTEK40VTIC		11
#define HALFTEK40HTIC		11	

#ifdef UNIXPLOT

#define UP_XMAX 4096
#define UP_YMAX 4096

#define UP_XLAST (UP_XMAX - 1)
#define UP_YLAST (UP_YMAX - 1)

#define UP_VCHAR (UP_YMAX/30)
#define UP_HCHAR (UP_XMAX/72)	/* just a guess--no way to know this! */
#define UP_VTIC (UP_YMAX/80)
#define UP_HTIC (UP_XMAX/80)

#endif /* UNIXPLOT */



#define TERMCOUNT (sizeof(term_tbl)/sizeof(struct termentry))

#ifdef PC

void PC_curloc(row,col)
int row, col;
{
union REGS rg;
        rg.h.ah = 2;
        rg.h.bh = 0;
        rg.h.dh = row;
        rg.h.dl = col;
        int86(16,&rg,&rg);
}

PC_lrput_text(row,str)
int row;
char str[];
{
	PC_curloc(23-row,78-strlen(str));
	/*PC_*/puts(str);
}

PC_ulput_text(row,str)
int row;
char str[];
{
	PC_curloc(row+1,2);
	/*PC_*/puts(str);
}

#ifdef CORONA
COR_init()
{
}

COR_graphics()
{
	graphics_on = TRUE;
	setmod(3);
	grinit(screen);
	grandtx();
}

COR_text()
{
	if (graphics_on) {
		graphics_on = FALSE;
		while (!kbhit())
			;
	}
	grreset();
	txonly();
	setmod(3);
}

COR_linetype(linetype)
{
	if (linetype > 2)
		linetype %= 3;
	mask = pattern[linetype+2];
}

COR_move(x,y)
{
	if (x < 0)
		startx = 0;
	else if (x > COR_XLAST)
		startx = COR_XLAST;
	else
		startx = x;

	if (y < 0)
		starty = 0;
	else if (y > COR_YLAST)
		starty = COR_YLAST;
	else
		starty = y;
}

COR_vector(x,y)
{
	if (x < 0)
		x = 0;
	else if (x > COR_XLAST)
		x = COR_XLAST;
	if (y < 0)
		y = 0;
	else if (y > COR_YLAST)
		y = COR_YLAST;

	Cor_line(startx,COR_YLAST-starty,x,COR_YLAST-y);
	startx = x;
	starty = y;
}

#define COR_lrput_text PC_lrput_text
#define COR_ulput_text PC_ulput_text

COR_reset()
{
}
#endif /* CORONA */


CGA_init()
{
	PC_color = 1;		/* monochrome */
}

CGA_graphics()
{
	graphics_on = TRUE;
	_setvideomode(_HRESBW);
}

CGA_text()
{
	if (graphics_on) {
		graphics_on = FALSE;
		while (!kbhit());
    	        _setvideomode(_DEFAULTMODE);
	}
}

CGA_linetype(linetype)
{
	if (linetype > 2)
		linetype %= 3;
        _setlinestyle(pattern[linetype+2]);
}

CGA_move(x,y)
{
	startx = x;
	starty = y;
}


CGA_vector(x,y)
{
        (void)_moveto(startx,CGA_YLAST-starty);
        (void)_lineto(x,CGA_YLAST-y);
	startx = x;
	starty = y;
}

#define CGA_lrput_text PC_lrput_text
#define CGA_ulput_text PC_ulput_text


CGA_reset()
{
}


EGA_init()
{
}

EGA_graphics()
{
	graphics_on = TRUE;
	_setvideomode(_ERESCOLOR);
}

EGA_text()
{
	PC_curloc(24,0);
	if (graphics_on) {
		graphics_on = FALSE;
		while (!kbhit())
			;
	}
}

EGA_linetype(linetype)
{
	static int c[] = {9, 8, 10, 11, 12, 13, 14, 15, 7, 5, 4, 3, 2, 6};
	PC_color = c[linetype+2];
}

EGA_move(x,y)
{
	startx = x;
	starty = y;
}


EGA_vector(x,y)
{
        (void)_setcolor(PC_color);
        (void)_moveto(startx,EGA_YLAST-starty);
        (void)_lineto(x,EGA_YLAST-y);
	startx = x;
	starty = y;
}

#define EGA_lrput_text PC_lrput_text
#define EGA_ulput_text PC_ulput_text


EGA_reset()
{
	_setvideomode(_DEFAULTMODE);
}
#endif /* PC */


#ifdef AED
AED_init()
{
	fprintf(outfile,
	"\033SEN3DDDN.SEC.7.SCT.0.1.80.80.90.SBC.0.AAV2.MOV.0.9.CHR.0.FFD");
/*   2            3     4                5     7    6       1
	1. Clear Screen
	2. Set Encoding
	3. Set Default Color
	4. Set Backround Color Table Entry
	5. Set Backround Color
	6. Move to Bottom Lefthand Corner
	7. Anti-Alias Vectors
*/
}


AED_graphics()
{
	fprintf(outfile,"\033FFD\033");
}


AED_text()
{
	fprintf(outfile,"\033MOV.0.9.SEC.7.XXX");
}



AED_linetype(linetype)
int linetype;
{
static int color[9+2] = { 7, 1, 6, 2, 3, 5, 1, 6, 2, 3, 5 };
static int type[9+2] = { 85, 85, 255, 255, 255, 255, 255,
					85, 85, 85, 85 };
	
	fprintf(outfile,"\033SLS%d.255.",type[linetype+2]);
	fprintf(outfile,"\033SEC%d.",color[linetype+2]);

}



AED_move(x,y)
int x,y;
{
	fprintf(outfile,"\033MOV%d.%d.",x,y);
}


AED_vector(x,y)
int x,y;
{
	fprintf(outfile,"\033DVA%d.%d.",x,y);
}


AED_lrput_text(row,str) /* write text to screen while still in graphics mode */
int row;
char str[];
{
	AED_move(AED_XMAX-((strlen(str)+2)*AED_HCHAR),AED_VTIC+AED_VCHAR*(row+1));
	fprintf(outfile,"\033XXX%s\033",str);
}


AED_ulput_text(row,str) /* write text to screen while still in graphics mode */
int row;
char str[];
{
	AED_move(AED_HTIC*2,AED_YMAX-AED_VTIC-AED_VCHAR*(row+1));
	fprintf(outfile,"\033XXX%s\033",str);
}


#define hxt (AED_HTIC/2)
#define hyt (AED_VTIC/2)

AED_reset()
{
	fprintf(outfile,"\033SCT0.1.0.0.0.SBC.0.FFD");
}

#endif /* AED */




#ifdef HP75

HP75_init()
{
	fprintf(outfile,
	"\033.Y;IN;\033.P1:SC0,%d,0,%d;\nRO90;IP;CS20;SI0.2137,0.2812;\n",
		HP75_XMAX,HP75_YMAX);
/*	 1      2  3       4             5    6  7
	1. turn on eavesdropping
	2. reset to power-up defaults
	3. enable XON/XOFF flow control
	4. set SCaling to 2000 x 2000
	5. rotate page 90 degrees
	6. ???
	7. set some character set stuff
*/
}


HP75_graphics()
{
	fputs("\033.Y",outfile);
/*         1
	1. enable eavesdropping
*/
}


HP75_text()
{
	fputs("NR;\033.Z",outfile);
/*         1  2
	1. go into 'view' mode
	2. disable plotter eavesdropping
*/
}


HP75_linetype(linetype)
int linetype;
{
	fprintf(outfile,"SP%d;\n",3+(linetype%8));
}


HP75_move(x,y)
int x,y;
{
	fprintf(outfile,"PU%d,%d;\n",x,y);
}


HP75_vector(x,y)
int x,y;
{
	fprintf(outfile,"PD%d,%d;\n",x,y);
}


HP75_lrput_text(row,str)
int row;
char str[];
{
	HP75_move(HP75_XMAX-HP75_HTIC*2,HP75_VTIC*2+HP75_VCHAR*row);
	fprintf(outfile,"LO17;LB%s\003\n",str);
}

HP75_ulput_text(row,str)
int row;
char str[];
{
	HP75_move(HP75_HTIC*2,HP75_YMAX-HP75_VTIC*2-HP75_VCHAR*row);
	fprintf(outfile,"LO13;LB%s\003\n",str);
}

HP75_reset()
{
}

#endif /* HP75 */



#ifdef REGIS

REGISinit()
{
	fprintf(outfile,"\033[r\033[24;1H");
/*                   1     2
	1. reset scrolling region
	2. locate cursor on bottom line
*/
}


REGISgraphics()
{
	fprintf(outfile,"\033[2J\033P1pS(C0)");
/*                   1      2      3
	1. clear screen
	2. enter ReGIS graphics
	3. turn off graphics diamond cursor
*/
}


REGIStext()
{
	fprintf(outfile,"\033[24;1H");
/*	                 1
 	1. locate cursor on last line of screen (and leave ReGIS)
*/
}


REGISlinetype(linetype)
int linetype;
{
	static int in_map[9+2] = {2,2,3,2,3,2,3,2,1,1,1};
	static int lt_map[9+2] = {1,4,1,1,4,4,6,6,1,4,6};
	fprintf(outfile,"W(I%d)",in_map[linetype+2]);
	fprintf(outfile,"W(P%d)",lt_map[linetype+2]);
}


REGISmove(x,y)
int x,y;
{
	fprintf(outfile,"P[%d,%d]v[]",x,REGISYLAST-y,x,REGISYLAST-y);
}


REGISvector(x,y)
int x,y;
{
	fprintf(outfile,"v[%d,%d]",x,REGISYLAST - y);
}


REGISlrput_text(row,str)
int row;
char *str;
{
	REGISmove(REGISXMAX-REGISHTIC-REGISHCHAR*(strlen(str)+3),
		REGISVTIC+REGISVCHAR*(row+1));
	(void) putc('T',outfile); (void) putc('\'',outfile);
	while (*str) {
		(void) putc(*str,outfile);
		if (*str == '\'')
				(void) putc('\'',outfile);	/* send out another one */
		str++;
	}
	(void) putc('\'',outfile);
}


REGISulput_text(row,str)
int row;
char *str;
{
	REGISmove(REGISVTIC,REGISYMAX-REGISVTIC*2-REGISVCHAR*row);
	(void) putc('T',outfile); (void) putc('\'',outfile);
	while (*str) {
		(void) putc(*str,outfile);
		if (*str == '\'')
				(void) putc('\'',outfile);	/* send out another one */
		str++;
	}
	(void) putc('\'',outfile);
}


REGISreset()
{
	fprintf(outfile,"\033[2J\033[24;1H");
}

#endif /* REGIS */




#ifdef QMS

QMS_init()
{
	fprintf(outfile,"^IOL\n");
}


QMS_graphics()
{
	fprintf(outfile,"^IGV\n");
}



QMS_text()
{
	fprintf(outfile,"^IGE\n^,");
}


QMS_linetype(linetype)
int linetype;
{
static int width[9+2] = {7, 3, 3, 3, 3, 5, 5, 5, 7, 7, 7};
static int type[9+2] =  {0, 0, 0, 2, 5, 0, 2, 5, 0, 2, 5};
	fprintf(outfile,"^PW%02d\n^V%x\n",width[linetype+2], type[linetype+2]);
}


QMS_move(x,y)
int x,y;
{
	fprintf(outfile,"^U%05d:%05d\n", 1000 + x, QMS_YLAST + 1000 - y);
}


QMS_vector(x2,y2)
int x2,y2;
{
	fprintf(outfile,"^D%05d:%05d\n", 1000 + x2, QMS_YLAST + 1000 - y2);
}


QMS_lrput_text(row,str)
int row;
char str[];
{
	QMS_move(QMS_XMAX-QMS_HTIC-QMS_HCHAR*(strlen(str)+1),
		QMS_VTIC+QMS_VCHAR*(row+1));
	fprintf(outfile,"^IGE\n%s\n^IGV\n",str);
}

QMS_ulput_text(row,str)
int row;
char str[];
{
	QMS_move(QMS_HTIC*2,QMS_YMAX-QMS_VTIC-QMS_VCHAR*(row+1));
	fprintf(outfile,"^IGE\n%s\n^IGV\n",str);
}


QMS_reset()
{
	fprintf(outfile,"^,\n");
}

#endif /* QMS */



#ifdef TEK

#define HX 0x20		/* bit pattern to OR over 5-bit data */
#define HY 0x20
#define LX 0x40
#define LY 0x60

#define LOWER5 31
#define UPPER5 (31<<5)


TEK40init()
{
}


TEK40graphics()
{
	fprintf(outfile,"\033\014");
/*                   1
	1. clear screen
*/
}


TEK40text()
{
	TEK40move(0,12);
	fprintf(outfile,"\037");
/*                   1
	1. into alphanumerics
*/
}


TEK40linetype(linetype)
int linetype;
{
}



TEK40move(x,y)
unsigned int x,y;
{
	(void) putc('\035', outfile);	/* into graphics */
	TEK40vector(x,y);
}


TEK40vector(x,y)
unsigned int x,y;
{
	(void) putc((HY | (y & UPPER5)>>5), outfile);
	(void) putc((LY | (y & LOWER5)), outfile);
	(void) putc((HX | (x & UPPER5)>>5), outfile);
	(void) putc((LX | (x & LOWER5)), outfile);
}


TEK40lrput_text(row,str)
unsigned int row;
char str[];
{
	TEK40move(TEK40XMAX - TEK40HTIC - TEK40HCHAR*(strlen(str)+1),
		TEK40VTIC + TEK40VCHAR*(row+1));
	fprintf(outfile,"\037%s\n",str);
}


TEK40ulput_text(row,str)
unsigned int row;
char str[];
{
	TEK40move(TEK40HTIC, TEK40YMAX - TEK40VTIC - TEK40VCHAR*(row+1));
	fprintf(outfile,"\037%s\n",str);
}


TEK40reset()
{
}

#endif /* TEK */

#ifdef HALFTEK

#define HALF_HX 0x20		/* bit pattern to OR over 5-bit data */
#define HALF_HY 0x20
#define HALF_LX 0x40
#define HALF_LY 0x60

#define HALF_LOWER5 31
#define HALF_UPPER5 (31<<5)


HALFTEK40init()
{
}


HALFTEK40graphics()
{
	fprintf(outfile,"\033\014");
/*                   1
	1. clear screen
*/
}


BOTTEK40text()
{
	BOTTEK40move(0,12);
	fprintf(outfile,"\037");
/*                   1
	1. into alphanumerics
*/
}

TOPTEK40text()
{
	TOPTEK40move(0,12);
	fprintf(outfile,"\037");
/*                   1
	1. into alphanumerics
*/
}


HALFTEK40linetype(linetype)
int linetype;
{
}



TOPTEK40move(x,y)
unsigned int x,y;
{
	(void) putc('\035', outfile);	/* into graphics */
	TOPTEK40vector(x,y);
}

BOTTEK40move(x,y)
unsigned int x,y;
{
	(void) putc('\035', outfile);	/* into graphics */
	BOTTEK40vector(x,y);
}


BOTTEK40vector(x,y)
unsigned int x,y;
{
	(void) putc((HALF_HY | (x & HALF_UPPER5)>>5), outfile);
	(void) putc((HALF_LY | (x & HALF_LOWER5)), outfile);
	(void) putc((HALF_HX | (((HALFTEK40YLAST-y)+HALFTEK40YMAX) & HALF_UPPER5)>>5), outfile);
	(void) putc((HALF_LX | (((HALFTEK40YLAST-y)+HALFTEK40YMAX) & HALF_LOWER5)), outfile);
}


TOPTEK40vector(x,y)
unsigned int x,y;
{
	(void) putc((HALF_HY | (x & HALF_UPPER5)>>5), outfile);
	(void) putc((HALF_LY | (x & HALF_LOWER5)), outfile);
	(void) putc((HALF_HX | (((HALFTEK40YMID-y)+HALFTEK40YMID) & HALF_UPPER5)>>5), outfile);
	(void) putc((HALF_LX | (((HALFTEK40YMID-y)+HALFTEK40YMID) & HALF_LOWER5)), outfile);
}

HALFTEK40lrput_text(row,str)
unsigned int row;
char str[];
{
}


HALFTEK40ulput_text(row,str)
unsigned int row;
char str[];
{
}


HALFTEK40reset()
{
}

#endif /* HALFTEK */

#ifdef UNIXPLOT
UP_init()
{
	openpl();
	space(0, 0, UP_XMAX, UP_YMAX);
}


UP_graphics()
{
	erase();
}


UP_text()
{
}


UP_linetype(linetype)
int linetype;
{
static char *lt[] = {"solid", "longdashed", "solid", "dotted", "shortdashed",
	"dotdashed", "longdashed"};

	if (linetype >= 5)
		linetype %= 5;
	linemod(lt[linetype+2]);
}


UP_move(x,y)
unsigned int x,y;
{
	move(x,y);
}


UP_vector(x,y)
unsigned int x,y;
{
	cont(x,y);
}


UP_lrput_text(row,str)
unsigned int row;
char str[];
{
	move(UP_XMAX - UP_HTIC - UP_HCHAR*(strlen(str)+1),
		UP_VTIC + UP_VCHAR*(row+1));
	label(str);
}


UP_ulput_text(row,str)
unsigned int row;
char str[];
{
	UP_move(UP_HTIC, UP_YMAX - UP_VTIC - UP_VCHAR*(row+1));
	label(str);
}

UP_reset()
{
	closepl();
}

#endif /* UNIXPLOT */

#ifdef LATEX

#define LATEX_PTS_PER_INCH (72.27)
#define LATEX_UNIT (.01)		/* points */

#define LATEX_HTIC (5./LATEX_UNIT)
#define LATEX_VTIC (5./LATEX_UNIT)
#define LATEX_HCHAR (4./LATEX_UNIT)
#define LATEX_VCHAR (12./LATEX_UNIT)

#define LATEX_TICSIZ 101		/* no more than 100 chars in a tic label */

#define LATEX_FORMAT "$%g$"	/* default format for tic marks */

static long LATEX_posx;
static long LATEX_posy;
static BOOLEAN LATEX_inplot;
static long LATEX_xmax;
static long LATEX_ymax;
static char *LATEX_xlabel = NULL;

static LATEX_endplot();
extern char *malloc();

#define sign(x) ((x) >= 0 ? 1 : -1)
#define abs(x) ((x) >= 0 ? (x) : -(x))
#define max(a,b) ((a) > (b) ? (a) : (b))
#define min(a,b) ((a) < (b) ? (a) : (b))

/* Default line-drawing character */
#define LATEX_DOT_SPACING (2.0/LATEX_UNIT)
#define LATEX_DOT "\\circle*{1}"
#define LATEX_TINY_DOT "{\\sevrm $\\cdot$}"

static int LATEX_type;		/* negative types use real lines */
static struct st_entry *LATEX_style = NULL; /* NULL => use default styles */
static LATEX_seq_pos;		/* position in sequence */

#define LATEX_POINT_TYPES POINT_TYPES /* we use the same points */
static char *LATEX_points[] = {
    "$\\Diamond$", "$+$", "$\\Box$", "$\\times$", "$\\triangle$", "$\\star$"
};

LATEX_init()
{
    LATEX_posx = LATEX_posy = 0;
    LATEX_inplot = FALSE;
    LATEX_style = NULL;
    LATEX_type = -1;
    
    fprintf(outfile, "\\setlength{\\unitlength}{%fpt}\n", LATEX_UNIT);
}


LATEX_graphics(xmax, ymax, t, xlabel, ylabel, yskip, title)
	float xmax, ymax;		/* in inches */
	struct termentry *t;
	char *xlabel;			/* x-axis label */
	char *ylabel;			/* y-axis label */
	int yskip;			/* y-axis label skip factor */
	char *title;			/* plot title */
{
    /* computed margin of plot */
    long bot_margin, left_margin, top_margin, right_margin;

    if (LATEX_inplot) 
	 LATEX_endplot();

    /* Convert inches to points to coordinates */
    LATEX_xmax = (long) (xmax * LATEX_PTS_PER_INCH / LATEX_UNIT + 0.5);
    LATEX_ymax = (long) (ymax * LATEX_PTS_PER_INCH / LATEX_UNIT + 0.5);

    /* store these away for the use of plotting routines */
    t->xmax = LATEX_xmax;
    t->ymax = LATEX_ymax;

    /* Compute the margins, based on the positioning of tick labels */
    left_margin = LATEX_VTIC + 2*LATEX_HCHAR;
    right_margin = 0;
    bot_margin = LATEX_HTIC + LATEX_VCHAR;
    top_margin = LATEX_VTIC;

    /* Construct the image from the labels and the plot, as a table */
    fprintf(outfile, "\\begin{tabular}{r@{}c}\n");
    if (title && *title != '\0')
	 fprintf(outfile, " & \\shortstack{%s} \\\\ \n", title);
    if (ylabel && *ylabel != '\0') {
	   fprintf(outfile, "\\raisebox{%gpt}{\\begin{tabular}[c]{@{}c@{}}\n", 
			 ((float)(LATEX_ymax-1) / 2. + bot_margin) * LATEX_UNIT);
	   fprintf(outfile, "%s\n", ylabel);
	   fprintf(outfile, "\\end{tabular} \\hspace*{%dem}}\n", yskip);
    }
    /* Define the plot, computing the total size and the lower-left corner*/
    fprintf(outfile, " & \\begin{picture}(%ld,%ld)(%ld,%ld)\n", 
		  (long)(LATEX_xmax + left_margin + right_margin),
		  (long)(LATEX_ymax + bot_margin + top_margin),
		  (long)(-left_margin), (long)(-bot_margin));
    LATEX_inplot = TRUE;

    LATEX_posx = LATEX_posy = 0;

    /* Remember x label for use after plot is defined */
    if (xlabel && *xlabel != '\0') {
	   LATEX_xlabel = malloc(strlen(xlabel)+1);
	   strcpy(LATEX_xlabel, xlabel);
    } else
	 LATEX_xlabel = NULL;
}


static 
LATEX_endplot()
{
    /* Complete the plot */
    fprintf(outfile, "\\end{picture}\n");

    /* Now finish that line of the table and do the x label */
    if (LATEX_xlabel) {
	   fprintf(outfile, "\\\\\n");
	   fprintf(outfile, " & \\shortstack{%s}\n", LATEX_xlabel);
	   free(LATEX_xlabel);
    }
    fprintf(outfile, "\\end{tabular}\n\n");
}


LATEX_text()
{
}


LATEX_linetype(linetype)
int linetype;
{
    LATEX_type = linetype;
    LATEX_style = NULL;
}


LATEX_plotstyle(stp)
struct st_entry *stp;
{
    LATEX_style = stp;
    LATEX_seq_pos = 0;
}


LATEX_move(x,y)
unsigned int x,y;
{
    LATEX_posx = x;
    LATEX_posy = y;
}


LATEX_point(x,y, number, special)		/* version of line_and_point */
unsigned int x,y;
int number;				/* type of point */
char *special;				/* overrides number as the character to use */
{
    if (clipping && (x < LATEX_HTIC || y < LATEX_VTIC || 
				 x >= LATEX_xmax-LATEX_HTIC ||
				 y >= LATEX_ymax-LATEX_VTIC) ) 
	 return;

    LATEX_move(x,y);
    
    /* Print the special character, if given, otherwise use the one */
    /* defined by 'number'; number < 0 means to use a dot, otherwise */
    /* one of the defined points. */
    fprintf(outfile, "\\put(%d,%d){\\makebox(0,0){%s}}\n", x, y, 
		  special != NULL ? special :
		    (number < 0 ? LATEX_TINY_DOT
			: LATEX_points[number % LATEX_POINT_TYPES]));
}


LATEX_vector(ux,uy)
unsigned int ux,uy;
{
    int x=ux, y=uy;

    /* Negative linestyles are straight lines for frame and axes. */
    /* These are vertical and horizontal lines only. */
    if (LATEX_type < 0) {
	   if (x == LATEX_posx) {		/* vertical */
		  fprintf(outfile, "\\put(%ld,%ld){\\line(0,%ld){%ld}}\n",
				LATEX_posx, LATEX_posy, 
				sign((long)y - LATEX_posy), abs((long)y - LATEX_posy));
	   } else if (y == LATEX_posy) {		/* horizontal */
		  fprintf(outfile, "\\put(%ld,%ld){\\line(%ld,0){%ld}}\n",
				LATEX_posx, LATEX_posy, 
				sign((long)x - LATEX_posx), abs((long)x - LATEX_posx));
	   }
    } else {				/* drawing real curves */
	   long deltax = x - LATEX_posx;
	   long deltay = y - LATEX_posy;
	   long n = max(abs(deltax), abs(deltay)) 
		/ (LATEX_style ? LATEX_style->st_spacing/LATEX_UNIT : LATEX_DOT_SPACING) + 1;
	   float dx = (float)deltax / n;
	   float dy = (float)deltay / n;
	   float curx = LATEX_posx, cury = LATEX_posy;
	   BOOLEAN first = TRUE;

	   while (curx != x || cury != y) {
		  if (LATEX_style)
		    if (!first)
			 LATEX_seq_pos = (LATEX_seq_pos + 1) % LATEX_style->st_length;
		    else
			 first = FALSE;

		  fprintf(outfile, "\\put(%ld,%ld){%s}\n", 
				(long)(curx + .5), (long)(cury + .5), 
				LATEX_style ? LATEX_style->st_seq[LATEX_seq_pos]
				            : LATEX_DOT);

		  if (abs(dx) > abs(x - curx))
		    curx = x;
		  else
		    curx += dx;

		  if (abs(dy) > abs(y - cury))
		    cury = y;
		  else
		    cury += dy;
	   }
    }

    LATEX_posx = x;
    LATEX_posy = y;
}

LATEX_lrput_text(row,str)
unsigned int row;
char str[];
{
	fprintf(outfile, "\\put(%ld,%ld){$%s$}\n",
		   (long)(LATEX_xmax - 2*LATEX_HTIC - LATEX_HCHAR*(strlen(str)+1)),
		   (long)(LATEX_VTIC + 3 + LATEX_VCHAR*row),
		   str);
}


LATEX_ulput_text(row,str)
unsigned int row;
char str[];
{
	fprintf(outfile, "\\put(%ld,%ld){%s}\n",
		   (long)(LATEX_HTIC+3),
		   (long)(LATEX_ymax - LATEX_VTIC - LATEX_VCHAR*(row+1)),
		   str);
}

LATEX_xyput_text(x, y, str, pos, length, dx, dy)
unsigned int x,y;			/* reference point of string */
char str[];				/* the text */
char pos[];				/* for optional [pos] to \makebox */
unsigned int length;		/* optional arrow length */
int dx, dy;				/* optional slopes for arrow */
{
    if (!LATEX_inplot)
	 return;

    if (pos != NULL && *pos != NULL) {
	   fprintf(outfile, "\\put(%d,%d){\\makebox(0,0)[%s]{%s}",
			 x, y, pos, str);
    } else {
	   fprintf(outfile, "\\put(%d,%d){\\makebox(0,0){%s}",
			 x, y, str);
    }

    /* optional arrow */
    if (length != 0 && pos != NULL && *pos != NULL) {
	   if (dx == 0 && dy == 0) { /* determine slope from pos */
 		  if (INDEX(pos, 'l') != NULL) dx = -1;
 		  if (INDEX(pos, 'r') != NULL) dx = 1;
 		  if (INDEX(pos, 't') != NULL) dy = 1;
 		  if (INDEX(pos, 'b') != NULL) dy = -1;
	   }
	   fprintf(outfile, "\\vector(%d,%d){%u}\n", dx, dy, length);
    }

    fprintf(outfile, "}\n");	/* finish the \put */
}

LATEX_key(x, y, style, names)
	unsigned int x,y;
	int style[];
	char *names[];
{
    int curve;
    int pcount = 0;			/* counter of point-like styles */
    char *point;			/* string representing type */
    static char *LATEX_key_point();
    BOOLEAN first = TRUE;

    /* Plot all of the curves in a shortstack */
    /* Each curve has two boxes, the left right-justified,  */
    /* the right left-justified, so they line up at the middle. */
    fprintf(outfile, "\\put(%d,%d){\\shortstack{\n", x, y);
    for (curve = 0; names[curve] != NULL; curve++) {
	   /* Get a string that describes this style */
	   point = LATEX_key_point(style[curve], &pcount);

	   /* But don't print it out if the description is empty */
	   if (*names[curve] != '\0') {
		  if (!first) 
		    fprintf(outfile, "\\\\\n");
		  else
		    first = FALSE;
		  fprintf(outfile, " \\makebox[0pt][r]{%s}", point);
		  fprintf(outfile, " \\makebox[0pt][l]{ %s}", names[curve]);
	   }
    }
    fprintf(outfile, "\n}}\n");
}

static 
char *					/* pointer to static storage */
LATEX_key_point(style, pcount)
	int style;			/* style number to describe */
	int *pcount;			/* running counter of point-like styles */
{
    static char s[MAX_ID_LEN]; /* the string representing the style */
    struct st_entry *stp;	/* the style description of this style */
    int seq;				/* sequence in a style */
    int p;				/* loop variable */
    extern struct st_entry st[]; /* all style descriptions */

    switch(style) {
	   case IMPULSES: {
		  strcpy(s, "|"); /* hack */
		  break;
	   }
	   case LINES: {
		  *s = NULL;
		  for (p=0; p < 5; p++)
		    sprintf(s, "%s%s\\hspace{%gpt}", 
				  s, LATEX_DOT, LATEX_DOT_SPACING * LATEX_UNIT);
		  break;
	   }
	   case POINTS: {	/* hack */
		  strcpy(s, LATEX_points[(*pcount)++ % LATEX_POINT_TYPES]);
		  break;
	   }
	   case DOTS: {
		  strcpy(s, LATEX_TINY_DOT);
		  break;
	   }
	   case LINESPOINTS: {
		  *s = NULL;
		  for (p=0; p < 5; p++) {
			 sprintf(s, "%s%s\\hspace{%gpt}", 
				    s, LATEX_DOT, LATEX_DOT_SPACING * LATEX_UNIT);
			 if (p == 2)
			   strcat(s, LATEX_points[(*pcount)++ % LATEX_POINT_TYPES]);
		  }
		  break;
	   }
	   default: {
		  *s = NULL;
		  /* Plot points if the style has a line pattern */
		  stp = &(st[style]);
		  if (stp->st_length > 0) {
			 for (p=0, seq=0; p < 5; p++) {
				sprintf(s, "%s%s\\hspace{%gpt}", 
					   s, stp->st_seq[seq], stp->st_spacing); 
				seq = (seq + 1) % stp->st_length;
				if (p == 2 && stp->st_point != NULL) 
				  strcat(s, stp->st_point);
			 }
		  } else {		  
			 /* and plot the data point if the style has that */
			 if (stp->st_point != NULL) 
			   strcat(s, stp->st_point);
		  }
		  break;
	   }
    }

    return (s);
}

LATEX_xtick_text(x, number, format)
unsigned int x;			/* place to put on axis */
double number;				/* the number to be written at that tick */
char *format;
{
    char mark[LATEX_TICSIZ];

    if (*format == '\0')
	 format = LATEX_FORMAT;
    sprintf(mark, format, number);
    fprintf(outfile, "\\put(%ld,%ld){\\makebox(0,0)[t]{%s}}\n",
		  (long)x, (long)(-LATEX_HTIC), mark);
}

LATEX_ytick_text(y, number, format)
unsigned int y;			/* place to put on axis */
double number;				/* the number to be written at that tick */
char *format;
{
    char mark[LATEX_TICSIZ];

    if (*format == '\0')
	 format = LATEX_FORMAT;
    sprintf(mark, format, number);
    fprintf(outfile, "\\put(%ld,%ld){\\makebox(0,0)[r]{%s}}\n",
		  (long)(-LATEX_VTIC), (long)y, mark);
}


LATEX_reset()
{
    if (LATEX_inplot) {
	   LATEX_endplot();
	   LATEX_inplot = FALSE;
    }
    LATEX_posx = LATEX_posy = 0;
}

#endif /* LATEX */

#ifdef FIG

#include "object.h"			/* from the TransFig distribution */

#ifndef FIG_RES
/* Must be 80 for the Fig editor, but may be increased if used 
 * only by TransFig filters
 */
#define FIG_RES		80
#endif

#define FIG_COORD_SYS	2
#define FIG_MAGIC	"#FIG 1.4-TFX"

#define FIG_HTIC	5
#define FIG_VTIC	5
#define FIG_HCHAR	8
#define FIG_VCHAR	16

#define FIG_TICSIZ 101		/* no more than 100 chars in a tic label */

#define FIG_FORMAT "%g"		/* default format for tic marks */


static long FIG_xbase = FIG_RES/2;
static long FIG_ybase = FIG_RES/2;

static long FIG_posx;
static long FIG_posy;
static BOOLEAN FIG_inplot;
static long FIG_xmax;
static long FIG_ymax;

static FIG_endplot();
extern char *malloc();

#define sign(x) ((x) >= 0 ? 1 : -1)
#define abs(x) ((x) >= 0 ? (x) : -(x))
#define max(a,b) ((a) > (b) ? (a) : (b))
#define min(a,b) ((a) < (b) ? (a) : (b))

static int FIG_type;		/* negative types use real lines */
static struct st_entry *FIG_style = NULL; /* NULL => use default styles */
static FIG_seq_pos;		/* position in sequence */

#define FIG_POINT_TYPES POINT_TYPES /* we use the same points */

FIG_init()
{
    FIG_posx = FIG_posy = 0;
    FIG_inplot = FALSE;
    FIG_style = NULL;
    FIG_type = -1;

    fprintf(outfile, "%s\n", FIG_MAGIC);
    fprintf(outfile, "%d %d\n", FIG_RES, FIG_COORD_SYS);
}


FIG_graphics(xmax, ymax, t, xlabel, ylabel, yskip, title)
	float xmax, ymax;		/* in inches */
	struct termentry *t;
	char *xlabel;			/* x-axis label */
	char *ylabel;			/* y-axis label */
	int yskip;			/* y-axis label skip factor */
	char *title;			/* plot title */
{
    /* computed margin of plot */
    long bot_margin, left_margin, top_margin, right_margin;

    if (FIG_inplot) 
	 FIG_endplot();

    /* Convert inches to points to coordinates */
    FIG_xmax = (long) (xmax * FIG_RES + 0.5);
    FIG_ymax = (long) (ymax * FIG_RES + 0.5);

    /* store these away for the use of plotting routines */
    t->xmax = FIG_xmax;
    t->ymax = FIG_ymax;

    /* Compute the margins, based on the positioning of tick labels */
    left_margin = FIG_VTIC + 4*FIG_HCHAR;
    right_margin = 0;
    bot_margin = FIG_HTIC + FIG_VCHAR;
    top_margin = FIG_VTIC;

    FIG_xbase += left_margin;
    FIG_ybase += top_margin;

    /* Place the title and labels */

    if (ylabel && *ylabel != '\0') {
        FIG_xbase += (strlen(ylabel)+1)*FIG_HCHAR;
	FIG_xy_text(-left_margin, (FIG_ymax-1)/2, ylabel, "r");
    }

    if (title && *title != '\0')
	FIG_xy_text((FIG_xmax-1)/2, FIG_ymax + top_margin, title, "cb");

    if (xlabel && *xlabel != '\0')
	FIG_xy_text((FIG_xmax-1)/2, -bot_margin, xlabel, "tc");

    FIG_inplot = TRUE;

    FIG_posx = FIG_posy = 0;
}


static 
FIG_endplot()
{
}


FIG_text()
{
}


FIG_linetype(linetype)
int linetype;
{
    FIG_type = linetype;
    FIG_style = NULL;
}


FIG_plotstyle(stp)
struct st_entry *stp;
{
    FIG_style = stp;
    FIG_seq_pos = 0;
}


FIG_move(x,y)
unsigned int x,y;
{
    FIG_posx = x;
    FIG_posy = y;
}

FIG_vector(ux,uy)
unsigned int ux,uy;
{
    	int x=ux, y=uy;

  	fprintf(outfile, "%d %d %d %d %d %d %d %d %6.3f  %d %d\n",
	 	O_POLYLINE, T_POLYLINE,
	 	SOLID_LINE, 1, DEFAULT, DEFAULT, DEFAULT, DEFAULT, 0.0,
	 	0, 0);
  	fprintf(outfile, "%d %d %d %d 9999 9999\n",
	 	FIG_xbase+FIG_posx, FIG_ybase+FIG_ymax-FIG_posy,
		FIG_xbase+x, FIG_ybase+FIG_ymax-y);

	FIG_posx = x;
    	FIG_posy = y;
}

FIG_lrput_text(row,str)
unsigned int row;
char str[];
{
     FIG_xy_text(FIG_xmax - 2*FIG_HTIC - FIG_HCHAR*(strlen(str)+1),
	FIG_VTIC + FIG_VCHAR*row,
        str, NULL);
}


FIG_ulput_text(row,str)
unsigned int row;
char str[];
{
     FIG_xy_text(FIG_HTIC,
	FIG_ymax - FIG_VTIC - FIG_VCHAR*(row+1), str, NULL);
}

FIG_xyput_text(x, y, str, pos, length, dx, dy)
unsigned int x,y;			/* reference point of string */
char str[];				/* the text */
char pos[];				/* for optional [pos] to \makebox */
unsigned int length;		/* optional arrow length */
int dx, dy;				/* optional slopes for arrow */
{
    if (!FIG_inplot)
	 return;

   FIG_xy_text(x, y, str, pos);

    /* optional arrow */
    if (length != 0 && pos != NULL && *pos != NULL) {
	   if (dx == 0 && dy == 0) { /* determine slope from pos */
 		  if (INDEX(pos, 'l') != NULL) dx = -1;
 		  if (INDEX(pos, 'r') != NULL) dx = 1;
 		  if (INDEX(pos, 't') != NULL) dy = 1;
 		  if (INDEX(pos, 'b') != NULL) dy = -1;
	   }
  	fprintf(outfile, "%d %d %d %d %d %d %d %d %6.3f  %d %d\n",
	 	O_POLYLINE, T_POLYLINE,
	 	SOLID_LINE, 1, DEFAULT, DEFAULT, DEFAULT, DEFAULT, 0.0,
	 	1, 0);
	fprintf(outfile, "%d %d %d %d %d\n",
		DEFAULT, DEFAULT, DEFAULT, 4, 8);
  	fprintf(outfile, "%d %d %d %d 9999 9999\n",
	 	x, y, x+dx, y+dy);
    }
}

/* internally called, just dumps out string */
FIG_xy_text(x, y, str, pos)
long x, y;
char *str, *pos;
{
    int j = T_CENTER_JUSTIFIED;

    y = y - FIG_VCHAR/2;
    if (pos != NULL) {
      if (INDEX(pos, 'l') != NULL) j = T_LEFT_JUSTIFIED;
      if (INDEX(pos, 'r') != NULL) j = T_RIGHT_JUSTIFIED;
      if (INDEX(pos, 't') != NULL) y = y - FIG_VCHAR/2;
      if (INDEX(pos, 'b') != NULL) y = y + FIG_VCHAR/2;
    }
    fprintf(outfile, "%d %d %d %d %d %d %d %6.3f %d %d %d %d %d %s\01\n",
        O_TEXT, j,
        DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, 0.0, DEFAULT,
    	16, 8*strlen(str), FIG_xbase+x, FIG_ybase+FIG_ymax-y, str);
}

FIG_key(x, y, style, names)
	unsigned int x,y;
	int style[];
	char *names[];
{
/* Not for now... */
}

static 
char *					/* pointer to static storage */
FIG_key_point(style, pcount)
	int style;			/* style number to describe */
	int *pcount;			/* running counter of point-like styles */
{
/* Not for now... */
}

FIG_xtick_text(x, number, format)
unsigned int x;			/* place to put on axis */
double number;			/* the number to be written at that tick */
char *format;
{
    char mark[FIG_TICSIZ];

    if (*format == '\0')
	 format = FIG_FORMAT;
    sprintf(mark, format, number);
    FIG_xy_text(x, -FIG_HTIC, mark, "t");
}

FIG_ytick_text(y, number, format)
unsigned int y;			/* place to put on axis */
double number;			/* the number to be written at that tick */
char *format;
{
    char mark[FIG_TICSIZ];

    if (*format == '\0')
	 format = FIG_FORMAT;
    sprintf(mark, format, number);
    FIG_xy_text(-FIG_VTIC, y, mark, "r");
}


FIG_reset()
{
    if (FIG_inplot) {
	   FIG_endplot();
	   FIG_inplot = FALSE;
    }
    FIG_posx = FIG_posy = 0;
}

#endif /* FIG */

#ifdef IMAGEN

#include "imPcodes.h"

#define IMAGEN_PTS_PER_INCH (300)
#define IMAGEN_UNIT (.01)		/* points */

#define IMAGEN_HTIC 20
#define IMAGEN_VTIC 20
#define IMAGEN_HCHAR (4./IMAGEN_UNIT)
#define IMAGEN_VCHAR (12./IMAGEN_UNIT)

#define IMAGEN_TICSIZ 101	/* no more than 100 chars in a tic label */

#define IMAGEN_FORMAT "%g"	/* default tick mark format */

static int IMAGEN_orgx;		/* absolute-pixel-ORIgin of graph.	*/
static int IMAGEN_orgy;
static int IMAGEN_posx;		/* current drawing position (lines).	*/
static int IMAGEN_posy;
static int IMAGEN_inplot;
static int IMAGEN_xmax;		/* width of graph in pixels.		*/
static int IMAGEN_ymax;		/* height of graph in pixels.		*/
static int IMAGEN_hchar;	/* Height of CHAR in current font.	*/
static int IMAGEN_wchar;	/* Width of CHAR in current font.	*/
static int IMAGEN_blofs;	/* BaseLine OFfSet from bounding box.	*/
static int IMAGEN_rotated = -1;	/* text printing is ROTATED (y-axis label) */

static int IMAGEN_titlefsz = 15;
static int IMAGEN_axisfsz = 12;
static int IMAGEN_labelfsz = 10;
static int IMAGEN_tickfsz = 9;
static int IMAGEN_cursize = -1; /* pointer to one of above.		*/

static IMAGEN_endplot();
extern char *malloc();

#ifndef sign
#define sign(x) ((x) >= 0 ? 1 : -1)
#define abs(x) ((x) >= 0 ? (x) : -(x))
#define max(a,b) ((a) > (b) ? (a) : (b))
#define min(a,b) ((a) < (b) ? (a) : (b))
#endif /* sign */

/* Default line-drawing character */
#define IMAGEN_DOT_SPACING (2.0/IMAGEN_UNIT)

static int IMAGEN_type;		/* negative types use real lines */
static struct st_entry *IMAGEN_style = NULL; /* NULL => use default styles */
static IMAGEN_seq_pos;		/* position in sequence */

IMAGEN_init()
{
    IMAGEN_posx = IMAGEN_posy = 0;
    IMAGEN_inplot = FALSE;
    IMAGEN_style = NULL;
    IMAGEN_type = -1;

	IMAGEN_rotated = -1;

	fputs("@document(language impress)", outfile);
	putc(imP_SET_HV_SYSTEM, outfile);
	  putc((3<<3)|5, outfile);
	putc(imP_SET_ADV_DIRS, outfile); /* up and to the right, landscape. */
	  putc(7, outfile);
	IMAGEN_createfamily("cour06",  6);
	IMAGEN_createfamily("cour07",  7);
	IMAGEN_createfamily("cour08",  8);
	IMAGEN_createfamily("cour09",  9);
	IMAGEN_createfamily("cour10", 10);
	IMAGEN_createfamily("cour12", 12);
	IMAGEN_createfamily("cour14", 14);
	IMAGEN_createfamily("cour15", 15);
	IMAGEN_setfont(IMAGEN_titlefsz);
	IMAGEN_unrotate();
	putc(imP_SET_ABS_H, outfile);
	  IMAGEN_putwd(0);
	putc(imP_SET_ABS_V, outfile);
	  IMAGEN_putwd(0);
}
IMAGEN_putwd(w)
{
	putc(w>>8, outfile);
	putc(w, outfile);
}
IMAGEN_createfamily(c, sz)

	char		*c;
	int		sz;

	{
	putc(imP_CREATE_FAMILY_TABLE, outfile);
	  putc(sz, outfile);
	  putc(1, outfile);
	  putc(0, outfile);
	  fputs(c, outfile);
	  putc(0, outfile);
	}
IMAGEN_setfont(sz) int sz;
{
	if (IMAGEN_cursize == sz)
		return;
	IMAGEN_hchar = sz * 5;
	IMAGEN_wchar = IMAGEN_hchar / 2;
	IMAGEN_blofs = IMAGEN_hchar / 3;
	putc(imP_SET_FAMILY, outfile);
	  putc(sz, outfile);
	putc(imP_SET_SP, outfile);
	  IMAGEN_putwd(IMAGEN_wchar);
	putc(imP_SET_IL, outfile);
	  IMAGEN_putwd(IMAGEN_hchar);
	IMAGEN_cursize = sz;
}


IMAGEN_graphics(xmax, ymax, t, xlabel, ylabel, yskip, title)
	float xmax, ymax;		/* in inches */
	struct termentry *t;
	char *xlabel;			/* x-axis label */
	char *ylabel;			/* y-axis label */
	int yskip;			/* y-axis label skip factor */
	char *title;			/* plot title */
{
    int	h, w;
    char *s;

    if (IMAGEN_inplot) 
	 IMAGEN_newpage();
    IMAGEN_inplot = TRUE;

    /* Convert inches to points to coordinates */
    IMAGEN_xmax = (int) (xmax * IMAGEN_PTS_PER_INCH);
    IMAGEN_ymax = (int) (ymax * IMAGEN_PTS_PER_INCH);
    IMAGEN_orgx = ((int) (11.0 - xmax)) * IMAGEN_PTS_PER_INCH / 2;
    IMAGEN_orgy = ((int) (8.5 - ymax)) * IMAGEN_PTS_PER_INCH / 2;

    /* store these away for the use of plotting routines */
    t->xmax = IMAGEN_xmax;
    t->ymax = IMAGEN_ymax;

    /* Construct the image from the labels and the plot, as a table */

    if (title && *title != '\0')
	 {
	 IMAGEN_unrotate();
	 IMAGEN_setfont(IMAGEN_titlefsz);
	 IMAGEN_xy_text(IMAGEN_xmax / 2,
			IMAGEN_ymax + 2 * IMAGEN_hchar,
			title, "b");
	 }
    if (ylabel && *ylabel != '\0') {
	   IMAGEN_rotate();
	   IMAGEN_setfont(IMAGEN_axisfsz);
	   IMAGEN_xy_text((-yskip - 3) * IMAGEN_wchar,
			  IMAGEN_ymax / 2,
			  ylabel, "r");
    }
    if (xlabel && *xlabel != '\0') {
	    IMAGEN_unrotate();
	    IMAGEN_setfont(IMAGEN_axisfsz);
	    IMAGEN_xy_text(IMAGEN_xmax / 2,
			   -2 * IMAGEN_hchar,
			   xlabel, "t");
    }

    IMAGEN_move(0, 0);

}


static 
IMAGEN_newpage()
{
    putc(imP_ENDPAGE, outfile);
}

static 
IMAGEN_endplot()
{
    putc(imP_EOF, outfile);
}


IMAGEN_text()
{
}


IMAGEN_linetype(linetype)
int linetype;
{
	static int lastlinetype = -1;

	IMAGEN_type = linetype;
	if (linetype < 0)
		linetype = -linetype;
	else
		linetype = 1;
	if (lastlinetype == linetype)
		return;
	lastlinetype = linetype;
	putc(imP_SET_PEN, outfile);
	  putc(linetype, outfile);
	IMAGEN_style = NULL;
}


IMAGEN_plotstyle(stp)
struct st_entry *stp;
{
    IMAGEN_style = stp;
    IMAGEN_seq_pos = 0;
}


IMAGEN_move(x,y)
unsigned int x,y;
{
    IMAGEN_posx = x;
    IMAGEN_posy = y;
}

IMAGEN_vector(ux,uy)
unsigned int ux,uy;
{
    int x=ux, y=uy;

    /* Create path.							*/

    putc(imP_CREATE_PATH, outfile);
      IMAGEN_putwd(2);
      IMAGEN_putwd(IMAGEN_posx + IMAGEN_orgx);
      IMAGEN_putwd(IMAGEN_posy + IMAGEN_orgy);
      IMAGEN_putwd(ux + IMAGEN_orgx);
      IMAGEN_putwd(uy + IMAGEN_orgy);

    /* Draw path with black pen.					*/

    putc(imP_DRAW_PATH, outfile);
      putc(15, outfile);

    /* Set current position to end of line.				*/

    IMAGEN_move(ux, uy);
}

IMAGEN_setpos(ux, uy)

int ux,uy;
{
    /* Set x and y position, also set beginning-of-line.		*/

    putc(imP_SET_ABS_H, outfile);
      IMAGEN_putwd(ux + IMAGEN_orgx);
    putc(imP_SET_ABS_V, outfile);
      IMAGEN_putwd(uy + IMAGEN_orgy);
    putc(imP_SET_BOL, outfile);
      if (IMAGEN_rotated)
	      IMAGEN_putwd(uy + IMAGEN_orgx);
      else
	      IMAGEN_putwd(ux + IMAGEN_orgx);
}

IMAGEN_rotate()

	{
	if (IMAGEN_rotated == 1)
		return;

	/* Cause text to run from bottom to top.			*/

	putc(imP_SET_ADV_DIRS, outfile);
	  putc(7, outfile);
	IMAGEN_rotated = 1;
	}

IMAGEN_unrotate()

	{
	if (IMAGEN_rotated == 0)
		return;

	/* Cause text to run from left to right.			*/

	putc(imP_SET_ADV_DIRS, outfile);
	  putc(0, outfile);
	IMAGEN_rotated = 0;
	}

char *
IMAGEN_cvts(str, width, height)

	char		*str;
	int		*width;
	int		*height;

	{
	char		*cp1;
	char		*cp2;
	static char	*buf = NULL;
	int		h;
	int		maxw;
	int		w;

	/* Free up old buffer, if there is one, get a new one.  Since	*/
	/* all transformations shorten the string, get a buffer that is	*/
	/* the same size as the input string.				*/

	if (buf != NULL)
		(void)free(buf);
	buf = (char *)malloc(strlen(str));

	/* Do the transformations.					*/

	cp1 = str;
	cp2 = buf;
	h = 1;
	maxw = 0;
	w = 0;
	while (*cp1 != NULL)
		{
		switch (*cp1)
		{
		case ' ' :

			/* Space character.				*/

			*cp2++ = imP_SP;
			w++;
			break;

		case  '\\' :

			/* Escape sequence.				*/

			if (*++cp1 == '\\')
				{

				/* Begin new line.			*/

				h++;
				if (w > maxw)
					maxw = w;
				w = 0;
				*cp2++ = imP_CRLF;
				break;
				}
			
			/* Fall through to just copy next char out.	*/

		default :
			*cp2++ = *cp1;
			w++;
			break;
		}
		cp1++;
		}

	*cp2 = '\0';
	if (w > maxw)
		maxw = w;

	if (height != NULL)
		*height = IMAGEN_rotated ?
			  IMAGEN_wchar * maxw :
			  IMAGEN_hchar * h;
	if (width != NULL)
		*width = IMAGEN_rotated ?
			 IMAGEN_hchar * h :
			 IMAGEN_wchar * maxw;
	return (buf);
	}

IMAGEN_puts(str)

	char		*str;

	{
	str = IMAGEN_cvts(str, NULL, NULL);
	fputs(str, outfile);
	}

IMAGEN_lrput_text(row,str)
unsigned int row;
char str[];
{
	char		*imstr;
	int		width;

	imstr = IMAGEN_cvts(str, &width, NULL);
	IMAGEN_setpos((int)(IMAGEN_xmax - IMAGEN_HTIC - width),
		      (int)(IMAGEN_VTIC + 3 + IMAGEN_hchar*row));
	fputs(imstr, outfile);
}


IMAGEN_ulput_text(row,str)
unsigned int row;
char str[];
{
	IMAGEN_setpos((int)(IMAGEN_HTIC+3),
		      (int)(IMAGEN_ymax -
			    IMAGEN_VTIC - IMAGEN_hchar*(row+1)));
	IMAGEN_puts(str);
}

/* Invoked from gnutex, puts out optional arrow and forces font.	*/

IMAGEN_xyput_text(ref_x, ref_y, str, pos, length, dx, dy)
int ref_x,ref_y;		/* reference point of string */
char str[];				/* the text */
char pos[];				/* for optional [pos] to \makebox */
unsigned int length;		/* optional arrow length */
int dx, dy;				/* optional slopes for arrow */

{
	IMAGEN_unrotate();
	IMAGEN_setfont(IMAGEN_labelfsz);
	IMAGEN_xy_text(ref_x, ref_y, str, pos);
	if (length != 0 && pos != NULL && *pos != '\0')
		{
		if (dx == 0 && dy == 0)
			{
			if (INDEX(pos, 'l'))
				dx = -1;
			if (INDEX(pos, 'r'))
				dx = 1;
			if (INDEX(pos, 't'))
				dy = 1;
			if (INDEX(pos, 'b'))
				dy = -1;
			}
		IMAGEN_move(ref_x, ref_y);
		IMAGEN_vector(ref_x + dx * length, ref_y + dy * length);
		}
}

/* Called internally, just dumps string.				*/

IMAGEN_xy_text(ref_x, ref_y, str, pos)

int ref_x,ref_y;		/* reference point of string */
char str[];				/* the text */
char pos[];				/* for optional [pos] to \makebox */
{
    char		*cvstr;
    int			dy = 0;
    int			height;
    int			width;
    int			x = ref_x;
    int			y = ref_y;

    if (!IMAGEN_inplot)
	 return;

    cvstr = IMAGEN_cvts(str, &width, &height);
    x -= width / 2;
    dy += height / 2;
    if (pos != NULL)
	{
	if (INDEX(pos, 'l'))
		x += width / 2;
	if (INDEX(pos, 'r'))
		x -= width / 2;
	if (INDEX(pos, 't'))
		dy -= height / 2;
	if (INDEX(pos, 'b'))
		dy += height / 2;
	}
    if (IMAGEN_rotated)
	{
	x += IMAGEN_hchar;
	y -= dy;
	}
    else
	y += dy - IMAGEN_hchar;
    IMAGEN_setpos(x, y + IMAGEN_blofs);
    fputs(cvstr, outfile);
}

IMAGEN_key(x, y, style, names)
	unsigned int x,y;
	int style[];
	char *names[];
{
    /* @@@ maybe someday . . . */
}

static 
char *					/* pointer to static storage */
IMAGEN_key_point(style, pcount)
	int style;			/* style number to describe */
	int *pcount;			/* running counter of point-like styles */
{
    /* @@@ Maybe someday . . . */
}

IMAGEN_xtick_text(x, number, format)
unsigned int x;			/* place to put on axis */
double number;				/* the number to be written at that tick */
char *format;
{
    char mark[IMAGEN_TICSIZ];

    if (*format == '\0')
	 format = IMAGEN_FORMAT;
    IMAGEN_unrotate();
    IMAGEN_setfont(IMAGEN_tickfsz);
    sprintf(mark, format, number);
    IMAGEN_xy_text(x, (int)(-IMAGEN_HTIC), mark, "t");
}

IMAGEN_ytick_text(y, number, format)
int y;			/* place to put on axis */
double number;				/* the number to be written at that tick */
char *format;
{
    char mark[IMAGEN_TICSIZ];

    if (*format == '\0')
	 format = IMAGEN_FORMAT;
    IMAGEN_unrotate();
    IMAGEN_setfont(IMAGEN_tickfsz);
    sprintf(mark, format, number);
    IMAGEN_xy_text((int)(-IMAGEN_VTIC), y,  mark, "r");
}


IMAGEN_reset()
{
    if (IMAGEN_inplot) {
	   IMAGEN_endplot();
	   IMAGEN_inplot = FALSE;
    }
    IMAGEN_posx = IMAGEN_posy = 0;
}

#endif /* IMAGEN */


UNKNOWN_null()
{
	int_error("you must set your terminal type before plotting!",NO_CARET);
}

ALL_nop()					/* i.e. doesn't support this feature */
{
}


/*
 * term_tbl[] contains an entry for each terminal.  "unknown" must be the
 *   first, since term is initialized to 0.
 */
struct termentry term_tbl[] = {
	{"unknown", 100, 100, 1, 1, 1, 1, UNKNOWN_null, UNKNOWN_null, UNKNOWN_null,
	UNKNOWN_null, UNKNOWN_null, UNKNOWN_null, UNKNOWN_null, UNKNOWN_null,
	UNKNOWN_null, UNKNOWN_null,
	UNKNOWN_null, UNKNOWN_null, UNKNOWN_null}
#ifdef PC
	,{"cga", CGA_XMAX, CGA_YMAX, CGA_VCHAR, CGA_HCHAR,
		CGA_VTIC, CGA_HTIC, CGA_init, CGA_reset,
		CGA_text, CGA_graphics, CGA_move, CGA_vector,
		CGA_linetype, CGA_lrput_text, CGA_ulput_text, line_and_point,
	     ALL_nop, ALL_nop, ALL_nop, ALL_nop}
	,{"ega", EGA_XMAX, EGA_YMAX, EGA_VCHAR, EGA_HCHAR,
		EGA_VTIC, EGA_HTIC, EGA_init, EGA_reset,
		EGA_text, EGA_graphics, EGA_move, EGA_vector,
		EGA_linetype, EGA_lrput_text, EGA_ulput_text, do_point,
	     ALL_nop, ALL_nop, ALL_nop, ALL_nop}

#ifdef CORONA
	,{"corona", COR_XMAX, COR_YMAX, COR_VCHAR, COR_HCHAR,
		COR_VTIC, COR_HTIC, COR_init, COR_reset,
		COR_text, COR_graphics, COR_move, COR_vector,
		COR_linetype, COR_lrput_text, COR_ulput_text, line_and_point,
	     ALL_nop, ALL_nop, ALL_nop, ALL_nop}
#endif /* CORONA */
#endif /* PC */

#ifdef AED
	,{"aed767", AED_XMAX, AED_YMAX, AED_VCHAR, AED_HCHAR,
		AED_VTIC, AED_HTIC, AED_init, AED_reset, 
		AED_text, AED_graphics, AED_move, AED_vector, 
		AED_linetype, AED_lrput_text, AED_ulput_text, do_point,
	     ALL_nop, ALL_nop, ALL_nop, ALL_nop}
#endif

#ifdef HP75
	,{"hp75xx",HP75_XMAX,HP75_YMAX, HP75_VCHAR, HP75_HCHAR,HP75_VTIC,HP75_HTIC,
		HP75_init,HP75_reset,HP75_text, HP75_graphics, HP75_move, HP75_vector,
		HP75_linetype, HP75_lrput_text, HP75_ulput_text, do_point,
	     ALL_nop, ALL_nop, ALL_nop, ALL_nop}
#endif

#ifdef QMS
	,{"qms",QMS_XMAX,QMS_YMAX, QMS_VCHAR, QMS_HCHAR, QMS_VTIC, QMS_HTIC,
		QMS_init,QMS_reset, QMS_text, QMS_graphics, QMS_move, QMS_vector,
		QMS_linetype,QMS_lrput_text,QMS_ulput_text,line_and_point,
	     ALL_nop, ALL_nop, ALL_nop, ALL_nop}
#endif

#ifdef REGIS
	,{"regis", REGISXMAX, REGISYMAX, REGISVCHAR, REGISHCHAR, REGISVTIC,
		REGISHTIC, REGISinit, REGISreset, REGIStext, REGISgraphics,
		REGISmove,REGISvector,REGISlinetype, REGISlrput_text, REGISulput_text,
		line_and_point,
	     ALL_nop, ALL_nop, ALL_nop, ALL_nop}
#endif

#ifdef TEK
	,{"tek40xx",TEK40XMAX,TEK40YMAX,TEK40VCHAR, TEK40HCHAR, TEK40VTIC, 
		TEK40HTIC, TEK40init,TEK40reset, TEK40text, TEK40graphics, 
		TEK40move, TEK40vector,TEK40linetype,TEK40lrput_text,
		TEK40ulput_text, line_and_point,
	     ALL_nop, ALL_nop, ALL_nop, ALL_nop}
#endif

#ifdef HALFTEK
	,{"toptek",HALFTEK40XMAX,HALFTEK40YMAX,HALFTEK40VCHAR, HALFTEK40HCHAR, HALFTEK40VTIC, 
		HALFTEK40HTIC, HALFTEK40init,HALFTEK40reset, TOPTEK40text, HALFTEK40graphics, 
		TOPTEK40move, TOPTEK40vector,HALFTEK40linetype,HALFTEK40lrput_text,
		HALFTEK40ulput_text, line_and_point,
	     ALL_nop, ALL_nop, ALL_nop, ALL_nop}
	,{"bottek",HALFTEK40XMAX,HALFTEK40YMAX,HALFTEK40VCHAR, HALFTEK40HCHAR, HALFTEK40VTIC, 
		HALFTEK40HTIC, HALFTEK40init,HALFTEK40reset, BOTTEK40text, HALFTEK40graphics, 
		BOTTEK40move, BOTTEK40vector,HALFTEK40linetype,HALFTEK40lrput_text,
		HALFTEK40ulput_text, line_and_point,
	     ALL_nop, ALL_nop, ALL_nop, ALL_nop}
#endif

#ifdef UNIXPLOT
	,{"unixplot", UP_XMAX, UP_YMAX, UP_VCHAR, UP_HCHAR, UP_VTIC, UP_HTIC,
		UP_init, UP_reset, UP_text, UP_graphics, UP_move, UP_vector,
		UP_linetype, UP_lrput_text, UP_ulput_text, line_and_point,
	     ALL_nop, ALL_nop, ALL_nop, ALL_nop}
#endif

#ifdef LATEX
	/* xmax and ymax are filled in by LATEX_graphics */
	/* We supply the absolute maximum here */
	,{"latex", (int)(8.5*LATEX_PTS_PER_INCH), (int)(11*LATEX_PTS_PER_INCH),
	    (int)LATEX_VCHAR, (int)LATEX_HCHAR, (int)LATEX_VTIC, (int)LATEX_HTIC,
	    LATEX_init, LATEX_reset, LATEX_text, LATEX_graphics, LATEX_move, 
	    LATEX_vector,
	    LATEX_linetype, LATEX_lrput_text, LATEX_ulput_text, LATEX_point,
	    LATEX_xyput_text, LATEX_xtick_text, LATEX_ytick_text, LATEX_plotstyle}
#endif

#ifdef FIG
	/* xmax and ymax are filled in by FIG_graphics */
	/* We supply the absolute maximum here */
	,{"fig", (int)(8.5*FIG_RES), 11*FIG_RES,
	    FIG_VCHAR, FIG_HCHAR, FIG_VTIC, FIG_HTIC,
	    FIG_init, FIG_reset, FIG_text, FIG_graphics, FIG_move, 
	    FIG_vector,
	    FIG_linetype, FIG_lrput_text, FIG_ulput_text, do_point,
	    FIG_xyput_text, FIG_xtick_text, FIG_ytick_text, FIG_plotstyle}
#endif

#ifdef IMAGEN
	/* xmax and ymax are filled in by IMAGEN_graphics */
	/* We supply the absolute maximum here */
	,{"imagen", 11*IMAGEN_PTS_PER_INCH, 8.5*IMAGEN_PTS_PER_INCH,
	    IMAGEN_VCHAR, IMAGEN_HCHAR, IMAGEN_VTIC, IMAGEN_HTIC,
	    IMAGEN_init, IMAGEN_reset, IMAGEN_text, IMAGEN_graphics, IMAGEN_move, 
	    IMAGEN_vector,
	    IMAGEN_linetype, IMAGEN_lrput_text, IMAGEN_ulput_text, do_point,
	    IMAGEN_xyput_text, IMAGEN_xtick_text, IMAGEN_ytick_text, IMAGEN_plotstyle}
#endif
	};


list_terms()
{
register int i;

	(void) putc('\n',stderr);
	fprintf(stderr,"available terminal types: \n");
	for (i = 0; i < TERMCOUNT; i++)
		fprintf(stderr,"\t%s\n",term_tbl[i].name);
	(void) putc('\n',stderr);
}


set_term(c_token)
int c_token;
{
register int i,t;

	if (!token[c_token].is_token)
		int_error("terminal name expected",c_token);
	t = -1;
	for (i = 0; i < TERMCOUNT; i++) {
		if (!strncmp(input_line + token[c_token].start_index,term_tbl[i].name,
			token[c_token].length)) {
			if (t != -1)
				int_error("ambiguous terminal name",c_token);
			t = i;
		}
	}
	if (t == -1)
		int_error("unknown terminal type; type just 'set terminal' for a list",
			c_token);
	term_init = FALSE;
	return(t);
}