Files
harbour-core/harbour/source/rdd/dbfcdx/dbfcdx1.c
2000-04-15 18:46:12 +00:00

3303 lines
98 KiB
C
Raw Blame History

/*
* $Id$
*/
/*
* Harbour Project source code:
* DBFCDX RDD
*
* Copyright 1999 Bruno Cantero <bruno@issnet.net>
* www - http://www.harbour-project.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version, with one exception:
*
* The exception is that if you link the Harbour Runtime Library (HRL)
* and/or the Harbour Virtual Machine (HVM) with other files to produce
* an executable, this does not by itself cause the resulting executable
* to be covered by the GNU General Public License. Your use of that
* executable is in no way restricted on account of linking the HRL
* and/or HVM code into it.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA (or visit
* their web site at http://www.gnu.org/).
*
*/
#define SUPERTABLE ( &cdxSuper )
#include <time.h>
#include <ctype.h>
#include "hbapi.h"
#include "hbapiitm.h"
#include "hbapirdd.h"
#include "hbapierr.h"
#include "hbapilng.h"
#include "hbdate.h"
#include "hbvm.h"
#include "hbinit.h"
#include "rddsys.ch"
#define LOCK_START 0x40000000L
#define LOCK_APPEND 0x7FFFFFFEL
#define LOCK_FILE 0x3FFFFFFFL
#define MEMO_BLOCK 64
#define CDX_MAX_KEY 240
#define CDX_MAX_TAG_NAME_LEN 10
#define CDX_BLOCK_SIZE 512
#define CDX_INTERNAL_SPACE 500
#define CDX_EXTERNAL_SPACE 488
#define CDX_MAX_REC_NUM 0x7FFFFFFFL
#define CDX_IGNORE_REC_NUM -1
#define PAGE_ROOT 1
#define PAGE_NODE 2
#define PAGE_LEAF 3
#define TOP_RECORD 1
#define BTTM_RECORD 2
#define PREV_RECORD 3
#define NEXT_RECORD 4
#define SORT_CHUNK_LIMIT 16384
#define SORT_ACTIVE_LIST 0
#define SORT_END_OF_KEY 1
#define SORT_END_OF_WORD 2
#define SORT_STACK_OF_CHAR 3
typedef struct _DBFHEADER
{
BYTE bVersion;
BYTE bYear;
BYTE bMonth;
BYTE bDay;
ULONG ulRecords;
USHORT uiHeaderLen;
USHORT uiRecordLen;
BYTE bReserved1[ 16 ];
BYTE bHasMDX;
BYTE bReserved2[ 3 ];
} DBFHEADER;
typedef DBFHEADER * LPDBFHEADER;
typedef struct _DBFFIELD
{
BYTE bName[ 11 ];
BYTE bType;
BYTE bReserved1[ 4 ];
BYTE bLen;
BYTE bDec;
BYTE bReserved2[ 13 ];
BYTE bHasTag;
} DBFFIELD;
typedef DBFFIELD * LPDBFFIELD;
typedef struct
{
ULONG lNextBlock;
ULONG lBlockSize;
} MEMOHEADER;
typedef MEMOHEADER * LPMEMOHEADER;
typedef struct _DBFMEMO
{
BOOL fChanged; /* Memo status */
BYTE * pData; /* Memo data */
USHORT uiLen; /* Len of data */
} DBFMEMO;
typedef DBFMEMO * LPDBFMEMO;
typedef struct _CDXHEADER
{
LONG Root;
LONG FreePtr;
LONG ChgFlag;
USHORT Key_Lgth;
BYTE IndexOpts;
BYTE IndexSig;
BYTE Reserve3[ 486 ];
USHORT AscDesc;
USHORT Reserve4;
USHORT ForExpLen;
USHORT Reserve5;
USHORT KeyExpLen;
BYTE KeyPool[ CDX_BLOCK_SIZE ];
} CDXHEADER;
typedef CDXHEADER * LPCDXHEADER;
typedef struct
{
USHORT FreeSpace;
LONG RecNumMask;
BYTE DupCntMask;
BYTE TrlCntMask;
BYTE RecNumBits;
BYTE DupCntBits;
BYTE TrlCntBits;
BYTE ShortBytes;
BYTE ExtData[ CDX_EXTERNAL_SPACE ];
} CDXEXTERNAL;
typedef struct
{
BYTE IntData[ CDX_INTERNAL_SPACE ];
} CDXINTERNAL;
typedef struct _CDXDATA
{
USHORT Node_Atr;
USHORT Entry_Ct;
LONG Left_Ptr;
LONG Rght_Ptr;
union
{
CDXEXTERNAL External;
CDXINTERNAL Internal;
} cdxu;
} CDXDATA;
typedef CDXDATA * LPCDXDATA;
typedef struct
{
char Character;
BYTE NUse;
USHORT WordArray;
USHORT Fill02;
USHORT LevelLink;
} SORT_A;
typedef struct
{
BYTE Fill03[ 4 ];
char ChrStack[ 4 ];
} SORT_B;
typedef struct
{
LONG Fill04;
LONG ChrFill;
} SORT_C;
typedef struct
{
union
{
SORT_A A;
SORT_B B;
SORT_C C;
} sortu;
} SORTDATA;
typedef SORTDATA * LPSORTDATA;
typedef struct
{
LONG WordCount;
LONG RootLink;
LONG LevelPtr;
LONG PriorPtr;
LONG KeyTot;
LONG KeyCnt;
LONG LastTag;
LONG * ChunkList;
BYTE * SortBuffer;
USHORT SortChunk;
USHORT NodeLimit;
USHORT NodeMask;
USHORT NodeShift;
USHORT ChunkSize;
USHORT ChunkLimit;
USHORT ChunkCur;
USHORT NodeCur;
USHORT KeySize;
USHORT WCur;
BOOL Unique;
BOOL Ascend;
BOOL Closing;
char WPch[ 256 ];
SORTDATA * WAdr;
LPTAGINFO CurTag;
LPCDXDATA NodeList[ 32 ];
LPKEYINFO KeyWork;
LPKEYINFO LastKey;
} SORTINFO;
typedef SORTINFO * LPSORTINFO;
extern HB_FUNC( _DBFCDX );
extern HB_FUNC( DBFCDX_GETFUNCTABLE );
HB_INIT_SYMBOLS_BEGIN( dbfcdx1__InitSymbols )
{ "_DBFCDX", HB_FS_PUBLIC, HB_FUNCNAME( _DBFCDX ), NULL },
{ "DBFCDX_GETFUNCTABLE", HB_FS_PUBLIC, HB_FUNCNAME( DBFCDX_GETFUNCTABLE ), NULL }
HB_INIT_SYMBOLS_END( dbfcdx1__InitSymbols )
#if ! defined(__GNUC__) && ! defined(_MSC_VER)
#pragma startup dbfcdx1__InitSymbols
#endif
static RDDFUNCS cdxSuper = { 0 };
ERRCODE cdxOrderListClear( AREAP pArea );
LPKEYINFO hb_cdxKeyNew( void );
void hb_cdxKeyFree( LPKEYINFO pKey );
int hb_cdxKeyCompare( LPKEYINFO pKey1, LPKEYINFO pKey2, USHORT * EndPos, BOOL Exact );
LPTAGINFO hb_cdxTagNew( LPINDEXINFO PIF, char * ITN, LONG TagHdr );
void hb_cdxTagFree( LPTAGINFO pTag );
void hb_cdxTagIndexTagNew( LPTAGINFO pTag, char * KeyExp, PHB_ITEM pKeyItem,
BYTE bType, USHORT uiLen, char * ForExp,
PHB_ITEM pForItem, BOOL Ascnd, BOOL Uniq );
void hb_cdxTagDoIndex( LPTAGINFO pTag );
void hb_cdxTagEmptyIndex( LPTAGINFO pTag );
void hb_cdxTagTagStore( LPTAGINFO pTag );
void hb_cdxTagTagOpen( LPTAGINFO pTag, BYTE bCode );
void hb_cdxTagTagClose( LPTAGINFO pTag );
LONG hb_cdxTagNewRoot( LPTAGINFO pTag );
void hb_cdxTagPageLoad( LPTAGINFO pTag, LPPAGEINFO pPage );
void hb_cdxTagKeyRead( LPTAGINFO pTag, BYTE bTypRead );
void hb_cdxTagKeyAdd( LPTAGINFO pTag, LPKEYINFO pKey );
void hb_cdxTagPageStore( LPTAGINFO pTag, LPPAGEINFO PIK );
void hb_cdxTagExtNodeWrite( LPTAGINFO pTag, LONG PN, LPCDXDATA pData, LPPAGEINFO PIK );
USHORT hb_cdxTagFillExternalNode( LPTAGINFO pTag, LPCDXDATA pData, LPPAGEINFO PIK,
USHORT kcnt, USHORT ck, LPKEYINFO * p );
void hb_cdxTagExtNodeBuild( LPTAGINFO pTag, LPCDXDATA pData, LPPAGEINFO pPage );
void hb_cdxTagTagLoad( LPTAGINFO pTag );
void hb_cdxTagSetRoot( LPTAGINFO pTag, LPPAGEINFO PIK );
void hb_cdxTagIntNodeWrite( LPTAGINFO pTag, LONG PN, LPCDXDATA pData, LPPAGEINFO PIK );
USHORT hb_cdxTagFillInternalNode( LPTAGINFO pTag, LPCDXDATA pData, LPPAGEINFO PIK,
USHORT kcnt, USHORT ck, LPKEYINFO * p );
void hb_cdxTagIntNodeBuild( LPTAGINFO pTag, LPCDXDATA pData, LPPAGEINFO pPage );
LONG hb_cdxTagKeyFind( LPTAGINFO pTag, LPKEYINFO pKey );
LPPAGEINFO hb_cdxPageNew( LPTAGINFO PIT, LPPAGEINFO PIK, LONG FilePosn );
void hb_cdxPageFree( LPPAGEINFO pPage );
BOOL hb_cdxPageReadTopKey( LPPAGEINFO pPage );
BOOL hb_cdxPageReadBottomKey( LPPAGEINFO pPage );
int hb_cdxPageSeekKey( LPPAGEINFO pPage, LONG lBlock, LPKEYINFO pKey, BOOL bExact );
void hb_cdxPageInsertKey( LPPAGEINFO pPage, LPKEYINFO pKey, BOOL bAddAfter );
void hb_cdxPagePageStore( LPPAGEINFO pPage );
BOOL hb_cdxPageReadNextKey( LPPAGEINFO pPage );
LPKEYINFO hb_cdxPageGetKey( LPPAGEINFO pPage, USHORT uiKey );
void hb_cdxPagePageLoad( LPPAGEINFO pPage );
int hb_cdxPageRetrieveKey( LPPAGEINFO pPage, LPKEYINFO pKey );
void hb_cdxPageAddNodeKey( LPPAGEINFO pPage, LPKEYINFO pKey );
int hb_cdxPageSeekNodeTag( LPPAGEINFO pPage, LONG Tag );
BOOL hb_cdxPageGetChild( LPPAGEINFO pPage, LONG Tag );
void hb_cdxPageDeleteKey( LPPAGEINFO pPage );
LPINDEXINFO hb_cdxIndexNew( AREAP pArea );
void hb_cdxIndexFree( LPINDEXINFO pIndex );
LONG hb_cdxIndexGetAvailPage( LPINDEXINFO pIndex );
void hb_cdxIndexResetAvailPage( LPINDEXINFO pIndex );
void hb_cdxIndexPageRead( LPINDEXINFO pIndex, LONG lPos, void * pBuffer, USHORT uiSize );
void hb_cdxIndexPageWrite( LPINDEXINFO pIndex, LONG lPos, void * pBuffer, USHORT uiSize );
void hb_cdxIndexAddTag( LPINDEXINFO pIndex, char * szTagName, char * szKeyExp,
PHB_ITEM pKeyItem, BYTE bType, USHORT uiLen, char * szForExp,
PHB_ITEM pForItem, BOOL bAscending, BOOL bUnique );
LPSORTINFO hb_cdxSortNew( LPTAGINFO pTag, BOOL bUnique );
void hb_cdxSortFree( LPSORTINFO pSort );
void hb_cdxSortLinkNew( LPSORTINFO pSort, LONG * NewLink );
void hb_cdxSortGetNewChunk( LPSORTINFO pSort );
void hb_cdxSortInsertWord( LPSORTINFO pSort, LONG Tag, char * Value );
void hb_cdxSortStuffKey( LPSORTINFO pSort, LPSORTDATA * wx );
void hb_cdxSortGetNode( LPSORTINFO pSort, char Character, LONG * NewLink );
LPSORTDATA hb_cdxSortLinkGet( LPSORTINFO pSort, LONG Value );
void hb_cdxSortDisplayWord( LPSORTINFO pSort );
void hb_cdxSortRecurseDict( LPSORTINFO pSort, LONG WPtr, LONG WBgn );
void hb_cdxSortSendWord( LPSORTINFO pSort, char * Value );
void hb_cdxSortOutputWord( LPSORTINFO pSort, LONG Tag, char * Value );
void hb_cdxSortAddToNode( LPSORTINFO pSort, USHORT Lvl, LONG Tag, LONG Link,
LPKEYINFO Value );
void hb_cdxSortAddExternal( LPSORTINFO pSort, USHORT Lvl, LONG Tag, LONG Link,
LPKEYINFO Value );
void hb_cdxSortAddInternal( LPSORTINFO pSort, USHORT Lvl, LONG Tag, LONG Link,
LPKEYINFO Value );
static BOOL hb_cdxltoa( LONG lValue, char * szBuffer, USHORT uiLen )
{
LONG lAbsNumber;
int iCount, iPos;
HB_TRACE(HB_TR_DEBUG, ("hb_nltoa(%ld, %p, %hu)", lValue, szBuffer, uiLen));
lAbsNumber = ( lValue > 0 ) ? lValue : - lValue;
iCount = iPos = uiLen;
while( iCount-- > 0 )
{
szBuffer[ iCount ] = ( '0' + lAbsNumber % 10 );
lAbsNumber /= 10;
}
if( lAbsNumber > 0 )
{
memset( szBuffer, ' ', uiLen );
return FALSE;
}
uiLen--;
for( iCount = 0; iCount < uiLen; iCount++ )
if( szBuffer[ iCount ] == '0' )
szBuffer[ iCount ] = ' ';
else
break;
if( lValue < 0 )
{
if( szBuffer[ 0 ] != ' ' )
{
memset( szBuffer, ' ', iPos );
return FALSE;
}
for( iCount = uiLen; iCount >= 0; iCount-- )
{
if( szBuffer[ iCount ] == ' ' )
{
szBuffer[ iCount ] = '-';
break;
}
}
}
return TRUE;
}
static ULONG hb_cdxSwapBytes( ULONG ulValue )
{
BYTE * pValue, * pNewValue;
ULONG ulNewValue;
HB_TRACE(HB_TR_DEBUG, ("hb_cdxSwapBytes(%lu)", ulValue));
pValue = ( BYTE * ) &ulValue;
pNewValue = ( BYTE * ) &ulNewValue;
pNewValue[ 0 ] = pValue[ 3 ];
pNewValue[ 1 ] = pValue[ 2 ];
pNewValue[ 2 ] = pValue[ 1 ];
pNewValue[ 3 ] = pValue[ 0 ];
return ulNewValue;
}
static LONG hb_cdxMakeMask( BYTE bByte )
{
BYTE bCount;
LONG lMask;
for( lMask = 0, bCount = 1; bCount <= bByte; bCount++,
lMask = ( lMask << 1 ) + 1 );
return lMask;
}
static void hb_cdxReadMemo( AREAP pArea, LPDBFMEMO pMemo, ULONG lMemoBlock )
{
ULONG ulSpaceUsed;
MEMOHEADER pMemoHeader;
HB_TRACE(HB_TR_DEBUG, ("hb_cdxReadMemo(%p, %p, %lu)", pArea, pMemo, lMemoBlock));
hb_fsSeek( pArea->lpDataInfo->pNext->hFile, lMemoBlock * MEMO_BLOCK, FS_SET );
hb_fsRead( pArea->lpDataInfo->pNext->hFile, ( BYTE * ) &pMemoHeader,
sizeof( MEMOHEADER ) );
ulSpaceUsed = hb_cdxSwapBytes( pMemoHeader.lBlockSize );
if( pMemo->uiLen != ulSpaceUsed )
{
if( pMemo->uiLen > 0 )
pMemo->pData = ( BYTE * ) hb_xrealloc( pMemo->pData, ulSpaceUsed + 1 );
else
pMemo->pData = ( BYTE * ) hb_xgrab( ulSpaceUsed + 1 );
pMemo->uiLen = ulSpaceUsed;
}
hb_fsRead( pArea->lpDataInfo->pNext->hFile, pMemo->pData, pMemo->uiLen );
}
static BOOL hb_cdxWriteMemo( AREAP pArea, LPDBFMEMO pMemo, ULONG * lNewRecNo )
{
USHORT uiNumBlocks;
MEMOHEADER pMemoHeader;
BYTE * pBuffer;
HB_TRACE(HB_TR_DEBUG, ("hb_cdxWriteMemo(%p, %p, %p)", pArea, pMemo, lNewRecNo));
if( !pArea->lpExtendInfo->fExclusive && !pArea->lpDataInfo->fFileLocked &&
!hb_fsLock( pArea->lpDataInfo->pNext->hFile, LOCK_APPEND - 1, 1, FL_LOCK ) )
return FALSE;
uiNumBlocks = 1 + ( pMemo->uiLen + sizeof( MEMOHEADER ) ) / MEMO_BLOCK;
if( * lNewRecNo > 0 )
{
hb_fsSeek( pArea->lpDataInfo->pNext->hFile, * lNewRecNo * MEMO_BLOCK, FS_SET );
hb_fsRead( pArea->lpDataInfo->pNext->hFile, ( BYTE * ) &pMemoHeader,
sizeof( MEMOHEADER ) );
if( pMemo->uiLen > hb_cdxSwapBytes( pMemoHeader.lBlockSize ) )
* lNewRecNo = 0; /* Not room for data */
}
if( * lNewRecNo == 0 ) /* Add an entry at eof */
{
hb_fsSeek( pArea->lpDataInfo->pNext->hFile, 0, FS_SET );
hb_fsRead( pArea->lpDataInfo->pNext->hFile, ( BYTE * ) &pMemoHeader,
sizeof( MEMOHEADER ) );
* lNewRecNo = hb_cdxSwapBytes( pMemoHeader.lNextBlock );
pMemoHeader.lNextBlock = hb_cdxSwapBytes( * lNewRecNo + uiNumBlocks );
hb_fsSeek( pArea->lpDataInfo->pNext->hFile, 0, FS_SET );
hb_fsWrite( pArea->lpDataInfo->pNext->hFile, ( BYTE * ) &pMemoHeader,
sizeof( MEMOHEADER ) );
}
hb_fsSeek( pArea->lpDataInfo->pNext->hFile, * lNewRecNo * MEMO_BLOCK, FS_SET );
pMemoHeader.lNextBlock = hb_cdxSwapBytes( 1 );
pMemoHeader.lBlockSize = hb_cdxSwapBytes( pMemo->uiLen );
hb_fsWrite( pArea->lpDataInfo->pNext->hFile, ( BYTE * ) &pMemoHeader,
sizeof( MEMOHEADER ) );
if( hb_fsWrite( pArea->lpDataInfo->pNext->hFile, pMemo->pData,
pMemo->uiLen ) != pMemo->uiLen )
{
if( !pArea->lpExtendInfo->fExclusive && !pArea->lpDataInfo->fFileLocked )
hb_fsLock( pArea->lpDataInfo->pNext->hFile, LOCK_APPEND - 1, 1, FL_UNLOCK );
return FALSE;
}
uiNumBlocks = ( pMemo->uiLen + sizeof( MEMOHEADER ) ) % MEMO_BLOCK;
if( uiNumBlocks > 0 )
{
pBuffer = ( BYTE * ) hb_xgrab( MEMO_BLOCK );
memset( pBuffer, 0, MEMO_BLOCK );
hb_fsWrite( pArea->lpDataInfo->pNext->hFile, pBuffer, MEMO_BLOCK - uiNumBlocks );
hb_xfree( pBuffer);
}
if( !pArea->lpExtendInfo->fExclusive && !pArea->lpDataInfo->fFileLocked )
hb_fsLock( pArea->lpDataInfo->pNext->hFile, LOCK_APPEND - 1, 1, FL_UNLOCK );
return TRUE;
}
static LPKEYINFO hb_cdxKeyNew()
{
LPKEYINFO pKey;
pKey = ( LPKEYINFO ) hb_xgrab( sizeof( KEYINFO ) );
pKey->pItem = hb_itemNew( NULL );
pKey->Tag = pKey->Xtra = 0;
pKey->pNext = NULL;
return pKey;
}
static void hb_cdxKeyFree( LPKEYINFO pKey )
{
hb_itemRelease( pKey->pItem );
hb_xfree( pKey );
}
static int hb_cdxKeyCompare( LPKEYINFO pKey1, LPKEYINFO pKey2, USHORT * EndPos, BOOL Exact )
{
int iLimit, iResult;
* EndPos = 0;
if( pKey2 == NULL || pKey2->pItem->item.asString.length == 0 )
return 1;
if( pKey1 == NULL || pKey1->pItem->item.asString.length == 0 )
return ( pKey2->pItem->item.asString.length == 0 ) ? 0: -1;
switch( hb_itemType( pKey1->pItem ) )
{
case HB_IT_STRING:
iLimit = ( pKey1->pItem->item.asString.length >
pKey2->pItem->item.asString.length ) ?
pKey2->pItem->item.asString.length :
pKey1->pItem->item.asString.length;
do
{
iResult = pKey1->pItem->item.asString.value[ * EndPos ] -
pKey2->pItem->item.asString.value[ * EndPos ];
* EndPos += 1;
} while( iResult == 0 && * EndPos < iLimit );
if( iResult == 0 )
{
* EndPos += 1;
iResult = pKey1->pItem->item.asString.length -
pKey2->pItem->item.asString.length;
}
if( iResult < 0 && * EndPos > pKey1->pItem->item.asString.length && !Exact )
iResult = 0;
break;
default:
printf( "hb_cdxKeyCompare()" );
}
if( iResult < 0 )
return -1;
else if( iResult > 0 )
return 1;
else
return 0;
}
static LPTAGINFO hb_cdxTagNew( LPINDEXINFO PIF, char * ITN, LONG TagHdr )
{
LPTAGINFO pTag;
pTag = ( LPTAGINFO ) hb_xgrab( sizeof( TAGINFO ) );
memset( pTag, 0, sizeof( TAGINFO ) );
pTag->TagName = ( char * ) hb_xgrab( CDX_MAX_TAG_NAME_LEN + 1 );
hb_strncpyUpper( pTag->TagName, ITN, CDX_MAX_TAG_NAME_LEN );
pTag->Owner = PIF;
pTag->AscendKey = TRUE;
pTag->KeyType = 'C';
pTag->CurKeyInfo = hb_cdxKeyNew();
if( TagHdr == -1 )
{
pTag->TagBlock = hb_cdxIndexGetAvailPage( PIF );
hb_cdxIndexGetAvailPage( PIF );
pTag->TagChanged = TRUE;
}
else
{
pTag->TagBlock = TagHdr;
hb_cdxTagTagLoad( pTag );
}
pTag->OptFlags = 0x60;
return pTag;
}
static void hb_cdxTagFree( LPTAGINFO pTag )
{
if( pTag->RootPage != NULL )
{
hb_cdxPageFree( pTag->RootPage );
pTag->RootPage = NULL;
}
if( pTag->TagChanged )
hb_cdxTagTagStore( pTag );
if( pTag->TagName != NULL )
hb_xfree( pTag->TagName );
if( pTag->KeyExpr != NULL )
hb_xfree( pTag->KeyExpr );
if( pTag->pKeyItem != NULL )
{
if( hb_itemType( pTag->pKeyItem ) != HB_IT_BLOCK )
hb_macroDelete( ( HB_MACRO_PTR ) hb_itemGetPtr( pTag->pKeyItem ) );
hb_itemRelease( pTag->pKeyItem );
}
if( pTag->ForExpr != NULL )
hb_xfree( pTag->ForExpr );
if( pTag->pForItem != NULL )
{
if( hb_itemType( pTag->pForItem ) != HB_IT_BLOCK )
hb_macroDelete( ( HB_MACRO_PTR ) hb_itemGetPtr( pTag->pForItem ) );
hb_itemRelease( pTag->pForItem );
}
hb_cdxKeyFree( pTag->CurKeyInfo );
hb_xfree( pTag );
}
static void hb_cdxTagIndexTagNew( LPTAGINFO pTag, char * KeyExp, PHB_ITEM pKeyItem,
BYTE bType, USHORT uiLen, char * ForExp,
PHB_ITEM pForItem, BOOL Ascnd, BOOL Uniq )
{
CDXHEADER pHeader;
if( KeyExp != NULL )
{
pTag->KeyExpr = ( char * ) hb_xgrab( CDX_MAX_KEY + 1 );
hb_strncpyUpper( pTag->KeyExpr, KeyExp, CDX_MAX_KEY );
}
pTag->pKeyItem = pKeyItem;
if( ForExp != NULL )
{
pTag->ForExpr = ( char * ) hb_xgrab( CDX_MAX_KEY + 1 );
hb_strncpyUpper( pTag->ForExpr, ForExp, CDX_MAX_KEY );
}
pTag->pForItem = pForItem;
pTag->AscendKey = Ascnd;
pTag->UniqueKey = Uniq;
pTag->KeyType = bType;
pTag->KeyLength = uiLen;
pTag->MaxKeys = ( CDX_BLOCK_SIZE - 12 ) / ( uiLen + 8 );
memset( &pHeader, 0, sizeof( CDXHEADER ) );
hb_cdxIndexPageWrite( pTag->Owner, pTag->TagBlock, &pHeader, sizeof( CDXHEADER ) );
hb_cdxTagDoIndex( pTag );
}
static void hb_cdxTagDoIndex( LPTAGINFO pTag )
{
ULONG ulRecNo;
BOOL bWhileOk;
LPSORTINFO pSort;
LPKEYINFO pKey;
HB_MACRO_PTR pMacro;
if( pTag->OptFlags & 0x80 )
hb_cdxTagEmptyIndex( pTag );
else
{
pSort = hb_cdxSortNew( pTag, pTag->UniqueKey );
pKey = hb_cdxKeyNew();
for( ulRecNo = 1; ulRecNo <= pTag->Owner->Owner->lpExtendInfo->ulRecCount; ulRecNo++ )
{
hb_fsSeek( pTag->Owner->Owner->lpDataInfo->hFile,
pTag->Owner->Owner->lpExtendInfo->uiHeaderLen +
( ulRecNo - 1 ) * pTag->Owner->Owner->lpExtendInfo->uiRecordLen,
FS_SET );
hb_fsRead( pTag->Owner->Owner->lpDataInfo->hFile,
pTag->Owner->Owner->lpExtendInfo->bRecord,
pTag->Owner->Owner->lpExtendInfo->uiRecordLen );
if( pTag->pForItem != NULL )
/* TODO: test for expression */
bWhileOk = TRUE;
else
bWhileOk = TRUE;
if( bWhileOk )
{
if( hb_itemType( pTag->pKeyItem ) == HB_IT_BLOCK )
{
hb_vmPushSymbol( &hb_symEval );
hb_vmPush( pTag->pKeyItem );
hb_vmDo( 0 );
}
else
{
pMacro = ( HB_MACRO_PTR ) hb_itemGetPtr( pTag->pKeyItem );
hb_macroRun( pMacro );
}
hb_itemCopy( pKey->pItem, &hb_stack.Return );
switch( hb_itemType( pKey->pItem ) )
{
case HB_IT_STRING:
hb_cdxSortInsertWord( pSort, ulRecNo, pKey->pItem->item.asString.value );
break;
default:
printf( "hb_cdxTagDoIndex( LPTAGINFO pTag )" );
}
}
}
if( pSort->WordCount > 0 )
hb_cdxSortDisplayWord( pSort );
else
hb_cdxTagEmptyIndex( pTag );
hb_cdxSortFree( pSort );
hb_cdxKeyFree( pKey );
}
pTag->TagChanged = TRUE;
hb_cdxTagTagStore( pTag );
}
static void hb_cdxTagEmptyIndex( LPTAGINFO pTag )
{
USHORT uiKeyLength, uiBitCount;
CDXDATA pData;
pTag->RootBlock = hb_cdxIndexGetAvailPage( pTag->Owner );
memset( &pData, 0, sizeof( CDXDATA ) );
pData.Node_Atr = 3;
pData.Left_Ptr = pData.Rght_Ptr = -1;
uiKeyLength = pTag->KeyLength;
for( uiBitCount = 0; uiKeyLength; uiBitCount++, uiKeyLength >>= 1 );
pData.cdxu.External.ShortBytes = 3;
pData.cdxu.External.RecNumBits = 24 - uiBitCount * 2;
pData.cdxu.External.RecNumMask = hb_cdxMakeMask( pData.cdxu.External.RecNumBits );
pData.cdxu.External.FreeSpace = CDX_EXTERNAL_SPACE;
pData.cdxu.External.DupCntBits = pData.cdxu.External.TrlCntBits = uiBitCount;
pData.cdxu.External.DupCntMask = hb_cdxMakeMask( pData.cdxu.External.DupCntBits );
pData.cdxu.External.TrlCntMask = hb_cdxMakeMask( pData.cdxu.External.TrlCntBits );
hb_cdxIndexPageWrite( pTag->Owner, pTag->RootBlock, &pData, sizeof( CDXDATA ) );
}
static void hb_cdxTagTagStore( LPTAGINFO pTag )
{
USHORT uiForLen;
CDXHEADER pHeader;
if( !pTag->TagChanged )
return;
pTag->TagChanged = FALSE;
if( pTag->UniqueKey )
pTag->OptFlags |= 0x01;
if( pTag->pForItem != NULL )
pTag->OptFlags |= 0x08;
memset( &pHeader, 0, sizeof( CDXHEADER ) );
pHeader.Root = pTag->RootBlock;
pHeader.Key_Lgth = pTag->KeyLength;
pHeader.IndexOpts = pTag->OptFlags;
pHeader.IndexSig = 1;
if( !pTag->AscendKey )
pHeader.AscDesc = 1;
pHeader.Reserve4 = 1 + ( pTag->KeyExpr == NULL ? 0 : strlen( pTag->KeyExpr ) );
pHeader.KeyExpLen = pHeader.Reserve4;
if( pTag->KeyExpr != NULL )
strcpy( pHeader.KeyPool, pTag->KeyExpr );
uiForLen = pTag->ForExpr == NULL ? 0 : strlen( pTag->ForExpr );
if( uiForLen > 0 )
{
pHeader.ForExpLen = uiForLen + 1;
strcpy( pHeader.KeyPool + pHeader.KeyExpLen, pTag->ForExpr );
}
else
pHeader.ForExpLen = 1;
hb_cdxIndexPageWrite( pTag->Owner, pTag->TagBlock, &pHeader, sizeof( CDXHEADER ) );
}
static void hb_cdxTagTagOpen( LPTAGINFO pTag, BYTE bCode )
{
hb_cdxTagTagClose( pTag );
pTag->RootBlock = hb_cdxTagNewRoot( pTag );
pTag->RootPage = hb_cdxPageNew( pTag, NULL, pTag->RootBlock );
if( bCode == 2 )
return;
if( bCode == 0 )
hb_cdxTagKeyRead( pTag, TOP_RECORD );
else
printf( "hb_cdxTagTagOpen()" );
}
static void hb_cdxTagTagClose( LPTAGINFO pTag )
{
if( pTag->RootPage != NULL )
{
hb_cdxPageFree( pTag->RootPage );
pTag->RootPage = NULL;
}
if( pTag->TagChanged )
hb_cdxTagTagStore( pTag );
}
static LONG hb_cdxTagNewRoot( LPTAGINFO pTag )
{
CDXHEADER pHeader;
hb_cdxIndexPageRead( pTag->Owner, pTag->TagBlock, &pHeader, sizeof( CDXHEADER ) );
return pHeader.Root;
}
static void hb_cdxTagPageLoad( LPTAGINFO pTag, LPPAGEINFO pPage )
{
CDXDATA pData;
LPKEYINFO pKey;
hb_cdxIndexPageRead( pTag->Owner, pPage->Page, &pData, sizeof( CDXDATA ) );
if( pData.Node_Atr > 1 )
pPage->PageType = PAGE_LEAF;
else
pPage->PageType = PAGE_NODE;
pPage->Left = pData.Left_Ptr;
pPage->Right = pData.Rght_Ptr;
if( pData.Entry_Ct > 0 )
{
if( pPage->PageType == PAGE_LEAF )
hb_cdxTagExtNodeBuild( pTag, &pData, pPage );
else
hb_cdxTagIntNodeBuild( pTag, &pData, pPage );
}
pPage->Changed = FALSE;
}
static void hb_cdxTagKeyRead( LPTAGINFO pTag, BYTE bTypRead )
{
pTag->CurKeyInfo->Tag = 0;
if( pTag->RootPage == NULL )
return;
if( !pTag->AscendKey )
{
switch( bTypRead )
{
case TOP_RECORD:
bTypRead = BTTM_RECORD;
break;
case BTTM_RECORD:
bTypRead = TOP_RECORD;
break;
case NEXT_RECORD:
bTypRead = PREV_RECORD;
break;
case PREV_RECORD:
bTypRead = NEXT_RECORD;
break;
}
}
pTag->TagBOF = pTag->TagEOF = FALSE;
switch( bTypRead )
{
case TOP_RECORD:
hb_cdxTagTagOpen( pTag, 2 );
if( pTag->pForItem != NULL )
printf( "hb_cdxTagKeyRead()" );
else
pTag->TagBOF = !hb_cdxPageReadTopKey( pTag->RootPage );
if( pTag->pForItem != NULL )
printf( "hb_cdxTagTestRange()" );
if( pTag->TagEOF )
pTag->TagBOF = TRUE;
pTag->TagEOF = pTag->TagBOF;
break;
case BTTM_RECORD:
hb_cdxTagTagOpen( pTag, 2 );
if( pTag->pForItem != NULL )
printf( "hb_cdxTagKeyRead()" );
else
pTag->TagEOF = !hb_cdxPageReadBottomKey( pTag->RootPage );
if( pTag->pForItem != NULL )
{
printf( "hb_cdxTagTestRange()" );
}
if( pTag->TagBOF )
pTag->TagEOF = TRUE;
pTag->TagBOF = pTag->TagEOF;
break;
case NEXT_RECORD:
while( TRUE )
{
pTag->TagEOF = !hb_cdxPageReadNextKey( pTag->RootPage );
if( pTag->pForItem != NULL )
printf( "hb_cdxTagKeyRead()" );
else
break;
}
break;
}
if( pTag->TagBOF || pTag->TagEOF )
{
if( !pTag->AscendKey )
{
pTag->CurKeyInfo->Tag = pTag->TagEOF;
pTag->TagEOF = pTag->TagBOF;
pTag->TagBOF = ( BOOL ) pTag->CurKeyInfo->Tag;
}
pTag->CurKeyInfo->Tag = 0;
}
}
static void hb_cdxTagKeyAdd( LPTAGINFO pTag, LPKEYINFO pKey )
{
int iSeek;
LONG lOldXtra;
LPKEYINFO pNewKey;
lOldXtra = pKey->Xtra;
pKey->Xtra = pKey->Tag;
hb_cdxTagTagOpen( pTag, 0 );
pNewKey = hb_cdxKeyNew();
hb_itemCopy( pNewKey->pItem, pKey->pItem );
pNewKey->Tag = pKey->Tag;
pNewKey->Xtra = pKey->Xtra;
if( pTag->KeyType == 'C' )
{
while( pNewKey->pItem->item.asString.length > 0 &&
pNewKey->pItem->item.asString.value[ pNewKey->pItem->item.asString.length - 1 ] == ' ' )
pNewKey->pItem->item.asString.length--;
pNewKey->pItem->item.asString.value[ pNewKey->pItem->item.asString.length ] = NULL;
}
pTag->TagBOF = pTag->TagEOF = FALSE;
iSeek = hb_cdxPageSeekKey( pTag->RootPage, pNewKey->Tag, pNewKey, TRUE );
if( iSeek < 1 )
{
hb_cdxPageInsertKey( pTag->RootPage, pNewKey, FALSE );
hb_cdxTagTagOpen( pTag, 0 );
hb_cdxPageSeekKey( pTag->RootPage, pNewKey->Tag, pNewKey, FALSE );
iSeek = hb_cdxPageRetrieveKey( pTag->RootPage, pTag->CurKeyInfo );
if( !pTag->AscendKey )
{
pTag->TagBOF = ( iSeek & 2 );
pTag->TagEOF = ( iSeek & 1 );
}
else
{
pTag->TagBOF = ( iSeek & 1 );
pTag->TagEOF = ( iSeek & 2 );
}
}
else
{
if( !pTag->AscendKey )
printf( "hb_cdxTagKeyAdd()\n");
else
hb_cdxTagKeyRead( pTag, BTTM_RECORD );
hb_cdxPageInsertKey( pTag->RootPage, pNewKey, TRUE );
hb_cdxTagTagOpen( pTag, 0 );
if( !pTag->AscendKey )
{
printf( "hb_cdxTagKeyAdd()\n");
pTag->TagBOF = TRUE;
}
else
{
hb_cdxTagKeyRead( pTag, BTTM_RECORD );
pTag->TagEOF = TRUE;
}
}
hb_cdxKeyFree( pNewKey );
pKey->Xtra = lOldXtra;
}
static void hb_cdxTagPageStore( LPTAGINFO pTag, LPPAGEINFO PIK )
{
CDXDATA pData;
memset( &pData, 0, sizeof( CDXDATA ) );
pData.Node_Atr = ( PIK->PageType < PAGE_LEAF ) ? 0 : 2;
if( PIK->Owner == NULL )
pData.Node_Atr++;
pData.Left_Ptr = PIK->Left;
pData.Rght_Ptr = PIK->Right;
if( pData.Node_Atr < 2 )
hb_cdxTagIntNodeWrite( pTag, PIK->Page, &pData, PIK );
else
hb_cdxTagExtNodeWrite( pTag, PIK->Page, &pData, PIK );
}
static void hb_cdxTagExtNodeWrite( LPTAGINFO pTag, LONG PN, LPCDXDATA pData,
LPPAGEINFO PIK )
{
USHORT uiKeyLength, uiBitCount, cd, kcnt, lm, uiCount, ck, na;
LONG sr, rp, lp, NPN, TmpTag;
LPKEYINFO p, q;
if( pTag->OptFlags & 0x80 )
sr = hb_fsSeek( pTag->Owner->DiskFile, 0, FS_END );
else
sr = pTag->Owner->Owner->lpExtendInfo->ulRecCount;
uiKeyLength = pTag->KeyLength;
for( uiBitCount = 0; uiKeyLength; uiBitCount++, uiKeyLength >>= 1 );
PIK->ReqByte = 3;
PIK->RNBits = 24 - uiBitCount * 2;
PIK->RNMask = hb_cdxMakeMask( PIK->RNBits );
while( sr > PIK->RNMask )
{
PIK->ReqByte++;
PIK->RNBits += 8;
PIK->RNMask = ( PIK->RNMask << 8 ) | 0xFF;
if( PIK->RNMask < 0 )
{
PIK->RNMask = 0x7FFFFFFF;
PIK->RNBits = 31;
}
}
PIK->Space = CDX_EXTERNAL_SPACE;
PIK->DCBits = PIK->TCBits = uiBitCount;
PIK->DCMask = hb_cdxMakeMask( PIK->DCBits );
PIK->TCMask = hb_cdxMakeMask( PIK->TCBits );
sr = cd = kcnt = 0;
lm = sizeof( pData->cdxu.Internal.IntData ) / 2;
q = NULL;
for( uiCount = 0; uiCount < PIK->uiKeys; uiCount++ )
{
p = hb_cdxPageGetKey( PIK, uiCount );
if( q != NULL )
{
hb_cdxKeyCompare( p, q, &cd, TRUE );
if( cd > 0 )
cd--;
}
q = p;
/* Comprobar que las Keys son de tipo car<61>cter. */
cd = p->pItem->item.asString.length - cd;
sr += cd + PIK->ReqByte;
if( sr < lm )
kcnt++;
}
if( sr < CDX_EXTERNAL_SPACE )
kcnt = PIK->uiKeys;
ck = 0;
pData->Entry_Ct = 0;
if( kcnt < PIK->uiKeys )
{
ck = hb_cdxTagFillExternalNode( pTag, pData, PIK, kcnt, ck, &p );
if( pData->Node_Atr % 2 > 0 )
pData->Node_Atr--;
na = pData->Node_Atr;
rp = pData->Rght_Ptr;
lp = pData->Left_Ptr;
pData->Rght_Ptr = PN;
pData->cdxu.External.FreeSpace = PIK->Space;
NPN = hb_cdxIndexGetAvailPage( pTag->Owner );
TmpTag = p->Tag;
p->Tag = NPN;
hb_cdxPageAddNodeKey( PIK, p );
p->Tag = TmpTag;
if( PIK->PageType == PAGE_ROOT )
PIK->PageType = PAGE_NODE;
hb_cdxIndexPageWrite( pTag->Owner, NPN, pData, CDX_BLOCK_SIZE );
if( lp > 0 )
{
hb_cdxIndexPageRead( pTag->Owner, lp, pData, CDX_BLOCK_SIZE );
pData->Rght_Ptr = NPN;
hb_cdxIndexPageWrite( pTag->Owner, lp, pData, CDX_BLOCK_SIZE );
}
memset( pData, 0, CDX_BLOCK_SIZE );
pData->Node_Atr = na;
pData->Rght_Ptr = rp;
pData->Left_Ptr = NPN;
pData->Entry_Ct = 0;
kcnt = PIK->uiKeys;
}
hb_cdxTagFillExternalNode( pTag, pData, PIK, kcnt, ck, &p );
pData->cdxu.External.FreeSpace = PIK->Space;
hb_cdxIndexPageWrite( pTag->Owner, PN, pData, sizeof( CDXDATA ) );
}
static USHORT hb_cdxTagFillExternalNode( LPTAGINFO pTag, LPCDXDATA pData,
LPPAGEINFO PIK, USHORT kcnt,
USHORT ck, LPKEYINFO * p )
{
USHORT i, k, ct, cd, v, c;
LONG m, r;
LPKEYINFO q;
memset( pData->cdxu.External.ExtData, 0, sizeof( pData->cdxu.External.ExtData ) );
pData->cdxu.External.FreeSpace = PIK->Space;
pData->cdxu.External.RecNumMask = PIK->RNMask;
pData->cdxu.External.DupCntMask = PIK->DCMask;
pData->cdxu.External.TrlCntMask = PIK->TCMask;
pData->cdxu.External.RecNumBits = PIK->RNBits;
pData->cdxu.External.DupCntBits = PIK->DCBits;
pData->cdxu.External.TrlCntBits = PIK->TCBits;
pData->cdxu.External.ShortBytes = PIK->ReqByte;
m = ~PIK->RNMask;
PIK->Space = CDX_EXTERNAL_SPACE;
k = CDX_EXTERNAL_SPACE;
q = NULL;
i = 0;
while( i < kcnt && ck < PIK->uiKeys )
{
* p = hb_cdxPageGetKey( PIK, ck );
ct = pTag->KeyLength - ( * p )->pItem->item.asString.length;
if( q != NULL )
{
hb_cdxKeyCompare( * p, q, &cd, TRUE );
if( cd > 0 )
cd--;
}
else
cd = 0;
q = * p;
PIK->Space -= pTag->KeyLength + PIK->ReqByte - cd - ct;
v = i * PIK->ReqByte;
c = ( ct << ( 16 - PIK->TCBits ) ) | ( cd << ( 16 - PIK->TCBits - PIK->DCBits ) );
memcpy( &pData->cdxu.External.ExtData[ v + PIK->ReqByte - 2 ], &c, 2 );
memcpy( &r, &pData->cdxu.External.ExtData[ v ], 4 );
r &= m;
r |= ( * p )->Tag;
memcpy( &pData->cdxu.External.ExtData[ v ], &r, 4 );
k -= pTag->KeyLength - cd - ct;
if( pTag->KeyLength - cd - ct > 0 )
memcpy( &pData->cdxu.External.ExtData[ k ], ( * p )->pItem->item.asString.value + cd,
pTag->KeyLength - cd - ct );
i++;
ck++;
pData->Entry_Ct++;
}
return ck;
}
static void hb_cdxTagExtNodeBuild( LPTAGINFO pTag, LPCDXDATA pData, LPPAGEINFO PIK )
{
USHORT k, i, v, c, t, d;
LONG r;
LPKEYINFO pKey, pLastKey;
static char szBuffer[ CDX_MAX_KEY + 1 ];
k = CDX_EXTERNAL_SPACE;
PIK->Space = pData->cdxu.External.FreeSpace;
PIK->RNMask = pData->cdxu.External.RecNumMask;
PIK->DCMask = pData->cdxu.External.DupCntMask;
PIK->TCMask = pData->cdxu.External.TrlCntMask;
PIK->RNBits = pData->cdxu.External.RecNumBits;
PIK->DCBits = pData->cdxu.External.DupCntBits;
PIK->TCBits = pData->cdxu.External.TrlCntBits;
PIK->ReqByte = pData->cdxu.External.ShortBytes;
i = 0;
while( i < pData->Entry_Ct )
{
v = i * PIK->ReqByte;
memcpy( &c, &pData->cdxu.External.ExtData[ v + PIK->ReqByte - 2 ], 2 );
t = ( c >> ( 16 - PIK->TCBits ) ) & PIK->TCMask;
d = ( c >> ( 16 - PIK->TCBits - PIK->DCBits ) ) & PIK->DCMask;
memcpy( &r, &pData->cdxu.External.ExtData[ v ], 4 );
r &= PIK->RNMask;
k -= pTag->KeyLength - d - t;
if( pTag->KeyLength - d - t > 0 )
memcpy( &szBuffer[ d ], &pData->cdxu.External.ExtData[ k ],
pTag->KeyLength - d - t );
szBuffer[ pTag->KeyLength - t ] = NULL;
pKey = hb_cdxKeyNew();
pKey->Tag = r;
pKey->Xtra = r;
hb_itemPutC( pKey->pItem, szBuffer );
if( PIK->pKeys == NULL )
PIK->pKeys = pKey;
else
{
pLastKey = PIK->pKeys;
while( pLastKey->pNext )
pLastKey = pLastKey->pNext;
pLastKey->pNext = pKey;
}
PIK->uiKeys++;
i++;
}
}
static void hb_cdxTagTagLoad( LPTAGINFO pTag )
{
CDXHEADER pHeader;
HB_MACRO_PTR pMacro;
hb_cdxIndexPageRead( pTag->Owner, pTag->TagBlock, &pHeader, sizeof( CDXHEADER ) );
pTag->RootBlock = pHeader.Root;
if( pTag->RootBlock == 0 || pTag->RootBlock % CDX_BLOCK_SIZE > 0 ||
pTag->RootBlock > hb_fsSeek( pTag->Owner->DiskFile, 0, FS_END ) ||
pHeader.Key_Lgth > CDX_MAX_KEY )
return;
pTag->KeyLength = pHeader.Key_Lgth;
pTag->MaxKeys = ( CDX_BLOCK_SIZE - 12 ) / ( pTag->KeyLength + 8 );
pTag->OptFlags = pHeader.IndexOpts;
pTag->UniqueKey = ( pTag->OptFlags & 0x01 );
pTag->AscendKey = ( pHeader.AscDesc == 0 );
pTag->KeyExpr = ( char * ) hb_xgrab( CDX_MAX_KEY + 1 );
hb_strncpyUpper( pTag->KeyExpr, pHeader.KeyPool, CDX_MAX_KEY );
if( pTag->OptFlags < 0x80 && pTag->KeyExpr[ 0 ] == 0 )
return;
if( pTag->OptFlags & 0x80 )
return;
SELF_COMPILE( pTag->Owner->Owner, pTag->KeyExpr );
pTag->pKeyItem = pTag->Owner->Owner->valResult;
pTag->Owner->Owner->valResult = NULL;
pMacro = ( HB_MACRO_PTR ) hb_itemGetPtr( pTag->pKeyItem );
hb_macroRun( pMacro );
switch( hb_itemType( &hb_stack.Return ) )
{
case HB_IT_INTEGER:
case HB_IT_LONG:
case HB_IT_DOUBLE:
pTag->KeyType = 'N';
pTag->KeyLength = 10;
break;
case HB_IT_DATE:
pTag->KeyType = 'D';
pTag->KeyLength = 8;
break;
case HB_IT_LOGICAL:
pTag->KeyType = 'C';
pTag->KeyLength = 1;
break;
case HB_IT_STRING:
pTag->KeyType = 'C';
pTag->KeyLength = hb_stack.Return.item.asString.length > CDX_MAX_KEY ? CDX_MAX_KEY :
hb_stack.Return.item.asString.length;
break;
}
if( pHeader.KeyPool[ strlen( pTag->KeyExpr ) + 1 ] == NULL )
return;
pTag->ForExpr = ( char * ) hb_xgrab( CDX_MAX_KEY + 1 );
hb_strncpyUpper( pTag->ForExpr, pHeader.KeyPool +
strlen( pTag->KeyExpr ) + 1, CDX_MAX_KEY );
SELF_COMPILE( pTag->Owner->Owner, pTag->ForExpr );
pTag->pForItem = pTag->Owner->Owner->valResult;
pTag->Owner->Owner->valResult = NULL;
pMacro = ( HB_MACRO_PTR ) hb_itemGetPtr( pTag->pForItem );
hb_macroRun( pMacro );
if( hb_itemType( &hb_stack.Return ) != HB_IT_LOGICAL )
{
hb_macroDelete( pMacro );
hb_itemRelease( pTag->pForItem );
pTag->pForItem = NULL;
hb_xfree( pTag->ForExpr );
pTag->ForExpr = NULL;
}
}
static void hb_cdxTagSetRoot( LPTAGINFO pTag, LPPAGEINFO PIK )
{
LONG NRN, TmpTag;
LPKEYINFO p, TmpStr;
PIK->Owner = hb_cdxPageNew( pTag, NULL, 0 );
NRN = hb_cdxIndexGetAvailPage( pTag->Owner );
PIK->Owner->Page = NRN;
PIK->Owner->PageType = PAGE_ROOT;
if( PIK->uiKeys > 0 )
{
p = hb_cdxPageGetKey( PIK, PIK->uiKeys - 1 );
TmpTag = p->Tag;
p->Tag = PIK->Page;
hb_cdxPageInsertKey( PIK->Owner, p, TRUE );
p->Tag = TmpTag;
}
else
{
TmpStr = hb_cdxKeyNew();
TmpStr->Tag = PIK->Page;
hb_cdxPageInsertKey( PIK->Owner, TmpStr, TRUE );
hb_cdxKeyFree( TmpStr );
}
PIK->Owner->Child = PIK;
pTag->RootPage = PIK->Owner;
pTag->RootBlock = NRN;
pTag->TagChanged = TRUE;
}
static void hb_cdxTagIntNodeWrite( LPTAGINFO pTag, LONG PN, LPCDXDATA pData, LPPAGEINFO PIK )
{
USHORT Cnt, ck, kcnt, na;
LONG rp, lp, NPN, TmpTag;
LPKEYINFO p;
if( PIK->uiKeys > pTag->MaxKeys )
{
Cnt = PIK->uiKeys / 2;
Cnt = PIK->uiKeys - Cnt;
}
else
Cnt = PIK->uiKeys;
ck = 0;
kcnt = Cnt;
if( PIK->uiKeys > 0 )
{
pData->Entry_Ct = 0;
if( kcnt < PIK->uiKeys )
{
ck = hb_cdxTagFillInternalNode( pTag, pData, PIK, kcnt, ck, &p );
if( pData->Node_Atr % 2 > 0 )
pData->Node_Atr--;
na = pData->Node_Atr;
rp = pData->Rght_Ptr;
lp = pData->Left_Ptr;
pData->Rght_Ptr = PN;
NPN = hb_cdxIndexGetAvailPage( pTag->Owner );
TmpTag = p->Tag;
p->Tag = NPN;
hb_cdxPageAddNodeKey( PIK, p );
p->Tag = TmpTag;
if( PIK->PageType == PAGE_ROOT )
PIK->PageType = PAGE_NODE;
hb_cdxIndexPageWrite( pTag->Owner, NPN, pData, CDX_BLOCK_SIZE );
if( lp > 0 )
{
hb_cdxIndexPageRead( pTag->Owner, lp, pData, CDX_BLOCK_SIZE );
pData->Rght_Ptr = NPN;
hb_cdxIndexPageWrite( pTag->Owner, lp, pData, CDX_BLOCK_SIZE );
}
memset( pData, 32, CDX_BLOCK_SIZE );
pData->Node_Atr = na;
pData->Rght_Ptr = rp;
pData->Left_Ptr = NPN;
pData->Entry_Ct = 0;
kcnt = pTag->MaxKeys;
}
hb_cdxTagFillInternalNode( pTag, pData, PIK, kcnt, ck, &p );
}
hb_cdxIndexPageWrite( pTag->Owner, PN, pData, CDX_BLOCK_SIZE );
}
static USHORT hb_cdxTagFillInternalNode( LPTAGINFO pTag, LPCDXDATA pData,
LPPAGEINFO PIK, USHORT kcnt,
USHORT ck, LPKEYINFO * p )
{
USHORT i, v;
LONG r;
i = 0;
memset( pData->cdxu.Internal.IntData, ( pTag->KeyType == 'C' ) ? 32 : 0,
sizeof( pData->cdxu.Internal.IntData ) );
while( i < kcnt && ck < PIK->uiKeys )
{
* p = hb_cdxPageGetKey( PIK, ck );
v = i * ( pTag->KeyLength + 8 );
memcpy( &pData->cdxu.Internal.IntData[ v ],
( * p )->pItem->item.asString.value,
( * p )->pItem->item.asString.length );
v += pTag->KeyLength;
r = hb_cdxSwapBytes( ( * p )->Xtra );
memcpy( &pData->cdxu.Internal.IntData[ v ], &r, 4 );
r = hb_cdxSwapBytes( ( * p )->Tag );
memcpy( &pData->cdxu.Internal.IntData[ v + 4 ], &r, 4 );
i++;
ck++;
pData->Entry_Ct++;
}
return ck;
}
static void hb_cdxTagIntNodeBuild( LPTAGINFO pTag, LPCDXDATA pData, LPPAGEINFO pPage )
{
USHORT i, v;
LONG r, n;
LPKEYINFO pKey, pLastKey;
static char szBuffer[ CDX_MAX_KEY + 1 ];
i = 0;
while( i < pData->Entry_Ct )
{
v = i * ( pTag->KeyLength + 8 );
memmove( szBuffer, pData->cdxu.Internal.IntData + v, pTag->KeyLength );
szBuffer[ pTag->KeyLength ] = NULL;
v += pTag->KeyLength;
memcpy( &r, &pData->cdxu.Internal.IntData[ v ], 4 );
r = hb_cdxSwapBytes( r );
memcpy( &n, &pData->cdxu.Internal.IntData[ v + 4 ], 4 );
n = hb_cdxSwapBytes( n );
pKey = hb_cdxKeyNew();
if( pTag->KeyType == 'C' )
{
v = strlen( szBuffer );
while( v > 0 && szBuffer[ v - 1 ] == 32 )
v--;
szBuffer[ v ] = NULL;
}
else
{
printf( "hb_cdxTagIntNodeBuild()" );
}
hb_itemPutC( pKey->pItem, szBuffer );
pKey->Tag = n;
pKey->Xtra = r;
if( pPage->pKeys == NULL )
pPage->pKeys = pKey;
else
{
pLastKey = pPage->pKeys;
while( pLastKey->pNext != NULL )
pLastKey = pLastKey->pNext;
pLastKey->pNext = pKey;
}
pPage->uiKeys++;
i++;
}
}
static LONG hb_cdxTagKeyFind( LPTAGINFO pTag, LPKEYINFO pKey )
{
int K;
LPKEYINFO stot;
pTag->CurKeyInfo->Tag = 0;
hb_cdxTagTagOpen( pTag, 0 );
if( pTag->RootPage == NULL )
return 0;
stot = hb_cdxKeyNew();
hb_itemCopy( stot->pItem, pKey->pItem );
stot->Tag = pKey->Tag;
stot->Xtra = pKey->Xtra;
if( pTag->KeyType == 'C' )
{
while( stot->pItem->item.asString.length > 0 &&
stot->pItem->item.asString.value[ stot->pItem->item.asString.length - 1 ] == ' ' )
stot->pItem->item.asString.length--;
stot->pItem->item.asString.value[ stot->pItem->item.asString.length ] = NULL;
}
pTag->TagBOF = pTag->TagEOF = FALSE;
K = hb_cdxPageSeekKey( pTag->RootPage, stot->Tag, stot, FALSE );
hb_cdxKeyFree( stot );
if( K == 0 )
{
hb_cdxPageRetrieveKey( pTag->RootPage, pTag->CurKeyInfo );
if( pTag->pForItem == NULL )
return pTag->CurKeyInfo->Tag;
else
/* TODO: test for expression */
pTag->TagEOF = TRUE;
}
else if( K < 0 )
{
hb_cdxPageRetrieveKey( pTag->RootPage, pTag->CurKeyInfo );
if( pTag->pForItem != NULL )
/* TODO: test for expression */
pTag->TagEOF = TRUE;
}
else
pTag->TagEOF = TRUE;
return 0;
}
static LPPAGEINFO hb_cdxPageNew( LPTAGINFO PIT, LPPAGEINFO PIK, LONG FilePosn )
{
LPPAGEINFO pPage;
pPage = ( LPPAGEINFO ) hb_xgrab( sizeof( PAGEINFO ) );
memset( pPage, 0, sizeof( PAGEINFO ) );
pPage->Page = FilePosn;
pPage->Left = pPage->Right = -1;
pPage->Owner = PIK;
pPage->TagParent = PIT;
pPage->CurKey = -1;
if( FilePosn > 0 )
hb_cdxPagePageLoad( pPage );
return pPage;
}
static void hb_cdxPageFree( LPPAGEINFO pPage )
{
LPKEYINFO pKey;
if( pPage->Child != NULL )
{
hb_cdxPageFree( pPage->Child );
pPage->Child = NULL;
}
if( pPage->Changed )
hb_cdxPagePageStore( pPage );
if( pPage->NewRoot && pPage->Owner != NULL )
{
pPage->Owner->Child = NULL;
hb_cdxPageFree( pPage->Owner );
pPage->Owner = NULL;
}
pPage->NewRoot = FALSE;
if( pPage->Owner != NULL )
pPage->Owner->Child = NULL;
pPage->Owner = NULL;
/* Free all keys */
while( pPage->pKeys != NULL )
{
pKey = pPage->pKeys;
pPage->pKeys = pKey->pNext;
hb_cdxKeyFree( pKey );
}
hb_xfree( pPage );
}
static BOOL hb_cdxPageReadTopKey( LPPAGEINFO pPage )
{
LPKEYINFO pKey;
if( pPage->uiKeys == 0 )
return FALSE;
pPage->CurKey = 0;
pKey = pPage->pKeys;
if( pPage->PageType < PAGE_LEAF )
{
if( hb_cdxPageGetChild( pPage, pKey->Tag ) )
return hb_cdxPageReadTopKey( pPage->Child );
else
return FALSE;
}
else
{
hb_itemCopy( pPage->TagParent->CurKeyInfo->pItem, pKey->pItem );
pPage->TagParent->CurKeyInfo->Tag = pKey->Tag;
return TRUE;
}
}
static BOOL hb_cdxPageReadBottomKey( LPPAGEINFO pPage )
{
LPKEYINFO pKey;
if( pPage->uiKeys == 0 )
return FALSE;
pPage->CurKey = pPage->uiKeys - 1;
pKey = hb_cdxPageGetKey( pPage, pPage->CurKey );
if( pPage->PageType < PAGE_LEAF )
{
printf( "hb_cdxPageReadBottomKey()" );
return TRUE;
}
else
{
hb_itemCopy( pPage->TagParent->CurKeyInfo->pItem, pKey->pItem );
pPage->TagParent->CurKeyInfo->Tag = pKey->Tag;
return TRUE;
}
}
static int hb_cdxPageSeekKey( LPPAGEINFO pPage, LONG lBlock, LPKEYINFO pKey, BOOL bExact )
{
int k;
USHORT dav;
LPKEYINFO p;
k = 1;
bExact = ( bExact || pPage->TagParent->KeyType != 'C' );
pPage->CurKey = 0;
if( pPage->uiKeys > 0 )
{
while( k > 0 && pPage->CurKey < pPage->uiKeys )
{
p = hb_cdxPageGetKey( pPage, pPage->CurKey );
k = hb_cdxKeyCompare( pKey, p, &dav, bExact );
if( !pPage->TagParent->AscendKey )
k = -k;
if( k == 0 && lBlock == CDX_MAX_REC_NUM )
k = 1;
if( k == 0 && lBlock != CDX_IGNORE_REC_NUM )
{
if( lBlock > p->Xtra )
k = 1;
else if( lBlock < p->Xtra )
k = -1;
}
if( k <= 0 || pPage->CurKey == pPage->uiKeys - 1 )
{
if( pPage->PageType < PAGE_LEAF )
{
hb_cdxPageGetChild( pPage, p->Tag );
k = hb_cdxPageSeekKey( pPage->Child, lBlock, pKey, bExact );
}
else if( k == 0 && lBlock != CDX_IGNORE_REC_NUM )
{
if( lBlock > p->Tag )
k = 1;
else if( lBlock < p->Tag )
k = -1;
}
}
if( k > 0 )
pPage->CurKey++;
}
}
return k;
}
static void hb_cdxPageInsertKey( LPPAGEINFO pPage, LPKEYINFO pKey, BOOL bAddAfter )
{
USHORT uiCount;
LPKEYINFO pNewKey, pLastKey;
if( pPage->Child != NULL )
hb_cdxPageInsertKey( pPage->Child, pKey, bAddAfter );
else
{
pNewKey = hb_cdxKeyNew();
hb_itemCopy( pNewKey->pItem, pKey->pItem );
pNewKey->Tag = pKey->Tag;
pNewKey->Xtra = pKey->Xtra;
if( bAddAfter )
pPage->CurKey++;
if( pPage->CurKey > pPage->uiKeys )
pPage->CurKey = pPage->uiKeys;
if( pPage->CurKey < 0 )
pPage->CurKey = 0;
if( pPage->Owner != NULL && pPage->CurKey >= pPage->uiKeys )
printf( "hb_cdxPageInsertKey()" );
if( pPage->pKeys == NULL )
pPage->pKeys = pNewKey;
else
{
if( pPage->CurKey == 0 )
{
pNewKey->pNext = pPage->pKeys;
pPage->pKeys = pNewKey;
}
else
{
uiCount = pPage->CurKey;
pLastKey = pPage->pKeys;
while( uiCount > 1 && pLastKey->pNext )
{
pLastKey = pLastKey->pNext;
uiCount--;
}
pNewKey->pNext = pLastKey->pNext;
pLastKey->pNext = pNewKey;
}
}
pPage->uiKeys++;
pPage->Changed = TRUE;
}
}
static void hb_cdxPagePageStore( LPPAGEINFO pPage )
{
if( pPage->Page == 0 )
pPage->Page = hb_cdxIndexGetAvailPage( pPage->TagParent->Owner );
hb_cdxTagPageStore( pPage->TagParent, pPage );
pPage->Changed = FALSE;
}
static BOOL hb_cdxPageReadNextKey( LPPAGEINFO pPage )
{
BOOL b;
LPKEYINFO p;
if( pPage->uiKeys == 0 )
return FALSE;
if( pPage->PageType < PAGE_LEAF )
{
b = FALSE;
while( ! b && pPage->CurKey < pPage->uiKeys )
{
p = hb_cdxPageGetKey( pPage, pPage->CurKey );
if( hb_cdxPageGetChild( pPage, p->Tag ) )
{
if( pPage->Child->CurKey == -1 )
{
if( pPage->Child->PageType < PAGE_LEAF )
pPage->Child->CurKey = 0;
}
b = hb_cdxPageReadNextKey( pPage->Child );
}
else
b = FALSE;
if( !b )
pPage->CurKey++;
}
if( !b )
pPage->CurKey = pPage->uiKeys;
return b;
}
else
{
pPage->CurKey++;
if( pPage->CurKey < pPage->uiKeys )
{
p = hb_cdxPageGetKey( pPage, pPage->CurKey );
hb_itemCopy( pPage->TagParent->CurKeyInfo->pItem, p->pItem );
pPage->TagParent->CurKeyInfo->Tag = p->Tag;
return TRUE;
}
else
{
pPage->CurKey = pPage->uiKeys;
return FALSE;
}
}
}
static LPKEYINFO hb_cdxPageGetKey( LPPAGEINFO pPage, USHORT uiKey )
{
LPKEYINFO pKey;
pKey = pPage->pKeys;
while( uiKey > 0 && pKey->pNext != NULL )
{
pKey = pKey->pNext;
uiKey--;
}
return pKey;
}
static void hb_cdxPagePageLoad( LPPAGEINFO pPage )
{
LPKEYINFO pKey;
while( pPage->pKeys != NULL )
{
pKey = pPage->pKeys;
pPage->pKeys = pPage->pKeys->pNext;
hb_cdxKeyFree( pKey );
}
pPage->uiKeys = 0;
hb_cdxTagPageLoad( pPage->TagParent, pPage );
pPage->Changed = FALSE;
}
static int hb_cdxPageRetrieveKey( LPPAGEINFO pPage, LPKEYINFO pKey )
{
int iCheck;
LPKEYINFO pNewKey;
if( pPage->Owner == NULL )
pPage->ChkBOF = pPage->ChkEOF = TRUE;
pPage->ChkBOF = ( pPage->ChkBOF && pPage->CurKey == 0 );
pPage->ChkEOF = ( pPage->ChkEOF && pPage->CurKey == pPage->uiKeys - 1 );
if( pPage->Child != NULL )
return hb_cdxPageRetrieveKey( pPage->Child, pKey );
else
{
pNewKey = hb_cdxPageGetKey( pPage, pPage->CurKey );
hb_itemCopy( pKey->pItem, pNewKey->pItem );
pKey->Tag = pNewKey->Tag;
iCheck = 0;
if( pPage->ChkBOF )
iCheck = 1;
if( pPage->ChkEOF )
iCheck += 2;
return iCheck;
}
}
static void hb_cdxPageAddNodeKey( LPPAGEINFO pPage, LPKEYINFO pKey )
{
if( pPage->Owner == NULL )
{
hb_cdxTagSetRoot( pPage->TagParent, pPage );
pPage->NewRoot = TRUE;
}
pPage->Owner->CurKey = hb_cdxPageSeekNodeTag( pPage->Owner, pPage->Page );
pPage->Owner->Child = NULL;
hb_cdxPageInsertKey( pPage->Owner, pKey, FALSE );
pPage->Owner->CurKey++;
pPage->Owner->Child = pPage;
pPage->Reload = TRUE;
}
static int hb_cdxPageSeekNodeTag( LPPAGEINFO pPage, LONG Tag )
{
int iSeek;
USHORT i;
LPKEYINFO p;
if( pPage->uiKeys == 0 )
return -1;
else
{
iSeek = -1;
i = 0;
while( iSeek < 0 && i < pPage->uiKeys )
{
p = hb_cdxPageGetKey( pPage, i );
if( p->Tag == Tag )
iSeek = i;
i++;
}
return iSeek;
}
}
static BOOL hb_cdxPageGetChild( LPPAGEINFO pPage, LONG Tag )
{
if( Tag == 0 )
return FALSE;
if( pPage->TagParent->Owner->NextAvail > 0 &&
Tag > pPage->TagParent->Owner->NextAvail )
return FALSE;
if( pPage->PageType < PAGE_LEAF )
{
if( pPage->Child != NULL )
{
if( pPage->Child->Page != Tag || pPage->Child->Reload )
{
hb_cdxPageFree( pPage->Child );
pPage->Child = NULL;
}
}
if( pPage->Child == NULL )
pPage->Child = hb_cdxPageNew( pPage->TagParent, pPage, Tag );
}
return ( pPage->Child != NULL );
}
static void hb_cdxPageDeleteKey( LPPAGEINFO pPage )
{
BOOL lastone;
LONG TempTag;
LPKEYINFO p, pPrevKey;
pPage->Changed = TRUE;
if( pPage->Child != NULL )
hb_cdxPageDeleteKey( pPage->Child );
else
{
lastone = ( pPage->CurKey >= pPage->uiKeys - 1 );
p = hb_cdxPageGetKey( pPage, pPage->CurKey );
if( pPage->pKeys == p )
pPage->pKeys = p->pNext;
else
{
pPrevKey = hb_cdxPageGetKey( pPage, pPage->CurKey - 1 );
pPrevKey->pNext = p->pNext;
}
pPage->uiKeys--;
hb_cdxKeyFree( p );
if( pPage->CurKey >= pPage->uiKeys )
pPage->CurKey = pPage->uiKeys - 1;
if( pPage->CurKey < 0 )
pPage->CurKey = 0;
if( lastone && pPage->Owner != NULL )
{
if( pPage->uiKeys > 0 )
{
p = hb_cdxPageGetKey( pPage, pPage->CurKey );
TempTag = p->Tag;
p->Tag = pPage->Page;
printf( "ReplaceNodeKey();" );
p->Tag = TempTag;
}
else
printf( "DeleteNodeKey();" );
}
}
}
static LPINDEXINFO hb_cdxIndexNew( AREAP pArea )
{
LPINDEXINFO pIndex;
pIndex = ( LPINDEXINFO ) hb_xgrab( sizeof( INDEXINFO ) );
memset( pIndex, 0, sizeof( INDEXINFO ) );
pIndex->DiskFile = FS_ERROR;
pIndex->Owner = pArea;
pIndex->NextAvail = -1;
return pIndex;
}
static void hb_cdxIndexFree( LPINDEXINFO pIndex )
{
LPTAGINFO pTag;
/* Free Compound tag */
if( pIndex->CompoundTag != NULL )
{
hb_cdxTagTagClose( pIndex->CompoundTag );
hb_cdxTagFree( pIndex->CompoundTag );
}
/* Free all tags */
while( pIndex->TagList )
{
pTag = pIndex->TagList;
pIndex->TagList = pTag->pNext;
hb_cdxTagFree( pTag );
}
/* Close file */
if( pIndex->DiskFile != FS_ERROR )
hb_fsClose( pIndex->DiskFile );
hb_xfree( pIndex );
}
static LONG hb_cdxIndexGetAvailPage( LPINDEXINFO pIndex )
{
if( pIndex->NextAvail == -1 )
hb_cdxIndexResetAvailPage( pIndex );
pIndex->NextAvail += CDX_BLOCK_SIZE;
return pIndex->NextAvail - CDX_BLOCK_SIZE;
}
static void hb_cdxIndexResetAvailPage( LPINDEXINFO pIndex )
{
pIndex->NextAvail = hb_fsSeek( pIndex->DiskFile, 0, FS_END );
}
static void hb_cdxIndexPageRead( LPINDEXINFO pIndex, LONG lPos, void * pBuffer,
USHORT uiSize )
{
if( hb_fsSeek( pIndex->DiskFile, lPos, FS_SET ) == lPos )
hb_fsRead( pIndex->DiskFile, ( BYTE * ) pBuffer, uiSize );
}
static void hb_cdxIndexPageWrite( LPINDEXINFO pIndex, LONG lPos, void * pBuffer,
USHORT uiSize )
{
if( hb_fsSeek( pIndex->DiskFile, lPos, FS_SET ) == lPos )
hb_fsWrite( pIndex->DiskFile, ( BYTE * ) pBuffer, uiSize );
}
static void hb_cdxIndexAddTag( LPINDEXINFO pIndex, char * szTagName, char * szKeyExp,
PHB_ITEM pKeyItem, BYTE bType, USHORT uiLen, char * szForExp,
PHB_ITEM pForItem, BOOL bAscending, BOOL bUnique )
{
LPTAGINFO pTag, pLastTag;
LPKEYINFO pKey;
hb_cdxTagTagOpen( pIndex->CompoundTag, 0 );
pKey = hb_cdxKeyNew();
hb_itemPutC( pKey->pItem, szTagName );
pTag = pIndex->TagList;
pLastTag = NULL;
while( pTag != NULL )
{
if( hb_stricmp( pTag->TagName, szTagName ) == 0 )
{
pKey->Tag = pTag->TagBlock;
if( hb_cdxTagKeyFind( pIndex->CompoundTag, pKey ) > 0 )
hb_cdxPageDeleteKey( pIndex->CompoundTag->RootPage );
if( pLastTag == NULL )
pIndex->TagList = pTag->pNext;
else
pLastTag->pNext = pTag->pNext;
hb_cdxTagFree( pTag );
break;
}
pLastTag = pTag;
pTag = pTag->pNext;
}
/* Create new tag an add to tag list */
pTag = hb_cdxTagNew( pIndex, szTagName, -1 );
if( pIndex->TagList == NULL )
pIndex->TagList = pTag;
else
{
pLastTag = pIndex->TagList;
while( pLastTag->pNext )
pLastTag = pLastTag->pNext;
pLastTag->pNext = pTag;
}
hb_cdxTagIndexTagNew( pTag, szKeyExp, pKeyItem, bType, uiLen, szForExp,
pForItem, bAscending, bUnique );
hb_itemPutC( pKey->pItem, pTag->TagName );
pKey->Tag = pTag->TagBlock;
hb_cdxTagKeyAdd( pIndex->CompoundTag, pKey );
hb_cdxKeyFree( pKey );
pIndex->CompoundTag->RootPage->Changed = TRUE;
hb_cdxTagTagClose( pIndex->CompoundTag );
}
static LPSORTINFO hb_cdxSortNew( LPTAGINFO pTag, BOOL bUnique )
{
BYTE * P;
LPSORTINFO pSort;
pSort = ( LPSORTINFO ) hb_xgrab( sizeof( SORTINFO ) );
memset( pSort, 0, sizeof( SORTINFO ) );
pSort->SortChunk = SORT_CHUNK_LIMIT;
pSort->NodeLimit = pSort->SortChunk / sizeof( SORTDATA );
pSort->NodeMask = pSort->NodeShift = pSort->NodeCur = 1;
pSort->ChunkLimit = 0x8000;
while( pSort->NodeMask < pSort->NodeLimit - 1 )
{
pSort->NodeMask = ( pSort->NodeMask << 1 ) + 1;
pSort->ChunkLimit >>= 1;
pSort->NodeShift++;
}
pSort->ChunkSize = pSort->ChunkLimit;
pSort->ChunkList = hb_xgrab( pSort->ChunkSize * sizeof( LONG ) );
memset( pSort->ChunkList, 0, pSort->ChunkSize * sizeof( LONG ) );
P = hb_xgrab( pSort->SortChunk * sizeof( BYTE ) );
memset( P, 0, pSort->SortChunk * sizeof( BYTE ) );
pSort->ChunkList[ 0 ] = ( LONG ) P;
hb_cdxSortLinkNew( pSort, &pSort->RootLink );
pSort->Unique = bUnique;
pSort->Ascend = TRUE;
pSort->CurTag = pTag;
pSort->KeyTot = pTag->Owner->Owner->lpExtendInfo->ulRecCount;
pSort->KeyWork = hb_cdxKeyNew();
pSort->LastKey = hb_cdxKeyNew();
return pSort;
}
static void hb_cdxSortFree( LPSORTINFO pSort )
{
USHORT usCount;
LONG pa;
pSort->Closing = TRUE;
for( usCount = 0; usCount <= 30; usCount++ )
{
if( pSort->NodeList[ usCount ] != NULL )
{
pa = pSort->NodeList[ usCount ]->Rght_Ptr;
pSort->NodeList[ usCount ]->Rght_Ptr = -1;
if( pSort->NodeList[ usCount ]->Entry_Ct > 0 )
{
if( pSort->NodeList[ usCount + 1 ] == NULL )
{
pSort->CurTag->RootBlock = pa;
pSort->NodeList[ usCount ]->Node_Atr++;
}
hb_cdxIndexPageWrite( pSort->CurTag->Owner, pa, pSort->NodeList[ usCount ],
sizeof( CDXDATA ) );
if( pSort->NodeList[ usCount + 1 ] != NULL )
hb_cdxSortAddToNode( pSort, ( USHORT ) ( usCount + 1 ), pa,
pSort->LastTag, pSort->KeyWork );
}
hb_xfree( ( LPCDXDATA ) pSort->NodeList[ usCount ] );
}
}
if( pSort->ChunkList != NULL )
{
for( usCount = 0; usCount < pSort->ChunkLimit; usCount++ )
{
if( pSort->ChunkList[ usCount ] != NULL )
hb_xfree( ( BYTE * ) pSort->ChunkList[ usCount ] );
}
hb_xfree( pSort->ChunkList );
}
hb_cdxKeyFree( pSort->KeyWork );
hb_cdxKeyFree( pSort->LastKey );
hb_xfree( pSort );
}
static void hb_cdxSortLinkNew( LPSORTINFO pSort, LONG * NewLink )
{
if( pSort->NodeCur >= pSort->NodeLimit )
hb_cdxSortGetNewChunk( pSort );
* NewLink = ( pSort->ChunkCur << pSort->NodeShift ) + pSort->NodeCur;
pSort->NodeCur++;
}
static void hb_cdxSortGetNewChunk( LPSORTINFO pSort )
{
BYTE * P;
pSort->ChunkCur++;
if( pSort->ChunkCur == pSort->ChunkLimit )
{
printf( "FlushChunks();" );
return;
}
P = ( BYTE * ) pSort->ChunkList[ pSort->ChunkCur ];
if( P == NULL )
P = hb_xgrab( pSort->SortChunk * sizeof( BYTE ) );
if( pSort->ChunkCur != 0 )
{
memset( P, 0, pSort->SortChunk * sizeof( BYTE ) );
pSort->ChunkList[ pSort->ChunkCur ] = ( LONG ) P;
pSort->NodeCur = 0;
}
}
static void hb_cdxSortInsertWord( LPSORTINFO pSort, LONG Tag, char * Value )
{
char s[ 34 ];
USHORT w, cc, nc, EOK;
SHORT v;
LPSORTDATA wx;
hb_cdxltoa( Tag, s + 1, 10 );
w = strlen( Value );
if( pSort->NodeLimit - pSort->NodeCur < w + strlen( s + 1 ) + 1 )
{
cc = pSort->ChunkCur;
nc = pSort->NodeCur;
hb_cdxSortGetNewChunk( pSort );
if( pSort->ChunkCur > 0 )
{
pSort->ChunkCur = cc;
pSort->NodeCur = nc;
}
}
pSort->WordCount++;
strcpy( pSort->WPch, Value );
v = strlen( pSort->WPch );
if( v > 0 )
{
if( v > pSort->KeySize )
pSort->KeySize = v;
v--;
}
while( v >= 0 && pSort->WPch[ v ] == ' ' )
{
pSort->WPch[ v ] = NULL;
v--;
}
v++;
EOK = v;
if( !pSort->Unique )
{
s[ 0 ] = ( char ) strlen( s + 1 );
memcpy( &pSort->WPch[ v ], s, s[ 0 ] + 1 );
v += ( SHORT ) ( s[ 0 ] + 1 );
pSort->WPch[ v ] = NULL;
}
pSort->LevelPtr = pSort->RootLink;
pSort->PriorPtr = 0;
pSort->WCur = 0;
do
hb_cdxSortStuffKey( pSort, &wx );
while( pSort->WPch[ pSort->WCur ] != 0 );
if( pSort->Unique )
{
if( wx->sortu.A.NUse == SORT_END_OF_KEY )
return;
wx->sortu.A.NUse = SORT_END_OF_KEY;
if( EOK == 0 )
EOK++;
memcpy( &pSort->WPch[ EOK ], s, s[ 0 ] + 1 );
v = EOK + s[ 0 ] + 1;
pSort->WPch[ v ] = NULL;
do
hb_cdxSortStuffKey( pSort, &wx );
while( pSort->WPch[ pSort->WCur ] != 0 );
}
wx->sortu.A.NUse = SORT_END_OF_WORD;
}
static void hb_cdxSortStuffKey( LPSORTINFO pSort, LPSORTDATA * wx )
{
USHORT w;
SHORT v;
LONG p1;
LPSORTDATA x;
hb_cdxSortGetNode( pSort, pSort->WPch[ pSort->WCur ], &p1 );
* wx = hb_cdxSortLinkGet( pSort, p1 );
pSort->WCur++;
if( pSort->LevelPtr == 0 )
{
if( pSort->PriorPtr > 0 )
{
x = hb_cdxSortLinkGet( pSort, pSort->PriorPtr );
x->sortu.A.WordArray = p1;
}
w = strlen( pSort->WPch );
v = w - pSort->WCur - 1;
if( v > 0 )
{
if( v > 4 )
v = 4;
memcpy( ( * wx )->sortu.B.ChrStack, &pSort->WPch[ pSort->WCur ], v );
( * wx )->sortu.A.NUse = SORT_STACK_OF_CHAR;
pSort->WCur += v;
}
}
pSort->PriorPtr = p1;
pSort->LevelPtr = ( * wx )->sortu.A.WordArray;
}
static void hb_cdxSortGetNode( LPSORTINFO pSort, char Character, LONG * NewLink )
{
char c;
int df;
LONG p, q, r;
LPSORTDATA px, qx, rx;
if( pSort->LevelPtr == 0 )
{
hb_cdxSortLinkNew( pSort, NewLink );
px = hb_cdxSortLinkGet( pSort, * NewLink );
px->sortu.A.Character = Character;
return;
}
p = pSort->LevelPtr;
px = hb_cdxSortLinkGet( pSort, pSort->LevelPtr );
q = pSort->PriorPtr;
if( px->sortu.A.NUse == SORT_STACK_OF_CHAR )
{
hb_cdxSortLinkNew( pSort, &r );
c = px->sortu.A.Character;
qx = hb_cdxSortLinkGet( pSort, q );
qx->sortu.A.WordArray = r;
rx = hb_cdxSortLinkGet( pSort, r );
rx->sortu.A.Character = c;
rx->sortu.A.WordArray = p;
px = hb_cdxSortLinkGet( pSort, p );
px->sortu.A.Character = px->sortu.B.ChrStack[ 0 ];
memmove( &px->sortu.B.ChrStack[ 0 ], &px->sortu.B.ChrStack[ 1 ], 3 );
px->sortu.B.ChrStack[ 3 ] = NULL;
if( px->sortu.C.ChrFill != 0 )
px->sortu.A.NUse = SORT_STACK_OF_CHAR;
else
px->sortu.A.NUse = SORT_ACTIVE_LIST;
p = r;
px = hb_cdxSortLinkGet( pSort, p );
}
if( Character > px->sortu.A.Character )
df = 1;
else if( Character < px->sortu.A.Character )
df = -1;
else
df = 0;
if( !pSort->Ascend && Character > 0 && px->sortu.A.Character > 0 )
df = -df;
while( px->sortu.A.LevelLink != 0 && df > 0 )
{
q = p;
p = px->sortu.A.LevelLink;
px = hb_cdxSortLinkGet( pSort, p );
if( px->sortu.A.NUse == SORT_STACK_OF_CHAR )
{
hb_cdxSortLinkNew( pSort, &r );
c = px->sortu.A.Character;
qx = hb_cdxSortLinkGet( pSort, q );
qx->sortu.A.WordArray = r;
rx = hb_cdxSortLinkGet( pSort, r );
rx->sortu.A.Character = c;
rx->sortu.A.WordArray = p;
px = hb_cdxSortLinkGet( pSort, p );
px->sortu.A.Character = px->sortu.B.ChrStack[ 0 ];
memmove( &px->sortu.B.ChrStack[ 0 ], &px->sortu.B.ChrStack[ 1 ], 3 );
px->sortu.B.ChrStack[ 3 ] = NULL;
if( px->sortu.C.ChrFill != 0 )
px->sortu.A.NUse = SORT_STACK_OF_CHAR;
else
px->sortu.A.NUse = SORT_ACTIVE_LIST;
p = r;
px = hb_cdxSortLinkGet( pSort, p );
}
if( Character > px->sortu.A.Character )
df = 1;
else if( Character < px->sortu.A.Character )
df = -1;
else
df = 0;
if( !pSort->Ascend && Character > 0 && px->sortu.A.Character > 0 )
df = -df;
}
if( df == 0 )
* NewLink = p;
else
{
hb_cdxSortLinkNew( pSort, &r );
if( df == -1 )
{
qx = hb_cdxSortLinkGet( pSort, q );
if( q == pSort->PriorPtr )
qx->sortu.A.WordArray = r;
else
qx->sortu.A.LevelLink = r;
}
else
{
p = px->sortu.A.LevelLink;
px->sortu.A.LevelLink = r;
}
rx = hb_cdxSortLinkGet( pSort, r );
rx->sortu.A.LevelLink = p;
rx->sortu.A.Character = Character;
* NewLink = r;
}
}
static LPSORTDATA hb_cdxSortLinkGet( LPSORTINFO pSort, LONG Value )
{
LPSORTDATA P;
if( Value > 0 )
{
P = ( LPSORTDATA ) pSort->ChunkList[ Value >> pSort->NodeShift ];
if( P != NULL )
return &P[ Value & pSort->NodeMask ];
else
return NULL;
}
return NULL;
}
static void hb_cdxSortDisplayWord( LPSORTINFO pSort )
{
pSort->WPch[ 0 ] = NULL;
hb_cdxSortRecurseDict( pSort, pSort->RootLink, 0 );
}
static void hb_cdxSortRecurseDict( LPSORTINFO pSort, LONG WPtr, LONG WBgn )
{
USHORT WCnt;
if( WPtr == 0 )
return;
WCnt = strlen( pSort->WPch );
pSort->WAdr = hb_cdxSortLinkGet( pSort, WPtr );
if( pSort->WAdr->sortu.A.Character != 0 )
{
pSort->WPch[ WCnt ] = pSort->WAdr->sortu.A.Character;
pSort->WPch[ WCnt + 1 ] = NULL;
}
if( pSort->WAdr->sortu.A.NUse == SORT_STACK_OF_CHAR )
{
memcpy( &pSort->WPch[ strlen( pSort->WPch ) ], pSort->WAdr->sortu.B.ChrStack, 4 );
pSort->WPch[ WCnt + 5 ] = NULL;
}
if( pSort->WAdr->sortu.A.NUse == SORT_END_OF_WORD )
hb_cdxSortSendWord( pSort, pSort->WPch );
else
{
if( pSort->WAdr->sortu.A.WordArray != 0 )
hb_cdxSortRecurseDict( pSort, pSort->WAdr->sortu.A.WordArray, WBgn );
pSort->WAdr = hb_cdxSortLinkGet( pSort, WPtr );
}
pSort->WPch[ WCnt ] = NULL;
if( pSort->WAdr->sortu.A.LevelLink != 0 && pSort->WAdr->sortu.A.NUse != SORT_STACK_OF_CHAR )
hb_cdxSortRecurseDict( pSort, pSort->WAdr->sortu.A.LevelLink, WCnt );
}
static void hb_cdxSortSendWord( LPSORTINFO pSort, char * Value )
{
LONG Tag;
BYTE OldByte;
char * pce;
pce = Value + strlen( Value ) - 1;
while( pce[ 0 ] > 31 )
pce--;
Tag = atol( pce + 1 );
OldByte = pce[ 0 ];
pce[ 0 ] = NULL;
hb_cdxSortOutputWord( pSort, Tag, Value );
pce[ 0 ] = OldByte;
}
static void hb_cdxSortOutputWord( LPSORTINFO pSort, LONG Tag, char * Value )
{
pSort->KeyCnt++;
hb_itemPutC( pSort->KeyWork->pItem, Value );
if( pSort->CurTag->KeyType != 'C' )
printf( "pSort->CurTag->AdjustValue( &KeyWork );" );
hb_cdxSortAddToNode( pSort, 0, Tag, Tag, pSort->KeyWork );
pSort->LastTag = Tag;
hb_itemCopy( pSort->LastKey->pItem, pSort->KeyWork->pItem );
}
static void hb_cdxSortAddToNode( LPSORTINFO pSort, USHORT Lvl, LONG Tag,
LONG Link, LPKEYINFO Value )
{
USHORT i, bitcnt;
LONG sr;
if( pSort->NodeList[ Lvl ] == NULL )
{
pSort->NodeList[ Lvl ] = ( LPCDXDATA ) hb_xgrab( sizeof( CDXDATA ) );
memset( pSort->NodeList[ Lvl ], 0, sizeof( CDXDATA ) );
if( Lvl == 0 )
{
sr = pSort->KeyTot;
i = pSort->CurTag->KeyLength;
for( bitcnt = 0; i; bitcnt++, i >>= 1 );
pSort->NodeList[ 0 ]->cdxu.External.ShortBytes = 3;
pSort->NodeList[ 0 ]->cdxu.External.RecNumBits = 24 - bitcnt * 2;
pSort->NodeList[ 0 ]->cdxu.External.RecNumMask =
hb_cdxMakeMask( pSort->NodeList[ 0 ]->cdxu.External.RecNumBits );
while( sr > pSort->NodeList[ 0 ]->cdxu.External.RecNumMask )
{
pSort->NodeList[ 0 ]->cdxu.External.ShortBytes++;
pSort->NodeList[ 0 ]->cdxu.External.RecNumBits += 8;
pSort->NodeList[ 0 ]->cdxu.External.RecNumMask =
( pSort->NodeList[ 0 ]->cdxu.External.RecNumMask << 8 ) | 0xFF;
}
pSort->NodeList[ 0 ]->cdxu.External.FreeSpace = CDX_EXTERNAL_SPACE;
pSort->NodeList[ 0 ]->cdxu.External.DupCntBits =
pSort->NodeList[ 0 ]->cdxu.External.TrlCntBits = bitcnt;
pSort->NodeList[ 0 ]->cdxu.External.DupCntMask =
hb_cdxMakeMask( pSort->NodeList[ 0 ]->cdxu.External.DupCntBits );
pSort->NodeList[ 0 ]->cdxu.External.TrlCntMask =
hb_cdxMakeMask( pSort->NodeList[ 0 ]->cdxu.External.TrlCntBits );
}
pSort->NodeList[ Lvl ]->Left_Ptr = -1;
pSort->NodeList[ Lvl ]->Rght_Ptr = hb_cdxIndexGetAvailPage( pSort->CurTag->Owner );
pSort->NodeList[ Lvl ]->Node_Atr = ( Lvl == 0 ) ? 2 : 0;
}
if( Lvl == 0 )
hb_cdxSortAddExternal( pSort, Lvl, Tag, Link, Value );
else
hb_cdxSortAddInternal( pSort, Lvl, Tag, Link, Value );
}
static void hb_cdxSortAddExternal( LPSORTINFO pSort, USHORT Lvl, LONG Tag, LONG Link,
LPKEYINFO Value )
{
USHORT k, ct, cd, v, c;
LONG m, r, pa;
if( pSort->NodeList[ Lvl ]->Entry_Ct == 0 )
{
memset( pSort->NodeList[ Lvl ]->cdxu.External.ExtData, 0,
sizeof( pSort->NodeList[ Lvl ]->cdxu.External.ExtData ) );
pSort->NodeList[ Lvl ]->cdxu.External.FreeSpace = CDX_EXTERNAL_SPACE;
hb_itemPutC( pSort->LastKey->pItem, "" );
}
m = ~pSort->NodeList[ Lvl ]->cdxu.External.RecNumMask;
ct = ( USHORT ) ( pSort->CurTag->KeyLength -
Value->pItem->item.asString.length );
hb_cdxKeyCompare( Value, pSort->LastKey, &cd, TRUE );
if( cd > 0 )
cd -= ( USHORT ) 1;
v = ( USHORT ) ( pSort->NodeList[ Lvl ]->Entry_Ct *
pSort->NodeList[ Lvl ]->cdxu.External.ShortBytes );
k = ( USHORT ) ( pSort->NodeList[ Lvl ]->cdxu.External.FreeSpace + v );
pSort->NodeList[ Lvl ]->cdxu.External.FreeSpace -=
( USHORT ) ( pSort->CurTag->KeyLength +
pSort->NodeList[ Lvl ]->cdxu.External.ShortBytes - cd - ct );
c = ( USHORT ) ( ( ct << ( 16 - pSort->NodeList[ Lvl ]->cdxu.External.TrlCntBits ) ) |
( cd << ( 16 - pSort->NodeList[ Lvl ]->cdxu.External.TrlCntBits -
pSort->NodeList[ Lvl ]->cdxu.External.DupCntBits ) ) );
memcpy( &pSort->NodeList[ Lvl ]->cdxu.External.ExtData[ v +
pSort->NodeList[ Lvl ]->cdxu.External.ShortBytes - 2 ], &c, 2 );
memcpy( &r, &pSort->NodeList[ Lvl ]->cdxu.External.ExtData[ v ], 4 );
r &= m;
r |= Tag;
memcpy( &pSort->NodeList[ Lvl ]->cdxu.External.ExtData[ v ], &r, 4 );
k -= ( USHORT ) ( pSort->CurTag->KeyLength - cd - ct );
if( pSort->CurTag->KeyLength - cd - ct > 0 )
memcpy( &pSort->NodeList[ Lvl ]->cdxu.External.ExtData[ k ],
Value->pItem->item.asString.value + cd,
pSort->CurTag->KeyLength - cd - ct );
pSort->NodeList[ Lvl ]->Entry_Ct++;
if( pSort->NodeList[ Lvl ]->cdxu.External.FreeSpace <
( pSort->CurTag->KeyLength + 8 +
pSort->NodeList[ Lvl ]->cdxu.External.ShortBytes ) * 2 )
{
pa = pSort->NodeList[ Lvl ]->Rght_Ptr;
if( pSort->KeyCnt < pSort->KeyTot )
pSort->NodeList[ Lvl ]->Rght_Ptr = hb_cdxIndexGetAvailPage( pSort->CurTag->Owner );
else
pSort->NodeList[ Lvl ]->Rght_Ptr = -1;
pSort->NodeList[ Lvl ]->Node_Atr = 2;
hb_cdxIndexPageWrite( pSort->CurTag->Owner, pa, pSort->NodeList[ Lvl ],
sizeof( CDXDATA ) );
pSort->NodeList[ Lvl ]->Left_Ptr = pa;
hb_cdxSortAddToNode( pSort, ( USHORT ) ( Lvl + 1 ), pa, Link, Value );
pSort->NodeList[ Lvl ]->Entry_Ct = 0;
}
}
static void hb_cdxSortAddInternal( LPSORTINFO pSort, USHORT Lvl, LONG Tag, LONG Link,
LPKEYINFO Value )
{
USHORT v;
LONG r, pa;
if( pSort->NodeList[ Lvl ]->Entry_Ct == 0 )
memset( pSort->NodeList[ Lvl ]->cdxu.Internal.IntData,
pSort->CurTag->KeyType == 'C' ? 32 : 0,
sizeof( pSort->NodeList[ Lvl ]->cdxu.Internal.IntData ) );
v = ( USHORT ) ( pSort->NodeList[ Lvl ]->Entry_Ct *
( pSort->CurTag->KeyLength + 8 ) );
memcpy( &pSort->NodeList[ Lvl ]->cdxu.Internal.IntData[ v ],
Value->pItem->item.asString.value, Value->pItem->item.asString.length );
v += pSort->CurTag->KeyLength;
r = hb_cdxSwapBytes( Link );
memcpy( &pSort->NodeList[ Lvl ]->cdxu.Internal.IntData[ v ], &r, 4 );
r = hb_cdxSwapBytes( Tag );
memcpy( &pSort->NodeList[ Lvl ]->cdxu.Internal.IntData[ v + 4 ], &r, 4 );
pSort->NodeList[ Lvl ]->Entry_Ct++;
if( pSort->NodeList[ Lvl ]->Entry_Ct >= pSort->CurTag->MaxKeys )
{
pa = pSort->NodeList[ Lvl ]->Rght_Ptr;
if( !pSort->Closing )
pSort->NodeList[ Lvl ]->Rght_Ptr = hb_cdxIndexGetAvailPage( pSort->CurTag->Owner );
else
pSort->NodeList[ Lvl ]->Rght_Ptr = -1;
pSort->NodeList[ Lvl ]->Node_Atr = 0;
hb_cdxIndexPageWrite( pSort->CurTag->Owner, pa, pSort->NodeList[ Lvl ],
sizeof( CDXDATA ) );
pSort->NodeList[ Lvl ]->Left_Ptr = pa;
hb_cdxSortAddToNode( pSort, ( USHORT ) ( Lvl + 1 ), pa, Link, Value );
pSort->NodeList[ Lvl ]->Entry_Ct = 0;
}
}
/*
* -- CDX METHODS --
*/
#define cdxBof NULL
#define cdxEof NULL
#define cdxFound NULL
#define cdxGoBottom NULL
#define cdxGoTo NULL
#define cdxGoToId NULL
#define cdxGoTop NULL
#define cdxSkip NULL
#define cdxSkipFilter NULL
#define cdxSkipRaw NULL
#define cdxAddField NULL
#define cdxAppend NULL
#define cdxCreateFields NULL
#define cdxDeleteRec NULL
#define cdxDeleted NULL
#define cdxFieldCount NULL
#define cdxFieldDisplay NULL
#define cdxFieldInfo NULL
#define cdxFieldName NULL
#define cdxFlush NULL
#define cdxGetRec NULL
#define cdxGetValue NULL
#define cdxGetVarLen NULL
#define cdxGoCold NULL
#define cdxGoHot NULL
#define cdxPutRec NULL
#define cdxPutValue NULL
#define cdxRecAll NULL
#define cdxRecCount NULL
#define cdxRecInfo NULL
#define cdxRecNo NULL
#define cdxSetFieldsExtent NULL
#define cdxAlias NULL
#define cdxCreate NULL
#define cdxNewArea NULL
#define cdxOpen NULL
#define cdxRelease NULL
#define cdxStructSize NULL
#define cdxSysName NULL
#define cdxEval NULL
#define cdxPack NULL
#define cdxZap NULL
#define cdxOrderCondition NULL
#define cdxClearFilter NULL
#define cdxClearLocate NULL
#define cdxFilterText NULL
#define cdxSetFilter NULL
#define cdxSetLocate NULL
#define cdxCompile NULL
#define cdxError NULL
#define cdxEvalBlock NULL
#define cdxRawLock NULL
#define cdxLock NULL
#define cdxUnLock NULL
#define cdxCloseMemFile NULL
#define cdxReadDBHeader NULL
#define cdxWhoCares NULL
static ERRCODE cdxClose( AREAP pArea )
{
HB_TRACE(HB_TR_DEBUG, ("cdxClose(%p)", pArea));
cdxOrderListClear( pArea );
return SUPER_CLOSE( pArea );
}
static ERRCODE cdxCreateMemFile( AREAP pArea, LPDBOPENINFO pCreateInfo )
{
LPFILEINFO lpMemInfo;
LPMEMOHEADER pMemoHeader;
BOOL bError;
PHB_ITEM pError = NULL;
HB_TRACE(HB_TR_DEBUG, ("cdxCreateMemFile(%p, %p)", pArea, pCreateInfo));
lpMemInfo = pArea->lpDataInfo->pNext;
do
{
lpMemInfo->hFile = hb_fsCreate( pCreateInfo->abName, FC_NORMAL );
if( lpMemInfo->hFile == FS_ERROR )
{
if( !pError )
{
pError = hb_errNew();
hb_errPutGenCode( pError, EG_CREATE );
hb_errPutSubCode( pError, 1005 );
hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_CREATE ) );
hb_errPutFileName( pError, ( char * ) pCreateInfo->abName );
hb_errPutFlags( pError, EF_CANRETRY );
}
bError = ( SELF_ERROR( pArea, pError ) == E_RETRY );
}
else
bError = FALSE;
} while( bError );
if( pError )
hb_errRelease( pError );
if( lpMemInfo->hFile == FS_ERROR )
return FAILURE;
pMemoHeader = ( LPMEMOHEADER ) hb_xgrab( 512 );
memset( pMemoHeader, 0, 512 );
pMemoHeader->lNextBlock = hb_cdxSwapBytes( 512 / MEMO_BLOCK );
pMemoHeader->lBlockSize = hb_cdxSwapBytes( MEMO_BLOCK );
bError = ( hb_fsWrite( lpMemInfo->hFile, ( BYTE * ) pMemoHeader, 512 ) != 512 );
hb_xfree( pMemoHeader );
hb_fsClose( lpMemInfo->hFile );
lpMemInfo->hFile = FS_ERROR;
if( bError )
return FAILURE;
else
return SUCCESS;
}
static ERRCODE cdxGetValueFile( AREAP pArea, USHORT uiIndex, void * pFile )
{
ULONG lRecNo, lNewRecNo;
BYTE * szText, szEndChar;
LPFIELD pField;
HB_TRACE(HB_TR_DEBUG, ("cdxGetValueFile(%p, %hu, %p)", pArea, uiIndex, pFile));
HB_SYMBOL_UNUSED( pFile );
if( uiIndex > pArea->uiFieldCount )
return FAILURE;
pField = pArea->lpFields + uiIndex - 1;
szText = pArea->lpExtendInfo->bRecord + pField->uiOffset;
if( !( ( LPDBFMEMO ) pField->memo )->pData )
memset( szText, ' ', pField->uiLen );
else
{
szEndChar = * ( szText + pField->uiLen );
* ( szText + pField->uiLen ) = 0;
lRecNo = atol( ( char * ) szText );
lNewRecNo = lRecNo;
if( !hb_cdxWriteMemo( pArea, ( LPDBFMEMO ) pField->memo, &lNewRecNo ) )
return FAILURE;
if( lNewRecNo != lRecNo )
hb_cdxltoa( lNewRecNo, ( char * ) szText, pField->uiLen );
* ( szText + pField->uiLen ) = szEndChar;
}
( ( LPDBFMEMO ) pField->memo )->fChanged = FALSE;
return SUCCESS;
}
static ERRCODE cdxInfo( AREAP pArea, USHORT uiIndex, PHB_ITEM pItem )
{
HB_TRACE(HB_TR_DEBUG, ("cdxInfo(%p, %hu, %p)", pArea, uiIndex, pItem));
if( uiIndex == DBI_MEMOEXT )
{
hb_itemPutC( pItem, ".fpt" );
return SUCCESS;
}
return SUPER_INFO( pArea, uiIndex, pItem );
}
static ERRCODE cdxOpenMemFile( AREAP pArea, LPDBOPENINFO pOpenInfo )
{
LPFILEINFO lpMemInfo;
LPMEMOHEADER pMemoHeader;
USHORT uiFlags;
PHB_ITEM pError = NULL;
BOOL bRetry;
HB_TRACE(HB_TR_DEBUG, ("cdxOpenMemFile(%p, %p)", pArea, pOpenInfo));
lpMemInfo = pArea->lpDataInfo->pNext;
uiFlags = pOpenInfo->fReadonly ? FO_READ : FO_READWRITE;
uiFlags |= pOpenInfo->fShared ? FO_DENYNONE : FO_EXCLUSIVE;
do
{
lpMemInfo->hFile = hb_fsOpen( pOpenInfo->abName, uiFlags );
if( lpMemInfo->hFile == FS_ERROR )
{
if( !pError )
{
pError = hb_errNew();
hb_errPutGenCode( pError, EG_OPEN );
hb_errPutSubCode( pError, 1002 );
hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_OPEN ) );
hb_errPutFileName( pError, ( char * ) pOpenInfo->abName );
hb_errPutFlags( pError, EF_CANRETRY );
}
bRetry = ( SELF_ERROR( pArea, pError ) == E_RETRY );
}
else
bRetry = FALSE;
} while( bRetry );
if( pError )
hb_errRelease( pError );
if( lpMemInfo->hFile == FS_ERROR )
return FAILURE;
pMemoHeader = ( LPMEMOHEADER ) hb_xgrab( 512 );
if( hb_fsRead( lpMemInfo->hFile, ( BYTE * ) pMemoHeader, 512 ) != 512 )
{
hb_xfree( pMemoHeader );
return FAILURE;
}
hb_xfree( pMemoHeader );
return SUCCESS;
}
static ERRCODE cdxOrderCreate( AREAP pArea, LPDBORDERCREATEINFO pOrderInfo )
{
PHB_ITEM pExpr, pKeyExp, pForExp, pResult, pError;
HB_MACRO_PTR pExpMacro, pForMacro;
USHORT uiType, uiLen, uiCount;
char * szFileName, * szTagName;
PHB_FNAME pFileName;
DBORDERINFO pExtInfo;
LPINDEXINFO pIndex;
LPTAGINFO pTag, pLastTag;
DBFHEADER pHeader;
BYTE bType;
BOOL bNewFile;
HB_TRACE(HB_TR_DEBUG, ("cdxOrderCreate(%p, %p)", pArea, pOrderInfo));
if( SELF_GOCOLD( pArea ) == FAILURE )
return FAILURE;
/* If we have a codeblock for the expression, use it */
if( pOrderInfo->itmCobExpr )
pExpr = pOrderInfo->itmCobExpr;
else /* Otherwise, try compiling the key expression string */
{
if( SELF_COMPILE( pArea, ( BYTE * ) pOrderInfo->abExpr->item.asString.value ) == FAILURE )
return FAILURE;
pExpr = pArea->valResult;
pArea->valResult = NULL;
}
/* Save for later use */
pKeyExp = hb_itemNew( NULL );
hb_itemCopy( pKeyExp, pExpr );
/* Get a blank record before testing expression */
SELF_GOBOTTOM( pArea );
SELF_SKIP( pArea, 1 );
pExpMacro = pForMacro = NULL;
if( hb_itemType( pExpr ) == HB_IT_BLOCK )
{
if( SELF_EVALBLOCK( pArea, pExpr ) == FAILURE )
{
hb_itemRelease( pKeyExp );
return FAILURE;
}
pResult = pArea->valResult;
pArea->valResult = NULL;
}
else
{
pExpMacro = ( HB_MACRO_PTR ) hb_itemGetPtr( pExpr );
hb_macroRun( pExpMacro );
pResult = pExpr;
hb_itemCopy( pResult, &hb_stack.Return );
}
uiType = hb_itemType( pResult );
uiLen = 0;
switch( uiType )
{
case HB_IT_INTEGER:
case HB_IT_LONG:
case HB_IT_DOUBLE:
bType = 'N';
uiLen = 10;
break;
case HB_IT_DATE:
bType = 'D';
uiLen = 8;
break;
case HB_IT_LOGICAL:
bType = 'C';
uiLen = 1;
break;
case HB_IT_STRING:
bType = 'C';
uiLen = pResult->item.asString.length > CDX_MAX_KEY ? CDX_MAX_KEY :
pResult->item.asString.length;
break;
}
hb_itemRelease( pResult );
/* Make sure uiLen is not 0 */
if( uiLen == 0 )
{
hb_itemRelease( pKeyExp );
pError = hb_errNew();
hb_errPutGenCode( pError, EG_DATAWIDTH );
hb_errPutSubCode( pError, 1026 );
hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_DATAWIDTH ) );
SELF_ERROR( pArea, pError );
hb_errRelease( pError );
if( pExpMacro != NULL )
hb_macroDelete( pExpMacro );
return FAILURE;
}
/* Check conditional expression */
pExpr = pForExp = NULL;
if( pArea->lpdbOrdCondInfo )
{
/* If we have a codeblock for the conditional expression, use it */
if( pArea->lpdbOrdCondInfo->itmCobFor )
pExpr = pArea->lpdbOrdCondInfo->itmCobFor;
else /* Otherwise, try compiling the conditional expression string */
{
if( SELF_COMPILE( pArea, pArea->lpdbOrdCondInfo->abFor ) == FAILURE )
{
hb_itemRelease( pKeyExp );
if( pExpMacro != NULL )
hb_macroDelete( pExpMacro );
return FAILURE;
}
pExpr = pArea->valResult;
pArea->valResult = NULL;
}
/* Save for later use */
pForExp = hb_itemNew( NULL );
hb_itemCopy( pForExp, pExpr );
}
/* Test conditional expression */
if( pExpr )
{
if( hb_itemType( pExpr ) == HB_IT_BLOCK )
{
if( SELF_EVALBLOCK( pArea, pExpr ) == FAILURE )
{
hb_itemRelease( pKeyExp );
hb_itemRelease( pForExp );
if( pExpMacro != NULL )
hb_macroDelete( pExpMacro );
return FAILURE;
}
pResult = pArea->valResult;
}
else
{
pForMacro = ( HB_MACRO_PTR ) hb_itemGetPtr( pExpr );
hb_macroRun( pForMacro );
pResult = pExpr;
hb_itemCopy( pResult, &hb_stack.Return );
}
uiType = hb_itemType( pResult );
hb_itemRelease( pResult );
if( uiType != HB_IT_LOGICAL )
{
hb_itemRelease( pKeyExp );
hb_itemRelease( pForExp );
if( pExpMacro != NULL )
hb_macroDelete( pExpMacro );
if( pForMacro != NULL )
hb_macroDelete( pForMacro );
return FAILURE;
}
}
/* Check file name */
szFileName = ( char * ) hb_xgrab( _POSIX_PATH_MAX + 3 );
szFileName[ 0 ] = '\0';
if( strlen( ( char * ) pOrderInfo->abBagName ) == 0 )
{
pFileName = hb_fsFNameSplit( pArea->lpDataInfo->szFileName );
if( pFileName->szDrive )
strcat( szFileName, pFileName->szDrive );
if( pFileName->szPath )
strcat( szFileName, pFileName->szPath );
strcat( szFileName, pFileName->szName );
pExtInfo.itmResult = hb_itemPutC( NULL, "" );
SELF_ORDINFO( pArea, DBOI_BAGEXT, &pExtInfo );
strcat( szFileName, pExtInfo.itmResult->item.asString.value );
hb_itemRelease( pExtInfo.itmResult );
}
else
{
strcpy( szFileName, ( char * ) pOrderInfo->abBagName );
pFileName = hb_fsFNameSplit( szFileName );
if( !pFileName->szExtension )
{
pExtInfo.itmResult = hb_itemPutC( NULL, "" );
SELF_ORDINFO( pArea, DBOI_BAGEXT, &pExtInfo );
strcat( szFileName, pExtInfo.itmResult->item.asString.value );
hb_itemRelease( pExtInfo.itmResult );
}
}
szTagName = ( char * ) hb_xgrab( CDX_MAX_TAG_NAME_LEN + 1 );
hb_strncpyUpper( szTagName, pFileName->szName, CDX_MAX_TAG_NAME_LEN );
hb_xfree( pFileName );
/* Close all index */
cdxOrderListClear( pArea );
pIndex = hb_cdxIndexNew( pArea );
pArea->lpIndexInfo = pIndex;
/* New file? */
if( !hb_fsFile( szFileName ) )
{
pIndex->DiskFile = hb_fsCreate( szFileName, FC_NORMAL );
bNewFile = TRUE;
}
else
{
pIndex->DiskFile = hb_fsOpen( szFileName, FO_READWRITE |
( pArea->lpExtendInfo->fExclusive ?
FO_EXCLUSIVE : FO_DENYNONE ) );
bNewFile = FALSE;
}
if( pIndex->DiskFile == FS_ERROR )
{
cdxOrderListClear( pArea );
hb_xfree( szFileName );
hb_xfree( szTagName );
hb_itemRelease( pKeyExp );
if( pForExp != NULL )
hb_itemRelease( pForExp );
if( pExpMacro != NULL )
hb_macroDelete( pExpMacro );
if( pForMacro != NULL )
hb_macroDelete( pForMacro );
return FAILURE;
}
/* Corrupted? */
if( !bNewFile )
{
bNewFile = ( hb_fsSeek( pIndex->DiskFile, 0, FS_END ) <= CDX_BLOCK_SIZE );
hb_fsSeek( pIndex->DiskFile, 0, FS_SET );
}
if( bNewFile )
{
pIndex->NextAvail = 0;
pIndex->CompoundTag = hb_cdxTagNew( pIndex, szTagName, -1 );
pIndex->CompoundTag->OptFlags = 0xE0;
hb_cdxTagIndexTagNew( pIndex->CompoundTag, NULL, NULL, 'C', 10, NULL, NULL,
TRUE, FALSE );
hb_cdxTagTagOpen( pIndex->CompoundTag, 0 );
}
else
{
pIndex->CompoundTag = hb_cdxTagNew( pIndex, szTagName, 0 );
pIndex->CompoundTag->OptFlags = 0xE0;
hb_cdxIndexResetAvailPage( pIndex );
hb_cdxTagTagOpen( pIndex->CompoundTag, 0 );
while( !pIndex->CompoundTag->TagEOF )
{
pTag = hb_cdxTagNew( pIndex,
pIndex->CompoundTag->CurKeyInfo->pItem->item.asString.value,
pIndex->CompoundTag->CurKeyInfo->Tag );
if( pIndex->TagList == NULL )
pIndex->TagList = pTag;
else
{
pLastTag = pIndex->TagList;
while( pLastTag->pNext )
pLastTag = pLastTag->pNext;
pLastTag->pNext = pTag;
}
hb_cdxTagKeyRead( pIndex->CompoundTag, NEXT_RECORD );
}
}
/* Update DBF header */
if( !pArea->lpExtendInfo->fHasMDX )
{
pFileName = hb_fsFNameSplit( pArea->lpDataInfo->szFileName );
hb_strncpyUpper( szFileName, pFileName->szName, CDX_MAX_TAG_NAME_LEN );
hb_xfree( pFileName );
if( strcmp( szFileName, szTagName ) == 0 && hb_fsRead( pArea->lpDataInfo->hFile,
( BYTE * ) &pHeader, sizeof( DBFHEADER ) ) == sizeof( DBFHEADER ) )
{
pHeader.bHasMDX = 1;
hb_fsWrite( pArea->lpDataInfo->hFile, ( BYTE * ) &pHeader, sizeof( DBFHEADER ) );
}
}
hb_xfree( szFileName );
hb_strncpyUpper( szTagName, pOrderInfo->atomBagName, CDX_MAX_TAG_NAME_LEN );
uiCount = strlen( szTagName );
while( uiCount > 0 && szTagName[ uiCount - 1 ] == ' ' )
uiCount--;
szTagName[ uiCount ] = NULL;
hb_cdxIndexAddTag( pIndex, szTagName, pOrderInfo->abExpr->item.asString.value,
pKeyExp, bType, uiLen, pArea->lpdbOrdCondInfo ? pArea->lpdbOrdCondInfo->abFor :
NULL, pForExp, pArea->lpdbOrdCondInfo ?
!pArea->lpdbOrdCondInfo->fDescending : TRUE , pOrderInfo->fUnique );
hb_xfree( szTagName );
/* Clear pArea->lpdbOrdCondInfo */
SELF_ORDSETCOND( pArea, NULL );
return SELF_GOTOP( pArea );
}
static ERRCODE cdxOrderDestroy( AREAP pArea, LPDBORDERINFO pOrderInfo )
{
HB_TRACE(HB_TR_DEBUG, ("cdxOrderDestroy(%p, %p)", pArea, pOrderInfo));
HB_SYMBOL_UNUSED( pArea );
HB_SYMBOL_UNUSED( pOrderInfo );
return SUCCESS;
}
static ERRCODE cdxOrderInfo( AREAP pArea, USHORT uiIndex, LPDBORDERINFO pInfo )
{
HB_TRACE(HB_TR_DEBUG, ("cdxOrderInfo(%p, %hu, %p)", pArea, uiIndex, pInfo));
HB_SYMBOL_UNUSED( pArea );
switch( uiIndex )
{
case DBOI_BAGEXT:
hb_itemPutC( pInfo->itmResult, ".cdx" );
break;
}
return SUCCESS;
}
static ERRCODE cdxOrderListAdd( AREAP pArea, LPDBORDERINFO pOrderInfo )
{
HB_TRACE(HB_TR_DEBUG, ("cdxOrderListAdd(%p, %p)", pArea, pOrderInfo));
HB_SYMBOL_UNUSED( pArea );
HB_SYMBOL_UNUSED( pOrderInfo );
return SUCCESS;
}
static ERRCODE cdxOrderListClear( AREAP pArea )
{
LPINDEXINFO pIndex;
HB_TRACE(HB_TR_DEBUG, ("cdxOrderListClear(%p)", pArea));
while( pArea->lpIndexInfo )
{
pIndex = pArea->lpIndexInfo;
pArea->lpIndexInfo = pArea->lpIndexInfo->pNext;
hb_cdxIndexFree( pIndex );
}
pArea->lpIndexInfo = NULL;
return SUCCESS;
}
static ERRCODE cdxOrderListFocus( AREAP pArea, LPDBORDERINFO pOrderInfo )
{
HB_TRACE(HB_TR_DEBUG, ("cdxOrderListFocus(%p, %p)", pArea, pOrderInfo));
HB_SYMBOL_UNUSED( pArea );
HB_SYMBOL_UNUSED( pOrderInfo );
return SUCCESS;
}
static ERRCODE cdxOrderListRebuild( AREAP pArea )
{
HB_TRACE(HB_TR_DEBUG, ("cdxOrderListRebuild(%p)", pArea));
HB_SYMBOL_UNUSED( pArea );
return SUCCESS;
}
static ERRCODE cdxPutValueFile( AREAP pArea, USHORT uiIndex, void * pFile )
{
LPFIELD pField;
BYTE * szText, szEndChar;
ULONG lMemoBlock;
HB_TRACE(HB_TR_DEBUG, ("cdxPutValueFile(%p, %hu, %p)", pArea, uiIndex, pFile));
HB_SYMBOL_UNUSED( pFile );
if( uiIndex > pArea->uiFieldCount )
return FAILURE;
pField = pArea->lpFields + uiIndex - 1;;
szText = pArea->lpExtendInfo->bRecord + pField->uiOffset;
szEndChar = * ( szText + pField->uiLen );
* ( szText + pField->uiLen ) = 0;
lMemoBlock = atol( ( char * ) szText ) * MEMO_BLOCK;
* ( szText + pField->uiLen ) = szEndChar;
if( lMemoBlock > 0 )
hb_cdxReadMemo( pArea, ( LPDBFMEMO ) pField->memo, lMemoBlock );
else if( ( ( LPDBFMEMO ) pField->memo )->pData )
{
hb_xfree( ( ( LPDBFMEMO ) pField->memo )->pData );
memset( pField->memo, 0, sizeof( DBFMEMO ) );
}
return SUCCESS;
}
static ERRCODE cdxSeek( AREAP pArea, BOOL bSoftSeek, PHB_ITEM pKey, BOOL bFindLast )
{
HB_TRACE(HB_TR_DEBUG, ("cdxSeek(%p, %d, %p, %d)", pArea, bSoftSeek, pKey, bFindLast));
HB_SYMBOL_UNUSED( pArea );
HB_SYMBOL_UNUSED( bSoftSeek );
HB_SYMBOL_UNUSED( pKey );
HB_SYMBOL_UNUSED( bFindLast );
return SUCCESS;
}
static ERRCODE cdxWriteDBHeader( AREAP pArea )
{
DBFHEADER pHeader;
DBFFIELD pDBField;
USHORT uiCount;
LPFIELD pField;
time_t t;
struct tm * pTime;
HB_TRACE(HB_TR_DEBUG, ("cdxWriteDBHeader(%p)", pArea));
memset( &pHeader, 0, sizeof( DBFHEADER ) );
pHeader.uiRecordLen = 1;
pHeader.bVersion = 0x03;
pField = pArea->lpFields;
for( uiCount = 0; uiCount < pArea->uiFieldCount; uiCount++ )
{
switch( pField->uiType )
{
case 'C':
case 'N':
pHeader.uiRecordLen += pField->uiLen;
break;
case 'M':
pHeader.uiRecordLen += 10;
pHeader.bVersion = 0xF5;
pArea->lpExtendInfo->fHasMemo = TRUE;
break;
case 'D':
pHeader.uiRecordLen += 8;
break;
case 'L':
pHeader.uiRecordLen += 1;
break;
}
pField++;
}
time( &t );
pTime = localtime( &t );
pHeader.bYear = ( BYTE ) pTime->tm_year;
pHeader.bMonth = ( BYTE ) pTime->tm_mon + 1;
pHeader.bDay = ( BYTE ) pTime->tm_mday;
pHeader.uiHeaderLen = ( USHORT ) ( 32 * ( pArea->uiFieldCount + 1 ) + 1 );
pHeader.ulRecords = 0;
pHeader.bHasMDX = pArea->lpExtendInfo->fHasMDX;
if( hb_fsWrite( pArea->lpDataInfo->hFile, ( BYTE * ) &pHeader,
sizeof( DBFHEADER ) ) != sizeof( DBFHEADER ) )
return FAILURE;
pField = pArea->lpFields;
for( uiCount = 0; uiCount < pArea->uiFieldCount; uiCount++ )
{
memset( &pDBField, 0, sizeof( DBFFIELD ) );
strncpy( ( char * ) pDBField.bName, ( ( PHB_DYNS ) pField->sym )->pSymbol->szName,
sizeof( pDBField.bName ) );
pDBField.bType = pField->uiType;
switch( pDBField.bType )
{
case 'C':
pDBField.bLen = pField->uiLen & 0xFF;
pDBField.bDec = pField->uiLen >> 8;
break;
case 'M':
pDBField.bLen = 10;
pDBField.bDec = 0;
break;
case 'D':
pDBField.bLen = 8;
pDBField.bDec = 0;
break;
case 'L':
pDBField.bLen = 1;
pDBField.bDec = 0;
break;
case 'N':
pDBField.bLen = pField->uiLen;
pDBField.bDec = pField->uiDec;
break;
}
if( hb_fsWrite( pArea->lpDataInfo->hFile, ( BYTE * ) &pDBField,
sizeof( DBFFIELD ) ) != sizeof( DBFFIELD ) )
return FAILURE;
pField++;
}
if( hb_fsWrite( pArea->lpDataInfo->hFile, ( BYTE * ) "\15\32", 2 ) != 2 )
return FAILURE;
return SUCCESS;
}
static RDDFUNCS cdxTable = { cdxBof,
cdxEof,
cdxFound,
cdxGoBottom,
cdxGoTo,
cdxGoToId,
cdxGoTop,
cdxSeek,
cdxSkip,
cdxSkipFilter,
cdxSkipRaw,
cdxAddField,
cdxAppend,
cdxCreateFields,
cdxDeleteRec,
cdxDeleted,
cdxFieldCount,
cdxFieldDisplay,
cdxFieldInfo,
cdxFieldName,
cdxFlush,
cdxGetRec,
cdxGetValue,
cdxGetVarLen,
cdxGoCold,
cdxGoHot,
cdxPutRec,
cdxPutValue,
cdxRecAll,
cdxRecCount,
cdxRecInfo,
cdxRecNo,
cdxSetFieldsExtent,
cdxAlias,
cdxClose,
cdxCreate,
cdxInfo,
cdxNewArea,
cdxOpen,
cdxRelease,
cdxStructSize,
cdxSysName,
cdxEval,
cdxPack,
cdxZap,
cdxOrderListAdd,
cdxOrderListClear,
cdxOrderListFocus,
cdxOrderListRebuild,
cdxOrderCondition,
cdxOrderCreate,
cdxOrderDestroy,
cdxOrderInfo,
cdxClearFilter,
cdxClearLocate,
cdxFilterText,
cdxSetFilter,
cdxSetLocate,
cdxCompile,
cdxError,
cdxEvalBlock,
cdxRawLock,
cdxLock,
cdxUnLock,
cdxCloseMemFile,
cdxCreateMemFile,
cdxGetValueFile,
cdxOpenMemFile,
cdxPutValueFile,
cdxReadDBHeader,
cdxWriteDBHeader,
cdxWhoCares
};
HB_FUNC( _DBFCDX )
{
}
HB_FUNC( DBFCDX_GETFUNCTABLE )
{
RDDFUNCS * pTable;
USHORT * uiCount;
uiCount = ( USHORT * ) hb_parnl( 1 );
* uiCount = RDDFUNCSCOUNT;
pTable = ( RDDFUNCS * ) hb_parnl( 2 );
if( pTable )
hb_retni( hb_rddInherit( pTable, &cdxTable, &cdxSuper, ( BYTE * ) "DBF" ) );
else
hb_retni( FAILURE );
}