433 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			433 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
/* m4memo.c   (c)Copyright Sequiter Software Inc., 1988-1996.  All rights reserved.  */
 | 
						|
 | 
						|
 | 
						|
#include "d4all.h"
 | 
						|
#ifndef S4UNIX
 | 
						|
   #ifdef __TURBOC__
 | 
						|
      #pragma hdrstop
 | 
						|
   #endif
 | 
						|
#endif
 | 
						|
 | 
						|
#ifndef S4OFF_MEMO
 | 
						|
 | 
						|
#ifdef S4CLIENT
 | 
						|
#ifndef S4OFF_WRITE
 | 
						|
int S4FUNCTION d4memoCompress( DATA4 *data )
 | 
						|
{
 | 
						|
   int rc ;
 | 
						|
   CONNECTION4 *connection ;
 | 
						|
   CODE4 *c4 ;
 | 
						|
 | 
						|
   #ifdef S4VBASIC
 | 
						|
      if ( c4parm_check( data, 2, E95201 ) )
 | 
						|
         return -1 ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   #ifdef E4PARM_HIGH
 | 
						|
      if ( data == 0 )
 | 
						|
         return error4( 0, e4parm_null, E95201 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   c4 = data->codeBase ;
 | 
						|
   if ( error4code( c4 ) < 0 )
 | 
						|
      return e4codeBase ;
 | 
						|
 | 
						|
   if ( data->readOnly == 1 )
 | 
						|
      return error4describe( c4, e4write, E80606, d4alias( data ), 0, 0 ) ;
 | 
						|
 | 
						|
   if ( data->dataFile->nFieldsMemo == 0 )
 | 
						|
      return 0 ;
 | 
						|
 | 
						|
   rc = d4update( data ) ;
 | 
						|
   if ( rc )
 | 
						|
      return rc ;
 | 
						|
 | 
						|
   connection = data->dataFile->connection ;
 | 
						|
   if ( connection == 0 )
 | 
						|
      return error4stack( c4, e4connection, E95201 ) ;
 | 
						|
 | 
						|
   data->count = -1 ;
 | 
						|
   data->dataFile->numRecs = -1 ;
 | 
						|
   connection4assign( connection, CON4MEMO_COMPRESS, data4clientId( data ), data4serverId( data ) ) ;
 | 
						|
   rc = connection4repeat( connection, -2, -1, -1, data ) ;
 | 
						|
   if ( rc < 0 )
 | 
						|
      connection4error( connection, c4, rc, E95201 ) ;
 | 
						|
 | 
						|
   return rc ;
 | 
						|
}
 | 
						|
#endif /* S4OFF_WRITE */
 | 
						|
#endif /* S4CLIENT */
 | 
						|
#endif /* S4OFF_MEMO */
 | 
						|
 | 
						|
#ifndef S4CLIENT
 | 
						|
 | 
						|
#ifndef S4OFF_MEMO
 | 
						|
#ifdef S4MFOX
 | 
						|
long memo4lenPart( MEMO4FILE *f4memo, long memoId )
 | 
						|
{
 | 
						|
   long pos ;
 | 
						|
   int rc ;
 | 
						|
   MEMO4BLOCK memoBlock ;
 | 
						|
 | 
						|
   if ( memoId <= 0L )
 | 
						|
      return 0 ;
 | 
						|
 | 
						|
   pos = memoId * f4memo->blockSize ;
 | 
						|
   rc = file4readAll( &f4memo->file, pos, &memoBlock, sizeof( MEMO4BLOCK ) ) ;
 | 
						|
   if ( rc < 0 )
 | 
						|
      return error4stack( f4memo->file.codeBase, rc, E95204 ) ;
 | 
						|
   #ifdef S4BYTE_SWAP
 | 
						|
      memoBlock.type = x4reverseLong( (void *)&memoBlock.type ) ;
 | 
						|
      memoBlock.numChars = x4reverseLong( (void *)&memoBlock.numChars ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   return x4reverseLong( (void *)&memoBlock.numChars ) ;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
#ifndef S4OFF_WRITE
 | 
						|
int S4FUNCTION d4memoCompress( DATA4 *data )
 | 
						|
{
 | 
						|
   CODE4 *c4 ;
 | 
						|
   int rc ;
 | 
						|
 | 
						|
   #ifdef S4VBASIC
 | 
						|
      if ( c4parm_check( data, 2, E95201 ) )
 | 
						|
         return -1 ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   #ifdef E4PARM_HIGH
 | 
						|
      if ( data == 0 )
 | 
						|
         return error4( 0, e4parm_null, E95201 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   c4 = data->codeBase ;
 | 
						|
   if ( error4code( c4 ) < 0 )
 | 
						|
      return e4codeBase ;
 | 
						|
 | 
						|
   if ( data->dataFile->nFieldsMemo == 0 )
 | 
						|
      return 0 ;
 | 
						|
 | 
						|
   rc = d4update( data ) ;
 | 
						|
   if ( rc )
 | 
						|
      return rc ;
 | 
						|
 | 
						|
   #ifndef S4OFF_MULTI
 | 
						|
      #ifdef S4SERVER
 | 
						|
         rc = dfile4lockFile( data->dataFile, data4clientId( data ), data4serverId( data ) ) ;
 | 
						|
      #else
 | 
						|
         rc = d4lockFile( data ) ;
 | 
						|
      #endif
 | 
						|
      if ( rc )
 | 
						|
         return rc ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   #ifndef S4OFF_TRAN
 | 
						|
      if ( code4transEnabled( c4 ) )
 | 
						|
         if ( tran4active( c4, data ) != 0 )
 | 
						|
            return error4( c4, e4transViolation, E81502 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   return dfile4memoCompress( data->dataFile, data ) ;
 | 
						|
}
 | 
						|
 | 
						|
int dfile4memoCompress( DATA4FILE *data, DATA4 *d4 )
 | 
						|
{
 | 
						|
   char *rdBuf, *wrBuf, *ptr ;
 | 
						|
   FILE4SEQ_READ rd ;
 | 
						|
   FILE4SEQ_WRITE wr ;
 | 
						|
   MEMO4FILE newFile ;
 | 
						|
   CODE4 *c4 ;
 | 
						|
   unsigned int bufSize, ptrLen, ptrMax, saveFlag ;
 | 
						|
   long curCount, iRec, newId ;
 | 
						|
   int  rc, i ;
 | 
						|
   FIELD4 *field ;
 | 
						|
   #ifdef S4MFOX
 | 
						|
      long memoLen, memoType ;
 | 
						|
      unsigned long pos ;
 | 
						|
 | 
						|
      memoType = 1 ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   #ifdef S4VBASIC
 | 
						|
      if ( c4parm_check( d4, 2, E95201 ) )
 | 
						|
         return -1 ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   #ifdef E4PARM_HIGH
 | 
						|
      if ( data == 0 )
 | 
						|
         return error4( 0, e4parm_null, E95201 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   c4 = data->c4 ;
 | 
						|
   if ( error4code( c4 ) < 0 )
 | 
						|
      return e4codeBase ;
 | 
						|
 | 
						|
   if ( data->memoFile.file.hand == -1 )
 | 
						|
      return 0 ;
 | 
						|
 | 
						|
   #ifndef S4OFF_MULTI
 | 
						|
      #ifndef N4OTHER
 | 
						|
         #ifdef S4SERVER
 | 
						|
            rc = dfile4lockMemo( data ) ;
 | 
						|
         #else
 | 
						|
            rc = dfile4lockMemo( data ) ;
 | 
						|
         #endif
 | 
						|
         if ( rc )
 | 
						|
            return rc ;
 | 
						|
      #endif
 | 
						|
   #endif
 | 
						|
 | 
						|
   saveFlag = c4->memSizeMemo ;
 | 
						|
   c4->memSizeMemo = (unsigned int)data->memoFile.blockSize ;
 | 
						|
 | 
						|
   rc = memo4fileCreate( &newFile, c4, data, 0 ) ;
 | 
						|
   if ( rc < 0 )
 | 
						|
      return error4stack( c4, rc, E91102 ) ;
 | 
						|
 | 
						|
   c4->memSizeMemo = saveFlag ;
 | 
						|
   newFile.blockSize = data->memoFile.blockSize ;
 | 
						|
 | 
						|
   rdBuf = wrBuf = 0 ;
 | 
						|
   bufSize = c4->memSizeBuffer ;
 | 
						|
 | 
						|
   for (; bufSize > data->recWidth; bufSize -= 0x800 )
 | 
						|
   {
 | 
						|
      rdBuf = (char *)u4allocFree( c4, (long)bufSize ) ;
 | 
						|
      if ( rdBuf == 0 )
 | 
						|
         continue ;
 | 
						|
 | 
						|
      wrBuf = (char *)u4allocFree( c4, (long)bufSize ) ;
 | 
						|
      if ( wrBuf )
 | 
						|
         break ;
 | 
						|
 | 
						|
      u4free( rdBuf ) ;
 | 
						|
      rdBuf = 0 ;
 | 
						|
   }
 | 
						|
 | 
						|
   #ifdef S4ADVANCE_READ
 | 
						|
      file4seqReadInitDo( &rd, &data->file, dfile4recordPosition( data, 1L ), rdBuf, bufSize, 1 ) ;
 | 
						|
   #else
 | 
						|
      file4seqReadInit( &rd, &data->file, dfile4recordPosition( data, 1L ), rdBuf, bufSize ) ;
 | 
						|
   #endif
 | 
						|
   file4seqWriteInit( &wr, &data->file, dfile4recordPosition( data, 1L ), wrBuf, bufSize ) ;
 | 
						|
 | 
						|
   curCount = dfile4recCount( data, data4serverId( d4 )  ) ;
 | 
						|
 | 
						|
   ptr = 0 ;
 | 
						|
   ptrLen = ptrMax = 0 ;
 | 
						|
 | 
						|
   for ( iRec= 1L ; iRec <= curCount && rc == 0 ; iRec++ )
 | 
						|
   {
 | 
						|
      if ( file4seqReadAll( &rd, d4->record, data->recWidth ) < 0 )
 | 
						|
         break ;
 | 
						|
 | 
						|
      for ( i = 0 ; i < d4->dataFile->nFieldsMemo ; i++ )
 | 
						|
      {
 | 
						|
         field = d4->fieldsMemo[i].field ;
 | 
						|
 | 
						|
         #ifdef S4FOX
 | 
						|
            pos = 0L ;
 | 
						|
 | 
						|
            if ( f4null( field ) == 1 )
 | 
						|
               memoLen = 0 ;
 | 
						|
            else
 | 
						|
               memoLen = memo4lenPart( &data->memoFile, f4long( field ) ) ;
 | 
						|
 | 
						|
 | 
						|
            if ( memoLen > 0L )
 | 
						|
            {
 | 
						|
               newId = 0L ;
 | 
						|
               do
 | 
						|
               {
 | 
						|
                  #ifdef E4ANALYZE
 | 
						|
                     if ( pos > (unsigned long)memoLen )
 | 
						|
                     {
 | 
						|
                        rc = error4( c4, e4memoCorrupt, E91102 ) ;
 | 
						|
                        break ;
 | 
						|
                     }
 | 
						|
                  #endif
 | 
						|
 | 
						|
                  ptrLen = ptrMax ;
 | 
						|
 | 
						|
                  if ( memo4fileReadPart( &data->memoFile, f4long( field ), &ptr, &ptrLen, pos, UINT_MAX - 100, &memoType ) < 0 )
 | 
						|
                  {
 | 
						|
                     rc = -1 ;
 | 
						|
                     break ;
 | 
						|
                  }
 | 
						|
 | 
						|
                  if ( ptrLen > ptrMax )
 | 
						|
                     ptrMax = ptrLen ;
 | 
						|
 | 
						|
                  if ( memo4fileWritePart( &newFile, &newId, ptr, memoLen, pos, ptrLen, memoType ) < 0 )
 | 
						|
                  {
 | 
						|
                     rc = -1 ;
 | 
						|
                     break ;
 | 
						|
                  }
 | 
						|
                  pos += ptrLen ;
 | 
						|
               } while( pos != (unsigned long)memoLen ) ;
 | 
						|
               c4ltoa45( newId, f4ptr(field), -( (int)field->len ) ) ;
 | 
						|
            }
 | 
						|
            else
 | 
						|
               c4ltoa45( 0L, f4ptr(field), -( (int)field->len) ) ;
 | 
						|
         #else
 | 
						|
            ptrLen = ptrMax ;
 | 
						|
            if ( memo4fileRead( &data->memoFile, f4long(field), &ptr, &ptrLen ) < 0 )
 | 
						|
            {
 | 
						|
               rc = -1 ;
 | 
						|
               break ;
 | 
						|
            }
 | 
						|
 | 
						|
            if ( ptrLen > ptrMax )
 | 
						|
               ptrMax = ptrLen ;
 | 
						|
 | 
						|
            newId = 0L ;
 | 
						|
            if ( memo4fileWrite( &newFile, &newId, ptr, ptrLen ) < 0 )
 | 
						|
            {
 | 
						|
               rc = -1 ;
 | 
						|
               break ;
 | 
						|
            }
 | 
						|
 | 
						|
            c4ltoa45( newId, f4ptr(field), - ((int) field->len) ) ;
 | 
						|
         #endif
 | 
						|
      }
 | 
						|
      file4seqWrite( &wr, d4->record, data->recWidth ) ;
 | 
						|
   }
 | 
						|
 | 
						|
   if ( rc < 0 )
 | 
						|
      file4close( &newFile.file ) ;  /* error occurred */
 | 
						|
   else
 | 
						|
      file4seqWriteFlush(&wr) ;
 | 
						|
 | 
						|
   #ifdef S4ADVANCE_READ
 | 
						|
      file4seqReadInitUndo( &rd ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   u4free( ptr ) ;
 | 
						|
   u4free( rdBuf ) ;
 | 
						|
   u4free( wrBuf ) ;
 | 
						|
 | 
						|
   if ( rc == 0 )
 | 
						|
   {
 | 
						|
      rc = file4replace( &data->memoFile.file, &newFile.file ) ;
 | 
						|
      if ( rc == 0 )
 | 
						|
         #ifdef S4MMDX
 | 
						|
            if ( file4len( &data->memoFile.file ) < data->memoFile.blockSize )
 | 
						|
               rc = file4lenSet( &data->memoFile.file, data->memoFile.blockSize ) ;
 | 
						|
         #else
 | 
						|
            if ( file4len( &data->memoFile.file ) < 512 )
 | 
						|
               rc = file4lenSet( &data->memoFile.file, 512L ) ;
 | 
						|
         #endif
 | 
						|
   }
 | 
						|
 | 
						|
   return rc ;
 | 
						|
}
 | 
						|
#endif /* S4OFF_WRITE */
 | 
						|
 | 
						|
#ifndef S4MFOX
 | 
						|
#ifndef S4MNDX
 | 
						|
 | 
						|
int memo4fileChainFlush( MEMO4FILE *f4memo, MEMO4CHAIN_ENTRY *chain )
 | 
						|
{
 | 
						|
   #ifdef S4BYTE_SWAP
 | 
						|
      MEMO4CHAIN_ENTRY swap ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   if ( chain->toDisk )
 | 
						|
   {
 | 
						|
      chain->toDisk = 0 ;
 | 
						|
      #ifdef S4BYTE_SWAP
 | 
						|
         memcpy( (void *)&swap, (void *)chain, sizeof( MEMO4CHAIN_ENTRY ) ) ;
 | 
						|
         swap.next = x4reverseLong( (void *)&swap.next ) ;
 | 
						|
         swap.num = x4reverseLong( (void *)&swap.num ) ;
 | 
						|
 | 
						|
         return file4write( &f4memo->file, chain->blockNo * f4memo->blockSize, &swap, 2*sizeof(S4LONG) ) ;
 | 
						|
      #else
 | 
						|
         return file4write( &f4memo->file, chain->blockNo * f4memo->blockSize, chain, 2*sizeof(S4LONG) ) ;
 | 
						|
      #endif
 | 
						|
   }
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
int memo4fileChainSkip( MEMO4FILE *f4memo, MEMO4CHAIN_ENTRY *chain )
 | 
						|
{
 | 
						|
   unsigned lenRead ;
 | 
						|
 | 
						|
   chain->toDisk = 0 ;
 | 
						|
   chain->blockNo = chain->next ;
 | 
						|
 | 
						|
   if ( chain->next < 0 )
 | 
						|
      lenRead = 0 ;
 | 
						|
   else
 | 
						|
   {
 | 
						|
      lenRead = file4read( &f4memo->file, chain->next * f4memo->blockSize, chain, sizeof(chain->next)+sizeof(chain->num) ) ;
 | 
						|
      #ifdef S4BYTE_SWAP
 | 
						|
         chain->next = x4reverseLong( (void *)&chain->next ) ;
 | 
						|
         chain->num = x4reverseLong( (void *)&chain->num ) ;
 | 
						|
      #endif
 | 
						|
   }
 | 
						|
   if ( f4memo->data->c4->errorCode < 0 )
 | 
						|
      return -1 ;
 | 
						|
   if ( lenRead == 0 )
 | 
						|
   {
 | 
						|
      chain->num = -1 ;
 | 
						|
      chain->next = -1 ;
 | 
						|
      return 0 ;
 | 
						|
   }
 | 
						|
   if ( lenRead != sizeof(chain->next)+sizeof(chain->num) )
 | 
						|
      return file4readError( &f4memo->file, chain->next * f4memo->blockSize, sizeof(chain->next)+sizeof(chain->num), "memo4fileChainSkip" ) ;
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
 | 
						|
#endif  /* S4OFF_MEMO */
 | 
						|
 | 
						|
/* Make the memo file entries current */
 | 
						|
#ifndef S4OFF_MEMO
 | 
						|
#ifndef S4OFF_MULTI
 | 
						|
int d4validateMemoIds( DATA4 *data )
 | 
						|
{
 | 
						|
   int i, rc ;
 | 
						|
   char *fromPtr ;
 | 
						|
 | 
						|
   #ifdef E4PARM_HIGH
 | 
						|
      if ( data == 0 )
 | 
						|
         return error4( 0, e4parm_null, E95203 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   if ( data->memoValidated )
 | 
						|
      return 0 ;
 | 
						|
 | 
						|
   if ( data->recNum > 0 )
 | 
						|
   {
 | 
						|
      #ifdef S4SERVER
 | 
						|
         rc = dfile4lock( data->dataFile, data4clientId( data ), data4serverId( data ), data->recNum ) ;
 | 
						|
      #else
 | 
						|
         rc = d4lock( data, data->recNum ) ;
 | 
						|
      #endif
 | 
						|
      if ( rc )
 | 
						|
         return rc ;
 | 
						|
   }
 | 
						|
 | 
						|
   rc = d4readOld( data, data->recNum ) ;
 | 
						|
   if ( rc < 0 )
 | 
						|
      return error4stack( data->codeBase, rc, E95203 ) ;
 | 
						|
 | 
						|
   if ( data->recordChanged == 0 )   /* if the record has changed, leave intact */
 | 
						|
      for ( i = 0 ; i < data->dataFile->nFieldsMemo ; i++ )
 | 
						|
      {
 | 
						|
         if ( data->fieldsMemo[i].isChanged == 0 )
 | 
						|
         {
 | 
						|
            fromPtr = data->recordOld + data->fieldsMemo[i].field->offset ;
 | 
						|
            memcpy( f4ptr( data->fieldsMemo[i].field ), fromPtr, f4len( data->fieldsMemo[i].field ) ) ;  /* need f4len() because S4FOX 3.0 has 4 byte memos, not 10 byte */
 | 
						|
         }
 | 
						|
      }
 | 
						|
 | 
						|
   data->memoValidated = 1 ;
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
#endif  /* S4OFF_MULTI */
 | 
						|
#endif  /* S4OFF_MEMO */
 | 
						|
#endif  /* S4CLIENT */
 |