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 */
 |