Files
TeslaRel410/BORLAND/BDE/EXAMPLES/PDOXWIN/SEEK/DBFSEEK.C
T
CydandClaude Fable 5 63312e07f9 source410: literal 4.10 source reconstruction + BC++ 4.52 fleet toolchain archived
- 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>
2026-07-19 07:33:26 -05:00

887 lines
27 KiB
C++

// BDE - (C) Copyright 1995 by Borland International
#include "dbfseek.h"
#include "macro.h"
#define szCURRENTMODULE "DBFSEEK"
//=====================================================================
// This BDE example provides Paradox for Windows ver. 5.0 ObjectPAL users
// a means of doing a seek similar to the dBASE seek of MAINTAINED
// expression indexes on dBASE tables for retrieving record numbers. The
// ObjectPAL procedures created are: DbfIdxSeek and DbfGetIdxExpr.
//
// Expressions tested in an MDX file:
//
// LTRIM(STR(MONTH(DATES)))+"/"+LTRIM(STR(DAY(DATES)))+"/"
// +SUBSTR(LTRIM(STR(YEAR(DATES))),3,2)
// LTRIM(FIRST_NAME)
// LTRIM(FIRST_NAME)-LTRIM(LAST_NAME)
// FIRST_NAME (a character field)
// FIRST_NAME-LAST_NAME
// FLOATS (a float field)
// NUMBERS (a number field)
// RECNO()
// RTRIM(FIRST_NAME) + DTOS(DATES)
// Indexes on concatenation of character and date field. The date
// field is converted to characters in format YYYYMMDD.
// i.e. - Jerry19950518.
// SQRT(NUMBERS)
// LTRIM(STR(FLOATS))
// SUBSTR(FIRST_NAME,2,3)
//
// Notes:
//
// DbfIdxSeek returns a record number. A return of 0 means that the record
// was not found.
//
// DbfGetIdxExpr is just for viewing an expression string.
//
// The EXACT setting, when set to FALSE, will find records with partial
// values in character expressions. EXACT set to TRUE sets NEAR to FALSE.
//
// EXACT: 0 = FALSE, 1 = TRUE
//
// The NEAR setting, after an unsuccessful dbfSEEK, positions the record
// pointer at the record in the indexed table immediately after the position
// at which the value searched for would have been found.
//
// NEAR: 0 = FALSE, 1 = TRUE
//
// Character expressions are case sensitive except for soundex which must
// sound like the key value for a match to occur.
//
// Use no commas in values seeking NUMERIC expressions.
//
// "Sounds like" can be used if SOUNDEX is the only function used
// and is at the beginning of the expression. All field names and
// other words must be contained within its perentheses i.e. -
// SOUNDEX(FIRST_NAME)
// SOUNDEX(FIRST_NAME-LAST_NAME)
//
// DATE fields can be used directly if the field name is at the beginning
// of the expression and is used alone i.e. -
// DATES (a date field)
//
//
// This is how the Paradox Uses block should appear:
//
// Uses dbfseek
//
// DbfIdxSeek(TableDir cptr, TableName cptr,
// IndexFileNameWithExtension cptr,
// IndexTagName cptr, KeyValue cptr,
// Exact cword, Near cword,
// returnStringBuffer cptr)cdouble
// DbfGetIdxExpr(TableDir cptr, TableName cptr,
// IndexFileNameWithExtension cptr,
// IndexTagName cptr, ReturnValue cptr)
//
// endUses
//
//
// And some typical methods:
//
// Var
// returnStringBuffer String
// endVar
//
//
// method open(var eventInfo Event)
//
// if eventInfo.isPreFilter() then
// ;// This code executes for each object on the form:
//
// else
// ;// This code executes only for the form:
//
// ; requires a 129 byte buffer:
// returnStringBuffer = space(129) ; VERY IMPORTANT! or GPF
//
// endif
//
// endmethod
//
//
// method pushButton(var eventInfo Event)
//
// var exact, near smallint endvar
// exact = 0
// near = 0
// RecNoReturn = DbfIdxSeek(workingdir(), "test.dbf",
// "test.mdx", "sometag",
// "somevalue", exact, near, returnStringBuffer)
// if RecNoReturn > 0 then
// TableFrameName.moveToRecNo(RecNoReturn)
// else
// TableFrameName.moveToRecNo(1)
// endif
// message(returnStringBuffer) ; for errors
//
// endmethod
//
//
// method pushButton(var eventInfo Event)
//
// DbfGetIdxExpr(workingdir(), "test.dbf", "test.mdx",
// "sometag", returnStringBuffer)
// view(returnStringBuffer)
//
// endmethod
//
//=====================================================================
//=====================================================================
// Function:
// DbfIdxSeek(pCHAR pTblDir, pCHAR pTblName, pCHAR pIdxName,
// pCHAR pIdxTag, pCHAR pKeyVal, pCHAR pszRetBuffer)
//
// Description:
// This example shows how to seek for a key value in a dBASE
// maintained key expression.
//
//=====================================================================
DFLOAT FAR WINAPI _export
DbfIdxSeek (pCHAR pTblDir, pCHAR pTblName, pCHAR pIdxName,
pCHAR pIdxTag, pCHAR pKeyVal, int bExact, int bNear,
pCHAR pszRetBuffer)
{
CHAR szTblType[] = szDBASE; // table type (dBASE)
UINT16 i = 0; // for loops
UINT16 iKeyValLen = 0; // for total key bytes received
UINT16 iKeyValEven = 1; // for total used key bytes
div_t x; // for calcing total used key bytes
FMTBcd Bcd;
CURProps TblProps;
IDXDesc *pIdxDesc = NULL;
DBIResult rslt = NULL;
UINT32 retVal = 0;
hDBIDb hDb = NULL;
hDBICur hCur = NULL;
pRECProps precProps = NULL;
char *ptok = NULL;
UINT16 iFldNum = 0;
DFLOAT fKeyVal = 0;
pFLDDesc pFldDesc = NULL;
char *ptrFunc, c = '(';
UINT16 iIndexSeqNumber = 0;
pBYTE pBuf = NULL; // Pointer to the record buffer
pBYTE pKeyBuf = NULL; // Pointer to the key buffer
BOOL bIsNegative = 0;
BOOL bExpFunc = 0;
BOOL bHasNoFld = 0;
BOOL bBlank = 0;
BOOL bBlankDate = 0;
UINT16 ptr = 0;
UINT16 iFldType = 0;
DBIDATE dateD = NULL;
UINT16 uDay = NULL; // Day portion of date
UINT16 uMon = NULL; // Month portion of date
INT16 iYear = NULL; // Year portion of date
char szYear[5]; // buffer for year
char szPlaces[2] = "4";
char *szKeyBuf1 = NULL;
char *szKeyBuf2 = NULL;
char *szKeyBuf3 = NULL;
char *szKeyBuf4 = NULL;
char *szFField = NULL; // buffer for first exp. field name
UINT16 uDecLen = 0; // Decimal length
if (bExact == 1)
{
bNear = 0;
}
// initialize buffer for error string
memset(pszRetBuffer, 0, (DBIMAXMSGLEN + 1) * sizeof(char));
// do nothing if a key value is not sent
CHKERR_NODISPLAY(!strcmp(pKeyVal, ""))
iKeyValLen = strlen(&pKeyVal[0]);
if (pKeyVal[0] == '-') // for negative numbers
{
bIsNegative = TRUE;
}
precProps = ((pRECProps) malloc (sizeof(RECProps)));
if (precProps == NULL)
{
GetString(1, pszRetBuffer); //"Out of Memory."
CLEANUP_NODISPLAY;
}
// open a database in the current session and get a database handle
CHKERR_CLEANUP(DbiOpenDatabase(NULL, NULL, dbiREADONLY, dbiOPENSHARED,
NULL, 0, NULL, NULL, &hDb));
// set the current directory
CHKERR_CLEANUP(DbiSetDirectory(hDb, pTblDir));
// associate a cursor handle with an opened table
CHKERR_CLEANUP(DbiOpenTable(hDb, pTblName, NULL, pIdxName, pIdxTag,
0, dbiREADONLY, dbiOPENSHARED, xltFIELD,
FALSE, NULL, &hCur));
CHKERR_CLEANUP(DbiGetCursorProps(hCur, &TblProps));
if (strcmp(szTblType, TblProps.szTableType))
{
GetString(7, pszRetBuffer); //"Only dBASE tables are supported."
CLEANUP_NODISPLAY;
}
pFldDesc = (pFLDDesc) malloc (sizeof(FLDDesc) * TblProps.iFields);
if (pFldDesc == NULL)
{
GetString(1, pszRetBuffer); //"Out of Memory."
CLEANUP_NODISPLAY;
}
CHKERR_CLEANUP(DbiGetFieldDescs(hCur, pFldDesc));
pIdxDesc = (IDXDesc*) malloc (TblProps.iIndexes * sizeof(IDXDesc));
if (pIdxDesc == NULL)
{
GetString(1, pszRetBuffer); //"Out of Memory."
CLEANUP_NODISPLAY;
}
CHKERR_CLEANUP(DbiGetIndexDescs(hCur, pIdxDesc));
pBuf = (pBYTE) malloc (TblProps.iRecBufSize);
if (pBuf == NULL)
{
GetString(1, pszRetBuffer); //"Out of Memory."
CLEANUP_NODISPLAY;
}
CHKERR_CLEANUP(DbiInitRecord(hCur, pBuf));
CHKERR_CLEANUP(DbiGetIndexSeqNo(hCur, pIdxName, pIdxTag, NULL,
&iIndexSeqNumber));
if (pIdxDesc[iIndexSeqNumber - 1].bMaintained == 0)
{
GetString(3, pszRetBuffer); //"Only maintained indexes are supported."
CLEANUP_NODISPLAY;
}
pKeyBuf = (pBYTE) malloc((pIdxDesc[iIndexSeqNumber - 1].iKeyLen + 1) *
sizeof (BYTE));
szKeyBuf1 = (char*) malloc((pIdxDesc[iIndexSeqNumber - 1].iKeyLen + 1) *
sizeof (char));
szKeyBuf2 = (char*) malloc((pIdxDesc[iIndexSeqNumber - 1].iKeyLen + 1) *
sizeof (char));
szKeyBuf3 = (char*) malloc((pIdxDesc[iIndexSeqNumber - 1].iKeyLen + 1) *
sizeof (char));
szKeyBuf4 = (char*) malloc((pIdxDesc[iIndexSeqNumber - 1].iKeyLen + 1) *
sizeof (char));
// initialize buffer for first exp. field name
szFField = (char*) malloc((strlen(pIdxDesc[iIndexSeqNumber - 1].szKeyExp)
+ 1) * sizeof (char));
if ((szFField == NULL) ||
(pKeyBuf == NULL) ||
(szKeyBuf1 == NULL) ||
(szKeyBuf2 == NULL) ||
(szKeyBuf3 == NULL) ||
(szKeyBuf4 == NULL))
{
GetString(1, pszRetBuffer); //"Out of Memory."
CLEANUP_NODISPLAY;
}
// does the expression contain soundex
ptrFunc = strchr(pIdxDesc[iIndexSeqNumber - 1].szKeyExp, c);
if (ptrFunc)
{
ptr = strncmpi("soundex", pIdxDesc[iIndexSeqNumber - 1].szKeyExp, 7);
if (ptr == 0)
{
bExpFunc = 1;
}
// get first field name and type disregarding function
ptok = strtok(pIdxDesc[iIndexSeqNumber - 1].szKeyExp, "(");
ptok = strtok('\0', " ()-+/*");
if (ptok)
{
strcpy(szFField, ptok);
}
else
{
// has no field name in the expression
bHasNoFld = 1;
}
}
else
{
// has no function, then assuming expression has a field name
ptok = strtok(pIdxDesc[iIndexSeqNumber - 1].szKeyExp, " -+/*");
if (ptok)
{
strcpy(szFField, ptok);
}
else
{
bHasNoFld = 1;
}
}
if (bHasNoFld == 0)
{
for (i = 0; i < TblProps.iFields; i++)
{
if (!strcmp(pFldDesc[i].szName, ptok))
{
iFldType = pFldDesc[i].iFldType;
iFldNum = pFldDesc[i].iFldNum;
break;
}
}
}
if (iFldType == fldDATE)
{
// set max input to key buffer
if (iKeyValLen > pIdxDesc[iIndexSeqNumber - 1].iKeyLen + 3)
{
GetString(4, pszRetBuffer); //"Key length exceeded."
MessageBeep(-1);
CLEANUP_NODISPLAY;
}
if (pKeyVal[0] == ' ')
{
uMon = 12;
uDay = 31;
iYear = 9999;
bBlankDate = 1;
bNear = 1;
}
else
{
ptok = strtok(pKeyVal, " /");
if (ptok)
{
uMon = atoi(ptok);
}
for (i = 0; i < 2; i++)
{
ptok = strtok('\0', "/");
if ((i == 0)&&(ptok))
{
uDay = atoi(ptok);
}
if ((i == 1)&&(ptok))
{
// assumption: dates entered > 51 and <100 = 1950 otherwise
// it = 2050 unless 4 digit year is entered
if (atoi(ptok) > 50 && atoi(ptok) < 100)
{
if (atoi(ptok) > 50)
{
strcpy(szYear, "19");
strcat(szYear, ptok);
iYear = atoi(szYear);
}
else
{
strcpy(szYear, "20");
strcat(szYear, ptok);
iYear = atoi(szYear);
}
}
else
{
strcpy(szYear, ptok);
iYear = atoi(szYear);
}
}
}
}
CHKERR_CLEANUP(DbiDateEncode(uMon, uDay, iYear, &dateD));
CHKERR_CLEANUP(DbiPutField(hCur, iFldNum, pBuf, (pBYTE) &dateD));
CHKERR_CLEANUP(DbiExtractKey(hCur, pBuf, (pBYTE) pKeyBuf));
if (bNear == 1)
{
CHKERR_CLEANUP(DbiSetToKey(hCur, keySEARCHGEQ, TRUE, 0, 0,
pKeyBuf));
}
else
{
CHKERR_CLEANUP(DbiSetToKey(hCur, keySEARCHEQ, TRUE, 0, 0,
pKeyBuf));
}
CHKERR_CLEANUP(DbiGetNextRecord(hCur, dbiNOLOCK, pBuf, precProps));
CHKERR_CLEANUP(DbiGetField(hCur, iFldNum, pBuf, NULL, &bBlank));
if (bBlank)
{
// if set to near and the indate is larger than any key value,
// force an end of table (message only), otherwise a blank
// record gets found.
if (bNear == 1 && bBlankDate == 0)
{
GetString(9, pszRetBuffer); //"At end of table."
CLEANUP_NODISPLAY;
}
}
retVal = precProps[0].iPhyRecNum;
}
else
{
if (pIdxDesc[iIndexSeqNumber - 1].iKeyExpType == fldDBCHAR)
{
// set key buffer for char expression type
memset(pKeyBuf, ' ', pIdxDesc[iIndexSeqNumber - 1].
iKeyLen + 1 * sizeof (BYTE));
if (bExpFunc == 0)
{
// set max input to key buffer
if (iKeyValLen > pIdxDesc[iIndexSeqNumber - 1].iKeyLen)
{
GetString(4, pszRetBuffer); //"Key length exceeded."
MessageBeep(-1);
CLEANUP_NODISPLAY;
}
memcpy((pCHAR)pKeyBuf, pKeyVal, iKeyValLen);
if (bExact == 0 && bNear == 0)
{
CHKERR_CLEANUP(DbiGetRecordForKey(hCur, TRUE, 0,
iKeyValLen, (pBYTE)
pKeyBuf, NULL));
CHKERR_CLEANUP(DbiGetRecord(hCur, dbiNOLOCK, NULL,
precProps));
}
if (bExact == 1)
{
CHKERR_CLEANUP(DbiGetRecordForKey(hCur, TRUE, 0,
0, (pBYTE) pKeyBuf,
NULL));
CHKERR_CLEANUP(DbiGetRecord(hCur, dbiNOLOCK, NULL,
precProps));
}
if (bNear == 1)
{
CHKERR_CLEANUP(DbiSetToKey(hCur, keySEARCHGEQ, TRUE, 0,
0, pKeyBuf));
CHKERR_CLEANUP(DbiGetNextRecord(hCur, dbiNOLOCK, pBuf,
precProps));
}
}
if (bExpFunc == 1) // for soundex
{
// if first char in pKeyVal is not a letter, fail
// (because DbiGetRecordForKey won't).
if (!((pKeyVal[0] > '@') && (pKeyVal[0] < '[')) &&
!((pKeyVal[0] > '`') && (pKeyVal[0] < '{')))
{
GetString(5, pszRetBuffer); //"Invalid character."
MessageBeep(-1);
CLEANUP_NODISPLAY;
}
CHKERR_CLEANUP(DbiPutField(hCur, iFldNum, pBuf,
(pBYTE) pKeyVal));
CHKERR_CLEANUP(DbiExtractKey(hCur, pBuf, (pBYTE) pKeyBuf));
CHKERR_CLEANUP(DbiGetRecordForKey(hCur, TRUE, 0, 0,
(pBYTE) pKeyBuf, NULL));
CHKERR_CLEANUP(DbiGetRecord(hCur, dbiNOLOCK, NULL, precProps));
}
retVal = precProps[0].iPhyRecNum;
}
if (pIdxDesc[iIndexSeqNumber - 1].iKeyExpType == fldDBKEYBCD)
{
// can't start with a space
if (pKeyVal[0] == ' ')
{
CLEANUP_NODISPLAY;
}
if (strchr(&pKeyVal[0], ','))
{
GetString(6, pszRetBuffer); //"Use no commas."
MessageBeep(-1);
CLEANUP_NODISPLAY;
}
// set max for input to key buffer
if (iKeyValLen > (pIdxDesc[iIndexSeqNumber - 1].iKeyLen) + 3)
{
GetString(4, pszRetBuffer); //"Key length exceeded."
MessageBeep(-1);
CLEANUP_NODISPLAY;
}
memset(pKeyBuf, '\0', pIdxDesc[iIndexSeqNumber - 1].
iKeyLen * sizeof (BYTE));
memset(szKeyBuf1, '\0', pIdxDesc[iIndexSeqNumber - 1].
iKeyLen * sizeof (char));
// OK, now for some decimal and negative number control...
if (pKeyVal[0] == '.' || (pKeyVal[0] == '-' && pKeyVal[1] == '.'))
{
GetString(8, pszRetBuffer); //"Enter 0 or -0 first."
MessageBeep(-1);
CLEANUP_NODISPLAY;
}
ptok = strtok(pKeyVal, " .");
strcpy(szKeyBuf4, ptok);
iKeyValLen = strlen(szKeyBuf4);
if (ptok)
{
ptok = strtok(NULL, ".");
if (ptok)
{
uDecLen = strlen(&ptok[0]);
strcat(szKeyBuf4, ptok);
i = 0;
if (szKeyBuf4[0] == '0')
{
while (szKeyBuf4[i] == '0')
{
i++;
}
strcpy(szKeyBuf2, &szKeyBuf4[i]);
}
else
{
szKeyBuf2 = strdup(szKeyBuf4);
iKeyValLen = strlen(szKeyBuf2);
}
}
else
{
szKeyBuf2 = strdup(szKeyBuf4);
}
}
if (bIsNegative)
{
if (strlen(&pKeyVal[0]) > 1)
{
ptok = strtok(szKeyBuf2, " -");
strcpy(szKeyBuf3, ptok);
iKeyValLen = strlen(szKeyBuf3);
fKeyVal = atof(szKeyBuf3);
}
else
{
CLEANUP_NODISPLAY;
}
}
else
{
fKeyVal = atof(szKeyBuf2);
}
if (fKeyVal == 0)
{
CLEANUP_NODISPLAY;
}
// make total key bytes used an even number.
x = div(iKeyValLen, 2);
if (iKeyValLen > 1)
{
iKeyValEven = iKeyValLen;
}
if (x.rem == 1)
{
iKeyValEven = iKeyValLen + 1;
}
// setup first key buffer byte
szPlaces[0] = szPlaces[0] + (char)(iKeyValLen - uDecLen);
memmove(szKeyBuf1, szPlaces, 1);
// setup second key buffer byte
if (bIsNegative)
{
szPlaces[0] = (((iKeyValLen - 1) * 4) + 129);
}
else
{
szPlaces[0] = ((iKeyValLen * 4) + 1);
}
memmove(&szKeyBuf1[1], &szPlaces[0], 1);
CHKERR_CLEANUP(DbiBcdFromFloat(&fKeyVal, iKeyValLen + 2,
2, &Bcd));
if (iKeyValLen > 1)
{
iKeyValLen--;
}
for (i = 0; i < iKeyValLen; i++)
{
memmove(&szKeyBuf1[i + 2], &Bcd.iFraction[i], 1);
}
memcpy((pCHAR)pKeyBuf, szKeyBuf1, (iKeyValEven / 2) + 2);
if (bNear == 1)
{
CHKERR_CLEANUP(DbiSetToKey(hCur, keySEARCHGEQ, TRUE, 0, 0,
pKeyBuf));
}
else
{
CHKERR_CLEANUP(DbiSetToKey(hCur, keySEARCHEQ, TRUE, 0, 0,
pKeyBuf));
}
CHKERR_CLEANUP(DbiGetNextRecord(hCur, dbiNOLOCK, pBuf, precProps));
retVal = precProps[0].iPhyRecNum;
}
}
CleanUp:
if (hCur)
{
DbiCloseCursor(&hCur);
}
if (hDb)
{
DbiCloseDatabase(&hDb);
}
if (precProps)
{
free(precProps);
}
if (pBuf)
{
free(pBuf);
}
if (pKeyBuf)
{
free(pKeyBuf);
}
if (pIdxDesc)
{
free(pIdxDesc);
}
if (pFldDesc)
{
free(pFldDesc);
}
if (szKeyBuf1)
{
free(szKeyBuf1);
}
if (szKeyBuf2)
{
free(szKeyBuf2);
}
if (szKeyBuf3)
{
free(szKeyBuf3);
}
if (szKeyBuf4)
{
free(szKeyBuf4);
}
if (szFField)
{
free(szFField);
}
return retVal;
}
//=====================================================================
// Function:
// DbfGetIdxExpr(pCHAR pTblDir, pCHAR pTblName, pCHAR pIdxName,
// pCHAR pIdxTag, pCHAR pszRetBuffer)
//
// Description:
// This example shows how to return an expression string and
// other information about an MDX file.
//
//=====================================================================
void FAR WINAPI _export
DbfGetIdxExpr (pCHAR pTblDir, pCHAR pTblName, pCHAR pIdxName,
pCHAR pIdxTag, pCHAR pszRetBuffer)
{
CHAR szTblType[] = szDBASE;
DBIResult rslt;
CURProps TblProps;
UINT16 iIndexSeqNumber;
hDBIDb hDb = NULL;
hDBICur hCur = NULL;
IDXDesc *pIdxDesc = NULL;
// initialize buffer for error string
memset(pszRetBuffer, 0, (DBIMAXMSGLEN + 1) * sizeof(char));
// open a database in the current session and get a database handle
CHKERR_CLEANUP(DbiOpenDatabase(NULL, NULL, dbiREADONLY, dbiOPENSHARED,
NULL, 0, NULL, NULL, &hDb));
// set the current directory
CHKERR_CLEANUP(DbiSetDirectory(hDb, pTblDir));
// associate a cursor handle with an opened table
CHKERR_CLEANUP(DbiOpenTable(hDb, pTblName, NULL, pIdxName, pIdxTag,
0, dbiREADONLY, dbiOPENSHARED, xltFIELD,
FALSE, NULL, &hCur));
CHKERR_CLEANUP(DbiGetCursorProps(hCur, &TblProps));
if (strcmp(szTblType, TblProps.szTableType))
{
GetString(7, pszRetBuffer); //"Only dBASE tables are supported."
CLEANUP_NODISPLAY;
}
pIdxDesc = (IDXDesc*) malloc (TblProps.iIndexes * sizeof(IDXDesc));
if (pIdxDesc == NULL)
{
GetString(1, pszRetBuffer); //"Out of Memory."
CLEANUP_NODISPLAY;
}
CHKERR_CLEANUP(DbiGetIndexDescs(hCur, pIdxDesc));
CHKERR_CLEANUP(DbiGetIndexSeqNo(hCur, pIdxName, pIdxTag, NULL,
&iIndexSeqNumber));
if (pIdxDesc[iIndexSeqNumber - 1].bMaintained == 0)
{
GetString(3, pszRetBuffer); //"Only maintained indexes are supported."
CLEANUP_NODISPLAY;
}
strcpy(pszRetBuffer, pIdxDesc[iIndexSeqNumber - 1].szKeyExp);
CleanUp:
if (hCur)
{
DbiCloseCursor(&hCur);
}
if (hDb)
{
DbiCloseDatabase(&hDb);
}
if (pIdxDesc)
{
free(pIdxDesc);
}
}
//=====================================================================
// Function:
// DBIError(DBIResult retVal, pCHAR pszRetBuffer)
//
// Input:
// retVal - BDE return
// pszRetBuffer - Buffer to contain the error string
//
// Return: a DBIResult value.
//
// Description:
// This function gets information of where an error occurred.
//=====================================================================
DBIResult
DBIError (DBIResult retVal, pCHAR pszRetBuffer)
{
if (retVal == DBIERR_NONE)
{
return retVal;
}
if (retVal == DBIERR_CANTFINDODAPI)
{
GetString(2, pszRetBuffer); //"Cannot find IDAPI files: Check path."
CLEANUP_DISPLAYERR(pszRetBuffer);
}
else
{
DbiGetErrorString(retVal, pszRetBuffer);
}
CleanUp:
return retVal;
}
//=====================================================================
// Function:
// GetString(WORD iStringID, pCHAR pszRetBuffer)
//
// Input:
// iStringID - Identifier for the string
// pszRetBuffer - Buffer to contain the error string.
// (Allocated by the calling function)
//
// Description:
// Load a string from DBFSEEK.DLL.
//=====================================================================
void
GetString (WORD iStringID, pCHAR pszRetBuffer)
{
if (pszRetBuffer)
{
LoadString(GetModuleHandle(szCURRENTMODULE), iStringID, pszRetBuffer,
DBIMAXMSGLEN - 1);
}
}
#pragma argsused
BOOL WINAPI
LibMain (HINSTANCE hInstance, WORD wDataSeg,
WORD cbHeapSize, LPSTR lpCmdLine)
{
if (cbHeapSize != 0)
{
UnlockData(0);
}
return TRUE;
}
int WINAPI
WEP (int nSystemExit)
{
switch (nSystemExit)
{
case WEP_SYSTEM_EXIT:
break;
case WEP_FREE_DLL:
break;
}
return 1;
}