Files
Old/PROMS/VEPROMS.CSLA.Library/Extension/DisplayText.cs
T
2009-05-05 13:29:07 +00:00

835 lines
65 KiB
C#

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<displayTextElement> _DisplayTextElementList;਍ഀ
public List<displayTextElement> 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<int, string> _dicRtfFontTable;਍ഀ
public Dictionary<int, string> 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਍ഀ
/// <summary>਍ഀ
/// 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.਍ഀ
/// </summary>਍ഀ
public DisplayText(ItemInfo itemInfo, E_EditPrintMode epMode, E_ViewMode vwMode)਍ഀ
{਍ഀ
_MyItemInfo = itemInfo;਍ഀ
DisplayTextElementList = new List<displayTextElement>();਍ഀ
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<displayLinkElement> 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<int, ContentTransition> ctReplacements = BuildCtReplacements(itm.MyContent.ContentTransitions);਍ഀ
Dictionary<int, ContentRoUsage> 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<int, ContentRoUsage> roUsgReplacements)਍ഀ
{਍ഀ
foreach (int oldid in roUsgReplacements.Keys)਍ഀ
{਍ഀ
p = p.Replace(string.Format("<CROUSGID={0}>", oldid), roUsgReplacements[oldid].ROUsageID.ToString());਍ഀ
}਍ഀ
return p;਍ഀ
}਍ഀ
਍ഀ
private Dictionary<int, ContentRoUsage> BuildRoUsgReplacements(ContentRoUsages contentRoUsages)਍ഀ
{਍ഀ
Dictionary<int, ContentRoUsage> retval = new Dictionary<int, ContentRoUsage>();਍ഀ
foreach (ContentRoUsage rou in contentRoUsages)਍ഀ
{਍ഀ
if (rou.ROUsageID < 0) retval.Add(rou.ROUsageID, rou);਍ഀ
}਍ഀ
return retval;਍ഀ
}਍ഀ
private string FixCtReplacements(string p, Dictionary<int, ContentTransition> ctReplacements)਍ഀ
{਍ഀ
foreach (int oldid in ctReplacements.Keys)਍ഀ
{਍ഀ
p = p.Replace(string.Format("<CTID={0}>",oldid),ctReplacements[oldid].TransitionID.ToString()); ਍ഀ
}਍ഀ
return p;਍ഀ
}਍ഀ
਍ഀ
private Dictionary<int, ContentTransition> BuildCtReplacements(ContentTransitions contentTransitions)਍ഀ
{਍ഀ
Dictionary<int, ContentTransition> retval = new Dictionary<int, ContentTransition>();਍ഀ
foreach (ContentTransition ct in contentTransitions)਍ഀ
{਍ഀ
if (ct.TransitionID < 0) retval.Add(ct.TransitionID, ct);਍ഀ
}਍ഀ
return retval;਍ഀ
}਍ഀ
private void ProcessRoTranChanges(Item itm, List<displayLinkElement> 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("<NewID>", string.Format("<CROUSGID={0}>", rousg.ROUsageID));਍ഀ
l_dte.TextAndLink = l_dte.TextAndLink.Replace("<NewID>", string.Format("<CROUSGID={0}>", 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("<NewID>", string.Format("<CTID={0}>", ct.TransitionID));਍ഀ
l_dte.TextAndLink = l_dte.TextAndLink.Replace("<NewID>", string.Format("<CTID={0}>", ct.TransitionID));਍ഀ
}਍ഀ
}਍ഀ
}਍ഀ
}਍ഀ
}਍ഀ
private List<displayLinkElement> GetLinkList(List<displayTextElement> locDisplayTextElementList)਍ഀ
{਍ഀ
List<displayLinkElement> retList = new List<displayLinkElement>();਍ഀ
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><START]", @"[END>\v0 \v <START]");਍ഀ
਍ഀ
// GetFontTable returns a non-negative number font number in the਍ഀ
// font table for the unicode font, if it is used (otherwise -1)਍ഀ
//int unicodeFont = GetFontTable(rtb.Rtf);਍ഀ
਍ഀ
// strip off all rtf commands...਍ഀ
noExtraRtfStr = StripRtfCommands(noExtraRtfStr);਍ഀ
਍ഀ
// Also, set back the hard dash to a regular dash... Do this after the removal਍ഀ
// of other rtf commands though since the \u8209 was surrounded by font commands਍ഀ
// that, without there removal first, was also removing the dash. There is no਍ഀ
// space after the unicode character with a "?" ending it! and this is the only਍ഀ
// way it is entered (either thru a string replace or thru data entry).਍ഀ
noExtraRtfStr = noExtraRtfStr.Replace(@"\u8209?", @"-");਍ഀ
਍ഀ
DisplayTextElementList.Clear();਍ഀ
int startIndex = 0;਍ഀ
int index = -1;਍ഀ
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 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<data.Length && data[endindx + 1] != ' ') return endindx;਍ഀ
return endindx + 1; // add one to get past the space that was added after a symbol (to end the font cmd)਍ഀ
}਍ഀ
private int GetFontTable(string rtf)਍ഀ
{਍ഀ
dicRtfFontTable = new Dictionary<int, string>();਍ഀ
// 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<num>਍ഀ
// and links are represented by \v <START]\v0 'link text'\v #'link info'[END>\v0਍ഀ
bool done = false;਍ഀ
while (!done)਍ഀ
{਍ഀ
// There were two links in a row, very special case, handle here...਍ഀ
//if (TwoLinksInARow)਍ഀ
//{਍ഀ
// int tindx = txt.IndexOf("<START]", startIndex);਍ഀ
// if (tindx > 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("<NewID>") != -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 <START], can't count characters਍ഀ
// because there may be formatting characters such as \b or \ul before਍ഀ
// the \v0਍ഀ
int linkIndx = text.IndexOf(@"#Link", index);਍ഀ
int endStartTknIndx = text.IndexOf(@"\v0 ", index);਍ഀ
int endTextIndx = text.IndexOf(@"\v ", endStartTknIndx); // find end of text਍ഀ
vte.Text = text.Substring(endStartTknIndx + 4, endTextIndx - endStartTknIndx - 4); // 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;਍ഀ
}਍ഀ
਍ഀ
// 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 <START]਍ഀ
int endToken = (endLinkIndx == endLinkIndxE)?endLinkIndx+3:text.IndexOf(@"[END>", 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਍ഀ
//// <START]਍ഀ
//int startToken = -1;਍ഀ
//if (endLinkIndxE + 4 + 7 < text.Length) // is there enough length of text for another link?਍ഀ
// startToken = text.IndexOf(@"<START]", endLinkIndxE + 4);਍ഀ
int rettoken = 0;਍ഀ
//if (startToken == -1 || endLinkIndxV > 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਍ഀ
਍ഀ
}਍ഀ