Files
TeslaRel410/BORLAND/BDE/EXAMPLES/SNIPIT/LANGDRV.C
T
CydandClaude Fable 5 63312e07f9 source410: literal 4.10 source reconstruction + BC++ 4.52 fleet toolchain archived
- BORLAND/: Borland C++ 4.52 (chosen over 4.5 by byte-match: CODE/RP/CW32.LIB
  is identical to 4.52's install lib). BCC32/TLINK32/TLIB/MAKE run natively on
  Win11; CODE/BT/OPT.MAK is the shipped BTL4OPT.EXE's exact flag recipe
  (extender = Borland PowerPack DPMI32, not Phar Lap TNT).
- restoration/source410/: the literal 1995-form reconstruction of the missing
  BT game source (never mixed into CODE/). Round 1-3 state:
  * 6 of 10 surviving original TUs COMPILE CLEAN under the period toolchain
    (BTMSSN, BTCNSL, BTSCNRL, BTTEAM, BTL4MODE, BTL4ARND) - first builds
    since 1996.
  * BT_L4/BTL4APP.CPP pilot reconstruction: 12/12 functions, Fail() lands on
    its binary-recorded line 400 exactly.
  * BT/BTCNSL.HPP: console wire IDs recovered from the binary's ctors
    (Killed=9, Damaged=10, ScoreUpdate=13, DeathWithoutHonor=15 [T1];
    TeamScore=12 flagged [T4]).
  * MUNGA/: 8 engine-header backfills back-dated from the BT412 WinTesla tree
    (VDATA numbering decomp-verified; AUDREND's OpenAL-era virtual removed -
    the period compiler is the drift detector).
  * Tooling: backdate.py (WinTesla->1995 header transform), compile410.sh
    (per-TU verification sweep under authentic OPT.MAK flags).
  * README: corrected roadmap - MECH.HPP is the capstone grown with the mech
    TU reconstructions; BTREG.CPP green = the header-family milestone.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 07:33:26 -05:00

877 lines
34 KiB
C++

// BDE - (C) Copyright 1995 by Borland International
// Langdrv.C
#include "snipit.h"
#define MAXLEN 50
static DBIResult GetLdObjectFromLdName(hDBIDb hDb, pCHAR pLdName,
ppVOID ppLdObj);
static DBIResult IntlFillTable(hDBIDb hDb, pCHAR szTblName, pCHAR szTblType,
DFLOAT NumRecs);
static DBIResult IntlPutFieldSample(hDBICur hCur, pBYTE pRecBuf,
UINT16 FldNum, pFLDDesc pfldDesc);
static DBIResult IntlDisplayTable(hDBICur hCur, UINT32 uDisplayNRecs);
static const char szTblType[] = szPARADOX;
// Field descriptor used in creating the temporary table.
static SNIPFAR FLDDesc tmpFldDesc[] = {
{ // Field 1 - NUMERIC
1, "XNUM", fldFLOAT, fldUNKNOWN,
0, 0, 0, 0, 0, fldvNOCHECKS, fldrREADWRITE
}
}; // Array of field descriptors
static SNIPFAR FLDDesc OptFldDesc[] = {
{ 1, "LANGDRIVER", fldZSTRING, fldUNKNOWN,
DBIMAXTBLNAMELEN, 0, 0, DBIMAXSCFLDLEN, 0,
fldvNOCHECKS, fldrREADWRITE
}
}; // Array of field descriptors
//=====================================================================
// Function:
// LangDriver();
//
// Description:
// This sample code will create a Paradox table with the default
// Paradox language driver (as defined in the IDAPI configuration
// file), append 10 records to the table, and then delete the
// table. Field names, table names, and field data need to be
// converted when using non-ASCII characters. This code
// demonstrates how to do international support in IDAPI
// functions DbiGetLdName, DbiGetLdObj, DbiAnsiToNative and
// DbiNativeToAnsi.
//=====================================================================
void
LangDriver (void)
{
hDBIDb hDb; // Handle to the database
hDBICur hCur; // Handle to the table
CRTblDesc TblDesc; // Create table descriptor
UINT16 uDispNumRecs = 10 ; // Number of records to add
// and display
CHAR pDefLdName[DBIMAXNAMELEN]; // Default language driver
// name
pVOID pLdObj = NULL; // Language driver object
CHAR szDspTblName[DBIMAXNAMELEN]; // Buffer to hold table name
// for display (in ANSI
// character set)
UINT16 i; // Loop counter
BOOL bDataLoss; // Contains if data loss
// occured durring
// conversion
DBIResult rslt; // Return value from IDAPI
// functions
// Variables are declared local because they are changed within
// this example and need to be reset each time the example is run.
char szTblName[] = "ÇR8PXTßL";
// Field descriptor used in creating a table.
FLDDesc fldDesc[] = {
{ // Field 1 - ALPHA
1, // Field number
"ÄLPHÅ", // Field name
fldZSTRING, // Field type
fldUNKNOWN, // Field subtype
10, // Field size
0, // Decimal places ( 0 )
// computed
0, // Offset in record ( 0 )
0, // Length in bytes ( 0 )
0, // For Null bits ( 0 )
fldvNOCHECKS, // Validity checks ( 0 )
fldrREADWRITE // Rights
},
{ // Field 2 - NUMERIC
2, "ÑÜMERIC", fldFLOAT, fldUNKNOWN,
0, 0, 0, 0, 0, fldvNOCHECKS, fldrREADWRITE
},
{ // Field 3 - MONEY
3, "MÖNEY", fldFLOAT, fldstMONEY,
0, 0, 0, 0, 0, fldvNOCHECKS, fldrREADWRITE
},
{ // Field 4 - DATE
4, "DATÉ", fldDATE, fldUNKNOWN,
0, 0, 0, 0, 0, fldvNOCHECKS, fldrREADWRITE
},
{ // Field 5 - MEMO
5, "MÉMO", fldBLOB, fldstMEMO,
20, 0, 0, 0, 0, fldvNOCHECKS, fldrREADWRITE
}
}; // Array of field descriptors.
// The number of fields in the table.
const unsigned uNumFields = sizeof(fldDesc) / sizeof (fldDesc[0]);
Screen("*** Creating language independent applications ***\r\n");
BREAK_IN_DEBUGGER();
Screen(" Initializing IDAPI...");
if (InitAndConnect(&hDb) != DBIERR_NONE)
{
Screen("\r\n*** End of Example ***");
return;
}
Screen(" Setting the default database directory...");
rslt = DbiSetDirectory(hDb, (pCHAR)szTblDirectory);
ChkRslt(rslt, "SetDirectory");
// Table name is received from users in ANSI character set, but IDAPI
// expects it in OEM.
AnsiToOem((pCHAR)szTblName, (pCHAR)szTblName);
Screen(" Initializing the table descriptor...");
memset((void *) &TblDesc , 0, sizeof(CRTblDesc));
lstrcpy(TblDesc.szTblName, szTblName);
lstrcpy(TblDesc.szTblType, szTblType);
TblDesc.iFldCount = uNumFields;
// Translate field names in field descriptor from ANSI (as received
// from users) to the table's character set using table's language
// driver.
// Get default language driver name for specified table type. This
// will also be the language driver of the new table.
rslt = DbiGetLdName((pCHAR)szTblType, NULL, pDefLdName);
if (ChkRslt(rslt, "GetLdName") == DBIERR_NONE)
{
if (GetLdObjectFromLdName(hDb, pDefLdName, &pLdObj) == DBIERR_NONE)
{
for (i=0; i<uNumFields; i++)
{
rslt = DbiAnsiToNative(pLdObj, fldDesc[i].szName,
fldDesc[i].szName, NULL, &bDataLoss);
ChkRslt(rslt, "AnsiToNative");
}
}
else
{
CloseDbAndExit(&hDb);
Screen("\r\n*** End of Example ***");
return;
}
}
else
{
CloseDbAndExit(&hDb);
Screen("\r\n*** End of Example ***");
return;
}
TblDesc.pfldDesc = fldDesc;
// Create and overwrite the table using the default language driver
// defined in the IDAPI configuration file.
Screen(" Creating the Paradox table...");
rslt = DbiCreateTable(hDb, TRUE, &TblDesc);
if (ChkRslt(rslt, "CreateTable") != DBIERR_NONE)
{
CloseDbAndExit(&hDb);
Screen("\r\n*** End of Example ***");
return;
}
Screen(" Fill the table with random data...");
IntlFillTable(hDb, (pCHAR)szTblName, (pCHAR)szTblType, uDispNumRecs);
// Open the table which we just created. The table name should be
// translated from the DOS character set to ANSI for display.
OemToAnsi(szTblName, szDspTblName);
Screen(" Open the \"%s\" table...", szDspTblName);
rslt = DbiOpenTable(hDb, (pCHAR)szTblName, (pCHAR)szTblType,
NULL, NULL, 0, dbiREADWRITE, dbiOPENSHARED,
xltFIELD, FALSE, NULL, &hCur);
if (ChkRslt(rslt, "OpenTable") != DBIERR_NONE)
{
rslt = DbiDeleteTable(hDb, (pCHAR)szTblName, (pCHAR)szTblType);
ChkRslt(rslt, "DeleteTable");
CloseDbAndExit(&hDb);
Screen("\r\n*** End of Example ***");
return;
}
Screen(" Display the \"%s\" table which we just created...",
szDspTblName);
IntlDisplayTable(hCur, uDispNumRecs);
Screen("\r\n Close the table...");
rslt = DbiCloseCursor(&hCur);
ChkRslt(rslt, "CloseCursor");
Screen(" Deleting the table...");
rslt = DbiDeleteTable(hDb, (pCHAR)szTblName, (pCHAR)szTblType);
ChkRslt(rslt, "DeleteTable");
Screen(" Close the database and exit IDAPI...");
CloseDbAndExit(&hDb);
Screen("\r\n*** End of Example ***");
}
//=====================================================================
// Function:
// GetLdObjectFromLdName(hDb, pLdName, ppLdObj)
//
// Input: hDb - Database handle
// pLdName - Language driver name
//
// Return: DBIResult - Success of the opperation
//
// Description:
// This function is used to get the language driver (LD) object from
// an LD name rather than from a table cursor (as in DbiGetLdObj).
// This allows us to get the LD object before a table is created.
// If a table exists, you may use DbiGetLdObj to get the LD object.
// The function creates a temporary table "__X123" (using optional
// parameters to specify the language driver name) and gets the LD
// object from the table. The temporary table will be deleted upon
// exiting IDAPI.
//=====================================================================
DBIResult
GetLdObjectFromLdName (hDBIDb hDb, pCHAR pLdName, ppVOID ppLdObj)
{
hDBICur hTmpCur; // Handle to the table
pCRTblDesc pTmpTblDesc; // Create table descriptor
DBIResult rslt; // Return value
DBIResult rslt2; // Return value to use during cleanup
CHAR szTmpTblName[] = "__X123";
pTmpTblDesc = (pCRTblDesc)malloc(sizeof(CRTblDesc));
// Initialize the Table create descriptor.
memset((void *) pTmpTblDesc , 0, sizeof(CRTblDesc));
lstrcpy(pTmpTblDesc->szTblName, szTmpTblName);
lstrcpy(pTmpTblDesc->szTblType, szPARADOX);
pTmpTblDesc->iFldCount = 1;
pTmpTblDesc->pfldDesc = tmpFldDesc;
pTmpTblDesc->iOptParams = 1;
pTmpTblDesc->pfldOptParams = OptFldDesc;
pTmpTblDesc->pOptData = (pBYTE)pLdName;
// Create and overwrite the table using specific language driver
// passed to the function.
rslt = DbiCreateTable(hDb, TRUE, pTmpTblDesc);
ChkRslt(rslt, "CreateTable");
if (rslt != DBIERR_NONE)
{
free(pTmpTblDesc);
Screen("\r\n GetLdObjectFromLdName\r\n");
return rslt;
}
rslt = DbiOpenTable(hDb, szTmpTblName, szPARADOX, NULL, NULL,
NULL, dbiREADONLY, dbiOPENSHARED, xltNONE,
FALSE, NULL, &hTmpCur);
ChkRslt(rslt, "OpenTable");
if (rslt != DBIERR_NONE)
{
free(pTmpTblDesc);
return rslt;
}
// Get LD object.
rslt = DbiGetLdObj(hTmpCur, ppLdObj);
ChkRslt(rslt, "GetLdObj");
if (rslt != DBIERR_NONE)
{
rslt2 = DbiCloseCursor(&hTmpCur);
ChkRslt(rslt2, "CloseCursor");
rslt2 = DbiDeleteTable(hDb, (pCHAR)szTmpTblName, (pCHAR)szTblType);
ChkRslt(rslt2, "DeleteTable");
free(pTmpTblDesc);
return rslt;
}
free(pTmpTblDesc);
rslt = DbiCloseCursor(&hTmpCur);
ChkRslt(rslt, "CloseCursor");
rslt = DbiDeleteTable(hDb, (pCHAR)szTmpTblName, (pCHAR)szTblType);
ChkRslt(rslt, "DeleteTable");
return rslt;
}
//=====================================================================
// Function:
// IntlFillTable(hDb, szTblName, szTblType, NumRecs);
//
// Input: hDb - The database handle
// szTblName - Name of the table to fill
// szTblTyps - Type of the table to fill
// NumRecs - The number of records to insert
//
// Return: DBIResult - Success of the operation
//
// Description:
// This function adds the specified number of records to
// the table containing random data.
//=====================================================================
DBIResult
IntlFillTable (hDBIDb hDb, pCHAR szTblName, pCHAR szTblType, DFLOAT NumRecs)
{
DBIResult rslt; // Return value from IDAPI functions
DFLOAT fRecCount; // Loop variable = count of records
UINT16 FldCntr; // Field counter
pBYTE pRecBuf = NULL; // Pointer to the record buffer
FLDDesc fldDesc; // Field descriptor
CURProps TblProps; // Table descriptor
hDBICur hCur; // Handle to the table
hDBICur hFldList; // Handle to the field list table
rslt = DbiOpenTable(hDb, szTblName, szTblType, NULL, NULL, 0,
dbiREADWRITE, dbiOPENSHARED, xltFIELD, FALSE,
NULL, &hCur);
if (ChkRslt(rslt,"OpenTable") != DBIERR_NONE)
{
return rslt;
}
// Create an in-memory table that contains a list of fields. Note
// that logical (i.e. IDAPI types), are being requested instead of
// driver types.
rslt = DbiOpenFieldList(hDb, szTblName, szTblType, FALSE, &hFldList);
if (ChkRslt(rslt,"OpenFieldList")!= DBIERR_NONE)
{
rslt = DbiCloseCursor(&hCur);
ChkRslt(rslt, "CloseCursor");
return rslt;
}
// Append the records if the list and table are available.
if (hCur && hFldList)
{
ChkRslt(DbiGetCursorProps(hCur, &TblProps),
"GetCursorProps");
pRecBuf = (pBYTE) malloc(TblProps.iRecBufSize);
if (!pRecBuf)
{
Screen("Out of Memory");
rslt = DbiCloseCursor(&hCur);
ChkRslt(rslt, "CloseCursor");
rslt = DbiCloseCursor(&hFldList);
ChkRslt(rslt, "CloseCursor");
return DBIERR_NOMEMORY;
}
// Loop until the specified number of records have been written
// to the table.
for (fRecCount = 0; fRecCount < NumRecs; fRecCount++)
{
// Make sure we're starting with a clean record buffer.
rslt = DbiInitRecord(hCur, pRecBuf);
ChkRslt(rslt, "InitRecord");
FldCntr = 1;
rslt = DbiSetToBegin(hFldList);
ChkRslt(rslt, "SetToBegin");
// This loop will use the previously opened field list to
// determine what type of data is inserted into the table.
while (DbiGetNextRecord(hFldList, dbiNOLOCK, (pBYTE) &fldDesc,
NULL) == DBIERR_NONE)
{
// Put field data into the record buffer.
IntlPutFieldSample(hCur, pRecBuf, FldCntr, &fldDesc);
FldCntr++;
}
// All fields have been inserted into the record buffer. Now
// we need to append the record to the table.
rslt = DbiAppendRecord(hCur, pRecBuf);
ChkRslt(rslt, "AppendRecord") ;
// Make sure to close all BLOBs (opened when data was put into
// the record buffer).
FldCntr = 1;
rslt = DbiSetToBegin(hFldList);
ChkRslt(rslt, "SetToBegin");
while (DbiGetNextRecord(hFldList, dbiNOLOCK, (pBYTE) &fldDesc,
NULL) == DBIERR_NONE)
{
if (fldDesc.iFldType == fldBLOB)
{
rslt = DbiFreeBlob(hCur, pRecBuf, FldCntr);
ChkRslt(rslt, "FreeBlob");
}
FldCntr++;
}
}
// Free allocated record buffer.
free((pCHAR) pRecBuf);
}
// Clean up and return.
rslt = DbiCloseCursor(&hFldList);
ChkRslt(rslt, "CloseCursor");
rslt = DbiCloseCursor(&hCur);
ChkRslt(rslt, "CloseCursor");
return DBIERR_NONE;
}
//=====================================================================
// Function:
// IntlPutFieldSample(hCur, pRecBuf, FldNum, pfldDesc);
//
// Input: hCur - The handle for the table to fill
// pRecBuf - The record buffer to insert data into
// FldNum - The field we are generating
// pfldDesc - A descriptor that describes the field to generate
//
// Return: Result returned from DbiPutField()
//
// Description:
// This routine is used to put field data into a record
// buffer. Note that all logical field types are covered. You
// will need to refer to documentation, or run the DRVCAPS.C
// example for physical to logical field mappings.
//=====================================================================
DBIResult
IntlPutFieldSample (hDBICur hCur, pBYTE pRecBuf, UINT16 FldNum,
pFLDDesc pfldDesc)
{
pBYTE pBuf; // Buffer which contains the record data
DBIResult rslt; // Return value from IDAPI functions
INT16 i; // Loop counter
INT16 BlobSize; // Size of the BLOB
BOOL bDataLoss; // If any data is lost in translation
BOOL Bool; // Used for fldBOOL
INT16 Int16; // Used for fldINT16
UINT16 uInt16; // Used for fldUINT16
INT32 Int32; // Used for fldINT32
UINT32 uInt32; // Used for fldUINT32
DFLOAT Float; // Used for fldFLOAT
FMTBcd fmtBcd; // Used for fldBCD
DBIDATE Date; // Used for fldDATE
TIME Time; // Used for fldTIME
TIMESTAMP tStamp; // Used for fldTIMESTAMP
UINT16 month; // Used in generating the date
UINT16 day; // Used in generating the date
UINT16 year; // Used in generating the date
UINT16 hour; // Used in generating the time
UINT16 min; // Used in generating the time
UINT16 sec; // Used in generating the time
pVOID pLdObj = NULL; // Table's language driver object
// Allocate a generic buffer (used for string & blob fields).
pBuf = (pBYTE) malloc(4096);
if (!pBuf)
{
Screen(" Error - Out of memory.");
return DBIERR_NOMEMORY;
}
// This section contains sample code demonstrating how to
// insert a field of any type into a record buffer. Random data
// is used by this example. Field data is assumed to be in the ANSI
// character set, and needs to be translated into the table's
// character set before being inserted in the table.
// Get tables language driver.
rslt = DbiGetLdObj(hCur, &pLdObj);
ChkRslt(rslt, "GetLdObj");
switch (pfldDesc->iFldType)
{
case fldBYTES:
case fldZSTRING:
sprintf((pCHAR)pBuf, "Fïéld #%d", FldNum);
// Translate the character string. If table's language
// driver is based on the ANSI character set, no translation
// is performed.
rslt = DbiAnsiToNative(pLdObj, (pCHAR)pBuf, (pCHAR)pBuf, NULL,
&bDataLoss);
ChkRslt(rslt, "AnsiToNative");
// Put the data into the record buffer.
rslt = DbiPutField(hCur, FldNum, pRecBuf, pBuf);
break;
case fldDATE:
// Randomly generate and encode a date.
month = (rand() % 12) + 1;
day = (rand() % 20) + 1;
year = (rand() % 99) + 1900;
rslt = DbiDateEncode(month, day, year, &Date);
ChkRslt(rslt, "DateEncode");
// Put the data into the record buffer.
rslt = DbiPutField(hCur, FldNum, pRecBuf, (pBYTE) &Date);
break;
case fldBLOB:
// Generate a blob with length from 10-4010 bytes.
BlobSize = (rand() % 4000) + 11;
strcpy((pCHAR)pBuf, "BLÖB éxámple ");
// Write data to the BLOB field.
for (i = 0; i < (BlobSize % 11); i++)
{
strcat((pCHAR)pBuf, "BLÖB tèst ");
}
// Translate character data. If table's language
// driver is based on ANSI character set, no translation
// is performed.
rslt = DbiAnsiToNative(pLdObj, (pCHAR)pBuf, (pCHAR)pBuf, NULL,
&bDataLoss);
ChkRslt(rslt, "AnsiToNative");
// Init the BLOB header (contents defined by IDAPI client).
if ((pfldDesc->iSubType == fldstFMTMEMO) ||
(pfldDesc->iSubType == fldstOLEOBJ) ||
(pfldDesc->iSubType == fldstGRAPHIC))
{
memset(pBuf, 8, '\0');
}
// Open the BLOB prior to putting.
ChkRslt(DbiOpenBlob(hCur, pRecBuf, FldNum, dbiREADWRITE), "OpenBlob");
// Put the BLOB. Note that DbiFreeBlob() will be
// called after the record is inserted!
rslt = DbiPutBlob(hCur, pRecBuf, FldNum, 0, BlobSize,
pBuf);
break;
case fldBOOL:
// Boolean fields are either TRUE or FALSE.
if ((rand() % 100) < 50)
Bool = 1;
else
Bool = 0;
// Put the data into the record buffer.
rslt = DbiPutField(hCur, FldNum, pRecBuf, (pBYTE)&Bool);
break;
case fldINT16:
Int16 = (rand() % 255);
// Put the data into the record buffer.
rslt = DbiPutField(hCur, FldNum, pRecBuf, (pBYTE)&Int16);
break;
case fldBCD:
Float = (rand() / 1.21324);
rslt = DbiBcdFromFloat(&Float, pfldDesc->iUnits1,
pfldDesc->iUnits2, &fmtBcd);
ChkRslt(rslt, "BcdFromFloat");
// Put the data into the record buffer.
rslt = DbiPutField(hCur, FldNum, pRecBuf, (pBYTE)&fmtBcd);
break;
case fldLOCKINFO:
rslt = 0;
break;
case fldUINT16:
uInt16 = (rand() % 255);
// Put the data into the record buffer.
rslt = DbiPutField(hCur, FldNum, pRecBuf, (pBYTE)&uInt16);
break;
case fldINT32:
// Put the data into the record buffer if it is not an
// auto-increment field.
if (pfldDesc->iSubType != fldstAUTOINC)
{
Int32 = (rand() % 10000);
rslt = DbiPutField(hCur, FldNum, pRecBuf, (pBYTE)&Int32);
}
else
{
// Don't have to put a value into an auto-increment field,
// but make certain not to return an error.
rslt = 0;
}
break;
case fldUINT32:
uInt32 = (rand() % 10000);
// Put the data into the record buffer.
rslt = DbiPutField(hCur, FldNum, pRecBuf, (pBYTE)&uInt32);
break;
case fldFLOAT:
Float = (rand() % 128000L);
// Put the data into the record buffer.
rslt = DbiPutField(hCur, FldNum, pRecBuf, (pBYTE)&Float);
break;
case fldTIME:
// Randomize and encode a time value.
hour = (rand() % 23) + 1;
min = (rand() % 59) + 1;
sec = ((rand() * 2) % 59999U) + 1;
rslt = DbiTimeEncode( hour, min, sec, &Time);
ChkRslt(rslt, "TimeEncode");
// Put the data into the record buffer.
rslt = DbiPutField(hCur, FldNum, pRecBuf, (pBYTE)&Time);
break;
case fldTIMESTAMP:
// Encode a date and a time.
month = (rand() % 12) + 1;
day = (rand() % 20) + 1;
year = (rand() % 99) + 1900;
rslt = DbiDateEncode(month, day, year, &Date);
ChkRslt(rslt, "DateEncode");
hour = (rand() % 23) + 1;
min = (rand() % 59) + 1;
sec = ((rand() * 2) % 59999U) + 1;
rslt = DbiTimeEncode(hour, min, sec, &Time);
ChkRslt(rslt, "TimeEncode");
// Now encode and put the time stamp.
rslt = DbiTimeStampEncode(Date, Time, &tStamp);
ChkRslt(rslt, "TimeStampEncode");
// Put the data into the record buffer.
rslt = DbiPutField(hCur, FldNum, pRecBuf, (pBYTE)&tStamp);
break;
case fldVARBYTES:
// Init the size (1st two bytes) and contents.
*((int *) pBuf) = (pfldDesc->iUnits1 - 2);
for (i = 2; i < pfldDesc->iUnits1; i++)
{
pBuf[i] = (rand() % 90) + 32;
}
pBuf[i] = '\0';
// Put the data into the record buffer.
rslt = DbiPutField(hCur, FldNum, pRecBuf, (pBYTE)pBuf);
break;
default:
rslt = DBIERR_INVALIDFLDTYPE;
break;
}
// Determine if any of the previous DbiPutField functions failed.
ChkRslt(rslt, "PutField");
// Clean up and return.
free((pCHAR) pBuf);
return rslt;
}
//=====================================================================
// Function:
// DisplayTable(hCur, uDisplayNRecs);
//
// Input: The cursor handle - Which table to access
// DisplayNRecs - How many records to display
// (0 means display all records in the table.)
//
// Return: Result of displaying the records in the table
//
// Descrption:
// This function will display all records in the table referenced
// by the cursor. Records are read from the table in blocks,
// making this function faster than the DisplayInMemoryTable()
// function.
//
// Note: This function will only display the columns
// correctly when using a fixed pitch font.
//=====================================================================
DBIResult
IntlDisplayTable (hDBICur hCur, UINT32 uDisplayNRecs)
{
DBIResult rslt = DBIERR_NONE; // Return value from IDAPI functions
CURProps TblProps; // Table properties
pFLDDesc pFldDescs; // List of fields
pBYTE pRecBuf; // Record buffer
CHAR** ppszField; // Array to contain the fields of the
// table
pCHAR szFormat; // Contains an entire record (row)
CHAR szTemp[MAXLEN] =""; // Temporary variable for reading data
UINT16 uFldNum; // Loop variable
UINT16 uMaxNumRecs = 30; // Maximum number of record to read
// from the table at a time
UINT32 uNumRecs; // Number of records Read in from the
// table
UINT16 uCount; // Loop variable
UINT32 uCurCountRec = 0; // Counter to keep track of how many
// records have been displayed
const UINT16 uDefLength = 15; // Default size of a field
pVOID pLdObj = NULL; // Language driver object
BOOL bDataLoss; // Data loss parameter for character
// translation
rslt = DbiGetCursorProps(hCur, &TblProps);
if ((ChkRslt(rslt, "GetCursorProps")) != DBIERR_NONE)
{
return rslt;
}
// Allocate memory for the format string.
szFormat = (pCHAR)malloc(1400);
// Allocate space for the record buffer.
pRecBuf = (pBYTE)malloc(TblProps.iRecBufSize * sizeof(BYTE) *
uMaxNumRecs);
// Allocate enough space to contain information (field descriptors)
// about all the fields in the answer table.
pFldDescs = (pFLDDesc)malloc(TblProps.iFields * sizeof(FLDDesc));
if ((!pFldDescs) || (!pRecBuf) || (!szFormat))
{
if (szFormat) free(szFormat);
if (pRecBuf) free(pRecBuf);
if (pFldDescs) free(pFldDescs);
return DBIERR_NOMEMORY;
}
szFormat[0] = 0;
// Get information about the fields.
rslt = DbiGetFieldDescs(hCur, pFldDescs);
ChkRslt(rslt, "GetFieldDescs");
// Allocate enough buffers to contain data from the fields in the
// answer table. Also set the width of non-fldZSTRING fields
// (all data will be converted to strings for display.)
ppszField = (CHAR**)malloc(TblProps.iFields * sizeof(CHAR*));
if (!ppszField)
{
free(szFormat);
free(pRecBuf);
free(pFldDescs);
return DBIERR_NOMEMORY;
}
SetupFields(TblProps, pFldDescs, ppszField, uDefLength);
// Get table language driver to translate field names from table's
// character set to ANSI for display.
rslt = DbiGetLdObj(hCur, &pLdObj);
if ((ChkRslt(rslt, "GetLdObj")) != DBIERR_NONE)
{
free(szFormat);
free(pRecBuf);
free(pFldDescs);
return rslt;
}
// Format the names of the fields, aligned by column.
strcpy(szFormat,"\r\n ");
for (uFldNum = 0; uFldNum < TblProps.iFields; uFldNum++)
{
sprintf(szTemp, "%-*s\t", pFldDescs[uFldNum].iUnits1 + 1,
pFldDescs[uFldNum].szName);
strcat(szFormat, szTemp);
}
// Translate field names from table's character set to ANSI for display.
rslt = DbiNativeToAnsi(pLdObj, szFormat, szFormat, NULL,
&bDataLoss);
if ((ChkRslt(rslt, "NativeToAnsi")) != DBIERR_NONE)
{
free(szFormat);
free(pRecBuf);
free(pFldDescs);
return rslt;
}
// Display the header information (field names).
Screen(szFormat);
// Get records from the table until the end of the table is reached
// Note that not all field types are supported. All supported field
// types are displayed as strings.
// The DbiReadBlock function is used in case field mapping
// is taking place - the GetNextRec, GetPriorRec, and GetRelativeRec
// functions do not take field mapping into consideration.
uNumRecs = uMaxNumRecs; // Set the number of records to read from the
// table as a block
// If uCurCoutRec == 0, display all the records in the table.
if (uDisplayNRecs == 0)
{
uDisplayNRecs = (UINT16)-1; // uDisplayNRecs is unsigned, so
// -1 maximizes the value.
}
// Get the records from the table and display.
do
{
// Limit the number of records to be read from the table -
// do not want to display more than uDisplayNRecs records.
if ((uNumRecs + uCurCountRec) > uDisplayNRecs)
{
uNumRecs = uDisplayNRecs - uCurCountRec;
}
// Read a block of records - this is more efficient than reading
// records one at a time from the table.
rslt = DbiReadBlock(hCur, &uNumRecs, pRecBuf);
if ((rslt != DBIERR_EOF) && // DBIERR_EOF is an expected return
(rslt != DBIERR_NONE)) // code - means cannot read more records.
{
free(szFormat);
for (uFldNum = 0; uFldNum < TblProps.iFields; uFldNum++)
{
free(ppszField[uFldNum]);
}
free(ppszField);
free(pFldDescs);
free(pRecBuf);
return rslt;
}
for (uCount=0; uCount < uNumRecs; uCount++)
{
uCurCountRec++;
// Fill the record buffer with the field values.
GetFields(hCur, pFldDescs,
&pRecBuf[uCount * TblProps.iRecBufSize],
ppszField, uDefLength);
// Add leading blank space to the record.
strcpy(szFormat," ");
// Add each field to be displayed, making certain that the
// columns line up.
for (uFldNum = 0; uFldNum < TblProps.iFields; uFldNum++)
{
sprintf(szTemp, " %-*s\t", pFldDescs[uFldNum].iUnits1,
ppszField[uFldNum]);
strcat(szFormat, szTemp);
}
// Translate table data from table's character set to ANSI for
// display.
rslt = DbiNativeToAnsi(pLdObj, szFormat, szFormat, NULL,
&bDataLoss);
if ((ChkRslt(rslt, "NativeToAnsi")) != DBIERR_NONE)
{
// Clean up.
for (uFldNum = 0; uFldNum < TblProps.iFields; uFldNum++)
{
free(ppszField[uFldNum]);
}
free(szFormat);
free(ppszField);
free(pFldDescs);
free(pRecBuf);
}
// Display the record.
Screen(szFormat);
} // For ... uCount.
// While ReadBlock reads as many records as are supposed to be
// batched (uMaxNumRecs) and the maximum number of records have not
// been read from the table. Reading a smaller number of records than
// that specified in uMaxNumRecs indicates that the end of the table has
// been reached.
} while((uNumRecs == uMaxNumRecs) &&
(uCurCountRec < uDisplayNRecs));
// Expect the End-Of-File error - just means that there
// aren't any more records in the table.
if (rslt == DBIERR_EOF)
{
rslt = DBIERR_NONE;
}
// Clean up.
for (uFldNum = 0; uFldNum < TblProps.iFields; uFldNum++)
{
free(ppszField[uFldNum]);
}
free(szFormat);
free(ppszField);
free(pFldDescs);
free(pRecBuf);
return DBIERR_NONE;
}