/*
 * Copyright 1988 Anant Agarwal
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and 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.  No representations about the suitability of this software
 * for any purpose.  It is provided "as is" without express or implied 
 * warranty.
 *
 * Author:  Anant Agarwal, MIT Laboratory for Computer Science
 */

#include <strings.h>	
#include <stdio.h>
#include <math.h>
#include "plotio.h"
#include "defs.h"
#include "structs.h"
#include "plot.h"

extern double getdegrees(), atan(), charheight(),charwidth(),log10(),mylog();

printtics(z)
int z;
{
int ticcnt;

    	/* end code for linear scaling */
    	if (axis[z].scale.type == linear) ticcnt = ticslinear(z);
	/* end code for log scaling */
    	else if (axis[z].scale.type == logstype) ticcnt = ticslog(z);
    
    	curtic += ticcnt;
    	if (z == 0) Xtics = curtic;
}

/* called only from printtics */
ticslinear(z)
int z;
{
double axismin, axismax, starttic, interval;
int numticsN;/* major tics only */
int n;
int numi;
double numf;
int ticcnt, ticnm;
double  startticnm;

	axismin = axis[z].axismin;
	axismax = axis[z].axismax;
	interval = axis[z].interval;
	numticsN = ceil((axismax - axismin) / interval);
	starttic =  axismin;
	if (numticsN > MAXTICS)
	{
		fprintf(stderr,"Tics: Too many of them, defaulting to max!\n");
		numticsN = MAXTICS;
	}
	n = 0;
	ticcnt = 0;
	while (n <= numticsN)
	{
		ticnm = curtic + n;
		startticnm = starttic + n*interval;
		tics[ticnm].validtic = TRUE;
		tics[ticnm].major = TRUE;
		tics[ticnm].pos = startticnm;
		if ((tics[ticnm].pos >= 
		       axis[z].axismin)&&(tics[ticnm].pos<=axis[z].axismax))
		       tics[ticnm].showtic = TRUE;
		else 
			tics[ticnm].showtic = FALSE;
		if (axis[z].numberstyle == integer)
		{
			numi = startticnm;
			sprintf(tics[ticnm].label,"%d",
				(int) (numi * axis[z].unit));
		}
		else 
		{
			numf = startticnm;
			axisFloatNumberEnter(z,ticnm,numf);
		}
		n++;
		ticcnt++;
	}/* do for all tics */
	return(ticcnt);
}

/* called only from printtics */
ticslog(z)
int z;
{
double axismin, axismax, starttic, endtic, interval;
int intervalI, axisminI;/* to get starttic */
int numticsN, numticsM;/* M stands for minor and N for major */
int n,m;
int numi;
double numf;
double base;
int ticcnt, ticnm;
double  startticnm;

    	base = axis[z].scale.base;
	axismin = (log(axis[z].axismin) / log(base));
	axismax = (log(axis[z].axismax) / log(base));
	interval = axis[z].interval;
	numticsN = ceil((axismax - axismin + 1)/ interval);
	numticsM = (int) pow(base, 1.0*interval) - 1;
	if (numticsN > MAXTICS) 
	{
		fprintf(stderr,
		     "Tics: Warning , Too many of them, defaulting to max!\n");
		numticsN = MAXTICS;
	}
	if (numticsM > MAXTICSM) 
	{
		fprintf(stderr,
		"Minor-Tics: Too many of them, defaulting to max!\n");
		numticsM = MAXTICSM;
	}
	intervalI = (int) interval;
	axisminI = floor(axismin);/*start from the lowest possible */
	if (intervalI > 0) 
		starttic =  (axisminI - (axisminI % intervalI));
	else starttic =  axismin;
	n = 0;
	ticcnt = 0;
	while (n <= numticsN)
	{/*major tic loop */
		m = 0;/* m=0 is actually the first major tic*/
		while (((m < numticsM)&&(n <numticsN))||
				((n == numticsN)&&(m == 0)))
		{/*minor tic loop */
			ticnm = curtic+m+n*numticsM;
			startticnm = starttic+n*interval;
			tics[ticnm].validtic = TRUE;
			if (m == 0) tics[ticnm].major = TRUE;
			else tics[ticnm].major = FALSE;
			tics[ticnm].pos = pow(base,1.0*startticnm) * (m+1);
			if ((tics[ticnm].pos < axis[z].axismin)||
			   (tics[ticnm].pos > (axis[z].axismax + SMALL)))
				tics[ticnm].showtic = FALSE;
			else tics[ticnm].showtic = TRUE;
			/* hack: if ShowMinTics is FALSE make showtic
				false for minor tics */
			if ((m != 0)&&(!(ShowMinTics)))
				tics[ticnm].showtic = FALSE;
			if (axis[z].numberstyle == integer)
			{
				numi = (int) pow(base,1.0*startticnm) * (m+1);
				sprintf(tics[ticnm].label,
					"%d",(int) (numi * axis[z].unit));
			}
			else 
			{
				numf =  pow(base , 1.0*	startticnm) * (m+1);
				axisFloatNumberEnter(z,	ticnm,numf);
			}
			m++; /* minor tic loop */
			ticcnt++;
		}
		n++; /* major tic loop */
	}/* do for all tics */
	return(ticcnt);
}


printEnterTicsIntoObj()
{
static int n = 0; /* why is this static? */
int z;/*xpt or ypt */
int zinv; /* ypt or xpt */
boolean mirror=FALSE; /* no mirroring to start with */
	if (ShowAxes)
	while (n < curtic)
	{
		if (n < Xtics) { z = 0; zinv = 1;}
		else { z = 1; zinv = 0;}
		
		if (tics[n].showtic)
		{
			/* regular axes first */
			/* first do tic mark */
			enterticmark(z,zinv,n,mirror);/* no mirroring */
			/* now enter number */

			if ( ((z == 0)&&(ShowXNos)) || ((z == 1)&&(ShowYNos)))
			   if ((tics[n].major)||(MinticNos == TRUE))
			     enterticnumber(z,zinv,n,mirror);/* no mirroring*/
		}
		n++;
	}

	/* mirror axes if necessary */
	if (MirrorAxes)
	{
	    mirror = TRUE;
	    n = 0;
	    while (n < curtic)
	    {
		if (n < Xtics) { z = 0; zinv = 1;}
		else { z = 1; zinv = 0;}
		
		if (tics[n].showtic)
		{
			/* first do tic mark */
			enterticmark(z,zinv,n,mirror);

			/* now enter number */
			if ( ((z == 0)&&(ShowXNos)) || ((z == 1)&&(ShowYNos)))
			   if ( MirrorAxisNumbers &&
			     ((tics[n].major)||(MinticNos == TRUE)))
			     enterticnumber(z,zinv,n,mirror);
		}
		n++;
	    }
	}
}


/* called only from enterticsintoobj */
enterticmark(z,zinv,n,mirror)
int z, zinv, n;
/* z,zinv say which axis, n says which tic */
boolean mirror;/* FALSE for the left corner axes */
{
int ticfnt;
	if (tics[n].major) ticfnt = majorticfont;
	else ticfnt = minorticfont;

	(obj[curobj])->name = objtext;
	(obj[curobj])->from[z] = tics[n].pos;
	(obj[curobj])->un.text.align = center;	
	if (!mirror) (obj[curobj])->from[zinv] = 
		(NewOrigin ? origin[zinv] : limits[zinv][minval]);
	else (obj[curobj])->from[zinv] = limits[zinv][maxval];
	if (z == xpt) (obj[curobj])->un.text.angle = 
	    (mirror ? getdegrees(-1.0,0.0) : getdegrees(1.0,0.0));/* hor */
	else (obj[curobj])->un.text.angle = 
	    (mirror ? getdegrees(0.0,1.0) : getdegrees(0.0,-1.0));/*lay down*/
	(obj[curobj])->scale = TRUE;
	(obj[curobj])->un.text.font = ticfnt;
	(obj[curobj])->un.text.fontsize = FFsize(ticfnt);
	(obj[curobj])->un.text.FF = FF(ticfnt);
	(obj[curobj])->un.text.StrPtr = ticmark;
	GetNewObjcurobj();
}

/* called only from enterticsintoobj */
enterticnumber(z,zinv,n,mirror)
int z, zinv, n;
/* z,zinv specify which axis, n says which tic */
boolean mirror;/* FALSE for the left corner axes */
{
int minussign= -1, plussign= 1;

	(obj[curobj])->name = objtext;
	(obj[curobj])->scale = TRUE;/* scale only part of it */
	(obj[curobj])->un.text.angle = getdegrees(1.0,0.0);
	(obj[curobj])->from[z] = tics[n].pos;
	if (!mirror) (obj[curobj])->from[zinv] = 
		(NewOrigin ? origin[zinv] : limits[zinv][minval]);
	else (obj[curobj])->from[zinv] = limits[zinv][maxval];
	if (z == xpt)
		(obj[curobj])->un.text.align = center;/*center if xaxis */
	else (obj[curobj])->un.text.align = 
		(mirror ?  left : right);
	(obj[curobj])->un.text.fontsize = FFsize(axis[z].font);
	(obj[curobj])->un.text.font = axis[z].font;
	(obj[curobj])->un.text.FF = FF(axis[z].font);
	(obj[curobj])->un.text.StrPtr = tics[n].label;
	scaleobj(obj[curobj]);
	/* now add in non-scaled portions */
	(obj[curobj])->scale = FALSE;
	if (z == xpt) (obj[curobj])->from[ypt] -= CMPT * numberBelowXAxis *
		(mirror ? (minussign * FracDownMirror) : plussign);
	else
	{
		(obj[curobj])->from[xpt] -= CMPT * numberLeftYAxis *
			(mirror ? minussign : plussign );
		(obj[curobj])->from[ypt] -= CMPT * NumberBelowYMinorTic;
	}
	GetNewObjcurobj(); 
}

axisFloatNumberEnter(z,indexn,numf)
int z,indexn;   /* z:axis, n:tic */
double numf;/* what number to enter */
{
   numf = numf * axis[z].unit;
   if (axis[z].numberstyle == exponent) switch (axis[z].signif)
	{
		case 0:	    sprintf(tics[indexn].label,"%.0e",numf);break;
		case 1:	    sprintf(tics[indexn].label,"%.1e",numf);break;
		case 2:	    sprintf(tics[indexn].label,"%.2e",numf);break;
		case 3:	    sprintf(tics[indexn].label,"%.3e",numf);break;
		case 4:	    sprintf(tics[indexn].label,"%.4e",numf);break;
		case 5:	    sprintf(tics[indexn].label,"%.5e",numf);break;
		case 6:	    sprintf(tics[indexn].label,"%.6e",numf);break;
		case 7:	    sprintf(tics[indexn].label,"%.7e",numf);break;
		case 8:	    sprintf(tics[indexn].label,"%.8e",numf);break;
		default:    sprintf(tics[indexn].label,"%.2e",numf);
	}
   else if (axis[z].numberstyle == floating) switch (axis[z].signif)
	{
		case 0:	    sprintf(tics[indexn].label,"%.0f",numf);break;
		case 1:	    sprintf(tics[indexn].label,"%.1f",numf);break;
		case 2:	    sprintf(tics[indexn].label,"%.2f",numf);break;
		case 3:	    sprintf(tics[indexn].label,"%.3f",numf);break;
		case 4:	    sprintf(tics[indexn].label,"%.4f",numf);break;
		case 5:	    sprintf(tics[indexn].label,"%.5f",numf);break;
		case 6:	    sprintf(tics[indexn].label,"%.6f",numf);break;
		case 7:	    sprintf(tics[indexn].label,"%.7f",numf);break;
		case 8:	    sprintf(tics[indexn].label,"%.8f",numf);break;
		default:    sprintf(tics[indexn].label,"%.2f",numf);
	}
   else if (axis[z].numberstyle == scientific) 
	{
	    switch (axis[z].signif)
	    {
		case 0:	    sprintf(tics[indexn].label,"%.0e",numf);break;
		case 1:	    sprintf(tics[indexn].label,"%.1e",numf);break;
		case 2:	    sprintf(tics[indexn].label,"%.2e",numf);break;
		case 3:	    sprintf(tics[indexn].label,"%.3e",numf);break;
		case 4:	    sprintf(tics[indexn].label,"%.4e",numf);break;
		case 5:	    sprintf(tics[indexn].label,"%.5e",numf);break;
		case 6:	    sprintf(tics[indexn].label,"%.6e",numf);break;
		case 7:	    sprintf(tics[indexn].label,"%.7e",numf);break;
		case 8:	    sprintf(tics[indexn].label,"%.8e",numf);break;
		default:    sprintf(tics[indexn].label,"%.2e",numf);
	    }/* switch */
	    convertExpToSci(tics[indexn].label);
	}
	else fprintf(stderr,"****Splot error: Unknown axis numberstyle\n");
}

/* converts exponent notation text in label array to scientific notation */
/*Searches for an "e" and if it finds it, replaces it with 10 and 
raises the remaining text as a superscript */
convertExpToSci(lab)
char lab[];
{
register int i=0,j=0;
int startofexp;
char tmplab[MAXTICLABEL];
	while ((lab[i] != 'e')&&(lab[i] != 'E')&&(lab[i] != '\0'))
		i++;
	/* i points to e or is end of line */
	if (lab[i] != '\0') 
	/* i points to e */
	/* convert e to *, and insert 10\+{} */
	{
		lab[i] = '*';
		i++;/* i points to exponent */
		startofexp = i;
		while (lab[i] != '\0')
		{
			tmplab[j] = lab[i];
			i++;j++;
		}
		i = startofexp;
		lab[i] = '1';i++;
		lab[i] = '0';i++;
		lab[i] = '\\';i++;
		lab[i] = '+';i++;
		lab[i] = '{';i++;
		/* now put back exponent */
		j = 0;
		while (tmplab[j] != '\0')
		{
			lab[i] = tmplab[j];
			i++;j++;
		}
		/* now add '}' and \0 */
		lab[i] = '}';i++;
		lab[i] = tmplab[j];
	}
	else /* lab[i]  points to \0 */
	{
		fprintf(stderr,"***Splot: Error in scientific notation conversion\n");
	}
}

