// 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;iFName)); 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; iszTagName); } 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(iszName); 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