/********************************************************************************************* * Copyright 2002 - Volian Enterprises, Inc. All rights reserved. * Volian Enterprises - Proprietary Information - DO NOT COPY OR DISTRIBUTE * ------------------------------------------------------------------------------ * $Workfile: ConvertParadoxROs.cs $ $Revision: 16 $ * $Author: Jsj $ $Date: 8/02/04 11:02a $ * * $History: ConvertParadoxROs.cs $ * * ***************** Version 16 ***************** * User: Jsj Date: 8/02/04 Time: 11:02a * Updated in $/EXE/RefObj/ParadoxConversion * Bug fix B2004-028 added check of local defined fields when checking if * the field we are converting is a combo field. * * ***************** Version 15 ***************** * User: Kathy Date: 10/15/03 Time: 10:29a * Updated in $/EXE/RefObj/ParadoxConversion * Found/fix during debugging of B2003-060 (will go through QA process * with that bug fix) * * ***************** Version 14 ***************** * User: Kathy Date: 3/13/03 Time: 1:15p * Updated in $/EXE/RefObj/ParadoxConversion * master different than local field name, use local * * ***************** Version 13 ***************** * User: Jsj Date: 1/22/03 Time: 12:49p * Updated in $/EXE/RefObj/ParadoxConversion * remove old paradox user and lock files before trying the convert. Was * not able to open the paradox master file. * * ***************** Version 12 ***************** * User: Jsj Date: 1/06/03 Time: 12:56p * Updated in $/EXE/RefObj/ParadoxConversion * uses a special ROMASTER.MDB to convert data, will now remove temporary * TXT files if the DEBUG switch is not passed in. * * ***************** Version 11 ***************** * User: Jsj Date: 12/19/02 Time: 9:17a * Updated in $/EXE/RefObj/ParadoxConversion * now modifies the VEPROMS INI file if it has a [Graphics] section * * ***************** Version 10 ***************** * User: Jsj Date: 12/18/02 Time: 9:01a * Updated in $/EXE/RefObj/ParadoxConversion * fix for IP2 and FNP data * * ***************** Version 9 ***************** * User: Jsj Date: 12/06/02 Time: 3:20p * Updated in $/EXE/RefObj/ParadoxConversion * added Debug and new function to replace invalid characters in the field * names * * ***************** Version 8 ***************** * User: Jsj Date: 12/04/02 Time: 11:01a * Updated in $/EXE/RefObj/ParadoxConversion * added logic to handle Parameter Display Data data * * ***************** Version 7 ***************** * User: Jsj Date: 11/27/02 Time: 1:39p * Updated in $/EXE/RefObj/ParadoxConversion * Handle - and / in field names * * ***************** Version 6 ***************** * User: Jsj Date: 10/15/02 Time: 11:39a * Updated in $/EXE/RefObj/ParadoxConversion * added "a" to combo field names in non-master tables. * * ***************** Version 5 ***************** * User: Jsj Date: 10/04/02 Time: 2:02p * Updated in $/EXE/RefObj/ParadoxConversion * added better user interface * * ***************** Version 4 ***************** * User: Jsj Date: 9/27/02 Time: 2:57p * Updated in $/EXE/RefObj/ParadoxConversion * Fixed Graphic image information storage * * ***************** Version 3 ***************** * User: Jsj Date: 9/26/02 Time: 4:17p * Updated in $/EXE/RefObj/ParadoxConversion * There was a leading space in all of the field values - is now fixed. * * ***************** Version 2 ***************** * User: Jsj Date: 9/25/02 Time: 10:19a * Updated in $/EXE/RefObj/ParadoxConversion * added header *********************************************************************************************/ using System; using System.Collections; using System.IO; using System.Xml; using System.Windows.Forms; // Application.StartupPath using System.Diagnostics; using DBEncapsulation; using ROFields; namespace ParadoxConversion { /// /// This class contains the functions needed to convert the old Paradox RO Database /// to a newer type database. /// public class ConvertParadoxROs { System.Windows.Forms.Label StatusWin; bool ProcessingMasterTable = false; bool DoDebugFile = false; BinaryReader BReader; // read text file as binary (for chars like hard spaces) BinaryWriter BWrite; // for a debug file String AppPath; String ROConvertPath; String ROPath; String LineOfText; String ROTableName, ROTblElmt; String RecID, RecType, ParentRecID, AccPageID, DateTime, Info, GroupTitle; int intRecType = 0; int CurrentFieldType = 0; int NumCRLFs = 0; XmlTextWriter xmlTxtWriter = null; RODBRecordInterface MyDbRec; ROField NewDbField; struct FieldInfo { public String fldRecID; // Field Record ID public String fldName; // Field name public String fldType; }; ArrayList MasterFieldInfoList = new ArrayList(); ArrayList LocalFieldInfoList = new ArrayList(); struct GroupTitles { public String GrpRecID; public String GrpTitle; } ArrayList GroupTitlesList = new ArrayList(); public void OpenTextFile(String FName) { BReader = new BinaryReader(File.Open(FName,System.IO.FileMode.Open,System.IO.FileAccess.ReadWrite)); } public void CloseTextFile() { BReader.Close(); } public String TxF_ReadLine() { bool success = true; String TxFstr = ""; byte rdByte = 0; if (BReader != null) { NumCRLFs = 0; while (success) { try { rdByte = BReader.ReadByte(); } catch (Exception e) { success = false; TxFstr = null; } if (rdByte == 0x0D) // carrage return (end of line) { NumCRLFs++; rdByte = BReader.ReadByte(); // read the new line character if (rdByte == 0x0D) // sometimes there's an extra carrage return { rdByte = BReader.ReadByte(); NumCRLFs++; } success = false; // to stop the loop } if (success) { TxFstr += Convert.ToString(Convert.ToChar(rdByte)); } } } return TxFstr; } /*** for debugging..... */ public void DEBUG_OpenFile(String FName) { if (DoDebugFile) BWrite = new BinaryWriter(File.Open(FName,System.IO.FileMode.Create,System.IO.FileAccess.ReadWrite)); } public void DEBUG_CloseFile() { if (DoDebugFile) BWrite.Close(); } public void DEBUG_Write(string str) { if (DoDebugFile) { DEBUG_WriteString(str); DEBUG_WriteString("\n"); } } public void DEBUG_WriteString(string str) { if (DoDebugFile) { int i; for(i =0; i < str.Length; i++) { byte WrByte; WrByte = (byte)str[i]; BWrite.Write(WrByte); } } } public void DEBUG_CheckFieldName(string fldname) { if (DoDebugFile) { char[] tmpstr = fldname.ToCharArray(); int len = fldname.Length; int cnt = 0; bool FirstOne = true; string OKpunch = " -._"; // we're also going to ignore spaces string outstr = ""; int decval; while (cnt < len) { char tmpchr = tmpstr[cnt]; if(!char.IsLetterOrDigit(tmpchr)) { if (OKpunch.IndexOf(tmpchr) == -1) // not found { if (FirstOne) { FirstOne = false; DEBUG_Write(fldname); } decval = tmpchr; outstr = " " + tmpchr.ToString() +" [" + decval.ToString() + "]";; DEBUG_Write(outstr); } } cnt++; } if (!FirstOne) DEBUG_Write("----------------\n"); } } /** End - For Debugging **/ public ConvertParadoxROs(System.Windows.Forms.Label statWin, bool DoingDebugFile) { // Assume we are currently in the RO directory to be converted // Was it already converted? (check for existance of a backup // created during the conversion process) // Yes - return // else select the new database type StatusWin = statWin; DoDebugFile = DoingDebugFile; ClearFieldStrings(); } /* * Initialize the fields to empty strings. */ public void ClearFieldStrings() { RecID = ""; RecType = ""; ParentRecID = ""; AccPageID = ""; DateTime = ""; Info = ""; } public void CreateNewRoDatabase() { // Prompt user to select the new databaes type (ex Access, SQL Server, etc) // For now, we will be creating just an Access database. /* * Copy our empty ROMaster.mdb file into the CONVERT directory (is the current * directory at this point) This RomasterCvrt.mdb is located in the VE-PROMS.NET\BIN16 * directory and is different than the ROMaster.mdb in VE-PROM.NET\BIN. The one in the BIN16 * directory does not have any tables, while the one in the BIN directory has an * ROMASTER table with the default records needed to create RO tables. */ String toPath = ROConvertPath + "\\ROMaster.mdb"; String fromPath = AppPath + "16\\RomasterCvrt.mdb"; File.Copy(fromPath,toPath,true); // overwrite the file if already there // Create an empty database. MyDbRec = new RODBRecordInterface(1,ROConvertPath); // Open the database connection MyDbRec.RODB_OpenConnection(); } public void CloseNewRoDatabase() { MyDbRec.RODB_CloseConnection(); } /* * Create a ORIG_RO directory and move everything(except for the CONVERT directory) * in RO into it. Then move everying in CONVERT into RO. */ public void MoveOldROData() { Directory.SetCurrentDirectory("..\\"); Directory.Move("RO","ORIG_RO"); Directory.Move("CONVERT","RO"); } /* This function will create TXT files from the Paradox database (PX2TXT.EXE) then parse * them and place the RO information in the new database. * * Note that the Microsoft Paradox driver could not read our Paradox BLOB fields. * We had to write a program in the old Borland 16-bit environment that would basically * dump the RO information into a file that the Microsoft drivers could read. We decided * to keep things simple and just dump the RO information into text files. * * Each line in the text file represents a database record. Each "field" is separated by * a space. Each "record" has the following fields: * * RECORD ID * RECORD TYPE * PARENT ID * ACCPAGE ID * DATETIME * The Paradox BLOB data */ public void TestMessage() { StatusWin.Text = "This is a TEST!"; StatusWin.Refresh(); } private void StatusMessage(String Mess1) { StatusWin.Text = Mess1; StatusWin.Refresh(); } private void StatusMessage(String Mess1, String Mess2) { StatusWin.Text = Mess1 + Mess2; StatusWin.Refresh(); } private void StatusMessage(String Mess1, String Mess2, String Mess3) { StatusWin.Text = Mess1 + Mess2 + Mess3; StatusWin.Refresh(); } public void ConvertParadoxRODb(string PassedInROPath) { // Set the current working directory to my sample RO directory // Directory.SetCurrentDirectory("G:\\PROMSDAT\\VEWPB\\RO"); // ROPath = "G:\\PROMSDAT\\VEBRAID\\RO"; // Directory.SetCurrentDirectory(ROPath); ROPath = PassedInROPath; ROConvertPath = ROPath.Substring(0,ROPath.LastIndexOf("\\")); ROConvertPath += "\\CONVERT"; // Create text files from the Paradox RO Database StatusMessage("Paradox to Text Files"); // Get the path of where this executable resides AppPath = Application.StartupPath; // append "16\\px2txt.exe" to the path of the VE-PROMS.NET\BIN path // to get the resulting path: VE-PROMS.NET\BIN16\px2txt.exe String ToTxtAppPath = AppPath + "16\\px2txt.exe"; /* * Before we run the PX2TXT.EXE program, delete any Paradox lock files that might * be hanging around. */ File.Delete("Pdoxusrs.net"); File.Delete("Pdoxusrs.lck"); File.Delete("paradox.lck"); // create a process & wait until it exits. Process myProcess = new Process(); myProcess.StartInfo.FileName = ToTxtAppPath; myProcess.Start(); myProcess.WaitForExit(); /* * Now change directory to the CONVERT sub-directory that was created * from PX2TXT.EXE * * This directory should have the TXT files containing the RO data and * the graphic files (Intergrated Graphics) used in the current RO database. * Note that some of the graphic files might be converted to a different * graphics format than what is used in the old RO Editor. */ Directory.SetCurrentDirectory(ROConvertPath); /* The PX2TXT.EXE program also creates a file called PXCONLST.TXT which * contains a list of the TXT files that it created. * * Read the PXCONLST.TXT file. This contains the list of TXT files * that were generated as the first step to the conversion. * Place these in a array list for processing. * Assume that we are in the RO directory that is being converted */ string FileName = "Pxconlst.txt"; int numDbs = 0; ArrayList DbList = new ArrayList(); ArrayList DbTitleList = new ArrayList(); if (!File.Exists(FileName)) { // Conversion from Paradox to a text file failed. // **** provide error message **** StatusMessage("Conversion from Paradox to a text file failed."); return; } OpenTextFile(FileName); String FileNameTitle; // the title of the ROxxxxxx file String TextFileName; while ((FileNameTitle = TxF_ReadLine())!=null) { DbTitleList.Add(FileNameTitle); TextFileName = TxF_ReadLine(); DbList.Add(TextFileName); numDbs++; } CloseTextFile(); // delete the Pxconlst.txt file if we are NOT debugging if (!DoDebugFile) File.Delete(FileName); // Create a new (empty) database CreateNewRoDatabase(); // DEBUG - write the field names that have problem characters DEBUG_OpenFile("DebugFieldNames"); // For each file listed in PXCONLST.TXT // Open the file // read each line // (each line represents a record from the old Paradox database) // translate each line into a database record System.Collections.IEnumerator myEnumerator = DbList.GetEnumerator(); System.Collections.IEnumerator myTitleEnumerator = DbTitleList.GetEnumerator(); while(myEnumerator.MoveNext()) { myTitleEnumerator.MoveNext(); // Clear the GroupTitles Array GroupTitlesList.Clear(); // Clear the LocalFieldInfoList Array LocalFieldInfoList.Clear(); TextFileName = myEnumerator.Current.ToString(); // Get the RO Table Name (ex. ROMASTER, RO000001) ROTableName = myEnumerator.Current.ToString(); int slen = ROTableName.Length; ROTableName = ROTableName.Remove(slen-4,4); // Create the database table MyDbRec.RODB_AddNewTable(ROTableName); if (StringsAreEqualU(ROTableName,"ROMASTER")) ProcessingMasterTable = true; else ProcessingMasterTable = false; String tmpMess; tmpMess = "Processing " + myTitleEnumerator.Current.ToString(); StatusMessage(tmpMess); OpenTextFile(TextFileName); // Open the text file DEBUG_Write("==================="); DEBUG_Write(tmpMess); DEBUG_Write(TextFileName); int cnt = 0; while ((LineOfText = TxF_ReadLine()) != null) { // Process the text line (each line is a record) ClearFieldStrings(); cnt++; StatusMessage(tmpMess,"\nRecord: ",Convert.ToString(cnt)); ProcessTextLine(); } StatusMessage(" "); CloseTextFile(); // delete the ROxxxx.txt file if we are NOT debugging if (!DoDebugFile) File.Delete(TextFileName); // Close database table } // DEBUG - Close Debug file DEBUG_CloseFile(); CloseNewRoDatabase(); MoveOldROData(); } /* This function makes a copy of the passed in string, then replaces * any blank character with an underbar ('_') character. * The copy is returned. */ String StrBlanksToUnderbars(String TheString) { String RtnStr = TheString; RtnStr.Replace(" ", "_"); return RtnStr; } /* * This function compares a String with a (char *) array and returns * true if they are equal, else it returns false */ bool StringsAreEqual(String thisStr, String thatStr) { bool StringsAreEqual = false; StringsAreEqual = (thisStr.CompareTo(thatStr) == 0); return StringsAreEqual; } /* * This function will first uppercase the strings then compare them * and returns true if they are equal, else it returns false */ bool StringsAreEqualU(String thisStr, String thatStr) { String ThisOne = thisStr; String ThatOne = thatStr; ThisOne.ToUpper(); ThatOne.ToUpper(); bool StringsAreEqual = false; StringsAreEqual = (ThisOne.CompareTo(ThatOne) == 0); return StringsAreEqual; } /* * This function reads up to the next space character (or null) */ String GetFieldTxt() { String RtnStr = "0"; char[] space = new char[1]{' '}; int txtIdxEnd = LineOfText.IndexOfAny(space); // blank is the end of a the field if (txtIdxEnd > 0) { RtnStr = LineOfText.Substring(0,txtIdxEnd); LineOfText = LineOfText.Remove(0,txtIdxEnd+1); // remove this "field" from the string } else if (LineOfText.Length > 0) // last field in the string { RtnStr = LineOfText; LineOfText = ""; } return RtnStr; } /* * This function converts the given string to an interger */ int GetFieldInt(String TmpStr) { int RtnInt; RtnInt = Convert.ToInt32(TmpStr); return RtnInt; } /* This function will first read the length of the string (number of characters to get) * Then get the string of that length. */ String GetStringByLength() { String RtnStr = ""; int len = (int)GetFieldInt(GetFieldTxt()); int LineTextLen = LineOfText.Length; while (len > LineTextLen) { RtnStr += LineOfText + "\r\n"; // need both a '\r' and a '\n' /* NumCRLFs accounts for the number of "\r\n"s that was originally counted when the text * file was created. */ len -= (LineTextLen + NumCRLFs); LineOfText = TxF_ReadLine(); if (len == 0) // end of string had \r\n still may need to remove a blank at the beginning of the string buffer { if (LineOfText.StartsWith(" ")) LineOfText = LineOfText.Remove(0,1); } LineTextLen = LineOfText.Length; } if (len > 0) { RtnStr += LineOfText.Substring(0,len); LineOfText = LineOfText.Remove(0,len+1); // add one to remove following space } return RtnStr; } /* * This function builds the field definition string */ String GetFieldDefinition() { String tmpStr; String RtnStr = ""; String FieldTypeStr = ""; int FieldType = 0; String FieldLength = ""; String FieldName = ""; FieldName = GetStringByLength(); // get the field name FieldName = FixFieldName(FieldName); NewDbField.SetFieldname(FieldName); // get the field type FieldTypeStr = GetFieldTxt(); FieldType = GetFieldInt(FieldTypeStr); // Save the name and rec id and type in an array FieldInfo TheFieldInfo = new FieldInfo(); TheFieldInfo.fldName = FieldName; TheFieldInfo.fldRecID = RecID; TheFieldInfo.fldType = FieldTypeStr; if (ProcessingMasterTable) { MasterFieldInfoList.Add(TheFieldInfo); } else // is a local definition { LocalFieldInfoList.Add(TheFieldInfo); } NewDbField.SetFieldType((uint)FieldType); switch (FieldType) { case 1: // Fixed Length Text case 2: // Variable Length Text case 8: // X/Y Plot case 0x10: // Table // Get the field length FieldLength = GetFieldTxt(); // append/save the Field Name and Field Length to RtnStr RtnStr += NewDbField.MakeSchemaString(FieldName,FieldLength,""); break; case 4: // Formatted Text String Pattern; // Get the field length FieldLength = GetFieldTxt(); // Get the pattern Pattern = GetStringByLength(); // append/save the Field Name, Length, and Pattern to RtnStr RtnStr += NewDbField.MakeSchemaString(FieldName,FieldLength,Pattern); break; case 0x20: // Image (Intergrated Graphics) // append/save only the type to RtnStr RtnStr = NewDbField.MakeImageSchemaString(FieldName); break; case 0x40: // Multi Field (used by Parameter Display Data) RtnStr += FieldName + " " + FieldTypeStr; tmpStr = GetFieldTxt(); // Create a list of RecIDs separated by a blank while (!StringsAreEqual(tmpStr,"0")) // while not "0" { // append/save the RefRecID to Rtn Str RtnStr += " " + tmpStr; tmpStr = GetFieldTxt(); } if (intRecType == 2) { RecType = "4"; intRecType = 4; } break; case 0x100: // Generic Field (reference to a field definition) tmpStr = GetFieldTxt(); string tmp1 = GetSavedMasterFieldNameAndType(tmpStr).Substring(0,4); if (tmp1.Equals("128 ")) RtnStr = tmpStr + " " + tmp1 + FieldName + "a"; else RtnStr = tmpStr + " " + tmp1 + FieldName; // RtnStr = tmpStr + " " + (GetSavedMasterFieldNameAndType(tmpStr)); break; case 0x80: // Combo Field String SingleLineWidth = ""; String MultiLineWidth = ""; String TableWidth = ""; String XYPlotWidth = ""; bool Single = false, Multi = false, Tbl = false, XYPlt = false; int fldtyp; do { tmpStr = GetFieldTxt(); fldtyp = GetFieldInt(tmpStr); switch (fldtyp) { case 1: // single line text SingleLineWidth = GetFieldTxt(); Single = true; break; case 2: // multi line text MultiLineWidth = GetFieldTxt(); Multi = true; break; case 8: // X/Y Plot XYPlotWidth = GetFieldTxt(); XYPlt = true; break; case 16: // Table TableWidth = GetFieldTxt(); Tbl = true; break; default: break; } // end switch } while (!StringsAreEqual(tmpStr,"0")); // append/save the Field Type to RtnStr RtnStr = NewDbField.MakeComboSchemaString(FieldName,Single,SingleLineWidth,Multi,MultiLineWidth,Tbl,TableWidth,XYPlt,XYPlotWidth); break; default: // nothing to do break; } // end switch return RtnStr; } String GetValueDefinition() { String RtnStr = ""; String tmpStr = ""; String tmpStr2 = ""; String tmpStr3 = ""; String RecIDRef = ""; String MenuText = ""; String ValueDefTypeStr = ""; int ValueDefType = 0; int NumItems; do { ValueDefTypeStr = GetFieldTxt(); ValueDefType = GetFieldInt(ValueDefTypeStr); switch (ValueDefType) { case 1: // Record ID referencing a field record RecIDRef = GetFieldTxt(); tmpStr = GetSavedLocalFieldName(RecIDRef); // append/save ValueDefType and RecIDRef to RtnStr RtnStr += "<" + tmpStr + ">"; break; case 2: // Text value tmpStr = GetStringByLength(); tmpStr = FixString(tmpStr); // append/save ValueDefType and TxtStr to Rtn Str RtnStr += tmpStr; break; case 3: // Decimal allignment field // append/save RecIDRef, OffSetVal, and Width to RtnStr RecIDRef = GetFieldTxt(); tmpStr = GetSavedLocalFieldName(RecIDRef); // append/save ValueDefType and RecIDRef to RtnStr RtnStr += "<" + tmpStr; tmpStr = GetFieldTxt(); //int OffSetVal = GetFieldInt(tmpStr); RtnStr += ","+tmpStr; tmpStr = GetFieldTxt(); //int Width = GetFieldInt(tmpStr); RtnStr += ","+tmpStr+">"; break; case 4: // Menu value definition MenuText = ""; // number of menu items tmpStr = GetFieldTxt(); NumItems = GetFieldInt(tmpStr); tmpStr2 = ""; while (NumItems > 0) { // menu text string (maybe) tmpStr = GetFieldTxt(); if (!StringsAreEqual(tmpStr,"0")) // do we have MenuText? { MenuText = GetStringByLength(); MenuText = FixString(MenuText); } // append/save ValueDefType, NumItems, tmpStr, and MenuText to RtnStr // Get list of other ValueDefTypes tmpStr = GetValueDefinition(); // call itself // append/save tmpStr to RtnStr tmpStr2 += "{" + MenuText + "=" + tmpStr + "}"; NumItems--; } RtnStr += tmpStr2; break; case 5: // Conditional value definition MenuText = ""; // number of menu items tmpStr = GetFieldTxt(); NumItems = GetFieldInt(tmpStr); tmpStr3 = ""; tmpStr2 = ""; while (NumItems > 0) { // menu text string (maybe) tmpStr = GetFieldTxt(); if (!StringsAreEqual(tmpStr,"0")) // do we have MenuText? { MenuText = GetStringByLength(); MenuText = FixString(MenuText); } // append/save ValueDefType, NumItems, tmpStr, and MenuText to RtnStr // Get list of other ValueDefTypes tmpStr = GetValueDefinition(); // call itself // append/save tmpStr to RtnStr tmpStr2 += "{" + MenuText + "=" + tmpStr + "}"; NumItems--; } // Conditional text??? tmpStr = GetStringByLength(); // append/save tmpStr to RtnStr tmpStr = FixString(tmpStr); tmpStr3 = "{" + tmpStr + tmpStr2 + "}"; RtnStr += tmpStr3; break; case 6: // VARUSE tmpStr = GetStringByLength(); tmpStr = FixString(tmpStr); // append/save ValueDefType and TxtStr to RtnStr RtnStr += "{" + tmpStr + "}"; break; case 7: // VARDEFINE tmpStr2 = GetStringByLength(); tmpStr2 = FixString(tmpStr2); tmpStr = GetValueDefinition(); // call itself // append/save ValueDefType, TxtStr, and tmpStr to RtnStr RtnStr += "{" + tmpStr2 + "=" + tmpStr + "}"; break; default: // nothing to do break; } // end switch } while (ValueDefType != 0); /* * Need to replace '<' with '<' and '>' with '>' */ RtnStr = ReplaceGreaterLessSigns(RtnStr); return RtnStr; } /* * This function returns a string containing a value to an RO field. */ String GetFieldValue() { String RtnStr; String tmpStr; String ValueTypeStr; int ValueType = 0; ValueTypeStr = GetFieldTxt(); ValueType = GetFieldInt(ValueTypeStr); CurrentFieldType = ValueType; RtnStr = ""; switch (ValueType) { case 1: // Text String case 2: // variable text string tmpStr = GetStringByLength(); tmpStr = FixString(tmpStr); RtnStr += tmpStr; break; case 0x20: // Image File (Intergrated Graphics) tmpStr = GetStringByLength(); // image file name tmpStr = FixString(tmpStr); String DateTimeStr = GetFieldTxt(); String ImgHeight = GetFieldTxt(); String ImgWidth = GetFieldTxt(); RtnStr += "\r\n" + DateTimeStr + " " + tmpStr + "\r\n"; RtnStr += "" + ImgHeight + "\r\n"; RtnStr += "" + ImgWidth + "\r\n"; break; case 0x40: // Parameter Display Data tmpStr = GetFieldTxt(); while (!StringsAreEqual(tmpStr,"0")) { tmpStr = GetFieldTxt(); // get the RecID of the field while (!StringsAreEqual(tmpStr,"0")) { string FieldName = GetSavedLocalFieldName(tmpStr); RtnStr += "<" + FieldName+ ">"; RtnStr += GetFieldValue(); RtnStr += "\r\n"; tmpStr = GetFieldTxt(); // next } tmpStr = GetFieldTxt(); // next } break; default: // should never get into here.... tmpStr = GetStringByLength(); tmpStr = FixString(tmpStr); RtnStr += tmpStr; break; } // end switch return RtnStr; } // Search the local list for the given Record ID // Return the field name String GetSavedLocalFieldName(String RecordID) { String RtnStr = ""; FieldInfo TmpInfo; System.Collections.IEnumerator FldLstEnumerator = LocalFieldInfoList.GetEnumerator(); while (FldLstEnumerator.MoveNext() && StringsAreEqual(RtnStr,"")) { TmpInfo = (FieldInfo)FldLstEnumerator.Current; if (StringsAreEqual(TmpInfo.fldRecID,RecordID)) RtnStr = TmpInfo.fldName; } return RtnStr; } // Search the master field list for a the given Record ID // Return the field name and type if found String GetSavedMasterFieldNameAndType(String RecordID) { String RtnStr = ""; FieldInfo TmpInfo; System.Collections.IEnumerator FldLstEnumerator = MasterFieldInfoList.GetEnumerator(); while (FldLstEnumerator.MoveNext() && StringsAreEqual(RtnStr,"")) { TmpInfo = (FieldInfo)FldLstEnumerator.Current; if (StringsAreEqual(TmpInfo.fldRecID,RecordID)) { RtnStr = TmpInfo.fldType.PadLeft(3,'0') + " " + TmpInfo.fldName; if (TmpInfo.fldType.Equals("128")) // is this a combo type? RtnStr += "a"; // append an "a" } } return RtnStr; } /* * See if the given RECID is referencing a combo field. */ bool IsComboFieldType(String fldName) { bool IsACombo = false; bool wasFound = false; FieldInfo TmpInfo; System.Collections.IEnumerator LocFldLstEnumerator = LocalFieldInfoList.GetEnumerator(); System.Collections.IEnumerator FldLstEnumerator = MasterFieldInfoList.GetEnumerator(); // Bug fix: B2004-028 // Need to check local list of fields (of this group) // Then then if not in the local list, check the "global" list while (!IsACombo && LocFldLstEnumerator.MoveNext()) { TmpInfo = (FieldInfo)LocFldLstEnumerator.Current; if (StringsAreEqual(TmpInfo.fldName,fldName)) { wasFound = true; if (StringsAreEqual(TmpInfo.fldType,"128")) IsACombo = true; } } if (!wasFound) { while (!IsACombo && FldLstEnumerator.MoveNext()) { TmpInfo = (FieldInfo)FldLstEnumerator.Current; if (StringsAreEqual(TmpInfo.fldName,fldName) && StringsAreEqual(TmpInfo.fldType,"128")) IsACombo = true; } } return IsACombo; } String BuildComboFieldName(String FldName) { String RtnStr = FldName; switch (CurrentFieldType) { case 1: //Fixed Text RtnStr += "a"; break; case 2: // Variable Text RtnStr += "b"; break; case 16: // Table RtnStr += "c"; break; case 8: RtnStr += "d"; break; default: break; } return RtnStr; } String GetGroupTitle(String RecordID) { String RtnStr = ""; GroupTitles Tmpitem; System.Collections.IEnumerator GrpLstEnumerator = GroupTitlesList.GetEnumerator(); while (GrpLstEnumerator.MoveNext() && StringsAreEqual(RtnStr,"")) { Tmpitem = (GroupTitles)GrpLstEnumerator.Current; if (StringsAreEqual(Tmpitem.GrpRecID,RecordID)) RtnStr = Tmpitem.GrpTitle; } return RtnStr; } String ReplaceGreaterLessSigns(String InStr) { String OutStr = InStr; OutStr = OutStr.Replace("<","<"); OutStr = OutStr.Replace(">",">"); return OutStr; } // Replace any character less than 32 (space) or greater then // 126 (~) with "&#D;" where D is the decimal value of the character String ReplaceNonStandardChars(string instring) { string outstring = ""; int len = instring.Length; int i=0; int substart=0; ushort decchar; while (i < len) { while (i < len && instring[i] < 127) i++; outstring += instring.Substring(substart, i-substart); if (i < len) { decchar = instring[i]; outstring += "&#" + decchar.ToString() + ";"; i++; substart = i; } } return outstring; } /* * String cannot have '&' or '/' chars * replace them with an '_' */ String FixString(String instring) { String FixedString = ""; StringWriter strWriter = new StringWriter(); xmlTxtWriter = new XmlTextWriter(strWriter); xmlTxtWriter.WriteString(instring); FixedString = strWriter.ToString(); xmlTxtWriter.Close(); // Now replace any character less than 32 (space) or greater then // 126 (~) with "&#D;" where D is the decimal value of the character FixedString = ReplaceNonStandardChars(FixedString); // need to replace the forward slash with an character reference FixedString = FixedString.Replace("/","/"); /* * The WriteString method is not replacing the single * and double quotes. So we will do it manually */ FixedString = FixedString.Replace("'","'"); FixedString = FixedString.Replace("\"","""); return FixedString; } public string ReplaceNonValidCharsInFieldName(string fldname) { string tmpstr = fldname; int len = fldname.Length; int cnt = 0; // this is also our sequence that tells us the follow 3 digits is the ascii number (base 10) // of the character we replaced. string OKpunch = "-._"; string outstr = ""; int decval; while (cnt < len) { char tmpchr = tmpstr[cnt]; if(!char.IsLetterOrDigit(tmpchr)&& (OKpunch.IndexOf(tmpchr) == -1) ) { decval = tmpchr; outstr += OKpunch + decval.ToString("D3"); } else { outstr += tmpchr.ToString(); } cnt++; } DEBUG_Write(outstr); return outstr; } /* * Field names cannot have ' ', '&', or '/' characters */ String FixFieldName(String fldname) { String fixedField = fldname; DEBUG_CheckFieldName(fldname); fixedField = fixedField.Replace(" ","__"); /* * If the first character is 0-9, then put a '_' in front of the field name */ if (Char.IsDigit(fixedField,0)) fixedField = "__" + fixedField; fixedField = ReplaceNonValidCharsInFieldName(fixedField); return fixedField; } /* * This function will parse the remaining information in the LineOfText string * and create the value needed for the Info field of the database record. */ String ParseInfoField() { String RtnStr = ""; String tmpStr; String Title; String ROMenuHead; String GrpMenuHead; String RoValueDef; String RoMenuItemDef; String GroupMenuItemDef; String RoFieldsInUse; String GroupFieldsInUse; String FieldName; int intRecType = GetFieldInt(RecType); switch (intRecType) { case 0: // Next Record Id or next database table name RtnStr = GetFieldTxt(); break; case 1: // Database title and database name RtnStr = GetStringByLength(); // database title ROTblElmt = FixFieldName(RtnStr); RtnStr += "\t"; tmpStr = GetStringByLength(); // database table name if (tmpStr.Length == 0) RtnStr += "RO000001"; // default database table name else RtnStr += tmpStr; break; case 2: // Field Description // get the field definition RtnStr = GetFieldDefinition(); break; case 3: // RO Group GroupTitle = GetStringByLength(); // group name (title) ROMenuHead = GetStringByLength(); // RO menu header GrpMenuHead = GetStringByLength();// Group menu header RtnStr = ""; SubGrpFldsAndVals += GetFieldValue(); SubGrpFldsAndVals += "\r\n"; tmpStr = GetFieldTxt(); // next } RtnStr += SubGrpFldsAndVals; RtnStr += ""; // end group definition break; case 5: // RO Value Record // RO Menu Item Value String ROMenuItemValue = GetStringByLength(); ROMenuItemValue = FixString(ROMenuItemValue); RtnStr = "<" + FixFieldName(GroupTitle) + " "; // RO Menu Item RtnStr += "MenuTitle=\"" + ROMenuItemValue + "\">\r\n"; //RO fields and values String ROFldsAndVals = ""; tmpStr = GetFieldTxt(); while (!StringsAreEqual(tmpStr,"0")) { FieldName = GetSavedLocalFieldName(tmpStr); tmpStr = GetFieldValue(); if (IsComboFieldType(FieldName)) { FieldName = BuildComboFieldName(FieldName); } ROFldsAndVals += "<" + FieldName + ">"; ROFldsAndVals += tmpStr; ROFldsAndVals += "\r\n"; tmpStr = GetFieldTxt(); } RtnStr += ROFldsAndVals; RtnStr += "\r\n"; break; default: break; }// end switch return RtnStr; } /* * This function will parse the given text record (string) and place the * information in a database record. */ void ProcessTextLine() { /* * Get the first 5 database fields and save them in string types. */ RecID= GetFieldTxt(); RecType = GetFieldTxt(); ParentRecID = GetFieldTxt(); AccPageID = GetStringByLength(); DateTime = GetFieldTxt(); intRecType = GetFieldInt(RecType); /***** For Debugging ***/ // if (RecID.Equals("000000c1")) // { // int test; // test = 1; // } // if (AccPageID.Equals("R.29")) // { // MessageBox.Show("debug"); // } /**** End - for debugging ****/ // setup a new database record NewDbField = new ROField("", RecID, ParentRecID, (uint)intRecType); /* * Now what's remaining in the txtRecord string is the BLOB info from * the old Paradox database record. * Parse the remaining information and build the XML or XSD string that * represents the data. */ Info = ParseInfoField(); // Fix the single quotes before writing to the database // MS Access complained when we tried to write "C'.'99", wanted "C''.''99" instead Info = Info.Replace("'","''"); // if we are processing a record type 4, save it as a record type 3. // record type 4's were considered subgroups. We are going to store them // as groups (type 3) with the parent id pointing to the the parent group // or subgroup. if (intRecType == 4 && !StringsAreEqual(RecType,"2")) intRecType = 3; // write to database MyDbRec.RODB_WriteDbRecord(ROTableName,RecID,intRecType,ParentRecID,AccPageID,DateTime,Info); if (StringsAreEqual(RecType,"0")&& StringsAreEqual(RecID,"00000001")) { // build schema header for the table just inserted Info = "\r\n"; Info += ""; Info += "\r\n"; Info += ""; // write the schema header record (type 6) // Note that a null recid will cause RODB_WriteDbRecord to get the next // available one and update the "next RecID" database record. MyDbRec.RODB_WriteDbRecord(ROTableName,"",6,"00000000","",DateTime,Info); // build the schema footer for the table just inserted Info = "\r\n"; Info += "\r\n"; Info += "\r\n"; Info += "\r\n"; Info += "\r\n"; Info += "\r\n"; Info += "\r\n"; Info += "\r\n"; Info += "\r\n"; Info += "\r\n"; Info += "\r\n"; Info += "\r\n"; Info += "\r\n"; Info += "\r\n"; Info += "\r\n"; Info += "\r\n"; Info += "\r\n"; Info += "\r\n"; Info += "\r\n"; Info += "\r\n"; Info += "\r\n"; Info += "\r\n"; Info += "\r\n"; // write the schema footer record (type 7) // Note that a null recid will cause RODB_WriteDbRecord to get the next // available one and update the "next RecID" database record. MyDbRec.RODB_WriteDbRecord(ROTableName,"",7,"00000000","",DateTime,Info); } } } }