home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / BC_502 / 32SNIPIT.PAK / SNIPTOOL.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  65.1 KB  |  1,881 lines

  1. // BDE32 3.x - (C) Copyright 1996 by Borland International
  2.  
  3. // sniptool.c
  4. #include "snipit.h"
  5.  
  6. #define MAXLEN 50
  7.  
  8. //===============================================================
  9. //  Function:
  10. //          Screen(Format, ...);
  11. //
  12. //  Input:  Format  - A string that represents the format that
  13. //                    the function vsprintf() uses.
  14. //          ...     - A varied number of input parameters (based
  15. //                    on the needs of the format string).
  16. //
  17. //  Return: None.
  18. //
  19. //  Description:
  20. //          This will build, and echo, a message. 
  21. //===============================================================
  22. void
  23. Screen (pCHAR Format, ...)
  24. {
  25.     va_list argptr;
  26.     CHAR    szMsg[1400];
  27.     pCHAR   pBuf;
  28.     
  29.     va_start(argptr, Format);
  30.     vsprintf(szMsg, Format, argptr);
  31.     va_end(argptr);
  32.  
  33.     if (szMsg)
  34.     {
  35.         // Dump the string and output a CR+LF
  36.         pBuf = (pCHAR) malloc(lstrlen(szMsg) + 3);
  37.         wsprintf(pBuf, "%s\r\n", szMsg);
  38.         Edit_ReplaceSel(GetDlgItem(hMainWnd, IDE_VIEWER_OUTPUT), pBuf);
  39.         free(pBuf);
  40.     }              
  41. }
  42.  
  43. //==============================================================
  44. //  Function:
  45. //          ChkRslt(rslt, pMsg);
  46. //  Input:  rslt    - Return code from IDAPI
  47. //          pMsg    - Null-terminated message.
  48. //
  49. //  Return: IDAPI return code passed in
  50. //
  51. //  Description:
  52. //          This will echo an error message if the expected
  53. //          result does not equal the actual result. The output will be
  54. //          echoed to the screen.
  55. //===============================================================
  56. DBIResult
  57. ChkRslt (DBIResult rslt, pCHAR pMsg)
  58. {
  59.     DBIMSG  dbi_status;
  60.     DBIErrInfo  ErrInfo;
  61.  
  62.     if (rslt == DBIERR_NONE)
  63.     {
  64.         return DBIERR_NONE;
  65.     }
  66.     if (rslt != DBIERR_CANTFINDODAPI)
  67.     {
  68.         // Get as much error information as possible
  69.         DbiGetErrorInfo(TRUE, &ErrInfo);
  70.  
  71.         // Make certain information is returned on the correct error
  72.         if (ErrInfo.iError == rslt)
  73.         {
  74.             Screen("        ERROR %i - %s  Cat:Code [%xh:%xh]\r\n"
  75.                    "          %s",
  76.                    ErrInfo.iError, pMsg, ErrCat(ErrInfo.iError),
  77.                    ErrCode(ErrInfo.iError), ErrInfo.szErrCode);
  78.  
  79.             if (strcmp(ErrInfo.szContext1, ""))
  80.             {
  81.                 Screen("          %s",
  82.                        ErrInfo.szContext1);
  83.             }
  84.             if (strcmp(ErrInfo.szContext2, ""))
  85.             {
  86.                 Screen("          %s",
  87.                        ErrInfo.szContext2);
  88.             }
  89.             if (strcmp(ErrInfo.szContext3, ""))
  90.             {
  91.                 Screen("          %s",
  92.                        ErrInfo.szContext3);
  93.             }
  94.             if (strcmp(ErrInfo.szContext4, ""))
  95.             {
  96.                 Screen("          %s",
  97.                        ErrInfo.szContext4);
  98.             }
  99.         }
  100.         else {
  101.             DbiGetErrorString(rslt, dbi_status);
  102.             Screen("        ERROR %i - %s  Cat:Code [%xh:%xh]\r\n"
  103.                    "          %s",
  104.                    rslt, pMsg, ErrCat(rslt), ErrCode(rslt), dbi_status);
  105.         }
  106.     }
  107.     else
  108.     {
  109.         MessageBox(NULL, "Cannot find IDAPI files: Check path.",
  110.                    "IDAPI Initialization Error", MB_ICONHAND | MB_OK);
  111.     }
  112.  
  113.     return rslt;
  114. }
  115.  
  116. //===============================================================
  117. //  Function:
  118. //          WinMsg(Msg, TypeMsg, TypeBtn);
  119. //
  120. //  Input:  Msg -    The message to display.
  121. //          TypeMsg - The type of messagebox to use (i.e. Stop,
  122. //                    Information)
  123. //          TypeBtn - The buttons to use (i.e. Yes, No, OK, ...)
  124. //
  125. //  Return: Response from the user.
  126. //
  127. //  Description:
  128. //          Display a message box and return a value representing
  129. //          the button the user pressed.
  130. //================================================================
  131. INT16
  132. WinMsg (pCHAR pMsg, UINT16 TypeMsg, UINT16 TypeBtn)
  133. {
  134.     INT16   Style, Buttons;
  135.  
  136.     // Set the style of message box to display
  137.     switch (TypeMsg)
  138.     {
  139.         case MSG_INFO:
  140.             Style = MB_ICONINFORMATION;
  141.             break;
  142.         case MSG_QUESTION:
  143.             Style = MB_ICONQUESTION;
  144.             break;
  145.         case MSG_STOP:
  146.             Style = MB_ICONSTOP;
  147.             break;
  148.         default:
  149.         case MSG_EXCLAMATION:
  150.             Style = MB_ICONEXCLAMATION;
  151.             break;
  152.     }
  153.  
  154.     // Set the style of buttons to make available
  155.     switch (TypeBtn)
  156.     {
  157.         case BTN_OK_CANCEL:
  158.             Buttons = MB_OKCANCEL;
  159.             break;
  160.         case BTN_RETRY_CANCEL:
  161.             Buttons = MB_RETRYCANCEL;
  162.             break;
  163.         case BTN_YES_NO:
  164.             Buttons = MB_YESNO;
  165.             break;
  166.         case BTN_YES_NO_CANCEL:
  167.             Buttons = MB_YESNOCANCEL;
  168.             break;
  169.         default:
  170.         case BTN_OK:
  171.             Buttons = MB_OK;
  172.             break;
  173.     }
  174.     return (INT16)MessageBox(hMainWnd, pMsg, "Code Viewer Message",
  175.                       (WPARAM)(Buttons | Style | MB_APPLMODAL));
  176. }
  177.  
  178. //===============================================================
  179. //  Function:
  180. //          InitAndConnect(phDb);
  181. //
  182. //  Input:  phDb - Pointer to the database handle
  183. //
  184. //  Return: IDAPI return code after DbiInit() and DbiOpenDatabase().
  185. //
  186. //  Description:
  187. //          Initialize IDAPI and connect to a Standard
  188. //          database (non-SQL).
  189. //================================================================
  190. DBIResult
  191. InitAndConnect(phDBIDb phDb)
  192. {
  193.     DBIResult   rslt;
  194.  
  195.     // Initialize IDAPI with a NULL environment structure
  196.     rslt = DbiInit(NULL);
  197.     if (ChkRslt(rslt, "Init") == DBIERR_NONE)
  198.     {
  199.         rslt = DbiDebugLayerOptions(DEBUGON | OUTPUTTOFILE, "SNIPIT.DBG");
  200.         ChkRslt(rslt, "DebugLayerOptions");
  201.  
  202.         // IDAPI initialized. Now open a Standard database (used to access
  203.         //   Paradox and dBASE tables), by using a NULL database type.
  204.         rslt = DbiOpenDatabase(NULL, NULL, dbiREADWRITE, dbiOPENSHARED,
  205.                                NULL, 0, NULL, NULL, phDb);
  206.         if (ChkRslt(rslt, "OpenDatabase") != DBIERR_NONE)
  207.         {
  208.             rslt = DbiExit();
  209.             ChkRslt(rslt, "Exit");
  210.         }
  211.  
  212.         rslt = DbiSetPrivateDir(szPrivDirectory);
  213.         if (ChkRslt(rslt, "SetPrivateDir") != DBIERR_NONE)
  214.         {
  215.             CloseDbAndExit(phDb);
  216.         }                   
  217.     }
  218.     return rslt;
  219. }
  220.  
  221. //===============================================================
  222. //  Function:
  223. //          InitAndConnect2(phDb);
  224. //
  225. //  Input:  phDb - Pointer to the database handle
  226. //
  227. //  Return: IDAPI return code after DbiInit() and DbiOpenDatabase().
  228. //
  229. //  Description:
  230. //          Initialize IDAPI and connect to a SQL database.
  231. //================================================================
  232. DBIResult
  233. InitAndConnect2(phDBIDb phDb)
  234. {
  235.     DBIResult   rslt;
  236. #ifndef WIN32
  237.     FARPROC     lpTempProc;
  238. #endif
  239.  
  240.     // Initialize IDAPI with a NULL environment structure.
  241.     *phDb = NULL;
  242.     rslt = DbiInit(NULL);
  243.     if (ChkRslt(rslt, "Init") == DBIERR_NONE)
  244.     {
  245.         rslt = DbiDebugLayerOptions(DEBUGON | OUTPUTTOFILE, "SNIPIT.DBG");
  246.         ChkRslt(rslt, "DebugLayerOptions");
  247.  
  248.         // Get a handle to an IDAPI database (STANDARD database handle
  249.         //   can be returned, but this is mainly used for SQL connections).
  250. #ifndef WIN32
  251.         lpTempProc =
  252.             MakeProcInstance((FARPROC) ConnectDlgProc, hInst);
  253.         DialogBox(hInst, "ConnectDlg", hMainWnd, (DLGPROC) lpTempProc);
  254.         FreeProcInstance((FARPROC) lpTempProc);
  255. #else
  256.         DialogBox(hInst, "ConnectDlg", hMainWnd, (DLGPROC) ConnectDlgProc);
  257. #endif
  258.  
  259.         // Return the handle (if connect worked).
  260.         if (SnipItDb)
  261.             *phDb = SnipItDb;
  262.         else
  263.         {
  264.             rslt = DbiExit();
  265.             ChkRslt(rslt, "Exit");
  266.  
  267.             // Connect failed or CANCEL was hit.
  268.             rslt = DBIERR_INVALIDHNDL;
  269.             return rslt;
  270.         }
  271.  
  272.         rslt = DbiSetPrivateDir(szPrivDirectory);
  273.         if (ChkRslt(rslt, "SetPrivateDir") != DBIERR_NONE)
  274.         {
  275.             CloseDbAndExit(phDb);
  276.         }                   
  277.     }
  278.     return rslt;
  279. }
  280.  
  281. //===============================================================
  282. //  Function:
  283. //          CloseDbAndExit(phDb);
  284. //
  285. //  Input:  phDb - Pointer to the database handle
  286. //
  287. //  Return: IDAPI return code after DbiCloseDatabase() and DbiExit().
  288. //
  289. //  Description:
  290. //          Close the supplied database and exit IDAPI.
  291. //================================================================
  292. DBIResult
  293. CloseDbAndExit (phDBIDb phDb)
  294. {
  295.     DBIResult   rslt;
  296.  
  297.     // Close the supplied database
  298.     rslt = DbiCloseDatabase(phDb);
  299.     if (ChkRslt(rslt, "CloseDatabase") == DBIERR_NONE)
  300.     {
  301.         rslt = DbiDebugLayerOptions(0, NULL);
  302.         ChkRslt(rslt, "DebugLayerOptions");
  303.  
  304.         rslt = DbiExit();
  305.         ChkRslt(rslt, "Exit");
  306.     }
  307.     return rslt;
  308. }
  309.  
  310.  
  311. //=====================================================================
  312. //  Function:
  313. //          FillTable(hDb, szTblName, szTblType, NumRecs);
  314. //
  315. //  Input:  hDb         - The database handle
  316. //          szTblName   - Name of the table to fill
  317. //          szTblTyps   - Type of the table to fill
  318. //          NumRecs     - The number of records to insert
  319. //
  320. //  Return: DBIResult - success?
  321. //
  322. //  Description:
  323. //          This function adds the specified number of records to
  324. //          the table. The records will contain random data.
  325. //=====================================================================
  326. DBIResult
  327. FillTable (hDBIDb hDb, pCHAR szTblName, pCHAR szTblType, DFLOAT NumRecs)
  328. {
  329.     DBIResult   rslt;           // Return value from IDAPI functions
  330.     DFLOAT      fRecCount;      // Loop variable = count of records
  331.     UINT16      FldCntr;        // Field counter
  332.     pBYTE       pRecBuf;        // Pointer to the record buffer
  333.     FLDDesc     fldDesc;        // Field Descriptor
  334.     CURProps    TblProps;       // Table descriptor
  335.     hDBICur     hCur;           // Handle to the table
  336.     hDBICur     hFldList;       // Handle to the field list table
  337.  
  338.     // Echo the message that the records are being inserted.
  339.     Screen("    Inserting %.0f records into the table...", NumRecs);
  340.  
  341.     // Open the table.
  342.     rslt = DbiOpenTable(hDb, szTblName, szTblType, NULL, NULL, 0,
  343.                         dbiREADWRITE, dbiOPENSHARED, xltFIELD, FALSE,
  344.                         NULL, &hCur);
  345.     if (ChkRslt(rslt, "OpenTable") != DBIERR_NONE)
  346.     {
  347.         return rslt;
  348.     }
  349.  
  350.     // Create an in-memory table that contains a list of fields. Note
  351.     //   that logical (i.e. IDAPI types), are being requested instead of
  352.     //   driver types.
  353.     rslt = DbiOpenFieldList(hDb, szTblName, szTblType, FALSE, &hFldList);
  354.     if (ChkRslt(rslt, "OpenFieldList") != DBIERR_NONE)
  355.     {
  356.         rslt = DbiCloseCursor(&hCur);
  357.         return(ChkRslt(rslt, "CloseCursor"));
  358.     }
  359.  
  360.     // Append the records if the list and table are available
  361.     if (hCur && hFldList)
  362.     {
  363.         //  Allocate a record buffer
  364.         rslt = DbiGetCursorProps(hCur, &TblProps);
  365.         ChkRslt(rslt, "GetCursorProps");
  366.  
  367.         pRecBuf = (pBYTE) malloc(TblProps.iRecBufSize * sizeof(CHAR));
  368.         if (pRecBuf == NULL)
  369.         {
  370.             Screen("    Error - Out of memory");
  371.             rslt = DbiCloseCursor(&hCur);
  372.             ChkRslt(rslt, "CloseCursor");
  373.             rslt = DbiCloseCursor(&hFldList);
  374.             ChkRslt(rslt, "CloseCursor");
  375.             return DBIERR_NOMEMORY;
  376.         }
  377.  
  378.         // Loop until the specified number of records have been written
  379.         //   to the table.
  380.         for (fRecCount = 0; fRecCount < NumRecs; fRecCount++)
  381.         {
  382.             //  Make sure we're starting with a clean record buffer.
  383.             rslt = DbiInitRecord(hCur, pRecBuf);
  384.             ChkRslt(rslt, "InitRecord");
  385.  
  386.             // Start at the beginning of the field list. Setting the
  387.             //   cursor to the start of the table (i.e. BOF), does not leave
  388.             //   you on a record. You are effectively left on a crack.
  389.             //   Because of this, you will need to go to the next record in
  390.             //   the table to reach the first record of the table.
  391.             FldCntr = 1;
  392.             rslt = DbiSetToBegin(hFldList);
  393.             ChkRslt(rslt, "SetToBegin");
  394.  
  395.             // This loop will use the previously opened field list to
  396.             //   determine what type of data is inserted into the table.
  397.             while (DbiGetNextRecord(hFldList, dbiNOLOCK,
  398.                                     (pBYTE) &fldDesc, NULL)
  399.                    == DBIERR_NONE)
  400.             {
  401.                 // Put field data into the record buffer.
  402.                 PutFieldSample(hCur, pRecBuf, FldCntr, &fldDesc);
  403.                 FldCntr++;
  404.             }
  405.  
  406.             // All fields have been inserted into the record buffer. Now
  407.             //   we need to append the record to the table...
  408.             rslt = DbiAppendRecord(hCur, pRecBuf);
  409.             ChkRslt(rslt, "InsertRecord");
  410.  
  411.             // Make sure to close all blobs (opened when data was put into
  412.             //   the record buffer).
  413.             FldCntr = 1;
  414.  
  415.             rslt = DbiSetToBegin(hFldList);
  416.             ChkRslt(rslt, "SetToBegin");
  417.  
  418.             while (DbiGetNextRecord(hFldList, dbiNOLOCK,
  419.                                     (pBYTE) &fldDesc, NULL)
  420.                    == DBIERR_NONE)
  421.             {
  422.                 if (fldDesc.iFldType == fldBLOB)
  423.                 {
  424.                     rslt = DbiFreeBlob(hCur, pRecBuf, FldCntr);
  425.                     ChkRslt(rslt, "FreeBlob");
  426.                 }
  427.                 FldCntr++;
  428.             }
  429.         }
  430.  
  431.         // Free allocated record buffer.
  432.         free((pCHAR) pRecBuf);
  433.     }
  434.  
  435.     // Clean up and return.
  436.     rslt = DbiCloseCursor(&hFldList);
  437.     ChkRslt(rslt, "CloseCursor");
  438.  
  439.     rslt = DbiCloseCursor(&hCur);
  440.     ChkRslt(rslt, "CloseCursor");
  441.  
  442.     return DBIERR_NONE;
  443. }
  444.  
  445. //===============================================================
  446. //  Function:
  447. //          CreateAndFillTable(hDb, pTblDesc, NumRecs, phCur);
  448. //
  449. //  Input:  hDb         - Database handle
  450. //          pTblDesc    - Pointer to a descriptor for the table to
  451. //                        create
  452. //          phCur       - Pointer to table cursor (NULL means do not
  453. //                        open the table after creating
  454. //
  455. //  Return: IDAPI return code.
  456. //
  457. //  Description:
  458. //          Create a table based on the table descriptor
  459. //          supplied. If "phCur != NULL" then the table will be opened,
  460. //          and the table cursor will be passed back through this parameter.
  461. //================================================================
  462. DBIResult
  463. CreateAndFillTable (hDBIDb hDb, pCRTblDesc pTblDesc, DFLOAT NumRecs,
  464.                     phDBICur phCur)
  465. {
  466.     DBIResult   rslt;
  467.  
  468.     Screen("  Creating table \"%s\"...", pTblDesc->szTblName);
  469.     rslt = DbiCreateTable(hDb, TRUE, pTblDesc);
  470.     if (ChkRslt(rslt, "CreateTable") == DBIERR_NONE)
  471.     {
  472.         // Call the routine that will fill the table.
  473.         rslt = FillTable(hDb, pTblDesc->szTblName, pTblDesc->szTblType,
  474.                          NumRecs);
  475.  
  476.         // Open the table if the create and fill worked.
  477.         if ((rslt == DBIERR_NONE) && phCur)
  478.         {
  479.             rslt = DbiOpenTable(hDb, pTblDesc->szTblName,
  480.                                 pTblDesc->szTblType, NULL, NULL, 0,
  481.                                 dbiREADWRITE, dbiOPENSHARED, xltFIELD,
  482.                                 FALSE, NULL, phCur);
  483.             ChkRslt(rslt, "OpenTable");
  484.         }
  485.     }
  486.     return rslt;
  487. }
  488.  
  489. //=====================================================================
  490. //  Function:
  491. //          DisplayInMemoryTable();
  492. //
  493. //  Input:  The cursor handle - which table to access
  494. //          DisplayNRecs      - How many records to display
  495. //                              (0 means all in the table)
  496. //
  497. //  Return: Result of displaying the records in the table
  498. //
  499. //  Description:
  500. //          This function will display all records in the table referenced
  501. //          by the cursor. This function is used to display
  502. //          in-memory and schema tables which do not support
  503. //          the use of ReadBlock ( which is used in DisplayTable )
  504. //
  505. //  Note:   This function will only display the columns
  506. //          correctly when using a fixed pitch font.
  507. //=====================================================================
  508. DBIResult
  509. DisplayInMemoryTable (hDBICur hCur, UINT32 uDisplayNRecs)
  510. {
  511.     DBIResult   rslt;               // IDAPI function return value
  512.     CURProps    TblProps;           // Table Properties
  513.     pFLDDesc    pFldDescs;          // List of fields
  514.     pBYTE       pRecBuf;            // Record Buffer
  515.     CHAR**      pszField;           // Array to contain the fields of the
  516.                                     // table.
  517.     CHAR*       szFormat;           // Contains an entire record (row)
  518.     CHAR        szTemp[MAXLEN] =""; // Temporary variable for reading data
  519.     UINT16      uFldNum;            // Loop variable
  520.     UINT32      uCurCountRec=0;     // Counter to keep track of how many
  521.                                     //   records have been displayed.
  522.  
  523.     const UINT16 uDefLength = 15;   // Default size of a field
  524.                                          
  525.     szFormat = (pCHAR) malloc(1600 * sizeof(CHAR));
  526.     if (szFormat == NULL)
  527.     {
  528.         return DBIERR_NOMEMORY;
  529.     }
  530.  
  531.     rslt = DbiGetCursorProps(hCur, &TblProps);
  532.     if (ChkRslt(rslt, "GetCursorProps") != DBIERR_NONE)
  533.     {
  534.         free(szFormat);
  535.         return rslt;
  536.     }
  537.  
  538.     // Allocate space for the record buffer
  539.     pRecBuf = (pBYTE) malloc(TblProps.iRecBufSize * sizeof(BYTE));
  540.     if (pRecBuf == NULL)
  541.     {
  542.         Screen("    Error - Out of memory");
  543.         return DBIERR_NOMEMORY;
  544.     }
  545.  
  546.     // Allocate enough space to contain information (Field Descriptors)
  547.     // about all the fields in the answer table.
  548.     pFldDescs = (pFLDDesc) malloc(TblProps.iFields * sizeof(FLDDesc));
  549.     if (pFldDescs == NULL)
  550.     {
  551.         free(szFormat);
  552.         free(pRecBuf);
  553.         Screen("    Error - Out of memory");
  554.         return DBIERR_NOMEMORY;
  555.     }
  556.  
  557.     // Get information about the fields.
  558.     rslt = DbiGetFieldDescs(hCur, pFldDescs);
  559.     ChkRslt(rslt, "GetFieldDescs");
  560.  
  561.     // Allocate enough buffers to contain data from the fields in the
  562.     // answer table. Also sets the width of non-fldZSTRING fields
  563.     // (all data will be converted to strings for display )
  564.     pszField = (CHAR**) malloc(TblProps.iFields * sizeof(CHAR*));
  565.  
  566.     // Set up formatting for the fields
  567.     SetupFields(TblProps, pFldDescs, pszField, uDefLength);
  568.  
  569.     // Display the names of the fields, aligned by column.
  570.     strcpy(szFormat,"\r\n        ");
  571.     for (uFldNum = 0; uFldNum < TblProps.iFields; uFldNum++)
  572.     {
  573.         sprintf(szTemp, "%-*s\t", pFldDescs[uFldNum].iUnits1 + 1,
  574.                  pFldDescs[uFldNum].szName);
  575.         strcat(szFormat, szTemp);
  576.     }
  577.  
  578.     // Display the header.
  579.     Screen(szFormat);
  580.  
  581.     // Get records from the table until the end of the table is reached
  582.     //   or the maximum number of records is reached.
  583.     //   Note that not all field types are supported. All supported field
  584.     //   types are displayed as strings.
  585.     if (uDisplayNRecs == 0)
  586.     {
  587.         uDisplayNRecs = (UINT16)-1; // uDisplayNRecs is unsigned, so
  588.                                     // -1 maximizes the value
  589.     }
  590.  
  591.     while ((uCurCountRec < uDisplayNRecs) &&
  592.            ((rslt = DbiGetNextRecord(hCur, dbiNOLOCK, pRecBuf, NULL))
  593.             == DBIERR_NONE))
  594.     {
  595.         // Fill the record buffer with the field values.
  596.         uCurCountRec++;
  597.         GetFields(hCur, pFldDescs, pRecBuf, pszField, uDefLength);
  598.  
  599.         // Initialize szFormat to all zeroes.
  600.         memset(szFormat, 0, sizeof(szFormat));
  601.  
  602.         // Add leading blank space to the record.
  603.         strcpy(szFormat,"        ");
  604.  
  605.         // Add each field to be displayed, making certain that the
  606.         //   columns line up.
  607.         for (uFldNum = 0; uFldNum < TblProps.iFields; uFldNum++)
  608.         {
  609.             sprintf(szTemp, " %-*s\t", pFldDescs[uFldNum].iUnits1,
  610.             pszField[uFldNum]);
  611.             strcat(szFormat, szTemp);
  612.         }
  613.  
  614.         // Display the record.
  615.         Screen(szFormat);
  616.     }
  617.  
  618.     // Expect the End-Of-File error - just means that there
  619.     //   are no more records in the table.
  620.     if (rslt == DBIERR_EOF)
  621.         rslt = DBIERR_NONE;
  622.  
  623.     // Clean up.
  624.     for (uFldNum = 0; uFldNum < TblProps.iFields; uFldNum++)
  625.     {
  626.         free(pszField[uFldNum]);
  627.     }
  628.  
  629.     free(pszField);
  630.     free(pFldDescs);
  631.     free(pRecBuf);
  632.     free(szFormat);
  633.  
  634.     return rslt;
  635. }
  636.  
  637. //=====================================================================
  638. //  Function:
  639. //          DisplayTable();
  640. //
  641. //  Input:  The cursor handle - which table to access
  642. //          DisplayNRecs      - How many records to display
  643. //                              (0 means display all records in the table)
  644. //
  645. //  Return: Result of displaying the records in the table
  646. //
  647. //  Description:
  648. //          This function will display all records in the table referenced
  649. //          by the cursor. Records are read from the table in blocks,
  650. //          making this function faster than the DisplayInMemoryTable()
  651. //          function.
  652. //
  653. //  Note:   This function will only display the columns
  654. //          correctly when using a fixed pitch font.
  655. //=====================================================================
  656. DBIResult
  657. DisplayTable (hDBICur hCur, UINT32 uDisplayNRecs)
  658. {
  659.     DBIResult   rslt;               // IDAPI function return value
  660.     CURProps    TblProps;           // Table Properties
  661.     pFLDDesc    pFldDescs;          // List of fields
  662.     pBYTE       pRecBuf;            // Record Buffer
  663.     CHAR**      pszField;           // Array to contain the fields of the
  664.                                     //   table.
  665.     pCHAR       szFormat;           // Contains an entire record (row)
  666.     CHAR        szTemp[MAXLEN] =""; // Temporary variable for reading data
  667.     UINT16      uFldNum;            // Loop variable
  668.     UINT16      uMaxNumRecs = 30;   // Maximum number of records to read
  669.                                     // from the table at a time
  670.     UINT32      uNumRecs;           // Number of records read in from the
  671.                                     //   table.
  672.     UINT16      uCount;             // Loop Variable
  673.     UINT32      uCurCountRec = 0;   // Counter to keep track of how many
  674.                                     //   records have been displayed.
  675.  
  676.     const UINT16 uDefLength = 15;   // Default size of a field
  677.  
  678.     // Allocate memory for the format string
  679.     szFormat = (pCHAR) malloc(1400 * sizeof(CHAR));
  680.     if (szFormat == NULL)
  681.     {
  682.         Screen("    Error - Out of memory");
  683.         return DBIERR_NOMEMORY;
  684.     }
  685.  
  686.     // Set szFormat == "".
  687.     szFormat[0] = 0;
  688.  
  689.     // Get the size of the record buffer.
  690.     rslt = DbiGetCursorProps(hCur, &TblProps);
  691.     if (ChkRslt(rslt, "GetCursorProps") != DBIERR_NONE)
  692.     {
  693.         free(szFormat);
  694.         return rslt;
  695.     } 
  696.  
  697.     // Allocate space for the record buffer.
  698.     pRecBuf = (pBYTE) malloc(TblProps.iRecBufSize * sizeof(BYTE) *
  699.                              uMaxNumRecs);
  700.     if (pRecBuf == NULL)
  701.     {
  702.         free(szFormat);
  703.         Screen("    Error - Out of memory");
  704.         return DBIERR_NOMEMORY;
  705.     }
  706.  
  707.     // Allocate enough space to contain information (Field Descriptors)
  708.     //   about all the fields in the answer table.
  709.     pFldDescs = (pFLDDesc) malloc(TblProps.iFields * sizeof(FLDDesc));
  710.     if (pFldDescs == NULL)
  711.     {
  712.         free(szFormat);
  713.         free(pRecBuf);
  714.         Screen("    Error - Out of memory");
  715.         return DBIERR_NOMEMORY;
  716.     }
  717.  
  718.     // Get information about the fields.
  719.     rslt = DbiGetFieldDescs(hCur, pFldDescs);
  720.     ChkRslt(rslt, "GetFieldDescs");
  721.  
  722.     // Allocate enough buffers to contain data from the fields in the
  723.     //   answer table. Also sets the width of non-fldZSTRING fields
  724.     //   (all data will be converted to strings for display )
  725.     pszField = (CHAR**) malloc(TblProps.iFields * sizeof(CHAR*));
  726.     if (pszField == NULL)
  727.     {
  728.         free(szFormat);
  729.         free(pRecBuf);
  730.         free(pFldDescs);
  731.         Screen("    Error - Out of memory");
  732.         return DBIERR_NOMEMORY;
  733.     }
  734.  
  735.     SetupFields(TblProps, pFldDescs, pszField, uDefLength);
  736.  
  737.     // Format the names of the fields, aligned by column.
  738.     strcpy(szFormat,"\r\n        ");
  739.     for (uFldNum = 0; uFldNum < TblProps.iFields; uFldNum++)
  740.     {
  741.         sprintf(szTemp, "%-*s\t", pFldDescs[uFldNum].iUnits1 + 1,
  742.                  pFldDescs[uFldNum].szName);
  743.         strcat(szFormat, szTemp);
  744.     }
  745.  
  746.     // Display the header information ( field names ).
  747.     Screen(szFormat);
  748.  
  749.     // Get records from the table until the end of the table is reached.
  750.     //   Note that not all field types are supported. All supported field
  751.     //   types are displayed as strings.
  752.     uNumRecs = uMaxNumRecs; // Set the number of records to read from the
  753.                             //   table as a block.
  754.     // if uCurCoutRec == 0, display all the records in the table.
  755.     if (uDisplayNRecs == 0)
  756.     {
  757.         uDisplayNRecs = (UINT16)-1; // uDisplayNRecs is unsigned, so
  758.                                     // -1 maximizes the value
  759.     }
  760.  
  761.     // Get the records from the table and display.
  762.     do
  763.     {
  764.         // Limit the number of records to be read from the table -
  765.         //   do not want to display more total records than is specified
  766.         //   in uDisplayNRecs.
  767.         if ((uNumRecs + uCurCountRec) > uDisplayNRecs)
  768.         {
  769.             uNumRecs = uDisplayNRecs - uCurCountRec;
  770.         }
  771.  
  772.         // Read a block of records - reading more than one record at a
  773.         //   time is more efficient than reading records one at a time from
  774.         //   the table.
  775.         rslt = DbiReadBlock(hCur, &uNumRecs, pRecBuf);
  776.         if ((rslt != DBIERR_EOF) && (rslt != DBIERR_NONE))
  777.         {
  778.             ChkRslt(rslt, "ReadBlock");
  779.             free(szFormat);
  780.             for (uFldNum = 0; uFldNum < TblProps.iFields; uFldNum++)
  781.             {
  782.                 free(pszField[uFldNum]);
  783.             }
  784.             free(pszField);
  785.             free(pFldDescs);
  786.             free(pRecBuf);
  787.             return rslt;
  788.         }
  789.  
  790.         for (uCount=0; uCount < uNumRecs; uCount++)
  791.         {
  792.             uCurCountRec++;
  793.  
  794.             // Fill the Record buffer with the field values.
  795.             GetFields(hCur, pFldDescs,
  796.                       &pRecBuf[uCount * TblProps.iRecBufSize],
  797.                       pszField, uDefLength);
  798.  
  799.             // Add leading blank space to the record.
  800.             strcpy(szFormat,"        ");
  801.  
  802.             // Add each field to be displayed, making certain that the
  803.             //   columns line up.
  804.             for (uFldNum = 0; uFldNum < TblProps.iFields; uFldNum++)
  805.             {
  806.                 sprintf(szTemp, " %-*s\t", pFldDescs[uFldNum].iUnits1,
  807.                 pszField[uFldNum]);
  808.                 strcat(szFormat, szTemp);
  809.             }
  810.  
  811.             // Display the record.
  812.             Screen(szFormat);
  813.         } // for ... uCount
  814.  
  815.         // While ReadBlock reads as many records as are supposed to be
  816.         //   batched (uMaxNumRecs) and the maximum number of records have not
  817.         //   been read from the table. If fewer than uMaxNumRecs records were
  818.         //   read, we reached the end of the table.
  819.     } while ((uNumRecs == uMaxNumRecs) && (uCurCountRec < uDisplayNRecs));
  820.  
  821.     // Expect the End-Of-File error - just means that there
  822.     //   are no more records in the table.
  823.     if (rslt == DBIERR_EOF)
  824.     {
  825.         rslt = DBIERR_NONE;
  826.     }
  827.  
  828.     // Clean up.
  829.     for (uFldNum = 0; uFldNum < TblProps.iFields; uFldNum++)
  830.     {
  831.         free(pszField[uFldNum]);
  832.     }
  833.     free(szFormat);
  834.     free(pszField);
  835.     free(pFldDescs);
  836.     free(pRecBuf);
  837.  
  838.     return rslt;
  839. }
  840.  
  841. //=====================================================================
  842. //  Function:
  843. //          GetFields(hCur, pFldDescs, pRecBuf, pszField, uDefLength)
  844. //
  845. //  Input:  hCur        - Handle to the Cursor
  846. //          pFldDescs   - Field Descriptor
  847. //          pRecBuf     - Record buffer - contains the record from
  848. //                        which the field values are to be retrieved.
  849. //          pszField    - Fields in the table
  850. //          uDefLength  - Default length of a field
  851. //
  852. //  Return: Success of the operation.
  853. //
  854. //  Description:
  855. //          This function is used to extract all field values from
  856. //          a record and place them into an array of strings.
  857. //=====================================================================
  858. DBIResult
  859. GetFields (hDBICur hCur, pFLDDesc pFldDescs, pBYTE pRecBuf,
  860.            CHAR ** pszField, UINT16 uDefLength)
  861. {
  862.     DBIResult   rslt;           // Return value from IDAPI functions
  863.     CURProps    TblProps;       // Properties of the table
  864.     UINT16      uFldNum;        // Loop Counter - used to determine the
  865.                                 // current field.
  866.     CHAR        szTemp[MAXLEN] =""; // Temporary variable for reading data
  867.     UINT32      ulBlobSize;     // Size of the BLOB
  868.     DFLOAT      lfFloat;        // Float value
  869.     BOOL        bIsBlank;       // Check if the field is blank
  870.  
  871.     rslt = DbiGetCursorProps(hCur, &TblProps);
  872.     if (ChkRslt(rslt, "GetCursorProps") != DBIERR_NONE)
  873.     {
  874.         return rslt;
  875.     }
  876.  
  877.     // Get the field values from the record. Gets each field from
  878.     //   the table, placing the results in the pszField variable.
  879.     for (uFldNum = 0; uFldNum < TblProps.iFields; uFldNum++)
  880.     {
  881.         switch (pFldDescs[uFldNum].iFldType)
  882.         {
  883.             case fldBYTES:
  884.             case fldZSTRING:
  885.                 rslt = DbiGetField(hCur, (UINT16)(uFldNum+1), pRecBuf,
  886.                                    (pBYTE) pszField[uFldNum],
  887.                                    &bIsBlank);
  888.                 ChkRslt(rslt, "GetField");
  889.                 break;
  890.             case fldFLOAT:
  891.                 rslt = DbiGetField(hCur, (UINT16)(uFldNum+1), pRecBuf,
  892.                                    (pBYTE) szTemp, &bIsBlank);
  893.                 ChkRslt(rslt, "GetField");
  894.                 if (! bIsBlank)
  895.                 {
  896.                     if (pFldDescs[uFldNum].iSubType == fldstMONEY)
  897.                     {
  898.                         sprintf(pszField[uFldNum], "$%.2lf",
  899.                                 *(DFLOAT *)szTemp);
  900.                     }
  901.                     else
  902.                     {
  903.                         sprintf(pszField[uFldNum], "%.1lf",
  904.                                 *(DFLOAT *)szTemp);
  905.                     }
  906.                     // Format the number string.
  907.                     FormatNumber(pszField[uFldNum]);
  908.                 }
  909.                 break;
  910.             case fldBCD:
  911.                 rslt = DbiGetField(hCur, (UINT16)(uFldNum+1), pRecBuf,
  912.                                    (pBYTE) szTemp, &bIsBlank);
  913.                 ChkRslt(rslt, "GetField");
  914.                 if ((! bIsBlank) && (szTemp[0]!='\0'))
  915.                 {
  916.                     rslt = DbiBcdToFloat((FMTBcd *)szTemp,
  917.                             &lfFloat);
  918.                     ChkRslt(rslt, "    BcdToFloat");
  919.  
  920.                     sprintf(pszField[uFldNum], "%.*lf",
  921.                             pFldDescs[uFldNum].iUnits2, lfFloat);
  922.                     FormatNumber(pszField[uFldNum]);
  923.                 }
  924.                 break;
  925.             case fldDATE:
  926.                 rslt = DbiGetField(hCur, (UINT16)(uFldNum+1), pRecBuf,
  927.                                    (pBYTE) szTemp, &bIsBlank);
  928.                 ChkRslt(rslt, "GetField");
  929.                 if (! bIsBlank)
  930.                 {
  931.                     // Format the date. FormatDate defined in
  932.                     // SNIPTOOL.C
  933.                     FormatDate(*(DBIDATE *)szTemp,
  934.                                pszField[uFldNum]);
  935.                 }
  936.                 break;
  937.             case fldTIME:
  938.                 rslt = DbiGetField(hCur, (UINT16)(uFldNum+1), pRecBuf,
  939.                                    (pBYTE)&szTemp, &bIsBlank);
  940.                 ChkRslt(rslt, "GetField");
  941.                 if (! bIsBlank)
  942.                 {
  943.                     FormatTime(*(TIME *)szTemp, pszField[uFldNum]);
  944.                 }
  945.                 break;
  946.             case fldTIMESTAMP:
  947.                 rslt = DbiGetField(hCur, (UINT16)(uFldNum+1), pRecBuf,
  948.                                    (pBYTE) szTemp, &bIsBlank);
  949.                 ChkRslt(rslt, "GetField");
  950.                 if (! bIsBlank)
  951.                 {
  952.                     FormatTimeStamp(*(TIMESTAMP *)szTemp,
  953.                                     pszField[uFldNum]);
  954.                 }
  955.                 break;
  956.            case fldINT16:
  957.                 rslt = DbiGetField(hCur, (UINT16)(uFldNum+1), pRecBuf,
  958.                                    (pBYTE) szTemp, &bIsBlank);
  959.                 ChkRslt(rslt, "GetField");
  960.                 if (! bIsBlank)
  961.                 {
  962.                     sprintf(pszField[uFldNum], "%d", *(INT16 *)szTemp);
  963.                 }
  964.                 break;
  965.             case fldUINT16:
  966.                 rslt = DbiGetField(hCur, (UINT16)(uFldNum+1), pRecBuf,
  967.                                    (pBYTE) szTemp, &bIsBlank);
  968.                 ChkRslt(rslt, "GetField");
  969.                 if (! bIsBlank)
  970.                 {
  971.                     sprintf(pszField[uFldNum], "%u", *(UINT16 *)szTemp);
  972.                 }
  973.                 break;
  974.             case fldINT32:
  975.                 rslt = DbiGetField(hCur, (UINT16)(uFldNum+1), pRecBuf,
  976.                                    (pBYTE) szTemp, &bIsBlank);
  977.                 ChkRslt(rslt, "GetField");
  978.                 if (! bIsBlank)
  979.                 {
  980.                     sprintf(pszField[uFldNum], "%ld",
  981.                             *(INT32 *)szTemp);
  982.                 }
  983.                 break;
  984.             case fldUINT32:
  985.                 rslt = DbiGetField(hCur, (UINT16)(uFldNum+1), pRecBuf,
  986.                                    (pBYTE) szTemp, &bIsBlank);
  987.                 ChkRslt(rslt, "GetField");
  988.                 if (! bIsBlank)
  989.                 {
  990.                     sprintf(pszField[uFldNum], "%lu",
  991.                             *(UINT32 *)szTemp);
  992.                 }
  993.                 break;
  994.             case fldBOOL:
  995.                 rslt = DbiGetField(hCur, (UINT16)(uFldNum+1), pRecBuf,
  996.                                    (pBYTE) szTemp, &bIsBlank);
  997.                 ChkRslt(rslt, "GetField");
  998.                 if (! bIsBlank)
  999.                 {
  1000.                     if (*(BOOL*)szTemp == 0)
  1001.                     {
  1002.                         strcpy(pszField[uFldNum], "No");
  1003.                     }
  1004.                     else
  1005.                     {
  1006.                         strcpy(pszField[uFldNum], "Yes");
  1007.                     }
  1008.                 }
  1009.                 break;
  1010.             case fldBLOB:
  1011.                 // Display the first uDefLength characters of
  1012.                 //   Memo BLOB fields.
  1013.                 if (pFldDescs[uFldNum].iSubType == fldstMEMO)
  1014.                 {
  1015.                     rslt = DbiOpenBlob(hCur, pRecBuf, (UINT16)(uFldNum + 1),
  1016.                                        dbiREADONLY);
  1017.                     ChkRslt(rslt, "OpenBlob");
  1018.  
  1019.                     //Determine the size of the BLOB
  1020.                     rslt = DbiGetBlobSize(hCur, pRecBuf, (UINT16)(uFldNum + 1),
  1021.                                           &ulBlobSize);
  1022.                     ChkRslt(rslt, "GetBlobSize");
  1023.  
  1024.                     // Determine the maximum amount to read
  1025.                     ulBlobSize = min((UINT32) ulBlobSize,
  1026.                                      (UINT32) (uDefLength - 2));
  1027.  
  1028.                     // Get the BLOB from the table
  1029.                     rslt = DbiGetBlob(hCur, pRecBuf, (UINT16)(uFldNum + 1), 0,
  1030.                                       ulBlobSize, (pBYTE) pszField[uFldNum],
  1031.                                       &ulBlobSize);
  1032.                     ChkRslt(rslt, "GetBlob");
  1033.  
  1034.                     // Add the NULL terminator to the string.
  1035.                     pszField[uFldNum][(UINT16)ulBlobSize] = 0;
  1036.  
  1037.                     // Free the blob from memory.
  1038.                     rslt = DbiFreeBlob(hCur, pRecBuf, (UINT16)(uFldNum + 1));
  1039.                     ChkRslt(rslt, "FreeBlob");
  1040.                 }
  1041.                 else
  1042.                 {
  1043.                     strcpy(pszField[uFldNum], "Can't Display");
  1044.                 }                        
  1045.                 break;
  1046.             default:
  1047.                 strcpy(pszField[uFldNum], "Can't Display");
  1048.                 break;
  1049.         }
  1050.  
  1051.         // Initialize the string in case the field was blank.
  1052.         if (bIsBlank)
  1053.         {
  1054.             strcpy(pszField[uFldNum], "");
  1055.             bIsBlank = FALSE;
  1056.         }
  1057.     }
  1058.     return DBIERR_NONE;
  1059. }
  1060.  
  1061. //=====================================================================
  1062. //  Function:
  1063. //          SetupFields(TblProps, pFldDescs, pszField, uDefLength)
  1064. //
  1065. //  Input:  TblProps    - Properties of the Table
  1066. //          pFldDescs   - Field Descriptor
  1067. //          pszField    - Fields in the table
  1068. //          uDefLength  - Default length of a field
  1069. //
  1070. //  Return: DBIERR_NONE (success)
  1071. //
  1072. //  Description:
  1073. //          This function sets up the formatting of the fields.
  1074. //=====================================================================
  1075. DBIResult
  1076. SetupFields (CURProps TblProps, pFLDDesc pFldDescs, CHAR** pszField,
  1077.              UINT16 uDefLength)
  1078. {
  1079.     UINT16      uFldNum;            // Loop variable
  1080.  
  1081.     for (uFldNum = 0; uFldNum < TblProps.iFields; uFldNum++)
  1082.     {
  1083.         // Allocate enough space to contain the data in each field.
  1084.         switch (pFldDescs[uFldNum].iFldType)
  1085.         {
  1086.             case fldBYTES:
  1087.             case fldZSTRING:
  1088.                 pszField[uFldNum] = (CHAR*)malloc((pFldDescs[uFldNum].iLen
  1089.                                                   * sizeof(CHAR)));
  1090.                 if (MAXLEN - 4 < pFldDescs[uFldNum].iLen)
  1091.                 {
  1092.                     pFldDescs[uFldNum].iUnits1 = MAXLEN-4;
  1093.                     pFldDescs[uFldNum].iLen    = MAXLEN-3;
  1094.                 }
  1095.                 // Adjust if the field is smaller than it's description.
  1096.                 if (pFldDescs[uFldNum].iLen <
  1097.                     strlen(pFldDescs[uFldNum].szName))
  1098.                 {
  1099.                     pFldDescs[uFldNum].iUnits1 =
  1100.                                      (UINT16)strlen(pFldDescs[uFldNum].szName);
  1101.                     pFldDescs[uFldNum].iLen    =
  1102.                                      (UINT16)(pFldDescs[uFldNum].iUnits1 - 1);
  1103.                 }
  1104.                 break;
  1105.             case fldFLOAT:
  1106.             case fldDATE:
  1107.             case fldINT16:
  1108.             case fldUINT16:
  1109.             case fldINT32:
  1110.             case fldUINT32:
  1111.             case fldBOOL:
  1112.             case fldBLOB:
  1113.             case fldBCD:
  1114.                 pszField[uFldNum] = (CHAR*)malloc((uDefLength *
  1115.                                                   sizeof(CHAR)));
  1116.                 // Set the width of the field as it will be displayed
  1117.                 pFldDescs[uFldNum].iUnits1 = (UINT16)(uDefLength-1);
  1118.                 pFldDescs[uFldNum].iLen    = (UINT16)uDefLength;
  1119.                 // Adjust if the field is smaller than it's description
  1120.                 if (pFldDescs[uFldNum].iLen <
  1121.                     strlen(pFldDescs[uFldNum].szName))
  1122.                 {
  1123.                     pFldDescs[uFldNum].iUnits1 =
  1124.                                     (UINT16)strlen(pFldDescs[uFldNum].szName);
  1125.                     pFldDescs[uFldNum].iLen    =
  1126.                                     (UINT16)(pFldDescs[uFldNum].iUnits1 - 1);
  1127.                 }
  1128.                 break;
  1129.             case fldTIMESTAMP:
  1130.                 pszField[uFldNum] = (CHAR*)malloc((36 * sizeof(CHAR)));
  1131.                 // Set the width of the field as it will be displayed.
  1132.                 pFldDescs[uFldNum].iUnits1 = 36;
  1133.                 pFldDescs[uFldNum].iLen    = 35;
  1134.                 // Adjust if the field is smaller than it's description.
  1135.                 if (pFldDescs[uFldNum].iLen <
  1136.                     strlen(pFldDescs[uFldNum].szName))
  1137.                 {
  1138.                     pFldDescs[uFldNum].iUnits1 =
  1139.                                    (UINT16)strlen(pFldDescs[uFldNum].szName);
  1140.                     pFldDescs[uFldNum].iLen    =
  1141.                                    (UINT16)(pFldDescs[uFldNum].iUnits1 - 1);
  1142.                 }
  1143.                 break;
  1144.             case fldTIME:
  1145.                 pszField[uFldNum] = (CHAR*)malloc((20 * sizeof(CHAR)));
  1146.                 // Set the width of the field as it will be displayed.
  1147.                 pFldDescs[uFldNum].iUnits1 = 20;
  1148.                 pFldDescs[uFldNum].iLen    = 19;
  1149.                 // Adjust if the field is smaller than it's description.
  1150.                 if (pFldDescs[uFldNum].iLen <
  1151.                     strlen(pFldDescs[uFldNum].szName))
  1152.                 {
  1153.                     pFldDescs[uFldNum].iUnits1 =
  1154.                                      (UINT16)strlen(pFldDescs[uFldNum].szName);
  1155.                     pFldDescs[uFldNum].iLen    =
  1156.                                      (UINT16)(pFldDescs[uFldNum].iUnits1 - 1);
  1157.                 }
  1158.               break;
  1159.             default:
  1160.                 // This field size will hold the 'Not Supported'
  1161.                 //   message.
  1162.                 pszField[uFldNum] = (CHAR*)malloc((uDefLength *
  1163.                                                   sizeof(CHAR)));
  1164.                 // Set the width of the field as it will be displayed.
  1165.                 pFldDescs[uFldNum].iUnits1 = uDefLength;
  1166.                 break;
  1167.         }
  1168.     }
  1169.  
  1170.     return DBIERR_NONE;
  1171. }
  1172.  
  1173. //=====================================================================
  1174. //  Function:
  1175. //          PutFieldSample(hCur, pRecBuf, FldNum, pfldDesc);
  1176. //
  1177. //  Input:  hCur     - The handle for the table to fill
  1178. //          pRecBuf  - The record buffer to insert data into
  1179. //          FldNum   - The field we are generating
  1180. //          pfldDesc - A descriptor for the field to generate
  1181. //
  1182. //  Return: Result returned from DbiPutField().
  1183. //
  1184. //  Description:
  1185. //          This routine is used to put field data into a record
  1186. //          buffer. Note that all LOGICAL field types are covered. You
  1187. //          will need to refer to documentation, or run the DRVCAPS.C
  1188. //          example for PHYSICAL to LOGICAL field mappings.
  1189. //=====================================================================
  1190. DBIResult
  1191. PutFieldSample (hDBICur hCur, pBYTE pRecBuf, UINT16 FldNum,
  1192.                 pFLDDesc pfldDesc)
  1193. {
  1194.     pBYTE       pBuf;       // Buffer which contains the record data
  1195.     DBIResult   rslt;       // Return value from Paradox functions
  1196.     INT16       i;          // Loop counter
  1197.     INT16       BlobSize;   // Size of the BLOB
  1198.  
  1199.     BOOL        Bool;       // Used for fldBOOL
  1200.     INT16       Int16;      // Used for fldINT16
  1201.     UINT16      uInt16;     // Used for fldUINT16
  1202.     INT32       Int32;      // Used for fldINT32
  1203.     UINT32      uInt32;     // Used for fldUINT32
  1204.     DFLOAT      Float;      // Used for fldFLOAT
  1205.     FMTBcd      fmtBcd;     // Used for fldBCD
  1206.     DBIDATE     Date;       // Used for fldDATE
  1207.     TIME        Time;       // Used for fldTIME
  1208.     TIMESTAMP   tStamp;     // Used for fldTIMESTAMP
  1209.     UINT16      month;      // Used in generating the date
  1210.     UINT16      day;        // Used in generating the date
  1211.     UINT16      year;       // Used in generating the date
  1212.     UINT16      hour;       // Used in generating the time
  1213.     UINT16      min;        // Used in generating the time
  1214.     UINT16      sec;        // Used in generating the time
  1215.  
  1216.     // Allocate a generic buffer (used for string and blob fields)
  1217.     pBuf = (pBYTE) malloc(4096 * sizeof(CHAR));
  1218.  
  1219.     // This switch contains sample code that demonstrates how to
  1220.     //   insert a field of any type into a record buffer. Random data
  1221.     //   is used by this example.
  1222.     switch (pfldDesc->iFldType)
  1223.     {
  1224.         case fldBYTES:
  1225.         case fldZSTRING:
  1226.             sprintf((pCHAR)pBuf, "Field #%d", FldNum);
  1227.  
  1228.             // Put the data into the record buffer.
  1229.             rslt = DbiPutField(hCur, FldNum, pRecBuf, pBuf);
  1230.             break;
  1231.         case fldDATE:
  1232.             // Randomly generate and encode a date.
  1233.             month = (UINT16)((rand() % 12) + 1);
  1234.             day = (UINT16)((rand() % 20) + 1);
  1235.             year = (UINT16)((rand() % 99) + 1900);
  1236.  
  1237.             rslt = DbiDateEncode(month, day, year, &Date);
  1238.             ChkRslt(rslt, "DateEncode");
  1239.  
  1240.             // Put the data into the record buffer.
  1241.             rslt = DbiPutField(hCur, FldNum, pRecBuf, (pBYTE) &Date);
  1242.             break;
  1243.         case fldBLOB:
  1244.             // Generate a blob size from 10-4010 bytes.
  1245.             BlobSize = (UINT16)((rand() % 4000) + 11);
  1246.  
  1247.             strcpy((pCHAR)pBuf, "BLOB example ");
  1248.             // Write data to the BLOB field
  1249.             for (i = 0; i < (BlobSize / 11); i++)
  1250.             {
  1251.                 strcat((pCHAR)pBuf, "BLOB test ");
  1252.             }
  1253.  
  1254.             // Init the blob header (contents defined by IDAPI client).
  1255.             if ((pfldDesc->iSubType == fldstFMTMEMO) ||
  1256.                  (pfldDesc->iSubType == fldstOLEOBJ) ||
  1257.                  (pfldDesc->iSubType == fldstGRAPHIC))
  1258.             {
  1259.                  memset(pBuf, 8, '\0');
  1260.             }
  1261.  
  1262.             // Open the blob prior to putting.
  1263.             rslt = DbiOpenBlob(hCur, pRecBuf, FldNum, dbiREADWRITE);
  1264.             ChkRslt(rslt, "OpenBlob");
  1265.  
  1266.             // Put the blob. Note that DbiFreeBlob() will be
  1267.             //   called after the record is inserted!
  1268.             rslt = DbiPutBlob(hCur, pRecBuf, FldNum, 0, BlobSize,
  1269.                               pBuf);
  1270.             break;
  1271.         case fldBOOL:
  1272.             // Boolean fields are either TRUE or FALSE.
  1273.             if ((rand() % 100) < 50)
  1274.             {
  1275.                 Bool = 1;
  1276.             }
  1277.             else
  1278.             {
  1279.                 Bool = 0;
  1280.             }
  1281.             // Put the data into the record buffer.
  1282.             rslt = DbiPutField(hCur, FldNum, pRecBuf, (pBYTE)&Bool);
  1283.             break;
  1284.         case fldINT16:
  1285.             Int16 = (INT16)(rand() % 255);
  1286.             // Put the data into the record buffer.
  1287.             rslt = DbiPutField(hCur, FldNum, pRecBuf, (pBYTE)&Int16);
  1288.             break;
  1289.         case fldBCD:
  1290.             Float = (rand() / 1.21324);
  1291.             rslt = DbiBcdFromFloat(&Float, pfldDesc->iUnits1,
  1292.                                    pfldDesc->iUnits2, &fmtBcd);
  1293.             ChkRslt(rslt, "BcdFromFloat");
  1294.  
  1295.             // Put the data into the record buffer.
  1296.             rslt = DbiPutField(hCur, FldNum, pRecBuf, (pBYTE)&fmtBcd);
  1297.             break;
  1298.         case fldLOCKINFO:
  1299.             rslt = 0;
  1300.             break;
  1301.         case fldUINT16:
  1302.             uInt16 = (UINT16)(rand() % 255);
  1303.             // Put the data into the record buffer.
  1304.             rslt = DbiPutField(hCur, FldNum, pRecBuf, (pBYTE)&uInt16);
  1305.             break;
  1306.         case fldINT32:
  1307.             // Put the data into the record buffer if it is not an
  1308.             //   auto-increment field.
  1309.             if (pfldDesc->iSubType != fldstAUTOINC)
  1310.             {
  1311.                 Int32 = (rand() % 10000);
  1312.                 rslt = DbiPutField(hCur, FldNum, pRecBuf, (pBYTE)&Int32);
  1313.             }
  1314.             else
  1315.             {
  1316.                 // Don't have to put a value into an auto-increment field,
  1317.                 // b  ut make certain we don't return an error.
  1318.                 rslt = 0;
  1319.             }
  1320.             break;
  1321.         case fldUINT32:
  1322.             uInt32 = (rand() % 10000);
  1323.             // Put the data into the record buffer.
  1324.             rslt = DbiPutField(hCur, FldNum, pRecBuf, (pBYTE)&uInt32);
  1325.             break;
  1326.         case fldFLOAT:
  1327.             Float = (rand() % 128000L);
  1328.             // Put the data into the record buffer.
  1329.             rslt = DbiPutField(hCur, FldNum, pRecBuf, (pBYTE)&Float);
  1330.             break;
  1331.         case fldTIME:
  1332.             // Randomize and encode a time value.
  1333.             hour = (UINT16)((rand() % 23) + 1);
  1334.             min = (UINT16)((rand() % 59) + 1);
  1335.             sec = (UINT16)(((rand() * 2) % 59999U) + 1);
  1336.  
  1337.             rslt = DbiTimeEncode(hour, min, sec, &Time);
  1338.             ChkRslt(rslt, "TimeEncode");
  1339.  
  1340.             // Put the data into the record buffer.
  1341.             rslt = DbiPutField(hCur, FldNum, pRecBuf, (pBYTE)&Time);
  1342.             break;
  1343.         case fldTIMESTAMP:
  1344.             // Encode a date and a time.
  1345.             month = (UINT16)((rand() % 12) + 1);
  1346.             day = (UINT16)((rand() % 20) + 1);
  1347.             year = (UINT16)((rand() % 99) + 1900);
  1348.  
  1349.             rslt = DbiDateEncode(month, day, year, &Date);
  1350.             ChkRslt(rslt, "DateEncode");
  1351.  
  1352.             hour = (UINT16)((rand() % 23) + 1);
  1353.             min = (UINT16)((rand() % 59) + 1);
  1354.             sec = (UINT16)(((rand() * 2) % 59999U) + 1);
  1355.  
  1356.             rslt = DbiTimeEncode(hour, min, sec, &Time);
  1357.             ChkRslt(rslt, "TimeEncode");
  1358.  
  1359.             // Now encode and put the time stamp.
  1360.             rslt = DbiTimeStampEncode(Date, Time, &tStamp);
  1361.             ChkRslt(rslt, "TimeStampEncode");
  1362.  
  1363.             // Put the data into the record buffer.
  1364.             rslt = DbiPutField(hCur, FldNum, pRecBuf, (pBYTE)&tStamp);
  1365.             break;
  1366.         case fldVARBYTES:
  1367.             // Init the size (1st two bytes) and contents.
  1368.             *((int *) pBuf) = (pfldDesc->iUnits1 - 2);
  1369.             for (i = 2; i < pfldDesc->iUnits1; i++)
  1370.             {
  1371.                 pBuf[i] = (UINT16)((rand() % 90) + 32);
  1372.             }
  1373.             pBuf[i] = '\0';
  1374.  
  1375.             // Put the data into the record buffer.
  1376.             rslt = DbiPutField(hCur, FldNum, pRecBuf, (pBYTE)pBuf);
  1377.             break;
  1378.         default:
  1379.             rslt = DBIERR_INVALIDFLDTYPE;
  1380.             break;
  1381.     }
  1382.  
  1383.     // Determine if any of the previous DbiPutField functions failed.
  1384.     ChkRslt(rslt, "PutField");
  1385.  
  1386.     // Clean up and return.
  1387.     free((pCHAR) pBuf);
  1388.     return rslt;
  1389. }
  1390.  
  1391. //=====================================================================
  1392. //  Function:
  1393. //          FormatDate (DBIDATE Date, pCHAR szDate)
  1394. //
  1395. //  Input:  DATE     - Date which needs to be formatted
  1396. //          szDate   - String to contain the formatted date
  1397. //
  1398. //  Return: Result returned from DbiDateDecode().
  1399. //
  1400. //  Description:
  1401. //          This function is used to format date fields according to the
  1402. //          settings in the IDAPI.CFG file.
  1403. //=====================================================================
  1404. DBIResult
  1405. FormatDate (DBIDATE Date, pCHAR szDate)
  1406. {
  1407.     DBIResult   rslt;       // Return Value from IDAPI
  1408.     FMTDate     fmtDate;    // Date Format
  1409.     UINT16      uDay;       // Day portion of date
  1410.     UINT16      uMonth;     // Month portion of date
  1411.     INT16       iYear;      // Year portion of date
  1412.                 
  1413.     // Get the formatting of the Date.
  1414.     rslt = DbiGetDateFormat(&fmtDate);
  1415.     ChkRslt(rslt, "    GetDateFormat");
  1416.  
  1417.     // Decode the date.
  1418.     rslt = DbiDateDecode(Date, &uMonth, &uDay, &iYear);
  1419.     ChkRslt(rslt, "DateDecode");
  1420.  
  1421.     // Determine if date should be displayed year-biased.
  1422.     if ((! fmtDate.bFourDigitYear) && fmtDate.bYearBiased)
  1423.     {
  1424.         iYear = (UINT16)(iYear + 1900);
  1425.     }
  1426.  
  1427.     if (! fmtDate.bFourDigitYear)
  1428.     {
  1429.         iYear = (UINT16)(iYear - 1900);
  1430.     }
  1431.  
  1432.     // Make certain the separator is not the
  1433.     //   escape character.
  1434.     if (! strcmp(fmtDate.szDateSeparator, "\\"))
  1435.     {
  1436.         strcpy(fmtDate.szDateSeparator, "/");
  1437.     }
  1438.  
  1439.     // Format the date.
  1440.     switch(fmtDate.iDateMode)
  1441.     {
  1442.         // MM/DD/YY - Month, Day, Year.
  1443.         case 0:
  1444.             sprintf(szDate,
  1445.                     "%0*d%s%0*d%s%0*d",
  1446.                     1 + fmtDate.bMonthLeadingZero,
  1447.                     uMonth,
  1448.                     fmtDate.szDateSeparator,
  1449.                     1 + fmtDate.bDayLeadingZero,
  1450.                     uDay,
  1451.                     fmtDate.szDateSeparator,
  1452.                     2,
  1453.                     iYear);
  1454.             break;
  1455.         // DD/MM/YY - Day, Month, Year.
  1456.         case 1:
  1457.             sprintf(szDate,
  1458.                     "%0*d%s%0*d%s%0*d",
  1459.                     1 + fmtDate.bDayLeadingZero,
  1460.                     uDay,
  1461.                     fmtDate.szDateSeparator,
  1462.                     1 + fmtDate.bMonthLeadingZero,
  1463.                     uMonth,
  1464.                     fmtDate.szDateSeparator,
  1465.                     2,
  1466.                     iYear);
  1467.             break;
  1468.         // YY/MM/DD - Year, Month, Day.
  1469.         case 2:
  1470.             sprintf(szDate,
  1471.                     "%0*d%s%0*d%s%0*d",
  1472.                     2,
  1473.                     iYear,
  1474.                     fmtDate.szDateSeparator,
  1475.                     1 + fmtDate.bMonthLeadingZero,
  1476.                     uMonth,
  1477.                     fmtDate.szDateSeparator,
  1478.                     1 + fmtDate.bDayLeadingZero,
  1479.                     uDay);
  1480.             break;
  1481.     }
  1482.     return rslt;
  1483. }
  1484.  
  1485. //=====================================================================
  1486. //  Function:
  1487. //          FormatTime (TIME Time, pCHAR szTime)
  1488. //
  1489. //  Input:  TIME     - Time which needs to be formatted
  1490. //          szTime   - String to contain the formatted time
  1491. //
  1492. //  Return: Result returned from DbiTimeDecode().
  1493. //
  1494. //  Description:
  1495. //          This function is used to format time fields according to
  1496. //          the settings in the IDAPI.CFG file.
  1497. //=====================================================================
  1498. DBIResult
  1499. FormatTime (TIME Time, pCHAR szTime)
  1500. {
  1501.     DBIResult   rslt;       // Return value from IDAPI functions
  1502.     FMTTime     fmtTime;    // Time format
  1503.     UINT16      uHour;      // Hour portion of the time
  1504.     UINT16      uMinute;    // Minute portion of the time
  1505.     UINT16      uMilSec;    // Second portion (in ms) of the time
  1506.     UINT16      uIsAm;      // Is Time AM?
  1507.     CHAR        szTemp[10]; // Temp buffer, used for AM, PM string
  1508.  
  1509.     // Get the formatting of the time.
  1510.     rslt = DbiGetTimeFormat(&fmtTime);
  1511.     ChkRslt(rslt, "GetTimeFormat");
  1512.  
  1513.     // Decode the time. 
  1514.     rslt = DbiTimeDecode(Time, &uHour, &uMinute, &uMilSec);
  1515.     ChkRslt(rslt, "TimeDecode");
  1516.  
  1517.     // Make certain the separator is not the
  1518.     //   escape character.
  1519.     if (fmtTime.cTimeSeparator == '\\')
  1520.     {
  1521.         fmtTime.cTimeSeparator  = '/';
  1522.     }
  1523.  
  1524.     // Check if time should be displayed in 12 or 24 hour format.
  1525.     if (fmtTime.bTwelveHour)
  1526.     {
  1527.         // Temporary variable used to determine if the time is AM or PM.
  1528.         uIsAm = uHour;
  1529.         uHour = (UINT16)(uHour % 12);
  1530.         if (uHour == 0)
  1531.         {
  1532.             uHour = 12;
  1533.         }
  1534.         // If AM, set uIsAm to TRUE, else set uIsAm to 0.
  1535.         if (uIsAm == uHour)
  1536.         {
  1537.             uIsAm = 1;
  1538.         }
  1539.         else
  1540.         {
  1541.             uIsAm = 0;
  1542.         }
  1543.     }
  1544.  
  1545.     // Format the hour and minute of the time.
  1546.     wsprintf(szTime, "%2u%c%02u",
  1547.              uHour,
  1548.              fmtTime.cTimeSeparator,
  1549.              uMinute);
  1550.  
  1551.     // Determine if seconds are to be displayed.
  1552.     if (fmtTime.bSeconds)
  1553.     {
  1554.         wsprintf(szTemp, "%c%02u",
  1555.                  fmtTime.cTimeSeparator,
  1556.                  (uMilSec / 1000));
  1557.  
  1558.         strcat(szTime, szTemp);
  1559.  
  1560.         // Determine if milliseconds are to be displayed.
  1561.         if (fmtTime.bMilSeconds)
  1562.         {
  1563.             wsprintf(szTemp, "%c%03u",
  1564.                      fmtTime.cTimeSeparator,
  1565.                      (uMilSec % 1000));
  1566.             strcat(szTime, szTemp);   
  1567.         }
  1568.     }
  1569.  
  1570.     // Add a string to the time if the time is 12-hour.
  1571.     if (fmtTime.bTwelveHour)
  1572.     {
  1573.         // Add a space to the format.
  1574.         strcat(szTime, " ");
  1575.         // If AM.
  1576.         if (uIsAm)
  1577.         {
  1578.             // Copy the AM string.
  1579.             strcat(szTime, fmtTime.szAmString);
  1580.         }
  1581.         else // otherwise it's PM.
  1582.         {
  1583.             // Copy the PM string.
  1584.             strcat(szTime, fmtTime.szPmString);
  1585.         }
  1586.     }
  1587.  
  1588.     return rslt;
  1589. }
  1590.  
  1591. //=====================================================================
  1592. //  Function:
  1593. //          FormatTimeStamp (TIMESTAMPE TimeStamp, pCHAR szTime)
  1594. //
  1595. //  Input:  TIME     - Time which needs to be formatted
  1596. //          szTime   - String to contain the formatted time
  1597. //
  1598. //  Return: Result returned from DbiTimeStampDecode().
  1599. //
  1600. //  Description:
  1601. //          This function is used to format TimeStamp fields according
  1602. //          to the settings in the IDAPI.CFG file. It calls the
  1603. //          FormatDate and FormatTime functions which are defined
  1604. //          above.
  1605. //=====================================================================
  1606. DBIResult
  1607. FormatTimeStamp (TIMESTAMP TimeStamp, pCHAR szTimeStamp)
  1608. {
  1609.     DBIResult   rslt;       // Return value from IDAPI functions
  1610.     TIME        Time;       // Time portion of the TimeStamp
  1611.     DBIDATE     Date;       // Date portion of the TimeStamp
  1612.     CHAR        szDate[15]; // Date string
  1613.     CHAR        szTime[20]; // Time String
  1614.  
  1615.     // Get the date and time components.
  1616.     rslt = DbiTimeStampDecode(TimeStamp, &Date, &Time);
  1617.     ChkRslt(rslt, "TimeStampDecode");
  1618.  
  1619.     // Get the Date format.
  1620.     FormatDate(Date, szDate);
  1621.  
  1622.     // Get the Time format.
  1623.     FormatTime(Time, szTime);
  1624.  
  1625.     // Format the TimeStamp.
  1626.     wsprintf(szTimeStamp, "%s, %s", szTime, szDate);
  1627.  
  1628.     return rslt;
  1629. }
  1630.  
  1631. //=====================================================================
  1632. //  Function:
  1633. //          FormatNumber(szNumber)
  1634. //
  1635. //  Input:  szNumber   - String that contains number in US format.
  1636. //
  1637. //  Return: Result returned from DbiGetNumberFormat().
  1638. //
  1639. //  Description:
  1640. //          This function is used to format number fields according to
  1641. //          the settings in the IDAPI.CFG file.
  1642. //=====================================================================
  1643. DBIResult
  1644. FormatNumber (pCHAR szNumber)
  1645. {
  1646.     DBIResult  rslt;            // Return value from IDAPI functions
  1647.     FMTNumber  fmtNumber;       // Number Format
  1648.     pCHAR      ptr;
  1649.     int        period = '.';    //Default US decimal separetor
  1650.  
  1651.     // Get the formatting of the Number
  1652.     rslt = DbiGetNumberFormat(&fmtNumber);
  1653.     ChkRslt(rslt, "    GetNumberFormat.");
  1654.  
  1655.     ptr = strchr(szNumber, period);
  1656.     if (ptr)
  1657.     {
  1658.         *ptr = fmtNumber.cDecimalSeparator;
  1659.     }
  1660.  
  1661.     return rslt;
  1662. }
  1663.  
  1664. //=====================================================================
  1665. //  Function:
  1666. //          MakeFullPath (pszDirectory, pszRelativeDirectory)
  1667. //
  1668. //  Input:  pszDirectory            - String to contain the path to the tables
  1669. //                                      directory.
  1670. //          pszRelativeDirectory    - String which contains the relative offset
  1671. //                                      from the current directory.
  1672. //
  1673. //  Return: int     - If the directory exists
  1674. //
  1675. //  Description:
  1676. //          This function is used to get the fully qualified path to
  1677. //          the directory which will contain the tables. This function
  1678. //          will only work when pszRelativeDirectory contains either "."
  1679. //          an absolute path, or <..\\..\\>TABLES.
  1680. //=====================================================================
  1681. int
  1682. MakeFullPath (pCHAR pszDirectory, pCHAR pszRelativeDirectory)
  1683. {
  1684.     int     iExists;    // Does the directory exist?
  1685.     int     iLen;       // Length of the path
  1686.     int     iLoop;      // Loop counter
  1687.     int     iDepth;     // How relative the directory is
  1688.     
  1689.     // Assume absolute path if second character is a ':'.
  1690.     if (pszRelativeDirectory[1] == ':')
  1691.     {
  1692.         strcpy(pszDirectory, pszRelativeDirectory);
  1693.     }
  1694.     else if (!strcmp(pszRelativeDirectory, "."))
  1695.     {
  1696.         // Get the current working directory.
  1697.         getcwd(pszDirectory, DBIMAXPATHLEN);
  1698.     }
  1699.     else
  1700.     {
  1701.         // Get the current working directory.
  1702.         getcwd(pszDirectory, DBIMAXPATHLEN);
  1703.         
  1704.         iLen = strlen(pszDirectory);
  1705.  
  1706.         // Remove relative parts of the path.
  1707.         iDepth = 0;
  1708.         while (!strncmp(&pszRelativeDirectory[iDepth * 3], "..\\", 3))
  1709.         {
  1710.             for (iLoop = iLen; iLoop > -1; iLoop = iLoop - 1)
  1711.             {
  1712.                 if (pszDirectory[iLoop] == '\\')
  1713.                 {
  1714.                     break;
  1715.                 }
  1716.             }
  1717.             iLen = iLoop - 1;
  1718.             iDepth++;
  1719.         }
  1720.  
  1721.         // Copy the 'TABLES' directory to form the full path to the tables.
  1722.         //   Need to move szDirectory past the '\\' and szTblDirectory
  1723.         //   past the '..\\'.
  1724.         strcpy(&pszDirectory[iLoop+1], &pszRelativeDirectory[(3 * iDepth)]);
  1725.     }
  1726.  
  1727.     // Check if the directory exists.
  1728.     iExists = access(pszDirectory, 00);
  1729.  
  1730.     return iExists;
  1731. }
  1732.  
  1733. //=====================================================================
  1734. //  Function:
  1735. //          DisplayNextRecord(HDBICur hCur)
  1736. //
  1737. //  Input:  Handle to the cursor.
  1738. //
  1739. //  Return: DBIERR_SUCCESS
  1740. //
  1741. //  Description:
  1742. //          This function will call DisplayInMemoryTable() with a value
  1743. //          of 1 for the second parameter.  This causes it to display the
  1744. //          next record.
  1745. //=====================================================================
  1746. DBIResult
  1747. DisplayNextRecord(hDBICur hCur)
  1748. {
  1749.     return(DisplayInMemoryTable(hCur, 1));
  1750. }
  1751.  
  1752. //=====================================================================
  1753. //  Function:
  1754. //          DisplayCurrentRecord();
  1755. //
  1756. //  Input:  The cursor handle - which table to access
  1757. //
  1758. //  Return: Result of displaying the records in the table
  1759. //
  1760. //  Description:
  1761. //          This function will display the current record only.
  1762. //
  1763. //  Note:   This function will only display the columns
  1764. //          correctly when using a fixed pitch font.
  1765. //=====================================================================
  1766. DBIResult
  1767. DisplayCurrentRecord (hDBICur hCur)
  1768. {
  1769.     DBIResult   rslt;               // IDAPI function return value
  1770.     CURProps    TblProps;           // Table Properties
  1771.     pFLDDesc    pFldDescs;          // List of fields
  1772.     pBYTE       pRecBuf;            // Record Buffer
  1773.     CHAR**      pszField;           // Array to contain the fields of the
  1774.                                     // table.
  1775.     CHAR*       szFormat;           // Contains an entire record (row)
  1776.     CHAR        szTemp[MAXLEN] =""; // Temporary variable for reading data
  1777.     UINT16      uFldNum;            // Loop variable
  1778.     const UINT16 uDefLength = 15;   // Default size of a field
  1779.  
  1780.  
  1781.     szFormat = (pCHAR) malloc(1600 * sizeof(CHAR));
  1782.     if (szFormat == NULL)
  1783.     {
  1784.         return DBIERR_NOMEMORY;
  1785.     }
  1786.  
  1787.     rslt = DbiGetCursorProps(hCur, &TblProps);
  1788.     if (ChkRslt(rslt, "GetCursorProps") != DBIERR_NONE)
  1789.     {
  1790.         free(szFormat);
  1791.         return rslt;
  1792.     }
  1793.  
  1794.     // Allocate space for the record buffer.
  1795.     pRecBuf = (pBYTE) malloc(TblProps.iRecBufSize * sizeof(BYTE));
  1796.     if (pRecBuf == NULL)
  1797.     {
  1798.         return DBIERR_NOMEMORY;
  1799.     }
  1800.  
  1801.     // Allocate enough space to contain information (field descriptors)
  1802.     //   about all the fields in the answer table.
  1803.     pFldDescs = (pFLDDesc) malloc(TblProps.iFields * sizeof(FLDDesc));
  1804.     if (pFldDescs == NULL)
  1805.     {
  1806.         free(szFormat);
  1807.         free(pRecBuf);
  1808.         return DBIERR_NOMEMORY;
  1809.     }
  1810.  
  1811.     // Get information about the fields.
  1812.     rslt = DbiGetFieldDescs(hCur, pFldDescs);
  1813.     ChkRslt(rslt, "GetFieldDescs");
  1814.  
  1815.     // Allocate enough buffers to contain data from the fields in the
  1816.     //   answer table. Also set the width of non-fldZSTRING fields
  1817.     //   (all data will be converted to strings for display).
  1818.     pszField = (CHAR**)malloc(TblProps.iFields * sizeof(CHAR*));
  1819.  
  1820.     // Set up formatting for the fields.
  1821.     SetupFields(TblProps, pFldDescs, pszField, uDefLength);
  1822.  
  1823.     // Display the names of the fields, aligned by column.
  1824.     strcpy(szFormat,"\r\n        ");
  1825.     for (uFldNum = 0; uFldNum < TblProps.iFields; uFldNum++)
  1826.     {
  1827.         sprintf(szTemp, "%-*s\t", pFldDescs[uFldNum].iUnits1 + 1,
  1828.                 pFldDescs[uFldNum].szName);
  1829.         strcat(szFormat, szTemp);
  1830.     }
  1831.  
  1832.     // Display the header.
  1833.     Screen(szFormat);
  1834.  
  1835.     rslt = DbiGetRecord(hCur, dbiNOLOCK, pRecBuf, NULL);
  1836.     ChkRslt(rslt, "GetRecord");
  1837.  
  1838.     // Fill the record buffer with the field values.
  1839.     GetFields(hCur, pFldDescs, pRecBuf, pszField, uDefLength);
  1840.  
  1841.     // Initialize szFormat to all zeroes.
  1842.     memset(szFormat, 0, sizeof(szFormat));
  1843.  
  1844.     // Add leading blank space to the record.
  1845.     strcpy(szFormat,"        ");
  1846.  
  1847.     // Add each field to be displayed, making certain that the
  1848.     //   columns line up.
  1849.     for (uFldNum = 0; uFldNum < TblProps.iFields; uFldNum++)
  1850.     {
  1851.         sprintf(szTemp, " %-*s\t", pFldDescs[uFldNum].iUnits1,
  1852.         pszField[uFldNum]);
  1853.         strcat(szFormat, szTemp);
  1854.     }
  1855.  
  1856.     // Display the record.
  1857.     Screen(szFormat);
  1858.  
  1859.     // Expect the End-Of-File error - just means that there
  1860.     //   are no more records in the table.
  1861.     if (rslt == DBIERR_EOF)
  1862.     {
  1863.         rslt = DBIERR_NONE;
  1864.     }
  1865.  
  1866.     // Clean up.
  1867.     for (uFldNum = 0; uFldNum < TblProps.iFields; uFldNum++)
  1868.     {
  1869.         free(pszField[uFldNum]);
  1870.     }
  1871.  
  1872.     free(pszField);
  1873.     free(pFldDescs);
  1874.     free(pRecBuf);
  1875.     free(szFormat);
  1876.  
  1877.     return rslt;
  1878. }
  1879.  
  1880.  
  1881.