* 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
6087 lines
177 KiB
C
6087 lines
177 KiB
C
/*
|
||
* $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 */
|
||
|