/*
 *
 * Turbo Mugs Version 1.0
 *
 * Original csh version written by Julian Tirado-Rives.  Translated
 * to C by James Blake.
 *
 * Options:
 *
 *   -d      Do not append a <control-d>
 *
 *   -n      Do not change the scale of the plot when in portrait mode.
 *
 *   -x      Number of plots desired in the  X-direction  (horizontal)
 *
 *   -y      Number of plots desired in the Y-direction  (vertical)
 *
 *   -o      Name of the PostScript output file to  be  produced.
 *           If  this  flag  is  not  used,  the  output  will be
 *           automatically piped to the printer and deleted.
 *
 *   -s      The input files are, in that order, left  and  right
 *           views of a stereopair.  The figures will be adjusted
 *           to a separation between equivalent positions of 6 cm
 *           (12 cm for double sized figures).  Typical command :
 *	     tm -x 4 -y 3 -r -s blank blank blank blank blank left right
 *
 *   -r      Remove all input files after finished.
 *
 *   -t      will reduce the thickness of the  lines  proportion-
 *           ally  to  the  scale  of  the plots themselves.  The
 *           default setting preserves the original thickness.
 */

#include <stdio.h>
#include <strings.h>

#ifndef TRUE
#define TRUE	1
#define FALSE	0
#endif

#ifndef PROLOGUE
#define PROLOGUE "/usr/local/lib/graphics.prologue"
#endif

#define MAXLINE 1024		/* Maximum string length. */

#define ADJUST  47		/* Adjustment for stereo placement */
#define SIZEX	3150
#define SIZEY	2400
#define TH	1000


char           *optarg;		/* Optional command line argument. */
int             optind;		/* Optional command line argument indicator. */
int             rmcount;	/* number of files to delete. */
char           *progname = NULL;/* Name of this program. */

char            infile[MAXLINE], outfile[MAXLINE];
char            buf[MAXLINE], tmpstr[MAXLINE];

int             portrait = FALSE, stereo = FALSE, delete = FALSE, thick = TRUE;
int             no_scale = FALSE, no_control_d = FALSE;
int             number_x, number_y, count, pltnu;

FILE           *fp, *pf;

main (argc, argv)
  int             argc;
  char           *argv[];
{
  float           scaleX, scaleY, scale;
  float           plot_off_x, plot_off_y, global_off_x, global_off_y;
  float           left_offx, right_offx;
  float           stereo_offset;
  float           position_x, position_y;
  float           offset_x, offset_y;

  progname = argv[0];		/* Save this program name. */
  get_options (argc, argv);	/* Read and process command line options. */
  rmcount = optind;		/* Save for deleteing files if requested */

  if (number_x == 0 || number_y == 0)
    usage ();

  scaleX = TH / number_x;
  scaleY = TH / number_y;

  scale = (scaleX < scaleY) ? scaleX : scaleY;

  plot_off_x = (SIZEX * scale) / TH;
  plot_off_y = (SIZEY * scale) / TH;
  global_off_x = (SIZEX - (plot_off_x * number_x)) / 2;
  global_off_y = (SIZEY - (plot_off_y * number_y)) / 2;

  if ((number_x > 2) || (number_y > 2)) {
    left_offx = ADJUST;
    right_offx = -ADJUST;
  } else {
    left_offx = 2 * ADJUST;
    right_offx = -2 * ADJUST;
  }

/*
 * open a file for saving
 */

  if (strlen (outfile) != 0)
    if (freopen (outfile, "w", stdout) == NULL) {
      sprintf (buf, "%s: can't open output file %s\n", progname, outfile);
      perror (buf);
      exit (1);
    }
/*
 * Process the portrait option
 */

  if (portrait) {
    if ((pf = fopen (PROLOGUE, "r")) == NULL) {
      sprintf (buf, "%s: Prologue file %s not found.\n", progname, PROLOGUE);
      perror (buf);
      exit (1);
    }
    while (fgets (buf, MAXLINE, pf) != NULL) {
      sscanf (buf, "%s", tmpstr);
      if (strcmp (tmpstr, "%%BoundingBox:") == 0) {
	fprintf (stdout, "%%%%BoundingBox: 0 320 612 792\n");
      } else {
	fputs (buf, stdout);
      }
    }
    fclose (pf);
    printf ("-90 rotate\n");
    if (!no_scale) {
      printf ("-2360 1200 translate\n");
    } else {
      printf ("-2600 -600 translate\n");
    }
    printf ("0 0 moveto\n");
    if (!no_scale)
      printf ("17 22 div dup scale\n");
    if (thick) {
      printf ("%%% Set a new line width\n");
      printf ("/W {currentpoint stroke moveto 0.7727 div setlinewidth} def\n");
      printf ("1 W\n");
    }
    for (; optind < argc; ++optind)
      copy_commands (argv);
  } else {
/*
 * write the full PostScript prologue
 */
    cat_file (PROLOGUE);
/*
 * write the global offsets
 */
    printf ("%d %d translate\n", (int) global_off_x, (int) global_off_y);
    count = 1;
    pltnu = 0;
    for (; optind < argc; ++optind) {
      if (2 * (pltnu / 2) == pltnu) {
	stereo_offset = left_offx;
      } else {
	stereo_offset = right_offx;
      }
      position_x = ((count - 1) % number_x);
      position_y = ((number_y - 1) - ((count - 1) / number_x));
      offset_x = position_x * plot_off_x;
      offset_y = position_y * plot_off_y;
      if (stereo)
	offset_x += stereo_offset;
      printf ("gsave\n");
      printf ("%d %d translate\n", (int) offset_x, (int) offset_y);
      printf ("%5.3f dup scale\n", scale / TH);
      if (thick) {
	printf ("%% Set a new line width\n");
	printf ("/W {currentpoint stroke moveto 0.7727 div setlinewidth} def\n");

	printf ("1 W\n");
      } copy_commands (argv);
      printf ("grestore\n");
      count++;
    }
  }
  printf ("showpage\n");
  printf ("restore\n");
  printf ("%% End File\n");
  if (!no_control_d) {
#ifdef CONTROL_D
    putchar (4);
    putchar ('\n');
#endif
  }
/*
 * delete the files
 */
  if (delete)
    for (; rmcount < argc; ++rmcount)
      unlink (argv[rmcount]);
  exit(0);
}

get_opt (argc, argv, options)
  int             argc;
  char          **argv, *options;
{
  char            opch, *str, *ptr;
  static int      flag = 0;
  static int      cur_argc;
  static char   **cur_argv;

  if (flag == 0) {
    cur_argc = argc;
    cur_argv = argv;
    flag = 1;
    optind = 1;
  }
  if (cur_argc <= 1)
    return -1;

  if (--cur_argc >= 1) {
    str = *++cur_argv;
    if (*str != '-')
      return -1;		/* Argument is not an option   */
    else {			/* Argument is an option */
      if ((ptr = index (options, opch = *++str)) != (char *) 0) {
	++optind;
	optarg = ++str;		/* Point to rest of argument if any  */
	if ((*++ptr == ':') && (*optarg == '\0')) {
	  if (--cur_argc <= 0)
	    return '?';
	  optarg = *++cur_argv;
	  ++optind;
	}
	return opch;
      } else if (opch == '-') {	/* End of options */
	++optind;
	return -1;
      } else
	return '?';
    }
  }
  return 0;			/* Should never be reached. */
}


get_options (argc, argv)	/* Read and process command line options. */
  int             argc;
  char           *argv[];
{
  int             opch;

  while ((opch = get_opt (argc, argv, "dno:prstx:y:")) != -1)
    switch (opch) {
    case 'd':
      no_control_d = TRUE;
      break;
    case 'n':
      no_scale = TRUE;
      break;
    case 'o':
      if (strlen (optarg))
	strcpy (outfile, optarg);
      break;
    case 'p':
      portrait = TRUE;
      number_x = 1;
      number_y = 1;
      break;
    case 'r':
      delete = TRUE;
      break;
    case 's':
      stereo = TRUE;
      break;
    case 't':
      thick = FALSE;
      break;
    case 'x':
      if (strlen (optarg))
	number_x = (int) atoi (optarg);
      break;
    case 'y':
      if (strlen (optarg))
	number_y = (int) atoi (optarg);
      break;
    default:
      usage ();
      break;
    }
}

cat_file (current_file)
  char           *current_file;
{

  if ((pf = fopen (current_file, "r")) == NULL) {
    fprintf (stderr, "%s: Prologue file %s not found.\n", progname, PROLOGUE);
    exit (1);
  }
  while (fgets (buf, MAXLINE, pf) != NULL) {
    fputs (buf, stdout);
  }
  fclose (pf);
}

copy_commands (argv)
  char           *argv[];
{
  strcpy (infile, argv[optind]);/* Current file to print. */
  if (strcmp ("blank", infile) != 0) {
    if ((fp = fopen (infile, "r")) == NULL) {
      fprintf (stderr, "%s: cannot open %s\n", progname, infile);
      exit (1);
    }
    pltnu++;
    while (fgets (buf, MAXLINE, fp) != NULL) {
      sscanf (buf, "%s", tmpstr);
      if (strcmp (tmpstr, "%%EndProlog") != 0) {
	continue;
      } else {
	while (fgets (buf, MAXLINE, fp) != NULL) {
	  sscanf (buf, "%s", tmpstr);
	  if (strcmp (tmpstr, "showpage") == 0) {
	    fclose (fp);
	  } else {
	    fputs (buf, stdout);
	  }
	}
      }
    }				/* finished cutting out plotfile */
  }
}

usage ()
{
  fprintf (stderr, "usage:\t%s [-x #] [-y #] [-d] [-n] [-o outfile] [-r] [-t] [-p] [-s]\n", progname);
  fprintf (stderr, "\t[blank] plotfile1 plotfile2 ...\n");
  exit (1);
}
