
/****************************************************************************/

/*  Module PNLNUMVC.C

    Copyright 1986 Roundhill Computer Systems Limited
    All rights reserved

    Use and disclosure of this code are prohibited unless in accordance
    with the terms of the PANEL software licence.

    ************************************************************************
    *** THE OBJECT CODE VERSION OF THIS MODULE IS INCLUDED IN THE PANEL  ***
    *** LIBRARY.  IF YOU AMEND AND COMPILE THIS MODULE AND LINK IT WITH  ***
    *** YOUR APPLICATION IT WILL SUPERSEDE THE LIBRARY VERSION.          ***
    ************************************************************************

    PANEL:  Type 4          : Validation
            Source Language : C

    Modification History (Push-Down List):  

            01.02.86        : Remove from LV00 to separate module
            01.01.86        : use temp PAXAST to allow empty substrings
            28.12.85        : Convert to table-driven operation
            27.11.85        : Prevent PALVAL redisplay for * protect

*****************************************************************************/

#include <pnl4.h>

/*****************************************************************************/

int PANUMV(dp,code)

/*  Validate and reformat the number in str with dp decimal places.  Note that
    the maximum length numeric field is 32 bytes.  Increase this if required.

    If code is true, omit the validation step and just pick the value
    from the saved field (if used).  If not used, return false, which
    will be ignored, but which will avoid changing the field.

    The 'user' (X) attribute accepts and formats a blank field as the
    equivalent of a nil value.

    This routine uses sscanf to read the field into a long or a double
    depending on whether dp is 0 or 2.  If the NXANF extended attribute 
    is present, the numeric value is placed in the numeric array element 
    indexed by the value in the first substring.  In this case the 
    element number may optionally be followed by two values for a
    numeric range check (low and high limits).

    The routine returns false if the number is invalid.  If the number
    is valid, sprintf is called to reformat the value cleanly ready for
    display.

    If the C compiler in use has an option to generate in-line code, for
    a numeric co-processor such as the 8087, that option will NOT have 
    been used for the version of this module in the panel library.  If 
    you wish to the option, recompile this module.

******************************************************************************/

int dp;
int code;

{
    int nel;
    register uchar *sp;
    double tmpd;    /* temporary double result */
    long tmpl;      /* temporary long result */
    double dumd;    /* dummy used to exclude second value in field */
    long lol, hil;      /* actual limit value */
    double lod,hid;     /* actual limit value */

#ifdef WIZARD   /* extra sscanf arg converts a value even if input finished */
#define NODUM 1
#endif

#ifdef DESMET   /* DeSmet does likewise */
#define NODUM 1
#endif

#ifdef QNX      /* returns -1 if extra patterns */
#define NODUM 1
#endif

    if (code == 0)
        {
        tmpd = 0.0;
        tmpl = 0L;
        nel = 0;                    /* no value elements yet done */
        sp = (uchar*)&PVWSTR[0];       /* start at start of i/p area */
        while (*sp == ' ') sp++;    /* ignore leading blanks */
	if ( (*sp == '\0') &&       /* empty field */
	     (PACRF.sa & usr) )     /* 'x' attribute set */
	    {
	    tmpl = 0L;      /* force result to 0 */        
	    tmpd = 0.0;
	    nel = 1;	    /* assume we have one element */
	    }
	  else
	    {
#ifdef NODUM 
            if (dp == 2)       nel = sscanf(sp,"%lf",&tmpd); /* fmt as double */
            else if (dp == 0)  nel = sscanf(sp,"%ld",&tmpl); /* fmt as long */
#else        
            if (dp == 2)       nel = sscanf(sp,"%lf %lf",&tmpd,&dumd);
            else if (dp == 0)  nel = sscanf(sp,"%ld %lf",&tmpl,&dumd);
#endif
	    }
        if (nel != 1) return(0);    /* none, or too many valid */
        }

    nel = 0;                    /* if all fails, use first array element */
    PAXASN = 0;                         
    if ( (PACRF.xa != PANULL) && (PACRF.xa->xbits & (1 << NXANF) ) )
        {
        PAXAST(PACRF.xa->xattr[NXANF]); /* use the extended attribute string */
        if ( (PAXASN == 0) || (1 != sscanf(PAXASP[0],"%d",&nel) ) ) nel = 0;
        if (code == 0)
            {
            if ( (PAXASN > 1) && (PAXASP[1][0] != '\0') )
                {                   /* process low limit if range check */
                if (dp == 2)
                    {
                    lod = 0.0;
                    sscanf(PAXASP[1],"%lf",&lod);
                    if (tmpd < lod) return(0);
                    }
                else if (dp == 0) 
                    {
                    lol = 0L;
                    sscanf(PAXASP[1],"%ld",&lol);
                    if (tmpl < lol) return(0);
                    }
                }
            if ( (PAXASN > 2) && (PAXASP[2][0] != '\0') )
                {
                if (dp == 2)
                    {
                    hid = 0.0;
                    sscanf(PAXASP[2],"%lf",&hid);
                    if (tmpd > hid) return(0);
                    }
                else if (dp == 0) 
                    {
                    hil = 0L;
                    sscanf(PAXASP[2],"%ld",&hil);
                    if (tmpl > hil) return(0);
                    }
                }
            }
        }
    if (dp == 2)
        {
        if (nel >= PAMAXD) nel = 0;
        if ( code && (nel == 0) ) return 0;
        if ( code == 0 ) PANUMD[nel] = tmpd;  else tmpd = PANUMD[nel];
        if ( (PACRF.sa & usr) && (tmpd == 0.0) ) PVWSTR[0] = '\0'; else
        sprintf(PVWSTR,(PAXASN > 3)?PAXASP[3]:"%-1.2f",tmpd);
        }
    else if (dp == 0) 
        {
        if (nel >= PAMAXL) nel = 0;
        if ( code && (nel == 0) ) return 0;
        if ( code == 0 ) PANUML[nel] = tmpl;  else tmpl = PANUML[nel];
        if ( (PACRF.sa & usr) && (tmpl == 0L) ) PVWSTR[0] = '\0'; else
        sprintf(PVWSTR,(PAXASN > 3)?PAXASP[3]:"%-1ld",tmpl);
        }
    if(strlen(PVWSTR) > UCI(PACRF.sl)) return(0);      /* too long for field */
    return 1;
}

