Rich 7bcfafcc8b Move frmErrors when frmLoader is moved
Shutoff SpellCheck for StepRTB
Use using for temporary StepRTB
Use using for vlnFlexGrid
Added debug output to track StepRTBs and vlnFlexGrids in memory
Limit bottom margin to 0 or above
Dispose of roImage after it is done being used
Dispose of Figure after it is done being used.
Use GetJustRODB so that images are not loaded.
Added ErrorHandler if annotation is deleted after a search
Track create, dispose and finalize
Add static variable to control if SpellCheck is used
Use using for temporary StepRTB
Lazy Load SelectionStack
Clean-up on Dispose
Track create, dispose and finalize
Make MyCopyInfo Lazy Loaded
Use using for temporary StepRTB
Add Dispose method for TableCellEditor
Cleanup on Dispose
Only kill MSWord instances that are invisible
2012-07-13 18:34:57 +00:00

3356 lines
112 KiB
C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using VEPROMS.CSLA.Library;
using Volian.Base.Library;
namespace Volian.Controls.Library
{
public delegate void StepRTBEvent(object sender, EventArgs args);
public delegate void StepRTBCursorKeysEvent(object sender, KeyEventArgs args);
public delegate void StepRTBCursorMovementEvent(object sender, StepRTBCursorMovementEventArgs args);
public delegate void StepRTBModeChangeEvent(object sender, StepRTBModeChangeEventArgs args);
public delegate void StepRTBMenuEvent(object sender, StepRTBMenuEventArgs args);
public delegate void StepRTBTableWidthEvent(object sender, StepRTBTableWidthEventArgs args);
public delegate bool StepRTBBooleanEvent(object sender, EventArgs args);
public delegate void StepRTBLocationEvent(object sender, StepRTBLocationEventArgs args);
public delegate void StepRTBMouseEvent(object sender, MouseEventArgs args);
public delegate void StepRTBRoEvent(object sender, StepRTBRoEventArgs args);
//public delegate void StepRTBMouseWheelEvent(object sender, MouseEventArgs args);
public partial class StepRTB : RichTextBox // , IStepRTB
{
private static readonly log4net.ILog _MyLog = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private bool _Disposed = false;
private static int _CountCreated = 0;
private static int _CountDisposed = 0;
private static int _CountFinalized = 0;
private static int IncrementCountCreated
{ get { return ++_CountCreated; } }
private int _CountWhenCreated = IncrementCountCreated;
public static int CountCreated
{ get { return _CountCreated; } }
public static int CountNotDisposed
{ get { return _CountCreated - _CountDisposed; } }
public static int CountNotFinalized
{ get { return _CountCreated - _CountFinalized; } }
private bool _Finalized = false;
~StepRTB()
{
if (!_Finalized) _CountFinalized++;
_Finalized = true;
}
#region Events
public event StepRTBRoEvent RoInsert;
public void OnRoInsert(object sender, StepRTBRoEventArgs args)
{
if (RoInsert != null) RoInsert(sender, args);
}
public event StepRTBEvent ReturnToEditor;
public void OnReturnToEditor(object sender, EventArgs args)
{
if (ReturnToEditor != null) ReturnToEditor(sender, args);
}
public event StepRTBEvent EditModeChanged;
public void OnEditModeChanged(object sender, EventArgs args)
{
if (EditModeChanged != null) EditModeChanged(sender, args);
}
public event StepRTBEvent DoSaveContents;
public void OnDoSaveContents(object sender, EventArgs args)
{
if (DoSaveContents != null) DoSaveContents(sender, args);
}
public event StepRTBMouseEvent DoMouseWheel;
public void OnDoMouseWheel(object sender, MouseEventArgs args)
{
if (DoMouseWheel != null) DoMouseWheel(sender, args);
}
public event StepRTBLocationEvent OpenContextMenu;
public void OnOpenContextMenu(object sender, StepRTBLocationEventArgs args)
{
if (OpenContextMenu != null) OpenContextMenu(sender, args);
}
public event StepRTBEvent CopyStep;
public void OnCopyStep(object sender, EventArgs args)
{
if (CopyStep != null) CopyStep(sender, args);
}
public event StepRTBBooleanEvent CheckClipboard;
public bool OnCheckClipboard(object sender, EventArgs args)
{
if (CheckClipboard != null) return CheckClipboard(sender, args);
return false;
}
public event StepRTBCursorKeysEvent EnterKeyPressed;
public void OnEnterKeyPressed(object sender, KeyEventArgs args)
{
if (EnterKeyPressed != null) EnterKeyPressed(sender, args);
}
public event StepRTBEvent InsertPgBrk;
public void OnInsertPgBrk(object sender, EventArgs args)
{
if (InsertPgBrk != null) InsertPgBrk(sender, args);
}
public event StepRTBEvent OpenAnnotations;
public void OnOpenAnnotations(object sender, EventArgs args)
{
if (OpenAnnotations != null) OpenAnnotations(sender, args);
}
public event StepRTBBooleanEvent IsNotCurrentSelection;
public bool OnIsNotCurrentSelection(object sender, EventArgs args)
{
if (IsNotCurrentSelection != null) return IsNotCurrentSelection(sender, args);
return false;
}
public event StepRTBTableWidthEvent AdjustTableWidth;
public void OnAdjustTableWidth(object sender, StepRTBTableWidthEventArgs args)
{
if (AdjustTableWidth != null) AdjustTableWidth(sender, args);
}
public event StepRTBMenuEvent SetMenu;
private void OnSetMenu(object sender, StepRTBMenuEventArgs args)
{
if (SetMenu != null) SetMenu(sender, args);
}
public event StepRTBEvent RTBSelectionChanged;
private void OnRTBSelectionChanged(object sender, EventArgs args)
{
if (RTBSelectionChanged != null) RTBSelectionChanged(sender, args);
}
public event StepRTBEvent LinkLocationsChanged;
private void OnLinkLocationChanged(object sender, EventArgs args)
{
if (LinkLocationsChanged != null) LinkLocationsChanged(sender, args);
}
public event StepRTBEvent RTBRangeStatusChanged;
private void OnRTBRangeStatusChanged(object sender, EventArgs args)
{
if (RTBRangeStatusChanged != null) RTBRangeStatusChanged(sender, args);
}
public event StepRTBCursorKeysEvent CursorKeyPress;
private void OnCursorKeyPress(object sender, KeyEventArgs args)
{
if (CursorKeyPress != null) CursorKeyPress(sender, args);
}
public event StepRTBCursorMovementEvent CursorMovement;
private void OnCursorMovement(object sender, StepRTBCursorMovementEventArgs args)
{
if (CursorMovement != null) CursorMovement(sender, args);
}
//public event StepRTBModeChangeEvent ModeChange;
//private void OnModeChange(object sender, StepRTBModeChangeEventArgs args)
//{
// //_MyModeChangeEventArgs = args;
// if (ModeChange != null) ModeChange(sender, args);
// else MessageBox.Show("StepRTB - no mode change defined");
//}
//public event StepRTBMouseWheelEvent MouseWheel;
//private void OnMouseWheel(object sender, MouseEventArgs args)
//{
// if (MouseWheel != null) MouseWheel(sender, args);
//}
/// <summary>
/// This event is not raised during all the in-between changes for link deletions
/// </summary>
public event StepRTBEvent RTBTextChanged;
private void OnRTBTextChanged(object sender, EventArgs args)
{
if (RTBTextChanged != null) RTBTextChanged(sender, args);
}
#endregion
#region Properties and Variables
public bool IsRoTable
{
get { return (Parent is VlnFlexGrid && (Parent as VlnFlexGrid).IsRoTable); }
}
public bool HasVScroll
{
get
{
return RTBAPI.HasVertScroll(this);
}
}
public bool HasHScroll
{
get
{
return RTBAPI.HasHorzScroll(this);
}
}
private bool _EditMode = true;
/// <summary>
/// Allows insert of links. If false, don't allow selection of links.
/// </summary>
public bool EditMode
{
get { return _EditMode; }
set
{
_EditMode = value;
OnEditModeChanged(this, new EventArgs());
}
}
private static string _MySymbolFontName;
public static string MySymbolFontName
{
get { return StepRTB._MySymbolFontName; }
set { StepRTB._MySymbolFontName = value; }
}
private static FontFamily _MyFontFamily = null;
public static FontFamily MyFontFamily
{
get { return StepRTB._MyFontFamily; }
set
{
_MyFontFamily = value;
if (value != null)
{
Font font;
if (value.IsStyleAvailable(FontStyle.Regular))
font = new Font(value, 10);
else if (value.IsStyleAvailable(FontStyle.Bold))
font = new Font(value, 10, FontStyle.Bold);
else // (value.IsStyleAvailable(FontStyle.Italic))
font = new Font(value, 10, FontStyle.Italic);
using (StepRTB srtb = new StepRTB())
{
if (srtb.FontIsFixed(font)) _MySymbolFontName = "VESymbFix";
else _MySymbolFontName = "Arial Unicode MS";
}
}
}
}
// use newer rich text box....
//[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
//static extern IntPtr LoadLibrary(string lpFileName);
//protected override CreateParams CreateParams
//{
// get
// {
// CreateParams prams = base.CreateParams;
// if (LoadLibrary("msftedit.dll") != IntPtr.Zero)
// {
// //prams.ExStyle |= 0x020; // transparent
// prams.ClassName = "RICHEDIT50W";
// }
// return prams;
// }
//}
private E_FieldToEdit _FieldToEdit = E_FieldToEdit.StepText;
public E_FieldToEdit FieldToEdit
{
get { return _FieldToEdit; }
set { _FieldToEdit = value; }
}
private string _RtfPrefix; // contains Font table and styles (bold/underline/italics) for rtb from step style
public string RtfPrefixForSymbols
{
get
{
if (_RtfPrefix == null)
{
StringBuilder selectedRtfSB = new StringBuilder();
AddFontTable(selectedRtfSB, FormatFont, FontIsFixed(FormatFont));
_RtfPrefix = selectedRtfSB.ToString();
}
return _RtfPrefix + @"\f1\fs" + FormatFont.SizeInPoints * 2 + " ";
}
}
public string RtfPrefix
{
get
{
if (_RtfPrefix == null)
{
StringBuilder selectedRtfSB = new StringBuilder();
AddFontTable(selectedRtfSB, FormatFont, FontIsFixed(FormatFont));
_RtfPrefix = selectedRtfSB.ToString();
}
return _RtfPrefix;// +@"{\colortbl ;\red255\green0\blue0;}";
}
}
// August 5, 2009 - KBR & RHM:
// Insert/Overwrite will be developed later if needed. various issues
// were found during initial development that made its scope larger than
// expected. Problems were related to having overstrike on in the following
// cases:
// 1) left arrow when on link - positions after link
// 2) left arrow and after link - does not move
// 3) shift left arrow does not move past links correctly and also, first
// shift left arrow looks more like insert mode.
// private bool _OverWrite;
// _IsDirty compares the original rtf to the current rtf from the
// richtextbox to see if a change was made.
public bool IsDirty
{
get { return OrigRTF != Rtf; }
}
private bool _InitializingRTB;
private IContainer _Container = null;
private string _MyClassName=string.Empty;
public string MyClassName
{
get { if (_MyClassName == string.Empty)_MyClassName = CreateParams.ClassName; return _MyClassName; }
set { _MyClassName = value; }
}
//private E_EditPrintMode _epMode = E_EditPrintMode.Edit;
//public E_EditPrintMode EpMode
//{
// get { return _epMode; }
// set {
// if (value == E_EditPrintMode.Print) Console.WriteLine("");
// _epMode = value; }
//}
private E_ViewMode _vwMode = E_ViewMode.Edit;
public E_ViewMode VwMode
{
get { return _vwMode; }
set { _vwMode = value; }
}
private VE_Font _MyStyleFont;
public VE_Font MyStyleFont
{
get
{
if (_MyStyleFont == null) _MyStyleFont = MyItemInfo.GetItemFont();
return _MyStyleFont;
}
}
private bool _ActiveMode = false;
public bool ActiveMode
{
get { return _ActiveMode; }
set { _ActiveMode = value; }
}
private ItemInfo _MyItemInfo;
public ItemInfo MyItemInfo
{
get
{
if (_MyItemInfo == null && Parent is EditItem)
_MyItemInfo = (Parent as EditItem).MyItemInfo;
else if (_MyItemInfo == null && Parent != null && Parent.Parent is EditItem)
_MyItemInfo = (Parent.Parent as EditItem).MyItemInfo;
return _MyItemInfo;
}
set { _MyItemInfo = value; }
}
private string _OrigRTF;
public string OrigRTF
{
get { return _OrigRTF; }
set { _OrigRTF = value; }
}
private Font _FormatFont;
public Font FormatFont
{
get
{
if (_FormatFont == null)
{
Font formatFont;
if (MyItemInfo != null)
formatFont = MyItemInfo.GetItemFont().WindowsFont; // OrigDisplayText.TextFont.WindowsFont;
else
formatFont = Font;
if (MyItemInfo != null && (MyItemInfo.IsTable || MyItemInfo.IsFigure))
_FormatFont = formatFont;
else
{
//if (VlnSettings.DebugMode || VlnSettings.ProductionMode)
_FormatFont = new Font(MyFontFamily == null ? formatFont.FontFamily : MyFontFamily, formatFont.Size, formatFont.Style);
//else
// _FormatFont = new Font("Bookman Old Style", formatFont.Size, formatFont.Style);
// TODO: Release Mode
//Font = _origDisplayText.TextFont.WindowsFont; // font defined in plant's format
}
}
return _FormatFont;
}
set { _FormatFont = value; }
}
public void SetupRichText(string rtf, VE_Font vFont)
{
//FormatFont = vFont.WindowsFont;
DisplayText vlnText = new DisplayText(rtf, vFont, true);
AddRtfText(vlnText.StartText);
ReadOnly = true;
}
public void RefreshDisplay()
{
if (Closed) return;
try
{
RefreshDisplay(ActiveMode);
}
catch (Exception ex)
{
_MyLog.Error(string.Format("MyItemInfo: {0} - {1} Problem doing RefreshDisplay",MyItemInfo.ItemID,MyItemInfo.ShortPath), ex);
}
}
// RefreshDisplay is used to update the rtb for an entire Item as defined by MyItemInfo.
public void RefreshDisplay(bool activeMode)
{
ActiveMode = activeMode;
OnAdjustTableWidth(this, new StepRTBTableWidthEventArgs(true));
_InitializingRTB = true;
DisplayText vlntxt = new DisplayText(MyItemInfo, E_EditPrintMode.Edit, VwMode, !ActiveMode, FieldToEdit, true);
//if (_origDisplayText != null && vlntxt.StartText == _origDisplayText.StartText)
//{
// ReadOnly = !(EpMode == E_EditPrintMode.Edit && VwMode == E_ViewMode.Edit);
// if (!ReadOnly && !edit) ReadOnly = true;
// return;
//}
OrigDisplayText = vlntxt;
// RHM 20101201 - Don't reset the text. Calculate the text and compare it with the existing text in AddRTFText
//Text = ""; // Initialize text before add text
// IMPORTANT: SetLineSpacing must be set before Links, otherwise it
// was confusing the 'handle' of the rtf box.
//Console.WriteLine("'font',{0}", Font);
//if(Text == "")SelectionFont = Font; // Initialize SelectionFont
if (MyItemInfo != null)
{
if (MyItemInfo.IsStep) Font = MyFontFamily == null ? MyItemInfo.FormatStepData.Font.WindowsFont:new Font(MyFontFamily, MyItemInfo.FormatStepData.Font.WindowsFont.Size, MyItemInfo.FormatStepData.Font.WindowsFont.Style);
else Font = Font = MyFontFamily == null ? MyItemInfo.ActiveFormat.PlantFormat.FormatData.Font.WindowsFont : new Font(MyFontFamily, MyItemInfo.ActiveFormat.PlantFormat.FormatData.Font.WindowsFont.Size, MyItemInfo.ActiveFormat.PlantFormat.FormatData.Font.WindowsFont.Style);
}
RTBAPI.SetLineSpacing(this, RTBAPI.ParaSpacing.PFS_EXACT);
ReadOnly = VwMode == E_ViewMode.View || ActiveMode == false;
AddRtfText(vlntxt.StartText);
//AddRtfStyles();
// set readonly based on initial modes, however, these may change if
// user selected view mode.
ClearUndo();
// RHM: 20101122 - Not sure why the RightMargin is set. The following line was added in Rev 23
// in May of 2008.
//
// RightMargin = Width;
//
// Normally a the Right Margin is handled by the RichTextBox it defaults to a value of 0.
//
// If the RightMargin is equal to the width of the RichTextBox the word-wrap occurs just beyond
// the visible extent (right edge) of the RichTextBox when it is in view mode. In edit mode it
// wraps within the visible extent. An example of this is Step 24 of ES02 in HLP EOPs.
//
// If the RightMargin is greater than the width of the RichTextBox, the word-wrap occurs beyond
// the visible extent of the RichTextBox for both view and edit modes.
//
// Setting the RightMargin to the Width minus one, accounts for the slight indent (1 pixel) of
// the text within the RichTextBox.
RightMargin = Width > 0 ? Width - 1 : 0;
// figure out if needs outlined, depends on table/figure type
if (!ActiveMode)
{
RemoveEventHandlers();
OnAdjustTableWidth(this, new StepRTBTableWidthEventArgs(false));// View Mode
SelectAll();
if (SelectionHangingIndent !=0) SelectionHangingIndent = 0;
int indchar = 0;
string indentToken = MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.IndentToken;
if (indentToken == null || indentToken=="0") indentToken = "\x5";
// this line of code was moved before the find for the indent so that
// the window gets resized if the indent changes the height, i.e. more line(s) in window.
AddEventHandlers();
while ((indchar = Find(indentToken, indchar, RichTextBoxFinds.None)) >= 0)
{
Point indent = GetPositionFromCharIndex(indchar);
SelectionHangingIndent = indent.X;
SelectedRtf = SelectedRtf.Replace(@"\'05","");
}
}
OrigRTF = Rtf;
_InitializingRTB = false;
AdjustSizeForContents(!ActiveMode);
}
private bool _ProcessKeystrokes = true;
public bool ProcessKeystrokes
{
get { return _ProcessKeystrokes; }
set { _ProcessKeystrokes = value; }
}
private Point ScrollPos
{
get { return RTBAPI.GetScrollLocation(this); }
set { RTBAPI.SetScrollLocation(this, value); }
}
private Rectangle _ContentsRectangle = new Rectangle(0,0,0,0);
public Rectangle ContentsRectangle
{
get
{
if (_ContentsRectangle.X == 0 && _ContentsRectangle.Y == 0 && _ContentsRectangle.Width == 0 && _ContentsRectangle.Height == 0)
_ContentsRectangle = this.ClientRectangle;
return _ContentsRectangle;
}
set
{
_ContentsRectangle = value;
AdjustSizeForContents(false);
}
}
public Size ContentsSize
{
get { return _ContentsRectangle.Size; }
}
private Size _AdjustSize = new Size(0,0); // if 0,0 puts text right next to bottom of box.
public Size AdjustSize
{
get { return _AdjustSize; }
set
{
_AdjustSize = value;
AdjustSizeForContents(false);
}
}
public System.Windows.Forms.AutoScaleMode AutoScaleMode;
private DisplayText _OrigDisplayText;
public DisplayText OrigDisplayText
{
get { return _OrigDisplayText; }
set { _OrigDisplayText = value; }
}
private RichTextBox _rtbTemp = new RichTextBox();
private string _MyLinkText;
public string MyLinkText
{
get { return _MyLinkText; }
set
{
//if (value != _MyLinkText)
//{
// updates to the info panel were not always occurring when the previous two
// lines were active
_MyLinkText = value;
OnLinkChanged(this, new StepPanelLinkEventArgs(_MyLinkText));
//}
}
}
#endregion
#region Constructors
public StepRTB()
{
InitializeComponent();
SetUpStepRTB();
AddEventHandlers();
this.BorderStyleChanged += new EventHandler(StepRTB_BorderStyleChanged);
}
public StepRTB(IContainer container)
{
container.Add(this);
InitializeComponent();
_Container = container;
SetUpStepRTB();
AddEventHandlers();
this.BorderStyleChanged += new EventHandler(StepRTB_BorderStyleChanged);
}
protected override void OnMouseWheel(MouseEventArgs e)
{
OnDoMouseWheel(this, e);
//MyRTBItem.MyStepPanel.MouseWheel(e);
//base.OnMouseWheel(e);
}
// When a border style is changed, the richtextbox's handle is 'destroyed', so that the handleDestroyed
// event is done. This was causing the event handlers to be removed (RemoveEventHandler) so that the
// keypress event handler was not run.
private void RemoveEventHandlers()
{
if (_EventHandlersForKeyPress==0) return;
ContentsResized -= new ContentsResizedEventHandler(StepRTB_ContentsResized);
this.Click -= new EventHandler(StepRTB_Click);
this.KeyPress -= new KeyPressEventHandler(StepRTB_KeyPress);
this.KeyDown -= new KeyEventHandler(StepRTB_KeyDown);
this.KeyUp -= new KeyEventHandler(StepRTB_KeyUp);
this.TextChanged -= new EventHandler(StepRTB_TextChanged);
this.MouseUp -= new MouseEventHandler(StepRTB_MouseUp);
this.MouseDown -= new MouseEventHandler(StepRTB_MouseDown);
this.MouseLeave -= new EventHandler(StepRTB_MouseLeave);
this.SelectionChanged -= new EventHandler(StepRTB_SelectionChanged);
this.ContextMenuStripChanged -= new EventHandler(StepRTB_ContextMenuStripChanged);
this.RTBSelectionChanged -= new StepRTBEvent(StepRTB_RTBSelectionChanged);
this.HandleDestroyed -= new EventHandler(StepRTB_HandleDestroyed);
_EventHandlersForKeyPress = _EventHandlersForKeyPress - 1;
}
private int _EventHandlersForKeyPress = 0;
// When a border style is changed, the richtextbox's handle is 'destroyed', so that the handleDestroyed
// event is done. This was causing the event handlers to be removed (RemoveEventHandler) so that the
// keypress event handler was not run.
private void AddEventHandlers()
{
if (_EventHandlersForKeyPress>0) return;
// Always be sure to add the same event handlers to RemoveEventHandlers
BorderStyle = System.Windows.Forms.BorderStyle.None;
this.DetectUrls = true;
ContentsResized += new ContentsResizedEventHandler(StepRTB_ContentsResized);
this.Click +=new EventHandler(StepRTB_Click);
this.KeyPress += new KeyPressEventHandler(StepRTB_KeyPress);
this.KeyDown += new KeyEventHandler(StepRTB_KeyDown);
this.KeyUp += new KeyEventHandler(StepRTB_KeyUp);
this.TextChanged += new EventHandler(StepRTB_TextChanged);
this.MouseUp += new MouseEventHandler(StepRTB_MouseUp);
this.MouseDown += new MouseEventHandler(StepRTB_MouseDown);
this.MouseLeave += new EventHandler(StepRTB_MouseLeave);
this.SelectionChanged +=new EventHandler(StepRTB_SelectionChanged);
this.ContextMenuStripChanged += new EventHandler(StepRTB_ContextMenuStripChanged);
this.RTBSelectionChanged += new StepRTBEvent(StepRTB_RTBSelectionChanged);
this.HandleDestroyed += new EventHandler(StepRTB_HandleDestroyed);
_EventHandlersForKeyPress = _EventHandlersForKeyPress+1;
}
// When a border style is changed, the richtextbox's handle is 'destroyed', so that the handleDestroyed
// event is done. This was causing the event handlers to be removed (RemoveEventHandler) so that the
// keypress event handler was not run. The following was added so that the keypress event is restored
// after the border style was changed. This is specifically for the steprtb's on property pages.
void StepRTB_BorderStyleChanged(object sender, EventArgs e)
{
if (_EventHandlersForKeyPress==0)
this.KeyPress += new KeyPressEventHandler(StepRTB_KeyPress);
_EventHandlersForKeyPress++;
}
private bool _Closed = false;
public bool Closed
{
get { return _Closed; }
set { _Closed = value; }
}
void StepRTB_HandleDestroyed(object sender, EventArgs e)
{
Closed = true;
RemoveEventHandlers();
}
void StepRTB_RTBSelectionChanged(object sender, EventArgs args)
{
//Console.WriteLine("RTBSelectionChanged id= {0}", MyItemInfo.ItemID);
if (!Focused) Focus();
}
void StepRTB_ContextMenuStripChanged(object sender, EventArgs e)
{
//Console.WriteLine("********** StepRTB_ContextMenuStripChanged");
int sublocation = 0;
try
{
//Console.WriteLine("{0}", ContextMenuStrip.GetType().FullName);
OnSetMenu(this, new StepRTBMenuEventArgs(null));
sublocation = 1;
_ContextMenuStripChanged = true;
sublocation = 2;
_ContextMenuStepRTB = this;
sublocation = 3;
_ContextMenuStrip = ContextMenuStrip;
sublocation = 4;
}
catch(Exception ex)
{
Console.WriteLine("StepRTB_ContextMenuStripChanged {0} - {1} [{2}]", ex.GetType().Name, ex.Message, sublocation);
}
}
private void SetUpStepRTB()
{
DetectUrls = false;
if(DoSpellCheck)
C1SpellChecker2.SetActiveSpellChecking(this, true);
this.Height = 10; // initialize the height to 10, the default height was too big for the cells in grid tables
BorderStyle = System.Windows.Forms.BorderStyle.None;
this.ScrollBars = RichTextBoxScrollBars.None;
this.DetectUrls = true;
}
// An event is needed to set MouseDown to false on mouse leave, because additional rtb's may
// have been exposed based on entering a step, which causes the underlying item/rtb for which
// the mouse event occurs to not be the current rtb. RTB gets selected on MouseDown, MouseEnter
// and MouseUp are
void StepRTB_MouseLeave(object sender, EventArgs e)
{
_MouseDown = false;
}
//void MyConfig_PropertyChanged(object sender, PropertyChangedEventArgs e)
//{
// SaveConfig();
//}
private void StepRTB_Click(object sender, EventArgs e)
{
if (ReadOnly) return;
}
void StepRTB_SelectionChanged(object sender, EventArgs e)
{
//Console.WriteLine("StepRTB_SelectionChanged id= {0}", MyItemInfo.ItemID);
if (_InitializingRTB) return;
HandleSelectionChange();
}
private bool _MouseDown = false;
private bool _ContextMenuStripChanged = false;
private void StepRTB_MouseDown(object sender, MouseEventArgs e)
{
_MouseDown = true;
//Console.WriteLine("vvvvvvvvvv StepRTB Mouse Down id= {0}",MyItemInfo.ItemID);
bool inPsi = this.Parent.FindForm().Name.Contains("frmPSI");
if (!_ContextMenuStripChanged)
OnSetMenu(this, new StepRTBMenuEventArgs(inPsi?"PSI":"OpenContextMenu"));
_ContextMenuStripChanged = false;
CorrectSelectionAtEndOfLine();
}
void StepRTB_MouseUp(object sender, MouseEventArgs e)
{
_MouseDown = false;
//Console.WriteLine("^^^^^^^^^^ StepRTB Mouse Up id= {0}", MyItemInfo.ItemID);
if(this.Focused) // Only HandleSelectionChange if this control has focus.
{
HandleSelectionChange();
// save our context menu to add to the spell checker's context menu
ThisContextMenuStrip = this.ContextMenuStrip;
}
}
#endregion
#region ApplicationSupport
// Used in StepTabRibbon:
//public void ToggleEditView(E_ViewMode vwMode)
//{
// OnDoSaveContents(this, new EventArgs()); // SaveText();
// //ItemInfo tmp = MyItemInfo;
// //MyItemInfo = null;
// //ReadOnly = !ReadOnly;
// //EpMode = ReadOnly ? E_EditPrintMode.Print : E_EditPrintMode.Edit;
// VwMode = vwMode;
// ReadOnly = VwMode == E_ViewMode.View;
// ViewRTB = ReadOnly;
// Clear();
// RefreshDisplay(!ViewRTB);
// //MyItemInfo = tmp;
// SelectionStart = 0;
// SelectionLength = 0;
// //OnModeChange(this, new StepRTBModeChangeEventArgs(ViewRTB?E_ViewMode.View:E_ViewMode.Edit));
//}
public void InsertRO(string value, string link)
{
AddRtfLink(value, link);
}
public void InsertTran(string value, string link)
{
AddRtfLink(value, link);
}
public void InsertSymbol(int symbcode)
{
string sym = string.Format(symbcode < 256 ? "\'{0:X2}" : @"\u{0}", symbcode);
if (symbcode < 256)
AddText(((char)symbcode).ToString());
else
AddSymbol(sym); // Adds font commands around symbol, needed for higher codes
}
public void InsertSymbol(string symbol)
{
AddSymbol(symbol);
}
public void InsertIndent(string indentToken)
{
if (indentToken == null || indentToken == "0") indentToken = "\x5";
AddText(indentToken);
}
public void InsertText(string txt)
{
AddText(txt);
}
private void ToggleCase()
{
char type = 'l';
// do not change case on linked text
RangeStatus rs = FindRangeStatus();
string tmp = null;
if (rs != RangeStatus.NoContainedLinks)
{
int start = SelectionStart;
int ostart = SelectionStart;
int end = SelectionStart + SelectionLength;
bool processed = false;
while (!processed && start <= end)
{
foreach (LinkLocation ll in LinkLocations)
{
if (ll.Start >= start && ll.End <= end)
{
processed = true;
if (start < ll.Start)
{
SelectionStart = start;
SelectionLength = ll.Start - start;
}
start = ll.End + 1;
break;
}
}
}
}
string ostring = SelectedText;
if (ostring.Length == 0) return; // nothing selected
if (ostring.Length == 1)
type = char.IsUpper(ostring, 0) ? 'l' : 'U';
else if ((char.IsUpper(ostring, 0) && char.IsUpper(ostring, 1)) ||
(char.IsLower(ostring, 0) && char.IsUpper(ostring, 1))) type = 'l'; // lower case
else if ((char.IsUpper(ostring, 0) && char.IsLower(ostring, 1))) type = 'U'; // upper case
else type = 'T'; // Title case
SetSelectedCase(type);
}
public void SetSelectedCase(char type)
{
// do not change case on linked text
RangeStatus rs = FindRangeStatus();
string tmp = null;
if (rs == RangeStatus.NoContainedLinks)
SetCase(type);
else
{
int start = SelectionStart;
int ostart = SelectionStart;
int end = SelectionStart + SelectionLength;
StringBuilder sb = new StringBuilder();
while (start <= end)
{
bool processed = false;
foreach (LinkLocation ll in LinkLocations)
{
if (ll.Start >= start && ll.End <= end)
{
processed = true;
if (start < ll.Start)
{
SelectionStart = start;
SelectionLength = ll.Start - start;
SetCase(type);
}
start = ll.End + 1;
break;
}
}
// if none were processed, no more links, copy over any remaining text.
if (!processed)
{
SelectionStart = start;
SelectionLength = end-start;
SetCase(type);
start = end + 1;
}
}
SelectionStart = ostart;
SelectionLength = end - ostart;
}
}
private void SetCase(char type)
{
int ostart = SelectionStart;
int olen = SelectionLength;
string ostring = SelectedText;
string tmp = null;
bool docap = true;
// go character by character. Because of symbols, setting entire
// to upper or lower set symbols incorrectly some of time (depending
// on symbol) .
for (int i = 0; i < olen; i++)
{
SelectionStart = ostart + i;
SelectionLength = 1;
switch (type)
{
case 'l':
if (SelectedText[0] >= 'A' && SelectedText[0] <= 'Z')
SelectedText = SelectedText.ToLower();
break;
case 'U':
if (SelectedText[0] >= 'a' && SelectedText[0] <= 'z')
SelectedText = SelectedText.ToUpper();
break;
case 'T':
if (docap && SelectedText[0] >= 'a' && SelectedText[0] <= 'z')
SelectedText = SelectedText.ToUpper();
else if (!docap && SelectedText[0] >= 'A' && SelectedText[0] <= 'Z')
SelectedText = SelectedText.ToLower();
docap = ostring[i] == ' ';
break;
}
}
SelectionStart = ostart;
SelectionLength = olen;
}
#endregion
#region AddRtfTextAndStyles
private string _LastRtf = "";
public string LastRtf
{
get { return _LastRtf; }
set { _LastRtf = value; }
}
private bool _lastReadOnly = false;
private void AddRtfText(string txt)
{
//Console.WriteLine("ItemID:{0}", MyItemInfo.ItemID);
//if(MyItemInfo.ItemID==10256)
// Volian.Base.Library.vlnStackTrace.ShowStackLocal("ItemID:{0}", MyItemInfo.ItemID.ToString());
StringBuilder selectedRtfSB = new StringBuilder();
AddFontTable(selectedRtfSB, FormatFont, FontIsFixed(FormatFont));
_RtfPrefix = selectedRtfSB.ToString();
selectedRtfSB.Append(txt);
string newRtf = selectedRtfSB.ToString() + "}";
if(newRtf != _LastRtf || ReadOnly != _lastReadOnly)
{
//Console.WriteLine("ItemID:{0}\r\nOld:'{1}'\r\nNew:'{2}'\r\n", MyItemInfo.ItemID, Rtf, newRtf);
this.ContentsResized -= new ContentsResizedEventHandler(StepRTB_ContentsResized);
Text = "";
this.ContentsResized += new ContentsResizedEventHandler(StepRTB_ContentsResized);
SelectedRtf = _LastRtf = newRtf;
_lastReadOnly = ReadOnly;
}
FindAllLinks();
if (txt == "") SelectionFont = FormatFont;
}
public void SetTableGridCellRTFPrefix(Font myfont)
{
if (_FormatFont == null)
_FormatFont = myfont;
if (_RtfPrefix == null)
{
StringBuilder selectedRtfSB = new StringBuilder();
AddFontTable(selectedRtfSB, myfont, FontIsFixed(myfont));
_RtfPrefix = selectedRtfSB.ToString();
}
}
private static void AddFontTable(StringBuilder selectedRtfSB, Font myFont, bool isFixed)
{
StringBuilder sbbeg = new StringBuilder();
StringBuilder sbend = new StringBuilder();
if (myFont.Bold)
{
sbbeg.Append(@"\b");
sbend.Append(@"\b0");
}
if (myFont.Underline)
{
sbbeg.Append(@"\ul");
sbend.Insert(0, @"\ulnone");
}
if (myFont.Italic)
{
sbbeg.Append(@"\i");
sbend.Insert(0, @"\i0");
}
selectedRtfSB.Append(@"{\rtf1\ansi\ansicpg1252\deff0\deflang1033{\fonttbl{\f0\fnil\fcharset2 " + myFont.FontFamily.Name + @";}"); //}\f0\fs" + this.Font.SizeInPoints * 2 + @" " + myDisplayTextElement.Text + @"}}";
if (!isFixed)
selectedRtfSB.Append(@"{\f1\fnil\fcharset0 Arial Unicode MS;}}{\colortbl ;\red255\green0\blue0;}");
else
selectedRtfSB.Append(@"{\f1\fnil\fcharset0 VESymbFix;}}{\colortbl ;\red255\green0\blue0;}");
selectedRtfSB.Append("\r\n");
// use styles to construct rtf commands to insert into next line (where \b, etc is)
selectedRtfSB.Append(@"\viewkind4\uc1\pard\sl-240\slmult0" + sbbeg.ToString() + @"\fs" + Convert.ToInt32(myFont.SizeInPoints * 2).ToString() + @" "); // \f0\fs" + this.Font.SizeInPoints * 2 + @" " + myDisplayTextElement.Text + @"}";
}
private bool FontIsFixed(Font myFont)
{
Graphics grph = Graphics.FromHwnd(this.Handle);
SizeF sfW = grph.MeasureString("W", myFont);
SizeF sfE = grph.MeasureString("!", myFont);
if (sfW.Width == sfE.Width) return true;
return false;
}
private void AddRtf(string str)
{
// Because we're inserting rtf with { }, the surrounding styles are not included. Get the font
// style of current position & use it after the insert to set the style.
RTBAPI.E_FontStyle fs = RTBAPI.GetFontStyle(this);
int positionStart = SelectionStart;
SelectedRtf = @"{\rtf1{\fonttbl{\f0\fcharset2 " + this.Font.FontFamily.Name + @";}}\f0\fs" + this.Font.SizeInPoints * 2 + @" " + str + @"}}";
// Note that SelectedRtf does not contain the inserted text after the previous line. We need
// to determine how long the inserted string is in order to set its style. SelectionStart contains
// the location after the insertion.
int positionAfter = SelectionStart;
Select(positionStart, positionAfter - positionStart);
RTBAPI.SetFontStyle(this, fs);
Select(positionAfter, 0);
}
private void AddText(string str)
{
// See comments in AddRtf(string str) to explain the font style setting
RTBAPI.E_FontStyle fs = RTBAPI.GetFontStyle(this);
int positionStart = SelectionStart;
SelectedText = str;
int positionAfter = SelectionStart;
Select(positionStart, positionAfter - positionStart);
RTBAPI.SetFontStyle(this, fs);
Select(positionAfter, 0);
}
private void AddSymbol(string str)
{
// See comments in AddRtf(string str) to explain the font style setting
RTBAPI.E_FontStyle fs = RTBAPI.GetFontStyle(this);
int position = SelectionStart;
SelectedRtf = RtfPrefixForSymbols + str + @"}";
Select(position, 1);
RTBAPI.SetFontStyle(this, fs);
Select(position + 1, 0);
SelectionFont = MyItemInfo.GetItemFont().WindowsFont;
}
private string GetAddSymbolText(string symtxt)
{
return (@"{\f0\fs" + this.Font.SizeInPoints * 2 + @" " + symtxt + @"}");
}
public void AddRtfLink(string linkUrl, string linkValue)
{
if (CreateParams.ClassName == "RICHEDIT50W")
AddLink50(linkUrl, linkValue);
else
AddLink20(linkUrl, linkValue);
}
public string FontTable
{
get
{
StringBuilder sb = new StringBuilder();
sb.Append(@"{\fonttbl{\f0\fnil\fcharset2 " + this.Font.FontFamily.Name + @";}");
if (!FontIsFixed(this.Font))
sb.Append(@"{\f1\fnil\fcharset0 Arial Unicode MS;}}");
else
sb.Append(@"{\f1\fnil\fcharset0 VESymbFix;}}");
return sb.ToString();
}
}
private string FontSize
{
get
{
Match match = Regex.Match(Rtf, @"\\fs[0-9]*");
return match.Value;
}
}
private void AddLink20(string linkValue, string linkUrl)
{
string fonttab = FontTable;
string fontsize = FontSize;
//if (this.DetectUrls) this.DetectUrls = false;
if (SelectionLength > 0)HandleDeleteKeyWithSelectedText(new KeyEventArgs(Keys.None), null);
int position = SelectionStart;
SelectionLength = 0;
linkValue = linkValue.Replace("\\u8209?", "\\f1\\u8209?\\f0 ");
SelectedRtf = @"{\rtf1\ansi"+FontTable+@"{\colortbl ;\red255\green0\blue0;}\v"+FontSize+@" <START]\v0\cf1 " + linkValue + @"\cf0\v " + linkUrl + @"[END>\v0 }";
this.SelectionLength = 0;
this.SelectionStart = position;
FindAllLinks();
}
private void AddLink50(string linkValue, string linkUrl)
{
//this.DetectUrls = false;
int position = SelectionStart;
SelectionLength = 0;
SelectedRtf = string.Format(@"{{\rtf\field{{\*\fldinst{{HYPERLINK ""www.volian.com #{0}"" }}}}{{\fldrslt{{\cf2\ul {1}}}}}}}", linkUrl, linkValue);
this.SelectionStart = this.TextLength;
this.SelectionLength = 0;
}
private void AddRtfStyles()
{
if ((OrigDisplayText.TextFont.Style & E_Style.Bold) > 0)
{
this.SelectAll();
RTBAPI.ToggleBold(true, this, RTBAPI.RTBSelection.SCF_SELECTION);
this.Select(0, 0);
}
// Bug Fix
// The code below was changed to select all of the text and then
// apply the underlining to the selected text, because if the
// the underlining was applied to RTBAPI.RTBSelection.SCF_ALL
// the Links were changed so that they were no longer hidden.
if ((OrigDisplayText.TextFont.Style & E_Style.Underline) > 0)
// RTBAPI.ToggleUnderline(true, this, RTBAPI.RTBSelection.SCF_ALL);
{
this.SelectAll();
RTBAPI.ToggleUnderline(true, this, RTBAPI.RTBSelection.SCF_SELECTION);
this.Select(0, 0);
}
// Bug Fix
// The code below was changed to select all of the text and then
// apply the italics to the selected text, because if the
// the italics was applied to RTBAPI.RTBSelection.SCF_ALL
// the Links were changed so that they were no longer hidden.
if ((OrigDisplayText.TextFont.Style & E_Style.Italics) > 0)
// RTBAPI.ToggleItalic(true, this, RTBAPI.RTBSelection.SCF_ALL);
{
this.SelectAll();
RTBAPI.ToggleItalic(true, this, RTBAPI.RTBSelection.SCF_SELECTION);
this.Select(0, 0);
}
}
#endregion
#region HeightSupport
public event StepRTBEvent HeightChanged;
private void OnHeightChanged(object sender, EventArgs args)
{
if (HeightChanged != null) HeightChanged(sender, args);
}
private void AdjustSizeForContents(bool adjustWidth)
{
if (!_InitializingRTB)
{
Size offset = Size - ClientSize;
int widthNew = (this is TableCellEditor) ? Width : (ContentsSize.Width + offset.Width + AdjustSize.Width);
//int widthNew = Width;
//if (!(this is TableCellEditor))
// widthNew = ContentsSize.Width + offset.Width + AdjustSize.Width;
int heightNew = ContentsSize.Height + offset.Height + AdjustSize.Height;
// Don't make the window narrower unless it has text - RHM - 20100107
Size szNew = new Size(((Text != "" && adjustWidth) ? widthNew : (widthNew > Width ? widthNew : Width)), heightNew);
if (this.Size != szNew)
{
int heightOld = Height;
//Console.WriteLine("before {0}, {1}, {2}, {3}, {4}", Size, szNew, widthNew, Width, this.GetType().Name);
this.Size = szNew;
//Console.WriteLine("after {0}, {1}, {2}, {3}", Size, szNew, widthNew, Width);
if (heightOld != Height)
{
OnHeightChanged(this, new EventArgs());
if (ScrollPos.Y != 0) // Adjust ScrollPosition if it isn't Zero
ScrollPos = new Point(0, 0);
}
}
}
}
private float GetStringWidth(string strMeasureString)
{
using (Graphics g = Graphics.FromHwnd(Handle))
{
return g.MeasureString(strMeasureString, Font).Width;
}
}
private int Ceiling(float f)
{
return (int)(Math.Ceiling(f));
}
public int MaxTextWidth
{
get
{
int maxWidth = 0;
for (int i = 0; i < TextLength; i++)
{
int w = GetPositionFromCharIndex(i).X;
maxWidth = Math.Max(maxWidth, w);
}
return maxWidth+10; // add 10 to account for the last character
}
}
public void AdjustWidthForContent()
{
int widthNL = Ceiling(GetStringWidth("\n"));
int widthMax = 0;
int widthMaxWW = 0;
int indexStart = 0;
int lineCountFromLines = Lines.Length;
int lineCountFromGet = GetLineFromCharIndex(TextLength)+1;
for (int i = 0; i < Lines.Length; i++)
{
int lineStart = GetLineFromCharIndex(indexStart);
int indexEnd = indexStart + Lines[i].Length;
int lineEnd = GetLineFromCharIndex(indexEnd);
Point pointStart = GetPositionFromCharIndex(indexStart);
Point pointEnd = GetPositionFromCharIndex(indexEnd);
int indexEndPos = GetCharIndexFromPosition(pointEnd);
if (indexEndPos + 1 < indexEnd) // This indicates that the text is wider than the Rich Text Box
{
int w = pointEnd.X + (indexEnd - indexEndPos) * widthNL;
if (w > widthMaxWW)
{
widthMaxWW = w;
}
}
if (lineEnd > lineStart)// this indicates that there was word-wrap on this line.
{
int w = pointEnd.X + Width * (lineEnd - lineStart);
if (w > widthMaxWW)
widthMaxWW = w;
}
else
{
if (pointEnd.X > widthMax)
widthMax = pointEnd.X;
}
indexStart = indexEnd + 1;
}
if (widthMaxWW == 0)
{
int widthBorder = Width - ClientSize.Width;
int w = widthMax + widthNL + widthBorder;
if (Width != w)
{
Width = w;
AdjustWidthForContent();// Try one more time
}
}
else
{
Width = widthMaxWW;
AdjustWidthForContent();
}
}
public int CalculateHeight()
{
if (this.CreateParams.ClassName == "RICHEDIT50W")
return CalculateHeight50();
else
return CalculateHeight20();
}
private int CalculateHeight20()
{
Application.DoEvents();
int yBottom = GetPositionFromCharIndex(TextLength).Y;
int yTop = GetPositionFromCharIndex(0).Y;
int heightFont = SelectionFont.Height;
int borderSize = this.Height - this.ClientSize.Height;
int heightNext = (yBottom - yTop) + heightFont + borderSize + 2;// 2 pixels - 1 at the top and 1 at the bottom
if (heightNext != Height)
{
Height = heightNext;
OnHeightChanged(this, new EventArgs());
ScrollPos = new Point(0, 0); // Scroll to make sure that the first line is displayed as the first line
}
return heightNext;
}
private int CalculateHeight50()
{
Application.DoEvents();
int heightFont = SelectionFont.Height;
int borderSize = this.Height - this.ClientSize.Height;
int heightNext = (1 + GetLineFromCharIndex(TextLength)) * heightFont + borderSize + 2;// 2 pixels - 1 at the top and 1 at the bottom
return heightNext;
}
#endregion
#region ColorSupport - Not currently used.
//private void SetBackGroundColor(ItemInfo itemInfo)
//{
// string backcolor = null;
// int type = (int)itemInfo.MyContent.Type;
// FormatInfo formatinfo = itemInfo.ActiveFormat;
// if (type == (int)E_FromType.Procedure)
// backcolor = formatinfo.PlantFormat.FormatData.ProcData.BackColor;
// else if (type == (int)E_FromType.Section)
// backcolor = formatinfo.PlantFormat.FormatData.SectData.BackColor;
// else
// {
// int typindx = (int)itemInfo.MyContent.Type - 20000; // what to do for other types rather than steps
// backcolor = formatinfo.PlantFormat.FormatData.StepDataList[typindx].StepLayoutData.BackColor;
// }
// BackColor = Color.FromName(backcolor);
//}
#endregion
#region EventSupport
#region LinkEvents
private StepPanelLinkEventArgs _MyLinkClickedEventArgs;
public event StepRTBLinkEvent LinkChanged;
private void OnLinkChanged(object sender, StepPanelLinkEventArgs args)
{
_MyLinkClickedEventArgs = args;
if (LinkChanged != null) LinkChanged(sender, args);
}
public event StepRTBLinkEvent LinkGoTo;
private void OnLinkGoTo(object sender, StepPanelLinkEventArgs args)
{
_MyLinkClickedEventArgs = args;
if (LinkGoTo != null) LinkGoTo(sender, args);
}
public event StepRTBLinkEvent LinkModifyTran;
private void OnLinkModifyTran(object sender, StepPanelLinkEventArgs args)
{
_MyLinkClickedEventArgs = args;
if (LinkModifyTran != null) LinkModifyTran(sender, args);
}
public event StepRTBLinkEvent LinkModifyRO;
private void OnLinkModifyRO(object sender, StepPanelLinkEventArgs args)
{
_MyLinkClickedEventArgs = args;
if (LinkModifyRO != null) LinkModifyRO(sender, args);
}
#endregion
#region TextAndContentsEvents
void StepRTB_TextChanged(object sender, EventArgs e)
{
if (_InitializingRTB) return;
// Was setting _IsDirty to true here, but this was getting called from
// 'dotnetbar' when text was NOT Changed. So _IsDirty was made into
// a property and compared original rtf versus current richtextbox's
// rtf.
// the below 2 lines were added to solve the problem with the change manager detail not showing the text of an audit when the same audit
//was selected twice
if (Text == string.Empty)
LastRtf = string.Empty;
FindAllLinks();
}
public void StepRTB_ContentsResized(object sender, ContentsResizedEventArgs e)
{
ContentsRectangle = e.NewRectangle;
}
#endregion
#region Selection Handlers
bool _AdjustingSelection = false;
private bool _ProcessingDelete;
private bool _HandlingCtrlA = false;
private void HandleLocalSelectionChange()
{
//if (MyRTBItem != null && MyRTBItem.MyStepPanel.SelectedStepRTB != this)
if (OnIsNotCurrentSelection(this, new EventArgs()))
return;
HandleSelectionChange();
}
private void HandleSelectionChange()
{
if (_HandlingCtrlA) return;
if (!_HandlingCtrlA && this.TextLength == this.SelectionLength && this.SelectedRtf.EndsWith("\\par\r\n}\r\n"))
{
_HandlingCtrlA = true;
SelectAll();
_HandlingCtrlA = false;
}
//HandleOverWrite();
//vlnStackTrace.ShowStackLocal("HandleSelectionChangeStack", 1, 10);
bool startingValue = _AdjustingSelection;
if (_IdentifyingLinks || _ProcessingDelete) return;
// If the cursor is beyond the end of the line then move the cursor back one character
if (CorrectSelectionAtEndOfLine())
return;
if (ProcessKeystrokes)
{
if (!_MouseDown && !_AdjustingSelection)
{
if (_LinkLocations != null)
{
DebugPrint("HSC===================>Beginning: SelectionStart {0}, SelectionLength {1}", SelectionStart, SelectionLength);
_AdjustingSelection = true;
LinkLocation ll = FindLinkLocation();
LinkLocation llend = null;
if (SelectionLength != 0)
llend = FindLinkLocation(SelectionStart + SelectionLength - 1);
if (ll != null)
{
if (SelectionStart == ll.Start && SelectionLength == 0)
{
if (SelectionStart >= 7)
{
// If the cursor is at the beginning of the line and a link is at the beginning of the line
// then select the link rather than postitioning the cursor at the end of the previous line
if (!_LastWasLeftArrow && GetFirstCharIndexOfCurrentLine() == SelectionStart)
SetSelection(ll);
else
{
DebugPrint("HSC===================>ll Insert: Sel {0}, Length {1}, Link Start {2}, Link Length {3}", SelectionStart, SelectionLength, ll.Start, ll.Length);
SelectionStart = ll.Start - 7;
}
}
}
else if (SelectionStart + SelectionLength > ll.End) // Beyond the end of the starting link
{
int end = SelectionStart + SelectionLength;
if (llend != null) end = llend.End; // If it extends into another link extend the end to the end of that link
DebugPrint("HSC===================>ll After: Sel {0}, Length {1}, Link Start {2}, Link Length {3}", SelectionStart, SelectionLength, ll.Start, ll.Length);
SetSelection(ll.Start, end - ll.Start);
}
else if (SelectionStart >= ll.Start || SelectionLength > 0)// Within the starting link
{
DebugPrint("HSC===================>ll: Sel {0}, Length {1}, Link Start {2}, Link Length {3}", SelectionStart, SelectionLength, ll.Start, ll.Length);
SetSelection(ll);
}
}
else if (llend != null)
{
DebugPrint("HSC===================>llend: Sel {0}, Length {1}, Link Start {2}, Link Length {3}", SelectionStart, SelectionLength, llend.Start, llend.Length);
// Check to see if the beginning starts before the <START] token. If it does, adjust the start
int newStart = SelectionStart + (SelectedText.StartsWith("<START]") ? 7 : 0);
SetSelection(newStart, llend.End - newStart);
}
else
{
if (SelectedText.EndsWith("<START]") && !SelectedText.EndsWith("[END><START]"))
{
DebugPrint("HSC===================>Removing ending <START] token");
SelectionLength = SelectionLength - 7;
}
if (SelectedText.StartsWith("<START]"))
{
DebugPrint("HSC===================>Removing starting <START] token");
SetSelection(SelectionStart + 7, SelectionLength - 7);
}
}
_AdjustingSelection = false;
}
}
}
if (startingValue != _AdjustingSelection)
DebugPrint("================> _AdjustingSelection problem");
DebugPrint("RS------ SelectionChange > {0}", FindRangeStatus());
if (SelectionLength > 0 && IsSelectionLinked(SelectionStart, SelectionLength))
{
if (SelectedText.IndexOf(@"[END>") > 0) MyLinkText = SelectedText.Substring(0, SelectedText.IndexOf(@"[END>"));
else MyLinkText = SelectedText;
}
else
MyLinkText = null;
OnRTBSelectionChanged(this, new EventArgs());
_LastWasLeftArrow = false;
}
/// <summary>
/// If the Selection is beyond the end of the line, move the selection back one character
/// </summary>
/// <returns></returns>
private bool CorrectSelectionAtEndOfLine()
{
if (SelectionStart > 0 && SelectionLength == 0 &&
GetFirstCharIndexFromLine(GetLineFromCharIndex(SelectionStart)) >
GetFirstCharIndexOfCurrentLine())
{
SelectionStart--; // Move the cursor back one character
return true;
}
return false;
}
//private void HandleOverWrite()
//{
// if (!_OverWrite) return;
// if (SelectionLength > 0) return;
// if (SelectionStart == TextLength) return;
// Console.WriteLine("Handle Overwrite, SelectionStart = {0}, SelectionLength = {1}", SelectionStart, SelectionLength);
// SelectionLength = 1;
//}
private bool _CheckSelection = false;
#endregion
#region Delete Handlers
private void HandleDeleteKeyWithSelectedText(KeyEventArgs e, string keychars)
{
_ProcessingDelete = true;
FindRangeStatus();
//DebugPrint("RS---------------- Delete > {0}", _RTBRangeStatus);
switch (_RTBRangeStatus)
{
case RangeStatus.NoContainedLinks:
case RangeStatus.Before_After:
case RangeStatus.Before_EndLink:
case RangeStatus.Before_EndBox:
default:
DeleteCurrentSelection(keychars);
e.SuppressKeyPress = true;
break;
case RangeStatus.Before_Between: //myRTB1.SelectedText.EndsWith(@"[END><START]")
DeleteEndBetweenLinks(keychars);
e.SuppressKeyPress = true;
break;
case RangeStatus.Between_EndBox:
case RangeStatus.Between_EndLink:
case RangeStatus.Between_After:
DeleteStartBetweenLinks(keychars);
e.SuppressKeyPress = true;
break;
case RangeStatus.Between_Between:
DeleteBetweenBetweenLinks(keychars);
e.SuppressKeyPress = true;
break;
case RangeStatus.StartLink_EndBox:
case RangeStatus.StartLink_EndLink:
case RangeStatus.StartLink_After:
ExpandSelectionToIncludeStart();
DeleteCurrentSelection(keychars);
e.SuppressKeyPress = true;
break;
case RangeStatus.StartLink_Between:
ExpandSelectionToIncludeStart();
DeleteEndBetweenLinks(keychars);
e.SuppressKeyPress = true;
break;
case RangeStatus.StartBox_EndLink:
case RangeStatus.StartBox_EndBox:
case RangeStatus.StartBox_After:
DeleteFromStartOfBox(keychars);
e.SuppressKeyPress = true;
break;
case RangeStatus.StartBox_Between:
DeleteFromStartOfBoxEndBetweenLinks(keychars);
e.SuppressKeyPress = true;
break;
// REMOVE THESE CASES OR PUT A MESSAGE OUT SAYING ERROR IN CODE - CASE
// NOT HANDLED
case RangeStatus.Before_StartLink:
case RangeStatus.Between_StartLink:
case RangeStatus.StartLink_StartLink:
case RangeStatus.StartBox_StartLink:
break;
}
_ProcessingDelete = false;
StepRTB_TextChanged(this, new EventArgs());
}
private void InsertCharBetweenLinks(LinkLocation ll)
{
InsertCharBetweenLinks(ll, ' ', false);
}
private void InsertCharBetweenLinks(LinkLocation ll, string strToAdd)
{
InsertCharBetweenLinks(ll, strToAdd, true);
}
private void InsertCharBetweenLinks(LinkLocation ll, string strToAdd, bool setSelect)
{
Rtf = Rtf.Substring(0, ll.StartRtf) + @"\v0 " + strToAdd + @"\v " + Rtf.Substring(ll.StartRtf);
if (setSelect)
SelectionStart = ll.Start - 6; // account for <START] - 1 for the character typed
}
/// <summary>
/// This inserts a space in between two links.
/// It actually inserts "\v0 {space}\v " between the END tag and the START tag
/// </summary>
/// <param name="ll"></param>
/// <param name="charToAdd"></param>
/// <param name="setSelect"></param>
private void InsertCharBetweenLinks(LinkLocation ll, char charToAdd, bool setSelect)
{
//_InsertingSpaceBetweenLinks = true;
DebugPrint("ICBLvvvvvvvvvvvvvvv>>>");
Rtf = Rtf.Substring(0, ll.StartRtf) + @"\v0 " + charToAdd.ToString() + @"\v " + Rtf.Substring(ll.StartRtf);
//_InsertingSpaceBetweenLinks = false;
if (setSelect)
SelectionStart = ll.Start - 6; // account for <START] - 1 for the character typed
DebugPrint("ICBL^^^^^^^^^^^^^^^>>>");
}
private void ExpandSelectionToIncludeStart()
{
//_AdjustingSelection = true;
SetSelection(SelectionStart - 7, SelectionLength + 7); // Expand selection to include start
//_AdjustingSelection = false;
}
public string GetSelectionForClipBoard()
{
string selTxtRTF = SelectedRtf;
LinkLocation llstart = FindLinkLocation();
if (llstart != null)
{
selTxtRTF = Rtf.Substring(llstart.StartRtf, llstart.EndRtf - llstart.StartRtf);
string lookfor = selTxtRTF.Substring(selTxtRTF.IndexOf(' '));
return SelectedRtf.Replace(lookfor, @"\v " + selTxtRTF);
}
return (selTxtRTF);
}
private void DeleteBetweenBetweenLinks(string keychars)
{
DebugSelection("DeleteBetweenBetweenLinks");
int selStart = SelectionStart - 7;
int selLength = SelectionLength + 2; // Include the two added spaces
InsertCharBetweenLinks(_RangeEndLink.NextLink); // Add a space at the end link
InsertCharBetweenLinks(_RangeStartLink); // Add a space a the start link
SetSelection(selStart, selLength);// Select everything including the spaces
DeleteCurrentSelection(keychars);// Delete Selection
}
/// <summary>
/// This is added to handle a glitch in richtextbox. Depending on
/// which direction that selection is made (left -> right or right -> left)
/// a replacement or delete may not work, you'll just get a 'beep'.
/// This approach consistently works.
/// </summary>
public bool WasXDelete = false;
private void DeleteCurrentSelection(string keys)
{
DebugPrint("vvvvvvvvvvvvxxxxxxxxxxxx>");
DebugSelection("Before X");
DebugPrint(keys == null ? "NULL" : "NOT NULL");
SelectedText = keys==null?"X":keys; // replace text with X
WasXDelete = (keys == null);
DebugSelection("After X");
DebugPrint("------------xxxxxxxxxxxx>");
if (keys == null)
{
_SendBackSpace = true;
RtbSendKeys("{BS}"); // remove X
//this.ClearUndo(); // undo was redisplay 'X' and then deleted text
Application.DoEvents();
DebugSelection("After BS");
}
DebugPrint("^^^^^^^^^^^^xxxxxxxxxxxx>");
}
private void DeleteSelection(int start, int length, string keychars)
{
SetSelection(start, length);
DeleteCurrentSelection(keychars);
}
private void DeleteEndBetweenLinks(string keychars)
{
_ProcessingKeys++;
DebugSelection("DeleteEndBetweenLinks");
int sstart = SelectionStart;
int slen = SelectionLength + 1 - 7;
// This puts a space at the link that starts at the end of the selection
InsertCharBetweenLinks(_RangeEndLink.NextLink);
//_AdjustingSelection = true;
DeleteSelection(sstart, slen, keychars);
//_AdjustingSelection = false;
_ProcessingKeys--;
}
private void DeleteStartBetweenLinks(string keychars)
{
_ProcessingKeys++;
DebugSelection("DeleteStartBetweenLinks");
int slen = SelectionLength + 8;
int sstart = SelectionStart - 7;
//LinkLocation ll = FindBetweenLinks(SelectionStart);
InsertCharBetweenLinks(_RangeStartLink);
DeleteSelection(sstart, slen, keychars);
_ProcessingKeys--;
}
private void DeleteFromStartOfBox(string keychars)
{
_ProcessingKeys++;
DebugSelection("DeleteFromStartOfBox");
int slen = SelectionLength;
SetSelection(0, 0);
//RtbSendKeys(" "); // open for space between links which separates END/START tokens
SelectedText = " ";
DeleteSelection(0, slen + 8, keychars);
_ProcessingKeys--;
}
private void DeleteFromStartOfBoxEndBetweenLinks(string keychars)
{
_ProcessingKeys++;
DebugSelection("DeleteFromStartOfBoxEndBetweenLinks");
// This puts a space at the link that starts at the end of the selection
int sLen = SelectionStart + SelectionLength - 7 + 2;// -7 for <START] + 2 for the spaces that are added
//LinkLocation ll = FindBetweenLinks(SelectionStart + SelectionLength);
InsertCharBetweenLinks(_RangeEndLink.NextLink);
//RtbSendKeys("{RIGHT} "); // open for space between links which separates END/START tokens
//int sLen = myRTB1.SelectionStart;
SetSelection(0, 0);
//RtbSendKeys(" "); // open for space between links which separates END/START tokens
SelectedText = " "; // open for space between links which separates END/START tokens
DeleteSelection(0, sLen, keychars);
_ProcessingKeys--;
}
#endregion
#region KeyboardHandling
void StepRTB_KeyUp(object sender, KeyEventArgs e)
{
if (e.Control)
{
if (e.Alt)
{
switch (e.KeyCode)
{
case Keys.M:
OnOpenAnnotations(this, new EventArgs());
e.Handled = true;
break;
default:
break;
}
}
if (e.Shift)
{
switch (e.KeyCode)
{
case Keys.F:
OnSetMenu(this, new StepRTBMenuEventArgs("InsFigure"));
e.Handled = true;
break;
case Keys.T:
OnSetMenu(this, new StepRTBMenuEventArgs("InsTable"));
e.Handled = true;
break;
case Keys.N:
OnSetMenu(this, new StepRTBMenuEventArgs("InsNote"));
e.Handled = true;
break;
case Keys.C:
OnSetMenu(this, new StepRTBMenuEventArgs("InsCaution"));
e.Handled = true;
break;
case Keys.S:
OnSetMenu(this, new StepRTBMenuEventArgs("InsSubStps"));
e.Handled = true;
break;
case Keys.H:
OnSetMenu(this, new StepRTBMenuEventArgs("InsHLS"));
e.Handled = true;
break;
case Keys.R:
OnSetMenu(this, new StepRTBMenuEventArgs("InsRNO"));
e.Handled = true;
break;
}
}
}
if (!e.Shift) return;
switch (e.KeyCode)
{
// this was put here rather than in the KeyDown event like the others
// so that processing of keystroke (StepRTB_KeyDown) would position selectionstart
// and selectionlength
case Keys.Down:
int newend = FindEndDown();
if (newend > 0) SetSelection(SelectionStart, newend - SelectionStart);
break;
case Keys.Space:
if (e.Control) // Hardspace - Ctrl+Shift+Space
InsertSymbol(@"\u160?");
break;
case Keys.F3: // shift F3
e.Handled = true;
ToggleCase(); // toggle through Upper, Lower, and Title case
break;
default:
break;
}
}
private string GetSelectedDisplayableText()
{
using (StepRTB srtb = new StepRTB())
{
srtb.Rtf = this.SelectedRtf.Replace(@"\u8209?", "-");
string rtnstr = "";
string ctxt = srtb.Text;//this.SelectedText;
if (ctxt.EndsWith("<START]"))
ctxt = ctxt.Substring(0, ctxt.Length - 7);
int idx = 0;
int strtidx = ctxt.IndexOf("<START]");
int lnkidx = ctxt.IndexOf("#Link");
int endidx = ctxt.IndexOf("[END>");
if ((strtidx == -1 || strtidx > lnkidx) && lnkidx > -1 && endidx > -1)
{
rtnstr += ctxt.Substring(idx, lnkidx);
idx = endidx + 5;
strtidx = ctxt.IndexOf("<START]", idx);
lnkidx = ctxt.IndexOf("#Link:", idx);
endidx = ctxt.IndexOf("[END>", idx);
}
while (strtidx > -1)
{
rtnstr += ctxt.Substring(idx, strtidx - idx);
idx = strtidx + 7;
rtnstr += ctxt.Substring(idx, lnkidx - idx);
idx = endidx + 5;
strtidx = ctxt.IndexOf("<START]", idx);
lnkidx = ctxt.IndexOf("#Link:", idx);
endidx = ctxt.IndexOf("[END>", idx);
}
if (idx < ctxt.Length)
rtnstr += ctxt.Substring(idx);
return rtnstr;
}
}
private bool IsControlChar = false;
private bool _SendBackSpace = false;
void StepRTB_KeyDown(object sender, KeyEventArgs e)
{
if (e.Control)
{
IsControlChar = true;
switch (e.KeyCode)
{
case Keys.X: //ctrl-X
case Keys.C: //ctrl-C
// handle the clipboard copy and cut when a Transition or RO is selected
// For now, we are coping/cutting just the displayed text to the clipboard (like 16-bit VE-PROMS)
string ts = GetSelectedDisplayableText();
if (ts!=null&&ts!="") Clipboard.SetText(GetSelectedDisplayableText());
e.Handled = true;
e.SuppressKeyPress = true;
if (ts!=null&&ts!=""&&e.KeyCode == Keys.X) // cut to clipboard - delete the selected text
HandleDeleteKeyWithSelectedText(e, null);
break;
case Keys.V:
IDataObject iData = Clipboard.GetDataObject();
if (!iData.GetDataPresent(DataFormats.Text) && !iData.GetDataPresent(DataFormats.Rtf))
{
MessageBox.Show("Cannot paste, text has special characters or symbols that will not paste correctly.");
}
else
{
Paste();
if (SelectionLength == 0) SelectionFont = MyStyleFont.WindowsFont;
}
e.Handled = true;
return;
case Keys.Home:
StepRTB_HomeEndPressed(e);
e.Handled = true;
break;
case Keys.End:
StepRTB_HomeEndPressed(e);
e.Handled = true;
break;
// 16bit Proms used 'ctrl-enter' for Hard returns. 32bit Proms uses 'shift-enter'
// because the richtextbox does this by default. Also Word uses 'shift-enter'
// for Hard return. And Word uses 'ctrl-enter' for inserting of page break. So
// 'ctrl-enter' for 32bit will insert page break
case Keys.Enter:
OnInsertPgBrk(this, new EventArgs());
e.Handled = true;
break;
}
}
if (((int)e.KeyCode) == 220) e.Handled = true;
switch (e.KeyCode)
{
case Keys.Left:
if (e.Shift)
{
int newstart = FindStart(); // find start of link ending on.
// if not link, don't do special processing
if (newstart == SelectionStart - 1) return;
int len = SelectionLength + SelectionStart - newstart;
SetSelection(newstart, len);
e.Handled = true;
return;
}
if (e.Control || SelectionStart == 0)
{
StepRTB_ArrowPressed(e.Control ? E_ArrowKeys.CtrlLeft : E_ArrowKeys.Left);
e.Handled = true;
}
HandleLocalSelectionChange();
break;
case Keys.Up:
int ln = GetLineFromCharIndex(SelectionStart);
if (e.Control || ln == 0)
{
StepRTB_ArrowPressed(e.Control ? E_ArrowKeys.CtrlUp : E_ArrowKeys.Up);
e.Handled = true;
}
// if shift-up & at selection had a link, handle this as special case.
if (e.Shift && SelectionLength > 0)
{
RangeStatus rs = FindRangeStatus();
if (rs != RangeStatus.NoContainedLinks)
{
int curend = SelectionStart + SelectionLength;
SelectionLength = 0;
RtbSendKeys("{Up}");
Application.DoEvents();
Select(SelectionStart, curend - SelectionStart);
e.Handled = true;
}
}
else
{
HandleLocalSelectionChange();
}
break;
case Keys.Right:
// If at beginning of box that starts with a link, don't worry about shift or not,
// because selection is first character or link without any other selection. Don't
// need to write code to handle link at beginning of box in Shift Right code because
// it's handled in HandleSelectionChange.
if (e.Shift && ((SelectionStart > 0) || (SelectionStart == 0 && _LinkLocations.Count > 0 && _LinkLocations[0].Start != 7)))
{
int newlen = FindEnd();
int len = SelectionLength + newlen;
SetSelection(SelectionStart, len);
e.Handled = true;
return;
}
if (e.Control || SelectionStart == this.Text.Length)
{
StepRTB_ArrowPressed(e.Control ? E_ArrowKeys.CtrlRight : E_ArrowKeys.Right);
e.Handled = true;
}
HandleLocalSelectionChange();
break;
case Keys.Down:
int l = GetLineFromCharIndex(SelectionStart);
Point pos = new Point();
pos.X = ClientRectangle.Width;
pos.Y = ClientRectangle.Height;
int lastIndex = this.GetCharIndexFromPosition(pos);
int lastLine = this.GetLineFromCharIndex(lastIndex);
if (e.Control || l >= lastLine)
{
StepRTB_ArrowPressed(e.Control ? E_ArrowKeys.CtrlDown : E_ArrowKeys.Down);
HandleLocalSelectionChange();
e.Handled = true;
return;
}
if (!e.Shift) HandleLocalSelectionChange();
// if shift-down & on link at beginning of box - do special processing (regular processing
// didn't handle it correctly.
if (e.Shift && lastLine > 0 && SelectionStart == 0 && _LinkLocations.Count > 0 && _LinkLocations[0].Start == 7)
{
Point cpos = GetPositionFromCharIndex(SelectionStart);
int addon = ClientRectangle.Height / (lastLine + 1);
cpos.Y = cpos.Y + addon;
int selend = GetCharIndexFromPosition(cpos);
Select(7, selend - 7);
e.Handled = true;
}
break;
case Keys.PageUp:
StepRTB_PageKeyPressed(e);
e.Handled = true;
break;
case Keys.PageDown:
StepRTB_PageKeyPressed(e);
e.Handled = true;
break;
case Keys.Delete:
if (SelectionLength == 0)
{
foreach (LinkLocation lls in _LinkLocations)
{
if (SelectionStart >= lls.Start - 7 && SelectionStart < lls.End)
{
SetSelection(lls);// Select the link to the right
HandleDeleteKeyWithSelectedText(e, null);
e.SuppressKeyPress = true;
return;
}
}
if (SelectionStart != TextLength)
{
SelectionStart++;// A Delete can be accomplished with a right arrow followed by a backspace.
RtbSendKeys("{BS}"); // This is done due to a glitch in the RichTextBox that sometimes causes a beep rather than a delete
e.SuppressKeyPress = true;
}
}
else
HandleDeleteKeyWithSelectedText(e, null);
break;
case Keys.Back:
if (_SendBackSpace)
{
_SendBackSpace = false;
return;
}
_CheckSelection = true;
if (SelectionLength == 0)
{
foreach (LinkLocation lls in _LinkLocations)
{
if (SelectionStart > lls.Start - 7 && SelectionStart <= lls.End)
{
SetSelection(lls);
break;
}
}
}
if (SelectionLength > 0) HandleDeleteKeyWithSelectedText(e, null);
break;
case Keys.Insert:
//_OverWrite = !_OverWrite;
//if (_OverWrite)
//{
// HandleSelectionChange();
//}
//else
//{
// SelectionLength = 0;
// HandleSelectionChange();
//}
// For now, don't allow for toggling between insert/overwrite mode - see
// comment on _OverWrite
e.Handled = true;
break;
case Keys.F5:
if (e.Shift)
{
e.Handled = true;
if (!OnCheckClipboard(this, new EventArgs())) return; // check if 'clipboard' contains a step.
OnSetMenu(this, new StepRTBMenuEventArgs("StepPaste"));
}
else if (!e.Control && !e.Alt)
{
e.Handled = true;
OnCopyStep(this, new EventArgs());
}
break;
case Keys.F6:
e.Handled = true;
SendKeys.Send("%H{ESC}");
break;
case Keys.Tab:
VlnFlexGrid myGrid = Parent as VlnFlexGrid;
if (myGrid == null)
{
e.SuppressKeyPress = true;
e.Handled = true;
Form frm = ParentForm(this);
if (frm != null)
frm.SelectNextControl(this, true, true, true, true);
}
else
{
if (e.Shift)
{
e.SuppressKeyPress = true;
e.Handled = true;
if (!myGrid.SelectPrevCell())
{
// don't do anything if at top (for now)
}
}
else
{
e.SuppressKeyPress = true;
e.Handled = true;
if (!myGrid.SelectNextCell())
{
myGrid.MyBorders.InsertRow(myGrid.Rows.Count - 1);
myGrid.Rows.Add(1);
myGrid.SelectNextCell();
}
}
}
break;
case Keys.Enter:
if (!e.Control && !e.Shift && !e.Alt)
{
OnEnterKeyPressed(sender, e);
}
break;
}
}
private static Form ParentForm(Control ctrl)
{
while (!(ctrl.Parent is Form || ctrl.Parent is EditItem))
ctrl = ctrl.Parent;
return ctrl.Parent as Form;
}
private void StepRTB_HomeEndPressed(KeyEventArgs keyargs)
{
if (MyItemInfo.IsProcedure || MyItemInfo.IsSection) return;
// Cursor moves out of box only if control is pressed too - otherwise key is
// handled in rtb.
//if (keyargs.Control)MyRTBItem.MyStepPanel.StepCursorKeys(this, keyargs); // Replaced with an event
if (keyargs.Control) OnCursorKeyPress(this, keyargs);
}
private void StepRTB_PageKeyPressed(KeyEventArgs keyargs)
{
if (MyItemInfo.IsProcedure || MyItemInfo.IsSection) return;
//MyRTBItem.MyStepPanel.StepCursorKeys(this, keyargs); Replaced with an event
OnCursorKeyPress(this, keyargs);
}
public void StepRTB_ArrowPressed(E_ArrowKeys key)
{
Point cp = PointToClient(Cursor.Position);
//MyRTBItem.MyStepPanel.CursorMovement(this, cp, key); Replaced with an event
OnCursorMovement(this, new StepRTBCursorMovementEventArgs(cp, key));
}
private void StepRTB_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
if (!ReadOnly)
{
// The richtextbox in steprtb does not properly place backslashes into the rtf text. It appears
// that the backslash is stored as a single backslash rather than a double backslash which
// causes the rtf/displaytext saving to strip additional characters. For now, the easiest
// approach is to not allow backslashes to be used. This is a 'temporary' fix for B2011-077.
if (e.KeyChar == 92)
{
MessageBox.Show("Backslash is not a usable character in PROMS", "Backslash", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
e.Handled = true;
return;
}
// add the character with its font depending on the char....
if (!IsControlChar)
{
string strpressed = null;
if (e.KeyChar == '-')
strpressed = GetAddSymbolText(@"\u8209?");
else
strpressed = e.KeyChar.ToString();
if (e.KeyChar >= ' ')
{
LinkLocation ll = FindBetweenLinks();
if (ll != null && SelectionLength == 0) // SelectionLength = 0 means insert
{
if (e.KeyChar == '}')
strpressed = @"\}";
else if (e.KeyChar == '{')
strpressed = @"\{";
InsertCharBetweenLinks(ll, strpressed); // e.KeyChar);
e.Handled = true;
}
else if (SelectionLength != 0)
{
HandleDeleteKeyWithSelectedText(new KeyEventArgs(Keys.None), strpressed);
e.Handled = true;
}
}
if (!e.Handled)
{
if (e.KeyChar == '-')
AddSymbol(@"\u8209?");
else if (e.KeyChar == '{')
AddRtf(@"\{");
else if (e.KeyChar == '}')
AddRtf(@"\}");
else
return;
e.Handled = true; // flag that it's been handled, otherwise, will get 2 chars.
}
if (e.Handled && SelectionLength != 0) SelectionFont = MyStyleFont.WindowsFont;
}
IsControlChar = false;
}
}
private void RtbSendKeys(string keys)
{
Focus();
SendKeys.Send(keys); // With .Net Framework 3.0 this can be replaced with EditingCommands
// http://msdn.microsoft.com/en-us/library/ms771634.aspx
}
private void DoDeleteEndBetweenLinks()
{
DebugSelection("Beginning");
int sstart = SelectionStart;
RtbSendKeys("{RIGHT} "); // open for space between links which separates END/START tokens
SetSelection(sstart, SelectionStart - sstart - 1); // 1 is accounting for typed space
DebugSelection("SetSelection");
RtbSendKeys("{DELETE}"); // deletes text including link
RtbSendKeys("{RIGHT}{BS}"); // deletes space that was added
}
private void DoDeleteStartBetweenLinks()
{
int slen = SelectionLength;
RtbSendKeys("{LEFT} ");
SetSelection(SelectionStart, slen + 7);
RtbSendKeys("{DELETE}");
RtbSendKeys("{BS}");
}
#endregion
#region LinkSelectionAndHandling
public bool IsSelectionLinked(int index, int len)
{
if (_LinkLocations == null)return false;
int sel = index;
int selLength = len;
foreach (LinkLocation ll in _LinkLocations)
{
// When the selector moved to the right of a link, the GOTO button was still lit.
// Removing the "+7" seems to have fixed this. - jsj 1/08/2010
//if (sel >= ll.Start && sel < ll.Start + ll.Length + 7) return true;
if (sel >= ll.Start && sel < ll.Start + ll.Length) return true;
}
return false;
}
/// <summary>
/// For use in Find/Replace.
/// If text is found is part of the link information and not the link value,
/// then we want to continue searching.
/// </summary>
/// <param name="index"></param>
/// <param name="len"></param>
/// <returns></returns>
public bool SkipLinkInfo(int index, int len)
{
if (_LinkLocations == null)return false;
int sel = index;
int selLength = len;
foreach (LinkLocation ll in _LinkLocations)
{
if (sel >= ll.Start - 7 && sel < ll.Start + ll.Length)
{
int pos = ll.Text.IndexOf("#Link:");
if (sel < ll.Start || sel >= ll.Start-7+pos)
return (true);
}
}
return false;
}
#endregion
#endregion
#region SelectionStack
Stack<SelectionData> _SelectionStack = null;
public Stack<SelectionData> SelectionStack
{
get
{
if (_SelectionStack == null)
_SelectionStack = new Stack<SelectionData>();
return _SelectionStack;
}
}
public void PushSelection()
{
SelectionStack.Push(new SelectionData(this));
}
public void PopSelection()
{
SelectionData selection = SelectionStack.Pop();
if (SelectionStack.Count == 0)
_SelectionStack = null;
Select(selection.SelectionStart, selection.SelectionLength);
}
public class SelectionData
{
int _SelectionStart;
public int SelectionStart
{
get { return _SelectionStart; }
set { _SelectionStart = value; }
}
int _SelectionLength;
public int SelectionLength
{
get { return _SelectionLength; }
set { _SelectionLength = value; }
}
public SelectionData(RichTextBox richTextBox)
{
_SelectionStart = richTextBox.SelectionStart;
_SelectionLength = richTextBox.SelectionLength;
}
}
#endregion
#region Link Support
int _ProcessingKeys = 0;
List<LinkLocation> _LinkLocations;
public List<LinkLocation> LinkLocations
{
get { return _LinkLocations; }
}
private int _FALLevel = 0;
private bool _IdentifyingLinks = false;
public void FindAllLinks()
{
if (_IdentifyingLinks || _ProcessingDelete) return;
//DebugPrint("FAL{0}vvvvvvvvvvvvvvvvvvvvvvvvv>>", ++_FALLevel);
_AdjustingSelection = true;
PushSelection();
FindLinks();
//IdentifyLinks();
PopSelection();
LinkLocation llx = FindLinkLocation();
if (_CheckSelection)
{
if (llx != null) SetSelection(llx.End, 0);
_CheckSelection = false;
}
_AdjustingSelection = false;
if (!_ProcessingDelete)
OnLinkLocationChanged(this, new EventArgs());
//DebugPrint("FAL{0}^^^^^^^^^^^^^^^^^^^^^^^^^>>", _FALLevel--);
}
private void FindLinks()
{
string str = Text;
_LinkLocations = new List<LinkLocation>();
MatchCollection matches = Regex.Matches(str, @"<START](.*?)[[]END>", RegexOptions.Singleline);
MatchCollection matchesRtf = Regex.Matches(Rtf, "<START](.*?)[[]END>", RegexOptions.Singleline);
LinkLocation thisLink = null;
for (int i = 0; i < matches.Count; i++) //each (Match match in matches)
{
Match match = matches[i];
Match matchrtf = matchesRtf[i];
thisLink = new LinkLocation(match.Index + 7, // If the [END> is immediately followed by <START] include it
match.Length - (((match.Index + match.Length + 7 <= str.Length) && (str.Substring(match.Index + match.Length, 7) == "<START]")) ? 0 : 7),
match.Value, matchrtf.Index, matchrtf.Length, thisLink);
_LinkLocations.Add(thisLink);
}
}
private LinkLocation FindBetweenLinks()
{
return FindBetweenLinks(SelectionStart);
}
private LinkLocation FindBetweenLinks(int start)
{
DebugPrint("FL----------------Between>");
if (_LinkLocations == null) return null;
foreach (LinkLocation ll in _LinkLocations)
if (ll.Start == start && ll.StartsBetween)
return ll;
return null;
}
private LinkLocation FindLinkLocation()
{
return FindLinkLocation(SelectionStart);
}
private LinkLocation FindLinkLocation(int sel)
{
//DebugPrint("FL----------------Location>");
if (_LinkLocations == null) return null;
foreach (LinkLocation ll in _LinkLocations)
{
// Moving right:
// if less than, allows stopping between two links
if (ll.Start < sel && ll.End > sel)
{
DebugPrint("Greater Than {0} {1} {2}", sel, ll.Start, ll.End);
return ll;
}
// if less than or equal, does not stop between two links
if ((!ll.StartsBetween) && ll.Start <= sel && ll.End > sel)
{
DebugPrint("Greater Than or Equal {0} {1} {2}", sel, ll.Start, ll.End);
return ll;
}
}
return null;
}
public DialogResult ReplaceText(string rpltxt, string fndstr, bool caseSensitive, bool matchWholeWord, bool reverse, bool prompt, IWin32Window fndrpldlg)
{
DialogResult dlgrslt = DialogResult.Yes;
if (SelectionLength > 0)
{
if (IsSelectionLinked(SelectionStart, SelectionLength))
{
MessageBox.Show(fndrpldlg,"Cannot replace linked text!", "Find/Replace");
dlgrslt = DialogResult.No;
}
else
{
if (prompt)
dlgrslt = MessageBox.Show(fndrpldlg,"Replace This Occurence?", "Replace Text", MessageBoxButtons.YesNoCancel);
if (dlgrslt == DialogResult.Yes)
SelectedText = rpltxt;
}
}
return dlgrslt;
}
private RichTextBoxFinds _FindOptions = RichTextBoxFinds.None;
public bool FindText(string str, bool caseSensitive, bool matchWholeWord, bool reverse)
{
using (StepRTB savRTF = new StepRTB())
{
int startpos = SelectionStart + SelectionLength;
savRTF.Text = this.Text;
_FindOptions = RichTextBoxFinds.None;
if (caseSensitive)
_FindOptions |= RichTextBoxFinds.MatchCase;
if (matchWholeWord)
_FindOptions |= RichTextBoxFinds.WholeWord;
if (reverse)
{
_FindOptions |= RichTextBoxFinds.Reverse;
savRTF.Text = this.Text.Substring(0, SelectionStart);
startpos = savRTF.Text.Length;
if (startpos == 0)
return false; // at beginning of rtfbox during a reverse find
}
else
{
if (startpos >= savRTF.Text.Length)
return false; // at end of rtfbox during a forward find
}
// look for the find string in the temporary rtfbox
// then set the cursor selection in the real rtfbox
bool keepgoing = true;
while (keepgoing)
{
int pos = savRTF.Find(str, startpos, _FindOptions);
keepgoing = false;
if (pos >= 0)
{
if (this.SkipLinkInfo(pos, str.Length))
{
if (reverse)
{
startpos--;
savRTF.Text = savRTF.Text.Substring(0, startpos);
}
else
startpos++;
if (startpos > 0 && startpos < savRTF.Text.Length)
keepgoing = true;
}
else
{
SelectionStart = pos;
SelectionLength = str.Length;
}
}
else
return false;
}
return true;
}
}
private int FindStart()
{
foreach (LinkLocation ll in _LinkLocations)
{
if (SelectionStart == ll.End) return ll.Start;
if (SelectionStart == ll.Start)
{
if (ll.Start == 7) return 7;
return ll.Start - 8;
}
}
if (SelectionStart > 0) return SelectionStart - 1;
return 0;
}
private int FindEnd()
{
foreach (LinkLocation ll in _LinkLocations)
{
if (SelectionStart + SelectionLength + 7 == ll.Start) return ll.Length + 7;
// this is for in-between links
if (SelectionStart + SelectionLength == ll.Start) return ll.Length;
}
if (SelectionStart + SelectionLength < TextLength) return 1;
return 0;
}
private int FindEndDown()
{
foreach (LinkLocation ll in _LinkLocations)
{
if (SelectionStart + SelectionLength >= ll.Start && SelectionStart + SelectionLength <= ll.End) return ll.End;
}
return 0;
}
private int FindStartUp()
{
foreach (LinkLocation ll in _LinkLocations)
{
if ((SelectionStart >= ll.Start) && (SelectionStart <= ll.End)) return ll.Start;
}
return -1;
}
public void SetSelection(LinkLocation ll)
{
SetSelection(ll.Start, ll.Length);
}
public void SetSelection(int locStart, int locLength)
{
//Application.DoEvents(); // Not needed since SendKeys is always done last.
if (_IdentifyingLinks)
DebugPrint("SS------------------------> {0} {1}", locStart, locLength);
else
DebugPrint("SS========================> {0} {1}", locStart, locLength);
Select(locStart, locLength);
}
#endregion
//#region FontAndStylesSupport
//private void ToggleFontStyle(FontStyle style, bool att_on)
//{
// int start = SelectionStart;
// int len = SelectionLength;
// System.Drawing.Font currentFont;
// FontStyle fs;
// for (int i = 0; i < len; ++i)
// {
// Select(start + i, 1);
// currentFont = SelectionFont;
// fs = currentFont.Style;
// //add or remove style
// if (!att_on)fs = fs | style;
// else fs = fs & ~style;
// SelectionFont = new Font(
// currentFont.FontFamily,
// currentFont.Size,
// fs
// );
// }
//}
/// <summary>
/// Returns a Font with:
/// 1) The font applying to the entire selection, if none is the default font.
/// 2) The font size applying to the entire selection, if none is the size of the default font.
/// 3) A style containing the attributes that are common to the entire selection, default regular.
/// </summary>
///
//public Font GetFontDetails()
//{
// //This method should handle cases that occur when multiple fonts/styles are selected
// int start = SelectionStart;
// int len = SelectionLength;
// int TempStart = 0;
// if (len <= 1)
// {
// // Return the selection or default font
// if (SelectionFont != null)
// return SelectionFont;
// else
// return Font; // should be default from format.
// }
// // Step through the selected text one char at a time
// // after setting defaults from first char
// _rtbTemp.Rtf = SelectedRtf;
// //Turn everything on so we can turn it off one by one
// FontStyle replystyle =
// FontStyle.Bold | FontStyle.Italic | FontStyle.Underline;
// // Set reply font, size and style to that of first char in selection.
// _rtbTemp.Select(TempStart, 1);
// string replyfont = _rtbTemp.SelectionFont.Name;
// float replyfontsize = _rtbTemp.SelectionFont.Size;
// replystyle = replystyle & _rtbTemp.SelectionFont.Style;
// // Search the rest of the selection
// for (int i = 1; i < len; ++i)
// {
// _rtbTemp.Select(TempStart + i, 1);
// // Check reply for different style
// replystyle = replystyle & _rtbTemp.SelectionFont.Style;
// // Check font
// if (replyfont != _rtbTemp.SelectionFont.FontFamily.Name)
// replyfont = "";
// // Check font size
// if (replyfontsize != _rtbTemp.SelectionFont.Size)
// replyfontsize = (float)0.0;
// }
// // Now set font and size if more than one font or font size was selected
// if (replyfont == "")
// replyfont = _rtbTemp.Font.FontFamily.Name;
// if (replyfontsize == 0.0)
// replyfontsize = _rtbTemp.Font.Size;
// // generate reply font
// Font reply
// = new Font(replyfont, replyfontsize, replystyle);
// return reply;
//}
//#endregion
#region EnumsSelectionRange
private enum StartStatus : int
{
Before = 100,
Between = 200,
StartLink = 300,
StartBox = 400
};
private enum EndStatus : int
{
After = 1,
Between = 2,
EndLink = 3,
EndBox = 4,
StartLink = 5
};
public enum RangeStatus : int
{
NoContainedLinks = 0,
Before_After = StartStatus.Before + EndStatus.After,
Before_Between = StartStatus.Before + EndStatus.Between,
Before_EndLink = StartStatus.Before + EndStatus.EndLink,
Before_EndBox = StartStatus.Before + EndStatus.EndBox,
Before_StartLink = StartStatus.Before + EndStatus.StartLink,
Between_After = StartStatus.Between + EndStatus.After,
Between_Between = StartStatus.Between + EndStatus.Between,
Between_EndLink = StartStatus.Between + EndStatus.EndLink,
Between_EndBox = StartStatus.Between + EndStatus.EndBox,
Between_StartLink = StartStatus.Between + EndStatus.StartLink,
StartLink_After = StartStatus.StartLink + EndStatus.After,
StartLink_Between = StartStatus.StartLink + EndStatus.Between,
StartLink_EndLink = StartStatus.StartLink + EndStatus.EndLink,
StartLink_EndBox = StartStatus.StartLink + EndStatus.EndBox,
StartLink_StartLink = StartStatus.StartLink + EndStatus.StartLink,
StartBox_After = StartStatus.StartBox + EndStatus.After,
StartBox_Between = StartStatus.StartBox + EndStatus.Between,
StartBox_EndLink = StartStatus.StartBox + EndStatus.EndLink,
StartBox_EndBox = StartStatus.StartBox + EndStatus.EndBox,
StartBox_StartLink = StartStatus.StartBox + EndStatus.StartLink
};
private RangeStatus _RTBRangeStatus;
public RangeStatus RTBRangeStatus
{
get { return _RTBRangeStatus; }
set
{
_RTBRangeStatus = value;
if (!_ProcessingDelete) OnRTBRangeStatusChanged(this, new EventArgs());
}
}
private LinkLocation _RangeStartLink = null;
private LinkLocation _RangeEndLink = null;
public RangeStatus FindRangeStatus()
{
_RangeStartLink = null;
_RangeEndLink = null;
if (_LinkLocations == null || _LinkLocations.Count == 0)
{
return RTBRangeStatus = RangeStatus.NoContainedLinks;
}
LinkLocation foundLink = null;
int start = SelectionStart;
int end = start + SelectionLength;
foreach (LinkLocation ll in _LinkLocations)
{
if (foundLink == null && ((ll.Start >= start && ll.Start < end) || (ll.End >= start && ll.End < end)))
foundLink = ll;
if (_RangeStartLink == null && start >= ll.Start - 7 && start < ll.End)
_RangeStartLink = ll;
if (_RangeEndLink == null && end >= ll.Start && end <= ll.End)
_RangeEndLink = ll;
}
DebugPrint("SelectionStart {0}, SelectionEnd {1}, TextLength {2}",
SelectionStart, SelectionStart + SelectionLength,
TextLength);
//if (_RangeStartLink != null)
// _RangeStartLink.Show("startLink");
//if (_RangeEndLink != null)
// _RangeEndLink.Show("endLink");
//if (foundLink != null)
// foundLink.Show("foundLink");
if (foundLink == null)
return RTBRangeStatus = RangeStatus.NoContainedLinks;
StartStatus myStartStatus = StartStatus.Before;
EndStatus myEndStatus = EndStatus.After;
if (_RangeStartLink != null)
{
if (_RangeStartLink.Start == 7)
myStartStatus = StartStatus.StartBox;
else if (_RangeStartLink.StartsBetween)
myStartStatus = StartStatus.Between;
else
myStartStatus = StartStatus.StartLink;
}
if (_RangeEndLink != null)
{
if (_RangeEndLink.End == TextLength)
myEndStatus = EndStatus.EndBox;
else if (_RangeEndLink.NextStart == _RangeEndLink.End)
myEndStatus = EndStatus.Between;
else if (end == _RangeEndLink.Start)
myEndStatus = EndStatus.StartLink; // Should not happen because of code in HandleSelectionChange
else //if (end == endLink.End)
myEndStatus = EndStatus.EndLink;
}
return RTBRangeStatus = (RangeStatus)((int)myStartStatus + (int)myEndStatus);
}
#endregion
#region OutlineTable
private string _CheckRight = "-\u2500\u2011";
public string CheckRight
{
get { return _CheckRight; }
set { _CheckRight = value; }
}
private string _CheckAbove = "|\u2502\u2514\u252c\u253c\u251c\u250c\u2534\u2510\u2524";
public string CheckAbove
{
get { return _CheckAbove; }
set { _CheckAbove = value; }
}
private string _CheckLeft = "-\u2500\u2524\u252c\u251c\u253c\u250c\u2510\u2514\u2011";
public string CheckLeft
{
get { return _CheckLeft; }
set { _CheckLeft = value; }
}
private string _CheckBelow = "|\u2502";
public string CheckBelow
{
get { return _CheckBelow; }
set { _CheckBelow = value; }
}
// This is a table of graphics characters
// The index into this table (0-15) is a bitmask with each bit representing
// a different direction from the current character.
// Right is Bit 0 (0 or 1)
// Above is Bit 1 (0 or 2)
// Left is Bit 2 (0 or 4)
// Below is Bit 3 (0 or 8)
// The index is contolled in the following way:
// If there is a graphics character to the right, then you add 1
// If there is a graphics character above, then you add 2
// If there is a graphics character left, then you add 4
// If there is a graphics character below, then you add 8
// The total results in an index into this array and gives the appropriate character
// combining horizontal and vertical lines.
static private string [] TableCharsU = {
"\x0", // HEX"\x0", // No character
@"\u9472", // HEX@"\u2500",// - Horizontal line - 16-bit char: '\xC4'
@"\u9474", // HEX@"\u2502",// | Vertical line - 16-bit char: '\xB3'
@"\u9492", // HEX@"\u2514",// L Bottom Left corner - 16-bit char: '\xC0'
@"\u9472", // HEX@"\u2500",// - Horizontal line - 16-bit char: '\xC4'
@"\u9472", // HEX@"\u2500",// - Horizontal line - 16-bit char: '\xC4'
@"\u9496", // HEX@"\u2518",// Bottom Right Corner - 16-bit char: '\xD9'
@"\u9524", // HEX@"\u2534",// Bottom Tee - 16-bit char: '\xC1'
@"\u9474", // HEX@"\u2502",// | Vertical Bar - 16-bit char: '\xB3'
@"\u9484", // HEX@"\u250c",// Upper Left corner - 16-bit char: '\xDA'
@"\u9474", // HEX@"\u2502",// | Vertical Bar - 16-bit char: '\xB3'
@"\u9500", // HEX@"\u251c",// Left Tee - 16-bit char: '\xC3'
@"\u9488", // HEX@"\u2510",// Upper Right corner - 16-bit char: '\xBF'
@"\u9516", // HEX@"\u252c",// T Top Tee - 16-bit char: '\xC2'
@"\u9508", // HEX@"\u2524",// Right Tee - 16-bit char: '\xB4'
@"\u9532", // HEX@"\u253c" // + Plus - 16-bit char: '\xC5'
};
private int MaxCharacterWidth()
{
// loop through lines and get the width in characters
int w = 0;
foreach (string line in Lines)
{
string cleanLine = RemoveLinkComments(line);
if (w < cleanLine.Length)
w = cleanLine.Length;
}
return w;
}
internal static string RemoveLinkComments(string line)
{
StringBuilder sb = new StringBuilder();
int lastIndex = 0;
MatchCollection mc = Regex.Matches(line, @"<START\](.*?)#Link.*?\[END>");
foreach (Match m in mc)
{
sb.Append(line.Substring(lastIndex, m.Index - lastIndex)); // Append text before the link
sb.Append(m.Groups[1].Value); // Append the text portion of the link
lastIndex = m.Index + m.Length; // Calculate the beginning of the remaining text
}
sb.Append(line.Substring(lastIndex)); // Append the text following the last link
string result = sb.ToString();
result = result.Replace(@"<START]", "");
MatchCollection mcEnd = Regex.Matches(result, @"#Link.*?\[END>");
if (mcEnd.Count > 0)
{
result = result.Substring(0, mcEnd[0].Index) + result.Substring(mcEnd[0].Index + mcEnd[0].Length);
}
return result;
}
private void ReplaceLinesInTable(bool withBorder)
{
int rowWidth = Lines[0].Length;
for (int row=1;row<Lines.Length-1;row++)
{
string line = Lines[row];
string lineAbove = RemoveLinkComments(Lines[row-1]);
string lineBelow = RemoveLinkComments(Lines[row+1]);
int rowOffset = GetFirstCharIndexFromLine(row);
MatchCollection matchCollection = Regex.Matches(line, @"<START\](.*?)#Link.*?\[END>"); //, RegexOptions.Singleline);
if (matchCollection.Count == 0) matchCollection = Regex.Matches(line, @"<START\]");
if (matchCollection.Count == 0) matchCollection = Regex.Matches(line, @"#Link.*?\[END>");
Match match = matchCollection.Count > 0 ? matchCollection[0] : null;
int matchOffset = 0;
for (int col = 1; col < rowWidth - 1; col++)
{
if (match != null && match.Index == matchOffset + col)
{
matchOffset += match.Length - match.Groups[1].Length; // Increment the offset by the link comment length
col += match.Groups[1].Length; // increment the column by the link value length
if (col >= rowWidth - 1) break;// Don't continue if beyond the contents
match = match.NextMatch(); // Watch for the next match
}
int coll = matchOffset + col;
char chr = line[coll];
char chrLast = line[coll - 1];
char chrNext = line[coll + 1];
char chrAbove = lineAbove[col];
char chrBelow = lineBelow[col];
// The following is all using symbol font (either unicode for proportional or
// VeSymbFix for fixed font):
// if this character is a table line draw character, i.e. a dash or vertical bar, or
// graphics characters for those, look around it to see what table character it is
// replaced with
// Look for -||-- (last three are graphics chars or unicode dash)
if ("-|\u2500\u2502\u2011".IndexOf(chr) > -1)
{
bool horizontalCharacter = "-\u2500\u2011".IndexOf(chr) > -1;
int lineDrawRight = (CheckRight.IndexOf(chrNext) > -1 || (horizontalCharacter && "\u2502".IndexOf(chrNext) > -1)) ? 1 : 0;
int lineDrawAbove = (CheckAbove.IndexOf(chrAbove) > -1 || (!horizontalCharacter && "\u2500\u2011".IndexOf(chrAbove) > -1)) ? 2 : 0;
int lineDrawLeft = (CheckLeft.IndexOf(chrLast) > -1 || (horizontalCharacter && "\u2502".IndexOf(chrLast) > -1)) ? 4 : 0;
int lineDrawBelow = (CheckBelow.IndexOf(chrBelow) > -1 || (!horizontalCharacter && "-\u2500\u2011".IndexOf(chrBelow) > -1)) ? 8 : 0;
int tableCharIndx = lineDrawRight + lineDrawAbove + lineDrawLeft + lineDrawBelow;
if (tableCharIndx > 0)
{
SetTableChar(row, coll, tableCharIndx);
if (withBorder) // Adjust the border as it intersects with lines within the box
{
if (row == 1 && !horizontalCharacter ) SetTableChar(row - 1, col, 13); // Top Row
if (row == Lines.Length - 2 && !horizontalCharacter) SetTableChar(row + 1, col, 7); // Bottom Row
if (col == 1 && horizontalCharacter && ((tableCharIndx & 4)==4)) SetTableChar(row, col - 1, 11); // First Column
if (col == rowWidth - 2 && horizontalCharacter && ((tableCharIndx & 1) == 1)) SetTableChar(row, coll + 1, 14); // Last Column
}
}
}
}
}
}
private void SetTableChar(int row, int col, int tableCharIndx)
{
int rowOffset = GetFirstCharIndexFromLine(row);
Select(rowOffset + col, 1);
string charToBeReplaced = SelectedText;
if (Text.Length > (rowOffset + col + 7) && Text.Substring(rowOffset + col + 1, 6) != "#Link:")
SelectedRtf = RtfPrefixForSymbols + TableCharsU[tableCharIndx] + "?}";
else
{
SelectionStart++;
int lenComment = 1 + SelectionStart - (rowOffset + col);
//Console.WriteLine("{0},{1},{2}", rowOffset + col, SelectionStart, SelectionLength);
Select(rowOffset + col, 0);
SelectedRtf = RtfPrefixForSymbols + TableCharsU[tableCharIndx] + "?}";
Select(rowOffset + col, lenComment);
//Console.WriteLine("'{0}',{1},{2},{3}", SelectedText, lenComment, SelectionLength, SelectionStart);
//Console.WriteLine("'{0}'", SelectedRtf);
SelectedRtf = SelectedRtf.Replace(" " + charToBeReplaced, "");
}
}
#endregion
#region SpellChecker
private static bool _DoSpellCheck = true;
public static bool DoSpellCheck
{
get { return StepRTB._DoSpellCheck; }
set { StepRTB._DoSpellCheck = value; }
}
// We made the Spell Checker method a static so that all of the StepRTB boxes will bare the same instance of the dictionary.
// This allow all the StepRTB's to automatically update when a new word is added.
private static C1.Win.C1SpellChecker.C1SpellChecker _C1SpellChecker2;
private static C1.Win.C1SpellChecker.C1SpellChecker C1SpellChecker2
{
get
{
if (_C1SpellChecker2 == null)
{
_C1SpellChecker2 = new C1.Win.C1SpellChecker.C1SpellChecker();
_C1SpellChecker2.ContextMenuCreated += new C1.Win.C1SpellChecker.ContextMenuEventHandler(_C1SpellChecker2_ContextMenuCreated);
// The veproms.dct file is the main spell checker dictionary.
// We edited the C1 dictionary (C:\Program Files\ComponentOne\Dictionaries\C1Spell_en-US.dct) using ComponentOne's
// dictionary editor (C:\Program Files\ComponentOne\Studio for WinForms\C1SpellChecker\C1DictionaryEditor.exe)
// and added the veproms.words list as another word list in the dictionary. We saved the resulting file as veproms.dct.
string dictpath = string.Format(@"{0}\veproms.dct", Application.StartupPath);
// Only use the veproms.dct if it is found in the BIN folder. Otherwise, let it default to use the standard dictionary.
if (File.Exists(dictpath))
_C1SpellChecker2.MainDictionary.FileName = dictpath; // looks in the bin folder by default
// NOTE: By default, a "Custom.dct" file (UserDictionary) will be created in the BIN folder when a user adds words to the
// spell checker dictionary. The words that the user adds are not placed in the Volian.dct file.
//_C1SpellChecker2.UserDictionary.FileName = @"C:\Development\proms\VEPROMS User Interface\bin\Debug\MYDictionary.dct";
}
return StepRTB._C1SpellChecker2;
}
}
// the grid uses this to reference the same instance of the spell checker
public C1.Win.C1SpellChecker.C1SpellChecker SpellCheckerInstance
{
get { return C1SpellChecker2; }
}
// Get or Save our context menu
// This is added to the the spell checker's context menu for a mis-spelled word
private static ContextMenuStrip _ThisContextMenuStrip;
public ContextMenuStrip ThisContextMenuStrip
{
get { return _ThisContextMenuStrip; }
set { _ThisContextMenuStrip = value; }
}
private static StepRTB _ContextMenuStepRTB;
private static object _ContextMenuStrip;
static void _C1SpellChecker2_ContextMenuCreated(object sender, C1.Win.C1SpellChecker.ContextMenuEventArgs e)
{
// Adjust their bad word context menu
//Console.WriteLine("==========> spell check context menu {0}",e.Menu.Items[0].Text);
if (e.Menu.Equals(_ContextMenuStrip))
{
// Add an item for our "Edit Menu" context menu on their spell check context menu
// This gives the user access to our regular context menu when on a mis-spelled word
ToolStripItem tsi = e.Menu.Items.Add("Edit Menu");
tsi.Click += new EventHandler(tsi_Click);
//Now replace their "Spell" item with ours, so that we can display our custom spell check dialog
for (int i = 0; i < e.Menu.Items.Count; i++)
{
ToolStripItem tsi1 = e.Menu.Items[i];
if (tsi1 is ToolStripMenuItem && tsi1.Text == "Spell")
{
e.Menu.Items.RemoveAt(i); // remove their spell check dialog item
ToolStripMenuItem tsi2 = new ToolStripMenuItem("Spell");
tsi2.Click += new EventHandler(tsi2_Click);
e.Menu.Items.Insert(i, tsi2); // add our spell check dialog item
}
}
}
}
static void tsi2_Click(object sender, EventArgs e)
{
C1SpellChecker2.CheckControl(_ContextMenuStepRTB, true, MySpellCheckDlg);
}
// Click event to display our "Edit Menu" (StepRTB context menu)
static void tsi_Click(object sender, EventArgs e)
{
ToolStripMenuItem tsmi = sender as ToolStripMenuItem;
//_ContextMenuStepRTB.MyRTBItem.MyStepPanel.MyStepTabPanel.MyStepTabRibbon.OpenContextMenu(tsmi.Owner.Location);
_ContextMenuStepRTB.OnOpenContextMenu(sender, new StepRTBLocationEventArgs(tsmi.Owner.Location));
}
// This is our customized Spell Check dialog
// This is display when the use clicks the Spell button from the Ribbon
// or when the "Spell" item is selected from the context menu when on a mis-spelled word
static VlnSpellCheckDlg _MySpellCheckDlg;
public static VlnSpellCheckDlg MySpellCheckDlg
{
get
{
if (_MySpellCheckDlg == null)
_MySpellCheckDlg = new VlnSpellCheckDlg();
return _MySpellCheckDlg;
}
}
// This is used when walking through the section doing a spell check
// (from the Spell button on the ribbon)
public bool SpellCheckNext()
{
int nBad = C1SpellChecker2.CheckControl(this, false, MySpellCheckDlg);
return (nBad >= 0); // nBad = -1 means user pressed Cancel button
}
// This allows us to turn off/on the specll check context menu when we toggle in and out of View Mode.
// see btnToggleEditView_Click() in StepTabRibbon.cs
public void SpellCheckContextMenuOn(bool turnOnMenu)
{
C1SpellChecker2.Options.ShowSuggestionsInContextMenu = turnOnMenu;
}
#endregion
#region
public string DoNewLinkInGridCell()
{
// first find the new link and determine whether it's RO or transition.
int indx = Rtf.IndexOf(@"#Link:ReferencedObject:<NewID>");
if (indx > 0)
{
Match mro = Regex.Match(Rtf.Substring(indx, Rtf.Length - indx), @"([A-Za-z]*):(.*)\[END>");
string linkstr = mro.Groups[2].Value;
string[] roparts = linkstr.Split(" ".ToCharArray());
ContentRoUsage rousg = null;
int oldid = -1;
using (Item itm = MyItemInfo.Get())
{
using (RODb rodb = RODb.GetJustRoDb(Convert.ToInt32(roparts[2])))
{
rousg = itm.MyContent.ContentRoUsages.Add(roparts[1], rodb);
}
//get temporary rousageid
oldid = rousg.ROUsageID;
Rtf = Rtf.Replace("<NewID>", string.Format("<CROUSGID={0}>", rousg.ROUsageID));
//save temporary rousageid to get real rousageid
itm.Save();
//replace temprorary rousageid with real rousageid
Rtf = Rtf.Replace(string.Format("<CROUSGID={0}>", oldid), rousg.ROUsageID.ToString());
//save real rousageid
itm.Save();
MyItemInfo.MyContent.RefreshContentRoUsages();
}
}
// Need to look for any 'New' transitions, don't include existing ones.
Match mt = Regex.Match(Rtf, @"#Link:Transition:([0-9]+) <NewID> ");
if (mt.Length <= 0) mt = Regex.Match(Rtf, @"#Link:TransitionRange:([0-9]+) <NewID> ");
if (mt.Length > 0)
{
indx = mt.Index+6; // get past '#Link:"
Match m = Regex.Match(Rtf.Substring(indx, Rtf.Length - indx), @"([A-Za-z]*):(.*)\[END>");
bool isSingleTran = true;
if (Rtf.Substring(indx, 16).IndexOf("TransitionRange") >= 0) isSingleTran = false;
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;
using (Item itm = MyItemInfo.Get())
{
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 (isSingleTran)
ct.IsRange = 0;
else if (tr1 != tr2)
ct.IsRange = 1;
else
ct.IsRange = 2;
int oldidt = ct.TransitionID;
Rtf = Rtf.Replace("<NewID>", string.Format("<CTID={0}>", ct.TransitionID));
itm.Save();
Rtf = Rtf.Replace(string.Format("<CTID={0}>", oldidt), ct.TransitionID.ToString());
itm.Save();
MyItemInfo.MyContent.RefreshContentTransitions();
}
if (dispose2) itm2.Dispose();
if (dispose1) itm1.Dispose();
}
return Rtf;
}
#endregion
#region RoInsertInterface
public void UpdateStepRtb(string linktxt, string valtxt)
{
int ss = SelectionStart; // Remember where the link is being added
int sl = SelectionLength;
OnReturnToEditor(this, new EventArgs());
Select(ss, sl);
InsertRO(valtxt, linktxt); // Insert the LINK
OnDoSaveContents(this, new EventArgs()); // .SaveText(); // Save the text with the LINK - This also moves the cursor to the end of the text
// By selecting a starting position within a link, StepRTB (HandleSelectionChange) will select the link
Select(ss + 7 + valtxt.Length, 0);// Select the link, Try 7 for "<Start]" plus the length of the value
//Console.WriteLine("'{0}'",MyRTB.Text.Substring(MyRTB.SelectionStart,MyRTB.SelectionLength));
string linkText = Text.Substring(SelectionStart, SelectionLength);
if (_MyLog.IsInfoEnabled && (linkText.Contains("NewID") || linkText.Contains("CROUSGID")))
_MyLog.InfoFormat("ItemID {0}, LinkText '{1}'", MyItemInfo.ItemID, linkText);
int sel = SelectionStart + SelectionLength;
Select(sel, 0);// Move cursor to end of LINK
Focus();
}
#endregion
#region Debug
private bool _ShowDebug = false;
public bool ShowDebug
{
get { return _ShowDebug; }
set { _ShowDebug = value; }
}
private void DebugPrint(string where, string format, params object[] myParams)
{
DebugPrint(where + string.Format(format, myParams));
}
private void DebugPrint(string format, params object[] myParams)
{
if (_ShowDebug)
Console.WriteLine(format, myParams);
}
private void DebugSelection(string where)
{
DebugPrint(where, ": {0} {1} '{2}'", SelectionStart, SelectionLength, SelectedText);
}
#endregion
private bool _LastWasLeftArrow = false;
private void StepRTB_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
if ((e.KeyCode == Keys.Tab) && (!e.Alt && !e.Control))
e.IsInputKey = true;
// Remember if the last key pressed was a left arrow. This is used in HandleSelectionChanged
// When a Link overlaps the beginning of a line. Normally a left arrow will move the cursor
// back one character, or if a Link is selected, it will move the cursor to the space before
// the link. Since the Link overlaps the line, special consideration must be given to assure
// that the cursor goes to the proper place.
_LastWasLeftArrow = (!e.Shift && !e.Control && !e.Alt && e.KeyCode == Keys.Left);
}
}
public partial class StepRTBModeChangeEventArgs : EventArgs
{
private E_ViewMode _ViewMode;
public E_ViewMode ViewMode
{
get { return _ViewMode; }
set { _ViewMode = value; }
}
public StepRTBModeChangeEventArgs(E_ViewMode vmode)
{
_ViewMode = vmode;
}
}
public partial class StepRTBMenuEventArgs
{
private string _MenuGroup;
public string MenuGroup
{
get { return _MenuGroup; }
set { _MenuGroup = value; }
}
public StepRTBMenuEventArgs(string menuGroup)
{
_MenuGroup = menuGroup;
}
}
public partial class StepRTBTableWidthEventArgs
{
bool _EditMode;
public bool EditMode
{
get { return _EditMode; }
set { _EditMode = value; }
}
public StepRTBTableWidthEventArgs(bool editMode)
{
_EditMode = editMode;
}
}
public class StepRTBCursorMovementEventArgs
{
private Point _CursorLocation;
public Point CursorLocation
{
get { return _CursorLocation; }
set { _CursorLocation = value; }
}
private E_ArrowKeys _Key;
public E_ArrowKeys Key
{
get { return _Key; }
set { _Key = value; }
}
public StepRTBCursorMovementEventArgs(Point pt, E_ArrowKeys key)
{
_CursorLocation = pt;
_Key = key;
}
}
public class StepRTBLocationEventArgs:EventArgs
{
private Point _Location;
public Point Location
{
get { return _Location; }
set { _Location = value; }
}
public StepRTBLocationEventArgs(Point location)
{
_Location = location;
}
}
public partial class StepRTBRoEventArgs : EventArgs
{
private string _ValText;
public string ValText
{
get { return _ValText; }
set { _ValText = value; }
}
private string _RawValText;
public string RawValText
{
get { return _RawValText; }
set { _RawValText = value; }
}
private string _LinkText;
public string LinkText
{
get { return _LinkText; }
set { _LinkText = value; }
}
private string _ROID;
public string ROID
{
get { return _ROID; }
set { _ROID = value; }
}
private int _RODbID;
public int RODbID
{
get { return _RODbID; }
set { _RODbID = value; }
}
public StepRTBRoEventArgs(string valtext, string rawvaltext, string linktext, string roid, int rodbid)
{
_ValText = valtext;
_RawValText = rawvaltext;
_LinkText = linktext;
_ROID = roid;
_RODbID = rodbid;
}
}
#region LinkLocation Class
public class LinkLocation
{
private int _Start;
public int Start
{
get { return _Start; }
set { _Start = value; }
}
private int _Length;
public int Length
{
get { return _Length; }
set { _Length = value; }
}
public int End
{
get { return _Length + _Start; }
}
private int _StartRtf;
public int StartRtf
{
get { return _StartRtf; }
set { _StartRtf = value; }
}
private int _LengthRtf;
public int LengthRtf
{
get { return _LengthRtf; }
set { _LengthRtf = value; }
}
public int EndRtf
{
get { return _LengthRtf + _StartRtf; }
}
private string _Text;
public string Text
{
get { return _Text; }
set { _Text = value; }
}
private LinkLocation _PreviousLink = null;
public LinkLocation PreviousLink
{
get { return _PreviousLink; }
set
{
_PreviousLink = value;
value.NextLink = this;
}
}
private LinkLocation _NextLink = null;
public LinkLocation NextLink
{
get { return _NextLink; }
set { _NextLink = value; }
}
public int PreviousEnd
{
get { return PreviousLink == null ? -1 : PreviousLink.End; }
}
public bool StartsBetween
{
get { return PreviousEnd == Start; }
}
public int NextStart
{
get { return NextLink == null ? -1 : NextLink.Start; }
}
public bool EndsBetween
{
get { return NextStart == End; }
}
public LinkLocation(int start, int length, string text, int startRtf, int lengthRtf, LinkLocation previousLink)
{
_Start = start;
_Length = length;
_Text = text;
_StartRtf = startRtf;
_LengthRtf = lengthRtf;
if (previousLink != null) PreviousLink = previousLink;
}
public override string ToString()
{
return (string.Format("{0}, {1}", Start, End));
}
public void Show(string str)
{
if (PreviousLink != null)
Console.WriteLine("LinkLocation: {0}.PreviousLink {1}", str, PreviousLink);
Console.WriteLine("LinkLocation: {0} {1}", str, this);
if (NextLink != null)
Console.WriteLine("LinkLocation: {0}.NextLink {1}", str, NextLink);
}
// #region ClipboardHandler
// private const int WM_CUT = 0x0300;
// private const int WM_COPY = 0x0301;
// private const int WM_PASTE = 0x0302;
// public delegate void ClipboardEventHandler(object sender, ClipboardEventArgs e);
// [Category("Clipboard")]
// public event ClipboardEventHandler CutText;
// [Category("Clipboard")]
// public event ClipboardEventHandler CopiedText;
// [Category("Clipboard")]
// public event ClipboardEventHandler PastedText;
// protected override void WndProc(ref Message m)
// {
// if (m.Msg == WM_CUT)
// {
// if (CutText != null)
// CutText(this, new ClipboardEventArgs(this.SelectedText));
// }
// else if (m.Msg == WM_COPY)
// {
// if (CopiedText != null)
// CopiedText(this, new ClipboardEventArgs(this.SelectedText));
// }
// else if (m.Msg == WM_PASTE)
// {
// if (PastedText != null)
// PastedText(this, new ClipboardEventArgs(Clipboard.GetText()));
// }
// base.WndProc(ref m);
// }
//}
//public class ClipboardEventArgs : EventArgs
//{
// private string clipboardText;
// public string ClipboardText
// {
// get
// {
// return clipboardText;
// }
// set
// {
// clipboardText = value;
// }
// }
// public ClipboardEventArgs(string clipboardText)
// {
// this.clipboardText = clipboardText;
// }
// #endregion
}
#endregion
}