1326 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1326 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
| /* f4field.c (c)Copyright Sequiter Software Inc., 1988-1996.  All rights reserved. */
 | |
| 
 | |
| #include "d4all.h"
 | |
| #ifndef S4UNIX
 | |
|    #ifdef __TURBOC__
 | |
|       #pragma hdrstop
 | |
|    #endif
 | |
| #endif
 | |
| 
 | |
| #ifndef S4OFF_WRITE
 | |
| char *S4FUNCTION f4assignPtr( FIELD4 *field )
 | |
| {
 | |
|    #ifdef E4PARM_HIGH
 | |
|       if ( field == 0 )
 | |
|       {
 | |
|          error4( 0, e4parm_null, E90507 ) ;
 | |
|          return 0 ;
 | |
|       }
 | |
|    #endif
 | |
| 
 | |
|    #ifdef S4CLIENT_OR_FOX
 | |
|       if ( d4version( field->data ) == 0x30 )
 | |
|          f4assignNotNull( field ) ;
 | |
|    #endif
 | |
| 
 | |
|    field->data->recordChanged = 1 ;
 | |
| 
 | |
|    return ( field->data->record + field->offset ) ;
 | |
| }
 | |
| 
 | |
| void S4FUNCTION f4blank( FIELD4 *field )
 | |
| {
 | |
|    #ifdef S4VBASIC
 | |
|       if ( c4parm_check( (void *)field, 3, E90508 ) )
 | |
|          return ;
 | |
|    #endif
 | |
| 
 | |
|    #ifdef E4PARM_HIGH
 | |
|       if ( field == 0 )
 | |
|       {
 | |
|          error4( 0, e4parm_null, E90508 ) ;
 | |
|          return ;
 | |
|       }
 | |
|    #endif
 | |
| 
 | |
|    if ( error4code( field->data->codeBase ) < 0 )
 | |
|       return ;
 | |
| 
 | |
|    #ifndef S4SERVER
 | |
|       #ifndef S4OFF_ENFORCE_LOCK
 | |
|          if ( field->data->codeBase->lockEnforce && field->data->recNum > 0L )
 | |
|             if ( d4lockTest( field->data, field->data->recNum ) != 1 )
 | |
|             {
 | |
|                error4( field->data->codeBase, e4lock, E90508 ) ;
 | |
|                return ;
 | |
|             }
 | |
|       #endif
 | |
|    #endif
 | |
| 
 | |
|    #ifdef S4CLIENT_OR_FOX
 | |
|       if ( field->binary )
 | |
|          memset( f4assignPtr( field ), 0, field->len ) ;
 | |
|       else
 | |
|    #endif
 | |
|    memset( f4assignPtr( field ), ' ', field->len ) ;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| DATA4 *S4FUNCTION f4data( const FIELD4 *field )
 | |
| {
 | |
|    #ifdef E4PARM_HIGH
 | |
|       if ( field == 0 )
 | |
|       {
 | |
|          error4( 0, e4parm_null, E90509 ) ;
 | |
|          return 0 ;
 | |
|       }
 | |
|    #endif
 | |
| 
 | |
|    return field->data ;
 | |
| }
 | |
| 
 | |
| int S4FUNCTION f4decimals( const FIELD4 *field )
 | |
| {
 | |
|    #ifdef S4VBASIC
 | |
|       if ( c4parm_check( (void *)field, 3, E90510 ) )
 | |
|          return -1 ;
 | |
|    #endif
 | |
| 
 | |
|    #ifdef E4PARM_HIGH
 | |
|       if ( field == 0 )
 | |
|          return error4( 0, e4parm_null, E90510 ) ;
 | |
|    #endif
 | |
| 
 | |
|    return field->dec ;
 | |
| }
 | |
| 
 | |
| unsigned S4FUNCTION f4len( const FIELD4 *field )
 | |
| {
 | |
|    #ifdef S4VBASIC
 | |
|       if ( c4parm_check( (void *)field, 3, E90511 ) )
 | |
|          return 0 ;
 | |
|    #endif
 | |
| 
 | |
|    #ifdef E4PARM_HIGH
 | |
|       if ( field == 0 )
 | |
|       {
 | |
|          error4( 0, e4parm_null, E90511 ) ;
 | |
|          return 0 ;
 | |
|       }
 | |
|    #endif
 | |
| 
 | |
|    return field->len ;
 | |
| }
 | |
| 
 | |
| S4CONST char *S4FUNCTION f4name( S4CONST FIELD4 *field )
 | |
| {
 | |
|    #ifdef S4VBASIC
 | |
|       if ( c4parm_check( (void *)field, 3, E90512 ) )
 | |
|          return 0 ;
 | |
|    #endif
 | |
| 
 | |
|    #ifdef E4PARM_HIGH
 | |
|       if ( field == 0 )
 | |
|       {
 | |
|          error4( 0, e4parm_null, E90512 ) ;
 | |
|          return 0 ;
 | |
|       }
 | |
|    #endif
 | |
| 
 | |
|    return field->name ;
 | |
| }
 | |
| 
 | |
| int S4FUNCTION f4number( const FIELD4 *field )
 | |
| {
 | |
|    FIELD4 *fieldOn ;
 | |
|    int fNum ;
 | |
| 
 | |
|    #ifdef E4PARM_HIGH
 | |
|       if ( field == 0 )
 | |
|          return error4( 0, e4parm_null, E90538 ) ;
 | |
|    #endif
 | |
| 
 | |
|    fieldOn = field->data->fields ;
 | |
| 
 | |
|    for ( fNum = 1 ;;  fNum++ )
 | |
|    {
 | |
|       if ( fieldOn == field )
 | |
|          return fNum ;
 | |
|       fieldOn++ ;
 | |
|    }
 | |
| }
 | |
| 
 | |
| int S4FUNCTION f4type( const FIELD4 *field )
 | |
| {
 | |
|    #ifdef S4VBASIC
 | |
|       if ( c4parm_check( (void *)field, 3, E90513 ) )
 | |
|          return -1 ;
 | |
|    #endif
 | |
| 
 | |
|    #ifdef E4PARM_HIGH
 | |
|       if ( field == 0 )
 | |
|          return error4( 0, e4parm_null, E90513 ) ;
 | |
|    #endif
 | |
| 
 | |
|    #ifdef S4CLIENT_OR_FOX
 | |
|       switch( field->type )
 | |
|       {
 | |
|          case 'F':
 | |
|             return (int)r4num ;
 | |
|          case 'C':
 | |
|             if ( field->binary )
 | |
|                return r4charBin ;
 | |
|             else
 | |
|                return r4str ;
 | |
|          case 'M':
 | |
|             if ( field->binary == 1 )
 | |
|                return r4memoBin ;
 | |
|             else
 | |
|                return r4memo ;
 | |
|          default:
 | |
|             return (int)field->type ;
 | |
|       }
 | |
|    #else
 | |
|       if ( field->type == 'F' )
 | |
|          return (int)r4num ;
 | |
|       else
 | |
|          return (int)field->type ;
 | |
|    #endif
 | |
| }
 | |
| 
 | |
| #ifdef S4CLIENT_OR_FOX
 | |
| 
 | |
| static void negate( CURRENCY4 *, const CURRENCY4 * ) ;
 | |
| static void shiftLeft( long *, long *, int ) ;
 | |
| 
 | |
| int S4FUNCTION date4timeCompare( const long *dt1, const long *dt2 )
 | |
| {
 | |
|    long date1, date2, time1, time2 ;
 | |
| 
 | |
|    date1 = dt1[0] ;
 | |
|    date2 = dt2[0] ;
 | |
| 
 | |
|    if ( date1 == date2 )  /* must compare on times */
 | |
|    {
 | |
|       time1 = dt1[1] ;
 | |
|       time2 = dt2[1] ;
 | |
| 
 | |
|       if ( time1 > time2 )
 | |
|          return 1 ;
 | |
|       if ( time1 < time2 )
 | |
|          return -1 ;
 | |
|       return 0 ;
 | |
|    }
 | |
|    else  /* dates not equal */
 | |
|    {
 | |
|       if ( date1 > date2 )
 | |
|          return 1 ;
 | |
|       return -1 ;
 | |
|    }
 | |
| }
 | |
| 
 | |
| /* returns -1 if c1 < c2, 0 if equal, 1 if c1 > c2 */
 | |
| int S4FUNCTION currency4compare( const CURRENCY4 *c1, const CURRENCY4 *c2 )
 | |
| {
 | |
|    char sign1, sign2 ;
 | |
|    short int loop ;
 | |
|    long result ;
 | |
| 
 | |
|    sign1 = (short int)(c1->lo[3]) >= 0 ? 1 : -1 ;
 | |
|    sign2 = (short int)(c2->lo[3]) >= 0 ? 1 : -1 ;
 | |
| 
 | |
|    if ( sign1 != sign2 )   /* one positive, one negative, so comparison easy */
 | |
|    {
 | |
|       if ( sign1 == -1 )
 | |
|          return -1 ;
 | |
|       else
 | |
|          return 1 ;
 | |
|    }
 | |
| 
 | |
|    if ( sign1 == -1 )   /* negative comparison, larger value is smaller */
 | |
|    {
 | |
|       for ( loop = 3 ; loop > 0 ; loop-- )
 | |
|       {
 | |
|          result = c1->lo[loop] ;
 | |
|          result -= c2->lo[loop] ;
 | |
| 
 | |
|          if ( result < 0 )
 | |
|             return 1 ;
 | |
|          if ( result > 0 )
 | |
|             return -1 ;
 | |
|       }
 | |
|       return 0 ;
 | |
|    }
 | |
| 
 | |
|    /* otherwise both values positive, larger is larger */
 | |
|    for ( loop = 3 ; loop > 0 ; loop-- )
 | |
|    {
 | |
|       result = c1->lo[loop] ;
 | |
|       result -= c2->lo[loop] ;
 | |
| 
 | |
|       if ( result < 0 )
 | |
|          return -1 ;
 | |
|       if ( result > 0 )
 | |
|          return 1 ;
 | |
|    }
 | |
|    return 0 ;
 | |
| }
 | |
| 
 | |
| int S4FUNCTION currency4add( CURRENCY4 *result, const CURRENCY4 *c1, const CURRENCY4 *c2 )
 | |
| {
 | |
|    char sign1, sign2, carry ;
 | |
|    short int loop ;
 | |
|    long val1, val2, resultVal ;
 | |
| 
 | |
|    sign1 = (short int)(c1->lo[3]) >= 0 ? 1 : -1 ;
 | |
|    sign2 = (short int)(c2->lo[3]) >= 0 ? 1 : -1 ;
 | |
| 
 | |
|    carry = 0 ;
 | |
|    for ( loop = 0 ; loop < 4 ; loop++ )
 | |
|    {
 | |
|       if ( sign1 == -1 && sign2 == -1 )
 | |
|       {
 | |
|          val1 = -(short int)(c1->lo[loop]) ;
 | |
|          val2 = -(short int)(c2->lo[loop]) ;
 | |
|          if ( val1 == 0 )
 | |
|             val1 = 65536 ;
 | |
|          if ( val2 == 0 )
 | |
|             val2 = 65536 ;
 | |
|          if ( loop != 0 )
 | |
|             val2-- ;
 | |
|       }
 | |
|       else
 | |
|       {
 | |
|          val1 = c1->lo[loop] ;
 | |
|          val2 = c2->lo[loop] ;
 | |
|       }
 | |
|       resultVal = val1 + val2 + carry ;
 | |
|       carry = 0 ;
 | |
|       if ( resultVal > USHRT_MAX )
 | |
|       {
 | |
|          #ifdef S4TESTING
 | |
|             if ( ( resultVal - (long)USHRT_MAX ) > USHRT_MAX )
 | |
|                return error4( 0, e4info, E99999 ) ;
 | |
|          #endif
 | |
|          carry = 1 ;
 | |
|          result->lo[loop] = (int)(resultVal - (long)USHRT_MAX - 1) ;
 | |
|       }
 | |
|       else
 | |
|          result->lo[loop] = (int)resultVal ;
 | |
|       if ( sign1 == -1 && sign2 == -1 )
 | |
|          result->lo[loop] = -((short int)result->lo[loop]) ;
 | |
|    }
 | |
| 
 | |
|    return 0 ;
 | |
| }
 | |
| 
 | |
| int S4FUNCTION currency4subtract( CURRENCY4 *result, const CURRENCY4 *c1, const CURRENCY4 *c2 )
 | |
| {
 | |
|    CURRENCY4 temp ;
 | |
| 
 | |
|    memcpy( &temp, c2, sizeof( CURRENCY4 ) ) ;
 | |
|    negate( &temp, &temp ) ;
 | |
| 
 | |
|    currency4add( result, c1, &temp ) ;
 | |
| 
 | |
|    return 0 ;
 | |
| }
 | |
| 
 | |
| int S4FUNCTION currency4multiplyShort( CURRENCY4 *result, const CURRENCY4 *c1, const short c2 )
 | |
| {
 | |
|    int loop, sign1, sign2, signResult, pos ;
 | |
|    CURRENCY4 cur1, hold ;
 | |
|    unsigned long val1, valResult ;
 | |
|    short int cur2 ;
 | |
| 
 | |
|    sign1 = (short int)(c1->lo[3]) >= 0 ? 1 : -1 ;
 | |
|    sign2 = c2 >= 0 ? 1 : -1 ;
 | |
| 
 | |
|    if ( sign1 == -1 )
 | |
|    {
 | |
|       negate( &cur1, c1 ) ;
 | |
|       signResult = -1 ;
 | |
|    }
 | |
|    else
 | |
|    {
 | |
|       memcpy( &cur1, c1, sizeof( CURRENCY4 ) ) ;
 | |
|       signResult = 1 ;
 | |
|    }
 | |
| 
 | |
|    if ( sign2 == -1 )
 | |
|    {
 | |
|       cur2 = -c2 ;
 | |
|       signResult *= -1 ;
 | |
|    }
 | |
|    else  /* no change to sign */
 | |
|       cur2 = c2 ;
 | |
| 
 | |
|    memset( result, 0, sizeof( CURRENCY4 ) ) ;
 | |
| 
 | |
|    for ( loop = 0 ; loop < 4 ; loop++ )
 | |
|    {
 | |
|       val1 = cur1.lo[loop] ;
 | |
|       pos = loop ;
 | |
|       if ( pos >= 4 )  /* too large to store results */
 | |
|          break ;
 | |
|       if ( val1 == 0 )
 | |
|          continue ;
 | |
|       valResult = val1 * cur2 ;
 | |
|       memset( &hold, 0, sizeof( CURRENCY4 ) ) ;
 | |
|       if ( pos == 3 )  /* only least significant bytes important */
 | |
|          memcpy( &(hold.lo[pos]), &valResult, 2 ) ;
 | |
|       else
 | |
|          memcpy( &(hold.lo[pos]), &valResult, 4 ) ;
 | |
|       currency4add( result, result, &hold ) ;
 | |
|    }
 | |
| 
 | |
|    if ( signResult == -1 )
 | |
|       negate( result, result ) ;
 | |
| 
 | |
|    return 0 ;
 | |
| }
 | |
| #ifdef NOT_IMPLEMENTED_YET
 | |
| int currency4multiply( CURRENCY4 *result, const CURRENCY4 *c1, const CURRENCY4 *c2 )
 | |
| {
 | |
|    int loop, sign1, sign2, signResult, jLoop, pos ;
 | |
|    CURRENCY4 cur1, cur2, hold, tenThousand ;
 | |
|    unsigned long val1, val2, valResult ;
 | |
| 
 | |
|    sign1 = (short int)(c1->lo[3]) >= 0 ? 1 : -1 ;
 | |
|    sign2 = (short int)(c2->lo[3]) >= 0 ? 1 : -1 ;
 | |
| 
 | |
|    if ( sign1 == -1 )
 | |
|    {
 | |
|       negate( &cur1, c1 ) ;
 | |
|       signResult = -1 ;
 | |
|    }
 | |
|    else
 | |
|    {
 | |
|       memcpy( &cur1, c1, sizeof( CURRENCY4 ) ) ;
 | |
|       signResult = 1 ;
 | |
|    }
 | |
| 
 | |
|    if ( sign2 == -1 )
 | |
|    {
 | |
|       negate( &cur2, c2 ) ;
 | |
|       signResult *= -1 ;
 | |
|    }
 | |
|    else  /* no change to sign */
 | |
|       memcpy( &cur2, c2, sizeof( CURRENCY4 ) ) ;
 | |
| 
 | |
|    memset( result, 0, sizeof( CURRENCY4 ) ) ;
 | |
|    memset( &tenThousand, 0, sizeof( CURRENCY4 ) ) ;
 | |
|    tenThousand.lo[0] = 0x2710 ;
 | |
| 
 | |
|    for ( jLoop = 0 ; jLoop < 4 ; jLoop++ )
 | |
|    {
 | |
|       val2 = cur2.lo[jLoop] ;
 | |
|       if ( val2 == 0 )
 | |
|          continue ;
 | |
|       for ( loop = 0 ; loop < 4 ; loop++ )
 | |
|       {
 | |
|          val1 = cur1.lo[loop] ;
 | |
|          pos = loop + jLoop ;
 | |
|          if ( pos >= 4 )  /* too large to store results */
 | |
|             break ;
 | |
|          if ( val1 == 0 )
 | |
|             continue ;
 | |
|          valResult = val1 * val2 ;
 | |
|          memset( &hold, 0, sizeof( CURRENCY4 ) ) ;
 | |
|          if ( pos == 3 )  /* only least significant bytes important */
 | |
|             memcpy( &(hold.lo[pos]), &valResult, 2 ) ;
 | |
|          else
 | |
|             memcpy( &(hold.lo[pos]), &valResult, 4 ) ;
 | |
|          currency4add( result, result, &hold ) ;
 | |
|       }
 | |
|    }
 | |
| 
 | |
|    if ( signResult == -1 )
 | |
|       negate( result, result ) ;
 | |
| 
 | |
|    return 0 ;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| static void negate( CURRENCY4 *result, const CURRENCY4 *source )
 | |
| {
 | |
|    int loop ;
 | |
|    CURRENCY4 one ;
 | |
| 
 | |
|    if ( ( (short int)(source->lo[3]) >= 0 ? 1 : -1 ) == -1 )  /* negative */
 | |
|    {
 | |
|       memset( &one, 0, sizeof( CURRENCY4 ) ) ;
 | |
|       one.lo[0] = 0x0001 ;
 | |
| 
 | |
|       for ( loop = 0; loop < 4 ; loop++ )
 | |
|          result->lo[loop] = ~source->lo[loop] ;
 | |
|       currency4add( result, result, &one ) ;
 | |
|    }
 | |
|    else /* positive */
 | |
|    {
 | |
|       memset( &one, (unsigned char)0xFF, sizeof( CURRENCY4 ) ) ;
 | |
| 
 | |
|       memcpy( result, source, sizeof( CURRENCY4 ) ) ;
 | |
|       currency4add( result, result, &one ) ;
 | |
|       for ( loop = 0; loop < 4 ; loop++ )
 | |
|          result->lo[loop] = ~result->lo[loop] ;
 | |
|    }
 | |
| }
 | |
| 
 | |
| static void shiftLeft( long *left, long *right, int numShift )
 | |
| {
 | |
|    int loop ;
 | |
| 
 | |
|    for ( loop = 0 ; loop < numShift ; loop++ )
 | |
|    {
 | |
|       *left = *left << 1 ;
 | |
|       *left = *left | ( 1 * ( *right & 0x80000000 ) ) ;
 | |
|       *right = *right << 1 ;
 | |
|    }
 | |
| }
 | |
| 
 | |
| static void shiftRight( long *left, long *right, int numShift )
 | |
| {
 | |
|    int loop ;
 | |
| 
 | |
|    for ( loop = 0 ; loop < numShift ; loop++ )
 | |
|    {
 | |
|       *right = *right >> 1 ;
 | |
|       *right = *right | ( 0x80000000 * ( *left & 0x00000001 ) ) ;
 | |
|       *left = *left >> 1 ;
 | |
|    }
 | |
| }
 | |
| 
 | |
| int S4FUNCTION currency4divideShort( CURRENCY4 *result, const CURRENCY4 *c1, const short c2 )
 | |
| {
 | |
|    unsigned short int shortResult ;
 | |
|    short int cur2 ;
 | |
|    unsigned long shortMod ;
 | |
|    int sign1, sign2, signResult, loop ;
 | |
|    CURRENCY4 add, cur1 ;
 | |
| 
 | |
|    sign1 = (short int)(c1->lo[3]) >= 0 ? 1 : -1 ;
 | |
|    sign2 = c2 >= 0 ? 1 : -1 ;
 | |
| 
 | |
|    if ( sign1 == -1 )
 | |
|    {
 | |
|       negate( &cur1, c1 ) ;
 | |
|       signResult = -1 ;
 | |
|    }
 | |
|    else
 | |
|    {
 | |
|       memcpy( &cur1, c1, sizeof( CURRENCY4 ) ) ;
 | |
|       signResult = 1 ;
 | |
|    }
 | |
| 
 | |
|    if ( sign2 == -1 )
 | |
|    {
 | |
|       cur2 = -c2 ;
 | |
|       signResult *= -1 ;
 | |
|    }
 | |
|    else  /* no change to sign */
 | |
|       cur2 = c2 ;
 | |
| 
 | |
|    if ( cur2 == 0 )
 | |
|       return -1 ;
 | |
| 
 | |
|    memset( result, 0, sizeof( CURRENCY4 ) ) ;
 | |
| 
 | |
|    if ( *((long *)(&cur1.lo[2])) == 0 )  /* value smaller than max long */
 | |
|    {
 | |
|       *((long *)(&result->lo[0])) = *((long *)(&cur1.lo[0])) / cur2 ;
 | |
|       if ( signResult == -1 )
 | |
|          negate( result, result ) ;
 | |
|       return 0 ;
 | |
|    }
 | |
| 
 | |
|    shortMod = 0 ;
 | |
|    for ( loop = 3 ; loop >= 0 ; loop-- )
 | |
|    {
 | |
|       memset( &add, 0, sizeof( CURRENCY4 ) ) ;
 | |
|       shortResult = (unsigned short)(((unsigned long)cur1.lo[loop] + shortMod )/ cur2) ;
 | |
|       memcpy( ((unsigned short int *)(&add)) + loop, &shortResult, sizeof( short int ) ) ;
 | |
|       if ( loop != 0 )
 | |
|          shortMod = ((unsigned long)(USHRT_MAX)+1) * ((cur1.lo[loop] + shortMod) % cur2 ) ;
 | |
|       currency4add( result, result, &add) ;
 | |
|    }
 | |
| 
 | |
|    if ( signResult == -1 )
 | |
|       negate( result, result ) ;
 | |
| 
 | |
|    return 0 ;
 | |
| }
 | |
| #ifdef NOT_IMPLEMENTED_YET
 | |
| int currency4divide( CURRENCY4 *result, const CURRENCY4 *c1, const CURRENCY4 *c2 )
 | |
| {
 | |
|    long topLeft, topRight, bottomLeft, bottomRight, resultRight ;
 | |
|    long stopShiftVal, holdLeft, holdRight ;
 | |
|    int sign1, sign2, signResult, numShift, signHold ;
 | |
|    CURRENCY4 add, subtract, hold, hold2, cur1, cur2 ;
 | |
| 
 | |
|    sign1 = (short int)(c1->lo[3]) >= 0 ? 1 : -1 ;
 | |
|    sign2 = (short int)(c2->lo[3]) >= 0 ? 1 : -1 ;
 | |
| 
 | |
|    if ( sign1 == -1 )
 | |
|    {
 | |
|       negate( &cur1, c1 ) ;
 | |
|       signResult = -1 ;
 | |
|    }
 | |
|    else
 | |
|    {
 | |
|       memcpy( &cur1, c1, sizeof( CURRENCY4 ) ) ;
 | |
|       signResult = 1 ;
 | |
|    }
 | |
| 
 | |
|    if ( sign2 == -1 )
 | |
|    {
 | |
|       negate( &cur2, c2 ) ;
 | |
|       signResult *= -1 ;
 | |
|    }
 | |
|    else  /* no change to sign */
 | |
|       memcpy( &cur2, c2, sizeof( CURRENCY4 ) ) ;
 | |
| 
 | |
|    topLeft = *((long *)(&cur1.lo[2])) ;
 | |
|    topRight = *((long *)(&cur1.lo[0])) ;
 | |
|    bottomLeft = *((long *)(&cur2.lo[2])) ;
 | |
|    bottomRight = *((long *)(&cur2.lo[0])) ;
 | |
| 
 | |
|    if ( bottomLeft == 0 && bottomRight == 0 )  /* divide by zero */
 | |
|       return -1 ;
 | |
| 
 | |
|    memset( result, 0, sizeof( CURRENCY4 ) ) ;
 | |
| 
 | |
|    if ( topLeft == 0 )  /* value smaller than max long */
 | |
|    {
 | |
|       if ( bottomLeft != 0 )  /* bottom larger than top */
 | |
|          return 0 ;
 | |
|       if ( bottomRight == 0 )
 | |
|          return -1 ;
 | |
|       resultRight = topRight / bottomRight ;
 | |
|       memcpy( &(result->lo[0]), &resultRight, sizeof( long ) ) ;
 | |
|       if ( signResult == -1 )
 | |
|          negate( result, result ) ;
 | |
|       return 0 ;
 | |
|    }
 | |
| 
 | |
|    if ( topLeft < bottomLeft )   /* zero return */
 | |
|    {
 | |
|       if ( signResult == -1 )
 | |
|          negate( result, result ) ;
 | |
|       return 0 ;
 | |
|    }
 | |
| 
 | |
|    if ( topLeft == bottomLeft )  /* either one or zero return */
 | |
|    {
 | |
|       if ( topRight >= bottomRight )
 | |
|       {
 | |
|          result->lo[0] = 1 ;
 | |
|          if ( signResult == -1 )
 | |
|             negate( result, result ) ;
 | |
|       }
 | |
|       return 0 ;
 | |
|    }
 | |
| 
 | |
|    /* case where topLeft > 0 && topLeft > bottomLeft */
 | |
|    memcpy( &(hold.lo[0]), &topRight, sizeof( long ) ) ;
 | |
|    memcpy( &(hold.lo[2]), &topLeft, sizeof( long ) ) ;
 | |
|    stopShiftVal = topLeft / 2 ;
 | |
|    for ( ;; )
 | |
|    {
 | |
|       numShift = -1 ;
 | |
|       while( bottomLeft < stopShiftVal )
 | |
|       {
 | |
|          holdLeft = bottomLeft ;
 | |
|          holdRight = bottomRight ;
 | |
|          shiftLeft( &bottomLeft, &bottomRight, 1 ) ;
 | |
|          numShift++ ;
 | |
|       }
 | |
| 
 | |
|       bottomLeft = holdLeft ;
 | |
|       bottomRight = holdRight ;
 | |
| 
 | |
|       memset( &add, 0, sizeof( CURRENCY4 ) ) ;
 | |
| 
 | |
|       currency4add( result, result, &add ) ;
 | |
| 
 | |
|       #ifdef E4DEBUG
 | |
|          if ( ( (short int)(hold->lo[3]) >= 0 ? 1 : -1 ) == -1 )
 | |
|             return error4( 0, e4info, E90542 ) ;
 | |
|       #endif
 | |
| 
 | |
|       for ( signHold = 1 ;; )
 | |
|       {
 | |
|          memcpy( &(subtract.lo[0]), &holdRight, sizeof( long ) ) ;
 | |
|          memcpy( &(subtract.lo[2]), &holdLeft, sizeof( long ) ) ;
 | |
|          memcpy( &hold2, &hold, sizeof( CURRENCY4 ) ) ;
 | |
|          currency4subtract( &hold, &hold, &subtract ) ;
 | |
|          signHold = (short int)(hold.lo[3]) >= 0 ? 1 : -1 ;
 | |
|          if ( signHold == -1 )
 | |
|             break ;
 | |
|       }
 | |
| 
 | |
|       memcpy( &hold, &hold2, sizeof( CURRENCY4 ) ) ;
 | |
|       topLeft = *((long *)(&hold.lo[2])) ;
 | |
|       topRight = *((long *)(&hold.lo[0])) ;
 | |
| 
 | |
|       stopShiftVal = topLeft / 2 ;
 | |
|       while ( bottomLeft > topLeft )
 | |
|       {
 | |
|          shiftRight( &bottomLeft, &bottomRight, 1 ) ;
 | |
|          numShift-- ;
 | |
|       }
 | |
|    }
 | |
| 
 | |
|    if ( signResult == -1 )
 | |
|       negate( result, result ) ;
 | |
| 
 | |
|    return 0 ;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| /*
 | |
| int currency4mod( CURRENCY4 *result, const CURRENCY4 *c1, const CURRENCY4 *c1 )
 | |
| {
 | |
| 
 | |
| }
 | |
| */
 | |
| 
 | |
| int S4FUNCTION c4currencyToA( char *out, int outLen, const CURRENCY4 *sourceIn, int numDec )
 | |
| {
 | |
|    int sign, pos, loop, reqdLen ;
 | |
|    CURRENCY4 hold, old, mod, sv, source ;
 | |
|    unsigned char buf[21] ;
 | |
|    unsigned long l1 ;
 | |
| 
 | |
|    memcpy( &source, sourceIn, sizeof( CURRENCY4 ) ) ;
 | |
|    sign = (short int)(source.lo[3]) >= 0 ? 1 : -1 ;
 | |
|    if ( sign == -1 )
 | |
|       negate( &source, &source ) ;
 | |
| 
 | |
|    memcpy( &hold, &source, sizeof( CURRENCY4 ) ) ;
 | |
|    memset( buf, 0, sizeof( buf ) ) ;
 | |
| 
 | |
|    for ( pos = 0 ; pos < 20 ; pos++ )
 | |
|    {
 | |
|       if ( *((long *)(&hold.lo[2])) == 0L )  /* only right portion */
 | |
|          break ;
 | |
|       memcpy( &old, &hold, sizeof( CURRENCY4 ) ) ;
 | |
|       currency4divideShort( &hold, &hold, 10 ) ;
 | |
|       currency4multiplyShort( &sv, &hold, 10 ) ;
 | |
|       currency4subtract( &mod, &old, &sv ) ;
 | |
|       buf[pos] = (char)mod.lo[0] ;
 | |
|    }
 | |
| 
 | |
|    /* if any portion is left, it is only the right portion */
 | |
|    if ( *((long *)(&hold.lo[2])) == 0L )  /* only right portion */
 | |
|    {
 | |
|       l1 = *((long *)(&hold.lo[0])) ;
 | |
|       if ( l1 == 0 )
 | |
|       {
 | |
|          if ( pos == 0 )   /* zero */
 | |
|             pos = -1 ;
 | |
|       }
 | |
|       else
 | |
|       {
 | |
|          for ( ; pos < 20 ; )
 | |
|          {
 | |
|             buf[pos] = (unsigned char) (l1 % 10) ;
 | |
|             l1 = l1 / 10 ;
 | |
|             if ( l1 == 0 )
 | |
|                break ;
 | |
|             pos++ ;
 | |
|          }
 | |
|       }
 | |
|    }
 | |
| 
 | |
|    memset( out, 0, outLen ) ;
 | |
| 
 | |
|    if ( pos == -1 )
 | |
|    {
 | |
|       reqdLen = 6 ;  /* x.xxxx */
 | |
|       memset( out, '0', 5 ) ;
 | |
|    }
 | |
|    else
 | |
|    {
 | |
|       reqdLen = pos + 2 ; /* for decimal point and because pos is 1 less than amount */
 | |
|       if ( reqdLen < 6 )
 | |
|       {
 | |
|          memset( out, '0', 5 ) ;
 | |
|          reqdLen = 6 ;  /* x.xxxx */
 | |
|       }
 | |
|    }
 | |
| 
 | |
| 
 | |
|    if ( (reqdLen+1) > outLen + (sign == -1) )   /* insufficient space */
 | |
|       return -1 ;
 | |
| 
 | |
|    loop = 5 - (pos+1) ;
 | |
|    if ( loop < 0 )
 | |
|       loop = 0 ;
 | |
|    for ( ; pos >= 0 ; pos--, loop++ )  /* reverse the string */
 | |
|       out[loop] = buf[pos] + '0' ;
 | |
| 
 | |
|    /* now reposition for the decimal points */
 | |
|    c4memmove( &(out[reqdLen-4]), &(out[reqdLen-5]), 4 ) ;
 | |
|    out[reqdLen-5] = '.' ;
 | |
| 
 | |
|    /* now remove any decimal points according to input */
 | |
|    if ( numDec == 0 )
 | |
|    {
 | |
|       reqdLen -= 5 ;
 | |
|       out[reqdLen] = 0 ;
 | |
|    }
 | |
|    else
 | |
|    {
 | |
|       if ( numDec > 4 || numDec < 0 )
 | |
|          numDec = 4 ;
 | |
|       out[reqdLen-4+numDec] = 0 ;
 | |
|       reqdLen -= (4 - numDec) ;
 | |
|    }
 | |
| 
 | |
|    if ( sign == -1 )
 | |
|    {
 | |
|       c4memmove( out+1, out, reqdLen + 1 ) ;
 | |
|       out[0] = '-' ;
 | |
|    }
 | |
| 
 | |
|    return 0 ;
 | |
| }
 | |
| 
 | |
| /* returns -1 if an invalid currency input string */
 | |
| int S4FUNCTION c4atoCurrency( CURRENCY4 *result, const char *str, int strLen )
 | |
| {
 | |
|    char buf[21] ;
 | |
|    int loop, len, numDecimals, numWhole, sign, numDigits ;
 | |
|    short int multiplier, mPower ;
 | |
|    long val ;
 | |
|    const char *decPt ;
 | |
|    CURRENCY4 temp, mult ;
 | |
|    char *ptr ;
 | |
| 
 | |
|    memset( result, 0, sizeof( CURRENCY4 ) ) ;
 | |
| 
 | |
|    decPt = 0 ;
 | |
|    len = strLen ;
 | |
|    if ( len == 0 )
 | |
|       return 0 ;
 | |
|    for ( ;; )
 | |
|    {
 | |
|       if ( str[0] != ' ' )
 | |
|          break ;
 | |
|       len-- ;
 | |
|       str++ ;
 | |
|       if ( len == 0 )
 | |
|          return 0 ;
 | |
|    }
 | |
|    if ( str[0] == '-' )
 | |
|    {
 | |
|       sign = -1 ;
 | |
|       str++ ;
 | |
|       len-- ;
 | |
|    }
 | |
|    else
 | |
|    {
 | |
|       sign = 1 ;
 | |
|       if ( str[0] == '+' )
 | |
|       {
 | |
|          str++ ;
 | |
|          len-- ;
 | |
|       }
 | |
|    }
 | |
|    while ( str[0] == '0' && str[1] == '0' )  /* get rid of leading zeros */
 | |
|    {
 | |
|       str++ ;
 | |
|       len-- ;
 | |
|    }
 | |
|    numDecimals = 0 ;
 | |
|    numWhole = len ;
 | |
|    for ( loop = len - 1 ; loop >= 0 ; loop-- )
 | |
|    {
 | |
|       if ( str[loop] == '.' )
 | |
|       {
 | |
|          numDecimals = len - loop - 1 ;
 | |
|          numWhole = len - numDecimals - 1 ;
 | |
|          decPt = &str[loop]+1 ;
 | |
|          break ;
 | |
|       }
 | |
|    }
 | |
| 
 | |
|    if ( numDecimals > 4 )
 | |
|       return -1 ;
 | |
| 
 | |
|    numDigits = numWhole + 4 ;
 | |
| 
 | |
|    if ( numDigits > 20 )
 | |
|       return -1 ;
 | |
| 
 | |
|    memcpy( buf, str, numWhole ) ;
 | |
|    if ( decPt != 0 )
 | |
|       c4memmove( buf+numWhole, decPt, numDecimals ) ;
 | |
|    for ( loop = numDecimals ; loop < 4 ; loop++ )
 | |
|    {
 | |
|       buf[numWhole+loop] = '0' ;
 | |
|    }
 | |
| 
 | |
|    buf[numDigits] = 0 ;
 | |
| 
 | |
|    if ( numDigits < 10 || ( numDigits == 10 && ( str[0] <= '3' && str[0] >= '0' ) ) )
 | |
|    {
 | |
|       /* fits in a single long */
 | |
| 
 | |
|       val = c4atol( buf, strlen( buf ) ) ;
 | |
|       if ( sign == -1 )
 | |
|          val = -val ;
 | |
| 
 | |
|       if ( val == 0 )   /* negative 0 is still zero */
 | |
|          sign = 1 ;
 | |
| 
 | |
|       if ( sign == 1 )   /* positive value */
 | |
|       {
 | |
|          result->lo[3] = 0 ;
 | |
|          result->lo[2] = 0 ;
 | |
|       }
 | |
|       else   /* negative value */
 | |
|       {
 | |
|          result->lo[3] = 0xFFFF ;
 | |
|          result->lo[2] = 0xFFFF ;
 | |
|       }
 | |
| 
 | |
|       memcpy( &result->lo[0], &val, sizeof( long ) ) ;
 | |
| 
 | |
|       return 0 ;
 | |
|    }
 | |
| 
 | |
|    /* more complex scenario because number is larger than a long */
 | |
|    /* first get the first 9 bytes and store to long */
 | |
|    val = c4atol( buf, 9 ) ;
 | |
| 
 | |
|    memcpy( &result->lo[0], &val, sizeof( long ) ) ;
 | |
| 
 | |
|    ptr = buf + 9 ;
 | |
|    numDigits -= 9 ;
 | |
|    while ( numDigits > 4 )
 | |
|    {
 | |
|       multiplier = c4atoi( ptr, 4 ) ;
 | |
|       memset( &mult, 0, sizeof( CURRENCY4 ) ) ;
 | |
|       mult.lo[0] = 10000 ;
 | |
|       currency4multiplyShort( &temp, result, 10000 ) ;
 | |
|       *result = temp ;
 | |
|       if ( multiplier != 0 )  /* add */
 | |
|       {
 | |
|          memset( &temp, 0, sizeof( temp ) ) ;
 | |
|          memcpy( &(temp.lo[0]), &multiplier, sizeof( short ) ) ;
 | |
|          currency4add( result, result, &temp ) ;
 | |
|       }
 | |
|       numDigits -= 4 ;
 | |
|       ptr += 4 ;
 | |
|    }
 | |
| 
 | |
|    if ( numDigits != 0 )
 | |
|    {
 | |
|       multiplier = c4atoi( ptr, numDigits ) ;
 | |
|       mPower = 1 ;
 | |
|       for ( ; numDigits > 0 ; numDigits-- )
 | |
|          mPower *= 10 ;
 | |
|       currency4multiplyShort( &temp, result, mPower ) ;
 | |
|       *result = temp ;
 | |
|       if ( multiplier != 0 )  /* add */
 | |
|       {
 | |
|          memset( &temp, 0, sizeof( temp ) ) ;
 | |
|          memcpy( &(temp.lo[0]), &multiplier, sizeof( short ) ) ;
 | |
|          currency4add( result, result, &temp ) ;
 | |
|       }
 | |
|    }
 | |
| 
 | |
|    if ( sign == -1 )
 | |
|    {
 | |
|       memset( &mult, 0, sizeof( CURRENCY4 ) ) ;
 | |
|       mult.lo[0] = 0x0001 ;
 | |
|       currency4subtract( result, result, &mult ) ;
 | |
|       for ( loop = 0; loop < 4 ; loop++ )
 | |
|          result->lo[loop] = ~result->lo[loop] ;
 | |
|    }
 | |
| 
 | |
|    return 0 ;
 | |
| }
 | |
| 
 | |
| #ifndef S4OFF_WRITE
 | |
| void S4FUNCTION f4assignCurrency( FIELD4 *field, char *str )
 | |
| {
 | |
|    #ifdef S4VBASIC
 | |
|       if ( c4parm_check( field, 3, E90541 ) )
 | |
|          return ;
 | |
|    #endif
 | |
| 
 | |
|    #ifdef E4PARM_HIGH
 | |
|       if ( field == 0 || str == 0 )
 | |
|       {
 | |
|          error4( 0, e4parm_null, E90541 ) ;
 | |
|          return ;
 | |
|       }
 | |
|    #endif
 | |
| 
 | |
|    if ( field->type != r4currency )
 | |
|    {
 | |
|       #ifdef E4PARM_HIGH
 | |
|          error4( field->data->codeBase, e4parm, E81409 ) ;
 | |
|       #endif
 | |
|       return ;
 | |
|    }
 | |
| 
 | |
|    #ifdef E4ANALYZE
 | |
|       if ( field->data == 0 )
 | |
|       {
 | |
|          error4( 0, e4struct, E90541 ) ;
 | |
|          return ;
 | |
|       }
 | |
|       if ( field->data->codeBase == 0 )
 | |
|       {
 | |
|          error4( 0, e4struct, E90541 ) ;
 | |
|          return ;
 | |
|       }
 | |
|    #endif
 | |
| 
 | |
|    #ifdef E4PARM_HIGH
 | |
|       if ( field->type != r4currency )
 | |
|       {
 | |
|          error4( field->data->codeBase, e4parm, E81404 ) ;
 | |
|          return ;
 | |
|       }
 | |
|    #endif
 | |
| 
 | |
|    if ( error4code( field->data->codeBase ) < 0 )
 | |
|       return ;
 | |
| 
 | |
|    #ifndef S4SERVER
 | |
|       #ifndef S4OFF_ENFORCE_LOCK
 | |
|          if ( field->data->codeBase->lockEnforce && field->data->recNum > 0L )
 | |
|             if ( d4lockTest( field->data, field->data->recNum ) != 1 )
 | |
|             {
 | |
|                error4( field->data->codeBase, e4lock, E90541 ) ;
 | |
|                return ;
 | |
|             }
 | |
|       #endif
 | |
|    #endif
 | |
| 
 | |
|    c4atoCurrency( (CURRENCY4 *)f4assignPtr( field ), str, strlen( str ) ) ;
 | |
| }
 | |
| #endif /* S4OFF_WRITE */
 | |
| 
 | |
| /* this function uses the same memory as f4str() */
 | |
| char *S4FUNCTION f4currency( const FIELD4 *field, int numDec )
 | |
| {
 | |
|    CODE4 *codeBase ;
 | |
| 
 | |
|    #ifdef S4VBASIC
 | |
|       if ( c4parm_check( field, 3, E90542 ) )
 | |
|          return -1 ;
 | |
|    #endif
 | |
| 
 | |
|    #ifdef E4PARM_HIGH
 | |
|       if ( field == 0 || numDec < 0 || numDec > 4 )
 | |
|       {
 | |
|          error4( 0, e4parm, E90542 ) ;
 | |
|          return 0 ;
 | |
|       }
 | |
|    #endif
 | |
| 
 | |
|    codeBase = field->data->codeBase ;
 | |
| 
 | |
|    #ifdef E4PARM_HIGH
 | |
|       if ( field->type != r4currency )
 | |
|       {
 | |
|          error4( codeBase, e4parm, E81409 ) ;
 | |
|          return 0 ;
 | |
|       }
 | |
|    #endif
 | |
| 
 | |
|    if ( error4code( codeBase ) < 0 )
 | |
|       return 0 ;
 | |
| 
 | |
|    if ( codeBase->bufLen <= 20 )   /* not room for field length + null */
 | |
|    {
 | |
|       if ( u4allocAgain( codeBase, &codeBase->fieldBuffer, &codeBase->bufLen, 21 ) < 0 )
 | |
|       {
 | |
|          #ifdef E4STACK
 | |
|             error4stack( codeBase, e4memory, E90542 ) ;
 | |
|          #endif
 | |
|          return 0 ;
 | |
|       }
 | |
|    }
 | |
|    else
 | |
|       codeBase->fieldBuffer[20] = 0 ;
 | |
| 
 | |
|    c4currencyToA( codeBase->fieldBuffer, 20, (CURRENCY4 *)f4ptr( field ), numDec ) ;
 | |
|    return codeBase->fieldBuffer ;
 | |
| }
 | |
| 
 | |
| #ifndef S4OFF_WRITE
 | |
| void S4FUNCTION f4assignNotNull( FIELD4 *field )
 | |
| {
 | |
|    FIELD4 *nullFlags ;
 | |
|    unsigned short int byteNum, offset ;
 | |
|    char mask ;
 | |
|    char *fPtr ;
 | |
| 
 | |
|    if ( d4version( field->data ) != 0x30 )
 | |
|       return ;
 | |
| 
 | |
|    if ( field->null == 1 )
 | |
|    {
 | |
|       if ( f4null( field ) )
 | |
|       {
 | |
|          nullFlags = &(field->data->fields[d4numFields(field->data)]) ;
 | |
|          #ifdef E4MISC
 | |
|             if ( nullFlags->type != r4system )
 | |
|             {
 | |
|                error4( field->data->codeBase, e4data, E83805 ) ;
 | |
|                return ;
 | |
|             }
 | |
|          #endif
 | |
|          byteNum = field->nullBit / 8 ;
 | |
|          #ifdef E4MISC
 | |
|             if ( nullFlags->len < ( byteNum + 1 ) )
 | |
|             {
 | |
|                error4( field->data->codeBase, e4data, E83805 ) ;
 | |
|                return ;
 | |
|             }
 | |
|          #endif
 | |
|          offset = ( field->nullBit - (byteNum * 8) ) ;
 | |
|          mask = (unsigned int)0x01 << offset ;
 | |
|          mask = ~mask ;
 | |
|          fPtr = f4ptr( nullFlags ) ;
 | |
|          fPtr[byteNum] = fPtr[byteNum] & mask ;
 | |
|       }
 | |
|    }
 | |
| }
 | |
| 
 | |
| void S4FUNCTION f4assignNull( FIELD4 *field )
 | |
| {
 | |
|    FIELD4 *nullFlags ;
 | |
|    unsigned short int byteNum, offset ;
 | |
|    char mask ;
 | |
|    char *fPtr ;
 | |
| 
 | |
|    #ifdef S4VBASIC
 | |
|       if ( c4parm_check( field, 3, E90539 ) )
 | |
|          return ;
 | |
|    #endif
 | |
| 
 | |
|    #ifdef E4PARM_HIGH
 | |
|       if ( field == 0 )
 | |
|       {
 | |
|          error4( 0, e4parm_null, E90539 ) ;
 | |
|          return ;
 | |
|       }
 | |
|    #endif
 | |
| 
 | |
|    if ( error4code( field->data->codeBase ) < 0 )
 | |
|       return ;
 | |
| 
 | |
|    if ( d4version( field->data ) != 0x30 )
 | |
|    {
 | |
|       error4( field->data->codeBase, e4parm, E81409 ) ;
 | |
|       return ;
 | |
|    }
 | |
| 
 | |
|    #ifndef S4SERVER
 | |
|       #ifndef S4OFF_ENFORCE_LOCK
 | |
|          if ( field->data->codeBase->lockEnforce && field->data->recNum > 0L )
 | |
|             if ( d4lockTest( field->data, field->data->recNum ) != 1 )
 | |
|             {
 | |
|                error4( field->data->codeBase, e4lock, E90539 ) ;
 | |
|                return ;
 | |
|             }
 | |
|       #endif
 | |
|    #endif
 | |
| 
 | |
|    if ( field->null == 1 )
 | |
|    {
 | |
|       nullFlags = &(field->data->fields[d4numFields(field->data)]) ;
 | |
|       #ifdef E4MISC
 | |
|          if ( nullFlags->type != r4system )
 | |
|          {
 | |
|             error4( field->data->codeBase, e4data, E83805 ) ;
 | |
|             return ;
 | |
|          }
 | |
|       #endif
 | |
|       byteNum = field->nullBit / 8 ;
 | |
|       #ifdef E4MISC
 | |
|          if ( nullFlags->len < ( byteNum + 1 ) )
 | |
|          {
 | |
|             error4( field->data->codeBase, e4data, E83805 ) ;
 | |
|             return ;
 | |
|          }
 | |
|       #endif
 | |
|       offset = ( field->nullBit - (byteNum * 8 ) ) ;
 | |
|       mask = 0x01 << offset ;
 | |
|       fPtr = f4assignPtr( nullFlags ) ;
 | |
|       fPtr[byteNum] = fPtr[byteNum] | mask ;
 | |
|    }
 | |
|    #ifdef E4PARM_HIGH
 | |
|       else
 | |
|          error4( field->data->codeBase, e4parm, E81409 ) ;
 | |
|    #endif
 | |
| }
 | |
| #endif  /* S4OFF_WRITE */
 | |
| 
 | |
| int S4FUNCTION f4null( const FIELD4 *field )
 | |
| {
 | |
|    FIELD4 *nullFlags ;
 | |
|    unsigned short int byteNum, offset ;
 | |
|    char mask ;
 | |
| 
 | |
|    #ifdef S4VBASIC
 | |
|       if ( c4parm_check( field, 3, E90540 ) )
 | |
|          return -1 ;
 | |
|    #endif
 | |
| 
 | |
|    #ifdef E4PARM_HIGH
 | |
|       if ( field == 0 )
 | |
|          return error4( 0, e4parm_null, E90540 ) ;
 | |
|    #endif
 | |
| 
 | |
|    if ( d4version( field->data ) != 0x30 )
 | |
|       return 0 ;
 | |
| 
 | |
|    if ( field->null == 1 )
 | |
|    {
 | |
|       nullFlags = &(field->data->fields[d4numFields(field->data)]) ;
 | |
|       #ifdef E4MISC
 | |
|          if ( nullFlags->type != r4system )
 | |
|             return error4( field->data->codeBase, e4data, E83805 ) ;
 | |
|       #endif
 | |
|       byteNum = field->nullBit / 8 ;
 | |
|       #ifdef E4MISC
 | |
|          if ( nullFlags->len < ( byteNum + 1 ) )
 | |
|             return error4( field->data->codeBase, e4data, E83805 ) ;
 | |
|       #endif
 | |
|       offset = ( field->nullBit - (byteNum * 8 ) ) ;
 | |
|       mask = 0x01 << offset ;
 | |
|       if ( ( f4ptr( nullFlags )[byteNum] & mask ) != 0 )
 | |
|          return 1 ;
 | |
|    }
 | |
|    return 0 ;
 | |
| }
 | |
| 
 | |
| static void time4assign( char *ptr, unsigned long inVal )
 | |
| {
 | |
|    long seconds, minutes, hours, milliSeconds, val ;
 | |
| 
 | |
|    val = inVal / 1000 ;  /* remove the thousandths's of seconds */
 | |
|    milliSeconds = inVal - ( val * 1000 ) ;
 | |
|    seconds = val % 60 ;
 | |
|    val /= 60 ;
 | |
|    minutes = val % 60 ;
 | |
|    val /= 60 ;
 | |
|    hours = val ;
 | |
| 
 | |
|    c4ltoa45( hours, ptr, -2 ) ;  /* - means fill with 0s */
 | |
|    ptr[2] = ':' ;
 | |
|    c4ltoa45( minutes, ptr+3, -2 ) ;  /* - means fill with 0s */
 | |
|    ptr[5] = ':' ;
 | |
|    c4ltoa45( seconds, ptr+6, -2 ) ;  /* - means fill with 0s */
 | |
|    if ( milliSeconds != 0 )
 | |
|    {
 | |
|       ptr[8] = ':' ;
 | |
|       c4ltoa45( milliSeconds, ptr+9, -3 ) ;  /* - means fill with 0s */
 | |
|    }
 | |
| }
 | |
| 
 | |
| /* this function uses the same memory as f4str() */
 | |
| char S4PTR *S4FUNCTION f4dateTime( const FIELD4 *field )
 | |
| {
 | |
|    CODE4 *codeBase ;
 | |
|    long val ;
 | |
|    char *fPtr ;
 | |
| 
 | |
|    #ifdef S4VBASIC
 | |
|       if ( c4parm_check( field, 3, E90543 ) )
 | |
|          return -1 ;
 | |
|    #endif
 | |
| 
 | |
|    #ifdef E4PARM_HIGH
 | |
|       if ( field == 0 )
 | |
|       {
 | |
|          error4( 0, e4parm, E90543 ) ;
 | |
|          return 0 ;
 | |
|       }
 | |
|    #endif
 | |
| 
 | |
|    codeBase = field->data->codeBase ;
 | |
| 
 | |
|    #ifdef E4PARM_HIGH
 | |
|       if ( field->type != r4dateTime )
 | |
|       {
 | |
|          error4( codeBase, e4parm, E81409 ) ;
 | |
|          return 0 ;
 | |
|       }
 | |
|    #endif
 | |
| 
 | |
|    if ( error4code( codeBase ) < 0 )
 | |
|       return 0 ;
 | |
| 
 | |
|    if ( codeBase->bufLen <= 20 )   /* not room for field length + null (incl. millisecs) */
 | |
|    {
 | |
|       if ( u4allocAgain( codeBase, &codeBase->fieldBuffer, &codeBase->bufLen, 21 ) < 0 )
 | |
|       {
 | |
|          #ifdef E4STACK
 | |
|             error4stack( codeBase, e4memory, E90542 ) ;
 | |
|          #endif
 | |
|          return 0 ;
 | |
|       }
 | |
|    }
 | |
|    memset( codeBase->fieldBuffer, ' ', 20 ) ;
 | |
|    codeBase->fieldBuffer[20] = 0 ;
 | |
| 
 | |
|    fPtr = f4ptr( field ) ;
 | |
|    val = *((long *)fPtr) ; /* date */
 | |
|    date4assign( codeBase->fieldBuffer, val ) ;
 | |
|    val = *(((long *)fPtr) + 1) ; /* time */
 | |
|    time4assign( codeBase->fieldBuffer + 8, val ) ;
 | |
|    c4trimN( codeBase->fieldBuffer, 21 ) ;
 | |
|    return codeBase->fieldBuffer ;
 | |
| }
 | |
| 
 | |
| /* input date time of format: "YYYYMMDDHH:MM:SS:MMM" */
 | |
| #ifndef S4OFF_WRITE
 | |
| void S4FUNCTION f4assignDateTime( FIELD4 *field, char *dateTime )
 | |
| {
 | |
|    long date, time ;
 | |
| 
 | |
|    if ( field->type != r4dateTime )
 | |
|    {
 | |
|       #ifdef E4PARM_HIGH
 | |
|          error4( field->data->codeBase, e4parm, E81409 ) ;
 | |
|       #endif
 | |
|       return ;
 | |
|    }
 | |
| 
 | |
|    date = date4long( dateTime ) ;
 | |
|    time = time4long( dateTime + 8, strlen( dateTime ) - 8 ) ;
 | |
| 
 | |
|    *((long *)f4assignPtr( field )) = date ;
 | |
|    *(((long *)f4assignPtr( field ))+1) = time ;
 | |
| }
 | |
| #endif /* S4OFF_WRITE */
 | |
| #endif /* S4CLIENT_OR_FOX */
 | |
| 
 | |
| #ifdef S4VBASIC
 | |
| 
 | |
| int S4FUNCTION f4len_v( FIELD4 *f4 )
 | |
| {
 | |
|    return (int)f4len( f4 );
 | |
| }
 | |
| 
 | |
| #ifdef S4VB_DOS
 | |
| 
 | |
| char * f4name_v( FIELD4 *fld )
 | |
| {
 | |
|  return v4str( f4name(fld) ) ;
 | |
| }
 | |
| 
 | |
| #endif /* S4VB_DOS */
 | |
| 
 | |
| #endif /* S4VBASIC */
 |