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)਍ഀ {਍ഀ _MyItemInfo = itemInfo;਍ഀ DisplayTextElementList = new List();਍ഀ OriginalText = itemInfo.MyContent.Text;਍ഀ TextFont = GetItemFont();਍ഀ string text = _MyItemInfo.MyContent.Text;਍ഀ ਍ഀ // if in print mode or view mode, do replace words. Only if in edit mode are replace਍ഀ // words left as is.਍ഀ _MyFormat = itemInfo.ActiveFormat;਍ഀ if (epMode == E_EditPrintMode.Print || vwMode == E_ViewMode.View) text = DoReplaceWords(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?");਍ഀ ਍ഀ // 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.਍ഀ 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);਍ഀ }਍ഀ #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 '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਍ഀ ਍ഀ }਍ഀ