1997-06-16 13:01:08 +00:00
|
|
|
/* d4skip.c (c)Copyright Sequiter Software Inc., 1988-1996. All rights reserved. */
|
|
|
|
|
|
|
|
#include "d4all.h"
|
|
|
|
#ifndef S4UNIX
|
|
|
|
#ifdef __TURBOC__
|
|
|
|
#pragma hdrstop
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef S4SERVER
|
|
|
|
/* -2 means eof, -3 means bof */
|
|
|
|
long d4skipRecno( DATA4 *data, long n )
|
|
|
|
{
|
|
|
|
#ifndef S4OFF_INDEX
|
|
|
|
TAG4 *tag ;
|
|
|
|
TAG4FILE *tagFile ;
|
|
|
|
#endif
|
|
|
|
long startRec, newRec ;
|
|
|
|
#ifndef S4OFF_INDEX
|
|
|
|
unsigned char *keyValue ;
|
|
|
|
int rc ;
|
|
|
|
long recno, nSkipped ;
|
|
|
|
#endif
|
|
|
|
CODE4 *c4 ;
|
|
|
|
|
|
|
|
#ifdef S4VBASIC
|
|
|
|
if ( c4parm_check( data, 2, E94801 ) )
|
|
|
|
return -1 ;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef E4PARM_LOW
|
|
|
|
if ( data == 0 )
|
|
|
|
return error4( 0, e4parm_null, E94801 ) ;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
c4 = data->codeBase ;
|
|
|
|
if ( c4 == 0 )
|
|
|
|
return e4info ;
|
|
|
|
if ( error4code( c4 ) < 0 )
|
|
|
|
return error4code( c4 ) ;
|
|
|
|
|
|
|
|
if ( data->recNum < 1L )
|
|
|
|
{
|
|
|
|
#ifndef S4SERVER
|
|
|
|
if ( c4->errSkip )
|
|
|
|
return error4( c4, e4info, E84801 ) ;
|
|
|
|
#endif
|
|
|
|
return e4info ;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef S4OFF_INDEX
|
|
|
|
tag = data->tagSelected ; /* avoid function call */
|
|
|
|
if ( tag == 0 )
|
|
|
|
{
|
|
|
|
#endif
|
|
|
|
if ( n != 0L )
|
|
|
|
if ( d4recCountLessEq( data, 1L ) == 0 ) /* count == 0 */
|
|
|
|
return -4L ;
|
|
|
|
|
|
|
|
data->bofFlag = 0 ;
|
|
|
|
startRec = data->recNum ;
|
|
|
|
newRec = startRec + n ;
|
|
|
|
|
|
|
|
if ( newRec > 0L )
|
|
|
|
{
|
|
|
|
if ( d4recCountLessEq( data, newRec ) == 0 )
|
|
|
|
return -2L ;
|
|
|
|
return newRec ;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return -3L ;
|
|
|
|
#ifndef S4OFF_INDEX
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tagFile = tag->tagFile ;
|
|
|
|
if ( data->eofFlag )
|
|
|
|
{
|
|
|
|
if ( n >= 0L )
|
|
|
|
return -2L ;
|
|
|
|
|
|
|
|
rc = d4bottom( data ) ;
|
|
|
|
if ( rc && rc != r4eof )
|
|
|
|
return rc ;
|
|
|
|
if ( rc == r4eof )
|
|
|
|
return -2L ;
|
|
|
|
n++ ;
|
|
|
|
data->recNum = tfile4recNo( tagFile ) ;
|
|
|
|
}
|
|
|
|
|
|
|
|
data->bofFlag = 0 ;
|
|
|
|
|
|
|
|
#ifndef S4OFF_WRITE
|
|
|
|
if ( data->recordChanged )
|
|
|
|
{
|
1997-06-16 13:10:44 +00:00
|
|
|
rc = d4updateRecord( data, 0 ) ; /* was 1 */
|
1997-06-16 13:01:08 +00:00
|
|
|
if ( rc < 0 )
|
|
|
|
return rc ;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
t4versionCheck( tag, 1, 0 ) ;
|
|
|
|
|
|
|
|
if ( n == 0 )
|
|
|
|
return data->recNum ;
|
|
|
|
|
|
|
|
if ( tfile4recNo( tagFile ) != data->recNum )
|
|
|
|
{
|
|
|
|
if ( d4lockTest( data, data->recNum ) == 0 ) /* ensure latest from disk */
|
|
|
|
{
|
|
|
|
rc = d4go( data, data->recNum ) ;
|
|
|
|
if ( rc < 0 )
|
|
|
|
return rc ;
|
|
|
|
}
|
|
|
|
|
|
|
|
expr4context( tagFile->expr, data ) ;
|
|
|
|
tfile4exprKey( tagFile, &keyValue ) ;
|
|
|
|
|
|
|
|
rc = tfile4go( tagFile, keyValue, data->recNum, 0 ) ;
|
|
|
|
if ( rc < 0 )
|
|
|
|
return rc ;
|
|
|
|
|
|
|
|
if ( tfile4empty( tagFile ) )
|
|
|
|
return -4L ;
|
|
|
|
|
|
|
|
if ( tfile4eof( tagFile ) && n >= 0L )
|
|
|
|
return -2L ;
|
|
|
|
|
|
|
|
#ifdef S4HAS_DESCENDING
|
|
|
|
if ( tagFile->header.descending )
|
|
|
|
{
|
|
|
|
if ( (rc > 0) && (n < 0) )
|
|
|
|
n-- ;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if ( (rc > 0) && (n > 0) )
|
|
|
|
n-- ;
|
|
|
|
#else
|
|
|
|
if ( (rc > 0) && (n > 0) )
|
|
|
|
n-- ;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( tfile4eof( tagFile ) )
|
|
|
|
return -2L ;
|
|
|
|
}
|
|
|
|
|
|
|
|
nSkipped = tfile4dskip( tagFile, n ) ;
|
|
|
|
|
|
|
|
if ( n > 0 && nSkipped != n )
|
|
|
|
return -2L ;
|
|
|
|
if ( n < 0 && nSkipped != n )
|
|
|
|
return -3L ;
|
|
|
|
|
|
|
|
if ( tfile4eof( tagFile ) )
|
|
|
|
return -2L ;
|
|
|
|
|
|
|
|
recno = tfile4recNo( tagFile ) ;
|
|
|
|
if ( recno < 0 )
|
|
|
|
return recno ;
|
|
|
|
return recno ;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif /* S4SERVER */
|
|
|
|
|
|
|
|
/* flush the current record to disk, and update the data pointer to point
|
|
|
|
to a valid tag location (in case the current record has been filtered out */
|
|
|
|
/* direction is -1 if line up backwards, or 1 if line up forwards */
|
|
|
|
#ifdef P4ARGS_USED
|
|
|
|
#pragma argsused
|
|
|
|
#endif
|
|
|
|
int S4FUNCTION d4tagSync( DATA4 *data, TAG4 * const tag )
|
|
|
|
{
|
|
|
|
#ifdef S4OFF_INDEX
|
|
|
|
return 0 ;
|
|
|
|
#else
|
|
|
|
CODE4 *c4 ;
|
|
|
|
#ifdef S4CLIENT
|
|
|
|
int rc, saveRc ;
|
|
|
|
CONNECTION4 *connection ;
|
|
|
|
CONNECTION4TAG_SYNCH_INFO_IN info ;
|
|
|
|
CONNECTION4TAG_SYNCH_INFO_OUT *out ;
|
|
|
|
#ifndef S4OFF_MEMO
|
|
|
|
int i ;
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef S4VBASIC
|
|
|
|
if ( c4parm_check( data, 2, E94803 ) )
|
|
|
|
return -1 ;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef E4PARM_HIGH
|
|
|
|
if ( data == 0 )
|
|
|
|
return error4( 0, e4parm_null, E94803 ) ;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if ( tag == 0 )
|
|
|
|
return 0 ;
|
|
|
|
|
|
|
|
c4 = data->codeBase ;
|
|
|
|
if ( error4code( c4 ) < 0 )
|
|
|
|
return error4code( c4 ) ;
|
|
|
|
|
|
|
|
#ifdef S4CLIENT
|
|
|
|
if ( data->recNum <= 0 || d4eof( data ) )
|
|
|
|
{
|
|
|
|
#ifndef S4OFF_MEMO
|
|
|
|
for ( i = 0; i < data->dataFile->nFieldsMemo; i++ )
|
|
|
|
f4memoReset( data->fieldsMemo[i].field ) ;
|
|
|
|
#endif
|
|
|
|
data->recordChanged = 0 ;
|
|
|
|
return 0 ;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( data->recordChanged == 0 )
|
|
|
|
return 0 ;
|
|
|
|
|
|
|
|
connection = data->dataFile->connection ;
|
|
|
|
if ( connection == 0 )
|
|
|
|
return error4stack( data->codeBase, e4connection, E94803 ) ;
|
|
|
|
|
|
|
|
connection4assign( connection, CON4TAG_SYNCH, data4clientId( data ), data4serverId( data ) ) ;
|
|
|
|
memcpy( info.tagName, tag->tagFile->alias, LEN4TAG_ALIAS ) ;
|
|
|
|
info.tagName[LEN4TAG_ALIAS] = 0 ;
|
|
|
|
info.recno = d4recNo( data ) ;
|
|
|
|
connection4addData( connection, &info, sizeof( CONNECTION4TAG_SYNCH_INFO_IN ), 0 ) ;
|
|
|
|
saveRc = connection4repeat( connection, -2, -1, -1, data ) ;
|
|
|
|
|
|
|
|
if ( saveRc == r4eof || saveRc == r4noRecords )
|
|
|
|
{
|
|
|
|
data->bofFlag = 0 ;
|
|
|
|
rc = d4goEof( data ) ;
|
|
|
|
if ( rc == 0 )
|
|
|
|
rc = r4eof ;
|
|
|
|
if ( saveRc == r4noRecords )
|
|
|
|
data->bofFlag = 1 ;
|
|
|
|
return rc ;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( saveRc == r4bof )
|
|
|
|
{
|
|
|
|
data->eofFlag = 0 ;
|
|
|
|
rc = d4goBof( data ) ;
|
|
|
|
data->bofFlag = 1 ;
|
|
|
|
if ( rc == 0 )
|
|
|
|
rc = r4bof ;
|
|
|
|
return rc ;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( saveRc != 0 )
|
|
|
|
{
|
|
|
|
if ( saveRc < 0 )
|
|
|
|
return connection4errorDescribe( connection, c4, saveRc, E94803, tag->tagFile->alias, 0, 0 ) ;
|
|
|
|
return saveRc ;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( connection4len( connection ) != sizeof( CONNECTION4TAG_SYNCH_INFO_OUT ) )
|
|
|
|
return error4( c4, e4packetLen, E94803 ) ;
|
|
|
|
out = (CONNECTION4TAG_SYNCH_INFO_OUT *)connection4data( connection ) ;
|
|
|
|
|
|
|
|
if ( out->recNo != 0 && out->recNo != d4recNo( data ) )
|
|
|
|
{
|
|
|
|
rc = d4go( data, out->recNo ) ;
|
|
|
|
if ( rc < 0 )
|
|
|
|
return rc ;
|
|
|
|
}
|
|
|
|
|
|
|
|
return saveRc ;
|
|
|
|
#else
|
|
|
|
return d4tagSyncDo( data, tag, 1 ) ;
|
|
|
|
#endif
|
|
|
|
#endif /* S4OFF_INDEX */
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef S4OFF_INDEX
|
|
|
|
#ifndef S4CLIENT
|
|
|
|
int d4tagSyncDo( DATA4 *data, TAG4 * const tag, int direction )
|
|
|
|
{
|
|
|
|
int rc ;
|
|
|
|
CODE4 *c4 ;
|
|
|
|
unsigned char *keyValue ;
|
|
|
|
#ifndef S4OFF_MULTI
|
|
|
|
int done, verifyReccount ;
|
|
|
|
#ifndef S4OFF_TRAN
|
|
|
|
int nSkipped ;
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
TAG4 *oldSelected ;
|
|
|
|
TAG4FILE *tagFile ;
|
|
|
|
long recno ;
|
|
|
|
|
|
|
|
c4 = data->codeBase ;
|
|
|
|
|
|
|
|
tagFile = tag->tagFile ;
|
|
|
|
expr4context( tagFile->expr, data ) ;
|
|
|
|
tfile4exprKey( tagFile, &keyValue ) ;
|
|
|
|
recno = tfile4recNo( tagFile ) ;
|
|
|
|
if ( recno != data->recNum )
|
|
|
|
{
|
|
|
|
rc = tfile4go( tagFile, keyValue, data->recNum, 0 ) ;
|
|
|
|
if ( rc )
|
|
|
|
return rc ;
|
|
|
|
}
|
|
|
|
|
|
|
|
oldSelected = data->tagSelected ;
|
|
|
|
d4tagSelect( data, tag ) ;
|
|
|
|
|
|
|
|
#ifndef S4OFF_WRITE
|
|
|
|
if ( data->recordChanged )
|
|
|
|
{
|
|
|
|
rc = d4updateRecord( data, 0 ) ;
|
|
|
|
if ( rc )
|
|
|
|
{
|
|
|
|
d4tagSelect( data, oldSelected ) ;
|
|
|
|
return rc ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if ( data->eofFlag )
|
|
|
|
{
|
|
|
|
d4tagSelect( data, oldSelected ) ;
|
|
|
|
|
|
|
|
/* if forward skip not true, not eof, here is */
|
|
|
|
return d4goEof( data ) ;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
t4versionCheck( tag, 1, 0 ) ;
|
|
|
|
|
|
|
|
if ( tfile4eof( tagFile ) )
|
|
|
|
return d4goEof( data ) ;
|
|
|
|
|
|
|
|
recno = tfile4recNo( tagFile ) ;
|
|
|
|
if ( recno != data->recNum )
|
|
|
|
rc = d4go( data, recno ) ;
|
|
|
|
else
|
|
|
|
rc = 0 ;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef S4OFF_MULTI
|
|
|
|
for( verifyReccount = 1, done = 0 ; done == 0 ; )
|
|
|
|
{
|
|
|
|
#ifndef S4OFF_TRAN
|
|
|
|
if ( code4transEnabled( c4 ) )
|
|
|
|
if ( t4unique( tag ) != 0 )
|
|
|
|
if ( code4tranStatus( c4 ) == r4active )
|
|
|
|
if ( d4lockTest( data, recno ) )
|
|
|
|
{
|
|
|
|
/* if within a transaction, and record is locked, it may mean
|
|
|
|
that the record contents have changed. If the current tag key
|
|
|
|
does not match, it must be an old entry (if a unique tag),
|
|
|
|
and thus skip over
|
|
|
|
*/
|
|
|
|
for ( ;; )
|
|
|
|
{
|
|
|
|
if ( recno > data->dataFile->minCount ) /* ensure correct sequencing for multi-user */
|
|
|
|
break ; /* just let the code below take care of this case */
|
|
|
|
verifyReccount = 1 ;
|
|
|
|
expr4context( tagFile->expr, data ) ;
|
|
|
|
if ( recno != d4recNo( data ) ) /* need to reposition data4 first */
|
|
|
|
d4go( data, recno ) ;
|
|
|
|
tfile4exprKey( tagFile, &keyValue ) ;
|
|
|
|
if ( memcmp( tfile4key( tagFile ), keyValue, tagFile->header.keyLen ) != 0 ) /* different, so skip */
|
|
|
|
nSkipped = (int)tfile4skip( tagFile, direction ) ;
|
|
|
|
else /* done */
|
|
|
|
break ;
|
|
|
|
|
|
|
|
if ( direction > 0 && nSkipped != 1 )
|
|
|
|
{
|
|
|
|
rc = d4goEof( data ) ;
|
|
|
|
done = 1 ;
|
|
|
|
break ;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( tfile4eof( tagFile ) )
|
|
|
|
{
|
|
|
|
data->bofFlag = 1 ;
|
|
|
|
rc = d4goEof( data ) ;
|
|
|
|
done = 1 ;
|
|
|
|
break ;
|
|
|
|
}
|
|
|
|
if ( tfile4recNo( tagFile ) != recno ) /* ok, may continue */
|
|
|
|
{
|
|
|
|
recno = tfile4recNo( tagFile ) ;
|
|
|
|
d4go( data, recno ) ;
|
|
|
|
break ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* S4OFF_TRAN */
|
|
|
|
|
|
|
|
if ( done == 1 )
|
|
|
|
break ;
|
|
|
|
|
|
|
|
if ( verifyReccount == 1 )
|
|
|
|
{
|
|
|
|
verifyReccount = 0 ;
|
|
|
|
if ( recno > data->dataFile->minCount ) /* ensure correct sequencing for multi-user */
|
|
|
|
{
|
|
|
|
if ( d4recCountLessEq( data, recno ) == 0 )
|
|
|
|
{
|
|
|
|
rc = (int)tfile4skip( tagFile, direction ) ;
|
|
|
|
if ( rc < 0 )
|
|
|
|
done = 1 ;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( rc == 0 )
|
|
|
|
{
|
|
|
|
data->bofFlag = 1 ;
|
|
|
|
done = 1 ;
|
|
|
|
rc = d4goEof( data ) ;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
recno = tfile4recNo( tagFile ) ;
|
|
|
|
if ( recno <= 0 || recno > data->dataFile->minCount )
|
|
|
|
{
|
|
|
|
done = 1 ;
|
|
|
|
rc = -1 ;
|
|
|
|
}
|
|
|
|
if ( tfile4recNo( tagFile ) != recno ) /* ok, may continue */
|
|
|
|
{
|
|
|
|
recno = tfile4recNo( tagFile ) ;
|
|
|
|
d4go( data, recno ) ;
|
|
|
|
break ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
done = 1 ;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
done = 1 ;
|
|
|
|
}
|
|
|
|
#endif /* S4OFF_MULTI */
|
|
|
|
|
|
|
|
d4tagSelect( data, oldSelected ) ;
|
|
|
|
return rc ;
|
|
|
|
}
|
|
|
|
#endif /* S4CLIENT */
|
|
|
|
#endif /* S4OFF_INDEX */
|
|
|
|
|
|
|
|
int S4FUNCTION d4skip( DATA4 *data, const long nSkip )
|
|
|
|
{
|
|
|
|
int rc ;
|
|
|
|
CODE4 *c4 ;
|
|
|
|
#ifdef S4CLIENT
|
|
|
|
int saveRc ;
|
|
|
|
CONNECTION4 *connection ;
|
|
|
|
CONNECTION4GO_INFO_OUT *out ;
|
|
|
|
CONNECTION4SKIP_INFO_IN info ;
|
|
|
|
#else
|
|
|
|
#ifndef S4OFF_INDEX
|
|
|
|
unsigned char *keyValue ;
|
|
|
|
long nSkipped, recno ;
|
|
|
|
TAG4FILE *tagFile ;
|
|
|
|
#endif
|
|
|
|
long n ;
|
|
|
|
#ifndef S4SERVER
|
|
|
|
int saveFlag ;
|
|
|
|
#endif
|
|
|
|
long startRec, newRec ;
|
|
|
|
int oldEofFlag, c1 ;
|
|
|
|
#endif
|
|
|
|
#ifndef S4OFF_INDEX
|
|
|
|
TAG4 *tag ;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef S4VBASIC
|
|
|
|
if ( c4parm_check( data, 2, E94802 ) )
|
|
|
|
return -1 ;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef E4PARM_HIGH
|
|
|
|
if ( data == 0 )
|
|
|
|
return error4( 0, e4parm_null, E94802 ) ;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
c4 = data->codeBase ;
|
|
|
|
if ( error4code( c4 ) < 0 )
|
|
|
|
return error4code( c4 ) ;
|
|
|
|
|
|
|
|
if ( data->recNum < 1L )
|
|
|
|
{
|
|
|
|
#ifndef S4SERVER
|
|
|
|
if ( c4->errSkip )
|
|
|
|
error4( c4, e4info, E84801 ) ;
|
|
|
|
#endif
|
|
|
|
return e4info ;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef S4CLIENT
|
|
|
|
rc = d4updateRecord( data, 0 ) ; /* returns -1 if error4code( codeBase ) < 0 */
|
|
|
|
if ( rc )
|
|
|
|
return rc ;
|
|
|
|
|
|
|
|
connection = data->dataFile->connection ;
|
|
|
|
if ( connection == 0 )
|
|
|
|
return error4stack( data->codeBase, e4connection, E94802 ) ;
|
|
|
|
|
|
|
|
connection4assign( connection, CON4SKIP, data4clientId( data ), data4serverId( data ) ) ;
|
|
|
|
info.startPos = data->recNum ;
|
|
|
|
info.numSkip = nSkip ;
|
|
|
|
#ifdef S4OFF_INDEX
|
|
|
|
info.usesTag = 0 ;
|
|
|
|
#else
|
|
|
|
tag = data->tagSelected ;
|
|
|
|
if ( tag == 0 )
|
|
|
|
info.usesTag = 0 ;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
info.usesTag = 1 ;
|
|
|
|
memcpy( info.tagName, tag->tagFile->alias, LEN4TAG_ALIAS ) ;
|
|
|
|
info.tagName[LEN4TAG_ALIAS] = 0 ;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
connection4addData( connection, &info, sizeof( CONNECTION4SKIP_INFO_IN ), 0 ) ;
|
|
|
|
rc = connection4repeat( connection, -2, -1, -1, data ) ;
|
|
|
|
if ( rc == r4locked )
|
|
|
|
return r4locked ;
|
|
|
|
|
|
|
|
if ( (long)connection4len( connection ) < (long)sizeof( CONNECTION4GO_INFO_OUT ) )
|
|
|
|
return error4( c4, e4packetLen, E94802 ) ;
|
|
|
|
out = (CONNECTION4GO_INFO_OUT *)connection4data( connection ) ;
|
|
|
|
|
|
|
|
saveRc = out->skipRc ;
|
|
|
|
if ( saveRc < 0 )
|
|
|
|
{
|
|
|
|
if ( tag == 0 )
|
|
|
|
return connection4error( connection, c4, saveRc, E94802 ) ;
|
|
|
|
else
|
|
|
|
return connection4errorDescribe( connection, c4, saveRc, E94802, tag->tagFile->alias, 0, 0 ) ;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( saveRc == r4eof || saveRc == r4noRecords )
|
|
|
|
{
|
|
|
|
data->bofFlag = 0 ;
|
|
|
|
rc = d4goEof( data ) ;
|
|
|
|
if ( rc == 0 )
|
|
|
|
rc = r4eof ;
|
|
|
|
if ( saveRc == r4noRecords )
|
|
|
|
data->bofFlag = 1 ;
|
|
|
|
return rc ;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( saveRc == r4bof )
|
|
|
|
{
|
|
|
|
data->eofFlag = 0 ;
|
|
|
|
rc = d4goBof( data ) ;
|
|
|
|
data->bofFlag = 1 ;
|
|
|
|
if ( rc == 0 )
|
|
|
|
rc = r4bof ;
|
|
|
|
return rc ;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( saveRc != 0 )
|
|
|
|
{
|
|
|
|
if ( saveRc < 0 )
|
|
|
|
return error4( c4, saveRc, E94802 ) ;
|
|
|
|
return saveRc ;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = connection4status( connection ) ;
|
|
|
|
if ( out->recNo != 0 )
|
|
|
|
{
|
|
|
|
if ( (long)connection4len( connection ) != (long)sizeof( CONNECTION4GO_INFO_OUT ) + (long)dfile4recWidth( data->dataFile ) )
|
|
|
|
return error4( c4, e4packetLen, E94802 ) ;
|
|
|
|
return d4goVirtual( data, out->recNo, rc, out, connection ) ; /* maybe r4locked, or whatever */
|
|
|
|
}
|
|
|
|
|
|
|
|
return rc ;
|
|
|
|
#else
|
|
|
|
n = nSkip ;
|
|
|
|
|
|
|
|
#ifndef S4OFF_INDEX
|
|
|
|
tag = data->tagSelected ;
|
|
|
|
if ( tag == 0 )
|
|
|
|
{
|
|
|
|
#endif
|
|
|
|
data->bofFlag = 0 ;
|
|
|
|
startRec = data->recNum ;
|
|
|
|
newRec = startRec + n ;
|
|
|
|
if ( newRec > 0L )
|
|
|
|
{
|
|
|
|
#ifndef S4SERVER
|
|
|
|
saveFlag = c4->errGo ;
|
|
|
|
c4->errGo = 0 ;
|
|
|
|
#endif
|
|
|
|
#ifndef S4OFF_OPTIMIZE
|
|
|
|
data->dataFile->hiPrio = -1 ; /* indicate d4skip - data level */
|
|
|
|
#endif
|
|
|
|
rc = d4go( data, newRec ) ;
|
|
|
|
#ifndef S4OFF_OPTIMIZE
|
|
|
|
data->dataFile->hiPrio = 0 ;
|
|
|
|
#endif
|
|
|
|
#ifndef S4SERVER
|
|
|
|
c4->errGo = saveFlag ;
|
|
|
|
#endif
|
|
|
|
if ( rc >= 0 && rc != r4entry )
|
|
|
|
return rc ;
|
|
|
|
}
|
|
|
|
|
|
|
|
c1 = d4recCountLessEq( data, 1L ) ;
|
|
|
|
if ( c1 < 0 )
|
|
|
|
return c1 ;
|
|
|
|
if ( ( c1 == 0 ) || ( d4recCountLessEq( data, newRec ) == 0 ) )
|
|
|
|
{
|
|
|
|
if ( c1 == 0L )
|
|
|
|
{
|
|
|
|
rc = d4goEof( data ) ;
|
|
|
|
if ( rc != r4eof )
|
|
|
|
return rc ;
|
|
|
|
data->bofFlag = 1 ;
|
|
|
|
}
|
|
|
|
if ( n < 0 )
|
|
|
|
{
|
|
|
|
data->bofFlag = 1 ;
|
|
|
|
return r4bof ;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return d4goEof( data ) ;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( newRec < 1L )
|
|
|
|
{
|
|
|
|
oldEofFlag = data->eofFlag ;
|
|
|
|
rc = d4go( data, 1L ) ;
|
|
|
|
if ( rc )
|
|
|
|
return rc ;
|
|
|
|
data->bofFlag = 1 ;
|
|
|
|
data->eofFlag = oldEofFlag ;
|
|
|
|
return r4bof ;
|
|
|
|
}
|
|
|
|
|
|
|
|
return d4go( data, newRec ) ;
|
|
|
|
#ifndef S4OFF_INDEX
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tagFile = tag->tagFile ;
|
|
|
|
if ( data->eofFlag )
|
|
|
|
{
|
|
|
|
if ( n >= 0 )
|
|
|
|
return d4goEof( data ) ;
|
|
|
|
|
|
|
|
rc = d4bottom( data ) ;
|
|
|
|
if ( rc && rc != r4eof )
|
|
|
|
return rc ;
|
|
|
|
if ( rc == r4eof )
|
|
|
|
{
|
|
|
|
rc = d4goEof( data ) ;
|
|
|
|
if ( rc != r4eof )
|
|
|
|
return rc ;
|
|
|
|
return r4bof ;
|
|
|
|
}
|
|
|
|
n++ ;
|
|
|
|
data->recNum = tfile4recNo( tagFile ) ;
|
|
|
|
}
|
|
|
|
|
|
|
|
data->bofFlag = 0 ;
|
|
|
|
|
|
|
|
#ifndef S4OFF_WRITE
|
|
|
|
if ( data->recordChanged )
|
|
|
|
{
|
1997-06-16 13:10:44 +00:00
|
|
|
rc = d4updateRecord( data, 0 ) ; /* was 1 */
|
1997-06-16 13:01:08 +00:00
|
|
|
if ( rc < 0 )
|
|
|
|
return rc ;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
t4versionCheck( tag, 1, 0 ) ;
|
|
|
|
|
|
|
|
if ( n == 0 )
|
|
|
|
return 0 ;
|
|
|
|
|
|
|
|
if ( tfile4recNo( tagFile ) != data->recNum )
|
|
|
|
{
|
|
|
|
rc = d4go( data, data->recNum ) ;
|
|
|
|
if ( rc )
|
|
|
|
return rc ;
|
|
|
|
|
|
|
|
expr4context( tagFile->expr, data ) ;
|
|
|
|
tfile4exprKey( tagFile, &keyValue ) ;
|
|
|
|
|
|
|
|
rc = tfile4go( tagFile, keyValue, data->recNum, 0 ) ;
|
|
|
|
if ( rc < 0 )
|
|
|
|
return rc ;
|
|
|
|
|
|
|
|
#ifdef S4HAS_DESCENDING
|
|
|
|
if ( tagFile->header.descending )
|
|
|
|
{
|
|
|
|
if ( (rc > 0) && (n < 0) )
|
|
|
|
n-- ;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if ( (rc > 0) && (n > 0) )
|
|
|
|
n-- ;
|
|
|
|
#else
|
|
|
|
if ( (rc > 0) && (n > 0) )
|
|
|
|
n-- ;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
nSkipped = tfile4dskip( tagFile, n ) ;
|
|
|
|
if ( n > 0 && nSkipped != n )
|
|
|
|
return d4goEof( data ) ;
|
|
|
|
|
|
|
|
if ( tfile4eof( tagFile ) )
|
|
|
|
{
|
|
|
|
data->bofFlag = 1 ;
|
|
|
|
return d4goEof( data ) ;
|
|
|
|
}
|
|
|
|
|
|
|
|
recno = tfile4recNo( tagFile ) ;
|
|
|
|
if ( recno < 0 )
|
|
|
|
return (int)recno ;
|
|
|
|
rc = d4go( data, recno ) ;
|
|
|
|
if ( rc )
|
|
|
|
return rc ;
|
|
|
|
#ifndef S4OFF_MULTI
|
|
|
|
rc = d4tagSyncDo( data, tag, n > 0 ? 1 : -1 ) ;
|
|
|
|
if ( rc != 0 )
|
|
|
|
return rc ;
|
|
|
|
#endif
|
|
|
|
if ( n == nSkipped )
|
|
|
|
return 0 ;
|
|
|
|
|
|
|
|
#ifdef S4HAS_DESCENDING
|
|
|
|
if ( ( n < 0 && !tagFile->header.descending ) || ( n < 0 && tagFile->header.descending ) )
|
|
|
|
#else
|
|
|
|
if ( n < 0 )
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
data->bofFlag = 1 ;
|
|
|
|
return r4bof ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0 ;
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
}
|