Files
harbour-core/harbour/source/rdd/dbfcdx/dbfcdx1.c
Horacio Dario Roldan Kasimatis 334ec4a219 2002-06-02 09:30 UTC-0300 Horacio Roldan <harbour_ar@yahoo.com.ar>
* source/rdd/dbfcdx/dbfcdx1.c
     ! fix in locking logic.
     ! fixed bug updating conditionals indexes, reported by Walter Negro
     ! fixed bug in dbgoto, reported by Pritpal Bedi
2002-06-02 12:42:13 +00:00

6087 lines
177 KiB
C
Raw Blame History

/*
* $Id$
*/
/*
* Harbour Project source code:
* DBFCDX RDD
*
* Copyright 1999-2002 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, or (at your option)
* any later version.
*
* 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 software; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/).
*
* As a special exception, the Harbour Project gives permission for
* additional uses of the text contained in its release of Harbour.
*
* The exception is that, if you link the Harbour libraries 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 Harbour library code into it.
*
* This exception does not however invalidate any other reasons why
* the executable file might be covered by the GNU General Public License.
*
* This exception applies only to the code released by the Harbour
* Project under the name Harbour. If you copy code from other
* Harbour Project or Free Software Foundation releases into a copy of
* Harbour, as the General Public License permits, the exception does
* not apply to the code that you add in this way. To avoid misleading
* anyone as to the status of such modified files, you must delete
* this exception notice from them.
*
* If you write modifications of your own for Harbour, it is your choice
* whether to permit this exception to apply to your modifications.
* If you do not wish that, delete this exception notice.
*
*/
/* #define __XHARBOUR__ */
#include "hbapi.h"
#include "hbinit.h"
#include "hbvm.h"
#include "hbstack.h"
#include "hbapiitm.h"
#include "hbdbf.h"
#include "hbapierr.h"
#include "hbapilng.h"
#include "hbset.h"
#include "hbdate.h"
#include "error.ch"
#include "dbfcdx1.h"
#include "hbrddcdx.h"
#include "dbfcdx2.h"
extern HB_FUNC( _DBFCDX );
extern HB_FUNC( DBFCDX_GETFUNCTABLE );
#ifdef HB_PCODE_VER
#undef HB_PRG_PCODE_VER
#define HB_PRG_PCODE_VER HB_PCODE_VER
#endif
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(_MSC_VER)
#if _MSC_VER >= 1010
#pragma data_seg( ".CRT$XIY" )
#pragma comment( linker, "/Merge:.CRT=.data" )
#else
#pragma data_seg( "XIY" )
#endif
static HB_$INITSYM hb_vm_auto_dbfcdx1__InitSymbols = dbfcdx1__InitSymbols;
#pragma data_seg()
#elif ! defined(__GNUC__)
#pragma startup dbfcdx1__InitSymbols
#endif
static USHORT s_uiMemoBlockSize = 64; /* Default block memo size */
static RDDFUNCS cdxSuper = { NULL };
static RDDFUNCS cdxTable = { ( DBENTRYP_BP ) hb_cdxBof,
( DBENTRYP_BP ) hb_cdxEof,
( DBENTRYP_BP ) hb_cdxFound,
( DBENTRYP_V ) hb_cdxGoBottom,
( DBENTRYP_UL ) hb_cdxGoTo,
( DBENTRYP_I ) hb_cdxGoToId,
( DBENTRYP_V ) hb_cdxGoTop,
( DBENTRYP_BIB ) hb_cdxSeek,
( DBENTRYP_L ) hb_cdxSkip,
( DBENTRYP_L ) hb_cdxSkipFilter,
( DBENTRYP_L ) hb_cdxSkipRaw,
( DBENTRYP_VF ) hb_cdxAddField,
( DBENTRYP_B ) hb_cdxAppend,
( DBENTRYP_I ) hb_cdxCreateFields,
( DBENTRYP_V ) hb_cdxDeleteRec,
( DBENTRYP_BP ) hb_cdxDeleted,
( DBENTRYP_SP ) hb_cdxFieldCount,
( DBENTRYP_VF ) hb_cdxFieldDisplay,
( DBENTRYP_SSI ) hb_cdxFieldInfo,
( DBENTRYP_SVP ) hb_cdxFieldName,
( DBENTRYP_V ) hb_cdxFlush,
( DBENTRYP_PP ) hb_cdxGetRec,
( DBENTRYP_SI ) hb_cdxGetValue,
( DBENTRYP_SVL ) hb_cdxGetVarLen,
( DBENTRYP_V ) hb_cdxGoCold,
( DBENTRYP_V ) hb_cdxGoHot,
( DBENTRYP_P ) hb_cdxPutRec,
( DBENTRYP_SI ) hb_cdxPutValue,
( DBENTRYP_V ) hb_cdxRecall,
( DBENTRYP_ULP ) hb_cdxRecCount,
( DBENTRYP_ISI ) hb_cdxRecInfo,
( DBENTRYP_I ) hb_cdxRecNo,
( DBENTRYP_S ) hb_cdxSetFieldExtent,
( DBENTRYP_P ) hb_cdxAlias,
( DBENTRYP_V ) hb_cdxClose,
( DBENTRYP_VP ) hb_cdxCreate,
( DBENTRYP_SI ) hb_cdxInfo,
( DBENTRYP_V ) hb_cdxNewArea,
( DBENTRYP_VP ) hb_cdxOpen,
( DBENTRYP_V ) hb_cdxRelease,
( DBENTRYP_SP ) hb_cdxStructSize,
( DBENTRYP_P ) hb_cdxSysName,
( DBENTRYP_VEI ) hb_cdxEval,
( DBENTRYP_V ) hb_cdxPack,
( DBENTRYP_LSP ) hb_cdxPackRec,
( DBENTRYP_VS ) hb_cdxSort,
( DBENTRYP_VT ) hb_cdxTrans,
( DBENTRYP_VT ) hb_cdxTransRec,
( DBENTRYP_V ) hb_cdxZap,
( DBENTRYP_VR ) hb_cdxChildEnd,
( DBENTRYP_VR ) hb_cdxChildStart,
( DBENTRYP_VR ) hb_cdxChildSync,
( DBENTRYP_V ) hb_cdxSyncChildren,
( DBENTRYP_V ) hb_cdxClearRel,
( DBENTRYP_V ) hb_cdxForceRel,
( DBENTRYP_SVP ) hb_cdxRelArea,
( DBENTRYP_VR ) hb_cdxRelEval,
( DBENTRYP_SVP ) hb_cdxRelText,
( DBENTRYP_VR ) hb_cdxSetRel,
( DBENTRYP_OI ) hb_cdxOrderListAdd,
( DBENTRYP_V ) hb_cdxOrderListClear,
( DBENTRYP_VP ) hb_cdxOrderListDelete,
( DBENTRYP_OI ) hb_cdxOrderListFocus,
( DBENTRYP_V ) hb_cdxOrderListRebuild,
( DBENTRYP_VOI ) hb_cdxOrderCondition,
( DBENTRYP_VOC ) hb_cdxOrderCreate,
( DBENTRYP_OI ) hb_cdxOrderDestroy,
( DBENTRYP_OII ) hb_cdxOrderInfo,
( DBENTRYP_V ) hb_cdxClearFilter,
( DBENTRYP_V ) hb_cdxClearLocate,
( DBENTRYP_V ) hb_cdxClearScope,
( DBENTRYP_VPLP ) hb_cdxCountScope,
( DBENTRYP_I ) hb_cdxFilterText,
( DBENTRYP_SI ) hb_cdxScopeInfo,
( DBENTRYP_VFI ) hb_cdxSetFilter,
( DBENTRYP_VLO ) hb_cdxSetLocate,
( DBENTRYP_VOS ) hb_cdxSetScope,
( DBENTRYP_VPL ) hb_cdxSkipScope,
( DBENTRYP_P ) hb_cdxCompile,
( DBENTRYP_I ) hb_cdxError,
( DBENTRYP_I ) hb_cdxEvalBlock,
( DBENTRYP_VSP ) hb_cdxRawLock,
( DBENTRYP_VL ) hb_cdxLock,
( DBENTRYP_UL ) hb_cdxUnLock,
( DBENTRYP_V ) hb_cdxCloseMemFile,
( DBENTRYP_VP ) hb_cdxCreateMemFile,
( DBENTRYP_SVPB ) hb_cdxGetValueFile,
( DBENTRYP_VP ) hb_cdxOpenMemFile,
( DBENTRYP_SVP ) hb_cdxPutValueFile,
( DBENTRYP_V ) hb_cdxReadDBHeader,
( DBENTRYP_V ) hb_cdxWriteDBHeader /*, */
/* ( DBENTRYP_SVP ) hb_cdxWhoCares */
};
static long hb_cdxDBOIKeyCount( CDXAREAP pArea );
static long hb_cdxDBOIKeyNo( CDXAREAP pArea );
/*
* Common functions.
*/
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_cdxDNtoSort( double dValue, BYTE * szBuffer )
{
int i;
BYTE * pTemp;
/* HB_TRACE(HB_TR_DEBUG, ("hb_cdxDNtoSort(%ld, %p)", lValue, szBuffer)); */
pTemp = ( BYTE* ) &dValue;
if( dValue < 0 )
{
for( i = 7 ; i >= 0 ; i--, pTemp++)
szBuffer[ i ] = ( *pTemp ) ^ (BYTE) 0xFF;
}
else
{
for( i = 7 ; i >= 0 ; i--, pTemp++)
szBuffer[i] = ( *pTemp );
szBuffer[ 0 ] ^= 0x80;
}
}
static double hb_cdxSorttoND( BYTE * szBuffer, USHORT uiLen )
{
double dNumber;
int i;
BYTE * pTemp;
pTemp = ( BYTE* ) &dNumber;
pTemp += 7;
if( szBuffer[ 0 ] & 0x80 ) /* >0 */
{
for( i = 0 ; i < 8 ; i++, pTemp-- )
{
/* if( i < 8 - uiLen ) */
if( i >= uiLen )
( *pTemp ) = 0;
else
( *pTemp ) = szBuffer[ i ];
}
pTemp += 8;
( *pTemp ) ^= 0x80;
}
else
{
for( i = 0 ; i < 8 ; i++, pTemp-- )
{
/* if( i < 8 - uiLen ) */
if( i >= uiLen )
( *pTemp ) = 0;
else
( *pTemp ) = szBuffer[ i ] ^ (BYTE) 0xFF;
}
}
return dNumber;
}
/*
* Swap bytes.
*/
ULONG hb_cdxSwapBytes( ULONG ulLong )
{
BYTE * pLong, bByte;
HB_TRACE(HB_TR_DEBUG, ("hb_cdxSwapBytes(%lu)", ulLong));
pLong = ( BYTE * ) &ulLong;
bByte = pLong[ 0 ];
pLong[ 0 ] = pLong[ 3 ];
pLong[ 3 ] = bByte;
bByte = pLong[ 1 ];
pLong[ 1 ] = pLong[ 2 ];
pLong[ 2 ] = bByte;
return ulLong;
}
/* hb_cdx memo */
/* #include "cdxmemo.c" */
/*
* Converts memo block offset into ASCII.
*/
static ULONG hb_cdxGetMemoBlock( CDXAREAP pArea, USHORT uiIndex )
{
USHORT uiCount;
BYTE bByte;
ULONG ulBlock;
HB_TRACE(HB_TR_DEBUG, ("hb_cdxGetMemoBlock(%p, %hu)", pArea, uiIndex));
ulBlock = 0;
for( uiCount = 0; uiCount < 10; uiCount++ )
{
bByte = pArea->pRecord[ pArea->pFieldOffset[ uiIndex ] + uiCount ];
if( bByte >= '0' && bByte <= '9' )
ulBlock = ulBlock * 10 + ( bByte - '0' );
}
return ulBlock;
}
/*
* Converts ASCII data into memo block offset.
*/
static void hb_cdxPutMemoBlock( CDXAREAP pArea, USHORT uiIndex, ULONG ulBlock )
{
SHORT iCount;
HB_TRACE(HB_TR_DEBUG, ("hb_cdxPutMemoBlock(%p, %hu, %lu)", pArea, uiIndex, ulBlock));
for( iCount = 9; iCount >= 0; iCount-- )
{
if( ulBlock > 0 )
{
pArea->pRecord[ pArea->pFieldOffset[ uiIndex ] + iCount ] = ( BYTE ) (( ulBlock % 10 ) + '0');
ulBlock /= 10;
}
else
pArea->pRecord[ pArea->pFieldOffset[ uiIndex ] + iCount ] = ' ';
}
}
/*
* Return the size of memo.
*/
static ULONG hb_cdxGetMemoLen( CDXAREAP pArea, USHORT uiIndex )
{
ULONG ulBlock;
MEMOBLOCK mbBlock;
HB_TRACE(HB_TR_DEBUG, ("hb_cdxGetMemoLen(%p, %hu)", pArea, uiIndex));
ulBlock = hb_cdxGetMemoBlock( pArea, uiIndex );
if( ulBlock == 0 )
return 0;
hb_fsSeek( pArea->hMemoFile, ulBlock * pArea->uiMemoBlockSize, FS_SET );
if( hb_fsRead( pArea->hMemoFile, ( BYTE * ) &mbBlock, sizeof( MEMOBLOCK ) ) !=
sizeof( MEMOBLOCK ) )
return 0;
return hb_cdxSwapBytes( mbBlock.ulSize );
}
/*
* Read memo data.
*/
static void hb_cdxGetMemo( CDXAREAP pArea, USHORT uiIndex, PHB_ITEM pItem )
{
ULONG ulBlock, ulSize;
BYTE * pBuffer;
MEMOBLOCK mbBlock;
HB_TRACE(HB_TR_DEBUG, ("hb_cdxGetMemo(%p, %hu, %p)", pArea, uiIndex, pItem));
ulBlock = hb_cdxGetMemoBlock( pArea, uiIndex );
if( ulBlock > 0 )
{
hb_fsSeek( pArea->hMemoFile, ulBlock * pArea->uiMemoBlockSize, FS_SET );
if( hb_fsRead( pArea->hMemoFile, ( BYTE * ) &mbBlock, sizeof( MEMOBLOCK ) ) !=
sizeof( MEMOBLOCK ) )
ulSize = 0;
else
ulSize = hb_cdxSwapBytes( mbBlock.ulSize );
if( ulSize > 0 && ulSize < 0xFFFF )
{
pBuffer = ( BYTE * ) hb_xgrab( ulSize + 1 );
hb_fsReadLarge( pArea->hMemoFile, pBuffer, ulSize );
hb_itemPutCPtr( pItem, ( char * ) pBuffer, ulSize );
hb_itemSetCMemo( pItem );
}
}
else
{
hb_itemPutC( pItem, "" );
hb_itemSetCMemo( pItem );
}
}
/*
* Append blocks to free memo blocks list.
*/
static void hb_cdxAddFreeBlocks( CDXAREAP pArea, ULONG ulBlock, USHORT uiBlocks )
{
SHORT iCount;
BOOL bFound;
LPMEMOFREEBLOCK pFreeBlock;
HB_TRACE(HB_TR_DEBUG, ("hb_cdxAddFreeBlocks(%p, %lu, %hu)", pArea, ulBlock, uiBlocks));
bFound = FALSE;
for( iCount = pArea->pMemoRoot->uiListLen - 1; iCount >= 0; iCount-- )
{
pFreeBlock = ( LPMEMOFREEBLOCK ) ( pArea->pMemoRoot->pFreeList + iCount * SIZEOFMEMOFREEBLOCK );
if( pFreeBlock->ulBlock < ulBlock )
{
/* Can grow current free block? */
if( (pFreeBlock->ulBlock + pFreeBlock->uiBlocks) == ulBlock )
{
/* The new blocks are directly after the current free block */
pFreeBlock->uiBlocks += uiBlocks;
ulBlock = pFreeBlock->ulBlock;
uiBlocks = pFreeBlock->uiBlocks;
}
/* Can append to next free block? */
else if( iCount < pArea->pMemoRoot->uiListLen - 1 &&
(ulBlock + uiBlocks) == ( pFreeBlock + 1 )->ulBlock )
{
/* The new blocks are directly before the next free block */
pFreeBlock++;
iCount++;
pFreeBlock->ulBlock = ulBlock;
pFreeBlock->uiBlocks += uiBlocks;
uiBlocks = pFreeBlock->uiBlocks;
}
/* Append to next free block */
else
{
pFreeBlock++;
iCount++;
memmove( pFreeBlock + 1, pFreeBlock,
( HB_MIN( MAXFREEBLOCKS, pArea->pMemoRoot->uiListLen ) - iCount ) *
sizeof( SIZEOFMEMOFREEBLOCK ) );
pFreeBlock->ulBlock = ulBlock;
pFreeBlock->uiBlocks = uiBlocks;
pArea->pMemoRoot->uiListLen = HB_MIN( MAXFREEBLOCKS, pArea->pMemoRoot->uiListLen + 1 );
}
pArea->pMemoRoot->fChanged = TRUE;
bFound = TRUE;
break;
}
}
/* If it is the last block in memo file truncate it */
if( (ulBlock + uiBlocks) == pArea->pMemoRoot->ulNextBlock )
{
pArea->pMemoRoot->ulNextBlock = ulBlock;
pArea->pMemoRoot->fChanged = TRUE;
if( bFound )
{
memmove( pFreeBlock, pFreeBlock + 1,
( HB_MIN( MAXFREEBLOCKS, pArea->pMemoRoot->uiListLen ) - iCount ) *
sizeof( SIZEOFMEMOFREEBLOCK ) );
pArea->pMemoRoot->uiListLen--;
}
hb_fsSeek( pArea->hMemoFile, ulBlock * pArea->uiMemoBlockSize, FS_SET );
hb_fsWrite( pArea->hMemoFile, NULL, 0 );
return;
}
/* Insert free block */
if( !bFound && pArea->pMemoRoot->uiListLen < MAXFREEBLOCKS )
{
pFreeBlock = ( LPMEMOFREEBLOCK ) pArea->pMemoRoot->pFreeList;
memmove( pFreeBlock + 1, pFreeBlock,
HB_MIN( MAXFREEBLOCKS, pArea->pMemoRoot->uiListLen ) * sizeof( SIZEOFMEMOFREEBLOCK ) );
pFreeBlock->ulBlock = ulBlock;
pFreeBlock->uiBlocks = uiBlocks;
pArea->pMemoRoot->uiListLen = HB_MIN( MAXFREEBLOCKS, pArea->pMemoRoot->uiListLen + 1 );
pArea->pMemoRoot->fChanged = TRUE;
}
}
/*
* Try get free memo blocks from list.
*/
static BOOL hb_cdxCompleteFromFreeBlocks( CDXAREAP pArea, ULONG ulBlock, USHORT uiBlocks )
{
USHORT uiCount;
LPMEMOFREEBLOCK pFreeBlock;
MEMOBLOCK mbBlock;
HB_TRACE(HB_TR_DEBUG, ("hb_cdxCompleteFromFreeBlocks(%p, %lu, %hu)", pArea, ulBlock, uiBlocks));
for( uiCount = 0; uiCount < pArea->pMemoRoot->uiListLen; uiCount++ )
{
pFreeBlock = ( LPMEMOFREEBLOCK ) ( pArea->pMemoRoot->pFreeList + uiCount * SIZEOFMEMOFREEBLOCK );
if( pFreeBlock->ulBlock == ulBlock )
{
if( pFreeBlock->uiBlocks >= uiBlocks )
{
/* Same size, remove it */
if( pFreeBlock->uiBlocks == uiBlocks )
{
memmove( pFreeBlock, pFreeBlock + SIZEOFMEMOFREEBLOCK,
( pArea->pMemoRoot->uiListLen - uiCount ) * SIZEOFMEMOFREEBLOCK );
memset( pArea->pMemoRoot->pFreeList + ( pArea->pMemoRoot->uiListLen - 1 ) *
SIZEOFMEMOFREEBLOCK, 0, SIZEOFMEMOFREEBLOCK );
pArea->pMemoRoot->uiListLen--;
}
else /* Adjust new free size */
{
pFreeBlock->ulBlock += uiBlocks;
pFreeBlock->uiBlocks -= uiBlocks;
mbBlock.ulType = mbBlock.ulSize = 0;
hb_fsSeek( pArea->hMemoFile, pFreeBlock->ulBlock * pArea->uiMemoBlockSize, FS_SET );
hb_fsWrite( pArea->hMemoFile, ( BYTE * ) &mbBlock, sizeof( MEMOBLOCK ) );
}
pArea->pMemoRoot->fChanged = TRUE;
return TRUE;
}
else
break;
}
}
return FALSE;
}
/*
* Get free memo blocks from list or return a new block.
*/
static void hb_cdxGetFreeBlocks( CDXAREAP pArea, USHORT uiBlocks, ULONG * ulBlock )
{
USHORT uiCount;
LPMEMOFREEBLOCK pFreeBlock;
MEMOBLOCK mbBlock;
HB_TRACE(HB_TR_DEBUG, ("hb_cdxGetFreeBlocks(%p, %hu, %p)", pArea, uiBlocks, ulBlock));
for( uiCount = 0; uiCount < pArea->pMemoRoot->uiListLen; uiCount++ )
{
pFreeBlock = ( LPMEMOFREEBLOCK ) ( pArea->pMemoRoot->pFreeList + uiCount * SIZEOFMEMOFREEBLOCK );
if( uiBlocks <= pFreeBlock->uiBlocks )
{
* ulBlock = pFreeBlock->ulBlock;
/* Same size, remove it */
if( pFreeBlock->uiBlocks == uiBlocks )
{
memmove( pFreeBlock, pFreeBlock + SIZEOFMEMOFREEBLOCK,
( pArea->pMemoRoot->uiListLen - uiCount ) * SIZEOFMEMOFREEBLOCK );
memset( pArea->pMemoRoot->pFreeList + ( pArea->pMemoRoot->uiListLen - 1 ) *
SIZEOFMEMOFREEBLOCK, 0, SIZEOFMEMOFREEBLOCK );
pArea->pMemoRoot->uiListLen--;
}
else /* Adjust new free size */
{
pFreeBlock->ulBlock += uiBlocks;
pFreeBlock->uiBlocks -= uiBlocks;
mbBlock.ulType = mbBlock.ulSize = 0;
hb_fsSeek( pArea->hMemoFile, pFreeBlock->ulBlock * pArea->uiMemoBlockSize, FS_SET );
hb_fsWrite( pArea->hMemoFile, ( BYTE * ) &mbBlock, sizeof( MEMOBLOCK ) );
}
pArea->pMemoRoot->fChanged = TRUE;
return;
}
}
/* Not found a free block */
* ulBlock = pArea->pMemoRoot->ulNextBlock;
pArea->pMemoRoot->ulNextBlock += uiBlocks;
pArea->pMemoRoot->fChanged = TRUE;
}
/*
* Write memo data.
*/
static void hb_cdxWriteMemo( CDXAREAP pArea, ULONG ulBlock, PHB_ITEM pItem, ULONG ulLen,
ULONG * ulStoredBlock, USHORT uiType )
{
USHORT uiBloksRequired, uiBlocksUsed;
MEMOBLOCK mbBlock;
BOOL bWriteBlocks;
HB_TRACE(HB_TR_DEBUG, ("hb_cdxWriteMemo(%p, %lu, %p, %lu, %p, %hu)", pArea, ulBlock,
pItem, ulLen, ulStoredBlock, uiType));
uiBloksRequired = ( USHORT ) (( ulLen + sizeof( MEMOBLOCK ) + pArea->uiMemoBlockSize - 1 ) /
pArea->uiMemoBlockSize);
if( ulBlock > 0 )
{
hb_fsSeek( pArea->hMemoFile, ulBlock * pArea->uiMemoBlockSize, FS_SET );
hb_fsRead( pArea->hMemoFile, ( BYTE * ) &mbBlock, sizeof( MEMOBLOCK ) );
uiBlocksUsed = ( USHORT ) (( hb_cdxSwapBytes( mbBlock.ulSize ) + sizeof( MEMOBLOCK ) +
pArea->uiMemoBlockSize - 1 ) / pArea->uiMemoBlockSize);
}
bWriteBlocks = FALSE;
/* Use same space */
if( ulBlock > 0 && uiBlocksUsed >= uiBloksRequired )
{
* ulStoredBlock = ulBlock;
bWriteBlocks = TRUE;
/* Free space */
if( uiBlocksUsed > uiBloksRequired )
hb_cdxAddFreeBlocks( pArea, ulBlock + uiBloksRequired, uiBlocksUsed - uiBloksRequired );
}
else /* Need more space */
{
if( ulBlock > 0 )
{
if( hb_cdxCompleteFromFreeBlocks( pArea, ulBlock + uiBlocksUsed,
uiBloksRequired - uiBlocksUsed ) )
bWriteBlocks = TRUE;
else /* Free all blocks */
hb_cdxAddFreeBlocks( pArea, ulBlock, uiBlocksUsed );
}
if( !bWriteBlocks )
{
hb_cdxGetFreeBlocks( pArea, uiBloksRequired, ulStoredBlock );
bWriteBlocks = TRUE;
}
}
/* Write memo header and data */
if( bWriteBlocks )
{
mbBlock.ulType = hb_cdxSwapBytes( uiType );
mbBlock.ulSize = hb_cdxSwapBytes( ulLen );
hb_fsSeek( pArea->hMemoFile, * ulStoredBlock * pArea->uiMemoBlockSize, FS_SET );
hb_fsWrite( pArea->hMemoFile, ( BYTE * ) &mbBlock, sizeof( MEMOBLOCK ) );
hb_fsWriteLarge( pArea->hMemoFile, ( BYTE * ) hb_itemGetCPtr( pItem ), ulLen );
}
}
/*
* Assign a value to the specified memo field.
*/
static BOOL hb_cdxPutMemo( CDXAREAP pArea, USHORT uiIndex, PHB_ITEM pItem )
{
USHORT uiBlocksUsed;
ULONG ulLen, ulBlock;
MEMOBLOCK mbBlock;
HB_TRACE(HB_TR_DEBUG, ("hb_cdxPutMemo(%p, %hu, %p)", pArea, uiIndex, pItem));
ulLen = hb_itemGetCLen( pItem );
ulBlock = hb_cdxGetMemoBlock( pArea, uiIndex );
if( ulLen > 0 )
hb_cdxWriteMemo( pArea, ulBlock, pItem, ulLen, &ulBlock, 1 );
else
{
/* Free blocks */
if( ulBlock > 0 )
{
hb_fsSeek( pArea->hMemoFile, ulBlock * pArea->uiMemoBlockSize, FS_SET );
hb_fsRead( pArea->hMemoFile, ( BYTE * ) &mbBlock, sizeof( MEMOBLOCK ) );
uiBlocksUsed = ( USHORT ) (( hb_cdxSwapBytes( mbBlock.ulSize ) +
pArea->uiMemoBlockSize - 1 ) / pArea->uiMemoBlockSize);
hb_cdxAddFreeBlocks( pArea, ulBlock, uiBlocksUsed );
}
ulBlock = 0;
}
if( pArea->fShared && pArea->pMemoRoot->fChanged )
{
pArea->pMemoRoot->fChanged = FALSE;
hb_fsSeek( pArea->hMemoFile, 0, FS_SET );
pArea->pMemoRoot->ulNextBlock = hb_cdxSwapBytes( pArea->pMemoRoot->ulNextBlock );
pArea->pMemoRoot->ulBlockSize = hb_cdxSwapBytes( pArea->pMemoRoot->ulBlockSize );
hb_fsWrite( pArea->hMemoFile, ( BYTE * ) pArea->pMemoRoot, sizeof( MEMOROOT ) );
pArea->pMemoRoot->ulNextBlock = hb_cdxSwapBytes( pArea->pMemoRoot->ulNextBlock );
pArea->pMemoRoot->ulBlockSize = hb_cdxSwapBytes( pArea->pMemoRoot->ulBlockSize );
}
hb_cdxPutMemoBlock( pArea, uiIndex, ulBlock );
return TRUE;
}
/* end hb_cdx memo*/
/* hb_cdxkeyxxx */
/* #include "cdxkey.c" */
/* hb_cdxkeyxxx */
static LPKEYINFO hb_cdxKeyNew()
{
LPKEYINFO pKey;
pKey = ( LPKEYINFO ) hb_xgrab( sizeof( KEYINFO ) );
pKey->Value = NULL;
pKey->length = 0;
pKey->fString = FALSE;
pKey->Tag = pKey->Xtra = 0;
pKey->pNext = NULL;
return pKey;
}
static void hb_cdxKeyFree( LPKEYINFO pKey )
{
if( pKey )
{
if( pKey->Value )
hb_xfree( pKey->Value );
hb_xfree( pKey );
}
}
static int hb_cdxKeyCompare( LPKEYINFO pKey1, LPKEYINFO pKey2, USHORT * EndPos, BOOL Exact )
{
int iLimit, iResult;
* EndPos = 0;
if ( pKey1 == NULL )
return ( pKey2 == NULL ) ? 0 : -1;
if ( pKey2 == NULL )
return 1;
if ( pKey1->length == 0 )
return ( pKey2->length == 0 ) ? 0: -1;
if ( pKey2->length == 0 )
return 1;
/*
if( pKey2 == NULL || pKey2->length == 0 )
return 1;
if( pKey1 == NULL || pKey1->length == 0 )
return ( pKey2->length == 0 ) ? 0: -1;
*/
iLimit = (pKey1->length > pKey2->length) ? pKey2->length : pKey1->length;
if( pKey1->fString && pKey2->fString)
{
do
{
/*
for nation sorting support
iResult = hb_charcmp( pKey1->value[ * EndPos ],
pKey2->value[ * EndPos ] )
*/
iResult = ( (unsigned char) pKey1->Value[ * EndPos ]) -
( (unsigned char) pKey2->Value[ * EndPos ]);
(* EndPos)++; /* EndPos += 1; */
} while( iResult == 0 && * EndPos < iLimit );
}
else
{
do
{
iResult = ( (unsigned char) pKey1->Value[ * EndPos ]) -
( (unsigned char) pKey2->Value[ * EndPos ]);
(* EndPos)++; /* * EndPos += 1; */
} while( iResult == 0 && * EndPos < iLimit );
}
if( iResult == 0 )
{
(* EndPos)++; /* * EndPos += 1; */
iResult = pKey1->length - pKey2->length;
}
if( (iResult < 0) && ((ULONG)* EndPos > pKey1->length) && !Exact )
iResult = 0;
if( iResult < 0 )
return -1;
else if( iResult > 0 )
return 1;
else
return 0;
}
static LPKEYINFO hb_cdxKeyPutItem( LPKEYINFO pKey, PHB_ITEM pItem )
{
BYTE cTemp[8];
int i;
if( !pKey )
pKey = hb_cdxKeyNew();
if( pKey->Value )
{
hb_xfree( pKey->Value );
pKey->Value = NULL;
}
switch( hb_itemType( pItem ) )
{
case HB_IT_STRING:
pKey->Value = hb_itemGetC( pItem );
pKey->length = pItem->item.asString.length;
pKey->fString = TRUE;
while( pKey->length > 0 &&
pKey->Value[ pKey->length - 1 ] == ' ' )
/*pKey->Value[ pItem->item.asString.length - 1 ] == ' ' )*/
pKey->length--;
pKey->Value[ pKey->length ] = 0;
break;
case HB_IT_INTEGER:
case HB_IT_LONG:
case HB_IT_DOUBLE:
hb_cdxDNtoSort( hb_itemGetND( pItem ), &cTemp[0] );
i = 7;
while( !cTemp[i] )
i--;
i++;
pKey->length = i;
pKey->Value = (char *) hb_xgrab( i + 1 );
pKey->Value[i] = 0;
memcpy( pKey->Value, cTemp, i );
pKey->fString = FALSE;
break;
case HB_IT_DATE:
hb_cdxDNtoSort( (double) hb_itemGetDL( pItem ), &cTemp[0] );
i = 7;
while( !cTemp[i] )
i--;
i++;
pKey->length = i;
pKey->Value = (char *) hb_xgrab( i + 1 );
pKey->Value[i] = 0;
memcpy( pKey->Value, cTemp, i );
pKey->fString = FALSE;
break;
case HB_IT_LOGICAL:
pKey->length = 1;
pKey->Value = (char *) hb_xgrab( 2 );
pKey->fString = TRUE;
pKey->Value[0] = (char) ( hb_itemGetL( pItem ) ? 'T' : 'F' );
pKey->Value[1] = 0;
break;
default:
printf( "hb_cdxKeyPutItem( )" );
}
return pKey;
}
static PHB_ITEM hb_cdxKeyGetItem( LPKEYINFO pKey, PHB_ITEM pItem, USHORT uiType )
{
if( pKey && pKey->Value )
{
switch( uiType )
{
case HB_IT_STRING:
pItem = hb_itemPutC( pItem, pKey->Value );
break;
case HB_IT_INTEGER:
case HB_IT_LONG:
case HB_IT_DOUBLE:
pItem = (PHB_ITEM) hb_itemPutND( pItem,
(long) hb_cdxSorttoND( (BYTE*) pKey->Value, (USHORT) pKey->length ) );
break;
case HB_IT_DATE:
pItem = (PHB_ITEM) hb_itemPutDL( pItem,
(long) hb_cdxSorttoND( (BYTE*) pKey->Value, (USHORT) pKey->length ) );
break;
/*
case HB_IT_DOUBLE:
pItem = (PHB_ITEM) hb_itemPutND( pItem,
(long) hb_cdxSorttoND( pKey->Value, (USHORT) pKey->length ) );
break;
case HB_IT_DATE:
pItem = (PHB_ITEM) hb_itemPutDL( pItem,
(long) hb_cdxSorttoND( pKey->Value, (USHORT) pKey->length ) );
break;
*/
case HB_IT_LOGICAL:
pItem = hb_itemPutL( pItem,
(pKey->Value[0] == 'T' ? TRUE : FALSE ) );
break;
default:
pItem = hb_itemNew( pItem );
printf( "hb_cdxKeyGetItem() ???" );
}
}
else
pItem = hb_itemNew( pItem );
return pItem;
}
static LPKEYINFO hb_cdxKeyCopy( LPKEYINFO pKeyDest, LPKEYINFO pKey )
{
if( !pKeyDest )
{
pKeyDest = hb_cdxKeyNew();
}
if( pKeyDest->Value )
{
hb_xfree( pKeyDest->Value );
pKeyDest->Value = NULL;
pKeyDest->length = 0;
}
if( pKey )
{
pKeyDest->Value = (char *) hb_xgrab( pKey->length + 1 );
memcpy( pKeyDest->Value, pKey->Value, pKey->length );
pKeyDest->length = pKey->length;
pKeyDest->Value[ pKeyDest->length ] = 0;
pKeyDest->fString = pKey->fString;
pKeyDest->Tag = pKey->Tag;
pKeyDest->Xtra = pKey->Xtra;
}
return pKeyDest;
}
static LPKEYINFO hb_cdxKeyPut( LPKEYINFO pKey, BYTE * szText, USHORT uiLen )
{
if( !pKey )
pKey = hb_cdxKeyNew();
if( pKey->Value )
{
hb_xfree( pKey->Value );
pKey->Value = NULL;
}
if( szText == NULL )
{
pKey->length = 0;
pKey->fString = FALSE;
}
else
{
pKey->length = uiLen;
pKey->Value = ( char * ) hb_xgrab( uiLen + 1 );
memcpy( pKey->Value, szText, uiLen );
pKey->fString = FALSE;
}
return pKey;
}
static LPKEYINFO hb_cdxKeyPutC( LPKEYINFO pKey, char * szText )
{
if( !pKey )
pKey = hb_cdxKeyNew();
if( szText == NULL )
szText = "";
if( pKey->Value )
{
hb_xfree( pKey->Value );
pKey->Value = NULL;
}
pKey->length = strlen( szText );
pKey->Value = ( char * ) hb_xgrab( pKey->length + 1 );
strcpy( pKey->Value, szText );
pKey->fString = TRUE;
return pKey;
}
/* end hb_cdxkeyxxx */
/* end hb_cdxkeyxxx */
/* hb_cdxTagxxx */
/* #include "cdxtag.c" */
/* hb_cdxTagxxx */
/* Creates a new structure with a tag information
*
* PIF = pointer to a parent index structure
* ITN = tag name
* TagHdr = number of index page where a tag header is stored or -1 if
* allocate a new tag page
*/
static LPCDXTAG hb_cdxTagNew( LPCDXINDEX PIF, char * ITN, LONG TagHdr )
{
LPCDXTAG pTag;
pTag = ( LPCDXTAG ) hb_xgrab( sizeof( CDXTAG ) );
memset( pTag, 0, sizeof( CDXTAG ) );
pTag->szName = ( char * ) hb_xgrab( CDX_MAXTAGNAMELEN + 1 );
hb_strncpyUpper( pTag->szName, ITN, CDX_MAXTAGNAMELEN );
pTag->pIndex = PIF;
pTag->AscendKey = TRUE;
pTag->uiType = 'C';
pTag->CurKeyInfo = hb_cdxKeyNew();
if( TagHdr == -1 )
{
/* this tag is not stored in the file yet - allocate a space for it */
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( LPCDXTAG pTag )
{
if( pTag->RootPage != NULL )
{
hb_cdxPageFree( pTag->RootPage );
pTag->RootPage = NULL;
}
if( pTag->TagChanged )
hb_cdxTagTagStore( pTag );
if( pTag->szName != NULL )
hb_xfree( pTag->szName );
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_cdxTagClearScope( pTag, 0);
hb_cdxTagClearScope( pTag, 1);
hb_xfree( pTag );
}
static void hb_cdxTagIndexTagNew( LPCDXTAG pTag, char * KeyExp, PHB_ITEM pKeyItem,
BYTE bType, USHORT uiLen, char * ForExp,
PHB_ITEM pForItem, BOOL Ascnd, BOOL Uniq )
{
CDXTAGHEADER pHeader;
if( KeyExp != NULL )
{
pTag->KeyExpr = ( char * ) hb_xgrab( CDX_MAXKEY + 1 );
hb_strncpyUpper( pTag->KeyExpr, KeyExp, CDX_MAXKEY );
}
pTag->pKeyItem = pKeyItem;
if( ForExp != NULL )
{
pTag->ForExpr = ( char * ) hb_xgrab( CDX_MAXKEY + 1 );
hb_strncpyUpper( pTag->ForExpr, ForExp, CDX_MAXKEY );
}
pTag->pForItem = pForItem;
pTag->AscendKey = Ascnd;
pTag->UniqueKey = Uniq;
pTag->uiType = bType;
pTag->uiLen = uiLen;
pTag->MaxKeys = ( CDX_PAGELEN - 12 ) / ( uiLen + 8 );
memset( &pHeader, 0, sizeof( CDXTAGHEADER ) );
hb_cdxIndexPageWrite( pTag->pIndex, pTag->TagBlock, &pHeader, sizeof( CDXTAGHEADER ) );
hb_cdxTagDoIndex( pTag );
}
static void hb_cdxTagDoIndex( LPCDXTAG pTag )
{
ULONG ulRecNo;
BOOL bWhileOk;
LPSORTINFO pSort;
PHB_ITEM pItem;
HB_MACRO_PTR pMacro;
BYTE cTemp[8];
if( pTag->OptFlags & 0x80 )
hb_cdxTagEmptyIndex( pTag );
else
{
pSort = hb_cdxSortNew( pTag, pTag->UniqueKey );
pItem = hb_itemNew( NULL );
for( ulRecNo = 1; ulRecNo <= pTag->pIndex->pArea->ulRecCount; ulRecNo++ )
{
hb_fsSeek( pTag->pIndex->pArea->hDataFile,
pTag->pIndex->pArea->uiHeaderLen +
( ulRecNo - 1 ) * pTag->pIndex->pArea->uiRecordLen,
FS_SET );
hb_fsRead( pTag->pIndex->pArea->hDataFile,
pTag->pIndex->pArea->pRecord,
pTag->pIndex->pArea->uiRecordLen );
pTag->pIndex->pArea->ulRecNo = ulRecNo;
if( pTag->pForItem != NULL )
{
/* TODO: test for expression */
/* now is working but not tested */
/* bWhileOk = TRUE; */
if( hb_itemType( pTag->pForItem ) == HB_IT_BLOCK )
{
hb_vmPushSymbol( &hb_symEval );
hb_vmPush( pTag->pForItem );
hb_vmSend( 0 );
hb_itemCopy( pItem, &hb_stack.Return );
}
else
{
pMacro = ( HB_MACRO_PTR ) hb_itemGetPtr( pTag->pForItem );
hb_macroRun( pMacro );
hb_itemCopy( pItem, hb_stackItemFromTop( - 1 ) );
hb_stackPop();
}
bWhileOk = hb_itemGetL( pItem );
}
else
bWhileOk = TRUE;
if( bWhileOk )
{
if( hb_itemType( pTag->pKeyItem ) == HB_IT_BLOCK )
{
hb_vmPushSymbol( &hb_symEval );
hb_vmPush( pTag->pKeyItem );
hb_vmSend( 0 );
hb_itemCopy( pItem, &hb_stack.Return );
}
else
{
pMacro = ( HB_MACRO_PTR ) hb_itemGetPtr( pTag->pKeyItem );
hb_macroRun( pMacro );
hb_itemCopy( pItem, hb_stackItemFromTop( - 1 ) );
hb_stackPop();
}
switch( hb_itemType( pItem ) )
{
case HB_IT_STRING:
hb_cdxSortInsertWord( pSort, (long) ulRecNo, pItem->item.asString.value,
pItem->item.asString.length );
break;
case HB_IT_INTEGER:
case HB_IT_LONG:
case HB_IT_DOUBLE:
hb_cdxDNtoSort( hb_itemGetND( pItem ), &cTemp[0] );
hb_cdxSortInsertWord( pSort, ulRecNo, (char *) cTemp, 8 );
break;
case HB_IT_LOGICAL:
cTemp[0] = (BYTE) (hb_itemGetL( pItem ) ? 'T' : 'F');
hb_cdxSortInsertWord( pSort, ulRecNo, (char *) cTemp, 1 );
break;
case HB_IT_DATE:
hb_cdxDNtoSort( (double) hb_itemGetDL( pItem ), &cTemp[0] );
hb_cdxSortInsertWord( pSort, ulRecNo, (char *) cTemp, 8 );
break;
default:
printf( "hb_cdxTagDoIndex( LPCDXTAG pTag )" );
}
}
}
if( pSort->WordCount > 0 )
hb_cdxSortDisplayWord( pSort );
else
hb_cdxTagEmptyIndex( pTag );
hb_cdxSortFree( pSort );
hb_itemRelease( pItem );
}
pTag->TagChanged = TRUE;
hb_cdxTagTagStore( pTag );
pTag->pIndex->pArea->ulRecNo = 0;
}
static void hb_cdxTagEmptyIndex( LPCDXTAG pTag )
{
USHORT uiKeyLength, uiBitCount;
CDXDATA pData;
pTag->RootBlock = hb_cdxIndexGetAvailPage( pTag->pIndex );
memset( &pData, 0, sizeof( CDXDATA ) );
pData.Node_Atr = 3;
pData.Left_Ptr = pData.Rght_Ptr = -1;
uiKeyLength = pTag->uiLen;
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->pIndex, pTag->RootBlock, &pData, sizeof( CDXDATA ) );
}
static void hb_cdxTagTagStore( LPCDXTAG pTag )
{
USHORT uiForLen;
CDXTAGHEADER 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( CDXTAGHEADER ) );
pHeader.lRoot = pTag->RootBlock;
pHeader.uiKeySize = pTag->uiLen;
pHeader.bType = pTag->OptFlags;
pHeader.bSignature = 1;
if( !pTag->AscendKey )
pHeader.iDescending = 1;
pHeader.iFilterPos = 1 + ( pTag->KeyExpr == NULL ? 0 : strlen( pTag->KeyExpr ) );
pHeader.iExprLen = pHeader.iFilterPos;
if( pTag->KeyExpr != NULL )
strcpy( ( char * ) pHeader.KeyPool, pTag->KeyExpr );
uiForLen = pTag->ForExpr == NULL ? 0 : strlen( pTag->ForExpr );
if( uiForLen > 0 )
{
pHeader.iFilterLen = uiForLen + 1;
strcpy( ( char * ) pHeader.KeyPool + pHeader.iExprLen, pTag->ForExpr );
}
else
pHeader.iFilterLen = 1;
hb_cdxIndexPageWrite( pTag->pIndex, pTag->TagBlock, &pHeader, sizeof( CDXTAGHEADER ) );
}
static void hb_cdxTagTagOpen( LPCDXTAG pTag, BYTE bCode )
{
hb_cdxIndexLockRead( pTag->pIndex, pTag );
hb_cdxTagTagClose( pTag );
pTag->RootBlock = hb_cdxTagNewRoot( pTag );
pTag->RootPage = hb_cdxPageNew( pTag, NULL, pTag->RootBlock );
/*
if( bCode == 2 )
return;
*/
if( bCode != 2 )
{
if( bCode == 0 )
hb_cdxTagKeyRead( pTag, TOP_RECORD );
else
printf( "hb_cdxTagTagOpen()" );
}
hb_cdxIndexUnLockRead( pTag->pIndex, pTag );
}
static void hb_cdxTagTagClose( LPCDXTAG pTag )
{
if( pTag->RootPage != NULL )
{
hb_cdxPageFree( pTag->RootPage );
pTag->RootPage = NULL;
}
if( pTag->TagChanged )
hb_cdxTagTagStore( pTag );
}
static LONG hb_cdxTagNewRoot( LPCDXTAG pTag )
{
CDXTAGHEADER pHeader;
hb_cdxIndexPageRead( pTag->pIndex, pTag->TagBlock, &pHeader, sizeof( CDXTAGHEADER ) );
return pHeader.lRoot;
}
static void hb_cdxTagPageLoad( LPCDXTAG pTag, LPPAGEINFO pPage, short noKeys )
{
CDXDATA pData;
hb_cdxIndexPageRead( pTag->pIndex, 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, noKeys );
else
hb_cdxTagIntNodeBuild( pTag, &pData, pPage );
}
pPage->Changed = FALSE;
}
static void hb_cdxTagKeyRead( LPCDXTAG pTag, BYTE bTypRead )
{
pTag->CurKeyInfo->Tag = 0;
if( pTag->RootPage == NULL )
return;
hb_cdxIndexLockRead( pTag->pIndex, pTag );
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 );
/* -----------------10/10/2001 19:04-----------------
Disable this test for now.
--------------------------------------------------
if( pTag->pForItem != NULL )
printf( "hb_cdxTagKeyRead()" );
else
pTag->TagBOF = !hb_cdxPageReadTopKey( pTag->RootPage );
*/
pTag->TagBOF = !hb_cdxPageReadTopKey( pTag->RootPage );
/* -----------------10/10/2001 19:04-----------------
Disable this test for now.
--------------------------------------------------
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 );
/* -----------------10/10/2001 19:04-----------------
Disable this test for now.
--------------------------------------------------
if( pTag->pForItem != NULL )
printf( "hb_cdxTagKeyRead()" );
else
pTag->TagEOF = !hb_cdxPageReadBottomKey( pTag->RootPage );
*/
pTag->TagEOF = !hb_cdxPageReadBottomKey( pTag->RootPage );
/* -----------------10/10/2001 19:04-----------------
Disable this test for now.
--------------------------------------------------
if( pTag->pForItem != NULL )
{
printf( "hb_cdxTagTestRange()" );
}
*/
if( pTag->TagBOF )
pTag->TagEOF = TRUE;
pTag->TagBOF = pTag->TagEOF;
break;
case NEXT_RECORD:
/* -----------------10/10/2001 19:04-----------------
Disable this test for now.
--------------------------------------------------
while( TRUE )
{
pTag->TagEOF = !hb_cdxPageReadNextKey( pTag->RootPage );
if( pTag->pForItem != NULL )
printf( "hb_cdxTagKeyRead()" );
else
break;
}
*/
pTag->TagEOF = !hb_cdxPageReadNextKey( pTag->RootPage );
break;
case PREV_RECORD:
/* -----------------10/10/2001 19:04-----------------
Disable this test for now.
--------------------------------------------------
while( TRUE )
{
pTag->TagBOF = !hb_cdxPageReadPrevKey( pTag->RootPage );
if( pTag->pForItem != NULL )
printf( "hb_cdxTagKeyRead()" );
else
break;
}
break;
*/
pTag->TagBOF = !hb_cdxPageReadPrevKey( pTag->RootPage );
}
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;
}
hb_cdxIndexUnLockRead( pTag->pIndex, pTag );
}
static void hb_cdxTagKeyAdd( LPCDXTAG pTag, LPKEYINFO pKey )
{
int iSeek;
LONG lOldXtra;
LPKEYINFO pNewKey;
lOldXtra = pKey->Xtra;
pKey->Xtra = pKey->Tag;
hb_cdxTagTagOpen( pTag, 0 );
pNewKey = hb_cdxKeyNew();
pNewKey = hb_cdxKeyCopy( pNewKey, pKey );
pTag->TagBOF = pTag->TagEOF = FALSE;
iSeek = hb_cdxPageSeekKey( pTag->RootPage,
pTag->UniqueKey ? CDX_IGNORE_REC_NUM : pNewKey->Tag, pNewKey, TRUE );
if( pTag->UniqueKey && iSeek == 0 )
{
}
else 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( LPCDXTAG 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( LPCDXTAG 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->pIndex->hFile, 0, FS_END );
else
sr = pTag->pIndex->pArea->ulRecCount;
uiKeyLength = pTag->uiLen;
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; */
cd = p->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->pIndex );
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->pIndex, NPN, pData, CDX_PAGELEN );
if( lp > 0 )
{
hb_cdxIndexPageRead( pTag->pIndex, lp, pData, CDX_PAGELEN );
pData->Rght_Ptr = NPN;
hb_cdxIndexPageWrite( pTag->pIndex, lp, pData, CDX_PAGELEN );
}
memset( pData, 0, CDX_PAGELEN );
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->pIndex, PN, pData, sizeof( CDXDATA ) );
}
static USHORT hb_cdxTagFillExternalNode( LPCDXTAG 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->uiLen - ( * p )->length ;
if( q != NULL )
{
hb_cdxKeyCompare( * p, q, &cd, TRUE );
if( cd > 0 )
cd--;
}
else
cd = 0;
q = * p;
PIK->Space -= pTag->uiLen + 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->uiLen - cd - ct;
if( pTag->uiLen - cd - ct > 0 )
memcpy( &pData->cdxu.External.ExtData[ k ], ( * p )->Value + cd,
pTag->uiLen - cd - ct );
i++;
ck++;
pData->Entry_Ct++;
}
return ck;
}
static void hb_cdxTagExtNodeBuild( LPCDXTAG pTag, LPCDXDATA pData, LPPAGEINFO PIK, short noKeys )
{
USHORT k, i, v, c, t, d;
LONG r;
LPKEYINFO pKey, pLastKey;
static char szBuffer[ CDX_MAXKEY + 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;
if ( noKeys )
{
PIK->uiKeys = pData->Entry_Ct;
}
else
{
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->uiLen - d - t;
if( pTag->uiLen - d - t > 0 )
memcpy( &szBuffer[ d ], &pData->cdxu.External.ExtData[ k ],
pTag->uiLen - d - t );
szBuffer[ pTag->uiLen - t ] = 0;
pKey = hb_cdxKeyNew();
pKey->Tag = r;
pKey->Xtra = r;
pKey->length = pTag->uiLen - t;
pKey->Value = (char *) hb_xgrab( pKey->length + 1 );
memcpy( pKey->Value, szBuffer, pKey->length );
pKey->Value[ pKey->length ] = 0;
if( PIK->pKeys == NULL )
PIK->pKeys = pKey;
else
{
pLastKey = PIK->pKeys;
while( pLastKey->pNext )
pLastKey = pLastKey->pNext;
pLastKey->pNext = pKey;
}
PIK->uiKeys++;
i++;
}
}
}
/* Read a tag definition from the index file
*
* pTag = structure with a tag information
*/
static void hb_cdxTagTagLoad( LPCDXTAG pTag )
{
CDXTAGHEADER pHeader;
HB_MACRO_PTR pMacro;
/* read the page from a file */
hb_cdxIndexLockRead( pTag->pIndex, pTag );
hb_cdxIndexPageRead( pTag->pIndex, pTag->TagBlock, &pHeader, sizeof( CDXTAGHEADER ) );
hb_cdxIndexUnLockRead( pTag->pIndex, pTag );
pTag->RootBlock = pHeader.lRoot;
/* Return if:
* no root page allocated
* invalid root page offset (position inside an index file)
* invalid key value length
*/
if( pTag->RootBlock == 0 || pTag->RootBlock % CDX_PAGELEN > 0 ||
(ULONG) pTag->RootBlock > hb_fsSeek( pTag->pIndex->hFile, 0, FS_END ) ||
pHeader.uiKeySize > CDX_MAXKEY )
return;
pTag->uiLen = pHeader.uiKeySize;
pTag->MaxKeys = ( CDX_PAGELEN - 12 ) / ( pTag->uiLen + 8 );
pTag->OptFlags = pHeader.bType;
pTag->UniqueKey = ( pTag->OptFlags & 0x01 );
pTag->AscendKey = ( pHeader.iDescending == 0 );
pTag->KeyExpr = ( char * ) hb_xgrab( CDX_MAXKEY + 1 );
/* QUESTION: Is UPPER a valid operation here?
* This will break expressions like:
* somefield+'smallcaps'+otherfield
*/
hb_strncpyUpper( pTag->KeyExpr, ( char * ) pHeader.KeyPool, CDX_MAXKEY );
if( pTag->OptFlags < 0x80 && pTag->KeyExpr[ 0 ] == 0 )
return;
if( pTag->OptFlags & 0x80 )
return;
SELF_COMPILE( (AREAP) pTag->pIndex->pArea, ( BYTE * ) pTag->KeyExpr );
pTag->pKeyItem = pTag->pIndex->pArea->valResult;
pTag->pIndex->pArea->valResult = NULL;
pMacro = ( HB_MACRO_PTR ) hb_itemGetPtr( pTag->pKeyItem );
hb_macroRun( pMacro );
/*
This line must be replace the next one when hb_macroRun is fixed.
By now it do the work as only string keys are supported.
switch( hb_itemType( &hb_stack.Return ) )
*/
switch( hb_itemType( hb_stackItemFromTop( -1 ) ) )
{
case HB_IT_INTEGER:
case HB_IT_LONG:
case HB_IT_DOUBLE:
pTag->uiType = 'N';
/* pTag->uiLen = 10; */
pTag->uiLen = 8;
break;
case HB_IT_DATE:
pTag->uiType = 'D';
pTag->uiLen = 8;
break;
case HB_IT_LOGICAL:
pTag->uiType = 'L';
pTag->uiLen = 1;
break;
case HB_IT_STRING:
pTag->uiType = 'C';
/*
pTag->uiLen = hb_stack.Return.item.asString.length > CDX_MAXKEY ? CDX_MAXKEY :
hb_stack.Return.item.asString.length;
*/
pTag->uiLen = ( hb_stackItemFromTop( -1 ) )->item.asString.length > CDX_MAXKEY ? CDX_MAXKEY :
( hb_stackItemFromTop( -1 ) )->item.asString.length;
break;
}
hb_stackPop(); /* pop macro evaluated value */
/* Check if there is a FOR expression */
if( pHeader.KeyPool[ strlen( pTag->KeyExpr ) + 1 ] == 0 )
return;
pTag->ForExpr = ( char * ) hb_xgrab( CDX_MAXKEY + 1 );
hb_strncpyUpper( pTag->ForExpr, ( const char * ) pHeader.KeyPool +
strlen( pTag->KeyExpr ) + 1, CDX_MAXKEY );
SELF_COMPILE( (AREAP) pTag->pIndex->pArea, ( BYTE * ) pTag->ForExpr );
pTag->pForItem = pTag->pIndex->pArea->valResult;
pTag->pIndex->pArea->valResult = NULL;
pMacro = ( HB_MACRO_PTR ) hb_itemGetPtr( pTag->pForItem );
hb_macroRun( pMacro );
if( hb_itemType( hb_stackItemFromTop( -1 ) ) != HB_IT_LOGICAL )
{
hb_macroDelete( pMacro );
hb_itemRelease( pTag->pForItem );
pTag->pForItem = NULL;
hb_xfree( pTag->ForExpr );
pTag->ForExpr = NULL;
}
hb_stackPop();
}
static void hb_cdxTagSetRoot( LPCDXTAG pTag, LPPAGEINFO PIK )
{
LONG NRN, TmpTag;
LPKEYINFO p, TmpStr;
PIK->Owner = hb_cdxPageNew( pTag, NULL, 0 );
NRN = hb_cdxIndexGetAvailPage( pTag->pIndex );
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( LPCDXTAG 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->pIndex );
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->pIndex, NPN, pData, CDX_PAGELEN );
if( lp > 0 )
{
hb_cdxIndexPageRead( pTag->pIndex, lp, pData, CDX_PAGELEN );
pData->Rght_Ptr = NPN;
hb_cdxIndexPageWrite( pTag->pIndex, lp, pData, CDX_PAGELEN );
}
memset( pData, 32, CDX_PAGELEN );
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->pIndex, PN, pData, CDX_PAGELEN );
}
static USHORT hb_cdxTagFillInternalNode( LPCDXTAG pTag, LPCDXDATA pData,
LPPAGEINFO PIK, USHORT kcnt,
USHORT ck, LPKEYINFO * p )
{
USHORT i, v;
LONG r;
i = 0;
memset( pData->cdxu.Internal.IntData, ( pTag->uiType == 'C' ) ? 32 : 0,
sizeof( pData->cdxu.Internal.IntData ) );
while( i < kcnt && ck < PIK->uiKeys )
{
* p = hb_cdxPageGetKey( PIK, ck );
v = i * ( pTag->uiLen + 8 );
memcpy( &pData->cdxu.Internal.IntData[ v ],
( * p )->Value,
( * p )->length );
v += pTag->uiLen;
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( LPCDXTAG pTag, LPCDXDATA pData, LPPAGEINFO pPage )
{
USHORT i, v;
LONG r, n;
LPKEYINFO pKey, pLastKey;
static char szBuffer[ CDX_MAXKEY + 1 ];
i = 0;
while( i < pData->Entry_Ct )
{
v = i * ( pTag->uiLen + 8 );
memmove( szBuffer, pData->cdxu.Internal.IntData + v, pTag->uiLen );
szBuffer[ pTag->uiLen ] = 0;
v += pTag->uiLen;
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->uiType == 'C' )
{
v = strlen( szBuffer );
while( v > 0 && szBuffer[ v - 1 ] == ' ' )
v--;
szBuffer[ v ] = 0;
}
else
{
v = pTag->uiLen;
while( v > 0 && szBuffer[ v - 1 ] == 0 )
v--;
szBuffer[ v ] = 0;
}
pKey->length = v;
pKey->Value = (char *) hb_xgrab( v + 1 );
memcpy( pKey->Value, szBuffer, v );
pKey->Value[v] = 0;
pKey->fString = ( pTag->uiType == 'C' ? TRUE : FALSE);
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( LPCDXTAG pTag, LPKEYINFO pKey )
{
int K;
LONG ret = 0;
pTag->CurKeyInfo->Tag = 0;
hb_cdxTagTagOpen( pTag, 0 );
if( pTag->RootPage == NULL )
return 0;
pTag->TagBOF = pTag->TagEOF = FALSE;
K = hb_cdxPageSeekKey( pTag->RootPage, pKey->Tag, pKey, FALSE );
if( K == 0 )
{
hb_cdxPageRetrieveKey( pTag->RootPage, &pTag->CurKeyInfo );
ret = pTag->CurKeyInfo->Tag;
}
else if( K < 0 )
{
hb_cdxPageRetrieveKey( pTag->RootPage, &pTag->CurKeyInfo );
}
else
pTag->TagEOF = TRUE;
if ( pKey->Tag == CDX_MAX_REC_NUM ) {
USHORT dav;
hb_cdxPageRetrieveKey( pTag->RootPage, &pTag->CurKeyInfo );
hb_cdxTagKeyRead( pTag, PREV_RECORD );
if ( pTag->CurKeyInfo->Tag ) {
if ( hb_cdxKeyCompare( pKey, pTag->CurKeyInfo, &dav, FALSE ) == 0 )
ret = pTag->CurKeyInfo->Tag;
}
}
return ret;
}
/* end hb_cdxTagxxx */
/* end hb_cdxTagxxx */
/* hb_cdxPagexxx */
/* #include "cdxpage.c" */
/* hb_cdxPagexxx */
static LPPAGEINFO hb_cdxPageNew( LPCDXTAG PIT, LPPAGEINFO PIK, LONG FilePosn )
{
LPPAGEINFO pPage;
pPage = ( LPPAGEINFO ) hb_xgrab( sizeof( HB_PAGEINFO ) );
memset( pPage, 0, sizeof( HB_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
{
pPage->TagParent->CurKeyInfo =
hb_cdxKeyCopy( pPage->TagParent->CurKeyInfo, pKey );
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;
*/
if( hb_cdxPageGetChild( pPage, pKey->Tag ) )
return hb_cdxPageReadBottomKey( pPage->Child );
else
return FALSE;
}
else
{
pPage->TagParent->CurKeyInfo =
hb_cdxKeyCopy( pPage->TagParent->CurKeyInfo, pKey );
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->uiType != '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;
LONG TempTag;
if( pPage->Child != NULL )
hb_cdxPageInsertKey( pPage->Child, pKey, bAddAfter );
else
{
pNewKey = hb_cdxKeyNew();
pNewKey = hb_cdxKeyCopy( pNewKey, pKey );
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()" );*/
TempTag = pNewKey->Tag;
pNewKey->Tag = pPage->Page;
hb_cdxPageReplaceNodeKey( pPage->Owner, pNewKey );
pNewKey->Tag = TempTag;
}
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->pIndex );
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 );
pPage->TagParent->CurKeyInfo =
hb_cdxKeyCopy( pPage->TagParent->CurKeyInfo, p );
return TRUE;
}
else
{
pPage->CurKey = pPage->uiKeys;
return FALSE;
}
}
}
static BOOL hb_cdxPageReadPrevKey( LPPAGEINFO pPage )
{
BOOL b;
LPKEYINFO p;
if( pPage->uiKeys == 0 )
return FALSE;
if( pPage->PageType < PAGE_LEAF )
{
b = FALSE;
while( ! b && pPage->CurKey >= 0 )
{
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 = pPage->Child->uiKeys - 1;
else
pPage->Child->CurKey = pPage->Child->uiKeys;
}
b = hb_cdxPageReadPrevKey( pPage->Child );
}
else
b = FALSE;
if( !b )
pPage->CurKey--;
}
if( !b )
pPage->CurKey = -1;
return b;
}
else
{
pPage->CurKey--;
if( pPage->CurKey >= 0 )
{
p = hb_cdxPageGetKey( pPage, pPage->CurKey );
pPage->TagParent->CurKeyInfo =
hb_cdxKeyCopy( pPage->TagParent->CurKeyInfo, p );
return TRUE;
}
else
{
pPage->CurKey = -1;
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, 0 );
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 );
*pKey = hb_cdxKeyCopy( *pKey, pNewKey );
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->pIndex->NextAvail > 0 &&
Tag > pPage->TagParent->pIndex->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--;
pPage->Changed = TRUE;
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();" ); */
hb_cdxPageReplaceNodeKey( pPage->Owner, p );
p->Tag = TempTag;
}
else
/* printf( "DeleteNodeKey();" ); */
hb_cdxPageDeleteNodeKey( pPage->Owner );
}
}
}
static void hb_cdxPageReplaceNodeKey( LPPAGEINFO pPage, LPKEYINFO pKey )
{
LPKEYINFO p, pPrevKey;
LONG TempTag;
p = hb_cdxPageGetKey( pPage, pPage->CurKey );
p = hb_cdxKeyCopy( p, pKey );
if( !pPage->CurKey )
pPage->pKeys = p;
else
{
pPrevKey = hb_cdxPageGetKey( pPage, pPage->CurKey - 1 );
pPrevKey->pNext = p;
}
pPage->Changed = TRUE;
if( pPage->Owner != NULL && pPage->CurKey >= pPage->uiKeys - 1 )
{
TempTag = p->Tag;
p->Tag = pPage->Page;
hb_cdxPageReplaceNodeKey( pPage->Owner, pKey );
p->Tag = TempTag;
}
return;
}
static void hb_cdxPageDeleteNodeKey( LPPAGEINFO pPage )
{
BOOL lastone;
LONG TempTag;
LPKEYINFO p, pPrevKey;
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;
hb_cdxPageReplaceNodeKey( pPage->Owner, p );
p->Tag = TempTag;
}
else
hb_cdxPageDeleteNodeKey( pPage->Owner );
}
}
/* end hb_cdxPagexxx */
/* end hb_cdxPagexxx */
/* hb_cdxIndexxxx */
/* #include "cdxindex.c" */
/* hb_cdxIndexxxx */
static LPCDXINDEX hb_cdxIndexNew( AREAP pArea )
{
LPCDXINDEX pIndex;
pIndex = ( LPCDXINDEX ) hb_xgrab( sizeof( CDXINDEX ) );
memset( pIndex, 0, sizeof( CDXINDEX ) );
pIndex->hFile = FS_ERROR;
pIndex->pArea = (LPCDXAREA) pArea;
pIndex->NextAvail = -1;
return pIndex;
}
static void hb_cdxIndexFree( LPCDXINDEX pIndex )
{
LPCDXTAG pTag;
hb_cdxIndexLockWrite ( pIndex, NULL );
/* Free Compound tag */
if( pIndex->pCompound != NULL )
{
hb_cdxTagTagClose( pIndex->pCompound );
hb_cdxTagFree( pIndex->pCompound );
pIndex->pCompound = NULL;
}
/* Free all tags */
while( pIndex->TagList )
{
pTag = pIndex->TagList;
pIndex->TagList = pTag->pNext;
hb_cdxTagFree( pTag );
}
hb_cdxIndexUnLockWrite ( pIndex, NULL );
/* Close file */
if( pIndex->hFile != FS_ERROR )
hb_fsClose( pIndex->hFile );
if ( pIndex->fShared && ( pIndex->lockWrite || pIndex->lockRead ) )
hb_errInternal( 9104, "hb_cdxIndexFree: index file still locked.", "", "" );
if( pIndex->szFileName != NULL )
hb_xfree( pIndex->szFileName );
hb_xfree( pIndex );
}
static LONG hb_cdxIndexGetAvailPage( LPCDXINDEX pIndex )
{
if( pIndex->NextAvail == -1 )
hb_cdxIndexResetAvailPage( pIndex );
pIndex->NextAvail += CDX_PAGELEN;
return pIndex->NextAvail - CDX_PAGELEN;
}
static void hb_cdxIndexResetAvailPage( LPCDXINDEX pIndex )
{
pIndex->NextAvail = hb_fsSeek( pIndex->hFile, 0, FS_END );
}
static void hb_cdxIndexPageRead( LPCDXINDEX pIndex, LONG lPos, void * pBuffer,
USHORT uiSize )
{
/* testing properly rights */
if ( pIndex->fShared && !pIndex->lockRead )
hb_errInternal( 9103, "hb_cdxIndexPageRead on not locked index file.", "", "" );
if( hb_fsSeek( pIndex->hFile, lPos, FS_SET ) == (ULONG) lPos )
hb_fsRead( pIndex->hFile, ( BYTE * ) pBuffer, uiSize );
}
static void hb_cdxIndexPageWrite( LPCDXINDEX pIndex, LONG lPos, void * pBuffer,
USHORT uiSize )
{
/* testing properly rights */
if ( pIndex->fReadonly )
hb_errInternal( 9101, "hb_cdxIndexPageWrite on readonly database.", "", "" );
/* if ( pIndex->fShared && !pIndex->lockWrite ) */
if ( pIndex->fShared && !pIndex->lockRead )
hb_errInternal( 9102, "hb_cdxIndexPageWrite on not locked index file.", "", "" );
pIndex->changesWritten = 1;
if( !( ( hb_fsSeek( pIndex->hFile, lPos, FS_SET ) == (ULONG) lPos ) &&
( hb_fsWrite( pIndex->hFile, ( BYTE * ) pBuffer, uiSize ) == uiSize) ) )
hb_errInternal( 1010, "Write in index page failed.", "", "" );
}
static void hb_cdxIndexAddTag( LPCDXINDEX pIndex, char * szTagName, char * szKeyExp,
PHB_ITEM pKeyItem, BYTE bType, USHORT uiLen, char * szForExp,
PHB_ITEM pForItem, BOOL bAscending, BOOL bUnique )
{
LPCDXTAG pTag, pLastTag;
LPKEYINFO pKey;
hb_cdxTagTagOpen( pIndex->pCompound, 0 );
pKey = hb_cdxKeyNew();
pKey = hb_cdxKeyPutC( pKey, szTagName );
pTag = pIndex->TagList;
pLastTag = NULL;
while( pTag != NULL )
{
if( hb_stricmp( pTag->szName, szTagName ) == 0 )
{
pKey->Tag = pTag->TagBlock;
if( hb_cdxTagKeyFind( pIndex->pCompound, pKey ) > 0 )
hb_cdxPageDeleteKey( pIndex->pCompound->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 );
pKey = hb_cdxKeyPutC( pKey, pTag->szName );
pKey->Tag = pTag->TagBlock;
hb_cdxTagKeyAdd( pIndex->pCompound, pKey );
hb_cdxKeyFree( pKey );
pIndex->pCompound->RootPage->Changed = TRUE;
hb_cdxTagTagClose( pIndex->pCompound );
}
static USHORT hb_cdxIndexCheckVersion( LPCDXINDEX pIndex )
{
USHORT ret = 0;
ULONG ulVersion;
LPCDXTAG pTag;
if( (hb_fsSeek( pIndex->hFile, 0x08, FS_SET ) == 0x08) &&
(hb_fsRead( pIndex->hFile, ( BYTE * ) &ulVersion, 4) == 4) )
{
ulVersion = hb_cdxSwapBytes( ulVersion );
if ( ulVersion == pIndex->ulVersion ) {
ret = 1;
}
else
{
pIndex->ulVersion = ulVersion;
pTag = pIndex->TagList;
while ( pTag ) {
if( pTag->RootPage != NULL )
{
if ( !pTag->HotKey) {
hb_errInternal( 9110, "hb_cdxIndexCheckVersion: ulVersion changed and !HotKey.", "", "" );
}
hb_cdxTagTagOpen( pTag, 0 );
hb_cdxTagKeyFind( pTag, pTag->HotKey );
}
pTag = pTag->pNext;
}
}
}
else
hb_errInternal( 2155, "hb_cdxIndexCheckVersion: Read error on index heading page.", "", "" );
return ret;
}
static USHORT hb_cdxIndexLockRead( LPCDXINDEX pIndex, LPCDXTAG pTag )
{
USHORT ret;
/*
LPCDXINDEX pIndex;
pIndex = pTag->pIndex;
*/
if ( !pIndex->fShared )
return 1;
if ( pIndex->lockRead > 0 ) {
pIndex->lockRead++;
if ( pIndex->lockRead < 0 )
hb_errInternal( 9105, "hb_cdxTagLockRead: bad count of locks.", "", "" );
return 1;
}
/* ret = hb_fsLock ( pIndex->hFile, 0x7FFFFFFEL, 1, FL_LOCK ); */
while (! (ret = hb_fsLock ( pIndex->hFile, 0x7FFFFFFEL, 1, FL_LOCK ) ) );
if ( !ret )
hb_errInternal( 9107, "hb_cdxTagLockRead: lock failure.", "", "" ); /* change into error dbfcdx/1038 */
if ( ret ) {
pIndex->lockRead++;
if ( pIndex->lockRead < 0 )
hb_errInternal( 9105, "hb_cdxTagLockRead: bad count of locks.", "", "" );
if ( pTag )
ret = hb_cdxIndexCheckVersion( pIndex );
}
return ret;
}
static USHORT hb_cdxIndexUnLockRead( LPCDXINDEX pIndex, LPCDXTAG pTag )
{
USHORT ret;
/*
LPCDXINDEX pIndex;
pIndex = pTag->pIndex;
*/
if ( !pIndex->fShared )
return 1;
pIndex->lockRead--;
if( pIndex->lockRead < 0 )
hb_errInternal( 9106, "hb_cdxTagUnLockRead: bad count of locks.", "", "" );
if( pIndex->lockRead > 0 )
return 1;
if ( pTag ) {
pTag = pIndex->TagList;
while ( pTag ) {
if( pTag->TagChanged )
hb_cdxTagTagStore( pTag );
pTag = pTag->pNext;
}
}
if ( pIndex->changesWritten ) {
ULONG ulVersion;
(pIndex->ulVersion)++;
ulVersion = hb_cdxSwapBytes( pIndex->ulVersion );
if( !( (hb_fsSeek( pIndex->hFile, 0x08, FS_SET ) == 0x08) &&
(hb_fsWrite( pIndex->hFile, ( BYTE * ) &ulVersion, 4) == 4) ) )
hb_errInternal( 1010, "Write in index page failed.", "", "" );
pIndex->changesWritten = 0;
}
ret = hb_fsLock ( pIndex->hFile, 0x7FFFFFFEL, 1, FL_UNLOCK );
if ( !ret )
hb_errInternal( 9108, "hb_cdxTagUnLockRead: unlock error.", "", "" );
return ret;
}
/* These two are in case of different lock types (eg: Comix) */
static USHORT hb_cdxIndexLockWrite ( LPCDXINDEX pIndex, LPCDXTAG pTag )
{
return hb_cdxIndexLockRead( pIndex, pTag );
}
static USHORT hb_cdxIndexUnLockWrite ( LPCDXINDEX pIndex, LPCDXTAG pTag )
{
return hb_cdxIndexUnLockRead( pIndex, pTag );
}
/* end hb_cdxIndexxxx */
/* end hb_cdxIndexxxx */
/* hb_cdxSortxxx */
/* #include "cdxsort.c" */
/* hb_cdxSortxxx */
static LPSORTINFO hb_cdxSortNew( LPCDXTAG 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 = ( long * ) hb_xgrab( pSort->ChunkSize * sizeof( LONG ) );
memset( pSort->ChunkList, 0, pSort->ChunkSize * sizeof( LONG ) );
P = ( BYTE * ) 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->pIndex->pArea->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->pIndex, 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 ] != 0 )
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 = ( BYTE * ) 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,
USHORT uiLen )
{
char s[ 8 ];
USHORT cc, nc;
LPSORTDATA wx;
hb_cdxDNtoSort( ( double ) Tag, (BYTE *) &s[0] );
if( pSort->NodeLimit - pSort->NodeCur < uiLen + 8 )
{
cc = pSort->ChunkCur;
nc = pSort->NodeCur;
hb_cdxSortGetNewChunk( pSort );
if( pSort->ChunkCur > 0 )
{
pSort->ChunkCur = cc;
pSort->NodeCur = nc;
}
}
pSort->WordCount++;
memcpy( pSort->WPch+1, Value, uiLen );
pSort->WPch[0] = (BYTE) uiLen;
if( pSort->WPch[0] > 0 )
{
if( pSort->WPch[0] > pSort->KeySize )
pSort->KeySize = pSort->WPch[0];
/* pSort->WPch[0]--; lose last byte! */
/*
Patch for empty fields (> 1)
*/
while( pSort->WPch[0] > 1 && pSort->WPch[ pSort->WPch[0] ] ==
( pSort->CurTag->uiType == 'C' ? ' ' : 0 ) )
{
pSort->WPch[0]--;
}
}
pSort->LevelPtr = pSort->RootLink;
pSort->PriorPtr = 0;
pSort->WCur = 0;
do
hb_cdxSortStuffKey( pSort, &wx, FALSE );
while( pSort->WCur != pSort->WPch[0] );
if( pSort->Unique )
{
if( SORT_GET_NUSE(wx->sortu.A.NUse) == SORT_END_OF_KEY )
return;
SORT_SET_NUSE( wx->sortu.A.NUse, SORT_END_OF_KEY);
}
memcpy( &pSort->WPch[ pSort->WPch[0] + 1 ], s, 8 );
pSort->WPch[0] += 8;
do
hb_cdxSortStuffKey( pSort, &wx, TRUE );
while( pSort->WCur != pSort->WPch[0] );
SORT_SET_NUSE(wx->sortu.A.NUse, SORT_END_OF_WORD);
}
static void hb_cdxSortStuffKey( LPSORTINFO pSort, LPSORTDATA * wx, BOOL fTag )
{
SHORT v;
LONG p1;
LPSORTDATA x;
hb_cdxSortGetNode( pSort, pSort->WPch[ pSort->WCur + 1 ], &p1, fTag );
* 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;
}
v = pSort->WPch[0] - pSort->WCur - 1;
if( v > 0 )
{
if( v > 4 )
v = 4;
memcpy( ( * wx )->sortu.B.ChrStack, &pSort->WPch[ pSort->WCur+1 ], v );
SORT_SET_NUSE( ( * wx )->sortu.A.NUse, SORT_STACK_OF_CHAR );
SORT_SET_STACK_LEN( ( * wx )->sortu.A.NUse, v-1 );
pSort->WCur += v;
}
}
pSort->PriorPtr = p1;
pSort->LevelPtr = ( * wx )->sortu.A.WordArray;
}
static void hb_cdxSortGetNode( LPSORTINFO pSort, BYTE Character,
LONG * NewLink, BOOL fTag )
{
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;
if( fTag )
px->sortu.A.NUse |= SORT_NOT_KEY;
return;
}
p = pSort->LevelPtr;
px = hb_cdxSortLinkGet( pSort, pSort->LevelPtr );
q = pSort->PriorPtr;
if( SORT_GET_NUSE(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 ] = 0;
if( px->sortu.A.NUse & SORT_NOT_KEY )
rx->sortu.A.NUse |= SORT_NOT_KEY;
if( SORT_GET_STACK_LEN( px->sortu.A.NUse ) )
{
SORT_SET_STACK_LEN( px->sortu.A.NUse,
SORT_GET_STACK_LEN( px->sortu.A.NUse ) - 1 );
SORT_SET_NUSE( px->sortu.A.NUse, SORT_STACK_OF_CHAR );
}
else
SORT_SET_NUSE( px->sortu.A.NUse, SORT_ACTIVE_LIST );
p = r;
px = hb_cdxSortLinkGet( pSort, p );
}
if( ( px->sortu.A.NUse & SORT_NOT_KEY ) && !fTag)
df = 1;
else if( fTag && !( px->sortu.A.NUse & SORT_NOT_KEY ) )
df = -1;
/* nation support
else if( !fTag && pSort->CurTag->uiType == 'C' )
df = hb_charcmp( Character, px->sortu.A.Character );
*/
else if( Character > px->sortu.A.Character )
df = 1;
else if( Character < px->sortu.A.Character )
df = -1;
else
df = 0;
if( !pSort->Ascend )
df = -df;
while( px->sortu.A.LevelLink != 0 && df > 0 )
{
q = p;
p = px->sortu.A.LevelLink;
px = hb_cdxSortLinkGet( pSort, p );
if( SORT_GET_NUSE(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 ] = 0;
if( px->sortu.A.NUse & SORT_NOT_KEY )
rx->sortu.A.NUse |= SORT_NOT_KEY;
if( SORT_GET_STACK_LEN( px->sortu.A.NUse ) )
{
SORT_SET_STACK_LEN( px->sortu.A.NUse,
SORT_GET_STACK_LEN( px->sortu.A.NUse ) - 1 );
SORT_SET_NUSE( px->sortu.A.NUse, SORT_STACK_OF_CHAR );
}
else
SORT_SET_NUSE( px->sortu.A.NUse, SORT_ACTIVE_LIST );
p = r;
px = hb_cdxSortLinkGet( pSort, p );
}
if( (px->sortu.A.NUse & SORT_NOT_KEY) && !fTag)
df = 1;
else if( fTag && !( px->sortu.A.NUse & SORT_NOT_KEY ) )
df = -1;
/* nation support
else if( !fTag && pSort->CurTag->uiType == 'C' )
df = hb_charcmp( Character, px->sortu.A.Character );
*/
else if( Character > px->sortu.A.Character )
df = 1;
else if( Character < px->sortu.A.Character )
df = -1;
else
df = 0;
if( !pSort->Ascend )
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;
if( fTag )
rx->sortu.A.NUse |= SORT_NOT_KEY;
* 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 ] = 0;
hb_cdxSortRecurseDict( pSort, pSort->RootLink, 0 );
}
static void hb_cdxSortRecurseDict( LPSORTINFO pSort, LONG WPtr, LONG WBgn )
{
USHORT WCnt;
if( WPtr == 0 )
return;
WCnt = pSort->WPch[ 0 ];
pSort->WAdr = hb_cdxSortLinkGet( pSort, WPtr );
pSort->WPch[ WCnt + 1 ] = pSort->WAdr->sortu.A.Character;
pSort->WPch[ 0 ]++;
if( SORT_GET_NUSE( pSort->WAdr->sortu.A.NUse ) == SORT_STACK_OF_CHAR )
{
memcpy( &pSort->WPch[ pSort->WPch[ 0 ] + 1 ],
pSort->WAdr->sortu.B.ChrStack, 4 );
pSort->WPch[ 0 ] += SORT_GET_STACK_LEN( pSort->WAdr->sortu.A.NUse ) + 1;
}
if( SORT_GET_NUSE(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[ 0 ] = WCnt;
if( pSort->WAdr->sortu.A.LevelLink != 0 &&
SORT_GET_NUSE( pSort->WAdr->sortu.A.NUse) != SORT_STACK_OF_CHAR )
hb_cdxSortRecurseDict( pSort, pSort->WAdr->sortu.A.LevelLink, WCnt );
}
static void hb_cdxSortSendWord( LPSORTINFO pSort, BYTE * Value )
{
LONG Tag;
char * pce;
USHORT uiLen;
uiLen = ( USHORT ) Value[0];
Value++;
pce = (char *) (Value + uiLen - 8) ;
Tag = ( long ) hb_cdxSorttoND( (BYTE *) pce, 8 );
hb_cdxSortOutputWord( pSort, Tag, Value, uiLen-8 );
}
static void hb_cdxSortOutputWord( LPSORTINFO pSort, LONG Tag, BYTE * Value,
USHORT uiLen )
{
pSort->KeyCnt++;
/*
Patch for empty fields
*/
while( uiLen > 0 && Value[uiLen-1] ==
( pSort->CurTag->uiType == 'C' ? ' ' : 0 ) )
{
uiLen--;
}
hb_cdxKeyPut( pSort->KeyWork, Value, uiLen );
hb_cdxSortAddToNode( pSort, 0, Tag, Tag, pSort->KeyWork );
pSort->LastTag = Tag;
hb_cdxKeyCopy( pSort->LastKey, pSort->KeyWork );
}
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->uiLen;
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->pIndex );
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_cdxKeyPutC( pSort->LastKey, "" );
}
m = ~pSort->NodeList[ Lvl ]->cdxu.External.RecNumMask;
ct = ( USHORT ) ( pSort->CurTag->uiLen - Value->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->uiLen +
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->uiLen - cd - ct );
if( pSort->CurTag->uiLen - cd - ct > 0 )
memcpy( &pSort->NodeList[ Lvl ]->cdxu.External.ExtData[ k ],
Value->Value + cd,
pSort->CurTag->uiLen - cd - ct );
pSort->NodeList[ Lvl ]->Entry_Ct++;
if( pSort->NodeList[ Lvl ]->cdxu.External.FreeSpace <
( pSort->CurTag->uiLen + 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->pIndex );
else
pSort->NodeList[ Lvl ]->Rght_Ptr = -1;
pSort->NodeList[ Lvl ]->Node_Atr = 2;
hb_cdxIndexPageWrite( pSort->CurTag->pIndex, 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->uiType == 'C' ? 32 : 0,
sizeof( pSort->NodeList[ Lvl ]->cdxu.Internal.IntData ) );
v = ( USHORT ) ( pSort->NodeList[ Lvl ]->Entry_Ct *
( pSort->CurTag->uiLen + 8 ) );
memcpy( &pSort->NodeList[ Lvl ]->cdxu.Internal.IntData[ v ],
Value->Value, Value->length );
v += pSort->CurTag->uiLen;
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->pIndex );
else
pSort->NodeList[ Lvl ]->Rght_Ptr = -1;
pSort->NodeList[ Lvl ]->Node_Atr = 0;
hb_cdxIndexPageWrite( pSort->CurTag->pIndex, 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;
}
}
/* end hb_cdxSortxxx */
/* end hb_cdxSortxxx */
/* #include "cdxhlp.c" */
/* static LPCDXTAG hb_cdxGetActiveTag( LPCDXINDEX PIF ) */
static LPCDXTAG hb_cdxGetActiveTag( CDXAREAP pArea )
{
LPCDXTAG pTag;
USHORT uiTag;
// if( ! PIF )
if( ! pArea )
return NULL;
uiTag = pArea->uiTag;
if( ! uiTag )
return NULL;
/*
pTag = PIF->TagList;
--uiTag;
while( uiTag && pTag )
{
pTag = pTag->pNext;
--uiTag;
}
*/
pTag = hb_cdxGetTagByNumber( pArea, uiTag );
if( !pTag )
pArea->uiTag = 0;
return pTag;
}
static LPCDXTAG hb_cdxGetTagByNumber(CDXAREAP pArea, USHORT uiTag )
{
LPCDXTAG pTag;
LPCDXINDEX pCdx;
if( ! uiTag )
return NULL;
/*
pTag = pArea->lpIndexes->TagList;
--uiTag;
while( uiTag && pTag )
{
pTag = pTag->pNext;
--uiTag;
}
*/
pCdx = pArea->lpIndexes;
pTag = NULL;
while ( uiTag && pCdx ) {
pTag = pCdx->TagList;
if ( pTag )
uiTag--;
while ( uiTag && pTag ) {
pTag = pTag->pNext;
if ( pTag )
uiTag--;
}
pCdx = pCdx->pNext;
}
return pTag;
}
static USHORT hb_cdxFindTag( CDXAREAP pArea, LPDBORDERINFO pOrderInfo )
{
USHORT uiTag;
if( pOrderInfo->itmOrder )
{
if( hb_itemType( pOrderInfo->itmOrder ) != HB_IT_STRING &&
hb_itemGetNI( pOrderInfo->itmOrder ) == 0 )
uiTag = 0;
else
{
if( hb_itemType( pOrderInfo->itmOrder ) == HB_IT_STRING )
{
LPCDXTAG pTag;
LPCDXINDEX pCdx;
char szName[ CDX_MAX_TAG_NAME_LEN + 1 ];
/*
pTag = pArea->lpIndexes->TagList;
for( uiTag = 0; pTag; uiTag++ )
{
/ * if( !strcmp( pTag->szName, hb_itemGetCPtr( pOrderInfo->itmOrder ) ) ) * /
if( !hb_stricmp( pTag->szName, hb_itemGetCPtr( pOrderInfo->itmOrder ) ) )
break;
pTag = pTag->pNext;
}
if( pTag )
++uiTag;
else
uiTag = 0;
*/
hb_strncpyUpperTrim( szName, hb_itemGetCPtr( pOrderInfo->itmOrder ),
(hb_itemGetCLen( pOrderInfo->itmOrder ) > CDX_MAX_TAG_NAME_LEN) ?
CDX_MAX_TAG_NAME_LEN : hb_itemGetCLen( pOrderInfo->itmOrder ) );
pCdx = pArea->lpIndexes;
pTag = NULL;
uiTag = 0;
while ( pCdx && !pTag) {
pTag = pCdx->TagList;
while ( pTag ) {
uiTag++;
/* if( !hb_stricmp( pTag->szName, hb_itemGetCPtr( pOrderInfo->itmOrder ) ) ) */
if( !hb_stricmp( pTag->szName, szName ) )
break;
pTag = pTag->pNext;
}
pCdx = pCdx->pNext;
}
if ( !pTag )
uiTag = 0;
}
else
{
uiTag = hb_itemGetNI( pOrderInfo->itmOrder );
if ( ! hb_cdxGetTagByNumber(pArea, uiTag ) )
uiTag = 0;
}
}
}
else
uiTag = 0;
return uiTag;
}
static LPCDXTAG hb_cdxReorderTagList ( LPCDXTAG TagList )
{
LPCDXTAG pTag1, pTag2, pTagTmp;
pTag1 = TagList;
while( pTag1->pNext )
{
if( pTag1->TagBlock < pTag1->pNext->TagBlock )
pTag1 = pTag1->pNext;
else
{
if( TagList->TagBlock > pTag1->pNext->TagBlock )
{
pTagTmp = TagList;
TagList = pTag1->pNext;
pTag1->pNext = pTag1->pNext->pNext;
TagList->pNext = pTagTmp;
}
else
{
pTag2 = TagList;
while( pTag2->pNext && (pTag2->pNext->TagBlock < pTag1->pNext->TagBlock) )
pTag2 = pTag2->pNext;
pTagTmp = pTag2->pNext;
pTag2->pNext = pTag1->pNext;
pTag1->pNext = pTag1->pNext->pNext;
pTag2->pNext->pNext = pTagTmp;
}
}
}
return TagList;
}
static ERRCODE hb_cdxGoEof( CDXAREAP pArea )
{
ERRCODE retvalue;
LPCDXTAG pTag;
HB_TRACE(HB_TR_DEBUG, ("cdxGoBottom(%p)", pArea));
pTag = hb_cdxGetActiveTag( pArea );
retvalue = SUPER_GOTO( ( AREAP ) pArea, 0 );
if( pArea->ulRecCount ) {
pArea->fBof = FALSE;
if ( pTag )
pTag->TagBOF = FALSE;
}
pArea->fEof = TRUE;
if ( pTag )
pTag->TagEOF = TRUE;
return retvalue;
}
static BOOL hb_cdxTopScope( LPCDXTAG pTag, LPKEYINFO pKey )
{
USHORT EndPos;
if( pTag->topScope )
return ( hb_cdxKeyCompare( pTag->topScopeKey, pKey, &EndPos, FALSE) <= 0);
else
return TRUE;
}
static BOOL hb_cdxBottomScope( LPCDXTAG pTag, LPKEYINFO pKey )
{
USHORT EndPos;
if( pTag->bottomScope )
return ( hb_cdxKeyCompare( pTag->bottomScopeKey, pKey, &EndPos, FALSE) >= 0);
else
return TRUE;
}
static void hb_cdxTagClearScope( LPCDXTAG pTag, USHORT nScope )
{
PHB_ITEM *pScope;
LPKEYINFO *pScopeKey;
HB_TRACE(HB_TR_DEBUG, ("hb_cdxTagClearScope(%p, %hu)", pTag, nScope));
pScope = (nScope == 0) ? &(pTag->topScope) : &(pTag->bottomScope);
pScopeKey = (nScope == 0) ? &(pTag->topScopeKey) : &(pTag->bottomScopeKey);
if ( *pScope ) {
hb_itemRelease( *pScope );
*pScope = NULL;
}
if ( *pScopeKey ) {
hb_cdxKeyFree( *pScopeKey );
*pScopeKey = NULL;
}
}
static long hb_cdxDBOIKeyCount( CDXAREAP pArea )
{
LPKEYINFO pCurKey;
LPCDXTAG pTag;
LPPAGEINFO pPage1, pPage2;
long lKeyCount = 0;
pTag = hb_cdxGetActiveTag( pArea );
if( pTag )
{
hb_cdxIndexLockRead( pTag->pIndex, pTag );
pCurKey = hb_cdxKeyNew();
pCurKey = hb_cdxKeyCopy( pCurKey, pTag->CurKeyInfo );
if( pTag->topScope || pTag->bottomScope )
{
hb_cdxTagTagOpen( pTag, 0 );
if( pTag->topScope )
hb_cdxTagKeyFind( pTag, pTag->topScopeKey );
else
hb_cdxTagKeyRead( pTag, TOP_RECORD );
while( !pTag->TagEOF && hb_cdxBottomScope( pTag, pTag->CurKeyInfo ) )
{
lKeyCount++;
hb_cdxTagKeyRead( pTag, NEXT_RECORD );
}
}
else
{
hb_cdxTagTagOpen( pTag, 0 );
hb_cdxTagKeyRead( pTag, TOP_RECORD );
pPage1 = pTag->RootPage;
while ( pPage1->Child )
pPage1 = pPage1->Child;
lKeyCount = pPage1->uiKeys;
if ( pPage1->Right != -1 )
{
pPage2 = hb_cdxPageNew( pTag, 0, 0 );
pPage2->Page = pPage1->Right;
while ( pPage2->Page != -1 )
{
hb_cdxTagPageLoad( pTag, pPage2, 1);
lKeyCount += pPage2->uiKeys;
pPage2->Page = pPage2->Right;
}
hb_cdxPageFree( pPage2 );
}
}
hb_cdxTagKeyFind( pTag, pCurKey );
/* hb_cdxTagTagClose( pTag ); */
hb_cdxKeyFree( pCurKey );
hb_cdxIndexUnLockRead( pTag->pIndex, pTag );
}
return lKeyCount;
}
/*
static long hb_cdxDBOIKeyNo( CDXAREAP pArea )
{
LPKEYINFO pNewKey;
LPCDXTAG pTag;
long lKeyNo = 0;
pTag = hb_cdxGetActiveTag( pArea->lpIndexes );
if( pTag && !pArea->fEof && pTag->CurKeyInfo && ((ULONG) pTag->CurKeyInfo->Tag == pArea->ulRecNo) )
{
pNewKey = hb_cdxKeyNew();
pNewKey = hb_cdxKeyCopy( pNewKey, pTag->CurKeyInfo );
hb_cdxTagTagOpen( pTag, 0 );
hb_cdxTagKeyFind( pTag, pNewKey );
while( !pTag->TagBOF && !pTag->TagEOF)
{
lKeyNo++;
hb_cdxTagKeyRead( pTag, PREV_RECORD );
}
hb_cdxTagKeyFind( pTag, pNewKey );
hb_cdxTagTagClose( pTag );
hb_cdxKeyFree( pNewKey );
}
return lKeyNo;
}
*/
static long hb_cdxDBOIKeyNo( CDXAREAP pArea )
{
LPKEYINFO pCurKey;
LPCDXTAG pTag;
LPPAGEINFO pPage1, pPage2;
long lKeyNo = 0;
pTag = hb_cdxGetActiveTag( pArea );
if( pTag && !pArea->fEof && pTag->CurKeyInfo && ((ULONG) pTag->CurKeyInfo->Tag == pArea->ulRecNo) )
{
hb_cdxIndexLockRead( pTag->pIndex, pTag );
pCurKey = hb_cdxKeyNew();
pCurKey = hb_cdxKeyCopy( pCurKey, pTag->CurKeyInfo );
if( pTag->topScope || pTag->bottomScope )
{
hb_cdxTagTagOpen( pTag, 0 );
hb_cdxTagKeyFind( pTag, pCurKey );
if ( hb_cdxTopScope( pTag, pTag->CurKeyInfo ) && hb_cdxBottomScope( pTag, pTag->CurKeyInfo ) )
{
while( !pTag->TagBOF && !pTag->TagEOF && hb_cdxTopScope( pTag, pTag->CurKeyInfo ) )
{
lKeyNo++;
hb_cdxTagKeyRead( pTag, PREV_RECORD );
}
}
}
else
{
hb_cdxTagTagOpen( pTag, 0 );
hb_cdxTagKeyFind( pTag, pCurKey );
if ( !pTag->TagBOF && !pTag->TagEOF ) {
pPage1 = pTag->RootPage;
while ( pPage1->Child )
pPage1 = pPage1->Child;
lKeyNo = pPage1->CurKey + 1;
if ( pPage1->Left != -1 )
{
pPage2 = hb_cdxPageNew( pTag, 0, 0 );
pPage2->Page = pPage1->Left;
while ( pPage2->Page != -1 )
{
hb_cdxTagPageLoad( pTag, pPage2, 1);
lKeyNo += pPage2->uiKeys;
pPage2->Page = pPage2->Left;
}
hb_cdxPageFree( pPage2 );
}
}
}
hb_cdxTagKeyFind( pTag, pCurKey );
/*hb_cdxTagTagClose( pTag ); */
hb_cdxKeyFree( pCurKey );
hb_cdxIndexUnLockRead( pTag->pIndex, pTag );
}
return lKeyNo;
}
/* begin of cleanup --------------------------------------------------------------------------------- */
/*
* -- DBFCDX METHODS --
*/
HB_FUNC( _DBFCDX )
{
}
HB_FUNC( DBFCDX_GETFUNCTABLE )
{
RDDFUNCS * pTable;
USHORT * uiCount;
uiCount = ( USHORT * ) hb_itemGetPtr( hb_param( 1, HB_IT_POINTER ) );
* uiCount = RDDFUNCSCOUNT;
pTable = ( RDDFUNCS * ) hb_itemGetPtr( hb_param( 2, HB_IT_POINTER ) );
HB_TRACE(HB_TR_DEBUG, ("DBFCDX_GETFUNCTABLE(%i, %p)", uiCount, pTable));
if( pTable )
hb_retni( hb_rddInherit( pTable, &cdxTable, &cdxSuper, ( BYTE * ) "DBF" ) );
else
hb_retni( FAILURE );
}
/* #include "cdxrdd.c" */
/*
* -- DBFCDX METHODS --
*/
/* begin of cdxrdd.c */
// ( DBENTRYP_BP ) hb_cdxBof : NULL
// ( DBENTRYP_BP ) hb_cdxEof : NULL
// ( DBENTRYP_BP ) hb_cdxFound : NULL
// ( DBENTRYP_V ) hb_cdxGoBottom
ERRCODE hb_cdxGoBottom( CDXAREAP pArea )
{
LPCDXTAG pTag;
HB_TRACE(HB_TR_DEBUG, ("cdxGoBottom(%p)", pArea));
if( SELF_GOCOLD( ( AREAP ) pArea ) == FAILURE )
return FAILURE;
/*must change to follow ordSetFocus() - done?*/
pTag = hb_cdxGetActiveTag( pArea );
if( ! pTag )
SUPER_GOBOTTOM( ( AREAP ) pArea );
else
{
hb_cdxIndexLockRead( pTag->pIndex, pTag );
hb_cdxTagTagOpen( pTag, 0 );
if( pTag->bottomScope )
hb_cdxSeek( pArea, 1, pTag->bottomScope, 1 );
else
hb_cdxTagKeyRead( pTag, BTTM_RECORD );
SELF_GOTO( ( AREAP ) pArea, pTag->CurKeyInfo->Tag );
hb_cdxIndexUnLockRead( pTag->pIndex, pTag );
}
return SELF_SKIPFILTER( ( AREAP ) pArea, -1 );
}
// ( DBENTRYP_UL ) hb_cdxGoTo
/*
* Position cursor at a specific physical record.
*/
ERRCODE hb_cdxGoTo( CDXAREAP pArea, ULONG ulRecNo )
{
LPKEYINFO pKey;
HB_MACRO_PTR pMacro;
LONG lRecno;
LPCDXTAG pTag;
HB_TRACE(HB_TR_DEBUG, ("hb_cdxGoTo(%p, %lu)", pArea, ulRecNo));
if( SELF_GOCOLD( ( AREAP ) pArea ) == FAILURE )
return FAILURE;
if( SUPER_GOTO( ( AREAP ) pArea, ulRecNo ) == FAILURE )
return FAILURE;
if( pArea->fEof )
/* return FAILURE; */
return SUCCESS;
pTag = hb_cdxGetActiveTag( pArea );
if( ! pTag )
return SUCCESS;
if( !pTag->CurKeyInfo || (ULONG) pTag->CurKeyInfo->Tag != ulRecNo )
{
pKey = hb_cdxKeyNew();
if( hb_itemType( pTag->pKeyItem ) == HB_IT_BLOCK )
{
hb_vmPushSymbol( &hb_symEval );
hb_vmPush( pTag->pKeyItem );
hb_vmSend( 0 );
hb_cdxKeyPutItem( pKey, &hb_stack.Return );
}
else
{
pMacro = ( HB_MACRO_PTR ) hb_itemGetPtr( pTag->pKeyItem );
hb_macroRun( pMacro );
hb_cdxKeyPutItem( pKey, hb_stackItemFromTop( - 1 ) );
hb_stackPop();
}
pKey->Tag = pArea->ulRecNo;
hb_cdxIndexLockRead( pTag->pIndex, pTag );
lRecno = hb_cdxTagKeyFind( pTag, pKey );
hb_cdxIndexUnLockRead( pTag->pIndex, pTag );
pArea->fEof = pTag->TagEOF;
pArea->fBof = pTag->TagBOF;
if( lRecno > 0 )
{
if( ( ULONG ) lRecno == pArea->ulRecNo )
{
hb_cdxKeyFree( pKey );
return SUCCESS;
}
else
{
/* if( !pTag->UniqueKey && !pTag->TagEOF ) */
if( !pTag->TagEOF )
{
USHORT dav;
hb_cdxIndexLockRead( pTag->pIndex, pTag );
while( !pTag->TagEOF && pTag->CurKeyInfo->Tag != lRecno &&
!hb_cdxKeyCompare( pKey, pTag->CurKeyInfo, &dav, TRUE ) )
hb_cdxTagKeyRead( pTag, NEXT_RECORD );
hb_cdxIndexUnLockRead( pTag->pIndex, pTag );
pArea->fEof = pTag->TagEOF;
pArea->fBof = pTag->TagBOF;
}
}
}
else
{
/* Need fixed !!!!!! */
/* Error Index */
}
hb_cdxKeyFree( pKey );
}
return SUCCESS; /* ???? m.b FAILURE */
}
// ( DBENTRYP_I ) hb_cdxGoToId : NULL
/*
* Position the cursor to a specific, physical identity.
*/
/*
ERRCODE hb_cdxGoToId( CDXAREAP pArea, PHB_ITEM pItem )
{
PHB_ITEM pError;
HB_TRACE(HB_TR_DEBUG, ("hb_cdxGoToId(%p, %p)", pArea, pItem));
if( HB_IS_NUMERIC( pItem ) )
return SELF_GOTO( ( AREAP ) pArea, hb_itemGetNL( pItem ) );
else
{
pError = hb_errNew();
hb_errPutGenCode( pError, EG_DATATYPE );
hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_DATATYPE ) );
hb_errPutSubCode( pError, EDBF_DATATYPE );
SELF_ERROR( ( AREAP ) pArea, pError );
hb_errRelease( pError );
return FAILURE;
}
}
*/
// ( DBENTRYP_V ) hb_cdxGoTop
ERRCODE hb_cdxGoTop( CDXAREAP pArea )
{
LPCDXTAG pTag;
HB_TRACE(HB_TR_DEBUG, ("cdxGoTop(%p)", pArea));
if( SELF_GOCOLD( ( AREAP ) pArea ) == FAILURE )
return FAILURE;
/*must change to follow ordSetFocus(), done?*/
pTag = hb_cdxGetActiveTag( pArea );
if( ! pTag )
SUPER_GOTOP( ( AREAP ) pArea );
else
{
hb_cdxIndexLockRead( pTag->pIndex, pTag );
hb_cdxTagTagOpen( pTag, 0 );
if( pTag->topScope )
hb_cdxSeek( pArea, 1, pTag->topScope, 0);
else
hb_cdxTagKeyRead( pTag, TOP_RECORD );
SELF_GOTO( ( AREAP ) pArea, pTag->CurKeyInfo->Tag );
hb_cdxIndexUnLockRead( pTag->pIndex, pTag );
}
return SELF_SKIPFILTER( ( AREAP ) pArea, 1 );
}
// ( DBENTRYP_BIB ) hb_cdxSeek
ERRCODE hb_cdxSeek( CDXAREAP pArea, BOOL bSoftSeek, PHB_ITEM pKey, BOOL bFindLast )
{
PHB_ITEM pError;
ERRCODE retvalue;
LPCDXTAG pTag = hb_cdxGetActiveTag( pArea );
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 ); */
if( SELF_GOCOLD( ( AREAP ) pArea ) == FAILURE )
return FAILURE;
if( ! pTag )
{
pError = hb_errNew();
hb_errPutGenCode( pError, EG_NOORDER );
hb_errPutSubCode( pError, 1020 );
hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_NOORDER ) );
hb_errPutFlags( pError, EF_CANDEFAULT );
SELF_ERROR( ( AREAP ) pArea, pError );
hb_errRelease( pError );
return FAILURE;
}
else
{
LONG lRecno;
LPKEYINFO pKey2;
pKey2 = hb_cdxKeyNew();
hb_cdxKeyPutItem( pKey2, pKey );
if( bFindLast )
pKey2->Tag = CDX_MAX_REC_NUM;
else
pKey2->Tag = CDX_IGNORE_REC_NUM;
pKey2->Xtra = 0;
hb_cdxIndexLockRead( pTag->pIndex, pTag );
lRecno = hb_cdxTagKeyFind( pTag, pKey2 );
/*
if( bFindLast )
{
USHORT dav;
hb_cdxTagKeyRead( pTag, PREV_RECORD );
if ( pTag->CurKeyInfo->Tag ) {
if ( hb_cdxKeyCompare( pKey2, pTag->CurKeyInfo, &dav, FALSE ) == 0 )
lRecno = pTag->CurKeyInfo->Tag;
}
}
*/
pArea->fEof = pTag->TagEOF;
pArea->fBof = pTag->TagBOF;
/* hb_cdxKeyFree( pKey2 ); */
if( lRecno > 0 )
{
switch( pTag->uiType )
{
case 'C':
{
/* fix for key trimming*/
if( (USHORT) pKey->item.asString.length > pTag->uiLen)
{
lRecno = 0;
pTag->TagEOF = 1;
}
else if( strncmp( pKey->item.asString.value, pTag->CurKeyInfo->Value,
( pKey->item.asString.length < pTag->CurKeyInfo->length ?
pKey->item.asString.length : pTag->CurKeyInfo->length) ) != 0 )
{
lRecno = 0;
}
break;
}
}
}
if( lRecno > 0 )
{
retvalue = SELF_GOTO( ( AREAP ) pArea, pTag->CurKeyInfo->Tag );
pArea->fFound = TRUE;
if( retvalue != FAILURE )
if ( hb_set.HB_SET_DELETED || pArea->dbfi.itmCobExpr != NULL )
{
USHORT endPos;
int k;
retvalue = SELF_SKIPFILTER( ( AREAP ) pArea, 1 );
if ( pArea->fEof ) {
pArea->fFound = FALSE;
}
else
{
k = hb_cdxKeyCompare( pKey2, pTag->CurKeyInfo, &endPos, FALSE );
if ( k == 0)
{
pArea->fFound = TRUE;
}
else
{
pArea->fFound = FALSE;
if( !bSoftSeek )
{
//retvalue = SELF_GOTO( ( AREAP ) pArea, 0 );
SELF_GOBOTTOM( ( AREAP ) pArea );
retvalue = SELF_SKIP( ( AREAP ) pArea, 1 );
}
}
}
}
hb_cdxKeyFree( pKey2 );
/* return retvalue; */
}
else
{
hb_cdxKeyFree( pKey2 );
pArea->fFound = FALSE;
if( bSoftSeek && !pTag->TagEOF )
{
//return SELF_GOTO( ( AREAP ) pArea, pTag->CurKeyInfo->Tag );
retvalue = SELF_GOTO( ( AREAP ) pArea, pTag->CurKeyInfo->Tag );
if( retvalue != FAILURE )
if ( hb_set.HB_SET_DELETED || pArea->dbfi.itmCobExpr != NULL )
{
retvalue = SELF_SKIPFILTER( ( AREAP ) pArea, 1 );
}
/* return retvalue; */
}
else
{
SELF_GOBOTTOM( ( AREAP ) pArea );
/* return SELF_SKIP( ( AREAP ) pArea, 1 ); */
retvalue = SELF_SKIP( ( AREAP ) pArea, 1 );
/*pArea->fEof = pTag->TagEOF = TRUE; */
}
}
if( !hb_cdxTopScope( pTag, pTag->CurKeyInfo ) ||
!hb_cdxBottomScope( pTag, pTag->CurKeyInfo ) )
hb_cdxGoEof( pArea );
hb_cdxIndexUnLockRead( pTag->pIndex, pTag );
return retvalue;
}
/*return SUCCESS; */
}
// ( DBENTRYP_L ) hb_cdxSkip : NULL
// ( DBENTRYP_L ) hb_cdxSkipFilter : NULL
// ( DBENTRYP_L ) hb_cdxSkipRaw
ERRCODE hb_cdxSkipRaw( CDXAREAP pArea, LONG lToSkip )
{
LPCDXTAG pTag;
HB_TRACE(HB_TR_DEBUG, ("cdxSkipRaw(%p, %ld)", pArea, lToSkip));
if( SELF_GOCOLD( ( AREAP ) pArea ) == FAILURE )
return FAILURE;
/*must change to follow ordSetFocus()*/
pTag = hb_cdxGetActiveTag( pArea );
if( ! pTag )
SUPER_SKIPRAW( ( AREAP ) pArea, lToSkip );
else
{
hb_cdxIndexLockRead( pTag->pIndex, pTag );
if( pArea->fBof )
SELF_GOTOP( ( AREAP ) pArea );
if( lToSkip == 0 )
{
SUPER_SKIPRAW( ( AREAP ) pArea, 0 );
}
else if( lToSkip > 0 )
{
if( !pArea->fEof )
{
while( !pTag->TagEOF && lToSkip-- > 0 )
{
hb_cdxTagKeyRead( pTag, NEXT_RECORD );
if ( !pTag->TagEOF ) {
if( !hb_cdxTopScope( pTag, pTag->CurKeyInfo ) )
hb_cdxSeek( pArea, 1, pTag->topScope, 0 );
else if( !hb_cdxBottomScope( pTag, pTag->CurKeyInfo ) )
pTag->TagEOF = TRUE;
}
}
if( !pTag->TagEOF )
SELF_GOTO( ( AREAP ) pArea, pTag->CurKeyInfo->Tag );
else
{
hb_cdxGoEof( pArea );
}
}
}
else /* ( lToSkip < 0 ) */
{
if( pArea->fEof )
{
SELF_GOBOTTOM( ( AREAP ) pArea );
lToSkip++;
}
pTag->TagBOF = FALSE;
while( !pTag->TagBOF && lToSkip++ < 0 )
{
hb_cdxTagKeyRead( pTag, PREV_RECORD );
if ( !pTag->TagBOF ) {
if( !hb_cdxTopScope( pTag, pTag->CurKeyInfo ) )
{
hb_cdxSeek( pArea, 1, pTag->topScope, 0 );
pTag->TagBOF = TRUE;
}
else if( !hb_cdxBottomScope( pTag, pTag->CurKeyInfo ) )
hb_cdxSeek( pArea, 1, pTag->bottomScope, 1 );
}
}
if( !pTag->TagBOF )
SELF_GOTO( ( AREAP ) pArea, pTag->CurKeyInfo->Tag );
else
{
pTag->TagBOF = FALSE;
SELF_GOTOP( ( AREAP ) pArea );
pArea->fBof = pTag->TagBOF = TRUE;
}
}
hb_cdxIndexUnLockRead( pTag->pIndex, pTag );
}
/* return SELF_SKIPFILTER( ( AREAP ) pArea, -1 ); */
return SUCCESS;
}
// ( DBENTRYP_VF ) hb_cdxAddField : NULL
// ( DBENTRYP_B ) hb_cdxAppend : NULL
// ( DBENTRYP_I ) hb_cdxCreateFields : NULL
// ( DBENTRYP_V ) hb_cdxDeleteRec : NULL
// ( DBENTRYP_BP ) hb_cdxDeleted : NULL
// ( DBENTRYP_SP ) hb_cdxFieldCount : NULL
// ( DBENTRYP_VF ) hb_cdxFieldDisplay : NULL
// ( DBENTRYP_SSI ) hb_cdxFieldInfo : NULL
// ( DBENTRYP_SVP ) hb_cdxFieldName : NULL
// ( DBENTRYP_V ) hb_cdxFlush : NULL
// ( DBENTRYP_PP ) hb_cdxGetRec : NULL
// ( DBENTRYP_SI ) hb_cdxGetValue
/*
* Obtain the current value of a field.
*/
ERRCODE hb_cdxGetValue( CDXAREAP pArea, USHORT uiIndex, PHB_ITEM pItem )
{
BOOL bDeleted;
HB_TRACE(HB_TR_DEBUG, ("hb_cdxGetValue(%p, %hu, %p)", pArea, uiIndex, pItem));
if( pArea->lpFields[ uiIndex - 1 ].uiType == HB_IT_MEMO )
{
/* Force read record */
if( SELF_DELETED( ( AREAP ) pArea, &bDeleted ) == FAILURE )
return FAILURE;
hb_cdxGetMemo( pArea, uiIndex - 1, pItem );
return SUCCESS;
}
else
return SUPER_GETVALUE( ( AREAP ) pArea, uiIndex, pItem );
}
// ( DBENTRYP_SVL ) hb_cdxGetVarLen
/*
* Obtain the length of a field value.
*/
ERRCODE hb_cdxGetVarLen( CDXAREAP pArea, USHORT uiIndex, ULONG * pLength )
{
BOOL bDeleted;
HB_TRACE(HB_TR_DEBUG, ("hb_cdxGetVarLen(%p, %hu, %p)", pArea, uiIndex, pLength));
/* Force read record */
if( SELF_DELETED( ( AREAP ) pArea, &bDeleted ) == FAILURE )
return FAILURE;
if( pArea->fHasMemo )
* pLength = hb_cdxGetMemoLen( pArea, uiIndex - 1 );
else
* pLength = 0;
return SUCCESS;
}
// ( DBENTRYP_V ) hb_cdxGoCold
/*
* Perform a write of WorkArea memory to the data store.
*/
ERRCODE hb_cdxGoCold( CDXAREAP pArea )
{
LPCDXTAG pTag;
LPKEYINFO pKey;
HB_MACRO_PTR pMacro;
USHORT dav;
USHORT uiTag;
BOOL bForOk;
HB_TRACE(HB_TR_DEBUG, ("hb_cdxGoCold(%p)", pArea));
if( pArea->lpIndexes && pArea->lpIndexes->TagList )
{
pTag = pArea->lpIndexes->TagList;
if( pArea->fRecordChanged )
{
hb_cdxIndexLockWrite ( pTag->pIndex, pTag );
uiTag = 1;
while( pTag )
{
/* test for expresion, working but not tested */
if( pTag->pForItem != NULL )
{
if( hb_itemType( pTag->pForItem ) == HB_IT_BLOCK )
{
hb_vmPushSymbol( &hb_symEval );
hb_vmPush( pTag->pForItem );
hb_vmSend( 0 );
bForOk = hb_itemGetL( &hb_stack.Return );
}
else
{
pMacro = ( HB_MACRO_PTR ) hb_itemGetPtr( pTag->pForItem );
hb_macroRun( pMacro );
bForOk = hb_itemGetL( hb_stackItemFromTop( - 1 ) );
hb_stackPop();
}
}
else
bForOk = TRUE;
pKey = hb_cdxKeyNew();
if( hb_itemType( pTag->pKeyItem ) == HB_IT_BLOCK )
{
hb_vmPushSymbol( &hb_symEval );
hb_vmPush( pTag->pKeyItem );
hb_vmSend( 0 );
hb_cdxKeyPutItem( pKey, &hb_stack.Return );
}
else
{
pMacro = ( HB_MACRO_PTR ) hb_itemGetPtr( pTag->pKeyItem );
hb_macroRun( pMacro );
hb_cdxKeyPutItem( pKey, hb_stackItemFromTop( - 1 ) );
hb_stackPop();
}
pKey->Tag = pArea->ulRecNo;
if( pArea->fAppend )
{
if( bForOk )
{
hb_cdxTagKeyAdd( pTag, pKey );
pTag->RootPage->Changed = TRUE;
/* if( uiTag == pArea->lpIndexes->uiTag) */
if( uiTag == pArea->uiTag)
hb_cdxTagTagStore( pTag );
else
hb_cdxTagTagClose( pTag );
}
}
else
{
if( hb_cdxKeyCompare( pKey, pTag->HotKey, &dav, TRUE ) )
{
/* if( uiTag == pArea->lpIndexes->uiTag || */
if( uiTag == pArea->uiTag ||
hb_cdxTagKeyFind( pTag, pTag->HotKey ) > 0 )
hb_cdxPageDeleteKey( pTag->RootPage );
if( bForOk )
hb_cdxTagKeyAdd( pTag, pKey );
pTag->RootPage->Changed = TRUE;
if( uiTag == pArea->uiTag)
hb_cdxTagTagStore( pTag );
else
hb_cdxTagTagClose( pTag );
}
else
{
if( bForOk )
{
if( uiTag != pArea->uiTag )
hb_cdxTagKeyFind( pTag, pTag->HotKey );
if ( !pTag->CurKeyInfo || (ULONG) pTag->CurKeyInfo->Tag != pArea->ulRecNo )
{
hb_cdxTagKeyAdd( pTag, pKey );
pTag->RootPage->Changed = TRUE;
if( uiTag == pArea->uiTag)
hb_cdxTagTagStore( pTag );
else
hb_cdxTagTagClose( pTag );
}
}
else
{
if (uiTag != pArea->uiTag)
hb_cdxTagKeyFind( pTag, pTag->HotKey );
if ( pTag->CurKeyInfo && (ULONG) pTag->CurKeyInfo->Tag == pArea->ulRecNo )
{
hb_cdxPageDeleteKey( pTag->RootPage );
pTag->RootPage->Changed = TRUE;
if( uiTag == pArea->uiTag)
hb_cdxTagTagStore( pTag );
else
hb_cdxTagTagClose( pTag );
}
}
}
}
hb_cdxKeyFree( pKey );
if( pTag->HotKey )
{
hb_cdxKeyFree( pTag->HotKey );
pTag->HotKey = NULL;
}
/* pTag = pTag->pNext; */
if ( pTag->pNext )
pTag = pTag->pNext;
else
{
hb_cdxIndexUnLockWrite ( pTag->pIndex, pTag );
if ( pTag->pIndex->pNext )
{
pTag = pTag->pIndex->pNext->TagList;
hb_cdxIndexLockWrite ( pTag->pIndex, pTag );
}
else
pTag = NULL;
}
++uiTag;
}
}
}
if( SUPER_GOCOLD( ( AREAP ) pArea ) == FAILURE )
return FAILURE;
return SUCCESS;
}
// ( DBENTRYP_V ) hb_cdxGoHot
/*
* Mark the WorkArea data buffer as hot.
*/
ERRCODE hb_cdxGoHot( CDXAREAP pArea )
{
LPCDXTAG pTag;
/* USHORT uiTag; */
LPKEYINFO pKey;
HB_MACRO_PTR pMacro;
HB_TRACE(HB_TR_DEBUG, ("hb_cdxGoHot(%p)", pArea));
if( SUPER_GOHOT( ( AREAP ) pArea ) == FAILURE )
return FAILURE;
if( pArea->lpIndexes && pArea->lpIndexes->TagList )
{
pTag = pArea->lpIndexes->TagList;
/* uiTag = 1; */
while( pTag )
{
pKey = hb_cdxKeyNew();
if( hb_itemType( pTag->pKeyItem ) == HB_IT_BLOCK )
{
hb_vmPushSymbol( &hb_symEval );
hb_vmPush( pTag->pKeyItem );
hb_vmSend( 0 );
hb_cdxKeyPutItem( pKey, &hb_stack.Return );
}
else
{
pMacro = ( HB_MACRO_PTR ) hb_itemGetPtr( pTag->pKeyItem );
hb_macroRun( pMacro );
hb_cdxKeyPutItem( pKey, hb_stackItemFromTop( - 1 ) );
hb_stackPop();
}
pKey->Tag = pArea->ulRecNo;
pTag->HotKey = pKey;
/* pTag = pTag->pNext; */
if ( pTag->pNext )
pTag = pTag->pNext;
else
{
if ( pTag->pIndex->pNext )
pTag = pTag->pIndex->pNext->TagList;
else
pTag = NULL;
}
/* ++uiTag; */
}
}
return SUCCESS;
}
// ( DBENTRYP_P ) hb_cdxPutRec : NULL
// ( DBENTRYP_SI ) hb_cdxPutValue
/*
* Assign a value to a field.
*/
ERRCODE hb_cdxPutValue( CDXAREAP pArea, USHORT uiIndex, PHB_ITEM pItem )
{
BOOL bDeleted;
PHB_ITEM pError;
HB_TRACE(HB_TR_DEBUG, ("hb_cdxPutValue(%p, %hu, %p)", pArea, uiIndex, pItem));
if( pArea->lpFields[ uiIndex - 1 ].uiType == HB_IT_MEMO )
{
if( HB_IS_MEMO( pItem ) || HB_IS_STRING( pItem ) )
{
/* Force read record */
if( SELF_DELETED( ( AREAP ) pArea, &bDeleted ) == FAILURE )
return FAILURE;
if( !pArea->fPositioned )
return SUCCESS;
/* Buffer is hot? */
if( !pArea->fRecordChanged && SELF_GOHOT( ( AREAP ) pArea ) == FAILURE )
return FAILURE;
if( !hb_cdxPutMemo( pArea, uiIndex - 1, pItem ) )
{
pError = hb_errNew();
hb_errPutGenCode( pError, EG_DATAWIDTH );
hb_errPutDescription( pError, hb_langDGetErrorDesc( EDBF_DATAWIDTH ) );
hb_errPutSubCode( pError, EDBF_DATAWIDTH );
SELF_ERROR( ( AREAP ) pArea, pError );
hb_errRelease( pError );
return FAILURE;
}
/* Update deleted flag */
pArea->pRecord[ 0 ] = (BYTE) (pArea->fDeleted ? '*' : ' ');
return SUCCESS;
}
}
return SUPER_PUTVALUE( ( AREAP ) pArea, uiIndex, pItem);
}
// ( DBENTRYP_V ) hb_cdxRecall : NULL
// ( DBENTRYP_ULP ) hb_cdxRecCount : NULL
// ( DBENTRYP_ISI ) hb_cdxRecInfo : NULL
// ( DBENTRYP_I ) hb_cdxRecNo : NULL
// ( DBENTRYP_S ) hb_cdxSetFieldExtent : NULL
// ( DBENTRYP_P ) hb_cdxAlias : NULL
// ( DBENTRYP_V ) hb_cdxClose
/*
* Close the table in the WorkArea.
*/
ERRCODE hb_cdxClose( CDXAREAP pArea )
{
ERRCODE uiError;
HB_TRACE(HB_TR_DEBUG, ("hb_cdxClose(%p)", pArea));
if( SELF_GOCOLD( ( AREAP ) pArea ) == FAILURE )
return FAILURE;
/* Close all index */
SELF_ORDLSTCLEAR( ( AREAP ) pArea );
/* uiError = SUPER_CLOSE( ( AREAP ) pArea ); */
/* Free root memo block */
if( pArea->fHasMemo && pArea->pMemoRoot )
{
if( pArea->pMemoRoot->fChanged )
{
pArea->pMemoRoot->fChanged = FALSE;
hb_fsSeek( pArea->hMemoFile, 0, FS_SET );
pArea->pMemoRoot->ulNextBlock = hb_cdxSwapBytes( pArea->pMemoRoot->ulNextBlock );
pArea->pMemoRoot->ulBlockSize = hb_cdxSwapBytes( pArea->pMemoRoot->ulBlockSize );
hb_fsWrite( pArea->hMemoFile, ( BYTE * ) pArea->pMemoRoot, sizeof( MEMOROOT ) );
}
hb_xfree( pArea->pMemoRoot );
pArea->pMemoRoot = NULL;
}
uiError = SUPER_CLOSE( ( AREAP ) pArea );
return uiError;
}
// ( DBENTRYP_VP ) hb_cdxCreate : NULL
// ( DBENTRYP_SI ) hb_cdxInfo
/*
* Retrieve information about the current driver.
*/
ERRCODE hb_cdxInfo( CDXAREAP pArea, USHORT uiIndex, PHB_ITEM pItem )
{
HB_TRACE(HB_TR_DEBUG, ("hb_cdxInfo(%p, %hu, %p)", pArea, uiIndex, pItem));
switch( uiIndex )
{
case DBI_MEMOEXT:
hb_itemPutC( pItem, CDX_MEMOEXT );
break;
case DBI_MEMOBLOCKSIZE:
hb_itemPutNI( pItem, pArea->uiMemoBlockSize );
break;
/* case DBI_RDD_VERSION */
default:
return SUPER_INFO( ( AREAP ) pArea, uiIndex, pItem );
}
return SUCCESS;
}
// ( DBENTRYP_V ) hb_cdxNewArea : NULL
// ( DBENTRYP_VP ) hb_cdxOpen
/*
* Open a data store in the WorkArea.
*/
ERRCODE hb_cdxOpen( CDXAREAP pArea, LPDBOPENINFO pOpenInfo )
{
char * szFileName;
DBORDERINFO pExtInfo;
PHB_FNAME pFileName;
DBORDERINFO pOrderInfo;
#ifdef __XHARBOUR__
BYTE aFile[ _POSIX_PATH_MAX + 3 + 10 ];
#endif
/*
USHORT uiFlags;
FHANDLE hFile;
*/
HB_TRACE(HB_TR_DEBUG, ("hb_cdxOpen(%p, %p)", pArea, pOpenInfo));
/* Force exclusive mode
* 0: AUTOSHARE disabled.
* 1: AUTOSHARE enabled.
* 2: force exclusive mode.
* */
if( hb_set.HB_SET_AUTOSHARE == 2 )
pOpenInfo->fShared = FALSE;
if( SUPER_OPEN( ( AREAP ) pArea, pOpenInfo ) == FAILURE )
return FAILURE;
/* Alloc root memo block and read data */
if( pArea->fHasMemo )
{
pArea->pMemoRoot = ( LPMEMOROOT ) hb_xgrab( sizeof( MEMOROOT ) );
memset( pArea->pMemoRoot, 0, sizeof( MEMOROOT ) );
hb_fsSeek( pArea->hMemoFile, 0, FS_SET );
if( hb_fsRead( pArea->hMemoFile, ( BYTE * ) pArea->pMemoRoot, sizeof( MEMOROOT ) ) !=
sizeof( MEMOROOT ) )
return FAILURE;
if( pArea->pMemoRoot->szSignature[ 0 ] == 0 )
{
strcpy( ( char * ) pArea->pMemoRoot->szSignature, "Harbour" );
hb_fsSeek( pArea->hMemoFile, 0, FS_SET );
hb_fsWrite( pArea->hMemoFile, ( BYTE * ) pArea->pMemoRoot, sizeof( MEMOROOT ) );
}
pArea->pMemoRoot->ulNextBlock = hb_cdxSwapBytes( pArea->pMemoRoot->ulNextBlock );
pArea->pMemoRoot->ulBlockSize = hb_cdxSwapBytes( pArea->pMemoRoot->ulBlockSize );
}
/* If SET_AUTOPEN open index */
if( pArea->fHasTags && hb_set.HB_SET_AUTOPEN )
{
pFileName = hb_fsFNameSplit( pArea->szDataFileName );
szFileName = ( char * ) hb_xgrab( _POSIX_PATH_MAX + 3 );
szFileName[ 0 ] = '\0';
if( pFileName->szPath )
strcpy ( szFileName, pFileName->szPath );
strncat( szFileName, pFileName->szName, _POSIX_PATH_MAX -
strlen( szFileName ) );
pExtInfo.itmResult = hb_itemPutC( NULL, "" );
SELF_ORDINFO( ( AREAP ) pArea, DBOI_BAGEXT, &pExtInfo );
strncat( szFileName, pExtInfo.itmResult->item.asString.value, _POSIX_PATH_MAX -
strlen( szFileName ) );
hb_itemRelease( pExtInfo.itmResult );
hb_xfree( pFileName );
/*
uiFlags = (USHORT) (pArea->fReadonly ? FO_READ : FO_READWRITE);
uiFlags |= (USHORT) (pArea->fShared ? FO_DENYNONE : FO_EXCLUSIVE);
hFile = hb_spOpen( ( BYTE * ) szFileName, uiFlags );
if( hFile != FS_ERROR )
{
hb_fsClose( hFile );
*/
#ifdef __XHARBOUR__
if( hb_spFile(( BYTE * ) szFileName ,aFile) )
#else
if( hb_spFile(( BYTE * ) szFileName) )
#endif
{
pOrderInfo.itmResult = hb_itemPutNI( NULL, 0 );
pOrderInfo.atomBagName = hb_itemPutC( NULL, szFileName );
pOrderInfo.itmOrder = NULL;
SELF_ORDLSTADD( ( AREAP ) pArea, &pOrderInfo );
/* pOrderInfo.itmOrder = hb_itemPutNI( NULL, 1 ); */
pOrderInfo.itmOrder = hb_itemPutNI( NULL, hb_set.HB_SET_AUTORDER );
SELF_ORDLSTFOCUS( ( AREAP ) pArea, &pOrderInfo );
hb_itemRelease( pOrderInfo.itmOrder );
SELF_GOTOP( ( AREAP ) pArea );
hb_itemRelease( pOrderInfo.atomBagName );
hb_itemRelease( pOrderInfo.itmResult );
}
hb_xfree( szFileName );
}
return SUCCESS;
}
// ( DBENTRYP_V ) hb_cdxRelease : NULL
// ( DBENTRYP_SP ) hb_cdxStructSize
/*
* Retrieve the size of the WorkArea structure.
*/
ERRCODE hb_cdxStructSize( CDXAREAP pArea, USHORT * uiSize )
{
HB_TRACE(HB_TR_DEBUG, ("hb_cdxStrucSize(%p, %p)", pArea, uiSize));
HB_SYMBOL_UNUSED( pArea );
* uiSize = sizeof( CDXAREA );
return SUCCESS;
}
// ( DBENTRYP_P ) hb_cdxSysName
/*
* Obtain the name of replaceable database driver (RDD) subsystem.
*/
ERRCODE hb_cdxSysName( CDXAREAP pArea, BYTE * pBuffer )
{
HB_TRACE(HB_TR_DEBUG, ("hb_cdxSysName(%p, %p)", pArea, pBuffer));
HB_SYMBOL_UNUSED( pArea );
strncpy( ( char * ) pBuffer, "DBFCDX", HARBOUR_MAX_RDD_DRIVERNAME_LENGTH );
return SUCCESS;
}
// ( DBENTRYP_VEI ) hb_cdxEval : NULL
// ( DBENTRYP_V ) hb_cdxPack
extern ERRCODE hb_cdxPack( CDXAREAP pArea )
{
HB_TRACE(HB_TR_DEBUG, ("nb_cdxPack(%p)", pArea ));
/* Commit changes first */
if( SELF_GOCOLD( ( AREAP ) pArea ) == FAILURE )
return FAILURE;
if( SUPER_PACK( ( AREAP ) pArea ) == SUCCESS )
{
hb_cdxOrderListClear( pArea );
/* return hb_cdxOrderListRebuild( pArea ); */
return TRUE;
}
else
return FAILURE;
}
// ( DBENTRYP_LSP ) hb_cdxPackRec : NULL
// ( DBENTRYP_VS ) hb_cdxSort : NULL
// ( DBENTRYP_VT ) hb_cdxTrans : NULL
// ( DBENTRYP_VT ) hb_cdxTransRec : NULL
// ( DBENTRYP_V ) hb_cdxZap
extern ERRCODE hb_cdxZap ( CDXAREAP pArea )
{
HB_TRACE(HB_TR_DEBUG, ("nb_cdxZap(%p)", pArea ));
if( SUPER_ZAP( ( AREAP ) pArea ) == SUCCESS )
{
hb_cdxOrderListClear( pArea );
/* return hb_cdxOrderListRebuild( pArea ); */
return TRUE;
}
else
return FAILURE;
}
// ( DBENTRYP_VR ) hb_cdxChildEnd : NULL
// ( DBENTRYP_VR ) hb_cdxChildStart : NULL
// ( DBENTRYP_VR ) hb_cdxChildSync : NULL
// ( DBENTRYP_V ) hb_cdxSyncChildren : NULL
// ( DBENTRYP_V ) hb_cdxClearRel : NULL
// ( DBENTRYP_V ) hb_cdxForceRel : NULL
// ( DBENTRYP_SVP ) hb_cdxRelArea : NULL
// ( DBENTRYP_VR ) hb_cdxRelEval : NULL
// ( DBENTRYP_SVP ) hb_cdxRelText : NULL
// ( DBENTRYP_VR ) hb_cdxSetRel : NULL
// ( DBENTRYP_OI ) hb_cdxOrderListAdd
ERRCODE hb_cdxOrderListAdd( CDXAREAP pAreaCdx, LPDBORDERINFO pOrderInfo )
{
USHORT uiFlags;
char * szFileName, * szFileNameDbfPath = NULL, * szBaseName;
AREAP pArea = (AREAP) pAreaCdx;
LPCDXINDEX pIndex;
DBORDERINFO pExtInfo;
PHB_FNAME pFileName;
PHB_ITEM pError = NULL;
BOOL bRetry;
LPCDXTAG pTag, pLastTag;
LPCDXTAG TagList, pTag1, pTag2, pTagTmp;
LPCDXINDEX pIndexTmp;
ULONG ulVersion;
HB_TRACE(HB_TR_DEBUG, ("cdxOrderListAdd(%p, %p)", pArea, pOrderInfo));
if( SELF_GOCOLD( ( AREAP ) pArea ) == FAILURE )
return FAILURE;
/* Close all index for now (it must be fixed!)*/
/* hb_cdxOrderListClear((CDXAREAP) pArea ); */
/* File exists? */
/* Check file name */
szFileName = ( char * ) hb_xgrab( _POSIX_PATH_MAX + 3 );
szFileName[ 0 ] = '\0';
pIndex = hb_cdxIndexNew( pArea );
//pAreaCdx->lpIndexes = pIndex;
/*
if ( pAreaCdx->lpIndexes == NULL) {
pAreaCdx->lpIndexes = pIndex;
}
else
{
pIndexTmp = pAreaCdx->lpIndexes;
while ( pIndexTmp->pNext ) {
pIndexTmp = pIndexTmp->pNext;
}
pIndexTmp->pNext = pIndex;
}
*/
strcpy( szFileName, hb_itemGetCPtr( pOrderInfo->atomBagName ) );
if( strlen( szFileName ) == 0 )
{
hb_cdxOrderListClear( (CDXAREAP) pArea );
hb_xfree( szFileName );
hb_cdxIndexFree( pIndex );
return FAILURE;
}
else
{
pFileName = hb_fsFNameSplit( szFileName );
if( !pFileName->szExtension )
{
pExtInfo.itmResult = hb_itemPutC( NULL, "" );
SELF_ORDINFO( ( AREAP ) pArea, DBOI_BAGEXT, &pExtInfo );
strcat( szFileName, pExtInfo.itmResult->item.asString.value );
hb_itemRelease( pExtInfo.itmResult );
}
szBaseName = ( char * ) hb_xgrab( CDX_MAXTAGNAMELEN + 1 );
hb_strncpyUpper( szBaseName, pFileName->szName, CDX_MAXTAGNAMELEN );
if( !pFileName->szPath )
{
hb_xfree( pFileName );
pFileName = hb_fsFNameSplit( pAreaCdx->szDataFileName );
if( pFileName->szPath )
{
szFileNameDbfPath = ( char * ) hb_xgrab( _POSIX_PATH_MAX + 3 );
szFileNameDbfPath[ 0 ] = '\0';
strcpy( szFileNameDbfPath, pFileName->szPath );
strncat( szFileNameDbfPath, szFileName, _POSIX_PATH_MAX -
strlen( szFileNameDbfPath ) );
}
/* pArea->szDataFileName = (char *) hb_xgrab( strlen( (char * ) pOpenInfo->abName)+1 ); */
}
hb_xfree( pFileName );
}
if ( pAreaCdx->lpIndexes != NULL) {
pIndexTmp = pAreaCdx->lpIndexes;
while ( pIndexTmp && ( strcmp( szBaseName, pIndexTmp->pCompound->szName ) != 0 ) )
pIndexTmp = pIndexTmp->pNext;
if ( pIndexTmp )
{
// index already open, do nothing
// TODO: the full pathname should be compared when APIs are available
// hb_cdxOrderListClear( (CDXAREAP) pArea );
hb_xfree( szFileName );
hb_xfree( szBaseName );
hb_cdxIndexFree( pIndex );
return FAILURE;
}
}
if ( pAreaCdx->lpIndexes == NULL) {
pAreaCdx->lpIndexes = pIndex;
}
else
{
pIndexTmp = pAreaCdx->lpIndexes;
while ( pIndexTmp->pNext ) {
pIndexTmp = pIndexTmp->pNext;
}
pIndexTmp->pNext = pIndex;
}
uiFlags = (USHORT) ( pAreaCdx->fReadonly ? FO_READ : FO_READWRITE );
uiFlags |= (USHORT) ( pAreaCdx->fShared ? FO_DENYNONE : FO_EXCLUSIVE );
do
{
pIndex->hFile = FS_ERROR;
if( szFileNameDbfPath )
pIndex->hFile = hb_spOpen( ( BYTE * ) szFileNameDbfPath, uiFlags );
if( pIndex->hFile != FS_ERROR )
{
pIndex->szFileName = ( char * ) hb_xgrab( strlen( szFileNameDbfPath ) + 1 );
strcpy( pIndex->szFileName, szFileNameDbfPath);
}
else
{
pIndex->hFile = hb_spOpen( ( BYTE * ) szFileName, uiFlags );
if( pIndex->hFile != FS_ERROR )
{
pIndex->szFileName = ( char * ) hb_xgrab( strlen( szFileName ) + 1 );
strcpy( pIndex->szFileName, szFileName);
}
}
if( pIndex->hFile == FS_ERROR )
{
if( !pError )
{
pError = hb_errNew();
hb_errPutGenCode( pError, EG_OPEN );
hb_errPutSubCode( pError, 1003 );
hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_OPEN ) );
hb_errPutFileName( pError, szFileName );
hb_errPutFlags( pError, EF_CANRETRY | EF_CANDEFAULT );
}
bRetry = ( SELF_ERROR( ( AREAP ) pArea, pError ) == E_RETRY );
}
else
bRetry = FALSE;
} while( bRetry );
if( pError )
hb_errRelease( pError );
if( pIndex->hFile == FS_ERROR )
{
hb_cdxOrderListClear( (CDXAREAP) pArea );
if( szFileNameDbfPath != NULL )
hb_xfree( szFileNameDbfPath );
hb_xfree( szFileName );
hb_xfree( szBaseName );
return FAILURE;
}
/* Corrupted? */
/*mising test !*/
/* load the tags*/
/* pIndex->pCompound = hb_cdxTagNew( pIndex, szFileName, 0 ); */
pIndex->pCompound = hb_cdxTagNew( pIndex, szBaseName, 0 );
pIndex->pCompound->OptFlags = 0xE0;
pIndex->fShared = pAreaCdx->fShared;
pIndex->fReadonly = pAreaCdx->fReadonly;
hb_cdxIndexResetAvailPage( pIndex );
hb_cdxIndexLockRead( pIndex, NULL );
if( (hb_fsSeek( pIndex->hFile, 0x08, FS_SET ) != 0x08) ||
(hb_fsRead( pIndex->hFile, ( BYTE * ) &ulVersion, 4) != 4) )
hb_errInternal( 2155, "hb_cdxOrderListAdd: Read error on index heading page.", "", "" );
ulVersion = hb_cdxSwapBytes( ulVersion );
pIndex->ulVersion = ulVersion;
hb_cdxTagTagOpen( pIndex->pCompound, 0 );
TagList = NULL;
while( !pIndex->pCompound->TagEOF )
{
pTag = hb_cdxTagNew( pIndex,
pIndex->pCompound->CurKeyInfo->Value,
pIndex->pCompound->CurKeyInfo->Tag );
if( TagList == NULL )
TagList = pTag;
else
{
pLastTag = TagList;
while( pLastTag->pNext )
pLastTag = pLastTag->pNext;
pLastTag->pNext = pTag;
}
hb_cdxTagKeyRead( pIndex->pCompound, NEXT_RECORD );
}
hb_cdxIndexUnLockRead( pIndex, pIndex->pCompound );
/* Reorder the Tag list to be compatible with Clipper */
pTag1 = TagList;
while( pTag1->pNext )
{
if( pTag1->TagBlock < pTag1->pNext->TagBlock )
pTag1 = pTag1->pNext;
else
{
if( TagList->TagBlock > pTag1->pNext->TagBlock )
{
pTagTmp = TagList;
TagList = pTag1->pNext;
pTag1->pNext = pTag1->pNext->pNext;
TagList->pNext = pTagTmp;
}
else
{
pTag2 = TagList;
while( pTag2->pNext && (pTag2->pNext->TagBlock < pTag1->pNext->TagBlock) )
pTag2 = pTag2->pNext;
pTagTmp = pTag2->pNext;
pTag2->pNext = pTag1->pNext;
pTag1->pNext = pTag1->pNext->pNext;
pTag2->pNext->pNext = pTagTmp;
}
}
}
if( pIndex->TagList == NULL )
pIndex->TagList = TagList;
else
{
pLastTag = pIndex->TagList;
while( pLastTag->pNext )
pLastTag = pLastTag->pNext;
pLastTag->pNext = TagList;
}
/*missing: ordSetFocus(1) if there was no other open index in the area*/
//pIndex->uiTag = 1;
//SELF_GOTOP( ( AREAP ) pArea );
if( szFileNameDbfPath != NULL )
hb_xfree( szFileNameDbfPath );
hb_xfree( szFileName );
hb_xfree( szBaseName );
return SUCCESS;
}
// ( DBENTRYP_V ) hb_cdxOrderListClear
/*
* Clear the current order list.
*/
extern ERRCODE hb_cdxOrderListClear( CDXAREAP pArea )
{
LPCDXINDEX pIndex;
HB_TRACE(HB_TR_DEBUG, ("cdxOrderListClear(%p)", pArea));
/* Commit changes first */
if( SELF_GOCOLD( ( AREAP ) pArea ) == FAILURE )
return FAILURE;
while( pArea->lpIndexes )
{
pIndex = pArea->lpIndexes;
pArea->lpIndexes = pArea->lpIndexes->pNext;
hb_cdxIndexFree( pIndex );
}
pArea->lpIndexes = NULL;
return SUCCESS;
}
// ( DBENTRYP_VP ) hb_cdxOrderListDelete : NULL
// ( DBENTRYP_OI ) hb_cdxOrderListFocus
ERRCODE hb_cdxOrderListFocus( CDXAREAP pArea, LPDBORDERINFO pOrderInfo )
{
LPCDXTAG pTag;
HB_TRACE(HB_TR_DEBUG, ("cdxOrderListFocus(%p, %p)", pArea, pOrderInfo));
/*
HB_SYMBOL_UNUSED( pArea );
HB_SYMBOL_UNUSED( pOrderInfo );
*/
if( SELF_GOCOLD( ( AREAP ) pArea ) == FAILURE )
return FAILURE;
pTag = hb_cdxGetActiveTag( pArea );
if( ! pArea->lpIndexes )
return SUCCESS;
if( pTag )
pOrderInfo->itmResult = hb_itemPutC( pOrderInfo->itmResult, pTag->szName );
if( pOrderInfo->itmOrder )
{
/* pArea->lpIndexes->uiTag = hb_cdxFindTag( pArea, pOrderInfo ); */
pArea->uiTag = hb_cdxFindTag( pArea, pOrderInfo );
/* if( pArea->lpIndexes->uiTag ) */
if( pArea->uiTag )
SELF_GOTO( ( AREAP ) pArea, pArea->ulRecNo );
}
return SUCCESS;
}
// ( DBENTRYP_V ) hb_cdxOrderListRebuild: NULL
/*
static ERRCODE hb_cdxOrderListRebuild( CDXAREAP pArea )
{
LPCDXTAG pTag;
LPCDXINDEX pCdx;
USHORT uiPrevTag;
if ( ! pArea->lpIndexes )
return SUCCESS;
uiPrevTag = pArea->uiTag;
pCdx = pArea->lpIndexes;
pArea->lpIndexes = NULL;
pTag = NULL;
while ( uiTag && pCdx ) {
hb_fsClose( pCdx->hFile );
pCdx->hFile = FS_ERROR;
pTag = pCdx->TagList;
if ( pTag )
uiTag--;
while ( uiTag && pTag ) {
pTag = pTag->pNext;
if ( pTag )
uiTag--;
}
pCdx = pCdx->pNext;
}
*/
// ( DBENTRYP_VOI ) hb_cdxOrderCondition : NULL
// ( DBENTRYP_VOC ) hb_cdxOrderCreate
ERRCODE hb_cdxOrderCreate( CDXAREAP pAreaCdx, 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;
LPCDXINDEX pIndex;
LPCDXTAG pTag, pLastTag;
DBFHEADER pHeader;
BYTE bType;
BOOL bNewFile;
AREAP pArea = (AREAP) pAreaCdx;
/* this is for testing when doing changes or testing a new platform/compiler
if( sizeof(CDXINTERNAL) != 500 )
printf("cdxOrdCreate: Error, size of CDXINTERNAL: %i\n", sizeof(CDXINTERNAL));
if( sizeof(CDXDATA) != 512 )
printf("cdxOrdCreate: Error, size of CDXDATA: %i\n", sizeof(CDXDATA));
*/
HB_TRACE(HB_TR_DEBUG, ("cdxOrderCreate(%p, %p)", pArea, pOrderInfo));
if( SELF_GOCOLD( ( AREAP ) 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( (AREAP) 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( ( AREAP ) pArea );
SELF_SKIP( ( AREAP ) pArea, 1 );
*/
hb_cdxGoEof( pAreaCdx );
pExpMacro = pForMacro = NULL;
if( hb_itemType( pExpr ) == HB_IT_BLOCK )
{
if( SELF_EVALBLOCK( ( AREAP ) 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_stackItemFromTop( - 1 ) );
}
uiType = hb_itemType( pResult );
uiLen = 0;
switch( uiType )
{
case HB_IT_INTEGER:
case HB_IT_LONG:
case HB_IT_DOUBLE:
bType = 'N';
uiLen = 8;
break;
case HB_IT_DATE:
bType = 'D';
uiLen = 8;
break;
case HB_IT_LOGICAL:
bType = 'L';
uiLen = 1;
break;
case HB_IT_STRING:
bType = 'C';
uiLen = pResult->item.asString.length > CDX_MAXKEY ? CDX_MAXKEY :
pResult->item.asString.length;
break;
default:
bType = '\0';
}
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( ( AREAP ) 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( pArea->lpdbOrdCondInfo->abFor )
{
if( SELF_COMPILE( (AREAP) 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 */
if( pExpr )
{
pForExp = hb_itemNew( NULL );
hb_itemCopy( pForExp, pExpr );
}
}
/* Test conditional expression */
if( pExpr )
{
if( hb_itemType( pExpr ) == HB_IT_BLOCK )
{
if( SELF_EVALBLOCK( ( AREAP ) pArea, pExpr ) == FAILURE )
{
hb_itemRelease( pKeyExp );
hb_itemRelease( pForExp );
if( pExpMacro != NULL )
hb_macroDelete( pExpMacro );
return FAILURE;
}
pResult = pArea->valResult;
pArea->valResult = NULL;
}
else
{
pForMacro = ( HB_MACRO_PTR ) hb_itemGetPtr( pExpr );
hb_macroRun( pForMacro );
pResult = pExpr;
hb_itemCopy( pResult, hb_stackItemFromTop( - 1 ) );
}
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( pAreaCdx->szDataFileName );
/*
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( ( AREAP ) 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( ( AREAP ) pArea, DBOI_BAGEXT, &pExtInfo );
strcat( szFileName, pExtInfo.itmResult->item.asString.value );
hb_itemRelease( pExtInfo.itmResult );
}
}
szTagName = ( char * ) hb_xgrab( CDX_MAXTAGNAMELEN + 1 );
hb_strncpyUpper( szTagName, pFileName->szName, CDX_MAXTAGNAMELEN );
hb_xfree( pFileName );
/* Close all index */
hb_cdxOrderListClear( (CDXAREAP) pArea );
pIndex = hb_cdxIndexNew( pArea );
pAreaCdx->lpIndexes = pIndex;
/* New file? */
if( !hb_fsFile( ( BYTE * ) szFileName ) )
{
pIndex->hFile = hb_spCreate( ( BYTE * ) szFileName, FC_NORMAL );
bNewFile = TRUE;
pIndex->fShared = pAreaCdx->fShared;
pIndex->fReadonly = FALSE;
}
else
{
pIndex->hFile = hb_spOpen( ( BYTE * ) szFileName, FO_READWRITE |
( pAreaCdx->fShared ?
FO_DENYNONE : FO_EXCLUSIVE ) );
bNewFile = FALSE;
pIndex->fShared = pAreaCdx->fShared;
pIndex->fReadonly = FALSE;
}
if( pIndex->hFile == FS_ERROR )
{
hb_cdxOrderListClear( (CDXAREAP) 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;
}
pIndex->szFileName = ( char * ) hb_xgrab( strlen( szFileName ) + 1 );
strcpy( pIndex->szFileName, szFileName);
/* Corrupted? */
if( !bNewFile )
{
bNewFile = ( hb_fsSeek( pIndex->hFile, 0, FS_END ) <= CDX_PAGELEN );
hb_fsSeek( pIndex->hFile, 0, FS_SET );
}
hb_cdxIndexLockWrite( pIndex, NULL );
if( bNewFile )
{
pIndex->NextAvail = 0;
pIndex->pCompound = hb_cdxTagNew( pIndex, szTagName, -1 );
pIndex->pCompound->OptFlags = 0xE0;
hb_cdxTagIndexTagNew( pIndex->pCompound, NULL, NULL, 'C', 10, NULL, NULL,
TRUE, FALSE );
hb_cdxTagTagOpen( pIndex->pCompound, 0 );
}
else
{
pIndex->pCompound = hb_cdxTagNew( pIndex, szTagName, 0 );
pIndex->pCompound->OptFlags = 0xE0;
hb_cdxIndexResetAvailPage( pIndex );
hb_cdxTagTagOpen( pIndex->pCompound, 0 );
while( !pIndex->pCompound->TagEOF )
{
pTag = hb_cdxTagNew( pIndex,
pIndex->pCompound->CurKeyInfo->Value,
pIndex->pCompound->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->pCompound, NEXT_RECORD );
}
if ( pIndex->TagList != NULL ) {
pIndex->TagList = hb_cdxReorderTagList(pIndex->TagList);
}
}
/* Update DBF header */
if( !pAreaCdx->fHasTags )
{
pFileName = hb_fsFNameSplit( pAreaCdx->szDataFileName );
hb_strncpyUpper( szFileName, pFileName->szName, CDX_MAXTAGNAMELEN );
hb_xfree( pFileName );
hb_fsSeek( pAreaCdx->hDataFile, 0, FS_SET );
if( strcmp( szFileName, szTagName ) == 0 && hb_fsRead( pAreaCdx->hDataFile,
( BYTE * ) &pHeader, sizeof( DBFHEADER ) ) == sizeof( DBFHEADER ) )
{
pHeader.bHasTags = 1;
hb_fsSeek( pAreaCdx->hDataFile, 0, FS_SET );
hb_fsWrite( pAreaCdx->hDataFile, ( BYTE * ) &pHeader, sizeof( DBFHEADER ) );
}
}
hb_xfree( szFileName );
if ( strlen(( const char * ) pOrderInfo->atomBagName) > 0 )
hb_strncpyUpper( szTagName, ( const char * ) pOrderInfo->atomBagName, CDX_MAXTAGNAMELEN );
uiCount = strlen( szTagName );
while( uiCount > 0 && szTagName[ uiCount - 1 ] == ' ' )
uiCount--;
szTagName[ uiCount ] = 0;
hb_cdxIndexAddTag( pIndex, szTagName, pOrderInfo->abExpr->item.asString.value,
pKeyExp, bType, uiLen, ( char * ) ( pArea->lpdbOrdCondInfo ? pArea->lpdbOrdCondInfo->abFor :
NULL ), pForExp, pArea->lpdbOrdCondInfo ?
!pArea->lpdbOrdCondInfo->fDescending : TRUE , pOrderInfo->fUnique );
hb_xfree( szTagName );
hb_cdxIndexUnLockWrite( pIndex, NULL );
/* Clear pArea->lpdbOrdCondInfo */
SELF_ORDSETCOND( ( AREAP ) pArea, NULL );
return SELF_GOTOP( ( AREAP ) pArea );
}
// ( DBENTRYP_OI ) hb_cdxOrderDestroy : NULL
// ( DBENTRYP_OII ) hb_cdxOrderInfo
/*
* Provides information about order management.
*/
ERRCODE hb_cdxOrderInfo( CDXAREAP pArea, USHORT uiIndex, LPDBORDERINFO pOrderInfo )
{
USHORT uiTag;
LPCDXTAG pTag;
USHORT uiAux;
HB_TRACE(HB_TR_DEBUG, ("hb_cdxOrderInfo(%p, %hu, %p)", pArea, uiIndex, pOrderInfo));
HB_SYMBOL_UNUSED( pArea );
switch( uiIndex )
{
case DBOI_CONDITION :
if( ! pOrderInfo->itmOrder )
{
pTag = hb_cdxGetActiveTag( pArea );
}
else
{
uiTag = hb_cdxFindTag( pArea, pOrderInfo );
pTag = hb_cdxGetTagByNumber(pArea, uiTag );
}
if( pTag )
pOrderInfo->itmResult = hb_itemPutC( pOrderInfo->itmResult, pTag->ForExpr );
break;
case DBOI_EXPRESSION :
if( ! pOrderInfo->itmOrder )
{
pTag = hb_cdxGetActiveTag( pArea );
}
else
{
uiTag = hb_cdxFindTag( pArea, pOrderInfo );
pTag = hb_cdxGetTagByNumber( pArea, uiTag );
}
if( pTag )
pOrderInfo->itmResult = hb_itemPutC( pOrderInfo->itmResult, pTag->KeyExpr );
break;
case DBOI_POSITION :
hb_itemPutNL( pOrderInfo->itmResult, hb_cdxDBOIKeyNo(pArea) );
break;
/* case DBOI_RECNO : */
case DBOI_NAME :
if( ! pOrderInfo->itmOrder )
{
pTag = hb_cdxGetActiveTag( pArea );
}
else
{
uiTag = hb_itemGetNI( pOrderInfo->itmOrder );
pTag = hb_cdxGetTagByNumber( pArea, uiTag );
}
if( pTag )
pOrderInfo->itmResult = hb_itemPutC( pOrderInfo->itmResult, pTag->szName );
break;
case DBOI_NUMBER:
if( pArea->lpIndexes )
/* hb_itemPutNI( pOrderInfo->itmResult, pArea->lpIndexes->uiTag ); */
hb_itemPutNI( pOrderInfo->itmResult, pArea->uiTag );
else
hb_itemPutNI( pOrderInfo->itmResult, 0 );
break;
case DBOI_BAGNAME :
if( ! pOrderInfo->itmOrder )
{
pTag = hb_cdxGetActiveTag( pArea );
}
else
{
uiTag = hb_cdxFindTag( pArea, pOrderInfo );
if( uiTag )
pTag = hb_cdxGetTagByNumber(pArea, uiTag );
}
if( pTag )
/* hb_itemPutC( pOrderInfo->itmResult, pTag->pIndex->pCompound->szName ); */
hb_itemPutC( pOrderInfo->itmResult, pTag->pIndex->szFileName );
break;
case DBOI_BAGEXT:
pOrderInfo->itmResult = hb_itemPutC( pOrderInfo->itmResult, CDX_INDEXEXT );
break;
case DBOI_ORDERCOUNT :
uiTag = 0;
if( pArea->lpIndexes )
{
pTag = pArea->lpIndexes->TagList;
while( pTag )
{
uiTag++;
/* pTag = pTag->pNext; */
if ( pTag->pNext )
pTag = pTag->pNext;
else
{
if ( pTag->pIndex->pNext )
pTag = pTag->pIndex->pNext->TagList;
else
pTag = NULL;
}
}
}
hb_itemPutNI( pOrderInfo->itmResult, uiTag );
break;
case DBOI_FILEHANDLE :
if( ! pOrderInfo->itmOrder )
{
pTag = hb_cdxGetActiveTag( pArea );
}
else
{
uiTag = hb_cdxFindTag( pArea, pOrderInfo );
if( uiTag )
pTag = hb_cdxGetTagByNumber(pArea, uiTag );
}
if( pTag )
hb_itemPutNL( pOrderInfo->itmResult, (long) pTag->pIndex->hFile );
break;
case DBOI_ISCOND :
if( ! pOrderInfo->itmOrder )
{
pTag = hb_cdxGetActiveTag( pArea );
}
else
{
uiTag = hb_cdxFindTag( pArea, pOrderInfo );
pTag = hb_cdxGetTagByNumber(pArea, uiTag );
}
if( pTag )
pOrderInfo->itmResult = hb_itemPutL( pOrderInfo->itmResult, (pTag->ForExpr != NULL) );
break;
case DBOI_ISDESC :
if( ! pOrderInfo->itmOrder )
{
pTag = hb_cdxGetActiveTag( pArea );
}
else
{
uiTag = hb_cdxFindTag( pArea, pOrderInfo );
pTag = hb_cdxGetTagByNumber(pArea, uiTag );
}
if( pTag )
pOrderInfo->itmResult = hb_itemPutL( pOrderInfo->itmResult, !pTag->AscendKey );
break;
case DBOI_UNIQUE:
if( ! pOrderInfo->itmOrder )
{
pTag = hb_cdxGetActiveTag( pArea );
}
else
{
uiTag = hb_cdxFindTag( pArea, pOrderInfo );
pTag = hb_cdxGetTagByNumber(pArea, uiTag );
}
if( pTag )
pOrderInfo->itmResult = hb_itemPutL( pOrderInfo->itmResult, pTag->UniqueKey );
break;
/*------------------- */
case DBOI_KEYCOUNT :
hb_itemPutNL( pOrderInfo->itmResult, hb_cdxDBOIKeyCount(pArea) );
break;
case DBOI_KEYVAL:
pTag = hb_cdxGetActiveTag( pArea );
if( pTag && !pArea->fEof && pTag->CurKeyInfo && ((ULONG) pTag->CurKeyInfo->Tag == pArea->ulRecNo) )
{
switch( pTag->uiType )
{
case 'N' :
uiAux = HB_IT_DOUBLE; break;
case 'D' :
uiAux = HB_IT_DATE; break;
case 'L' :
uiAux = HB_IT_LOGICAL; break;
case 'C' :
uiAux = HB_IT_STRING; break;
default:
uiAux = HB_IT_NIL;
}
if( uiAux != HB_IT_NIL )
hb_cdxKeyGetItem( pTag->CurKeyInfo, pOrderInfo->itmResult, uiAux );
}
break;
/*------------------- */
case DBOI_SCOPETOP :
pTag = hb_cdxGetActiveTag( pArea );
if( pTag )
hb_cdxScopeInfo( pArea, 0, pOrderInfo->itmResult );
else
hb_itemClear( pOrderInfo->itmResult );
break;
case DBOI_SCOPEBOTTOM :
pTag = hb_cdxGetActiveTag( pArea );
if( pTag )
hb_cdxScopeInfo( pArea, 1, pOrderInfo->itmResult );
else
hb_itemClear( pOrderInfo->itmResult );
break;
case DBOI_SCOPETOPCLEAR :
pTag = hb_cdxGetActiveTag( pArea );
if( pTag )
{
hb_cdxScopeInfo( pArea, 0, pOrderInfo->itmResult );
hb_cdxTagClearScope( pTag, 0);
}
else
hb_itemClear( pOrderInfo->itmResult );
break;
case DBOI_SCOPEBOTTOMCLEAR :
pTag = hb_cdxGetActiveTag( pArea );
if( pTag )
{
hb_cdxScopeInfo( pArea, 1, pOrderInfo->itmResult );
hb_cdxTagClearScope( pTag, 1);
}
else
hb_itemClear( pOrderInfo->itmResult );
break;
/*------------------- */
case DBOI_CUSTOM :
hb_itemPutL( pOrderInfo->itmResult, 0 );
break;
case DBOI_KEYADD :
hb_itemPutL( pOrderInfo->itmResult, 0 );
break;
case DBOI_KEYDELETE :
hb_itemPutL( pOrderInfo->itmResult, 0 );
break;
default:
return SUPER_ORDINFO( ( AREAP ) pArea, uiIndex, pOrderInfo );
}
return SUCCESS;
}
// ( DBENTRYP_V ) hb_cdxClearFilter : NULL
// ( DBENTRYP_V ) hb_cdxClearLocate : NULL
// ( DBENTRYP_V ) hb_cdxClearScope : NULL
static ERRCODE hb_cdxClearScope( CDXAREAP pArea )
{
LPCDXTAG pTag;
PHB_ITEM *pScope;
HB_TRACE(HB_TR_DEBUG, ("hb_cdxClearScope(%p)", pArea));
pTag = hb_cdxGetActiveTag( pArea );
if( pTag )
{
hb_cdxTagClearScope( pTag, 0);
hb_cdxTagClearScope( pTag, 1);
}
return SUCCESS;
}
// ( DBENTRYP_VPLP ) hb_cdxCountScope : NULL
// ( DBENTRYP_I ) hb_cdxFilterText : NULL
// ( DBENTRYP_SI ) hb_cdxScopeInfo : NULL
static ERRCODE hb_cdxScopeInfo( CDXAREAP pArea, USHORT nScope, PHB_ITEM pItem )
{
LPCDXTAG pTag;
PHB_ITEM *pScope;
HB_TRACE(HB_TR_DEBUG, ("hb_cdxScopeInfo(%p, %hu, %p)", pArea, nScope, pItem));
pTag = hb_cdxGetActiveTag( pArea );
hb_itemClear( pItem );
if( pTag )
{
pScope = (nScope == 0) ? &(pTag->topScope) : &(pTag->bottomScope);
if ( *pScope ) {
hb_itemCopy( pItem, *pScope );
}
}
return SUCCESS;
}
// ( DBENTRYP_VFI ) hb_cdxSetFilter : NULL
// ( DBENTRYP_VLO ) hb_cdxSetLocate : NULL
// ( DBENTRYP_VOS ) hb_cdxSetScope : NULL
static ERRCODE hb_cdxSetScope( CDXAREAP pArea, LPDBORDSCOPEINFO sInfo )
{
LPCDXTAG pTag;
BOOL ok;
PHB_ITEM *pScope;
LPKEYINFO *pScopeKey;
HB_TRACE(HB_TR_DEBUG, ("hb_cdxSetScope(%p, %p)", pArea, sInfo));
pTag = hb_cdxGetActiveTag( pArea );
if( pTag )
{
pScope = (sInfo->nScope == 0) ? &(pTag->topScope) : &(pTag->bottomScope);
pScopeKey = (sInfo->nScope == 0) ? &(pTag->topScopeKey) : &(pTag->bottomScopeKey);
if( !sInfo->scopeValue )
{
if ( *pScope ) {
hb_itemRelease( *pScope );
*pScope = NULL;
}
if ( *pScopeKey ) {
hb_cdxKeyFree( *pScopeKey );
*pScopeKey = NULL;
}
}
else
{
switch( pTag->uiType )
{
case 'N' :
ok = ( sInfo->scopeValue->type & HB_IT_NUMERIC ); break;
case 'D' :
ok = ( sInfo->scopeValue->type == HB_IT_DATE ); break;
case 'L' :
ok = ( sInfo->scopeValue->type == HB_IT_LOGICAL ); break;
case 'C' :
ok = ( sInfo->scopeValue->type == HB_IT_STRING ); break;
default:
ok = FALSE;
}
if ( ok ) {
if( *pScope == NULL )
*pScope = hb_itemNew( NULL );
hb_itemCopy( *pScope, sInfo->scopeValue );
*pScopeKey = hb_cdxKeyPutItem( *pScopeKey, *pScope );
(*pScopeKey)->Tag = (sInfo->nScope == 0) ? (CDX_IGNORE_REC_NUM) : (CDX_MAX_REC_NUM);
}
else
printf("hb_cdxSetScope: scope value of wrong type"); /* DBFCDX/1051 Scope Type Mismatch */
}
}
else
printf("hb_cdxSetScope: workarea not indexed");
return SUCCESS;
}
// ( DBENTRYP_VPL ) hb_cdxSkipScope : NULL
// ( DBENTRYP_P ) hb_cdxCompile : NULL
// ( DBENTRYP_I ) hb_cdxError : NULL
// ( DBENTRYP_I ) hb_cdxEvalBlock : NULL
// ( DBENTRYP_VSP ) hb_cdxRawLock : NULL
// ( DBENTRYP_VL ) hb_cdxLock : NULL
// ( DBENTRYP_UL ) hb_cdxUnLock : NULL
// ( DBENTRYP_V ) hb_cdxCloseMemFile : NULL
// ( DBENTRYP_VP ) hb_cdxCreateMemFile
/*
* Create a memo file in the WorkArea.
*/
ERRCODE hb_cdxCreateMemFile( CDXAREAP pArea, LPDBOPENINFO pCreateInfo )
{
MEMOHEADER fptHeader;
BYTE pBlock[ 512 ];
BOOL bRetry;
PHB_ITEM pError;
HB_TRACE(HB_TR_DEBUG, ("hb_cdxCreateMemFile(%p, %p)", pArea, pCreateInfo));
if( pCreateInfo )
{
pError = NULL;
/* Try create */
do
{
pArea->hMemoFile = hb_spCreate( pCreateInfo->abName, FC_NORMAL );
if( pArea->hMemoFile == FS_ERROR )
{
if( !pError )
{
pError = hb_errNew();
hb_errPutGenCode( pError, EG_CREATE );
hb_errPutSubCode( pError, EDBF_CREATE_DBF );
hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_CREATE ) );
hb_errPutFileName( pError, ( char * ) pCreateInfo->abName );
hb_errPutFlags( pError, EF_CANRETRY );
}
bRetry = ( SELF_ERROR( ( AREAP ) pArea, pError ) == E_RETRY );
}
else
bRetry = FALSE;
} while( bRetry );
if( pError )
hb_errRelease( pError );
if( pArea->hMemoFile == FS_ERROR )
return FAILURE;
}
else /* For zap file */
hb_fsSeek( pArea->hMemoFile, 0, FS_SET );
pArea->uiMemoBlockSize = s_uiMemoBlockSize;
fptHeader.ulNextBlock = hb_cdxSwapBytes( s_uiMemoBlockSize > 512 ? 1 :
512 / s_uiMemoBlockSize );
fptHeader.ulBlockSize = hb_cdxSwapBytes( s_uiMemoBlockSize );
if( hb_fsWrite( pArea->hMemoFile, ( BYTE * ) &fptHeader, sizeof( MEMOHEADER ) ) !=
sizeof( MEMOHEADER ) )
return FAILURE;
memset( pBlock, 0, 512 );
if( hb_fsWrite( pArea->hMemoFile, pBlock, 512 - sizeof( MEMOHEADER ) ) !=
512 - sizeof( MEMOHEADER ) )
return FAILURE;
hb_fsWrite( pArea->hMemoFile, NULL, 0 );
return SUCCESS;
}
// ( DBENTRYP_SVPB ) hb_cdxGetValueFile : NULL
// ( DBENTRYP_VP ) hb_cdxOpenMemFile
/*
* Open a memo file in the specified WorkArea.
*/
ERRCODE hb_cdxOpenMemFile( CDXAREAP pArea, LPDBOPENINFO pOpenInfo )
{
USHORT uiFlags;
BOOL bRetry;
MEMOHEADER fptHeader;
PHB_ITEM pError;
BYTE buffer[0x20];
HB_TRACE(HB_TR_DEBUG, ("hb_cdxOpenMemFile(%p, %p)", pArea, pOpenInfo));
uiFlags = (USHORT) (pOpenInfo->fReadonly ? FO_READ : FO_READWRITE);
uiFlags |= (USHORT) (pOpenInfo->fShared ? FO_DENYNONE : FO_EXCLUSIVE);
pError = NULL;
/* Try open */
do
{
pArea->hMemoFile = hb_spOpen( pOpenInfo->abName, uiFlags );
if( pArea->hMemoFile == FS_ERROR )
{
if( !pError )
{
pError = hb_errNew();
hb_errPutGenCode( pError, EG_OPEN );
hb_errPutSubCode( pError, EDBF_OPEN_DBF );
hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_OPEN ) );
hb_errPutFileName( pError, ( char * ) pOpenInfo->abName );
hb_errPutFlags( pError, EF_CANRETRY | EF_CANDEFAULT );
}
bRetry = ( SELF_ERROR( ( AREAP ) pArea, pError ) == E_RETRY );
}
else
bRetry = FALSE;
} while( bRetry );
if( pError )
hb_errRelease( pError );
if( pArea->hMemoFile == FS_ERROR )
return FAILURE;
hb_fsSeek( pArea->hMemoFile, 0, FS_SET );
if( hb_fsRead( pArea->hMemoFile, ( BYTE * ) &fptHeader, sizeof( MEMOHEADER ) ) !=
sizeof( MEMOHEADER ) )
return FAILURE;
pArea->uiMemoBlockSize = ( USHORT ) hb_cdxSwapBytes( fptHeader.ulBlockSize );
if ( pArea->uiMemoBlockSize == 0)
{
/* Check for compatibility with Clipper 5.3/FlexFile3 malformed memo headers*/
hb_fsSeek( pArea->hMemoFile, 0x200, FS_SET );
if( hb_fsRead( pArea->hMemoFile, buffer, sizeof( buffer ) ) != sizeof( buffer ) )
return FAILURE;
if ( memcmp( (char *) buffer, "FlexFile3\x03", 10) == 0 )
{
pArea->uiMemoBlockSize = ( USHORT ) buffer[0x1C];
}
}
if ( pArea->uiMemoBlockSize == 0)
{
if( !pError )
{
pError = hb_errNew();
hb_errPutGenCode( pError, EG_CORRUPTION );
hb_errPutSubCode( pError, EDBF_CORRUPT );
hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_CORRUPTION ) );
hb_errPutFileName( pError, (char *) pOpenInfo->abName );
}
/* bRetry = ( SELF_ERROR( ( AREAP ) pArea, pError ) == E_RETRY ); */
SELF_ERROR( ( AREAP ) pArea, pError );
if( pError )
hb_errRelease( pError );
return FAILURE;
}
return SUCCESS;
}
// ( DBENTRYP_SVP ) hb_cdxPutValueFile : NULL
// ( DBENTRYP_V ) hb_cdxReadDBHeader
/*
* Read the database file header record in the WorkArea.
*/
ERRCODE hb_cdxReadDBHeader( CDXAREAP pArea )
{
DBFHEADER dbHeader;
BOOL bRetry, bError;
PHB_ITEM pError;
HB_TRACE(HB_TR_DEBUG, ("hb_cdxReadHeader(%p)", pArea));
pError = NULL;
/* Try read */
do
{
hb_fsSeek( pArea->hDataFile, 0, FS_SET );
if( hb_fsRead( pArea->hDataFile, ( BYTE * ) &dbHeader, sizeof( DBFHEADER ) ) !=
sizeof( DBFHEADER ) || ( dbHeader.bVersion != 0x03 && dbHeader.bVersion != 0xF5 ) )
{
bError = TRUE;
if( !pError )
{
pError = hb_errNew();
hb_errPutGenCode( pError, EG_CORRUPTION );
hb_errPutSubCode( pError, EDBF_CORRUPT );
hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_CORRUPTION ) );
hb_errPutFileName( pError, pArea->szDataFileName );
hb_errPutFlags( pError, EF_CANRETRY | EF_CANDEFAULT );
}
bRetry = ( SELF_ERROR( ( AREAP ) pArea, pError ) == E_RETRY );
}
else
bRetry = bError = FALSE;
} while( bRetry );
if( pError )
hb_errRelease( pError );
/* Read error? */
if( bError )
return FAILURE;
pArea->bDay = dbHeader.bDay;
pArea->bMonth = dbHeader.bMonth;
pArea->bYear = dbHeader.bYear;
pArea->uiHeaderLen = dbHeader.uiHeaderLen;
pArea->ulRecCount = dbHeader.ulRecCount;
pArea->fHasMemo = ( dbHeader.bVersion == 0xF5 );
pArea->fHasTags = dbHeader.bHasTags;
return SUCCESS;
}
// ( DBENTRYP_V ) hb_cdxWriteDBHeader
/*
* Write the database file header record in the WorkArea.
*/
ERRCODE hb_cdxWriteDBHeader( CDXAREAP pArea )
{
DBFHEADER dbfHeader;
ULONG ulRecCount;
long lYear, lMonth, lDay;
HB_TRACE(HB_TR_DEBUG, ("hb_cdxWriteDBHeader(%p)", pArea));
memset( &dbfHeader, 0, sizeof( DBFHEADER ) );
dbfHeader.bVersion = (BYTE) (pArea->fHasMemo ? 0xF5 : 0x03);
hb_dateToday( &lYear, &lMonth, &lDay );
dbfHeader.bYear = ( BYTE ) ( lYear - 1900 );
dbfHeader.bMonth = ( BYTE ) lMonth;
dbfHeader.bDay = ( BYTE ) lDay;
dbfHeader.bHasTags = ( BYTE ) pArea->fHasTags;
/* Update record count */
SELF_RECCOUNT( ( AREAP ) pArea, &ulRecCount );
dbfHeader.ulRecCount = ulRecCount;
dbfHeader.uiHeaderLen = pArea->uiHeaderLen;
dbfHeader.uiRecordLen = pArea->uiRecordLen;
hb_fsSeek( pArea->hDataFile, 0, FS_SET );
hb_fsWrite( pArea->hDataFile, ( BYTE * ) &dbfHeader, sizeof( DBFHEADER ) );
pArea->fUpdateHeader = FALSE;
return SUCCESS;
}
// ( DBENTRYP_SVP ) hb_cdxWhoCares : NULL
/* end of cdxrdd.c */