/*
 * mma2ltx.c - Copyright (C) 1994, 1995 by Giuseppe Ghibo`
 *
 * Written by Giuseppe Ghibo`
 *
 * Version 1.23 - 21 Jun 1995
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <math.h>
#include <time.h>
#include <ctype.h>

typedef int bool;
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif

#ifndef min
#define min(a, b) (a < b ? a : b)
#endif
#ifndef max
#define max(a, b) (a > b ? a : b)
#endif

struct pnts {
	float gx, gy, tx, ty;
};

struct point {
	float x, y;
};

struct scaletrasl {
	float Ax, Ay, Bx, By;
};

struct cw {
	float ctx, wtx, cgx, wgx, cty, wty, cgy, wgy;
};

struct TeXunits {
	float convfactor;
	char *strunit;
};

struct TeXunits TeXtable[] = {
  {72.0/25.4,"mm"},                     /* mm to bp */
  {72.0/2.54,"cm"},                     /* cm to bp */
  {72.0/72.27,"pt"},                    /* pt to bp */
  {1.0,"bp"},                           /* bp to bp */
  {72.0/72.27*12.0,"pc"},               /* pc to bp */
  {72.0,"in"},                          /* in to bp */
  {1238.0/1157.0*72.0/72.27,"dd"},      /* dd to bp */
  {1238.0/1157.0*12.0*72.0/72.27,"cc"}, /* cc to bp */
  {72.0/72.27/65536.0,"sp"},            /* sp to bp */
  {1.0,""}
};

/* Function prototypes */
void Mlprun(float,float,struct cw *);
void Mlp(float,float,struct scaletrasl *);
void Mlp1(float,float,float,float,float,float,float *,float *,bool *);
float strtobp(char *);
float bptounit(char *);
void stripext(char *,char *);
char *strtolwr(char *);


#ifdef MSDOS
#define NMAX 1000
#else
#define NMAX 10000
#endif /* MSDOS */

#define NMAXFILEIN 256 /* maximun number of files to process */
#define NMAXBBSUB  256
#define TMPLEN 1024
#define PROLOG "texmma22.pro"
#define OPTSWITCH1 '-'
#define OPTSWITCH2 '/'

char tmpbuf1[TMPLEN], tmpbuf2[TMPLEN], fnametex[256], namebuf[256];
char errbuf[512];

struct pnts *p;
bool Mnodistort = TRUE;              /* keep the aspect ratio ? */
int np = 0;

/* This is the Mathematica v2.2 prologue file (extracted) */
char prologue[] = {
"/Mlmarg 0 def /Mrmarg 0 def /Mbmarg 0 def /Mtmarg 0 def /Mtransform{}\n"
"bind def /Mfixwid true def /Mfixdash false def /Mrot 0 def /Mpstart{\n"
"MathPictureStart}bind def /Mpend{MathPictureEnd}bind def /Mscale{0 1 0 1\n"
"5 -1 roll MathScale}bind def /ISOLatin1Encoding dup where{pop pop}{[\n"
"/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
"/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
"/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
"/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
"/space /exclam /quotedbl /numbersign /dollar /percent /ampersand\n"
"/quoteright /parenleft /parenright /asterisk /plus /comma /minus /period\n"
"/slash /zero /one /two /three /four /five /six /seven /eight /nine\n"
"/colon /semicolon /less /equal /greater /question /at /A /B /C /D /E /F\n"
"/G /H /I /J /K /L /M /N /O /P /Q /R /S /T /U /V /W /X /Y /Z /bracketleft\n"
"/backslash /bracketright /asciicircum /underscore /quoteleft /a /b /c /d\n"
"/e /f /g /h /i /j /k /l /m /n /o /p /q /r /s /t /u /v /w /x /y /z\n"
"/braceleft /bar /braceright /asciitilde /.notdef /.notdef /.notdef\n"
"/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
"/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /dotlessi /grave\n"
"/acute /circumflex /tilde /macron /breve /dotaccent /dieresis /.notdef\n"
"/ring /cedilla /.notdef /hungarumlaut /ogonek /caron /space /exclamdown\n"
"/cent /sterling /currency /yen /brokenbar /section /dieresis /copyright\n"
"/ordfeminine /guillemotleft /logicalnot /hyphen /registered /macron\n"
"/degree /plusminus /twosuperior /threesuperior /acute /mu /paragraph\n"
"/periodcentered /cedilla /onesuperior /ordmasculine /guillemotright\n"
"/onequarter /onehalf /threequarters /questiondown /Agrave /Aacute\n"
"/Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla /Egrave /Eacute\n"
"/Ecircumflex /Edieresis /Igrave /Iacute /Icircumflex /Idieresis /Eth\n"
"/Ntilde /Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply\n"
"/Oslash /Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn\n"
"/germandbls /agrave /aacute /acircumflex /atilde /adieresis /aring /ae\n"
"/ccedilla /egrave /eacute /ecircumflex /edieresis /igrave /iacute\n"
"/icircumflex /idieresis /eth /ntilde /ograve /oacute /ocircumflex\n"
"/otilde /odieresis /divide /oslash /ugrave /uacute /ucircumflex\n"
"/udieresis /yacute /thorn /ydieresis]def}ifelse /MFontDict 50 dict def\n"
"/MStrCat{exch dup length 2 index length add string dup 3 1 roll copy\n"
"length exch dup 4 2 roll exch putinterval}def /MCreateEncoding{1 index\n"
"255 string cvs(-)MStrCat 1 index MStrCat cvn exch(Encoding)MStrCat cvn\n"
"dup where{exch get}{pop StandardEncoding}ifelse 3 1 roll dup MFontDict\n"
"exch known not{1 index findfont dup length dict begin{1 index /FID ne{\n"
"def}{pop pop}ifelse}forall /Encoding 3 index def currentdict end 1 index\n"
"exch definefont pop MFontDict 1 index null put}if exch pop exch pop}def\n"
"/ISOLatin1{(ISOLatin1)MCreateEncoding}def /ISO8859{(ISOLatin1)\n"
"MCreateEncoding}def /Mcopyfont{dup maxlength dict exch{1 index /FID eq{\n"
"pop pop}{2 index 3 1 roll put}ifelse}forall}def /Plain /Courier findfont\n"
"Mcopyfont definefont pop /Bold /Courier-Bold findfont Mcopyfont\n"
"definefont pop /Italic /Courier-Oblique findfont Mcopyfont definefont\n"
"pop /MathPictureStart{gsave Mtransform Mlmarg Mbmarg translate Mwidth\n"
"Mlmarg Mrmarg add sub /Mwidth exch def Mheight Mbmarg Mtmarg add sub\n"
"/Mheight exch def /Mtmatrix matrix currentmatrix def /Mgmatrix matrix\n"
"currentmatrix def}bind def /MathPictureEnd{grestore}bind def /MFill{0 0\n"
"moveto Mwidth 0 lineto Mwidth Mheight lineto 0 Mheight lineto fill}bind\n"
"def /MPlotRegion{3 index Mwidth mul 2 index Mheight mul translate exch\n"
"sub Mheight mul /Mheight exch def exch sub Mwidth mul /Mwidth exch def}\n"
"bind def /MathSubStart{Momatrix Mgmatrix Mtmatrix Mwidth Mheight 7 -2\n"
"roll moveto Mtmatrix setmatrix currentpoint Mgmatrix setmatrix 9 -2 roll\n"
"moveto Mtmatrix setmatrix currentpoint 2 copy translate /Mtmatrix matrix\n"
"currentmatrix def 3 -1 roll exch sub /Mheight exch def sub /Mwidth exch\n"
"def}bind def /MathSubEnd{/Mheight exch def /Mwidth exch def /Mtmatrix\n"
"exch def dup setmatrix /Mgmatrix exch def /Momatrix exch def}bind def\n"
"/Mdot{moveto 0 0 rlineto stroke}bind def /Mtetra{moveto lineto lineto\n"
"lineto fill}bind def /Metetra{moveto lineto lineto lineto closepath\n"
"gsave fill grestore 0 setgray stroke}bind def /Mistroke{flattenpath 0 0\n"
"0{4 2 roll pop pop}{4 -1 roll 2 index sub dup mul 4 -1 roll 2 index sub\n"
"dup mul add sqrt 4 -1 roll add 3 1 roll}{stop}{stop}pathforall pop pop\n"
"currentpoint stroke moveto currentdash 3 -1 roll add setdash}bind def\n"
"/Mfstroke{stroke currentdash pop 0 setdash}bind def /Mrotsboxa{gsave dup\n"
"/Mrot exch def Mrotcheck Mtmatrix dup setmatrix 7 1 roll 4 index 4 index\n"
"translate rotate 3 index -1 mul 3 index -1 mul translate /Mtmatrix\n"
"matrix currentmatrix def grestore Msboxa 3 -1 roll /Mtmatrix exch def\n"
"/Mrot 0 def}bind def /Msboxa{newpath 5 -1 roll Mvboxa pop Mboxout 6 -1\n"
"roll 5 -1 roll 4 -1 roll Msboxa1 5 -3 roll Msboxa1 Mboxrot[7 -2 roll 2\n"
"copy[3 1 roll 10 -1 roll 9 -1 roll]6 1 roll 5 -2 roll]}bind def /Msboxa1\n"
"{sub 2 div dup 2 index 1 add mul 3 -1 roll -1 add 3 -1 roll mul}bind def\n"
"/Mvboxa{Mfixwid{Mvboxa1}{dup Mwidthcal 0 exch{add}forall exch Mvboxa1 4\n"
"index 7 -1 roll add 4 -1 roll pop 3 1 roll}ifelse}bind def /Mvboxa1{\n"
"gsave newpath[true 3 -1 roll{Mbbox 5 -1 roll{0 5 1 roll}{7 -1 roll exch\n"
"sub(m)stringwidth pop .3 mul sub 7 1 roll 6 -1 roll 4 -1 roll Mmin 3 -1\n"
"roll 5 index add 5 -1 roll 4 -1 roll Mmax 4 -1 roll}ifelse false}forall{\n"
"stop}if counttomark 1 add 4 roll]grestore}bind def /Mbbox{1 dict begin 0\n"
"0 moveto /temp(T)def{gsave currentpoint newpath moveto temp 0 3 -1 roll\n"
"put temp false charpath flattenpath currentpoint pathbbox grestore\n"
"moveto lineto moveto}forall pathbbox newpath end}bind def /Mmin{2 copy\n"
"gt{exch}if pop}bind def /Mmax{2 copy lt{exch}if pop}bind def /Mrotshowa{\n"
"dup /Mrot exch def Mrotcheck Mtmatrix dup setmatrix 7 1 roll 4 index 4\n"
"index translate rotate 3 index -1 mul 3 index -1 mul translate /Mtmatrix\n"
"matrix currentmatrix def Mgmatrix setmatrix Mshowa /Mtmatrix exch def\n"
"/Mrot 0 def}bind def /Mshowa{4 -2 roll moveto 2 index Mtmatrix setmatrix\n"
"Mvboxa 7 1 roll Mboxout 6 -1 roll 5 -1 roll 4 -1 roll Mshowa1 4 1 roll\n"
"Mshowa1 rmoveto currentpoint Mfixwid{Mshowax}{Mshoway}ifelse pop pop pop\n"
"pop Mgmatrix setmatrix}bind def /Mshowax{0 1 4 index length -1 add{2\n"
"index 4 index 2 index get 3 index add moveto 4 index exch get Mfixdash{\n"
"Mfixdashp}if show}for}bind def /Mfixdashp{dup length 1 gt 1 index true\n"
"exch{45 eq and}forall and{gsave(--)stringwidth pop(-)stringwidth pop sub\n"
"2 div 0 rmoveto dup length 1 sub{(-)show}repeat grestore}if}bind def\n"
"/Mshoway{3 index Mwidthcal 5 1 roll 0 1 4 index length -1 add{2 index 4\n"
"index 2 index get 3 index add moveto 4 index exch get[6 index aload\n"
"length 2 add -1 roll{pop Strform stringwidth pop neg exch add 0 rmoveto}\n"
"exch kshow cleartomark}for pop}bind def /Mwidthcal{[exch{Mwidthcal1}\n"
"forall][exch dup Maxlen -1 add 0 1 3 -1 roll{[exch 2 index{1 index Mget\n"
"exch}forall pop Maxget exch}for pop]Mreva}bind def /Mreva{[exch aload\n"
"length -1 1{1 roll}for]}bind def /Mget{1 index length -1 add 1 index ge{\n"
"get}{pop pop 0}ifelse}bind def /Maxlen{[exch{length}forall Maxget}bind\n"
"def /Maxget{counttomark -1 add 1 1 3 -1 roll{pop Mmax}for exch pop}bind\n"
"def /Mwidthcal1{[exch{Strform stringwidth pop}forall]}bind def /Strform{\n"
"/tem(x)def tem 0 3 -1 roll put tem}bind def /Mshowa1{2 copy add 4 1 roll\n"
"sub mul sub -2 div}bind def /MathScale{Mwidth Mheight Mlp translate\n"
"scale /yscale exch def /ybias exch def /xscale exch def /xbias exch def\n"
"/Momatrix xscale yscale matrix scale xbias ybias matrix translate matrix\n"
"concatmatrix def /Mgmatrix matrix currentmatrix def}bind def /Mlp{3 copy\n"
"Mlpfirst{Mnodistort{Mmin dup}if 4 index 2 index 2 index Mlprun 11 index\n"
"11 -1 roll 10 -4 roll Mlp1 8 index 9 -5 roll Mlp1 4 -1 roll and{exit}if\n"
"3 -1 roll pop pop}loop exch 3 1 roll 7 -3 roll pop pop pop}bind def\n"
"/Mlpfirst{3 -1 roll dup length 2 copy -2 add get aload pop pop pop 4 -2\n"
"roll -1 add get aload pop pop pop 6 -1 roll 3 -1 roll 5 -1 roll sub div\n"
"4 1 roll exch sub div}bind def /Mlprun{2 copy 4 index 0 get dup 4 1 roll\n"
"Mlprun1 3 copy 8 -2 roll 9 -1 roll{3 copy Mlprun1 3 copy 11 -3 roll /gt\n"
"Mlpminmax 8 3 roll 11 -3 roll /lt Mlpminmax 8 3 roll}forall pop pop pop\n"
"pop 3 1 roll pop pop aload pop 5 -1 roll aload pop exch 6 -1 roll\n"
"Mlprun2 8 2 roll 4 -1 roll Mlprun2 6 2 roll 3 -1 roll Mlprun2 4 2 roll\n"
"exch Mlprun2 6 2 roll}bind def /Mlprun1{aload pop exch 6 -1 roll 5 -1\n"
"roll mul add 4 -2 roll mul 3 -1 roll add}bind def /Mlprun2{2 copy add 2\n"
"div 3 1 roll exch sub}bind def /Mlpminmax{cvx 2 index 6 index 2 index\n"
"exec{7 -3 roll 4 -1 roll}if 1 index 5 index 3 -1 roll exec{4 1 roll pop\n"
"5 -1 roll aload pop pop 4 -1 roll aload pop[8 -2 roll pop 5 -2 roll pop\n"
"6 -2 roll pop 5 -1 roll]4 1 roll pop}{pop pop pop}ifelse}bind def /Mlp1{\n"
"5 index 3 index sub 5 index 2 index mul 1 index le 1 index 0 le or dup\n"
"not{1 index 3 index div .99999 mul 8 -1 roll pop 7 1 roll}if 8 -1 roll 2\n"
"div 7 -2 roll pop sub 5 index 6 -3 roll pop pop mul sub exch}bind def\n"
"/intop 0 def /inrht 0 def /inflag 0 def /outflag 0 def /xadrht 0 def\n"
"/xadlft 0 def /yadtop 0 def /yadbot 0 def /Minner{outflag 1 eq{/outflag\n"
"0 def /intop 0 def /inrht 0 def}if 5 index gsave Mtmatrix setmatrix\n"
"Mvboxa pop grestore 3 -1 roll pop dup intop gt{/intop exch def}{pop}\n"
"ifelse dup inrht gt{/inrht exch def}{pop}ifelse pop /inflag 1 def}bind\n"
"def /Mouter{/xadrht 0 def /xadlft 0 def /yadtop 0 def /yadbot 0 def\n"
"inflag 1 eq{dup 0 lt{dup intop mul neg /yadtop exch def}if dup 0 gt{dup\n"
"intop mul /yadbot exch def}if pop dup 0 lt{dup inrht mul neg /xadrht\n"
"exch def}if dup 0 gt{dup inrht mul /xadlft exch def}if pop /outflag 1\n"
"def}{pop pop}ifelse /inflag 0 def /inrht 0 def /intop 0 def}bind def\n"
"/Mboxout{outflag 1 eq{4 -1 roll xadlft leadjust add sub 4 1 roll 3 -1\n"
"roll yadbot leadjust add sub 3 1 roll exch xadrht leadjust add add exch\n"
"yadtop leadjust add add /outflag 0 def /xadlft 0 def /yadbot 0 def\n"
"/xadrht 0 def /yadtop 0 def}if}bind def /leadjust{(m)stringwidth pop .5\n"
"mul}bind def /Mrotcheck{dup 90 eq{yadbot /yadbot xadrht def /xadrht\n"
"yadtop def /yadtop xadlft def /xadlft exch def}if dup cos 1 index sin\n"
"Checkaux dup cos 1 index sin neg exch Checkaux 3 1 roll pop pop}bind def\n"
"/Checkaux{4 index exch 4 index mul 3 1 roll mul add 4 1 roll}bind def\n"
"/Mboxrot{Mrot 90 eq{brotaux 4 2 roll}if Mrot 180 eq{4 2 roll brotaux 4 2\n"
"roll brotaux}if Mrot 270 eq{4 2 roll brotaux}if}bind def /brotaux{neg\n"
"exch neg}bind def /Mabsproc{0 matrix defaultmatrix dtransform\n"
"idtransform dup mul exch dup mul add sqrt}bind def /Mabswid{Mabsproc\n"
"setlinewidth}bind def /Mabsdash{exch[exch{Mabsproc}forall]exch setdash}\n"
"bind def /MBeginOrig{Momatrix concat}bind def /MEndOrig{Mgmatrix\n"
"setmatrix}bind def /sampledsound where{pop}{/sampledsound{exch pop exch\n"
"5 1 roll mul 4 idiv mul 2 idiv exch pop exch /Mtempproc exch def{\n"
"Mtempproc pop}repeat}bind def}ifelse /g{setgray}bind def /k{\n"
"setcmykcolor}bind def /m{moveto}bind def /p{gsave}bind def /r{\n"
"setrgbcolor}bind def /w{setlinewidth}bind def /C{curveto}bind def /F{\n"
"fill}bind def /L{lineto}bind def /P{grestore}bind def /s{stroke}bind def\n"
"/setcmykcolor where{pop}{/setcmykcolor{4 1 roll[4 1 roll]{1 index sub 1\n"
"sub neg dup 0 lt{pop 0}if dup 1 gt{pop 1}if exch}forall pop setrgbcolor}\n"
"bind def}ifelse /Mcharproc{currentfile(x)readhexstring pop 0 get exch\n"
"div}bind def /Mshadeproc{dup 3 1 roll{dup Mcharproc 3 1 roll}repeat 1 eq\n"
"{setgray}{3 eq{setrgbcolor}{setcmykcolor}ifelse}ifelse}bind def\n"
"/Mrectproc{3 index 2 index moveto 2 index 3 -1 roll lineto dup 3 1 roll\n"
"lineto lineto fill}bind def /Mcolorimage{7 1 roll pop pop matrix\n"
"invertmatrix concat 2 exch exp 1 sub 3 1 roll 1 1 2 index{1 1 4 index{\n"
"dup 1 sub exch 2 index dup 1 sub exch 7 index 9 index Mshadeproc\n"
"Mrectproc}for pop}for pop pop pop pop}bind def /Mimage{pop matrix\n"
"invertmatrix concat 2 exch exp 1 sub 3 1 roll 1 1 2 index{1 1 4 index{\n"
"dup 1 sub exch 2 index dup 1 sub exch 7 index Mcharproc setgray\n"
"Mrectproc}for pop}for pop pop pop}bind def\n" };

void main(argc,argv)
int argc;
char *argv[];
{
	float width = 161.0;         /* Picture width in bp */
	float height = 100.0;        /* Picture height in bp */
	float aspectratio = 0.61803; /* MMA aspect ratio */
	float convfactor;            /* conversion factor from bp to a TeX's unit */
	bool widthchoosen = FALSE;   /* the width has been choosen ? */
	bool heightchoosen = FALSE;  /* the height has been choosen ? */
	bool enclosemath = TRUE;     /* enclose MMA labels in $...$ ? */
	bool addfbox = FALSE;        /* enclose the picture into an \fbox ? */
	bool addfontsize = FALSE;    /* change default font size ? */
	bool nofnameout = TRUE;      /* output filename specified ? */
	bool substbboffs = FALSE;    /* substitute text bb offsets ? */
	bool includeprolog = FALSE;  /* include the PostScript prolog ? */
	bool usedefprolog = TRUE;    /* use the default PostScript prolog ? */
	bool whitebg = FALSE;        /* white background in mmaputtex ? */
	bool useescseq = FALSE;      /* use escape sequence ? */
	bool drawarrow = FALSE;      /* draw axes arrow ? */
	bool drawxarrow = FALSE;     /* draw x-axis arrow ? */
	bool drawyarrow = FALSE;     /* draw y-axis arrow ? */
	struct scaletrasl st, mat;
	int i, j, k, nfilein = 0;
	char *tmpptr;
	char *fnamein[NMAXFILEIN];
	char *fnameout = "";
	char *fboxsep  = "0pt";
	char *fontsize = "";
	char outunit[3];
	char tmpunit1[3], tmpunit2[3];
	char *prologuename  = NULL;
	char *escstring = "";
	FILE *filein, *fileout, *filetex;
	long tc;        /* for time/date */
	struct tm *tp;  /* for time/date */
	float *bboffx_old, *bboffy_old, *bboffx_new, *bboffy_new,
	      *bbaddx_new, *bbaddy_new;
	int nbbsubs = 0;             /* number of bb substitutions */
	float xmax, xmin, ymax, ymin;
	float xarrow_length = 0.025; /* length of the x-axis arrow */
	float xarrow_width  = 0.012; /* width of the x-axis arrow */
	float xarrow_inset  = 0.006; /* inset of the x-axis arrow */
	float yarrow_length = 0.025; /* length of the y-axis arrow */
	float yarrow_width  = 0.012; /* width of the y-axis arrow */
	float yarrow_inset  = 0.006; /* inset of the y-axis arrow */

	if ((p = malloc(sizeof(struct pnts) * NMAX)) == NULL)
	{
		fprintf(stderr,"Error: not enough memory! (need %u bytes)\n",
		        sizeof(struct pnts) * NMAX);
		exit(1);
	}

	if ( (bboffx_old = malloc(sizeof(float) * NMAXBBSUB)) == NULL ||
	     (bboffy_old = malloc(sizeof(float) * NMAXBBSUB)) == NULL ||
	     (bboffx_new = malloc(sizeof(float) * NMAXBBSUB)) == NULL ||
	     (bboffy_new = malloc(sizeof(float) * NMAXBBSUB)) == NULL ||
	     (bbaddx_new = malloc(sizeof(float) * NMAXBBSUB)) == NULL ||
	     (bbaddy_new = malloc(sizeof(float) * NMAXBBSUB)) == NULL )
	{
		fprintf(stderr,"Error: not enough memory! (need %u - %u bytes)\n",
		        sizeof(float) * NMAXBBSUB, 6 * sizeof(float) * NMAXBBSUB);
		exit(1);
	}

	printf("mma2ltx v1.23 - Copyright (C) 1994, 1995 by Giuseppe Ghibo`\n\n");

	strcpy(outunit,"bp");

/* scan options */
	for (i = 1; i < argc; i++)
	{
		if (*argv[i] == OPTSWITCH1 || *argv[i] == OPTSWITCH2)
		{
			char *s = argv[i] + 2; /* skip next char */
			char opt = argv[i][1]; /* option string */

			switch (opt)
			{
				case 'w': case 'W':
					if (*s == '\0' && argv[i+1] && *argv[i+1] != OPTSWITCH1 && *argv[i+1] != OPTSWITCH2)
						s = argv[++i];
					width = strtobp(s);
					widthchoosen = TRUE; /* a width has been choosen */
					break;

				case 'h': case 'H':
					if (*s == '\0' && argv[i+1] && *argv[i+1] != OPTSWITCH1 && *argv[i+1] != OPTSWITCH2)
						s = argv[++i];
					height=strtobp(s);
					heightchoosen = TRUE; /* an height has been choosen */
					break;

				case 'd': case 'D':
					Mnodistort = FALSE;
					break;

				case '?':
					fprintf(stderr,"Usage: mma2ltx [<options>] <filename(s)> [<options>]\n"
					       "Where <options> is one or more of:\n\n"
					       "\t  -?  Show these messages\n"
					       "\t  -d  Don't keep the aspect ratio\n"
					       "\t  -n  Deactivate automatic $...$ enclosing\n"
					       "\t  -b  Enclose every string into a white box (default = transpar. box)\n"
					       "\t  -p[<str>] Include the Mathematica PostScript prologue in the .EPS file\n"
					       "\t  -h[<dimen>] Set picture height to <dimen> (default = 100bp)\n"
					       "\t  -w[<dimen>] Set picture width  to <dimen> (default = 161bp)\n"
					       "\t  -f[<dimen>] Add an \\fbox to the picture (\\fboxsep=<dimen>)\n"
					       "\t  -u<unit> Set all dimensions in the unit <unit>\n"
					       "\t  -s<cmd>  Set the font size with the TeX command <cmd>\n"
					       "\t  -o<str>  Output filename\n"
					       "\t  -e<str>  Change only MMA labels which begin with <str>\n"
					       "\t  -c(sx,sy)=(newsx,newsy)(<dimen>,<dimen>) (change alignment)\n"
					       "\t  -a[<num>:<num>:<num>] Draw arrows on x and y axes\n\n"
					       "\t  <dimen> = a number followed by one of TeX's unit (e.g. 10.3cm)\n"
					       "\t  <num>   = a number (e.g. 0.0125)\n"
					       "\t  <unit>  = a TeX's unit (e.g. cm)\n"
					       "\t  <cmd>   = a TeX command without the backslash '\\'\n"
					       "\t  <str>   = a text string\n\n"
					       "Example:\n"
					       "\t mma2ltx -sfootnotesize -w5in pic1.ps pic2.ps\n"
					       "processes the files `pic1.ps' and `pic2.ps'. The width of the pictures\n"
					       "will be 5 inch and \\footnotesize will be used as LaTeX command to\n"
					       "set the font size.\n");
					exit(1);

				case 'n': case 'N':
					enclosemath = FALSE;
					break;

				case 'o': case 'O':
					if (*s == '\0' && argv[i+1] && *argv[i+1] != OPTSWITCH1 && *argv[i+1] != OPTSWITCH2)
						s = argv[++i];
					fnameout = s;
					nofnameout = FALSE;
					break;

				case 's': case 'S':
					if (*s == '\0' && argv[i+1] && *argv[i+1] != OPTSWITCH1 && *argv[i+1] != OPTSWITCH2)
						s = argv[++i];
					addfontsize = TRUE;
					if (*s != '\0')
						fontsize = s;
					break;

				case 'f': case 'F':
					if (*s == '\0' && argv[i+1] && *argv[i+1] != OPTSWITCH1 && *argv[i+1] != OPTSWITCH2)
						s = argv[++i];
					addfbox = TRUE;
					if (*s != '\0')
						fboxsep = s;
					break;

				case 'u': case 'U':
					if (*s == '\0' && argv[i+1] && *argv[i+1] != OPTSWITCH1 && *argv[i+1] != OPTSWITCH2)
						s = argv[++i];
					sscanf(s,"%2s",outunit);
					break;

				case 'c': case 'C':
				{
					float oldoffx, oldoffy, newoffx, newoffy, addoffx, addoffy;

					if (*s=='\0' && argv[i+1])
						s = argv[++i];

					k = sscanf(s,"(%f,%f)=(%f,%f)(%f%2s,%f%2s)",
							&oldoffx,&oldoffy,&newoffx,&newoffy,
							&addoffx,tmpunit1,&addoffy,tmpunit2);
					if (k != 8)
					{
						fprintf(stderr,"Warning: option '-c %s': bad argument!\n",s);
						break;
					}
					sprintf(tmpbuf1,"%f%2s",addoffx,tmpunit1);
					sprintf(tmpbuf2,"%f%2s",addoffy,tmpunit2);
					addoffx = strtobp(tmpbuf1);
					addoffy = strtobp(tmpbuf2);

					bboffx_old[nbbsubs] = oldoffx;
					bboffy_old[nbbsubs] = oldoffy;
					bboffx_new[nbbsubs] = newoffx;
					bboffy_new[nbbsubs] = newoffy;
					bbaddx_new[nbbsubs] = addoffx;
					bbaddy_new[nbbsubs] = addoffy;
					nbbsubs++;

					if (!substbboffs)
						substbboffs = TRUE;

					break;
				}

				case 'p': case 'P':
					if (*s == '\0' && argv[i+1] && *argv[i+1] != OPTSWITCH1 && *argv[i+1] != OPTSWITCH2)
						s = argv[++i];
					if (*s != '\0')
					{
						prologuename = s;
						usedefprolog = FALSE;
					}
					includeprolog = TRUE;
					break;

				case 'b': case 'B':
					whitebg = TRUE;
					break;

				case 'e': case 'E':
					if (*s == '\0' && argv[i+1] && *argv[i+1] != OPTSWITCH1 && *argv[i+1] != OPTSWITCH2)
						s = argv[++i];
					if (*s != '\0')
					{
						escstring = s;
						useescseq = TRUE;
					}
					break;

				case 'a': case 'A':
					if (*s == '\0' && argv[i+1] && *argv[i+1] != OPTSWITCH1 && *argv[i+1] != OPTSWITCH2)
						s = argv[++i];
					if (*s != '\0')
					{
						float length, width, inset;

						if (sscanf(s, "%f:%f:%f", &length, &width, &inset) == 3)
						{
							xarrow_length = yarrow_length = length;
							xarrow_width  = yarrow_width = width;
							xarrow_inset  = yarrow_inset = inset;
						}
						else
							fprintf(stderr,"Warning: option '-a %s': bad argument!\n", s);
					}
					drawarrow = TRUE;
					break;

				default:
					break;
			}
		}
		else
		{
			if (nfilein >= NMAXFILEIN)
			{
				fprintf(stderr,"Error: Can't process more than %d files!\n", NMAXFILEIN);
				exit(1);
			}
			else
				fnamein[nfilein++] = argv[i];
		}
	}

	if (nfilein == 0)
	{
		fprintf(stderr,"Error: You must specify at least one filename to process!\n");
		exit(1);
	}

	if (nfilein > 1 && !nofnameout)
	{
		fprintf(stderr,"Error: You can't specify the output name in multiple files mode!\n");
		exit(1);
	}

/* Main loop */
	for (j = 0; j < nfilein; j++)
	{
		if ((filein = fopen(fnamein[j], "r")) == NULL)
		{
			sprintf(errbuf,"Warning: Can't open file '%s' (r)", fnamein[j]);
			perror(errbuf);
			continue;
		}

		printf("Processing picture '%s' ", fnamein[j]);
		fflush(stdout);

		if (*fnameout == '\0' || nofnameout)
		{
			stripext(tmpbuf1, fnamein[j]);
			strcat(tmpbuf1, ".eps");
			strncpy(namebuf,tmpbuf1,256);
			fnameout = namebuf;
		}

		if ((fileout = fopen(fnameout, "w")) == NULL)
		{
			sprintf(errbuf, "Error: Can't open file '%s' (w)", fnameout);
			perror(errbuf);
			exit(1);
		}

/* search aspect ratio */
		while ((fgets(tmpbuf1, TMPLEN, filein) != NULL))
		{
			if ((tmpptr = strstr(tmpbuf1,"AspectRatio")) != NULL)
			{
				tmpptr += 12;
				sscanf(tmpptr, "%f", &aspectratio);
				break;
			}
		}

		mat.Ax = 0.0;
		mat.Ay = 0.0;
		mat.Bx = 0.0;
		mat.By = 0.0;

/* get transformation matrix */
		while ((fgets(tmpbuf1, TMPLEN, filein) != NULL))
		{
			if (strstr(tmpbuf1, "Scaling calc") != NULL)
			{
				fgets(tmpbuf1, TMPLEN, filein);
				sscanf(tmpbuf1, "%f %f %f %f [", &mat.Bx, &mat.Ax, &mat.By, &mat.Ay);
				break;
			}
		}

/* test for axes arrows */
		if (drawarrow)
		{
			xmin = - mat.Bx / mat.Ax;
			xmax = (1.0 - mat.Bx) / mat.Ax;
			ymin = - mat.By / mat.Ay;
			ymax = (aspectratio - mat.By) / mat.Ay;

			if (xmax >= 0.0 && xmin <= 0.0)
				drawyarrow = TRUE;
			if (ymax >= 0.0 && ymin <= 0.0)
				drawxarrow = TRUE;
		}

/* get size */
		np = 0;
		while ((fgets(tmpbuf1, TMPLEN, filein) != NULL) && (np < NMAX))
		{
			float gx, gy, tx, ty;
			if (strstr(tmpbuf1,"] MathSca") != NULL)
				break;
			if (sscanf(tmpbuf1,"[ %f %f %f %f ]",&gx, &gy, &tx, &ty) == 4)
			{
				p[np].gx = gx;
				p[np].gy = gy;
				p[np].tx = tx;
				p[np++].ty = ty;
			}
		}

		stripext(fnametex, fnameout);
		strcat(fnametex, ".tex");

		if ((filetex=fopen(fnametex,"w")) == NULL)
		{
			sprintf(errbuf, "Error: Can't open file '%s' (w)", fnametex);
			perror(errbuf);
			exit(1);
		}
		rewind(filein);

/* compute new scale factor */
		if (widthchoosen && !heightchoosen)
			height = width * aspectratio;
		else if (heightchoosen && !widthchoosen)
			width = height / aspectratio;

		if (np < 2)
		{
			p[0].gx = -0.001;
			p[0].gy = -0.001;
			p[0].tx = 0.0;
			p[0].ty = 0.0;
			p[1].gx = 1.001;
			p[1].gy = 0.61903;
			p[1].tx = 0.0;
			p[1].ty = 0.0;
			np = 2;
		}

		Mlp(width,height,&st);

/* Prepare PostScript file */
		time(&tc); /* get current time */
		tp = localtime(&tc);

		fprintf(fileout,"%%!PS-Adobe-2.0 EPSF-2.0\n"
				"%%%%BoundingBox: 0 0 %.0f %.0f\n"
				"%%%%Title: %s\n"
				"%%%%Creator: mma2ltx v1.23\n"
				"%%%%CreationDate: %s"
				"%%%%EndComments\n"
				"%%Mma2ltxCommandLine: ", ceil(width), ceil(height), fnameout, asctime(tp));
		for (i = 0; i < argc; i++)
			fprintf(fileout,"%s ",argv[i]);
		fprintf(fileout,"\n");

		if (!includeprolog)
		{
			fprintf(fileout,"%%Mma2ltxComment: For use with Mathematica prologue '%s'\n", PROLOG);
			fprintf(fileout,"Mathdict begin\n"
				   "/Mwidth %.2f def\n"
				   "/Mheight %.2f def\n"
				   "/Mnodistort %s def\n",width,height,(Mnodistort ? "true" : "false"));
		}
		else /* include prologue */
		{
			if (!usedefprolog)
			{
				FILE *tmpfp;

				if ((tmpfp = fopen(prologuename, "r")) == NULL)
				{
					fprintf(stderr,"\nWarning: prologue file `%s' not found. Use default prologue `%s'\n", prologuename, PROLOG);
					usedefprolog = TRUE;
				}
				else
				{
					int c, c1, c2, c3, c4;

					fprintf(fileout,"%%%%BeginProcSet: %s\n", prologuename);
					while (fgets(tmpbuf1, TMPLEN, tmpfp) != NULL)
					{
						if (strstr(tmpbuf1, "Mathdict begin") != NULL)
						{
							fputs(tmpbuf1,fileout);
							fprintf(fileout,"/Mwidth %.2f def\n"
									"/Mheight %.2f def\n"
									"/Mnodistort %s def\n", width, height, (Mnodistort ? "true" : "false"));
							break;
						}
						else
							fputs(tmpbuf1, fileout);
					}

					while ((c = fgetc(tmpfp)) != EOF)
					{
						if (c == 'e')   /* search the last 'end' occurrence */
						{
							if ((c1 = fgetc(tmpfp)) == 'n')
							{
								if ((c2 = fgetc(tmpfp)) == 'd')
								{
									if ((c3 = fgetc(tmpfp)) == '\n' || c3 == '\r')
									{
										if ((c4 = fgetc(tmpfp)) == EOF)
										{
											break;  /* skip last 'end' occurrence */
										}
										else
										{
											ungetc(c4, tmpfp);
											fputc(c, fileout);
											fputc(c1, fileout);
											fputc(c2, fileout);
											fputc(c3, fileout);
										}
									}               
									else
									{
										ungetc(c3, tmpfp);
										fputc(c, fileout);
										fputc(c1, fileout);
										fputc(c2, fileout);
									}
								}
								else
								{
									ungetc(c2, tmpfp);
									fputc(c, fileout);
									fputc(c1, fileout);
								}
							}
							else
							{
								ungetc(c1, tmpfp);
								fputc(c, fileout);
							}
						}
						else
							fputc(c, fileout);      /* insert prologue file */
					}
					fclose(tmpfp);
				}
			}

			if (usedefprolog)
			{
				fprintf(fileout,"%%%%BeginProcSet: %s\n"
						"%% Mathematica v2.2 prologue\n"
						"/Mathdict 150 dict def\n"
						"Mathdict begin\n"
						"/Mwidth %.2f def\n"
						"/Mheight %.2f def\n"
						"/Mnodistort %s def\n", PROLOG, width, height, (Mnodistort ? "true" : "false"));
				fwrite(prologue, strlen(prologue), 1, fileout);
			}
			fprintf(fileout,"%%%%EndProcSet: %s\n", (usedefprolog ? PROLOG : prologuename));
		}

		fprintf(fileout,"%%Mma2ltxComment: Here follow the original Mathematica file stripped of the text labels\n");

/* Prepare TeX file */
		fprintf(filetex,"%% Picture: %s\n"
				"%% Created by mma2ltx v1.23 - Copyright (C) 1994, 1995 by Giuseppe Ghib\\`o\n"
				"%% Command line : ", fnameout);
		for (i = 0; i < argc; i++)
			fprintf(filetex, "%s ", argv[i]);
		fprintf(filetex, "\n%% Creation date: %s", asctime(tp));

		convfactor = bptounit(outunit); /* set convfactor */

		if (includeprolog) /* don't use \special{header=texmmaXX.pro} */
			fprintf(filetex, "\\mmaheaderprofalse\n");
		else               /* use \special{header=texmmaXX.pro} */
			fprintf(filetex, "\\mmaheaderprotrue\n");

		fprintf(filetex, "\173%%\n"); /* left bracket */

		if (addfontsize)
			fprintf(filetex,"\\%s%%\n", fontsize);

		if (addfbox)
			fprintf(filetex,"\\fboxsep=%s%%\n\\fbox\173%%\n",fboxsep);

		fprintf(filetex,"\\mmasetpic(%.4f,%.4f)[%2s]\173%s\175\n",
			width/convfactor, height/convfactor, outunit, fnameout);

/* Scan #1 of Mathematica PostScript file, for text fits */
		while ((fgets(tmpbuf1, TMPLEN, filein) != NULL))
		{
			float x, y, gx, gy, offx, offy;
			bool donesubs = FALSE;

			if (strstr(tmpbuf1, "Mshowa") != NULL)
			{
				char *s1 = tmpbuf1, *s2 = tmpbuf2;

				while (*s1)
				{
					if (*s1 == '[' && *(s1+1) == '(')
						s1 += 2;
					if (*s1 == ')' && *(s1+1) == ']')
					{
						s1 += 2;
						break;
					}
					if (*s1 == '\\')        /* handle \( and \) and \\ in PS file */
						if (*(s1+1) == '(' || *(s1+1) == ')' || *(s1+1) == '\\')
							s1++;
					*s2++ = *s1++;
				}
				*s2 = '\0';
				sscanf(s1,"%f %f %f %f\n", &gx, &gy, &offx, &offy);
				x = st.Ax * gx + st.Bx;
				y = st.Ay * gy + st.By;

				if (useescseq)
				{
					int esclen = strlen(escstring);

					if (!strncmp(tmpbuf2, escstring, esclen))
					{
						char *p1 = tmpbuf2, *p2;

						for (p2 = tmpbuf2 + esclen; *p2 != '\0'; p2++)
						{
							*p1++ = *p2; /* throw away the escape string */
						}
						*p1 = '\0';
					}
					else
					{
						fputs(tmpbuf1,fileout);
						continue;       /* don't process labels without esc sequence */
					}
				}

				if (substbboffs)
				{
					int k;

					for (k = 0; k < nbbsubs; k++)
					{
						if (offx == bboffx_old[k] && offy == bboffy_old[k])
						{
							fprintf(filetex,"\\mmatextfits(%.3f,%.3f)(%g,%g)(%g,%g)\173%s%s%s\175\n",
								x/convfactor, y/convfactor, bboffx_new[k], bboffy_new[k],
								bbaddx_new[k]/convfactor, bbaddy_new[k]/convfactor, (enclosemath ? "$" : ""),
								tmpbuf2, (enclosemath ? "$" : ""));
								donesubs = TRUE;
							break;
						}
					}
				}

				if (donesubs)
					continue;
				else
				{
					fprintf(filetex,"\\mmatextfits(%.3f,%.3f)(%g,%g)\173%s%s%s\175\n",
						x/convfactor,y/convfactor,offx,offy,(enclosemath ? "$" : ""),
						tmpbuf2,(enclosemath ? "$" : ""));
					continue;
				}
			}

			if (strstr(tmpbuf1,"Msboxa") != NULL || strstr(tmpbuf1,"Mshowa") != NULL)
			{
				if (useescseq)
				{
					char *p1;
					int esclen = strlen(escstring);

					for (p1 = tmpbuf1; *p1 != '\0'; p1++)
					{
						if (*p1 == '(')
						{
							p1++;   /* p1 points to the label */
							break;
						}
					}

					if (!strncmp(p1, escstring, esclen))
						continue;
					else
						fputs(tmpbuf1, fileout);
				}
				else
					continue;
			}
			else if ((drawxarrow || drawyarrow) && strstr(tmpbuf1,"End of Graphics") != NULL)
			{
				struct point p0, p1, p2, p3;

				if (drawxarrow)
				{
					p0.x = 1.001;
					p0.y = mat.By;
					p1.x = p0.x - xarrow_length;
					p1.y = p0.y + xarrow_width/2.0;
					p2.x = p1.x + xarrow_inset;
					p2.y = p0.y;
					p3.x = p1.x;
					p3.y = p0.y - xarrow_width/2.0;

					fprintf(fileout,"p\n0 w\n0 g\n"
							"%1.5f %1.5f m\n"
							"%1.5f %1.5f L\n"
							"%1.5f %1.5f L\n"
							"%1.5f %1.5f L\n"
							"F\nP\n", p0.x, p0.y, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y);
				}

				if (drawyarrow)
				{
					p0.x = mat.Bx;
					p0.y = aspectratio + 0.001;
					p1.x = p0.x - yarrow_width/2.0;
					p1.y = p0.y - yarrow_length;
					p2.x = p0.x;
					p2.y = p0.y - yarrow_length + yarrow_inset;
					p3.x = p0.x + yarrow_width/2.0;
					p3.y = p1.y;

					fprintf(fileout,"p\n0 w\n0 g\n"
							"%1.5f %1.5f m\n"
							"%1.5f %1.5f L\n"
							"%1.5f %1.5f L\n"
							"%1.5f %1.5f L\n"
							"F\nP\n", p0.x, p0.y, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y);
				}

				fputs(tmpbuf1, fileout);
			}
			else
				fputs(tmpbuf1, fileout);
		}

		fprintf(fileout,"end\n"); /* appending end Mathdict */
		fclose(fileout);
		rewind(filein);

/* Scan #2 of Mathematica PostScript file to put text */
		fprintf(filetex,"\\begin{mmapicture}\n");
		while ((fgets(tmpbuf1,TMPLEN,filein) != NULL))
		{
			float x, y, gx, gy, offx, offy;
			bool donesubs = FALSE;

			if (strstr(tmpbuf1,"Mshowa") != NULL)
			{
				char *s1 = tmpbuf1, *s2 = tmpbuf2;

				while (*s1)
				{
					if (*s1 == '[' && *(s1+1) == '(')
						s1 += 2;
					if (*s1 == ')' && *(s1+1) == ']')
					{
						s1 += 2;
						break;
					}
					if (*s1 == '\\')
						if (*(s1+1) == '(' || *(s1+1) == ')' || *(s1+1) == '\\')
							s1++;
					*s2++ = *s1++;
				}
				*s2 = '\0';
				sscanf(s1,"%f %f %f %f\n",&gx,&gy,&offx,&offy);
				x = st.Ax * gx + st.Bx;
				y = st.Ay * gy + st.By;

				if (useescseq)
				{
					int esclen = strlen(escstring);

					if (!strncmp(tmpbuf2, escstring, esclen))
					{
						char *p1 = tmpbuf2, *p2;

						for (p2 = tmpbuf2 + esclen; *p2 != '\0'; p2++)
						{
							*p1++ = *p2; /* throw away the escape string */
						}
						*p1 = '\0';
					}
					else
						continue;       /* skip string without esc sequence */
				}

				if (substbboffs)
				{
					int k;

					for (k = 0; k < nbbsubs; k++)
					{
						if (offx == bboffx_old[k] && offy == bboffy_old[k])
						{
							fprintf(filetex,"\\mmaputtext%s(%.3f,%.3f)(%g,%g)(%g,%g)\173%s%s%s\175\n",
								(whitebg ? "*" : ""), x/convfactor, y/convfactor,
								bboffx_new[k], bboffy_new[k],
								bbaddx_new[k]/convfactor, bbaddy_new[k]/convfactor, (enclosemath ? "$" : ""),
								tmpbuf2, (enclosemath ? "$" : ""));
							donesubs = TRUE;
							break;
						}
					}
				}

				if (donesubs)
					continue;
				else
				{
					fprintf(filetex,"\\mmaputtext%s(%.3f,%.3f)(%g,%g)\173%s%s%s\175\n",
						(whitebg ? "*" : ""), x/convfactor, y/convfactor, offx, offy, (enclosemath ? "$" : ""),
						tmpbuf2, (enclosemath ? "$" : ""));
					continue;
				}
			}
		}

		fprintf(filetex,"\\end{mmapicture}%s%%\n\175%%\n",(addfbox ? "\175" : ""));

		fclose(filetex);
		fclose(filein);

		printf("...done (width=%g%s height=%g%s).\n\n",
	     width/convfactor, outunit, height/convfactor, outunit);
	}

	free(p);
	free(bboffx_old);
	free(bboffy_old);
	free(bboffx_new);
	free(bboffy_new);
	free(bbaddx_new);
	free(bbaddy_new);

	exit(0);

}

void Mlp(float sx, float sy, struct scaletrasl *st)
{
	struct cw cw;
	bool xok, yok;
	float Anew, Bnew;

	st->Ax = sx/(p[np-1].gx - p[np-2].gx);
	st->Ay = sy/(p[np-1].gy - p[np-2].gy);
	st->Bx = 0.0;
	st->By = 0.0;
	while (1)
	{
		if (Mnodistort)
			st->Ax = st->Ay = min(st->Ax, st->Ay);
		Mlprun(st->Ax, st->Ay,&cw);
		Mlp1(sx, st->Ax, cw.ctx, cw.wtx, cw.cgx, cw.wgx, &Anew, &Bnew, &xok);
		st->Ax = Anew;
		st->Bx = Bnew;
		Mlp1(sy, st->Ay, cw.cty, cw.wty, cw.cgy, cw.wgy, &Anew, &Bnew, &yok);
		st->Ay = Anew;
		st->By = Bnew;
		if (xok && yok)
			break;
	}       
}


void Mlprun(float Ax, float Ay, struct cw *cw)
{
	struct pnts low,high;
	float rx1, rx2, ry1, ry2;
	int i;

	low.gx = high.gx = p[0].gx;
	low.gy = high.gy = p[0].gy;
	low.tx = high.tx = p[0].tx;
	low.ty = high.ty = p[0].ty;

	for (i = 0; i < np; i++)
	{
		rx1 = p[i].gx * Ax + p[i].tx;
		ry1 = p[i].gy * Ay + p[i].ty;
/* get low */
		rx2 = low.gx * Ax + low.tx;
		ry2 = low.gy * Ay + low.ty;
		if (rx1 < rx2)
		{
			low.gx = p[i].gx;
			low.tx = p[i].tx;
		}
		if (ry1 < ry2)
		{
			low.gy = p[i].gy;
			low.ty = p[i].ty;
		}
/* get high */
		rx2 = high.gx * Ax + high.tx;
		ry2 = high.gy * Ay + high.ty;
		if (rx1 > rx2)
		{
			high.gx = p[i].gx;
			high.tx = p[i].tx;
		}
		if (ry1 > ry2)
		{
			high.gy = p[i].gy;
			high.ty = p[i].ty;
		}
	}
	cw->ctx = (low.tx + high.tx)/2.0;
	cw->wtx = high.tx - low.tx;
	cw->cgx = (low.gx + high.gx)/2.0;
	cw->wgx = high.gx - low.gx;
	cw->cty = (low.ty + high.ty)/2.0;
	cw->wty = high.ty - low.ty;
	cw->cgy = (low.gy + high.gy)/2.0;
	cw->wgy = high.gy - low.gy;
}

void Mlp1(float s, float A, float ct, float wt, float cg, float wg, float *Anew, float *B, bool *done)
{
	*Anew = A;
	*done = TRUE;

	if ((A*wg) >= (s-wt))
	{
		*Anew = (s-wt)/wg*0.99999;
		*done = FALSE;
	}
	*B = s/2.0 - ct - (*Anew) * cg;
}

/* converts TeX units to bp */
float strtobp(char *s)
{
	char unit[3];
	float value;
	struct TeXunits *t;

	if (*s == ':' || *s == '=')
		s++;

	sscanf(s,"%f%2s", &value, unit);
	for (t = TeXtable; *(t->strunit) != '\0'; t++)
	{
		if (strcmp(strtolwr(unit), t->strunit) == 0)
		{
			value *= t->convfactor;
			break;
		}
	}
	return(value);
}

/* converts bp to TeX units */
float bptounit(char *unit)
{
	struct TeXunits *t;

	for (t = TeXtable; *(t->strunit) != '\0'; t++)
	{
		if (strcmp(strtolwr(unit), t->strunit) == 0)
			return (t->convfactor);
	}
	return(1.0);
}

/* remove the extension from a filename */
void stripext(char *to, char *from)
{
	register char *p, *last;

	if ((last = strrchr(from, '.')) == NULL)
		strcpy(to, from);
	else
	{
		for (p = from; p < last; p++)
			*to++ = *p;
		*to = '\0';
	}
}

/* convert a string to a lowercase string */
char *strtolwr(char *str)
{
	register char *p;

	for (p = str; *p != '\0'; p++)
		*p = (char) tolower((int) *p);

	return (str);
}