835 lines
65 KiB
C#
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ഀ
|
||
ഀ
|
||
}ഀ
|