/* char	*ConvDecimalToScientific( s, x,	p)
 *
 * ARGUMENT
 *   DEC	*x;
 *   char	*s;
 *   int	p;
 *
 * DESCRIPTION
 *	Converts a DEC structure to an ascii string.  A	'-' will be printed
 *  for	negative numbers, but a	'+' sign will never be printed.	 A decimal
 *  point will be printed whenever the implied decimal is positive.  Trailing
 *  zeroes after the decimal point will	be printed.  The number	of decimal
 *  digits of the string is the	same as	the implied decimal of the DEC.
 *	The number is printed in scientific notation, similar to the %e	type
 *  of printf, with a precision	of p (i.e. p+1 digits).	  A negative p implies
 *  the	default	precision of the DEC.
 *	Possible error:	 the string not	being large enough
 *
 * SIDE	EFFECTS
 *	THE DESTINATION	char string MUST BE LONG ENOUGH	FOR ALL	THE DIGITS
 *  PLUS ANY SIGN, THE DECIMAL POINT AND THE TERMINATING NULL.
 *
 * RETURNS
 *	A string pointer if successful,	NULL otherwise.
 *
 * POSSIBLE ERROR CODES
 *
 *	GM_NULLPOINTER
 *	GM_NULLSTRING
 *	GM_CNVRW
 *	GM_INVALIDID
 *
 * AUTHOR
 *   Jared Levy		Feb 1, 1987
 *   Copyright (C) 1987-1990 Greenleaf Software	Inc.  All rights reserved.
 *
 * MODIFICATIONS
 *
 */

#include <stdio.h>
#include <string.h>
#include "gmsystem.h"

char	*ConvDecimalToScientific( s, x,	p)
DEC	*x;	/* DEC stucture	*/
char	*s;	/* string */
int	p;	/* precision */
{
	int	i, wDigits, wOut, wExp,	diff, ip, rup;
	DEC	a,*pa=&a;
	char	t[GM_IMAXID * 2];

	_MacStart(GM_DTOSCI);

	if(!s)	{
		_MacErr(GM_NULLSTRING);
		_MacRet(NULL);
	}

	if (!x)	 {
		strcpy(s, "(null)");
		_MacErr(GM_NULLPOINTER);
		_MacRet	(NULL);
	}

	if (_MacBad(x))	 {
		strcpy(s, "(null)");
		_MacErr(GM_INIT);
		_MacRet	(NULL);
	}

	if (p>18)  {
		_MacErr(GM_INVALIDID);
		p=18;
	}
	p++;

	wDigits	= wOut = 0;
	_MacDCopy(pa,x);	/* can't change	source field */

	if(_MacIsDecN(pa)) {
		++wOut;
	}

/* calculate digits */
	while(!(_MacIsDecZ(pa))) {
		i = (int) _DivUnsArrByUns(pa->dc.sl,10,5);
		t[wDigits] = (char) (i + 0x30);
		wDigits++;
	}

/* calculate exponent */
	wExp = wDigits - pa->dc.id - 1;

	if (wDigits == 0) {		/* case	pa == 0	*/
		t[0]='0';
		wDigits++;
		wExp=0;
	}

/* p<=0	--> use	default	precision */
	if (p<=0)
		p=wDigits;

/* too many digits */
	if (wDigits>p)	{
		diff = wDigits-p;
		rup = ((t[diff-1] >='5') ? 1 : 0);
		for (i=0; i<p; i++)
			t[i] = t[i+diff];
		if (rup	&& wfGMRound)  {
			i = 0;
			while (i<p)
				if (t[i]<'9')  {
					t[i]=t[i]+(char)1;
					i = p+1;
				}
				else  {
					t[i]='0';
					i++;
				}
			if (i == p)  {
				t[p-1] = '1';
				wExp++;
			}
		}
		_MacErr(GM_CNVRW);
	}

/* too few digits */
	if (wDigits<p)	{
		diff = p-wDigits;
		for (i=p-1; i>=0; i--)
			t[i+diff]=t[i];
		for (i=0; i<diff; i++)
			t[i] = '0';
	}

/* add minus sign */
	if (wOut!=0)
		s[0] = '-';

/* copy	wDigits	into string */
	ip= p;
	ip--;
	s[wOut]	= t[ip];
	wOut++;
	if (p>1)  {
		s[wOut]	= '.';
		wOut++;
		for (ip--; ip >= 0; ip--) {
			s[wOut]	= t[ip];
			wOut++;
		}
	}

/* a # in the format string forces a decimal point */
	if (wfFlagNumber && p<=1)  {
		s[wOut]	= '.';
		wOut++;
	}

/* add exponent	*/
	s[wOut]	= cGMSymExp;	/*  'e'	or 'E'	*/
	wOut++;

	if (wExp>=0)
		s[wOut]='+';
	else {
		s[wOut]='-';
		wExp = -wExp;
	}
	wOut++;

	s[wOut]='0';
	wOut++;
	s[wOut]= (char)	(0x30 +	wExp/10);
	wOut++;
	s[wOut]= (char)	(0x30 +	wExp%10);
	wOut++;

	s[wOut]	= '\0';
	_MacRet	(s);

}