/*
 * $Id: imagen.trm,v 1.11 1995/12/20 21:47:56 drd Exp $
 */

/* GNUPLOT - imagen.trm */
/*
 * Copyright (C) 1990   
 *
 * Permission to use, copy, and distribute this software and its
 * documentation for any purpose with or without fee is hereby granted, 
 * provided that the above copyright notice appear in all copies and 
 * that both that copyright notice and this permission notice appear 
 * in supporting documentation.
 *
 * Permission to modify the software is granted, but not the right to
 * distribute the modified code.  Modifications are to be distributed 
 * as patches to released version.
 *  
 * This software  is provided "as is" without express or implied warranty.
 * 
 * This file is included by ../term.c.
 *
 * This terminal driver supports:
 *   Imagen laser printers
 *
 * AUTHORS
 *   Paul E. McKenney, David Kotz
 *   Rewritten/extended by:
 *	Hans Olav Eggestad
 * send your comments or suggestions to (info-gnuplot@dartmouth.edu).
 * 
 */

/*
 * Original for direct Imagen output (but retaining many of the
 * LaTeX extensions) by Paul E. McKenney, 1989.
 * Further modified by David Kotz to fit into gnuplot 2.0.
 * Information Science and Technology Division, SRI International,
 * 333 Ravenswood Ave, Menlo Park, CA 94025.
 * Mail to mckenney@sri.com.
 */
/*
 * adapted to the new terminal layout by Stefan Bodewig (Dec. 1995)
 */

#ifndef GOT_DRIVER_H
#include "driver.h"
#endif

#ifdef TERM_REGISTER
register_term(imagen)
#endif

#ifdef TERM_PROTO
TERM_PUBLIC void IMAGEN_init __P((void));
TERM_PUBLIC void IMAGEN_graphics __P((void));
TERM_PUBLIC void IMAGEN_options __P((void));
TERM_PUBLIC void IMAGEN_text __P((void));
TERM_PUBLIC void IMAGEN_linetype __P((int lt));
TERM_PUBLIC void IMAGEN_move __P((unsigned int x, unsigned int y));
TERM_PUBLIC void IMAGEN_vector __P((unsigned int ux, unsigned int uy));
TERM_PUBLIC int IMAGEN_text_angle __P((int angle));
TERM_PUBLIC int IMAGEN_justify_text __P((enum JUSTIFY mode));
TERM_PUBLIC void IMAGEN_put_text __P((unsigned int x, unsigned int y, char str[]));
TERM_PUBLIC void IMAGEN_reset __P((void));
#define IMAGEN_PTS_PER_INCH (300)
#define IMAGEN_XMAX (IMAGEN_PTS_PER_INCH * 11) /* 10.0 inches */
#define IMAGEN_YMAX (IMAGEN_PTS_PER_INCH * 78 / 10) /* 7.5 inches */
#define IMAGEN_HTIC (20)
#define IMAGEN_VTIC (20)
#define IMAGEN_VCHAR (IMAGEN_FONTSIZE*5)
#define IMAGEN_HCHAR (IMAGEN_VCHAR/2)
#endif /* TERM_PROTO */

#ifndef TERM_PROTO_ONLY
#ifdef TERM_BODY

void IM_page __P((void));
void IMAGEN_draw_path __P((void));
static void IMAGEN_setpos __P((int ux, int uy));
static unsigned char * IMAGEN_cvts __P((unsigned char *str, int *width, int *height));
static void IMAGEN_putwd __P((unsigned int w));
static void IMAGEN_createfamily __P((char *c, int sz));
static void IMAGEN_setfont __P((int sz));
void IMP_set_draw_pattern __P((int pattern, int sz));
void IMAGEN_mapsinit __P((void));
void IMAGEN_createmap __P((int name, unsigned short *map));


/* #ifndef __malloc_h
#include <malloc.h>
#endif
*/
#include "impcodes.h"

#define IMAGEN_A4_H  (IMAGEN_PTS_PER_INCH * 83 / 10) /* default is landscape */
#define IMAGEN_A4_W  (IMAGEN_PTS_PER_INCH * 116 / 10)

static int IMAGEN_Xmax = IMAGEN_XMAX;  /* width in current orientation */
static int IMAGEN_Ymax = IMAGEN_YMAX;

#define IMAGEN_FONTSIZE 12
#define IMAGEN_FONT "cour"


unsigned short IMP_gmap[127];
unsigned char IMP_chmap[256];

static int IMAGEN_page_h  = IMAGEN_A4_H;
static int IMAGEN_page_w = IMAGEN_A4_W;
static int IM_win_horiz = 1;
static int IM_win_verti = 1;
static int IM_plot_nr = 0;

static int IMAGEN_fontsize = IMAGEN_FONTSIZE;
static int IMAGEN_familytable[36];
static int IMAGEN_orgX;		/* absolute-pixel-ORIgin of graph page.	*/
static int IMAGEN_orgY;
static int IMAGEN_orgx;		/* absolute-pixel-ORIgin of current 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 = IMAGEN_XMAX;	/* width of graph in pixels.	*/
static int IMAGEN_ymax = IMAGEN_YMAX;	/* height of graph in pixels.	*/
static int IMAGEN_winx = IMAGEN_XMAX;	/* width of window in pixels.	*/
static int IMAGEN_winy = IMAGEN_YMAX;	/* height of window 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_angle = -1;	/* 0 for horizontal text, 1 for vertical */
static int IMAGEN_portrait;	/* 0 for landscape */
static enum JUSTIFY IMAGEN_justify = LEFT; /* left/center/right */

/* static IMAGEN_seq_pos;		/* position in sequence */
#define STOREPATH 100
unsigned int IM_xvector[STOREPATH];	/* draw path vector of x values */
unsigned int IM_yvector[STOREPATH];	/* draw path vector of y values */
unsigned int IM_veclen;		/* length of allocated path vector */
unsigned int IM_vecpos = 0;		/* current pos in vector */

static void IMAGEN_putwd();
static void IMAGEN_createfamily();
static void IMAGEN_setfont();
static void IMAGEN_setpos();
void IMP_set_draw_pattern();
static unsigned char *IMAGEN_cvts();

/* char IMPdrpattern[10][10] = { {0}, {30,10,0}, {0}, {10,30,0}, {2,20,0}, 
	{20,10,0}, {30,20,10,20,0}, {30,20,4,10,10,10,4,20,0}, {40,20,0}, {30,15,4,15,0}
};
*/

char IMPdrpattern[10][10] = { 
/* -2 */ {0}, 
/* -1 */ {1,8,0}, 
/*  0 */ {0}, 
/*  1 */ {16,4,0}, 
/*  2 */ {3,8,0}, 
/*  3 */ {8,8,0}, 
/*  4 */ {16,6,3,6,0}, 
/*  5 */ {16,6,8,6,0}, 
/*  6 */ {16,4,1,4,8,4,1,4,0}, 
/*  7 */ {16,4,1,8,1,4,0}
};

TERM_PUBLIC void IMAGEN_init()
{
    register struct termentry *t = term;

    /* char font[10];	*/		/* font name */

    IMAGEN_posx = IMAGEN_posy = 0;

    IMAGEN_orgX = (IMAGEN_page_w - IMAGEN_Xmax) / 2;
    IMAGEN_orgY = (IMAGEN_page_h - IMAGEN_Ymax) / 2;

    IMAGEN_xmax = IMAGEN_winx = (int)(IMAGEN_Xmax / IM_win_horiz);
    IMAGEN_ymax = IMAGEN_winy = (int)(IMAGEN_Ymax / IM_win_verti);

    t->xmax = (unsigned int)(IMAGEN_xmax);
    t->ymax = (unsigned int)(IMAGEN_ymax);

    fputs("@document(language impress, paper a4)", outfile);

    if (IMAGEN_portrait) {
    	putc(imP_SET_ABS_V, outfile);
    	IMAGEN_putwd(3520);
    }
    putc(imP_SET_HV_SYSTEM, outfile);
    putc(((IMAGEN_portrait?3:0)<<5)|(3<<3)|(IMAGEN_portrait?0:5), outfile);

    /* sprintf(font, "cour%02d", IMAGEN_FONTSIZE); */
    IMAGEN_mapsinit();
    IMAGEN_createmap(1,IMP_gmap);
    /* IMAGEN_createfamily(font, IMAGEN_FONTSIZE); */
    IMAGEN_setfont(IMAGEN_fontsize);

    IMAGEN_text_angle(0);

    putc(imP_SET_ABS_H, outfile);
    IMAGEN_putwd(0);
    putc(imP_SET_ABS_V, outfile);
    IMAGEN_putwd(0);

    IMAGEN_linetype(-1);
    /*
    if ((IM_xvector = (unsigned int *) malloc(STOREPATH*sizeof(int))) == NULL) {
	fprintf (stderr,"Imagendriver: Unable to allocate memory for draw path\n");
	exit(1);
    }
    if ((IM_yvector = (unsigned int *) malloc(STOREPATH*sizeof(int))) == NULL) {
	fprintf (stderr,"Imagendriver: Unable to allocate memory for draw path\n");
	exit(1);
    }
    */
    IM_veclen = STOREPATH;
    IM_vecpos = 0;
}

void IM_page()
{
    if ( IM_vecpos ) {
	/* fprintf(stderr,"graphics, draw path\n"); */
	IMAGEN_draw_path();
    }
	putc(imP_ENDPAGE, outfile);
}

TERM_PUBLIC void IMAGEN_graphics()
{
    int tmpx, tmpy;
/*    int xoff, yoff; */

    if ( IM_vecpos ) {
	/* fprintf(stderr,"graphics, draw path\n"); */
	IMAGEN_draw_path();
    }
    if ( IM_plot_nr >= ( IM_win_horiz * IM_win_verti )) {
	IM_page();
	IM_plot_nr = 0;
    }
    IM_plot_nr++;
    tmpx = IMAGEN_orgX + ((IM_plot_nr - 1) % IM_win_horiz) * IMAGEN_winx;
    tmpy = IMAGEN_orgY + ((IM_win_verti - 1) - (int)((IM_plot_nr - 1) / IM_win_horiz)) * IMAGEN_winy;
    IMAGEN_orgx = tmpx + (int)((IMAGEN_winx - IMAGEN_xmax)/2);
    IMAGEN_orgy = tmpy + (int)((IMAGEN_winy - IMAGEN_ymax)/2);
}

TERM_PUBLIC void IMAGEN_options()
{
	struct value a;

	while (!END_OF_COMMAND) {
		if (almost_equals(c_token,"p$ortrait")) {
			IMAGEN_portrait=TRUE;
			IMAGEN_page_h = IMAGEN_A4_W;
			IMAGEN_page_w = IMAGEN_A4_H;
			IMAGEN_Xmax = IMAGEN_YMAX;
			IMAGEN_Ymax = IMAGEN_XMAX;
			c_token++;
		}
		else if (almost_equals(c_token,"l$andscape")) {
			IMAGEN_portrait=FALSE;
			c_token++;
		} else if (equals(c_token,"[")) { /* windows spesified */
			c_token++;
			/* if (IM_plot_nr>1) */
			if (equals(c_token,"]")) {
				IM_page();
				c_token++;
				continue;
			}
			if (END_OF_COMMAND) {
	    			int_error("no. windows: [horizontal,vertical] expected",c_token);
			} else if (!equals(c_token,","))  {
				IM_win_horiz = (int)real(const_express(&a));
			}	
			if (!equals(c_token,","))
				int_error("',' expected",c_token);
			c_token++;
			if (!equals(c_token,"]")) {
				IM_win_verti = (int)real(const_express(&a));
	 		}
			if (!equals(c_token,"]"))
		  		int_error("expecting ']'",c_token);
			c_token++;
		} else {
			/* We have font size specified */
			IMAGEN_fontsize = (int)real(const_express(&a));
			if ( IMAGEN_fontsize < 8 ) 
				IMAGEN_fontsize = 8;
			if ( IMAGEN_fontsize > 15 ) 
				IMAGEN_fontsize = 15;
		}
	}
	sprintf(term_options,"%d %s [%1d,%1d]",IMAGEN_fontsize,(IMAGEN_portrait)?"portrait":"landscape",IM_win_horiz,IM_win_verti);
}


TERM_PUBLIC void IMAGEN_text()
{
}


#define DRAW_PATTERNS 6


TERM_PUBLIC void IMAGEN_linetype(lt)
int lt;
{
    static int lastlinetype = -10;
    int pen/*, pattern*/ ;

    if ( IM_vecpos ) {
	/* fprintf(stderr,"move, draw path\n"); */
	IMAGEN_draw_path();
    }
/* -2: axis
   -1: border
    0: arrow
    1-7: graph
*/
	if (lt == -2) {
		pen = 4;
	} else {
		pen = (int) (lt/8)*2;
		if ( pen <= 0 ) pen = 1;
	}
	lt  = (lt % 8) +2;

    if (lastlinetype == lt)
	 return;

    lastlinetype = lt;	

    putc(imP_SET_PEN, outfile);
    putc(pen, outfile);
    IMP_set_draw_pattern(lt,pen);
}


TERM_PUBLIC void IMAGEN_move(x,y)
	unsigned int x,y;
{
    if ( IM_vecpos ) {
	/* fprintf(stderr,"move, draw path\n"); */
	IMAGEN_draw_path();
    }
    IM_xvector[0] = x + IMAGEN_orgx;
    IM_yvector[0] = y + IMAGEN_orgy;
	/* fprintf(stderr,"Ny vector: startpos: %1d %1d\n",IM_xvector[0],IM_yvector[0]); */
    IM_vecpos = 1;
    /* 
    IMAGEN_posx = x;
    IMAGEN_posy = y;
    */
}

TERM_PUBLIC void IMAGEN_vector(ux,uy)
	unsigned int ux,uy;
{
	/* void IMAGEN_draw_path(); */

    	/* Store path. */
	IM_xvector[IM_vecpos] = ux + IMAGEN_orgx;
	IM_yvector[IM_vecpos] = uy + IMAGEN_orgy;
	/* fprintf(stderr,"Ny node: nr: %1d; %1d %1d\n",IM_vecpos,IM_xvector[IM_vecpos],IM_yvector[IM_vecpos]);  */
	IM_vecpos ++;
	if ( IM_vecpos >= IM_veclen ) {
		IMAGEN_draw_path();
		IM_xvector[0] = ux + IMAGEN_orgx;
		IM_yvector[0] = uy + IMAGEN_orgy;
		IM_vecpos = 1;
	}
}

void IMAGEN_draw_path()
{
/*    unsigned int pos; */
    register int i;

    putc(imP_CREATE_PATH, outfile);
    IMAGEN_putwd(IM_vecpos);
    for (i=0;i<IM_vecpos;i++) {
	/*
    	IMAGEN_putwd(IM_xvector[i] + IMAGEN_orgx);
    	IMAGEN_putwd(IM_yvector[i] + IMAGEN_orgy);
	*/
    	IMAGEN_putwd(IM_xvector[i]);
    	IMAGEN_putwd(IM_yvector[i]);
    }
    IM_vecpos = 0;
    /* Draw path with black pen. */

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

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

    /* IMAGEN_move(ux, uy); */
}

static void
IMAGEN_setpos(ux, uy)
	int ux,uy;
{
    /* Set x and y position (for text), 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_angle == 1)
	 IMAGEN_putwd(uy + IMAGEN_orgx); /* vertical */
    else
	 IMAGEN_putwd(ux + IMAGEN_orgx); /* horizontal */
}

TERM_PUBLIC int IMAGEN_text_angle(angle)
	int angle;
{
    
    if ( IM_vecpos ) {
	/* fprintf(stderr,"text_angle, draw path\n"); */
	IMAGEN_draw_path();
    }
    if (IMAGEN_angle != angle) {
	   IMAGEN_angle = angle;	/* record for later use */
	   putc(imP_SET_ADV_DIRS, outfile);
	   putc(angle == 0 ? 0 : 7, outfile); /* 0=>horiz : 7=>vert */
    }

    return(TRUE);
}

TERM_PUBLIC int IMAGEN_justify_text(mode)
	enum JUSTIFY mode;
{
    if ( IM_vecpos ) {
	/* fprintf(stderr,"justify_text, draw path\n"); */
	IMAGEN_draw_path();
    }
    IMAGEN_justify = mode;
    return(TRUE);
}

static unsigned char *
IMAGEN_cvts(str, width, height)
	unsigned char		*str;
	int		*width;
	int		*height;
{
    unsigned char		*cp1;
    unsigned char		*cp2;
    static unsigned 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 = (unsigned char *)alloc(strlen((char *)str),"converted label string");

    /* Do the transformations. */

    cp1 = str;
    cp2 = buf;
    h = 1;
    maxw = 0;
    w = 0;
    while (strlen((char *)cp1) > 0) {
	   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++ = '\n';
				/* *cp2++ = imP_CRLF; */
				break;
			 }
		    
		    /* Fall through to just copy next char out.	*/
		    
		    default :
			 /* *cp2++ = *cp1; */
			 *cp2++ = IMP_chmap[*cp1];
		    w++;
		    break;
		}
	   cp1++;
    }
    
    *cp2++ = '\n';
    *cp2 = '\0';
    if (w > maxw)
	 maxw = w;
    
    if (height != NULL)
	 *height = IMAGEN_angle ?
	   IMAGEN_wchar * maxw :
		IMAGEN_hchar * h;
    if (width != NULL)
	 *width = IMAGEN_angle ?
	   IMAGEN_hchar * h :
		IMAGEN_wchar * maxw;
    return (buf);
}

TERM_PUBLIC void IMAGEN_put_text(x, y, str)
	unsigned int x,y;			/* reference point of string */
	char str[];				/* the text */
{
    unsigned char *cvstr, *p;
    int height;
    int width;
    int sx, sy;
    
    if ( IM_vecpos ) {
	/* fprintf(stderr,"put_text, draw path\n"); */
	IMAGEN_draw_path();
    }

    cvstr = IMAGEN_cvts((unsigned char *)str, &width, &height);

    if (IMAGEN_angle) {		/* vertical */
	/* x += IMAGEN_hchar; */
	   x -= width/2 - IMAGEN_hchar;
	  /* y -= height/2; */
    } else				/* horizontal */
	 y += height/2 - IMAGEN_hchar;

    while ( (p=(unsigned char *)strchr((char *)cvstr,'\n' )) ){
	*p = '\0';
    	sx = x;
    	sy = y;
    	if ( IMAGEN_angle )
		sx = x - IMAGEN_blofs;
    	else
		sy = y + IMAGEN_blofs;
	
    	width = strlen((char *)cvstr)*IMAGEN_wchar;
	
    	switch (IMAGEN_justify) {
	   	case LEFT: 
			break;
	   	case CENTRE: 
			if ( IMAGEN_angle ) {
				sy = y - width/2;
			} else {
				sx = x - width/2;
			}
			break;
			/*x -= width/2; break; */
	   	case RIGHT: 
			if ( IMAGEN_angle ) {
				sy = y - width;
			} else {
				sx = x - width;
			}
			break;
			/* x -= width; break; */
    	}

    	IMAGEN_setpos(sx, sy);
    	fputs((char *)cvstr, outfile);
	cvstr = ++p;
	if (IMAGEN_angle) { 	/* vertical */
		x += IMAGEN_hchar;
	} else {
		y -= IMAGEN_hchar;
	}

    }
}

TERM_PUBLIC void IMAGEN_reset()
{
    if ( IM_vecpos ) {
	/* fprintf(stderr,"reset, draw path\n"); */
	IMAGEN_draw_path();
    }
    putc(imP_EOF, outfile);
}

static void
IMAGEN_putwd(w)
unsigned int w;
{
	/* fprintf(stderr,"%1u\n",w); */
	putc(w>>8, outfile);
	putc(w, outfile);
}

static void
IMAGEN_createfamily(c, sz)
	char		*c;
	int		sz;
{

    putc(imP_CREATE_FAMILY_TABLE, outfile);
    putc(sz, outfile);
    putc(1, outfile);
    putc(1, outfile);
    /* putc(0, outfile); */
    fputs(c, outfile);
    putc(0, outfile);
}

static void
IMAGEN_setfont(sz) 
    int sz;
{
    char font[20];

    if ( ! IMAGEN_familytable[sz] ) {
	sprintf(font,"%s%02d",IMAGEN_FONT,sz);
	IMAGEN_createfamily(font, sz);
    	IMAGEN_familytable[sz] = sz;
    }
    IMAGEN_hchar = sz * 5;
    IMAGEN_wchar = IMAGEN_hchar / 2;
    IMAGEN_blofs = IMAGEN_hchar / 3;
	term->v_char = IMAGEN_hchar;
	term->h_char = IMAGEN_wchar;
    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);
}

void
IMP_set_draw_pattern(pattern,sz)
int sz, pattern;
{
	int i /*,j */ ;
	putc(imP_SET_DRAW_PATTERN, outfile);
	putc(0,outfile);
	putc(imP_SET_DRAW_PATTERN, outfile);
	/* if ( strlen(IMPdrpattern[pattern]) == 1 ) {
		putc(type,outfile);
		return;
	} */ 
	putc(strlen(IMPdrpattern[pattern]),outfile);
	for ( i=0;i<strlen(IMPdrpattern[pattern]);i++) {
		IMAGEN_putwd(IMPdrpattern[pattern][i]*sz);
	}
}


void IMAGEN_mapsinit()
{

    register int i /*, j */ ;

    for ( i=32;i<127;i++) {
        IMP_gmap[i] = i;
    }
    IMP_gmap[1] = 225;
    IMP_gmap[2]  = 233;
    IMP_gmap[3] = 61736;
    IMP_gmap[4] = 241;
    IMP_gmap[5]  = 249;
    IMP_gmap[6] = 61864;
    IMP_gmap[7] = 162;
    IMP_gmap[8] = 163;
    IMP_gmap[9] = 164;
    IMP_gmap[10] = 165;
    IMP_gmap[11] = 167;
    IMP_gmap[12] = 171;
    IMP_gmap[13] = 182;
    IMP_gmap[14] = 61346;
    IMP_gmap[15] = 191;
    IMP_gmap[16] = 187;
    IMP_gmap[17] = 188;
    IMP_gmap[18] = 189;
    IMP_gmap[19] = 190;
    IMP_gmap[20] = 210;
    IMP_gmap[21] = 211;
    IMP_gmap[22] = 251;
    IMP_gmap[23] = 61232;
    IMP_gmap[24] = 212;
    IMP_gmap[25] = 137;
    IMP_gmap[26] = 176;
    IMP_gmap[27] = 161;
    IMP_gmap[28] = 139;
    IMP_gmap[29] = 133;
    IMP_gmap[30] = 140;
    IMP_gmap[31] = 61249;
    IMP_gmap[32] = 8738;
    IMP_gmap[34] = 186;
    IMP_gmap[36] = 164;
    IMP_gmap[39] = 185;
    IMP_gmap[127] = 61286;

    /* for (i=1;i<127;i++) fprintf(stderr,"%d -> %d\n",i,IMP_gmap[i]); */

    for ( i=32;i<=127;i++) {
        IMP_chmap [i] = i;
    }
    for ( i=128;i<=255;i++) {
        IMP_chmap [i] = 128; /* first map all non printable chars to SPACE */
    }

    IMP_chmap [161] = 27;
    IMP_chmap [162] = 7;
    IMP_chmap [163] = 8;
    IMP_chmap [164] = 120;
    IMP_chmap [165] = 10;
    IMP_chmap [166] = 124;
    IMP_chmap [167] = 11;
    IMP_chmap [168] = 25;
    IMP_chmap [169] = 21;
    IMP_chmap [170] = 45;
    IMP_chmap [171] = 12;
    IMP_chmap [172] = 83;
    IMP_chmap [173] = 45;
    IMP_chmap [174] = 20;
    IMP_chmap [175] = 126;
    IMP_chmap [176] = 26;
    IMP_chmap [177] = 12;
    IMP_chmap [178] = 1;
    IMP_chmap [179] = 2;
    IMP_chmap [180] = 29;
    IMP_chmap [181] = 52;
    IMP_chmap [182] = 13;
    IMP_chmap [183] = 5;
    IMP_chmap [184] = 28;
    IMP_chmap [185] = 3;
    IMP_chmap [186] = 45;
    IMP_chmap [187] = 16;
    IMP_chmap [188] = 17;
    IMP_chmap [189] = 18;
    IMP_chmap [190] = 19;
    IMP_chmap [191] = 15;
    IMP_chmap [192] = 65;
    IMP_chmap [193] = 65;
    IMP_chmap [194] = 65;
    IMP_chmap [195] = 65;
    IMP_chmap [196] = 65;
    IMP_chmap [197] = 3;
    IMP_chmap [198] = 1;
    IMP_chmap [199] = 67;
    IMP_chmap [200] = 69;
    IMP_chmap [201] = 69;
    IMP_chmap [202] = 69;
    IMP_chmap [203] = 69;
    IMP_chmap [204] = 73;
    IMP_chmap [205] = 73;
    IMP_chmap [206] = 73;
    IMP_chmap [207] = 73;
    IMP_chmap [208] = 68;
    IMP_chmap [209] = 78;
    IMP_chmap [210] = 79;
    IMP_chmap [211] = 79;
    IMP_chmap [212] = 79;
    IMP_chmap [213] = 79;
    IMP_chmap [214] = 79;
    IMP_chmap [215] = 13;
    IMP_chmap [216] = 2;
    IMP_chmap [217] = 85;
    IMP_chmap [218] = 85;
    IMP_chmap [219] = 85;
    IMP_chmap [220] = 85;
    IMP_chmap [221] = 89;
    IMP_chmap [222] = 32;
    IMP_chmap [223] = 22;
    IMP_chmap [224] = 97;
    IMP_chmap [225] = 97;
    IMP_chmap [226] = 97;
    IMP_chmap [227] = 97;
    IMP_chmap [228] = 97;
    IMP_chmap [229] = 6;
    IMP_chmap [230] = 4;
    IMP_chmap [231] = 99;
    IMP_chmap [232] = 101;
    IMP_chmap [233] = 101;
    IMP_chmap [234] = 101;
    IMP_chmap [235] = 101;
    IMP_chmap [236] = 105;
    IMP_chmap [237] = 105;
    IMP_chmap [238] = 105;
    IMP_chmap [239] = 105;
    IMP_chmap [240] = 100;
    IMP_chmap [241] = 110;
    IMP_chmap [242] = 111;
    IMP_chmap [243] = 111;
    IMP_chmap [244] = 111;
    IMP_chmap [245] = 111;
    IMP_chmap [246] = 111;
    IMP_chmap [247] = 10;
    IMP_chmap [248] = 5;
    IMP_chmap [249] = 117;
    IMP_chmap [250] = 117;
    IMP_chmap [251] = 117;
    IMP_chmap [252] = 117;
    IMP_chmap [253] = 121;
    IMP_chmap [254] = 32;
    IMP_chmap [255] = 121;
}
 
void IMAGEN_createmap(name,map) 
unsigned short *map; 
int name; 
{ 
    register int i,j; 
    unsigned char s[4], *p; 
 
    p = s; 
    *p++ = imP_CREATE_MAP; 
    *p++ = name; 
    j = 0; 
    for (i=0;i<127;i++) { 
        if ( map[i] ) j++; 
    } 
    *p = j; 
    for (i=0;i<3;i++) putc(s[i],outfile); 
 
    s[3] = 1;
    for (j=0;j<127;j++) { 
        if ( map[j] ) { 
            p = s; 
            *p++ = j; 
            *p++ = map[j] >> 8; 
            *p   = map[j] & 255;
            for (i=0;i<4;i++) putc(s[i],outfile); 
        } 
    } 
} 
 
#endif /* TERM_BODY */

#ifdef TERM_TABLE

TERM_TABLE_START(imagen_driver)
    "imagen", "Imagen laser printer",
	   IMAGEN_XMAX, IMAGEN_YMAX, IMAGEN_VCHAR, IMAGEN_HCHAR, 
	   IMAGEN_VTIC, IMAGEN_HTIC, IMAGEN_options, IMAGEN_init, IMAGEN_reset, 
	   IMAGEN_text, null_scale, IMAGEN_graphics, IMAGEN_move, 
	   IMAGEN_vector, IMAGEN_linetype, IMAGEN_put_text, IMAGEN_text_angle,
	   IMAGEN_justify_text, line_and_point, do_arrow, set_font_null
TERM_TABLE_END(imagen_driver)

#undef LAST_TERM
#define LAST_TERM imagen_driver

#endif /* TERM_TABLE */
#endif /* TERM_PROTO_ONLY */

/*
 * NAME: imagen
 *
 * OPTIONS: fontsize (default 12)
 *	    portrait|landscape (default landscape)
 *	    [horiz,vert] = window size, use with [], alternative to prt|lands
 *
 * SUPPORTS: Imagen laser printer
 *
 * Further Info: none
 *
 */
