Files
TeslaRel410/BORLAND/BDE/EXAMPLES/PDOXWIN/RESTRUCT/STRUCTER.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

1188 lines
40 KiB
C++

// BDE - (C) Copyright 1995 by Borland International
#include "structer.h"
#include "macro.h"
#define szCURRENTMODULE "STRUCTER"
//=====================================================================
// This BDE example provides users a means of doing a limited Paradox and
// dBASE table restructure using Paradox for Windows ver. 5.0 ObjectPAL. The
// ObjectPAL procedures created are: AddField, DeleteField, ModifyField,
// and MoveField. You only need to use one procedure for an entire
// restructure.
//
// You can change field order, names, types, and sizes on local tables or on
// tables where the user has all rights to its directory. You can also add
// or delete fields and/or pack the table. Table properties are maintained
// (i.e. Validity Checks, Table Lookup, Secondary Indexes, etc.).
//
// Because you can already re-key a table with ObjectPAL, primary key
// operations are not done in this DLL. If adding, dropping, or copying
// (moving) a field in the the key you will need to remove the key with
// ObjectPAL (delete .PX), restructure with this DLL, and then reindex
// using ObjectPAL. You can modify a field in a primary key without
// removing the key.
//
// Also, because of the complexity of table encryption (passwords) this
// example only supports tables with no passwords.
//
//
// This is a Paradox Uses block:
//
// Uses structer
//
// DeleteField(tablePath cptr, tableName cptr, FieldName cptr,
// PackOrNoPack cptr, returnStringBuffer cptr)
//
// MoveField(tablePath cptr, tableName cptr,
// NewFieldPosition cword, CurrentFieldName cptr,
// PackOrNoPack cptr, returnStringBuffer cptr)
//
// AddField(tablePath cptr, tableName cptr, NewFieldPosition
// cword, FieldName cptr, FieldType cptr, FieldSize cword,
// PackOrNoPack cptr, returnStringBuffer cptr)
//
// ModifyField(tablePath cptr, tableName cptr,
// FieldName cptr, NewFieldName cptr, FieldType cptr,
// FieldSize cword, PackOrNoPack cptr,
// returnStringBuffer cptr)
//
// endUses
//
//
// Return value: (returnStringBuffer) "Restructure successful." or an error.
// Using the return value is optional.
//
//
// And some typical methods:
//
// Var ; on the form level
// returnStringBuffer String
// endVar
//
// method open(var eventInfo Event)
// ; requires a 129 byte buffer:
// returnStringBuffer = space(129)
// endmethod
//
// method mouseDown(var eventInfo MouseEvent)
// DeleteField(workingdir(), "test.dbf", "Company", "PACK",
// returnStringBuffer)
// message(returnStringBuffer)
// endmethod
//
// method mouseDown(var eventInfo MouseEvent)
// MoveField(workingdir(), "test", 2, "Phone", "NOPACK",
// returnStringBuffer)
// message(returnStringBuffer)
// endmethod
//
// method mouseDown(var eventInfo MouseEvent)
// AddField(workingdir(), "test", 2, "autoincre", "+", 0, "PACK",
// returnStringBuffer)
// message(returnStringBuffer)
// endmethod
//
// method mouseDown(var eventInfo MouseEvent)
// ModifyField(workingdir(), "test", "Company", "Company Name", "A",
// 50, "NOPACK", returnStringBuffer)
// message(returnStringBuffer)
// endmethod
//
//
// Arguments used with DeleteField:
//
// 1st and 2nd argument: the table Path and the table name (.db is optional,
// and .dbf is
// required)
// 3th argument: the current field name
// 4th argument: specify "PACK" or "NOPACK" (anything but "PACK" does not
// pack the table)
// 5th argument: return value
//
// Arguments used with MoveField:
//
// 1st and 2nd argument: the table Path and the table name
// 3rd argument: the new field position
// 4th argument: the current field name
// 5th argument: specify "PACK" or "NOPACK"
// 6th argument: return value
//
//
// Arguments used with AddField and ModifyField:
//
// 1st and 2nd argument: the table Path and the table name
// 3rd argument: the new field position
// 4th argument: the current field name
// 5th argument: the new field type:
//
// Paradox types: dBASE types:
// "A" = Alpha "C" = Character
// "N" = Number "F" = Float
// "$" = Money "N" = Number
// "S" = Short "D" = Date
// "I" = Long Integer "L" = Logical
// "#" = BCD "M" = Memo
// "D" = Date "O" = OLE
// "T" = Time "B" = Binary
// "@" = Timestamp
// "M" = Memo
// "F" = Formatted Memo
// "G" = Graphic
// "O" = OLE
// "L" = Logical
// "+" = Autoincrement
// "B" = Binary
// "Y" = Bytes
//
// 6th argument: Field size
// Needs a valid number. If a type requires no size, then use 0.
// 7th argument: specify "PACK" or "NOPACK"
// 8th argument: return value
//
//
// Other notes:
//
// Follow the standard rules for all field types (i.e. you can
// convert existing number, short, and long integer fields to
// autoincrement fields if the field is the table's single-field
// primary index (key). Use correct field sizes (0 for no size).)
//
// Changes get ignored outside of these rules and give various BDE
// errors such as "Invalid field type" or "Invalid field descriptor".
//
// Make sure that you have enough file handles (IDAPI maxfilehandles
// + 20). Only use full, absolute paths for tablePathOrAlias. Relative
// paths are not supported.
// Using too few or too many parameters the Paradox Uses block
// WILL CAUSE A GPF!! (in Pdoxwin).
//=====================================================================
//=====================================================================
// Function:
// AddField(pCHAR pTblDir, pCHAR pTblName, int iNewFldNum,
// pCHAR pNewName, pCHAR pFldType, UINT16 iUnits1,
// pCHAR pPack, pCHAR pszRetBuffer)
//
// Description:
// This example shows how to change the characteristics of a
// table, just adding one field.
//
//=====================================================================
void FAR WINAPI _export
AddField (pCHAR pTblDir, pCHAR pTblName, int iNewFldNum,
pCHAR pNewName, pCHAR pFldType, UINT16 iUnits1, pCHAR pPack,
pCHAR pszRetBuffer)
{
CHAR szFldType[1] = {"\0"}; // for user field type code
HGLOBAL hglbCorrectTableInfo; // handle to TableInfo struct
// store field type code
sprintf(szFldType, "%s", pFldType);
// initialize buffer for return string
memset(pszRetBuffer, 0, (DBIMAXMSGLEN +1) * sizeof(char));
// initialize handle to TableInfo struct
hglbCorrectTableInfo = NULL;
// allocate memory for TableInfo struct
hglbCorrectTableInfo = (struct TBLINFO*) GlobalAlloc (GMEM_MOVEABLE,
sizeof(struct TBLINFO));
if (hglbCorrectTableInfo == NULL)
{
GetString(1, pszRetBuffer); //"Out of Memory."
CLEANUP_NODISPLAY;
}
// get return string from calling the first function
// set the new number of fields to + 1
BeginRestructure(hglbCorrectTableInfo, pTblDir, pTblName, 1, pszRetBuffer);
if (!strcmp(pszRetBuffer, "\0"))
{
SetFieldDescriptions(hglbCorrectTableInfo, crADD, iNewFldNum,
pNewName, pNewName, szFldType, iUnits1,
pszRetBuffer);
}
if (!strcmp(pszRetBuffer, "\0"))
{
EndRestructure(hglbCorrectTableInfo, pPack, pszRetBuffer);
}
CleanUp:
if (hglbCorrectTableInfo)
{
cleanUpMemory(hglbCorrectTableInfo);
}
}
//=====================================================================
// Function:
// DeleteField(pCHAR pTblDir, pCHAR pTblName, pCHAR pOldName,
// pCHAR pPack, pCHAR pszRetBuffer)
//
// Description:
// This example shows how to change the characteristics of a
// table, just deleting one field.
//
//=====================================================================
void FAR WINAPI _export
DeleteField (pCHAR pTblDir, pCHAR pTblName, pCHAR pOldName, pCHAR pPack,
pCHAR pszRetBuffer)
{
CHAR szFldType[1] = {"\0"};
HGLOBAL hglbCorrectTableInfo;
memset(pszRetBuffer, 0, (DBIMAXMSGLEN +1) * sizeof(char));
hglbCorrectTableInfo = NULL;
hglbCorrectTableInfo = (struct TBLINFO*) GlobalAlloc (GMEM_MOVEABLE,
sizeof(struct TBLINFO));
if (hglbCorrectTableInfo == NULL)
{
GetString(1, pszRetBuffer); //"Out of Memory."
CLEANUP_NODISPLAY;
}
BeginRestructure(hglbCorrectTableInfo, pTblDir, pTblName, -1, pszRetBuffer);
if (!strcmp(pszRetBuffer, "\0"))
{
SetFieldDescriptions(hglbCorrectTableInfo, crDROP, 0, pOldName,
pOldName, szFldType, 0, pszRetBuffer);
}
if (!strcmp(pszRetBuffer, "\0"))
{
EndRestructure(hglbCorrectTableInfo, pPack, pszRetBuffer);
}
CleanUp:
if (hglbCorrectTableInfo)
{
cleanUpMemory(hglbCorrectTableInfo);
}
}
//=====================================================================
// Function:
// ModifyField(pCHAR pTblDir, pCHAR pTblName, pCHAR pOldName,
// pCHAR pNewName, pCHAR pFldType, UINT16 iUnits1,
// pCHAR pPack, pCHAR pszRetBuffer)
//
// Description:
// This example shows how to change the characteristics of a
// table, just modifying one field.
//
//=====================================================================
void FAR WINAPI _export
ModifyField (pCHAR pTblDir, pCHAR pTblName, pCHAR pOldName,
pCHAR pNewName, pCHAR pFldType, UINT16 iUnits1, pCHAR pPack,
pCHAR pszRetBuffer)
{
CHAR szFldType[1] = {"\0"};
HGLOBAL hglbCorrectTableInfo;
sprintf(szFldType, "%s", pFldType);
memset(pszRetBuffer, 0, (DBIMAXMSGLEN +1) * sizeof(char));
hglbCorrectTableInfo = NULL;
hglbCorrectTableInfo = (struct TBLINFO*) GlobalAlloc (GMEM_MOVEABLE,
sizeof(struct TBLINFO));
if (hglbCorrectTableInfo == NULL)
{
GetString(1, pszRetBuffer); //"Out of Memory."
CLEANUP_NODISPLAY;
}
BeginRestructure(hglbCorrectTableInfo, pTblDir, pTblName, 0, pszRetBuffer);
if (!strcmp(pszRetBuffer, "\0"))
{
SetFieldDescriptions(hglbCorrectTableInfo, crMODIFY, 0, pOldName,
pNewName, szFldType, iUnits1, pszRetBuffer);
}
if (!strcmp(pszRetBuffer, "\0"))
{
EndRestructure(hglbCorrectTableInfo, pPack, pszRetBuffer);
}
CleanUp:
if (hglbCorrectTableInfo)
{
cleanUpMemory(hglbCorrectTableInfo);
}
}
//=====================================================================
// Function:
// MoveField(pCHAR pTblDir, pCHAR pTblName, int iNewFldNum,
// pCHAR pOldName, pCHAR pPack, pCHAR pszRetBuffer)
//
// Description:
// This example shows how to change the characteristics of a
// table, just moving one field.
//
//=====================================================================
void FAR WINAPI _export
MoveField (pCHAR pTblDir, pCHAR pTblName, int iNewFldNum,
pCHAR pOldName, pCHAR pPack, pCHAR pszRetBuffer)
{
CHAR szFldType[1] = {"\0"};
HGLOBAL hglbCorrectTableInfo;
memset(pszRetBuffer, 0, (DBIMAXMSGLEN +1) * sizeof(char));
hglbCorrectTableInfo = NULL;
hglbCorrectTableInfo = (struct TBLINFO*) GlobalAlloc (GMEM_MOVEABLE,
sizeof(struct TBLINFO));
if (hglbCorrectTableInfo == NULL)
{
GetString(1, pszRetBuffer); //"Out of Memory."
CLEANUP_NODISPLAY;
}
BeginRestructure(hglbCorrectTableInfo, pTblDir, pTblName, 0, pszRetBuffer);
if (!strcmp(pszRetBuffer, "\0"))
{
SetFieldDescriptions(hglbCorrectTableInfo, crCOPY, iNewFldNum,
pOldName, "", szFldType, 0, pszRetBuffer);
}
if (!strcmp(pszRetBuffer, "\0"))
{
EndRestructure(hglbCorrectTableInfo, pPack, pszRetBuffer);
}
CleanUp:
if (hglbCorrectTableInfo)
{
cleanUpMemory(hglbCorrectTableInfo);
}
}
//=====================================================================
// Function:
// BeginRestructure(HGLOBAL hglbCorrectTableInfo, pCHAR pTblDir,
// pCHAR pTblName, int wNUMOFFIELDS,
// pCHAR pszRetBuffer)
//
// Input:
// from AddField(), DeleteField(), ModifyField(), or MoveField()
// hglbCorrectTableInfo - handle to TableInfo struct
// pTblDir - table directory
// pTblName - table name
// wNUMOFFIELDS - -1 (delete), 0 (move/modify), 1 (add)
// pszRetBuffer - return to client
//
// Return: (pszRetBuffer) null or error string.
//
// Description:
// This function allocates memory based on the new number of
// fields passed from the client, for example, Paradox. And,
// it gets the field descriptor for an existing cursor. The
// engine is not initialized or closed because it is in use
// by the client - Paradox for Windows. The private directory
// has also been set by Paradox.
//=====================================================================
void FAR WINAPI
BeginRestructure (HGLOBAL hglbCorrectTableInfo, pCHAR pTblDir, pCHAR pTblName,
int wNUMOFFIELDS, pCHAR pszRetBuffer)
{
DBIResult rslt;
UINT16 i; // loop counter
CURProps curProps; // table properties
struct TBLINFO *TableInfo; // pointer to TableInfo struct
CHAR szTblType1[] = szPARADOX; // table type (PARADOX)
CHAR szTblType2[] = szDBASE; // table type (DBASE)
// initialize return string to NULL
memset(pszRetBuffer, 0, (DBIMAXMSGLEN +1) * sizeof(char));
// make sure we have handle to TableInfo struct
CHKERR_NODISPLAY(hglbCorrectTableInfo == NULL);
// point to TableInfo struct
TableInfo = GlobalLock (hglbCorrectTableInfo);
if (TableInfo == NULL)
{
hglbCorrectTableInfo = NULL;
GetString(1, pszRetBuffer); //"Out of Memory."
CLEANUP_NODISPLAY;
}
// initialize TableInfo struct
TableInfo->pIdxDesc = NULL;
TableInfo->pFldDesc = NULL;
TableInfo->pFldDescriptor = NULL;
TableInfo->ecrFldOp = NULL;
TableInfo->uNumFields = 0;
TableInfo->uNewNumFields = 0;
TableInfo->hDb = NULL;
TableInfo->hCur = NULL;
TableInfo->retVal = 1;
TableInfo->bHasIndex = 0;
// initialize new table descriptor
memset(&TableInfo->crTblDesc, 0, sizeof(CRTblDesc));
// set new table descriptor to table name
strcpy(TableInfo->crTblDesc.szTblName, pTblName);
// open a database in the current session and get a database handle
CHKERR_CLEANUP(DbiOpenDatabase(NULL, NULL, dbiREADWRITE, dbiOPENEXCL,
NULL, 0, NULL, NULL, &TableInfo->hDb));
// set the current directory
CHKERR_CLEANUP(DbiSetDirectory(TableInfo->hDb, pTblDir));
// associate a cursor handle with an opened table
CHKERR_CLEANUP(DbiOpenTable(TableInfo->hDb, (pCHAR) pTblName, NULL,
NULL, NULL, 0, dbiREADWRITE, dbiOPENEXCL,
xltFIELD, FALSE, NULL, &TableInfo->hCur));
// set field translate mode no translation
CHKERR_CLEANUP(DbiSetProp(TableInfo->hCur, curXLTMODE, xltNONE));
// get the cursor properties for the existing table
CHKERR_CLEANUP(DbiGetCursorProps(TableInfo->hCur, &curProps));
// if table is password protected, cancel restructure
if (curProps.bProtected)
{
GetString(12, pszRetBuffer); //"Only tables without passwords are
// supported."
CLEANUP_NODISPLAY;
}
// if table is other than Paradox or dBASE, cancel restructure
if (strcmp(szTblType1, curProps.szTableType) && strcmp(szTblType2,
curProps.szTableType))
{
GetString(6, pszRetBuffer); //"Only Paradox and dBASE tables are
// supported."
CLEANUP_NODISPLAY;
}
// set new table descriptor to table type
strcpy(TableInfo->crTblDesc.szTblType, curProps.szTableType);
// if table has primary key, allocate memory for existing index descriptor
if (curProps.iIndexes)
{
TableInfo->bHasIndex = 1;
TableInfo->pIdxDesc =
(IDXDesc*) malloc (curProps.iIndexes * sizeof(IDXDesc));
if (TableInfo->pIdxDesc == NULL)
{
GetString(1, pszRetBuffer); //"Out of Memory."
CLEANUP_NODISPLAY;
}
}
// get existing number of fields
TableInfo->uNumFields = curProps.iFields;
// get new number of fields
TableInfo->uNewNumFields = curProps.iFields + wNUMOFFIELDS;
// allocate memory for existing field descriptor
TableInfo->pFldDesc =
(FLDDesc*) malloc (curProps.iFields * sizeof(FLDDesc));
if (TableInfo->pFldDesc == NULL)
{
GetString(1, pszRetBuffer); //"Out of Memory."
CLEANUP_NODISPLAY;
}
// allocate memory for new field descriptor
TableInfo->pFldDescriptor =
(FLDDesc*) malloc (TableInfo->uNewNumFields * sizeof(FLDDesc));
if (TableInfo->pFldDescriptor == NULL)
{
GetString(1, pszRetBuffer); //"Out of Memory."
CLEANUP_NODISPLAY;
}
// allocate memory for field operations array
TableInfo->ecrFldOp =
(CROpType*) malloc (TableInfo->uNewNumFields * sizeof(CROpType));
if (TableInfo->ecrFldOp == NULL)
{
GetString(1, pszRetBuffer); //"Out of Memory."
CLEANUP_NODISPLAY;
}
// get existing field descriptors
CHKERR_CLEANUP(DbiGetFieldDescs(TableInfo->hCur, TableInfo->pFldDesc));
CHKERR_CLEANUP(DbiSetProp(TableInfo->hCur, curXLTMODE, xltFIELD));
// initialize new field numbers and field operations array
for (i = 0; i < TableInfo->uNewNumFields; i++)
{
TableInfo->pFldDescriptor[i].iFldNum = -1;
TableInfo->ecrFldOp[i] = NULL;
}
TableInfo->retVal = 0;
CleanUp:
if (hglbCorrectTableInfo)
{
GlobalUnlock(hglbCorrectTableInfo);
hglbCorrectTableInfo = NULL;
}
}
//=====================================================================
// Function:
// SetFieldDescriptions(HGLOBAL hglbCorrectTableInfo,
// CROpType FieldOp, UINT16 iNewFldNum,
// pCHAR pOldName, pCHAR pNewName,
// pCHAR pFldType, UINT16 iUnits1,
// pCHAR pszRetBuffer)
//
// Input:
// from AddField(), DeleteField(), ModifyField(), or MoveField()
// hglbCorrectTableInfo - handle to TableInfo struct
// FieldOp - crCOPY, crDROP, crADD, or crMODIFY
// iNewFldNum - new position of field
// pOldName - old field name
// pNewName - new field name
// pFldType - field type
// iUnits1 - field size
// pszRetBuffer - return to client
//
// Return: (pszRetBuffer) null or error string.
//
// Description:
// This function sets up the field structure for the new table.
//=====================================================================
void FAR WINAPI
SetFieldDescriptions (HGLOBAL hglbCorrectTableInfo, CROpType FieldOp,
UINT16 iNewFldNum, pCHAR pOldName, pCHAR pNewName,
pCHAR pFldType, UINT16 iUnits1, pCHAR pszRetBuffer)
{
UINT16 i;
UINT16 iField = 0;
UINT16 iDropped = 0;
UINT16 iCompleted= 0;
UINT16 iFieldFound = 0;
UINT16 iOrigFld;
UINT16 FieldType = 0;
struct TBLINFO *TableInfo;
memset(pszRetBuffer, 0, (DBIMAXMSGLEN +1) * sizeof(char));
CHKERR_NODISPLAY(hglbCorrectTableInfo == NULL);
TableInfo = GlobalLock (hglbCorrectTableInfo);
if (TableInfo == NULL)
{
hglbCorrectTableInfo = NULL;
GetString(1, pszRetBuffer); //"Out of Memory."
CLEANUP_NODISPLAY;
}
CHKERR_NODISPLAY((TableInfo == NULL) || (TableInfo->retVal == 1))
TableInfo->retVal = 1;
// allow any case for user input of field type
AnsiUpper(pFldType);
// set field types for dBASE
if (!strcmp(TableInfo->crTblDesc.szTblType, szDBASE))
{
switch (pFldType[0])
{
case 'C':
FieldType = fldDBCHAR;
break;
case 'F':
FieldType = fldDBFLOAT;
break;
case 'N':
FieldType = fldDBNUM;
break;
case 'D':
FieldType = fldDBDATE;
break;
case 'L':
FieldType = fldDBBOOL;
break;
case 'M':
FieldType = fldDBMEMO;
break;
case 'O':
FieldType = fldDBOLEBLOB;
break;
case 'B':
FieldType = fldDBBINARY;
break;
}
}
// set field types for Paradox
if (!strcmp(TableInfo->crTblDesc.szTblType, szPARADOX))
{
switch (pFldType[0])
{
case 'A':
FieldType = fldPDXCHAR;
break;
case 'N':
FieldType = fldPDXNUM;
break;
case '$':
FieldType = fldPDXMONEY;
break;
case 'D':
FieldType = fldPDXDATE;
break;
case 'S':
FieldType = fldPDXSHORT;
break;
case 'M':
FieldType = fldPDXMEMO;
break;
case 'B':
FieldType = fldPDXBINARYBLOB;
break;
case 'F':
FieldType = fldPDXFMTMEMO;
break;
case 'O':
FieldType = fldPDXOLEBLOB;
break;
case 'G':
FieldType = fldPDXGRAPHIC;
break;
case 'I':
FieldType = fldPDXLONG;
break;
case 'T':
FieldType = fldPDXTIME;
break;
case '@':
FieldType = fldPDXDATETIME;
break;
case 'L':
FieldType = fldPDXBOOL;
break;
case '+':
FieldType = fldPDXAUTOINC;
break;
case 'Y':
FieldType = fldPDXBYTES;
break;
case '#':
FieldType = fldPDXBCD;
break;
}
}
// get index descriptor if a primary key exists
if (TableInfo->bHasIndex)
{
DbiGetIndexDescs(TableInfo->hCur, TableInfo->pIdxDesc);
}
// setup in order, set field numbers to old positions.
for (i = 0; i < TableInfo->uNumFields; i++)
{
// operation for moving fields
if (FieldOp == crCOPY)
{
// was it copied already?
if (!strcmpi(pOldName, TableInfo->pFldDesc[iNewFldNum - 1].szName))
{
GetString(9, pszRetBuffer); //"The field was already moved."
CLEANUP_NODISPLAY;
}
// the existing field name is found
if (!strcmpi(TableInfo->pFldDesc[i].szName,
pOldName))
{
// the table has a primary key
if (TableInfo->bHasIndex)
{
// don't allow a copy to an existing key
if ((((i + 1) <= TableInfo->pIdxDesc[0].iFldsInKey) ||
(iNewFldNum <= TableInfo->pIdxDesc[0].iFldsInKey) &&
!strcmp(TableInfo->crTblDesc.szTblType, szPARADOX)) &&
TableInfo->pIdxDesc[0].bPrimary)
{
GetString(2, pszRetBuffer); //"Only modifications can
// be made to primary keys."
CLEANUP_NODISPLAY;
}
}
// is the new field number within range of the existing field
// descriptors?
if (iNewFldNum < 1 || iNewFldNum > TableInfo->uNumFields)
{
GetString(5, pszRetBuffer); //"Invalid field descriptor."
CLEANUP_NODISPLAY;
}
// copy a field descriptor
TableInfo->pFldDescriptor[iNewFldNum - 1] =
TableInfo->pFldDesc[i];
// set field number to the old position (not to iFldNum)
TableInfo->pFldDescriptor[iNewFldNum - 1].iFldNum = i + 1;
// set field operation
TableInfo->ecrFldOp[iNewFldNum - 1] = crCOPY;
// done with this operation
iFieldFound = 1;
}
// couldn't find field name
if (i + 1 == TableInfo->uNumFields && iFieldFound == 0)
{
GetString(5, pszRetBuffer); //"Invalid field descriptor."
CLEANUP_NODISPLAY;
}
}
// operation for adding fields
if (FieldOp == crADD)
{
// is the new field number out of range?
if (iNewFldNum - 1 > TableInfo->uNumFields)
{
GetString(10, pszRetBuffer); //"The new field number is out of
// range."
CLEANUP_NODISPLAY;
}
// was the field added already?
for (iFieldFound = 0; iFieldFound < TableInfo->uNumFields;
iFieldFound++)
{
if (!strcmpi(pOldName, TableInfo->pFldDesc[iFieldFound].szName))
{
GetString(4, pszRetBuffer); //"The field was already added."
CLEANUP_NODISPLAY;
}
}
if (TableInfo->bHasIndex)
{
if (iNewFldNum <= TableInfo->pIdxDesc[0].iFldsInKey &&
!strcmp(TableInfo->crTblDesc.szTblType, szPARADOX) &&
TableInfo->pIdxDesc[0].bPrimary)
{
GetString(2, pszRetBuffer); //"Only modifications can be made
// to primary keys."
CLEANUP_NODISPLAY;
}
}
// set field numbers to zero for added fields
TableInfo->pFldDescriptor[iNewFldNum - 1].iFldNum = 0;
strcpy(TableInfo->pFldDescriptor[iNewFldNum - 1]
.szName, pOldName);
TableInfo->pFldDescriptor[iNewFldNum - 1].iFldType = FieldType;
TableInfo->pFldDescriptor[iNewFldNum - 1].iSubType = 0;
TableInfo->pFldDescriptor[iNewFldNum - 1].iUnits1 = iUnits1;
TableInfo->pFldDescriptor[iNewFldNum - 1].iUnits2 = 0;
TableInfo->pFldDescriptor[iNewFldNum - 1].iOffset = 0;
TableInfo->pFldDescriptor[iNewFldNum - 1].iLen = 0;
TableInfo->pFldDescriptor[iNewFldNum - 1].iNullOffset = 0;
TableInfo->pFldDescriptor[iNewFldNum - 1].efldvVchk =
fldvNOCHECKS;
TableInfo->pFldDescriptor[iNewFldNum - 1].efldrRights =
fldrREADWRITE;
TableInfo->ecrFldOp[iNewFldNum - 1] = crADD;
}
// operation for modifying field names, types, or sizes
if (FieldOp == crMODIFY)
{
// quit loop if this operation is finished
if (iCompleted == 1)
{
break;
}
for (iFieldFound = 0; iFieldFound < TableInfo->uNumFields;
iFieldFound++)
{
if (!strcmpi(pOldName, TableInfo->pFldDesc[iFieldFound].szName))
{
TableInfo->pFldDescriptor[iFieldFound] =
TableInfo->pFldDesc[iFieldFound];
TableInfo->pFldDescriptor[iFieldFound].iFldNum =
iFieldFound + 1;
strcpy(TableInfo->pFldDescriptor[iFieldFound].szName,
pNewName);
TableInfo->pFldDescriptor[iFieldFound].iFldType = FieldType;
TableInfo->pFldDescriptor[iFieldFound].iSubType = 0;
TableInfo->pFldDescriptor[iFieldFound].iUnits1 = iUnits1;
TableInfo->pFldDescriptor[iFieldFound].iUnits2 = 0;
TableInfo->pFldDescriptor[iFieldFound].iOffset = 0;
TableInfo->pFldDescriptor[iFieldFound].iLen = 0;
TableInfo->pFldDescriptor[iFieldFound].iNullOffset = 0;
TableInfo->pFldDescriptor[iFieldFound].efldvVchk =
fldvNOCHECKS;
TableInfo->pFldDescriptor[iFieldFound].efldrRights =
fldrREADWRITE;
TableInfo->ecrFldOp[iFieldFound] = crMODIFY;
iCompleted = 1;
break;
}
if (iFieldFound + 1 == TableInfo->uNumFields)
{
GetString(7, pszRetBuffer); //"The field name can't be found."
CLEANUP_NODISPLAY;
}
}
}
// operation for deleting fields - deletes by skipping a field
// descriptor copy
// does nothing except check if field was already dropped
if (FieldOp == crDROP)
{
// was it dropped already?
for (iFieldFound = 0; iFieldFound < TableInfo->uNumFields;
iFieldFound++)
{
if (!strcmpi(TableInfo->pFldDesc[iFieldFound].szName, pOldName))
{
if (TableInfo->bHasIndex)
{
if ((iFieldFound + 1) <= TableInfo->pIdxDesc[0].
iFldsInKey && !strcmp(TableInfo->crTblDesc.
szTblType, szPARADOX)&& TableInfo->pIdxDesc[0].
bPrimary)
{
GetString(2, pszRetBuffer); //"Only modifications can
// be made to primary keys."
CLEANUP_NODISPLAY;
}
}
iDropped = 1;
}
if ((iFieldFound + 1 == TableInfo->uNumFields) && iDropped == 0)
{
GetString(8, pszRetBuffer); //"The field was already deleted."
CLEANUP_NODISPLAY;
}
}
}
}
// fill in blank field descriptors
for (i = 0; i < TableInfo->uNewNumFields; i++)
{
// check for blank field (preassigned -1u - max of possible ranges)
if (TableInfo->pFldDescriptor[i].iFldNum == -1u)
{
for (iOrigFld = iField; iOrigFld < TableInfo->uNumFields;
iOrigFld++)
{
iField++;
if (strcmpi(TableInfo->pFldDesc[iOrigFld].szName, pOldName))
{
TableInfo->pFldDescriptor[i] =
TableInfo->pFldDesc[iOrigFld];
// set field number to the old position (not the iFldNum)
TableInfo->pFldDescriptor[i].iFldNum = iOrigFld + 1;
TableInfo->ecrFldOp[i] = crCOPY;
break;
}
}
}
}
TableInfo->retVal = 0;
CleanUp:
if (hglbCorrectTableInfo)
{
GlobalUnlock(hglbCorrectTableInfo);
hglbCorrectTableInfo = NULL;
}
}
//=====================================================================
// Function:
// EndRestructure(HGLOBAL hglbCorrectTableInfo, pCHAR pPack,
// pCHAR pszRetBuffer)
//
// Input:
// from AddField(), DeleteField(), ModifyField(), or MoveField()
// hglbCorrectTableInfo - handle to TableInfo struct
// pPack - "PACK" or "NOPACK"
// pCHAR pszRetBuffer - return to client
//
// Return: null or error string.
//
// Description:
// This function gets creates a new table descriptor image
// and calls IDAPI to do the actual restructure.
//=====================================================================
void FAR WINAPI
EndRestructure (HGLOBAL hglbCorrectTableInfo, pCHAR pPack,
pCHAR pszRetBuffer)
{
DBIResult rslt;
DBIPATH szKeyViol;
struct TBLINFO *TableInfo;
GetString(11, szKeyViol); // Key violation table name
memset(pszRetBuffer, 0, (DBIMAXMSGLEN +1) * sizeof(char));
CHKERR_NODISPLAY(hglbCorrectTableInfo == NULL);
TableInfo = GlobalLock (hglbCorrectTableInfo);
if (TableInfo == NULL)
{
hglbCorrectTableInfo = NULL;
GetString(1, pszRetBuffer); //"Out of Memory."
CLEANUP_NODISPLAY;
}
CHKERR_NODISPLAY((TableInfo == NULL) || (TableInfo->retVal == 1))
TableInfo->retVal = 1;
// allow any case for user input of pack operation
AnsiUpper(pPack);
// set default to no table pack
TableInfo->crTblDesc.bPack = FALSE;
if (!strcmpi(pPack, "PACK"))
{
TableInfo->crTblDesc.bPack = TRUE;
}
if (!strcmpi(pPack, "NOPACK"))
{
TableInfo->crTblDesc.bPack = FALSE;
}
// copy information to new table descriptor
TableInfo->crTblDesc.iFldCount = TableInfo->uNewNumFields;
TableInfo->crTblDesc.pecrFldOp = TableInfo->ecrFldOp;
TableInfo->crTblDesc.pfldDesc = TableInfo->pFldDescriptor;
// allows DbiDoRestructure to get an exclusive lock on the table
CHKERR_CLEANUP(DbiCloseCursor(&TableInfo->hCur));
TableInfo->hCur = NULL;
// call to BDE to restructure the table
CHKERR_CLEANUP(DbiDoRestructure(TableInfo->hDb, 1, &TableInfo->crTblDesc,
NULL, szKeyViol, NULL, FALSE));
TableInfo->retVal = 0;
CleanUp:
if (hglbCorrectTableInfo)
{
GlobalUnlock(hglbCorrectTableInfo);
hglbCorrectTableInfo = NULL;
}
if (!strcmp(pszRetBuffer, "\0"))
{
GetString(13, pszRetBuffer); // "Restructure successful."
}
}
//=====================================================================
// Function:
// DBIError(HGLOBAL hglbCorrectTableInfo, DBIResult retVal,
// pCHAR pszRetBuffer)
//
// Input:
// from macro.h:
// hglbCorrectTableInfo - handle to TableInfo struct
// retVal - BDE return
// pszRetBuffer - Buffer to contain the error string
//
// Return: a DBIResult value.
//
// Description:
// This function gets information of where an error occurred.
//=====================================================================
DBIResult
DBIError (HGLOBAL hglbCorrectTableInfo, DBIResult retVal, pCHAR pszRetBuffer)
{
struct TBLINFO *TableInfo;
if (retVal == DBIERR_NONE)
{
return retVal;
}
CHKERR_NODISPLAY(hglbCorrectTableInfo == NULL)
TableInfo = GlobalLock (hglbCorrectTableInfo);
if (TableInfo == NULL)
{
hglbCorrectTableInfo = NULL;
CLEANUP_NODISPLAY;
}
if (retVal == DBIERR_CANTFINDODAPI)
{
GetString(3, pszRetBuffer); //"Cannot find IDAPI files: Check path."
CLEANUP_DISPLAYERR(pszRetBuffer);
}
else
{
DbiGetErrorString(retVal, pszRetBuffer);
}
CleanUp:
if (hglbCorrectTableInfo)
{
GlobalUnlock(hglbCorrectTableInfo);
hglbCorrectTableInfo = NULL;
}
return retVal;
}
//=====================================================================
// Function:
// cleanUpMemory(HGLOBAL hglbCorrectTableInfo);
//
// Description:
// Free all allocations, cursors, and tables if needed.
//=====================================================================
void
cleanUpMemory (HGLOBAL hglbCorrectTableInfo)
{
UINT16 i;
struct TBLINFO *TableInfo;
CHKERR_NODISPLAY(hglbCorrectTableInfo == NULL);
TableInfo = GlobalLock (hglbCorrectTableInfo);
if (TableInfo == NULL)
{
hglbCorrectTableInfo = NULL;
CLEANUP_NODISPLAY;
}
if (hglbCorrectTableInfo)
{
if (TableInfo->hCur)
{
DbiCloseCursor(&TableInfo->hCur);
}
if (TableInfo->hDb)
{
DbiCloseDatabase(&TableInfo->hDb);
}
if (TableInfo->ecrFldOp)
{
free(TableInfo->ecrFldOp);
}
if (TableInfo->pIdxDesc)
{
free(TableInfo->pIdxDesc);
}
if (TableInfo->pFldDescriptor)
{
free(TableInfo->pFldDescriptor);
}
if (TableInfo->pFldDesc)
{
free(TableInfo->pFldDesc);
}
//decrement lock count to 0.
for (i = GlobalFlags(hglbCorrectTableInfo); i > 0; i--)
{
GlobalUnlock(hglbCorrectTableInfo);
}
GlobalFree(hglbCorrectTableInfo);
CleanUp:
}
}
//=====================================================================
// Function:
// GetString(WORD iStringID, pCHAR pszRetBuffer)
//
// Input:
// iStringID - Identifier for the string
// pszBuffer - Buffer to contain the error string.
// (Allocated by the calling function)
//
// Description:
// Load a string from STRUCTER.DLL.
//=====================================================================
void
GetString (WORD iStringID, pCHAR pszRetBuffer)
{
if (pszRetBuffer)
{
LoadString(GetModuleHandle(szCURRENTMODULE), iStringID, pszRetBuffer,
DBIMAXMSGLEN - 1);
}
}
#pragma argsused
BOOL WINAPI
LibMain (HINSTANCE hInstance, WORD wDataSeg,
WORD cbHeapSize, LPSTR lpCmdLine) {
if (cbHeapSize != 0)
{
UnlockData(0);
}
return TRUE;
}
int WINAPI
WEP (int nSystemExit) {
switch (nSystemExit) {
case WEP_SYSTEM_EXIT:
break;
case WEP_FREE_DLL:
break;
}
return 1;
}