From c69282e2301c61b18f2c7dff31d14a34d9f52b86 Mon Sep 17 00:00:00 2001 From: Bruno Cantero Date: Sun, 10 Oct 1999 11:34:58 +0000 Subject: [PATCH] ChangeLogTag:19991010-13:26 GMT+1 Bruno Cantero --- harbour/ChangeLog | 34 ++ harbour/config/global.cf | 1 + harbour/include/rddapi.h | 12 +- harbour/makefile.vc | 19 +- harbour/rdd.b32 | 9 +- harbour/source/rdd/dbcmd.c | 309 ++++++----- harbour/source/rdd/dbf1.c | 754 ++++++++++++++++---------- harbour/source/rdd/dbfcdx/dbfcdx0.prg | 63 +++ harbour/source/rdd/dbfcdx/dbfcdx1.c | 650 ++++++++++++++++++++++ harbour/tests/bld_vc.bat | 2 +- harbour/tests/testdbf.prg | 44 +- 11 files changed, 1435 insertions(+), 462 deletions(-) create mode 100644 harbour/source/rdd/dbfcdx/dbfcdx0.prg create mode 100644 harbour/source/rdd/dbfcdx/dbfcdx1.c diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 6c3b045093..eede5f96d5 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -1,3 +1,37 @@ +19991010-13:26 GMT+1 Bruno Cantero + + * include/rddapi.h + * source/rdd/dbcmd.c + + Added undocumented parameters: + dbCreate( cFileName, aStruct, cRDD, lNew, cAlias, cDelimiter ) + lNew: if specified, the created file will also be opened. If .F. this will be done + in the current workarea; if .T. this will be done in the next available. + cAlias: Alias for the workarea. + cDelimiter: for the DELIM driver (not implemented yet). + + * source/rdd/dbf1.c + * SELF_OPEN(), now generate an error with retry possibility. + * SELF_OPENMEMFILE(), now generate an error with retry possibility. + * SELF_CREATE(), now generate an error with retry possibility. + * SELF_CREATEMEMFILE(), now generate an error with retry possibility. + * SELF_INFO(), more values. + + + source/rdd/dbfcdx/Makefile + + source/rdd/dbfcdx/dbfcdx0.prg + + source/rdd/dbfcdx/dbfcdx1.c + + Files for the DBFCDX driver. + + .DBT and .FPT file memos. + + * rdd.b32 + * makefile.vc + * config/global.cf + * tests/bld_vc.bat + * Added new driver. + + * tests/testdbf.prg + * Test for undocumented parameters in dbCreate() + * Test for the DBFCDX driver. + 19991010-13:25 GMT+2 Ryszard Glab *source/rtl/console.c diff --git a/harbour/config/global.cf b/harbour/config/global.cf index 3617905e36..bb877b6b8c 100644 --- a/harbour/config/global.cf +++ b/harbour/config/global.cf @@ -8,6 +8,7 @@ ARCH := $(HB_ARCHITECTURE)/$(HB_COMPILER) HB_DB_DRIVERS=\ nulsys \ dbfntx \ + dbfcdx \ ifeq ($(HB_BIN_COMPILE),) HB_BIN_COMPILE := $(TOP)$(ROOT)source/compiler/$(ARCH) diff --git a/harbour/include/rddapi.h b/harbour/include/rddapi.h index 417dbd7165..aaf52b461a 100644 --- a/harbour/include/rddapi.h +++ b/harbour/include/rddapi.h @@ -511,6 +511,7 @@ typedef struct _FIELD USHORT uiLen; /* Field length */ USHORT uiDec; /* Decimal length */ USHORT uiArea; /* Area this field resides in */ + USHORT uiOffset; /* Offset for this field */ void * sym; /* Symbol that represents the field */ void * memo; /* Pointer to memo data */ struct _FIELD *lpfNext; /* The next field in the list */ @@ -589,7 +590,6 @@ typedef USHORT ( * DBENTRYP_SSI )( AREAP area, USHORT p1, USHORT p2, PHB_ITEM p typedef USHORT ( * DBENTRYP_ISI )( AREAP area, PHB_ITEM p1, USHORT p2, PHB_ITEM p3 ); #if 0 -typedef USHORT ( * DBENTRYP_SVPB )( AREAP area, USHORT index, void * param, USHORT mode); typedef USHORT ( * DBENTRYP_VPL )( AREAP area, void * p1, LONG p2); typedef USHORT ( * DBENTRYP_VPLP )( AREAP area, void * p1, LONGP p2); typedef USHORT ( * DBENTRYP_LSP )( AREAP area, LONG p1, USHORTP p2); @@ -728,13 +728,9 @@ typedef struct _RDDFUNCS DBENTRYP_V closeMemFile; DBENTRYP_VP createMemFile; -#if 0 - DBENTRYP_SVPB getValueFile; -#endif + DBENTRYP_SVP getValueFile; DBENTRYP_VP openMemFile; -#if 0 DBENTRYP_SVP putValueFile; -#endif /* Database file header handling */ @@ -885,7 +881,7 @@ typedef RDDFUNCS * PRDDFUNCS; #define SELF_CLOSEMEMFILE(w) ((*(w)->lprfsHost->closeMemFile)(w)) #define SELF_CREATEMEMFILE(w,bp) ((*(w)->lprfsHost->createMemFile)(w,bp)) -#define SELF_GETVALUEFILE(w,i,bp,b) ((*(w)->lprfsHost->getValueFile)(w,i,bp,b)) +#define SELF_GETVALUEFILE(w,i,bp) ((*(w)->lprfsHost->getValueFile)(w,i,bp)) #define SELF_OPENMEMFILE(w,bp) ((*(w)->lprfsHost->openMemFile)(w,bp)) #define SELF_PUTVALUEFILE(w,i,bp) ((*(w)->lprfsHost->putValueFile)(w,i,bp)) @@ -1039,7 +1035,7 @@ typedef RDDFUNCS * PRDDFUNCS; #define SUPER_CLOSEMEMFILE(w) ((*(SUPERTABLE)->closeMemFile)(w)) #define SUPER_CREATEMEMFILE(w,bp) ((*(SUPERTABLE)->createMemFile)(w,bp)) -#define SUPER_GETVALUEFILE(w,i,bp,b) ((*(SUPERTABLE)->getValueFile)(w,i,bp,b)) +#define SUPER_GETVALUEFILE(w,i,bp) ((*(SUPERTABLE)->getValueFile)(w,i,bp)) #define SUPER_OPENMEMFILE(w,bp) ((*(SUPERTABLE)->openMemFile)(w,bp)) #define SUPER_PUTVALUEFILE(w,i,bp) ((*(SUPERTABLE)->putValueFile)(w,i,bp)) diff --git a/harbour/makefile.vc b/harbour/makefile.vc index 4dd689261e..1de9c7040a 100644 --- a/harbour/makefile.vc +++ b/harbour/makefile.vc @@ -50,13 +50,14 @@ TOOLS_LIB=$(LIB_DIR)\hbtools.lib PP_LIB=$(LIB_DIR)\hbpp.lib DEBUG_LIB=$(LIB_DIR)\debug.lib DBFNTX_LIB=$(LIB_DIR)\dbfntx.lib +DBFCDX_LIB=$(LIB_DIR)\dbfcdx.lib RUNNER_LIB=$(LIB_DIR)\runner.lib HARBOUR_EXE=$(BIN_DIR)\harbour.exe PP_EXE=$(BIN_DIR)\hbpp.exe RUNNER_EXE=$(BIN_DIR)\hbrun.exe HARBOURFLAGS=-iinclude -n -q -LIBS=$(HARBOUR_LIB) $(TERMINAL_LIB) $(TOOLS_LIB) $(DEBUG_LIB) $(PP_LIB) $(DBFNTX_LIB) $(RUNNER_LIB) +LIBS=$(HARBOUR_LIB) $(TERMINAL_LIB) $(TOOLS_LIB) $(DEBUG_LIB) $(PP_LIB) $(DBFNTX_LIB) $(DBFCDX_LIB) $(RUNNER_LIB) # # OBJ list for harbour.lib. Add new ones as needed @@ -190,6 +191,10 @@ DBFNTX_LIB_OBJS = \ $(OBJ_DIR)\dbfntx0.obj \ $(OBJ_DIR)\dbfntx1.obj +DBFCDX_LIB_OBJS = \ + $(OBJ_DIR)\dbfcdx0.obj \ + $(OBJ_DIR)\dbfcdx1.obj + # # OBJ list for runner.lib. Add new ones as needed # @@ -226,6 +231,7 @@ all: $(HARBOUR_EXE) \ $(PP_LIB) \ $(DEBUG_LIB) \ $(DBFNTX_LIB) \ + $(DBFCDX_LIB) \ $(PP_EXE) \ $(RUNNER_LIB) \ $(RUNNER_EXE) @@ -296,6 +302,9 @@ $(TERMINAL_LIB) : $(TERMINAL_LIB_OBJS) $(DBFNTX_LIB) : $(DBFNTX_LIB_OBJS) lib /OUT:$(DBFNTX_LIB) $(DBFNTX_LIB_OBJS) +$(DBFCDX_LIB) : $(DBFCDX_LIB_OBJS) + lib /OUT:$(DBFCDX_LIB) $(DBFCDX_LIB_OBJS) + $(RUNNER_LIB) : $(RUNNER_LIB_OBJS) lib /OUT:$(RUNNER_LIB) $(RUNNER_LIB_OBJS) @@ -813,3 +822,11 @@ $(OBJ_DIR)\dbfntx0.obj : $(RDD_DIR)\dbfntx\dbfntx0.c $(OBJ_DIR)\dbfntx1.obj : $(RDD_DIR)\dbfntx\dbfntx1.c $(CC) $(CLIBFLAGS) -Fo$@ $** +$(RDD_DIR)\dbfcdx\dbfcdx0.c : $(RDD_DIR)\dbfcdx\dbfcdx0.prg + $(HARBOUR_EXE) $** $(HARBOURFLAGS) -o$@ + +$(OBJ_DIR)\dbfcdx0.obj : $(RDD_DIR)\dbfcdx\dbfcdx0.c + $(CC) $(CLIBFLAGS) -Fo$@ $** + +$(OBJ_DIR)\dbfcdx1.obj : $(RDD_DIR)\dbfcdx\dbfcdx1.c + $(CC) $(CLIBFLAGS) -Fo$@ $** diff --git a/harbour/rdd.b32 b/harbour/rdd.b32 index 0ae5820fee..14b4f5a059 100644 --- a/harbour/rdd.b32 +++ b/harbour/rdd.b32 @@ -5,20 +5,21 @@ # makefile for Borland C/C++ 32 bits # ODBC Harbor Library and Import Library makefile -.path.c = source\rdd;source\rdd\dbfntx +.path.c = source\rdd;source\rdd\dbfntx;source\rdd\dbfcdx .path.h = include .path.lib = lib\b32 .path.obj = obj -.path.prg = source\rdd;source\rdd\dbfntx +.path.prg = source\rdd;source\rdd\dbfntx;source\rdd\dbfcdx lib\b32\rdd.lib : rddsys.obj dbcmd.obj dbfntx1.obj dbfntx0.obj dbf0.obj dbf1.obj \ - delim0.obj delim1.obj sdf0.obj sdf1.obj + delim0.obj delim1.obj sdf0.obj sdf1.obj dbfcdx1.obj dbfcdx0.obj dbf0.c : dbf0.prg dbfntx0.c : dbfntx0.prg rddsys.c : rddsys.prg sdf0.c : sdf0.prg delim0.c : delim0.prg +dbfcdx0.c : dbfcdx0.prg dbcmd.obj : dbcmd.c rddsys.obj : rddsys.c @@ -30,6 +31,8 @@ sdf0.obj : sdf0.c sdf1.obj : sdf1.c delim0.obj : delim0.c delim1.obj : delim1.c +dbfcdx0.obj : dbfcdx0.c +dbfcdx1.obj : dbfcdx1.c .c.obj : bcc32 -c -O2 -Iinclude -o$@ -v $< diff --git a/harbour/source/rdd/dbcmd.c b/harbour/source/rdd/dbcmd.c index 8e6019b9c6..63083c6da4 100644 --- a/harbour/source/rdd/dbcmd.c +++ b/harbour/source/rdd/dbcmd.c @@ -144,7 +144,18 @@ static ERRCODE AddField( AREAP pArea, LPDBFIELDINFO pFieldInfo ) pField = pArea->lpFields + pArea->uiFieldCount; if( pArea->uiFieldCount > 0 ) + { ( ( LPFIELD ) ( pField - 1 ) )->lpfNext = pField; + if( ( ( LPFIELD ) ( pField - 1 ) )->uiType == 'C' ) + pField->uiOffset = ( ( LPFIELD ) ( pField - 1 ) )->uiOffset + + ( ( LPFIELD ) ( pField - 1 ) )->uiLen + + ( ( USHORT ) ( ( LPFIELD ) ( pField - 1 ) )->uiDec << 8 ); + else + pField->uiOffset = ( ( LPFIELD ) ( pField - 1 ) )->uiOffset + + ( ( LPFIELD ) ( pField - 1 ) )->uiLen; + } + else + pField->uiOffset = 1; pField->sym = ( void * ) hb_dynsymGet( ( char * ) pFieldInfo->atomName ); pField->uiType = pFieldInfo->uiType; pField->uiTypeExtended = pFieldInfo->typeExtended; @@ -226,36 +237,35 @@ static ERRCODE FieldInfo( AREAP pArea, USHORT uiIndex, USHORT uiType, PHB_ITEM p LPFIELD pField; char szType[ 2 ]; - pField = pArea->lpFields; - while( pField && uiIndex > 1 ) + if( uiIndex > pArea->uiFieldCount ) + return FAILURE; + + pField = pArea->lpFields + uiIndex - 1; + switch( uiType ) { - pField = pField->lpfNext; - uiIndex--; + case DBS_NAME: + hb_itemPutC( pItem, ( ( PHB_DYNS ) pField->sym )->pSymbol->szName ); + break; + + case DBS_TYPE: + szType[ 0 ] = pField->uiType; + szType[ 1 ] = '\0'; + hb_itemPutC( pItem, szType ); + break; + + case DBS_LEN: + hb_itemPutNL( pItem, pField->uiLen ); + break; + + case DBS_DEC: + hb_itemPutNL( pItem, pField->uiDec ); + break; + + default: + return FAILURE; + } - if( pField ) - { - switch( uiType ) - { - case DBS_NAME: - hb_itemPutC( pItem, ( ( PHB_DYNS ) pField->sym )->pSymbol->szName ); - return SUCCESS; - - case DBS_TYPE: - szType[ 0 ] = pField->uiType; - szType[ 1 ] = '\0'; - hb_itemPutC( pItem, szType ); - return SUCCESS; - - case DBS_LEN: - hb_itemPutNL( pItem, pField->uiLen ); - return SUCCESS; - - case DBS_DEC: - hb_itemPutNL( pItem, pField->uiDec ); - return SUCCESS; - } - } - return FAILURE; + return SUCCESS; } @@ -263,19 +273,13 @@ static ERRCODE FieldName( AREAP pArea, USHORT uiIndex, void * szName ) { LPFIELD pField; - pField = pArea->lpFields; - while( pField && uiIndex > 1 ) - { - pField = pField->lpfNext; - uiIndex--; - } - if( pField ) - { - strncpy( ( char * ) szName, ( ( PHB_DYNS ) pField->sym )->pSymbol->szName, - HARBOUR_MAX_RDD_FIELDNAME_LENGTH ); - return SUCCESS; - } - return FAILURE; + if( uiIndex > pArea->uiFieldCount ) + return FAILURE; + + pField = pArea->lpFields + uiIndex - 1; + strncpy( ( char * ) szName, ( ( PHB_DYNS ) pField->sym )->pSymbol->szName, + HARBOUR_MAX_RDD_FIELDNAME_LENGTH ); + return SUCCESS; } static ERRCODE Found( AREAP pArea, BOOL * pFound ) @@ -290,31 +294,6 @@ static ERRCODE GetRec( AREAP pArea, BYTE ** pBuffer ) return SUCCESS; } -static ERRCODE GoCold( AREAP pArea ) -{ - PHB_ITEM pError; - - if( pArea->lpExtendInfo->fReadOnly ) - { - pError = hb_errNew(); - hb_errPutGenCode( pError, EG_READONLY ); - hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_READONLY ) ); - hb_errPutSubCode( pError, 1025 ); - SELF_ERROR( ( AREAP ) pCurrArea->pArea, pError ); - hb_errRelease( pError ); - return FAILURE; - } - else - return SUCCESS; -} - -static ERRCODE GoHot( AREAP pArea ) -{ - pArea->lpExtendInfo->fRecordChanged = FALSE; - pArea->lpFileInfo->fAppend = FALSE; - return SUCCESS; -} - static ERRCODE NewArea( AREAP pArea ) { pArea->lpFileInfo = ( LPFILEINFO ) hb_xgrab( sizeof( FILEINFO ) ); @@ -438,8 +417,8 @@ static RDDFUNCS defTable = { Bof, GetRec, ( DBENTRYP_SI ) UnSupported, ( DBENTRYP_SVL ) UnSupported, - GoCold, - GoHot, + UnSupported, + UnSupported, ( DBENTRYP_P ) UnSupported, ( DBENTRYP_SI ) UnSupported, UnSupported, @@ -462,7 +441,9 @@ static RDDFUNCS defTable = { Bof, ( DBENTRYP_UL ) UnSupported, UnSupported, ( DBENTRYP_VP ) UnSupported, + ( DBENTRYP_SVP ) UnSupported, ( DBENTRYP_VP ) UnSupported, + ( DBENTRYP_SVP ) UnSupported, UnSupported, UnSupported, ( DBENTRYP_SVP ) UnSupported @@ -852,6 +833,21 @@ ERRCODE hb_rddFieldGet( HB_ITEM_PTR pItem, PHB_SYMB pFieldSymbol ) return FAILURE; } +void hb_rddShutDown( void ) +{ + LPRDDNODE pRddNode; + + hb_rddCloseAll(); + if( szDefDriver ) + hb_xfree( szDefDriver ); + while( pRddList ) + { + pRddNode = pRddList; + pRddList = pRddList->pNext; + hb_xfree( pRddNode ); + } +} + /* * -- HARBOUR FUNCTIONS -- */ @@ -997,8 +993,6 @@ HARBOUR HB_DBAPPEND( void ) if( pCurrArea ) { bNetError = FALSE; - if( SELF_GOCOLD( ( AREAP ) pCurrArea->pArea ) == FAILURE ) - return; if( ISLOG( 1 ) ) bUnLockAll = hb_parl( 1 ); bNetError = ( SELF_APPEND( ( AREAP ) pCurrArea->pArea, bUnLockAll ) == FAILURE ); @@ -1057,15 +1051,17 @@ HARBOUR HB_DBCOMMITALL( void ) HARBOUR HB_DBCREATE( void ) { - char * szFileName, * szDriver; + char * szFileName, * szMemoName, * szDriver, * szAlias; PHB_ITEM pStruct, pFieldDesc, pFileExt; LPRDDNODE pRddNode; + LPAREANODE pAreaNode; AREAP pTempArea; USHORT uiSize, uiRddID; DBOPENINFO pInfo; USHORT uiLen; PHB_FNAME pFileName; char cDriverBuffer[ HARBOUR_MAX_RDD_DRIVERNAME_LENGTH ]; + BOOL bError; szFileName = hb_parc( 1 ); pStruct = hb_param( 2 , IT_ARRAY ); @@ -1128,6 +1124,7 @@ HARBOUR HB_DBCREATE( void ) pFileName = hb_fsFNameSplit( szFileName ); szFileName = ( char * ) hb_xgrab( _POSIX_PATH_MAX + 3 ); + szMemoName = ( char * ) hb_xgrab( _POSIX_PATH_MAX + 3 ); strcpy( szFileName, hb_parc( 1 ) ); if( !pFileName->szExtension ) { @@ -1138,25 +1135,108 @@ HARBOUR HB_DBCREATE( void ) } pInfo.abName = ( BYTE * ) szFileName; - if( SELF_CREATE( ( AREAP ) pTempArea, &pInfo ) == SUCCESS && - pTempArea->lpExtendInfo->fHasMemo ) + bError = ( SELF_CREATE( ( AREAP ) pTempArea, &pInfo ) == FAILURE ); + if( !bError && pTempArea->lpExtendInfo->fHasMemo ) { pFileExt = hb_itemPutC( NULL, "" ); SELF_INFO( ( AREAP ) pTempArea, DBI_MEMOEXT, pFileExt ); - szFileName[ 0 ] = '\0'; + szMemoName[ 0 ] = '\0'; if( pFileName->szPath ) - strcat( szFileName, pFileName->szPath ); - strcat( szFileName, pFileName->szName ); - strcat( szFileName, pFileExt->item.asString.value ); - pInfo.abName = ( BYTE * ) szFileName; - SELF_CREATEMEMFILE( ( AREAP ) pTempArea, &pInfo ); + strcat( szMemoName, pFileName->szPath ); + strcat( szMemoName, pFileName->szName ); + strcat( szMemoName, pFileExt->item.asString.value ); + pInfo.abName = ( BYTE * ) szMemoName; + bError = ( SELF_CREATEMEMFILE( ( AREAP ) pTempArea, &pInfo ) == FAILURE ); hb_itemRelease( pFileExt ); } SELF_RELEASE( ( AREAP ) pTempArea ); - hb_xfree( szFileName ); - hb_xfree( pFileName ); hb_xfree( pTempArea ); + hb_xfree( pFileName ); + + if( !bError && ISLOG( 4 ) ) + { + bNetError = FALSE; + if( hb_parl( 4 ) ) + hb_rddSelectFirstAvailable(); + else if( pCurrArea ) /* If current WorkArea is in use then close it */ + { + SELF_CLOSE( ( AREAP ) pCurrArea->pArea ); + SELF_RELEASE( ( AREAP ) pCurrArea->pArea ); + + if( pWorkAreas == pCurrArea ) /* Empty list */ + pWorkAreas = NULL; + else + { + if( pCurrArea->pPrev ) + pCurrArea->pPrev->pNext = pCurrArea->pNext; + if( pCurrArea->pNext ) + pCurrArea->pNext->pPrev = pCurrArea->pPrev; + } + + hb_xfree( pCurrArea->pArea ); + hb_xfree( pCurrArea ); + pCurrArea = NULL; + } + + szAlias = hb_parc( 5 ); + pCurrArea = ( LPAREANODE ) hb_xgrab( sizeof( AREANODE ) ); + pCurrArea->pArea = ( AREAP ) hb_xgrab( pRddNode->uiAreaSize ); + memset( pCurrArea->pArea, 0, pRddNode->uiAreaSize ); + ( ( AREAP ) pCurrArea->pArea )->lprfsHost = &pRddNode->pTable; + ( ( AREAP ) pCurrArea->pArea )->rddID = uiRddID; + + pCurrArea->pPrev = NULL; + pCurrArea->pNext = NULL; + + SELF_NEW( ( AREAP ) pCurrArea->pArea ); + + pInfo.uiArea = uiCurrArea; + pInfo.abName = ( BYTE * ) szFileName; + pInfo.atomAlias = ( BYTE * ) szAlias; + pInfo.fShared = !hb_set.HB_SET_EXCLUSIVE; + pInfo.fReadonly = FALSE; + + if( SELF_OPEN( ( AREAP ) pCurrArea->pArea, &pInfo ) == FAILURE ) + { + SELF_RELEASE( ( AREAP ) pCurrArea->pArea ); + hb_xfree( pCurrArea->pArea ); + hb_xfree( pCurrArea ); + hb_xfree( szFileName ); + hb_xfree( szMemoName ); + pCurrArea = NULL; + return; + } + + ( ( AREAP ) pCurrArea->pArea )->uiArea = uiCurrArea; + + /* Insert the new WorkArea node */ + + if( !pWorkAreas ) + pWorkAreas = pCurrArea; /* The new WorkArea node is the first */ + else + { + pAreaNode = pWorkAreas; + while( pAreaNode->pNext ) + { + if( ( ( AREAP ) pAreaNode->pArea )->uiArea > uiCurrArea ) + { + /* Insert the new WorkArea node */ + pCurrArea->pPrev = pAreaNode->pPrev; + pCurrArea->pNext = pAreaNode; + pAreaNode->pPrev = pCurrArea; + if( pCurrArea->pPrev ) + pCurrArea->pPrev->pNext = pCurrArea; + } + pAreaNode = pAreaNode->pNext; + } + pAreaNode->pNext = pCurrArea; /* Append the new WorkArea node */ + pCurrArea->pPrev = pAreaNode; + } + } + + hb_xfree( szFileName ); + hb_xfree( szMemoName ); } HARBOUR HB_DBDELETE( void ) @@ -1546,30 +1626,6 @@ HARBOUR HB_DBUSEAREA( void ) return; } - if( ( ( AREAP ) pCurrArea->pArea )->lpExtendInfo->fHasMemo ) - { - pFileExt = hb_itemPutC( NULL, "" ); - SELF_INFO( ( AREAP ) pCurrArea->pArea, DBI_MEMOEXT, pFileExt ); - szFileName[ 0 ] = '\0'; - if( pFileName->szPath ) - strcat( szFileName, pFileName->szPath ); - strcat( szFileName, pFileName->szName ); - strcat( szFileName, pFileExt->item.asString.value ); - pInfo.abName = ( BYTE * ) szFileName; - hb_itemRelease( pFileExt ); - if( SELF_OPENMEMFILE( ( AREAP ) pCurrArea->pArea, &pInfo ) == FAILURE ) - { - SELF_CLOSE( ( AREAP ) pCurrArea->pArea ); - SELF_RELEASE( ( AREAP ) pCurrArea->pArea ); - hb_xfree( pCurrArea->pArea ); - hb_xfree( pCurrArea ); - hb_xfree( szFileName ); - hb_xfree( pFileName ); - pCurrArea = NULL; - return; - } - } - hb_xfree( szFileName ); hb_xfree( pFileName ); ( ( AREAP ) pCurrArea->pArea )->uiArea = uiCurrArea; @@ -1577,24 +1633,23 @@ HARBOUR HB_DBUSEAREA( void ) /* Insert the new WorkArea node */ if( !pWorkAreas ) - { pWorkAreas = pCurrArea; /* The new WorkArea node is the first */ - return; - } - - pAreaNode = pWorkAreas; - while( pAreaNode->pNext ) + else { - if( ( ( AREAP ) pAreaNode->pArea )->uiArea > uiCurrArea ) + pAreaNode = pWorkAreas; + while( pAreaNode->pNext ) { - /* Insert the new WorkArea node */ - pCurrArea->pPrev = pAreaNode->pPrev; - pCurrArea->pNext = pAreaNode; - pAreaNode->pPrev = pCurrArea; - if( pCurrArea->pPrev ) - pCurrArea->pPrev->pNext = pCurrArea; + if( ( ( AREAP ) pAreaNode->pArea )->uiArea > uiCurrArea ) + { + /* Insert the new WorkArea node */ + pCurrArea->pPrev = pAreaNode->pPrev; + pCurrArea->pNext = pAreaNode; + pAreaNode->pPrev = pCurrArea; + if( pCurrArea->pPrev ) + pCurrArea->pPrev->pNext = pCurrArea; + } + pAreaNode = pAreaNode->pNext; } - pAreaNode = pAreaNode->pNext; } pAreaNode->pNext = pCurrArea; /* Append the new WorkArea node */ pCurrArea->pPrev = pAreaNode; @@ -1875,21 +1930,6 @@ HARBOUR HB_RDDSETDEFAULT( void ) } } -void hb_rddShutDown( void ) -{ - LPRDDNODE pRddNode; - - hb_rddCloseAll(); - if( szDefDriver ) - hb_xfree( szDefDriver ); - while( pRddList ) - { - pRddNode = pRddList; - pRddList = pRddList->pNext; - hb_xfree( pRddNode ); - } -} - HARBOUR HB_RECCOUNT( void ) { ULONG ulRecCount = 0; @@ -1982,3 +2022,4 @@ HARBOUR HB___RDDSETDEFAULT( void ) strcpy( szDefDriver, szNewDriver ); } } + diff --git a/harbour/source/rdd/dbf1.c b/harbour/source/rdd/dbf1.c index 62010fd5ad..d986e04fc5 100644 --- a/harbour/source/rdd/dbf1.c +++ b/harbour/source/rdd/dbf1.c @@ -46,7 +46,7 @@ #include "dates.h" #include "langapi.h" -typedef struct +typedef struct _DBFHEADER { BYTE bVersion; BYTE bYear; @@ -63,15 +63,7 @@ typedef struct typedef DBFHEADER * LPDBFHEADER; -typedef struct -{ - ULONG lNextBlock; -} MEMOHEADER; - -typedef MEMOHEADER * LPMEMOHEADER; - - -typedef struct +typedef struct _DBFFIELD { BYTE bName[ 11 ]; BYTE bType; @@ -85,6 +77,14 @@ typedef struct typedef DBFFIELD * LPDBFFIELD; +typedef struct +{ + ULONG lNextBlock; +} MEMOHEADER; + +typedef MEMOHEADER * LPMEMOHEADER; + + typedef struct _DBFMEMO { BOOL fChanged; /* Memo status */ @@ -106,9 +106,10 @@ HB_INIT_SYMBOLS_END( dbf1__InitSymbols ) #pragma startup dbf1__InitSymbols #endif -#define LOCK_START 0x40000000L -#define LOCK_FILE 0x3FFFFFFFL -#define MEMO_BLOCK 512 +#define LOCK_START 0x40000000L +#define LOCK_APPEND 0x7FFFFFFEL +#define LOCK_FILE 0x3FFFFFFFL +#define MEMO_BLOCK 512 static BOOL hb_nltoa( LONG lValue, char * szBuffer, USHORT uiLen ) @@ -219,6 +220,10 @@ static BOOL hb_dbfWriteMemo( AREAP pArea, LPDBFMEMO pMemo, ULONG * lNewRecNo ) BYTE szBuffer[ MEMO_BLOCK ]; MEMOHEADER pMemoHeader; + if( !pArea->lpExtendInfo->fExclusive && !pArea->lpFileInfo->fFileLocked && + !hb_fsLock( pArea->lpFileInfo->pNext->hFile, LOCK_APPEND - 1, 1, FL_LOCK ) ) + return FALSE; + uiNumBlocks = ( pMemo->uiLen + MEMO_BLOCK - 1 ) / MEMO_BLOCK; if( * lNewRecNo > 0 ) { @@ -229,7 +234,11 @@ static BOOL hb_dbfWriteMemo( AREAP pArea, LPDBFMEMO pMemo, ULONG * lNewRecNo ) uiBytesRead += MEMO_BLOCK; uiRead = hb_fsRead( pArea->lpFileInfo->pNext->hFile, szBuffer, MEMO_BLOCK ); if( !uiRead ) + { + if( !pArea->lpExtendInfo->fExclusive && !pArea->lpFileInfo->fFileLocked ) + hb_fsLock( pArea->lpFileInfo->pNext->hFile, LOCK_APPEND - 1, 1, FL_UNLOCK ); return FALSE; + } for( uiCount = 0; uiCount < uiRead; uiCount++ ) if( szBuffer[ uiCount ] == 0x1A ) break; @@ -253,21 +262,30 @@ static BOOL hb_dbfWriteMemo( AREAP pArea, LPDBFMEMO pMemo, ULONG * lNewRecNo ) hb_fsSeek( pArea->lpFileInfo->pNext->hFile, * lNewRecNo * MEMO_BLOCK, FS_SET ); if( hb_fsWrite( pArea->lpFileInfo->pNext->hFile, pMemo->pData, pMemo->uiLen ) != pMemo->uiLen ) + { + if( !pArea->lpExtendInfo->fExclusive && !pArea->lpFileInfo->fFileLocked ) + hb_fsLock( pArea->lpFileInfo->pNext->hFile, LOCK_APPEND - 1, 1, FL_UNLOCK ); return FALSE; + } szBuffer[ 0 ] = 0x1A; if( hb_fsWrite( pArea->lpFileInfo->pNext->hFile, szBuffer, 1 ) != 1 ) + { + if( !pArea->lpExtendInfo->fExclusive && !pArea->lpFileInfo->fFileLocked ) + hb_fsLock( pArea->lpFileInfo->pNext->hFile, LOCK_APPEND - 1, 1, FL_UNLOCK ); return FALSE; + } + if( !pArea->lpExtendInfo->fExclusive && !pArea->lpFileInfo->fFileLocked ) + hb_fsLock( pArea->lpFileInfo->pNext->hFile, LOCK_APPEND - 1, 1, FL_UNLOCK ); return TRUE; } static BOOL hb_dbfUpdateRecord( AREAP pArea, ULONG lRecNo ) { - ULONG lRecCount, lNewRecNo; - USHORT uiCount, uiOffset; + ULONG lRecCount; + USHORT uiCount; LPFIELD pField; - BYTE * szText, szEndChar; if( SELF_RECCOUNT( pArea, &lRecCount ) == FAILURE ) return FALSE; @@ -280,35 +298,12 @@ static BOOL hb_dbfUpdateRecord( AREAP pArea, ULONG lRecNo ) lRecCount = lRecNo; if( pArea->lpExtendInfo->fHasMemo ) { - uiOffset = 1; for( uiCount = 0; uiCount < pArea->uiFieldCount; uiCount++ ) { pField = pArea->lpFields + uiCount; - if( pField->uiType == 'C' ) - uiOffset += pField->uiLen + ( ( USHORT ) pField->uiDec << 8 ); - else - { - if( pField->uiType == 'M' && ( ( LPDBFMEMO ) pField->memo )->fChanged ) - { - szText = pArea->lpExtendInfo->bRecord + uiOffset; - if( !( ( LPDBFMEMO ) pField->memo )->pData ) - memset( szText, ' ', pField->uiLen ); - else - { - szEndChar = * ( szText + pField->uiLen ); - * ( szText + pField->uiLen ) = 0; - lRecNo = atol( ( char * ) szText ); - lNewRecNo = lRecNo; - if( !hb_dbfWriteMemo( pArea, ( LPDBFMEMO ) pField->memo, &lNewRecNo ) ) - return FALSE; - if( lNewRecNo != lRecNo ) - hb_nltoa( lNewRecNo, ( char * ) szText, pField->uiLen ); - * ( szText + pField->uiLen ) = szEndChar; - } - ( ( LPDBFMEMO ) pField->memo )->fChanged = FALSE; - } - uiOffset += pField->uiLen; - } + if( pField->uiType == 'M' && ( ( LPDBFMEMO ) pField->memo )->fChanged ) + if( SELF_GETVALUEFILE( pArea, uiCount + 1, NULL ) == FAILURE ) + return FALSE; } } if( hb_fsWrite( pArea->lpFileInfo->hFile, pArea->lpExtendInfo->bRecord, @@ -316,7 +311,6 @@ static BOOL hb_dbfUpdateRecord( AREAP pArea, ULONG lRecNo ) !hb_dbfUpdateHeader( pArea, lRecCount ) ) return FALSE; } - SELF_GOHOT( pArea ); return TRUE; } @@ -396,12 +390,9 @@ static void hb_dbfReadMemo( AREAP pArea, LPDBFMEMO pMemo, ULONG lMemoBlock ) static ERRCODE hb_dbfReadBuffer( AREAP pArea, ULONG lRecNo ) { LPFIELD pField; - USHORT uiCount, uiOffset; - BYTE * szText, szEndChar; - ULONG lMemoBlock; + USHORT uiCount; - if( pArea->lpExtendInfo->fRecordChanged && - !hb_dbfUpdateRecord( pArea, pArea->lpExtendInfo->lRecNo ) ) + if( SELF_GOCOLD( pArea ) == FAILURE ) return FAILURE; if( hb_fsSeek( pArea->lpFileInfo->hFile, pArea->lpExtendInfo->uiHeaderLen + @@ -419,34 +410,13 @@ static ERRCODE hb_dbfReadBuffer( AREAP pArea, ULONG lRecNo ) if( pArea->lpExtendInfo->fHasMemo && pArea->lpFileInfo->pNext ) { pField = pArea->lpFields; - uiOffset = 1; for( uiCount = 0; uiCount < pArea->uiFieldCount; uiCount++ ) { - if( pField->uiType == 'C' ) - uiOffset += pField->uiLen + ( ( USHORT ) pField->uiDec << 8 ); - else - { - if( pField->uiType == 'M' ) - { - szText = pArea->lpExtendInfo->bRecord + uiOffset; - szEndChar = * ( szText + pField->uiLen ); - * ( szText + pField->uiLen ) = 0; - lMemoBlock = atol( ( char * ) szText ) * MEMO_BLOCK; - * ( szText + pField->uiLen ) = szEndChar; - if( lMemoBlock > 0 ) - hb_dbfReadMemo( pArea, ( LPDBFMEMO ) pField->memo, lMemoBlock ); - else if( ( ( LPDBFMEMO ) pField->memo )->pData ) - { - hb_xfree( ( ( LPDBFMEMO ) pField->memo )->pData ); - memset( pField->memo, 0, sizeof( DBFMEMO ) ); - } - } - uiOffset += pField->uiLen; - } + if( pField->uiType == 'M' ) + SELF_PUTVALUEFILE( pArea, uiCount + 1, NULL ); pField = pField->lpfNext; } } - return SUCCESS; } @@ -476,7 +446,9 @@ static BOOL hb_dbfLockRecord( AREAP pArea, ULONG lRecNum ) if( hb_dbfIsLocked( pArea, lRecNum ) ) return TRUE; - if( !hb_fsLock( pArea->lpFileInfo->hFile, LOCK_START + lRecNum, 1, FL_LOCK ) ) + if( !hb_fsLock( pArea->lpFileInfo->hFile, LOCK_START + + pArea->lpExtendInfo->uiHeaderLen + + ( lRecNum - 1 ) * pArea->lpExtendInfo->uiRecordLen, 1, FL_LOCK ) ) return FALSE; if( pFileInfo->lNumLocksPos == 0 ) /* Create the list */ @@ -502,10 +474,6 @@ static BOOL hb_dbfUnLockRecord( AREAP pArea, ULONG lRecNum ) LPFILEINFO pFileInfo; ULONG lLockPos, * pList; - if( pArea->lpExtendInfo->fRecordChanged && - !hb_dbfUpdateRecord( pArea, lRecNum ) ) - return FALSE; - if( pArea->lpExtendInfo->fExclusive || pArea->lpFileInfo->fFileLocked ) return TRUE; @@ -513,7 +481,9 @@ static BOOL hb_dbfUnLockRecord( AREAP pArea, ULONG lRecNum ) if( !hb_dbfIsLocked( pArea, lRecNum ) ) return TRUE; - if( !hb_fsLock( pArea->lpFileInfo->hFile, LOCK_START + lRecNum, 1, FL_UNLOCK ) ) + if( !hb_fsLock( pArea->lpFileInfo->hFile, LOCK_START + + pArea->lpExtendInfo->uiHeaderLen + + ( lRecNum - 1 ) * pArea->lpExtendInfo->uiRecordLen, 1, FL_UNLOCK ) ) return FALSE; if( pFileInfo->lNumLocksPos == 1 ) /* Delete the list */ @@ -551,8 +521,7 @@ static BOOL hb_dbfUnLockAllRecords( AREAP pArea ) ULONG lPosLocked; BOOL bUnLocked = TRUE; - if( pArea->lpExtendInfo->fRecordChanged && - !hb_dbfUpdateRecord( pArea, pArea->lpExtendInfo->lRecNo ) ) + if( SELF_GOCOLD( pArea ) == FAILURE ) return FALSE; if( pArea->lpExtendInfo->fExclusive ) @@ -561,7 +530,9 @@ static BOOL hb_dbfUnLockAllRecords( AREAP pArea ) pFileInfo = pArea->lpFileInfo; for( lPosLocked = 0; lPosLocked < pFileInfo->lNumLocksPos; lPosLocked++ ) if( !hb_fsLock( pArea->lpFileInfo->hFile, LOCK_START + - pFileInfo->pLocksPos[ lPosLocked ], 1, FL_UNLOCK ) ) + pArea->lpExtendInfo->uiHeaderLen + + ( pFileInfo->pLocksPos[ lPosLocked ] - 1 ) * + pArea->lpExtendInfo->uiRecordLen, 1, FL_UNLOCK ) ) bUnLocked = FALSE; if( pFileInfo->lNumLocksPos > 1 ) @@ -585,8 +556,7 @@ static BOOL hb_dbfLockFile( AREAP pArea ) static BOOL hb_dbfUnLockFile( AREAP pArea ) { - if( pArea->lpExtendInfo->fRecordChanged && - !hb_dbfUpdateRecord( pArea, pArea->lpExtendInfo->lRecNo ) ) + if( SELF_GOCOLD( pArea ) == FAILURE ) return FALSE; if( pArea->lpExtendInfo->fExclusive ) @@ -618,7 +588,26 @@ static RDDFUNCS dbfSuper = { 0 }; * -- DBF METHODS -- */ -static ERRCODE AddField( AREAP pArea, LPDBFIELDINFO pFieldInfo ) +#define dbfBof NULL +#define dbfEof NULL +#define dbfFound NULL +#define dbfSkip NULL +#define dbfSkipFilter NULL +#define dbfCreateFields NULL +#define dbfFieldCount NULL +#define dbfFieldDisplay NULL +#define dbfFieldInfo NULL +#define dbfFieldName NULL +#define dbfGetRec NULL +#define dbfSetFieldsExtent NULL +#define dbfAlias NULL +#define dbfNewArea NULL +#define dbfStructSize NULL +#define dbfSysName NULL +#define dbfError NULL +#define dbfWhoCares NULL + +static ERRCODE dbfAddField( AREAP pArea, LPDBFIELDINFO pFieldInfo ) { LPFIELD pField; @@ -632,13 +621,24 @@ static ERRCODE AddField( AREAP pArea, LPDBFIELDINFO pFieldInfo ) } return SUCCESS; } - return FAILURE; } -static ERRCODE Append( AREAP pArea, BOOL bUnLockAll ) +static ERRCODE dbfAppend( AREAP pArea, BOOL bUnLockAll ) { ULONG lRecCount, lRecNo; + PHB_ITEM pError; + + if( pArea->lpExtendInfo->fReadOnly ) + { + pError = hb_errNew(); + hb_errPutGenCode( pError, EG_READONLY ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_READONLY ) ); + hb_errPutSubCode( pError, 1025 ); + SELF_ERROR( pArea, pError ); + hb_errRelease( pError ); + return FAILURE; + } if( SELF_RECCOUNT( pArea, &lRecCount ) == FAILURE ) return FAILURE; @@ -661,13 +661,15 @@ static ERRCODE Append( AREAP pArea, BOOL bUnLockAll ) pArea->lpFileInfo->fAppend = TRUE; if( !hb_dbfUpdateRecord( pArea, lRecNo ) ) { - hb_fsLock( pArea->lpFileInfo->hFile, LOCK_START, 1, FL_UNLOCK ); + if( !pArea->lpExtendInfo->fExclusive && !pArea->lpFileInfo->fFileLocked ) + hb_fsLock( pArea->lpFileInfo->hFile, LOCK_START, 1, FL_UNLOCK ); return FAILURE; } if( !hb_dbfLockRecord( pArea, lRecNo ) ) { - hb_fsLock( pArea->lpFileInfo->hFile, LOCK_START, 1, FL_UNLOCK ); + if( !pArea->lpExtendInfo->fExclusive && !pArea->lpFileInfo->fFileLocked ) + hb_fsLock( pArea->lpFileInfo->hFile, LOCK_START, 1, FL_UNLOCK ); return FAILURE; } @@ -678,10 +680,13 @@ static ERRCODE Append( AREAP pArea, BOOL bUnLockAll ) return SUCCESS; } -static ERRCODE Close( AREAP pArea ) +static ERRCODE dbfClose( AREAP pArea ) { if( pArea->lpFileInfo->hFile != FS_ERROR ) { + if( SELF_GOCOLD( pArea ) == FAILURE ) + return FAILURE; + SELF_RAWLOCK( pArea, FILE_UNLOCK, 0 ); SELF_FLUSH( pArea ); hb_fsClose( pArea->lpFileInfo->hFile ); @@ -693,7 +698,7 @@ static ERRCODE Close( AREAP pArea ) return SUPER_CLOSE( pArea ); } -static ERRCODE CloseMemFile( AREAP pArea ) +static ERRCODE dbfCloseMemFile( AREAP pArea ) { if( pArea->lpFileInfo->pNext->hFile != FS_ERROR ) { @@ -705,9 +710,32 @@ static ERRCODE CloseMemFile( AREAP pArea ) return SUCCESS; } -static ERRCODE Create( AREAP pArea, LPDBOPENINFO pCreateInfo ) +static ERRCODE dbfCreate( AREAP pArea, LPDBOPENINFO pCreateInfo ) { - pArea->lpFileInfo->hFile = hb_fsCreate( pCreateInfo->abName, FC_NORMAL ); + PHB_ITEM pError = NULL; + BOOL bRetry; + + do + { + pArea->lpFileInfo->hFile = hb_fsCreate( pCreateInfo->abName, FC_NORMAL ); + if( pArea->lpFileInfo->hFile == FS_ERROR ) + { + if( !pError ) + { + pError = hb_errNew(); + hb_errPutGenCode( pError, EG_CREATE ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_CREATE ) ); + hb_errPutFileName( pError, ( char * ) pCreateInfo->abName ); + hb_errPutFlags( pError, EF_CANRETRY ); + } + bRetry = ( SELF_ERROR( pArea, pError ) == E_RETRY ); + } + else + bRetry = FALSE; + } while( bRetry ); + if( pError ) + hb_errRelease( pError ); + if( pArea->lpFileInfo->hFile == FS_ERROR ) return FAILURE; @@ -723,25 +751,55 @@ static ERRCODE Create( AREAP pArea, LPDBOPENINFO pCreateInfo ) return SUCCESS; } -static ERRCODE CreateMemFile( AREAP pArea, LPDBOPENINFO pCreateInfo ) +static ERRCODE dbfCreateMemFile( AREAP pArea, LPDBOPENINFO pCreateInfo ) { LPFILEINFO lpMemInfo; LPMEMOHEADER pMemoHeader; BOOL bError; + PHB_ITEM pError = NULL; + BYTE * pBuffer; + + if( !pArea->lpFileInfo->pNext ) + { + lpMemInfo = ( LPFILEINFO ) hb_xgrab( sizeof( FILEINFO ) ); + memset( lpMemInfo, 0, sizeof( FILEINFO ) ); + lpMemInfo->hFile = FS_ERROR; + pArea->lpFileInfo->pNext = lpMemInfo; + } + else + lpMemInfo = pArea->lpFileInfo->pNext; + + do + { + lpMemInfo->hFile = hb_fsCreate( pCreateInfo->abName, FC_NORMAL ); + if( lpMemInfo->hFile == FS_ERROR ) + { + if( !pError ) + { + pError = hb_errNew(); + hb_errPutGenCode( pError, EG_CREATE ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_CREATE ) ); + hb_errPutFileName( pError, ( char * ) pCreateInfo->abName ); + hb_errPutFlags( pError, EF_CANRETRY ); + } + bError = ( SELF_ERROR( pArea, pError ) == E_RETRY ); + } + else + bError = FALSE; + } while( bError ); + if( pError ) + hb_errRelease( pError ); - lpMemInfo = ( LPFILEINFO ) hb_xgrab( sizeof( FILEINFO ) ); - memset( lpMemInfo, 0, sizeof( FILEINFO ) ); - lpMemInfo->hFile = FS_ERROR; - pArea->lpFileInfo->pNext = lpMemInfo; - lpMemInfo->hFile = hb_fsCreate( pCreateInfo->abName, FC_NORMAL ); if( lpMemInfo->hFile == FS_ERROR ) return FAILURE; pMemoHeader = ( LPMEMOHEADER ) hb_xgrab( MEMO_BLOCK + 1 ); memset( pMemoHeader, 0, MEMO_BLOCK + 1 ); pMemoHeader->lNextBlock = 1; + pBuffer = ( BYTE * ) pMemoHeader; + pBuffer[ MEMO_BLOCK ] = 0x1A; bError = ( hb_fsWrite( lpMemInfo->hFile, ( BYTE * ) pMemoHeader, - MEMO_BLOCK + 1 ) != MEMO_BLOCK + 1 ); + MEMO_BLOCK + 1 ) != MEMO_BLOCK + 1 ); hb_xfree( pMemoHeader ); hb_fsClose( lpMemInfo->hFile ); lpMemInfo->hFile = FS_ERROR; @@ -751,42 +809,33 @@ static ERRCODE CreateMemFile( AREAP pArea, LPDBOPENINFO pCreateInfo ) return SUCCESS; } -static ERRCODE Deleted( AREAP pArea, BOOL * pDeleted ) +static ERRCODE dbfDeleted( AREAP pArea, BOOL * pDeleted ) { * pDeleted = ( pArea->lpExtendInfo->bRecord[ 0 ] == '*' ); return SUCCESS; } -static ERRCODE DeleteRec( AREAP pArea ) +static ERRCODE dbfDeleteRec( AREAP pArea ) { - PHB_ITEM pError; - - if( SELF_GOCOLD( pArea ) == FAILURE ) + if( SELF_GOHOT( pArea ) == FAILURE ) return FAILURE; if( pArea->lpExtendInfo->bRecord[ 0 ] == '*' ) - return SUCCESS; - - if( !pArea->lpExtendInfo->fExclusive && !pArea->lpFileInfo->fFileLocked && - !hb_dbfIsLocked( pArea, pArea->lpExtendInfo->lRecNo ) ) { - pError = hb_errNew(); - hb_errPutGenCode( pError, EG_UNLOCKED ); - hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_UNLOCKED ) ); - hb_errPutSubCode( pError, 1022 ); - SELF_ERROR( pArea, pError ); - hb_errRelease( pError ); - return FAILURE; + pArea->lpExtendInfo->fRecordChanged = FALSE; + return SUCCESS; } pArea->lpExtendInfo->bRecord[ 0 ] = '*'; - pArea->lpExtendInfo->fRecordChanged = TRUE; return SUCCESS; } -static ERRCODE Flush( AREAP pArea ) +static ERRCODE dbfFlush( AREAP pArea ) { + if( SELF_GOCOLD( pArea ) == FAILURE ) + return FAILURE; + if( pArea->lpFileInfo->hFile != FS_ERROR ) hb_fsCommit( pArea->lpFileInfo->hFile ); if( pArea->lpExtendInfo->fHasMemo && pArea->lpFileInfo->pNext->hFile != FS_ERROR ) @@ -794,27 +843,16 @@ static ERRCODE Flush( AREAP pArea ) return FAILURE; } -static ERRCODE GetValue( AREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) +static ERRCODE dbfGetValue( AREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) { LPFIELD pField; - USHORT uiCount, uiOffset; BYTE * szText, szEndChar; if( uiIndex > pArea->uiFieldCount ) return FAILURE; - pField = pArea->lpFields; - uiOffset = 1; - for( uiCount = 1; uiCount < uiIndex; uiCount++ ) - { - if( pField->uiType == 'C' ) - uiOffset += pField->uiLen + ( ( USHORT ) pField->uiDec << 8 ); - else - uiOffset += pField->uiLen; - pField = pField->lpfNext; - } - - szText = pArea->lpExtendInfo->bRecord + uiOffset; + pField = pArea->lpFields + uiIndex - 1; + szText = pArea->lpExtendInfo->bRecord + pField->uiOffset; switch( pField->uiType ) { case 'C': @@ -854,32 +892,55 @@ static ERRCODE GetValue( AREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) hb_itemPutC( pItem, "" ); break; } - return SUCCESS; } -static ERRCODE GetVarLen( AREAP pArea, USHORT uiIndex, ULONG * ulLen ) +static ERRCODE dbfGetValueFile( AREAP pArea, USHORT uiIndex, void * pFile ) +{ + ULONG lRecNo, lNewRecNo; + BYTE * szText, szEndChar; + LPFIELD pField; + + HB_SYMBOL_UNUSED( pFile ); + if( uiIndex > pArea->uiFieldCount ) + return FAILURE; + + pField = pArea->lpFields + uiIndex - 1; + szText = pArea->lpExtendInfo->bRecord + pField->uiOffset; + if( !( ( LPDBFMEMO ) pField->memo )->pData ) + memset( szText, ' ', pField->uiLen ); + else + { + szEndChar = * ( szText + pField->uiLen ); + * ( szText + pField->uiLen ) = 0; + lRecNo = atol( ( char * ) szText ); + lNewRecNo = lRecNo; + if( !hb_dbfWriteMemo( pArea, ( LPDBFMEMO ) pField->memo, &lNewRecNo ) ) + return FAILURE; + if( lNewRecNo != lRecNo ) + hb_nltoa( lNewRecNo, ( char * ) szText, pField->uiLen ); + * ( szText + pField->uiLen ) = szEndChar; + } + ( ( LPDBFMEMO ) pField->memo )->fChanged = FALSE; + return SUCCESS; +} + +static ERRCODE dbfGetVarLen( AREAP pArea, USHORT uiIndex, ULONG * ulLen ) { LPFIELD pField; - pField = pArea->lpFields; - while( pField && uiIndex > 1 ) - { - pField = pField->lpfNext; - uiIndex--; - } - if( pField ) - { - if( pField->uiType == 'M' ) - * ulLen = ( ( LPDBFMEMO ) pField->memo )->uiLen; - else - * ulLen = pField->uiLen; - return SUCCESS; - } - return FAILURE; + if( uiIndex > pArea->uiFieldCount ) + return FAILURE; + + pField = pArea->lpFields + uiIndex - 1; + if( pField->uiType == 'M' ) + * ulLen = ( ( LPDBFMEMO ) pField->memo )->uiLen; + else + * ulLen = pField->uiLen; + return SUCCESS; } -static ERRCODE GoBottom( AREAP pArea ) +static ERRCODE dbfGoBottom( AREAP pArea ) { ULONG lRecCount; @@ -889,12 +950,52 @@ static ERRCODE GoBottom( AREAP pArea ) return SELF_GOTO( pArea, lRecCount ); } -static ERRCODE GoTo( AREAP pArea, ULONG lRecNo ) +static ERRCODE dbfGoCold( AREAP pArea ) +{ + if( pArea->lpExtendInfo->fRecordChanged && + !hb_dbfUpdateRecord( pArea, pArea->lpExtendInfo->lRecNo ) ) + return FAILURE; + + pArea->lpExtendInfo->fRecordChanged = FALSE; + pArea->lpFileInfo->fAppend = FALSE; + return SUCCESS; +} + +static ERRCODE dbfGoHot( AREAP pArea ) +{ + PHB_ITEM pError; + + if( !pArea->lpExtendInfo->fExclusive && !pArea->lpFileInfo->fFileLocked && + !hb_dbfIsLocked( pArea, pArea->lpExtendInfo->lRecNo ) ) + { + pError = hb_errNew(); + hb_errPutGenCode( pError, EG_UNLOCKED ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_UNLOCKED ) ); + hb_errPutSubCode( pError, 1022 ); + SELF_ERROR( pArea, pError ); + hb_errRelease( pError ); + return FAILURE; + } + + if( pArea->lpExtendInfo->fReadOnly ) + { + pError = hb_errNew(); + hb_errPutGenCode( pError, EG_READONLY ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_READONLY ) ); + hb_errPutSubCode( pError, 1025 ); + SELF_ERROR( pArea, pError ); + hb_errRelease( pError ); + return FAILURE; + } + pArea->lpExtendInfo->fRecordChanged = TRUE; + return SUCCESS; +} + +static ERRCODE dbfGoTo( AREAP pArea, ULONG lRecNo ) { ULONG lRecCount; - if( pArea->lpExtendInfo->fRecordChanged && - !hb_dbfUpdateRecord(pArea, pArea->lpExtendInfo->lRecNo ) ) + if( SELF_GOCOLD( pArea ) == FAILURE ) return FAILURE; if( SELF_RECCOUNT( pArea, &lRecCount ) == FAILURE ) @@ -924,7 +1025,7 @@ static ERRCODE GoTo( AREAP pArea, ULONG lRecNo ) return SUCCESS; } -static ERRCODE GoToId( AREAP pArea, PHB_ITEM pItem ) +static ERRCODE dbfGoToId( AREAP pArea, PHB_ITEM pItem ) { PHB_ITEM pError; ULONG lRecNo; @@ -948,15 +1049,20 @@ static ERRCODE GoToId( AREAP pArea, PHB_ITEM pItem ) } } -static ERRCODE GoTop( AREAP pArea ) +static ERRCODE dbfGoTop( AREAP pArea ) { return SELF_GOTO( pArea, 1 ); } -static ERRCODE Info( AREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) +static ERRCODE dbfInfo( AREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) { switch( uiIndex ) { + case DBI_ISDBF: + case DBI_CANPUTREC: + hb_itemPutL( pItem, TRUE ); + break; + case DBI_TABLEEXT: hb_itemPutC( pItem, ".DBF" ); break; @@ -988,7 +1094,7 @@ static ERRCODE Info( AREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) return SUCCESS; } -static ERRCODE Lock( AREAP pArea, LPDBLOCKINFO pLockInfo ) +static ERRCODE dbfLock( AREAP pArea, LPDBLOCKINFO pLockInfo ) { if( pLockInfo->itmRecID == 0 ) { @@ -1005,16 +1111,40 @@ static ERRCODE Lock( AREAP pArea, LPDBLOCKINFO pLockInfo ) return SUCCESS; } -static ERRCODE Open( AREAP pArea, LPDBOPENINFO pOpenInfo ) +static ERRCODE dbfOpen( AREAP pArea, LPDBOPENINFO pOpenInfo ) { USHORT uiFlags; + PHB_ITEM pFileExt; + char * szFileName; + PHB_FNAME pFileName; + PHB_ITEM pError = NULL; + BOOL bRetry; if( SUPER_OPEN( pArea, pOpenInfo ) == FAILURE ) return FAILURE; uiFlags = pOpenInfo->fReadonly ? FO_READ : FO_READWRITE; uiFlags |= pOpenInfo->fShared ? FO_DENYNONE : FO_EXCLUSIVE; - pArea->lpFileInfo->hFile = hb_fsOpen( pOpenInfo->abName, uiFlags ); + do + { + pArea->lpFileInfo->hFile = hb_fsOpen( pOpenInfo->abName, uiFlags ); + if( pArea->lpFileInfo->hFile == FS_ERROR ) + { + if( !pError ) + { + pError = hb_errNew(); + hb_errPutGenCode( pError, EG_OPEN ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_OPEN ) ); + hb_errPutFileName( pError, ( char * ) pOpenInfo->abName ); + hb_errPutFlags( pError, EF_CANRETRY ); + } + bRetry = ( SELF_ERROR( pArea, pError ) == E_RETRY ); + } + else + bRetry = FALSE; + } while( bRetry ); + if( pError ) + hb_errRelease( pError ); if( pArea->lpFileInfo->hFile == FS_ERROR ) { @@ -1027,25 +1157,73 @@ static ERRCODE Open( AREAP pArea, LPDBOPENINFO pOpenInfo ) SELF_CLOSE( pArea ); return FAILURE; } - pArea->lpExtendInfo->fExclusive = !pOpenInfo->fShared; + + if( pArea->lpExtendInfo->fHasMemo ) + { + pFileName = hb_fsFNameSplit( ( char * ) pOpenInfo->abName ); + pFileExt = hb_itemPutC( NULL, "" ); + SELF_INFO( pArea, DBI_MEMOEXT, pFileExt ); + szFileName = ( char * ) hb_xgrab( _POSIX_PATH_MAX + 3 ); + szFileName[ 0 ] = '\0'; + if( pFileName->szPath ) + strcat( szFileName, pFileName->szPath ); + strcat( szFileName, pFileName->szName ); + strcat( szFileName, pFileExt->item.asString.value ); + pOpenInfo->abName = ( BYTE * ) szFileName; + hb_itemRelease( pFileExt ); + hb_xfree( pFileName ); + if( SELF_OPENMEMFILE( pArea, pOpenInfo ) == FAILURE ) + { + SELF_CLOSE( pArea ); + hb_xfree( szFileName ); + return FAILURE; + } + hb_xfree( szFileName ); + } return SELF_GOTOP( pArea ); } -static ERRCODE OpenMemFile( AREAP pArea, LPDBOPENINFO pOpenInfo ) +static ERRCODE dbfOpenMemFile( AREAP pArea, LPDBOPENINFO pOpenInfo ) { LPFILEINFO lpMemInfo; LPMEMOHEADER pMemoHeader; USHORT uiFlags; + PHB_ITEM pError = NULL; + BOOL bRetry; - lpMemInfo = ( LPFILEINFO ) hb_xgrab( sizeof( FILEINFO ) ); - memset( lpMemInfo, 0, sizeof( FILEINFO ) ); - lpMemInfo->hFile = FS_ERROR; - pArea->lpFileInfo->pNext = lpMemInfo; + if( !pArea->lpFileInfo->pNext ) + { + lpMemInfo = ( LPFILEINFO ) hb_xgrab( sizeof( FILEINFO ) ); + memset( lpMemInfo, 0, sizeof( FILEINFO ) ); + lpMemInfo->hFile = FS_ERROR; + pArea->lpFileInfo->pNext = lpMemInfo; + } + else + lpMemInfo = pArea->lpFileInfo->pNext; uiFlags = pOpenInfo->fReadonly ? FO_READ : FO_READWRITE; uiFlags |= pOpenInfo->fShared ? FO_DENYNONE : FO_EXCLUSIVE; - lpMemInfo->hFile = hb_fsOpen( pOpenInfo->abName, uiFlags ); + do + { + lpMemInfo->hFile = hb_fsOpen( pOpenInfo->abName, uiFlags ); + if( lpMemInfo->hFile == FS_ERROR ) + { + if( !pError ) + { + pError = hb_errNew(); + hb_errPutGenCode( pError, EG_OPEN ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_OPEN ) ); + hb_errPutFileName( pError, ( char * ) pOpenInfo->abName ); + hb_errPutFlags( pError, EF_CANRETRY ); + } + bRetry = ( SELF_ERROR( pArea, pError ) == E_RETRY ); + } + else + bRetry = FALSE; + } while( bRetry ); + if( pError ) + hb_errRelease( pError ); if( lpMemInfo->hFile == FS_ERROR ) return FAILURE; @@ -1059,38 +1237,22 @@ static ERRCODE OpenMemFile( AREAP pArea, LPDBOPENINFO pOpenInfo ) } pArea->lpExtendInfo->lNextBlock = pMemoHeader->lNextBlock; hb_xfree( pMemoHeader ); - - return SELF_GOTOP( pArea ); -} - -static ERRCODE PutRec( AREAP pArea, BYTE * pBuffer ) -{ - PHB_ITEM pError; - - if( SELF_GOCOLD( pArea ) == FAILURE ) - return FAILURE; - - if( !pArea->lpExtendInfo->fExclusive && !pArea->lpFileInfo->fFileLocked && - !hb_dbfIsLocked( pArea, pArea->lpExtendInfo->lRecNo ) ) - { - pError = hb_errNew(); - hb_errPutGenCode( pError, EG_UNLOCKED ); - hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_UNLOCKED ) ); - hb_errPutSubCode( pError, 1022 ); - SELF_ERROR( pArea, pError ); - hb_errRelease( pError ); - return FAILURE; - } - - memcpy( pArea->lpExtendInfo->bRecord, pBuffer, pArea->lpExtendInfo->uiRecordLen ); - pArea->lpExtendInfo->fRecordChanged = TRUE; return SUCCESS; } -static ERRCODE PutValue( AREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) +static ERRCODE dbfPutRec( AREAP pArea, BYTE * pBuffer ) +{ + if( SELF_GOHOT( pArea ) == FAILURE ) + return FAILURE; + + memcpy( pArea->lpExtendInfo->bRecord, pBuffer, pArea->lpExtendInfo->uiRecordLen ); + return SUCCESS; +} + +static ERRCODE dbfPutValue( AREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) { LPFIELD pField; - USHORT uiCount, uiOffset; + USHORT uiCount; BYTE * szText, szEndChar; BOOL bError; long lDay, lMonth, lYear; @@ -1099,33 +1261,11 @@ static ERRCODE PutValue( AREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) if( uiIndex > pArea->uiFieldCount ) return FAILURE; - if( SELF_GOCOLD( pArea ) == FAILURE ) + if( SELF_GOHOT( pArea ) == FAILURE ) return FAILURE; - if( !pArea->lpExtendInfo->fExclusive && !pArea->lpFileInfo->fFileLocked && - !hb_dbfIsLocked( pArea, pArea->lpExtendInfo->lRecNo ) ) - { - pError = hb_errNew(); - hb_errPutGenCode( pError, EG_UNLOCKED ); - hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_UNLOCKED ) ); - hb_errPutSubCode( pError, 1022 ); - SELF_ERROR( pArea, pError ); - hb_errRelease( pError ); - return FAILURE; - } - - pField = pArea->lpFields; - uiOffset = 1; - for( uiCount = 1; uiCount < uiIndex; uiCount++ ) - { - if( pField->uiType == 'C' ) - uiOffset += pField->uiLen + ( ( USHORT ) pField->uiDec << 8 ); - else - uiOffset += pField->uiLen; - pField = pField->lpfNext; - } - - szText = pArea->lpExtendInfo->bRecord + uiOffset; + pField = pArea->lpFields + uiIndex - 1; + szText = pArea->lpExtendInfo->bRecord + pField->uiOffset; bError = TRUE; switch( pField->uiType ) { @@ -1192,8 +1332,12 @@ static ERRCODE PutValue( AREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) if( ( ( LPDBFMEMO ) pField->memo )->uiLen < uiCount ) { if( ( ( LPDBFMEMO ) pField->memo )->pData ) - hb_xfree( ( ( LPDBFMEMO ) pField->memo )->pData ); - ( ( LPDBFMEMO ) pField->memo )->pData = ( BYTE * ) hb_xgrab( uiCount + 1 ); + ( ( LPDBFMEMO ) pField->memo )->pData = + ( BYTE * ) hb_xrealloc( ( ( LPDBFMEMO ) pField->memo )->pData, + uiCount + 1 ); + else + ( ( LPDBFMEMO ) pField->memo )->pData = + ( BYTE * ) hb_xgrab( uiCount + 1 ); } ( ( LPDBFMEMO ) pField->memo )->uiLen = uiCount; if( uiCount > 0 ) @@ -1223,16 +1367,47 @@ static ERRCODE PutValue( AREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) hb_errPutSubCode( pError, 1020 ); SELF_ERROR( pArea, pError ); hb_errRelease( pError ); + pArea->lpExtendInfo->fRecordChanged = FALSE; return FAILURE; } pArea->lpExtendInfo->fRecordChanged = TRUE; return SUCCESS; } -static ERRCODE RawLock( AREAP pArea, USHORT uiAction, ULONG lRecNo ) +static ERRCODE dbfPutValueFile( AREAP pArea, USHORT uiIndex, void * pFile ) +{ + LPFIELD pField; + BYTE * szText, szEndChar; + ULONG lMemoBlock; + + HB_SYMBOL_UNUSED( pFile ); + + if( uiIndex > pArea->uiFieldCount ) + return FAILURE; + + pField = pArea->lpFields + uiIndex - 1;; + szText = pArea->lpExtendInfo->bRecord + pField->uiOffset; + szEndChar = * ( szText + pField->uiLen ); + * ( szText + pField->uiLen ) = 0; + lMemoBlock = atol( ( char * ) szText ) * MEMO_BLOCK; + * ( szText + pField->uiLen ) = szEndChar; + if( lMemoBlock > 0 ) + hb_dbfReadMemo( pArea, ( LPDBFMEMO ) pField->memo, lMemoBlock ); + else if( ( ( LPDBFMEMO ) pField->memo )->pData ) + { + hb_xfree( ( ( LPDBFMEMO ) pField->memo )->pData ); + memset( pField->memo, 0, sizeof( DBFMEMO ) ); + } + return SUCCESS; +} + +static ERRCODE dbfRawLock( AREAP pArea, USHORT uiAction, ULONG lRecNo ) { HB_SYMBOL_UNUSED( lRecNo ); + if( SELF_GOCOLD( pArea ) == FAILURE ) + return FAILURE; + switch( uiAction ) { case REC_LOCK: @@ -1258,7 +1433,7 @@ static ERRCODE RawLock( AREAP pArea, USHORT uiAction, ULONG lRecNo ) return SUCCESS; } -static ERRCODE ReadDBHeader( AREAP pArea ) +static ERRCODE dbfReadDBHeader( AREAP pArea ) { DBFHEADER pHeader; DBFIELDINFO pFieldInfo; @@ -1337,34 +1512,22 @@ static ERRCODE ReadDBHeader( AREAP pArea ) return SUCCESS; } -static ERRCODE RecAll( AREAP pArea ) +static ERRCODE dbfRecAll( AREAP pArea ) { - PHB_ITEM pError; - - if( SELF_GOCOLD( pArea ) == FAILURE ) + if( SELF_GOHOT( pArea ) == FAILURE ) return FAILURE; if( pArea->lpExtendInfo->bRecord[ 0 ] != '*' ) - return SUCCESS; - - if( !pArea->lpExtendInfo->fExclusive && !pArea->lpFileInfo->fFileLocked && - !hb_dbfIsLocked( pArea, pArea->lpExtendInfo->lRecNo ) ) { - pError = hb_errNew(); - hb_errPutGenCode( pError, EG_UNLOCKED ); - hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_UNLOCKED ) ); - hb_errPutSubCode( pError, 1022 ); - SELF_ERROR( pArea, pError ); - hb_errRelease( pError ); - return FAILURE; + pArea->lpExtendInfo->fRecordChanged = FALSE; + return SUCCESS; } pArea->lpExtendInfo->bRecord[ 0 ] = ' '; - pArea->lpExtendInfo->fRecordChanged = TRUE; return SUCCESS; } -static ERRCODE RecCount( AREAP pArea, ULONG * pRecCount ) +static ERRCODE dbfRecCount( AREAP pArea, ULONG * pRecCount ) { DBFHEADER pHeader; @@ -1376,7 +1539,7 @@ static ERRCODE RecCount( AREAP pArea, ULONG * pRecCount ) return SUCCESS; } -static ERRCODE RecInfo( AREAP pArea, PHB_ITEM pRecNo, USHORT uiType, PHB_ITEM pItem ) +static ERRCODE dbfRecInfo( AREAP pArea, PHB_ITEM pRecNo, USHORT uiType, PHB_ITEM pItem ) { ULONG lRecNo; @@ -1410,13 +1573,13 @@ static ERRCODE RecInfo( AREAP pArea, PHB_ITEM pRecNo, USHORT uiType, PHB_ITEM pI return SUCCESS; } -static ERRCODE RecNo( AREAP pArea, PHB_ITEM pRecNo ) +static ERRCODE dbfRecNo( AREAP pArea, PHB_ITEM pRecNo ) { hb_itemPutNL( pRecNo, pArea->lpExtendInfo->lRecNo ); return SUCCESS; } -static ERRCODE Release( AREAP pArea ) +static ERRCODE dbfRelease( AREAP pArea ) { USHORT uiCount; LPFIELD pField; @@ -1437,7 +1600,7 @@ static ERRCODE Release( AREAP pArea ) return SUPER_RELEASE( pArea ); } -static ERRCODE SkipRaw( AREAP pArea, LONG lToSkip ) +static ERRCODE dbfSkipRaw( AREAP pArea, LONG lToSkip ) { LONG lRecNo = pArea->lpExtendInfo->lRecNo + lToSkip; @@ -1452,7 +1615,7 @@ static ERRCODE SkipRaw( AREAP pArea, LONG lToSkip ) return SELF_GOTO( pArea, lRecNo ); } -static ERRCODE UnLock( AREAP pArea, ULONG lRecNo ) +static ERRCODE dbfUnLock( AREAP pArea, ULONG lRecNo ) { if( lRecNo == 0 ) hb_dbfUnLockAllRecords( pArea ); @@ -1461,7 +1624,7 @@ static ERRCODE UnLock( AREAP pArea, ULONG lRecNo ) return SUCCESS; } -static ERRCODE WriteDBHeader( AREAP pArea ) +static ERRCODE dbfWriteDBHeader( AREAP pArea ) { DBFHEADER pHeader; DBFFIELD pDBField; @@ -1556,57 +1719,59 @@ static ERRCODE WriteDBHeader( AREAP pArea ) return SUCCESS; } -static RDDFUNCS dbfTable = { 0, /* Super Bof */ - 0, /* Super Eof */ - 0, /* Super Found */ - GoBottom, - GoTo, - GoToId, - GoTop, - 0, /* Super Skip */ - 0, /* Super SkipFilter */ - SkipRaw, - AddField, - Append, - 0, /* Super CreateFields */ - DeleteRec, - Deleted, - 0, /* Super FieldCount */ - 0, /* Super FieldDisplay */ - 0, /* Super FieldInfo */ - 0, /* Super FieldName */ - Flush, - 0, /* Super GetRec */ - GetValue, - GetVarLen, - 0, /* Super GoCold */ - 0, /* Super GoHot */ - PutRec, - PutValue, - RecAll, - RecCount, - RecInfo, - RecNo, - 0, /* Super SetFieldsExtent */ - 0, /* Super Alias */ - Close, - Create, - Info, - 0, /* Super NewArea */ - Open, - Release, - 0, /* Super StructSize */ - 0, /* Super SysName */ - 0, /* Super Error */ - RawLock, - Lock, - UnLock, - CloseMemFile, - CreateMemFile, - OpenMemFile, - ReadDBHeader, - WriteDBHeader, - 0 /* Super WhoCares */ +static RDDFUNCS dbfTable = { dbfBof, + dbfEof, + dbfFound, + dbfGoBottom, + dbfGoTo, + dbfGoToId, + dbfGoTop, + dbfSkip, + dbfSkipFilter, + dbfSkipRaw, + dbfAddField, + dbfAppend, + dbfCreateFields, + dbfDeleteRec, + dbfDeleted, + dbfFieldCount, + dbfFieldDisplay, + dbfFieldInfo, + dbfFieldName, + dbfFlush, + dbfGetRec, + dbfGetValue, + dbfGetVarLen, + dbfGoCold, + dbfGoHot, + dbfPutRec, + dbfPutValue, + dbfRecAll, + dbfRecCount, + dbfRecInfo, + dbfRecNo, + dbfSetFieldsExtent, + dbfAlias, + dbfClose, + dbfCreate, + dbfInfo, + dbfNewArea, + dbfOpen, + dbfRelease, + dbfStructSize, + dbfSysName, + dbfError, + dbfRawLock, + dbfLock, + dbfUnLock, + dbfCloseMemFile, + dbfCreateMemFile, + dbfGetValueFile, + dbfOpenMemFile, + dbfPutValueFile, + dbfReadDBHeader, + dbfWriteDBHeader, + dbfWhoCares }; HARBOUR HB__DBFC( void ) @@ -1626,3 +1791,4 @@ HARBOUR HB_DBF_GETFUNCTABLE( void ) else hb_retni( FAILURE ); } + diff --git a/harbour/source/rdd/dbfcdx/dbfcdx0.prg b/harbour/source/rdd/dbfcdx/dbfcdx0.prg new file mode 100644 index 0000000000..df69949f37 --- /dev/null +++ b/harbour/source/rdd/dbfcdx/dbfcdx0.prg @@ -0,0 +1,63 @@ +/* + * $Id$ + */ + +/* + * Harbour Project source code: + * DBFCDX RDD + * + * Copyright 1999 Bruno Cantero + * www - http://www.harbour-project.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version, with one exception: + * + * The exception is that if you link the Harbour Runtime Library (HRL) + * and/or the Harbour Virtual Machine (HVM) with other files to produce + * an executable, this does not by itself cause the resulting executable + * to be covered by the GNU General Public License. Your use of that + * executable is in no way restricted on account of linking the HRL + * and/or HVM code into it. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA (or visit + * their web site at http://www.gnu.org/). + * + */ + +#include "error.ch" +#include "rddsys.ch" + +ANNOUNCE DBFCDX + +init procedure DBFCDXInit + + REQUEST _DBFCDX + + rddRegister( "DBF", RDT_FULL ) + rddRegister( "DBFCDX", RDT_FULL ) + +return + +init procedure InitHandler + + local bOldError := ErrorBlock( { | oError | LockErrHandler( oError, bOldError ) } ) + +return + +static function LockErrHandler( oError, bOldError ) + + if oError:gencode() == EG_LOCK + return .T. + endif + +return Eval( bOldError, oError ) + diff --git a/harbour/source/rdd/dbfcdx/dbfcdx1.c b/harbour/source/rdd/dbfcdx/dbfcdx1.c new file mode 100644 index 0000000000..cd36ffe3d2 --- /dev/null +++ b/harbour/source/rdd/dbfcdx/dbfcdx1.c @@ -0,0 +1,650 @@ +/* + * $Id$ + */ + +/* + * Harbour Project source code: + * DBFCDX RDD + * + * Copyright 1999 Bruno Cantero + * www - http://www.harbour-project.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version, with one exception: + * + * The exception is that if you link the Harbour Runtime Library (HRL) + * and/or the Harbour Virtual Machine (HVM) with other files to produce + * an executable, this does not by itself cause the resulting executable + * to be covered by the GNU General Public License. Your use of that + * executable is in no way restricted on account of linking the HRL + * and/or HVM code into it. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA (or visit + * their web site at http://www.gnu.org/). + * + */ + +#define SUPERTABLE ( &cdxSuper ) + +#include +#include "extend.h" +#include "init.h" +#include "itemapi.h" +#include "rddapi.h" +#include "rddsys.ch" +#include "errorapi.h" +#include "langapi.h" + + +typedef struct _DBFHEADER +{ + BYTE bVersion; + BYTE bYear; + BYTE bMonth; + BYTE bDay; + ULONG ulRecords; + USHORT uiHeaderLen; + USHORT uiRecordLen; + BYTE bReserved1[ 16 ]; + BYTE bHasTag; + BYTE bReserved2[ 3 ]; +} DBFHEADER; + +typedef DBFHEADER * LPDBFHEADER; + + +typedef struct _DBFFIELD +{ + BYTE bName[ 11 ]; + BYTE bType; + BYTE bReserved1[ 4 ]; + BYTE bLen; + BYTE bDec; + BYTE bReserved2[ 13 ]; + BYTE bHasTag; +} DBFFIELD; + +typedef DBFFIELD * LPDBFFIELD; + + +typedef struct +{ + ULONG lNextBlock; + ULONG lBlockSize; +} MEMOHEADER; + +typedef MEMOHEADER * LPMEMOHEADER; + + +typedef struct _DBFMEMO +{ + BOOL fChanged; /* Memo status */ + BYTE * pData; /* Memo data */ + USHORT uiLen; /* Len of data */ +} DBFMEMO; + +typedef DBFMEMO * LPDBFMEMO; + + +HARBOUR HB__DBFCDX( void ); +HARBOUR HB_DBFCDX_GETFUNCTABLE( void ); + +HB_INIT_SYMBOLS_BEGIN( dbfcdx1__InitSymbols ) +{ "_DBFCDX", FS_PUBLIC, HB__DBFCDX, 0 }, +{ "DBFCDX_GETFUNCTABLE", FS_PUBLIC, HB_DBFCDX_GETFUNCTABLE, 0 } +HB_INIT_SYMBOLS_END( dbfcdx1__InitSymbols ) +#if ! defined(__GNUC__) +#pragma startup dbfcdx1__InitSymbols +#endif + +#define LOCK_START 0x40000000L +#define LOCK_APPEND 0x7FFFFFFEL +#define LOCK_FILE 0x3FFFFFFFL +#define MEMO_BLOCK 64 + +static RDDFUNCS cdxSuper = { 0 }; + +static BOOL hb_nltoa( LONG lValue, char * szBuffer, USHORT uiLen ) +{ + LONG lAbsNumber; + int iCount, iPos; + + lAbsNumber = ( lValue > 0 ) ? lValue : - lValue; + iCount = iPos = uiLen; + while( iCount-- > 0 ) + { + szBuffer[ iCount ] = ( '0' + lAbsNumber % 10 ); + lAbsNumber /= 10; + } + + if( lAbsNumber > 0 ) + { + memset( szBuffer, ' ', uiLen ); + return FALSE; + } + + uiLen--; + for( iCount = 0; iCount < uiLen; iCount++ ) + if( szBuffer[ iCount ] == '0' ) + szBuffer[ iCount ] = ' '; + else + break; + + if( lValue < 0 ) + { + if( szBuffer[ 0 ] != ' ' ) + { + memset( szBuffer, ' ', iPos ); + return FALSE; + } + for( iCount = uiLen; iCount >= 0; iCount-- ) + { + if( szBuffer[ iCount ] == ' ' ) + { + szBuffer[ iCount ] = '-'; + break; + } + } + } + return TRUE; +} + +static ULONG hb_cdxSwapBytes( ULONG ulValue ) +{ + BYTE * pValue, pByte; + + pValue = ( BYTE * ) &ulValue; + pByte = pValue[ 0 ]; + pValue[ 0 ] = pValue[ 3 ]; + pValue[ 3 ] = pByte; + pByte = pValue[ 1 ]; + pValue[ 1 ] = pValue[ 2 ]; + pValue[ 2 ] = pByte; + return ulValue; +} + +static void hb_cdxReadMemo( AREAP pArea, LPDBFMEMO pMemo, ULONG lMemoBlock ) +{ + ULONG ulSpaceUsed; + MEMOHEADER pMemoHeader; + + hb_fsSeek( pArea->lpFileInfo->pNext->hFile, lMemoBlock * MEMO_BLOCK, FS_SET ); + hb_fsRead( pArea->lpFileInfo->pNext->hFile, ( BYTE * ) &pMemoHeader, + sizeof( MEMOHEADER ) ); + ulSpaceUsed = hb_cdxSwapBytes( pMemoHeader.lBlockSize ); + if( pMemo->uiLen != ulSpaceUsed ) + { + if( pMemo->uiLen > 0 ) + pMemo->pData = ( BYTE * ) hb_xrealloc( pMemo->pData, ulSpaceUsed + 1 ); + else + pMemo->pData = ( BYTE * ) hb_xgrab( ulSpaceUsed + 1 ); + pMemo->uiLen = ulSpaceUsed; + } + hb_fsRead( pArea->lpFileInfo->pNext->hFile, pMemo->pData, pMemo->uiLen ); +} + +static BOOL hb_cdxWriteMemo( AREAP pArea, LPDBFMEMO pMemo, ULONG * lNewRecNo ) +{ + USHORT uiNumBlocks; + MEMOHEADER pMemoHeader; + BYTE * pBuffer; + + if( !pArea->lpExtendInfo->fExclusive && !pArea->lpFileInfo->fFileLocked && + !hb_fsLock( pArea->lpFileInfo->pNext->hFile, LOCK_APPEND - 1, 1, FL_LOCK ) ) + return FALSE; + + uiNumBlocks = 1 + ( pMemo->uiLen + sizeof( MEMOHEADER ) ) / MEMO_BLOCK; + if( * lNewRecNo > 0 ) + { + hb_fsSeek( pArea->lpFileInfo->pNext->hFile, * lNewRecNo * MEMO_BLOCK, FS_SET ); + hb_fsRead( pArea->lpFileInfo->pNext->hFile, ( BYTE * ) &pMemoHeader, + sizeof( MEMOHEADER ) ); + if( pMemo->uiLen > hb_cdxSwapBytes( pMemoHeader.lBlockSize ) ) + * lNewRecNo = 0; /* Not room for data */ + } + + if( * lNewRecNo == 0 ) /* Add an entry at eof */ + { + hb_fsSeek( pArea->lpFileInfo->pNext->hFile, 0, FS_SET ); + hb_fsRead( pArea->lpFileInfo->pNext->hFile, ( BYTE * ) &pMemoHeader, + sizeof( MEMOHEADER ) ); + * lNewRecNo = hb_cdxSwapBytes( pMemoHeader.lNextBlock ); + pMemoHeader.lNextBlock = hb_cdxSwapBytes( * lNewRecNo + uiNumBlocks ); + hb_fsSeek( pArea->lpFileInfo->pNext->hFile, 0, FS_SET ); + hb_fsWrite( pArea->lpFileInfo->pNext->hFile, ( BYTE * ) &pMemoHeader, + sizeof( MEMOHEADER ) ); + } + + hb_fsSeek( pArea->lpFileInfo->pNext->hFile, * lNewRecNo * MEMO_BLOCK, FS_SET ); + pMemoHeader.lNextBlock = hb_cdxSwapBytes( 1 ); + pMemoHeader.lBlockSize = hb_cdxSwapBytes( pMemo->uiLen ); + hb_fsWrite( pArea->lpFileInfo->pNext->hFile, ( BYTE * ) &pMemoHeader, + sizeof( MEMOHEADER ) ); + if( hb_fsWrite( pArea->lpFileInfo->pNext->hFile, pMemo->pData, + pMemo->uiLen ) != pMemo->uiLen ) + { + if( !pArea->lpExtendInfo->fExclusive && !pArea->lpFileInfo->fFileLocked ) + hb_fsLock( pArea->lpFileInfo->pNext->hFile, LOCK_APPEND - 1, 1, FL_UNLOCK ); + return FALSE; + } + uiNumBlocks = ( pMemo->uiLen + sizeof( MEMOHEADER ) ) % MEMO_BLOCK; + if( uiNumBlocks > 0 ) + { + pBuffer = ( BYTE * ) hb_xgrab( MEMO_BLOCK ); + memset( pBuffer, 0, MEMO_BLOCK ); + hb_fsWrite( pArea->lpFileInfo->pNext->hFile, pBuffer, MEMO_BLOCK - uiNumBlocks ); + hb_xfree( pBuffer); + } + + if( !pArea->lpExtendInfo->fExclusive && !pArea->lpFileInfo->fFileLocked ) + hb_fsLock( pArea->lpFileInfo->pNext->hFile, LOCK_APPEND - 1, 1, FL_UNLOCK ); + return TRUE; +} + + +/* + * -- CDX METHODS -- + */ + +#define cdxBof NULL +#define cdxEof NULL +#define cdxFound NULL +#define cdxGoBottom NULL +#define cdxGoTo NULL +#define cdxGoToId NULL +#define cdxGoTop NULL +#define cdxSkip NULL +#define cdxSkipFilter NULL +#define cdxSkipRaw NULL +#define cdxAddField NULL +#define cdxAppend NULL +#define cdxCreateFields NULL +#define cdxDeleteRec NULL +#define cdxDeleted NULL +#define cdxFieldCount NULL +#define cdxFieldDisplay NULL +#define cdxFieldInfo NULL +#define cdxFieldName NULL +#define cdxFlush NULL +#define cdxGetRec NULL +#define cdxGetValue NULL +#define cdxGetVarLen NULL +#define cdxGoCold NULL +#define cdxGoHot NULL +#define cdxPutRec NULL +#define cdxPutValue NULL +#define cdxRecAll NULL +#define cdxRecCount NULL +#define cdxRecInfo NULL +#define cdxRecNo NULL +#define cdxSetFieldsExtent NULL +#define cdxAlias NULL +#define cdxClose NULL +#define cdxCreate NULL +#define cdxNewArea NULL +#define cdxOpen NULL +#define cdxRelease NULL +#define cdxStructSize NULL +#define cdxSysName NULL +#define cdxError NULL +#define cdxRawLock NULL +#define cdxLock NULL +#define cdxUnLock NULL +#define cdxCloseMemFile NULL +#define cdxReadDBHeader NULL +#define cdxWhoCares NULL + +static ERRCODE cdxCreateMemFile( AREAP pArea, LPDBOPENINFO pCreateInfo ) +{ + LPFILEINFO lpMemInfo; + LPMEMOHEADER pMemoHeader; + BOOL bError; + PHB_ITEM pError = NULL; + + if( !pArea->lpFileInfo->pNext ) + { + lpMemInfo = ( LPFILEINFO ) hb_xgrab( sizeof( FILEINFO ) ); + memset( lpMemInfo, 0, sizeof( FILEINFO ) ); + lpMemInfo->hFile = FS_ERROR; + pArea->lpFileInfo->pNext = lpMemInfo; + } + else + lpMemInfo = pArea->lpFileInfo->pNext; + + do + { + lpMemInfo->hFile = hb_fsCreate( pCreateInfo->abName, FC_NORMAL ); + if( lpMemInfo->hFile == FS_ERROR ) + { + if( !pError ) + { + pError = hb_errNew(); + hb_errPutGenCode( pError, EG_CREATE ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_CREATE ) ); + hb_errPutFileName( pError, ( char * ) pCreateInfo->abName ); + hb_errPutFlags( pError, EF_CANRETRY ); + } + bError = ( SELF_ERROR( pArea, pError ) == E_RETRY ); + } + else + bError = FALSE; + } while( bError ); + if( pError ) + hb_errRelease( pError ); + + if( lpMemInfo->hFile == FS_ERROR ) + return FAILURE; + + pMemoHeader = ( LPMEMOHEADER ) hb_xgrab( 512 ); + memset( pMemoHeader, 0, 512 ); + pMemoHeader->lNextBlock = hb_cdxSwapBytes( 512 / MEMO_BLOCK ); + pMemoHeader->lBlockSize = hb_cdxSwapBytes( MEMO_BLOCK ); + bError = ( hb_fsWrite( lpMemInfo->hFile, ( BYTE * ) pMemoHeader, 512 ) != 512 ); + hb_xfree( pMemoHeader ); + hb_fsClose( lpMemInfo->hFile ); + lpMemInfo->hFile = FS_ERROR; + if( bError ) + return FAILURE; + else + return SUCCESS; +} + +static ERRCODE cdxGetValueFile( AREAP pArea, USHORT uiIndex, void * pFile ) +{ + ULONG lRecNo, lNewRecNo; + BYTE * szText, szEndChar; + LPFIELD pField; + + HB_SYMBOL_UNUSED( pFile ); + if( uiIndex > pArea->uiFieldCount ) + return FAILURE; + + pField = pArea->lpFields + uiIndex - 1; + szText = pArea->lpExtendInfo->bRecord + pField->uiOffset; + if( !( ( LPDBFMEMO ) pField->memo )->pData ) + memset( szText, ' ', pField->uiLen ); + else + { + szEndChar = * ( szText + pField->uiLen ); + * ( szText + pField->uiLen ) = 0; + lRecNo = atol( ( char * ) szText ); + lNewRecNo = lRecNo; + if( !hb_cdxWriteMemo( pArea, ( LPDBFMEMO ) pField->memo, &lNewRecNo ) ) + return FAILURE; + if( lNewRecNo != lRecNo ) + hb_nltoa( lNewRecNo, ( char * ) szText, pField->uiLen ); + * ( szText + pField->uiLen ) = szEndChar; + } + ( ( LPDBFMEMO ) pField->memo )->fChanged = FALSE; + return SUCCESS; +} + +static ERRCODE cdxInfo( AREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) +{ + if( uiIndex == DBI_MEMOEXT ) + { + hb_itemPutC( pItem, ".FPT" ); + return SUCCESS; + } + + return SUPER_INFO( pArea, uiIndex, pItem ); +} + +static ERRCODE cdxOpenMemFile( AREAP pArea, LPDBOPENINFO pOpenInfo ) +{ + LPFILEINFO lpMemInfo; + LPMEMOHEADER pMemoHeader; + USHORT uiFlags; + PHB_ITEM pError = NULL; + BOOL bRetry; + + if( !pArea->lpFileInfo->pNext ) + { + lpMemInfo = ( LPFILEINFO ) hb_xgrab( sizeof( FILEINFO ) ); + memset( lpMemInfo, 0, sizeof( FILEINFO ) ); + lpMemInfo->hFile = FS_ERROR; + pArea->lpFileInfo->pNext = lpMemInfo; + } + else + lpMemInfo = pArea->lpFileInfo->pNext; + + uiFlags = pOpenInfo->fReadonly ? FO_READ : FO_READWRITE; + uiFlags |= pOpenInfo->fShared ? FO_DENYNONE : FO_EXCLUSIVE; + do + { + lpMemInfo->hFile = hb_fsOpen( pOpenInfo->abName, uiFlags ); + if( lpMemInfo->hFile == FS_ERROR ) + { + if( !pError ) + { + pError = hb_errNew(); + hb_errPutGenCode( pError, EG_OPEN ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_OPEN ) ); + hb_errPutFileName( pError, ( char * ) pOpenInfo->abName ); + hb_errPutFlags( pError, EF_CANRETRY ); + } + bRetry = ( SELF_ERROR( pArea, pError ) == E_RETRY ); + } + else + bRetry = FALSE; + } while( bRetry ); + if( pError ) + hb_errRelease( pError ); + + if( lpMemInfo->hFile == FS_ERROR ) + return FAILURE; + + pMemoHeader = ( LPMEMOHEADER ) hb_xgrab( 512 ); + if( hb_fsRead( lpMemInfo->hFile, ( BYTE * ) pMemoHeader, 512 ) != 512 ) + { + hb_xfree( pMemoHeader ); + return FAILURE; + } + hb_xfree( pMemoHeader ); + return SUCCESS; +} + +static ERRCODE cdxPutValueFile( AREAP pArea, USHORT uiIndex, void * pFile ) +{ + LPFIELD pField; + BYTE * szText, szEndChar; + ULONG lMemoBlock; + + HB_SYMBOL_UNUSED( pFile ); + + if( uiIndex > pArea->uiFieldCount ) + return FAILURE; + + pField = pArea->lpFields + uiIndex - 1;; + szText = pArea->lpExtendInfo->bRecord + pField->uiOffset; + szEndChar = * ( szText + pField->uiLen ); + * ( szText + pField->uiLen ) = 0; + lMemoBlock = atol( ( char * ) szText ) * MEMO_BLOCK; + * ( szText + pField->uiLen ) = szEndChar; + if( lMemoBlock > 0 ) + hb_cdxReadMemo( pArea, ( LPDBFMEMO ) pField->memo, lMemoBlock ); + else if( ( ( LPDBFMEMO ) pField->memo )->pData ) + { + hb_xfree( ( ( LPDBFMEMO ) pField->memo )->pData ); + memset( pField->memo, 0, sizeof( DBFMEMO ) ); + } + return SUCCESS; +} + +static ERRCODE cdxWriteDBHeader( AREAP pArea ) +{ + DBFHEADER pHeader; + DBFFIELD pDBField; + USHORT uiCount; + LPFIELD pField; + time_t t; + struct tm * pTime; + + memset( &pHeader, 0, sizeof( DBFHEADER ) ); + pHeader.uiRecordLen = 1; + pHeader.bVersion = 0x03; + pField = pArea->lpFields; + for( uiCount = 0; uiCount < pArea->uiFieldCount; uiCount++ ) + { + switch( pField->uiType ) + { + case 'C': + case 'N': + pHeader.uiRecordLen += pField->uiLen; + break; + + case 'M': + pHeader.uiRecordLen += 10; + pHeader.bVersion = 0xF5; + pArea->lpExtendInfo->fHasMemo = TRUE; + break; + + case 'D': + pHeader.uiRecordLen += 8; + break; + + case 'L': + pHeader.uiRecordLen += 1; + break; + } + pField++; + } + + time( &t ); + pTime = localtime( &t ); + pHeader.bYear = ( BYTE ) pTime->tm_year; + pHeader.bMonth = ( BYTE ) pTime->tm_mon + 1; + pHeader.bDay = ( BYTE ) pTime->tm_mday; + pHeader.uiHeaderLen = ( USHORT ) ( 32 * ( pArea->uiFieldCount + 1 ) + 1 ); + pHeader.bHasTag = 0; + pHeader.ulRecords = 0; + if( hb_fsWrite( pArea->lpFileInfo->hFile, ( BYTE * ) &pHeader, + sizeof( DBFHEADER ) ) != sizeof( DBFHEADER ) ) + return FAILURE; + + pField = pArea->lpFields; + for( uiCount = 0; uiCount < pArea->uiFieldCount; uiCount++ ) + { + memset( &pDBField, 0, sizeof( DBFFIELD ) ); + strncpy( ( char * ) pDBField.bName, ( ( PHB_DYNS ) pField->sym )->pSymbol->szName, + sizeof( pDBField.bName ) ); + pDBField.bType = pField->uiType; + switch( pDBField.bType ) + { + case 'C': + pDBField.bLen = pField->uiLen & 0xFF; + pDBField.bDec = pField->uiLen >> 8; + break; + + case 'M': + pDBField.bLen = 10; + pDBField.bDec = 0; + break; + + case 'D': + pDBField.bLen = 8; + pDBField.bDec = 0; + break; + + case 'L': + pDBField.bLen = 1; + pDBField.bDec = 0; + break; + + case 'N': + pDBField.bLen = pField->uiLen; + pDBField.bDec = pField->uiDec; + break; + } + if( hb_fsWrite( pArea->lpFileInfo->hFile, ( BYTE * ) &pDBField, + sizeof( DBFFIELD ) ) != sizeof( DBFFIELD ) ) + return FAILURE; + pField++; + } + if( hb_fsWrite( pArea->lpFileInfo->hFile, ( BYTE * ) "\15\32", 2 ) != 2 ) + return FAILURE; + return SUCCESS; +} + +static RDDFUNCS cdxTable = { cdxBof, + cdxEof, + cdxFound, + cdxGoBottom, + cdxGoTo, + cdxGoToId, + cdxGoTop, + cdxSkip, + cdxSkipFilter, + cdxSkipRaw, + cdxAddField, + cdxAppend, + cdxCreateFields, + cdxDeleteRec, + cdxDeleted, + cdxFieldCount, + cdxFieldDisplay, + cdxFieldInfo, + cdxFieldName, + cdxFlush, + cdxGetRec, + cdxGetValue, + cdxGetVarLen, + cdxGoCold, + cdxGoHot, + cdxPutRec, + cdxPutValue, + cdxRecAll, + cdxRecCount, + cdxRecInfo, + cdxRecNo, + cdxSetFieldsExtent, + cdxAlias, + cdxClose, + cdxCreate, + cdxInfo, + cdxNewArea, + cdxOpen, + cdxRelease, + cdxStructSize, + cdxSysName, + cdxError, + cdxRawLock, + cdxLock, + cdxUnLock, + cdxCloseMemFile, + cdxCreateMemFile, + cdxGetValueFile, + cdxOpenMemFile, + cdxPutValueFile, + cdxReadDBHeader, + cdxWriteDBHeader, + cdxWhoCares + }; + +HARBOUR HB__DBFCDX( void ) +{ +} + +HARBOUR HB_DBFCDX_GETFUNCTABLE( void ) +{ + RDDFUNCS * pTable; + USHORT * uiCount; + + uiCount = ( USHORT * ) hb_parnl( 1 ); + * uiCount = RDDFUNCSCOUNT; + pTable = ( RDDFUNCS * ) hb_parnl( 2 ); + if( pTable ) + hb_retni( hb_rddInherit( pTable, &cdxTable, &cdxSuper, ( BYTE * ) "DBF" ) ); + else + hb_retni( FAILURE ); +} + diff --git a/harbour/tests/bld_vc.bat b/harbour/tests/bld_vc.bat index 7a2388e423..c1b80a0f69 100644 --- a/harbour/tests/bld_vc.bat +++ b/harbour/tests/bld_vc.bat @@ -4,5 +4,5 @@ rem $Id$ rem ..\bin\harbour %1 /n /i..\include -cl -Fd..\bin\harbour -w -Zi -TP -GZ -GA -DDEBUG -DHARBOUR_USE_WIN_GTAPI -I..\include %1.c /link /subsystem:CONSOLE ..\lib\vc\harbour.lib ..\lib\vc\terminal.lib ..\lib\vc\hbtools.lib ..\lib\vc\dbfntx.lib ..\lib\vc\debug.lib +cl -Fd..\bin\harbour -w -Zi -TP -GZ -GA -DDEBUG -DHARBOUR_USE_WIN_GTAPI -I..\include %1.c /link /subsystem:CONSOLE ..\lib\vc\harbour.lib ..\lib\vc\terminal.lib ..\lib\vc\hbtools.lib ..\lib\vc\dbfntx.lib ..\lib\vc\dbfcdx.lib ..\lib\vc\debug.lib del %1.c diff --git a/harbour/tests/testdbf.prg b/harbour/tests/testdbf.prg index 54baff9f01..a35b8466a7 100644 --- a/harbour/tests/testdbf.prg +++ b/harbour/tests/testdbf.prg @@ -5,32 +5,34 @@ function main() local aStruct := { { "CHARACTER", "C", 25, 0 }, ; - { "NUMERIC", "N", 8, 0 }, ; - { "DOUBLE", "N", 8, 2 }, ; - { "DATE", "D", 8, 0 }, ; + { "NUMERIC", "N", 8, 0 }, ; + { "DOUBLE", "N", 8, 2 }, ; + { "DATE", "D", 8, 0 }, ; { "LOGICAL", "L", 1, 0 }, ; { "MEMO1", "M", 10, 0 }, ; { "MEMO2", "M", 10, 0 } } - dbCreate( "testdbf", aStruct ) - dbUseArea(,, "testdbf" ) - ? "[" + FIELD->MEMO1 + "]" - ? "[" + FIELD->MEMO2 + "]" + REQUEST DBFCDX + + dbCreate( "testdbf", aStruct, "DBFCDX", .t., "MYALIAS" ) + + ? "[" + MYALIAS->MEMO1 + "]" + ? "[" + MYALIAS->MEMO2 + "]" ? "-" - FIELD->MEMO1 := "Hello world!" - FIELD->MEMO2 := "Harbour power" - ? "[" + FIELD->MEMO1 + "]" - ? "[" + FIELD->MEMO2 + "]" dbAppend() - FIELD->MEMO1 := "111" - FIELD->MEMO2 := "222" - ? "[" + FIELD->MEMO1 + "]" - ? "[" + FIELD->MEMO2 + "]" - - FIELD->NUMERIC := 90 - FIELD->DOUBLE := 120.138 - - ? "[" + Str(FIELD->DOUBLE) + "]" - ? "[" + Str(FIELD->NUMERIC) + "]" + MYALIAS->MEMO1 := "Hello world!" + MYALIAS->MEMO2 := "Harbour power" + ? "[" + MYALIAS->MEMO1 + "]" + ? "[" + MYALIAS->MEMO2 + "]" + dbAppend() + MYALIAS->MEMO1 := "111" + MYALIAS->MEMO2 := "222" + ? "[" + MYALIAS->MEMO1 + "]" + ? "[" + MYALIAS->MEMO2 + "]" + MYALIAS->NUMERIC := 90 + MYALIAS->DOUBLE := 120.138 + ? "[" + Str( MYALIAS->DOUBLE ) + "]" + ? "[" + Str( MYALIAS->NUMERIC ) + "]" return nil +