/* s4next.c   (c)Copyright Sequiter Software Inc., 1988-1996.  All rights reserved. */

#include "d4all.h"
#ifndef S4UNIX
   #ifdef __TURBOC__
      #pragma hdrstop
   #endif
#endif

int s4nextSpoolEntry( SORT4 *s4 )
{
   long lastDiskPos, diskDataLeft, newRec, spoolRec ;
   unsigned maxRead, lenRead ;
   int low, high, pos, rc ;
   char *newData ;
   S4SPOOL saveSpool ;

   #ifdef E4PARM_LOW
      if ( s4 == 0 )
         return error4( 0, e4parm_null, E91908 ) ;
   #endif

   s4->spoolPointer->pos += s4->totLen ;
   if ( s4->spoolPointer->pos >= s4->spoolPointer->len )
   {
      s4->spoolPointer->pos = 0 ;
      if ( s4->spoolPointer->disk >= 0L )
      {
         lastDiskPos  = (s4->spoolPointer->spoolI+1) * s4->spoolDiskLen  ;
         diskDataLeft = lastDiskPos - s4->spoolPointer->disk ;
         maxRead = s4->spoolMemLen ;
         if ( (long) s4->spoolMemLen > diskDataLeft )
            maxRead = (unsigned) diskDataLeft ;
         lenRead = file4read( &s4->file, s4->spoolPointer->disk, s4->spoolPointer->ptr, maxRead) ;

         if ( error4code( s4->codeBase ) < 0 )
         {
            sort4free( s4 ) ;
            return error4stack( s4->codeBase, (short)error4code( s4->codeBase ), E91908 ) ;
         }

         s4->spoolPointer->len = lenRead ;
         s4->spoolPointer->disk += lenRead ;
         if ( lenRead != maxRead || lenRead == 0 )
         {
            if ( lenRead % s4->totLen )
            {
               sort4free( s4 ) ;
               return error4describe( s4->codeBase, e4read, E91908, s4->file.name, 0, 0 ) ;
            }
            s4->spoolPointer->disk = -1 ;
            if ( lenRead == 0 )
            {
               s4deleteSpoolEntry( s4 ) ;
               return 0 ;
            }
            else
               s4->spoolPointer->len = lenRead ;
         }
         else  /* Check if we are out of disk entries for the spool */
            if ( s4->spoolPointer->disk >= lastDiskPos )
               s4->spoolPointer->disk = -1L ;
      }
      else
      {
         s4deleteSpoolEntry(s4) ;
         return 0 ;
      }
   }

   /* Position the new entry to the sorted location using a binary search */
   /* New entry is placed before 'result':  int pos >= 1  when complete */
   low = 1 ;
   high = s4->spoolsN ;
   newData = s4->spoolPointer->ptr + s4->spoolPointer->pos ;
   memcpy( (void *)&newRec, newData + s4->sortLen, sizeof(newRec) ) ;

   for(;;)
   {
      pos = ( low + high ) / 2 ;
      if ( pos == low && pos == high )  /* then found */
      {
         memcpy( (void *)&saveSpool, (void *)s4->spoolPointer, sizeof(S4SPOOL) ) ;
         c4memmove( s4->spoolPointer, s4->spoolPointer+1, sizeof(S4SPOOL)*(pos-1) ) ;
         memcpy( (void *)(s4->spoolPointer+pos-1), (void *)&saveSpool, sizeof(S4SPOOL) ) ;
         return 0 ;
      }
      rc = (*s4->cmp)(newData, s4->spoolPointer[pos].ptr + s4->spoolPointer[pos].pos, s4->sortLen) ;
      if ( rc == 0 )
      {
         memcpy( (void *)&spoolRec, s4->spoolPointer[pos].ptr + s4->spoolPointer[pos].pos + s4->sortLen, sizeof(spoolRec) ) ;
         if ( newRec > spoolRec )
            rc = 1 ;
      }

      if ( rc > 0 )
         low = pos+1 ;
      else
         high = pos ;
      #ifdef E4ANALYZE
         if ( high < low )
            return error4( s4->codeBase, e4result, E91908 ) ;
      #endif
   }
}