// 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; }