Files
TeslaRel410/BORLAND/BDE/EXAMPLES/C/INVENTRY/ENGINE.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

1229 lines
42 KiB
C++

// BDE - (C) Copyright 1994 by Borland International
#include "inventry.h"
//======================================================================
// Name: DbInit()
//
// Input: None.
//
// Return: DBIERR_NONE if the engine initializes successfully.
//
// Description:
// This function starts up the engine.
//======================================================================
DBIResult
DbInit (void)
{
DBIResult rslt; // Return value from IDAPI funcions.
pCHAR pszMessage;
// Initialize the engine
CHKERR(DbiInit(NULL));
// Enable trace info if the debugging layer is enabled.
DbiDebugLayerOptions(DEBUGON | OUTPUTTOFILE, "INVENTRY.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 success of the operation
// Note that the CHKERR macro will return from this function
// if an error occurs.
return DBIERR_NONE;
}
//======================================================================
// Name: DbExit()
//
// Input: None.
//
// Return: DBIERR_NONE if the engine closes successfully.
//
// Description:
// This function shuts down the engine.
//======================================================================
DBIResult
DbExit (void)
{
// Turn off outputting trace information
DbiDebugLayerOptions(0, NULL);
// Edit IDAPI
CHKERR(DbiExit());
// Return the success of the operation
// Note that the DBIErr macro will return from this function if
// an error occurs.
return DBIERR_NONE;
}
//======================================================================
// Name: GetTable(phDb, phCur)
//
// Input: phDb - Pointer to a database handle
// phCur - Pointer to the cursor handle
//
// Return: DBIERR_NONE if the database and table open without error.
//
// Description:
// This function opens a database and a table.
//======================================================================
DBIResult
GetTable (phDBIDb phDb, phDBICur phCur)
{
// Open a standard database handle
CHKERR(DbiOpenDatabase(NULL, NULL, dbiREADWRITE, dbiOPENSHARED,
NULL, 0, NULL, NULL, phDb));
// Set the directory for the table handle
CHKERR(DbiSetDirectory(*phDb, (pCHAR)szTblDirectory));
// Open the table to acquire a cursor on the table.
CHKERR(DbiOpenTable(*phDb, (pCHAR)szTblName, (pCHAR)szTblType,
NULL, NULL, 0, dbiREADWRITE, dbiOPENSHARED,
xltFIELD, FALSE, NULL, phCur));
// Return the success of opening the table
// Note that the DBIErr macro will cause the error value
// to be returned to the calling function.
return DBIERR_NONE;
}
//======================================================================
// Name: CreateTable(phDb, phCur)
//
// Input: phDb - Pointer to the database handle
/// phCur - Pointer to the cursor handle
//
// Return: DBIERR_NONE if the database and table open without error.
//
// Description:
// This function opens a database and creates a table.
//======================================================================
DBIResult
CreateTable (phDBIDb phDb, phDBICur phCur)
{
CRTblDesc crTblDsc; // Table Descriptor
BOOL bOverWrite = TRUE; // Overwrite, yes/no flag
// Set the directory for the database handle
CHKERR(DbiOpenDatabase(NULL, NULL, dbiREADWRITE, dbiOPENSHARED,
NULL, 0, NULL, NULL, phDb));
CHKERR(DbiSetDirectory(*phDb, (pCHAR)szTblDirectory));
// Initialize the table descriptor.
memset(&crTblDsc, 0, sizeof(CRTblDesc));
strcpy(crTblDsc.szTblName, szTblName);
strcpy(crTblDsc.szTblType, szTblType);
crTblDsc.iFldCount = uNumFields;
crTblDsc.pfldDesc = fldDesc;
crTblDsc.iIdxCount = uNumIndexes;
crTblDsc.pidxDesc = idxDesc;
crTblDsc.iValChkCount = uNumVchks;
crTblDsc.pvchkDesc = VchkDesc;
// Fixup the VCHKDesc array before creating the table.
CreateVchk(uNumFields, uNumVchks, fldDesc, VchkDesc);
CHKERR(DbiCreateTable(*phDb, bOverWrite, &crTblDsc));
// Open the table to acquire a cursor to the newly created table.
CHKERR(DbiOpenTable(*phDb, (pCHAR)szTblName, (pCHAR)szTblType,
NULL, NULL, 0, dbiREADWRITE, dbiOPENSHARED,
xltFIELD, FALSE, NULL, phCur));
// Return the success of opening the table
// Note that the DBIErr macro will return from this function
// if an error occurs.
return DBIERR_NONE;
}
//======================================================================
// Name: AddRecord(hCur, *pString, Add)
//
// Input: hCur - Handle to the cursor
// pString - Pointer to a record structure
// Add - 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.
//
// Description:
// This function adds a record to the table pointed at by the
// cursor.
//======================================================================
DBIResult
AddRecord (hDBICur hCur, RecordType *pString, BOOL Add)
{
DBIResult rslt; // Return value from IDAPI functions
pBYTE pRecBuf=NULL; // Record buffer
CURProps TblProps; // Table Properties
UINT16 j=1; // Field loop counter
DATE date; // Date
INT16 ItemId; // Item Id
FLOAT In_Stock; // Items in stock
FLOAT Cost; // Cost of the item
// Get the properties of the cursor: size of the record is what is
// needed in this case.
CHKERR_CLEANUP(DbiGetCursorProps(hCur, &TblProps));
// Allocate memory for the record.
if((pRecBuf = (pBYTE) malloc(TblProps.iRecBufSize))== NULL)
{
WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
CLEANUP(DBIERR_NOMEMORY);
}
if(!Add)
{
// Get the record.
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.
ItemId = atoi(pString->ItemId);
CHKERR_CLEANUP(DbiPutField(hCur, j++, pRecBuf, (pBYTE)&ItemId));
CHKERR_CLEANUP(DbiPutField(hCur, j++, pRecBuf,
(pBYTE)pString->Building));
CHKERR_CLEANUP(DbiPutField(hCur, j++, pRecBuf, (pBYTE)pString->Item));
In_Stock = atof(pString->In_Stock);
CHKERR_CLEANUP(DbiPutField(hCur, j++, pRecBuf, (pBYTE)&In_Stock));
Cost = atof(pString->Cost);
CHKERR_CLEANUP(DbiPutField(hCur, j++, pRecBuf, (pBYTE)&Cost));
// Only write date if items are on order.
if (strcmpi(pString->DateD, szNoneOnOrder))
{
// Set the date by parsing the date string found in the record
// structure.
SetDate(&date, pString->DateD);
// Put the date into the record buffer.
CHKERR_CLEANUP(DbiPutField(hCur, j++, pRecBuf, (pBYTE)&date));
}
else
{
j++; // Increment field counter.
}
// Open the BLOb. You must open a blob before you can read or
// write a BLOb.
CHKERR_CLEANUP(DbiOpenBlob(hCur, pRecBuf, j, dbiREADWRITE));
// 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, j, 0,
(UINT32)strlen(pString->Message) + 1,
(pBYTE)pString->Message));
// If Add then insert the record.
if(Add)
{
// Insert the record.
rslt = DbiInsertRecord(hCur, dbiWRITELOCK, pRecBuf);
if(rslt == DBIERR_NONE)
{
// Release the record lock.
CHKERR_CLEANUP(DbiRelRecordLock(hCur, FALSE));
}
else
{
// Release the record 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.
DbiRelRecordLock(hCur, FALSE);
CHKERR_CLEANUP(rslt);
}
}
// NOW YOU MUST FREE the blob.
CHKERR_CLEANUP(DbiFreeBlob(hCur, pRecBuf, j));
free(pRecBuf);
// Return the success of the operation
// Note that the DBIErr macro will return from this function
// if an error occurs.
return DBIERR_NONE;
CleanUp:
if(pRecBuf)
{
free(pRecBuf);
}
DbiFreeBlob(hCur, pRecBuf, j);
return GlobalDBIErr;
}
//======================================================================
// Name: SetDate(Date, pString)
//
// Input: Date - Date to set
// pString - Date in MM/DD/YY form
//
// Return: DBIERR_NONE if the string holds a valid date..
//
// Description:
// This function puts the date that is in the pString into the
// Date variable.
//======================================================================
DBIResult
SetDate (pDATE Date, pCHAR pString)
{
UINT16 uMonth; // Month portion of the date
UINT16 uDay; // Day portion of the date
UINT16 uYear; // Year portion of the date
char cMonth[3]; // Used in formatting string
char cDay[3]; // Used in formatting string
char cYear[5]; // Used in foramtting string
// Get the first two month's numbers (the first two numbers).
strncpy(cMonth, pString, 2);
cMonth[2] = 0;
uMonth = atoi(cMonth);
// Skip the separator.
strncpy(cDay, pString + 3, 2);
cDay[2] = 0;
uDay = atoi(cDay);
// Skip second separator.
strncpy(cYear, pString + 6, 4);
uYear = atoi(cYear);
if ((uMonth != 0) && (uDay != 0) && (uYear != 0))
{
CHKERR(DbiDateEncode(uMonth, uDay, uYear, Date));
}
else
{
Date = 0;
}
// Return the success of the operation
// Note that the DBIErr macro will return from this function
// if an error occurs.
return DBIERR_NONE;
}
//======================================================================
// Name: GetData(hCur, *pRecord)
//
// Input: hCur - Handle to the cursor
// pRecord - Record buffer
//
// Return: DBIERR_NONE if the record buffer is allocated and the data
// is read successfully.
//
// Description:
// This function gets the data pointed to by hCur and puts it
// into the record structure.
//======================================================================
DBIResult
GetData (hDBICur hCur, RecordType *pRecord)
{
DBIResult rslt; // Return value from IDAPI functions
CURProps TblProps; // Properties of the table
pBYTE pRecBuf = NULL; // Buffer to contain the record
// Get the properties 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));
// Create the record buffer. The size comes from the proporty
// recsize.
if((pRecBuf = (pBYTE) malloc(TblProps.iRecBufSize))==NULL)
{
CLEANUP(DBIERR_NOMEMORY);
}
// Initialize the record buffer.
CHKERR_CLEANUP(DbiInitRecord(hCur, pRecBuf));
// Get the current reocord with a READLOCK.
rslt = DbiGetRecord(hCur, dbiREADLOCK, pRecBuf, 0);
// If there was no current rec, get the current rec.
if (rslt == DBIERR_NONE)
{
// Fill the structure with the present record pointed to by hCur.
CHKERR_NODISPLAY(FillRec(hCur, pRecBuf, pRecord));
// Now free the record lock on this record ONLY.
CHKERR_CLEANUP(DbiRelRecordLock(hCur, FALSE));
}
else
{
// Check if the table is empty.
if(!(AtBOF(hCur) && AtEOF(hCur)))
{
CHKERR_CLEANUP(rslt);
}
}
free(pRecBuf);
// Return the success of the operation
// Note that the DBIErr macro will return from this function
// if an error occurs.
return DBIERR_NONE;
CleanUp:
if(pRecBuf)
{
free(pRecBuf);
}
return GlobalDBIErr;
}
//======================================================================
// Name: FillRec(hCur, pRecBuf, *pString)
//
// Input: hCur - Handle to the cursor
// pRecBuf - Record buffer
// pString - Where to store data from the table
//
// Return: DBIERR_NONE if the database and table open without error.
//
// Description:
// This function adds a record to the table pointed at by the
// cursor.
//======================================================================
DBIResult
FillRec (hDBICur hCur, pBYTE pRecBuf, RecordType *pString)
{
UINT16 j=1; // Field counter
UINT16 uDay; // Day part of the date
UINT16 uMonth; // Month part of the date
INT16 iYear; // Year part of the date
UINT32 uActual; // Total amount read from blob
UINT32 BlobSize; // Size of blob
BOOL bEmpty; // Is field empty variable
CHAR szTemp[FLDLENGTH] =""; // Temporary variable for reading
// data
INT16 ItemId; // Item ID
FLOAT In_Stock; // Number in Stock
FLOAT Cost; // Cost of the item
// Get each field from the table and place into the data structure
CHKERR(DbiGetField(hCur, j++, pRecBuf, (pBYTE)&ItemId, &bEmpty));
sprintf(pString->ItemId, "%d", ItemId);
CHKERR(DbiGetField(hCur, j++, pRecBuf, (pBYTE)pString->Building,
&bEmpty));
CHKERR(DbiGetField(hCur, j++, pRecBuf, (pBYTE)pString->Item,
&bEmpty));
CHKERR(DbiGetField(hCur, j++, pRecBuf, (pBYTE)&In_Stock, &bEmpty));
sprintf(pString->In_Stock, "%.0lf", In_Stock);
CHKERR(DbiGetField(hCur, j++, pRecBuf, (pBYTE)&Cost, &bEmpty));
sprintf(pString->Cost, "%.2lf", Cost);
CHKERR(DbiGetField(hCur, j++, pRecBuf, (pBYTE)szTemp, &bEmpty));
// Check if any items are on order.
if ((bEmpty) || !strcmp(szTemp, ""))
{
strcpy(pString->DateD, szNoneOnOrder);
}
else
{
CHKERR(DbiDateDecode(*(DATE *)szTemp, &uMonth, &uDay, &iYear));
// Format the date to MM\DD\YYYY format.
wsprintf(pString->DateD, "%02u-%02u-%02u", uMonth, uDay, iYear);
}
CHKERR(DbiOpenBlob(hCur, pRecBuf, j, dbiREADWRITE));
// Get the size of the blob so that you can allocate the
// correct amount of memory. The BlobSize variable is a UINT32.
CHKERR(DbiGetBlobSize(hCur, pRecBuf, j, &BlobSize));
CHKERR(DbiGetBlob(hCur, pRecBuf, j, 0, BlobSize,
(pBYTE)pString->Message, &uActual));
CHKERR(DbiFreeBlob(hCur, pRecBuf, j));
// Return the success of the operation
// Note that the DBIErr macro will return from this function
// if an error occurs.
return DBIERR_NONE;
}
//======================================================================
// Name: GoBottom(hCur, MoveRec)
//
// Input: hCur - Handle to the Cursor
// MoveRec - Select last item in the table?
//
// Return: DBIERR_NONE if DbiSetToEnd is successful.
//
// Description:
// This function moves to the bottom of the table, and moves one
// record back if MoveRec (BOOL) is TRUE.
//======================================================================
DBIResult
GoBottom (hDBICur hCur, BOOL MoveRec)
{
DBIResult rslt; // Return value from IDAPI functions
rslt = CHKERR(DbiSetToEnd(hCur));
if ((MoveRec) && (rslt == DBIERR_NONE))
{
rslt = GetPrevRec(hCur);
}
return rslt;
}
//======================================================================
// Name: GoTop(hCur, MoveRec)
//
// Input: hCur - Handle to the Cursor
// MoveRec - Select the first record in the table
//
// Return: DBIERR_NONE if DbiSetToBegin is successful.
//
// Description:
// This function moves to the top of the table, and moves one
// record forward if MoveRec (BOOL) is TRUE.
//======================================================================
DBIResult
GoTop (hDBICur hCur, BOOL MoveRec)
{
DBIResult rslt; // Return value from IDAPI functions
rslt = CHKERR(DbiSetToBegin(hCur));
if ((MoveRec) && rslt == DBIERR_NONE)
{
rslt = GetNextRec(hCur);
}
return rslt;
}
//======================================================================
// Name: GetNextRec(hCur)
//
// Input: hCur - Handle to the cursor.
//
// Return: DBIERR_NONE if DbiGetNextRecord is successful.
//
// Description:
// This function moves one record forward.
//======================================================================
DBIResult
GetNextRec (hDBICur hCur)
{
DBIResult rslt;
rslt = DbiGetNextRecord(hCur, dbiNOLOCK, NULL, 0);
return rslt;
}
//======================================================================
// Name: GetPrevRec(hCur)
//
// Input: hCur - Handle to the cursor.
//
// Return: DBIERR_NONE if DbiGetPrevRec is successful.
//
// Description:
// This function moves one record backwards.
//======================================================================
DBIResult
GetPrevRec (hDBICur hCur)
{
DBIResult rslt;
rslt = DbiGetPriorRecord(hCur, dbiNOLOCK, NULL, 0);
return rslt;
}
//======================================================================
// Name: AtEOF(hCur)
//
// Input: hCur - Handle to the cursor
//
// Return: TRUE: If the cursor is at the End Of File (EOF).
// FALSE: If the cursor is not at the EOF.
//
// Description:
// 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; // Return value from IDAPI functions
BOOL RetVal; // At EOF? True/False
// Check if we are at the end of the table.
rslt = DbiGetNextRecord(hCur, dbiNOLOCK, NULL, 0);
if(rslt == DBIERR_EOF)
{
RetVal = TRUE;
}
else
{
RetVal = FALSE;
}
// Put the cursor back to where it was before entering this function.
DbiGetPriorRecord(hCur, dbiNOLOCK, NULL, 0);
return RetVal;
}
//======================================================================
// Name: AtBOF(hCur)
//
// Input: hCur - Handle to the cursor
//
// Return: TRUE: If the cursor is at the Beginning Of File (BOF).
// FALSE: If the cursor is not at the BOF.
//
// Description:
// 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; // Return value from IDAPI functions
BOOL RetVal; // At BOF? True/False
// Check if we are at the end of the table.
rslt = DbiGetPriorRecord(hCur, dbiNOLOCK, NULL, 0);
if(rslt == DBIERR_BOF)
{
RetVal = TRUE;
}
else
{
RetVal = FALSE;
}
// Put the cursor back to where it was before entering this function.
DbiGetNextRecord(hCur, dbiNOLOCK, NULL, 0);
return RetVal;
}
//======================================================================
// Name: CloseDb(phDb)
//
// Input: phDb - Pointer to the Database Handle
//
// Return: DBIERR_NONE if the table closed successfully.
//
// Description:
// This function closes the table based upon the table pointer
// that was passed into the function.
//======================================================================
DBIResult
CloseDb (phDBIDb phDb)
{
// Close the database
CHKERR(DbiCloseDatabase(phDb));
// Return the success of the operation
// Note that the DBIErr macro will return from this function
// if an error occurs.
return DBIERR_NONE;
}
//======================================================================
// Name: SetupIndex(phCur, IndexNum)
//
// Input: phCur - Pointer to the cursor handle
// IndexNum - Which index
//
// Return: DBIERR_NONE if the index descriptor memory is allocated and if
// the index switch was successful.
//
// Description:
// This function switches to an index based upon the index array
// that is used to create the table, and the IndexNum that is
// passed into the function. The IndexNum corresponds to an
// element in the array.
//======================================================================
DBIResult
SetupIndex (phDBICur phCur, UINT16 IndexNum)
{
// Switch indexes - note that Paradox tables cannot switch to the
// primary index by name, so must use the index Id, which
// is allways 0 for the primary index. The name of secondary indexes
// is used because the index Id of secondary indexes can change.
if (!IndexNum)
{
CHKERR(DbiSwitchToIndex(phCur, NULL, NULL, IndexNum,
TRUE));
}
else
{
CHKERR(DbiSwitchToIndex(phCur, idxDesc[IndexNum].szName,
NULL, TRUE, TRUE));
}
// Return the success of the operation
// Note that the DBIErr macro will return from this function
// if an error occurs.
return DBIERR_NONE;
}
//======================================================================
// Name: SetIndex(phCur, IndexNum)
//
// Input: phCur - Pointer to the cursor handle
// IndexNum - Which index
//
// Return: DBIERR_NONE if SetupIndex was successful.
//
// Description:
// This function runs SetupIndex and moves the new cursor to the
// first record in the table.
//======================================================================
DBIResult
SetIndex (phDBICur phCur, UINT16 uNum)
{
DBIResult rslt; // Return value from IDAPI functions
// Move to the top of the table and move forward one record past the
// crack.
GoTop(*phCur, TRUE);
SetupIndex(phCur, uNum);
// Again move to the first record of the table so that the first
// record is displayed when the dialog box is displayed.
rslt = GoTop(*phCur, TRUE);
return rslt;
}
//======================================================================
// Name: GetIndexNum(hCur)
//
// Input: hCur - Handle to the cursor
//
// Return: The present index number based upon the index array (UINT16).
//
// Description:
// This function returns the index number that corresponds to
// the index found in the index array (idxDesc).
//======================================================================
UINT16
GetIndexNum (hDBICur hCur)
{
UINT16 i=0;
INT16 uNum=500; // set it to a value it can never reach.
pIDXDesc MyDesc = NULL; // Index Descriptor.
if ((MyDesc = (pIDXDesc)malloc(sizeof(IDXDesc) * 1)) == NULL)
{
CLEANUP(DBIERR_NOMEMORY);
}
// Get information about the current indexe
CHKERR_CLEANUP(DbiGetIndexDesc(hCur, 0, MyDesc));
// Check if the primary index is the current index - primary index
// does not have a name.
if (MyDesc->iIndexId == 0)
{
free(MyDesc);
return 0;
}
// Loop until you found a match or until the maximum number of indexes
// that are open on this table.
while(i<uNumIndexes && (uNum!=0))
{
// Compare the current name with the names we know. If it matches
// then return that element number of the index array.
uNum=strcmp(MyDesc->szName, idxDesc[i].szName);
i++;
}
free(MyDesc);
// return the current index number.
return i-1;
CleanUp:
if(MyDesc)
{
free(MyDesc);
}
return GlobalDBIErr;
}
//======================================================================
// Name: DeleteRec(hCur)
//
// Input: hCur - Handle to the cursor
//
// Return: DBIERR_NONE if the record is successfully deleted.
//
// Description:
// This function deletes the record that is pointed to by the
// cursor.
//======================================================================
DBIResult
DeleteRec (hDBICur hCur)
{
// Lock the record before deleting.
CHKERR(DbiGetRecord(hCur, dbiWRITELOCK, NULL, 0));
// Delete the record.
CHKERR(DbiDeleteRecord(hCur, NULL));
// Return the success of the operation
// Note that the DBIErr macro will return from this function
// if an error occurs.
return DBIERR_NONE;
}
//======================================================================
// Name: SetRange(*pHighRec, *pLowRec, bHighInclude, bLowInclude,
// hCur, bHighEmpty, bLowEmpty)
//
// Input: pHighRec - Values of the high value record
// pLowRec - Values of the locw value record
// bHighInclude - Include the high value in the range
// bLowInclude - Include the low value in the range
// hCur - Handle to the cursor
// bHighEmpty - Is the high value empty
// bLowEmpty - Is the low value empty
//
// Return: DBIERR_NONE if the range is successfully set, and the memory
// is successfully allocated for the high and low record buffers.
//
// Description:
// 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. If
// either of them are FALSE we do not allocate memory for the
// record buffers that are used in the range setting. If one is
// TRUE then we allocate memory for the pRecBuf and copy the
// RecordType pointer data into it.
//======================================================================
DBIResult
SetRange (RecordType *pHighRec, RecordType *pLowRec, BOOL bHighInclude,
BOOL bLowInclude, hDBICur hCur, BOOL bHighEmpty, BOOL bLowEmpty)
{
CURProps TblProps; // Properties of the table
pBYTE pHighRecBuf = NULL; // Record containing the high value
pBYTE pLowRecBuf = NULL; // Record containing the low value
// Get the properties of the table so that we can create the correct
// buffer size for the record.
CHKERR_CLEANUP(DbiGetCursorProps(hCur,&TblProps));
if(!bHighEmpty)
{
if((pHighRecBuf = (pBYTE) malloc(TblProps.iRecBufSize))==NULL)
{
CLEANUP(DBIERR_NOMEMORY);
}
CHKERR_CLEANUP(DbiInitRecord(hCur, pHighRecBuf));
// Copy the value into the pRecBuf.
CHKERR_NODISPLAY(FillBuf(hCur, pHighRecBuf, pHighRec));
}
// Create the Low record buffer. The size comes from the property
// recsize.
if(!bLowEmpty)
{
if((pLowRecBuf = (pBYTE) malloc(TblProps.iRecBufSize))==NULL)
{
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.
if(!bLowEmpty)
{
free(pLowRecBuf);
}
if(!bHighEmpty)
{
free(pHighRecBuf);
}
// Return the success of the operation
// Note that the DBIErr macro will return from this function
// if an error occurs.
return DBIERR_NONE;
CleanUp:
if(!bLowEmpty)
{
free(pLowRecBuf);
}
if(!bHighEmpty)
{
free(pHighRecBuf);
}
return GlobalDBIErr;
}
//======================================================================
// Name: FillBuf(hCur, pRecBuf, *pString)
//
// Input: hCur - Handle to the cursor
// pRecBuf - Record buffer
// pStirng - Pointer to a Record structure
//
// Return: DBIErr_NONE if the PutFields are all successful.
//
// Description:
// 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)
{
INT16 ItemId;
double In_Stock;
double Cost;
// Fill each field with the structure's data.
ItemId = atoi(pString->ItemId);
CHKERR(DbiPutField(hCur, 1, pRecBuf, (pBYTE)&ItemId));
CHKERR(DbiPutField(hCur, 2, pRecBuf, (pBYTE)pString->Building));
CHKERR(DbiPutField(hCur, 3, pRecBuf, (pBYTE)pString->Item));
In_Stock = atof(pString->In_Stock);
CHKERR(DbiPutField(hCur, 4, pRecBuf, (pBYTE)&In_Stock));
Cost = atof(pString->Cost);
CHKERR(DbiPutField(hCur, 5, pRecBuf, (pBYTE)&Cost));
return DBIERR_NONE;
}
//======================================================================
// Name: Search(hCur, uCond, cKey)
//
// Input: hCur - Handle to the cursor
// uCond - Search condition
// cKey - Key to search for
//
// Return: DBIERR_NONE if the search is successful.
//
// Description:
// This function searches the first field of an index for the
// value passed in cKey. Note that this function only supports
// the field types: fldINT16, fldFLOAT, and fldZSTRING.
//======================================================================
DBIResult
Search (hDBICur hCur, DBISearchCond uCond, pBYTE cKey)
{
DBIResult rslt; // Return value from IDAPI functions
CURProps TblProps; // Properties of the table
IDXDesc idxDesc; // Index Descriptor.
pFLDDesc pFldDesc = NULL;// Field Descriptor
INT16 iFldNum; // Field Number
FLOAT fTemp;
INT16 iTemp;
pBYTE pRecBuf = NULL;
// Get information about the current index.
CHKERR_CLEANUP(DbiGetIndexDesc(hCur, 0, &idxDesc));
// Determine the first field of the Index.
iFldNum = idxDesc.aiKeyFld[0];
// Get information about the cursor - needed to determine the number
// of fields in the table.
CHKERR_CLEANUP(DbiGetCursorProps(hCur, &TblProps));
// Allocate a Field descriptior large enough to contain information
// about all fields in the table.
if((pFldDesc = (pFLDDesc) malloc(sizeof(FLDDesc) * TblProps.iFields))
== NULL)
{
WinMsg("Out of memory!", MB_ICONHAND, MB_OK);
CLEANUP(DBIERR_NOMEMORY);
}
// Get the field descriptors - needed to determine the type of the
// first field of the index.
CHKERR_CLEANUP(DbiGetFieldDescs(hCur, pFldDesc));
// Create the key buffer. The size comes from the proporty recsize.
if((pRecBuf = (pBYTE) malloc(TblProps.iRecBufSize))==NULL)
{
WinMsg("Out of memory!", MB_ICONHAND, MB_OK);
CLEANUP(DBIERR_NOMEMORY);
}
// Initialize the record buffer.
CHKERR_CLEANUP(DbiInitRecord(hCur, pRecBuf));
// Write the data to the record buffer.
switch(pFldDesc[iFldNum - 1].iFldType)
{
case fldINT16:
iTemp = atoi((pCHAR)cKey);
CHKERR_CLEANUP(DbiPutField(hCur, iFldNum, pRecBuf,
(pBYTE)&iTemp));
break;
case fldFLOAT:
fTemp = atof((pCHAR)cKey);
CHKERR_CLEANUP(DbiPutField(hCur, iFldNum, pRecBuf,
(pBYTE)&fTemp));
break;
case fldZSTRING:
CHKERR_CLEANUP(DbiPutField(hCur, iFldNum, pRecBuf,
(pBYTE)cKey));
break;
default:
WinMsg("Operation currently not supported", MB_ICONHAND, MB_OK);
CLEANUP(DBIERR_NOTSUPPORTED);
}
// Perform the actual search on the table.
rslt = DbiSetToKey(hCur, uCond, FALSE, 0, 0, pRecBuf);
// Display an error message if an error other than Record not Found
// is detected.
if ((rslt != DBIERR_NONE) && (rslt != DBIERR_RECNOTFOUND))
{
CHKERR_CLEANUP(rslt);
}
else
{
// If keySEARCHEQ was NOT used then there will be no error.
// Therefore we need to check if there was an error. If we
// are at the end of the table then there was no record found.
if(AtEOF(hCur))
{
rslt = DBIERR_RECNOTFOUND;
}
}
free(pRecBuf);
free(pFldDesc);
return rslt;
CleanUp:
if(pRecBuf)
{
free(pRecBuf);
}
if(pFldDesc)
{
free(pFldDesc);
}
return GlobalDBIErr;
}
//======================================================================
// Name: ResetRange(hCur)
//
// Input: hCur - Handle to the cursor
//
// Return: DBIERR_NONE if the range is successfully reset.
//
// Description:
// This function clears any range settings. The outcome is that
// all records will be visable to the user.
//======================================================================
DBIResult
ResetRange (hDBICur hCur)
{
// Reset the range - all records
CHKERR(DbiResetRange(hCur));
// Return the success of the operation
// Note that the DBIErr macro will return from this function
// if an error occurs.
return DBIERR_NONE;
}
//======================================================================
// Name: DateEncode(mon, day, year, pTempDate)
//
// Input: mon - Month
// day - Day
// year - Year
// pTempDate - Pointer to the DATE variable that is to be
// encoded
//
// Return: DBIERR_NONE if the date is successfully encoded.
//
// Description:
// This function takes in the date, month, and year and encodes
// them into the DATE pointer with the DateEncode function.
//======================================================================
DBIResult
DateEncode (UINT16 mon, UINT16 day, UINT16 year, pDATE pTempDate)
{
DBIResult rslt; // Return value from IDAPI functions
// Check the result of the date encode and return it.
rslt = DbiDateEncode(mon, day, year, pTempDate);
return rslt;
}
//=====================================================================
// Code: CreateVchk(uNumFields, uNumVchks, fldDesc, VchkDesc);
//
// Input: uNumFields - Number of fields
// uNumVchks - Number of validity checks
// fldDesc - Field descriptor
// VchkDesc - Validity descriptor
//
// Return: None. However, the VchkDesc is modified.
//
// Description:
// This function will take in a Validity Check structure and
// change the number fields so that they are compatible with
// the manner in which IDAPI wants to see them.
//=====================================================================
void
CreateVchk (UINT16 uNumFields, UINT16 uNumVchks, pFLDDesc fldDesc,
pVCHKDesc VchkDesc)
{
UINT16 i=0; // Used for iteration purposes.
UINT16 j=0; // Used for iteration purposes.
INT16 iNumber; // Used to hold the number to be put
// into the VC.
BOOL bFlag = FALSE; // Used inside of VC loop.
// Loop through all the fields and check if it has a VC associated to
// it. If it does then check if the field is a INT16 - if it is convert
// the VC values that are not NULL to numbers that IDAPI wants to see.
for(i=0; i<uNumFields; i++)
{
// Check if the field is an INT16 field and then check if it has a
// Validity Check associated with it.
if(fldDesc[i].iFldType == fldINT16)
{
// Reset the variables for each iteration.
j=0;
bFlag = FALSE;
while(j<uNumVchks && !bFlag)
{
// Check if the current field (i+1) has a VC associated
// with it.
if(VchkDesc[j].iFldNum == (i+1))
{
// Since we found a VC associated with the field - set
// the BOOL variable to TRUE - so that we get out of
// the loop.
bFlag = TRUE;
// If the VC Structure has a MinVal for this field
// then convert it.
if(VchkDesc[j].bHasMinVal)
{
// Get the number that you want to use.
iNumber = atoi((pCHAR)VchkDesc[j].aMinVal);
// Clear the string so that we can change it.
memset(VchkDesc[j].aMinVal, '\0',
strlen((pCHAR)VchkDesc[j].aMinVal));
// Set the new value into the structure.
memmove(VchkDesc[j].aMinVal, &iNumber, 2);
}
// If the VC Structure has a MaxVal for this field
// then convert it.
if(VchkDesc[j].bHasMaxVal)
{
// Get the number that you want to use.
iNumber = atoi((pCHAR)VchkDesc[j].aMaxVal);
// Clear the string so that we can change it.
memset(VchkDesc[j].aMaxVal, '\0',
strlen((pCHAR)VchkDesc[j].aMaxVal));
// Set the new value into the structure.
memmove(VchkDesc[j].aMaxVal, &iNumber, 2);
}
// If the VC Structure has a DefVal for this field
// then convert it.
if(VchkDesc[j].bHasDefVal)
{
// Get the number that you want to use.
iNumber = atoi((pCHAR)VchkDesc[j].aDefVal);
// Clear the string so that we can change it.
memset(VchkDesc[j].aDefVal, '\0',
strlen((pCHAR)VchkDesc[j].aDefVal));
// Set the new value into the structure.
memmove(VchkDesc[j].aDefVal, &iNumber, 2);
}
} // Close of the if(VC)
// Increment j so that we can go through the VC array.
j++;
} // Close of the while loop
} // Close of the if (number field)
} // Close of for loop
}