Rich 2067a6f212 Added IsTransition, AdjustStepTransitionText and BoldTransitionExceptHLS properties to PlantFormat class for VCSummer data
Added code to utilize BoldTransitionExceptHLS property for VCSummer data
Added code to reset MyGaps when changing sections for drawing centerline for VCSummer data
Added code to handle Transition Caution and Transiton Note when printing PDF for VCSummer data
Added code to handle proper incrementing for lower case roman numeral page numbering for VCSummer data
Added code to handle hard new lines in Procedure title for VCSummer data
2013-07-03 03:40:09 +00:00

1748 lines
72 KiB
C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using System.Drawing;
using VEPROMS.CSLA.Library;
namespace Volian.Controls.Library
{
public class DisplayText
{
private static readonly log4net.ILog _MyLog = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
#region Properties
private E_FieldToEdit _FieldToEdit;
public E_FieldToEdit FieldToEdit
{
get { return _FieldToEdit; }
set { _FieldToEdit = value; }
}
private ItemInfo _MyItemInfo;
private string InfoText
{
get
{
switch (FieldToEdit)
{
case E_FieldToEdit.StepText:
case E_FieldToEdit.Text:
return _MyItemInfo.MyContent.Text;
break;
case E_FieldToEdit.Number:
return _MyItemInfo.MyContent.Number;
break;
}
return string.Empty;
}
}
private Item _MyItem;
private string EditText
{
get
{
switch (FieldToEdit)
{
case E_FieldToEdit.StepText:
case E_FieldToEdit.Text:
return _MyItem.MyContent.Text;
break;
case E_FieldToEdit.Number:
return _MyItem.MyContent.Number;
break;
}
return string.Empty;
}
set
{
switch (FieldToEdit)
{
case E_FieldToEdit.StepText:
case E_FieldToEdit.Text:
_MyItem.MyContent.Text = value;
_MyItem.MyContent.UserID = Volian.Base.Library.VlnSettings.UserID;
_MyItem.MyContent.DTS = DateTime.Now;
break;
case E_FieldToEdit.Number:
_MyItem.MyContent.Number = value;
_MyItem.MyContent.UserID = Volian.Base.Library.VlnSettings.UserID;
_MyItem.MyContent.DTS = DateTime.Now;
break;
default:
break;
}
}
}
// 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; }
}
private bool PrintingSmartTemplate = false;
public string StartText;
public string OriginalText; // compare for save to see if change for links.
private FormatInfo _MyFormat;
#endregion
#region Constructors
/// <summary>
/// DisplayText constructor:
/// Creates a DisplayText object that converts the database text into rtf text
/// 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.
/// bool noEdit - flags whether to edit or not (used to set data in
/// rtb as resolved replacewords for non-active rtb.
/// E_FieldToEdit fieldToEdit - identifies the field to edit (number or text)
/// bool colorLinks - whether to add color to links
/// </summary>
public DisplayText(ItemInfo itemInfo, E_EditPrintMode epMode, E_ViewMode vwMode, bool noEdit,E_FieldToEdit fieldToEdit, bool colorLinks, string prefix, string suffix)
{
_FieldToEdit = fieldToEdit;
_MyItemInfo = itemInfo;
OriginalText = InfoText;
TextFont = itemInfo.GetItemFont();//GetItemFont();
// if in print mode, and this is the HLS of a smart template (checklist formats), add a space before and
// after the HLS text - this allows for the vertical bar characters to be added.
if (itemInfo.IsStep && itemInfo.FormatStepData.UseSmartTemplate && epMode == E_EditPrintMode.Print) Console.WriteLine("here");
string addSpace = (itemInfo.IsStep && itemInfo.FormatStepData.UseSmartTemplate && epMode == E_EditPrintMode.Print) ? " " : "";
string text = prefix + addSpace + InfoText + addSpace + suffix;
_MyFormat = itemInfo.ActiveFormat;
bool tableShouldBeOutlined = (epMode == E_EditPrintMode.Print || vwMode == E_ViewMode.View || noEdit) &&
(_FieldToEdit == E_FieldToEdit.StepText || _FieldToEdit == E_FieldToEdit.Text) &&
(!itemInfo.IsSection && !itemInfo.IsProcedure) && (itemInfo.IsTable || itemInfo.IsFigure);
bool wordsShouldBeReplaced = epMode == E_EditPrintMode.Print || vwMode == E_ViewMode.View || noEdit;
if (_MyFormat == null)
Console.WriteLine(this._MyItemInfo.MyItemInfoUnique);
bool numbersShouldBeFormated = (!_MyFormat.PlantFormat.FormatData.SectData.StepSectionData.FortranFormatNumbers && (epMode == E_EditPrintMode.Print || vwMode == E_ViewMode.View || noEdit));
int typ = ((int)itemInfo.MyContent.Type) % 10000;
bool tableHasBorder = tableShouldBeOutlined ? itemInfo.ActiveFormat.PlantFormat.FormatData.StepDataList[typ].Type.IndexOf(@"Borderless") < 0 : false;
bool ROsShouldBeAdjusted = wordsShouldBeReplaced; // same logical value
if (epMode == E_EditPrintMode.Print && _MyItemInfo.IsStep)
{
if (_MyItemInfo.FormatStepData.UseSmartTemplate)
{
// Add 2 spaces before and 1 after if there is prefix so that wrapping in RTB accounts for vertical
// lines (the 2 spaces after the first "\par " command and 1 space before 2nd "\par"). Tried other
// combinations that did not work.
if (_MyItemInfo.FormatStepData.Prefix != null && _MyItemInfo.FormatStepData.Prefix != "")
text = !_MyItemInfo.FormatStepData.Font.FontIsProportional() ? ReplaceLinesWithUnicode(_MyItemInfo.FormatStepData.Prefix) + @"\par " + text + @"\par " :
@"\par " + text + @"\par ";
if (_MyItemInfo.FormatStepData.Suffix != null && _MyItemInfo.FormatStepData.Suffix != "")
text = text + (!_MyItemInfo.FormatStepData.Font.FontIsProportional() ? ReplaceLinesWithUnicode(_MyItemInfo.FormatStepData.Suffix) :
@"\par\par\par ");
}
}
text = CreateRtf(colorLinks, text, tableShouldBeOutlined, wordsShouldBeReplaced, numbersShouldBeFormated, tableHasBorder, ROsShouldBeAdjusted);
StartText = text;
}
private string ReplaceLinesWithUnicode(string text)
{
text = text.Replace("\x2500", @"\u9472?"); // Horizontal
text = text.Replace("\x2502", @"\u9474?"); // Vertical
text = text.Replace("\x2514", @"\u9492?"); // Bottom Left Corner
text = text.Replace("\x2518", @"\u9496?"); // Bottom Right Corner
text = text.Replace("\x2534", @"\u9524?"); // Bottom Tee
text = text.Replace("\x250c", @"\u9484?"); // Upper Left Corner
text = text.Replace("\x251c", @"\u9500?"); // Left Tee
text = text.Replace("\x2510", @"\u9488?"); // Upper Right Corner
text = text.Replace("\x252c", @"\u9516?"); // Top Tee
text = text.Replace("\x2524", @"\u9508?"); // Right Tee
text = text.Replace("\x253c", @"\u9532?"); // Plus
return text;
}
public DisplayText(string text, VE_Font vFont, bool colorLinks)
{
TextFont = vFont;
StartText = CreateRtf(colorLinks, text, false, false, false, false, false);
}
public DisplayText(ItemInfo itemInfo, string text, bool colorLinks)
{
_FieldToEdit = E_FieldToEdit.Text;
_MyItemInfo = itemInfo;
OriginalText = text;
TextFont = itemInfo.GetItemFont();
_MyFormat = itemInfo.ActiveFormat;
bool wordsShouldBeReplaced = true;
bool numbersShouldBeFormated = !_MyFormat.PlantFormat.FormatData.SectData.StepSectionData.FortranFormatNumbers;
int typ = ((int)itemInfo.MyContent.Type) % 10000;
bool ROsShouldBeAdjusted = wordsShouldBeReplaced; // same logical value
text = CreateRtf(colorLinks, text, false, wordsShouldBeReplaced, numbersShouldBeFormated, false, ROsShouldBeAdjusted);
StartText = text;
}
private string CreateRtf(bool colorLinks, string text, bool tableShouldBeOutlined, bool wordsShouldBeReplaced, bool numbersShouldBeFormated, bool tableHasBorder, bool ROsShouldBeAdjusted)
{
// Adjust RO display
if (ROsShouldBeAdjusted)
{
try // Added try/catch because an unresolved RO Link was causing a failure.
{
text = DoROAdjustments(text);
}
catch (Exception ex)
{
if (_MyItemInfo != null)
{
_MyLog.ErrorFormat("<<< ERROR >>> Error doing DoROAdjustments\r\n==>'RO Adjustments Error',{0},'{1}','{2}','{3}'"
, _MyItemInfo.ItemID, _MyItemInfo.MyDocVersion.MyFolder.Name, _MyItemInfo.ShortPath, ex.Message);
}
else
_MyLog.Error("DisplayText.CreateRTF Error doing DoROAdjustments", ex);
}
}
// if in print mode, view mode, or non-active richtextbox do replace words. Only if in
// actual edit mode are replace words left as is.
if (wordsShouldBeReplaced)
text = DoReplaceWords2(text);
if (_MyItemInfo != null)
{
text = DoSearchAndReplace(text, "<U-ID>", _MyItemInfo.MyDocVersion.DocVersionConfig.Unit_ID);
text = text.Replace(@"<S\u8209?ID>", _MyItemInfo.MyDocVersion.DocVersionConfig.Unit_ProcedureSetID);
text = text.Replace("<U>", _MyItemInfo.MyDocVersion.DocVersionConfig.Unit_Number);
}
// Adjust RO display
if (ROsShouldBeAdjusted)
text = DoTransitionAdjustments(text, _MyItemInfo.ActiveFormat.PlantFormat.FormatData.TransData.BoldTransition || (_MyItemInfo.ActiveFormat.PlantFormat.FormatData.TransData.BoldTransitionExceptHLS && !_MyItemInfo.IsHigh));
// add colors around links:
if (colorLinks)
text = DoColorLinks(text);
//Console.WriteLine(text);
// adjust formatting of exponents
if (numbersShouldBeFormated)
text = DoFortranFormat(text);
// determine whether the table/figure should be outlined:
if (tableShouldBeOutlined)
{
OutlineRTFTable myTable = new OutlineRTFTable(text, tableHasBorder);
// if a table has internal line draw characters, we may have to do part of 'OutlineTable'
// to convert dashes and vertical bars to line draw characters.
if (tableHasBorder) myTable.OutlineTable();
text = myTable.Lines.ToString();
}
// if we're working with a grid it won't go thru here.
if (!text.StartsWith(@"{\rtf"))
{
// 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?");
text = text.Replace("\r\n", @"\par ");
//if (text.IndexOf(@"\line") > -1)
// MessageBox.Show("Found rtf line");
text = text.Replace(@"\line", @"\par");
// Now put symbol (for fixed fonts) or unicode font (proportional) around symbols
// These fonts are VESymbFix & Arial Unicode MS respectively, and the font table
// is actually defined in the StepRTB code.
int indxsym = NextUnicode(text, 0);//text.IndexOf(@"\u");
while (indxsym != -1)
{
int incrindx = 3;
if (text[indxsym + 2] != 'l')
{
text = text.Insert(indxsym, @"\f1 ");
int indxendsym = text.IndexOfAny(@"\ ?".ToCharArray(), indxsym + 5);
if (indxendsym == -1) // must be end of line:
text = text.Insert(text.Length - 1, @"\f0 ");
else
{
if (text[indxendsym] == '?') indxendsym++;
text = text.Insert(indxendsym, @"\f0 "); // TODO: do I need a space??
}
incrindx = 5;
}
indxsym = NextUnicode(text, indxsym + incrindx);//text.IndexOf(@"\u", indxsym + incrindx);
}
}
return text;
}
private string DoSearchAndReplace(string text, string find, string replace)
{
return text.Replace(find, replace);
}
private static string DoColorLinks(string text)
{
string origtext = text;
text = Regex.Replace(text, @"(<START\](\\[^v \\]+)*\\v0)((?= |\\))", @"$1\cf1");
//text = Regex.Replace(text, @"<START]\b0\v0 ", @"<START]\b0\v0\cf1 ");
int indxcf = text.IndexOf(@"\v0\cf1");
int indxend = 0;
try
{
while (indxcf != -1)
{
indxcf += 4;
indxend = text.IndexOf(@"\v", indxcf);
if (indxend > -1)
{
text = text.Insert(indxend, @"\cf0");
indxcf = text.IndexOf(@"\v0\cf1", indxend);
}
else
{
indxcf = -1;
_MyLog.WarnFormat("DisplayText.DoColorLinks Failed\r\norgitext:'{0}'\r\ntext'{1}'", origtext, text);
}
}
}
catch (Exception ex)
{
_MyLog.WarnFormat("DisplayText.DoColorLinks Failed\r\norgitext:'{0}'\r\ntext'{1}'", origtext, text);
}
return text;
}
private int NextUnicode(string text, int offset)
{
// Skip Hard Spaces
Match m = Regex.Match(text.Substring(offset), @"\\u[0-9a-fA-F]");
while(m.Success && text.Substring(offset+m.Index).StartsWith(@"\u160"))
{
offset += m.Index + 5;
m = Regex.Match(text.Substring(offset), @"\\u[0-9a-fA-F]");
}
if (m.Success)
return m.Index + offset;
return -1;
}
private string DoROAdjustments(string text)
{
Regex regRefObj = new Regex(@"\#Link\:ReferencedObject:([0-9]*) ([0-9a-zA-Z]*) ([0-9]*)", RegexOptions.Singleline);
string strippedText = StaticStripRtfCommands(text);
// (\\[^v \\]+)* --> look for any rtf commands (first part of lookFor)
// \\v0 --> end of comment
// (\\[^v \\]+)* --> more rtf commands ended by a space
// (.*?) --> smallest anything to that matches this based on what's next
// (\\[^v' \\]+)* --> look for rtf commands but exclude \' before the \v
// \\v(\\[^v \\]+)* --> look for rtf commands after the \v
// if it turns out that if ro's have any embedded unicode characters this needs expanded, such as /u8209? (hard hyphen)
string lookFor = string.Format(@"<START\](\\[^v \\]+)*\\v0(\\[^v \\]+)* (.*?)(\\[^v'? \\]+)*\\v(\\[^v \\]+)* #Link:(ReferencedObject|Transition[^:]*?):.*?\[END>");
MatchCollection matches = Regex.Matches(text, lookFor);
for (int i = matches.Count - 1; i >= 0; i--)
{
Match m = matches[i];
if (m != null && m.Groups.Count > 6 && m.Groups[6].ToString() == "ReferencedObject")
{
System.Text.RegularExpressions.Group g = m.Groups[3];
string beforeRO = StaticStripRtfCommands(text.Substring(0, g.Index));
string afterRO = StaticStripRtfCommands(text.Substring(g.Index + g.Length));
string newvalue = DoROFormatFlags(g.ToString(), beforeRO, afterRO);
newvalue = DoROReplaceWords(_MyFormat.PlantFormat.FormatData.SectData.ReplaceStrList, newvalue, _MyItemInfo.IsHigh);
Match myMatch = regRefObj.Match(m.ToString());
int dbid = System.Convert.ToInt32(myMatch.Groups[2].Value.Substring(0, 4), 16);
int rodbid = int.Parse(myMatch.Groups[3].Value);
ROFstInfo myROFst = _MyItemInfo.MyDocVersion.GetROFst(rodbid);
if (myROFst.IsSetpointDB(dbid)) newvalue = ReplaceSpaceWithHardspace(newvalue);
if (g.ToString() != newvalue)
text = text.Substring(0, g.Index) + newvalue + text.Substring(g.Index + g.Length);
}
}
return text;
}
private string DoROReplaceWords(ReplaceStrList replaceStrList, string newvalue, bool isHigh)
{
foreach (ReplaceStr rs in replaceStrList)
{
if (((rs.Flag & E_ReplaceFlags.Setpoint) > 0) || (isHigh && (rs.Flag & E_ReplaceFlags.HLSSetpnt) > 0))
{
newvalue = newvalue.Replace(rs.ReplaceWord, rs.ReplaceWith);
}
}
return newvalue;
}
// Replace spaces with hardspaces, but DO NOT replace the end of an Rtf Command with a hardspace
private string ReplaceSpaceWithHardspace(string newvalue)
{
string oldvalue = newvalue;
int spindx = newvalue.IndexOf(" ");
int lstindx = -1;
while (spindx >= 0)
{
if (!EndsRtfCommand(newvalue, spindx, lstindx))
{
newvalue = newvalue.Remove(spindx, 1);
newvalue = newvalue.Insert(spindx, @"\u160?");
}
lstindx = spindx;
spindx = (spindx + 1 >= newvalue.Length)?spindx = -1: newvalue.IndexOf(" ", spindx+1);
}
return newvalue;
}
private bool EndsRtfCommand(string str, int spindx, int previndx)
{
// get text from last space to current, or from beginning of string to current:
int start = previndx < 0 ? 0 : previndx+1;
string substring = str.Substring(start, spindx-start);
if (substring.Contains(@"\"))
{
// is space ending an rtf command.
int startCmd = substring.LastIndexOf(@"\");
string Cmd = substring.Substring(startCmd);
char tst = Cmd[1];
// consider rtf commands up/dn/b/ul/i
if (tst == 'u' || tst == 'd' || tst == 'b' || tst == 'u' || tst == 'i') return true;
}
return false;
}
private string DoTransitionAdjustments(string text, bool boldTran)
{
string strippedText = StaticStripRtfCommands(text);
string lookFor = string.Format(@"<START\](\\[^v \\]+)*\\v0(\\[^v \\]+)* (.*?)(\\[^v \\u]+)*\\v(\\[^v \\]+)* #Link:(ReferencedObject|Transition[^:]*?):[0-9]* ([0-9]*).*?\[END>");
MatchCollection matches = Regex.Matches(text, lookFor);
if (matches.Count == 0) return text;
string retstr = text;
for (int i = matches.Count - 1; i >= 0; i--)
{
Match m = matches[i];
// if this transition text already has a hard space, don't add another.
if (m.Groups[3].Value.Contains("\xA0")) continue;
// if the transition text does not start with a digit, don't add the hardspace.
//if (!Char.IsDigit(m.Groups[3].Value[0])) continue;
if (m != null && m.Groups.Count > 7 && m.Groups[6].ToString().StartsWith("Transition"))
{
if (m.Groups[7].Value != "") // && StepTransition(int.Parse(m.Groups[7].Value)))
{
System.Text.RegularExpressions.Group g = m.Groups[3];
string beforeTran = retstr.Substring(0, g.Index);
string afterTran = retstr.Substring(g.Index + g.Length);
// if replacing text in the 'beforeTran' string, then do it here,
// i.e. there is a format flag 'BeforeTrans' that bolds text before the transition
// (in wst formats).
beforeTran = DoBeforeTransFlagSupport(beforeTran, _MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.ReplaceStrList);
string newvalue = g.ToString();
// if this is a 'step transition' type, i.e. includes a step number, in addition to other replacements,
// we want to change a space to a hardspace.
if (StepTransition(int.Parse(m.Groups[7].Value)))
{
int indexLastSpace = newvalue.LastIndexOf(' ');
if (indexLastSpace >= 0)
// Use a "\x1" as a token to replace later. Insert the unicode char, whose length is
// more than 1 character was throwing of the regexp Matches index, so that the resulting
// string may have been incorrect.
retstr = beforeTran + (boldTran ? @"\b " : null) + newvalue.Substring(0, indexLastSpace) + "\x1" + newvalue.Substring(indexLastSpace + 1) + (boldTran ? @"\b0" : null) + afterTran;
else
if (beforeTran.EndsWith(" "))
retstr = ReplaceLastSpaceWithHardSpace(beforeTran) + (boldTran ? @"\b " : null) + newvalue + (boldTran ? @"\b0" : null) + afterTran;
else
Console.Write("");// Don't know where to put the Hard Space
}
else if (boldTran)
{
retstr = beforeTran + @"\b " + newvalue + @"\b0" + afterTran;
}
}
}
}
return retstr.Replace("\x1", @"\u160?");
}
private string DoBeforeTransFlagSupport(string beforeTran, ReplaceStrList replaceStrList)
{
foreach (ReplaceStr repstr in replaceStrList)
{
if ((repstr.Flag & E_ReplaceFlags.BeforeTrans) > 0)
{
// the beforeTran string ends with the string that starts the transition comment, i.e.
// '\\v <START] \\v0 '. The replace word string needs to be before this:
int indx = beforeTran.LastIndexOf(@"\v <START]\v0");
if (indx > -1)
{
string findit = beforeTran.Substring(0, beforeTran.LastIndexOf(@"\v <START]\v0"));
if (findit != null && findit.Trim().ToUpper().EndsWith(repstr.ReplaceWord.ToUpper()))
{
int rindx = findit.Trim().ToUpper().IndexOf(repstr.ReplaceWord.ToUpper());
// don't replace string because case of words may be match replace with string.
beforeTran = findit.Substring(0, rindx) + @"\b " + findit.Substring(rindx) + @"\b0" + beforeTran.Substring(indx);
return beforeTran;
}
}
}
}
return beforeTran;
}
private string ReplaceLastSpaceWithHardSpace(string str)
{
int ind =str.LastIndexOf("<START]");
ind = str.LastIndexOf(@"\", ind);
while (ind > 0 && str[ind - 1] != ' ')
{
if (ind > 5 && str.Substring(0, ind).EndsWith(@"\u160?") || str.Substring(0, ind).ToLower().EndsWith(@"\'a0"))
return str;//Already has a Hard Space
ind = str.LastIndexOf(@"\", ind - 1);
}
// If the previous character is a comma or a space then don't add a Hard Space
if (ind > 1 && (str[ind - 2] == ',' || str[ind - 2] == ' ')) return str;
if (ind <= 0) return str;
// replace with a 'token' "\x1" instead of a hardspace unicode char. When using a hardspace unicode
// char the string length/contents was thrown off so that the calling method's processing was off
// in terms of regexp matches in string.
return str.Substring(0, ind - 1) + "\x1" + str.Substring(ind);
}
private bool StepTransition(int TransId)
{
if (_MyItemInfo == null) return false;
_MyItemInfo.MyContent.RefreshContentTransitions();
foreach (TransitionInfo trans in _MyItemInfo.MyContent.ContentTransitions)
if (trans.TransitionID == TransId)
return trans.MyItemToID.IsStep;
return false;
}
private string DoFortranFormat(string text)
{
if (text.IndexOf(@".E") < 0) return text;
// Look for text as n.Ey, where n can be null or a number, and y can be
// positive or negative. This translates into nx10x10y where y is
// superscripted. For example, .E3 -> x103 where 3 is superscripted
// and 10.E5 -> 10x10-5 where 5 is superscripted
string pat = @"(\d*).E([+-]*\d+)";
string retstr = text;
// for each one that needs translated:
foreach (Match m in Regex.Matches(text, pat))
{
string fnum = m.Groups[1].Value;
string supnum = m.Groups[2].Value;
string newstr = string.Format(@"{0}x10\up2 {1}\up0 ", fnum, supnum);
retstr = retstr.Replace(m.Value, newstr);
}
return retstr;
}
#endregion
#region SaveData
public bool Save(RichTextBox rtb)
{
//int savSelStart = rtb.SelectionStart;
try
{
//FormatInfo formatInfo = _MyItemInfo.ActiveFormat;
using (_MyItem = _MyItemInfo.Get())
{
// The following was added to support transitions to un-numbered steps
if (_MyItemInfo.NewTransToUnNumberedItem && rtb.Text.Contains("<NewID>"))
{
ItemAnnotation ia = _MyItem.ItemAnnotations.Add(AnnotationType.GetByName("Verification Required"));
ia.SearchText = "Transition to Un-Numbered Step";
_MyItemInfo.NewTransToUnNumberedItem = false;
}
// check for different text, i.e. text from this itm doesn't match
// original text, a change occurred in database, but not from this user.
if (OriginalText != EditText)
{
Console.WriteLine("Save Failed because text changed outside of this edit session.");
return false;
}
string modtext = RtfToDbText(rtb.Rtf).Replace("<BackSlash>", "\\\\");
// if there are links, we'll need to do extra processing to see if
// there were additions, deletions or modifications.
bool haslinks = ((modtext.IndexOf(@"<START]") > -1) || (OriginalText != null && OriginalText != "" && OriginalText.IndexOf(@"<START]") > -1));
if (haslinks)
{
// Get all links in original list
RtfToDisplayTextElements(OriginalText);
List<displayLinkElement> origList = GetLinkList(DisplayTextElementList);
// now get new text into displaytext elements for comparison for links:
RtfToDisplayTextElements(modtext);
// Compare ro/transition lists and delete or add any to the item for any ros/transitions that have been
// added/deleted or modified.
ProcessRoTranChanges(_MyItem, origList);
EditText = DteToString();
// if new transitions/ros, we need to 'fix' the string in the embedded link to contain the
// transition or usage record.
Dictionary<int, ContentTransition> ctReplacements = BuildCtReplacements(_MyItem.MyContent.ContentTransitions);
Dictionary<int, ContentRoUsage> roUsgReplacements = BuildRoUsgReplacements(_MyItem.MyContent.ContentRoUsages);
_MyItem.DTS = DateTime.Now;
_MyItem.UserID = Volian.Base.Library.VlnSettings.UserID;
// Do the Save once rather than multiple times
_MyItem.Save();
if (ctReplacements.Count > 0)
{
EditText = FixCtReplacements(EditText, ctReplacements);
// Replace Transition Text
foreach (ContentTransition ct in ctReplacements.Values)
using (TransitionInfo tran = TransitionInfo.Get(ct.TransitionID))
_MyItem.MyContent.FixTransitionText(tran);
_MyItem.Save();
}
if (roUsgReplacements.Count > 0)
{
EditText = FixRoUsgReplacements(EditText, roUsgReplacements);
_MyItem.Save();
}
modtext = EditText;
}
else
{
EditText = modtext;
foreach (Csla.Validation.BrokenRule br in _MyItem.MyContent.BrokenRulesCollection)
{
Console.WriteLine("{0} - {1}", br.Property, br.Description);
}
// Don't update the DTS or User for Text Changes
//_MyItem.DTS = DateTime.Now;
//_MyItem.UserID = Volian.Base.Library.VlnSettings.UserID;
_MyItem.Save();
}
_MyItem = null;
OriginalText = modtext;
}
}
catch (Exception ex)
{
Console.WriteLine("DisplayText Save Failed with error: {0} - {1}\r\n{2}", ex.GetType().Name, ex.Message, ex.StackTrace);
return false;
}
//rtb.SelectionStart = savSelStart;
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.GetJustRoDb(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[2] is token for tranid
int tr2 = tr1;
if(tparts.Length > 3)
tr2 = System.Convert.ToInt32(tparts[3]); // tparts[3] is token for rangeid
bool dispose1 = false;
Item itm1 = null;
bool dispose2 = false;
Item itm2 = null;
if (itm.ItemID == tr1)
itm1 = itm; // a transition that points to itself should not dispose
else
{
dispose1 = true;
itm1 = Item.Get(tr1);
}
if (itm.ItemID == tr2)
itm2 = itm; // a transition that points to itself should not dispose
else if (tr1 == tr2)
itm2 = itm1; // if both destinations are the same only dispose the first one
else
{
dispose2 = true;
itm2 = Item.Get(tr2);
}
ContentTransition ct = itm.MyContent.ContentTransitions.Add(itm1, itm2);
//Console.WriteLine("CT {0},{1},{2},{3}", ct.TransitionID, itm.ItemID, itm.MyContent.MyContentUnique, itm.MyContent.ContentTransitions.Count);
ct.TranType = type;
if (dte.Type == E_TextElementType.Transition)
ct.IsRange = 0;
else if (tr1 != tr2)
ct.IsRange = 1;
else
ct.IsRange = 2;
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));
if (dispose2) itm2.Dispose();
if (dispose1) itm1.Dispose();
}
}
}
}
}
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(string text)
{
// get original text into displaytext elements for comparison for links:
if (DisplayTextElementList == null)
DisplayTextElementList = new List<displayTextElement>();
else
DisplayTextElementList.Clear();
if (text == null || text == "") return;
string noExtraRtfStr = text;
int startIndex = 0;
int index = -1;
noExtraRtfStr = noExtraRtfStr.Replace(@"><", @">\v0 \v <");
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 string RtfToDbText(string text)
{
// 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 = text.Replace(@"\~", @"\u160?");
noExtraRtfStr = noExtraRtfStr.Replace(@"\'a0", @"\u160?");
// Check for two links in a row & if found, add separating rtf comment
// commands (these get removed in the richtextbox:
// RHM 20100303 Not sure why this is here. The RichTextBox will always remove it.
//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);
// the indent character was translated in the richtextbox, change it back:
if (noExtraRtfStr.IndexOf(@"\'05") > -1) noExtraRtfStr = noExtraRtfStr.Replace(@"\'05", "\x05");
return noExtraRtfStr;
}
public static string StaticReplaceRTFClause(Match m)
{
try
{
string token = m.Groups[1].Value;
switch (token[1])
{
case '\\':
return token;
case 'u':
if (Regex.IsMatch(token, @"^\\u[0-9]+$"))
return token; // Special Charcaters
if (Regex.IsMatch(token, @"^\\ulnone ?$"))
return token;
if (Regex.IsMatch(token, @"^\\ul.*$"))
return token; // Underline
if (Regex.IsMatch(token, @"^\\up[0-9] ?$"))
return token; // shift up (superscript)
break;
case 'd':
if (Regex.IsMatch(token, @"^\\dn[0-9] ?$"))
return token; // shift down (subscript)
break;
case '\'': // Special Character
return token;
case 'b': // Bold
return token;
case 'i': // Italics
return token;
case '{': // look for escape for curly braces:
return token;
case '}':
return token;
case 'v': // save link hidden info
if (Regex.IsMatch(token, @"^\\v0? ?$")) return token; // 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(token, @"\\v0 "))
// return token;
//if (Regex.IsMatch(token, @"\\v0"))
// return token;
break;
case 'l':
if (Regex.IsMatch(token, @"^\\line ?$")) return token;
break;
case 'p':
if (Regex.IsMatch(token, @"^\\par ?$")) return "\r\n";
//if (token == @"\protect")
// return token;
//if (token == @"\protect0")
// return token;
//if (token.Length >= 6 && token.Substring(0, 6) == "\\par\r\n") return token.Replace("\r\n", " ");
break;
//case 'f': // handle fonts separately because they may or may not have a space after them
// if (token[2] >= '0' && token[2] <= '9') return token;
// break;
}
}
catch (Exception ex)
{
Console.WriteLine("StaticReplaceRTFClause {0} - {1}", ex.GetType().Name, ex.Message);
}
return "";//Strip All
}
public 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(@"\}", @"(!]");
// remove carriage return/newlines after \par commands (these are introduced by rtb
// for hard returns, goes into rtb as \par and comes out as \par\r\n):
retval = Regex.Replace(retval, @"\\par\r\n(?!\\)", "\\par ");
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, @"(\\[^' \\?\r\n\t]+)(?=\\)", "$1 "); // add space after token if followed by token
retval = Regex.Replace(retval, @"(\\[^' \\?\r\n\t]+ )", new MatchEvaluator(StaticReplaceRTFClause)); // take backslash xyz and evaluates them
retval = Regex.Replace(retval, @"(\\[^' \\?\r\n\t]+) (?=\\)", "$1"); // remove space between tokens
retval = Regex.Replace(retval, @"(\\[^' \\?\r\n\t]+) (?=\r\n)", "$1"); // remove space before /r/n
// remove \r\n at end of string if the string has 2 or more characters
if (retval.EndsWith("\r\n")) retval = retval.Remove(retval.Length - 2, 2);
if (retval.Length == 0) return "";
if (retval.EndsWith(@"\v")) retval = retval.Remove(retval.Length - 2, 2);
retval = _MyItemInfo.RemoveRtfStyles(retval); // RemoveRtfStyles(retval);
retval = retval.Replace(@"(![", @"\{");
retval = retval.Replace(@"(!]", @"\}");
retval = retval.TrimEnd(' ');
return retval;
}
// This is used in the DataLoader
public static string StaticStripRtfCommands(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(@"\}", @"(!]");
// 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?
retval = retval.Replace(@"\~", @"\u160?");
// remove carriage return/newlines after \par commands (these are introduced by rtb
// for hard returns, goes into rtb as \par and comes out as \par\r\n):
retval = Regex.Replace(retval, @"\\par\r\n(?!\\)", "\\par ");
//retval = Regex.Replace(retval, @"\\par\r\n(?=\\)", "\\par");
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, @"(\\[^ \\?\r\n\t]+)\\f[0-9] ", "$1 "); // remove font command - if next to another command, keep other command and space
// OLD: The following two lines are replaced by the more generic replace above.
//retval = Regex.Replace(retval, @"\\v\\f[0-9] ", "\\v "); // remove font command - if next to Comment keep space
//retval = Regex.Replace(retval, @"\\line\\f[0-9] ", "\\line "); // remove font command - if next to Line keep space
//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, @"\\par ", "\r\n");
retval = Regex.Replace(retval, @"(\\[^' \\?\r\n\t]+)(?=\\)", "$1 "); // add space after token if followed by token
//retval = Regex.Replace(retval, @"(\\[^ \\?\r\n\t]+)(\\)", "$1 $2"); // take backslash xyz and evaluates them
retval = Regex.Replace(retval, @"(\\[^ \\?\r\n\t]+ )", new MatchEvaluator(StaticReplaceRTFClause)); // take backslash xyz and evaluates them
retval = Regex.Replace(retval, @"(\\[^ \\?\r\n\t]+) (?=\\)", "$1"); // remove space between tokens
retval = Regex.Replace(retval, @"(\\[^ \\?\r\n\t]+) (?=\r\n)", "$1"); // remove space before /r/n
// remove a space if there is one as the first character or the last character
//if (retval[0] == ' ') retval = retval.Remove(0, 1);
//retval = retval.TrimEnd(' ');
// remove \r\n at end of string if the string has 2 or more characters
if (retval.Length > 1 && retval.Substring(retval.Length - 2, 2) == "\r\n") retval = retval.Remove(retval.Length - 2, 2);
// remove \par at end of string if the string has 4 or more characters
//if (retval.Length > 3 && retval.Substring(retval.Length - 4, 4) == @"\par") retval = retval.Remove(retval.Length - 4, 4);
// remove a space following \r\n
//retval = Regex.Replace(retval, "\r\n ", "\r\n");
////if there are still spaces following \r\n, then probable in a table - we need to put the space back
//retval = Regex.Replace(retval, "\r\n ", "\r\n ");
if (retval.Length == 0) return "";
if (retval.Length > 1 && retval.Substring(retval.Length - 2, 2) == @"\v") retval = retval.Remove(retval.Length - 2, 2);
//retval = RemoveRtfStyles(retval);
//if (itmInfo != null)
// retval = StaticRemoveRtfStyles(retval, itmInfo);
retval = retval.Replace(@"(![", @"\{");
retval = retval.Replace(@"(!]", @"\}");
retval = retval.TrimEnd(' ');
// the indent character was translated in the richtextbox, change it back:
if (retval.IndexOf(@"\'05") > -1) retval = retval.Replace(@"\'05", "\x05");
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)
{
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 + 2] !='p')) || (txt[indx + 1] == '\'')) return indx;
// see if link
if (txt[indx + 1] == 'v') return indx; //TODO - should have <START here too!
// 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 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;
}
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)
{
// TODO: RHM 20100310
_MyItemInfo.MyContent.RefreshContentTransitions();
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, ti.TranType, ti.MyItemToID, ti.MyItemRangeID);
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 GetLastLower(string stepText)
//{
// // TO DO: need to check AlwaysUpperCase format setting - this was not yet converted as of 17Jun2010
// // if (AlwaysUpperCase[steptype]) return (stepText.Length-1);
// int idx = stepText.Length - 1;
// while (idx >= 0 && !(char.IsLower(stepText[idx]) && stepText[idx] != 's')) idx--;
// if (idx < 0) idx = stepText.Length - 1; // entire string is uppercased set return value to end of string
// return idx;
//}
//private bool IsSpaceOrHardSpace(char ch)
//{
// string spaces = @" \u160?";
// return (spaces.IndexOf(ch) >= 0);
//}
private string DoROFormatFlags(string roText, string beforeRO, string afterRO)
{
string rtnstr = roText;
// The RO text is being changed to match it's context. Since it is changed in reverse order, the text before the RO
// should ignore other RO text.
beforeRO = Regex.Replace(beforeRO, @"(\\[^v \\]+)*\\v0[^v\\]*\\v(\\[^v \\]+)* #Link:Refer", ""); // Remove any RO Values.
beforeRO = Regex.Replace(beforeRO, @"(\\[^v \\]+)*\\v(\\[^v \\]+)* .*?\\v0(\\[^v \\]+)*( |$)", ""); // Remove Comments
afterRO = Regex.Replace(afterRO, @"(\\[^v \\]+)*\\v(\\[^v \\]+)* .*?\\v0(\\[^v \\]+)*( |$)", ""); // Remove Comments
// Underline all ROs, values and Units
if (_MyItemInfo.ActiveFormat.PlantFormat.FormatData.ROData.UnderlineRo)
{
// TO DO: Need to check if step text is already underlined
rtnstr = @"\ul " + rtnstr + @"\ulnone ";
}
// UpcaseAllRoUnits - Uppercases ALL ROs units everywhere.
if (_MyItemInfo.ActiveFormat.PlantFormat.FormatData.ROData.UpcaseAllRoUnits)
return UpperCaseUnits(rtnstr);
//Forces the units for a RO to be uppercased for high level steps
if (_MyItemInfo.ActiveFormat.PlantFormat.FormatData.ROData.CapHighRo &&_MyItemInfo.IsHigh)
return UpperCaseUnits(rtnstr);
// Caps ROs anywhere if no lower case text follows
// and an upper case letter immediately precedes the RO.
if (_MyItemInfo.ActiveFormat.PlantFormat.FormatData.ROData.CapRoIfLastLower && !Regex.IsMatch(afterRO,"[a-z]") && char.IsUpper(LastAlpha(beforeRO)))
{
//int indx = startLinkText - 1;
//int indx2 = endLinkText + 1;
//while (indx > 0 && !IsSpaceOrHardSpace(stepText[indx])) indx--; // find character before RO
//while (indx2 <= stepText.Length && !IsSpaceOrHardSpace(stepText[indx2])) indx2++; // find character after RO
//if (indx >= 0 && char.IsUpper(stepText[indx]) && indx2 > GetLastLower(stepText))
// doUpCase = true;
return UpperCaseUnits(rtnstr);
}
// If a RO follows a "- " then it will be uppercased
if (_MyItemInfo.ActiveFormat.PlantFormat.FormatData.ROData.UpRoAftrDash && Regex.IsMatch(beforeRO, @".*\\u8209\?( |\\u160\?)$"))
{
//int indx = startLinkText - 1;
//while (indx > 0 && !IsSpaceOrHardSpace(stepText[indx])) indx--; // find character before RO
//string prefix = indx >= 7?stepText.Substring(indx-7,8):"";
//doUpCase = (prefix == @"\u8209? "); // Dash character before RO
return UpperCaseUnits(rtnstr);
}
// Uppercase the RO Unit if the previous letter is uppercase
if (_MyItemInfo.ActiveFormat.PlantFormat.FormatData.ROData.UpRoIfPrevUpper && char.IsUpper(LastAlpha(beforeRO)))
{
//doUpCase = (char.IsUpper(stepText[startLinkText - 1]));
return UpperCaseUnits(rtnstr);
}
//CapFirstLetterInHighRO - Cap only the first letters of the units in a high level RO
// note: used in FLP (Turkey Point) format
if (_MyItemInfo.ActiveFormat.PlantFormat.FormatData.ROData.CapFirstLetterInHighRO && _MyItemInfo.IsHigh)
{
int idx = 0;
string tstr = "";
while (idx < rtnstr.Length && !char.IsLetter(rtnstr[idx])) tstr += rtnstr[idx++].ToString();
if (idx < rtnstr.Length)
{
tstr += char.ToUpper(rtnstr[idx]).ToString();
if (idx + 1 < rtnstr.Length)
tstr += rtnstr.Substring(idx + 1);
}
rtnstr = tstr;
}
//In a sequence of RO values, the unit appears with every value
//(e.g., "25 gpm and 30 gpm" vs. "25 and 30 gpm")
//if (!_MyItemInfo.ActiveFormat.PlantFormat.FormatData.ROData.AllUnits)
//{
// int idx = rtnstr.LastIndexOf(' ');
// if (idx > 0)
// {
// StringBuilder sb = new StringBuilder();
// string lastunit = rtnstr.Substring(idx); // RO unit including preceeding space
// int idx2 = rtnstr.IndexOf(lastunit);
// int si = 0;
// while (idx2 < idx)
// {
// sb.Append(rtnstr.Substring(si, idx2 - si));
// si = idx2 + lastunit.Length;
// idx2 = rtnstr.IndexOf(lastunit, si);
// }
// sb.Append(rtnstr.Substring(si));
// rtnstr = sb.ToString();
// }
//}
return rtnstr;
}
/// <summary>
/// Uppercase alphabetical strings excluding any RTF token
/// </summary>
/// <param name="match"></param>
/// <returns></returns>
private string MatchEvaluatorUppercaseROUnits(Match match)
{
if (match.Value[0] == '\\') // If the previous character is a backslash then this is an RTF token
return match.Value;
return match.Value.ToUpper();
}
Regex _RegExUppercaseROUnits = new Regex("(^|[^a-zA-Z])[a-zA-Z]+");
private string UpperCaseUnits(string rtnstr)
{
// Uppercase Units
rtnstr = _RegExUppercaseROUnits.Replace(rtnstr, new MatchEvaluator(MatchEvaluatorUppercaseROUnits));
// After converting the value to uppercase, change X10 to x10 to handle Fortran Formatted numbers
return rtnstr.Replace("X10", "x10");
}
// Find the last Alphabetical character
private char LastAlpha(string beforeRO)
{
Match m = Regex.Match(beforeRO, ".*([a-zA-Z])[^a-zA-Z]*");
if (m.Success) return m.Groups[1].ToString()[0];
return '\0';
}
private int DoLinkElements(string text, int index, displayLinkElement vte)
{
// Find the 'end comment' for this <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);
if (endStartTknIndx == -1)
endStartTknIndx = text.IndexOf(@"\v0", index);
int endTextIndx = text.IndexOf(@"\v ", endStartTknIndx); // find end of text
if (endTextIndx == -1)
endTextIndx = text.IndexOf(@"\v", endStartTknIndx);
int endTextIndx2 = text.IndexOf(@"\v\up0 ", endStartTknIndx); // find end of text
if(endTextIndx2 > 0 && (endTextIndx < 0 || endTextIndx > endTextIndx2))
endTextIndx = endTextIndx2;
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;
}
//else
//{
// tmptxt = DoROFormatFlags(vte.Text, text, index, endLinkIndx);
// 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);
int rettoken = 0;
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;
if (vte.Type != E_TextElementType.ReferencedObject)
{
if (vte.TextAndLink.Contains("(Resolved Transition Text)"))
vte.TextAndLink = vte.TextAndLink.Replace("(Resolved Transition Text)", tmptxt);
else
if (vte.Text != tmptxt)
vte.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
#region commented out
//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;
// if (_MyItemInfo.ItemID == 2557) Console.WriteLine("here");
// // 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.IsStepPart && (rs.Flag & E_ReplaceFlags.Substep) > 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|$)";
// //// jsj 07Jun2010 HardSpaces defeat replaceword logic
// //string pat = @"(?<=\W|^)(?<![\\u160?])" + rs.ReplaceWord.ToUpper() + @"(?=[^\\u160?]|$)";
// //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;
// // If there are Regex Control Characters '\[]()' prefix them with backslash
// string replaceWord = Regex.Replace(rs.ReplaceWord, @"[[\]\\()]", @"\$0");
// //string pat = @"(?<=\W|^)" + replaceWord + @"(?=\W|$)";
// // jsj 07Jun2010 HardSpaces defeat replaceword logic
// //string pat = @"(?<=\W|^)(?<![\\u160?])" + replaceWord + @"(?=[^\\u160?]|\W|$)";
// string pat = @"(?<=\W|^)(?<![\\u160?])" + replaceWord + @"(?![\\u160?])(?=\W|$)";
// try
// {
// Text = ReplaceWord(Text, pat, rs.ReplaceWith, RegexOptions.IgnoreCase);
// //Text = Regex.Replace(Text, pat, rs.ReplaceWith, RegexOptions.IgnoreCase);
// }
// catch (Exception ex)
// {
// Console.WriteLine("{0},'{1}',{2},'{3}'", _MyItemInfo.ActiveFormat.Name, replaceWord, ex.GetType().Name, ex.Message);
// }
// }
// // CASEINSENSALL: Do ReplaceWords for all words that match the ReplaceWord, regardless of case
// else if ((rs.Flag & E_ReplaceFlags.CaseInsensAll) > 0)
// {
// // only in Maine Yankee - we don't need to do this one.
// }
// // 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)
// {
// // only used in V.C. Summer - we don't need to do this either.
// }
// else
// {
// // If there are Regex Control Characters '\[]()' prefix them with backslash
// string replaceWord = Regex.Replace(rs.ReplaceWord, @"[[\]\\()]", @"\$0");
// //string pat = @"(?<=\W|^)" + replaceWord + @"(?=\W|$)";
// // jsj 07Jun2010 HardSpaces defeat replaceword logic
// //string pat = @"(?<=\W|^)(?<![\\u160?])" + replaceWord + @"(?=[^\\u160?]|\W|$)";
// string pat = @"(?<=\W|^)(?<![\\u160?])" + replaceWord + @"(?![\\u160?])(?=\W|$)";
// try
// {
// Text = ReplaceWord(Text, pat, rs.ReplaceWith, RegexOptions.None);
// //Text = Regex.Replace(Text, pat, rs.ReplaceWith);
// }
// catch (Exception ex)
// {
// Console.WriteLine("{0},'{1}',{2},'{3}'", _MyItemInfo.ActiveFormat.Name, replaceWord, ex.GetType().Name, ex.Message);
// }
// }
// }
// }
// //Console.WriteLine("--- Before '{0}'", Text);
// Text = Text.Replace(@"\xA0", @"\u160?"); //replace hard space
// //Console.WriteLine("--- After '{0}'", Text);
// return Text;
//}
//private string DoReplaceWords1(string Text)
//{
// if (_MyItemInfo.MyContent.Type < 20000) return Text; // for now only replace in steps.
// ReplaceStrList rsl = _MyFormat.PlantFormat.FormatData.SectData.ReplaceStrList;
// // Loop through text looking for words to be replaced
// foreach (ReplaceStr rs in rsl)
// {
// 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.IsStepPart && (rs.Flag & E_ReplaceFlags.Substep) > 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
// RegexOptions myOptions = (rs.Flag & E_ReplaceFlags.CaseInsens) == E_ReplaceFlags.CaseInsens ? RegexOptions.IgnoreCase : RegexOptions.None;
// string replaceWord = Regex.Replace(rs.ReplaceWord, @"[[\]\\()]", @"\$0");
// string pat = @"(?<=\W|^)(?<![\\u160?])" + replaceWord + @"(?![\\u160?])(?=\W|$)";
// try
// {
// Text = ReplaceWord(Text, pat, rs.ReplaceWith, myOptions);
// }
// catch (Exception ex)
// {
// Console.WriteLine("{0},'{1}',{2},'{3}'", _MyItemInfo.ActiveFormat.Name, replaceWord, ex.GetType().Name, ex.Message);
// }
// }
// }
// Text = Text.Replace(@"\xA0", @"\u160?"); //replace hard space
// return Text;
//}
#endregion
private Dictionary<ReplaceStr, Regex> dicReplaceRegex = new Dictionary<ReplaceStr, Regex>();
private string DoReplaceWords2(string Text)
{
if (_MyItemInfo.MyContent.Type < 20000) return Text; // for now only replace in steps.
FoundMatches myMatches = new FoundMatches(Text);
// Exclude Link Text from Replace Word process
myMatches.AddLink(regFindLink, _MyFormat.PlantFormat.FormatData.SectData.ReplaceWordsInROs, _MyItemInfo.MyProcedure.MyDocVersion);
ReplaceStrList rsl = _MyFormat.PlantFormat.FormatData.SectData.ReplaceStrList;
// The only way to get an 'empty' list is to have one 'dummy' replacestr, i.e. that has ReplaceWord as an empty string. If the
// ReplaceStrData xml node is empty, it does the inheritance and gets the 'base' format's list.
if (rsl.Count==1 && (rsl[0].ReplaceWord == null || rsl[0].ReplaceWord == "")) return Text;
// Loop through text looking for words to be replaced
foreach (ReplaceStr rs in rsl)
{
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.IsStepPart && (rs.Flag & E_ReplaceFlags.Substep) > 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)
{
if (!dicReplaceRegex.ContainsKey(rs))
{
// CASEINSENS: Do ReplaceWords for all words that match, regardless of case, and replace with the ReplaceWith string as is
//RegexOptions myOptions = (rs.Flag & E_ReplaceFlags.CaseInsens) == E_ReplaceFlags.CaseInsens ? RegexOptions.IgnoreCase & RegexOptions.Singleline : RegexOptions.None & RegexOptions.Singleline;
RegexOptions myOptions = (rs.Flag & E_ReplaceFlags.CaseInsens) == E_ReplaceFlags.CaseInsens ? RegexOptions.IgnoreCase: RegexOptions.None;
string replaceWord = Regex.Replace(rs.ReplaceWord, @"[[\]\\()]", @"\$0");
// if first or last character in replaceword is a non-word character, for example, ',', ')', or '.',
// don't use the \W, i.e. don't bother to look for a non-word character.
string wordMatchBeg = Regex.IsMatch(replaceWord.Substring(0, 1), @"\W") ? "" : @"(?<=\W|^)";
string wordMatchEnd = Regex.IsMatch(replaceWord.Substring(replaceWord.Length - 1, 1), @"\W") ? "" : @"(?=\W|$)";
string pat = wordMatchBeg + @"(?<!\\u160\?)" + replaceWord + @"(?!\\u160\?)" + wordMatchEnd;
dicReplaceRegex.Add(rs, new Regex(pat, myOptions));
}
try
{
myMatches.Add(dicReplaceRegex[rs], rs);
}
catch (Exception ex)
{
Console.WriteLine("{0},'{1}',{2},'{3}'", _MyItemInfo.ActiveFormat.Name, rs.ReplaceWord, ex.GetType().Name, ex.Message);
}
}
}
Text = myMatches.ReplaceMatches();
Text = Text.Replace(@"\xA0", @"\u160?"); //replace hard space
return Text;
}
#region notused
static Regex regFindLink = new Regex(@"\<START\].*?\[END\>", RegexOptions.Singleline);
private string ReplaceWord(string text, string replace, string with, RegexOptions regexOptions)
{
MatchCollection myMatches = Regex.Matches(text, replace, regexOptions);
MatchCollection myLinks = regFindLink.Matches(text);
for (int i = myMatches.Count - 1; i >= 0; i--)
{
Match myMatch = myMatches[i];
if (!PartOfLinkText(myMatch, myLinks))
text = text.Substring(0, myMatch.Index) + with + text.Substring(myMatch.Index + myMatch.Length);
}
return text;
}
private bool PartOfLinkText(Match myMatch, MatchCollection myLinks)
{
foreach (Match myLink in myLinks)
if (myMatch.Index > myLink.Index && myMatch.Index < (myLink.Index + myLink.Length))
return true;
return false;
}
#endregion
#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; }
}
protected string _Text;
virtual 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; }
}
/// <summary>
/// Text - this should parse the text and return the results
/// </summary>
override public string Text
{
get
{
if (_TextAndLink != null)
{
Match m = Regex.Match(_TextAndLink, @"<START\](\\[^v \\]+)*\\v0(\\[^v \\]+)* (.*?)(\\[^v'? \\]+)*\\v(\\[^v \\]+)* #Link:(.*?)\[END>");
return m.Groups[3].ToString();
}
return _Text;
}
set
{
if (_TextAndLink != null)
{
Match m = Regex.Match(_TextAndLink, @"<START\](\\[^v \\]+)*\\v0(\\[^v \\]+)* (.*?)(\\[^v'? \\]+)*\\v(\\[^v \\]+)* #Link:(.*?)\[END>");
System.Text.RegularExpressions.Group g = m.Groups[3];
_TextAndLink = _TextAndLink.Substring(0, g.Index) + value + _TextAndLink.Substring(g.Index + g.Length);
}
_Text = value;
}
}
}
#endregion
public class FoundMatches : SortedList<int, FoundMatch>
{
private static readonly log4net.ILog _MyLog = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private string _Text;
public FoundMatches(string text)
: base()
{
_Text = text;
}
public void Add(Regex myRegEx, ReplaceStr myWord)
{
MatchCollection myMatches = myRegEx.Matches(_Text);
foreach (Match myMatch in myMatches)
Add(myMatch, myWord);
}
public void AddLink(Regex myRegEx, bool replaceWordsInROs, DocVersionInfo myDocVersion)
{
MatchCollection myMatches = myRegEx.Matches(_Text);
foreach (Match myMatch in myMatches)
{
if (!replaceWordsInROs || IsTransition(myMatch.Value) || IsSetpointRO(myMatch.Value, myDocVersion))
Add(myMatch, null);// Exclude from Replace Words
}
}
private bool IsTransition(string link)
{
return link.Contains("#Link:Transition");
}
private static Regex regRefObj = new Regex(@"\#Link\:ReferencedObject:([0-9]*) ([0-9a-zA-Z]*) ([0-9]*)", RegexOptions.Singleline);
private static bool IsSetpointRO(string link, DocVersionInfo myDocVersion)
{
Match myMatch = regRefObj.Match(link);
if (myMatch.Success)
{
int dbid = System.Convert.ToInt32(myMatch.Groups[2].Value.Substring(0, 4), 16);
int rodbid = int.Parse(myMatch.Groups[3].Value);
ROFstInfo myROFst = myDocVersion.GetROFst(rodbid);
return myROFst.IsSetpointDB(dbid);
}
return false;
}
public void Add(Match myMatch, ReplaceStr myWord)
{
// If one already exists for this location, then don't add another.
if (ContainsKey(myMatch.Index)) return;
// Start by Adding it.
base.Add(myMatch.Index, new FoundMatch(myMatch, myWord));
// Now see what I can do with it.
int index = this.IndexOfKey(myMatch.Index);
if (index > 0) // If this match is contained within the previous match remove it
{
FoundMatch previousMatch = Values[index - 1];
if (previousMatch.MyMatch.Index + previousMatch.MyMatch.Length > myMatch.Index)
Remove(myMatch.Index);
} // If the next match is contained within this match, remove the next match
while (index < Count - 1 && Values[index + 1].MyMatch.Index < (myMatch.Index + myMatch.Length))
Remove(Values[index + 1].MyMatch.Index);
}
public string ReplaceMatches()
{
int offset = 0;
string text = _Text;
foreach (FoundMatch foundMatch in Values)
{
if (foundMatch.MyWord != null)
{
text = text.Substring(0, offset + foundMatch.MyMatch.Index) + foundMatch.MyWord.ReplaceWith + text.Substring(offset + foundMatch.MyMatch.Index + foundMatch.MyMatch.Length);
offset += foundMatch.MyWord.ReplaceWith.Length - foundMatch.MyMatch.Length;
}
}
return text;
}
}
public class FoundMatch
{
private Match _MyMatch;
public Match MyMatch
{
get { return _MyMatch; }
set { _MyMatch = value; }
}
private ReplaceStr _MyWord;
public ReplaceStr MyWord
{
get { return _MyWord; }
set { _MyWord = value; }
}
public FoundMatch(Match myMatch, ReplaceStr myWord)
{
_MyMatch = myMatch;
_MyWord = myWord;
}
}
}