Files
TeslaRel410/BORLAND/BDE/EXAMPLES/SNIPIT/SNIPTOOL.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

1865 lines
64 KiB
C++

// BDE - (C) Copyright 1995 by Borland International
// sniptool.c
#include "snipit.h"
#define MAXLEN 50
//===============================================================
// Function:
// Screen(Format, ...);
//
// Input: Format - A string that represents the format that
// the function vsprintf() uses
// ... - A varied number of input parameters (based
// on the needs of the format string)
//
// Return: None
//
// Description:
// This will build, and echo, a message.
//===============================================================
void
Screen (pCHAR Format, ...)
{
va_list argptr;
CHAR szMsg[1400];
pCHAR pBuf;
va_start(argptr, Format);
vsprintf(szMsg, Format, argptr);
va_end(argptr);
if (szMsg)
{
// Dump the string and output a CR+LF
pBuf = (pCHAR) malloc(lstrlen(szMsg) + 3);
wsprintf(pBuf, "%s\r\n", szMsg);
SendMsg(IDE_VIEWER_OUTPUT, EM_REPLACESEL, 0, (LPARAM)(LPCSTR)pBuf);
free(pBuf);
}
}
//==============================================================
// Function:
// ChkRslt(rslt, pMsg);
// Input: rslt - Return code from IDAPI
// pMsg - Null-terminated message
//
// Return: IDAPI return code passed in
//
// Description:
// This will echo an error message if the expected
// result does not equal the actual result. The output will be
// echoed to the screen.
//===============================================================
DBIResult
ChkRslt (DBIResult rslt, pCHAR pMsg)
{
DBIMSG dbi_status;
DBIErrInfo ErrInfo;
// Echo only if actual result doesn't equal expected result
if (rslt != DBIERR_NONE)
{
// Get as much error information as possible
DbiGetErrorInfo(TRUE, &ErrInfo);
// Make certain information is returned on the correct error
if (ErrInfo.iError == rslt)
{
Screen(" ERROR - %s"
"\r\n Cat:Code = [%xh:%xh]"
"\r\n %s",
pMsg, ErrCat(ErrInfo.iError), ErrCode(ErrInfo.iError),
ErrInfo.szErrCode);
if (strcmp(ErrInfo.szContext1, ""))
{
Screen(" %s",
ErrInfo.szContext1);
}
if (strcmp(ErrInfo.szContext2, ""))
{
Screen(" %s",
ErrInfo.szContext2);
}
if (strcmp(ErrInfo.szContext3, ""))
{
Screen(" %s",
ErrInfo.szContext3);
}
if (strcmp(ErrInfo.szContext4, ""))
{
Screen(" %s",
ErrInfo.szContext4);
}
}
else {
DbiGetErrorString(rslt, dbi_status);
Screen(" ERROR - %s Cat:Code [%xh:%xh]\r\n"
" %s",
pMsg, ErrCat(rslt), ErrCode(rslt), dbi_status);
}
}
return rslt;
}
//===============================================================
// Function:
// WinMsg(Msg, TypeMsg, TypeBtn);
//
// Input: Msg - The message to display
// TypeMsg - The type of messagebox to use (i.e. Stop,
// Information)
// TypeBtn - The buttons to use (i.e. Yes, No, OK, ...)
//
// Return: Response from the user
//
// Description:
// Display a message box and return a value representing
// the button the user pressed.
//================================================================
INT16
WinMsg (pCHAR pMsg, INT16 TypeMsg, INT16 TypeBtn)
{
INT16 Style, Buttons;
// Set the style of message box to display
switch (TypeMsg)
{
case MSG_INFO:
Style = MB_ICONINFORMATION;
break;
case MSG_QUESTION:
Style = MB_ICONQUESTION;
break;
case MSG_STOP:
Style = MB_ICONSTOP;
break;
default:
case MSG_EXCLAMATION:
Style = MB_ICONEXCLAMATION;
break;
}
// Set the style of buttons to make available
switch (TypeBtn)
{
case BTN_OK_CANCEL:
Buttons = MB_OKCANCEL;
break;
case BTN_RETRY_CANCEL:
Buttons = MB_RETRYCANCEL;
break;
case BTN_YES_NO:
Buttons = MB_YESNO;
break;
case BTN_YES_NO_CANCEL:
Buttons = MB_YESNOCANCEL;
break;
default:
case BTN_OK:
Buttons = MB_OK;
break;
}
return MessageBox(hMainWnd, (LPSTR) pMsg, "Code Viewer Message",
(WORD) Buttons | Style | MB_APPLMODAL);
}
//===============================================================
// Function:
// InitAndConnect(phDb);
//
// Input: phDb - Pointer to the database handle
//
// Return: IDAPI return code after DbiInit() and DbiOpenDatabase()
//
// Description:
// Initialize IDAPI and connect to a Standard
// database (non-SQL).
//================================================================
DBIResult
InitAndConnect (phDBIDb phDb)
{
DBIResult rslt;
// Initialize IDAPI with a NULL environment structure
rslt = DbiInit(NULL);
if (ChkRslt(rslt, "Init") == DBIERR_NONE)
{
DbiDebugLayerOptions(DEBUGON | OUTPUTTOFILE, "SNIPIT.INF");
// IDAPI initialized. Now open a Standard database (used to access
// Paradox and dBASE tables), by using a NULL database type.
rslt = DbiOpenDatabase(NULL, NULL, dbiREADWRITE, dbiOPENSHARED,
NULL, 0, NULL, NULL, phDb);
if (ChkRslt(rslt, "OpenDatabase") != DBIERR_NONE)
{
rslt = DbiExit();
ChkRslt(rslt, "Exit");
}
rslt = DbiSetPrivateDir(szPrivDirectory);
if (ChkRslt(rslt, "SetPrivateDir") != DBIERR_NONE)
{
CloseDbAndExit(phDb);
}
}
return rslt;
}
//===============================================================
// Function:
// InitAndConnect2(phDb);
//
// Input: phDb - Pointer to the database handle
//
// Return: IDAPI return code after DbiInit() and DbiOpenDatabase()
//
// Description:
// Initialize IDAPI and connect to a SQL database.
//================================================================
DBIResult
InitAndConnect2 (phDBIDb phDb)
{
DBIResult rslt;
FARPROC lpTempProc;
// Initialize IDAPI with a NULL environment structure.
*phDb = NULL;
rslt = DbiInit(NULL);
if (ChkRslt(rslt, "Init") == DBIERR_NONE)
{
DbiDebugLayerOptions(DEBUGON | OUTPUTTOFILE, "SNIPIT.INF");
// Get a handle to an IDAPI database (STANDARD database handle
// can be returned, but this is mainly used for SQL connections).
lpTempProc =
MakeProcInstance((FARPROC) ConnectDlgProc, hInst);
DialogBox(hInst, "ConnectDlg", hMainWnd, (DLGPROC) lpTempProc);
FreeProcInstance((FARPROC) lpTempProc);
// Return the handle (if connect worked).
if (SnipItDb)
*phDb = SnipItDb;
else
{
rslt = DbiExit();
ChkRslt(rslt, "Exit");
// Connect failed or CANCEL was hit.
rslt = DBIERR_INVALIDHNDL;
return rslt;
}
rslt = DbiSetPrivateDir(szPrivDirectory);
if (ChkRslt(rslt, "SetPrivateDir") != DBIERR_NONE)
{
CloseDbAndExit(phDb);
}
}
return rslt;
}
//===============================================================
// Function:
// CloseDbAndExit(phDb);
//
// Input: phDb - Pointer to the database handle
//
// Return: IDAPI return code after DbiCloseDatabase() and DbiExit()
//
// Description:
// Close the supplied database and exit IDAPI.
//================================================================
DBIResult
CloseDbAndExit (phDBIDb phDb)
{
DBIResult rslt;
// Close the supplied database
rslt = DbiCloseDatabase(phDb);
if (ChkRslt(rslt, "CloseDatabase") == DBIERR_NONE)
{
DbiDebugLayerOptions(0, NULL);
rslt = DbiExit();
ChkRslt(rslt, "Exit");
}
return rslt;
}
//=====================================================================
// Function:
// FillTable(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?
//
// Description:
// This function adds the specified number of records to
// the table. The records will contain random data.
//=====================================================================
DBIResult
FillTable (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
// Echo the message that the records are being inserted.
Screen(" Inserting %.0f records into the table...", NumRecs);
// Open the 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);
return(ChkRslt(rslt, "CloseCursor"));
}
// Append the records if the list and table are available
if (hCur && hFldList)
{
// Allocate a record buffer
rslt = DbiGetCursorProps(hCur, &TblProps);
ChkRslt(rslt, "GetCursorProps");
pRecBuf = (pBYTE) malloc(TblProps.iRecBufSize);
if (pRecBuf == NULL)
{
Screen(" Error - 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");
// Start at the beginning of the field list. Setting the
// cursor to the start of the table (i.e. BOF), does not leave
// you on a record. You are effectively left on a crack.
// Because of this, you will need to go to the next record in
// the table to reach the first record of the table.
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.
PutFieldSample(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, "InsertRecord");
// 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:
// CreateAndFillTable(hDb, pTblDesc, NumRecs, phCur);
//
// Input: hDb - Database handle
// pTblDesc - Pointer to a descriptor for the table to
// create
// phCur - Pointer to table cursor (NULL means do not
// open the table after creating
//
// Return: IDAPI return code
//
// Description:
// Create a table based on the table descriptor
// supplied. If "phCur != NULL" then the table will be opened,
// and the table cursor will be passed back through this parameter.
//================================================================
DBIResult
CreateAndFillTable (hDBIDb hDb, pCRTblDesc pTblDesc, DFLOAT NumRecs,
phDBICur phCur)
{
DBIResult rslt;
Screen(" Creating table \"%s\"...", pTblDesc->szTblName);
rslt = DbiCreateTable(hDb, TRUE, pTblDesc);
if (ChkRslt(rslt, "CreateTable") == DBIERR_NONE)
{
// Call the routine that will fill the table.
rslt = FillTable(hDb, pTblDesc->szTblName, pTblDesc->szTblType,
NumRecs);
// Open the table if the create and fill worked.
if ((rslt == DBIERR_NONE) && phCur)
{
rslt = DbiOpenTable(hDb, pTblDesc->szTblName,
pTblDesc->szTblType, NULL, NULL, 0,
dbiREADWRITE, dbiOPENSHARED, xltFIELD,
FALSE, NULL, phCur);
ChkRslt(rslt, "OpenTable");
}
}
return rslt;
}
//=====================================================================
// Function:
// DisplayInMemoryTable();
//
// Input: The cursor handle - which table to access
// DisplayNRecs - How many records to display
// (0 means all in the table)
//
// Return: Result of displaying the records in the table
//
// Description:
// This function will display all records in the table referenced
// by the cursor. This function is used to display
// in-memory and schema tables which do not support
// the use of ReadBlock ( which is used in DisplayTable )
//
// Note: This function will only display the columns
// correctly when using a fixed pitch font.
//=====================================================================
DBIResult
DisplayInMemoryTable (hDBICur hCur, UINT32 uDisplayNRecs)
{
DBIResult rslt; // IDAPI function return value
CURProps TblProps; // Table Properties
pFLDDesc pFldDescs; // List of fields
pBYTE pRecBuf; // Record Buffer
CHAR** pszField; // Array to contain the fields of the
// table.
CHAR* szFormat; // Contains an entire record (row)
CHAR szTemp[MAXLEN] =""; // Temporary variable for reading data
UINT16 uFldNum; // 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
szFormat = (pCHAR) malloc(1600 * sizeof(BYTE));
if (szFormat == NULL)
{
return DBIERR_NOMEMORY;
}
rslt = DbiGetCursorProps(hCur, &TblProps);
if (ChkRslt(rslt, "GetCursorProps") != DBIERR_NONE)
{
free(szFormat);
return rslt;
}
// Allocate space for the record buffer
pRecBuf = (pBYTE) malloc(TblProps.iRecBufSize * sizeof(BYTE));
if (pRecBuf == NULL)
{
Screen(" Error - Out of memory");
return DBIERR_NOMEMORY;
}
// 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 == NULL)
{
free(szFormat);
free(pRecBuf);
Screen(" Error - Out of memory");
return DBIERR_NOMEMORY;
}
// 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 sets the width of non-fldZSTRING fields
// (all data will be converted to strings for display )
pszField = (CHAR**) malloc(TblProps.iFields * sizeof(CHAR*));
// Set up formatting for the fields
SetupFields(TblProps, pFldDescs, pszField, uDefLength);
// Display 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);
}
// Display the header.
Screen(szFormat);
// Get records from the table until the end of the table is reached
// or the maximum number of records is reached.
// Note that not all field types are supported. All supported field
// types are displayed as strings.
if (uDisplayNRecs == 0)
{
uDisplayNRecs = (UINT16)-1; // uDisplayNRecs is unsigned, so
// -1 maximizes the value
}
while ((uCurCountRec < uDisplayNRecs) &&
((rslt = DbiGetNextRecord(hCur, dbiNOLOCK, pRecBuf, NULL))
== DBIERR_NONE))
{
// Fill the record buffer with the field values.
uCurCountRec++;
GetFields(hCur, pFldDescs, pRecBuf, pszField, uDefLength);
// Initialize szFormat to all zeroes.
memset(szFormat, 0, sizeof(szFormat));
// 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,
pszField[uFldNum]);
strcat(szFormat, szTemp);
}
// Display the record.
Screen(szFormat);
}
// Expect the End-Of-File error - just means that there
// are no more records in the table.
if (rslt == DBIERR_EOF)
rslt = DBIERR_NONE;
// Clean up.
for (uFldNum = 0; uFldNum < TblProps.iFields; uFldNum++)
{
free(pszField[uFldNum]);
}
free(pszField);
free(pFldDescs);
free(pRecBuf);
free(szFormat);
return rslt;
}
//=====================================================================
// Function:
// DisplayTable();
//
// 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
//
// Description:
// 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
DisplayTable (hDBICur hCur, UINT32 uDisplayNRecs)
{
DBIResult rslt; // IDAPI function return value
CURProps TblProps; // Table Properties
pFLDDesc pFldDescs; // List of fields
pBYTE pRecBuf; // Record Buffer
CHAR** pszField; // 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 records 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
// Allocate memory for the format string
szFormat = (pCHAR) malloc(2000);
if (szFormat == NULL)
{
Screen(" Error - Out of memory");
return DBIERR_NOMEMORY;
}
// Set szFormat == "".
szFormat[0] = 0;
// Get the size of the record buffer.
rslt = DbiGetCursorProps(hCur, &TblProps);
if (ChkRslt(rslt, "GetCursorProps") != DBIERR_NONE)
{
free(szFormat);
return rslt;
}
// Allocate space for the record buffer.
pRecBuf = (pBYTE) malloc(TblProps.iRecBufSize * sizeof(BYTE) *
uMaxNumRecs);
if (pRecBuf == NULL)
{
free(szFormat);
Screen(" Error - Out of memory");
return DBIERR_NOMEMORY;
}
// 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 == NULL)
{
free(szFormat);
free(pRecBuf);
Screen(" Error - Out of memory");
return DBIERR_NOMEMORY;
}
// 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 sets the width of non-fldZSTRING fields
// (all data will be converted to strings for display )
pszField = (CHAR**) malloc(TblProps.iFields * sizeof(CHAR*));
if (pszField == NULL)
{
free(szFormat);
free(pRecBuf);
free(pFldDescs);
Screen(" Error - Out of memory");
return DBIERR_NOMEMORY;
}
SetupFields(TblProps, pFldDescs, pszField, uDefLength);
// 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);
}
// 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.
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 total records than is specified
// in uDisplayNRecs.
if ((uNumRecs + uCurCountRec) > uDisplayNRecs)
{
uNumRecs = uDisplayNRecs - uCurCountRec;
}
// Read a block of records - reading more than one record at a
// time is more efficient than reading records one at a time from
// the table.
rslt = DbiReadBlock(hCur, &uNumRecs, pRecBuf);
if ((rslt != DBIERR_EOF) && (rslt != DBIERR_NONE))
{
ChkRslt(rslt, "ReadBlock");
free(szFormat);
for (uFldNum = 0; uFldNum < TblProps.iFields; uFldNum++)
{
free(pszField[uFldNum]);
}
free(pszField);
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],
pszField, 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,
pszField[uFldNum]);
strcat(szFormat, szTemp);
}
// 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. If fewer than uMaxNumRecs records were
// read, we reached the end of the table.
} while ((uNumRecs == uMaxNumRecs) && (uCurCountRec < uDisplayNRecs));
// Expect the End-Of-File error - just means that there
// are no more records in the table.
if (rslt == DBIERR_EOF)
{
rslt = DBIERR_NONE;
}
// Clean up.
for (uFldNum = 0; uFldNum < TblProps.iFields; uFldNum++)
{
free(pszField[uFldNum]);
}
free(szFormat);
free(pszField);
free(pFldDescs);
free(pRecBuf);
return DBIERR_NONE;
}
//=====================================================================
// Function:
// GetFields(hCur, pFldDescs, pRecBuf, pszField, uDefLength)
//
// Input: hCur - Handle to the Cursor
// pFldDescs - Field Descriptor
// pRecBuf - Record buffer - contains the record from
// which the field values are to be retrieved.
// pszField - Fields in the table
// uDefLength - Default length of a field
//
// Return: Success of the operation
//
// Description:
// This function is used to extract all field values from
// a record and place them into an array of strings.
//=====================================================================
DBIResult
GetFields (hDBICur hCur, pFLDDesc pFldDescs, pBYTE pRecBuf,
CHAR ** pszField, UINT16 uDefLength)
{
DBIResult rslt; // Return value from IDAPI functions
CURProps TblProps; // Properties of the table
UINT16 uFldNum; // Loop Counter - used to determine the
// current field
CHAR szTemp[MAXLEN] =""; // Temporary variable for reading data
UINT32 ulBlobSize; // Size of the BLOB
DFLOAT lfFloat; // Float value
BOOL bIsBlank; // Check if the field is blank
rslt = DbiGetCursorProps(hCur, &TblProps);
if (ChkRslt(rslt, "GetCursorProps") != DBIERR_NONE)
{
return rslt;
}
// Get the field values from the record. Gets each field from
// the table, placing the results in the pszField variable.
for (uFldNum = 0; uFldNum < TblProps.iFields; uFldNum++)
{
switch (pFldDescs[uFldNum].iFldType)
{
case fldBYTES:
case fldZSTRING:
rslt = DbiGetField(hCur, uFldNum+1, pRecBuf,
(pBYTE) pszField[uFldNum],
&bIsBlank);
ChkRslt(rslt, "GetField");
break;
case fldFLOAT:
rslt = DbiGetField(hCur, uFldNum+1, pRecBuf,
(pBYTE) szTemp, &bIsBlank);
ChkRslt(rslt, "GetField");
if (! bIsBlank)
{
if (pFldDescs[uFldNum].iSubType == fldstMONEY)
{
sprintf(pszField[uFldNum], "$%.2lf",
*(DFLOAT *)szTemp);
}
else
{
sprintf(pszField[uFldNum], "%.1lf",
*(DFLOAT *)szTemp);
}
// Format the number string.
FormatNumber(pszField[uFldNum]);
}
break;
case fldBCD:
rslt = DbiGetField(hCur, uFldNum+1, pRecBuf,
(pBYTE) szTemp, &bIsBlank);
ChkRslt(rslt, "GetField");
if ((! bIsBlank) && (szTemp[0]!='\0'))
{
rslt = DbiBcdToFloat((FMTBcd *)szTemp,
&lfFloat);
ChkRslt(rslt, " BcdToFloat");
sprintf(pszField[uFldNum], "%.*lf",
pFldDescs[uFldNum].iUnits2, lfFloat);
FormatNumber(pszField[uFldNum]);
}
break;
case fldDATE:
rslt = DbiGetField(hCur, uFldNum+1, pRecBuf,
(pBYTE) szTemp, &bIsBlank);
ChkRslt(rslt, "GetField");
if (! bIsBlank)
{
// Format the date.
FormatDate(*(DBIDATE *)szTemp,
pszField[uFldNum]);
}
break;
case fldTIME:
rslt = DbiGetField(hCur, uFldNum+1, pRecBuf,
(pBYTE)&szTemp, &bIsBlank);
ChkRslt(rslt, "GetField");
if (! bIsBlank)
{
FormatTime(*(TIME *)szTemp, pszField[uFldNum]);
}
break;
case fldTIMESTAMP:
rslt = DbiGetField(hCur, uFldNum+1, pRecBuf,
(pBYTE) szTemp, &bIsBlank);
ChkRslt(rslt, "GetField");
if (! bIsBlank)
{
FormatTimeStamp(*(TIMESTAMP *)szTemp,
pszField[uFldNum]);
}
break;
case fldINT16:
rslt = DbiGetField(hCur, uFldNum+1, pRecBuf,
(pBYTE) szTemp, &bIsBlank);
ChkRslt(rslt, "GetField");
if (! bIsBlank)
{
sprintf(pszField[uFldNum], "%d", *(DFLOAT *)szTemp);
}
break;
case fldUINT16:
rslt = DbiGetField(hCur, uFldNum+1, pRecBuf,
(pBYTE) szTemp, &bIsBlank);
ChkRslt(rslt, "GetField");
if (! bIsBlank)
{
sprintf(pszField[uFldNum], "%u", *(DFLOAT *)szTemp);
}
break;
case fldINT32:
rslt = DbiGetField(hCur, uFldNum+1, pRecBuf,
(pBYTE) szTemp, &bIsBlank);
ChkRslt(rslt, "GetField");
if (! bIsBlank)
{
sprintf(pszField[uFldNum], "%ld",
*(INT32 *)szTemp);
}
break;
case fldUINT32:
rslt = DbiGetField(hCur, uFldNum+1, pRecBuf,
(pBYTE) szTemp, &bIsBlank);
ChkRslt(rslt, "GetField");
if (! bIsBlank)
{
sprintf(pszField[uFldNum], "%lu",
*(UINT32 *)szTemp);
}
break;
case fldBOOL:
rslt = DbiGetField(hCur, uFldNum+1, pRecBuf,
(pBYTE) szTemp, &bIsBlank);
ChkRslt(rslt, "GetField");
if (! bIsBlank)
{
if (*(BOOL*)szTemp == 0)
{
strcpy(pszField[uFldNum], "No");
}
else
{
strcpy(pszField[uFldNum], "Yes");
}
}
break;
case fldBLOB:
// Display the first uDefLength characters of
// Memo BLOB fields.
if (pFldDescs[uFldNum].iSubType == fldstMEMO)
{
rslt = DbiOpenBlob(hCur, pRecBuf, (uFldNum + 1),
dbiREADONLY);
ChkRslt(rslt, "OpenBlob");
//Determine the size of the BLOB
rslt = DbiGetBlobSize(hCur, pRecBuf, (uFldNum + 1),
&ulBlobSize);
ChkRslt(rslt, "GetBlobSize");
// Determine the maximum amount to read
ulBlobSize = min((UINT32) ulBlobSize,
(UINT32) (uDefLength - 2));
// Get the BLOB from the table
rslt = DbiGetBlob(hCur, pRecBuf, (uFldNum + 1), 0,
ulBlobSize, (pBYTE) pszField[uFldNum],
&ulBlobSize);
ChkRslt(rslt, "GetBlob");
// Add the NULL terminator to the string.
pszField[uFldNum][(UINT16)ulBlobSize] = 0;
// Free the blob from memory.
rslt = DbiFreeBlob(hCur, pRecBuf, (uFldNum + 1));
ChkRslt(rslt, "FreeBlob");
}
else
{
strcpy(pszField[uFldNum], "Can't Display");
}
break;
default:
strcpy(pszField[uFldNum], "Can't Display");
break;
}
// Initialize the string in case the field was blank.
if (bIsBlank)
{
strcpy(pszField[uFldNum], "");
bIsBlank = FALSE;
}
}
return DBIERR_NONE;
}
//=====================================================================
// Function:
// SetupFields(TblProps, pFldDescs, pszField, uDefLength)
//
// Input: TblProps - Properties of the Table
// pFldDescs - Field Descriptor
// pszField - Fields in the table
// uDefLength - Default length of a field
//
// Return: DBIERR_NONE (success)
//
// Description:
// This function sets up the formatting of the fields.
//=====================================================================
DBIResult
SetupFields (CURProps TblProps, pFLDDesc pFldDescs, CHAR** pszField,
UINT16 uDefLength)
{
UINT16 uFldNum; // Loop variable
for (uFldNum = 0; uFldNum < TblProps.iFields; uFldNum++)
{
// Allocate enough space to contain the data in each field.
switch (pFldDescs[uFldNum].iFldType)
{
case fldBYTES:
case fldZSTRING:
pszField[uFldNum] = (CHAR*)malloc((pFldDescs[uFldNum].iLen
* sizeof(CHAR)));
if (MAXLEN - 4 < pFldDescs[uFldNum].iLen)
{
pFldDescs[uFldNum].iUnits1 = MAXLEN-4;
pFldDescs[uFldNum].iLen = MAXLEN-3;
}
// Adjust if the field is smaller than it's description.
if (pFldDescs[uFldNum].iLen <
strlen(pFldDescs[uFldNum].szName))
{
pFldDescs[uFldNum].iUnits1 =
strlen(pFldDescs[uFldNum].szName);
pFldDescs[uFldNum].iLen =
pFldDescs[uFldNum].iUnits1 - 1;
}
break;
case fldFLOAT:
case fldDATE:
case fldINT16:
case fldUINT16:
case fldINT32:
case fldUINT32:
case fldBOOL:
case fldBLOB:
case fldBCD:
pszField[uFldNum] = (CHAR*)malloc((uDefLength *
sizeof(CHAR)));
// Set the width of the field as it will be displayed
pFldDescs[uFldNum].iUnits1 = uDefLength-1;
pFldDescs[uFldNum].iLen = uDefLength;
// Adjust if the field is smaller than it's description
if (pFldDescs[uFldNum].iLen <
strlen(pFldDescs[uFldNum].szName))
{
pFldDescs[uFldNum].iUnits1 =
strlen(pFldDescs[uFldNum].szName);
pFldDescs[uFldNum].iLen =
pFldDescs[uFldNum].iUnits1 - 1;
}
break;
case fldTIMESTAMP:
pszField[uFldNum] = (CHAR*)malloc((36 *
sizeof(CHAR)));
// Set the width of the field as it will be displayed.
pFldDescs[uFldNum].iUnits1 = 36;
pFldDescs[uFldNum].iLen = 35;
// Adjust if the field is smaller than it's description.
if (pFldDescs[uFldNum].iLen <
strlen(pFldDescs[uFldNum].szName))
{
pFldDescs[uFldNum].iUnits1 =
strlen(pFldDescs[uFldNum].szName);
pFldDescs[uFldNum].iLen =
pFldDescs[uFldNum].iUnits1 - 1;
}
break;
case fldTIME:
pszField[uFldNum] = (CHAR*)malloc((20 *
sizeof(CHAR)));
// Set the width of the field as it will be displayed.
pFldDescs[uFldNum].iUnits1 = 20;
pFldDescs[uFldNum].iLen = 19;
// Adjust if the field is smaller than it's description.
if (pFldDescs[uFldNum].iLen <
strlen(pFldDescs[uFldNum].szName))
{
pFldDescs[uFldNum].iUnits1 =
strlen(pFldDescs[uFldNum].szName);
pFldDescs[uFldNum].iLen =
pFldDescs[uFldNum].iUnits1 - 1;
}
break;
default:
// This field size will hold the 'Not Supported'
// message.
pszField[uFldNum] = (CHAR*)malloc((uDefLength *
sizeof(CHAR)));
// Set the width of the field as it will be displayed.
pFldDescs[uFldNum].iUnits1 = uDefLength;
break;
}
}
return DBIERR_NONE;
}
//=====================================================================
// Function:
// PutFieldSample(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 for 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
PutFieldSample (hDBICur hCur, pBYTE pRecBuf, UINT16 FldNum,
pFLDDesc pfldDesc)
{
pBYTE pBuf; // Buffer which contains the record data
DBIResult rslt; // Return value from Paradox functions
INT16 i; // Loop counter
INT16 BlobSize; // Size of the BLOB
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
// Allocate a generic buffer (used for string and blob fields)
pBuf = (pBYTE) malloc(4096);
// This switch contains sample code that demonstrates how to
// insert a field of any type into a record buffer. Random data
// is used by this example.
switch (pfldDesc->iFldType)
{
case fldBYTES:
case fldZSTRING:
sprintf((pCHAR)pBuf, "Field #%d", FldNum);
// 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 size from 10-4010 bytes.
BlobSize = (rand() % 4000) + 11;
strcpy((pCHAR)pBuf, "BLOB example ");
// Write data to the BLOB field
for (i = 0; i < (BlobSize / 11); i++)
{
strcat((pCHAR)pBuf, "BLOB test ");
}
// 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.
rslt = DbiOpenBlob(hCur, pRecBuf, FldNum, dbiREADWRITE);
ChkRslt(rslt, "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 we don't 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:
// FormatDate (DBIDATE Date, pCHAR szDate)
//
// Input: DBIDATE - Date which needs to be formatted
// szDate - String to contain the formatted date
//
// Return: Result returned from DbiDateDecode()
//
// Description:
// This function is used to format date fields according to the
// settings in the IDAPI.CFG file.
//=====================================================================
DBIResult
FormatDate (DBIDATE Date, pCHAR szDate)
{
DBIResult rslt; // Return Value from IDAPI
FMTDate fmtDate; // Date Format
UINT16 uDay; // Day portion of date
UINT16 uMonth; // Month portion of date
INT16 iYear; // Year portion of date
// Get the formatting of the Date.
rslt = DbiGetDateFormat(&fmtDate);
ChkRslt(rslt, " GetDateFormat");
// Decode the date.
rslt = DbiDateDecode(Date, &uMonth, &uDay, &iYear);
ChkRslt(rslt, "DateDecode");
// Determine if date should be displayed year-biased.
if ((! fmtDate.bFourDigitYear) && fmtDate.bYearBiased)
{
iYear = iYear + 1900;
}
if (! fmtDate.bFourDigitYear)
{
iYear = iYear - 1900;
}
// Make certain the separator is not the
// escape character.
if (! strcmp(fmtDate.szDateSeparator, "\\"))
{
strcpy(fmtDate.szDateSeparator, "/");
}
// Format the date.
switch(fmtDate.iDateMode)
{
// MM/DD/YY - Month, Day, Year.
case 0:
sprintf(szDate,
"%0*d%s%0*d%s%0*d",
1 + fmtDate.bMonthLeadingZero,
uMonth,
fmtDate.szDateSeparator,
1 + fmtDate.bDayLeadingZero,
uDay,
fmtDate.szDateSeparator,
2,
iYear);
break;
// DD/MM/YY - Day, Month, Year.
case 1:
sprintf(szDate,
"%0*d%s%0*d%s%0*d",
1 + fmtDate.bDayLeadingZero,
uDay,
fmtDate.szDateSeparator,
1 + fmtDate.bMonthLeadingZero,
uMonth,
fmtDate.szDateSeparator,
2,
iYear);
break;
// YY/MM/DD - Year, Month, Day.
case 2:
sprintf(szDate,
"%0*d%s%0*d%s%0*d",
2,
iYear,
fmtDate.szDateSeparator,
1 + fmtDate.bMonthLeadingZero,
uMonth,
fmtDate.szDateSeparator,
1 + fmtDate.bDayLeadingZero,
uDay);
break;
}
return rslt;
}
//=====================================================================
// Function:
// FormatTime(Time, szTime)
//
// Input: TIME - Time which needs to be formatted
// szTime - String to contain the formatted time
//
// Return: Result returned from DbiTimeDecode()
//
// Description:
// This function is used to format time fields according to
// the settings in the IDAPI.CFG file.
//=====================================================================
DBIResult
FormatTime (TIME Time, pCHAR szTime)
{
DBIResult rslt; // Return value from IDAPI functions
FMTTime fmtTime; // Time format
UINT16 uHour; // Hour portion of the time
UINT16 uMinute; // Minute portion of the time
UINT16 uMilSec; // Second portion (in ms) of the time
UINT16 uIsAm; // Is Time AM?
CHAR szTemp[10]; // Temp buffer, used for AM, PM string
// Get the formatting of the time.
rslt = DbiGetTimeFormat(&fmtTime);
ChkRslt(rslt, "GetTimeFormat");
// Decode the time.
rslt = DbiTimeDecode(Time, &uHour, &uMinute, &uMilSec);
ChkRslt(rslt, "TimeDecode");
// Make certain the separator is not the
// escape character.
if (fmtTime.cTimeSeparator == '\\')
{
fmtTime.cTimeSeparator = '/';
}
// Check if time should be displayed in 12 or 24 hour format.
if (fmtTime.bTwelveHour)
{
// Temporary variable used to determine if the time is AM or PM.
uIsAm = uHour;
uHour = uHour % 12;
if (uHour == 0)
{
uHour = 12;
}
// If AM, set uIsAm to TRUE, else set uIsAm to 0.
if (uIsAm == uHour)
{
uIsAm = 1;
}
else
{
uIsAm = 0;
}
}
// Format the hour and minute of the time.
wsprintf(szTime, "%2u%c%02u",
uHour,
fmtTime.cTimeSeparator,
uMinute);
// Determine if seconds are to be displayed.
if (fmtTime.bSeconds)
{
wsprintf(szTemp, "%c%02u",
fmtTime.cTimeSeparator,
(uMilSec / 1000));
strcat(szTime, szTemp);
// Determine if milliseconds are to be displayed.
if (fmtTime.bMilSeconds)
{
wsprintf(szTemp, "%c%03u",
fmtTime.cTimeSeparator,
(uMilSec % 1000));
strcat(szTime, szTemp);
}
}
// Add a string to the time if the time is 12-hour.
if (fmtTime.bTwelveHour)
{
// Add a space to the format.
strcat(szTime, " ");
// If AM.
if (uIsAm)
{
// Copy the AM string.
strcat(szTime, fmtTime.szAmString);
}
else // otherwise it's PM.
{
// Copy the PM string.
strcat(szTime, fmtTime.szPmString);
}
}
return rslt;
}
//=====================================================================
// Function:
// FormatTimeStamp(TimeStamp, szTime)
//
// Input: TIME - Time which needs to be formatted
// szTime - String to contain the formatted time
//
// Return: Result returned from DbiTimeStampDecode()
//
// Description:
// This function is used to format TimeStamp fields according
// to the settings in the IDAPI.CFG file. It calls the
// FormatDate and FormatTime functions which are defined
// above.
//=====================================================================
DBIResult
FormatTimeStamp (TIMESTAMP TimeStamp, pCHAR szTimeStamp)
{
DBIResult rslt; // Return value from IDAPI functions
TIME Time; // Time portion of the TimeStamp
DBIDATE Date; // Date portion of the TimeStamp
CHAR szDate[15]; // Date string
CHAR szTime[20]; // Time String
// Get the date and time components.
rslt = DbiTimeStampDecode(TimeStamp, &Date, &Time);
ChkRslt(rslt, "TimeStampDecode");
// Get the Date format.
FormatDate(Date, szDate);
// Get the Time format.
FormatTime(Time, szTime);
// Format the TimeStamp.
wsprintf(szTimeStamp, "%s, %s", szTime, szDate);
return rslt;
}
//=====================================================================
// Function:
// FormatNumber(szNumber)
//
// Input: szNumber - String that contains number in US format
//
// Return: Result returned from DbiGetNumberFormat()
//
// Description:
// This function is used to format number fields according to
// the settings in the IDAPI.CFG file.
//=====================================================================
DBIResult
FormatNumber (pCHAR szNumber)
{
DBIResult rslt = DBIERR_NONE; // Return value from IDAPI functions
FMTNumber fmtNumber; // Number Format
pCHAR ptr;
int period = '.'; //Default US decimal separetor
// Get the formatting of the Number
rslt = DbiGetNumberFormat(&fmtNumber);
ChkRslt(rslt, " GetNumberFormat.");
ptr = strchr(szNumber, period);
if (ptr)
{
*ptr = fmtNumber.cDecimalSeparator;
}
return rslt;
}
//=====================================================================
// Function:
// MakeFullPath (pszDirectory, pszRelativeDirectory)
//
// Input: pszDirectory - String to contain the path to the
// tables directory
// pszRelativeDirectory - String which contains the relative
// offset from the current directory
//
// Return: int - If the directory exists
//
// Description:
// This function is used to get the fully qualified path to
// the directory which will contain the tables. This function
// will only work when pszRelativeDirectory contains either "."
// an absolute path, or <..\\..\\>TABLES.
//=====================================================================
int
MakeFullPath (pCHAR pszDirectory, pCHAR pszRelativeDirectory)
{
int iExists; // Does the directory exist?
int iLen; // Length of the path
int iLoop; // Loop counter
int iDepth = 0; // How relative the directory is
// Assume absolute path if second character is a ':'.
if (pszRelativeDirectory[1] == ':')
{
strcpy(pszDirectory, pszRelativeDirectory);
}
else if (!strcmp(pszRelativeDirectory, "."))
{
// Get the current working directory.
getcwd(pszDirectory, DBIMAXPATHLEN);
}
else
{
// Get the current working directory.
getcwd(pszDirectory, DBIMAXPATHLEN);
iLen = strlen(pszDirectory);
// Remove relative parts of the path.
iDepth = 0;
while (!strncmp(&pszRelativeDirectory[iDepth * 3], "..\\", 3))
{
for (iLoop = iLen; iLoop > -1; iLoop = iLoop - 1)
{
if (pszDirectory[iLoop] == '\\')
{
break;
}
}
iLen = iLoop - 1;
iDepth++;
}
// Copy the 'TABLES' directory to form the full path to the tables.
// Need to move szDirectory past the '\\' and szTblDirectory
// past the '..\\'.
strcpy(&pszDirectory[iLoop+1], &pszRelativeDirectory[(3 * iDepth)]);
}
// Check if the directory exists.
iExists = access(pszDirectory, 00);
return iExists;
}
//=====================================================================
// Function:
// DisplayNextRecord(hCur)
//
// Input: Handle to the cursor
//
// Return: DBIERR_SUCCESS
//
// Description:
// This function will call DisplayInMemoryTable() with a value
// of 1 for the second parameter. This causes it to display the
// next record.
//=====================================================================
DBIResult
DisplayNextRecord(hDBICur hCur)
{
return(DisplayInMemoryTable(hCur, 1));
}
//=====================================================================
// Function:
// DisplayCurrentRecord(hCur);
//
// Input: hCur - Cursor handle - which table to access
//
// Return: Result of displaying the records in the table
//
// Description:
// This function will display the current record only.
//
// Note: This function will only display the columns
// correctly when using a fixed pitch font.
//=====================================================================
DBIResult
DisplayCurrentRecord (hDBICur hCur)
{
DBIResult rslt; // IDAPI function return value
CURProps TblProps; // Table Properties
pFLDDesc pFldDescs; // List of fields
pBYTE pRecBuf; // Record Buffer
CHAR** pszField; // Array to contain the fields of the
// table.
CHAR* szFormat; // Contains an entire record (row)
CHAR szTemp[MAXLEN] =""; // Temporary variable for reading data
UINT16 uFldNum; // Loop variable
const UINT16 uDefLength = 15; // Default size of a field
szFormat = (pCHAR) malloc(1600 * sizeof(BYTE));
if (szFormat == NULL)
{
return DBIERR_NOMEMORY;
}
rslt = DbiGetCursorProps(hCur, &TblProps);
if (ChkRslt(rslt, "GetCursorProps") != DBIERR_NONE)
{
free(szFormat);
return rslt;
}
// Allocate space for the record buffer.
pRecBuf = (pBYTE) malloc(TblProps.iRecBufSize * sizeof(BYTE));
if (pRecBuf == NULL)
{
return DBIERR_NOMEMORY;
}
// 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 == NULL)
{
free(szFormat);
free(pRecBuf);
return DBIERR_NOMEMORY;
}
// 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).
pszField = (CHAR**)malloc(TblProps.iFields * sizeof(CHAR*));
// Set up formatting for the fields.
SetupFields(TblProps, pFldDescs, pszField, uDefLength);
// Display 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);
}
// Display the header.
Screen(szFormat);
rslt = DbiGetRecord(hCur, dbiNOLOCK, pRecBuf, NULL);
ChkRslt(rslt, "GetRecord");
// Fill the record buffer with the field values.
GetFields(hCur, pFldDescs, pRecBuf, pszField, uDefLength);
// Initialize szFormat to all zeroes.
memset(szFormat, 0, sizeof(szFormat));
// 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,
pszField[uFldNum]);
strcat(szFormat, szTemp);
}
// Display the record.
Screen(szFormat);
// Expect the End-Of-File error - just means that there
// are no more records in the table.
if (rslt == DBIERR_EOF)
{
rslt = DBIERR_NONE;
}
// Clean up.
for (uFldNum = 0; uFldNum < TblProps.iFields; uFldNum++)
{
free(pszField[uFldNum]);
}
free(pszField);
free(pFldDescs);
free(pRecBuf);
free(szFormat);
return rslt;
}