* harbour/include/hbvm.h
* harbour/include/hbrdddbf.h
* harbour/include/hbapidbg.h
* harbour/include/hbset.h
* harbour/include/hbcomp.h
* harbour/include/hbapirdd.h
* harbour/include/hbstack.h
* harbour/include/hbsxfunc.h
* harbour/include/hbapilng.h
* harbour/include/hbgtcore.h
* harbour/include/hbapifs.h
* harbour/include/hbdbsort.h
* harbour/include/hbapigt.h
* harbour/include/hbapi.h
* harbour/include/hbapierr.h
* harbour/include/hbapiitm.h
* harbour/include/hbrddfpt.h
* harbour/contrib/hbmysql/mysql.c
* harbour/contrib/hbct/bitnum.c
* harbour/contrib/hbct/token2.c
* harbour/contrib/hbct/charsprd.c
* harbour/contrib/hbct/ctnet.c
* harbour/contrib/hbct/charonly.c
* harbour/contrib/hbct/atadjust.c
* harbour/contrib/hbct/ctwin.c
* harbour/contrib/hbct/charsort.c
* harbour/contrib/hbct/ctwin.h
* harbour/contrib/hbct/charmix.c
* harbour/contrib/hbct/charevod.c
* harbour/contrib/hbct/maxline.c
* harbour/contrib/hbct/wordrepl.c
* harbour/contrib/hbct/charrepl.c
* harbour/contrib/hbct/files.c
* harbour/contrib/hbct/video.c
* harbour/contrib/hbct/charswap.c
* harbour/contrib/hbct/dattime3.c
* harbour/contrib/hbct/charop.c
* harbour/contrib/hbct/misc2.c
* harbour/contrib/hbct/charone.c
* harbour/contrib/hbct/ctstr.c
* harbour/contrib/hbct/screen1.c
* harbour/contrib/hbct/token1.c
* harbour/contrib/hbct/ctstr.h
* harbour/contrib/hbct/charmirr.c
* harbour/contrib/hbct/relation.c
* harbour/contrib/hbct/atnum.c
* harbour/contrib/hbct/like.c
* harbour/contrib/hbct/count.c
* harbour/contrib/hbct/disk.c
* harbour/contrib/hbct/ctstrfil.c
* harbour/contrib/hbct/posdiff.c
* harbour/contrib/hbct/addascii.c
* harbour/contrib/hbct/tab.c
* harbour/contrib/hbct/numline.c
* harbour/contrib/hbct/dattime2.c
* harbour/contrib/hbct/asciisum.c
* harbour/contrib/hbct/expand.c
* harbour/contrib/hbct/pos2.c
* harbour/contrib/hbct/numat.c
* harbour/contrib/hbct/atrepl.c
* harbour/contrib/hbct/wordtoch.c
* harbour/contrib/hbct/print.c
* harbour/contrib/hbct/justify.c
* harbour/contrib/xhb/hbxml.c
* harbour/contrib/xhb/dbf2txt.c
* harbour/contrib/xhb/xhbis.c
* harbour/contrib/xhb/fparse.c
* harbour/contrib/xhb/xstrdel.c
* harbour/contrib/xhb/hbcomprs.c
* harbour/contrib/xhb/datesxhb.c
* harbour/contrib/xhb/xhbmsgs.c
* harbour/contrib/xhb/freadlin.c
* harbour/contrib/xhb/txtline.c
* harbour/contrib/xhb/xhbtrim.c
* harbour/contrib/xhb/xhbcopyf.c
* harbour/contrib/xhb/cstructc.c
* harbour/contrib/xhb/xhbfunc.c
* harbour/contrib/hbtpathy/tplinux.c
* harbour/contrib/hbgt/charmixg.c
* harbour/contrib/hbgt/strexpan.c
* harbour/contrib/hbgt/charodd.c
* harbour/contrib/hbgt/strright.c
* harbour/contrib/hbgt/asciisgt.c
* harbour/contrib/hbgt/strdiffg.c
* harbour/contrib/hbgt/chrtotal.c
* harbour/contrib/hbgt/strcount.c
* harbour/contrib/hbgt/strleft.c
* harbour/contrib/hbgt/ascposgt.c
* harbour/contrib/hbgt/chrfirst.c
* harbour/contrib/hbgt/chrcount.c
* harbour/contrib/hbgt/strpbrk.c
* harbour/contrib/hbgt/chareven.c
* harbour/contrib/hbgt/strcspn.c
* harbour/contrib/hbgt/atdiff.c
* harbour/contrib/hbsqlit3/hbsqlit3.c
* harbour/contrib/hbmzip/hbmzip.c
* harbour/contrib/hbnf/proper.c
* harbour/contrib/hbnf/fttext.c
* harbour/contrib/hbnf/chdir.c
* harbour/contrib/hbnf/getver.c
* harbour/contrib/hbnf/ftattr.c
* harbour/contrib/hbnf/mkdir.c
* harbour/contrib/hbnf/rmdir.c
* harbour/contrib/Makefile
* harbour/contrib/hbcurl/hbcurl.c
* harbour/contrib/rddsql/sddmy/mysqldd.c
* harbour/contrib/rddsql/sddpg/pgsqldd.c
* harbour/contrib/rddsql/sddfb/fbirddd.c
* harbour/contrib/rddsql/sddodbc/odbcdd.c
* harbour/contrib/rddsql/sqlmix.c
* harbour/contrib/hbhpdf/harupdf.c
* harbour/contrib/rddads/adsx.c
* harbour/contrib/rddads/adsfunc.c
* harbour/contrib/rddads/rddads.h
* harbour/contrib/rddads/ads1.c
* harbour/contrib/hbmisc/hb_f.c
* harbour/contrib/hbmisc/strfmt.c
* harbour/contrib/hbmisc/stringsx.c
* harbour/contrib/hbmisc/spd.c
* harbour/contrib/hbtip/utils.c
* harbour/contrib/hbwin/wapi_winbase.c
* harbour/contrib/hbwin/win_misc.c
* harbour/contrib/hbbtree/hb_btree.h
* harbour/contrib/hbbtree/hb_btree.c
* harbour/source/pp/hbpp.c
* harbour/source/vm/runner.c
* harbour/source/vm/estack.c
* harbour/source/vm/itemapi.c
* harbour/source/vm/hvm.c
* harbour/source/vm/cmdarg.c
* harbour/source/vm/memvars.c
* harbour/source/vm/dynlibhb.c
* harbour/source/vm/set.c
* harbour/source/main/harbour.c
* harbour/source/debug/dbgentry.c
* harbour/source/common/hbfsapi.c
* harbour/source/common/hbfopen.c
* harbour/source/rtl/gtdos/gtdos.c
* harbour/source/rtl/diskspac.c
* harbour/source/rtl/console.c
* harbour/source/rtl/chrasc.c
* harbour/source/rtl/fscopy.c
* harbour/source/rtl/run.c
* harbour/source/rtl/spfiles.c
* harbour/source/rtl/defpath.c
* harbour/source/rtl/philes.c
* harbour/source/rtl/oldbox.c
* harbour/source/rtl/math.c
* harbour/source/rtl/hbgtcore.c
* harbour/source/rtl/cdpapi.c
* harbour/source/rtl/gtcrs/gtcrs.c
* harbour/source/rtl/dirdrive.c
* harbour/source/rtl/hbi18n1.c
* harbour/source/rtl/trim.c
* harbour/source/rtl/hbzlibgz.c
* harbour/source/rtl/philesx.c
* harbour/source/rtl/mlcfunc.c
* harbour/source/rtl/filehb.c
* harbour/source/rtl/fstemp.c
* harbour/source/rtl/is.c
* harbour/source/rtl/hbrunfun.c
* harbour/source/rtl/ampm.c
* harbour/source/rtl/setcolor.c
* harbour/source/rtl/oemansi.c
* harbour/source/rtl/disksphb.c
* harbour/source/rtl/hbzlib.c
* harbour/source/rtl/strpeek.c
* harbour/source/rtl/replic.c
* harbour/source/rtl/stuff.c
* harbour/source/rtl/hbstrfmt.c
* harbour/source/rtl/transfrm.c
* harbour/source/rtl/hbhex.c
* harbour/source/rtl/trace.c
* harbour/source/rtl/hbadler.c
* harbour/source/rtl/samples.c
* harbour/source/rtl/filebuf.c
* harbour/source/rtl/hbcrc.c
* harbour/source/rtl/gete.c
* harbour/source/rtl/hbmd5.c
* harbour/source/rtl/langapi.c
* harbour/source/rtl/gtcgi/gtcgi.c
* harbour/source/rtl/errapi.c
* harbour/source/rtl/hbregexc.c
* harbour/source/rtl/natmsg.c
* harbour/source/rtl/fssize.c
* harbour/source/rtl/hbinet.c
* harbour/source/rtl/colorind.c
* harbour/source/rtl/copyfile.c
* harbour/source/rtl/mouseapi.c
* harbour/source/rtl/soundex.c
* harbour/source/rtl/memofile.c
* harbour/source/rtl/hbffind.c
* harbour/source/rtl/gtapi.c
* harbour/source/rtl/direct.c
* harbour/source/rtl/filesys.c
* harbour/source/rtl/file.c
* harbour/source/rtl/val.c
* harbour/source/rtl/hbregex.c
* harbour/source/rtl/rat.c
* harbour/source/rtl/isprint.c
* harbour/source/rdd/dbfntx/dbfntx1.c
* harbour/source/rdd/dbsql.c
* harbour/source/rdd/workarea.c
* harbour/source/rdd/wacore.c
* harbour/source/rdd/sdf1.c
* harbour/source/rdd/dbdetach.c
* harbour/source/rdd/dbcmdx.c
* harbour/source/rdd/dbfnsx/dbfnsx1.c
* harbour/source/rdd/dbcmd.c
* harbour/source/rdd/dbfcdx/dbfcdx1.c
* harbour/source/rdd/delim1.c
* harbour/source/rdd/dbf1.c
* harbour/source/rdd/hsx/hsx.c
* harbour/source/rdd/dbcmd53.c
* harbour/source/rdd/usrrdd/usrrdd.c
* harbour/source/rdd/wafunc.c
* harbour/source/rdd/dbffpt/dbffpt1.c
* harbour/source/rdd/hbsix/sxsem.c
* harbour/source/rdd/hbsix/sxord.c
* harbour/source/rdd/hbsix/sxfname.c
* harbour/source/rdd/hbsix/sxtable.c
* harbour/source/rdd/hbsix/sxdate.c
* harbour/source/rdd/hbsix/sxutil.c
* harbour/source/rdd/hbsix/sxcompr.c
* harbour/source/compiler/hbmain.c
* harbour/source/compiler/cmdcheck.c
* harbour/source/compiler/hbpcode.c
* harbour/source/compiler/genc.c
* harbour/source/compiler/gencc.c
* harbour/source/compiler/hbcmplib.c
* harbour/source/compiler/ppcomp.c
* changed 'char *' and changed 'BYTE *' to 'const char *' in
the following functions:
const char * hb_vmFindModuleSymbolName( PHB_SYMB pSym );
void hb_vmInitSymbolGroup( void * hNewDynLib, int argc,
const char * argv[] );
void hb_dbgEntry( int nMode, int nLine, const char *szName,
int nIndex, PHB_ITEM pFrame );
void hb_dbgAddBreak( void *handle, const char *cModule,
int nLine, const char *szFunction );
void hb_dbgAddWatch( void *handle, const char *szExpr, BOOL bTrace );
PHB_ITEM hb_dbgGetExpressionValue( void *handle,
const char *expression );
BOOL hb_dbgIsValidStopLine( void *handle, const char *szModule,
int nLine );
void hb_dbgSetToCursor( void *handle, const char *szModule,
int nLine );
void hb_dbgSetWatch( void *handle, int nWatch,
const char *szExpr, BOOL bTrace );
const char * hb_setGetCPtr( HB_set_enum set_specifier );
const char * hb_setGetAltFile( void );
const char * hb_setGetDateFormat( void );
const char * hb_setGetTimeFormat( void );
const char * hb_setGetDefault( void );
const char * hb_setGetDelimChars( void );
const char * hb_setGetDevice( void );
const char * hb_setGetExtraFile( void );
const char * hb_setGetPath( void );
const char * hb_setGetMFileExt( void );
const char * hb_setGetPrintFile( void );
const char * hb_setGetEOL( void );
const char * hb_setGetHBOUTLOG( void );
const char * hb_setGetHBOUTLOGINFO( void );
const char * hb_setGetOSCODEPAGE( void );
void hb_compInitPP( HB_COMP_DECL, int argc,
const char * const argv[] );
void hb_compGenPCodeN( const BYTE * pBuffer, ULONG ulSize,
HB_COMP_DECL );
int hb_compMain( int argc, const char * const argv[],
BYTE ** pBufPtr, ULONG * pulSize,
const char * szSource );
void hb_compChkCompilerSwitch( HB_COMP_DECL, int,
const char * const args[] );
void hb_compChkDefines( HB_COMP_DECL, int iArg,
const char * const args[] );
void hb_compGenCString( FILE * yyc, const BYTE * pText, ULONG ulLen );
AREAP hb_rddRequestArea( const char * szAlias, PHB_ITEM pCargo,
BOOL fNewArea, BOOL fWait );
char * hb_stackDirBuffer( void );
LONG hb_sxPtoD( const char * pDate );
const char * hb_langID( void );
const char * hb_langSelectID( const char * pszID );
const char * hb_langDGetItem( int iIndex );
const char * hb_langDGetErrorDesc( ULONG ulIndex );
BOOL hb_fsChDir( const char * pszDirName );
HB_FHANDLE hb_fsCreate( const char * pszFileName, ULONG ulAttr );
HB_FHANDLE hb_fsCreateEx( const char * pszFilename, ULONG ulAttr,
USHORT uiFlags );
HB_FHANDLE hb_fsCreateTemp( const char * pszDir,
const char * pszPrefix,
ULONG ulAttr, char * pszName );
HB_FHANDLE hb_fsCreateTempEx( char * pszName, const char * pszDir,
const char * pszPrefix,
const char * pszExt, ULONG ulAttr );
const char * hb_fsCurDir( USHORT uiDrive );
USHORT hb_fsCurDirBuff( USHORT uiDrive, char * pbyBuffer,
ULONG ulLen );
void hb_fsBaseDirBuff( char * pbyBuffer );
BOOL hb_fsDelete( const char * pszFileName );
BOOL hb_fsFile( const char * pszFileName );
BOOL hb_fsIsDirectory( const char * pszFilename );
HB_FOFFSET hb_fsFSize( const char * pszFileName, BOOL bUseDirEntry );
HB_FHANDLE hb_fsExtOpen( const char * pszFileName,
const char * pDefExt,
char * hb_fsExtName( const char * pFilename,
const char * pDefExt, USHORT uiExFlags,
const char * pPaths );
BOOL hb_fsMkDir( const char * pszDirName );
HB_FHANDLE hb_fsOpen( const char * pszFileName, USHORT uiFlags );
BOOL hb_fsRmDir( const char * pszDirName );
BOOL hb_fsRename( const char * pszOldName,
const char * pszNewName );
BOOL hb_fsGetFileTime( const char * pszFileName,
LONG * plJulian, LONG * plMillisec );
BOOL hb_fsSetFileTime( const char * pszFileName,
LONG lJulian, LONG lMillisec );
BOOL hb_fsGetAttr( const char * pszFileName, ULONG * pulAttr );
BOOL hb_fsSetAttr( const char * pszFileName, ULONG ulAttr );
HB_FHANDLE hb_fsPOpen( const char * pFilename, const char * pMode );
BOOL hb_fsCopy( const char * pSource, const char * pDest );
BOOL hb_spFile( const char * pFilename, char * pRetPath );
BOOL hb_spFileExists( const char * pFilename, char * pRetPath );
HB_FHANDLE hb_spOpen( const char * pFilename, USHORT uiFlags );
HB_FHANDLE hb_spCreate( const char * pFilename, ULONG ulAttr );
HB_FHANDLE hb_spCreateEx( const char * pFilename,
ULONG ulAttr, USHORT uiFlags );
PHB_FILE hb_fileExtOpen( const char * pFilename,
const char * pDefExt, USHORT uiExFlags,
const char * pPaths, PHB_ITEM pError );
PHB_FILE hb_fileCreateTemp( const char * pszDir,
const char * pszPrefix,
ULONG ulAttr, char * pszName );
PHB_FILE hb_fileCreateTempEx( char * pszName, const char * pszDir,
const char * pszPrefix,
const char * pszExt, ULONG ulAttr );
HB_ERRCODE hb_gtBox( SHORT uiTop, SHORT uiLeft, SHORT uiBottom,
SHORT uiRight, const BYTE * pbyFrame );
HB_ERRCODE hb_gtDrawBox( SHORT uiTop, SHORT uiLeft, SHORT uiBottom,
SHORT uiRight, const BYTE * pbyFrame,
int iColor );
HB_ERRCODE hb_gtWrite( const BYTE * pbyStr, ULONG ulLen );
HB_ERRCODE hb_gtWriteAt( USHORT uiRow, USHORT uiCol,
const BYTE * pbyStr, ULONG ulLen );
HB_ERRCODE hb_gtWriteCon( const BYTE * pbyStr, ULONG ulLen );
HB_ERRCODE hb_gtPutText( USHORT uiRow, USHORT uiCol,
const BYTE * pStr, ULONG ulLength,
int iColor );
HB_ERRCODE hb_gtOutStd( const BYTE * pbyStr, ULONG ulLen );
HB_ERRCODE hb_gtOutErr( const BYTE * pbyStr, ULONG ulLen );
HB_ERRCODE hb_gtBoxEx( int iTop, int iLeft, int iBottom, int iRight,
const BYTE * pbyFrame, int iColor );
void hb_mouseRestoreState( const BYTE * pBuffer );
const char * hb_strLTrim( const char * szText, ULONG * ulLen );
const char * hb_conNewLine( void );
const char * hb_conSetColor( const char * szColor );
const char * hb_errGetDescription( PHB_ITEM pError );
const char * hb_errGetFileName( PHB_ITEM pError );
const char * hb_errGetOperation( PHB_ITEM pError );
const char * hb_errGetSubSystem( PHB_ITEM pError );
int hb_ctwAddWindowBox( int iWindow, const BYTE * szBox, int iColor );
const char *ct_at_exact_forward
( const char *pcString, size_t sStrLen,
const char *pcMatch, size_t sMatchLen,
size_t *psMatchStrLen );
const char *ct_at_exact_backward
( const char *pcString, size_t sStrLen,
const char *pcMatch, size_t sMatchLen,
size_t *psMatchStrLen );
const char *ct_at_wildcard_forward
( const char *pcString, size_t sStrLen,
const char *pcMatch, size_t sMatchLen,
char cWildCard, size_t *psMatchStrLen );
const char *ct_at_wildcard_backward
( const char *pcString, size_t sStrLen,
const char *pcMatch, size_t sMatchLen,
char cWildCard, size_t *psMatchStrLen );
const char *ct_at_charset_forward
( const char *pcString, size_t sStrLen,
const char *pcCharSet, size_t sCharSetLen,
size_t *psMatchedCharPos );
const char *ct_at_charset_backward
( const char *pcString, size_t sStrLen,
const char *pcCharSet, size_t sCharSetLen,
size_t *psMatchedCharPos );
char * hb_adsOemToAnsi( const char * pcString, ULONG ulLen );
char * hb_adsAnsiToOem( const char * pcString, ULONG ulLen );
struct hb_BTree * hb_BTreeNew( const char *FileName,
USHORT usPageSize, USHORT usKeySize,
ULONG ulFlags, USHORT usBuffers );
struct hb_BTree * hb_BTreeOpen( const char *FileName, ULONG lFlags,
USHORT usBuffers );
BOOL hb_BTreeInsert( struct hb_BTree * pBTree, const char * szKey,
PHB_ITEM pData );
BOOL hb_BTreeDelete( struct hb_BTree * pBTree, const char * szKey,
LONG lData );
BOOL hb_BTreeSeek( struct hb_BTree * pBTree, const char * szKey,
LONG lData, BOOL bSoftSeek );
const char * hb_BTreeKey( struct hb_BTree * pBTree );
* modified RDD methods:
HB_ERRCODE PUTVALUEFILE( AREAP, USHORT, const char *, USHORT );
HB_ERRCODE GETVALUEFILE( AREAP, USHORT, const char *, USHORT );
* modified GT methods:
void REST( HB_GT_PTR, int, int, int, int, const BYTE * );
void PUTTEXT( HB_GT_PTR, int, int, BYTE, const BYTE *, ULONG );
void WRITEAT( HB_GT_PTR, int, int, const BYTE *, ULONG );
void WRITE( HB_GT_PTR, const BYTE *, ULONG );
void WRITECON( HB_GT_PTR, const BYTE *, ULONG );
void BOX( HB_GT_PTR, int, int, int, int, const BYTE *, BYTE );
void BOXD( HB_GT_PTR, int, int, int, int, const BYTE *, BYTE );
void BOXS( HB_GT_PTR, int, int, int, int, const BYTE *, BYTE );
void OUTSTD( HB_GT_PTR, BYTE *, ULONG );
void OUTERR( HB_GT_PTR, BYTE *, ULONG );
void MOUSERESTORESTATE( HB_GT_PTR, const BYTE * );
* modified RDD structers:
DBFIELDINFO, DBOPENINFO, DBORDERCONDINFO, DBCONSTRAINTINFO,
DBORDERCREATEINFO
+ modified parameters and behevior:
const char * hb_fsNameConv( const char * szFileName, char ** pszFree );
const char * hb_osEncode( const char * szFileName, char ** pszFree );
const char * hb_osDecode( const char * szFileName, char ** pszFree );
Please look at implementation and current usage of these functions.
+ added new function:
BOOL hb_itemGetWriteCL( PHB_ITEM pItem,
char ** pszValue, ULONG * pulLen );
which converts item string buffer to writable state to use with
functions like FREAD() instead of hb_itemUnShare*()
* updatd other code to respect above modifications
! fixed bugs (also GPF traps) located by above modifications
TODO: please make build tests. Especially in OS2 - not tested at all.
2264 lines
63 KiB
C
2264 lines
63 KiB
C
/*
|
|
* $Id$
|
|
*/
|
|
|
|
/*
|
|
* Harbour Project source code:
|
|
* Default RDD module
|
|
*
|
|
* Copyright 1999 Bruno Cantero <bruno@issnet.net>
|
|
* Copyright 2004-2007 Przemyslaw Czerpak <druzus / at / priv.onet.pl>
|
|
* www - http://www.harbour-project.org
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2, or (at your option)
|
|
* any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this software; see the file COPYING. If not, write to
|
|
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
|
* Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/).
|
|
*
|
|
* As a special exception, the Harbour Project gives permission for
|
|
* additional uses of the text contained in its release of Harbour.
|
|
*
|
|
* The exception is that, if you link the Harbour libraries with other
|
|
* files to produce an executable, this does not by itself cause the
|
|
* resulting executable to be covered by the GNU General Public License.
|
|
* Your use of that executable is in no way restricted on account of
|
|
* linking the Harbour library code into it.
|
|
*
|
|
* This exception does not however invalidate any other reasons why
|
|
* the executable file might be covered by the GNU General Public License.
|
|
*
|
|
* This exception applies only to the code released by the Harbour
|
|
* Project under the name Harbour. If you copy code from other
|
|
* Harbour Project or Free Software Foundation releases into a copy of
|
|
* Harbour, as the General Public License permits, the exception does
|
|
* not apply to the code that you add in this way. To avoid misleading
|
|
* anyone as to the status of such modified files, you must delete
|
|
* this exception notice from them.
|
|
*
|
|
* If you write modifications of your own for Harbour, it is your choice
|
|
* whether to permit this exception to apply to your modifications.
|
|
* If you do not wish that, delete this exception notice.
|
|
*
|
|
*
|
|
* The following functions are added by
|
|
* Horacio Roldan <harbour_ar@yahoo.com.ar>
|
|
* hb_waCloseAux()
|
|
*
|
|
*/
|
|
|
|
#include "hbapi.h"
|
|
#include "hbapirdd.h"
|
|
#include "hbapiitm.h"
|
|
#include "hbapierr.h"
|
|
#include "hbapilng.h"
|
|
#include "hbvm.h"
|
|
#include "hbthread.h"
|
|
#include "hbset.h"
|
|
|
|
/*
|
|
* -- BASIC RDD METHODS --
|
|
*/
|
|
|
|
/*
|
|
* Determine logical beginning of file.
|
|
*/
|
|
static HB_ERRCODE hb_waBof( AREAP pArea, BOOL * pBof )
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waBof(%p, %p)", pArea, pBof));
|
|
|
|
* pBof = pArea->fBof;
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* Determine logical end of file.
|
|
*/
|
|
static HB_ERRCODE hb_waEof( AREAP pArea, BOOL * pEof )
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waEof(%p, %p)", pArea, pEof));
|
|
|
|
* pEof = pArea->fEof;
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* Determine outcome of the last search operation.
|
|
*/
|
|
static HB_ERRCODE hb_waFound( AREAP pArea, BOOL * pFound )
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waFound(%p, %p)", pArea, pFound));
|
|
|
|
* pFound = pArea->fFound;
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* Reposition cursor relative to current position.
|
|
*/
|
|
static HB_ERRCODE hb_waSkip( AREAP pArea, LONG lToSkip )
|
|
{
|
|
LONG lSkip;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waSkip(%p, %ld)", pArea, lToSkip));
|
|
|
|
/* Flush record and exit */
|
|
if( lToSkip == 0 )
|
|
return SELF_SKIPRAW( pArea, 0 );
|
|
|
|
pArea->fTop = pArea->fBottom = FALSE;
|
|
|
|
if( lToSkip > 0 )
|
|
lSkip = 1;
|
|
else
|
|
{
|
|
lSkip = -1;
|
|
lToSkip *= -1;
|
|
}
|
|
while( --lToSkip >= 0 )
|
|
{
|
|
if( SELF_SKIPRAW( pArea, lSkip ) != HB_SUCCESS )
|
|
return HB_FAILURE;
|
|
if( SELF_SKIPFILTER( pArea, lSkip ) != HB_SUCCESS )
|
|
return HB_FAILURE;
|
|
if( pArea->fBof || pArea->fEof )
|
|
break;
|
|
}
|
|
|
|
/* Update Bof and Eof flags */
|
|
if( lSkip < 0 )
|
|
pArea->fEof = FALSE;
|
|
else /* ( lSkip > 0 ) */
|
|
pArea->fBof = FALSE;
|
|
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* Reposition cursor respecting any filter setting.
|
|
*/
|
|
static HB_ERRCODE hb_waSkipFilter( AREAP pArea, LONG lUpDown )
|
|
{
|
|
BOOL fBottom, fDeleted;
|
|
HB_ERRCODE uiError;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waSkipFilter(%p, %ld)", pArea, lUpDown));
|
|
|
|
if( pArea->dbfi.itmCobExpr == NULL && !hb_setGetDeleted() )
|
|
return HB_SUCCESS;
|
|
|
|
/* Since lToSkip is passed to SkipRaw, it should never request more than
|
|
a single skip.
|
|
The implied purpose of hb_waSkipFilter is to get off of a "bad" record
|
|
after a skip was performed, NOT to skip lToSkip filtered records.
|
|
*/
|
|
lUpDown = ( lUpDown < 0 ? -1 : 1 );
|
|
|
|
/* remember if we are here after SLEF_GOTOP() */
|
|
fBottom = pArea->fBottom;
|
|
|
|
while( !pArea->fBof && !pArea->fEof )
|
|
{
|
|
/* SET DELETED */
|
|
if( hb_setGetDeleted() )
|
|
{
|
|
if( SELF_DELETED( pArea, &fDeleted ) != HB_SUCCESS )
|
|
return HB_FAILURE;
|
|
if( fDeleted )
|
|
{
|
|
if( SELF_SKIPRAW( pArea, lUpDown ) != HB_SUCCESS )
|
|
return HB_FAILURE;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
/* SET FILTER TO */
|
|
if( pArea->dbfi.itmCobExpr )
|
|
{
|
|
if( SELF_EVALBLOCK( pArea, pArea->dbfi.itmCobExpr ) != HB_SUCCESS )
|
|
return HB_FAILURE;
|
|
|
|
if( HB_IS_LOGICAL( pArea->valResult ) &&
|
|
!hb_itemGetL( pArea->valResult ) )
|
|
{
|
|
if( SELF_SKIPRAW( pArea, lUpDown ) != HB_SUCCESS )
|
|
return HB_FAILURE;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* The only one situation when we should repos is backward skipping
|
|
* if we are at BOTTOM position (it's SKIPFILTER called from GOBOTTOM)
|
|
* then GOEOF() if not then GOTOP()
|
|
*/
|
|
if( pArea->fBof && lUpDown < 0 )
|
|
{
|
|
if( fBottom )
|
|
{
|
|
/* GOTO EOF (phantom) record -
|
|
this is the only one place where GOTO is used by xHarbour
|
|
directly and RDD which does not operate on numbers should
|
|
serve this method only as SELF_GOEOF() synonym. If it's a
|
|
problem then we can remove this if and always use SELF_GOTOP()
|
|
but it also means second table scan if all records filtered
|
|
are out of filter so I do not want to do that. I will prefer
|
|
explicit add SELF_GOEOF() method
|
|
*/
|
|
uiError = SELF_GOTO( pArea, 0 );
|
|
}
|
|
else
|
|
{
|
|
uiError = SELF_GOTOP( pArea );
|
|
pArea->fBof = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
uiError = HB_SUCCESS;
|
|
}
|
|
|
|
return uiError;
|
|
}
|
|
|
|
/*
|
|
* Add a field to the WorkArea.
|
|
*/
|
|
static HB_ERRCODE hb_waAddField( AREAP pArea, LPDBFIELDINFO pFieldInfo )
|
|
{
|
|
LPFIELD pField;
|
|
char szFieldName[ HB_SYMBOL_NAME_LEN + 1 ], *szPtr;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waAddField(%p, %p)", pArea, pFieldInfo));
|
|
|
|
/* Validate the name of field */
|
|
szPtr = ( char * ) pFieldInfo->atomName;
|
|
while( HB_ISSPACE( *szPtr ) )
|
|
{
|
|
++szPtr;
|
|
}
|
|
hb_strncpyUpperTrim( szFieldName, szPtr, sizeof( szFieldName ) - 1 );
|
|
if( strlen( szFieldName ) == 0 )
|
|
return HB_FAILURE;
|
|
|
|
pField = pArea->lpFields + pArea->uiFieldCount;
|
|
if( pArea->uiFieldCount > 0 )
|
|
( ( LPFIELD ) ( pField - 1 ) )->lpfNext = pField;
|
|
pField->sym = ( void * ) hb_dynsymGetCase( szFieldName );
|
|
pField->uiType = pFieldInfo->uiType;
|
|
pField->uiTypeExtended = pFieldInfo->uiTypeExtended;
|
|
pField->uiLen = pFieldInfo->uiLen;
|
|
pField->uiDec = pFieldInfo->uiDec;
|
|
pField->uiFlags = pFieldInfo->uiFlags;
|
|
pField->uiArea = pArea->uiArea;
|
|
pArea->uiFieldCount++;
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* Add all fields defined in an array to the WorkArea.
|
|
*/
|
|
static HB_ERRCODE hb_waCreateFields( AREAP pArea, PHB_ITEM pStruct )
|
|
{
|
|
USHORT uiItems, uiCount, uiLen, uiDec;
|
|
HB_ERRCODE errCode = HB_SUCCESS;
|
|
DBFIELDINFO pFieldInfo;
|
|
PHB_ITEM pFieldDesc;
|
|
int iData;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waCreateFields(%p, %p)", pArea, pStruct));
|
|
|
|
uiItems = ( USHORT ) hb_arrayLen( pStruct );
|
|
if( SELF_SETFIELDEXTENT( pArea, uiItems ) != HB_SUCCESS )
|
|
return HB_FAILURE;
|
|
|
|
for( uiCount = 0; uiCount < uiItems; uiCount++ )
|
|
{
|
|
pFieldInfo.uiTypeExtended = 0;
|
|
pFieldDesc = hb_arrayGetItemPtr( pStruct, uiCount + 1 );
|
|
pFieldInfo.atomName = hb_arrayGetCPtr( pFieldDesc, DBS_NAME );
|
|
iData = hb_arrayGetNI( pFieldDesc, DBS_LEN );
|
|
if( iData < 0 )
|
|
iData = 0;
|
|
uiLen = pFieldInfo.uiLen = ( USHORT ) iData;
|
|
iData = hb_arrayGetNI( pFieldDesc, DBS_DEC );
|
|
if( iData < 0 )
|
|
iData = 0;
|
|
uiDec = ( USHORT ) iData;
|
|
pFieldInfo.uiDec = 0;
|
|
#ifdef DBS_FLAG
|
|
pFieldInfo.uiFlags = hb_arrayGetNI( pFieldDesc, DBS_FLAG );
|
|
#else
|
|
pFieldInfo.uiFlags = 0;
|
|
#endif
|
|
iData = HB_TOUPPER( hb_arrayGetCPtr( pFieldDesc, DBS_TYPE )[ 0 ] );
|
|
switch( iData )
|
|
{
|
|
case 'C':
|
|
pFieldInfo.uiType = HB_FT_STRING;
|
|
pFieldInfo.uiLen = uiLen;
|
|
/* Too many people reported the behavior with code below as a
|
|
Clipper compatibility bug so I commented this code. Druzus.
|
|
#ifdef HB_C52_STRICT
|
|
pFieldInfo.uiLen = uiLen;
|
|
#else
|
|
pFieldInfo.uiLen = uiLen + uiDec * 256;
|
|
#endif
|
|
*/
|
|
break;
|
|
|
|
case 'L':
|
|
pFieldInfo.uiType = HB_FT_LOGICAL;
|
|
pFieldInfo.uiLen = 1;
|
|
break;
|
|
|
|
case 'D':
|
|
pFieldInfo.uiType = HB_FT_DATE;
|
|
pFieldInfo.uiLen = ( uiLen == 3 || uiLen == 4 ) ? uiLen : 8;
|
|
break;
|
|
|
|
case 'I':
|
|
pFieldInfo.uiType = HB_FT_INTEGER;
|
|
pFieldInfo.uiLen = ( ( uiLen > 0 && uiLen <= 4 ) || uiLen == 8 ) ? uiLen : 4;
|
|
pFieldInfo.uiDec = uiDec;
|
|
break;
|
|
|
|
case 'Y':
|
|
pFieldInfo.uiType = HB_FT_CURRENCY;
|
|
pFieldInfo.uiLen = 8;
|
|
pFieldInfo.uiDec = 4;
|
|
break;
|
|
|
|
case 'Z':
|
|
pFieldInfo.uiType = HB_FT_CURDOUBLE;
|
|
pFieldInfo.uiLen = 8;
|
|
pFieldInfo.uiDec = uiDec;
|
|
break;
|
|
|
|
case '2':
|
|
case '4':
|
|
pFieldInfo.uiType = HB_FT_INTEGER;
|
|
pFieldInfo.uiLen = iData - '0';
|
|
break;
|
|
|
|
case 'B':
|
|
case '8':
|
|
pFieldInfo.uiType = HB_FT_DOUBLE;
|
|
pFieldInfo.uiLen = 8;
|
|
pFieldInfo.uiDec = uiDec;
|
|
break;
|
|
|
|
case 'N':
|
|
pFieldInfo.uiType = HB_FT_LONG;
|
|
pFieldInfo.uiDec = uiDec;
|
|
/* DBASE documentation defines maximum numeric field size as 20
|
|
* but Clipper alows to create longer fileds so I remove this
|
|
* limit, Druzus
|
|
*/
|
|
/*
|
|
if( uiLen > 20 )
|
|
*/
|
|
if( uiLen > 255 )
|
|
errCode = HB_FAILURE;
|
|
break;
|
|
|
|
case 'F':
|
|
pFieldInfo.uiType = HB_FT_FLOAT;
|
|
pFieldInfo.uiDec = uiDec;
|
|
/* see note above */
|
|
if( uiLen > 255 )
|
|
errCode = HB_FAILURE;
|
|
break;
|
|
|
|
case 'T':
|
|
if( uiLen == 8 )
|
|
{
|
|
pFieldInfo.uiType = HB_FT_TIMESTAMP;
|
|
pFieldInfo.uiLen = 8;
|
|
}
|
|
else
|
|
{
|
|
pFieldInfo.uiType = HB_FT_TIME;
|
|
pFieldInfo.uiLen = 4;
|
|
}
|
|
break;
|
|
|
|
case '@':
|
|
pFieldInfo.uiType = HB_FT_TIMESTAMP;
|
|
pFieldInfo.uiLen = 8;
|
|
break;
|
|
|
|
case '=':
|
|
pFieldInfo.uiType = HB_FT_MODTIME;
|
|
pFieldInfo.uiLen = 8;
|
|
break;
|
|
|
|
case '^':
|
|
pFieldInfo.uiType = HB_FT_ROWVER;
|
|
pFieldInfo.uiLen = 8;
|
|
break;
|
|
|
|
case '+':
|
|
pFieldInfo.uiType = HB_FT_AUTOINC;
|
|
pFieldInfo.uiLen = 4;
|
|
break;
|
|
|
|
case 'Q':
|
|
pFieldInfo.uiType = HB_FT_VARLENGTH;
|
|
pFieldInfo.uiLen = uiLen > 255 ? 255 : ( uiLen == 0 ? 1 : uiLen );
|
|
break;
|
|
|
|
case 'M':
|
|
pFieldInfo.uiType = HB_FT_MEMO;
|
|
pFieldInfo.uiLen = ( uiLen == 4 ) ? 4 : 10;
|
|
break;
|
|
|
|
case 'V':
|
|
pFieldInfo.uiType = HB_FT_ANY;
|
|
pFieldInfo.uiLen = ( uiLen < 3 || uiLen == 5 ) ? 6 : uiLen;
|
|
break;
|
|
|
|
case 'P':
|
|
pFieldInfo.uiType = HB_FT_IMAGE;
|
|
pFieldInfo.uiLen = ( uiLen == 4 ) ? 4 : 10;
|
|
break;
|
|
|
|
case 'W':
|
|
pFieldInfo.uiType = HB_FT_BLOB;
|
|
pFieldInfo.uiLen = ( uiLen == 4 ) ? 4 : 10;
|
|
break;
|
|
|
|
case 'G':
|
|
pFieldInfo.uiType = HB_FT_OLE;
|
|
pFieldInfo.uiLen = ( uiLen == 4 ) ? 4 : 10;
|
|
break;
|
|
|
|
default:
|
|
errCode = HB_FAILURE;
|
|
break;
|
|
}
|
|
|
|
if( errCode != HB_SUCCESS )
|
|
{
|
|
hb_errRT_DBCMD( EG_ARG, EDBCMD_DBCMDBADPARAMETER, NULL, HB_ERR_FUNCNAME );
|
|
return errCode;
|
|
}
|
|
/* Add field */
|
|
else if( SELF_ADDFIELD( pArea, &pFieldInfo ) != HB_SUCCESS )
|
|
return HB_FAILURE;
|
|
}
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* Determine the number of fields in the WorkArea.
|
|
*/
|
|
static HB_ERRCODE hb_waFieldCount( AREAP pArea, USHORT * uiFields )
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waFieldCount(%p, %p)", pArea, uiFields));
|
|
|
|
* uiFields = pArea->uiFieldCount;
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* Retrieve information about a field.
|
|
*/
|
|
static HB_ERRCODE hb_waFieldInfo( AREAP pArea, USHORT uiIndex, USHORT uiType, PHB_ITEM pItem )
|
|
{
|
|
LPFIELD pField;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waFieldInfo(%p, %hu, %hu, %p)", pArea, uiIndex, uiType, pItem));
|
|
|
|
if( uiIndex > pArea->uiFieldCount )
|
|
return HB_FAILURE;
|
|
|
|
pField = pArea->lpFields + uiIndex - 1;
|
|
switch( uiType )
|
|
{
|
|
case DBS_NAME:
|
|
hb_itemPutC( pItem, hb_dynsymName( ( PHB_DYNS ) pField->sym ) );
|
|
break;
|
|
|
|
case DBS_TYPE:
|
|
switch( pField->uiType )
|
|
{
|
|
case HB_FT_STRING:
|
|
hb_itemPutC( pItem, "C" );
|
|
break;
|
|
|
|
case HB_FT_LOGICAL:
|
|
hb_itemPutC( pItem, "L" );
|
|
break;
|
|
|
|
case HB_FT_DATE:
|
|
hb_itemPutC( pItem, "D" );
|
|
break;
|
|
|
|
case HB_FT_LONG:
|
|
hb_itemPutC( pItem, "N" );
|
|
break;
|
|
|
|
case HB_FT_INTEGER:
|
|
hb_itemPutC( pItem, "I" );
|
|
break;
|
|
|
|
case HB_FT_DOUBLE:
|
|
hb_itemPutC( pItem, "B" );
|
|
break;
|
|
|
|
case HB_FT_FLOAT:
|
|
hb_itemPutC( pItem, "F" );
|
|
break;
|
|
|
|
case HB_FT_TIME:
|
|
hb_itemPutC( pItem, "T" );
|
|
break;
|
|
|
|
case HB_FT_TIMESTAMP:
|
|
hb_itemPutC( pItem, "@" );
|
|
break;
|
|
|
|
case HB_FT_MODTIME:
|
|
hb_itemPutC( pItem, "=" );
|
|
break;
|
|
|
|
case HB_FT_ROWVER:
|
|
hb_itemPutC( pItem, "^" );
|
|
break;
|
|
|
|
case HB_FT_AUTOINC:
|
|
hb_itemPutC( pItem, "+" );
|
|
break;
|
|
|
|
case HB_FT_CURRENCY:
|
|
hb_itemPutC( pItem, "Y" );
|
|
break;
|
|
|
|
case HB_FT_CURDOUBLE:
|
|
hb_itemPutC( pItem, "Z" );
|
|
break;
|
|
|
|
case HB_FT_VARLENGTH:
|
|
hb_itemPutC( pItem, "Q" );
|
|
break;
|
|
|
|
case HB_FT_MEMO:
|
|
hb_itemPutC( pItem, "M" );
|
|
break;
|
|
|
|
case HB_FT_ANY:
|
|
hb_itemPutC( pItem, "V" );
|
|
break;
|
|
|
|
case HB_FT_IMAGE:
|
|
hb_itemPutC( pItem, "P" );
|
|
break;
|
|
|
|
case HB_FT_BLOB:
|
|
hb_itemPutC( pItem, "W" );
|
|
break;
|
|
|
|
case HB_FT_OLE:
|
|
hb_itemPutC( pItem, "G" );
|
|
break;
|
|
|
|
default:
|
|
hb_itemPutC( pItem, "U" );
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case DBS_LEN:
|
|
hb_itemPutNL( pItem, pField->uiLen );
|
|
break;
|
|
|
|
case DBS_DEC:
|
|
hb_itemPutNL( pItem, pField->uiDec );
|
|
break;
|
|
|
|
#ifdef DBS_FLAG
|
|
case DBS_FLAG:
|
|
hb_itemPutNL( pItem, pField->uiFlags );
|
|
break;
|
|
#endif
|
|
|
|
default:
|
|
return HB_FAILURE;
|
|
|
|
}
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* Determine the name associated with a field number.
|
|
*/
|
|
static HB_ERRCODE hb_waFieldName( AREAP pArea, USHORT uiIndex, void * szName )
|
|
{
|
|
LPFIELD pField;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waFieldName(%p, %hu, %p)", pArea, uiIndex, szName));
|
|
|
|
if( uiIndex > pArea->uiFieldExtent )
|
|
return HB_FAILURE;
|
|
|
|
pField = pArea->lpFields + uiIndex - 1;
|
|
hb_strncpy( ( char * ) szName, hb_dynsymName( ( PHB_DYNS ) pField->sym ),
|
|
pArea->uiMaxFieldNameLength );
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* Establish the extent of the array of fields for a WorkArea.
|
|
*/
|
|
static HB_ERRCODE hb_waSetFieldExtent( AREAP pArea, USHORT uiFieldExtent )
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waSetFieldExtent(%p, %hu)", pArea, uiFieldExtent));
|
|
|
|
pArea->uiFieldExtent = uiFieldExtent;
|
|
|
|
/* Alloc field array */
|
|
if( uiFieldExtent )
|
|
{
|
|
pArea->lpFields = ( LPFIELD ) hb_xgrab( uiFieldExtent * sizeof( FIELD ) );
|
|
memset( pArea->lpFields, 0, uiFieldExtent * sizeof( FIELD ) );
|
|
}
|
|
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* Obtain the alias of the WorkArea.
|
|
*/
|
|
static HB_ERRCODE hb_waAlias( AREAP pArea, BYTE * szAlias )
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waAlias(%p, %p)", pArea, szAlias));
|
|
|
|
hb_strncpy( ( char * ) szAlias,
|
|
pArea->atomAlias && hb_dynsymAreaHandle( ( PHB_DYNS ) pArea->atomAlias )
|
|
? hb_dynsymName( ( PHB_DYNS ) pArea->atomAlias ) : "",
|
|
HB_RDD_MAX_ALIAS_LEN );
|
|
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* Close the table in the WorkArea.
|
|
*/
|
|
static HB_ERRCODE hb_waClose( AREAP pArea )
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waClose(%p)", pArea));
|
|
|
|
/* Clear items */
|
|
SELF_CLEARFILTER( pArea );
|
|
SELF_CLEARREL( pArea );
|
|
SELF_CLEARLOCATE( pArea );
|
|
|
|
/* Clear relations that has this area as a child */
|
|
hb_rddCloseAllParentRelations( pArea );
|
|
|
|
if( pArea->atomAlias )
|
|
hb_dynsymSetAreaHandle( ( PHB_DYNS ) pArea->atomAlias, 0 );
|
|
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* Retrieve information about the current driver.
|
|
*/
|
|
static HB_ERRCODE hb_waInfo( AREAP pArea, USHORT uiIndex, PHB_ITEM pItem )
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waInfo(%p, %hu, %p)", pArea, uiIndex, pItem));
|
|
|
|
switch( uiIndex )
|
|
{
|
|
case DBI_ISDBF:
|
|
case DBI_CANPUTREC:
|
|
case DBI_ISFLOCK:
|
|
case DBI_SHARED:
|
|
hb_itemPutL( pItem, FALSE );
|
|
break;
|
|
|
|
/*
|
|
* IMHO better to return HB_FAILURE to notice that it's not supported
|
|
*/
|
|
case DBI_GETDELIMITER:
|
|
case DBI_SETDELIMITER:
|
|
case DBI_SEPARATOR:
|
|
hb_itemPutC( pItem, NULL );
|
|
return HB_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;
|
|
USHORT uiCount = 0;
|
|
while( lpdbRelations )
|
|
{
|
|
uiCount++;
|
|
lpdbRelations = lpdbRelations->lpdbriNext;
|
|
}
|
|
hb_itemPutNI( pItem, uiCount );
|
|
break;
|
|
}
|
|
|
|
case DBI_BOF:
|
|
hb_itemPutL( pItem, pArea->fBof );
|
|
break;
|
|
|
|
case DBI_EOF:
|
|
hb_itemPutL( pItem, pArea->fEof );
|
|
break;
|
|
|
|
case DBI_DBFILTER:
|
|
if( pArea->dbfi.abFilterText )
|
|
hb_itemCopy( pItem, pArea->dbfi.abFilterText );
|
|
else
|
|
hb_itemPutC( pItem, NULL );
|
|
break;
|
|
|
|
case DBI_FOUND:
|
|
hb_itemPutL( pItem, pArea->fFound );
|
|
break;
|
|
|
|
case DBI_FCOUNT:
|
|
hb_itemPutNI( pItem, pArea->uiFieldCount );
|
|
break;
|
|
|
|
case DBI_ALIAS:
|
|
{
|
|
char szAlias[ HB_RDD_MAX_ALIAS_LEN + 1 ];
|
|
if( SELF_ALIAS( pArea, ( BYTE * ) szAlias ) != HB_SUCCESS )
|
|
{
|
|
return HB_FAILURE;
|
|
}
|
|
hb_itemPutC( pItem, szAlias );
|
|
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 );
|
|
BOOL fScoped = FALSE;
|
|
|
|
if( iRelNo > 0 )
|
|
{
|
|
LPDBRELINFO lpdbRelations = pArea->lpdbRelations;
|
|
while( lpdbRelations )
|
|
{
|
|
if( --iRelNo == 0 )
|
|
{
|
|
fScoped = lpdbRelations->isScoped;
|
|
break;
|
|
}
|
|
lpdbRelations = lpdbRelations->lpdbriNext;
|
|
}
|
|
}
|
|
hb_itemPutL( pItem, fScoped );
|
|
break;
|
|
}
|
|
case DBI_POSITIONED:
|
|
{
|
|
ULONG ulRecCount, ulRecNo;
|
|
if( SELF_RECNO( pArea, &ulRecNo ) != HB_SUCCESS )
|
|
return HB_FAILURE;
|
|
if( ulRecNo == 0 )
|
|
hb_itemPutL( pItem, FALSE );
|
|
else if( SELF_RECCOUNT( pArea, &ulRecCount ) != HB_SUCCESS )
|
|
return HB_FAILURE;
|
|
else
|
|
hb_itemPutL( pItem, ulRecNo != ulRecCount + 1 );
|
|
break;
|
|
}
|
|
case DBI_RM_SUPPORTED:
|
|
hb_itemPutL( pItem, FALSE );
|
|
break;
|
|
|
|
case DBI_DB_VERSION:
|
|
hb_itemPutC( pItem, NULL );
|
|
break;
|
|
|
|
case DBI_RDD_VERSION:
|
|
hb_itemPutC( pItem, NULL );
|
|
break;
|
|
|
|
default:
|
|
return HB_FAILURE;
|
|
}
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* Retrieve information about the current order that SELF could not.
|
|
* Called by SELF_ORDINFO if uiIndex is not supported.
|
|
*/
|
|
static HB_ERRCODE hb_waOrderInfo( AREAP pArea, USHORT index, LPDBORDERINFO pInfo )
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waOrderInfo(%p, %hu, %p)", pArea, index, pInfo));
|
|
|
|
HB_SYMBOL_UNUSED( pArea );
|
|
HB_SYMBOL_UNUSED( index );
|
|
|
|
if( pInfo->itmResult )
|
|
hb_itemClear( pInfo->itmResult );
|
|
|
|
/* CA-Cl*pper does not generate RT error when default ORDERINFO() method
|
|
* is called
|
|
*/
|
|
/* hb_errRT_DBCMD( EG_ARG, EDBCMD_BADPARAMETER, NULL, HB_ERR_FUNCNAME ); */
|
|
|
|
return HB_FAILURE;
|
|
}
|
|
|
|
/*
|
|
* Clear the WorkArea for use.
|
|
*/
|
|
static HB_ERRCODE hb_waNewArea( AREAP pArea )
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waNewArea(%p)", pArea));
|
|
|
|
pArea->valResult = hb_itemNew( NULL );
|
|
pArea->lpdbRelations = NULL;
|
|
pArea->uiParents = 0;
|
|
pArea->uiMaxFieldNameLength = 10;
|
|
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* Open a data store in the WorkArea.
|
|
* Like in Clipper it's also mapped as Create() method at WA level
|
|
*/
|
|
static HB_ERRCODE hb_waOpen( AREAP pArea, LPDBOPENINFO pInfo )
|
|
{
|
|
if( !pArea->atomAlias && pInfo->atomAlias && pInfo->atomAlias[ 0 ] )
|
|
{
|
|
pArea->atomAlias = hb_rddAllocWorkAreaAlias( ( char * ) pInfo->atomAlias,
|
|
( int ) pInfo->uiArea );
|
|
if( ! pArea->atomAlias )
|
|
{
|
|
SELF_CLOSE( ( AREAP ) pArea );
|
|
return HB_FAILURE;
|
|
}
|
|
}
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
static HB_ERRCODE hb_waOrderCondition( AREAP pArea, LPDBORDERCONDINFO param )
|
|
{
|
|
if( pArea->lpdbOrdCondInfo )
|
|
{
|
|
if( pArea->lpdbOrdCondInfo->abFor )
|
|
hb_xfree( pArea->lpdbOrdCondInfo->abFor );
|
|
if( pArea->lpdbOrdCondInfo->abWhile )
|
|
hb_xfree( pArea->lpdbOrdCondInfo->abWhile );
|
|
if( pArea->lpdbOrdCondInfo->itmCobFor )
|
|
{
|
|
hb_itemRelease( pArea->lpdbOrdCondInfo->itmCobFor );
|
|
}
|
|
if( pArea->lpdbOrdCondInfo->itmCobWhile )
|
|
{
|
|
hb_itemRelease( pArea->lpdbOrdCondInfo->itmCobWhile );
|
|
}
|
|
if( pArea->lpdbOrdCondInfo->itmCobEval )
|
|
{
|
|
hb_itemRelease( pArea->lpdbOrdCondInfo->itmCobEval );
|
|
}
|
|
if( pArea->lpdbOrdCondInfo->itmStartRecID )
|
|
{
|
|
hb_itemRelease( pArea->lpdbOrdCondInfo->itmStartRecID );
|
|
}
|
|
if( pArea->lpdbOrdCondInfo->itmRecID )
|
|
{
|
|
hb_itemRelease( pArea->lpdbOrdCondInfo->itmRecID );
|
|
}
|
|
hb_xfree( pArea->lpdbOrdCondInfo );
|
|
}
|
|
pArea->lpdbOrdCondInfo = param;
|
|
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* Release all references to a WorkArea.
|
|
*/
|
|
static HB_ERRCODE hb_waRelease( AREAP pArea )
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waRelease(%p)", pArea));
|
|
|
|
/* Free all allocated pointers */
|
|
if( pArea->lpFields )
|
|
hb_xfree( pArea->lpFields );
|
|
if( pArea->valResult )
|
|
hb_itemRelease( pArea->valResult );
|
|
if( pArea->lpdbOrdCondInfo )
|
|
/* intentionally direct call not a method */
|
|
hb_waOrderCondition( pArea,NULL );
|
|
hb_xfree( pArea );
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* Retrieve the size of the WorkArea structure.
|
|
*/
|
|
static HB_ERRCODE hb_waStructSize( AREAP pArea, USHORT * uiSize )
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waStrucSize(%p, %p)", pArea, uiSize));
|
|
HB_SYMBOL_UNUSED( pArea );
|
|
|
|
* uiSize = sizeof( AREA );
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* Obtain the name of replaceable database driver (RDD) subsystem.
|
|
*/
|
|
static HB_ERRCODE hb_waSysName( AREAP pArea, BYTE * pBuffer )
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waSysName(%p, %p)", pArea, pBuffer));
|
|
|
|
hb_strncpy( ( char * ) pBuffer, SELF_RDDNODE( pArea )->szName,
|
|
HB_RDD_MAX_DRIVERNAME_LEN );
|
|
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* Evaluate code block for each record in WorkArea.
|
|
*/
|
|
static HB_ERRCODE hb_waEval( AREAP pArea, LPDBEVALINFO pEvalInfo )
|
|
{
|
|
LONG lNext = 1;
|
|
BOOL fEof, fFor;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waEval(%p, %p)", pArea, pEvalInfo));
|
|
|
|
if( pEvalInfo->dbsci.itmRecID )
|
|
{
|
|
if( SELF_GOTOID( pArea, pEvalInfo->dbsci.itmRecID ) != HB_SUCCESS )
|
|
return HB_FAILURE;
|
|
}
|
|
else if( pEvalInfo->dbsci.lNext )
|
|
{
|
|
lNext = hb_itemGetNL( pEvalInfo->dbsci.lNext );
|
|
}
|
|
else if( !pEvalInfo->dbsci.itmCobWhile &&
|
|
!hb_itemGetL( pEvalInfo->dbsci.fRest ) )
|
|
{
|
|
if( SELF_GOTOP( pArea ) != HB_SUCCESS )
|
|
return HB_FAILURE;
|
|
}
|
|
|
|
/* TODO: use SKIPSCOPE() method and fRest parameter */
|
|
|
|
if( !pEvalInfo->dbsci.lNext || lNext > 0 )
|
|
{
|
|
for( ;; )
|
|
{
|
|
if( SELF_EOF( pArea, &fEof ) != HB_SUCCESS )
|
|
return HB_FAILURE;
|
|
|
|
if( fEof )
|
|
break;
|
|
|
|
if( pEvalInfo->dbsci.itmCobWhile )
|
|
{
|
|
if( SELF_EVALBLOCK( pArea, pEvalInfo->dbsci.itmCobWhile ) != HB_SUCCESS )
|
|
return HB_FAILURE;
|
|
if( ! hb_itemGetL( pArea->valResult ) )
|
|
break;
|
|
}
|
|
|
|
if( pEvalInfo->dbsci.itmCobFor )
|
|
{
|
|
if( SELF_EVALBLOCK( pArea, pEvalInfo->dbsci.itmCobFor ) != HB_SUCCESS )
|
|
return HB_FAILURE;
|
|
fFor = hb_itemGetL( pArea->valResult );
|
|
}
|
|
else
|
|
fFor = TRUE;
|
|
|
|
if( fFor )
|
|
{
|
|
if( SELF_EVALBLOCK( pArea, pEvalInfo->itmBlock ) != HB_SUCCESS )
|
|
return HB_FAILURE;
|
|
}
|
|
|
|
if( pEvalInfo->dbsci.itmRecID || ( pEvalInfo->dbsci.lNext && --lNext < 1 ) )
|
|
break;
|
|
|
|
if( SELF_SKIP( pArea, 1 ) != HB_SUCCESS )
|
|
return HB_FAILURE;
|
|
}
|
|
}
|
|
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* Locate a record which pass given condition
|
|
*/
|
|
static HB_ERRCODE hb_waLocate( AREAP pArea, BOOL fContinue )
|
|
{
|
|
LONG lNext = 1;
|
|
BOOL fEof;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waLocate(%p, %d)", pArea, fContinue));
|
|
|
|
if( fContinue )
|
|
{
|
|
if( ! pArea->dbsi.itmCobFor )
|
|
return HB_SUCCESS;
|
|
|
|
if( SELF_SKIP( pArea, 1 ) != HB_SUCCESS )
|
|
return HB_FAILURE;
|
|
}
|
|
else if( pArea->dbsi.itmRecID )
|
|
{
|
|
if( SELF_GOTOID( pArea, pArea->dbsi.itmRecID ) != HB_SUCCESS )
|
|
return HB_FAILURE;
|
|
}
|
|
else if( pArea->dbsi.lNext )
|
|
{
|
|
lNext = hb_itemGetNL( pArea->dbsi.lNext );
|
|
}
|
|
else if( !pArea->dbsi.itmCobWhile &&
|
|
!hb_itemGetL( pArea->dbsi.fRest ) )
|
|
{
|
|
if( SELF_GOTOP( pArea ) != HB_SUCCESS )
|
|
return HB_FAILURE;
|
|
}
|
|
|
|
pArea->fFound = FALSE;
|
|
|
|
/* TODO: use SKIPSCOPE() method and fRest parameter */
|
|
|
|
if( !pArea->dbsi.lNext || lNext > 0 )
|
|
{
|
|
for( ;; )
|
|
{
|
|
if( SELF_EOF( pArea, &fEof ) != HB_SUCCESS )
|
|
return HB_FAILURE;
|
|
|
|
if( fEof )
|
|
break;
|
|
|
|
if( !fContinue && pArea->dbsi.itmCobWhile )
|
|
{
|
|
if( SELF_EVALBLOCK( pArea, pArea->dbsi.itmCobWhile ) != HB_SUCCESS )
|
|
return HB_FAILURE;
|
|
if( ! hb_itemGetL( pArea->valResult ) )
|
|
break;
|
|
}
|
|
|
|
if( ! pArea->dbsi.itmCobFor )
|
|
{
|
|
pArea->fFound = TRUE;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
if( SELF_EVALBLOCK( pArea, pArea->dbsi.itmCobFor ) != HB_SUCCESS )
|
|
return HB_FAILURE;
|
|
|
|
if( hb_itemGetL( pArea->valResult ) )
|
|
{
|
|
pArea->fFound = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( !fContinue &&
|
|
( pArea->dbsi.itmRecID || ( pArea->dbsi.lNext && --lNext < 1 ) ) )
|
|
break;
|
|
|
|
if( SELF_SKIP( pArea, 1 ) != HB_SUCCESS )
|
|
return HB_FAILURE;
|
|
}
|
|
}
|
|
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* Copy one or more records from one WorkArea to another.
|
|
*/
|
|
static HB_ERRCODE hb_waTrans( AREAP pArea, LPDBTRANSINFO pTransInfo )
|
|
{
|
|
LONG lNext = 1;
|
|
BOOL fEof, fFor;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waTrans(%p, %p)", pArea, pTransInfo));
|
|
|
|
if( pTransInfo->dbsci.itmRecID )
|
|
{
|
|
if( SELF_GOTOID( pArea, pTransInfo->dbsci.itmRecID ) != HB_SUCCESS )
|
|
return HB_FAILURE;
|
|
}
|
|
else if( pTransInfo->dbsci.lNext )
|
|
{
|
|
lNext = hb_itemGetNL( pTransInfo->dbsci.lNext );
|
|
}
|
|
else if( !pTransInfo->dbsci.itmCobWhile &&
|
|
!hb_itemGetL( pTransInfo->dbsci.fRest ) )
|
|
{
|
|
if( SELF_GOTOP( pArea ) != HB_SUCCESS )
|
|
return HB_FAILURE;
|
|
}
|
|
|
|
/* TODO: use SKIPSCOPE() method and fRest parameter */
|
|
|
|
if( !pTransInfo->dbsci.lNext || lNext > 0 )
|
|
{
|
|
for( ;; )
|
|
{
|
|
if( SELF_EOF( pArea, &fEof ) != HB_SUCCESS )
|
|
return HB_FAILURE;
|
|
|
|
if( fEof )
|
|
break;
|
|
|
|
if( pTransInfo->dbsci.itmCobWhile )
|
|
{
|
|
if( SELF_EVALBLOCK( pArea, pTransInfo->dbsci.itmCobWhile ) != HB_SUCCESS )
|
|
return HB_FAILURE;
|
|
if( ! hb_itemGetL( pArea->valResult ) )
|
|
break;
|
|
}
|
|
|
|
if( pTransInfo->dbsci.itmCobFor )
|
|
{
|
|
if( SELF_EVALBLOCK( pArea, pTransInfo->dbsci.itmCobFor ) != HB_SUCCESS )
|
|
return HB_FAILURE;
|
|
fFor = hb_itemGetL( pArea->valResult );
|
|
}
|
|
else
|
|
fFor = TRUE;
|
|
|
|
if( fFor )
|
|
{
|
|
if( SELF_TRANSREC( pArea, pTransInfo ) != HB_SUCCESS )
|
|
return HB_FAILURE;
|
|
}
|
|
|
|
if( pTransInfo->dbsci.itmRecID || ( pTransInfo->dbsci.lNext && --lNext < 1 ) )
|
|
break;
|
|
|
|
if( SELF_SKIP( pArea, 1 ) != HB_SUCCESS )
|
|
return HB_FAILURE;
|
|
}
|
|
}
|
|
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* Copy a record to another WorkArea.
|
|
*/
|
|
static HB_ERRCODE hb_waTransRec( AREAP pArea, LPDBTRANSINFO pTransInfo )
|
|
{
|
|
BOOL bDeleted;
|
|
BYTE *pRecord;
|
|
HB_ERRCODE errCode;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waTransRec(%p, %p)", pArea, pTransInfo));
|
|
|
|
/* Record deleted? */
|
|
errCode = SELF_DELETED( ( AREAP ) pArea, &bDeleted );
|
|
if( errCode != HB_SUCCESS )
|
|
return errCode;
|
|
|
|
if( pTransInfo->uiFlags & DBTF_MATCH && pTransInfo->uiFlags & DBTF_PUTREC )
|
|
{
|
|
errCode = SELF_GETREC( ( AREAP ) pArea, &pRecord );
|
|
if( errCode != HB_SUCCESS )
|
|
return errCode;
|
|
|
|
/* Append a new record */
|
|
errCode = SELF_APPEND( ( AREAP ) pTransInfo->lpaDest, TRUE );
|
|
if( errCode != HB_SUCCESS )
|
|
return errCode;
|
|
|
|
/* Copy record */
|
|
errCode = SELF_PUTREC( ( AREAP ) pTransInfo->lpaDest, pRecord );
|
|
}
|
|
else
|
|
{
|
|
LPDBTRANSITEM pTransItem;
|
|
PHB_ITEM pItem;
|
|
USHORT uiCount;
|
|
|
|
/* Append a new record */
|
|
errCode = SELF_APPEND( ( AREAP ) pTransInfo->lpaDest, TRUE );
|
|
if( errCode != HB_SUCCESS )
|
|
return errCode;
|
|
|
|
pItem = hb_itemNew( NULL );
|
|
pTransItem = pTransInfo->lpTransItems;
|
|
for( uiCount = pTransInfo->uiItemCount; uiCount; --uiCount )
|
|
{
|
|
errCode = SELF_GETVALUE( ( AREAP ) pArea,
|
|
pTransItem->uiSource, pItem );
|
|
if( errCode != HB_SUCCESS )
|
|
break;
|
|
errCode = SELF_PUTVALUE( ( AREAP ) pTransInfo->lpaDest,
|
|
pTransItem->uiDest, pItem );
|
|
if( errCode != HB_SUCCESS )
|
|
break;
|
|
++pTransItem;
|
|
}
|
|
hb_itemRelease( pItem );
|
|
}
|
|
|
|
/* Delete the new record if copy fail */
|
|
if( errCode != HB_SUCCESS )
|
|
{
|
|
SELF_DELETE( ( AREAP ) pTransInfo->lpaDest );
|
|
return errCode;
|
|
}
|
|
|
|
/* Delete the new record */
|
|
if( bDeleted )
|
|
return SELF_DELETE( ( AREAP ) pTransInfo->lpaDest );
|
|
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* Report end of relation.
|
|
*/
|
|
static HB_ERRCODE hb_waChildEnd( AREAP pArea, LPDBRELINFO pRelInfo )
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waChildEnd(%p, %p)", pArea, pRelInfo));
|
|
|
|
if( pRelInfo->isScoped )
|
|
{
|
|
DBORDERINFO pInfo;
|
|
pInfo.itmOrder = NULL;
|
|
pInfo.atomBagName = NULL;
|
|
pInfo.itmResult = hb_itemNew( NULL );
|
|
pInfo.itmNewVal = NULL;
|
|
SELF_ORDINFO( pArea, DBOI_SCOPETOPCLEAR, &pInfo );
|
|
SELF_ORDINFO( pArea, DBOI_SCOPEBOTTOMCLEAR, &pInfo );
|
|
hb_itemRelease( pInfo.itmResult );
|
|
}
|
|
|
|
pArea->uiParents--;
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* Report initialization of a relation.
|
|
*/
|
|
static HB_ERRCODE hb_waChildStart( AREAP pArea, LPDBRELINFO pRelInfo )
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waChildStart(%p, %p)", pArea, pRelInfo));
|
|
HB_SYMBOL_UNUSED( pRelInfo );
|
|
|
|
pArea->uiParents ++;
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* Force relational movement in child WorkAreas.
|
|
*/
|
|
static HB_ERRCODE hb_waSyncChildren( AREAP pArea )
|
|
{
|
|
|
|
LPDBRELINFO lpdbRelation;
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waSyncChildren(%p)", pArea));
|
|
|
|
lpdbRelation = pArea->lpdbRelations;
|
|
while( lpdbRelation )
|
|
{
|
|
if( SELF_CHILDSYNC( lpdbRelation->lpaChild, lpdbRelation ) != HB_SUCCESS )
|
|
return HB_FAILURE;
|
|
lpdbRelation = lpdbRelation->lpdbriNext;
|
|
}
|
|
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* Clear all relations in the specified WorkArea.
|
|
*/
|
|
static HB_ERRCODE hb_waClearRel( AREAP pArea )
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waClearRel(%p)", pArea ));
|
|
|
|
/* Free all relations */
|
|
if( pArea->lpdbRelations )
|
|
{
|
|
int iCurrArea = hb_rddGetCurrentWorkAreaNumber();
|
|
|
|
do
|
|
{
|
|
LPDBRELINFO lpdbRelation = pArea->lpdbRelations;
|
|
|
|
hb_rddSelectWorkAreaNumber( lpdbRelation->lpaChild->uiArea );
|
|
SELF_CHILDEND( lpdbRelation->lpaChild, lpdbRelation );
|
|
pArea->lpdbRelations = lpdbRelation->lpdbriNext;
|
|
|
|
if( lpdbRelation->itmCobExpr )
|
|
{
|
|
hb_itemRelease( lpdbRelation->itmCobExpr );
|
|
}
|
|
if( lpdbRelation->abKey )
|
|
{
|
|
hb_itemRelease( lpdbRelation->abKey );
|
|
}
|
|
hb_xfree( lpdbRelation );
|
|
}
|
|
while( pArea->lpdbRelations );
|
|
|
|
hb_rddSelectWorkAreaNumber( iCurrArea );
|
|
}
|
|
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* Obtain the workarea number of the specified relation.
|
|
*/
|
|
static HB_ERRCODE hb_waRelArea( AREAP pArea, USHORT uiRelNo, void * pRelArea )
|
|
{
|
|
LPDBRELINFO lpdbRelations;
|
|
USHORT uiIndex = 1;
|
|
USHORT * pWA = (USHORT *) pRelArea;
|
|
/*TODO: Why pRelArea declared as void*? This creates casting hassles.*/
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waRelArea(%p, %hu, %p)", pArea, uiRelNo, pRelArea));
|
|
|
|
*pWA = 0;
|
|
lpdbRelations = pArea->lpdbRelations;
|
|
while( lpdbRelations )
|
|
{
|
|
if( uiIndex++ == uiRelNo )
|
|
{
|
|
*pWA = lpdbRelations->lpaChild->uiArea;
|
|
break;
|
|
}
|
|
lpdbRelations = lpdbRelations->lpdbriNext;
|
|
}
|
|
return *pWA ? HB_SUCCESS : HB_FAILURE;
|
|
}
|
|
|
|
/*
|
|
* Evaluate a block against the relation in specified WorkArea.
|
|
*/
|
|
static HB_ERRCODE hb_waRelEval( AREAP pArea, LPDBRELINFO pRelInfo )
|
|
{
|
|
PHB_ITEM pResult;
|
|
DBORDERINFO pInfo;
|
|
HB_ERRCODE errCode;
|
|
int iOrder;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waRelEval(%p, %p)", pArea, pRelInfo));
|
|
|
|
errCode = SELF_EVALBLOCK( pRelInfo->lpaParent, pRelInfo->itmCobExpr );
|
|
|
|
if( errCode == HB_SUCCESS )
|
|
{
|
|
/*
|
|
* Check the current order
|
|
*/
|
|
pResult = pRelInfo->lpaParent->valResult;
|
|
pRelInfo->lpaParent->valResult = NULL;
|
|
memset( &pInfo, 0, sizeof( DBORDERINFO ) );
|
|
pInfo.itmResult = hb_itemPutNI( NULL, 0 );
|
|
errCode = SELF_ORDINFO( pArea, DBOI_NUMBER, &pInfo );
|
|
|
|
if( errCode == HB_SUCCESS )
|
|
{
|
|
iOrder = hb_itemGetNI( pInfo.itmResult );
|
|
if( iOrder != 0 )
|
|
{
|
|
if( pRelInfo->isScoped )
|
|
{
|
|
pInfo.itmNewVal = pResult;
|
|
errCode = SELF_ORDINFO( pArea, DBOI_SCOPETOP, &pInfo );
|
|
if( errCode == HB_SUCCESS )
|
|
errCode = SELF_ORDINFO( pArea, DBOI_SCOPEBOTTOM, &pInfo );
|
|
}
|
|
if( errCode == HB_SUCCESS )
|
|
errCode = SELF_SEEK( pArea, FALSE, pResult, FALSE );
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* If current order equals to zero, use GOTOID instead of SEEK
|
|
* Unfortunately it interacts with buggy .prg code which returns
|
|
* non numerical values from relation expression and RDD accepts
|
|
* only numerical record ID. In such case SELF_GOTO() works like
|
|
* SELF_GOEOF() but SELF_GOTOID() reports error. So for Clipper
|
|
* compatibility SELF_GOTO() is used here but if RDD can use
|
|
* non numerical record IDs then this method should be overloaded
|
|
* to use SELF_GOTOID(), [druzus]
|
|
*/
|
|
/* errCode = SELF_GOTOID( pArea, pResult ); */
|
|
errCode = SELF_GOTO( pArea, hb_itemGetNL( pResult ) );
|
|
}
|
|
}
|
|
hb_itemRelease( pInfo.itmResult );
|
|
hb_itemRelease( pResult );
|
|
}
|
|
|
|
return errCode;
|
|
}
|
|
|
|
/*
|
|
* Obtain the character expression of the specified relation.
|
|
*/
|
|
static HB_ERRCODE hb_waRelText( AREAP pArea, USHORT uiRelNo, PHB_ITEM pExpr )
|
|
{
|
|
LPDBRELINFO lpdbRelations;
|
|
USHORT uiIndex = 1;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waRelText(%p, %hu, %p)", pArea, uiRelNo, pExpr));
|
|
|
|
lpdbRelations = pArea->lpdbRelations;
|
|
|
|
while( lpdbRelations )
|
|
{
|
|
if( uiIndex++ == uiRelNo )
|
|
{
|
|
hb_itemCopy( pExpr, lpdbRelations->abKey );
|
|
return HB_SUCCESS;
|
|
}
|
|
lpdbRelations = lpdbRelations->lpdbriNext;
|
|
}
|
|
|
|
return HB_FAILURE;
|
|
}
|
|
|
|
/*
|
|
* Set a relation in the parent file.
|
|
*/
|
|
static HB_ERRCODE hb_waSetRel( AREAP pArea, LPDBRELINFO lpdbRelInf )
|
|
{
|
|
LPDBRELINFO lpdbRelations;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waSetRel(%p, %p)", pArea, lpdbRelInf));
|
|
|
|
lpdbRelations = pArea->lpdbRelations;
|
|
if( ! lpdbRelations )
|
|
{
|
|
pArea->lpdbRelations = ( LPDBRELINFO ) hb_xgrab( sizeof( DBRELINFO ) );
|
|
lpdbRelations = pArea->lpdbRelations;
|
|
}
|
|
else
|
|
{
|
|
while( lpdbRelations->lpdbriNext )
|
|
lpdbRelations = lpdbRelations->lpdbriNext;
|
|
lpdbRelations->lpdbriNext = ( LPDBRELINFO ) hb_xgrab( sizeof( DBRELINFO ) );
|
|
lpdbRelations = lpdbRelations->lpdbriNext;
|
|
}
|
|
lpdbRelations->lpaParent = pArea;
|
|
lpdbRelations->lpaChild = lpdbRelInf->lpaChild;
|
|
lpdbRelations->itmCobExpr = lpdbRelInf->itmCobExpr;
|
|
lpdbRelations->isScoped = lpdbRelInf->isScoped;
|
|
lpdbRelations->isOptimized = lpdbRelInf->isOptimized;
|
|
lpdbRelations->abKey = lpdbRelInf->abKey;
|
|
lpdbRelations->lpdbriNext = lpdbRelInf->lpdbriNext;
|
|
|
|
return SELF_CHILDSTART( ( AREAP ) lpdbRelInf->lpaChild, lpdbRelations );
|
|
}
|
|
|
|
/*
|
|
* Clear the active filter expression.
|
|
*/
|
|
static HB_ERRCODE hb_waClearFilter( AREAP pArea )
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waClearFilter(%p)", pArea));
|
|
|
|
/* Free all items */
|
|
if( pArea->dbfi.itmCobExpr )
|
|
{
|
|
hb_itemRelease( pArea->dbfi.itmCobExpr );
|
|
pArea->dbfi.itmCobExpr = NULL;
|
|
}
|
|
if( pArea->dbfi.abFilterText )
|
|
{
|
|
hb_itemRelease( pArea->dbfi.abFilterText );
|
|
pArea->dbfi.abFilterText = NULL;
|
|
}
|
|
pArea->dbfi.fOptimized = FALSE;
|
|
pArea->dbfi.fFilter = FALSE;
|
|
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* Clear the active locate expression.
|
|
*/
|
|
static HB_ERRCODE hb_waClearLocate( AREAP pArea )
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waClearLocate(%p)", pArea));
|
|
|
|
/* Free all items */
|
|
if( pArea->dbsi.itmCobFor )
|
|
{
|
|
hb_itemRelease( pArea->dbsi.itmCobFor );
|
|
pArea->dbsi.itmCobFor = NULL;
|
|
}
|
|
if( pArea->dbsi.lpstrFor )
|
|
{
|
|
hb_itemRelease( pArea->dbsi.lpstrFor );
|
|
pArea->dbsi.lpstrFor = NULL;
|
|
}
|
|
if( pArea->dbsi.itmCobWhile )
|
|
{
|
|
hb_itemRelease( pArea->dbsi.itmCobWhile );
|
|
pArea->dbsi.itmCobWhile = NULL;
|
|
}
|
|
if( pArea->dbsi.lpstrWhile )
|
|
{
|
|
hb_itemRelease( pArea->dbsi.lpstrWhile );
|
|
pArea->dbsi.lpstrWhile = NULL;
|
|
}
|
|
if( pArea->dbsi.lNext )
|
|
{
|
|
hb_itemRelease( pArea->dbsi.lNext );
|
|
pArea->dbsi.lNext = NULL;
|
|
}
|
|
if( pArea->dbsi.itmRecID )
|
|
{
|
|
hb_itemRelease( pArea->dbsi.itmRecID );
|
|
pArea->dbsi.itmRecID = NULL;
|
|
}
|
|
if( pArea->dbsi.fRest )
|
|
{
|
|
hb_itemRelease( pArea->dbsi.fRest );
|
|
pArea->dbsi.fRest = NULL;
|
|
}
|
|
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* Return filter condition of the specified WorkArea.
|
|
*/
|
|
static HB_ERRCODE hb_waFilterText( AREAP pArea, PHB_ITEM pFilter )
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waFilterText(%p, %p)", pArea, pFilter));
|
|
|
|
if( pArea->dbfi.abFilterText )
|
|
hb_itemCopy( pFilter, pArea->dbfi.abFilterText );
|
|
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* Set the filter condition for the specified WorkArea.
|
|
*/
|
|
static HB_ERRCODE hb_waSetFilter( AREAP pArea, LPDBFILTERINFO pFilterInfo )
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waSetFilter(%p, %p)", pArea, pFilterInfo));
|
|
|
|
/* Clear the active filter expression */
|
|
if( SELF_CLEARFILTER( pArea ) != HB_SUCCESS )
|
|
return HB_FAILURE;
|
|
|
|
if( pFilterInfo->itmCobExpr )
|
|
{
|
|
pArea->dbfi.itmCobExpr = hb_itemNew( pFilterInfo->itmCobExpr );
|
|
}
|
|
if( pFilterInfo->abFilterText )
|
|
{
|
|
pArea->dbfi.abFilterText = hb_itemNew( pFilterInfo->abFilterText );
|
|
}
|
|
pArea->dbfi.fOptimized = pFilterInfo->fOptimized;
|
|
pArea->dbfi.fFilter = TRUE;
|
|
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* Set the locate scope for the specified WorkArea.
|
|
*/
|
|
static HB_ERRCODE hb_waSetLocate( AREAP pArea, LPDBSCOPEINFO pScopeInfo )
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waSetLocate(%p, %p)", pArea, pScopeInfo));
|
|
|
|
/* Clear the active locate expression */
|
|
if( SELF_CLEARLOCATE( pArea ) != HB_SUCCESS )
|
|
return HB_FAILURE;
|
|
|
|
if( pScopeInfo->itmCobFor )
|
|
pArea->dbsi.itmCobFor = hb_itemNew( pScopeInfo->itmCobFor );
|
|
|
|
if( pScopeInfo->lpstrFor )
|
|
pArea->dbsi.lpstrFor = hb_itemNew( pScopeInfo->lpstrFor );
|
|
|
|
if( pScopeInfo->itmCobWhile )
|
|
pArea->dbsi.itmCobWhile = hb_itemNew( pScopeInfo->itmCobWhile );
|
|
|
|
if( pScopeInfo->lpstrWhile )
|
|
pArea->dbsi.lpstrWhile = hb_itemNew( pScopeInfo->lpstrWhile );
|
|
|
|
if( pScopeInfo->lNext )
|
|
pArea->dbsi.lNext = hb_itemNew( pScopeInfo->lNext );
|
|
|
|
if( pScopeInfo->itmRecID )
|
|
pArea->dbsi.itmRecID = hb_itemNew( pScopeInfo->itmRecID );
|
|
|
|
if( pScopeInfo->fRest )
|
|
pArea->dbsi.fRest = hb_itemNew( pScopeInfo->fRest );
|
|
|
|
pArea->dbsi.fIgnoreFilter = pScopeInfo->fIgnoreFilter;
|
|
pArea->dbsi.fIncludeDeleted = pScopeInfo->fIncludeDeleted;
|
|
pArea->dbsi.fLast = pScopeInfo->fLast;
|
|
pArea->dbsi.fIgnoreDuplicates = pScopeInfo->fIgnoreDuplicates;
|
|
pArea->dbsi.fBackward = pScopeInfo->fBackward;
|
|
pArea->dbsi.fOptimized = pScopeInfo->fOptimized;
|
|
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* Compile a character expression.
|
|
*/
|
|
static HB_ERRCODE hb_waCompile( AREAP pArea, BYTE * pExpr )
|
|
{
|
|
HB_MACRO_PTR pMacro;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waCompile(%p, %p)", pArea, pExpr));
|
|
|
|
pMacro = hb_macroCompile( ( char * ) pExpr );
|
|
if( pMacro )
|
|
{
|
|
pArea->valResult = hb_itemPutPtr( pArea->valResult, ( void * ) pMacro );
|
|
return HB_SUCCESS;
|
|
}
|
|
else
|
|
return HB_FAILURE;
|
|
}
|
|
|
|
/*
|
|
* Raise a runtime error.
|
|
*/
|
|
static HB_ERRCODE hb_waError( AREAP pArea, PHB_ITEM pError )
|
|
{
|
|
char * szRddName;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waError(%p, %p)", pArea, pError));
|
|
|
|
szRddName = ( char * ) hb_xgrab( HB_RDD_MAX_DRIVERNAME_LEN + 1 );
|
|
if( pArea && pArea->lprfsHost->sysName )
|
|
SELF_SYSNAME( pArea, ( BYTE * ) szRddName );
|
|
else
|
|
hb_strncpy( szRddName, "???DRIVER", HB_RDD_MAX_DRIVERNAME_LEN );
|
|
hb_errPutSeverity( pError, ES_ERROR );
|
|
hb_errPutSubSystem( pError, szRddName );
|
|
hb_xfree( szRddName );
|
|
return hb_errLaunch( pError );
|
|
}
|
|
|
|
/*
|
|
* Evaluate a code block.
|
|
*/
|
|
static HB_ERRCODE hb_waEvalBlock( AREAP pArea, PHB_ITEM pBlock )
|
|
{
|
|
PHB_ITEM pItem;
|
|
int iCurrArea, iUsedArea;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waEvalBlock(%p, %p)", pArea, pBlock));
|
|
|
|
iCurrArea = hb_rddGetCurrentWorkAreaNumber();
|
|
iUsedArea = pArea->uiArea;
|
|
if( iCurrArea != iUsedArea )
|
|
hb_rddSelectWorkAreaNumber( iUsedArea );
|
|
|
|
pItem = hb_vmEvalBlockOrMacro( pBlock );
|
|
|
|
if( ( AREAP ) hb_rddGetWorkAreaPointer( iUsedArea ) != pArea )
|
|
return HB_FAILURE;
|
|
|
|
if( ! pArea->valResult )
|
|
pArea->valResult = hb_itemNew( NULL );
|
|
hb_itemCopy( pArea->valResult, pItem );
|
|
|
|
hb_rddSelectWorkAreaNumber( iCurrArea );
|
|
|
|
return hb_vmRequestQuery() ? HB_FAILURE : HB_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* RDD info
|
|
*/
|
|
static HB_ERRCODE hb_waRddInfo( LPRDDNODE pRDD, USHORT uiIndex, ULONG ulConnection, PHB_ITEM pItem )
|
|
{
|
|
BOOL fResult;
|
|
int iResult;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_rddInfo(%p, %hu, %lu, %p)", pRDD, uiIndex, ulConnection, pItem));
|
|
|
|
HB_SYMBOL_UNUSED( pRDD );
|
|
HB_SYMBOL_UNUSED( ulConnection );
|
|
|
|
switch( uiIndex )
|
|
{
|
|
case RDDI_ISDBF:
|
|
case RDDI_CANPUTREC:
|
|
case RDDI_LOCAL:
|
|
case RDDI_REMOTE:
|
|
case RDDI_RECORDMAP:
|
|
case RDDI_ENCRYPTION:
|
|
case RDDI_AUTOLOCK:
|
|
case RDDI_STRUCTORD:
|
|
case RDDI_LARGEFILE:
|
|
case RDDI_MULTITAG:
|
|
case RDDI_SORTRECNO:
|
|
case RDDI_MULTIKEY:
|
|
case RDDI_BLOB_SUPPORT:
|
|
hb_itemPutL( pItem, FALSE );
|
|
break;
|
|
|
|
case RDDI_CONNECTION:
|
|
case RDDI_TABLETYPE:
|
|
case RDDI_MEMOTYPE:
|
|
case RDDI_MEMOVERSION:
|
|
hb_itemPutNI( pItem, 0 );
|
|
break;
|
|
|
|
case RDDI_STRICTREAD:
|
|
fResult = hb_setGetStrictRead();
|
|
if( hb_itemType( pItem ) == HB_IT_LOGICAL )
|
|
hb_setSetItem( HB_SET_STRICTREAD, pItem );
|
|
hb_itemPutL( pItem, fResult );
|
|
break;
|
|
case RDDI_OPTIMIZE:
|
|
fResult = hb_setGetOptimize();
|
|
if( hb_itemType( pItem ) == HB_IT_LOGICAL )
|
|
hb_setSetItem( HB_SET_OPTIMIZE, pItem );
|
|
hb_itemPutL( pItem, fResult );
|
|
break;
|
|
case RDDI_FORCEOPT:
|
|
fResult = hb_setGetForceOpt();
|
|
if( hb_itemType( pItem ) == HB_IT_LOGICAL )
|
|
hb_setSetItem( HB_SET_FORCEOPT, pItem );
|
|
hb_itemPutL( pItem, fResult );
|
|
break;
|
|
case RDDI_AUTOOPEN:
|
|
fResult = hb_setGetAutOpen();
|
|
if( hb_itemType( pItem ) == HB_IT_LOGICAL )
|
|
hb_setSetItem( HB_SET_AUTOPEN, pItem );
|
|
hb_itemPutL( pItem, fResult );
|
|
break;
|
|
case RDDI_AUTOORDER:
|
|
fResult = hb_setGetAutOrder();
|
|
if( hb_itemType( pItem ) == HB_IT_LOGICAL )
|
|
hb_setSetItem( HB_SET_AUTORDER, pItem );
|
|
hb_itemPutL( pItem, fResult );
|
|
break;
|
|
case RDDI_AUTOSHARE:
|
|
fResult = hb_setGetAutoShare();
|
|
if( hb_itemType( pItem ) == HB_IT_LOGICAL )
|
|
hb_setSetItem( HB_SET_AUTOSHARE, pItem );
|
|
hb_itemPutL( pItem, fResult );
|
|
break;
|
|
case RDDI_LOCKSCHEME:
|
|
iResult = hb_setGetDBFLockScheme();
|
|
if( hb_itemType( pItem ) & HB_IT_NUMERIC )
|
|
hb_setSetItem( HB_SET_DBFLOCKSCHEME, pItem );
|
|
hb_itemPutNI( pItem, iResult );
|
|
break;
|
|
case RDDI_MEMOBLOCKSIZE:
|
|
iResult = hb_setGetMBlockSize();
|
|
if( hb_itemType( pItem ) & HB_IT_NUMERIC )
|
|
hb_setSetItem( HB_SET_MBLOCKSIZE, pItem );
|
|
hb_itemPutNI( pItem, iResult );
|
|
break;
|
|
case RDDI_MEMOEXT:
|
|
{
|
|
const char * szExt = hb_setGetMFileExt();
|
|
char * szResult = szExt ? hb_strdup( szExt ) : NULL;
|
|
if( hb_itemType( pItem ) & HB_IT_STRING )
|
|
{
|
|
hb_setSetItem( HB_SET_MFILEEXT, pItem );
|
|
if( szResult )
|
|
hb_itemPutCLPtr( pItem, szResult, strlen( szResult ) );
|
|
else
|
|
hb_itemPutC( pItem, NULL );
|
|
break;
|
|
}
|
|
else if( szResult )
|
|
{
|
|
hb_itemPutCLPtr( pItem, szResult, strlen( szResult ) );
|
|
break;
|
|
}
|
|
/* no break - return HB_FAILURE */
|
|
}
|
|
case RDDI_TABLEEXT:
|
|
case RDDI_ORDBAGEXT:
|
|
case RDDI_ORDEREXT:
|
|
case RDDI_ORDSTRUCTEXT:
|
|
case RDDI_DELIMITER:
|
|
case RDDI_SEPARATOR:
|
|
case RDDI_TRIGGER:
|
|
case RDDI_PENDINGTRIGGER:
|
|
hb_itemPutC( pItem, NULL );
|
|
/* no break - return HB_FAILURE */
|
|
|
|
default:
|
|
return HB_FAILURE;
|
|
}
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* Raise a runtime error if an method is not defined.
|
|
*/
|
|
static HB_ERRCODE hb_waUnsupported( AREAP pArea )
|
|
{
|
|
PHB_ITEM pError;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waUnsupported(%p)", pArea));
|
|
|
|
pError = hb_errNew();
|
|
hb_errPutGenCode( pError, EG_UNSUPPORTED );
|
|
hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_UNSUPPORTED ) );
|
|
SELF_ERROR( pArea, pError );
|
|
hb_itemRelease( pError );
|
|
|
|
return HB_FAILURE;
|
|
}
|
|
|
|
/*
|
|
* Raise a runtime error if an method is not defined.
|
|
*/
|
|
static HB_ERRCODE hb_waRddUnsupported( LPRDDNODE pRDD )
|
|
{
|
|
PHB_ITEM pError;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waRDDUnsupported(%p)", pRDD));
|
|
|
|
pError = hb_errNew();
|
|
hb_errPutGenCode( pError, EG_UNSUPPORTED );
|
|
hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_UNSUPPORTED ) );
|
|
|
|
hb_errPutSeverity( pError, ES_ERROR );
|
|
hb_errPutSubSystem( pError, pRDD->szName );
|
|
hb_errLaunch( pError );
|
|
hb_itemRelease( pError );
|
|
|
|
return HB_FAILURE;
|
|
}
|
|
|
|
#if 0
|
|
/*
|
|
* Empty method.
|
|
*/
|
|
static HB_ERRCODE hb_waNull( AREAP pArea )
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_waNull(%p)", pArea));
|
|
|
|
HB_SYMBOL_UNUSED( pArea );
|
|
|
|
return HB_SUCCESS;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* The default virtual method table for all WorkAreas.
|
|
*/
|
|
static const RDDFUNCS waTable =
|
|
{
|
|
/* Movement and positioning methods */
|
|
/* ( DBENTRYP_BP ) */ hb_waBof, /* Bof */
|
|
/* ( DBENTRYP_BP ) */ hb_waEof, /* Eof */
|
|
/* ( DBENTRYP_BP ) */ hb_waFound, /* Found */
|
|
( DBENTRYP_V ) hb_waUnsupported, /* GoBottom */
|
|
( DBENTRYP_UL ) hb_waUnsupported, /* GoTo */
|
|
( DBENTRYP_I ) hb_waUnsupported, /* GoToId */
|
|
( DBENTRYP_V ) hb_waUnsupported, /* GoTop */
|
|
( DBENTRYP_BIB ) hb_waUnsupported, /* Seek */
|
|
/* ( DBENTRYP_L ) */ hb_waSkip, /* Skip */
|
|
/* ( DBENTRYP_L ) */ hb_waSkipFilter, /* SkipFilter */
|
|
( DBENTRYP_L ) hb_waUnsupported, /* SkipRaw */
|
|
|
|
/* Data management */
|
|
/* ( DBENTRYP_VF ) */ hb_waAddField, /* AddField */
|
|
( DBENTRYP_B ) hb_waUnsupported, /* Append */
|
|
/* ( DBENTRYP_I ) */ hb_waCreateFields, /* CreateFields */
|
|
( DBENTRYP_V ) hb_waUnsupported, /* DeleteRec */
|
|
( DBENTRYP_BP ) hb_waUnsupported, /* Deleted */
|
|
/* ( DBENTRYP_SP ) */ hb_waFieldCount, /* FieldCount */
|
|
( DBENTRYP_VF ) hb_waUnsupported, /* FieldDisplay */
|
|
/* ( DBENTRYP_SSI ) */ hb_waFieldInfo, /* FieldInfo */
|
|
/* ( DBENTRYP_SVP ) */ hb_waFieldName, /* FieldName */
|
|
( DBENTRYP_V ) hb_waUnsupported, /* Flush */
|
|
( DBENTRYP_PP ) hb_waUnsupported, /* GetRec */
|
|
( DBENTRYP_SI ) hb_waUnsupported, /* GetValue */
|
|
( DBENTRYP_SVL ) hb_waUnsupported, /* GetVarLen */
|
|
( DBENTRYP_V ) hb_waUnsupported, /* GoCold */
|
|
( DBENTRYP_V ) hb_waUnsupported, /* GoHot */
|
|
( DBENTRYP_P ) hb_waUnsupported, /* PutRec */
|
|
( DBENTRYP_SI ) hb_waUnsupported, /* PutValue */
|
|
( DBENTRYP_V ) hb_waUnsupported, /* Recall */
|
|
( DBENTRYP_ULP ) hb_waUnsupported, /* RecCount */
|
|
( DBENTRYP_ISI ) hb_waUnsupported, /* RecInfo */
|
|
( DBENTRYP_ULP ) hb_waUnsupported, /* RecNo */
|
|
( DBENTRYP_I ) hb_waUnsupported, /* RecId */
|
|
/* ( DBENTRYP_S ) */ hb_waSetFieldExtent, /* SetFieldExtent */
|
|
|
|
/* WorkArea/Database management */
|
|
/* ( DBENTRYP_P ) */ hb_waAlias, /* Alias */
|
|
/* ( DBENTRYP_V ) */ hb_waClose, /* Close */
|
|
/* Like in Clipper map CREATE() method at work area level to OPEN() */
|
|
/* ( DBENTRYP_VP ) */ hb_waOpen, /* Create */
|
|
/* ( DBENTRYP_SI ) */ hb_waInfo, /* Info */
|
|
/* ( DBENTRYP_V ) */ hb_waNewArea, /* NewArea */
|
|
/* ( DBENTRYP_VP ) */ hb_waOpen, /* Open */
|
|
/* ( DBENTRYP_V ) */ hb_waRelease, /* Release */
|
|
/* ( DBENTRYP_SP ) */ hb_waStructSize, /* StructSize */
|
|
/* ( DBENTRYP_P ) */ hb_waSysName, /* SysName */
|
|
/* ( DBENTRYP_VEI ) */ hb_waEval, /* Eval */
|
|
( DBENTRYP_V ) hb_waUnsupported, /* Pack */
|
|
( DBENTRYP_LSP ) hb_waUnsupported, /* PackRec */
|
|
( DBENTRYP_VS ) hb_waUnsupported, /* Sort */
|
|
/* ( DBENTRYP_VT ) */ hb_waTrans, /* Trans */
|
|
/* ( DBENTRYP_VT ) */ hb_waTransRec, /* TransRec */
|
|
( DBENTRYP_V ) hb_waUnsupported, /* Zap */
|
|
|
|
/* Relational Methods */
|
|
/* ( DBENTRYP_VR ) */ hb_waChildEnd, /* ChildEnd */
|
|
/* ( DBENTRYP_VR ) */ hb_waChildStart, /* ChildStart */
|
|
( DBENTRYP_VR ) hb_waUnsupported, /* ChildSync */
|
|
/* ( DBENTRYP_V ) */ hb_waSyncChildren, /* SyncChildren */
|
|
/* ( DBENTRYP_V ) */ hb_waClearRel, /* ClearRel */
|
|
( DBENTRYP_V ) hb_waUnsupported, /* ForceRel */
|
|
/* ( DBENTRYP_SVP ) */ hb_waRelArea, /* RelArea */
|
|
/* ( DBENTRYP_VR ) */ hb_waRelEval, /* RelEval */
|
|
/* ( DBENTRYP_SI ) */ hb_waRelText, /* RelText */
|
|
/* ( DBENTRYP_VR ) */ hb_waSetRel, /* SetRel */
|
|
|
|
/* Order Management */
|
|
( DBENTRYP_OI ) hb_waUnsupported, /* OrderListAdd */
|
|
( DBENTRYP_V ) hb_waUnsupported, /* OrderListClear */
|
|
( DBENTRYP_OI ) hb_waUnsupported, /* OrderListDelete */
|
|
( DBENTRYP_OI ) hb_waUnsupported, /* OrderListFocus */
|
|
( DBENTRYP_V ) hb_waUnsupported, /* OrderListRebuild */
|
|
/* ( DBENTRYP_VOI ) */ hb_waOrderCondition, /* OrderCondition */
|
|
( DBENTRYP_VOC ) hb_waUnsupported, /* OrderCreate */
|
|
( DBENTRYP_OI ) hb_waUnsupported, /* OrderDestroy */
|
|
/* ( DBENTRYP_OII ) */ hb_waOrderInfo, /* OrderInfo */
|
|
|
|
/* Filters and Scope Settings */
|
|
/* ( DBENTRYP_V ) */ hb_waClearFilter, /* ClearFilter */
|
|
/* ( DBENTRYP_V ) */ hb_waClearLocate, /* ClearLocate */
|
|
( DBENTRYP_V ) hb_waUnsupported, /* ClearScope */
|
|
( DBENTRYP_VPLP ) hb_waUnsupported, /* CountScope */
|
|
/* ( DBENTRYP_I ) */ hb_waFilterText, /* FilterText */
|
|
( DBENTRYP_SI ) hb_waUnsupported, /* ScopeInfo */
|
|
/* ( DBENTRYP_VFI ) */ hb_waSetFilter, /* SetFilter */
|
|
/* ( DBENTRYP_VLO ) */ hb_waSetLocate, /* SetLocate */
|
|
( DBENTRYP_VOS ) hb_waUnsupported, /* SetScope */
|
|
( DBENTRYP_VPL ) hb_waUnsupported, /* SkipScope */
|
|
/* ( DBENTRYP_B ) */ hb_waLocate, /* Locate */
|
|
|
|
/* Miscellaneous */
|
|
/* ( DBENTRYP_P ) */ hb_waCompile, /* Compile */
|
|
/* ( DBENTRYP_I ) */ hb_waError, /* Error */
|
|
/* ( DBENTRYP_I ) */ hb_waEvalBlock, /* EvalBlock */
|
|
|
|
/* Network operations */
|
|
( DBENTRYP_VSP ) hb_waUnsupported, /* RawLock */
|
|
( DBENTRYP_VL ) hb_waUnsupported, /* Lock */
|
|
( DBENTRYP_I ) hb_waUnsupported, /* UnLock */
|
|
|
|
/* Memofile functions */
|
|
( DBENTRYP_V ) hb_waUnsupported, /* CloseMemFile */
|
|
( DBENTRYP_VP ) hb_waUnsupported, /* CreateMemFile */
|
|
( DBENTRYP_SVPB ) hb_waUnsupported, /* GetValueFile */
|
|
( DBENTRYP_VP ) hb_waUnsupported, /* OpenMemFile */
|
|
( DBENTRYP_SVPB ) hb_waUnsupported, /* PutValueFile */
|
|
|
|
/* Database file header handling */
|
|
( DBENTRYP_V ) hb_waUnsupported, /* ReadDBHeader */
|
|
( DBENTRYP_V ) hb_waUnsupported, /* WriteDBHeader */
|
|
|
|
/* non WorkArea functions */
|
|
( DBENTRYP_R ) NULL, /* Init */
|
|
( DBENTRYP_R ) NULL, /* Exit */
|
|
( DBENTRYP_RVVL ) hb_waRddUnsupported, /* Drop */
|
|
( DBENTRYP_RVVL ) hb_waRddUnsupported, /* Exists */
|
|
/* ( DBENTRYP_RSLV ) */ hb_waRddInfo, /* RddInfo */
|
|
|
|
/* Special and reserved methods */
|
|
( DBENTRYP_SVP ) hb_waUnsupported /* WhoCares */
|
|
};
|
|
|
|
#define HB_RDD_POOL_ALLOCSIZE 128
|
|
/* common for all threads list of registered RDDs */
|
|
static HB_CRITICAL_NEW( s_rddMtx );
|
|
static LPRDDNODE * s_RddList = NULL; /* Registered RDDs pool */
|
|
static USHORT s_uiRddMax = 0; /* Size of RDD pool */
|
|
static USHORT s_uiRddCount = 0; /* Number of registered RDD */
|
|
|
|
/*
|
|
* Get RDD node poionter
|
|
*/
|
|
LPRDDNODE hb_rddGetNode( USHORT uiNode )
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_rddGetNode(%hu)", uiNode));
|
|
|
|
return uiNode < s_uiRddCount ? s_RddList[ uiNode ] : NULL;
|
|
}
|
|
|
|
PHB_ITEM hb_rddList( USHORT uiType )
|
|
{
|
|
USHORT uiCount, uiIndex, uiRdds;
|
|
PHB_ITEM pRddArray;
|
|
LPRDDNODE pNode;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_rddList(%hu)", uiType));
|
|
|
|
for( uiCount = uiRdds = 0; uiCount < s_uiRddCount; ++uiCount )
|
|
{
|
|
if( uiType == 0 || s_RddList[ uiCount ]->uiType == uiType )
|
|
++uiRdds;
|
|
}
|
|
pRddArray = hb_itemArrayNew( uiRdds );
|
|
for( uiCount = uiIndex = 0; uiCount < s_uiRddCount && uiIndex < uiRdds; ++uiCount )
|
|
{
|
|
pNode = s_RddList[ uiCount ];
|
|
if( uiType == 0 || pNode->uiType == uiType )
|
|
hb_arraySetC( pRddArray, ++uiIndex, pNode->szName );
|
|
}
|
|
return pRddArray;
|
|
}
|
|
|
|
/*
|
|
* Find a RDD node.
|
|
*/
|
|
LPRDDNODE hb_rddFindNode( const char * szDriver, USHORT * uiIndex )
|
|
{
|
|
USHORT uiCount;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_rddFindNode(%s, %p)", szDriver, uiIndex));
|
|
|
|
for( uiCount = 0; uiCount < s_uiRddCount; uiCount++ )
|
|
{
|
|
LPRDDNODE pNode = s_RddList[ uiCount ];
|
|
if( strcmp( pNode->szName, szDriver ) == 0 ) /* Matched RDD */
|
|
{
|
|
if( uiIndex )
|
|
* uiIndex = uiCount;
|
|
return pNode;
|
|
}
|
|
}
|
|
if( uiIndex )
|
|
* uiIndex = 0;
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* Shutdown the RDD system.
|
|
*/
|
|
void hb_rddShutDown( void )
|
|
{
|
|
USHORT uiCount;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_rddShutDown()"));
|
|
|
|
hb_rddCloseDetachedAreas();
|
|
|
|
if( s_uiRddCount > 0 )
|
|
{
|
|
for( uiCount = 0; uiCount < s_uiRddCount; uiCount++ )
|
|
{
|
|
if( s_RddList[ uiCount ]->pTable.exit != NULL )
|
|
{
|
|
SELF_EXIT( s_RddList[ uiCount ] );
|
|
}
|
|
hb_xfree( s_RddList[ uiCount ] );
|
|
}
|
|
hb_xfree( s_RddList );
|
|
s_RddList = NULL;
|
|
s_uiRddMax = s_uiRddCount = 0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Register a RDD driver.
|
|
*/
|
|
int hb_rddRegister( const char * szDriver, USHORT uiType )
|
|
{
|
|
LPRDDNODE pRddNewNode;
|
|
PHB_DYNS pGetFuncTable;
|
|
char szGetFuncTable[ HB_RDD_MAX_DRIVERNAME_LEN + 14 ];
|
|
USHORT uiFunctions;
|
|
int iResult;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_rddRegister(%s, %hu)", szDriver, uiType));
|
|
|
|
if( hb_rddFindNode( szDriver, NULL ) ) /* Duplicated RDD */
|
|
return 1;
|
|
|
|
hb_snprintf( szGetFuncTable, sizeof( szGetFuncTable ), "%s_GETFUNCTABLE",
|
|
szDriver );
|
|
pGetFuncTable = hb_dynsymFindName( szGetFuncTable );
|
|
if( !pGetFuncTable )
|
|
return 2; /* Not valid RDD */
|
|
|
|
/* Create a new RDD node */
|
|
pRddNewNode = ( LPRDDNODE ) hb_xgrab( sizeof( RDDNODE ) );
|
|
memset( pRddNewNode, 0, sizeof( RDDNODE ) );
|
|
|
|
/* Fill the new RDD node */
|
|
hb_strncpy( pRddNewNode->szName, szDriver, sizeof( pRddNewNode->szName ) - 1 );
|
|
pRddNewNode->uiType = uiType;
|
|
pRddNewNode->rddID = s_uiRddCount;
|
|
|
|
/* Call <szDriver>_GETFUNCTABLE() */
|
|
hb_vmPushDynSym( pGetFuncTable );
|
|
hb_vmPushNil();
|
|
hb_vmPushPointer( ( void * ) &uiFunctions );
|
|
hb_vmPushPointer( ( void * ) &pRddNewNode->pTable );
|
|
hb_vmPushPointer( ( void * ) &pRddNewNode->pSuperTable );
|
|
hb_vmPushInteger( s_uiRddCount );
|
|
hb_vmProc( 4 );
|
|
if( hb_parni( -1 ) != HB_SUCCESS )
|
|
iResult = 3; /* Invalid FUNCTABLE */
|
|
else
|
|
{
|
|
hb_threadEnterCriticalSection( &s_rddMtx );
|
|
/* repeat the test to protect against possible registering RDD by
|
|
* <szDriver>_GETFUNCTABLE()
|
|
*/
|
|
if( ! hb_rddFindNode( szDriver, NULL ) ) /* Duplicated RDD */
|
|
{
|
|
if( s_uiRddCount == s_uiRddMax )
|
|
{
|
|
s_uiRddMax += HB_RDD_POOL_ALLOCSIZE;
|
|
s_RddList = ( LPRDDNODE * )
|
|
hb_xrealloc( s_RddList, sizeof( LPRDDNODE ) * s_uiRddMax );
|
|
}
|
|
s_RddList[ s_uiRddCount ] = pRddNewNode; /* Add the new RDD node */
|
|
s_uiRddCount++;
|
|
iResult = 0;
|
|
}
|
|
else
|
|
iResult = 1;
|
|
hb_threadLeaveCriticalSection( &s_rddMtx );
|
|
}
|
|
|
|
if( iResult != 0 )
|
|
hb_xfree( pRddNewNode );
|
|
else if( pRddNewNode->pTable.init != NULL )
|
|
SELF_INIT( pRddNewNode );
|
|
|
|
return iResult;
|
|
}
|
|
|
|
/*
|
|
* pTable - a table in new RDDNODE that will be filled
|
|
* pSubTable - a table with a list of supported functions
|
|
* pSuperTable - a current table in a RDDNODE
|
|
* szDrvName - a driver name that will be inherited
|
|
*/
|
|
HB_ERRCODE hb_rddInherit( RDDFUNCS * pTable, const RDDFUNCS * pSubTable, RDDFUNCS * pSuperTable, const char * szDrvName )
|
|
{
|
|
LPRDDNODE pRddNode;
|
|
USHORT uiCount;
|
|
DBENTRYP_V * pFunction, * pSubFunction;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_rddInherit(%p, %p, %p, %s)", pTable, pSubTable, pSuperTable, szDrvName));
|
|
|
|
if( !pTable )
|
|
{
|
|
return HB_FAILURE;
|
|
}
|
|
|
|
/* Copy the pSuperTable into pTable */
|
|
if( !szDrvName || ! *szDrvName )
|
|
{
|
|
/* no name for inherited driver - use the default one */
|
|
memcpy( pTable, &waTable, sizeof( RDDFUNCS ) );
|
|
memcpy( pSuperTable, &waTable, sizeof( RDDFUNCS ) );
|
|
}
|
|
else
|
|
{
|
|
char szSuperName[ HB_RDD_MAX_DRIVERNAME_LEN + 1 ];
|
|
hb_strncpyUpper( szSuperName, szDrvName, sizeof( szSuperName ) - 1 );
|
|
pRddNode = hb_rddFindNode( szSuperName, NULL );
|
|
|
|
if( !pRddNode )
|
|
{
|
|
return HB_FAILURE;
|
|
}
|
|
|
|
memcpy( pTable, &pRddNode->pTable, sizeof( RDDFUNCS ) );
|
|
memcpy( pSuperTable, &pRddNode->pTable, sizeof( RDDFUNCS ) );
|
|
}
|
|
|
|
/* Copy the non NULL entries from pSubTable into pTable */
|
|
pFunction = ( DBENTRYP_V * ) pTable;
|
|
pSubFunction = ( DBENTRYP_V * ) pSubTable;
|
|
for( uiCount = 0; uiCount < RDDFUNCSCOUNT; uiCount++ )
|
|
{
|
|
if( * pSubFunction )
|
|
* pFunction = * pSubFunction;
|
|
pFunction ++;
|
|
pSubFunction ++;
|
|
}
|
|
return HB_SUCCESS;
|
|
}
|
|
|
|
/* extend the size of RDD nodes buffer to given value to avoid later
|
|
* RT reallocations. It may be useful in some very seldom cases
|
|
* for MT programs which will register dynamically at runtime
|
|
* more then 128 RDDs.
|
|
*/
|
|
HB_FUNC( __RDDPREALLOCATE )
|
|
{
|
|
LONG lNewSize = hb_parnl( 1 );
|
|
|
|
if( lNewSize > ( LONG ) USHRT_MAX )
|
|
lNewSize = USHRT_MAX;
|
|
if( lNewSize > ( LONG ) s_uiRddMax )
|
|
{
|
|
s_uiRddMax += HB_RDD_POOL_ALLOCSIZE;
|
|
s_RddList = ( LPRDDNODE * )
|
|
hb_xrealloc( s_RddList, sizeof( LPRDDNODE ) * s_uiRddMax );
|
|
}
|
|
|
|
hb_retnl( s_uiRddMax );
|
|
}
|
|
|
|
HB_FUNC_EXTERN( RDDSYS );
|
|
void _hb_rddWorkAreaForceLink( void )
|
|
{
|
|
HB_FUNC_EXEC( RDDSYS );
|
|
}
|