using System; using System.Collections.Generic; using System.Collections.Specialized; using System.Text; using System.ComponentModel; using System.Text.RegularExpressions; using System.IO; namespace VEPROMS.CSLA.Library { [Serializable] [TypeConverter(typeof(ExpandableObjectConverter))] public class ROFSTLookup { #region Log4Net private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); #endregion #region Structs [Serializable] public struct roHdr { public int hSize; public int hYear; public byte hMonth; public byte hDay; public int hcYear; public byte hcMonth; public byte hcDay; public byte hcHour; public byte hcMin; public byte hcSec; public byte hcHund; public rodbi[] myDbs; }; [Serializable] public struct rodbi { public int dbiID; public int dbiType; public int dbiAW; public string dbiTitle; public string dbiAP; public int ID; public int ParentID; public rochild[] children; }; public struct rogrp { public int ID; public int ParentID; public rochild[] children; public string value; public string appid; }; public struct rochild { public int ID; public int ParentID; public int type; public string title; public string roid; public string appid; public string value; public rochild[] children; }; public class roChild { rochild _MyChild; public rochild MyChild { get { return _MyChild; } set { _MyChild = value; } } public roChild(rochild myChild) { _MyChild = myChild; } public override string ToString() { return _MyChild.title; } }; #endregion #region Local Data private string _ROValue = ""; private List lstRoValues; private List multiRoValues; private Dictionary DictROVar = new Dictionary(); #endregion #region Constructors private ROFst _ROFst; private ROFstInfo _ROFstInfo; private int _SelectedSlave; private DocVersionInfo _DocVersionInfo; public DocVersionInfo DocVersionInfo { get { return _DocVersionInfo; } set { _DocVersionInfo = value; if (_DocVersionInfo.DocVersionConfig.SelectedSlave != _SelectedSlave) { _SelectedSlave = _DocVersionInfo.DocVersionConfig.SelectedSlave; Reset(); } } } public ROFSTLookup(ROFst rofst) { _ROFst = rofst; _ROFstInfo = null; using (ROFstInfo rfi = ROFstInfo.GetJustROFst(_ROFst.ROFstID)) { _DocVersionInfo = rfi.docVer;//==null?null: DocVersionInfo.Get(rfi.docVer.VersionID); } ParseIntoDictionary(rofst.ROLookup); } public ROFSTLookup(ROFstInfo rofstinfo) { _ROFstInfo = rofstinfo; _ROFst = null; // docversion will be null if we're working with an ro.fst that is not currently connected // to a docversion. One example of this is when updating ro.fst and comparing the original // with the new to find differences. The docversioninfo is only used to get unit/master // slave info, thus is not needed to compare the raw values. _DocVersionInfo = _ROFstInfo.docVer;//==null?null: DocVersionInfo.Get(_ROFstInfo.docVer.VersionID); ParseIntoDictionary(rofstinfo.ROLookup); } public ROFSTLookup(string filePath) { _ROFstInfo = null; _ROFst = null; _DocVersionInfo = null; FileInfo rofstFile = new FileInfo(filePath); FileStream fs = rofstFile.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite); byte[] buf = new byte[rofstFile.Length]; fs.Read(buf, 0, buf.Length); fs.Close(); ParseIntoDictionary(buf); } #endregion #region PropertiesAndData public roHdr myHdr; private int TableID; private Dictionary dicRos; private Dictionary dicRosIntIDs; public void Reset() { dicRos = null; dicRosIntIDs = null; } #endregion #region AppSupport public void Close() { // remove the dictionary if (dicRosIntIDs != null)dicRosIntIDs.Clear(); dicRosIntIDs = null; if (dicRos != null)dicRos.Clear(); dicRos = null; } public List GetValueDifferences(ROFSTLookup origROFst, ref List delList) { // use this list to see what differences are between it and the original List modList = new List(); // assume each rofstlookup has a parsed dictionary foreach (string key in origROFst.dicRos.Keys) { string cvalue = null; string ovalue = origROFst.dicRos[key].value; if (dicRos.ContainsKey(key)) cvalue = dicRos[key].value; if (cvalue == null && cvalue != ovalue) delList.Add(key); else if (cvalue != ovalue) { // Value Change modList.Add(key); //Console.WriteLine("RO{0}\t\"{1}\"\t\"{2}\"", key, cvalue, ovalue); } } return modList; } //public static ROImageInfo Get(RODbInfo rodbinfo, string filename) //{ // if (rodbinfo.RODbROImageCount != 0) // { // foreach (ROImageInfo ri in rodbinfo.RODbROImages) // { // if (ri.FileName == filename) return ri; // } // } // return null; //} public string GetTranslatedRoValue(string ROID16, bool DoCaret) { string retval = GetRoValue(ROID16); retval = ReplaceUnicode(retval, DoCaret); retval = ConvertFortranFormatToScienctificNotation(retval); return retval.Replace("\r\n", @"\par "); } private string ReplaceUnicode(string s2, bool DoCaret) { string orig = s2; s2 = s2.Replace("`", @"\'b0"); // convert backquote to degree - left over from DOS days. s2 = s2.Replace("\xa0", @"\u160?"); // hardspace s2 = s2.Replace("\xb0", @"\'b0"); // degree s2 = s2.Replace("\x7f", @"\u916?"); // delta s2 = s2.Replace("\x2265", @"\u8805?"); // greater than or equal s2 = s2.Replace("\x2264", @"\u8804?"); // less than or equal s2 = s2.Replace("\xB1", @"\'b1"); // plus minus s2 = s2.Replace("\x3A3", @"\u931?"); // sigma s2 = s2.Replace("\x3C4", @"\u947?"); // gamma s2 = s2.Replace("\xBD", @"\'bd"); // half s2 = s2.Replace("\x25A0", @"\u9604?"); // accum 2584 s2 = s2.Replace("\x7", @"\u9679?"); // bullet 25CF s2 = s2.Replace("\x2248", @"\u8776?"); // approx eq s2 = s2.Replace("\x2261", @"\u8773?"); // similar eq 2245 s2 = s2.Replace("\xF7", @"\'f7"); // division s2 = s2.Replace("\x221A", @"\u8730?"); // square root s2 = s2.Replace("\x393", @"\u961?"); // rho 3C1 s2 = s2.Replace("\x3C0", @"\u960?"); // pi s2 = s2.Replace("\xb5", @"\u956?"); // micro 3BC (try e6, if not work try 109) s2 = s2.Replace("\x3B4", @"\u948?"); // lower case delta s2 = s2.Replace("\x3C3", @"\u963?"); // lower case sigma s2 = s2.Replace("\xBC", @"\'bc"); // quarter s2 = s2.Replace("\x3C6", @"\'d8"); // dist zero, D8 s2 = s2.Replace("\xC9", @"\u274?"); // energy, 112 s2 = s2.Replace("\xEC", @"\'ec"); // grave s2 = s2.Replace("\x2502", @"\u9474?"); // bar s2 = s2.Replace("\x3B5", @"\u949?"); // epsilon s2 = s2.Replace("\x398", @"\u952?"); // theta, 3B8 s2 = s2.Replace("\x221E", @"\u8857?"); // dot in oval, 2299 s2 = s2.Replace("\xBF", @"\u964?"); // tau, 3C4 s2 = s2.Replace("\x2310", @"\u9830?"); // diamond, 2666 s2 = s2.Replace("\x2192", @"\u8594?"); s2 = s2.Replace("\x2190", @"\u8592?"); s2 = s2.Replace("\x2191", @"\u8593?"); s2 = s2.Replace("\x2193", @"\u8595?"); s2 = s2.Replace("\x2207", @"\u8711?"); s2 = s2.Replace("\x2591", @"\'b0"); // Degree Symbol s2 = s2.Replace("\xFF", @"\u8593?"); // Up Arrow s2 = s2.Replace("\xD6", @"\u8595?"); // Down Arrow if (DoCaret) s2 = s2.Replace("^", @"\u916?"); // Convert dash to a non-breaking dash. This is a unicode character. // This character will be used in veproms rather than a dash. //if the dash is preceeded byte a token remove the space following the token s2 = Regex.Replace(s2, @"(\\[^ \\?]*) \-", @"$1\u8209?"); s2 = s2.Replace("-", @"\u8209?"); return s2; } private string FixUnitROs(string val) { if (val.StartsWith("") val = _ROFstInfo.docVer.DocVersionConfig.Unit_Text; else if (val.ToUpper() == "") val = _ROFstInfo.docVer.DocVersionConfig.Unit_Number; else if (val.ToUpper() == "") val = _ROFstInfo.docVer.DocVersionConfig.Unit_Name; else if (val.ToUpper() == "") val = _ROFstInfo.docVer.DocVersionConfig.Unit_ID; else if (val.ToUpper() == "") val = _ROFstInfo.docVer.DocVersionConfig.Other_Unit_Text; else if (val.ToUpper() == "") val = _ROFstInfo.docVer.DocVersionConfig.Other_Unit_Number; else if (val.ToUpper() == "") val = _ROFstInfo.docVer.DocVersionConfig.Other_Unit_Name; else if (val.ToUpper() == "") val = _ROFstInfo.docVer.DocVersionConfig.Other_Unit_ID; } return val; } // this only gets rochild values. Later we may want another // dictionary to get groups. public string GetRoValue(string ROID16) { string ROID = ROID16.Substring(0,12); if (dicRos == null) ParseIntoDictionary(_ROFst!=null?_ROFst.ROLookup:_ROFstInfo.ROLookup); // Use the ROID to get the value from the dictionary if (dicRos.ContainsKey(ROID.ToUpper())) { rochild rochld = (rochild)dicRos[ROID.ToUpper()]; if (rochld.value != null && rochld.value != string.Empty) return FixUnitROs( rochld.value); if (rochld.children != null) { foreach (rochild child in rochld.children) if (child.roid.ToUpper() == ROID16.ToUpper() || (child.roid.EndsWith("0041") && ROID16.EndsWith("0000"))) return FixUnitROs(child.value); // if there isn't a specific match for multi-return values, default to the first child. return FixUnitROs(rochld.children[0].value); } } //if (ROID == "FFFF00000001") return _ROFstInfo.ROFstAssociations[0].MyDocVersion.DocVersionConfig.Unit_Number; //if (ROID == "FFFF00000002") return _ROFstInfo.ROFstAssociations[0].MyDocVersion.DocVersionConfig.Other_Unit_Number; //if (ROID == "FFFF00000003") return _ROFstInfo.ROFstAssociations[0].MyDocVersion.DocVersionConfig.Unit_Text; //if (ROID == "FFFF00000004") return _ROFstInfo.ROFstAssociations[0].MyDocVersion.DocVersionConfig.Other_Unit_Text; //if (ROID == "FFFF00000005") return _ROFstInfo.ROFstAssociations[0].MyDocVersion.DocVersionConfig.Unit_ID; //if (ROID == "FFFF00000006") return _ROFstInfo.ROFstAssociations[0].MyDocVersion.DocVersionConfig.Other_Unit_ID; //if (ROID == "FFFF00000007") return _ROFstInfo.ROFstAssociations[0].MyDocVersion.DocVersionConfig.Unit_Name; //if (ROID == "FFFF00000008") return _ROFstInfo.ROFstAssociations[0].MyDocVersion.DocVersionConfig.Other_Unit_Name; //new stuff if (ROID == "FFFF00000001") return _ROFstInfo.docVer.DocVersionConfig.Unit_Number; if (ROID == "FFFF00000002") return _ROFstInfo.docVer.DocVersionConfig.Other_Unit_Number; if (ROID == "FFFF00000003") return _ROFstInfo.docVer.DocVersionConfig.Unit_Text; if (ROID == "FFFF00000004") return _ROFstInfo.docVer.DocVersionConfig.Other_Unit_Text; if (ROID == "FFFF00000005") return _ROFstInfo.docVer.DocVersionConfig.Unit_ID; if (ROID == "FFFF00000006") return _ROFstInfo.docVer.DocVersionConfig.Other_Unit_ID; if (ROID == "FFFF00000007") return _ROFstInfo.docVer.DocVersionConfig.Unit_Name; if (ROID == "FFFF00000008") return _ROFstInfo.docVer.DocVersionConfig.Other_Unit_Name; //end new stuff if (ROID.StartsWith("FFFF")) return "?"; // string.Format("Invalid Unit RO '{0}'", ROID); return "?"; // string.Format("Invalid RO '{0}'", ROID); } // Get the the RO's Accessory Page ID public string GetRoACID(string ROID16) { string ROID = ROID16.Substring(0,12); if (dicRos == null) ParseIntoDictionary(_ROFst!=null?_ROFst.ROLookup:_ROFstInfo.ROLookup); // Use the ROID to get the value from the dictionary if (dicRos.ContainsKey(ROID.ToUpper())) { rochild rochld = (rochild)dicRos[ROID.ToUpper()]; if (rochld.value != null && rochld.value != string.Empty) return rochld.appid; if (rochld.children != null) { foreach (rochild child in rochld.children) if (child.roid.ToUpper() == ROID16 || (child.roid.EndsWith("0041") && ROID16.EndsWith("0000"))) return child.appid; // if there isn't a specific match for multi-return values, default to the first child. return rochld.children[0].appid; } } return ""; // no accessory page ID found } public rochild GetRoChild12(string ROID16) { string ROID = ROID16.Substring(0, 12); if (dicRos == null) ParseIntoDictionary(_ROFst != null ? _ROFst.ROLookup : _ROFstInfo.ROLookup); // Use the ROID to get the value from the dictionary if (dicRos.ContainsKey(ROID.ToUpper())) { rochild rochld = (rochild)dicRos[ROID.ToUpper()]; return rochld; } rochild tmp = new rochild(); tmp.ID = -1; return tmp; } public rochild GetRoChild(string ROID) { if (dicRos == null) ParseIntoDictionary(_ROFst != null ? _ROFst.ROLookup : _ROFstInfo.ROLookup); // Use the ROID to get the value from the dictionary if (dicRos.ContainsKey(ROID.ToUpper())) { rochild rochld = (rochild)dicRos[ROID.ToUpper()]; return rochld; } if (ROID.StartsWith("FFFF")) { rochild roc = new rochild(); roc.roid = ROID; roc.type = 1; int selectedSlave = _ROFstInfo.docVer.DocVersionConfig.SelectedSlave; _ROFstInfo.docVer.DocVersionConfig.SelectedSlave = 0; roc.value = GetRoValue(ROID); _ROFstInfo.docVer.DocVersionConfig.SelectedSlave = selectedSlave; switch (ROID) { case "FFFF00000001": roc.appid = "U-Number"; break; case "FFFF00000002": roc.appid = "U-Other Number"; break; case "FFFF00000003": roc.appid = "U-Text"; break; case "FFFF00000004": roc.appid = "U-Other Text"; break; case "FFFF00000005": roc.appid = "U-ID"; break; case "FFFF00000006": roc.appid = "U-Other ID"; break; case "FFFF00000007": roc.appid = "U-Name"; break; case "FFFF00000008": roc.appid = "U-Other Name"; break; default: roc.appid = "U-Unknown"; break; } return roc; } rochild tmp = new rochild(); tmp.ID = -1; return tmp; } public string GetROTitle(string ROID) { StringBuilder sb = new StringBuilder(); rochild roc = GetRoChild12(ROID); if (roc.value == null) roc = GetRoChild(ROID); sb.Append(roc.title.Replace(roc.appid,"").Replace(roc.value,"").Trim()); do { string parent = ROID.Substring(0, 4) + string.Format("{0:X8}", roc.ParentID); roc = GetRoChild12(parent); if (roc.ID > 0) sb.Insert(0, roc.title + " - "); } while (roc.ID > 0); return sb.ToString(); } // Return the RO Title in a list of strings // The last item in the list is the actual RO title, the items preceding it are the // titles of the groups and sub-groups containing the RO public List GetROTitleAndGroupPath(string ROID) { List titlePath = new List(); rochild roc = GetRoChild12(ROID); //string tmp = roc.title.Replace(roc.appid, "").Replace(roc.value, "").Trim(); string tmp = roc.title.Replace(roc.appid, string.Format("<{0}>",roc.appid)).Trim(); titlePath.Add(tmp); do { string parent = ROID.Substring(0, 4) + string.Format("{0:X8}", roc.ParentID); roc = GetRoChild12(parent); if (roc.ID > 0) titlePath.Add(roc.title); } while (roc.ID > 0); titlePath.Reverse(); return titlePath; } // The following Method is not correct. It needs to have a RO database id as well as an id. Without that, // the first RO with a specific id will be found regardless of the RO Database id. //public rochild GetRoChildFromID(int id) //{ // if (dicRosIntIDs == null) ParseIntoDictionary(_ROFst != null ? _ROFst.ROLookup : _ROFstInfo.ROLookup); // // Use the id to get the value from the dictionary // if (dicRosIntIDs.ContainsKey(id)) // { // rochild rochld = (rochild)dicRosIntIDs[id]; // return rochld; // } // rochild tmp = new rochild(); // tmp.ID = -1; // return tmp; //} public rodbi[] GetRODatabaseList() { return myHdr.myDbs; } //public string GetDefaultROPrefix() //{ // if (docVer != null) // return docVer.DocVersionConfig.RODefaults_setpointprefix; // else // return "SP1"; // Not Sure about this... //} //public string GetDefaultGraphicsPrefix() //{ // if (docVer != null) // return docVer.DocVersionConfig.RODefaults_graphicsprefix; // else // return "IG1"; // Not Sure about this... //} #region Update Ro Values /// /// Updates an ro.fst into a sql database. /// /// /// ROFst: Returns the created rofst object //public static ROFst UpdateRoFst(RODbInfo rdi, DocVersionAssociation dva, DocVersion docver) //{ // // file validity checks are done before getting here - just do the import // // here. // string rofstfilepath = rdi.FolderPath + @"\ro.fst"; // DirectoryInfo di = new DirectoryInfo(rdi.FolderPath); // // There may be more than 1 'ro' as the 'ROName' field (ROName is derived from the ropath). // // Get new name be incrementing, if so. // string newname = NewROName(di.Name); // // Next read in the rofst & make the rofst record. // FileStream fsIn = new FileStream(rofstfilepath, FileMode.Open, FileAccess.Read, FileShare.Read); // // Create an instance of StreamReader that can read characters from the FileStream. // BinaryReader r = new BinaryReader(fsIn); // byte[] ab = r.ReadBytes((int)fsIn.Length); // fsIn.Close(); // using (RODb rd = RODb.Get(rdi.RODbID)) // { // ROFst rofst = ROFst.MakeROFst(rd, ab, null, di.LastWriteTimeUtc, rdi.UserID); // // Hook this into the current docversion by replacing the rofstid field in the doc version // // association object: // dva.MyROFst = rofst; // docver.Save(); // // Now load any images in... type 8 - integrated graphics ro type // ROFstInfo rofstInfo = ROFstInfo.Get(rofst.ROFstID); // rofstInfo.ParseIntoDictionary(rofstInfo.ROFST); // for (int i = 0; i < rofstInfo.myHdr.myDbs.Length; i++) // { // // walk through the rofst 'database' searching for all nodes that are integrated graphics, type 8: // if (rofstInfo.myHdr.myDbs[i].children != null) rofstInfo.MigrateRoFstGraphics(rdi, rofstInfo.myHdr.myDbs[i].children); // } // return rofst; // } //} //private static string RoAppConfigExt(string fstPath) //{ // string inipath = fstPath + @"\roapp.ini"; // if (!File.Exists(inipath)) return null; // StreamReader myReader = new StreamReader(inipath); // string sLine; // int indx = -1; // while ((sLine = myReader.ReadLine()) != null) // { // if (sLine.Length > 0 && sLine.Substring(0, 1) != ";") // { // if ((indx = sLine.ToLower().IndexOf("extention")) >= 0) // { // indx = sLine.IndexOf("=", indx + 9); // return sLine.Substring(indx + 1, sLine.Length - indx - 1).Trim(); // } // } // } // myReader.Close(); // return null; //} //private static string NewROName(string roName) //{ // string retval = roName; // int iSuffix = -1; // RODbInfoList rodblist = RODbInfoList.Get(); // foreach (RODbInfo rdi in rodblist) // { // if (rdi.ROName.StartsWith(roName)) // { // if (rdi.ROName == roName) // iSuffix = 0; // else if (Regex.IsMatch(rdi.ROName, roName + "[_][0-9]+")) // { // int ii = int.Parse(rdi.ROName.Substring(1 + roName.Length)); // if (ii > iSuffix) iSuffix = ii; // } // } // } // if (iSuffix >= 0) // retval = string.Format("{0}_{1}", roName, iSuffix + 1); // return retval; //} //private void MigrateRoFstGraphics(RODbInfo rdi, ROFstInfo.rochild[] rochild) //{ // for (int i = 0; i < rochild.Length; i++) // { // if (rochild[i].type == 8) AddGraphic(rdi, rochild[i].value); // if (rochild[i].children != null) MigrateRoFstGraphics(rdi, rochild[i].children); // } //} //private void AddGraphic(RODbInfo rdi, string p) //{ // if (p == null) return; // string imgname = p.Substring(0, p.IndexOf('\n')); // int thedot = imgname.LastIndexOf('.'); // string fname = imgname; // if (thedot == -1 || (thedot != (imgname.Length - 4))) // { // RODbConfig roDbCfg = new RODbConfig(rdi.Config); // fname += string.Format(".{0}", roDbCfg.GetDefaultGraphicExtension()); // } // string imgfile = rdi.FolderPath + @"\" + fname; // ROImage roImg = null; // if (File.Exists(imgfile)) // { // FileInfo fi = new FileInfo(imgfile); // // if the roimage record exists, don't create a new one... // using (roImg = ROImage.GetByRODbID_FileName_DTS(rdi.RODbID, imgname, fi.LastWriteTimeUtc)) // { // if (roImg == null) // { // FileStream fsIn = new FileStream(imgfile, FileMode.Open, FileAccess.Read, FileShare.Read); // BinaryReader r = new BinaryReader(fsIn); // byte[] ab = r.ReadBytes((int)fsIn.Length); // r.Close(); // fsIn.Close(); // using (RODb rodb = RODb.Get(rdi.RODbID)) // { // roImg = ROImage.MakeROImage(rodb, imgname, ab, null, fi.LastWriteTimeUtc, "Migration"); // } // } // Figure figure = Figure.GetByROFstID_ImageID(this.ROFstID, roImg.ImageID); // if (figure != null) return; // using (ROFst rofst = ROFst.Get(this.ROFstID)) // { // figure = Figure.MakeFigure(rofst, roImg, null); // } // } // } // else // Console.WriteLine(string.Format("{0}", imgfile), "Cannot Find Image File"); //} #endregion #endregion #region LoadStructs private int StringLength(byte[] ab, int offset) { int i = 0; while (ab[i + offset] != 0) i++; return i; } private rogrp LoadGroup(byte[] ab, int offset) { rogrp myGrp = new rogrp(); myGrp.ID = BitConverter.ToInt32(ab, offset); if (myGrp.ID == 1195) Console.WriteLine("jcb"); myGrp.ParentID = BitConverter.ToInt32(ab, offset + 4); int howmany = BitConverter.ToInt16(ab, offset + 8); if (howmany > 0) { myGrp.children = new rochild[howmany]; int myOffset = offset + 10; for (int i = 0; i < myGrp.children.Length; i++) { int childOffset = BitConverter.ToInt32(ab, myOffset); rochild tmp = new rochild(); //tmp.offset=BitConverter.ToInt32(ab,myOffset); tmp.type = BitConverter.ToInt16(ab, myOffset + 4); int slen = StringLength(ab, myOffset + 6); tmp.title = Encoding.Default.GetString(ab, myOffset + 6, slen); myOffset += (7 + slen); rogrp tmpg = LoadGroup(ab, childOffset); MultipleReturnValuesInheritType(ref tmpg, tmp.type); tmp.ID = tmpg.ID; tmp.ParentID = tmpg.ParentID; tmp.children = tmpg.children; tmp.value = tmpg.value; tmp.appid = tmpg.appid; tmp.roid = TableID.ToString("X4") + tmp.ID.ToString("X8"); // Add dictionary entries for children if (tmp.children != null) { foreach (rochild child in tmp.children) if (!dicRos.ContainsKey(child.roid.ToUpper())) dicRos.Add(child.roid.ToUpper(), child); } dicRos.Add(tmp.roid.ToUpper(), tmp); if (!dicRosIntIDs.ContainsKey(tmp.ID)) dicRosIntIDs.Add(tmp.ID, tmp); int j; for (j = i - 1; j >= 0 && tmp.ID < myGrp.children[j].ID; j--) { myGrp.children[j + 1] = myGrp.children[j]; } myGrp.children[j + 1] = tmp; } } else { int slen = StringLength(ab, offset + 12); //myGrp.value = Encoding.Default.GetString(ab, offset + 12, slen); ProcessROReturnValue(ref myGrp, Encoding.Default.GetString(ab, offset + 12, slen)); int slen2 = StringLength(ab, offset + 13 + slen); myGrp.appid = Encoding.Default.GetString(ab, offset + 13 + slen, slen2); } return myGrp; } /// /// This function will take the raw RO return value and resolve any macros, conditionals, and /// generated the return value or a list of multiple return values. /// /// /// private void ProcessROReturnValue(ref rogrp myGrp, string rawvalue) { if (dicRos == null) ParseIntoDictionary(_ROFst != null ? _ROFst.ROLookup : _ROFstInfo.ROLookup); List lstROVals = GetROReturnValue(rawvalue); if (lstROVals.Count > 1) // mulitple return values { myGrp.children = new rochild[lstROVals.Count]; for (int i = 0; i < lstROVals.Count; i++) { string tsts = Convert.ToInt32(multiRoValues[i][0]).ToString("X4"); myGrp.children[i].value = lstROVals[i]; myGrp.children[i].roid = TableID.ToString("X4") + myGrp.ID.ToString("X8") + tsts; myGrp.children[i].type = -1; // Multiple return value inherit type from parent myGrp.children[i].title = lstROVals[i]; } } else myGrp.value = lstROVals[0]; return; } /// /// Multiple return values need to get the type from the parent node. /// /// /// private void MultipleReturnValuesInheritType(ref rogrp myGrp, int parenttype) { if (myGrp.children != null) { for (int cnt = 0; cnt < myGrp.children.Length; cnt++) { if (myGrp.children[cnt].type == -1) { myGrp.children[cnt].type = parenttype; myGrp.children[cnt].appid = myGrp.appid; } } } } private void ParseIntoDictionary(byte[] ab) { if (dicRos == null) dicRos = new Dictionary(); if (dicRosIntIDs == null) dicRosIntIDs = new Dictionary(); myHdr.hSize = BitConverter.ToInt32(ab, 0); myHdr.hYear = BitConverter.ToInt16(ab, 4); myHdr.hMonth = ab[6]; myHdr.hDay = ab[7]; myHdr.hcYear = BitConverter.ToInt16(ab, 8); myHdr.hcMonth = ab[10]; myHdr.hcDay = ab[11]; myHdr.hcHour = ab[12]; myHdr.hcMin = ab[13]; myHdr.hcSec = ab[14]; myHdr.hcHund = ab[15]; int hdrOffset = BitConverter.ToInt32(ab, 16); int howbig = BitConverter.ToInt32(ab, hdrOffset); int dbs = BitConverter.ToInt16(ab, hdrOffset + 4); myHdr.myDbs = new rodbi[dbs]; for (int i = 0; i < dbs; i++) { int offset = hdrOffset + 6 + (i * 30); myHdr.myDbs[i].dbiID = BitConverter.ToInt16(ab, offset + 0); TableID = myHdr.myDbs[i].dbiID; myHdr.myDbs[i].dbiType = BitConverter.ToInt16(ab, offset + 2); myHdr.myDbs[i].dbiAW = BitConverter.ToInt16(ab, offset + 4); rogrp tmp = LoadGroup(ab, BitConverter.ToInt32(ab, offset + 6)); myHdr.myDbs[i].ID = tmp.ID; myHdr.myDbs[i].children = tmp.children; int iPtr = BitConverter.ToInt32(ab, offset + 22) + hdrOffset + 6; myHdr.myDbs[i].dbiTitle = Encoding.Default.GetString(ab, iPtr, StringLength(ab, iPtr)); iPtr = BitConverter.ToInt32(ab, offset + 26) + hdrOffset + 6; myHdr.myDbs[i].dbiAP = Encoding.Default.GetString(ab, iPtr, StringLength(ab, iPtr)); } } #endregion #region GetRoValues public List GetROReturnValue(string roval) { lstRoValues = new List(); multiRoValues = new List(); DictROVar = new Dictionary(); // set up a dictionary of RO defined Variables string tmp = ProcessRO(_DocVersionInfo==null?roval:_DocVersionInfo.ProcessDocVersionSpecificInfo(roval), false); if (tmp != null && lstRoValues.Count == 0) // was not a multiple return value lstRoValues.Add(tmp); return lstRoValues; } private string ProcessRO(string roval, bool multiRtnVal) { string str = roval; string rtnstr = ""; int l = roval.Length; while (l > 0) { int ptr = NextDelimiter("{", str); if (ptr == -1) { // add remaining text //add(new seText(str, l)); rtnstr += str; l = 0; // break out of while loop } else { int cnt = ptr; //(int)(ptr - str); if (cnt > 0) { // add text //add(new seText(str, cnt)); rtnstr += str.Substring(0, cnt); l -= cnt; //str = ptr; str = str.Substring(ptr); } ptr = MatchingBrace(str) + 1; cnt = ptr; //(int)(ptr - str); bool nfnd = false; string pbstr = ProcessBrace(str.Substring(1, cnt - 2), cnt - 2, ref nfnd, multiRtnVal); if (pbstr == null) return null; if (nfnd) rtnstr += str.Substring(0, cnt); // add(new seText(str, cnt)); else rtnstr += pbstr; l -= cnt; //str = ptr; str = str.Substring(ptr); } } //rtnstr = rtnstr.Replace("`", @"\'b0"); // convert backquote to degree - left over from DOS days. rtnstr = ProcessMacros(rtnstr); return rtnstr; } // // Takes the ro text value and sees if a macro has been used. If so it will perform the macro // operation on the substring in the text value // // right now the only macro is @HSP(), where every space between the "(" and ")" will be replaced with a hardspace // private string ProcessMacros(string str) { if( str == null || str == "" ) return str; string rtnstr = str; int indx = -1; while ((indx = rtnstr.ToUpper().IndexOf("@HSP("))>-1) { string resstr = rtnstr.Substring(0,indx); int endHsp = rtnstr.IndexOf(")",indx); string tmpstr = rtnstr.Substring(indx+5,endHsp-indx-5); tmpstr = tmpstr.Replace(" ", @"\u160?"); resstr = resstr + tmpstr; rtnstr = resstr + rtnstr.Substring(endHsp+1); } return rtnstr; } private string ProcessConditional(string cnd, string opt, int lencnd, int lenopt, bool multiRtnVal) { // equaluate condition string stat = (_DocVersionInfo != null) ? this._DocVersionInfo.Evaluate(cnd, lencnd) : ""; int ls = stat.Length;//strlen(stat); if (ls == 0) return ""; // if evaluation not defined then return an empty string - no matches can be made // look for match - remember default string match = null; int matchlen = 0; string def = null; int deflen = 0; while (lenopt > 0 && match == null) { int end = MatchingBrace(opt); int eq = opt.IndexOf('=');// strchr(opt, '='); int len = end + 1; //(int)((end + 1) - opt); // +1 to include the '}' int li = eq - 1;//(int)(eq - opt) - 1; int ld = len - li - 3;// One for '{', '=' and '}' if (def == null || eq == 1) // (!def || eq == opt+1) { def = opt.Substring(eq + 1); //def=eq+1; deflen = ld; } if (ls == li && opt.Substring(1).StartsWith(stat+"=")) // (stat.IndexOf(opt.Substring(1), li) > -1)) //(ls == li && !strncmp(stat, opt + 1, li)) { match = opt.Substring(eq + 1, ld);// match = eq + 1; matchlen = ld; } opt = opt.Substring(len); //opt += len;// point to the next piece lenopt -= len; } // if match process option - or process default if (match == null) //(!match) { match = def.Substring(0, deflen); matchlen = deflen; } return ProcessRO(match, multiRtnVal); //process(match, matchlen); } private string ProcessBrace(string str, int l, ref bool nfnd, bool multiRtnVal) { string rtnstr = ""; int nxt = NextDelimiter("{=", str); //nextDelimiter("{=", str, l); if (nxt == -1) // no delimiter found { // VarUse //strList *found=vl->lookFor(str,l); bool found = DictROVar.ContainsKey(str); if (found) rtnstr = DictROVar[str]; //add(new seVarUse(found)); else nfnd = true; } else { if (str[nxt] == '{') { // conditonal or menu if (nxt == 0) // if (nxt == str) { // menu // TODO: implement Menu logic //ml->process(str, l, vl); //add(new seMenuUse(ml)); //lstRoValues.Add(ProcessRO(str.Substring(0,l), true)); ProcessMultiReturnValues(str, l); } else { // conditional rtnstr = ProcessConditional(str, str.Substring(nxt), nxt, str.Length - nxt - 1, multiRtnVal);//processCondition(str, nxt, (int)(nxt - str), l - (int)(nxt - str)); } } else { // must be variable definiton //vl->add(str, nxt+1, (int)(nxt-str), (l - (int)(nxt-str))-1, ml); // 'l' is the lenght up to the matching brace of the variable definition string tmpval = ProcessRO(str.Substring(nxt + 1, l - nxt - 1), multiRtnVal); if (tmpval.Equals(string.Empty)) tmpval = " "; // nothing assinged to variable if (!DictROVar.ContainsKey(str.Substring(0, nxt))) // need a try/catch here. { DictROVar.Add(str.Substring(0, nxt), tmpval); if(nxt == 1) multiRoValues.Add(str.Substring(0, nxt)); } else return null; if (multiRtnVal) rtnstr = tmpval; } } return rtnstr; } private Dictionary> _ValueLookupDictionary = null; public List GetRosByValue(string value) { if (_ValueLookupDictionary == null) BuildValueDictionary(); if (value == string.Empty) return null; if(_ValueLookupDictionary.ContainsKey(value.ToUpper())) return _ValueLookupDictionary[value.ToUpper()]; return null; } private void BuildValueDictionary() { _ValueLookupDictionary = new Dictionary>(); if (dicRos == null) ParseIntoDictionary(_ROFst != null ? _ROFst.ROLookup : _ROFstInfo.ROLookup); foreach (rochild child in dicRos.Values) { if (child.value != null) { string value = child.value.ToUpper(); if (_ValueLookupDictionary.ContainsKey(value)) _ValueLookupDictionary[value].Add(new roChild(child)); else { List children = new List(); children.Add(new roChild(child)); _ValueLookupDictionary.Add(value, children); } } } } private Dictionary _dicROAPID = null; public rochild? GetROChildByAccPageID(string accPageID, string spDefault, string igDefault) { rochild? child = GetRoChildByAccPagID(accPageID, spDefault, igDefault); if (child == null) { if(Regex.IsMatch(accPageID, @".*\.[A-Z]")) { string accpage = accPageID.Substring(0, accPageID.Length - 3); int index = accPageID.Substring(accPageID.Length - 2, 1)[0] - 'A'; child = GetRoChildByAccPagID(accpage, spDefault, igDefault); if (child == null) return null; if (((rochild)child).children != null && ((rochild)child).children.Length > 0 && ((rochild)child).children.Length > index) return ((rochild)child).children[index]; } return null; } if (((rochild)child).children != null && ((rochild)child).children.Length > 0) return ((rochild)child).children[0]; return (rochild)child; } public string GetROValueByAccPagID(string accPageID, string spDefault, string igDefault) { rochild? child = GetROChildByAccPageID(accPageID, spDefault, igDefault); if (child == null) return null; return ((rochild)child).value; } public int? GetROTypeByAccPagID(string accPageID, string spDefault, string igDefault) { rochild? child = GetROChildByAccPageID(accPageID, spDefault, igDefault); if (child == null) return null; return ((rochild)child).type; } public string GetROIDByAccPagID(string accPageID, string spDefault, string igDefault) { rochild? child = GetROChildByAccPageID(accPageID, spDefault, igDefault); if (child == null) return null; return ((rochild)child).roid; } public rochild? GetRoChildByAccPagID(string accPageID, string spDefault, string igDefault) { if (_dicROAPID == null) BuildROAPIDDictionary(); accPageID = accPageID.Replace("".ToCharArray()); // String < and > if (_dicROAPID.ContainsKey(accPageID)) return _dicROAPID[accPageID]; return null; } private void BuildROAPIDDictionary() { if (dicRos == null) ParseIntoDictionary(_ROFst != null ? _ROFst.ROLookup : _ROFstInfo.ROLookup); _dicROAPID = new Dictionary(); foreach (rodbi dbi in myHdr.myDbs) { if (dbi.children != null) BuildROAPIDDictionary(dbi.dbiAP, dbi.children); } } private void BuildROAPIDDictionary(string prefix, rochild[] children) { foreach (rochild child in children) { if (child.appid != null && child.appid != "" && child.ID != 0) { string key = string.Format("{0}-{1}", prefix, child.appid); if (!_dicROAPID.ContainsKey(key)) _dicROAPID.Add(key, child); } if (child.children != null) BuildROAPIDDictionary(prefix, child.children); } } private void ProcessMultiReturnValues(string str, int len) { if (str.Contains("{A={EQ}}")) // .StartsWith("{EQ=}")) Console.WriteLine("jcb"); string tstr = str.Substring(0, len); while (tstr.Length > 0) { int idx = MatchingBrace(tstr); string tmpVal = ProcessRO(tstr.Substring(0, idx + 1), true); if (tmpVal != null) lstRoValues.Add(tmpVal); // duplicates get returned as null tstr = tstr.Substring(idx + 1); } } private int MatchingBrace(string str) { int level = 1; int idx = 0; // the while will skip the first position (the first brace) while (level > 0 && idx++ < str.Length) { switch (str[idx]) { case '{': level++; break; case '}': level--; break; } } if (level != 0) idx = -1; // didn't find matching brace return idx; //length including end brace } private int NextDelimiter(string delim, string str) { int idx; idx = str.IndexOfAny(delim.ToCharArray()); return idx; } public List GetRoChildrenByType(int type) { List children = new List(); AddRoChildByType(children, type); return children; } private void AddRoChildByType(List children, int type) { foreach (rodbi dbi in myHdr.myDbs) { if (dbi.children != null) AddRoChildByType(dbi.children,children,type); } } private void AddRoChildByType(rochild[] roChildren, List children, int type) { foreach (rochild child in roChildren) { if (child.type == type && child.value != null) children.Add(child); if (child.children != null) AddRoChildByType(child.children,children,type); } } #endregion #region FortranFormat public static string ConvertFortranFormatToScienctificNotation(string str) { // ([+-]?|\\u8209\?) either an optional single character Plus (+) or Minus (-) or non-breaking dash (\u8209?) // ([0-9]+) a group of at least one digits // [.] a decimal point // ([0-9]*?) a group of zero or more digits // 0*E optional zeros (spare zeros) followed // ([+-]?|\\u8209\?) either an optional single character Plus (+) or Minus (-) or non-breaking dash (\u8209?) // ([0-9]+) a group of at least one digits string retval = Regex.Replace(str, @"([+-]?|\\u8209\?)([0-9]+)[.]([0-9]*?)0*E([+-]?|\\u8209\?)([0-9]+)", new MatchEvaluator(FixFortranNumber)); // don't convert # and ~ to super/subscripts, this is a DOS holdout and is done only for non-procedure step sections //retval = Regex.Replace(retval, "[#](.*?)[#]", "\\up2 $1\\up0 ");// DOS Superscript //retval = Regex.Replace(retval, "[~](.*?)[~]", "\\dn2 $1\\up0 ");// DOS Subscript return retval; } private static string FixFortranNumber(Match match) { StringBuilder sb = new StringBuilder(match.Groups[1].Value.Replace("-",@"\u8209?")); if (match.Groups[3].Length == 0) // Nothing to the right of the decimal if (match.Groups[2].Value != "1") // Other than "1", multiply it times 10 raised to a power sb.Append(match.Groups[2].Value + "x10"); else // The number is simply 1 so it can be ignored and 10 can be raised to a power sb.Append("10"); else // A number with a decimal point sb.Append(match.Groups[2].Value + "." + match.Groups[3].Value + "x10"); // Add the exponent as superscript return sb.ToString() + "\\up2 " + match.Groups[4].Value.Replace("-",@"\u8209?") + match.Groups[5].Value + "\\up0 "; } #endregion } [Flags] public enum E_ROValueType : uint { All = 0, Text = 1, Table = 2, Graph = 4, Image = 8, Video = 16, Hologram = 32 } }