diff --git a/harbour/ChangeLog b/harbour/ChangeLog index a9a9697c91..100cfded4b 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -8,6 +8,48 @@ 2002-12-01 23:12 UTC+0100 Foo Bar */ +2003-11-05 22:50 UTC+0300 Alexander Kresin + * config/global.cf + * include/hbapirdd.h + * include/hbapi.h + * include/hbapifs.h + * include/hbdefs.h + * include/hbrddcdx.h + * include/hbrddntx.h + * include/hbrdddbf.h + * include/hbrdddel.h + * include/hbrddsdf.h + + include/hbdbferr.h + + include/hbrdddbt.h + + include/hbrddfpt.h + + * source/rtl/filesys.c + * source/rtl/spfiles.c + * source/rtl/filehb.c + + * source/rdd/dbcmd.c + * source/rdd/dbf1.c + * source/rdd/delim1.c + * source/rdd/rddsys.prg + * source/rdd/sdf1.c + * source/rdd/workarea.c + + * source/rdd/dbfcdx/dbfcdx0.prg + * source/rdd/dbfcdx/dbfcdx1.c + * source/rdd/dbfcdx/dbfcdx1.h + - source/rdd/dbfcdx/dbfcdx2.h + + * source/rdd/dbfntx/dbfntx1.c + + + source/rdd/dbfdbt/ + + source/rdd/dbfdbt/dbfdbt0.prg + + source/rdd/dbfdbt/dbfdbt1.c + + + source/rdd/dbffpt/ + + source/rdd/dbffpt/dbffpt0.prg + + source/rdd/dbffpt/dbffpt1.c + * Latest RDD changes, has been made by Przemyslaw Czerpak - synced with xHarbour. + 2003-10-30 19:50 UTC+0100 Ryszard Glab * source/compiler/harbour.l * source/compiler/harbour.y diff --git a/harbour/config/global.cf b/harbour/config/global.cf index bb877b6b8c..cd7e2c3d1b 100644 --- a/harbour/config/global.cf +++ b/harbour/config/global.cf @@ -9,6 +9,8 @@ HB_DB_DRIVERS=\ nulsys \ dbfntx \ dbfcdx \ + dbffpt \ + dbfdbt \ ifeq ($(HB_BIN_COMPILE),) HB_BIN_COMPILE := $(TOP)$(ROOT)source/compiler/$(ARCH) diff --git a/harbour/include/hbapi.h b/harbour/include/hbapi.h index ac921aa219..51f0ba95e2 100644 --- a/harbour/include/hbapi.h +++ b/harbour/include/hbapi.h @@ -73,6 +73,7 @@ extern "C" { #define HB_IT_LONG ( ( USHORT ) 0x0008 ) #define HB_IT_DOUBLE ( ( USHORT ) 0x0010 ) #define HB_IT_DATE ( ( USHORT ) 0x0020 ) +#define HB_IT_LONGLONG ( ( USHORT ) 0x0040 ) #define HB_IT_LOGICAL ( ( USHORT ) 0x0080 ) #define HB_IT_SYMBOL ( ( USHORT ) 0x0100 ) #define HB_IT_ALIAS ( ( USHORT ) 0x0200 ) @@ -85,6 +86,7 @@ extern "C" { #define HB_IT_ARRAY ( ( USHORT ) 0x8000 ) #define HB_IT_OBJECT HB_IT_ARRAY #define HB_IT_NUMERIC ( ( USHORT ) ( HB_IT_INTEGER | HB_IT_LONG | HB_IT_DOUBLE ) ) +#define HB_IS_NUMBER( p ) ( ( p )->type & HB_IT_NUMERIC ) #define HB_IT_ANY ( ( USHORT ) 0xFFFF ) #define HB_IS_OF_TYPE( p, t ) ( ( ( p )->type & ~HB_IT_BYREF ) == t ) diff --git a/harbour/include/hbapifs.h b/harbour/include/hbapifs.h index 159b2decb6..931df4a278 100644 --- a/harbour/include/hbapifs.h +++ b/harbour/include/hbapifs.h @@ -69,6 +69,12 @@ typedef int FHANDLE; /* File locking flags */ #define FL_LOCK 0x0000 /* Lock a region */ #define FL_UNLOCK 0x0001 /* Unlock a region */ +#define FL_MASK 0x00FF /* Mask for lock type */ + +/* Extended file locking flags */ +#define FLX_EXCLUSIVE 0x0000 /* Exclusive lock */ +#define FLX_SHARED 0x0100 /* Shared lock */ +#define FLX_WAIT 0x0200 /* Wait for lock until success */ /* File inheritance flags */ #define FO_INHERITED 0x0000 /* Spawned processes can inherit this file handle */ @@ -160,7 +166,7 @@ typedef struct _HB_PATHNAMES extern void hb_fsAddSearchPath( char * szPath, HB_PATHNAMES * * pSearchList ); -extern BOOL hb_spFile( BYTE * pFilename ); +extern BOOL hb_spFile( BYTE * pFilename, BYTE RetPath[ _POSIX_PATH_MAX + 3 + 10 ] ); extern FHANDLE hb_spOpen( BYTE * pFilename, USHORT uiFlags ); extern FHANDLE hb_spCreate( BYTE * pFilename, USHORT uiAttr ); extern FHANDLE hb_spCreateEx( BYTE * pFilename, USHORT uiAttr, USHORT uiFlags ); diff --git a/harbour/include/hbapirdd.h b/harbour/include/hbapirdd.h index 4fc10a426b..5f17bfaf68 100644 --- a/harbour/include/hbapirdd.h +++ b/harbour/include/hbapirdd.h @@ -68,6 +68,7 @@ extern "C" { /* RDD virtual machine integration functions */ extern USHORT hb_rddInsertAreaNode( char *szDriver ); +extern USHORT hb_rddGetCurrentFieldPos( char * szName ); extern int hb_rddGetCurrentWorkAreaNumber( void ); void * hb_rddGetCurrentWorkAreaPointer( void ); extern ERRCODE hb_rddSelectWorkAreaAlias( char * szAlias ); @@ -570,146 +571,145 @@ typedef USHORT ( * DBENTRYP_I2 )( PHB_ITEM p1, PHB_ITEM p2); typedef struct _RDDFUNCS { - /* Movement and positioning methods */ - DBENTRYP_BP bof; - DBENTRYP_BP eof; - DBENTRYP_BP found; - DBENTRYP_V goBottom; - DBENTRYP_UL go; - DBENTRYP_I goToId; - DBENTRYP_V goTop; - DBENTRYP_BIB seek; - DBENTRYP_L skip; - DBENTRYP_L skipFilter; - DBENTRYP_L skipRaw; + DBENTRYP_BP bof; /* Determine logical beginning of file. */ + DBENTRYP_BP eof; /* Determine logical end of file. */ + DBENTRYP_BP found; /* Determine outcome of the last search operation. */ + DBENTRYP_V goBottom; /* Position cursor at the last record. */ + DBENTRYP_UL go; /* Position cursor at a specific physical record. */ + DBENTRYP_I goToId; /* Position the cursor to a specific, physical identity. */ + DBENTRYP_V goTop; /* Position cursor at the first record. */ + DBENTRYP_BIB seek; /* */ + DBENTRYP_L skip; /* Reposition cursor relative to current position. */ + DBENTRYP_L skipFilter; /*-Reposition cursor respecting any filter setting. */ + DBENTRYP_L skipRaw; /* Reposition cursor, regardless of filter. */ /* Data management */ - DBENTRYP_VF addField; - DBENTRYP_B append; - DBENTRYP_I createFields; - DBENTRYP_V deleterec; - DBENTRYP_BP deleted; - DBENTRYP_SP fieldCount; - DBENTRYP_VF fieldDisplay; - DBENTRYP_SSI fieldInfo; - DBENTRYP_SVP fieldName; - DBENTRYP_V flush; - DBENTRYP_PP getRec; - DBENTRYP_SI getValue; - DBENTRYP_SVL getVarLen; - DBENTRYP_V goCold; - DBENTRYP_V goHot; - DBENTRYP_P putRec; - DBENTRYP_SI putValue; - DBENTRYP_V recall; - DBENTRYP_ULP reccount; - DBENTRYP_ISI recInfo; - DBENTRYP_I recno; - DBENTRYP_S setFieldExtent; + DBENTRYP_VF addField; /* Add a field to the WorkArea. */ + DBENTRYP_B append; /* Append a record to the WorkArea. */ + DBENTRYP_I createFields; /*-Add all fields defined in an array to the WorkArea. */ + DBENTRYP_V deleterec; /* Delete a record. */ + DBENTRYP_BP deleted; /* Determine deleted status for a record. */ + DBENTRYP_SP fieldCount; /*-Determine the number of fields in the WorkArea. */ + DBENTRYP_VF fieldDisplay; /* */ + DBENTRYP_SSI fieldInfo; /*-Retrieve information about a field. */ + DBENTRYP_SVP fieldName; /*-Determine the name associated with a field number. */ + DBENTRYP_V flush; /* Write data buffer to the data store. */ + DBENTRYP_PP getRec; /* */ + DBENTRYP_SI getValue; /* Obtain the current value of a field. */ + DBENTRYP_SVL getVarLen; /* Obtain the length of a field value. */ + DBENTRYP_V goCold; /* Perform a write of WorkArea memory to the data store. */ + DBENTRYP_V goHot; /* Mark the WorkArea data buffer as hot. */ + DBENTRYP_P putRec; /* Replace the current record. */ + DBENTRYP_SI putValue; /* Assign a value to a field. */ + DBENTRYP_V recall; /* Undelete the current record. */ + DBENTRYP_ULP reccount; /* Obtain number of records in WorkArea. */ + DBENTRYP_ISI recInfo; /* */ + DBENTRYP_I recno; /* Obtain physical row number at current WorkArea cursor position. */ + DBENTRYP_S setFieldExtent; /* Establish the extent of the array of fields for a WorkArea. */ /* WorkArea/Database management */ - DBENTRYP_P alias; - DBENTRYP_V close; - DBENTRYP_VP create; - DBENTRYP_SI info; - DBENTRYP_V newarea; - DBENTRYP_VP open; - DBENTRYP_V release; - DBENTRYP_SP structSize; - DBENTRYP_P sysName; - DBENTRYP_VEI dbEval; - DBENTRYP_V pack; - DBENTRYP_LSP packRec; - DBENTRYP_VS sort; - DBENTRYP_VT trans; - DBENTRYP_VT transRec; - DBENTRYP_V zap; + DBENTRYP_P alias; /*-Obtain the alias of the WorkArea. */ + DBENTRYP_V close; /* Close the table in the WorkArea. */ + DBENTRYP_VP create; /* Create a data store in the specified WorkArea. */ + DBENTRYP_SI info; /* Retrieve information about the current driver (DBI). */ + DBENTRYP_V newarea; /* Clear the WorkArea for use. */ + DBENTRYP_VP open; /* Open a data store in the WorkArea. */ + DBENTRYP_V release; /*-Release all references to a WorkArea. */ + DBENTRYP_SP structSize; /* Retrieve the size of the WorkArea structure. */ + DBENTRYP_P sysName; /* Obtain the name of replaceable database driver (RDD) subsystem. */ + DBENTRYP_VEI dbEval; /*-Evaluate code block for each record in WorkArea. */ + DBENTRYP_V pack; /* Remove records marked for deletion from a database. */ + DBENTRYP_LSP packRec; /* */ + DBENTRYP_VS sort; /* Physically reorder a database. */ + DBENTRYP_VT trans; /* Copy one or more records from one WorkArea to another. */ + DBENTRYP_VT transRec; /* Copy a record to another WorkArea. */ + DBENTRYP_V zap; /* Physically remove all records from data store. */ /* Relational Methods */ - DBENTRYP_VR childEnd; - DBENTRYP_VR childStart; - DBENTRYP_VR childSync; - DBENTRYP_V syncChildren; - DBENTRYP_V clearRel; - DBENTRYP_V forceRel; - DBENTRYP_SVP relArea; - DBENTRYP_VR relEval; - DBENTRYP_SVP relText; - DBENTRYP_VR setRel; + DBENTRYP_VR childEnd; /* Report end of relation. */ + DBENTRYP_VR childStart; /* Report initialization of a relation. */ + DBENTRYP_VR childSync; /* Post a pending relational movement. */ + DBENTRYP_V syncChildren; /*-Force relational movement in child WorkAreas. */ + DBENTRYP_V clearRel; /* Clear all relations in the specified WorkArea. */ + DBENTRYP_V forceRel; /* Force relational seeks in the specified WorkArea. */ + DBENTRYP_SVP relArea; /*-Obtain the workarea number of the specified relation. */ + DBENTRYP_VR relEval; /*-Evaluate a block against the relation in specified WorkArea. */ + DBENTRYP_SVP relText; /*-Obtain the character expression of the specified relation. */ + DBENTRYP_VR setRel; /*-Set a relation in the parent file. */ /* Order Management */ - DBENTRYP_OI orderListAdd; - DBENTRYP_V orderListClear; - DBENTRYP_VP orderListDelete; - DBENTRYP_OI orderListFocus; - DBENTRYP_V orderListRebuild; - DBENTRYP_VOI orderCondition; - DBENTRYP_VOC orderCreate; - DBENTRYP_OI orderDestroy; - DBENTRYP_OII orderInfo; + DBENTRYP_OI orderListAdd; /* */ + DBENTRYP_V orderListClear; /* */ + DBENTRYP_VP orderListDelete; /* */ + DBENTRYP_OI orderListFocus; /* */ + DBENTRYP_V orderListRebuild; /* */ + DBENTRYP_VOI orderCondition; /* */ + DBENTRYP_VOC orderCreate; /* */ + DBENTRYP_OI orderDestroy; /* */ + DBENTRYP_OII orderInfo; /*-Retrieve information about the current order that SELF could not. */ /* Filters and Scope Settings */ - DBENTRYP_V clearFilter; - DBENTRYP_V clearLocate; - DBENTRYP_V clearScope; - DBENTRYP_VPLP countScope; - DBENTRYP_I filterText; - DBENTRYP_SI scopeInfo; - DBENTRYP_VFI setFilter; - DBENTRYP_VLO setLocate; - DBENTRYP_VOS setScope; - DBENTRYP_VPL skipScope; + DBENTRYP_V clearFilter; /*-Clear the active filter expression. */ + DBENTRYP_V clearLocate; /*-Clear the active locate expression. */ + DBENTRYP_V clearScope; /* */ + DBENTRYP_VPLP countScope; /* */ + DBENTRYP_I filterText; /*-Return filter condition of the specified WorkArea. */ + DBENTRYP_SI scopeInfo; /* */ + DBENTRYP_VFI setFilter; /* Set the filter condition for the specified WorkArea. */ + DBENTRYP_VLO setLocate; /*-Set the locate scope for the specified WorkArea. */ + DBENTRYP_VOS setScope; /* */ + DBENTRYP_VPL skipScope; /* */ /* Miscellaneous */ - DBENTRYP_P compile; - DBENTRYP_I error; - DBENTRYP_I evalBlock; + DBENTRYP_P compile; /*-Compile a character expression. */ + DBENTRYP_I error; /*-Raise a runtime error. */ + DBENTRYP_I evalBlock; /*-Evaluate a code block. */ /* Network operations */ - DBENTRYP_VSP rawlock; - DBENTRYP_VL lock; - DBENTRYP_UL unlock; + DBENTRYP_VSP rawlock; /* Perform a lowlevel network lock in the specified WorkArea. */ + DBENTRYP_VL lock; /* Perform a network lock in the specified WorkArea. */ + DBENTRYP_UL unlock; /* Release network locks in the specified WorkArea. */ /* Memofile functions */ - DBENTRYP_V closeMemFile; - DBENTRYP_VP createMemFile; - DBENTRYP_SVPB getValueFile; - DBENTRYP_VP openMemFile; - DBENTRYP_SVP putValueFile; + DBENTRYP_V closeMemFile; /* Close a memo file in the WorkArea. */ + DBENTRYP_VP createMemFile; /* Create a memo file in the WorkArea. */ + DBENTRYP_SVPB getValueFile; /* */ + DBENTRYP_VP openMemFile; /* Open a memo file in the specified WorkArea. */ + DBENTRYP_SVP putValueFile; /* */ /* Database file header handling */ - DBENTRYP_V readDBHeader; - DBENTRYP_V writeDBHeader; + DBENTRYP_V readDBHeader; /* Read the database file header record in the WorkArea. */ + DBENTRYP_V writeDBHeader; /* Write the database file header record in the WorkArea. */ /* non WorkArea functions */ - DBENTRYP_I0 exit; - DBENTRYP_I1 drop; - DBENTRYP_I2 exists; + DBENTRYP_I0 exit; /* */ + DBENTRYP_I1 drop; /* remove table */ + DBENTRYP_I2 exists; /* check if table exist */ /* Special and reserved methods */ - DBENTRYP_SVP whoCares; + DBENTRYP_SVP whoCares; /* */ } RDDFUNCS; diff --git a/harbour/include/hbdbferr.h b/harbour/include/hbdbferr.h new file mode 100644 index 0000000000..a6006b3cf3 --- /dev/null +++ b/harbour/include/hbdbferr.h @@ -0,0 +1,81 @@ +/* + * $Id$ + */ + +/* + * xHarbour Project source code: + * DBF error codes + * + * Copyright 2003 Przemyslaw Czerpak + * www - http://www.xharbour.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/). + * + * As a special exception, the Harbour Project gives permission for + * additional uses of the text contained in its release of Harbour. + * + * The exception is that, if you link the Harbour libraries with other + * files to produce an executable, this does not by itself cause the + * resulting executable to be covered by the GNU General Public License. + * Your use of that executable is in no way restricted on account of + * linking the Harbour library code into it. + * + * This exception does not however invalidate any other reasons why + * the executable file might be covered by the GNU General Public License. + * + * This exception applies only to the code released by the Harbour + * Project under the name Harbour. If you copy code from other + * Harbour Project or Free Software Foundation releases into a copy of + * Harbour, as the General Public License permits, the exception does + * not apply to the code that you add in this way. To avoid misleading + * anyone as to the status of such modified files, you must delete + * this exception notice from them. + * + * If you write modifications of your own for Harbour, it is your choice + * whether to permit this exception to apply to your modifications. + * If you do not wish that, delete this exception notice. + * + */ + +#ifndef HB_DBFERR_H_ +#define HB_DBFERR_H_ + +#if defined(HB_EXTERN_C) +extern "C" { +#endif + +/* DBF 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 +#define EDBF_LOCK 1038 +/* ORDER errors */ +#define EDBF_INVALIDKEY 1026 + + +#if defined(HB_EXTERN_C) +} +#endif + +#endif /* HB_DBFERR_H_ */ diff --git a/harbour/include/hbdefs.h b/harbour/include/hbdefs.h index a260112a20..b38bf4ca91 100644 --- a/harbour/include/hbdefs.h +++ b/harbour/include/hbdefs.h @@ -163,6 +163,210 @@ ( ( ( ULONG ) ( b3 ) ) << 16 ) | \ ( ( ( ULONG ) ( b2 ) ) << 8 ) | \ ( ( ( ULONG ) ( b1 ) ) ) ) +#define HB_SWAP_USHORT( w ) ( ( USHORT ) ( ( ( ( USHORT ) ( w ) & 0xFF00 ) >> 8 ) | \ + ( ( ( USHORT ) ( w ) & 0x00FF ) << 8 ) ) ) +#define HB_SWAP_ULONG( w ) ( ( ULONG ) ( ( ( ( ULONG ) ( w ) & 0x000000FFL ) << 24 ) | \ + ( ( ( ULONG ) ( w ) & 0x0000FF00L ) << 8 ) | \ + ( ( ( ULONG ) ( w ) & 0x00FF0000L ) >> 8 ) | \ + ( ( ( ULONG ) ( w ) & 0xFF000000L ) >> 24 ) ) ) +/* Be careful with double conversion. Some machines can use mixed form + (Little/Big) for BYTE ORDER and WORD ORDER or even completely differ + internal representation */ +#define HB_SWAP_PDOUBLE( p ) ( { \ + union { \ + double d; \ + BYTE buffer[ 8 ]; \ + } u; \ + u.buffer[ 0 ] = ( ( BYTE * ) ( p ) )[ 7 ]; \ + u.buffer[ 1 ] = ( ( BYTE * ) ( p ) )[ 6 ]; \ + u.buffer[ 2 ] = ( ( BYTE * ) ( p ) )[ 5 ]; \ + u.buffer[ 3 ] = ( ( BYTE * ) ( p ) )[ 4 ]; \ + u.buffer[ 4 ] = ( ( BYTE * ) ( p ) )[ 3 ]; \ + u.buffer[ 5 ] = ( ( BYTE * ) ( p ) )[ 2 ]; \ + u.buffer[ 6 ] = ( ( BYTE * ) ( p ) )[ 1 ]; \ + u.buffer[ 7 ] = ( ( BYTE * ) ( p ) )[ 0 ]; \ + u.d; \ + } ) +#define HB_SWAP_DOUBLE( d ) ( { \ + BYTE double_var[ 8 ]; \ + *( double * )double_var = ( double ) ( d ); \ + HB_SWAP_PDOUBLE( double_var ); \ + } ) + +#if defined(HB_PDP_ENDIAN) + #error PDP-Endian support unimplemented. If you have such machine do it yourself. +#elif !defined(HB_BIG_ENDIAN) + /* We use Little-Endian here */ + + #define HB_GET_LE_USHORT( p ) ( *( USHORT * )( p ) ) + #define HB_PUT_LE_USHORT( p, w ) ( *( USHORT * )( p ) = ( USHORT ) ( w ) ) + #define HB_GET_LE_ULONG( p ) ( *( ULONG * )( p ) ) + #define HB_PUT_LE_ULONG( p, l ) ( *( ULONG * )( p ) = ( ULONG ) ( l ) ) + #define HB_GET_LE_DOUBLE( p ) ( *( double * )( p ) ) + #define HB_PUT_LE_DOUBLE( p, d ) ( *( double * )( p ) = ( double ) ( d ) ) + + #define HB_GET_BE_USHORT( p ) HB_SWAP_USHORT( *( USHORT * )( p ) ) + #define HB_PUT_BE_USHORT( p, w ) ( *( USHORT * )( p ) = HB_SWAP_USHORT( w ) ) + #define HB_GET_BE_ULONG( p ) HB_SWAP_ULONG( *( ULONG * )( p ) ) + #define HB_PUT_BE_ULONG( p, l ) ( *( ULONG * )( p ) = HB_SWAP_ULONG( l ) ) + #define HB_GET_BE_DOUBLE( p ) HB_SWAP_PDOUBLE( p ) + #define HB_PUT_BE_DOUBLE( p, d ) ( *( double * )( p ) = HB_SWAP_DOUBLE( d ) ) + + #define HB_USHORT_FROM_LE( w ) ( ( USHORT )( w ) ) + #define HB_ULONG_FROM_LE( l ) ( ( ULONG )( l ) ) + #define HB_USHORT_TO_LE( w ) ( ( USHORT )( w ) ) + #define HB_ULONG_TO_LE( l ) ( ( ULONG )( l ) ) + #define HB_DOUBLE_TO_LE( d ) ( ( double )( d ) ) + + #define HB_PCODE_MKSHORT( p ) ( *( SHORT * )( p ) ) + #define HB_PCODE_MKUSHORT( p ) ( *( USHORT * )( p ) ) + #define HB_PCODE_MKLONG( p ) ( *( LONG * )( p ) ) + #define HB_PCODE_MKULONG( p ) ( *( ULONG * )( p ) ) + #define HB_PCODE_MKDOUBLE( p ) ( *( double * )( p ) ) + + /* the conversion for BIG endian can be used here but for speed reasons + * I decided to write full version to avoid one bytes conversion */ + #define HB_GET_SORTDBL( v, p ) { \ + union { \ + double d; \ + BYTE buffer[ 8 ]; \ + } u; \ + if ( ( ( BYTE * ) ( p ) )[ 0 ] & 0x80 ) { \ + u.buffer[ 0 ] = ( ( BYTE * ) ( p ) )[ 7 ]; \ + u.buffer[ 1 ] = ( ( BYTE * ) ( p ) )[ 6 ]; \ + u.buffer[ 2 ] = ( ( BYTE * ) ( p ) )[ 5 ]; \ + u.buffer[ 3 ] = ( ( BYTE * ) ( p ) )[ 4 ]; \ + u.buffer[ 4 ] = ( ( BYTE * ) ( p ) )[ 3 ]; \ + u.buffer[ 5 ] = ( ( BYTE * ) ( p ) )[ 2 ]; \ + u.buffer[ 6 ] = ( ( BYTE * ) ( p ) )[ 1 ]; \ + u.buffer[ 7 ] = ( ( BYTE * ) ( p ) )[ 0 ] ^ 0x80; \ + } else { \ + u.buffer[ 0 ] = ( ( BYTE * ) ( p ) )[ 7 ] ^ 0xFF; \ + u.buffer[ 1 ] = ( ( BYTE * ) ( p ) )[ 6 ] ^ 0xFF; \ + u.buffer[ 2 ] = ( ( BYTE * ) ( p ) )[ 5 ] ^ 0xFF; \ + u.buffer[ 3 ] = ( ( BYTE * ) ( p ) )[ 4 ] ^ 0xFF; \ + u.buffer[ 4 ] = ( ( BYTE * ) ( p ) )[ 3 ] ^ 0xFF; \ + u.buffer[ 5 ] = ( ( BYTE * ) ( p ) )[ 2 ] ^ 0xFF; \ + u.buffer[ 6 ] = ( ( BYTE * ) ( p ) )[ 1 ] ^ 0xFF; \ + u.buffer[ 7 ] = ( ( BYTE * ) ( p ) )[ 0 ] ^ 0xFF; \ + } \ + v = u.d; \ + } + + #define HB_PUT_SORTDBL( p, v ) { \ + union { \ + double d; \ + BYTE buffer[ 8 ]; \ + } u; \ + u.d = ( double ) ( v ); \ + if ( u.d >= 0.0 ) { \ + ( ( BYTE * ) ( p ) )[ 0 ] = u.buffer[ 7 ] ^ 0x80; \ + ( ( BYTE * ) ( p ) )[ 1 ] = u.buffer[ 6 ]; \ + ( ( BYTE * ) ( p ) )[ 2 ] = u.buffer[ 5 ]; \ + ( ( BYTE * ) ( p ) )[ 3 ] = u.buffer[ 4 ]; \ + ( ( BYTE * ) ( p ) )[ 4 ] = u.buffer[ 3 ]; \ + ( ( BYTE * ) ( p ) )[ 5 ] = u.buffer[ 2 ]; \ + ( ( BYTE * ) ( p ) )[ 6 ] = u.buffer[ 1 ]; \ + ( ( BYTE * ) ( p ) )[ 7 ] = u.buffer[ 0 ]; \ + } else { \ + ( ( BYTE * ) ( p ) )[ 7 ] = u.buffer[ 0 ] ^ 0xFF; \ + ( ( BYTE * ) ( p ) )[ 6 ] = u.buffer[ 1 ] ^ 0xFF; \ + ( ( BYTE * ) ( p ) )[ 5 ] = u.buffer[ 2 ] ^ 0xFF; \ + ( ( BYTE * ) ( p ) )[ 4 ] = u.buffer[ 3 ] ^ 0xFF; \ + ( ( BYTE * ) ( p ) )[ 3 ] = u.buffer[ 4 ] ^ 0xFF; \ + ( ( BYTE * ) ( p ) )[ 2 ] = u.buffer[ 5 ] ^ 0xFF; \ + ( ( BYTE * ) ( p ) )[ 1 ] = u.buffer[ 6 ] ^ 0xFF; \ + ( ( BYTE * ) ( p ) )[ 0 ] = u.buffer[ 7 ] ^ 0xFF; \ + } \ + } +#else + /* We use Big-Endian here */ + + #define HB_GET_LE_USHORT( p ) HB_SWAP_USHORT( *( USHORT * )( p ) ) + #define HB_PUT_LE_USHORT( p, w ) ( *( USHORT * )( p ) = HB_SWAP_USHORT( w ) ) + #define HB_GET_LE_ULONG( p ) HB_SWAP_ULONG( *( ULONG * )( p ) ) + #define HB_PUT_LE_ULONG( p, l ) ( *( ULONG * )( p ) = HB_SWAP_ULONG( l ) ) + #define HB_GET_BE_USHORT( p ) ( *( USHORT * )( p ) ) + #define HB_PUT_BE_USHORT( p, w ) ( *( USHORT * )( p ) = ( USHORT ) ( w ) ) + #define HB_GET_BE_ULONG( p ) ( *( ULONG * )( p ) ) + #define HB_PUT_BE_ULONG( p, l ) ( *( ULONG * )( p ) = ( ULONG ) ( l ) ) + #define HB_GET_BE_DOUBLE( p ) ( *( double * )( p ) ) + #define HB_PUT_BE_DOUBLE( p, d ) ( *( double * )( p ) = ( double ) ( d ) ) + + #define HB_USHORT_FROM_LE( w ) HB_MKUSHORT( HB_HIBYTE( w ), HB_LOBYTE( w ) ) + #define HB_ULONG_FROM_LE( l ) HB_MKULONG( HB_HIBYTE( HB_HIWORD( l ) ), HB_LOBYTE( HB_HIWORD( l ) ), HB_HIBYTE( l ), HB_LOBYTE( l ) ) + #define HB_USHORT_TO_LE( w ) HB_USHORT_FROM_LE( w ) + #define HB_ULONG_TO_LE( l ) HB_ULONG_FROM_LE( l ) + + #define HB_PCODE_MKSHORT( p ) HB_MKSHORT( *( BYTE * )( p ), ( ( BYTE * )( p ) )[ 1 ] ) + #define HB_PCODE_MKUSHORT( p ) HB_MKUSHORT( *( BYTE * )( p ), ( ( BYTE * )( p ) )[ 1 ] ) + #define HB_PCODE_MKLONG( p ) HB_MKLONG( *( BYTE * )( p ), ( ( BYTE * )( p ) )[ 1 ], ( ( BYTE * )( p ) )[ 2 ], ( ( BYTE * )( p ) )[ 3 ] ) + #define HB_PCODE_MKULONG( p ) HB_MKULONG( *( BYTE * )( p ), ( ( BYTE * )( p ) )[ 1 ], ( ( BYTE * )( p ) )[ 2 ], ( ( BYTE * )( p ) )[ 3 ] ) + +#if defined( __GNUC__ ) + #define HB_GET_LE_DOUBLE( p ) HB_SWAP_PDOUBLE( p ) + #define HB_PUT_LE_DOUBLE( p, d ) ( *( double * )( p ) = HB_SWAP_DOUBLE( d ) ) + + #define HB_DOUBLE_FROM_LE( d ) HB_SWAP_DOUBLE( d ); + #define HB_DOUBLE_TO_LE( d ) HB_DOUBLE_FROM_LE( d ) + #define HB_PCODE_MKDOUBLE( p ) HB_SWAP_PDOUBLE( p ) + + #define HB_GET_SORTDBL( v, p ) ( { \ + union { \ + double d; \ + BYTE buffer[ 8 ]; \ + } u; \ + u.d = HB_GET_BE_DOUBLE( p ); \ + if ( u.buffer[ 0 ] & 0x80 ) { \ + u.buffer[ 0 ] ^= 0x80; \ + } else { \ + ( ( LONG * ) ( u.buffer ) )[ 0 ] ^= 0xFFFFFFFFL; \ + ( ( LONG * ) ( u.buffer ) )[ 1 ] ^= 0xFFFFFFFFL; \ + } \ + v = u.d; \ + } ) + + #define HB_PUT_SORTDBL( p, v ) ( { \ + HB_PUT_BE_DOUBLE( p, v ); \ + if ( ( double ) ( v ) >= 0.0 ) { \ + ( ( BYTE * ) ( p ) )[ 0 ] ^= 0x80; \ + } else { \ + ( ( LONG * ) ( p ) )[ 0 ] ^= 0xFFFFFFFFL; \ + ( ( LONG * ) ( p ) )[ 1 ] ^= 0xFFFFFFFFL; \ + } \ + } ) + +/* + #define HB_DOUBLE_FROM_LE( d ) \ + ( { \ + BYTE double_var[ 8 ]; \ + *( double * )double_var = d; \ + HB_PCODE_MKDOUBLE( double_var ); \ + } ) + #define HB_PCODE_MKDOUBLE( p ) \ + ( { \ + union { \ + double d; \ + BYTE buffer[ 8 ]; \ + } u; \ + u.buffer[ 0 ] = ( p )[ 7 ]; \ + u.buffer[ 1 ] = ( p )[ 6 ]; \ + u.buffer[ 2 ] = ( p )[ 5 ]; \ + u.buffer[ 3 ] = ( p )[ 4 ]; \ + u.buffer[ 4 ] = ( p )[ 3 ]; \ + u.buffer[ 5 ] = ( p )[ 2 ]; \ + u.buffer[ 6 ] = ( p )[ 1 ]; \ + u.buffer[ 7 ] = ( p )[ 0 ]; \ + u.d; \ + } ) +*/ +#else + #error Little-Endian IEEE 754 double type conversion unimplemented with a non-GCC compiler +#endif + +#endif + +#define HB_PCODE_MK24BIT( p ) HB_MKLONG( *( BYTE * )( p ), ( ( BYTE * )( p ) )[ 1 ], ( ( BYTE * )( p ) )[ 2 ], 0 ) #define HB_SYMBOL_UNUSED( symbol ) ( void ) symbol diff --git a/harbour/include/hbrddcdx.h b/harbour/include/hbrddcdx.h index 226eedc771..353602cf18 100644 --- a/harbour/include/hbrddcdx.h +++ b/harbour/include/hbrddcdx.h @@ -3,11 +3,11 @@ */ /* - * Harbour Project source code: - * DBFCDX RDD + * DBFCDX RDD (ver.2) * * Copyright 1999 Bruno Cantero - * www - http://www.harbour-project.org + * Copyright 2003 Przemyslaw Czerpak + * www - http://www.xharbour.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 @@ -54,244 +54,276 @@ #define HB_RDDCDX_H_ #include "hbapirdd.h" +#include "hbdbferr.h" +#ifndef HB_CDP_SUPPORT_OFF #include "hbapicdp.h" +#endif #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 -#define EDBF_INVALIDKEY 1026 - - - -/* DBFCDX default extensions */ -#define CDX_MEMOEXT ".fpt" +/* CDX constants and defaults */ #define CDX_INDEXEXT ".cdx" - - - -/* FPT's and CDX's */ - -#define FPT_DEFBLOCKSIZE 64 -#define SIZEOFMEMOFREEBLOCK 6 -#define MAXFREEBLOCKS 82 #define CDX_MAXKEY 240 #define CDX_MAXTAGNAMELEN 10 #define CDX_PAGELEN 512 -#define CDX_RIGHTTYPE 0 -#define CDX_ROOTTYPE 1 -#define CDX_LEAFTYPE 2 -#define CDX_LEAFFREESPACE 488 +#define CDX_INT_FREESPACE 500 +#define CDX_EXT_FREESPACE 488 +#define CDX_DUMMYNODE 0xFFFFFFFFL +#define CDX_LOCKOFFSET 0x7FFFFFFEL +#define CDX_LOCKSIZE 1L +#define CDX_STACKSIZE 64 +#define CDX_PAGECACHESIZE 16 +#define CDX_NODE_BRANCH 0 +#define CDX_NODE_ROOT 1 +#define CDX_NODE_LEAF 2 +#define CDX_NODE_UNUSED 0xFF +#define CDX_IGNORE_REC_NUM 0x0L +#define CDX_MAX_REC_NUM 0xFFFFFFFFL +#define CDX_BALANCE_LEAFPAGES 3 +#define CDX_BALANCE_INTPAGES 3 + +/* +#define CDX_CURKEY_UNDEF 1 +#define CDX_CURKEY_REC 2 +#define CDX_CURKEY_VAL 4 +#define CDX_CURKEY_INPAGE 8 +#define CDX_CURKEY_INSTACK 16 +#define CDX_CURKEY_NOTEXIST 32 +*/ + +#define TOP_RECORD 1 +#define BTTM_RECORD 2 +#define PREV_RECORD 3 +#define NEXT_RECORD 4 +#define PRVU_RECORD 6 +#define NXTU_RECORD 5 + +#define NODE_NEWLASTKEY 1 +#define NODE_SPLIT 2 +#define NODE_JOIN 4 +#define NODE_BALANCE 8 +#define NODE_EAT 16 + +/* +#define CURKEY_UNDEF(pTag) (((pTag)->curKeyState & CDX_CURKEY_UNDEF) != 0) +#define CURKEY_NOTEXIST(pTag) (((pTag)->curKeyState & CDX_CURKEY_NOTEXIST) != 0) +#define CURKEY_ISSET(pTag) (((pTag)->curKeyState & (CDX_CURKEY_NOTEXIST | CDX_CURKEY_UNDEF)) == 0) +#define CURKEY_REC(pTag) ((((pTag)->curKeyState & CDX_CURKEY_REC) != 0) ? (pTag)->curKey->rec : 0) +#define CURKEY_VAL(pTag) ((((pTag)->curKeyState & CDX_CURKEY_VAL) != 0) ? (pTag)->curKey->val : NULL) +#define CURKEY_REFRESH(pTag) +*/ + +#define HB_CDXMAXKEY( x ) ((USHORT) ((x) > CDX_MAXKEY ? CDX_MAXKEY : (x))) +#define HB_CDXBITMASK( x ) ((LONG) ((1L<<(x))-1)) + +//#define FAST_GOCOLD( A ) (((CDXAREAP) (A))->fRecordChanged || ((CDXAREAP) (A))->fCdxAppend ? (SELF_GOCOLD((A))) : SUCCESS) +#define FAST_GOCOLD( A ) SELF_GOCOLD(A) - -struct _CDXAREA; - -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 */ - -struct _CDXINDEX; /* forward declaration */ -typedef struct _CDXTAG -{ - char * szName; /* Name of tag */ - PHB_ITEM pKeyItem; /* item with a macro pcode for a tag key expression */ - PHB_ITEM pForItem; /* item with a macro pcode for a tag for expression */ - char * KeyExpr; /* a tag key expression as text */ - char * ForExpr; /* a tag for expression as text */ - USHORT uiType; /* a type of key expression value */ - USHORT uiLen; /* length of the key expression value */ - USHORT nField; - struct _CDXINDEX * pIndex; /* a parent index info */ - // review this ... - struct _CDXTAG * pNext; - BOOL AscendKey; /* ascending/descending order flag */ - BOOL UniqueKey; /* unique order flag */ - BOOL Temporary; - BOOL Custom; - BOOL TagChanged; - BOOL TagBOF; - BOOL TagEOF; - //BYTE KeyType; - BYTE OptFlags; - LONG TagBlock; /* a page offset where a tag header is stored */ - LONG RootBlock; /* a page offset with the root of keys tree */ - //USHORT KeyLength; - USHORT MaxKeys; - LPCDXKEYINFO CurKeyInfo; /* current value of key expression */ - LPCDXPAGEINFO RootPage; - LPCDXKEYINFO HotKey; /* value of hot key expression */ - PHB_ITEM topScope; - LPCDXKEYINFO topScopeKey; - PHB_ITEM bottomScope; - LPCDXKEYINFO bottomScopeKey; - LPCDXPAGEINFO pagePool; - ULONG ulVersion; -} CDXTAG; -typedef CDXTAG * LPCDXTAG; - -typedef struct _CDXINDEX -{ - char * szFileName; /* Name of index file */ - FHANDLE hFile; /* Index file handle */ - struct _CDXAREA * pArea; /* Parent WorkArea */ - LPCDXTAG pCompound; - LONG NextAvail; - // review this... - LPCDXTAG TagList; - struct _CDXINDEX * pNext; /* The next index in the list */ - /* USHORT uiTag; */ /* current tag focus */ - BOOL fShared; /* Shared file */ - BOOL fReadonly; /* Read only file */ - int lockWrite; - int lockRead; - int changesWritten; - ULONG ulVersion; -} CDXINDEX; -typedef CDXINDEX * LPCDXINDEX; - -#if (__BORLANDC__ > 1040) /* Use this only above Borland C++ 3.1 */ - #pragma option -a1 /* byte alignment */ -#elif defined(__GNUC__) - #pragma pack(1) -#elif defined(__WATCOMC__) - #pragma push(pack, 1); -#elif defined(__cplusplus) - #pragma pack(1) -#endif - -/* ---- -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; ------ */ - -#define CDX_TYPE_UNIQUE 1 /* unique index */ +#define CDX_TYPE_UNIQUE 0x01 /* unique index */ +#define CDX_TYPE_TEMPORARY 0x02 /* temporary index */ +#define CDX_TYPE_CUSTOM 0x04 /* custom index */ #define CDX_TYPE_FORFILTER 0x08 /* for expression present */ #define CDX_TYPE_BITVECTOR 0x10 /* SoftC? */ #define CDX_TYPE_COMPACT 0x20 /* FoxPro */ #define CDX_TYPE_COMPOUND 0x40 /* FoxPro */ #define CDX_TYPE_STRUCTURE 0x80 /* FoxPro */ +/* CDX index node strucutres */ +/* Compact Index Header Record */ typedef struct _CDXTAGHEADER { - LONG lRoot; /* offset of the root node */ - LONG lFreeList; /* offset of list of free pages or -1 */ - LONG lChgFlag; //lLength; /* Version number ? MSDN: pointer to end of file */ - USHORT uiKeySize; /* key length */ - BYTE bType; /* index options see CDX_TYPE_* */ - BYTE bSignature; /* index signature */ - BYTE bReserved1[ 486 ]; - USHORT iDescending; /* 0 = ascending 1 = descending */ - USHORT iFilterPos; /* offset of filter expression */ - USHORT iFilterLen; /* length of filter expression */ - USHORT iExprPos; /* offset of key expression */ - USHORT iExprLen; /* length of key expression */ - BYTE KeyPool[ CDX_PAGELEN ]; + BYTE rootPtr [ 4 ]; /* offset of the root node */ + BYTE freePtr [ 4 ]; /* offset of list of free pages or -1 */ + BYTE reserved1[ 4 ]; /* Version number ??? */ + BYTE keySize [ 2 ]; /* key length */ + BYTE indexOpt; /* index options see CDX_TYPE_* */ + BYTE indexSig; /* index signature */ + BYTE reserved2[ 486 ]; + BYTE ascendFlg[ 2 ]; /* 0 = ascending 1 = descending */ + BYTE forExpPos[ 2 ]; /* offset of filter expression */ + BYTE forExpLen[ 2 ]; /* length of filter expression */ + BYTE keyExpPos[ 2 ]; /* offset of key expression */ + BYTE keyExpLen[ 2 ]; /* length of key expression */ + BYTE keyExpPool[ CDX_PAGELEN ]; } CDXTAGHEADER; typedef CDXTAGHEADER * LPCDXTAGHEADER; -#define CDX_NODE_BRANCH 0 -#define CDX_NODE_ROOT 1 -#define CDX_NODE_LEAF 2 - -typedef struct _CDXLEAFHEADER +/* Compact Index Interior Node Record */ +typedef struct _CDXINTNODE { - USHORT uiNodeType; /* node type see CDX_NODE_* */ - USHORT uiKeyCount; /* number of keys */ - LONG lLeftNode; /* offset of left node or -1 */ - LONG lRightNode; /* offset of right node or -1 */ - USHORT uiFreeSpace; /* free space available in a page */ - ULONG ulRecNumMask; /* record number mask */ - BYTE bDupByteMask; /* duplicate bytes count mask */ - BYTE bTrailByteMask; /* trailing bytes count mask */ - BYTE bRecNumLen; /* number of bits for record number */ - BYTE bDupCntLen; /* number of bits for duplicate count */ - BYTE bTrailCntLen; /* number of bits for trailing count */ - BYTE bInfo; /* total number of bytes for recnn/dup/trail info */ - BYTE bData[ CDX_LEAFFREESPACE ]; -} CDXLEAFHEADER; -typedef CDXLEAFHEADER * LPCDXLEAFHEADER; -#if (__BORLANDC__ > 1040) /* Use this only above Borland C++ 3.1 */ - #pragma option -a /* default alignment */ -#elif defined(__GNUC__) - #pragma pack() -#elif defined(__WATCOMC__) - #pragma pop(pack); -#elif defined(__cplusplus) - #pragma pack() -#endif + BYTE attr [ 2 ]; /* node type see CDX_NODE_* */ + BYTE nKeys [ 2 ]; /* number of keys */ + BYTE leftPtr [ 4 ]; /* offset of left node or -1 */ + BYTE rightPtr[ 4 ]; /* offset of right node or -1 */ + BYTE keyPool [ CDX_INT_FREESPACE ]; +} CDXINTNODE; +typedef CDXINTNODE * LPCDXINTNODE; +typedef CDXINTNODE CDXNODE; +typedef CDXNODE * LPCDXNODE; + +/* Compact Index Exterior Node Record */ +typedef struct _CDXEXTNODE +{ + BYTE attr [ 2 ]; /* node type see CDX_NODE_* */ + BYTE nKeys [ 2 ]; /* number of keys */ + BYTE leftPtr [ 4 ]; /* offset of left node or -1 */ + BYTE rightPtr[ 4 ]; /* offset of right node or -1 */ + BYTE freeSpc [ 2 ]; /* free space available in a page */ + BYTE recMask [ 4 ]; /* record number mask */ + BYTE dupMask; /* duplicate bytes count mask */ + BYTE trlMask; /* trailing bytes count mask */ + BYTE recBits; /* number of bits for record number */ + BYTE dupBits; /* number of bits for duplicate count */ + BYTE trlBits; /* number of bits for trailing count */ + BYTE keyBytes; /* total number of bytes for recnn/dup/trail info */ + BYTE keyPool [ CDX_EXT_FREESPACE ]; /* rec/dup/trl */ +} CDXEXTNODE; +typedef CDXEXTNODE * LPCDXEXTNODE; + + + +/* CDX internal memory structures */ + +struct _CDXAREA; /* forward declaration */ +struct _CDXINDEX; /* forward declaration */ +struct _CDXTAG; /* forward declaration */ + +typedef struct _CDXKEY +{ + BYTE * val; + BYTE len; + ULONG rec; +} CDXKEY; +typedef CDXKEY * LPCDXKEY; + +typedef struct _CDXPAGE +{ + ULONG Page; + ULONG Left; + ULONG Right; + + BYTE PageType; + SHORT iKeys; + SHORT iCurKey; + + BOOL fChanged; + BYTE bUsed; + + ULONG RNMask; + BYTE ReqByte; + BYTE RNBits; + BYTE DCBits; + BYTE TCBits; + BYTE DCMask; + BYTE TCMask; + BOOL fBufChanged; + union + { + CDXEXTNODE extNode; + CDXINTNODE intNode; + } node; + BYTE bufKeyVal[ CDX_MAXKEY ]; /* buffer for leaf key val or added branch key */ + SHORT bufKeyNum; /* do not change these vars' order */ + SHORT bufKeyPos; /* they have to be just after the node */ + SHORT bufKeyLen; /* and maybe temporary overwriten when adding */ + SHORT iFree; /* new key to interior node record. */ + BYTE * pKeyBuf; /* pointer to uncompressed leaf page key pool */ + //SHORT iKeyInBuf; + + struct _CDXPAGE * Owner; + struct _CDXPAGE * Child; + struct _CDXTAG * TagParent; + struct _CDXPAGE * pPoolPrev; + struct _CDXPAGE * pPoolNext; +} CDXPAGE; +typedef CDXPAGE * LPCDXPAGE; + +typedef struct _CDXSTACK +{ + LPCDXPAGE Page; + SHORT iKey; +} CDXSTACK; +typedef CDXSTACK * LPCDXSTACK; + +typedef struct _CDXLIST +{ + ULONG ulAddr; + BOOL fStat; + struct _CDXLIST * pNext; +} CDXLIST; +typedef CDXLIST * LPCDXLIST; + +typedef struct _CDXTAG +{ + char * szName; /* Name of tag */ + char * KeyExpr; /* a tag key expression as text */ + char * ForExpr; /* a tag for expression as text */ + PHB_ITEM pKeyItem; /* item with a macro pcode for a tag key expression */ + PHB_ITEM pForItem; /* item with a macro pcode for a tag for expression */ + USHORT uiType; /* a type of key expression value */ + USHORT uiLen; /* length of the key expression value */ + USHORT nField; /* Field number for simple (one field) key expersion */ + BYTE OptFlags; /* index options flag */ + BOOL AscendKey; /* ascending/descending order flag */ + BOOL UniqueKey; /* unique order flag */ + BOOL Temporary; /* temporary order flag */ + BOOL Custom; /* custom order flag */ + + BOOL UsrAscend; /* user settable ascending/descending order flag */ + BOOL UsrUnique; /* user settable unique order flag */ + + BOOL TagChanged; + BOOL TagBOF; + BOOL TagEOF; + + BOOL fRePos; + BYTE curKeyState; /* see: CDX_CURKEY_* */ + + ULONG TagBlock; /* a page offset where a tag header is stored */ + ULONG RootBlock; /* a page offset with the root of keys tree */ + USHORT MaxKeys; /* maximum number of keys in Interior node */ + + struct _CDXINDEX * pIndex; /* a parent index info */ + struct _CDXTAG * pNext; /* pointer to next tag in index */ + + //CDXSTACK PageStack[ CDX_STACKSIZE ]; /* stack with page path to current key */ + LPCDXPAGE RootPage; /* pointer to root of keys tree in memory */ + LPCDXKEY CurKey; /* current value of key expression */ + LPCDXKEY HotKey; /* value of hot key expression */ + BOOL HotFor; /* index FOR condition for HotKey */ + + PHB_ITEM topScope; /* Top scope HB_ITEM */ + LPCDXKEY topScopeKey; /* Top scope index key */ + PHB_ITEM bottomScope; /* Bottom scope HB_ITEM */ + LPCDXKEY bottomScopeKey; /* Bottom index key */ + + LPCDXPAGE pagePool; /* page buffer in memory */ +} CDXTAG; +typedef CDXTAG * LPCDXTAG; + +typedef struct _CDXINDEX +{ + char * szFileName; /* Name of index file */ + FHANDLE hFile; /* Index file handle */ + struct _CDXAREA * pArea; /* Parent WorkArea */ + struct _CDXINDEX * pNext; /* The next index in the list */ + LPCDXTAG pCompound; /* Compound Tag (index of tags) */ + LPCDXTAG TagList; /* List of tags in index file */ + BOOL fShared; /* Shared file */ + BOOL fReadonly; /* Read only file */ + ULONG nextAvail; /* offset to next free page in the end of index file */ + ULONG freePage; /* offset to next free page inside index file */ + LPCDXLIST freeLst; /* list of free pages in index file */ + int lockWrite; /* number of write lock set */ + int lockRead; /* number of read lock set */ + BOOL fChanged; /* changes written to index, need upadte ulVersion */ + ULONG ulVersion; /* network version/update flag */ +} CDXINDEX; +typedef CDXINDEX * LPCDXINDEX; /* @@ -341,9 +373,12 @@ typedef struct _CDXAREA ULONG ulRecCount; /* Total records */ char * szDataFileName; /* Name of data file */ char * szMemoFileName; /* Name of memo file */ + USHORT uiMemoBlockSize; /* Size of memo block */ + BYTE bMemoType; /* MEMO type used in DBF memo fields */ BOOL fHasMemo; /* WorkArea with Memo fields */ BOOL fHasTags; /* WorkArea with MDX or CDX index */ - BYTE bCodePage; + BYTE bVersion; /* DBF version ID byte */ + BYTE bCodePage; /* DBF codepage ID */ BOOL fShared; /* Shared file */ BOOL fReadonly; /* Read only file */ USHORT * pFieldOffset; /* Pointer to field offset array */ @@ -362,21 +397,21 @@ typedef struct _CDXAREA BYTE bDay; ULONG * pLocksPos; /* List of records locked */ ULONG ulNumLocksPos; /* Number of records locked */ +#ifndef HB_CDP_SUPPORT_OFF PHB_CODEPAGE cdPage; /* Area's codepage pointer */ +#endif /* * CDX's additions to the workarea structure * - * Warning: The above section MUST match WORKAREA exactly! Any + * Warning: The above section MUST match DBFAREA 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 */ - //LPCDXTAG * lpIndexes; /* Pointer to indexes array */ - LPCDXINDEX lpIndexes; /* Pointer to indexes array */ - USHORT uiTag; /* current tag focus */ + BOOL fCdxAppend; /* Appended record changed */ + LPCDXINDEX lpIndexes; /* Pointer to indexes array */ + USHORT uiTag; /* current tag focus */ } CDXAREA; @@ -396,15 +431,14 @@ typedef CDXAREA * LPCDXAREA; #define hb_cdxBof NULL #define hb_cdxEof NULL #define hb_cdxFound NULL -extern ERRCODE hb_cdxGoBottom( CDXAREAP pArea ); -//#define hb_cdxGoTo NULL -extern ERRCODE hb_cdxGoTo( CDXAREAP pArea, ULONG ulRecNo ); +static ERRCODE hb_cdxGoBottom( CDXAREAP pArea ); +#define hb_cdxGoTo NULL #define hb_cdxGoToId NULL -extern ERRCODE hb_cdxGoTop( CDXAREAP pArea ); -extern ERRCODE hb_cdxSeek( CDXAREAP pArea, BOOL bSoftSeek, PHB_ITEM pKey, BOOL bFindLast ); +static ERRCODE hb_cdxGoTop( CDXAREAP pArea ); +static ERRCODE hb_cdxSeek( CDXAREAP pArea, BOOL bSoftSeek, PHB_ITEM pKey, BOOL bFindLast ); #define hb_cdxSkip NULL #define hb_cdxSkipFilter NULL -extern ERRCODE hb_cdxSkipRaw( CDXAREAP pArea, LONG lToSkip ); +static ERRCODE hb_cdxSkipRaw( CDXAREAP pArea, LONG lToSkip ); #define hb_cdxAddField NULL #define hb_cdxAppend NULL #define hb_cdxCreateFields NULL @@ -416,36 +450,33 @@ extern ERRCODE hb_cdxSkipRaw( CDXAREAP pArea, LONG lToSkip ); #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 -extern ERRCODE hb_cdxGoCold( CDXAREAP pArea ); -//#define hb_cdxGoHot NULL -extern ERRCODE hb_cdxGoHot( CDXAREAP pArea ); +#define hb_cdxGetValue NULL +#define hb_cdxGetVarLen NULL +static ERRCODE hb_cdxGoCold( CDXAREAP pArea ); +static ERRCODE hb_cdxGoHot( CDXAREAP pArea ); #define hb_cdxPutRec NULL -extern ERRCODE hb_cdxPutValue( CDXAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ); +#define hb_cdxPutValue NULL #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 ); +static ERRCODE hb_cdxClose( CDXAREAP pArea ); #define hb_cdxCreate NULL -extern ERRCODE hb_cdxInfo( CDXAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ); +#define hb_cdxInfo NULL #define hb_cdxNewArea NULL -extern ERRCODE hb_cdxOpen( CDXAREAP pArea, LPDBOPENINFO pOpenInfo ); +static 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 ); +static ERRCODE hb_cdxStructSize( CDXAREAP pArea, USHORT * uiSize ); +static ERRCODE hb_cdxSysName( CDXAREAP pArea, BYTE * pBuffer ); #define hb_cdxEval NULL -extern ERRCODE hb_cdxPack ( CDXAREAP pArea ); +static ERRCODE hb_cdxPack ( CDXAREAP pArea ); #define hb_cdxPackRec NULL #define hb_cdxSort NULL #define hb_cdxTrans NULL #define hb_cdxTransRec NULL -/* #define hb_cdxZap NULL */ -extern ERRCODE hb_cdxZap ( CDXAREAP pArea ); +static ERRCODE hb_cdxZap ( CDXAREAP pArea ); #define hb_cdxChildEnd NULL #define hb_cdxChildStart NULL #define hb_cdxChildSync NULL @@ -456,26 +487,23 @@ extern ERRCODE hb_cdxZap ( CDXAREAP pArea ); #define hb_cdxRelEval NULL #define hb_cdxRelText NULL #define hb_cdxSetRel NULL -extern ERRCODE hb_cdxOrderListAdd( CDXAREAP pArea, LPDBORDERINFO pOrderInfo ); -extern ERRCODE hb_cdxOrderListClear( CDXAREAP pArea ); +static ERRCODE hb_cdxOrderListAdd( CDXAREAP pArea, LPDBORDERINFO pOrderInfo ); +static ERRCODE hb_cdxOrderListClear( CDXAREAP pArea ); #define hb_cdxOrderListDelete NULL -extern ERRCODE hb_cdxOrderListFocus( CDXAREAP pArea, LPDBORDERINFO pOrderInfo ); +static ERRCODE hb_cdxOrderListFocus( CDXAREAP pArea, LPDBORDERINFO pOrderInfo ); static ERRCODE hb_cdxOrderListRebuild( CDXAREAP pArea ); #define hb_cdxOrderCondition NULL -extern ERRCODE hb_cdxOrderCreate( CDXAREAP pArea, LPDBORDERCREATEINFO pOrderInfo ); -extern ERRCODE hb_cdxOrderDestroy( CDXAREAP pArea, LPDBORDERINFO pOrderInfo ); -extern ERRCODE hb_cdxOrderInfo( CDXAREAP pArea, USHORT uiIndex, LPDBORDERINFO pOrderInfo ); +static ERRCODE hb_cdxOrderCreate( CDXAREAP pArea, LPDBORDERCREATEINFO pOrderInfo ); +static ERRCODE hb_cdxOrderDestroy( CDXAREAP pArea, LPDBORDERINFO pOrderInfo ); +static ERRCODE hb_cdxOrderInfo( CDXAREAP pArea, USHORT uiIndex, LPDBORDERINFO pOrderInfo ); #define hb_cdxClearFilter NULL #define hb_cdxClearLocate NULL -/* #define hb_cdxClearScope NULL */ static ERRCODE hb_cdxClearScope( CDXAREAP pArea ); #define hb_cdxCountScope NULL #define hb_cdxFilterText NULL -/* #define hb_cdxScopeInfo NULL */ static ERRCODE hb_cdxScopeInfo( CDXAREAP pArea, USHORT nScope, PHB_ITEM pItem ); #define hb_cdxSetFilter NULL #define hb_cdxSetLocate NULL -/* #define hb_cdxSetScope NULL */ static ERRCODE hb_cdxSetScope( CDXAREAP pArea, LPDBORDSCOPEINFO sInfo ); #define hb_cdxSkipScope NULL #define hb_cdxCompile NULL @@ -485,14 +513,19 @@ static ERRCODE hb_cdxSetScope( CDXAREAP pArea, LPDBORDSCOPEINFO sInfo ); #define hb_cdxLock NULL #define hb_cdxUnLock NULL #define hb_cdxCloseMemFile NULL -extern ERRCODE hb_cdxCreateMemFile( CDXAREAP pArea, LPDBOPENINFO pCreateInfo ); +#define hb_cdxCreateMemFile NULL #define hb_cdxGetValueFile NULL -extern ERRCODE hb_cdxOpenMemFile( CDXAREAP pArea, LPDBOPENINFO pOpenInfo ); +#define hb_cdxOpenMemFile NULL #define hb_cdxPutValueFile NULL -extern ERRCODE hb_cdxReadDBHeader( CDXAREAP pArea ); -extern ERRCODE hb_cdxWriteDBHeader( CDXAREAP pArea ); +#define hb_cdxReadDBHeader NULL +#define hb_cdxWriteDBHeader NULL +#define hb_cdxExit NULL +#define hb_cdxDrop NULL +#define hb_cdxExists NULL #define hb_cdxWhoCares NULL +//#define hb_cdxSwapBytes( n ) HB_SWAP_ULONG( n ); + #if defined(HB_EXTERN_C) } #endif diff --git a/harbour/include/hbrdddbf.h b/harbour/include/hbrdddbf.h index c59cb0c08b..eb41f9c840 100644 --- a/harbour/include/hbrdddbf.h +++ b/harbour/include/hbrdddbf.h @@ -54,47 +54,21 @@ #define HB_RDDDBF_H_ #include "hbapirdd.h" +#include "hbdbferr.h" #include "hbapicdp.h" #if defined(HB_EXTERN_C) extern "C" { #endif -/* DBF 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 - - /* DBF default file extensions */ - #define DBF_TABLEEXT ".dbf" -#define DBF_MEMOEXT ".dbt" - - - /* DBF lock */ - #define DBF_LOCKPOS 1000000000L -/* DBT's */ - -#define DBT_BLOCKSIZE 512 - - - /* * DBF WORKAREA * ------------ @@ -105,26 +79,26 @@ extern "C" { typedef struct _DBFAREA { struct _RDDFUNCS * lprfsHost; /* Virtual method table for this workarea */ - USHORT uiArea; /* The number assigned to 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 */ + 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 */ + 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; + USHORT heap; + USHORT heapSize; + USHORT rddID; USHORT uiMaxFieldNameLength; /* @@ -142,9 +116,12 @@ typedef struct _DBFAREA ULONG ulRecCount; /* Total records */ char * szDataFileName; /* Name of data file */ char * szMemoFileName; /* Name of memo file */ + USHORT uiMemoBlockSize; /* Size of memo block */ + BYTE bMemoType; /* MEMO type used in DBF memo fields */ BOOL fHasMemo; /* WorkArea with Memo fields */ BOOL fHasTags; /* WorkArea with MDX or CDX index */ - BYTE bCodePage; + BYTE bVersion; /* DBF version ID byte */ + BYTE bCodePage; /* DBF codepage ID */ BOOL fShared; /* Shared file */ BOOL fReadonly; /* Read only file */ USHORT * pFieldOffset; /* Pointer to field offset array */ @@ -173,6 +150,7 @@ typedef DBFAREA * LPDBFAREA; #endif +#ifndef HB_EXTRANAL_RDDDBF_USE /* * -- DBF METHODS -- @@ -180,61 +158,61 @@ typedef DBFAREA * LPDBFAREA; #define SUPERTABLE ( &dbfSuper ) -extern ERRCODE hb_dbfBof( DBFAREAP pArea, BOOL * pBof ); -extern ERRCODE hb_dbfEof( DBFAREAP pArea, BOOL * pEof ); -extern ERRCODE hb_dbfFound( DBFAREAP pArea, BOOL * pFound ); -extern ERRCODE hb_dbfGoBottom( DBFAREAP pArea ); -extern ERRCODE hb_dbfGoTo( DBFAREAP pArea, ULONG ulRecNo ); -extern ERRCODE hb_dbfGoToId( DBFAREAP pArea, PHB_ITEM pItem ); -extern ERRCODE hb_dbfGoTop( DBFAREAP pArea ); +static ERRCODE hb_dbfBof( DBFAREAP pArea, BOOL * pBof ); +static ERRCODE hb_dbfEof( DBFAREAP pArea, BOOL * pEof ); +static ERRCODE hb_dbfFound( DBFAREAP pArea, BOOL * pFound ); +static ERRCODE hb_dbfGoBottom( DBFAREAP pArea ); +static ERRCODE hb_dbfGoTo( DBFAREAP pArea, ULONG ulRecNo ); +static ERRCODE hb_dbfGoToId( DBFAREAP pArea, PHB_ITEM pItem ); +static ERRCODE hb_dbfGoTop( DBFAREAP pArea ); #define hb_dbfSeek NULL -extern ERRCODE hb_dbfSkip( DBFAREAP pArea, LONG lToSkip ); +static ERRCODE hb_dbfSkip( DBFAREAP pArea, LONG lToSkip ); #define hb_dbfSkipFilter NULL -extern ERRCODE hb_dbfSkipRaw( DBFAREAP pArea, LONG lToSkip ); -extern ERRCODE hb_dbfAddField( DBFAREAP pArea, LPDBFIELDINFO pFieldInfo ); -extern ERRCODE hb_dbfAppend( DBFAREAP pArea, BOOL bUnLockAll ); +static ERRCODE hb_dbfSkipRaw( DBFAREAP pArea, LONG lToSkip ); +static ERRCODE hb_dbfAddField( DBFAREAP pArea, LPDBFIELDINFO pFieldInfo ); +static ERRCODE hb_dbfAppend( DBFAREAP pArea, BOOL bUnLockAll ); #define hb_dbfCreateFields NULL -extern ERRCODE hb_dbfDeleteRec( DBFAREAP pArea ); -extern ERRCODE hb_dbfDeleted( DBFAREAP pArea, BOOL * pDeleted ); +static ERRCODE hb_dbfDeleteRec( DBFAREAP pArea ); +static ERRCODE hb_dbfDeleted( DBFAREAP pArea, BOOL * pDeleted ); #define hb_dbfFieldCount NULL #define hb_dbfFieldDisplay NULL #define hb_dbfFieldInfo NULL #define hb_dbfFieldName NULL -extern ERRCODE hb_dbfFlush( DBFAREAP pArea ); +static ERRCODE hb_dbfFlush( DBFAREAP pArea ); #define hb_dbfGetRec NULL -extern ERRCODE hb_dbfGetValue( DBFAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ); -extern ERRCODE hb_dbfGetVarLen( DBFAREAP pArea, USHORT uiIndex, ULONG * pLength ); -extern ERRCODE hb_dbfGoCold( DBFAREAP pArea ); -extern ERRCODE hb_dbfGoHot( DBFAREAP pArea ); -extern ERRCODE hb_dbfPutRec( DBFAREAP pArea, BYTE * pBuffer ); -extern ERRCODE hb_dbfPutValue( DBFAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ); -extern ERRCODE hb_dbfRecall( DBFAREAP pArea ); -extern ERRCODE hb_dbfRecCount( DBFAREAP pArea, ULONG * pRecCount ); +static ERRCODE hb_dbfGetValue( DBFAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ); +static ERRCODE hb_dbfGetVarLen( DBFAREAP pArea, USHORT uiIndex, ULONG * pLength ); +static ERRCODE hb_dbfGoCold( DBFAREAP pArea ); +static ERRCODE hb_dbfGoHot( DBFAREAP pArea ); +static ERRCODE hb_dbfPutRec( DBFAREAP pArea, BYTE * pBuffer ); +static ERRCODE hb_dbfPutValue( DBFAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ); +static ERRCODE hb_dbfRecall( DBFAREAP pArea ); +static ERRCODE hb_dbfRecCount( DBFAREAP pArea, ULONG * pRecCount ); #define hb_dbfRecInfo NULL -extern ERRCODE hb_dbfRecNo( DBFAREAP pArea, PHB_ITEM pRecNo ); -extern ERRCODE hb_dbfSetFieldExtent( DBFAREAP pArea, USHORT uiFieldExtent ); +static ERRCODE hb_dbfRecNo( DBFAREAP pArea, PHB_ITEM pRecNo ); +static ERRCODE hb_dbfSetFieldExtent( DBFAREAP pArea, USHORT uiFieldExtent ); #define hb_dbfAlias NULL -extern ERRCODE hb_dbfClose( DBFAREAP pArea ); -extern ERRCODE hb_dbfCreate( DBFAREAP pArea, LPDBOPENINFO pCreateInfo ); -extern ERRCODE hb_dbfInfo( DBFAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ); -extern ERRCODE hb_dbfNewArea( DBFAREAP pArea ); -extern ERRCODE hb_dbfOpen( DBFAREAP pArea, LPDBOPENINFO pOpenInfo ); +static ERRCODE hb_dbfClose( DBFAREAP pArea ); +static ERRCODE hb_dbfCreate( DBFAREAP pArea, LPDBOPENINFO pCreateInfo ); +static ERRCODE hb_dbfInfo( DBFAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ); +static ERRCODE hb_dbfNewArea( DBFAREAP pArea ); +static ERRCODE hb_dbfOpen( DBFAREAP pArea, LPDBOPENINFO pOpenInfo ); #define hb_dbfRelease NULL -extern ERRCODE hb_dbfStructSize( DBFAREAP pArea, USHORT * uiSize ); -extern ERRCODE hb_dbfSysName( DBFAREAP pArea, BYTE * pBuffer ); +static ERRCODE hb_dbfStructSize( DBFAREAP pArea, USHORT * uiSize ); +static ERRCODE hb_dbfSysName( DBFAREAP pArea, BYTE * pBuffer ); #define hb_dbfEval NULL -extern ERRCODE hb_dbfPack( DBFAREAP pArea ); +static ERRCODE hb_dbfPack( DBFAREAP pArea ); #define hb_dbfPackRec NULL -extern ERRCODE hb_dbfSort( DBFAREAP pArea, LPDBSORTINFO pSortInfo ); -extern ERRCODE hb_dbfTrans( DBFAREAP pArea, LPDBTRANSINFO pTransInfo ); -extern ERRCODE hb_dbfTransRec( DBFAREAP pArea, LPDBTRANSINFO pTransInfo ); -extern ERRCODE hb_dbfZap( DBFAREAP pArea ); -extern ERRCODE hb_dbfChildEnd( DBFAREAP pArea, LPDBRELINFO pRelInfo ); -extern ERRCODE hb_dbfChildStart( DBFAREAP pArea, LPDBRELINFO pRelInfo ); -extern ERRCODE hb_dbfChildSync( DBFAREAP pArea, LPDBRELINFO pRelInfo ); +static ERRCODE hb_dbfSort( DBFAREAP pArea, LPDBSORTINFO pSortInfo ); +static ERRCODE hb_dbfTrans( DBFAREAP pArea, LPDBTRANSINFO pTransInfo ); +static ERRCODE hb_dbfTransRec( DBFAREAP pArea, LPDBTRANSINFO pTransInfo ); +static ERRCODE hb_dbfZap( DBFAREAP pArea ); +static ERRCODE hb_dbfChildEnd( DBFAREAP pArea, LPDBRELINFO pRelInfo ); +static ERRCODE hb_dbfChildStart( DBFAREAP pArea, LPDBRELINFO pRelInfo ); +static ERRCODE hb_dbfChildSync( DBFAREAP pArea, LPDBRELINFO pRelInfo ); #define hb_dbfSyncChildren NULL #define hb_dbfClearRel NULL -extern ERRCODE hb_dbfForceRel( DBFAREAP pArea ); +static ERRCODE hb_dbfForceRel( DBFAREAP pArea ); #define hb_dbfRelArea NULL #define hb_dbfRelEval NULL #define hb_dbfRelText NULL @@ -254,30 +232,32 @@ extern ERRCODE hb_dbfForceRel( DBFAREAP pArea ); #define hb_dbfCountScope NULL #define hb_dbfFilterText NULL #define hb_dbfScopeInfo NULL -extern ERRCODE hb_dbfSetFilter( DBFAREAP pArea, LPDBFILTERINFO pFilterInfo ); +static ERRCODE hb_dbfSetFilter( DBFAREAP pArea, LPDBFILTERINFO pFilterInfo ); #define hb_dbfSetLocate NULL #define hb_dbfSetScope NULL #define hb_dbfSkipScope NULL #define hb_dbfCompile NULL #define hb_dbfError NULL #define hb_dbfEvalBlock NULL -#define hb_dbfRawLock NULL -extern ERRCODE hb_dbfLock( DBFAREAP pArea, LPDBLOCKINFO pLockInfo ); -extern ERRCODE hb_dbfUnLock( DBFAREAP pArea, ULONG ulRecNo ); +static ERRCODE hb_dbfRawLock( DBFAREAP pArea, USHORT uiAction, ULONG lRecNo ); +static ERRCODE hb_dbfLock( DBFAREAP pArea, LPDBLOCKINFO pLockInfo ); +static ERRCODE hb_dbfUnLock( DBFAREAP pArea, ULONG ulRecNo ); #define hb_dbfCloseMemFile NULL -extern ERRCODE hb_dbfCreateMemFile( DBFAREAP pArea, LPDBOPENINFO pCreateInfo ); +static ERRCODE hb_dbfCreateMemFile( DBFAREAP pArea, LPDBOPENINFO pCreateInfo ); #define hb_dbfGetValueFile NULL -extern ERRCODE hb_dbfOpenMemFile( DBFAREAP pArea, LPDBOPENINFO pOpenInfo ); +static ERRCODE hb_dbfOpenMemFile( DBFAREAP pArea, LPDBOPENINFO pOpenInfo ); #define hb_dbfPutValueFile NULL -extern ERRCODE hb_dbfReadDBHeader( DBFAREAP pArea ); -extern ERRCODE hb_dbfWriteDBHeader( DBFAREAP pArea ); +static ERRCODE hb_dbfReadDBHeader( DBFAREAP pArea ); +static ERRCODE hb_dbfWriteDBHeader( DBFAREAP pArea ); #define hb_dbfExit NULL -extern ERRCODE hb_dbfDrop( PHB_ITEM pItemTable ); -extern BOOL hb_dbfExists( PHB_ITEM pItemTable, PHB_ITEM pItemIndex ); +static ERRCODE hb_dbfDrop( PHB_ITEM pItemTable ); +static BOOL hb_dbfExists( PHB_ITEM pItemTable, PHB_ITEM pItemIndex ); #define hb_dbfWhoCares NULL +#endif /* HB_EXTRANAL_RDDDBF_USE */ + #if defined(HB_EXTERN_C) } #endif diff --git a/harbour/include/hbrdddbt.h b/harbour/include/hbrdddbt.h new file mode 100644 index 0000000000..ab04155142 --- /dev/null +++ b/harbour/include/hbrdddbt.h @@ -0,0 +1,200 @@ +/* + * $Id$ + */ + +/* + * xHarbour Project source code: + * DBFDBT RDD + * + * Copyright 2003 Przemyslaw Czerpak + * www - http://www.xharbour.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/). + * + * As a special exception, the Harbour Project gives permission for + * additional uses of the text contained in its release of Harbour. + * + * The exception is that, if you link the Harbour libraries with other + * files to produce an executable, this does not by itself cause the + * resulting executable to be covered by the GNU General Public License. + * Your use of that executable is in no way restricted on account of + * linking the Harbour library code into it. + * + * This exception does not however invalidate any other reasons why + * the executable file might be covered by the GNU General Public License. + * + * This exception applies only to the code released by the Harbour + * Project under the name Harbour. If you copy code from other + * Harbour Project or Free Software Foundation releases into a copy of + * Harbour, as the General Public License permits, the exception does + * not apply to the code that you add in this way. To avoid misleading + * anyone as to the status of such modified files, you must delete + * this exception notice from them. + * + * If you write modifications of your own for Harbour, it is your choice + * whether to permit this exception to apply to your modifications. + * If you do not wish that, delete this exception notice. + * + */ + +#ifndef HB_RDDDBT_H_ +#define HB_RDDDBT_H_ + +#include "hbdbf.h" +#include "hbdbferr.h" +#include "hbapirdd.h" +#ifndef HB_CDP_SUPPORT_OFF +#include "hbapicdp.h" +#endif +#define HB_EXTRANAL_RDDDBF_USE +#include "hbrdddbf.h" + +#if defined(HB_EXTERN_C) +extern "C" { +#endif + +/* MEMO constants and defaults */ +#define DBT_MEMOEXT ".dbt" +#define DBT_BLOCKSIZE 512 +#define DBT_LOCKPOS 0x00000001L +#define DBT_LOCKSIZE 0x7FFFFFFFL + +/* + * DBFDBT WORKAREA + * ------------ + * The Workarea Structure of DBFDBT RDD + * + */ + +/* we don't have to change DBFAREA to create DBTAREA */ +typedef DBFAREA DBTAREA; +typedef DBTAREA * LPDBTAREA; +#ifndef DBTAREAP +#define DBTAREAP LPDBTAREA +#endif + + +/* + * -- DBFDBT METHODS -- + */ + +#define SUPERTABLE ( &dbtSuper ) + +#define hb_dbtBof NULL +#define hb_dbtEof NULL +#define hb_dbtFound NULL +#define hb_dbtGoBottom NULL +#define hb_dbtGoTo NULL +#define hb_dbtGoToId NULL +#define hb_dbtGoTop NULL +#define hb_dbtSeek NULL +#define hb_dbtSkip NULL +#define hb_dbtSkipFilter NULL +#define hb_dbtSkipRaw NULL +#define hb_dbtAddField NULL +#define hb_dbtAppend NULL +#define hb_dbtCreateFields NULL +#define hb_dbtDeleteRec NULL +#define hb_dbtDeleted NULL +#define hb_dbtFieldCount NULL +#define hb_dbtFieldDisplay NULL +#define hb_dbtFieldInfo NULL +#define hb_dbtFieldName NULL +#define hb_dbtFlush NULL +#define hb_dbtGetRec NULL +static ERRCODE hb_dbtGetValue( DBTAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ); +static ERRCODE hb_dbtGetVarLen( DBTAREAP pArea, USHORT uiIndex, ULONG * pLength ); +#define hb_dbtGoCold NULL +#define hb_dbtGoHot NULL +#define hb_dbtPutRec NULL +static ERRCODE hb_dbtPutValue( DBTAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ); +#define hb_dbtRecall NULL +#define hb_dbtRecCount NULL +#define hb_dbtRecInfo NULL +#define hb_dbtRecNo NULL +#define hb_dbtSetFieldExtent NULL +#define hb_dbtAlias NULL +#define hb_dbtClose NULL +#define hb_dbtCreate NULL +static ERRCODE hb_dbtInfo( DBTAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ); +#define hb_dbtNewArea NULL +#define hb_dbtOpen NULL +#define hb_dbtRelease NULL +static ERRCODE hb_dbtStructSize( DBTAREAP pArea, USHORT * uiSize ); +static ERRCODE hb_dbtSysName( DBTAREAP pArea, BYTE * pBuffer ); +#define hb_dbtEval NULL +#define hb_dbtPack NULL +#define hb_dbtPackRec NULL +#define hb_dbtSort NULL +#define hb_dbtTrans NULL +#define hb_dbtTransRec NULL +#define hb_dbtZap NULL +#define hb_dbtChildEnd NULL +#define hb_dbtChildStart NULL +#define hb_dbtChildSync NULL +#define hb_dbtSyncChildren NULL +#define hb_dbtClearRel NULL +#define hb_dbtForceRel NULL +#define hb_dbtRelArea NULL +#define hb_dbtRelEval NULL +#define hb_dbtRelText NULL +#define hb_dbtSetRel NULL +#define hb_dbtOrderListAdd NULL +#define hb_dbtOrderListClear NULL +#define hb_dbtOrderListDelete NULL +#define hb_dbtOrderListFocus NULL +#define hb_dbtOrderListRebuild NULL +#define hb_dbtOrderCondition NULL +#define hb_dbtOrderCreate NULL +#define hb_dbtOrderDestroy NULL +#define hb_dbtOrderInfo NULL +#define hb_dbtClearFilter NULL +#define hb_dbtClearLocate NULL +#define hb_dbtClearScope NULL +#define hb_dbtCountScope NULL +#define hb_dbtFilterText NULL +#define hb_dbtScopeInfo NULL +#define hb_dbtSetFilter NULL +#define hb_dbtSetLocate NULL +#define hb_dbtSetScope NULL +#define hb_dbtSkipScope NULL +#define hb_dbtCompile NULL +#define hb_dbtError NULL +#define hb_dbtEvalBlock NULL +#define hb_dbtRawLock NULL +#define hb_dbtLock NULL +#define hb_dbtUnLock NULL +#define hb_dbtCloseMemFile NULL +static ERRCODE hb_dbtCreateMemFile( DBTAREAP pArea, LPDBOPENINFO pCreateInfo ); +#define hb_dbtGetValueFile NULL +static ERRCODE hb_dbtOpenMemFile( DBTAREAP pArea, LPDBOPENINFO pOpenInfo ); +#define hb_dbtPutValueFile NULL +static ERRCODE hb_dbtReadDBHeader( DBTAREAP pArea ); +static ERRCODE hb_dbtWriteDBHeader( DBTAREAP pArea ); +#define hb_dbtExit NULL +#define hb_dbtDrop NULL +#define hb_dbtExists NULL +#define hb_dbtWhoCares NULL + + +#if defined(HB_EXTERN_C) +} +#endif + +extern ULONG hb_dbfGetMemoBlock( DBFAREAP pArea, USHORT uiIndex ); +extern void hb_dbfPutMemoBlock( DBFAREAP pArea, USHORT uiIndex, ULONG ulBlock ); + +#endif /* HB_RDDDBT */ diff --git a/harbour/include/hbrdddel.h b/harbour/include/hbrdddel.h index abf9a1eba1..f961c0a570 100644 --- a/harbour/include/hbrdddel.h +++ b/harbour/include/hbrdddel.h @@ -154,6 +154,9 @@ extern "C" { #define hb_delimPutValueFile NULL #define hb_delimReadDBHeader NULL #define hb_delimWriteDBHeader NULL +#define hb_delimExit NULL +#define hb_delimDrop NULL +#define hb_delimExists NULL #define hb_delimWhoCares NULL #if defined(HB_EXTERN_C) diff --git a/harbour/include/hbrddfpt.h b/harbour/include/hbrddfpt.h new file mode 100644 index 0000000000..1cb499658f --- /dev/null +++ b/harbour/include/hbrddfpt.h @@ -0,0 +1,318 @@ +/* + * $Id$ + */ + +/* + * xHarbour Project source code: + * DBFFPT RDD + * + * Copyright 2003 Przemyslaw Czerpak + * www - http://www.xharbour.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/). + * + * As a special exception, the Harbour Project gives permission for + * additional uses of the text contained in its release of Harbour. + * + * The exception is that, if you link the Harbour libraries with other + * files to produce an executable, this does not by itself cause the + * resulting executable to be covered by the GNU General Public License. + * Your use of that executable is in no way restricted on account of + * linking the Harbour library code into it. + * + * This exception does not however invalidate any other reasons why + * the executable file might be covered by the GNU General Public License. + * + * This exception applies only to the code released by the Harbour + * Project under the name Harbour. If you copy code from other + * Harbour Project or Free Software Foundation releases into a copy of + * Harbour, as the General Public License permits, the exception does + * not apply to the code that you add in this way. To avoid misleading + * anyone as to the status of such modified files, you must delete + * this exception notice from them. + * + * If you write modifications of your own for Harbour, it is your choice + * whether to permit this exception to apply to your modifications. + * If you do not wish that, delete this exception notice. + * + */ + +#ifndef HB_RDDFPT_H_ +#define HB_RDDFPT_H_ + +#include "hbdbf.h" +#include "hbdbferr.h" +#include "hbapirdd.h" +#ifndef HB_CDP_SUPPORT_OFF +#include "hbapicdp.h" +#endif +#define HB_EXTRANAL_RDDDBF_USE +#include "hbrdddbf.h" + +#if defined(HB_EXTERN_C) +extern "C" { +#endif + + +/* MEMO constants and defaults */ +#define FPT_MEMOEXT ".fpt" +#define FPT_LOCKPOS 0x00000000L +#define FPT_LOCKSIZE 0x7FFFFFFFL +#define FPT_DEFBLOCKSIZE 64 +#define SIX_ITEM_BUFSIZE 14 +#define FLEX_ITEM_BUFSIZE 8 +#define MAX_SIXFREEBLOCKS 82 +#define MAX_FLEXFREEBLOCKS 126 +#define FLEXGCPAGE_SIZE 1010 + +/* usMemoType */ +#define MEMO_DBT 1 +#define MEMO_FPT_HB 2 +#define MEMO_FPT_SIX 3 +#define MEMO_FPT_SIXHB 4 +#define MEMO_FPT_FLEX 5 +#define MEMO_FPT_CLIP 6 + +#define FPTIT_BINARY 0x0000 +#define FPTIT_PICT 0x0000 /* Picture */ +#define FPTIT_TEXT 0x0001 /* Text */ +#define FPTIT_OBJ 0x0002 /* Object */ + +#define FPTIT_SIX_LNUM 0x0002 /* LONG LE */ +#define FPTIT_SIX_DNUM 0x0008 /* DOUBLE LE */ +#define FPTIT_SIX_LDATE 0x0020 /* DATE (LONG LE) */ +#define FPTIT_SIX_LOG 0x0080 /* LOGIC */ +#define FPTIT_SIX_CHAR 0x0400 /* CHAR */ +#define FPTIT_SIX_ARRAY 0x8000 /* ARRAY */ + +//#define FPTIT_SIX_BLOCK 0x1000 +//#define FPTIT_SIX_VREF 0x2000 +//#define FPTIT_SIX_MREF 0x4000 + +#define FPTIT_FLEX_GC 0x03E8 +#define FPTIT_FLEX_UNUSED 0x03E9 + +#define FPTIT_FLEX_ARRAY 0x03EA +#define FPTIT_FLEX_NIL 0x03EE +#define FPTIT_FLEX_TRUE 0x03EF +#define FPTIT_FLEX_FALSE 0x03F0 +#define FPTIT_FLEX_LDATE 0x03F1 +#define FPTIT_FLEX_BYTE 0x03F2 +#define FPTIT_FLEX_SHORT 0x03F4 +#define FPTIT_FLEX_LONG 0x03F6 +#define FPTIT_FLEX_DOUBLE 0x03F8 + +#define FPTIT_FLEXAR_ARAY 0x0C +#define FPTIT_FLEXAR_NIL 0x00 +#define FPTIT_FLEXAR_TRUE 0x19 +#define FPTIT_FLEXAR_FALSE 0x1A +#define FPTIT_FLEXAR_DATE 0x0E +#define FPTIT_FLEXAR_BYTE 0x12 +#define FPTIT_FLEXAR_SHORT 0x13 +#define FPTIT_FLEXAR_LONG 0x20 +#define FPTIT_FLEXAR_DBL 0x0F +#define FPTIT_FLEXAR_STR 0x07 + +/* +#define HB_IT_NIL ( ( USHORT ) 0x0000 ) +#define HB_IT_POINTER ( ( USHORT ) 0x0001 ) +#define HB_IT_LONGLONG ( ( USHORT ) 0x0040 ) +#define HB_IT_SYMBOL ( ( USHORT ) 0x0100 ) +#define HB_IT_ALIAS ( ( USHORT ) 0x0200 ) +#define HB_IT_BLOCK ( ( USHORT ) 0x1000 ) +#define HB_IT_BYREF ( ( USHORT ) 0x2000 ) +#define HB_IT_MEMVAR ( ( USHORT ) 0x4000 ) +#define HB_IT_ANY ( ( USHORT ) 0xFFFF ) +*/ + +/* MEMO file strucutres */ +typedef struct _FPTHEADER +{ + BYTE nextBlock[ 4 ]; /* Next free block in the file */ + BYTE reserved1[ 2 ]; /* */ + BYTE blockSize[ 2 ]; /* Size of block */ + BYTE signature1[ 10 ]; /* Signature: "SixMemo", "Harbour", "Made by CLIP"-overwrites next bytes*/ + BYTE nGCitems[ 2 ]; /* number of GC items in reserved2 (max 82)*/ + BYTE reserved2[ 492 ]; /* */ + BYTE signature2[ 12 ]; /* Signature: "FlexFile3\003" */ + BYTE flexRev[ 4 ]; /* Offset of reversed GC page */ + BYTE flexDir[ 4 ]; /* Offset of GC page */ + BYTE counter[ 4 ]; /* cyclic counter to sign changes in network env. */ + BYTE reserved3[ 4 ]; /* */ + BYTE flexSize[ 2 ]; /* FlexFile3 alternative block size */ + BYTE reserved4[ 482 ]; /* */ +} FPTHEADER; +typedef FPTHEADER * LPFPTHEADER; + +typedef struct _FPTBLOCK +{ + BYTE type[ 4 ]; /* see: FPTIT_ */ + BYTE size[ 4 ]; /* length of data in bytes */ +} FPTBLOCK; +typedef FPTBLOCK * LPFPTBLOCK; + + +/* MEMO internal memory structures */ +typedef struct _MEMOGCITEM +{ + ULONG ulOffset; /* Number of blocks */ + ULONG ulSize; /* Block number */ + BOOL fChanged; /* Mark the free page as changed */ +} MEMOGCITEM; +typedef MEMOGCITEM * LPMEMOGCITEM; + +typedef struct _MEMOGCTABLE +{ + BYTE bType; /* MEMO_FPT_SIX or MEMO_FPT_FLEX */ + BYTE bChanged; /* Should we write GC data to disk */ + ULONG ulNextBlock; /* Next free block in the file */ + ULONG ulRevPage; /* FLEX Rev GC page offset */ + ULONG ulDirPage; /* FLEX Dir GC page offset */ + ULONG ulCounter; /* FLEX cyclic counter */ + ULONG ulSize; /* FLEX GC page size in bytes */ + USHORT usMaxItem; /* max number of items in pGCitems */ + USHORT usItems; /* number of items in pGCitems */ + LPMEMOGCITEM pGCitems; /* free block list */ + FPTHEADER fptHeader; /* FPT file header */ +} MEMOGCTABLE; +typedef MEMOGCTABLE * LPMEMOGCTABLE; + + +/* + * DBFFPT WORKAREA + * ------------ + * The Workarea Structure of DBFFPT RDD + * + */ + +/* we don't have to change DBFAREA to create FPTAREA */ +typedef DBFAREA FPTAREA; +typedef FPTAREA * LPFPTAREA; +#ifndef FPTAREAP +#define FPTAREAP LPFPTAREA +#endif + +/* + * -- DBFFPT METHODS -- + */ + +#define SUPERTABLE ( &fptSuper ) + +#define hb_fptBof NULL +#define hb_fptEof NULL +#define hb_fptFound NULL +#define hb_fptGoBottom NULL +#define hb_fptGoTo NULL +#define hb_fptGoToId NULL +#define hb_fptGoTop NULL +#define hb_fptSeek NULL +#define hb_fptSkip NULL +#define hb_fptSkipFilter NULL +#define hb_fptSkipRaw NULL +#define hb_fptAddField NULL +#define hb_fptAppend NULL +#define hb_fptCreateFields NULL +#define hb_fptDeleteRec NULL +#define hb_fptDeleted NULL +#define hb_fptFieldCount NULL +#define hb_fptFieldDisplay NULL +#define hb_fptFieldInfo NULL +#define hb_fptFieldName NULL +#define hb_fptFlush NULL +#define hb_fptGetRec NULL +static ERRCODE hb_fptGetValue( FPTAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ); +static ERRCODE hb_fptGetVarLen( FPTAREAP pArea, USHORT uiIndex, ULONG * pLength ); +#define hb_fptGoCold NULL +#define hb_fptGoHot NULL +#define hb_fptPutRec NULL +static ERRCODE hb_fptPutValue( FPTAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ); +#define hb_fptRecall NULL +#define hb_fptRecCount NULL +#define hb_fptRecInfo NULL +#define hb_fptRecNo NULL +#define hb_fptSetFieldExtent NULL +#define hb_fptAlias NULL +#define hb_fptClose NULL +#define hb_fptCreate NULL +static ERRCODE hb_fptInfo( FPTAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ); +#define hb_fptNewArea NULL +#define hb_fptOpen NULL +#define hb_fptRelease NULL +static ERRCODE hb_fptStructSize( FPTAREAP pArea, USHORT * uiSize ); +static ERRCODE hb_fptSysName( FPTAREAP pArea, BYTE * pBuffer ); +#define hb_fptEval NULL +#define hb_fptPack NULL +#define hb_fptPackRec NULL +#define hb_fptSort NULL +#define hb_fptTrans NULL +#define hb_fptTransRec NULL +#define hb_fptZap NULL +#define hb_fptChildEnd NULL +#define hb_fptChildStart NULL +#define hb_fptChildSync NULL +#define hb_fptSyncChildren NULL +#define hb_fptClearRel NULL +#define hb_fptForceRel NULL +#define hb_fptRelArea NULL +#define hb_fptRelEval NULL +#define hb_fptRelText NULL +#define hb_fptSetRel NULL +#define hb_fptOrderListAdd NULL +#define hb_fptOrderListClear NULL +#define hb_fptOrderListDelete NULL +#define hb_fptOrderListFocus NULL +#define hb_fptOrderListRebuild NULL +#define hb_fptOrderCondition NULL +#define hb_fptOrderCreate NULL +#define hb_fptOrderDestroy NULL +#define hb_fptOrderInfo NULL +#define hb_fptClearFilter NULL +#define hb_fptClearLocate NULL +#define hb_fptClearScope NULL +#define hb_fptCountScope NULL +#define hb_fptFilterText NULL +#define hb_fptScopeInfo NULL +#define hb_fptSetFilter NULL +#define hb_fptSetLocate NULL +#define hb_fptSetScope NULL +#define hb_fptSkipScope NULL +#define hb_fptCompile NULL +#define hb_fptError NULL +#define hb_fptEvalBlock NULL +#define hb_fptRawLock NULL +#define hb_fptLock NULL +#define hb_fptUnLock NULL +#define hb_fptCloseMemFile NULL +static ERRCODE hb_fptCreateMemFile( FPTAREAP pArea, LPDBOPENINFO pCreateInfo ); +#define hb_fptGetValueFile NULL +static ERRCODE hb_fptOpenMemFile( FPTAREAP pArea, LPDBOPENINFO pOpenInfo ); +#define hb_fptPutValueFile NULL +static ERRCODE hb_fptReadDBHeader( FPTAREAP pArea ); +static ERRCODE hb_fptWriteDBHeader( FPTAREAP pArea ); +#define hb_fptExit NULL +#define hb_fptDrop NULL +#define hb_fptExists NULL +#define hb_fptWhoCares NULL + +#if defined(HB_EXTERN_C) +} +#endif + +extern ULONG hb_dbfGetMemoBlock( DBFAREAP pArea, USHORT uiIndex ); +extern void hb_dbfPutMemoBlock( DBFAREAP pArea, USHORT uiIndex, ULONG ulBlock ); +extern ERRCODE hb_dbfGetEGcode( ERRCODE errCode ); + +#endif /* HB_RDDFPT */ diff --git a/harbour/include/hbrddntx.h b/harbour/include/hbrddntx.h index 310a2c85ad..42d19bcd00 100644 --- a/harbour/include/hbrddntx.h +++ b/harbour/include/hbrddntx.h @@ -54,6 +54,7 @@ #define HB_RDDNTX_H_ #include "hbapirdd.h" +#include "hbdbferr.h" #include "hbapicdp.h" #if defined(HB_EXTERN_C) @@ -61,23 +62,6 @@ extern "C" { #endif -/* DBFNTX 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 -#define EDBF_INVALIDKEY 1026 - - - /* DBFNTX default extensions */ #define NTX_MEMOEXT ".dbt" #define NTX_INDEXEXT ".ntx" @@ -103,7 +87,7 @@ struct _NTXINDEX; typedef struct _KEYINFO { - // PHB_ITEM pItem; + /* PHB_ITEM pItem; */ LONG Tag; LONG Xtra; char key[ 1 ]; /* value of key */ @@ -265,6 +249,7 @@ typedef struct _NTXAREA USHORT heapSize; USHORT rddID; USHORT uiMaxFieldNameLength; + /* * DBFS's additions to the workarea structure * @@ -280,9 +265,12 @@ typedef struct _NTXAREA ULONG ulRecCount; /* Total records */ char * szDataFileName; /* Name of data file */ char * szMemoFileName; /* Name of memo file */ + USHORT uiMemoBlockSize; /* Size of memo block */ + BYTE bMemoType; /* MEMO type used in DBF memo fields */ BOOL fHasMemo; /* WorkArea with Memo fields */ BOOL fHasTags; /* WorkArea with MDX or CDX index */ - BYTE bCodePage; + BYTE bVersion; /* DBF version ID byte */ + BYTE bCodePage; /* DBF codepage ID */ BOOL fShared; /* Shared file */ BOOL fReadonly; /* Read only file */ USHORT * pFieldOffset; /* Pointer to field offset array */ @@ -306,14 +294,14 @@ typedef struct _NTXAREA /* * NTX's additions to the workarea structure * - * Warning: The above section MUST match WORKAREA exactly! Any + * Warning: The above section MUST match DBFAREA exactly! Any * additions to the structure MUST be added below, as in this * example. */ - LPTAGINFO lpCurTag; /* Pointer to current order */ - LPTAGINFO lpNtxTag; /* Pointer to tags list */ - BOOL fNtxAppend; /* TRUE if new record is added */ + LPTAGINFO lpCurTag; /* Pointer to current order */ + LPTAGINFO lpNtxTag; /* Pointer to tags list */ + BOOL fNtxAppend; /* TRUE if new record is added */ } NTXAREA; @@ -342,7 +330,7 @@ static ERRCODE ntxSeek( NTXAREAP pArea, BOOL bSoftSeek, PHB_ITEM pKey, BOOL bFin #define ntxSkipFilter NULL static ERRCODE ntxSkipRaw( NTXAREAP pArea, LONG lToSkip ); #define ntxAddField NULL -// static ERRCODE ntxAppend( NTXAREAP pArea, BOOL bUnLockAll ); +/* static ERRCODE ntxAppend( NTXAREAP pArea, BOOL bUnLockAll ); */ #define ntxAppend NULL #define ntxCreateFields NULL #define ntxDeleteRec NULL @@ -428,6 +416,9 @@ static ERRCODE ntxSetScope( NTXAREAP pArea, LPDBORDSCOPEINFO sInfo ); #define ntxPutValueFile NULL #define ntxReadDBHeader NULL #define ntxWriteDBHeader NULL +#define ntxExit NULL +#define ntxDrop NULL +#define ntxExists NULL #define ntxWhoCares NULL #if defined(HB_EXTERN_C) diff --git a/harbour/include/hbrddsdf.h b/harbour/include/hbrddsdf.h index 94569e1402..5d02d6962b 100644 --- a/harbour/include/hbrddsdf.h +++ b/harbour/include/hbrddsdf.h @@ -154,6 +154,9 @@ extern "C" { #define hb_sdfPutValueFile NULL #define hb_sdfReadDBHeader NULL #define hb_sdfWriteDBHeader NULL +#define hb_sdfExit NULL +#define hb_sdfDrop NULL +#define hb_sdfExists NULL #define hb_sdfWhoCares NULL #if defined(HB_EXTERN_C) diff --git a/harbour/source/rdd/dbcmd.c b/harbour/source/rdd/dbcmd.c index cb9ac2df72..f71ebe040e 100644 --- a/harbour/source/rdd/dbcmd.c +++ b/harbour/source/rdd/dbcmd.c @@ -2230,6 +2230,7 @@ HB_FUNC( FLOCK ) dbLockInfo.fResult = FALSE; if( s_pCurrArea ) { + dbLockInfo.itmRecID = NULL; dbLockInfo.uiMethod = DBLM_FILE; SELF_LOCK( ( AREAP ) s_pCurrArea->pArea, &dbLockInfo ); } @@ -2638,6 +2639,45 @@ HB_FUNC( ORDKEYNO ) hb_errRT_DBCMD( EG_NOTABLE, EDBCMD_NOTABLE, NULL, "ORDKEYNO" ); } +HB_FUNC( ORDKEYGOTO ) +{ + DBORDERINFO pOrderInfo; + + if( s_pCurrArea ) + { + pOrderInfo.itmOrder = hb_param( 1, HB_IT_STRING ); + if( !pOrderInfo.itmOrder ) + pOrderInfo.itmOrder = hb_param( 1, HB_IT_NUMERIC ); + pOrderInfo.atomBagName = hb_param( 2, HB_IT_STRING ); + /* Either or both may be NIL */ + + pOrderInfo.itmNewVal = hb_param( 3 , HB_IT_NUMERIC ); + pOrderInfo.itmResult = hb_itemPutL( NULL, FALSE ); + SELF_ORDINFO( ( AREAP ) s_pCurrArea->pArea, DBOI_POSITION, &pOrderInfo ); + hb_retl( hb_itemGetL( pOrderInfo.itmResult ) ); + hb_itemRelease( pOrderInfo.itmResult ); + } + else + hb_errRT_DBCMD( EG_NOTABLE, EDBCMD_NOTABLE, NULL, "ORDKEYGOTO" ); +} + +HB_FUNC( ORDSKIPUNIQUE ) +{ + DBORDERINFO pOrderInfo; + + if( s_pCurrArea ) + { + pOrderInfo.itmOrder = NULL; + pOrderInfo.itmNewVal = hb_param( 1, HB_IT_ANY ); + pOrderInfo.itmResult = hb_itemPutL( NULL, FALSE ); + SELF_ORDINFO( ( AREAP ) s_pCurrArea->pArea, DBOI_SKIPUNIQUE, &pOrderInfo ); + hb_retl( hb_itemGetL( pOrderInfo.itmResult ) ); + hb_itemRelease( pOrderInfo.itmResult ); + } + else + hb_errRT_DBCMD( EG_NOTABLE, EDBCMD_NOTABLE, NULL, "ORDSKIPUNIQUE" ); +} + HB_FUNC( ORDKEYVAL ) { DBORDERINFO pOrderInfo; @@ -2695,6 +2735,48 @@ HB_FUNC( ORDKEYDEL ) hb_errRT_DBCMD( EG_NOTABLE, EDBCMD_NOTABLE, NULL, "ORDKEYDEL" ); } +HB_FUNC( ORDDESCEND ) +{ + DBORDERINFO pOrderInfo; + + if( s_pCurrArea ) + { + pOrderInfo.itmOrder = hb_param( 1, HB_IT_STRING ); + if( !pOrderInfo.itmOrder ) + pOrderInfo.itmOrder = hb_param( 1, HB_IT_NUMERIC ); + pOrderInfo.atomBagName = hb_param( 2, HB_IT_STRING ); + /* Either or both may be NIL */ + pOrderInfo.itmNewVal = hb_param( 3 , HB_IT_LOGICAL ); + pOrderInfo.itmResult = hb_itemPutL( NULL, FALSE ); + SELF_ORDINFO( ( AREAP ) s_pCurrArea->pArea, DBOI_ISDESC, &pOrderInfo ); + hb_retl( hb_itemGetL( pOrderInfo.itmResult ) ); + hb_itemRelease( pOrderInfo.itmResult ); + } + else + hb_errRT_DBCMD( EG_NOTABLE, EDBCMD_NOTABLE, NULL, "ORDDESCEND" ); +} + +HB_FUNC( ORDISUNIQUE ) +{ + DBORDERINFO pOrderInfo; + + if( s_pCurrArea ) + { + pOrderInfo.itmOrder = hb_param( 1, HB_IT_STRING ); + if( !pOrderInfo.itmOrder ) + pOrderInfo.itmOrder = hb_param( 1, HB_IT_NUMERIC ); + pOrderInfo.atomBagName = hb_param( 2, HB_IT_STRING ); + /* HARBOUR extension: NewVal to set/reset unique flag */ + pOrderInfo.itmNewVal = hb_param( 3 , HB_IT_LOGICAL ); + pOrderInfo.itmResult = hb_itemPutL( NULL, FALSE ); + SELF_ORDINFO( ( AREAP ) s_pCurrArea->pArea, DBOI_UNIQUE, &pOrderInfo ); + hb_retl( hb_itemGetL( pOrderInfo.itmResult ) ); + hb_itemRelease( pOrderInfo.itmResult ); + } + else + hb_errRT_DBCMD( EG_NOTABLE, EDBCMD_NOTABLE, NULL, "ORDISUNIQUE" ); +} + #endif HB_FUNC( ORDLISTADD ) @@ -2725,16 +2807,18 @@ HB_FUNC( ORDLISTADD ) hb_itemRelease( pOrderInfo.itmResult ); return; } - SELF_ORDLSTADD( ( AREAP ) s_pCurrArea->pArea, &pOrderInfo ); - if ( bFirst ) /* set as controlling order and go top */ + if( SELF_ORDLSTADD( ( AREAP ) s_pCurrArea->pArea, &pOrderInfo ) == SUCCESS ) { - pOrderInfo.itmOrder = hb_itemPutNI( NULL, 1 ); - SELF_ORDLSTFOCUS( ( AREAP ) s_pCurrArea->pArea, &pOrderInfo ); - hb_itemRelease( pOrderInfo.itmOrder ); - SELF_GOTOP( ( AREAP ) s_pCurrArea->pArea ); + if ( bFirst ) /* set as controlling order and go top */ + { + pOrderInfo.itmOrder = hb_itemPutNI( NULL, 1 ); + SELF_ORDLSTFOCUS( ( AREAP ) s_pCurrArea->pArea, &pOrderInfo ); + hb_itemRelease( pOrderInfo.itmOrder ); + SELF_GOTOP( ( AREAP ) s_pCurrArea->pArea ); + } + hb_itemRelease( pOrderInfo.itmResult ); } - hb_itemRelease( pOrderInfo.itmResult ); } else hb_errRT_DBCMD( EG_NOTABLE, EDBCMD_NOTABLE, NULL, "ORDLISTADD" ); @@ -2877,8 +2961,10 @@ HB_FUNC( RDDREGISTER ) uiLen = ( USHORT ) hb_parclen( 1 ); if( uiLen > 0 ) { - hb_strncpyUpper( szDriver, hb_parc( 1 ), - min( uiLen, HARBOUR_MAX_RDD_DRIVERNAME_LENGTH ) ); + if( uiLen > HARBOUR_MAX_RDD_DRIVERNAME_LENGTH ) + uiLen = HARBOUR_MAX_RDD_DRIVERNAME_LENGTH; + + hb_strncpyUpper( szDriver, hb_parc( 1 ), uiLen ); /* * hb_rddRegister returns: * @@ -2932,6 +3018,7 @@ HB_FUNC( RLOCK ) dbLockInfo.fResult = FALSE; if( s_pCurrArea ) { + dbLockInfo.itmRecID = NULL; dbLockInfo.uiMethod = DBLM_EXCLUSIVE; SELF_LOCK( ( AREAP ) s_pCurrArea->pArea, &dbLockInfo ); } @@ -2979,9 +3066,23 @@ HB_FUNC( __RDDSETDEFAULT ) hb_retc( s_szDefDriver ); uiLen = ( USHORT ) hb_parclen( 1 ); + if( uiLen > 0 ) { - s_szDefDriver = ( char * ) hb_xrealloc( s_szDefDriver, uiLen + 1 ); + if( uiLen > HARBOUR_MAX_RDD_DRIVERNAME_LENGTH ) + { + uiLen = HARBOUR_MAX_RDD_DRIVERNAME_LENGTH; + } + + if( s_szDefDriver ) + { + s_szDefDriver = ( char * ) hb_xrealloc( s_szDefDriver, uiLen + 1 ); + } + else + { + s_szDefDriver = ( char * ) hb_xgrab( uiLen + 1 ); + } + hb_strncpyUpper( s_szDefDriver, hb_parc( 1 ), uiLen ); } } @@ -2989,41 +3090,61 @@ HB_FUNC( __RDDSETDEFAULT ) HB_FUNC( RDDSETDEFAULT ) { USHORT uiLen; - char szNewDriver[ HARBOUR_MAX_RDD_DRIVERNAME_LENGTH +1 ]; + char szNewDriver[ HARBOUR_MAX_RDD_DRIVERNAME_LENGTH + 1 ]; hb_rddCheck(); hb_retc( s_szDefDriver ); uiLen = ( USHORT ) hb_parclen( 1 ); + if( uiLen > 0 ) { - hb_strncpyUpper( szNewDriver, hb_parc( 1 ), - min( uiLen, HARBOUR_MAX_RDD_DRIVERNAME_LENGTH ) ); + if( uiLen > HARBOUR_MAX_RDD_DRIVERNAME_LENGTH ) + { + uiLen = HARBOUR_MAX_RDD_DRIVERNAME_LENGTH; + } - if( !hb_rddFindNode( szNewDriver, NULL ) ) + hb_strncpyUpper( szNewDriver, hb_parc( 1 ), uiLen ); + + if( ! hb_rddFindNode( szNewDriver, NULL ) ) { hb_errRT_DBCMD( EG_ARG, EDBCMD_BADPARAMETER, NULL, "RDDSETDEFAULT" ); return; } - s_szDefDriver = ( char * ) hb_xrealloc( s_szDefDriver, uiLen + 1 ); - strcpy( s_szDefDriver, szNewDriver ); + if( s_szDefDriver ) + { + s_szDefDriver = ( char * ) hb_xrealloc( s_szDefDriver, uiLen + 1 ); + } + else + { + s_szDefDriver = ( char * ) hb_xgrab( uiLen + 1 ); + } + + strncpy( s_szDefDriver, szNewDriver, uiLen ); + s_szDefDriver[ uiLen ] = '\0'; } } HB_FUNC( DBSETDRIVER ) { + USHORT uiLen; - char szNewDriver[ HARBOUR_MAX_RDD_DRIVERNAME_LENGTH +1 ]; + char szNewDriver[ HARBOUR_MAX_RDD_DRIVERNAME_LENGTH + 1 ]; hb_rddCheck(); hb_retc( s_szDefDriver ); uiLen = ( USHORT ) hb_parclen( 1 ); + if( uiLen > 0 ) { - hb_strncpyUpper( szNewDriver, hb_parc( 1 ), - min( uiLen, HARBOUR_MAX_RDD_DRIVERNAME_LENGTH ) ); + if( uiLen > HARBOUR_MAX_RDD_DRIVERNAME_LENGTH ) + { + uiLen = HARBOUR_MAX_RDD_DRIVERNAME_LENGTH; + } + + hb_strncpyUpper( szNewDriver, hb_parc( 1 ), uiLen ); if( !hb_rddFindNode( szNewDriver, NULL ) ) { @@ -3031,8 +3152,17 @@ HB_FUNC( DBSETDRIVER ) return; } - s_szDefDriver = ( char * ) hb_xrealloc( s_szDefDriver, uiLen + 1 ); - strcpy( s_szDefDriver, szNewDriver ); + if( s_szDefDriver ) + { + s_szDefDriver = ( char * ) hb_xrealloc( s_szDefDriver, uiLen + 1 ); + } + else + { + s_szDefDriver = ( char * ) hb_xgrab( uiLen + 1 ); + } + + strncpy( s_szDefDriver, szNewDriver, uiLen ); + s_szDefDriver[ uiLen ] = '\0'; } } diff --git a/harbour/source/rdd/dbf1.c b/harbour/source/rdd/dbf1.c index e7e7d144d3..2a3c0c2175 100644 --- a/harbour/source/rdd/dbf1.c +++ b/harbour/source/rdd/dbf1.c @@ -62,17 +62,18 @@ #include "hbdate.h" #include "hbdbsort.h" #include "error.ch" -#include "hbapicdp.h" #include - +# include "hbapicdp.h" extern PHB_CODEPAGE s_cdpage; +#define __PRG_SOURCE__ __FILE__ + /* DJGPP can sprintf a float that is almost 320 digits long */ #define HB_MAX_DOUBLE_LENGTH 320 HB_FUNC( _DBFC ); HB_FUNC( DBF_GETFUNCTABLE ); - +#define __PRG_SOURCE__ __FILE__ #undef HB_PRG_PCODE_VER #define HB_PRG_PCODE_VER HB_PCODE_VER @@ -81,7 +82,10 @@ HB_INIT_SYMBOLS_BEGIN( dbf1__InitSymbols ) { "_DBFC", HB_FS_PUBLIC, HB_FUNCNAME( _DBFC ), NULL }, { "DBF_GETFUNCTABLE", HB_FS_PUBLIC, HB_FUNCNAME( DBF_GETFUNCTABLE ), NULL } HB_INIT_SYMBOLS_END( dbf1__InitSymbols ) -#if defined(_MSC_VER) + +#if defined(HB_STATIC_STARTUP) + #pragma startup dbf1__InitSymbols +#elif defined(_MSC_VER) #if _MSC_VER >= 1010 #pragma data_seg( ".CRT$XIY" ) #pragma comment( linker, "/Merge:.CRT=.data" ) @@ -94,8 +98,7 @@ HB_INIT_SYMBOLS_END( dbf1__InitSymbols ) #pragma startup dbf1__InitSymbols #endif -static RDDFUNCS dbfSuper = { NULL }; - +static RDDFUNCS dbfSuper; static RDDFUNCS dbfTable = { ( DBENTRYP_BP ) hb_dbfBof, ( DBENTRYP_BP ) hb_dbfEof, ( DBENTRYP_BP ) hb_dbfFound, @@ -295,8 +298,7 @@ static void hb_dbfUnlockAllRecords( DBFAREAP pArea ) if( pArea->pLocksPos ) { for( ulCount = 0; ulCount < pArea->ulNumLocksPos; ulCount++ ) - hb_fsLock( pArea->hDataFile, DBF_LOCKPOS + pArea->pLocksPos[ ulCount ], - 1, FL_UNLOCK ); + SELF_RAWLOCK( ( AREAP ) pArea, REC_UNLOCK, pArea->pLocksPos[ ulCount ] ); hb_xfree( pArea->pLocksPos ); pArea->pLocksPos = NULL; } @@ -312,8 +314,10 @@ static void hb_dbfUnlockRecord( DBFAREAP pArea, ULONG ulRecNo ) HB_TRACE(HB_TR_DEBUG, ("hb_dbfUnlockRecord(%p, %lu)", pArea, ulRecNo)); - if( hb_fsLock( pArea->hDataFile, DBF_LOCKPOS + pArea->pLocksPos[ ulRecNo - 1 ], - 1, FL_UNLOCK ) ) + if( ulRecNo <= 0 ) + ulRecNo = 1; + + if( SELF_RAWLOCK( ( AREAP ) pArea, REC_UNLOCK, ulRecNo ) == SUCCESS ) { if( pArea->ulNumLocksPos == 1 ) /* Delete the list */ { @@ -360,6 +364,9 @@ static ERRCODE hb_dbfLockRecord( DBFAREAP pArea, ULONG ulRecNo, BOOL * pResult, return SUCCESS; } + if( ulRecNo <= 0 ) + ulRecNo = 1; + if( bExclusive ) hb_dbfUnlockAllRecords( pArea ); @@ -374,7 +381,7 @@ static ERRCODE hb_dbfLockRecord( DBFAREAP pArea, ULONG ulRecNo, BOOL * pResult, } } - if( hb_fsLock( pArea->hDataFile, DBF_LOCKPOS + ulRecNo, 1, FL_LOCK ) ) + if( SELF_RAWLOCK( ( AREAP ) pArea, REC_LOCK, ulRecNo ) == SUCCESS ) { if( pArea->ulNumLocksPos == 0 ) /* Create the list */ { @@ -416,8 +423,8 @@ static ERRCODE hb_dbfLockFile( DBFAREAP pArea, BOOL * pResult ) hb_dbfUnlockAllRecords( pArea ); - pArea->fFLocked = hb_fsLock( pArea->hDataFile, DBF_LOCKPOS + 1, - DBF_LOCKPOS, FL_LOCK ); + SELF_RAWLOCK( ( AREAP ) pArea, FILE_LOCK, 0 ); + * pResult = pArea->fFLocked; if( !pArea->fPositioned ) hb_dbfGoTo( pArea, pArea->ulRecNo ); @@ -438,8 +445,7 @@ static void hb_dbfUnlockFile( DBFAREAP pArea ) HB_TRACE(HB_TR_DEBUG, ("hb_dbfUnlockFile(%p)", pArea)); if( pArea->fFLocked ) - pArea->fFLocked = !hb_fsLock( pArea->hDataFile, DBF_LOCKPOS + 1, - DBF_LOCKPOS, FL_UNLOCK ); + SELF_RAWLOCK( ( AREAP ) pArea, FILE_UNLOCK, 0 ); } /* @@ -479,9 +485,68 @@ static void hb_dbfGetLockArray( DBFAREAP pArea, PHB_ITEM pItem ) } /* - * Converts memo block offset into ASCII. + * Converts EDBF_* error code into EG_* one. + * This function is common for different DBF based RDD implementation + * so I don't make it static */ -static ULONG hb_dbfGetMemoBlock( DBFAREAP pArea, USHORT uiIndex ) +ERRCODE hb_dbfGetEGcode( ERRCODE errCode ) +{ + ERRCODE errEGcode; + + HB_TRACE(HB_TR_DEBUG, ("hb_dbfGetEGcode(%hu)", errCode)); + + switch ( errCode ) + { + case EDBF_OPEN_DBF: + errEGcode = EG_OPEN; + break; + case EDBF_CREATE_DBF: + errEGcode = EG_CREATE; + break; + case EDBF_READ: + errEGcode = EG_READ; + break; + case EDBF_WRITE: + errEGcode = EG_WRITE; + break; + case EDBF_CORRUPT: + errEGcode = EG_CORRUPTION; + break; + case EDBF_DATATYPE: + errEGcode = EG_DATATYPE; + break; + case EDBF_DATAWIDTH: + errEGcode = EG_DATAWIDTH; + break; + case EDBF_UNLOCKED: + errEGcode = EG_UNLOCKED; + break; + case EDBF_SHARED: + errEGcode = EG_SHARED; + break; + case EDBF_APPENDLOCK: + errEGcode = EG_APPENDLOCK; + break; + case EDBF_READONLY: + errEGcode = EG_READONLY; + break; + case EDBF_LOCK: + errEGcode = EG_LOCK; + break; + case EDBF_INVALIDKEY: + default: + errEGcode = EG_UNSUPPORTED; + break; + } + + return errEGcode; +} +/* + * Converts memo block offset into ASCII. + * This function is common for different MEMO implementation + * so I left it in DBF. + */ +ULONG hb_dbfGetMemoBlock( DBFAREAP pArea, USHORT uiIndex ) { USHORT uiCount; BYTE bByte; @@ -501,8 +566,10 @@ static ULONG hb_dbfGetMemoBlock( DBFAREAP pArea, USHORT uiIndex ) /* * Converts ASCII data into memo block offset. + * This function is common for different MEMO implementation + * so I left it in DBF. */ -static void hb_dbfPutMemoBlock( DBFAREAP pArea, USHORT uiIndex, ULONG ulBlock ) +void hb_dbfPutMemoBlock( DBFAREAP pArea, USHORT uiIndex, ULONG ulBlock ) { SHORT iCount; @@ -520,124 +587,6 @@ static void hb_dbfPutMemoBlock( DBFAREAP pArea, USHORT uiIndex, ULONG ulBlock ) } } -/* - * Return the size of memo. - */ -static ULONG hb_dbfGetMemoLen( DBFAREAP pArea, USHORT uiIndex ) -{ - ULONG ulBlock; - BYTE pBlock[ DBT_BLOCKSIZE ]; - - HB_TRACE(HB_TR_DEBUG, ("hb_dbfGetMemoLen(%p, %hu)", pArea, uiIndex)); - - ulBlock = hb_dbfGetMemoBlock( pArea, uiIndex ); - if( ulBlock == 0 ) - return 0; - hb_fsSeek( pArea->hMemoFile, ulBlock * DBT_BLOCKSIZE, FS_SET ); - ulBlock = 0; - do - { - hb_fsRead( pArea->hMemoFile, pBlock, DBT_BLOCKSIZE ); - uiIndex = 0; - while( uiIndex < DBT_BLOCKSIZE && pBlock[ uiIndex ] != 0x1A ) - uiIndex++; - ulBlock += uiIndex; - } while( uiIndex == DBT_BLOCKSIZE ); - return ulBlock; -} - -/* - * Read memo data. - */ -static void hb_dbfGetMemo( DBFAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) -{ - ULONG ulSize, ulBlock; - BYTE * pBuffer; - - HB_TRACE(HB_TR_DEBUG, ("hb_dbfGetMemo(%p, %hu, %p)", pArea, uiIndex, pItem)); - - ulSize = hb_dbfGetMemoLen( pArea, uiIndex ); - - pBuffer = ( BYTE * ) hb_xgrab( ulSize + 1 ); - if( ulSize > 0 ) - { - ulBlock = hb_dbfGetMemoBlock( pArea, uiIndex ); - hb_fsSeek( pArea->hMemoFile, ulBlock * DBT_BLOCKSIZE, FS_SET ); - hb_fsReadLarge( pArea->hMemoFile, pBuffer, ulSize ); - } - else - *pBuffer = '\0'; - - hb_itemPutCPtr( pItem, ( char * ) pBuffer, ulSize ); - hb_cdpTranslate( pItem->item.asString.value, pArea->cdPage,s_cdpage ); - hb_itemSetCMemo( pItem ); -} - -/* - * Write memo data. - */ -static void hb_dbfWriteMemo( DBFAREAP pArea, ULONG ulBlock, PHB_ITEM pItem, ULONG ulLen, - ULONG * ulStoredBlock ) -{ - BYTE pBlock[ DBT_BLOCKSIZE ]; - BOOL bNewBlock; - ULONG ulNewBlock, ulNextBlock; - - HB_TRACE(HB_TR_DEBUG, ("hb_dbfWriteMemo(%p, %lu, %p, %lu, %p)", pArea, ulBlock, pItem, - ulLen, ulStoredBlock)); - - memset( pBlock, 0x1A, DBT_BLOCKSIZE ); - bNewBlock = !( ulBlock && ulLen < DBT_BLOCKSIZE - 1 ); - if( bNewBlock ) - { - /* Get next block from header */ - hb_fsSeek( pArea->hMemoFile, 0, FS_SET ); - hb_fsRead( pArea->hMemoFile, ( BYTE * ) &ulNewBlock, sizeof( ulNewBlock ) ); - ulNextBlock = ulNewBlock * DBT_BLOCKSIZE; - hb_fsSeek( pArea->hMemoFile, ulNextBlock, FS_SET ); - } - else - { - hb_fsSeek( pArea->hMemoFile, ulBlock * DBT_BLOCKSIZE, FS_SET ); - ulNewBlock = ulBlock; - } - * ulStoredBlock = ulNewBlock; - - /* Write memo data and eof mark */ - hb_fsWriteLarge( pArea->hMemoFile, ( BYTE * ) hb_itemGetCPtr( pItem ), ulLen ); - hb_fsWrite( pArea->hMemoFile, pBlock, ( DBT_BLOCKSIZE - ( USHORT ) ( ulLen % DBT_BLOCKSIZE ) ) ); - - if( bNewBlock ) - { - ulNextBlock += ulLen + 1; - ulNextBlock += ( DBT_BLOCKSIZE - ulNextBlock % DBT_BLOCKSIZE ); - ulNextBlock /= DBT_BLOCKSIZE; - hb_fsSeek( pArea->hMemoFile, 0, FS_SET ); - hb_fsWrite( pArea->hMemoFile, ( BYTE * ) &ulNextBlock, sizeof( ulNextBlock ) ); - } -} - -/* - * Assign a value to the specified memo field. - */ -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 ) - { - ulBlock = hb_dbfGetMemoBlock( pArea, uiIndex ); - hb_dbfWriteMemo( pArea, ulBlock, pItem, ulLen, &ulBlock ); - } - else - ulBlock = 0; - hb_dbfPutMemoBlock( pArea, uiIndex, ulBlock ); - return TRUE; -} - /* * -- DBF METHODS -- */ @@ -645,7 +594,7 @@ static BOOL hb_dbfPutMemo( DBFAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) /* * Determine logical beginning of file. */ -ERRCODE hb_dbfBof( DBFAREAP pArea, BOOL * pBof ) +static ERRCODE hb_dbfBof( DBFAREAP pArea, BOOL * pBof ) { HB_TRACE(HB_TR_DEBUG, ("hb_dbfBof(%p, %p)", pArea, pBof)); @@ -659,7 +608,7 @@ ERRCODE hb_dbfBof( DBFAREAP pArea, BOOL * pBof ) /* * Determine logical end of file. */ -ERRCODE hb_dbfEof( DBFAREAP pArea, BOOL * pEof ) +static ERRCODE hb_dbfEof( DBFAREAP pArea, BOOL * pEof ) { HB_TRACE(HB_TR_DEBUG, ("hb_dbfEof(%p, %p)", pArea, pEof)); @@ -673,7 +622,7 @@ ERRCODE hb_dbfEof( DBFAREAP pArea, BOOL * pEof ) /* * Determine outcome of the last search operation. */ -ERRCODE hb_dbfFound( DBFAREAP pArea, BOOL * pFound ) +static ERRCODE hb_dbfFound( DBFAREAP pArea, BOOL * pFound ) { HB_TRACE(HB_TR_DEBUG, ("hb_dbfFound(%p, %p)", pArea, pFound)); @@ -687,7 +636,7 @@ ERRCODE hb_dbfFound( DBFAREAP pArea, BOOL * pFound ) /* * Position cursor at the last record. */ -ERRCODE hb_dbfGoBottom( DBFAREAP pArea ) +static ERRCODE hb_dbfGoBottom( DBFAREAP pArea ) { HB_TRACE(HB_TR_DEBUG, ("hb_dbfGoBottom(%p)", pArea)); @@ -708,7 +657,7 @@ ERRCODE hb_dbfGoBottom( DBFAREAP pArea ) /* * Position cursor at a specific physical record. */ -ERRCODE hb_dbfGoTo( DBFAREAP pArea, ULONG ulRecNo ) +static ERRCODE hb_dbfGoTo( DBFAREAP pArea, ULONG ulRecNo ) { HB_TRACE(HB_TR_DEBUG, ("hb_dbfGoTo(%p, %lu)", pArea, ulRecNo)); @@ -749,7 +698,7 @@ ERRCODE hb_dbfGoTo( DBFAREAP pArea, ULONG ulRecNo ) /* * Position the cursor to a specific, physical identity. */ -ERRCODE hb_dbfGoToId( DBFAREAP pArea, PHB_ITEM pItem ) +static ERRCODE hb_dbfGoToId( DBFAREAP pArea, PHB_ITEM pItem ) { PHB_ITEM pError; @@ -772,7 +721,7 @@ ERRCODE hb_dbfGoToId( DBFAREAP pArea, PHB_ITEM pItem ) /* * Position cursor at the first record. */ -ERRCODE hb_dbfGoTop( DBFAREAP pArea ) +static ERRCODE hb_dbfGoTop( DBFAREAP pArea ) { HB_TRACE(HB_TR_DEBUG, ("hb_dbfGoTop(%p)", pArea)); @@ -788,7 +737,7 @@ ERRCODE hb_dbfGoTop( DBFAREAP pArea ) /* * Reposition cursor relative to current position. */ -ERRCODE hb_dbfSkip( DBFAREAP pArea, LONG lToSkip ) +static ERRCODE hb_dbfSkip( DBFAREAP pArea, LONG lToSkip ) { ERRCODE uiError; @@ -824,7 +773,7 @@ ERRCODE hb_dbfSkip( DBFAREAP pArea, LONG lToSkip ) /* * Reposition cursor, regardless of filter. */ -ERRCODE hb_dbfSkipRaw( DBFAREAP pArea, LONG lToSkip ) +static ERRCODE hb_dbfSkipRaw( DBFAREAP pArea, LONG lToSkip ) { BOOL bBof, bEof; @@ -851,7 +800,7 @@ ERRCODE hb_dbfSkipRaw( DBFAREAP pArea, LONG lToSkip ) /* * Add a field to the WorkArea. */ -ERRCODE hb_dbfAddField( DBFAREAP pArea, LPDBFIELDINFO pFieldInfo ) +static ERRCODE hb_dbfAddField( DBFAREAP pArea, LPDBFIELDINFO pFieldInfo ) { HB_TRACE(HB_TR_DEBUG, ("hb_dbfAddField(%p, %p)", pArea, pFieldInfo)); @@ -864,7 +813,7 @@ ERRCODE hb_dbfAddField( DBFAREAP pArea, LPDBFIELDINFO pFieldInfo ) /* * Append a record to the WorkArea. */ -ERRCODE hb_dbfAppend( DBFAREAP pArea, BOOL bUnLockAll ) +static ERRCODE hb_dbfAppend( DBFAREAP pArea, BOOL bUnLockAll ) { ULONG ulNewRecord; PHB_ITEM pError; @@ -938,7 +887,7 @@ ERRCODE hb_dbfAppend( DBFAREAP pArea, BOOL bUnLockAll ) /* * Delete a record. */ -ERRCODE hb_dbfDeleteRec( DBFAREAP pArea ) +static ERRCODE hb_dbfDeleteRec( DBFAREAP pArea ) { HB_TRACE(HB_TR_DEBUG, ("hb_dbfDeleteRec(%p)", pArea)); @@ -964,7 +913,7 @@ ERRCODE hb_dbfDeleteRec( DBFAREAP pArea ) /* * Determine deleted status for a record. */ -ERRCODE hb_dbfDeleted( DBFAREAP pArea, BOOL * pDeleted ) +static ERRCODE hb_dbfDeleted( DBFAREAP pArea, BOOL * pDeleted ) { HB_TRACE(HB_TR_DEBUG, ("hb_dbfDeleted(%p, %p)", pArea, pDeleted)); @@ -982,7 +931,7 @@ ERRCODE hb_dbfDeleted( DBFAREAP pArea, BOOL * pDeleted ) /* * Write data buffer to the data store. */ -ERRCODE hb_dbfFlush( DBFAREAP pArea ) +static ERRCODE hb_dbfFlush( DBFAREAP pArea ) { ERRCODE uiError; @@ -1015,7 +964,7 @@ ERRCODE hb_dbfFlush( DBFAREAP pArea ) /* * Obtain the current value of a field. */ -ERRCODE hb_dbfGetValue( DBFAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) +static ERRCODE hb_dbfGetValue( DBFAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) { LPFIELD pField; char szBuffer[ 21 ]; @@ -1039,7 +988,7 @@ ERRCODE hb_dbfGetValue( DBFAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) case HB_IT_STRING: hb_itemPutCL( pItem, ( char * ) pArea->pRecord + pArea->pFieldOffset[ uiIndex ], pField->uiLen ); - hb_cdpTranslate( pItem->item.asString.value, pArea->cdPage,s_cdpage ); + hb_cdpTranslate( pItem->item.asString.value, pArea->cdPage, s_cdpage ); break; case HB_IT_LOGICAL: @@ -1049,10 +998,6 @@ ERRCODE hb_dbfGetValue( DBFAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) pArea->pRecord[ pArea->pFieldOffset[ uiIndex ] ] == 'y' ); break; - case HB_IT_MEMO: - hb_dbfGetMemo( pArea, uiIndex, pItem ); - break; - case HB_IT_DATE: memcpy( szBuffer, pArea->pRecord + pArea->pFieldOffset[ uiIndex ], 8 ); szBuffer[ 8 ] = 0; @@ -1080,6 +1025,7 @@ ERRCODE hb_dbfGetValue( DBFAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) } break; + case HB_IT_MEMO: default: bError = TRUE; break; @@ -1102,7 +1048,7 @@ ERRCODE hb_dbfGetValue( DBFAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) /* * Obtain the length of a field value. */ -ERRCODE hb_dbfGetVarLen( DBFAREAP pArea, USHORT uiIndex, ULONG * pLength ) +static ERRCODE hb_dbfGetVarLen( DBFAREAP pArea, USHORT uiIndex, ULONG * pLength ) { HB_TRACE(HB_TR_DEBUG, ("hb_dbfGetVarLen(%p, %hu, %p)", pArea, uiIndex, pLength)); @@ -1113,10 +1059,7 @@ ERRCODE hb_dbfGetVarLen( DBFAREAP pArea, USHORT uiIndex, ULONG * pLength ) if( !pArea->fValidBuffer && !hb_dbfReadRecord( pArea ) ) return FAILURE; - if( pArea->fHasMemo ) - * pLength = hb_dbfGetMemoLen( pArea, uiIndex - 1 ); - else - * pLength = 0; + * pLength = pArea->lpFields[ uiIndex - 1 ].uiLen; return SUCCESS; } @@ -1124,7 +1067,7 @@ ERRCODE hb_dbfGetVarLen( DBFAREAP pArea, USHORT uiIndex, ULONG * pLength ) /* * Perform a write of WorkArea memory to the data store. */ -ERRCODE hb_dbfGoCold( DBFAREAP pArea ) +static ERRCODE hb_dbfGoCold( DBFAREAP pArea ) { HB_TRACE(HB_TR_DEBUG, ("hb_dbfGoCold(%p)", pArea)); @@ -1154,7 +1097,7 @@ ERRCODE hb_dbfGoCold( DBFAREAP pArea ) /* * Mark the WorkArea data buffer as hot. */ -ERRCODE hb_dbfGoHot( DBFAREAP pArea ) +static ERRCODE hb_dbfGoHot( DBFAREAP pArea ) { PHB_ITEM pError; @@ -1188,7 +1131,7 @@ ERRCODE hb_dbfGoHot( DBFAREAP pArea ) /* * Replace the current record. */ -ERRCODE hb_dbfPutRec( DBFAREAP pArea, BYTE * pBuffer ) +static ERRCODE hb_dbfPutRec( DBFAREAP pArea, BYTE * pBuffer ) { HB_TRACE(HB_TR_DEBUG, ("hb_dbfPutRec(%p, %p)", pArea, pBuffer)); @@ -1203,7 +1146,7 @@ ERRCODE hb_dbfPutRec( DBFAREAP pArea, BYTE * pBuffer ) /* * Assign a value to a field. */ -ERRCODE hb_dbfPutValue( DBFAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) +static ERRCODE hb_dbfPutValue( DBFAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) { USHORT uiSize; LPFIELD pField; @@ -1231,16 +1174,7 @@ ERRCODE hb_dbfPutValue( DBFAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) uiIndex--; pField = pArea->lpFields + uiIndex; if( pField->uiType == HB_IT_MEMO ) - { - if( HB_IS_MEMO( pItem ) || HB_IS_STRING( pItem ) ) - { - hb_cdpTranslate( pItem->item.asString.value, s_cdpage, pArea->cdPage ); - uiError = hb_dbfPutMemo( pArea, uiIndex, pItem ) ? SUCCESS : EDBF_DATAWIDTH; - hb_cdpTranslate( pItem->item.asString.value, pArea->cdPage,s_cdpage ); - } - else - uiError = EDBF_DATATYPE; - } + uiError = EDBF_DATATYPE; else { if( HB_IS_MEMO( pItem ) || HB_IS_STRING( pItem ) ) @@ -1335,10 +1269,10 @@ ERRCODE hb_dbfPutValue( DBFAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) if( uiError != SUCCESS ) { pError = hb_errNew(); - hb_errPutGenCode( pError, uiError == EDBF_DATAWIDTH ? EG_DATAWIDTH : EG_DATATYPE ); - hb_errPutDescription( pError, hb_langDGetErrorDesc( uiError == EDBF_DATAWIDTH ? - EG_DATAWIDTH : EG_DATATYPE ) ); + hb_errPutGenCode( pError, hb_dbfGetEGcode( uiError ) ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( hb_dbfGetEGcode( uiError ) ) ); hb_errPutSubCode( pError, uiError ); + hb_errPutFlags( pError, EF_CANDEFAULT ); SELF_ERROR( ( AREAP ) pArea, pError ); hb_errRelease( pError ); return FAILURE; @@ -1352,7 +1286,7 @@ ERRCODE hb_dbfPutValue( DBFAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) /* * Undelete the current record. */ -ERRCODE hb_dbfRecall( DBFAREAP pArea ) +static ERRCODE hb_dbfRecall( DBFAREAP pArea ) { HB_TRACE(HB_TR_DEBUG, ("hb_dbfRecall(%p)", pArea)); @@ -1378,7 +1312,7 @@ ERRCODE hb_dbfRecall( DBFAREAP pArea ) /* * Obtain number of records in WorkArea. */ -ERRCODE hb_dbfRecCount( DBFAREAP pArea, ULONG * pRecCount ) +static ERRCODE hb_dbfRecCount( DBFAREAP pArea, ULONG * pRecCount ) { HB_TRACE(HB_TR_DEBUG, ("hb_dbfRecCount(%p, %p)", pArea, pRecCount)); @@ -1393,7 +1327,7 @@ ERRCODE hb_dbfRecCount( DBFAREAP pArea, ULONG * pRecCount ) /* * Obtain physical row number at current WorkArea cursor position. */ -ERRCODE hb_dbfRecNo( DBFAREAP pArea, PHB_ITEM pRecNo ) +static ERRCODE hb_dbfRecNo( DBFAREAP pArea, PHB_ITEM pRecNo ) { HB_TRACE(HB_TR_DEBUG, ("hb_dbfRecNo(%p, %p)", pArea, pRecNo)); @@ -1406,7 +1340,7 @@ ERRCODE hb_dbfRecNo( DBFAREAP pArea, PHB_ITEM pRecNo ) /* * Establish the extent of the array of fields for a WorkArea. */ -ERRCODE hb_dbfSetFieldExtent( DBFAREAP pArea, USHORT uiFieldExtent ) +static ERRCODE hb_dbfSetFieldExtent( DBFAREAP pArea, USHORT uiFieldExtent ) { HB_TRACE(HB_TR_DEBUG, ("hb_dbfSetFieldExtent(%p, %hu)", pArea, uiFieldExtent)); @@ -1422,7 +1356,7 @@ ERRCODE hb_dbfSetFieldExtent( DBFAREAP pArea, USHORT uiFieldExtent ) /* * Close the table in the WorkArea. */ -ERRCODE hb_dbfClose( DBFAREAP pArea ) +static ERRCODE hb_dbfClose( DBFAREAP pArea ) { HB_TRACE(HB_TR_DEBUG, ("hb_dbfClose(%p)", pArea)); /* Reset parent rel struct */ @@ -1504,7 +1438,7 @@ ERRCODE hb_dbfClose( DBFAREAP pArea ) /* * Create a data store in the specified WorkArea. */ -ERRCODE hb_dbfCreate( DBFAREAP pArea, LPDBOPENINFO pCreateInfo ) +static ERRCODE hb_dbfCreate( DBFAREAP pArea, LPDBOPENINFO pCreateInfo ) { USHORT uiSize, uiCount; BOOL bHasMemo, bRetry; @@ -1604,6 +1538,8 @@ ERRCODE hb_dbfCreate( DBFAREAP pArea, LPDBOPENINFO pCreateInfo ) pArea->ulRecCount = 0; pArea->uiHeaderLen = sizeof( DBFHEADER ) + uiSize + 2; pArea->fHasMemo = bHasMemo; + pArea->uiMemoBlockSize = 0; + pArea->bVersion = 0x03; /* Write header */ if( SELF_WRITEDBHEADER( ( AREAP ) pArea ) == FAILURE ) @@ -1655,7 +1591,7 @@ ERRCODE hb_dbfCreate( DBFAREAP pArea, LPDBOPENINFO pCreateInfo ) /* * Retrieve information about the current driver. */ -ERRCODE hb_dbfInfo( DBFAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) +static ERRCODE hb_dbfInfo( DBFAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) { HB_TRACE(HB_TR_DEBUG, ("hb_dbfInfo(%p, %hu, %p)", pArea, uiIndex, pItem)); @@ -1691,11 +1627,11 @@ ERRCODE hb_dbfInfo( DBFAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) break; case DBI_MEMOEXT: - hb_itemPutC( pItem, DBF_MEMOEXT ); + hb_itemPutC( pItem, "" ); break; case DBI_MEMOBLOCKSIZE: - hb_itemPutNI( pItem, DBT_BLOCKSIZE ); + hb_itemPutNI( pItem, pArea->uiMemoBlockSize ); break; case DBI_FULLPATH: @@ -1713,6 +1649,7 @@ ERRCODE hb_dbfInfo( DBFAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) case DBI_MEMOHANDLE: hb_itemPutNL( pItem, (LONG)pArea->hMemoFile ); break; + } return SUCCESS; @@ -1721,7 +1658,7 @@ ERRCODE hb_dbfInfo( DBFAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) /* * Clear the WorkArea for use. */ -ERRCODE hb_dbfNewArea( DBFAREAP pArea ) +static ERRCODE hb_dbfNewArea( DBFAREAP pArea ) { HB_TRACE(HB_TR_DEBUG, ("hb_dbfNewArea(%p)", pArea)); @@ -1738,7 +1675,7 @@ ERRCODE hb_dbfNewArea( DBFAREAP pArea ) /* * Open a data store in the WorkArea. */ -ERRCODE hb_dbfOpen( DBFAREAP pArea, LPDBOPENINFO pOpenInfo ) +static ERRCODE hb_dbfOpen( DBFAREAP pArea, LPDBOPENINFO pOpenInfo ) { USHORT uiFlags, uiFields, uiSize, uiCount; BOOL bRetry, bError; @@ -1773,8 +1710,15 @@ ERRCODE hb_dbfOpen( DBFAREAP pArea, LPDBOPENINFO pOpenInfo ) pArea->cdPage = s_cdpage; pArea->fShared = pOpenInfo->fShared; pArea->fReadonly = pOpenInfo->fReadonly; - uiFlags = pOpenInfo->fReadonly ? FO_READ : FO_READWRITE; - uiFlags |= pOpenInfo->fShared ? FO_DENYNONE : FO_EXCLUSIVE; + /* Force exclusive mode + * 0: AUTOSHARE disabled. + * 1: AUTOSHARE enabled. + * 2: force exclusive mode. + * */ + if( hb_set.HB_SET_AUTOSHARE == 2 ) + pArea->fShared = FALSE; + uiFlags = (pArea->fReadonly ? FO_READ : FO_READWRITE) | + (pArea->fShared ? FO_DENYNONE : FO_EXCLUSIVE); pError = NULL; /* Try open */ @@ -1829,6 +1773,7 @@ ERRCODE hb_dbfOpen( DBFAREAP pArea, LPDBOPENINFO pOpenInfo ) /* Open memo file if exists */ if( pArea->fHasMemo ) { + BYTE *tmp; pFileName = hb_fsFNameSplit( ( char * ) pOpenInfo->abName ); pFileExt = hb_itemPutC( NULL, "" ); SELF_INFO( ( AREAP ) pArea, DBI_MEMOEXT, pFileExt ); @@ -1841,15 +1786,18 @@ ERRCODE hb_dbfOpen( DBFAREAP pArea, LPDBOPENINFO pOpenInfo ) strlen( szFileName ) ); hb_itemRelease( pFileExt ); hb_xfree( pFileName ); + tmp = pOpenInfo->abName; pOpenInfo->abName = ( BYTE * ) szFileName; pArea->szMemoFileName = szFileName; /* Open memo file and exit if error */ if( SELF_OPENMEMFILE( ( AREAP ) pArea, pOpenInfo ) == FAILURE ) { + pOpenInfo->abName = tmp; SELF_CLOSE( ( AREAP ) pArea ); return FAILURE; } + pOpenInfo->abName = tmp; } /* Add fields */ @@ -1902,7 +1850,7 @@ ERRCODE hb_dbfOpen( DBFAREAP pArea, LPDBOPENINFO pOpenInfo ) pField = ( LPDBFFIELD ) ( pBuffer + uiCount * sizeof( DBFFIELD ) ); pFieldInfo.atomName = pField->bName; pFieldInfo.atomName[10] = '\0'; - hb_strUpper( (char*) pFieldInfo.atomName,10 ); + hb_strUpper( (char *) pFieldInfo.atomName, 10 ); pFieldInfo.uiLen = pField->bLen; pFieldInfo.uiDec = 0; switch( pField->bType ) @@ -1978,7 +1926,7 @@ ERRCODE hb_dbfOpen( DBFAREAP pArea, LPDBOPENINFO pOpenInfo ) /* * Retrieve the size of the WorkArea structure. */ -ERRCODE hb_dbfStructSize( DBFAREAP pArea, USHORT * uiSize ) +static ERRCODE hb_dbfStructSize( DBFAREAP pArea, USHORT * uiSize ) { HB_TRACE(HB_TR_DEBUG, ("hb_dbfStrucSize(%p, %p)", pArea, uiSize)); HB_SYMBOL_UNUSED( pArea ); @@ -1990,7 +1938,7 @@ ERRCODE hb_dbfStructSize( DBFAREAP pArea, USHORT * uiSize ) /* * Obtain the name of replaceable database driver (RDD) subsystem. */ -ERRCODE hb_dbfSysName( DBFAREAP pArea, BYTE * pBuffer ) +static ERRCODE hb_dbfSysName( DBFAREAP pArea, BYTE * pBuffer ) { HB_TRACE(HB_TR_DEBUG, ("hb_dbfSysName(%p, %p)", pArea, pBuffer)); HB_SYMBOL_UNUSED( pArea ); @@ -2002,7 +1950,7 @@ ERRCODE hb_dbfSysName( DBFAREAP pArea, BYTE * pBuffer ) /* * Remove records marked for deletion from a database. */ -ERRCODE hb_dbfPack( DBFAREAP pArea ) +static ERRCODE hb_dbfPack( DBFAREAP pArea ) { ULONG ulRecIn, ulRecOut, ulEvery, ulUserEvery; PHB_ITEM pError, pBlock; @@ -2087,7 +2035,7 @@ ERRCODE hb_dbfPack( DBFAREAP pArea ) /* * Physically reorder a database. */ -ERRCODE hb_dbfSort( DBFAREAP pArea, LPDBSORTINFO pSortInfo ) +static ERRCODE hb_dbfSort( DBFAREAP pArea, LPDBSORTINFO pSortInfo ) { ULONG ulRecNo; USHORT uiCount; @@ -2114,7 +2062,7 @@ ERRCODE hb_dbfSort( DBFAREAP pArea, LPDBSORTINFO pSortInfo ) { ulRecNo = hb_itemGetNL( pSortInfo->dbtri.dbsci.lNext ); bLimited = TRUE; - bMoreRecords = ( ulRecNo >= 0 ); + bMoreRecords = ( ulRecNo > 0 ); } else { @@ -2186,7 +2134,7 @@ ERRCODE hb_dbfSort( DBFAREAP pArea, LPDBSORTINFO pSortInfo ) /* * Copy one or more records from one WorkArea to another. */ -ERRCODE hb_dbfTrans( DBFAREAP pArea, LPDBTRANSINFO pTransInfo ) +static ERRCODE hb_dbfTrans( DBFAREAP pArea, LPDBTRANSINFO pTransInfo ) { PHB_ITEM pPutRec; @@ -2206,7 +2154,7 @@ ERRCODE hb_dbfTrans( DBFAREAP pArea, LPDBTRANSINFO pTransInfo ) /* * Copy a record to another WorkArea. */ -ERRCODE hb_dbfTransRec( DBFAREAP pArea, LPDBTRANSINFO pTransInfo ) +static ERRCODE hb_dbfTransRec( DBFAREAP pArea, LPDBTRANSINFO pTransInfo ) { BOOL bDeleted; @@ -2240,7 +2188,7 @@ ERRCODE hb_dbfTransRec( DBFAREAP pArea, LPDBTRANSINFO pTransInfo ) /* * Physically remove all records from data store. */ -ERRCODE hb_dbfZap( DBFAREAP pArea ) +static ERRCODE hb_dbfZap( DBFAREAP pArea ) { PHB_ITEM pError; @@ -2267,8 +2215,8 @@ ERRCODE hb_dbfZap( DBFAREAP pArea ) /* Zap memo file */ if( pArea->fHasMemo ) { - SELF_CREATEMEMFILE( ( AREAP ) pArea, NULL ); - hb_fsWrite( pArea->hMemoFile, NULL, 0 ); + if ( SELF_CREATEMEMFILE( ( AREAP ) pArea, NULL ) == FAILURE ) + return FAILURE; } return SUCCESS; } @@ -2276,7 +2224,7 @@ ERRCODE hb_dbfZap( DBFAREAP pArea ) /* * Report end of relation. */ -ERRCODE hb_dbfChildEnd( DBFAREAP pArea, LPDBRELINFO pRelInfo ) +static ERRCODE hb_dbfChildEnd( DBFAREAP pArea, LPDBRELINFO pRelInfo ) { ERRCODE uiError; @@ -2293,7 +2241,7 @@ ERRCODE hb_dbfChildEnd( DBFAREAP pArea, LPDBRELINFO pRelInfo ) /* * Report initialization of a relation. */ -ERRCODE hb_dbfChildStart( DBFAREAP pArea, LPDBRELINFO pRelInfo ) +static ERRCODE hb_dbfChildStart( DBFAREAP pArea, LPDBRELINFO pRelInfo ) { HB_TRACE(HB_TR_DEBUG, ("hb_dbfChildStart(%p, %p)", pArea, pRelInfo)); @@ -2304,7 +2252,7 @@ ERRCODE hb_dbfChildStart( DBFAREAP pArea, LPDBRELINFO pRelInfo ) /* * Post a pending relational movement. */ -ERRCODE hb_dbfChildSync( DBFAREAP pArea, LPDBRELINFO pRelInfo ) +static ERRCODE hb_dbfChildSync( DBFAREAP pArea, LPDBRELINFO pRelInfo ) { HB_TRACE(HB_TR_DEBUG, ("hb_dbfChildSync(%p, %p)", pArea, pRelInfo)); @@ -2317,7 +2265,7 @@ ERRCODE hb_dbfChildSync( DBFAREAP pArea, LPDBRELINFO pRelInfo ) /* * Force relational seeks in the specified WorkArea. */ -ERRCODE hb_dbfForceRel( DBFAREAP pArea ) +static ERRCODE hb_dbfForceRel( DBFAREAP pArea ) { LPDBRELINFO lpdbPendingRel; ERRCODE uiError; @@ -2350,7 +2298,7 @@ ERRCODE hb_dbfForceRel( DBFAREAP pArea ) /* * Set the filter condition for the specified WorkArea. */ -ERRCODE hb_dbfSetFilter( DBFAREAP pArea, LPDBFILTERINFO pFilterInfo ) +static ERRCODE hb_dbfSetFilter( DBFAREAP pArea, LPDBFILTERINFO pFilterInfo ) { HB_TRACE(HB_TR_DEBUG, ("hb_dbfSetFilter(%p, %p)", pArea, pFilterInfo)); @@ -2359,10 +2307,56 @@ ERRCODE hb_dbfSetFilter( DBFAREAP pArea, LPDBFILTERINFO pFilterInfo ) return SUPER_SETFILTER( ( AREAP ) pArea, pFilterInfo ); } +/* + * Perform a network lowlevel lock in the specified WorkArea. + */ +static ERRCODE hb_dbfRawLock( DBFAREAP pArea, USHORT uiAction, ULONG ulRecNo ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_dbfRawLock(%p, %hu, %lu)", pArea, uiAction, ulRecNo)); + + switch( uiAction ) + { + case FILE_LOCK: + if( pArea->fShared && !pArea->fFLocked ) + pArea->fFLocked = hb_fsLock( pArea->hDataFile, DBF_LOCKPOS + 1, DBF_LOCKPOS, FL_LOCK ); + break; + + case FILE_UNLOCK: + if( pArea->fShared && pArea->fFLocked ) + pArea->fFLocked = !hb_fsLock( pArea->hDataFile, DBF_LOCKPOS + 1, DBF_LOCKPOS, FL_UNLOCK ); + break; + + case APPEND_LOCK: + case REC_LOCK: + if( pArea->fShared && !pArea->fFLocked ) + if( !hb_fsLock( pArea->hDataFile, DBF_LOCKPOS + ulRecNo, 1, FL_LOCK ) ) + return FAILURE; + break; + + case APPEND_UNLOCK: + case REC_UNLOCK: + if( pArea->fShared && !pArea->fFLocked ) + if( !hb_fsLock( pArea->hDataFile, DBF_LOCKPOS + ulRecNo, 1, FL_UNLOCK ) ) + return FAILURE; + break; + case HEADER_LOCK: + if( pArea->fShared && !pArea->fFLocked ) + if( !hb_fsLock( pArea->hDataFile, DBF_LOCKPOS, 1, FL_LOCK ) ) + return FAILURE; + break; + case HEADER_UNLOCK: + if( pArea->fShared && !pArea->fFLocked ) + if( !hb_fsLock( pArea->hDataFile, DBF_LOCKPOS, 1, FL_UNLOCK ) ) + return FAILURE; + break; + } + return SUCCESS; +} + /* * Perform a network lock in the specified WorkArea. */ -ERRCODE hb_dbfLock( DBFAREAP pArea, LPDBLOCKINFO pLockInfo ) +static ERRCODE hb_dbfLock( DBFAREAP pArea, LPDBLOCKINFO pLockInfo ) { HB_TRACE(HB_TR_DEBUG, ("hb_dbfLock(%p, %p)", pArea, pLockInfo)); @@ -2395,7 +2389,7 @@ ERRCODE hb_dbfLock( DBFAREAP pArea, LPDBLOCKINFO pLockInfo ) /* * Release network locks in the specified WorkArea. */ -ERRCODE hb_dbfUnLock( DBFAREAP pArea, ULONG ulRecNo ) +static ERRCODE hb_dbfUnLock( DBFAREAP pArea, ULONG ulRecNo ) { ERRCODE uiError; @@ -2426,114 +2420,62 @@ ERRCODE hb_dbfUnLock( DBFAREAP pArea, ULONG ulRecNo ) /* * Create a memo file in the WorkArea. */ -ERRCODE hb_dbfCreateMemFile( DBFAREAP pArea, LPDBOPENINFO pCreateInfo ) +static ERRCODE hb_dbfCreateMemFile( DBFAREAP pArea, LPDBOPENINFO pCreateInfo ) { - BYTE pBlock[ DBT_BLOCKSIZE ]; - BOOL bRetry; PHB_ITEM pError; HB_TRACE(HB_TR_DEBUG, ("hb_dbfCreateMemFile(%p, %p)", pArea, pCreateInfo)); if( pCreateInfo ) { - pError = NULL; - /* Try create */ - do - { - pArea->hMemoFile = hb_spCreate( pCreateInfo->abName, FC_NORMAL ); - if( pArea->hMemoFile == FS_ERROR ) - { - if( !pError ) - { - pError = hb_errNew(); - hb_errPutGenCode( pError, EG_CREATE ); - hb_errPutSubCode( pError, EDBF_CREATE_DBF ); - hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_CREATE ) ); - hb_errPutFileName( pError, ( char * ) pCreateInfo->abName ); - hb_errPutFlags( pError, EF_CANRETRY ); - } - bRetry = ( SELF_ERROR( ( AREAP ) pArea, pError ) == E_RETRY ); - } - else - bRetry = FALSE; - } while( bRetry ); - if( pError ) - hb_errRelease( pError ); - - if( pArea->hMemoFile == FS_ERROR ) - return FAILURE; + pError = hb_errNew(); + hb_errPutGenCode( pError, EG_DATATYPE ); + hb_errPutSubCode( pError, EDBF_DATATYPE ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_CREATE ) ); + hb_errPutFileName( pError, ( char * ) pCreateInfo->abName ); + SELF_ERROR( ( AREAP ) pArea, pError ); + hb_errRelease( pError ); } - 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; - hb_fsWrite( pArea->hMemoFile, NULL, 0 ); - return SUCCESS; + pArea->fHasMemo = FALSE; + return FAILURE; } /* * Open a memo file in the specified WorkArea. */ -ERRCODE hb_dbfOpenMemFile( DBFAREAP pArea, LPDBOPENINFO pOpenInfo ) +static ERRCODE hb_dbfOpenMemFile( DBFAREAP pArea, LPDBOPENINFO pOpenInfo ) { - USHORT uiFlags; - BOOL bRetry; PHB_ITEM pError; HB_TRACE(HB_TR_DEBUG, ("hb_dbfOpenMemFile(%p, %p)", pArea, pOpenInfo)); - uiFlags = pOpenInfo->fReadonly ? FO_READ : FO_READWRITE; - uiFlags |= pOpenInfo->fShared ? FO_DENYNONE : FO_EXCLUSIVE; - pError = NULL; - - /* Try open */ - do - { - pArea->hMemoFile = hb_spOpen( pOpenInfo->abName, uiFlags ); - if( pArea->hMemoFile == FS_ERROR ) - { - if( !pError ) - { - pError = hb_errNew(); - hb_errPutGenCode( pError, EG_OPEN ); - hb_errPutSubCode( pError, EDBF_OPEN_DBF ); - hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_OPEN ) ); - hb_errPutFileName( pError, ( char * ) pOpenInfo->abName ); - hb_errPutFlags( pError, EF_CANRETRY | EF_CANDEFAULT ); - } - bRetry = ( SELF_ERROR( ( AREAP ) pArea, pError ) == E_RETRY ); - } - else - bRetry = FALSE; - } while( bRetry ); - if( pError ) - { - hb_errRelease( pError ); - } - return ( pArea->hMemoFile == FS_ERROR ? FAILURE : SUCCESS ); + pError = hb_errNew(); + hb_errPutGenCode( pError, EG_OPEN ); + hb_errPutSubCode( pError, EDBF_OPEN_DBF ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_OPEN ) ); + hb_errPutFileName( pError, ( char * ) pOpenInfo->abName ); + SELF_ERROR( ( AREAP ) pArea, pError ); + hb_errRelease( pError ); + return FAILURE; } - /* * Read the database file header record in the WorkArea. */ -ERRCODE hb_dbfReadDBHeader( DBFAREAP pArea ) +static ERRCODE hb_dbfReadDBHeader( DBFAREAP pArea ) { DBFHEADER dbHeader; BOOL bRetry, bError; PHB_ITEM pError; - HB_TRACE(HB_TR_DEBUG, ("hb_dbfReadHeader(%p)", pArea)); + HB_TRACE(HB_TR_DEBUG, ("hb_dbfReadDBHeader(%p)", pArea)); pError = NULL; /* Try read */ do { hb_fsSeek( pArea->hDataFile, 0, FS_SET ); - if( hb_fsRead( pArea->hDataFile, ( BYTE * ) &dbHeader, sizeof( DBFHEADER ) ) != - sizeof( DBFHEADER ) || ( dbHeader.bVersion != 0x03 && dbHeader.bVersion != 0x83 ) ) + if( hb_fsRead( pArea->hDataFile, ( BYTE * ) &dbHeader, sizeof( DBFHEADER ) ) != sizeof( DBFHEADER ) || + ( dbHeader.bVersion != 0x03 && dbHeader.bVersion != 0x83 && dbHeader.bVersion != 0xF5 ) ) { bError = TRUE; if( !pError ) @@ -2561,18 +2503,19 @@ ERRCODE hb_dbfReadDBHeader( DBFAREAP pArea ) pArea->bDay = dbHeader.bDay; pArea->bMonth = dbHeader.bMonth; pArea->bYear = dbHeader.bYear; - pArea->uiHeaderLen = dbHeader.uiHeaderLen; - pArea->ulRecCount = dbHeader.ulRecCount; - pArea->fHasMemo = ( dbHeader.bVersion == 0x83 ); pArea->fHasTags = dbHeader.bHasTags; + pArea->bVersion = dbHeader.bVersion; pArea->bCodePage = dbHeader.bCodePage; + pArea->uiHeaderLen = HB_USHORT_FROM_LE( dbHeader.uiHeaderLen ); + pArea->ulRecCount = HB_ULONG_FROM_LE( dbHeader.ulRecCount ); + pArea->fHasMemo = FALSE; return SUCCESS; } /* * Write the database file header record in the WorkArea. */ -ERRCODE hb_dbfWriteDBHeader( DBFAREAP pArea ) +static ERRCODE hb_dbfWriteDBHeader( DBFAREAP pArea ) { DBFHEADER dbfHeader; long lYear, lMonth, lDay; @@ -2580,7 +2523,7 @@ ERRCODE hb_dbfWriteDBHeader( DBFAREAP pArea ) HB_TRACE(HB_TR_DEBUG, ("hb_dbfWriteDBHeader(%p)", pArea)); memset( &dbfHeader, 0, sizeof( DBFHEADER ) ); - dbfHeader.bVersion = pArea->fHasMemo ? 0x83 : 0x03; + dbfHeader.bVersion = pArea->bVersion; hb_dateToday( &lYear, &lMonth, &lDay ); dbfHeader.bYear = ( BYTE ) ( lYear - 1900 ); dbfHeader.bMonth = ( BYTE ) lMonth; @@ -2591,22 +2534,22 @@ ERRCODE hb_dbfWriteDBHeader( DBFAREAP pArea ) /* Update record count */ if( pArea->fShared ) { - hb_fsLock( pArea->hDataFile, DBF_LOCKPOS, 1, FL_LOCK ); + SELF_RAWLOCK( ( AREAP ) pArea, HEADER_LOCK, 0 ); pArea->ulRecCount = hb_dbfCalcRecCount( pArea ); } - dbfHeader.ulRecCount = pArea->ulRecCount; - dbfHeader.uiHeaderLen = pArea->uiHeaderLen; - dbfHeader.uiRecordLen = pArea->uiRecordLen; + HB_PUT_LE_ULONG( &dbfHeader.ulRecCount, pArea->ulRecCount ); + HB_PUT_LE_USHORT( &dbfHeader.uiHeaderLen, pArea->uiHeaderLen ); + HB_PUT_LE_USHORT( &dbfHeader.uiRecordLen, pArea->uiRecordLen ); hb_fsSeek( pArea->hDataFile, 0, FS_SET ); hb_fsWrite( pArea->hDataFile, ( BYTE * ) &dbfHeader, sizeof( DBFHEADER ) ); - if( pArea->fShared ) - hb_fsLock( pArea->hDataFile, DBF_LOCKPOS, 1, FL_UNLOCK ); pArea->fUpdateHeader = FALSE; + if( pArea->fShared ) + SELF_RAWLOCK( ( AREAP ) pArea, HEADER_UNLOCK, 0 ); return SUCCESS; } -ERRCODE hb_dbfDrop( PHB_ITEM pItemTable ) +static ERRCODE hb_dbfDrop( PHB_ITEM pItemTable ) { BYTE * pBuffer; char szFileName[ _POSIX_PATH_MAX + 1 ]; diff --git a/harbour/source/rdd/dbfcdx/dbfcdx0.prg b/harbour/source/rdd/dbfcdx/dbfcdx0.prg index a01c34367b..41f03d5def 100644 --- a/harbour/source/rdd/dbfcdx/dbfcdx0.prg +++ b/harbour/source/rdd/dbfcdx/dbfcdx0.prg @@ -4,10 +4,11 @@ /* * Harbour Project source code: - * DBFCDX RDD + * DBFCDX RDD (ver.2) * * Copyright 1999 Bruno Cantero - * www - http://www.harbour-project.org + * Copyright 2003 Przemyslaw Czerpak + * www - http://www.xharbour.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 @@ -50,12 +51,11 @@ * */ -#include "error.ch" #include "rddsys.ch" ANNOUNCE DBFCDX -init procedure DBFCDXInit +procedure DBFCDXInit REQUEST _DBFCDX diff --git a/harbour/source/rdd/dbfcdx/dbfcdx1.c b/harbour/source/rdd/dbfcdx/dbfcdx1.c index 7dcd7b0c99..8c2480dba0 100644 --- a/harbour/source/rdd/dbfcdx/dbfcdx1.c +++ b/harbour/source/rdd/dbfcdx/dbfcdx1.c @@ -3,13 +3,14 @@ */ /* - * Harbour Project source code: - * DBFCDX RDD + * xHarbour Project source code: + * DBFCDX RDD (ver.2) * * Copyright 1999-2002 Bruno Cantero * Copyright 2000-2003 Horacio Roldan (portions) - * Copyright 2003 Przemyslaw Czerpak (portions) - * www - http://www.harbour-project.org + * Copyright 2003 Przemyslaw Czerpak - all code except + * hb_cdxTagDoIndex and related hb_cdxSort* rewritten. + * www - http://www.xharbour.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 @@ -51,100 +52,21 @@ * If you do not wish that, delete this exception notice. * */ -/* - * Functions added by Horacio Roldan - * -hb_cdxPack -hb_cdxDBOIKeyNo -hb_cdxDBOIKeyCount -hb_cdxGetActiveTag -hb_cdxFindTag - -hb_cdxClearScope -hb_cdxScopeInfo -hb_cdxSetScope -hb_cdxTopScope -hb_cdxBottomScope -hb_cdxTagClearScope - -hb_cdxOrderDestroy -hb_cdxIndexDelTag - -hb_cdxSortSwapSavePage -hb_cdxSortSwapFillPage -hb_cdxSortSwapRecurseDict -hb_cdxSortSwapSendWord -hb_cdxSortSwapBuildIndex -hb_cdxSortSwapGetNextKey - -hb_cdxGetTagByNumber -hb_cdxGetTagNumber -hb_cdxKeyGetItem -hb_cdxReorderTagList -hb_cdxGoEof -hb_cdxIndexCheckVersion -hb_cdxIndexUnLockRead -hb_cdxIndexLockRead -hb_cdxIndexLockWrite -hb_cdxIndexUnLockWrite -hb_cdxIndexDelTag - -hb_cdxKeyValCompare -hb_cdxMacroRun -cdxError -hb_cdxOrderListRebuild -hb_cdxIndexReindex -hb_cdxOrdListClear -hb_cdxFindBag -hb_cdxEvalKey -hb_cdxEvalCond - * - */ - -/* #define __XHARBOUR__ */ - -#define XDBFCDX +#define HB_CDX_DBGCODE_OFF +//#define HB_CDX_DSPDBG_INFO +//#define HB_CDP_SUPPORT_OFF +//#define HB_CDX_DBGTIME #include "hbapi.h" #include "hbinit.h" -#include "hbvm.h" -#include "hbstack.h" -#include "hbapiitm.h" -#include "hbdbf.h" #include "hbapierr.h" #include "hbapilng.h" +#include "hbvm.h" #include "hbset.h" -#include "hbdate.h" -#include "error.ch" - -//#define HB_CDX_DBGCODE_OFF -//#define HB_LONG_LONG_OFF -//#define HB_CDP_SUPPORT_OFF - -#ifndef HB_CDP_SUPPORT_OFF - /* for nation sorting support */ - #include "hbapicdp.h" - extern PHB_CODEPAGE s_cdpage; - #define hb_cdpcharcmp( c1, c2 ) ( ( s_cdpage && s_cdpage->lSort ) ? \ - hb_cdpchrcmp( c1, c2, s_cdpage ) : \ - ( (BYTE)(c1) - (BYTE)(c2) ) ) -// #define hb_cdpcharcmp( c1, c2 ) ( (BYTE)(c1) - (BYTE)(c2) ) -#endif - -#include "dbfcdx1.h" #include "hbrddcdx.h" -#include "dbfcdx2.h" #define __PRG_SOURCE__ __FILE__ - -//#include "xfpt2.h" - - - -extern HB_FUNC( _DBFCDX ); -extern HB_FUNC( DBFCDX_GETFUNCTABLE ); - #ifndef __XHARBOUR__ #define HB_VM_STACK hb_stack #endif @@ -153,6 +75,233 @@ extern HB_FUNC( DBFCDX_GETFUNCTABLE ); #define HB_PRG_PCODE_VER HB_PCODE_VER #endif +#ifndef HB_CDP_SUPPORT_OFF + /* for nation sorting support */ + #include "hbapicdp.h" + extern PHB_CODEPAGE s_cdpage; + #define hb_cdpcharcmp( c1, c2, cdpage ) \ + ( ( cdpage && cdpage->lSort ) ? \ + hb_cdpchrcmp( c1, c2, cdpage ) : \ + ( (BYTE)(c1) - (BYTE)(c2) ) ) +/* + #define hb_cdpcharcmp( c1, c2, cdpage ) ( (BYTE)(c1) - (BYTE)(c2) ) + */ +#endif + + +/* + * TODO: !!! hb_cdxFindTag doesn't use bag name! + * TODO: Tag->fRePos = TURE means that rootPage->...->childLeafPage path is + * bad and has to be reloaded + * CurKey->rec == 0 means that there is no correct CurKey + */ + +/* create a new Tag (make index) */ +static void hb_cdxTagDoIndex( LPCDXTAG pTag ); + +/* Close Tag */ +static void hb_cdxTagClose( LPCDXTAG pTag ); + +/* free Tag pages from cache */ +static void hb_cdxTagPoolFree( LPCDXTAG pTag, int nPagesLeft ); + +/* Store tag header to index files */ +static void hb_cdxTagHeaderStore( LPCDXTAG pTag ); + +/* write all changed pages in tag cache */ +static void hb_cdxTagPoolFlush( LPCDXTAG pTag ); + +/* Discard all pages in cache (TagClose and TagPoolFree for all Tags) */ +static void hb_cdxIndexDiscardBuffers( LPCDXINDEX pIndex ); + +/* write all changed pages in cache (pagePool and Tag Header) */ +static void hb_cdxIndexFlushBuffers( LPCDXINDEX pIndex ); + +/* free cached pages of index file */ +static void hb_cdxIndexPoolFree( LPCDXINDEX pIndex, int nPagesLeft ); + +/* split Root Page */ +static int hb_cdxPageRootSplit( LPCDXPAGE pPage ); + +static LPCDXKEY hb_cdxKeyNew( void ); + +static RDDFUNCS cdxSuper; +static RDDFUNCS cdxTable = +{ + + /* Movement and positioning methods */ + + ( 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, + + + /* Data management */ + + ( 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, + + + /* WorkArea/Database management */ + + ( 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, + + + /* Relational Methods */ + + ( 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, + + + /* Order Management */ + + ( 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, + + + /* Filters and Scope Settings */ + + ( DBENTRYP_V ) hb_cdxClearFilter, + ( DBENTRYP_V ) hb_cdxClearLocate, + ( DBENTRYP_V ) hb_cdxClearScope, + ( DBENTRYP_VPLP ) hb_cdxCountScope, + ( DBENTRYP_I ) hb_cdxFilterText, + ( DBENTRYP_SI ) hb_cdxScopeInfo, + ( DBENTRYP_VFI ) hb_cdxSetFilter, + ( DBENTRYP_VLO ) hb_cdxSetLocate, + ( DBENTRYP_VOS ) hb_cdxSetScope, + ( DBENTRYP_VPL ) hb_cdxSkipScope, + + + /* Miscellaneous */ + + ( DBENTRYP_P ) hb_cdxCompile, + ( DBENTRYP_I ) hb_cdxError, + ( DBENTRYP_I ) hb_cdxEvalBlock, + + + /* Network operations */ + + ( DBENTRYP_VSP ) hb_cdxRawLock, + ( DBENTRYP_VL ) hb_cdxLock, + ( DBENTRYP_UL ) hb_cdxUnLock, + + + /* Memofile functions */ + + ( DBENTRYP_V ) hb_cdxCloseMemFile, + ( DBENTRYP_VP ) hb_cdxCreateMemFile, + ( DBENTRYP_SVPB ) hb_cdxGetValueFile, + ( DBENTRYP_VP ) hb_cdxOpenMemFile, + ( DBENTRYP_SVP ) hb_cdxPutValueFile, + + + /* Database file header handling */ + + ( DBENTRYP_V ) hb_cdxReadDBHeader, + ( DBENTRYP_V ) hb_cdxWriteDBHeader, + + + /* non WorkArea functions */ + ( DBENTRYP_I0 ) hb_cdxExit, + ( DBENTRYP_I1 ) hb_cdxDrop, + ( DBENTRYP_I2 ) hb_cdxExists, + + + /* Special and reserved methods */ + + ( DBENTRYP_SVP ) hb_cdxWhoCares +}; + + +HB_FUNC( _DBFCDX ) {;} + +HB_FUNC( DBFCDX_GETFUNCTABLE ) +{ + RDDFUNCS * pTable; + USHORT * uiCount; + + uiCount = ( USHORT * ) hb_itemGetPtr( hb_param( 1, HB_IT_POINTER ) ); + pTable = ( RDDFUNCS * ) hb_itemGetPtr( hb_param( 2, HB_IT_POINTER ) ); + + HB_TRACE(HB_TR_DEBUG, ("DBFCDX_GETFUNCTABLE(%i, %p)", uiCount, pTable)); + + if ( pTable ) + { + SHORT iRet; + + if ( uiCount ) + * uiCount = RDDFUNCSCOUNT; + iRet = hb_rddInherit( pTable, &cdxTable, &cdxSuper, ( BYTE * ) "DBFFPT" ); + if ( iRet == FAILURE ) + iRet = hb_rddInherit( pTable, &cdxTable, &cdxSuper, ( BYTE * ) "DBFDBT" ); + if ( iRet == FAILURE ) + iRet = hb_rddInherit( pTable, &cdxTable, &cdxSuper, ( BYTE * ) "DBF" ); + hb_retni( iRet ); + } + else + hb_retni( FAILURE ); +} + + HB_INIT_SYMBOLS_BEGIN( dbfcdx1__InitSymbols ) { "_DBFCDX", HB_FS_PUBLIC, HB_FUNCNAME( _DBFCDX ), NULL }, { "DBFCDX_GETFUNCTABLE", HB_FS_PUBLIC, HB_FUNCNAME( DBFCDX_GETFUNCTABLE ), NULL } @@ -173,1308 +322,314 @@ HB_INIT_SYMBOLS_END( dbfcdx1__InitSymbols ) #pragma startup dbfcdx1__InitSymbols #endif -static USHORT s_uiMemoBlockSize = 64; /* Default block memo size */ - -static RDDFUNCS cdxSuper ;//= { NULL }; - -static RDDFUNCS cdxTable = { ( DBENTRYP_BP ) hb_cdxBof, - ( DBENTRYP_BP ) hb_cdxEof, - ( DBENTRYP_BP ) hb_cdxFound, - ( DBENTRYP_V ) hb_cdxGoBottom, - ( DBENTRYP_UL ) hb_cdxGoTo, - ( DBENTRYP_I ) hb_cdxGoToId, - ( DBENTRYP_V ) hb_cdxGoTop, - ( DBENTRYP_BIB ) hb_cdxSeek, - ( DBENTRYP_L ) hb_cdxSkip, - ( DBENTRYP_L ) hb_cdxSkipFilter, - ( DBENTRYP_L ) hb_cdxSkipRaw, - ( DBENTRYP_VF ) hb_cdxAddField, - ( DBENTRYP_B ) hb_cdxAppend, - ( DBENTRYP_I ) hb_cdxCreateFields, - ( DBENTRYP_V ) hb_cdxDeleteRec, - ( DBENTRYP_BP ) hb_cdxDeleted, - ( DBENTRYP_SP ) hb_cdxFieldCount, - ( DBENTRYP_VF ) hb_cdxFieldDisplay, - ( DBENTRYP_SSI ) hb_cdxFieldInfo, - ( DBENTRYP_SVP ) hb_cdxFieldName, - ( DBENTRYP_V ) hb_cdxFlush, - ( DBENTRYP_PP ) hb_cdxGetRec, - ( DBENTRYP_SI ) hb_cdxGetValue, - ( DBENTRYP_SVL ) hb_cdxGetVarLen, - ( DBENTRYP_V ) hb_cdxGoCold, - ( DBENTRYP_V ) hb_cdxGoHot, - ( DBENTRYP_P ) hb_cdxPutRec, - ( DBENTRYP_SI ) hb_cdxPutValue, - ( DBENTRYP_V ) hb_cdxRecall, - ( DBENTRYP_ULP ) hb_cdxRecCount, - ( DBENTRYP_ISI ) hb_cdxRecInfo, - ( DBENTRYP_I ) hb_cdxRecNo, - ( DBENTRYP_S ) hb_cdxSetFieldExtent, - ( DBENTRYP_P ) hb_cdxAlias, - ( DBENTRYP_V ) hb_cdxClose, - ( DBENTRYP_VP ) hb_cdxCreate, - ( DBENTRYP_SI ) hb_cdxInfo, - ( DBENTRYP_V ) hb_cdxNewArea, - ( DBENTRYP_VP ) hb_cdxOpen, - ( DBENTRYP_V ) hb_cdxRelease, - ( DBENTRYP_SP ) hb_cdxStructSize, - ( DBENTRYP_P ) hb_cdxSysName, - ( DBENTRYP_VEI ) hb_cdxEval, - ( DBENTRYP_V ) hb_cdxPack, - ( DBENTRYP_LSP ) hb_cdxPackRec, - ( DBENTRYP_VS ) hb_cdxSort, - ( DBENTRYP_VT ) hb_cdxTrans, - ( DBENTRYP_VT ) hb_cdxTransRec, - ( DBENTRYP_V ) hb_cdxZap, - ( DBENTRYP_VR ) hb_cdxChildEnd, - ( DBENTRYP_VR ) hb_cdxChildStart, - ( DBENTRYP_VR ) hb_cdxChildSync, - ( DBENTRYP_V ) hb_cdxSyncChildren, - ( DBENTRYP_V ) hb_cdxClearRel, - ( DBENTRYP_V ) hb_cdxForceRel, - ( DBENTRYP_SVP ) hb_cdxRelArea, - ( DBENTRYP_VR ) hb_cdxRelEval, - ( DBENTRYP_SVP ) hb_cdxRelText, - ( DBENTRYP_VR ) hb_cdxSetRel, - ( DBENTRYP_OI ) hb_cdxOrderListAdd, - ( DBENTRYP_V ) hb_cdxOrderListClear, - ( DBENTRYP_VP ) hb_cdxOrderListDelete, - ( DBENTRYP_OI ) hb_cdxOrderListFocus, - ( DBENTRYP_V ) hb_cdxOrderListRebuild, - ( DBENTRYP_VOI ) hb_cdxOrderCondition, - ( DBENTRYP_VOC ) hb_cdxOrderCreate, - ( DBENTRYP_OI ) hb_cdxOrderDestroy, - ( DBENTRYP_OII ) hb_cdxOrderInfo, - ( DBENTRYP_V ) hb_cdxClearFilter, - ( DBENTRYP_V ) hb_cdxClearLocate, - ( DBENTRYP_V ) hb_cdxClearScope, - ( DBENTRYP_VPLP ) hb_cdxCountScope, - ( DBENTRYP_I ) hb_cdxFilterText, - ( DBENTRYP_SI ) hb_cdxScopeInfo, - ( DBENTRYP_VFI ) hb_cdxSetFilter, - ( DBENTRYP_VLO ) hb_cdxSetLocate, - ( DBENTRYP_VOS ) hb_cdxSetScope, - ( DBENTRYP_VPL ) hb_cdxSkipScope, - ( DBENTRYP_P ) hb_cdxCompile, - ( DBENTRYP_I ) hb_cdxError, - ( DBENTRYP_I ) hb_cdxEvalBlock, - ( DBENTRYP_VSP ) hb_cdxRawLock, - ( DBENTRYP_VL ) hb_cdxLock, - ( DBENTRYP_UL ) hb_cdxUnLock, - ( DBENTRYP_V ) hb_cdxCloseMemFile, - ( DBENTRYP_VP ) hb_cdxCreateMemFile, - ( DBENTRYP_SVPB ) hb_cdxGetValueFile, - ( DBENTRYP_VP ) hb_cdxOpenMemFile, - ( DBENTRYP_SVP ) hb_cdxPutValueFile, - ( DBENTRYP_V ) hb_cdxReadDBHeader, - ( DBENTRYP_V ) hb_cdxWriteDBHeader, - /* ( DBENTRYP_SVP ) hb_cdxWhoCares */ - 0,0,0,0 - }; - - -static long hb_cdxDBOIKeyCount( CDXAREAP pArea, LPCDXTAG pTag, int iFilters ); -static long hb_cdxDBOIKeyNo( CDXAREAP pArea, LPCDXTAG pTag, int iFilters ); - -static ULONG hb_xfptWriteItemSx( FHANDLE hMemoFile, PHB_ITEM pItem ); -static ULONG hb_xfptWriteItemSxLength( PHB_ITEM pItem ); -static void hb_xfptReadItemSx( FHANDLE hMemoFile, PHB_ITEM pItem ); - - -/* - * Common functions. - */ - -static LONG hb_cdxMakeMask( BYTE bByte ) +#ifdef HB_CDX_DSPDBG_INFO +static void hb_cdxDspTags( LPCDXINDEX pIndex ) { - BYTE bCount; - LONG lMask; + LPCDXTAG pTag = NULL; - for( lMask = 0, bCount = 1; bCount <= bByte; bCount++, - lMask = ( lMask << 1 ) + 1 ); - - return lMask; -} - -static void hb_cdxDNtoSort( double dValue, BYTE * szBuffer ) -{ - int i; - BYTE * pTemp; - -/* HB_TRACE(HB_TR_DEBUG, ("hb_cdxDNtoSort(%ld, %p)", lValue, szBuffer)); */ - - pTemp = ( BYTE* ) &dValue; - - if( dValue < 0 ) + printf( "\r\n*TAGS*" ); + while ( pIndex ) { - for( i = 7 ; i >= 0 ; i--, pTemp++) - szBuffer[ i ] = ( *pTemp ) ^ (BYTE) 0xFF; - } - else - { - for( i = 7 ; i >= 0 ; i--, pTemp++) - szBuffer[i] = ( *pTemp ); - - szBuffer[ 0 ] ^= 0x80; - } -} - -static double hb_cdxSorttoND( BYTE * szBuffer, USHORT uiLen ) -{ - double dNumber; - int i; - BYTE * pTemp; - - pTemp = ( BYTE* ) &dNumber; - pTemp += 7; - - if( szBuffer[ 0 ] & 0x80 ) /* >0 */ - { - for( i = 0 ; i < 8 ; i++, pTemp-- ) + printf( "\r\nBAG: [%s] ->", pIndex->szFileName ); + pTag = pIndex->TagList; + while ( pTag ) { - /* if( i < 8 - uiLen ) */ - - if( i >= uiLen ) - ( *pTemp ) = 0; - else - ( *pTemp ) = szBuffer[ i ]; + printf( " {%s}", pTag->szName ); + pTag = pTag->pNext; } - - pTemp += 8; - ( *pTemp ) ^= 0x80; - } - else - { - for( i = 0 ; i < 8 ; i++, pTemp-- ) - { - /* if( i < 8 - uiLen ) */ - if( i >= uiLen ) - ( *pTemp ) = 0; - else - ( *pTemp ) = szBuffer[ i ] ^ (BYTE) 0xFF; - } - } - - return dNumber; -} - -/* - * Swap bytes. - */ -ULONG hb_cdxSwapBytes( ULONG ulLong ) -{ - BYTE * pLong, bByte; - - HB_TRACE(HB_TR_DEBUG, ("hb_cdxSwapBytes(%lu)", ulLong)); - - pLong = ( BYTE * ) &ulLong; - bByte = pLong[ 0 ]; - pLong[ 0 ] = pLong[ 3 ]; - pLong[ 3 ] = bByte; - bByte = pLong[ 1 ]; - pLong[ 1 ] = pLong[ 2 ]; - pLong[ 2 ] = bByte; - - return ulLong; -} - -/* hb_cdx memo */ -/* #include "cdxmemo.c" */ - -/* - * Converts memo block offset into ASCII. - */ -static ULONG hb_cdxGetMemoBlock( CDXAREAP pArea, USHORT uiIndex ) -{ - USHORT uiCount; - BYTE bByte; - ULONG ulBlock; - - HB_TRACE(HB_TR_DEBUG, ("hb_cdxGetMemoBlock(%p, %hu)", pArea, uiIndex)); - - ulBlock = 0; - - for( uiCount = 0; uiCount < 10; uiCount++ ) - { - bByte = pArea->pRecord[ pArea->pFieldOffset[ uiIndex ] + uiCount ]; - - if( bByte >= '0' && bByte <= '9' ) - ulBlock = ulBlock * 10 + ( bByte - '0' ); - } - - return ulBlock; -} - -/* - * Converts ASCII data into memo block offset. - */ -static void hb_cdxPutMemoBlock( CDXAREAP pArea, USHORT uiIndex, ULONG ulBlock ) -{ - SHORT iCount; - - HB_TRACE(HB_TR_DEBUG, ("hb_cdxPutMemoBlock(%p, %hu, %lu)", pArea, uiIndex, ulBlock)); - - for( iCount = 9; iCount >= 0; iCount-- ) - { - if( ulBlock > 0 ) - { - pArea->pRecord[ pArea->pFieldOffset[ uiIndex ] + iCount ] = ( BYTE ) (( ulBlock % 10 ) + '0'); - ulBlock /= 10; - } - else - pArea->pRecord[ pArea->pFieldOffset[ uiIndex ] + iCount ] = ' '; - } -} - -/* - * Return the size of memo. - */ -static ULONG hb_cdxGetMemoLen( CDXAREAP pArea, USHORT uiIndex ) -{ - ULONG ulBlock; - MEMOBLOCK mbBlock; - - HB_TRACE(HB_TR_DEBUG, ("hb_cdxGetMemoLen(%p, %hu)", pArea, uiIndex)); - - ulBlock = hb_cdxGetMemoBlock( pArea, uiIndex ); - - if( ulBlock == 0 ) - return 0; - - hb_fsSeek( pArea->hMemoFile, ulBlock * pArea->uiMemoBlockSize, FS_SET ); - - if( hb_fsRead( pArea->hMemoFile, ( BYTE * ) &mbBlock, sizeof( MEMOBLOCK ) ) != - sizeof( MEMOBLOCK ) ) - return 0; - - return hb_cdxSwapBytes( mbBlock.ulSize ); -} - -#if 0 -/* - * Read memo data. - */ -static void hb_cdxGetMemo( CDXAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) -{ - ULONG ulBlock, ulSize; - BYTE * pBuffer; - MEMOBLOCK mbBlock; - long lSize; - - 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 ); - lSize = (long) ulSize; - /* if( ulSize > 0 && ulSize < 0xFFFFFF ) */ - if ( lSize > 0 ) - { - pBuffer = ( BYTE * ) hb_xgrab( ulSize + 1 ); - hb_fsReadLarge( pArea->hMemoFile, pBuffer, ulSize ); - hb_itemPutCPtr( pItem, ( char * ) pBuffer, ulSize ); - hb_itemSetCMemo( pItem ); - } - } - else - { - hb_itemPutC( pItem, "" ); - hb_itemSetCMemo( pItem ); + pIndex = pIndex->pNext; } + printf( "\r\n*END*\r\n" ); fflush( stdout ); } #endif -/* - * Append blocks to free memo blocks list. - */ -static void hb_cdxAddFreeBlocks( CDXAREAP pArea, ULONG ulBlock, ULONG ulBlocks ) +#ifdef HB_CDX_DBGTIME +#include +typedef long long CDXDBGTIME; + +static CDXDBGTIME cdxTimeIntBld = 0; +static CDXDBGTIME cdxTimeExtBld = 0; +static CDXDBGTIME cdxTimeIntBlc = 0; +static CDXDBGTIME cdxTimeExtBlc = 0; +static CDXDBGTIME cdxTimeGetKey = 0; +static CDXDBGTIME cdxTimeFreeKey = 0; + +static CDXDBGTIME hb_cdxGetTime() { - /* - SHORT iCount; - BOOL bFound; - LPMEMOFREEBLOCK pFreeBlock; - */ - - HB_TRACE(HB_TR_DEBUG, ("hb_cdxAddFreeBlocks(%p, %lu, %hu)", pArea, ulBlock, ulBlocks)); - HB_SYMBOL_UNUSED( pArea ); - HB_SYMBOL_UNUSED( ulBlock ); - HB_SYMBOL_UNUSED( ulBlocks ); - return; - /* - * Def'ed out temporarily this version doesn't seem correct for shared access or compatible with VFP. - * Do the dumb thing, no free block list (as VFP) - */ -#if 0 - bFound = FALSE; - for( iCount = pArea->pMemoRoot->uiListLen - 1; iCount >= 0; iCount-- ) - { - pFreeBlock = ( LPMEMOFREEBLOCK ) ( pArea->pMemoRoot->pFreeList + iCount * SIZEOFMEMOFREEBLOCK ); - if( pFreeBlock->ulBlock < ulBlock ) - { - /* Can grow current free block? */ - if( (pFreeBlock->ulBlock + pFreeBlock->uiBlocks) == ulBlock ) - { - /* The new blocks are directly after the current free block */ - pFreeBlock->uiBlocks += uiBlocks; - ulBlock = pFreeBlock->ulBlock; - uiBlocks = pFreeBlock->uiBlocks; - } - /* Can append to next free block? */ - else if( iCount < pArea->pMemoRoot->uiListLen - 1 && - (ulBlock + uiBlocks) == ( pFreeBlock + 1 )->ulBlock ) - { - /* The new blocks are directly before the next free block */ - pFreeBlock++; - iCount++; - pFreeBlock->ulBlock = ulBlock; - pFreeBlock->uiBlocks += uiBlocks; - uiBlocks = pFreeBlock->uiBlocks; - } - /* Append to next free block */ - else - { - pFreeBlock++; - iCount++; - memmove( pFreeBlock + 1, pFreeBlock, - ( HB_MIN( MAXFREEBLOCKS, pArea->pMemoRoot->uiListLen ) - iCount ) * - sizeof( SIZEOFMEMOFREEBLOCK ) ); - pFreeBlock->ulBlock = ulBlock; - pFreeBlock->uiBlocks = uiBlocks; - pArea->pMemoRoot->uiListLen = HB_MIN( MAXFREEBLOCKS, pArea->pMemoRoot->uiListLen + 1 ); - } - pArea->pMemoRoot->fChanged = TRUE; - bFound = TRUE; - break; - } - } - - /* If it is the last block in memo file truncate it */ - if( (ulBlock + uiBlocks) == pArea->pMemoRoot->ulNextBlock ) - { - pArea->pMemoRoot->ulNextBlock = ulBlock; - pArea->pMemoRoot->fChanged = TRUE; - if( bFound ) - { - memmove( pFreeBlock, pFreeBlock + 1, - ( HB_MIN( MAXFREEBLOCKS, pArea->pMemoRoot->uiListLen ) - iCount ) * - sizeof( SIZEOFMEMOFREEBLOCK ) ); - pArea->pMemoRoot->uiListLen--; - } - hb_fsSeek( pArea->hMemoFile, ulBlock * pArea->uiMemoBlockSize, FS_SET ); - hb_fsWrite( pArea->hMemoFile, NULL, 0 ); - return; - } - - /* Insert free block */ - if( !bFound && pArea->pMemoRoot->uiListLen < MAXFREEBLOCKS ) - { - pFreeBlock = ( LPMEMOFREEBLOCK ) pArea->pMemoRoot->pFreeList; - memmove( pFreeBlock + 1, pFreeBlock, - HB_MIN( MAXFREEBLOCKS, pArea->pMemoRoot->uiListLen ) * sizeof( SIZEOFMEMOFREEBLOCK ) ); - pFreeBlock->ulBlock = ulBlock; - pFreeBlock->uiBlocks = uiBlocks; - pArea->pMemoRoot->uiListLen = HB_MIN( MAXFREEBLOCKS, pArea->pMemoRoot->uiListLen + 1 ); - pArea->pMemoRoot->fChanged = TRUE; - } + struct timeval tv; + gettimeofday(&tv, NULL); + return ( (CDXDBGTIME) tv.tv_sec * 1000000 + (CDXDBGTIME) tv.tv_usec ); +} #endif -} + /* - * Try get free memo blocks from list. + * internal DBFCDX function */ -static BOOL hb_cdxCompleteFromFreeBlocks( CDXAREAP pArea, ULONG ulBlock, ULONG ulBlocks ) +static void hb_cdxErrInternal( char * szMsg ) { - /* - USHORT uiCount; - LPMEMOFREEBLOCK pFreeBlock; - MEMOBLOCK mbBlock; - */ + hb_errInternal( 9201, szMsg ? szMsg : "hb_cdxErrInternal: data integrity error.", "", "" ); +} - HB_TRACE(HB_TR_DEBUG, ("hb_cdxCompleteFromFreeBlocks(%p, %lu, %hu)", pArea, ulBlock, ulBlocks)); - HB_SYMBOL_UNUSED( pArea ); - HB_SYMBOL_UNUSED( ulBlock ); - HB_SYMBOL_UNUSED( ulBlocks ); - return FALSE; - /* - * Def'ed out temporarily this version doesn't seem correct for shared access or compatible with VFP. - * Do the dumb thing, no free block list (as VFP) - */ -#if 0 - 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; -#endif +static ERRCODE hb_cdxErrorRT( CDXAREAP pArea, USHORT uiGenCode, USHORT uiSubCode, char * filename, USHORT uiFlags ) +{ + PHB_ITEM pError; + ERRCODE iRet; + + pError = hb_errNew(); + hb_errPutGenCode( pError, uiGenCode ); + hb_errPutSubCode( pError, uiSubCode ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( uiGenCode ) ); + if ( filename ) + hb_errPutFileName( pError, filename ); + if ( uiFlags ) + hb_errPutFlags( pError, uiFlags ); + iRet = SELF_ERROR( ( AREAP ) pArea, pError ); + hb_errRelease( pError ); + return iRet; } /* - * Get free memo blocks from list or return a new block. + * create new index key */ -/* static void hb_cdxGetFreeBlocks( CDXAREAP pArea, USHORT uiBlocks, ULONG * ulBlock ) */ -static void hb_cdxGetFreeBlocks( CDXAREAP pArea, ULONG ulBlocks, ULONG * ulBlock ) +static LPCDXKEY hb_cdxKeyNew( void ) { - /* - USHORT uiCount; - LPMEMOFREEBLOCK pFreeBlock; - MEMOBLOCK mbBlock; - */ + LPCDXKEY pKey; - HB_TRACE(HB_TR_DEBUG, ("hb_cdxGetFreeBlocks(%p, %hu, %p)", pArea, ulBlocks, ulBlock)); - - /* - * Def'ed out temporarily this version doesn't seem correct for shared access or compatible with VFP. - * Do the dumb thing, no free block list (as VFP) - */ -#if 0 - for( uiCount = 0; uiCount < pArea->pMemoRoot->uiListLen; uiCount++ ) - { - pFreeBlock = ( LPMEMOFREEBLOCK ) ( pArea->pMemoRoot->pFreeList + uiCount * SIZEOFMEMOFREEBLOCK ); - if( ulBlocks <= 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; - } - } -#endif - /* Not found a free block */ - * ulBlock = pArea->pMemoRoot->ulNextBlock; - pArea->pMemoRoot->ulNextBlock += ulBlocks; - pArea->pMemoRoot->fChanged = TRUE; -} - -/* - * Write memo data. - */ -static void hb_cdxWriteMemo( CDXAREAP pArea, ULONG ulBlock, PHB_ITEM pItem, ULONG ulLen, - ULONG * ulStoredBlock, ULONG ulType ) -{ - /* USHORT uiBloksRequired, uiBlocksUsed; */ - ULONG ulBlocksRequired, ulBlocksUsed = 0; - MEMOBLOCK mbBlock; - BOOL bWriteBlocks; - - HB_TRACE(HB_TR_DEBUG, ("hb_cdxWriteMemo(%p, %lu, %p, %lu, %p, %hu)", pArea, ulBlock, - pItem, ulLen, ulStoredBlock, ulType)); - /* - uiBloksRequired = ( USHORT ) (( ulLen + sizeof( MEMOBLOCK ) + pArea->uiMemoBlockSize - 1 ) / - pArea->uiMemoBlockSize); - */ - ulBlocksRequired = (( 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); - */ - ulBlocksUsed = (( hb_cdxSwapBytes( mbBlock.ulSize ) + sizeof( MEMOBLOCK ) + - pArea->uiMemoBlockSize - 1 ) / pArea->uiMemoBlockSize); - } - - bWriteBlocks = FALSE; - /* Use same space */ - if( ulBlock > 0 && ulBlocksUsed >= ulBlocksRequired ) - { - * ulStoredBlock = ulBlock; - bWriteBlocks = TRUE; - - /* Free space */ - if( ulBlocksUsed > ulBlocksRequired ) - hb_cdxAddFreeBlocks( pArea, ulBlock + ulBlocksRequired, ulBlocksUsed - ulBlocksRequired ); - } - else /* Need more space */ - { - if( ulBlock > 0 ) - { - if( hb_cdxCompleteFromFreeBlocks( pArea, ulBlock + ulBlocksUsed, - ulBlocksRequired - ulBlocksUsed ) ) - bWriteBlocks = TRUE; - else /* Free all blocks */ - hb_cdxAddFreeBlocks( pArea, ulBlock, ulBlocksUsed ); - } - - if( !bWriteBlocks ) - { - hb_cdxGetFreeBlocks( pArea, ulBlocksRequired, ulStoredBlock ); - bWriteBlocks = TRUE; - } - } - - /* Write memo header and data */ - if( bWriteBlocks ) - { -#ifdef XDBFCDX - if ( HB_IS_STRING( pItem ) ) - { - mbBlock.ulType = hb_cdxSwapBytes( ulType ); - 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 ); - } - else - { - mbBlock.ulType = hb_cdxSwapBytes( ulType ); - mbBlock.ulSize = hb_cdxSwapBytes( ulLen ); - hb_fsSeek( pArea->hMemoFile, * ulStoredBlock * pArea->uiMemoBlockSize, FS_SET ); - hb_fsWrite( pArea->hMemoFile, ( BYTE * ) &mbBlock, sizeof( MEMOBLOCK ) ); - hb_xfptWriteItemSx( pArea->hMemoFile, pItem ); - // hb_fsWriteLarge( pArea->hMemoFile, ( BYTE * ) hb_itemGetCPtr( pItem ), ulLen ); - } -#else - mbBlock.ulType = hb_cdxSwapBytes( ulType ); - 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 ); -#endif - } -} - -/* - * Assign a value to the specified memo field. - */ -static BOOL hb_cdxPutMemo( CDXAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) -{ - /* USHORT uiBlocksUsed; */ - ULONG ulBlocksUsed; - ULONG ulLen, ulBlock, ulType; - MEMOBLOCK mbBlock; - - HB_TRACE(HB_TR_DEBUG, ("hb_cdxPutMemo(%p, %hu, %p)", pArea, uiIndex, pItem)); - -#ifdef XDBFCDX - if ( HB_IS_STRING( pItem ) ) - { - ulLen = hb_itemGetCLen( pItem ); - ulType = 1; - } - else - { - ulType = hb_itemType( pItem ); - ulLen = hb_xfptWriteItemSxLength( pItem ); - switch ( ulType ) - { - case HB_IT_INTEGER : // ( ( USHORT ) 0x0002 ) - case HB_IT_LONG : // ( ( USHORT ) 0x0008 ) - ulType = 0x0002; /* CLIP_IT_LNUM */ - break; - case HB_IT_DOUBLE : // ( ( USHORT ) 0x0010 ) - ulType = 0x0008; /* CLIP_IT_DNUM */ - break; - case HB_IT_DATE : // ( ( USHORT ) 0x0020 ) - ulType = 0x0020; /* CLIP_IT_LDATE */ - break; - case HB_IT_LOGICAL : // ( ( USHORT ) 0x0080 ) - ulType = 0x0080; /* CLIP_IT_LOG */ - break; - case HB_IT_ARRAY : // HB_IT_OBJECT = HB_IT_ARRAY - ulType = 0x8000; /* CLIP_IT_ARRAY */ - break; - default : - ulType = 0x0000; - ulLen = 0; - break; - } - } -#else - ulType = 1; - ulLen = hb_itemGetCLen( pItem ); -#endif - ulBlock = hb_cdxGetMemoBlock( pArea, uiIndex ); - if( ulLen > 0 ) - hb_cdxWriteMemo( pArea, ulBlock, pItem, ulLen, &ulBlock, ulType ); - 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 ); - */ - ulBlocksUsed = (( hb_cdxSwapBytes( mbBlock.ulSize ) + - pArea->uiMemoBlockSize - 1 ) / pArea->uiMemoBlockSize); - hb_cdxAddFreeBlocks( pArea, ulBlock, ulBlocksUsed ); - } - ulBlock = 0; - } - if( pArea->fShared && pArea->pMemoRoot->fChanged ) - { - pArea->pMemoRoot->fChanged = FALSE; - hb_fsSeek( pArea->hMemoFile, 0, FS_SET ); - pArea->pMemoRoot->ulNextBlock = hb_cdxSwapBytes( pArea->pMemoRoot->ulNextBlock ); - pArea->pMemoRoot->ulBlockSize = hb_cdxSwapBytes( pArea->pMemoRoot->ulBlockSize ); - hb_fsWrite( pArea->hMemoFile, ( BYTE * ) pArea->pMemoRoot, sizeof( MEMOROOT ) ); - pArea->pMemoRoot->ulNextBlock = hb_cdxSwapBytes( pArea->pMemoRoot->ulNextBlock ); - pArea->pMemoRoot->ulBlockSize = hb_cdxSwapBytes( pArea->pMemoRoot->ulBlockSize ); - } - hb_cdxPutMemoBlock( pArea, uiIndex, ulBlock ); - return TRUE; -} -/* end hb_cdx memo*/ - -/* hb_xfpt */ -/* #include "xfptmemo.c" */ -/* - * XDBFCDX - * xfptmemo.c - * */ - - -/* - * Read fpt vartype memos. - */ -static void hb_xfptGetMemo( CDXAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) -{ - ULONG ulBlock, ulSize, ulType; - BYTE * pBuffer; - MEMOBLOCK mbBlock; - long lSize; - - 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 ); - lSize = (long) ulSize; - ulType = hb_cdxSwapBytes( mbBlock.ulType ); - - /* if( ulSize > 0 && ulSize < 0xFFFFFF ) */ - if ( lSize > 0 ) - { - switch ( ulType ) - { - case 0x0000 : /* Picture */ - case 0x0001 : /* Text */ - pBuffer = ( BYTE * ) hb_xgrab( ulSize + 1 ); - hb_fsReadLarge( pArea->hMemoFile, pBuffer, ulSize ); - hb_itemPutCPtr( pItem, ( char * ) pBuffer, ulSize ); - hb_itemSetCMemo( pItem ); - break; - - case 0x0002 : /* CLIP_IT_LNUM */ - case 0x0008 : /* CLIP_IT_DNUM */ - case 0x0020 : /* CLIP_IT_LDATE */ - case 0x0080 : /* CLIP_IT_LOG */ - case 0x8000 : /* CLIP_IT_ARRAY */ - hb_xfptReadItemSx( pArea->hMemoFile, pItem ); - break; - - default: - hb_itemClear( pItem ); - break; - } - } - } - else - { - hb_itemPutC( pItem, "" ); - hb_itemSetCMemo( pItem ); - } -} - -static void hb_xfptReadItemSx( FHANDLE hMemoFile, PHB_ITEM pItem ) -{ - BYTE itmBuffer[14]; - BYTE * pStr; - USHORT usType; - ULONG ulLen, i; - PHB_ITEM pArray, pNewItem; - - hb_fsRead( hMemoFile, itmBuffer, 14 ); - usType = *(short *)(&itmBuffer[0]); - switch ( usType ) - { - case 0x0002 : /* CLIP_IT_LNUM */ - hb_itemPutNL( pItem, *(long *)(&itmBuffer[6]) ); - break; - - case 0x0008 : /* CLIP_IT_DNUM */ - hb_itemPutNDLen( pItem, *(double *)(&itmBuffer[6]), - *(short *)(&itmBuffer[2]), *(short *)(&itmBuffer[4]) ); - break; - - case 0x0020 : /* CLIP_IT_LDATE */ - hb_itemPutDL( pItem, *(long *)(&itmBuffer[6]) ); - break; - - case 0x0080 : /* CLIP_IT_LOG */ - hb_itemPutL( pItem, *(BOOL *)(&itmBuffer[6]) ); - break; - - case 0x0400 : /* CLIP_IT_CHAR */ - ulLen = *(short *)(&itmBuffer[2]); /* only 2 bytes for SIX compatibility */ - pStr = ( BYTE * ) hb_xgrab( ulLen + 1 ); - hb_fsRead( hMemoFile, pStr, ulLen ); - hb_itemPutCPtr( pItem, ( char * ) pStr, ulLen ); - break; - - //#define CLIP_IT_BLOCK 0x1000 - //#define CLIP_IT_VREF 0x2000 - //#define CLIP_IT_MREF 0x4000 - //#define CLIP_IT_ARRAY 0x8000 - - case 0x8000 : /* CLIP_IT_ARRAY */ - ulLen = *(short *)(&itmBuffer[2]); /* only 2 bytes for SIX compatibility */ - pArray = hb_itemArrayNew( ulLen ); - pNewItem = hb_itemNew( NULL ); - for ( i = 1 ; i <= ulLen ; i++ ) - { - hb_xfptReadItemSx( hMemoFile, pNewItem ); - pArray = hb_itemArrayPut( pArray, i, pNewItem ); - hb_itemClear( pNewItem ); - } - hb_itemCopy( pItem, pArray ); - break; - default: - hb_itemClear( pItem ); - break; - } -} - - -/* - * Write fpt vartype memos. - * */ - -#if 1 - -static ULONG hb_xfptWriteItemSx( FHANDLE hMemoFile, PHB_ITEM pItem ) -{ - BYTE itmBuffer[14]; - USHORT usType; - ULONG ulLen, i, ulSize; - PHB_ITEM pTmpItem; - - - usType = hb_itemType( pItem ); - memset(itmBuffer, '\0', 14); - ulSize = 14; - switch ( usType ) - { - case HB_IT_ARRAY : // HB_IT_OBJECT = HB_IT_ARRAY - ulLen = hb_arrayLen( pItem ); - if ( ulLen > 65535 ) - { - ulLen = 65535; - } - *(short *)(&itmBuffer[0]) = 0x8000; /* CLIP_IT_ARRAY */ - *(short *)(&itmBuffer[2]) = ulLen; /* only 2 bytes for SIX compatibility */ - hb_fsWrite( hMemoFile, itmBuffer, 14 ); - for ( i = 1 ; i <= ulLen ; i++ ) - { - pTmpItem = hb_arrayGetItemPtr( pItem, i ); - ulSize += hb_xfptWriteItemSx( hMemoFile, pTmpItem ); - } - break; - - case HB_IT_INTEGER : // ( ( USHORT ) 0x0002 ) - *(USHORT *)(&itmBuffer[0]) = 0x0002; /* CLIP_IT_LNUM */ - *(USHORT *)(&itmBuffer[2]) = pItem->item.asInteger.length; - *(long *)(&itmBuffer[6]) = pItem->item.asInteger.value; - hb_fsWrite( hMemoFile, itmBuffer, 14 ); - break; - - case HB_IT_LONG : // ( ( USHORT ) 0x0008 ) - *(USHORT *)(&itmBuffer[0]) = 0x0002; /* CLIP_IT_LNUM */ - *(USHORT *)(&itmBuffer[2]) = pItem->item.asLong.length; - *(long *)(&itmBuffer[6]) = pItem->item.asLong.value; - hb_fsWrite( hMemoFile, itmBuffer, 14 ); - break; - - case HB_IT_DOUBLE : // ( ( USHORT ) 0x0010 ) - *(USHORT *)(&itmBuffer[0]) = 0x0008; /* CLIP_IT_DNUM */ - *(USHORT *)(&itmBuffer[2]) = pItem->item.asDouble.length; - *(USHORT *)(&itmBuffer[4]) = pItem->item.asDouble.decimal; - *(double *)(&itmBuffer[6]) = pItem->item.asDouble.value; - hb_fsWrite( hMemoFile, itmBuffer, 14 ); - break; - - case HB_IT_DATE : // ( ( USHORT ) 0x0020 ) - *(USHORT *)(&itmBuffer[0]) = 0x0020; /* CLIP_IT_LDATE */ - *(long *)(&itmBuffer[6]) = pItem->item.asDate.value; - hb_fsWrite( hMemoFile, itmBuffer, 14 ); - break; - - case HB_IT_LOGICAL : // ( ( USHORT ) 0x0080 ) - *(USHORT *)(&itmBuffer[0]) = 0x0080; /* CLIP_IT_LOG */ - *(BOOL *)(&itmBuffer[6]) = pItem->item.asLogical.value; - hb_fsWrite( hMemoFile, itmBuffer, 14 ); - break; - - case HB_IT_STRING : - case HB_IT_MEMO : - /* only 2 bytes for SIX compatibility, - * TODO: decide how to extend its capabilities. - * */ - ulLen = pItem->item.asString.length; - if ( ulLen > 65535 ) - { - ulLen = 65535; - } - *(USHORT *)(&itmBuffer[0]) = 0x0400; /* CLIP_IT_CHAR */ - *(USHORT *)(&itmBuffer[2]) = ( USHORT ) ulLen; - // *(USHORT *)(&itmBuffer[4]) = pItem->item.asDouble.decimal; - hb_fsWrite( hMemoFile, itmBuffer, 14 ); - ulSize += ulLen; - if ( ulLen > 0 ) - { - hb_fsWrite( hMemoFile, (BYTE *) (pItem->item.asString.value), ulLen ); - } - break; - -/* -#define HB_IT_NIL ( ( USHORT ) 0x0000 ) -#define HB_IT_POINTER ( ( USHORT ) 0x0001 ) -#define HB_IT_SYMBOL ( ( USHORT ) 0x0100 ) -#define HB_IT_ALIAS ( ( USHORT ) 0x0200 ) -#define HB_IT_BLOCK ( ( USHORT ) 0x1000 ) -#define HB_IT_BYREF ( ( USHORT ) 0x2000 ) -#define HB_IT_MEMVAR ( ( USHORT ) 0x4000 ) -#define HB_IT_NUMERIC ( ( USHORT ) ( HB_IT_INTEGER | HB_IT_LONG | HB_IT_DOUBLE ) ) -#define HB_IT_ANY ( ( USHORT ) 0xFFFF ) -*/ - default : - hb_fsWrite( hMemoFile, itmBuffer, 14 ); - break; - } - return ulSize; -} - -static ULONG hb_xfptWriteItemSxLength( PHB_ITEM pItem ) -{ - ULONG ulLen, i, ulSize; - PHB_ITEM pTmpItem; - USHORT usType; - - usType = hb_itemType( pItem ); - switch ( usType ) - { - case HB_IT_ARRAY : // HB_IT_OBJECT = HB_IT_ARRAY - ulSize = 14; - ulLen = hb_arrayLen( pItem ); - for ( i = 1 ; i <= ulLen ; i++ ) - { - pTmpItem = hb_arrayGetItemPtr( pItem, i ); - ulSize += hb_xfptWriteItemSxLength( pTmpItem ); - } - break; - case HB_IT_STRING : - case HB_IT_MEMO : - ulSize = 14; - ulSize += pItem->item.asString.length; - break; - default : - ulSize = 14; - } - return ulSize; -} -/* -#define HB_IT_NIL ( ( USHORT ) 0x0000 ) -#define HB_IT_POINTER ( ( USHORT ) 0x0001 ) -#define HB_IT_INTEGER ( ( USHORT ) 0x0002 ) -#define HB_IT_LONG ( ( USHORT ) 0x0008 ) -#define HB_IT_DOUBLE ( ( USHORT ) 0x0010 ) -#define HB_IT_DATE ( ( USHORT ) 0x0020 ) -#define HB_IT_LOGICAL ( ( USHORT ) 0x0080 ) -#define HB_IT_SYMBOL ( ( USHORT ) 0x0100 ) -#define HB_IT_ALIAS ( ( USHORT ) 0x0200 ) -#define HB_IT_STRING ( ( USHORT ) 0x0400 ) -#define HB_IT_MEMOFLAG ( ( USHORT ) 0x0800 ) -#define HB_IT_MEMO ( HB_IT_MEMOFLAG | HB_IT_STRING ) -#define HB_IT_BLOCK ( ( USHORT ) 0x1000 ) -#define HB_IT_BYREF ( ( USHORT ) 0x2000 ) -#define HB_IT_MEMVAR ( ( USHORT ) 0x4000 ) -#define HB_IT_NUMERIC ( ( USHORT ) ( HB_IT_INTEGER | HB_IT_LONG | HB_IT_DOUBLE ) ) -#define HB_IT_ANY ( ( USHORT ) 0xFFFF ) -*/ - -#endif -/* end hb_xfpt */ - -/* hb_cdxkeyxxx */ -/* #include "cdxkey.c" */ - -/* hb_cdxkeyxxx */ - -static LPCDXKEYINFO hb_cdxKeyNew() -{ - LPCDXKEYINFO pKey; - - pKey = ( LPCDXKEYINFO ) hb_xgrab( sizeof( CDXKEYINFO ) ); - pKey->Value = NULL; - pKey->length = 0; - pKey->realLength = 0; - pKey->fString = FALSE; - pKey->Tag = pKey->Xtra = 0; - pKey->pNext = NULL; + pKey = ( LPCDXKEY ) hb_xgrab( sizeof( CDXKEY ) ); + memset( pKey, 0, sizeof( CDXKEY ) ); return pKey; } -static void hb_cdxKeyFree( LPCDXKEYINFO pKey ) +/* + * Free index key + */ +static void hb_cdxKeyFree( LPCDXKEY pKey ) { - if( pKey ) - { - if( pKey->Value ) - hb_xfree( pKey->Value ); - - hb_xfree( pKey ); - } + if ( pKey->val ) + hb_xfree( pKey->val ); + hb_xfree( pKey ); } -static void hb_cdxKeyListFree( LPCDXKEYINFO pKeyList ) +/* + * copy index key, if dst is null create new dst key else destroy dst + */ +static LPCDXKEY hb_cdxKeyCopy( LPCDXKEY pKeyDest, LPCDXKEY pKey ) { - LPCDXKEYINFO pKeyTmp; - while( pKeyList != NULL ) + if ( !pKeyDest ) + pKeyDest = hb_cdxKeyNew(); + else { - pKeyTmp = pKeyList; - pKeyList = pKeyList->pNext; - hb_cdxKeyFree( pKeyTmp ); + pKeyDest->rec = 0; + if ( pKeyDest->val && pKeyDest->len != pKey->len ) + { + hb_xfree( pKeyDest->val ); + pKeyDest->val = NULL; + pKeyDest->len = 0; + } } + if ( pKey ) + { + if ( pKey->len ) + { + if ( !pKeyDest->val ) + pKeyDest->val = (BYTE *) hb_xgrab( pKey->len + 1 ); + memcpy( pKeyDest->val, pKey->val, pKey->len ); + pKeyDest->len = pKey->len; + pKeyDest->val[ pKeyDest->len ] = '\0'; + } + pKeyDest->rec = pKey->rec; + } + return pKeyDest; } -static LPCDXKEYINFO hb_cdxKeyListGetKey ( LPCDXKEYINFO pKeyList, USHORT uiKey ) +/* + * store bytes value in inkdex key + */ +static LPCDXKEY hb_cdxKeyPut( LPCDXKEY pKey, BYTE * pbVal, USHORT uiLen, ULONG ulRec ) { - LPCDXKEYINFO pKey; - - pKey = pKeyList; - while( uiKey > 0 && pKey->pNext != NULL ) + if ( !pKey ) + pKey = hb_cdxKeyNew(); + else { - pKey = pKey->pNext; - uiKey--; + if ( pKey->val && pKey->len != uiLen ) + { + hb_xfree( pKey->val ); + pKey->val = NULL; + pKey->len = 0; + } } - return ( uiKey ? NULL : pKey); -} - -static LPCDXKEYINFO hb_cdxKeyListGetLast ( LPCDXKEYINFO pKeyList ) -{ - LPCDXKEYINFO pKey; - - pKey = pKeyList; - while( pKey->pNext != NULL ) + if ( pbVal && uiLen ) { - pKey = pKey->pNext; + pKey->len = uiLen; + if ( !pKey->val ) + pKey->val = ( BYTE * ) hb_xgrab( uiLen + 1 ); + memcpy( pKey->val, pbVal, uiLen ); + pKey->val[ uiLen ] = '\0'; } + pKey->rec = ulRec; return pKey; } - -static int hb_cdxKeyValCompare( LPCDXTAG pTag, char * pKeyVal1, BYTE keyLen1, - char * pKeyVal2, BYTE keyLen2, BOOL Exact ) +/* + * store string0 value in index key + */ +static LPCDXKEY hb_cdxKeyPutC( LPCDXKEY pKey, char * szText, USHORT uiRealLen, ULONG ulRec ) { - CDXKEYINFO pKey1, pKey2; - int ret; + USHORT uiLen; - pKey1.Value = pKeyVal1; - pKey1.length = keyLen1; - pKey2.Value = pKeyVal2; - pKey2.length = keyLen2; - pKey1.realLength = pTag->uiLen; - pKey2.realLength = pTag->uiLen; - pKey1.fString = (pTag->uiType == 'C'); - pKey2.fString = (pTag->uiType == 'C'); - ret = hb_cdxKeyCompare( &pKey1, &pKey2, Exact ); - return ret; -} - -static SHORT hb_cdxKeyFindDup( LPCDXKEYINFO pKey1, LPCDXKEYINFO pKey2 ) -{ - SHORT usDup = 0; - - if ( pKey1 == NULL ) - hb_cdxErrInternal( "hb_cdxKeyFindDup: pKey1 is NULL!" ); - - if ( pKey2 != NULL ) + if ( !pKey ) + pKey = hb_cdxKeyNew(); + else { - int iLimit = (pKey1->length > pKey2->length) ? pKey2->length : pKey1->length; - while ( usDup < iLimit && ( (BYTE) pKey1->Value[ usDup ] ) == - ( (BYTE) pKey2->Value[ usDup ] ) ) + if ( pKey->val ) { - usDup++; + hb_xfree( pKey->val ); + pKey->val = NULL; + pKey->len = 0; } } - - return usDup; + uiLen = szText ? strlen( szText ) : 0; + if ( uiLen > uiRealLen ) + uiLen = uiRealLen; + pKey->len = uiRealLen; + pKey->val = ( BYTE * ) hb_xgrab( uiRealLen + 1 ); + if ( uiLen ) + memcpy( pKey->val, szText, uiLen ); + if ( uiLen < uiRealLen ) + memset( &pKey->val[ uiLen ], ' ', uiRealLen - uiLen ); + pKey->val[ uiRealLen ] = '\0'; + pKey->rec = ulRec; + return pKey; } -static int hb_cdxKeyCompare( LPCDXKEYINFO pKey1, LPCDXKEYINFO pKey2, BOOL Exact ) +/* + * compare two values using Tag conditions (len & type) + */ +static int hb_cdxValCompare( LPCDXTAG pTag, BYTE * val1, BYTE len1, + BYTE * val2, BYTE len2, BOOL fExact ) { - int iLimit, iResult = 0, iPos = 0; + int iLimit, iResult = 0; - if ( pKey1 == NULL ) - return ( pKey2 == NULL ) ? 0 : -1; - if ( pKey2 == NULL ) - return 1; - if( !pKey1->fString || !pKey2->fString) - { - if ( pKey1->length == 0) - return ( pKey2->length == 0 ) ? 0: -1; - if ( pKey2->length == 0 ) - return 1; - } - /* - if( pKey2 == NULL || pKey2->length == 0 ) - return 1; - if( pKey1 == NULL || pKey1->length == 0 ) - return ( pKey2->length == 0 ) ? 0: -1; - */ + iLimit = (len1 > len2) ? len2 : len1; - iLimit = (pKey1->length > pKey2->length) ? pKey2->length : pKey1->length; - - if( pKey1->fString && pKey2->fString) + if ( pTag->uiType == 'C' ) { #ifndef HB_CDP_SUPPORT_OFF - while( iResult == 0 && iPos < iLimit ) + PHB_CODEPAGE cdpage = pTag->pIndex->pArea->cdPage; + int iPos = 0; + + while ( iResult == 0 && iPos < iLimit ) { /* for nation sorting support */ - iResult = hb_cdpcharcmp( pKey1->Value[ iPos ], pKey2->Value[ iPos ] ); + iResult = hb_cdpcharcmp( val1[ iPos ], val2[ iPos ], cdpage ); iPos++; /* EndPos += 1; */ } #else - iResult = memcmp(pKey1->Value, pKey2->Value, iLimit); + if ( iLimit > 0 ) + iResult = memcmp( val1, val2, iLimit ); #endif - - if ( iResult == 0 ) { - unsigned char c1, c2; - iPos = iLimit; - iLimit = ( pKey1->realLength > pKey2->realLength ) ? pKey2->realLength : pKey1->realLength; - while( iResult == 0 && iPos < iLimit ) - { - c1 = (unsigned char) ( ( iPos < pKey1->length ) ? ( pKey1->Value[ iPos ]) : ' ' ); - c2 = (unsigned char) ( ( iPos < pKey2->length ) ? ( pKey2->Value[ iPos ]) : ' ' ); -#ifndef HB_CDP_SUPPORT_OFF - /* for nation sorting support */ - iResult = hb_cdpcharcmp( c1, c2 ); -#else - iResult = c1 - c2; -#endif - iPos++; - } - } - if( iResult == 0 ) + if ( iResult == 0 ) { - iPos++; - iResult = pKey1->realLength - pKey2->realLength; + if ( len1 > len2 ) + iResult = 1; + else if ( len1 < len2 && fExact ) + iResult = -1; } - if( (iResult < 0) && (iPos > pKey1->realLength) && !Exact ) - iResult = 0; } else { - if( iLimit == 0 || (iResult = memcmp( pKey1->Value, pKey2->Value, iLimit )) == 0 ) - iResult = pKey1->length - pKey2->length; - - /*-----------------05/01/2003 06:55p.--------------- - * If key isn't a string, Exact flag doesn't seem correct. - * -------------------------------------------------- - if( (iResult < 0) && (* EndPos > pKey1->length) && !Exact ) - iResult = 0; - */ + if ( iLimit == 0 || (iResult = memcmp( val1, val2, iLimit )) == 0 ) + { + if ( len1 > len2 ) + iResult = 1; + else if ( len1 < len2 ) + iResult = -1; + } } - - if( iResult < 0 ) - return -1; - else if( iResult > 0 ) - return 1; - else - return 0; + return iResult; } -static LPCDXKEYINFO hb_cdxKeyPutItem( LPCDXKEYINFO pKey, PHB_ITEM pItem ) +/* + * store Item in index key + * TODO: uiType check + */ +static LPCDXKEY hb_cdxKeyPutItem( LPCDXKEY pKey, PHB_ITEM pItem, ULONG ulRec, LPCDXTAG pTag, BOOL fTrans ) { - BYTE cTemp[8]; - int i; + BYTE buf[8], *ptr; + BYTE len = 0; + ptr = &buf[0]; - if( !pKey ) - pKey = hb_cdxKeyNew(); - if( pKey->Value ) - { - hb_xfree( pKey->Value ); - pKey->Value = NULL; - } - - pKey->realLength = 0; - switch( hb_itemType( pItem ) ) + switch ( hb_itemType( pItem ) ) { case HB_IT_STRING: case HB_IT_STRING | HB_IT_MEMO: - - pKey->Value = hb_itemGetC( pItem ); - pKey->realLength = pKey->length = (USHORT) (pItem->item.asString.length > CDX_MAXKEY ? - CDX_MAXKEY : pItem->item.asString.length); - pKey->fString = TRUE; - - while( pKey->length > 0 && - pKey->Value[ pKey->length - 1 ] == ' ' ) - /*pKey->Value[ pItem->item.asString.length - 1 ] == ' ' )*/ - pKey->length--; - - pKey->Value[ pKey->length ] = 0; - + ptr = pItem->item.asString.value; + len = ( BYTE ) HB_CDXMAXKEY( pItem->item.asString.length ); break; - case HB_IT_INTEGER: case HB_IT_LONG: case HB_IT_DOUBLE: - hb_cdxDNtoSort( hb_itemGetND( pItem ), &cTemp[0] ); - i = 7; - while( !cTemp[i] ) - i--; - - i++; - pKey->length = i; - pKey->realLength = 8; - pKey->Value = (char *) hb_xgrab( i + 1 ); - pKey->Value[i] = 0; - memcpy( pKey->Value, cTemp, i ); - pKey->fString = FALSE; - +#ifndef HB_LONG_LONG_OFF + case HB_IT_LONGLONG: +#endif + HB_PUT_SORTDBL( ptr, hb_itemGetND( pItem ) ); + len = 8; break; - case HB_IT_DATE: - hb_cdxDNtoSort( (double) hb_itemGetDL( pItem ), &cTemp[0] ); - - i = 7; - while( !cTemp[i] ) - i--; - - i++; - pKey->length = i; - pKey->realLength = 8; - pKey->Value = (char *) hb_xgrab( i + 1 ); - pKey->Value[i] = 0; - memcpy( pKey->Value, cTemp, i ); - pKey->fString = FALSE; - + HB_PUT_SORTDBL( ptr, (double) hb_itemGetDL( pItem ) ); + len = 8; break; - case HB_IT_LOGICAL: - pKey->realLength = pKey->length = 1; - pKey->Value = (char *) hb_xgrab( 2 ); - pKey->fString = TRUE; - - pKey->Value[0] = (char) ( hb_itemGetL( pItem ) ? 'T' : 'F' ); - pKey->Value[1] = 0; - + *ptr = ( hb_itemGetL( pItem ) ? 'T' : 'F' ); + len = 1; break; - default: + ptr = NULL; +#ifndef HB_CDX_DBGCODE_OFF + /* TODO: RTerror */ printf( "hb_cdxKeyPutItem( invalid item type: %i )", hb_itemType( pItem ) ); +#endif + break; } - + pKey = hb_cdxKeyPut( pKey, ptr, len, ulRec ); +#ifndef HB_CDP_SUPPORT_OFF + if ( fTrans && pTag->uiType == 'C' ) + hb_cdpnTranslate( pKey->val, s_cdpage, pTag->pIndex->pArea->cdPage, pKey->len ); +#endif return pKey; } -static PHB_ITEM hb_cdxKeyGetItem( LPCDXKEYINFO pKey, PHB_ITEM pItem, USHORT uiType ) +/* + * get Item from index key (TODO: add pTag param) + */ +static PHB_ITEM hb_cdxKeyGetItem( LPCDXKEY pKey, PHB_ITEM pItem, USHORT uiType ) { - - if( pKey && pKey->Value ) + if ( pKey ) { + double d; + switch( uiType ) { - case HB_IT_STRING: - pItem = hb_itemPutC( pItem, pKey->Value ); + case 'C': + pItem = hb_itemPutCL( pItem, pKey->val, pKey->len ); break; - - case HB_IT_INTEGER: - case HB_IT_LONG: - - case HB_IT_DOUBLE: - pItem = (PHB_ITEM) hb_itemPutND( pItem, - hb_cdxSorttoND( (BYTE*) pKey->Value, (USHORT) pKey->length ) ); + case 'N': + HB_GET_SORTDBL( d, pKey->val ) + pItem = hb_itemPutND( pItem, d ); break; - - case HB_IT_DATE: - pItem = (PHB_ITEM) hb_itemPutDL( pItem, - (long) hb_cdxSorttoND( (BYTE*) pKey->Value, (USHORT) pKey->length ) ); + case 'D': + HB_GET_SORTDBL( d, pKey->val ) + pItem = hb_itemPutDL( pItem, (LONG) d ); break; -/* - case HB_IT_DOUBLE: - pItem = (PHB_ITEM) hb_itemPutND( pItem, - (long) hb_cdxSorttoND( pKey->Value, (USHORT) pKey->length ) ); - break; - - case HB_IT_DATE: - pItem = (PHB_ITEM) hb_itemPutDL( pItem, - (long) hb_cdxSorttoND( pKey->Value, (USHORT) pKey->length ) ); - break; -*/ - case HB_IT_LOGICAL: - pItem = hb_itemPutL( pItem, - (pKey->Value[0] == 'T' ? TRUE : FALSE ) ); + case 'L': + pItem = hb_itemPutL( pItem, pKey->val[0] == 'T' ); break; default: pItem = hb_itemNew( pItem ); - printf( "hb_cdxKeyGetItem() ???" ); +#ifndef HB_CDX_DBGCODE_OFF + printf( "hb_cdxKeyGetItem() ??? (%x)\n", uiType ); +#endif } } else @@ -1483,1337 +638,1407 @@ static PHB_ITEM hb_cdxKeyGetItem( LPCDXKEYINFO pKey, PHB_ITEM pItem, USHORT uiTy return pItem; } -static LPCDXKEYINFO hb_cdxKeyCopy( LPCDXKEYINFO pKeyDest, LPCDXKEYINFO pKey ) +/* + * evaluate key expression and create new Key the from result + */ +static LPCDXKEY hb_cdxKeyEval( LPCDXKEY pKey, LPCDXTAG pTag, BOOL fSetWA ) { - if( !pKeyDest ) + HB_MACRO_PTR pMacro; + int iCurrArea = 0; + CDXAREAP pArea = pTag->pIndex->pArea; +#ifndef HB_CDP_SUPPORT_OFF + /* TODO: this hack is not thread safe, s_cdpage has to be thread specific */ + PHB_CODEPAGE cdpTmp = s_cdpage; + s_cdpage = pArea->cdPage; +#endif + + if ( fSetWA && !pTag->nField ) { - pKeyDest = hb_cdxKeyNew(); + iCurrArea = hb_rddGetCurrentWorkAreaNumber(); + if ( iCurrArea != pArea->uiArea ) + hb_rddSelectWorkAreaNumber( pArea->uiArea ); + else + iCurrArea = 0; } - if( pKeyDest->Value ) + if ( pTag->nField ) { - hb_xfree( pKeyDest->Value ); - pKeyDest->Value = NULL; - pKeyDest->length = 0; + PHB_ITEM pItem = hb_itemNew( NULL ); + SELF_GETVALUE( ( AREAP ) pArea, pTag->nField, pItem ); + pKey = hb_cdxKeyPutItem( pKey, pItem, pArea->ulRecNo, pTag, FALSE ); + hb_itemRelease( pItem ); } - - if( pKey ) + else if ( hb_itemType( pTag->pKeyItem ) == HB_IT_BLOCK ) { - pKeyDest->Value = (char *) hb_xgrab( pKey->length + 1 ); - memcpy( pKeyDest->Value, pKey->Value, pKey->length ); - pKeyDest->length = pKey->length; - pKeyDest->realLength = pKey->realLength; - pKeyDest->Value[ pKeyDest->length ] = 0; - pKeyDest->fString = pKey->fString; - pKeyDest->Tag = pKey->Tag; - pKeyDest->Xtra = pKey->Xtra; - } - - return pKeyDest; -} - -static LPCDXKEYINFO hb_cdxKeyPut( LPCDXKEYINFO pKey, BYTE * szText, USHORT uiLen, USHORT uiRealLen, BOOL fString ) -{ - if( !pKey ) - pKey = hb_cdxKeyNew(); - - if( pKey->Value ) - { - hb_xfree( pKey->Value ); - pKey->Value = NULL; - } - pKey->realLength = uiRealLen; - if( szText == NULL ) - { - pKey->length = 0; - pKey->fString = fString; + hb_vmPushSymbol( &hb_symEval ); + hb_vmPush( pTag->pKeyItem ); + hb_vmSend( 0 ); + pKey = hb_cdxKeyPutItem( pKey, &(HB_VM_STACK.Return), pArea->ulRecNo, pTag, FALSE ); } else { - pKey->length = uiLen; - pKey->Value = ( char * ) hb_xgrab( uiLen + 1 ); - memcpy( pKey->Value, szText, uiLen ); - pKey->Value[ uiLen ] = 0; - pKey->fString = fString; + pMacro = ( HB_MACRO_PTR ) hb_itemGetPtr( pTag->pKeyItem ); + hb_macroRun( pMacro ); + pKey = hb_cdxKeyPutItem( pKey, hb_stackItemFromTop( -1 ), pArea->ulRecNo, pTag, FALSE ); + hb_stackPop(); } + if ( iCurrArea ) + hb_rddSelectWorkAreaNumber( iCurrArea ); + +#ifndef HB_CDP_SUPPORT_OFF + s_cdpage = cdpTmp; +#endif + return pKey; } -static LPCDXKEYINFO hb_cdxKeyPutC( LPCDXKEYINFO pKey, char * szText, USHORT uiRealLen ) +/* + * evaluate macro expression + * the result is on the stack hb_stackItemFromTop(-1) + * TODO: eliminate it by implementing macro evaluation + * in SELF_EVALBLOCK( AREAP pArea, PHB_ITEM pExpr) + */ +static void hb_cdxMacroRun( CDXAREAP pArea, HB_MACRO_PTR pMacro ) { - if( !pKey ) - pKey = hb_cdxKeyNew(); - - if( szText == NULL ) - szText = ""; - - if( pKey->Value ) - { - hb_xfree( pKey->Value ); - pKey->Value = NULL; - } - - pKey->realLength = uiRealLen; - pKey->length = strlen( szText ); - pKey->Value = ( char * ) hb_xgrab( pKey->length + 1 ); - strcpy( pKey->Value, szText ); - pKey->fString = TRUE; - - return pKey; + int iCurrArea; + iCurrArea = hb_rddGetCurrentWorkAreaNumber(); + if ( iCurrArea != pArea->uiArea ) + hb_rddSelectWorkAreaNumber( pArea->uiArea ); + else + iCurrArea = 0; + hb_macroRun( pMacro ); + if ( iCurrArea ) + hb_rddSelectWorkAreaNumber( iCurrArea ); } -/* end hb_cdxkeyxxx */ -/* end hb_cdxkeyxxx */ +/* + * evaluate conditional expression and return the result + */ +static BOOL hb_cdxEvalCond( CDXAREAP pArea, PHB_ITEM pCondItem, BOOL fSetWA ) +{ + HB_MACRO_PTR pMacro; + int iCurrArea = 0; + BOOL fRet; -/* hb_cdxTagxxx */ -/* #include "cdxtag.c" */ + if ( fSetWA ) { + iCurrArea = hb_rddGetCurrentWorkAreaNumber(); + if ( iCurrArea != pArea->uiArea ) + hb_rddSelectWorkAreaNumber( pArea->uiArea ); + else + iCurrArea = 0; + } -/* hb_cdxTagxxx */ + if ( hb_itemType( pCondItem ) == HB_IT_BLOCK ) + { + hb_vmPushSymbol( &hb_symEval ); + hb_vmPush( pCondItem ); + hb_vmSend( 0 ); + fRet = hb_itemGetL( &(HB_VM_STACK.Return) ); + } + else + { + pMacro = ( HB_MACRO_PTR ) hb_itemGetPtr( pCondItem ); + hb_macroRun( pMacro ); + fRet = hb_itemGetL( hb_stackItemFromTop( -1 ) ); + hb_stackPop(); + } -/* Creates a new structure with a tag information - * - * PIF = pointer to a parent index structure - * ITN = tag name - * TagHdr = number of index page where a tag header is stored or -1 if - * allocate a new tag page -*/ -static LPCDXTAG hb_cdxTagNew( LPCDXINDEX PIF, char * ITN, LONG TagHdr ) + if ( iCurrArea ) + hb_rddSelectWorkAreaNumber( iCurrArea ); + + return fRet; +} + +/* + * check if Key is in top scope + */ +static BOOL hb_cdxTopScope( LPCDXTAG pTag ) +{ + return !pTag->topScopeKey || !pTag->topScopeKey->len || + hb_cdxValCompare( pTag, pTag->topScopeKey->val, + pTag->topScopeKey->len, + pTag->CurKey->val, + pTag->CurKey->len, FALSE ) <= 0; +} + +/* + * check if Key is in bottom scope + */ +static BOOL hb_cdxBottomScope( LPCDXTAG pTag ) +{ + return !pTag->bottomScopeKey || !pTag->topScopeKey->len || + hb_cdxValCompare( pTag, pTag->bottomScopeKey->val, + pTag->bottomScopeKey->len, + pTag->CurKey->val, + pTag->CurKey->len, FALSE ) >= 0; +} + +/* + * clear scopes + */ +static void hb_cdxTagClearScope( LPCDXTAG pTag, USHORT nScope ) +{ + PHB_ITEM *pScope; + LPCDXKEY *pScopeKey; + + HB_TRACE(HB_TR_DEBUG, ("hb_cdxTagClearScope(%p, %hu)", pTag, nScope)); + + if ( nScope == 0 ) + { + pScope = &pTag->topScope; + pScopeKey = &pTag->topScopeKey; + } + else + { + pScope = &pTag->bottomScope; + pScopeKey = &pTag->bottomScopeKey; + } + if ( *pScope ) + { + hb_itemRelease( *pScope ); + *pScope = NULL; + } + if ( *pScopeKey ) + { + hb_cdxKeyFree( *pScopeKey ); + *pScopeKey = NULL; + } +} + +#ifndef HB_CDX_DBGCODE_OFF +/* + * check internal integrity of page pool + */ +static void hb_cdxTagPoolCheck( LPCDXTAG pTag ) +{ + LPCDXPAGE pPage, pPrevPage; + + pPage = pTag->pagePool; + pPrevPage = NULL; + while ( pPage ) + { + if ( pPage->pPoolPrev != pPrevPage || pPage->TagParent != pTag ) + hb_cdxErrInternal( "hb_cdxTagPoolCheck: data integrity error." ); + pPrevPage = pPage; + pPage = pPage->pPoolNext; + } +} + +/* + * check if the Tag buffers was not changed without write lock + */ +static void hb_cdxTagCheckBuffers( LPCDXTAG pTag ) +{ + BOOL fChanged = FALSE; + + hb_cdxTagPoolCheck( pTag ); + if ( pTag->TagChanged ) + fChanged = TRUE; + else + { + LPCDXPAGE pPage = pTag->pagePool; + while ( pPage && !fChanged ) + { + fChanged = pPage->fChanged; + pPage = pPage->pPoolNext; + } + } + if ( fChanged ) + hb_cdxErrInternal( "hb_cdxTagCheckBuffers: modification without write lock." ); +} + +/* + * check if the Index buffers was not changed without write lock + */ +static void hb_cdxIndexCheckBuffers( LPCDXINDEX pIndex ) { LPCDXTAG pTag; - pTag = ( LPCDXTAG ) hb_xgrab( sizeof( CDXTAG ) ); - memset( pTag, 0, sizeof( CDXTAG ) ); - pTag->szName = ( char * ) hb_xgrab( CDX_MAXTAGNAMELEN + 1 ); - hb_strncpyUpper( pTag->szName, ITN, CDX_MAXTAGNAMELEN ); - pTag->pIndex = PIF; - pTag->AscendKey = TRUE; - pTag->uiType = 'C'; - pTag->CurKeyInfo = hb_cdxKeyNew(); - if( TagHdr == -1 ) + if ( pIndex->fChanged || ( pIndex->freeLst && pIndex->freeLst->fStat ) ) + hb_cdxErrInternal( "hb_cdxIndexCheckBuffers: modification without write lock." ); + + if ( pIndex->pCompound ) + hb_cdxTagCheckBuffers( pIndex->pCompound ); + pTag = pIndex->TagList; + while ( pTag ) { - /* this tag is not stored in the file yet - allocate a space for it */ - pTag->TagBlock = hb_cdxIndexGetAvailPage( PIF ); - hb_cdxIndexGetAvailPage( PIF ); - pTag->TagChanged = TRUE; + hb_cdxTagCheckBuffers( pTag ); + pTag = pTag->pNext; } - else - { - pTag->TagBlock = TagHdr; - hb_cdxTagTagLoad( pTag ); - } - pTag->OptFlags = 0x60; - return pTag; } - -static void hb_cdxTagFree( LPCDXTAG pTag ) -{ - if( pTag->RootPage != NULL ) - { - hb_cdxPageFree( pTag->RootPage ); - pTag->RootPage = NULL; - } - // hb_cdxPagePoolFlush( pTag->pIndex ); - // hb_cdxPagePoolFree( pTag->pIndex, 0 ); - hb_cdxPagePoolFlushTag( pTag ); - hb_cdxPagePoolFreeTag( pTag, 0 ); - if( pTag->TagChanged ) - hb_cdxTagTagStore( pTag ); - if( pTag->szName != NULL ) - hb_xfree( pTag->szName ); - if( pTag->KeyExpr != NULL ) - hb_xfree( pTag->KeyExpr ); - if( pTag->pKeyItem != NULL ) - { - if( hb_itemType( pTag->pKeyItem ) != HB_IT_BLOCK ) - hb_macroDelete( ( HB_MACRO_PTR ) hb_itemGetPtr( pTag->pKeyItem ) ); - hb_itemRelease( pTag->pKeyItem ); - } - if( pTag->ForExpr != NULL ) - hb_xfree( pTag->ForExpr ); - if( pTag->pForItem != NULL ) - { - if( hb_itemType( pTag->pForItem ) != HB_IT_BLOCK ) - hb_macroDelete( ( HB_MACRO_PTR ) hb_itemGetPtr( pTag->pForItem ) ); - hb_itemRelease( pTag->pForItem ); - } - hb_cdxKeyFree( pTag->CurKeyInfo ); - hb_cdxTagClearScope( pTag, 0); - hb_cdxTagClearScope( pTag, 1); - hb_xfree( pTag ); -} - -static void hb_cdxTagIndexTagNew( LPCDXTAG pTag, char * KeyExp, PHB_ITEM pKeyItem, - BYTE bType, USHORT uiLen, char * ForExp, - PHB_ITEM pForItem, BOOL Ascnd, BOOL Uniq, BOOL bCustom ) -{ - CDXTAGHEADER pHeader; - - if( KeyExp != NULL ) - { - pTag->KeyExpr = ( char * ) hb_xgrab( CDX_MAXKEY + 1 ); - hb_strncpyUpper( pTag->KeyExpr, KeyExp, CDX_MAXKEY ); - pTag->nField = hb_rddFieldIndex( (AREAP) pTag->pIndex->pArea, pTag->KeyExpr ); - } - pTag->pKeyItem = pKeyItem; - if( ForExp != NULL ) - { - pTag->ForExpr = ( char * ) hb_xgrab( CDX_MAXKEY + 1 ); - hb_strncpyUpper( pTag->ForExpr, ForExp, CDX_MAXKEY ); - } - pTag->pForItem = pForItem; - pTag->AscendKey = Ascnd; - pTag->UniqueKey = Uniq; - pTag->Custom = bCustom; - pTag->uiType = bType; - pTag->uiLen = uiLen; - pTag->MaxKeys = ( CDX_PAGELEN - 12 ) / ( uiLen + 8 ); - memset( &pHeader, 0, sizeof( CDXTAGHEADER ) ); - hb_cdxIndexPageWrite( pTag->pIndex, pTag->TagBlock, &pHeader, sizeof( CDXTAGHEADER ) ); - hb_cdxTagDoIndex( pTag ); -} - -static void hb_cdxTagDoIndex( LPCDXTAG pTag ) -{ - ULONG ulRecNo, ulRecCount; - BOOL bForOk; - LPSORTINFO pSort; - PHB_ITEM pItem; - HB_MACRO_PTR pMacro; - BYTE cTemp[8]; - LPCDXAREA pArea = pTag->pIndex->pArea; - LONG lStep = 0; - BOOL bDirectRead, bEnd; - PHB_ITEM pForItem, pWhileItem, pEvalItem; - - if( ( pTag->OptFlags & 0x80 ) || pTag->Custom ) - hb_cdxTagEmptyIndex( pTag ); - else - { - PHB_ITEM pSaveFilter; - BOOL bSaveDeleted; - bSaveDeleted = hb_set.HB_SET_DELETED; - hb_set.HB_SET_DELETED = FALSE; - pSaveFilter = pArea->dbfi.itmCobExpr; - pArea->dbfi.itmCobExpr = NULL; - - bDirectRead = TRUE; - if ( pArea->lpdbOrdCondInfo && !pArea->lpdbOrdCondInfo->fAll ) - bDirectRead = FALSE; - if ( pArea->lpdbRelations ) - bDirectRead = FALSE; - bEnd = FALSE; - if ( !bDirectRead ) - { - if ( !pArea->lpdbOrdCondInfo || pArea->lpdbOrdCondInfo->fAll || pArea->lpdbOrdCondInfo->fUseCurrent ) { - SELF_GOTOP( ( AREAP ) pArea ); - } - else - { - if ( pArea->lpdbOrdCondInfo->lRecno ) - { - SELF_GOTO( ( AREAP ) pArea, pArea->lpdbOrdCondInfo->lRecno ); - bEnd = TRUE; - } - else - { - SELF_GOTO( ( AREAP ) pArea, pArea->lpdbOrdCondInfo->lStartRecno ); - } - } - } - pSort = hb_cdxSortNew( pTag, pTag->UniqueKey ); - pItem = hb_itemNew( NULL ); - ulRecCount = pArea->ulRecCount; - pForItem = pTag->pForItem; - bForOk = TRUE; - pEvalItem = ( pArea->lpdbOrdCondInfo ? pArea->lpdbOrdCondInfo->itmCobEval : NULL); - pWhileItem = ( pArea->lpdbOrdCondInfo ? pArea->lpdbOrdCondInfo->itmCobWhile : NULL); - for( ulRecNo = 1; ulRecNo <= ulRecCount; ulRecNo++ ) - { - if ( bDirectRead ) - { - hb_fsSeek( pArea->hDataFile, - pArea->uiHeaderLen + - ( ulRecNo - 1 ) * pArea->uiRecordLen, - FS_SET ); - hb_fsRead( pArea->hDataFile, - pArea->pRecord, - pArea->uiRecordLen ); - pArea->ulRecNo = ulRecNo; - pArea->fDeleted = ( pArea->pRecord[ 0 ] == '*' ); - } - else - { - if ( pWhileItem && !hb_cdxEvalCond ( NULL, pWhileItem, 0 ) ) - break; - } - if( pForItem != NULL ) - { - /* TODO: test for expression */ - /* now is working but not tested */ - /* bWhileOk = TRUE; */ - /* - if( hb_itemType( pTag->pForItem ) == HB_IT_BLOCK ) - { - hb_vmPushSymbol( &hb_symEval ); - hb_vmPush( pTag->pForItem ); - hb_vmSend( 0 ); - hb_itemCopy( pItem, &(HB_VM_STACK.Return) ); - } - else - { - pMacro = ( HB_MACRO_PTR ) hb_itemGetPtr( pTag->pForItem ); - hb_macroRun( pMacro ); - hb_itemCopy( pItem, hb_stackItemFromTop( - 1 ) ); - hb_stackPop(); - } - bForOk = hb_itemGetL( pItem ); - */ - bForOk = hb_cdxEvalCond ( pArea, pForItem, 0 ); - } - /* - else - bForOk = TRUE; - */ - if( bForOk ) - { - if ( pTag->nField ) - { - SELF_GETVALUE( ( AREAP ) pArea, pTag->nField, pItem ); - } - else - { - if( hb_itemType( pTag->pKeyItem ) == HB_IT_BLOCK ) - { - - hb_vmPushSymbol( &hb_symEval ); - hb_vmPush( pTag->pKeyItem ); - hb_vmSend( 0 ); - hb_itemCopy( pItem, &(HB_VM_STACK.Return) ); - } - else - { - pMacro = ( HB_MACRO_PTR ) hb_itemGetPtr( pTag->pKeyItem ); - hb_macroRun( pMacro ); - hb_itemCopy( pItem, hb_stackItemFromTop( - 1 ) ); - hb_stackPop(); - } - } - - switch( hb_itemType( pItem ) ) - { - case HB_IT_STRING: - hb_cdxSortInsertWord( pSort, (long) pArea->ulRecNo, pItem->item.asString.value, - HB_CDXMAXKEY( pItem->item.asString.length ) ); - break; - - case HB_IT_INTEGER: - case HB_IT_LONG: - case HB_IT_DOUBLE: - hb_cdxDNtoSort( hb_itemGetND( pItem ), &cTemp[0] ); - hb_cdxSortInsertWord( pSort, pArea->ulRecNo, (char *) cTemp, 8 ); - break; - - case HB_IT_LOGICAL: - cTemp[0] = (BYTE) (hb_itemGetL( pItem ) ? 'T' : 'F'); - hb_cdxSortInsertWord( pSort, pArea->ulRecNo, (char *) cTemp, 1 ); - break; - - case HB_IT_DATE: - hb_cdxDNtoSort( (double) hb_itemGetDL( pItem ), &cTemp[0] ); - hb_cdxSortInsertWord( pSort, pArea->ulRecNo, (char *) cTemp, 8 ); - break; - - default: - printf( "hb_cdxTagDoIndex( LPCDXTAG pTag ): hb_itemType( pItem ) = %i", hb_itemType( pItem ) ); - } - } - if( pEvalItem ) - { - if( pArea->lpdbOrdCondInfo->lStep ) - { - lStep ++; - if( lStep == pArea->lpdbOrdCondInfo->lStep ) - lStep = 0; - } - if( pEvalItem && !lStep ) - { - hb_vmPushSymbol( &hb_symEval ); - hb_vmPush( pEvalItem ); - hb_vmSend( 0 ); - } - } - if ( !bDirectRead ) - { - if ( bEnd ) - break; - if( pArea->lpdbOrdCondInfo->lNextCount > 0 ) - { - pArea->lpdbOrdCondInfo->lNextCount--; - if( pArea->lpdbOrdCondInfo->lNextCount <= 0 ) - break; - } - SELF_SKIP( ( AREAP ) pArea, 1 ); - if ( pArea->fEof ) - break; - } - } -#ifdef CDXDEBUG - printf( "hb_cdxTagDoIndex: pSort->WordCount: %i, pSort->KeyCnt: %i, pSort->TotalWordCount: %i \n", - pSort->WordCount, pSort->KeyCnt, pSort->TotalWordCount ); -#endif - if( pSort->WordCount + pSort->TotalWordCount > 0 ) - hb_cdxSortDisplayWord( pSort ); - else - hb_cdxTagEmptyIndex( pTag ); -#ifdef CDXDEBUG - printf( "hb_cdxTagDoIndex: pSort->WordCount: %i, pSort->KeyCnt: %i, pSort->TotalWordCount: %i \n", - pSort->WordCount, pSort->KeyCnt, pSort->TotalWordCount ); - { - char ss[ 8 ]; - ULONG pp; - pp = 161293; - hb_cdxDNtoSort( ( double ) pp, (BYTE *) ss ); - printf("pp: %i, dopo: %i\n", pp, ( ULONG ) hb_cdxSorttoND( (BYTE *) ss, 8 )); - } -#endif - hb_cdxSortFree( pSort ); - hb_itemRelease( pItem ); - hb_set.HB_SET_DELETED = bSaveDeleted; - pArea->dbfi.itmCobExpr = pSaveFilter; - } - pTag->TagChanged = TRUE; - hb_cdxTagTagStore( pTag ); - pTag->pIndex->pArea->ulRecNo = 0; -} - -static void hb_cdxTagEmptyIndex( LPCDXTAG pTag ) -{ - USHORT uiKeyLength; - BYTE uiBitCount; - CDXDATA pData; - - pTag->RootBlock = hb_cdxIndexGetAvailPage( pTag->pIndex ); - memset( &pData, 0, sizeof( CDXDATA ) ); - pData.Node_Atr = 3; - pData.Left_Ptr = pData.Rght_Ptr = -1; - uiKeyLength = pTag->uiLen; - for( uiBitCount = 0; uiKeyLength; uiBitCount++, uiKeyLength >>= 1 ); - pData.cdxu.External.ShortBytes = 3; - pData.cdxu.External.RecNumBits = 24 - uiBitCount * 2; - pData.cdxu.External.RecNumMask = hb_cdxMakeMask( pData.cdxu.External.RecNumBits ); - pData.cdxu.External.FreeSpace = CDX_EXTERNAL_SPACE; - pData.cdxu.External.DupCntBits = pData.cdxu.External.TrlCntBits = uiBitCount; - pData.cdxu.External.DupCntMask = (BYTE) hb_cdxMakeMask( pData.cdxu.External.DupCntBits ); - pData.cdxu.External.TrlCntMask = (BYTE) hb_cdxMakeMask( pData.cdxu.External.TrlCntBits ); - - hb_cdxIndexPageWrite( pTag->pIndex, pTag->RootBlock, &pData, sizeof( CDXDATA ) ); -} - -static void hb_cdxTagTagStore( LPCDXTAG pTag ) -{ - USHORT uiForLen; - CDXTAGHEADER pHeader; - - if( !pTag->TagChanged ) - return; - pTag->TagChanged = FALSE; - if( pTag->UniqueKey ) - pTag->OptFlags |= 0x01; - if( pTag->Temporary ) - pTag->OptFlags |= 0x02; - if( pTag->Custom ) - pTag->OptFlags |= 0x04; - if( pTag->pForItem != NULL ) - pTag->OptFlags |= 0x08; - memset( &pHeader, 0, sizeof( CDXTAGHEADER ) ); - pHeader.lRoot = pTag->RootBlock; - pHeader.uiKeySize = pTag->uiLen; - pHeader.bType = pTag->OptFlags; - pHeader.bSignature = 1; - if( !pTag->AscendKey ) - pHeader.iDescending = 1; - pHeader.iFilterPos = 1 + ( pTag->KeyExpr == NULL ? 0 : strlen( pTag->KeyExpr ) ); - pHeader.iExprLen = pHeader.iFilterPos; - if( pTag->KeyExpr != NULL ) - strcpy( ( char * ) pHeader.KeyPool, pTag->KeyExpr ); - uiForLen = pTag->ForExpr == NULL ? 0 : strlen( pTag->ForExpr ); - if( uiForLen > 0 ) - { - pHeader.iFilterLen = uiForLen + 1; - strcpy( ( char * ) pHeader.KeyPool + pHeader.iExprLen, pTag->ForExpr ); - } - else - pHeader.iFilterLen = 1; - hb_cdxIndexPageWrite( pTag->pIndex, pTag->TagBlock, &pHeader, sizeof( CDXTAGHEADER ) ); -} - -static void hb_cdxTagTagOpen( LPCDXTAG pTag, BYTE bCode ) -{ - hb_cdxIndexLockRead( pTag->pIndex, pTag ); - hb_cdxTagTagClose( pTag ); - pTag->RootBlock = hb_cdxTagNewRoot( pTag ); - pTag->RootPage = hb_cdxPageNew( pTag, NULL, pTag->RootBlock ); - /* - if( bCode == 2 ) - return; - */ - if( bCode != 2 ) - { - if( bCode == 0 ) - hb_cdxTagKeyRead( pTag, TOP_RECORD ); - else - printf( "hb_cdxTagTagOpen()" ); - } - hb_cdxIndexUnLockRead( pTag->pIndex, pTag ); -} - -static void hb_cdxTagTagClose( LPCDXTAG pTag ) -{ - if( pTag->RootPage != NULL ) - { - hb_cdxPageFree( pTag->RootPage ); - pTag->RootPage = NULL; - } - if( pTag->TagChanged ) - hb_cdxTagTagStore( pTag ); -} - -static LONG hb_cdxTagNewRoot( LPCDXTAG pTag ) -{ - CDXTAGHEADER pHeader; - - hb_cdxIndexPageRead( pTag->pIndex, pTag->TagBlock, &pHeader, sizeof( CDXTAGHEADER ) ); - return pHeader.lRoot; -} - -static void hb_cdxTagPageLoad( LPCDXTAG pTag, LPCDXPAGEINFO pPage, short noKeys ) -{ - CDXDATA pData; - - hb_cdxIndexPageRead( pTag->pIndex, pPage->Page, &pData, sizeof( CDXDATA ) ); - if( pData.Node_Atr > 1 ) - pPage->PageType = PAGE_LEAF; - else - pPage->PageType = PAGE_NODE; - pPage->Left = pData.Left_Ptr; - pPage->Right = pData.Rght_Ptr; - if( pData.Entry_Ct > 0 ) - { - if( pPage->PageType == PAGE_LEAF ) - hb_cdxTagExtNodeBuild( pTag, &pData, pPage, noKeys ); - else - hb_cdxTagIntNodeBuild( pTag, &pData, pPage ); - } - pPage->Changed = FALSE; -} - -static void hb_cdxTagKeyRead( LPCDXTAG pTag, BYTE bTypRead ) -{ - pTag->CurKeyInfo->Tag = 0; - if( pTag->RootPage == NULL ) - return; - hb_cdxIndexLockRead( pTag->pIndex, pTag ); - if( !pTag->AscendKey ) - { - switch( bTypRead ) - { - case TOP_RECORD: - bTypRead = BTTM_RECORD; - break; - - case BTTM_RECORD: - bTypRead = TOP_RECORD; - break; - - case NEXT_RECORD: - bTypRead = PREV_RECORD; - break; - - case PREV_RECORD: - bTypRead = NEXT_RECORD; - break; - } - } - pTag->TagBOF = pTag->TagEOF = FALSE; - switch( bTypRead ) - { - case TOP_RECORD: - hb_cdxTagTagOpen( pTag, 2 ); - /* -----------------10/10/2001 19:04----------------- - Disable this test for now. - -------------------------------------------------- - if( pTag->pForItem != NULL ) - printf( "hb_cdxTagKeyRead()" ); - else - pTag->TagBOF = !hb_cdxPageReadTopKey( pTag->RootPage ); - */ - pTag->TagBOF = !hb_cdxPageReadTopKey( pTag->RootPage ); - /* -----------------10/10/2001 19:04----------------- - Disable this test for now. - -------------------------------------------------- - if( pTag->pForItem != NULL ) - printf( "hb_cdxTagTestRange()" ); - */ - if( pTag->TagEOF ) - pTag->TagBOF = TRUE; - pTag->TagEOF = pTag->TagBOF; - break; - - case BTTM_RECORD: - hb_cdxTagTagOpen( pTag, 2 ); - /* -----------------10/10/2001 19:04----------------- - Disable this test for now. - -------------------------------------------------- - if( pTag->pForItem != NULL ) - printf( "hb_cdxTagKeyRead()" ); - else - pTag->TagEOF = !hb_cdxPageReadBottomKey( pTag->RootPage ); - */ - pTag->TagEOF = !hb_cdxPageReadBottomKey( pTag->RootPage ); - /* -----------------10/10/2001 19:04----------------- - Disable this test for now. - -------------------------------------------------- - if( pTag->pForItem != NULL ) - { - printf( "hb_cdxTagTestRange()" ); - } - */ - if( pTag->TagBOF ) - pTag->TagEOF = TRUE; - pTag->TagBOF = pTag->TagEOF; - break; - - case NEXT_RECORD: - /* -----------------10/10/2001 19:04----------------- - Disable this test for now. - -------------------------------------------------- - while( TRUE ) - { - pTag->TagEOF = !hb_cdxPageReadNextKey( pTag->RootPage ); - if( pTag->pForItem != NULL ) - printf( "hb_cdxTagKeyRead()" ); - else - break; - } - */ - pTag->TagEOF = !hb_cdxPageReadNextKey( pTag->RootPage ); - break; - - case PREV_RECORD: - /* -----------------10/10/2001 19:04----------------- - Disable this test for now. - -------------------------------------------------- - while( TRUE ) - { - pTag->TagBOF = !hb_cdxPageReadPrevKey( pTag->RootPage ); - if( pTag->pForItem != NULL ) - printf( "hb_cdxTagKeyRead()" ); - else - break; - } - break; - */ - pTag->TagBOF = !hb_cdxPageReadPrevKey( pTag->RootPage ); - - } - if( pTag->TagBOF || pTag->TagEOF ) - { - if( !pTag->AscendKey ) - { - pTag->CurKeyInfo->Tag = pTag->TagEOF; - pTag->TagEOF = pTag->TagBOF; - pTag->TagBOF = ( BOOL ) pTag->CurKeyInfo->Tag; - } - pTag->CurKeyInfo->Tag = 0; - } - hb_cdxIndexUnLockRead( pTag->pIndex, pTag ); -} - -static void hb_cdxTagKeyAdd( LPCDXTAG pTag, LPCDXKEYINFO pKey ) -{ - int iSeek; - LONG lOldXtra; - LPCDXKEYINFO pNewKey; - - lOldXtra = pKey->Xtra; - pKey->Xtra = pKey->Tag; - hb_cdxTagTagOpen( pTag, 0 ); - pNewKey = hb_cdxKeyNew(); - pNewKey = hb_cdxKeyCopy( pNewKey, pKey ); - - pTag->TagBOF = pTag->TagEOF = FALSE; - iSeek = hb_cdxPageSeekKey( pTag->RootPage, - pTag->UniqueKey ? CDX_IGNORE_REC_NUM : pNewKey->Tag, pNewKey, TRUE ); - if( pTag->UniqueKey && iSeek == 0 ) - { - } - else if( iSeek < 1 ) - { - hb_cdxPageKeyInsert( 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 ) - hb_cdxTagKeyRead( pTag, BTTM_RECORD ); -// else -// printf( "hb_cdxTagKeyAdd()\n"); - hb_cdxPageKeyInsert( pTag->RootPage, pNewKey, TRUE ); - hb_cdxTagTagOpen( pTag, 0 ); - if( !pTag->AscendKey ) - { - //printf( "hb_cdxTagKeyAdd()\n"); - pTag->TagBOF = TRUE; - } - else - { - hb_cdxTagKeyRead( pTag, BTTM_RECORD ); - pTag->TagEOF = TRUE; - } - } - hb_cdxKeyFree( pNewKey ); - pKey->Xtra = lOldXtra; -} - -static void hb_cdxTagPageStore( LPCDXTAG pTag, LPCDXPAGEINFO PIK ) -{ - CDXDATA pData; - - memset( &pData, 0, sizeof( CDXDATA ) ); - pData.Node_Atr = ( PIK->PageType < PAGE_LEAF ) ? 0 : 2; - if( PIK->Owner == NULL ) - pData.Node_Atr++; - pData.Left_Ptr = PIK->Left; - pData.Rght_Ptr = PIK->Right; - if( pData.Node_Atr < 2 ) - hb_cdxTagIntNodeWrite( pTag, PIK->Page, &pData, PIK ); - else - hb_cdxTagExtNodeWrite( pTag, PIK->Page, &pData, PIK ); -} - -static void hb_cdxTagExtNodeWrite( LPCDXTAG pTag, LONG PN, LPCDXDATA pData, - LPCDXPAGEINFO PIK ) -{ - USHORT uiKeyLength, cd, kcnt, lm, uiCount, ck, na; - BYTE uiBitCount; - LONG /*sr,*/ rp, lp, NPN, TmpTag; - LPCDXKEYINFO p, q; - ULONG sr; - -#ifndef HB_CDX_DBGCODE_OFF - hb_cdxPageLeafCheckKeys( PIK ); #endif - if( pTag->OptFlags & 0x80 ) - sr = hb_fsSeek( pTag->pIndex->hFile, 0, FS_END ); - else - sr = pTag->pIndex->pArea->ulRecCount; - uiKeyLength = pTag->uiLen; - // if ( PIK->keyAdded ) - if ( !PIK->ReqByte ) - { - 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; - /* - TODO: I don't know why this was here, but the index structure was wrong with this. - * - if( PIK->RNMask < 0 ) - { - PIK->RNMask = 0x7FFFFFFF; - PIK->RNBits = 31; - } - */ - } - PIK->FreeSpace = CDX_EXTERNAL_SPACE; - PIK->DCBits = PIK->TCBits = uiBitCount; - PIK->DCMask = (BYTE) hb_cdxMakeMask( PIK->DCBits ); - PIK->TCMask = (BYTE) 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 ); - cd = p->length - hb_cdxKeyFindDup( p, q ) ; - q = p; - sr += cd + PIK->ReqByte; - if ( (ULONG) p->Tag > PIK->RNMask ) - hb_cdxErrInternal( "hb_cdxTagExtNodeWrite: record mask calculated wrong!." ); - - if( sr < (ULONG) lm ) - kcnt++; - } - if( sr <= CDX_EXTERNAL_SPACE ) - kcnt = PIK->uiKeys; - else - { - hb_cdxErrInternal( "hb_cdxTagExtNodeWrite: node space exceed!." ); - } - ck = 0; - pData->Entry_Ct = 0; - if( kcnt < PIK->uiKeys ) - { - hb_cdxErrInternal( "hb_cdxTagExtNodeWrite: node space exceed!!!." ); - - 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->FreeSpace; - NPN = hb_cdxIndexGetAvailPage( pTag->pIndex ); - TmpTag = p->Tag; - p->Tag = NPN; - hb_cdxPageAddNodeKey( PIK, p ); - p->Tag = TmpTag; - if( PIK->PageType == PAGE_ROOT ) - PIK->PageType = PAGE_NODE; - hb_cdxIndexPageWrite( pTag->pIndex, NPN, pData, CDX_PAGELEN ); - if( lp > 0 ) - { - hb_cdxIndexPageRead( pTag->pIndex, lp, pData, CDX_PAGELEN ); - pData->Rght_Ptr = NPN; - hb_cdxIndexPageWrite( pTag->pIndex, lp, pData, CDX_PAGELEN ); - } - memset( pData, 0, CDX_PAGELEN ); - pData->Node_Atr = na; - pData->Rght_Ptr = rp; - pData->Left_Ptr = NPN; - pData->Entry_Ct = 0; - kcnt = PIK->uiKeys; - } - hb_cdxTagFillExternalNode( pTag, pData, PIK, kcnt, ck, &p ); - pData->cdxu.External.FreeSpace = PIK->FreeSpace; - hb_cdxIndexPageWrite( pTag->pIndex, PN, pData, sizeof( CDXDATA ) ); -} - -static USHORT hb_cdxTagFillExternalNode( LPCDXTAG pTag, LPCDXDATA pData, - LPCDXPAGEINFO PIK, USHORT kcnt, - USHORT ck, LPCDXKEYINFO * p ) -{ - USHORT i, k, ct, cd, v; -#ifndef HB_LONG_LONG_OFF - ULONGLONG rr; -#else - LONG r; - USHORT c; -#endif - LPCDXKEYINFO q; - - memset( pData->cdxu.External.ExtData, 0, sizeof( pData->cdxu.External.ExtData ) ); - pData->cdxu.External.FreeSpace = PIK->FreeSpace; - 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; - PIK->FreeSpace = CDX_EXTERNAL_SPACE; - k = CDX_EXTERNAL_SPACE; - q = NULL; - i = 0; - while( i < kcnt && ck < PIK->uiKeys ) - { - * p = hb_cdxPageGetKey( PIK, ck ); - ct = pTag->uiLen - ( * p )->length ; - cd = hb_cdxKeyFindDup( *p, q ); - q = * p; - PIK->FreeSpace -= pTag->uiLen + PIK->ReqByte - cd - ct; - // TODO: remove this check - if ( PIK->FreeSpace < 0) - { - hb_cdxErrInternal( "hb_cdxTagFillExternalNode: FreeSpace calculated wrong!." ); - } - v = i * PIK->ReqByte; - k -= pTag->uiLen - cd - ct; - if ( k < v + PIK->ReqByte ) - { - hb_cdxErrInternal( "hb_cdxTagFillExternalNode: FreeSpace calculated wrong!!." ); - } - /* RECMASK */ -#ifndef HB_LONG_LONG_OFF - rr = ( (ULONGLONG) ct << ( ( PIK->ReqByte * 8 ) - PIK->TCBits ) ) | - ( (ULONGLONG) cd << ( ( PIK->ReqByte * 8 ) - PIK->TCBits - PIK->DCBits ) ) | - ( * p )->Tag; - memcpy( &pData->cdxu.External.ExtData[ v ], &rr, PIK->ReqByte ); -#else - 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 &= ~PIK->RNMask; - r |= ( * p )->Tag; - memcpy( &pData->cdxu.External.ExtData[ v ], &r, 4 ); -#endif - if( pTag->uiLen - cd - ct > 0 ) - memcpy( &pData->cdxu.External.ExtData[ k ], ( * p )->Value + cd, - pTag->uiLen - cd - ct ); - i++; - ck++; - pData->Entry_Ct++; - } - return ck; -} - -static void hb_cdxTagExtNodeBuild( LPCDXTAG pTag, LPCDXDATA pData, LPCDXPAGEINFO PIK, short noKeys ) -{ - USHORT k, i, v, t, d; - LONG r; -#ifndef HB_LONG_LONG_OFF - ULONGLONG rr; -#else - USHORT c; -#endif - LPCDXKEYINFO pKey, pLastKey = NULL; - static char szBuffer[ CDX_MAXKEY + 1 ]; - - k = CDX_EXTERNAL_SPACE; - PIK->FreeSpace = pData->cdxu.External.FreeSpace; - PIK->RNMask = pData->cdxu.External.RecNumMask; - PIK->DCMask = pData->cdxu.External.DupCntMask; - PIK->TCMask = pData->cdxu.External.TrlCntMask; - PIK->RNBits = pData->cdxu.External.RecNumBits; - PIK->DCBits = pData->cdxu.External.DupCntBits; - PIK->TCBits = pData->cdxu.External.TrlCntBits; - PIK->ReqByte = pData->cdxu.External.ShortBytes; - i = 0; - if ( noKeys ) - { - PIK->uiKeys = pData->Entry_Ct; - } - else - { - while( i < pData->Entry_Ct ) - { - v = i * PIK->ReqByte; - /* RECMASK */ -#ifndef HB_LONG_LONG_OFF - rr = 0; - memcpy( &rr, &pData->cdxu.External.ExtData[ v ], PIK->ReqByte ); - t = ( rr >> ( ( PIK->ReqByte * 8 ) - PIK->TCBits ) ) & PIK->TCMask; - d = ( rr >> ( ( PIK->ReqByte * 8 ) - PIK->TCBits - PIK->DCBits ) ) & PIK->DCMask; - r = rr & PIK->RNMask; -#else - 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; - r = 0; - memcpy( &r, &pData->cdxu.External.ExtData[ v ], 4 ); - r &= PIK->RNMask; -#endif - k -= pTag->uiLen - d - t; -#ifndef HB_CDX_DBGCODE_OFF - if ( d + t > pTag->uiLen || k > CDX_EXTERNAL_SPACE ) - { - hb_cdxErrInternal( "hb_cdxTagExtNodeBuild: FreeSpace calculated wrong!." ); - } -#endif - if ( pLastKey ) { - if ( d > pLastKey->length ) - memset(&szBuffer[ pLastKey->length ], ( pTag->uiType == 'C' ? ' ' : 0), d - pLastKey->length); - } - if( pTag->uiLen - d - t > 0 ) - memcpy( &szBuffer[ d ], &pData->cdxu.External.ExtData[ k ], - pTag->uiLen - d - t ); - szBuffer[ pTag->uiLen - t ] = 0; - pKey = hb_cdxKeyNew(); - pKey->Tag = r; - pKey->Xtra = r; - pKey->length = pTag->uiLen - t; - pKey->realLength = pTag->uiLen; - pKey->Value = (char *) hb_xgrab( pKey->length + 1 ); - memcpy( pKey->Value, szBuffer, pKey->length ); - pKey->Value[ pKey->length ] = 0; - pKey->fString = ( pTag->uiType == 'C' ? TRUE : FALSE); - - if( PIK->pKeys == NULL ) - { - PIK->pKeys = pKey; - pLastKey = pKey; - } - else - { - if ( !pLastKey ) { - pLastKey = PIK->pKeys; - while( pLastKey->pNext ) - pLastKey = pLastKey->pNext; - } - pLastKey->pNext = pKey; - pLastKey = pKey; - } - PIK->uiKeys++; - i++; - } -#ifndef HB_CDX_DBGCODE_OFF - hb_cdxPageLeafCheckKeys( PIK ); -#endif - } -} - -/* Read a tag definition from the index file - * - * pTag = structure with a tag information +/* + * get free index page */ -static void hb_cdxTagTagLoad( LPCDXTAG pTag ) +static ULONG hb_cdxIndexGetAvailPage( LPCDXINDEX pIndex, BOOL bHeader ) { - CDXTAGHEADER pHeader; - HB_MACRO_PTR pMacro; + FHANDLE hFile = pIndex->hFile; + BYTE byBuf[4]; + ULONG ulPos = 0; - /* read the page from a file */ - hb_cdxIndexLockRead( pTag->pIndex, pTag ); - hb_cdxIndexPageRead( pTag->pIndex, pTag->TagBlock, &pHeader, sizeof( CDXTAGHEADER ) ); - hb_cdxIndexUnLockRead( pTag->pIndex, pTag ); - pTag->RootBlock = pHeader.lRoot; - /* Return if: - * no root page allocated - * invalid root page offset (position inside an index file) - * invalid key value length - */ - if( pTag->RootBlock == 0 || pTag->RootBlock % CDX_PAGELEN > 0 || - (ULONG) pTag->RootBlock > hb_fsSeek( pTag->pIndex->hFile, 0, FS_END ) || - pHeader.uiKeySize > CDX_MAXKEY ) - return; - - pTag->uiLen = pHeader.uiKeySize; - pTag->MaxKeys = ( CDX_PAGELEN - 12 ) / ( pTag->uiLen + 8 ); - pTag->OptFlags = pHeader.bType; - pTag->UniqueKey = ( pTag->OptFlags & 0x01 ); - pTag->Temporary = ( pTag->OptFlags & 0x02 ); - pTag->Custom = ( pTag->OptFlags & 0x04 ); - pTag->AscendKey = ( pHeader.iDescending == 0 ); - pTag->KeyExpr = ( char * ) hb_xgrab( CDX_MAXKEY + 1 ); - /* QUESTION: Is UPPER a valid operation here? - * This will break expressions like: - * somefield+'smallcaps'+otherfield - */ - hb_strncpyUpper( pTag->KeyExpr, ( char * ) pHeader.KeyPool, CDX_MAXKEY ); - - if( pTag->OptFlags < 0x80 && pTag->KeyExpr[ 0 ] == 0 ) - return; - if( pTag->OptFlags & 0x80 ) - return; - - SELF_COMPILE( (AREAP) pTag->pIndex->pArea, ( BYTE * ) pTag->KeyExpr ); - pTag->pKeyItem = pTag->pIndex->pArea->valResult; - pTag->pIndex->pArea->valResult = NULL; - pMacro = ( HB_MACRO_PTR ) hb_itemGetPtr( pTag->pKeyItem ); - hb_macroRun( pMacro ); - /* - This line must be replace the next one when hb_macroRun is fixed. - By now it do the work as only string keys are supported. - - switch( hb_itemType( &(HB_VM_STACK.Return) ) ) - */ - switch( hb_itemType( hb_stackItemFromTop( -1 ) ) ) + if ( pIndex->fReadonly ) { - case HB_IT_INTEGER: - case HB_IT_LONG: - case HB_IT_DOUBLE: - pTag->uiType = 'N'; - /* pTag->uiLen = 10; */ - pTag->uiLen = 8; - break; - - case HB_IT_DATE: - pTag->uiType = 'D'; - pTag->uiLen = 8; - break; - - case HB_IT_LOGICAL: - pTag->uiType = 'L'; - pTag->uiLen = 1; - break; - - case HB_IT_STRING: - pTag->uiType = 'C'; - /* - pTag->uiLen = ( hb_stackItemFromTop( -1 ) )->item.asString.length > CDX_MAXKEY ? CDX_MAXKEY : - ( hb_stackItemFromTop( -1 ) )->item.asString.length; - */ - pTag->uiLen = HB_CDXMAXKEY( ( hb_stackItemFromTop( -1 ) )->item.asString.length ); - break; + hb_errInternal( 9101, "hb_cdxIndexGetAvailPage on readonly database.", "", "" ); } - hb_stackPop(); /* pop macro evaluated value */ - - pTag->nField = hb_rddFieldIndex( (AREAP) pTag->pIndex->pArea, pTag->KeyExpr ); - - /* Check if there is a FOR expression */ - if( pHeader.KeyPool[ strlen( pTag->KeyExpr ) + 1 ] == 0 ) - return; - pTag->ForExpr = ( char * ) hb_xgrab( CDX_MAXKEY + 1 ); - hb_strncpyUpper( pTag->ForExpr, ( const char * ) pHeader.KeyPool + - strlen( pTag->KeyExpr ) + 1, CDX_MAXKEY ); - SELF_COMPILE( (AREAP) pTag->pIndex->pArea, ( BYTE * ) pTag->ForExpr ); - pTag->pForItem = pTag->pIndex->pArea->valResult; - pTag->pIndex->pArea->valResult = NULL; - pMacro = ( HB_MACRO_PTR ) hb_itemGetPtr( pTag->pForItem ); - hb_macroRun( pMacro ); - if( hb_itemType( hb_stackItemFromTop( -1 ) ) != HB_IT_LOGICAL ) + if ( pIndex->fShared && !pIndex->lockWrite ) { - hb_macroDelete( pMacro ); - hb_itemRelease( pTag->pForItem ); - pTag->pForItem = NULL; - hb_xfree( pTag->ForExpr ); - pTag->ForExpr = NULL; + hb_errInternal( 9102, "hb_cdxIndexGetAvailPage on not locked index file.", "", "" ); } - hb_stackPop(); -} -static void hb_cdxTagSetRoot( LPCDXTAG pTag, LPCDXPAGEINFO PIK ) -{ - LONG NRN, TmpTag; - LPCDXKEYINFO p, TmpStr; - - PIK->Owner = hb_cdxPageNew( pTag, NULL, 0 ); - NRN = hb_cdxIndexGetAvailPage( pTag->pIndex ); - PIK->Owner->Page = NRN; - PIK->Owner->PageType = PAGE_ROOT; - if( PIK->uiKeys > 0 ) + if ( pIndex->freePage != 0 && pIndex->freePage != CDX_DUMMYNODE && !bHeader ) { - p = hb_cdxPageGetKey( PIK, PIK->uiKeys - 1 ); - TmpTag = p->Tag; - p->Tag = PIK->Page; - hb_cdxPageInsertKey( PIK->Owner, p, TRUE ); - p->Tag = TmpTag; - } - else - { - TmpStr = hb_cdxKeyNew(); - TmpStr->Tag = PIK->Page; - hb_cdxPageInsertKey( PIK->Owner, TmpStr, TRUE ); - hb_cdxKeyFree( TmpStr ); - } - PIK->Owner->Child = PIK; - pTag->RootPage = PIK->Owner; - pTag->RootBlock = NRN; - pTag->TagChanged = TRUE; -} - -static void hb_cdxTagIntNodeWrite( LPCDXTAG pTag, LONG PN, LPCDXDATA pData, LPCDXPAGEINFO PIK ) -{ - USHORT Cnt, ck, kcnt, na; - LONG rp, lp, NPN, TmpTag; - LPCDXKEYINFO 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 ) + ulPos = pIndex->freePage; + if ( pIndex->freeLst != NULL ) { - hb_cdxErrInternal( "hb_cdxTagIntNodeWrite: too many keys!." ); + LPCDXLIST pLst = pIndex->freeLst; + pIndex->freePage = pLst->ulAddr; + pIndex->freeLst = pLst->pNext; + hb_xfree( pLst ); + } + else + { + if ( hb_fsSeek( hFile, ulPos, FS_SET ) != ulPos || + hb_fsRead( hFile, (BYTE *) &byBuf, 4 ) != 4 ) + hb_errInternal( EDBF_READ, "Read index page failed.", "", "" ); + pIndex->freePage = HB_GET_LE_ULONG( byBuf ); + } + } + else + { + int iCnt = (bHeader ? 2 : 1 ); - ck = hb_cdxTagFillInternalNode( pTag, pData, PIK, kcnt, ck, &p ); - if( pData->Node_Atr % 2 > 0 ) - pData->Node_Atr--; - na = pData->Node_Atr; - rp = pData->Rght_Ptr; - lp = pData->Left_Ptr; - pData->Rght_Ptr = PN; - NPN = hb_cdxIndexGetAvailPage( pTag->pIndex ); - TmpTag = p->Tag; - p->Tag = NPN; - hb_cdxPageAddNodeKey( PIK, p ); - p->Tag = TmpTag; - if( PIK->PageType == PAGE_ROOT ) - PIK->PageType = PAGE_NODE; - hb_cdxIndexPageWrite( pTag->pIndex, NPN, pData, CDX_PAGELEN ); - if( lp > 0 ) + if ( pIndex->nextAvail != CDX_DUMMYNODE ) + ulPos = pIndex->nextAvail; + else + ulPos = hb_fsSeek( hFile, 0, FS_END ); + pIndex->nextAvail = ulPos + iCnt * CDX_PAGELEN; + + /* TODO: ### */ + if ( bHeader ) + { + BYTE byBuf[CDX_PAGELEN]; + memset( byBuf, 0, CDX_PAGELEN ); + if ( hb_fsSeek( hFile, ulPos, FS_SET ) != ulPos ) + hb_errInternal( EDBF_WRITE, "Write in index page failed.(1)", "", "" ); + while ( iCnt-- ) { - hb_cdxIndexPageRead( pTag->pIndex, lp, pData, CDX_PAGELEN ); - pData->Rght_Ptr = NPN; - hb_cdxIndexPageWrite( pTag->pIndex, lp, pData, CDX_PAGELEN ); + if ( hb_fsWrite( hFile, byBuf, CDX_PAGELEN ) != CDX_PAGELEN ) + hb_errInternal( EDBF_WRITE, "Write in index page failed.(2)", "", "" ); } - memset( pData, 32, CDX_PAGELEN ); - pData->Node_Atr = na; - pData->Rght_Ptr = rp; - pData->Left_Ptr = NPN; - pData->Entry_Ct = 0; - kcnt = pTag->MaxKeys; } - hb_cdxTagFillInternalNode( pTag, pData, PIK, kcnt, ck, &p ); } - hb_cdxIndexPageWrite( pTag->pIndex, PN, pData, CDX_PAGELEN ); + return ulPos; } -static USHORT hb_cdxTagFillInternalNode( LPCDXTAG pTag, LPCDXDATA pData, - LPCDXPAGEINFO PIK, USHORT kcnt, - USHORT ck, LPCDXKEYINFO * p ) +/* + * free index page + */ +static void hb_cdxIndexPutAvailPage( LPCDXINDEX pIndex, ULONG ulPos, BOOL bHeader ) { - USHORT i, v; - LONG r; - - i = 0; - memset( pData->cdxu.Internal.IntData, ( pTag->uiType == 'C' ) ? 32 : 0, - sizeof( pData->cdxu.Internal.IntData ) ); - while( i < kcnt && ck < PIK->uiKeys ) + if ( ulPos != 0 && ulPos != CDX_DUMMYNODE ) { - * p = hb_cdxPageGetKey( PIK, ck ); - v = i * ( pTag->uiLen + 8 ); - memcpy( &pData->cdxu.Internal.IntData[ v ], - ( * p )->Value, - ( * p )->length ); - v += pTag->uiLen; - r = hb_cdxSwapBytes( ( * p )->Xtra ); - memcpy( &pData->cdxu.Internal.IntData[ v ], &r, 4 ); - r = hb_cdxSwapBytes( ( * p )->Tag ); - memcpy( &pData->cdxu.Internal.IntData[ v + 4 ], &r, 4 ); - i++; - ck++; - pData->Entry_Ct++; - } - return ck; -} + int iCnt = (bHeader ? 2 : 1 ); + LPCDXLIST pLst; -static void hb_cdxTagIntNodeBuild( LPCDXTAG pTag, LPCDXDATA pData, LPCDXPAGEINFO pPage ) -{ - USHORT i, v; - LONG r, n; - LPCDXKEYINFO pKey, pLastKey; - static char szBuffer[ CDX_MAXKEY + 1 ]; + if ( pIndex->fReadonly ) + hb_errInternal( 9101, "hb_cdxIndexPutAvailPage on readonly database.", "", "" ); + if ( pIndex->fShared && !pIndex->lockWrite ) + hb_errInternal( 9102, "hb_cdxIndexPutAvailPage on not locked index file.", "", "" ); - i = 0; - while( i < pData->Entry_Ct ) - { - v = i * ( pTag->uiLen + 8 ); - memmove( szBuffer, pData->cdxu.Internal.IntData + v, pTag->uiLen ); - szBuffer[ pTag->uiLen ] = 0; - v += pTag->uiLen; - memcpy( &r, &pData->cdxu.Internal.IntData[ v ], 4 ); - r = hb_cdxSwapBytes( r ); - memcpy( &n, &pData->cdxu.Internal.IntData[ v + 4 ], 4 ); - n = hb_cdxSwapBytes( n ); - pKey = hb_cdxKeyNew(); - if( pTag->uiType == 'C' ) + while ( iCnt-- ) { - v = pTag->uiLen; // strlen( szBuffer ); - while( v > 0 && szBuffer[ v - 1 ] == ' ' ) - v--; - szBuffer[ v ] = 0; + pLst = (LPCDXLIST) hb_xgrab( sizeof( CDXLIST ) ); + pLst->ulAddr = pIndex->freePage; + pIndex->freePage = ulPos; + pLst->fStat = TRUE; + pLst->pNext = pIndex->freeLst; + pIndex->freeLst = pLst; + ulPos += CDX_PAGELEN; } - else - { - v = pTag->uiLen; - while( v > 0 && szBuffer[ v - 1 ] == 0 ) - v--; - szBuffer[ v ] = 0; - } - pKey->realLength = pTag->uiLen; - pKey->length = v; - pKey->Value = (char *) hb_xgrab( v + 1 ); - memcpy( pKey->Value, szBuffer, v ); - pKey->Value[v] = 0; - pKey->fString = ( pTag->uiType == 'C' ? TRUE : FALSE); - - pKey->Tag = n; - pKey->Xtra = r; - if( pPage->pKeys == NULL ) - pPage->pKeys = pKey; - else - { - pLastKey = pPage->pKeys; - while( pLastKey->pNext != NULL ) - pLastKey = pLastKey->pNext; - pLastKey->pNext = pKey; - } - pPage->uiKeys++; - i++; } } -static LONG hb_cdxTagKeyFind( LPCDXTAG pTag, LPCDXKEYINFO pKey ) +/* + * flush list of free pages into index file + */ +static void hb_cdxIndexFlushAvailPage( LPCDXINDEX pIndex ) { - int K; - LONG ret = 0; + LPCDXLIST pLst = pIndex->freeLst; + BYTE byPageBuf[CDX_PAGELEN]; + ULONG ulPos; - pTag->CurKeyInfo->Tag = 0; - hb_cdxTagTagOpen( pTag, 0 ); - if( pTag->RootPage == NULL ) - return 0; - pTag->TagBOF = pTag->TagEOF = FALSE; - K = hb_cdxPageSeekKey( pTag->RootPage, pKey->Tag, pKey, FALSE ); - if( K == 0 ) - { - hb_cdxPageRetrieveKey( pTag->RootPage, &pTag->CurKeyInfo ); - ret = pTag->CurKeyInfo->Tag; - } - else if( K < 0 ) - { - hb_cdxPageRetrieveKey( pTag->RootPage, &pTag->CurKeyInfo ); - } - else - pTag->TagEOF = TRUE; + if ( pIndex->fReadonly ) + hb_errInternal( 9101, "hb_cdxIndexPutAvailPage on readonly database.", "", "" ); + if ( pIndex->fShared && !pIndex->lockWrite ) + hb_errInternal( 9102, "hb_cdxIndexPutAvailPage on not locked index file.", "", "" ); - if ( pKey->Tag == CDX_MAX_REC_NUM ) { - hb_cdxPageRetrieveKey( pTag->RootPage, &pTag->CurKeyInfo ); - if( pTag->AscendKey ) - hb_cdxTagKeyRead( pTag, PREV_RECORD ); - else - hb_cdxTagKeyRead( pTag, NEXT_RECORD ); - if ( pTag->CurKeyInfo->Tag ) { - if ( hb_cdxKeyCompare( pKey, pTag->CurKeyInfo, FALSE ) == 0 ) - ret = pTag->CurKeyInfo->Tag; + memset( byPageBuf, 0, CDX_PAGELEN ); + ulPos = pIndex->freePage; + while ( pLst && pLst->fStat ) + { + HB_PUT_LE_ULONG( byPageBuf, pLst->ulAddr ); + if ( hb_fsSeek( pIndex->hFile, ulPos, FS_SET ) != ulPos || + hb_fsWrite( pIndex->hFile, byPageBuf, CDX_PAGELEN ) != CDX_PAGELEN ) + { + hb_errInternal( EDBF_WRITE, "Write in index page failed.", "", "" ); } + pIndex->fChanged = TRUE; + ulPos = pLst->ulAddr; + pLst->fStat = FALSE; + pLst = pLst->pNext; + } +} + +/* + * drop list of free pages in index file + */ +static void hb_cdxIndexDropAvailPage( LPCDXINDEX pIndex ) +{ + LPCDXLIST pLst; + + while ( pIndex->freeLst ) + { + pLst = pIndex->freeLst->pNext; + hb_xfree( pIndex->freeLst ); + pIndex->freeLst = pLst; + } +} + +/* + * write index page + */ +static void hb_cdxIndexPageWrite( LPCDXINDEX pIndex, ULONG ulPos, BYTE * pBuffer, + USHORT uiSize ) +{ + if ( pIndex->fReadonly ) + hb_errInternal( 9101, "hb_cdxIndexPageWrite on readonly database.", "", "" ); + if ( pIndex->fShared && !pIndex->lockWrite ) + hb_errInternal( 9102, "hb_cdxIndexPageWrite on not locked index file.", "", "" ); + + if ( hb_fsSeek( pIndex->hFile, ulPos, FS_SET ) != ulPos || + hb_fsWrite( pIndex->hFile, pBuffer, uiSize ) != uiSize ) + hb_errInternal( EDBF_WRITE, "Write in index page failed.", "", "" ); + pIndex->fChanged = TRUE; +} + +/* + * read index page + */ +static void hb_cdxIndexPageRead( LPCDXINDEX pIndex, ULONG ulPos, BYTE * pBuffer, + USHORT uiSize ) +{ + if ( pIndex->fShared && !( pIndex->lockRead || pIndex->lockWrite ) ) + hb_errInternal( 9103, "hb_cdxIndexPageRead on not locked index file.", "", "" ); + + if ( hb_fsSeek( pIndex->hFile, ulPos, FS_SET ) != ulPos || + hb_fsRead( pIndex->hFile, pBuffer, uiSize ) != uiSize ) + hb_errInternal( EDBF_READ, "Read index page failed.", "", "" ); +} + +/* + * check if index was updated by other process and if it was discard buffers + */ +static void hb_cdxIndexCheckVersion( LPCDXINDEX pIndex ) +{ + BYTE byBuf[8]; + ULONG ulVer, ulFree; + + if ( hb_fsSeek( pIndex->hFile, 0x04, FS_SET ) != 0x04 || + hb_fsRead( pIndex->hFile, byBuf, 8 ) != 8 ) + { + if ( pIndex->lockWrite > 0 && hb_fsSeek( pIndex->hFile, 0, FS_END ) == 0 ) + memset( byBuf, 0, 8 ); + else + hb_errInternal( 2155, "hb_cdxIndexCheckVersion: Read error on index heading page.", "", "" ); + } + ulFree = HB_GET_LE_ULONG( &byBuf[0] ); + ulVer = HB_GET_BE_ULONG( &byBuf[4] ); + if ( ulVer != pIndex->ulVersion || ulFree != pIndex->freePage ) + { + pIndex->nextAvail = CDX_DUMMYNODE; + pIndex->ulVersion = ulVer; + pIndex->freePage = ulFree; + hb_cdxIndexDiscardBuffers( pIndex ); + } + /* TODO: !!! ## remove it */ + //hb_cdxIndexDiscardBuffers( pIndex ); +} + +/* + * lock index for reading (shared lock) + */ +static BOOL hb_cdxIndexLockRead( LPCDXINDEX pIndex ) +{ + BOOL ret; + + if ( pIndex->lockRead > 0 || pIndex->lockWrite > 0 || !pIndex->fShared ) + { + pIndex->lockRead++; + return TRUE; + } + if ( pIndex->lockRead != 0 ) + hb_errInternal( 9105, "hb_cdxIndexLockRead: bad count of locks.", "", "" ); + + while (! (ret = hb_fsLock ( pIndex->hFile, CDX_LOCKOFFSET, CDX_LOCKSIZE, + FL_LOCK | FLX_SHARED | FLX_WAIT ) ) ); + if ( !ret ) + /* TODO: change into RT error dbfcdx/1038 */ + hb_errInternal( 9107, "hb_cdxIndexLockRead: lock failure.", "", "" ); + if ( ret ) + { + pIndex->lockRead++; + hb_cdxIndexCheckVersion( pIndex ); } return ret; } -/* end hb_cdxTagxxx */ -/* end hb_cdxTagxxx */ - -/* hb_cdxPagexxx */ -/* #include "cdxpage.c" */ - -/* hb_cdxPagexxx */ - -static LPCDXPAGEINFO hb_cdxPageNew( LPCDXTAG pTag, LPCDXPAGEINFO PIK, LONG FilePosn ) +/* + * lock index for writing (exclusive lock) + */ +static BOOL hb_cdxIndexLockWrite( LPCDXINDEX pIndex ) { - LPCDXPAGEINFO pPage; - pPage = NULL; - /* - if ( pTag->ulVersion != pTag->pIndex->ulVersion ) + BOOL ret; + + if ( pIndex->lockRead ) + hb_errInternal( 9105, "hb_cdxIndexLockRead: writeLock after readLock.", "", "" ); + if ( pIndex->lockWrite > 0 || !pIndex->fShared ) { - hb_cdxPagePoolFree( pTag->pIndex ); + pIndex->lockWrite++; + return TRUE; + } + if ( pIndex->lockWrite != 0 ) + hb_errInternal( 9105, "hb_cdxIndexLockWrite: bad count of locks.", "", "" ); + + while (! (ret = hb_fsLock ( pIndex->hFile, CDX_LOCKOFFSET, CDX_LOCKSIZE, + FL_LOCK | FLX_EXCLUSIVE | FLX_WAIT ) ) ); + if ( !ret ) + /* TODO: change into RT error dbfcdx/1038 */ + hb_errInternal( 9107, "hb_cdxIndexLockWrite: lock failure.", "", "" ); + if ( ret ) + { + pIndex->lockWrite++; + hb_cdxIndexCheckVersion( pIndex ); + } + return ret; +} + +/* + * remove index read lock (shared lock) + */ +static BOOL hb_cdxIndexUnLockRead( LPCDXINDEX pIndex ) +{ + pIndex->lockRead--; + if ( pIndex->lockRead < 0 ) + { + hb_errInternal( 9106, "hb_cdxIndexUnLockRead: bad count of locks.", "", "" ); + } + if ( pIndex->lockRead || pIndex->lockWrite ) + { + return TRUE; } - */ #ifndef HB_CDX_DBGCODE_OFF - hb_cdxPagePoolCheck( pTag ); + hb_cdxIndexCheckBuffers( pIndex ); #endif - if ( ( FilePosn > 0 ) && pTag->pagePool ) + + hb_cdxIndexPoolFree( pIndex, CDX_PAGECACHESIZE ); + + if ( pIndex->fShared ) + { + if ( !hb_fsLock ( pIndex->hFile, CDX_LOCKOFFSET, CDX_LOCKSIZE, FL_UNLOCK ) ) + { + hb_errInternal( 9108, "hb_cdxIndexUnLockRead: unlock error.", "", "" ); + } + } + return TRUE; +} + +/* + * remove index write lock (exclusive lock) + */ +static BOOL hb_cdxIndexUnLockWrite( LPCDXINDEX pIndex ) +{ + if ( pIndex->lockWrite > 1 ) + { + pIndex->lockWrite--; + return TRUE; + } + + if ( pIndex->lockWrite < 1 ) + { + hb_errInternal( 9106, "hb_cdxIndexUnLockRead: bad count of locks.", "", "" ); + } + if ( pIndex->lockRead ) + { + hb_errInternal( 9105, "hb_cdxIndexUnLockWrite: writeUnLock before readUnLock.", "", "" ); + } + + hb_cdxIndexFlushBuffers( pIndex ); + hb_cdxIndexPoolFree( pIndex, CDX_PAGECACHESIZE ); + + pIndex->lockWrite--; + if ( pIndex->fShared ) + { + if ( pIndex->fChanged ) + { + BYTE byBuf[8]; + (pIndex->ulVersion)++; + HB_PUT_LE_ULONG( &byBuf[0], pIndex->freePage ); + HB_PUT_BE_ULONG( &byBuf[4], pIndex->ulVersion ); + if ( hb_fsSeek( pIndex->hFile, 0x04, FS_SET ) != 0x04 || + hb_fsWrite( pIndex->hFile, byBuf, 8) != 8 ) + { + hb_errInternal( EDBF_WRITE, "Write in index page failed (ver)", "", "" ); + } + pIndex->fChanged = FALSE; + } + if ( !hb_fsLock ( pIndex->hFile, CDX_LOCKOFFSET, CDX_LOCKSIZE, FL_UNLOCK ) ) + { + hb_errInternal( 9108, "hb_cdxIndexUnLockWrite: unlock error.", "", "" ); + } + } + else + { + pIndex->fChanged = FALSE; + } + return TRUE; +} + +/* + * discard all pages in cache (TagClose and TagPoolFree for all Tags) + */ +static void hb_cdxIndexDiscardBuffers( LPCDXINDEX pIndex ) +{ + LPCDXTAG pTag; + +#ifndef HB_CDX_DBGCODE_OFF + hb_cdxIndexCheckBuffers( pIndex ); +#endif + + hb_cdxIndexDropAvailPage( pIndex ); + if ( pIndex->pCompound ) + { + hb_cdxTagClose( pIndex->pCompound ); + hb_cdxTagPoolFree( pIndex->pCompound, 0 ); + pIndex->pCompound->fRePos = TRUE; + if ( pIndex->pCompound->CurKey ) + pIndex->pCompound->CurKey->rec = 0; + } + pTag = pIndex->TagList; + while ( pTag ) + { + hb_cdxTagClose( pTag ); + hb_cdxTagPoolFree( pTag, 0 ); + pTag->fRePos = TRUE; + if ( pTag->CurKey && !pTag->Custom ) + pTag->CurKey->rec = 0; + pTag = pTag->pNext; + } +} + +/* + * write all changed pages in cache (pagePool, pages in Tags and Tag Header) + */ +static void hb_cdxIndexFlushBuffers( LPCDXINDEX pIndex ) +{ + LPCDXTAG pTag; + + if ( pIndex->pCompound ) + { + hb_cdxTagPoolFlush( pIndex->pCompound ); + if ( pIndex->pCompound->TagChanged ) + hb_cdxTagHeaderStore( pIndex->pCompound ); + } + pTag = pIndex->TagList; + while ( pTag ) + { + hb_cdxTagPoolFlush( pTag ); + if ( pTag->TagChanged ) + hb_cdxTagHeaderStore( pTag ); + pTag = pTag->pNext; + } + hb_cdxIndexFlushAvailPage( pIndex ); +} + +/* + * free cached pages of index file + */ +static void hb_cdxIndexPoolFree( LPCDXINDEX pIndex, int nPagesLeft ) +{ + LPCDXTAG pTag; + + if ( pIndex->pCompound ) + { + hb_cdxTagPoolFree( pIndex->pCompound, nPagesLeft ); + } + pTag = pIndex->TagList; + while ( pTag ) + { + hb_cdxTagPoolFree( pTag, nPagesLeft ); + pTag = pTag->pNext; + } +} + +/* + * get key value ptr from index page + */ +static BYTE * hb_cdxPageGetKeyVal( LPCDXPAGE pPage, SHORT iKey ) +{ +#ifndef HB_CDX_DBGCODE_OFF + if ( iKey < 0 || iKey >= pPage->iKeys ) + hb_cdxErrInternal( "hb_cdxPageGetKeyVal: wrong iKey index." ); +#endif + if ( pPage->pKeyBuf ) + return &pPage->pKeyBuf[ iKey * ( pPage->TagParent->uiLen + 6 ) ]; + else if ( pPage->PageType & CDX_NODE_LEAF ) + { + SHORT iPos, iLen, iTmp, iTrl, iDup; + BYTE bTrail; + + iLen = pPage->TagParent->uiLen; + bTrail = ( pPage->TagParent->uiType == 'C' ) ? ' ' : '\0'; + if ( iKey < pPage->bufKeyNum - 1 ) + pPage->bufKeyNum = 0; + if ( pPage->bufKeyNum == 0 ) + { + pPage->bufKeyPos = CDX_EXT_FREESPACE; + pPage->bufKeyLen = iLen; + } + while ( pPage->bufKeyNum <= iKey ) + { + iPos = pPage->bufKeyNum * pPage->ReqByte; + iTmp = HB_GET_LE_USHORT( &pPage->node.extNode.keyPool[ iPos + pPage->ReqByte - 2 ] ) >> + ( 16 - pPage->TCBits - pPage->DCBits ); + iDup = ( pPage->bufKeyNum == 0 ) ? 0 : ( iTmp & pPage->DCMask ); + iTrl = ( iTmp >> pPage->DCBits ) & pPage->TCMask; + if ( ( iTmp = iLen - iDup - iTrl ) > 0 ) + { + pPage->bufKeyPos -= iTmp; + memcpy( &pPage->bufKeyVal[ iDup ], + &pPage->node.extNode.keyPool[ pPage->bufKeyPos ], iTmp ); + } + if ( iTrl > 0 && ( iTmp = pPage->bufKeyLen - iLen + iTrl ) > 0 ) + memset( &pPage->bufKeyVal[ iLen - iTrl ], bTrail, iTmp ); + pPage->bufKeyLen = iLen - iTrl; + pPage->bufKeyNum++; + } + return pPage->bufKeyVal; + } + else + return &pPage->node.intNode.keyPool[ iKey * ( pPage->TagParent->uiLen + 8 ) ]; +} + +/* + * get record number from index page + */ +static ULONG hb_cdxPageGetKeyRec( LPCDXPAGE pPage, SHORT iKey ) +{ +#ifndef HB_CDX_DBGCODE_OFF + if ( iKey < 0 || iKey >= pPage->iKeys ) + hb_cdxErrInternal( "hb_cdxPageGetKeyRec: wrong iKey index." ); +#endif + if ( pPage->pKeyBuf ) + return HB_GET_LE_ULONG( &pPage->pKeyBuf[ ( iKey + 1 ) * ( pPage->TagParent->uiLen + 6 ) - 6 ] ); + else if ( pPage->PageType & CDX_NODE_LEAF ) + return HB_GET_LE_ULONG( &pPage->node.extNode.keyPool[ iKey * pPage->ReqByte ] ) & pPage->RNMask; + else + return HB_GET_BE_ULONG( &pPage->node.intNode.keyPool[ + ( iKey + 1 ) * ( pPage->TagParent->uiLen + 8 ) - 8 ] ); +} + +/* + * get child page number from interrior index page + */ +static ULONG hb_cdxPageGetKeyPage( LPCDXPAGE pPage, SHORT iKey ) +{ +#ifndef HB_CDX_DBGCODE_OFF + if ( iKey < 0 || iKey >= pPage->iKeys ) + hb_cdxErrInternal( "hb_cdxPageGetKeyPage: wrong iKey index." ); + if ( pPage->PageType & CDX_NODE_LEAF ) + hb_cdxErrInternal( "hb_cdxPageGetKeyPage: page is a leaf." ); +#endif + return HB_GET_BE_ULONG( &pPage->node.intNode.keyPool[ + ( iKey + 1 ) * ( pPage->TagParent->uiLen + 8 ) - 4 ] ); +} + +#if 0 +/* + * get key from uncompressed page + */ +static LPCDXKEY hb_cdxPageGetKey( LPCDXPAGE pPage, SHORT iKey, LPCDXKEY pKey ) +{ + return hb_cdxKeyPut( pKey, + hb_cdxPageGetKeyVal( pPage, iKey ), + pPage->TagParent->uiLen, + hb_cdxPageGetKeyRec( pPage, iKey ) ); +} +#endif + +#ifndef HB_CDX_DBGCODE_OFF +/* + * check if keys are sorted in proper order + */ +static void hb_cdxPageCheckKeys( LPCDXPAGE pPage ) +{ + SHORT i, K, iLen = pPage->TagParent->uiLen; + ULONG ulRec, ulRecPrev; + BYTE * pbVal, pbValPrev[CDX_MAXKEY]; + + if ( pPage->iKeys > 1 ) + { + pPage->bufKeyNum = 0; + pbVal = hb_cdxPageGetKeyVal( pPage, 0 ); + ulRec = hb_cdxPageGetKeyRec( pPage, 0 ); + for ( i = 1; i < pPage->iKeys; i++ ) + { + memcpy( pbValPrev, pbVal, iLen ); + ulRecPrev = ulRec; + pbVal = hb_cdxPageGetKeyVal( pPage, i ); + ulRec = hb_cdxPageGetKeyRec( pPage, i ); + K = hb_cdxValCompare( pPage->TagParent, + pbValPrev, iLen, + pbVal, iLen, TRUE ); + if ( K > 0 || ( K == 0 && ulRecPrev >= ulRec ) ) + { + printf( "\r\nikey=%d, pPage->iKeys=%d, K=%d, ulRecPrev=%ld, ulRec=%ld", + i, pPage->iKeys, K, ulRecPrev, ulRec );fflush(stdout); + printf( "\r\npbValPrev=[%s] pbVal=[%s], [%d], pPage->pKeyBuf=%p, pPage->iCurKey=%d", + pbValPrev, pbVal, memcmp( pbValPrev, pbVal, iLen ), + pPage->pKeyBuf, pPage->iCurKey );fflush(stdout); + hb_cdxErrInternal( "hb_cdxPageCheckKeys: index corrupted." ); + } + } + } +} + +/* + * Check decoded leaf page if all trailing and duplicate characters are set + */ +static void hb_cdxPageCheckDupTrl( LPCDXPAGE pPage, BYTE * pKeyBuf, SHORT iKeys ) +{ + SHORT iNum = pPage->TagParent->uiLen, iKey, iPos; + SHORT iLen = iNum + 6; + BYTE bDup, bTrl; + BYTE bTrail = ( pPage->TagParent->uiType == 'C' ) ? ' ' : '\0'; + BOOL bErr = FALSE; + + for ( iKey = 0; iKey < iKeys; iKey++ ) + { + iPos = iKey * iLen; + bTrl = bDup = 0; + while ( bTrl < iNum && pKeyBuf[ iPos + iNum - bTrl - 1 ] == bTrail ) + ++bTrl; + if ( iKey > 0 ) + { + SHORT iMax = iNum - /* bTrl; */ HB_MAX( pKeyBuf[ iPos - 1 ], bTrl ); + while ( bDup < iMax && pKeyBuf[ iPos + bDup ] == + pKeyBuf[ iPos - iLen + bDup ] ) + ++bDup; + } + if ( bTrl != pKeyBuf[ iPos + iNum + 5 ] ) + { + printf("\r\nbTrl=%d, keybuf->bTrl=%d, iKey=%d/%d\r\n", bTrl, pKeyBuf[ iPos + iNum + 5 ], iKey, iKeys ); + fflush(stdout); + bErr = TRUE; + } + if ( bDup != ( iKey == 0 ? 0 : pKeyBuf[ iPos + iNum + 4 ] ) ) + { + printf("\r\nbDup=%d, keybuf->bDup=%d, iKey=%d/%d\r\n", bDup, pKeyBuf[ iPos + iNum + 4 ], iKey, iKeys ); + fflush(stdout); + bErr = TRUE; + } + if ( iKey > 0 ) + { + SHORT K; + K = hb_cdxValCompare( pPage->TagParent, + &pKeyBuf[ iPos - iLen ], iNum, + &pKeyBuf[ iPos ], iNum, TRUE ); + if ( K > 0 || ( K == 0 && + HB_GET_LE_ULONG( &pKeyBuf[ iPos + iNum - iLen ] ) >= + HB_GET_LE_ULONG( &pKeyBuf[ iPos + iNum ] ) ) ) + { + printf( "\r\nikey=%d, iKeys=%d, K=%d, ulRecPrev=%ld, ulRec=%ld", + iKey, iKeys, K, + HB_GET_LE_ULONG( &pKeyBuf[ iPos + iNum - iLen ] ), + HB_GET_LE_ULONG( &pKeyBuf[ iPos + iNum ] ) ); + printf( "\r\npbValPrev=[%s] pbVal=[%s], [%d], pKeyBuf=%p", + &pKeyBuf[ iPos - iLen ], &pKeyBuf[ iPos ], + memcmp( &pKeyBuf[ iPos - iLen ], &pKeyBuf[ iPos ], iNum ), + pKeyBuf ); + fflush(stdout); + bErr = TRUE; + } + } + } + if ( bErr ) + hb_cdxErrInternal( "hb_cdxPageCheckDupTrl: index corrupted." ); +} +#endif + +/* + * encode keys in buffer into cdx leaf node + */ +static void hb_cdxPageLeafEncode( LPCDXPAGE pPage, BYTE * pKeyBuf, SHORT iKeys ) +{ + SHORT iKey, iPos, iTrl, iDup, iTmp, iNum = pPage->TagParent->uiLen; + SHORT iLen = iNum + 6, iRecPos, iWrPos; + ULONG ulRec; + +#ifndef HB_CDX_DBGCODE_OFF + if ( ( pPage->PageType & CDX_NODE_LEAF ) == 0 ) + { + printf("\r\npPage->Page=%lx. left=%lx, right=%lx", + pPage->Page, pPage->Left, pPage->Right); fflush(stdout); + hb_cdxErrInternal( "hb_cdxPageLeafEncode: page is not a leaf." ); + } + if ( ! pKeyBuf ) + hb_cdxErrInternal( "hb_cdxPageLeafEncode: page has no buffer." ); +#endif + iWrPos = CDX_EXT_FREESPACE; + for ( iKey = 0; iKey < iKeys; iKey++ ) + { + iPos = iKey * iLen; + ulRec = HB_GET_LE_ULONG( &pKeyBuf[ iPos + iNum ] ); + iDup = pKeyBuf[ iPos + iNum + 4 ]; + iTrl = pKeyBuf[ iPos + iNum + 5 ]; + iRecPos = iKey * pPage->ReqByte; + HB_PUT_LE_USHORT( &pPage->node.extNode.keyPool[ iRecPos + pPage->ReqByte - 2 ], + ( iTrl << ( 16 - pPage->TCBits ) ) | + ( iDup << ( 16 - pPage->TCBits - pPage->DCBits ) ) ); + HB_PUT_LE_ULONG( &pPage->node.extNode.keyPool[ iRecPos ], + ( HB_GET_LE_ULONG( &pPage->node.extNode.keyPool[ iRecPos ] ) & ~pPage->RNMask ) | ulRec ); + if ( ( iTmp = iNum - iTrl - iDup ) > 0 ) + { + iWrPos -= iTmp; + memcpy( &pPage->node.extNode.keyPool[ iWrPos ], + &pKeyBuf[ iPos + iDup ], iTmp ); + } + } + iRecPos = iKeys * pPage->ReqByte; + if ( iRecPos < iWrPos ) + memset( &pPage->node.extNode.keyPool[ iRecPos ], 0, iWrPos - iRecPos ); +#ifndef HB_CDX_DBGCODE_OFF + if ( iWrPos - iRecPos != pPage->iFree ) + { + printf("\r\nPage=%ld, calc=%d,iFree=%d, req=%d, keys=%d, wrpos=%d\r\n", + pPage->Page,iWrPos - iRecPos, pPage->iFree, pPage->ReqByte, iKeys, iWrPos); + fflush(stdout); + hb_cdxErrInternal( "hb_cdxPageLeafEncode: FreeSpace calculated wrong!." ); + } + if ( pPage->iFree < 0 ) + hb_cdxErrInternal( "hb_cdxPageLeafEncode: FreeSpace calculated wrong!!." ); +#endif + pPage->iKeys = iKeys; + pPage->fChanged = TRUE; + pPage->bufKeyNum = 0; +#ifndef HB_CDX_DBGCODE_OFF + hb_cdxPageCheckKeys( pPage ); + hb_cdxPageCheckDupTrl( pPage, pKeyBuf, pPage->iKeys ); +#endif +} + +/* + * decode keys in page into buffer + */ +static void hb_cdxPageLeafDecode( LPCDXPAGE pPage, BYTE * pKeyBuf ) +{ + SHORT iKey, iTmp, iLen = pPage->TagParent->uiLen, iBits; + BYTE bDup, bTrl, bReq, *pDst, *pSrc, *pRec, + bTrail = ( pPage->TagParent->uiType == 'C' ) ? ' ' : '\0'; + +#ifndef HB_CDX_DBGCODE_OFF + if ( ( pPage->PageType & CDX_NODE_LEAF ) == 0 ) + { + printf("\r\npPage->Page=%lx", pPage->Page); fflush(stdout); + hb_cdxErrInternal( "hb_cdxPageLeafDecode: page is not a leaf." ); + } +#endif + iBits = ( 16 - pPage->TCBits - pPage->DCBits ); + pDst = pKeyBuf; + pSrc = &pPage->node.extNode.keyPool[ CDX_EXT_FREESPACE ]; + pRec = pPage->node.extNode.keyPool; + bReq = pPage->ReqByte; + for ( iKey = 0; iKey < pPage->iKeys; iKey++, pRec += bReq ) + { + iTmp = HB_GET_LE_USHORT( &pRec[ bReq - 2 ] ) >> iBits; + bDup = ( iKey == 0 ) ? 0 : ( iTmp & pPage->DCMask ); + bTrl = ( iTmp >> pPage->DCBits ) & pPage->TCMask; + if ( bDup != 0 ) + { + memcpy( pDst, pDst - iLen - 6, bDup ); + pDst += bDup; + } + if ( ( iTmp = iLen - bDup - bTrl ) > 0 ) + { + pSrc -= iTmp; + memcpy( pDst, pSrc, iTmp ); + pDst += iTmp; + } + if ( bTrl != 0 ) + { + memset( pDst, bTrail, bTrl ); + pDst += bTrl; + } + HB_PUT_LE_ULONG( pDst, HB_GET_LE_ULONG( pRec ) & pPage->RNMask ); + pDst += 4; + *(pDst++) = bDup; + *(pDst++) = bTrl; + } +#ifndef HB_CDX_DBGCODE_OFF + { + BOOL fChg = pPage->fChanged; + hb_cdxPageLeafEncode( pPage, pKeyBuf, pPage->iKeys ); + pPage->fChanged = fChg; + } +#endif +} + +/* + * init space leaf page + */ +static void hb_cdxPageLeafInitSpace( LPCDXPAGE pPage ) +{ + SHORT iLen = pPage->TagParent->uiLen; + BYTE bBits; + + for ( bBits = 0; iLen; bBits++, iLen >>= 1 ); + pPage->ReqByte = 3; + pPage->RNBits = 24 - bBits * 2; + pPage->DCBits = pPage->TCBits = bBits; + pPage->DCMask = pPage->TCMask = (BYTE) HB_CDXBITMASK( bBits ); + pPage->RNMask = HB_CDXBITMASK( pPage->RNBits ); + pPage->iFree = CDX_EXT_FREESPACE; +} + +/* + * calculate the size of keys stored in buffer, return + * the nymber of keys wich can be stored in the page + */ +static void hb_cdxPageCalcLeafSpace( LPCDXPAGE pPage, BYTE * pKeyBuf, SHORT iKeys ) +{ + SHORT iNum = pPage->TagParent->uiLen, iKey, iSize; + SHORT iLen = iNum + 6; + BYTE bDup, bTrl, ReqByte, *bPtr; + ULONG ulRec, RNMask; + + hb_cdxPageLeafInitSpace( pPage ); + pPage->iKeys = 0; + RNMask = pPage->RNMask; + ReqByte = pPage->ReqByte; +#ifndef HB_CDX_DBGCODE_OFF + hb_cdxPageCheckDupTrl( pPage, pKeyBuf, iKeys ); +#endif + for ( iKey = 0; iKey < iKeys; iKey++ ) + { + bPtr = &pKeyBuf[ iKey * iLen + iNum ]; + bTrl = bPtr[ 5 ]; + if ( iKey == 0 ) + bDup = bPtr[ 4 ] = 0; + else + bDup = bPtr[ 4 ]; + ulRec = HB_GET_LE_ULONG( bPtr ); + iSize = ReqByte + iNum - bTrl - bDup; + if ( ulRec > RNMask ) + { + BYTE RNBits = pPage->RNBits; + while ( ulRec > RNMask ) + { + ReqByte++; + RNBits += 8; + RNMask = ( RNMask << 8 ) | 0xFF; + iSize += ( iKey + 1 ); + } + if ( iSize > pPage->iFree ) + break; +#ifdef HB_CDX_DSPDBG_INFO_X + printf("\r\npPage->Page=%lx, ulRec=%lx, RNMask=%lx/%lx, RNBits=%d/%d, DCB=%d, TCB=%d (%lx), iKey=%d/%d", + pPage->Page, ulRec, RNMask, pPage->RNMask, RNBits, pPage->RNBits, + pPage->DCBits, pPage->TCBits, HB_CDXBITMASK( RNBits ), iKey, iKeys); + fflush(stdout); +#endif + pPage->RNMask = RNMask; + pPage->RNBits = RNBits; + pPage->ReqByte = ReqByte; + } + else if ( iSize > pPage->iFree ) + break; + pPage->iFree -= iSize; + pPage->iKeys++; + } +} + +/* + * remove key from page + */ +static int hb_cdxPageLeafDelKey( LPCDXPAGE pPage ) +{ + SHORT iKey = pPage->iCurKey, iLen = pPage->TagParent->uiLen + 6, iSpc; + int iRet = 0; + +#ifndef HB_CDX_DBGCODE_OFF + if ( ( pPage->PageType & CDX_NODE_LEAF ) == 0 ) + hb_cdxErrInternal( "hb_cdxPageLeafDelKey: page is not a leaf." ); + if ( iKey < 0 || iKey >= pPage->iKeys ) + hb_cdxErrInternal( "hb_cdxPageLeafDelKey: wrong iKey index." ); +#endif + if ( !pPage->pKeyBuf ) + { + BYTE *pKeyBuf = (BYTE *) hb_xgrab( ( pPage->iKeys ) * iLen ); + hb_cdxPageLeafDecode( pPage, pKeyBuf ); + pPage->pKeyBuf = pKeyBuf; + } +#ifdef HB_CDX_DSPDBG_INFO + printf("\r\ndelkey: Page=%lx, iKey=%d/%d, rec=%ld", + pPage->Page, iKey, pPage->iKeys, + HB_GET_LE_ULONG( &pPage->pKeyBuf[ ( iKey + 1 ) * iLen - 6 ] )); + fflush(stdout); +#endif + iSpc = pPage->ReqByte + pPage->TagParent->uiLen - + pPage->pKeyBuf[ ( iKey + 1 ) * iLen - 2 ] - + pPage->pKeyBuf[ ( iKey + 1 ) * iLen - 1 ]; + if ( iKey < pPage->iKeys - 1 ) + { + SHORT iPos = ( iKey + 2 ) * iLen - 2, iDup = 0; + iSpc -= pPage->pKeyBuf[ iPos ]; + if ( iKey > 0 ) + { + SHORT iPrev = ( iKey - 1 ) * iLen, iNext = ( iKey + 1 ) * iLen, + iNum = pPage->TagParent->uiLen; + iNum -= /* pPage->pKeyBuf[ iNext + iNum + 5 ]; */ + HB_MAX( pPage->pKeyBuf[ iNext + iNum + 5 ], + pPage->pKeyBuf[ iPrev + iNum + 5 ] ); + while ( iDup < iNum && pPage->pKeyBuf[ iPrev + iDup ] == + pPage->pKeyBuf[ iNext + iDup ] ) + ++iDup; + } + iSpc += pPage->pKeyBuf[ iPos ] = iDup; + } + pPage->iFree += iSpc; + if ( --pPage->iKeys > iKey ) + { + memmove( &pPage->pKeyBuf[ iKey * iLen ], + &pPage->pKeyBuf[ ( iKey + 1 ) * iLen ], + ( pPage->iKeys - iKey ) * iLen ); + } + pPage->fBufChanged = pPage->fChanged = TRUE; +#ifndef HB_CDX_DBGCODE_OFF + hb_cdxPageCheckKeys( pPage ); + hb_cdxPageCheckDupTrl( pPage, pPage->pKeyBuf, pPage->iKeys ); +#endif + if ( iKey >= pPage->iKeys ) + iRet |= NODE_NEWLASTKEY; + if ( pPage->iKeys == 0 ) + iRet |= NODE_JOIN; + /* if ( pPage->iFree >= CDX_EXT_FREESPACE / 2 ) */ + if ( pPage->iFree >= pPage->ReqByte ) + iRet |= NODE_BALANCE; + return iRet; +} + +/* + * add key to page at current position + */ +static int hb_cdxPageLeafAddKey( LPCDXPAGE pPage, LPCDXKEY pKey ) +{ + SHORT iKey, iNum = pPage->TagParent->uiLen; + SHORT iLen = iNum + 6, iSpc, iTrl, iDup, iMax, iPos; + BYTE bTrail = ( pPage->TagParent->uiType == 'C' ) ? ' ' : '\0'; + int iRet = 0; + +#ifdef HB_CDX_DSPDBG_INFO + printf("\r\naddkey: Page=%lx, iKey=%d/%d, rec=%ld", + pPage->Page, pPage->iCurKey, pPage->iKeys, pKey->rec); + fflush(stdout); +#endif +#ifndef HB_CDX_DBGCODE_OFF + if ( ( pPage->PageType & CDX_NODE_LEAF ) == 0 ) + hb_cdxErrInternal( "hb_cdxPageLeafAddKey: page is not a leaf." ); + if ( pPage->iCurKey < 0 || pPage->iCurKey > pPage->iKeys ) + hb_cdxErrInternal( "hb_cdxPageLeafAddKey: wrong iKey index." ); +#endif + if ( !pPage->pKeyBuf ) + { + BYTE *pKeyBuf = (BYTE *) hb_xgrab( ( pPage->iKeys + 1 ) * iLen ); + hb_cdxPageLeafDecode( pPage, pKeyBuf ); + pPage->pKeyBuf = pKeyBuf; + } + else + { + pPage->pKeyBuf = hb_xrealloc( pPage->pKeyBuf, ( pPage->iKeys + 1 ) * iLen ); + } + +#ifndef HB_CDX_DBGCODE_OFF + hb_cdxPageCheckKeys( pPage ); + hb_cdxPageCheckDupTrl( pPage, pPage->pKeyBuf, pPage->iKeys ); +#endif +#if 0 + /* TODO: use this code if memmove forward doesn't work correctly */ + for ( iKey = pPage->iKeys, iPos = iKey * iLen; iKey > pPage->iCurKey; + iKey--, iPos -= iLen ) + { + memcpy( &pPage->pKeyBuf[ iPos ], &pPage->pKeyBuf[ iPos - iLen ], iLen ); + } +#else + iKey = pPage->iCurKey; + iPos = iKey * iLen; + if ( iKey < pPage->iKeys ) + { + memmove( &pPage->pKeyBuf[ iPos + iLen ], &pPage->pKeyBuf[ iPos ], + iLen * ( pPage->iKeys - iKey ) ); + } +#endif + if ( pKey->len >= iNum ) + memcpy( &pPage->pKeyBuf[ iPos ], pKey->val, iNum ); + else + { + memcpy( &pPage->pKeyBuf[ iPos ], pKey->val, pKey->len ); + memset( &pPage->pKeyBuf[ iPos + pKey->len ], bTrail, iNum - pKey->len ); + } + HB_PUT_LE_ULONG( &pPage->pKeyBuf[ iPos + iNum ], pKey->rec ); + iTrl = iDup = 0; + while ( iTrl < iNum && pPage->pKeyBuf[ iPos + iNum - iTrl - 1 ] == bTrail ) + ++iTrl; + if ( iKey > 0 ) + { + iMax = iNum - HB_MAX( iTrl, pPage->pKeyBuf[ iPos - 1 ] ); + while ( iDup < iMax && pPage->pKeyBuf[ iPos + iDup ] == + pPage->pKeyBuf[ iPos + iDup - iLen ] ) + ++iDup; + } + pPage->pKeyBuf[ iPos + iNum + 4 ] = (BYTE) iDup; + pPage->pKeyBuf[ iPos + iNum + 5 ] = (BYTE) iTrl; + iSpc = pPage->ReqByte + iNum - iTrl - iDup; + if ( iKey < pPage->iKeys ) + { + iMax = iNum - HB_MAX( iTrl, pPage->pKeyBuf[ iPos + iLen + iLen - 1 ] ); + iSpc += pPage->pKeyBuf[ iPos + iLen + iLen - 2 ]; + iDup = 0; + while ( iDup < iMax && pPage->pKeyBuf[ iPos + iDup ] == + pPage->pKeyBuf[ iPos + iDup + iLen ] ) + ++iDup; + iSpc -= pPage->pKeyBuf[ iPos + iLen + iLen - 2 ] = iDup; + } + pPage->iKeys++; + while ( pKey->rec > pPage->RNMask ) + { + pPage->RNMask = ( pPage->RNMask << 8 ) | 0xFF; + pPage->ReqByte++; + pPage->RNBits += 8; + iSpc += pPage->iKeys; + } + pPage->iFree -= iSpc; + pPage->fBufChanged = pPage->fChanged = TRUE; +#ifndef HB_CDX_DBGCODE_OFF + hb_cdxPageCheckKeys( pPage ); + hb_cdxPageCheckDupTrl( pPage, pPage->pKeyBuf, pPage->iKeys ); +#endif + if ( iKey >= pPage->iKeys - 1 ) + iRet |= NODE_NEWLASTKEY; + if ( pPage->iFree < 0 ) + iRet |= NODE_SPLIT; + /* if ( pPage->iFree >= CDX_EXT_FREESPACE / 2 ) */ + if ( pPage->iFree >= pPage->ReqByte ) + iRet |= NODE_BALANCE; + return iRet; +} + +/* + * set (insert) key in interior node record to (with) given value + */ +static void hb_cdxPageIntSetKey( LPCDXPAGE pPage, SHORT iKey, BOOL fIns, BYTE * pbVal, ULONG ulRec, ULONG ulPag ) +{ + SHORT iLen = pPage->TagParent->uiLen; + SHORT iPos = iKey * ( iLen + 8 ); + +#ifdef HB_CDX_DSPDBG_INFO + printf("\r\nintSetKey (%s): Page=%lx, iKey=%d/%d, ulPag=%lx", + fIns ? "ins" : "set", pPage->Page, iKey, pPage->iKeys, ulPag); + fflush(stdout); +#endif +#ifndef HB_CDX_DBGCODE_OFF + if ( ( pPage->PageType & CDX_NODE_LEAF ) != 0 ) + hb_cdxErrInternal( "hb_cdxPageIntSetKey: page is a leaf!" ); + if ( iKey < 0 || iKey >= pPage->iKeys + ( fIns ? 1 : 0 ) ) + { + hb_cdxErrInternal( "hb_cdxPageIntSetKey: wrong iKey index." ); + } +#endif + if ( fIns ) + { +#if 0 + /* TODO: use this code if memmove forward doesn't work correctly */ + SHORT i, l, n; + for ( i = pPage->iKeys, l = iLen + 8, n = i * l; i > iKey; i--, n -= l ) + { + memcpy( &pPage->node.intNode.keyPool[ n ], + &pPage->node.intNode.keyPool[ n - l ], l ); + } +#else + if ( iKey < pPage->iKeys ) + { + memmove( &pPage->node.intNode.keyPool[ iPos + iLen + 8 ], + &pPage->node.intNode.keyPool[ iPos ], + ( iLen + 8 ) * ( pPage->iKeys - iKey ) ); + } +#endif + pPage->iKeys++; + } + if ( pbVal ) + memcpy( &pPage->node.intNode.keyPool[ iPos ], pbVal, iLen ); + else + memset( &pPage->node.intNode.keyPool[ iPos ], + ( pPage->TagParent->uiType == 'C' ) ? ' ' : '\0', iLen ); + HB_PUT_BE_ULONG( &pPage->node.intNode.keyPool[ iPos + iLen ], ulRec ); + HB_PUT_BE_ULONG( &pPage->node.intNode.keyPool[ iPos + iLen + 4 ], ulPag ); + pPage->fChanged = TRUE; +} + +/* + * delete key in interior node record + */ +static void hb_cdxPageIntDelKey( LPCDXPAGE pPage, SHORT iKey ) +{ + SHORT iLen = pPage->TagParent->uiLen + 8; + +#ifdef HB_CDX_DSPDBG_INFO + printf("\r\nintDelKey: Page=%lx, iKey=%d/%d, ulPag=%lx", + pPage->Page, iKey, pPage->iKeys, + HB_GET_BE_ULONG( &pPage->node.intNode.keyPool[ (iKey+1) * iLen - 4 ] ) ); + fflush(stdout); +#endif +#ifndef HB_CDX_DBGCODE_OFF + if ( ( pPage->PageType & CDX_NODE_LEAF ) != 0 ) + hb_cdxErrInternal( "hb_cdxPageIntDelKey: page is a leaf!" ); + if ( iKey < 0 || iKey >= pPage->iKeys ) + { + hb_cdxErrInternal( "hb_cdxPageIntDelKey: wrong iKey index." ); + } +#endif + pPage->iKeys--; + if ( pPage->iKeys > iKey ) + { + memmove( &pPage->node.intNode.keyPool[ iKey * iLen ], + &pPage->node.intNode.keyPool[ ( iKey + 1 ) * iLen ], ( pPage->iKeys - iKey ) * iLen ); + } + memset( &pPage->node.intNode.keyPool[ pPage->iKeys * iLen ], 0, iLen ); + pPage->fChanged = TRUE; +} + +/* + * (re)load CDX page from index file + */ +static void hb_cdxPageLoad( LPCDXPAGE pPage ) +{ + if ( pPage->pKeyBuf ) + { + hb_xfree( pPage->pKeyBuf ); + pPage->pKeyBuf = NULL; + pPage->fBufChanged = FALSE; + } + hb_cdxIndexPageRead( pPage->TagParent->pIndex, pPage->Page, (BYTE *) &pPage->node, sizeof( CDXNODE ) ); + pPage->PageType = HB_GET_LE_USHORT( pPage->node.intNode.attr ); + pPage->Left = HB_GET_LE_ULONG( pPage->node.intNode.leftPtr ); + pPage->Right = HB_GET_LE_ULONG( pPage->node.intNode.rightPtr ); + pPage->iKeys = HB_GET_LE_USHORT( pPage->node.intNode.nKeys ); + pPage->fChanged = FALSE; + + if ( ( pPage->PageType & CDX_NODE_LEAF ) != 0 ) + { + pPage->iFree = HB_GET_LE_USHORT( pPage->node.extNode.freeSpc ); + pPage->RNMask = HB_GET_LE_ULONG( pPage->node.extNode.recMask ); + /* TODO: redundant, use it directly */ + pPage->DCMask = pPage->node.extNode.dupMask; + pPage->TCMask = pPage->node.extNode.trlMask; + pPage->RNBits = pPage->node.extNode.recBits; + pPage->DCBits = pPage->node.extNode.dupBits; + pPage->TCBits = pPage->node.extNode.trlBits; + pPage->ReqByte = pPage->node.extNode.keyBytes; + pPage->bufKeyNum = 0; +#if 0 + if ( !pPage->pKeyBuf ) + { + BYTE *pKeyBuf = (BYTE *) hb_xgrab( ( pPage->iKeys + 1 ) * ( pPage->TagParent->uiLen + 6 ) ); + hb_cdxPageLeafDecode( pPage, pKeyBuf ); + pPage->pKeyBuf = pKeyBuf; + } +#endif + } +#ifndef HB_CDX_DBGCODE_OFF + hb_cdxPageCheckKeys( pPage ); +#endif +} + +/* + * store page into index file + */ +static void hb_cdxPageStore( LPCDXPAGE pPage ) +{ +#ifndef HB_CDX_DBGCODE_OFF + if ( pPage->Page == 0 || pPage->Page == CDX_DUMMYNODE ) + hb_cdxErrInternal( "hb_cdxPageStore: Page number wrong!." ); +#endif +#ifndef HB_CDX_DBGCODE_OFF + if ( pPage->PageType & CDX_NODE_LEAF ) + { + if ( pPage->iFree < 0 ) + hb_cdxErrInternal( "hb_cdxPageStore: FreeSpace calculated wrong!." ); + } + else if ( pPage->iKeys > pPage->TagParent->MaxKeys ) + hb_cdxErrInternal( "hb_cdxPageStore: number of keys exceed!." ); +#endif + HB_PUT_LE_USHORT( pPage->node.intNode.attr, pPage->PageType ); + HB_PUT_LE_USHORT( pPage->node.intNode.nKeys, pPage->iKeys ); + HB_PUT_LE_ULONG( pPage->node.intNode.leftPtr, pPage->Left ); + HB_PUT_LE_ULONG( pPage->node.intNode.rightPtr, pPage->Right ); + + if ( ( pPage->PageType & CDX_NODE_LEAF ) != 0 ) + { + HB_PUT_LE_USHORT( pPage->node.extNode.freeSpc, pPage->iFree ); + HB_PUT_LE_ULONG( pPage->node.extNode.recMask, pPage->RNMask ); + /* TODO: redundant, use it directly */ + pPage->node.extNode.dupMask = pPage->DCMask; + pPage->node.extNode.trlMask = pPage->TCMask; + pPage->node.extNode.recBits = pPage->RNBits; + pPage->node.extNode.dupBits = pPage->DCBits; + pPage->node.extNode.trlBits = pPage->TCBits; + pPage->node.extNode.keyBytes = pPage->ReqByte; + + if ( pPage->pKeyBuf && pPage->fBufChanged ) + { + hb_cdxPageLeafEncode( pPage, pPage->pKeyBuf, pPage->iKeys ); + pPage->fBufChanged = FALSE; + } +#if 0 + if ( pPage->pKeyBuf ) + { + hb_xfree( pPage->pKeyBuf ); + pPage->pKeyBuf = NULL; + } +#endif + } + hb_cdxIndexPageWrite( pPage->TagParent->pIndex, pPage->Page, (BYTE *) &pPage->node, sizeof( CDXNODE ) ); +#ifndef HB_CDX_DBGCODE_OFF + hb_cdxPageCheckKeys( pPage ); +#endif + pPage->fChanged = FALSE; +} + +/* + * create new empty page and allocate space for it in index file if ulPage == 0 + * or load it from index file if ulPage != CDX_DUMMYNODE + */ +static LPCDXPAGE hb_cdxPageNew( LPCDXTAG pTag, LPCDXPAGE pOwnerPage, ULONG ulPage ) +{ + LPCDXPAGE pPage = NULL; + +#ifndef HB_CDX_DBGCODE_OFF + hb_cdxTagPoolCheck( pTag ); +#endif + if ( ulPage && ulPage != CDX_DUMMYNODE && pTag->pagePool ) { pPage = pTag->pagePool; - while ( pPage && pPage->Page != FilePosn ) + while ( pPage && pPage->Page != ulPage ) { pPage = pPage->pPoolNext; } @@ -2832,78 +2057,1047 @@ static LPCDXPAGEINFO hb_cdxPageNew( LPCDXTAG pTag, LPCDXPAGEINFO PIK, LONG FileP pPage->pPoolNext->pPoolPrev = pPage; pTag->pagePool = pPage; } - pPage->Owner = PIK; - pPage->TagParent = pTag; - pPage->CurKey = -1; -#ifndef HB_CDX_DBGCODE_OFF - hb_cdxPagePoolCheck( pTag ); -#endif } else { - pPage = ( LPCDXPAGEINFO ) hb_xgrab( sizeof( HB_CDXPAGEINFO ) ); - memset( pPage, 0, sizeof( HB_CDXPAGEINFO ) ); - pPage->Page = FilePosn; - pPage->Left = pPage->Right = -1; - pPage->Owner = PIK; + pPage = ( LPCDXPAGE ) hb_xgrab( sizeof( CDXPAGE ) ); + memset( pPage, 0, sizeof( CDXPAGE ) ); + pPage->PageType = CDX_NODE_UNUSED; + pPage->Left = pPage->Right = CDX_DUMMYNODE; pPage->TagParent = pTag; - pPage->CurKey = -1; - if( FilePosn > 0 ) + + if ( ulPage && ulPage != CDX_DUMMYNODE ) { - hb_cdxPagePageLoad( pPage ); + pPage->Page = ulPage; + hb_cdxPageLoad( pPage ); + } + else if ( ! ulPage ) + { + pPage->Page = hb_cdxIndexGetAvailPage( pTag->pIndex, FALSE ); + pPage->fChanged = TRUE; } pPage->pPoolPrev = NULL; pPage->pPoolNext = pTag->pagePool; pTag->pagePool = pPage; if ( pPage->pPoolNext ) pPage->pPoolNext->pPoolPrev = pPage; -#ifndef HB_CDX_DBGCODE_OFF - hb_cdxPagePoolCheck( pTag ); -#endif } + pPage->Owner = pOwnerPage; + pPage->iCurKey = -1; pPage->bUsed = 1; +#ifndef HB_CDX_DBGCODE_OFF + hb_cdxTagPoolCheck( pTag ); +#endif return pPage; } -#ifndef HB_CDX_DBGCODE_OFF -static void hb_cdxPagePoolCheck( LPCDXTAG pTag ) +/* + * free single page + */ +static void hb_cdxPageFree( LPCDXPAGE pPage, BOOL fReal ) { - LPCDXPAGEINFO pPage, pPrevPage; - - pPage = pTag->pagePool; - pPrevPage = NULL; - while ( pPage ) +#ifndef HB_CDX_DBGCODE_OFF + LPCDXTAG pTag = pPage->TagParent; + hb_cdxTagPoolCheck( pTag ); +#endif + if ( pPage->Child != NULL ) { - if ( pPage->pPoolPrev != pPrevPage ) - hb_cdxErrInternal( "hb_cdxPagePoolCheck: data integrity error." ); - pPrevPage = pPage; - pPage = pPage->pPoolNext; + hb_cdxPageFree( pPage->Child, fReal ); + pPage->Child = NULL; } + + if ( pPage->PageType == CDX_NODE_UNUSED ) + { + fReal = TRUE; + pPage->fChanged = FALSE; + } + + if ( fReal ) + { + if ( pPage->fChanged ) + hb_cdxPageStore( pPage ); + +#ifndef HB_CDX_DBGCODE_OFF + hb_cdxTagPoolCheck( pTag ); +#endif + if ( pPage->pPoolPrev ) + { + pPage->pPoolPrev->pPoolNext = pPage->pPoolNext; + if ( pPage->pPoolNext ) + { + pPage->pPoolNext->pPoolPrev = pPage->pPoolPrev; + } + } + else + { + pPage->TagParent->pagePool = pPage->pPoolNext; + if ( pPage->pPoolNext ) + { + pPage->pPoolNext->pPoolPrev = NULL; + } + } +#ifndef HB_CDX_DBGCODE_OFF + hb_cdxTagPoolCheck( pTag ); +#endif + } + + if ( pPage->Owner != NULL && pPage->Owner->Child == pPage ) + pPage->Owner->Child = NULL; + pPage->Owner = NULL; + pPage->bUsed = 0; + + if ( fReal ) + { + if ( pPage->PageType == CDX_NODE_UNUSED ) + hb_cdxIndexPutAvailPage( pPage->TagParent->pIndex, pPage->Page, FALSE ); + if ( pPage->pKeyBuf ) + hb_xfree( pPage->pKeyBuf ); + hb_xfree( pPage ); + } +#ifndef HB_CDX_DBGCODE_OFF + hb_cdxTagPoolCheck( pTag ); +#endif } + +/* + * read child page + */ +static void hb_cdxPageGetChild( LPCDXPAGE pPage ) +{ + ULONG ulPage; + +#ifndef HB_CDX_DBGCODE_OFF + if ( ( pPage->PageType & CDX_NODE_LEAF ) != 0 ) + hb_cdxErrInternal( "hb_cdxPageGetChild: index corrupted." ); #endif -static void hb_cdxPagePoolFree( LPCDXINDEX pIndex, int nPagesLeft ) + ulPage = hb_cdxPageGetKeyPage( pPage, pPage->iCurKey ); + if ( pPage->Child != NULL ) + { + if ( pPage->Child->Page != ulPage ) + { + hb_cdxPageFree( pPage->Child, FALSE ); + pPage->Child = NULL; + } + } + if ( pPage->Child == NULL ) + pPage->Child = hb_cdxPageNew( pPage->TagParent, pPage, ulPage ); +} + +static int hb_cdxPageKeyLeafBalance( LPCDXPAGE pPage, SHORT iChildRet ) +{ + LPCDXPAGE childs[ CDX_BALANCE_LEAFPAGES + 2 ], lpTmpPage; + SHORT iFirstKey, iBlncKeys = CDX_BALANCE_LEAFPAGES; + SHORT iLen = pPage->TagParent->uiLen + 6, + iKeys = 0, iFree = 0, iSkip = 0, iMaxReq = 0; + BYTE * pKeyPool = NULL, * pPtr; + BOOL fIns; + ULONG ulPage; + int iRet = 0, i; + +#ifndef HB_CDX_DBGCODE_OFF + hb_cdxPageCheckKeys( pPage ); +#endif + + if ( pPage->iCurKey > 0 ) + iFirstKey = pPage->iCurKey - 1; + else + iFirstKey = 0; + if ( iBlncKeys > pPage->iKeys - iFirstKey ) + { + iBlncKeys = pPage->iKeys - iFirstKey; + iRet |= NODE_BALANCE; + } + +#ifdef HB_CDX_DSPDBG_INFO + printf("\r\nleaf balance: Page=%lx (%d/%d)", pPage->Page, iFirstKey, iBlncKeys); + fflush(stdout); +#endif + + if ( ( iChildRet & ( NODE_SPLIT | NODE_JOIN ) ) == 0 && + ( iBlncKeys < 2 || ( iChildRet & NODE_BALANCE ) == 0 ) ) + return iRet; + + for ( i = 0; i < iBlncKeys; i++ ) + { + ulPage = hb_cdxPageGetKeyPage( pPage, iFirstKey + i ); + if ( pPage->Child && pPage->Child->Page == ulPage ) + { + childs[i] = pPage->Child; + pPage->Child = NULL; + } + else + { + childs[i] = hb_cdxPageNew( pPage->TagParent, pPage, ulPage ); + } +#ifndef HB_CDX_DBGCODE_OFF + if ( i > 0 && ( childs[i]->Page != childs[i-1]->Right || + childs[i]->Left != childs[i-1]->Page ) ) + { + printf("\r\nchilds[%d]->Page=%lx, childs[%d]->Right=%lx, childs[%d]->Page=%lx, childs[%d]->Left=%lx", + i-1, childs[i-1]->Page, i-1, childs[i-1]->Right, + i, childs[i]->Page, i, childs[i]->Left); + fflush(stdout); + hb_cdxErrInternal( "hb_cdxPageKeyLeafBalance: index corrupted." ); + } +#endif + if ( childs[i]->iFree >= childs[i]->ReqByte ) /* TODO: increase limit for last page */ + iFree += childs[i]->iFree; + else if ( childs[i]->iFree >= 0 ) + { + if ( i == iSkip ) + ++iSkip; + else if ( i + 1 == iBlncKeys ) + { + iBlncKeys--; + hb_cdxPageFree( childs[i], FALSE ); + } + } + if ( i >= iSkip && i < iBlncKeys ) + iKeys += childs[i]->iKeys; + +#ifdef HB_CDX_DSPDBG_INFO + printf(", childs[%d]->Page=%lx(%d/%d)", i, childs[i]->Page, childs[i]->iKeys, childs[i]->iFree); + printf("(%d/%d/%d:%d,%lx)", i, iSkip, iBlncKeys, iKeys,childs[i]->Right); + fflush(stdout); +#endif + } + + if ( ( iChildRet & ( NODE_SPLIT | NODE_JOIN ) ) == 0 && + ( iBlncKeys < 2 || iFree < CDX_EXT_FREESPACE ) ) + { + for ( i = 0; i < iBlncKeys; i++ ) + hb_cdxPageFree( childs[i], FALSE ); + return iRet; + } + +#ifdef HB_CDX_DSPDBG_INFO + printf("\r\nleaf balance: Page=%lx iKeys=%d", pPage->Page, iKeys); + fflush(stdout); +#endif + if ( iKeys > 0 ) + { + pPtr = pKeyPool = (BYTE *) hb_xgrab( iKeys * iLen ); + for ( i = iSkip; i < iBlncKeys && iKeys > 0; i++ ) + { + if ( childs[i]->iKeys > 0 ) + { + if ( childs[i]->pKeyBuf ) + memcpy( pPtr, childs[i]->pKeyBuf, childs[i]->iKeys * iLen ); + else + hb_cdxPageLeafDecode( childs[i], pPtr ); + /* update number of duplicate characters when join pages */ + if ( pPtr > pKeyPool ) + { + BYTE bDup = 0, bMax = iLen - 6 - HB_MAX( pPtr[ iLen - 1 ], pPtr[ -1 ] ); + while ( bDup < bMax && pPtr[ bDup ] == pPtr[ bDup - iLen ] ) + ++bDup; + pPtr[ iLen - 2 ] = bDup; + if ( iSkip == i - 1 && childs[iSkip]->iFree >= 0 && + iLen - 6 - bDup - pPtr[ iLen - 1 ] > + childs[iSkip]->iFree - childs[iSkip]->ReqByte ) + { + memmove( pKeyPool, pPtr, childs[i]->iKeys * iLen ); + pPtr = pKeyPool; + iKeys -= childs[i-1]->iKeys; + iSkip++; +#ifdef HB_CDX_DSPDBG_INFO + printf("\r\niSkip=%d, iBlncKeys=%d", iSkip, iBlncKeys); + fflush(stdout); +#endif + } + } + pPtr += childs[i]->iKeys * iLen; + if ( childs[i]->ReqByte > iMaxReq ) + iMaxReq = childs[i]->ReqByte; +#ifdef HB_CDX_DSPDBG_INFO + printf(", childs[%d]->iKeys=%d", i, childs[i]->iKeys); + fflush(stdout); +#endif + } + } + } + +#ifndef HB_CDX_DBGCODE_OFF + hb_cdxPageCheckDupTrl( pPage, pKeyPool, iKeys ); +#endif + pPtr = pKeyPool; + fIns = FALSE; + i = iSkip; + while ( iKeys > 0 ) + { + if ( i == iBlncKeys ) + { + if ( childs[i-1]->Right != CDX_DUMMYNODE ) + lpTmpPage = hb_cdxPageNew( pPage->TagParent, pPage, childs[i-1]->Right ); + else + lpTmpPage = NULL; + + if ( !fIns && lpTmpPage != NULL ) + { + if ( lpTmpPage->ReqByte > iMaxReq ) + iMaxReq = lpTmpPage->ReqByte; + if ( lpTmpPage->iFree < iKeys * ( iLen - 6 + iMaxReq ) + + ( iMaxReq - lpTmpPage->ReqByte ) * lpTmpPage->iKeys ) + fIns = TRUE; + else + { + BYTE * pTmp = (BYTE *) hb_xgrab( ( iKeys + lpTmpPage->iKeys ) * iLen ); + /* TODO: iBufSize to avoid new allocation if old buffer is large enough */ +#ifdef HB_CDX_DSPDBG_INFO + printf("\r\ninserting #keys=%d/%d (%d) parent=%lx, child=%lx, rec=%ld", + iKeys, lpTmpPage->iKeys, i, pPage->Page, lpTmpPage->Page, HB_GET_LE_ULONG( pPtr + iLen - 6 )); + fflush(stdout); +#endif + memcpy( pTmp, pPtr, iKeys * iLen ); + hb_xfree( pKeyPool ); + pPtr = pKeyPool = pTmp; + pTmp = &pTmp[ iKeys * iLen ]; + if ( lpTmpPage->iKeys > 0 ) + { + BYTE bDup = 0, bMax; + if ( lpTmpPage->pKeyBuf ) + memcpy( pTmp, lpTmpPage->pKeyBuf, lpTmpPage->iKeys * iLen ); + else + hb_cdxPageLeafDecode( lpTmpPage, pTmp ); + bMax = iLen - 6 - HB_MAX( pTmp[ iLen - 1 ], pTmp[ -1 ] ); + while ( bDup < bMax && pTmp[ bDup ] == pTmp[ bDup - iLen ] ) + ++bDup; + pTmp[ iLen - 2 ] = bDup; + iKeys += lpTmpPage->iKeys; + } + childs[i] = lpTmpPage; + if ( iFirstKey + i >= pPage->iKeys ) + iRet |= NODE_NEWLASTKEY; + } + } + else + fIns = TRUE; + + if ( fIns ) + { + childs[ i ] = hb_cdxPageNew( pPage->TagParent, pPage, 0 ); + childs[ i ]->PageType = CDX_NODE_LEAF; + /* Update siblings links */ + childs[ i ]->Left = childs[i-1]->Page; + childs[ i ]->Right = childs[i-1]->Right; + childs[i-1]->Right = childs[ i ]->Page; + childs[i-1]->fChanged = TRUE; + if ( lpTmpPage != NULL ) + { + lpTmpPage->Left = childs[i]->Page; + lpTmpPage->fChanged = TRUE; + hb_cdxPageFree( lpTmpPage, FALSE ); + } + iBlncKeys++; + iRet |= NODE_BALANCE; +#ifdef HB_CDX_DSPDBG_INFO + printf("\r\nleaf balance: new child[%d]->Page=%lx",i,childs[i]->Page); + fflush(stdout); +#endif + } + } + childs[i]->iKeys = 0; + if ( childs[i]->pKeyBuf ) + { + hb_xfree( childs[i]->pKeyBuf ); + childs[i]->pKeyBuf = NULL; + childs[i]->fBufChanged = FALSE; + } + hb_cdxPageCalcLeafSpace( childs[i], pPtr, iKeys ); + hb_cdxPageLeafEncode( childs[i], pPtr, childs[i]->iKeys ); + pPtr += childs[i]->iKeys * iLen; + iKeys -= childs[i]->iKeys; + /* update parent key */ + if ( i < iBlncKeys ) + { + hb_cdxPageIntSetKey( pPage, iFirstKey + i,fIns, + pPtr - iLen, HB_GET_LE_ULONG( pPtr - 6 ), + childs[i]->Page ); + } +#ifdef HB_CDX_DSPDBG_INFO + printf(" (%d/%d)", childs[i]->iKeys,childs[i]->iFree); + fflush(stdout); +#endif +#ifndef HB_CDX_DBGCODE_OFF + hb_cdxPageCheckKeys( childs[i] ); +#endif + hb_cdxPageFree( childs[i], FALSE ); + i++; + } + if ( i < iBlncKeys ) + { + ULONG Left, Right; + + /* Update siblings links */ + Right = childs[iBlncKeys-1]->Right; + if ( i > 0 ) + { + Left = childs[i-1]->Page; + childs[i-1]->Right = Right; + childs[i-1]->fChanged = TRUE; + } + else + { + Left = childs[0]->Left; + if ( Left != CDX_DUMMYNODE ) + { + lpTmpPage = hb_cdxPageNew( pPage->TagParent, pPage, Left ); + lpTmpPage->Right = Right; + lpTmpPage->fChanged = TRUE; + hb_cdxPageFree( lpTmpPage, FALSE ); + } + } + if ( Right != CDX_DUMMYNODE ) + { + lpTmpPage = hb_cdxPageNew( pPage->TagParent, pPage, Right ); + lpTmpPage->Left = Left; + lpTmpPage->fChanged = TRUE; + hb_cdxPageFree( lpTmpPage, FALSE ); + } + + /* Unlink empty pages from parent */ + while ( i < iBlncKeys ) + { + /* Delete parent key */ + iBlncKeys--; +#ifdef HB_CDX_DSPDBG_INFO + printf("\r\nleaf balance: free child[%d]->Page=%lx", iBlncKeys, childs[iBlncKeys]->Page); + fflush(stdout); +#endif + if ( childs[iBlncKeys]->pKeyBuf ) + { + hb_xfree( childs[iBlncKeys ]->pKeyBuf ); + childs[iBlncKeys]->pKeyBuf = NULL; + childs[iBlncKeys]->fBufChanged = FALSE; + } + hb_cdxPageIntDelKey( pPage, iFirstKey + iBlncKeys ); + childs[iBlncKeys]->Owner = NULL; + childs[iBlncKeys]->fChanged = FALSE; + childs[iBlncKeys]->PageType = CDX_NODE_UNUSED; + childs[iBlncKeys]->Left = CDX_DUMMYNODE; + childs[iBlncKeys]->Right = CDX_DUMMYNODE; + hb_cdxPageFree( childs[iBlncKeys], FALSE ); + } + iRet |= NODE_BALANCE; + } + for ( i = 0; i < iSkip; i++ ) + hb_cdxPageFree( childs[i], FALSE ); + + if ( pKeyPool ) + hb_xfree( pKeyPool ); + pPage->fChanged = TRUE; +#ifndef HB_CDX_DBGCODE_OFF + hb_cdxPageCheckKeys( pPage ); +#endif + if ( pPage->iKeys > pPage->TagParent->MaxKeys ) + iRet |= NODE_SPLIT; + return iRet; +} + +static int hb_cdxPageKeyIntBalance( LPCDXPAGE pPage, SHORT iChildRet ) +{ + LPCDXPAGE childs[ CDX_BALANCE_INTPAGES + 2 ], lpTmpPage; + SHORT iFirstKey, iBlncKeys = CDX_BALANCE_INTPAGES; + SHORT iLen = pPage->TagParent->uiLen + 8, iKeys = 0, iNeedKeys, iNodeKeys, + iMin = pPage->TagParent->MaxKeys, iMax = 0; + ULONG ulPage; + BYTE * pKeyPool = NULL, *pPtr; + int iRet = 0, i; + + if ( pPage->Child && pPage->Child->Child ) + hb_cdxPageFree( pPage->Child->Child, FALSE ); + +#ifndef HB_CDX_DBGCODE_OFF + hb_cdxPageCheckKeys( pPage ); +#endif + + if ( pPage->iKeys <= iBlncKeys || pPage->iCurKey <= iBlncKeys / 2 ) + iFirstKey = 0; + else if ( pPage->iCurKey + iBlncKeys / 2 >= pPage->iKeys ) + iFirstKey = pPage->iKeys - iBlncKeys; + else + iFirstKey = pPage->iCurKey - iBlncKeys / 2; + if ( iBlncKeys > pPage->iKeys - iFirstKey ) + { + iBlncKeys = pPage->iKeys - iFirstKey; + iRet |= NODE_BALANCE; + } + +#ifdef HB_CDX_DSPDBG_INFO + printf("\r\nbalance: Page=%lx (%d/%d)", pPage->Page, iFirstKey, iBlncKeys); + fflush(stdout); +#endif + + if ( ( iChildRet & ( NODE_SPLIT | NODE_JOIN ) ) == 0 && + ( iBlncKeys < 2 || ( iChildRet & NODE_BALANCE ) == 0 ) ) + return iRet; + + for ( i = 0; i < iBlncKeys; i++ ) + { + ulPage = hb_cdxPageGetKeyPage( pPage, iFirstKey + i ); + if ( pPage->Child && pPage->Child->Page == ulPage ) + { + childs[i] = pPage->Child; + pPage->Child = NULL; + } + else + { + childs[i] = hb_cdxPageNew( pPage->TagParent, pPage, ulPage ); + } +#ifndef HB_CDX_DBGCODE_OFF + if ( i > 0 && ( childs[i]->Page != childs[i-1]->Right || + childs[i]->Left != childs[i-1]->Page ) ) + { + printf("\r\nchilds[%d]->Page=%lx, childs[%d]->Right=%lx, childs[%d]->Page=%lx, childs[%d]->Left=%lx", + i-1, childs[i-1]->Page, i-1, childs[i-1]->Right, + i, childs[i]->Page, i, childs[i]->Left); + fflush(stdout); + hb_cdxErrInternal( "hb_cdxPageKeyIntBalance: index corrupted." ); + } +#endif + iKeys += childs[i]->iKeys; + + if ( childs[i]->iKeys > iMax ) + iMax = childs[i]->iKeys; + if ( childs[i]->iKeys < iMin ) + iMin = childs[i]->iKeys; +#ifdef HB_CDX_DSPDBG_INFO + printf(", childs[%d]->Page=%lx(%d)", i, childs[i]->Page, childs[i]->iKeys); + fflush(stdout); +#endif + } + + if ( ( iChildRet & ( NODE_SPLIT | NODE_JOIN ) ) == 0 && + ( iBlncKeys < 2 || iMax - iMin < 2 ) ) + { + for ( i = 0; i < iBlncKeys; i++ ) + hb_cdxPageFree( childs[i], FALSE ); + return iRet; + } + + if ( iKeys > 0 ) + { + pPtr = pKeyPool = hb_xgrab( iKeys * iLen ); + for ( i = 0; i < iBlncKeys; i++ ) + { + if ( childs[i]->iKeys > 0 ) + { + memcpy( pPtr, childs[i]->node.intNode.keyPool, childs[i]->iKeys * iLen ); + pPtr += childs[i]->iKeys * iLen; + } + } + } + + iNeedKeys = ( iKeys + pPage->TagParent->MaxKeys - 1 ) + / pPage->TagParent->MaxKeys; + + if ( iNeedKeys > iBlncKeys ) + { + childs[iBlncKeys] = hb_cdxPageNew( pPage->TagParent, pPage, 0 ); + childs[iBlncKeys]->PageType = CDX_NODE_BRANCH; + childs[iBlncKeys]->iKeys = 0; + childs[iBlncKeys]->fChanged = TRUE; + /* Add new parent key */ + hb_cdxPageIntSetKey( pPage, iFirstKey + iBlncKeys, TRUE, + NULL, 0, childs[iBlncKeys]->Page ); + /* Update siblings links */ + childs[iBlncKeys ]->Left = childs[iBlncKeys-1]->Page; + childs[iBlncKeys ]->Right = childs[iBlncKeys-1]->Right; + childs[iBlncKeys-1]->Right = childs[iBlncKeys ]->Page; + if ( childs[iBlncKeys]->Right != CDX_DUMMYNODE ) + { + lpTmpPage = hb_cdxPageNew( pPage->TagParent, pPage, childs[iBlncKeys]->Right ); + lpTmpPage->Left = childs[iBlncKeys]->Page; + lpTmpPage->fChanged = TRUE; + hb_cdxPageFree( lpTmpPage, FALSE ); + } +#ifdef HB_CDX_DSPDBG_INFO + printf("\r\nint balance: new child[%d]->Page=%lx",iBlncKeys,childs[iBlncKeys]->Page); + fflush(stdout); +#endif + iBlncKeys++; + iRet |= NODE_BALANCE; + } + else if ( iNeedKeys < iBlncKeys ) + { + ULONG Left, Right; + + /* Update siblings links */ + Right = childs[iBlncKeys-1]->Right; + if ( iNeedKeys > 0 ) + { + Left = childs[iNeedKeys-1]->Page; + childs[iNeedKeys-1]->Right = Right; + } + else + { + Left = childs[0]->Left; + if ( Left != CDX_DUMMYNODE ) + { + lpTmpPage = hb_cdxPageNew( pPage->TagParent, pPage, Left ); + lpTmpPage->Right = Right; + lpTmpPage->fChanged = TRUE; + hb_cdxPageFree( lpTmpPage, FALSE ); + } + } + if ( Right != CDX_DUMMYNODE ) + { + lpTmpPage = hb_cdxPageNew( pPage->TagParent, pPage, Right ); + lpTmpPage->Left = Left; + lpTmpPage->fChanged = TRUE; + hb_cdxPageFree( lpTmpPage, FALSE ); + } + /* Unlink empty pages from parent */ + for ( i = iBlncKeys - 1; i >= iNeedKeys; i-- ) + { + /* Delete parent key */ +#ifdef HB_CDX_DSPDBG_INFO + printf("\r\nbalance: free child[%d]->Page=%lx",i,childs[i]->Page); + fflush(stdout); +#endif + hb_cdxPageIntDelKey( pPage, iFirstKey + i ); + childs[i]->Owner = NULL; + childs[i]->fChanged = FALSE; + childs[i]->PageType = CDX_NODE_UNUSED; + childs[i]->Left = CDX_DUMMYNODE; + childs[i]->Right = CDX_DUMMYNODE; + childs[i]->iKeys = 0; + hb_cdxPageFree( childs[i], FALSE ); + } + iBlncKeys = iNeedKeys; + iRet |= NODE_BALANCE; + } + + /* + * Redistribute childs internal node's keys and update parent keys + */ + if ( iKeys > 0 ) + { + pPtr = pKeyPool; + for ( i = 0; i < iBlncKeys; i++ ) + { + iNodeKeys = ( iKeys + iBlncKeys - i - 1 ) / ( iBlncKeys - i ); +#ifndef HB_CDX_DBGCODE_OFF + if ( iNodeKeys > pPage->TagParent->MaxKeys ) + hb_cdxErrInternal( "hb_cdxPageKeyIntBalance: iNodeKeys calculated wrong!." ); +#endif + /* TODO: do nothing if iNodeKeys == childs[i]->iKeys && i == iSkip */ + memcpy( childs[i]->node.intNode.keyPool, pPtr, iNodeKeys * iLen ); + childs[i]->iKeys = iNodeKeys; + childs[i]->fChanged = TRUE; + pPtr += iNodeKeys * iLen; + iKeys -= iNodeKeys; + /* update parent key */ + hb_cdxPageIntSetKey( pPage, iFirstKey + i, FALSE, + pPtr - iLen, HB_GET_BE_ULONG( pPtr - 8 ), + childs[i]->Page ); +#ifdef HB_CDX_DSPDBG_INFO + printf(" (%d)", childs[i]->iKeys); +#endif +#ifndef HB_CDX_DBGCODE_OFF + hb_cdxPageCheckKeys( childs[i] ); +#endif + hb_cdxPageFree( childs[i], FALSE ); + } + hb_xfree( pKeyPool ); + } + pPage->fChanged = TRUE; +#ifndef HB_CDX_DBGCODE_OFF + hb_cdxPageCheckKeys( pPage ); +#endif + if ( pPage->iKeys > pPage->TagParent->MaxKeys ) + iRet |= NODE_SPLIT; + return iRet; +} + +/* + * balance keys in child pages + */ +static int hb_cdxPageBalance( LPCDXPAGE pPage, int iChildRet ) +{ + int iRet = 0; + + if ( ( pPage->PageType & CDX_NODE_LEAF ) != 0 ) + iRet = iChildRet; + else + { + if ( iChildRet & NODE_NEWLASTKEY ) + { + if ( pPage->Child->iKeys == 0 ) + { + iChildRet |= NODE_JOIN; + iRet |= NODE_NEWLASTKEY; + } + else + { + hb_cdxPageIntSetKey( pPage, pPage->iCurKey, FALSE, + hb_cdxPageGetKeyVal( pPage->Child, pPage->Child->iKeys-1 ), + hb_cdxPageGetKeyRec( pPage->Child, pPage->Child->iKeys-1 ), + pPage->Child->Page ); +#ifndef HB_CDX_DBGCODE_OFF + hb_cdxPageCheckKeys( pPage ); +#endif + pPage->fChanged = TRUE; + if ( pPage->iCurKey >= pPage->iKeys - 1 ) + iRet |= NODE_NEWLASTKEY; + } + } + if ( ( pPage->Child->PageType & CDX_NODE_LEAF ) != 0 ) + iRet |= hb_cdxPageKeyLeafBalance( pPage, iChildRet ); + else + iRet |= hb_cdxPageKeyIntBalance( pPage, iChildRet ); + } + if ( !pPage->Owner ) + { + if ( pPage->iKeys == 0 ) + pPage->PageType |= CDX_NODE_LEAF; + else if ( iRet & NODE_SPLIT ) + iRet = hb_cdxPageRootSplit( pPage ); + } + return iRet; +} + +/* + * split Root Page + */ +static int hb_cdxPageRootSplit( LPCDXPAGE pPage ) +{ + LPCDXPAGE pNewRoot; + ULONG ulPage; + + pNewRoot = hb_cdxPageNew( pPage->TagParent, NULL, 0 ); + /* + * do not change root page address if it's unnecessary + * so we don't have to update Tag header + */ + pPage->TagParent->RootPage = pNewRoot; + ulPage = pNewRoot->Page; + pNewRoot->Page = pPage->Page; + pPage->Page = ulPage; + pPage->Owner = pNewRoot; + pPage->PageType &= ~CDX_NODE_ROOT; + pNewRoot->PageType = CDX_NODE_ROOT | CDX_NODE_BRANCH; + pNewRoot->fChanged = TRUE; + pNewRoot->Child = pPage; + pNewRoot->iCurKey = 0; + hb_cdxPageIntSetKey( pNewRoot, 0, TRUE, + hb_cdxPageGetKeyVal( pPage, pPage->iKeys-1 ), + hb_cdxPageGetKeyRec( pPage, pPage->iKeys-1 ), + pPage->Page ); +#ifndef HB_CDX_DBGCODE_OFF + hb_cdxPageCheckKeys( pNewRoot ); + hb_cdxTagPoolCheck( pPage->TagParent ); +#endif + hb_cdxPageBalance( pNewRoot, NODE_SPLIT ); + return 0; +} + +/* + * remove current Key from Tag + */ +static int hb_cdxPageKeyDelete( LPCDXPAGE pPage ) +{ + int iChildRet; + + if ( pPage->PageType & CDX_NODE_LEAF ) + iChildRet = hb_cdxPageLeafDelKey( pPage ); + else /* interior node */ + iChildRet = hb_cdxPageKeyDelete( pPage->Child ); + return hb_cdxPageBalance( pPage, iChildRet ); +} + +/* + * add Key to Tag at current position + */ +static int hb_cdxPageKeyInsert( LPCDXPAGE pPage, LPCDXKEY pKey ) +{ + int iChildRet; + + if ( pPage->PageType & CDX_NODE_LEAF ) + iChildRet = hb_cdxPageLeafAddKey( pPage, pKey ); + else /* interior node */ + iChildRet = hb_cdxPageKeyInsert( pPage->Child, pKey ); + return hb_cdxPageBalance( pPage, iChildRet ); +} + +/* + * Store Tag header to index files + */ +static void hb_cdxTagHeaderStore( LPCDXTAG pTag ) +{ + USHORT uiKeyLen, uiForLen; + CDXTAGHEADER tagHeader; + + if ( !pTag->TagChanged ) + return; + + /* + * TODO: !!! read the following field from the index file, + * at least freePtr has to be read for pTag->TagBlock == 0 + * tagHeader.freePtr [ 4 ] offset of list of free pages or -1 + * tagHeader.reserved1[ 4 ] Version number ??? + * tagHeader.reserved2[ 486 ] + */ + + pTag->TagChanged = FALSE; + if ( pTag->UniqueKey ) + pTag->OptFlags |= CDX_TYPE_UNIQUE; + if ( pTag->Temporary ) + pTag->OptFlags |= CDX_TYPE_TEMPORARY; + if ( pTag->Custom ) + pTag->OptFlags |= CDX_TYPE_CUSTOM; + if ( pTag->pForItem != NULL ) + pTag->OptFlags |= CDX_TYPE_FORFILTER; + + memset( &tagHeader, 0, sizeof( CDXTAGHEADER ) ); + HB_PUT_LE_ULONG( tagHeader.rootPtr, pTag->RootBlock ); + HB_PUT_LE_USHORT( tagHeader.keySize, pTag->uiLen ); + tagHeader.indexOpt = pTag->OptFlags; + tagHeader.indexSig = 1; + if ( !pTag->AscendKey ) + HB_PUT_LE_USHORT( tagHeader.ascendFlg, 1 ); + + uiKeyLen = pTag->KeyExpr == NULL ? 0 : strlen( pTag->KeyExpr ); + uiForLen = pTag->ForExpr == NULL ? 0 : strlen( pTag->ForExpr ); + + HB_PUT_LE_USHORT( tagHeader.keyExpPos, 0 ); + HB_PUT_LE_USHORT( tagHeader.keyExpLen, uiKeyLen + 1 ); + HB_PUT_LE_USHORT( tagHeader.forExpPos, uiKeyLen + 1 ); + HB_PUT_LE_USHORT( tagHeader.forExpLen, uiForLen + 1 ); + if ( uiKeyLen > 0 ) + { + strcpy( ( char * ) tagHeader.keyExpPool, pTag->KeyExpr ); + } + if ( uiForLen > 0 ) + { + strcpy( ( char * ) tagHeader.keyExpPool + uiKeyLen + 1, pTag->ForExpr ); + } + hb_cdxIndexPageWrite( pTag->pIndex, pTag->TagBlock, (BYTE *) &tagHeader, sizeof( CDXTAGHEADER ) ); +} + +/* + * Read a tag definition from the index file + */ +static void hb_cdxTagLoad( LPCDXTAG pTag ) +{ + CDXTAGHEADER pHeader; + HB_MACRO_PTR pMacro; + ULONG ulRecNo; + + /* read the page from a file */ + hb_cdxIndexPageRead( pTag->pIndex, pTag->TagBlock, (BYTE *) &pHeader, sizeof( CDXTAGHEADER ) ); + pTag->RootBlock = HB_GET_LE_ULONG( pHeader.rootPtr ); + /* Return if: + * no root page allocated + * invalid root page offset (position inside an index file) + * invalid key value length + */ + if ( pTag->RootBlock == 0 || pTag->RootBlock % CDX_PAGELEN != 0 || + pTag->RootBlock >= hb_fsSeek( pTag->pIndex->hFile, 0, FS_END ) || + HB_GET_LE_USHORT( pHeader.keySize ) > CDX_MAXKEY ) + { + /* TODO: pTag->RootBlock = 0; || {internal,RT}Error ? */ + return; + } + pTag->uiLen = HB_GET_LE_USHORT( pHeader.keySize ); + pTag->MaxKeys = CDX_INT_FREESPACE / ( pTag->uiLen + 8 ); + pTag->OptFlags = pHeader.indexOpt; + pTag->UniqueKey = ( pTag->OptFlags & CDX_TYPE_UNIQUE ); + pTag->Temporary = ( pTag->OptFlags & CDX_TYPE_TEMPORARY ); + pTag->Custom = ( pTag->OptFlags & CDX_TYPE_CUSTOM ); + pTag->AscendKey = pTag->UsrAscend = ( HB_GET_LE_USHORT( pHeader.ascendFlg ) == 0 ); + pTag->UsrUnique = FALSE; + pTag->KeyExpr = ( char * ) hb_xgrab( CDX_MAXKEY + 1 ); + /* QUESTION: Is UPPER a valid operation here? + * This will break expressions like: + * somefield+'smallcaps'+otherfield + * TODO: + */ + hb_strncpyUpper( pTag->KeyExpr, ( char * ) pHeader.keyExpPool, CDX_MAXKEY ); + + if ( ( pTag->OptFlags & CDX_TYPE_STRUCTURE ) || pTag->KeyExpr[ 0 ] == 0 ) + return; + + SELF_COMPILE( ( AREAP ) pTag->pIndex->pArea, ( BYTE * ) pTag->KeyExpr ); + pTag->pKeyItem = pTag->pIndex->pArea->valResult; + pTag->pIndex->pArea->valResult = NULL; + /* Get a blank record before testing expression */ + ulRecNo = pTag->pIndex->pArea->ulRecNo; + SELF_GOTO( ( AREAP ) pTag->pIndex->pArea, 0 ); + hb_macroRun( ( HB_MACRO_PTR ) hb_itemGetPtr( pTag->pKeyItem ) ); + switch( hb_itemType( hb_stackItemFromTop( -1 ) ) ) + { + case HB_IT_INTEGER: + case HB_IT_LONG: +#ifndef HB_LONG_LONG_OFF + case HB_IT_LONGLONG: +#endif + case HB_IT_DOUBLE: + pTag->uiType = 'N'; + pTag->uiLen = 8; + break; + + case HB_IT_DATE: + pTag->uiType = 'D'; + pTag->uiLen = 8; + break; + + case HB_IT_LOGICAL: + pTag->uiType = 'L'; + pTag->uiLen = 1; + break; + + case HB_IT_STRING: + pTag->uiType = 'C'; + /* TODO: is this safe? */ + pTag->uiLen = HB_CDXMAXKEY( ( hb_stackItemFromTop( -1 ) )->item.asString.length ); + break; + } + hb_stackPop(); /* pop macro evaluated value */ + + pTag->nField = hb_rddFieldIndex( ( AREAP ) pTag->pIndex->pArea, pTag->KeyExpr ); + + /* Check if there is a FOR expression CDX_TYPE_FORFILTER */ + if ( pHeader.keyExpPool[ strlen( pTag->KeyExpr ) + 1 ] != 0 ) + { + pTag->ForExpr = ( char * ) hb_xgrab( CDX_MAXKEY + 1 ); + /* TODO: Uppering is bad */ + hb_strncpyUpper( pTag->ForExpr, ( const char * ) pHeader.keyExpPool + + strlen( pTag->KeyExpr ) + 1, CDX_MAXKEY ); + SELF_COMPILE( ( AREAP ) pTag->pIndex->pArea, ( BYTE * ) pTag->ForExpr ); + pTag->pForItem = pTag->pIndex->pArea->valResult; + pTag->pIndex->pArea->valResult = NULL; + pMacro = ( HB_MACRO_PTR ) hb_itemGetPtr( pTag->pForItem ); + hb_macroRun( pMacro ); + if ( hb_itemType( hb_stackItemFromTop( -1 ) ) != HB_IT_LOGICAL ) + { + hb_macroDelete( pMacro ); + hb_itemRelease( pTag->pForItem ); + pTag->pForItem = NULL; + hb_xfree( pTag->ForExpr ); + pTag->ForExpr = NULL; + } + hb_stackPop(); + } + SELF_GOTO( ( AREAP ) pTag->pIndex->pArea, ulRecNo ); +} + +/* + * Creates a new structure with a tag information + * TagHdr = offset of index page where a tag header is stored + * if CDX_DUMMYNODE then allocate space ofor a new tag header + */ +static LPCDXTAG hb_cdxTagNew( LPCDXINDEX pIndex, char *szTagName, ULONG TagHdr ) { LPCDXTAG pTag; - if ( pIndex->pCompound ) + pTag = ( LPCDXTAG ) hb_xgrab( sizeof( CDXTAG ) ); + memset( pTag, 0, sizeof( CDXTAG ) ); + pTag->szName = ( char * ) hb_xgrab( CDX_MAXTAGNAMELEN + 1 ); + hb_strncpyUpperTrim( pTag->szName, szTagName, CDX_MAXTAGNAMELEN ); + pTag->pIndex = pIndex; + pTag->AscendKey = pTag->UsrAscend = TRUE; + pTag->UsrUnique = FALSE; + pTag->uiType = 'C'; + pTag->CurKey = hb_cdxKeyNew(); + if ( TagHdr == CDX_DUMMYNODE ) { - hb_cdxPagePoolFreeTag( pIndex->pCompound, nPagesLeft ); + pTag->TagBlock = hb_cdxIndexGetAvailPage( pIndex, TRUE ); + pTag->TagChanged = TRUE; + pTag->OptFlags = CDX_TYPE_COMPACT | CDX_TYPE_COMPOUND; } - pTag = pIndex->TagList; - while ( pTag ) + else { - hb_cdxPagePoolFreeTag( pTag, nPagesLeft ); - pTag = pTag->pNext; + pTag->TagBlock = TagHdr; + hb_cdxTagLoad( pTag ); + } + return pTag; +} + +/* + * release structure with a tag information from memory + */ +static void hb_cdxTagFree( LPCDXTAG pTag ) +{ + if ( pTag->RootPage != NULL ) + { + hb_cdxPageFree( pTag->RootPage, FALSE ); + pTag->RootPage = NULL; + } + hb_cdxTagPoolFlush( pTag ); + hb_cdxTagPoolFree( pTag, 0 ); + if ( pTag->TagChanged ) + hb_cdxTagHeaderStore( pTag ); + if ( pTag->szName != NULL ) + hb_xfree( pTag->szName ); + if ( pTag->KeyExpr != NULL ) + hb_xfree( pTag->KeyExpr ); + if ( pTag->pKeyItem != NULL ) + { + if ( hb_itemType( pTag->pKeyItem ) != HB_IT_BLOCK ) + hb_macroDelete( ( HB_MACRO_PTR ) hb_itemGetPtr( pTag->pKeyItem ) ); + hb_itemRelease( pTag->pKeyItem ); + } + if ( pTag->ForExpr != NULL ) + hb_xfree( pTag->ForExpr ); + if ( pTag->pForItem != NULL ) + { + if ( hb_itemType( pTag->pForItem ) != HB_IT_BLOCK ) + hb_macroDelete( ( HB_MACRO_PTR ) hb_itemGetPtr( pTag->pForItem ) ); + hb_itemRelease( pTag->pForItem ); + } + hb_cdxKeyFree( pTag->CurKey ); + if ( pTag->HotKey ) + hb_cdxKeyFree( pTag->HotKey ); + hb_cdxTagClearScope( pTag, 0); + hb_cdxTagClearScope( pTag, 1); + hb_xfree( pTag ); +} + +/* + * close Tag (free used pages into page pool) + */ +static void hb_cdxTagClose( LPCDXTAG pTag ) +{ + if ( pTag->RootPage != NULL ) + { + hb_cdxPageFree( pTag->RootPage, FALSE ); + pTag->RootPage = NULL; + } + if ( pTag->TagChanged ) + { + hb_cdxTagHeaderStore( pTag ); } } -static void hb_cdxPagePoolFreeTag( LPCDXTAG pTag, int nPagesLeft ) +/* + * (re)open Tag + */ +static void hb_cdxTagOpen( LPCDXTAG pTag ) { - LPCDXPAGEINFO pPage, pPageNext; + CDXTAGHEADER tagHeader; + + if ( !pTag->RootPage ) + { + hb_cdxIndexPageRead( pTag->pIndex, pTag->TagBlock, (BYTE *) &tagHeader, sizeof( CDXTAGHEADER ) ); + pTag->RootBlock = HB_GET_LE_ULONG( tagHeader.rootPtr ); + if ( pTag->RootBlock && pTag->RootBlock != CDX_DUMMYNODE ) + pTag->RootPage = hb_cdxPageNew( pTag, NULL, pTag->RootBlock ); + /* if ( !pTag->RootPage ) + hb_cdxErrInternal("corruption"); */ + } +} + +/* + * free Tag pages from cache + */ +static void hb_cdxTagPoolFree( LPCDXTAG pTag, int nPagesLeft ) +{ + LPCDXPAGE pPage, pPageNext; #ifndef HB_CDX_DBGCODE_OFF - hb_cdxPagePoolCheck( pTag ); + hb_cdxTagPoolCheck( pTag ); #endif pPage = pTag->pagePool; while ( nPagesLeft && pPage ) @@ -2913,1878 +3107,644 @@ static void hb_cdxPagePoolFreeTag( LPCDXTAG pTag, int nPagesLeft ) } while ( pPage ) { - // pTag->pagePool = pPage->pPoolNext; pPageNext = pPage->pPoolNext; if ( ! pPage->bUsed ) { - hb_cdxPageRealFree( pPage ); + hb_cdxPageFree( pPage, TRUE ); } pPage = pPageNext; } #ifndef HB_CDX_DBGCODE_OFF - hb_cdxPagePoolCheck( pTag ); + hb_cdxTagPoolCheck( pTag ); #endif - pTag->ulVersion = pTag->pIndex->ulVersion; } - -static void hb_cdxPagePoolFlush( LPCDXINDEX pIndex ) +/* + * write all changed pages in tag cache + */ +static void hb_cdxTagPoolFlush( LPCDXTAG pTag ) { - LPCDXTAG pTag; + LPCDXPAGE pPage; - if ( pIndex->pCompound ) - { - hb_cdxPagePoolFlushTag( pIndex->pCompound ); - } - pTag = pIndex->TagList; - while ( pTag ) - { - hb_cdxPagePoolFlushTag( pTag ); - pTag = pTag->pNext; - } -} - -static void hb_cdxPagePoolFlushTag( LPCDXTAG pTag ) -{ - LPCDXPAGEINFO pPage; - -#ifndef HB_CDX_DBGCODE_OFF - hb_cdxPagePoolCheck( pTag ); -#endif pPage = pTag->pagePool; while ( pPage ) { - if( pPage->Changed ) - hb_cdxPagePageStore( pPage ); + if ( pPage->fChanged ) + { + hb_cdxPageStore( pPage ); + } pPage = pPage->pPoolNext; } #ifndef HB_CDX_DBGCODE_OFF - hb_cdxPagePoolCheck( pTag ); + hb_cdxTagPoolCheck( pTag ); #endif } -static void hb_cdxPageRealFree( LPCDXPAGEINFO pPage ) +/* + * retrive CurKey from current Tag possition + */ +static void hb_cdxSetCurKey( LPCDXPAGE pPage ) { -#ifndef HB_CDX_DBGCODE_OFF - LPCDXTAG pTag = pPage->TagParent; - hb_cdxPagePoolCheck( pTag ); -#endif - if( pPage->Child != NULL ) - { - hb_cdxPageRealFree( pPage->Child ); - pPage->Child = NULL; - } + while ( pPage->Child ) + pPage = pPage->Child; - if( pPage->Changed ) - hb_cdxPagePageStore( pPage ); - -#ifndef HB_CDX_DBGCODE_OFF - hb_cdxPagePoolCheck( pTag ); -#endif - if ( pPage->pPoolPrev ) - { - pPage->pPoolPrev->pPoolNext = pPage->pPoolNext; - if ( pPage->pPoolNext ) - pPage->pPoolNext->pPoolPrev = pPage->pPoolPrev; -#ifndef HB_CDX_DBGCODE_OFF - hb_cdxPagePoolCheck( pTag ); -#endif - } - else - { - pPage->TagParent->pagePool = pPage->pPoolNext; - if ( pPage->pPoolNext ) - pPage->pPoolNext->pPoolPrev = NULL; -#ifndef HB_CDX_DBGCODE_OFF - hb_cdxPagePoolCheck( pTag ); -#endif - } -#ifndef HB_CDX_DBGCODE_OFF - hb_cdxPagePoolCheck( pTag ); -#endif - - if ( pPage->NewRoot && pPage->Owner != NULL ) - { - pPage->Owner->Child = NULL; - hb_cdxPageRealFree( pPage->Owner ); - pPage->Owner = NULL; - } - pPage->NewRoot = FALSE; - - if( pPage->Owner != NULL ) - pPage->Owner->Child = NULL; - pPage->Owner = NULL; - - /* Free all keys */ - hb_cdxKeyListFree( pPage->pKeys ); - pPage->pKeys = NULL; - - if ( pPage->Left == -1 && pPage->Right == -1 && (pPage->PageType & 0xf0) == 0xf0 ) - { - hb_cdxIndexPutAvailPage( pPage ); - } - - hb_xfree( pPage ); -#ifndef HB_CDX_DBGCODE_OFF - hb_cdxPagePoolCheck( pTag ); -#endif + hb_cdxKeyPut( pPage->TagParent->CurKey, + hb_cdxPageGetKeyVal( pPage, pPage->iCurKey ), + pPage->TagParent->uiLen, + hb_cdxPageGetKeyRec( pPage, pPage->iCurKey ) ); } - -static void hb_cdxPageFree( LPCDXPAGEINFO pPage ) +/* + * seek given Key in the Page or in its children + */ +static int hb_cdxPageSeekKey( LPCDXPAGE pPage, LPCDXKEY pKey, BOOL fExact ) { -#ifndef HB_CDX_DBGCODE_OFF - LPCDXTAG pTag = pPage->TagParent; - hb_cdxPagePoolCheck( pTag ); -#endif - if( pPage->Child != NULL ) + int l, r, n = -1, k = 1; + BOOL fLeaf = ( pPage->PageType & CDX_NODE_LEAF ) != 0; + ULONG ulKeyRec = pKey->rec; + + if ( pPage->TagParent->UsrUnique ) { - 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; - pPage->bUsed = 0; - - /* Free all keys */ - // hb_cdxKeyListFree( pPage->pKeys ); - // pPage->pKeys = NULL; - - // hb_xfree( pPage ); -} - -static BOOL hb_cdxPageReadTopKey( LPCDXPAGEINFO pPage ) -{ - LPCDXKEYINFO pKey; - - if( pPage->uiKeys == 0 ) - return FALSE; - pPage->CurKey = 0; - pKey = pPage->pKeys; - if( pPage->PageType < PAGE_LEAF ) - { - if( hb_cdxPageGetChild( pPage, pKey->Tag ) ) - return hb_cdxPageReadTopKey( pPage->Child ); - else - return FALSE; - } - else - { - pPage->TagParent->CurKeyInfo = - hb_cdxKeyCopy( pPage->TagParent->CurKeyInfo, pKey ); - return TRUE; - } -} - -static BOOL hb_cdxPageReadBottomKey( LPCDXPAGEINFO pPage ) -{ - LPCDXKEYINFO pKey; - - if( pPage->uiKeys == 0 ) - return FALSE; - pPage->CurKey = pPage->uiKeys - 1; - pKey = hb_cdxPageGetKey( pPage, pPage->CurKey ); - if( pPage->PageType < PAGE_LEAF ) - { - /* - printf( "hb_cdxPageReadBottomKey()" ); - return TRUE; - */ - if( hb_cdxPageGetChild( pPage, pKey->Tag ) ) - return hb_cdxPageReadBottomKey( pPage->Child ); - else - return FALSE; - } - else - { - pPage->TagParent->CurKeyInfo = - hb_cdxKeyCopy( pPage->TagParent->CurKeyInfo, pKey ); - return TRUE; - } -} - -static int hb_cdxPageSeekKey( LPCDXPAGEINFO pPage, LONG lBlock, LPCDXKEYINFO pKey, BOOL bExact ) -{ - int k; - LPCDXKEYINFO p; - - k = 1; - bExact = ( bExact || pPage->TagParent->uiType != 'C' ); - pPage->CurKey = 0; - if( pPage->uiKeys > 0 ) - { - while( k > 0 && pPage->CurKey < pPage->uiKeys ) + if ( pPage->TagParent->UsrAscend ) { - p = hb_cdxPageGetKey( pPage, pPage->CurKey ); - k = hb_cdxKeyCompare( pKey, p, bExact ); - /* - * TODO: review this - if( !pPage->TagParent->AscendKey ) - k = -k; - */ - if( k == 0 && lBlock == CDX_MAX_REC_NUM ) + if ( ulKeyRec == CDX_MAX_REC_NUM ) + ulKeyRec = CDX_IGNORE_REC_NUM; + } + else if ( ulKeyRec == CDX_IGNORE_REC_NUM ) + ulKeyRec = CDX_MAX_REC_NUM; + } + + if ( fLeaf && !pPage->pKeyBuf && pPage->iKeys > 0 ) + { + SHORT iLen = pPage->TagParent->uiLen + 6; + BYTE *pKeyBuf = (BYTE *) hb_xgrab( pPage->iKeys * iLen ); + hb_cdxPageLeafDecode( pPage, pKeyBuf ); + pPage->pKeyBuf = pKeyBuf; + } + + l = 0; + r = pPage->iKeys - 1; + while ( l < r ) + { + n = (l + r ) >> 1; + k = hb_cdxValCompare( pPage->TagParent, pKey->val, pKey->len, + hb_cdxPageGetKeyVal( pPage, n ), + pPage->TagParent->uiLen, fExact ); + if ( k == 0 ) + { + if ( ulKeyRec == CDX_MAX_REC_NUM ) k = 1; - if( k == 0 && lBlock != CDX_IGNORE_REC_NUM ) + else if ( ulKeyRec != CDX_IGNORE_REC_NUM ) { - if( lBlock > p->Xtra ) + ULONG ulRec = hb_cdxPageGetKeyRec( pPage, n ); + if ( ulKeyRec > ulRec ) k = 1; - else if( lBlock < p->Xtra ) + else if ( ulKeyRec < ulRec ) 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++; + } + if ( k > 0 ) + l = n + 1; + else + r = n; + } + pPage->iCurKey = l; + if ( r < 0 ) + return k; + + if ( !fLeaf ) + { + hb_cdxPageGetChild( pPage ); +#ifndef HB_CDX_DBGCODE_OFF + if ( memcmp( hb_cdxPageGetKeyVal( pPage, pPage->iCurKey ), + hb_cdxPageGetKeyVal( pPage->Child, pPage->Child->iKeys-1 ), + pPage->TagParent->uiLen ) != 0 || + hb_cdxPageGetKeyRec( pPage, pPage->iCurKey ) != + hb_cdxPageGetKeyRec( pPage->Child, pPage->Child->iKeys-1 ) ) + { + printf("\r\nparent=%lx, iKey=%d, rec=%ld", pPage->Page, pPage->iCurKey, hb_cdxPageGetKeyRec( pPage, pPage->iCurKey )); + printf("\r\n child=%lx, iKey=%d, rec=%ld", pPage->Child->Page, pPage->Child->iKeys-1, hb_cdxPageGetKeyRec( pPage->Child, pPage->Child->iKeys-1 )); + fflush(stdout); + hb_cdxErrInternal("hb_cdxPageSeekKey: wrong parent key."); + } +#endif + k = hb_cdxPageSeekKey( pPage->Child, pKey, fExact ); + } + else if ( l != n || ulKeyRec == CDX_MAX_REC_NUM ) + { + k = hb_cdxValCompare( pPage->TagParent, pKey->val, pKey->len, + hb_cdxPageGetKeyVal( pPage, pPage->iCurKey ), + pPage->TagParent->uiLen, fExact ); + if ( k == 0 && ulKeyRec != CDX_MAX_REC_NUM && + ulKeyRec != CDX_IGNORE_REC_NUM ) + { + ULONG ulRec = hb_cdxPageGetKeyRec( pPage, pPage->iCurKey ); + if ( ulKeyRec > ulRec ) + k = 1; + else if ( ulKeyRec < ulRec ) + k = -1; } } + if ( ulKeyRec == CDX_MAX_REC_NUM ) + { + if ( pPage->iCurKey > 0 && k < 0 ) + { + pPage->iCurKey--; + if ( !fLeaf ) + { + hb_cdxPageGetChild( pPage ); + k = hb_cdxPageSeekKey( pPage->Child, pKey, fExact ); + } + else + k = hb_cdxValCompare( pPage->TagParent, pKey->val, pKey->len, + hb_cdxPageGetKeyVal( pPage, pPage->iCurKey ), + pPage->TagParent->uiLen, fExact ); + } + } + else if ( k > 0 && fLeaf ) + pPage->iCurKey++; return k; } -static BYTE hb_cdxPageKeyLeafInsert( LPCDXPAGEINFO pPage, LPCDXKEYINFO pKey, BOOL bAddAfter ) +/* + * read Top Key from Page or its children + */ +static BOOL hb_cdxPageReadTopKey( LPCDXPAGE pPage ) { - LPCDXKEYINFO pNewKey, pTmpKey; - BYTE bRet = 0; - - pNewKey = hb_cdxKeyCopy( NULL, pKey ); - if( bAddAfter ) - pPage->CurKey++; - if( pPage->CurKey > pPage->uiKeys ) - pPage->CurKey = pPage->uiKeys; - if( pPage->CurKey < 0 ) - pPage->CurKey = 0; - - // if( pPage->Owner && ( pPage->CurKey >= pPage->uiKeys - 1 ) ) - if( pPage->Owner && ( pPage->CurKey >= pPage->uiKeys ) ) - bRet |= 1; - - if( pPage->pKeys == NULL ) + while ( ( pPage->PageType & CDX_NODE_LEAF ) == 0 && pPage->iKeys > 0 ) { - pPage->pKeys = pNewKey; - pPage->uiKeys = 1; - hb_cdxPageCalcLeafSpace( pPage ); - // pPage->FreeSpace -= pPage->ReqByte + pNewKey->length; + pPage->iCurKey = 0; + hb_cdxPageGetChild( pPage ); + pPage = pPage->Child; } - else - { - if( pPage->CurKey == 0 ) - { - pNewKey->pNext = pPage->pKeys; - pPage->pKeys = pNewKey; - pPage->uiKeys++; - // TODO : optimize this calc - hb_cdxPageCalcLeafSpace( pPage ); - } - else - { - pTmpKey = hb_cdxPageGetKey( pPage, pPage->CurKey - 1); - pNewKey->pNext = pTmpKey->pNext; - pTmpKey->pNext = pNewKey; - pPage->uiKeys++; - // TODO : optimize this calc - hb_cdxPageCalcLeafSpace( pPage ); - } - } - pPage->Changed = TRUE; - pPage->keyAdded = TRUE; - if ( pPage->FreeSpace < 0 ) - { - bRet |= 2; - } - return bRet; -} - -static BYTE hb_cdxPageKeyInsert( LPCDXPAGEINFO pPage, LPCDXKEYINFO pKey, BOOL bAddAfter ) -{ - LONG TempTag; - LPCDXKEYINFO p; - BYTE bRet, bChildRet; - - if ( pPage->PageType == PAGE_LEAF ) - { - bChildRet = hb_cdxPageKeyLeafInsert( pPage, pKey, bAddAfter ); -#ifndef HB_CDX_DBGCODE_OFF - hb_cdxPageLeafCheckKeys( pPage ); -#endif - - if ( ( pPage->Owner ) || !( bChildRet & 2 ) ) - { - bRet = bChildRet; - // return bChildRet; - } - else - { - bRet = hb_cdxPageRootSplit( pPage ); - // return bChildRet; - } - } - else - { - /* Internal node */ - bChildRet = hb_cdxPageKeyInsert( pPage->Child, pKey, bAddAfter); - - bRet = 0; - if ( !bChildRet ) - { - return bRet; - } - else if ( bChildRet & 1 ) - { - p = hb_cdxPageGetKey( pPage, pPage->CurKey ); - TempTag = pKey->Tag; - pKey->Tag = pPage->Child->Page; - // p = - hb_cdxKeyCopy( p, pKey ); - pKey->Tag = TempTag; - pPage->Changed = TRUE; - pPage->keyAdded = TRUE; - if ( pPage->Owner && ( pPage->CurKey >= pPage->uiKeys - 1 ) ) - bRet |= 1; - } - - if ( bChildRet & 2 ) - { - /* - * Child needs more space - */ - if ( pPage->Child->PageType == PAGE_LEAF ) - { - // bChildRet = - hb_cdxPageKeyLeafBalance( pPage ); - /* If a new child is needed and this page is full: - * - If it's root, copy to a child page linked to an empty root and redistribute it - * - if not ask the parent to redistribute this page - */ - if ( pPage->uiKeys >= pPage->TagParent->MaxKeys ) - { - if ( pPage->Owner ) - { - bRet |= 2; - return bRet; /* request space for this page */ - } - else - { - bChildRet = hb_cdxPageRootSplit( pPage ); - return bChildRet; - } - } - } - else - { - /* Internal child node needs more space: - * 1) Try redistribute to siblings nodes - * 2) If not: - * - redistribute childs adding a new child node - * - if this page is full: - * if it is Root: split "internal root" - * else: request space to caller - * */ - // bChildRet = - hb_cdxPageKeyIntBalance( pPage ); - - if ( pPage->uiKeys >= pPage->TagParent->MaxKeys ) - { - if ( pPage->Owner ) - { - bRet |= 2; - return bRet; /* request space for this page */ - } - else - { - bChildRet = hb_cdxPageRootSplit( pPage ); - return bChildRet; - } - } - } - } - } - return bRet; -} - - -static void hb_cdxPageInsertKey( LPCDXPAGEINFO pPage, LPCDXKEYINFO pKey, BOOL bAddAfter ) -{ - USHORT uiCount; - LPCDXKEYINFO pNewKey, pLastKey; - LONG TempTag; - - if( pPage->Child != NULL ) - hb_cdxPageInsertKey( pPage->Child, pKey, bAddAfter ); - else - { - pNewKey = hb_cdxKeyNew(); - pNewKey = hb_cdxKeyCopy( pNewKey, pKey ); - - if( bAddAfter ) - pPage->CurKey++; - if( pPage->CurKey > pPage->uiKeys ) - pPage->CurKey = pPage->uiKeys; - if( pPage->CurKey < 0 ) - pPage->CurKey = 0; - - if( pPage->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; - if( pPage->Owner != NULL && pPage->CurKey >= pPage->uiKeys ) - { - /*printf( "hb_cdxPageInsertKey()" );*/ - TempTag = pNewKey->Tag; - pNewKey->Tag = pPage->Page; - hb_cdxPageReplaceNodeKey( pPage->Owner, pNewKey ); - pNewKey->Tag = TempTag; - } - } -} - -static void hb_cdxPagePageStore( LPCDXPAGEINFO pPage ) -{ - if( pPage->Page == 0 ) - pPage->Page = hb_cdxIndexGetAvailPage( pPage->TagParent->pIndex ); - hb_cdxTagPageStore( pPage->TagParent, pPage ); - pPage->Changed = FALSE; - pPage->keyAdded = FALSE; -} - -static BOOL hb_cdxPageReadNextKey( LPCDXPAGEINFO pPage ) -{ - BOOL b; - LPCDXKEYINFO p; - - if( pPage->uiKeys == 0 ) + if ( pPage->iKeys == 0 ) return FALSE; - if( pPage->PageType < PAGE_LEAF ) - { - b = FALSE; - while( ! b && pPage->CurKey < pPage->uiKeys ) - { - p = hb_cdxPageGetKey( pPage, pPage->CurKey ); - if( hb_cdxPageGetChild( pPage, p->Tag ) ) - { - if( pPage->Child->CurKey == -1 ) - { - if( pPage->Child->PageType < PAGE_LEAF ) - pPage->Child->CurKey = 0; - } - b = hb_cdxPageReadNextKey( pPage->Child ); - } - else - b = FALSE; - if( !b ) - pPage->CurKey++; - } - if( !b ) - pPage->CurKey = pPage->uiKeys; - return b; - } - else - { - pPage->CurKey++; - if( pPage->CurKey < pPage->uiKeys ) - { - p = hb_cdxPageGetKey( pPage, pPage->CurKey ); - pPage->TagParent->CurKeyInfo = - hb_cdxKeyCopy( pPage->TagParent->CurKeyInfo, p ); - return TRUE; - } - else - { - pPage->CurKey = pPage->uiKeys; - return FALSE; - } - } + pPage->iCurKey = 0; + + hb_cdxSetCurKey( pPage ); + return TRUE; } -static BOOL hb_cdxPageReadPrevKey( LPCDXPAGEINFO pPage ) +/* + * read Bottom Key from Page or its children + */ +static BOOL hb_cdxPageReadBottomKey( LPCDXPAGE pPage ) { - BOOL b; - LPCDXKEYINFO p; - - if( pPage->uiKeys == 0 ) + while ( ( pPage->PageType & CDX_NODE_LEAF ) == 0 && pPage->iKeys > 0 ) + { + pPage->iCurKey = pPage->iKeys - 1; + hb_cdxPageGetChild( pPage ); + pPage = pPage->Child; + } + if ( pPage->iKeys == 0 ) return FALSE; - if( pPage->PageType < PAGE_LEAF ) + pPage->iCurKey = pPage->iKeys - 1; + + hb_cdxSetCurKey( pPage ); + return TRUE; +} + +/* + * read Previous Key from Page or its children + */ +static BOOL hb_cdxPageReadPrevKey( LPCDXPAGE pPage ) +{ + LPCDXPAGE pOwnerPage = NULL; + + while ( pPage->Child ) { - b = FALSE; - while( ! b && pPage->CurKey >= 0 ) - { - p = hb_cdxPageGetKey( pPage, pPage->CurKey ); - if( hb_cdxPageGetChild( pPage, p->Tag ) ) - { - if( pPage->Child->CurKey == -1 ) - { - if( pPage->Child->PageType < PAGE_LEAF ) - pPage->Child->CurKey = pPage->Child->uiKeys - 1; - else - pPage->Child->CurKey = pPage->Child->uiKeys; - } - b = hb_cdxPageReadPrevKey( pPage->Child ); - } - else - b = FALSE; - if( !b ) - pPage->CurKey--; - } - if( !b ) - pPage->CurKey = -1; - return b; + pOwnerPage = pPage; + pPage = pPage->Child; } - else + pPage->iCurKey--; + while ( pPage->iCurKey < 0 ) { - pPage->CurKey--; - if( pPage->CurKey >= 0 ) + if ( pPage->Left == CDX_DUMMYNODE || !pOwnerPage ) + return FALSE; + pOwnerPage->Child = hb_cdxPageNew( pPage->TagParent, pPage->Owner, pPage->Left ); + hb_cdxPageFree( pPage, FALSE ); + pPage = pOwnerPage->Child; + pPage->iCurKey = pPage->iKeys - 1; + } + + hb_cdxSetCurKey( pPage ); + return TRUE; +} + +/* + * read Next Key from Page or its children + */ +static BOOL hb_cdxPageReadNextKey( LPCDXPAGE pPage ) +{ + LPCDXPAGE pOwnerPage = NULL; + + while ( pPage->Child ) + { + pOwnerPage = pPage; + pPage = pPage->Child; + } + pPage->iCurKey++; + while ( pPage->iCurKey >= pPage->iKeys ) + { + if ( pPage->Right == CDX_DUMMYNODE || !pOwnerPage ) + return FALSE; + pOwnerPage->Child = hb_cdxPageNew( pPage->TagParent, pPage->Owner, pPage->Right ); + hb_cdxPageFree( pPage, FALSE ); + pPage = pOwnerPage->Child; + pPage->iCurKey = 0; + } + + hb_cdxSetCurKey( pPage ); + return TRUE; +} + +/* + * read Previous Unique Key from Page or its children + */ +static BOOL hb_cdxPageReadPrevUniqKey( LPCDXPAGE pPage ) +{ + LPCDXPAGE pOwnerPage = NULL; +// BYTE pbVal[CDX_MAXKEY]; + + while ( pPage->Child ) + { + pOwnerPage = pPage; + pPage = pPage->Child; + } +// memcpy( pbVal, hb_cdxPageGetKeyVal( pPage, pPage->iCurKey ), pPage->TagParent->uiLen ); +// pPage->iCurKey--; +// while ( pPage->iCurKey < 0 || memcmp( pbVal, hb_cdxPageGetKeyVal( pPage, pPage->iCurKey ), pPage->TagParent->uiLen ) == 0 ) + while ( pPage->iCurKey < 0 || memcmp( pPage->TagParent->CurKey->val, hb_cdxPageGetKeyVal( pPage, pPage->iCurKey ), pPage->TagParent->uiLen ) == 0 ) + { + if ( pPage->iCurKey > 0 ) + pPage->iCurKey--; + else { - p = hb_cdxPageGetKey( pPage, pPage->CurKey ); - pPage->TagParent->CurKeyInfo = - hb_cdxKeyCopy( pPage->TagParent->CurKeyInfo, p ); - return TRUE; + if ( pPage->Left == CDX_DUMMYNODE || !pOwnerPage ) + { + if ( pPage->iKeys > 0 ) + hb_cdxSetCurKey( pPage ); + return FALSE; + } + pOwnerPage->Child = hb_cdxPageNew( pPage->TagParent, pPage->Owner, pPage->Left ); + hb_cdxPageFree( pPage, FALSE ); + pPage = pOwnerPage->Child; + pPage->iCurKey = pPage->iKeys - 1; + } + } + + hb_cdxSetCurKey( pPage ); + return TRUE; +} + +/* + * read Next Unique Key from Page or its children + */ +static BOOL hb_cdxPageReadNextUniqKey( LPCDXPAGE pPage ) +{ + LPCDXPAGE pOwnerPage = NULL; +// BYTE pbVal[CDX_MAXKEY]; + + while ( pPage->Child ) + { + pOwnerPage = pPage; + pPage = pPage->Child; + } +// memcpy( pbVal, hb_cdxPageGetKeyVal( pPage, pPage->iCurKey ), pPage->TagParent->uiLen ); +// pPage->iCurKey++; +// while ( pPage->iCurKey >= pPage->iKeys || memcmp( pbVal, hb_cdxPageGetKeyVal( pPage, pPage->iCurKey ), pPage->TagParent->uiLen ) == 0 ) + while ( pPage->iCurKey >= pPage->iKeys || memcmp( pPage->TagParent->CurKey->val, hb_cdxPageGetKeyVal( pPage, pPage->iCurKey ), pPage->TagParent->uiLen ) == 0 ) + { + if ( pPage->iCurKey < pPage->iKeys - 1 ) + pPage->iCurKey++; + else + { + if ( pPage->Right == CDX_DUMMYNODE || !pOwnerPage ) + { + if ( pPage->iKeys > 0 ) + hb_cdxSetCurKey( pPage ); + return FALSE; + } + pOwnerPage->Child = hb_cdxPageNew( pPage->TagParent, pPage->Owner, pPage->Right ); + hb_cdxPageFree( pPage, FALSE ); + pPage = pOwnerPage->Child; + pPage->iCurKey = 0; + } + } + hb_cdxSetCurKey( pPage ); + return TRUE; +} + +/* + * read the TOP/BOTTOM/NEXT/PREVIOUS Key from Tag + */ +static void hb_cdxTagKeyRead( LPCDXTAG pTag, BYTE bTypRead ) +{ + BOOL fAfter = FALSE; + + pTag->CurKey->rec = 0; + pTag->fRePos = FALSE; + hb_cdxTagOpen( pTag ); + + if ( pTag->UsrUnique ) + { + switch( bTypRead ) + { + case NEXT_RECORD: + bTypRead = NXTU_RECORD; + break; + + case PREV_RECORD: + bTypRead = PRVU_RECORD; + case BTTM_RECORD: + fAfter = TRUE; + break; + } + } + if ( !pTag->UsrAscend ) + { + switch( bTypRead ) + { + case TOP_RECORD: + bTypRead = BTTM_RECORD; + break; + + case BTTM_RECORD: + bTypRead = TOP_RECORD; + break; + + case PREV_RECORD: + bTypRead = NEXT_RECORD; + break; + + case NEXT_RECORD: + bTypRead = PREV_RECORD; + break; + + case PRVU_RECORD: + bTypRead = NXTU_RECORD; + break; + + case NXTU_RECORD: + bTypRead = PRVU_RECORD; + break; + } + } + pTag->TagBOF = pTag->TagEOF = FALSE; + switch( bTypRead ) + { + case TOP_RECORD: + pTag->TagBOF = pTag->TagEOF = !hb_cdxPageReadTopKey( pTag->RootPage ); + break; + + case BTTM_RECORD: + pTag->TagBOF = pTag->TagEOF = !hb_cdxPageReadBottomKey( pTag->RootPage ); + break; + + case PREV_RECORD: + pTag->TagBOF = !hb_cdxPageReadPrevKey( pTag->RootPage ); + break; + + case NEXT_RECORD: + pTag->TagEOF = !hb_cdxPageReadNextKey( pTag->RootPage ); + break; + + case PRVU_RECORD: + pTag->TagBOF = !hb_cdxPageReadPrevUniqKey( pTag->RootPage ); + break; + + case NXTU_RECORD: + pTag->TagEOF = !hb_cdxPageReadNextUniqKey( pTag->RootPage ); + break; + } + if ( pTag->TagBOF || pTag->TagEOF ) + { + if ( !pTag->UsrAscend ) + { + BOOL fTmp; + fTmp = pTag->TagEOF; + pTag->TagEOF = pTag->TagBOF; + pTag->TagBOF = fTmp; + } + pTag->CurKey->rec = 0; + } + else if ( fAfter ) + { + if ( pTag->UsrAscend ) + { + if ( hb_cdxPageReadPrevUniqKey( pTag->RootPage ) ) + hb_cdxPageReadNextKey( pTag->RootPage ); } else { - pPage->CurKey = -1; - return FALSE; + if ( hb_cdxPageReadNextUniqKey( pTag->RootPage ) ) + hb_cdxPageReadPrevKey( pTag->RootPage ); } } } - -static LPCDXKEYINFO hb_cdxPageGetKey( LPCDXPAGEINFO pPage, USHORT uiKey ) +/* + * find pKey in pTag return 0 or TagNO + */ +static ULONG hb_cdxTagKeyFind( LPCDXTAG pTag, LPCDXKEY pKey ) { - LPCDXKEYINFO pKey; + int K; - if ( !pPage ) - hb_cdxErrInternal( "hb_cdxPageGetKey: pPage is NULL" ); - if ( !pPage->pKeys ) + pTag->CurKey->rec = 0; + pTag->fRePos = FALSE; + hb_cdxTagOpen( pTag ); + + pTag->TagBOF = pTag->TagEOF = FALSE; + K = hb_cdxPageSeekKey( pTag->RootPage, pKey, FALSE ); + if ( pKey->rec == CDX_MAX_REC_NUM && K != 0 ) + K = - K; + + if ( K > 0 ) + pTag->TagEOF = TRUE; + else { - //if ( uiKey == 0xffff ) return NULL; - //hb_cdxErrInternal( "hb_cdxPageGetKey: pPage->pKeys is NULL" ); - pKey = pPage->pKeys; - } - pKey = pPage->pKeys; - while( uiKey > 0 && pKey->pNext != NULL ) - { - pKey = pKey->pNext; - uiKey--; + hb_cdxSetCurKey( pTag->RootPage ); + if ( K == 0 ) + return pTag->CurKey->rec; } - return pKey; + return 0; } -static void hb_cdxPagePageLoad( LPCDXPAGEINFO pPage ) +/* + * add the Key into the Tag + */ +static void hb_cdxTagKeyAdd( LPCDXTAG pTag, LPCDXKEY pKey ) { - LPCDXKEYINFO pKey; + BOOL fFound; - while( pPage->pKeys != NULL ) + hb_cdxTagOpen( pTag ); + if ( pTag->UniqueKey ) { - pKey = pPage->pKeys; - pPage->pKeys = pPage->pKeys->pNext; + ULONG ulRec = pKey->rec; + pKey->rec = CDX_IGNORE_REC_NUM; + fFound = ( hb_cdxPageSeekKey( pTag->RootPage, pKey, TRUE ) == 0 ); + pKey->rec = ulRec; + } + else + fFound = ( hb_cdxPageSeekKey( pTag->RootPage, pKey, TRUE ) == 0 ); + + if ( ! fFound ) + { + hb_cdxPageKeyInsert( pTag->RootPage, pKey ); + /* TODO: !!! remove when page leaf balance can save CurKey */ + hb_cdxTagKeyFind( pTag, pKey ); + } +} + +/* + * Reorder the Tag list by their position in index file (not names) + * to be Clipper compatible + */ +static void hb_cdxReorderTagList( LPCDXTAG * TagListPtr ) +{ + LPCDXTAG *pTagPtr, pTagTmp; + BOOL fRepeat = TRUE; + + while ( fRepeat ) + { + fRepeat = FALSE; + pTagPtr = TagListPtr; + while ( *pTagPtr && (*pTagPtr)->pNext ) + { + if ( (*pTagPtr)->TagBlock > (*pTagPtr)->pNext->TagBlock ) + { + pTagTmp = (*pTagPtr); + (*pTagPtr) = (*pTagPtr)->pNext; + pTagTmp->pNext = (*pTagPtr)->pNext; + (*pTagPtr)->pNext = pTagTmp; + fRepeat = TRUE; + } + pTagPtr = &(*pTagPtr)->pNext; + } + } +} + +/* + * create new order header, store it and then make an order + */ +static void hb_cdxTagIndexTagNew( LPCDXTAG pTag, + char * KeyExp, PHB_ITEM pKeyItem, + BYTE bType, USHORT uiLen, + char * ForExp, PHB_ITEM pForItem, + BOOL fAscnd, BOOL fUniq, BOOL fCustom ) +{ + if ( KeyExp != NULL ) + { + pTag->KeyExpr = ( char * ) hb_xgrab( CDX_MAXKEY + 1 ); + /* TODO: !!! upering is buggy */ + hb_strncpyUpper( pTag->KeyExpr, KeyExp, CDX_MAXKEY ); + pTag->nField = hb_rddFieldIndex( (AREAP) pTag->pIndex->pArea, pTag->KeyExpr ); + } + pTag->pKeyItem = pKeyItem; + if ( ForExp != NULL ) + { + pTag->ForExpr = ( char * ) hb_xgrab( CDX_MAXKEY + 1 ); + /* TODO: !!! upering is buggy */ + hb_strncpyUpper( pTag->ForExpr, ForExp, CDX_MAXKEY ); + } + pTag->pForItem = pForItem; + pTag->AscendKey = pTag->UsrAscend = fAscnd; + pTag->UniqueKey = fUniq; + pTag->UsrUnique = FALSE; + pTag->Custom = fCustom; + pTag->uiType = bType; + pTag->uiLen = uiLen; + pTag->MaxKeys = CDX_INT_FREESPACE / ( uiLen + 8 ); + pTag->TagChanged = TRUE; + hb_cdxTagDoIndex( pTag ); +} + +/* + * remove Tag from Bag + */ +static void hb_cdxIndexDelTag( LPCDXINDEX pIndex, char * szTagName ) +{ + LPCDXTAG *pTagPtr = &pIndex->TagList; + + while ( *pTagPtr && hb_stricmp( (*pTagPtr)->szName, szTagName ) != 0 ) + pTagPtr = &(*pTagPtr)->pNext; + + if ( *pTagPtr ) + { + LPCDXTAG pTag = *pTagPtr; + LPCDXKEY pKey = hb_cdxKeyPutC( NULL, szTagName, CDX_MAXTAGNAMELEN, pTag->TagBlock ); + if ( hb_cdxTagKeyFind( pIndex->pCompound, pKey ) > 0 ) + { + hb_cdxPageKeyDelete( pIndex->pCompound->RootPage ); + /* TODO: !!! free header and all pages used by order */ + } + *pTagPtr = pTag->pNext; + hb_cdxTagFree( pTag ); hb_cdxKeyFree( pKey ); } - pPage->uiKeys = 0; - hb_cdxTagPageLoad( pPage->TagParent, pPage, 0 ); - pPage->Changed = FALSE; - pPage->keyAdded = FALSE; } -static int hb_cdxPageRetrieveKey( LPCDXPAGEINFO pPage, LPCDXKEYINFO *pKey ) +/* + * add tag to order bag + */ +static LPCDXTAG hb_cdxIndexAddTag( LPCDXINDEX pIndex, char * szTagName, + char * szKeyExp, PHB_ITEM pKeyItem, + BYTE bType, USHORT uiLen, + char * szForExp, PHB_ITEM pForItem, + BOOL fAscend, BOOL fUnique, BOOL fCustom ) { - int iCheck; - LPCDXKEYINFO pNewKey; + LPCDXTAG pTag, *pTagPtr; + LPCDXKEY pKey; - if( pPage->Owner == NULL ) - pPage->ChkBOF = pPage->ChkEOF = TRUE; - pPage->ChkBOF = ( pPage->ChkBOF && pPage->CurKey == 0 ); - pPage->ChkEOF = ( pPage->ChkEOF && pPage->CurKey == pPage->uiKeys - 1 ); - if( pPage->Child != NULL ) - return hb_cdxPageRetrieveKey( pPage->Child, pKey ); - else - { - pNewKey = hb_cdxPageGetKey( pPage, pPage->CurKey ); - *pKey = hb_cdxKeyCopy( *pKey, pNewKey ); - iCheck = 0; - if( pPage->ChkBOF ) - iCheck = 1; - if( pPage->ChkEOF ) - iCheck += 2; - return iCheck; - } -} - -static void hb_cdxPageAddNodeKey( LPCDXPAGEINFO pPage, LPCDXKEYINFO 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( LPCDXPAGEINFO pPage, LONG Tag ) -{ - int iSeek; - USHORT i; - LPCDXKEYINFO 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( LPCDXPAGEINFO pPage, LONG Tag ) -{ - if( Tag == 0 ) - return FALSE; - - /* TODO: What's this hack ??? PCZ */ - /* - if( pPage->TagParent->pIndex->NextAvail > 0 && - Tag > pPage->TagParent->pIndex->NextAvail ) - return FALSE; - */ - - if( pPage->PageType < PAGE_LEAF ) - { - if( pPage->Child != NULL ) - { - if( pPage->Child->Page != Tag || pPage->Child->Reload ) - { - hb_cdxPageFree( pPage->Child ); - pPage->Child = NULL; - } - } - if( pPage->Child == NULL ) - pPage->Child = hb_cdxPageNew( pPage->TagParent, pPage, Tag ); - } - return ( pPage->Child != NULL ); -} - -static void hb_cdxPageDeleteKey( LPCDXPAGEINFO pPage ) -{ - BOOL lastone; - LONG TempTag; - LPCDXKEYINFO p, pPrevKey; - - pPage->Changed = TRUE; - if( pPage->Child != NULL ) - hb_cdxPageDeleteKey( pPage->Child ); - else - { - lastone = ( pPage->CurKey >= pPage->uiKeys - 1 ); - p = hb_cdxPageGetKey( pPage, pPage->CurKey ); - if( pPage->pKeys == p ) - pPage->pKeys = p->pNext; - else - { - pPrevKey = hb_cdxPageGetKey( pPage, pPage->CurKey - 1 ); - pPrevKey->pNext = p->pNext; - } - pPage->uiKeys--; - pPage->Changed = TRUE; - hb_cdxKeyFree( p ); - if( pPage->CurKey >= pPage->uiKeys ) - pPage->CurKey = pPage->uiKeys - 1; - if( pPage->CurKey < 0 ) - pPage->CurKey = 0; - if( lastone && pPage->Owner != NULL ) - { - if( pPage->uiKeys > 0 ) - { - p = hb_cdxPageGetKey( pPage, pPage->CurKey ); - TempTag = p->Tag; - p->Tag = pPage->Page; - /* printf( "ReplaceNodeKey();" ); */ - hb_cdxPageReplaceNodeKey( pPage->Owner, p ); - p->Tag = TempTag; - } - else - /* printf( "DeleteNodeKey();" ); */ - hb_cdxPageDeleteNodeKey( pPage->Owner ); - } - } -} - -static void hb_cdxPageReplaceNodeKey( LPCDXPAGEINFO pPage, LPCDXKEYINFO pKey ) -{ - LPCDXKEYINFO p, pPrevKey; - LONG TempTag; - - p = hb_cdxPageGetKey( pPage, pPage->CurKey ); - p = hb_cdxKeyCopy( p, pKey ); - if( !pPage->CurKey ) - pPage->pKeys = p; - else - { - pPrevKey = hb_cdxPageGetKey( pPage, pPage->CurKey - 1 ); - pPrevKey->pNext = p; - } - pPage->Changed = TRUE; - if( pPage->Owner != NULL && pPage->CurKey >= pPage->uiKeys - 1 ) - { - TempTag = p->Tag; - p->Tag = pPage->Page; - hb_cdxPageReplaceNodeKey( pPage->Owner, pKey ); - p->Tag = TempTag; - } - - return; -} - -static void hb_cdxPageDeleteNodeKey( LPCDXPAGEINFO pPage ) -{ - BOOL lastone; - LONG TempTag; - LPCDXKEYINFO p, pPrevKey; - - lastone = ( pPage->CurKey >= pPage->uiKeys - 1 ); - p = hb_cdxPageGetKey( pPage, pPage->CurKey ); - if( pPage->pKeys == p ) - pPage->pKeys = p->pNext; - else - { - pPrevKey = hb_cdxPageGetKey( pPage, pPage->CurKey - 1 ); - pPrevKey->pNext = p->pNext; - } - pPage->uiKeys--; - hb_cdxKeyFree( p ); - if( pPage->CurKey >= pPage->uiKeys ) - pPage->CurKey = pPage->uiKeys - 1; - if( pPage->CurKey < 0 ) - pPage->CurKey = 0; - if( lastone && pPage->Owner != NULL ) - { - if( pPage->uiKeys > 0 ) - { - p = hb_cdxPageGetKey( pPage, pPage->CurKey ); - TempTag = p->Tag; - p->Tag = pPage->Page; - hb_cdxPageReplaceNodeKey( pPage->Owner, p ); - p->Tag = TempTag; - } - else - hb_cdxPageDeleteNodeKey( pPage->Owner ); - } -} - - -static void hb_cdxPageCalcLeafSpace( LPCDXPAGEINFO pPage ) -{ - USHORT uiKeyLength, cd, uiCount; - SHORT iSpace; - BYTE uiBitCount; - LPCDXTAG pTag; - ULONG ulMaxRec; - LPCDXKEYINFO p, q; - - pTag = pPage->TagParent; - if( pTag->OptFlags & 0x80 ) - ulMaxRec = hb_fsSeek( pTag->pIndex->hFile, 0, FS_END ); - else - ulMaxRec = pTag->pIndex->pArea->ulRecCount; - uiKeyLength = pTag->uiLen; - // if ( pPage->keyAdded || !pPage->ReqByte ) - if ( !pPage->ReqByte ) - { - for( uiBitCount = 0; uiKeyLength; uiBitCount++, uiKeyLength >>= 1 ); - pPage->ReqByte = 3; - pPage->RNBits = 24 - uiBitCount * 2; - pPage->RNMask = hb_cdxMakeMask( pPage->RNBits ); - while( ulMaxRec > pPage->RNMask ) - { - pPage->ReqByte++; - pPage->RNBits += 8; - pPage->RNMask = ( pPage->RNMask << 8 ) | 0xFF; - } - // pPage->FreeSpace = CDX_EXTERNAL_SPACE; - pPage->DCBits = pPage->TCBits = uiBitCount; - pPage->DCMask = (BYTE) hb_cdxMakeMask( pPage->DCBits ); - pPage->TCMask = (BYTE) hb_cdxMakeMask( pPage->TCBits ); - } - iSpace = 0; - q = NULL; - for( uiCount = 0; uiCount < pPage->uiKeys; uiCount++ ) - { - p = hb_cdxPageGetKey( pPage, uiCount ); - cd = p->length - hb_cdxKeyFindDup( p, q ); - q = p; - while( (ULONG) p->Tag > pPage->RNMask ) - { - pPage->ReqByte++; - pPage->RNBits += 8; - pPage->RNMask = ( pPage->RNMask << 8 ) | 0xFF; - iSpace += uiCount; - } - iSpace += cd + pPage->ReqByte; - } - pPage->FreeSpace = CDX_EXTERNAL_SPACE - iSpace; -} - -static SHORT hb_cdxPageCalcLeafKeySpace( LPCDXPAGEINFO pPage, LPCDXKEYINFO pKeyPrev, LPCDXKEYINFO pKey, LPCDXKEYINFO pKeyNext ) -{ - SHORT iSpace = 0; - - if ( pKeyPrev ) - { - iSpace += pPage->ReqByte + pKey->length - hb_cdxKeyFindDup( pKey, pKeyPrev ); - } - else - { - iSpace += pPage->ReqByte + pKey->length; // - cd; - } - if ( pKeyNext ) - { - if ( pKeyPrev ) - { - iSpace -= pKeyNext->length - hb_cdxKeyFindDup( pKeyNext, pKeyPrev ); - } - else - { - iSpace -= pKeyNext->length; - } - iSpace += pKeyNext->length - hb_cdxKeyFindDup( pKeyNext, pKey ); - } - if ( (ULONG) pKey->Tag > pPage->RNMask ) - { - ULONG RNMask = pPage->RNMask; - while( (ULONG) pKey->Tag > RNMask ) - { - iSpace += pPage->uiKeys + 1; - RNMask = ( RNMask << 8 ) | 0xFF; - } - //iSpace = -iSpace; - } - return iSpace; -} - -static BYTE hb_cdxPageKeyLeafBalance( LPCDXPAGEINFO pPage ) -{ - SHORT nFirstChild, nChilds, iSpace, iKeySpace; - LPCDXPAGEINFO childs[4], lpTmpPage; - LPCDXKEYINFO pKeyList, pKey, pKeyTmp; - BYTE bRet = 0; - USHORT uiCount, usKeys, usTotalKeys, i, j; - - nFirstChild = pPage->CurKey - 1; - if ( nFirstChild >= pPage->uiKeys - 2 ) - nFirstChild = pPage->uiKeys - 3; - if ( nFirstChild < 0 ) - nFirstChild = 0; - nChilds = pPage->uiKeys - nFirstChild; - if ( nChilds > 3 ) - nChilds = 3; - -#ifndef HB_CDX_DBGCODE_OFF - if ( nChilds <= 0 ) - hb_cdxErrInternal( "hb_cdxPageKeyLeafBalance: NO child keys." ); -#endif - - if ( nChilds > 0 ) - { - usTotalKeys = 0; - pKey = NULL; /* to avoid warning */ - for ( i = 0 ; i < nChilds ; i++ ) - { - pKey = hb_cdxPageGetKey( pPage, nFirstChild + i ); - if ( ( pPage->Child ) && ( pPage->Child->Page == pKey->Tag ) ) - { - childs[i] = pPage->Child; - pPage->Child = NULL; - } - else - { - childs[i] = hb_cdxPageNew( pPage->TagParent, pPage, pKey->Tag ); - } -#ifndef HB_CDX_DBGCODE_OFF - hb_cdxPageLeafCheckKeys( childs[i] ); -#endif - usTotalKeys += childs[i]->uiKeys; - } - - /* - * Join the complete key list - */ - pKeyList = pKeyTmp = NULL; - for ( i = 0 ; i < nChilds ; i++ ) - { - if ( childs[i]->uiKeys > 0 ) - { - if ( pKeyList == NULL ) - { - pKeyList = pKeyTmp = childs[i]->pKeys; - } - else - { - pKeyTmp = hb_cdxKeyListGetLast( pKeyTmp ); - pKeyTmp->pNext = childs[i]->pKeys; - } - childs[i]->pKeys = NULL; - childs[i]->uiKeys = 0; - } - } - - /* - * Redistribute childs internal node's keys - */ - usKeys = 0; - for ( i = 0 ; i < nChilds && pKeyList ; i++ ) - { - childs[i]->pKeys = pKeyList; - childs[i]->uiKeys = uiCount = 1; - hb_cdxPageCalcLeafSpace( childs[i] ); - iSpace = childs[i]->FreeSpace; - pKeyTmp = pKeyList; - pKeyList = pKeyList->pNext; - while ( pKeyList && ( iKeySpace = hb_cdxPageCalcLeafKeySpace( - childs[i], pKeyTmp, pKeyList, NULL ) ) <= iSpace ) - { - childs[i]->uiKeys++; - while ( (ULONG) pKeyList->Tag > childs[i]->RNMask ) - { - childs[i]->ReqByte++; - childs[i]->RNBits += 8; - childs[i]->RNMask = ( childs[i]->RNMask << 8 ) | 0xFF; - } - iSpace -= iKeySpace; - pKeyTmp = pKeyList; - pKeyList = pKeyList->pNext; - } - usKeys += childs[i]->uiKeys; - pKeyTmp->pNext = NULL; -#ifndef HB_CDX_DBGCODE_OFF - hb_cdxPageCalcLeafSpace( childs[i] ); - if ( childs[i]->FreeSpace != iSpace ) - { - hb_cdxErrInternal( "hb_cdxPageKeyLeafBalance: space calculated wrong!(1)." ); - } -#else - childs[i]->FreeSpace = iSpace; -#endif - } - - if ( pKeyList ) - { - childs[nChilds] = hb_cdxPageNew( pPage->TagParent, pPage, 0 ); - childs[nChilds]->Page = hb_cdxIndexGetAvailPage( pPage->TagParent->pIndex ); - childs[nChilds]->pKeys = pKeyList; - childs[nChilds]->uiKeys = usTotalKeys - usKeys; - childs[nChilds]->Changed = TRUE; - childs[nChilds]->keyAdded = TRUE; - childs[nChilds]->PageType = PAGE_LEAF; - nChilds++; - - /* Add new parent key */ - /* Already is: pKey = hb_cdxPageGetKey( pPage, nFirstChild + nChilds - 2 ); */ - pKeyTmp = hb_cdxKeyNew(); - pKeyTmp->pNext = pKey->pNext; - pKey->pNext = pKeyTmp; - pPage->uiKeys++; - - /* Update siblings links */ - childs[nChilds-1]->Left = childs[nChilds-2]->Page; - childs[nChilds-1]->Right = childs[nChilds-2]->Right; - childs[nChilds-2]->Right = childs[nChilds-1]->Page; - - if ( childs[nChilds-1]->Right != -1 ) - { - lpTmpPage = hb_cdxPageNew( pPage->TagParent, pPage, childs[nChilds-1]->Right ); - lpTmpPage->Left = childs[nChilds-1]->Page; - lpTmpPage->Changed = TRUE; - hb_cdxPageFree( lpTmpPage ); - } - hb_cdxPageCalcLeafSpace( childs[nChilds-1] ); -#ifndef HB_CDX_DBGCODE_OFF - if ( childs[nChilds-1]->FreeSpace < 0 ) - { - hb_cdxErrInternal( "hb_cdxPageKeyLeafBalance: space calculated wrong!(2)." ); - } -#endif - } - else if ( i < nChilds ) - { - LONG Left, Right; - - /* Update siblings links */ - Right = childs[nChilds-1]->Right; - if ( i > 0 ) - { - Left = childs[i-1]->Page; - childs[i-1]->Right = Right; - } - else - { - Left = childs[0]->Left; - if ( Left != -1 ) - { - lpTmpPage = hb_cdxPageNew( pPage->TagParent, pPage, Left ); - lpTmpPage->Right = Right; - lpTmpPage->Changed = TRUE; - hb_cdxPageFree( lpTmpPage ); - } - } - if ( Right != -1 ) - { - lpTmpPage = hb_cdxPageNew( pPage->TagParent, pPage, Right ); - lpTmpPage->Left = Left; - lpTmpPage->Changed = TRUE; - hb_cdxPageFree( lpTmpPage ); - } - - /* Unlink page from parent */ - for ( j = i ; j < nChilds ; j++ ) - { - /* Delete parent key */ - if ( nFirstChild + i - 1 < 0 ) - { - pKeyTmp = pPage->pKeys; - pPage->pKeys = pPage->pKeys->pNext; - } - else - { - pKey = hb_cdxPageGetKey( pPage, nFirstChild + i - 1 ); - pKeyTmp = pKey->pNext; - pKey->pNext = pKeyTmp->pNext; - } - hb_cdxKeyFree( pKeyTmp ); - pPage->uiKeys--; - - childs[j]->Owner = NULL; - childs[j]->Changed = FALSE; - childs[j]->PageType |= 0xF0; - childs[j]->Left = -1; - childs[j]->Right = -1; - hb_cdxPageRealFree( childs[j] ); - } - nChilds = i; - } - - for ( i = 0 ; i < nChilds ; i++ ) - { - /* Update parent node */ - pKeyTmp = hb_cdxPageGetKey( pPage, nFirstChild + i ); - pKey = hb_cdxKeyListGetLast( childs[i]->pKeys ); - hb_cdxKeyCopy( pKeyTmp, pKey ); - pKeyTmp->Tag = childs[i]->Page; - - childs[i]->Changed = TRUE; - childs[i]->keyAdded = TRUE; -#ifndef HB_CDX_DBGCODE_OFF - hb_cdxPageLeafCheckKeys( childs[i] ); -#endif - hb_cdxPageFree( childs[i] ); - } - pPage->Changed = TRUE; - if ( pPage->uiKeys > pPage->TagParent->MaxKeys - 1 ) - bRet |= 2; - if ( pPage->uiKeys < pPage->TagParent->MaxKeys / 2 - 1 ) - bRet |= 4; - } - else - bRet |= 4; - - return bRet; -} - -static BYTE hb_cdxPageKeyIntBalance( LPCDXPAGEINFO pPage ) -{ - SHORT nFirstChild, nChilds, nNeedCh; - LPCDXPAGEINFO childs[4], lpTmpPage; - LPCDXKEYINFO pKeyList, pKey, pKeyTmp; - BYTE bRet = 0; - USHORT usNodeKeys, usExtraKeys, i, usKeys; - - if ( pPage->Child->Child ) - hb_cdxPageFree( pPage->Child->Child ); - - nFirstChild = pPage->CurKey - 1; - if ( nFirstChild >= pPage->uiKeys - 2 ) - nFirstChild = pPage->uiKeys - 3; - if ( nFirstChild < 0 ) - nFirstChild = 0; - nChilds = pPage->uiKeys - nFirstChild; - if ( nChilds > 3 ) - nChilds = 3; - -#ifndef HB_CDX_DBGCODE_OFF - if ( nChilds <= 0 ) - hb_cdxErrInternal( "hb_cdxPageKeyIntBalance: NO child keys." ); -#endif - - if ( nChilds > 0 ) - { - usKeys = 0; - pKey = NULL; /* to avoid warning */ - for ( i = 0 ; i < nChilds ; i++ ) - { - pKey = hb_cdxPageGetKey( pPage, nFirstChild + i ); - if ( ( pPage->Child ) && ( pPage->Child->Page == pKey->Tag ) ) - { - childs[i] = pPage->Child; - pPage->Child = NULL; - } - else - { - childs[i] = hb_cdxPageNew( pPage->TagParent, pPage, pKey->Tag ); - } - usKeys += childs[i]->uiKeys; - } - - /* - * Join the complete key list - */ - pKeyList = pKeyTmp = NULL; - for ( i = 0 ; i < nChilds ; i++ ) - { - if ( childs[i]->uiKeys > 0 ) - { - if ( pKeyList == NULL ) - { - pKeyList = pKeyTmp = childs[i]->pKeys; - } - else - { - pKeyTmp = hb_cdxKeyListGetLast( pKeyTmp ); - pKeyTmp->pNext = childs[i]->pKeys; - } - childs[i]->pKeys = NULL; - childs[i]->uiKeys = 0; - } - } - - nNeedCh = ( usKeys + pPage->TagParent->MaxKeys - 1 ) - / pPage->TagParent->MaxKeys; - - if ( nNeedCh > nChilds ) - { - childs[nChilds] = hb_cdxPageNew( pPage->TagParent, pPage, 0 ); - childs[nChilds]->Page = hb_cdxIndexGetAvailPage( pPage->TagParent->pIndex ); - childs[nChilds]->pKeys = NULL; - childs[nChilds]->uiKeys = 0; - childs[nChilds]->Changed = TRUE; - childs[nChilds]->PageType = PAGE_NODE; - nChilds++; - - /* Add new parent key */ - /* Already is: pKey = hb_cdxPageGetKey( pPage, nFirstChild + nChilds - 2 ); */ - pKeyTmp = hb_cdxKeyNew(); - pKeyTmp->pNext = pKey->pNext; - pKey->pNext = pKeyTmp; - pPage->uiKeys++; - - /* Update siblings links */ - childs[nChilds-1]->Left = childs[nChilds-2]->Page; - childs[nChilds-1]->Right = childs[nChilds-2]->Right; - childs[nChilds-2]->Right = childs[nChilds-1]->Page; - - if ( childs[nChilds-1]->Right != -1 ) - { - lpTmpPage = hb_cdxPageNew( pPage->TagParent, pPage, childs[nChilds-1]->Right ); - lpTmpPage->Left = childs[nChilds-1]->Page; - lpTmpPage->Changed = TRUE; - hb_cdxPageFree( lpTmpPage ); - } - } - else if ( nNeedCh < nChilds ) - { - LONG Left, Right; - - /* Update siblings links */ - Right = childs[nChilds-1]->Right; - if ( nNeedCh > 0 ) - { - Left = childs[nNeedCh-1]->Page; - childs[nNeedCh-1]->Right = Right; - } - else - { - Left = childs[0]->Left; - if ( Left != -1 ) - { - lpTmpPage = hb_cdxPageNew( pPage->TagParent, pPage, Left ); - lpTmpPage->Right = Right; - lpTmpPage->Changed = TRUE; - hb_cdxPageFree( lpTmpPage ); - } - } - if ( Right != -1 ) - { - lpTmpPage = hb_cdxPageNew( pPage->TagParent, pPage, Right ); - lpTmpPage->Left = Left; - lpTmpPage->Changed = TRUE; - hb_cdxPageFree( lpTmpPage ); - } - /* Unlink page from parent */ - for ( i = nNeedCh ; i < nChilds ; i++ ) - { - /* Delete parent key */ - if ( nFirstChild + nNeedCh - 1 < 0 ) - { - pKeyTmp = pPage->pKeys; - pPage->pKeys = pPage->pKeys->pNext; - } - else - { - pKey = hb_cdxPageGetKey( pPage, nFirstChild + nNeedCh - 1 ); - pKeyTmp = pKey->pNext; - pKey->pNext = pKeyTmp->pNext; - } - hb_cdxKeyFree( pKeyTmp ); - pPage->uiKeys--; - - childs[i]->Owner = NULL; - childs[i]->Changed = FALSE; - childs[i]->PageType |= 0xF0; - childs[i]->Left = -1; - childs[i]->Right = -1; - hb_cdxPageRealFree( childs[i] ); - } - nChilds = nNeedCh; - } - - /* - * Redistribute childs internal node's keys - */ - - usNodeKeys = usKeys / ( nChilds ); - usExtraKeys = usKeys % ( nChilds ); - for ( i = 0 ; i < nChilds ; i++ ) - { - if ( usExtraKeys > 0 ) - { - childs[i]->uiKeys = usNodeKeys + 1; - usExtraKeys--; - } - else - { - childs[i]->uiKeys = usNodeKeys; - } - childs[i]->pKeys = pKeyList; - pKeyTmp = hb_cdxKeyListGetKey( pKeyList, childs[i]->uiKeys-1 ); - pKeyList = pKeyTmp->pNext; - pKeyTmp->pNext = NULL; - } - - for ( i = 0 ; i < nChilds ; i++ ) - { - /* Update parent node */ - pKeyTmp = hb_cdxPageGetKey( pPage, nFirstChild + i ); - pKey = hb_cdxKeyListGetLast( childs[i]->pKeys ); - hb_cdxKeyCopy( pKeyTmp, pKey ); - pKeyTmp->Tag = childs[i]->Page; - - childs[i]->Changed = TRUE; - hb_cdxPageFree( childs[i] ); - } - pPage->Changed = TRUE; - if ( pPage->uiKeys > pPage->TagParent->MaxKeys - 1 ) - bRet |= 2; - if ( pPage->uiKeys < pPage->TagParent->MaxKeys / 2 - 1 ) - bRet |= 4; - } - else - bRet |= 4; - - return bRet; -} - -static BYTE hb_cdxPageRootSplit( LPCDXPAGEINFO pPage ) -{ - LPCDXPAGEINFO pNewChild; - BYTE bChildRet; - LPCDXKEYINFO pKey; - - if ( pPage->PageType >= PAGE_LEAF ) - { - // es la raíz (hoja) y se quedó sin espacio!!! - /* is "Leaf / Root" - split it! */ - pNewChild = hb_cdxPageNew( pPage->TagParent, pPage, 0 ); - pNewChild->Page = hb_cdxIndexGetAvailPage( pPage->TagParent->pIndex ); - pNewChild->pKeys = pPage->pKeys; - pNewChild->uiKeys = pPage->uiKeys; - pNewChild->Changed = TRUE; - pNewChild->keyAdded = TRUE; - pNewChild->PageType = PAGE_LEAF; - hb_cdxPageCalcLeafSpace( pNewChild ); - pKey = hb_cdxKeyListGetLast( pNewChild->pKeys ); - pPage->pKeys = hb_cdxKeyCopy( NULL, pKey ); - pPage->pKeys->Tag = pNewChild->Page; - pPage->uiKeys = 1; - pPage->CurKey = 0; - pPage->PageType = PAGE_ROOT; - pPage->Child = pNewChild; - pPage->Changed = TRUE; - pPage->keyAdded = TRUE; - bChildRet = hb_cdxPageKeyLeafBalance( pPage ); - // ret = childRet; - } - else - { - // es la raíz (interior) y se quedó sin espacio... - /* is "Internal / Root" - split it! */ - pNewChild = hb_cdxPageNew( pPage->TagParent, pPage, 0 ); - pNewChild->Page = hb_cdxIndexGetAvailPage( pPage->TagParent->pIndex ); - pNewChild->pKeys = pPage->pKeys; - pNewChild->uiKeys = pPage->uiKeys; - pNewChild->Changed = TRUE; - pNewChild->PageType = PAGE_NODE; - hb_cdxPageCalcLeafSpace( pNewChild ); - pKey = hb_cdxKeyListGetLast( pNewChild->pKeys ); - pPage->pKeys = hb_cdxKeyCopy( NULL, pKey ); - pPage->pKeys->Tag = pNewChild->Page; - pPage->uiKeys = 1; - pPage->CurKey = 0; - pPage->PageType = PAGE_ROOT; - pPage->Child = pNewChild; - pPage->Changed = TRUE; - bChildRet = hb_cdxPageKeyIntBalance( pPage ); - // ret = childRet; - } - return bChildRet; -} - -static BYTE hb_cdxPageKeyLeafDelete( LPCDXPAGEINFO pPage ) -{ - LPCDXKEYINFO pDelKey, pTmpKey; - BYTE bRet = 0; - - if( pPage->CurKey > pPage->uiKeys ) - pPage->CurKey = pPage->uiKeys - 1; - if( pPage->CurKey < 0 ) - pPage->CurKey = 0; - - if( pPage->Owner && ( pPage->CurKey >= pPage->uiKeys - 1 ) ) - bRet |= 1; - - if( !pPage->uiKeys ) - { - bRet |= 8; /* Internal error */ - hb_cdxErrInternal( "hb_cdxPageKeyLeafDelete: delete in empty page!." ); - } - else - { - if( pPage->CurKey == 0 ) - { - pDelKey = pPage->pKeys; - pPage->pKeys = pPage->pKeys->pNext; - hb_cdxKeyFree(pDelKey); - pPage->uiKeys--; - // TODO : optimize this calc - hb_cdxPageCalcLeafSpace( pPage ); - } - else - { - pTmpKey = hb_cdxPageGetKey( pPage, pPage->CurKey - 1); - pDelKey = pTmpKey->pNext; - pTmpKey->pNext = pDelKey->pNext; - hb_cdxKeyFree(pDelKey); - pPage->uiKeys--; - // TODO : optimize this calc - hb_cdxPageCalcLeafSpace( pPage ); - } - } - pPage->Changed = TRUE; - if ( pPage->FreeSpace > CDX_EXTERNAL_SPACE / 2 + 3 ) - { - bRet |= 4; - } - return bRet; -} - -static BYTE hb_cdxPageKeyDelete( LPCDXPAGEINFO pPage ) -{ - LPCDXKEYINFO pLastKey, p; - BYTE bRet, bChildRet; - - if ( pPage->PageType == PAGE_LEAF ) - { - bRet = hb_cdxPageKeyLeafDelete( pPage ); - } - else - { - /* Internal node */ - bChildRet = hb_cdxPageKeyDelete( pPage->Child ); - - bRet = 0; - if ( !bChildRet ) - { - return bRet; - } - else if ( bChildRet & 1 ) - { - if ( pPage->Child->uiKeys == 0 ) - { - bChildRet |= 4; - } - else - { - p = hb_cdxPageGetKey( pPage, pPage->CurKey ); - pLastKey = hb_cdxPageGetKey( pPage->Child, pPage->Child->uiKeys - 1 ); - hb_cdxKeyCopy( p, pLastKey ); - p->Tag = pPage->Child->Page; - } - pPage->Changed = TRUE; - if ( pPage->Owner && ( pPage->CurKey >= pPage->uiKeys - 1 ) ) - bRet |= 1; - } - - if ( bChildRet & 4 ) - { - /* - * Child has free space > 1/2 - */ - if ( pPage->Child->PageType == PAGE_LEAF ) - { - /* Reorganize the childs, if this page is root and the childs are small enough, - * then join them into root - */ - // bChildRet = - hb_cdxPageKeyLeafBalance( pPage ); - /* If a new child is needed and this page is full: - * - If it's root, copy to a child page linked to an empty LEAF root and redistribute it - * - if not ask the parent to redistribute this page - */ - if ( pPage->uiKeys < pPage->TagParent->MaxKeys / 2 - 1 ) - { - if ( pPage->Owner ) - { - bRet |= 4; - return bRet; /* too much free space for this page */ - } - else - { - return bRet; - } - } - } - else - { - /* Internal child has too much free space: - * 1) Try redistribute from siblings nodes - * 2) If it is possible: - * - redistribute childs deleting one child node - * - if this page is root and it can hold child keys: - * Join then into Root: - * */ - // bChildRet = - hb_cdxPageKeyIntBalance( pPage ); - - if ( pPage->uiKeys < pPage->TagParent->MaxKeys / 2 - 1 ) - { - if ( pPage->Owner ) - { - bRet |= 4; /* too much free space for this page */ - } - return bRet; - } - } - } - } - return bRet; -} - -#ifndef HB_CDX_DBGCODE_OFF -static void hb_cdxPageLeafCheckKeys( LPCDXPAGEINFO pPage ) -{ - LPCDXKEYINFO p, last; - int res; - - last = pPage->pKeys; - if ( pPage->uiKeys > 0 || last ) - { - p = last->pNext; - while ( p ) - { - res = hb_cdxKeyCompare( last, p, TRUE); - if ( res == 0 ) - { - res = last->Tag - p->Tag; - } - if ( res >= 0 ) - { - hb_cdxErrInternal( "hb_cdxPageLeafCheckKeys: index corrupted." ); - } - last = p; - p = last->pNext; - } - } -} -#endif - -/* end hb_cdxPagexxx */ -/* end hb_cdxPagexxx */ - - -/* hb_cdxIndexxxx */ -/* #include "cdxindex.c" */ - -/* hb_cdxIndexxxx */ - -static LPCDXINDEX hb_cdxIndexNew( AREAP pArea ) -{ - LPCDXINDEX pIndex; - - pIndex = ( LPCDXINDEX ) hb_xgrab( sizeof( CDXINDEX ) ); - memset( pIndex, 0, sizeof( CDXINDEX ) ); - pIndex->hFile = FS_ERROR; - pIndex->pArea = (LPCDXAREA) pArea; - pIndex->NextAvail = -1; - return pIndex; -} - -static void hb_cdxIndexFree( LPCDXINDEX pIndex ) -{ - LPCDXTAG pTag; - - hb_cdxIndexLockWrite ( pIndex, NULL ); - /* Free Compound tag */ - if( pIndex->pCompound != NULL ) - { - hb_cdxTagTagClose( pIndex->pCompound ); - hb_cdxTagFree( pIndex->pCompound ); - pIndex->pCompound = NULL; - } - - /* Free all tags */ - while( pIndex->TagList ) - { - pTag = pIndex->TagList; - pIndex->TagList = pTag->pNext; - hb_cdxTagFree( pTag ); - } - hb_cdxIndexUnLockWrite ( pIndex, NULL ); - - /* Close file */ - if( pIndex->hFile != FS_ERROR ) - hb_fsClose( pIndex->hFile ); - - if ( pIndex->fShared && ( pIndex->lockWrite || pIndex->lockRead ) ) - hb_errInternal( 9104, "hb_cdxIndexFree: index file still locked.", "", "" ); - - if( pIndex->szFileName != NULL ) - hb_xfree( pIndex->szFileName ); - - hb_xfree( pIndex ); -} - -static void hb_cdxIndexResetAvailPage( LPCDXINDEX pIndex ) -{ - pIndex->NextAvail = hb_fsSeek( pIndex->hFile, 0, FS_END ); -} - -static LONG hb_cdxIndexGetAvailPage( LPCDXINDEX pIndex ) -{ - FHANDLE hFile = pIndex->hFile; - LONG lPos = 0; - - if ( pIndex->fReadonly ) - { - hb_errInternal( 9101, "hb_cdxIndexGetAvailPage on readonly database.", "", "" ); - } - if ( pIndex->fShared && !pIndex->lockRead ) - { - hb_errInternal( 9102, "hb_cdxIndexGetAvailPage on not locked index file.", "", "" ); - } - - if( pIndex->NextAvail == -1 ) - hb_cdxIndexResetAvailPage( pIndex ); - - if ( pIndex->NextAvail != 0 ) - { - if ( hb_fsSeek( hFile, 4, FS_SET ) != 4 || - hb_fsRead( hFile, (BYTE *) &lPos, 4 ) != 4 ) - { - hb_errInternal( HB_EI_ERRUNRECOV, "hb_cdxIndexGetAvailPage: index read failed.", "", "" ); - } - } - - if ( lPos == 0 || lPos == -1 ) - { - BYTE byBuf[CDX_PAGELEN]; - memset( byBuf, 0, CDX_PAGELEN ); - lPos = hb_fsSeek( hFile, 0, FS_END ); - if ( hb_fsWrite( hFile, byBuf, CDX_PAGELEN ) != CDX_PAGELEN ) - hb_errInternal( 1010, "Write in index page failed.(0)", "", "" ); - } - else - { - BYTE byBuf[4]; - - if ( hb_fsSeek( hFile, lPos, FS_SET ) != (ULONG) lPos || - hb_fsRead( hFile, (BYTE *) &byBuf, 4 ) != 4 || - hb_fsSeek( hFile, 4, FS_SET ) != 4 || - hb_fsWrite( hFile, (BYTE *) &byBuf, 4 ) != 4 ) - { - hb_errInternal( 1010, "Write in index page failed.(1)", "", "" ); - } - - } - - pIndex->NextAvail = lPos + CDX_PAGELEN; - - return lPos; -} - -static void hb_cdxIndexPutAvailPage( LPCDXPAGEINFO pPage ) -{ - if ( pPage->Page != 0 && pPage->Page != -1 ) - { - FHANDLE hFile = pPage->TagParent->pIndex->hFile; - LONG lPos = pPage->Page; - BYTE byPageBuf[CDX_PAGELEN]; - - /* testing properly rights */ - if ( pPage->TagParent->pIndex->fReadonly ) - { - hb_errInternal( 9101, "hb_cdxIndexPutAvailPage on readonly database.", "", "" ); - } - if ( pPage->TagParent->pIndex->fShared && - !pPage->TagParent->pIndex->lockRead ) - { - hb_errInternal( 9102, "hb_cdxIndexPutAvailPage on not locked index file.", "", "" ); - } - memset(byPageBuf, 0, CDX_PAGELEN); - if ( hb_fsSeek( hFile, 4, FS_SET ) != 4 || - hb_fsRead( hFile, byPageBuf, 4 ) != 4 ) - { - hb_errInternal( HB_EI_ERRUNRECOV, "hb_cdxIndexPutAvailPage: index read failed.", "", "" ); - } - if ( hb_fsSeek( hFile, lPos, FS_SET ) != (ULONG) lPos || - hb_fsWrite( hFile, byPageBuf, CDX_PAGELEN ) != CDX_PAGELEN || - hb_fsSeek( hFile, 4, FS_SET ) != 4 || - hb_fsWrite( hFile, (BYTE *) &lPos, 4 ) != 4 ) - { - hb_errInternal( 1010, "Write in index page failed.", "", "" ); - } - } -} - -static void hb_cdxIndexPageRead( LPCDXINDEX pIndex, LONG lPos, void * pBuffer, - USHORT uiSize ) -{ - /* testing properly rights */ - if ( pIndex->fShared && !pIndex->lockRead ) - hb_errInternal( 9103, "hb_cdxIndexPageRead on not locked index file.", "", "" ); - - if( hb_fsSeek( pIndex->hFile, lPos, FS_SET ) == (ULONG) lPos ) - hb_fsRead( pIndex->hFile, ( BYTE * ) pBuffer, uiSize ); -} - -static void hb_cdxIndexPageWrite( LPCDXINDEX pIndex, LONG lPos, void * pBuffer, - USHORT uiSize ) -{ - /* testing properly rights */ - if ( pIndex->fReadonly ) - hb_errInternal( 9101, "hb_cdxIndexPageWrite on readonly database.", "", "" ); - - /* if ( pIndex->fShared && !pIndex->lockWrite ) */ - if ( pIndex->fShared && !pIndex->lockRead ) - hb_errInternal( 9102, "hb_cdxIndexPageWrite on not locked index file.", "", "" ); - pIndex->changesWritten = 1; - if( !( ( hb_fsSeek( pIndex->hFile, lPos, FS_SET ) == (ULONG) lPos ) && - ( hb_fsWrite( pIndex->hFile, ( BYTE * ) pBuffer, uiSize ) == uiSize) ) ) - hb_errInternal( 1010, "Write in index page failed.", "", "" ); -} - -static LPCDXTAG hb_cdxIndexAddTag( LPCDXINDEX pIndex, char * szTagName, char * szKeyExp, - PHB_ITEM pKeyItem, BYTE bType, USHORT uiLen, char * szForExp, - PHB_ITEM pForItem, BOOL bAscending, BOOL bUnique, BOOL bCustom ) -{ - LPCDXTAG pTag, pTagTmp, pLastTag; - LPCDXKEYINFO pKey; + /* Delete previous tag first to free the place for new one */ + hb_cdxIndexDelTag( pIndex, szTagName ); /* Create new tag an add to tag list */ - pTag = hb_cdxTagNew( pIndex, szTagName, -1 ); - - hb_cdxTagIndexTagNew( pTag, szKeyExp, pKeyItem, bType, uiLen, szForExp, - pForItem, bAscending, bUnique, bCustom ); - - /* Delete previous tag an new one add to tag list */ - hb_cdxTagTagOpen( pIndex->pCompound, 0 ); - pKey = hb_cdxKeyNew(); - pKey = hb_cdxKeyPutC( pKey, szTagName, CDX_MAX_TAG_NAME_LEN ); - pTagTmp = pIndex->TagList; - pLastTag = NULL; - while( pTagTmp != NULL ) - { - if( hb_stricmp( pTagTmp->szName, szTagName ) == 0 ) - { - pKey->Tag = pTagTmp->TagBlock; - if( hb_cdxTagKeyFind( pIndex->pCompound, pKey ) > 0 ) - hb_cdxPageDeleteKey( pIndex->pCompound->RootPage ); - if( pLastTag == NULL ) - pIndex->TagList = pTagTmp->pNext; - else - pLastTag->pNext = pTagTmp->pNext; - hb_cdxTagFree( pTagTmp ); - break; - } - pLastTag = pTagTmp; - pTagTmp = pTagTmp->pNext; - } - - if( pIndex->TagList == NULL ) - pIndex->TagList = pTag; - else - { - pLastTag = pIndex->TagList; - while( pLastTag->pNext ) - pLastTag = pLastTag->pNext; - pLastTag->pNext = pTag; - } - - pKey = hb_cdxKeyPutC( pKey, pTag->szName, CDX_MAX_TAG_NAME_LEN ); - pKey->Tag = pTag->TagBlock; + pTag = hb_cdxTagNew( pIndex, szTagName, CDX_DUMMYNODE ); + hb_cdxTagIndexTagNew( pTag, szKeyExp, pKeyItem, bType, uiLen, + szForExp, pForItem, + fAscend, fUnique, fCustom ); + pTagPtr = &pIndex->TagList; + while ( *pTagPtr ) + pTagPtr = &(*pTagPtr)->pNext; + *pTagPtr = pTag; + pKey = hb_cdxKeyPutC( NULL, szTagName, CDX_MAXTAGNAMELEN, pTag->TagBlock ); hb_cdxTagKeyAdd( pIndex->pCompound, pKey ); hb_cdxKeyFree( pKey ); - pIndex->pCompound->RootPage->Changed = TRUE; - hb_cdxTagTagClose( pIndex->pCompound ); return pTag; } - -static void hb_cdxIndexDelTag( LPCDXINDEX pIndex, char * szTagName ) -{ - LPCDXTAG pTag, pLastTag; - LPCDXKEYINFO pKey; - - hb_cdxTagTagOpen( pIndex->pCompound, 0 ); - pKey = hb_cdxKeyNew(); - pKey = hb_cdxKeyPutC( pKey, szTagName, CDX_MAX_TAG_NAME_LEN ); - pTag = pIndex->TagList; - pLastTag = NULL; - while( pTag != NULL ) - { - if( hb_stricmp( pTag->szName, szTagName ) == 0 ) - { - pKey->Tag = pTag->TagBlock; - if( hb_cdxTagKeyFind( pIndex->pCompound, pKey ) > 0 ) - hb_cdxPageDeleteKey( pIndex->pCompound->RootPage ); - if( pLastTag == NULL ) - pIndex->TagList = pTag->pNext; - else - pLastTag->pNext = pTag->pNext; - hb_cdxTagFree( pTag ); - break; - } - pLastTag = pTag; - pTag = pTag->pNext; - } - - hb_cdxKeyFree( pKey ); - pIndex->pCompound->RootPage->Changed = TRUE; - hb_cdxTagTagClose( pIndex->pCompound ); -} - +/* + * rebuild from scratch all orders in index file + */ static void hb_cdxIndexReindex( LPCDXINDEX pIndex ) { - LPCDXTAG pOldCompound, pTagList, pTag; + LPCDXTAG pCompound, pTagList, pTag; - hb_cdxPagePoolFlush( pIndex ); - hb_cdxPagePoolFree( pIndex, 0 ); - /* Free Compound tag */ - pOldCompound = pIndex->pCompound; - if( pIndex->pCompound != NULL ) - { - hb_cdxTagTagClose( pIndex->pCompound ); - hb_cdxPagePoolFreeTag( pIndex->pCompound, 0 ); - //hb_cdxTagFree( pIndex->pCompound ); - pIndex->pCompound = NULL; - } - /* Free all tags */ - pTag = pIndex->TagList; - while( pTag ) - { - hb_cdxTagTagClose( pTag ); - hb_cdxPagePoolFreeTag( pTag, 0 ); - // hb_cdxTagFree( pTag ); - pTag = pTag->pNext; - } + hb_cdxIndexLockWrite( pIndex ); + hb_cdxIndexDiscardBuffers( pIndex ); + + pCompound = pIndex->pCompound; pTagList = pIndex->TagList; - - /* Reset index */ - pIndex->NextAvail = 0; - // FHANDLE pIndex->hFile; /* Index file handle */ pIndex->pCompound = NULL; pIndex->TagList = NULL; - // pIndex->fShared; /* Shared file */ - // pIndex->fReadonly; /* Read only file */ - pIndex->lockWrite = pIndex->lockRead = 0; - pIndex->changesWritten = 0; - pIndex->ulVersion = 0; + pIndex->ulVersion = 0; + pIndex->nextAvail = 0; + pIndex->freePage = 0; hb_fsSeek( pIndex->hFile, 0, FS_SET ); hb_fsWrite( pIndex->hFile, NULL, 0 ); - /* Rebuild the master tag */ - pIndex->NextAvail = 0; - if ( pOldCompound ) + /* Rebuild the compound (master) tag */ + if ( pCompound ) { - pIndex->pCompound = hb_cdxTagNew( pIndex, pOldCompound->szName, -1 ); - pIndex->pCompound->OptFlags = 0xE0; - hb_cdxTagIndexTagNew( pIndex->pCompound, NULL, NULL, 'C', 10, NULL, NULL, - TRUE, FALSE, FALSE ); - hb_cdxTagTagOpen( pIndex->pCompound, 0 ); - hb_cdxTagFree( pOldCompound ); + pIndex->pCompound = hb_cdxTagNew( pIndex, pCompound->szName, CDX_DUMMYNODE ); + pIndex->pCompound->OptFlags = CDX_TYPE_COMPACT | CDX_TYPE_COMPOUND | CDX_TYPE_STRUCTURE;; + hb_cdxTagIndexTagNew( pIndex->pCompound, NULL, NULL, 'C', + CDX_MAXTAGNAMELEN, NULL, NULL, TRUE, FALSE, FALSE ); + hb_cdxTagFree( pCompound ); } + /* Rebuild each tag */ while ( pTagList ) { @@ -4796,161 +3756,2496 @@ static void hb_cdxIndexReindex( LPCDXINDEX pIndex ) pTag->pKeyItem = pTag->pForItem = NULL; hb_cdxTagFree( pTag ); } + hb_cdxIndexUnLockWrite( pIndex ); } -static USHORT hb_cdxIndexCheckVersion( LPCDXINDEX pIndex ) +/* + * create new index structure + */ +static LPCDXINDEX hb_cdxIndexNew( CDXAREAP pArea ) +{ + LPCDXINDEX pIndex; + + pIndex = ( LPCDXINDEX ) hb_xgrab( sizeof( CDXINDEX ) ); + memset( pIndex, 0, sizeof( CDXINDEX ) ); + pIndex->hFile = FS_ERROR; + pIndex->pArea = pArea; + pIndex->nextAvail = CDX_DUMMYNODE; + return pIndex; +} + +/* + * free (close) index and all tags in it + */ +static void hb_cdxIndexFree( LPCDXINDEX pIndex ) { - USHORT ret = 0; - ULONG ulVersion; LPCDXTAG pTag; - if( (hb_fsSeek( pIndex->hFile, 0x08, FS_SET ) == 0x08) && - (hb_fsRead( pIndex->hFile, ( BYTE * ) &ulVersion, 4) == 4) ) + /* Free Compound tag */ + if ( pIndex->pCompound != NULL ) { - ulVersion = hb_cdxSwapBytes( ulVersion ); - if ( ulVersion == pIndex->ulVersion ) { - ret = 1; + hb_cdxTagFree( pIndex->pCompound ); + pIndex->pCompound = NULL; + } + + /* Free all tags */ + while ( pIndex->TagList ) + { + pTag = pIndex->TagList; + pIndex->TagList = pTag->pNext; + hb_cdxTagFree( pTag ); + } + /* Close file */ + if ( pIndex->hFile != FS_ERROR ) + hb_fsClose( pIndex->hFile ); + + if ( pIndex->fShared && ( pIndex->lockWrite || pIndex->lockRead ) ) + hb_errInternal( 9104, "hb_cdxIndexFree: index file still locked.", "", "" ); + + if ( pIndex->szFileName != NULL ) + hb_xfree( pIndex->szFileName ); + + hb_xfree( pIndex ); +} + +/* + * load orders from index file + */ +static void hb_cdxIndexLoad( LPCDXINDEX pIndex, char * szBaseName ) +{ + LPCDXTAG TagList, * pTagPtr; + + /* TODO: check if index file is not corrupted */ + + pIndex->fShared = pIndex->pArea->fShared; + pIndex->fReadonly = pIndex->pArea->fReadonly; + hb_cdxIndexLockRead( pIndex ); + /* load the tags*/ + pIndex->pCompound = hb_cdxTagNew( pIndex, szBaseName, 0L ); + pIndex->pCompound->OptFlags = CDX_TYPE_COMPACT | CDX_TYPE_COMPOUND | CDX_TYPE_STRUCTURE; + TagList = NULL; + pTagPtr = &TagList; + hb_cdxTagKeyRead( pIndex->pCompound, TOP_RECORD ); + while ( !pIndex->pCompound->TagEOF ) + { + (*pTagPtr) = hb_cdxTagNew( pIndex, pIndex->pCompound->CurKey->val, + pIndex->pCompound->CurKey->rec ); + pTagPtr = &(*pTagPtr)->pNext; + hb_cdxTagKeyRead( pIndex->pCompound, NEXT_RECORD ); + } + hb_cdxIndexUnLockRead( pIndex ); + hb_cdxReorderTagList( &TagList ); + pTagPtr = &pIndex->TagList; + while ( *pTagPtr != NULL ) + pTagPtr = &(*pTagPtr)->pNext; + (*pTagPtr) = TagList; +#ifdef HB_CDX_DSPDBG_INFO + hb_cdxDspTags( pIndex ); +#endif +} + +/* + * free (close) used indexes, if not fAll then keep structure index + */ +static void hb_cdxOrdListClear( CDXAREAP pArea, BOOL fAll, LPCDXINDEX pKeepInd ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_cdxOrdListClear(%p, %d)", pArea, (int) fAll)); + + if ( pArea->lpIndexes ) + { + LPCDXINDEX pIndex, * pIndexPtr; + if ( !fAll ) + { + /* TODO: we have to control this on open */ + PHB_FNAME pFileNameDbf, pFileNameCdx; + pFileNameDbf = hb_fsFNameSplit( pArea->szDataFileName ); + pFileNameCdx = hb_fsFNameSplit( pArea->lpIndexes->szFileName ); + fAll = ( hb_stricmp( pFileNameDbf->szName, pFileNameCdx->szName ) != 0 ); + hb_xfree( pFileNameDbf ); + hb_xfree( pFileNameCdx ); + } + pIndexPtr = fAll ? &pArea->lpIndexes : &pArea->lpIndexes->pNext; + while ( *pIndexPtr ) + { + pIndex = *pIndexPtr; + if ( pKeepInd == pIndex ) + pIndexPtr = &pIndex->pNext; + else + { + *pIndexPtr = pIndex->pNext; + hb_cdxIndexFree( pIndex ); + } + } + } +} + +/* + * find order bag by its name + * TODO: This only checks for basename of bag, + * a complete (but reliable) test should be done to look for the same file + * druzus: if we allow to make more bugs with the same name - + * I'm not a fun of this + */ +static LPCDXINDEX hb_cdxFindBag( CDXAREAP pArea, char * szBagName ) +{ + LPCDXINDEX pIndex; + PHB_FNAME pFileName; + char * szBaseName; + + pFileName = hb_fsFNameSplit( szBagName ); + szBaseName = hb_strdup( pFileName->szName ); + hb_strUpper( szBaseName, strlen(szBaseName)); + + pIndex = pArea->lpIndexes; + while ( pIndex ) { + hb_xfree( pFileName ); + pFileName = hb_fsFNameSplit( pIndex->szFileName ); + hb_strUpper( pFileName->szName, strlen(pFileName->szName)); + if ( !hb_stricmp( pFileName->szName, szBaseName ) ) + break; + pIndex = pIndex->pNext; + } + hb_xfree( pFileName ); + hb_xfree( szBaseName ); + return pIndex; +} + +/* + * get Tag by number + */ +static LPCDXTAG hb_cdxGetTagByNumber( CDXAREAP pArea, USHORT uiTag ) +{ + LPCDXTAG pTag = NULL; + LPCDXINDEX pIndex = pArea->lpIndexes; + + while ( uiTag && pIndex ) + { + pTag = pIndex->TagList; + while ( uiTag && pTag ) + { + if ( --uiTag ) + pTag = pTag->pNext; + } + pIndex = pIndex->pNext; + } + return pTag; +} + +/* + * get Tag number + */ +static USHORT hb_cdxGetTagNumber( CDXAREAP pArea, LPCDXTAG pFindTag ) +{ + USHORT uiTag = 0; + LPCDXTAG pTag = NULL; + LPCDXINDEX pCdx = pArea->lpIndexes; + + if ( pFindTag ) + { + while ( pCdx && ( pTag != pFindTag ) ) + { + pTag = pCdx->TagList; + while ( pTag ) + { + uiTag++; + if ( pTag == pFindTag ) + break; + pTag = pTag->pNext; + } + pCdx = pCdx->pNext; + } + if ( !pTag ) + uiTag = 0; + } + return uiTag; +} + +/* + * find Tag in tag list + */ +static USHORT hb_cdxFindTag( CDXAREAP pArea, PHB_ITEM pItem ) +{ + USHORT uiTag = 0; + + if ( pItem ) + { + if ( HB_IS_NUMBER( pItem ) ) + { + uiTag = hb_itemGetNI( pItem ); + if ( ! hb_cdxGetTagByNumber(pArea, uiTag ) ) + uiTag = 0; + } + else if ( HB_IS_STRING( pItem ) ) + { + LPCDXTAG pTag; + LPCDXINDEX pIndex; + char szName[ CDX_MAXTAGNAMELEN + 1 ]; + + hb_strncpyUpperTrim( szName, hb_itemGetCPtr( pItem ), + HB_MIN(hb_itemGetCLen( pItem ), CDX_MAXTAGNAMELEN) ); + pIndex = pArea->lpIndexes; + pTag = NULL; + uiTag = 0; + while ( pIndex && !pTag) + { + pTag = pIndex->TagList; + while ( pTag ) + { + uiTag++; + if ( !hb_stricmp( pTag->szName, szName ) ) + break; + pTag = pTag->pNext; + } + pIndex = pIndex->pNext; + } + if ( !pTag ) + uiTag = 0; + } + } + + return uiTag; +} + +/* + * get current active Tag + */ +static LPCDXTAG hb_cdxGetActiveTag( CDXAREAP pArea ) +{ + LPCDXTAG pTag; + + if ( !pArea->uiTag ) + return NULL; + pTag = hb_cdxGetTagByNumber( pArea, pArea->uiTag ); + if ( !pTag ) + pArea->uiTag = 0; + return pTag; +} + +/* + * go to Eof and update BOF and EOF flags. + */ +static ERRCODE hb_cdxGoEof( CDXAREAP pArea ) +{ + ERRCODE retvalue; + LPCDXTAG pTag; + + HB_TRACE(HB_TR_DEBUG, ("cdxGoEof(%p)", pArea)); + + pTag = hb_cdxGetActiveTag( pArea ); + retvalue = SELF_GOTO( ( AREAP ) pArea, 0 ); + if ( pArea->ulRecCount ) + { + pArea->fBof = FALSE; + if ( pTag ) + pTag->TagBOF = FALSE; + } + if ( pTag ) + { + pTag->TagEOF = TRUE; + pTag->fRePos = FALSE; + pTag->CurKey->rec = 0; + } + return retvalue; +} + +/* + * refresh CurKey value and set proper path from RootPage to LeafPage + * fUniq is used for forward skipunique + */ +static BOOL hb_cdxCurKeyRefresh( CDXAREAP pArea, LPCDXTAG pTag, BOOL fUniq ) +{ + if ( pArea->ulRecNo == 0 ) + { + pTag->TagEOF = TRUE; + pTag->fRePos = FALSE; + pTag->CurKey->rec = 0; + } + else if ( pTag->fRePos || pTag->CurKey->rec != pArea->ulRecNo ) + { + if ( pTag->CurKey->rec == pArea->ulRecNo ) + hb_cdxTagKeyFind( pTag, pTag->CurKey ); + if ( pTag->CurKey->rec != pArea->ulRecNo ) + { + LPCDXKEY pKey = hb_cdxKeyEval( NULL, pTag, TRUE ); + hb_cdxTagKeyFind( pTag, pKey ); + if ( fUniq ) + { + memcpy( pTag->CurKey->val, pKey->val, pKey->len ); + } + hb_cdxKeyFree( pKey ); + } + } + return ( pTag->CurKey->rec == pArea->ulRecNo ); +} + +/* + * return number of keys in order + */ +ERRCODE hb_cdxSkipUnique( CDXAREAP pArea, LPCDXTAG pTag, BOOL fForward ) +{ + ERRCODE retval; + + HB_TRACE(HB_TR_DEBUG, ("hb_cdxSkipUnique(%p, %ld)", pArea, iDir)); + + if ( FAST_GOCOLD( ( AREAP ) pArea ) == FAILURE ) + return FAILURE; + + if ( ! pTag ) + return SUPER_SKIPRAW( ( AREAP ) pArea, fForward ? 1 : -1 ); + + hb_cdxIndexLockRead( pTag->pIndex ); + if ( !pArea->fEof ) + { + if ( ! hb_cdxCurKeyRefresh( pArea, pTag, fForward ) ) + { + if ( fForward ) + { + if ( pTag->TagEOF ) + pArea->fEof = TRUE; + } + else if ( pTag->TagEOF ) + pArea->fBof = TRUE; + } + } + if ( fForward ) + { + if ( !pArea->fEof ) + { + hb_cdxTagKeyRead( pTag, NXTU_RECORD ); + if ( !pTag->TagEOF ) + { + if ( !hb_cdxTopScope( pTag ) ) + hb_cdxTagKeyFind( pTag, pTag->topScopeKey ); + else if ( !hb_cdxBottomScope( pTag ) ) + pTag->TagEOF = TRUE; + } + } + if ( pArea->fEof || pTag->TagEOF ) + retval = hb_cdxGoEof( pArea ); + else + retval = SELF_GOTO( ( AREAP ) pArea, pTag->CurKey->rec ); + } + else + { + if ( pArea->fEof ) + { + SELF_GOBOTTOM( ( AREAP ) pArea ); } else { - pIndex->NextAvail = -1; - pIndex->ulVersion = ulVersion; - hb_cdxPagePoolFree( pIndex, 0 ); - pTag = pIndex->TagList; - while ( pTag ) { - if( pTag->RootPage != NULL ) + pTag->TagBOF = pArea->fBof; + if ( !pTag->TagBOF ) + { + hb_cdxTagKeyRead( pTag, PRVU_RECORD ); + if ( !pTag->TagBOF ) { - /* - if ( !pTag->HotKey) { - hb_errInternal( 9110, "hb_cdxIndexCheckVersion: ulVersion changed and !HotKey.", "", "" ); + if ( !hb_cdxTopScope( pTag ) || + !hb_cdxBottomScope( pTag ) ) + pTag->TagBOF = TRUE; + } + } + } + if ( pTag->TagBOF ) + { + retval = SELF_GOTOP( ( AREAP ) pArea ); + pArea->fBof = pTag->TagBOF = TRUE; + } + else + { + retval = SELF_GOTO( ( AREAP ) pArea, pTag->CurKey->rec ); + } + } + hb_cdxIndexUnLockRead( pTag->pIndex ); + return SUCCESS; +} + + +/* + * return number of keys in order + */ +static long hb_cdxDBOIKeyCount( CDXAREAP pArea, LPCDXTAG pTag, BOOL fFilters ) +{ + LPCDXKEY pCurKey; + LPCDXPAGE pPage; + ULONG lKeyCount = 0; + + pTag = hb_cdxGetActiveTag( pArea ); + + if ( fFilters && ! pArea->dbfi.itmCobExpr ) + fFilters = FALSE; + + if ( fFilters ) + { + PHB_ITEM pRecNo; + ULONG ulRec; + USHORT uiTag; + LPDBRELINFO lpdbRelations; + + uiTag = pArea->uiTag; + pArea->uiTag = hb_cdxGetTagNumber( pArea, pTag ); + /* remove relations when skiping: it's faster and resolve problem + * when child can repos on skip */ + lpdbRelations = pArea->lpdbRelations; + pArea->lpdbRelations = NULL; + + pRecNo = hb_itemPutNL( NULL, 0 ); + SELF_RECNO( ( AREAP ) pArea, pRecNo ); + ulRec = hb_itemGetNL( pRecNo ); + hb_itemRelease( pRecNo ); + + SELF_GOTOP( ( AREAP ) pArea ); + while ( !( ( AREAP ) pArea )->fEof ) + { + lKeyCount++; + SELF_SKIP( ( AREAP ) pArea, 1 ); + } + SELF_GOTO( ( AREAP ) pArea, ulRec ); + /* restore relations and current order */ + pArea->lpdbRelations = lpdbRelations; + pArea->uiTag = uiTag; + } + else if ( pTag ) + { + hb_cdxIndexLockRead( pTag->pIndex ); + pCurKey = hb_cdxKeyCopy( NULL, pTag->CurKey ); + + if ( pTag->topScope || pTag->bottomScope || pTag->UsrUnique ) + { + if ( pTag->topScope ) + hb_cdxTagKeyFind( pTag, pTag->topScopeKey ); + else + hb_cdxTagKeyRead( pTag, TOP_RECORD ); + while ( !pTag->TagEOF && hb_cdxBottomScope( pTag ) ) + { + lKeyCount++; + hb_cdxTagKeyRead( pTag, NEXT_RECORD ); + } + } + else + { + hb_cdxTagKeyRead( pTag, TOP_RECORD ); + pPage = pTag->RootPage; + while ( pPage->Child ) + pPage = pPage->Child; + lKeyCount = pPage->iKeys; + if ( pPage->Right != CDX_DUMMYNODE ) + { + ULONG ulPage = pPage->Right; + pPage = hb_cdxPageNew( pTag, NULL, CDX_DUMMYNODE ); + pPage->Page = ulPage; + while ( pPage->Page != CDX_DUMMYNODE ) + { + hb_cdxPageLoad( pPage ); + lKeyCount += pPage->iKeys; + pPage->Page = pPage->Right; + } + hb_cdxPageFree( pPage, TRUE ); + } + } + pTag->fRePos = TRUE; + hb_cdxKeyCopy( pTag->CurKey, pCurKey ); + hb_cdxKeyFree( pCurKey ); + hb_cdxIndexUnLockRead( pTag->pIndex ); + } + else /* no filter, no order */ + { + SELF_RECCOUNT( ( AREAP ) pArea, &lKeyCount ); + } + return lKeyCount; +} + +/* + * return logical key position in order + */ +static long hb_cdxDBOIKeyNo( CDXAREAP pArea, LPCDXTAG pTag, BOOL fFilters ) +{ + LPCDXKEY pCurKey; + LPCDXPAGE pPage; + ULONG lKeyNo = 0; + + pTag = hb_cdxGetActiveTag( pArea ); + + if ( fFilters && ! pArea->dbfi.itmCobExpr ) + fFilters = 0; + + if ( pArea->fEof ) + lKeyNo = 0; + else if ( pTag && ( pTag->CurKey->rec != pArea->ulRecNo ) ) + /* TODO: fix it */ + lKeyNo = 0; + else if ( fFilters ) + { + PHB_ITEM pRecNo; + ULONG ulRec; + USHORT uiTag; + LPDBRELINFO lpdbRelations; + + uiTag = pArea->uiTag; + pArea->uiTag = hb_cdxGetTagNumber( pArea, pTag ); + /* remove relations when skiping: it's faster and resolve problem + * when child can repos on skip */ + lpdbRelations = pArea->lpdbRelations; + pArea->lpdbRelations = NULL; + + pRecNo = hb_itemPutNL( NULL, 0 ); + SELF_RECNO( ( AREAP ) pArea, pRecNo ); + ulRec = hb_itemGetNL( pRecNo ); + hb_itemRelease( pRecNo ); + do + { + lKeyNo++; + SELF_SKIP( ( AREAP ) pArea, -1 ); + } while ( !( ( AREAP ) pArea )->fBof ); + SELF_GOTO( ( AREAP ) pArea, ulRec ); + /* restore relations and current order */ + pArea->lpdbRelations = lpdbRelations; + pArea->uiTag = uiTag; + } + else if ( pTag ) + { + hb_cdxIndexLockRead( pTag->pIndex ); + if ( hb_cdxCurKeyRefresh( pArea, pTag, FALSE ) ) + { + pCurKey = hb_cdxKeyCopy( NULL, pTag->CurKey ); + if ( pTag->topScope || pTag->bottomScope || pTag->UsrUnique ) + { + if ( hb_cdxBottomScope( pTag ) ) + { + while ( !pTag->TagBOF && !pTag->TagEOF && hb_cdxTopScope( pTag ) ) + { + lKeyNo++; + hb_cdxTagKeyRead( pTag, PREV_RECORD ); } - hb_cdxTagTagOpen( pTag, 0 ); - hb_cdxTagKeyFind( pTag, pTag->HotKey ); - */ - if ( pTag->HotKey ) { - hb_cdxTagTagOpen( pTag, 0 ); - hb_cdxTagKeyFind( pTag, pTag->HotKey ); + } + } + else + { + if ( !pTag->TagBOF && !pTag->TagEOF ) + { + pPage = pTag->RootPage; + while ( pPage->Child ) + pPage = pPage->Child; + if ( pTag->UsrAscend ) + { + lKeyNo = pPage->iCurKey + 1; + if ( pPage->Left != CDX_DUMMYNODE ) + { + ULONG ulPage = pPage->Right; + pPage = hb_cdxPageNew( pTag, NULL, CDX_DUMMYNODE ); + pPage->Page = ulPage; + while ( pPage->Page != CDX_DUMMYNODE ) + { + hb_cdxPageLoad( pPage ); + lKeyNo += pPage->iKeys; + pPage->Page = pPage->Left; + } + hb_cdxPageFree( pPage, TRUE ); + } } else { - SELF_GOTO( ( AREAP ) ( pIndex->pArea ), pIndex->pArea->ulRecNo ); + lKeyNo = pPage->iKeys - pPage->iCurKey; + if ( pPage->Right != CDX_DUMMYNODE ) + { + ULONG ulPage = pPage->Right; + pPage = hb_cdxPageNew( pTag, NULL, CDX_DUMMYNODE ); + pPage->Page = ulPage; + while ( pPage->Page != CDX_DUMMYNODE ) + { + hb_cdxPageLoad( pPage ); + lKeyNo += pPage->iKeys; + pPage->Page = pPage->Right; + } + hb_cdxPageFree( pPage, TRUE ); + } } } + } + pTag->fRePos = TRUE; + hb_cdxKeyCopy( pTag->CurKey, pCurKey ); + hb_cdxKeyFree( pCurKey ); + } + hb_cdxIndexUnLockRead( pTag->pIndex ); + } + else + { + PHB_ITEM pRecNo; + pRecNo = hb_itemPutNL( NULL, 0 ); + SELF_RECNO( ( AREAP ) pArea, pRecNo ); + lKeyNo = hb_itemGetNL( pRecNo ); + hb_itemRelease( pRecNo ); + } + return lKeyNo; +} + +/* + * DBOI_KEYGOTO goto specific logical record in the index file + */ +static long hb_cdxDBOIKeyGoto( CDXAREAP pArea, LPCDXTAG pTag, BOOL fFilters ) +{ + /* TODO: DBOI_KEYGOTO goto specific logical record in the index file */ + HB_SYMBOL_UNUSED( pArea ); + HB_SYMBOL_UNUSED( pTag ); + HB_SYMBOL_UNUSED( fFilters ); + + return 0; +} + + +/* + * -- DBFCDX METHODS -- + */ + +/* ( DBENTRYP_BP ) hb_cdxBof : NULL */ +/* ( DBENTRYP_BP ) hb_cdxEof : NULL */ +/* ( DBENTRYP_BP ) hb_cdxFound : NULL */ + +/* ( DBENTRYP_V ) hb_cdxGoBottom */ +ERRCODE hb_cdxGoBottom( CDXAREAP pArea ) +{ + LPCDXTAG pTag; + ERRCODE retval; + + HB_TRACE(HB_TR_DEBUG, ("cdxGoBottom(%p)", pArea)); + + if ( FAST_GOCOLD( ( AREAP ) pArea ) == FAILURE ) + return FAILURE; + + pTag = hb_cdxGetActiveTag( pArea ); + if ( ! pTag ) + return SUPER_GOBOTTOM( ( AREAP ) pArea ); + + hb_cdxIndexLockRead( pTag->pIndex ); + if ( pTag->bottomScope ) + hb_cdxTagKeyFind( pTag, pTag->bottomScopeKey ); + else + hb_cdxTagKeyRead( pTag, BTTM_RECORD ); + if ( pTag->CurKey->rec != 0 && ! hb_cdxTopScope( pTag ) ) + pTag->CurKey->rec = 0; + retval = SELF_GOTO( ( AREAP ) pArea, pTag->CurKey->rec ); + if ( retval != FAILURE && !pArea->fEof ) + retval = SELF_SKIPFILTER( ( AREAP ) pArea, -1 ); + hb_cdxIndexUnLockRead( pTag->pIndex ); + return retval; +} + +/* ( DBENTRYP_UL ) hb_cdxGoTo : NULL */ +/* ( DBENTRYP_I ) hb_cdxGoToId : NULL */ + +/* ( DBENTRYP_V ) hb_cdxGoTop */ +ERRCODE hb_cdxGoTop( CDXAREAP pArea ) +{ + LPCDXTAG pTag; + ERRCODE retval; + + HB_TRACE(HB_TR_DEBUG, ("cdxGoTop(%p)", pArea)); + + if ( FAST_GOCOLD( ( AREAP ) pArea ) == FAILURE ) + return FAILURE; + + pTag = hb_cdxGetActiveTag( pArea ); + if ( ! pTag ) + return SUPER_GOTOP( ( AREAP ) pArea ); + + hb_cdxIndexLockRead( pTag->pIndex ); + if ( pTag->topScope ) + hb_cdxTagKeyFind( pTag, pTag->topScopeKey ); + else + hb_cdxTagKeyRead( pTag, TOP_RECORD ); + if ( pTag->CurKey->rec != 0 && ! hb_cdxBottomScope( pTag ) ) + pTag->CurKey->rec = 0; + retval = SELF_GOTO( ( AREAP ) pArea, pTag->CurKey->rec ); + if ( retval != FAILURE && !pArea->fEof ) + retval = SELF_SKIPFILTER( ( AREAP ) pArea, 1 ); + hb_cdxIndexUnLockRead( pTag->pIndex ); + return retval; +} + +/* ( DBENTRYP_BIB ) hb_cdxSeek */ +ERRCODE hb_cdxSeek( CDXAREAP pArea, BOOL fSoftSeek, PHB_ITEM pKeyItm, BOOL fFindLast ) +{ + LPCDXTAG pTag + + HB_TRACE(HB_TR_DEBUG, ("cdxSeek(%p, %d, %p, %d)", pArea, fSoftSeek, pKeyItm, fFindLast)); + + if ( FAST_GOCOLD( ( AREAP ) pArea ) == FAILURE ) + return FAILURE; + + pTag = hb_cdxGetActiveTag( pArea ); + + if ( ! pTag ) + { + hb_cdxErrorRT( pArea, EG_NOORDER, 1020, NULL, EF_CANDEFAULT ); + return FAILURE; + } + else + { + LPCDXKEY pKey; + ERRCODE retval = SUCCESS; + BOOL fEOF = FALSE; + ULONG ulRec; + + if ( !pTag->UsrAscend ) + fFindLast = !fFindLast; + + /* TODO: runtime error if valtype(pKeyItm) != pTag->Type */ + pKey = hb_cdxKeyPutItem( NULL, pKeyItm, fFindLast ? CDX_MAX_REC_NUM : CDX_IGNORE_REC_NUM, pTag, TRUE ); + + hb_cdxIndexLockRead( pTag->pIndex ); + ulRec = hb_cdxTagKeyFind( pTag, pKey ); + if ( ( ulRec == 0 && ! fSoftSeek ) || pTag->TagEOF ) + fEOF = TRUE; + else if ( fSoftSeek ) + { + if ( pTag->UsrAscend ) + { + if ( ! hb_cdxBottomScope( pTag ) ) + fEOF = TRUE; + else if ( ! hb_cdxTopScope( pTag ) ) + hb_cdxTagKeyFind( pTag, pTag->topScopeKey ); + } + else + { + if ( ! hb_cdxTopScope( pTag ) ) + fEOF = TRUE; + else if ( ! hb_cdxBottomScope( pTag ) ) + hb_cdxTagKeyFind( pTag, pTag->bottomScopeKey ); + } + if ( pTag->CurKey->rec == 0 ) + fEOF = TRUE; + } + hb_cdxIndexUnLockRead( pTag->pIndex ); + if ( !fEOF ) + { + retval = SELF_GOTO( ( AREAP ) pArea, pTag->CurKey->rec ); + if ( retval != FAILURE && !pArea->fEof ) + { + retval = SELF_SKIPFILTER( ( AREAP ) pArea, fFindLast ? -1 : 1 ); + if ( retval != FAILURE && ulRec && ! pArea->fEof ) + { + pArea->fFound = ( ulRec == pArea->ulRecNo || + hb_cdxValCompare( pTag, pKey->val, pKey->len, + pTag->CurKey->val, pTag->CurKey->len, FALSE ) == 0 ); + if ( ! pArea->fFound && ! fSoftSeek ) + fEOF = TRUE; + } + } + } + if ( retval != FAILURE && ! pArea->fEof && + ( fEOF || ! hb_cdxTopScope( pTag ) || + ! hb_cdxBottomScope( pTag ) ) ) + { + retval = hb_cdxGoEof( pArea ); + } + hb_cdxKeyFree( pKey ); + return retval; + } +} + +/* ( DBENTRYP_L ) hb_cdxSkip : NULL */ +/* ( DBENTRYP_L ) hb_cdxSkipFilter : NULL */ + +/* ( DBENTRYP_L ) hb_cdxSkipRaw */ +ERRCODE hb_cdxSkipRaw( CDXAREAP pArea, LONG lToSkip ) +{ + LPCDXTAG pTag; + ERRCODE retval; + + HB_TRACE(HB_TR_DEBUG, ("cdxSkipRaw(%p, %ld)", pArea, lToSkip)); + + if ( FAST_GOCOLD( ( AREAP ) pArea ) == FAILURE ) + return FAILURE; + + pTag = hb_cdxGetActiveTag( pArea ); + + if ( ! pTag || lToSkip == 0 ) + return SUPER_SKIPRAW( ( AREAP ) pArea, lToSkip ); + + hb_cdxIndexLockRead( pTag->pIndex ); + if ( !pArea->fEof ) + { + if ( ! hb_cdxCurKeyRefresh( pArea, pTag, FALSE ) ) + { + if ( lToSkip > 0 ) + { + if ( pTag->TagEOF ) + pArea->fEof = TRUE; + else + lToSkip--; + } + else if ( pTag->TagEOF ) + pArea->fBof = TRUE; + } + } + if ( lToSkip >= 0 ) + { + if ( !pArea->fEof ) + { + while ( !pTag->TagEOF && lToSkip-- > 0 ) + { + hb_cdxTagKeyRead( pTag, NEXT_RECORD ); + if ( !pTag->TagEOF ) + { + if ( !hb_cdxTopScope( pTag ) ) + hb_cdxTagKeyFind( pTag, pTag->topScopeKey ); + else if ( !hb_cdxBottomScope( pTag ) ) + pTag->TagEOF = TRUE; + } + } + } + if ( pArea->fEof || pTag->TagEOF ) + retval = hb_cdxGoEof( pArea ); + else + retval = SELF_GOTO( ( AREAP ) pArea, pTag->CurKey->rec ); + } + else /* if ( lToSkip < 0 ) */ + { + if ( pArea->fEof ) + { + SELF_GOBOTTOM( ( AREAP ) pArea ); + lToSkip++; + } + pTag->TagBOF = pArea->fBof; + while ( !pTag->TagBOF && lToSkip++ < 0 ) + { + hb_cdxTagKeyRead( pTag, PREV_RECORD ); + if ( !pTag->TagBOF ) + { + if ( !hb_cdxTopScope( pTag ) || + !hb_cdxBottomScope( pTag ) ) + { + pTag->TagBOF = TRUE; + } + } + } + + if ( pTag->TagBOF ) + { + retval = SELF_GOTOP( ( AREAP ) pArea ); + pArea->fBof = pTag->TagBOF = TRUE; + } + else + { + retval = SELF_GOTO( ( AREAP ) pArea, pTag->CurKey->rec ); + } + } + hb_cdxIndexUnLockRead( pTag->pIndex ); + return SUCCESS; +} + +/* ( DBENTRYP_VF ) hb_cdxAddField : NULL */ +/* ( DBENTRYP_B ) hb_cdxAppend : NULL */ +/* ( DBENTRYP_I ) hb_cdxCreateFields : NULL */ +/* ( DBENTRYP_V ) hb_cdxDeleteRec : NULL */ +/* ( DBENTRYP_BP ) hb_cdxDeleted : NULL */ +/* ( DBENTRYP_SP ) hb_cdxFieldCount : NULL */ +/* ( DBENTRYP_VF ) hb_cdxFieldDisplay : NULL */ +/* ( DBENTRYP_SSI ) hb_cdxFieldInfo : NULL */ +/* ( DBENTRYP_SVP ) hb_cdxFieldName : NULL */ +/* ( DBENTRYP_V ) hb_cdxFlush : NULL */ +/* ( DBENTRYP_PP ) hb_cdxGetRec : NULL */ +/* ( DBENTRYP_SI ) hb_cdxGetValue : NULL */ +/* ( DBENTRYP_SVL ) hb_cdxGetVarLen : NULL */ + +/* ( DBENTRYP_V ) hb_cdxGoCold */ +/* + * Perform a write of WorkArea memory to the data store. + */ +ERRCODE hb_cdxGoCold( CDXAREAP pArea ) +{ + BOOL fRecordChanged = pArea->fRecordChanged; + BOOL fAppend = pArea->fAppend; + + HB_TRACE(HB_TR_DEBUG, ("hb_cdxGoCold(%p)", pArea)); + + if ( SUPER_GOCOLD( ( AREAP ) pArea ) == FAILURE ) + return FAILURE; + + if ( ( fRecordChanged || pArea->fCdxAppend ) && pArea->lpIndexes ) + { + LPCDXTAG pTag = pArea->lpIndexes->TagList; + USHORT uiTag = 1; + LPCDXKEY pKey = NULL; + BOOL fAdd, fDel, fLck = FALSE; + + if ( pArea->fShared ) + { + if ( fAppend ) + { + if ( pArea->fCdxAppend ) + hb_cdxErrInternal( "hb_cdxGoCold: multiple appending without GOCOLD." ); + pArea->fCdxAppend = TRUE; + return SUCCESS; + } + else + { + fAppend = pArea->fCdxAppend; + pArea->fCdxAppend = FALSE; + } + } + /* TODO: + * There is possible race condition here but not very dangerous. + * To avoid it we should Lock all index file before SUPER_GOCOLD + * but it make other problem if two station open the database index + * file in a differ order then they can block each other. + * Without changes in locking scheme we can do only one thing which + * is enough if there is only one index file: lock first index only + * before SUPER_GOCOLD + * Druzus, 05 Oct 2003 10:27:52 CEST + */ + + while ( pTag ) + { + if ( !pTag->Custom ) + { + pKey = hb_cdxKeyEval( pKey, pTag, TRUE ); + /* test for expresion, working but not tested */ + if ( pTag->pForItem != NULL ) + fAdd = hb_cdxEvalCond ( pArea, pTag->pForItem, TRUE ); + else + fAdd = TRUE; + + if ( fAppend ) + fDel = FALSE; + else + { + if ( hb_cdxValCompare( pTag, pKey->val, pKey->len, + pTag->HotKey->val, pTag->HotKey->len, TRUE ) == 0 ) + { + fAdd = !pTag->HotFor; + fDel = FALSE; + } + else if ( !pTag->HotFor ) + fDel = FALSE; + else + { + if ( !fLck ) + { + hb_cdxIndexLockWrite( pTag->pIndex ); + fLck = TRUE; + } + fDel = hb_cdxTagKeyFind( pTag, pTag->HotKey ) > 0; + } + } + if ( fDel || fAdd ) + { + if ( !fLck ) + { + hb_cdxIndexLockWrite( pTag->pIndex ); + fLck = TRUE; + } + if ( fDel ) + hb_cdxPageKeyDelete( pTag->RootPage ); + if ( fAdd ) + hb_cdxTagKeyAdd( pTag, pKey ); + /* TODO: I have to think about it yet. In some cases it could + * decrease performance so I disbale it + */ +#if 0 + if ( uiTag != pArea->uiTag ) + hb_cdxTagClose( pTag ); +#endif + } +/* + if ( pTag->HotKey ) + { + hb_cdxKeyFree( pTag->HotKey ); + pTag->HotKey = NULL; + } +*/ + } + if ( pTag->pNext ) pTag = pTag->pNext; + else + { + if ( fLck ) + { + hb_cdxIndexUnLockWrite( pTag->pIndex ); + fLck = FALSE; + } + if ( pTag->pIndex->pNext ) + pTag = pTag->pIndex->pNext->TagList; + else + pTag = NULL; + } + ++uiTag; + } + if ( pKey ) + hb_cdxKeyFree( pKey ); + } + + return SUCCESS; +} + +/* ( DBENTRYP_V ) hb_cdxGoHot */ +/* + * Mark the WorkArea data buffer as hot. + */ +ERRCODE hb_cdxGoHot( CDXAREAP pArea ) +{ + + HB_TRACE(HB_TR_DEBUG, ("hb_cdxGoHot(%p)", pArea)); + + if ( pArea->fRecordChanged ) + hb_cdxErrInternal( "hb_cdxGoHot: multiple marking buffer as hot." ); + + if ( SUPER_GOHOT( ( AREAP ) pArea ) == FAILURE ) + return FAILURE; + + if ( pArea->lpIndexes && !pArea->fCdxAppend ) + { + LPCDXTAG pTag = pArea->lpIndexes->TagList; + while ( pTag ) + { + if ( !pTag->Custom ) + { + pTag->HotKey = hb_cdxKeyEval( pTag->HotKey, pTag, TRUE ); + pTag->HotFor = pTag->pForItem == NULL || hb_cdxEvalCond ( pArea, pTag->pForItem, TRUE ); + } + + if ( pTag->pNext ) + pTag = pTag->pNext; + else + { + if ( pTag->pIndex->pNext ) + pTag = pTag->pIndex->pNext->TagList; + else + pTag = NULL; + } + } + } + return SUCCESS; +} + +/* ( DBENTRYP_P ) hb_cdxPutRec : NULL */ +/* ( DBENTRYP_SI ) hb_cdxPutValue : NULL */ +/* ( DBENTRYP_V ) hb_cdxRecall : NULL */ +/* ( DBENTRYP_ULP ) hb_cdxRecCount : NULL */ +/* ( DBENTRYP_ISI ) hb_cdxRecInfo : NULL */ +/* ( DBENTRYP_I ) hb_cdxRecNo : NULL */ +/* ( DBENTRYP_S ) hb_cdxSetFieldExtent : NULL */ +/* ( DBENTRYP_P ) hb_cdxAlias : NULL */ + +/* ( DBENTRYP_V ) hb_cdxClose */ +/* + * Close the table in the WorkArea. + */ +ERRCODE hb_cdxClose( CDXAREAP pArea ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_cdxClose(%p)", pArea)); + + if ( FAST_GOCOLD( ( AREAP ) pArea ) == FAILURE ) + return FAILURE; + + hb_cdxOrdListClear( pArea, TRUE, NULL ); + +#ifdef HB_CDX_DBGTIME + printf( "\r\ncdxTimeIntBld=%f, cdxTimeExtBld=%f, cdxTimeBld=%f\r\n" + "cdxTimeGetKey=%f, cdxTimeFreeKey=%f\r\n" + "cdxTimeExtBlc=%f, cdxTimeIntBlc=%f\r\n" + "cdxTimeTotal=%f\r\n", + (double) cdxTimeIntBld / 1000000, (double) cdxTimeExtBld / 1000000, + (double) ( cdxTimeIntBld + cdxTimeExtBld ) / 1000000, + (double) cdxTimeGetKey / 1000000, (double) cdxTimeFreeKey / 1000000, + (double) cdxTimeIntBlc / 1000000, (double) cdxTimeExtBlc / 1000000, + (double) ( cdxTimeIntBld + cdxTimeExtBld + + cdxTimeGetKey + cdxTimeFreeKey + + cdxTimeExtBlc + cdxTimeIntBlc ) / 1000000 ); + fflush(stdout); + cdxTimeIntBld = cdxTimeExtBld = 0; +#endif + + return SUPER_CLOSE( ( AREAP ) pArea ); +} + +/* ( DBENTRYP_VP ) hb_cdxCreate : NULL */ +/* ( DBENTRYP_SI ) hb_cdxInfo : NULL */ +/* ( DBENTRYP_V ) hb_cdxNewArea : NULL */ + +/* ( DBENTRYP_VP ) hb_cdxOpen */ +/* + * 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)); + + if ( SUPER_OPEN( ( AREAP ) pArea, pOpenInfo ) == FAILURE ) + { + return FAILURE; + } + + /* If SET_AUTOPEN open index */ + if ( pArea->fHasTags && hb_set.HB_SET_AUTOPEN ) + { + char * szFileName; + BYTE szSpFile[ _POSIX_PATH_MAX + 3 + 10 ]; + PHB_FNAME pFileName; + DBORDERINFO pOrderInfo; + + pFileName = hb_fsFNameSplit( pArea->szDataFileName ); + szFileName = ( char * ) hb_xgrab( _POSIX_PATH_MAX + 3 ); + szFileName[ 0 ] = '\0'; + if ( pFileName->szPath ) + strcpy( szFileName, pFileName->szPath ); + strncat( szFileName, pFileName->szName, _POSIX_PATH_MAX - strlen( szFileName ) ); + pOrderInfo.itmResult = hb_itemPutC( NULL, "" ); + SELF_ORDINFO( ( AREAP ) pArea, DBOI_BAGEXT, &pOrderInfo ); + strncat( szFileName, pOrderInfo.itmResult->item.asString.value, _POSIX_PATH_MAX - strlen( szFileName ) ); + hb_itemRelease( pOrderInfo.itmResult ); + hb_xfree( pFileName ); + + if ( hb_spFile( ( BYTE * ) szFileName, szSpFile ) ) + { + pOrderInfo.itmResult = hb_itemPutNI( NULL, 0 ); + pOrderInfo.atomBagName = hb_itemPutC( NULL, szSpFile ); + pOrderInfo.itmOrder = NULL; + SELF_ORDLSTADD( ( AREAP ) pArea, &pOrderInfo ); + pOrderInfo.itmOrder = hb_itemPutNI( NULL, hb_set.HB_SET_AUTORDER ); + SELF_ORDLSTFOCUS( ( AREAP ) pArea, &pOrderInfo ); + hb_itemRelease( pOrderInfo.atomBagName ); + hb_itemRelease( pOrderInfo.itmOrder ); + hb_itemRelease( pOrderInfo.itmResult ); + + SELF_GOTOP( ( AREAP ) pArea ); + } + hb_xfree( szFileName ); + } + + return SUCCESS; +} + +/* ( DBENTRYP_V ) hb_cdxRelease : NULL */ + +/* ( DBENTRYP_SP ) hb_cdxStructSize */ +/* + * Retrieve the size of the WorkArea structure. + */ +ERRCODE hb_cdxStructSize( CDXAREAP pArea, USHORT * uiSize ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_cdxStrucSize(%p, %p)", pArea, uiSize)); + HB_SYMBOL_UNUSED( pArea ); + + * uiSize = sizeof( CDXAREA ); + return SUCCESS; +} + +/* ( DBENTRYP_P ) hb_cdxSysName */ +/* + * Obtain the name of replaceable database driver (RDD) subsystem. + */ +ERRCODE hb_cdxSysName( CDXAREAP pArea, BYTE * pBuffer ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_cdxSysName(%p, %p)", pArea, pBuffer)); + HB_SYMBOL_UNUSED( pArea ); + + strncpy( ( char * ) pBuffer, "DBFCDX", 7 /* HARBOUR_MAX_RDD_DRIVERNAME_LENGTH */ ); + return SUCCESS; +} + +/* ( DBENTRYP_VEI ) hb_cdxEval : NULL */ + +/* ( DBENTRYP_V ) hb_cdxPack */ +extern ERRCODE hb_cdxPack( CDXAREAP pArea ) +{ + HB_TRACE(HB_TR_DEBUG, ("nb_cdxPack(%p)", pArea )); + + if ( FAST_GOCOLD( ( AREAP ) pArea ) == FAILURE ) + return FAILURE; + + if ( SUPER_PACK( ( AREAP ) pArea ) == SUCCESS ) + { + return hb_cdxOrderListRebuild( pArea ); + } + else + return FAILURE; +} + +/* ( DBENTRYP_LSP ) hb_cdxPackRec : NULL */ +/* ( DBENTRYP_VS ) hb_cdxSort : NULL */ +/* ( DBENTRYP_VT ) hb_cdxTrans : NULL */ +/* ( DBENTRYP_VT ) hb_cdxTransRec : NULL */ + +/* ( DBENTRYP_V ) hb_cdxZap */ +extern ERRCODE hb_cdxZap ( CDXAREAP pArea ) +{ + HB_TRACE(HB_TR_DEBUG, ("nb_cdxZap(%p)", pArea )); + + if ( FAST_GOCOLD( ( AREAP ) pArea ) == FAILURE ) + return FAILURE; + + hb_cdxOrderListRebuild( pArea ); + if ( SUPER_ZAP( ( AREAP ) pArea ) == SUCCESS ) + { + return hb_cdxOrderListRebuild( pArea ); + } + else + return FAILURE; +} + +/* ( DBENTRYP_VR ) hb_cdxChildEnd : NULL */ +/* ( DBENTRYP_VR ) hb_cdxChildStart : NULL */ +/* ( DBENTRYP_VR ) hb_cdxChildSync : NULL */ +/* ( DBENTRYP_V ) hb_cdxSyncChildren : NULL */ +/* ( DBENTRYP_V ) hb_cdxClearRel : NULL */ +/* ( DBENTRYP_V ) hb_cdxForceRel : NULL */ +/* ( DBENTRYP_SVP ) hb_cdxRelArea : NULL */ +/* ( DBENTRYP_VR ) hb_cdxRelEval : NULL */ +/* ( DBENTRYP_SVP ) hb_cdxRelText : NULL */ +/* ( DBENTRYP_VR ) hb_cdxSetRel : NULL */ + +/* ( DBENTRYP_OI ) hb_cdxOrderListAdd */ +ERRCODE hb_cdxOrderListAdd( CDXAREAP pArea, LPDBORDERINFO pOrderInfo ) +{ + USHORT uiFlags; + FHANDLE hFile; + char * szBaseName, * szFileName, * szFileNameDbfPath = NULL; + BYTE szSpFile[ _POSIX_PATH_MAX + 3 + 10 ]; + LPCDXINDEX pIndex, pIndexTmp; + BOOL bRetry; + + HB_TRACE(HB_TR_DEBUG, ("cdxOrderListAdd(%p, %p)", pArea, pOrderInfo)); + + if ( FAST_GOCOLD( ( AREAP ) pArea ) == FAILURE ) + return FAILURE; + + szFileName = ( char * ) hb_xgrab( _POSIX_PATH_MAX + 3 ); + strcpy( szFileName, hb_itemGetCPtr( pOrderInfo->atomBagName ) ); + szFileName = ( char * ) hb_filecase( szFileName ) ; + + if ( strlen( szFileName ) == 0 ) + { + hb_xfree( szFileName ); + return FAILURE; + } + else + { + PHB_FNAME pFileName = hb_fsFNameSplit( szFileName ); + + if ( !pFileName->szExtension ) + { + DBORDERINFO pExtInfo; + pExtInfo.itmResult = hb_itemPutC( NULL, "" ); + SELF_ORDINFO( ( AREAP ) pArea, DBOI_BAGEXT, &pExtInfo ); + strcat( szFileName, pExtInfo.itmResult->item.asString.value ); + hb_itemRelease( pExtInfo.itmResult ); + } + szBaseName = ( char * ) hb_xgrab( CDX_MAXTAGNAMELEN + 1 ); + hb_strncpyUpper( szBaseName, pFileName->szName, CDX_MAXTAGNAMELEN ); + if ( !pFileName->szPath ) + { + hb_xfree( pFileName ); + pFileName = hb_fsFNameSplit( pArea->szDataFileName ); + if ( pFileName->szPath ) + { + szFileNameDbfPath = ( char * ) hb_xgrab( _POSIX_PATH_MAX + 3 ); + strcpy( szFileNameDbfPath, pFileName->szPath ); + strncat( szFileNameDbfPath, szFileName, + _POSIX_PATH_MAX - strlen( szFileNameDbfPath ) ); + } + } + hb_xfree( pFileName ); + } + + if ( pArea->lpIndexes != NULL) + { + pIndexTmp = pArea->lpIndexes; + while ( pIndexTmp && ( strcmp( szBaseName, pIndexTmp->pCompound->szName ) != 0 ) ) + pIndexTmp = pIndexTmp->pNext; + if ( pIndexTmp ) + { + /* + * index already open, do nothing + * TODO: the full pathname should be compared when APIs are available + * ??? I'm not sure, it breaks upper lewel API if we have + * two Bags with the same name. But we can close the old bag + * and open the new one - 10/05/2003 Druzus + */ + if ( ! pArea->uiTag ) + { + pArea->uiTag = hb_cdxGetTagNumber( pArea, pIndexTmp->TagList ); + SELF_GOTOP( ( AREAP ) pArea ); + } + if ( szFileNameDbfPath != NULL ) + hb_xfree( szFileNameDbfPath ); + hb_xfree( szFileName ); + hb_xfree( szBaseName ); + return FAILURE; + } + } + + uiFlags = ( pArea->fReadonly ? FO_READ : FO_READWRITE ) | + ( pArea->fShared ? FO_DENYNONE : FO_EXCLUSIVE ); + do + { + hFile = FS_ERROR; + if ( szFileNameDbfPath && + hb_spFile( ( BYTE * ) szFileNameDbfPath, szSpFile ) ) + hFile = hb_spOpen( szSpFile, uiFlags ); + else if ( hb_spFile( ( BYTE * ) szFileName, szSpFile ) ) + hFile = hb_spOpen( szSpFile, uiFlags ); + else + *szSpFile = '\0'; + if ( hFile == FS_ERROR ) + bRetry = ( hb_cdxErrorRT( pArea, EG_OPEN, 1003, *szSpFile ? (char *) szSpFile : szFileName, + EF_CANRETRY | EF_CANDEFAULT ) == E_RETRY ); + else + bRetry = FALSE; + + } while ( bRetry ); + + if ( szFileNameDbfPath != NULL ) + hb_xfree( szFileNameDbfPath ); + hb_xfree( szFileName ); + + if ( hFile == FS_ERROR ) + { + hb_xfree( szBaseName ); + return FAILURE; + } + + pIndex = hb_cdxIndexNew( pArea ); + pIndex->hFile = hFile; + pIndex->szFileName = hb_strdup( szSpFile ); + if ( pArea->lpIndexes == NULL ) + { + pArea->lpIndexes = pIndex; + } + else + { + pIndexTmp = pArea->lpIndexes; + while ( pIndexTmp->pNext ) + pIndexTmp = pIndexTmp->pNext; + pIndexTmp->pNext = pIndex; + } + + /* TODO: check if index file is not corrupted */ + hb_cdxIndexLoad( pIndex, szBaseName ); + hb_xfree( szBaseName ); + + /* dbfcdx specific: If there was no controlling order, set this one. + * This is the behaviour of Clipper's dbfcdx, although + * Clipper doc says a different rule + */ + if ( ! pArea->uiTag ) + { + pArea->uiTag = hb_cdxGetTagNumber( pArea, pIndex->TagList ); + SELF_GOTOP( ( AREAP ) pArea ); + } + return SUCCESS; +} + +/* ( DBENTRYP_V ) hb_cdxOrderListClear */ +/* + * Clear the current order list. + */ +extern ERRCODE hb_cdxOrderListClear( CDXAREAP pArea ) +{ + HB_TRACE(HB_TR_DEBUG, ("cdxOrderListClear(%p)", pArea)); + + if ( FAST_GOCOLD( ( AREAP ) pArea ) == FAILURE ) + return FAILURE; + + hb_cdxOrdListClear( pArea, FALSE, NULL ); + pArea->uiTag = 0; + + return SUCCESS; +} + +/* TODO: in the future, now there is no API call to SELF_ORDLSTDELETE */ +/* ( DBENTRYP_VP ) hb_cdxOrderListDelete : NULL */ + +/* ( DBENTRYP_OI ) hb_cdxOrderListFocus */ +ERRCODE hb_cdxOrderListFocus( CDXAREAP pArea, LPDBORDERINFO pOrderInfo ) +{ + LPCDXTAG pTag; + + HB_TRACE(HB_TR_DEBUG, ("cdxOrderListFocus(%p, %p)", pArea, pOrderInfo)); + + if ( FAST_GOCOLD( ( AREAP ) pArea ) == FAILURE ) + return FAILURE; + + if ( ! pArea->lpIndexes ) + return SUCCESS; + + pTag = hb_cdxGetActiveTag( pArea ); + if ( pTag ) + pOrderInfo->itmResult = hb_itemPutC( pOrderInfo->itmResult, pTag->szName ); + + if ( pOrderInfo->itmOrder ) + pArea->uiTag = hb_cdxFindTag( pArea, pOrderInfo->itmOrder ); + /* TODO: RTerror if not found? */ + + return SUCCESS; +} + +/* ( DBENTRYP_V ) hb_cdxOrderListRebuild */ +static ERRCODE hb_cdxOrderListRebuild( CDXAREAP pArea ) +{ + LPCDXINDEX pIndex, * pIndexPtr; + USHORT uiPrevTag; + + HB_TRACE(HB_TR_DEBUG, ("nb_cdxPack(%p)", pArea )); + + if ( FAST_GOCOLD( ( AREAP ) pArea ) == FAILURE ) + return FAILURE; + + if ( pArea->fShared ) + { + hb_cdxErrorRT( pArea, EG_SHARED, EDBF_SHARED, pArea->szDataFileName, 0 ); + return FAILURE; + } + if ( pArea->fReadonly ) + { + hb_cdxErrorRT( pArea, EG_READONLY, EDBF_READONLY, pArea->szDataFileName, 0 ); + return FAILURE; + } + + if ( ! pArea->lpIndexes ) + return SUCCESS; + + uiPrevTag = pArea->uiTag; + pArea->uiTag = 0; + + pIndex = pArea->lpIndexes; + pArea->lpIndexes = NULL; + pIndexPtr = &pArea->lpIndexes; + while ( pIndex ) + { + (*pIndexPtr) = pIndex; + pIndex = pIndex->pNext; + (*pIndexPtr)->pNext = NULL; + hb_cdxIndexReindex( *pIndexPtr ); + pIndexPtr = &(*pIndexPtr)->pNext; + } + + pArea->uiTag = uiPrevTag; + /* Clear pArea->lpdbOrdCondInfo */ + SELF_ORDSETCOND( ( AREAP ) pArea, NULL ); + + return SELF_GOTOP( ( AREAP ) pArea ); +} + +/* ( DBENTRYP_VOI ) hb_cdxOrderCondition : NULL */ + +/* ( DBENTRYP_VOC ) hb_cdxOrderCreate */ +/* + * create new order + */ +ERRCODE hb_cdxOrderCreate( CDXAREAP pArea, LPDBORDERCREATEINFO pOrderInfo ) +{ + ULONG ulRecNo; + BOOL fNewFile, fOpenedIndex; + FHANDLE hFile; + PHB_ITEM pKeyExp, pForExp, pResult; + HB_MACRO_PTR pExpMacro, pForMacro; + char * szFileName, * szCpndTagName, * szTagName; + BYTE szSpFile[ _POSIX_PATH_MAX + 3 + 10 ]; + PHB_FNAME pFileName; + DBORDERINFO pExtInfo; + LPCDXINDEX pIndex; + LPCDXTAG pTag; + USHORT uiType, uiLen; + BYTE bType; + + pKeyExp = pForExp = NULL; + pExpMacro = pForMacro = NULL; + + HB_TRACE(HB_TR_DEBUG, ("cdxOrderCreate(%p, %p)", pArea, pOrderInfo)); + + if ( FAST_GOCOLD( ( AREAP ) pArea ) == FAILURE ) + return FAILURE; + + /* If we have a codeblock for the expression, use it */ + if ( pOrderInfo->itmCobExpr ) + pKeyExp = hb_itemNew( pOrderInfo->itmCobExpr ); + else /* Otherwise, try compiling the key expression string */ + { + if ( SELF_COMPILE( (AREAP) pArea, ( BYTE * ) pOrderInfo->abExpr->item.asString.value ) == FAILURE ) + return FAILURE; + pKeyExp = pArea->valResult; + pArea->valResult = NULL; + } + + /* Get a blank record before testing expression */ + ulRecNo = pArea->ulRecNo; + SELF_GOTO( ( AREAP ) pArea, 0 ); + if ( hb_itemType( pKeyExp ) == HB_IT_BLOCK ) + { + if ( SELF_EVALBLOCK( ( AREAP ) pArea, pKeyExp ) == FAILURE ) + { + hb_itemRelease( pKeyExp ); + SELF_GOTO( ( AREAP ) pArea, ulRecNo ); + return FAILURE; + } + pResult = pArea->valResult; + pArea->valResult = NULL; + } + else + { + pExpMacro = ( HB_MACRO_PTR ) hb_itemGetPtr( pKeyExp ); + hb_cdxMacroRun( pArea, pExpMacro ); + pResult = hb_itemNew( hb_stackItemFromTop( -1 ) ); + } + uiType = hb_itemType( pResult ); + switch ( uiType ) + { + case HB_IT_INTEGER: + case HB_IT_LONG: +#ifndef HB_LONG_LONG_OFF + case HB_IT_LONGLONG: +#endif + case HB_IT_DOUBLE: + bType = 'N'; + uiLen = 8; + break; + case HB_IT_DATE: + bType = 'D'; + uiLen = 8; + break; + case HB_IT_LOGICAL: + bType = 'L'; + uiLen = 1; + break; + case HB_IT_STRING: + bType = 'C'; + uiLen = HB_CDXMAXKEY( pResult->item.asString.length ); + break; + default: + hb_itemRelease( pKeyExp ); + if ( pExpMacro != NULL ) + hb_macroDelete( pExpMacro ); + SELF_GOTO( ( AREAP ) pArea, ulRecNo ); + /* TODO: !!! runtime error ? */ + return FAILURE; + } + hb_itemRelease( pResult ); + if ( uiLen == 0 ) + { + hb_itemRelease( pKeyExp ); + if ( pExpMacro != NULL ) + hb_macroDelete( pExpMacro ); + SELF_GOTO( ( AREAP ) pArea, ulRecNo ); + hb_cdxErrorRT( pArea, EG_DATAWIDTH, 1026, NULL, 0 ); + return FAILURE; + } + /* Check conditional expression */ + if ( pArea->lpdbOrdCondInfo ) + { + /* If we have a codeblock for the conditional expression, use it */ + if ( pArea->lpdbOrdCondInfo->itmCobFor ) + pForExp = hb_itemNew( pArea->lpdbOrdCondInfo->itmCobFor ); + else /* Otherwise, try compiling the conditional expression string */ + { + if ( pArea->lpdbOrdCondInfo->abFor ) + { + if ( SELF_COMPILE( (AREAP) pArea, pArea->lpdbOrdCondInfo->abFor ) == FAILURE ) + { + hb_itemRelease( pKeyExp ); + if ( pExpMacro != NULL ) + hb_macroDelete( pExpMacro ); + SELF_GOTO( ( AREAP ) pArea, ulRecNo ); + return FAILURE; + } + pForExp = pArea->valResult; + pArea->valResult = NULL; + } + } + } + /* Test conditional expression */ + if ( pForExp ) + { + if ( hb_itemType( pForExp ) == HB_IT_BLOCK ) + { + if ( SELF_EVALBLOCK( ( AREAP ) pArea, pForExp ) == FAILURE ) + { + hb_itemRelease( pKeyExp ); + hb_itemRelease( pForExp ); + if ( pExpMacro != NULL ) + hb_macroDelete( pExpMacro ); + SELF_GOTO( ( AREAP ) pArea, ulRecNo ); + return FAILURE; + } + uiType = hb_itemType( pArea->valResult ); + hb_itemRelease( pArea->valResult ); + pArea->valResult = NULL; + } + else + { + pForMacro = ( HB_MACRO_PTR ) hb_itemGetPtr( pForExp ); + hb_cdxMacroRun( pArea, pForMacro ); + uiType = hb_itemType( hb_stackItemFromTop( -1 ) ); + } + if ( uiType != HB_IT_LOGICAL ) + { + hb_itemRelease( pKeyExp ); + hb_itemRelease( pForExp ); + if ( pExpMacro != NULL ) + hb_macroDelete( pExpMacro ); + if ( pForMacro != NULL ) + hb_macroDelete( pForMacro ); + SELF_GOTO( ( AREAP ) pArea, ulRecNo ); + /* TODO: !!! runtime error ? */ + return FAILURE; + } + } + /* Check file name */ + szFileName = ( char * ) hb_xgrab( _POSIX_PATH_MAX + 3 ); + szFileName[ 0 ] = '\0'; + if ( !pOrderInfo->abBagName || ( strlen( ( char * ) pOrderInfo->abBagName ) == 0 ) ) + { + pFileName = hb_fsFNameSplit( pArea->szDataFileName ); + if ( pFileName->szPath ) + strcat( szFileName, pFileName->szPath ); + strcat( szFileName, pFileName->szName ); + pExtInfo.itmResult = hb_itemPutC( NULL, "" ); + SELF_ORDINFO( ( AREAP ) pArea, DBOI_BAGEXT, &pExtInfo ); + strcat( szFileName, pExtInfo.itmResult->item.asString.value ); + hb_itemRelease( pExtInfo.itmResult ); + } + else + { + strcpy( szFileName, ( char * ) pOrderInfo->abBagName ); + pFileName = hb_fsFNameSplit( szFileName ); + if ( !pFileName->szExtension ) + { + pExtInfo.itmResult = hb_itemPutC( NULL, "" ); + SELF_ORDINFO( ( AREAP ) pArea, DBOI_BAGEXT, &pExtInfo ); + strcat( szFileName, pExtInfo.itmResult->item.asString.value ); + hb_itemRelease( pExtInfo.itmResult ); + } + } + szTagName = ( char * ) hb_xgrab( CDX_MAXTAGNAMELEN + 1 ); + szCpndTagName = ( char * ) hb_xgrab( CDX_MAXTAGNAMELEN + 1 ); + hb_strncpyUpperTrim( szCpndTagName, pFileName->szName, CDX_MAXTAGNAMELEN ); + hb_xfree( pFileName ); + if ( pOrderInfo->atomBagName && ( strlen( ( char * ) pOrderInfo->atomBagName ) > 0 ) ) + hb_strncpyUpperTrim( szTagName, ( char * ) pOrderInfo->atomBagName, CDX_MAXTAGNAMELEN ); + else + strcpy( szTagName, szCpndTagName ); + + if ( !pArea->lpdbOrdCondInfo || + ( pArea->lpdbOrdCondInfo->fAll && !pArea->lpdbOrdCondInfo->fAdditive ) ) + hb_cdxOrdListClear( pArea, FALSE, NULL ); + + pIndex = hb_cdxFindBag( pArea, szFileName ); + fOpenedIndex = ( pIndex != NULL ); + + if ( !fOpenedIndex ) + { + fNewFile = ! hb_spFile( ( BYTE * ) szFileName, szSpFile ); + if ( fNewFile ) + { + /* TODO: no API to take real file name with path */ + hFile = hb_spCreate( ( BYTE * ) szFileName, FC_NORMAL ); + } + else + { + strcpy( szFileName, szSpFile ); + hFile = hb_spOpen( ( BYTE * ) szFileName, + FO_READWRITE | ( pArea->fShared ? FO_DENYNONE : FO_EXCLUSIVE ) ); + } + if ( hFile == FS_ERROR ) + { + hb_xfree( szFileName ); + hb_xfree( szTagName ); + hb_xfree( szCpndTagName ); + hb_itemRelease( pKeyExp ); + if ( pForExp != NULL ) + hb_itemRelease( pForExp ); + if ( pExpMacro != NULL ) + hb_macroDelete( pExpMacro ); + if ( pForMacro != NULL ) + hb_macroDelete( pForMacro ); + SELF_GOTO( ( AREAP ) pArea, ulRecNo ); + /* TODO: !!! runtime error ? */ + return FAILURE; + } + pIndex = hb_cdxIndexNew( pArea ); + pIndex->hFile = hFile; + pIndex->fShared = pArea->fShared; + pIndex->fReadonly = FALSE; + pIndex->szFileName = hb_strdup( szFileName ); + + if ( !fNewFile ) + { + /* TODO: check if index file is not corrupted */ + /* cut corrupted files */ + fNewFile = ( hb_fsSeek( hFile, 0, FS_END ) <= sizeof( CDXTAGHEADER ) ); + hb_fsSeek( hFile, 0, FS_SET ); + if ( fNewFile ) + hb_fsWrite( hFile, NULL, 0 ); + } + + hb_cdxIndexLockWrite( pIndex ); + if ( fNewFile ) + { + hb_cdxIndexDropAvailPage( pIndex ); + pIndex->nextAvail = pIndex->freePage = 0; + pIndex->pCompound = hb_cdxTagNew( pIndex, szCpndTagName, CDX_DUMMYNODE ); + pIndex->pCompound->OptFlags = CDX_TYPE_COMPACT | CDX_TYPE_COMPOUND | CDX_TYPE_STRUCTURE; + hb_cdxTagIndexTagNew( pIndex->pCompound, NULL, NULL, 'C', 10, NULL, NULL, + TRUE, FALSE, FALSE ); + } + else + { + hb_cdxIndexLoad( pIndex, szCpndTagName ); + /* Delete new tag if exist */ + hb_cdxIndexDelTag( pIndex, szTagName ); + } + + /* Update DBF header */ + if ( !pArea->fHasTags ) + { + pFileName = hb_fsFNameSplit( pArea->szDataFileName ); + hb_strncpyUpper( szFileName, pFileName->szName, CDX_MAXTAGNAMELEN ); + hb_xfree( pFileName ); + if ( strcmp( szFileName, szCpndTagName ) == 0 ) + { + pArea->fHasTags = TRUE; + SELF_WRITEDBHEADER( ( AREAP ) pArea ); + } + } + } + else /* if ( fOpenedIndex ) */ + { + hb_cdxIndexLockWrite( pIndex ); + /* Delete new tag if exist */ + hb_cdxIndexDelTag( pIndex, szTagName ); + } + hb_xfree( szFileName ); + + if ( !pArea->lpdbOrdCondInfo || pArea->lpdbOrdCondInfo->fAll ) + pArea->uiTag = 0; + + pTag = 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, + ( pArea->lpdbOrdCondInfo ? pArea->lpdbOrdCondInfo->fCustom : FALSE ) ); + + hb_xfree( szTagName ); + hb_xfree( szCpndTagName ); + if ( pArea->lpdbOrdCondInfo && ( !pArea->lpdbOrdCondInfo->fAll && + !pArea->lpdbOrdCondInfo->fAdditive ) ) + { + hb_cdxOrdListClear( pArea, FALSE, pIndex ); + } + if ( !fOpenedIndex ) + { + if ( pArea->lpIndexes == NULL ) + pArea->lpIndexes = pIndex; + else + { + LPCDXINDEX pIndexTmp = pArea->lpIndexes; + while ( pIndexTmp->pNext ) + pIndexTmp = pIndexTmp->pNext; + pIndexTmp->pNext = pIndex; + } + } + + hb_cdxIndexUnLockWrite( pIndex ); + pArea->uiTag = hb_cdxGetTagNumber( pArea, pTag ); + + /* Clear pArea->lpdbOrdCondInfo */ + SELF_ORDSETCOND( ( AREAP ) pArea, NULL ); + + return SELF_GOTOP( ( AREAP ) pArea ); +} + +/* ( DBENTRYP_OI ) hb_cdxOrderDestroy */ +ERRCODE hb_cdxOrderDestroy( CDXAREAP pArea, LPDBORDERINFO pOrderInfo ) +{ + LPCDXINDEX pIndex, pIndexTmp; + LPCDXTAG pTag; + USHORT uiTag; + char * szFileName; + + HB_TRACE(HB_TR_DEBUG, ("cdxOrderDestroy(%p, %p)", pArea, pOrderInfo)); + + if ( FAST_GOCOLD( ( AREAP ) pArea ) == FAILURE ) + return FAILURE; + + if ( ! pArea->lpIndexes ) + return SUCCESS; + + if ( pOrderInfo->itmOrder ) + { + uiTag = hb_cdxFindTag( pArea, pOrderInfo->itmOrder ); + if ( uiTag ) + { + pTag = hb_cdxGetTagByNumber( pArea, uiTag ); + pIndex = pTag->pIndex; + if ( !pIndex->fShared && !pIndex->fReadonly ) + { + hb_cdxIndexLockWrite( pIndex ); + hb_cdxIndexDelTag( pIndex, pTag->szName ); + hb_cdxIndexUnLockWrite( pIndex ); + if ( !pIndex->TagList ) + { + if ( pArea->lpIndexes == pIndex ) + { + pArea->lpIndexes = pIndex->pNext; + if ( pArea->fHasTags ) + { + pArea->fHasTags = FALSE; + SELF_WRITEDBHEADER( ( AREAP ) pArea ); + } + } + else + { + pIndexTmp = pArea->lpIndexes; + while ( pIndexTmp->pNext && ( pIndexTmp->pNext != pIndex ) ) + { + pIndexTmp = pIndexTmp->pNext; + } + if ( pIndexTmp->pNext == pIndex ) + { + pIndexTmp->pNext = pIndex->pNext; + } + } + szFileName = hb_strdup( pIndex->szFileName ); + hb_cdxIndexFree( pIndex ); + hb_fsDelete( (BYTE *) szFileName ); + hb_xfree( szFileName ); + } + } + else + { + /* TODO: allow this operation for shared mode? */ + hb_errInternal( 1023, "hb_cdxOrderDestroy: exclusive required.", "", "" ); + } + } + } + return SUCCESS; +} + +/* ( DBENTRYP_OII ) hb_cdxOrderInfo */ +/* + * Provides information about order management. + */ +ERRCODE hb_cdxOrderInfo( CDXAREAP pArea, USHORT uiIndex, LPDBORDERINFO pOrderInfo ) +{ + LPCDXTAG pTag = NULL; + USHORT uiTag = 0; + + HB_TRACE(HB_TR_DEBUG, ("hb_cdxOrderInfo(%p, %hu, %p)", pArea, uiIndex, pOrderInfo)); + HB_SYMBOL_UNUSED( pArea ); + + if ( FAST_GOCOLD( ( AREAP ) pArea ) == FAILURE ) + return FAILURE; + + switch( uiIndex ) + { + case DBOI_ORDERCOUNT: + case DBOI_BAGEXT: + case DBOI_LOCKOFFSET: + break; + default: + if ( pOrderInfo->itmOrder ) + /* TODO: check for atom bug name (indename) */ + uiTag = hb_cdxFindTag( pArea, pOrderInfo->itmOrder ); + else + uiTag = pArea->uiTag; + pTag = hb_cdxGetTagByNumber( pArea, uiTag ); + } + + switch( uiIndex ) + { + case DBOI_CONDITION: + pOrderInfo->itmResult = hb_itemPutC( pOrderInfo->itmResult, ( pTag ? pTag->ForExpr : "" ) ); + break; + + case DBOI_EXPRESSION: + pOrderInfo->itmResult = hb_itemPutC( pOrderInfo->itmResult, ( pTag ? pTag->KeyExpr : "" ) ); + break; + + case DBOI_POSITION: + if ( pOrderInfo->itmNewVal && HB_IS_NUMERIC( pOrderInfo->itmNewVal ) ) + { + /* TODO: DBOI_KEYGOTO goto specific logical record in the index file */ + pOrderInfo->itmResult = hb_itemPutNL( pOrderInfo->itmResult, + hb_cdxDBOIKeyGoto( pArea, pTag, TRUE ) ); + } + else + pOrderInfo->itmResult = hb_itemPutNL( pOrderInfo->itmResult, + hb_cdxDBOIKeyNo( pArea, pTag, TRUE ) ); + break; + + case DBOI_RECNO: /* TODO: is this ok? DBOI_RECNO == DBOI_KEYNORAW ? */ + case DBOI_KEYNORAW: + pOrderInfo->itmResult = hb_itemPutNL( pOrderInfo->itmResult, + hb_cdxDBOIKeyNo( pArea, pTag, FALSE ) ); + break; + + case DBOI_KEYCOUNT: + pOrderInfo->itmResult = hb_itemPutNL( pOrderInfo->itmResult, + hb_cdxDBOIKeyCount( pArea, pTag, TRUE ) ); + break; + + case DBOI_KEYCOUNTRAW: + pOrderInfo->itmResult = hb_itemPutNL( pOrderInfo->itmResult, + hb_cdxDBOIKeyCount( pArea, pTag, FALSE ) ); + break; + + case DBOI_SKIPUNIQUE: + pOrderInfo->itmResult = hb_itemPutL( pOrderInfo->itmResult, + hb_cdxSkipUnique( pArea, pTag, + hb_itemGetNI( pOrderInfo->itmNewVal ) >= 0 ) == SUCCESS ); + break; + + case DBOI_NAME: + pOrderInfo->itmResult = hb_itemPutC( pOrderInfo->itmResult, ( pTag ? pTag->szName : "" ) ); + break; + + case DBOI_NUMBER: + pOrderInfo->itmResult = hb_itemPutNI( pOrderInfo->itmResult, uiTag ); + break; + + case DBOI_BAGNAME: + if ( pTag ) + { + PHB_FNAME pFileName = hb_fsFNameSplit( pTag->pIndex->szFileName ); + pOrderInfo->itmResult = hb_itemPutC( pOrderInfo->itmResult, pFileName->szName ); + hb_xfree( pFileName ); + } + else + pOrderInfo->itmResult = hb_itemPutC( pOrderInfo->itmResult, "" ); + break; + + case DBOI_FULLPATH: + pOrderInfo->itmResult = hb_itemPutC( pOrderInfo->itmResult, ( pTag ? pTag->pIndex->szFileName : "" ) ); + break; + + case DBOI_BAGEXT: + pOrderInfo->itmResult = hb_itemPutC( pOrderInfo->itmResult, CDX_INDEXEXT ); + break; + + case DBOI_LOCKOFFSET: + pOrderInfo->itmResult = hb_itemPutNL( pOrderInfo->itmResult, CDX_LOCKSIZE ); + break; + + case DBOI_ORDERCOUNT: + uiTag = 0; + if ( pArea->lpIndexes ) + { + pTag = pArea->lpIndexes->TagList; + while ( pTag ) + { + uiTag++; + if ( pTag->pNext ) + pTag = pTag->pNext; + else + { + if ( pTag->pIndex->pNext ) + pTag = pTag->pIndex->pNext->TagList; + else + pTag = NULL; + } + } + } + pOrderInfo->itmResult = hb_itemPutNI( pOrderInfo->itmResult, uiTag ); + break; + + case DBOI_FILEHANDLE: + pOrderInfo->itmResult = hb_itemPutNL( pOrderInfo->itmResult, ( pTag ? ( LONG ) pTag->pIndex->hFile : FS_ERROR ) ); + break; + + case DBOI_ISCOND: + pOrderInfo->itmResult = hb_itemPutL( pOrderInfo->itmResult, ( pTag ? (pTag->ForExpr != NULL) : FALSE ) ); + break; + + case DBOI_ISDESC: + pOrderInfo->itmResult = hb_itemPutL( pOrderInfo->itmResult, ( pTag ? !pTag->UsrAscend : FALSE ) ); + if ( pOrderInfo->itmNewVal && HB_IS_LOGICAL( pOrderInfo->itmNewVal ) ) + pTag->UsrAscend = ! hb_itemGetL( pOrderInfo->itmNewVal ); + break; + + case DBOI_UNIQUE: + pOrderInfo->itmResult = hb_itemPutL( pOrderInfo->itmResult, ( pTag ? pTag->UniqueKey || pTag->UsrUnique : FALSE ) ); + if ( pOrderInfo->itmNewVal && HB_IS_LOGICAL( pOrderInfo->itmNewVal ) && !pTag->UniqueKey ) + pTag->UsrUnique = hb_itemGetL( pOrderInfo->itmNewVal ); + break; + + case DBOI_KEYTYPE: + if ( pTag ) + { + char szType[2]; + szType[0] = (char) pTag->uiType; + szType[1] = 0; + pOrderInfo->itmResult = hb_itemPutC( pOrderInfo->itmResult, szType ); + } + else + pOrderInfo->itmResult = hb_itemPutC( pOrderInfo->itmResult, "" ); + break; + + case DBOI_KEYSIZE: + if ( pTag ) + pOrderInfo->itmResult = hb_itemPutNL( pOrderInfo->itmResult, pTag->uiLen ); + else + pOrderInfo->itmResult = hb_itemPutNL( pOrderInfo->itmResult, 0 ); + break; + + case DBOI_KEYVAL: + hb_itemClear( pOrderInfo->itmResult ); + if ( pTag && !pArea->fEof ) + { + if ( pTag->CurKey->rec != pArea->ulRecNo ) + { + hb_cdxIndexLockRead( pTag->pIndex ); + hb_cdxCurKeyRefresh( pArea, pTag, FALSE ); + hb_cdxIndexUnLockRead( pTag->pIndex ); + } + if ( pTag->CurKey->rec == pArea->ulRecNo ) + hb_cdxKeyGetItem( pTag->CurKey, pOrderInfo->itmResult, pTag->uiType ); + } + break; + + case DBOI_SCOPETOP: + if ( pTag ) + hb_cdxScopeInfo( pArea, 0, pOrderInfo->itmResult ); + else + hb_itemClear( pOrderInfo->itmResult ); + break; + + case DBOI_SCOPEBOTTOM: + if ( pTag ) + hb_cdxScopeInfo( pArea, 1, pOrderInfo->itmResult ); + else + hb_itemClear( pOrderInfo->itmResult ); + break; + + case DBOI_SCOPETOPCLEAR: + if ( pTag ) + { + hb_cdxScopeInfo( pArea, 0, pOrderInfo->itmResult ); + hb_cdxTagClearScope( pTag, 0); + } + else + hb_itemClear( pOrderInfo->itmResult ); + break; + + case DBOI_SCOPEBOTTOMCLEAR: + if ( pTag ) + { + hb_cdxScopeInfo( pArea, 1, pOrderInfo->itmResult ); + hb_cdxTagClearScope( pTag, 1); + } + else + hb_itemClear( pOrderInfo->itmResult ); + break; + + case DBOI_CUSTOM: + pOrderInfo->itmResult = hb_itemPutL( pOrderInfo->itmResult, ( pTag ? pTag->Custom : FALSE ) ); + break; + + case DBOI_KEYADD: + if ( !pTag ) + { + pOrderInfo->itmResult = hb_itemPutL( pOrderInfo->itmResult, FALSE ); + } + else + { + if ( pTag->Custom ) + { + LPCDXKEY pKey; + hb_cdxIndexLockWrite( pTag->pIndex ); + if ( pOrderInfo->itmNewVal && !HB_IS_NIL( pOrderInfo->itmNewVal ) ) + pKey = hb_cdxKeyPutItem( NULL, pOrderInfo->itmNewVal, pArea->ulRecNo, pTag, TRUE ); + else + pKey = hb_cdxKeyEval( NULL, pTag, TRUE ); + hb_cdxTagKeyAdd( pTag, pKey ); + if ( uiTag != pArea->uiTag ) + hb_cdxTagClose( pTag ); + hb_cdxIndexUnLockWrite( pTag->pIndex ); + pOrderInfo->itmResult = hb_itemPutL( pOrderInfo->itmResult, TRUE ); + hb_cdxKeyFree( pKey ); + } + else + { + hb_cdxErrorRT( pArea, 0, 1052, "", 0 ); + } + } + break; + + case DBOI_KEYDELETE: + if ( !pTag ) + { + pOrderInfo->itmResult = hb_itemPutL( pOrderInfo->itmResult, FALSE ); + } + else + { + if ( pTag->Custom ) + { + LPCDXKEY pKey; + hb_cdxIndexLockWrite( pTag->pIndex ); + if ( pOrderInfo->itmNewVal && !HB_IS_NIL( pOrderInfo->itmNewVal ) ) + pKey = hb_cdxKeyPutItem( NULL, pOrderInfo->itmNewVal, pArea->ulRecNo, pTag, TRUE ); + else + pKey = hb_cdxKeyEval( NULL, pTag, TRUE ); + if ( hb_cdxTagKeyFind( pTag, pKey ) > 0 ) + { + hb_cdxPageKeyDelete( pTag->RootPage ); + pOrderInfo->itmResult = hb_itemPutL( pOrderInfo->itmResult, TRUE ); + } + else + { + pOrderInfo->itmResult = hb_itemPutL( pOrderInfo->itmResult, FALSE ); + } + if ( uiTag != pArea->uiTag ) + hb_cdxTagClose( pTag ); + hb_cdxIndexUnLockWrite( pTag->pIndex ); + hb_cdxKeyFree( pKey ); + } + else + { + hb_cdxErrorRT( pArea, 0, 1052, "", 0 ); + } + } + break; + + default: + return SUPER_ORDINFO( ( AREAP ) pArea, uiIndex, pOrderInfo ); + + } + return SUCCESS; +} + +/* ( DBENTRYP_V ) hb_cdxClearFilter : NULL */ +/* ( DBENTRYP_V ) hb_cdxClearLocate : NULL */ + +/* ( DBENTRYP_V ) hb_cdxClearScope */ +static ERRCODE hb_cdxClearScope( CDXAREAP pArea ) +{ + LPCDXTAG pTag; + + HB_TRACE(HB_TR_DEBUG, ("hb_cdxClearScope(%p)", pArea)); + + pTag = hb_cdxGetActiveTag( pArea ); + + if ( pTag ) + { + hb_cdxTagClearScope( pTag, 0); + hb_cdxTagClearScope( pTag, 1); + } + return SUCCESS; +} + +/* ( DBENTRYP_VPLP ) hb_cdxCountScope : NULL */ +/* ( DBENTRYP_I ) hb_cdxFilterText : NULL */ + +/* ( DBENTRYP_SI ) hb_cdxScopeInfo */ +static ERRCODE hb_cdxScopeInfo( CDXAREAP pArea, USHORT nScope, PHB_ITEM pItem ) +{ + LPCDXTAG pTag; + + HB_TRACE(HB_TR_DEBUG, ("hb_cdxScopeInfo(%p, %hu, %p)", pArea, nScope, pItem)); + + pTag = hb_cdxGetActiveTag( pArea ); + + hb_itemClear( pItem ); + if ( pTag ) + { + PHB_ITEM *pScope; + + nScope = ( ( nScope == 0 ) ? 0 : 1 ) ^ ( pTag->UsrAscend ? 0 : 1 ); + pScope = ( nScope == 0 ) ? &(pTag->topScope) : &(pTag->bottomScope); + if ( *pScope ) + hb_itemCopy( pItem, *pScope ); + } + return SUCCESS; +} + +/* ( DBENTRYP_VFI ) hb_cdxSetFilter : NULL */ +/* ( DBENTRYP_VLO ) hb_cdxSetLocate : NULL */ + +/* ( DBENTRYP_VOS ) hb_cdxSetScope */ +static ERRCODE hb_cdxSetScope( CDXAREAP pArea, LPDBORDSCOPEINFO sInfo ) +{ + USHORT nScope = sInfo->nScope; + LPCDXTAG pTag; + + HB_TRACE(HB_TR_DEBUG, ("hb_cdxSetScope(%p, %p)", pArea, sInfo)); + + pTag = hb_cdxGetActiveTag( pArea ); + + if ( pTag ) + { + nScope = ( ( nScope == 0 ) ? 0 : 1 ) ^ ( pTag->UsrAscend ? 0 : 1 ); + + if ( !sInfo->scopeValue ) + { + hb_cdxTagClearScope( pTag, nScope ); + } + else + { + PHB_ITEM *pScope; + LPCDXKEY *pScopeKey; + USHORT type; + BOOL fOK, fCB = FALSE; + + pScope = (nScope == 0) ? &(pTag->topScope) : &(pTag->bottomScope); + pScopeKey = (nScope == 0) ? &(pTag->topScopeKey) : &(pTag->bottomScopeKey); + type = sInfo->scopeValue->type; + if ( type == HB_IT_BLOCK ) + { + hb_vmPushSymbol( &hb_symEval ); + hb_vmPush( sInfo->scopeValue ); + hb_vmSend( 0 ); + type = HB_VM_STACK.Return.type; + fCB = TRUE; + } + //printf("\r\ntype=%lx", type);fflush(stdout); + + switch ( pTag->uiType ) + { + case 'C' : + fOK = ( type & HB_IT_STRING ); break; + case 'N' : + fOK = ( type & HB_IT_NUMERIC ); break; + case 'D' : + fOK = ( type == HB_IT_DATE ); break; + case 'L' : + fOK = ( type == HB_IT_LOGICAL ); break; + default: + fOK = FALSE; + } + if ( fOK ) + { + if ( *pScope == NULL ) + *pScope = hb_itemNew( NULL ); + hb_itemCopy( *pScope, sInfo->scopeValue ); + *pScopeKey = hb_cdxKeyPutItem( *pScopeKey, + fCB ? &(HB_VM_STACK.Return) : sInfo->scopeValue, + (nScope == 0) ? CDX_IGNORE_REC_NUM : CDX_MAX_REC_NUM, + pTag, TRUE ); + } + else + { + /* TODO: !!! + * RT error: DBFCDX/1051 Scope Type Mismatch + * hb_cdxErrorRT + */ } } } else - hb_errInternal( 2155, "hb_cdxIndexCheckVersion: Read error on index heading page.", "", "" ); - return ret; + { + /* TODO: !!! + * RT error: hb_cdxSetScope: workarea not indexed + */ + } + + return SUCCESS; } -static USHORT hb_cdxIndexLockRead( LPCDXINDEX pIndex, LPCDXTAG pTag ) +/* ( DBENTRYP_VPL ) hb_cdxSkipScope : NULL */ + +/* ( DBENTRYP_P ) hb_cdxCompile : NULL */ +/* ( DBENTRYP_I ) hb_cdxError : NULL */ +/* ( DBENTRYP_I ) hb_cdxEvalBlock : NULL */ + +/* ( DBENTRYP_VSP ) hb_cdxRawLock : NULL */ +/* ( DBENTRYP_VL ) hb_cdxLock : NULL */ +/* ( DBENTRYP_UL ) hb_cdxUnLock : NULL */ + +/* ( DBENTRYP_V ) hb_cdxCloseMemFile : NULL */ +/* ( DBENTRYP_VP ) hb_cdxCreateMemFile : NULL */ +/* ( DBENTRYP_SVPB ) hb_cdxGetValueFile : NULL */ +/* ( DBENTRYP_VP ) hb_cdxOpenMemFile : NULL */ +/* ( DBENTRYP_SVP ) hb_cdxPutValueFile : NULL */ + +/* ( DBENTRYP_V ) hb_cdxReadDBHeader : NULL */ +/* ( DBENTRYP_V ) hb_cdxWriteDBHeader : NULL */ +/* ( DBENTRYP_SVP ) hb_cdxWhoCares : NULL */ + + + +/* ######################################################################### */ +/* ######################################################################### */ +/* ######################################################################### */ +/* ######################################################################### */ + +#include "dbfcdx1.h" + +/* ######################################################################### */ +static LPSORTINFO hb_cdxSortNew( LPCDXTAG 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, + USHORT uiLen ); +static void hb_cdxSortStuffKey( LPSORTINFO pSort, LPSORTDATA * wx, BOOL fTag ); +static void hb_cdxSortGetNode( LPSORTINFO pSort, BYTE Character, + LONG * NewLink, BOOL fTag ); +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, BYTE * Value ); +static void hb_cdxSortOutputWord( LPSORTINFO pSort, LONG Tag, BYTE * Value, + USHORT uiLen ); +static void hb_cdxSortAddToNode( LPSORTINFO pSort, USHORT Lvl, LONG Tag, LONG Link, + LPCDXKEYINFO Value ); +static void hb_cdxSortAddExternal( LPSORTINFO pSort, USHORT Lvl, LONG Tag, LONG Link, + LPCDXKEYINFO Value ); +static void hb_cdxSortAddInternal( LPSORTINFO pSort, USHORT Lvl, LONG Tag, LONG Link, + LPCDXKEYINFO Value ); +#define hb_cdxSwapBytes( n ) HB_SWAP_ULONG( n ); +/* ######################################################################### */ + +static LPCDXKEYINFO hb_cdxSortKeyNew( void ) { - USHORT ret; - /* - LPCDXINDEX pIndex; - pIndex = pTag->pIndex; - */ - if ( pIndex->lockRead > 0 ) { - pIndex->lockRead++; - if ( pIndex->lockRead < 0 ) - hb_errInternal( 9105, "hb_cdxTagLockRead: bad count of locks.", "", "" ); - return 1; - } - if ( !pIndex->fShared ) - { - pIndex->lockRead++; - return 1; - } - /* ret = hb_fsLock ( pIndex->hFile, 0x7FFFFFFEL, 1, FL_LOCK ); */ - while (! (ret = hb_fsLock ( pIndex->hFile, 0x7FFFFFFEL, 1, FL_LOCK ) ) ); - if ( !ret ) - hb_errInternal( 9107, "hb_cdxTagLockRead: lock failure.", "", "" ); /* change into error dbfcdx/1038 */ - if ( ret ) { - pIndex->lockRead++; - if ( pIndex->lockRead < 0 ) - hb_errInternal( 9105, "hb_cdxTagLockRead: bad count of locks.", "", "" ); - if ( pTag ) - ret = hb_cdxIndexCheckVersion( pIndex ); - } - return ret; + LPCDXKEYINFO pKey; + pKey = ( LPCDXKEYINFO ) hb_xgrab( sizeof( CDXKEYINFO ) ); + memset( pKey, 0, sizeof( CDXKEYINFO ) ); + return pKey; } -static USHORT hb_cdxIndexUnLockRead( LPCDXINDEX pIndex, LPCDXTAG pTag ) +static void hb_cdxSortKeyFree( LPCDXKEYINFO pKey ) { - USHORT ret; - /* - LPCDXINDEX pIndex; - pIndex = pTag->pIndex; - */ - if ( pIndex->lockRead == 1) + if ( pKey ) { - hb_cdxPagePoolFlush( pIndex ); - hb_cdxPagePoolFree( pIndex, 10 ); - } - /* - pIndex->lockRead--; - if( pIndex->lockRead < 0 ) - hb_errInternal( 9106, "hb_cdxTagUnLockRead: bad count of locks.", "", "" ); - if( pIndex->lockRead > 0 ) - return 1; - */ - if( pIndex->lockRead - 1 < 0 ) - hb_errInternal( 9106, "hb_cdxTagUnLockRead: bad count of locks.", "", "" ); - if( pIndex->lockRead > 1 ) - { - pIndex->lockRead--; - return 1; + if ( pKey->Value ) + hb_xfree( pKey->Value ); + hb_xfree( pKey ); } +} - if ( pTag ) { - pTag = pIndex->TagList; - while ( pTag ) { - if( pTag->TagChanged ) - hb_cdxTagTagStore( pTag ); - pTag = pTag->pNext; - } - } - if ( !pIndex->fShared ) +static LPCDXKEYINFO hb_cdxSortKeyCopy( LPCDXKEYINFO pKeyDest, LPCDXKEYINFO pKey ) +{ + if ( !pKeyDest ) + pKeyDest = hb_cdxSortKeyNew(); + if ( pKeyDest->Value ) { - ret = 1; + hb_xfree( pKeyDest->Value ); + pKeyDest->Value = NULL; + pKeyDest->length = pKeyDest->realLength = 0; } + if ( pKey ) + { + pKeyDest->Value = (BYTE *) hb_xgrab( pKey->length + 1 ); + memcpy( pKeyDest->Value, pKey->Value, pKey->length ); + pKeyDest->length = pKey->length; + pKeyDest->realLength = pKey->realLength; + pKeyDest->Value[ pKeyDest->length ] = '\0'; + pKeyDest->fString = pKey->fString; + pKeyDest->Tag = pKey->Tag; + pKeyDest->Xtra = pKey->Xtra; + } + return pKeyDest; +} + +static LPCDXKEYINFO hb_cdxSortKeyPut( LPCDXKEYINFO pKey, BYTE * pbVal, USHORT uiLen, USHORT uiRealLen, BOOL fString ) +{ + if ( !pKey ) + pKey = hb_cdxSortKeyNew(); + if ( pKey->Value ) + { + hb_xfree( pKey->Value ); + pKey->Value = NULL; + } + pKey->realLength = uiRealLen; + pKey->fString = fString; + if ( pbVal == NULL ) + pKey->length = 0; else { - if ( pIndex->changesWritten ) { - ULONG ulVersion; - (pIndex->ulVersion)++; - ulVersion = hb_cdxSwapBytes( pIndex->ulVersion ); - if( !( (hb_fsSeek( pIndex->hFile, 0x08, FS_SET ) == 0x08) && - (hb_fsWrite( pIndex->hFile, ( BYTE * ) &ulVersion, 4) == 4) ) ) - hb_errInternal( 1010, "Write in index page failed 2.", "", "" ); - pIndex->changesWritten = 0; - } - ret = hb_fsLock ( pIndex->hFile, 0x7FFFFFFEL, 1, FL_UNLOCK ); - if ( !ret ) - hb_errInternal( 9108, "hb_cdxTagUnLockRead: unlock error.", "", "" ); + if ( uiLen > uiRealLen ) + uiLen = uiRealLen; + pKey->length = uiLen; + pKey->Value = ( BYTE * ) hb_xgrab( uiLen + 1 ); + memcpy( pKey->Value, pbVal, uiLen ); + pKey->Value[ uiLen ] = '\0'; } - pIndex->lockRead--; - return ret; + return pKey; } -/* These two are in case of different lock types (eg: Comix) */ -static USHORT hb_cdxIndexLockWrite ( LPCDXINDEX pIndex, LPCDXTAG pTag ) + +static SHORT hb_cdxSortKeyFindDup( LPCDXKEYINFO pKey1, LPCDXKEYINFO pKey2 ) { - return hb_cdxIndexLockRead( pIndex, pTag ); + SHORT usDup = 0; + if ( pKey2 != NULL ) + { + int iLimit = (pKey1->length > pKey2->length) ? pKey2->length : pKey1->length; + while ( usDup < iLimit && ( (BYTE) pKey1->Value[ usDup ] ) == + ( (BYTE) pKey2->Value[ usDup ] ) ) + usDup++; + } + return usDup; } -static USHORT hb_cdxIndexUnLockWrite ( LPCDXINDEX pIndex, LPCDXTAG pTag ) + +#ifndef HB_CDP_SUPPORT_OFF +static int hb_cdxSortKeyCompare( LPCDXKEYINFO pKey1, LPCDXKEYINFO pKey2, PHB_CODEPAGE cdpage ) +#else +static int hb_cdxSortKeyCompare( LPCDXKEYINFO pKey1, LPCDXKEYINFO pKey2 ) +#endif { - return hb_cdxIndexUnLockRead( pIndex, pTag ); + int iLimit, iResult = 0, iPos = 0; + if ( pKey1 == NULL ) + return ( pKey2 == NULL ) ? 0 : -1; + if ( pKey2 == NULL ) + return 1; + iLimit = (pKey1->length > pKey2->length) ? pKey2->length : pKey1->length; + if ( pKey1->fString && pKey2->fString) + { +#ifndef HB_CDP_SUPPORT_OFF + while ( iResult == 0 && iPos < iLimit ) + { + /* for nation sorting support */ + iResult = hb_cdpcharcmp( pKey1->Value[ iPos ], pKey2->Value[ iPos ], cdpage ); + iPos++; /* EndPos += 1; */ + } +#else + if ( iLimit > 0 ) + iResult = memcmp(pKey1->Value, pKey2->Value, iLimit); +#endif + if ( iResult == 0 ) + { + BYTE c1, c2; + iPos = iLimit; + iLimit = ( pKey1->realLength > pKey2->realLength ) ? pKey2->realLength : pKey1->realLength; + while ( iResult == 0 && iPos < iLimit ) + { + c1 = (BYTE) ( ( iPos < pKey1->length ) ? ( pKey1->Value[ iPos ]) : ' ' ); + c2 = (BYTE) ( ( iPos < pKey2->length ) ? ( pKey2->Value[ iPos ]) : ' ' ); +#ifndef HB_CDP_SUPPORT_OFF + /* for nation sorting support */ + iResult = hb_cdpcharcmp( c1, c2, cdpage ); +#else + iResult = c1 - c2; +#endif + iPos++; + } + } + if ( iResult == 0 ) + iResult = pKey1->realLength - pKey2->realLength; + } + else if ( iLimit == 0 || (iResult = memcmp( pKey1->Value, pKey2->Value, iLimit )) == 0 ) + iResult = pKey1->length - pKey2->length; + if ( iResult < 0 ) + return -1; + else if ( iResult > 0 ) + return 1; + else + return 0; } -/* end hb_cdxIndexxxx */ -/* end hb_cdxIndexxxx */ +static int hb_cdxSortKeyValCompare( LPCDXTAG pTag, BYTE * pKeyVal1, BYTE keyLen1, + BYTE * pKeyVal2, BYTE keyLen2 ) +{ + CDXKEYINFO pKey1, pKey2; + pKey1.Value = pKeyVal1; + pKey1.length = keyLen1; + pKey2.Value = pKeyVal2; + pKey2.length = keyLen2; + pKey2.realLength = pKey1.realLength = pTag->uiLen; + pKey2.fString = pKey1.fString = ( pTag->uiType == 'C' ); +#ifndef HB_CDP_SUPPORT_OFF + return hb_cdxSortKeyCompare( &pKey1, &pKey2, pTag->pIndex->pArea->cdPage ); +#else + return hb_cdxSortKeyCompare( &pKey1, &pKey2 ); +#endif +} -/* hb_cdxSortxxx */ -/* #include "cdxsort.c" */ - -/* hb_cdxSortxxx */ static LPSORTINFO hb_cdxSortNew( LPCDXTAG pTag, BOOL bUnique ) { @@ -4980,8 +6275,8 @@ static LPSORTINFO hb_cdxSortNew( LPCDXTAG pTag, BOOL bUnique ) pSort->Ascend = TRUE; pSort->CurTag = pTag; pSort->KeyTot = pTag->pIndex->pArea->ulRecCount; - pSort->KeyWork = hb_cdxKeyNew(); - pSort->LastKey = hb_cdxKeyNew(); + pSort->KeyWork = hb_cdxSortKeyNew(); + pSort->LastKey = hb_cdxSortKeyNew(); return pSort; } @@ -5004,7 +6299,7 @@ static void hb_cdxSortFree( LPSORTINFO pSort ) pSort->CurTag->RootBlock = pa; pSort->NodeList[ usCount ]->Node_Atr++; } - hb_cdxIndexPageWrite( pSort->CurTag->pIndex, pa, pSort->NodeList[ usCount ], + hb_cdxIndexPageWrite( pSort->CurTag->pIndex, pa, (BYTE *) pSort->NodeList[ usCount ], sizeof( CDXDATA ) ); if( pSort->NodeList[ usCount + 1 ] != NULL ) hb_cdxSortAddToNode( pSort, ( USHORT ) ( usCount + 1 ), pa, @@ -5023,8 +6318,8 @@ static void hb_cdxSortFree( LPSORTINFO pSort ) } hb_xfree( pSort->ChunkList ); } - hb_cdxKeyFree( pSort->KeyWork ); - hb_cdxKeyFree( pSort->LastKey ); + hb_cdxSortKeyFree( pSort->KeyWork ); + hb_cdxSortKeyFree( pSort->LastKey ); if ( pSort->hTempFile ) { @@ -5055,6 +6350,7 @@ static void hb_cdxSortSwapSendWord( LPSORTINFO pSort, BYTE * Value ) LONG Tag; BYTE * pce; BYTE bLen; + double d; LPSORTSWAPITEM pItem; @@ -5062,7 +6358,9 @@ static void hb_cdxSortSwapSendWord( LPSORTINFO pSort, BYTE * Value ) bLen -= 8; Value++; pce = Value + bLen; - Tag = ( long ) hb_cdxSorttoND( pce, 8 ); + HB_GET_SORTDBL( d, pce ); + Tag = ( LONG ) d; + // hb_cdxSortOutputWord( pSort, Tag, Value, uiLen ); if ( pSort->pSwapPage->nCurPos + sizeof(SORTSWAPITEM) + bLen - 1 >= sizeof(pSort->pSwapPage->page) ) { if ( hb_fsWrite( pSort->hTempFile, (BYTE *) pSort->pSwapPage->page, pSort->pSwapPage->nCurPos ) != pSort->pSwapPage->nCurPos ) @@ -5128,15 +6426,8 @@ static void hb_cdxSortSwapFillPage( LPSORTINFO pSort ) static int hb_cdxSortSwapSavePage( LPSORTINFO pSort ) { SORTSWAPPAGE swap; - // LPSORTSWAPITEM pItem; char *ptr; - // short nCurPos; - // ULONG nFileOffset; pSort->nSwapPages++; -#ifdef CDXDEBUG - printf( "hb_cdxSortSwapSavePage(): %i : %li\n" , pSort->nSwapPages, pSort->WordCount); -#endif - /* save page */ if ( ! pSort->hTempFile ) { BYTE szName[ _POSIX_PATH_MAX + 1 ]; @@ -5223,7 +6514,10 @@ static BOOL hb_cdxSortSwapGetNextKey( LPSORTINFO pSort, LONG * pKeyRec, BYTE * p BYTE winKeyLen; char * winKeyVal; int iResult = 1; - winPage = winKeyLen = winKeyRec = 0; /* this way some compilers don't emit warnings */ + + /* this way some compilers don't emit warnings */ + winPage = winKeyLen = 0; + winKeyRec = 0; winKeyVal = NULL; for ( nPage = 0 ; nPage < pSort->nSwapPages ; nPage++) { pPage = pSort->pSwapPage + nPage; @@ -5231,12 +6525,8 @@ static BOOL hb_cdxSortSwapGetNextKey( LPSORTINFO pSort, LONG * pKeyRec, BYTE * p { if( winKeyVal ) { - iResult = hb_cdxKeyValCompare( pSort->CurTag, winKeyVal, winKeyLen, - pPage->tmpKeyVal, pPage->tmpKeyLen, TRUE ); - /* TODO - if( descend && iResult ) - result = ( result > 0 )? -1:1; - */ + iResult = hb_cdxSortKeyValCompare( pSort->CurTag, winKeyVal, winKeyLen, + pPage->tmpKeyVal, pPage->tmpKeyLen ); } if( iResult > 0 || ( iResult == 0 && pPage->tmpRecNo < winKeyRec ) ) { @@ -5361,8 +6651,8 @@ static int hb_cdxSortSwapBuildIndex( LPSORTINFO pSort ) { if ( pKeyPrevVal ) { if ( nKeyPrevLen == nKeyLen ) { - if (! hb_cdxKeyValCompare( pSort->CurTag, (char *) pKeyPrevVal, (BYTE) nKeyPrevLen, - (char *) pKeyVal, (BYTE) nKeyLen, TRUE ) ) + if (! hb_cdxSortKeyValCompare( pSort->CurTag, (char *) pKeyPrevVal, (BYTE) nKeyPrevLen, + (char *) pKeyVal, (BYTE) nKeyLen ) ) { continue; } @@ -5406,7 +6696,6 @@ static void hb_cdxSortGetNewChunk( LPSORTINFO pSort ) pSort->ChunkCur++; if( pSort->ChunkCur == pSort->ChunkLimit ) { - /* printf( "FlushChunks();" ); */ hb_cdxSortSwapSavePage( pSort ); return; } @@ -5428,7 +6717,7 @@ static void hb_cdxSortInsertWord( LPSORTINFO pSort, LONG Tag, char * Value, USHORT cc, nc; LPSORTDATA wx; - hb_cdxDNtoSort( ( double ) Tag, (BYTE *) &s[0] ); + HB_PUT_SORTDBL( s, ( double ) Tag ); if( pSort->NodeLimit - pSort->NodeCur < uiLen + 8 ) { @@ -5523,6 +6812,9 @@ static void hb_cdxSortGetNode( LPSORTINFO pSort, BYTE Character, LONG * NewLink, int df; LONG p, q, r; LPSORTDATA px, qx, rx; +#ifndef HB_CDP_SUPPORT_OFF + PHB_CODEPAGE cdPage = pSort->CurTag->pIndex->pArea->cdPage; +#endif if( pSort->LevelPtr == 0 ) { @@ -5568,7 +6860,7 @@ static void hb_cdxSortGetNode( LPSORTINFO pSort, BYTE Character, LONG * NewLink, if( pSort->CurTag->uiType == 'C' && ( !( px->sortu.A.NUse & SORT_NOT_KEY ) || !fTag ) ) #ifndef HB_CDP_SUPPORT_OFF /* for nation sorting support */ - df = hb_cdpcharcmp( fTag ? ' ' : Character, ( px->sortu.A.NUse & SORT_NOT_KEY ) ? ' ' : px->sortu.A.Character ); + df = hb_cdpcharcmp( fTag ? ' ' : Character, ( px->sortu.A.NUse & SORT_NOT_KEY ) ? ' ' : px->sortu.A.Character, cdPage ); #else df = ( fTag ? ' ' : Character ) - ( ( px->sortu.A.NUse & SORT_NOT_KEY ) ? ' ' : px->sortu.A.Character ); #endif @@ -5622,7 +6914,7 @@ static void hb_cdxSortGetNode( LPSORTINFO pSort, BYTE Character, LONG * NewLink, if( pSort->CurTag->uiType == 'C' && ( !( px->sortu.A.NUse & SORT_NOT_KEY ) || !fTag ) ) #ifndef HB_CDP_SUPPORT_OFF /* for nation sorting support */ - df = hb_cdpcharcmp( fTag ? ' ' : Character, ( px->sortu.A.NUse & SORT_NOT_KEY ) ? ' ' : px->sortu.A.Character ); + df = hb_cdpcharcmp( fTag ? ' ' : Character, ( px->sortu.A.NUse & SORT_NOT_KEY ) ? ' ' : px->sortu.A.Character, cdPage ); #else df = ( fTag ? ' ' : Character ) - ( ( px->sortu.A.NUse & SORT_NOT_KEY ) ? ' ' : px->sortu.A.Character ); #endif @@ -5735,11 +7027,13 @@ static void hb_cdxSortSendWord( LPSORTINFO pSort, BYTE * Value ) LONG Tag; char * pce; USHORT uiLen; + double d; uiLen = ( USHORT ) Value[0]; Value++; pce = (char *) (Value + uiLen - 8) ; - Tag = ( long ) hb_cdxSorttoND( (BYTE *) pce, 8 ); + HB_GET_SORTDBL( d, pce ); + Tag = ( LONG ) d; hb_cdxSortOutputWord( pSort, Tag, Value, uiLen-8 ); } @@ -5755,11 +7049,11 @@ static void hb_cdxSortOutputWord( LPSORTINFO pSort, LONG Tag, BYTE * Value, { uiLen--; } - hb_cdxKeyPut( pSort->KeyWork, Value, uiLen, - pSort->CurTag->uiLen, ( pSort->CurTag->uiType == 'C' ) ); + hb_cdxSortKeyPut( pSort->KeyWork, Value, uiLen, + pSort->CurTag->uiLen, ( pSort->CurTag->uiType == 'C' ) ); hb_cdxSortAddToNode( pSort, 0, Tag, Tag, pSort->KeyWork ); pSort->LastTag = Tag; - hb_cdxKeyCopy( pSort->LastKey, pSort->KeyWork ); + hb_cdxSortKeyCopy( pSort->LastKey, pSort->KeyWork ); } static void hb_cdxSortAddToNode( LPSORTINFO pSort, USHORT Lvl, LONG Tag, @@ -5780,7 +7074,7 @@ static void hb_cdxSortAddToNode( LPSORTINFO pSort, USHORT Lvl, LONG Tag, 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 ); + HB_CDXBITMASK( pSort->NodeList[ 0 ]->cdxu.External.RecNumBits ); while( sr > pSort->NodeList[ 0 ]->cdxu.External.RecNumMask ) { pSort->NodeList[ 0 ]->cdxu.External.ShortBytes++; @@ -5792,12 +7086,12 @@ static void hb_cdxSortAddToNode( LPSORTINFO pSort, USHORT Lvl, LONG Tag, pSort->NodeList[ 0 ]->cdxu.External.DupCntBits = pSort->NodeList[ 0 ]->cdxu.External.TrlCntBits = (BYTE) bitcnt; pSort->NodeList[ 0 ]->cdxu.External.DupCntMask = - (BYTE) hb_cdxMakeMask( pSort->NodeList[ 0 ]->cdxu.External.DupCntBits ); + (BYTE) HB_CDXBITMASK( pSort->NodeList[ 0 ]->cdxu.External.DupCntBits ); pSort->NodeList[ 0 ]->cdxu.External.TrlCntMask = - (BYTE) hb_cdxMakeMask( pSort->NodeList[ 0 ]->cdxu.External.TrlCntBits ); + (BYTE) HB_CDXBITMASK( pSort->NodeList[ 0 ]->cdxu.External.TrlCntBits ); } pSort->NodeList[ Lvl ]->Left_Ptr = -1; - pSort->NodeList[ Lvl ]->Rght_Ptr = hb_cdxIndexGetAvailPage( pSort->CurTag->pIndex ); + pSort->NodeList[ Lvl ]->Rght_Ptr = hb_cdxIndexGetAvailPage( pSort->CurTag->pIndex, FALSE ); pSort->NodeList[ Lvl ]->Node_Atr = ( Lvl == 0 ) ? 2 : 0; } if( Lvl == 0 ) @@ -5823,13 +7117,13 @@ static void hb_cdxSortAddExternal( LPSORTINFO pSort, USHORT Lvl, LONG Tag, LONG memset( pSort->NodeList[ Lvl ]->cdxu.External.ExtData, 0, sizeof( pSort->NodeList[ Lvl ]->cdxu.External.ExtData ) ); pSort->NodeList[ Lvl ]->cdxu.External.FreeSpace = CDX_EXTERNAL_SPACE; - hb_cdxKeyPutC( pSort->LastKey, "", 0 ); + hb_cdxSortKeyPut( pSort->LastKey, "", 0, 0, ( pSort->CurTag->uiType == 'C' ) ); } ct = ( USHORT ) ( pSort->CurTag->uiLen - Value->length ); - cd = hb_cdxKeyFindDup( Value, pSort->LastKey ); + cd = hb_cdxSortKeyFindDup( Value, pSort->LastKey ); #ifndef HB_CDX_DBGCODE_OFF - if( hb_cdxKeyCompare( Value, pSort->LastKey, TRUE ) < 0 ) + if( hb_cdxSortKeyCompare( Value, pSort->LastKey, pSort->CurTag->pIndex->pArea->cdPage ) < 0 ) { /* printf("\r\nValue->length=%2d, Value->Value=%s", Value->length, Value->Value); @@ -5847,7 +7141,7 @@ static void hb_cdxSortAddExternal( LPSORTINFO pSort, USHORT Lvl, LONG Tag, LONG pSort->NodeList[ Lvl ]->cdxu.External.ShortBytes - cd - ct ); /* RECMASK */ #ifndef HB_LONG_LONG_OFF - rr = ( (ULONGLONG) ct << ( ( pSort->NodeList[ Lvl ]->cdxu.External.ShortBytes * 8 ) - + rr = ( (ULONGLONG) ct << ( ( pSort->NodeList[ Lvl ]->cdxu.External.ShortBytes * 8 ) - pSort->NodeList[ Lvl ]->cdxu.External.TrlCntBits ) ) | ( (ULONGLONG) cd << ( ( pSort->NodeList[ Lvl ]->cdxu.External.ShortBytes * 8 ) - pSort->NodeList[ Lvl ]->cdxu.External.TrlCntBits - @@ -5871,18 +7165,18 @@ static void hb_cdxSortAddExternal( LPSORTINFO pSort, USHORT Lvl, LONG Tag, LONG pSort->CurTag->uiLen - cd - ct ); pSort->NodeList[ Lvl ]->Entry_Ct++; if( pSort->NodeList[ Lvl ]->cdxu.External.FreeSpace < - ( pSort->CurTag->uiLen + + ( pSort->CurTag->uiLen + pSort->NodeList[ Lvl ]->cdxu.External.ShortBytes ) * 1 ) /* 2 only if count after the key was added */ { pa = pSort->NodeList[ Lvl ]->Rght_Ptr; // TODO : check this, may be wrong /* if( pSort->KeyCnt < pSort->KeyTot ) */ if( pSort->KeyCnt < pSort->TotalWordCount ) - pSort->NodeList[ Lvl ]->Rght_Ptr = hb_cdxIndexGetAvailPage( pSort->CurTag->pIndex ); + pSort->NodeList[ Lvl ]->Rght_Ptr = hb_cdxIndexGetAvailPage( pSort->CurTag->pIndex, FALSE ); else pSort->NodeList[ Lvl ]->Rght_Ptr = -1; pSort->NodeList[ Lvl ]->Node_Atr = 2; - hb_cdxIndexPageWrite( pSort->CurTag->pIndex, pa, pSort->NodeList[ Lvl ], + hb_cdxIndexPageWrite( pSort->CurTag->pIndex, pa, (BYTE *) pSort->NodeList[ Lvl ], sizeof( CDXDATA ) ); pSort->NodeList[ Lvl ]->Left_Ptr = pa; hb_cdxSortAddToNode( pSort, ( USHORT ) ( Lvl + 1 ), pa, Link, Value ); @@ -5914,3381 +7208,208 @@ static void hb_cdxSortAddInternal( LPSORTINFO pSort, USHORT Lvl, LONG Tag, LONG { pa = pSort->NodeList[ Lvl ]->Rght_Ptr; if( !pSort->Closing ) - pSort->NodeList[ Lvl ]->Rght_Ptr = hb_cdxIndexGetAvailPage( pSort->CurTag->pIndex ); + pSort->NodeList[ Lvl ]->Rght_Ptr = hb_cdxIndexGetAvailPage( pSort->CurTag->pIndex, FALSE ); else pSort->NodeList[ Lvl ]->Rght_Ptr = -1; pSort->NodeList[ Lvl ]->Node_Atr = 0; - hb_cdxIndexPageWrite( pSort->CurTag->pIndex, pa, pSort->NodeList[ Lvl ], + hb_cdxIndexPageWrite( pSort->CurTag->pIndex, pa, (BYTE *) pSort->NodeList[ Lvl ], sizeof( CDXDATA ) ); pSort->NodeList[ Lvl ]->Left_Ptr = pa; hb_cdxSortAddToNode( pSort, ( USHORT ) ( Lvl + 1 ), pa, Link, Value ); pSort->NodeList[ Lvl ]->Entry_Ct = 0; } } -/* end hb_cdxSortxxx */ -/* end hb_cdxSortxxx */ -/* #include "cdxhlp.c" */ +/* ######################################################################### */ - -/* static LPCDXTAG hb_cdxGetActiveTag( LPCDXINDEX PIF ) */ -static LPCDXTAG hb_cdxGetActiveTag( CDXAREAP pArea ) +static void hb_cdxTagEmptyIndex( LPCDXTAG pTag ) { - LPCDXTAG pTag; - USHORT uiTag; - - // if( ! PIF ) - if( ! pArea ) - return NULL; - - uiTag = pArea->uiTag; - if( ! uiTag ) - return NULL; - /* - pTag = PIF->TagList; - --uiTag; - while( uiTag && pTag ) - { - pTag = pTag->pNext; - --uiTag; - } - */ - pTag = hb_cdxGetTagByNumber( pArea, uiTag ); - if( !pTag ) - pArea->uiTag = 0; - return pTag; + pTag->RootPage = hb_cdxPageNew( pTag, NULL, 0 ); + pTag->RootBlock = pTag->RootPage->Page; + pTag->RootPage->PageType = CDX_NODE_ROOT | CDX_NODE_LEAF; + hb_cdxPageLeafInitSpace( pTag->RootPage ); } -static LPCDXTAG hb_cdxGetTagByNumber(CDXAREAP pArea, USHORT uiTag ) +static void hb_cdxTagDoIndex( LPCDXTAG pTag ) { - LPCDXTAG pTag; - LPCDXINDEX pCdx; - - if( ! uiTag ) - return NULL; - /* - pTag = pArea->lpIndexes->TagList; - --uiTag; - while( uiTag && pTag ) - { - pTag = pTag->pNext; - --uiTag; - } - */ - pCdx = pArea->lpIndexes; - pTag = NULL; - while ( uiTag && pCdx ) { - pTag = pCdx->TagList; - if ( pTag ) - uiTag--; - while ( uiTag && pTag ) { - pTag = pTag->pNext; - if ( pTag ) - uiTag--; - } - pCdx = pCdx->pNext; - } - return pTag; -} - -static USHORT hb_cdxGetTagNumber(CDXAREAP pArea, LPCDXTAG pFindTag) -{ - LPCDXTAG pTag; - LPCDXINDEX pCdx; - USHORT uiTag; - - if( ! pFindTag ) - return 0; - pCdx = pArea->lpIndexes; - pTag = NULL; - uiTag = 0; - while ( pCdx && (pTag != pFindTag) ) { - pTag = pCdx->TagList; - while ( pTag && (pTag != pFindTag) ) { - pTag = pTag->pNext; - uiTag++; - } - if ( pTag ) - uiTag++; - pCdx = pCdx->pNext; - } - if ( !pTag ) - uiTag = 0; - return uiTag; -} - - -static USHORT hb_cdxFindTag( CDXAREAP pArea, LPDBORDERINFO pOrderInfo ) -{ - USHORT uiTag; - - if( pOrderInfo->itmOrder ) - { - if( hb_itemType( pOrderInfo->itmOrder ) != HB_IT_STRING && - hb_itemGetNI( pOrderInfo->itmOrder ) == 0 ) - uiTag = 0; - else - { - if( hb_itemType( pOrderInfo->itmOrder ) == HB_IT_STRING ) - { - LPCDXTAG pTag; - LPCDXINDEX pCdx; - char szName[ CDX_MAX_TAG_NAME_LEN + 1 ]; - - /* - pTag = pArea->lpIndexes->TagList; - for( uiTag = 0; pTag; uiTag++ ) - { - / * if( !strcmp( pTag->szName, hb_itemGetCPtr( pOrderInfo->itmOrder ) ) ) * / - if( !hb_stricmp( pTag->szName, hb_itemGetCPtr( pOrderInfo->itmOrder ) ) ) - break; - pTag = pTag->pNext; - } - - if( pTag ) - ++uiTag; - else - uiTag = 0; - */ - hb_strncpyUpperTrim( szName, hb_itemGetCPtr( pOrderInfo->itmOrder ), - (hb_itemGetCLen( pOrderInfo->itmOrder ) > CDX_MAX_TAG_NAME_LEN) ? - CDX_MAX_TAG_NAME_LEN : hb_itemGetCLen( pOrderInfo->itmOrder ) ); - pCdx = pArea->lpIndexes; - pTag = NULL; - uiTag = 0; - while ( pCdx && !pTag) { - pTag = pCdx->TagList; - while ( pTag ) { - uiTag++; - /* if( !hb_stricmp( pTag->szName, hb_itemGetCPtr( pOrderInfo->itmOrder ) ) ) */ - if( !hb_stricmp( pTag->szName, szName ) ) - break; - pTag = pTag->pNext; - } - pCdx = pCdx->pNext; - } - if ( !pTag ) - uiTag = 0; - } - else - { - uiTag = hb_itemGetNI( pOrderInfo->itmOrder ); - if ( ! hb_cdxGetTagByNumber(pArea, uiTag ) ) - uiTag = 0; - } - } - } - else - uiTag = 0; - - return uiTag; -} - -static LPCDXINDEX hb_cdxFindBag( CDXAREAP pArea, char * szBagName ) -{ - /* TODO: This only checks for basename of bag, a complete (but reliable) test should be done to look for the same file */ - LPCDXINDEX pCdx; - PHB_FNAME pFileName; - char * szBaseName; - - pFileName = hb_fsFNameSplit( szBagName ); - szBaseName = hb_strdup( pFileName->szName ); - hb_strUpper( szBaseName, strlen(szBaseName)); - // hb_xfree( pFileName ); - - pCdx = pArea->lpIndexes; - while ( pCdx ) { - hb_xfree( pFileName ); - pFileName = hb_fsFNameSplit( pCdx->szFileName ); - hb_strUpper( pFileName->szName, strlen(pFileName->szName)); - if( !hb_stricmp( pFileName->szName, szBaseName ) ) - break; - pCdx = pCdx->pNext; - } - hb_xfree( pFileName ); - hb_xfree( szBaseName ); - return pCdx; -} - -static LPCDXTAG hb_cdxReorderTagList ( LPCDXTAG TagList ) -{ - LPCDXTAG pTag1, pTag2, pTagTmp; - - pTag1 = TagList; - while( pTag1->pNext ) - { - if( pTag1->TagBlock < pTag1->pNext->TagBlock ) - pTag1 = pTag1->pNext; - else - { - if( TagList->TagBlock > pTag1->pNext->TagBlock ) - { - pTagTmp = TagList; - TagList = pTag1->pNext; - pTag1->pNext = pTag1->pNext->pNext; - TagList->pNext = pTagTmp; - } - else - { - pTag2 = TagList; - while( pTag2->pNext && (pTag2->pNext->TagBlock < pTag1->pNext->TagBlock) ) - pTag2 = pTag2->pNext; - - pTagTmp = pTag2->pNext; - pTag2->pNext = pTag1->pNext; - pTag1->pNext = pTag1->pNext->pNext; - pTag2->pNext->pNext = pTagTmp; - } - } - } - return TagList; -} - -static ERRCODE hb_cdxGoEof( CDXAREAP pArea ) -{ - ERRCODE retvalue; - LPCDXTAG pTag; - HB_TRACE(HB_TR_DEBUG, ("cdxGoEof(%p)", pArea)); - - pTag = hb_cdxGetActiveTag( pArea ); - retvalue = SUPER_GOTO( ( AREAP ) pArea, 0 ); - if( pArea->ulRecCount ) { - pArea->fBof = FALSE; - if ( pTag ) - pTag->TagBOF = FALSE; - } - pArea->fEof = TRUE; - if ( pTag ) - { - pTag->TagEOF = TRUE; - pTag->CurKeyInfo->Tag = 0; - } - return retvalue; -} - -static BOOL hb_cdxTopScope( LPCDXTAG pTag, LPCDXKEYINFO pKey ) -{ - if( pTag->topScope ) - { - if ( pTag->topScopeKey->realLength ) - return ( hb_cdxKeyCompare( pTag->topScopeKey, pKey, FALSE) <= 0); - else - return TRUE; - } - else - return TRUE; -} - -static BOOL hb_cdxBottomScope( LPCDXTAG pTag, LPCDXKEYINFO pKey ) -{ - if( pTag->bottomScope ) - { - if ( pTag->bottomScopeKey->realLength ) - return ( hb_cdxKeyCompare( pTag->bottomScopeKey, pKey, FALSE) >= 0); - else - return TRUE; - } - else - return TRUE; -} - -static void hb_cdxTagClearScope( LPCDXTAG pTag, USHORT nScope ) -{ - PHB_ITEM *pScope; - LPCDXKEYINFO *pScopeKey; - - HB_TRACE(HB_TR_DEBUG, ("hb_cdxTagClearScope(%p, %hu)", pTag, nScope)); - - pScope = (nScope == 0) ? &(pTag->topScope) : &(pTag->bottomScope); - pScopeKey = (nScope == 0) ? &(pTag->topScopeKey) : &(pTag->bottomScopeKey); - if ( *pScope ) { - hb_itemRelease( *pScope ); - *pScope = NULL; - } - if ( *pScopeKey ) { - hb_cdxKeyFree( *pScopeKey ); - *pScopeKey = NULL; - } -} - -static void hb_cdxMacroRun( AREAP pArea, HB_MACRO_PTR pMacro ) -{ - int iCurrArea; - iCurrArea = hb_rddGetCurrentWorkAreaNumber(); - if ( iCurrArea != pArea->uiArea ) - hb_rddSelectWorkAreaNumber( pArea->uiArea ); - else - iCurrArea = 0; - hb_macroRun( pMacro ); - if ( iCurrArea ) - hb_rddSelectWorkAreaNumber( iCurrArea ); -} - -static LPCDXKEYINFO hb_cdxEvalKey( CDXAREAP pArea, LPCDXTAG pTag ) -{ - LPCDXKEYINFO pKey; + ULONG ulRecNo, ulRecCount; + BOOL bForOk; + LPSORTINFO pSort; + PHB_ITEM pItem; HB_MACRO_PTR pMacro; - int iCurrArea; - - iCurrArea = hb_rddGetCurrentWorkAreaNumber(); - if ( iCurrArea != pArea->uiArea ) - hb_rddSelectWorkAreaNumber( pArea->uiArea ); - else - iCurrArea = 0; - - pKey = hb_cdxKeyNew(); - - if( hb_itemType( pTag->pKeyItem ) == HB_IT_BLOCK ) - { - hb_vmPushSymbol( &hb_symEval ); - hb_vmPush( pTag->pKeyItem ); - hb_vmSend( 0 ); - hb_cdxKeyPutItem( pKey, &(HB_VM_STACK.Return) ); - } - else - { - pMacro = ( HB_MACRO_PTR ) hb_itemGetPtr( pTag->pKeyItem ); - hb_macroRun( pMacro ); - // hb_cdxMacroRun( (AREAP) pArea, pMacro ); - hb_cdxKeyPutItem( pKey, hb_stackItemFromTop( - 1 ) ); - hb_stackPop(); - } - pKey->Tag = pArea->ulRecNo; - - if ( iCurrArea ) - hb_rddSelectWorkAreaNumber( iCurrArea ); - - return pKey; -} - -static BOOL hb_cdxEvalCond ( CDXAREAP pArea, PHB_ITEM pCondItem, BOOL checkenv ) -{ - HB_MACRO_PTR pMacro; - int iCurrArea = 0; - BOOL ret; - - if ( checkenv ) { - iCurrArea = hb_rddGetCurrentWorkAreaNumber(); - if ( iCurrArea != pArea->uiArea ) - hb_rddSelectWorkAreaNumber( pArea->uiArea ); - else - iCurrArea = 0; - } - - if( hb_itemType( pCondItem ) == HB_IT_BLOCK ) - { - hb_vmPushSymbol( &hb_symEval ); - hb_vmPush( pCondItem ); - hb_vmSend( 0 ); - ret = hb_itemGetL( &(HB_VM_STACK.Return) ); - } - else - { - pMacro = ( HB_MACRO_PTR ) hb_itemGetPtr( pCondItem ); - hb_macroRun( pMacro ); - // hb_cdxMacroRun( (AREAP) pArea, pMacro ); - ret = hb_itemGetL( hb_stackItemFromTop( - 1 ) ); - hb_stackPop(); - } - - if ( checkenv ) { - if ( iCurrArea ) - hb_rddSelectWorkAreaNumber( iCurrArea ); - } - return ret; -} - - -static ERRCODE cdxError( CDXAREAP pArea, USHORT uiGenCode, USHORT uiSubCode, char * filename, USHORT uiFlags ) -{ - PHB_ITEM pError; - ERRCODE iRet; - - pError = hb_errNew(); - hb_errPutGenCode( pError, uiGenCode ); - hb_errPutSubCode( pError, uiSubCode ); - hb_errPutDescription( pError, hb_langDGetErrorDesc( uiGenCode ) ); - if( filename ) - hb_errPutFileName( pError, filename ); - if( uiFlags ) - hb_errPutFlags( pError, uiFlags ); - iRet = SELF_ERROR( ( AREAP ) pArea, pError ); - hb_errRelease( pError ); - return iRet; -} - -static ERRCODE hb_cdxOrdListClear( CDXAREAP pArea, int iComplete, LPCDXINDEX pKeepIndex ) -{ - LPCDXINDEX pIndex, pLastIndex, pNextIndex; - - HB_TRACE(HB_TR_DEBUG, ("hb_cdxOrdListClear(%p, %i)", pArea, iComplete)); - /* Commit changes first */ - if( FAST_GOCOLD( ( AREAP ) pArea ) == FAILURE ) - return FAILURE; - if ( pArea->lpIndexes ) { - if ( !iComplete ) { - PHB_FNAME pFileNameDbf, pFileNameCdx; - pFileNameDbf = hb_fsFNameSplit( pArea->szDataFileName ); - pFileNameCdx = hb_fsFNameSplit( pArea->lpIndexes->szFileName ); - if ( hb_stricmp( pFileNameDbf->szName, pFileNameCdx->szName ) != 0 ) - iComplete = 1; - hb_xfree( pFileNameDbf ); - hb_xfree( pFileNameCdx ); - } - /* - if ( iComplete ) { - while( pArea->lpIndexes ) - { - pIndex = pArea->lpIndexes; - pArea->lpIndexes = pArea->lpIndexes->pNext; - hb_cdxIndexFree( pIndex ); - } - pArea->lpIndexes = NULL; - } - else - { - LPCDXINDEX pMasterIndex; - pMasterIndex = pArea->lpIndexes; - while( pMasterIndex->pNext ) - { - pIndex = pMasterIndex->pNext; - pMasterIndex->pNext = pIndex->pNext; - hb_cdxIndexFree( pIndex ); - } - } - */ - if ( iComplete ) { - pLastIndex = NULL; - pNextIndex = pArea->lpIndexes; - } - else - { - pLastIndex = pArea->lpIndexes; - pNextIndex = pLastIndex->pNext; - } - while( pNextIndex ) - { - pIndex = pNextIndex; - pNextIndex = pNextIndex->pNext; - if ( pKeepIndex && ( pKeepIndex == pIndex ) ) { - pLastIndex = pIndex; - } - else - { - hb_cdxIndexFree( pIndex ); - if ( pLastIndex ) { - pLastIndex->pNext = pNextIndex; - } - else - { - pArea->lpIndexes = pNextIndex; - } - } - } - } - return SUCCESS; -} - -/* - * This was just for debugging - * */ -static void hb_cdxErrInternal( char * szMsg ) -{ - char * p = NULL; - hb_errInternal( 9201, szMsg ? szMsg : "hb_cdxErrInternal: data integrity error.", "", "" ); - *p = '\0'; -} - - - -static long hb_cdxDBOIKeyCount( CDXAREAP pArea, LPCDXTAG pTag, int iFilters ) -{ - LPCDXKEYINFO pCurKey; - /* LPCDXTAG pTag; */ - LPCDXPAGEINFO pPage1, pPage2; - /* long lKeyCount = 0; */ - ULONG lKeyCount = 0; - - pTag = hb_cdxGetActiveTag( pArea ); - - if ( iFilters && ! pArea->dbfi.itmCobExpr ) - iFilters = 0; - - if( iFilters ) - { - /* TODO: Skip movement may move child areas to first related record */ - PHB_ITEM pRecNo; - ULONG ulRec; - pRecNo = hb_itemPutNL( NULL, 0 ); - SELF_RECNO( ( AREAP ) pArea, pRecNo ); - ulRec = hb_itemGetNL( pRecNo ); - hb_itemRelease( pRecNo ); - - SELF_GOTOP( ( AREAP ) pArea ); - while( !( ( AREAP ) pArea )->fEof ) - { - lKeyCount++; - SELF_SKIP( ( AREAP ) pArea, 1 ); - } - SELF_GOTO( ( AREAP ) pArea, ulRec ); - } - else if( pTag ) - { - hb_cdxIndexLockRead( pTag->pIndex, pTag ); - pCurKey = hb_cdxKeyNew(); - pCurKey = hb_cdxKeyCopy( pCurKey, pTag->CurKeyInfo ); - - if( pTag->topScope || pTag->bottomScope ) - { - hb_cdxTagTagOpen( pTag, 0 ); - if( pTag->topScope ) - hb_cdxTagKeyFind( pTag, pTag->topScopeKey ); - else - hb_cdxTagKeyRead( pTag, TOP_RECORD ); - while( !pTag->TagEOF && hb_cdxBottomScope( pTag, pTag->CurKeyInfo ) ) - { - lKeyCount++; - hb_cdxTagKeyRead( pTag, NEXT_RECORD ); - } - } - else - { - hb_cdxTagTagOpen( pTag, 0 ); - hb_cdxTagKeyRead( pTag, TOP_RECORD ); - - pPage1 = pTag->RootPage; - while ( pPage1->Child ) - pPage1 = pPage1->Child; - - lKeyCount = pPage1->uiKeys; - if ( pPage1->Right != -1 ) - { - pPage2 = hb_cdxPageNew( pTag, 0, 0 ); - pPage2->Page = pPage1->Right; - while ( pPage2->Page != -1 ) - { - hb_cdxTagPageLoad( pTag, pPage2, 1); - lKeyCount += pPage2->uiKeys; - pPage2->Page = pPage2->Right; - } - hb_cdxPageFree( pPage2 ); - } - } - hb_cdxTagKeyFind( pTag, pCurKey ); - /* hb_cdxTagTagClose( pTag ); */ - hb_cdxKeyFree( pCurKey ); - hb_cdxIndexUnLockRead( pTag->pIndex, pTag ); - } - else /* no filter, no order */ - { - // ULONG ulRecCount = 0; - // SELF_RECCOUNT( ( AREAP ) pArea, &ulRecCount ); - // lKeyCount = ulRecCount; - SELF_RECCOUNT( ( AREAP ) pArea, &lKeyCount ); - } - return lKeyCount; -} - -/* -static long hb_cdxDBOIKeyNo( CDXAREAP pArea ) -{ - LPKEYINFO pNewKey; - LPCDXTAG pTag; - long lKeyNo = 0; - - pTag = hb_cdxGetActiveTag( pArea->lpIndexes ); - - if( pTag && !pArea->fEof && pTag->CurKeyInfo && ((ULONG) pTag->CurKeyInfo->Tag == pArea->ulRecNo) ) - { - pNewKey = hb_cdxKeyNew(); - pNewKey = hb_cdxKeyCopy( pNewKey, pTag->CurKeyInfo ); - hb_cdxTagTagOpen( pTag, 0 ); - hb_cdxTagKeyFind( pTag, pNewKey ); - while( !pTag->TagBOF && !pTag->TagEOF) - { - lKeyNo++; - hb_cdxTagKeyRead( pTag, PREV_RECORD ); - } - hb_cdxTagKeyFind( pTag, pNewKey ); - hb_cdxTagTagClose( pTag ); - hb_cdxKeyFree( pNewKey ); - } - return lKeyNo; -} -*/ - -static long hb_cdxDBOIKeyNo( CDXAREAP pArea, LPCDXTAG pTag, int iFilters ) -{ - LPCDXKEYINFO pCurKey; - /* LPCDXTAG pTag; */ - LPCDXPAGEINFO pPage1, pPage2; - long lKeyNo = 0; - - pTag = hb_cdxGetActiveTag( pArea ); - - if ( iFilters && ! pArea->dbfi.itmCobExpr ) - iFilters = 0; - - if( pArea->fEof ) - lKeyNo = 0; - else if( pTag && ( !pTag->CurKeyInfo || ((ULONG) pTag->CurKeyInfo->Tag != pArea->ulRecNo) ) ) - lKeyNo = 0; - else if( iFilters ) - { - /* TODO: Skip movement may move child areas to first related record */ - PHB_ITEM pRecNo; - ULONG ulRec; - pRecNo = hb_itemPutNL( NULL, 0 ); - SELF_RECNO( ( AREAP ) pArea, pRecNo ); - ulRec = hb_itemGetNL( pRecNo ); - hb_itemRelease( pRecNo ); - do - { - lKeyNo++; - SELF_SKIP( ( AREAP ) pArea, -1 ); - } while( !( ( AREAP ) pArea )->fBof ); - SELF_GOTO( ( AREAP ) pArea, ulRec ); - } - else if( pTag ) - /* if( pTag && !pArea->fEof && pTag->CurKeyInfo && ((ULONG) pTag->CurKeyInfo->Tag == pArea->ulRecNo) ) */ - { - hb_cdxIndexLockRead( pTag->pIndex, pTag ); - pCurKey = hb_cdxKeyNew(); - pCurKey = hb_cdxKeyCopy( pCurKey, pTag->CurKeyInfo ); - if( pTag->topScope || pTag->bottomScope ) - { - hb_cdxTagTagOpen( pTag, 0 ); - hb_cdxTagKeyFind( pTag, pCurKey ); - if ( hb_cdxTopScope( pTag, pTag->CurKeyInfo ) && hb_cdxBottomScope( pTag, pTag->CurKeyInfo ) ) - { - while( !pTag->TagBOF && !pTag->TagEOF && hb_cdxTopScope( pTag, pTag->CurKeyInfo ) ) - { - lKeyNo++; - hb_cdxTagKeyRead( pTag, PREV_RECORD ); - } - } - } - else - { - hb_cdxTagTagOpen( pTag, 0 ); - hb_cdxTagKeyFind( pTag, pCurKey ); - if ( !pTag->TagBOF && !pTag->TagEOF ) { - pPage1 = pTag->RootPage; - while ( pPage1->Child ) - pPage1 = pPage1->Child; - if ( pTag->AscendKey ) - { - lKeyNo = pPage1->CurKey + 1; - if ( pPage1->Left != -1 ) - { - pPage2 = hb_cdxPageNew( pTag, 0, 0 ); - pPage2->Page = pPage1->Left; - while ( pPage2->Page != -1 ) - { - hb_cdxTagPageLoad( pTag, pPage2, 1); - lKeyNo += pPage2->uiKeys; - pPage2->Page = pPage2->Left; - } - hb_cdxPageFree( pPage2 ); - } - } - else - { - lKeyNo = pPage1->uiKeys - pPage1->CurKey; - if ( pPage1->Right != -1 ) - { - pPage2 = hb_cdxPageNew( pTag, 0, 0 ); - pPage2->Page = pPage1->Right; - while ( pPage2->Page != -1 ) - { - hb_cdxTagPageLoad( pTag, pPage2, 1); - lKeyNo += pPage2->uiKeys; - pPage2->Page = pPage2->Right; - } - hb_cdxPageFree( pPage2 ); - } - } - } - } - hb_cdxTagKeyFind( pTag, pCurKey ); - /*hb_cdxTagTagClose( pTag ); */ - hb_cdxKeyFree( pCurKey ); - hb_cdxIndexUnLockRead( pTag->pIndex, pTag ); - } - else - { - PHB_ITEM pRecNo; - pRecNo = hb_itemPutNL( NULL, 0 ); - SELF_RECNO( ( AREAP ) pArea, pRecNo ); - lKeyNo = hb_itemGetNL( pRecNo ); - hb_itemRelease( pRecNo ); - } - return lKeyNo; -} - -/* begin of cleanup --------------------------------------------------------------------------------- */ - -/* - * -- DBFCDX METHODS -- - */ - -HB_FUNC( _DBFCDX ) -{ -} - -HB_FUNC( DBFCDX_GETFUNCTABLE ) -{ - RDDFUNCS * pTable; - USHORT * uiCount; - - uiCount = ( USHORT * ) hb_itemGetPtr( hb_param( 1, HB_IT_POINTER ) ); - * uiCount = RDDFUNCSCOUNT; - pTable = ( RDDFUNCS * ) hb_itemGetPtr( hb_param( 2, HB_IT_POINTER ) ); - - HB_TRACE(HB_TR_DEBUG, ("DBFCDX_GETFUNCTABLE(%i, %p)", uiCount, pTable)); - - if( pTable ) - hb_retni( hb_rddInherit( pTable, &cdxTable, &cdxSuper, ( BYTE * ) "DBF" ) ); - else - hb_retni( FAILURE ); -} - -/* #include "cdxrdd.c" */ -/* - * -- DBFCDX METHODS -- - */ -/* begin of cdxrdd.c */ - -// ( DBENTRYP_BP ) hb_cdxBof : NULL -// ( DBENTRYP_BP ) hb_cdxEof : NULL -// ( DBENTRYP_BP ) hb_cdxFound : NULL - -// ( DBENTRYP_V ) hb_cdxGoBottom -ERRCODE hb_cdxGoBottom( CDXAREAP pArea ) -{ - LPCDXTAG pTag; - HB_TRACE(HB_TR_DEBUG, ("cdxGoBottom(%p)", pArea)); - - // if( SELF_GOCOLD( ( AREAP ) pArea ) == FAILURE ) - if( FAST_GOCOLD( ( AREAP ) pArea ) == FAILURE ) - return FAILURE; - - /*must change to follow ordSetFocus() - done?*/ - pTag = hb_cdxGetActiveTag( pArea ); - - if( ! pTag ) - SUPER_GOBOTTOM( ( AREAP ) pArea ); - else - { - hb_cdxIndexLockRead( pTag->pIndex, pTag ); - hb_cdxTagTagOpen( pTag, 0 ); - if( pTag->bottomScope ) - { - hb_cdxSeek( pArea, 1, pTag->bottomScope, 1 ); - if (! pArea->fEof ) - SELF_GOTO( ( AREAP ) pArea, pTag->CurKeyInfo->Tag ); - } - else - { - hb_cdxTagKeyRead( pTag, BTTM_RECORD ); - SELF_GOTO( ( AREAP ) pArea, pTag->CurKeyInfo->Tag ); - } - hb_cdxIndexUnLockRead( pTag->pIndex, pTag ); - } - return SELF_SKIPFILTER( ( AREAP ) pArea, -1 ); -} - - -// ( DBENTRYP_UL ) hb_cdxGoTo -/* - * Position cursor at a specific physical record. - */ -ERRCODE hb_cdxGoTo( CDXAREAP pArea, ULONG ulRecNo ) -{ - LPCDXKEYINFO pKey; - HB_MACRO_PTR pMacro; - LONG lRecno; - LPCDXTAG pTag; - - HB_TRACE(HB_TR_DEBUG, ("hb_cdxGoTo(%p, %lu)", pArea, ulRecNo)); - - if( FAST_GOCOLD( ( AREAP ) pArea ) == FAILURE ) - return FAILURE; - - if( SUPER_GOTO( ( AREAP ) pArea, ulRecNo ) == FAILURE ) - return FAILURE; - - if( pArea->fEof ) - /* return FAILURE; */ - return SUCCESS; - - pTag = hb_cdxGetActiveTag( pArea ); - if( ! pTag ) - return SUCCESS; - - if( !pTag->CurKeyInfo || (ULONG) pTag->CurKeyInfo->Tag != ulRecNo ) - { - pKey = hb_cdxKeyNew(); - - if( hb_itemType( pTag->pKeyItem ) == HB_IT_BLOCK ) - { - hb_vmPushSymbol( &hb_symEval ); - hb_vmPush( pTag->pKeyItem ); - hb_vmSend( 0 ); - hb_cdxKeyPutItem( pKey, &(HB_VM_STACK.Return) ); - } - else - { - pMacro = ( HB_MACRO_PTR ) hb_itemGetPtr( pTag->pKeyItem ); - // hb_macroRun( pMacro ); - hb_cdxMacroRun( (AREAP) pArea, pMacro ); - hb_cdxKeyPutItem( pKey, hb_stackItemFromTop( - 1 ) ); - hb_stackPop(); - } - pKey->Tag = pArea->ulRecNo; - - hb_cdxIndexLockRead( pTag->pIndex, pTag ); - lRecno = hb_cdxTagKeyFind( pTag, pKey ); - hb_cdxIndexUnLockRead( pTag->pIndex, pTag ); - pArea->fEof = pTag->TagEOF; - pArea->fBof = pTag->TagBOF; - - if( lRecno > 0 ) - { - if( ( ULONG ) lRecno == pArea->ulRecNo ) - { - hb_cdxKeyFree( pKey ); - return SUCCESS; - } - else - { - /* if( !pTag->UniqueKey && !pTag->TagEOF ) */ - if( !pTag->TagEOF ) - { - hb_cdxIndexLockRead( pTag->pIndex, pTag ); - while( !pTag->TagEOF && pTag->CurKeyInfo->Tag != lRecno && - !hb_cdxKeyCompare( pKey, pTag->CurKeyInfo, TRUE ) ) - hb_cdxTagKeyRead( pTag, NEXT_RECORD ); - hb_cdxIndexUnLockRead( pTag->pIndex, pTag ); - pArea->fEof = pTag->TagEOF; - pArea->fBof = pTag->TagBOF; - } - } - } - else - { - /* Need fixed !!!!!! */ - /* Error Index */ - } - hb_cdxKeyFree( pKey ); - } - - return SUCCESS; /* ???? m.b FAILURE */ -} - - -// ( DBENTRYP_I ) hb_cdxGoToId : NULL -/* - * Position the cursor to a specific, physical identity. - */ -/* -ERRCODE hb_cdxGoToId( CDXAREAP pArea, PHB_ITEM pItem ) -{ - PHB_ITEM pError; - - HB_TRACE(HB_TR_DEBUG, ("hb_cdxGoToId(%p, %p)", pArea, pItem)); - - if( HB_IS_NUMERIC( pItem ) ) - return SELF_GOTO( ( AREAP ) pArea, hb_itemGetNL( pItem ) ); - else - { - pError = hb_errNew(); - hb_errPutGenCode( pError, EG_DATATYPE ); - hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_DATATYPE ) ); - hb_errPutSubCode( pError, EDBF_DATATYPE ); - SELF_ERROR( ( AREAP ) pArea, pError ); - hb_errRelease( pError ); - return FAILURE; - } -} -*/ - -// ( DBENTRYP_V ) hb_cdxGoTop -ERRCODE hb_cdxGoTop( CDXAREAP pArea ) -{ - LPCDXTAG pTag; - - HB_TRACE(HB_TR_DEBUG, ("cdxGoTop(%p)", pArea)); - - if( FAST_GOCOLD( ( AREAP ) pArea ) == FAILURE ) - return FAILURE; - - /*must change to follow ordSetFocus(), done?*/ - pTag = hb_cdxGetActiveTag( pArea ); - - if( ! pTag ) - SUPER_GOTOP( ( AREAP ) pArea ); - else - { - hb_cdxIndexLockRead( pTag->pIndex, pTag ); - hb_cdxTagTagOpen( pTag, 0 ); - if( pTag->topScope ) - hb_cdxSeek( pArea, 1, pTag->topScope, 0); - else - hb_cdxTagKeyRead( pTag, TOP_RECORD ); - /* - if( !hb_cdxTopScope( pTag, pTag->CurKeyInfo ) || - !hb_cdxBottomScope( pTag, pTag->CurKeyInfo ) ) - hb_cdxGoEof( pArea ); - else - */ - SELF_GOTO( ( AREAP ) pArea, pTag->CurKeyInfo->Tag ); - hb_cdxIndexUnLockRead( pTag->pIndex, pTag ); - } - - return SELF_SKIPFILTER( ( AREAP ) pArea, 1 ); -} - - -// ( DBENTRYP_BIB ) hb_cdxSeek -ERRCODE hb_cdxSeek( CDXAREAP pArea, BOOL bSoftSeek, PHB_ITEM pKey, BOOL bFindLast ) -{ - PHB_ITEM pError; - ERRCODE retvalue; - LPCDXTAG pTag = hb_cdxGetActiveTag( pArea ); - - HB_TRACE(HB_TR_DEBUG, ("cdxSeek(%p, %d, %p, %d)", pArea, bSoftSeek, pKey, bFindLast)); - - if( FAST_GOCOLD( ( AREAP ) pArea ) == FAILURE ) - return FAILURE; - - if( ! pTag ) - { - pError = hb_errNew(); - hb_errPutGenCode( pError, EG_NOORDER ); - hb_errPutSubCode( pError, 1020 ); - hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_NOORDER ) ); - hb_errPutFlags( pError, EF_CANDEFAULT ); - SELF_ERROR( ( AREAP ) pArea, pError ); - hb_errRelease( pError ); - return FAILURE; - } - else - { - LONG lRecno; - LPCDXKEYINFO pKey2; - - pKey2 = hb_cdxKeyNew(); - hb_cdxKeyPutItem( pKey2, pKey ); - if ( !pTag->AscendKey ) - { - if ( bFindLast ) - bFindLast = 0; - else - bFindLast = 1; - } - if( bFindLast ) - pKey2->Tag = CDX_MAX_REC_NUM; - else - pKey2->Tag = CDX_IGNORE_REC_NUM; - pKey2->Xtra = 0; - - hb_cdxIndexLockRead( pTag->pIndex, pTag ); - - lRecno = hb_cdxTagKeyFind( pTag, pKey2 ); - pArea->fEof = pTag->TagEOF; - pArea->fBof = pTag->TagBOF; - - if( lRecno > 0 ) - { - switch( pTag->uiType ) - { - case 'C': - { - /* fix for key trimming*/ - if( (USHORT) pKey->item.asString.length > pTag->uiLen) - { - lRecno = 0; - pTag->TagEOF = 1; - } - break; - } - } - } - - if( lRecno > 0 ) - { - retvalue = SELF_GOTO( ( AREAP ) pArea, pTag->CurKeyInfo->Tag ); - pArea->fFound = TRUE; - if( retvalue != FAILURE ) - if ( hb_set.HB_SET_DELETED || pArea->dbfi.itmCobExpr != NULL ) - { - int k; - if( bFindLast ) - retvalue = SELF_SKIPFILTER( ( AREAP ) pArea, -1 ); - else - retvalue = SELF_SKIPFILTER( ( AREAP ) pArea, 1 ); - if ( pArea->fEof ) { - pArea->fFound = FALSE; - } - else - { - k = hb_cdxKeyCompare( pKey2, pTag->CurKeyInfo, FALSE ); - if ( k == 0) - { - pArea->fFound = TRUE; - } - else - { - pArea->fFound = FALSE; - if( !bSoftSeek ) - { - retvalue = hb_cdxGoEof( pArea ); - } - } - } - } - hb_cdxKeyFree( pKey2 ); - } - else - { - hb_cdxKeyFree( pKey2 ); - - if ( pTag->uiType == 'C' && pKey->item.asString.length == 0 ) - { - retvalue = SELF_GOTOP( (AREAP) pArea); - pArea->fFound = TRUE; - } - else - { - pArea->fFound = FALSE; - - if( bSoftSeek && !pTag->TagEOF ) - { - retvalue = SELF_GOTO( ( AREAP ) pArea, pTag->CurKeyInfo->Tag ); - if( retvalue != FAILURE ) - if ( hb_set.HB_SET_DELETED || pArea->dbfi.itmCobExpr != NULL ) - { - if( bFindLast ) - retvalue = SELF_SKIPFILTER( ( AREAP ) pArea, -1 ); - else - retvalue = SELF_SKIPFILTER( ( AREAP ) pArea, 1 ); - } - } - else - { - retvalue = hb_cdxGoEof( pArea ); - } - } - } - if( !hb_cdxTopScope( pTag, pTag->CurKeyInfo ) || - !hb_cdxBottomScope( pTag, pTag->CurKeyInfo ) ) - hb_cdxGoEof( pArea ); - - hb_cdxIndexUnLockRead( pTag->pIndex, pTag ); - return retvalue; - } -} - -// ( DBENTRYP_L ) hb_cdxSkip : NULL -// ( DBENTRYP_L ) hb_cdxSkipFilter : NULL - -// ( DBENTRYP_L ) hb_cdxSkipRaw -ERRCODE hb_cdxSkipRaw( CDXAREAP pArea, LONG lToSkip ) -{ - LPCDXTAG pTag; - - HB_TRACE(HB_TR_DEBUG, ("cdxSkipRaw(%p, %ld)", pArea, lToSkip)); - - if( FAST_GOCOLD( ( AREAP ) pArea ) == FAILURE ) - return FAILURE; - - /*must change to follow ordSetFocus()*/ - pTag = hb_cdxGetActiveTag( pArea ); - - if( ! pTag ) - SUPER_SKIPRAW( ( AREAP ) pArea, lToSkip ); - else - { - hb_cdxIndexLockRead( pTag->pIndex, pTag ); - - if( pArea->fBof && !pArea->fEof ) - SELF_GOTOP( ( AREAP ) pArea ); - - if( lToSkip == 0 ) - { - SUPER_SKIPRAW( ( AREAP ) pArea, 0 ); - } - - else if( lToSkip > 0 ) - { - if( !pArea->fEof ) - { - while( !pTag->TagEOF && lToSkip-- > 0 ) - { - hb_cdxTagKeyRead( pTag, NEXT_RECORD ); - if ( !pTag->TagEOF ) { - if( !hb_cdxTopScope( pTag, pTag->CurKeyInfo ) ) - hb_cdxSeek( pArea, 1, pTag->topScope, 0 ); - else if( !hb_cdxBottomScope( pTag, pTag->CurKeyInfo ) ) - pTag->TagEOF = TRUE; - } - } - - if( !pTag->TagEOF ) - SELF_GOTO( ( AREAP ) pArea, pTag->CurKeyInfo->Tag ); - else - { - hb_cdxGoEof( pArea ); - } - } - } - else /* ( lToSkip < 0 ) */ - { - if( pArea->fEof ) - { - SELF_GOBOTTOM( ( AREAP ) pArea ); - lToSkip++; - } - pTag->TagBOF = FALSE; - while( !pTag->TagBOF && lToSkip++ < 0 ) - { - hb_cdxTagKeyRead( pTag, PREV_RECORD ); - if ( !pTag->TagBOF ) { - if( !hb_cdxTopScope( pTag, pTag->CurKeyInfo ) ) - { - hb_cdxSeek( pArea, 1, pTag->topScope, 0 ); - pTag->TagBOF = TRUE; - } - else if( !hb_cdxBottomScope( pTag, pTag->CurKeyInfo ) ) - hb_cdxSeek( pArea, 1, pTag->bottomScope, 1 ); - } - } - - if( !pTag->TagBOF ) - SELF_GOTO( ( AREAP ) pArea, pTag->CurKeyInfo->Tag ); - else - { - pTag->TagBOF = FALSE; - SELF_GOTOP( ( AREAP ) pArea ); - pArea->fBof = pTag->TagBOF = TRUE; - } - } - hb_cdxIndexUnLockRead( pTag->pIndex, pTag ); - } - - /* return SELF_SKIPFILTER( ( AREAP ) pArea, -1 ); */ - return SUCCESS; -} - - -// ( DBENTRYP_VF ) hb_cdxAddField : NULL -// ( DBENTRYP_B ) hb_cdxAppend : NULL -// ( DBENTRYP_I ) hb_cdxCreateFields : NULL -// ( DBENTRYP_V ) hb_cdxDeleteRec : NULL -// ( DBENTRYP_BP ) hb_cdxDeleted : NULL -// ( DBENTRYP_SP ) hb_cdxFieldCount : NULL -// ( DBENTRYP_VF ) hb_cdxFieldDisplay : NULL -// ( DBENTRYP_SSI ) hb_cdxFieldInfo : NULL -// ( DBENTRYP_SVP ) hb_cdxFieldName : NULL -// ( DBENTRYP_V ) hb_cdxFlush : NULL -// ( DBENTRYP_PP ) hb_cdxGetRec : NULL - -// ( DBENTRYP_SI ) hb_cdxGetValue -/* - * Obtain the current value of a field. - */ -ERRCODE hb_cdxGetValue( CDXAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) -{ - BOOL bDeleted; - - HB_TRACE(HB_TR_DEBUG, ("hb_cdxGetValue(%p, %hu, %p)", pArea, uiIndex, pItem)); - - if( pArea->lpFields[ uiIndex - 1 ].uiType == HB_IT_MEMO ) - { - /* Force read record */ - if( SELF_DELETED( ( AREAP ) pArea, &bDeleted ) == FAILURE ) - return FAILURE; -#ifdef XDBFCDX - hb_xfptGetMemo( pArea, uiIndex - 1, pItem ); -#else - hb_cdxGetMemo( pArea, uiIndex - 1, pItem ); + BYTE cTemp[8]; + LPCDXAREA pArea = pTag->pIndex->pArea; + LONG lStep = 0; + BOOL bDirectRead, bEnd; + PHB_ITEM pForItem, pWhileItem, pEvalItem; +#ifndef HB_CDP_SUPPORT_OFF + /* TODO: this hack is not thread safe, s_cdpage has to be thread specific */ + PHB_CODEPAGE cdpTmp = s_cdpage; + s_cdpage = pArea->cdPage; #endif - return SUCCESS; + + if ( ( pTag->OptFlags & CDX_TYPE_STRUCTURE ) || pTag->Custom ) + { + hb_cdxTagEmptyIndex( pTag ); } else - return SUPER_GETVALUE( ( AREAP ) pArea, uiIndex, pItem ); -} - -// ( DBENTRYP_SVL ) hb_cdxGetVarLen -/* - * Obtain the length of a field value. - */ -ERRCODE hb_cdxGetVarLen( CDXAREAP pArea, USHORT uiIndex, ULONG * pLength ) -{ - BOOL bDeleted; - - HB_TRACE(HB_TR_DEBUG, ("hb_cdxGetVarLen(%p, %hu, %p)", pArea, uiIndex, pLength)); - - /* Force read record */ - if( SELF_DELETED( ( AREAP ) pArea, &bDeleted ) == FAILURE ) - return FAILURE; - - if( pArea->fHasMemo ) - * pLength = hb_cdxGetMemoLen( pArea, uiIndex - 1 ); - else - * pLength = 0; - - return SUCCESS; -} - -// ( DBENTRYP_V ) hb_cdxGoCold -/* - * Perform a write of WorkArea memory to the data store. - */ -ERRCODE hb_cdxGoCold( CDXAREAP pArea ) -{ - LPCDXTAG pTag; - LPCDXKEYINFO pKey; - HB_MACRO_PTR pMacro; - USHORT uiTag; - BOOL bForOk, fInAppend; - PHB_ITEM pItem; // = NULL; - - HB_TRACE(HB_TR_DEBUG, ("hb_cdxGoCold(%p)", pArea)); - - if( pArea->fRecordChanged ) { - fInAppend = pArea->fAppend; - if( SUPER_GOCOLD( ( AREAP ) pArea ) == FAILURE ) - return FAILURE; - if( pArea->lpIndexes && pArea->lpIndexes->TagList ) + PHB_ITEM pSaveFilter; + BOOL bSaveDeleted; + bSaveDeleted = hb_set.HB_SET_DELETED; + hb_set.HB_SET_DELETED = FALSE; + pSaveFilter = pArea->dbfi.itmCobExpr; + pArea->dbfi.itmCobExpr = NULL; + + bDirectRead = TRUE; + if ( pArea->lpdbOrdCondInfo && !pArea->lpdbOrdCondInfo->fAll ) + bDirectRead = FALSE; + if ( pArea->lpdbRelations ) + bDirectRead = FALSE; + bEnd = FALSE; + if ( !bDirectRead ) { - pTag = pArea->lpIndexes->TagList; - hb_cdxIndexLockWrite( pTag->pIndex, pTag ); - uiTag = 1; - while( pTag ) + if ( !pArea->lpdbOrdCondInfo || pArea->lpdbOrdCondInfo->fAll || pArea->lpdbOrdCondInfo->fUseCurrent ) { + SELF_GOTOP( ( AREAP ) pArea ); + } + else { - if ( !pTag->Custom ) + if ( pArea->lpdbOrdCondInfo->lRecno ) { - /* test for expresion, working but not tested */ - if( pTag->pForItem != NULL ) - { - if( hb_itemType( pTag->pForItem ) == HB_IT_BLOCK ) - { - hb_vmPushSymbol( &hb_symEval ); - hb_vmPush( pTag->pForItem ); - hb_vmSend( 0 ); - bForOk = hb_itemGetL( &(HB_VM_STACK.Return) ); - } - else - { - pMacro = ( HB_MACRO_PTR ) hb_itemGetPtr( pTag->pForItem ); - // hb_macroRun( pMacro ); - hb_cdxMacroRun( (AREAP) pArea, pMacro ); - bForOk = hb_itemGetL( hb_stackItemFromTop( - 1 ) ); - hb_stackPop(); - } - } - else - bForOk = TRUE; - - pKey = hb_cdxKeyNew(); - - if ( pTag->nField ) - { - pItem = hb_itemNew( NULL ); - SELF_GETVALUE( ( AREAP ) pArea, pTag->nField, pItem ); - hb_cdxKeyPutItem( pKey, pItem ); - hb_itemRelease( pItem ); - // pItem = NULL; - } - else - { - if( hb_itemType( pTag->pKeyItem ) == HB_IT_BLOCK ) - { - hb_vmPushSymbol( &hb_symEval ); - hb_vmPush( pTag->pKeyItem ); - hb_vmSend( 0 ); - hb_cdxKeyPutItem( pKey, &(HB_VM_STACK.Return) ); - } - else - { - pMacro = ( HB_MACRO_PTR ) hb_itemGetPtr( pTag->pKeyItem ); - // hb_macroRun( pMacro ); - hb_cdxMacroRun( (AREAP) pArea, pMacro ); - hb_cdxKeyPutItem( pKey, hb_stackItemFromTop( - 1 ) ); - hb_stackPop(); - } - } - pKey->Tag = pArea->ulRecNo; - - if( fInAppend ) - { - if( bForOk ) - { - hb_cdxTagKeyAdd( pTag, pKey ); - pTag->RootPage->Changed = TRUE; - /* if( uiTag == pArea->lpIndexes->uiTag) */ - if( uiTag == pArea->uiTag) - hb_cdxTagTagStore( pTag ); - else - hb_cdxTagTagClose( pTag ); - } - } - else - { - if( hb_cdxKeyCompare( pKey, pTag->HotKey, TRUE ) ) - { - /* if( uiTag == pArea->lpIndexes->uiTag || */ - if( uiTag == pArea->uiTag || - hb_cdxTagKeyFind( pTag, pTag->HotKey ) > 0 ) - { - // hb_cdxPageDeleteKey( pTag->RootPage ); - if ( pTag->CurKeyInfo && (ULONG) pTag->CurKeyInfo->Tag == pArea->ulRecNo ) - hb_cdxPageKeyDelete( pTag->RootPage ); - } - - if( bForOk ) - hb_cdxTagKeyAdd( pTag, pKey ); - - pTag->RootPage->Changed = TRUE; - - if( uiTag == pArea->uiTag) - hb_cdxTagTagStore( pTag ); - else - hb_cdxTagTagClose( pTag ); - } - else - { - if( bForOk ) - { - if( uiTag != pArea->uiTag ) - hb_cdxTagKeyFind( pTag, pTag->HotKey ); - if ( !pTag->CurKeyInfo || (ULONG) pTag->CurKeyInfo->Tag != pArea->ulRecNo ) - { - hb_cdxTagKeyAdd( pTag, pKey ); - pTag->RootPage->Changed = TRUE; - if( uiTag == pArea->uiTag) - hb_cdxTagTagStore( pTag ); - else - hb_cdxTagTagClose( pTag ); - } - } - else - { - if (uiTag != pArea->uiTag) - hb_cdxTagKeyFind( pTag, pTag->HotKey ); - if ( pTag->CurKeyInfo && (ULONG) pTag->CurKeyInfo->Tag == pArea->ulRecNo ) - { - // hb_cdxPageDeleteKey( pTag->RootPage ); - hb_cdxPageKeyDelete( pTag->RootPage ); - pTag->RootPage->Changed = TRUE; - if( uiTag == pArea->uiTag) - hb_cdxTagTagStore( pTag ); - else - hb_cdxTagTagClose( pTag ); - } - } - } - } - - hb_cdxKeyFree( pKey ); - - if( pTag->HotKey ) - { - hb_cdxKeyFree( pTag->HotKey ); - pTag->HotKey = NULL; - } + SELF_GOTO( ( AREAP ) pArea, pArea->lpdbOrdCondInfo->lRecno ); + bEnd = TRUE; } - /* pTag = pTag->pNext; */ - if ( pTag->pNext ) - pTag = pTag->pNext; else { - hb_cdxIndexUnLockWrite ( pTag->pIndex, pTag ); - if ( pTag->pIndex->pNext ) - { - pTag = pTag->pIndex->pNext->TagList; - hb_cdxIndexLockWrite ( pTag->pIndex, pTag ); - } - else - pTag = NULL; + SELF_GOTO( ( AREAP ) pArea, pArea->lpdbOrdCondInfo->lStartRecno ); } - ++uiTag; } } - } - - return SUCCESS; -} - -// ( DBENTRYP_V ) hb_cdxGoHot -/* - * Mark the WorkArea data buffer as hot. - */ -ERRCODE hb_cdxGoHot( CDXAREAP pArea ) -{ - LPCDXTAG pTag; - /* USHORT uiTag; */ - LPCDXKEYINFO pKey; - HB_MACRO_PTR pMacro; - - HB_TRACE(HB_TR_DEBUG, ("hb_cdxGoHot(%p)", pArea)); - - if( SUPER_GOHOT( ( AREAP ) pArea ) == FAILURE ) - return FAILURE; - - if( pArea->lpIndexes && pArea->lpIndexes->TagList ) - { - pTag = pArea->lpIndexes->TagList; - /* uiTag = 1; */ - while( pTag ) + pSort = hb_cdxSortNew( pTag, pTag->UniqueKey ); + pItem = hb_itemNew( NULL ); + ulRecCount = pArea->ulRecCount; + pForItem = pTag->pForItem; + bForOk = TRUE; + pEvalItem = ( pArea->lpdbOrdCondInfo ? pArea->lpdbOrdCondInfo->itmCobEval : NULL); + pWhileItem = ( pArea->lpdbOrdCondInfo ? pArea->lpdbOrdCondInfo->itmCobWhile : NULL); + for ( ulRecNo = 1; ulRecNo <= ulRecCount; ulRecNo++ ) { - if ( !pTag->Custom ) + if ( bDirectRead ) { - pKey = hb_cdxKeyNew(); - if( hb_itemType( pTag->pKeyItem ) == HB_IT_BLOCK ) + hb_fsSeek( pArea->hDataFile, + pArea->uiHeaderLen + + ( ulRecNo - 1 ) * pArea->uiRecordLen, + FS_SET ); + hb_fsRead( pArea->hDataFile, + pArea->pRecord, + pArea->uiRecordLen ); + pArea->ulRecNo = ulRecNo; + pArea->fDeleted = ( pArea->pRecord[ 0 ] == '*' ); + } + else if ( pWhileItem && !hb_cdxEvalCond ( NULL, pWhileItem, 0 ) ) + break; + + if ( pForItem != NULL ) + { + bForOk = hb_cdxEvalCond ( pArea, pForItem, FALSE ); + } + + if ( bForOk ) + { + if ( pTag->nField ) + { + SELF_GETVALUE( ( AREAP ) pArea, pTag->nField, pItem ); + } + else if ( hb_itemType( pTag->pKeyItem ) == HB_IT_BLOCK ) { hb_vmPushSymbol( &hb_symEval ); hb_vmPush( pTag->pKeyItem ); hb_vmSend( 0 ); - hb_cdxKeyPutItem( pKey, &(HB_VM_STACK.Return) ); + hb_itemCopy( pItem, &(HB_VM_STACK.Return) ); } else { pMacro = ( HB_MACRO_PTR ) hb_itemGetPtr( pTag->pKeyItem ); - // hb_macroRun( pMacro ); - hb_cdxMacroRun( (AREAP) pArea, pMacro ); - hb_cdxKeyPutItem( pKey, hb_stackItemFromTop( - 1 ) ); + hb_macroRun( pMacro ); + hb_itemCopy( pItem, hb_stackItemFromTop( -1 ) ); hb_stackPop(); } - pKey->Tag = pArea->ulRecNo; - pTag->HotKey = pKey; - } - /* pTag = pTag->pNext; */ - if ( pTag->pNext ) - pTag = pTag->pNext; - else - { - if ( pTag->pIndex->pNext ) - pTag = pTag->pIndex->pNext->TagList; - else - pTag = NULL; - } - /* ++uiTag; */ - } - } - return SUCCESS; -} - -// ( DBENTRYP_P ) hb_cdxPutRec : NULL - -// ( DBENTRYP_SI ) hb_cdxPutValue -/* - * Assign a value to a field. - */ -ERRCODE hb_cdxPutValue( CDXAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) -{ - BOOL bDeleted; - PHB_ITEM pError; - - HB_TRACE(HB_TR_DEBUG, ("hb_cdxPutValue(%p, %hu, %p)", pArea, uiIndex, pItem)); - - if( pArea->lpFields[ uiIndex - 1 ].uiType == HB_IT_MEMO ) - { -#ifndef XDBFCDX - if( HB_IS_MEMO( pItem ) || HB_IS_STRING( pItem ) ) - { -#endif - /* Force read record */ - if( SELF_DELETED( ( AREAP ) pArea, &bDeleted ) == FAILURE ) - return FAILURE; - - if( !pArea->fPositioned ) - return SUCCESS; - - /* Buffer is hot? */ - if( !pArea->fRecordChanged && SELF_GOHOT( ( AREAP ) pArea ) == FAILURE ) - return FAILURE; - - if( !hb_cdxPutMemo( pArea, uiIndex - 1, pItem ) ) - { - pError = hb_errNew(); - hb_errPutGenCode( pError, EG_DATAWIDTH ); - hb_errPutDescription( pError, hb_langDGetErrorDesc( EDBF_DATAWIDTH ) ); - hb_errPutSubCode( pError, EDBF_DATAWIDTH ); - SELF_ERROR( ( AREAP ) pArea, pError ); - hb_errRelease( pError ); - return FAILURE; - } - - /* Update deleted flag */ - pArea->pRecord[ 0 ] = (BYTE) (pArea->fDeleted ? '*' : ' '); - return SUCCESS; -#ifndef XDBFCDX - } -#endif - } - return SUPER_PUTVALUE( ( AREAP ) pArea, uiIndex, pItem); -} - - -// ( DBENTRYP_V ) hb_cdxRecall : NULL -// ( DBENTRYP_ULP ) hb_cdxRecCount : NULL -// ( DBENTRYP_ISI ) hb_cdxRecInfo : NULL -// ( DBENTRYP_I ) hb_cdxRecNo : NULL -// ( DBENTRYP_S ) hb_cdxSetFieldExtent : NULL -// ( DBENTRYP_P ) hb_cdxAlias : NULL - -// ( DBENTRYP_V ) hb_cdxClose -/* - * Close the table in the WorkArea. - */ -ERRCODE hb_cdxClose( CDXAREAP pArea ) -{ - ERRCODE uiError; - - HB_TRACE(HB_TR_DEBUG, ("hb_cdxClose(%p)", pArea)); - - if( FAST_GOCOLD( ( AREAP ) pArea ) == FAILURE ) - return FAILURE; - - /* Close all index */ - /* SELF_ORDLSTCLEAR( ( AREAP ) pArea ); */ - hb_cdxOrdListClear( pArea, 1, 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; - } - uiError = SUPER_CLOSE( ( AREAP ) pArea ); - return uiError; -} - - -// ( DBENTRYP_VP ) hb_cdxCreate : NULL - -// ( DBENTRYP_SI ) hb_cdxInfo -/* - * Retrieve information about the current driver. - */ -ERRCODE hb_cdxInfo( CDXAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) -{ - HB_TRACE(HB_TR_DEBUG, ("hb_cdxInfo(%p, %hu, %p)", pArea, uiIndex, pItem)); - - switch( uiIndex ) - { - case DBI_MEMOEXT: - hb_itemPutC( pItem, CDX_MEMOEXT ); - break; - - case DBI_MEMOBLOCKSIZE: - hb_itemPutNI( pItem, pArea->uiMemoBlockSize ); - break; - - /* case DBI_RDD_VERSION */ - - default: - return SUPER_INFO( ( AREAP ) pArea, uiIndex, pItem ); - } - - return SUCCESS; -} - -// ( DBENTRYP_V ) hb_cdxNewArea : NULL - -// ( DBENTRYP_VP ) hb_cdxOpen -/* - * Open a data store in the WorkArea. - */ -ERRCODE hb_cdxOpen( CDXAREAP pArea, LPDBOPENINFO pOpenInfo ) -{ - char * szFileName; - DBORDERINFO pExtInfo; - PHB_FNAME pFileName; - DBORDERINFO pOrderInfo; -#ifdef __XHARBOUR__ - BYTE aFile[ _POSIX_PATH_MAX + 3 + 10 ]; -#endif - /* - USHORT uiFlags; - FHANDLE hFile; - */ - - HB_TRACE(HB_TR_DEBUG, ("hb_cdxOpen(%p, %p)", pArea, pOpenInfo)); - - /* Force exclusive mode - * 0: AUTOSHARE disabled. - * 1: AUTOSHARE enabled. - * 2: force exclusive mode. - * */ - if( hb_set.HB_SET_AUTOSHARE == 2 ) - pOpenInfo->fShared = FALSE; - - if( SUPER_OPEN( ( AREAP ) pArea, pOpenInfo ) == FAILURE ) - return FAILURE; - - /* Alloc root memo block and read data */ - if( pArea->fHasMemo ) - { - pArea->pMemoRoot = ( LPMEMOROOT ) hb_xgrab( sizeof( MEMOROOT ) ); - memset( pArea->pMemoRoot, 0, sizeof( MEMOROOT ) ); - hb_fsSeek( pArea->hMemoFile, 0, FS_SET ); - if( hb_fsRead( pArea->hMemoFile, ( BYTE * ) pArea->pMemoRoot, sizeof( MEMOROOT ) ) != - sizeof( MEMOROOT ) ) - return FAILURE; - if( pArea->pMemoRoot->szSignature[ 0 ] == 0 ) - { - strcpy( ( char * ) pArea->pMemoRoot->szSignature, "Harbour" ); - hb_fsSeek( pArea->hMemoFile, 0, FS_SET ); - hb_fsWrite( pArea->hMemoFile, ( BYTE * ) pArea->pMemoRoot, sizeof( MEMOROOT ) ); - } - pArea->pMemoRoot->ulNextBlock = hb_cdxSwapBytes( pArea->pMemoRoot->ulNextBlock ); - pArea->pMemoRoot->ulBlockSize = hb_cdxSwapBytes( pArea->pMemoRoot->ulBlockSize ); - } - - /* If SET_AUTOPEN open index */ - if( pArea->fHasTags && hb_set.HB_SET_AUTOPEN ) - { - pFileName = hb_fsFNameSplit( pArea->szDataFileName ); - szFileName = ( char * ) hb_xgrab( _POSIX_PATH_MAX + 3 ); - szFileName[ 0 ] = '\0'; - if( pFileName->szPath ) - strcpy ( szFileName, pFileName->szPath ); - - strncat( szFileName, pFileName->szName, _POSIX_PATH_MAX - - strlen( szFileName ) ); - - pExtInfo.itmResult = hb_itemPutC( NULL, "" ); - SELF_ORDINFO( ( AREAP ) pArea, DBOI_BAGEXT, &pExtInfo ); - strncat( szFileName, pExtInfo.itmResult->item.asString.value, _POSIX_PATH_MAX - - strlen( szFileName ) ); - hb_itemRelease( pExtInfo.itmResult ); - hb_xfree( pFileName ); - - /* - uiFlags = (USHORT) (pArea->fReadonly ? FO_READ : FO_READWRITE); - uiFlags |= (USHORT) (pArea->fShared ? FO_DENYNONE : FO_EXCLUSIVE); - hFile = hb_spOpen( ( BYTE * ) szFileName, uiFlags ); - - if( hFile != FS_ERROR ) - { - hb_fsClose( hFile ); - */ -#ifdef __XHARBOUR__ - if( hb_spFile(( BYTE * ) szFileName ,aFile) ) -#else - if( hb_spFile(( BYTE * ) szFileName) ) -#endif - { - pOrderInfo.itmResult = hb_itemPutNI( NULL, 0 ); - pOrderInfo.atomBagName = hb_itemPutC( NULL, szFileName ); - pOrderInfo.itmOrder = NULL; - SELF_ORDLSTADD( ( AREAP ) pArea, &pOrderInfo ); - - /* pOrderInfo.itmOrder = hb_itemPutNI( NULL, 1 ); */ - pOrderInfo.itmOrder = hb_itemPutNI( NULL, hb_set.HB_SET_AUTORDER ); - SELF_ORDLSTFOCUS( ( AREAP ) pArea, &pOrderInfo ); - hb_itemRelease( pOrderInfo.itmOrder ); - - SELF_GOTOP( ( AREAP ) pArea ); - - hb_itemRelease( pOrderInfo.atomBagName ); - hb_itemRelease( pOrderInfo.itmResult ); - } - hb_xfree( szFileName ); - } - return SUCCESS; -} - -// ( DBENTRYP_V ) hb_cdxRelease : NULL - -// ( DBENTRYP_SP ) hb_cdxStructSize -/* - * Retrieve the size of the WorkArea structure. - */ -ERRCODE hb_cdxStructSize( CDXAREAP pArea, USHORT * uiSize ) -{ - HB_TRACE(HB_TR_DEBUG, ("hb_cdxStrucSize(%p, %p)", pArea, uiSize)); - HB_SYMBOL_UNUSED( pArea ); - - * uiSize = sizeof( CDXAREA ); - return SUCCESS; -} - -// ( DBENTRYP_P ) hb_cdxSysName -/* - * Obtain the name of replaceable database driver (RDD) subsystem. - */ -ERRCODE hb_cdxSysName( CDXAREAP pArea, BYTE * pBuffer ) -{ - HB_TRACE(HB_TR_DEBUG, ("hb_cdxSysName(%p, %p)", pArea, pBuffer)); - HB_SYMBOL_UNUSED( pArea ); - - strncpy( ( char * ) pBuffer, "DBFCDX", 7 /* HARBOUR_MAX_RDD_DRIVERNAME_LENGTH */ ); - return SUCCESS; -} - -// ( DBENTRYP_VEI ) hb_cdxEval : NULL - -// ( DBENTRYP_V ) hb_cdxPack -extern ERRCODE hb_cdxPack( CDXAREAP pArea ) -{ - HB_TRACE(HB_TR_DEBUG, ("nb_cdxPack(%p)", pArea )); - - /* Commit changes first */ - if( FAST_GOCOLD( ( AREAP ) pArea ) == FAILURE ) - return FAILURE; - - if( SUPER_PACK( ( AREAP ) pArea ) == SUCCESS ) - { - return hb_cdxOrderListRebuild( pArea ); - } - else - return FAILURE; -} - -// ( DBENTRYP_LSP ) hb_cdxPackRec : NULL -// ( DBENTRYP_VS ) hb_cdxSort : NULL -// ( DBENTRYP_VT ) hb_cdxTrans : NULL -// ( DBENTRYP_VT ) hb_cdxTransRec : NULL - -// ( DBENTRYP_V ) hb_cdxZap -extern ERRCODE hb_cdxZap ( CDXAREAP pArea ) -{ - HB_TRACE(HB_TR_DEBUG, ("nb_cdxZap(%p)", pArea )); - - if( SUPER_ZAP( ( AREAP ) pArea ) == SUCCESS ) - { - return hb_cdxOrderListRebuild( pArea ); - } - else - return FAILURE; -} - -// ( DBENTRYP_VR ) hb_cdxChildEnd : NULL -// ( DBENTRYP_VR ) hb_cdxChildStart : NULL -// ( DBENTRYP_VR ) hb_cdxChildSync : NULL -// ( DBENTRYP_V ) hb_cdxSyncChildren : NULL -// ( DBENTRYP_V ) hb_cdxClearRel : NULL -// ( DBENTRYP_V ) hb_cdxForceRel : NULL -// ( DBENTRYP_SVP ) hb_cdxRelArea : NULL -// ( DBENTRYP_VR ) hb_cdxRelEval : NULL -// ( DBENTRYP_SVP ) hb_cdxRelText : NULL -// ( DBENTRYP_VR ) hb_cdxSetRel : NULL - -// ( DBENTRYP_OI ) hb_cdxOrderListAdd -ERRCODE hb_cdxOrderListAdd( CDXAREAP pAreaCdx, LPDBORDERINFO pOrderInfo ) -{ - USHORT uiFlags; - char * szFileName, * szFileNameDbfPath = NULL, * szBaseName; - AREAP pArea = (AREAP) pAreaCdx; - LPCDXINDEX pIndex; - DBORDERINFO pExtInfo; - PHB_FNAME pFileName; - PHB_ITEM pError = NULL; - BOOL bRetry; - LPCDXTAG pTag, pLastTag; - LPCDXTAG TagList, pTag1, pTag2, pTagTmp; - LPCDXINDEX pIndexTmp; - ULONG ulVersion; - - HB_TRACE(HB_TR_DEBUG, ("cdxOrderListAdd(%p, %p)", pArea, pOrderInfo)); - - if( FAST_GOCOLD( ( AREAP ) pArea ) == FAILURE ) - return FAILURE; - - /* Close all index for now (it must be fixed!)*/ - /* hb_cdxOrderListClear((CDXAREAP) pArea ); */ - - /* File exists? */ - /* Check file name */ - szFileName = ( char * ) hb_xgrab( _POSIX_PATH_MAX + 3 ); - szFileName[ 0 ] = '\0'; - pIndex = hb_cdxIndexNew( pArea ); - - //pAreaCdx->lpIndexes = pIndex; - /* - if ( pAreaCdx->lpIndexes == NULL) { - pAreaCdx->lpIndexes = pIndex; - } - else - { - pIndexTmp = pAreaCdx->lpIndexes; - while ( pIndexTmp->pNext ) { - pIndexTmp = pIndexTmp->pNext; - } - pIndexTmp->pNext = pIndex; - } - */ - - strcpy( szFileName, hb_itemGetCPtr( pOrderInfo->atomBagName ) ); - szFileName = (char*) hb_filecase( szFileName ) ; - - if( strlen( szFileName ) == 0 ) - { - /* hb_cdxOrderListClear( (CDXAREAP) pArea ); */ - /* - * TOTEST: this line doens't seem needed - * - * hb_cdxOrdListClear( (CDXAREAP) pArea, 1 ); */ - hb_xfree( szFileName ); - hb_cdxIndexFree( pIndex ); - return FAILURE; - } - else - { - pFileName = hb_fsFNameSplit( szFileName ); - if( !pFileName->szExtension ) - { - - pExtInfo.itmResult = hb_itemPutC( NULL, "" ); - SELF_ORDINFO( ( AREAP ) pArea, DBOI_BAGEXT, &pExtInfo ); - strcat( szFileName, pExtInfo.itmResult->item.asString.value ); - hb_itemRelease( pExtInfo.itmResult ); - } - szBaseName = ( char * ) hb_xgrab( CDX_MAXTAGNAMELEN + 1 ); - hb_strncpyUpper( szBaseName, pFileName->szName, CDX_MAXTAGNAMELEN ); - if( !pFileName->szPath ) - { - hb_xfree( pFileName ); - pFileName = hb_fsFNameSplit( pAreaCdx->szDataFileName ); - if( pFileName->szPath ) - { - szFileNameDbfPath = ( char * ) hb_xgrab( _POSIX_PATH_MAX + 3 ); - szFileNameDbfPath[ 0 ] = '\0'; - strcpy( szFileNameDbfPath, pFileName->szPath ); - strncat( szFileNameDbfPath, szFileName, _POSIX_PATH_MAX - - strlen( szFileNameDbfPath ) ); - } - /* pArea->szDataFileName = (char *) hb_xgrab( strlen( (char * ) pOpenInfo->abName)+1 ); */ - } - hb_xfree( pFileName ); - } - - if ( pAreaCdx->lpIndexes != NULL) { - pIndexTmp = pAreaCdx->lpIndexes; - while ( pIndexTmp && ( strcmp( szBaseName, pIndexTmp->pCompound->szName ) != 0 ) ) - pIndexTmp = pIndexTmp->pNext; - if ( pIndexTmp ) - { - // index already open, do nothing - // TODO: the full pathname should be compared when APIs are available - // hb_cdxOrderListClear( (CDXAREAP) pArea ); - if ( ! pAreaCdx->uiTag ) - { - pAreaCdx->uiTag = hb_cdxGetTagNumber( pAreaCdx, pIndexTmp->TagList); - SELF_GOTOP( ( AREAP ) pArea ); - } - hb_xfree( szFileName ); - hb_xfree( szBaseName ); - hb_cdxIndexFree( pIndex ); - return FAILURE; - } - } - if ( pAreaCdx->lpIndexes == NULL) { - pAreaCdx->lpIndexes = pIndex; - } - else - { - pIndexTmp = pAreaCdx->lpIndexes; - while ( pIndexTmp->pNext ) { - pIndexTmp = pIndexTmp->pNext; - } - pIndexTmp->pNext = pIndex; - } - - uiFlags = (USHORT) ( pAreaCdx->fReadonly ? FO_READ : FO_READWRITE ); - uiFlags |= (USHORT) ( pAreaCdx->fShared ? FO_DENYNONE : FO_EXCLUSIVE ); - - do - { - pIndex->hFile = FS_ERROR; - - if( szFileNameDbfPath ) - pIndex->hFile = hb_spOpen( ( BYTE * ) szFileNameDbfPath, uiFlags ); - - if( pIndex->hFile != FS_ERROR ) - { - pIndex->szFileName = ( char * ) hb_xgrab( strlen( szFileNameDbfPath ) + 1 ); - strcpy( pIndex->szFileName, szFileNameDbfPath); - } - else - { - pIndex->hFile = hb_spOpen( ( BYTE * ) szFileName, uiFlags ); - if( pIndex->hFile != FS_ERROR ) - { - pIndex->szFileName = ( char * ) hb_xgrab( strlen( szFileName ) + 1 ); - strcpy( pIndex->szFileName, szFileName); - } - } - - if( pIndex->hFile == FS_ERROR ) - { - if( !pError ) - { - pError = hb_errNew(); - hb_errPutGenCode( pError, EG_OPEN ); - hb_errPutSubCode( pError, 1003 ); - hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_OPEN ) ); - hb_errPutFileName( pError, szFileName ); - hb_errPutFlags( pError, EF_CANRETRY | EF_CANDEFAULT ); - } - bRetry = ( SELF_ERROR( ( AREAP ) pArea, pError ) == E_RETRY ); - } - else - bRetry = FALSE; - - } while( bRetry ); - - if( pError ) - hb_errRelease( pError ); - - if( pIndex->hFile == FS_ERROR ) - { - /* hb_cdxOrderListClear( (CDXAREAP) pArea ); */ - hb_cdxOrdListClear( (CDXAREAP) pArea, 1, NULL ); - if( szFileNameDbfPath != NULL ) - hb_xfree( szFileNameDbfPath ); - hb_xfree( szFileName ); - hb_xfree( szBaseName ); - return FAILURE; - } - - /* Corrupted? */ - /*mising test !*/ - /* load the tags*/ - /* pIndex->pCompound = hb_cdxTagNew( pIndex, szFileName, 0 ); */ - pIndex->pCompound = hb_cdxTagNew( pIndex, szBaseName, 0 ); - pIndex->pCompound->OptFlags = 0xE0; - pIndex->fShared = pAreaCdx->fShared; - pIndex->fReadonly = pAreaCdx->fReadonly; - - hb_cdxIndexResetAvailPage( pIndex ); - - hb_cdxIndexLockRead( pIndex, NULL ); - - if( (hb_fsSeek( pIndex->hFile, 0x08, FS_SET ) != 0x08) || - (hb_fsRead( pIndex->hFile, ( BYTE * ) &ulVersion, 4) != 4) ) - hb_errInternal( 2155, "hb_cdxOrderListAdd: Read error on index heading page.", "", "" ); - ulVersion = hb_cdxSwapBytes( ulVersion ); - pIndex->ulVersion = ulVersion; - - hb_cdxTagTagOpen( pIndex->pCompound, 0 ); - TagList = NULL; - while( !pIndex->pCompound->TagEOF ) - { - pTag = hb_cdxTagNew( pIndex, - pIndex->pCompound->CurKeyInfo->Value, - pIndex->pCompound->CurKeyInfo->Tag ); - - if( TagList == NULL ) - TagList = pTag; - else - { - pLastTag = TagList; - while( pLastTag->pNext ) - pLastTag = pLastTag->pNext; - pLastTag->pNext = pTag; - } - hb_cdxTagKeyRead( pIndex->pCompound, NEXT_RECORD ); - } - - hb_cdxIndexUnLockRead( pIndex, pIndex->pCompound ); - - /* Reorder the Tag list to be compatible with Clipper */ - pTag1 = TagList; - while( pTag1->pNext ) - { - if( pTag1->TagBlock < pTag1->pNext->TagBlock ) - pTag1 = pTag1->pNext; - else - { - if( TagList->TagBlock > pTag1->pNext->TagBlock ) - { - pTagTmp = TagList; - TagList = pTag1->pNext; - pTag1->pNext = pTag1->pNext->pNext; - TagList->pNext = pTagTmp; - } - else - { - pTag2 = TagList; - while( pTag2->pNext && (pTag2->pNext->TagBlock < pTag1->pNext->TagBlock) ) - pTag2 = pTag2->pNext; - - pTagTmp = pTag2->pNext; - pTag2->pNext = pTag1->pNext; - pTag1->pNext = pTag1->pNext->pNext; - pTag2->pNext->pNext = pTagTmp; - } - } - } - - if( pIndex->TagList == NULL ) - pIndex->TagList = TagList; - else - { - pLastTag = pIndex->TagList; - while( pLastTag->pNext ) - pLastTag = pLastTag->pNext; - pLastTag->pNext = TagList; - } - - /* dbfcdx specific: If there was no controlling order, set this one. - * This is the behaviour of Clipper's dbfcdx, although - * Clipper doc says a different rule - * */ - if ( ! pAreaCdx->uiTag ) - { - pAreaCdx->uiTag = hb_cdxGetTagNumber( pAreaCdx, pIndex->TagList); - SELF_GOTOP( ( AREAP ) pArea ); - } - - if( szFileNameDbfPath != NULL ) - hb_xfree( szFileNameDbfPath ); - - hb_xfree( szFileName ); - hb_xfree( szBaseName ); - - return SUCCESS; -} - -// ( DBENTRYP_V ) hb_cdxOrderListClear -/* - * Clear the current order list. - */ -extern ERRCODE hb_cdxOrderListClear( CDXAREAP pArea ) -{ - /* LPCDXINDEX pIndex; */ - - HB_TRACE(HB_TR_DEBUG, ("cdxOrderListClear(%p)", pArea)); - /* Commit changes first */ - if( FAST_GOCOLD( ( AREAP ) pArea ) == FAILURE ) - return FAILURE; - /* - while( pArea->lpIndexes ) - { - pIndex = pArea->lpIndexes; - pArea->lpIndexes = pArea->lpIndexes->pNext; - hb_cdxIndexFree( pIndex ); - } - pArea->lpIndexes = NULL; - */ - hb_cdxOrdListClear( pArea, 0, NULL ); - pArea->uiTag = 0; - return SUCCESS; -} - -// ( DBENTRYP_VP ) hb_cdxOrderListDelete : NULL - -// ( DBENTRYP_OI ) hb_cdxOrderListFocus -ERRCODE hb_cdxOrderListFocus( CDXAREAP pArea, LPDBORDERINFO pOrderInfo ) -{ - LPCDXTAG pTag; - BOOL bFound; - - HB_TRACE(HB_TR_DEBUG, ("cdxOrderListFocus(%p, %p)", pArea, pOrderInfo)); - /* - HB_SYMBOL_UNUSED( pArea ); - HB_SYMBOL_UNUSED( pOrderInfo ); - */ - if( FAST_GOCOLD( ( AREAP ) pArea ) == FAILURE ) - return FAILURE; - - pTag = hb_cdxGetActiveTag( pArea ); - - if( ! pArea->lpIndexes ) - return SUCCESS; - - if( pTag ) - pOrderInfo->itmResult = hb_itemPutC( pOrderInfo->itmResult, pTag->szName ); - - if( pOrderInfo->itmOrder ) - { - /* pArea->lpIndexes->uiTag = hb_cdxFindTag( pArea, pOrderInfo ); */ - pArea->uiTag = hb_cdxFindTag( pArea, pOrderInfo ); - - /* if( pArea->lpIndexes->uiTag ) */ - if( pArea->uiTag ) - { - bFound = pArea->fFound; - SELF_GOTO( ( AREAP ) pArea, pArea->ulRecNo ); - pArea->fFound = bFound; - } - } - - return SUCCESS; -} - -// ( DBENTRYP_V ) hb_cdxOrderListRebuild: NULL - -static ERRCODE hb_cdxOrderListRebuild( CDXAREAP pArea ) -{ - LPCDXINDEX pCdx, pLastCdx, pNextCdx; - USHORT uiPrevTag; - - HB_TRACE(HB_TR_DEBUG, ("nb_cdxPack(%p)", pArea )); - - /* Commit changes first */ - if( FAST_GOCOLD( ( AREAP ) pArea ) == FAILURE ) - return FAILURE; - - if( pArea->fShared ) - { - cdxError( pArea, EG_SHARED, EDBF_SHARED, pArea->szDataFileName, 0 ); - return FAILURE; - } - if( pArea->fReadonly ) - { - cdxError( pArea, EG_READONLY, EDBF_READONLY, pArea->szDataFileName, 0 ); - return FAILURE; - } - - if ( ! pArea->lpIndexes ) - return SUCCESS; - - uiPrevTag = pArea->uiTag; - pArea->uiTag = 0; - - pCdx = pArea->lpIndexes; - pArea->lpIndexes = pLastCdx = NULL; - while ( pCdx ) { - pNextCdx = pCdx->pNext; - pCdx->pNext = NULL; - if ( pLastCdx ) { - pLastCdx->pNext = pCdx; - pLastCdx = pCdx; - } - else - { - pArea->lpIndexes = pLastCdx = pCdx; - } - hb_cdxIndexReindex( pCdx ); - pCdx = pNextCdx; - } - - pArea->uiTag = uiPrevTag; - /* Clear pArea->lpdbOrdCondInfo */ - SELF_ORDSETCOND( ( AREAP ) pArea, NULL ); - - return SELF_GOTOP( ( AREAP ) pArea ); -} - - - -// ( DBENTRYP_VOI ) hb_cdxOrderCondition : NULL - -// ( DBENTRYP_VOC ) hb_cdxOrderCreate -ERRCODE hb_cdxOrderCreate( CDXAREAP pAreaCdx, LPDBORDERCREATEINFO pOrderInfo ) -{ - PHB_ITEM pExpr, pKeyExp, pForExp, pResult, pError; - HB_MACRO_PTR pExpMacro, pForMacro; - USHORT uiType, uiLen, uiCount; - char * szFileName, * szCpndTagName, * szTagName; - PHB_FNAME pFileName; - DBORDERINFO pExtInfo; - LPCDXINDEX pIndex; - LPCDXTAG pTag, pLastTag; - DBFHEADER pHeader; - BYTE bType; - BOOL bNewFile, bOpenedIndex; - AREAP pArea = (AREAP) pAreaCdx; -#ifdef __XHARBOUR__ - BYTE aFile[ _POSIX_PATH_MAX + 3 + 10 ]; -#endif - /* this is for testing when doing changes or testing a new platform/compiler - if( sizeof(CDXINTERNAL) != 500 ) - printf("cdxOrdCreate: Error, size of CDXINTERNAL: %i\n", sizeof(CDXINTERNAL)); - if( sizeof(CDXDATA) != 512 ) - printf("cdxOrdCreate: Error, size of CDXDATA: %i\n", sizeof(CDXDATA)); - */ - HB_TRACE(HB_TR_DEBUG, ("cdxOrderCreate(%p, %p)", pArea, pOrderInfo)); - - if( FAST_GOCOLD( ( AREAP ) pArea ) == FAILURE ) - return FAILURE; - - /* If we have a codeblock for the expression, use it */ - if( pOrderInfo->itmCobExpr ) - pExpr = pOrderInfo->itmCobExpr; - else /* Otherwise, try compiling the key expression string */ - { - if( SELF_COMPILE( (AREAP) pArea, ( BYTE * ) pOrderInfo->abExpr->item.asString.value ) == FAILURE ) - return FAILURE; - pExpr = pArea->valResult; - pArea->valResult = NULL; - } - - /* Save for later use */ - pKeyExp = hb_itemNew( NULL ); - hb_itemCopy( pKeyExp, pExpr ); - - /* Get a blank record before testing expression */ - hb_cdxGoEof( pAreaCdx ); - pExpMacro = pForMacro = NULL; - if( hb_itemType( pExpr ) == HB_IT_BLOCK ) - { - if( SELF_EVALBLOCK( ( AREAP ) pArea, pExpr ) == FAILURE ) - { - hb_itemRelease( pKeyExp ); - return FAILURE; - } - pResult = pArea->valResult; - pArea->valResult = NULL; - } - else - { - pExpMacro = ( HB_MACRO_PTR ) hb_itemGetPtr( pExpr ); - // hb_macroRun( pExpMacro ); - hb_cdxMacroRun( pArea, pExpMacro ); - pResult = pExpr; - hb_itemCopy( pResult, hb_stackItemFromTop( - 1 ) ); - } - - uiType = hb_itemType( pResult ); - - switch( uiType ) - { - case HB_IT_INTEGER: - case HB_IT_LONG: - case HB_IT_DOUBLE: - bType = 'N'; - uiLen = 8; - break; - - case HB_IT_DATE: - bType = 'D'; - uiLen = 8; - break; - - case HB_IT_LOGICAL: - bType = 'L'; - uiLen = 1; - break; - - case HB_IT_STRING: - bType = 'C'; - // uiLen = (USHORT) (pResult->item.asString.length > CDX_MAXKEY ? CDX_MAXKEY : - // pResult->item.asString.length); - uiLen = HB_CDXMAXKEY( pResult->item.asString.length ); - break; - - default: - hb_itemRelease( pKeyExp ); - if( pExpMacro != NULL ) - hb_macroDelete( pExpMacro ); - return FAILURE; - } - - hb_itemRelease( pResult ); - - /* Make sure uiLen is not 0 */ - if( uiLen == 0 ) - { - hb_itemRelease( pKeyExp ); - pError = hb_errNew(); - hb_errPutGenCode( pError, EG_DATAWIDTH ); - hb_errPutSubCode( pError, 1026 ); - hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_DATAWIDTH ) ); - SELF_ERROR( ( AREAP ) pArea, pError ); - hb_errRelease( pError ); - if( pExpMacro != NULL ) - hb_macroDelete( pExpMacro ); - return FAILURE; - } - - /* Check conditional expression */ - pExpr = pForExp = NULL; - if( pArea->lpdbOrdCondInfo ) - { - /* If we have a codeblock for the conditional expression, use it */ - if( pArea->lpdbOrdCondInfo->itmCobFor ) - pExpr = pArea->lpdbOrdCondInfo->itmCobFor; - else /* Otherwise, try compiling the conditional expression string */ - { - if( pArea->lpdbOrdCondInfo->abFor ) - { - if( SELF_COMPILE( (AREAP) pArea, pArea->lpdbOrdCondInfo->abFor ) == FAILURE ) + switch( hb_itemType( pItem ) ) { - hb_itemRelease( pKeyExp ); - if( pExpMacro != NULL ) - hb_macroDelete( pExpMacro ); - return FAILURE; - } - pExpr = pArea->valResult; - pArea->valResult = NULL; - } - } - /* Save for later use */ - if( pExpr ) - { - pForExp = hb_itemNew( NULL ); - hb_itemCopy( pForExp, pExpr ); - } - } + case HB_IT_STRING: + hb_cdxSortInsertWord( pSort, (long) pArea->ulRecNo, + pItem->item.asString.value, + HB_CDXMAXKEY( pItem->item.asString.length ) ); + break; - /* Test conditional expression */ - if( pExpr ) - { - if( hb_itemType( pExpr ) == HB_IT_BLOCK ) - { - if( SELF_EVALBLOCK( ( AREAP ) pArea, pExpr ) == FAILURE ) - { - hb_itemRelease( pKeyExp ); - hb_itemRelease( pForExp ); - if( pExpMacro != NULL ) - hb_macroDelete( pExpMacro ); - return FAILURE; - } - pResult = pArea->valResult; - pArea->valResult = NULL; - } - else - { - pForMacro = ( HB_MACRO_PTR ) hb_itemGetPtr( pExpr ); - // hb_macroRun( pForMacro ); - hb_cdxMacroRun( pArea, pForMacro ); - pResult = pExpr; - hb_itemCopy( pResult, hb_stackItemFromTop( - 1 ) ); - } - uiType = hb_itemType( pResult ); - hb_itemRelease( pResult ); - if( uiType != HB_IT_LOGICAL ) - { - hb_itemRelease( pKeyExp ); - hb_itemRelease( pForExp ); - if( pExpMacro != NULL ) - hb_macroDelete( pExpMacro ); - if( pForMacro != NULL ) - hb_macroDelete( pForMacro ); - return FAILURE; - } - } + case HB_IT_INTEGER: + case HB_IT_LONG: +#ifndef HB_LONG_LONG_OFF + case HB_IT_LONGLONG: +#endif + case HB_IT_DOUBLE: + HB_PUT_SORTDBL( &cTemp[0], hb_itemGetND( pItem ) ); + hb_cdxSortInsertWord( pSort, pArea->ulRecNo, (char *) cTemp, 8 ); + break; - /* Check file name */ - szFileName = ( char * ) hb_xgrab( _POSIX_PATH_MAX + 3 ); - szFileName[ 0 ] = '\0'; - if( !pOrderInfo->abBagName || (strlen( ( char * ) pOrderInfo->abBagName ) == 0) ) - { - pFileName = hb_fsFNameSplit( pAreaCdx->szDataFileName ); - /* - if( pFileName->szDrive ) - strcat( szFileName, pFileName->szDrive ); - */ - if( pFileName->szPath ) - strcat( szFileName, pFileName->szPath ); - strcat( szFileName, pFileName->szName ); - pExtInfo.itmResult = hb_itemPutC( NULL, "" ); - SELF_ORDINFO( ( AREAP ) pArea, DBOI_BAGEXT, &pExtInfo ); - strcat( szFileName, pExtInfo.itmResult->item.asString.value ); - hb_itemRelease( pExtInfo.itmResult ); - } - else - { - strcpy( szFileName, ( char * ) pOrderInfo->abBagName ); - pFileName = hb_fsFNameSplit( szFileName ); - if( !pFileName->szExtension ) - { - pExtInfo.itmResult = hb_itemPutC( NULL, "" ); - SELF_ORDINFO( ( AREAP ) pArea, DBOI_BAGEXT, &pExtInfo ); - strcat( szFileName, pExtInfo.itmResult->item.asString.value ); - hb_itemRelease( pExtInfo.itmResult ); - } - } - szTagName = ( char * ) hb_xgrab( CDX_MAXTAGNAMELEN + 1 ); - szCpndTagName = ( char * ) hb_xgrab( CDX_MAXTAGNAMELEN + 1 ); - hb_strncpyUpper( szCpndTagName, pFileName->szName, CDX_MAXTAGNAMELEN ); - hb_strncpyUpper( szTagName, pFileName->szName, CDX_MAXTAGNAMELEN ); - hb_xfree( pFileName ); - if ( pOrderInfo->atomBagName && ( strlen(( const char * ) pOrderInfo->atomBagName) > 0 ) ) - hb_strncpyUpper( szTagName, ( const char * ) pOrderInfo->atomBagName, CDX_MAXTAGNAMELEN ); - uiCount = strlen( szTagName ); - while( uiCount > 0 && szTagName[ uiCount - 1 ] == ' ' ) - uiCount--; - szTagName[ uiCount ] = 0; + case HB_IT_DATE: + HB_PUT_SORTDBL( &cTemp[0], (double) hb_itemGetDL( pItem ) ); + hb_cdxSortInsertWord( pSort, pArea->ulRecNo, (char *) cTemp, 8 ); + break; + case HB_IT_LOGICAL: + cTemp[0] = (BYTE) (hb_itemGetL( pItem ) ? 'T' : 'F'); + hb_cdxSortInsertWord( pSort, pArea->ulRecNo, (char *) cTemp, 1 ); + break; - if( !pArea->lpdbOrdCondInfo || ( pArea->lpdbOrdCondInfo->fAll && - !pArea->lpdbOrdCondInfo->fAdditive ) ) - hb_cdxOrdListClear( (CDXAREAP) pArea, 0, NULL ); - - if( !pArea->lpdbOrdCondInfo || pArea->lpdbOrdCondInfo->fAll ) - pAreaCdx->uiTag = 0; - - pIndex = hb_cdxFindBag( pAreaCdx, szFileName ); - bOpenedIndex = pIndex ? 1 : 0; - - /* TOFIX: Do not close all indexes */ - // hb_cdxOrdListClear( (CDXAREAP) pArea, 1 ); - - if ( !bOpenedIndex ) - { - pIndex = hb_cdxIndexNew( pArea ); - - /* pAreaCdx->lpIndexes = pIndex; */ - - /* New file? */ - /* if( !hb_spFile( ( BYTE * ) szFileName ) ) */ - #ifdef __XHARBOUR__ - if( !hb_spFile( ( BYTE * ) szFileName, aFile ) ) - #else - if( !hb_spFile( ( BYTE * ) szFileName ) ) - #endif - { - pIndex->hFile = hb_spCreate( ( BYTE * ) szFileName, FC_NORMAL ); - bNewFile = TRUE; - pIndex->fShared = pAreaCdx->fShared; - pIndex->fReadonly = FALSE; - } - else - { - pIndex->hFile = hb_spOpen( ( BYTE * ) szFileName, FO_READWRITE | - ( pAreaCdx->fShared ? - FO_DENYNONE : FO_EXCLUSIVE ) ); - bNewFile = FALSE; - pIndex->fShared = pAreaCdx->fShared; - pIndex->fReadonly = FALSE; - } - - if( pIndex->hFile == FS_ERROR ) - { - /* hb_cdxOrderListClear( (CDXAREAP) pArea ); */ - /* hb_cdxOrdListClear( (CDXAREAP) pArea, 1 ); */ - hb_cdxIndexFree( pIndex ); - hb_xfree( szFileName ); - hb_xfree( szTagName ); - hb_xfree( szCpndTagName ); - hb_itemRelease( pKeyExp ); - if( pForExp != NULL ) - hb_itemRelease( pForExp ); - if( pExpMacro != NULL ) - hb_macroDelete( pExpMacro ); - if( pForMacro != NULL ) - hb_macroDelete( pForMacro ); - return FAILURE; - } - pIndex->szFileName = ( char * ) hb_xgrab( strlen( szFileName ) + 1 ); - strcpy( pIndex->szFileName, szFileName); - - /* Corrupted? */ - if( !bNewFile ) - { - bNewFile = ( hb_fsSeek( pIndex->hFile, 0, FS_END ) <= CDX_PAGELEN ); - hb_fsSeek( pIndex->hFile, 0, FS_SET ); - } - - hb_cdxIndexLockWrite( pIndex, NULL ); - - if( bNewFile ) - { - pIndex->NextAvail = 0; - pIndex->pCompound = hb_cdxTagNew( pIndex, szCpndTagName, -1 ); - pIndex->pCompound->OptFlags = 0xE0; - hb_cdxTagIndexTagNew( pIndex->pCompound, NULL, NULL, 'C', 10, NULL, NULL, - TRUE, FALSE, FALSE ); - hb_cdxTagTagOpen( pIndex->pCompound, 0 ); - } - else - { - pIndex->pCompound = hb_cdxTagNew( pIndex, szCpndTagName, 0 ); - pIndex->pCompound->OptFlags = 0xE0; - hb_cdxIndexResetAvailPage( pIndex ); - - /* Delete new tag if exist */ - hb_cdxTagTagOpen( pIndex->pCompound, 0 ); - while( !pIndex->pCompound->TagEOF ) - { - if( hb_stricmp( pIndex->pCompound->CurKeyInfo->Value, szTagName ) == 0 ) - { - hb_cdxPageDeleteKey( pIndex->pCompound->RootPage ); - break; - } - hb_cdxTagKeyRead( pIndex->pCompound, NEXT_RECORD ); - } - - hb_cdxTagTagOpen( pIndex->pCompound, 0 ); - while( !pIndex->pCompound->TagEOF ) - { - pTag = hb_cdxTagNew( pIndex, - pIndex->pCompound->CurKeyInfo->Value, - pIndex->pCompound->CurKeyInfo->Tag ); - if( pIndex->TagList == NULL ) - pIndex->TagList = pTag; - else - { - pLastTag = pIndex->TagList; - while( pLastTag->pNext ) - pLastTag = pLastTag->pNext; - pLastTag->pNext = pTag; - } - hb_cdxTagKeyRead( pIndex->pCompound, NEXT_RECORD ); - } - if ( pIndex->TagList != NULL ) { - pIndex->TagList = hb_cdxReorderTagList(pIndex->TagList); - } - } - - /* Update DBF header */ - if( !pAreaCdx->fHasTags ) - { - pFileName = hb_fsFNameSplit( pAreaCdx->szDataFileName ); - hb_strncpyUpper( szFileName, pFileName->szName, CDX_MAXTAGNAMELEN ); - hb_xfree( pFileName ); - hb_fsSeek( pAreaCdx->hDataFile, 0, FS_SET ); - if( strcmp( szFileName, szCpndTagName ) == 0 && hb_fsRead( pAreaCdx->hDataFile, - ( BYTE * ) &pHeader, sizeof( DBFHEADER ) ) == sizeof( DBFHEADER ) ) - { - pAreaCdx->fHasTags = pHeader.bHasTags = 1; - hb_fsSeek( pAreaCdx->hDataFile, 0, FS_SET ); - hb_fsWrite( pAreaCdx->hDataFile, ( BYTE * ) &pHeader, sizeof( DBFHEADER ) ); - } - } - } /* if ( !bOpenedIndex ) */ - else - { - hb_cdxIndexLockWrite( pIndex, NULL ); - } - hb_xfree( szFileName ); - /* - if ( pOrderInfo->atomBagName && ( strlen(( const char * ) pOrderInfo->atomBagName) > 0 ) ) - hb_strncpyUpper( szTagName, ( const char * ) pOrderInfo->atomBagName, CDX_MAXTAGNAMELEN ); - uiCount = strlen( szTagName ); - while( uiCount > 0 && szTagName[ uiCount - 1 ] == ' ' ) - uiCount--; - szTagName[ uiCount ] = 0; - */ - pTag = 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, - ( pArea->lpdbOrdCondInfo ? pArea->lpdbOrdCondInfo->fCustom : FALSE ) ); - - hb_xfree( szTagName ); - hb_xfree( szCpndTagName ); - if ( !bOpenedIndex ) - { - if ( pAreaCdx->lpIndexes == NULL) { - pAreaCdx->lpIndexes = pIndex; - } - else - { - LPCDXINDEX pIndexTmp; - pIndexTmp = pAreaCdx->lpIndexes; - while ( pIndexTmp->pNext ) { - pIndexTmp = pIndexTmp->pNext; - } - pIndexTmp->pNext = pIndex; - } - } - if( pArea->lpdbOrdCondInfo && ( !pArea->lpdbOrdCondInfo->fAll && - !pArea->lpdbOrdCondInfo->fAdditive ) ) - hb_cdxOrdListClear( (CDXAREAP) pArea, 0, pIndex ); - - hb_cdxIndexUnLockWrite( pIndex, NULL ); - pAreaCdx->uiTag = hb_cdxGetTagNumber(pAreaCdx, pTag); - - /* Clear pArea->lpdbOrdCondInfo */ - SELF_ORDSETCOND( ( AREAP ) pArea, NULL ); - - return SELF_GOTOP( ( AREAP ) pArea ); -} - - -// ( DBENTRYP_OI ) hb_cdxOrderDestroy : NULL -ERRCODE hb_cdxOrderDestroy( CDXAREAP pArea, LPDBORDERINFO pOrderInfo ) -{ - LPCDXINDEX pIndex, pIndexTmp; - LPCDXTAG pTag; - USHORT uiTag; - char * szFileName; - - HB_TRACE(HB_TR_DEBUG, ("cdxOrderDestroy(%p, %p)", pArea, pOrderInfo)); - - if( FAST_GOCOLD( ( AREAP ) pArea ) == FAILURE ) - return FAILURE; - - if( ! pArea->lpIndexes ) - return SUCCESS; - - if( pOrderInfo->itmOrder ) - { - /* pArea->lpIndexes->uiTag = hb_cdxFindTag( pArea, pOrderInfo ); */ - uiTag = hb_cdxFindTag( pArea, pOrderInfo ); - if ( uiTag ) { - pTag = hb_cdxGetTagByNumber(pArea, uiTag ); - /* if( pArea->lpIndexes->uiTag ) */ - pIndex = pTag->pIndex; - if ( !pIndex->fShared && !pIndex->fReadonly ) - { - hb_cdxIndexDelTag( pIndex, pTag->szName ); - if ( !pIndex->TagList ) { - szFileName = ( char * ) hb_xgrab( strlen( pIndex->szFileName ) + 1 ); - strcpy( szFileName, pIndex->szFileName); - if ( pArea->lpIndexes == pIndex ) - { - pArea->lpIndexes = pIndex->pNext; - if ( pArea->fHasTags ) { - pArea->fHasTags = 0; - SELF_WRITEDBHEADER( ( AREAP ) pArea ); - } - } - else - { - pIndexTmp = pArea->lpIndexes; - while( pIndexTmp->pNext && ( pIndexTmp->pNext != pIndex ) ) - { - pIndexTmp = pIndexTmp->pNext; - } - if ( pIndexTmp->pNext == pIndex ) { - pIndexTmp->pNext = pIndex->pNext; - } - } - hb_cdxIndexFree( pIndex ); - hb_fsDelete( (BYTE *) szFileName ); - hb_xfree( szFileName ); - - } - } - else - { - hb_errInternal( 1023, "hb_cdxOrderDestroy: exclusive required.", "", "" ); - } - } - } - return SUCCESS; - -} - -// ( DBENTRYP_OII ) hb_cdxOrderInfo -/* - * Provides information about order management. - */ -ERRCODE hb_cdxOrderInfo( CDXAREAP pArea, USHORT uiIndex, LPDBORDERINFO pOrderInfo ) -{ - USHORT uiTag = 0; - LPCDXTAG pTag = NULL; - USHORT uiAux; - - HB_TRACE(HB_TR_DEBUG, ("hb_cdxOrderInfo(%p, %hu, %p)", pArea, uiIndex, pOrderInfo)); - HB_SYMBOL_UNUSED( pArea ); - - if( FAST_GOCOLD( ( AREAP ) pArea ) == FAILURE ) - return FAILURE; - - switch( uiIndex ) - { - case DBOI_ORDERCOUNT : - case DBOI_KEYVAL : - case DBOI_BAGEXT : - break; - default: - if( ! pOrderInfo->itmOrder ) - { - pTag = hb_cdxGetActiveTag( pArea ); - } - else - { - uiTag = hb_cdxFindTag( pArea, pOrderInfo ); - pTag = hb_cdxGetTagByNumber(pArea, uiTag ); - } - } - - switch( uiIndex ) - { - case DBOI_CONDITION : - pOrderInfo->itmResult = hb_itemPutC( pOrderInfo->itmResult, ( pTag ? pTag->ForExpr : "" ) ); - break; - - case DBOI_EXPRESSION : - pOrderInfo->itmResult = hb_itemPutC( pOrderInfo->itmResult, ( pTag ? pTag->KeyExpr : "" ) ); - break; - - case DBOI_POSITION : - /* TODO: use specified tag */ - /* - pTag = hb_cdxGetActiveTag( pArea ); - if ( pTag ) { - hb_itemPutNL( pOrderInfo->itmResult, hb_cdxDBOIKeyNo(pArea, pTag, 1) ); - } - else - { - hb_itemPutNL( pOrderInfo->itmResult, 0 ); - SELF_RECNO( ( AREAP ) pArea, pOrderInfo->itmResult ); - } - */ - hb_itemPutNL( pOrderInfo->itmResult, hb_cdxDBOIKeyNo(pArea, pTag, 1) ); - break; - - case DBOI_RECNO : /* TODO: is this ok? DBOI_RECNO == DBOI_KEYNORAW ? */ - case DBOI_KEYNORAW : - /* TODO: use specified tag */ - /* - pTag = hb_cdxGetActiveTag( pArea ); - if ( pTag ) { - hb_itemPutNL( pOrderInfo->itmResult, hb_cdxDBOIKeyNo(pArea, pTag, 0) ); - } - else - { - hb_itemPutNL( pOrderInfo->itmResult, 0 ); - SELF_RECNO( ( AREAP ) pArea, pOrderInfo->itmResult ); - } - */ - hb_itemPutNL( pOrderInfo->itmResult, hb_cdxDBOIKeyNo(pArea, pTag, 0) ); - break; - - case DBOI_NAME : - pOrderInfo->itmResult = hb_itemPutC( pOrderInfo->itmResult, ( pTag ? pTag->szName : "" ) ); - break; - - case DBOI_NUMBER: - if( ! pOrderInfo->itmOrder ) - { - if( pArea->lpIndexes ) - /* hb_itemPutNI( pOrderInfo->itmResult, pArea->lpIndexes->uiTag ); */ - hb_itemPutNI( pOrderInfo->itmResult, pArea->uiTag ); - else - hb_itemPutNI( pOrderInfo->itmResult, 0 ); - } - else - { - hb_itemPutNI( pOrderInfo->itmResult, hb_cdxFindTag( pArea, pOrderInfo ) ); - } - break; - - case DBOI_BAGNAME : - /* hb_itemPutC( pOrderInfo->itmResult, pTag->pIndex->pCompound->szName ); */ - /* pOrderInfo->itmResult = hb_itemPutC( pOrderInfo->itmResult, ( pTag ? pTag->pIndex->szFileName : "" ) ); */ - if ( pTag ) - { - PHB_FNAME pFileName = hb_fsFNameSplit( pTag->pIndex->szFileName ); - hb_itemPutC( pOrderInfo->itmResult, pFileName->szName ); - hb_xfree( pFileName ); - } - else - hb_itemPutC( pOrderInfo->itmResult, "" ); - break; - - case DBOI_FULLPATH : - pOrderInfo->itmResult = hb_itemPutC( pOrderInfo->itmResult, ( pTag ? pTag->pIndex->szFileName : "" ) ); - break; - - case DBOI_BAGEXT: - pOrderInfo->itmResult = hb_itemPutC( pOrderInfo->itmResult, CDX_INDEXEXT ); - break; - - case DBOI_ORDERCOUNT : - uiTag = 0; - if( pArea->lpIndexes ) - { - pTag = pArea->lpIndexes->TagList; - while( pTag ) - { - uiTag++; - /* pTag = pTag->pNext; */ - if ( pTag->pNext ) - pTag = pTag->pNext; - else - { - if ( pTag->pIndex->pNext ) - pTag = pTag->pIndex->pNext->TagList; - else - pTag = NULL; - } - } - } - hb_itemPutNI( pOrderInfo->itmResult, uiTag ); - break; - - case DBOI_FILEHANDLE : - hb_itemPutNL( pOrderInfo->itmResult, ( pTag ? (long) pTag->pIndex->hFile : 0 ) ); - break; - - case DBOI_ISCOND : - hb_itemPutL( pOrderInfo->itmResult, ( pTag ? (pTag->ForExpr != NULL) : 0 ) ); - break; - - case DBOI_ISDESC : - hb_itemPutL( pOrderInfo->itmResult, ( pTag ? !pTag->AscendKey : 0 ) ); - break; - - case DBOI_UNIQUE: - hb_itemPutL( pOrderInfo->itmResult, ( pTag ? pTag->UniqueKey : 0 ) ); - break; - - /*------------------- */ - - case DBOI_KEYCOUNT : - /* TODO: use specified tag */ - /* - pTag = hb_cdxGetActiveTag( pArea ); - if ( pTag ) { - hb_itemPutNL( pOrderInfo->itmResult, hb_cdxDBOIKeyCount(pArea) ); - } - else - { - ULONG ulRecCount = 0; - SELF_RECCOUNT( ( AREAP ) pArea, &ulRecCount ); - hb_itemPutNL( pOrderInfo->itmResult, ulRecCount ); - } - */ - hb_itemPutNL( pOrderInfo->itmResult, hb_cdxDBOIKeyCount(pArea, pTag, 1) ); - break; - - case DBOI_KEYCOUNTRAW : - /* TODO: use specified tag */ - /* - pTag = hb_cdxGetActiveTag( pArea ); - if ( pTag ) { - hb_itemPutNL( pOrderInfo->itmResult, hb_cdxDBOIKeyCount(pArea) ); - } - else - { - ULONG ulRecCount = 0; - SELF_RECCOUNT( ( AREAP ) pArea, &ulRecCount ); - hb_itemPutNL( pOrderInfo->itmResult, ulRecCount ); - } - */ - hb_itemPutNL( pOrderInfo->itmResult, hb_cdxDBOIKeyCount(pArea, pTag, 0) ); - break; - - case DBOI_KEYTYPE: - if ( pTag ) - { - char szType[2]; - szType[0] = (char) pTag->uiType; - szType[1] = 0; - hb_itemPutC( pOrderInfo->itmResult, szType ); - } - else - hb_itemPutC( pOrderInfo->itmResult, "" ); - break; - - case DBOI_KEYSIZE: - if ( pTag ) - hb_itemPutNL( pOrderInfo->itmResult, pTag->uiLen ); - else - hb_itemPutNL( pOrderInfo->itmResult, 0 ); - break; - - case DBOI_KEYVAL: - pTag = hb_cdxGetActiveTag( pArea ); - hb_itemClear( pOrderInfo->itmResult ); - if( pTag && !pArea->fEof && pTag->CurKeyInfo && ((ULONG) pTag->CurKeyInfo->Tag == pArea->ulRecNo) ) - { - switch( pTag->uiType ) - { - case 'N' : - uiAux = HB_IT_DOUBLE; break; - case 'D' : - uiAux = HB_IT_DATE; break; - case 'L' : - uiAux = HB_IT_LOGICAL; break; - case 'C' : - uiAux = HB_IT_STRING; break; default: - uiAux = HB_IT_NIL; + printf( "hb_cdxTagDoIndex( LPCDXTAG pTag ): hb_itemType( pItem ) = %i", hb_itemType( pItem ) ); } - - if( uiAux != HB_IT_NIL ) - hb_cdxKeyGetItem( pTag->CurKeyInfo, pOrderInfo->itmResult, uiAux ); } - break; - /*------------------- */ - case DBOI_SCOPETOP : - pTag = hb_cdxGetActiveTag( pArea ); - if( pTag ) - hb_cdxScopeInfo( pArea, 0, pOrderInfo->itmResult ); - else - hb_itemClear( pOrderInfo->itmResult ); - break; - case DBOI_SCOPEBOTTOM : - pTag = hb_cdxGetActiveTag( pArea ); - if( pTag ) - hb_cdxScopeInfo( pArea, 1, pOrderInfo->itmResult ); - else - hb_itemClear( pOrderInfo->itmResult ); - break; - case DBOI_SCOPETOPCLEAR : - pTag = hb_cdxGetActiveTag( pArea ); - if( pTag ) + if ( pEvalItem ) { - hb_cdxScopeInfo( pArea, 0, pOrderInfo->itmResult ); - hb_cdxTagClearScope( pTag, 0); + if ( pArea->lpdbOrdCondInfo->lStep ) + { + lStep ++; + if ( lStep == pArea->lpdbOrdCondInfo->lStep ) + lStep = 0; + } + if ( pEvalItem && !lStep ) + { + hb_vmPushSymbol( &hb_symEval ); + hb_vmPush( pEvalItem ); + hb_vmSend( 0 ); + } } - else - hb_itemClear( pOrderInfo->itmResult ); - break; - case DBOI_SCOPEBOTTOMCLEAR : - pTag = hb_cdxGetActiveTag( pArea ); - if( pTag ) + if ( !bDirectRead ) { - hb_cdxScopeInfo( pArea, 1, pOrderInfo->itmResult ); - hb_cdxTagClearScope( pTag, 1); - } - else - hb_itemClear( pOrderInfo->itmResult ); - break; - - /*------------------- - * TODO: - * CUSTOM: allow changing an index into custom - * */ - case DBOI_CUSTOM : - hb_itemPutL( pOrderInfo->itmResult, ( pTag ? pTag->Custom : 0 ) ); - break; - case DBOI_KEYADD : - if ( !pTag ) { - hb_itemPutL( pOrderInfo->itmResult, 0 ); - } - else - { - if ( pTag->Custom ) + if ( bEnd ) + break; + if ( pArea->lpdbOrdCondInfo && pArea->lpdbOrdCondInfo->lNextCount > 0 ) { - LPCDXKEYINFO pKey; - hb_cdxIndexLockWrite ( pTag->pIndex, pTag ); - if ( pOrderInfo->itmNewVal && !HB_IS_NIL( pOrderInfo->itmNewVal ) ) - { - pKey = hb_cdxKeyPutItem( NULL, pOrderInfo->itmNewVal ); - pKey->Tag = pArea->ulRecNo; - } - else - { - pKey = hb_cdxEvalKey( pArea, pTag ); - } - hb_cdxTagKeyAdd( pTag, pKey ); - pTag->RootPage->Changed = TRUE; - /* if( uiTag == pArea->lpIndexes->uiTag) */ - if( uiTag == pArea->uiTag) - hb_cdxTagTagStore( pTag ); - else - hb_cdxTagTagClose( pTag ); - hb_cdxIndexUnLockWrite ( pTag->pIndex, pTag ); - hb_itemPutL( pOrderInfo->itmResult, 1 ); - hb_cdxKeyFree( pKey ); + pArea->lpdbOrdCondInfo->lNextCount--; + if ( pArea->lpdbOrdCondInfo->lNextCount <= 0 ) + break; } - else - { - cdxError( pArea, 0, 1052, 0, 0 ); - } - } - break; - case DBOI_KEYDELETE : - if ( !pTag ) { - hb_itemPutL( pOrderInfo->itmResult, 0 ); - } - else - { - if ( pTag->Custom ) - { - LPCDXKEYINFO pKey; - hb_cdxIndexLockWrite ( pTag->pIndex, pTag ); - if ( pOrderInfo->itmNewVal && !HB_IS_NIL( pOrderInfo->itmNewVal ) ) - { - pKey = hb_cdxKeyPutItem( NULL, pOrderInfo->itmNewVal ); - pKey->Tag = pArea->ulRecNo; - } - else - { - pKey = hb_cdxEvalKey( pArea, pTag ); - } - if( hb_cdxTagKeyFind( pTag, pKey ) > 0 ) - { - hb_cdxPageDeleteKey( pTag->RootPage ); - pTag->RootPage->Changed = TRUE; - if( uiTag == pArea->uiTag) - hb_cdxTagTagStore( pTag ); - else - hb_cdxTagTagClose( pTag ); - hb_itemPutL( pOrderInfo->itmResult, 1 ); - } - else - { - hb_itemPutL( pOrderInfo->itmResult, 0 ); - } - hb_cdxIndexUnLockWrite ( pTag->pIndex, pTag ); - hb_cdxKeyFree( pKey ); - } - else - { - cdxError( pArea, 0, 1052, 0, 0 ); - } - } - break; - - default: - return SUPER_ORDINFO( ( AREAP ) pArea, uiIndex, pOrderInfo ); - - } - return SUCCESS; -} - -// ( DBENTRYP_V ) hb_cdxClearFilter : NULL -// ( DBENTRYP_V ) hb_cdxClearLocate : NULL - -// ( DBENTRYP_V ) hb_cdxClearScope : NULL -static ERRCODE hb_cdxClearScope( CDXAREAP pArea ) -{ - LPCDXTAG pTag; - /* PHB_ITEM *pScope; */ - - HB_TRACE(HB_TR_DEBUG, ("hb_cdxClearScope(%p)", pArea)); - - pTag = hb_cdxGetActiveTag( pArea ); - - if( pTag ) - { - hb_cdxTagClearScope( pTag, 0); - hb_cdxTagClearScope( pTag, 1); - } - return SUCCESS; -} - -// ( DBENTRYP_VPLP ) hb_cdxCountScope : NULL -// ( DBENTRYP_I ) hb_cdxFilterText : NULL - -// ( DBENTRYP_SI ) hb_cdxScopeInfo : NULL -static ERRCODE hb_cdxScopeInfo( CDXAREAP pArea, USHORT nScope, PHB_ITEM pItem ) -{ - LPCDXTAG pTag; - PHB_ITEM *pScope; - - HB_TRACE(HB_TR_DEBUG, ("hb_cdxScopeInfo(%p, %hu, %p)", pArea, nScope, pItem)); - - pTag = hb_cdxGetActiveTag( pArea ); - - hb_itemClear( pItem ); - if( pTag ) - { - pScope = (nScope == 0) ? &(pTag->topScope) : &(pTag->bottomScope); - if ( *pScope ) { - hb_itemCopy( pItem, *pScope ); - } - } - return SUCCESS; -} - -// ( DBENTRYP_VFI ) hb_cdxSetFilter : NULL -// ( DBENTRYP_VLO ) hb_cdxSetLocate : NULL - -// ( DBENTRYP_VOS ) hb_cdxSetScope : NULL -static ERRCODE hb_cdxSetScope( CDXAREAP pArea, LPDBORDSCOPEINFO sInfo ) -{ - LPCDXTAG pTag; - BOOL ok; - PHB_ITEM *pScope; - LPCDXKEYINFO *pScopeKey; - - HB_TRACE(HB_TR_DEBUG, ("hb_cdxSetScope(%p, %p)", pArea, sInfo)); - - pTag = hb_cdxGetActiveTag( pArea ); - - if( pTag ) - { - pScope = (sInfo->nScope == 0) ? &(pTag->topScope) : &(pTag->bottomScope); - pScopeKey = (sInfo->nScope == 0) ? &(pTag->topScopeKey) : &(pTag->bottomScopeKey); - if( !sInfo->scopeValue ) - { - if ( *pScope ) { - hb_itemRelease( *pScope ); - *pScope = NULL; - } - if ( *pScopeKey ) { - hb_cdxKeyFree( *pScopeKey ); - *pScopeKey = NULL; + SELF_SKIP( ( AREAP ) pArea, 1 ); + if ( pArea->fEof ) + break; } } + if ( pSort->WordCount + pSort->TotalWordCount > 0 ) + hb_cdxSortDisplayWord( pSort ); else - { - switch( pTag->uiType ) - { - case 'N' : - ok = ( sInfo->scopeValue->type & HB_IT_NUMERIC ); break; - case 'D' : - ok = ( sInfo->scopeValue->type == HB_IT_DATE ); break; - case 'L' : - ok = ( sInfo->scopeValue->type == HB_IT_LOGICAL ); break; - case 'C' : - ok = ( sInfo->scopeValue->type == HB_IT_STRING ); break; - default: - ok = FALSE; - } - if ( ok ) { - if( *pScope == NULL ) - *pScope = hb_itemNew( NULL ); - hb_itemCopy( *pScope, sInfo->scopeValue ); - *pScopeKey = hb_cdxKeyPutItem( *pScopeKey, *pScope ); - (*pScopeKey)->Tag = (sInfo->nScope == 0) ? (CDX_IGNORE_REC_NUM) : (CDX_MAX_REC_NUM); - } - else - printf("hb_cdxSetScope: scope value of wrong type"); /* DBFCDX/1051 Scope Type Mismatch */ - } + hb_cdxTagEmptyIndex( pTag ); + hb_cdxSortFree( pSort ); + hb_itemRelease( pItem ); + hb_set.HB_SET_DELETED = bSaveDeleted; + pArea->dbfi.itmCobExpr = pSaveFilter; + pTag->TagChanged = TRUE; } - else - printf("hb_cdxSetScope: workarea not indexed"); - - return SUCCESS; + pTag->pIndex->pArea->ulRecNo = 0; +#ifndef HB_CDP_SUPPORT_OFF + s_cdpage = cdpTmp; +#endif } -// ( DBENTRYP_VPL ) hb_cdxSkipScope : NULL - -// ( DBENTRYP_P ) hb_cdxCompile : NULL -// ( DBENTRYP_I ) hb_cdxError : NULL -// ( DBENTRYP_I ) hb_cdxEvalBlock : NULL - -// ( DBENTRYP_VSP ) hb_cdxRawLock : NULL -// ( DBENTRYP_VL ) hb_cdxLock : NULL -// ( DBENTRYP_UL ) hb_cdxUnLock : NULL - -// ( DBENTRYP_V ) hb_cdxCloseMemFile : NULL - -// ( DBENTRYP_VP ) hb_cdxCreateMemFile -/* - * Create a memo file in the WorkArea. - */ -ERRCODE hb_cdxCreateMemFile( CDXAREAP pArea, LPDBOPENINFO pCreateInfo ) -{ - MEMOHEADER fptHeader; - BYTE pBlock[ 512 ]; - BOOL bRetry; - PHB_ITEM pError; - - HB_TRACE(HB_TR_DEBUG, ("hb_cdxCreateMemFile(%p, %p)", pArea, pCreateInfo)); - - if( pCreateInfo ) - { - pError = NULL; - /* Try create */ - do - { - pArea->hMemoFile = hb_spCreate( pCreateInfo->abName, FC_NORMAL ); - if( pArea->hMemoFile == FS_ERROR ) - { - if( !pError ) - { - pError = hb_errNew(); - hb_errPutGenCode( pError, EG_CREATE ); - hb_errPutSubCode( pError, EDBF_CREATE_DBF ); - hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_CREATE ) ); - hb_errPutFileName( pError, ( char * ) pCreateInfo->abName ); - hb_errPutFlags( pError, EF_CANRETRY ); - } - bRetry = ( SELF_ERROR( ( AREAP ) pArea, pError ) == E_RETRY ); - } - else - bRetry = FALSE; - } while( bRetry ); - if( pError ) - hb_errRelease( pError ); - - if( pArea->hMemoFile == FS_ERROR ) - return FAILURE; - } - else /* For zap file */ - hb_fsSeek( pArea->hMemoFile, 0, FS_SET ); - - pArea->uiMemoBlockSize = s_uiMemoBlockSize; - fptHeader.ulNextBlock = hb_cdxSwapBytes( s_uiMemoBlockSize > 512 ? 1 : - 512 / s_uiMemoBlockSize ); - fptHeader.ulBlockSize = hb_cdxSwapBytes( s_uiMemoBlockSize ); - if( hb_fsWrite( pArea->hMemoFile, ( BYTE * ) &fptHeader, sizeof( MEMOHEADER ) ) != - sizeof( MEMOHEADER ) ) - return FAILURE; - memset( pBlock, 0, 512 ); - if( hb_fsWrite( pArea->hMemoFile, pBlock, 512 - sizeof( MEMOHEADER ) ) != - 512 - sizeof( MEMOHEADER ) ) - return FAILURE; - hb_fsWrite( pArea->hMemoFile, NULL, 0 ); - return SUCCESS; -} - - -// ( DBENTRYP_SVPB ) hb_cdxGetValueFile : NULL - -// ( DBENTRYP_VP ) hb_cdxOpenMemFile -/* - * Open a memo file in the specified WorkArea. - */ -ERRCODE hb_cdxOpenMemFile( CDXAREAP pArea, LPDBOPENINFO pOpenInfo ) -{ - USHORT uiFlags; - BOOL bRetry; - MEMOHEADER fptHeader; - PHB_ITEM pError; - BYTE buffer[0x20]; - - HB_TRACE(HB_TR_DEBUG, ("hb_cdxOpenMemFile(%p, %p)", pArea, pOpenInfo)); - - uiFlags = (USHORT) (pOpenInfo->fReadonly ? FO_READ : FO_READWRITE); - uiFlags |= (USHORT) (pOpenInfo->fShared ? FO_DENYNONE : FO_EXCLUSIVE); - pError = NULL; - - /* Try open */ - do - { - pArea->hMemoFile = hb_spOpen( pOpenInfo->abName, uiFlags ); - if( pArea->hMemoFile == FS_ERROR ) - { - if( !pError ) - { - pError = hb_errNew(); - hb_errPutGenCode( pError, EG_OPEN ); - hb_errPutSubCode( pError, EDBF_OPEN_DBF ); - hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_OPEN ) ); - hb_errPutFileName( pError, ( char * ) pOpenInfo->abName ); - hb_errPutFlags( pError, EF_CANRETRY | EF_CANDEFAULT ); - } - bRetry = ( SELF_ERROR( ( AREAP ) pArea, pError ) == E_RETRY ); - } - else - bRetry = FALSE; - } while( bRetry ); - if( pError ) - hb_errRelease( pError ); - if( pArea->hMemoFile == FS_ERROR ) - return FAILURE; - - hb_fsSeek( pArea->hMemoFile, 0, FS_SET ); - if( hb_fsRead( pArea->hMemoFile, ( BYTE * ) &fptHeader, sizeof( MEMOHEADER ) ) != - sizeof( MEMOHEADER ) ) - return FAILURE; - pArea->uiMemoBlockSize = ( USHORT ) hb_cdxSwapBytes( fptHeader.ulBlockSize ); - if ( pArea->uiMemoBlockSize == 0) - { - /* Check for compatibility with Clipper 5.3/FlexFile3 malformed memo headers*/ - hb_fsSeek( pArea->hMemoFile, 0x200, FS_SET ); - if( hb_fsRead( pArea->hMemoFile, buffer, sizeof( buffer ) ) != sizeof( buffer ) ) - return FAILURE; - if ( memcmp( (char *) buffer, "FlexFile3\x03", 10) == 0 ) - { - pArea->uiMemoBlockSize = ( USHORT ) buffer[0x1C]; - } - } - if ( pArea->uiMemoBlockSize == 0) - { - if( !pError ) - { - pError = hb_errNew(); - hb_errPutGenCode( pError, EG_CORRUPTION ); - hb_errPutSubCode( pError, EDBF_CORRUPT ); - hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_CORRUPTION ) ); - hb_errPutFileName( pError, (char *) pOpenInfo->abName ); - } - /* bRetry = ( SELF_ERROR( ( AREAP ) pArea, pError ) == E_RETRY ); */ - SELF_ERROR( ( AREAP ) pArea, pError ); - if( pError ) - hb_errRelease( pError ); - return FAILURE; - } - - - return SUCCESS; -} - -// ( DBENTRYP_SVP ) hb_cdxPutValueFile : NULL - -// ( DBENTRYP_V ) hb_cdxReadDBHeader -/* - * Read the database file header record in the WorkArea. - */ -ERRCODE hb_cdxReadDBHeader( CDXAREAP pArea ) -{ - DBFHEADER dbHeader; - BOOL bRetry, bError; - PHB_ITEM pError; - - HB_TRACE(HB_TR_DEBUG, ("hb_cdxReadHeader(%p)", pArea)); - - pError = NULL; - /* Try read */ - do - { - hb_fsSeek( pArea->hDataFile, 0, FS_SET ); - if( hb_fsRead( pArea->hDataFile, ( BYTE * ) &dbHeader, sizeof( DBFHEADER ) ) != - sizeof( DBFHEADER ) || ( dbHeader.bVersion != 0x03 && dbHeader.bVersion != 0xF5 ) ) - { - bError = TRUE; - if( !pError ) - { - pError = hb_errNew(); - hb_errPutGenCode( pError, EG_CORRUPTION ); - hb_errPutSubCode( pError, EDBF_CORRUPT ); - hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_CORRUPTION ) ); - hb_errPutFileName( pError, pArea->szDataFileName ); - hb_errPutFlags( pError, EF_CANRETRY | EF_CANDEFAULT ); - } - bRetry = ( SELF_ERROR( ( AREAP ) pArea, pError ) == E_RETRY ); - } - else - bRetry = bError = FALSE; - } while( bRetry ); - - if( pError ) - hb_errRelease( pError ); - - /* Read error? */ - if( bError ) - return FAILURE; - - pArea->bDay = dbHeader.bDay; - pArea->bMonth = dbHeader.bMonth; - pArea->bYear = dbHeader.bYear; - pArea->uiHeaderLen = dbHeader.uiHeaderLen; - pArea->ulRecCount = dbHeader.ulRecCount; - pArea->fHasMemo = ( dbHeader.bVersion == 0xF5 ); - pArea->fHasTags = dbHeader.bHasTags; - pArea->bCodePage = dbHeader.bCodePage; - - return SUCCESS; -} - -// ( DBENTRYP_V ) hb_cdxWriteDBHeader -/* - * Write the database file header record in the WorkArea. - */ -ERRCODE hb_cdxWriteDBHeader( CDXAREAP pArea ) -{ - DBFHEADER dbfHeader; - ULONG ulRecCount; - long lYear, lMonth, lDay; - - HB_TRACE(HB_TR_DEBUG, ("hb_cdxWriteDBHeader(%p)", pArea)); - - memset( &dbfHeader, 0, sizeof( DBFHEADER ) ); - dbfHeader.bVersion = (BYTE) (pArea->fHasMemo ? 0xF5 : 0x03); - hb_dateToday( &lYear, &lMonth, &lDay ); - dbfHeader.bYear = ( BYTE ) ( lYear - 1900 ); - dbfHeader.bMonth = ( BYTE ) lMonth; - dbfHeader.bDay = ( BYTE ) lDay; - dbfHeader.bHasTags = ( BYTE ) pArea->fHasTags; - dbfHeader.bCodePage = pArea->bCodePage; - - /* Update record count */ - SELF_RECCOUNT( ( AREAP ) pArea, &ulRecCount ); - - dbfHeader.ulRecCount = ulRecCount; - dbfHeader.uiHeaderLen = pArea->uiHeaderLen; - dbfHeader.uiRecordLen = pArea->uiRecordLen; - hb_fsSeek( pArea->hDataFile, 0, FS_SET ); - hb_fsWrite( pArea->hDataFile, ( BYTE * ) &dbfHeader, sizeof( DBFHEADER ) ); - pArea->fUpdateHeader = FALSE; - return SUCCESS; -} - -// ( DBENTRYP_SVP ) hb_cdxWhoCares : NULL - -/* end of cdxrdd.c */ - diff --git a/harbour/source/rdd/dbfcdx/dbfcdx1.h b/harbour/source/rdd/dbfcdx/dbfcdx1.h index 5862b5aa88..6a68f382bd 100644 --- a/harbour/source/rdd/dbfcdx/dbfcdx1.h +++ b/harbour/source/rdd/dbfcdx/dbfcdx1.h @@ -51,19 +51,9 @@ * */ - /* -#define LOCK_START 0x40000000L -#define LOCK_APPEND 0x7FFFFFFEL -#define LOCK_FILE 0x3FFFFFFFL -#define MEMO_BLOCK 64 -#define CDX_MAX_KEY 240 -#define CDX_BLOCK_SIZE 512 -*/ #define CDX_MAX_TAG_NAME_LEN 10 -#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 @@ -73,6 +63,11 @@ #define BTTM_RECORD 2 #define PREV_RECORD 3 #define NEXT_RECORD 4 +*/ + +#define CDX_INTERNAL_SPACE 500 +#define CDX_EXTERNAL_SPACE 488 + #define SORT_CHUNK_LIMIT 16384 #define SORT_ACTIVE_LIST 0 #define SORT_END_OF_KEY 1 @@ -80,14 +75,12 @@ #define SORT_STACK_OF_CHAR 3 #define SORT_NOT_KEY 0x10 -#define HB_CDXMAXKEY( x ) ((USHORT) ((x) > CDX_MAXKEY ? CDX_MAXKEY : (x))) - #if (__BORLANDC__ > 1040) /* Use this only above Borland C++ 3.1 */ #pragma option -a1 /* byte alignment */ #elif defined(__GNUC__) #pragma pack(1) #elif defined(__WATCOMC__) - #pragma push(pack, 1); + #pragma pack(push, 1); #elif defined(__cplusplus) #pragma pack(1) #endif @@ -122,6 +115,7 @@ typedef struct _CDXDATA CDXINTERNAL Internal; } cdxu; } CDXDATA; +typedef CDXDATA * LPCDXDATA; typedef struct _SORTSWAPPAGE { @@ -154,64 +148,11 @@ typedef SORTSWAPITEM * LPSORTSWAPITEM; #elif defined(__GNUC__) #pragma pack() #elif defined(__WATCOMC__) - #pragma pop(pack); + #pragma pack(pop); #elif defined(__cplusplus) #pragma pack() #endif -typedef CDXDATA * LPCDXDATA; - -typedef struct _CDXKEYINFO -{ - char * Value; - USHORT length; - USHORT realLength; - BOOL fString; - LONG Tag; - LONG Xtra; - struct _CDXKEYINFO * pNext; -} CDXKEYINFO; - -typedef CDXKEYINFO * LPCDXKEYINFO; - -struct _CDXTAG; /* forward declaration */ - -typedef struct HB_CDXPAGEINFO_STRU -{ - LONG Page; - LONG Left; - LONG Right; - BOOL Changed; - BOOL keyAdded; - BYTE bUsed; - BOOL NewRoot; - BOOL LastEntry; - BOOL Reload; - BOOL ChkBOF; - BOOL ChkEOF; - BYTE PageType; - ULONG RNMask; - BYTE ReqByte; - BYTE RNBits; - BYTE DCBits; - BYTE TCBits; - BYTE DCMask; - BYTE TCMask; - /* USHORT Space; */ - SHORT FreeSpace; - LPCDXKEYINFO pKeys; - USHORT uiKeys; - SHORT CurKey; - struct HB_CDXPAGEINFO_STRU * Owner; - struct HB_CDXPAGEINFO_STRU * Child; - struct _CDXTAG * TagParent; - struct HB_CDXPAGEINFO_STRU * pPoolPrev; - struct HB_CDXPAGEINFO_STRU * pPoolNext; -} HB_CDXPAGEINFO; - -typedef HB_CDXPAGEINFO * LPCDXPAGEINFO; - - /*SORT stuff*/ typedef struct { @@ -251,6 +192,18 @@ typedef struct typedef SORTDATA * LPSORTDATA; +typedef struct _CDXKEYINFO +{ + BYTE * Value; + USHORT length; + USHORT realLength; + BOOL fString; + ULONG Tag; + ULONG Xtra; + struct _CDXKEYINFO * pNext; +} CDXKEYINFO; +typedef CDXKEYINFO * LPCDXKEYINFO; + typedef struct { LONG WordCount; diff --git a/harbour/source/rdd/dbfcdx/dbfcdx2.h b/harbour/source/rdd/dbfcdx/dbfcdx2.h deleted file mode 100644 index 1df86d9c21..0000000000 --- a/harbour/source/rdd/dbfcdx/dbfcdx2.h +++ /dev/null @@ -1,197 +0,0 @@ -/* - * $Id$ - */ - -/* - * Harbour Project source code: - * DBFCDX RDD - * - * Copyright 1999 Bruno Cantero - * Copyright 2000-2002 Horacio Roldan (portions) - * www - http://www.harbour-project.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/). - * - * As a special exception, the Harbour Project gives permission for - * additional uses of the text contained in its release of Harbour. - * - * The exception is that, if you link the Harbour libraries with other - * files to produce an executable, this does not by itself cause the - * resulting executable to be covered by the GNU General Public License. - * Your use of that executable is in no way restricted on account of - * linking the Harbour library code into it. - * - * This exception does not however invalidate any other reasons why - * the executable file might be covered by the GNU General Public License. - * - * This exception applies only to the code released by the Harbour - * Project under the name Harbour. If you copy code from other - * Harbour Project or Free Software Foundation releases into a copy of - * Harbour, as the General Public License permits, the exception does - * not apply to the code that you add in this way. To avoid misleading - * anyone as to the status of such modified files, you must delete - * this exception notice from them. - * - * If you write modifications of your own for Harbour, it is your choice - * whether to permit this exception to apply to your modifications. - * If you do not wish that, delete this exception notice. - * - */ - - -static LPCDXKEYINFO hb_cdxKeyNew( void ); -static void hb_cdxKeyFree( LPCDXKEYINFO pKey ); -static int hb_cdxKeyCompare( LPCDXKEYINFO pKey1, LPCDXKEYINFO pKey2, BOOL Exact ); - -static LPCDXTAG hb_cdxTagNew( LPCDXINDEX PIF, char * ITN, LONG TagHdr ); -static void hb_cdxTagFree( LPCDXTAG pTag ); -static void hb_cdxTagIndexTagNew( LPCDXTAG pTag, char * KeyExp, PHB_ITEM pKeyItem, - BYTE bType, USHORT uiLen, char * ForExp, - PHB_ITEM pForItem, BOOL Ascnd, BOOL Uniq, BOOL bCustom ); -static void hb_cdxTagDoIndex( LPCDXTAG pTag ); -static void hb_cdxTagEmptyIndex( LPCDXTAG pTag ); -static void hb_cdxTagTagStore( LPCDXTAG pTag ); -static void hb_cdxTagTagOpen( LPCDXTAG pTag, BYTE bCode ); -static void hb_cdxTagTagClose( LPCDXTAG pTag ); -static LONG hb_cdxTagNewRoot( LPCDXTAG pTag ); -static void hb_cdxTagPageLoad( LPCDXTAG pTag, LPCDXPAGEINFO pPage, short noKeys ); -static void hb_cdxTagKeyRead( LPCDXTAG pTag, BYTE bTypRead ); -static void hb_cdxTagKeyAdd( LPCDXTAG pTag, LPCDXKEYINFO pKey ); -static void hb_cdxTagPageStore( LPCDXTAG pTag, LPCDXPAGEINFO PIK ); -static void hb_cdxTagExtNodeWrite( LPCDXTAG pTag, LONG PN, LPCDXDATA pData, LPCDXPAGEINFO PIK ); -static USHORT hb_cdxTagFillExternalNode( LPCDXTAG pTag, LPCDXDATA pData, LPCDXPAGEINFO PIK, - USHORT kcnt, USHORT ck, LPCDXKEYINFO * p ); -static void hb_cdxTagExtNodeBuild( LPCDXTAG pTag, LPCDXDATA pData, LPCDXPAGEINFO pPage, short noKeys ); -static void hb_cdxTagTagLoad( LPCDXTAG pTag ); -static void hb_cdxTagSetRoot( LPCDXTAG pTag, LPCDXPAGEINFO PIK ); -static void hb_cdxTagIntNodeWrite( LPCDXTAG pTag, LONG PN, LPCDXDATA pData, LPCDXPAGEINFO PIK ); -static USHORT hb_cdxTagFillInternalNode( LPCDXTAG pTag, LPCDXDATA pData, LPCDXPAGEINFO PIK, - USHORT kcnt, USHORT ck, LPCDXKEYINFO * p ); -static void hb_cdxTagIntNodeBuild( LPCDXTAG pTag, LPCDXDATA pData, LPCDXPAGEINFO pPage ); -static LONG hb_cdxTagKeyFind( LPCDXTAG pTag, LPCDXKEYINFO pKey ); - -static LPCDXPAGEINFO hb_cdxPageNew( LPCDXTAG PIT, LPCDXPAGEINFO PIK, LONG FilePosn ); -static void hb_cdxPageFree( LPCDXPAGEINFO pPage ); -static BOOL hb_cdxPageReadTopKey( LPCDXPAGEINFO pPage ); -static BOOL hb_cdxPageReadBottomKey( LPCDXPAGEINFO pPage ); -static int hb_cdxPageSeekKey( LPCDXPAGEINFO pPage, LONG lBlock, LPCDXKEYINFO pKey, BOOL bExact ); -static void hb_cdxPageInsertKey( LPCDXPAGEINFO pPage, LPCDXKEYINFO pKey, BOOL bAddAfter ); -static void hb_cdxPagePageStore( LPCDXPAGEINFO pPage ); -static BOOL hb_cdxPageReadNextKey( LPCDXPAGEINFO pPage ); -static BOOL hb_cdxPageReadPrevKey( LPCDXPAGEINFO pPage ); -static LPCDXKEYINFO hb_cdxPageGetKey( LPCDXPAGEINFO pPage, USHORT uiKey ); -static void hb_cdxPagePageLoad( LPCDXPAGEINFO pPage ); -static int hb_cdxPageRetrieveKey( LPCDXPAGEINFO pPage, LPCDXKEYINFO *pKey ); -static void hb_cdxPageAddNodeKey( LPCDXPAGEINFO pPage, LPCDXKEYINFO pKey ); -static int hb_cdxPageSeekNodeTag( LPCDXPAGEINFO pPage, LONG Tag ); -static BOOL hb_cdxPageGetChild( LPCDXPAGEINFO pPage, LONG Tag ); -static void hb_cdxPageDeleteKey( LPCDXPAGEINFO pPage ); -static void hb_cdxPageReplaceNodeKey( LPCDXPAGEINFO pPage, LPCDXKEYINFO pKey ); -static void hb_cdxPageDeleteNodeKey( LPCDXPAGEINFO pPage ); - -static LPCDXINDEX hb_cdxIndexNew( AREAP pArea ); -static void hb_cdxIndexFree( LPCDXINDEX pIndex ); -static LONG hb_cdxIndexGetAvailPage( LPCDXINDEX pIndex ); -static void hb_cdxIndexPutAvailPage( LPCDXPAGEINFO pPage ); -static void hb_cdxIndexResetAvailPage( LPCDXINDEX pIndex ); -static void hb_cdxIndexPageRead( LPCDXINDEX pIndex, LONG lPos, void * pBuffer, USHORT uiSize ); -static void hb_cdxIndexPageWrite( LPCDXINDEX pIndex, LONG lPos, void * pBuffer, USHORT uiSize ); -static LPCDXTAG hb_cdxIndexAddTag( LPCDXINDEX pIndex, char * szTagName, char * szKeyExp, - PHB_ITEM pKeyItem, BYTE bType, USHORT uiLen, char * szForExp, - PHB_ITEM pForItem, BOOL bAscending, BOOL bUnique, BOOL bCustom ); - -static LPSORTINFO hb_cdxSortNew( LPCDXTAG 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, - USHORT uiLen ); -static void hb_cdxSortStuffKey( LPSORTINFO pSort, LPSORTDATA * wx, BOOL fTag ); -static void hb_cdxSortGetNode( LPSORTINFO pSort, BYTE Character, - LONG * NewLink, BOOL fTag ); -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, BYTE * Value ); -static void hb_cdxSortOutputWord( LPSORTINFO pSort, LONG Tag, BYTE * Value, - USHORT uiLen ); -static void hb_cdxSortAddToNode( LPSORTINFO pSort, USHORT Lvl, LONG Tag, LONG Link, - LPCDXKEYINFO Value ); -static void hb_cdxSortAddExternal( LPSORTINFO pSort, USHORT Lvl, LONG Tag, LONG Link, - LPCDXKEYINFO Value ); -static void hb_cdxSortAddInternal( LPSORTINFO pSort, USHORT Lvl, LONG Tag, LONG Link, - LPCDXKEYINFO Value ); - -/* static LPCDXTAG hb_cdxGetActiveTag( LPCDXINDEX PIF ); */ -static LPCDXTAG hb_cdxGetActiveTag( CDXAREAP pArea ); -static USHORT hb_cdxFindTag( CDXAREAP pArea, LPDBORDERINFO pOrderInfo ); -static LPCDXTAG hb_cdxGetTagByNumber(CDXAREAP pArea, USHORT uiTag ); -static USHORT hb_cdxGetTagNumber(CDXAREAP pArea, LPCDXTAG pFindTag); -static PHB_ITEM hb_cdxKeyGetItem( LPCDXKEYINFO pKey, PHB_ITEM pItem, USHORT uiType ); -static LPCDXTAG hb_cdxReorderTagList ( LPCDXTAG TagList ); -static ERRCODE hb_cdxGoEof( CDXAREAP pArea ); -static BOOL hb_cdxTopScope( LPCDXTAG pTag, LPCDXKEYINFO pKey ); -static BOOL hb_cdxBottomScope( LPCDXTAG pTag, LPCDXKEYINFO pKey ); -static void hb_cdxTagClearScope( LPCDXTAG pTag, USHORT nScope ); - - -static USHORT hb_cdxIndexCheckVersion( LPCDXINDEX pIndex ); -static USHORT hb_cdxIndexUnLockRead( LPCDXINDEX pIndex, LPCDXTAG pTag ); -static USHORT hb_cdxIndexLockRead( LPCDXINDEX pIndex, LPCDXTAG pTag ); -static USHORT hb_cdxIndexLockWrite ( LPCDXINDEX pIndex, LPCDXTAG pTag ); -static USHORT hb_cdxIndexUnLockWrite ( LPCDXINDEX pIndex, LPCDXTAG pTag ); -static void hb_cdxIndexDelTag( LPCDXINDEX pIndex, char * szTagName ); - -static int hb_cdxKeyValCompare( LPCDXTAG pTag, char * pKeyVal1, BYTE keyLen1, - char * pKeyVal2, BYTE keyLen2, BOOL Exact ); -static void hb_cdxMacroRun( AREAP pArea, HB_MACRO_PTR pMacro ); -static ERRCODE cdxError( CDXAREAP pArea, USHORT uiGenCode, USHORT uiSubCode, char * filename, USHORT uiFlags ); -static void hb_cdxIndexReindex( LPCDXINDEX pIndex ); -static ERRCODE hb_cdxOrdListClear( CDXAREAP pArea, int iComplete, LPCDXINDEX pKeepIndex ); -static LPCDXINDEX hb_cdxFindBag( CDXAREAP pArea, char * szBagName ); -static LPCDXKEYINFO hb_cdxEvalKey( CDXAREAP pArea, LPCDXTAG pTag ); -static BOOL hb_cdxEvalCond ( CDXAREAP pArea, PHB_ITEM pCondItem, BOOL checkenv ); - - -static BYTE hb_cdxPageKeyLeafInsert( LPCDXPAGEINFO pPage, LPCDXKEYINFO pKey, BOOL bAddAfter ); -static BYTE hb_cdxPageKeyInsert( LPCDXPAGEINFO pPage, LPCDXKEYINFO pKey, BOOL bAddAfter ); -static void hb_cdxPageCalcLeafSpace( LPCDXPAGEINFO pPage ); -static SHORT hb_cdxPageCalcLeafKeySpace( LPCDXPAGEINFO pPage, - LPCDXKEYINFO pKeyPrev, LPCDXKEYINFO pKey, LPCDXKEYINFO pKeyNext); -static BYTE hb_cdxPageKeyLeafBalance( LPCDXPAGEINFO pPage ); -static BYTE hb_cdxPageKeyIntBalance( LPCDXPAGEINFO pPage ); -static BYTE hb_cdxPageRootSplit( LPCDXPAGEINFO pPage ); - -static BYTE hb_cdxPageKeyDelete( LPCDXPAGEINFO pPage ); -static BYTE hb_cdxPageKeyLeafDelete( LPCDXPAGEINFO pPage ); - -static void hb_cdxPagePoolFree( LPCDXINDEX pIndex, int nPagesLeft ); -static void hb_cdxPagePoolFreeTag( LPCDXTAG pTag, int nPagesLeft ); -static void hb_cdxPagePoolFlush( LPCDXINDEX pIndex ); -static void hb_cdxPagePoolFlushTag( LPCDXTAG pTag ); -static void hb_cdxPageRealFree( LPCDXPAGEINFO pPage ); - -static void hb_cdxKeyListFree( LPCDXKEYINFO pKeyList ); -static LPCDXKEYINFO hb_cdxKeyListGetKey ( LPCDXKEYINFO pKeyList, USHORT uiKey ); -static LPCDXKEYINFO hb_cdxKeyListGetLast ( LPCDXKEYINFO pKeyList ); - -#define FAST_GOCOLD(A) ( ((CDXAREAP) (A))->fRecordChanged ? ( SELF_GOCOLD( (A) ) ) : SUCCESS ) - -static void hb_cdxErrInternal ( char * szMsg ); -#ifndef HB_CDX_DBGCODE_OFF -static void hb_cdxPagePoolCheck( LPCDXTAG pTag ); -static void hb_cdxPageLeafCheckKeys( LPCDXPAGEINFO pPage ); -#endif diff --git a/harbour/source/rdd/dbfdbt/Makefile b/harbour/source/rdd/dbfdbt/Makefile new file mode 100644 index 0000000000..68e1e78fb9 --- /dev/null +++ b/harbour/source/rdd/dbfdbt/Makefile @@ -0,0 +1,15 @@ +# +# $Id$ +# + +ROOT = ../../../ + +C_SOURCES=\ + dbfdbt1.c \ + +PRG_SOURCES=\ + dbfdbt0.prg \ + +LIBNAME=dbfdbt + +include $(TOP)$(ROOT)config/lib.cf diff --git a/harbour/source/rdd/dbfdbt/dbfdbt0.prg b/harbour/source/rdd/dbfdbt/dbfdbt0.prg new file mode 100644 index 0000000000..01b9ee49eb --- /dev/null +++ b/harbour/source/rdd/dbfdbt/dbfdbt0.prg @@ -0,0 +1,64 @@ +/* + * $Id$ + */ + +/* + * Harbour Project source code: + * DBFDBT RDD + * + * Copyright 2003 Przemyslaw Czerpak + * www - http://www.xharbour.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/). + * + * As a special exception, the Harbour Project gives permission for + * additional uses of the text contained in its release of Harbour. + * + * The exception is that, if you link the Harbour libraries with other + * files to produce an executable, this does not by itself cause the + * resulting executable to be covered by the GNU General Public License. + * Your use of that executable is in no way restricted on account of + * linking the Harbour library code into it. + * + * This exception does not however invalidate any other reasons why + * the executable file might be covered by the GNU General Public License. + * + * This exception applies only to the code released by the Harbour + * Project under the name Harbour. If you copy code from other + * Harbour Project or Free Software Foundation releases into a copy of + * Harbour, as the General Public License permits, the exception does + * not apply to the code that you add in this way. To avoid misleading + * anyone as to the status of such modified files, you must delete + * this exception notice from them. + * + * If you write modifications of your own for Harbour, it is your choice + * whether to permit this exception to apply to your modifications. + * If you do not wish that, delete this exception notice. + * + */ + +#include "rddsys.ch" + +ANNOUNCE DBFDBT + +procedure DBFDBTInit + + REQUEST _DBFDBT + + rddRegister( "DBF", RDT_FULL ) + rddRegister( "DBFDBT", RDT_FULL ) + +return diff --git a/harbour/source/rdd/dbfdbt/dbfdbt1.c b/harbour/source/rdd/dbfdbt/dbfdbt1.c new file mode 100644 index 0000000000..ed82d1f4e9 --- /dev/null +++ b/harbour/source/rdd/dbfdbt/dbfdbt1.c @@ -0,0 +1,748 @@ +/* + * $Id$ + */ + +/* + * xHarbour Project source code: + * DBFDBT RDD + * + * Copyright 2003 Przemyslaw Czerpak + * www - http://www.xharbour.org + * Most of code taken from dbf1.c + * 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, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/). + * + * As a special exception, the Harbour Project gives permission for + * additional uses of the text contained in its release of Harbour. + * + * The exception is that, if you link the Harbour libraries with other + * files to produce an executable, this does not by itself cause the + * resulting executable to be covered by the GNU General Public License. + * Your use of that executable is in no way restricted on account of + * linking the Harbour library code into it. + * + * This exception does not however invalidate any other reasons why + * the executable file might be covered by the GNU General Public License. + * + * This exception applies only to the code released by the Harbour + * Project under the name Harbour. If you copy code from other + * Harbour Project or Free Software Foundation releases into a copy of + * Harbour, as the General Public License permits, the exception does + * not apply to the code that you add in this way. To avoid misleading + * anyone as to the status of such modified files, you must delete + * this exception notice from them. + * + * If you write modifications of your own for Harbour, it is your choice + * whether to permit this exception to apply to your modifications. + * If you do not wish that, delete this exception notice. + * + */ + +#include "hbapi.h" +#include "hbinit.h" +#include "hbapierr.h" +#include "hbapilng.h" +#include "hbset.h" +#include "hbdate.h" +#include "hbrdddbt.h" + +#ifndef HB_CDP_SUPPORT_OFF +# include "hbapicdp.h" + extern PHB_CODEPAGE s_cdpage; +#endif + +#define __PRG_SOURCE__ __FILE__ +#ifndef __XHARBOUR__ +# define HB_VM_STACK hb_stack +#endif +#ifdef HB_PCODE_VER +# undef HB_PRG_PCODE_VER +# define HB_PRG_PCODE_VER HB_PCODE_VER +#endif + +static RDDFUNCS dbtSuper; +static RDDFUNCS dbtTable = +{ + + /* Movement and positioning methods */ + + ( DBENTRYP_BP ) hb_dbtBof, + ( DBENTRYP_BP ) hb_dbtEof, + ( DBENTRYP_BP ) hb_dbtFound, + ( DBENTRYP_V ) hb_dbtGoBottom, + ( DBENTRYP_UL ) hb_dbtGoTo, + ( DBENTRYP_I ) hb_dbtGoToId, + ( DBENTRYP_V ) hb_dbtGoTop, + ( DBENTRYP_BIB ) hb_dbtSeek, + ( DBENTRYP_L ) hb_dbtSkip, + ( DBENTRYP_L ) hb_dbtSkipFilter, + ( DBENTRYP_L ) hb_dbtSkipRaw, + + + /* Data management */ + + ( DBENTRYP_VF ) hb_dbtAddField, + ( DBENTRYP_B ) hb_dbtAppend, + ( DBENTRYP_I ) hb_dbtCreateFields, + ( DBENTRYP_V ) hb_dbtDeleteRec, + ( DBENTRYP_BP ) hb_dbtDeleted, + ( DBENTRYP_SP ) hb_dbtFieldCount, + ( DBENTRYP_VF ) hb_dbtFieldDisplay, + ( DBENTRYP_SSI ) hb_dbtFieldInfo, + ( DBENTRYP_SVP ) hb_dbtFieldName, + ( DBENTRYP_V ) hb_dbtFlush, + ( DBENTRYP_PP ) hb_dbtGetRec, + ( DBENTRYP_SI ) hb_dbtGetValue, + ( DBENTRYP_SVL ) hb_dbtGetVarLen, + ( DBENTRYP_V ) hb_dbtGoCold, + ( DBENTRYP_V ) hb_dbtGoHot, + ( DBENTRYP_P ) hb_dbtPutRec, + ( DBENTRYP_SI ) hb_dbtPutValue, + ( DBENTRYP_V ) hb_dbtRecall, + ( DBENTRYP_ULP ) hb_dbtRecCount, + ( DBENTRYP_ISI ) hb_dbtRecInfo, + ( DBENTRYP_I ) hb_dbtRecNo, + ( DBENTRYP_S ) hb_dbtSetFieldExtent, + + + /* WorkArea/Database management */ + + ( DBENTRYP_P ) hb_dbtAlias, + ( DBENTRYP_V ) hb_dbtClose, + ( DBENTRYP_VP ) hb_dbtCreate, + ( DBENTRYP_SI ) hb_dbtInfo, + ( DBENTRYP_V ) hb_dbtNewArea, + ( DBENTRYP_VP ) hb_dbtOpen, + ( DBENTRYP_V ) hb_dbtRelease, + ( DBENTRYP_SP ) hb_dbtStructSize, + ( DBENTRYP_P ) hb_dbtSysName, + ( DBENTRYP_VEI ) hb_dbtEval, + ( DBENTRYP_V ) hb_dbtPack, + ( DBENTRYP_LSP ) hb_dbtPackRec, + ( DBENTRYP_VS ) hb_dbtSort, + ( DBENTRYP_VT ) hb_dbtTrans, + ( DBENTRYP_VT ) hb_dbtTransRec, + ( DBENTRYP_V ) hb_dbtZap, + + + /* Relational Methods */ + + ( DBENTRYP_VR ) hb_dbtChildEnd, + ( DBENTRYP_VR ) hb_dbtChildStart, + ( DBENTRYP_VR ) hb_dbtChildSync, + ( DBENTRYP_V ) hb_dbtSyncChildren, + ( DBENTRYP_V ) hb_dbtClearRel, + ( DBENTRYP_V ) hb_dbtForceRel, + ( DBENTRYP_SVP ) hb_dbtRelArea, + ( DBENTRYP_VR ) hb_dbtRelEval, + ( DBENTRYP_SVP ) hb_dbtRelText, + ( DBENTRYP_VR ) hb_dbtSetRel, + + + /* Order Management */ + + ( DBENTRYP_OI ) hb_dbtOrderListAdd, + ( DBENTRYP_V ) hb_dbtOrderListClear, + ( DBENTRYP_VP ) hb_dbtOrderListDelete, + ( DBENTRYP_OI ) hb_dbtOrderListFocus, + ( DBENTRYP_V ) hb_dbtOrderListRebuild, + ( DBENTRYP_VOI ) hb_dbtOrderCondition, + ( DBENTRYP_VOC ) hb_dbtOrderCreate, + ( DBENTRYP_OI ) hb_dbtOrderDestroy, + ( DBENTRYP_OII ) hb_dbtOrderInfo, + + + /* Filters and Scope Settings */ + + ( DBENTRYP_V ) hb_dbtClearFilter, + ( DBENTRYP_V ) hb_dbtClearLocate, + ( DBENTRYP_V ) hb_dbtClearScope, + ( DBENTRYP_VPLP ) hb_dbtCountScope, + ( DBENTRYP_I ) hb_dbtFilterText, + ( DBENTRYP_SI ) hb_dbtScopeInfo, + ( DBENTRYP_VFI ) hb_dbtSetFilter, + ( DBENTRYP_VLO ) hb_dbtSetLocate, + ( DBENTRYP_VOS ) hb_dbtSetScope, + ( DBENTRYP_VPL ) hb_dbtSkipScope, + + + /* Miscellaneous */ + + ( DBENTRYP_P ) hb_dbtCompile, + ( DBENTRYP_I ) hb_dbtError, + ( DBENTRYP_I ) hb_dbtEvalBlock, + + + /* Network operations */ + + ( DBENTRYP_VSP ) hb_dbtRawLock, + ( DBENTRYP_VL ) hb_dbtLock, + ( DBENTRYP_UL ) hb_dbtUnLock, + + + /* Memofile functions */ + + ( DBENTRYP_V ) hb_dbtCloseMemFile, + ( DBENTRYP_VP ) hb_dbtCreateMemFile, + ( DBENTRYP_SVPB ) hb_dbtGetValueFile, + ( DBENTRYP_VP ) hb_dbtOpenMemFile, + ( DBENTRYP_SVP ) hb_dbtPutValueFile, + + + /* Database file header handling */ + + ( DBENTRYP_V ) hb_dbtReadDBHeader, + ( DBENTRYP_V ) hb_dbtWriteDBHeader, + + + /* non WorkArea functions */ + ( DBENTRYP_I0 ) hb_dbtExit, + ( DBENTRYP_I1 ) hb_dbtDrop, + ( DBENTRYP_I2 ) hb_dbtExists, + + /* Special and reserved methods */ + + ( DBENTRYP_SVP ) hb_dbtWhoCares +}; + + +HB_FUNC( _DBFDBT ) {;} + +HB_FUNC( DBFDBT_GETFUNCTABLE ) +{ + RDDFUNCS * pTable; + USHORT * uiCount; + + uiCount = ( USHORT * ) hb_itemGetPtr( hb_param( 1, HB_IT_POINTER ) ); + pTable = ( RDDFUNCS * ) hb_itemGetPtr( hb_param( 2, HB_IT_POINTER ) ); + + HB_TRACE(HB_TR_DEBUG, ("DBFDBT_GETFUNCTABLE(%i, %p)", uiCount, pTable)); + + if( pTable ) + { + if ( uiCount ) + * uiCount = RDDFUNCSCOUNT; + hb_retni( hb_rddInherit( pTable, &dbtTable, &dbtSuper, ( BYTE * ) "DBF" ) ); + } + else + hb_retni( FAILURE ); +} + + +HB_INIT_SYMBOLS_BEGIN( dbfdbt1__InitSymbols ) +{ "_DBFDBT", HB_FS_PUBLIC, HB_FUNCNAME( _DBFDBT ), NULL }, +{ "DBFDBT_GETFUNCTABLE", HB_FS_PUBLIC, HB_FUNCNAME( DBFDBT_GETFUNCTABLE ), NULL } +HB_INIT_SYMBOLS_END( dbfdbt1__InitSymbols ) + +#if defined(HB_STATIC_STARTUP) +# pragma startup dbfdbt1__InitSymbols +#elif defined(_MSC_VER) +# if _MSC_VER >= 1010 +# pragma data_seg( ".CRT$XIY" ) +# pragma comment( linker, "/Merge:.CRT=.data" ) +# else +# pragma data_seg( "XIY" ) +# endif + static HB_$INITSYM hb_vm_auto_dbfdbt1__InitSymbols = dbfdbt1__InitSymbols; +# pragma data_seg() +#elif ! defined(__GNUC__) +# pragma startup dbfdbt1__InitSymbols +#endif + +/* + * Exclusive lock memo file. + */ +static BOOL hb_dbtFileLockEx( DBTAREAP pArea ) +{ + BOOL bRet; + + while ( ! ( bRet = hb_fsLock( pArea->hMemoFile, DBT_LOCKPOS, DBT_LOCKSIZE, + FL_LOCK | FLX_EXCLUSIVE | FLX_WAIT ) ) ); + return bRet; +} + +/* + * Shared lock memo file. + */ +static BOOL hb_dbtFileLockSh( DBTAREAP pArea ) +{ + BOOL bRet; + + while ( ! ( bRet = hb_fsLock( pArea->hMemoFile, DBT_LOCKPOS, DBT_LOCKSIZE, + FL_LOCK | FLX_SHARED | FLX_WAIT ) ) ); + return bRet; +} + +/* + * Unlock memo file. + */ +static BOOL hb_dbtFileUnLock( DBTAREAP pArea ) +{ + return hb_fsLock( pArea->hMemoFile, DBT_LOCKPOS, DBT_LOCKSIZE, FL_UNLOCK ); +} + +/* + * Return the size of memo. + */ +static ULONG hb_dbtGetMemoLen( DBTAREAP pArea, USHORT uiIndex ) +{ + ULONG ulBlock; + BYTE pBlock[ DBT_BLOCKSIZE ]; + + HB_TRACE(HB_TR_DEBUG, ("hb_dbtGetMemoLen(%p, %hu)", pArea, uiIndex)); + + ulBlock = hb_dbfGetMemoBlock( ( DBFAREAP ) pArea, uiIndex ); + if( ulBlock == 0 ) + return 0; + hb_fsSeek( pArea->hMemoFile, ulBlock * DBT_BLOCKSIZE, FS_SET ); + ulBlock = 0; + do + { + hb_fsRead( pArea->hMemoFile, pBlock, DBT_BLOCKSIZE ); + uiIndex = 0; + while( uiIndex < DBT_BLOCKSIZE && pBlock[ uiIndex ] != 0x1A ) + uiIndex++; + ulBlock += uiIndex; + } while( uiIndex == DBT_BLOCKSIZE ); + return ulBlock; +} + +/* + * Read memo data. + */ +static void hb_dbtGetMemo( DBTAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) +{ + ULONG ulSize, ulBlock; + BYTE * pBuffer; + + HB_TRACE(HB_TR_DEBUG, ("hb_dbtGetMemo(%p, %hu, %p)", pArea, uiIndex, pItem)); + + ulSize = hb_dbtGetMemoLen( pArea, uiIndex ); + + pBuffer = ( BYTE * ) hb_xgrab( ulSize + 1 ); + if( ulSize > 0 ) + { + ulBlock = hb_dbfGetMemoBlock( ( DBFAREAP ) pArea, uiIndex ); + hb_fsSeek( pArea->hMemoFile, ulBlock * DBT_BLOCKSIZE, FS_SET ); + hb_fsReadLarge( pArea->hMemoFile, pBuffer, ulSize ); + } + else + *pBuffer = '\0'; + + hb_itemPutCPtr( pItem, ( char * ) pBuffer, ulSize ); +#ifndef HB_CDP_SUPPORT_OFF + hb_cdpTranslate( pItem->item.asString.value, pArea->cdPage, s_cdpage ); +#endif + hb_itemSetCMemo( pItem ); +} + +/* + * Write memo data. + */ +static void hb_dbtWriteMemo( DBTAREAP pArea, ULONG ulBlock, PHB_ITEM pItem, ULONG ulLen, + ULONG * ulStoredBlock ) +{ + BYTE pBlock[ DBT_BLOCKSIZE ]; + BOOL bNewBlock; + ULONG ulNewBlock, ulNextBlock; + + HB_TRACE(HB_TR_DEBUG, ("hb_dbtWriteMemo(%p, %lu, %p, %lu, %p)", pArea, ulBlock, pItem, + ulLen, ulStoredBlock)); + + memset( pBlock, 0x1A, DBT_BLOCKSIZE ); + bNewBlock = !( ulBlock && ulLen < DBT_BLOCKSIZE - 1 ); + if( bNewBlock ) + { + /* Get next block from header */ + hb_fsSeek( pArea->hMemoFile, 0, FS_SET ); + hb_fsRead( pArea->hMemoFile, ( BYTE * ) &ulNewBlock, sizeof( ulNewBlock ) ); + ulNextBlock = ulNewBlock * DBT_BLOCKSIZE; + hb_fsSeek( pArea->hMemoFile, ulNextBlock, FS_SET ); + } + else + { + hb_fsSeek( pArea->hMemoFile, ulBlock * DBT_BLOCKSIZE, FS_SET ); + ulNewBlock = ulBlock; + } + * ulStoredBlock = ulNewBlock; + +#ifndef HB_CDP_SUPPORT_OFF + hb_cdpTranslate( pItem->item.asString.value, s_cdpage, pArea->cdPage ); +#endif + /* Write memo data and eof mark */ + hb_fsWriteLarge( pArea->hMemoFile, ( BYTE * ) hb_itemGetCPtr( pItem ), ulLen ); + hb_fsWrite( pArea->hMemoFile, pBlock, ( DBT_BLOCKSIZE - ( USHORT ) ( ulLen % DBT_BLOCKSIZE ) ) ); +#ifndef HB_CDP_SUPPORT_OFF + hb_cdpTranslate( pItem->item.asString.value, pArea->cdPage, s_cdpage ); +#endif + + if( bNewBlock ) + { + ulNextBlock += ulLen + 1; + ulNextBlock += ( DBT_BLOCKSIZE - ulNextBlock % DBT_BLOCKSIZE ); + ulNextBlock /= DBT_BLOCKSIZE; + hb_fsSeek( pArea->hMemoFile, 0, FS_SET ); + hb_fsWrite( pArea->hMemoFile, ( BYTE * ) &ulNextBlock, sizeof( ulNextBlock ) ); + } +} + +/* + * Assign a value to the specified memo field. + */ +static BOOL hb_dbtPutMemo( DBTAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) +{ + ULONG ulLen, ulBlock; + + HB_TRACE(HB_TR_DEBUG, ("hb_dbtPutMemo(%p, %hu, %p)", pArea, uiIndex, pItem)); + + ulLen = hb_itemGetCLen( pItem ); + if( ulLen > 0 ) + { + ulBlock = hb_dbfGetMemoBlock( ( DBFAREAP ) pArea, uiIndex ); + hb_dbtWriteMemo( pArea, ulBlock, pItem, ulLen, &ulBlock ); + } + else + ulBlock = 0; + hb_dbfPutMemoBlock( ( DBFAREAP ) pArea, uiIndex, ulBlock ); + return TRUE; +} + + +/* DBT METHODS */ + +/* + * Obtain the length of a field value. + * ( DBENTRYP_SVL ) hb_dbtGetVarLen + */ +static ERRCODE hb_dbtGetVarLen( DBTAREAP pArea, USHORT uiIndex, ULONG * pLength ) +{ + BOOL bDeleted; + + HB_TRACE(HB_TR_DEBUG, ("hb_dbtGetVarLen(%p, %hu, %p)", pArea, uiIndex, pLength)); + + if( pArea->fHasMemo && pArea->hMemoFile != FS_ERROR ) + { + /* Force read record */ + if( SELF_DELETED( ( AREAP ) pArea, &bDeleted ) == FAILURE ) + return FAILURE; + + if( pArea->lpFields[ uiIndex - 1 ].uiType == HB_IT_MEMO ) + { + if( hb_dbtFileLockSh( pArea ) ) + { + * pLength = hb_dbtGetMemoLen( pArea, uiIndex - 1 ); + hb_dbtFileUnLock( pArea ); + } + else + { + * pLength = 0; + } + return SUCCESS; + } + } + + return SUPER_GETVARLEN( ( AREAP ) pArea, uiIndex, pLength ); +} + +/* + * Retrieve information about the current driver. + * ( DBENTRYP_SI ) hb_dbtInfo + */ +static ERRCODE hb_dbtInfo( DBTAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_dbtInfo(%p, %hu, %p)", pArea, uiIndex, pItem)); + + switch( uiIndex ) + { + case DBI_MEMOEXT: + hb_itemPutC( pItem, DBT_MEMOEXT ); + break; + + /* case DBI_RDD_VERSION */ + + default: + return SUPER_INFO( ( AREAP ) pArea, uiIndex, pItem ); + } + + return SUCCESS; +} + +/* + * Retrieve the size of the WorkArea structure. + * ( DBENTRYP_SP ) hb_dbtStructSize + */ +static ERRCODE hb_dbtStructSize( DBTAREAP pArea, USHORT * uiSize ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_dbtStrucSize(%p, %p)", pArea, uiSize)); + HB_SYMBOL_UNUSED( pArea ); + + * uiSize = sizeof( DBTAREA ); + return SUCCESS; +} + +/* + * Obtain the name of replaceable database driver (RDD) subsystem. + * ( DBENTRYP_P ) hb_dbtSysName + */ +static ERRCODE hb_dbtSysName( DBTAREAP pArea, BYTE * pBuffer ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_dbtSysName(%p, %p)", pArea, pBuffer)); + HB_SYMBOL_UNUSED( pArea ); + + strncpy( ( char * ) pBuffer, "DBFDBT", 7 /* HARBOUR_MAX_RDD_DRIVERNAME_LENGTH */ ); + return SUCCESS; +} + +/* + * Obtain the current value of a field. + * ( DBENTRYP_SI ) hb_dbtGetValue + */ +static ERRCODE hb_dbtGetValue( DBTAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) +{ + BOOL bDeleted; + + HB_TRACE(HB_TR_DEBUG, ("hb_dbtGetValue(%p, %hu, %p)", pArea, uiIndex, pItem)); + + if( pArea->fHasMemo && pArea->hMemoFile != FS_ERROR && + pArea->lpFields[ uiIndex - 1 ].uiType == HB_IT_MEMO ) + { + /* Force read record */ + if( SELF_DELETED( ( AREAP ) pArea, &bDeleted ) == FAILURE ) + return FAILURE; + + if( hb_dbtFileLockSh( pArea ) ) + { + hb_dbtGetMemo( pArea, uiIndex - 1, pItem ); + hb_dbtFileUnLock( pArea ); + } + else + { + PHB_ITEM pError = hb_errNew(); + + hb_errPutGenCode( pError, EG_LOCK ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_LOCK ) ); + hb_errPutSubCode( pError, EDBF_LOCK ); + hb_errPutFlags( pError, EF_CANDEFAULT ); + SELF_ERROR( ( AREAP ) pArea, pError ); + hb_errRelease( pError ); + return FAILURE; + } + return SUCCESS; + } + else + return SUPER_GETVALUE( ( AREAP ) pArea, uiIndex, pItem ); +} + +/* + * Assign a value to a field. + * ( DBENTRYP_SI ) hb_dbtPutValue + */ +static ERRCODE hb_dbtPutValue( DBTAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) +{ + BOOL bDeleted; + PHB_ITEM pError; + ERRCODE uiError, uiErrorG; + + HB_TRACE(HB_TR_DEBUG, ("hb_dbtPutValue(%p, %hu, %p)", pArea, uiIndex, pItem)); + + if( pArea->fHasMemo && pArea->hMemoFile != FS_ERROR && + pArea->lpFields[ uiIndex - 1 ].uiType == HB_IT_MEMO ) + { + if( HB_IS_MEMO( pItem ) || HB_IS_STRING( pItem ) ) + { + /* Force read record */ + if( SELF_DELETED( ( AREAP ) pArea, &bDeleted ) == FAILURE ) + return FAILURE; + + if( !pArea->fPositioned ) + return SUCCESS; + + /* Buffer is hot? */ + if( !pArea->fRecordChanged && SELF_GOHOT( ( AREAP ) pArea ) == FAILURE ) + return FAILURE; + + if( hb_dbtFileLockEx( pArea ) ) + { + uiError = hb_dbtPutMemo( pArea, uiIndex -1, pItem ) ? SUCCESS : EDBF_DATAWIDTH; + hb_dbtFileUnLock( pArea ); + } + else + { + uiError = EDBF_LOCK; + } + /* Update deleted flag */ + pArea->pRecord[ 0 ] = (BYTE) (pArea->fDeleted ? '*' : ' '); + } + else + uiError = EDBF_DATATYPE; + + if( uiError != SUCCESS ) + { + uiErrorG = uiError == EDBF_DATAWIDTH ? EG_DATAWIDTH : + ( uiError == EDBF_LOCK ? EG_LOCK : EG_DATATYPE ); + pError = hb_errNew(); + hb_errPutGenCode( pError, uiErrorG ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( uiErrorG ) ); + hb_errPutSubCode( pError, uiError ); + hb_errPutFlags( pError, EF_CANDEFAULT ); + SELF_ERROR( ( AREAP ) pArea, pError ); + hb_errRelease( pError ); + return FAILURE; + } + return SUCCESS; + } + return SUPER_PUTVALUE( ( AREAP ) pArea, uiIndex, pItem); +} + + +/* ( DBENTRYP_V ) hb_dbtCloseMemFile : NULL */ + +/* + * Create a memo file in the WorkArea. + * ( DBENTRYP_VP ) hb_dbtCreateMemFile + */ +static ERRCODE hb_dbtCreateMemFile( DBTAREAP pArea, LPDBOPENINFO pCreateInfo ) +{ + BYTE pBlock[ DBT_BLOCKSIZE ]; + BOOL bRetry; + PHB_ITEM pError; + + HB_TRACE(HB_TR_DEBUG, ("hb_dbtCreateMemFile(%p, %p)", pArea, pCreateInfo)); + + pArea->uiMemoBlockSize = DBT_BLOCKSIZE; + + if( pCreateInfo ) + { + pError = NULL; + /* Try create */ + do + { + pArea->hMemoFile = hb_spCreate( pCreateInfo->abName, FC_NORMAL ); + if( pArea->hMemoFile == FS_ERROR ) + { + if( !pError ) + { + pError = hb_errNew(); + hb_errPutGenCode( pError, EG_CREATE ); + hb_errPutSubCode( pError, EDBF_CREATE_DBF ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_CREATE ) ); + hb_errPutFileName( pError, ( char * ) pCreateInfo->abName ); + hb_errPutFlags( pError, EF_CANRETRY ); + } + bRetry = ( SELF_ERROR( ( AREAP ) pArea, pError ) == E_RETRY ); + } + else + bRetry = FALSE; + } while( bRetry ); + if( pError ) + hb_errRelease( pError ); + + if( pArea->hMemoFile == FS_ERROR ) + return FAILURE; + } + else /* For zap file */ + hb_fsSeek( pArea->hMemoFile, 0, FS_SET ); + + memset( pBlock, 0, DBT_BLOCKSIZE ); + * ( ( LONG * ) pBlock ) = 1; + if( hb_fsWrite( pArea->hMemoFile, pBlock, DBT_BLOCKSIZE ) != DBT_BLOCKSIZE ) + return FAILURE; + hb_fsWrite( pArea->hMemoFile, NULL, 0 ); + + return SUCCESS; +} + + +/* ( DBENTRYP_SVPB ) hb_dbtGetValueFile : NULL */ + +/* + * Open a memo file in the specified WorkArea. + * ( DBENTRYP_VP ) hb_dbtOpenMemFile + */ +static ERRCODE hb_dbtOpenMemFile( DBTAREAP pArea, LPDBOPENINFO pOpenInfo ) +{ + USHORT uiFlags; + BOOL bRetry; + PHB_ITEM pError = NULL; + + HB_TRACE(HB_TR_DEBUG, ("hb_dbtOpenMemFile(%p, %p)", pArea, pOpenInfo)); + + uiFlags = (pOpenInfo->fReadonly ? FO_READ : FO_READWRITE) | + (pOpenInfo->fShared ? FO_DENYNONE : FO_EXCLUSIVE); + + /* Try open */ + do + { + pArea->hMemoFile = hb_spOpen( pOpenInfo->abName, uiFlags ); + if( pArea->hMemoFile == FS_ERROR ) + { + if( !pError ) + { + pError = hb_errNew(); + hb_errPutGenCode( pError, EG_OPEN ); + hb_errPutSubCode( pError, EDBF_OPEN_DBF ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_OPEN ) ); + hb_errPutFileName( pError, ( char * ) pOpenInfo->abName ); + hb_errPutFlags( pError, EF_CANRETRY | EF_CANDEFAULT ); + } + bRetry = ( SELF_ERROR( ( AREAP ) pArea, pError ) == E_RETRY ); + } + else + bRetry = FALSE; + } while( bRetry ); + + if( pError ) + { + hb_errRelease( pError ); + } + pArea->uiMemoBlockSize = DBT_BLOCKSIZE; + + return ( pArea->hMemoFile == FS_ERROR ? FAILURE : SUCCESS ); +} + +/* ( DBENTRYP_SVP ) hb_dbtPutValueFile : NULL */ + +/* + * Read the database file header record in the WorkArea. + * ( DBENTRYP_V ) hb_dbtReadDBHeader + */ +static ERRCODE hb_dbtReadDBHeader( DBTAREAP pArea ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_dbtReadHeader(%p)", pArea)); + + if( SUPER_READDBHEADER( ( AREAP ) pArea ) == FAILURE ) + return FAILURE; + + pArea->fHasMemo = ( pArea->bVersion == 0x83 ); + + return SUCCESS; +} + +/* + * Write the database file header record in the WorkArea. + * ( DBENTRYP_V ) hb_dbtWriteDBHeader + */ +static ERRCODE hb_dbtWriteDBHeader( DBTAREAP pArea ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_dbtWriteDBHeader(%p)", pArea)); + + if ( pArea->fHasMemo ) + pArea->bVersion = 0x83; + + return SUPER_WRITEDBHEADER( ( AREAP ) pArea ); +} diff --git a/harbour/source/rdd/dbffpt/Makefile b/harbour/source/rdd/dbffpt/Makefile new file mode 100644 index 0000000000..ec5012384e --- /dev/null +++ b/harbour/source/rdd/dbffpt/Makefile @@ -0,0 +1,15 @@ +# +# $Id$ +# + +ROOT = ../../../ + +C_SOURCES=\ + dbffpt1.c \ + +PRG_SOURCES=\ + dbffpt0.prg \ + +LIBNAME=dbffpt + +include $(TOP)$(ROOT)config/lib.cf diff --git a/harbour/source/rdd/dbffpt/dbffpt0.prg b/harbour/source/rdd/dbffpt/dbffpt0.prg new file mode 100644 index 0000000000..578f2c4d18 --- /dev/null +++ b/harbour/source/rdd/dbffpt/dbffpt0.prg @@ -0,0 +1,64 @@ +/* + * $Id$ + */ + +/* + * Harbour Project source code: + * DBFFPT RDD + * + * Copyright 2003 Przemyslaw Czerpak + * www - http://www.xharbour.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/). + * + * As a special exception, the Harbour Project gives permission for + * additional uses of the text contained in its release of Harbour. + * + * The exception is that, if you link the Harbour libraries with other + * files to produce an executable, this does not by itself cause the + * resulting executable to be covered by the GNU General Public License. + * Your use of that executable is in no way restricted on account of + * linking the Harbour library code into it. + * + * This exception does not however invalidate any other reasons why + * the executable file might be covered by the GNU General Public License. + * + * This exception applies only to the code released by the Harbour + * Project under the name Harbour. If you copy code from other + * Harbour Project or Free Software Foundation releases into a copy of + * Harbour, as the General Public License permits, the exception does + * not apply to the code that you add in this way. To avoid misleading + * anyone as to the status of such modified files, you must delete + * this exception notice from them. + * + * If you write modifications of your own for Harbour, it is your choice + * whether to permit this exception to apply to your modifications. + * If you do not wish that, delete this exception notice. + * + */ + +#include "rddsys.ch" + +ANNOUNCE DBFFPT + +procedure DBFFPTInit + + REQUEST _DBFFPT + + rddRegister( "DBF", RDT_FULL ) + rddRegister( "DBFFPT", RDT_FULL ) + +return diff --git a/harbour/source/rdd/dbffpt/dbffpt1.c b/harbour/source/rdd/dbffpt/dbffpt1.c new file mode 100644 index 0000000000..7906d4fb11 --- /dev/null +++ b/harbour/source/rdd/dbffpt/dbffpt1.c @@ -0,0 +1,2122 @@ +/* + * $Id$ + */ + +/* + * xHarbour Project source code: + * DBFFPT RDD + * + * Copyright 2003 Przemyslaw Czerpak + * www - http://www.xharbour.org + * + * The SIX memo conversion algorithms and some piece of code taken from + * DBFCDX and DBFFPT + * Copyright 1999-2002 Bruno Cantero + * Copyright 2000-2003 Horacio Roldan (portions) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/). + * + * As a special exception, the Harbour Project gives permission for + * additional uses of the text contained in its release of Harbour. + * + * The exception is that, if you link the Harbour libraries with other + * files to produce an executable, this does not by itself cause the + * resulting executable to be covered by the GNU General Public License. + * Your use of that executable is in no way restricted on account of + * linking the Harbour library code into it. + * + * This exception does not however invalidate any other reasons why + * the executable file might be covered by the GNU General Public License. + * + * This exception applies only to the code released by the Harbour + * Project under the name Harbour. If you copy code from other + * Harbour Project or Free Software Foundation releases into a copy of + * Harbour, as the General Public License permits, the exception does + * not apply to the code that you add in this way. To avoid misleading + * anyone as to the status of such modified files, you must delete + * this exception notice from them. + * + * If you write modifications of your own for Harbour, it is your choice + * whether to permit this exception to apply to your modifications. + * If you do not wish that, delete this exception notice. + * + */ + +#include "hbapi.h" +#include "hbinit.h" +#include "hbapierr.h" +#include "hbapilng.h" +#include "hbset.h" +#include "hbdate.h" +#include "hbrddfpt.h" + +#ifndef HB_CDP_SUPPORT_OFF +# include "hbapicdp.h" + extern PHB_CODEPAGE s_cdpage; +#endif + +#define __PRG_SOURCE__ __FILE__ +#ifndef __XHARBOUR__ +# define HB_VM_STACK hb_stack +#endif +#ifdef HB_PCODE_VER +# undef HB_PRG_PCODE_VER +# define HB_PRG_PCODE_VER HB_PCODE_VER +#endif + +static RDDFUNCS fptSuper; +static RDDFUNCS fptTable = +{ + + /* Movement and positioning methods */ + + ( DBENTRYP_BP ) hb_fptBof, + ( DBENTRYP_BP ) hb_fptEof, + ( DBENTRYP_BP ) hb_fptFound, + ( DBENTRYP_V ) hb_fptGoBottom, + ( DBENTRYP_UL ) hb_fptGoTo, + ( DBENTRYP_I ) hb_fptGoToId, + ( DBENTRYP_V ) hb_fptGoTop, + ( DBENTRYP_BIB ) hb_fptSeek, + ( DBENTRYP_L ) hb_fptSkip, + ( DBENTRYP_L ) hb_fptSkipFilter, + ( DBENTRYP_L ) hb_fptSkipRaw, + + + /* Data management */ + + ( DBENTRYP_VF ) hb_fptAddField, + ( DBENTRYP_B ) hb_fptAppend, + ( DBENTRYP_I ) hb_fptCreateFields, + ( DBENTRYP_V ) hb_fptDeleteRec, + ( DBENTRYP_BP ) hb_fptDeleted, + ( DBENTRYP_SP ) hb_fptFieldCount, + ( DBENTRYP_VF ) hb_fptFieldDisplay, + ( DBENTRYP_SSI ) hb_fptFieldInfo, + ( DBENTRYP_SVP ) hb_fptFieldName, + ( DBENTRYP_V ) hb_fptFlush, + ( DBENTRYP_PP ) hb_fptGetRec, + ( DBENTRYP_SI ) hb_fptGetValue, + ( DBENTRYP_SVL ) hb_fptGetVarLen, + ( DBENTRYP_V ) hb_fptGoCold, + ( DBENTRYP_V ) hb_fptGoHot, + ( DBENTRYP_P ) hb_fptPutRec, + ( DBENTRYP_SI ) hb_fptPutValue, + ( DBENTRYP_V ) hb_fptRecall, + ( DBENTRYP_ULP ) hb_fptRecCount, + ( DBENTRYP_ISI ) hb_fptRecInfo, + ( DBENTRYP_I ) hb_fptRecNo, + ( DBENTRYP_S ) hb_fptSetFieldExtent, + + + /* WorkArea/Database management */ + + ( DBENTRYP_P ) hb_fptAlias, + ( DBENTRYP_V ) hb_fptClose, + ( DBENTRYP_VP ) hb_fptCreate, + ( DBENTRYP_SI ) hb_fptInfo, + ( DBENTRYP_V ) hb_fptNewArea, + ( DBENTRYP_VP ) hb_fptOpen, + ( DBENTRYP_V ) hb_fptRelease, + ( DBENTRYP_SP ) hb_fptStructSize, + ( DBENTRYP_P ) hb_fptSysName, + ( DBENTRYP_VEI ) hb_fptEval, + ( DBENTRYP_V ) hb_fptPack, + ( DBENTRYP_LSP ) hb_fptPackRec, + ( DBENTRYP_VS ) hb_fptSort, + ( DBENTRYP_VT ) hb_fptTrans, + ( DBENTRYP_VT ) hb_fptTransRec, + ( DBENTRYP_V ) hb_fptZap, + + + /* Relational Methods */ + + ( DBENTRYP_VR ) hb_fptChildEnd, + ( DBENTRYP_VR ) hb_fptChildStart, + ( DBENTRYP_VR ) hb_fptChildSync, + ( DBENTRYP_V ) hb_fptSyncChildren, + ( DBENTRYP_V ) hb_fptClearRel, + ( DBENTRYP_V ) hb_fptForceRel, + ( DBENTRYP_SVP ) hb_fptRelArea, + ( DBENTRYP_VR ) hb_fptRelEval, + ( DBENTRYP_SVP ) hb_fptRelText, + ( DBENTRYP_VR ) hb_fptSetRel, + + + /* Order Management */ + + ( DBENTRYP_OI ) hb_fptOrderListAdd, + ( DBENTRYP_V ) hb_fptOrderListClear, + ( DBENTRYP_VP ) hb_fptOrderListDelete, + ( DBENTRYP_OI ) hb_fptOrderListFocus, + ( DBENTRYP_V ) hb_fptOrderListRebuild, + ( DBENTRYP_VOI ) hb_fptOrderCondition, + ( DBENTRYP_VOC ) hb_fptOrderCreate, + ( DBENTRYP_OI ) hb_fptOrderDestroy, + ( DBENTRYP_OII ) hb_fptOrderInfo, + + + /* Filters and Scope Settings */ + + ( DBENTRYP_V ) hb_fptClearFilter, + ( DBENTRYP_V ) hb_fptClearLocate, + ( DBENTRYP_V ) hb_fptClearScope, + ( DBENTRYP_VPLP ) hb_fptCountScope, + ( DBENTRYP_I ) hb_fptFilterText, + ( DBENTRYP_SI ) hb_fptScopeInfo, + ( DBENTRYP_VFI ) hb_fptSetFilter, + ( DBENTRYP_VLO ) hb_fptSetLocate, + ( DBENTRYP_VOS ) hb_fptSetScope, + ( DBENTRYP_VPL ) hb_fptSkipScope, + + + /* Miscellaneous */ + + ( DBENTRYP_P ) hb_fptCompile, + ( DBENTRYP_I ) hb_fptError, + ( DBENTRYP_I ) hb_fptEvalBlock, + + + /* Network operations */ + + ( DBENTRYP_VSP ) hb_fptRawLock, + ( DBENTRYP_VL ) hb_fptLock, + ( DBENTRYP_UL ) hb_fptUnLock, + + + /* Memofile functions */ + + ( DBENTRYP_V ) hb_fptCloseMemFile, + ( DBENTRYP_VP ) hb_fptCreateMemFile, + ( DBENTRYP_SVPB ) hb_fptGetValueFile, + ( DBENTRYP_VP ) hb_fptOpenMemFile, + ( DBENTRYP_SVP ) hb_fptPutValueFile, + + + /* Database file header handling */ + + ( DBENTRYP_V ) hb_fptReadDBHeader, + ( DBENTRYP_V ) hb_fptWriteDBHeader, + + + /* non WorkArea functions */ + ( DBENTRYP_I0 ) hb_fptExit, + ( DBENTRYP_I1 ) hb_fptDrop, + ( DBENTRYP_I2 ) hb_fptExists, + + /* Special and reserved methods */ + + ( DBENTRYP_SVP ) hb_fptWhoCares +}; + + +HB_FUNC( _DBFFPT ) {;} + +HB_FUNC( DBFFPT_GETFUNCTABLE ) +{ + RDDFUNCS * pTable; + USHORT * uiCount; + + uiCount = ( USHORT * ) hb_itemGetPtr( hb_param( 1, HB_IT_POINTER ) ); + pTable = ( RDDFUNCS * ) hb_itemGetPtr( hb_param( 2, HB_IT_POINTER ) ); + + HB_TRACE(HB_TR_DEBUG, ("DBFFPT_GETFUNCTABLE(%i, %p)", uiCount, pTable)); + + if( pTable ) + { + if ( uiCount ) + * uiCount = RDDFUNCSCOUNT; + hb_retni( hb_rddInherit( pTable, &fptTable, &fptSuper, ( BYTE * ) "DBF" ) ); + } + else + hb_retni( FAILURE ); +} + + +HB_INIT_SYMBOLS_BEGIN( dbffpt1__InitSymbols ) +{ "_DBFFPT", HB_FS_PUBLIC, HB_FUNCNAME( _DBFFPT ), NULL }, +{ "DBFFPT_GETFUNCTABLE", HB_FS_PUBLIC, HB_FUNCNAME( DBFFPT_GETFUNCTABLE ), NULL } +HB_INIT_SYMBOLS_END( dbffpt1__InitSymbols ) + +#if defined(HB_STATIC_STARTUP) +# pragma startup dbffpt1__InitSymbols +#elif defined(_MSC_VER) +# if _MSC_VER >= 1010 +# pragma data_seg( ".CRT$XIY" ) +# pragma comment( linker, "/Merge:.CRT=.data" ) +# else +# pragma data_seg( "XIY" ) +# endif + static HB_$INITSYM hb_vm_auto_dbffpt1__InitSymbols = dbffpt1__InitSymbols; +# pragma data_seg() +#elif ! defined(__GNUC__) +# pragma startup dbffpt1__InitSymbols +#endif + + +/* + * Exclusive lock memo file. + */ +static BOOL hb_fptFileLockEx( FPTAREAP pArea ) +{ + BOOL bRet; + + while ( ! ( bRet = hb_fsLock( pArea->hMemoFile, FPT_LOCKPOS, FPT_LOCKSIZE, + FL_LOCK | FLX_EXCLUSIVE | FLX_WAIT ) ) ); + return bRet; +} + +/* + * Shared lock memo file. + */ +static BOOL hb_fptFileLockSh( FPTAREAP pArea ) +{ + BOOL bRet; + + while ( ! ( bRet = hb_fsLock( pArea->hMemoFile, FPT_LOCKPOS, FPT_LOCKSIZE, + FL_LOCK | FLX_SHARED | FLX_WAIT ) ) ); + return bRet; +} + +/* + * Unlock memo file. + */ +static BOOL hb_fptFileUnLock( FPTAREAP pArea ) +{ + return hb_fsLock( pArea->hMemoFile, FPT_LOCKPOS, FPT_LOCKSIZE, FL_UNLOCK ); +} + +/* + GARBAGE COLLECTOR: + I don't have any documentation about it. All I know is reverse engineering + or analyzes of other sources. If any one can tell me sth more about it then + I will be really glad. I use method one for SixMemo and method 2 for FLEX + memos. + + Method 1. + FPTHEADER->reserved2[492] is a list of free pages, + 6 bytes for each page + size[2] (size in blocks) (little endian) + block[4] (block number) (little endian) + signature1[12] has to be cutted down to + 10 bytes. The last 2 bytes becomes the + number of entries in freeblock list (max 82) + + Method 2. + FPTHEADER->flexDir[4] is a little endian offset to page + (1024 bytes size) where header is: + type[4] = 1000 (big endian) + size[4] = 1010 (big endian) + then + nItem[2] numeber of item (little endian) + then 1008 bytes with free blocks list + (max 126 entries) in format: + offset[4] (litle endian) + size[4] (litle endian) + nItem is allways odd and after read we have + to recalculate it: + nItem = ( nItem - 3 ) / 4 + if FPTHEADER->flexDir = 0 then we can create it by allocating + two 1024 bytes pages ofr flexRev and flexDir page. + FPTHEADER->flexRev[4] 1024 bytes in next free block + FPTHEADER->flexDir[4] next 1024 bytes + flexRev page is copy of flexDir page but the items are stored + in reversed form size[4] first then offset[4] + size[4] (litle endian) + offset[4] (litle endian) + before writting GC pages (dir and rev, both has to be synced) + we should first sort the entries moving the shortest blocks + to the begining so when we where looking for free block we + can scan the list from the begining finding the first one + large enough. unused bytes in GC pgae should be fill with 0xAD + when we free fpt block we should set in its header: + type[4] = 1001 (big endian) + size[4] = rest of block size (block size - 8) (big endian) + + TODO: Clipper 5.3 can use more then one GC page. I don't have any + documentation for that and don't have time for farther hacking + binary files to find the algorithm. If you have any documentation + about it, please send it to me. + */ + +/* + * Sort GC free memo block list by size. + */ +static void hb_fptSortGCitems( LPMEMOGCTABLE pGCtable ) +{ + ULONG ulOffset, ulSize; + BOOL fMoved = TRUE; + int i, j, l; + + /* this table should be allready quite good sorted so this simple + algorithms will be the most efficient one. + It will need only one or two passes */ + l = pGCtable->usItems - 1; + while ( fMoved ) + { + fMoved = FALSE; + j = l; + for( i = 0; i < j; i++ ) + { + if ( pGCtable->pGCitems[i].ulSize > pGCtable->pGCitems[i+1].ulSize ) + { + ulOffset = pGCtable->pGCitems[i+1].ulOffset; + ulSize = pGCtable->pGCitems[i+1].ulSize; + pGCtable->pGCitems[i+1].ulSize = pGCtable->pGCitems[i].ulSize; + pGCtable->pGCitems[i+1].ulOffset = pGCtable->pGCitems[i].ulOffset; + pGCtable->pGCitems[ i ].ulSize = ulSize; + pGCtable->pGCitems[ i ].ulOffset = ulOffset; + fMoved = TRUE; + pGCtable->bChanged |= 2; + l = i; + } + } + } +} + +/* + * Pack GC free memo block list - try to join free blocks. + */ +static void hb_fptPackGCitems( LPMEMOGCTABLE pGCtable ) +{ + ULONG ulEnd; + int i, j; + + /* TODO: better alogrithm this primitve one can be too slow for big + free block list table */ + for( i = 0; i < pGCtable->usItems; i++ ) + { + if ( pGCtable->pGCitems[i].ulOffset != 0 && + pGCtable->pGCitems[i].ulSize != 0 ) + { + ulEnd = pGCtable->pGCitems[i].ulOffset + pGCtable->pGCitems[i].ulSize; + if ( ulEnd == pGCtable->ulNextBlock ) + { + pGCtable->ulNextBlock -= pGCtable->pGCitems[i].ulSize; + pGCtable->pGCitems[i].ulOffset = pGCtable->pGCitems[i].ulSize = 0; + pGCtable->bChanged |= 2; + i = -1; + } + else + { + for( j = i + 1; j < pGCtable->usItems; j++ ) + { + if ( ulEnd == pGCtable->pGCitems[j].ulOffset ) + { + pGCtable->pGCitems[i].ulSize += pGCtable->pGCitems[j].ulSize; + pGCtable->pGCitems[j].ulOffset = pGCtable->pGCitems[j].ulSize = 0; + pGCtable->bChanged |= 2; + i = -1; + break; + } + } + } + } + } + + /* remove empty items */ + for( i = j = 0; i < pGCtable->usItems; i++ ) + { + if ( pGCtable->pGCitems[i].ulOffset != 0 && + pGCtable->pGCitems[i].ulSize != 0 ) + { + if ( i > j ) + { + pGCtable->pGCitems[j].ulOffset = pGCtable->pGCitems[i].ulOffset; + pGCtable->pGCitems[j].ulSize = pGCtable->pGCitems[i].ulSize; + } + j++; + } + } + pGCtable->usItems = j; +} + +/* + * Write proper header into modified GC free memo blocks. + */ +static ERRCODE hb_fptWriteGCitems( FPTAREAP pArea, LPMEMOGCTABLE pGCtable, USHORT usItem ) +{ + FPTBLOCK fptBlock; + ERRCODE errCode = SUCCESS; + int i, iStart, iStop; + + if ( usItem == 0 ) + { + iStart = 0; + iStop = pGCtable->usItems; + } + else + { + iStart = usItem; + iStop = usItem + 1; + } + for( i = 0; i < pGCtable->usItems; i++ ) + { + if ( pGCtable->pGCitems[i].fChanged ) + { + HB_PUT_BE_ULONG( &fptBlock.type, FPTIT_FLEX_UNUSED ); + HB_PUT_BE_ULONG( &fptBlock.size, pArea->uiMemoBlockSize * + pGCtable->pGCitems[i].ulSize - sizeof( FPTBLOCK ) ); + hb_fsSeek( pArea->hMemoFile, pGCtable->pGCitems[i].ulOffset * + pArea->uiMemoBlockSize, FS_SET ); + if ( hb_fsWrite( pArea->hMemoFile, ( BYTE * ) &fptBlock, + sizeof( FPTBLOCK ) ) != sizeof( FPTBLOCK ) ) + { + errCode = EDBF_WRITE; + } + pGCtable->pGCitems[i].fChanged = FALSE; + } + } + return errCode; +} + +/* + * Add new block to GC free memo blocks list. + */ +static ERRCODE hb_fptGCfreeBlock( FPTAREAP pArea, LPMEMOGCTABLE pGCtable, + ULONG ulOffset, ULONG ulByteSize ) +{ + ERRCODE errCode = SUCCESS; + ULONG ulSize; + + if ( ulByteSize == 0 ) + { + FPTBLOCK fptBlock; + + hb_fsSeek( pArea->hMemoFile, ulOffset * pArea->uiMemoBlockSize, FS_SET ); + if( hb_fsRead( pArea->hMemoFile, ( BYTE * ) &fptBlock, + sizeof( FPTBLOCK ) ) == sizeof( FPTBLOCK ) ) + { + ulByteSize = HB_GET_BE_ULONG( &fptBlock.size ) + sizeof( FPTBLOCK ); + } + } + else + { + ulByteSize += sizeof( FPTBLOCK ); + } + + ulSize = ( ulByteSize + pArea->uiMemoBlockSize - 1 ) / pArea->uiMemoBlockSize; + + if ( ulByteSize == 0 ) + { + return EDBF_CORRUPT; + } + + if ( ulOffset + ulSize == pGCtable->ulNextBlock ) + { + pGCtable->ulNextBlock -= ulSize; + pGCtable->bChanged |= 1; + hb_fptPackGCitems( pGCtable ); + } + else + { + BOOL fChanged = FALSE; + int i; + + for( i = 0; i < pGCtable->usItems; i++ ) + { + if ( pGCtable->pGCitems[i].ulOffset + pGCtable->pGCitems[i].ulSize == ulOffset ) + { + ulOffset = pGCtable->pGCitems[i].ulOffset; + ulSize = pGCtable->pGCitems[i].ulSize += ulSize; + fChanged = pGCtable->pGCitems[i].fChanged = TRUE; + break; + } + if ( pGCtable->pGCitems[i].ulOffset == ulOffset + ulSize ) + { + pGCtable->pGCitems[i].ulOffset = ulOffset; + ulSize = pGCtable->pGCitems[i].ulSize += ulSize; + fChanged = pGCtable->pGCitems[i].fChanged = TRUE; + break; + } + } + if ( !fChanged ) + { + if ( pGCtable->usItems < pGCtable->usMaxItem ) + { + if ( pGCtable->pGCitems == NULL ) + { + pGCtable->pGCitems = ( LPMEMOGCITEM ) hb_xgrab( sizeof( MEMOGCITEM ) * ( pGCtable->usMaxItem + 1 ) ); + } + pGCtable->pGCitems[ pGCtable->usItems ].ulOffset = ulOffset; + pGCtable->pGCitems[ pGCtable->usItems ].ulSize = ulSize; + pGCtable->pGCitems[ pGCtable->usItems ].fChanged = fChanged = TRUE; + pGCtable->usItems++; + } + else if ( pGCtable->pGCitems[ 1 ].ulSize < ulSize ) + { + if ( pGCtable->ulNextBlock == pGCtable->pGCitems[ 1 ].ulOffset + + pGCtable->pGCitems[ 1 ].ulSize ) + { + pGCtable->ulNextBlock -= pGCtable->pGCitems[ 1 ].ulSize; + } + else if ( pGCtable->pGCitems[ 1 ].fChanged ) + { + errCode = hb_fptWriteGCitems( pArea, pGCtable, 1 ); + } + pGCtable->pGCitems[ 1 ].ulOffset = ulOffset; + pGCtable->pGCitems[ 1 ].ulSize = ulSize; + pGCtable->pGCitems[ 1 ].fChanged = fChanged = TRUE; + } + } + + if ( fChanged ) + { + pGCtable->bChanged |= 2; + hb_fptPackGCitems( pGCtable ); + hb_fptSortGCitems( pGCtable ); + } + } + + return errCode; +} + +/* + * Get free memo block from GC free memo blocks list or allocate new one. + */ +static ERRCODE hb_fptGCgetFreeBlock( FPTAREAP pArea, LPMEMOGCTABLE pGCtable, + ULONG * ulOffset, ULONG ulByteSize ) +{ + BOOL fAlloc = FALSE; + ULONG ulSize; + int i; + + ulSize = ( ulByteSize + sizeof( FPTBLOCK ) + pArea->uiMemoBlockSize - 1 ) / + pArea->uiMemoBlockSize; + + for( i = 0; i < pGCtable->usItems; i++ ) + { + if ( pGCtable->pGCitems[i].ulSize >= ulSize ) + { + *ulOffset = pGCtable->pGCitems[i].ulOffset; + pGCtable->pGCitems[i].ulOffset += ulSize; + pGCtable->pGCitems[i].ulSize -= ulSize; + if ( pGCtable->pGCitems[i].ulSize == 0 ) + { + while ( ++i < pGCtable->usItems ) + { + pGCtable->pGCitems[i-1].ulOffset = pGCtable->pGCitems[i].ulOffset; + pGCtable->pGCitems[i-1].ulSize = pGCtable->pGCitems[i].ulSize; + } + pGCtable->usItems--; + } + else + { + pGCtable->pGCitems[i].fChanged = TRUE; + hb_fptSortGCitems( pGCtable ); + } + pGCtable->bChanged |= 2; + fAlloc = TRUE; + break; + } + } + if ( !fAlloc ) + { + *ulOffset = pGCtable->ulNextBlock; + pGCtable->ulNextBlock += ulSize; + pGCtable->bChanged |= 1; + } + return SUCCESS; +} + +/* + * Init GC table free memo blok list. + */ +static void hb_fptInitGCdata( LPMEMOGCTABLE pGCtable ) +{ + memset( pGCtable, 0, sizeof(MEMOGCTABLE) ); +} + +/* + * Clean GC table free memo blok list. + */ +static void hb_fptDestroyGCdata( LPMEMOGCTABLE pGCtable ) +{ + if ( pGCtable->pGCitems != NULL ) + { + hb_xfree( pGCtable->pGCitems ); + pGCtable->pGCitems = NULL; + pGCtable->usItems = 0; + } + pGCtable->bChanged = 0; +} + +/* + * Read GC table from memo file. + */ +static ERRCODE hb_fptReadGCdata( FPTAREAP pArea, LPMEMOGCTABLE pGCtable ) +{ + int i; + + hb_fptDestroyGCdata( pGCtable ); + memset( &pGCtable->fptHeader, 0, sizeof( FPTHEADER ) ); + + hb_fsSeek( pArea->hMemoFile, 0, FS_SET ); + if ( hb_fsRead( pArea->hMemoFile, ( BYTE * ) &pGCtable->fptHeader, sizeof( FPTHEADER ) ) >= 512 ) + { + pGCtable->ulNextBlock = HB_GET_BE_ULONG( &pGCtable->fptHeader.nextBlock ); + + if ( pArea->bMemoType == MEMO_FPT_SIX || + pArea->bMemoType == MEMO_FPT_SIXHB ) + { + pGCtable->bType = MEMO_FPT_SIX; + pGCtable->usMaxItem = MAX_SIXFREEBLOCKS; + pGCtable->usItems = HB_GET_LE_USHORT( &pGCtable->fptHeader.nGCitems ); + if ( pGCtable->usItems > pGCtable->usMaxItem ) + { + return EDBF_CORRUPT; + } + + pGCtable->pGCitems = ( LPMEMOGCITEM ) hb_xgrab( sizeof( MEMOGCITEM ) * ( pGCtable->usMaxItem + 1 ) ); + + for( i = 0; i < pGCtable->usItems; i++ ) + { + pGCtable->pGCitems[i].ulSize = HB_GET_LE_USHORT( &pGCtable->fptHeader.reserved2[ i * 6 ] ); + pGCtable->pGCitems[i].ulOffset = HB_GET_LE_ULONG( &pGCtable->fptHeader.reserved2[ i * 6 + 2 ] ); + pGCtable->pGCitems[i].fChanged = FALSE; + } + } + else if ( pArea->bMemoType == MEMO_FPT_FLEX || + pArea->bMemoType == MEMO_FPT_HB || + pArea->bMemoType == MEMO_FPT_CLIP ) + { + FPTBLOCK fptBlock; + BYTE *bPageBuf; + + pGCtable->bType = MEMO_FPT_FLEX; + pGCtable->usMaxItem = MAX_FLEXFREEBLOCKS; + pGCtable->ulRevPage = HB_GET_LE_ULONG( &pGCtable->fptHeader.flexRev ); + pGCtable->ulDirPage = HB_GET_LE_ULONG( &pGCtable->fptHeader.flexDir ); + pGCtable->ulCounter = HB_GET_LE_ULONG( &pGCtable->fptHeader.counter ); + if ( pGCtable->ulDirPage ) + { + hb_fsSeek( pArea->hMemoFile, pGCtable->ulDirPage, FS_SET ); + if ( hb_fsRead( pArea->hMemoFile, ( BYTE * ) &fptBlock, + sizeof( FPTBLOCK ) ) != sizeof( FPTBLOCK ) || + HB_GET_BE_ULONG( &fptBlock.type ) != FPTIT_FLEX_GC ) + { + return EDBF_CORRUPT; + } + pGCtable->ulSize = HB_GET_BE_ULONG( &fptBlock.size ); + bPageBuf = ( BYTE * ) hb_xgrab( pGCtable->ulSize ); + if ( hb_fsRead( pArea->hMemoFile, bPageBuf, ( USHORT ) pGCtable->ulSize ) != + pGCtable->ulSize ) + { + hb_xfree( bPageBuf ); + return EDBF_CORRUPT; + } + pGCtable->usMaxItem = (USHORT ) ( ( pGCtable->ulSize - 2 ) >> 3 ); + pGCtable->usItems = ( HB_GET_LE_USHORT( bPageBuf ) - 3 ) >> 2; + + pGCtable->pGCitems = ( LPMEMOGCITEM ) hb_xgrab( sizeof( MEMOGCITEM ) * + ( HB_MIN( pGCtable->usItems, pGCtable->usMaxItem ) + 1 ) ); + + for( i = 0; i < pGCtable->usItems; i++ ) + { + pGCtable->pGCitems[i].ulOffset = HB_GET_LE_ULONG( &bPageBuf[ i * 8 + 2 ] ) / + pArea->uiMemoBlockSize; + pGCtable->pGCitems[i].ulSize = HB_GET_LE_ULONG( &bPageBuf[ i * 8 + 6 ] ) / + pArea->uiMemoBlockSize; + pGCtable->pGCitems[i].fChanged = FALSE; + } + hb_xfree( bPageBuf ); + } + } + + if ( pGCtable->pGCitems ) + { + hb_fptSortGCitems( pGCtable ); + } + + return SUCCESS; + } + return EDBF_READ; +} + +/* + * Write GC table into memo file. + */ +static ERRCODE hb_fptWriteGCdata( FPTAREAP pArea, LPMEMOGCTABLE pGCtable ) +{ + ERRCODE errCode = SUCCESS; + ULONG ulHdrSize = 512; + int i, j; + + if ( pGCtable->bChanged > 0 ) + { + if ( pGCtable->bType == MEMO_FPT_SIX ) + { + HB_PUT_LE_USHORT( &pGCtable->fptHeader.nGCitems, pGCtable->usItems ); + memset( pGCtable->fptHeader.reserved2, 0, sizeof( pGCtable->fptHeader.reserved2 ) ); + j = ( pGCtable->usItems > pGCtable->usMaxItem ) ? + pGCtable->usItems - pGCtable->usMaxItem : 0; + for( i = j ; i < pGCtable->usItems; i++ ) + { + HB_PUT_LE_USHORT( &pGCtable->fptHeader.reserved2[ ( i - j ) * 6 ], + (( USHORT ) pGCtable->pGCitems[i].ulSize ) ); + HB_PUT_LE_ULONG( &pGCtable->fptHeader.reserved2[ ( i - j ) * 6 + 2 ], + pGCtable->pGCitems[i].ulOffset ); + } + } + else if ( pGCtable->bType == MEMO_FPT_FLEX ) + { + ulHdrSize = sizeof( FPTHEADER ); + pGCtable->ulCounter++; + if ( pGCtable->usItems == 0 && pGCtable->ulDirPage ) + { + ULONG ulOffset = pGCtable->ulDirPage; + ULONG ulSize = ( pGCtable->ulSize + pArea->uiMemoBlockSize - 1 ) / + pArea->uiMemoBlockSize; + if ( pGCtable->ulRevPage ) + { + ulSize <<= 1; + if ( pGCtable->ulDirPage > pGCtable->ulRevPage ) + { + ulOffset = pGCtable->ulRevPage; + } + } + ulOffset /= pArea->uiMemoBlockSize; + if ( ulOffset + ulSize == pGCtable->ulNextBlock ) + { + pGCtable->ulDirPage = pGCtable->ulRevPage = 0; + pGCtable->ulNextBlock -= ulSize; + } + } + else if ( pGCtable->usItems > 0 && ! pGCtable->ulDirPage ) + { + pGCtable->ulSize = FLEXGCPAGE_SIZE; + errCode = hb_fptGCgetFreeBlock( pArea, pGCtable, + &pGCtable->ulDirPage, pGCtable->ulSize ); + if ( errCode == SUCCESS ) + { + pGCtable->ulDirPage *= pArea->uiMemoBlockSize; + errCode = hb_fptGCgetFreeBlock( pArea, pGCtable, + &pGCtable->ulRevPage, pGCtable->ulSize ); + pGCtable->ulRevPage *= pArea->uiMemoBlockSize; + } + pGCtable->bChanged |= 2; + } + if ( pGCtable->ulDirPage && pGCtable->bChanged > 1 ) + { + FPTBLOCK fptBlock; + BYTE *bPageBuf; + + HB_PUT_BE_ULONG( &fptBlock.type, FPTIT_FLEX_GC ); + HB_PUT_BE_ULONG( &fptBlock.size, pGCtable->ulSize ); + bPageBuf = ( BYTE * ) hb_xgrab( pGCtable->ulSize ); + memset( bPageBuf, 0xAD, pGCtable->ulSize ); + HB_PUT_LE_USHORT( bPageBuf, ( (USHORT) pGCtable->usItems << 2 ) + 3 ); + j = ( pGCtable->usItems > pGCtable->usMaxItem ) ? + pGCtable->usItems - pGCtable->usMaxItem : 0; + for( i = j ; i < pGCtable->usItems; i++ ) + { + HB_PUT_LE_ULONG( &bPageBuf[ ( i - j ) * 8 + 2 ], + pGCtable->pGCitems[i].ulOffset * pArea->uiMemoBlockSize ); + HB_PUT_LE_ULONG( &bPageBuf[ ( i - j ) * 8 + 6 ], + pGCtable->pGCitems[i].ulSize * pArea->uiMemoBlockSize ); + } + hb_fsSeek( pArea->hMemoFile, pGCtable->ulDirPage, FS_SET ); + if ( hb_fsWrite( pArea->hMemoFile, ( BYTE * ) &fptBlock, + sizeof( FPTBLOCK ) ) != sizeof( FPTBLOCK ) || + hb_fsWrite( pArea->hMemoFile, bPageBuf, + ( USHORT ) pGCtable->ulSize ) != pGCtable->ulSize ) + { + errCode = EDBF_WRITE; + } + else if ( pGCtable->ulRevPage ) + { + for( i = j; i < pGCtable->usItems; i++ ) + { + HB_PUT_LE_ULONG( &bPageBuf[ ( i - j ) * 8 + 2 ], + ( ( USHORT ) pGCtable->pGCitems[i].ulSize * pArea->uiMemoBlockSize ) ); + HB_PUT_LE_ULONG( &bPageBuf[ ( i - j ) * 8 + 6 ], + pGCtable->pGCitems[i].ulOffset * pArea->uiMemoBlockSize ); + } + hb_fsSeek( pArea->hMemoFile, pGCtable->ulRevPage, FS_SET ); + if ( hb_fsWrite( pArea->hMemoFile, ( BYTE * ) &fptBlock, + sizeof( FPTBLOCK ) ) != sizeof( FPTBLOCK ) || + hb_fsWrite( pArea->hMemoFile, bPageBuf, + ( USHORT )pGCtable->ulSize ) != pGCtable->ulSize ) + { + errCode = EDBF_WRITE; + } + } + hb_xfree( bPageBuf ); + } + HB_PUT_LE_ULONG( &pGCtable->fptHeader.flexRev, pGCtable->ulRevPage ); + HB_PUT_LE_ULONG( &pGCtable->fptHeader.flexDir, pGCtable->ulDirPage ); + HB_PUT_LE_ULONG( &pGCtable->fptHeader.counter, pGCtable->ulCounter ); + } + + if ( pGCtable->bChanged > 1 && errCode == SUCCESS ) + { + errCode = hb_fptWriteGCitems( pArea, pGCtable, 0 ); + } + if ( errCode == SUCCESS ) + { + HB_PUT_BE_ULONG( &pGCtable->fptHeader.nextBlock, pGCtable->ulNextBlock ); + hb_fsSeek( pArea->hMemoFile, 0, FS_SET ); + if ( hb_fsWrite( pArea->hMemoFile, ( BYTE * ) &pGCtable->fptHeader, ( USHORT )ulHdrSize ) != ulHdrSize ) + { + errCode = EDBF_WRITE; + } + else + { + /* trunc file */ + hb_fsSeek( pArea->hMemoFile, pGCtable->ulNextBlock * pArea->uiMemoBlockSize, FS_SET ); + hb_fsWrite( pArea->hMemoFile, NULL, 0 ); + } + } + pGCtable->bChanged = 0; + } + return errCode; +} + +/* + * Return the size of memo. + */ +static ULONG hb_fptGetMemoLen( FPTAREAP pArea, USHORT uiIndex ) +{ + ULONG ulBlock; + FPTBLOCK fptBlock; + + HB_TRACE(HB_TR_DEBUG, ("hb_fptGetMemoLen(%p, %hu)", pArea, uiIndex)); + + ulBlock = hb_dbfGetMemoBlock( (DBFAREAP) pArea, uiIndex ); + + if( ulBlock == 0 ) + return 0; + + hb_fsSeek( pArea->hMemoFile, ulBlock * pArea->uiMemoBlockSize, FS_SET ); + + if( hb_fsRead( pArea->hMemoFile, ( BYTE * ) &fptBlock, + sizeof( FPTBLOCK ) ) != sizeof( FPTBLOCK ) ) + return 0; + + return HB_GET_BE_ULONG( &fptBlock.size ); +} + +/* + * Read SIX item from memo. + */ +static ERRCODE hb_fptReadSixItem( FPTAREAP pArea, BYTE ** pbMemoBuf, BYTE * bBufEnd, PHB_ITEM pItem ) +{ + USHORT usType; + ULONG ulLen, i; + PHB_ITEM pNewItem; + ERRCODE errCode = SUCCESS; + + ulLen = SIX_ITEM_BUFSIZE; + if ( bBufEnd - (*pbMemoBuf) >= ( LONG ) ulLen ) + { + usType = HB_GET_LE_USHORT( &(*pbMemoBuf)[0] ); + switch ( usType ) + { + case FPTIT_SIX_LNUM: + hb_itemPutNL( pItem, ( LONG ) HB_GET_LE_ULONG( &(*pbMemoBuf)[6] ) ); + break; + + case FPTIT_SIX_DNUM: + hb_itemPutNDLen( pItem, HB_GET_LE_DOUBLE( &(*pbMemoBuf)[6] ), + HB_GET_LE_USHORT( &(*pbMemoBuf)[2] ), + HB_GET_LE_USHORT( &(*pbMemoBuf)[4] ) ); + break; + + case FPTIT_SIX_LDATE: + hb_itemPutDL( pItem, ( LONG ) HB_GET_LE_ULONG( &(*pbMemoBuf)[6] ) ); + break; + + case FPTIT_SIX_LOG: + hb_itemPutL( pItem, (&(*pbMemoBuf)[6]) != 0 ); + break; + + case FPTIT_SIX_CHAR: + ulLen = HB_GET_LE_ULONG( &(*pbMemoBuf)[2] ); + if ( pArea->bMemoType == MEMO_FPT_SIX ) + { + ulLen &= 0xFFFF; /* only 2 bytes (SHORT) for SIX compatibility */ + } + (*pbMemoBuf) += SIX_ITEM_BUFSIZE; + if ( bBufEnd - (*pbMemoBuf) >= ( LONG ) ulLen ) + { + hb_itemPutCL( pItem, ( char *) (*pbMemoBuf), ulLen ); +#ifndef HB_CDP_SUPPORT_OFF + hb_cdpnTranslate( pItem->item.asString.value, pArea->cdPage, s_cdpage, ulLen ); +#endif + } + else + { + errCode = EDBF_CORRUPT; + } + break; + +// case FPTIT_SIX_BLOCK: +// case FPTIT_SIX_VREF: +// case FPTIT_SIX_MREF: + + case FPTIT_SIX_ARRAY: + ulLen = HB_GET_LE_ULONG( &(*pbMemoBuf)[2] ); + if ( pArea->bMemoType == MEMO_FPT_SIX ) + { + ulLen &= 0xFFFF; /* only 2 bytes (SHORT) for SIX compatibility */ + } + (*pbMemoBuf) += SIX_ITEM_BUFSIZE; + hb_arrayNew( pItem, ulLen ); + pNewItem = hb_itemNew( NULL ); + for ( i = 1 ; i <= ulLen ; i++ ) + { + errCode = hb_fptReadSixItem( pArea, pbMemoBuf, bBufEnd, pNewItem ); + if ( errCode != SUCCESS ) + { + break; + } + hb_itemArrayPut( pItem, i, pNewItem ); + hb_itemClear( pNewItem ); + } + hb_itemRelease( pNewItem ); + ulLen = 0; + break; + default: + hb_itemClear( pItem ); + break; + } + *pbMemoBuf += ulLen; + } + else + { + errCode = EDBF_CORRUPT; + } + + return errCode; +} + +/* + * Read FLEX item from memo. + */ +static ERRCODE hb_fptReadFlexItem( FPTAREAP pArea, BYTE ** pbMemoBuf, BYTE * bBufEnd, PHB_ITEM pItem, BOOL bRoot ) +{ + BYTE usType; + ULONG ulLen, i; + PHB_ITEM pNewItem; + ERRCODE errCode = SUCCESS; + + if ( bRoot ) + { + usType = FPTIT_FLEXAR_ARAY; + } + else if ( bBufEnd - (*pbMemoBuf) > 0 ) + { + usType = *(*pbMemoBuf)++; + } + else + { + return EDBF_CORRUPT; + } + switch ( usType ) + { + case FPTIT_FLEXAR_NIL: + hb_itemClear( pItem ); + break; + case FPTIT_FLEXAR_TRUE: + hb_itemPutL( pItem, TRUE ); + break; + case FPTIT_FLEXAR_FALSE: + hb_itemPutL( pItem, FALSE ); + break; + case FPTIT_FLEXAR_DATE: + if ( bBufEnd - (*pbMemoBuf) >= 4 ) + { + hb_itemPutDL( pItem, (LONG) HB_GET_LE_ULONG( *pbMemoBuf ) ); + *pbMemoBuf += 4; + } + else + { + errCode = EDBF_CORRUPT; + } + break; + case FPTIT_FLEXAR_BYTE: + if ( bBufEnd - (*pbMemoBuf) >= 2 ) + { + hb_itemPutNI( pItem, **pbMemoBuf ); + *pbMemoBuf += 2; + } + else + { + errCode = EDBF_CORRUPT; + } + break; + case FPTIT_FLEXAR_SHORT: + if ( bBufEnd - (*pbMemoBuf) >= 3 ) + { + hb_itemPutNI( pItem, (SHORT) HB_GET_LE_USHORT( *pbMemoBuf ) ); + *pbMemoBuf += 3; + } + else + { + errCode = EDBF_CORRUPT; + } + break; + case FPTIT_FLEXAR_LONG: + if ( bBufEnd - (*pbMemoBuf) >= 6 ) + { + hb_itemPutNL( pItem, (LONG) HB_GET_LE_ULONG( *pbMemoBuf ) ); + *pbMemoBuf += 6; + } + else + { + errCode = EDBF_CORRUPT; + } + break; + case FPTIT_FLEXAR_DBL: + if ( bBufEnd - (*pbMemoBuf) >= 10 ) + { + hb_itemPutNDLen( pItem, HB_GET_LE_DOUBLE( *pbMemoBuf + 2 ), + **pbMemoBuf, (*pbMemoBuf)[1] ); + *pbMemoBuf += 10; + } + else + { + errCode = EDBF_CORRUPT; + } + break; + case FPTIT_FLEXAR_STR: + if ( bBufEnd - (*pbMemoBuf) >= 2 ) + { + ulLen = HB_GET_LE_USHORT( *pbMemoBuf ); + *pbMemoBuf += 2; + if ( bBufEnd - (*pbMemoBuf) >= ( LONG ) ulLen ) + { + hb_itemPutCL( pItem, ( char *) *pbMemoBuf, ulLen ); + *pbMemoBuf += ulLen; +#ifndef HB_CDP_SUPPORT_OFF + hb_cdpnTranslate( pItem->item.asString.value, pArea->cdPage, s_cdpage, ulLen ); +#endif + } + else + { + errCode = EDBF_CORRUPT; + } + } + else + { + errCode = EDBF_CORRUPT; + } + break; + + case FPTIT_FLEXAR_ARAY: + if ( bBufEnd - (*pbMemoBuf) >= 2 ) + { + ulLen = HB_GET_LE_USHORT( *pbMemoBuf ); + *pbMemoBuf += 2; + if ( bBufEnd - (*pbMemoBuf) >= ( LONG ) ulLen ) + { + hb_arrayNew( pItem, ulLen ); + pNewItem = hb_itemNew( NULL ); + for ( i = 1 ; i <= ulLen ; i++ ) + { + errCode = hb_fptReadFlexItem( pArea, pbMemoBuf, bBufEnd, pNewItem, FALSE ); + if ( errCode != SUCCESS ) + { + break; + } + hb_itemArrayPut( pItem, i, pNewItem ); + hb_itemClear( pNewItem ); + } + hb_itemRelease( pNewItem ); + } + else + { + errCode = EDBF_CORRUPT; + } + } + else + { + errCode = EDBF_CORRUPT; + } + break; + default: + hb_itemClear( pItem ); + break; + } + return errCode; +} + +/* + * Read fpt vartype memos. + */ +static ERRCODE hb_fptGetMemo( FPTAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) +{ + ERRCODE errCode = SUCCESS; + ULONG ulBlock, ulSize, ulType; + BYTE * pBuffer, * bMemoBuf; + FPTBLOCK fptBlock; + + HB_TRACE(HB_TR_DEBUG, ("hb_fptGetMemo(%p, %hu, %p)", pArea, uiIndex, pItem)); + + ulBlock = hb_dbfGetMemoBlock( (DBFAREAP) pArea, uiIndex ); + + if( ulBlock > 0 ) + { + hb_fsSeek( pArea->hMemoFile, ulBlock * pArea->uiMemoBlockSize, FS_SET ); + + if( hb_fsRead( pArea->hMemoFile, ( BYTE * ) &fptBlock, + sizeof( FPTBLOCK ) ) != sizeof( FPTBLOCK ) ) + { + ulSize = 0; + } + else + { + ulSize = HB_GET_BE_ULONG( &fptBlock.size ); + } + + ulType = HB_GET_BE_ULONG( &fptBlock.type ); + pBuffer = ( BYTE * ) hb_xgrab( HB_MAX( ulSize + 1, 8 ) ); + memset( pBuffer, '\0', 8); + if ( hb_fsReadLarge( pArea->hMemoFile, pBuffer, ulSize ) != ulSize ) + { + errCode = EDBF_READ; + } + else + { + switch ( ulType ) + { + case FPTIT_SIX_LNUM: + case FPTIT_SIX_DNUM: + case FPTIT_SIX_LDATE: + case FPTIT_SIX_LOG: + case FPTIT_SIX_CHAR: + case FPTIT_SIX_ARRAY: +// case FPTIT_SIX_BLOCK: +// case FPTIT_SIX_VREF: +// case FPTIT_SIX_MREF: + bMemoBuf = pBuffer; + errCode = hb_fptReadSixItem( pArea, &bMemoBuf, bMemoBuf + ulSize, pItem ); + break; + case FPTIT_FLEX_ARRAY: + bMemoBuf = pBuffer; + errCode = hb_fptReadFlexItem( pArea, &bMemoBuf, bMemoBuf + ulSize, pItem, TRUE ); + break; + case FPTIT_FLEX_NIL: + hb_itemClear( pItem ); + break; + case FPTIT_FLEX_TRUE: + hb_itemPutL( pItem, TRUE ); + break; + case FPTIT_FLEX_FALSE: + hb_itemPutL( pItem, FALSE ); + break; + case FPTIT_FLEX_LDATE: + hb_itemPutDL( pItem, (LONG) HB_GET_LE_ULONG( pBuffer ) ); + break; + case FPTIT_FLEX_BYTE: + hb_itemPutNI( pItem, pBuffer[0] ); + break; + case FPTIT_FLEX_SHORT: + hb_itemPutNI( pItem, (SHORT) HB_GET_LE_USHORT( pBuffer ) ); + break; + case FPTIT_FLEX_LONG: + hb_itemPutNL( pItem, (LONG) HB_GET_LE_ULONG( pBuffer ) ); + break; + case FPTIT_FLEX_DOUBLE: + hb_itemPutND( pItem, HB_GET_LE_DOUBLE( pBuffer ) ); + break; + case FPTIT_TEXT: +#ifndef HB_CDP_SUPPORT_OFF + hb_cdpnTranslate( ( char *) pBuffer, pArea->cdPage, s_cdpage, ulSize ); +#endif + case FPTIT_PICT: + pBuffer[ ulSize ] = '\0'; + hb_itemPutCPtr( pItem, ( char * ) pBuffer, ulSize ); + hb_itemSetCMemo( pItem ); + pBuffer = NULL; + break; + default: + hb_itemClear( pItem ); + break; + } + if ( pBuffer ) + hb_xfree(pBuffer); + } + } + else + { + hb_itemPutC( pItem, "" ); + hb_itemSetCMemo( pItem ); + } + return errCode; +} + +/* + * Calculate the size of SIX memo item + */ +static ULONG hb_fptCountSixItemLength( FPTAREAP pArea, PHB_ITEM pItem ) +{ + ULONG ulLen, i, ulSize = 0; + USHORT usType; + + usType = hb_itemType( pItem ); + switch ( usType ) + { + case HB_IT_ARRAY: // HB_IT_OBJECT = HB_IT_ARRAY + ulSize = SIX_ITEM_BUFSIZE; + ulLen = hb_arrayLen( pItem ); + if ( pArea->bMemoType == MEMO_FPT_SIX ) + { + ulLen &= 0xFFFF; /* only 2 bytes (SHORT) for SIX compatibility */ + } + for ( i = 1 ; i <= ulLen ; i++ ) + { + ulSize += hb_fptCountSixItemLength( pArea, hb_arrayGetItemPtr( pItem, i ) ); + } + break; + case HB_IT_MEMO: + case HB_IT_STRING: + ulSize = SIX_ITEM_BUFSIZE; + ulLen = pItem->item.asString.length; + if ( pArea->bMemoType == MEMO_FPT_SIX ) + { + ulLen &= 0xFFFF; /* only 2 bytes (SHORT) for SIX compatibility */ + } + ulSize += ulLen; + break; + case HB_IT_INTEGER: + case HB_IT_LONG: + case HB_IT_DOUBLE: + case HB_IT_DATE: + case HB_IT_LOGICAL: + default: + ulSize = SIX_ITEM_BUFSIZE; + } + return ulSize; +} + +/* + * Write fpt vartype as SIX memos. + */ +static ULONG hb_fptStoreSixItem( FPTAREAP pArea, PHB_ITEM pItem, BYTE ** bBufPtr ) +{ + USHORT usType; + ULONG ulLen, i, ulSize; + PHB_ITEM pTmpItem; + + memset( *bBufPtr, '\0', SIX_ITEM_BUFSIZE ); + usType = hb_itemType( pItem ); + ulSize = SIX_ITEM_BUFSIZE; + switch ( usType ) + { + case HB_IT_ARRAY: // HB_IT_OBJECT = HB_IT_ARRAY + HB_PUT_LE_USHORT( &(*bBufPtr)[0], FPTIT_SIX_ARRAY ); + ulLen = hb_arrayLen( pItem ); + if ( pArea->bMemoType == MEMO_FPT_SIX ) + { + ulLen &= 0xFFFF; /* only 2 bytes (SHORT) for SIX compatibility */ + } + HB_PUT_LE_ULONG( &(*bBufPtr)[2], ulLen ); + *bBufPtr += SIX_ITEM_BUFSIZE; + for ( i = 1 ; i <= ulLen ; i++ ) + { + pTmpItem = hb_arrayGetItemPtr( pItem, i ); + ulSize += hb_fptStoreSixItem( pArea, pTmpItem, bBufPtr ); + } + break; + + case HB_IT_INTEGER: + HB_PUT_LE_USHORT( &(*bBufPtr)[0], FPTIT_SIX_LNUM ); + HB_PUT_LE_USHORT( &(*bBufPtr)[2], pItem->item.asInteger.length ); + HB_PUT_LE_ULONG( &(*bBufPtr)[6], pItem->item.asInteger.value ); + *bBufPtr += SIX_ITEM_BUFSIZE; + break; + + case HB_IT_LONG: + HB_PUT_LE_USHORT( &(*bBufPtr)[0], FPTIT_SIX_LNUM ); + HB_PUT_LE_USHORT( &(*bBufPtr)[2], pItem->item.asLong.length ); + HB_PUT_LE_ULONG( &(*bBufPtr)[6], pItem->item.asLong.value ); + *bBufPtr += SIX_ITEM_BUFSIZE; + break; + + case HB_IT_DOUBLE: + HB_PUT_LE_USHORT( &(*bBufPtr)[0], FPTIT_SIX_DNUM ); + HB_PUT_LE_USHORT( &(*bBufPtr)[2], pItem->item.asDouble.length ); + HB_PUT_LE_USHORT( &(*bBufPtr)[4], pItem->item.asDouble.decimal ); + HB_PUT_LE_DOUBLE( &(*bBufPtr)[6], pItem->item.asDouble.value ); + *bBufPtr += SIX_ITEM_BUFSIZE; + break; + + case HB_IT_DATE: + HB_PUT_LE_USHORT( &(*bBufPtr)[0], FPTIT_SIX_LDATE ); + HB_PUT_LE_ULONG( &(*bBufPtr)[6], pItem->item.asDate.value ); + *bBufPtr += SIX_ITEM_BUFSIZE; + break; + + case HB_IT_LOGICAL: + HB_PUT_LE_USHORT( &(*bBufPtr)[0], FPTIT_SIX_LOG ); + *(BOOL*) ( &(*bBufPtr)[6] ) = pItem->item.asLogical.value; + *bBufPtr += SIX_ITEM_BUFSIZE; + break; + + case HB_IT_STRING: + case HB_IT_MEMO: + HB_PUT_LE_USHORT( &(*bBufPtr)[0], FPTIT_SIX_CHAR ); + ulLen = pItem->item.asString.length; + if ( pArea->bMemoType == MEMO_FPT_SIX ) + { + ulLen &= 0xFFFF; /* only 2 bytes (SHORT) for SIX compatibility */ + } + HB_PUT_LE_ULONG( &(*bBufPtr)[2], ulLen ); + *bBufPtr += SIX_ITEM_BUFSIZE; + if ( ulLen > 0 ) + { + memcpy( *bBufPtr, pItem->item.asString.value, ulLen ); +#ifndef HB_CDP_SUPPORT_OFF + hb_cdpnTranslate( ( char *) *bBufPtr, pArea->cdPage, s_cdpage, ulLen ); +#endif + *bBufPtr += ulLen; + } + break; + default: + *bBufPtr += SIX_ITEM_BUFSIZE; + break; + } + return ulSize; +} + +/* + * Calculate the size of FLEX memo item + */ +static ULONG hb_fptCountFlexItemLength( FPTAREAP pArea, PHB_ITEM pItem ) +{ + ULONG ulLen, i, ulSize = 1; + USHORT usType; + + usType = hb_itemType( pItem ); + switch ( usType ) + { + case HB_IT_ARRAY: + ulSize += 2; + ulLen = hb_arrayLen( pItem ) & 0xFFFF; + for ( i = 1 ; i <= ulLen ; i++ ) + { + ulSize += hb_fptCountFlexItemLength( pArea, hb_arrayGetItemPtr( pItem, i ) ); + } + break; + case HB_IT_MEMO: + case HB_IT_STRING: + ulLen = pItem->item.asString.length & 0xFFFF; + ulSize += ulLen + 2; + break; + case HB_IT_DATE: + ulSize += 4; + break; + case HB_IT_INTEGER: + ulSize += 3; + break; + case HB_IT_LONG: + ulSize += 6; + break; + case HB_IT_DOUBLE: + ulSize += 10; + break; + } + return ulSize; +} + +/* + * Store in buffer fpt vartype as FLEX memos. + */ +static void hb_fptStoreFlexItem( FPTAREAP pArea, PHB_ITEM pItem, BYTE ** bBufPtr ) +{ + ULONG ulLen, i; + USHORT usType; + + usType = hb_itemType( pItem ); + switch ( usType ) + { + case HB_IT_ARRAY: + ulLen = hb_arrayLen( pItem ) & 0xFFFF; + *(*bBufPtr)++ = FPTIT_FLEXAR_ARAY; + HB_PUT_LE_USHORT( *bBufPtr, ( USHORT ) ulLen ); + *bBufPtr += 2; + for ( i = 1 ; i <= ulLen ; i++ ) + { + hb_fptStoreFlexItem( pArea, hb_arrayGetItemPtr( pItem, i ), bBufPtr ); + } + break; + case HB_IT_MEMO: + case HB_IT_STRING: + *(*bBufPtr)++ = FPTIT_FLEXAR_STR; + ulLen = pItem->item.asString.length & 0xFFFF; + HB_PUT_LE_USHORT( *bBufPtr, ( USHORT ) ulLen ); + *bBufPtr += 2; + memcpy( *bBufPtr, pItem->item.asString.value, ulLen ); +#ifndef HB_CDP_SUPPORT_OFF + hb_cdpnTranslate( ( char *) *bBufPtr, pArea->cdPage, s_cdpage, ulLen ); +#endif + *bBufPtr += ulLen; + break; + case HB_IT_DATE: + *(*bBufPtr)++ = FPTIT_FLEXAR_DATE; + HB_PUT_LE_ULONG( *bBufPtr, pItem->item.asDate.value ); + *bBufPtr += 4; + break; + case HB_IT_INTEGER: + *(*bBufPtr)++ = FPTIT_FLEXAR_SHORT; + HB_PUT_LE_USHORT( *bBufPtr, pItem->item.asInteger.value ); + *bBufPtr += 2; + *(*bBufPtr)++ = '\0'; + break; + case HB_IT_LONG: + *(*bBufPtr)++ = FPTIT_FLEXAR_LONG; + HB_PUT_LE_ULONG( *bBufPtr, pItem->item.asLong.value ); + *bBufPtr += 4; + *(*bBufPtr)++ = '\0'; + *(*bBufPtr)++ = '\0'; + break; + case HB_IT_DOUBLE: + *(*bBufPtr)++ = FPTIT_FLEXAR_DBL; + *(*bBufPtr)++ = (BYTE) pItem->item.asDouble.length; + *(*bBufPtr)++ = (BYTE) pItem->item.asDouble.decimal; + HB_PUT_LE_DOUBLE( *bBufPtr, pItem->item.asDouble.value ); + *bBufPtr += 8; + break; + case HB_IT_LOGICAL: + *(*bBufPtr)++ = pItem->item.asLogical.value ? + FPTIT_FLEXAR_TRUE : FPTIT_FLEXAR_FALSE; + break; + case HB_IT_NIL: + default: + *(*bBufPtr)++ = FPTIT_FLEXAR_NIL; + } +} + +/* + * Write memo data. + */ +static ERRCODE hb_fptWriteMemo( FPTAREAP pArea, ULONG ulBlock, BYTE *bBufPtr, + ULONG ulType, ULONG ulLen, ULONG * ulStoredBlock ) +{ + MEMOGCTABLE fptGCtable; + ERRCODE errCode; + BOOL bWrite; + + HB_TRACE(HB_TR_DEBUG, ("hb_fptWriteMemo(%p, %lu, %p, %hu, %lu, %p)", + pArea, ulBlock, bBufPtr, ulType, ulLen, ulStoredBlock)); + + bWrite = ( ulLen != 0 || ( ulType != FPTIT_TEXT && ulType != FPTIT_BINARY ) ); + + if ( ulBlock == 0 && !bWrite ) + { + * ulStoredBlock = 0; + return SUCCESS; + } + + hb_fptInitGCdata( &fptGCtable ); + errCode = hb_fptReadGCdata( pArea, &fptGCtable ); + if ( errCode != SUCCESS ) + { + return errCode; + } + + if ( ulBlock > 0 ) + { + errCode = hb_fptGCfreeBlock( pArea, &fptGCtable, ulBlock, 0 ); + if ( errCode != SUCCESS ) + { + hb_fptDestroyGCdata( &fptGCtable ); + return errCode; + } + } + + /* Write memo header and data */ + if( bWrite ) + { + FPTBLOCK fptBlock; + + errCode = hb_fptGCgetFreeBlock( pArea, &fptGCtable, ulStoredBlock, ulLen ); + if ( errCode != SUCCESS ) + { + hb_fptDestroyGCdata( &fptGCtable ); + return errCode; + } + + HB_PUT_BE_ULONG( &fptBlock.type, ulType ); + HB_PUT_BE_ULONG( &fptBlock.size, ulLen ); + hb_fsSeek( pArea->hMemoFile, *ulStoredBlock * pArea->uiMemoBlockSize, FS_SET ); + hb_fsWrite( pArea->hMemoFile, ( BYTE * ) &fptBlock, sizeof( FPTBLOCK ) ); + + if ( ulLen > 0 ) + { + if ( hb_fsWriteLarge( pArea->hMemoFile, bBufPtr, ulLen ) != ulLen ) + { + errCode = EDBF_WRITE; + } + } + /* if written block is smaller then block size we should write at last + block byte 0xAF to be FLEX compatible */ + if ( errCode == SUCCESS && + pArea->bMemoType != MEMO_FPT_SIX && + pArea->bMemoType != MEMO_FPT_SIXHB && + ( ulLen + sizeof( FPTBLOCK ) ) % pArea->uiMemoBlockSize != 0 ) + { + ULONG ulBlocks = ( ulLen + sizeof( FPTBLOCK ) + pArea->uiMemoBlockSize - 1 ) / + pArea->uiMemoBlockSize; + hb_fsSeek( pArea->hMemoFile, ( *ulStoredBlock + ulBlocks ) * + pArea->uiMemoBlockSize - 1, FS_SET ); + hb_fsWrite( pArea->hMemoFile, ( BYTE * ) "\xAF", 1 ); + } + } + else + { + * ulStoredBlock = 0; + } + + if ( errCode == SUCCESS ) + { + errCode = hb_fptWriteGCdata( pArea, &fptGCtable ); + } + hb_fptDestroyGCdata( &fptGCtable ); + + return errCode; +} + +/* + * Assign a value to the specified memo field. + */ +static ERRCODE hb_fptPutMemo( FPTAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) +{ + ULONG ulLen, ulBlock, ulType; + BYTE itmBuffer[FLEX_ITEM_BUFSIZE], *bBufPtr = NULL, *bBufAlloc = NULL; + ERRCODE errCode; + + HB_TRACE(HB_TR_DEBUG, ("hb_fptPutMemo(%p, %hu, %p)", pArea, uiIndex, pItem)); + + if ( HB_IS_STRING( pItem ) ) + { + ulType = FPTIT_TEXT; + ulLen = pItem->item.asString.length; + bBufPtr = ( BYTE *) pItem->item.asString.value; +#ifndef HB_CDP_SUPPORT_OFF + if ( pArea->cdPage != s_cdpage ) + { + bBufAlloc = ( BYTE * ) hb_xgrab( ulLen ); + memcpy( bBufAlloc, bBufPtr, ulLen ); + hb_cdpnTranslate( ( char *) bBufAlloc, s_cdpage, pArea->cdPage, ulLen ); + bBufPtr = bBufAlloc; + } +#endif + } + else if ( pArea->bMemoType == MEMO_FPT_SIX || + pArea->bMemoType == MEMO_FPT_SIXHB ) + { + ulType = hb_itemType( pItem ); + ulLen = hb_fptCountSixItemLength( pArea, pItem ); + if ( ulLen > 0 ) + { + bBufPtr = bBufAlloc = ( BYTE * ) hb_xgrab( ulLen ); + hb_fptStoreSixItem( pArea, pItem, &bBufPtr ); + ulType = ( ULONG ) HB_GET_LE_USHORT( bBufAlloc ); + bBufPtr = bBufAlloc; + } + } + else if ( pArea->bMemoType == MEMO_FPT_FLEX || + pArea->bMemoType == MEMO_FPT_HB ) + { + ulType = hb_itemType( pItem ); + switch ( ulType ) + { + case HB_IT_ARRAY: + ulType = FPTIT_FLEX_ARRAY; + ulLen = hb_fptCountFlexItemLength( pArea, pItem ) - 1; + if ( ulLen > 0 ) + { + bBufPtr = bBufAlloc = (BYTE *) hb_xgrab( ulLen + 1 ); + hb_fptStoreFlexItem( pArea, pItem, &bBufPtr ); + bBufPtr = bBufAlloc + 1; /* FLEX doesn't store the first byte of array ID */ + } + break; + case HB_IT_NIL: + ulType = FPTIT_FLEX_NIL; + ulLen = 0; + break; + case HB_IT_LOGICAL: + ulType = pItem->item.asLogical.value ? FPTIT_FLEX_TRUE : FPTIT_FLEX_FALSE; + ulLen = 0; + break; + case HB_IT_DATE: + ulType = FPTIT_FLEX_LDATE; + ulLen = 4; + HB_PUT_LE_ULONG( itmBuffer, pItem->item.asDate.value ); + bBufPtr = itmBuffer; + break; + case HB_IT_INTEGER: + ulType = FPTIT_FLEX_SHORT; + ulLen = 2; + HB_PUT_LE_USHORT( itmBuffer, pItem->item.asInteger.value ); + bBufPtr = itmBuffer; + break; + case HB_IT_LONG: + ulType = FPTIT_FLEX_LONG; + ulLen = 4; + HB_PUT_LE_ULONG( itmBuffer, pItem->item.asLong.value ); + bBufPtr = itmBuffer; + break; + case HB_IT_DOUBLE: + ulType = FPTIT_FLEX_DOUBLE; + ulLen = 8; + HB_PUT_LE_DOUBLE( itmBuffer, pItem->item.asDouble.value ); + bBufPtr = itmBuffer; + break; + default : + ulType = FPTIT_BINARY; + ulLen = 0; + break; + } + } + else + { + ulType = FPTIT_BINARY; + ulLen = 0; + } + + ulBlock = hb_dbfGetMemoBlock( (DBFAREAP) pArea, uiIndex ); + + errCode = hb_fptWriteMemo( pArea, ulBlock, bBufPtr, ulType, ulLen, &ulBlock ); + + if ( bBufAlloc != NULL ) + { + hb_xfree( bBufAlloc ); + } + + hb_dbfPutMemoBlock( (DBFAREAP) pArea, uiIndex, ulBlock ); + + return errCode; +} + + +/* FPT METHODS */ + +/* + * Obtain the length of a field value. + * ( DBENTRYP_SVL ) hb_fptGetVarLen + */ +static ERRCODE hb_fptGetVarLen( FPTAREAP pArea, USHORT uiIndex, ULONG * pLength ) +{ + BOOL bDeleted; + + HB_TRACE(HB_TR_DEBUG, ("hb_fptGetVarLen(%p, %hu, %p)", pArea, uiIndex, pLength)); + + /* Force read record */ + if( SELF_DELETED( ( AREAP ) pArea, &bDeleted ) == FAILURE ) + return FAILURE; + + if( pArea->fHasMemo && pArea->hMemoFile != FS_ERROR && + pArea->lpFields[ uiIndex - 1 ].uiType == HB_IT_MEMO ) + { + if( hb_fptFileLockSh( pArea ) ) + { + * pLength = hb_fptGetMemoLen( pArea, uiIndex - 1 ); + hb_fptFileUnLock( pArea ); + } + else + { + * pLength = 0; + } + return SUCCESS; + } + + return SUPER_GETVARLEN( ( AREAP ) pArea, uiIndex, pLength ); +} + +/* + * Retrieve information about the current driver. + * ( DBENTRYP_SI ) hb_fptInfo + */ +static ERRCODE hb_fptInfo( FPTAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_fptInfo(%p, %hu, %p)", pArea, uiIndex, pItem)); + + switch( uiIndex ) + { + case DBI_MEMOEXT: + if ( pArea->fHasMemo && pArea->hMemoFile != FS_ERROR ) + { + PHB_FNAME pFileName; + + pFileName = hb_fsFNameSplit( ( char * ) pArea->szMemoFileName ); + hb_itemPutC( pItem, pFileName->szExtension ); + hb_xfree( pFileName ); + } + else + { + hb_itemPutC( pItem, ( hb_set.HB_SET_MFILEEXT && + strlen( hb_set.HB_SET_MFILEEXT ) > 0 ) ? + hb_set.HB_SET_MFILEEXT : + FPT_MEMOEXT ); + } + break; + + /* case DBI_RDD_VERSION */ + + default: + return SUPER_INFO( ( AREAP ) pArea, uiIndex, pItem ); + } + + return SUCCESS; +} + +/* + * Open a data store in the WorkArea. + * ( DBENTRYP_VP ) hb_fptOpen : NULL + */ + +/* + * Retrieve the size of the WorkArea structure. + * ( DBENTRYP_SP ) hb_fptStructSize + */ +static ERRCODE hb_fptStructSize( FPTAREAP pArea, USHORT * uiSize ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_fptStrucSize(%p, %p)", pArea, uiSize)); + HB_SYMBOL_UNUSED( pArea ); + + * uiSize = sizeof( FPTAREA ); + return SUCCESS; +} + +/* + * Obtain the name of replaceable database driver (RDD) subsystem. + * ( DBENTRYP_P ) hb_fptSysName + */ +static ERRCODE hb_fptSysName( FPTAREAP pArea, BYTE * pBuffer ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_fptSysName(%p, %p)", pArea, pBuffer)); + HB_SYMBOL_UNUSED( pArea ); + + strncpy( ( char * ) pBuffer, "DBFFPT", 7 /* HARBOUR_MAX_RDD_DRIVERNAME_LENGTH */ ); + return SUCCESS; +} + +/* + * Obtain the current value of a field. + * ( DBENTRYP_SI ) hb_fptGetValue + */ +static ERRCODE hb_fptGetValue( FPTAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) +{ + BOOL bDeleted; + ERRCODE uiError = SUCCESS; + + HB_TRACE(HB_TR_DEBUG, ("hb_fptGetValue(%p, %hu, %p)", pArea, uiIndex, pItem)); + + if( pArea->fHasMemo && pArea->hMemoFile != FS_ERROR && + pArea->lpFields[ uiIndex - 1 ].uiType == HB_IT_MEMO ) + { + /* Force read record */ + if( SELF_DELETED( ( AREAP ) pArea, &bDeleted ) == FAILURE ) + return FAILURE; + if( hb_fptFileLockSh( pArea ) ) + { + uiError = hb_fptGetMemo( pArea, uiIndex - 1, pItem ); + hb_fptFileUnLock( pArea ); + } + else + { + uiError = EDBF_LOCK; + } + if ( uiError != SUCCESS ) + { + PHB_ITEM pError = hb_errNew(); + ERRCODE uiErrorG = hb_dbfGetEGcode( uiError ); + + hb_errPutGenCode( pError, uiErrorG ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( uiErrorG ) ); + hb_errPutSubCode( pError, uiError ); + hb_errPutFlags( pError, EF_CANDEFAULT ); + SELF_ERROR( ( AREAP ) pArea, pError ); + hb_errRelease( pError ); + return FAILURE; + } + return SUCCESS; + } + else + return SUPER_GETVALUE( ( AREAP ) pArea, uiIndex, pItem ); +} + +/* + * Assign a value to a field. + * ( DBENTRYP_SI ) hb_fptPutValue + */ +static ERRCODE hb_fptPutValue( FPTAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) +{ + BOOL bDeleted; + ERRCODE uiError = SUCCESS; + + HB_TRACE(HB_TR_DEBUG, ("hb_fptPutValue(%p, %hu, %p)", pArea, uiIndex, pItem)); + + if( pArea->fHasMemo && pArea->hMemoFile != FS_ERROR && + pArea->lpFields[ uiIndex - 1 ].uiType == HB_IT_MEMO ) + { + /* Force read record */ + if( SELF_DELETED( ( AREAP ) pArea, &bDeleted ) == FAILURE ) + return FAILURE; + + if( !pArea->fPositioned ) + return SUCCESS; + + /* Buffer is hot? */ + if( !pArea->fRecordChanged && SELF_GOHOT( ( AREAP ) pArea ) == FAILURE ) + return FAILURE; + + if( hb_fptFileLockEx( pArea ) ) + { + uiError = hb_fptPutMemo( pArea, uiIndex -1, pItem ); + hb_fptFileUnLock( pArea ); + } + else + { + uiError = EDBF_LOCK; + } + /* Update deleted flag */ + pArea->pRecord[ 0 ] = (BYTE) (pArea->fDeleted ? '*' : ' '); + + if( uiError != SUCCESS ) + { + PHB_ITEM pError; + ERRCODE uiErrorG = hb_dbfGetEGcode( uiError ); + + pError = hb_errNew(); + hb_errPutGenCode( pError, uiErrorG ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( uiErrorG ) ); + hb_errPutSubCode( pError, uiError ); + hb_errPutFlags( pError, EF_CANDEFAULT ); + SELF_ERROR( ( AREAP ) pArea, pError ); + hb_errRelease( pError ); + return FAILURE; + } + return SUCCESS; + } + return SUPER_PUTVALUE( ( AREAP ) pArea, uiIndex, pItem); +} + + +/* ( DBENTRYP_V ) hb_fptCloseMemFile : NULL */ + +/* + * Create a memo file in the WorkArea. + * ( DBENTRYP_VP ) hb_fptCreateMemFile + */ +static ERRCODE hb_fptCreateMemFile( FPTAREAP pArea, LPDBOPENINFO pCreateInfo ) +{ + FPTHEADER fptHeader; + ULONG ulNextBlock, ulSize, ulLen; + BOOL bRetry; + PHB_ITEM pError; + + HB_TRACE(HB_TR_DEBUG, ("hb_fptCreateMemFile(%p, %p)", pArea, pCreateInfo)); + + if( pCreateInfo ) + { + pError = NULL; + /* Try create */ + do + { + pArea->hMemoFile = hb_spCreate( pCreateInfo->abName, FC_NORMAL ); + if( pArea->hMemoFile == FS_ERROR ) + { + if( !pError ) + { + pError = hb_errNew(); + hb_errPutGenCode( pError, EG_CREATE ); + hb_errPutSubCode( pError, EDBF_CREATE_DBF ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_CREATE ) ); + hb_errPutFileName( pError, ( char * ) pCreateInfo->abName ); + hb_errPutFlags( pError, EF_CANRETRY ); + } + bRetry = ( SELF_ERROR( ( AREAP ) pArea, pError ) == E_RETRY ); + } + else + bRetry = FALSE; + } while( bRetry ); + if( pError ) + hb_errRelease( pError ); + + if( pArea->hMemoFile == FS_ERROR ) + return FAILURE; + } + else /* For zap file */ + hb_fsSeek( pArea->hMemoFile, 0, FS_SET ); + + memset( &fptHeader, 0, sizeof( FPTHEADER ) ); + pArea->uiMemoBlockSize = ( hb_set.HB_SET_MBLOCKSIZE > 0 && + hb_set.HB_SET_MBLOCKSIZE < 0xFFFF ) ? + hb_set.HB_SET_MBLOCKSIZE : FPT_DEFBLOCKSIZE; + pArea->bMemoType = MEMO_FPT_HB; + //pArea->bMemoType = MEMO_FPT_SIX; + + ulNextBlock = ( sizeof( FPTHEADER ) + pArea->uiMemoBlockSize - 1 ) / pArea->uiMemoBlockSize; + HB_PUT_BE_ULONG( &fptHeader.nextBlock, ulNextBlock ); + HB_PUT_BE_USHORT( &fptHeader.blockSize, pArea->uiMemoBlockSize ); + if ( pArea->bMemoType == MEMO_FPT_SIX || + pArea->bMemoType == MEMO_FPT_SIXHB ) + { + strcpy( ( char *) fptHeader.signature1, "SIxMemo" ); + ulSize = 512; + } + else + { + strcpy( ( char *) fptHeader.signature1, "Harbour" ); + strcpy( ( char *) fptHeader.signature2, "FlexFile3\003" ); + ulSize = sizeof( FPTHEADER ); + } + if( hb_fsWrite( pArea->hMemoFile, ( BYTE * ) &fptHeader, ( USHORT) ulSize ) != ulSize ) + return FAILURE; + + memset( &fptHeader, 0, sizeof( FPTHEADER ) ); + ulLen = ulNextBlock * pArea->uiMemoBlockSize - ulSize; + while ( ulLen > 0 ) + { + ulSize = HB_MIN( ulLen, sizeof( FPTHEADER ) ); + if( hb_fsWrite( pArea->hMemoFile, ( BYTE * ) &fptHeader, ( USHORT ) ulSize ) != ulSize ) + return FAILURE; + ulLen -= ulSize; + } + /* trunc file */ + hb_fsWrite( pArea->hMemoFile, NULL, 0 ); + return SUCCESS; +} + + +/* ( DBENTRYP_SVPB ) hb_fptGetValueFile : NULL */ + +/* + * Open a memo file in the specified WorkArea. + * ( DBENTRYP_VP ) hb_fptOpenMemFile + */ +static ERRCODE hb_fptOpenMemFile( FPTAREAP pArea, LPDBOPENINFO pOpenInfo ) +{ + USHORT uiFlags; + BOOL bRetry; + FPTHEADER fptHeader; + PHB_ITEM pError; + + HB_TRACE(HB_TR_DEBUG, ("hb_fptOpenMemFile(%p, %p)", pArea, pOpenInfo)); + + uiFlags = (pOpenInfo->fReadonly ? FO_READ : FO_READWRITE) | + (pOpenInfo->fShared ? FO_DENYNONE : FO_EXCLUSIVE); + pError = NULL; + + /* Try open */ + do + { + pArea->hMemoFile = hb_spOpen( pOpenInfo->abName, uiFlags ); + if( pArea->hMemoFile == FS_ERROR ) + { + if( !pError ) + { + pError = hb_errNew(); + hb_errPutGenCode( pError, EG_OPEN ); + hb_errPutSubCode( pError, EDBF_OPEN_DBF ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_OPEN ) ); + hb_errPutFileName( pError, ( char * ) pOpenInfo->abName ); + hb_errPutFlags( pError, EF_CANRETRY | EF_CANDEFAULT ); + } + bRetry = ( SELF_ERROR( ( AREAP ) pArea, pError ) == E_RETRY ); + } + else + bRetry = FALSE; + } while( bRetry ); + + if( pError ) + hb_errRelease( pError ); + + if( pArea->hMemoFile == FS_ERROR ) + return FAILURE; + + pArea->uiMemoBlockSize = 0; + memset( &fptHeader, 0, sizeof( FPTHEADER ) ); + hb_fsSeek( pArea->hMemoFile, 0, FS_SET ); + if ( hb_fsRead( pArea->hMemoFile, ( BYTE * ) &fptHeader, sizeof( FPTHEADER ) ) >= 512 ) + { + pArea->uiMemoBlockSize = HB_GET_BE_USHORT( &fptHeader.blockSize ); + + /* Check for compatibility with Harbour memo headers */ + if ( memcmp( fptHeader.signature1, "Harbour", 7 ) == 0 ) + { + pArea->bMemoType = MEMO_FPT_HB; + } + /* Check for compatibility with SIX memo headers */ + else if ( memcmp( fptHeader.signature1, "SIxMemo", 7 ) == 0 ) + { + pArea->bMemoType = MEMO_FPT_SIX; + } + /* Check for compatibility with CLIP (www.itk.ru) memo headers */ + else if( memcmp( fptHeader.signature1, "Made by CLIP", 12 ) == 0 ) + { + pArea->bMemoType = MEMO_FPT_CLIP; + } + /* Check for compatibility with Clipper 5.3/FlexFile3 malformed memo headers */ + if ( pArea->bMemoType != MEMO_FPT_SIX && + memcmp( fptHeader.signature2, "FlexFile3\003", 10) == 0 ) + { + pArea->bMemoType = MEMO_FPT_FLEX; + if ( pArea->uiMemoBlockSize == 0) + pArea->uiMemoBlockSize = HB_GET_LE_USHORT( &fptHeader.flexSize ); + } + } + + if ( pArea->uiMemoBlockSize == 0 ) + { + pError = hb_errNew(); + hb_errPutGenCode( pError, EG_CORRUPTION ); + hb_errPutSubCode( pError, EDBF_CORRUPT ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_CORRUPTION ) ); + hb_errPutFileName( pError, (char *) pOpenInfo->abName ); + SELF_ERROR( ( AREAP ) pArea, pError ); + hb_errRelease( pError ); + return FAILURE; + } + + return SUCCESS; +} + +/* ( DBENTRYP_SVP ) hb_fptPutValueFile : NULL */ + +/* + * Read the database file header record in the WorkArea. + * ( DBENTRYP_V ) hb_fptReadDBHeader + */ +static ERRCODE hb_fptReadDBHeader( FPTAREAP pArea ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_fptReadHeader(%p)", pArea)); + + if( SUPER_READDBHEADER( ( AREAP ) pArea ) == FAILURE ) + return FAILURE; + + pArea->fHasMemo = ( pArea->bVersion == 0xF5 ); + + return SUCCESS; +} + +/* + * Write the database file header record in the WorkArea. + * ( DBENTRYP_V ) hb_fptWriteDBHeader + */ +static ERRCODE hb_fptWriteDBHeader( FPTAREAP pArea ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_fptWriteDBHeader(%p)", pArea)); + + if ( pArea->fHasMemo ) + pArea->bVersion = 0xF5; + + return SUPER_WRITEDBHEADER( ( AREAP ) pArea ); +} diff --git a/harbour/source/rdd/dbfntx/dbfntx1.c b/harbour/source/rdd/dbfntx/dbfntx1.c index 8fffae4b95..20e3f93f80 100644 --- a/harbour/source/rdd/dbfntx/dbfntx1.c +++ b/harbour/source/rdd/dbfntx/dbfntx1.c @@ -130,6 +130,7 @@ #include "hbapicdp.h" extern PHB_CODEPAGE s_cdpage; +#define __PRG_SOURCE__ __FILE__ extern USHORT hb_rddFieldIndex( AREAP pArea, char * szName ); @@ -158,7 +159,7 @@ HB_INIT_SYMBOLS_END( dbfntx1__InitSymbols ) #pragma startup dbfntx1__InitSymbols #endif -static RDDFUNCS ntxSuper = { 0 }; +static RDDFUNCS ntxSuper; /* Internal functions */ static LPKEYINFO hb_ntxKeyNew( LPKEYINFO pKeyFrom, int keylen ); @@ -2526,12 +2527,23 @@ static ERRCODE hb_ntxIndexCreate( LPNTXINDEX pIndex ) USHORT nAttemptLeft = 999; pszTempName = (char*) hb_xgrab( _POSIX_PATH_MAX ); // sortInfo.tempHandle = hb_fsCreateTemp( NULL, NULL, FC_NORMAL, pszTempName ); + #if defined( HB_OS_LINUX ) || defined( HB_OS_BSD ) + strcpy(pszTempName, "sort-tmp.XXXXXX" ); + #endif while( --nAttemptLeft ) { + #if !defined( HB_OS_LINUX ) && !defined( HB_OS_BSD ) tmpnam( pszTempName ); sortInfo.tempHandle = hb_fsCreate( (BYTE*)pszTempName,FC_NORMAL ); if( sortInfo.tempHandle != FS_ERROR ) break; + #else + sortInfo.tempHandle = mkstemp( pszTempName ); + if( sortInfo.tempHandle > -1 ) + { + break; + } + #endif } if( sortInfo.tempHandle == FS_ERROR ) hb_errInternal( HB_EI_ERRUNRECOV, "Cannot create temp file", "hb_ntxIndexCreate", NULL ); @@ -4281,12 +4293,13 @@ static RDDFUNCS ntxTable = { ntxBof, ntxPutValueFile, ntxReadDBHeader, ntxWriteDBHeader, + ntxExit, + ntxDrop, + ntxExists, ntxWhoCares }; -HB_FUNC(_DBFNTX ) -{ -} +HB_FUNC(_DBFNTX ){;} HB_FUNC( DBFNTX_GETFUNCTABLE ) { @@ -4294,10 +4307,22 @@ HB_FUNC( DBFNTX_GETFUNCTABLE ) USHORT * uiCount; uiCount = ( USHORT * ) hb_itemGetPtr( hb_param( 1, HB_IT_POINTER ) ); - * uiCount = RDDFUNCSCOUNT; pTable = ( RDDFUNCS * ) hb_itemGetPtr( hb_param( 2, HB_IT_POINTER ) ); if( pTable ) - hb_retni( hb_rddInherit( pTable, &ntxTable, &ntxSuper, ( BYTE * ) "DBF" ) ); + { + SHORT iRet; + + if ( uiCount ) + * uiCount = RDDFUNCSCOUNT; + iRet = hb_rddInherit( pTable, &ntxTable, &ntxSuper, ( BYTE * ) "DBFDBT" ); + if ( iRet == FAILURE ) + iRet = hb_rddInherit( pTable, &ntxTable, &ntxSuper, ( BYTE * ) "DBFFPT" ); + if ( iRet == FAILURE ) + iRet = hb_rddInherit( pTable, &ntxTable, &ntxSuper, ( BYTE * ) "DBF" ); + hb_retni( iRet ); + } else + { hb_retni( FAILURE ); + } } diff --git a/harbour/source/rdd/delim1.c b/harbour/source/rdd/delim1.c index a8a97c74fc..499fd01ffd 100644 --- a/harbour/source/rdd/delim1.c +++ b/harbour/source/rdd/delim1.c @@ -57,14 +57,22 @@ #include "hbapiitm.h" #include "hbrdddel.h" +#define __PRG_SOURCE__ __FILE__ + HB_FUNC( _DELIMC ); HB_FUNC( DELIM_GETFUNCTABLE ); +#undef HB_PRG_PCODE_VER +#define HB_PRG_PCODE_VER HB_PCODE_VER + HB_INIT_SYMBOLS_BEGIN( delim1__InitSymbols ) { "_DELIMC", HB_FS_PUBLIC, HB_FUNCNAME( _DELIMC ), NULL }, { "DELIM_GETFUNCTABLE", HB_FS_PUBLIC, HB_FUNCNAME( DELIM_GETFUNCTABLE ), NULL } HB_INIT_SYMBOLS_END( delim1__InitSymbols ) -#if defined(_MSC_VER) + +#if defined(HB_STATIC_STARTUP) + #pragma startup delim1__InitSymbols +#elif defined(_MSC_VER) #if _MSC_VER >= 1010 #pragma data_seg( ".CRT$XIY" ) #pragma comment( linker, "/Merge:.CRT=.data" ) @@ -77,8 +85,7 @@ HB_INIT_SYMBOLS_END( delim1__InitSymbols ) #pragma startup delim1__InitSymbols #endif -static RDDFUNCS delimSuper = { NULL }; - +static RDDFUNCS delimSuper; static RDDFUNCS delimTable = { hb_delimBof, hb_delimEof, hb_delimFound, @@ -170,6 +177,9 @@ static RDDFUNCS delimTable = { hb_delimBof, hb_delimPutValueFile, hb_delimReadDBHeader, hb_delimWriteDBHeader, + hb_delimExit, + hb_delimDrop, + hb_delimExists, hb_delimWhoCares }; diff --git a/harbour/source/rdd/rddsys.prg b/harbour/source/rdd/rddsys.prg index 79e8eccbce..a25441d834 100644 --- a/harbour/source/rdd/rddsys.prg +++ b/harbour/source/rdd/rddsys.prg @@ -54,9 +54,10 @@ ANNOUNCE RDDSYS -init procedure RddInit +PROCEDURE RddInit REQUEST DBFNTX + REQUEST DBFDBT /* NOTE: Using this internal version of this functions, since at this point the DBFNTX RDD may not be registered, depending on the diff --git a/harbour/source/rdd/sdf1.c b/harbour/source/rdd/sdf1.c index d3975836f3..a0dc69616d 100644 --- a/harbour/source/rdd/sdf1.c +++ b/harbour/source/rdd/sdf1.c @@ -57,14 +57,22 @@ #include "hbapiitm.h" #include "hbrddsdf.h" +#define __PRG_SOURCE__ __FILE__ + HB_FUNC( _SDFC ); HB_FUNC( SDF_GETFUNCTABLE ); +#undef HB_PRG_PCODE_VER +#define HB_PRG_PCODE_VER HB_PCODE_VER + HB_INIT_SYMBOLS_BEGIN( sdf1__InitSymbols ) { "_SDFC", HB_FS_PUBLIC, HB_FUNCNAME( _SDFC ), NULL }, { "SDF_GETFUNCTABLE", HB_FS_PUBLIC, HB_FUNCNAME( SDF_GETFUNCTABLE ), NULL } HB_INIT_SYMBOLS_END( sdf1__InitSymbols ) -#if defined(_MSC_VER) + +#if defined(HB_STATIC_STARTUP) + #pragma startup sdf1__InitSymbols +#elif defined(_MSC_VER) #if _MSC_VER >= 1010 #pragma data_seg( ".CRT$XIY" ) #pragma comment( linker, "/Merge:.CRT=.data" ) @@ -77,8 +85,7 @@ HB_INIT_SYMBOLS_END( sdf1__InitSymbols ) #pragma startup sdf1__InitSymbols #endif -static RDDFUNCS sdfSuper = { NULL }; - +static RDDFUNCS sdfSuper; static RDDFUNCS sdfTable = { hb_sdfBof, hb_sdfEof, hb_sdfFound, @@ -170,6 +177,9 @@ static RDDFUNCS sdfTable = { hb_sdfBof, hb_sdfPutValueFile, hb_sdfReadDBHeader, hb_sdfWriteDBHeader, + hb_sdfExit, + hb_sdfDrop, + hb_sdfExists, hb_sdfWhoCares }; diff --git a/harbour/source/rdd/workarea.c b/harbour/source/rdd/workarea.c index f51187704b..9bab8c6179 100644 --- a/harbour/source/rdd/workarea.c +++ b/harbour/source/rdd/workarea.c @@ -57,6 +57,7 @@ #include #include "hbapi.h" +#include "hbapirdd.h" #include "hbinit.h" #include "hbvm.h" #include "hbapiitm.h" @@ -448,7 +449,6 @@ ERRCODE hb_waAlias( AREAP pArea, BYTE * szAlias ) HB_TRACE(HB_TR_DEBUG, ("hb_waAlias(%p, %p)", pArea, szAlias)); szAlias[0] = '\0'; - strncat( ( char * ) szAlias, ( ( PHB_DYNS ) pArea->atomAlias )->pSymbol->szName, HARBOUR_MAX_RDD_ALIAS_LENGTH ); return SUCCESS; @@ -644,11 +644,11 @@ ERRCODE hb_waSysName( AREAP pArea, BYTE * pBuffer ) ERRCODE hb_waEval( AREAP pArea, LPDBEVALINFO pEvalInfo ) { BOOL bFor, bWhile; - ULONG ulNext; + LONG lNext; HB_TRACE(HB_TR_DEBUG, ("hb_waEval(%p, %p)", pArea, pEvalInfo)); - ulNext = 0; + lNext = 0; if( pEvalInfo->dbsci.itmRecID ) { SELF_GOTO( pArea, hb_itemGetNL( pEvalInfo->dbsci.itmRecID ) ); @@ -676,30 +676,35 @@ ERRCODE hb_waEval( AREAP pArea, LPDBEVALINFO pEvalInfo ) SELF_GOTOP( pArea ); if( pEvalInfo->dbsci.lNext ) - ulNext = hb_itemGetNL( pEvalInfo->dbsci.lNext ); + lNext = hb_itemGetNL( pEvalInfo->dbsci.lNext ); - while( !pArea->fEof ) + if( !pEvalInfo->dbsci.lNext || lNext > 0 ) { - if( pEvalInfo->dbsci.lNext && ulNext-- < 1 ) - break; - - if( pEvalInfo->dbsci.itmCobWhile ) + while( !pArea->fEof ) { - bWhile = hb_itemGetL( hb_vmEvalBlock( pEvalInfo->dbsci.itmCobWhile ) ); - if( !bWhile ) + + if( pEvalInfo->dbsci.itmCobWhile ) + { + bWhile = hb_itemGetL( hb_vmEvalBlock( pEvalInfo->dbsci.itmCobWhile ) ); + if( !bWhile ) + break; + } + else + bWhile = TRUE; + + if( pEvalInfo->dbsci.itmCobFor ) + bFor = hb_itemGetL( hb_vmEvalBlock( pEvalInfo->dbsci.itmCobFor ) ); + else + bFor = TRUE; + + if( bFor && bWhile ) + hb_vmEvalBlock( pEvalInfo->itmBlock ); + + if( pEvalInfo->dbsci.lNext && --lNext < 1 ) break; + + SELF_SKIP( pArea, 1 ); } - else - bWhile = TRUE; - - if( pEvalInfo->dbsci.itmCobFor ) - bFor = hb_itemGetL( hb_vmEvalBlock( pEvalInfo->dbsci.itmCobFor ) ); - else - bFor = TRUE; - - if( bFor && bWhile ) - hb_vmEvalBlock( pEvalInfo->itmBlock ); - SELF_SKIP( pArea, 1 ); } return SUCCESS; diff --git a/harbour/source/rtl/filehb.c b/harbour/source/rtl/filehb.c index bc016b197b..e56a01c5c4 100644 --- a/harbour/source/rtl/filehb.c +++ b/harbour/source/rtl/filehb.c @@ -58,5 +58,5 @@ HB_FUNC( FILE ) { - hb_retl( ISCHAR( 1 ) ? hb_spFile( ( BYTE * ) hb_parc( 1 ) ) : FALSE ); + hb_retl( ISCHAR( 1 ) ? hb_spFile( ( BYTE * ) hb_parc( 1 ),NULL ) : FALSE ); } diff --git a/harbour/source/rtl/filesys.c b/harbour/source/rtl/filesys.c index 03979c0e70..09d26ab033 100644 --- a/harbour/source/rtl/filesys.c +++ b/harbour/source/rtl/filesys.c @@ -1291,7 +1291,7 @@ BOOL hb_fsLock ( FHANDLE hFileHandle, ULONG ulStart, #if defined(X__WIN32__) { errno = 0; - switch( uiMode ) + switch( uiMode & FL_MASK ) { case FL_LOCK: bResult = ( LockFile( DostoWinHandle(hFileHandle), ulStart,0, ulLength,0 ) == 0 ); @@ -1314,7 +1314,7 @@ BOOL hb_fsLock ( FHANDLE hFileHandle, ULONG ulStart, errno = 0; - switch( uiMode ) + switch( uiMode & FL_MASK ) { case FL_LOCK: @@ -1351,7 +1351,7 @@ BOOL hb_fsLock ( FHANDLE hFileHandle, ULONG ulStart, ULONG ulOldPos = hb_fsSeek( hFileHandle, ulStart, FS_SET ); errno = 0; - switch( uiMode ) + switch( uiMode & FL_MASK ) { case FL_LOCK: bResult = ( locking( hFileHandle, _LK_LOCK, ulLength ) == 0 ); @@ -1375,7 +1375,7 @@ BOOL hb_fsLock ( FHANDLE hFileHandle, ULONG ulStart, ULONG ulOldPos = hb_fsSeek( hFileHandle, ulStart, FS_SET ); errno = 0; - switch( uiMode ) + switch( uiMode & FL_MASK ) { case FL_LOCK: bResult = ( _locking( hFileHandle, _LK_LOCK, ulLength ) == 0 ); @@ -1402,7 +1402,7 @@ BOOL hb_fsLock ( FHANDLE hFileHandle, ULONG ulStart, errno = 0; - switch( uiMode ) + switch( uiMode & FL_MASK ) { case FL_LOCK: @@ -1436,7 +1436,7 @@ BOOL hb_fsLock ( FHANDLE hFileHandle, ULONG ulStart, #elif defined(HAVE_POSIX_IO) && !defined(__IBMCPP__) && ( !defined(__GNUC__) || defined(__DJGPP__) ) errno = 0; - switch( uiMode ) + switch( uiMode & FL_MASK ) { case FL_LOCK: bResult = ( lock( hFileHandle, ulStart, ulLength ) == 0 ); diff --git a/harbour/source/rtl/spfiles.c b/harbour/source/rtl/spfiles.c index 647c68a73c..dec810a78f 100644 --- a/harbour/source/rtl/spfiles.c +++ b/harbour/source/rtl/spfiles.c @@ -53,64 +53,75 @@ #include "hbapifs.h" #include "hbset.h" -static BOOL FindFile( BYTE * pFilename, BYTE * path ) +BOOL hb_spFile( BYTE * pFilename, BYTE RetPath[ _POSIX_PATH_MAX + 3 + 10 ] ) { + BYTE *Path; BOOL bIsFile = FALSE; PHB_FNAME pFilepath; - HB_TRACE(HB_TR_DEBUG, ("FindFile(%s, %p)", (char*) pFilename, path)); + HB_TRACE(HB_TR_DEBUG, ("hb_spFile(%s, %p)", (char*) pFilename, RetPath)); + + if( RetPath ) + { + Path = RetPath; + } + else + { + Path = (BYTE *) hb_xgrab( _POSIX_PATH_MAX + 3 + 10 ); + } pFilepath = hb_fsFNameSplit( (char*) pFilename ); + if( pFilepath->szPath ) { - hb_fsFNameMerge( (char*) path, pFilepath ); - bIsFile = hb_fsFile( path ); + hb_fsFNameMerge( (char*) Path, pFilepath ); + bIsFile = hb_fsFile( Path ); } else { if( hb_set.HB_SET_DEFAULT ) { pFilepath->szPath = hb_set.HB_SET_DEFAULT; - hb_fsFNameMerge( (char*) path, pFilepath ); - bIsFile = hb_fsFile( path ); + hb_fsFNameMerge( (char*) Path, pFilepath ); + bIsFile = hb_fsFile( Path ); } if( !bIsFile && hb_set.HB_SET_PATH ) { - HB_PATHNAMES * nextPath = hb_setGetFirstSetPath(); - while( !bIsFile && nextPath ) + HB_PATHNAMES *NextPath = hb_setGetFirstSetPath(); + + while( bIsFile == FALSE && NextPath ) { - pFilepath->szPath = nextPath->szPath; - hb_fsFNameMerge( (char*) path, pFilepath ); - bIsFile = hb_fsFile( path ); - nextPath = nextPath->pNext; + pFilepath->szPath = NextPath->szPath; + hb_fsFNameMerge( (char*) Path, pFilepath ); + bIsFile = hb_fsFile( Path ); + NextPath = NextPath->pNext; } } } + hb_xfree( pFilepath ); - if( !bIsFile ) - *path = '\0'; + if( bIsFile == FALSE ) + { + Path[0] = '\0'; + } + + if( RetPath == NULL ) + { + hb_xfree( Path ); + } return bIsFile; } -BOOL hb_spFile( BYTE * pFilename ) -{ - BYTE path[ _POSIX_PATH_MAX + 1 ]; - - HB_TRACE(HB_TR_DEBUG, ("hb_spFile(%s, %p)", (char*) pFilename, path)); - - return FindFile( pFilename, path ); -} - FHANDLE hb_spOpen( BYTE * pFilename, USHORT uiFlags ) { - BYTE path[ _POSIX_PATH_MAX + 1 ]; + BYTE path[ _POSIX_PATH_MAX + 3 + 10 ]; HB_TRACE(HB_TR_DEBUG, ("hb_spOpen(%p, %hu)", pFilename, uiFlags)); - if( FindFile( pFilename, path ) ) + if( hb_spFile( pFilename, path ) ) return hb_fsOpen( path, uiFlags ); else return hb_fsOpen( pFilename, uiFlags );