/*
 * $Id: rgip.trm,v 1.8 1995/12/20 21:48:11 drd Exp $
 */

/* GNUPLOT - rgip.trm Uniplex graphics metafile */
/*
 * 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:
 *   RGIP metafile
 *
 * AUTHORS
 *   Hans Olav Eggestad
 *
 * send your comments or suggestions to (info-gnuplot@dartmouth.edu).
 *
 */

/*
 * Original for direct RGIP Metafile output.
 */
/* 
 * Max pixels for X and Y in one window is 10000.
 */
/*
 * adapted to the new terminal layout by Stefan Bodewig (Dec. 1995)
 */

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

#ifdef TERM_REGISTER
register_term(rgip)
register_term(uniplex)
#endif

#ifdef TERM_PROTO
TERM_PUBLIC void RGIP_init __P((void));
TERM_PUBLIC void RGIP_graphics __P((void));
TERM_PUBLIC void RGIP_text __P((void));
TERM_PUBLIC void RGIP_linetype __P((int lt));
TERM_PUBLIC void RGIP_move __P((unsigned int x, unsigned int y));
TERM_PUBLIC void RGIP_vector __P((unsigned int ux, unsigned int uy));
TERM_PUBLIC int RGIP_text_angle __P((int angle));
TERM_PUBLIC int RGIP_justify_text __P((enum JUSTIFY mode));
TERM_PUBLIC void RGIP_put_text __P((unsigned int x, unsigned int y, char *str));
TERM_PUBLIC void RGIP_reset __P((void));
TERM_PUBLIC void RGIP_do_point __P((unsigned int x, unsigned int y, int number));
TERM_PUBLIC void RGIP_options __P((void));
#define RGIP_X_MAX 10000
#define RGIP_Y_MAX 6700

#define RGIP_FONTSIZE 1
#define RGIP_SC (300)
#define RGIP_XMAX 9900
#define RGIP_YMAX 6600
#define RGIP_HTIC (100)
#define RGIP_VTIC (100)
#define RGIP_VCHAR (RGIP_FONTSIZE*RGIP_SC) 
#define RGIP_HCHAR (RGIP_VCHAR*3/7)   
#endif /* TERM_PROTO */

#ifndef TERM_PROTO_ONLY
#ifdef TERM_BODY


void RGIP_write_poly __P((void));
static unsigned char * RGIP_cvts __P((unsigned char *str, int *lcnt));
/* static void RGIP_setfont __P((int sz)); */

#include <sys/types.h>
#include <sys/stat.h>

#define RGIPDOTS 0
#define RGIPMARK 1
#define RGIPTEXT 2
#define RGIPLINE 3
#define RGIPPOLY 4
#define RGIP_MAX_POLY 250
static char *RGIP_Obj[6] = { "DOTS", "MARK", "TEXT", "LINE", "POLY" };

/* 
 * RGIP fontsises range from 1 to 8 
 */

#define RGIP_FACES 3
#define RGIP_FSTYLES 4
#define RGIP_FSIZES 8
#define RGIP_HELVETICA 0
#define RGIP_TIMES 1
#define RGIP_COURIER 2
#define RGIP_LINE_WIDTHS 8 /* future, currently invisible and visible 0
and 1 */
#define RGIP_LINE_TYPES 8
#define RGIP_COLORS 16
#define RGIP_POINT_TYPES 8




static int RGIP_orgX;		/* absolute-pixel-ORIgin of graph.	*/
static int RGIP_orgY;
static int RGIP_orgx;		/* absolute-pixel-ORIgin of current plot. */
static int RGIP_orgy;
static int RGIP_posx;		/* current drawing position (lines).	*/
static int RGIP_posy;
/* static int RGIP_inplot; */
static int RGIP_xmax = RGIP_XMAX;  /* width of graph in pixels.		*/
static int RGIP_ymax = RGIP_YMAX;  /* height of graph in pixels.	*/
static int RGIP_winx = RGIP_XMAX;  /* width of graph in pixels.		*/
static int RGIP_winy = RGIP_YMAX;  /* height of graph in pixels.	*/
/* static int RGIP_blofs;		/* BaseLine OFfSet from bounding box.	*/
static int RGIP_angle = 0;	/* 0 for horizontal text, 90 for vertical */
static int RGIP_portrait = 0;	/* 0 for horizontal text, 90 for vertical */
static enum JUSTIFY RGIP_justify = LEFT; /* left/center/right */
static int RGIP_fface = 2;  /* Times */
static int RGIP_ftype = 1; /* style roman */
static int RGIP_fontsize = RGIP_FONTSIZE; /*  */
static int RGIP_tcol = 7;  /* text color */
static int RGIP_lsty = 1;  /* line style */
static int RGIP_lcol = 7;  /* line color */
static int RGIP_lwid = 1;  /* line width */
static int RGIP_fsty = 8;  /* fill style */
static int RGIP_fcol = 8;  /* fill color */
static int RGIP_mcol = 7;  /* marker color */
static int RGIP_msty = 1;  /* marker style */
static int RGIP_msize = 1;  /* marker size */

static int RGIP_win_horiz = 1;
static int RGIP_win_verti = 1;
static int RGIP_plot_nr = 0;

unsigned int RGIP_vecpos;
unsigned int RGIP_xvector[RGIP_MAX_POLY];
unsigned int RGIP_yvector[RGIP_MAX_POLY];
static unsigned char *RGIP_cvts();


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

    RGIP_posx = RGIP_posy = 0;

    if ( RGIP_portrait ) {
	    RGIP_orgX = (RGIP_Y_MAX - RGIP_YMAX) / 2;
	    RGIP_orgY = (RGIP_X_MAX - RGIP_XMAX) / 2;
	    RGIP_xmax = RGIP_winx = (int)(RGIP_YMAX / RGIP_win_horiz);
	    RGIP_ymax = RGIP_winy = (int)(RGIP_XMAX / RGIP_win_verti);
    } else {
	    RGIP_orgX = (RGIP_X_MAX - RGIP_XMAX) / 2;
	    RGIP_orgY = (RGIP_Y_MAX - RGIP_YMAX) / 2;
	    RGIP_xmax = RGIP_winx = (int)(RGIP_XMAX / RGIP_win_horiz);
	    RGIP_ymax = RGIP_winy = (int)(RGIP_YMAX / RGIP_win_verti);
    }

    t->xmax = (unsigned int)(RGIP_xmax);
    t->ymax = (unsigned int)(RGIP_ymax);

    RGIP_vecpos = 0;
}

TERM_PUBLIC void RGIP_graphics()
{
    static int Gnr = 0;
    struct stat buf;
    unsigned char *p, fn[128];

    int tmpx, tmpy;
/*    int xoff, yoff; */

    if ( RGIP_vecpos ) {
	RGIP_write_poly();
    }

    if ( ! Gnr || RGIP_plot_nr >= ( RGIP_win_horiz * RGIP_win_verti )) {
    	fstat(fileno(outfile),&buf);
    	if ( S_ISREG(buf.st_mode)) {
	    if ( (p=(unsigned char *)strchr(outstr,'X')) ){ /* substitute X with graphnr */
		if ( ! Gnr ) { /* delete the base file */
		    sprintf(fn,"%s",&outstr[1]);
		    fn[strlen(fn)-1]='\0';
		    unlink(fn);
		} else {
        		fputs("%RI_GROUPEND\n", outfile);
			fclose(outfile);
		}
		*p = '\0';
		sprintf(fn,"%s%1d%s",&outstr[1],++Gnr,p+1);
	   	fn[strlen(fn)-1]='\0';
                if ( (outfile = fopen(fn,"w")) == (FILE *)NULL ) {
                     os_error("cannot reopen file with binary type; output unknown",
                           NO_CARET);
                }
		*p = 'X';  /* put back X */
            }
    	}
	fputs("%RGIP_METAFILE: 1.0a\n", outfile);
	fputs("%RI_GROUPSTART\n", outfile);
	fprintf(outfile,"0 0 %d %d SetWindow\n", 
		(RGIP_portrait)?RGIP_Y_MAX : RGIP_X_MAX,
		(RGIP_portrait)?RGIP_X_MAX : RGIP_Y_MAX);
	fprintf(outfile,"100 100 %d %d 10 1 7 1 8 BOX\n", 
		(RGIP_portrait) ? RGIP_YMAX : RGIP_XMAX,
		(RGIP_portrait) ? RGIP_XMAX : RGIP_YMAX);
	RGIP_plot_nr = 0;
    } else {
    	fputs("%RI_GROUPEND\n", outfile);
    }
    fputs("%RI_GROUPSTART\n", outfile);
    RGIP_plot_nr++;
    /* Gnr++; */
    tmpx = RGIP_orgX + ((RGIP_plot_nr - 1) % RGIP_win_horiz) * RGIP_winx;
    tmpy = RGIP_orgY + ((RGIP_win_verti - 1) - (int)((RGIP_plot_nr - 1) / RGIP_win_horiz)) * RGIP_winy;
    RGIP_orgx = tmpx + (int)((RGIP_winx - RGIP_xmax)/2);
    RGIP_orgy = tmpy + (int)((RGIP_winy - RGIP_ymax)/2);


    /* RGIP_linetype(-1); */
}

TERM_PUBLIC void RGIP_text()
{
}

TERM_PUBLIC void RGIP_linetype(lt)
int lt;
{
/*    int pen, pattern; */

    if ( RGIP_vecpos ) {
	RGIP_write_poly();
    }
/*  -2: axis
 *  -1: border
 *   0: arrow
 *   1-7: graph
*/
    if ( lt == -2 ) {
	lt = 1;
	RGIP_lwid = 5;
    } else if ( lt == -1 ) {
	lt = 5;
	RGIP_lwid = 2;
    } else {
	RGIP_lwid = (int) (lt/RGIP_LINE_TYPES);
	if ( RGIP_lwid < 1 ) RGIP_lwid = 1;
	RGIP_lwid *= 2;
    	lt  = (lt % RGIP_LINE_TYPES) + 1;
    }
    fputs("%RI_GROUPEND\n", outfile);
    fputs("%RI_GROUPSTART\n", outfile);

    /* RGIP_lsty  = (lt == 0 || lt == 2) ? 1 : lt; */

    RGIP_lsty = lt;
}


TERM_PUBLIC void RGIP_move(x,y)
	unsigned int x,y;
{
/*
    fputs("%RI_GROUPEND\n", outfile);
    fputs("%RI_GROUPSTART\n", outfile);
*/
    if ( RGIP_vecpos ) {
	RGIP_write_poly();
    }
    RGIP_xvector[0] = x + RGIP_orgx;
    RGIP_yvector[0] = y + RGIP_orgy;
    RGIP_vecpos = 1;
    /*
    RGIP_posx = x;
    RGIP_posy = y;
    */
}


TERM_PUBLIC void RGIP_vector(ux,uy)
	unsigned int ux,uy;
{
    /* store polygon-node */

    RGIP_xvector[RGIP_vecpos] = ux + RGIP_orgx;
    RGIP_yvector[RGIP_vecpos] = uy + RGIP_orgy;
    RGIP_vecpos++;
    if ( RGIP_vecpos >= RGIP_MAX_POLY ) {
	RGIP_write_poly();
    RGIP_xvector[RGIP_vecpos] = ux + RGIP_orgx;
    RGIP_yvector[RGIP_vecpos] = uy + RGIP_orgy;
    RGIP_vecpos++;
    }
}

void RGIP_write_poly()
{
    register int i;

    putc ('[',outfile);
    for (i=0;i<RGIP_vecpos;i++) {
	if ( ! (i%8)) putc ('\n',outfile);
	fprintf (outfile," %1d",RGIP_xvector[i]);
	fprintf (outfile," %1d",RGIP_yvector[i]);
    }
    RGIP_vecpos = 0;
    putc (']',outfile);

    fprintf(outfile," %1d %d %1d %1d %1d %s\n", RGIP_lwid, RGIP_lsty,
        RGIP_lcol, RGIP_fsty, RGIP_fcol, RGIP_Obj[RGIPPOLY]);

    /*
    RGIP_posx = ux;
    RGIP_posy = uy;
    */
    /* RGIP_move(ux, uy); */
}


TERM_PUBLIC int RGIP_text_angle(angle)
	int angle;
{
    if ( RGIP_vecpos ) {
	RGIP_write_poly();
    }
    if (RGIP_angle != angle) {
	   RGIP_angle = angle;	/* record for later use */
    }

    return(TRUE);
}

TERM_PUBLIC int RGIP_justify_text(mode)
	enum JUSTIFY mode;
{
    if ( RGIP_vecpos ) {
	RGIP_write_poly();
    }
    RGIP_justify = mode;
    return(TRUE);
}

static unsigned char *
RGIP_cvts(str,lcnt)
	unsigned char		*str;
	int *lcnt;			/* lines */
{
    unsigned char		*cp1;
    unsigned char		*cp2;
    static unsigned char	*buf = NULL;
    int lc = 1;

    lc = 1;
    /* 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(str), "converted label string");

    /* Do the transformations. */

    cp1 = str;
    cp2 = buf;
    while (strlen(cp1) > 0) {
	   switch (*cp1) {
		    case  '\\' :	/* Escape sequence. */
			 if (*++cp1 == '\\') {
				/* Begin new line. */
				*cp2++ = '\n';
				lc++;
				break;
			 }
		
		    case '(' :
			*cp2++ = '\\';
			*cp2++ = '(';
			break;
		    case ')' :
			*cp2++ = '\\';
			*cp2++ = ')';
			break;
		    /* Fall through to just copy next char out.	*/
		
		    default :
			 *cp2++ = *cp1;
		    break;
		}
	   cp1++;
    }
 
    *cp2++ = '\n';
    *cp2 = '\0';
    *lcnt = lc; 
    return (buf);
}

TERM_PUBLIC void RGIP_put_text(x, y, str)
	unsigned int x,y;			/* reference point of string */
	char *str;				/* the text */
{
    register struct termentry *t = term;
    unsigned char *cvstr, *p;
    int xlines;		/* lines */
 
    if ( RGIP_vecpos ) {
	RGIP_write_poly();
    }
    cvstr = RGIP_cvts(str,&xlines);

    x += RGIP_orgx,
    y += RGIP_orgy;

    if (! RGIP_angle) {  	/* horisontal */
	y += (int)(t->v_char)*(xlines-2)/2;
	/* y += (t->v_char)*xlines; */
	y += (int)(t->v_char)/4;
    } else {
	x -= (int)(t->v_char)*(xlines-2)/2;
	x -= (int)(t->v_char)/4;
    }

    while ( (p=(unsigned char *)strchr(cvstr,'\n' )) ){
	*p = '\0';
	if (strlen(cvstr)) 
    	    fprintf(outfile,"%1d %1d %1d  %1d (%s) %1d %1d %1d %1d %s\n",
            	x,y,RGIP_justify, RGIP_angle*90, cvstr, RGIP_fface, RGIP_ftype,
            	RGIP_fontsize, RGIP_tcol, RGIP_Obj[RGIPTEXT]);
	cvstr = ++p;
	if (RGIP_angle) { 	/* vertical */
		x += (t->v_char);
	} else {
		y -= (t->v_char);
	}
    }
}


TERM_PUBLIC void RGIP_reset()
{
    if ( RGIP_vecpos ) {
	RGIP_write_poly();
    }
    fputs("%RI_GROUPEND\n", outfile);
    /* fputs("%RI_GROUPEND\n", outfile); */
}

/* static void
RGIP_setfont(sz)
    int sz;
{
    RGIP_fontsize = (int) (sz);
    if ( RGIP_fontsize < 1 ) RGIP_fontsize = 1;
    term->v_char = (unsigned int)(RGIP_fontsize*RGIP_SC);
    term->h_char = (unsigned int)(RGIP_fontsize*RGIP_SC*3/7);
}
*/

TERM_PUBLIC void RGIP_do_point(x,y,number)
unsigned int x,y;
int number;
{

    x += RGIP_orgx,
    y += RGIP_orgy;

    if (number < 0) {		/* do dot */
        fprintf(outfile,"%1d %1d %1d %s\n",
               x,y,RGIP_mcol,RGIP_Obj[RGIPDOTS]);
	    return;
	}

	RGIP_msty = (number % RGIP_POINT_TYPES) + 1;
	RGIP_msize = ((int)(number / RGIP_POINT_TYPES)) + 1;

    fprintf(outfile,"%1d %1d %1d %1d %1d %s\n",
               x,y,RGIP_msize, RGIP_msty, RGIP_mcol, RGIP_Obj[RGIPMARK]);
}

TERM_PUBLIC void RGIP_options()
{
	struct value a;

	while (!END_OF_COMMAND) {
		if (almost_equals(c_token,"p$ortrait")) {
			RGIP_portrait=TRUE;
			c_token++;
		}
		else if (almost_equals(c_token,"l$andscape")) {
			RGIP_portrait=FALSE;
			c_token++;
		}
		else if (equals(c_token,"[")) { /* windows spesified */
			c_token++;
			/* if (RGIP_plot_nr>1) */
			if (equals(c_token,"]")) {
				/* RGIP_page(); */
				c_token++;
				continue;
			}
			if (END_OF_COMMAND) {
	    			int_error("no. windows: [horizontal,vertical] expected",c_token);
			} else if (!equals(c_token,","))  {
				RGIP_win_horiz = (int)real(const_express(&a));
			}	
			if (!equals(c_token,","))
				int_error("',' expected",c_token);
			c_token++;
			if (!equals(c_token,"]")) {
				RGIP_win_verti = (int)real(const_express(&a));
	 		}
			if (!equals(c_token,"]"))
		  		int_error("expecting ']'",c_token);
			c_token++;
		} else {
			/* We have font size specified */
			RGIP_fontsize = (int)real(const_express(&a));
			if ( RGIP_fontsize < 1 ) 
				RGIP_fontsize = 1;
			term->v_char = (unsigned int)(RGIP_fontsize*RGIP_SC);
			term->h_char = (unsigned int)(RGIP_fontsize*RGIP_SC*3/7);
		}
	}
	sprintf(term_options,"%s %d [%1d,%1d]",
		(RGIP_portrait)?"portrait":"landscape",
		RGIP_fontsize,RGIP_win_horiz,RGIP_win_verti);
}

#endif /* TERM_BODY */

#ifdef TERM_TABLE

TERM_TABLE_START(rgip_driver)
    "rgip", "RGIP metafile (Uniplex). Option: fontsize (1-8)",
	   RGIP_XMAX, RGIP_YMAX, RGIP_VCHAR, RGIP_HCHAR,
	   RGIP_VTIC, RGIP_HTIC, RGIP_options, RGIP_init, RGIP_reset,
	   RGIP_text, null_scale, RGIP_graphics, RGIP_move,
	   RGIP_vector, RGIP_linetype, RGIP_put_text, RGIP_text_angle,
	   RGIP_justify_text, RGIP_do_point, do_arrow, set_font_null
TERM_TABLE_END(rgip_driver)

#undef LAST_TERM
#define LAST_TERM rgip_driver

TERM_TABLE_START(uniplex_driver)
    "uniplex", "RGIP metafile (Uniplex). Option: fontsize (1-8) (Same
as rgip)",
	   RGIP_XMAX, RGIP_YMAX, RGIP_VCHAR, RGIP_HCHAR,
	   RGIP_VTIC, RGIP_HTIC, RGIP_options, RGIP_init, RGIP_reset,
	   RGIP_text, null_scale, RGIP_graphics, RGIP_move,
	   RGIP_vector, RGIP_linetype, RGIP_put_text, RGIP_text_angle,
	   RGIP_justify_text, RGIP_do_point, do_arrow, set_font_null
TERM_TABLE_END(uniplex_driver)

#undef LAST_TERM
#define LAST_TERM uniplex_driver


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

/*
 * NAME: rgip
 *
 * OPTIONS: font-size (legal 1-8; default 1)
 *	    portrait|landscape (default landscape)
 *	    [horiz,vert] = window size, use with [], alternative to prt|lands
 *
 * SUPPORTS: RGIP metafile (Uniplex)
 *
 * Further Info: Same as uniplex terminal.
 *
 */

/*
 * NAME: uniplex
 *
 * OPTIONS: font-size (legal 1-8; default 1)
 *	    portrait|landscape (default landscape)
 *	    [horiz,vert] = window size, use with [], alternative to prt|lands
 *
 * SUPPORTS: RGIP metafile (Uniplex)
 *
 * Further Info: Same as rgip terminal.
 *
 */
