/*===========================================================================
  Copyright (C) 1986-2009 European Southern Observatory (ESO)
 
  This program is free software; you can redistribute it and/or 
  modify it under the terms of the GNU General Public License as 
  published by the Free Software Foundation; either version 2 of 
  the License, or (at your option) any later version.
 
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
 
  You should have received a copy of the GNU General Public 
  License along with this program; if not, write to the Free 
  Software Foundation, Inc., 675 Massachusetss Ave, Cambridge, 
  MA 02139, USA.
 
  Corresponding concerning ESO-MIDAS should be addressed as follows:
	Internet e-mail: midas@eso.org
	Postal address: European Southern Observatory
			Data Management Division 
			Karl-Schwarzschild-Strasse 2
			D 85748 Garching bei Muenchen 
			GERMANY
===========================================================================*/

/*+++++++++  
.MODULE    edpic.c
.AUTHOR    Francois Ochsenbein [ESO]
.LANGUAGE  C
.CATEGORY  Edition of integer data

.COMMENTS
	Functions in this module edit numbers using a "picture" or template.
\begin{TeX}
The picture is a character string specifying how to edit a number.
All characters but the following ones are simply copied to the output:
\begin{itemize}
\item \& ends the picture (starting the next number)
\item 0 is replaced either by a digit or by the fill character
\item digits in the range 1\dots9 indicate an edition in base $n+1$, \ie
	9 for decimal representation, 7 for octal, etc\dots
\item X for an hexadecimal edition, performed in uppercase
\item $+$ is replaced by the sign, with repetition for floating position.
\item $-$ is replaced by a minus sign if the number is negative,
	or is equivalent to 0 in case of a positive number;
	the repetition indicates a floating position for the sign.
\end{itemize}
If neither $+$ nor $-$ character is specified in the picture,
the value to be edited is assumed to be {\em unsigned}. 
Some illustrations:
\begin{itemize}
\item {\tt "+99 59 59"} (edition of a declination expressed in arc seconds)
applied to 86400 results in \fbox{{\tt +24 00 00}}
\item {\tt "+++999.9"} applied on the number 256 results in 
	\fbox{{\tt\ \ +025.6"}}
\item {\tt "-9.9"} applied on 123 results in {\tt "12.3"}, and
	applied on -1 results in \fbox{{\tt -0.1}}
\item {\tt "77 77 77 77 77 77"} applied on the number -1 results in 
	\fbox{{\tt 03 77 77 77 77 77}}, since the number -1 is in fact $2^{32}-1$.
\item {\tt "-XXXX XXXX"} applied on the number -12 results in 
	\fbox{{\tt -0000 000C}}
\end{itemize}
\end{TeX}
To copy the ``picture'' characters to the output, use the \ espace char,
i.e. '\+' for +, '\-' for --, etc, and \\ to issue the backslash.

.VERSION 1.0	18-Apr-1986: Creation 
.VERSION 1.1 	23-May-1986: Added hexa possibility
.VERSION 1.2 	03-Mar-1987: Cosmetic modifications.
.VERSION 2.0 	25-Jan-1988: Integrated for Midas
.VERSION 2.1 	12-Jun-1989: Sign after digit or dots is taken as `copy char'
 
 090831		last modif
----------------------------------------------------------------------------*/

#include <osdefos.h>	/* Required for shareable images... */
#include <atype.h>	/* Required for isdigit	*/

#define ABSOLUTE(x)	((x) < 0 ? (-x) : (x))     /* Absolute*/
#define EOS		'\0'		/* End Of String	*/

#define	_ERR_CHAR_	'~'	/* Character used if edition error occurs */

MID_STATIC unsigned int base = 10;	/* Base for the edition of digits	*/
MID_STATIC unsigned int sign =  0;	/* Sign of the number from 0 to 2, 
				   used as an index in signs[]		*/
MID_STATIC int pic_len;		/* Where picture stops, used by ed_mpic	*/

MID_STATIC unsigned char signs[] = { ' ', '-', '+'};
MID_STATIC char fill_char = ' ';
MID_RSTATIC char xdigit[] = "0123456789ABCDEF";

/*===========================================================================
 *			ed_pic
 *===========================================================================*/
/*++++++
.PURPOSE Edit an integer number according to a picture.
.RETURNS The length of the edited number.
.REMARKS Digits are replaced with `~' if ``value'' cannot be edited 
	(number too large). The buffer is terminated with the EOS character.
----------*/
int ed_pic(dest, pic, value)
	char *dest; 	/* OUT: pointer to destination buffer 	*/
	char *pic;	/* IN: EOS-terminated picture string	*/
	long int value;		/* IN: The integer number to edit	*/
{
 	unsigned long int n;
	char 	*a, *p, *ps;	/* ps indicates sign */
	unsigned int op;
	int length;

	/* Initialisation */
  sign = 0 ; base = 10; signs[0] = fill_char; op = 0;
  ps = (char *)0;

	/* Look for sign */
  for (p=pic; *p; p++)
  {	if (isdigit(*p))	;
  	else if (*p == '.')	;
  	else if (*p == '+')	{ if(!ps) sign = 2; continue; }
  	else if (*p == '-')	{ if(!ps) sign = 1; continue; }
  	else if (*p == 'X')	;
  	else if (*p == '\\')	{ op++; p++;        continue; }
  	else if (*p == '&')	break;
  	else			continue;
  	if (!ps) ps = p;
  }
  if(!ps) ps = p;
  pic_len = (p--) - pic;
  
  length = pic_len - op;
  a = dest + length;		/* Last char of destination string */
  *(a--) = EOS;

  if (sign)			/* Look for signed or unsigned number	*/
  {	n = ABSOLUTE(value); 
	sign -= (sign-1) ^ (value>=0);	/* Leads to 0 or 1 if '-' asked,
						    1 or 2 if '+' asked */
  }
  else 	n = (unsigned int) value;

	/* Edition of digits, from right to left */
  for (; p>=pic; p--, a--)
  { op = 3; 		/* Default operation */
    if ((p>pic) && (*(p-1) == '\\'))	{ *a = *(p--); continue;}
    switch(*p)
    { case '0' : op = (n ? 1 : 0 ); break;
      case '-' : case '+': if(p<ps) op = (n ? 1 : 2); break;
      case 'X' : base = 16; op = 1; break;
      default  : if ((*p > '9')||(*p < '0')) break; 
                 base = *p - '0' + 1; op = 1;
    }
    switch(op)
    { case 0: *a = fill_char; break;		/* Insert fill char	*/
      case 1: *a = xdigit[n%base]; 		/* Insert a digit	*/
		n /= base; break;
      case 2: *a = signs[sign]; 		/* Insert the sign	*/
		sign = 0; break;
      case 3: *a = *p;				/* Copy from picture	*/
    }
  }

  if (n | sign) 			/* Number not completely edited	*/
  { 	for (p=pic, a=dest; *p; p++, a++)
	{	switch(*p)
		{ case '\\': p++; 				continue;
		  default  : if ((*p > '9')||(*p < '0'))	continue; 
		  case '+' : case '-' : case 'X': *a = _ERR_CHAR_;
		}
	}
  }

  return(length);
}

/*===========================================================================
 *			ed_pic4
 *=========================================================================*/

/*++++++
.PURPOSE Edit an integer according to a picture, with specified fill character.
.RETURNS The length of the edited string.
.REMARKS The string is filled with `~' if ``value'' cannot be edited 
	(number too large); 
.REMARKS The destination string if terminated with an EOS character.
------------*/
int ed_pic4(dest, pic, value, fill)
     char *dest; 	/* OUT: pointer to destination string 	*/
     char *pic;		/* IN: EOS-terminated picture string	*/
     long int value;	/* IN: The integer number to edit	*/
     char fill;		/* IN: The fill character		*/
{ 
	register int ret;

  fill_char = fill;
  ret = ed_pic(dest, pic, value);
  fill_char = ' ';
  return(ret);
}

