diff --git a/harbour/ChangeLog b/harbour/ChangeLog index d9d2ebeb7a..a2d6626a45 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -8,6 +8,67 @@ 2002-12-01 13:30 UTC+0100 Foo Bar */ +2006-05-31 13:45 UTC+0200 Tomaz Zupan (tomaz.zupan at orpo.si) + * harbour.spec + * Added Mandriva to recognised distros + * Sinchronised version with harbour/include/hbver.h + +2006-05-30 18:15 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) + * harbour/source/rdd/sdf1.c + * cleaned BCC warning + * harbour/source/rdd/delim1.c + ! fixed BCC compilation (string initialization with dynamic + values is forbidden by BCC) + +2006-05-30 12:15 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) + * harbour/include/hbver.h + * changed version number and ChangeLog entry + + * harbour/make_tgz.sh + ! fixed creating PP in DJGPP builds + + * harbour/contrib/dot/pp.prg + ! minor fix in parameter checking + + * harbour/contrib/libmisc/hb_f.c + ! fixed bug in record numbering after reaching EOF position and + backward skipping + + * harbour/include/hbrdddel.h + * harbour/source/rdd/delim1.c + + implemented DELIM RDD. It should be fully Clipper compatible + in comma files parsing. If you will find any difference, please + inform me and I'll update it. Unlike in Clipper in [x]Harbour + these RDD can be used also in direct import operations with + APPEND FROM ... VIA "DELIM" + These RDD also support whole record transfering between RDDs + if they support the same record format and field representation + and can translate extended field types like "I", "B", "V3", "V4", + etc. + + * harbour/source/rtl/dbdelim.prg + * replaced old code of __dbDelim() function with simple calls to + __dbCopy()/__dbApp() - it should fix most of the reported + incompatibilities in DELIM import/export operations and + increase their speed many times + + * harbour/include/hbrddsdf.h + * harbour/source/rdd/sdf1.c + + implemented SDF RDD. It should be fully Clipper compatible + in SDF files parsing. If you will find any difference, please + inform me and I'll update it. Unlike in Clipper in [x]Harbour + these RDD can be used also in direct import operations with + APPEND FROM ... VIA "SDF" + These RDD also support whole record transfering between RDDs + if they support the same record format and field representation + and can translate extended field types like "I", "B", "V3", "V4", + etc. + + * harbour/source/rtl/dbsdf.prg + * replaced old code of __dbSDF() function with simple calls to + __dbCopy()/__dbApp() - it should fix most of the reported + incompatibilities in SDF import/export operations and + increase their speed many times * harbour/source/rdd/dbcmd.c + added support for table structure inheriting in transfer RDDs. diff --git a/harbour/contrib/dot/pp.prg b/harbour/contrib/dot/pp.prg index c42161ea1d..beb1827bc7 100644 --- a/harbour/contrib/dot/pp.prg +++ b/harbour/contrib/dot/pp.prg @@ -439,7 +439,7 @@ STATIC s_aSwitchDefs := {} bCompile := .T. sSwitch := "" aParams := { p1, p2, p3, p4, p5, p6, p7, p8, p9 } - aSize( aParams, PCount() ) + aSize( aParams, PCount() - 1 ) endif #endif diff --git a/harbour/contrib/libmisc/hb_f.c b/harbour/contrib/libmisc/hb_f.c index 4b8bafc5af..2a9d81de7e 100644 --- a/harbour/contrib/libmisc/hb_f.c +++ b/harbour/contrib/libmisc/hb_f.c @@ -253,7 +253,7 @@ HB_FUNC( HB_FGOBOTTOM ) { int x; int len; - long loc; + long loc, last; if ( last_rec[area] != 0 ) { recno[area] = last_rec[area]; @@ -263,14 +263,15 @@ HB_FUNC( HB_FGOBOTTOM ) loc = 0L; + last = offset[area]; do { - hb_fsSeek( handles[area], offset[area], SEEK_SET ); len = hb_fsRead( handles[area], ( BYTE * ) c, c_size ); for ( x = 0; x < len; x++ ) { if ( ((*(c + x) == 13) && (*(c + x + 1) == 10)) || ((*(c + x) == 10) && (*(c + x + 1) == 13)) || ( x - loc > b_size ) ) { + last = offset[area] + loc; recno[area]++; x++; loc = x + 1; @@ -281,7 +282,7 @@ HB_FUNC( HB_FGOBOTTOM ) } while ( len == c_size ); last_rec[area] = --recno[area]; - last_off[area] = offset[area]; + last_off[area] = last; } } @@ -371,6 +372,7 @@ HB_FUNC( HB_FREADANDSKIP ) ((*(b + x) == 10) && x < read-1 && (*(b + x + 1) == 13)) ) { x += 2; + bHasCRLF = TRUE; break; } x++; diff --git a/harbour/include/hbrdddel.h b/harbour/include/hbrdddel.h index 5ca2bb7655..80599fb882 100644 --- a/harbour/include/hbrdddel.h +++ b/harbour/include/hbrdddel.h @@ -4,9 +4,9 @@ /* * Harbour Project source code: - * DELIMITED RDD module + * DELIM RDD * - * Copyright 1999 Bruno Cantero + * Copyright 2006 Przemyslaw Czerpak * www - http://www.harbour-project.org * * This program is free software; you can redistribute it and/or modify @@ -57,109 +57,84 @@ HB_EXTERN_BEGIN +/* DELIMITED default file extensions */ +#define DELIM_TABLEEXT ".txt" + + /* - * -- DELIMITED METHODS -- + * DELIM WORKAREA + * ------------ + * The Workarea Structure of DELIM RDD + * */ -#define hb_delimBof NULL -#define hb_delimEof NULL -#define hb_delimFound NULL -#define hb_delimGoBottom NULL -#define hb_delimGoTo NULL -#define hb_delimGoToId NULL -#define hb_delimGoTop NULL -#define hb_delimSeek NULL -#define hb_delimSkip NULL -#define hb_delimSkipFilter NULL -#define hb_delimSkipRaw NULL -#define hb_delimAddField NULL -#define hb_delimAppend NULL -#define hb_delimCreateFields NULL -#define hb_delimDeleteRec NULL -#define hb_delimDeleted NULL -#define hb_delimFieldCount NULL -#define hb_delimFieldDisplay NULL -#define hb_delimFieldInfo NULL -#define hb_delimFieldName NULL -#define hb_delimFlush NULL -#define hb_delimGetRec NULL -#define hb_delimGetValue NULL -#define hb_delimGetVarLen NULL -#define hb_delimGoCold NULL -#define hb_delimGoHot NULL -#define hb_delimPutRec NULL -#define hb_delimPutValue NULL -#define hb_delimRecall NULL -#define hb_delimRecCount NULL -#define hb_delimRecInfo NULL -#define hb_delimRecNo NULL -#define hb_delimRecId NULL -#define hb_delimSetFieldExtent NULL -#define hb_delimAlias NULL -#define hb_delimClose NULL -#define hb_delimCreate NULL -#define hb_delimInfo NULL -#define hb_delimNewArea NULL -#define hb_delimOpen NULL -#define hb_delimRelease NULL -#define hb_delimStructSize NULL -#define hb_delimSysName NULL -#define hb_delimEval NULL -#define hb_delimPack NULL -#define hb_delimPackRec NULL -#define hb_delimSort NULL -#define hb_delimTrans NULL -#define hb_delimTransRec NULL -#define hb_delimZap NULL -#define hb_delimChildEnd NULL -#define hb_delimChildStart NULL -#define hb_delimChildSync NULL -#define hb_delimSyncChildren NULL -#define hb_delimClearRel NULL -#define hb_delimForceRel NULL -#define hb_delimRelArea NULL -#define hb_delimRelEval NULL -#define hb_delimRelText NULL -#define hb_delimSetRel NULL -#define hb_delimOrderListAdd NULL -#define hb_delimOrderListClear NULL -#define hb_delimOrderListDelete NULL -#define hb_delimOrderListFocus NULL -#define hb_delimOrderListRebuild NULL -#define hb_delimOrderCondition NULL -#define hb_delimOrderCreate NULL -#define hb_delimOrderDestroy NULL -#define hb_delimOrderInfo NULL -#define hb_delimClearFilter NULL -#define hb_delimClearLocate NULL -#define hb_delimClearScope NULL -#define hb_delimCountScope NULL -#define hb_delimFilterText NULL -#define hb_delimScopeInfo NULL -#define hb_delimSetFilter NULL -#define hb_delimSetLocate NULL -#define hb_delimSetScope NULL -#define hb_delimSkipScope NULL -#define hb_delimLocate NULL -#define hb_delimCompile NULL -#define hb_delimError NULL -#define hb_delimEvalBlock NULL -#define hb_delimRawLock NULL -#define hb_delimLock NULL -#define hb_delimUnLock NULL -#define hb_delimCloseMemFile NULL -#define hb_delimCreateMemFile NULL -#define hb_delimGetValueFile NULL -#define hb_delimOpenMemFile NULL -#define hb_delimPutValueFile NULL -#define hb_delimReadDBHeader NULL -#define hb_delimWriteDBHeader NULL -#define hb_delimInit NULL -#define hb_delimExit NULL -#define hb_delimDrop NULL -#define hb_delimExists NULL -#define hb_delimRddInfo NULL -#define hb_delimWhoCares NULL +typedef struct _DELIMAREA +{ + struct _RDDFUNCS * lprfsHost; /* Virtual method table for this workarea */ + USHORT uiArea; /* The number assigned to this workarea */ + void * atomAlias; /* Pointer to the alias symbol for this workarea */ + USHORT uiFieldExtent; /* Total number of fields allocated */ + USHORT uiFieldCount; /* Total number of fields used */ + LPFIELD lpFields; /* Pointer to an array of fields */ + void * lpFieldExtents; /* Void ptr for additional field properties */ + PHB_ITEM valResult; /* All purpose result holder */ + BOOL fTop; /* TRUE if "top" */ + BOOL fBottom; /* TRUE if "bottom" */ + BOOL fBof; /* TRUE if "bof" */ + BOOL fEof; /* TRUE if "eof" */ + BOOL fFound; /* TRUE if "found" */ + DBSCOPEINFO dbsi; /* Info regarding last LOCATE */ + DBFILTERINFO dbfi; /* Filter in effect */ + LPDBORDERCONDINFO lpdbOrdCondInfo; + LPDBRELINFO lpdbRelations; /* Parent/Child relationships used */ + USHORT uiParents; /* Number of parents for this area */ + USHORT heap; + USHORT heapSize; + USHORT rddID; + USHORT uiMaxFieldNameLength; + PHB_CODEPAGE cdPage; /* Area's codepage pointer */ + + /* + * DELIM's additions to the workarea structure + * + * Warning: The above section MUST match WORKAREA exactly! Any + * additions to the structure MUST be added below, as in this + * example. + */ + + FHANDLE hFile; /* Data file handle */ + char * szFileName; /* Name of data file */ + char * szEol; /* EOL marker */ + USHORT uiEolLen; /* Size of EOL marker */ + BOOL fDelim; /* Use character field delimiter? */ + char cDelim; /* Character field delimiter */ + char cSeparator; /* Field delimiter */ + USHORT uiRecordLen; /* Size of record */ + USHORT * pFieldOffset; /* Pointer to field offset array */ + BYTE * pRecord; /* Buffer of record data */ + BYTE * pBuffer; /* Read/Write */ + ULONG ulBufferSize; /* IO buffer size */ + ULONG ulBufferRead; /* Number of bytes in read buffer */ + ULONG ulBufferIndex; /* Index to read read buffer */ + HB_FOFFSET ulRecordOffset; /* Current record offest */ + HB_FOFFSET ulNextOffset; /* Next record offest */ + HB_FOFFSET ulFileSize; /* File table size in export mode */ + HB_FOFFSET ulBufferStart; /* Start offset of read buffer */ + ULONG ulRecNo; /* Current record */ + ULONG ulRecCount; /* Number of records (in export) */ + BOOL fTransRec; /* Can put whole records */ + BOOL fFlush; /* Data was written to table and not commited */ + BOOL fShared; /* Shared file */ + BOOL fReadonly; /* Read only file */ + BOOL fPositioned; /* Positioned record */ + BOOL fRecordChanged; /* Record changed */ +} DELIMAREA; + +typedef DELIMAREA * LPDELIMAREA; + +#ifndef DELIMAREAP +#define DELIMAREAP LPDELIMAREA +#endif HB_EXTERN_END diff --git a/harbour/include/hbrddsdf.h b/harbour/include/hbrddsdf.h index d1cebbf81a..3489d502f5 100644 --- a/harbour/include/hbrddsdf.h +++ b/harbour/include/hbrddsdf.h @@ -4,9 +4,9 @@ /* * Harbour Project source code: - * SDF RDD module + * SDF RDD * - * Copyright 1999 Bruno Cantero + * Copyright 2006 Przemyslaw Czerpak * www - http://www.harbour-project.org * * This program is free software; you can redistribute it and/or modify @@ -57,109 +57,76 @@ HB_EXTERN_BEGIN +/* SDF default file extensions */ +#define SDF_TABLEEXT ".txt" + + /* - * -- SDF METHODS -- + * SDF WORKAREA + * ------------ + * The Workarea Structure of SDF RDD + * */ -#define hb_sdfBof NULL -#define hb_sdfEof NULL -#define hb_sdfFound NULL -#define hb_sdfGoBottom NULL -#define hb_sdfGoTo NULL -#define hb_sdfGoToId NULL -#define hb_sdfGoTop NULL -#define hb_sdfSeek NULL -#define hb_sdfSkip NULL -#define hb_sdfSkipFilter NULL -#define hb_sdfSkipRaw NULL -#define hb_sdfAddField NULL -#define hb_sdfAppend NULL -#define hb_sdfCreateFields NULL -#define hb_sdfDeleteRec NULL -#define hb_sdfDeleted NULL -#define hb_sdfFieldCount NULL -#define hb_sdfFieldDisplay NULL -#define hb_sdfFieldInfo NULL -#define hb_sdfFieldName NULL -#define hb_sdfFlush NULL -#define hb_sdfGetRec NULL -#define hb_sdfGetValue NULL -#define hb_sdfGetVarLen NULL -#define hb_sdfGoCold NULL -#define hb_sdfGoHot NULL -#define hb_sdfPutRec NULL -#define hb_sdfPutValue NULL -#define hb_sdfRecall NULL -#define hb_sdfRecCount NULL -#define hb_sdfRecInfo NULL -#define hb_sdfRecNo NULL -#define hb_sdfRecId NULL -#define hb_sdfSetFieldExtent NULL -#define hb_sdfAlias NULL -#define hb_sdfClose NULL -#define hb_sdfCreate NULL -#define hb_sdfInfo NULL -#define hb_sdfNewArea NULL -#define hb_sdfOpen NULL -#define hb_sdfRelease NULL -#define hb_sdfStructSize NULL -#define hb_sdfSysName NULL -#define hb_sdfEval NULL -#define hb_sdfPack NULL -#define hb_sdfPackRec NULL -#define hb_sdfSort NULL -#define hb_sdfTrans NULL -#define hb_sdfTransRec NULL -#define hb_sdfZap NULL -#define hb_sdfChildEnd NULL -#define hb_sdfChildStart NULL -#define hb_sdfChildSync NULL -#define hb_sdfSyncChildren NULL -#define hb_sdfClearRel NULL -#define hb_sdfForceRel NULL -#define hb_sdfRelArea NULL -#define hb_sdfRelEval NULL -#define hb_sdfRelText NULL -#define hb_sdfSetRel NULL -#define hb_sdfOrderListAdd NULL -#define hb_sdfOrderListClear NULL -#define hb_sdfOrderListDelete NULL -#define hb_sdfOrderListFocus NULL -#define hb_sdfOrderListRebuild NULL -#define hb_sdfOrderCondition NULL -#define hb_sdfOrderCreate NULL -#define hb_sdfOrderDestroy NULL -#define hb_sdfOrderInfo NULL -#define hb_sdfClearFilter NULL -#define hb_sdfClearLocate NULL -#define hb_sdfClearScope NULL -#define hb_sdfCountScope NULL -#define hb_sdfFilterText NULL -#define hb_sdfScopeInfo NULL -#define hb_sdfSetFilter NULL -#define hb_sdfSetLocate NULL -#define hb_sdfSetScope NULL -#define hb_sdfSkipScope NULL -#define hb_sdfLocate NULL -#define hb_sdfCompile NULL -#define hb_sdfError NULL -#define hb_sdfEvalBlock NULL -#define hb_sdfRawLock NULL -#define hb_sdfLock NULL -#define hb_sdfUnLock NULL -#define hb_sdfCloseMemFile NULL -#define hb_sdfCreateMemFile NULL -#define hb_sdfGetValueFile NULL -#define hb_sdfOpenMemFile NULL -#define hb_sdfPutValueFile NULL -#define hb_sdfReadDBHeader NULL -#define hb_sdfWriteDBHeader NULL -#define hb_sdfInit NULL -#define hb_sdfExit NULL -#define hb_sdfDrop NULL -#define hb_sdfExists NULL -#define hb_sdfRddInfo NULL -#define hb_sdfWhoCares NULL +typedef struct _SDFAREA +{ + struct _RDDFUNCS * lprfsHost; /* Virtual method table for this workarea */ + USHORT uiArea; /* The number assigned to this workarea */ + void * atomAlias; /* Pointer to the alias symbol for this workarea */ + USHORT uiFieldExtent; /* Total number of fields allocated */ + USHORT uiFieldCount; /* Total number of fields used */ + LPFIELD lpFields; /* Pointer to an array of fields */ + void * lpFieldExtents; /* Void ptr for additional field properties */ + PHB_ITEM valResult; /* All purpose result holder */ + BOOL fTop; /* TRUE if "top" */ + BOOL fBottom; /* TRUE if "bottom" */ + BOOL fBof; /* TRUE if "bof" */ + BOOL fEof; /* TRUE if "eof" */ + BOOL fFound; /* TRUE if "found" */ + DBSCOPEINFO dbsi; /* Info regarding last LOCATE */ + DBFILTERINFO dbfi; /* Filter in effect */ + LPDBORDERCONDINFO lpdbOrdCondInfo; + LPDBRELINFO lpdbRelations; /* Parent/Child relationships used */ + USHORT uiParents; /* Number of parents for this area */ + USHORT heap; + USHORT heapSize; + USHORT rddID; + USHORT uiMaxFieldNameLength; + PHB_CODEPAGE cdPage; /* Area's codepage pointer */ + + /* + * SDFS's additions to the workarea structure + * + * Warning: The above section MUST match WORKAREA exactly! Any + * additions to the structure MUST be added below, as in this + * example. + */ + + FHANDLE hFile; /* Data file handle */ + char * szFileName; /* Name of data file */ + char * szEol; /* EOL marker */ + USHORT uiEolLen; /* Size of EOL marker */ + USHORT uiRecordLen; /* Size of record */ + USHORT * pFieldOffset; /* Pointer to field offset array */ + BYTE * pRecord; /* Buffer of record data */ + HB_FOFFSET ulRecordOffset; /* Current record offest */ + HB_FOFFSET ulNextOffset; /* Next record offest */ + HB_FOFFSET ulFileSize; /* File table size in export mode */ + ULONG ulRecNo; /* Current record */ + ULONG ulRecCount; /* Number of records (in export) */ + BOOL fTransRec; /* Can put whole records */ + BOOL fFlush; /* Data was written to SDF and not commited */ + BOOL fShared; /* Shared file */ + BOOL fReadonly; /* Read only file */ + BOOL fPositioned; /* Positioned record */ + BOOL fRecordChanged; /* Record changed */ +} SDFAREA; + +typedef SDFAREA * LPSDFAREA; + +#ifndef SDFAREAP +#define SDFAREAP LPSDFAREA +#endif HB_EXTERN_END diff --git a/harbour/include/hbver.h b/harbour/include/hbver.h index 2c8f514147..d5727975f1 100644 --- a/harbour/include/hbver.h +++ b/harbour/include/hbver.h @@ -62,13 +62,13 @@ /* NOTE: One of these next three fields can be incremented by the hbverfix program */ #define HB_VER_MAJOR 0 /* Major version number */ -#define HB_VER_MINOR 46 /* Minor version number */ +#define HB_VER_MINOR 47 /* Minor version number */ #define HB_VER_REVISION 0 /* Revision number */ /* NOTE: The next two fields are automatically updated by the hbverfix program */ -#define HB_VER_LENTRY "2006-05-29 14:10 UTC+0100 Ryszard Glab" -#define HB_VER_CHLCVS "ChangeLog,v 1.4894 2006/05/29 11:59:37 rglab" +#define HB_VER_LENTRY "2006-05-30 12:09 UTC+0300 Chen Kedem" +#define HB_VER_CHLCVS "ChangeLog,v 1.4896 2006/05/30 09:09:16 ckedem" /* TOFIX: The next three fields need to get updated automatically */ diff --git a/harbour/make_tgz.sh b/harbour/make_tgz.sh index db0ee71f09..b4106940ab 100644 --- a/harbour/make_tgz.sh +++ b/harbour/make_tgz.sh @@ -255,13 +255,14 @@ then fi # Create and install PP -pushd contrib/dot -$HB_BIN_INSTALL/${hb_pref}mk pp -n -w -D_DEFAULT_INC_DIR=\"${_DEFAULT_INC_DIR}\" -$INSTALL -m755 pp $HB_BIN_INSTALL/pp -ln -s pp $HB_BIN_INSTALL/pprun +(cd contrib/dot +export PRG_USR="\"-D_DEFAULT_INC_DIR='${_DEFAULT_INC_DIR}'\"" +$HB_BIN_INSTALL/${hb_pref}mk pp -n -w +strip pp${hb_exesuf} +$INSTALL -m755 pp${hb_exesuf} $HB_BIN_INSTALL/pp${hb_exesuf} +ln -s pp${hb_exesuf} $HB_BIN_INSTALL/pprun${hb_exesuf} $INSTALL -m644 rp_dot.ch $HB_INC_INSTALL/ -rm -f pp -popd +rm -f pp${hb_exesuf}) CURDIR=$(pwd) diff --git a/harbour/source/rdd/dbcmd.c b/harbour/source/rdd/dbcmd.c index f76083119d..09c7658f28 100644 --- a/harbour/source/rdd/dbcmd.c +++ b/harbour/source/rdd/dbcmd.c @@ -75,6 +75,7 @@ #include "hbapilng.h" #include "hbapiitm.h" #include "hbrddwrk.h" +#include "rddsys.ch" #if defined(__XHARBOUR__) #include "hbfast.h" #else @@ -1589,7 +1590,8 @@ HB_FUNC( DBCOMMITALL ) static ERRCODE hb_rddOpenTable( char * szFileName, char * szDriver, USHORT uiArea, char *szAlias, BOOL fShared, BOOL fReadonly, - char * szCpId, ULONG ulConnection ) + char * szCpId, ULONG ulConnection, + PHB_ITEM pStruct ) { char szDriverBuffer[ HARBOUR_MAX_RDD_DRIVERNAME_LENGTH + 1 ]; DBOPENINFO pInfo; @@ -1642,13 +1644,25 @@ static ERRCODE hb_rddOpenTable( char * szFileName, char * szDriver, pInfo.ulConnection = ulConnection; pInfo.lpdbHeader = NULL; - /* Open file */ - errCode = SELF_OPEN( pArea, &pInfo ); - - if( errCode != SUCCESS ) + if( pStruct ) { - hb_rddReleaseCurrentArea(); - hb_rddSelectWorkAreaNumber( uiPrevArea ); + errCode = SELF_CREATEFIELDS( pArea, pStruct ); + } + else + { + errCode = SUCCESS; + } + + if( errCode == SUCCESS ) + { + /* Open file */ + errCode = SELF_OPEN( pArea, &pInfo ); + + if( errCode != SUCCESS ) + { + hb_rddReleaseCurrentArea(); + hb_rddSelectWorkAreaNumber( uiPrevArea ); + } } s_bNetError = errCode != SUCCESS; @@ -2247,7 +2261,7 @@ HB_FUNC( DBUSEAREA ) hb_parl( 1 ) ? 0 : hb_rddGetCurrentWorkAreaNumber(), hb_parc( 4 ), ISLOG( 5 ) ? hb_parl( 5 ) : !hb_set.HB_SET_EXCLUSIVE, - hb_parl( 6 ), hb_parc( 7 ), hb_parnl( 8 ) ); + hb_parl( 6 ), hb_parc( 7 ), hb_parnl( 8 ), NULL ); } HB_FUNC( __DBZAP ) @@ -4282,11 +4296,13 @@ static ERRCODE hb_rddTransRecords( AREAP pArea, PHB_ITEM pCobWhile, PHB_ITEM pStrWhile, PHB_ITEM pNext, PHB_ITEM pRecID, PHB_ITEM pRest, - char *szCpId ) + char *szCpId, + PHB_ITEM pDelim ) { - AREAP lpaSource, lpaDest, lpaClose = NULL; + AREAP lpaClose = NULL; + PHB_ITEM pStruct = NULL; DBTRANSINFO dbTransInfo; - USHORT uiPrevArea; + USHORT uiPrevArea, uiCount, uiSwap; ERRCODE errCode; memset( &dbTransInfo, 0, sizeof( DBTRANSINFO ) ); @@ -4294,10 +4310,7 @@ static ERRCODE hb_rddTransRecords( AREAP pArea, if( fExport ) { - PHB_ITEM pStruct = NULL; - - lpaSource = pArea; - errCode = hb_dbTransStruct( lpaSource, NULL, &dbTransInfo, + errCode = hb_dbTransStruct( pArea, NULL, &dbTransInfo, &pStruct, pFields ); if( errCode == SUCCESS ) { @@ -4305,26 +4318,71 @@ static ERRCODE hb_rddTransRecords( AREAP pArea, TRUE, 0, "", szCpId, ulConnection ); if( errCode == SUCCESS ) { - dbTransInfo.lpaDest = lpaClose = lpaDest = + dbTransInfo.lpaDest = lpaClose = ( AREAP ) hb_rddGetCurrentWorkAreaPointer(); + if( pDelim ) + { + SELF_INFO( dbTransInfo.lpaDest, DBI_SETDELIMITER, pDelim ); + } } } - if( pStruct ) - hb_itemRelease( pStruct ); } else { - lpaDest = pArea; - errCode = hb_rddOpenTable( szFileName, szDriver, 0, "", TRUE, TRUE, - szCpId, ulConnection ); - if( errCode == SUCCESS ) + LPRDDNODE pRddNode = hb_rddFindNode( szDriver, NULL ); + + if( !pRddNode ) { - lpaClose = lpaSource = ( AREAP ) hb_rddGetCurrentWorkAreaPointer(); - errCode = hb_dbTransStruct( lpaSource, lpaDest, &dbTransInfo, - NULL, pFields ); + hb_errRT_DBCMD( EG_ARG, EDBCMD_USE_BADPARAMETER, NULL, "DBUSEAREA" ); + return FAILURE; + } + + if( pRddNode->uiType == RDT_TRANSFER ) + { + errCode = hb_dbTransStruct( pArea, NULL, &dbTransInfo, + &pStruct, pFields ); + + /* revert area and items */ + dbTransInfo.lpaDest = dbTransInfo.lpaSource; + for( uiCount = 0; uiCount < dbTransInfo.uiItemCount; ++uiCount ) + { + uiSwap = dbTransInfo.lpTransItems[uiCount].uiSource; + dbTransInfo.lpTransItems[uiCount].uiSource = + dbTransInfo.lpTransItems[uiCount].uiDest; + dbTransInfo.lpTransItems[uiCount].uiDest = uiSwap; + } + + if( errCode == SUCCESS ) + { + errCode = hb_rddOpenTable( szFileName, szDriver, 0, "", TRUE, TRUE, + szCpId, ulConnection, pStruct ); + if( errCode == SUCCESS ) + { + lpaClose = dbTransInfo.lpaSource = + ( AREAP ) hb_rddGetCurrentWorkAreaPointer(); + if( pDelim ) + { + SELF_INFO( dbTransInfo.lpaSource, DBI_SETDELIMITER, pDelim ); + } + } + } + } + else + { + errCode = hb_rddOpenTable( szFileName, szDriver, 0, "", TRUE, TRUE, + szCpId, ulConnection, NULL ); + if( errCode == SUCCESS ) + { + lpaClose = ( AREAP ) hb_rddGetCurrentWorkAreaPointer(); + errCode = hb_dbTransStruct( lpaClose, pArea, &dbTransInfo, + NULL, pFields ); + } } } + if( pStruct ) + hb_itemRelease( pStruct ); + if( errCode == SUCCESS ) { hb_rddSelectWorkAreaNumber( dbTransInfo.lpaSource->uiArea ); @@ -4378,7 +4436,8 @@ HB_FUNC( __DBAPP ) hb_param( 5, HB_IT_NUMERIC ), /* Next */ ISNIL( 6 ) ? NULL : hb_param( 6, HB_IT_ANY ), /* RecID */ hb_param( 7, HB_IT_LOGICAL ), /* Rest */ - hb_parc( 10 ) ); /* Codepage */ + hb_parc( 10 ), /* Codepage */ + hb_param( 11, HB_IT_STRING ) );/* Delimiter */ } else { @@ -4407,7 +4466,8 @@ HB_FUNC( __DBCOPY ) hb_param( 5, HB_IT_NUMERIC ), /* Next */ ISNIL( 6 ) ? NULL : hb_param( 6, HB_IT_ANY ), /* RecID */ hb_param( 7, HB_IT_LOGICAL ), /* Rest */ - hb_parc( 10 ) ); /* Codepage */ + hb_parc( 10 ), /* Codepage */ + hb_param( 11, HB_IT_STRING ) );/* Delimiter */ } else { diff --git a/harbour/source/rdd/dbf1.c b/harbour/source/rdd/dbf1.c index 330f1f96e4..f2c423fa90 100644 --- a/harbour/source/rdd/dbf1.c +++ b/harbour/source/rdd/dbf1.c @@ -1098,6 +1098,11 @@ static ERRCODE hb_dbfAddField( DBFAREAP pArea, LPDBFIELDINFO pFieldInfo ) { HB_TRACE(HB_TR_DEBUG, ("hb_dbfAddField(%p, %p)", pArea, pFieldInfo)); + if( pFieldInfo->uiType == HB_IT_MEMO && pArea->bMemoType == DB_MEMO_SMT ) + { + pFieldInfo->uiLen = 10; + } + /* Update field offset */ pArea->pFieldOffset[ pArea->uiFieldCount ] = pArea->uiRecordLen; pArea->uiRecordLen += pFieldInfo->uiLen; @@ -1265,7 +1270,7 @@ static ERRCODE hb_dbfFlush( DBFAREAP pArea ) } /* - * Replace the current record. + * Retrieve current record buffer */ static ERRCODE hb_dbfGetRec( DBFAREAP pArea, BYTE ** pBuffer ) { @@ -1420,18 +1425,16 @@ static ERRCODE hb_dbfGetValue( DBFAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) if( pField->uiDec ) { hb_itemPutNDLen( pItem, fDbl ? dVal : ( double ) lVal, - ( int ) pField->uiLen - ( ( int ) pField->uiDec + 1 ), + ( int ) ( pField->uiLen - pField->uiDec - 1 ), ( int ) pField->uiDec ); } - else if( pField->uiLen > 9 ) + else if( fDbl ) { - hb_itemPutNDLen( pItem, fDbl ? dVal : ( double ) lVal, - ( int ) pField->uiLen, 0 ); + hb_itemPutNDLen( pItem, dVal, ( int ) pField->uiLen, 0 ); } else { - hb_itemPutNLLen( pItem, ( LONG ) ( fDbl ? dVal : lVal ), - ( int ) pField->uiLen ); + hb_itemPutNIntLen( pItem, lVal, ( int ) pField->uiLen ); } } break; @@ -1669,8 +1672,7 @@ static ERRCODE hb_dbfPutValue( DBFAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) memcpy( pArea->pRecord + pArea->pFieldOffset[ uiIndex ], hb_itemGetCPtr( pItem ), uiSize ); #ifndef HB_CDP_SUPPORT_OFF - if( HB_IS_STRING( pItem ) ) - hb_cdpnTranslate( (char *) pArea->pRecord + pArea->pFieldOffset[ uiIndex ], hb_cdp_page, pArea->cdPage, uiSize ); + hb_cdpnTranslate( (char *) pArea->pRecord + pArea->pFieldOffset[ uiIndex ], hb_cdp_page, pArea->cdPage, uiSize ); #endif memset( pArea->pRecord + pArea->pFieldOffset[ uiIndex ] + uiSize, ' ', pField->uiLen - uiSize ); @@ -1933,8 +1935,8 @@ static ERRCODE hb_dbfSetFieldExtent( DBFAREAP pArea, USHORT uiFieldExtent ) /* Alloc field offsets array */ if( uiFieldExtent ) { - pArea->pFieldOffset = ( USHORT * ) hb_xgrab( uiFieldExtent * sizeof( USHORT * ) ); - memset( pArea->pFieldOffset, 0, uiFieldExtent * sizeof( USHORT * ) ); + pArea->pFieldOffset = ( USHORT * ) hb_xgrab( uiFieldExtent * sizeof( USHORT ) ); + memset( pArea->pFieldOffset, 0, uiFieldExtent * sizeof( USHORT ) ); } return SUCCESS; @@ -2096,9 +2098,6 @@ static ERRCODE hb_dbfCreate( DBFAREAP pArea, LPDBOPENINFO pCreateInfo ) pArea->szDataFileName = hb_strdup( ( char * ) szFileName ); - /* Size for deleted flag */ - pArea->uiRecordLen = 1; - if( pArea->bTableType == 0 ) { pItem = hb_itemPutNI( pItem, 0 ); @@ -2162,6 +2161,9 @@ static ERRCODE hb_dbfCreate( DBFAREAP pArea, LPDBOPENINFO pCreateInfo ) pArea->fHasMemo = fError = FALSE; + /* Size for deleted flag */ + pArea->uiRecordLen = 1; + for( uiCount = 0; uiCount < pArea->uiFieldCount; uiCount++ ) { LPFIELD pField = pArea->lpFields + uiCount; @@ -2196,7 +2198,7 @@ static ERRCODE hb_dbfCreate( DBFAREAP pArea, LPDBOPENINFO pCreateInfo ) } pThisField->bLen = ( BYTE ) pField->uiLen; pThisField->bDec = 0; - pArea->uiRecordLen += pThisField->bLen; + pArea->uiRecordLen += pField->uiLen; pArea->fHasMemo = TRUE; break; @@ -2228,14 +2230,14 @@ static ERRCODE hb_dbfCreate( DBFAREAP pArea, LPDBOPENINFO pCreateInfo ) } pThisField->bLen = ( BYTE ) pField->uiLen; pThisField->bDec = 0; - pArea->uiRecordLen += pThisField->bLen; + pArea->uiRecordLen += pField->uiLen; break; case HB_IT_LONG: pThisField->bType = 'N'; pThisField->bLen = ( BYTE ) pField->uiLen; pThisField->bDec = ( BYTE ) pField->uiDec; - pArea->uiRecordLen += pThisField->bLen; + pArea->uiRecordLen += pField->uiLen; break; case HB_IT_DOUBLE: @@ -2243,7 +2245,7 @@ static ERRCODE hb_dbfCreate( DBFAREAP pArea, LPDBOPENINFO pCreateInfo ) pField->uiLen = 8; pThisField->bLen = ( BYTE ) pField->uiLen; pThisField->bDec = ( BYTE ) pField->uiDec; - pArea->uiRecordLen += pThisField->bLen; + pArea->uiRecordLen += pField->uiLen; break; case HB_IT_INTEGER: @@ -2255,7 +2257,7 @@ static ERRCODE hb_dbfCreate( DBFAREAP pArea, LPDBOPENINFO pCreateInfo ) } pThisField->bLen = ( BYTE ) pField->uiLen; pThisField->bDec = 0; - pArea->uiRecordLen += pThisField->bLen; + pArea->uiRecordLen += pField->uiLen; break; default: diff --git a/harbour/source/rdd/delim1.c b/harbour/source/rdd/delim1.c index b27f296b0f..349ac6f1f4 100644 --- a/harbour/source/rdd/delim1.c +++ b/harbour/source/rdd/delim1.c @@ -4,9 +4,9 @@ /* * Harbour Project source code: - * DELIMITED RDD module + * DELIM RDD * - * Copyright 1999 Bruno Cantero + * Copyright 2006 Przemyslaw Czerpak * www - http://www.harbour-project.org * * This program is free software; you can redistribute it and/or modify @@ -53,112 +53,1404 @@ #include "hbapi.h" #include "hbinit.h" #include "hbvm.h" +#include "hbset.h" +#include "hbdate.h" #include "hbapirdd.h" #include "hbapiitm.h" +#include "hbapilng.h" #include "hbapierr.h" +#include "hbdbferr.h" #include "hbrdddel.h" #include "rddsys.ch" +#define SUPERTABLE (&delimSuper) + static RDDFUNCS delimSuper; -static RDDFUNCS delimTable = { hb_delimBof, - hb_delimEof, - hb_delimFound, - hb_delimGoBottom, - hb_delimGoTo, - hb_delimGoToId, - hb_delimGoTop, - hb_delimSeek, - hb_delimSkip, - hb_delimSkipFilter, - hb_delimSkipRaw, - hb_delimAddField, - hb_delimAppend, - hb_delimCreateFields, - hb_delimDeleteRec, - hb_delimDeleted, - hb_delimFieldCount, - hb_delimFieldDisplay, - hb_delimFieldInfo, - hb_delimFieldName, - hb_delimFlush, - hb_delimGetRec, - hb_delimGetValue, - hb_delimGetVarLen, - hb_delimGoCold, - hb_delimGoHot, - hb_delimPutRec, - hb_delimPutValue, - hb_delimRecall, - hb_delimRecCount, - hb_delimRecInfo, - hb_delimRecNo, - hb_delimRecId, - hb_delimSetFieldExtent, - hb_delimAlias, - hb_delimClose, - hb_delimCreate, - hb_delimInfo, - hb_delimNewArea, - hb_delimOpen, - hb_delimRelease, - hb_delimStructSize, - hb_delimSysName, - hb_delimEval, - hb_delimPack, - hb_delimPackRec, - hb_delimSort, - hb_delimTrans, - hb_delimTransRec, - hb_delimZap, - hb_delimChildEnd, - hb_delimChildStart, - hb_delimChildSync, - hb_delimSyncChildren, - hb_delimClearRel, - hb_delimForceRel, - hb_delimRelArea, - hb_delimRelEval, - hb_delimRelText, - hb_delimSetRel, - hb_delimOrderListAdd, - hb_delimOrderListClear, - hb_delimOrderListDelete, - hb_delimOrderListFocus, - hb_delimOrderListRebuild, - hb_delimOrderCondition, - hb_delimOrderCreate, - hb_delimOrderDestroy, - hb_delimOrderInfo, - hb_delimClearFilter, - hb_delimClearLocate, - hb_delimClearScope, - hb_delimCountScope, - hb_delimFilterText, - hb_delimScopeInfo, - hb_delimSetFilter, - hb_delimSetLocate, - hb_delimSetScope, - hb_delimSkipScope, - hb_delimLocate, - hb_delimCompile, - hb_delimError, - hb_delimEvalBlock, - hb_delimRawLock, - hb_delimLock, - hb_delimUnLock, - hb_delimCloseMemFile, - hb_delimCreateMemFile, - hb_delimGetValueFile, - hb_delimOpenMemFile, - hb_delimPutValueFile, - hb_delimReadDBHeader, - hb_delimWriteDBHeader, - hb_delimInit, - hb_delimExit, - hb_delimDrop, - hb_delimExists, - hb_delimRddInfo, - hb_delimWhoCares +static USHORT s_uiNumLength[ 9 ] = { 0, 4, 6, 8, 11, 13, 16, 18, 20 }; + +static void hb_delimInitArea( DELIMAREAP pArea, char * szFileName ) +{ + /* Allocate only after succesfully open file */ + pArea->szFileName = hb_strdup( szFileName ); + + /* set line separator: EOL */ +#ifdef __XHARBOUR__ + if( hb_itemGetCLen( hb_set.HB_SET_EOL ) == 0 ) + pArea->szEol = hb_strdup( hb_conNewLine() ); + else + pArea->szEol = hb_strdup( hb_itemGetCPtr( hb_set.HB_SET_EOL ) ); +#else + pArea->szEol = hb_strdup( hb_conNewLine() ); +#endif + pArea->uiEolLen = strlen( pArea->szEol ); + + /* allocate record buffer, one additional byte is for deleted flag */ + pArea->pRecord = ( BYTE * ) hb_xgrab( pArea->uiRecordLen + 1 ); + /* pseudo deleted flag */ + *pArea->pRecord++ = ' '; + + /* Allocate IO buffer */ + pArea->ulBufferSize += pArea->uiEolLen; + pArea->pBuffer = ( BYTE * ) hb_xgrab( pArea->ulBufferSize ); + + pArea->ulRecCount = 0; + pArea->ulFileSize = 0; + pArea->ulBufferRead = pArea->ulBufferIndex = 0; +} + +static void hb_delimClearRecordBuffer( DELIMAREAP pArea ) +{ + memset( pArea->pRecord, ' ', pArea->uiRecordLen ); +} + +static ULONG hb_delimEncodeBuffer( DELIMAREAP pArea ) +{ + ULONG ulSize; + USHORT uiField, uiLen; + LPFIELD pField; + BYTE * pBuffer, * pFieldBuf; + + HB_TRACE(HB_TR_DEBUG, ("hb_delimEncodeBuffer(%p)", pArea)); + + /* mark the read buffer as empty */ + pArea->ulBufferRead = pArea->ulBufferIndex = 0; + + pBuffer = pArea->pBuffer; + ulSize = 0; + for( uiField = 0; uiField < pArea->uiFieldCount; ++uiField ) + { + pField = pArea->lpFields + uiField; + pFieldBuf = pArea->pRecord + pArea->pFieldOffset[ uiField ]; + if( ulSize ) + pBuffer[ ulSize++ ] = pArea->cSeparator; + + switch( pField->uiType ) + { + case HB_IT_STRING: + uiLen = pField->uiLen; + while( uiLen && pFieldBuf[ uiLen - 1 ] == ' ' ) + --uiLen; + if( pArea->fDelim ) + { + pBuffer[ ulSize++ ] = pArea->cDelim; + memcpy( pBuffer + ulSize, pFieldBuf, uiLen ); + ulSize += uiLen; + pBuffer[ ulSize++ ] = pArea->cDelim; + } + else + { + memcpy( pBuffer + ulSize, pFieldBuf, uiLen ); + ulSize += uiLen; + } + break; + + case HB_IT_LOGICAL: + pBuffer[ ulSize++ ] = ( *pFieldBuf == 'T' || *pFieldBuf == 't' || + *pFieldBuf == 'Y' || *pFieldBuf == 'y' ) ? + 'T' : 'F'; + break; + + case HB_IT_DATE: + uiLen = 0; + while( uiLen < 8 && pFieldBuf[ uiLen ] == ' ' ) + ++uiLen; + if( uiLen < 8 ) + { + memcpy( pBuffer + ulSize, pFieldBuf, 8 ); + ulSize += 8; + } + break; + + case HB_IT_LONG: + uiLen = 0; + while( uiLen < pField->uiLen && pFieldBuf[ uiLen ] == ' ' ) + ++uiLen; + if( uiLen < pField->uiLen ) + { + memcpy( pBuffer + ulSize, pFieldBuf + uiLen, pField->uiLen - uiLen ); + ulSize += pField->uiLen - uiLen; + } + else + { + pBuffer[ ulSize++ ] = '0'; + if( pField->uiDec ) + { + pBuffer[ ulSize++ ] = '.'; + memset( pBuffer + ulSize, '0', pField->uiDec ); + ulSize += pField->uiDec; + } + } + break; + + case HB_IT_MEMO: + default: + if( ulSize ) + --ulSize; + break; + } + } + memcpy( pBuffer + ulSize, pArea->szEol, pArea->uiEolLen ); + ulSize += pArea->uiEolLen; + + return ulSize; +} + +static int hb_delimNextChar( DELIMAREAP pArea ) +{ + if( pArea->ulBufferIndex + pArea->uiEolLen >= pArea->ulBufferRead && + ( pArea->ulBufferRead == 0 || + pArea->ulBufferRead >= pArea->ulBufferSize - 1 ) ) + { + USHORT uiLeft = ( USHORT ) pArea->ulBufferRead - pArea->ulBufferIndex; + + if( uiLeft ) + memcpy( pArea->pBuffer, + pArea->pBuffer + pArea->ulBufferIndex, uiLeft ); + pArea->ulBufferStart += pArea->ulBufferIndex; + pArea->ulBufferIndex = 0; + hb_fsSeekLarge( pArea->hFile, pArea->ulBufferStart + uiLeft, FS_SET ); + pArea->ulBufferRead = hb_fsReadLarge( pArea->hFile, + pArea->pBuffer + uiLeft, + pArea->ulBufferSize - uiLeft ); + if( pArea->ulBufferRead > 0 && + pArea->pBuffer[ pArea->ulBufferRead + uiLeft - 1 ] == '\032' ) + pArea->ulBufferRead--; + pArea->ulBufferRead += uiLeft; + } + + if( pArea->ulBufferIndex + pArea->uiEolLen <= pArea->ulBufferRead && + memcmp( pArea->pBuffer + pArea->ulBufferIndex, + pArea->szEol, pArea->uiEolLen ) == 0 ) + { + pArea->ulBufferIndex += pArea->uiEolLen; + pArea->ulNextOffset = pArea->ulBufferStart + pArea->ulBufferIndex; + return -1; + } + else if( pArea->ulBufferIndex < pArea->ulBufferRead ) + { + return pArea->pBuffer[ pArea->ulBufferIndex++ ]; + } + + pArea->ulNextOffset = ( HB_FOFFSET ) -1; + return -2; +} + +/* + * Read record, decode it to buffer and set next record offset + */ +static ERRCODE hb_delimReadRecord( DELIMAREAP pArea ) +{ + USHORT uiField, uiLen, uiSize; + HB_TYPE uiType; + LPFIELD pField; + BYTE * pFieldBuf, buffer[ 256 ]; + char cStop; + int ch = 0; + + HB_TRACE(HB_TR_DEBUG, ("hb_delimReadRecord(%p)", pArea)); + + if( pArea->ulBufferStart <= pArea->ulRecordOffset && + pArea->ulBufferStart + pArea->ulBufferRead > pArea->ulRecordOffset ) + { + pArea->ulBufferIndex = pArea->ulRecordOffset - pArea->ulBufferStart; + } + else + { + pArea->ulBufferStart = pArea->ulRecordOffset; + pArea->ulBufferRead = pArea->ulBufferIndex = 0; + } + + /* clear the record buffer */ + hb_delimClearRecordBuffer( pArea ); + + for( uiField = 0; uiField < pArea->uiFieldCount; ++uiField ) + { + pField = pArea->lpFields + uiField; + uiType = pField->uiType; + if( uiType == HB_IT_STRING || uiType == HB_IT_LOGICAL || + uiType == HB_IT_DATE || uiType == HB_IT_LONG ) + { + uiSize = 0; + uiLen = pField->uiLen; + pFieldBuf = pArea->pRecord + pArea->pFieldOffset[ uiField ]; + + /* ignore leading spaces */ + do + ch = hb_delimNextChar( pArea ); + while( ch == ' ' ); + + /* set the stop character */ + if( pArea->fDelim && ch == pArea->cDelim ) + { + cStop = pArea->cDelim; + ch = hb_delimNextChar( pArea ); + } + else + cStop = pArea->cSeparator; + + /* + * Clipper uses differ rules for character fields, they + * can be terminated only with valid stop character, when + * other fields also by length + */ + if( pField->uiType == HB_IT_STRING ) + { + while( ch >= 0 && ch != cStop ) + { + if( uiSize < uiLen ) + pFieldBuf[ uiSize++ ] = ( BYTE ) ch; + ch = hb_delimNextChar( pArea ); + } + } + else + { + while( ch >= 0 && ch != cStop && uiSize < uiLen ) + { + buffer[ uiSize++ ] = ( BYTE ) ch; + ch = hb_delimNextChar( pArea ); + } + buffer[ uiSize ] = '\0'; + + if( pField->uiType == HB_IT_LOGICAL ) + { + *pFieldBuf = ( *buffer == 'T' || *buffer == 't' || + *buffer == 'Y' || *buffer == 'y' ) ? 'T' : 'F'; + } + else if( pField->uiType == HB_IT_DATE ) + { + if( uiSize == 8 && hb_dateEncStr( ( char * ) buffer ) != 0 ) + memcpy( pFieldBuf, buffer, 8 ); + } + else + { + HB_LONG lVal; + double dVal; + BOOL fDbl; + + fDbl = hb_strnToNum( (const char *) buffer, uiSize, &lVal, &dVal ); + if( fDbl ) + pArea->valResult = hb_itemPutNDLen( pArea->valResult, dVal, + uiLen - pField->uiDec - 1, pField->uiDec ); + else + pArea->valResult = hb_itemPutNIntLen( pArea->valResult, + lVal, uiLen ); + hb_itemStrBuf( ( char * ) buffer, pArea->valResult, uiLen, pField->uiDec ); + /* TODO: RT error on width range */ + memcpy( pFieldBuf, buffer, uiLen ); + } + } + + /* ignore all character to the next field separator */ + while( ch >= 0 && ch != pArea->cSeparator ) + ch = hb_delimNextChar( pArea ); + + /* stop reading on EOL */ + if( ch < 0 ) + break; + } + + } + /* ignore all character to the end of line */ + while( ch >= 0 ) + ch = hb_delimNextChar( pArea ); + + if( ch == -2 && + pArea->ulRecordOffset == pArea->ulBufferStart + pArea->ulBufferIndex ) + { + pArea->fEof = TRUE; + pArea->fPositioned = FALSE; + } + else + { + pArea->fEof = FALSE; + pArea->fPositioned = TRUE; + } + + return SUCCESS; +} + +static ERRCODE hb_delimNextRecord( DELIMAREAP pArea ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_delimNextRecord(%p)", pArea)); + + if( pArea->fPositioned ) + { + if( pArea->ulNextOffset == ( HB_FOFFSET ) -1 ) + { + pArea->fEof = TRUE; + pArea->fPositioned = FALSE; + hb_delimClearRecordBuffer( pArea ); + } + else + { + pArea->ulRecNo++; + pArea->ulRecordOffset = pArea->ulNextOffset; + return hb_delimReadRecord( pArea ); + } + } + return SUCCESS; +} + +/* + * -- DELIM METHODS -- + */ + +/* + * Position cursor at the first record. + */ +static ERRCODE hb_delimGoTop( DELIMAREAP pArea ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_delimGoTop(%p)", pArea)); + + if( SELF_GOCOLD( ( AREAP ) pArea ) == FAILURE ) + return FAILURE; + + pArea->fTop = TRUE; + pArea->fBottom = FALSE; + + pArea->ulRecordOffset = 0; + pArea->ulRecNo = 1; + if( hb_delimReadRecord( pArea ) != SUCCESS ) + return FAILURE; + + return SELF_SKIPFILTER( ( AREAP ) pArea, 1 ); +} + +/* + * Reposition cursor, regardless of filter. + */ +static ERRCODE hb_delimSkipRaw( DELIMAREAP pArea, LONG lToSkip ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_delimSkipRaw(%p,%ld)", pArea, lToSkip)); + + if( SELF_GOCOLD( ( AREAP ) pArea ) == FAILURE ) + return FAILURE; + + if( lToSkip != 1 ) + return FAILURE; + else + return hb_delimNextRecord( pArea ); +} + +/* + * Determine deleted status for a record. + */ +static ERRCODE hb_delimDeleted( DELIMAREAP pArea, BOOL * pDeleted ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_delimDeleted(%p,%p)", pArea, pDeleted)); + + HB_SYMBOL_UNUSED( pArea ); + + * pDeleted = FALSE; + + return SUCCESS; +} + +/* + * Obtain number of records in WorkArea. + */ +static ERRCODE hb_delimRecCount( DELIMAREAP pArea, ULONG * pRecCount ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_delimRecCount(%p,%p)", pArea, pRecCount)); + + * pRecCount = pArea->ulRecCount; + + return SUCCESS; +} + +/* + * Obtain physical row number at current WorkArea cursor position. + */ +static ERRCODE hb_delimRecNo( DELIMAREAP pArea, ULONG * pulRecNo ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_delimRecNo(%p,%p)", pArea, pulRecNo)); + + *pulRecNo = pArea->ulRecNo; + + return SUCCESS; +} + +/* + * Obtain physical row ID at current WorkArea cursor position. + */ +static ERRCODE hb_delimRecId( DELIMAREAP pArea, PHB_ITEM pRecNo ) +{ + ERRCODE errCode; + ULONG ulRecNo; + + HB_TRACE(HB_TR_DEBUG, ("hb_delimRecId(%p,%p)", pArea, pRecNo)); + + errCode = SELF_RECNO( ( AREAP ) pArea, &ulRecNo ); + +#ifdef HB_C52_STRICT + /* this is for strict Clipper compatibility but IMHO Clipper should not + do that and always set fixed size independent to the record number */ + if( ulRecNo < 10000000 ) + { + hb_itemPutNLLen( pRecNo, ulRecNo, 7 ); + } + else + { + hb_itemPutNLLen( pRecNo, ulRecNo, 10 ); + } +#else + hb_itemPutNInt( pRecNo, ulRecNo ); +#endif + return errCode; +} + +/* + * Append a record to the WorkArea. + */ +static ERRCODE hb_delimAppend( DELIMAREAP pArea, BOOL fUnLockAll ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_delimAppend(%p,%d)", pArea, (int) fUnLockAll)); + + HB_SYMBOL_UNUSED( fUnLockAll ); + + if( SELF_GOCOLD( ( AREAP ) pArea ) == FAILURE ) + return FAILURE; + + if( SELF_GOHOT( ( AREAP ) pArea ) == FAILURE ) + return FAILURE; + + pArea->ulRecordOffset = pArea->ulFileSize; + pArea->ulRecNo = ++pArea->ulRecCount; + pArea->fEof = FALSE; + pArea->fPositioned = TRUE; + hb_delimClearRecordBuffer( pArea ); + + return SUCCESS; +} + +/* + * Delete a record. + */ +static ERRCODE hb_delimDeleteRec( DELIMAREAP pArea ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_delimDeleteRec(%p)", pArea)); + + if( pArea->fRecordChanged ) + { + pArea->ulRecCount--; + pArea->fEof = TRUE; + pArea->fPositioned = pArea->fRecordChanged = FALSE; + hb_delimClearRecordBuffer( pArea ); + } + + return SUCCESS; +} + +/* + * Obtain the current value of a field. + */ +static ERRCODE hb_delimGetValue( DELIMAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) +{ + LPFIELD pField; + + HB_TRACE(HB_TR_DEBUG, ("hb_delimGetValue(%p, %hu, %p)", pArea, uiIndex, pItem)); + + --uiIndex; + pField = pArea->lpFields + uiIndex; + switch( pField->uiType ) + { + case HB_IT_STRING: +#ifndef HB_CDP_SUPPORT_OFF + if( pArea->cdPage != hb_cdp_page ) + { + char * pVal = ( char * ) hb_xgrab( pField->uiLen + 1 ); + memcpy( pVal, pArea->pRecord + pArea->pFieldOffset[ uiIndex ], pField->uiLen ); + pVal[ pField->uiLen ] = '\0'; + hb_cdpnTranslate( pVal, pArea->cdPage, hb_cdp_page, pField->uiLen ); + hb_itemPutCPtr( pItem, pVal, pField->uiLen ); + } + else +#endif + { + hb_itemPutCL( pItem, ( char * ) pArea->pRecord + pArea->pFieldOffset[ uiIndex ], + pField->uiLen ); + } + break; + + case HB_IT_LOGICAL: + switch( pArea->pRecord[ pArea->pFieldOffset[ uiIndex ] ] ) + { + case 'T': + case 't': + case 'Y': + case 'y': + hb_itemPutL( pItem, TRUE ); + break; + default: + hb_itemPutL( pItem, FALSE ); + break; + } + break; + + case HB_IT_DATE: + { + char szBuffer[ 9 ]; + memcpy( szBuffer, pArea->pRecord + pArea->pFieldOffset[ uiIndex ], 8 ); + szBuffer[ 8 ] = 0; + hb_itemPutDS( pItem, szBuffer ); + } + break; + + case HB_IT_LONG: + { + HB_LONG lVal; + double dVal; + BOOL fDbl; + + fDbl = hb_strnToNum( (const char *) pArea->pRecord + pArea->pFieldOffset[ uiIndex ], + pField->uiLen, &lVal, &dVal ); + + + if( pField->uiDec ) + { + hb_itemPutNDLen( pItem, fDbl ? dVal : ( double ) lVal, + ( int ) ( pField->uiLen - pField->uiDec - 1 ), + ( int ) pField->uiDec ); + } + else if( fDbl ) + { + hb_itemPutNDLen( pItem, dVal, ( int ) pField->uiLen, 0 ); + } + else + { + hb_itemPutNIntLen( pItem, lVal, ( int ) pField->uiLen ); + } + } + break; + + case HB_IT_MEMO: + hb_itemPutC( pItem, "" ); + break; + + default: + { + PHB_ITEM pError; + pError = hb_errNew(); + hb_errPutGenCode( pError, EG_DATATYPE ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_DATATYPE ) ); + hb_errPutOperation( pError, hb_dynsymName( ( PHB_DYNS ) pField->sym ) ); + hb_errPutSubCode( pError, EDBF_DATATYPE ); + SELF_ERROR( ( AREAP ) pArea, pError ); + hb_itemRelease( pError ); + return FAILURE; + } + } + + return SUCCESS; +} + +/* + * Assign a value to a field. + */ +static ERRCODE hb_delimPutValue( DELIMAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) +{ + char szBuffer[ 256 ]; + ERRCODE uiError; + LPFIELD pField; + USHORT uiSize; + + HB_TRACE(HB_TR_DEBUG, ("hb_delimPutValue(%p,%hu,%p)", pArea, uiIndex, pItem)); + + if( !pArea->fPositioned ) + return SUCCESS; + + if( !pArea->fRecordChanged ) + return FAILURE; + + uiError = SUCCESS; + --uiIndex; + pField = pArea->lpFields + uiIndex; + if( pField->uiType != HB_IT_MEMO ) + { + if( HB_IS_MEMO( pItem ) || HB_IS_STRING( pItem ) ) + { + if( pField->uiType == HB_IT_STRING ) + { + uiSize = ( USHORT ) hb_itemGetCLen( pItem ); + if( uiSize > pField->uiLen ) + uiSize = pField->uiLen; + memcpy( pArea->pRecord + pArea->pFieldOffset[ uiIndex ], + hb_itemGetCPtr( pItem ), uiSize ); +#ifndef HB_CDP_SUPPORT_OFF + hb_cdpnTranslate( (char *) pArea->pRecord + pArea->pFieldOffset[ uiIndex ], hb_cdp_page, pArea->cdPage, uiSize ); +#endif + memset( pArea->pRecord + pArea->pFieldOffset[ uiIndex ] + uiSize, + ' ', pField->uiLen - uiSize ); + } + else + uiError = EDBF_DATATYPE; + } + else if( HB_IS_DATE( pItem ) ) + { + if( pField->uiType == HB_IT_DATE ) + { + hb_itemGetDS( pItem, szBuffer ); + memcpy( pArea->pRecord + pArea->pFieldOffset[ uiIndex ], szBuffer, 8 ); + } + else + uiError = EDBF_DATATYPE; + } + else if( HB_IS_NUMBER( pItem ) ) + { + if( pField->uiType == HB_IT_LONG ) + { + if( hb_itemStrBuf( szBuffer, pItem, pField->uiLen, pField->uiDec ) ) + { + memcpy( pArea->pRecord + pArea->pFieldOffset[ uiIndex ], + szBuffer, pField->uiLen ); + } + else + { + uiError = EDBF_DATAWIDTH; + memset( pArea->pRecord + pArea->pFieldOffset[ uiIndex ], + '*', pField->uiLen ); + } + } + else + uiError = EDBF_DATATYPE; + } + else if( HB_IS_LOGICAL( pItem ) ) + { + if( pField->uiType == HB_IT_LOGICAL ) + pArea->pRecord[ pArea->pFieldOffset[ uiIndex ] ] = hb_itemGetL( pItem ) ? 'T' : 'F'; + else + uiError = EDBF_DATATYPE; + } + else + uiError = EDBF_DATATYPE; + } + + if( uiError != SUCCESS ) + { + PHB_ITEM pError= hb_errNew(); + USHORT uiGenCode = uiError == EDBF_DATAWIDTH ? EG_DATAWIDTH : EDBF_DATATYPE; + + hb_errPutGenCode( pError, uiGenCode ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( uiGenCode ) ); + hb_errPutOperation( pError, hb_dynsymName( ( PHB_DYNS ) pField->sym ) ); + hb_errPutSubCode( pError, uiError ); + hb_errPutFlags( pError, EF_CANDEFAULT ); + SELF_ERROR( ( AREAP ) pArea, pError ); + hb_itemRelease( pError ); + return SUCCESS; + /* return FAILURE; */ + } + + return SUCCESS; +} + +/* + * Replace the current record. + */ +static ERRCODE hb_delimPutRec( DELIMAREAP pArea, BYTE * pBuffer ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_delimPutRec(%p,%p)", pArea, pBuffer)); + + if( !pArea->fPositioned ) + return SUCCESS; + + if( !pArea->fRecordChanged ) + return FAILURE; + + /* Copy data to buffer */ + memcpy( pArea->pRecord, pBuffer + 1, pArea->uiRecordLen ); + + return SUCCESS; +} + +/* + * Retrieve current record buffer + */ +static ERRCODE hb_delimGetRec( DELIMAREAP pArea, BYTE ** pBufferPtr ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_delimGetRec(%p,%p)", pArea, pBufferPtr)); + + *pBufferPtr = pArea->pRecord - 1; + + return SUCCESS; +} + +/* + * Copy one or more records from one WorkArea to another. + */ +static ERRCODE hb_delimTrans( DELIMAREAP pArea, LPDBTRANSINFO pTransInfo ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_delimTrans(%p, %p)", pArea, pTransInfo)); + + if( pTransInfo->uiFlags & DBTF_MATCH ) + { + if( !pArea->fTransRec || pArea->cdPage != pTransInfo->lpaDest->cdPage ) + pTransInfo->uiFlags &= ~DBTF_PUTREC; + else if( pArea->rddID == pTransInfo->lpaDest->rddID ) + pTransInfo->uiFlags |= DBTF_PUTREC; + else + { + PHB_ITEM pPutRec = hb_itemPutL( NULL, FALSE ); + SELF_INFO( ( AREAP ) pTransInfo->lpaDest, DBI_CANPUTREC, pPutRec ); + if( hb_itemGetL( pPutRec ) ) + pTransInfo->uiFlags |= DBTF_PUTREC; + else + pTransInfo->uiFlags &= ~DBTF_PUTREC; + hb_itemRelease( pPutRec ); + } + } + return SUPER_TRANS( ( AREAP ) pArea, pTransInfo ); +} + +/* + * Perform a write of WorkArea memory to the data store. + */ +static ERRCODE hb_delimGoCold( DELIMAREAP pArea ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_delimGoCold(%p)", pArea)); + + if( pArea->fRecordChanged ) + { + ULONG ulSize = hb_delimEncodeBuffer( pArea ); + + hb_fsSeekLarge( pArea->hFile, pArea->ulRecordOffset, FS_SET ); + if( hb_fsWriteLarge( pArea->hFile, pArea->pBuffer, ulSize ) != ulSize ) + { + PHB_ITEM pError = hb_errNew(); + + hb_errPutGenCode( pError, EG_WRITE ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_WRITE ) ); + hb_errPutSubCode( pError, EDBF_WRITE ); + hb_errPutOsCode( pError, hb_fsError() ); + hb_errPutFileName( pError, pArea->szFileName ); + SELF_ERROR( ( AREAP ) pArea, pError ); + hb_itemRelease( pError ); + return FAILURE; + } + pArea->ulFileSize += ulSize; + pArea->ulNextOffset = pArea->ulFileSize; + pArea->fRecordChanged = FALSE; + pArea->fFlush = TRUE; + } + return SUCCESS; +} + +/* + * Mark the WorkArea data buffer as hot. + */ +static ERRCODE hb_delimGoHot( DELIMAREAP pArea ) +{ + PHB_ITEM pError; + + HB_TRACE(HB_TR_DEBUG, ("hb_delimGoHot(%p)", pArea)); + + if( pArea->fReadonly ) + { + pError = hb_errNew(); + hb_errPutGenCode( pError, EG_READONLY ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_READONLY ) ); + hb_errPutSubCode( pError, EDBF_READONLY ); + SELF_ERROR( ( AREAP ) pArea, pError ); + hb_itemRelease( pError ); + return FAILURE; + } + pArea->fRecordChanged = TRUE; + return SUCCESS; +} + +/* + * Write data buffer to the data store. + */ +static ERRCODE hb_delimFlush( DELIMAREAP pArea ) +{ + ERRCODE uiError; + + HB_TRACE(HB_TR_DEBUG, ("hb_delimFlush(%p)", pArea)); + + uiError = SELF_GOCOLD( ( AREAP ) pArea ); + + if( pArea->fFlush ) + { + hb_fsSeekLarge( pArea->hFile, pArea->ulFileSize, FS_SET ); + hb_fsWrite( pArea->hFile, ( BYTE * ) "\032", 1 ); + if( hb_set.HB_SET_HARDCOMMIT ) + { + hb_fsCommit( pArea->hFile ); + pArea->fFlush = FALSE; + } + } + + return uiError; +} + +/* + * Retrieve information about the current table/driver. + */ +static ERRCODE hb_delimInfo( DELIMAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_delimInfo(%p,%hu,%p)", pArea, uiIndex, pItem)); + + switch( uiIndex ) + { + case DBI_CANPUTREC: + hb_itemPutL( pItem, pArea->fTransRec ); + break; + + case DBI_GETRECSIZE: + hb_itemPutNL( pItem, pArea->uiRecordLen ); + break; + + case DBI_GETDELIMITER: + { + char szDelim[ 2 ] = { pArea->cDelim, '\0' }; + hb_itemPutC( pItem, szDelim ); + break; + } + case DBI_SETDELIMITER: + if( hb_itemType( pItem ) & HB_IT_STRING ) + { + char * szDelim = hb_itemGetCPtr( pItem ); + if( hb_stricmp( szDelim, "BLANK" ) == 0 ) + { + pArea->fDelim = FALSE; + pArea->cDelim = '\0'; + pArea->cSeparator = ' '; + } + else if( *szDelim ) + pArea->cDelim = *szDelim; + } + break; + + case DBI_SEPARATOR: + { + char szSeparator[ 2 ] = { pArea->cSeparator, '\0' }; + char * szNew = hb_itemGetCPtr( pItem ); + if( *szNew ) + pArea->cSeparator = *szNew; + hb_itemPutC( pItem, szSeparator ); + break; + } + case DBI_FULLPATH: + hb_itemPutC( pItem, pArea->szFileName); + break; + + case DBI_FILEHANDLE: + hb_itemPutNInt( pItem, ( HB_LONG ) pArea->hFile ); + break; + + case DBI_SHARED: + hb_itemPutL( pItem, pArea->fShared ); + break; + + case DBI_ISREADONLY: + hb_itemPutL( pItem, pArea->fReadonly ); + break; + + case DBI_DB_VERSION: + case DBI_RDD_VERSION: + { + char szBuf[ 64 ]; + int iSub = hb_itemGetNI( pItem ); + + if( iSub == 1 ) + snprintf( szBuf, sizeof( szBuf ), "%d.%d (%s)", 0, 1, "DELIM" ); + else if( iSub == 2 ) + snprintf( szBuf, sizeof( szBuf ), "%d.%d (%s:%d)", 0, 1, "DELIM", pArea->rddID ); + else + snprintf( szBuf, sizeof( szBuf ), "%d.%d", 0, 1 ); + hb_itemPutC( pItem, szBuf ); + break; + } + + default: + return SUPER_INFO( ( AREAP ) pArea, uiIndex, pItem ); + } + + return SUCCESS; +} + +/* + * Add a field to the WorkArea. + */ +static ERRCODE hb_delimAddField( DELIMAREAP pArea, LPDBFIELDINFO pFieldInfo ) +{ + USHORT uiDelim = 0; + + HB_TRACE(HB_TR_DEBUG, ("hb_delimAddField(%p, %p)", pArea, pFieldInfo)); + + switch( pFieldInfo->uiType ) + { + case HB_IT_STRING: + uiDelim = 2; + break; + + case HB_IT_MEMO: + pFieldInfo->uiLen = 0; + pArea->fTransRec = FALSE; + break; + + case HB_IT_ANY: + if( pFieldInfo->uiLen == 3 ) + { + pFieldInfo->uiType = HB_IT_DATE; + pFieldInfo->uiLen = 8; + } + else if( pFieldInfo->uiLen < 6 ) + { + pFieldInfo->uiType = HB_IT_LONG; + pFieldInfo->uiLen = s_uiNumLength[ pFieldInfo->uiLen ]; + } + else + { + pFieldInfo->uiType = HB_IT_MEMO; + pFieldInfo->uiLen = 0; + } + pArea->fTransRec = FALSE; + break; + + case HB_IT_DATE: + if( pFieldInfo->uiLen != 8 ) + { + pFieldInfo->uiLen = 8; + pArea->fTransRec = FALSE; + } + break; + + case HB_IT_INTEGER: + pFieldInfo->uiType = HB_IT_LONG; + pFieldInfo->uiLen = s_uiNumLength[ pFieldInfo->uiLen ]; + pArea->fTransRec = FALSE; + break; + + case HB_IT_DOUBLE: + pFieldInfo->uiType = HB_IT_LONG; + pFieldInfo->uiLen = 20; + pArea->fTransRec = FALSE; + break; + } + + /* Update field offset */ + pArea->pFieldOffset[ pArea->uiFieldCount ] = pArea->uiRecordLen; + pArea->uiRecordLen += pFieldInfo->uiLen; + pArea->ulBufferSize += pFieldInfo->uiLen + uiDelim + 1; + + return SUPER_ADDFIELD( ( AREAP ) pArea, pFieldInfo ); +} + +/* + * Establish the extent of the array of fields for a WorkArea. + */ +static ERRCODE hb_delimSetFieldExtent( DELIMAREAP pArea, USHORT uiFieldExtent ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_delimSetFieldExtent(%p,%hu)", pArea, uiFieldExtent)); + + if( SUPER_SETFIELDEXTENT( ( AREAP ) pArea, uiFieldExtent ) == FAILURE ) + return FAILURE; + + /* Alloc field offsets array */ + if( uiFieldExtent ) + { + pArea->pFieldOffset = ( USHORT * ) hb_xgrab( uiFieldExtent * sizeof( USHORT ) ); + memset( pArea->pFieldOffset, 0, uiFieldExtent * sizeof( USHORT ) ); + } + + return SUCCESS; +} + +/* + * Clear the WorkArea for use. + */ +static ERRCODE hb_delimNewArea( DELIMAREAP pArea ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_delimNewArea(%p)", pArea)); + + if( SUPER_NEW( ( AREAP ) pArea ) == FAILURE ) + return FAILURE; + + pArea->hFile = FS_ERROR; + pArea->fTransRec = TRUE; + pArea->uiRecordLen = 0; + pArea->ulBufferSize = 0; + + /* set character field delimiter */ + pArea->fDelim = TRUE; + pArea->cDelim = '"'; + + /* set field delimiter */ + pArea->cSeparator = ','; + + return SUCCESS; +} + +/* + * Retrieve the size of the WorkArea structure. + */ +static ERRCODE hb_delimStructSize( DELIMAREAP pArea, USHORT * uiSize ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_delimStrucSize(%p,%p)", pArea, uiSize)); + HB_SYMBOL_UNUSED( pArea ); + + * uiSize = sizeof( DELIMAREA ); + return SUCCESS; +} + +/* + * Close the table in the WorkArea. + */ +static ERRCODE hb_delimClose( DELIMAREAP pArea ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_delimClose(%p)", pArea)); + + SUPER_CLOSE( ( AREAP ) pArea ); + + /* Update record and unlock records */ + if( pArea->hFile != FS_ERROR ) + { + SELF_FLUSH( ( AREAP ) pArea ); + hb_fsClose( pArea->hFile ); + pArea->hFile = FS_ERROR; + } + + if( pArea->pFieldOffset ) + { + hb_xfree( pArea->pFieldOffset ); + pArea->pFieldOffset = NULL; + } + if( pArea->pRecord ) + { + hb_xfree( pArea->pRecord - 1 ); + pArea->pRecord = NULL; + } + if( pArea->pBuffer ) + { + hb_xfree( pArea->pBuffer ); + pArea->pBuffer = NULL; + } + if( pArea->szEol ) + { + hb_xfree( pArea->szEol ); + pArea->szEol = NULL; + } + if( pArea->szFileName ) + { + hb_xfree( pArea->szFileName ); + pArea->szFileName = NULL; + } + + return SUCCESS; +} + +/* + * Create a data store in the specified WorkArea. + */ +static ERRCODE hb_delimCreate( DELIMAREAP pArea, LPDBOPENINFO pCreateInfo ) +{ + ERRCODE errCode = SUCCESS; + PHB_FNAME pFileName; + PHB_ITEM pError = NULL; + BOOL fRetry; + BYTE szFileName[ _POSIX_PATH_MAX + 1 ]; + + HB_TRACE(HB_TR_DEBUG, ("hb_delimCreate(%p,%p)", pArea, pCreateInfo)); + + pArea->fShared = FALSE; /* pCreateInfo->fShared; */ + pArea->fReadonly = FALSE; /* pCreateInfo->fReadonly */ +#ifndef HB_CDP_SUPPORT_OFF + if( pCreateInfo->cdpId ) + { + pArea->cdPage = hb_cdpFind( (char *) pCreateInfo->cdpId ); + if( !pArea->cdPage ) + pArea->cdPage = hb_cdp_page; + } + else + pArea->cdPage = hb_cdp_page; +#endif + + pFileName = hb_fsFNameSplit( ( char * ) pCreateInfo->abName ); + if( ! pFileName->szExtension ) + { + PHB_ITEM pItem = hb_itemPutC( NULL, "" ); + SELF_INFO( ( AREAP ) pArea, DBI_TABLEEXT, pItem ); + pFileName->szExtension = hb_itemGetCPtr( pItem ); + hb_fsFNameMerge( ( char * ) szFileName, pFileName ); + hb_itemRelease( pItem ); + } + else + { + hb_strncpy( ( char * ) szFileName, ( char * ) pCreateInfo->abName, _POSIX_PATH_MAX ); + } + hb_xfree( pFileName ); + + /* Try create */ + do + { + pArea->hFile = hb_fsExtOpen( szFileName, NULL, + FO_READWRITE | FO_EXCLUSIVE | FXO_TRUNCATE | + FXO_DEFAULTS | FXO_SHARELOCK | FXO_COPYNAME, + NULL, pError ); + if( pArea->hFile == FS_ERROR ) + { + if( !pError ) + { + pError = hb_errNew(); + hb_errPutGenCode( pError, EG_CREATE ); + hb_errPutSubCode( pError, EDBF_CREATE_DBF ); + hb_errPutOsCode( pError, hb_fsError() ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_CREATE ) ); + hb_errPutFileName( pError, ( char * ) szFileName ); + hb_errPutFlags( pError, EF_CANRETRY | EF_CANDEFAULT ); + } + fRetry = ( SELF_ERROR( ( AREAP ) pArea, pError ) == E_RETRY ); + } + else + fRetry = FALSE; + } + while( fRetry ); + + if( pError ) + hb_itemRelease( pError ); + + if( pArea->hFile == FS_ERROR ) + return FAILURE; + + errCode = SUPER_CREATE( ( AREAP ) pArea, pCreateInfo ); + if( errCode != SUCCESS ) + { + SELF_CLOSE( ( AREAP ) pArea ); + return errCode; + } + + hb_delimInitArea( pArea, ( char * ) szFileName ); + + /* Position cursor at the first record */ + return SELF_GOTOP( ( AREAP ) pArea ); +} + +/* + * Open a data store in the WorkArea. + */ +static ERRCODE hb_delimOpen( DELIMAREAP pArea, LPDBOPENINFO pOpenInfo ) +{ + PHB_ITEM pError = NULL; + PHB_FNAME pFileName; + ERRCODE errCode; + USHORT uiFlags; + BOOL fRetry; + BYTE szFileName[ _POSIX_PATH_MAX + 1 ]; + char szAlias[ HARBOUR_MAX_RDD_ALIAS_LENGTH + 1 ]; + + HB_TRACE(HB_TR_DEBUG, ("hb_delimOpen(%p,%p)", pArea, pOpenInfo)); + + pArea->fShared = TRUE; /* pOpenInfo->fShared; */ + pArea->fReadonly = TRUE; /* pOpenInfo->fReadonly; */ +#ifndef HB_CDP_SUPPORT_OFF + if( pOpenInfo->cdpId ) + { + pArea->cdPage = hb_cdpFind( (char *) pOpenInfo->cdpId ); + if( !pArea->cdPage ) + pArea->cdPage = hb_cdp_page; + } + else + pArea->cdPage = hb_cdp_page; +#endif + + uiFlags = ( pArea->fReadonly ? FO_READ : FO_READWRITE ) | + ( pArea->fShared ? FO_DENYNONE : FO_EXCLUSIVE ); + + pFileName = hb_fsFNameSplit( ( char * ) pOpenInfo->abName ); + /* Add default file name extension if necessary */ + if( ! pFileName->szExtension ) + { + PHB_ITEM pFileExt = hb_itemPutC( NULL, "" ); + SELF_INFO( ( AREAP ) pArea, DBI_TABLEEXT, pFileExt ); + pFileName->szExtension = hb_itemGetCPtr( pFileExt ); + hb_fsFNameMerge( ( char * ) szFileName, pFileName ); + hb_itemRelease( pFileExt ); + } + else + { + hb_strncpy( ( char * ) szFileName, ( char * ) pOpenInfo->abName, _POSIX_PATH_MAX ); + } + + /* Create default alias if necessary */ + if( !pOpenInfo->atomAlias && pFileName->szName ) + { + hb_strncpyUpperTrim( szAlias, pFileName->szName, HARBOUR_MAX_RDD_ALIAS_LENGTH ); + pOpenInfo->atomAlias = ( BYTE * ) szAlias; + } + hb_xfree( pFileName ); + + /* Try open */ + do + { + pArea->hFile = hb_fsExtOpen( szFileName, NULL, uiFlags | + FXO_DEFAULTS | FXO_SHARELOCK | FXO_COPYNAME, + NULL, pError ); + if( pArea->hFile == FS_ERROR ) + { + if( !pError ) + { + pError = hb_errNew(); + hb_errPutGenCode( pError, EG_OPEN ); + hb_errPutSubCode( pError, EDBF_OPEN_DBF ); + hb_errPutOsCode( pError, hb_fsError() ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_OPEN ) ); + hb_errPutFileName( pError, ( char * ) szFileName ); + hb_errPutFlags( pError, EF_CANRETRY | EF_CANDEFAULT ); + } + fRetry = ( SELF_ERROR( ( AREAP ) pArea, pError ) == E_RETRY ); + } + else + fRetry = FALSE; + } + while( fRetry ); + + if( pError ) + hb_itemRelease( pError ); + + if( pArea->hFile == FS_ERROR ) + return FAILURE; + + errCode = SUPER_OPEN( ( AREAP ) pArea, pOpenInfo ); + if( errCode != SUCCESS ) + { + SELF_CLOSE( ( AREAP ) pArea ); + return FAILURE; + } + + hb_delimInitArea( pArea, ( char * ) szFileName ); + + /* Position cursor at the first record */ + return SELF_GOTOP( ( AREAP ) pArea ); +} + +/* + * Retrieve information about the current driver. + */ +static ERRCODE hb_delimRddInfo( LPRDDNODE pRDD, USHORT uiIndex, ULONG ulConnect, PHB_ITEM pItem ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_delimRddInfo(%p,%hu,%lu,%p)", pRDD, uiIndex, ulConnect, pItem)); + + switch( uiIndex ) + { + case RDDI_CANPUTREC: + case RDDI_LOCAL: + case RDDI_LARGEFILE: + hb_itemPutL( pItem, TRUE ); + break; + + case RDDI_TABLEEXT: + hb_itemPutC( pItem, DELIM_TABLEEXT ); + break; + + default: + return SUPER_RDDINFO( pRDD, uiIndex, ulConnect, pItem ); + + } + + return SUCCESS; +} + + +static RDDFUNCS delimTable = { NULL /* hb_delimBof */, + NULL /* hb_delimEof */, + NULL /* hb_delimFound */, + NULL /* hb_delimGoBottom */, + NULL /* hb_delimGoTo */, + NULL /* hb_delimGoToId */, + ( DBENTRYP_V ) hb_delimGoTop, + NULL /* hb_delimSeek */, + NULL /* hb_delimSkip */, + NULL /* hb_delimSkipFilter */, + ( DBENTRYP_L ) hb_delimSkipRaw, + ( DBENTRYP_VF ) hb_delimAddField, + ( DBENTRYP_B ) hb_delimAppend, + NULL /* hb_delimCreateFields */, + ( DBENTRYP_V ) hb_delimDeleteRec, + ( DBENTRYP_BP ) hb_delimDeleted, + NULL /* hb_delimFieldCount */, + NULL /* hb_delimFieldDisplay */, + NULL /* hb_delimFieldInfo */, + NULL /* hb_delimFieldName */, + ( DBENTRYP_V ) hb_delimFlush, + ( DBENTRYP_PP ) hb_delimGetRec, + ( DBENTRYP_SI ) hb_delimGetValue, + NULL /* hb_delimGetVarLen */, + ( DBENTRYP_V ) hb_delimGoCold, + ( DBENTRYP_V ) hb_delimGoHot, + ( DBENTRYP_P ) hb_delimPutRec, + ( DBENTRYP_SI ) hb_delimPutValue, + NULL /* hb_delimRecall */, + ( DBENTRYP_ULP ) hb_delimRecCount, + NULL /* hb_delimRecInfo */, + ( DBENTRYP_ULP ) hb_delimRecNo, + ( DBENTRYP_I ) hb_delimRecId, + ( DBENTRYP_S ) hb_delimSetFieldExtent, + NULL /* hb_delimAlias */, + ( DBENTRYP_V ) hb_delimClose, + ( DBENTRYP_VP ) hb_delimCreate, + ( DBENTRYP_SI ) hb_delimInfo, + ( DBENTRYP_V ) hb_delimNewArea, + ( DBENTRYP_VP ) hb_delimOpen, + NULL /* hb_delimRelease */, + ( DBENTRYP_SP ) hb_delimStructSize, + NULL /* hb_delimSysName */, + NULL /* hb_delimEval */, + NULL /* hb_delimPack */, + NULL /* hb_delimPackRec */, + NULL /* hb_delimSort */, + ( DBENTRYP_VT ) hb_delimTrans, + NULL /* hb_delimTransRec */, + NULL /* hb_delimZap */, + NULL /* hb_delimChildEnd */, + NULL /* hb_delimChildStart */, + NULL /* hb_delimChildSync */, + NULL /* hb_delimSyncChildren */, + NULL /* hb_delimClearRel */, + NULL /* hb_delimForceRel */, + NULL /* hb_delimRelArea */, + NULL /* hb_delimRelEval */, + NULL /* hb_delimRelText */, + NULL /* hb_delimSetRel */, + NULL /* hb_delimOrderListAdd */, + NULL /* hb_delimOrderListClear */, + NULL /* hb_delimOrderListDelete */, + NULL /* hb_delimOrderListFocus */, + NULL /* hb_delimOrderListRebuild */, + NULL /* hb_delimOrderCondition */, + NULL /* hb_delimOrderCreate */, + NULL /* hb_delimOrderDestroy */, + NULL /* hb_delimOrderInfo */, + NULL /* hb_delimClearFilter */, + NULL /* hb_delimClearLocate */, + NULL /* hb_delimClearScope */, + NULL /* hb_delimCountScope */, + NULL /* hb_delimFilterText */, + NULL /* hb_delimScopeInfo */, + NULL /* hb_delimSetFilter */, + NULL /* hb_delimSetLocate */, + NULL /* hb_delimSetScope */, + NULL /* hb_delimSkipScope */, + NULL /* hb_delimLocate */, + NULL /* hb_delimCompile */, + NULL /* hb_delimError */, + NULL /* hb_delimEvalBlock */, + NULL /* hb_delimRawLock */, + NULL /* hb_delimLock */, + NULL /* hb_delimUnLock */, + NULL /* hb_delimCloseMemFile */, + NULL /* hb_delimCreateMemFile */, + NULL /* hb_delimGetValueFile */, + NULL /* hb_delimOpenMemFile */, + NULL /* hb_delimPutValueFile */, + NULL /* hb_delimReadDBHeader */, + NULL /* hb_delimWriteDBHeader */, + NULL /* hb_delimInit */, + NULL /* hb_delimExit */, + NULL /* hb_delimDrop */, + NULL /* hb_delimExists */, + ( DBENTRYP_RSLV ) hb_delimRddInfo, + NULL /* hb_delimWhoCares */ }; @@ -189,9 +1481,6 @@ HB_FUNC( DELIM_GETFUNCTABLE ) #define __PRG_SOURCE__ __FILE__ -HB_FUNC( DELIM ); -HB_FUNC( DELIM_GETFUNCTABLE ); - #ifdef HB_PCODE_VER #undef HB_PRG_PCODE_VER #define HB_PRG_PCODE_VER HB_PCODE_VER diff --git a/harbour/source/rdd/sdf1.c b/harbour/source/rdd/sdf1.c index 3869ebd400..697838a3e3 100644 --- a/harbour/source/rdd/sdf1.c +++ b/harbour/source/rdd/sdf1.c @@ -4,9 +4,9 @@ /* * Harbour Project source code: - * SDF RDD module + * SDF RDD * - * Copyright 1999 Bruno Cantero + * Copyright 2006 Przemyslaw Czerpak * www - http://www.harbour-project.org * * This program is free software; you can redistribute it and/or modify @@ -53,120 +53,1180 @@ #include "hbapi.h" #include "hbinit.h" #include "hbvm.h" +#include "hbset.h" #include "hbapirdd.h" #include "hbapiitm.h" +#include "hbapilng.h" #include "hbapierr.h" +#include "hbdbferr.h" #include "hbrddsdf.h" #include "rddsys.ch" -static RDDFUNCS sdfSuper; -static RDDFUNCS sdfTable = { hb_sdfBof, - hb_sdfEof, - hb_sdfFound, - hb_sdfGoBottom, - hb_sdfGoTo, - hb_sdfGoToId, - hb_sdfGoTop, - hb_sdfSeek, - hb_sdfSkip, - hb_sdfSkipFilter, - hb_sdfSkipRaw, - hb_sdfAddField, - hb_sdfAppend, - hb_sdfCreateFields, - hb_sdfDeleteRec, - hb_sdfDeleted, - hb_sdfFieldCount, - hb_sdfFieldDisplay, - hb_sdfFieldInfo, - hb_sdfFieldName, - hb_sdfFlush, - hb_sdfGetRec, - hb_sdfGetValue, - hb_sdfGetVarLen, - hb_sdfGoCold, - hb_sdfGoHot, - hb_sdfPutRec, - hb_sdfPutValue, - hb_sdfRecall, - hb_sdfRecCount, - hb_sdfRecInfo, - hb_sdfRecNo, - hb_sdfRecId, - hb_sdfSetFieldExtent, - hb_sdfAlias, - hb_sdfClose, - hb_sdfCreate, - hb_sdfInfo, - hb_sdfNewArea, - hb_sdfOpen, - hb_sdfRelease, - hb_sdfStructSize, - hb_sdfSysName, - hb_sdfEval, - hb_sdfPack, - hb_sdfPackRec, - hb_sdfSort, - hb_sdfTrans, - hb_sdfTransRec, - hb_sdfZap, - hb_sdfChildEnd, - hb_sdfChildStart, - hb_sdfChildSync, - hb_sdfSyncChildren, - hb_sdfClearRel, - hb_sdfForceRel, - hb_sdfRelArea, - hb_sdfRelEval, - hb_sdfRelText, - hb_sdfSetRel, - hb_sdfOrderListAdd, - hb_sdfOrderListClear, - hb_sdfOrderListDelete, - hb_sdfOrderListFocus, - hb_sdfOrderListRebuild, - hb_sdfOrderCondition, - hb_sdfOrderCreate, - hb_sdfOrderDestroy, - hb_sdfOrderInfo, - hb_sdfClearFilter, - hb_sdfClearLocate, - hb_sdfClearScope, - hb_sdfCountScope, - hb_sdfFilterText, - hb_sdfScopeInfo, - hb_sdfSetFilter, - hb_sdfSetLocate, - hb_sdfSetScope, - hb_sdfSkipScope, - hb_sdfLocate, - hb_sdfCompile, - hb_sdfError, - hb_sdfEvalBlock, - hb_sdfRawLock, - hb_sdfLock, - hb_sdfUnLock, - hb_sdfCloseMemFile, - hb_sdfCreateMemFile, - hb_sdfGetValueFile, - hb_sdfOpenMemFile, - hb_sdfPutValueFile, - hb_sdfReadDBHeader, - hb_sdfWriteDBHeader, - hb_sdfInit, - hb_sdfExit, - hb_sdfDrop, - hb_sdfExists, - hb_sdfRddInfo, - hb_sdfWhoCares - }; +#define SUPERTABLE (&sdfSuper) +static RDDFUNCS sdfSuper; +static USHORT s_uiNumLength[ 9 ] = { 0, 4, 6, 8, 11, 13, 16, 18, 20 }; + +static void hb_sdfInitArea( SDFAREAP pArea, char * szFileName ) +{ + /* Allocate only after succesfully open file */ + pArea->szFileName = hb_strdup( szFileName ); + +#ifdef __XHARBOUR__ + if( hb_itemGetCLen( hb_set.HB_SET_EOL ) == 0 ) + pArea->szEol = hb_strdup( hb_conNewLine() ); + else + pArea->szEol = hb_strdup( hb_itemGetCPtr( hb_set.HB_SET_EOL ) ); +#else + pArea->szEol = hb_strdup( hb_conNewLine() ); +#endif + pArea->uiEolLen = strlen( pArea->szEol ); + + /* Alloc buffer */ + pArea->pRecord = ( BYTE * ) hb_xgrab( pArea->uiRecordLen + pArea->uiEolLen + 3 ); + /* pseudo deleted flag */ + *pArea->pRecord++ = ' '; + + pArea->ulFileSize = 0; + pArea->ulRecCount = 0; +} + +static void hb_sdfClearRecordBuffer( SDFAREAP pArea ) +{ + memset( pArea->pRecord, ' ', pArea->uiRecordLen ); + memcpy( pArea->pRecord + pArea->uiRecordLen, + pArea->szEol, pArea->uiEolLen ); +} + +static ERRCODE hb_sdfReadRecord( SDFAREAP pArea ) +{ + USHORT uiRead, uiToRead, uiEolPos; + + HB_TRACE(HB_TR_DEBUG, ("hb_sdfReadRecord(%p)", pArea)); + + uiToRead = pArea->uiRecordLen + pArea->uiEolLen + 2; + hb_fsSeekLarge( pArea->hFile, pArea->ulRecordOffset, FS_SET ); + uiRead = hb_fsRead( pArea->hFile, pArea->pRecord, uiToRead ); + + if( uiRead > 0 && uiRead < uiToRead && pArea->pRecord[ uiRead - 1 ] == '\032' ) + --uiRead; + + if( uiRead == 0 ) + { + pArea->fEof = TRUE; + pArea->fPositioned = FALSE; + hb_sdfClearRecordBuffer( pArea ); + } + else + { + pArea->fEof = FALSE; + pArea->fPositioned = TRUE; + uiEolPos = hb_strAt( pArea->szEol, pArea->uiEolLen, + ( char * ) pArea->pRecord, uiRead ); + if( uiEolPos ) + { + --uiEolPos; + if( uiRead == pArea->uiRecordLen + pArea->uiEolLen ) + pArea->ulNextOffset = ( HB_FOFFSET ) -1; + else + pArea->ulNextOffset = pArea->ulRecordOffset + uiEolPos + pArea->uiEolLen; + + if( uiEolPos < pArea->uiRecordLen ) + memset( pArea->pRecord + uiEolPos, ' ', pArea->uiRecordLen - uiEolPos ); + } + else + { + if( uiRead < uiToRead ) + pArea->ulNextOffset = ( HB_FOFFSET ) -1; + else + pArea->ulNextOffset = 0; + + if( uiRead < pArea->uiRecordLen ) + memset( pArea->pRecord + uiRead, ' ', pArea->uiRecordLen - uiRead ); + } + + if( uiEolPos != pArea->uiRecordLen ) + memcpy( pArea->pRecord + pArea->uiRecordLen, + pArea->szEol, pArea->uiEolLen ); + } + + return SUCCESS; +} + +static ERRCODE hb_sdfNextRecord( SDFAREAP pArea ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_sdfNextRecord(%p)", pArea)); + + if( !pArea->fPositioned ) + pArea->ulNextOffset = ( HB_FOFFSET ) -1; + else + { + if( pArea->ulNextOffset == 0 ) + { + USHORT uiRead, uiToRead, uiEolPos, uiRest = 0; + HB_FOFFSET ulOffset = 0; + + uiToRead = pArea->uiRecordLen + pArea->uiEolLen + 2; + hb_fsSeekLarge( pArea->hFile, pArea->ulRecordOffset, FS_SET ); + + do + { + uiRead = hb_fsRead( pArea->hFile, pArea->pRecord + uiRest, + uiToRead - uiRest ) + uiRest; + if( uiRead > 0 && uiRead < uiToRead && + pArea->pRecord[ uiRead - 1 ] == '\032' ) + --uiRead; + + uiEolPos = hb_strAt( pArea->szEol, pArea->uiEolLen, + ( char * ) pArea->pRecord, uiRead ); + if( uiEolPos ) + { + --uiEolPos; + if( uiRead == pArea->uiRecordLen + pArea->uiEolLen ) + pArea->ulNextOffset = ( HB_FOFFSET ) -1; + else + pArea->ulNextOffset = pArea->ulRecordOffset + ulOffset + + uiEolPos + pArea->uiEolLen; + } + else if( uiRead < uiToRead ) + { + pArea->ulNextOffset = ( HB_FOFFSET ) -1; + } + else + { + if( pArea->uiEolLen > 1 ) + { + uiRest = pArea->uiEolLen - 1; + memcpy( pArea->pRecord, pArea->pRecord + uiRead - uiRest, uiRest ); + } + ulOffset += uiRead - uiRest; + } + } + while( pArea->ulNextOffset == 0 ); + } + pArea->ulRecNo++; + } + + if( pArea->ulNextOffset == ( HB_FOFFSET ) -1 ) + { + pArea->fEof = TRUE; + pArea->fPositioned = FALSE; + hb_sdfClearRecordBuffer( pArea ); + return SUCCESS; + } + + pArea->ulRecordOffset = pArea->ulNextOffset; + return hb_sdfReadRecord( pArea ); +} /* * -- SDF METHODS -- */ +/* + * Position cursor at the first record. + */ +static ERRCODE hb_sdfGoTop( SDFAREAP pArea ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_sdfGoTop(%p)", pArea)); + if( SELF_GOCOLD( ( AREAP ) pArea ) == FAILURE ) + return FAILURE; + + pArea->fTop = TRUE; + pArea->fBottom = FALSE; + + pArea->ulRecordOffset = 0; + pArea->ulRecNo = 1; + if( hb_sdfReadRecord( pArea ) != SUCCESS ) + return FAILURE; + + return SELF_SKIPFILTER( ( AREAP ) pArea, 1 ); +} + +/* + * Reposition cursor, regardless of filter. + */ +static ERRCODE hb_sdfSkipRaw( SDFAREAP pArea, LONG lToSkip ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_sdfSkipRaw(%p,%ld)", pArea, lToSkip)); + + if( SELF_GOCOLD( ( AREAP ) pArea ) == FAILURE ) + return FAILURE; + + if( lToSkip != 1 ) + return FAILURE; + else + return hb_sdfNextRecord( pArea ); +} + +/* + * Determine deleted status for a record. + */ +static ERRCODE hb_sdfDeleted( SDFAREAP pArea, BOOL * pDeleted ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_sdfDeleted(%p,%p)", pArea, pDeleted)); + + HB_SYMBOL_UNUSED( pArea ); + + * pDeleted = FALSE; + + return SUCCESS; +} + +/* + * Obtain number of records in WorkArea. + */ +static ERRCODE hb_sdfRecCount( SDFAREAP pArea, ULONG * pRecCount ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_sdfRecCount(%p,%p)", pArea, pRecCount)); + + * pRecCount = pArea->ulRecCount; + return SUCCESS; +} + +/* + * Obtain physical row number at current WorkArea cursor position. + */ +static ERRCODE hb_sdfRecNo( SDFAREAP pArea, ULONG * pulRecNo ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_sdfRecNo(%p,%p)", pArea, pulRecNo)); + + *pulRecNo = pArea->ulRecNo; + return SUCCESS; +} + +/* + * Obtain physical row ID at current WorkArea cursor position. + */ +static ERRCODE hb_sdfRecId( SDFAREAP pArea, PHB_ITEM pRecNo ) +{ + ERRCODE errCode; + ULONG ulRecNo; + + HB_TRACE(HB_TR_DEBUG, ("hb_sdfRecId(%p,%p)", pArea, pRecNo)); + + errCode = SELF_RECNO( ( AREAP ) pArea, &ulRecNo ); + +#ifdef HB_C52_STRICT + /* this is for strict Clipper compatibility but IMHO Clipper should not + do that and always set fixed size independent to the record number */ + if( ulRecNo < 10000000 ) + { + hb_itemPutNLLen( pRecNo, ulRecNo, 7 ); + } + else + { + hb_itemPutNLLen( pRecNo, ulRecNo, 10 ); + } +#else + hb_itemPutNInt( pRecNo, ulRecNo ); +#endif + return errCode; +} + +/* + * Append a record to the WorkArea. + */ +static ERRCODE hb_sdfAppend( SDFAREAP pArea, BOOL fUnLockAll ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_sdfAppend(%p,%d)", pArea, (int) fUnLockAll)); + + HB_SYMBOL_UNUSED( fUnLockAll ); + + if( SELF_GOCOLD( ( AREAP ) pArea ) == FAILURE ) + return FAILURE; + + if( SELF_GOHOT( ( AREAP ) pArea ) == FAILURE ) + return FAILURE; + + pArea->ulRecordOffset = pArea->ulFileSize; + pArea->ulRecNo = ++pArea->ulRecCount; + pArea->fEof = FALSE; + pArea->fPositioned = TRUE; + hb_sdfClearRecordBuffer( pArea ); + + return SUCCESS; +} + +/* + * Delete a record. + */ +static ERRCODE hb_sdfDeleteRec( SDFAREAP pArea ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_sdfDeleteRec(%p)", pArea)); + + if( pArea->fRecordChanged ) + { + pArea->ulRecCount--; + pArea->fEof = TRUE; + pArea->fPositioned = pArea->fRecordChanged = FALSE; + hb_sdfClearRecordBuffer( pArea ); + } + + return SUCCESS; +} + +/* + * Obtain the current value of a field. + */ +static ERRCODE hb_sdfGetValue( SDFAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) +{ + LPFIELD pField; + + HB_TRACE(HB_TR_DEBUG, ("hb_sdfGetValue(%p, %hu, %p)", pArea, uiIndex, pItem)); + + --uiIndex; + pField = pArea->lpFields + uiIndex; + switch( pField->uiType ) + { + case HB_IT_STRING: +#ifndef HB_CDP_SUPPORT_OFF + if( pArea->cdPage != hb_cdp_page ) + { + char * pVal = ( char * ) hb_xgrab( pField->uiLen + 1 ); + memcpy( pVal, pArea->pRecord + pArea->pFieldOffset[ uiIndex ], pField->uiLen ); + pVal[ pField->uiLen ] = '\0'; + hb_cdpnTranslate( pVal, pArea->cdPage, hb_cdp_page, pField->uiLen ); + hb_itemPutCPtr( pItem, pVal, pField->uiLen ); + } + else +#endif + { + hb_itemPutCL( pItem, ( char * ) pArea->pRecord + pArea->pFieldOffset[ uiIndex ], + pField->uiLen ); + } + break; + + case HB_IT_LOGICAL: + switch( pArea->pRecord[ pArea->pFieldOffset[ uiIndex ] ] ) + { + case 'T': + case 't': + case 'Y': + case 'y': + hb_itemPutL( pItem, TRUE ); + break; + default: + hb_itemPutL( pItem, FALSE ); + break; + } + break; + + case HB_IT_DATE: + { + char szBuffer[ 9 ]; + memcpy( szBuffer, pArea->pRecord + pArea->pFieldOffset[ uiIndex ], 8 ); + szBuffer[ 8 ] = 0; + hb_itemPutDS( pItem, szBuffer ); + } + break; + + case HB_IT_LONG: + { + HB_LONG lVal; + double dVal; + BOOL fDbl; + + fDbl = hb_strnToNum( (const char *) pArea->pRecord + pArea->pFieldOffset[ uiIndex ], + pField->uiLen, &lVal, &dVal ); + + if( pField->uiDec ) + { + hb_itemPutNDLen( pItem, fDbl ? dVal : ( double ) lVal, + ( int ) ( pField->uiLen - pField->uiDec - 1 ), + ( int ) pField->uiDec ); + } + else if( fDbl ) + { + hb_itemPutNDLen( pItem, dVal, ( int ) pField->uiLen, 0 ); + } + else + { + hb_itemPutNIntLen( pItem, lVal, ( int ) pField->uiLen ); + } + } + break; + + case HB_IT_MEMO: + hb_itemPutC( pItem, "" ); + break; + + default: + { + PHB_ITEM pError; + pError = hb_errNew(); + hb_errPutGenCode( pError, EG_DATATYPE ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_DATATYPE ) ); + hb_errPutOperation( pError, hb_dynsymName( ( PHB_DYNS ) pField->sym ) ); + hb_errPutSubCode( pError, EDBF_DATATYPE ); + SELF_ERROR( ( AREAP ) pArea, pError ); + hb_itemRelease( pError ); + return FAILURE; + } + } + + return SUCCESS; +} + +/* + * Assign a value to a field. + */ +static ERRCODE hb_sdfPutValue( SDFAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) +{ + char szBuffer[ 256 ]; + ERRCODE uiError; + LPFIELD pField; + USHORT uiSize; + + HB_TRACE(HB_TR_DEBUG, ("hb_sdfPutValue(%p,%hu,%p)", pArea, uiIndex, pItem)); + + if( !pArea->fPositioned ) + return SUCCESS; + + if( !pArea->fRecordChanged ) + return FAILURE; + + uiError = SUCCESS; + --uiIndex; + pField = pArea->lpFields + uiIndex; + if( pField->uiType != HB_IT_MEMO ) + { + if( HB_IS_MEMO( pItem ) || HB_IS_STRING( pItem ) ) + { + if( pField->uiType == HB_IT_STRING ) + { + uiSize = ( USHORT ) hb_itemGetCLen( pItem ); + if( uiSize > pField->uiLen ) + uiSize = pField->uiLen; + memcpy( pArea->pRecord + pArea->pFieldOffset[ uiIndex ], + hb_itemGetCPtr( pItem ), uiSize ); +#ifndef HB_CDP_SUPPORT_OFF + hb_cdpnTranslate( (char *) pArea->pRecord + pArea->pFieldOffset[ uiIndex ], hb_cdp_page, pArea->cdPage, uiSize ); +#endif + memset( pArea->pRecord + pArea->pFieldOffset[ uiIndex ] + uiSize, + ' ', pField->uiLen - uiSize ); + } + else + uiError = EDBF_DATATYPE; + } + else if( HB_IS_DATE( pItem ) ) + { + if( pField->uiType == HB_IT_DATE ) + { + hb_itemGetDS( pItem, szBuffer ); + memcpy( pArea->pRecord + pArea->pFieldOffset[ uiIndex ], szBuffer, 8 ); + } + else + uiError = EDBF_DATATYPE; + } + else if( HB_IS_NUMBER( pItem ) ) + { + if( pField->uiType == HB_IT_LONG ) + { + if( hb_itemStrBuf( szBuffer, pItem, pField->uiLen, pField->uiDec ) ) + { + memcpy( pArea->pRecord + pArea->pFieldOffset[ uiIndex ], + szBuffer, pField->uiLen ); + } + else + { + uiError = EDBF_DATAWIDTH; + memset( pArea->pRecord + pArea->pFieldOffset[ uiIndex ], + '*', pField->uiLen ); + } + } + else + uiError = EDBF_DATATYPE; + } + else if( HB_IS_LOGICAL( pItem ) ) + { + if( pField->uiType == HB_IT_LOGICAL ) + pArea->pRecord[ pArea->pFieldOffset[ uiIndex ] ] = hb_itemGetL( pItem ) ? 'T' : 'F'; + else + uiError = EDBF_DATATYPE; + } + else + uiError = EDBF_DATATYPE; + } + + if( uiError != SUCCESS ) + { + PHB_ITEM pError= hb_errNew(); + USHORT uiGenCode = uiError == EDBF_DATAWIDTH ? EG_DATAWIDTH : EDBF_DATATYPE; + + hb_errPutGenCode( pError, uiGenCode ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( uiGenCode ) ); + hb_errPutOperation( pError, hb_dynsymName( ( PHB_DYNS ) pField->sym ) ); + hb_errPutSubCode( pError, uiError ); + hb_errPutFlags( pError, EF_CANDEFAULT ); + SELF_ERROR( ( AREAP ) pArea, pError ); + hb_itemRelease( pError ); + return SUCCESS; + /* return FAILURE; */ + } + + return SUCCESS; +} + +/* + * Replace the current record. + */ +static ERRCODE hb_sdfPutRec( SDFAREAP pArea, BYTE * pBuffer ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_sdfPutRec(%p,%p)", pArea, pBuffer)); + + if( !pArea->fPositioned ) + return SUCCESS; + + if( !pArea->fRecordChanged ) + return FAILURE; + + /* Copy data to buffer */ + memcpy( pArea->pRecord, pBuffer + 1, pArea->uiRecordLen ); + + return SUCCESS; +} + +/* + * Retrieve current record buffer + */ +static ERRCODE hb_sdfGetRec( SDFAREAP pArea, BYTE ** pBufferPtr ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_sdfGetRec(%p,%p)", pArea, pBufferPtr)); + + *pBufferPtr = pArea->pRecord - 1; + + return SUCCESS; +} + +/* + * Copy one or more records from one WorkArea to another. + */ +static ERRCODE hb_sdfTrans( SDFAREAP pArea, LPDBTRANSINFO pTransInfo ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_sdfTrans(%p, %p)", pArea, pTransInfo)); + + if( pTransInfo->uiFlags & DBTF_MATCH ) + { + if( !pArea->fTransRec || pArea->cdPage != pTransInfo->lpaDest->cdPage ) + pTransInfo->uiFlags &= ~DBTF_PUTREC; + else if( pArea->rddID == pTransInfo->lpaDest->rddID ) + pTransInfo->uiFlags |= DBTF_PUTREC; + else + { + PHB_ITEM pPutRec = hb_itemPutL( NULL, FALSE ); + SELF_INFO( ( AREAP ) pTransInfo->lpaDest, DBI_CANPUTREC, pPutRec ); + if( hb_itemGetL( pPutRec ) ) + pTransInfo->uiFlags |= DBTF_PUTREC; + else + pTransInfo->uiFlags &= ~DBTF_PUTREC; + hb_itemRelease( pPutRec ); + } + } + return SUPER_TRANS( ( AREAP ) pArea, pTransInfo ); +} + +/* + * Perform a write of WorkArea memory to the data store. + */ +static ERRCODE hb_sdfGoCold( SDFAREAP pArea ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_sdfGoCold(%p)", pArea)); + + if( pArea->fRecordChanged ) + { + USHORT uiWrite = pArea->uiRecordLen + pArea->uiEolLen; + + hb_fsSeekLarge( pArea->hFile, pArea->ulRecordOffset, FS_SET ); + if( hb_fsWrite( pArea->hFile, pArea->pRecord, uiWrite ) != uiWrite ) + { + PHB_ITEM pError = hb_errNew(); + + hb_errPutGenCode( pError, EG_WRITE ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_WRITE ) ); + hb_errPutSubCode( pError, EDBF_WRITE ); + hb_errPutOsCode( pError, hb_fsError() ); + hb_errPutFileName( pError, pArea->szFileName ); + SELF_ERROR( ( AREAP ) pArea, pError ); + hb_itemRelease( pError ); + return FAILURE; + } + pArea->ulFileSize += uiWrite; + pArea->ulNextOffset = pArea->ulFileSize; + pArea->fRecordChanged = FALSE; + pArea->fFlush = TRUE; + } + return SUCCESS; +} + +/* + * Mark the WorkArea data buffer as hot. + */ +static ERRCODE hb_sdfGoHot( SDFAREAP pArea ) +{ + PHB_ITEM pError; + + HB_TRACE(HB_TR_DEBUG, ("hb_sdfGoHot(%p)", pArea)); + + if( pArea->fReadonly ) + { + pError = hb_errNew(); + hb_errPutGenCode( pError, EG_READONLY ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_READONLY ) ); + hb_errPutSubCode( pError, EDBF_READONLY ); + SELF_ERROR( ( AREAP ) pArea, pError ); + hb_itemRelease( pError ); + return FAILURE; + } + pArea->fRecordChanged = TRUE; + return SUCCESS; +} + +/* + * Write data buffer to the data store. + */ +static ERRCODE hb_sdfFlush( SDFAREAP pArea ) +{ + ERRCODE uiError; + + HB_TRACE(HB_TR_DEBUG, ("hb_sdfFlush(%p)", pArea)); + + uiError = SELF_GOCOLD( ( AREAP ) pArea ); + + if( pArea->fFlush ) + { + hb_fsSeekLarge( pArea->hFile, pArea->ulFileSize, FS_SET ); + hb_fsWrite( pArea->hFile, ( BYTE * ) "\032", 1 ); + if( hb_set.HB_SET_HARDCOMMIT ) + { + hb_fsCommit( pArea->hFile ); + pArea->fFlush = FALSE; + } + } + + return uiError; +} + +/* + * Retrieve information about the current table/driver. + */ +static ERRCODE hb_sdfInfo( SDFAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_sdfInfo(%p,%hu,%p)", pArea, uiIndex, pItem)); + + switch( uiIndex ) + { + case DBI_CANPUTREC: + hb_itemPutL( pItem, pArea->fTransRec ); + break; + + case DBI_GETRECSIZE: + hb_itemPutNL( pItem, pArea->uiRecordLen ); + break; + + case DBI_FULLPATH: + hb_itemPutC( pItem, pArea->szFileName); + break; + + case DBI_FILEHANDLE: + hb_itemPutNInt( pItem, ( HB_LONG ) pArea->hFile ); + break; + + case DBI_SHARED: + hb_itemPutL( pItem, pArea->fShared ); + break; + + case DBI_ISREADONLY: + hb_itemPutL( pItem, pArea->fReadonly ); + break; + + case DBI_DB_VERSION: + case DBI_RDD_VERSION: + { + char szBuf[ 64 ]; + int iSub = hb_itemGetNI( pItem ); + + if( iSub == 1 ) + snprintf( szBuf, sizeof( szBuf ), "%d.%d (%s)", 0, 1, "SDF" ); + else if( iSub == 2 ) + snprintf( szBuf, sizeof( szBuf ), "%d.%d (%s:%d)", 0, 1, "SDF", pArea->rddID ); + else + snprintf( szBuf, sizeof( szBuf ), "%d.%d", 0, 1 ); + hb_itemPutC( pItem, szBuf ); + break; + } + + default: + return SUPER_INFO( ( AREAP ) pArea, uiIndex, pItem ); + } + + return SUCCESS; +} + +/* + * Add a field to the WorkArea. + */ +static ERRCODE hb_sdfAddField( SDFAREAP pArea, LPDBFIELDINFO pFieldInfo ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_sdfAddField(%p, %p)", pArea, pFieldInfo)); + + switch( pFieldInfo->uiType ) + { + case HB_IT_MEMO: + pFieldInfo->uiLen = 0; + pArea->fTransRec = FALSE; + break; + + case HB_IT_ANY: + if( pFieldInfo->uiLen == 3 ) + { + pFieldInfo->uiType = HB_IT_DATE; + pFieldInfo->uiLen = 8; + } + else if( pFieldInfo->uiLen < 6 ) + { + pFieldInfo->uiType = HB_IT_LONG; + pFieldInfo->uiLen = s_uiNumLength[ pFieldInfo->uiLen ]; + } + else + { + pFieldInfo->uiType = HB_IT_MEMO; + pFieldInfo->uiLen = 0; + } + pArea->fTransRec = FALSE; + break; + + case HB_IT_DATE: + if( pFieldInfo->uiLen != 8 ) + { + pFieldInfo->uiLen = 8; + pArea->fTransRec = FALSE; + } + break; + + case HB_IT_INTEGER: + pFieldInfo->uiType = HB_IT_LONG; + pFieldInfo->uiLen = s_uiNumLength[ pFieldInfo->uiLen ]; + pArea->fTransRec = FALSE; + break; + + case HB_IT_DOUBLE: + pFieldInfo->uiType = HB_IT_LONG; + pFieldInfo->uiLen = 20; + pArea->fTransRec = FALSE; + break; + } + + /* Update field offset */ + pArea->pFieldOffset[ pArea->uiFieldCount ] = pArea->uiRecordLen; + pArea->uiRecordLen += pFieldInfo->uiLen; + + return SUPER_ADDFIELD( ( AREAP ) pArea, pFieldInfo ); +} + +/* + * Establish the extent of the array of fields for a WorkArea. + */ +static ERRCODE hb_sdfSetFieldExtent( SDFAREAP pArea, USHORT uiFieldExtent ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_sdfSetFieldExtent(%p,%hu)", pArea, uiFieldExtent)); + + if( SUPER_SETFIELDEXTENT( ( AREAP ) pArea, uiFieldExtent ) == FAILURE ) + return FAILURE; + + /* Alloc field offsets array */ + if( uiFieldExtent ) + { + pArea->pFieldOffset = ( USHORT * ) hb_xgrab( uiFieldExtent * sizeof( USHORT ) ); + memset( pArea->pFieldOffset, 0, uiFieldExtent * sizeof( USHORT ) ); + } + + return SUCCESS; +} + +/* + * Clear the WorkArea for use. + */ +static ERRCODE hb_sdfNewArea( SDFAREAP pArea ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_sdfNewArea(%p)", pArea)); + + if( SUPER_NEW( ( AREAP ) pArea ) == FAILURE ) + return FAILURE; + + pArea->hFile = FS_ERROR; + pArea->fTransRec = TRUE; + pArea->uiRecordLen = 0; + + return SUCCESS; +} + +/* + * Retrieve the size of the WorkArea structure. + */ +static ERRCODE hb_sdfStructSize( SDFAREAP pArea, USHORT * uiSize ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_sdfStrucSize(%p,%p)", pArea, uiSize)); + HB_SYMBOL_UNUSED( pArea ); + + * uiSize = sizeof( SDFAREA ); + return SUCCESS; +} + +/* + * Close the table in the WorkArea. + */ +static ERRCODE hb_sdfClose( SDFAREAP pArea ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_sdfClose(%p)", pArea)); + + SUPER_CLOSE( ( AREAP ) pArea ); + + /* Update record and unlock records */ + if( pArea->hFile != FS_ERROR ) + { + SELF_FLUSH( ( AREAP ) pArea ); + hb_fsClose( pArea->hFile ); + pArea->hFile = FS_ERROR; + } + + if( pArea->pFieldOffset ) + { + hb_xfree( pArea->pFieldOffset ); + pArea->pFieldOffset = NULL; + } + if( pArea->pRecord ) + { + hb_xfree( pArea->pRecord - 1 ); + pArea->pRecord = NULL; + } + if( pArea->szEol ) + { + hb_xfree( pArea->szEol ); + pArea->szEol = NULL; + } + if( pArea->szFileName ) + { + hb_xfree( pArea->szFileName ); + pArea->szFileName = NULL; + } + + return SUCCESS; +} + +/* + * Create a data store in the specified WorkArea. + */ +static ERRCODE hb_sdfCreate( SDFAREAP pArea, LPDBOPENINFO pCreateInfo ) +{ + ERRCODE errCode = SUCCESS; + PHB_FNAME pFileName; + PHB_ITEM pError = NULL; + BOOL fRetry; + BYTE szFileName[ _POSIX_PATH_MAX + 1 ]; + + HB_TRACE(HB_TR_DEBUG, ("hb_sdfCreate(%p,%p)", pArea, pCreateInfo)); + + pArea->fShared = FALSE; /* pCreateInfo->fShared; */ + pArea->fReadonly = FALSE; /* pCreateInfo->fReadonly */ +#ifndef HB_CDP_SUPPORT_OFF + if( pCreateInfo->cdpId ) + { + pArea->cdPage = hb_cdpFind( (char *) pCreateInfo->cdpId ); + if( !pArea->cdPage ) + pArea->cdPage = hb_cdp_page; + } + else + pArea->cdPage = hb_cdp_page; +#endif + + pFileName = hb_fsFNameSplit( ( char * ) pCreateInfo->abName ); + if( ! pFileName->szExtension ) + { + PHB_ITEM pItem = hb_itemPutC( NULL, "" ); + SELF_INFO( ( AREAP ) pArea, DBI_TABLEEXT, pItem ); + pFileName->szExtension = hb_itemGetCPtr( pItem ); + hb_fsFNameMerge( ( char * ) szFileName, pFileName ); + hb_itemRelease( pItem ); + } + else + { + hb_strncpy( ( char * ) szFileName, ( char * ) pCreateInfo->abName, _POSIX_PATH_MAX ); + } + hb_xfree( pFileName ); + + /* Try create */ + do + { + pArea->hFile = hb_fsExtOpen( szFileName, NULL, + FO_READWRITE | FO_EXCLUSIVE | FXO_TRUNCATE | + FXO_DEFAULTS | FXO_SHARELOCK | FXO_COPYNAME, + NULL, pError ); + if( pArea->hFile == FS_ERROR ) + { + if( !pError ) + { + pError = hb_errNew(); + hb_errPutGenCode( pError, EG_CREATE ); + hb_errPutSubCode( pError, EDBF_CREATE_DBF ); + hb_errPutOsCode( pError, hb_fsError() ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_CREATE ) ); + hb_errPutFileName( pError, ( char * ) szFileName ); + hb_errPutFlags( pError, EF_CANRETRY | EF_CANDEFAULT ); + } + fRetry = ( SELF_ERROR( ( AREAP ) pArea, pError ) == E_RETRY ); + } + else + fRetry = FALSE; + } + while( fRetry ); + + if( pError ) + hb_itemRelease( pError ); + + if( pArea->hFile == FS_ERROR ) + return FAILURE; + + errCode = SUPER_CREATE( ( AREAP ) pArea, pCreateInfo ); + if( errCode != SUCCESS ) + { + SELF_CLOSE( ( AREAP ) pArea ); + return errCode; + } + + hb_sdfInitArea( pArea, ( char * ) szFileName ); + + /* Position cursor at the first record */ + return SELF_GOTOP( ( AREAP ) pArea ); +} + +/* + * Open a data store in the WorkArea. + */ +static ERRCODE hb_sdfOpen( SDFAREAP pArea, LPDBOPENINFO pOpenInfo ) +{ + PHB_ITEM pError = NULL; + PHB_FNAME pFileName; + ERRCODE errCode; + USHORT uiFlags; + BOOL fRetry; + BYTE szFileName[ _POSIX_PATH_MAX + 1 ]; + char szAlias[ HARBOUR_MAX_RDD_ALIAS_LENGTH + 1 ]; + + HB_TRACE(HB_TR_DEBUG, ("hb_sdfOpen(%p,%p)", pArea, pOpenInfo)); + + pArea->fShared = TRUE; /* pOpenInfo->fShared; */ + pArea->fReadonly = TRUE; /* pOpenInfo->fReadonly; */ +#ifndef HB_CDP_SUPPORT_OFF + if( pOpenInfo->cdpId ) + { + pArea->cdPage = hb_cdpFind( (char *) pOpenInfo->cdpId ); + if( !pArea->cdPage ) + pArea->cdPage = hb_cdp_page; + } + else + pArea->cdPage = hb_cdp_page; +#endif + + uiFlags = ( pArea->fReadonly ? FO_READ : FO_READWRITE ) | + ( pArea->fShared ? FO_DENYNONE : FO_EXCLUSIVE ); + + pFileName = hb_fsFNameSplit( ( char * ) pOpenInfo->abName ); + /* Add default file name extension if necessary */ + if( ! pFileName->szExtension ) + { + PHB_ITEM pFileExt = hb_itemPutC( NULL, "" ); + SELF_INFO( ( AREAP ) pArea, DBI_TABLEEXT, pFileExt ); + pFileName->szExtension = hb_itemGetCPtr( pFileExt ); + hb_fsFNameMerge( ( char * ) szFileName, pFileName ); + hb_itemRelease( pFileExt ); + } + else + { + hb_strncpy( ( char * ) szFileName, ( char * ) pOpenInfo->abName, _POSIX_PATH_MAX ); + } + + /* Create default alias if necessary */ + if( !pOpenInfo->atomAlias && pFileName->szName ) + { + hb_strncpyUpperTrim( szAlias, pFileName->szName, HARBOUR_MAX_RDD_ALIAS_LENGTH ); + pOpenInfo->atomAlias = ( BYTE * ) szAlias; + } + hb_xfree( pFileName ); + + /* Try open */ + do + { + pArea->hFile = hb_fsExtOpen( szFileName, NULL, uiFlags | + FXO_DEFAULTS | FXO_SHARELOCK | FXO_COPYNAME, + NULL, pError ); + if( pArea->hFile == FS_ERROR ) + { + if( !pError ) + { + pError = hb_errNew(); + hb_errPutGenCode( pError, EG_OPEN ); + hb_errPutSubCode( pError, EDBF_OPEN_DBF ); + hb_errPutOsCode( pError, hb_fsError() ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_OPEN ) ); + hb_errPutFileName( pError, ( char * ) szFileName ); + hb_errPutFlags( pError, EF_CANRETRY | EF_CANDEFAULT ); + } + fRetry = ( SELF_ERROR( ( AREAP ) pArea, pError ) == E_RETRY ); + } + else + fRetry = FALSE; + } + while( fRetry ); + + if( pError ) + hb_itemRelease( pError ); + + if( pArea->hFile == FS_ERROR ) + return FAILURE; + + errCode = SUPER_OPEN( ( AREAP ) pArea, pOpenInfo ); + if( errCode != SUCCESS ) + { + SELF_CLOSE( ( AREAP ) pArea ); + return FAILURE; + } + + hb_sdfInitArea( pArea, ( char * ) szFileName ); + + /* Position cursor at the first record */ + return SELF_GOTOP( ( AREAP ) pArea ); +} + +/* + * Retrieve information about the current driver. + */ +static ERRCODE hb_sdfRddInfo( LPRDDNODE pRDD, USHORT uiIndex, ULONG ulConnect, PHB_ITEM pItem ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_sdfRddInfo(%p,%hu,%lu,%p)", pRDD, uiIndex, ulConnect, pItem)); + + switch( uiIndex ) + { + case RDDI_CANPUTREC: + case RDDI_LOCAL: + case RDDI_LARGEFILE: + hb_itemPutL( pItem, TRUE ); + break; + + case RDDI_TABLEEXT: + hb_itemPutC( pItem, SDF_TABLEEXT ); + break; + + default: + return SUPER_RDDINFO( pRDD, uiIndex, ulConnect, pItem ); + + } + + return SUCCESS; +} + + +static RDDFUNCS sdfTable = { NULL /* hb_sdfBof */, + NULL /* hb_sdfEof */, + NULL /* hb_sdfFound */, + NULL /* hb_sdfGoBottom */, + NULL /* hb_sdfGoTo */, + NULL /* hb_sdfGoToId */, + ( DBENTRYP_V ) hb_sdfGoTop, + NULL /* hb_sdfSeek */, + NULL /* hb_sdfSkip */, + NULL /* hb_sdfSkipFilter */, + ( DBENTRYP_L ) hb_sdfSkipRaw, + ( DBENTRYP_VF ) hb_sdfAddField, + ( DBENTRYP_B ) hb_sdfAppend, + NULL /* hb_sdfCreateFields */, + ( DBENTRYP_V ) hb_sdfDeleteRec, + ( DBENTRYP_BP ) hb_sdfDeleted, + NULL /* hb_sdfFieldCount */, + NULL /* hb_sdfFieldDisplay */, + NULL /* hb_sdfFieldInfo */, + NULL /* hb_sdfFieldName */, + ( DBENTRYP_V ) hb_sdfFlush, + ( DBENTRYP_PP ) hb_sdfGetRec, + ( DBENTRYP_SI ) hb_sdfGetValue, + NULL /* hb_sdfGetVarLen */, + ( DBENTRYP_V ) hb_sdfGoCold, + ( DBENTRYP_V ) hb_sdfGoHot, + ( DBENTRYP_P ) hb_sdfPutRec, + ( DBENTRYP_SI ) hb_sdfPutValue, + NULL /* hb_sdfRecall */, + ( DBENTRYP_ULP ) hb_sdfRecCount, + NULL /* hb_sdfRecInfo */, + ( DBENTRYP_ULP ) hb_sdfRecNo, + ( DBENTRYP_I ) hb_sdfRecId, + ( DBENTRYP_S ) hb_sdfSetFieldExtent, + NULL /* hb_sdfAlias */, + ( DBENTRYP_V ) hb_sdfClose, + ( DBENTRYP_VP ) hb_sdfCreate, + ( DBENTRYP_SI ) hb_sdfInfo, + ( DBENTRYP_V ) hb_sdfNewArea, + ( DBENTRYP_VP ) hb_sdfOpen, + NULL /* hb_sdfRelease */, + ( DBENTRYP_SP ) hb_sdfStructSize, + NULL /* hb_sdfSysName */, + NULL /* hb_sdfEval */, + NULL /* hb_sdfPack */, + NULL /* hb_sdfPackRec */, + NULL /* hb_sdfSort */, + ( DBENTRYP_VT ) hb_sdfTrans, + NULL /* hb_sdfTransRec */, + NULL /* hb_sdfZap */, + NULL /* hb_sdfChildEnd */, + NULL /* hb_sdfChildStart */, + NULL /* hb_sdfChildSync */, + NULL /* hb_sdfSyncChildren */, + NULL /* hb_sdfClearRel */, + NULL /* hb_sdfForceRel */, + NULL /* hb_sdfRelArea */, + NULL /* hb_sdfRelEval */, + NULL /* hb_sdfRelText */, + NULL /* hb_sdfSetRel */, + NULL /* hb_sdfOrderListAdd */, + NULL /* hb_sdfOrderListClear */, + NULL /* hb_sdfOrderListDelete */, + NULL /* hb_sdfOrderListFocus */, + NULL /* hb_sdfOrderListRebuild */, + NULL /* hb_sdfOrderCondition */, + NULL /* hb_sdfOrderCreate */, + NULL /* hb_sdfOrderDestroy */, + NULL /* hb_sdfOrderInfo */, + NULL /* hb_sdfClearFilter */, + NULL /* hb_sdfClearLocate */, + NULL /* hb_sdfClearScope */, + NULL /* hb_sdfCountScope */, + NULL /* hb_sdfFilterText */, + NULL /* hb_sdfScopeInfo */, + NULL /* hb_sdfSetFilter */, + NULL /* hb_sdfSetLocate */, + NULL /* hb_sdfSetScope */, + NULL /* hb_sdfSkipScope */, + NULL /* hb_sdfLocate */, + NULL /* hb_sdfCompile */, + NULL /* hb_sdfError */, + NULL /* hb_sdfEvalBlock */, + NULL /* hb_sdfRawLock */, + NULL /* hb_sdfLock */, + NULL /* hb_sdfUnLock */, + NULL /* hb_sdfCloseMemFile */, + NULL /* hb_sdfCreateMemFile */, + NULL /* hb_sdfGetValueFile */, + NULL /* hb_sdfOpenMemFile */, + NULL /* hb_sdfPutValueFile */, + NULL /* hb_sdfReadDBHeader */, + NULL /* hb_sdfWriteDBHeader */, + NULL /* hb_sdfInit */, + NULL /* hb_sdfExit */, + NULL /* hb_sdfDrop */, + NULL /* hb_sdfExists */, + ( DBENTRYP_RSLV ) hb_sdfRddInfo, + NULL /* hb_sdfWhoCares */ + }; HB_FUNC( SDF ) { ; } diff --git a/harbour/source/rdd/workarea.c b/harbour/source/rdd/workarea.c index c2e09f014a..feea968f6b 100644 --- a/harbour/source/rdd/workarea.c +++ b/harbour/source/rdd/workarea.c @@ -583,12 +583,13 @@ ERRCODE hb_waClose( AREAP pArea ) ERRCODE hb_waInfo( AREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) { HB_TRACE(HB_TR_DEBUG, ("hb_waInfo(%p, %hu, %p)", pArea, uiIndex, pItem)); - HB_SYMBOL_UNUSED( pArea ); switch ( uiIndex ) { case DBI_ISDBF: case DBI_CANPUTREC: + case DBI_ISFLOCK: + case DBI_SHARED: hb_itemPutL( pItem, FALSE ); break; @@ -601,6 +602,20 @@ ERRCODE hb_waInfo( AREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) hb_itemPutC( pItem, "" ); return FAILURE; + case DBI_GETHEADERSIZE: + case DBI_GETRECSIZE: + case DBI_LOCKCOUNT: + hb_itemPutNI( pItem, 0 ); + break; + + case DBI_LASTUPDATE: + hb_itemPutDL( pItem, 0 ); + break; + + case DBI_GETLOCKARRAY: + hb_arrayNew( pItem, 0 ); + break; + case DBI_CHILDCOUNT: { LPDBRELINFO lpdbRelations = pArea->lpdbRelations; @@ -648,6 +663,10 @@ ERRCODE hb_waInfo( AREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) break; } + case DBI_TABLEEXT: + hb_itemClear( pItem ); + return SELF_RDDINFO( SELF_RDDNODE( pArea ), RDDI_TABLEEXT, 0, pItem ); + case DBI_SCOPEDRELATION: { int iRelNo = hb_itemGetNI( pItem ); diff --git a/harbour/source/rtl/dbdelim.prg b/harbour/source/rtl/dbdelim.prg index 57d559d041..e93ee72bd6 100644 --- a/harbour/source/rtl/dbdelim.prg +++ b/harbour/source/rtl/dbdelim.prg @@ -11,6 +11,10 @@ * www - http://www.harbour-project.org * APPEND FROM code submitted by Marco Braida * + * Copyright 2006 Przemyslaw Czerpak + * function __dbDelim() replaced by the new one which uses + * DELIM RDD I've just created + * * 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) @@ -52,6 +56,21 @@ * */ +REQUEST DELIM + +PROCEDURE __dbDelim( lExport, cFile, cDelimArg, aFields, bFor, bWhile, nNext, nRecord, lRest ) + + IF lExport + __dbCopy( cFile, aFields, bFor, bWhile, nNext, nRecord, lRest, "DELIM", , , cDelimArg ) + ELSE + __dbApp( cFile, aFields, bFor, bWhile, nNext, nRecord, lRest, "DELIM", , , cDelimArg ) + ENDIF + +RETURN + + +#ifdef __DBDELIM_OLD_CODE__ + #include "hbcommon.ch" #include "fileio.ch" #include "error.ch" @@ -368,3 +387,5 @@ for ii:=1 to nDBFfields FIELDPUT(ii,vRes) next return .T. + +#endif /* __DBDELIM_OLD_CODE__ */ diff --git a/harbour/source/rtl/dbsdf.prg b/harbour/source/rtl/dbsdf.prg index d64115692f..d1cac4184c 100644 --- a/harbour/source/rtl/dbsdf.prg +++ b/harbour/source/rtl/dbsdf.prg @@ -10,6 +10,10 @@ * Copyright 2001-2002 David G. Holm * www - http://www.harbour-project.org * + * Copyright 2006 Przemyslaw Czerpak + * function __dbSDF() replaced by the new one which uses + * SDF RDD I've just created + * * 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) @@ -58,6 +62,21 @@ HB_FILE_VER( "$Id$" ) +REQUEST SDF + +PROCEDURE __dbSDF( lExport, cFile, aFields, bFor, bWhile, nNext, nRecord, lRest ) + + IF lExport + __dbCopy( cFile, aFields, bFor, bWhile, nNext, nRecord, lRest, "SDF" ) + ELSE + __dbApp( cFile, aFields, bFor, bWhile, nNext, nRecord, lRest, "SDF" ) + ENDIF + +RETURN + + +#ifdef __DBSDF_OLD_CODE__ + #define SkipEOL( handle ) FSEEK( handle, nEOLSize, FS_RELATIVE ) #define AppendEOL( handle ) FWRITE( handle, HB_OSNewLine() ) #define AppendEOF( handle ) FWRITE( handle, CHR( 26 ) ) @@ -287,3 +306,4 @@ STATIC FUNCTION FindEOL(fh) endif RETURN cResult +#endif /* __DBSDF_OLD_CODE__ */