home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / BC_502 / 32ADDRES.PAK / ENGINE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  63.1 KB  |  2,017 lines

  1. // BDE32 3.x - (C) Copyright 1996 by Borland International
  2.  
  3. #include "address.h"
  4.  
  5. //======================================================================
  6. //  Name:   DbInit()
  7. //
  8. //  Input:  None.
  9. //
  10. //  Return: DBIERR_NONE if the engine initializes successfully.
  11. //
  12. //  Desc:   This function starts up the engine.
  13. //======================================================================
  14. DBIResult
  15. DbInit (void)
  16. {
  17.     DBIResult   rslt;   // Return value from IDAPI functions
  18.     pCHAR       pszMessage;
  19.     
  20.     CHKERR(DbiInit(NULL));
  21.     
  22.     DbiDebugLayerOptions(DEBUGON | OUTPUTTOFILE, "ADDRESS.INF");
  23.  
  24.     rslt = DbiSetPrivateDir(szPrivDirectory);
  25.     if (rslt == DBIERR_DIRBUSY)
  26.     {
  27.         pszMessage = (pCHAR)malloc(((DBIMAXMSGLEN * 3) + 1) * sizeof(char));
  28.         if (pszMessage)
  29.         {
  30.             sprintf(pszMessage, "Directory is busy. Make certain no .LCK"
  31.                     " files exist in the %s directory and that the IDAPI"
  32.                     " DLLs are unloaded (Reboot Windows).",
  33.                     szPrivDirectory);
  34.             WinMsg(pszMessage, MB_ICONHAND, MB_OK);
  35.             free(pszMessage);
  36.         }
  37.         return rslt;
  38.     }
  39.  
  40.     CHKERR(rslt);
  41.  
  42.     return DBIERR_NONE;
  43. }
  44.  
  45. //======================================================================
  46. //  Name:   DbExit()
  47. //
  48. //  Input:  None.
  49. //
  50. //  Return: DBIERR_NONE if the engine closes successfully.
  51. //
  52. //  Desc:   This function shuts down the engine.
  53. //======================================================================
  54. DBIResult
  55. DbExit (void)
  56. {
  57.     DbiDebugLayerOptions(0, NULL);
  58.     CHKERR(DbiExit());
  59.     return DBIERR_NONE;
  60. }
  61.  
  62. //======================================================================
  63. //  Name:   GetTable()
  64. //
  65. //  Input:  Pointer to the database (phDBIDb), and a pointer to the
  66. //          cursor (phDBICur).
  67. //
  68. //  Return: DBIERR_NONE if the table opens without error.
  69. //
  70. //  Desc:   This function opens a table.
  71. //======================================================================
  72. DBIResult
  73. GetTable (hDBIDb hDb, phDBICur phCur)
  74. {
  75.     CURProps    TblProps;
  76.     UINT16      iLen;    
  77.     DBIResult   rslt;
  78.  
  79.     if(!bIsServer)
  80.     {
  81.         // Set the directory for the table handle
  82.         CHKERR(DbiSetDirectory(hDb, (pCHAR)szTblDirectory));
  83.     }
  84.  
  85.     CHKERR(DbiGetProp((hDBIObj)hDb, dbDATABASETYPE, (pCHAR)szTblType,
  86.                        sizeof(DBINAME), &iLen));
  87.  
  88.     // Open the table to acquire a cursor on the table.
  89.     HourGlassCursor(TRUE);
  90.     rslt = DbiOpenTable(hDb, (pCHAR)szTblName, NULL,
  91.                          NULL, NULL, 0, dbiREADWRITE, dbiOPENSHARED,
  92.                          xltFIELD, FALSE, NULL, phCur);
  93.     HourGlassCursor(FALSE);
  94.     CHKERR(rslt);
  95.  
  96.     // Get the cursor properties for the Addressbook table.
  97.     rslt = DbiGetCursorProps(*phCur, &TblProps);
  98.     if(rslt!=DBIERR_NONE)
  99.     {
  100.         DbiCloseCursor(phCur);
  101.         CHKERR(rslt);
  102.     }
  103.  
  104.     strcpy((pCHAR)szTblType, TblProps.szTableType);
  105.  
  106.     return DBIERR_NONE;
  107. }
  108.  
  109. //======================================================================
  110. //  Name:   CreateTable()
  111. //
  112. //  Input:  Handle to the database (hDBIDb), pointer to the cursor
  113. //          (phDBICur), and the type of AddressBook (pCHAR).
  114. //
  115. //  Return: DBIERR_NONE if the table is created without error.
  116. //
  117. //  Desc:   This function creates a table for the given database.
  118. //======================================================================
  119. DBIResult
  120. CreateTable (hDBIDb hDb, phDBICur phCur, pCHAR pszABType)
  121. {
  122.     DBIResult   rslt;
  123.     CRTblDesc   crTblDsc;
  124.     BOOL        bOverWrite = TRUE;
  125.     UINT16      iLen;               
  126.     UINT16      i;
  127.  
  128.     if(!bIsServer)
  129.     {
  130.         // Set the directory for the table handle
  131.         CHKERR(DbiSetDirectory(hDb, (pCHAR)szTblDirectory));
  132.     }
  133.  
  134.     memset(&crTblDsc, 0, sizeof(CRTblDesc));
  135.  
  136.     // Set the name and the type of the table
  137.     strcpy(crTblDsc.szTblName, szTblName);
  138.  
  139.     strcpy(crTblDsc.szTblType, szTblType);
  140.  
  141.     // Check the AddressBook type.
  142.     if(strcmpi(pszABType, szPERSONAL)==0)
  143.     {
  144.         // Set the table to hold personal data
  145.         strcpy(fldDesc[2].szName, "Spouse");
  146.         strcpy(fldDesc[8].szName, "Work_No");
  147.         strcpy(fldDesc[9].szName, "Home_No");
  148.     }
  149.     else
  150.     {
  151.         // Set the table to hold business data
  152.         strcpy(fldDesc[2].szName, "Business");
  153.         strcpy(fldDesc[8].szName, "Phone1");
  154.         strcpy(fldDesc[9].szName, "Fax");
  155.     }
  156.     crTblDsc.iFldCount = uNumFields;
  157.     crTblDsc.pfldDesc = fldDesc;
  158.     
  159.     // Set the index information for the table
  160.     if(bIsServer)
  161.     {
  162.         idxIBPDDesc[0].bPrimary = FALSE;
  163.  
  164.         for(i=0;i<uNumIndexes;i++)
  165.         {
  166.             idxIBPDDesc[i].bUnique = TRUE;
  167.         }
  168.  
  169.         crTblDsc.pidxDesc = idxIBPDDesc;
  170.  
  171.         // Get the database type.
  172.         CHKERR(DbiGetProp((hDBIObj)hDb, dbDATABASETYPE, (pCHAR)szTblType,
  173.                            sizeof(DBINAME), &iLen));
  174.  
  175.         strcpy(crTblDsc.szTblType, szTblType);
  176.     }
  177.     else
  178.     {
  179.         if(strcmpi(szTblType, szPARADOX)==0)
  180.         {
  181.             crTblDsc.pidxDesc = idxIBPDDesc;
  182.             idxIBPDDesc[0].bPrimary = TRUE;
  183.         }
  184.         else
  185.         {
  186.             if(strcmpi(szTblType, szDBASE)==0)
  187.             {
  188.                 crTblDsc.pidxDesc = idxDBDesc;
  189.             }
  190.             else
  191.             {
  192.                 WinMsg("Unsupported Table type!", MB_ICONHAND, MB_OK);
  193.             }
  194.  
  195.         }
  196.     }
  197.     crTblDsc.iIdxCount = uNumIndexes;
  198.  
  199.     // Create the table using information supplied in the Table
  200.     // Descrpitor above.
  201.     HourGlassCursor(TRUE);
  202.     rslt = DbiCreateTable(hDb, bOverWrite, &crTblDsc);
  203.     HourGlassCursor(FALSE);
  204.     CHKERR(rslt);
  205.  
  206.     // Open the table to acquire a cursor to the newly created table.
  207.     HourGlassCursor(TRUE);
  208.     rslt = DbiOpenTable(hDb, (pCHAR)szTblName, (pCHAR)szTblType,
  209.                         NULL, NULL, 0, dbiREADWRITE, dbiOPENSHARED,
  210.                         xltFIELD, FALSE, NULL, phCur);
  211.     HourGlassCursor(FALSE);
  212.     CHKERR(rslt);
  213.  
  214.     return rslt;
  215. }
  216.  
  217. //======================================================================
  218. //  Name:   AddRecord()
  219. //
  220. //  Input:  Handle to the cursor (hDBICur), pointer to a record structure
  221. //          (RecordType *), and a Boolean - if TRUE: the record is inserted.
  222. //          If FALSE: the record pointed to by the cursor is overwritten
  223. //          by the data in the record structure.
  224. //
  225. //  Return: DBIERR_NONE if the record was inserted or overwritten
  226. //          successfully.
  227. //
  228. //  Desc:   This function adds a record to the table pointed at by the
  229. //          cursor.
  230. //======================================================================
  231. DBIResult
  232. AddRecord (hDBICur hCur, RecordType *pString, BOOL bAdd)
  233. {
  234.     pBYTE       pRecBuf=NULL;
  235.     CURProps    TblProps;           
  236.     DBIDATE     Date;
  237.     TIME        Time;
  238.     TIMESTAMP   TimeStamp;
  239.     pFLDDesc    pFields;
  240.     DBIResult   rslt;
  241.  
  242.     // Get all the field descriptors.
  243.     if ((pFields = (pFLDDesc)malloc(sizeof(FLDDesc) * uNumFields)) == NULL)
  244.     {
  245.         WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
  246.         CLEANUP(DBIERR_NOMEMORY);
  247.     }
  248.  
  249.     // Get the field descriptors.
  250.     CHKERR_CLEANUP(DbiGetFieldDescs(hCur, pFields));
  251.  
  252.     // Get the cursor properties for the Addressbook table.
  253.     CHKERR_CLEANUP(DbiGetCursorProps(hCur, &TblProps));
  254.  
  255.     // Get a record buffer for the Addressbook table.
  256.     if((pRecBuf = (pBYTE) malloc(TblProps.iRecBufSize))== NULL)
  257.     {
  258.         WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
  259.         CLEANUP(DBIERR_NOMEMORY);
  260.     }
  261.  
  262.     if(!bAdd)
  263.     {
  264.         CHKERR_CLEANUP(DbiGetRecord(hCur, dbiWRITELOCK, pRecBuf, NULL));
  265.     }
  266.     else
  267.     {
  268.         //  Make sure we're starting with a clean record buffer
  269.         CHKERR_CLEANUP(DbiInitRecord(hCur, pRecBuf));
  270.     }
  271.  
  272.     // Fill each field with the structure's data
  273.     CHKERR_CLEANUP(DbiPutField(hCur, 1, pRecBuf, (pBYTE)pString->FName));
  274.     CHKERR_CLEANUP(DbiPutField(hCur, 2, pRecBuf, (pBYTE)pString->LName));
  275.     CHKERR_CLEANUP(DbiPutField(hCur, 3, pRecBuf, (pBYTE)pString->Spouse));
  276.     CHKERR_CLEANUP(DbiPutField(hCur, 4, pRecBuf, (pBYTE)pString->Addrs1));
  277.     CHKERR_CLEANUP(DbiPutField(hCur, 5, pRecBuf, (pBYTE)pString->Addrs2));
  278.     CHKERR_CLEANUP(DbiPutField(hCur, 6, pRecBuf, (pBYTE)pString->City));
  279.     CHKERR_CLEANUP(DbiPutField(hCur, 7, pRecBuf, (pBYTE)pString->State));
  280.     CHKERR_CLEANUP(DbiPutField(hCur, 8, pRecBuf, (pBYTE)pString->Zip));
  281.     CHKERR_CLEANUP(DbiPutField(hCur, 9, pRecBuf, (pBYTE)pString->Phone1));
  282.     CHKERR_CLEANUP(DbiPutField(hCur, 10, pRecBuf, (pBYTE)pString->Phone2));
  283.  
  284.     // Set the date by parsing the date string found in the record
  285.     // structure.
  286.     SetDate(&Date, pString->Date1);
  287.  
  288.     // Check if the date field is really a timestamp field
  289.     if(pFields[10].iFldType == fldTIMESTAMP)
  290.     {
  291.         memset(&Time, '\0', sizeof(TIME));
  292.         CHKERR_CLEANUP(DbiTimeStampEncode(Date, Time, &TimeStamp));
  293.  
  294.         // Put the Timestamp into the record buffer.
  295.         CHKERR_CLEANUP(DbiPutField(hCur, 11, pRecBuf, (pBYTE)&TimeStamp));
  296.     }
  297.     else
  298.     {
  299.         // Put the date into the record buffer.
  300.         CHKERR_CLEANUP(DbiPutField(hCur, 11, pRecBuf, (pBYTE)&Date));
  301.     }
  302.  
  303.     // Now open the BLOb.  You must open a blob before you can read or
  304.     // write a BLOb.
  305.     CHKERR_CLEANUP(DbiOpenBlob(hCur, pRecBuf, 12, dbiREADWRITE));
  306.  
  307.     // Now put the BLOb into the record buffer.  We need to add one for
  308.     // the NULL termination used in the string.
  309.     CHKERR_CLEANUP(DbiPutBlob(hCur, pRecBuf, 12, 0L,
  310.                               strlen(pString->Comment) + 1,
  311.                               (pBYTE)pString->Comment));
  312.  
  313.     // If Add then insert the record.
  314.     if(bAdd)
  315.     {
  316.         // Insert the record.
  317.         rslt = DbiInsertRecord(hCur, dbiWRITELOCK, pRecBuf);
  318.         if(rslt == DBIERR_NONE)
  319.         {
  320.             // Release the record lock.  The record is not released unless
  321.             // you close the table or release the lock.
  322.             CHKERR_CLEANUP(DbiRelRecordLock(hCur, FALSE));
  323.         }
  324.         else
  325.         {
  326.             // Release the record lock.  The record is not released unless
  327.             // you close the table or release the lock.
  328.             DbiRelRecordLock(hCur, FALSE);
  329.             if (rslt == DBIERR_KEYVIOL)
  330.             {
  331.                 WinMsg("Cannot add a duplicate record", MB_ICONHAND, MB_OK);
  332.                 CLEANUP(rslt);
  333.             }
  334.             CHKERR_CLEANUP(rslt);
  335.         }
  336.     }
  337.  
  338.     // Otherwise we are going to overwrite the record.
  339.     else
  340.     {
  341.         // Overwrite the record, and release the lock once we have
  342.         // modified the record.
  343.         rslt = DbiModifyRecord(hCur, pRecBuf, TRUE);
  344.         if(rslt != DBIERR_NONE)
  345.         {
  346.             // Release the record lock.  The record is not released unless
  347.             //   you close the table or release the lock.
  348.             DbiRelRecordLock(hCur, FALSE);
  349.             CHKERR_CLEANUP(rslt);
  350.         }
  351.     }
  352.  
  353.     // YOU MUST FREE the blob.
  354.     CHKERR_CLEANUP(DbiFreeBlob(hCur, pRecBuf, 0));
  355.     free(pRecBuf);
  356.     free(pFields);
  357.     return DBIERR_NONE;
  358.  
  359. CleanUp:
  360.     if(pFields)
  361.     {
  362.         free(pFields);
  363.     }
  364.     if(pRecBuf)
  365.     {
  366.         free(pRecBuf);
  367.         DbiFreeBlob(hCur, pRecBuf, 0);
  368.     }
  369.     return GlobalDBIErr;
  370. }
  371.  
  372. //======================================================================
  373. //  Name:   SetDate()
  374. //
  375. //  Input:  Pointer to a DBIDATE variable, and a pointer to a string (pCHAR).
  376. //
  377. //  Return: DBIERR_NONE if the string holds a valid date..
  378. //
  379. //  Desc:   This function puts the date that is in the pString into the
  380. //          Date variable.
  381. //======================================================================
  382. DBIResult
  383. SetDate (pDBIDATE Date, pCHAR pszString)
  384. {
  385.     UINT16      iMonth;
  386.     UINT16      iDay;
  387.     UINT16      iYear;
  388.     UINT16      iSepLen;
  389.     CHAR        szMonth[3] = {0};
  390.     CHAR        szDay[3] = {0};
  391.     CHAR        szYear[5] = {0};
  392.     FMTDate     FmtDate;
  393.  
  394.     AdrGetDateFormat(&FmtDate);
  395.     iSepLen = (UINT16)strlen(FmtDate.szDateSeparator);
  396.  
  397.     // Get the first two month's numbers (the first two numbers).
  398.     strncpy(szMonth, pszString, 2);
  399.     iMonth = (UINT16)atoi(szMonth);
  400.  
  401.     // Skip the separator.
  402.     strncpy(szDay, pszString + 2 + iSepLen, 2);
  403.     iDay = (UINT16)atoi(szDay);
  404.  
  405.     // Skip second separator.
  406.     strncpy(szYear, pszString + 4 + (2*iSepLen), 4);
  407.     iYear = (UINT16)atoi(szYear);
  408.  
  409.     CHKERR(DbiDateEncode(iMonth, iDay, iYear, Date));
  410.     return DBIERR_NONE;
  411. }
  412.  
  413. //======================================================================
  414. //  Name:   GetData()
  415. //
  416. //  Input:  Handle to the cursor (hDBICur), pointer to a record structure
  417. //          (RecordType*).
  418. //
  419. //  Return: DBIERR_NONE if the record buffer is allocated and the data
  420. //          is read successfully.
  421. //
  422. //  Desc:   This function gets the data pointed to by hCur and puts it
  423. //          into the record structure.
  424. //======================================================================
  425. DBIResult
  426. GetData (hDBICur hCur, RecordType* pRecord)
  427. {
  428.     CURProps    TblProps;
  429.     pBYTE       pRecBuf = NULL;
  430.     DBIResult   rslt;
  431.  
  432.     // Get the proporties of the table so that we can create the correct
  433.     // buffer size for the record.  We will read the record into the buffer
  434.     // and then we will pull the field from the buffer.
  435.     CHKERR_CLEANUP(DbiGetCursorProps(hCur,&TblProps));
  436.  
  437.     if((pRecBuf = (pBYTE) malloc(TblProps.iRecBufSize))==NULL)
  438.     {
  439.         WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
  440.         CLEANUP(DBIERR_NOMEMORY);
  441.     }
  442.  
  443.     // Initialize the record buffer.
  444.     CHKERR_CLEANUP(DbiInitRecord(hCur, pRecBuf));
  445.  
  446.     rslt = DbiGetRecord(hCur, dbiREADLOCK, pRecBuf, 0);
  447.  
  448.     if(rslt == DBIERR_NONE)
  449.     {
  450.         CHKERR_NODISPLAY(FillRec(hCur, pRecBuf, pRecord));
  451.         CHKERR_CLEANUP(DbiRelRecordLock(hCur, FALSE));
  452.     }
  453.     else
  454.     {
  455.         // Check if the table is empty and that is why you got an error.
  456.         if(!(AtBOF(hCur) && AtEOF(hCur)))
  457.         {
  458.             CHKERR_CLEANUP(rslt);
  459.         }
  460.     }
  461.  
  462.     free(pRecBuf);
  463.  
  464.     return DBIERR_NONE;
  465.  
  466. CleanUp:
  467.     if(pRecBuf)
  468.     {
  469.         free(pRecBuf);
  470.     }
  471.     return GlobalDBIErr;
  472. }
  473.  
  474. //======================================================================
  475. //  Name:   FillRec()
  476. //
  477. //  Input:  Handle to the cursor (hDBICur), pointer to a record
  478. //          buffer (pBYTE), and a record structure pointer (RecordType *).
  479. //
  480. //  Return: DBIERR_NONE if the record structure is filled successfully.
  481. //
  482. //  Desc:   This function adds a record to the table pointed at by the
  483. //          cursor.
  484. //======================================================================
  485. DBIResult
  486. FillRec (hDBICur hCur, pBYTE pRecBuf, RecordType* pString)
  487. {
  488.     UINT16      iDay;
  489.     UINT16      iMonth;
  490.     INT16       iYear;
  491.     UINT32      lActualSize;
  492.     UINT32      lBlobSize;
  493.     CHAR        szTemp[30] ="";
  494.     DBIDATE     Date;
  495.     TIME        Time;
  496.     FMTDate     FmtDate;
  497.     BOOL        bEmpty;
  498.     pFLDDesc    pFields;
  499.  
  500.     if ((pFields = (pFLDDesc)malloc(sizeof(FLDDesc) * uNumFields)) == NULL)
  501.     {
  502.         WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
  503.         CLEANUP(DBIERR_NOMEMORY);
  504.     }
  505.  
  506.     CHKERR_CLEANUP(DbiGetFieldDescs(hCur, pFields));
  507.     CHKERR_NODISPLAY(AdrGetDateFormat(&FmtDate));
  508.  
  509.     // Put each field into the data structure
  510.     CHKERR_CLEANUP(DbiGetField(hCur, 1, pRecBuf, (pBYTE)pString->FName,
  511.                    &bEmpty));
  512.     CHKERR_CLEANUP(DbiGetField(hCur, 2, pRecBuf, (pBYTE)pString->LName,
  513.                    &bEmpty));
  514.     CHKERR_CLEANUP(DbiGetField(hCur, 3, pRecBuf, (pBYTE)pString->Spouse,
  515.                    &bEmpty));
  516.     CHKERR_CLEANUP(DbiGetField(hCur, 4, pRecBuf, (pBYTE)pString->Addrs1,
  517.                    &bEmpty));
  518.     CHKERR_CLEANUP(DbiGetField(hCur, 5, pRecBuf, (pBYTE)pString->Addrs2,
  519.                    &bEmpty));
  520.     CHKERR_CLEANUP(DbiGetField(hCur, 6, pRecBuf, (pBYTE)pString->City,
  521.                    &bEmpty));
  522.     CHKERR_CLEANUP(DbiGetField(hCur, 7, pRecBuf, (pBYTE)pString->State,
  523.                    &bEmpty));
  524.     CHKERR_CLEANUP(DbiGetField(hCur, 8, pRecBuf, (pBYTE)pString->Zip,
  525.                    &bEmpty));
  526.     CHKERR_CLEANUP(DbiGetField(hCur, 9, pRecBuf, (pBYTE)pString->Phone1,
  527.                    &bEmpty));
  528.     CHKERR_CLEANUP(DbiGetField(hCur, 10, pRecBuf, (pBYTE)pString->Phone2,
  529.                    &bEmpty));
  530.     CHKERR_CLEANUP(DbiGetField(hCur, 11, pRecBuf, (pBYTE)szTemp, &bEmpty));
  531.  
  532.     // Check if the date field is really a timestamp field
  533.     if(pFields[10].iFldType == fldTIMESTAMP)
  534.     {
  535.         CHKERR_CLEANUP(DbiTimeStampDecode(*(pTIMESTAMP)szTemp, &Date,
  536.                                           &Time));
  537.         CHKERR_CLEANUP(DbiDateDecode(Date, &iMonth, &iDay, &iYear));
  538.     }
  539.     else
  540.     {
  541.         CHKERR_CLEANUP(DbiDateDecode(*(pDBIDATE)szTemp, &iMonth, &iDay,
  542.                                      &iYear));
  543.     }
  544.  
  545.     // Format the date to whatever the date separator is.
  546.     wsprintf(pString->Date1, "%02d%s%02d%s%02d", iMonth,
  547.              FmtDate.szDateSeparator, iDay, FmtDate.szDateSeparator,
  548.              iYear);
  549.  
  550.     CHKERR_CLEANUP(DbiOpenBlob(hCur, pRecBuf, 12, dbiREADWRITE));
  551.  
  552.     // Get the size of the blob so that we can get the whole blob.
  553.     CHKERR_CLEANUP(DbiGetBlobSize(hCur, pRecBuf, 12, &lBlobSize));
  554.  
  555.     // Check to make sure that the buffer is large enough to hold the blob.
  556.     if(lBlobSize >= COMMENTLEN)
  557.     {
  558.         lBlobSize = COMMENTLEN - 1;
  559.     }
  560.  
  561.     CHKERR_CLEANUP(DbiGetBlob(hCur, pRecBuf, 12, 0L, lBlobSize,
  562.                      (pBYTE)pString->Comment, &lActualSize));
  563.  
  564.     CHKERR_CLEANUP(DbiFreeBlob(hCur, pRecBuf, 12));
  565.  
  566.     free(pFields);
  567.     return DBIERR_NONE;
  568.  
  569. CleanUp:
  570.     if(pFields)
  571.     {
  572.         free(pFields);
  573.     }
  574.     return GlobalDBIErr;
  575. }
  576.  
  577. //======================================================================
  578. //  Name:   GoBottom()
  579. //
  580. //  Input:  Handle to the cursor (hDBICur), Move a record prior Bool (BOOL).
  581. //
  582. //  Return: DBIERR_NONE if DbiSetToEnd is successful.
  583. //
  584. //  Desc:   This function moves to the bottom of the table, and moves one
  585. //          record back if MoveRec (BOOL) is TRUE.
  586. //======================================================================
  587. DBIResult
  588. GoBottom (hDBICur hCur, BOOL bMoveRec)
  589. {
  590.     CHKERR(DbiSetToEnd(hCur));
  591.     if(bMoveRec)
  592.     {
  593.         GetPrevRec(hCur);
  594.     }
  595.     return DBIERR_NONE;
  596. }
  597.  
  598. //======================================================================
  599. //  Name:   GoTop()
  600. //
  601. //  Input:  Handle to the cursor (hDBICur), Move a record forward Bool
  602. //          (BOOL).
  603. //
  604. //  Return: DBIERR_NONE if DbiSetToBegin is successful.
  605. //
  606. //  Desc:   This function moves to the top of the table, and moves one
  607. //          record forward if MoveRec (BOOL) is TRUE.
  608. //======================================================================
  609. DBIResult
  610. GoTop (hDBICur hCur, BOOL bMoveRec)
  611. {
  612.     DBIResult   rslt;       // Return value from IDAPI functions
  613.     CHKERR(DbiSetToBegin(hCur));
  614.     if(bMoveRec)
  615.     {
  616.         rslt = GetNextRec(hCur);
  617.         if (rslt != DBIERR_EOF)
  618.         {
  619.             CHKERR(rslt);
  620.         }
  621.     }
  622.     return DBIERR_NONE;
  623. }
  624.  
  625. //======================================================================
  626. //  Name:   GetNextRec()
  627. //
  628. //  Input:  Handle to the cursor (hDBICur).
  629. //
  630. //  Return: DBIERR_NONE if DbiGetNextRecord is successful.
  631. //
  632. //  Desc:   This function moves one record forward.
  633. //======================================================================
  634. DBIResult
  635. GetNextRec (hDBICur hCur)
  636. {
  637.     DBIResult rslt;
  638.  
  639.     rslt = DbiGetNextRecord(hCur, dbiNOLOCK, NULL, 0);
  640.  
  641.     return rslt;
  642. }
  643.  
  644. //======================================================================
  645. //  Name:   GetPrevRec()
  646. //
  647. //  Input:  Handle to the cursor (hDBICur).
  648. //
  649. //  Return: DBIERR_NONE if DbiGetPrevRec is successful.
  650. //
  651. //  Desc:   This function moves one record backwards.
  652. //======================================================================
  653. DBIResult
  654. GetPrevRec (hDBICur hCur)
  655. {
  656.     DBIResult rslt;
  657.     rslt = DbiGetPriorRecord(hCur, dbiNOLOCK, NULL, 0);
  658.     return rslt;
  659. }
  660.  
  661. //======================================================================
  662. //  Name:   AtEOF()
  663. //
  664. //  Input:  Handle to the cursor (hDBICur).
  665. //
  666. //  Return: TRUE:   If the cursor is at the End Of File (EOF).
  667. //          FALSE:  If the cursor is not at the EOF.
  668. //
  669. //  Desc:   This function moves one record forward to test if the cursor
  670. //          is at the EOF, and then moves back to put the cursor at the
  671. //          place it was before the start of this function.
  672. //======================================================================
  673. BOOL
  674. AtEOF (hDBICur hCur)
  675. {
  676.     DBIResult   rslt;
  677.     BOOL        bRetVal;
  678.  
  679.     // Check if we are at the end of the table.
  680.     rslt = DbiGetNextRecord(hCur, dbiNOLOCK, NULL, 0);
  681.     if(rslt == DBIERR_EOF)
  682.     {
  683.         bRetVal = TRUE;
  684.     }
  685.     else
  686.     {
  687.         bRetVal = FALSE;
  688.     }
  689.  
  690.     // Put the cursor back to its original place - if we are not at EOF.
  691.     DbiGetPriorRecord(hCur, dbiNOLOCK, NULL, 0);
  692.  
  693.     return bRetVal;
  694. }
  695.  
  696. //======================================================================
  697. //  Name:   AtBOF()
  698. //
  699. //  Input:  Handle to the cursor (hDBICur).
  700. //
  701. //  Return: TRUE:   If the cursor is at the Beginning Of File (BOF).
  702. //          FALSE:  If the cursor is not at the BOF.
  703. //
  704. //  Desc:   This function moves one record backwards to test if the cursor
  705. //          is at the BOF.  Then it moves the cursor one record forward to
  706. //          put it back to where it was originally.
  707. //======================================================================
  708. BOOL
  709. AtBOF (hDBICur hCur)
  710. {
  711.     DBIResult   rslt;
  712.     BOOL        bRetVal;
  713.  
  714.     // Check if we are at the end of the table.
  715.     rslt = DbiGetPriorRecord(hCur, dbiNOLOCK, NULL, 0);
  716.     if(rslt == DBIERR_BOF)
  717.     {
  718.         bRetVal = TRUE;
  719.     }
  720.     else
  721.     {
  722.         bRetVal = FALSE;
  723.     }
  724.  
  725.     // Put the cursor back to its original place if we are not at BOF.
  726.     DbiGetNextRecord(hCur, dbiNOLOCK, NULL, 0);
  727.  
  728.     return bRetVal;
  729. }
  730.  
  731. //======================================================================
  732. //  Name:   CloseDb()
  733. //
  734. //  Input:  Pointer to the Database (phDBIDb).
  735. //
  736. //  Return: DBIERR_NONE if the table closed successfully.
  737. //
  738. //  Desc:   This function closes the table based upon the table pointer
  739. //          that was passed into the function.
  740. //======================================================================
  741. DBIResult
  742. CloseDb (phDBIDb phDb)
  743. {                                                                       
  744.     CHKERR(DbiCloseDatabase(phDb));
  745.     return DBIERR_NONE;
  746. }
  747.  
  748. //======================================================================
  749. //  Name:   SetupIndex()
  750. //
  751. //  Input:  Pointer to cursor (phDBICur), index name (pCHAR), Tag name
  752. //          (pCHAR), and the Index ID (UINT16).
  753. //
  754. //  Return: DBIERR_NONE if the index switch was successful.
  755. //
  756. //  Desc:   This function switches to an index based upon the index name,
  757. //          index tag name, and index ID.
  758. //======================================================================
  759. DBIResult
  760. SetupIndex (phDBICur phCur, pCHAR pszName, pCHAR pszTagName, UINT16 IndexId)
  761. {                                                                       
  762.     DBIResult rslt;
  763.  
  764.     HourGlassCursor(TRUE);
  765.     rslt = DbiSwitchToIndex(phCur, pszName, pszTagName, IndexId, TRUE);
  766.     HourGlassCursor(FALSE);
  767.     CHKERR(rslt);
  768.  
  769.     return rslt;
  770. }
  771.  
  772. //======================================================================
  773. //  Name:   SetIndex()
  774. //
  775. //  Input:  Pointer to cursor (phDBICur), index name (pCHAR).
  776. //
  777. //  Return: DBIERR_NONE if SetupIndex was successful.
  778. //
  779. //  Desc:   This function runs SetupIndex with different parameters based
  780. //          upon the table type.
  781. //======================================================================
  782. DBIResult
  783. SetIndex (phDBICur phCur, pCHAR pszIndex)
  784. {
  785.     UINT16  iIndexId = NULL;
  786.     CHAR    szMdxName[DBIMAXPATHLEN];
  787.  
  788.     // Move to the top of the table and move forward one record past the
  789.     // crack.
  790.     GoTop(*phCur, TRUE);
  791.  
  792.     // Clear szMdxName
  793.     memset(szMdxName, '/0', DBIMAXNAMELEN);
  794.  
  795.     // Check if the index is called primary.  If it is there is no real
  796.     // index name and we need to send the switch index function an index id
  797.     // of 0.
  798.     if((strcmpi(pszIndex, "Primary")==0)&&(strcmpi(szTblType,
  799.                 szPARADOX)==0))
  800.     {
  801.         iIndexId = 0;
  802.         strcpy(pszIndex, "");
  803.         SetupIndex(phCur, pszIndex, NULL, iIndexId);
  804.     }
  805.     else
  806.     {
  807.         if(strcmpi(szTblType, szDBASE)==0)
  808.         {
  809.             // Get the Production index's name, since it is a dBASE index.
  810.             GetMdxName(*phCur, szMdxName);
  811.             iIndexId = NULL;
  812.             SetupIndex(phCur, szMdxName, pszIndex, iIndexId);
  813.         }
  814.         else
  815.         {
  816.             SetupIndex(phCur, pszIndex, NULL, iIndexId);
  817.         }
  818.     }
  819.  
  820.     return DBIERR_NONE;
  821. }
  822.  
  823. //======================================================================
  824. //  Name:   FillIndexStr()
  825. //
  826. //  Input:  Handle to the cursor (hDBICur), Handle to the database (hDBIDb),
  827. //          Pointer to the Addressbook Index structure (pABIDXDDESC) a
  828. //          pointer to the string that will hold the name of the active
  829. //          index (pCHAR), and a pointer to the active index (pUINT16).
  830. //
  831. //  Return: DBIERR_NONE if the pIndexes pointer is successfully filled.
  832. //
  833. //  Desc:   This function allocates memory to the index descriptor pointer
  834. //          and then fills it with the index information.  Then it fills the
  835. //          pActIdx pointer with the name of the presently active index.
  836. //          It then returns the total number of indexes inside the
  837. //          puIndexes variable.
  838. //======================================================================
  839. DBIResult
  840. FillIndexStr (hDBICur hCur, hDBIDb hDb, pABIDXDESC *pIndexes,
  841.               pCHAR pszActIdx, pUINT16 puIndexes)
  842. {
  843.     UINT16      i;
  844.     UINT16      j;
  845.     UINT        iKey;
  846.     UINT16        iIdx;
  847.     CURProps    TblProps;
  848.     DBIKEYEXP   KeyExp;
  849.     pIDXDesc    pMyDesc = NULL;
  850.     pIDXDesc    pAllDesc = NULL;
  851.     pFLDDesc    pFields = NULL;    
  852.     DBIKEYEXP   szFld;
  853.     pCHAR       pFld;
  854.  
  855.     CHKERR_CLEANUP(DbiGetCursorProps(hCur, &TblProps));
  856.  
  857.     if ((*pIndexes = (pABIDXDESC)malloc(sizeof(ABIDXDESC) *
  858.                                         TblProps.iIndexes)) == NULL)
  859.     {
  860.         WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
  861.         CLEANUP(DBIERR_NOMEMORY);
  862.     }
  863.  
  864.     if ((pMyDesc = (pIDXDesc)malloc(sizeof(IDXDesc) * 1)) == NULL)
  865.     {
  866.         WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
  867.         CLEANUP(DBIERR_NOMEMORY);
  868.     }
  869.  
  870.     if ((pFields = (pFLDDesc)malloc(sizeof(FLDDesc) * TblProps.iFields))
  871.                                     == NULL)
  872.     {
  873.         WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
  874.         CLEANUP(DBIERR_NOMEMORY);
  875.     }
  876.  
  877.     if ((pAllDesc = (pIDXDesc)malloc(sizeof(IDXDesc) * TblProps.iIndexes))
  878.                                    == NULL)
  879.     {
  880.         WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
  881.         CLEANUP(DBIERR_NOMEMORY);
  882.     }
  883.  
  884.     CHKERR_NODISPLAY(GetIndexDescs(hDb, pAllDesc));
  885.     CHKERR_CLEANUP(DbiGetFieldDescs(hCur, pFields));
  886.  
  887.     // Copy the data we need into the ABIDXDESC structure.
  888.     for(i=0; i<TblProps.iIndexes; i++)
  889.     {
  890.         // If it is a dBASE table just copy the information in - as the
  891.         // keyexp is already built for us.  Also get the index name and
  892.         // get the fields in the index.
  893.         if(strcmpi(TblProps.szTableType, szDBASE)==0)
  894.         {
  895.             strcpy((*pIndexes)[i].szTagName, pAllDesc[i].szTagName);
  896.             if(pAllDesc[i].bExpIdx)
  897.             {
  898.                 strcpy((*pIndexes)[i].szKeyExp, pAllDesc[i].szKeyExp);
  899.                 strcpy(szFld, pAllDesc[i].szKeyExp);
  900.  
  901.                 // Now parse the index expression.  We will only parse
  902.                 // for the + symbol.
  903.                 j=0;
  904.                 pFld = strtok(szFld, "+");
  905.  
  906.                 // Pass the string into this function to get the field
  907.                 // number and len for it.
  908.                 CHKERR_NODISPLAY(GetFieldInfo(pFld,
  909.                                               &((*pIndexes)[i].aiKeyFld[j]),
  910.                                               &((*pIndexes)[i].aiKeyLen[j]),
  911.                                               hCur, TblProps.iFields));
  912.                 j++;
  913.  
  914.                 while(pFld!=NULL)
  915.                 {
  916.                     pFld = strtok(NULL, "+");
  917.                     if(pFld != NULL)
  918.                     {
  919.                         CHKERR_NODISPLAY(GetFieldInfo(pFld,
  920.                                 &((*pIndexes)[i].aiKeyFld[j]),
  921.                                 &((*pIndexes)[i].aiKeyLen[j]), hCur,
  922.                                 TblProps.iFields));
  923.                         j++;
  924.                     }
  925.                 }
  926.  
  927.                 (*pIndexes)[i].iFldsInKey = j;
  928.             }
  929.             else
  930.             {
  931.                 strcpy((*pIndexes)[i].szKeyExp, pAllDesc[i].szKeyExp);
  932.                 strcpy(szFld, pAllDesc[i].szKeyExp);
  933.                 strcpy((*pIndexes)[i].szKeyExp, pAllDesc[i].szKeyExp);
  934.                 (*pIndexes)[i].iFldsInKey = pAllDesc[i].iFldsInKey;
  935.  
  936.                 // This is a single field index so get the zeroth item.
  937.                 iIdx = pAllDesc[i].aiKeyFld[0];
  938.  
  939.                 (*pIndexes)[i].aiKeyFld[0]=iIdx;
  940.  
  941.                 // Get the field length so for this particular field.
  942.                 if(pFields[iIdx-1].iFldType == fldDATE)
  943.                 {
  944.                     (*pIndexes)[i].aiKeyLen[0]= DATELEN-1;
  945.                 }
  946.  
  947.                 if(pFields[iIdx-1].iFldType == fldZSTRING)
  948.                 {
  949.                     (*pIndexes)[i].aiKeyLen[0] = (pFields[iIdx-1].iUnits1);
  950.                 }
  951.             }
  952.         }
  953.         // Else the keyexp is not built for us so we need to build it
  954.         // ourselves.
  955.         else
  956.         {
  957.             // First copy the index name, TagName, and iFldsInKey
  958.             strcpy((*pIndexes)[i].szTagName, pAllDesc[i].szName);
  959.             (*pIndexes)[i].iFldsInKey = pAllDesc[i].iFldsInKey;
  960.  
  961.             // Get the total number of fields in the index - 1.  That
  962.             // way when we stick + symbols into the string we will know
  963.             // when to stop.  Though it can be done other ways it is easier
  964.             // to understand this way.
  965.             iKey = pAllDesc[i].iFldsInKey - 1;
  966.  
  967.             // MUST clear the string everytime through to make sure we can
  968.             // use strcat even the first time.  Also set the fieldlen to 0.
  969.             memset(KeyExp, '\0', DBIMAXKEYEXPLEN+1);
  970.  
  971.             // Loop through the fields in the key and copy the Field's
  972.             // name into the string.
  973.             for(j=0; j<pAllDesc[i].iFldsInKey; j++)
  974.             {
  975.                 // Get the Jth field number for this Ith index.  We
  976.                 // subtract one because the fields are one based while the
  977.                 // array is zero based.
  978.                 iIdx = (pAllDesc[i].aiKeyFld[j]);
  979.                 strcat(KeyExp, pFields[iIdx-1].szName);
  980.  
  981.                 (*pIndexes)[i].aiKeyFld[j]=iIdx;
  982.  
  983.                 // Get the field length so for this particular field.
  984.                 if(pFields[iIdx-1].iFldType == fldDATE)
  985.                 {
  986.                     (*pIndexes)[i].aiKeyLen[j]= DATELEN-1;
  987.                 }
  988.  
  989.                 if(pFields[iIdx-1].iFldType == fldZSTRING)
  990.                 {
  991.                     (*pIndexes)[i].aiKeyLen[j] = (pFields[iIdx-1].iUnits1);
  992.                 }
  993.  
  994.                 // If iKey = 0 then this is the last field number in
  995.                 // the array and we do not want to add a + symbol to the
  996.                 // string.  Otherwise, add a + symbol to the string.
  997.                 if(iKey != 0)
  998.                 {
  999.                     strcat(KeyExp, " + ");
  1000.  
  1001.                     // Only subtract one from iKey here or else you will
  1002.                     // create a -1 value for this UINT16 variable.
  1003.                     iKey--;
  1004.                 }
  1005.             }
  1006.  
  1007.             // Add the created Key expression to the strcuture.
  1008.             strcpy((*pIndexes)[i].szKeyExp, KeyExp);
  1009.         }
  1010.  
  1011.     }
  1012.  
  1013.     CHKERR_CLEANUP(DbiGetIndexDesc(hCur, 0, pMyDesc));
  1014.  
  1015.     // If this is a dBASE table pass the tag name back as the active index.
  1016.     if(strcmpi(TblProps.szTableType, szDBASE)==0)
  1017.     {
  1018.         // Get information about the currently active index.
  1019.         strcpy(pszActIdx, pMyDesc->szTagName);
  1020.     }
  1021.     else
  1022.     {
  1023.         if(strcmpi(TblProps.szTableType, szPARADOX)==0)
  1024.         {
  1025.             if(pMyDesc->iIndexId==0)
  1026.             {
  1027.                 strcpy(pszActIdx, (pCHAR)"Primary");
  1028.             }
  1029.             else
  1030.             {
  1031.                 strcpy(pszActIdx, pMyDesc->szName);
  1032.             }
  1033.         }
  1034.         else
  1035.         {
  1036.             strcpy(pszActIdx, pMyDesc->szName);
  1037.         }
  1038.     }
  1039.  
  1040.     *puIndexes = TblProps.iIndexes;
  1041.  
  1042.     // Free all the memory except for the one we created for pIndexes.
  1043.     // That will be freed by the calling function.
  1044.     free(pMyDesc);
  1045.     free(pAllDesc);
  1046.     free(pFields);
  1047.  
  1048.     return DBIERR_NONE;
  1049.  
  1050. CleanUp:
  1051.     if(pMyDesc)
  1052.     {
  1053.         free(pMyDesc);
  1054.     }
  1055.     if(pAllDesc)
  1056.     {
  1057.         free(pAllDesc);
  1058.     }
  1059.     if(pFields)
  1060.     {
  1061.         free(pFields);
  1062.     }
  1063.     return GlobalDBIErr;
  1064. }
  1065.  
  1066. //======================================================================
  1067. //  Name:   DeleteRec()
  1068. //
  1069. //  Input:  Handle to the cursor (hDBICur).
  1070. //
  1071. //  Return: DBIERR_NONE if the record is successfully deleted.
  1072. //
  1073. //  Desc:   This function deletes the record that is pointed to by the
  1074. //          cursor.
  1075. //======================================================================
  1076. DBIResult
  1077. DeleteRec (hDBICur hCur)
  1078. {
  1079.     CHKERR(DbiGetRecord(hCur, dbiWRITELOCK, NULL, 0));
  1080.  
  1081.     CHKERR(DbiDeleteRecord(hCur, NULL));
  1082.     return DBIERR_NONE;
  1083. }
  1084.  
  1085. //======================================================================
  1086. //  Name:   SetRange()
  1087. //
  1088. //  Input:  Record structure pointer for high range value (RecordType *),
  1089. //          Record structure pointer for low range value (RecordType *),
  1090. //          Bool describing whether the high value is included in the range
  1091. //          (BOOL), Bool describing the low value is included in the range
  1092. //          (BOOL), Cursor handle (hDBICur), Bool describing whether
  1093. //          pHighRec is filled with a value (BOOL), Bool describing whether
  1094. //          pLowRec is filled with a value (BOOL).
  1095. //
  1096. //  Return: DBIERR_NONE if the range is successfully set.
  1097. //
  1098. //  Desc:   This function sets the range.  To do so it needs the high and
  1099. //          low values.  So we pass them inside of pHighRec and pLowRec.
  1100. //          Then we need to know if these range values are to be included in
  1101. //          the range set.  That is done by using the two booleans
  1102. //          bHighInclude and bLowInclude.  Finally we need to pass a NULL
  1103. //          pointer to the set range function if the user set no upper or
  1104. //          lower range.  So we look at bHighEmpty and bLowEmpty.  
  1105. //======================================================================
  1106. DBIResult
  1107. SetRange (RecordType *pHighRec, RecordType *pLowRec, BOOL bHighInclude,
  1108.          BOOL bLowInclude, hDBICur hCur, BOOL bHighEmpty, BOOL bLowEmpty)
  1109. {
  1110.     CURProps    TblProps;
  1111.     pBYTE       pHighRecBuf = NULL;
  1112.     pBYTE       pLowRecBuf = NULL;
  1113.  
  1114.     CHKERR_CLEANUP(DbiGetCursorProps(hCur,&TblProps));
  1115.  
  1116.     if(!bHighEmpty)
  1117.     {
  1118.         if((pHighRecBuf = (pBYTE) malloc(TblProps.iRecBufSize))==NULL)
  1119.         {
  1120.             WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
  1121.             CLEANUP(DBIERR_NOMEMORY);
  1122.         }
  1123.         CHKERR_CLEANUP(DbiInitRecord(hCur, pHighRecBuf));
  1124.  
  1125.         // Copy the value into the pRecBuf.
  1126.         CHKERR_NODISPLAY(FillBuf(hCur, pHighRecBuf, pHighRec));
  1127.     }
  1128.  
  1129.     if(!bLowEmpty)
  1130.     {
  1131.         if((pLowRecBuf = (pBYTE) malloc(TblProps.iRecBufSize))==NULL)
  1132.         {
  1133.             WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
  1134.             CLEANUP(DBIERR_NOMEMORY);
  1135.         }
  1136.         CHKERR_CLEANUP(DbiInitRecord(hCur, pLowRecBuf));
  1137.  
  1138.         // Copy the value into the pRecBuf.
  1139.         CHKERR_NODISPLAY(FillBuf(hCur, pLowRecBuf, pLowRec));
  1140.     }
  1141.  
  1142.     // Set the range.  The record buffers hold the low and high range
  1143.     // field values.  Since we are using buffers rather than using a direct
  1144.     // pair of strings we set the second parameter to FALSE.  The two
  1145.     // booleans are set by the check boxes in the range dialog box.  They
  1146.     // describe whether the range value will be included inside the answer
  1147.     // set.
  1148.     CHKERR_CLEANUP(DbiSetRange(hCur, FALSE, 0, 0, pLowRecBuf, bLowInclude,
  1149.                                0, 0, pHighRecBuf, bHighInclude));
  1150.  
  1151.     // Free the record buffers - ONLY if they need to be freed.
  1152.     if(!bLowEmpty)
  1153.     {
  1154.         free(pLowRecBuf);
  1155.     }
  1156.     if(!bHighEmpty)
  1157.     {
  1158.         free(pHighRecBuf);
  1159.     }
  1160.     return DBIERR_NONE;
  1161.  
  1162. CleanUp:
  1163.     if(!bLowEmpty)
  1164.     {
  1165.         free(pLowRecBuf);
  1166.     }
  1167.     if(!bHighEmpty)
  1168.     {
  1169.         free(pHighRecBuf);
  1170.     }
  1171.     return GlobalDBIErr;
  1172. }
  1173.  
  1174. //======================================================================
  1175. //  Name:   FillBuf()
  1176. //
  1177. //  Input:  Handle to the cursor (hDBICur), Record buffer (pBYTE), and
  1178. //          a record structure pointer (RecordType*).
  1179. //
  1180. //  Return: DBIErr_NONE if the PutFields are all successful.
  1181. //
  1182. //  Desc:   This function takes the relevent data from the record structure
  1183. //          and puts it into a record buffer that IDAPI understands.
  1184. //======================================================================
  1185. DBIResult
  1186. FillBuf (hDBICur hCur, pBYTE pRecBuf, RecordType* pString)
  1187. {
  1188.     // Fill each field with the structure's data
  1189.     CHKERR(DbiPutField(hCur, 1, pRecBuf, (pBYTE)pString->FName));
  1190.     CHKERR(DbiPutField(hCur, 2, pRecBuf, (pBYTE)pString->LName));
  1191.     CHKERR(DbiPutField(hCur, 3, pRecBuf, (pBYTE)pString->Spouse));
  1192.     CHKERR(DbiPutField(hCur, 4, pRecBuf, (pBYTE)pString->Addrs1));
  1193.     CHKERR(DbiPutField(hCur, 5, pRecBuf, (pBYTE)pString->Addrs2));
  1194.     CHKERR(DbiPutField(hCur, 6, pRecBuf, (pBYTE)pString->City));
  1195.     CHKERR(DbiPutField(hCur, 7, pRecBuf, (pBYTE)pString->State));
  1196.     CHKERR(DbiPutField(hCur, 8, pRecBuf, (pBYTE)pString->Zip));
  1197.     CHKERR(DbiPutField(hCur, 9, pRecBuf, (pBYTE)pString->Phone1));
  1198.     return DBIERR_NONE;
  1199. }
  1200.  
  1201. //======================================================================
  1202. //  Name:   Search()
  1203. //
  1204. //  Input:  Handle to the cursor (hDBICur), Search condition (DBISearchCond),
  1205. //          Boolean: TRUE if the key is in a string.  FALSE if the key is in
  1206. //          a record buffer BOOL), Number of fields to match (UINT16),
  1207. //          Length of characters needed to qualify a match (UINT16), and the
  1208. //          key to search (pBYTE).
  1209. //
  1210. //  Return: DBIERR_NONE if the search is successful.
  1211. //
  1212. //  Desc:   This function searches for a string based upon the index that
  1213. //          is presently active on the table.
  1214. //======================================================================
  1215. DBIResult
  1216. Search (hDBICur hCur, DBISearchCond eCond, BOOL bDirect, UINT16 iFlds,
  1217.         UINT16 iLen,  RecordType *pKey)
  1218. {                                                                       
  1219.     DBIResult   rslt;
  1220.     pBYTE       pRecBuf;
  1221.     CURProps    TblProps;
  1222.  
  1223.     CHKERR_CLEANUP(DbiGetCursorProps(hCur,&TblProps));
  1224.  
  1225.     if((pRecBuf = (pBYTE) malloc(TblProps.iRecBufSize))==NULL)
  1226.     {
  1227.         WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
  1228.         CLEANUP(DBIERR_NOMEMORY);
  1229.     }
  1230.     CHKERR_CLEANUP(DbiInitRecord(hCur, pRecBuf));
  1231.  
  1232.     // Copy the value into the pRecBuf.
  1233.     CHKERR_NODISPLAY(FillBuf(hCur, pRecBuf, pKey));
  1234.  
  1235.     rslt = DbiSetToKey(hCur, eCond, bDirect, iFlds, iLen, pRecBuf);
  1236.  
  1237.     if(rslt != DBIERR_NONE)
  1238.     {
  1239.         // Check if the error is RECNOTFOUND.  If it is return that as the
  1240.         // calling function is expecting either DBIERR_NONE or RECNOTFOUND.
  1241.         if(rslt!=DBIERR_RECNOTFOUND)
  1242.         {
  1243.             CHKERR(rslt);
  1244.         }
  1245.     }
  1246.     else
  1247.     {
  1248.         // Check if we are at the EOF.  If we are return RECNOTFOUND.    
  1249.         if(AtEOF(hCur))
  1250.         {
  1251.             rslt = DBIERR_RECNOTFOUND;
  1252.         }
  1253.     }
  1254.     return rslt;
  1255.  
  1256. CleanUp:
  1257.     if(pRecBuf)
  1258.     {
  1259.         free(pRecBuf);
  1260.     }
  1261.     return GlobalDBIErr;
  1262.  
  1263. }
  1264.  
  1265. //======================================================================
  1266. //  Name:   ResetRange()
  1267. //
  1268. //  Input:  Handle to the cursor (hDBICur).
  1269. //
  1270. //  Return: DBIERR_NONE if the range is successfully reset.
  1271. //
  1272. //  Desc:   This function clears any range settings.  The outcome is that
  1273. //          all records will be visable to the user.
  1274. //======================================================================
  1275. DBIResult
  1276. ResetRange (hDBICur hCur)
  1277. {
  1278.     CHKERR(DbiResetRange(hCur));
  1279.     return DBIERR_NONE;
  1280. }
  1281.  
  1282. //======================================================================
  1283. //  Name:   DateEncode()
  1284. //
  1285. //  Input:  The month, day, and year (UINT16), and a pointer to the
  1286. //          DBIDATE variable that is to be passed into a record buffer.
  1287. //
  1288. //  Return: DBIERR_NONE if the date is successfully encoded.
  1289. //
  1290. //  Desc:   This function takes in the date, month, and year and encodes
  1291. //          them into the DBIDATE pointer with the DateEncode function.
  1292. //======================================================================
  1293. DBIResult
  1294. DateEncode (UINT iMon, UINT iDay, int iYear, pDBIDATE pTempDate)
  1295. {
  1296.  
  1297.     DBIResult rslt;
  1298.  
  1299.     // Check the result of the date encode and return it.
  1300.     rslt = DbiDateEncode((UINT16)iMon, (UINT16)iDay, (INT16)iYear,
  1301.                          pTempDate);
  1302.  
  1303.     return rslt;
  1304. }
  1305.  
  1306. //======================================================================
  1307. //  Name:   AdrGetDateFormat()
  1308. //
  1309. //  Input:  Date format structure (FMTDate).
  1310. //
  1311. //  Return: DBIERR_NONE if the date format is successfully retrieved.
  1312. //
  1313. //  Desc:   This function takes in the in the date format structure and
  1314. //          fills it with the current date seettings of IDAPI.
  1315. //======================================================================
  1316. DBIResult
  1317. AdrGetDateFormat (pFMTDate pDate)
  1318. {
  1319.  
  1320.     DBIResult rslt;
  1321.  
  1322.     // Check the result of the date encode and return it.
  1323.     rslt = DbiGetDateFormat(pDate);
  1324.  
  1325.     return rslt;
  1326. }
  1327.  
  1328. //======================================================================
  1329. //  Name:   GetDirectory()
  1330. //
  1331. //  Input:  The database handle (hDBIDb), and a directory string (pCHAR). 
  1332. //
  1333. //  Return: DBIERR_NONE if the directory name is successfully retrieved.
  1334. //
  1335. //  Desc:   This function takes in the in the directory string and getss
  1336. //          the defualt directory.
  1337. //======================================================================
  1338. DBIResult
  1339. GetDirectory (hDBIDb hDb, pCHAR pszBuffer)
  1340. {
  1341.     DBIResult rslt;
  1342.     rslt = DbiGetDirectory(hDb, FALSE, pszBuffer);
  1343.     return rslt;
  1344. }
  1345.  
  1346. //======================================================================
  1347. //  Name:   FillAliasStr()
  1348. //
  1349. //  Input:  Pointer to a Database descriptor structure (pDBDesc).
  1350. //          Number of aliases (plNumAliases).
  1351. //
  1352. //  Return: DBIERR_NONE if Alias pointer is successfully filled.
  1353. //
  1354. //  Desc:   This function takes in the in the DBDesc structure and
  1355. //          fills it with all the alias information for the given table.
  1356. //          It then returns the number of aliases in the plNumAliases
  1357. //          parameter.
  1358. //======================================================================
  1359. DBIResult
  1360. FillAliasStr (pDBDesc *Alias, pUINT32 plNumAliases)
  1361. {
  1362.     UINT16      i;
  1363.     hDBICur     hDBCur = NULL;
  1364.     UINT32      iTempNum;
  1365.  
  1366.     *plNumAliases = 0;
  1367.  
  1368.     // Get the list of aliases, by getting the list of all Databases that
  1369.     // are available to the client.
  1370.     CHKERR_CLEANUP(DbiOpenDatabaseList(&hDBCur));
  1371.  
  1372.     CHKERR_CLEANUP(DbiGetRecordCount(hDBCur, plNumAliases));
  1373.  
  1374.     if(*plNumAliases * sizeof(DBDesc) > 64000L)
  1375.     {
  1376.         iTempNum = MAXCHARLEN/sizeof(DBDesc);
  1377.         *plNumAliases = iTempNum;
  1378.     }
  1379.  
  1380.     if(((*Alias = (pDBDesc) malloc((UINT16)*plNumAliases * sizeof(DBDesc)))
  1381.                 == NULL) && (*plNumAliases > 0))
  1382.     {
  1383.         WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
  1384.         CLEANUP(DBIERR_NOMEMORY);
  1385.     }
  1386.  
  1387.     CHKERR_CLEANUP(DbiSetToBegin(hDBCur));
  1388.  
  1389.     // Fill the pointer with the records that hDBCur points to.
  1390.     for(i=0; i<*plNumAliases; i++)
  1391.     {
  1392.         // Move past the BOF and loop until EOF.
  1393.         CHKERR_CLEANUP(DbiGetNextRecord(hDBCur, dbiNOLOCK,
  1394.                                         (pBYTE)&((*Alias)[i]), NULL));
  1395.     }
  1396.  
  1397.     // Close the schema table.
  1398.     CHKERR_CLEANUP(DbiCloseCursor(&hDBCur));
  1399.     return DBIERR_NONE;
  1400.  
  1401. CleanUp:
  1402.     if(hDBCur)
  1403.     {
  1404.         DbiCloseCursor(&hDBCur);
  1405.     }
  1406.     return GlobalDBIErr;
  1407. }
  1408.  
  1409. //======================================================================
  1410. //  Name:   OpenDB()
  1411. //
  1412. //  Input:  Pointer to the Database (phDBIDb), Table type (pCHAR),
  1413. //          Password (pCHAR), Table Name/Alias (pCHAR).
  1414. //
  1415. //  Return: DBIERR_NONE if the database is successfully opened.
  1416. //
  1417. //  Desc:   This function opens a database for the given pointer to the
  1418. //          database handle.
  1419. //======================================================================
  1420. DBIResult
  1421. OpenDB (phDBIDb phDb, pCHAR pszTableType, pCHAR pszPassword, pCHAR pszAlias)
  1422. {
  1423.     DBIResult   rslt;
  1424.  
  1425.     rslt = DbiOpenDatabase(pszAlias, pszTableType, dbiREADWRITE,
  1426.                            dbiOPENSHARED, pszPassword, 0, NULL, NULL, phDb);
  1427.     if(rslt != DBIERR_NONE)
  1428.     {
  1429.         CHKERR(rslt);
  1430.     }
  1431.  
  1432.     return rslt;
  1433. }
  1434.  
  1435. //======================================================================
  1436. //  Name:   DisplayError()
  1437. //
  1438. //  Input:  Error number (DBIResult), and pointer to the message string
  1439. //          (pCHAR).
  1440. //
  1441. //  Return: DBIERR_NONE if the error information is successfully retrieved.
  1442. //
  1443. //  Desc:   This function allocates memory for the pMsg string and the fills
  1444. //          it with all the extended error information.
  1445. //======================================================================
  1446. DBIResult
  1447. DisplayError (DBIResult rslt, pCHAR *pszMsg)
  1448. {
  1449.     DBIErrInfo  ErrInfo;
  1450.     DBIResult   rslt1;
  1451.  
  1452.     // Need enough space for the message from IDAPI, as well as additional
  1453.     // information.
  1454.     CHAR        szMsg[DBIMAXMSGLEN + 40];
  1455.  
  1456.     //  Need five plus additional information.
  1457.     if((*pszMsg = (pCHAR)malloc(DBIMAXMSGLEN * 7))==NULL)
  1458.     {
  1459.         WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
  1460.         rslt1 = DBIERR_NOMEMORY;
  1461.         CHKERR(rslt1);
  1462.     }
  1463.  
  1464.     // Failed to connect
  1465.     CHKERR(DbiGetErrorInfo(TRUE, &ErrInfo));
  1466.  
  1467.     wsprintf(*pszMsg, "    Error Category = %d      Error Code = %d\r\n",
  1468.              ErrCat(rslt), ErrCode(rslt));
  1469.  
  1470.     if (ErrInfo.szErrCode[0] != '\0')
  1471.     {
  1472.         wsprintf(szMsg, "     -> ErrCode: %s\r\n", ErrInfo.szErrCode);
  1473.         strcat(*pszMsg, szMsg);
  1474.     }
  1475.  
  1476.     if (ErrInfo.szContext1[0] != '\0')
  1477.     {
  1478.         wsprintf(szMsg, "     -> Context1: %s\r\n", ErrInfo.szContext1);
  1479.         strcat(*pszMsg, szMsg);
  1480.     }
  1481.  
  1482.     if (ErrInfo.szContext2[0] != '\0')
  1483.     {
  1484.         wsprintf(szMsg, "     -> Context2: %s\r\n", ErrInfo.szContext2);
  1485.         strcat(*pszMsg, szMsg);
  1486.     }
  1487.  
  1488.     if (ErrInfo.szContext3[0] != '\0')
  1489.     {
  1490.         wsprintf(szMsg, "     -> Context3: %s\r\n", ErrInfo.szContext3);
  1491.         strcat(*pszMsg, szMsg);
  1492.     }
  1493.  
  1494.     if (ErrInfo.szContext4[0] != '\0')
  1495.     {
  1496.         wsprintf(szMsg, "     -> Context4: %s\r\n", ErrInfo.szContext4);
  1497.         strcat(*pszMsg, szMsg);
  1498.     }
  1499.  
  1500.     return DBIERR_NONE;
  1501. }
  1502.  
  1503. //======================================================================
  1504. //  Name:   GetFieldInfo()
  1505. //
  1506. //  Input:  Field name (pCHAR), Pointer to the Field number (pUINT16),
  1507. //          Pointer to Field len (pUINT16), Cursor handle (hDBICur), and
  1508. //          Number of fields in table (UINT16).
  1509. //
  1510. //  Return: DBIERR_NONE if the field descriptor is successfully filled,
  1511. //          number of the field in FldNum, and the field len in FldLen.
  1512. //
  1513. //  Desc:   This function searches for the field name that is passed to
  1514. //          it and fills the FldNum variable with the number of the field.
  1515. //          The number correlates to the field number that IDAPI uses.
  1516. //          It also returns the field length inside of the FldLen variable.
  1517. //======================================================================
  1518. DBIResult
  1519. GetFieldInfo (pCHAR pFld, pUINT16 FldNum, pUINT16 FldLen, hDBICur hCur,
  1520.               UINT16 iFields)
  1521. {
  1522.     pFLDDesc    pFldDesc;
  1523.     pCHAR       pFldName = NULL;
  1524.     UINT16      i;
  1525.     BOOL        bFlag = FALSE;
  1526.  
  1527.     // Get all the field descriptors.
  1528.     if ((pFldDesc = (pFLDDesc)malloc(sizeof(FLDDesc) * iFields)) == NULL)
  1529.     {
  1530.         WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
  1531.         CLEANUP(DBIERR_NOMEMORY);
  1532.     }
  1533.  
  1534.     if ((pFldName = (pCHAR)malloc(sizeof(CHAR) * DBIMAXNAMELEN)) == NULL)
  1535.     {
  1536.         WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
  1537.         CLEANUP(DBIERR_NOMEMORY);
  1538.     }
  1539.  
  1540.     CHKERR_CLEANUP(DbiGetFieldDescs(hCur, pFldDesc));
  1541.  
  1542.     // Strip out any spaces so that we can find the field names correctly.
  1543.     StripChar(pFldName, pFld, 32);
  1544.  
  1545.     i = 0;
  1546.  
  1547.     // Loop through the field names and find the name that matches.
  1548.     while(i<iFields && !bFlag)
  1549.     {
  1550.         if(stricmp(pFldDesc[i].szName, pFldName)==0)
  1551.         {
  1552.             *FldNum = pFldDesc[i].iFldNum;
  1553.  
  1554.             // Get the field length so for this particular field.
  1555.             if(pFldDesc[i].iFldType == fldDATE)
  1556.             {
  1557.                 *FldLen = DATELEN-1;
  1558.                 bFlag = TRUE;
  1559.             }
  1560.  
  1561.             if(pFldDesc[i].iFldType == fldZSTRING)
  1562.             {
  1563.                 *FldLen = pFldDesc[i].iUnits1;
  1564.                 bFlag = TRUE;
  1565.             }
  1566.         }
  1567.         i++;
  1568.     }
  1569.  
  1570.     free(pFldDesc);
  1571.     free(pFldName);
  1572.  
  1573.     return DBIERR_NONE;
  1574.  
  1575. CleanUp:
  1576.     if(pFldDesc)
  1577.     {
  1578.         free(pFldDesc);
  1579.     }
  1580.     if(pFldName)
  1581.     {
  1582.         free(pFldName);
  1583.     }
  1584.     return GlobalDBIErr;
  1585. }
  1586.  
  1587. //======================================================================
  1588. //  Name:   StripChar()
  1589. //
  1590. //  Input:  Destination string (pCHAR), and Source string (pCHAR), Character
  1591. //          to strip out (CHAR).
  1592. //
  1593. //  Return: None.
  1594. //
  1595. //  Desc:   This function strips any charachter out of the source string
  1596. //          (Src) and puts the new string into the destination string
  1597. //          (Dest).
  1598. //======================================================================
  1599. void
  1600. StripChar (pCHAR pszDest, pCHAR pszSrc, CHAR cChar)
  1601. {
  1602.     UINT16 i;
  1603.     UINT16 iDest;
  1604.     UINT16 iLen;
  1605.  
  1606.     memset(pszDest, '\0', DBIMAXNAMELEN);
  1607.  
  1608.     // Get the total length of the string
  1609.     iLen = (UINT16)strlen(pszSrc);
  1610.  
  1611.     // Loop through the string.  If we find a space do not copy the space
  1612.     // into the dest string.  Also set iDest = 0.
  1613.     iDest=0;
  1614.     for(i=0; i<iLen; i++)
  1615.     {
  1616.         // If the character is not a space copy it to the Dest string.
  1617.         if(pszSrc[i]!=cChar)
  1618.         {
  1619.             pszDest[iDest]=pszSrc[i];
  1620.             iDest++;
  1621.         }
  1622.     }
  1623.     pszDest[iDest]='\0';
  1624. }
  1625.  
  1626. //======================================================================
  1627. //  Name:   GetMdxName()
  1628. //
  1629. //  Input:  Cursor handle (hDBICur), and a string to put the Mdx name in
  1630. //          (pCHAR).
  1631. //
  1632. //  Return: DBIERR_NONE if the Mdx name is successfully retrieved.
  1633. //
  1634. //  Desc:   This function gets the Mdx name for the given table pointed
  1635. //          to by hCur, and returns the name of the Mdx file associated
  1636. //          with that cursor handle.
  1637. //======================================================================
  1638. DBIResult
  1639. GetMdxName (hDBICur hCur, pCHAR pszMdxName)
  1640. {
  1641.     pIDXDesc    pMyDesc;    
  1642.  
  1643.     if ((pMyDesc = (pIDXDesc)malloc(sizeof(IDXDesc) * 1)) == NULL)
  1644.     {
  1645.         WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
  1646.         CLEANUP(DBIERR_NOMEMORY);
  1647.     }
  1648.  
  1649.     // Simply Get the first tag of the Mdx and get the Mdx name.  In an
  1650.     // Mdx all the tags have the same MDX file name, as they all live
  1651.     // inside the same MDX file.  We pass in 1, because that gets the first
  1652.     // index while 0 gets the active index - of which there is none - yet.
  1653.     CHKERR_CLEANUP(DbiGetIndexDesc(hCur, 1, pMyDesc));
  1654.     strcpy(pszMdxName, pMyDesc->szName);
  1655.     free(pMyDesc);
  1656.     return DBIERR_NONE;
  1657.  
  1658. CleanUp:
  1659.     if(pMyDesc)
  1660.     {
  1661.         free(pMyDesc);
  1662.     }
  1663.     return GlobalDBIErr;
  1664. }
  1665.  
  1666. //======================================================================
  1667. //  Name:   GetIndexDescs()
  1668. //
  1669. //  Input:  Cursor handle (hDBICur), and a pointer to the index descriptor
  1670. //          (pIDXDesc).
  1671. //
  1672. //  Return: DBIERR_NONE if the index descriptor is successfully filled.
  1673. //
  1674. //  Desc:   This function takes in the index descriptor and fills it with
  1675. //          all the indexes that are open for the table and database.
  1676. //======================================================================
  1677. DBIResult
  1678. GetIndexDescs (hDBIDb hDb, pIDXDesc pAllDesc)
  1679. {
  1680.     UINT16      i;
  1681.     hDBICur     hIdxCur = NULL;
  1682.  
  1683.     CHKERR_CLEANUP(DbiOpenIndexList(hDb, (pCHAR)szTblName, (pCHAR)szTblType,
  1684.                             &hIdxCur));
  1685.  
  1686.     // Go to the top of the in-memory table.
  1687.     CHKERR_CLEANUP(DbiSetToBegin(hIdxCur));
  1688.  
  1689.     // Now fill the pointer with the records that hDBCur points to.
  1690.     i = 0;
  1691.     while((DbiGetNextRecord(hIdxCur, dbiNOLOCK, (pBYTE)(&pAllDesc[i]),
  1692.                             NULL))!=DBIERR_EOF)
  1693.     {
  1694.         // Check if the table is a PARADOX table.  If it is the primary
  1695.         // index will not have a name and we need to give it one.
  1696.         if(strcmpi(szTblType, szPARADOX)==0)
  1697.         {
  1698.             if(pAllDesc[i].iIndexId == 0)
  1699.             {
  1700.                 strcpy(pAllDesc[i].szName, "Primary");
  1701.             }
  1702.         }
  1703.         i++;
  1704.     }
  1705.  
  1706.     DbiCloseCursor(&hIdxCur);
  1707.     return DBIERR_NONE;
  1708.  
  1709. CleanUp:
  1710.     if(hIdxCur)
  1711.     {
  1712.         DbiCloseCursor(&hIdxCur);
  1713.     }
  1714.     return GlobalDBIErr;
  1715. }
  1716.  
  1717. //======================================================================
  1718. //  Name:   GetFldNames()
  1719. //
  1720. //  Input:  Cursor handle (hDBICur), and a pointer to the Field name
  1721. //          structure (pFieldNames).
  1722. //
  1723. //  Return: DBIERR_NONE if the field names are successfully returned.
  1724. //
  1725. //  Desc:   This function fills the pFieldNames pointer with all the field
  1726. //          names for the given table.
  1727. //======================================================================
  1728. DBIResult
  1729. GetFldNames (hDBICur hCur, pFIELDName pFieldNames)
  1730. {
  1731.     pFLDDesc    pFields = NULL;
  1732.     UINT16      i;
  1733.     CURProps    TblProps;
  1734.  
  1735.     CHKERR_CLEANUP(DbiGetCursorProps(hCur, &TblProps));
  1736.  
  1737.     if ((pFields = (pFLDDesc)malloc(sizeof(FLDDesc) * TblProps.iFields))
  1738.                                     == NULL)
  1739.     {
  1740.         WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
  1741.         CLEANUP(DBIERR_NOMEMORY);
  1742.     }
  1743.  
  1744.     CHKERR_CLEANUP(DbiGetFieldDescs(hCur, pFields));
  1745.  
  1746.     for(i=0; i<TblProps.iFields; i++)
  1747.     {
  1748.         strcpy(pFieldNames[i].FieldName, pFields[i].szName);
  1749.     }
  1750.  
  1751.     free(pFields);
  1752.     return DBIERR_NONE;
  1753.  
  1754. CleanUp:
  1755.     if(pFields)
  1756.     {
  1757.         free(pFields);
  1758.     }
  1759.     return GlobalDBIErr;
  1760. }
  1761.  
  1762. //======================================================================
  1763. //  Name:   CloseTable()
  1764. //
  1765. //  Input:  Pointer to the cursor handle (phDBICur).
  1766. //
  1767. //  Return: DBIERR_NONE if the table is successfully closed.
  1768. //
  1769. //  Desc:   This function simply closes the given table.
  1770. //======================================================================
  1771. DBIResult
  1772. CloseTable (phDBICur pCur)
  1773. {
  1774.     CHKERR(DbiCloseCursor(pCur));
  1775.  
  1776.     return DBIERR_NONE;
  1777. }
  1778.  
  1779. //======================================================================
  1780. //  Name:   CheckTable()
  1781. //
  1782. //  Input:  Table Cursor (hDBICur).
  1783. //          Boolean (pBOOL).
  1784. //
  1785. //  Return: DBIERR_NONE if table is successfully checked.
  1786. //
  1787. //  Desc:   This function simply gets the field descriptors for the given
  1788. //          table and checks if they match the predefined structure for an
  1789. //          addressbook.  If they match it sets the pbFlag parameter to
  1790. //          TRUE.
  1791. //======================================================================
  1792. DBIResult
  1793. CheckTable (hDBICur hCur, pBOOL pbFlag)
  1794. {
  1795.     pFLDDesc    pFldDesc = NULL;
  1796.     UINT16      i;
  1797.     CURProps    TblProps;
  1798.  
  1799.     *pbFlag = TRUE;
  1800.  
  1801.     CHKERR_CLEANUP(DbiGetCursorProps(hCur, &TblProps));
  1802.  
  1803.     if ((pFldDesc = (pFLDDesc)malloc(sizeof(FLDDesc) * TblProps.iFields)) 
  1804.                     == NULL)
  1805.     {
  1806.         WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
  1807.         CLEANUP(DBIERR_NOMEMORY);
  1808.     }
  1809.  
  1810.     CHKERR_CLEANUP(DbiGetFieldDescs(hCur, pFldDesc));
  1811.  
  1812.     i = 0;
  1813.  
  1814.     // Now loop through the field structure and check that both the field
  1815.     // type matches and that the field len match.  If they do not then you
  1816.     // fall out of the loop and set *pbFlag to FALSE.
  1817.     while(i<TblProps.iFields && *pbFlag)
  1818.     {
  1819.         if(!((pFldDesc[i].iFldType == fldDesc[i].iFldType) &&
  1820.            (pFldDesc[i].iUnits1 == fldDesc[i].iUnits1)))
  1821.         {
  1822.             // If the field is a blob field we do not care what the size is.
  1823.             if(pFldDesc[i].iFldType == fldBLOB)
  1824.             {
  1825.                 if(!((pFldDesc[i].iFldType == fldDesc[i].iFldType) &&
  1826.                    (pFldDesc[i].iSubType == fldDesc[i].iSubType)))
  1827.                 {
  1828.                     *pbFlag = FALSE;
  1829.                 }
  1830.             }
  1831.             else
  1832.             {
  1833.                 // If this is a time stamp field or a date then do not
  1834.                 // care about size.
  1835.                 if((pFldDesc[i].iFldType != fldTIMESTAMP)&&
  1836.                     (pFldDesc[i].iFldType != fldDATE))
  1837.                 {
  1838.                     *pbFlag = FALSE;
  1839.                 }
  1840.             }
  1841.         }
  1842.  
  1843.         i++;
  1844.     }
  1845.  
  1846.     free(pFldDesc);
  1847.     return DBIERR_NONE;
  1848.  
  1849. CleanUp:
  1850.     if(pFldDesc)
  1851.     {
  1852.         free(pFldDesc);
  1853.     }
  1854.     *pbFlag = FALSE;
  1855.     return GlobalDBIErr;
  1856. }
  1857.  
  1858. //======================================================================
  1859. //  Name:   GetTblType()
  1860. //
  1861. //  Input:  Table Cursor (hDBICur), a pointer to the Table Type string
  1862. //          (pCHAR).
  1863. //
  1864. //  Return: DBIERR_NONE if the table type is successfully acquired.  It
  1865. //          also returns the table type into the pszTableType string.
  1866. //
  1867. //  Desc:   This function simply gets the table type for the given table
  1868. //          handle.  It then returns the table type in the string called
  1869. //          pszTableType (the second parameter).
  1870. //======================================================================
  1871. DBIResult
  1872. GetTblType (hDBICur hCur, pCHAR pszTableType)
  1873. {
  1874.  
  1875.     CURProps    TblProps;
  1876.  
  1877.     // Get the cursor properties for the Addressbook table.
  1878.     CHKERR(DbiGetCursorProps(hCur, &TblProps));
  1879.     strcpy(pszTableType, TblProps.szTableType);
  1880.     return DBIERR_NONE;
  1881. }
  1882.  
  1883. //======================================================================
  1884. //  Name:   InitIndex1()
  1885. //
  1886. //  Input:  Pointer to the Table Cursor (phDBICur).
  1887. //
  1888. //  Return: DBIERR_NONE if the index is successfully set.
  1889. //
  1890. //  Desc:   This function sets the initial index for a given table.  It
  1891. //          sets the index based upon the table type.
  1892. //======================================================================
  1893. DBIResult
  1894. InitIndex1 (phDBICur phCur)
  1895. {
  1896.     CURProps    TblProps;
  1897.     pIDXDesc    pIndexDesc = NULL;
  1898.  
  1899.     // Get the table's properties so that we can get the size.
  1900.     CHKERR_CLEANUP(DbiGetCursorProps(*phCur, &TblProps));
  1901.  
  1902.     if(TblProps.iIndexes !=0)
  1903.     {
  1904.         if((pIndexDesc = (pIDXDesc) malloc(TblProps.iIndexes *
  1905.                          sizeof(IDXDesc))) == NULL)
  1906.         {
  1907.             WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
  1908.             CLEANUP(DBIERR_NOMEMORY);
  1909.         }
  1910.     }
  1911.     else
  1912.     {
  1913.         WinMsg("There are no Indexes on this table!", MB_ICONHAND, MB_OK);
  1914.         CLEANUP(DBIERR_NOMEMORY);
  1915.     }
  1916.  
  1917.     // Get the index descriptors.
  1918.     CHKERR_CLEANUP(DbiGetIndexDescs(*phCur, pIndexDesc));
  1919.  
  1920.     if(stricmp(szTblType, szDBASE)==0)
  1921.     {
  1922.         SetupIndex(phCur, pIndexDesc[0].szName, pIndexDesc[0].szTagName,
  1923.                    NULL);
  1924.     }
  1925.     else
  1926.     {
  1927.         if(stricmp(szTblType, szPARADOX)==0)
  1928.         {
  1929.             SetupIndex(phCur, NULL, NULL, 0);
  1930.         }
  1931.         else
  1932.         {
  1933.             SetupIndex(phCur, pIndexDesc[0].szName, NULL, NULL);
  1934.         }
  1935.     }
  1936.  
  1937.     free(pIndexDesc);
  1938.     return DBIERR_NONE;
  1939.  
  1940. CleanUp:
  1941.     if(pIndexDesc)
  1942.     {
  1943.         free(pIndexDesc);
  1944.     }
  1945.     return GlobalDBIErr;
  1946. }
  1947.  
  1948. //======================================================================
  1949. //  Name:   GetTableList()
  1950. //
  1951. //  Input:  Handle to the database (hDBIDb), and the pointer to a table
  1952. //          that will point to a table containing information about all
  1953. //          the tables inside of this database (phDBICur).
  1954. //
  1955. //  Return: None.
  1956. //
  1957. //  Desc:   This function opens the table list using the cusror passed
  1958. //          into it by the calling function.
  1959. //======================================================================
  1960. DBIResult
  1961. GetTableList (hDBIDb hDb, phDBICur phTblCur)
  1962. {
  1963.     // Get the list of tables that are available to the client.
  1964.     CHKERR(DbiOpenTableList(hDb, FALSE, FALSE, NULL, phTblCur));
  1965.     return DBIERR_NONE;
  1966. }
  1967.  
  1968. //======================================================================
  1969. //  Name:   GetNextTblRec()
  1970. //
  1971. //  Input:  Handle to the Cursor (hDBICur), Pointer to a base table
  1972. //          descriptor (pTBLBaseDesc).
  1973. //
  1974. //  Return: DBIERR_NONE if the structure is successfully retrieved.
  1975. //
  1976. //  Desc:   This function simply gets the base table descriptor for
  1977. //          the given cursor.
  1978. //======================================================================
  1979. DBIResult
  1980. GetNextTblRec (hDBICur hTblCur, pTBLBaseDesc pbaseDesc)
  1981. {
  1982.     DBIResult rslt;
  1983.  
  1984.     rslt = DbiGetNextRecord(hTblCur, dbiNOLOCK, (pBYTE)pbaseDesc, NULL);
  1985.     if(rslt != DBIERR_NONE)
  1986.     {
  1987.         if(rslt == DBIERR_EOF)
  1988.         {
  1989.             return rslt;
  1990.         }
  1991.         else
  1992.         {
  1993.             CHKERR(rslt);
  1994.         }
  1995.     }
  1996.     return DBIERR_NONE;
  1997. }
  1998.  
  1999. //======================================================================
  2000. //  Name:   DeleteTable()
  2001. //
  2002. //  Input:  Pointer to the Cursor (phDBICur), Handle to the database
  2003. //          (hDBIDb), Table Name (pCHAR), and Table Type (pCHAR).    
  2004. //
  2005. //  Return: DBIERR_NONE if the table is successfully deleted.
  2006. //
  2007. //  Desc:   This function simply closes and then deletes the table whose
  2008. //          cursor and name are passed to it.
  2009. //======================================================================
  2010. DBIResult
  2011. DeleteTable (phDBICur phCur, hDBIDb hDb, pCHAR TblName, pCHAR TblType)
  2012. {
  2013.     CHKERR(DbiCloseCursor(phCur));
  2014.     CHKERR(DbiDeleteTable(hDb, TblName, TblType));
  2015.     return DBIERR_NONE;
  2016. }
  2017.