diff --git a/PROMS/Volian.Controls.Library/DisplayText.cs b/PROMS/Volian.Controls.Library/DisplayText.cs new file mode 100644 index 00000000..c585c21b --- /dev/null +++ b/PROMS/Volian.Controls.Library/DisplayText.cs @@ -0,0 +1,862 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows.Forms; +using System.Text.RegularExpressions; +using System.Drawing; + +namespace VEPROMS.CSLA.Library +{ + public class DisplayText + { + #region Properties + private ItemInfo _MyItemInfo; + // 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; } + } + public string OriginalText; // compare for save to see if change. + public string OriginalConfigText; + private FormatInfo _MyFormat; + #endregion + #region Constructors + /// + /// DisplayText constructor: + /// Creates a DisplayText object that converts the database text into a list of + /// displayTextElement elements. + /// 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. + /// + public DisplayText(ItemInfo itemInfo, E_EditPrintMode epMode, E_ViewMode vwMode, bool noEdit) + { + _MyItemInfo = itemInfo; + DisplayTextElementList = new List(); + OriginalText = itemInfo.MyContent.Text; + TextFont = GetItemFont(); + string text = _MyItemInfo.MyContent.Text; + + // 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. + _MyFormat = itemInfo.ActiveFormat; + if (epMode == E_EditPrintMode.Print || vwMode == E_ViewMode.View || noEdit) text = DoReplaceWords(text); + + // adjust formatting of exponents + if (!_MyFormat.PlantFormat.FormatData.SectData.StepSectionData.FortranFormatNumbers && (epMode == E_EditPrintMode.Print || vwMode == E_ViewMode.View || noEdit)) text = DoFortranFormat(text); + + // 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", @"\par "); + // replace the dash/hyphen or whatever you want to call it, with a hard hyphen. The 16-bit program + // treated the dash/hyphen as such. Translate back on any data saves. + if (itemInfo.ItemID == 1275) + Console.WriteLine("here"); + // text = text.Replace(@"-", @"\u8209?"); + + // displayTextElement List items are created for anything that is handled differently in RTB, i.e. + // symbols, ros, trans, text. + int startIndex = 0; + int index = -1; + while ((index = FindTokenChar(text, startIndex))>-1) + { + // Do any 'plain' text that preceeds the token. + if (index > startIndex) DoTextElement(text, startIndex, index); + if (text[index + 1] == 'v') + index = DoLink(text, index); + else + index = DoSymbol(text, startIndex, index); + startIndex = index; // +1; + if (startIndex >= text.Length) break; + } + // Add any remaining text. + if (startIndex < text.Length) DoTextElement(text, startIndex, index); + } + + 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\super {1}\nosupersub ", fnum, supnum); + retstr = retstr.Replace(m.Value, newstr); + } + return retstr; + } + #endregion + #region SaveData + public bool Save(RichTextBox rtb) + { + try + { + List origList = GetLinkList(DisplayTextElementList); + // massage string to store in DisplayTextElementList... + RtfToDisplayTextElements(rtb); + // take the list & convert to data in the format to save to the database. + string modtext = DteToString(); + + if (modtext != OriginalText) + { + Item itm = _MyItemInfo.Get(); + // check for different text, i.e. text from this itm doesn't match + // original text. + if (OriginalText != itm.MyContent.Text) + { + Console.WriteLine("Save Failed because text changed outside of this edit session."); + return false; + } + // Compare ro/transition lists and delete or add any to the item for any ros/transitions that have been + // added/deleted or modified. + ProcessRoTranChanges(itm, origList); + itm.MyContent.Text = DteToString(); + Dictionary ctReplacements = BuildCtReplacements(itm.MyContent.ContentTransitions); + Dictionary roUsgReplacements = BuildRoUsgReplacements(itm.MyContent.ContentRoUsages); + itm.Save(); + if (ctReplacements.Count > 0) + { + itm.MyContent.Text = FixCtReplacements(itm.MyContent.Text, ctReplacements); + itm.Save(); + } + if (roUsgReplacements.Count > 0) + { + itm.MyContent.Text = FixRoUsgReplacements(itm.MyContent.Text, roUsgReplacements); + itm.Save(); + } + OriginalText = modtext; + } + else + return true; // no text changed, but did not fail so return true. + } + catch (Exception ex) + { + Console.WriteLine("Save Failed with error: {0}", ex.Message); + return false; + } + 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.Get(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[1] is token for tranid + Item itm1 = Item.Get(tr1); + Item itm2 = null; + if (dte.Type == E_TextElementType.TransitionRange) + { + itm2 = Item.Get(System.Convert.ToInt32(tparts[2])); + } + else + itm2 = itm1; + ContentTransition ct = itm.MyContent.ContentTransitions.Add(itm1, itm2); + ct.TranType = type; + l_dte.Link = l_dte.Link.Replace("", string.Format("", ct.TransitionID)); + l_dte.TextAndLink = l_dte.TextAndLink.Replace("", string.Format("", ct.TransitionID)); + } + } + } + } + } + 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(RichTextBox rtb) + { + // 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 = rtb.Rtf.Replace(@"\~", @"\u160?"); + + // Check for two links in a row & if found, add separating rtf comment + // commands (these get removed in the richtextbox: + noExtraRtfStr = noExtraRtfStr.Replace(@"[END>\v0 \v -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 int SaveTextElement(string data, int startIndex, int index) + { + displayTextElement vte = new displayTextElement(); + vte.Type = E_TextElementType.Text; + int len = (index == -1) ? data.Length - startIndex : index - startIndex; + vte.Text = data.Substring(startIndex, len); + DisplayTextElementList.Add(vte); + return index; + } + private int SaveSymbolTE(string data, int startIndex) + { + displayLinkElement vte = new displayLinkElement(); + vte.Type = E_TextElementType.Symbol; + // symbols are just the unicode/rtf command, no font associated with it + // by the time it gets here... A symbol can be represented by \'xy or \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 (data[startIndex + 1] == '\'') endindx = startIndex + 3; + else endindx = data.IndexOf("?", startIndex); + if (endindx == -1) return startIndex; // not found - error + vte.Text = data.Substring(startIndex, endindx - startIndex + 1); + DisplayTextElementList.Add(vte); + if (endindx+1(); + // return unicode (symbol) font number, if it exists, to expedite finding + // the font for symbols. + int unicodeFont = -1; + int bindx = rtf.IndexOf(@"{\fonttbl"); + if (bindx < -1) return -1; + int eindx = rtf.IndexOf("}}", bindx); + // get font table string and then do regular expressions to get font number + // with font name. + string tbl = rtf.Substring(bindx + 9, eindx - bindx - 8); + tbl = tbl.Replace("{", "<"); + tbl = tbl.Replace("}", ">"); + string pat = @"(?:<\\f)([0-9]+)(?:[\S]+ )([\w ]+)"; + StringBuilder sb = new StringBuilder(); + foreach (Match m in Regex.Matches(tbl, pat)) + { + int num = Convert.ToInt32(m.Result("${1}")); + string nam = m.Result("${2}"); + dicRtfFontTable.Add(num, nam); + if ((unicodeFont == -1) && (nam == "Arial Unicode MS")) unicodeFont = num; + } + return unicodeFont; + } + private string RemoveRtfStyles(string rtf) + { + string retval = rtf; + // remove rtf commands for any styles that were added. Note that if + // the entire item has a style, and also contains 'pieces' of text with + // the same style, the underlying rtf box removes the embedded rtf commands, + // for example, if the entire step is bolded, and 'THEN' has bold on/off + // surrounding it, the rtf box removes the bold around the 'THEN' + // These remove the command with a following space or the command alone, + // either case may exist, because if there are rtf commands following the + // style command, there will be no space character following the style command. + if (((TextFont.Style & E_Style.Bold) > 0) || ((TextFont.Style & E_Style.MmBold) > 0)) + { + retval = Regex.Replace(retval, @"\\b0 ?", ""); + retval = Regex.Replace(retval, @"\\b ?",""); + } + if ((TextFont.Style & E_Style.Underline) > 0) + { + retval = Regex.Replace(retval, @"\\ulnone ?", ""); + retval = Regex.Replace(retval, @"\\ul ?", ""); + } + if ((TextFont.Style & E_Style.Italics) > 0) + { + retval = Regex.Replace(retval, @"\\i0 ?", ""); + retval = Regex.Replace(retval, @"\\i ?", ""); + } + return retval; + } + public string ReplaceRTFClause(Match m) + { + switch (m.Value[1]) + { + case 'u': + if (Regex.IsMatch(m.Value, @"\\u[0-9]+")) + return m.Value; // Special Charcaters + if (Regex.IsMatch(m.Value, @"\\ulnone")) + return m.Value; + if (Regex.IsMatch(m.Value, @"\\ul.*")) + return m.Value; // Underline + break; + case '\'': // Special Character + return m.Value; + case 'b': // Bold + return m.Value; + case 's': // sub or super.... + if (m.Value == @"\sub") return m.Value; + if (m.Value == @"\super") return m.Value; + break; + case 'n': // nosubsuper... + if (m.Value == @"\nosupersub") return m.Value; + break; + case 'i': // Italics + return m.Value; + case '{': // look for escape for curly braces: + return m.Value; + case '}': + return m.Value; + case 'v': // save link hidden info + if (m.Value == @"\v") return m.Value; // comment part of link + // end comment may end in space or may end in '\' if another rtf command, + // or may end at end of string. First check for space, keep it in string + // if it is there. + if (Regex.IsMatch(m.Value, @"\\v0 ")) + return m.Value; + if (Regex.IsMatch(m.Value, @"\\v0")) + return m.Value; + break; + case 'l': + if (m.Value == @"\line") return m.Value; + break; + case 'p': + if (m.Value == @"\par") return "\r\n"; + //if (m.Value == @"\protect") + // return m.Value; + //if (m.Value == @"\protect0") + // return m.Value; + break; + case 'f': // handle fonts separately because they may or may not have a space after them + if (m.Value[2]>='0' && m.Value[2]<='9')return m.Value; + break; + } + return "";//Strip All + } + private 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(@"\}", @"(!]"); + 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, @"\\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, @"\\[^ \\?]+", new MatchEvaluator(ReplaceRTFClause)); // take backslash xyz and evaluates them + // remove a space if there is one as the first character.. + if (retval[0]==' ')retval = retval.Remove(0, 1); + // remove \r\n at end of string - this was added with the \par at the end of string by the rtf box + if (retval.Substring(retval.Length - 2, 2) == "\r\n") retval = retval.Remove(retval.Length - 2, 2); + if (retval.Length == 0) return ""; + if (retval.Substring(retval.Length - 2, 2) == @"\v") retval = retval.Remove(retval.Length - 2, 2); + retval = RemoveRtfStyles(retval); + retval = retval.Replace(@"(![", @"\{"); + retval = retval.Replace(@"(!]", @"\}"); + 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) + { + // There were two links in a row, very special case, handle here... + //if (TwoLinksInARow) + //{ + // int tindx = txt.IndexOf(" 0) + // { + // TwoLinksInARow = false; + // return tindx; + // } + //} + 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 + 1] == '\'')) return indx; + // see if link + if (txt[indx + 1] == 'v') return indx; + // Otherwise, get next index, must have been a slash or other rtf command. + startIndex = indx + 1; + } + return -1; + } + private int DoTextElement(string text, int startIndex, int index) + { + displayTextElement vte = new displayTextElement(); + vte.Type = E_TextElementType.Text; + int len = (index == -1) ? text.Length - startIndex : index - startIndex; + vte.Text = text.Substring(startIndex, len); + DisplayTextElementList.Add(vte); + return index+1; + } + private string CreateLink(E_TextElementType type, string linktxt) + { + string retlink = ""; + if (type == E_TextElementType.ReferencedObject) + retlink = "#Link:ReferencedObject:" + linktxt; + else if (type == E_TextElementType.Transition) + retlink = "#Link:Transition:" + linktxt; + else + retlink = "#Link:TransitionRange:" + linktxt; + + return retlink; + } + private int DoLink(string text, int startIndex) + { + int retval = -1; + int fnd = text.IndexOf("#Link:", startIndex); + if (text.Substring(fnd + 6, 3) == "Ref") + retval = DoRO(text, startIndex); + else + retval = DoTran(text, startIndex); + return retval; + } + //bool TwoLinksInARow = false; + private int DoRO(string text, int index) + { + displayLinkElement vte = new displayLinkElement(); + vte.Type = E_TextElementType.ReferencedObject; + return DoLinkElements(text, index, vte); + } + private string FixTransition(string link, string text) + { + if (link.IndexOf("") != -1) return text; + int transitionID = Convert.ToInt32(link.Split(" ".ToCharArray())[1]); + // Find the transition + 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, ItemInfo.Get(ti.ToID), ti.RangeID==0?null:ItemInfo.Get(ti.RangeID)); + 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 DoLinkElements(string text, int index, displayLinkElement vte) + { + // Find the 'end comment' for the + 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; + } + + // 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); + + //// if the above is at end of string, don't bother with looking for another + //// startToken) // don't worry about two links in a row.... + //{ + 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; + + //} + //else + //{ + // TwoLinksInARow = true; + // vte.TextAndLink = text.Substring(index, startToken - index) + @"\v0 "; + // rettoken = endComment + 5; // 5 for "\v0 " + //} + if (vte.Type != E_TextElementType.ReferencedObject) vte.TextAndLink = vte.TextAndLink = vte.TextAndLink.Replace("(Resolved Transition 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 + private ReplaceStr _rs; + private string ReplaceIt(Match m) + { + string s = m.ToString(); + string t = s.Replace(_rs.ReplaceWord, _rs.ReplaceWith); + return m.ToString().Replace(_rs.ReplaceWord, _rs.ReplaceWith); + } + 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; + + // 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.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|$)"; + int cpindx = 0; + foreach (Match m in Regex.Matches(fortest, pat)) + { + res += Text.Substring(cpindx, m.Index-cpindx); + cpindx += (m.Index - cpindx); + res += rs.ReplaceWith; + cpindx += rs.ReplaceWord.Length; + } + if (cpindx < Text.Length) res += Text.Substring(cpindx, Text.Length - cpindx); + Text = res; + } + // CASEINSENSALL: Do ReplaceWords for all words that match the ReplaceWord, regardless of case + else if ((rs.Flag & E_ReplaceFlags.CaseInsensAll) > 0) + { + // not in hlp + } + // 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) + { + // not in hlp + } + else + { + string pat = @"(?<=\W|^)" + rs.ReplaceWord + @"(?=\W|$)"; + Text = Regex.Replace(Text, pat, rs.ReplaceWith); + } + + } + } + return Text; + } + #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; } + } + private string _Text; + 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; } + } + } + #endregion + +}