// 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(iszName, 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