/************************************************************************\
*                                                                        *
*   mma2ltc.c - Copyright (C) 1994 by Giuseppe Ghibo`                    *
*                                                                        *
*   version 1.2 - 16 July 1994                                           *
*                                                                        *
\************************************************************************/

#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 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,""}
};

/* 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 *);

#define NMAX 1000
#define NMAXFILEIN 20 /* maximun number of files to process */
#define TMPLEN 512
#define PROLOG "texmma22.pro"
#define OPTSWITCH1 '-'
#define OPTSWITCH2 '/'

int np=0;
struct pnts *p;
char tmpbuf1[TMPLEN],tmpbuf2[TMPLEN];
char texfname[256];
bool Mnodistort = TRUE;              /* keep the aspect ratio ? */

/* This is the Mathematica v2.2 prologue file */
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 */
	float oldoffx,oldoffy;
	float newoffx,newoffy;
	float addoffx,addoffy;
	bool widthchoosen = FALSE;   /* the width has been choosen ? */
	bool heightchoosen = FALSE;  /* the height has been choosen ? */
	bool enclosemath = TRUE;     /* enclose MMA strings 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 whitebg = FALSE;        /* white background in mmaputtex ? */
	bool allocfnameout = FALSE;
	struct scaletrasl st,mat;
	int i,j,k,nfilein=0;
	char *fnamein[NMAXFILEIN];
	char *fnameout="";
	char *fboxsep="0pt";
	char *fontsize="";
	char *outunit="bp";
	char tmpunit1[3],tmpunit2[3];
	FILE *filein,*fileout,*filetex;
	long tc;        /* for time/date */
	struct tm *tp;  /* for time/date */

	if ((p=malloc(sizeof(struct pnts)*NMAX)) == NULL) {
		printf("Error: not enough memory\n");
		exit(1);
	}

	printf("mma2ltx v1.2 - Copyright (C) 1994 Giuseppe Ghibo`\n");

/* scan options */
	for (i=1; i<argc; i++) {
		if (*argv[i]==OPTSWITCH1 || *argv[i]=='/') {
			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])
					s=argv[++i];
				width=strtobp(s);
				widthchoosen = TRUE; /* a width has been choosen */
				break;

			case 'h': case 'H':
				if (*s=='\0' && argv[i+1])
					s=argv[++i];
				height=strtobp(s);
				heightchoosen = TRUE; /* an height has been choosen */
				break;

			case 'd': case 'D':
				Mnodistort = FALSE;
				break;

			case '?':
				printf("Usage: mma2ltx [<options>] <filename(s)> [<options>]\n");
				printf("Where <options> is one or more of:\n\n");
				printf("\t  -?  Show these messages\n");
				printf("\t  -d  Don't keep the aspect ratio\n");
				printf("\t  -n  Deactivate automatic $...$ enclosing\n");
				printf("\t  -p  Include the Mathematica PostScript prologue in the .EPS file\n");
				printf("\t  -b  Enclose every string into a white box (default = transpar. box)\n");
				printf("\t  -h<dimen> Set picture height to <dimen> (default = 100bp)\n");
				printf("\t  -w<dimen> Set picture width  to <dimen> (default = 161bp)\n");
				printf("\t  -f<dimen> Add an \\fbox to the picture (\\fboxsep=<dimen>)\n");
				printf("\t  -u<unit>  Set all dimensions in the unit <unit>\n");
				printf("\t  -s<cmd>   Set the font size with the TeX command <cmd>\n");
				printf("\t  -o<filename> Output filename\n");
				printf("\t  -c(sx,sy)=(newsx,newsy)(<dimen>,<dimen>) (change alignment)\n\n");
				printf("\t  <dimen> = a number followed by one of TeX's unit (e.g. 10.3cm)\n");
				printf("\t  <unit>  = a TeX's unit (e.g. cm)\n");
				printf("\t  <cmd>   = a TeX command without the backslash '\\'\n\n");
				printf("Example:\n");
				printf("\t mma2ltx -sfootnotesize -w5in pic1.ps pic2.ps\n");
				printf("process the files `pic1.ps' and `pic2.ps'. The width of the pictures\n");
				printf("will be 5 inch and \\footnotesize will be used as LaTeX command to\n");
				printf("set the pictures 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)
					s = argv[++i];
				fnameout = s;
				nofnameout = FALSE;
				break;

			case 's': case 'S':
				if (*s == '\0' && argv[i+1] && *argv[i+1] != OPTSWITCH1)
					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)
					s = argv[++i];
				addfbox = TRUE;
				if (*s != '\0')
					fboxsep = s;
				break;
			
			case 'u': case 'U':
				if (*s=='\0' && argv[i+1])
					s=argv[++i];
				sscanf(s,"%2s",outunit);
				break;

			case 'c': case 'C':
				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) {
					printf("Error, option '-c': bad argument!\n");
					exit(1);
				}
				sprintf(tmpbuf1,"%f%2s",addoffx,tmpunit1);
				sprintf(tmpbuf2,"%f%2s",addoffy,tmpunit2);
				addoffx = strtobp(tmpbuf1);
				addoffy = strtobp(tmpbuf2);
				substbboffs = TRUE;
				break;

			case 'p': case 'P':
				includeprolog = TRUE;
				break;

			case 'b': case 'B':
				whitebg = TRUE;
				break;

			default:
				break;
			}
		}
		else {
			if (nfilein >= NMAXFILEIN) {
				printf("Error: I can't process more than %d files.\n",NMAXFILEIN);
				exit(1);
			}
			else
				fnamein[nfilein++]=argv[i];
		}
	}

	if (nfilein == 0) {
		printf("Error: You must specify at least one filename!\n");
		exit(1);
	}

	if (nfilein > 1 && !nofnameout) {
		printf("Error: You can't specify the output name when process multiple files\n");
		exit(1);
	}

for (j=0 ; j < nfilein ; j++) {
	if ((filein=fopen(fnamein[j],"r")) == NULL) {
		printf("Error: Can't open file '%s' (r)\n",fnamein[j]);
		printf("%s\n",strerror(errno));
		exit(1);
	}

	if (*fnameout == '\0' || nofnameout) {
		stripext(tmpbuf1,fnamein[j]);
		strcat(tmpbuf1,".eps");
		if (allocfnameout)
			free(fnameout);
		if ((fnameout=malloc(strlen(tmpbuf1)+1)) == NULL) {
			printf("Error: Not enough memory!\n");
			exit(1);
		}
		allocfnameout = TRUE;
		strcpy(fnameout,tmpbuf1);
	}

	if ((fileout=fopen(fnameout,"w")) == NULL) {
		printf("Error: Can't open file '%s' (w)\n",fnameout);
		printf("%s\n",strerror(errno));
		exit(1);
	}

/* search aspect ratio */
	while ((fgets(tmpbuf1,TMPLEN,filein) != NULL)) {
		if ((sscanf(tmpbuf1,"%%%%AspectRatio: %f",&aspectratio)) == 1) {
			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;
		}
	}

/* 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(texfname,fnameout);
	strcat(texfname,".tex");

	if ((filetex=fopen(texfname,"w")) == NULL) {
		printf("Error: Can't open file '%s' (w)\n",texfname);
		printf("%s\n",strerror(errno));
		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 */
	fprintf(fileout,"%%!PS-Adobe-2.0 EPSF-2.0\n");
	fprintf(fileout,"%%%%BoundingBox: 0 0 %.2f %.2f\n",width,height);
	fprintf(fileout,"%%%%Title: %s\n",fnameout);
	fprintf(fileout,"%%%%Creator: mma2ltx v1.2\n");
	time(&tc); /* get current time */
	tp = localtime(&tc);
	fprintf(fileout,"%%%%CreationDate: %s",asctime(tp));
	fprintf(fileout,"%%%%EndComments\n");
	fprintf(fileout,"%%MMA2LTXCommandLine: ");
	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);
	}
	else {
		fprintf(fileout,"%%%%BeginProcSet: %s\n",PROLOG);
		fprintf(fileout,"%% Mathematica v2.2 prologue\n");
		fprintf(fileout,"/Mathdict 150 dict def\n");
	}
	fprintf(fileout,"Mathdict begin\n");
	fprintf(fileout,"/Mwidth %.2f def\n",width);
	fprintf(fileout,"/Mheight %.2f def\n",height);
	fprintf(fileout,"/Mnodistort %s def\n",(Mnodistort ? "true" : "false"));
	if (includeprolog) {
		int k=0;
		while (prologue[k][0] != '\0') {
			fputs(prologue[k++],fileout);
		}
		fprintf(fileout,"%%%%EndProcSet: %s\n",PROLOG);
	}
	fprintf(fileout,"%%MMA2LTXComment: Here follow the original Mathematica file stripped of the text strings\n");

/* Prepare TeX file */
	fprintf(filetex,"%% Picture: %s\n",fnameout);
	fprintf(filetex,"%% Created by mma2ltx v1.2 - Copyright (C) 1994 Giuseppe Ghib\\`o\n");
	fprintf(filetex,"%% Command line : ");
	for (i=0;i<argc;i++) fprintf(filetex,"%s ",argv[i]);
	fprintf(filetex,"\n");
	fprintf(filetex,"%% Creation date: %s",asctime(tp));

	convfactor = bptounit(outunit); /* set convfactor */

	if (includeprolog) /* don't use \special{header=texmma??.pro} */
		fprintf(filetex,"\\mmaheaderprofalse\n");
	else               /* use \special{header=texmma??.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",fboxsep);
		fprintf(filetex,"\\fbox\173%%\n");
	}

	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;
		if ((strstr(tmpbuf1,"Mshowa")) != NULL) {
			char *s1=tmpbuf1;
			char *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 (substbboffs && (offx == oldoffx || offy == oldoffy)) {
				fprintf(filetex,"\\mmatextfits(%.3f,%.3f)(%g,%g)(%g,%g)\173%s%s%s\175\n",
					x/convfactor,y/convfactor,newoffx,newoffy,
					addoffx/convfactor,addoffy/convfactor,(enclosemath ? "$" : ""),
					tmpbuf2,(enclosemath ? "$" : ""));
				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)
			 continue;
		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;
		if ((strstr(tmpbuf1,"Mshowa")) != NULL) {
			char *s1=tmpbuf1;
			char *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 (substbboffs && (offx == oldoffx || offy == oldoffy)) {
				fprintf(filetex,"\\mmaputtext%s(%.3f,%.3f)(%g,%g)(%g,%g)\173%s%s%s\175\n",
					(whitebg ? "*" : ""), x/convfactor,y/convfactor,newoffx,newoffy,
					addoffx/convfactor,addoffy/convfactor,(enclosemath ? "$" : ""),
					tmpbuf2,(enclosemath ? "$" : ""));
				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",(addfbox ? "\175" : ""));
	fprintf(filetex,"\175%%\n"); /* right bracket */

	fclose(filetex);
	fclose(filein);

	printf("picture '%s' processed.\n",fnamein[j]);
	printf("width=%g%s height=%g%s\n\n",width/convfactor,outunit,
		height/convfactor,outunit);

	}

	free(p);
	if (allocfnameout)
		 free(fnameout);
}

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)
{
	while (*from) {
		if (*from == '.')
			break;
		*to++ = *from++;
	}
	*to = '\0';
}

/* convert a string to lowercase */
char *strtolwr(char *str)
{
	register char *p=str;

	while (*p++)
		*p = (char) tolower((int) *p);

	return (str);
}
