736 lines
26 KiB
C#
736 lines
26 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 _itemInfo;
|
|
// 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.
|
|
#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)
|
|
{
|
|
_itemInfo = itemInfo;
|
|
DisplayTextElementList = new List<displayTextElement>();
|
|
OriginalText = itemInfo.MyContent.Text;
|
|
TextFont = GetItemFont();
|
|
string text = InsertRtfStyles();
|
|
|
|
// if in print mode or view mode, do replace words. Only if in edit mode are replace
|
|
// words left as is.
|
|
FormatInfo format = itemInfo.ActiveFormat;
|
|
if (epMode == E_EditPrintMode.PRINT || vwMode == E_ViewMode.VIEW) text = DoReplaceWords(text, format);
|
|
|
|
// 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);
|
|
|
|
// Now do any other types
|
|
if (text[index] == '\x15')
|
|
index = DoRO(text, index);
|
|
else if (text[index] == '\x252C' || text[index]=='\x2566')
|
|
index = DoTran(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.
|
|
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 if (vte.Type == E_TextElementType.RO)
|
|
sret.Append(ToData_RO((displayLinkElement)vte));
|
|
else if (vte.Type == E_TextElementType.TRANS_Single)
|
|
sret.Append(ToData_Trans((displayLinkElement)vte));
|
|
}
|
|
string modtext = sret.ToString();
|
|
if (modtext != OriginalText)
|
|
{
|
|
Item itm = _itemInfo.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 = modtext;
|
|
itm.Save();
|
|
}
|
|
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 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.RO)
|
|
{
|
|
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 "#Link:ReferencedObject:", i.e. index in link of 23
|
|
string srecid = odte.Link.Substring(23, sp-23);
|
|
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.RO || dte.Type == E_TextElementType.TRANS_Single || dte.Type == E_TextElementType.TRANS_Range)
|
|
{
|
|
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)
|
|
{
|
|
Console.WriteLine("New ro or trans");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
private List<displayLinkElement> GetLinkList(List<displayTextElement> locDisplayTextElementList)
|
|
{
|
|
List<displayLinkElement> retList = new List<displayLinkElement>();
|
|
foreach (displayTextElement vte in locDisplayTextElementList)
|
|
{
|
|
if (vte.Type == E_TextElementType.RO || vte.Type == E_TextElementType.TRANS_Range || vte.Type == E_TextElementType.TRANS_Single)
|
|
{
|
|
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)
|
|
{
|
|
// 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...
|
|
string noExtraRtfStr = StripRtfCommands(rtb.Rtf);
|
|
//Console.WriteLine("StripRtf: {0}", noExtraRtfStr);
|
|
|
|
DisplayTextElementList.Clear();
|
|
int startIndex = 0;
|
|
int index = -1;
|
|
while ((index = FindRtfChar(noExtraRtfStr, startIndex)) > -1)
|
|
{
|
|
int fndindx = -1;
|
|
// Do any 'plain' text that preceeds the token.
|
|
if (index > startIndex)
|
|
index = SaveTextElement(noExtraRtfStr, startIndex, index);
|
|
if ((fndindx = noExtraRtfStr.IndexOf("\\protect")) == index)
|
|
index = SaveLink(noExtraRtfStr, index);
|
|
else
|
|
index = SaveSymbolTE(noExtraRtfStr, index);
|
|
startIndex = index + 1;
|
|
if (startIndex >= noExtraRtfStr.Length) break;
|
|
}
|
|
// Add any remaining text.
|
|
if (startIndex < noExtraRtfStr.Length) DoTextElement(noExtraRtfStr, startIndex, index);
|
|
//Console.WriteLine(noExtraRtfStr);
|
|
}
|
|
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);
|
|
return endindx + 1;
|
|
}
|
|
private int SaveLink(string data, int startIndex)
|
|
{
|
|
displayLinkElement vte = new displayLinkElement();
|
|
|
|
// first find if RO or trans, the RO has a #R.
|
|
int istart = data.IndexOf("#Link:", startIndex);
|
|
if (data[istart + 6] == 'R') return SaveROTE(data, startIndex);
|
|
else if (data.Substring(istart+6,11) == "TransitionR")
|
|
return SaveTranTE(data, startIndex, E_TextElementType.TRANS_Range);
|
|
return SaveTranTE(data, startIndex, E_TextElementType.TRANS_Single);
|
|
}
|
|
private int SaveTranTE(string data, int startIndex, E_TextElementType type)
|
|
{
|
|
displayLinkElement vte = new displayLinkElement();
|
|
vte.Type = type;
|
|
// \protect {transition text} \v #Link:Transition(Range): 1 2 3\protect0\v0 where 1 2 3 are transition type and ids
|
|
int indx = data.IndexOf("\\v #Link:Transition", startIndex);
|
|
vte.Text = data.Substring(startIndex + 9, indx - startIndex - 9); // get past \protect
|
|
int iend = data.IndexOf("\\protect0\\v0", indx);
|
|
if (iend == -1) iend = data.IndexOf("\\v0\\protect0", indx);
|
|
// get past \v #Link:Transition or \v #Link:TransitionRange
|
|
int bindx = indx + 3;
|
|
//if (type == E_TextElementType.TRANS_Range) bindx += 5;
|
|
vte.Link = data.Substring(bindx, iend - bindx);
|
|
DisplayTextElementList.Add(vte);
|
|
return iend + 11; // get past the \protect0\vo
|
|
}
|
|
private int SaveROTE(string data, int startIndex)
|
|
{
|
|
displayLinkElement vte = new displayLinkElement();
|
|
vte.Type = E_TextElementType.RO;
|
|
// \protect {rovalue} \v #Link:ReferencedObject (RoUsageId) {ROID}\protect0\v0
|
|
int indx = data.IndexOf("\\v #Link:ReferencedObject", startIndex);
|
|
vte.Text = data.Substring(startIndex + 9, indx - startIndex - 9); // get past \protect
|
|
int iend = data.IndexOf("\\protect0\\v0", indx);
|
|
if (iend == -1) iend = data.IndexOf("\\v0\\protect0", indx);
|
|
vte.Link = data.Substring(indx + 3, iend - indx - 3); // get past \v #Link:ReferencedObject
|
|
DisplayTextElementList.Add(vte);
|
|
return iend + 11; // get past the \protect0\vo
|
|
}
|
|
private int FindRtfChar(string text, int startIndex)
|
|
{
|
|
int prindx = text.IndexOf("\\protect", startIndex);
|
|
int symindx1 = text.IndexOf("\\'", startIndex);
|
|
int symindx2 = text.IndexOf("\\u", startIndex);
|
|
if (symindx2 > -1)
|
|
{
|
|
if (text[symindx2+2] == 'l') symindx2 = -1; // don't process underlines
|
|
}
|
|
if (prindx == -1 && symindx1 == -1 && symindx2 == -1) return -1;
|
|
if (prindx == -1) prindx = text.Length + 1;
|
|
if (symindx1 == -1) symindx1 = text.Length + 1;
|
|
if (symindx2 == -1) symindx2 = text.Length + 1;
|
|
|
|
// Which token has smallest number, to determine which item is next
|
|
// in the string. If it is a symbol - see if it has a font specifier
|
|
// first.
|
|
int symindx = symindx1 < symindx2 ? symindx1 : symindx2;
|
|
int smallest = (prindx < symindx ? prindx : symindx);
|
|
return smallest;
|
|
}
|
|
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)
|
|
{
|
|
retval = Regex.Replace(retval, @"\\b0 ?", "");
|
|
retval = Regex.Replace(retval, @"\\b ?","");
|
|
}
|
|
if ((TextFont.Style & E_Style.UNDERLINE) > 0)
|
|
{
|
|
retval = Regex.Replace(retval, @"\\ul0 ?", "");
|
|
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 'v': // save link hidden info
|
|
if (m.Value == @"\v") return m.Value; // part of link
|
|
if (Regex.IsMatch(m.Value, @"\\v0"))
|
|
return m.Value; // hidden info off
|
|
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;
|
|
}
|
|
return "";//Strip All
|
|
}
|
|
private string StripRtfCommands(string rtf)
|
|
{
|
|
string retval = Regex.Replace(rtf, @"[\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, @"\\[^ \\?]+", 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);
|
|
retval = RemoveRtfStyles(retval);
|
|
|
|
return retval;
|
|
}
|
|
private string ToData_RO(displayLinkElement vte)
|
|
{
|
|
// get past the #Link:ReferencedObject part of the link.
|
|
return String.Format("\x15\\v RO\\v0 {0}\\v #{1}\\v0", vte.Text, vte.Link.Substring(23, vte.Link.Length-23));
|
|
}
|
|
private string ToData_Trans(displayLinkElement vte)
|
|
{
|
|
char trchar = vte.Type == E_TextElementType.TRANS_Single ? '\x252C' : '\x2566';
|
|
int indx = vte.Type == E_TextElementType.TRANS_Single ? 16 : 21;
|
|
return String.Format("{0}\\v TRAN\\v0 {1}\\v {2}\\v0", trchar, vte.Text, vte.Link.Substring(indx, vte.Link.Length-indx));
|
|
}
|
|
#endregion
|
|
#region StyleData
|
|
private VE_Font GetItemFont()
|
|
{
|
|
VE_Font font = null;
|
|
FormatInfo format = _itemInfo.ActiveFormat;
|
|
int type = (int)_itemInfo.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;
|
|
}
|
|
private string InsertRtfStyles()
|
|
{
|
|
StringBuilder sb = new StringBuilder(_itemInfo.MyContent.Text);
|
|
if ((TextFont.Style & E_Style.BOLD)>0)
|
|
{
|
|
sb.Insert(0, "\\b ");
|
|
sb.Append("\\b0 ");
|
|
}
|
|
if ((TextFont.Style & E_Style.UNDERLINE) > 0)
|
|
{
|
|
sb.Insert(0, "\\ul ");
|
|
sb.Append("\\ul0 ");
|
|
}
|
|
if ((TextFont.Style & E_Style.ITALICS) > 0)
|
|
{
|
|
sb.Insert(0, "\\i ");
|
|
sb.Append("\\i0 ");
|
|
}
|
|
return sb.ToString();
|
|
}
|
|
#endregion
|
|
#region DoListElements
|
|
private int FindTokenChar(string txt, int startIndex)
|
|
{
|
|
// tokens are ro, transitions and possible symbol
|
|
char[] tok = { '\x15', '\x252C', '\x2566', '\\' };
|
|
bool done = false;
|
|
// If there is only an rtf token from the indexed position on, don't return the
|
|
// IndexOfAny index value, because it will by one character past the '\' and throw
|
|
// of the return value of where in the string the text should be saved. For example
|
|
// for the string '\b text \v somevalue \v0\b0', the first time through the while
|
|
// loop has the index at the '\b' char of the b0.
|
|
//int savstartIndex = startIndex;
|
|
while (!done)
|
|
{
|
|
int indx = txt.IndexOfAny(tok, startIndex);
|
|
if (indx < 0) return indx;
|
|
if (txt[indx] != '\\') 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.
|
|
// Otherwise, get next index, must have been a slash or other rtf command.
|
|
if (((txt[indx + 1] == 'u' && txt[indx + 2] != 'l')) || (txt[indx + 1] == '\'')) return indx;
|
|
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.RO)
|
|
retlink = "#Link:ReferencedObject:" + linktxt;
|
|
else if (type == E_TextElementType.TRANS_Single)
|
|
retlink = "#Link:Transition:" + linktxt;
|
|
else
|
|
retlink = "#Link:TransitionRange:" + linktxt;
|
|
|
|
return retlink;
|
|
}
|
|
private int DoRO(string text, int index)
|
|
{
|
|
displayLinkElement vte = new displayLinkElement();
|
|
vte.Type = E_TextElementType.RO;
|
|
// ro has form \v RO\v0 9.5 psig\v #1 0001000000ec0000 \v0 - so find second
|
|
// \v0 to end the string.
|
|
int istart = text.IndexOf("\\v0",index) + 4;
|
|
int iend = text.IndexOf("\\v", istart);
|
|
vte.Text = text.Substring(istart, iend - istart);
|
|
istart = text.IndexOf("#", iend) + 1;
|
|
iend = text.IndexOf("\\v0", istart);
|
|
vte.Link = CreateLink(vte.Type, text.Substring(istart, iend - istart));
|
|
DisplayTextElementList.Add(vte);
|
|
// return the position past the end of the \v0. There is a space after the
|
|
// \v0 so account for that.
|
|
return iend + 4;
|
|
}
|
|
private string FixTransition(string link, string text)
|
|
{
|
|
int transitionID = Convert.ToInt32(link.Split(" ".ToCharArray())[1]);
|
|
// Find the transition
|
|
foreach (TransitionInfo ti in _itemInfo.MyContent.ContentTransitions)
|
|
{
|
|
if (ti.TransitionID == transitionID)
|
|
{
|
|
string path = ti.PathTo.Replace(" Section PROCEDURE STEPS ", ", ");
|
|
path = path.Replace(" Section PROCEDURE STEPS", "");
|
|
return path;
|
|
}
|
|
}
|
|
return text;
|
|
}
|
|
private int DoTran(string text,int index)
|
|
{
|
|
displayLinkElement vte = new displayLinkElement();
|
|
// transition (not range) has form \v TRAN\v0 (resolved transition text)\v type fromid toid [rangeid, if range]\v0
|
|
int istart = text.IndexOf("\\v0", index) + 4;
|
|
int iend = text.IndexOf("\\v", istart);
|
|
vte.Text = text.Substring(istart, iend - istart); // this stores the resolved transition text
|
|
istart = iend + 3; // get to transition type.
|
|
iend = text.IndexOf("\\v0", istart);
|
|
vte.Text = FixTransition(text.Substring(istart, iend - istart), vte.Text);
|
|
// Determine whether it is single or range transition. Can tell by number of spaces in
|
|
// link string.
|
|
string[] parts = text.Substring(istart, iend - istart).Split(" ".ToCharArray());
|
|
if (parts.Length == 3) vte.Type = E_TextElementType.TRANS_Single;
|
|
else vte.Type = E_TextElementType.TRANS_Range;
|
|
vte.Link = CreateLink(vte.Type, text.Substring(istart, iend - istart));
|
|
DisplayTextElementList.Add(vte);
|
|
// return the position past the end of the \v0. There is a space after the
|
|
// \v0 so account for that.
|
|
return iend + 4;
|
|
}
|
|
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 the position just past the symbol.
|
|
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, FormatInfo format)
|
|
{
|
|
ReplaceStrList rsl = format.PlantFormat.FormatData.SectData.ReplaceStrList;
|
|
foreach (ReplaceStr rs in rsl)
|
|
{
|
|
if (_itemInfo.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 (_itemInfo.IsHigh && (rs.Flag & E_ReplaceFlags.HIGH)>0) replaceit = true;
|
|
else if ((_itemInfo.IsTable || _itemInfo.IsFigure) && (rs.Flag & E_ReplaceFlags.TABLE) > 0) replaceit = true;
|
|
else if (_itemInfo.IsInRNO && (rs.Flag & E_ReplaceFlags.RNO) > 0) replaceit = true;
|
|
else if (_itemInfo.IsCaution && (rs.Flag & E_ReplaceFlags.CAUTION) > 0) replaceit = true;
|
|
else if (_itemInfo.IsNote && (rs.Flag & E_ReplaceFlags.NOTE) > 0) replaceit = true;
|
|
else if (_itemInfo.IsInFirstLevelSubStep && (rs.Flag & E_ReplaceFlags.SUBSTEP) > 0) replaceit = true;
|
|
else if (_itemInfo.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,
|
|
SYMBOL = 1,
|
|
RO = 2,
|
|
TRANS_Single = 3,
|
|
TRANS_Range = 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; }
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
}
|