diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 076453a549..21ca6d317f 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -1,3 +1,26 @@ +2000-09-02 00:08 GMT+1 Bruno Cantero + + include/hbdbf.h + + include/hbrddcdx.h + * makefile.bc + * makefile.vc + * source/rdd/dbfcdx/Makefile + * source/rdd/dbfcdx/dbfcdx1.c + * source/rdd/rddsys.prg + + Added DBFCDX files to makefiles and reactivate it. + By now is the default driver (rddsys.prg). + + * include/hbrdddbf.h + * source/rdd/dbcmd.c + * source/rdd/workarea.c + * source/rdd/hbdbsort.c + * Fixed some warnings. + + * tests/newrdd.prg + + Added CVS header Id. + + * tests/testcdx.prg + * Test FPT memos. + 2000-09-01 13:55 GMT+2 Maurilio Longo * source/rtl/tbrowse.prg ! fixed hilighting and dehilighting of cells if field is logical; that is logical cells value diff --git a/harbour/include/hbdbf.h b/harbour/include/hbdbf.h new file mode 100644 index 0000000000..8f6d0a428e --- /dev/null +++ b/harbour/include/hbdbf.h @@ -0,0 +1,84 @@ +/* + * $Id$ + */ + +/* + * Harbour Project source code: + * DBF structures + * + * Copyright 1999 Bruno Cantero + * www - http://www.harbour-project.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version, with one exception: + * + * The exception is that if you link the Harbour Runtime Library (HRL) + * and/or the Harbour Virtual Machine (HVM) with other files to produce + * an executable, this does not by itself cause the resulting executable + * to be covered by the GNU General Public License. Your use of that + * executable is in no way restricted on account of linking the HRL + * and/or HVM code into it. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA (or visit + * their web site at http://www.gnu.org/). + * + */ + +#ifndef HB_DBF_H_ +#define HB_DBF_H_ + +#include "hbapirdd.h" + +#if defined(HB_EXTERN_C) +extern "C" { +#endif + +/* DBF header */ + +typedef struct _DBFHEADER +{ + BYTE bVersion; + BYTE bYear; + BYTE bMonth; + BYTE bDay; + ULONG ulRecCount; + USHORT uiHeaderLen; + USHORT uiRecordLen; + BYTE bReserved1[ 16 ]; + BYTE bHasTags; + BYTE bReserved2[ 3 ]; +} DBFHEADER; + +typedef DBFHEADER * LPDBFHEADER; + + + +/* DBF fields */ + +typedef struct _DBFFIELD +{ + BYTE bName[ 11 ]; + BYTE bType; + BYTE bReserved1[ 4 ]; + BYTE bLen; + BYTE bDec; + BYTE bReserved2[ 13 ]; + BYTE bHasTag; +} DBFFIELD; + +typedef DBFFIELD * LPDBFFIELD; + +#if defined(HB_EXTERN_C) +} +#endif + +#endif /* HB_DBF_H_ */ \ No newline at end of file diff --git a/harbour/include/hbrddcdx.h b/harbour/include/hbrddcdx.h new file mode 100644 index 0000000000..8dacafb37c --- /dev/null +++ b/harbour/include/hbrddcdx.h @@ -0,0 +1,319 @@ +/* + * $Id$ + */ + +/* + * Harbour Project source code: + * DBFCDX RDD + * + * Copyright 1999 Bruno Cantero + * www - http://www.harbour-project.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version, with one exception: + * + * The exception is that if you link the Harbour Runtime Library (HRL) + * and/or the Harbour Virtual Machine (HVM) with other files to produce + * an executable, this does not by itself cause the resulting executable + * to be covered by the GNU General Public License. Your use of that + * executable is in no way restricted on account of linking the HRL + * and/or HVM code into it. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA (or visit + * their web site at http://www.gnu.org/). + * + */ + +#ifndef HB_RDDCDX_H_ +#define HB_RDDCDX_H_ + +#include "hbapirdd.h" + +#if defined(HB_EXTERN_C) +extern "C" { +#endif + + +/* DBFCDX errors */ + +#define EDBF_OPEN_DBF 1001 +#define EDBF_CREATE_DBF 1004 +#define EDBF_READ 1010 +#define EDBF_WRITE 1011 +#define EDBF_CORRUPT 1012 +#define EDBF_DATATYPE 1020 +#define EDBF_DATAWIDTH 1021 +#define EDBF_UNLOCKED 1022 +#define EDBF_SHARED 1023 +#define EDBF_APPENDLOCK 1024 +#define EDBF_READONLY 1025 + + + +/* DBFCDX default memo extension */ +#define CDX_MEMOEXT ".fpt" + + + +/* FPT's */ + +#define FPT_DEFBLOCKSIZE 64 +#define SIZEOFMEMOFREEBLOCK 6 +#define MAXFREEBLOCKS 82 + +typedef struct _MEMOHEADER +{ + ULONG ulNextBlock; /* Next memo entry */ + ULONG ulBlockSize; /* Size of block */ +} MEMOHEADER; + +typedef MEMOHEADER * LPMEMOHEADER; + + + +typedef struct _MEMOBLOCK +{ + ULONG ulType; /* 0 = binary, 1 = text */ + ULONG ulSize; /* length of data */ +} MEMOBLOCK; + +typedef MEMOBLOCK * LPMEMOBLOCK; + + + +typedef struct _MEMOFREEBLOCK +{ + USHORT uiBlocks; /* Number of blocks */ + ULONG ulBlock; /* Block number */ +} MEMOFREEBLOCK; + +typedef MEMOFREEBLOCK * LPMEMOFREEBLOCK; + + + +typedef struct _MEMOROOT +{ + ULONG ulNextBlock; /* Next block in the list */ + ULONG ulBlockSize; /* Size of block */ + BYTE szSignature[ 8 ]; /* Signature */ + BYTE fChanged; /* TRUE if root block is changed */ + USHORT uiListLen; /* Length of list */ + BYTE pFreeList[ 492 ]; /* Array of free memo blocks (82 MEMOFREEBLOCK's) */ +} MEMOROOT; + +typedef MEMOROOT * LPMEMOROOT; + + + +/* CDX's */ + +typedef struct _TAG +{ + BYTE * pKeyBuffer; /* Buffer of keys */ +} TAG; + +typedef TAG * LPTAG; + + + +/* + * DBF WORKAREA + * ------------ + * The Workarea Structure of DBFCDX RDD + * + */ + +typedef struct _CDXAREA +{ + struct _RDDFUNCS * lprfsHost; /* Virtual method table for this workarea */ + USHORT uiArea; /* The number assigned to this workarea */ + void * atomAlias; /* Pointer to the alias symbol for this workarea */ + USHORT uiFieldExtent; /* Total number of fields allocated */ + USHORT uiFieldCount; /* Total number of fields used */ + LPFIELD lpFields; /* Pointer to an array of fields */ + void * lpFieldExtents; /* Void ptr for additional field properties */ + PHB_ITEM valResult; /* All purpose result holder */ + BOOL fTop; /* TRUE if "top" */ + BOOL fBottom; /* TRUE if "bottom" */ + BOOL fBof; /* TRUE if "bof" */ + BOOL fEof; /* TRUE if "eof" */ + BOOL fFound; /* TRUE if "found" */ + DBSCOPEINFO dbsi; /* Info regarding last LOCATE */ + DBFILTERINFO dbfi; /* Filter in effect */ + LPDBORDERCONDINFO lpdbOrdCondInfo; + LPDBRELINFO lpdbRelations; /* Parent/Child relationships used */ + USHORT uiParents; /* Number of parents for this area */ + USHORT heap; + USHORT heapSize; + USHORT rddID; + + /* + * DBFS's additions to the workarea structure + * + * Warning: The above section MUST match WORKAREA exactly! Any + * additions to the structure MUST be added below, as in this + * example. + */ + + FHANDLE hDataFile; /* Data file handle */ + FHANDLE hMemoFile; /* Memo file handle */ + USHORT uiHeaderLen; /* Size of header */ + USHORT uiRecordLen; /* Size of record */ + ULONG ulRecCount; /* Total records */ + char * szDataFileName; /* Name of data file */ + char * szMemoFileName; /* Name of memo file */ + BOOL fHasMemo; /* WorkArea with Memo fields */ + BOOL fHasTags; /* WorkArea with MDX or CDX index */ + BOOL fShared; /* Shared file */ + BOOL fReadOnly; /* Read only file */ + USHORT * pFieldOffset; /* Pointer to field offset array */ + BYTE * pRecord; /* Buffer of record data */ + BOOL fValidBuffer; /* State of buffer */ + BOOL fPositioned; /* Positioned record */ + ULONG ulRecNo; /* Current record */ + BOOL fRecordChanged; /* Record changed */ + BOOL fAppend; /* TRUE if new record is added */ + BOOL fDeleted; /* TRUE if record is deleted */ + BOOL fUpdateHeader; /* Update header of file */ + BOOL fFLocked; /* TRUE if file is locked */ + LPDBRELINFO lpdbPendingRel; /* Pointer to parent rel struct */ + BYTE bYear; /* Last update */ + BYTE bMonth; + BYTE bDay; + ULONG * pLocksPos; /* List of records locked */ + ULONG ulNumLocksPos; /* Number of records locked */ + + /* + * CDX's additions to the workarea structure + * + * Warning: The above section MUST match WORKAREA exactly! Any + * additions to the structure MUST be added below, as in this + * example. + */ + + USHORT uiMemoBlockSize; /* Size of memo block */ + LPMEMOROOT pMemoRoot; /* Array of free memo blocks */ + LPTAG * lpIndexes; /* Pointer to indexes array */ + +} CDXAREA; + +typedef CDXAREA * LPCDXAREA; + +#ifndef CDXAREAP +#define CDXAREAP LPCDXAREA +#endif + + +/* + * -- DBFCDX METHODS -- + */ + +#define SUPERTABLE ( &cdxSuper ) + +#define hb_cdxBof NULL +#define hb_cdxEof NULL +#define hb_cdxFound NULL +#define hb_cdxGoBottom NULL +#define hb_cdxGoTo NULL +#define hb_cdxGoToId NULL +#define hb_cdxGoTop NULL +#define hb_cdxSeek NULL +#define hb_cdxSkip NULL +#define hb_cdxSkipFilter NULL +#define hb_cdxSkipRaw NULL +#define hb_cdxAddField NULL +#define hb_cdxAppend NULL +#define hb_cdxCreateFields NULL +#define hb_cdxDeleteRec NULL +#define hb_cdxDeleted NULL +#define hb_cdxFieldCount NULL +#define hb_cdxFieldDisplay NULL +#define hb_cdxFieldInfo NULL +#define hb_cdxFieldName NULL +#define hb_cdxFlush NULL +#define hb_cdxGetRec NULL +extern ERRCODE hb_cdxGetValue( CDXAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ); +extern ERRCODE hb_cdxGetVarLen( CDXAREAP pArea, USHORT uiIndex, ULONG * pLength ); +#define hb_cdxGoCold NULL +#define hb_cdxGoHot NULL +#define hb_cdxPutRec NULL +extern ERRCODE hb_cdxPutValue( CDXAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ); +#define hb_cdxRecAll NULL +#define hb_cdxRecCount NULL +#define hb_cdxRecInfo NULL +#define hb_cdxRecNo NULL +#define hb_cdxSetFieldExtent NULL +#define hb_cdxAlias NULL +extern ERRCODE hb_cdxClose( CDXAREAP pArea ); +#define hb_cdxCreate NULL +extern ERRCODE hb_cdxInfo( CDXAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ); +#define hb_cdxNewArea NULL +extern ERRCODE hb_cdxOpen( CDXAREAP pArea, LPDBOPENINFO pOpenInfo ); +#define hb_cdxRelease NULL +extern ERRCODE hb_cdxStructSize( CDXAREAP pArea, USHORT * uiSize ); +extern ERRCODE hb_cdxSysName( CDXAREAP pArea, BYTE * pBuffer ); +#define hb_cdxEval NULL +#define hb_cdxPack NULL +#define hb_cdxPackRec NULL +#define hb_cdxSort NULL +#define hb_cdxTrans NULL +#define hb_cdxTransRec NULL +#define hb_cdxZap NULL +#define hb_cdxChildEnd NULL +#define hb_cdxChildStart NULL +#define hb_cdxChildSync NULL +#define hb_cdxSyncChildren NULL +#define hb_cdxClearRel NULL +#define hb_cdxForceRel NULL +#define hb_cdxRelArea NULL +#define hb_cdxRelEval NULL +#define hb_cdxRelText NULL +#define hb_cdxSetRel NULL +#define hb_cdxOrderListAdd NULL +#define hb_cdxOrderListClear NULL +#define hb_cdxOrderListDelete NULL +#define hb_cdxOrderListFocus NULL +#define hb_cdxOrderListRebuild NULL +#define hb_cdxOrderCondition NULL +#define hb_cdxOrderCreate NULL +#define hb_cdxOrderDestroy NULL +#define hb_cdxOrderInfo NULL +#define hb_cdxClearFilter NULL +#define hb_cdxClearLocate NULL +#define hb_cdxClearScope NULL +#define hb_cdxCountScope NULL +#define hb_cdxFilterText NULL +#define hb_cdxScopeInfo NULL +#define hb_cdxSetFilter NULL +#define hb_cdxSetLocate NULL +#define hb_cdxSetScope NULL +#define hb_cdxSkipScope NULL +#define hb_cdxCompile NULL +#define hb_cdxError NULL +#define hb_cdxEvalBlock NULL +#define hb_cdxRawLock NULL +#define hb_cdxLock NULL +#define hb_cdxUnLock NULL +#define hb_cdxCloseMemFile NULL +extern ERRCODE hb_cdxCreateMemFile( CDXAREAP pArea, LPDBOPENINFO pCreateInfo ); +#define hb_cdxGetValueFile NULL +extern ERRCODE hb_cdxOpenMemFile( CDXAREAP pArea, LPDBOPENINFO pOpenInfo ); +#define hb_cdxPutValueFile NULL +extern ERRCODE hb_cdxReadDBHeader( CDXAREAP pArea ); +extern ERRCODE hb_cdxWriteDBHeader( CDXAREAP pArea ); +#define hb_cdxWhoCares NULL + +#if defined(HB_EXTERN_C) +} +#endif + +#endif /* HB_RDDCDX_H_ */ \ No newline at end of file diff --git a/harbour/include/hbrdddbf.h b/harbour/include/hbrdddbf.h index 0c93ee920f..0c5e0f5333 100644 --- a/harbour/include/hbrdddbf.h +++ b/harbour/include/hbrdddbf.h @@ -42,41 +42,6 @@ extern "C" { #endif -/* DBF header */ - -typedef struct _DBFHEADER -{ - BYTE bVersion; - BYTE bYear; - BYTE bMonth; - BYTE bDay; - ULONG ulRecCount; - USHORT uiHeaderLen; - USHORT uiRecordLen; - BYTE bReserved1[ 16 ]; - BYTE bHasTags; - BYTE bReserved2[ 3 ]; -} DBFHEADER; - -typedef DBFHEADER * LPDBFHEADER; - - - -typedef struct _DBFFIELD -{ - BYTE bName[ 11 ]; - BYTE bType; - BYTE bReserved1[ 4 ]; - BYTE bLen; - BYTE bDec; - BYTE bReserved2[ 13 ]; - BYTE bHasTag; -} DBFFIELD; - -typedef DBFFIELD * LPDBFFIELD; - - - /* DBF errors */ #define EDBF_OPEN_DBF 1001 @@ -105,11 +70,13 @@ typedef DBFFIELD * LPDBFFIELD; #define DBF_LOCKPOS 1000000000L + /* DBT's */ #define DBT_BLOCKSIZE 512 + /* * DBF WORKAREA * ------------ diff --git a/harbour/makefile.bc b/harbour/makefile.bc index 2f84f306ba..7d48a9aeb8 100644 --- a/harbour/makefile.bc +++ b/harbour/makefile.bc @@ -397,12 +397,9 @@ NULSYS_LIB_OBJS = \ DBFNTX_LIB_OBJS = \ $(OBJ_DIR)\dbfntx0.obj -#DBFCDX_LIB_OBJS = \ -# $(OBJ_DIR)\dbfcdx1.obj \ -# \ -# $(OBJ_DIR)\dbfcdx0.obj - DBFCDX_LIB_OBJS = \ + $(OBJ_DIR)\dbfcdx1.obj \ + \ $(OBJ_DIR)\dbfcdx0.obj # @@ -1916,9 +1913,9 @@ $(OBJ_DIR)\dbfcdx0.obj : $(OBJ_DIR)\dbfcdx0.c $(CC) $(CLIBFLAGS) -o$@ $** tlib $(DBFCDX_LIB) $(ARFLAGS) -+$@,, -#$(OBJ_DIR)\dbfcdx1.obj : $(RDD_DIR)\dbfcdx\dbfcdx1.c -# $(CC) $(CLIBFLAGS) -o$@ $** -# tlib $(DBFCDX_LIB) $(ARFLAGS) -+$@,, +$(OBJ_DIR)\dbfcdx1.obj : $(RDD_DIR)\dbfcdx\dbfcdx1.c + $(CC) $(CLIBFLAGS) -o$@ $** + tlib $(DBFCDX_LIB) $(ARFLAGS) -+$@,, # # DEBUG.LIB dependencies diff --git a/harbour/makefile.vc b/harbour/makefile.vc index 0b38673ff8..349b44f97f 100644 --- a/harbour/makefile.vc +++ b/harbour/makefile.vc @@ -465,11 +465,9 @@ DBFNTX_LIB_OBJS = \ $(HARBOUR_EXE) $(HARBOURFLAGS) -o$(OBJ_DIR)\ $< $(MAKE) -nologo /$(MK_FLAGS) /f$(MK_FILE) $(DBFCDX_LIB)2 -#DBFCDX_LIB_OBJS = \ -# $(OBJ_DIR)\dbfcdx1.obj \ -# \ -# $(OBJ_DIR)\dbfcdx0.obj DBFCDX_LIB_OBJS = \ + $(OBJ_DIR)\dbfcdx1.obj \ + \ $(OBJ_DIR)\dbfcdx0.obj # diff --git a/harbour/source/rdd/dbcmd.c b/harbour/source/rdd/dbcmd.c index 49e0ba9025..635b289657 100644 --- a/harbour/source/rdd/dbcmd.c +++ b/harbour/source/rdd/dbcmd.c @@ -661,6 +661,16 @@ ERRCODE hb_rddSelectWorkAreaAlias( char * szName ) return bResult; } +/* + * Function for getting current workarea pointer + */ +void * hb_rddGetCurrentWorkAreaPointer( void ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_rddGetCurrentWorkAreaPointer()")); + + return s_pCurrArea->pArea; +} + /* * Obtain the current value of a field. */ @@ -1102,6 +1112,8 @@ HB_FUNC( DBCREATE ) pStruct = hb_param( 2 , HB_IT_ARRAY ); if( pStruct ) uiLen = ( USHORT ) hb_arrayLen( pStruct ); + else + uiLen = 0; if( ( strlen( szFileName ) == 0 ) || !pStruct || uiLen == 0 ) { @@ -1129,10 +1141,10 @@ HB_FUNC( DBCREATE ) } } + uiPrevArea = s_uiCurrArea; if( !ISLOG( 4 ) ) { bOpen = FALSE; - uiPrevArea = s_uiCurrArea; hb_rddSelectFirstAvailable(); } else @@ -2834,14 +2846,16 @@ HB_FUNC( __DBARRANGE ) dbSortInfo.lpdbsItem = ( LPDBSORTITEM ) hb_xgrab( dbSortInfo.uiItemCount * sizeof( DBSORTITEM ) ); ulSize = 0; for( uiCount = 1; uiCount <= dbSortInfo.uiItemCount; uiCount++ ) + { if( hb_arrayGetCLen( pFields, uiCount ) > ulSize ) ulSize = hb_arrayGetCLen( pFields, uiCount ); + } szFieldLine = ( char * ) hb_xgrab( ulSize + 1 ); for( uiCount = 0; uiCount < dbSortInfo.uiItemCount; uiCount++ ) { dbSortInfo.lpdbsItem[ uiCount ].uiFlags = 0; - ulSize = hb_arrayGetCLen( pFields, uiCount + 1 ); - hb_strncpyUpper( szFieldLine, hb_arrayGetCPtr( pFields, uiCount + 1 ), ulSize ); + hb_strncpyUpper( szFieldLine, hb_arrayGetCPtr( pFields, uiCount + 1 ), + hb_arrayGetCLen( pFields, uiCount + 1 ) ); szPos = strchr( szFieldLine, '/' ); if( szPos ) { @@ -2858,7 +2872,6 @@ HB_FUNC( __DBARRANGE ) ( * ( szPos + 2 ) != 0 && * ( szPos + 3 ) == 'C' ) ) ) dbSortInfo.lpdbsItem[ uiCount ].uiFlags |= SF_CASE; * szPos = 0; - ulSize = szFieldLine - szPos; } else dbSortInfo.lpdbsItem[ uiCount ].uiFlags |= SF_ASCEND; diff --git a/harbour/source/rdd/dbf1.c b/harbour/source/rdd/dbf1.c index 80f1f07398..fcc4552eaf 100644 --- a/harbour/source/rdd/dbf1.c +++ b/harbour/source/rdd/dbf1.c @@ -38,6 +38,7 @@ #include "hbvm.h" #include "hbapiitm.h" #include "hbrdddbf.h" +#include "hbdbf.h" #include "hbapierr.h" #include "hbapilng.h" #include "hbset.h" @@ -570,6 +571,7 @@ static BOOL hb_dbfPutMemo( DBFAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) ULONG ulLen, ulBlock; HB_TRACE(HB_TR_DEBUG, ("hb_dbfPutMemo(%p, %hu, %p)", pArea, uiIndex, pItem)); + ulLen = hb_itemGetCLen( pItem ); if( ulLen > 0 ) { @@ -969,7 +971,7 @@ ERRCODE hb_dbfGetValue( DBFAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) return FAILURE; bError = FALSE; - uiIndex --; + uiIndex--; pField = pArea->lpFields + uiIndex; switch( pField->uiType ) { @@ -1037,7 +1039,6 @@ ERRCODE hb_dbfGetValue( DBFAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) ERRCODE hb_dbfGetVarLen( DBFAREAP pArea, USHORT uiIndex, ULONG * pLength ) { HB_TRACE(HB_TR_DEBUG, ("hb_dbfGetVarLen(%p, %hu, %p)", pArea, uiIndex, pLength)); - HB_SYMBOL_UNUSED( uiIndex ); if( pArea->lpdbPendingRel ) SELF_FORCEREL( ( AREAP ) pArea ); @@ -1047,7 +1048,7 @@ ERRCODE hb_dbfGetVarLen( DBFAREAP pArea, USHORT uiIndex, ULONG * pLength ) return FAILURE; if( pArea->fHasMemo ) - * pLength = hb_dbfGetMemoLen( pArea, uiIndex ); + * pLength = hb_dbfGetMemoLen( pArea, uiIndex - 1 ); else * pLength = 0; @@ -1160,7 +1161,7 @@ ERRCODE hb_dbfPutValue( DBFAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) return FAILURE; uiError = SUCCESS; - uiIndex --; + uiIndex--; pField = pArea->lpFields + uiIndex; if( pField->uiType == HB_IT_MEMO ) { @@ -1513,7 +1514,7 @@ ERRCODE hb_dbfCreate( DBFAREAP pArea, LPDBOPENINFO pCreateInfo ) pArea->fHasMemo = bHasMemo; /* Write header */ - if( hb_dbfWriteDBHeader( pArea ) == FAILURE ) + if( SELF_WRITEDBHEADER( ( AREAP ) pArea ) == FAILURE ) { hb_fsClose( pArea->hDataFile ); pArea->hDataFile = FS_ERROR; @@ -1546,12 +1547,12 @@ ERRCODE hb_dbfCreate( DBFAREAP pArea, LPDBOPENINFO pCreateInfo ) strcat( pArea->szMemoFileName, pFileName->szName ); hb_xfree( pFileName ); pFileExt = hb_itemPutC( NULL, "" ); - hb_dbfInfo( pArea, DBI_MEMOEXT, pFileExt ); + SELF_INFO( ( AREAP ) pArea, DBI_MEMOEXT, pFileExt ); strncat( pArea->szMemoFileName, hb_itemGetCPtr( pFileExt ), _POSIX_PATH_MAX - strlen( pArea->szMemoFileName ) ); hb_itemRelease( pFileExt ); pCreateInfo->abName = ( BYTE * ) pArea->szMemoFileName; - return hb_dbfCreateMemFile( pArea, pCreateInfo ); + return SELF_CREATEMEMFILE( ( AREAP ) pArea, pCreateInfo ); } else return SUCCESS; @@ -1682,7 +1683,7 @@ ERRCODE hb_dbfOpen( DBFAREAP pArea, LPDBOPENINFO pOpenInfo ) return FAILURE; /* Read file header and exit if error */ - if( hb_dbfReadDBHeader( pArea ) == FAILURE ) + if( SELF_READDBHEADER( ( AREAP ) pArea ) == FAILURE ) { SELF_CLOSE( ( AREAP ) pArea ); return FAILURE; @@ -1710,7 +1711,7 @@ ERRCODE hb_dbfOpen( DBFAREAP pArea, LPDBOPENINFO pOpenInfo ) pArea->szMemoFileName = szFileName; /* Open memo file and exit if error */ - if( hb_dbfOpenMemFile( pArea, pOpenInfo ) == FAILURE ) + if( SELF_OPENMEMFILE( ( AREAP ) pArea, pOpenInfo ) == FAILURE ) { SELF_CLOSE( ( AREAP ) pArea ); return FAILURE; @@ -1894,7 +1895,10 @@ ERRCODE hb_dbfPack( DBFAREAP pArea ) ulUserEvery = 1; } else + { pBlock = NULL; + ulUserEvery = 1; + } /* Force write new header */ pArea->fUpdateHeader = TRUE; @@ -1964,10 +1968,10 @@ ERRCODE hb_dbfSort( DBFAREAP pArea, LPDBSORTINFO pSortInfo ) uiError = SUCCESS; uiCount = 0; pBuffer = dbQuickSort.pBuffer; + ulRecNo = 1; if( pSortInfo->dbtri.dbsci.itmRecID ) { uiError = hb_dbfGoTo( pArea, hb_itemGetNL( pSortInfo->dbtri.dbsci.itmRecID ) ); - ulRecNo = 1; bMoreRecords = bLimited = TRUE; } else if( pSortInfo->dbtri.dbsci.lNext ) @@ -2102,7 +2106,6 @@ ERRCODE hb_dbfTransRec( DBFAREAP pArea, LPDBTRANSINFO pTransInfo ) */ ERRCODE hb_dbfZap( DBFAREAP pArea ) { - BYTE pBlock[ DBT_BLOCKSIZE ]; PHB_ITEM pError; HB_TRACE(HB_TR_DEBUG, ("hb_dbfZap(%p)", pArea)); @@ -2125,14 +2128,10 @@ ERRCODE hb_dbfZap( DBFAREAP pArea ) pArea->fUpdateHeader = TRUE; pArea->ulRecCount = 0; - /* Create memo file */ + /* Zap memo file */ if( pArea->fHasMemo ) { - memset( pBlock, 0, DBT_BLOCKSIZE ); - * ( ( LONG * ) pBlock ) = 1; - hb_fsSeek( pArea->hMemoFile, 0, FS_SET ); - if( hb_fsWrite( pArea->hMemoFile, pBlock, DBT_BLOCKSIZE ) != DBT_BLOCKSIZE ) - return FAILURE; + SELF_CREATEMEMFILE( ( AREAP ) pArea, NULL ); hb_fsWrite( pArea->hMemoFile, NULL, 0 ); } return SUCCESS; @@ -2295,34 +2294,39 @@ ERRCODE hb_dbfCreateMemFile( DBFAREAP pArea, LPDBOPENINFO pCreateInfo ) HB_TRACE(HB_TR_DEBUG, ("hb_dbfCreateMemFile(%p, %p)", pArea, pCreateInfo)); - memset( pBlock, 0, DBT_BLOCKSIZE ); - pError = NULL; - /* Try create */ - do + if( pCreateInfo ) { - pArea->hMemoFile = hb_fsCreate( pCreateInfo->abName, FC_NORMAL ); - if( pArea->hMemoFile == FS_ERROR ) + pError = NULL; + /* Try create */ + do { - if( !pError ) + pArea->hMemoFile = hb_fsCreate( pCreateInfo->abName, FC_NORMAL ); + if( pArea->hMemoFile == FS_ERROR ) { - 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 ); + 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 ); } - bRetry = ( SELF_ERROR( ( AREAP ) pArea, pError ) == E_RETRY ); - } - else - bRetry = FALSE; - } while( bRetry ); - if( pError ) - hb_errRelease( pError ); + else + bRetry = FALSE; + } while( bRetry ); + if( pError ) + hb_errRelease( pError ); - if( pArea->hMemoFile == FS_ERROR ) - return FAILURE; + if( pArea->hMemoFile == FS_ERROR ) + return FAILURE; + } + else /* For zap file */ + hb_fsSeek( pArea->hMemoFile, 0, FS_SET ); + memset( pBlock, 0, DBT_BLOCKSIZE ); * ( ( LONG * ) pBlock ) = 1; if( hb_fsWrite( pArea->hMemoFile, pBlock, DBT_BLOCKSIZE ) != DBT_BLOCKSIZE ) return FAILURE; diff --git a/harbour/source/rdd/dbfcdx/Makefile b/harbour/source/rdd/dbfcdx/Makefile index dcdb01b739..b089207922 100644 --- a/harbour/source/rdd/dbfcdx/Makefile +++ b/harbour/source/rdd/dbfcdx/Makefile @@ -4,8 +4,8 @@ ROOT = ../../../ -#C_SOURCES=\ -# dbfcdx1.c \ +C_SOURCES=\ + dbfcdx1.c \ PRG_SOURCES=\ dbfcdx0.prg \ diff --git a/harbour/source/rdd/dbfcdx/dbfcdx1.c b/harbour/source/rdd/dbfcdx/dbfcdx1.c index 1a4faf61e2..f29bf55bc7 100644 --- a/harbour/source/rdd/dbfcdx/dbfcdx1.c +++ b/harbour/source/rdd/dbfcdx/dbfcdx1.c @@ -33,222 +33,17 @@ * */ -#define SUPERTABLE ( &cdxSuper ) - -#include -#include - #include "hbapi.h" +#include "hbinit.h" +#include "hbvm.h" #include "hbapiitm.h" -#include "hbapirdd.h" +#include "hbrddcdx.h" +#include "hbdbf.h" #include "hbapierr.h" #include "hbapilng.h" +#include "hbset.h" #include "hbdate.h" -#include "hbvm.h" -#include "hbinit.h" -#include "rddsys.ch" - -#define LOCK_START 0x40000000L -#define LOCK_APPEND 0x7FFFFFFEL -#define LOCK_FILE 0x3FFFFFFFL -#define MEMO_BLOCK 64 -#define CDX_MAX_KEY 240 -#define CDX_MAX_TAG_NAME_LEN 10 -#define CDX_BLOCK_SIZE 512 -#define CDX_INTERNAL_SPACE 500 -#define CDX_EXTERNAL_SPACE 488 -#define CDX_MAX_REC_NUM 0x7FFFFFFFL -#define CDX_IGNORE_REC_NUM -1 -#define PAGE_ROOT 1 -#define PAGE_NODE 2 -#define PAGE_LEAF 3 -#define TOP_RECORD 1 -#define BTTM_RECORD 2 -#define PREV_RECORD 3 -#define NEXT_RECORD 4 -#define SORT_CHUNK_LIMIT 16384 -#define SORT_ACTIVE_LIST 0 -#define SORT_END_OF_KEY 1 -#define SORT_END_OF_WORD 2 -#define SORT_STACK_OF_CHAR 3 - -typedef struct _DBFHEADER -{ - BYTE bVersion; - BYTE bYear; - BYTE bMonth; - BYTE bDay; - ULONG ulRecords; - USHORT uiHeaderLen; - USHORT uiRecordLen; - BYTE bReserved1[ 16 ]; - BYTE bHasMDX; - BYTE bReserved2[ 3 ]; -} DBFHEADER; - -typedef DBFHEADER * LPDBFHEADER; - - -typedef struct _DBFFIELD -{ - BYTE bName[ 11 ]; - BYTE bType; - BYTE bReserved1[ 4 ]; - BYTE bLen; - BYTE bDec; - BYTE bReserved2[ 13 ]; - BYTE bHasTag; -} DBFFIELD; - -typedef DBFFIELD * LPDBFFIELD; - - -typedef struct -{ - ULONG lNextBlock; - ULONG lBlockSize; -} MEMOHEADER; - -typedef MEMOHEADER * LPMEMOHEADER; - - -typedef struct _DBFMEMO -{ - BOOL fChanged; /* Memo status */ - BYTE * pData; /* Memo data */ - USHORT uiLen; /* Len of data */ -} DBFMEMO; - -typedef DBFMEMO * LPDBFMEMO; - - -typedef struct _CDXHEADER -{ - LONG Root; - LONG FreePtr; - LONG ChgFlag; - USHORT Key_Lgth; - BYTE IndexOpts; - BYTE IndexSig; - BYTE Reserve3[ 486 ]; - USHORT AscDesc; - USHORT Reserve4; - USHORT ForExpLen; - USHORT Reserve5; - USHORT KeyExpLen; - BYTE KeyPool[ CDX_BLOCK_SIZE ]; -} CDXHEADER; - -typedef CDXHEADER * LPCDXHEADER; - - -typedef struct -{ - USHORT FreeSpace; - LONG RecNumMask; - BYTE DupCntMask; - BYTE TrlCntMask; - BYTE RecNumBits; - BYTE DupCntBits; - BYTE TrlCntBits; - BYTE ShortBytes; - BYTE ExtData[ CDX_EXTERNAL_SPACE ]; -} CDXEXTERNAL; - - -typedef struct -{ - BYTE IntData[ CDX_INTERNAL_SPACE ]; -} CDXINTERNAL; - - -typedef struct _CDXDATA -{ - USHORT Node_Atr; - USHORT Entry_Ct; - LONG Left_Ptr; - LONG Rght_Ptr; - union - { - CDXEXTERNAL External; - CDXINTERNAL Internal; - } cdxu; -} CDXDATA; - -typedef CDXDATA * LPCDXDATA; - - -typedef struct -{ - char Character; - BYTE NUse; - USHORT WordArray; - USHORT Fill02; - USHORT LevelLink; -} SORT_A; - - -typedef struct -{ - BYTE Fill03[ 4 ]; - char ChrStack[ 4 ]; -} SORT_B; - - -typedef struct -{ - LONG Fill04; - LONG ChrFill; -} SORT_C; - - -typedef struct -{ - union - { - SORT_A A; - SORT_B B; - SORT_C C; - } sortu; -} SORTDATA; - -typedef SORTDATA * LPSORTDATA; - - -typedef struct -{ - LONG WordCount; - LONG RootLink; - LONG LevelPtr; - LONG PriorPtr; - LONG KeyTot; - LONG KeyCnt; - LONG LastTag; - LONG * ChunkList; - BYTE * SortBuffer; - USHORT SortChunk; - USHORT NodeLimit; - USHORT NodeMask; - USHORT NodeShift; - USHORT ChunkSize; - USHORT ChunkLimit; - USHORT ChunkCur; - USHORT NodeCur; - USHORT KeySize; - USHORT WCur; - BOOL Unique; - BOOL Ascend; - BOOL Closing; - char WPch[ 256 ]; - SORTDATA * WAdr; - LPTAGINFO CurTag; - LPCDXDATA NodeList[ 32 ]; - LPKEYINFO KeyWork; - LPKEYINFO LastKey; -} SORTINFO; - -typedef SORTINFO * LPSORTINFO; - +#include "error.ch" extern HB_FUNC( _DBFCDX ); extern HB_FUNC( DBFCDX_GETFUNCTABLE ); @@ -270,3058 +65,910 @@ HB_INIT_SYMBOLS_END( dbfcdx1__InitSymbols ) #pragma startup dbfcdx1__InitSymbols #endif -static RDDFUNCS cdxSuper = { 0 }; +static USHORT s_uiMemoBlockSize = 64; /* Default block memo size */ -static ERRCODE cdxOrderListClear( AREAP pArea ); +static RDDFUNCS cdxSuper = { NULL }; -static LPKEYINFO hb_cdxKeyNew( void ); -static void hb_cdxKeyFree( LPKEYINFO pKey ); -static int hb_cdxKeyCompare( LPKEYINFO pKey1, LPKEYINFO pKey2, USHORT * EndPos, BOOL Exact ); +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_VP ) 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 LPTAGINFO hb_cdxTagNew( LPINDEXINFO PIF, char * ITN, LONG TagHdr ); -static void hb_cdxTagFree( LPTAGINFO pTag ); -static void hb_cdxTagIndexTagNew( LPTAGINFO pTag, char * KeyExp, PHB_ITEM pKeyItem, - BYTE bType, USHORT uiLen, char * ForExp, - PHB_ITEM pForItem, BOOL Ascnd, BOOL Uniq ); -static void hb_cdxTagDoIndex( LPTAGINFO pTag ); -static void hb_cdxTagEmptyIndex( LPTAGINFO pTag ); -static void hb_cdxTagTagStore( LPTAGINFO pTag ); -static void hb_cdxTagTagOpen( LPTAGINFO pTag, BYTE bCode ); -static void hb_cdxTagTagClose( LPTAGINFO pTag ); -static LONG hb_cdxTagNewRoot( LPTAGINFO pTag ); -static void hb_cdxTagPageLoad( LPTAGINFO pTag, LPPAGEINFO pPage ); -static void hb_cdxTagKeyRead( LPTAGINFO pTag, BYTE bTypRead ); -static void hb_cdxTagKeyAdd( LPTAGINFO pTag, LPKEYINFO pKey ); -static void hb_cdxTagPageStore( LPTAGINFO pTag, LPPAGEINFO PIK ); -static void hb_cdxTagExtNodeWrite( LPTAGINFO pTag, LONG PN, LPCDXDATA pData, LPPAGEINFO PIK ); -static USHORT hb_cdxTagFillExternalNode( LPTAGINFO pTag, LPCDXDATA pData, LPPAGEINFO PIK, - USHORT kcnt, USHORT ck, LPKEYINFO * p ); -static void hb_cdxTagExtNodeBuild( LPTAGINFO pTag, LPCDXDATA pData, LPPAGEINFO pPage ); -static void hb_cdxTagTagLoad( LPTAGINFO pTag ); -static void hb_cdxTagSetRoot( LPTAGINFO pTag, LPPAGEINFO PIK ); -static void hb_cdxTagIntNodeWrite( LPTAGINFO pTag, LONG PN, LPCDXDATA pData, LPPAGEINFO PIK ); -static USHORT hb_cdxTagFillInternalNode( LPTAGINFO pTag, LPCDXDATA pData, LPPAGEINFO PIK, - USHORT kcnt, USHORT ck, LPKEYINFO * p ); -static void hb_cdxTagIntNodeBuild( LPTAGINFO pTag, LPCDXDATA pData, LPPAGEINFO pPage ); -static LONG hb_cdxTagKeyFind( LPTAGINFO pTag, LPKEYINFO pKey ); +/* + * Common functions. + */ -static LPPAGEINFO hb_cdxPageNew( LPTAGINFO PIT, LPPAGEINFO PIK, LONG FilePosn ); -static void hb_cdxPageFree( LPPAGEINFO pPage ); -static BOOL hb_cdxPageReadTopKey( LPPAGEINFO pPage ); -static BOOL hb_cdxPageReadBottomKey( LPPAGEINFO pPage ); -static int hb_cdxPageSeekKey( LPPAGEINFO pPage, LONG lBlock, LPKEYINFO pKey, BOOL bExact ); -static void hb_cdxPageInsertKey( LPPAGEINFO pPage, LPKEYINFO pKey, BOOL bAddAfter ); -static void hb_cdxPagePageStore( LPPAGEINFO pPage ); -static BOOL hb_cdxPageReadNextKey( LPPAGEINFO pPage ); -static LPKEYINFO hb_cdxPageGetKey( LPPAGEINFO pPage, USHORT uiKey ); -static void hb_cdxPagePageLoad( LPPAGEINFO pPage ); -static int hb_cdxPageRetrieveKey( LPPAGEINFO pPage, LPKEYINFO pKey ); -static void hb_cdxPageAddNodeKey( LPPAGEINFO pPage, LPKEYINFO pKey ); -static int hb_cdxPageSeekNodeTag( LPPAGEINFO pPage, LONG Tag ); -static BOOL hb_cdxPageGetChild( LPPAGEINFO pPage, LONG Tag ); -static void hb_cdxPageDeleteKey( LPPAGEINFO pPage ); - -static LPINDEXINFO hb_cdxIndexNew( AREAP pArea ); -static void hb_cdxIndexFree( LPINDEXINFO pIndex ); -static LONG hb_cdxIndexGetAvailPage( LPINDEXINFO pIndex ); -static void hb_cdxIndexResetAvailPage( LPINDEXINFO pIndex ); -static void hb_cdxIndexPageRead( LPINDEXINFO pIndex, LONG lPos, void * pBuffer, USHORT uiSize ); -static void hb_cdxIndexPageWrite( LPINDEXINFO pIndex, LONG lPos, void * pBuffer, USHORT uiSize ); -static void hb_cdxIndexAddTag( LPINDEXINFO pIndex, char * szTagName, char * szKeyExp, - PHB_ITEM pKeyItem, BYTE bType, USHORT uiLen, char * szForExp, - PHB_ITEM pForItem, BOOL bAscending, BOOL bUnique ); - -static LPSORTINFO hb_cdxSortNew( LPTAGINFO pTag, BOOL bUnique ); -static void hb_cdxSortFree( LPSORTINFO pSort ); -static void hb_cdxSortLinkNew( LPSORTINFO pSort, LONG * NewLink ); -static void hb_cdxSortGetNewChunk( LPSORTINFO pSort ); -static void hb_cdxSortInsertWord( LPSORTINFO pSort, LONG Tag, char * Value ); -static void hb_cdxSortStuffKey( LPSORTINFO pSort, LPSORTDATA * wx ); -static void hb_cdxSortGetNode( LPSORTINFO pSort, char Character, LONG * NewLink ); -static LPSORTDATA hb_cdxSortLinkGet( LPSORTINFO pSort, LONG Value ); -static void hb_cdxSortDisplayWord( LPSORTINFO pSort ); -static void hb_cdxSortRecurseDict( LPSORTINFO pSort, LONG WPtr, LONG WBgn ); -static void hb_cdxSortSendWord( LPSORTINFO pSort, char * Value ); -static void hb_cdxSortOutputWord( LPSORTINFO pSort, LONG Tag, char * Value ); -static void hb_cdxSortAddToNode( LPSORTINFO pSort, USHORT Lvl, LONG Tag, LONG Link, - LPKEYINFO Value ); -static void hb_cdxSortAddExternal( LPSORTINFO pSort, USHORT Lvl, LONG Tag, LONG Link, - LPKEYINFO Value ); -static void hb_cdxSortAddInternal( LPSORTINFO pSort, USHORT Lvl, LONG Tag, LONG Link, - LPKEYINFO Value ); - -static BOOL hb_cdxltoa( LONG lValue, char * szBuffer, USHORT uiLen ) +/* + * Swap bytes. + */ +ULONG hb_cdxSwapBytes( ULONG ulLong ) { - LONG lAbsNumber; - int iCount, iPos; + BYTE * pLong, bByte; - HB_TRACE(HB_TR_DEBUG, ("hb_cdxltoa(%ld, %p, %hu)", lValue, szBuffer, uiLen)); + HB_TRACE(HB_TR_DEBUG, ("hb_cdxSwapBytes(%lu)", ulLong)); - lAbsNumber = ( lValue > 0 ) ? lValue : - lValue; - iCount = iPos = uiLen; - while( iCount-- > 0 ) - { - szBuffer[ iCount ] = ( '0' + lAbsNumber % 10 ); - lAbsNumber /= 10; - } - - if( lAbsNumber > 0 ) - { - memset( szBuffer, ' ', uiLen ); - return FALSE; - } - - uiLen--; - for( iCount = 0; iCount < uiLen; iCount++ ) - if( szBuffer[ iCount ] == '0' ) - szBuffer[ iCount ] = ' '; - else - break; - - if( lValue < 0 ) - { - if( szBuffer[ 0 ] != ' ' ) - { - memset( szBuffer, ' ', iPos ); - return FALSE; - } - for( iCount = uiLen; iCount >= 0; iCount-- ) - { - if( szBuffer[ iCount ] == ' ' ) - { - szBuffer[ iCount ] = '-'; - break; - } - } - } - return TRUE; + 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; } -static ULONG hb_cdxSwapBytes( ULONG ulValue ) -{ - BYTE * pValue, * pNewValue; - ULONG ulNewValue; - - HB_TRACE(HB_TR_DEBUG, ("hb_cdxSwapBytes(%lu)", ulValue)); - - pValue = ( BYTE * ) &ulValue; - pNewValue = ( BYTE * ) &ulNewValue; - pNewValue[ 0 ] = pValue[ 3 ]; - pNewValue[ 1 ] = pValue[ 2 ]; - pNewValue[ 2 ] = pValue[ 1 ]; - pNewValue[ 3 ] = pValue[ 0 ]; - return ulNewValue; -} - -static LONG hb_cdxMakeMask( BYTE bByte ) -{ - BYTE bCount; - LONG lMask; - - for( lMask = 0, bCount = 1; bCount <= bByte; bCount++, - lMask = ( lMask << 1 ) + 1 ); - return lMask; -} - -static void hb_cdxReadMemo( AREAP pArea, LPDBFMEMO pMemo, ULONG lMemoBlock ) -{ - ULONG ulSpaceUsed; - MEMOHEADER pMemoHeader; - - HB_TRACE(HB_TR_DEBUG, ("hb_cdxReadMemo(%p, %p, %lu)", pArea, pMemo, lMemoBlock)); - - hb_fsSeek( pArea->lpDataInfo->pNext->hFile, lMemoBlock * MEMO_BLOCK, FS_SET ); - hb_fsRead( pArea->lpDataInfo->pNext->hFile, ( BYTE * ) &pMemoHeader, - sizeof( MEMOHEADER ) ); - ulSpaceUsed = hb_cdxSwapBytes( pMemoHeader.lBlockSize ); - if( pMemo->uiLen != ulSpaceUsed ) - { - if( pMemo->uiLen > 0 ) - pMemo->pData = ( BYTE * ) hb_xrealloc( pMemo->pData, ulSpaceUsed + 1 ); - else - pMemo->pData = ( BYTE * ) hb_xgrab( ulSpaceUsed + 1 ); - pMemo->uiLen = ulSpaceUsed; - } - hb_fsRead( pArea->lpDataInfo->pNext->hFile, pMemo->pData, pMemo->uiLen ); -} - -static BOOL hb_cdxWriteMemo( AREAP pArea, LPDBFMEMO pMemo, ULONG * lNewRecNo ) -{ - USHORT uiNumBlocks; - MEMOHEADER pMemoHeader; - BYTE * pBuffer; - - HB_TRACE(HB_TR_DEBUG, ("hb_cdxWriteMemo(%p, %p, %p)", pArea, pMemo, lNewRecNo)); - - if( !pArea->lpExtendInfo->fExclusive && !pArea->lpDataInfo->fFileLocked && - !hb_fsLock( pArea->lpDataInfo->pNext->hFile, LOCK_APPEND - 1, 1, FL_LOCK ) ) - return FALSE; - - uiNumBlocks = 1 + ( pMemo->uiLen + sizeof( MEMOHEADER ) ) / MEMO_BLOCK; - if( * lNewRecNo > 0 ) - { - hb_fsSeek( pArea->lpDataInfo->pNext->hFile, * lNewRecNo * MEMO_BLOCK, FS_SET ); - hb_fsRead( pArea->lpDataInfo->pNext->hFile, ( BYTE * ) &pMemoHeader, - sizeof( MEMOHEADER ) ); - if( pMemo->uiLen > hb_cdxSwapBytes( pMemoHeader.lBlockSize ) ) - * lNewRecNo = 0; /* Not room for data */ - } - - if( * lNewRecNo == 0 ) /* Add an entry at eof */ - { - hb_fsSeek( pArea->lpDataInfo->pNext->hFile, 0, FS_SET ); - hb_fsRead( pArea->lpDataInfo->pNext->hFile, ( BYTE * ) &pMemoHeader, - sizeof( MEMOHEADER ) ); - * lNewRecNo = hb_cdxSwapBytes( pMemoHeader.lNextBlock ); - pMemoHeader.lNextBlock = hb_cdxSwapBytes( * lNewRecNo + uiNumBlocks ); - hb_fsSeek( pArea->lpDataInfo->pNext->hFile, 0, FS_SET ); - hb_fsWrite( pArea->lpDataInfo->pNext->hFile, ( BYTE * ) &pMemoHeader, - sizeof( MEMOHEADER ) ); - } - - hb_fsSeek( pArea->lpDataInfo->pNext->hFile, * lNewRecNo * MEMO_BLOCK, FS_SET ); - pMemoHeader.lNextBlock = hb_cdxSwapBytes( 1 ); - pMemoHeader.lBlockSize = hb_cdxSwapBytes( pMemo->uiLen ); - hb_fsWrite( pArea->lpDataInfo->pNext->hFile, ( BYTE * ) &pMemoHeader, - sizeof( MEMOHEADER ) ); - if( hb_fsWrite( pArea->lpDataInfo->pNext->hFile, pMemo->pData, - pMemo->uiLen ) != pMemo->uiLen ) - { - if( !pArea->lpExtendInfo->fExclusive && !pArea->lpDataInfo->fFileLocked ) - hb_fsLock( pArea->lpDataInfo->pNext->hFile, LOCK_APPEND - 1, 1, FL_UNLOCK ); - return FALSE; - } - uiNumBlocks = ( pMemo->uiLen + sizeof( MEMOHEADER ) ) % MEMO_BLOCK; - if( uiNumBlocks > 0 ) - { - pBuffer = ( BYTE * ) hb_xgrab( MEMO_BLOCK ); - memset( pBuffer, 0, MEMO_BLOCK ); - hb_fsWrite( pArea->lpDataInfo->pNext->hFile, pBuffer, MEMO_BLOCK - uiNumBlocks ); - hb_xfree( pBuffer); - } - - if( !pArea->lpExtendInfo->fExclusive && !pArea->lpDataInfo->fFileLocked ) - hb_fsLock( pArea->lpDataInfo->pNext->hFile, LOCK_APPEND - 1, 1, FL_UNLOCK ); - return TRUE; -} - -static LPKEYINFO hb_cdxKeyNew() -{ - LPKEYINFO pKey; - - pKey = ( LPKEYINFO ) hb_xgrab( sizeof( KEYINFO ) ); - pKey->pItem = hb_itemNew( NULL ); - pKey->Tag = pKey->Xtra = 0; - pKey->pNext = NULL; - return pKey; -} - -static void hb_cdxKeyFree( LPKEYINFO pKey ) -{ - hb_itemRelease( pKey->pItem ); - hb_xfree( pKey ); -} - -static int hb_cdxKeyCompare( LPKEYINFO pKey1, LPKEYINFO pKey2, USHORT * EndPos, BOOL Exact ) -{ - int iLimit, iResult; - - * EndPos = 0; - if( pKey2 == NULL || pKey2->pItem->item.asString.length == 0 ) - return 1; - if( pKey1 == NULL || pKey1->pItem->item.asString.length == 0 ) - return ( pKey2->pItem->item.asString.length == 0 ) ? 0: -1; - - switch( hb_itemType( pKey1->pItem ) ) - { - case HB_IT_STRING: - iLimit = ( pKey1->pItem->item.asString.length > - pKey2->pItem->item.asString.length ) ? - pKey2->pItem->item.asString.length : - pKey1->pItem->item.asString.length; - do - { - iResult = pKey1->pItem->item.asString.value[ * EndPos ] - - pKey2->pItem->item.asString.value[ * EndPos ]; - * EndPos += 1; - } while( iResult == 0 && * EndPos < iLimit ); - - if( iResult == 0 ) - { - * EndPos += 1; - iResult = pKey1->pItem->item.asString.length - - pKey2->pItem->item.asString.length; - } - if( iResult < 0 && * EndPos > pKey1->pItem->item.asString.length && !Exact ) - iResult = 0; - break; - - default: - iResult = 0; - printf( "hb_cdxKeyCompare()" ); - } - - if( iResult < 0 ) - return -1; - else if( iResult > 0 ) - return 1; - else - return 0; -} - -static LPTAGINFO hb_cdxTagNew( LPINDEXINFO PIF, char * ITN, LONG TagHdr ) -{ - LPTAGINFO pTag; - - pTag = ( LPTAGINFO ) hb_xgrab( sizeof( TAGINFO ) ); - memset( pTag, 0, sizeof( TAGINFO ) ); - pTag->TagName = ( char * ) hb_xgrab( CDX_MAX_TAG_NAME_LEN + 1 ); - hb_strncpyUpper( pTag->TagName, ITN, CDX_MAX_TAG_NAME_LEN ); - pTag->Owner = PIF; - pTag->AscendKey = TRUE; - pTag->KeyType = 'C'; - pTag->CurKeyInfo = hb_cdxKeyNew(); - if( TagHdr == -1 ) - { - pTag->TagBlock = hb_cdxIndexGetAvailPage( PIF ); - hb_cdxIndexGetAvailPage( PIF ); - pTag->TagChanged = TRUE; - } - else - { - pTag->TagBlock = TagHdr; - hb_cdxTagTagLoad( pTag ); - } - pTag->OptFlags = 0x60; - return pTag; -} - -static void hb_cdxTagFree( LPTAGINFO pTag ) -{ - if( pTag->RootPage != NULL ) - { - hb_cdxPageFree( pTag->RootPage ); - pTag->RootPage = NULL; - } - if( pTag->TagChanged ) - hb_cdxTagTagStore( pTag ); - if( pTag->TagName != NULL ) - hb_xfree( pTag->TagName ); - if( pTag->KeyExpr != NULL ) - hb_xfree( pTag->KeyExpr ); - if( pTag->pKeyItem != NULL ) - { - if( hb_itemType( pTag->pKeyItem ) != HB_IT_BLOCK ) - hb_macroDelete( ( HB_MACRO_PTR ) hb_itemGetPtr( pTag->pKeyItem ) ); - hb_itemRelease( pTag->pKeyItem ); - } - if( pTag->ForExpr != NULL ) - hb_xfree( pTag->ForExpr ); - if( pTag->pForItem != NULL ) - { - if( hb_itemType( pTag->pForItem ) != HB_IT_BLOCK ) - hb_macroDelete( ( HB_MACRO_PTR ) hb_itemGetPtr( pTag->pForItem ) ); - hb_itemRelease( pTag->pForItem ); - } - hb_cdxKeyFree( pTag->CurKeyInfo ); - hb_xfree( pTag ); -} - -static void hb_cdxTagIndexTagNew( LPTAGINFO pTag, char * KeyExp, PHB_ITEM pKeyItem, - BYTE bType, USHORT uiLen, char * ForExp, - PHB_ITEM pForItem, BOOL Ascnd, BOOL Uniq ) -{ - CDXHEADER pHeader; - - if( KeyExp != NULL ) - { - pTag->KeyExpr = ( char * ) hb_xgrab( CDX_MAX_KEY + 1 ); - hb_strncpyUpper( pTag->KeyExpr, KeyExp, CDX_MAX_KEY ); - } - pTag->pKeyItem = pKeyItem; - if( ForExp != NULL ) - { - pTag->ForExpr = ( char * ) hb_xgrab( CDX_MAX_KEY + 1 ); - hb_strncpyUpper( pTag->ForExpr, ForExp, CDX_MAX_KEY ); - } - pTag->pForItem = pForItem; - pTag->AscendKey = Ascnd; - pTag->UniqueKey = Uniq; - pTag->KeyType = bType; - pTag->KeyLength = uiLen; - pTag->MaxKeys = ( CDX_BLOCK_SIZE - 12 ) / ( uiLen + 8 ); - memset( &pHeader, 0, sizeof( CDXHEADER ) ); - hb_cdxIndexPageWrite( pTag->Owner, pTag->TagBlock, &pHeader, sizeof( CDXHEADER ) ); - hb_cdxTagDoIndex( pTag ); -} - -static void hb_cdxTagDoIndex( LPTAGINFO pTag ) -{ - ULONG ulRecNo; - BOOL bWhileOk; - LPSORTINFO pSort; - LPKEYINFO pKey; - HB_MACRO_PTR pMacro; - - if( pTag->OptFlags & 0x80 ) - hb_cdxTagEmptyIndex( pTag ); - else - { - pSort = hb_cdxSortNew( pTag, pTag->UniqueKey ); - pKey = hb_cdxKeyNew(); - for( ulRecNo = 1; ulRecNo <= pTag->Owner->Owner->lpExtendInfo->ulRecCount; ulRecNo++ ) - { - hb_fsSeek( pTag->Owner->Owner->lpDataInfo->hFile, - pTag->Owner->Owner->lpExtendInfo->uiHeaderLen + - ( ulRecNo - 1 ) * pTag->Owner->Owner->lpExtendInfo->uiRecordLen, - FS_SET ); - hb_fsRead( pTag->Owner->Owner->lpDataInfo->hFile, - pTag->Owner->Owner->lpExtendInfo->bRecord, - pTag->Owner->Owner->lpExtendInfo->uiRecordLen ); - if( pTag->pForItem != NULL ) - /* TODO: test for expression */ - bWhileOk = TRUE; - else - bWhileOk = TRUE; - if( bWhileOk ) - { - if( hb_itemType( pTag->pKeyItem ) == HB_IT_BLOCK ) - { - - hb_vmPushSymbol( &hb_symEval ); - hb_vmPush( pTag->pKeyItem ); - hb_vmDo( 0 ); - } - else - { - pMacro = ( HB_MACRO_PTR ) hb_itemGetPtr( pTag->pKeyItem ); - hb_macroRun( pMacro ); - } - hb_itemCopy( pKey->pItem, &hb_stack.Return ); - switch( hb_itemType( pKey->pItem ) ) - { - case HB_IT_STRING: - hb_cdxSortInsertWord( pSort, ulRecNo, pKey->pItem->item.asString.value ); - break; - - default: - printf( "hb_cdxTagDoIndex( LPTAGINFO pTag )" ); - } - } - } - if( pSort->WordCount > 0 ) - hb_cdxSortDisplayWord( pSort ); - else - hb_cdxTagEmptyIndex( pTag ); - hb_cdxSortFree( pSort ); - hb_cdxKeyFree( pKey ); - } - pTag->TagChanged = TRUE; - hb_cdxTagTagStore( pTag ); -} - -static void hb_cdxTagEmptyIndex( LPTAGINFO pTag ) -{ - USHORT uiKeyLength, uiBitCount; - CDXDATA pData; - - pTag->RootBlock = hb_cdxIndexGetAvailPage( pTag->Owner ); - memset( &pData, 0, sizeof( CDXDATA ) ); - pData.Node_Atr = 3; - pData.Left_Ptr = pData.Rght_Ptr = -1; - uiKeyLength = pTag->KeyLength; - for( uiBitCount = 0; uiKeyLength; uiBitCount++, uiKeyLength >>= 1 ); - pData.cdxu.External.ShortBytes = 3; - pData.cdxu.External.RecNumBits = 24 - uiBitCount * 2; - pData.cdxu.External.RecNumMask = hb_cdxMakeMask( pData.cdxu.External.RecNumBits ); - pData.cdxu.External.FreeSpace = CDX_EXTERNAL_SPACE; - pData.cdxu.External.DupCntBits = pData.cdxu.External.TrlCntBits = uiBitCount; - pData.cdxu.External.DupCntMask = hb_cdxMakeMask( pData.cdxu.External.DupCntBits ); - pData.cdxu.External.TrlCntMask = hb_cdxMakeMask( pData.cdxu.External.TrlCntBits ); - hb_cdxIndexPageWrite( pTag->Owner, pTag->RootBlock, &pData, sizeof( CDXDATA ) ); -} - -static void hb_cdxTagTagStore( LPTAGINFO pTag ) -{ - USHORT uiForLen; - CDXHEADER pHeader; - - if( !pTag->TagChanged ) - return; - pTag->TagChanged = FALSE; - if( pTag->UniqueKey ) - pTag->OptFlags |= 0x01; - if( pTag->pForItem != NULL ) - pTag->OptFlags |= 0x08; - memset( &pHeader, 0, sizeof( CDXHEADER ) ); - pHeader.Root = pTag->RootBlock; - pHeader.Key_Lgth = pTag->KeyLength; - pHeader.IndexOpts = pTag->OptFlags; - pHeader.IndexSig = 1; - if( !pTag->AscendKey ) - pHeader.AscDesc = 1; - pHeader.Reserve4 = 1 + ( pTag->KeyExpr == NULL ? 0 : strlen( pTag->KeyExpr ) ); - pHeader.KeyExpLen = pHeader.Reserve4; - if( pTag->KeyExpr != NULL ) - strcpy( ( char * ) pHeader.KeyPool, pTag->KeyExpr ); - uiForLen = pTag->ForExpr == NULL ? 0 : strlen( pTag->ForExpr ); - if( uiForLen > 0 ) - { - pHeader.ForExpLen = uiForLen + 1; - strcpy( ( char * ) pHeader.KeyPool + pHeader.KeyExpLen, pTag->ForExpr ); - } - else - pHeader.ForExpLen = 1; - hb_cdxIndexPageWrite( pTag->Owner, pTag->TagBlock, &pHeader, sizeof( CDXHEADER ) ); -} - -static void hb_cdxTagTagOpen( LPTAGINFO pTag, BYTE bCode ) -{ - hb_cdxTagTagClose( pTag ); - pTag->RootBlock = hb_cdxTagNewRoot( pTag ); - pTag->RootPage = hb_cdxPageNew( pTag, NULL, pTag->RootBlock ); - if( bCode == 2 ) - return; - if( bCode == 0 ) - hb_cdxTagKeyRead( pTag, TOP_RECORD ); - else - printf( "hb_cdxTagTagOpen()" ); -} - -static void hb_cdxTagTagClose( LPTAGINFO pTag ) -{ - if( pTag->RootPage != NULL ) - { - hb_cdxPageFree( pTag->RootPage ); - pTag->RootPage = NULL; - } - if( pTag->TagChanged ) - hb_cdxTagTagStore( pTag ); -} - -static LONG hb_cdxTagNewRoot( LPTAGINFO pTag ) -{ - CDXHEADER pHeader; - - hb_cdxIndexPageRead( pTag->Owner, pTag->TagBlock, &pHeader, sizeof( CDXHEADER ) ); - return pHeader.Root; -} - -static void hb_cdxTagPageLoad( LPTAGINFO pTag, LPPAGEINFO pPage ) -{ - CDXDATA pData; - - hb_cdxIndexPageRead( pTag->Owner, pPage->Page, &pData, sizeof( CDXDATA ) ); - if( pData.Node_Atr > 1 ) - pPage->PageType = PAGE_LEAF; - else - pPage->PageType = PAGE_NODE; - pPage->Left = pData.Left_Ptr; - pPage->Right = pData.Rght_Ptr; - if( pData.Entry_Ct > 0 ) - { - if( pPage->PageType == PAGE_LEAF ) - hb_cdxTagExtNodeBuild( pTag, &pData, pPage ); - else - hb_cdxTagIntNodeBuild( pTag, &pData, pPage ); - } - pPage->Changed = FALSE; -} - -static void hb_cdxTagKeyRead( LPTAGINFO pTag, BYTE bTypRead ) -{ - pTag->CurKeyInfo->Tag = 0; - if( pTag->RootPage == NULL ) - return; - if( !pTag->AscendKey ) - { - switch( bTypRead ) - { - case TOP_RECORD: - bTypRead = BTTM_RECORD; - break; - - case BTTM_RECORD: - bTypRead = TOP_RECORD; - break; - - case NEXT_RECORD: - bTypRead = PREV_RECORD; - break; - - case PREV_RECORD: - bTypRead = NEXT_RECORD; - break; - } - } - pTag->TagBOF = pTag->TagEOF = FALSE; - switch( bTypRead ) - { - case TOP_RECORD: - hb_cdxTagTagOpen( pTag, 2 ); - if( pTag->pForItem != NULL ) - printf( "hb_cdxTagKeyRead()" ); - else - pTag->TagBOF = !hb_cdxPageReadTopKey( pTag->RootPage ); - if( pTag->pForItem != NULL ) - printf( "hb_cdxTagTestRange()" ); - if( pTag->TagEOF ) - pTag->TagBOF = TRUE; - pTag->TagEOF = pTag->TagBOF; - break; - - case BTTM_RECORD: - hb_cdxTagTagOpen( pTag, 2 ); - if( pTag->pForItem != NULL ) - printf( "hb_cdxTagKeyRead()" ); - else - pTag->TagEOF = !hb_cdxPageReadBottomKey( pTag->RootPage ); - if( pTag->pForItem != NULL ) - { - printf( "hb_cdxTagTestRange()" ); - } - if( pTag->TagBOF ) - pTag->TagEOF = TRUE; - pTag->TagBOF = pTag->TagEOF; - break; - - case NEXT_RECORD: - while( TRUE ) - { - pTag->TagEOF = !hb_cdxPageReadNextKey( pTag->RootPage ); - if( pTag->pForItem != NULL ) - printf( "hb_cdxTagKeyRead()" ); - else - break; - } - break; - } - if( pTag->TagBOF || pTag->TagEOF ) - { - if( !pTag->AscendKey ) - { - pTag->CurKeyInfo->Tag = pTag->TagEOF; - pTag->TagEOF = pTag->TagBOF; - pTag->TagBOF = ( BOOL ) pTag->CurKeyInfo->Tag; - } - pTag->CurKeyInfo->Tag = 0; - } -} - -static void hb_cdxTagKeyAdd( LPTAGINFO pTag, LPKEYINFO pKey ) -{ - int iSeek; - LONG lOldXtra; - LPKEYINFO pNewKey; - - lOldXtra = pKey->Xtra; - pKey->Xtra = pKey->Tag; - hb_cdxTagTagOpen( pTag, 0 ); - pNewKey = hb_cdxKeyNew(); - hb_itemCopy( pNewKey->pItem, pKey->pItem ); - pNewKey->Tag = pKey->Tag; - pNewKey->Xtra = pKey->Xtra; - if( pTag->KeyType == 'C' ) - { - while( pNewKey->pItem->item.asString.length > 0 && - pNewKey->pItem->item.asString.value[ pNewKey->pItem->item.asString.length - 1 ] == ' ' ) - pNewKey->pItem->item.asString.length--; - pNewKey->pItem->item.asString.value[ pNewKey->pItem->item.asString.length ] = 0; - } - pTag->TagBOF = pTag->TagEOF = FALSE; - iSeek = hb_cdxPageSeekKey( pTag->RootPage, pNewKey->Tag, pNewKey, TRUE ); - if( iSeek < 1 ) - { - hb_cdxPageInsertKey( pTag->RootPage, pNewKey, FALSE ); - hb_cdxTagTagOpen( pTag, 0 ); - hb_cdxPageSeekKey( pTag->RootPage, pNewKey->Tag, pNewKey, FALSE ); - iSeek = hb_cdxPageRetrieveKey( pTag->RootPage, pTag->CurKeyInfo ); - if( !pTag->AscendKey ) - { - pTag->TagBOF = ( iSeek & 2 ); - pTag->TagEOF = ( iSeek & 1 ); - } - else - { - pTag->TagBOF = ( iSeek & 1 ); - pTag->TagEOF = ( iSeek & 2 ); - } - } - else - { - if( !pTag->AscendKey ) - printf( "hb_cdxTagKeyAdd()\n"); - else - hb_cdxTagKeyRead( pTag, BTTM_RECORD ); - hb_cdxPageInsertKey( pTag->RootPage, pNewKey, TRUE ); - hb_cdxTagTagOpen( pTag, 0 ); - if( !pTag->AscendKey ) - { - printf( "hb_cdxTagKeyAdd()\n"); - pTag->TagBOF = TRUE; - } - else - { - hb_cdxTagKeyRead( pTag, BTTM_RECORD ); - pTag->TagEOF = TRUE; - } - } - hb_cdxKeyFree( pNewKey ); - pKey->Xtra = lOldXtra; -} - -static void hb_cdxTagPageStore( LPTAGINFO pTag, LPPAGEINFO PIK ) -{ - CDXDATA pData; - - memset( &pData, 0, sizeof( CDXDATA ) ); - pData.Node_Atr = ( PIK->PageType < PAGE_LEAF ) ? 0 : 2; - if( PIK->Owner == NULL ) - pData.Node_Atr++; - pData.Left_Ptr = PIK->Left; - pData.Rght_Ptr = PIK->Right; - if( pData.Node_Atr < 2 ) - hb_cdxTagIntNodeWrite( pTag, PIK->Page, &pData, PIK ); - else - hb_cdxTagExtNodeWrite( pTag, PIK->Page, &pData, PIK ); -} - -static void hb_cdxTagExtNodeWrite( LPTAGINFO pTag, LONG PN, LPCDXDATA pData, - LPPAGEINFO PIK ) -{ - USHORT uiKeyLength, uiBitCount, cd, kcnt, lm, uiCount, ck, na; - LONG sr, rp, lp, NPN, TmpTag; - LPKEYINFO p, q; - - if( pTag->OptFlags & 0x80 ) - sr = hb_fsSeek( pTag->Owner->DiskFile, 0, FS_END ); - else - sr = pTag->Owner->Owner->lpExtendInfo->ulRecCount; - uiKeyLength = pTag->KeyLength; - for( uiBitCount = 0; uiKeyLength; uiBitCount++, uiKeyLength >>= 1 ); - PIK->ReqByte = 3; - PIK->RNBits = 24 - uiBitCount * 2; - PIK->RNMask = hb_cdxMakeMask( PIK->RNBits ); - while( sr > PIK->RNMask ) - { - PIK->ReqByte++; - PIK->RNBits += 8; - PIK->RNMask = ( PIK->RNMask << 8 ) | 0xFF; - if( PIK->RNMask < 0 ) - { - PIK->RNMask = 0x7FFFFFFF; - PIK->RNBits = 31; - } - } - PIK->Space = CDX_EXTERNAL_SPACE; - PIK->DCBits = PIK->TCBits = uiBitCount; - PIK->DCMask = hb_cdxMakeMask( PIK->DCBits ); - PIK->TCMask = hb_cdxMakeMask( PIK->TCBits ); - sr = cd = kcnt = 0; - lm = sizeof( pData->cdxu.Internal.IntData ) / 2; - q = NULL; - for( uiCount = 0; uiCount < PIK->uiKeys; uiCount++ ) - { - p = hb_cdxPageGetKey( PIK, uiCount ); - if( q != NULL ) - { - hb_cdxKeyCompare( p, q, &cd, TRUE ); - if( cd > 0 ) - cd--; - } - q = p; - /* Comprobar que las Keys son de tipo car cter. */ - cd = p->pItem->item.asString.length - cd; - sr += cd + PIK->ReqByte; - if( sr < lm ) - kcnt++; - } - if( sr < CDX_EXTERNAL_SPACE ) - kcnt = PIK->uiKeys; - ck = 0; - pData->Entry_Ct = 0; - if( kcnt < PIK->uiKeys ) - { - ck = hb_cdxTagFillExternalNode( pTag, pData, PIK, kcnt, ck, &p ); - if( pData->Node_Atr % 2 > 0 ) - pData->Node_Atr--; - na = pData->Node_Atr; - rp = pData->Rght_Ptr; - lp = pData->Left_Ptr; - pData->Rght_Ptr = PN; - pData->cdxu.External.FreeSpace = PIK->Space; - NPN = hb_cdxIndexGetAvailPage( pTag->Owner ); - TmpTag = p->Tag; - p->Tag = NPN; - hb_cdxPageAddNodeKey( PIK, p ); - p->Tag = TmpTag; - if( PIK->PageType == PAGE_ROOT ) - PIK->PageType = PAGE_NODE; - hb_cdxIndexPageWrite( pTag->Owner, NPN, pData, CDX_BLOCK_SIZE ); - if( lp > 0 ) - { - hb_cdxIndexPageRead( pTag->Owner, lp, pData, CDX_BLOCK_SIZE ); - pData->Rght_Ptr = NPN; - hb_cdxIndexPageWrite( pTag->Owner, lp, pData, CDX_BLOCK_SIZE ); - } - memset( pData, 0, CDX_BLOCK_SIZE ); - pData->Node_Atr = na; - pData->Rght_Ptr = rp; - pData->Left_Ptr = NPN; - pData->Entry_Ct = 0; - kcnt = PIK->uiKeys; - } - hb_cdxTagFillExternalNode( pTag, pData, PIK, kcnt, ck, &p ); - pData->cdxu.External.FreeSpace = PIK->Space; - hb_cdxIndexPageWrite( pTag->Owner, PN, pData, sizeof( CDXDATA ) ); -} - -static USHORT hb_cdxTagFillExternalNode( LPTAGINFO pTag, LPCDXDATA pData, - LPPAGEINFO PIK, USHORT kcnt, - USHORT ck, LPKEYINFO * p ) -{ - USHORT i, k, ct, cd, v, c; - LONG m, r; - LPKEYINFO q; - - memset( pData->cdxu.External.ExtData, 0, sizeof( pData->cdxu.External.ExtData ) ); - pData->cdxu.External.FreeSpace = PIK->Space; - pData->cdxu.External.RecNumMask = PIK->RNMask; - pData->cdxu.External.DupCntMask = PIK->DCMask; - pData->cdxu.External.TrlCntMask = PIK->TCMask; - pData->cdxu.External.RecNumBits = PIK->RNBits; - pData->cdxu.External.DupCntBits = PIK->DCBits; - pData->cdxu.External.TrlCntBits = PIK->TCBits; - pData->cdxu.External.ShortBytes = PIK->ReqByte; - m = ~PIK->RNMask; - PIK->Space = CDX_EXTERNAL_SPACE; - k = CDX_EXTERNAL_SPACE; - q = NULL; - i = 0; - while( i < kcnt && ck < PIK->uiKeys ) - { - * p = hb_cdxPageGetKey( PIK, ck ); - ct = pTag->KeyLength - ( * p )->pItem->item.asString.length; - if( q != NULL ) - { - hb_cdxKeyCompare( * p, q, &cd, TRUE ); - if( cd > 0 ) - cd--; - } - else - cd = 0; - q = * p; - PIK->Space -= pTag->KeyLength + PIK->ReqByte - cd - ct; - v = i * PIK->ReqByte; - c = ( ct << ( 16 - PIK->TCBits ) ) | ( cd << ( 16 - PIK->TCBits - PIK->DCBits ) ); - memcpy( &pData->cdxu.External.ExtData[ v + PIK->ReqByte - 2 ], &c, 2 ); - memcpy( &r, &pData->cdxu.External.ExtData[ v ], 4 ); - r &= m; - r |= ( * p )->Tag; - memcpy( &pData->cdxu.External.ExtData[ v ], &r, 4 ); - k -= pTag->KeyLength - cd - ct; - if( pTag->KeyLength - cd - ct > 0 ) - memcpy( &pData->cdxu.External.ExtData[ k ], ( * p )->pItem->item.asString.value + cd, - pTag->KeyLength - cd - ct ); - i++; - ck++; - pData->Entry_Ct++; - } - return ck; -} - -static void hb_cdxTagExtNodeBuild( LPTAGINFO pTag, LPCDXDATA pData, LPPAGEINFO PIK ) -{ - USHORT k, i, v, c, t, d; - LONG r; - LPKEYINFO pKey, pLastKey; - static char szBuffer[ CDX_MAX_KEY + 1 ]; - - k = CDX_EXTERNAL_SPACE; - PIK->Space = pData->cdxu.External.FreeSpace; - PIK->RNMask = pData->cdxu.External.RecNumMask; - PIK->DCMask = pData->cdxu.External.DupCntMask; - PIK->TCMask = pData->cdxu.External.TrlCntMask; - PIK->RNBits = pData->cdxu.External.RecNumBits; - PIK->DCBits = pData->cdxu.External.DupCntBits; - PIK->TCBits = pData->cdxu.External.TrlCntBits; - PIK->ReqByte = pData->cdxu.External.ShortBytes; - i = 0; - while( i < pData->Entry_Ct ) - { - v = i * PIK->ReqByte; - memcpy( &c, &pData->cdxu.External.ExtData[ v + PIK->ReqByte - 2 ], 2 ); - t = ( c >> ( 16 - PIK->TCBits ) ) & PIK->TCMask; - d = ( c >> ( 16 - PIK->TCBits - PIK->DCBits ) ) & PIK->DCMask; - memcpy( &r, &pData->cdxu.External.ExtData[ v ], 4 ); - r &= PIK->RNMask; - k -= pTag->KeyLength - d - t; - if( pTag->KeyLength - d - t > 0 ) - memcpy( &szBuffer[ d ], &pData->cdxu.External.ExtData[ k ], - pTag->KeyLength - d - t ); - szBuffer[ pTag->KeyLength - t ] = 0; - pKey = hb_cdxKeyNew(); - pKey->Tag = r; - pKey->Xtra = r; - hb_itemPutC( pKey->pItem, szBuffer ); - if( PIK->pKeys == NULL ) - PIK->pKeys = pKey; - else - { - pLastKey = PIK->pKeys; - while( pLastKey->pNext ) - pLastKey = pLastKey->pNext; - pLastKey->pNext = pKey; - } - PIK->uiKeys++; - i++; - } -} - -static void hb_cdxTagTagLoad( LPTAGINFO pTag ) -{ - CDXHEADER pHeader; - HB_MACRO_PTR pMacro; - - hb_cdxIndexPageRead( pTag->Owner, pTag->TagBlock, &pHeader, sizeof( CDXHEADER ) ); - pTag->RootBlock = pHeader.Root; - if( pTag->RootBlock == 0 || pTag->RootBlock % CDX_BLOCK_SIZE > 0 || - pTag->RootBlock > hb_fsSeek( pTag->Owner->DiskFile, 0, FS_END ) || - pHeader.Key_Lgth > CDX_MAX_KEY ) - return; - pTag->KeyLength = pHeader.Key_Lgth; - pTag->MaxKeys = ( CDX_BLOCK_SIZE - 12 ) / ( pTag->KeyLength + 8 ); - pTag->OptFlags = pHeader.IndexOpts; - pTag->UniqueKey = ( pTag->OptFlags & 0x01 ); - pTag->AscendKey = ( pHeader.AscDesc == 0 ); - pTag->KeyExpr = ( char * ) hb_xgrab( CDX_MAX_KEY + 1 ); - hb_strncpyUpper( pTag->KeyExpr, ( char * ) pHeader.KeyPool, CDX_MAX_KEY ); - if( pTag->OptFlags < 0x80 && pTag->KeyExpr[ 0 ] == 0 ) - return; - if( pTag->OptFlags & 0x80 ) - return; - SELF_COMPILE( pTag->Owner->Owner, ( BYTE * ) pTag->KeyExpr ); - pTag->pKeyItem = pTag->Owner->Owner->valResult; - pTag->Owner->Owner->valResult = NULL; - pMacro = ( HB_MACRO_PTR ) hb_itemGetPtr( pTag->pKeyItem ); - hb_macroRun( pMacro ); - switch( hb_itemType( &hb_stack.Return ) ) - { - case HB_IT_INTEGER: - case HB_IT_LONG: - case HB_IT_DOUBLE: - pTag->KeyType = 'N'; - pTag->KeyLength = 10; - break; - - case HB_IT_DATE: - pTag->KeyType = 'D'; - pTag->KeyLength = 8; - break; - - case HB_IT_LOGICAL: - pTag->KeyType = 'C'; - pTag->KeyLength = 1; - break; - - case HB_IT_STRING: - pTag->KeyType = 'C'; - pTag->KeyLength = hb_stack.Return.item.asString.length > CDX_MAX_KEY ? CDX_MAX_KEY : - hb_stack.Return.item.asString.length; - break; - } - - if( pHeader.KeyPool[ strlen( pTag->KeyExpr ) + 1 ] == 0 ) - return; - pTag->ForExpr = ( char * ) hb_xgrab( CDX_MAX_KEY + 1 ); - hb_strncpyUpper( pTag->ForExpr, ( const char * ) pHeader.KeyPool + - strlen( pTag->KeyExpr ) + 1, CDX_MAX_KEY ); - SELF_COMPILE( pTag->Owner->Owner, ( BYTE * ) pTag->ForExpr ); - pTag->pForItem = pTag->Owner->Owner->valResult; - pTag->Owner->Owner->valResult = NULL; - pMacro = ( HB_MACRO_PTR ) hb_itemGetPtr( pTag->pForItem ); - hb_macroRun( pMacro ); - if( hb_itemType( &hb_stack.Return ) != HB_IT_LOGICAL ) - { - hb_macroDelete( pMacro ); - hb_itemRelease( pTag->pForItem ); - pTag->pForItem = NULL; - hb_xfree( pTag->ForExpr ); - pTag->ForExpr = NULL; - } -} - -static void hb_cdxTagSetRoot( LPTAGINFO pTag, LPPAGEINFO PIK ) -{ - LONG NRN, TmpTag; - LPKEYINFO p, TmpStr; - - PIK->Owner = hb_cdxPageNew( pTag, NULL, 0 ); - NRN = hb_cdxIndexGetAvailPage( pTag->Owner ); - PIK->Owner->Page = NRN; - PIK->Owner->PageType = PAGE_ROOT; - if( PIK->uiKeys > 0 ) - { - p = hb_cdxPageGetKey( PIK, PIK->uiKeys - 1 ); - TmpTag = p->Tag; - p->Tag = PIK->Page; - hb_cdxPageInsertKey( PIK->Owner, p, TRUE ); - p->Tag = TmpTag; - } - else - { - TmpStr = hb_cdxKeyNew(); - TmpStr->Tag = PIK->Page; - hb_cdxPageInsertKey( PIK->Owner, TmpStr, TRUE ); - hb_cdxKeyFree( TmpStr ); - } - PIK->Owner->Child = PIK; - pTag->RootPage = PIK->Owner; - pTag->RootBlock = NRN; - pTag->TagChanged = TRUE; -} - -static void hb_cdxTagIntNodeWrite( LPTAGINFO pTag, LONG PN, LPCDXDATA pData, LPPAGEINFO PIK ) -{ - USHORT Cnt, ck, kcnt, na; - LONG rp, lp, NPN, TmpTag; - LPKEYINFO p; - - if( PIK->uiKeys > pTag->MaxKeys ) - { - Cnt = PIK->uiKeys / 2; - Cnt = PIK->uiKeys - Cnt; - } - else - Cnt = PIK->uiKeys; - ck = 0; - kcnt = Cnt; - if( PIK->uiKeys > 0 ) - { - pData->Entry_Ct = 0; - if( kcnt < PIK->uiKeys ) - { - ck = hb_cdxTagFillInternalNode( pTag, pData, PIK, kcnt, ck, &p ); - if( pData->Node_Atr % 2 > 0 ) - pData->Node_Atr--; - na = pData->Node_Atr; - rp = pData->Rght_Ptr; - lp = pData->Left_Ptr; - pData->Rght_Ptr = PN; - NPN = hb_cdxIndexGetAvailPage( pTag->Owner ); - TmpTag = p->Tag; - p->Tag = NPN; - hb_cdxPageAddNodeKey( PIK, p ); - p->Tag = TmpTag; - if( PIK->PageType == PAGE_ROOT ) - PIK->PageType = PAGE_NODE; - hb_cdxIndexPageWrite( pTag->Owner, NPN, pData, CDX_BLOCK_SIZE ); - if( lp > 0 ) - { - hb_cdxIndexPageRead( pTag->Owner, lp, pData, CDX_BLOCK_SIZE ); - pData->Rght_Ptr = NPN; - hb_cdxIndexPageWrite( pTag->Owner, lp, pData, CDX_BLOCK_SIZE ); - } - memset( pData, 32, CDX_BLOCK_SIZE ); - pData->Node_Atr = na; - pData->Rght_Ptr = rp; - pData->Left_Ptr = NPN; - pData->Entry_Ct = 0; - kcnt = pTag->MaxKeys; - } - hb_cdxTagFillInternalNode( pTag, pData, PIK, kcnt, ck, &p ); - } - hb_cdxIndexPageWrite( pTag->Owner, PN, pData, CDX_BLOCK_SIZE ); -} - -static USHORT hb_cdxTagFillInternalNode( LPTAGINFO pTag, LPCDXDATA pData, - LPPAGEINFO PIK, USHORT kcnt, - USHORT ck, LPKEYINFO * p ) -{ - USHORT i, v; - LONG r; - - i = 0; - memset( pData->cdxu.Internal.IntData, ( pTag->KeyType == 'C' ) ? 32 : 0, - sizeof( pData->cdxu.Internal.IntData ) ); - while( i < kcnt && ck < PIK->uiKeys ) - { - * p = hb_cdxPageGetKey( PIK, ck ); - v = i * ( pTag->KeyLength + 8 ); - memcpy( &pData->cdxu.Internal.IntData[ v ], - ( * p )->pItem->item.asString.value, - ( * p )->pItem->item.asString.length ); - v += pTag->KeyLength; - r = hb_cdxSwapBytes( ( * p )->Xtra ); - memcpy( &pData->cdxu.Internal.IntData[ v ], &r, 4 ); - r = hb_cdxSwapBytes( ( * p )->Tag ); - memcpy( &pData->cdxu.Internal.IntData[ v + 4 ], &r, 4 ); - i++; - ck++; - pData->Entry_Ct++; - } - return ck; -} - -static void hb_cdxTagIntNodeBuild( LPTAGINFO pTag, LPCDXDATA pData, LPPAGEINFO pPage ) -{ - USHORT i, v; - LONG r, n; - LPKEYINFO pKey, pLastKey; - static char szBuffer[ CDX_MAX_KEY + 1 ]; - - i = 0; - while( i < pData->Entry_Ct ) - { - v = i * ( pTag->KeyLength + 8 ); - memmove( szBuffer, pData->cdxu.Internal.IntData + v, pTag->KeyLength ); - szBuffer[ pTag->KeyLength ] = 0; - v += pTag->KeyLength; - memcpy( &r, &pData->cdxu.Internal.IntData[ v ], 4 ); - r = hb_cdxSwapBytes( r ); - memcpy( &n, &pData->cdxu.Internal.IntData[ v + 4 ], 4 ); - n = hb_cdxSwapBytes( n ); - pKey = hb_cdxKeyNew(); - if( pTag->KeyType == 'C' ) - { - v = strlen( szBuffer ); - while( v > 0 && szBuffer[ v - 1 ] == 32 ) - v--; - szBuffer[ v ] = 0; - } - else - { - printf( "hb_cdxTagIntNodeBuild()" ); - } - hb_itemPutC( pKey->pItem, szBuffer ); - pKey->Tag = n; - pKey->Xtra = r; - if( pPage->pKeys == NULL ) - pPage->pKeys = pKey; - else - { - pLastKey = pPage->pKeys; - while( pLastKey->pNext != NULL ) - pLastKey = pLastKey->pNext; - pLastKey->pNext = pKey; - } - pPage->uiKeys++; - i++; - } -} - -static LONG hb_cdxTagKeyFind( LPTAGINFO pTag, LPKEYINFO pKey ) -{ - int K; - LPKEYINFO stot; - - pTag->CurKeyInfo->Tag = 0; - hb_cdxTagTagOpen( pTag, 0 ); - if( pTag->RootPage == NULL ) - return 0; - stot = hb_cdxKeyNew(); - hb_itemCopy( stot->pItem, pKey->pItem ); - stot->Tag = pKey->Tag; - stot->Xtra = pKey->Xtra; - if( pTag->KeyType == 'C' ) - { - while( stot->pItem->item.asString.length > 0 && - stot->pItem->item.asString.value[ stot->pItem->item.asString.length - 1 ] == ' ' ) - stot->pItem->item.asString.length--; - stot->pItem->item.asString.value[ stot->pItem->item.asString.length ] = 0; - } - pTag->TagBOF = pTag->TagEOF = FALSE; - K = hb_cdxPageSeekKey( pTag->RootPage, stot->Tag, stot, FALSE ); - hb_cdxKeyFree( stot ); - if( K == 0 ) - { - hb_cdxPageRetrieveKey( pTag->RootPage, pTag->CurKeyInfo ); - if( pTag->pForItem == NULL ) - return pTag->CurKeyInfo->Tag; - else - /* TODO: test for expression */ - pTag->TagEOF = TRUE; - } - else if( K < 0 ) - { - hb_cdxPageRetrieveKey( pTag->RootPage, pTag->CurKeyInfo ); - if( pTag->pForItem != NULL ) - /* TODO: test for expression */ - pTag->TagEOF = TRUE; - } - else - pTag->TagEOF = TRUE; - return 0; -} - -static LPPAGEINFO hb_cdxPageNew( LPTAGINFO PIT, LPPAGEINFO PIK, LONG FilePosn ) -{ - LPPAGEINFO pPage; - - pPage = ( LPPAGEINFO ) hb_xgrab( sizeof( 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 - { - hb_itemCopy( pPage->TagParent->CurKeyInfo->pItem, pKey->pItem ); - pPage->TagParent->CurKeyInfo->Tag = pKey->Tag; - return TRUE; - } -} - -static BOOL hb_cdxPageReadBottomKey( LPPAGEINFO pPage ) -{ - LPKEYINFO pKey; - - if( pPage->uiKeys == 0 ) - return FALSE; - pPage->CurKey = pPage->uiKeys - 1; - pKey = hb_cdxPageGetKey( pPage, pPage->CurKey ); - if( pPage->PageType < PAGE_LEAF ) - { - printf( "hb_cdxPageReadBottomKey()" ); - return TRUE; - } - else - { - hb_itemCopy( pPage->TagParent->CurKeyInfo->pItem, pKey->pItem ); - pPage->TagParent->CurKeyInfo->Tag = pKey->Tag; - return TRUE; - } -} - -static int hb_cdxPageSeekKey( LPPAGEINFO pPage, LONG lBlock, LPKEYINFO pKey, BOOL bExact ) -{ - int k; - USHORT dav; - LPKEYINFO p; - - k = 1; - bExact = ( bExact || pPage->TagParent->KeyType != 'C' ); - pPage->CurKey = 0; - if( pPage->uiKeys > 0 ) - { - while( k > 0 && pPage->CurKey < pPage->uiKeys ) - { - p = hb_cdxPageGetKey( pPage, pPage->CurKey ); - k = hb_cdxKeyCompare( pKey, p, &dav, bExact ); - if( !pPage->TagParent->AscendKey ) - k = -k; - if( k == 0 && lBlock == CDX_MAX_REC_NUM ) - k = 1; - if( k == 0 && lBlock != CDX_IGNORE_REC_NUM ) - { - if( lBlock > p->Xtra ) - k = 1; - else if( lBlock < p->Xtra ) - k = -1; - } - if( k <= 0 || pPage->CurKey == pPage->uiKeys - 1 ) - { - if( pPage->PageType < PAGE_LEAF ) - { - hb_cdxPageGetChild( pPage, p->Tag ); - k = hb_cdxPageSeekKey( pPage->Child, lBlock, pKey, bExact ); - } - else if( k == 0 && lBlock != CDX_IGNORE_REC_NUM ) - { - if( lBlock > p->Tag ) - k = 1; - else if( lBlock < p->Tag ) - k = -1; - } - } - if( k > 0 ) - pPage->CurKey++; - } - } - return k; -} - -static void hb_cdxPageInsertKey( LPPAGEINFO pPage, LPKEYINFO pKey, BOOL bAddAfter ) +/* + * Converts memo block offset into ASCII. + */ +static ULONG hb_cdxGetMemoBlock( CDXAREAP pArea, USHORT uiIndex ) { USHORT uiCount; - LPKEYINFO pNewKey, pLastKey; + BYTE bByte; + ULONG ulBlock; - if( pPage->Child != NULL ) - hb_cdxPageInsertKey( pPage->Child, pKey, bAddAfter ); - else + HB_TRACE(HB_TR_DEBUG, ("hb_cdxGetMemoBlock(%p, %hu)", pArea, uiIndex)); + + ulBlock = 0; + for( uiCount = 0; uiCount < 10; uiCount++ ) { - pNewKey = hb_cdxKeyNew(); - hb_itemCopy( pNewKey->pItem, pKey->pItem ); - pNewKey->Tag = pKey->Tag; - pNewKey->Xtra = pKey->Xtra; - if( bAddAfter ) - pPage->CurKey++; - if( pPage->CurKey > pPage->uiKeys ) - pPage->CurKey = pPage->uiKeys; - if( pPage->CurKey < 0 ) - pPage->CurKey = 0; - if( pPage->Owner != NULL && pPage->CurKey >= pPage->uiKeys ) - printf( "hb_cdxPageInsertKey()" ); - if( pPage->pKeys == NULL ) - pPage->pKeys = pNewKey; - else - { - if( pPage->CurKey == 0 ) - { - pNewKey->pNext = pPage->pKeys; - pPage->pKeys = pNewKey; - } - else - { - uiCount = pPage->CurKey; - pLastKey = pPage->pKeys; - while( uiCount > 1 && pLastKey->pNext ) - { - pLastKey = pLastKey->pNext; - uiCount--; - } - pNewKey->pNext = pLastKey->pNext; - pLastKey->pNext = pNewKey; - } - } - pPage->uiKeys++; - pPage->Changed = TRUE; + bByte = pArea->pRecord[ pArea->pFieldOffset[ uiIndex ] + uiCount ]; + if( bByte >= '0' && bByte <= '9' ) + ulBlock = ulBlock * 10 + ( bByte - '0' ); } + return ulBlock; } -static void hb_cdxPagePageStore( LPPAGEINFO pPage ) +/* + * Converts ASCII data into memo block offset. + */ +static void hb_cdxPutMemoBlock( CDXAREAP pArea, USHORT uiIndex, ULONG ulBlock ) { - if( pPage->Page == 0 ) - pPage->Page = hb_cdxIndexGetAvailPage( pPage->TagParent->Owner ); - hb_cdxTagPageStore( pPage->TagParent, pPage ); - pPage->Changed = FALSE; -} + SHORT iCount; -static BOOL hb_cdxPageReadNextKey( LPPAGEINFO pPage ) -{ - BOOL b; - LPKEYINFO p; + HB_TRACE(HB_TR_DEBUG, ("hb_cdxPutMemoBlock(%p, %hu, %lu)", pArea, uiIndex, ulBlock)); - if( pPage->uiKeys == 0 ) - return FALSE; - if( pPage->PageType < PAGE_LEAF ) + for( iCount = 9; iCount >= 0; iCount-- ) { - b = FALSE; - while( ! b && pPage->CurKey < pPage->uiKeys ) + if( ulBlock > 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 = 0; - } - b = hb_cdxPageReadNextKey( pPage->Child ); - } - else - b = FALSE; - if( !b ) - pPage->CurKey++; - } - if( !b ) - pPage->CurKey = pPage->uiKeys; - return b; - } - else - { - pPage->CurKey++; - if( pPage->CurKey < pPage->uiKeys ) - { - p = hb_cdxPageGetKey( pPage, pPage->CurKey ); - hb_itemCopy( pPage->TagParent->CurKeyInfo->pItem, p->pItem ); - pPage->TagParent->CurKeyInfo->Tag = p->Tag; - return TRUE; + pArea->pRecord[ pArea->pFieldOffset[ uiIndex ] + iCount ] = ( BYTE )( ulBlock % 10 ) + '0'; + ulBlock /= 10; } else - { - pPage->CurKey = pPage->uiKeys; - return FALSE; - } - } -} - -static LPKEYINFO hb_cdxPageGetKey( LPPAGEINFO pPage, USHORT uiKey ) -{ - LPKEYINFO pKey; - - pKey = pPage->pKeys; - while( uiKey > 0 && pKey->pNext != NULL ) - { - pKey = pKey->pNext; - uiKey--; - } - return pKey; -} - -static void hb_cdxPagePageLoad( LPPAGEINFO pPage ) -{ - LPKEYINFO pKey; - - while( pPage->pKeys != NULL ) - { - pKey = pPage->pKeys; - pPage->pKeys = pPage->pKeys->pNext; - hb_cdxKeyFree( pKey ); - } - pPage->uiKeys = 0; - hb_cdxTagPageLoad( pPage->TagParent, pPage ); - pPage->Changed = FALSE; -} - -static int hb_cdxPageRetrieveKey( LPPAGEINFO pPage, LPKEYINFO pKey ) -{ - int iCheck; - LPKEYINFO pNewKey; - - if( pPage->Owner == NULL ) - pPage->ChkBOF = pPage->ChkEOF = TRUE; - pPage->ChkBOF = ( pPage->ChkBOF && pPage->CurKey == 0 ); - pPage->ChkEOF = ( pPage->ChkEOF && pPage->CurKey == pPage->uiKeys - 1 ); - if( pPage->Child != NULL ) - return hb_cdxPageRetrieveKey( pPage->Child, pKey ); - else - { - pNewKey = hb_cdxPageGetKey( pPage, pPage->CurKey ); - hb_itemCopy( pKey->pItem, pNewKey->pItem ); - pKey->Tag = pNewKey->Tag; - iCheck = 0; - if( pPage->ChkBOF ) - iCheck = 1; - if( pPage->ChkEOF ) - iCheck += 2; - return iCheck; - } -} - -static void hb_cdxPageAddNodeKey( LPPAGEINFO pPage, LPKEYINFO pKey ) -{ - if( pPage->Owner == NULL ) - { - hb_cdxTagSetRoot( pPage->TagParent, pPage ); - pPage->NewRoot = TRUE; - } - pPage->Owner->CurKey = hb_cdxPageSeekNodeTag( pPage->Owner, pPage->Page ); - pPage->Owner->Child = NULL; - hb_cdxPageInsertKey( pPage->Owner, pKey, FALSE ); - pPage->Owner->CurKey++; - pPage->Owner->Child = pPage; - pPage->Reload = TRUE; -} - -static int hb_cdxPageSeekNodeTag( LPPAGEINFO pPage, LONG Tag ) -{ - int iSeek; - USHORT i; - LPKEYINFO p; - - if( pPage->uiKeys == 0 ) - return -1; - else - { - iSeek = -1; - i = 0; - while( iSeek < 0 && i < pPage->uiKeys ) - { - p = hb_cdxPageGetKey( pPage, i ); - if( p->Tag == Tag ) - iSeek = i; - i++; - } - return iSeek; - } -} - -static BOOL hb_cdxPageGetChild( LPPAGEINFO pPage, LONG Tag ) -{ - if( Tag == 0 ) - return FALSE; - if( pPage->TagParent->Owner->NextAvail > 0 && - Tag > pPage->TagParent->Owner->NextAvail ) - return FALSE; - if( pPage->PageType < PAGE_LEAF ) - { - if( pPage->Child != NULL ) - { - if( pPage->Child->Page != Tag || pPage->Child->Reload ) - { - hb_cdxPageFree( pPage->Child ); - pPage->Child = NULL; - } - } - if( pPage->Child == NULL ) - pPage->Child = hb_cdxPageNew( pPage->TagParent, pPage, Tag ); - } - return ( pPage->Child != NULL ); -} - -static void hb_cdxPageDeleteKey( LPPAGEINFO pPage ) -{ - BOOL lastone; - LONG TempTag; - LPKEYINFO p, pPrevKey; - - pPage->Changed = TRUE; - if( pPage->Child != NULL ) - hb_cdxPageDeleteKey( pPage->Child ); - else - { - lastone = ( pPage->CurKey >= pPage->uiKeys - 1 ); - p = hb_cdxPageGetKey( pPage, pPage->CurKey ); - if( pPage->pKeys == p ) - pPage->pKeys = p->pNext; - else - { - pPrevKey = hb_cdxPageGetKey( pPage, pPage->CurKey - 1 ); - pPrevKey->pNext = p->pNext; - } - pPage->uiKeys--; - hb_cdxKeyFree( p ); - if( pPage->CurKey >= pPage->uiKeys ) - pPage->CurKey = pPage->uiKeys - 1; - if( pPage->CurKey < 0 ) - pPage->CurKey = 0; - if( lastone && pPage->Owner != NULL ) - { - if( pPage->uiKeys > 0 ) - { - p = hb_cdxPageGetKey( pPage, pPage->CurKey ); - TempTag = p->Tag; - p->Tag = pPage->Page; - printf( "ReplaceNodeKey();" ); - p->Tag = TempTag; - } - else - printf( "DeleteNodeKey();" ); - } - } -} - -static LPINDEXINFO hb_cdxIndexNew( AREAP pArea ) -{ - LPINDEXINFO pIndex; - - pIndex = ( LPINDEXINFO ) hb_xgrab( sizeof( INDEXINFO ) ); - memset( pIndex, 0, sizeof( INDEXINFO ) ); - pIndex->DiskFile = FS_ERROR; - pIndex->Owner = pArea; - pIndex->NextAvail = -1; - return pIndex; -} - -static void hb_cdxIndexFree( LPINDEXINFO pIndex ) -{ - LPTAGINFO pTag; - - /* Free Compound tag */ - if( pIndex->CompoundTag != NULL ) - { - hb_cdxTagTagClose( pIndex->CompoundTag ); - hb_cdxTagFree( pIndex->CompoundTag ); - } - - /* Free all tags */ - while( pIndex->TagList ) - { - pTag = pIndex->TagList; - pIndex->TagList = pTag->pNext; - hb_cdxTagFree( pTag ); - } - - /* Close file */ - if( pIndex->DiskFile != FS_ERROR ) - hb_fsClose( pIndex->DiskFile ); - - hb_xfree( pIndex ); -} - -static LONG hb_cdxIndexGetAvailPage( LPINDEXINFO pIndex ) -{ - if( pIndex->NextAvail == -1 ) - hb_cdxIndexResetAvailPage( pIndex ); - pIndex->NextAvail += CDX_BLOCK_SIZE; - return pIndex->NextAvail - CDX_BLOCK_SIZE; -} - -static void hb_cdxIndexResetAvailPage( LPINDEXINFO pIndex ) -{ - pIndex->NextAvail = hb_fsSeek( pIndex->DiskFile, 0, FS_END ); -} - -static void hb_cdxIndexPageRead( LPINDEXINFO pIndex, LONG lPos, void * pBuffer, - USHORT uiSize ) -{ - if( hb_fsSeek( pIndex->DiskFile, lPos, FS_SET ) == lPos ) - hb_fsRead( pIndex->DiskFile, ( BYTE * ) pBuffer, uiSize ); -} - -static void hb_cdxIndexPageWrite( LPINDEXINFO pIndex, LONG lPos, void * pBuffer, - USHORT uiSize ) -{ - if( hb_fsSeek( pIndex->DiskFile, lPos, FS_SET ) == lPos ) - hb_fsWrite( pIndex->DiskFile, ( BYTE * ) pBuffer, uiSize ); -} - -static void hb_cdxIndexAddTag( LPINDEXINFO pIndex, char * szTagName, char * szKeyExp, - PHB_ITEM pKeyItem, BYTE bType, USHORT uiLen, char * szForExp, - PHB_ITEM pForItem, BOOL bAscending, BOOL bUnique ) -{ - LPTAGINFO pTag, pLastTag; - LPKEYINFO pKey; - - hb_cdxTagTagOpen( pIndex->CompoundTag, 0 ); - pKey = hb_cdxKeyNew(); - hb_itemPutC( pKey->pItem, szTagName ); - pTag = pIndex->TagList; - pLastTag = NULL; - while( pTag != NULL ) - { - if( hb_stricmp( pTag->TagName, szTagName ) == 0 ) - { - pKey->Tag = pTag->TagBlock; - if( hb_cdxTagKeyFind( pIndex->CompoundTag, pKey ) > 0 ) - hb_cdxPageDeleteKey( pIndex->CompoundTag->RootPage ); - if( pLastTag == NULL ) - pIndex->TagList = pTag->pNext; - else - pLastTag->pNext = pTag->pNext; - hb_cdxTagFree( pTag ); - break; - } - pLastTag = pTag; - pTag = pTag->pNext; - } - - /* Create new tag an add to tag list */ - pTag = hb_cdxTagNew( pIndex, szTagName, -1 ); - if( pIndex->TagList == NULL ) - pIndex->TagList = pTag; - else - { - pLastTag = pIndex->TagList; - while( pLastTag->pNext ) - pLastTag = pLastTag->pNext; - pLastTag->pNext = pTag; - } - hb_cdxTagIndexTagNew( pTag, szKeyExp, pKeyItem, bType, uiLen, szForExp, - pForItem, bAscending, bUnique ); - hb_itemPutC( pKey->pItem, pTag->TagName ); - pKey->Tag = pTag->TagBlock; - hb_cdxTagKeyAdd( pIndex->CompoundTag, pKey ); - hb_cdxKeyFree( pKey ); - pIndex->CompoundTag->RootPage->Changed = TRUE; - hb_cdxTagTagClose( pIndex->CompoundTag ); -} - -static LPSORTINFO hb_cdxSortNew( LPTAGINFO pTag, BOOL bUnique ) -{ - BYTE * P; - LPSORTINFO pSort; - - pSort = ( LPSORTINFO ) hb_xgrab( sizeof( SORTINFO ) ); - memset( pSort, 0, sizeof( SORTINFO ) ); - pSort->SortChunk = SORT_CHUNK_LIMIT; - pSort->NodeLimit = pSort->SortChunk / sizeof( SORTDATA ); - pSort->NodeMask = pSort->NodeShift = pSort->NodeCur = 1; - pSort->ChunkLimit = 0x8000; - while( pSort->NodeMask < pSort->NodeLimit - 1 ) - { - pSort->NodeMask = ( pSort->NodeMask << 1 ) + 1; - pSort->ChunkLimit >>= 1; - pSort->NodeShift++; - } - pSort->ChunkSize = pSort->ChunkLimit; - pSort->ChunkList = ( 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->Owner->Owner->lpExtendInfo->ulRecCount; - pSort->KeyWork = hb_cdxKeyNew(); - pSort->LastKey = hb_cdxKeyNew(); - return pSort; -} - -static void hb_cdxSortFree( LPSORTINFO pSort ) -{ - USHORT usCount; - LONG pa; - - pSort->Closing = TRUE; - for( usCount = 0; usCount <= 30; usCount++ ) - { - if( pSort->NodeList[ usCount ] != NULL ) - { - pa = pSort->NodeList[ usCount ]->Rght_Ptr; - pSort->NodeList[ usCount ]->Rght_Ptr = -1; - if( pSort->NodeList[ usCount ]->Entry_Ct > 0 ) - { - if( pSort->NodeList[ usCount + 1 ] == NULL ) - { - pSort->CurTag->RootBlock = pa; - pSort->NodeList[ usCount ]->Node_Atr++; - } - hb_cdxIndexPageWrite( pSort->CurTag->Owner, pa, pSort->NodeList[ usCount ], - sizeof( CDXDATA ) ); - if( pSort->NodeList[ usCount + 1 ] != NULL ) - hb_cdxSortAddToNode( pSort, ( USHORT ) ( usCount + 1 ), pa, - pSort->LastTag, pSort->KeyWork ); - } - hb_xfree( ( LPCDXDATA ) pSort->NodeList[ usCount ] ); - } - } - - if( pSort->ChunkList != NULL ) - { - for( usCount = 0; usCount < pSort->ChunkLimit; usCount++ ) - { - if( pSort->ChunkList[ usCount ] != 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 ) -{ - char s[ 34 ]; - USHORT w, cc, nc, EOK; - SHORT v; - LPSORTDATA wx; - - hb_cdxltoa( Tag, s + 1, 10 ); - w = strlen( Value ); - if( pSort->NodeLimit - pSort->NodeCur < w + strlen( s + 1 ) + 1 ) - { - cc = pSort->ChunkCur; - nc = pSort->NodeCur; - hb_cdxSortGetNewChunk( pSort ); - if( pSort->ChunkCur > 0 ) - { - pSort->ChunkCur = cc; - pSort->NodeCur = nc; - } - } - pSort->WordCount++; - strcpy( pSort->WPch, Value ); - v = strlen( pSort->WPch ); - if( v > 0 ) - { - if( v > pSort->KeySize ) - pSort->KeySize = v; - v--; - } - while( v >= 0 && pSort->WPch[ v ] == ' ' ) - { - pSort->WPch[ v ] = 0; - v--; - } - v++; - EOK = v; - if( !pSort->Unique ) - { - s[ 0 ] = ( char ) strlen( s + 1 ); - memcpy( &pSort->WPch[ v ], s, s[ 0 ] + 1 ); - v += ( SHORT ) ( s[ 0 ] + 1 ); - pSort->WPch[ v ] = 0; - } - pSort->LevelPtr = pSort->RootLink; - pSort->PriorPtr = 0; - pSort->WCur = 0; - do - hb_cdxSortStuffKey( pSort, &wx ); - while( pSort->WPch[ pSort->WCur ] != 0 ); - if( pSort->Unique ) - { - if( wx->sortu.A.NUse == SORT_END_OF_KEY ) - return; - wx->sortu.A.NUse = SORT_END_OF_KEY; - if( EOK == 0 ) - EOK++; - memcpy( &pSort->WPch[ EOK ], s, s[ 0 ] + 1 ); - v = EOK + s[ 0 ] + 1; - pSort->WPch[ v ] = 0; - do - hb_cdxSortStuffKey( pSort, &wx ); - while( pSort->WPch[ pSort->WCur ] != 0 ); - } - wx->sortu.A.NUse = SORT_END_OF_WORD; -} - -static void hb_cdxSortStuffKey( LPSORTINFO pSort, LPSORTDATA * wx ) -{ - USHORT w; - SHORT v; - LONG p1; - LPSORTDATA x; - - hb_cdxSortGetNode( pSort, pSort->WPch[ pSort->WCur ], &p1 ); - * wx = hb_cdxSortLinkGet( pSort, p1 ); - pSort->WCur++; - if( pSort->LevelPtr == 0 ) - { - if( pSort->PriorPtr > 0 ) - { - x = hb_cdxSortLinkGet( pSort, pSort->PriorPtr ); - x->sortu.A.WordArray = p1; - } - w = strlen( pSort->WPch ); - v = w - pSort->WCur - 1; - if( v > 0 ) - { - if( v > 4 ) - v = 4; - memcpy( ( * wx )->sortu.B.ChrStack, &pSort->WPch[ pSort->WCur ], v ); - ( * wx )->sortu.A.NUse = SORT_STACK_OF_CHAR; - pSort->WCur += v; - } - } - pSort->PriorPtr = p1; - pSort->LevelPtr = ( * wx )->sortu.A.WordArray; -} - -static void hb_cdxSortGetNode( LPSORTINFO pSort, char Character, LONG * NewLink ) -{ - char c; - int df; - LONG p, q, r; - LPSORTDATA px, qx, rx; - - if( pSort->LevelPtr == 0 ) - { - hb_cdxSortLinkNew( pSort, NewLink ); - px = hb_cdxSortLinkGet( pSort, * NewLink ); - px->sortu.A.Character = Character; - return; - } - p = pSort->LevelPtr; - px = hb_cdxSortLinkGet( pSort, pSort->LevelPtr ); - q = pSort->PriorPtr; - if( px->sortu.A.NUse == SORT_STACK_OF_CHAR ) - { - hb_cdxSortLinkNew( pSort, &r ); - c = px->sortu.A.Character; - qx = hb_cdxSortLinkGet( pSort, q ); - qx->sortu.A.WordArray = r; - rx = hb_cdxSortLinkGet( pSort, r ); - rx->sortu.A.Character = c; - rx->sortu.A.WordArray = p; - px = hb_cdxSortLinkGet( pSort, p ); - px->sortu.A.Character = px->sortu.B.ChrStack[ 0 ]; - memmove( &px->sortu.B.ChrStack[ 0 ], &px->sortu.B.ChrStack[ 1 ], 3 ); - px->sortu.B.ChrStack[ 3 ] = 0; - if( px->sortu.C.ChrFill != 0 ) - px->sortu.A.NUse = SORT_STACK_OF_CHAR; - else - px->sortu.A.NUse = SORT_ACTIVE_LIST; - p = r; - px = hb_cdxSortLinkGet( pSort, p ); - } - if( Character > px->sortu.A.Character ) - df = 1; - else if( Character < px->sortu.A.Character ) - df = -1; - else - df = 0; - if( !pSort->Ascend && Character > 0 && px->sortu.A.Character > 0 ) - df = -df; - while( px->sortu.A.LevelLink != 0 && df > 0 ) - { - q = p; - p = px->sortu.A.LevelLink; - px = hb_cdxSortLinkGet( pSort, p ); - if( px->sortu.A.NUse == SORT_STACK_OF_CHAR ) - { - hb_cdxSortLinkNew( pSort, &r ); - c = px->sortu.A.Character; - qx = hb_cdxSortLinkGet( pSort, q ); - qx->sortu.A.WordArray = r; - rx = hb_cdxSortLinkGet( pSort, r ); - rx->sortu.A.Character = c; - rx->sortu.A.WordArray = p; - px = hb_cdxSortLinkGet( pSort, p ); - px->sortu.A.Character = px->sortu.B.ChrStack[ 0 ]; - memmove( &px->sortu.B.ChrStack[ 0 ], &px->sortu.B.ChrStack[ 1 ], 3 ); - px->sortu.B.ChrStack[ 3 ] = 0; - if( px->sortu.C.ChrFill != 0 ) - px->sortu.A.NUse = SORT_STACK_OF_CHAR; - else - px->sortu.A.NUse = SORT_ACTIVE_LIST; - p = r; - px = hb_cdxSortLinkGet( pSort, p ); - } - if( Character > px->sortu.A.Character ) - df = 1; - else if( Character < px->sortu.A.Character ) - df = -1; - else - df = 0; - if( !pSort->Ascend && Character > 0 && px->sortu.A.Character > 0 ) - df = -df; - } - if( df == 0 ) - * NewLink = p; - else - { - hb_cdxSortLinkNew( pSort, &r ); - if( df == -1 ) - { - qx = hb_cdxSortLinkGet( pSort, q ); - if( q == pSort->PriorPtr ) - qx->sortu.A.WordArray = r; - else - qx->sortu.A.LevelLink = r; - } - else - { - p = px->sortu.A.LevelLink; - px->sortu.A.LevelLink = r; - } - rx = hb_cdxSortLinkGet( pSort, r ); - rx->sortu.A.LevelLink = p; - rx->sortu.A.Character = Character; - * NewLink = r; - } -} - -static LPSORTDATA hb_cdxSortLinkGet( LPSORTINFO pSort, LONG Value ) -{ - LPSORTDATA P; - - if( Value > 0 ) - { - P = ( LPSORTDATA ) pSort->ChunkList[ Value >> pSort->NodeShift ]; - if( P != NULL ) - return &P[ Value & pSort->NodeMask ]; - else - return NULL; - } - return NULL; -} - -static void hb_cdxSortDisplayWord( LPSORTINFO pSort ) -{ - pSort->WPch[ 0 ] = 0; - hb_cdxSortRecurseDict( pSort, pSort->RootLink, 0 ); -} - -static void hb_cdxSortRecurseDict( LPSORTINFO pSort, LONG WPtr, LONG WBgn ) -{ - USHORT WCnt; - - if( WPtr == 0 ) - return; - WCnt = strlen( pSort->WPch ); - pSort->WAdr = hb_cdxSortLinkGet( pSort, WPtr ); - if( pSort->WAdr->sortu.A.Character != 0 ) - { - pSort->WPch[ WCnt ] = pSort->WAdr->sortu.A.Character; - pSort->WPch[ WCnt + 1 ] = 0; - } - if( pSort->WAdr->sortu.A.NUse == SORT_STACK_OF_CHAR ) - { - memcpy( &pSort->WPch[ strlen( pSort->WPch ) ], pSort->WAdr->sortu.B.ChrStack, 4 ); - pSort->WPch[ WCnt + 5 ] = 0; - } - if( pSort->WAdr->sortu.A.NUse == SORT_END_OF_WORD ) - hb_cdxSortSendWord( pSort, pSort->WPch ); - else - { - if( pSort->WAdr->sortu.A.WordArray != 0 ) - hb_cdxSortRecurseDict( pSort, pSort->WAdr->sortu.A.WordArray, WBgn ); - pSort->WAdr = hb_cdxSortLinkGet( pSort, WPtr ); - } - pSort->WPch[ WCnt ] = 0; - if( pSort->WAdr->sortu.A.LevelLink != 0 && pSort->WAdr->sortu.A.NUse != SORT_STACK_OF_CHAR ) - hb_cdxSortRecurseDict( pSort, pSort->WAdr->sortu.A.LevelLink, WCnt ); -} - -static void hb_cdxSortSendWord( LPSORTINFO pSort, char * Value ) -{ - LONG Tag; - BYTE OldByte; - char * pce; - - pce = Value + strlen( Value ) - 1; - while( pce[ 0 ] > 31 ) - pce--; - Tag = atol( pce + 1 ); - OldByte = pce[ 0 ]; - pce[ 0 ] = 0; - hb_cdxSortOutputWord( pSort, Tag, Value ); - pce[ 0 ] = OldByte; -} - -static void hb_cdxSortOutputWord( LPSORTINFO pSort, LONG Tag, char * Value ) -{ - pSort->KeyCnt++; - hb_itemPutC( pSort->KeyWork->pItem, Value ); - if( pSort->CurTag->KeyType != 'C' ) - printf( "pSort->CurTag->AdjustValue( &KeyWork );" ); - hb_cdxSortAddToNode( pSort, 0, Tag, Tag, pSort->KeyWork ); - pSort->LastTag = Tag; - hb_itemCopy( pSort->LastKey->pItem, pSort->KeyWork->pItem ); -} - -static void hb_cdxSortAddToNode( LPSORTINFO pSort, USHORT Lvl, LONG Tag, - LONG Link, LPKEYINFO Value ) -{ - USHORT i, bitcnt; - LONG sr; - - if( pSort->NodeList[ Lvl ] == NULL ) - { - pSort->NodeList[ Lvl ] = ( LPCDXDATA ) hb_xgrab( sizeof( CDXDATA ) ); - memset( pSort->NodeList[ Lvl ], 0, sizeof( CDXDATA ) ); - if( Lvl == 0 ) - { - sr = pSort->KeyTot; - i = pSort->CurTag->KeyLength; - for( bitcnt = 0; i; bitcnt++, i >>= 1 ); - pSort->NodeList[ 0 ]->cdxu.External.ShortBytes = 3; - pSort->NodeList[ 0 ]->cdxu.External.RecNumBits = 24 - bitcnt * 2; - pSort->NodeList[ 0 ]->cdxu.External.RecNumMask = - hb_cdxMakeMask( pSort->NodeList[ 0 ]->cdxu.External.RecNumBits ); - while( sr > pSort->NodeList[ 0 ]->cdxu.External.RecNumMask ) - { - pSort->NodeList[ 0 ]->cdxu.External.ShortBytes++; - pSort->NodeList[ 0 ]->cdxu.External.RecNumBits += 8; - pSort->NodeList[ 0 ]->cdxu.External.RecNumMask = - ( pSort->NodeList[ 0 ]->cdxu.External.RecNumMask << 8 ) | 0xFF; - } - pSort->NodeList[ 0 ]->cdxu.External.FreeSpace = CDX_EXTERNAL_SPACE; - pSort->NodeList[ 0 ]->cdxu.External.DupCntBits = - pSort->NodeList[ 0 ]->cdxu.External.TrlCntBits = bitcnt; - pSort->NodeList[ 0 ]->cdxu.External.DupCntMask = - hb_cdxMakeMask( pSort->NodeList[ 0 ]->cdxu.External.DupCntBits ); - pSort->NodeList[ 0 ]->cdxu.External.TrlCntMask = - hb_cdxMakeMask( pSort->NodeList[ 0 ]->cdxu.External.TrlCntBits ); - } - pSort->NodeList[ Lvl ]->Left_Ptr = -1; - pSort->NodeList[ Lvl ]->Rght_Ptr = hb_cdxIndexGetAvailPage( pSort->CurTag->Owner ); - pSort->NodeList[ Lvl ]->Node_Atr = ( Lvl == 0 ) ? 2 : 0; - } - if( Lvl == 0 ) - hb_cdxSortAddExternal( pSort, Lvl, Tag, Link, Value ); - else - hb_cdxSortAddInternal( pSort, Lvl, Tag, Link, Value ); -} - -static void hb_cdxSortAddExternal( LPSORTINFO pSort, USHORT Lvl, LONG Tag, LONG Link, - LPKEYINFO Value ) -{ - USHORT k, ct, cd, v, c; - LONG m, r, pa; - - if( pSort->NodeList[ Lvl ]->Entry_Ct == 0 ) - { - memset( pSort->NodeList[ Lvl ]->cdxu.External.ExtData, 0, - sizeof( pSort->NodeList[ Lvl ]->cdxu.External.ExtData ) ); - pSort->NodeList[ Lvl ]->cdxu.External.FreeSpace = CDX_EXTERNAL_SPACE; - hb_itemPutC( pSort->LastKey->pItem, "" ); - } - m = ~pSort->NodeList[ Lvl ]->cdxu.External.RecNumMask; - ct = ( USHORT ) ( pSort->CurTag->KeyLength - - Value->pItem->item.asString.length ); - hb_cdxKeyCompare( Value, pSort->LastKey, &cd, TRUE ); - if( cd > 0 ) - cd -= ( USHORT ) 1; - v = ( USHORT ) ( pSort->NodeList[ Lvl ]->Entry_Ct * - pSort->NodeList[ Lvl ]->cdxu.External.ShortBytes ); - k = ( USHORT ) ( pSort->NodeList[ Lvl ]->cdxu.External.FreeSpace + v ); - pSort->NodeList[ Lvl ]->cdxu.External.FreeSpace -= - ( USHORT ) ( pSort->CurTag->KeyLength + - pSort->NodeList[ Lvl ]->cdxu.External.ShortBytes - cd - ct ); - c = ( USHORT ) ( ( ct << ( 16 - pSort->NodeList[ Lvl ]->cdxu.External.TrlCntBits ) ) | - ( cd << ( 16 - pSort->NodeList[ Lvl ]->cdxu.External.TrlCntBits - - pSort->NodeList[ Lvl ]->cdxu.External.DupCntBits ) ) ); - memcpy( &pSort->NodeList[ Lvl ]->cdxu.External.ExtData[ v + - pSort->NodeList[ Lvl ]->cdxu.External.ShortBytes - 2 ], &c, 2 ); - memcpy( &r, &pSort->NodeList[ Lvl ]->cdxu.External.ExtData[ v ], 4 ); - r &= m; - r |= Tag; - memcpy( &pSort->NodeList[ Lvl ]->cdxu.External.ExtData[ v ], &r, 4 ); - k -= ( USHORT ) ( pSort->CurTag->KeyLength - cd - ct ); - if( pSort->CurTag->KeyLength - cd - ct > 0 ) - memcpy( &pSort->NodeList[ Lvl ]->cdxu.External.ExtData[ k ], - Value->pItem->item.asString.value + cd, - pSort->CurTag->KeyLength - cd - ct ); - pSort->NodeList[ Lvl ]->Entry_Ct++; - if( pSort->NodeList[ Lvl ]->cdxu.External.FreeSpace < - ( pSort->CurTag->KeyLength + 8 + - pSort->NodeList[ Lvl ]->cdxu.External.ShortBytes ) * 2 ) - { - pa = pSort->NodeList[ Lvl ]->Rght_Ptr; - if( pSort->KeyCnt < pSort->KeyTot ) - pSort->NodeList[ Lvl ]->Rght_Ptr = hb_cdxIndexGetAvailPage( pSort->CurTag->Owner ); - else - pSort->NodeList[ Lvl ]->Rght_Ptr = -1; - pSort->NodeList[ Lvl ]->Node_Atr = 2; - hb_cdxIndexPageWrite( pSort->CurTag->Owner, pa, pSort->NodeList[ Lvl ], - sizeof( CDXDATA ) ); - pSort->NodeList[ Lvl ]->Left_Ptr = pa; - hb_cdxSortAddToNode( pSort, ( USHORT ) ( Lvl + 1 ), pa, Link, Value ); - pSort->NodeList[ Lvl ]->Entry_Ct = 0; - } -} - -static void hb_cdxSortAddInternal( LPSORTINFO pSort, USHORT Lvl, LONG Tag, LONG Link, - LPKEYINFO Value ) -{ - USHORT v; - LONG r, pa; - - if( pSort->NodeList[ Lvl ]->Entry_Ct == 0 ) - memset( pSort->NodeList[ Lvl ]->cdxu.Internal.IntData, - pSort->CurTag->KeyType == 'C' ? 32 : 0, - sizeof( pSort->NodeList[ Lvl ]->cdxu.Internal.IntData ) ); - v = ( USHORT ) ( pSort->NodeList[ Lvl ]->Entry_Ct * - ( pSort->CurTag->KeyLength + 8 ) ); - memcpy( &pSort->NodeList[ Lvl ]->cdxu.Internal.IntData[ v ], - Value->pItem->item.asString.value, Value->pItem->item.asString.length ); - v += pSort->CurTag->KeyLength; - r = hb_cdxSwapBytes( Link ); - memcpy( &pSort->NodeList[ Lvl ]->cdxu.Internal.IntData[ v ], &r, 4 ); - r = hb_cdxSwapBytes( Tag ); - memcpy( &pSort->NodeList[ Lvl ]->cdxu.Internal.IntData[ v + 4 ], &r, 4 ); - pSort->NodeList[ Lvl ]->Entry_Ct++; - if( pSort->NodeList[ Lvl ]->Entry_Ct >= pSort->CurTag->MaxKeys ) - { - pa = pSort->NodeList[ Lvl ]->Rght_Ptr; - if( !pSort->Closing ) - pSort->NodeList[ Lvl ]->Rght_Ptr = hb_cdxIndexGetAvailPage( pSort->CurTag->Owner ); - else - pSort->NodeList[ Lvl ]->Rght_Ptr = -1; - pSort->NodeList[ Lvl ]->Node_Atr = 0; - hb_cdxIndexPageWrite( pSort->CurTag->Owner, pa, pSort->NodeList[ Lvl ], - sizeof( CDXDATA ) ); - pSort->NodeList[ Lvl ]->Left_Ptr = pa; - hb_cdxSortAddToNode( pSort, ( USHORT ) ( Lvl + 1 ), pa, Link, Value ); - pSort->NodeList[ Lvl ]->Entry_Ct = 0; + pArea->pRecord[ pArea->pFieldOffset[ uiIndex ] + iCount ] = ' '; } } /* - * -- CDX METHODS -- + * 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 ); + } + } +} + +/* + * 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 == uiBlocks ) + { + 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 ) + { + pFreeBlock++; + iCount++; + pFreeBlock->ulBlock = ulBlock; + pFreeBlock->uiBlocks += 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 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, ulNewBlock, 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; +} + +/* + * -- DBFCDX METHODS -- */ -#define cdxBof NULL -#define cdxEof NULL -#define cdxFound NULL -#define cdxGoBottom NULL -#define cdxGoTo NULL -#define cdxGoToId NULL -#define cdxGoTop NULL -#define cdxSkip NULL -#define cdxSkipFilter NULL -#define cdxSkipRaw NULL -#define cdxAddField NULL -#define cdxAppend NULL -#define cdxCreateFields NULL -#define cdxDeleteRec NULL -#define cdxDeleted NULL -#define cdxFieldCount NULL -#define cdxFieldDisplay NULL -#define cdxFieldInfo NULL -#define cdxFieldName NULL -#define cdxFlush NULL -#define cdxGetRec NULL -#define cdxGetValue NULL -#define cdxGetVarLen NULL -#define cdxGoCold NULL -#define cdxGoHot NULL -#define cdxPutRec NULL -#define cdxPutValue NULL -#define cdxRecAll NULL -#define cdxRecCount NULL -#define cdxRecInfo NULL -#define cdxRecNo NULL -#define cdxSetFieldsExtent NULL -#define cdxAlias NULL -#define cdxCreate NULL -#define cdxNewArea NULL -#define cdxOpen NULL -#define cdxRelease NULL -#define cdxStructSize NULL -#define cdxSysName NULL -#define cdxEval NULL -#define cdxPack NULL -#define cdxZap NULL -#define cdxchildEnd NULL -#define cdxchildStart NULL -#define cdxchildSync NULL -#define cdxsyncChildren NULL -#define cdxclearRel NULL -#define cdxforceRel NULL -#define cdxrelArea NULL -#define cdxrelEval NULL -#define cdxrelText NULL -#define cdxsetRel NULL -#define cdxOrderCondition NULL -#define cdxClearFilter NULL -#define cdxClearLocate NULL -#define cdxFilterText NULL -#define cdxSetFilter NULL -#define cdxSetLocate NULL -#define cdxCompile NULL -#define cdxError NULL -#define cdxEvalBlock NULL -#define cdxRawLock NULL -#define cdxLock NULL -#define cdxUnLock NULL -#define cdxCloseMemFile NULL -#define cdxReadDBHeader NULL -#define cdxWhoCares NULL - -static ERRCODE cdxClose( AREAP pArea ) +/* + * Obtain the current value of a field. + */ +ERRCODE hb_cdxGetValue( CDXAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) { - HB_TRACE(HB_TR_DEBUG, ("cdxClose(%p)", pArea)); + BOOL bDeleted; - cdxOrderListClear( pArea ); - return SUPER_CLOSE( pArea ); -} + HB_TRACE(HB_TR_DEBUG, ("hb_cdxGetValue(%p, %hu, %p)", pArea, uiIndex, pItem)); -static ERRCODE cdxCreateMemFile( AREAP pArea, LPDBOPENINFO pCreateInfo ) -{ - LPFILEINFO lpMemInfo; - LPMEMOHEADER pMemoHeader; - BOOL bError; - PHB_ITEM pError = NULL; - - HB_TRACE(HB_TR_DEBUG, ("cdxCreateMemFile(%p, %p)", pArea, pCreateInfo)); - - lpMemInfo = pArea->lpDataInfo->pNext; - do + if( pArea->lpFields[ uiIndex - 1 ].uiType == HB_IT_MEMO ) { - lpMemInfo->hFile = hb_fsCreate( pCreateInfo->abName, FC_NORMAL ); - if( lpMemInfo->hFile == FS_ERROR ) - { - if( !pError ) - { - pError = hb_errNew(); - hb_errPutGenCode( pError, EG_CREATE ); - hb_errPutSubCode( pError, 1005 ); - hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_CREATE ) ); - hb_errPutFileName( pError, ( char * ) pCreateInfo->abName ); - hb_errPutFlags( pError, EF_CANRETRY ); - } - bError = ( SELF_ERROR( pArea, pError ) == E_RETRY ); - } - else - bError = FALSE; - } while( bError ); - if( pError ) - hb_errRelease( pError ); - - if( lpMemInfo->hFile == FS_ERROR ) - return FAILURE; - - pMemoHeader = ( LPMEMOHEADER ) hb_xgrab( 512 ); - memset( pMemoHeader, 0, 512 ); - pMemoHeader->lNextBlock = hb_cdxSwapBytes( 512 / MEMO_BLOCK ); - pMemoHeader->lBlockSize = hb_cdxSwapBytes( MEMO_BLOCK ); - bError = ( hb_fsWrite( lpMemInfo->hFile, ( BYTE * ) pMemoHeader, 512 ) != 512 ); - hb_xfree( pMemoHeader ); - hb_fsClose( lpMemInfo->hFile ); - lpMemInfo->hFile = FS_ERROR; - if( bError ) - return FAILURE; - else - return SUCCESS; -} - -static ERRCODE cdxGetValueFile( AREAP pArea, USHORT uiIndex, void * pFile ) -{ - ULONG lRecNo, lNewRecNo; - BYTE * szText, szEndChar; - LPFIELD pField; - - HB_TRACE(HB_TR_DEBUG, ("cdxGetValueFile(%p, %hu, %p)", pArea, uiIndex, pFile)); - HB_SYMBOL_UNUSED( pFile ); - - if( uiIndex > pArea->uiFieldCount ) - return FAILURE; - - pField = pArea->lpFields + uiIndex - 1; - szText = pArea->lpExtendInfo->bRecord + pField->uiOffset; - if( !( ( LPDBFMEMO ) pField->memo )->pData ) - memset( szText, ' ', pField->uiLen ); - else - { - szEndChar = * ( szText + pField->uiLen ); - * ( szText + pField->uiLen ) = 0; - lRecNo = atol( ( char * ) szText ); - lNewRecNo = lRecNo; - if( !hb_cdxWriteMemo( pArea, ( LPDBFMEMO ) pField->memo, &lNewRecNo ) ) + /* Force read record */ + if( SELF_DELETED( ( AREAP ) pArea, &bDeleted ) == FAILURE ) return FAILURE; - if( lNewRecNo != lRecNo ) - hb_cdxltoa( lNewRecNo, ( char * ) szText, pField->uiLen ); - * ( szText + pField->uiLen ) = szEndChar; + + hb_cdxGetMemo( pArea, uiIndex - 1, pItem ); + return SUCCESS; } - ( ( LPDBFMEMO ) pField->memo )->fChanged = FALSE; + else + return SUPER_GETVALUE( ( AREAP ) pArea, uiIndex, pItem ); +} + +/* + * 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; } -static ERRCODE cdxInfo( AREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) +/* + * Assign a value to a field. + */ +ERRCODE hb_cdxPutValue( CDXAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) { - HB_TRACE(HB_TR_DEBUG, ("cdxInfo(%p, %hu, %p)", pArea, uiIndex, pItem)); + BOOL bDeleted; + PHB_ITEM pError; - if( uiIndex == DBI_MEMOEXT ) + HB_TRACE(HB_TR_DEBUG, ("hb_cdxPutValue(%p, %hu, %p)", pArea, uiIndex, pItem)); + + if( pArea->lpFields[ uiIndex - 1 ].uiType == HB_IT_MEMO ) { - hb_itemPutC( pItem, ".fpt" ); - return SUCCESS; - } + if( HB_IS_MEMO( pItem ) || HB_IS_STRING( pItem ) ) + { + /* Force read record */ + if( SELF_DELETED( ( AREAP ) pArea, &bDeleted ) == FAILURE ) + return FAILURE; - return SUPER_INFO( pArea, uiIndex, pItem ); + 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 ] = pArea->fDeleted ? '*' : ' '; + return SUCCESS; + } + } + return SUPER_PUTVALUE( ( AREAP ) pArea, uiIndex, pItem); } -static ERRCODE cdxOpenMemFile( AREAP pArea, LPDBOPENINFO pOpenInfo ) +/* + * Close the table in the WorkArea. + */ +ERRCODE hb_cdxClose( CDXAREAP pArea ) { - LPFILEINFO lpMemInfo; - LPMEMOHEADER pMemoHeader; - USHORT uiFlags; - PHB_ITEM pError = NULL; + ERRCODE uiError; + + HB_TRACE(HB_TR_DEBUG, ("hb_cdxClose(%p)", pArea)); + +/* SELF_ORDLSTCLEAR( ( AREAP ) pArea ); */ + + /* Free Indexes array */ + if( pArea->lpIndexes ) + { + hb_xfree( pArea->lpIndexes ); + pArea->lpIndexes = NULL; + } + 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; + } + return uiError; +} + +/* + * 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; + + default: + return SUPER_INFO( ( AREAP ) pArea, uiIndex, pItem ); + } + + return SUCCESS; +} + +/* + * Open a data store in the WorkArea. + */ +ERRCODE hb_cdxOpen( CDXAREAP pArea, LPDBOPENINFO pOpenInfo ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_cdxOpen(%p, %p)", pArea, pOpenInfo)); + + + /* 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 ) + { + printf("TODO: hb_cdxOpen()\n"); + } + return SUCCESS; +} + +/* + * 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; +} + +/* + * 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; +} + +/* + * 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, ("cdxOpenMemFile(%p, %p)", pArea, pOpenInfo)); + HB_TRACE(HB_TR_DEBUG, ("hb_cdxCreateMemFile(%p, %p)", pArea, pCreateInfo)); + + if( pCreateInfo ) + { + pError = NULL; + /* Try create */ + do + { + pArea->hMemoFile = hb_fsCreate( 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; +} + +/* + * Open a memo file in the specified WorkArea. + */ +ERRCODE hb_cdxOpenMemFile( CDXAREAP pArea, LPDBOPENINFO pOpenInfo ) +{ + USHORT uiFlags; + BOOL bRetry; + MEMOHEADER fptHeader; + PHB_ITEM pError; + + HB_TRACE(HB_TR_DEBUG, ("hb_cdxOpenMemFile(%p, %p)", pArea, pOpenInfo)); - lpMemInfo = pArea->lpDataInfo->pNext; uiFlags = pOpenInfo->fReadonly ? FO_READ : FO_READWRITE; uiFlags |= pOpenInfo->fShared ? FO_DENYNONE : FO_EXCLUSIVE; + pError = NULL; + + /* Try open */ do { - lpMemInfo->hFile = hb_fsOpen( pOpenInfo->abName, uiFlags ); - if( lpMemInfo->hFile == FS_ERROR ) + pArea->hMemoFile = hb_fsOpen( pOpenInfo->abName, uiFlags ); + if( pArea->hMemoFile == FS_ERROR ) { if( !pError ) { pError = hb_errNew(); hb_errPutGenCode( pError, EG_OPEN ); - hb_errPutSubCode( pError, 1002 ); + hb_errPutSubCode( pError, EDBF_OPEN_DBF ); hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_OPEN ) ); hb_errPutFileName( pError, ( char * ) pOpenInfo->abName ); - hb_errPutFlags( pError, EF_CANRETRY ); + hb_errPutFlags( pError, EF_CANRETRY | EF_CANDEFAULT ); } - bRetry = ( SELF_ERROR( pArea, pError ) == E_RETRY ); + bRetry = ( SELF_ERROR( ( AREAP ) pArea, pError ) == E_RETRY ); } else bRetry = FALSE; } while( bRetry ); if( pError ) - hb_errRelease( pError ); - - if( lpMemInfo->hFile == FS_ERROR ) - return FAILURE; - - pMemoHeader = ( LPMEMOHEADER ) hb_xgrab( 512 ); - if( hb_fsRead( lpMemInfo->hFile, ( BYTE * ) pMemoHeader, 512 ) != 512 ) { - hb_xfree( pMemoHeader ); - return FAILURE; + hb_errRelease( pError ); + pError = NULL; } - hb_xfree( pMemoHeader ); + 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 ); return SUCCESS; } -static ERRCODE cdxOrderCreate( AREAP pArea, LPDBORDERCREATEINFO pOrderInfo ) +/* + * Read the database file header record in the WorkArea. + */ +ERRCODE hb_cdxReadDBHeader( CDXAREAP pArea ) { - PHB_ITEM pExpr, pKeyExp, pForExp, pResult, pError; - HB_MACRO_PTR pExpMacro, pForMacro; - USHORT uiType, uiLen, uiCount; - char * szFileName, * szTagName; - PHB_FNAME pFileName; - DBORDERINFO pExtInfo; - LPINDEXINFO pIndex; - LPTAGINFO pTag, pLastTag; - DBFHEADER pHeader; - BYTE bType; - BOOL bNewFile; + DBFHEADER dbHeader; + BOOL bRetry, bError; + PHB_ITEM pError; - HB_TRACE(HB_TR_DEBUG, ("cdxOrderCreate(%p, %p)", pArea, pOrderInfo)); + HB_TRACE(HB_TR_DEBUG, ("hb_cdxReadHeader(%p)", pArea)); - if( SELF_GOCOLD( pArea ) == FAILURE ) - return FAILURE; - - /* If we have a codeblock for the expression, use it */ - if( pOrderInfo->itmCobExpr ) - pExpr = pOrderInfo->itmCobExpr; - else /* Otherwise, try compiling the key expression string */ + pError = NULL; + /* Try read */ + do { - if( SELF_COMPILE( pArea, ( BYTE * ) pOrderInfo->abExpr->item.asString.value ) == FAILURE ) - return FAILURE; - pExpr = pArea->valResult; - pArea->valResult = NULL; - } - - /* Save for later use */ - pKeyExp = hb_itemNew( NULL ); - hb_itemCopy( pKeyExp, pExpr ); - - /* Get a blank record before testing expression */ - SELF_GOBOTTOM( pArea ); - SELF_SKIP( pArea, 1 ); - pExpMacro = pForMacro = NULL; - if( hb_itemType( pExpr ) == HB_IT_BLOCK ) - { - if( SELF_EVALBLOCK( pArea, pExpr ) == FAILURE ) + hb_fsSeek( pArea->hDataFile, 0, FS_SET ); + if( hb_fsRead( pArea->hDataFile, ( BYTE * ) &dbHeader, sizeof( DBFHEADER ) ) != + sizeof( DBFHEADER ) || ( dbHeader.bVersion != 0x03 && dbHeader.bVersion != 0xF5 ) ) { - hb_itemRelease( pKeyExp ); - return FAILURE; - } - pResult = pArea->valResult; - pArea->valResult = NULL; - } - else - { - pExpMacro = ( HB_MACRO_PTR ) hb_itemGetPtr( pExpr ); - hb_macroRun( pExpMacro ); - pResult = pExpr; - hb_itemCopy( pResult, &hb_stack.Return ); - } - - uiType = hb_itemType( pResult ); - uiLen = 0; - - switch( uiType ) - { - case HB_IT_INTEGER: - case HB_IT_LONG: - case HB_IT_DOUBLE: - bType = 'N'; - uiLen = 10; - break; - - case HB_IT_DATE: - bType = 'D'; - uiLen = 8; - break; - - case HB_IT_LOGICAL: - bType = 'C'; - uiLen = 1; - break; - - case HB_IT_STRING: - bType = 'C'; - uiLen = pResult->item.asString.length > CDX_MAX_KEY ? CDX_MAX_KEY : - pResult->item.asString.length; - break; - - 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( pArea, pError ); - hb_errRelease( pError ); - if( pExpMacro != NULL ) - hb_macroDelete( pExpMacro ); - return FAILURE; - } - - /* Check conditional expression */ - pExpr = pForExp = NULL; - if( pArea->lpdbOrdCondInfo ) - { - /* If we have a codeblock for the conditional expression, use it */ - if( pArea->lpdbOrdCondInfo->itmCobFor ) - pExpr = pArea->lpdbOrdCondInfo->itmCobFor; - else /* Otherwise, try compiling the conditional expression string */ - { - if( SELF_COMPILE( pArea, pArea->lpdbOrdCondInfo->abFor ) == FAILURE ) + bError = TRUE; + if( !pError ) { - hb_itemRelease( pKeyExp ); - if( pExpMacro != NULL ) - hb_macroDelete( pExpMacro ); - return FAILURE; + 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 ); } - pExpr = pArea->valResult; - pArea->valResult = NULL; - } - /* Save for later use */ - pForExp = hb_itemNew( NULL ); - hb_itemCopy( pForExp, pExpr ); - } - - /* Test conditional expression */ - if( pExpr ) - { - if( hb_itemType( pExpr ) == HB_IT_BLOCK ) - { - if( SELF_EVALBLOCK( pArea, pExpr ) == FAILURE ) - { - hb_itemRelease( pKeyExp ); - hb_itemRelease( pForExp ); - if( pExpMacro != NULL ) - hb_macroDelete( pExpMacro ); - return FAILURE; - } - pResult = pArea->valResult; + bRetry = ( SELF_ERROR( ( AREAP ) pArea, pError ) == E_RETRY ); } else - { - pForMacro = ( HB_MACRO_PTR ) hb_itemGetPtr( pExpr ); - hb_macroRun( pForMacro ); - pResult = pExpr; - hb_itemCopy( pResult, &hb_stack.Return ); - } - uiType = hb_itemType( pResult ); - hb_itemRelease( pResult ); - if( uiType != HB_IT_LOGICAL ) - { - hb_itemRelease( pKeyExp ); - hb_itemRelease( pForExp ); - if( pExpMacro != NULL ) - hb_macroDelete( pExpMacro ); - if( pForMacro != NULL ) - hb_macroDelete( pForMacro ); - return FAILURE; - } - } + bRetry = bError = FALSE; + } while( bRetry ); - /* Check file name */ - szFileName = ( char * ) hb_xgrab( _POSIX_PATH_MAX + 3 ); - szFileName[ 0 ] = '\0'; - if( strlen( ( char * ) pOrderInfo->abBagName ) == 0 ) - { - pFileName = hb_fsFNameSplit( pArea->lpDataInfo->szFileName ); - if( pFileName->szDrive ) - strcat( szFileName, pFileName->szDrive ); - if( pFileName->szPath ) - strcat( szFileName, pFileName->szPath ); - strcat( szFileName, pFileName->szName ); - pExtInfo.itmResult = hb_itemPutC( NULL, "" ); - SELF_ORDINFO( pArea, DBOI_BAGEXT, &pExtInfo ); - strcat( szFileName, pExtInfo.itmResult->item.asString.value ); - hb_itemRelease( pExtInfo.itmResult ); - } - else - { - strcpy( szFileName, ( char * ) pOrderInfo->abBagName ); - pFileName = hb_fsFNameSplit( szFileName ); - if( !pFileName->szExtension ) - { - pExtInfo.itmResult = hb_itemPutC( NULL, "" ); - SELF_ORDINFO( pArea, DBOI_BAGEXT, &pExtInfo ); - strcat( szFileName, pExtInfo.itmResult->item.asString.value ); - hb_itemRelease( pExtInfo.itmResult ); - } - } - szTagName = ( char * ) hb_xgrab( CDX_MAX_TAG_NAME_LEN + 1 ); - hb_strncpyUpper( szTagName, pFileName->szName, CDX_MAX_TAG_NAME_LEN ); - hb_xfree( pFileName ); + if( pError ) + hb_errRelease( pError ); - /* Close all index */ - cdxOrderListClear( pArea ); - - pIndex = hb_cdxIndexNew( pArea ); - pArea->lpIndexInfo = pIndex; - - /* New file? */ - if( !hb_fsFile( ( BYTE * ) szFileName ) ) - { - pIndex->DiskFile = hb_fsCreate( ( BYTE * ) szFileName, FC_NORMAL ); - bNewFile = TRUE; - } - else - { - pIndex->DiskFile = hb_fsOpen( ( BYTE * ) szFileName, FO_READWRITE | - ( pArea->lpExtendInfo->fExclusive ? - FO_EXCLUSIVE : FO_DENYNONE ) ); - bNewFile = FALSE; - } - - if( pIndex->DiskFile == FS_ERROR ) - { - cdxOrderListClear( pArea ); - hb_xfree( szFileName ); - hb_xfree( szTagName ); - hb_itemRelease( pKeyExp ); - if( pForExp != NULL ) - hb_itemRelease( pForExp ); - if( pExpMacro != NULL ) - hb_macroDelete( pExpMacro ); - if( pForMacro != NULL ) - hb_macroDelete( pForMacro ); - return FAILURE; - } - - /* Corrupted? */ - if( !bNewFile ) - { - bNewFile = ( hb_fsSeek( pIndex->DiskFile, 0, FS_END ) <= CDX_BLOCK_SIZE ); - hb_fsSeek( pIndex->DiskFile, 0, FS_SET ); - } - - if( bNewFile ) - { - pIndex->NextAvail = 0; - pIndex->CompoundTag = hb_cdxTagNew( pIndex, szTagName, -1 ); - pIndex->CompoundTag->OptFlags = 0xE0; - hb_cdxTagIndexTagNew( pIndex->CompoundTag, NULL, NULL, 'C', 10, NULL, NULL, - TRUE, FALSE ); - hb_cdxTagTagOpen( pIndex->CompoundTag, 0 ); - } - else - { - pIndex->CompoundTag = hb_cdxTagNew( pIndex, szTagName, 0 ); - pIndex->CompoundTag->OptFlags = 0xE0; - hb_cdxIndexResetAvailPage( pIndex ); - hb_cdxTagTagOpen( pIndex->CompoundTag, 0 ); - while( !pIndex->CompoundTag->TagEOF ) - { - pTag = hb_cdxTagNew( pIndex, - pIndex->CompoundTag->CurKeyInfo->pItem->item.asString.value, - pIndex->CompoundTag->CurKeyInfo->Tag ); - if( pIndex->TagList == NULL ) - pIndex->TagList = pTag; - else - { - pLastTag = pIndex->TagList; - while( pLastTag->pNext ) - pLastTag = pLastTag->pNext; - pLastTag->pNext = pTag; - } - hb_cdxTagKeyRead( pIndex->CompoundTag, NEXT_RECORD ); - } - } - - /* Update DBF header */ - if( !pArea->lpExtendInfo->fHasMDX ) - { - pFileName = hb_fsFNameSplit( pArea->lpDataInfo->szFileName ); - hb_strncpyUpper( szFileName, pFileName->szName, CDX_MAX_TAG_NAME_LEN ); - hb_xfree( pFileName ); - if( strcmp( szFileName, szTagName ) == 0 && hb_fsRead( pArea->lpDataInfo->hFile, - ( BYTE * ) &pHeader, sizeof( DBFHEADER ) ) == sizeof( DBFHEADER ) ) - { - pHeader.bHasMDX = 1; - hb_fsWrite( pArea->lpDataInfo->hFile, ( BYTE * ) &pHeader, sizeof( DBFHEADER ) ); - } - } - - hb_xfree( szFileName ); - - hb_strncpyUpper( szTagName, ( const char * ) pOrderInfo->atomBagName, CDX_MAX_TAG_NAME_LEN ); - 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 ); - - /* Clear pArea->lpdbOrdCondInfo */ - SELF_ORDSETCOND( pArea, NULL ); - return SELF_GOTOP( pArea ); -} - -static ERRCODE cdxOrderDestroy( AREAP pArea, LPDBORDERINFO pOrderInfo ) -{ - HB_TRACE(HB_TR_DEBUG, ("cdxOrderDestroy(%p, %p)", pArea, pOrderInfo)); - - HB_SYMBOL_UNUSED( pArea ); - HB_SYMBOL_UNUSED( pOrderInfo ); - - return SUCCESS; -} - -static ERRCODE cdxOrderInfo( AREAP pArea, USHORT uiIndex, LPDBORDERINFO pInfo ) -{ - HB_TRACE(HB_TR_DEBUG, ("cdxOrderInfo(%p, %hu, %p)", pArea, uiIndex, pInfo)); - - HB_SYMBOL_UNUSED( pArea ); - - switch( uiIndex ) - { - case DBOI_BAGEXT: - hb_itemPutC( pInfo->itmResult, ".cdx" ); - break; - } - return SUCCESS; -} - -static ERRCODE cdxOrderListAdd( AREAP pArea, LPDBORDERINFO pOrderInfo ) -{ - HB_TRACE(HB_TR_DEBUG, ("cdxOrderListAdd(%p, %p)", pArea, pOrderInfo)); - - HB_SYMBOL_UNUSED( pArea ); - HB_SYMBOL_UNUSED( pOrderInfo ); - - return SUCCESS; -} - -static ERRCODE cdxOrderListClear( AREAP pArea ) -{ - LPINDEXINFO pIndex; - - HB_TRACE(HB_TR_DEBUG, ("cdxOrderListClear(%p)", pArea)); - - while( pArea->lpIndexInfo ) - { - pIndex = pArea->lpIndexInfo; - pArea->lpIndexInfo = pArea->lpIndexInfo->pNext; - hb_cdxIndexFree( pIndex ); - } - pArea->lpIndexInfo = NULL; - return SUCCESS; -} - -static ERRCODE cdxOrderListFocus( AREAP pArea, LPDBORDERINFO pOrderInfo ) -{ - HB_TRACE(HB_TR_DEBUG, ("cdxOrderListFocus(%p, %p)", pArea, pOrderInfo)); - - HB_SYMBOL_UNUSED( pArea ); - HB_SYMBOL_UNUSED( pOrderInfo ); - - return SUCCESS; -} - -static ERRCODE cdxOrderListRebuild( AREAP pArea ) -{ - HB_TRACE(HB_TR_DEBUG, ("cdxOrderListRebuild(%p)", pArea)); - - HB_SYMBOL_UNUSED( pArea ); - - return SUCCESS; -} - -static ERRCODE cdxPutValueFile( AREAP pArea, USHORT uiIndex, void * pFile ) -{ - LPFIELD pField; - BYTE * szText, szEndChar; - ULONG lMemoBlock; - - HB_TRACE(HB_TR_DEBUG, ("cdxPutValueFile(%p, %hu, %p)", pArea, uiIndex, pFile)); - HB_SYMBOL_UNUSED( pFile ); - - if( uiIndex > pArea->uiFieldCount ) + /* Read error? */ + if( bError ) return FAILURE; - pField = pArea->lpFields + uiIndex - 1;; - szText = pArea->lpExtendInfo->bRecord + pField->uiOffset; - szEndChar = * ( szText + pField->uiLen ); - * ( szText + pField->uiLen ) = 0; - lMemoBlock = atol( ( char * ) szText ) * MEMO_BLOCK; - * ( szText + pField->uiLen ) = szEndChar; - if( lMemoBlock > 0 ) - hb_cdxReadMemo( pArea, ( LPDBFMEMO ) pField->memo, lMemoBlock ); - else if( ( ( LPDBFMEMO ) pField->memo )->pData ) - { - hb_xfree( ( ( LPDBFMEMO ) pField->memo )->pData ); - memset( pField->memo, 0, sizeof( DBFMEMO ) ); - } + 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; } -static ERRCODE cdxSeek( AREAP pArea, BOOL bSoftSeek, PHB_ITEM pKey, BOOL bFindLast ) +/* + * Write the database file header record in the WorkArea. + */ +ERRCODE hb_cdxWriteDBHeader( CDXAREAP pArea ) { - HB_TRACE(HB_TR_DEBUG, ("cdxSeek(%p, %d, %p, %d)", pArea, bSoftSeek, pKey, bFindLast)); + DBFHEADER dbfHeader; + ULONG ulRecCount; + long lYear, lMonth, lDay; - HB_SYMBOL_UNUSED( pArea ); - HB_SYMBOL_UNUSED( bSoftSeek ); - HB_SYMBOL_UNUSED( pKey ); - HB_SYMBOL_UNUSED( bFindLast ); + HB_TRACE(HB_TR_DEBUG, ("hb_cdxWriteDBHeader(%p)", pArea)); + memset( &dbfHeader, 0, sizeof( DBFHEADER ) ); + dbfHeader.bVersion = 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; } -static ERRCODE cdxWriteDBHeader( AREAP pArea ) -{ - DBFHEADER pHeader; - DBFFIELD pDBField; - USHORT uiCount; - LPFIELD pField; - time_t t; - struct tm * pTime; - HB_TRACE(HB_TR_DEBUG, ("cdxWriteDBHeader(%p)", pArea)); - memset( &pHeader, 0, sizeof( DBFHEADER ) ); - pHeader.uiRecordLen = 1; - pHeader.bVersion = 0x03; - pField = pArea->lpFields; - for( uiCount = 0; uiCount < pArea->uiFieldCount; uiCount++ ) - { - switch( pField->uiType ) - { - case 'C': - case 'N': - pHeader.uiRecordLen += pField->uiLen; - break; - case 'M': - pHeader.uiRecordLen += 10; - pHeader.bVersion = 0xF5; - pArea->lpExtendInfo->fHasMemo = TRUE; - break; - - case 'D': - pHeader.uiRecordLen += 8; - break; - - case 'L': - pHeader.uiRecordLen += 1; - break; - } - pField++; - } - - time( &t ); - pTime = localtime( &t ); - pHeader.bYear = ( BYTE ) pTime->tm_year; - pHeader.bMonth = ( BYTE ) pTime->tm_mon + 1; - pHeader.bDay = ( BYTE ) pTime->tm_mday; - pHeader.uiHeaderLen = ( USHORT ) ( 32 * ( pArea->uiFieldCount + 1 ) + 1 ); - pHeader.ulRecords = 0; - pHeader.bHasMDX = pArea->lpExtendInfo->fHasMDX; - if( hb_fsWrite( pArea->lpDataInfo->hFile, ( BYTE * ) &pHeader, - sizeof( DBFHEADER ) ) != sizeof( DBFHEADER ) ) - return FAILURE; - - pField = pArea->lpFields; - for( uiCount = 0; uiCount < pArea->uiFieldCount; uiCount++ ) - { - memset( &pDBField, 0, sizeof( DBFFIELD ) ); - strncpy( ( char * ) pDBField.bName, ( ( PHB_DYNS ) pField->sym )->pSymbol->szName, - sizeof( pDBField.bName ) ); - pDBField.bType = pField->uiType; - switch( pDBField.bType ) - { - case 'C': - pDBField.bLen = pField->uiLen & 0xFF; - pDBField.bDec = pField->uiLen >> 8; - break; - - case 'M': - pDBField.bLen = 10; - pDBField.bDec = 0; - break; - - case 'D': - pDBField.bLen = 8; - pDBField.bDec = 0; - break; - - case 'L': - pDBField.bLen = 1; - pDBField.bDec = 0; - break; - - case 'N': - pDBField.bLen = pField->uiLen; - pDBField.bDec = pField->uiDec; - break; - } - if( hb_fsWrite( pArea->lpDataInfo->hFile, ( BYTE * ) &pDBField, - sizeof( DBFFIELD ) ) != sizeof( DBFFIELD ) ) - return FAILURE; - pField++; - } - if( hb_fsWrite( pArea->lpDataInfo->hFile, ( BYTE * ) "\15\32", 2 ) != 2 ) - return FAILURE; - return SUCCESS; -} - -static RDDFUNCS cdxTable = { cdxBof, - cdxEof, - cdxFound, - cdxGoBottom, - cdxGoTo, - cdxGoToId, - cdxGoTop, - cdxSeek, - cdxSkip, - cdxSkipFilter, - cdxSkipRaw, - cdxAddField, - cdxAppend, - cdxCreateFields, - cdxDeleteRec, - cdxDeleted, - cdxFieldCount, - cdxFieldDisplay, - cdxFieldInfo, - cdxFieldName, - cdxFlush, - cdxGetRec, - cdxGetValue, - cdxGetVarLen, - cdxGoCold, - cdxGoHot, - cdxPutRec, - cdxPutValue, - cdxRecAll, - cdxRecCount, - cdxRecInfo, - cdxRecNo, - cdxSetFieldsExtent, - cdxAlias, - cdxClose, - cdxCreate, - cdxInfo, - cdxNewArea, - cdxOpen, - cdxRelease, - cdxStructSize, - cdxSysName, - cdxEval, - cdxPack, - cdxZap, - cdxchildEnd, - cdxchildStart, - cdxchildSync, - cdxsyncChildren, - cdxclearRel, - cdxforceRel, - cdxrelArea, - cdxrelEval, - cdxrelText, - cdxsetRel, - cdxOrderListAdd, - cdxOrderListClear, - cdxOrderListFocus, - cdxOrderListRebuild, - cdxOrderCondition, - cdxOrderCreate, - cdxOrderDestroy, - cdxOrderInfo, - cdxClearFilter, - cdxClearLocate, - NULL, - NULL, - cdxFilterText, - NULL, - cdxSetFilter, - cdxSetLocate, - NULL, - NULL, - cdxCompile, - cdxError, - cdxEvalBlock, - cdxRawLock, - cdxLock, - cdxUnLock, - cdxCloseMemFile, - cdxCreateMemFile, - cdxGetValueFile, - cdxOpenMemFile, - cdxPutValueFile, - cdxReadDBHeader, - cdxWriteDBHeader, - cdxWhoCares - }; HB_FUNC( _DBFCDX ) { @@ -3335,9 +982,11 @@ HB_FUNC( DBFCDX_GETFUNCTABLE ) 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 ); -} - +} \ No newline at end of file diff --git a/harbour/source/rdd/hbdbsort.c b/harbour/source/rdd/hbdbsort.c index 9079df1f1c..8c22a25904 100644 --- a/harbour/source/rdd/hbdbsort.c +++ b/harbour/source/rdd/hbdbsort.c @@ -136,8 +136,8 @@ static BOOL hb_dbQSortIsLess( LPDBQUICKSORT pQuickSort, ULONG ulRecNo1, ULONG ul /* Compare buffers */ if( bIgnoreCase ) - iResult = stricmp( ( const char * ) pQuickSort->pCmpBufferA, - ( const char * ) pQuickSort->pCmpBufferB ); + iResult = hb_stricmp( ( const char * ) pQuickSort->pCmpBufferA, + ( const char * ) pQuickSort->pCmpBufferB ); else iResult = strcmp( ( const char * ) pQuickSort->pCmpBufferA, ( const char * ) pQuickSort->pCmpBufferB ); diff --git a/harbour/source/rdd/rddsys.prg b/harbour/source/rdd/rddsys.prg index 5d41a37b33..fb5a066537 100644 --- a/harbour/source/rdd/rddsys.prg +++ b/harbour/source/rdd/rddsys.prg @@ -39,13 +39,13 @@ ANNOUNCE RDDSYS init procedure RddInit - REQUEST DBFNTX + REQUEST DBFCDX /* NOTE: Using this internal version of this functions, since at this - point the DBFNTX RDD may not be registered, depending on the + point the DBFCDX RDD may not be registered, depending on the execution order of INIT procedures. */ - __rddSetDefault( "DBFNTX" ) + __rddSetDefault( "DBFCDX" ) return diff --git a/harbour/source/rdd/workarea.c b/harbour/source/rdd/workarea.c index 0d5e5094cc..c235e78383 100644 --- a/harbour/source/rdd/workarea.c +++ b/harbour/source/rdd/workarea.c @@ -688,6 +688,7 @@ ERRCODE hb_waRelText( AREAP pArea, USHORT uiRelNo, void * pExpr ) { HB_TRACE(HB_TR_DEBUG, ("hb_waRelText(%p, %hu, %p)", pArea, uiRelNo, pExpr)); HB_SYMBOL_UNUSED( pArea ); + HB_SYMBOL_UNUSED( uiRelNo ); HB_SYMBOL_UNUSED( pExpr ); printf( "\nTODO: hb_waRelText()\n" ); diff --git a/harbour/tests/newrdd.prg b/harbour/tests/newrdd.prg index ca7e4eeea9..d9e952cd88 100644 --- a/harbour/tests/newrdd.prg +++ b/harbour/tests/newrdd.prg @@ -1,3 +1,7 @@ +// +// $Id$ +// + function Main() local nI, aArray diff --git a/harbour/tests/testcdx.prg b/harbour/tests/testcdx.prg index 8a8574c9dc..278899bb74 100644 --- a/harbour/tests/testcdx.prg +++ b/harbour/tests/testcdx.prg @@ -8,18 +8,38 @@ function Main() { "NUMERIC", "N", 8, 0 }, ; { "DOUBLE", "N", 8, 2 }, ; { "DATE", "D", 8, 0 }, ; + { "MEMO", "M", 10, 0 }, ; { "LOGICAL", "L", 1, 0 } } - REQUEST DBFCDX + CLS + dbUseArea( .T., "DBFCDX", "test", "TESTDBF", .T., .F. ) + dbCreate( "testcdx", aStruct, "DBFCDX", .T., "TESTCDX" ) - rddSetDefault( "DBFCDX" ) + ? "RddName:", RddName() + ? "Press any key to continue..." + InKey( 0 ) + Select( "TESTDBF" ) + SET FILTER TO TESTDBF->SALARY > 140000 + TESTDBF->( dbGoTop() ) + while !TESTDBF->( Eof() ) + TESTCDX->( dbAppend() ) + TESTCDX->NUMERIC = TESTDBF->SALARY + TESTCDX->MEMO := TESTDBF->FIRST + Chr( 13 ) + Chr( 10 ) + ; + TESTDBF->LAST + Chr( 13 ) + Chr( 10 ) + ; + TESTDBF->STREET + TESTDBF->( dbSkip() ) + end - FErase( "testcdx.cdx" ) - dbCreate( "testcdx", aStruct, "DBFCDX" ) - dbUseArea( ,, "testcdx", "MYALIAS" ) - ordCreate( "testcdx", "1Tag ", "FIELD->Character", { || FIELD->Character }, .F. ) - ordCreate( "testcdx", "2Tag ", "FIELD->Character", { || FIELD->Character }, .F. ) - ? MYALIAS->CHARACTER + ? TESTCDX->( RecCount() ) + TESTCDX->( dbGoTop() ) + ? TESTCDX->( Eof() ) + while !TESTCDX->( Eof() ) + ? TESTCDX->( RecNo() ), TESTCDX->NUMERIC + ? TESTCDX->MEMO + TESTCDX->( dbSkip() ) + ? "Press any key to continue..." + InKey( 0 ) + end -return nil +return nil \ No newline at end of file