4194 lines
		
	
	
		
			150 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			4194 lines
		
	
	
		
			150 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;
 | |
| using JR.Utils.GUI.Forms;
 | |
| using System.Linq;
 | |
| 
 | |
| 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 ToggleChangeBar;  // shortcut key <Alt><F2>
 | |
| 		public void OnToggleChangeBar(object sender, EventArgs args)
 | |
| 		{
 | |
| 			if (ToggleChangeBar != null) ToggleChangeBar(sender, args);
 | |
| 		}
 | |
| 		public event StepRTBEvent ToggleContinuousActionSummary; // shortcut key <Shift><F7>
 | |
| 		public void OnToggleContinuousActionSummary(object sender, EventArgs args)
 | |
| 		{
 | |
| 			if (ToggleContinuousActionSummary != null) ToggleContinuousActionSummary(sender, args);
 | |
| 		}
 | |
| 		public event StepRTBEvent TogglePlaceKeeper; // shortcut key <Ctrl><F7>
 | |
| 		public void OnTogglePlaceKeeper(object sender, EventArgs args)
 | |
| 		{
 | |
| 			if (TogglePlaceKeeper != null) TogglePlaceKeeper(sender, args);
 | |
| 		}
 | |
| 		public event StepRTBEvent TogglePlaceKeeperContAct; // shortcut key <Shift><Ctrl><F7>
 | |
| 		public void OnTogglePlaceKeeperContAct(object sender, EventArgs args)
 | |
| 		{
 | |
| 			if (TogglePlaceKeeperContAct != null) TogglePlaceKeeperContAct(sender, args);
 | |
| 		}
 | |
| 		public event StepRTBEvent ToggleSuperScript; // shortcut key <Ctrl><Shift><=>
 | |
| 		public void OnToggleSuperScript(object sender, EventArgs args)
 | |
| 		{
 | |
| 			if (ToggleSuperScript != null) ToggleSuperScript(sender, args);
 | |
| 		}
 | |
| 		public event StepRTBEvent ToggleSubScript; // shortcut key <Ctrl><=>
 | |
| 		public void OnToggleSubScript(object sender, EventArgs args)
 | |
| 		{
 | |
| 			if (ToggleSubScript != null) ToggleSubScript(sender, args);
 | |
| 		}
 | |
| 		public event StepRTBEvent InsertPgBrk; // short key <Ctrl><Enter>
 | |
| 		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 IsRoFigure
 | |
| 		{
 | |
| 			get { return (MyItemInfo.IsFigure && MyItemInfo.MyContent.MyImage == null); }
 | |
| 		}
 | |
| 		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 DocVersionInfo _MyDVI = null;
 | |
| 
 | |
| 		public DocVersionInfo MyDVI
 | |
| 		{
 | |
| 			get
 | |
| 			{
 | |
| 				ItemInfo procInfo = _MyItemInfo.MyProcedure as ItemInfo;
 | |
| 				if (procInfo == null)
 | |
| 					_MyDVI = null;
 | |
| 				else
 | |
| 					_MyDVI = procInfo.ActiveParent as DocVersionInfo;
 | |
| 				return _MyDVI;
 | |
| 			}
 | |
| 		}
 | |
| 		private static UserInfo _MyUserInfo = null;
 | |
| 
 | |
| 		public static UserInfo MyUserInfo
 | |
| 		{
 | |
| 			get { return _MyUserInfo; }
 | |
| 			set { _MyUserInfo = value; }
 | |
| 		}
 | |
| 		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 = "FreeMono"; // FreeMono is now used for the edit screen only.  VESymbFix and Consolas are used for printing
 | |
|                         else MySymbolFontName = Volian.Base.Library.vlnFont.ProportionalSymbolFont; // C2017-036 get best available proportional font for symbols
 | |
| 					}
 | |
| 				}
 | |
| 				else
 | |
| 				{
 | |
| 					MySymbolFontName = null;
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 		// 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
 | |
| 			{
 | |
| 				//B2020-100 RHM Use SelectionFont rather than the font from the format file.
 | |
| 				//if (_RtfPrefix == null) 
 | |
| 				//{
 | |
| 					StringBuilder selectedRtfSB = new StringBuilder();
 | |
| 				//AddFontTable(selectedRtfSB, FormatFont, FontIsFixed(FormatFont));
 | |
| 				// B2021-100:  if SelectionFont is null, use the FormatFont
 | |
| 				AddFontTable(selectedRtfSB, SelectionFont==null?FormatFont:SelectionFont, 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 bool _IsExperimenting = false;
 | |
| 		public bool IsExperimenting
 | |
| 		{
 | |
| 			get { return _IsExperimenting; }
 | |
| 			set { _IsExperimenting = value; }
 | |
| 		}
 | |
| 		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 && MyItemInfo != null) _MyStyleFont = MyItemInfo.GetItemFont();  // B2017-023 null reference check for empty workdraft set information dialog
 | |
| 				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
 | |
| 					}
 | |
| 				}
 | |
| 				// We found that the characters in the Letter Gothic font do not all use the same spacing.
 | |
| 				// Also, the character spacing is even more different between screen resolutions.
 | |
| 				// But the Letter Gothic font will print just fine.
 | |
| 				// We also found that the Letter Gothic Tall font works just fine on the screen, the only difference
 | |
| 				// is that the characters are a little bit taller.
 | |
| 				// So we decided to use the Letter Gothic Tall font for the screen display any time that Letter Gothic is used.
 | |
| 				if (_FormatFont.Name.ToUpper().Equals("LETTER GOTHIC"))
 | |
| 					_FormatFont = new Font("Letter Gothic Tall", _FormatFont.Size, _FormatFont.Style);
 | |
| 				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);
 | |
| 			}
 | |
| 		}
 | |
| 		private static string FontKey(System.Drawing.Font font)
 | |
| 		{
 | |
| 			return string.Format("{0}_{1}_{2}", font.FontFamily.Name, font.Size, font.Style);
 | |
| 		}
 | |
| 		// RefreshDisplay is used to update the rtb for an entire Item as defined by MyItemInfo.  
 | |
| 		public void RefreshDisplay(bool activeMode)
 | |
| 		{
 | |
| 			if (IsExperimenting) return;
 | |
| 			if (IsDisposed) return;
 | |
| 
 | |
| 			ActiveMode = activeMode;
 | |
| 			OnAdjustTableWidth(this, new StepRTBTableWidthEventArgs(true));
 | |
| 			//Volian.Base.Library.HWndCounter.GetWindowHandlesForCurrentProcess(this.Handle, "RefreshDisplay 2");
 | |
| 			_InitializingRTB = true;
 | |
| 			DisplayText vlntxt = new DisplayText(MyItemInfo, E_EditPrintMode.Edit, VwMode, !ActiveMode, FieldToEdit, true,null, null,false);
 | |
| 			//Volian.Base.Library.HWndCounter.GetWindowHandlesForCurrentProcess(this.Handle, "RefreshDisplay 3");
 | |
| 			//if (_origDisplayText != null && vlntxt.StartText == _origDisplayText.StartText)
 | |
| 			//{
 | |
| 			//  ReadOnly = !(EpMode == E_EditPrintMode.Edit && VwMode == E_ViewMode.Edit);
 | |
| 			//  if (!ReadOnly && !edit) ReadOnly = true;
 | |
| 			//  return;
 | |
| 			//}
 | |
| 			OrigDisplayText = vlntxt;
 | |
| 			//Volian.Base.Library.HWndCounter.GetWindowHandlesForCurrentProcess(this.Handle, "RefreshDisplay 4");
 | |
| 
 | |
| 			// 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
 | |
| 			//Volian.Base.Library.HWndCounter.GetWindowHandlesForCurrentProcess(this.Handle, "1");
 | |
| 			if (FieldToEdit == E_FieldToEdit.StepText)
 | |
| 			{
 | |
| 				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);
 | |
| 					if (MyItemInfo.IsStep)
 | |
| 					{
 | |
| 						if (MyFontFamily == null)
 | |
| 						{
 | |
| 							//Volian.Base.Library.HWndCounter.GetWindowHandlesForCurrentProcess(this.Handle, "Before WindowsFont1");
 | |
| 							System.Drawing.Font fnt =  MyItemInfo.FormatStepData.Font.WindowsFont;
 | |
| 							//Volian.Base.Library.HWndCounter.GetWindowHandlesForCurrentProcess(this.Handle, "After WindowsFont1a");
 | |
| 							Application.DoEvents();
 | |
| 							if (FontKey(Font) != FontKey(fnt))
 | |
| 								Font = fnt;
 | |
| 							//Volian.Base.Library.HWndCounter.GetWindowHandlesForCurrentProcess(this.Handle, "After WindowsFont1b");
 | |
| 						}
 | |
| 						else
 | |
| 							Font = VE_Font.GetWinSysFont(MyFontFamily, MyItemInfo.FormatStepData.Font.WindowsFont.Size, MyItemInfo.FormatStepData.Font.WindowsFont.Style);
 | |
| 						//Volian.Base.Library.HWndCounter.GetWindowHandlesForCurrentProcess(this.Handle, "RefreshDisplay 4");
 | |
| 					}
 | |
| 					else
 | |
| 					{
 | |
| 						if (MyFontFamily == null)
 | |
| 						{
 | |
| 							//Volian.Base.Library.HWndCounter.GetWindowHandlesForCurrentProcess(this.Handle, "Before WindowsFont2");
 | |
| 							Font = MyItemInfo.ActiveFormat.PlantFormat.FormatData.Font.WindowsFont;
 | |
| 							//Volian.Base.Library.HWndCounter.GetWindowHandlesForCurrentProcess(this.Handle, "After WindowsFont2");
 | |
| 						}
 | |
| 						else
 | |
| 							Font = VE_Font.GetWinSysFont(MyFontFamily, MyItemInfo.ActiveFormat.PlantFormat.FormatData.Font.WindowsFont.Size, MyItemInfo.ActiveFormat.PlantFormat.FormatData.Font.WindowsFont.Style);
 | |
| 						//Volian.Base.Library.HWndCounter.GetWindowHandlesForCurrentProcess(this.Handle, "RefreshDisplay 5");
 | |
| 					}
 | |
| 					LastRtf = Rtf;
 | |
| 				}
 | |
| 			}
 | |
| 			//Volian.Base.Library.HWndCounter.GetWindowHandlesForCurrentProcess(this.Handle, "StepRTB.RefreshDisplay Before SetLineSpacing");
 | |
| 			RTBAPI.SetLineSpacing(this, RTBAPI.ParaSpacing.PFS_EXACT);
 | |
| 			//Volian.Base.Library.HWndCounter.GetWindowHandlesForCurrentProcess(this.Handle, "StepRTB.RefreshDisplay After SetLineSpacing");
 | |
| 			bool readOnlyStep = MyItemInfo == null || MyItemInfo.FormatStepData == null ? false : MyItemInfo.FormatStepData.ReadOnly;
 | |
| 			if (!readOnlyStep)
 | |
| 			{
 | |
| 				StepConfig sc = new StepConfig(MyItemInfo.MyContent.Config);
 | |
| 				if (IsDerived(sc) && !MyItemInfo.EnhAllowMod()) readOnlyStep = true;
 | |
| 			}
 | |
| 			ReadOnly = readOnlyStep || VwMode == E_ViewMode.View || ActiveMode == false;
 | |
| 			//Volian.Base.Library.HWndCounter.GetWindowHandlesForCurrentProcess(this.Handle, "Before AddRTFText");
 | |
| 			AddRtfText(vlntxt.StartText);
 | |
| 			//Volian.Base.Library.HWndCounter.GetWindowHandlesForCurrentProcess(this.Handle, "After AddRTFText");
 | |
| 			//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;
 | |
| 			RightMargin = ActiveMode ? Width : Width > 0 ? Width - 1 : 0; // > 0 ? Width - 1 : 0;
 | |
| 			// figure out if needs outlined, depends on table/figure type
 | |
| 			if (!ActiveMode)
 | |
| 			{
 | |
| 				RemoveEventHandlers();
 | |
| 				OnAdjustTableWidth(this, new StepRTBTableWidthEventArgs(false));// View Mode
 | |
| 				//Volian.Base.Library.HWndCounter.GetWindowHandlesForCurrentProcess(this.Handle, "Before SelectAll");
 | |
| 				SelectAll();
 | |
| 				//Volian.Base.Library.HWndCounter.GetWindowHandlesForCurrentProcess(this.Handle, "After 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();
 | |
| 				//if (MyItemInfo.InList(186722)) Console.WriteLine("here");
 | |
| 				if ((indchar = Find(indentToken, indchar, RichTextBoxFinds.None)) >= 0)
 | |
| 				{
 | |
| 					int nindents = 0;
 | |
| 					while ((indchar = Find(indentToken, indchar, RichTextBoxFinds.None)) >= 0)
 | |
| 					{
 | |
| 						nindents++;
 | |
| 						Point indent = GetPositionFromCharIndex(indchar);
 | |
| 						SelectionHangingIndent = indent.X;
 | |
| 
 | |
| 						// RHM 02/20/2013
 | |
| 						// The following line attempts to remove the indent character for display purposes.
 | |
| 						// However, if the indent is followed immediately by an RO or Transition the
 | |
| 						// RichTextBox will not allow the character to be removed this way and the RichTextBox
 | |
| 						// will beep.  So, to keep from going in an infintie loop, the value of indchar is incremented.
 | |
| 						SelectedRtf = SelectedRtf.Replace(@"\'05", "");
 | |
| 						indchar++;// Don't do the same one twice.
 | |
| 					}
 | |
| 					if (MyItemInfo != null && MyItemInfo.ActiveFormat != null
 | |
| 						&& MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.DontResetIndentOnNewline)
 | |
| 					{
 | |
| 						if (nindents == 1) Rtf = Rtf.Replace("\\par\r\n", @"\line ");
 | |
| 						Rtf = Rtf.Replace(@"\line\pard", @"\line");
 | |
| 					}
 | |
| 				}
 | |
| 				HideSelection = true;		// fix for B2016-093: this is needed so an rtb that is not focused is not highlighted.
 | |
| 			}
 | |
| 			// This is to fix an issue with Hard Spaces.  To Summarize:
 | |
| 			// The Microsoft RichTextBox has a problem with hardspaces, that they don't work between numbers and lettters
 | |
| 			// This is the majority of cases for PROMS including ROs (Sepoint Number and Units) and transtions (Step ###)
 | |
| 			// As I investigated this further I found that if you pass a rtf unicode value for a hard space (\u160?) to 
 | |
| 			// the RichTextBox, the RichTextBox will return an ASCII representation (\'A0).  If you pass an ASCII representation
 | |
| 			// the RichTextBox will return a space.
 | |
| 			// Alternatively, If you pass a unicode representation of zero (\u0?) it acts like a hard space and returns an ASCII 
 | |
| 			// representation (\'00).  If you pass in the ASCII representation, it truncates the text.
 | |
| 			// The following two lines replace hard spaces (ASCII) with the UNICODE represntation of Zero.
 | |
| 			// Lastly, If you pass a unicode representation of one (\u1?) it acts like a hard space and returns an ASCII 
 | |
| 			// representation (\'01).  If you pass in the ASCII representation, it keeps the ASCII representation.
 | |
| 			// The following two lines replace hard spaces (ASCII) with the UNICODE represntation of Zero.
 | |
| 			// Other characters which behave like hard spaces are 28-31 and 128-159.
 | |
| 			if (!activeMode && Rtf.Contains(@"\'a0"))
 | |
| 			{
 | |
| 				// The following 3 lines were added to fix B2016-069.  The issue was in the RichTextBox for the Arial 
 | |
| 				// (Proportional) font, the hardspace appeared to be 2 spaces (really it was showing the space as the widest 
 | |
| 				// width character).  So instead of a hard space, a single quote "'" was used to designate where the hardspace
 | |
| 				// would be. This is only used for display, printing works.
 | |
| 				//B2019-155 Hard spaces were displace as a square box for non-proportional fonts. 
 | |
| 				//          To fix this, we removed the check for a proportional font and now replace the hard space with a "'" mark for all fonts
 | |
| 					Rtf = Rtf.Replace(@"\'a0", "'");
 | |
| 			}
 | |
| 			OrigRTF = Rtf;
 | |
| 			_InitializingRTB = false;
 | |
| 			
 | |
| 			AdjustSizeForContents(!ActiveMode);
 | |
| 			//Volian.Base.Library.HWndCounter.GetWindowHandlesForCurrentProcess(this.Handle, "After RefreshDisplay");
 | |
| 			Application.DoEvents();
 | |
| 		}
 | |
| 
 | |
| 		private bool IsDerived(StepConfig sc)
 | |
| 		{
 | |
| 			foreach (EnhancedDocument ed in sc.MyEnhancedDocuments)
 | |
| 				if (ed.Type == 0) //New Design
 | |
| 					return true;
 | |
| 			return false;
 | |
| 		}
 | |
| 		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));
 | |
| 				}
 | |
| 				else
 | |
| 				{
 | |
| 					_MyLinkText = value;
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 		#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.  
 | |
| 		public 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.HandleCreated -= new EventHandler(StepRTB_HandleCreated);
 | |
| 			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 = false;
 | |
| 			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.HandleCreated += new EventHandler(StepRTB_HandleCreated);
 | |
| 			this.HandleDestroyed += new EventHandler(StepRTB_HandleDestroyed);
 | |
| 			_EventHandlersForKeyPress = _EventHandlersForKeyPress+1;
 | |
| 		}
 | |
| 		private int _HandleCount = 0;
 | |
| 		void StepRTB_HandleCreated(object sender, EventArgs e)
 | |
| 		{
 | |
| 			_HandleCount++;
 | |
| 		}
 | |
| 		// 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)
 | |
| 		{
 | |
| 			if (_HandleCount == 0)
 | |
| 			{
 | |
| 				Closed = true;
 | |
| 				RemoveEventHandlers();
 | |
| 			}
 | |
| 			_HandleCount--;
 | |
| 		}
 | |
| 		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);
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		// Bug fix  B2017-059, toggle the spellchecking status on only when being used - to control how many window handles are created by the spellchecker
 | |
| 		//          This fixed the issue of the spell checker closing PROMS - Callaway SAMG Background TSG-1, also reproduced on long procedure in calvert EOPs
 | |
| 
 | |
| 		private bool _SpellCheckStatus = false;
 | |
| 
 | |
| 		public bool SpellCheckStatus
 | |
| 		{
 | |
| 			get { return _SpellCheckStatus; }
 | |
| 			set 
 | |
| 			{
 | |
| 				if (_SpellCheckStatus != value)
 | |
| 				{
 | |
| 					_SpellCheckStatus = value;
 | |
| 					if (DoSpellCheck)
 | |
| 						C1SpellChecker2.SetActiveSpellChecking(this, value);
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		private void SetUpStepRTB()
 | |
| 		{
 | |
| 			DetectUrls = false;
 | |
| 			SpellCheckStatus = false;
 | |
| 			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 = false;
 | |
| 		}
 | |
| 		// 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;
 | |
| 		}
 | |
| 		// B2019-161 When tracking timing time this action
 | |
| 		private static VolianTimer _TimeActivity = new VolianTimer("StepRTB CloseWordApp_Tick", 902);
 | |
| 
 | |
| 		void StepRTB_SelectionChanged(object sender, EventArgs e)
 | |
| 		{
 | |
| 			_TimeActivity.Open();
 | |
| 			if (_InitializingRTB || _IsExperimenting || (MyItemInfo!=null && MyItemInfo.IsRtfRaw)) return;
 | |
| 			HandleSelectionChange();
 | |
| 			_TimeActivity.Close();
 | |
| 		}
 | |
| 		private bool _MouseDown = false;
 | |
| 		private bool _ContextMenuStripChanged = false;
 | |
| 		private void StepRTB_MouseDown(object sender, MouseEventArgs e)
 | |
| 		{
 | |
| 			//The following line fixes bugs B2016-121 and B2016-146
 | |
| 			if(!Focused)this.Focus();// If it doesn't have focus, set focus to the selected item
 | |
| 			//Console.WriteLine("vvvvvvvvvv StepRTB Mouse Down id= {0}",MyItemInfo.ItemID);
 | |
| 			bool inPsi = this.Parent.FindForm().Name.Contains("frmPSI") || this.Parent.FindForm().Name.Contains("frmSI");
 | |
| 			if (!_ContextMenuStripChanged)
 | |
| 				OnSetMenu(this, new StepRTBMenuEventArgs(inPsi?"PSI":"OpenContextMenu"));
 | |
| 			_ContextMenuStripChanged = false;
 | |
| 			CorrectSelectionAtEndOfLine();
 | |
| 			// B2017-023 null reference check for empty workdraft set information dialog
 | |
| 			if (e.Button == System.Windows.Forms.MouseButtons.Right && (MyItemInfo == null || MyItemInfo.IsRtfRaw)) OnSetMenu(this, new StepRTBMenuEventArgs((MyItemInfo != null && MyItemInfo.IsRtfRaw)?"OpenRtfRawContextMenu":"PSI"));
 | |
| 			_MouseDown = true;
 | |
| 		}
 | |
| 		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;
 | |
|                 // B2017-231 force the right mouse click to bring up word list if on a mis-spelled word
 | |
| 				if (e.Button == System.Windows.Forms.MouseButtons.Right && Parent is RTBItem) // right mouse click and we are not on a table cell
 | |
| 				{
 | |
| 					if (ThisContextMenuStrip != null)
 | |
| 					{
 | |
| 						(Parent as RTBItem).MyStepPanel.MyStepTabPanel.MyStepTabRibbon.ClearContextMenu();
 | |
| 						this.ContextMenuStrip.Show(this, e.X, e.Y);
 | |
| 					}
 | |
| 					else
 | |
| 					{
 | |
| 						(Parent as RTBItem).MyStepPanel.MyStepTabPanel.MyStepTabRibbon.OpenContextMenu(this.PointToScreen(e.Location), this);
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 		#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 string InsertSymbolInRO(string val)
 | |
| 		//{
 | |
| 		//	string retval = val;
 | |
| 			// C2019-043 convert a "->" to the Right Arrow symbol and a "<-" to the Left Arrow Symbol
 | |
| 			//           note that at the dash character gets convert to a non-breaking hyphen "\u8209?"
 | |
| 			//if (MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.UseDashGreaterLessThenForArrowsInROValue) 
 | |
| 			//{
 | |
| 			//	retval = retval.Replace("\\u8209?>", GetAddSymbolTextForROs(@"\u8594?")); // Right Arrow
 | |
| 			//	retval = retval.Replace("<\\u8209?", GetAddSymbolTextForROs(@"\u8592?")); // Left Arrow
 | |
| 			//}
 | |
| 			//// C2022-021 convert a "<=" to a less than or equal symbol, a ">=" to a greather than or equal symbol and +- to a 
 | |
| 			////	plus/minus symbol in ROs
 | |
| 			//if (MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.ConvertGTELTEPMinROValue)
 | |
| 			//{
 | |
| 			//	retval = retval.Replace("<=", GetAddSymbolTextForROs(@"\u8804?")); // Less than or Equal
 | |
| 			//	retval = retval.Replace(">=", GetAddSymbolTextForROs(@"\u8805?")); // Greater than or Equal
 | |
| 			//	retval = retval.Replace("+\\u8209?", @"\'b1");   // plus/minus - note - is stored as \u8209 and plus/minus is < 256, i.e. handled differently
 | |
| 			//}
 | |
| 		//	return retval;
 | |
| 		//}
 | |
| 		public void InsertRO(string value, string link)
 | |
| 		{
 | |
| 			// B2023-037:  Remove code that saves the unicode characters for <=, >=, +-, <- and -> into the link text.  The characters
 | |
| 			//  now get resolved when used.  InsertSymbolInRo was commented out also
 | |
| 			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;
 | |
| 		public override string ToString()
 | |
| 		{
 | |
| 			return string.Format("[StepRTB {0},{1},{2}]", MyItemInfo.ItemID, MyItemInfo.DisplayNumber, MyItemInfo.DisplayText);
 | |
| 		}
 | |
| 		public void AddRtfText(string txt)
 | |
| 		{
 | |
| 			if (MyItemInfo != null && MyItemInfo.IsRtfRaw)
 | |
| 			{
 | |
| 				if (txt != null && txt != "") SelectedRtf = _LastRtf = txt;
 | |
| 				_lastReadOnly = ReadOnly;
 | |
| 				OrigRTF = txt;
 | |
| 				return;
 | |
| 			}
 | |
| 			//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);
 | |
| 				// indents went from being handled by code support of an indent character (usually \05) to 
 | |
| 				// using rtf commands to fix various indent bugs including B2015-103).  The following code
 | |
| 				// puts the rtf indent characters that are stored at beginning of string into correct location
 | |
|  				// of rtf header (have to be after the \pard).  Otherwise the indents did not show up.
 | |
| 				Match match = Regex.Match(txt,@"\\fi([-0-9]+) ?\\li([0-9]+)");
 | |
| 				if (match.Success)
 | |
| 				{
 | |
| 					string indentStr = @"\fi" + match.Groups[1].Value + @"\li" + match.Groups[2].Value;
 | |
| 					Rtf = Rtf.Replace(@"\pard", @"\pard" + indentStr);
 | |
| 				}
 | |
| 				// B2017-048, B2017-052, B2017-055  ROs sometimes have two start tokens which make them uneditable.
 | |
| 				newRtf = newRtf.Replace("<START]<START]", "<START]");
 | |
| 				//Point linkIssues = FindLinkIssues(newRtf);
 | |
| 				//if (linkIssues.X != linkIssues.Y)
 | |
| 				//	newRtf = FixBadLinks(newRtf,linkIssues);
 | |
| 				SelectedRtf = _LastRtf = newRtf;
 | |
| 				_lastReadOnly = ReadOnly;
 | |
| 			}
 | |
| 			FindAllLinks();
 | |
| 			if (txt == "") SelectionFont = FormatFont;
 | |
| 		}
 | |
| 		//private string FixBadLinks(string newRtf, Point linkIssues)
 | |
| 		//{
 | |
| 		//	Console.WriteLine("Bad Link rtf = Starts={0}, Ends={1}, \"{2}\"", linkIssues.X,linkIssues.Y, newRtf);
 | |
| 		//	//Volian.Base.Library.vlnStackTrace.ShowStack();
 | |
| 		//	return newRtf;
 | |
| 		//}
 | |
| 		//private static Point FindLinkIssues(string rtf)
 | |
| 		//{
 | |
| 		//	MatchCollection mcStart = Regex.Matches(rtf, @"\<START\]");
 | |
| 		//	MatchCollection mcEnd = Regex.Matches(rtf, @"\[END\>");
 | |
| 		//	return new Point(mcStart.Count, mcEnd.Count);
 | |
| 		//}
 | |
| 		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();
 | |
| 			}
 | |
| 		}
 | |
| 		// The following code is used to display the little 'tic' marks to show indenting:
 | |
| 		private const int WM_PAINT = 15;
 | |
| 		protected override void WndProc(ref Message m)
 | |
| 		{
 | |
| 			if (m.Msg == WM_PAINT)
 | |
| 			{
 | |
| 				this.Invalidate();
 | |
| 				base.WndProc(ref m);
 | |
| 				// B2015-135 Don't Show Hanging Indent if MyItemInfo is null
 | |
| 				if (MyItemInfo == null) return;
 | |
| 				if ((FieldToEdit == E_FieldToEdit.StepText) && (SelectionHangingIndent > 0 || SelectionIndent > 0) && (ActiveMode || MyItemInfo.IsTable))
 | |
| 				{
 | |
| 					using (Graphics g = Graphics.FromHwnd(this.Handle))
 | |
| 					{
 | |
| 						int size = 2;
 | |
| 						g.DrawLine(Pens.DarkBlue, SelectionIndent, 0, SelectionIndent + size, 0);
 | |
| 						g.DrawLine(Pens.DarkBlue, SelectionIndent, 2 * size, SelectionIndent, 0);
 | |
| 						g.DrawLine(Pens.DarkBlue, SelectionHangingIndent, Height - 1, SelectionHangingIndent + size, Height - 1);
 | |
| 						g.DrawLine(Pens.DarkBlue, SelectionHangingIndent, Height - 1 - 2 * size, SelectionHangingIndent, Height - 1);
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 			else
 | |
| 			{
 | |
| 				try
 | |
| 				{
 | |
| 				base.WndProc(ref m);
 | |
| 			}
 | |
| 				catch (Exception ex)
 | |
| 				{
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 		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 " + Volian.Base.Library.vlnFont.ProportionalSymbolFont + @";}}{\colortbl ;\red255\green0\blue0;\red0\green0\blue255;}");  // C2017-036 get best available proportional font for symbols - B2025-039 add Blue for Colored Replace Words
 | |
|             else
 | |
| 				selectedRtfSB.Append(@"{\f1\fnil\fcharset0 FreeMono;}}{\colortbl ;\red255\green0\blue0;\red0\green0\blue255;}");  // FreeMono is now used for the edit screen only.  VESymbFix and Consolas are used for printing
 | |
| 			selectedRtfSB.Append("\r\n");
 | |
| 			// use styles to construct rtf commands to insert into next line (where \b, etc is)
 | |
| 			// B2015-134 Hanging Indent with Hard Returns was not being saved- removed \sl-240\slmult0
 | |
| 			selectedRtfSB.Append(@"\viewkind4\uc1\pard" + sbbeg.ToString() + @"\fs" + Convert.ToInt32(myFont.SizeInPoints * 2).ToString() + @" "); // \f0\fs" + this.Font.SizeInPoints * 2 + @" " + myDisplayTextElement.Text + @"}";
 | |
| 			//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);
 | |
| 			Font locfont = this.Font; 
 | |
| 			int position = SelectionStart;
 | |
| 			// B2021-100: if SelectionFont is null set it, it is used in RtfPrefixForSymbols
 | |
| 			if (SelectionFont == null)
 | |
| 			{
 | |
| 				if (FieldToEdit == E_FieldToEdit.StepText && MyItemInfo!=null)
 | |
| 					SelectionFont = MyItemInfo.GetItemFont().WindowsFont;
 | |
| 				else
 | |
| 					SelectionFont = locfont;
 | |
| 			}
 | |
| 			SelectedRtf = RtfPrefixForSymbols + str + @"}";
 | |
| 			Select(position, 1);
 | |
| 			Select(position + 1, 0);
 | |
| 			if (FieldToEdit == E_FieldToEdit.StepText)
 | |
| 			{
 | |
| 				SelectionFont = MyItemInfo.GetItemFont().WindowsFont;
 | |
| 				RTBAPI.SetFontStyle(this, fs);// B2020-100 Keep the font style
 | |
| 			}
 | |
| 			else
 | |
| 				// if doing properties for folder, docversion, proc or sect, don't get item's font.
 | |
| 				SelectionFont = locfont;  
 | |
| 		}
 | |
| 		private string GetAddSymbolText(string symtxt)
 | |
| 		{
 | |
| 			return (@"{\f1\fs" + this.Font.SizeInPoints * 2 + @" " + symtxt + @"}"); // B2016-281 fixed font selection when inserting a symbol character
 | |
| 		}
 | |
| 		private string GetAddSymbolTextForROs(string symtxt)
 | |
| 		{
 | |
| 			return (@"\f1\fs" + this.Font.SizeInPoints * 2 + @" " + symtxt); //C2019-043 Don't need curly braces when used in RO return value
 | |
| 		}
 | |
| 		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 " + Volian.Base.Library.vlnFont.ProportionalSymbolFont + @";}}"); // C2017-036 get best available proportional font for symbols
 | |
|                 else
 | |
| 					sb.Append(@"{\f1\fnil\fcharset0 FreeMono;}}"); // FreeMono is now used for the edit screen only.  VESymbFix and Consolas are used for printing
 | |
| 				return sb.ToString();
 | |
| 			}
 | |
| 		}
 | |
| 		private string FontSize
 | |
| 		{
 | |
| 			get
 | |
| 			{
 | |
| 				Match match = Regex.Match(Rtf, @"\\fs[0-9]+"); // B2018-012 Make sure that there is at least 1 digit
 | |
| 				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 ");
 | |
| 			linkValue = linkValue.Replace("\\u9586?", "\\f1\\u9586?\\f0 "); // backslash symbol
 | |
| 			linkValue = linkValue.Replace("\\u916?", "\\f1\\u916?\\f0 ");
 | |
| 			linkValue = linkValue.Replace(@"{", @"\{");
 | |
| 			linkValue = linkValue.Replace(@"}", @"\}");
 | |
| 			SelectedRtf = @"{\rtf1\ansi" + FontTable + @"{\colortbl ;\red255\green0\blue0;\red0\green0\blue255;}\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()
 | |
|     {
 | |
|       AdjustWidthForContent(0);
 | |
|     }
 | |
|     public void AdjustWidthForContent(int count)
 | |
| 		{
 | |
| 			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)
 | |
| 				{
 | |
|           if (count < 5 || Width < w)
 | |
|           {
 | |
|             Width = w;
 | |
|             AdjustWidthForContent(count + 1);// Try one more time
 | |
|           }
 | |
| 				}
 | |
| 			}
 | |
| 			else
 | |
| 			{
 | |
|         if (count < 5 || Width < widthMaxWW)
 | |
|         {
 | |
|           Width = widthMaxWW;
 | |
|           AdjustWidthForContent(count + 1);
 | |
|         }
 | |
| 			}
 | |
| 		}
 | |
| 		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 (Rtf.Contains("<START]<START]"))
 | |
| 			//	Volian.Base.Library.vlnStackTrace.ShowStackLocal(2, 10, "Start Start ItemID={0}", MyItemInfo.ItemID);
 | |
| 			if (_InitializingRTB || _IsExperimenting) 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();
 | |
| 		}
 | |
| 		private void ShowMyParentsFonts()
 | |
| 		{
 | |
| 			Console.WriteLine("\r\n--- Parents Fonts ---- For ----{0}", Text);
 | |
| 			ShowMyParentsFonts(this);
 | |
| 			Console.WriteLine("Selection Font".PadRight(31) + SelectionFont);
 | |
| 		}
 | |
| 		private void ShowMyParentsFonts(Control ctrl)
 | |
| 		{
 | |
| 			if (ctrl.Parent is Control)
 | |
| 				ShowMyParentsFonts(ctrl.Parent);
 | |
| 			Console.WriteLine("{0} {1}", ctrl.GetType().Name.PadRight(30), ctrl.Font);
 | |
| 		}
 | |
| 		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 (this.MyItemInfo != null && this.MyItemInfo.IsRtfRaw) return;  // B2017-023 null reference check for empty workdraft set information dialog
 | |
| 			//if (MyRTBItem != null && MyRTBItem.MyStepPanel.SelectedStepRTB != this)
 | |
| 			if (OnIsNotCurrentSelection(this, new EventArgs()))
 | |
| 				return;
 | |
| 
 | |
| 			HandleSelectionChange();
 | |
| 		}
 | |
| 		private void HandleSelectionChange()
 | |
| 		{
 | |
| 			if (_MouseDown) return;
 | |
| 			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.E:
 | |
| 							OnSetMenu(this, new StepRTBMenuEventArgs("InsEquation"));
 | |
| 							e.Handled = true;
 | |
| 							break;
 | |
| 						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;
 | |
| 					}
 | |
| 				}
 | |
| 				// B2022-052: Since any kind of font can occur during paste, if from an external program, a message will
 | |
| 				// be given stating that a symbol may be incorrect because an unsupported font was pasted. It was felt
 | |
| 				// that this was sufficient based on estimate of fix versus chance of occurrence.  Note that the message
 | |
| 				// was moved here from rtftools since the rtftools code is called by non-UI code (5/26/22)
 | |
| 				if (e.KeyCode==Keys.V && Rtf.ToUpper().Contains("GREEK") || Rtf.ToUpper().Contains("BALTIC"))
 | |
| 					System.Windows.Forms.MessageBox.Show("Pasted text may use an unsupported font so some characters may not paste correctly and may require delete/reenter of character from within Proms.",
 | |
| 						"Paste Font Issue", System.Windows.Forms.MessageBoxButtons.OK);
 | |
| 			}
 | |
| 			if (MyItemInfo == null || MyItemInfo.IsRtfRaw)  // B2017-023 null reference check for empty workdraft set information dialog
 | |
| 			{
 | |
| 				e.Handled = true;
 | |
| 				return;
 | |
| 			}
 | |
| 			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 && MyDVI != null && UserInfo.CanEdit(MyUserInfo, MyDVI))  // Hardspace - Ctrl+Shift+Space
 | |
| 					{
 | |
| 						InsertSymbol(@"\u160?");
 | |
| 						e.Handled = true;
 | |
| 					}
 | |
| 					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?", "-");
 | |
| 				srtb.Rtf = srtb.Rtf.Replace(@"\u9586?", @"\\");
 | |
| 				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;
 | |
| 		private int _ImageWidth = 0;
 | |
| 		public int ImageWidth
 | |
| 		{
 | |
| 			get { return _ImageWidth; }
 | |
| 			set { _ImageWidth = value; }
 | |
| 		}
 | |
| 		void StepRTB_KeyDown(object sender, KeyEventArgs e)
 | |
| 		{
 | |
| 			// added jcb 20130103 to support set ro from word doc with annotation when right click menu is opened by keyboard
 | |
| 			if (e.KeyCode == Keys.Apps)
 | |
| 				OnSetMenu(this, new StepRTBMenuEventArgs("OpenContextMenu"));
 | |
| 
 | |
| 			// the following code only allows arrow keys & pageup/down for rtf raw items:
 | |
| 			if (!e.Control && !e.Shift && MyItemInfo != null && MyItemInfo.IsRtfRaw)	// error message is displayed in keypress for this.
 | |
| 			{
 | |
| 				if (e.KeyCode != Keys.Up && e.KeyCode != Keys.Down && e.KeyCode != Keys.Right && e.KeyCode != Keys.Left && e.KeyCode != Keys.PageDown && e.KeyCode != Keys.PageUp)
 | |
| 				{
 | |
| 					e.Handled = true;
 | |
| 					return;
 | |
| 				}
 | |
| 			}
 | |
| 			if (e.Control)
 | |
| 			{
 | |
| 				IsControlChar = true;
 | |
| 				if (e.Shift)
 | |
| 				{
 | |
| 					//Console.WriteLine("keycode =  {0}  key value = {1}",e.KeyCode,e.KeyValue);
 | |
| 					switch (e.KeyCode)
 | |
| 					{
 | |
| 						// The following keys are supported in underlying RTB (with ctrl+shift key), 
 | |
| 						// but PROMS should not do anything for that functionality:
 | |
| 						case Keys.Add: // the plus on the key pad
 | |
| 						case Keys.Subtract:
 | |
| 						case Keys.L:
 | |
| 						case Keys.Oemplus: // the plus on the keyboard (not the key pad)
 | |
| 							e.Handled = true;
 | |
| 							break;
 | |
| 					}
 | |
| 				}
 | |
| 				else
 | |
| 				{
 | |
| 				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:
 | |
| 						// NOTE that if in a Properties Dialog StepRTB (for numbers and titles) or in a Procedure Specific
 | |
| 						// Information (PSI) Dialog, i.e. any non-EditItem/Step editor field, the following code is run 
 | |
| 						// for the ctrl-V.  For EditItems & Grid cells, the code in StepTabRibbon's btnPaste_Click is
 | |
| 						// run.  The way this occurs is that in the designer for StepTabRibbon (StepTabRibbon.designer.cs),
 | |
| 						// the line of code:
 | |
| 						//		this.btnPaste.Shortcuts.Add(DevComponents.DotNetBar.eShortcut.CtrlV);
 | |
| 						// maps the Ctrl-V to btnPaste for those StepRTB's that are associated with the StepTabRibbon, i.e.
 | |
| 						// EditItems & Grid cells.
 | |
| 						IDataObject iData = Clipboard.GetDataObject();
 | |
| 
 | |
| 						// verify that data in clipboard is valid for this type.  If inserting an equation, need to verify that
 | |
| 						// input data has an 'equation', and if not inserting into an equation step type, it must not have
 | |
| 						// equation data.
 | |
| 						//DataFormats.Format frm = DataFormats.GetFormat("Embed Source");
 | |
| 						//System.Windows.Forms.RichTextBox richTextBox1;
 | |
| 						using (System.Windows.Forms.RichTextBox richTextBox1 = new System.Windows.Forms.RichTextBox())
 | |
| 						{
 | |
| 						richTextBox1.Location = new System.Drawing.Point(35, 32);
 | |
| 						richTextBox1.Name = "richTextBox1";
 | |
| 						richTextBox1.Size = new System.Drawing.Size(67, 58);
 | |
| 						richTextBox1.TabIndex = 0;
 | |
| 						richTextBox1.Text = "";
 | |
| 						richTextBox1.ScrollBars = System.Windows.Forms.RichTextBoxScrollBars.None;
 | |
| 						bool hasEquation = false;
 | |
| 						try
 | |
| 						{
 | |
| 								DataFormats.Format frm = DataFormats.GetFormat("Embed Source");
 | |
| 							richTextBox1.Paste(frm);
 | |
| 							if (richTextBox1.Rtf.ToUpper().Contains("OBJCLASS EQU")) hasEquation = true;
 | |
| 							if (richTextBox1.Rtf.ToUpper().Contains("OBJCLASS VIS")) hasEquation = true; // Support Visio
 | |
| 						}
 | |
| 						catch (Exception ex)
 | |
| 						{
 | |
| 							hasEquation = true;
 | |
| 						}
 | |
| 						/// B2020-051: Don't allow pasting of a mathtype equation into an item that isn't the correct type
 | |
| 						if (iData.GetDataPresent("Embed Source")) hasEquation = true;   // mathtype
 | |
| 
 | |
| 						if (MyItemInfo != null && MyItemInfo.IsRtfRaw && MyItemInfo.FormatStepData.Type.ToUpper().Contains("EQUATION") && !hasEquation)
 | |
| 						{
 | |
| 							FlexibleMessageBox.Show("Cannot paste non-equation data into an equation step type.", "Invalid data", MessageBoxButtons.OK);
 | |
| 								//richTextBox1.Dispose();
 | |
| 							e.Handled = true;
 | |
| 							return;
 | |
| 						}
 | |
| 						// if inserting anything other than equation, be sure that an equation is not in the buffer:
 | |
| 						else if (hasEquation && (MyItemInfo == null || (MyItemInfo != null && !MyItemInfo.IsRtfRaw && !MyItemInfo.FormatStepData.Type.ToUpper().Contains("EQUATION"))))
 | |
| 						{
 | |
| 							FlexibleMessageBox.Show("Cannot paste equation data into an non-equation step type.", "Invalid data", MessageBoxButtons.OK);
 | |
| 							//richTextBox1.Dispose();
 | |
| 							e.Handled = true;
 | |
| 							return;
 | |
| 						}
 | |
| 
 | |
| 						// only allow the paste of a screen shot image if using the shortcut switch "/EmbedImages"
 | |
| 						if (Volian.Base.Library.VlnSettings.GetCommandFlag("EmbedImages") && iData.GetDataPresent(DataFormats.Dib)) // Device Independent Bitmap
 | |
| 						{
 | |
| 							System.Drawing.Image img = Clipboard.GetImage();
 | |
| 							ImageWidth = img.Width;
 | |
| 							Width = ImageWidth + 2;
 | |
| 							Paste();
 | |
| 							e.Handled = true;
 | |
| 							return;
 | |
| 						}
 | |
| 						else if (iData.GetDataPresent("Embed Source")) //DS Equation") || iData.GetDataPresent("MathType EF"))
 | |
| 						{
 | |
| 							Size sz = RtfRawItem.GetRtfRawSize(richTextBox1.Rtf);
 | |
| 							this.Rtf = richTextBox1.Rtf;
 | |
| 							Width = sz.Width;
 | |
| 							Height = sz.Height;
 | |
| 							e.Handled = true;
 | |
| 							return;
 | |
| 						}
 | |
| 						else if (iData.GetDataPresent(DataFormats.Dib))
 | |
| 						{
 | |
| 							System.Drawing.Image img = Clipboard.GetImage();
 | |
| 							ImageWidth = img.Width;
 | |
| 							Width = ImageWidth + 2;
 | |
| 							Paste();
 | |
| 							e.Handled = true;
 | |
| 							return;
 | |
| 						}
 | |
| 						else
 | |
| 						{
 | |
| 							if (!iData.GetDataPresent(DataFormats.Text) && !iData.GetDataPresent(DataFormats.Rtf))
 | |
| 							{
 | |
| 								FlexibleMessageBox.Show("Cannot paste, text has special characters or symbols that will not paste correctly.");
 | |
| 							}
 | |
| 							else
 | |
| 							{
 | |
| 								// if contains bad rtf (from Word), paste as text, otherwise, do the paste here.
 | |
| 								if (!PasteRtfAsText(true)) Paste();
 | |
| 								if (SelectionLength == 0 && MyStyleFont != null) SelectionFont = MyStyleFont.WindowsFont;  // B2017-023 null reference check for empty workdraft set information dialog
 | |
| 							}
 | |
| 						}
 | |
| 						} // end using
 | |
| 						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;
 | |
| 						// The following keys are supported in underlying RTB (with ctrl key), but PROMS should not
 | |
| 						// do anything for that functionality:
 | |
| 						case Keys.R:	// Right Align text
 | |
| 						case Keys.L:	// Left Align text
 | |
| 						case Keys.E:	// Center Align text
 | |
| 						case Keys.D1:   // Single space text (D1 is the '1' key)
 | |
| 						case Keys.D2:	// Double space text
 | |
| 						case Keys.D5:	// 1.5 space text
 | |
| 						case Keys.H:	// Find  (proms uses Ctrl+F for find)
 | |
| 						case Keys.Oemplus: // plus on the keyboard (not the key pad)
 | |
| 							e.Handled = true;
 | |
| 							break;
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 			if (((int)e.KeyCode) == 220) e.Handled = true;
 | |
| 			switch (e.KeyCode)
 | |
| 			{
 | |
| 				case Keys.Left:
 | |
| 					if (e.Shift)
 | |
| 					{
 | |
| 						int linkWidth = FindlinkWidth(false,e.Control);
 | |
| 						
 | |
| 						if (linkWidth == 0)// if not link, don't do special processing
 | |
| 						{
 | |
| 							if (e.Control)
 | |
| 							{
 | |
| 								this.AutoWordSelection = true; // this will select a word at a time
 | |
| 							}
 | |
| 							return;
 | |
| 						}
 | |
| 						else
 | |
| 							linkWidth++;
 | |
| 						int len = SelectionLength - linkWidth;
 | |
| 						SetSelection(SelectionStart, len); // adjust the selcection around the linked text
 | |
| 						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 = FindlinkWidth(true,e.Control);
 | |
| 						if (newlen == 0) // not on linked text
 | |
| 						{
 | |
| 							if (e.Shift && e.Control)
 | |
| 								this.AutoWordSelection = true;
 | |
| 							return;
 | |
| 						}
 | |
| 						else if (e.Shift && e.Control)
 | |
| 							newlen++;
 | |
| 						int len = SelectionLength + newlen;
 | |
| 						SetSelection(SelectionStart, len); // adjust the selection around the linked text
 | |
| 						e.Handled = true;
 | |
| 						return;
 | |
| 					}
 | |
| 					if(e.Control && e.Shift && SelectionStart == 0)//b2016-246 Ctrl-Shift-Right Arrow extend select * from ITEMS IIon a word at a time
 | |
| 					{
 | |
| 						SelectionLength++;
 | |
| 						this.AutoWordSelection = 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)
 | |
| 						{
 | |
| 							if (e.Control)
 | |
| 							{
 | |
| 								// B2016-245 [ctrl][delete] deletes rest of word to the right of the cursor
 | |
| 								RtbSendKeys("+^{RIGHT}{BS}");  //[shift][ctrl][right arrow] (selects rest of word to the right) folowed by a backspace (delete)
 | |
| 								e.SuppressKeyPress = true;
 | |
| 							}
 | |
| 							else
 | |
| 							{
 | |
| 								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 (!UserInfo.CanEdit(MyUserInfo, MyItemInfo.MyDocVersion))
 | |
| 					{
 | |
| 						e.Handled = true;
 | |
| 						break;
 | |
| 					}
 | |
| 					if (e.Shift)
 | |
| 					{
 | |
| 						e.Handled = true;
 | |
|             ItemInfo myCopyStep = (this.Parent.Parent.Parent as StepTabPanel).MyDisplayTabControl.MyCopyStep;
 | |
|             if (myCopyStep != null)
 | |
|             {
 | |
| 							// commented out as part of bug fix B2016-148 to fix the <Shift><F5> not popping up the paste options
 | |
| 							//if (this.MyItemInfo.IsSection && myCopyStep.IsSection)
 | |
| 							//	OnSetMenu(this, new StepRTBMenuEventArgs("StepPaste"));
 | |
| 							//if (this.MyItemInfo.IsStep && myCopyStep.IsStep)
 | |
| 							//{
 | |
| 							//	if ((this.MyItemInfo.IsHigh && myCopyStep.IsHigh) || (!this.MyItemInfo.IsHigh && !myCopyStep.IsHigh))
 | |
| 							//		OnSetMenu(this, new StepRTBMenuEventArgs("StepPaste"));
 | |
| 							//}
 | |
| 									OnSetMenu(this, new StepRTBMenuEventArgs("StepPaste"));
 | |
|             }
 | |
|             //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
 | |
| 							StepRTB_ArrowPressed(e.Shift ? E_ArrowKeys.CtrlUp : E_ArrowKeys.CtrlRight);
 | |
| 					}
 | |
| 					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.MyShading.InsertRow(myGrid.Rows.Count - 1); // C2021-004 Table Cell Shading information
 | |
| 								myGrid.Rows.Add(1);
 | |
| 								myGrid.SelectNextCell();
 | |
| 							}
 | |
| 						}
 | |
| 					}
 | |
| 					break;
 | |
| 				case Keys.Enter:
 | |
| 					if (!e.Control && !e.Shift && !e.Alt)
 | |
| 					{
 | |
| 						if (UserInfo.CanEdit(MyUserInfo,MyItemInfo.MyDocVersion))
 | |
| 							OnEnterKeyPressed(sender, e);
 | |
| 						else 
 | |
| 						{
 | |
| 							// user cannot change data so just move to the next step element
 | |
| 							StepRTB_ArrowPressed(E_ArrowKeys.CtrlDown); // perform a <Ctrl><DownArrow>
 | |
| 							HandleLocalSelectionChange();
 | |
| 							e.Handled = true;
 | |
| 						}
 | |
| 					}
 | |
| 					break;
 | |
| 				case Keys.F2:
 | |
| 					if (e.Alt && !e.Control && !e.Shift) // toggle change bar
 | |
| 					{
 | |
| 						if (MyUserInfo.IsAdministrator() || MyUserInfo.IsSetAdministrator(MyDVI) || MyUserInfo.IsWriter(MyDVI))
 | |
| 							OnToggleChangeBar(this, new EventArgs());
 | |
| 						e.Handled = true;
 | |
| 					}
 | |
| 					break;
 | |
| 				case Keys.F7:
 | |
| 					if (!e.Alt) // for the Include On check boxes on the step properties page
 | |
| 					{
 | |
| 						if (e.Control && e.Shift) // Toggle include on Placekeeper as Continuous Action
 | |
| 							OnTogglePlaceKeeperContAct(this, new EventArgs());
 | |
| 						else if (e.Control) // Toggle include on Placekeeper
 | |
| 							OnTogglePlaceKeeper(this, new EventArgs());
 | |
| 						else if (e.Shift) // toggle include on Continuous Action Summary
 | |
| 							OnToggleContinuousActionSummary(this, new EventArgs());
 | |
| 					e.Handled = true;
 | |
| 					}
 | |
| 					break;
 | |
| 			}
 | |
| 			if (e.KeyValue == 187 && e.Control) // equal key pressed
 | |
| 			{
 | |
| 				if (e.Shift) // superscript
 | |
| 				{
 | |
| 					OnToggleSuperScript(this, new EventArgs());
 | |
| 				}
 | |
| 				else // subscript
 | |
| 				{
 | |
| 					OnToggleSubScript(this, new EventArgs());
 | |
| 				}
 | |
| 				e.Handled = true;
 | |
| 			}
 | |
| 			
 | |
| 		}
 | |
| 		// C2021-005 set the selected cell(s) or cell text to the passed in font size
 | |
| 		public void SetFontSize(float newSize)
 | |
| 		{
 | |
| 			if (SelectedText == null || SelectedText == "") // empty table cell selected
 | |
| 				Rtf = SetFontSizeReplace(Rtf, newSize);
 | |
| 			else
 | |
| 			{
 | |
| 				// table cell text selected
 | |
| 				int selst = SelectionStart;
 | |
| 				int selln = SelectionLength;
 | |
| 				string newrtf = SelectedRtf; //B2021-052 use a temporary variable to allow easy debugging
 | |
| 				newrtf = SetFontSizeReplace(newrtf, newSize); // changes the /fs## command in the rtf string
 | |
| 				SelectedRtf = newrtf;// replace the selected portion with the updated font size version of the rtf
 | |
| 				Select(selst, selln); // re-select the cell text
 | |
| 			}
 | |
| 		}
 | |
| 		// C2021-005 set the font size of the passed in RTF text
 | |
| 		private string SetFontSizeReplace(string rtf, float newSize)
 | |
| 		{
 | |
| 			MatchCollection mc = Regex.Matches(rtf, @"\\fs([0-9]+)");
 | |
| 			foreach (Match match in mc)
 | |
| 			{
 | |
| 				float sz = float.Parse(match.Groups[1].Value);
 | |
| 				float repwith = newSize * 2; // RTF font size is double the selected point size
 | |
| 				string repsz = match.Value;     // use \fs## rather than number in replace in case text contains the number
 | |
| 				string repwithsz = match.Value.Replace(sz.ToString(), ((int)repwith).ToString());
 | |
| 				rtf = rtf.Replace(repsz, repwithsz);
 | |
| 			}
 | |
| 			return rtf;
 | |
| 		}
 | |
| 		// C2021-005 parse the rtf for the font sizes.
 | |
| 		//           if there are different font sizes, then return 0
 | |
| 		public float GetRTFFontSize()
 | |
| 		{
 | |
| 			string rtf;
 | |
| 			if (SelectedText == null || SelectedText == "")
 | |
| 				rtf = Rtf;
 | |
| 			else
 | |
| 				rtf = SelectedRtf;
 | |
| 			MatchCollection mc = Regex.Matches(rtf, @"\\fs([0-9]+)");
 | |
| 			bool differentFonts = false;
 | |
| 			float lastSZ = 0;
 | |
| 			foreach (Match match in mc)
 | |
| 			{
 | |
| 				float sz = float.Parse(match.Groups[1].Value);
 | |
| 				if (lastSZ == 0)
 | |
| 					lastSZ = sz;
 | |
| 				else if (lastSZ != sz)
 | |
| 					differentFonts = true;
 | |
| 			}
 | |
| 			return (differentFonts || lastSZ == 0) ? 0 : lastSZ/2; // divide the RTF font size by two to get the font point size
 | |
| 		}
 | |
| 		// F2022-137 Table performance improvements
 | |
| 		public static float GetRTFFontSize(string rtf)
 | |
| 		{
 | |
| 			MatchCollection mc = Regex.Matches(rtf, @"\\fs([0-9]+)");
 | |
| 			bool differentFonts = false;
 | |
| 			float lastSZ = 0;
 | |
| 			foreach (Match match in mc)
 | |
| 			{
 | |
| 				float sz = float.Parse(match.Groups[1].Value);
 | |
| 				if (lastSZ == 0)
 | |
| 					lastSZ = sz;
 | |
| 				else if (lastSZ != sz)
 | |
| 					differentFonts = true;
 | |
| 			}
 | |
| 			return (differentFonts || lastSZ == 0) ? 0 : lastSZ / 2; // divide the RTF font size by two to get the font point size
 | |
| 		}
 | |
| 		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)
 | |
| 			{
 | |
| 				if (!IsControlChar && MyItemInfo != null && MyItemInfo.IsRtfRaw)
 | |
| 				{
 | |
| 					string err = string.Format("Cannot enter text into an equation or incorrect keystroke entered for equation");
 | |
| 					FlexibleMessageBox.Show(err, "Invalid text.", MessageBoxButtons.OK);
 | |
| 					e.Handled = true;
 | |
| 					return;
 | |
| 				}
 | |
| 				if (Text == "" && Parent != null && Parent is VlnFlexGrid)
 | |
| 				{
 | |
| 					//ShowMyParentsFonts();
 | |
| 					SelectionFont = Parent.Font;
 | |
| 				}
 | |
| 				// add the character with its font depending on the char....
 | |
| 				if (!IsControlChar)
 | |
| 				{
 | |
| 					if (e.KeyChar >= ' ')
 | |
| 					{
 | |
| 						// B2016-281  if entered keystroke is a character that converted to a symbol (i.e. dash or backslash)
 | |
| 						//            or if it's a RFT special character (i.e. open and close curly brackets)
 | |
| 						//            then flag it and replace selected text with a null string (removing selected text)
 | |
| 						//            and then insert the symbol or RTF escape codes for those characters
 | |
| 						bool isSymbolOrRTF = e.KeyChar == '-' || e.KeyChar == '\\' || e.KeyChar == '{' || e.KeyChar == '}';
 | |
| 						LinkLocation ll = FindBetweenLinks();
 | |
| 						if (ll != null && SelectionLength == 0) // SelectionLength = 0 means insert
 | |
| 						{
 | |
| 							// replacing between links, this is a special case
 | |
| 							string strpressed = null;
 | |
| 							if (e.KeyChar == '-')
 | |
| 								strpressed = GetAddSymbolText(@"\u8209?");
 | |
| 							else if (e.KeyChar == '\\')
 | |
| 								strpressed = GetAddSymbolText(@"\u9586?");
 | |
| 							else if (e.KeyChar == '}')
 | |
| 								strpressed = @"\}";
 | |
| 							else if (e.KeyChar == '{')
 | |
| 								strpressed = @"\{";
 | |
| 							else
 | |
| 								strpressed = e.KeyChar.ToString();
 | |
| 							InsertCharBetweenLinks(ll, strpressed);
 | |
| 							e.Handled = true;
 | |
| 						}
 | |
| 						else if (SelectionLength != 0)
 | |
| 						{
 | |
| 							// B2016-281 if replacing with a dash, backslash, or curly brackets, first replace with nother (to delete selection)
 | |
| 							//           and set the e.Handled to false so that AddSybol or AddRTF is used to insert that character.
 | |
| 							HandleDeleteKeyWithSelectedText(new KeyEventArgs(Keys.None), isSymbolOrRTF ? "" : e.KeyChar.ToString());
 | |
| 							e.Handled = !isSymbolOrRTF;
 | |
| 						}
 | |
| 					}
 | |
| 					if (!e.Handled)
 | |
| 					{
 | |
| 						if (e.KeyChar == '-')
 | |
| 							AddSymbol(@"\u8209?");
 | |
| 						else if (e.KeyChar == '{')
 | |
| 							AddRtf(@"\{");
 | |
| 						else if (e.KeyChar == '}')
 | |
| 							AddRtf(@"\}");
 | |
| 						else if (e.KeyChar == '\\')
 | |
| 							AddSymbol(@"\u9586?"); // unicode hex 2572
 | |
| 						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;
 | |
| 			}
 | |
| 		}
 | |
| 		public void RtbSendKeys(string keys)
 | |
| 		{
 | |
| 			Focus();
 | |
| 			SendKeys.Send(keys);  // list of keys https://msdn.microsoft.com/en-us/library/system.windows.forms.sendkeys.send%28v=vs.80%29.aspx
 | |
| 			// With .Net Framework 3.0 this can be replaced with EditingCommands  http://msdn.microsoft.com/en-us/library/ms771634.aspx
 | |
| 		}
 | |
| 		public bool PasteRtfAsText(bool PasteNoReturnsSetting)
 | |
| 		{
 | |
| 			// check if rtf is coming from Word, i.e. if it has 'SCHEMAS.MICROSOFT.COM/OFFICE/WORD'.
 | |
| 			// If it is coming from Word, it will be pasted as text so as not to get any rtf commands
 | |
| 			// that PROMS does not support such as odd Fonts, other symbols, etc. This isn't a complete 
 | |
| 			// solution, clipboard data may come from other 3rd-party tools and unsupported Rtf may get 
 | |
| 			// pasted in.  But the hope is that this will happen less often than getting it from MS Word.
 | |
| 			IDataObject myDO = Clipboard.GetDataObject();
 | |
| 			if (myDO.GetDataPresent(DataFormats.Text)) return false;
 | |
| 			string tmpForLink = myDO.GetData(DataFormats.Rtf).ToString();
 | |
| 			if (tmpForLink.ToUpper().Contains(@"SCHEMAS.MICROSOFT.COM/OFFICE/WORD"))
 | |
| 			{
 | |
| 				SelectedText = GetPasteText(PasteNoReturnsSetting, myDO);
 | |
| 				return true;
 | |
| 			}
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		//CSM B2023-095/U2022-004 When Copy/Pasting Symbols, some of the symbols paste in an incorrect font
 | |
| 		//   Changed this to put in the unicode code for any symbols outside the normal ascii range
 | |
| 		// if supplied convertunicode flag is true
 | |
| 		public string GetPasteText(bool PasteNoReturnsSetting, IDataObject myDO, bool convertunicode = false)
 | |
| 		{
 | |
| 			// B2021-0039: symbols not pasting correctly from ctrl-v:
 | |
| 			//	get base list of valid symbols, use base format if MyItemInfo is null.  Use symbols from
 | |
| 			//	the format file versus a list in code
 | |
| 			FormatData fmtd = MyItemInfo != null ? MyItemInfo.ActiveFormat.PlantFormat.FormatData : FormatInfo.PROMSBaseFormat.FormatData;
 | |
| 			SymbolList sl = fmtd.SymbolList;
 | |
| 			string[] allowableSymbols = new string[sl.Count];
 | |
| 			for (int i = 0; i < sl.Count; i++) allowableSymbols[i] = string.Format(@"{0}", sl[i].Unicode);
 | |
| 
 | |
| 			// allowable symbols are those symbols in the format file that the proms editor supports that
 | |
| 			// can be pasted from word as is.
 | |
| 			string  ptext = (string)myDO.GetData(DataFormats.UnicodeText);
 | |
| 			ptext = ptext.TrimEnd("\r\n\t ".ToCharArray());
 | |
| 			if (PasteNoReturnsSetting) ptext = ptext.Replace("\r\n", " ");
 | |
| 
 | |
|             StringBuilder sb = new StringBuilder();
 | |
| 			bool hasBadChar = false;
 | |
| 			foreach (char c in ptext)
 | |
|             {
 | |
| 				if ((c > 0x7e))
 | |
| 				{
 | |
| 					// is this an allowable symbol/character:
 | |
| 					if (allowableSymbols.Any(x => x == $@"{(short)c}"))
 | |
| 					{
 | |
| 						if (convertunicode)
 | |
| 							sb.Append($"\\u{(short) c}?");
 | |
| 						else
 | |
| 							sb.Append(c);
 | |
| 					}
 | |
| 					else
 | |
| 					{
 | |
| 						hasBadChar = true;
 | |
| 						sb.Append("?");
 | |
| 					}
 | |
| 				}
 | |
| 				else
 | |
| 					sb.Append(c);
 | |
|             }
 | |
|             ptext = sb.ToString();
 | |
|             ptext = ptext.Replace("\u2013", "-"); // Replace EN Dash with hyphen
 | |
| 			ptext = ptext.Replace("\u2014", "-"); // Replace EM Dash with hyphen
 | |
| 			ptext = ptext.Replace("\u2011", "-"); // Replace non-breaking hyphen with hyphen
 | |
| 			ptext = ptext.Replace("\u2572", "\\"); // Replace backslash symbol with backslash character
 | |
| 			if (hasBadChar)
 | |
| 				FlexibleMessageBox.Show("Replacing pasted characters that are not supported by Proms with a '?'.");
 | |
| 			return ptext;
 | |
| 		}
 | |
| 		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);
 | |
| 			selection = null;
 | |
| 		}
 | |
| 		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))
 | |
| 				{
 | |
| 					FlexibleMessageBox.Show(fndrpldlg, "Cannot replace linked text!", "Find/Replace");
 | |
| 					dlgrslt = DialogResult.No;
 | |
| 				}
 | |
| 				else
 | |
| 				{
 | |
| 					if (prompt)
 | |
| 						dlgrslt = FlexibleMessageBox.Show(fndrpldlg, "Replace This Occurrence?", "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)
 | |
| 				{
 | |
| 					str = str.Replace("\\", "\u2572").Replace("-","\u2011");
 | |
| 					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;
 | |
| 		}
 | |
| 		// if the selection is on linked text, then return the length of that linked text (the rtf length)
 | |
| 		private int FindlinkWidth(bool movingRight, bool ctrlKey)
 | |
| 		{
 | |
| 			foreach (LinkLocation ll in _LinkLocations)
 | |
| 			{
 | |
| 				int selLen = SelectionLength + ((movingRight) ? 7 : 0);
 | |
| 				if (SelectionStart + selLen >= ll.Start && SelectionStart + selLen - ((!movingRight && ctrlKey)?1:0) <= ll.End) return ll.End - ll.Start + 7;
 | |
| 			}
 | |
| 			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>", RegexOptions.Singleline);
 | |
| 			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);// this last parameter was commented out in 7/24/09 but it appears to be valid
 | |
| 				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 share 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
 | |
| 				bool onword = true;
 | |
| 				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
 | |
| 					}
 | |
| 					else if (tsi1 is ToolStripMenuItem && tsi1.Text == "Clip Board") // B2017-024 added the Clip Board context menu in FrmSi design
 | |
| 					{
 | |
| 						e.Menu.Items.RemoveAt(i + 1); // if Clip Board menu item is there, then remove o ur Edit Menu
 | |
| 					}
 | |
| 					else
 | |
| 					{
 | |
| 						// B2016-242: check for editorial change on spell check word click.
 | |
| 						// Add an event to any context menu items that have a corrected word.
 | |
| 						// Note that a line separates corrected words from menu item selections  
 | |
| 						// and the line does not have any text.  So once we hit the line, don't add 
 | |
| 						// event handler to flag the user selected to use the correction.
 | |
| 						if (onword) e.Menu.Items[i].Click += new EventHandler(spellcheckWord_Click);
 | |
| 						if (e.Menu.Items[i].Text == null || e.Menu.Items[i].Text == "") onword = false;
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		static void spellcheckWord_Click(object sender, EventArgs e)
 | |
| 		{
 | |
| 			ToolStripMenuItem tsmi = sender as ToolStripMenuItem;
 | |
| 			if (tsmi != null)
 | |
| 			{
 | |
| 				// B2016-242: because this is a static method, the format flag for EditorialSpellCheck cannot be checked
 | |
| 				// before setting 'DidEditorialSpellCheck'.  But the format flag is checked before the 'DidEditorialSpellCheck'
 | |
| 				// is actually used in rtbitem.
 | |
| 				DidEditorialSpellCheck = true;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		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; 
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		//  B2015-024 have Spell Checker text changes be in editorial mode (not assign a change bar but keep existing change bar)
 | |
| 		public static bool DidEditorialSpellCheck = false;
 | |
| 
 | |
| 		// 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);
 | |
| 
 | |
| 			// C2015-028 Add Editorial Mode to PROMS Step Editor
 | |
| 			//   if in Editorial Mode, treat it the same as if the EditorialSpellCheck flag is set in the Format file
 | |
| 			bool editorialmode = (this.Parent.Parent.Parent as StepTabPanel).MyDisplayTabControl.IsInEditorialMode;
 | |
| 
 | |
|             if (MyItemInfo.ActiveFormat.PlantFormat.FormatData.EditData.EditoralSpellCheck || editorialmode)
 | |
| 					DidEditorialSpellCheck = MySpellCheckDlg.DidCorrectSpelling;  // B2015-024 spell checker in editoral mode
 | |
| 			return (nBad >= 0); // nBad = -1 means user pressed Cancel button
 | |
| 		}
 | |
| 		
 | |
| 		// This allows us to turn off/on the spell 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
 | |
| }
 |