2009-04-13 20:26:39 +00:00

822 lines
66 KiB
C#
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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);
// 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.ReferencedObject)
sret.Append(ToData_RO((displayLinkElement)vte));
else if (vte.Type == E_TextElementType.Transition || vte.Type == E_TextElementType.TransitionRange)
sret.Append(ToData_Trans((displayLinkElement)vte));
}
string modtext = sret.ToString();
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 = modtext;
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 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 "#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.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, ".*[#]Link:([A-Za-z]*):(.*)");
//_RoUsageid = m.Groups[2].Value;਍ഀ
//_Roid = m.Groups[3].Value;਍ഀ
string linkstr = m.Groups[2].Value;
if (linkstr[0] == ' ') linkstr = linkstr.Substring(1, linkstr.Length - 1);
int roidindx = linkstr.IndexOf(" ", 1)+1;
string roid = linkstr.Substring(roidindx, linkstr.Length - roidindx);
// TODO: KBR ROFST - need to add rodb ContentRoUsage cr = itm.MyContent.ContentRoUsages.Add(roid);਍ഀ
//int rou਍ഀ
//int trid = ct.TransitionID;਍ഀ
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, ".*[#]Link:([A-Za-z]*):(.*)");
string linkstr = m.Groups[2].Value;
if (linkstr[0] == ' ') linkstr = linkstr.Substring(1, linkstr.Length - 1);
int type = System.Convert.ToInt32(linkstr.Substring(0,1));
int trindx = linkstr.IndexOf(" ", 2); // start past the space after the type.਍ഀ
int trindx2 = linkstr.IndexOf(" ", trindx + 1);
if (trindx2 == -1) trindx2 = linkstr.Length - 1;
int tr1 = System.Convert.ToInt32(linkstr.Substring(trindx + 1, trindx2 - trindx));
Item itm1 = Item.Get(tr1);
int tr2 = 0;
Item itm2 = null;
if (dte.Type == E_TextElementType.TransitionRange)
{
tr2 = System.Convert.ToInt32(linkstr.Substring(trindx2,linkstr.Length-trindx2));
itm2 = Item.Get(tr2);
}
ContentTransition ct = itm.MyContent.ContentTransitions.Add(itm1, itm2);
ct.TranType = type;
int trid = 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?");
// 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);
//Console.WriteLine("StripRtf: {0}", 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. Have it with ਍ഀ
// a space & without because if it is at the end, there will be no space (leave਍ഀ
// it to rtf processing to make it more complicated)਍ഀ
noExtraRtfStr = noExtraRtfStr.Replace(@"\u8209? ", @"-");
noExtraRtfStr = noExtraRtfStr.Replace(@"\u8209?", @"-");
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)
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);
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 SaveLink(string data, int stIndex)
{
//displayLinkElement vte = new displayLinkElement();਍ഀ
// find the end of the link text, i.e. either the ending \v0 or \protect0. The win32 rtf box can਍ഀ
// put these in either order, take the lowest index.਍ഀ
int startIndex = stIndex + @"\protect ".Length;
int indx_v0 = data.IndexOf(@"\v0", startIndex);
int indx_protect0 = data.IndexOf(@"\protect0", startIndex);
int indx = indx_v0<indx_protect0?indx_v0:indx_protect0;
LinkText lt = new LinkText(data.Substring(startIndex,indx-startIndex));
displayLinkElement vte = new displayLinkElement();
vte.Type = (E_TextElementType)lt.MyParsedLinkType;
vte.Text = lt.MyValue;
vte.Link = lt.MyLink;
DisplayTextElementList.Add(vte);
return (indx_v0<indx_protect0?indx_protect0+1:indx_v0+1);
}
//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);਍ഀ
// // use '9' to get past \\protect਍ഀ
// vte.Text = data.Substring(startIndex + 9, indx - startIndex - 9);਍ഀ
// // the link is the text between the #Link... and the next '\\'.਍ഀ
// int iend = data.IndexOf("\\", indx+1);਍ഀ
// int bindx = data.IndexOf("#", indx);਍ഀ
// vte.Link = data.Substring(bindx, iend - bindx); ਍ഀ
// DisplayTextElementList.Add(vte);਍ഀ
// // unfortunately, the rtf box may add the \protect0 \v0 in either order਍ഀ
// // and with or without one or more spaces between then. The number of text਍ഀ
// // characters = 11 for \protect0\v0 - find the number of spaces between them਍ഀ
// // if any?਍ഀ
// int nsp = 0;਍ഀ
// for (int c = iend; c < iend + 11; c++) if (data[c] == ' ') nsp++;਍ഀ
// return iend + 11 + nsp;਍ഀ
//}਍ഀ
//private int SaveROTE(string data, int startIndex)਍ഀ
//{਍ഀ
// displayLinkElement vte = new displayLinkElement();਍ഀ
// vte.Type = E_TextElementType.ReferencedObject;਍ഀ
// // \protect {rovalue} \v #Link:ReferencedObject (RoUsageId) {ROID}\protect0\v0਍ഀ
// int indx = data.IndexOf("\\v #Link:ReferencedObject", startIndex);਍ഀ
// // use '9' to get past \\protect਍ഀ
// vte.Text = data.Substring(startIndex + 9, indx - startIndex - 9);਍ഀ
// // the link is the text between the #Link... and the next '\\'.਍ഀ
// int iend = data.IndexOf("\\", indx);਍ഀ
// int bindx = data.IndexOf("#", indx);਍ഀ
// vte.Link = data.Substring(bindx, iend - bindx);਍ഀ
// DisplayTextElementList.Add(vte);਍ഀ
// // unfortunately, the rtf box may add the \protect0 \v0 in either order਍ഀ
// // and with or without one or more spaces between then. The number of text਍ഀ
// // characters = 11 for \protect0\v0 - find the number of spaces between them਍ഀ
// // if any?਍ഀ
// int nsp = 0;਍ഀ
// for (int c = iend; c < iend + 11; c++) if (data[c] == ' ') nsp++;਍ഀ
// return iend + 11 + nsp;਍ഀ
//}਍ഀ
private int FindRtfChar(string text, int startIndex)
{
// look for the first 'rtf' token that represents either a link or symbol. Skip਍ഀ
// over any formatting commands..਍ഀ
bool done = false;
int indx = startIndex;
while (!done)
{
indx = text.IndexOf("\\", indx);
if (indx == -1) return indx;
if ((indx + 8) < text.Length && text.Substring(indx + 1, 7) == "protect") return indx;
if (text.Substring(indx + 1, 1) == "'") return indx;
if (text.Substring(indx + 1, 1) == "u" && text.Substring(indx + 2, 1) != "l") return indx;
indx = indx + 2; // get past \\ for next try.਍ഀ
}
return -1;
//int prindx = text.IndexOf("\\protect", startIndex);਍ഀ
//int symindx1 = text.IndexOf("\\'", startIndex);਍ഀ
//int symindx2 = text.IndexOf("\\u", startIndex);਍ഀ
//// if a 'u' is found, it can be either unicode or underline, if it's underline,਍ഀ
//// search the string for ਍ഀ
//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, @"\\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; // 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)
{
// 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, @"\\[^ \\?]+", 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);
retval = retval.Replace(@"(![", @"\{");
retval = retval.Replace(@"(!]", @"\}");
return retval;
}
private string ToData_RO(displayLinkElement vte)
{
// get past the #Link:ReferencedObject part of the link.਍ഀ
return String.Format("\x15ReferencedObject 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.Transition ? '\x252C' : '\x2566';
// depending on type, get past the #Link:Transition: or #Link:TransitionRange: part਍ഀ
// of text.਍ഀ
int indx = vte.Type == E_TextElementType.Transition ? 18 : 23;
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 = _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 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.ReferencedObject)
retlink = "#Link:ReferencedObject:" + linktxt;
else if (type == E_TextElementType.Transition)
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.ReferencedObject;
int iend = text.IndexOf(@"\v", index);
vte.Text = text.Substring(index + 1, iend - index - 1);
int istart = text.IndexOf("#", index);
iend = text.IndexOf(@"\v0", istart);
vte.Link = text.Substring(istart, iend - istart);
DisplayTextElementList.Add(vte);
return iend + 3;
}
private string FixTransition(string link, string text)
{
int transitionID = Convert.ToInt32(link.Split(" ".ToCharArray())[1]);
// Find the transition਍ഀ
foreach (TransitionInfo ti in _MyItemInfo.MyContent.ContentTransitions)
{
if (ti.TransitionID == transitionID)
{
//string path = ti.PathTo.Replace(" Section PROCEDURE STEPS ", ", ");਍ഀ
//path = path.Replace(" Section PROCEDURE STEPS", "");਍ഀ
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();
if (text[index]=='\x252C') vte.Type = E_TextElementType.Transition;
else vte.Type = E_TextElementType.TransitionRange; // '\x2566'\਍ഀ
int iend = text.IndexOf(@"\v",index);
vte.Text = text.Substring(index + 1, iend - index - 1);
int istart = text.IndexOf("#", index);
iend = text.IndexOf(@"\v0", istart);
vte.Link = text.Substring(istart, iend-istart);
vte.Text = FixTransition(vte.Link, vte.Text); // TODO: Transition text resolution?਍ഀ
DisplayTextElementList.Add(vte);
return iend + 3;
}
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)
{
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; }
}
}
#endregion
}