home *** CD-ROM | disk | FTP | other *** search
/ C Programming Starter Kit 2.0 / SamsPublishing-CProgrammingStarterKit-v2.0-Win31.iso / bde / snipit.pak / LANGDRV.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-07-24  |  33.8 KB  |  877 lines

  1. // BDE - (C) Copyright 1995 by Borland International
  2.  
  3. // Langdrv.C
  4. #include "snipit.h"
  5.  
  6. #define MAXLEN 50
  7.  
  8. static DBIResult GetLdObjectFromLdName(hDBIDb hDb, pCHAR pLdName,
  9.                                        ppVOID ppLdObj);
  10. static DBIResult IntlFillTable(hDBIDb hDb, pCHAR szTblName, pCHAR szTblType,
  11.                                DFLOAT NumRecs);
  12. static DBIResult IntlPutFieldSample(hDBICur hCur, pBYTE pRecBuf,
  13.                                     UINT16 FldNum, pFLDDesc pfldDesc);
  14. static DBIResult IntlDisplayTable(hDBICur hCur, UINT32 uDisplayNRecs);
  15.  
  16. static const char szTblType[] = szPARADOX;
  17.  
  18. // Field descriptor used in creating the temporary table.
  19. static SNIPFAR FLDDesc tmpFldDesc[] = {
  20.               { // Field 1 - NUMERIC
  21.                 1, "XNUM", fldFLOAT, fldUNKNOWN,
  22.                 0, 0, 0, 0, 0, fldvNOCHECKS, fldrREADWRITE
  23.               }
  24.              }; // Array of field descriptors
  25.  
  26. static SNIPFAR FLDDesc OptFldDesc[] = {
  27.               { 1, "LANGDRIVER", fldZSTRING, fldUNKNOWN,
  28.                DBIMAXTBLNAMELEN, 0, 0, DBIMAXSCFLDLEN, 0,
  29.                fldvNOCHECKS, fldrREADWRITE
  30.               }
  31.              }; // Array of field descriptors
  32.  
  33. //=====================================================================
  34. //  Function:
  35. //          LangDriver();
  36. //
  37. //  Description:
  38. //          This sample code will create a Paradox table with the default
  39. //          Paradox language driver (as defined in the IDAPI configuration
  40. //          file), append 10 records to the table, and then delete the
  41. //          table.  Field names, table names, and field data need to be
  42. //          converted when using non-ASCII characters.  This code
  43. //          demonstrates how to do international support in IDAPI 
  44. //          functions DbiGetLdName, DbiGetLdObj, DbiAnsiToNative and
  45. //          DbiNativeToAnsi.
  46. //=====================================================================
  47. void
  48. LangDriver (void)
  49. {
  50.     hDBIDb      hDb;                            // Handle to the database
  51.     hDBICur     hCur;                           // Handle to the table
  52.     CRTblDesc   TblDesc;                        // Create table descriptor
  53.     UINT16      uDispNumRecs = 10 ;             // Number of records to add
  54.                                                 //   and display
  55.     CHAR        pDefLdName[DBIMAXNAMELEN];      // Default language driver
  56.                                                 //  name
  57.     pVOID       pLdObj = NULL;                  // Language driver object
  58.     CHAR        szDspTblName[DBIMAXNAMELEN];    // Buffer to hold table name
  59.                                                 //   for display (in ANSI
  60.                                                 //   character set)
  61.     UINT16      i;                              // Loop counter
  62.     BOOL        bDataLoss;                      // Contains if data loss
  63.                                                 //   occured durring
  64.                                                 //   conversion
  65.     DBIResult   rslt;                           // Return value from IDAPI
  66.                                                 //   functions
  67.     // Variables are declared local because they are changed within
  68.     //   this example and need to be reset each time the example is run.
  69.     char szTblName[] = "╟R8PXT▀L";
  70.  
  71.     // Field descriptor used in creating a table.
  72.     FLDDesc fldDesc[] = {
  73.                      { // Field 1 - ALPHA
  74.                 1,            // Field number
  75.                 "─LPH┼",      // Field name
  76.                 fldZSTRING,   // Field type
  77.                 fldUNKNOWN,   // Field subtype
  78.                 10,           // Field size
  79.                 0,            // Decimal places   ( 0 )
  80.                               //   computed
  81.                 0,            // Offset in record ( 0 )
  82.                 0,           // Length in bytes  ( 0 )
  83.                 0,            // For Null bits    ( 0 )
  84.                 fldvNOCHECKS, // Validity checks  ( 0 )
  85.                 fldrREADWRITE // Rights
  86.               },
  87.               { // Field 2 - NUMERIC
  88.                 2, "╤▄MERIC", fldFLOAT, fldUNKNOWN,
  89.                 0, 0, 0, 0, 0, fldvNOCHECKS, fldrREADWRITE
  90.               },
  91.               { // Field 3 - MONEY
  92.                 3, "M╓NEY", fldFLOAT, fldstMONEY,
  93.                 0, 0, 0, 0, 0, fldvNOCHECKS, fldrREADWRITE
  94.               },
  95.               { // Field 4 - DATE
  96.                 4, "DAT╔", fldDATE, fldUNKNOWN,
  97.                 0, 0, 0, 0, 0, fldvNOCHECKS, fldrREADWRITE
  98.               },
  99.               { // Field 5 - MEMO
  100.                 5, "M╔MO", fldBLOB, fldstMEMO,
  101.                 20, 0, 0, 0, 0, fldvNOCHECKS, fldrREADWRITE
  102.               }
  103.              }; // Array of field descriptors.
  104.     
  105.     // The number of fields in the table.
  106.     const unsigned uNumFields = sizeof(fldDesc) / sizeof (fldDesc[0]);
  107.  
  108.     Screen("*** Creating language independent applications ***\r\n");
  109.  
  110.     BREAK_IN_DEBUGGER();
  111.  
  112.     Screen("    Initializing IDAPI...");
  113.     if (InitAndConnect(&hDb) != DBIERR_NONE)
  114.     {
  115.         Screen("\r\n*** End of Example ***");
  116.         return;
  117.     }
  118.  
  119.     Screen("    Setting the default database directory...");
  120.     rslt = DbiSetDirectory(hDb, (pCHAR)szTblDirectory);
  121.     ChkRslt(rslt, "SetDirectory");
  122.  
  123.     // Table name is received from users in ANSI character set, but IDAPI
  124.     //   expects it in OEM.
  125.     AnsiToOem((pCHAR)szTblName, (pCHAR)szTblName);
  126.  
  127.     Screen("    Initializing the table descriptor...");
  128.     memset((void *) &TblDesc , 0, sizeof(CRTblDesc));
  129.     lstrcpy(TblDesc.szTblName, szTblName);
  130.     lstrcpy(TblDesc.szTblType, szTblType);
  131.     TblDesc.iFldCount = uNumFields;
  132.  
  133.     // Translate field names in field descriptor from ANSI (as received
  134.     //   from users) to the table's character set using table's language
  135.     //   driver.
  136.     //   Get default language driver name for specified table type. This
  137.     //   will also be the language driver of the new table.
  138.     rslt = DbiGetLdName((pCHAR)szTblType, NULL, pDefLdName); 
  139.     if (ChkRslt(rslt, "GetLdName") == DBIERR_NONE)
  140.     {
  141.         if (GetLdObjectFromLdName(hDb, pDefLdName, &pLdObj) == DBIERR_NONE)
  142.         {
  143.             for (i=0; i<uNumFields; i++)
  144.             {
  145.                 rslt = DbiAnsiToNative(pLdObj, fldDesc[i].szName,
  146.                                        fldDesc[i].szName, NULL, &bDataLoss);
  147.                 ChkRslt(rslt, "AnsiToNative");
  148.             }
  149.         }
  150.         else
  151.         {
  152.             CloseDbAndExit(&hDb);
  153.             Screen("\r\n*** End of Example ***");
  154.             return;
  155.         }
  156.     }
  157.     else
  158.     {
  159.         CloseDbAndExit(&hDb);
  160.         Screen("\r\n*** End of Example ***");
  161.         return;
  162.     }
  163.  
  164.     TblDesc.pfldDesc = fldDesc;
  165.  
  166.     // Create and overwrite the table using the default language driver
  167.     //   defined in the IDAPI configuration file.
  168.     Screen("    Creating the Paradox table...");
  169.     rslt = DbiCreateTable(hDb, TRUE, &TblDesc);
  170.     if (ChkRslt(rslt, "CreateTable") != DBIERR_NONE)
  171.     {
  172.         CloseDbAndExit(&hDb);
  173.         Screen("\r\n*** End of Example ***");
  174.         return;
  175.     }
  176.  
  177.     Screen("    Fill the table with random data...");
  178.     IntlFillTable(hDb, (pCHAR)szTblName, (pCHAR)szTblType, uDispNumRecs);
  179.  
  180.     // Open the table which we just created.  The table name should be
  181.     //   translated from the DOS character set to ANSI for display.
  182.     OemToAnsi(szTblName, szDspTblName);
  183.     Screen("    Open the \"%s\" table...", szDspTblName);
  184.     rslt = DbiOpenTable(hDb, (pCHAR)szTblName, (pCHAR)szTblType,
  185.                         NULL, NULL, 0, dbiREADWRITE, dbiOPENSHARED,
  186.                         xltFIELD, FALSE, NULL, &hCur);
  187.     if (ChkRslt(rslt, "OpenTable") != DBIERR_NONE)
  188.     {
  189.         rslt = DbiDeleteTable(hDb, (pCHAR)szTblName, (pCHAR)szTblType);
  190.         ChkRslt(rslt, "DeleteTable");
  191.         CloseDbAndExit(&hDb);
  192.         Screen("\r\n*** End of Example ***");
  193.         return;
  194.     }
  195.  
  196.     Screen("    Display the \"%s\" table which we just created...",
  197.            szDspTblName);
  198.     IntlDisplayTable(hCur, uDispNumRecs);
  199.  
  200.     Screen("\r\n    Close the table...");
  201.     rslt = DbiCloseCursor(&hCur);
  202.     ChkRslt(rslt, "CloseCursor");
  203.  
  204.     Screen("    Deleting the table...");
  205.     rslt = DbiDeleteTable(hDb, (pCHAR)szTblName, (pCHAR)szTblType);
  206.     ChkRslt(rslt, "DeleteTable");
  207.  
  208.     Screen("    Close the database and exit IDAPI...");
  209.     CloseDbAndExit(&hDb);
  210.  
  211.     Screen("\r\n*** End of Example ***");
  212. }   
  213.  
  214. //=====================================================================
  215. //  Function:
  216. //          GetLdObjectFromLdName(hDb, pLdName, ppLdObj)
  217. //
  218. //  Input:  hDb     - Database handle
  219. //          pLdName - Language driver name
  220. //
  221. //  Return: DBIResult   - Success of the opperation
  222. //
  223. //  Description:
  224. //          This function is used to get the language driver (LD) object from
  225. //          an LD name rather than from a table cursor (as in DbiGetLdObj).
  226. //          This allows us to get the LD object before a table is created.
  227. //          If a table exists, you may use DbiGetLdObj to get the LD object.
  228. //          The function creates a temporary table "__X123" (using optional
  229. //          parameters to specify the language driver name) and gets the LD
  230. //          object from the table.  The temporary table will be deleted upon
  231. //          exiting IDAPI.
  232. //=====================================================================
  233. DBIResult
  234. GetLdObjectFromLdName (hDBIDb hDb, pCHAR pLdName, ppVOID ppLdObj)
  235. {
  236.     hDBICur     hTmpCur;        // Handle to the table
  237.     pCRTblDesc  pTmpTblDesc;    // Create table descriptor
  238.     DBIResult   rslt;           // Return value
  239.     DBIResult   rslt2;          // Return value to use during cleanup
  240.  
  241.     CHAR szTmpTblName[] = "__X123";
  242.  
  243.     pTmpTblDesc = (pCRTblDesc)malloc(sizeof(CRTblDesc));
  244.  
  245.     // Initialize the Table create descriptor.
  246.     memset((void *) pTmpTblDesc , 0, sizeof(CRTblDesc));
  247.     lstrcpy(pTmpTblDesc->szTblName, szTmpTblName);
  248.     lstrcpy(pTmpTblDesc->szTblType, szPARADOX);
  249.     pTmpTblDesc->iFldCount = 1;
  250.     pTmpTblDesc->pfldDesc = tmpFldDesc;
  251.     pTmpTblDesc->iOptParams = 1;
  252.     pTmpTblDesc->pfldOptParams = OptFldDesc;
  253.     pTmpTblDesc->pOptData = (pBYTE)pLdName;
  254.  
  255.     // Create and overwrite the table using specific language driver
  256.     //   passed to the function.
  257.     rslt = DbiCreateTable(hDb, TRUE, pTmpTblDesc);
  258.     ChkRslt(rslt, "CreateTable");
  259.     if (rslt != DBIERR_NONE)
  260.     {
  261.         free(pTmpTblDesc);
  262.         Screen("\r\n    GetLdObjectFromLdName\r\n");
  263.         return rslt;
  264.     }
  265.  
  266.     rslt = DbiOpenTable(hDb, szTmpTblName, szPARADOX, NULL, NULL,
  267.                         NULL, dbiREADONLY, dbiOPENSHARED, xltNONE,
  268.                         FALSE, NULL, &hTmpCur);
  269.     ChkRslt(rslt, "OpenTable");
  270.     if (rslt != DBIERR_NONE)
  271.     {
  272.         free(pTmpTblDesc);
  273.         return rslt;
  274.     }
  275.  
  276.     // Get LD object.
  277.     rslt = DbiGetLdObj(hTmpCur, ppLdObj);
  278.     ChkRslt(rslt, "GetLdObj");
  279.     if (rslt != DBIERR_NONE)
  280.     {
  281.         rslt2 = DbiCloseCursor(&hTmpCur);
  282.         ChkRslt(rslt2, "CloseCursor");
  283.         rslt2 = DbiDeleteTable(hDb, (pCHAR)szTmpTblName, (pCHAR)szTblType);
  284.         ChkRslt(rslt2, "DeleteTable");
  285.         free(pTmpTblDesc);
  286.         return rslt;
  287.     }            
  288.  
  289.     free(pTmpTblDesc);
  290.     rslt = DbiCloseCursor(&hTmpCur);
  291.     ChkRslt(rslt, "CloseCursor");
  292.  
  293.     rslt = DbiDeleteTable(hDb, (pCHAR)szTmpTblName, (pCHAR)szTblType);
  294.     ChkRslt(rslt, "DeleteTable");
  295.  
  296.     return rslt;
  297. }
  298.  
  299. //=====================================================================
  300. //  Function:
  301. //          IntlFillTable(hDb, szTblName, szTblType, NumRecs);
  302. //
  303. //  Input:  hDb         - The database handle
  304. //          szTblName   - Name of the table to fill
  305. //          szTblTyps   - Type of the table to fill
  306. //          NumRecs     - The number of records to insert
  307. //
  308. //  Return: DBIResult   - Success of the operation
  309. //
  310. //  Description:
  311. //          This function adds the specified number of records to
  312. //          the table containing random data.
  313. //=====================================================================
  314. DBIResult
  315. IntlFillTable (hDBIDb hDb, pCHAR szTblName, pCHAR szTblType, DFLOAT NumRecs)
  316. {
  317.     DBIResult   rslt;           // Return value from IDAPI functions
  318.     DFLOAT      fRecCount;      // Loop variable = count of records
  319.     UINT16      FldCntr;        // Field counter
  320.     pBYTE       pRecBuf = NULL; // Pointer to the record buffer
  321.     FLDDesc     fldDesc;        // Field descriptor
  322.     CURProps    TblProps;       // Table descriptor
  323.     hDBICur     hCur;           // Handle to the table
  324.     hDBICur     hFldList;       // Handle to the field list table
  325.  
  326.     rslt = DbiOpenTable(hDb, szTblName, szTblType, NULL, NULL, 0,
  327.                         dbiREADWRITE, dbiOPENSHARED, xltFIELD, FALSE,
  328.                         NULL, &hCur);
  329.     if (ChkRslt(rslt,"OpenTable") != DBIERR_NONE)
  330.     {
  331.         return rslt;
  332.     }
  333.  
  334.     //  Create an in-memory table that contains a list of fields. Note
  335.     //    that logical (i.e. IDAPI types), are being requested instead of
  336.     //    driver types.
  337.     rslt = DbiOpenFieldList(hDb, szTblName, szTblType, FALSE, &hFldList);
  338.     if (ChkRslt(rslt,"OpenFieldList")!= DBIERR_NONE)
  339.     {
  340.         rslt = DbiCloseCursor(&hCur);
  341.         ChkRslt(rslt, "CloseCursor");
  342.         return rslt;
  343.     }
  344.  
  345.     // Append the records if the list and table are available.
  346.     if (hCur && hFldList)
  347.     {
  348.         ChkRslt(DbiGetCursorProps(hCur, &TblProps),
  349.                 "GetCursorProps");
  350.  
  351.         pRecBuf = (pBYTE) malloc(TblProps.iRecBufSize);
  352.         if (!pRecBuf)
  353.         {
  354.             Screen("Out of Memory");
  355.             rslt = DbiCloseCursor(&hCur);
  356.             ChkRslt(rslt, "CloseCursor");
  357.             rslt = DbiCloseCursor(&hFldList);
  358.             ChkRslt(rslt, "CloseCursor");
  359.             return DBIERR_NOMEMORY;
  360.         }
  361.  
  362.         // Loop until the specified number of records have been written
  363.         //   to the table.
  364.         for (fRecCount = 0; fRecCount < NumRecs; fRecCount++)
  365.         {
  366.             //  Make sure we're starting with a clean record buffer.
  367.             rslt = DbiInitRecord(hCur, pRecBuf);
  368.             ChkRslt(rslt, "InitRecord");
  369.  
  370.             FldCntr = 1;
  371.             rslt = DbiSetToBegin(hFldList);
  372.             ChkRslt(rslt,  "SetToBegin");
  373.  
  374.             // This loop will use the previously opened field list to
  375.             //   determine what type of data is inserted into the table.
  376.             while (DbiGetNextRecord(hFldList, dbiNOLOCK, (pBYTE) &fldDesc,
  377.                                     NULL) == DBIERR_NONE)
  378.             {
  379.                 // Put field data into the record buffer.
  380.                 IntlPutFieldSample(hCur, pRecBuf, FldCntr, &fldDesc);
  381.                 FldCntr++;
  382.             }
  383.  
  384.             // All fields have been inserted into the record buffer. Now
  385.             //   we need to append the record to the table.
  386.             rslt = DbiAppendRecord(hCur, pRecBuf);
  387.             ChkRslt(rslt, "AppendRecord") ;
  388.  
  389.             // Make sure to close all BLOBs (opened when data was put into
  390.             //   the record buffer).
  391.             FldCntr = 1;
  392.             rslt = DbiSetToBegin(hFldList);
  393.             ChkRslt(rslt, "SetToBegin");
  394.             while (DbiGetNextRecord(hFldList, dbiNOLOCK, (pBYTE) &fldDesc,
  395.                                     NULL) == DBIERR_NONE)
  396.             {
  397.                 if (fldDesc.iFldType == fldBLOB)
  398.                 {
  399.                     rslt = DbiFreeBlob(hCur, pRecBuf, FldCntr);
  400.                     ChkRslt(rslt, "FreeBlob");
  401.                 }
  402.                 FldCntr++;
  403.             }
  404.         }
  405.  
  406.         // Free allocated record buffer.
  407.         free((pCHAR) pRecBuf);
  408.     }
  409.  
  410.     // Clean up and return.
  411.     rslt = DbiCloseCursor(&hFldList);
  412.     ChkRslt(rslt, "CloseCursor");
  413.  
  414.     rslt = DbiCloseCursor(&hCur);
  415.     ChkRslt(rslt, "CloseCursor");
  416.  
  417.     return DBIERR_NONE;
  418. }
  419.  
  420. //=====================================================================
  421. //  Function:
  422. //          IntlPutFieldSample(hCur, pRecBuf, FldNum, pfldDesc);
  423. //
  424. //  Input:  hCur     - The handle for the table to fill
  425. //          pRecBuf  - The record buffer to insert data into
  426. //          FldNum   - The field we are generating
  427. //          pfldDesc - A descriptor that describes the field to generate
  428. //
  429. //  Return: Result returned from DbiPutField()
  430. //
  431. //  Description:
  432. //          This routine is used to put field data into a record
  433. //          buffer. Note that all logical field types are covered. You
  434. //          will need to refer to documentation, or run the DRVCAPS.C
  435. //          example for physical to logical field mappings.
  436. //=====================================================================
  437. DBIResult
  438. IntlPutFieldSample (hDBICur hCur, pBYTE pRecBuf, UINT16 FldNum,
  439.                     pFLDDesc pfldDesc)
  440. {
  441.     pBYTE      pBuf;           // Buffer which contains the record data
  442.     DBIResult  rslt;           // Return value from IDAPI functions
  443.     INT16      i;              // Loop counter
  444.     INT16      BlobSize;       // Size of the BLOB
  445.     BOOL       bDataLoss;      // If any data is lost in translation
  446.     BOOL       Bool;           // Used for fldBOOL
  447.     INT16      Int16;          // Used for fldINT16
  448.     UINT16     uInt16;         // Used for fldUINT16
  449.     INT32      Int32;          // Used for fldINT32
  450.     UINT32     uInt32;         // Used for fldUINT32
  451.     DFLOAT     Float;          // Used for fldFLOAT
  452.     FMTBcd     fmtBcd;         // Used for fldBCD
  453.     DBIDATE    Date;           // Used for fldDATE
  454.     TIME       Time;           // Used for fldTIME
  455.     TIMESTAMP  tStamp;         // Used for fldTIMESTAMP
  456.     UINT16     month;          // Used in generating the date
  457.     UINT16     day;            // Used in generating the date
  458.     UINT16     year;           // Used in generating the date
  459.     UINT16     hour;           // Used in generating the time
  460.     UINT16     min;            // Used in generating the time
  461.     UINT16     sec;            // Used in generating the time
  462.     pVOID      pLdObj = NULL;  // Table's language driver object
  463.  
  464.     // Allocate a generic buffer (used for string & blob fields).
  465.     pBuf = (pBYTE) malloc(4096);
  466.     if (!pBuf)
  467.     {
  468.         Screen("    Error - Out of memory.");
  469.         return DBIERR_NOMEMORY;
  470.     }
  471.  
  472.     // This section contains sample code demonstrating how to
  473.     //   insert a field of any type into a record buffer.  Random data
  474.     //   is used by this example.  Field data is assumed to be in the ANSI
  475.     //   character set, and needs to be translated into the table's
  476.     //   character set before being inserted in the table.
  477.  
  478.     // Get tables language driver.
  479.     rslt = DbiGetLdObj(hCur, &pLdObj);
  480.     ChkRslt(rslt, "GetLdObj");
  481.  
  482.     switch (pfldDesc->iFldType)
  483.     {
  484.         case fldBYTES:
  485.         case fldZSTRING:
  486.             sprintf((pCHAR)pBuf, "F∩Θld #%d", FldNum);
  487.             // Translate the character string.  If table's language
  488.             //   driver is based on the ANSI character set, no translation
  489.             //   is performed.
  490.             rslt = DbiAnsiToNative(pLdObj, (pCHAR)pBuf, (pCHAR)pBuf, NULL,
  491.                                    &bDataLoss);
  492.             ChkRslt(rslt, "AnsiToNative");
  493.  
  494.             // Put the data into the record buffer.
  495.             rslt = DbiPutField(hCur, FldNum, pRecBuf, pBuf);
  496.             break;
  497.         case fldDATE:
  498.             // Randomly generate and encode a date.
  499.             month = (rand() % 12) + 1;
  500.             day = (rand() % 20) + 1;
  501.             year = (rand() % 99) + 1900;
  502.             rslt = DbiDateEncode(month, day, year, &Date);
  503.             ChkRslt(rslt, "DateEncode");
  504.  
  505.             // Put the data into the record buffer.
  506.             rslt = DbiPutField(hCur, FldNum, pRecBuf, (pBYTE) &Date);
  507.             break;
  508.         case fldBLOB:
  509.             // Generate a blob with length from 10-4010 bytes.
  510.             BlobSize = (rand() % 4000) + 11;
  511.  
  512.             strcpy((pCHAR)pBuf, "BL╓B Θxßmple ");
  513.  
  514.             // Write data to the BLOB field.
  515.             for (i = 0; i < (BlobSize % 11); i++)
  516.             {
  517.                 strcat((pCHAR)pBuf, "BL╓B tΦst ");
  518.             }
  519.  
  520.             // Translate character data.  If table's language
  521.             //   driver is based on ANSI character set, no translation
  522.             //   is performed.
  523.             rslt = DbiAnsiToNative(pLdObj, (pCHAR)pBuf, (pCHAR)pBuf, NULL,
  524.                                    &bDataLoss);
  525.             ChkRslt(rslt, "AnsiToNative");
  526.  
  527.             // Init the BLOB header (contents defined by IDAPI client).
  528.             if ((pfldDesc->iSubType == fldstFMTMEMO) ||
  529.                  (pfldDesc->iSubType == fldstOLEOBJ) ||
  530.                  (pfldDesc->iSubType == fldstGRAPHIC))
  531.             {
  532.                  memset(pBuf, 8, '\0');
  533.             }
  534.  
  535.             // Open the BLOB prior to putting.
  536.             ChkRslt(DbiOpenBlob(hCur, pRecBuf, FldNum, dbiREADWRITE), "OpenBlob");
  537.  
  538.             // Put the BLOB. Note that DbiFreeBlob() will be
  539.             //   called after the record is inserted!
  540.             rslt = DbiPutBlob(hCur, pRecBuf, FldNum, 0, BlobSize,
  541.                               pBuf);
  542.             break;
  543.         case fldBOOL:
  544.             // Boolean fields are either TRUE or FALSE.
  545.             if ((rand() % 100) < 50)
  546.                 Bool = 1;
  547.             else
  548.                 Bool = 0;
  549.             // Put the data into the record buffer.
  550.             rslt = DbiPutField(hCur, FldNum, pRecBuf, (pBYTE)&Bool);
  551.             break;
  552.         case fldINT16:
  553.             Int16 = (rand() % 255);
  554.             // Put the data into the record buffer.
  555.             rslt = DbiPutField(hCur, FldNum, pRecBuf, (pBYTE)&Int16);
  556.             break;
  557.         case fldBCD:
  558.             Float = (rand() / 1.21324);
  559.             rslt = DbiBcdFromFloat(&Float, pfldDesc->iUnits1,
  560.                                     pfldDesc->iUnits2, &fmtBcd);
  561.             ChkRslt(rslt, "BcdFromFloat");
  562.  
  563.             // Put the data into the record buffer.
  564.             rslt = DbiPutField(hCur, FldNum, pRecBuf, (pBYTE)&fmtBcd);
  565.             break;
  566.         case fldLOCKINFO:
  567.             rslt = 0;
  568.             break;
  569.         case fldUINT16:
  570.             uInt16 = (rand() % 255);
  571.             // Put the data into the record buffer.
  572.             rslt = DbiPutField(hCur, FldNum, pRecBuf, (pBYTE)&uInt16);
  573.             break;
  574.         case fldINT32:
  575.             // Put the data into the record buffer if it is not an
  576.             //   auto-increment field.
  577.             if (pfldDesc->iSubType != fldstAUTOINC)
  578.             {
  579.                 Int32 = (rand() % 10000);
  580.                 rslt = DbiPutField(hCur, FldNum, pRecBuf, (pBYTE)&Int32);
  581.             }
  582.             else
  583.             {
  584.                 // Don't have to put a value into an auto-increment field,
  585.                 //   but make certain not to return an error.
  586.                 rslt = 0;
  587.             }
  588.             break;
  589.         case fldUINT32:
  590.             uInt32 = (rand() % 10000);
  591.             // Put the data into the record buffer.
  592.             rslt = DbiPutField(hCur, FldNum, pRecBuf, (pBYTE)&uInt32);
  593.             break;
  594.         case fldFLOAT:
  595.             Float = (rand() % 128000L);
  596.             // Put the data into the record buffer.
  597.             rslt = DbiPutField(hCur, FldNum, pRecBuf, (pBYTE)&Float);
  598.             break;
  599.         case fldTIME:
  600.             // Randomize and encode a time value.
  601.             hour = (rand() % 23) + 1;
  602.             min = (rand() % 59) + 1;
  603.             sec = ((rand() * 2) % 59999U) + 1;
  604.             rslt = DbiTimeEncode( hour, min, sec, &Time);
  605.             ChkRslt(rslt, "TimeEncode");
  606.  
  607.             // Put the data into the record buffer.
  608.             rslt = DbiPutField(hCur, FldNum, pRecBuf, (pBYTE)&Time);
  609.             break;
  610.         case fldTIMESTAMP:
  611.             // Encode a date and a time.
  612.             month = (rand() % 12) + 1;
  613.             day = (rand() % 20) + 1;
  614.             year = (rand() % 99) + 1900;
  615.             rslt = DbiDateEncode(month, day, year, &Date);
  616.             ChkRslt(rslt, "DateEncode");
  617.             hour = (rand() % 23) + 1;
  618.             min = (rand() % 59) + 1;
  619.             sec = ((rand() * 2) % 59999U) + 1;
  620.             rslt = DbiTimeEncode(hour, min, sec, &Time);
  621.             ChkRslt(rslt, "TimeEncode");
  622.  
  623.             // Now encode and put the time stamp.
  624.             rslt = DbiTimeStampEncode(Date, Time, &tStamp);
  625.             ChkRslt(rslt, "TimeStampEncode");
  626.             // Put the data into the record buffer.
  627.             rslt = DbiPutField(hCur, FldNum, pRecBuf, (pBYTE)&tStamp);
  628.             break;
  629.         case fldVARBYTES:
  630.             // Init the size (1st two bytes) and contents.
  631.             *((int *) pBuf) = (pfldDesc->iUnits1 - 2);
  632.             for (i = 2; i < pfldDesc->iUnits1; i++)
  633.             {
  634.                 pBuf[i] = (rand() % 90) + 32;
  635.             }
  636.             pBuf[i] = '\0';
  637.  
  638.             // Put the data into the record buffer.
  639.             rslt = DbiPutField(hCur, FldNum, pRecBuf, (pBYTE)pBuf);
  640.             break;
  641.         default:
  642.             rslt = DBIERR_INVALIDFLDTYPE;
  643.             break;
  644.     }
  645.     // Determine if any of the previous DbiPutField functions failed.
  646.     ChkRslt(rslt, "PutField");
  647.  
  648.     // Clean up and return.
  649.     free((pCHAR) pBuf);
  650.     return rslt;
  651. }
  652.  
  653. //=====================================================================
  654. //  Function:
  655. //          DisplayTable(hCur, uDisplayNRecs);
  656. //
  657. //  Input:  The cursor handle - Which table to access
  658. //          DisplayNRecs      - How many records to display
  659. //                              (0 means display all records in the table.)
  660. //
  661. //  Return: Result of displaying the records in the table
  662. //
  663. //  Descrption:
  664. //          This function will display all records in the table referenced
  665. //          by the cursor.  Records are read from the table in blocks,
  666. //          making this function faster than the DisplayInMemoryTable()
  667. //          function.
  668. //
  669. //  Note:   This function will only display the columns
  670. //          correctly when using a fixed pitch font.
  671. //=====================================================================
  672. DBIResult
  673. IntlDisplayTable (hDBICur hCur, UINT32 uDisplayNRecs)
  674. {
  675.     DBIResult   rslt = DBIERR_NONE; // Return value from IDAPI functions
  676.     CURProps    TblProps;           // Table properties
  677.     pFLDDesc    pFldDescs;          // List of fields
  678.     pBYTE       pRecBuf;            // Record buffer
  679.     CHAR**      ppszField;          // Array to contain the fields of the
  680.                                     //   table
  681.     pCHAR       szFormat;           // Contains an entire record (row)
  682.     CHAR        szTemp[MAXLEN] =""; // Temporary variable for reading data
  683.     UINT16      uFldNum;            // Loop variable
  684.     UINT16      uMaxNumRecs = 30;   // Maximum number of record to read
  685.                                     // from the table at a time
  686.     UINT32      uNumRecs;           // Number of records Read in from the
  687.                                     //   table
  688.     UINT16      uCount;             // Loop variable
  689.     UINT32      uCurCountRec = 0;   // Counter to keep track of how many
  690.                                     //   records have been displayed
  691.     const UINT16 uDefLength = 15;   // Default size of a field
  692.     pVOID       pLdObj = NULL;      // Language driver object
  693.     BOOL        bDataLoss;          // Data loss parameter for character
  694.                                     //   translation 
  695.  
  696.     rslt = DbiGetCursorProps(hCur, &TblProps);
  697.     if ((ChkRslt(rslt, "GetCursorProps")) != DBIERR_NONE)
  698.     {
  699.         return rslt;
  700.     }
  701.  
  702.     // Allocate memory for the format string.
  703.     szFormat = (pCHAR)malloc(1400);
  704.     // Allocate space for the record buffer.
  705.     pRecBuf = (pBYTE)malloc(TblProps.iRecBufSize * sizeof(BYTE) *
  706.                             uMaxNumRecs);
  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) || (!pRecBuf) || (!szFormat))
  711.     {
  712.         if (szFormat) free(szFormat);
  713.         if (pRecBuf) free(pRecBuf);
  714.         if (pFldDescs) free(pFldDescs);
  715.         return DBIERR_NOMEMORY;
  716.     }
  717.  
  718.     szFormat[0] = 0;
  719.     
  720.     // Get information about the fields.
  721.     rslt = DbiGetFieldDescs(hCur, pFldDescs);
  722.     ChkRslt(rslt, "GetFieldDescs");
  723.  
  724.     // Allocate enough buffers to contain data from the fields in the
  725.     //   answer table.  Also set the width of non-fldZSTRING fields
  726.     //   (all data will be converted to strings for display.)
  727.     ppszField = (CHAR**)malloc(TblProps.iFields * sizeof(CHAR*));
  728.     if (!ppszField)
  729.     {
  730.         free(szFormat);
  731.         free(pRecBuf);
  732.         free(pFldDescs);
  733.         return DBIERR_NOMEMORY;
  734.     }
  735.  
  736.     SetupFields(TblProps, pFldDescs, ppszField, uDefLength);
  737.     // Get table language driver to translate field names from table's
  738.     //   character set to ANSI for display.
  739.     rslt = DbiGetLdObj(hCur, &pLdObj);
  740.     if ((ChkRslt(rslt, "GetLdObj")) != DBIERR_NONE)
  741.     {
  742.         free(szFormat);
  743.         free(pRecBuf);
  744.         free(pFldDescs);
  745.         return rslt;
  746.     }
  747.     
  748.     // Format the names of the fields, aligned by column.
  749.     strcpy(szFormat,"\r\n        ");
  750.     for (uFldNum = 0; uFldNum < TblProps.iFields; uFldNum++)
  751.     {
  752.         sprintf(szTemp, "%-*s\t", pFldDescs[uFldNum].iUnits1 + 1,
  753.                 pFldDescs[uFldNum].szName);
  754.         strcat(szFormat, szTemp);
  755.     }
  756.  
  757.     // Translate field names from table's character set to ANSI for display.
  758.     rslt = DbiNativeToAnsi(pLdObj, szFormat, szFormat, NULL,
  759.                                  &bDataLoss);
  760.     if ((ChkRslt(rslt, "NativeToAnsi")) != DBIERR_NONE)
  761.     {
  762.         free(szFormat);
  763.         free(pRecBuf);
  764.         free(pFldDescs);
  765.         return rslt;
  766.     }
  767.  
  768.     // Display the header information (field names).
  769.     Screen(szFormat);
  770.  
  771.     // Get records from the table until the end of the table is reached
  772.     //   Note that not all field types are supported. All supported field
  773.     //   types are displayed as strings.
  774.     //   The DbiReadBlock function is used in case field mapping
  775.     //   is taking place - the GetNextRec, GetPriorRec, and GetRelativeRec
  776.     //   functions do not take field mapping into consideration.
  777.     uNumRecs = uMaxNumRecs; // Set the number of records to read from the
  778.                             // table as a block
  779.     // If uCurCoutRec == 0, display all the records in the table.
  780.     if (uDisplayNRecs == 0)
  781.     {
  782.         uDisplayNRecs = (UINT16)-1; // uDisplayNRecs is unsigned, so
  783.                                     //   -1 maximizes the value.
  784.     }
  785.     // Get the records from the table and display.
  786.     do
  787.     {
  788.         // Limit the number of records to be read from the table -
  789.         //   do not want to display more than uDisplayNRecs records.
  790.         if ((uNumRecs + uCurCountRec) > uDisplayNRecs)
  791.         {
  792.             uNumRecs = uDisplayNRecs - uCurCountRec;
  793.         }
  794.         // Read a block of records - this is more efficient than reading 
  795.         //   records one at a time from the table.
  796.         rslt = DbiReadBlock(hCur, &uNumRecs, pRecBuf);
  797.         if ((rslt != DBIERR_EOF) && // DBIERR_EOF is an expected return
  798.             (rslt != DBIERR_NONE))  //   code - means cannot read more records.
  799.         {
  800.             free(szFormat);
  801.             for (uFldNum = 0; uFldNum < TblProps.iFields; uFldNum++)
  802.             {
  803.                 free(ppszField[uFldNum]);
  804.             }
  805.             free(ppszField);
  806.             free(pFldDescs);
  807.             free(pRecBuf);
  808.             return rslt;
  809.         }
  810.         for (uCount=0; uCount < uNumRecs; uCount++)
  811.         {
  812.             uCurCountRec++;
  813.  
  814.             // Fill the record buffer with the field values.
  815.             GetFields(hCur, pFldDescs,
  816.                       &pRecBuf[uCount * TblProps.iRecBufSize],
  817.                       ppszField, uDefLength);
  818.  
  819.             // Add leading blank space to the record.
  820.             strcpy(szFormat,"        ");
  821.             // Add each field to be displayed, making certain that the
  822.             //   columns line up.
  823.             for (uFldNum = 0; uFldNum < TblProps.iFields; uFldNum++)
  824.             {
  825.                      sprintf(szTemp, " %-*s\t", pFldDescs[uFldNum].iUnits1,
  826.                      ppszField[uFldNum]);
  827.                      strcat(szFormat, szTemp);
  828.                 }
  829.             // Translate table data from table's character set to ANSI for
  830.             //   display.
  831.             rslt = DbiNativeToAnsi(pLdObj, szFormat, szFormat, NULL,
  832.                                             &bDataLoss);
  833.                 if ((ChkRslt(rslt, "NativeToAnsi")) != DBIERR_NONE)
  834.                 {
  835.                      // Clean up.
  836.                      for (uFldNum = 0; uFldNum < TblProps.iFields; uFldNum++)
  837.                      {
  838.                          free(ppszField[uFldNum]);
  839.                      }
  840.                      free(szFormat);
  841.                      free(ppszField);
  842.                      free(pFldDescs);
  843.                      free(pRecBuf);
  844.                 }
  845.  
  846.                 // Display the record.
  847.                 Screen(szFormat);
  848.           } // For ... uCount.
  849.     // While ReadBlock reads as many records as are supposed to be
  850.     //   batched (uMaxNumRecs) and the maximum number of records have not
  851.     //   been read from the table.  Reading a smaller number of records than
  852.     //   that specified in uMaxNumRecs indicates that the end of the table has
  853.     //   been reached.
  854.     } while((uNumRecs == uMaxNumRecs) &&
  855.             (uCurCountRec < uDisplayNRecs));
  856.  
  857.     // Expect the End-Of-File error - just means that there
  858.     //   aren't any more records in the table.
  859.     if (rslt == DBIERR_EOF)
  860.     {
  861.         rslt = DBIERR_NONE;
  862.     }
  863.  
  864.     // Clean up.
  865.     for (uFldNum = 0; uFldNum < TblProps.iFields; uFldNum++)
  866.     {
  867.         free(ppszField[uFldNum]);
  868.     }
  869.     free(szFormat);
  870.     free(ppszField);
  871.     free(pFldDescs);
  872.     free(pRecBuf);
  873.  
  874.     return DBIERR_NONE;
  875. }
  876.  
  877.