- BORLAND/: Borland C++ 4.52 (chosen over 4.5 by byte-match: CODE/RP/CW32.LIB
is identical to 4.52's install lib). BCC32/TLINK32/TLIB/MAKE run natively on
Win11; CODE/BT/OPT.MAK is the shipped BTL4OPT.EXE's exact flag recipe
(extender = Borland PowerPack DPMI32, not Phar Lap TNT).
- restoration/source410/: the literal 1995-form reconstruction of the missing
BT game source (never mixed into CODE/). Round 1-3 state:
* 6 of 10 surviving original TUs COMPILE CLEAN under the period toolchain
(BTMSSN, BTCNSL, BTSCNRL, BTTEAM, BTL4MODE, BTL4ARND) - first builds
since 1996.
* BT_L4/BTL4APP.CPP pilot reconstruction: 12/12 functions, Fail() lands on
its binary-recorded line 400 exactly.
* BT/BTCNSL.HPP: console wire IDs recovered from the binary's ctors
(Killed=9, Damaged=10, ScoreUpdate=13, DeathWithoutHonor=15 [T1];
TeamScore=12 flagged [T4]).
* MUNGA/: 8 engine-header backfills back-dated from the BT412 WinTesla tree
(VDATA numbering decomp-verified; AUDREND's OpenAL-era virtual removed -
the period compiler is the drift detector).
* Tooling: backdate.py (WinTesla->1995 header transform), compile410.sh
(per-TU verification sweep under authentic OPT.MAK flags).
* README: corrected roadmap - MECH.HPP is the capstone grown with the mech
TU reconstructions; BTREG.CPP green = the header-family milestone.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2022 lines
63 KiB
C++
2022 lines
63 KiB
C++
// BDE - (C) Copyright 1994 by Borland International
|
|
|
|
#include "address.h"
|
|
|
|
//======================================================================
|
|
// Name: DbInit()
|
|
//
|
|
// Input: None.
|
|
//
|
|
// Return: DBIERR_NONE if the engine initializes successfully.
|
|
//
|
|
// Desc: This function starts up the engine.
|
|
//======================================================================
|
|
DBIResult
|
|
DbInit (void)
|
|
{
|
|
DBIResult rslt; // Return value from IDAPI functions
|
|
pCHAR pszMessage;
|
|
|
|
CHKERR(DbiInit(NULL));
|
|
|
|
DbiDebugLayerOptions(DEBUGON | OUTPUTTOFILE, "ADDRESS.INF");
|
|
|
|
rslt = DbiSetPrivateDir(szPrivDirectory);
|
|
if (rslt == DBIERR_DIRBUSY)
|
|
{
|
|
pszMessage = (pCHAR)malloc(((DBIMAXMSGLEN * 3) + 1) * sizeof(char));
|
|
if (pszMessage)
|
|
{
|
|
sprintf(pszMessage, "Directory is busy. Make certain no .LCK"
|
|
" files exist in the %s directory and that the IDAPI"
|
|
" DLLs are unloaded (Reboot Windows).",
|
|
szPrivDirectory);
|
|
WinMsg(pszMessage, MB_ICONHAND, MB_OK);
|
|
free(pszMessage);
|
|
}
|
|
return rslt;
|
|
}
|
|
|
|
CHKERR(rslt);
|
|
|
|
return DBIERR_NONE;
|
|
}
|
|
|
|
//======================================================================
|
|
// Name: DbExit()
|
|
//
|
|
// Input: None.
|
|
//
|
|
// Return: DBIERR_NONE if the engine closes successfully.
|
|
//
|
|
// Desc: This function shuts down the engine.
|
|
//======================================================================
|
|
DBIResult
|
|
DbExit (void)
|
|
{
|
|
DbiDebugLayerOptions(0, NULL);
|
|
CHKERR(DbiExit());
|
|
return DBIERR_NONE;
|
|
}
|
|
|
|
//======================================================================
|
|
// Name: GetTable()
|
|
//
|
|
// Input: Pointer to the database (phDBIDb), and a pointer to the
|
|
// cursor (phDBICur).
|
|
//
|
|
// Return: DBIERR_NONE if the table opens without error.
|
|
//
|
|
// Desc: This function opens a table.
|
|
//======================================================================
|
|
DBIResult
|
|
GetTable (hDBIDb hDb, phDBICur phCur)
|
|
{
|
|
CURProps TblProps;
|
|
UINT16 iLen;
|
|
DBIResult rslt;
|
|
|
|
if(!bIsServer)
|
|
{
|
|
// Set the directory for the table handle
|
|
CHKERR(DbiSetDirectory(hDb, (pCHAR)szTblDirectory));
|
|
}
|
|
|
|
CHKERR(DbiGetProp((hDBIObj)hDb, dbDATABASETYPE, (pCHAR)szTblType,
|
|
sizeof(DBINAME), &iLen));
|
|
|
|
// Open the table to acquire a cursor on the table.
|
|
HourGlassCursor(TRUE);
|
|
rslt = DbiOpenTable(hDb, (pCHAR)szTblName, NULL,
|
|
NULL, NULL, 0, dbiREADWRITE, dbiOPENSHARED,
|
|
xltFIELD, FALSE, NULL, phCur);
|
|
HourGlassCursor(FALSE);
|
|
CHKERR(rslt);
|
|
|
|
// Get the cursor properties for the Addressbook table.
|
|
rslt = DbiGetCursorProps(*phCur, &TblProps);
|
|
if(rslt!=DBIERR_NONE)
|
|
{
|
|
DbiCloseCursor(phCur);
|
|
CHKERR(rslt);
|
|
}
|
|
|
|
strcpy((pCHAR)szTblType, TblProps.szTableType);
|
|
|
|
return DBIERR_NONE;
|
|
}
|
|
|
|
//======================================================================
|
|
// Name: CreateTable()
|
|
//
|
|
// Input: Handle to the database (hDBIDb), pointer to the cursor
|
|
// (phDBICur), and the type of AddressBook (pCHAR).
|
|
//
|
|
// Return: DBIERR_NONE if the table is created without error.
|
|
//
|
|
// Desc: This function creates a table for the given database.
|
|
//======================================================================
|
|
DBIResult
|
|
CreateTable (hDBIDb hDb, phDBICur phCur, pCHAR pszABType)
|
|
{
|
|
DBIResult rslt;
|
|
CRTblDesc crTblDsc;
|
|
BOOL bOverWrite = TRUE;
|
|
UINT16 iLen;
|
|
UINT16 i=0;
|
|
|
|
if(!bIsServer)
|
|
{
|
|
// Set the directory for the table handle
|
|
CHKERR(DbiSetDirectory(hDb, (pCHAR)szTblDirectory));
|
|
}
|
|
|
|
memset(&crTblDsc, 0, sizeof(CRTblDesc));
|
|
|
|
// Set the name and the type of the table
|
|
strcpy(crTblDsc.szTblName, szTblName);
|
|
|
|
strcpy(crTblDsc.szTblType, szTblType);
|
|
|
|
// Check the AddressBook type.
|
|
if(strcmpi(pszABType, szPERSONAL)==0)
|
|
{
|
|
// Set the table to hold personal data
|
|
strcpy(fldDesc[2].szName, "Spouse");
|
|
strcpy(fldDesc[8].szName, "Work_No");
|
|
strcpy(fldDesc[9].szName, "Home_No");
|
|
}
|
|
else
|
|
{
|
|
// Set the table to hold business data
|
|
strcpy(fldDesc[2].szName, "Business");
|
|
strcpy(fldDesc[8].szName, "Phone1");
|
|
strcpy(fldDesc[9].szName, "Fax");
|
|
}
|
|
crTblDsc.iFldCount = uNumFields;
|
|
crTblDsc.pfldDesc = fldDesc;
|
|
|
|
// Set the index information for the table
|
|
if(bIsServer)
|
|
{
|
|
idxIBPDDesc[0].bPrimary = FALSE;
|
|
|
|
for(i=0;i<uNumIndexes;i++)
|
|
{
|
|
idxIBPDDesc[i].bUnique = TRUE;
|
|
}
|
|
|
|
crTblDsc.pidxDesc = idxIBPDDesc;
|
|
|
|
// Get the database type.
|
|
CHKERR(DbiGetProp((hDBIObj)hDb, dbDATABASETYPE, (pCHAR)szTblType,
|
|
sizeof(DBINAME), &iLen));
|
|
|
|
strcpy(crTblDsc.szTblType, szTblType);
|
|
}
|
|
else
|
|
{
|
|
if(strcmpi(szTblType, szPARADOX)==0)
|
|
{
|
|
crTblDsc.pidxDesc = idxIBPDDesc;
|
|
idxIBPDDesc[0].bPrimary = TRUE;
|
|
}
|
|
else
|
|
{
|
|
if(strcmpi(szTblType, szDBASE)==0)
|
|
{
|
|
crTblDsc.pidxDesc = idxDBDesc;
|
|
}
|
|
else
|
|
{
|
|
WinMsg("Unsupported Table type!", MB_ICONHAND, MB_OK);
|
|
}
|
|
|
|
}
|
|
}
|
|
crTblDsc.iIdxCount = uNumIndexes;
|
|
|
|
// Create the table using information supplied in the Table
|
|
// Descrpitor above.
|
|
HourGlassCursor(TRUE);
|
|
rslt = DbiCreateTable(hDb, bOverWrite, &crTblDsc);
|
|
HourGlassCursor(FALSE);
|
|
CHKERR(rslt);
|
|
|
|
// Open the table to acquire a cursor to the newly created table.
|
|
HourGlassCursor(TRUE);
|
|
rslt = DbiOpenTable(hDb, (pCHAR)szTblName, (pCHAR)szTblType,
|
|
NULL, NULL, 0, dbiREADWRITE, dbiOPENSHARED,
|
|
xltFIELD, FALSE, NULL, phCur);
|
|
HourGlassCursor(FALSE);
|
|
CHKERR(rslt);
|
|
|
|
return rslt;
|
|
}
|
|
|
|
//======================================================================
|
|
// Name: AddRecord()
|
|
//
|
|
// Input: Handle to the cursor (hDBICur), pointer to a record structure
|
|
// (RecordType *), and a Boolean - if TRUE: the record is inserted.
|
|
// If FALSE: the record pointed to by the cursor is overwritten
|
|
// by the data in the record structure.
|
|
//
|
|
// Return: DBIERR_NONE if the record was inserted or overwritten
|
|
// successfully.
|
|
//
|
|
// Desc: This function adds a record to the table pointed at by the
|
|
// cursor.
|
|
//======================================================================
|
|
DBIResult
|
|
AddRecord (hDBICur hCur, RecordType *pString, BOOL bAdd)
|
|
{
|
|
pBYTE pRecBuf=NULL;
|
|
CURProps TblProps;
|
|
DATE Date;
|
|
TIME Time;
|
|
TIMESTAMP TimeStamp;
|
|
pFLDDesc pFields = NULL;
|
|
DBIResult rslt;
|
|
|
|
// Get all the field descriptors.
|
|
if ((pFields = (pFLDDesc)malloc(sizeof(FLDDesc) * uNumFields)) == NULL)
|
|
{
|
|
WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
|
|
CLEANUP(DBIERR_NOMEMORY);
|
|
}
|
|
|
|
// Get the field descriptors.
|
|
CHKERR_CLEANUP(DbiGetFieldDescs(hCur, pFields));
|
|
|
|
// Get the cursor properties for the Addressbook table.
|
|
CHKERR_CLEANUP(DbiGetCursorProps(hCur, &TblProps));
|
|
|
|
// Get a record buffer for the Addressbook table.
|
|
if((pRecBuf = (pBYTE) malloc(TblProps.iRecBufSize))== NULL)
|
|
{
|
|
WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
|
|
CLEANUP(DBIERR_NOMEMORY);
|
|
}
|
|
|
|
if(!bAdd)
|
|
{
|
|
CHKERR_CLEANUP(DbiGetRecord(hCur, dbiWRITELOCK, pRecBuf, NULL));
|
|
}
|
|
else
|
|
{
|
|
// Make sure we're starting with a clean record buffer
|
|
CHKERR_CLEANUP(DbiInitRecord(hCur, pRecBuf));
|
|
}
|
|
|
|
// Fill each field with the structure's data
|
|
CHKERR_CLEANUP(DbiPutField(hCur, 1, pRecBuf, (pBYTE)pString->FName));
|
|
CHKERR_CLEANUP(DbiPutField(hCur, 2, pRecBuf, (pBYTE)pString->LName));
|
|
CHKERR_CLEANUP(DbiPutField(hCur, 3, pRecBuf, (pBYTE)pString->Spouse));
|
|
CHKERR_CLEANUP(DbiPutField(hCur, 4, pRecBuf, (pBYTE)pString->Addrs1));
|
|
CHKERR_CLEANUP(DbiPutField(hCur, 5, pRecBuf, (pBYTE)pString->Addrs2));
|
|
CHKERR_CLEANUP(DbiPutField(hCur, 6, pRecBuf, (pBYTE)pString->City));
|
|
CHKERR_CLEANUP(DbiPutField(hCur, 7, pRecBuf, (pBYTE)pString->State));
|
|
CHKERR_CLEANUP(DbiPutField(hCur, 8, pRecBuf, (pBYTE)pString->Zip));
|
|
CHKERR_CLEANUP(DbiPutField(hCur, 9, pRecBuf, (pBYTE)pString->Phone1));
|
|
CHKERR_CLEANUP(DbiPutField(hCur, 10, pRecBuf, (pBYTE)pString->Phone2));
|
|
|
|
// Set the date by parsing the date string found in the record
|
|
// structure.
|
|
SetDate(&Date, pString->Date1);
|
|
|
|
// Check if the date field is really a timestamp field
|
|
if(pFields[10].iFldType == fldTIMESTAMP)
|
|
{
|
|
memset(&Time, '\0', sizeof(TIME));
|
|
CHKERR_CLEANUP(DbiTimeStampEncode(Date, Time, &TimeStamp));
|
|
|
|
// Put the Timestamp into the record buffer.
|
|
CHKERR_CLEANUP(DbiPutField(hCur, 11, pRecBuf, (pBYTE)&TimeStamp));
|
|
}
|
|
else
|
|
{
|
|
// Put the date into the record buffer.
|
|
CHKERR_CLEANUP(DbiPutField(hCur, 11, pRecBuf, (pBYTE)&Date));
|
|
}
|
|
|
|
// Now open the BLOb. You must open a blob before you can read or
|
|
// write a BLOb.
|
|
CHKERR_CLEANUP(DbiOpenBlob(hCur, pRecBuf, 12, dbiREADWRITE));
|
|
|
|
// Now put the BLOb into the record buffer. We need to add one for
|
|
// the NULL termination used in the string.
|
|
CHKERR_CLEANUP(DbiPutBlob(hCur, pRecBuf, 12, 0L,
|
|
strlen(pString->Comment) + 1,
|
|
(pBYTE)pString->Comment));
|
|
|
|
// If Add then insert the record.
|
|
if(bAdd)
|
|
{
|
|
// Insert the record.
|
|
rslt = DbiInsertRecord(hCur, dbiWRITELOCK, pRecBuf);
|
|
if(rslt == DBIERR_NONE)
|
|
{
|
|
// Release the record lock. The record is not released unless
|
|
// you close the table or release the lock.
|
|
CHKERR_CLEANUP(DbiRelRecordLock(hCur, FALSE));
|
|
}
|
|
else
|
|
{
|
|
// Release the record lock. The record is not released unless
|
|
// you close the table or release the lock.
|
|
DbiRelRecordLock(hCur, FALSE);
|
|
if (rslt == DBIERR_KEYVIOL)
|
|
{
|
|
WinMsg("Cannot add a duplicate record", MB_ICONHAND, MB_OK);
|
|
CLEANUP(rslt);
|
|
}
|
|
CHKERR_CLEANUP(rslt);
|
|
}
|
|
}
|
|
|
|
// Otherwise we are going to overwrite the record.
|
|
else
|
|
{
|
|
// Overwrite the record, and release the lock once we have
|
|
// modified the record.
|
|
rslt = DbiModifyRecord(hCur, pRecBuf, TRUE);
|
|
if(rslt != DBIERR_NONE)
|
|
{
|
|
// Release the record lock. The record is not released unless
|
|
// you close the table or release the lock.
|
|
DbiRelRecordLock(hCur, FALSE);
|
|
CHKERR_CLEANUP(rslt);
|
|
}
|
|
}
|
|
|
|
// YOU MUST FREE the blob.
|
|
CHKERR_CLEANUP(DbiFreeBlob(hCur, pRecBuf, 0));
|
|
free(pRecBuf);
|
|
free(pFields);
|
|
return DBIERR_NONE;
|
|
|
|
CleanUp:
|
|
if(pFields)
|
|
{
|
|
free(pFields);
|
|
}
|
|
if(pRecBuf)
|
|
{
|
|
free(pRecBuf);
|
|
DbiFreeBlob(hCur, pRecBuf, 0);
|
|
}
|
|
return GlobalDBIErr;
|
|
}
|
|
|
|
//======================================================================
|
|
// Name: SetDate()
|
|
//
|
|
// Input: Pointer a DATE variable, and a pointer to a string (pCHAR).
|
|
//
|
|
// Return: DBIERR_NONE if the string holds a valid date..
|
|
//
|
|
// Desc: This function puts the date that is in the pString into the
|
|
// Date variable.
|
|
//======================================================================
|
|
DBIResult
|
|
SetDate (pDATE Date, pCHAR pszString)
|
|
{
|
|
UINT16 iMonth;
|
|
UINT16 iDay;
|
|
UINT16 iYear;
|
|
UINT16 iSepLen;
|
|
CHAR szMonth[3] = {0};
|
|
CHAR szDay[3] = {0};
|
|
CHAR szYear[5] = {0};
|
|
FMTDate FmtDate;
|
|
|
|
GetDateFormat(&FmtDate);
|
|
iSepLen = strlen(FmtDate.szDateSeparator);
|
|
|
|
// Get the first two month's numbers (the first two numbers).
|
|
strncpy(szMonth, pszString, 2);
|
|
iMonth = atoi(szMonth);
|
|
|
|
// Skip the separator.
|
|
strncpy(szDay, pszString + 2 + iSepLen, 2);
|
|
iDay = atoi(szDay);
|
|
|
|
// Skip second separator.
|
|
strncpy(szYear, pszString + 4 + (2*iSepLen), 4);
|
|
iYear = atoi(szYear);
|
|
|
|
CHKERR(DbiDateEncode(iMonth, iDay, iYear, Date));
|
|
return DBIERR_NONE;
|
|
}
|
|
|
|
//======================================================================
|
|
// Name: GetData()
|
|
//
|
|
// Input: Handle to the cursor (hDBICur), pointer to a record structure
|
|
// (RecordType*).
|
|
//
|
|
// Return: DBIERR_NONE if the record buffer is allocated and the data
|
|
// is read successfully.
|
|
//
|
|
// Desc: This function gets the data pointed to by hCur and puts it
|
|
// into the record structure.
|
|
//======================================================================
|
|
DBIResult
|
|
GetData (hDBICur hCur, RecordType* pRecord)
|
|
{
|
|
CURProps TblProps;
|
|
pBYTE pRecBuf = NULL;
|
|
DBIResult rslt;
|
|
|
|
// Get the proporties of the table so that we can create the correct
|
|
// buffer size for the record. We will read the record into the buffer
|
|
// and then we will pull the field from the buffer.
|
|
CHKERR_CLEANUP(DbiGetCursorProps(hCur,&TblProps));
|
|
|
|
if((pRecBuf = (pBYTE) malloc(TblProps.iRecBufSize))==NULL)
|
|
{
|
|
WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
|
|
CLEANUP(DBIERR_NOMEMORY);
|
|
}
|
|
|
|
// Initialize the record buffer.
|
|
CHKERR_CLEANUP(DbiInitRecord(hCur, pRecBuf));
|
|
|
|
rslt = DbiGetRecord(hCur, dbiREADLOCK, pRecBuf, 0);
|
|
|
|
if(rslt == DBIERR_NONE)
|
|
{
|
|
CHKERR_NODISPLAY(FillRec(hCur, pRecBuf, pRecord));
|
|
CHKERR_CLEANUP(DbiRelRecordLock(hCur, FALSE));
|
|
}
|
|
else
|
|
{
|
|
// Check if the table is empty and that is why you got an error.
|
|
if(!(AtBOF(hCur) && AtEOF(hCur)))
|
|
{
|
|
CHKERR_CLEANUP(rslt);
|
|
}
|
|
}
|
|
|
|
free(pRecBuf);
|
|
|
|
return DBIERR_NONE;
|
|
|
|
CleanUp:
|
|
if(pRecBuf)
|
|
{
|
|
free(pRecBuf);
|
|
}
|
|
return GlobalDBIErr;
|
|
}
|
|
|
|
//======================================================================
|
|
// Name: FillRec()
|
|
//
|
|
// Input: Handle to the cursor (hDBICur), pointer to a record
|
|
// buffer (pBYTE), and a record structure pointer (RecordType *).
|
|
//
|
|
// Return: DBIERR_NONE if the record structure is filled successfully.
|
|
//
|
|
// Desc: This function adds a record to the table pointed at by the
|
|
// cursor.
|
|
//======================================================================
|
|
DBIResult
|
|
FillRec (hDBICur hCur, pBYTE pRecBuf, RecordType* pString)
|
|
{
|
|
UINT16 iDay;
|
|
UINT16 iMonth;
|
|
INT16 iYear;
|
|
UINT32 lActualSize;
|
|
UINT32 lBlobSize;
|
|
CHAR szTemp[30] ="";
|
|
DATE Date;
|
|
TIME Time;
|
|
FMTDate FmtDate;
|
|
BOOL bEmpty;
|
|
pFLDDesc pFields = NULL;
|
|
|
|
if ((pFields = (pFLDDesc)malloc(sizeof(FLDDesc) * uNumFields)) == NULL)
|
|
{
|
|
WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
|
|
CLEANUP(DBIERR_NOMEMORY);
|
|
}
|
|
|
|
CHKERR_CLEANUP(DbiGetFieldDescs(hCur, pFields));
|
|
CHKERR_NODISPLAY(GetDateFormat(&FmtDate));
|
|
|
|
// Put each field into the data structure
|
|
CHKERR_CLEANUP(DbiGetField(hCur, 1, pRecBuf, (pBYTE)pString->FName,
|
|
&bEmpty));
|
|
CHKERR_CLEANUP(DbiGetField(hCur, 2, pRecBuf, (pBYTE)pString->LName,
|
|
&bEmpty));
|
|
CHKERR_CLEANUP(DbiGetField(hCur, 3, pRecBuf, (pBYTE)pString->Spouse,
|
|
&bEmpty));
|
|
CHKERR_CLEANUP(DbiGetField(hCur, 4, pRecBuf, (pBYTE)pString->Addrs1,
|
|
&bEmpty));
|
|
CHKERR_CLEANUP(DbiGetField(hCur, 5, pRecBuf, (pBYTE)pString->Addrs2,
|
|
&bEmpty));
|
|
CHKERR_CLEANUP(DbiGetField(hCur, 6, pRecBuf, (pBYTE)pString->City,
|
|
&bEmpty));
|
|
CHKERR_CLEANUP(DbiGetField(hCur, 7, pRecBuf, (pBYTE)pString->State,
|
|
&bEmpty));
|
|
CHKERR_CLEANUP(DbiGetField(hCur, 8, pRecBuf, (pBYTE)pString->Zip,
|
|
&bEmpty));
|
|
CHKERR_CLEANUP(DbiGetField(hCur, 9, pRecBuf, (pBYTE)pString->Phone1,
|
|
&bEmpty));
|
|
CHKERR_CLEANUP(DbiGetField(hCur, 10, pRecBuf, (pBYTE)pString->Phone2,
|
|
&bEmpty));
|
|
CHKERR_CLEANUP(DbiGetField(hCur, 11, pRecBuf, (pBYTE)szTemp, &bEmpty));
|
|
|
|
// Check if the date field is really a timestamp field
|
|
if(pFields[10].iFldType == fldTIMESTAMP)
|
|
{
|
|
CHKERR_CLEANUP(DbiTimeStampDecode(*(pTIMESTAMP)szTemp, &Date,
|
|
&Time));
|
|
CHKERR_CLEANUP(DbiDateDecode(Date, &iMonth, &iDay, &iYear));
|
|
}
|
|
else
|
|
{
|
|
CHKERR_CLEANUP(DbiDateDecode(*(pDATE)szTemp, &iMonth, &iDay,
|
|
&iYear));
|
|
}
|
|
|
|
// Format the date to whatever the date separator is.
|
|
wsprintf(pString->Date1, "%02d%s%02d%s%02d", iMonth,
|
|
FmtDate.szDateSeparator, iDay, FmtDate.szDateSeparator,
|
|
iYear);
|
|
|
|
CHKERR_CLEANUP(DbiOpenBlob(hCur, pRecBuf, 12, dbiREADWRITE));
|
|
|
|
// Get the size of the blob so that we can get the whole blob.
|
|
CHKERR_CLEANUP(DbiGetBlobSize(hCur, pRecBuf, 12, &lBlobSize));
|
|
|
|
// Check to make sure that the buffer is large enough to hold the blob.
|
|
if(lBlobSize >= COMMENTLEN)
|
|
{
|
|
lBlobSize = COMMENTLEN - 1;
|
|
}
|
|
|
|
CHKERR_CLEANUP(DbiGetBlob(hCur, pRecBuf, 12, 0L, lBlobSize,
|
|
(pBYTE)pString->Comment, &lActualSize));
|
|
|
|
CHKERR_CLEANUP(DbiFreeBlob(hCur, pRecBuf, 12));
|
|
|
|
free(pFields);
|
|
return DBIERR_NONE;
|
|
|
|
CleanUp:
|
|
if(pFields)
|
|
{
|
|
free(pFields);
|
|
}
|
|
return GlobalDBIErr;
|
|
}
|
|
|
|
//======================================================================
|
|
// Name: GoBottom()
|
|
//
|
|
// Input: Handle to the cursor (hDBICur), Move a record prior Bool (BOOL).
|
|
//
|
|
// Return: DBIERR_NONE if DbiSetToEnd is successful.
|
|
//
|
|
// Desc: This function moves to the bottom of the table, and moves one
|
|
// record back if MoveRec (BOOL) is TRUE.
|
|
//======================================================================
|
|
DBIResult
|
|
GoBottom (hDBICur hCur, BOOL bMoveRec)
|
|
{
|
|
CHKERR(DbiSetToEnd(hCur));
|
|
if(bMoveRec)
|
|
{
|
|
GetPrevRec(hCur);
|
|
}
|
|
return DBIERR_NONE;
|
|
}
|
|
|
|
//======================================================================
|
|
// Name: GoTop()
|
|
//
|
|
// Input: Handle to the cursor (hDBICur), Move a record forward Bool
|
|
// (BOOL).
|
|
//
|
|
// Return: DBIERR_NONE if DbiSetToBegin is successful.
|
|
//
|
|
// Desc: This function moves to the top of the table, and moves one
|
|
// record forward if MoveRec (BOOL) is TRUE.
|
|
//======================================================================
|
|
DBIResult
|
|
GoTop (hDBICur hCur, BOOL bMoveRec)
|
|
{
|
|
DBIResult rslt; // Return value from IDAPI functions
|
|
CHKERR(DbiSetToBegin(hCur));
|
|
if(bMoveRec)
|
|
{
|
|
rslt = GetNextRec(hCur);
|
|
if (rslt != DBIERR_EOF)
|
|
{
|
|
CHKERR(rslt);
|
|
}
|
|
}
|
|
return DBIERR_NONE;
|
|
}
|
|
|
|
//======================================================================
|
|
// Name: GetNextRec()
|
|
//
|
|
// Input: Handle to the cursor (hDBICur).
|
|
//
|
|
// Return: DBIERR_NONE if DbiGetNextRecord is successful.
|
|
//
|
|
// Desc: This function moves one record forward.
|
|
//======================================================================
|
|
DBIResult
|
|
GetNextRec (hDBICur hCur)
|
|
{
|
|
DBIResult rslt;
|
|
|
|
rslt = DbiGetNextRecord(hCur, dbiNOLOCK, NULL, 0);
|
|
|
|
return rslt;
|
|
}
|
|
|
|
//======================================================================
|
|
// Name: GetPrevRec()
|
|
//
|
|
// Input: Handle to the cursor (hDBICur).
|
|
//
|
|
// Return: DBIERR_NONE if DbiGetPrevRec is successful.
|
|
//
|
|
// Desc: This function moves one record backwards.
|
|
//======================================================================
|
|
DBIResult
|
|
GetPrevRec (hDBICur hCur)
|
|
{
|
|
DBIResult rslt;
|
|
rslt = DbiGetPriorRecord(hCur, dbiNOLOCK, NULL, 0);
|
|
return rslt;
|
|
}
|
|
|
|
//======================================================================
|
|
// Name: AtEOF()
|
|
//
|
|
// Input: Handle to the cursor (hDBICur).
|
|
//
|
|
// Return: TRUE: If the cursor is at the End Of File (EOF).
|
|
// FALSE: If the cursor is not at the EOF.
|
|
//
|
|
// Desc: This function moves one record forward to test if the cursor
|
|
// is at the EOF, and then moves back to put the cursor at the
|
|
// place it was before the start of this function.
|
|
//======================================================================
|
|
BOOL
|
|
AtEOF (hDBICur hCur)
|
|
{
|
|
DBIResult rslt;
|
|
BOOL bRetVal;
|
|
|
|
// Check if we are at the end of the table.
|
|
rslt = DbiGetNextRecord(hCur, dbiNOLOCK, NULL, 0);
|
|
if(rslt == DBIERR_EOF)
|
|
{
|
|
bRetVal = TRUE;
|
|
}
|
|
else
|
|
{
|
|
bRetVal = FALSE;
|
|
}
|
|
|
|
// Put the cursor back to its original place - if we are not at EOF.
|
|
DbiGetPriorRecord(hCur, dbiNOLOCK, NULL, 0);
|
|
|
|
return bRetVal;
|
|
}
|
|
|
|
//======================================================================
|
|
// Name: AtBOF()
|
|
//
|
|
// Input: Handle to the cursor (hDBICur).
|
|
//
|
|
// Return: TRUE: If the cursor is at the Beginning Of File (BOF).
|
|
// FALSE: If the cursor is not at the BOF.
|
|
//
|
|
// Desc: This function moves one record backwards to test if the cursor
|
|
// is at the BOF. Then it moves the cursor one record forward to
|
|
// put it back to where it was originally.
|
|
//======================================================================
|
|
BOOL
|
|
AtBOF (hDBICur hCur)
|
|
{
|
|
DBIResult rslt;
|
|
BOOL bRetVal;
|
|
|
|
// Check if we are at the end of the table.
|
|
rslt = DbiGetPriorRecord(hCur, dbiNOLOCK, NULL, 0);
|
|
if(rslt == DBIERR_BOF)
|
|
{
|
|
bRetVal = TRUE;
|
|
}
|
|
else
|
|
{
|
|
bRetVal = FALSE;
|
|
}
|
|
|
|
// Put the cursor back to its original place if we are not at BOF.
|
|
DbiGetNextRecord(hCur, dbiNOLOCK, NULL, 0);
|
|
|
|
return bRetVal;
|
|
}
|
|
|
|
//======================================================================
|
|
// Name: CloseDb()
|
|
//
|
|
// Input: Pointer to the Database (phDBIDb).
|
|
//
|
|
// Return: DBIERR_NONE if the table closed successfully.
|
|
//
|
|
// Desc: This function closes the table based upon the table pointer
|
|
// that was passed into the function.
|
|
//======================================================================
|
|
DBIResult
|
|
CloseDb (phDBIDb phDb)
|
|
{
|
|
CHKERR(DbiCloseDatabase(phDb));
|
|
return DBIERR_NONE;
|
|
}
|
|
|
|
//======================================================================
|
|
// Name: SetupIndex()
|
|
//
|
|
// Input: Pointer to cursor (phDBICur), index name (pCHAR), Tag name
|
|
// (pCHAR), and the Index ID (UINT16).
|
|
//
|
|
// Return: DBIERR_NONE if the index switch was successful.
|
|
//
|
|
// Desc: This function switches to an index based upon the index name,
|
|
// index tag name, and index ID.
|
|
//======================================================================
|
|
DBIResult
|
|
SetupIndex (phDBICur phCur, pCHAR pszName, pCHAR pszTagName, UINT16 IndexId)
|
|
{
|
|
DBIResult rslt;
|
|
|
|
HourGlassCursor(TRUE);
|
|
rslt = DbiSwitchToIndex(phCur, pszName, pszTagName, IndexId, TRUE);
|
|
HourGlassCursor(FALSE);
|
|
CHKERR(rslt);
|
|
|
|
return rslt;
|
|
}
|
|
|
|
//======================================================================
|
|
// Name: SetIndex()
|
|
//
|
|
// Input: Pointer to cursor (phDBICur), index name (pCHAR).
|
|
//
|
|
// Return: DBIERR_NONE if SetupIndex was successful.
|
|
//
|
|
// Desc: This function runs SetupIndex with different parameters based
|
|
// upon the table type.
|
|
//======================================================================
|
|
DBIResult
|
|
SetIndex (phDBICur phCur, pCHAR pszIndex)
|
|
{
|
|
UINT16 iIndexId = NULL;
|
|
CHAR szMdxName[DBIMAXPATHLEN];
|
|
|
|
// Move to the top of the table and move forward one record past the
|
|
// crack.
|
|
GoTop(*phCur, TRUE);
|
|
|
|
// Clear szMdxName
|
|
memset(szMdxName, '/0', DBIMAXNAMELEN);
|
|
|
|
// Check if the index is called primary. If it is there is no real
|
|
// index name and we need to send the switch index function an index id
|
|
// of 0.
|
|
if((strcmpi(pszIndex, "Primary")==0)&&(strcmpi(szTblType,
|
|
szPARADOX)==0))
|
|
{
|
|
iIndexId = 0;
|
|
strcpy(pszIndex, "");
|
|
SetupIndex(phCur, pszIndex, NULL, iIndexId);
|
|
}
|
|
else
|
|
{
|
|
if(strcmpi(szTblType, szDBASE)==0)
|
|
{
|
|
// Get the Production index's name, since it is a dBASE index.
|
|
GetMdxName(*phCur, szMdxName);
|
|
iIndexId = NULL;
|
|
SetupIndex(phCur, szMdxName, pszIndex, iIndexId);
|
|
}
|
|
else
|
|
{
|
|
SetupIndex(phCur, pszIndex, NULL, iIndexId);
|
|
}
|
|
}
|
|
|
|
return DBIERR_NONE;
|
|
}
|
|
|
|
//======================================================================
|
|
// Name: FillIndexStr()
|
|
//
|
|
// Input: Handle to the cursor (hDBICur), Handle to the database (hDBIDb),
|
|
// Pointer to the Addressbook Index structure (pABIDXDDESC) a
|
|
// pointer to the string that will hold the name of the active
|
|
// index (pCHAR), and a pointer to the active index (pUINT16).
|
|
//
|
|
// Return: DBIERR_NONE if the pIndexes pointer is successfully filled.
|
|
//
|
|
// Desc: This function allocates memory to the index descriptor pointer
|
|
// and then fills it with the index information. Then it fills the
|
|
// pActIdx pointer with the name of the presently active index.
|
|
// It then returns the total number of indexes inside the
|
|
// puIndexes variable.
|
|
//======================================================================
|
|
DBIResult
|
|
FillIndexStr (hDBICur hCur, hDBIDb hDb, pABIDXDESC *pIndexes,
|
|
pCHAR pszActIdx, pUINT16 puIndexes)
|
|
{
|
|
UINT16 i=0;
|
|
UINT16 j=0;
|
|
UINT16 iKey=0;
|
|
UINT16 iIdx=0;
|
|
CURProps TblProps;
|
|
DBIKEYEXP KeyExp;
|
|
pIDXDesc pMyDesc = NULL;
|
|
pIDXDesc pAllDesc = NULL;
|
|
pFLDDesc pFields = NULL;
|
|
DBIKEYEXP szFld;
|
|
pCHAR pFld = NULL;
|
|
|
|
CHKERR_CLEANUP(DbiGetCursorProps(hCur, &TblProps));
|
|
|
|
if ((*pIndexes = (pABIDXDESC)malloc(sizeof(ABIDXDESC) *
|
|
TblProps.iIndexes)) == NULL)
|
|
{
|
|
WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
|
|
CLEANUP(DBIERR_NOMEMORY);
|
|
}
|
|
|
|
if ((pMyDesc = (pIDXDesc)malloc(sizeof(IDXDesc) * 1)) == NULL)
|
|
{
|
|
WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
|
|
CLEANUP(DBIERR_NOMEMORY);
|
|
}
|
|
|
|
if ((pFields = (pFLDDesc)malloc(sizeof(FLDDesc) * TblProps.iFields))
|
|
== NULL)
|
|
{
|
|
WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
|
|
CLEANUP(DBIERR_NOMEMORY);
|
|
}
|
|
|
|
if ((pAllDesc = (pIDXDesc)malloc(sizeof(IDXDesc) * TblProps.iIndexes))
|
|
== NULL)
|
|
{
|
|
WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
|
|
CLEANUP(DBIERR_NOMEMORY);
|
|
}
|
|
|
|
CHKERR_NODISPLAY(GetIndexDescs(hDb, pAllDesc));
|
|
CHKERR_CLEANUP(DbiGetFieldDescs(hCur, pFields));
|
|
|
|
// Copy the data we need into the ABIDXDESC structure.
|
|
for(i=0; i<TblProps.iIndexes; i++)
|
|
{
|
|
// If it is a dBASE table just copy the information in - as the
|
|
// keyexp is already built for us. Also get the index name and
|
|
// get the fields in the index.
|
|
if(strcmpi(TblProps.szTableType, szDBASE)==0)
|
|
{
|
|
strcpy((*pIndexes)[i].szTagName, pAllDesc[i].szTagName);
|
|
if(pAllDesc[i].bExpIdx)
|
|
{
|
|
strcpy((*pIndexes)[i].szKeyExp, pAllDesc[i].szKeyExp);
|
|
strcpy(szFld, pAllDesc[i].szKeyExp);
|
|
|
|
// Now parse the index expression. We will only parse
|
|
// for the + symbol.
|
|
j=0;
|
|
pFld = strtok(szFld, "+");
|
|
|
|
// Pass the string into this function to get the field
|
|
// number and len for it.
|
|
CHKERR_NODISPLAY(GetFieldInfo(pFld,
|
|
&((*pIndexes)[i].aiKeyFld[j]),
|
|
&((*pIndexes)[i].aiKeyLen[j]),
|
|
hCur, TblProps.iFields));
|
|
j++;
|
|
|
|
while(pFld!=NULL)
|
|
{
|
|
pFld = strtok(NULL, "+");
|
|
if(pFld != NULL)
|
|
{
|
|
CHKERR_NODISPLAY(GetFieldInfo(pFld,
|
|
&((*pIndexes)[i].aiKeyFld[j]),
|
|
&((*pIndexes)[i].aiKeyLen[j]), hCur,
|
|
TblProps.iFields));
|
|
j++;
|
|
}
|
|
}
|
|
|
|
(*pIndexes)[i].iFldsInKey = j;
|
|
}
|
|
else
|
|
{
|
|
strcpy((*pIndexes)[i].szKeyExp, pAllDesc[i].szKeyExp);
|
|
strcpy(szFld, pAllDesc[i].szKeyExp);
|
|
strcpy((*pIndexes)[i].szKeyExp, pAllDesc[i].szKeyExp);
|
|
(*pIndexes)[i].iFldsInKey = pAllDesc[i].iFldsInKey;
|
|
|
|
// This is a single field index so get the zeroth item.
|
|
iIdx = pAllDesc[i].aiKeyFld[0];
|
|
|
|
(*pIndexes)[i].aiKeyFld[0]=iIdx;
|
|
|
|
// Get the field length so for this particular field.
|
|
if(pFields[iIdx-1].iFldType == fldDATE)
|
|
{
|
|
(*pIndexes)[i].aiKeyLen[0]= DATELEN-1;
|
|
}
|
|
|
|
if(pFields[iIdx-1].iFldType == fldZSTRING)
|
|
{
|
|
(*pIndexes)[i].aiKeyLen[0] = (pFields[iIdx-1].iUnits1);
|
|
}
|
|
}
|
|
}
|
|
// Else the keyexp is not built for us so we need to build it
|
|
// ourselves.
|
|
else
|
|
{
|
|
// First copy the index name, TagName, and iFldsInKey
|
|
strcpy((*pIndexes)[i].szTagName, pAllDesc[i].szName);
|
|
(*pIndexes)[i].iFldsInKey = pAllDesc[i].iFldsInKey;
|
|
|
|
// Get the total number of fields in the index - 1. That
|
|
// way when we stick + symbols into the string we will know
|
|
// when to stop. Though it can be done other ways it is easier
|
|
// to understand this way.
|
|
iKey = pAllDesc[i].iFldsInKey - 1;
|
|
|
|
// MUST clear the string everytime through to make sure we can
|
|
// use strcat even the first time. Also set the fieldlen to 0.
|
|
memset(KeyExp, '\0', DBIMAXKEYEXPLEN+1);
|
|
|
|
// Loop through the fields in the key and copy the Field's
|
|
// name into the string.
|
|
for(j=0; j<pAllDesc[i].iFldsInKey; j++)
|
|
{
|
|
// Get the Jth field number for this Ith index. We
|
|
// subtract one because the fields are one based while the
|
|
// array is zero based.
|
|
iIdx = (pAllDesc[i].aiKeyFld[j]);
|
|
strcat(KeyExp, pFields[iIdx-1].szName);
|
|
|
|
(*pIndexes)[i].aiKeyFld[j]=iIdx;
|
|
|
|
// Get the field length so for this particular field.
|
|
if(pFields[iIdx-1].iFldType == fldDATE)
|
|
{
|
|
(*pIndexes)[i].aiKeyLen[j]= DATELEN-1;
|
|
}
|
|
|
|
if(pFields[iIdx-1].iFldType == fldZSTRING)
|
|
{
|
|
(*pIndexes)[i].aiKeyLen[j] = (pFields[iIdx-1].iUnits1);
|
|
}
|
|
|
|
// If iKey = 0 then this is the last field number in
|
|
// the array and we do not want to add a + symbol to the
|
|
// string. Otherwise, add a + symbol to the string.
|
|
if(iKey != 0)
|
|
{
|
|
strcat(KeyExp, " + ");
|
|
|
|
// Only subtract one from iKey here or else you will
|
|
// create a -1 value for this UINT16 variable.
|
|
iKey--;
|
|
}
|
|
}
|
|
|
|
// Add the created Key expression to the strcuture.
|
|
strcpy((*pIndexes)[i].szKeyExp, KeyExp);
|
|
}
|
|
|
|
}
|
|
|
|
CHKERR_CLEANUP(DbiGetIndexDesc(hCur, 0, pMyDesc));
|
|
|
|
// If this is a dBASE table pass the tag name back as the active index.
|
|
if(strcmpi(TblProps.szTableType, szDBASE)==0)
|
|
{
|
|
// Get information about the currently active index.
|
|
strcpy(pszActIdx, pMyDesc->szTagName);
|
|
}
|
|
else
|
|
{
|
|
if(strcmpi(TblProps.szTableType, szPARADOX)==0)
|
|
{
|
|
if(pMyDesc->iIndexId==0)
|
|
{
|
|
strcpy(pszActIdx, (pCHAR)"Primary");
|
|
}
|
|
else
|
|
{
|
|
strcpy(pszActIdx, pMyDesc->szName);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
strcpy(pszActIdx, pMyDesc->szName);
|
|
}
|
|
}
|
|
|
|
*puIndexes = TblProps.iIndexes;
|
|
|
|
// Free all the memory except for the one we created for pIndexes.
|
|
// That will be freed by the calling function.
|
|
free(pMyDesc);
|
|
free(pAllDesc);
|
|
free(pFields);
|
|
|
|
return DBIERR_NONE;
|
|
|
|
CleanUp:
|
|
if(pMyDesc)
|
|
{
|
|
free(pMyDesc);
|
|
}
|
|
if(pAllDesc)
|
|
{
|
|
free(pAllDesc);
|
|
}
|
|
if(pFields)
|
|
{
|
|
free(pFields);
|
|
}
|
|
return GlobalDBIErr;
|
|
}
|
|
|
|
//======================================================================
|
|
// Name: DeleteRec()
|
|
//
|
|
// Input: Handle to the cursor (hDBICur).
|
|
//
|
|
// Return: DBIERR_NONE if the record is successfully deleted.
|
|
//
|
|
// Desc: This function deletes the record that is pointed to by the
|
|
// cursor.
|
|
//======================================================================
|
|
DBIResult
|
|
DeleteRec (hDBICur hCur)
|
|
{
|
|
CHKERR(DbiGetRecord(hCur, dbiWRITELOCK, NULL, 0));
|
|
|
|
CHKERR(DbiDeleteRecord(hCur, NULL));
|
|
return DBIERR_NONE;
|
|
}
|
|
|
|
//======================================================================
|
|
// Name: SetRange()
|
|
//
|
|
// Input: Record structure pointer for high range value (RecordType *),
|
|
// Record structure pointer for low range value (RecordType *),
|
|
// Bool describing whether the high value is included in the range
|
|
// (BOOL), Bool describing the low value is included in the range
|
|
// (BOOL), Cursor handle (hDBICur), Bool describing whether
|
|
// pHighRec is filled with a value (BOOL), Bool describing whether
|
|
// pLowRec is filled with a value (BOOL).
|
|
//
|
|
// Return: DBIERR_NONE if the range is successfully set.
|
|
//
|
|
// Desc: This function sets the range. To do so it needs the high and
|
|
// low values. So we pass them inside of pHighRec and pLowRec.
|
|
// Then we need to know if these range values are to be included in
|
|
// the range set. That is done by using the two booleans
|
|
// bHighInclude and bLowInclude. Finally we need to pass a NULL
|
|
// pointer to the set range function if the user set no upper or
|
|
// lower range. So we look at bHighEmpty and bLowEmpty.
|
|
//======================================================================
|
|
DBIResult
|
|
SetRange (RecordType *pHighRec, RecordType *pLowRec, BOOL bHighInclude,
|
|
BOOL bLowInclude, hDBICur hCur, BOOL bHighEmpty, BOOL bLowEmpty)
|
|
{
|
|
CURProps TblProps;
|
|
pBYTE pHighRecBuf = NULL;
|
|
pBYTE pLowRecBuf = NULL;
|
|
|
|
CHKERR_CLEANUP(DbiGetCursorProps(hCur,&TblProps));
|
|
|
|
if(!bHighEmpty)
|
|
{
|
|
if((pHighRecBuf = (pBYTE) malloc(TblProps.iRecBufSize))==NULL)
|
|
{
|
|
WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
|
|
CLEANUP(DBIERR_NOMEMORY);
|
|
}
|
|
CHKERR_CLEANUP(DbiInitRecord(hCur, pHighRecBuf));
|
|
|
|
// Copy the value into the pRecBuf.
|
|
CHKERR_NODISPLAY(FillBuf(hCur, pHighRecBuf, pHighRec));
|
|
}
|
|
|
|
if(!bLowEmpty)
|
|
{
|
|
if((pLowRecBuf = (pBYTE) malloc(TblProps.iRecBufSize))==NULL)
|
|
{
|
|
WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
|
|
CLEANUP(DBIERR_NOMEMORY);
|
|
}
|
|
CHKERR_CLEANUP(DbiInitRecord(hCur, pLowRecBuf));
|
|
|
|
// Copy the value into the pRecBuf.
|
|
CHKERR_NODISPLAY(FillBuf(hCur, pLowRecBuf, pLowRec));
|
|
}
|
|
|
|
// Set the range. The record buffers hold the low and high range
|
|
// field values. Since we are using buffers rather than using a direct
|
|
// pair of strings we set the second parameter to FALSE. The two
|
|
// booleans are set by the check boxes in the range dialog box. They
|
|
// describe whether the range value will be included inside the answer
|
|
// set.
|
|
CHKERR_CLEANUP(DbiSetRange(hCur, FALSE, 0, 0, pLowRecBuf, bLowInclude,
|
|
0, 0, pHighRecBuf, bHighInclude));
|
|
|
|
// Free the record buffers - ONLY if they need to be freed.
|
|
if(!bLowEmpty)
|
|
{
|
|
free(pLowRecBuf);
|
|
}
|
|
if(!bHighEmpty)
|
|
{
|
|
free(pHighRecBuf);
|
|
}
|
|
return DBIERR_NONE;
|
|
|
|
CleanUp:
|
|
if(!bLowEmpty)
|
|
{
|
|
free(pLowRecBuf);
|
|
}
|
|
if(!bHighEmpty)
|
|
{
|
|
free(pHighRecBuf);
|
|
}
|
|
return GlobalDBIErr;
|
|
}
|
|
|
|
//======================================================================
|
|
// Name: FillBuf()
|
|
//
|
|
// Input: Handle to the cursor (hDBICur), Record buffer (pBYTE), and
|
|
// a record structure pointer (RecordType*).
|
|
//
|
|
// Return: DBIErr_NONE if the PutFields are all successful.
|
|
//
|
|
// Desc: This function takes the relevent data from the record structure
|
|
// and puts it into a record buffer that IDAPI understands.
|
|
//======================================================================
|
|
DBIResult
|
|
FillBuf (hDBICur hCur, pBYTE pRecBuf, RecordType* pString)
|
|
{
|
|
// Fill each field with the structure's data
|
|
CHKERR(DbiPutField(hCur, 1, pRecBuf, (pBYTE)pString->FName));
|
|
CHKERR(DbiPutField(hCur, 2, pRecBuf, (pBYTE)pString->LName));
|
|
CHKERR(DbiPutField(hCur, 3, pRecBuf, (pBYTE)pString->Spouse));
|
|
CHKERR(DbiPutField(hCur, 4, pRecBuf, (pBYTE)pString->Addrs1));
|
|
CHKERR(DbiPutField(hCur, 5, pRecBuf, (pBYTE)pString->Addrs2));
|
|
CHKERR(DbiPutField(hCur, 6, pRecBuf, (pBYTE)pString->City));
|
|
CHKERR(DbiPutField(hCur, 7, pRecBuf, (pBYTE)pString->State));
|
|
CHKERR(DbiPutField(hCur, 8, pRecBuf, (pBYTE)pString->Zip));
|
|
CHKERR(DbiPutField(hCur, 9, pRecBuf, (pBYTE)pString->Phone1));
|
|
return DBIERR_NONE;
|
|
}
|
|
|
|
//======================================================================
|
|
// Name: Search()
|
|
//
|
|
// Input: Handle to the cursor (hDBICur), Search condition (DBISearchCond),
|
|
// Boolean: TRUE if the key is in a string. FALSE if the key is in
|
|
// a record buffer BOOL), Number of fields to match (UINT16),
|
|
// Length of characters needed to qualify a match (UINT16), and the
|
|
// key to search (pBYTE).
|
|
//
|
|
// Return: DBIERR_NONE if the search is successful.
|
|
//
|
|
// Desc: This function searches for a string based upon the index that
|
|
// is presently active on the table.
|
|
//======================================================================
|
|
DBIResult
|
|
Search (hDBICur hCur, DBISearchCond eCond, BOOL bDirect, UINT16 iFlds,
|
|
UINT16 iLen, RecordType *pKey)
|
|
{
|
|
DBIResult rslt;
|
|
pBYTE pRecBuf;
|
|
CURProps TblProps;
|
|
|
|
CHKERR_CLEANUP(DbiGetCursorProps(hCur,&TblProps));
|
|
|
|
if((pRecBuf = (pBYTE) malloc(TblProps.iRecBufSize))==NULL)
|
|
{
|
|
WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
|
|
CLEANUP(DBIERR_NOMEMORY);
|
|
}
|
|
CHKERR_CLEANUP(DbiInitRecord(hCur, pRecBuf));
|
|
|
|
// Copy the value into the pRecBuf.
|
|
CHKERR_NODISPLAY(FillBuf(hCur, pRecBuf, pKey));
|
|
|
|
rslt = DbiSetToKey(hCur, eCond, bDirect, iFlds, iLen, pRecBuf);
|
|
|
|
if(rslt != DBIERR_NONE)
|
|
{
|
|
// Check if the error is RECNOTFOUND. If it is return that as the
|
|
// calling function is expecting either DBIERR_NONE or RECNOTFOUND.
|
|
if(rslt!=DBIERR_RECNOTFOUND)
|
|
{
|
|
CHKERR(rslt);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Check if we are at the EOF. If we are return RECNOTFOUND.
|
|
if(AtEOF(hCur))
|
|
{
|
|
rslt = DBIERR_RECNOTFOUND;
|
|
}
|
|
}
|
|
|
|
if (pRecBuf)
|
|
{
|
|
free(pRecBuf);
|
|
}
|
|
|
|
return rslt;
|
|
|
|
CleanUp:
|
|
if(pRecBuf)
|
|
{
|
|
free(pRecBuf);
|
|
}
|
|
return GlobalDBIErr;
|
|
|
|
}
|
|
|
|
//======================================================================
|
|
// Name: ResetRange()
|
|
//
|
|
// Input: Handle to the cursor (hDBICur).
|
|
//
|
|
// Return: DBIERR_NONE if the range is successfully reset.
|
|
//
|
|
// Desc: This function clears any range settings. The outcome is that
|
|
// all records will be visable to the user.
|
|
//======================================================================
|
|
DBIResult
|
|
ResetRange (hDBICur hCur)
|
|
{
|
|
CHKERR(DbiResetRange(hCur));
|
|
return DBIERR_NONE;
|
|
}
|
|
|
|
//======================================================================
|
|
// Name: DateEncode()
|
|
//
|
|
// Input: The month, day, and year (UINT16), and a pointer to the
|
|
// DATE variable that is to be passed into a record buffer.
|
|
//
|
|
// Return: DBIERR_NONE if the date is successfully encoded.
|
|
//
|
|
// Desc: This function takes in the date, month, and year and encodes
|
|
// them into the DATE pointer with the DateEncode function.
|
|
//======================================================================
|
|
DBIResult
|
|
DateEncode (UINT16 iMon, UINT16 iDay, UINT16 iYear, pDATE pTempDate)
|
|
{
|
|
|
|
DBIResult rslt;
|
|
|
|
// Check the result of the date encode and return it.
|
|
rslt = DbiDateEncode(iMon, iDay, iYear, pTempDate);
|
|
|
|
return rslt;
|
|
}
|
|
|
|
//======================================================================
|
|
// Name: GetDateFormat()
|
|
//
|
|
// Input: Date format structure (FMTDate).
|
|
//
|
|
// Return: DBIERR_NONE if the date format is successfully retrieved.
|
|
//
|
|
// Desc: This function takes in the in the date format structure and
|
|
// fills it with the current date seettings of IDAPI.
|
|
//======================================================================
|
|
DBIResult
|
|
GetDateFormat (pFMTDate pDate)
|
|
{
|
|
|
|
DBIResult rslt;
|
|
|
|
// Check the result of the date encode and return it.
|
|
rslt = DbiGetDateFormat(pDate);
|
|
|
|
return rslt;
|
|
}
|
|
|
|
//======================================================================
|
|
// Name: GetDirectory()
|
|
//
|
|
// Input: The database handle (hDBIDb), and a directory string (pCHAR).
|
|
//
|
|
// Return: DBIERR_NONE if the directory name is successfully retrieved.
|
|
//
|
|
// Desc: This function takes in the in the directory string and getss
|
|
// the defualt directory.
|
|
//======================================================================
|
|
DBIResult
|
|
GetDirectory (hDBIDb hDb, pCHAR pszBuffer)
|
|
{
|
|
DBIResult rslt;
|
|
rslt = DbiGetDirectory(hDb, FALSE, pszBuffer);
|
|
return rslt;
|
|
}
|
|
|
|
//======================================================================
|
|
// Name: FillAliasStr()
|
|
//
|
|
// Input: Pointer to a Database descriptor structure (pDBDesc).
|
|
// Number of aliases (plNumAliases).
|
|
//
|
|
// Return: DBIERR_NONE if Alias pointer is successfully filled.
|
|
//
|
|
// Desc: This function takes in the in the DBDesc structure and
|
|
// fills it with all the alias information for the given table.
|
|
// It then returns the number of aliases in the plNumAliases
|
|
// parameter.
|
|
//======================================================================
|
|
DBIResult
|
|
FillAliasStr (pDBDesc *Alias, pUINT32 plNumAliases)
|
|
{
|
|
UINT16 i;
|
|
hDBICur hDBCur = NULL;
|
|
UINT32 iTempNum = 0;
|
|
|
|
*plNumAliases = 0;
|
|
|
|
// Get the list of aliases, by getting the list of all Databases that
|
|
// are available to the client.
|
|
CHKERR_CLEANUP(DbiOpenDatabaseList(&hDBCur));
|
|
|
|
CHKERR_CLEANUP(DbiGetRecordCount(hDBCur, plNumAliases));
|
|
|
|
if(*plNumAliases * sizeof(DBDesc) > 64000L)
|
|
{
|
|
iTempNum = MAXCHARLEN/sizeof(DBDesc);
|
|
*plNumAliases = iTempNum;
|
|
}
|
|
|
|
if(((*Alias = (pDBDesc) malloc((UINT16)*plNumAliases * sizeof(DBDesc)))
|
|
== NULL) && (*plNumAliases > 0))
|
|
{
|
|
WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
|
|
CLEANUP(DBIERR_NOMEMORY);
|
|
}
|
|
|
|
CHKERR_CLEANUP(DbiSetToBegin(hDBCur));
|
|
|
|
// Fill the pointer with the records that hDBCur points to.
|
|
for(i=0; i<*plNumAliases; i++)
|
|
{
|
|
// Move past the BOF and loop until EOF.
|
|
CHKERR_CLEANUP(DbiGetNextRecord(hDBCur, dbiNOLOCK,
|
|
(pBYTE)&((*Alias)[i]), NULL));
|
|
}
|
|
|
|
// Close the schema table.
|
|
CHKERR_CLEANUP(DbiCloseCursor(&hDBCur));
|
|
return DBIERR_NONE;
|
|
|
|
CleanUp:
|
|
if(hDBCur)
|
|
{
|
|
DbiCloseCursor(&hDBCur);
|
|
}
|
|
return GlobalDBIErr;
|
|
}
|
|
|
|
//======================================================================
|
|
// Name: OpenDB()
|
|
//
|
|
// Input: Pointer to the Database (phDBIDb), Table type (pCHAR),
|
|
// Password (pCHAR), Table Name/Alias (pCHAR).
|
|
//
|
|
// Return: DBIERR_NONE if the database is successfully opened.
|
|
//
|
|
// Desc: This function opens a database for the given pointer to the
|
|
// database handle.
|
|
//======================================================================
|
|
DBIResult
|
|
OpenDB (phDBIDb phDb, pCHAR pszTableType, pCHAR pszPassword, pCHAR pszAlias)
|
|
{
|
|
DBIResult rslt;
|
|
|
|
rslt = DbiOpenDatabase(pszAlias, pszTableType, dbiREADWRITE,
|
|
dbiOPENSHARED, pszPassword, 0, NULL, NULL, phDb);
|
|
if(rslt != DBIERR_NONE)
|
|
{
|
|
CHKERR(rslt);
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
//======================================================================
|
|
// Name: DisplayError()
|
|
//
|
|
// Input: Error number (DBIResult), and pointer to the message string
|
|
// (pCHAR).
|
|
//
|
|
// Return: DBIERR_NONE if the error information is successfully retrieved.
|
|
//
|
|
// Desc: This function allocates memory for the pMsg string and the fills
|
|
// it with all the extended error information.
|
|
//======================================================================
|
|
DBIResult
|
|
DisplayError (DBIResult rslt, pCHAR *pszMsg)
|
|
{
|
|
DBIErrInfo ErrInfo;
|
|
DBIResult rslt1;
|
|
|
|
// Need enough space for the message from IDAPI, as well as additional
|
|
// information.
|
|
CHAR szMsg[DBIMAXMSGLEN + 40];
|
|
|
|
// Need five plus additional information.
|
|
if((*pszMsg = (pCHAR)malloc(DBIMAXMSGLEN * 7))==NULL)
|
|
{
|
|
WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
|
|
rslt1 = DBIERR_NOMEMORY;
|
|
CHKERR(rslt1);
|
|
}
|
|
|
|
// Failed to connect
|
|
CHKERR(DbiGetErrorInfo(TRUE, &ErrInfo));
|
|
|
|
wsprintf(*pszMsg, " Error Category = %d Error Code = %d\r\n",
|
|
ErrCat(rslt), ErrCode(rslt));
|
|
|
|
if (ErrInfo.szErrCode[0] != '\0')
|
|
{
|
|
wsprintf(szMsg, " -> ErrCode: %s\r\n", ErrInfo.szErrCode);
|
|
strcat(*pszMsg, szMsg);
|
|
}
|
|
|
|
if (ErrInfo.szContext1[0] != '\0')
|
|
{
|
|
wsprintf(szMsg, " -> Context1: %s\r\n", ErrInfo.szContext1);
|
|
strcat(*pszMsg, szMsg);
|
|
}
|
|
|
|
if (ErrInfo.szContext2[0] != '\0')
|
|
{
|
|
wsprintf(szMsg, " -> Context2: %s\r\n", ErrInfo.szContext2);
|
|
strcat(*pszMsg, szMsg);
|
|
}
|
|
|
|
if (ErrInfo.szContext3[0] != '\0')
|
|
{
|
|
wsprintf(szMsg, " -> Context3: %s\r\n", ErrInfo.szContext3);
|
|
strcat(*pszMsg, szMsg);
|
|
}
|
|
|
|
if (ErrInfo.szContext4[0] != '\0')
|
|
{
|
|
wsprintf(szMsg, " -> Context4: %s\r\n", ErrInfo.szContext4);
|
|
strcat(*pszMsg, szMsg);
|
|
}
|
|
|
|
return DBIERR_NONE;
|
|
}
|
|
|
|
//======================================================================
|
|
// Name: GetFieldInfo()
|
|
//
|
|
// Input: Field name (pCHAR), Pointer to the Field number (pUINT16),
|
|
// Pointer to Field len (pUINT16), Cursor handle (hDBICur), and
|
|
// Number of fields in table (UINT16).
|
|
//
|
|
// Return: DBIERR_NONE if the field descriptor is successfully filled,
|
|
// number of the field in FldNum, and the field len in FldLen.
|
|
//
|
|
// Desc: This function searches for the field name that is passed to
|
|
// it and fills the FldNum variable with the number of the field.
|
|
// The number correlates to the field number that IDAPI uses.
|
|
// It also returns the field length inside of the FldLen variable.
|
|
//======================================================================
|
|
DBIResult
|
|
GetFieldInfo (pCHAR pFld, pUINT16 FldNum, pUINT16 FldLen, hDBICur hCur,
|
|
UINT16 iFields)
|
|
{
|
|
pFLDDesc pFldDesc = NULL;
|
|
pCHAR pFldName = NULL;
|
|
UINT16 i;
|
|
BOOL bFlag = FALSE;
|
|
|
|
// Get all the field descriptors.
|
|
if ((pFldDesc = (pFLDDesc)malloc(sizeof(FLDDesc) * iFields)) == NULL)
|
|
{
|
|
WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
|
|
CLEANUP(DBIERR_NOMEMORY);
|
|
}
|
|
|
|
if ((pFldName = (pCHAR)malloc(sizeof(CHAR) * DBIMAXNAMELEN)) == NULL)
|
|
{
|
|
WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
|
|
CLEANUP(DBIERR_NOMEMORY);
|
|
}
|
|
|
|
CHKERR_CLEANUP(DbiGetFieldDescs(hCur, pFldDesc));
|
|
|
|
// Strip out any spaces so that we can find the field names correctly.
|
|
StripChar(pFldName, pFld, 32);
|
|
|
|
i = 0;
|
|
|
|
// Loop through the field names and find the name that matches.
|
|
while(i<iFields && !bFlag)
|
|
{
|
|
if(stricmp(pFldDesc[i].szName, pFldName)==0)
|
|
{
|
|
*FldNum = pFldDesc[i].iFldNum;
|
|
|
|
// Get the field length so for this particular field.
|
|
if(pFldDesc[i].iFldType == fldDATE)
|
|
{
|
|
*FldLen = DATELEN-1;
|
|
bFlag = TRUE;
|
|
}
|
|
|
|
if(pFldDesc[i].iFldType == fldZSTRING)
|
|
{
|
|
*FldLen = pFldDesc[i].iUnits1;
|
|
bFlag = TRUE;
|
|
}
|
|
}
|
|
i++;
|
|
}
|
|
|
|
free(pFldDesc);
|
|
free(pFldName);
|
|
|
|
return DBIERR_NONE;
|
|
|
|
CleanUp:
|
|
if(pFldDesc)
|
|
{
|
|
free(pFldDesc);
|
|
}
|
|
if(pFldName)
|
|
{
|
|
free(pFldName);
|
|
}
|
|
return GlobalDBIErr;
|
|
}
|
|
|
|
//======================================================================
|
|
// Name: StripChar()
|
|
//
|
|
// Input: Destination string (pCHAR), and Source string (pCHAR), Character
|
|
// to strip out (CHAR).
|
|
//
|
|
// Return: None.
|
|
//
|
|
// Desc: This function strips any charachter out of the source string
|
|
// (Src) and puts the new string into the destination string
|
|
// (Dest).
|
|
//======================================================================
|
|
void
|
|
StripChar (pCHAR pszDest, pCHAR pszSrc, CHAR cChar)
|
|
{
|
|
UINT16 i;
|
|
UINT16 iDest;
|
|
UINT16 iLen;
|
|
|
|
memset(pszDest, '\0', DBIMAXNAMELEN);
|
|
|
|
// Get the total length of the string
|
|
iLen = strlen(pszSrc);
|
|
|
|
// Loop through the string. If we find a space do not copy the space
|
|
// into the dest string. Also set iDest = 0.
|
|
iDest=0;
|
|
for(i=0; i<iLen; i++)
|
|
{
|
|
// If the character is not a space copy it to the Dest string.
|
|
if(pszSrc[i]!=cChar)
|
|
{
|
|
pszDest[iDest]=pszSrc[i];
|
|
iDest++;
|
|
}
|
|
}
|
|
pszDest[iDest]='\0';
|
|
}
|
|
|
|
//======================================================================
|
|
// Name: GetMdxName()
|
|
//
|
|
// Input: Cursor handle (hDBICur), and a string to put the Mdx name in
|
|
// (pCHAR).
|
|
//
|
|
// Return: DBIERR_NONE if the Mdx name is successfully retrieved.
|
|
//
|
|
// Desc: This function gets the Mdx name for the given table pointed
|
|
// to by hCur, and returns the name of the Mdx file associated
|
|
// with that cursor handle.
|
|
//======================================================================
|
|
DBIResult
|
|
GetMdxName (hDBICur hCur, pCHAR pszMdxName)
|
|
{
|
|
pIDXDesc pMyDesc = NULL;
|
|
|
|
if ((pMyDesc = (pIDXDesc)malloc(sizeof(IDXDesc) * 1)) == NULL)
|
|
{
|
|
WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
|
|
CLEANUP(DBIERR_NOMEMORY);
|
|
}
|
|
|
|
// Simply Get the first tag of the Mdx and get the Mdx name. In an
|
|
// Mdx all the tags have the same MDX file name, as they all live
|
|
// inside the same MDX file. We pass in 1, because that gets the first
|
|
// index while 0 gets the active index - of which there is none - yet.
|
|
CHKERR_CLEANUP(DbiGetIndexDesc(hCur, 1, pMyDesc));
|
|
strcpy(pszMdxName, pMyDesc->szName);
|
|
free(pMyDesc);
|
|
return DBIERR_NONE;
|
|
|
|
CleanUp:
|
|
if(pMyDesc)
|
|
{
|
|
free(pMyDesc);
|
|
}
|
|
return GlobalDBIErr;
|
|
}
|
|
|
|
//======================================================================
|
|
// Name: GetIndexDescs()
|
|
//
|
|
// Input: Cursor handle (hDBICur), and a pointer to the index descriptor
|
|
// (pIDXDesc).
|
|
//
|
|
// Return: DBIERR_NONE if the index descriptor is successfully filled.
|
|
//
|
|
// Desc: This function takes in the index descriptor and fills it with
|
|
// all the indexes that are open for the table and database.
|
|
//======================================================================
|
|
DBIResult
|
|
GetIndexDescs (hDBIDb hDb, pIDXDesc pAllDesc)
|
|
{
|
|
UINT16 i;
|
|
hDBICur hIdxCur = NULL;
|
|
|
|
CHKERR_CLEANUP(DbiOpenIndexList(hDb, (pCHAR)szTblName, (pCHAR)szTblType,
|
|
&hIdxCur));
|
|
|
|
// Go to the top of the in-memory table.
|
|
CHKERR_CLEANUP(DbiSetToBegin(hIdxCur));
|
|
|
|
// Now fill the pointer with the records that hDBCur points to.
|
|
i = 0;
|
|
while((DbiGetNextRecord(hIdxCur, dbiNOLOCK, (pBYTE)(&pAllDesc[i]),
|
|
NULL))!=DBIERR_EOF)
|
|
{
|
|
// Check if the table is a PARADOX table. If it is the primary
|
|
// index will not have a name and we need to give it one.
|
|
if(strcmpi(szTblType, szPARADOX)==0)
|
|
{
|
|
if(pAllDesc[i].iIndexId == 0)
|
|
{
|
|
strcpy(pAllDesc[i].szName, "Primary");
|
|
}
|
|
}
|
|
i++;
|
|
}
|
|
|
|
DbiCloseCursor(&hIdxCur);
|
|
return DBIERR_NONE;
|
|
|
|
CleanUp:
|
|
if(hIdxCur)
|
|
{
|
|
DbiCloseCursor(&hIdxCur);
|
|
}
|
|
return GlobalDBIErr;
|
|
}
|
|
|
|
//======================================================================
|
|
// Name: GetFldNames()
|
|
//
|
|
// Input: Cursor handle (hDBICur), and a pointer to the Field name
|
|
// structure (pFieldNames).
|
|
//
|
|
// Return: DBIERR_NONE if the field names are successfully returned.
|
|
//
|
|
// Desc: This function fills the pFieldNames pointer with all the field
|
|
// names for the given table.
|
|
//======================================================================
|
|
DBIResult
|
|
GetFldNames (hDBICur hCur, pFIELDName pFieldNames)
|
|
{
|
|
pFLDDesc pFields = NULL;
|
|
UINT16 i;
|
|
CURProps TblProps;
|
|
|
|
CHKERR_CLEANUP(DbiGetCursorProps(hCur, &TblProps));
|
|
|
|
if ((pFields = (pFLDDesc)malloc(sizeof(FLDDesc) * TblProps.iFields))
|
|
== NULL)
|
|
{
|
|
WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
|
|
CLEANUP(DBIERR_NOMEMORY);
|
|
}
|
|
|
|
CHKERR_CLEANUP(DbiGetFieldDescs(hCur, pFields));
|
|
|
|
for(i=0; i<TblProps.iFields; i++)
|
|
{
|
|
strcpy(pFieldNames[i].FieldName, pFields[i].szName);
|
|
}
|
|
|
|
free(pFields);
|
|
return DBIERR_NONE;
|
|
|
|
CleanUp:
|
|
if(pFields)
|
|
{
|
|
free(pFields);
|
|
}
|
|
return GlobalDBIErr;
|
|
}
|
|
|
|
//======================================================================
|
|
// Name: CloseTable()
|
|
//
|
|
// Input: Pointer to the cursor handle (phDBICur).
|
|
//
|
|
// Return: DBIERR_NONE if the table is successfully closed.
|
|
//
|
|
// Desc: This function simply closes the given table.
|
|
//======================================================================
|
|
DBIResult
|
|
CloseTable (phDBICur pCur)
|
|
{
|
|
CHKERR(DbiCloseCursor(pCur));
|
|
|
|
return DBIERR_NONE;
|
|
}
|
|
|
|
//======================================================================
|
|
// Name: CheckTable()
|
|
//
|
|
// Input: Table Cursor (hDBICur).
|
|
// Boolean (pBOOL).
|
|
//
|
|
// Return: DBIERR_NONE if table is successfully checked.
|
|
//
|
|
// Desc: This function simply gets the field descriptors for the given
|
|
// table and checks if they match the predefined structure for an
|
|
// addressbook. If they match it sets the pbFlag parameter to
|
|
// TRUE.
|
|
//======================================================================
|
|
DBIResult
|
|
CheckTable (hDBICur hCur, pBOOL pbFlag)
|
|
{
|
|
pFLDDesc pFldDesc = NULL;
|
|
UINT16 i;
|
|
CURProps TblProps;
|
|
|
|
*pbFlag = TRUE;
|
|
|
|
CHKERR_CLEANUP(DbiGetCursorProps(hCur, &TblProps));
|
|
|
|
if ((pFldDesc = (pFLDDesc)malloc(sizeof(FLDDesc) * TblProps.iFields))
|
|
== NULL)
|
|
{
|
|
WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
|
|
CLEANUP(DBIERR_NOMEMORY);
|
|
}
|
|
|
|
CHKERR_CLEANUP(DbiGetFieldDescs(hCur, pFldDesc));
|
|
|
|
i = 0;
|
|
|
|
// Now loop through the field structure and check that both the field
|
|
// type matches and that the field len match. If they do not then you
|
|
// fall out of the loop and set *pbFlag to FALSE.
|
|
while(i<TblProps.iFields && *pbFlag)
|
|
{
|
|
if(!((pFldDesc[i].iFldType == fldDesc[i].iFldType) &&
|
|
(pFldDesc[i].iUnits1 == fldDesc[i].iUnits1)))
|
|
{
|
|
// If the field is a blob field we do not care what the size is.
|
|
if(pFldDesc[i].iFldType == fldBLOB)
|
|
{
|
|
if(!((pFldDesc[i].iFldType == fldDesc[i].iFldType) &&
|
|
(pFldDesc[i].iSubType == fldDesc[i].iSubType)))
|
|
{
|
|
*pbFlag = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// If this is a time stamp field or a date then do not
|
|
// care about size.
|
|
if((pFldDesc[i].iFldType != fldTIMESTAMP)&&
|
|
(pFldDesc[i].iFldType != fldDATE))
|
|
{
|
|
*pbFlag = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
free(pFldDesc);
|
|
return DBIERR_NONE;
|
|
|
|
CleanUp:
|
|
if(pFldDesc)
|
|
{
|
|
free(pFldDesc);
|
|
}
|
|
*pbFlag = FALSE;
|
|
return GlobalDBIErr;
|
|
}
|
|
|
|
//======================================================================
|
|
// Name: GetTblType()
|
|
//
|
|
// Input: Table Cursor (hDBICur), a pointer to the Table Type string
|
|
// (pCHAR).
|
|
//
|
|
// Return: DBIERR_NONE if the table type is successfully acquired. It
|
|
// also returns the table type into the pszTableType string.
|
|
//
|
|
// Desc: This function simply gets the table type for the given table
|
|
// handle. It then returns the table type in the string called
|
|
// pszTableType (the second parameter).
|
|
//======================================================================
|
|
DBIResult
|
|
GetTblType (hDBICur hCur, pCHAR pszTableType)
|
|
{
|
|
|
|
CURProps TblProps;
|
|
|
|
// Get the cursor properties for the Addressbook table.
|
|
CHKERR(DbiGetCursorProps(hCur, &TblProps));
|
|
strcpy(pszTableType, TblProps.szTableType);
|
|
return DBIERR_NONE;
|
|
}
|
|
|
|
//======================================================================
|
|
// Name: InitIndex1()
|
|
//
|
|
// Input: Pointer to the Table Cursor (phDBICur).
|
|
//
|
|
// Return: DBIERR_NONE if the index is successfully set.
|
|
//
|
|
// Desc: This function sets the initial index for a given table. It
|
|
// sets the index based upon the table type.
|
|
//======================================================================
|
|
DBIResult
|
|
InitIndex1 (phDBICur phCur)
|
|
{
|
|
CURProps TblProps;
|
|
pIDXDesc pIndexDesc = NULL;
|
|
|
|
// Get the table's properties so that we can get the size.
|
|
CHKERR_CLEANUP(DbiGetCursorProps(*phCur, &TblProps));
|
|
|
|
if(TblProps.iIndexes !=0)
|
|
{
|
|
if((pIndexDesc = (pIDXDesc) malloc(TblProps.iIndexes *
|
|
sizeof(IDXDesc))) == NULL)
|
|
{
|
|
WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
|
|
CLEANUP(DBIERR_NOMEMORY);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WinMsg("There are no Indexes on this table!", MB_ICONHAND, MB_OK);
|
|
CLEANUP(DBIERR_NOMEMORY);
|
|
}
|
|
|
|
// Get the index descriptors.
|
|
CHKERR_CLEANUP(DbiGetIndexDescs(*phCur, pIndexDesc));
|
|
|
|
if(stricmp(szTblType, szDBASE)==0)
|
|
{
|
|
SetupIndex(phCur, pIndexDesc[0].szName, pIndexDesc[0].szTagName,
|
|
NULL);
|
|
}
|
|
else
|
|
{
|
|
if(stricmp(szTblType, szPARADOX)==0)
|
|
{
|
|
SetupIndex(phCur, NULL, NULL, 0);
|
|
}
|
|
else
|
|
{
|
|
SetupIndex(phCur, pIndexDesc[0].szName, NULL, NULL);
|
|
}
|
|
}
|
|
|
|
free(pIndexDesc);
|
|
return DBIERR_NONE;
|
|
|
|
CleanUp:
|
|
if(pIndexDesc)
|
|
{
|
|
free(pIndexDesc);
|
|
}
|
|
return GlobalDBIErr;
|
|
}
|
|
|
|
//======================================================================
|
|
// Name: GetTableList()
|
|
//
|
|
// Input: Handle to the database (hDBIDb), and the pointer to a table
|
|
// that will point to a table containing information about all
|
|
// the tables inside of this database (phDBICur).
|
|
//
|
|
// Return: None.
|
|
//
|
|
// Desc: This function opens the table list using the cusror passed
|
|
// into it by the calling function.
|
|
//======================================================================
|
|
DBIResult
|
|
GetTableList (hDBIDb hDb, phDBICur phTblCur)
|
|
{
|
|
// Get the list of tables that are available to the client.
|
|
CHKERR(DbiOpenTableList(hDb, FALSE, FALSE, NULL, phTblCur));
|
|
return DBIERR_NONE;
|
|
}
|
|
|
|
//======================================================================
|
|
// Name: GetNextTblRec()
|
|
//
|
|
// Input: Handle to the Cursor (hDBICur), Pointer to a base table
|
|
// descriptor (pTBLBaseDesc).
|
|
//
|
|
// Return: DBIERR_NONE if the structure is successfully retrieved.
|
|
//
|
|
// Desc: This function simply gets the base table descriptor for
|
|
// the given cursor.
|
|
//======================================================================
|
|
DBIResult
|
|
GetNextTblRec(hDBICur hTblCur, pTBLBaseDesc pbaseDesc)
|
|
{
|
|
DBIResult rslt;
|
|
|
|
rslt = DbiGetNextRecord(hTblCur, dbiNOLOCK, (pBYTE)pbaseDesc, NULL);
|
|
if(rslt != DBIERR_NONE)
|
|
{
|
|
if(rslt == DBIERR_EOF)
|
|
{
|
|
return rslt;
|
|
}
|
|
else
|
|
{
|
|
CHKERR(rslt);
|
|
}
|
|
}
|
|
return DBIERR_NONE;
|
|
}
|
|
|
|
//======================================================================
|
|
// Name: DeleteTable()
|
|
//
|
|
// Input: Pointer to the Cursor (phDBICur), Handle to the database
|
|
// (hDBIDb), Table Name (pCHAR), and Table Type (pCHAR).
|
|
//
|
|
// Return: DBIERR_NONE if the table is successfully deleted.
|
|
//
|
|
// Desc: This function simply closes and then deletes the table whose
|
|
// cursor and name are passed to it.
|
|
//======================================================================
|
|
DBIResult
|
|
DeleteTable (phDBICur phCur, hDBIDb hDb, pCHAR TblName, pCHAR TblType)
|
|
{
|
|
CHKERR(DbiCloseCursor(phCur));
|
|
CHKERR(DbiDeleteTable(hDb, TblName, TblType));
|
|
return DBIERR_NONE;
|
|
}
|