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

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