/*
 * $Id: pstex.trm,v 1.2 1995/05/25 14:31:47 drd Exp $
 */

/* GNUPLOT - pstex.trm */
/*
 * Copyright (C) 1990 - 1993   
 *
 * 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:
 *     Generic TeX with embedded PostScript
 *
 * AUTHORS
 *  George Phillips
 *  Russell Lang
 *  David Kotz
 * 
 * send your comments or suggestions to (info-gnuplot@dartmouth.edu).
 */

/* Driver by Pieter Vosbeek from the PSLaTeX driver by George Phillips */

void PSTEX_options __P((void));
void PSTEX_PS_init __P((void));
void PSTEX_init __P((void));
int PSTEX_scale __P((double xs, double ys));
void PSTEX_PS_graphics __P((void));
void PSTEX_graphics __P((void));
void PSTEX_put_text __P((unsigned int x, unsigned int y, char str[]));
int PSTEX_justify_text __P((enum JUSTIFY mode));
int PSTEX_text_angle __P((int angle));
void PSTEX_reset __P((void));
void PSTEX_text __P((void));

#define PSTEX_XMAX (5*720)
#define PSTEX_YMAX (3*720)

/* 10 pt char is about 10 pts high (say) */
#define PSTEX_VCHAR (100)
/* 10 pt char is about 6 pts wide (say) */
#define PSTEX_HCHAR (60)

static int PSTEX_angle;
static int PSTEX_justify;
static int PSTEX_rotate = TRUE;

static struct text_command* PSTEX_labels;

#define PSTEX_PS_XOFF	50	/* page offset in pts */
#define PSTEX_PS_YOFF	50

#define PSTEX_PS_XMAX 7200
#define PSTEX_PS_YMAX 5040

#define PSTEX_PS_VTIC (PSTEX_PS_YMAX/120)
#define PSTEX_PS_HTIC (PSTEX_PS_YMAX/120)

#define PSTEX_PS_SC (10)		/* scale is 1pt = 10 units */
#define	PSTEX_PS_LW (0.5)		/* default linewidth = 0.5 pts */

static double PSTEX_linewidth = PSTEX_PS_LW;

void PSTEX_options()
{
  extern double real();
  extern struct value *const_express();
  int fontsize = 10;
  struct value a;

  if (!END_OF_COMMAND) {
    if (almost_equals(c_token, "d$efault")) {
      ps_color = FALSE;
      PSTEX_rotate = TRUE;
      PSTEX_linewidth = PSTEX_PS_LW;
      term->v_char = (unsigned int)PSTEX_VCHAR;
      term->h_char = (unsigned int)PSTEX_HCHAR;
      c_token++;
    }
  }
  
  if (!END_OF_COMMAND)
    {
      if (almost_equals(c_token, "c$olor"))
	{
	  ps_color = TRUE;
	  c_token++;
	}
      else if (almost_equals(c_token, "m$onochrome"))
	{
	  ps_color = FALSE;
	  c_token++;
	}
    }
  
  if (!END_OF_COMMAND)
    {
      if (almost_equals(c_token, "r$otate"))
	{
	  PSTEX_rotate = TRUE;
	  c_token++;
	}
      else if (almost_equals(c_token, "n$orotate"))
	{
	  PSTEX_rotate = FALSE;
	  c_token++;
	}
    }
  
  
  if (!END_OF_COMMAND)
    {
      if (almost_equals(c_token, "f$ontsize"))
	{
	  c_token++;
	  if (!END_OF_COMMAND)
	    {
	      fontsize = (int)real(const_express(&a));
	      term->v_char = (unsigned int)(fontsize*PSTEX_PS_SC);
	      term->h_char = (unsigned int)(fontsize*PSTEX_PS_SC*6/10);
	    }
	}
    }
  
  if (!END_OF_COMMAND)
    {
      if (almost_equals(c_token, "l$inewidth"))
	{
	  c_token++;
	  if (!END_OF_COMMAND)
	    PSTEX_linewidth = real(const_express(&a));
	}
    }
  
  sprintf(term_options, "%s %s fontsize %d linewidth %g",
	  ps_color ? "color" : "monochrome",
	  PSTEX_rotate ? "rotate" : "norotate",
	  fontsize, PSTEX_linewidth);
}

void PSTEX_PS_init()
{
  static char GPFAR psi1[] = "%%%%Creator: gnuplot\n\
%%%%DocumentFonts: %s\n\
%%%%BoundingBox: %d %d ";
  static char GPFAR psi2[] = "%%%%EndComments\n\
/gnudict 40 dict def\ngnudict begin\n\
/Color %s def\n\
/Solid %s def\n\
/gnulinewidth %.3f def\n\
/vshift %d def\n\
/dl {%d mul} def\n\
/hpt %.1f def\n\
/vpt %.1f def\n";

  struct termentry *t = term;
  int i;
  ps_page = 0;

  if (!ps_eps)
    fprintf(outfile,"%%!PS-Adobe-2.0\n");
  else
    fprintf(outfile,"%%!PS-Adobe-2.0 EPSF-2.0\n");

  fprintf(outfile, psi1, ps_font, PSTEX_PS_XOFF, PSTEX_PS_YOFF);
  if (ps_portrait)
    fprintf(outfile,"%d %d\n", 
	    (int)(xsize*(ps_eps ? 0.5 : 1.0)
		  *(PSTEX_PS_XMAX)/PSTEX_PS_SC+0.5+PSTEX_PS_XOFF), 
	    (int)(ysize*(ps_eps ? 0.5 : 1.0)
		  *(PSTEX_PS_YMAX)/PSTEX_PS_SC+0.5+PSTEX_PS_YOFF));
  else 
    fprintf(outfile,"%d %d\n", 
	    (int)(ysize*(ps_eps ? 0.5 : 1.0)
		  *(PSTEX_PS_YMAX)/PSTEX_PS_SC+0.5+PSTEX_PS_XOFF), 
	    (int)(xsize*(ps_eps ? 0.5 : 1.0)
		  *(PSTEX_PS_XMAX)/PSTEX_PS_SC+0.5+PSTEX_PS_YOFF));
  if (!ps_eps)
    fprintf(outfile,"%%%%Pages: (atend)\n");
  fprintf(outfile, psi2,
	  ps_color ? "true" : "false",
	  ps_solid ? "true" : "false",
	  PSTEX_linewidth*PSTEX_PS_SC,	/* line width */
	  (int)(t->v_char)/(-3),	/* shift for vertical centring */
	  PSTEX_PS_SC,			/* dash length */
	  PSTEX_PS_HTIC/2.0,		/* half point width */
	  PSTEX_PS_VTIC/2.0);		/* half point height */
  
  for ( i=0; PS_header[i] != NULL; i++)
    fprintf(outfile,"%s",PS_header[i]);
  fprintf(outfile,"end\n%%%%EndProlog\n");
}

void PSTEX_init()
{
  /* reset PostScript driver variables */
  ps_portrait = TRUE;
  ps_eps = FALSE;
  ps_color = FALSE;

  fprintf(outfile, "%% GNUPLOT: TeX with Postscript \\specials\n");
  fprintf(outfile, "\\expandafter\\ifx\\csname PSTeXpicture\\endcsname\\relax\n");
  fprintf(outfile, "\\newdimen\\PSTeXunit \\PSTeXunit=0.1bp\n");
  fprintf(outfile, "\\def\\PSTeXpicture(#1,#2){");
  fprintf(outfile, "\\vbox to#2\\PSTeXunit\\bgroup\n");
  fprintf(outfile, "  \\def\\put(##1,##2)##3{\\unskip\\raise##2\\PSTeXunit\n");
  fprintf(outfile, "    \\rlap{\\kern##1\\PSTeXunit ##3}\\ignorespaces}%%\n");
  fprintf(outfile, "  \\def\\lrlap##1{\\hbox to0pt{\\hss ##1\\hss}}%%\n");
  fprintf(outfile, "  \\def\\ulap##1{\\vbox to0pt{\\vss ##1}}%%\n");
  fprintf(outfile, "  \\def\\dlap##1{\\vbox to0pt{##1\\vss}}%%\n");
  fprintf(outfile, "  \\def\\udlap##1{\\vbox to0pt{\\vss ##1\\vss}}%%\n");
  fprintf(outfile, "  \\def\\stack##1{\\halign{\\hfil ####\\hfil\\cr ##1\\crcr}}%%\n");
  fprintf(outfile, "  \\vss\\hbox to#1\\PSTeXunit\\bgroup\\ignorespaces}%%\n");
  fprintf(outfile, "\\def\\endPSTeXpicture{\\hss\\egroup\\egroup}\\fi\n");
  fprintf(outfile, "\\special{!\n");
  PSTEX_PS_init();
  fprintf(outfile, "}\n");
  
  PSTEX_angle = 0;
  PSTEX_justify = 0;
  PSTEX_labels = 0;
}

int PSTEX_scale(xs, ys)
     double xs, ys;
{
  register struct termentry *t = term;
  
  t->xmax = (unsigned int)(PSTEX_XMAX * xs);
  t->ymax = (unsigned int)(PSTEX_YMAX * ys);
  
  return TRUE;
}

void PSTEX_PS_graphics()
{
  static char GPFAR psg1[] = "0 setgray\n/%s findfont %d scalefont setfont\nnewpath\n";
  struct termentry *t = term;

  ps_page++;
  if (!ps_eps)
    fprintf(outfile,"%%%%Page: %d %d\n",ps_page,ps_page);

  fprintf(outfile,"gnudict begin\ngsave\n");
  fprintf(outfile,"%d %d translate\n",PSTEX_PS_XOFF,PSTEX_PS_YOFF);
  fprintf(outfile,"%.3f %.3f scale\n", (ps_eps ? 0.5 : 1.0)/PSTEX_PS_SC,
	  (ps_eps ? 0.5 : 1.0)/PSTEX_PS_SC);
  if (!ps_portrait)
    {
      fprintf(outfile, "90 rotate\n0 %d translate\n",
	      (int)(-PSTEX_PS_YMAX*ysize));
    }
  fprintf(outfile, psg1, ps_font, (t->v_char) );
  ps_path_count = 0;
  PS_relative_ok = FALSE;
  PS_pen_x = PS_pen_y = -4000;
  PS_taken = 0;
  PS_linetype_last = -1;
}

void PSTEX_graphics()
{
  struct termentry *t = term;

/*  
  fprintf(outfile, "\\vbox to%d\\PSTeXunit{\\vss\n", t->ymax);
  fprintf(outfile, "\\hbox to%d\\PSTeXunit{%%\n", t->xmax);
*/
  fprintf(outfile, "\\PSTeXpicture(%d,%d)\n", t->xmax, t->ymax);
  
  fprintf(outfile, "\\special{\"\n");
  PSTEX_PS_graphics();
  /* thwart the translation done by PS_graphics() */
  fprintf(outfile, "%f %f translate\n",
	  -PSTEX_PS_XOFF * (float)PSTEX_PS_SC, -PSTEX_PS_YOFF * (float)PSTEX_PS_SC);
  PSTEX_labels = (struct text_command *)NULL;
}

void PSTEX_put_text(x, y, str)
     unsigned int x, y;
     char str[];
{
  struct text_command* tc;
  
  /* ignore empty strings */
  if (str[0] == '\0')
    return;
  
  tc = (struct text_command*)alloc(sizeof(struct text_command),"pstex");
  tc->x = x;
  tc->y = y;
  tc->label = (char *)alloc(strlen(str) + 1,"pstex");
  strcpy(tc->label, str);
  tc->justify = PSTEX_justify;
  tc->angle = PSTEX_angle;
  
  tc->next = PSTEX_labels;
  PSTEX_labels = tc;
}

int PSTEX_justify_text(mode)
     enum JUSTIFY mode;
{
  PSTEX_justify = mode;
  return TRUE;
}

int PSTEX_text_angle(angle)
     int angle;
{
  /* rotated text is put in a short stack, and optionally uses 
   * postscript specials depending on PSTEX_rotate */
  PSTEX_angle = angle;
  return TRUE;
}


void PSTEX_reset()
{
}

void PSTEX_text()
{
  struct text_command* tc;
  
  PS_text();
  fprintf(outfile, "}\n");
  
  for (tc = PSTEX_labels; tc != (struct text_command*)NULL; tc = tc->next) {
    fprintf(outfile, "\\put(%d,%d){", tc->x, tc->y);
    switch (tc->angle) {
    case 0:
      switch (tc->justify) {
      case LEFT:
	fprintf(outfile, "\\udlap{\\rlap{%s}}", tc->label);
	break;
      case CENTRE:
	fprintf(outfile, "\\udlap{\\lrlap{%s}}", tc->label);
	break;
      case RIGHT:
	fprintf(outfile, "\\udlap{\\llap{%s}}", tc->label);
	break;
      }
      break;
    case 1: /* put text in a short stack */
      if (PSTEX_rotate) {
	fprintf(outfile, "%%\n\\special{ps: gsave currentpoint currentpoint translate\n");
	fprintf(outfile, "270 rotate neg exch neg exch translate}%%\n");
      }
      switch (tc->justify) {
      case LEFT:
	fprintf(outfile, "\\rlap{\\ulap{\\stack{%s}}}", tc->label);
	break;
      case CENTRE:
	fprintf(outfile, "\\lrlap{\\ulap{\\stack{%s}}}", tc->label);
	break;
      case RIGHT:
	fprintf(outfile, "\\llap{\\dlap{\\stack{%s}}}", tc->label);
	break;
      }
      if (PSTEX_rotate) {
	fprintf(outfile, "%%\n\\special{ps: currentpoint grestore moveto}%%\n");
      }
    }
    fprintf(outfile, "}%%\n");
  }
  
  while (PSTEX_labels) {
    tc = PSTEX_labels->next;
    free(PSTEX_labels->label);
    free(PSTEX_labels);
    PSTEX_labels = tc;
  }
/*  
  fprintf(outfile, "\\hss}}\n");
*/
  fprintf(outfile, "\\endPSTeXpicture\n");
}

