using System; using System.Collections.Generic; using System.Text; using System.Windows.Forms; using System.Text.RegularExpressions; using System.Drawing; using VEPROMS.CSLA.Library; using Volian.Base.Library; namespace Volian.Controls.Library { public class DisplayText { private static readonly log4net.ILog _MyLog = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); #region Properties private E_FieldToEdit _FieldToEdit; public E_FieldToEdit FieldToEdit { get { return _FieldToEdit; } set { _FieldToEdit = value; } } private ItemInfo _MyItemInfo; private string InfoText { get { switch (FieldToEdit) { case E_FieldToEdit.StepText: case E_FieldToEdit.Text: return _MyItemInfo.MyContent.Text; break; case E_FieldToEdit.Number: return _MyItemInfo.MyContent.Number; break; } return string.Empty; } } private Item _MyItem; private string EditText { get { switch (FieldToEdit) { case E_FieldToEdit.StepText: case E_FieldToEdit.Text: return _MyItem.MyContent.Text; break; case E_FieldToEdit.Number: return _MyItem.MyContent.Number; break; } return string.Empty; } set { switch (FieldToEdit) { case E_FieldToEdit.StepText: case E_FieldToEdit.Text: _MyItem.MyContent.Text = value; _MyItem.MyContent.UserID = Volian.Base.Library.VlnSettings.UserID; _MyItem.MyContent.DTS = DateTime.Now; break; case E_FieldToEdit.Number: _MyItem.MyContent.Number = value; _MyItem.MyContent.UserID = Volian.Base.Library.VlnSettings.UserID; _MyItem.MyContent.DTS = DateTime.Now; break; default: break; } } } // list of 'pieces of text' for this item. Pieces include symbols, ros, // transitions & plain text. private List _DisplayTextElementList; public List DisplayTextElementList { get { return _DisplayTextElementList; } set { _DisplayTextElementList = value; } } // dictionary for the font table for this item. Note that this may // go away (it is not really used). private Dictionary _dicRtfFontTable; public Dictionary dicRtfFontTable { get { return _dicRtfFontTable; } set { _dicRtfFontTable = value; } } private VE_Font _textFont; // Font from format for this item public VE_Font TextFont { get { return _textFont; } set { _textFont = value; } } private bool PrintingSmartTemplate = false; public string StartText; public string OriginalText; // compare for save to see if change for links. private FormatInfo _MyFormat; #endregion #region Constructors /// /// DisplayText constructor: /// Creates a DisplayText object that converts the database text into rtf text /// Arguments are: /// ItemInfo itemInfo - the item whose text will be resolved /// E_EditPrintMode ep_mode - edit or print. /// E_ViewMode vw_mode - view or edit. /// bool noEdit - flags whether to edit or not (used to set data in /// rtb as resolved replacewords for non-active rtb. /// E_FieldToEdit fieldToEdit - identifies the field to edit (number or text) /// bool colorLinks - whether to add color to links /// public DisplayText(ItemInfo itemInfo, E_EditPrintMode epMode, E_ViewMode vwMode, bool noEdit,E_FieldToEdit fieldToEdit, bool colorLinks, string prefix, string suffix) { int profileDepth = ProfileTimer.Push(">>>> DisplayText"); _FieldToEdit = fieldToEdit; _MyItemInfo = itemInfo; OriginalText = InfoText; if (OriginalText.Contains("Prerequisite") && epMode == E_EditPrintMode.Print) OriginalText = Regex.Replace(OriginalText, @"\\{Prerequisite Step: .*?\\}", ""); TextFont = itemInfo.GetItemFont();//GetItemFont(); // if in print mode, and this is the HLS of a smart template (checklist formats) see if the hls // splits across 2 lines. if (itemInfo.IsStep && itemInfo.FormatStepData.UseSmartTemplate && epMode == E_EditPrintMode.Print) { int hlslen = (int)(itemInfo.FormatStepData.StepPrintData.HLSLength ?? 66); List titleLines = Volian.Base.Library.RtfTools.SplitText(OriginalText, hlslen); if (titleLines.Count > 1) { string tmporig = titleLines[0]; for (int ix = 1; ix < titleLines.Count; ix++) tmporig = tmporig + @"\par " + titleLines[ix]; OriginalText = tmporig; } } string text = prefix + OriginalText + suffix; _MyFormat = itemInfo.ActiveFormat; bool tableShouldBeOutlined = false; //(epMode == E_EditPrintMode.Print || vwMode == E_ViewMode.View || noEdit) && //(_FieldToEdit == E_FieldToEdit.StepText || _FieldToEdit == E_FieldToEdit.Text) && //(!itemInfo.IsSection && !itemInfo.IsProcedure) && (itemInfo.IsTable || itemInfo.IsFigure); bool wordsShouldBeReplaced = epMode == E_EditPrintMode.Print || vwMode == E_ViewMode.View || noEdit; if (_MyFormat == null) Console.WriteLine(this._MyItemInfo.MyItemInfoUnique); bool numbersShouldBeFormated = (!_MyFormat.PlantFormat.FormatData.SectData.StepSectionData.FortranFormatNumbers && (epMode == E_EditPrintMode.Print || vwMode == E_ViewMode.View || noEdit)); int typ = ((int)itemInfo.MyContent.Type) % 10000; bool tableHasBorder = tableShouldBeOutlined ? itemInfo.ActiveFormat.PlantFormat.FormatData.StepDataList[typ].Type.IndexOf(@"Borderless") < 0 : false; bool ROsShouldBeAdjusted = wordsShouldBeReplaced; // same logical value bool underlineAfterDashSpace = (itemInfo.FormatStepData == null) ? false : itemInfo.FormatStepData.UnderlineAfterDashSpace; if (epMode == E_EditPrintMode.Print && _MyItemInfo.IsStep) { if (_MyItemInfo.FormatStepData.UseSmartTemplate) { // Add 2 spaces before and 1 after if there is prefix so that wrapping in RTB accounts for vertical // lines (the 2 spaces after the first "\par " command and 1 space before 2nd "\par"). Tried other // combinations that did not work. if (_MyItemInfo.FormatStepData.Prefix != null && _MyItemInfo.FormatStepData.Prefix != "") text = !_MyItemInfo.FormatStepData.Font.FontIsProportional() ? ReplaceLinesWithUnicode(_MyItemInfo.FormatStepData.Prefix) + @"\par " + text + @"\par " : @"\par " + text + @"\par "; if (_MyItemInfo.FormatStepData.Suffix != null && _MyItemInfo.FormatStepData.Suffix != "") text = text + (!_MyItemInfo.FormatStepData.Font.FontIsProportional() ? ReplaceLinesWithUnicode(_MyItemInfo.FormatStepData.Suffix) : @"\par\par\par "); } } // Replace Hard Hyphens with normal hyphen so the PDF search for hyphens will work properly if (text.Contains(@"\u8209?") && epMode == E_EditPrintMode.Print) { // Handle RTF Tokens followed immediately by a hard hyphen text =Regex.Replace(text, @"(?<=\\[^\\?' \r\n\t]+)\\u8209\?", " -"); text = text.Replace(@"\u8209?", "-"); } _MyStaticItemInfo = _MyItemInfo; text = CreateRtf(colorLinks, text, tableShouldBeOutlined, wordsShouldBeReplaced, numbersShouldBeFormated, tableHasBorder, ROsShouldBeAdjusted, underlineAfterDashSpace, epMode); _MyStaticItemInfo = null; StartText = text; ProfileTimer.Pop(profileDepth); } private static ItemInfo _MyStaticItemInfo = null; // Used to report errors private string ReplaceLinesWithUnicode(string text) { text = text.Replace("\x2500", @"\u9472?"); // Horizontal text = text.Replace("\x2502", @"\u9474?"); // Vertical text = text.Replace("\x2514", @"\u9492?"); // Bottom Left Corner text = text.Replace("\x2518", @"\u9496?"); // Bottom Right Corner text = text.Replace("\x2534", @"\u9524?"); // Bottom Tee text = text.Replace("\x250c", @"\u9484?"); // Upper Left Corner text = text.Replace("\x251c", @"\u9500?"); // Left Tee text = text.Replace("\x2510", @"\u9488?"); // Upper Right Corner text = text.Replace("\x252c", @"\u9516?"); // Top Tee text = text.Replace("\x2524", @"\u9508?"); // Right Tee text = text.Replace("\x253c", @"\u9532?"); // Plus return text; } public DisplayText(string text, VE_Font vFont, bool colorLinks) { TextFont = vFont; StartText = CreateRtf(colorLinks, text, false, false, false, false, false, false, E_EditPrintMode.Edit); } public DisplayText(ItemInfo itemInfo, string text, bool colorLinks) { _FieldToEdit = E_FieldToEdit.Text; _MyItemInfo = itemInfo; OriginalText = text; TextFont = itemInfo.GetItemFont(); _MyFormat = itemInfo.ActiveFormat; bool wordsShouldBeReplaced = true; bool numbersShouldBeFormated = !_MyFormat.PlantFormat.FormatData.SectData.StepSectionData.FortranFormatNumbers; int typ = ((int)itemInfo.MyContent.Type) % 10000; bool ROsShouldBeAdjusted = wordsShouldBeReplaced; // same logical value bool underlineAfterDashSpace = (itemInfo.FormatStepData == null) ? false : itemInfo.FormatStepData.UnderlineAfterDashSpace; text = CreateRtf(colorLinks, text, false, wordsShouldBeReplaced, numbersShouldBeFormated, false, ROsShouldBeAdjusted, underlineAfterDashSpace,E_EditPrintMode.Edit); StartText = text; // Shearon Harris Tables are Bold if (itemInfo.IsTable && (TextFont.Style & E_Style.Bold) == E_Style.Bold) { // Strip out Bold OFF commands text = text.Replace(@"\b0 "," "); text = text.Replace(@"\b0", ""); // Insert a Bold ON command at the beginning of the printable text. StartText = Regex.Replace(text, @"(\\viewkind.*?)(?= |\\u[0-9]+?|\\'[0-9A-F])", @"$1\b"); } } private bool InLinkedText(string text, int idx) { MatchCollection mc = Regex.Matches(text, @"", RegexOptions.Singleline); if (mc.Count == 0) return false; foreach (Match m in mc) if (m.Index < idx && m.Index + m.Length > idx) return true; return (false); } private string CreateRtf(bool colorLinks, string text, bool tableShouldBeOutlined, bool wordsShouldBeReplaced, bool numbersShouldBeFormated, bool tableHasBorder, bool ROsShouldBeAdjusted, bool underlineAfterDashSpace, E_EditPrintMode epMode) { int profileDepth = ProfileTimer.Push(">>>> CreateRtf"); // Adjust RO display if (ROsShouldBeAdjusted) { try // Added try/catch because an unresolved RO Link was causing a failure. { text = DoROAdjustments(text); } catch (Exception ex) { if (_MyItemInfo != null) { _MyLog.ErrorFormat("<<< ERROR >>> Error doing DoROAdjustments\r\n==>'RO Adjustments Error',{0},'{1}','{2}','{3}'" , _MyItemInfo.ItemID, _MyItemInfo.MyDocVersion.MyFolder.Name, _MyItemInfo.ShortPath, ex.Message); } else _MyLog.Error("DisplayText.CreateRTF Error doing DoROAdjustments", ex); } } // if in print mode, view mode, or non-active richtextbox do replace words. Only if in // actual edit mode are replace words left as is. // But don't do ReplaceWords if the TurnOffReplaceWords format flag is set if (wordsShouldBeReplaced && !_MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.TurnOffReplaceWords) { int profileDepth1 = ProfileTimer.Push(">>>> DoReplaceWords2"); text = DoReplaceWords2(text); ProfileTimer.Pop(profileDepth1); } if (_MyItemInfo != null) { text = Regex.Replace(text, @"\", _MyItemInfo.MyDocVersion.DocVersionConfig.Unit_Number, RegexOptions.IgnoreCase); text = Regex.Replace(text, @"\<(U(-|\\u8209\?)ID)\>", _MyItemInfo.MyDocVersion.DocVersionConfig.Unit_ID, RegexOptions.IgnoreCase); text = Regex.Replace(text, @"\<(U(-|\\u8209\?)NAME)\>", _MyItemInfo.MyDocVersion.DocVersionConfig.Unit_Name, RegexOptions.IgnoreCase); text = Regex.Replace(text, @"\<(U(-|\\u8209\?)TEXT)\>", _MyItemInfo.MyDocVersion.DocVersionConfig.Unit_Text, RegexOptions.IgnoreCase); text = Regex.Replace(text, @"\<(U(-|\\u8209\?)NUMBER)\>", _MyItemInfo.MyDocVersion.DocVersionConfig.Unit_Number, RegexOptions.IgnoreCase); text = Regex.Replace(text, @"\<(U(-|\\u8209\?)OTHER ID)\>", _MyItemInfo.MyDocVersion.DocVersionConfig.Other_Unit_ID, RegexOptions.IgnoreCase); text = Regex.Replace(text, @"\<(U(-|\\u8209\?)OTHER NAME)\>", _MyItemInfo.MyDocVersion.DocVersionConfig.Other_Unit_Name, RegexOptions.IgnoreCase); text = Regex.Replace(text, @"\<(U(-|\\u8209\?)OTHER TEXT)\>", _MyItemInfo.MyDocVersion.DocVersionConfig.Other_Unit_Text, RegexOptions.IgnoreCase); text = Regex.Replace(text, @"\<(U(-|\\u8209\?)OTHER NUMBER)\>", _MyItemInfo.MyDocVersion.DocVersionConfig.Other_Unit_Number, RegexOptions.IgnoreCase); //text = DoSearchAndReplace(text, "", _MyItemInfo.MyDocVersion.DocVersionConfig.Unit_ID); text = text.Replace(@"", _MyItemInfo.MyDocVersion.DocVersionConfig.Unit_ProcedureSetID); //text = text.Replace("", _MyItemInfo.MyDocVersion.DocVersionConfig.Unit_Number); } // Adjust RO display if (ROsShouldBeAdjusted) text = DoTransitionAdjustments(text, _MyItemInfo.ActiveFormat.PlantFormat.FormatData.TransData.BoldTransition || (_MyItemInfo.ActiveFormat.PlantFormat.FormatData.TransData.BoldTransitionExceptHLS && !_MyItemInfo.IsHigh)); // add colors around links: if (colorLinks) text = DoColorLinks(text); //Console.WriteLine(text); // adjust formatting of exponents if (numbersShouldBeFormated) text = DoFortranFormat(text); // determine whether the table/figure should be outlined: if (tableShouldBeOutlined) { OutlineRTFTable myTable = new OutlineRTFTable(text, tableHasBorder); // if a table has internal line draw characters, we may have to do part of 'OutlineTable' // to convert dashes and vertical bars to line draw characters. if (tableHasBorder) myTable.OutlineTable(); text = myTable.Lines.ToString(); } // if we're working with a grid it won't go thru here. if (!text.StartsWith(@"{\rtf")) { // as a precaution, convert any \~ to \u160?. This is for Hard spaces. see the commentary in the // save portion of this code for an explanation. text = text.Replace(@"\~", @"\u160?"); text = text.Replace("\r\n", @"\line "); // replace a \r\n with a \line instead of a \par //if (text.IndexOf(@"\line") > -1) // MessageBox.Show("Found rtf line"); //text = text.Replace(@"\line", @"\par"); // we don't want to replace the \line part of bug fix B2015-140 // Now put symbol (for fixed fonts) or unicode font (proportional) around symbols // These fonts are VESymbFix & Arial Unicode MS respectively, and the font table // is actually defined in the StepRTB code. int indxsym = NextUnicode(text, 0);//text.IndexOf(@"\u"); while (indxsym != -1) { int incrindx = 3; if (text[indxsym + 2] != 'l') { text = text.Insert(indxsym, @"\f1 "); int indxendsym = text.IndexOfAny(@"\ ?".ToCharArray(), indxsym + 5); if (indxendsym == -1) // must be end of line: text = text.Insert(text.Length - 1, @"\f0 "); else { if (text[indxendsym] == '?') indxendsym++; text = text.Insert(indxendsym, @"\f0 "); // TODO: do I need a space?? } incrindx = 5; } indxsym = NextUnicode(text, indxsym + incrindx);//text.IndexOf(@"\u", indxsym + incrindx); } } if (underlineAfterDashSpace) { // Bug fix: B2015-110 - currently used in Byron and Braidwood formats // for the screen we need to look for the unicode dash // for printing we need to look for the keyboard dash character MatchCollection mc = Regex.Matches(text,((epMode == E_EditPrintMode.Edit)? @"\\u8209\?\\f[0-9]+ " : "- ")); if (mc.Count > 0) { Match m = mc[0]; if (!InLinkedText(text, m.Index)) { string str1 = text.Substring(0, m.Index + m.Length); string str2 = text.Substring(m.Index + m.Length); string str3 = ""; int iTerm = FindUnderlineTerminator(str2); if (iTerm >= 0) { str3 = str2.Substring(iTerm); str2 = str2.Substring(0, iTerm); } str2 = str2.Replace(@"\ulnone ", ""); str2 = str2.Replace(@"\ulnone", ""); str2 = str2.Replace(@"\ul ", ""); str2 = str2.Replace(@"\ul", ""); text = str1 + @"\ul " + str2 + @"\ulnone " + str3; } } } text = FixDiffUnitROReplaceWords(text); ProfileTimer.Pop(profileDepth); return text; } private string FixDiffUnitROReplaceWords(string text) { if (_MyFormat == null) return text; ReplaceStrList rsl = _MyFormat.PlantFormat.FormatData.SectData.ReplaceStrList; // The only way to get an 'empty' list is to have one 'dummy' replacestr, i.e. that has ReplaceWord as an empty string. If the // ReplaceStrData xml node is empty, it does the inheritance and gets the 'base' format's list. if (rsl.Count == 1 && (rsl[0].ReplaceWord == null || rsl[0].ReplaceWord == "")) return text; // Loop through text looking for words to be replaced List partialReplaceList = new List(); foreach (ReplaceStr rs in rsl) { if (rs.ReplaceWord.Contains("{RO}")) { //if (_MyItemInfo.InList(34770,34771,34782,34882,34886,34916,34891,35121,36361)) // Console.WriteLine("FixDiffUnitROReplaceWords jcb"); string oldvalue = text; string replaceWord = rs.ReplaceWord; string replaceWord2 = Regex.Replace( replaceWord,@"(\{RO\})([0-9,]+)(\{RO\})",@"\\v 0) { Match mm = Regex.Match(text, replaceWord2, RegexOptions.IgnoreCase); return matches[0]; } return null; } private int FindUnderlineTerminator(string text) { int idx = -1; UnderlineTerminateList utl = _MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.UnderlineTerminateList; foreach (UnderlineTerminate ut in utl) { MatchCollection mc = Regex.Matches(text, "(? 0) { Match m = mc[mc.Count - 1]; if (idx < 0 || idx > m.Index) idx = m.Index; } } return idx; } private string DoSearchAndReplace(string text, string find, string replace) { return text.Replace(find, replace); } private static string DoColorLinks(string text) { string origtext = text; text = Regex.Replace(text, @"( -1) { text = text.Insert(indxend, @"\cf0"); indxcf = text.IndexOf(@"\v0\cf1", indxend); } else { indxcf = -1; _MyLog.WarnFormat("DisplayText.DoColorLinks Failed\r\norgitext:'{0}'\r\ntext'{1}'", origtext, text); } } } catch (Exception ex) { _MyLog.WarnFormat("DisplayText.DoColorLinks Failed\r\norgitext:'{0}'\r\ntext'{1}'", origtext, text); } return text; } private int NextUnicode(string text, int offset) { // Skip Hard Spaces Match m = Regex.Match(text.Substring(offset), @"\\u[0-9a-fA-F]"); while(m.Success && text.Substring(offset+m.Index).StartsWith(@"\u160")) { offset += m.Index + 5; m = Regex.Match(text.Substring(offset), @"\\u[0-9a-fA-F]"); } if (m.Success) return m.Index + offset; return -1; } private string DoROAdjustments(string text) { Regex regRefObj = new Regex(@"\#Link\:ReferencedObject:([0-9]*|) ([0-9a-zA-Z]*) ([0-9]*)", RegexOptions.Singleline); string strippedText = StaticStripRtfCommands(text); // (\\[^v \\]+)* --> look for any rtf commands (first part of lookFor) // \\v0 --> end of comment // (\\[^v \\]+)* --> more rtf commands ended by a space // (.*?) --> smallest anything to that matches this based on what's next // (\\[^v' \\]+)* --> look for rtf commands but exclude \' before the \v // \\v(\\[^v \\]+)* --> look for rtf commands after the \v // if it turns out that if ro's have any embedded unicode characters this needs expanded, such as /u8209? (hard hyphen) string lookFor = string.Format(@""); MatchCollection matches = Regex.Matches(text, lookFor); string prevValue = null; for (int i = matches.Count - 1; i >= 0; i--) { Match m = matches[i]; if (m != null && m.Groups.Count > 7 && m.Groups[7].ToString() == "ReferencedObject") { // if previous processed (next ro) was found, then see if it has an 'and' between it and the previous //if (prevValue != null) //{ // int endIndx = m.Index + m.Length; // string tr = text.Substring(endIndx).Replace(@"\v0","").TrimStart(); // if (!tr.ToUpper().StartsWith("AND")) prevValue = null; //} int myIndex = m.Groups[4].Index; int myLength = m.Groups[4].Length; if (m.Groups[3].Value != " ") { myIndex = m.Groups[3].Index; myLength += m.Groups[3].Length; } string gg = text.Substring(myIndex, myLength); //System.Text.RegularExpressions.Group g = m.Groups[3]; string beforeRO = StaticStripRtfCommands(text.Substring(0, myIndex)); string afterRO = StaticStripRtfCommands(text.Substring(myIndex + myLength)); Match myMatch = regRefObj.Match(m.ToString()); if(m.ToString().ToUpper().Contains("")) _MyLog.WarnFormat("Unprocessed RO in {0},({1})",_MyItemInfo.ShortPath,gg); int dbid = System.Convert.ToInt32(myMatch.Groups[2].Value.Substring(0, 4), 16); int rodbid = int.Parse(myMatch.Groups[3].Value); ROFstInfo myROFst = _MyItemInfo.MyDocVersion.GetROFst(rodbid); bool isSetpoint=myROFst.IsSetpointDB(dbid, _MyItemInfo.MyDocVersion); string newvalue1 = DoROFormatFlags(gg, beforeRO, afterRO, isSetpoint); string newvalue = RemoveMultipleUnits(prevValue, newvalue1); if (!_MyItemInfo.ActiveFormat.PlantFormat.FormatData.ROData.AllUnits) prevValue = newvalue1; newvalue = DoROReplaceWords(_MyFormat.PlantFormat.FormatData.SectData.ReplaceStrList, newvalue, _MyItemInfo.IsHigh); if (isSetpoint) newvalue = ReplaceSpaceWithHardspace(newvalue); if (gg != newvalue) text = text.Substring(0, myIndex) + newvalue + text.Substring(myIndex + myLength); } } return text; } private string DoROReplaceWords(ReplaceStrList replaceStrList, string oldvalue, bool isHigh) { int profileDepth = ProfileTimer.Push(">>>> DoROReplaceWords"); string newvalue = oldvalue; foreach (ReplaceStr rs in replaceStrList) { if (((rs.Flag & E_ReplaceFlags.Setpoint) > 0) || (isHigh && (rs.Flag & E_ReplaceFlags.HLSSetpnt) > 0)) { try { // Use regular expression to assure that the ReplaceWord is not part of another word // For VEPROMS_CAL E-0 Step 23 (Reset SI) the word "after" was being changed to "aFTer" newvalue = Regex.Replace(newvalue, @"(?<=\W|^)" + rs.ReplaceWord + @"(?=\W|$)", rs.ReplaceWith); //newvalue = newvalue.Replace(rs.ReplaceWord, rs.ReplaceWith); } catch (Exception ex) { _MyLog.Warn("Problem with regular expression", ex); } } } //if (oldvalue != newvalue) // Console.WriteLine("\"{0}\"\r\n\"{1}\"",oldvalue,newvalue); ProfileTimer.Pop(profileDepth); return newvalue; } // Replace spaces with hardspaces, but DO NOT replace the end of an Rtf Command with a hardspace private string ReplaceSpaceWithHardspace(string newvalue) { string oldvalue = newvalue; int spindx = newvalue.IndexOf(" "); int lstindx = -1; while (spindx >= 0) { if (!EndsRtfCommand(newvalue, spindx, lstindx)) { newvalue = newvalue.Remove(spindx, 1); newvalue = newvalue.Insert(spindx, @"\u160?"); } lstindx = spindx; spindx = (spindx + 1 >= newvalue.Length)?spindx = -1: newvalue.IndexOf(" ", spindx+1); } return newvalue; } private bool EndsRtfCommand(string str, int spindx, int previndx) { // get text from last space to current, or from beginning of string to current: int start = previndx < 0 ? 0 : previndx+1; string substring = str.Substring(start, spindx-start); if (substring.Contains(@"\")) { // is space ending an rtf command. int startCmd = substring.LastIndexOf(@"\"); string Cmd = substring.Substring(startCmd); char tst = Cmd[1]; // consider rtf commands up/dn/b/ul/i if (tst == 'u' || tst == 'd' || tst == 'b' || tst == 'u' || tst == 'i') return true; } return false; } private string DoTransitionAdjustments(string text, bool boldTran) { int profileDepth = ProfileTimer.Push(">>>> DoTransitionAdjustments"); bool undtran = _MyItemInfo.ActiveFormat.PlantFormat.FormatData.TransData.Underline; string strippedText = StaticStripRtfCommands(text); string lookFor = string.Format(@""); MatchCollection matches = Regex.Matches(text, lookFor); if (matches.Count == 0) { ProfileTimer.Pop(profileDepth); return text; } string retstr = text; for (int i = matches.Count - 1; i >= 0; i--) { Match m = matches[i]; // if this transition text already has a hard space, don't add another. if (m.Groups[4].Value.Contains("\xA0")) continue; // if the transition text does not start with a digit, don't add the hardspace. //if (!Char.IsDigit(m.Groups[3].Value[0])) continue; if (m != null && m.Groups.Count > 8 && m.Groups[7].ToString().StartsWith("Transition")) { if (m.Groups[8].Value != "") // && StepTransition(int.Parse(m.Groups[7].Value))) { int myIndex = m.Groups[4].Index; int myLength = m.Groups[4].Length; if (m.Groups[3].Value != " ") { myIndex = m.Groups[3].Index; myLength += m.Groups[3].Length; } string newvalue = text.Substring(myIndex, myLength); //System.Text.RegularExpressions.Group g = m.Groups[3]; string beforeTran = retstr.Substring(0, myIndex); string afterTran = retstr.Substring(myIndex + myLength); // if replacing text in the 'beforeTran' string, then do it here, // i.e. there is a format flag 'BeforeTrans' that bolds text before the transition // (in wst formats). beforeTran = DoBeforeTransFlagSupport(beforeTran, _MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.ReplaceStrList); //string newvalue = g.ToString(); // if this is a 'step transition' type, i.e. includes a step number, in addition to other replacements, // we want to change a space to a hardspace. if (StepTransition(int.Parse(m.Groups[8].Value))) { int indexLastSpace = newvalue.LastIndexOf(' '); if (indexLastSpace >= 0) // Use a "\x1" as a token to replace later. Insert the unicode char, whose length is // more than 1 character was throwing of the regexp Matches index, so that the resulting // string may have been incorrect. retstr = beforeTran + (boldTran ? @"\b " : null) + (undtran ? @"\ul " : null) + newvalue.Substring(0, indexLastSpace) + "\x1" + newvalue.Substring(indexLastSpace + 1) + (undtran ? @"\ulnone " : null) + (boldTran ? @"\b0" : null) + afterTran; else if (beforeTran.EndsWith(" ")) retstr = ReplaceLastSpaceWithHardSpace(beforeTran) + (boldTran ? @"\b " : null) + (undtran ? @"\ul " : null) + newvalue + (undtran? @"\ulnone ":null) + (boldTran ? @"\b0" : null) + afterTran; else Console.Write("");// Don't know where to put the Hard Space } else if (boldTran) { retstr = beforeTran + @"\b " + newvalue + @"\b0" + afterTran; } } } } ProfileTimer.Pop(profileDepth); return retstr.Replace("\x1", @"\u160?"); } private string DoBeforeTransFlagSupport(string beforeTran, ReplaceStrList replaceStrList) { foreach (ReplaceStr repstr in replaceStrList) { if ((repstr.Flag & E_ReplaceFlags.BeforeTrans) > 0) { // the beforeTran string ends with the string that starts the transition comment, i.e. // '\\v -1) { string findit = beforeTran.Substring(0, beforeTran.LastIndexOf(@"\v 0 && str[ind - 1] != ' ') { if (ind > 5 && str.Substring(0, ind).EndsWith(@"\u160?") || str.Substring(0, ind).ToLower().EndsWith(@"\'a0")) return str;//Already has a Hard Space ind = str.LastIndexOf(@"\", ind - 1); } // If the previous character is a comma or a space then don't add a Hard Space if (ind > 1 && (str[ind - 2] == ',' || str[ind - 2] == ' ')) return str; if (ind <= 0) return str; // replace with a 'token' "\x1" instead of a hardspace unicode char. When using a hardspace unicode // char the string length/contents was thrown off so that the calling method's processing was off // in terms of regexp matches in string. return str.Substring(0, ind - 1) + "\x1" + str.Substring(ind); } private bool StepTransition(int TransId) { if (_MyItemInfo == null) return false; _MyItemInfo.MyContent.RefreshContentTransitions(); foreach (TransitionInfo trans in _MyItemInfo.MyContent.ContentTransitions) if (trans.TransitionID == TransId) return trans.MyItemToID.IsStep; return false; } private string DoFortranFormat(string text) { if (text.IndexOf(@".E") < 0) return text; // Look for text as n.Ey, where n can be null or a number, and y can be // positive or negative. This translates into nx10x10y where y is // superscripted. For example, .E3 -> x103 where 3 is superscripted // and 10.E5 -> 10x10-5 where 5 is superscripted string pat = @"(\d*).E([+-]*\d+)"; string retstr = text; // for each one that needs translated: foreach (Match m in Regex.Matches(text, pat)) { string fnum = m.Groups[1].Value; string supnum = m.Groups[2].Value; string newstr = string.Format(@"{0}x10\up2 {1}\up0 ", fnum, supnum); retstr = retstr.Replace(m.Value, newstr); } return retstr; } #endregion #region SaveData public bool Save(RichTextBox rtb) { //int savSelStart = rtb.SelectionStart; try { //FormatInfo formatInfo = _MyItemInfo.ActiveFormat; using (_MyItem = _MyItemInfo.Get()) { // The following was added to support transitions to un-numbered steps if (_MyItemInfo.NewTransToUnNumberedItem && rtb.Text.Contains("")) { ItemAnnotation ia = _MyItem.ItemAnnotations.Add(AnnotationType.GetByName("Verification Required")); ia.SearchText = "Transition to Un-Numbered Step"; _MyItemInfo.NewTransToUnNumberedItem = false; } // check for different text, i.e. text from this itm doesn't match // original text, a change occurred in database, but not from this user. if (OriginalText != EditText) { Console.WriteLine("Save Failed because text changed outside of this edit session."); return false; } string modtext = RtfToDbText(rtb.Rtf).Replace("", "\\\\"); // if there are links, we'll need to do extra processing to see if // there were additions, deletions or modifications. bool haslinks = ((modtext.IndexOf(@" -1) || (OriginalText != null && OriginalText != "" && OriginalText.IndexOf(@" -1)); if (haslinks) { // Get all links in original list RtfToDisplayTextElements(OriginalText); List origList = GetLinkList(DisplayTextElementList); // now get new text into displaytext elements for comparison for links: RtfToDisplayTextElements(modtext); // Compare ro/transition lists and delete or add any to the item for any ros/transitions that have been // added/deleted or modified. ProcessRoTranChanges(_MyItem, origList); EditText = DteToString(); // if new transitions/ros, we need to 'fix' the string in the embedded link to contain the // transition or usage record. Dictionary ctReplacements = BuildCtReplacements(_MyItem.MyContent.ContentTransitions); Dictionary roUsgReplacements = BuildRoUsgReplacements(_MyItem.MyContent.ContentRoUsages); _MyItem.DTS = DateTime.Now; _MyItem.UserID = Volian.Base.Library.VlnSettings.UserID; // Do the Save once rather than multiple times _MyItem.Save(); if (ctReplacements.Count > 0) { EditText = FixCtReplacements(EditText, ctReplacements); // Replace Transition Text foreach (ContentTransition ct in ctReplacements.Values) using (TransitionInfo tran = TransitionInfo.Get(ct.TransitionID)) _MyItem.MyContent.FixTransitionText(tran); _MyItem.Save(); } if (roUsgReplacements.Count > 0) { EditText = FixRoUsgReplacements(EditText, roUsgReplacements); _MyItem.Save(); } modtext = EditText; } else { EditText = modtext; foreach (Csla.Validation.BrokenRule br in _MyItem.MyContent.BrokenRulesCollection) { Console.WriteLine("{0} - {1}", br.Property, br.Description); } // Don't update the DTS or User for Text Changes //_MyItem.DTS = DateTime.Now; //_MyItem.UserID = Volian.Base.Library.VlnSettings.UserID; _MyItem.Save(); } _MyItem = null; OriginalText = modtext; } if (!_MyItemInfo.IsStep) { _MyItemInfo.UpdateTransitionText(); _MyItemInfo.UpdateROText(); } } catch (Exception ex) { Console.WriteLine("DisplayText Save Failed with error: {0} - {1}\r\n{2}", ex.GetType().Name, ex.Message, ex.StackTrace); return false; } //rtb.SelectionStart = savSelStart; return true; } private string DteToString() { StringBuilder sret = new StringBuilder(); foreach (displayTextElement vte in DisplayTextElementList) { if (vte.Type == E_TextElementType.Text || vte.Type == E_TextElementType.Symbol) sret.Append(vte.Text); else { displayLinkElement dle = vte as displayLinkElement; if (vte != null) sret.Append(dle.TextAndLink); } } string modtext = sret.ToString(); return modtext; } private string FixRoUsgReplacements(string p, Dictionary roUsgReplacements) { foreach (int oldid in roUsgReplacements.Keys) { p = p.Replace(string.Format("", oldid), roUsgReplacements[oldid].ROUsageID.ToString()); } return p; } private Dictionary BuildRoUsgReplacements(ContentRoUsages contentRoUsages) { Dictionary retval = new Dictionary(); foreach (ContentRoUsage rou in contentRoUsages) { if (rou.ROUsageID < 0) retval.Add(rou.ROUsageID, rou); } return retval; } private string FixCtReplacements(string p, Dictionary ctReplacements) { foreach (int oldid in ctReplacements.Keys) { p = p.Replace(string.Format("",oldid),ctReplacements[oldid].TransitionID.ToString()); } return p; } private Dictionary BuildCtReplacements(ContentTransitions contentTransitions) { Dictionary retval = new Dictionary(); foreach (ContentTransition ct in contentTransitions) { if (ct.TransitionID < 0) retval.Add(ct.TransitionID, ct); } return retval; } private void ProcessRoTranChanges(Item itm, List origList) { // go through list. Note that only linked items are in the origList. // 1) delete any that are in origList but not in the DisplayTextElementList // (that represents the current text & links) // 2) add any that are only in DisplayTextElementList // 3) delete/add for modify? // delete first - if in original, but not in current list, delete the one // in the original list. foreach (displayLinkElement odte in origList) { bool found = false; foreach (displayTextElement dte in DisplayTextElementList) { if (dte.Type == odte.Type) { displayLinkElement l_dte = (displayLinkElement)dte; if (odte.Link == l_dte.Link) { found = true; break; } } } // remove the link element from the item. if (!found) { // Get record id for ro or trans and then find the associated ro or transition // in the item's list. remove it. int recid = -1; if (odte.Type != E_TextElementType.ReferencedObject) { int sp = odte.Link.IndexOf(" ") + 1; // get past tran type string srecid = odte.Link.Substring(sp, odte.Link.IndexOf(" ", sp) - sp); recid = System.Convert.ToInt32(srecid); foreach (ContentTransition ct in itm.MyContent.ContentTransitions) { if (ct.TransitionID == recid) { itm.MyContent.ContentTransitions.Remove(ct); break; } } } else { int sp = odte.Link.IndexOf(" "); //rousageid starts after "ReferencedObject:", i.e. index in link of 17 string srecid = odte.Link.Substring(17, sp-17); recid = System.Convert.ToInt32(srecid); foreach (ContentRoUsage cr in itm.MyContent.ContentRoUsages) { if (cr.ROUsageID == recid) { itm.MyContent.ContentRoUsages.Remove(cr); break; } } } } } // now do insert, i.e. in new list, but not in old. foreach (displayTextElement dte in DisplayTextElementList) { bool found = false; if (dte.Type == E_TextElementType.ReferencedObject || dte.Type == E_TextElementType.Transition || dte.Type == E_TextElementType.TransitionRange) { foreach (displayLinkElement odte in origList) { if (dte.Type == odte.Type) { // if the link is the same, it exists, so no action is required. displayLinkElement l_dte = (displayLinkElement)dte; if (odte.Link == l_dte.Link) { found = true; break; } } } // Insert the link (ro or transition) to the item if (!found) { if (dte.Type == E_TextElementType.ReferencedObject) // do ro { displayLinkElement l_dte = (displayLinkElement)dte; Match m = Regex.Match(l_dte.Link, "([A-Za-z]*):(.*)"); string linkstr = m.Groups[2].Value; string[] roparts = linkstr.Split(" ".ToCharArray()); ContentRoUsage rousg = null; using (RODb rodb = RODb.GetJustRoDb(Convert.ToInt32(roparts[2]))) { rousg = itm.MyContent.ContentRoUsages.Add(roparts[1], rodb); } l_dte.Link = l_dte.Link.Replace("", string.Format("", rousg.ROUsageID)); l_dte.TextAndLink = l_dte.TextAndLink.Replace("", string.Format("", rousg.ROUsageID)); break; } else if (dte.Type == E_TextElementType.TransitionRange || dte.Type == E_TextElementType.Transition) { displayLinkElement l_dte = (displayLinkElement)dte; Match m = Regex.Match(l_dte.Link, "([A-Za-z]*):(.*)"); string linkstr = m.Groups[2].Value; string[] tparts = linkstr.Split(" ".ToCharArray()); int type = System.Convert.ToInt32(tparts[0]); int tr1 = System.Convert.ToInt32(tparts[2]); // tparts[2] is token for tranid int tr2 = tr1; if(tparts.Length > 3) tr2 = System.Convert.ToInt32(tparts[3]); // tparts[3] is token for rangeid bool dispose1 = false; Item itm1 = null; bool dispose2 = false; Item itm2 = null; if (itm.ItemID == tr1) itm1 = itm; // a transition that points to itself should not dispose else { dispose1 = true; itm1 = Item.Get(tr1); } if (itm.ItemID == tr2) itm2 = itm; // a transition that points to itself should not dispose else if (tr1 == tr2) itm2 = itm1; // if both destinations are the same only dispose the first one else { dispose2 = true; itm2 = Item.Get(tr2); } ContentTransition ct = itm.MyContent.ContentTransitions.Add(itm1, itm2); //Console.WriteLine("CT {0},{1},{2},{3}", ct.TransitionID, itm.ItemID, itm.MyContent.MyContentUnique, itm.MyContent.ContentTransitions.Count); ct.TranType = type; if (dte.Type == E_TextElementType.Transition) ct.IsRange = 0; else if (tr1 != tr2) ct.IsRange = 1; else ct.IsRange = 2; l_dte.Link = l_dte.Link.Replace("", string.Format("", ct.TransitionID)); l_dte.TextAndLink = l_dte.TextAndLink.Replace("", string.Format("", ct.TransitionID)); if (dispose2) itm2.Dispose(); if (dispose1) itm1.Dispose(); } } } } } private List GetLinkList(List locDisplayTextElementList) { List retList = new List(); foreach (displayTextElement vte in locDisplayTextElementList) { if (vte.Type == E_TextElementType.ReferencedObject || vte.Type == E_TextElementType.TransitionRange || vte.Type == E_TextElementType.Transition) { displayLinkElement tmp = (displayLinkElement)vte; displayLinkElement copy_vte = new displayLinkElement(); copy_vte.Type = tmp.Type; copy_vte.Link = tmp.Link; copy_vte.Text = tmp.Text; retList.Add(copy_vte); } } return retList; } private void RtfToDisplayTextElements(string text) { // get original text into displaytext elements for comparison for links: if (DisplayTextElementList == null) DisplayTextElementList = new List(); else DisplayTextElementList.Clear(); if (text == null || text == "") return; string noExtraRtfStr = text; int startIndex = 0; int index = -1; noExtraRtfStr = noExtraRtfStr.Replace(@"><", @">\v0 \v <"); while ((index = FindTokenChar(noExtraRtfStr, startIndex)) > -1) { // Do any 'plain' text that preceeds the token. if (index > startIndex) DoTextElement(noExtraRtfStr, startIndex, index); if (noExtraRtfStr[index + 1] == 'v') index = DoLink(noExtraRtfStr, index); else index = DoSymbol(noExtraRtfStr, startIndex, index); startIndex = index; // +1; if (startIndex >= noExtraRtfStr.Length) break; } // Add any remaining text. if (startIndex < noExtraRtfStr.Length) DoTextElement(noExtraRtfStr, startIndex, index); } private string RtfToDbText(string text) { // For hardspaces, the windows richtextbox does some 'quirky' things: // A unicode representation of \u160? is sent INTO the rtb. Coming out, // that \u160? was translated to a \~ (by the underlying windows rtb). // Note that if the \~ is sent to the rtb, it is treated as a regular space, // i.e. no longer a hardspace, and actually is converted to a regular space. // SO, on the way out, convert any \~ to \u160? string noExtraRtfStr = text.Replace(@"\~", @"\u160?"); noExtraRtfStr = noExtraRtfStr.Replace(@"\'a0", @"\u160?"); // Check for two links in a row & if found, add separating rtf comment // commands (these get removed in the richtextbox: // RHM 20100303 Not sure why this is here. The RichTextBox will always remove it. //noExtraRtfStr = noExtraRtfStr.Replace(@"[END>\v0 \v -1) noExtraRtfStr = noExtraRtfStr.Replace(@"\'05", "\x05"); return noExtraRtfStr; } public static string StaticReplaceRTFClause(Match m) { try { string token = m.Groups[1].Value; switch (token[1]) { case '\\': return token; case 'u': if (Regex.IsMatch(token, @"^\\u[0-9]+$")) return token; // Special Charcaters if (Regex.IsMatch(token, @"^\\ulnone ?$")) return token; if (Regex.IsMatch(token, @"^\\ul.*$")) return token; // Underline if (Regex.IsMatch(token, @"^\\up[0-9] ?$")) return token; // shift up (superscript) break; case 'd': if (Regex.IsMatch(token, @"^\\dn[0-9] ?$")) return token; // shift down (subscript) break; case '\'': // Special Character return token; case 'b': // Bold return token; case 'i': // Italics return token; case '{': // look for escape for curly braces: return token; case '}': return token; case 'v': // save link hidden info if (token == "\\viewkind4 ") break; if (Regex.IsMatch(token, @"^\\v0? ?$")) return token; // comment part of link // If possible show what procedure was being processed. if(_MyStaticItemInfo == null) _MyLog.WarnFormat("<<>>\r\n==> Token including Comment not processed '{0}'", token); else _MyLog.WarnFormat("<<>>\r\n==> Token including Comment not processed '{0}' in {1},[{2}]", token, _MyStaticItemInfo.ShortPath, _MyStaticItemInfo.ItemID); break; case 'l': if (Regex.IsMatch(token, @"^\\line ?$")) return token; if (Regex.IsMatch(token, @"^\\li[-0-9]+ ?$")) return token; // line indent break; case 'f': if (Regex.IsMatch(token, @"^\\fi[-0-9]+ ?$")) return token; // first line indent break; case 'p': if (Regex.IsMatch(token, @"^\\par ?$")) return "\r\n"; //if (token == @"\protect") // return token; //if (token == @"\protect0") // return token; //if (token.Length >= 6 && token.Substring(0, 6) == "\\par\r\n") return token.Replace("\r\n", " "); break; //case 'f': // handle fonts separately because they may or may not have a space after them // if (token[2] >= '0' && token[2] <= '9') return token; // break; } } catch (Exception ex) { Console.WriteLine("StaticReplaceRTFClause {0} - {1}", ex.GetType().Name, ex.Message); } return "";//Strip All } private static Regex reg1 = new Regex(@"\\par\r\n(?!\\)"); private static Regex reg2 = new Regex(@"[\r\n]", RegexOptions.Singleline); // Strip Carriage Returns and Newlines private static Regex reg3 = new Regex(@"^\{(.*)\}$", RegexOptions.Singleline); // Strip Opening and Closing Braces private static Regex reg4 = new Regex(@"\{[^{]*?\}", RegexOptions.Singleline); // Strip Clauses - remove anything from curly braces private static Regex reg5 = new Regex( @"\{[^{]*?\}", RegexOptions.Singleline); // Strip Clauses - remove anything from curly braces private static Regex reg6 = new Regex(@"(\\[^' \\?\r\n\t]+)(?=\\)"); // add space after token if followed by token private static Regex reg7 = new Regex(@"(\\[^' \\?\r\n\t]+ )"); // take backslash xyz and evaluates them private static Regex reg8 = new Regex( @"(\\[^' \\?\r\n\t]+) (?=\\)"); // remove space between tokens private static Regex reg9 = new Regex( @"(\\[^' \\?\r\n\t]+) (?=\r\n)"); // remove space before /r/n public string StripRtfCommands(string rtf) { // replace \{ & \} with (![ & (!] respectively and then redo at end. The curly braces // are rtf so were getting removed and/or not handled correctly. string retval = rtf.Replace(@"\{", @" (!["); retval = retval.Replace(@"\}", @" (!]"); // remove carriage return/newlines after \par commands (these are introduced by rtb // for hard returns, goes into rtb as \par and comes out as \par\r\n): retval = reg1.Replace(retval, "\\par "); retval = retval.Replace("\\v0\r\n", "\\v0 "); // Replace Carriage Return and Newline after comment retval = reg2.Replace(retval, ""); // Strip Carriage Returns and Newlines retval = reg3.Replace(retval, "$1"); // Strip Opening and Closing Braces retval = reg4.Replace(retval, ""); // Strip Clauses - remove anything from curly braces retval = reg5.Replace(retval, ""); // Strip Clauses - remove anything from curly braces retval = reg6.Replace(retval, "$1 "); // add space after token if followed by token retval = reg7.Replace(retval, new MatchEvaluator(StaticReplaceRTFClause)); // take backslash xyz and evaluates them retval = reg8.Replace(retval, "$1"); // remove space between tokens retval = reg9.Replace(retval, "$1"); // remove space before /r/n //retval = Regex.Replace(retval, @"\\par\r\n(?!\\)", "\\par "); //retval = retval.Replace("\\v0\r\n", "\\v0 "); // Replace Carriage Return and Newline after comment //retval = Regex.Replace(retval, @"[\r\n]", "", RegexOptions.Singleline); // Strip Carriage Returns and Newlines //retval = Regex.Replace(retval, @"^\{(.*)\}$", "$1", RegexOptions.Singleline); // Strip Opening and Closing Braces //retval = Regex.Replace(retval, @"\{[^{]*?\}", "", RegexOptions.Singleline); // Strip Clauses - remove anything from curly braces //retval = Regex.Replace(retval, @"\{[^{]*?\}", "", RegexOptions.Singleline); // Strip Clauses - remove anything from curly braces //retval = Regex.Replace(retval, @"(\\[^' \\?\r\n\t]+)(?=\\)", "$1 "); // add space after token if followed by token //retval = Regex.Replace(retval, @"(\\[^' \\?\r\n\t]+ )", new MatchEvaluator(StaticReplaceRTFClause)); // take backslash xyz and evaluates them //retval = Regex.Replace(retval, @"(\\[^' \\?\r\n\t]+) (?=\\)", "$1"); // remove space between tokens //retval = Regex.Replace(retval, @"(\\[^' \\?\r\n\t]+) (?=\r\n)", "$1"); // remove space before /r/n // remove \r\n at end of string if the string has 2 or more characters if (retval.EndsWith("\r\n")) retval = retval.Remove(retval.Length - 2, 2); if (retval.Length == 0) return ""; if (retval.EndsWith(@"\v")) retval = retval.Remove(retval.Length - 2, 2); retval = _MyItemInfo.RemoveRtfStyles(retval); // RemoveRtfStyles(retval); retval = retval.Replace(@" (![", @"\{"); retval = retval.Replace(@" (!]", @"\}"); retval = retval.TrimEnd(' '); return retval; } private static Regex sreg1 = new Regex(@"\\par\r\n(?!\\)"); private static Regex sreg2 = new Regex(@"[\r\n]",RegexOptions.Singleline); // Strip Carriage Returns and Newlines private static Regex sreg3 = new Regex(@"^\{(.*)\}$", RegexOptions.Singleline); // Strip Opening and Closing Braces private static Regex sreg4 = new Regex(@"\{[^{]*?\}", RegexOptions.Singleline); // Strip Clauses - remove anything from curly braces private static Regex sreg5 = new Regex(@"\{[^{]*?\}", RegexOptions.Singleline); // Strip Clauses - remove anything from curly braces private static Regex sreg6 = new Regex(@"(\\[^' \\?\r\n\t]+)(?=\\)"); // add space after token if followed by token private static Regex sreg7 = new Regex(@"(\\[^ \\?\r\n\t]+ )"); // take backslash xyz and evaluates them private static Regex sreg8 = new Regex(@"(\\[^ \\?\r\n\t]+) (?=\\)"); // remove space between tokens private static Regex sreg9 = new Regex(@"(\\[^ \\?\r\n\t]+) (?=\r\n)"); // remove space before /r/n // This is used in the DataLoader public static string StaticStripRtfCommands(string rtf) { // replace \{ & \} with (![ & (!] respectively and then redo at end. The curly braces // are rtf so were getting removed and/or not handled correctly. string retval = rtf.Replace(@"\{", @" (!["); retval = retval.Replace(@"\}", @" (!]"); // For hardspaces, the windows richtextbox does some 'quirky' things: // A unicode representation of \u160? is sent INTO the rtb. Coming out, // that \u160? was translated to a \~ (by the underlying windows rtb). // Note that if the \~ is sent to the rtb, it is treated as a regular space, // i.e. no longer a hardspace, and actually is converted to a regular space. // SO, on the way out, convert any \~ to \u160? retval = retval.Replace(@"\~", @"\u160?"); // remove carriage return/newlines after \par commands (these are introduced by rtb // for hard returns, goes into rtb as \par and comes out as \par\r\n): retval = sreg1.Replace(retval, "\\par "); retval = retval.Replace("\\v0\r\n", "\\v0 "); // Replace Carriage Return and Newline after comment retval = sreg2.Replace(retval,""); // Strip Carriage Returns and Newlines retval = sreg3.Replace(retval, "$1"); // Strip Opening and Closing Braces retval = sreg4.Replace(retval, ""); // Strip Clauses - remove anything from curly braces retval = sreg5.Replace(retval, ""); // Strip Clauses - remove anything from curly braces retval = sreg6.Replace(retval,"$1 "); // add space after token if followed by token retval = sreg7.Replace(retval, new MatchEvaluator(StaticReplaceRTFClause)); // take backslash xyz and evaluates them retval = sreg8.Replace(retval, "$1"); // remove space between tokens retval = sreg9.Replace(retval, "$1"); // remove space before /r/n //retval = Regex.Replace(retval, @"\\par\r\n(?!\\)", "\\par "); ////retval = Regex.Replace(retval, @"\\par\r\n(?=\\)", "\\par"); //retval = retval.Replace("\\v0\r\n", "\\v0 "); // Replace Carriage Return and Newline after comment //retval = Regex.Replace(retval, @"[\r\n]", "", RegexOptions.Singleline); // Strip Carriage Returns and Newlines //retval = Regex.Replace(retval, @"^\{(.*)\}$", "$1", RegexOptions.Singleline); // Strip Opening and Closing Braces //retval = Regex.Replace(retval, @"\{[^{]*?\}", "", RegexOptions.Singleline); // Strip Clauses - remove anything from curly braces //retval = Regex.Replace(retval, @"\{[^{]*?\}", "", RegexOptions.Singleline); // Strip Clauses - remove anything from curly braces ////retval = Regex.Replace(retval, @"(\\[^ \\?\r\n\t]+)\\f[0-9] ", "$1 "); // remove font command - if next to another command, keep other command and space //// OLD: The following two lines are replaced by the more generic replace above. ////retval = Regex.Replace(retval, @"\\v\\f[0-9] ", "\\v "); // remove font command - if next to Comment keep space ////retval = Regex.Replace(retval, @"\\line\\f[0-9] ", "\\line "); // remove font command - if next to Line keep space ////retval = Regex.Replace(retval, @"\\f[0-9] ", ""); // remove font command with ending space ////retval = Regex.Replace(retval, @"\\f[0-9]", ""); // remove font command without ending space ////retval = Regex.Replace(retval, @"\\par ", "\r\n"); //retval = Regex.Replace(retval, @"(\\[^' \\?\r\n\t]+)(?=\\)", "$1 "); // add space after token if followed by token ////retval = Regex.Replace(retval, @"(\\[^ \\?\r\n\t]+)(\\)", "$1 $2"); // take backslash xyz and evaluates them //retval = Regex.Replace(retval, @"(\\[^ \\?\r\n\t]+ )", new MatchEvaluator(StaticReplaceRTFClause)); // take backslash xyz and evaluates them //retval = Regex.Replace(retval, @"(\\[^ \\?\r\n\t]+) (?=\\)", "$1"); // remove space between tokens //retval = Regex.Replace(retval, @"(\\[^ \\?\r\n\t]+) (?=\r\n)", "$1"); // remove space before /r/n // remove a space if there is one as the first character or the last character //if (retval[0] == ' ') retval = retval.Remove(0, 1); //retval = retval.TrimEnd(' '); // remove \r\n at end of string if the string has 2 or more characters if (retval.Length > 1 && retval.Substring(retval.Length - 2, 2) == "\r\n") retval = retval.Remove(retval.Length - 2, 2); // remove \par at end of string if the string has 4 or more characters //if (retval.Length > 3 && retval.Substring(retval.Length - 4, 4) == @"\par") retval = retval.Remove(retval.Length - 4, 4); // remove a space following \r\n //retval = Regex.Replace(retval, "\r\n ", "\r\n"); ////if there are still spaces following \r\n, then probable in a table - we need to put the space back //retval = Regex.Replace(retval, "\r\n ", "\r\n "); if (retval.Length == 0) return ""; if (retval.Length > 1 && retval.Substring(retval.Length - 2, 2) == @"\v") retval = retval.Remove(retval.Length - 2, 2); //retval = RemoveRtfStyles(retval); //if (itmInfo != null) // retval = StaticRemoveRtfStyles(retval, itmInfo); retval = retval.Replace(@" (![", @"\{"); retval = retval.Replace(@" (!]", @"\}"); retval = retval.TrimEnd(' '); // the indent character was translated in the richtextbox, change it back: if (retval.IndexOf(@"\'05") > -1) retval = retval.Replace(@"\'05", "\x05"); return retval; } #endregion #region StyleData //private VE_Font GetItemFont() //{ // VE_Font font = null; // FormatInfo format = _MyItemInfo.ActiveFormat; // int type = (int)_MyItemInfo.MyContent.Type; // switch (type/10000) // { // case 0: // procedure // font = format.PlantFormat.FormatData.Font; // break; // case 1: // section // font = format.PlantFormat.FormatData.SectData.SectionHeader.Font; // break; // case 2: // step types // int typindx = type - 20000; // what to do for other types rather than steps // font = format.PlantFormat.FormatData.StepDataList[typindx].Font; // break; // } // TextFont = font; // return font; //} #endregion #region DoListElements private int FindTokenChar(string txt, int startIndex) { // 'tokens' are for symbols and links (ro & transitions). symbols are represented by \u // and links are represented by \v \v0 bool done = false; while (!done) { int indx = txt.IndexOf('\\', startIndex); if (indx < 0) return indx; // see if symbol (but not underline) or another rtf command: has a 'u' // followed by a non-underline or single quote, and if so, return it. if (((txt[indx + 1] == 'u' && txt[indx + 2] != 'l' && txt[indx + 2] !='p')) || (txt[indx + 1] == '\'')) return indx; // see if link if (txt[indx + 1] == 'v') return indx; //TODO - should have ") != -1) return text; int transitionID = Convert.ToInt32(link.Split(" ".ToCharArray())[1]); // Find the transition if (_MyItemInfo.MyContent.ContentTransitionCount <= 0) { // TODO: RHM 20100310 _MyItemInfo.MyContent.RefreshContentTransitions(); if (_MyItemInfo.MyContent.ContentTransitionCount <= 0) return "*Resolved Transition Text*"; } foreach (TransitionInfo ti in _MyItemInfo.MyContent.ContentTransitions) { if (ti.TransitionID == transitionID) { string path = ti.ResolvePathTo(_MyFormat, _MyItemInfo, ti.TranType, ti.MyItemToID, ti.MyItemRangeID); return path; } } return text; } private int DoTran(string text,int index) { displayLinkElement vte = new displayLinkElement(); // determine if Range by checking for "R" after Transition (otherwise ":") int linkindx = text.IndexOf(@"#Link", index); vte.Type = (text[linkindx+16]=='R')?E_TextElementType.TransitionRange:E_TextElementType.Transition; return DoLinkElements(text, index, vte); } //private int GetLastLower(string stepText) //{ // // TO DO: need to check AlwaysUpperCase format setting - this was not yet converted as of 17Jun2010 // // if (AlwaysUpperCase[steptype]) return (stepText.Length-1); // int idx = stepText.Length - 1; // while (idx >= 0 && !(char.IsLower(stepText[idx]) && stepText[idx] != 's')) idx--; // if (idx < 0) idx = stepText.Length - 1; // entire string is uppercased set return value to end of string // return idx; //} //private bool IsSpaceOrHardSpace(char ch) //{ // string spaces = @" \u160?"; // return (spaces.IndexOf(ch) >= 0); //} private string DoROFormatFlags(string roText, string beforeRO, string afterRO, bool isSetpoint) { string rtnstr = roText; // The RO text is being changed to match it's context. Since it is changed in reverse order, the text before the RO // should ignore other RO text. beforeRO = Regex.Replace(beforeRO, @"\", ""); // Remove any RO Values. beforeRO = Regex.Replace(beforeRO, @"(\\[^v \\]+)*\\v(\\[^v \\]+)* .*?\\v0(\\[^v \\]+)*( |$)", ""); // Remove Comments string allUnitAfterRo = afterRO; afterRO = Regex.Replace(afterRO, @"(\\[^v \\]+)*\\v(\\[^v \\]+)* .*?\\v0(\\[^v \\]+)*( |$)", ""); // Remove Comments // Underline all ROs, values and Units if (isSetpoint && _MyItemInfo.ActiveFormat.PlantFormat.FormatData.ROData.UnderlineRo) { // TO DO: Need to check if step text is already underlined if ((_MyItemInfo.FormatStepData.Font.Style & E_Style.Underline) == 0) rtnstr = @"\ul " + rtnstr + @"\ulnone "; } // UpcaseAllRoUnits - Uppercases ALL ROs units everywhere. if (isSetpoint && _MyItemInfo.ActiveFormat.PlantFormat.FormatData.ROData.UpcaseAllRoUnits) return UpperCaseUnits(rtnstr); //Forces the units for a RO to be uppercased for high level steps if (_MyItemInfo.ActiveFormat.PlantFormat.FormatData.ROData.CapHighRo &&_MyItemInfo.IsHigh) return UpperCaseUnits(rtnstr); // Caps ROs anywhere if no lower case text follows // and an upper case letter immediately precedes the RO. if (isSetpoint && _MyItemInfo.ActiveFormat.PlantFormat.FormatData.ROData.CapSPIfLastLower && !Regex.IsMatch(afterRO, @".*(? 0 && !IsSpaceOrHardSpace(stepText[indx])) indx--; // find character before RO //while (indx2 <= stepText.Length && !IsSpaceOrHardSpace(stepText[indx2])) indx2++; // find character after RO //if (indx >= 0 && char.IsUpper(stepText[indx]) && indx2 > GetLastLower(stepText)) // doUpCase = true; return UpperCaseUnits(rtnstr); } // If a RO follows a "- " then it will be uppercased if (_MyItemInfo.ActiveFormat.PlantFormat.FormatData.ROData.UpRoAftrDash && Regex.IsMatch(beforeRO, @".*\\u8209\?( |\\u160\?)")) { //int indx = startLinkText - 1; //while (indx > 0 && !IsSpaceOrHardSpace(stepText[indx])) indx--; // find character before RO //string prefix = indx >= 7?stepText.Substring(indx-7,8):""; //doUpCase = (prefix == @"\u8209? "); // Dash character before RO return UpperCaseUnits(rtnstr); } // For Wolf Creek, the "- " should be right before the link. This ro format flag was introduced // for Wolf Creek only because a problem was found with some of their data that was incorrectly // processed through the 'UpRoAftrDash' flag. That flag was more general, i.e. upper cased units // if there was a dash and then a space or hard space anywhere before the RO text. The original // 16bit flag was more specific. Other plants that were released had the UpRoAftrDash, but // we didn't want to change their formats since they had gone through testing. if (_MyItemInfo.ActiveFormat.PlantFormat.FormatData.ROData.UpRoImmAftrDashSpace && Regex.IsMatch(beforeRO, @".*\\u8209\?( )")) return UpperCaseUnits(rtnstr); // Uppercase the RO Unit if the previous letter is uppercase if (_MyItemInfo.ActiveFormat.PlantFormat.FormatData.ROData.UpRoIfPrevUpper && char.IsUpper(LastAlpha(beforeRO))) { //doUpCase = (char.IsUpper(stepText[startLinkText - 1])); return UpperCaseUnits(rtnstr); } //CapFirstLetterInHighRO - Cap only the first letters of the units in a high level RO // note: used in FLP (Turkey Point) format if (_MyItemInfo.ActiveFormat.PlantFormat.FormatData.ROData.CapFirstLetterInHighRO && _MyItemInfo.IsHigh) { int idx = 0; string tstr = ""; while (idx < rtnstr.Length && !char.IsLetter(rtnstr[idx])) tstr += rtnstr[idx++].ToString(); if (idx < rtnstr.Length) { tstr += char.ToUpper(rtnstr[idx]).ToString(); if (idx + 1 < rtnstr.Length) tstr += rtnstr.Substring(idx + 1); } rtnstr = tstr; } return rtnstr; } private string RemoveMultipleUnits(string prevValue, string rtnstr) { //In a sequence of RO values, the unit appears with every value //(e.g., "25 gpm and 30 gpm" vs. "25 and 30 gpm") if (!_MyItemInfo.ActiveFormat.PlantFormat.FormatData.ROData.AllUnits && prevValue != null) { string units = null; //Match m = Regex.Match(prevValue, "[^0-9]"); int ind = prevValue.LastIndexOfAny("0123456789".ToCharArray()); if (ind>=0) { string mynum = prevValue.Substring(0, ind+1); // Handle Hex characters which are part of the Units such as the degree character if (Regex.IsMatch(mynum, @".*\\'[A-Fa-f0-9]{2,2}$")) ind -= 4; units = prevValue.Substring(ind+1); if (rtnstr.EndsWith(units) && units != "")// Don't do this if there are no units { rtnstr = rtnstr.Replace(units, ""); } } } return rtnstr; } /// /// Uppercase alphabetical strings excluding any RTF token /// /// /// private string MatchEvaluatorUppercaseROUnits(Match match) { if (match.Value[0] == '\\') // If the previous character is a backslash then this is an RTF token return match.Value; return match.Value.ToUpper(); } Regex _RegExUppercaseROUnits = new Regex("(^|[^a-zA-Z])[a-zA-Z]+"); private string UpperCaseUnits(string rtnstr) { // Uppercase Units rtnstr = _RegExUppercaseROUnits.Replace(rtnstr, new MatchEvaluator(MatchEvaluatorUppercaseROUnits)); // After converting the value to uppercase, change X10 to x10 to handle Fortran Formatted numbers return rtnstr.Replace("X10", "x10"); } // Find the last Alphabetical character private char LastAlpha(string beforeRO) { Match m = Regex.Match(beforeRO, ".*([a-zA-Z])[^a-zA-Z]*"); if (m.Success) return m.Groups[1].ToString()[0]; return '\0'; } private int DoLinkElements(string text, int index, displayLinkElement vte) { // Find the 'end comment' for this 0 && (endTextIndx < 0 || endTextIndx > endTextIndx2)) endTextIndx = endTextIndx2; vte.Text = text.Substring(endStartTknIndx + startAdj, endTextIndx - endStartTknIndx - startAdj); // 4 for \v0 // Now get the link part. It can be terminated by a '\v0' or an [END> int endLinkIndxV = text.IndexOf(@"\v0 ", linkIndx); if (endLinkIndxV == -1) endLinkIndxV = text.IndexOf(@"\v0", linkIndx); // at end of string int endLinkIndxE = text.IndexOf(@"[END>", linkIndx); int endLinkIndx = (endLinkIndxV < endLinkIndxE) ? endLinkIndxV : endLinkIndxE; vte.Link = text.Substring(linkIndx + 6, endLinkIndx - linkIndx - 6); // 6 for #Link: string tmptxt = null; if (vte.Type != E_TextElementType.ReferencedObject) { tmptxt = FixTransition(vte.Link, vte.Text); vte.Text = tmptxt; } //else //{ // tmptxt = DoROFormatFlags(vte.Text, text, index, endLinkIndx); // vte.Text = tmptxt; //} // Now get the entire text & link. Account for various ending possibilities: // ends with '\v0\'; ends with '\v0 '; ends with '\v0' (end of string); // ends with '[END>' if two in a row - will have ", endLinkIndx + 3); // get past end of link int endComment = text.IndexOf(@"\v0", endToken); int rettoken = 0; int retlen = 4; if (endComment + 3 == text.Length) retlen = 3; else if (text[endComment + 3] == '\\') retlen = 3; vte.TextAndLink = text.Substring(index, endComment - index + retlen); rettoken = endComment + retlen; if (vte.Type != E_TextElementType.ReferencedObject) { if (vte.TextAndLink.Contains("(Resolved Transition Text)")) vte.TextAndLink = vte.TextAndLink.Replace("(Resolved Transition Text)", tmptxt); else if (vte.Text != tmptxt) vte.Text = tmptxt; } DisplayTextElementList.Add(vte); return rettoken; } private int DoSymbol(string text, int startIndex, int index) { displayTextElement vte = new displayTextElement(); vte.Type = E_TextElementType.Symbol; // symbols are the unicode/rtf command. A symbol can be represented by \'xy or // in the text from the database \uxyz?. If the \'xy is used the length of the // symbol number will always be two, otherwise find the index of the '?' to // find the end. int endindx = -1; if (text[index + 1] == '\'') endindx = index + 3; else endindx = text.IndexOf("?", index); vte.Text = text.Substring(index, endindx - index + 1); DisplayTextElementList.Add(vte); return endindx+1; } #endregion #region ReplaceWords #region commented out //private string DoReplaceWords(string Text) //{ // ReplaceStrList rsl = _MyFormat.PlantFormat.FormatData.SectData.ReplaceStrList; // foreach (ReplaceStr rs in rsl) // { // if (_MyItemInfo.MyContent.Type < 20000) return Text; // for now only replace in steps. // bool replaceit = false; // if (_MyItemInfo.ItemID == 2557) Console.WriteLine("here"); // // note that the order of this check is important. Check in this order... // // background here // if (_MyItemInfo.IsHigh && (rs.Flag & E_ReplaceFlags.High)>0) replaceit = true; // else if ((_MyItemInfo.IsTable || _MyItemInfo.IsFigure) && (rs.Flag & E_ReplaceFlags.Table) > 0) replaceit = true; // else if (_MyItemInfo.IsInRNO && (rs.Flag & E_ReplaceFlags.RNO) > 0) replaceit = true; // else if (_MyItemInfo.IsCaution && (rs.Flag & E_ReplaceFlags.Caution) > 0) replaceit = true; // else if (_MyItemInfo.IsNote && (rs.Flag & E_ReplaceFlags.Note) > 0) replaceit = true; // else if (_MyItemInfo.IsStepPart && (rs.Flag & E_ReplaceFlags.Substep) > 0) replaceit = true; // //else if (_MyItemInfo.IsInFirstLevelSubStep && (rs.Flag & E_ReplaceFlags.Substep) > 0) replaceit = true; // else if (_MyItemInfo.IsAccPages & (rs.Flag & E_ReplaceFlags.Attach) > 0) replaceit = true; // if (replaceit) // { // // CASEINSENS: Do ReplaceWords for all words that match, regardless of case, and replace // // with the ReplaceWith string as is // if ((rs.Flag & E_ReplaceFlags.CaseInsens) > 0) // { // //string res = ""; // //string fortest = Text.ToUpper(); // ////string pat = @"(?<=\W|^)" + rs.ReplaceWord.ToUpper() + @"(?=\W|$)"; // //// jsj 07Jun2010 HardSpaces defeat replaceword logic // //string pat = @"(?<=\W|^)(? 0) // { // // only in Maine Yankee - we don't need to do this one. // } // // CASEINSENSFIRST: Do ReplaceWords for all words that exactly match the ReplaceWord, // // except the case where the first character may be different // else if ((rs.Flag & E_ReplaceFlags.CaseInsensFirst) > 0) // { // // only used in V.C. Summer - we don't need to do this either. // } // else // { // // If there are Regex Control Characters '\[]()' prefix them with backslash // string replaceWord = Regex.Replace(rs.ReplaceWord, @"[[\]\\()]", @"\$0"); // //string pat = @"(?<=\W|^)" + replaceWord + @"(?=\W|$)"; // // jsj 07Jun2010 HardSpaces defeat replaceword logic // //string pat = @"(?<=\W|^)(? 0) replaceit = true; // else if ((_MyItemInfo.IsTable || _MyItemInfo.IsFigure) && (rs.Flag & E_ReplaceFlags.Table) > 0) replaceit = true; // else if (_MyItemInfo.IsInRNO && (rs.Flag & E_ReplaceFlags.RNO) > 0) replaceit = true; // else if (_MyItemInfo.IsCaution && (rs.Flag & E_ReplaceFlags.Caution) > 0) replaceit = true; // else if (_MyItemInfo.IsNote && (rs.Flag & E_ReplaceFlags.Note) > 0) replaceit = true; // else if (_MyItemInfo.IsStepPart && (rs.Flag & E_ReplaceFlags.Substep) > 0) replaceit = true; // //else if (_MyItemInfo.IsInFirstLevelSubStep && (rs.Flag & E_ReplaceFlags.Substep) > 0) replaceit = true; // else if (_MyItemInfo.IsAccPages & (rs.Flag & E_ReplaceFlags.Attach) > 0) replaceit = true; // if (replaceit) // { // // CASEINSENS: Do ReplaceWords for all words that match, regardless of case, and replace with the ReplaceWith string as is // RegexOptions myOptions = (rs.Flag & E_ReplaceFlags.CaseInsens) == E_ReplaceFlags.CaseInsens ? RegexOptions.IgnoreCase : RegexOptions.None; // string replaceWord = Regex.Replace(rs.ReplaceWord, @"[[\]\\()]", @"\$0"); // string pat = @"(?<=\W|^)(? dicReplaceRegex = new Dictionary(); private static bool? _ProcessReplaceWords; public static bool ProcessReplaceWords { get { if (_ProcessReplaceWords == null) { string[] parameters = System.Environment.CommandLine.Split(" ".ToCharArray()); _ProcessReplaceWords = true; foreach (string parameter in parameters) { if (parameter.ToUpper() == "/NRW") _ProcessReplaceWords = false; } } return (bool) _ProcessReplaceWords; } } private string DoReplaceWords2(string Text) { if (!ProcessReplaceWords) return Text; if (_MyItemInfo.MyContent.Type < 20000) return Text; // for now only replace in steps. FoundMatches myMatches = new FoundMatches(Text, _MyItemInfo.FormatStepData.Font, _MyItemInfo); // Exclude Link Text from Replace Word process myMatches.AddLink(regFindLink, _MyFormat.PlantFormat.FormatData.SectData.ReplaceWordsInROs, _MyItemInfo.MyProcedure.MyDocVersion); ReplaceStrList rsl = _MyFormat.PlantFormat.FormatData.SectData.ReplaceStrList; // ReplaceStrData xml node is empty, it does the inheritance and gets the 'base' format's list. if (rsl.Count==1 && (rsl[0].ReplaceWord == null || rsl[0].ReplaceWord == "")) return Text; // Loop through text looking for words to be replaced Dictionary partialReplaceList = new Dictionary(); Dictionary shouldReplace = new Dictionary(); //int profileDepth = ProfileTimer.Push(">>>> DoReplaceWords2.ForLoop"); foreach (ReplaceStr rs in rsl) { bool dopartial = (rs.Flag & E_ReplaceFlags.Partials) == E_ReplaceFlags.Partials; // note that the order of this check is important. Check in this order... // background here if (!shouldReplace.ContainsKey(rs.Flag)) { //int profileDepth2 = ProfileTimer.Push(">>>> Before ShouldReplaceIt"); shouldReplace.Add(rs.Flag, ShouldReplaceIt(rs.Flag)); //ProfileTimer.Pop(profileDepth2); } bool replaceit = shouldReplace[rs.Flag]; if (replaceit) { if (!dicReplaceRegex.ContainsKey(rs)) { RegexOptions myOptions = (rs.Flag & E_ReplaceFlags.CaseInsens) == E_ReplaceFlags.CaseInsens ? RegexOptions.IgnoreCase : RegexOptions.None; if (dopartial) { dicReplaceRegex.Add(rs, new Regex(rs.ReplaceWord, myOptions)); } else { //int profileDepth3 = ProfileTimer.Push(">>>> DoReplaceWords2.BuildMatch"); // CASEINSENS: Do ReplaceWords for all words that match, regardless of case, and replace with the ReplaceWith string as is //RegexOptions myOptions = (rs.Flag & E_ReplaceFlags.CaseInsens) == E_ReplaceFlags.CaseInsens ? RegexOptions.IgnoreCase & RegexOptions.Singleline : RegexOptions.None & RegexOptions.Singleline; string replaceWord = Regex.Replace(rs.ReplaceWord, @"[[\]\\()]", @"\$0"); // if first or last character in replaceword is a non-word character, for example, ',', ')', or '.', // don't use the \W, i.e. don't bother to look for a non-word character. string wordMatchBeg = Regex.IsMatch(replaceWord.Substring(0, 1), @"\W") ? "" : @"(?<=\W|^)"; string wordMatchEnd = Regex.IsMatch(replaceWord.Substring(replaceWord.Length - 1, 1), @"\W") ? "" : @"(?=\W|$)"; string pat = wordMatchBeg + @"(?>>> DoReplaceWords2.Partial"); if (!dopartial) myMatches.Add(dicReplaceRegex[rs], rs); else partialReplaceList.Add(rs, dicReplaceRegex[rs]); //ProfileTimer.Pop(profileDepth4); } catch (Exception ex) { Console.WriteLine("{0},'{1}',{2},'{3}'", _MyItemInfo.ActiveFormat.Name, rs.ReplaceWord, ex.GetType().Name, ex.Message); } dopartial = false; } } //ProfileTimer.Pop(profileDepth); //int profileDepth5 = ProfileTimer.Push(">>>> DoReplaceWords2.ReplaceMatches"); Text = myMatches.ReplaceMatches(); //ProfileTimer.Pop(profileDepth5); Text = Text.Replace(@"\xA0", @"\u160?"); //replace hard space try { foreach (ReplaceStr prs in partialReplaceList.Keys) Text = partialReplaceList[prs].Replace(Text, prs.ReplaceWith); } catch (Exception ex) // Don't crash on a format issue. { _MyLog.WarnFormat("{0} - {1}", ex.GetType().Name, ex.Message); } return Text; } private bool ShouldReplaceIt(E_ReplaceFlags? myFlag) { bool replaceit= false; if (_MyItemInfo.IsHigh && (myFlag & E_ReplaceFlags.High) > 0) { replaceit = true; } else if ((_MyItemInfo.IsTable || _MyItemInfo.IsFigure) && (myFlag & E_ReplaceFlags.Table) > 0) { replaceit = true; } else if (_MyItemInfo.IsInRNO && (myFlag & E_ReplaceFlags.RNO) > 0) { replaceit = true; } else if (_MyItemInfo.IsCaution && (myFlag & E_ReplaceFlags.Caution) > 0) { replaceit = true; } else if (_MyItemInfo.IsNote && (myFlag & E_ReplaceFlags.Note) > 0) { replaceit = true; } else if (_MyItemInfo.IsStepPart && !_MyItemInfo.IsHigh && (myFlag & E_ReplaceFlags.Substep) > 0) { replaceit = true; } //else if (_MyItemInfo.IsInFirstLevelSubStep && (rs.Flag & E_ReplaceFlags.Substep) > 0) replaceit = true; else if (_MyItemInfo.IsAccPages & (myFlag & E_ReplaceFlags.Attach) > 0) { replaceit = true; } return replaceit; } #region notused static Regex regFindLink = new Regex(@"\", RegexOptions.Singleline); private string ReplaceWord(string text, string replace, string with, RegexOptions regexOptions) { MatchCollection myMatches = Regex.Matches(text, replace, regexOptions); MatchCollection myLinks = regFindLink.Matches(text); for (int i = myMatches.Count - 1; i >= 0; i--) { Match myMatch = myMatches[i]; if (!PartOfLinkText(myMatch, myLinks)) text = text.Substring(0, myMatch.Index) + with + text.Substring(myMatch.Index + myMatch.Length); } return text; } private bool PartOfLinkText(Match myMatch, MatchCollection myLinks) { foreach (Match myLink in myLinks) if (myMatch.Index > myLink.Index && myMatch.Index < (myLink.Index + myLink.Length)) return true; return false; } #endregion #endregion } #region displayTextElementClass public enum E_TextElementType : uint { Text = 0, Transition = 1, TransitionRange = 2, ReferencedObject = 3, Symbol = 4 }; public class displayTextElement { private E_TextElementType _Type; public E_TextElementType Type { get { return _Type; } set { _Type = value; } } protected string _Text; virtual public string Text { get { return _Text; } set { _Text = value; } } } public class displayLinkElement : displayTextElement { private string _Link; public string Link { get { return _Link; } set { _Link = value; } } private string _TextAndLink; public string TextAndLink { get { return _TextAndLink; } set { _TextAndLink = value; } } /// /// Text - this should parse the text and return the results /// override public string Text { get { if (_TextAndLink != null) { Match m = Regex.Match(_TextAndLink, @"", RegexOptions.Singleline); if(m.Groups[3].Value == " ") return m.Groups[4].Value; return m.Groups[3].Value + m.Groups[4].Value; } return _Text; } set { if (_TextAndLink != null) { Match m = Regex.Match(_TextAndLink, @"", RegexOptions.Singleline); int myIndex = m.Groups[4].Index; int myLength = m.Groups[4].Length; if (m.Groups[3].Value != " ") { myIndex = m.Groups[3].Index; myLength += m.Groups[3].Length; } string gg = _TextAndLink.Substring(myIndex, myLength); string newvalue = value.Replace("{", @"\{").Replace("}", @"\}"); _TextAndLink = _TextAndLink.Substring(0, myIndex) + newvalue + _TextAndLink.Substring(myIndex + myLength); } _Text = value; } } } #endregion public class FoundMatches : SortedList { private static readonly log4net.ILog _MyLog = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); private string _Text; private VE_Font _Font; private ItemInfo _MyItemInfo; public FoundMatches(string text, VE_Font font, ItemInfo myItemInfo) : base() { _Text = text; _Font = font; _MyItemInfo = myItemInfo; } public void Add(Regex myRegEx, ReplaceStr myWord) { MatchCollection myMatches = myRegEx.Matches(_Text); foreach (Match myMatch in myMatches) Add(myMatch, myWord); } public void AddLink(Regex myRegEx, bool replaceWordsInROs, DocVersionInfo myDocVersion) { MatchCollection myMatches = myRegEx.Matches(_Text); foreach (Match myMatch in myMatches) { if (!replaceWordsInROs || IsTransition(myMatch.Value) || IsSetpointRO(myMatch.Value, myDocVersion)) Add(myMatch, null);// Exclude from Replace Words } } private bool IsTransition(string link) { return link.Contains("#Link:Transition"); } private static Regex regRefObj = new Regex(@"\#Link\:ReferencedObject:([0-9]*) ([0-9a-zA-Z]*) ([0-9]*)", RegexOptions.Singleline); private static bool IsSetpointRO(string link, DocVersionInfo myDocVersion) { Match myMatch = regRefObj.Match(link); if (myMatch.Success) { int dbid = System.Convert.ToInt32(myMatch.Groups[2].Value.Substring(0, 4), 16); int rodbid = int.Parse(myMatch.Groups[3].Value); ROFstInfo myROFst = myDocVersion.GetROFst(rodbid); return myROFst.IsSetpointDB(dbid, myDocVersion); } return false; } public void Add(Match myMatch, ReplaceStr myWord) { // If one already exists for this location, then don't add another. if (ContainsKey(myMatch.Index)) return; // Start by Adding it. base.Add(myMatch.Index, new FoundMatch(myMatch, myWord)); // Now see what I can do with it. int index = this.IndexOfKey(myMatch.Index); if (index > 0) // If this match is contained within the previous match remove it { FoundMatch previousMatch = Values[index - 1]; if (previousMatch.MyMatch.Index + previousMatch.MyMatch.Length > myMatch.Index) Remove(myMatch.Index); } // If the next match is contained within this match, remove the next match while (index < Count - 1 && Values[index + 1].MyMatch.Index < (myMatch.Index + myMatch.Length)) Remove(Values[index + 1].MyMatch.Index); } public bool StartsWith(string text, int index, params string[] examples) { foreach (string str in examples) if (str.Length == index && str == text.Substring(0, str.Length)) return true; return false; } public string ReplaceMatches() { int offset = 0; string text = _Text; foreach (FoundMatch foundMatch in Values) { if (foundMatch.MyWord != null) { if (VerifyNoHardSpace(text, foundMatch, offset) && VerifyNoLink(text, foundMatch, offset)) { //if(offset != 0 || foundMatch.MyMatch.Index != 0 || !foundMatch.MyWord.ReplaceWith.StartsWith(@"{\par}")) //{ if (((foundMatch.MyWord.Flag & E_ReplaceFlags.DiffUnit) == 0) || DiffUnit(foundMatch.MyWord.ReplaceWord,_MyItemInfo,"UNIT ")) { string with = foundMatch.MyWord.ReplaceWith; if (offset == 0 && with.StartsWith(@"{\par}")) if(StartsWith(text,foundMatch.MyMatch.Index,"",@"\ul ",@"\b ",@"* ",@"* \ul ",@"* \b ",@"*",@"*\ul ",@"*\b ")) with = with.Replace(@"{\par}", ""); bool IsBold = ((_Font.Style & E_Style.Bold) == E_Style.Bold) || (_MyItemInfo.FormatStepData != null && _MyItemInfo.FormatStepData.BoldHighLevel && _MyItemInfo.IsRNOPart && _MyItemInfo.MyParent.IsHigh ); if (IsBold && with.Contains(@"\b ")) { with = with.Replace(@"\b ",""); with = with.Replace(@"\b0 ",""); } bool IsUnderline = (((_Font.Style & E_Style.Underline) == E_Style.Underline) && with.Contains(@"\ul ")); // handle where replace words replaces a string with 'underline on'string'underline off', for example Point Beach // had replaced OR's turning underline off in the middle of a transition, "EOP-0 UNIT 1, RACTORE TRIP OR SAFETY INJECTION". if (!IsUnderline) { int repidxulnone = text.LastIndexOf(@"\ulnone", foundMatch.MyMatch.Index + offset); int repidxst = text.LastIndexOf(@"\ul", foundMatch.MyMatch.Index + offset); if (repidxulnone > 0) { repidxst = text.Substring(repidxulnone + 7, foundMatch.MyMatch.Index + offset - (repidxulnone + 7)).LastIndexOf(@"\ul"); if (repidxst >= 0) repidxst += (repidxulnone + 7); } if (repidxst >= 0) IsUnderline = true; } if (IsUnderline) { with = with.Replace(@"\ul ", ""); with = with.Replace(@"\ulnone ", ""); } string preceedingText = text.Substring(0, offset + foundMatch.MyMatch.Index); int ndxBold = preceedingText.LastIndexOf(@"\b"); if (ndxBold > -1 && preceedingText.Length>( ndxBold + 2) && preceedingText[ndxBold + 2] != '0' && with.Contains(@"\b ")) { with = with.Replace(@"\b ",""); with = with.Replace(@"\b0 ",""); } int ndxULine = preceedingText.LastIndexOf(@"\ul"); if (ndxULine > -1 && preceedingText[ndxULine + 3] != 'n' && with.Contains(@"\ul ")) { with = with.Replace(@"\ul ", ""); with = with.Replace(@"\ulnone ", ""); } text = text.Substring(0, offset + foundMatch.MyMatch.Index) + with + text.Substring(offset + foundMatch.MyMatch.Index + foundMatch.MyMatch.Length); //offset += foundMatch.MyWord.ReplaceWith.Length - foundMatch.MyMatch.Length; offset += with.Length - foundMatch.MyMatch.Length; } } } } return text; } private bool VerifyNoLink(string text, FoundMatch fndMatch, int offset) { if (text.Substring(offset + fndMatch.MyMatch.Index, fndMatch.MyMatch.Length) == "START") if (fndMatch.MyMatch.Index > 0 && offset + fndMatch.MyMatch.Index + fndMatch.MyMatch.Length < text.Length && text.Substring(offset + fndMatch.MyMatch.Index - 1, fndMatch.MyMatch.Length + 2) == "