3705 lines
127 KiB
C#
3705 lines
127 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.IO;
|
|
using System.Drawing;
|
|
using System.Data;
|
|
using System.Text;
|
|
using System.Windows.Forms;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text.RegularExpressions;
|
|
using VEPROMS.CSLA.Library;
|
|
using Volian.Base.Library;
|
|
|
|
namespace Volian.Controls.Library
|
|
{
|
|
public delegate void StepRTBEvent(object sender, EventArgs args);
|
|
public delegate void StepRTBCursorKeysEvent(object sender, KeyEventArgs args);
|
|
public delegate void StepRTBCursorMovementEvent(object sender, StepRTBCursorMovementEventArgs args);
|
|
public delegate void StepRTBModeChangeEvent(object sender, StepRTBModeChangeEventArgs args);
|
|
public delegate void StepRTBMenuEvent(object sender, StepRTBMenuEventArgs args);
|
|
public delegate void StepRTBTableWidthEvent(object sender, StepRTBTableWidthEventArgs args);
|
|
public delegate bool StepRTBBooleanEvent(object sender, EventArgs args);
|
|
public delegate void StepRTBLocationEvent(object sender, StepRTBLocationEventArgs args);
|
|
public delegate void StepRTBMouseEvent(object sender, MouseEventArgs args);
|
|
public delegate void StepRTBRoEvent(object sender, StepRTBRoEventArgs args);
|
|
//public delegate void StepRTBMouseWheelEvent(object sender, MouseEventArgs args);
|
|
public partial class StepRTB : RichTextBox // , IStepRTB
|
|
{
|
|
private static readonly log4net.ILog _MyLog = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
|
|
|
private bool _Disposed = false;
|
|
private static int _CountCreated = 0;
|
|
private static int _CountDisposed = 0;
|
|
private static int _CountFinalized = 0;
|
|
private static int IncrementCountCreated
|
|
{ get { return ++_CountCreated; } }
|
|
private int _CountWhenCreated = IncrementCountCreated;
|
|
public static int CountCreated
|
|
{ get { return _CountCreated; } }
|
|
public static int CountNotDisposed
|
|
{ get { return _CountCreated - _CountDisposed; } }
|
|
public static int CountNotFinalized
|
|
{ get { return _CountCreated - _CountFinalized; } }
|
|
private bool _Finalized = false;
|
|
~StepRTB()
|
|
{
|
|
if (!_Finalized) _CountFinalized++;
|
|
_Finalized = true;
|
|
}
|
|
#region Events
|
|
public event StepRTBRoEvent RoInsert;
|
|
public void OnRoInsert(object sender, StepRTBRoEventArgs args)
|
|
{
|
|
if (RoInsert != null) RoInsert(sender, args);
|
|
}
|
|
public event StepRTBEvent ReturnToEditor;
|
|
public void OnReturnToEditor(object sender, EventArgs args)
|
|
{
|
|
if (ReturnToEditor != null) ReturnToEditor(sender, args);
|
|
}
|
|
public event StepRTBEvent EditModeChanged;
|
|
public void OnEditModeChanged(object sender, EventArgs args)
|
|
{
|
|
if (EditModeChanged != null) EditModeChanged(sender, args);
|
|
}
|
|
public event StepRTBEvent DoSaveContents;
|
|
public void OnDoSaveContents(object sender, EventArgs args)
|
|
{
|
|
if (DoSaveContents != null) DoSaveContents(sender, args);
|
|
}
|
|
public event StepRTBMouseEvent DoMouseWheel;
|
|
public void OnDoMouseWheel(object sender, MouseEventArgs args)
|
|
{
|
|
if (DoMouseWheel != null) DoMouseWheel(sender, args);
|
|
}
|
|
public event StepRTBLocationEvent OpenContextMenu;
|
|
public void OnOpenContextMenu(object sender, StepRTBLocationEventArgs args)
|
|
{
|
|
if (OpenContextMenu != null) OpenContextMenu(sender, args);
|
|
}
|
|
public event StepRTBEvent CopyStep;
|
|
public void OnCopyStep(object sender, EventArgs args)
|
|
{
|
|
if (CopyStep != null) CopyStep(sender, args);
|
|
}
|
|
public event StepRTBBooleanEvent CheckClipboard;
|
|
public bool OnCheckClipboard(object sender, EventArgs args)
|
|
{
|
|
if (CheckClipboard != null) return CheckClipboard(sender, args);
|
|
return false;
|
|
}
|
|
public event StepRTBCursorKeysEvent EnterKeyPressed;
|
|
public void OnEnterKeyPressed(object sender, KeyEventArgs args)
|
|
{
|
|
if (EnterKeyPressed != null) EnterKeyPressed(sender, args);
|
|
}
|
|
public event StepRTBEvent 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 IsRoTable
|
|
{
|
|
get { return (Parent is VlnFlexGrid && (Parent as VlnFlexGrid).IsRoTable); }
|
|
}
|
|
public bool HasVScroll
|
|
{
|
|
get
|
|
{
|
|
return RTBAPI.HasVertScroll(this);
|
|
}
|
|
|
|
}
|
|
public bool HasHScroll
|
|
{
|
|
get
|
|
{
|
|
return RTBAPI.HasHorzScroll(this);
|
|
}
|
|
|
|
}
|
|
private bool _EditMode = true;
|
|
/// <summary>
|
|
/// Allows insert of links. If false, don't allow selection of links.
|
|
/// </summary>
|
|
public bool EditMode
|
|
{
|
|
get { return _EditMode; }
|
|
set
|
|
{
|
|
_EditMode = value;
|
|
OnEditModeChanged(this, new EventArgs());
|
|
}
|
|
}
|
|
private static string _MySymbolFontName;
|
|
public static string MySymbolFontName
|
|
{
|
|
get { return StepRTB._MySymbolFontName; }
|
|
set { StepRTB._MySymbolFontName = value; }
|
|
}
|
|
private static FontFamily _MyFontFamily = null;
|
|
public static FontFamily MyFontFamily
|
|
{
|
|
get { return StepRTB._MyFontFamily; }
|
|
set
|
|
{
|
|
_MyFontFamily = value;
|
|
if (value != null)
|
|
{
|
|
Font font;
|
|
if (value.IsStyleAvailable(FontStyle.Regular))
|
|
font = new Font(value, 10);
|
|
else if (value.IsStyleAvailable(FontStyle.Bold))
|
|
font = new Font(value, 10, FontStyle.Bold);
|
|
else // (value.IsStyleAvailable(FontStyle.Italic))
|
|
font = new Font(value, 10, FontStyle.Italic);
|
|
using (StepRTB srtb = new StepRTB())
|
|
{
|
|
if (srtb.FontIsFixed(font)) MySymbolFontName = "FreeMono"; // FreeMono is now used for the edit screen only. VESymbFix and Consolas are used for printing
|
|
else MySymbolFontName = "Arial Unicode MS";
|
|
}
|
|
}
|
|
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
|
|
{
|
|
if (_RtfPrefix == null)
|
|
{
|
|
StringBuilder selectedRtfSB = new StringBuilder();
|
|
AddFontTable(selectedRtfSB, FormatFont, FontIsFixed(FormatFont));
|
|
_RtfPrefix = selectedRtfSB.ToString();
|
|
}
|
|
return _RtfPrefix + @"\f1\fs" + FormatFont.SizeInPoints * 2 + " ";
|
|
}
|
|
}
|
|
public string RtfPrefix
|
|
{
|
|
get
|
|
{
|
|
if (_RtfPrefix == null)
|
|
{
|
|
StringBuilder selectedRtfSB = new StringBuilder();
|
|
AddFontTable(selectedRtfSB, FormatFont, FontIsFixed(FormatFont));
|
|
_RtfPrefix = selectedRtfSB.ToString();
|
|
}
|
|
return _RtfPrefix;// +@"{\colortbl ;\red255\green0\blue0;}";
|
|
}
|
|
}
|
|
// August 5, 2009 - KBR & RHM:
|
|
// Insert/Overwrite will be developed later if needed. various issues
|
|
// were found during initial development that made its scope larger than
|
|
// expected. Problems were related to having overstrike on in the following
|
|
// cases:
|
|
// 1) left arrow when on link - positions after link
|
|
// 2) left arrow and after link - does not move
|
|
// 3) shift left arrow does not move past links correctly and also, first
|
|
// shift left arrow looks more like insert mode.
|
|
// private bool _OverWrite;
|
|
// _IsDirty compares the original rtf to the current rtf from the
|
|
// richtextbox to see if a change was made.
|
|
public bool IsDirty
|
|
{
|
|
get { return OrigRTF != Rtf; }
|
|
}
|
|
private bool _InitializingRTB;
|
|
private 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) _MyStyleFont = MyItemInfo.GetItemFont();
|
|
return _MyStyleFont;
|
|
}
|
|
}
|
|
private bool _ActiveMode = false;
|
|
public bool ActiveMode
|
|
{
|
|
get { return _ActiveMode; }
|
|
set { _ActiveMode = value; }
|
|
}
|
|
private ItemInfo _MyItemInfo;
|
|
public ItemInfo MyItemInfo
|
|
{
|
|
get
|
|
{
|
|
if (_MyItemInfo == null && Parent is EditItem)
|
|
_MyItemInfo = (Parent as EditItem).MyItemInfo;
|
|
else if (_MyItemInfo == null && Parent != null && Parent.Parent is EditItem)
|
|
_MyItemInfo = (Parent.Parent as EditItem).MyItemInfo;
|
|
return _MyItemInfo;
|
|
}
|
|
set { _MyItemInfo = value; }
|
|
}
|
|
private string _OrigRTF;
|
|
public string OrigRTF
|
|
{
|
|
get { return _OrigRTF; }
|
|
set { _OrigRTF = value; }
|
|
}
|
|
private Font _FormatFont;
|
|
public Font FormatFont
|
|
{
|
|
get
|
|
{
|
|
if (_FormatFont == null)
|
|
{
|
|
Font formatFont;
|
|
if (MyItemInfo != null)
|
|
formatFont = MyItemInfo.GetItemFont().WindowsFont; // OrigDisplayText.TextFont.WindowsFont;
|
|
else
|
|
formatFont = Font;
|
|
if (MyItemInfo != null && (MyItemInfo.IsTable || MyItemInfo.IsFigure))
|
|
_FormatFont = formatFont;
|
|
else
|
|
{
|
|
//if (VlnSettings.DebugMode || VlnSettings.ProductionMode)
|
|
_FormatFont = new Font(MyFontFamily == null ? formatFont.FontFamily : MyFontFamily, formatFont.Size, formatFont.Style);
|
|
//else
|
|
// _FormatFont = new Font("Bookman Old Style", formatFont.Size, formatFont.Style);
|
|
// TODO: Release Mode
|
|
//Font = _origDisplayText.TextFont.WindowsFont; // font defined in plant's format
|
|
}
|
|
}
|
|
// 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);
|
|
}
|
|
}
|
|
// RefreshDisplay is used to update the rtb for an entire Item as defined by MyItemInfo.
|
|
public void RefreshDisplay(bool activeMode)
|
|
{
|
|
if (IsExperimenting) return;
|
|
ActiveMode = activeMode;
|
|
OnAdjustTableWidth(this, new StepRTBTableWidthEventArgs(true));
|
|
_InitializingRTB = true;
|
|
DisplayText vlntxt = new DisplayText(MyItemInfo, E_EditPrintMode.Edit, VwMode, !ActiveMode, FieldToEdit, true,null, null);
|
|
//if (_origDisplayText != null && vlntxt.StartText == _origDisplayText.StartText)
|
|
//{
|
|
// ReadOnly = !(EpMode == E_EditPrintMode.Edit && VwMode == E_ViewMode.Edit);
|
|
// if (!ReadOnly && !edit) ReadOnly = true;
|
|
// return;
|
|
//}
|
|
OrigDisplayText = vlntxt;
|
|
|
|
// RHM 20101201 - Don't reset the text. Calculate the text and compare it with the existing text in AddRTFText
|
|
//Text = ""; // Initialize text before add text
|
|
// IMPORTANT: SetLineSpacing must be set before Links, otherwise it
|
|
// was confusing the 'handle' of the rtf box.
|
|
//Console.WriteLine("'font',{0}", Font);
|
|
//if(Text == "")SelectionFont = Font; // Initialize SelectionFont
|
|
if (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);
|
|
LastRtf = Rtf;
|
|
}
|
|
}
|
|
RTBAPI.SetLineSpacing(this, RTBAPI.ParaSpacing.PFS_EXACT);
|
|
bool readOnlyStep = MyItemInfo == null || MyItemInfo.FormatStepData == null ? false : MyItemInfo.FormatStepData.ReadOnly;
|
|
if (!readOnlyStep)
|
|
{
|
|
StepConfig sc = new StepConfig(MyItemInfo.MyContent.Config);
|
|
if (IsDerived(sc))
|
|
readOnlyStep = true;
|
|
}
|
|
ReadOnly = readOnlyStep || VwMode == E_ViewMode.View || ActiveMode == false;
|
|
AddRtfText(vlntxt.StartText);
|
|
//AddRtfStyles();
|
|
// set readonly based on initial modes, however, these may change if
|
|
// user selected view mode.
|
|
ClearUndo();
|
|
// RHM: 20101122 - Not sure why the RightMargin is set. The following line was added in Rev 23
|
|
// in May of 2008.
|
|
//
|
|
// RightMargin = Width;
|
|
//
|
|
// Normally a the Right Margin is handled by the RichTextBox it defaults to a value of 0.
|
|
//
|
|
// If the RightMargin is equal to the width of the RichTextBox the word-wrap occurs just beyond
|
|
// the visible extent (right edge) of the RichTextBox when it is in view mode. In edit mode it
|
|
// wraps within the visible extent. An example of this is Step 24 of ES02 in HLP EOPs.
|
|
//
|
|
// If the RightMargin is greater than the width of the RichTextBox, the word-wrap occurs beyond
|
|
// the visible extent of the RichTextBox for both view and edit modes.
|
|
//
|
|
// Setting the RightMargin to the Width minus one, accounts for the slight indent (1 pixel) of
|
|
// the text within the RichTextBox.
|
|
RightMargin = Width > 0 ? Width - 1 : 0;
|
|
// figure out if needs outlined, depends on table/figure type
|
|
if (!ActiveMode)
|
|
{
|
|
RemoveEventHandlers();
|
|
OnAdjustTableWidth(this, new StepRTBTableWidthEventArgs(false));// View Mode
|
|
SelectAll();
|
|
//if (SelectionHangingIndent !=0) SelectionHangingIndent = 0;
|
|
int indchar = 0;
|
|
string indentToken = MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.IndentToken;
|
|
if (indentToken == null || indentToken=="0") indentToken = "\x5";
|
|
|
|
// this line of code was moved before the find for the indent so that
|
|
// the window gets resized if the indent changes the height, i.e. more line(s) in window.
|
|
AddEventHandlers();
|
|
//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 so 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");
|
|
}
|
|
}
|
|
}
|
|
// 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"))
|
|
Rtf = Rtf.Replace(@"\'a0", @"\u1?");
|
|
OrigRTF = Rtf;
|
|
_InitializingRTB = false;
|
|
|
|
AdjustSizeForContents(!ActiveMode);
|
|
}
|
|
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));
|
|
//}
|
|
}
|
|
}
|
|
#endregion
|
|
#region Constructors
|
|
public StepRTB()
|
|
{
|
|
InitializeComponent();
|
|
SetUpStepRTB();
|
|
AddEventHandlers();
|
|
this.BorderStyleChanged += new EventHandler(StepRTB_BorderStyleChanged);
|
|
|
|
}
|
|
public StepRTB(IContainer container)
|
|
{
|
|
container.Add(this);
|
|
InitializeComponent();
|
|
_Container = container;
|
|
SetUpStepRTB();
|
|
AddEventHandlers();
|
|
this.BorderStyleChanged += new EventHandler(StepRTB_BorderStyleChanged);
|
|
}
|
|
protected override void OnMouseWheel(MouseEventArgs e)
|
|
{
|
|
OnDoMouseWheel(this, e);
|
|
//MyRTBItem.MyStepPanel.MouseWheel(e);
|
|
//base.OnMouseWheel(e);
|
|
}
|
|
// When a border style is changed, the richtextbox's handle is 'destroyed', so that the handleDestroyed
|
|
// event is done. This was causing the event handlers to be removed (RemoveEventHandler) so that the
|
|
// keypress event handler was not run.
|
|
private void RemoveEventHandlers()
|
|
{
|
|
if (_EventHandlersForKeyPress==0) return;
|
|
ContentsResized -= new ContentsResizedEventHandler(StepRTB_ContentsResized);
|
|
this.Click -= new EventHandler(StepRTB_Click);
|
|
this.KeyPress -= new KeyPressEventHandler(StepRTB_KeyPress);
|
|
this.KeyDown -= new KeyEventHandler(StepRTB_KeyDown);
|
|
this.KeyUp -= new KeyEventHandler(StepRTB_KeyUp);
|
|
this.TextChanged -= new EventHandler(StepRTB_TextChanged);
|
|
this.MouseUp -= new MouseEventHandler(StepRTB_MouseUp);
|
|
this.MouseDown -= new MouseEventHandler(StepRTB_MouseDown);
|
|
this.MouseLeave -= new EventHandler(StepRTB_MouseLeave);
|
|
this.SelectionChanged -= new EventHandler(StepRTB_SelectionChanged);
|
|
this.ContextMenuStripChanged -= new EventHandler(StepRTB_ContextMenuStripChanged);
|
|
this.RTBSelectionChanged -= new StepRTBEvent(StepRTB_RTBSelectionChanged);
|
|
this.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);
|
|
}
|
|
}
|
|
private void SetUpStepRTB()
|
|
{
|
|
DetectUrls = false;
|
|
if(DoSpellCheck)
|
|
C1SpellChecker2.SetActiveSpellChecking(this, true);
|
|
this.Height = 10; // initialize the height to 10, the default height was too big for the cells in grid tables
|
|
BorderStyle = System.Windows.Forms.BorderStyle.None;
|
|
this.ScrollBars = RichTextBoxScrollBars.None;
|
|
this.DetectUrls = 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;
|
|
}
|
|
void StepRTB_SelectionChanged(object sender, EventArgs e)
|
|
{
|
|
if (_InitializingRTB || _IsExperimenting) return;
|
|
HandleSelectionChange();
|
|
}
|
|
private bool _MouseDown = false;
|
|
private bool _ContextMenuStripChanged = false;
|
|
private void StepRTB_MouseDown(object sender, MouseEventArgs e)
|
|
{
|
|
|
|
//Console.WriteLine("vvvvvvvvvv StepRTB Mouse Down id= {0}",MyItemInfo.ItemID);
|
|
bool inPsi = this.Parent.FindForm().Name.Contains("frmPSI");
|
|
if (!_ContextMenuStripChanged)
|
|
OnSetMenu(this, new StepRTBMenuEventArgs(inPsi?"PSI":"OpenContextMenu"));
|
|
_ContextMenuStripChanged = false;
|
|
CorrectSelectionAtEndOfLine();
|
|
}
|
|
void StepRTB_MouseUp(object sender, MouseEventArgs e)
|
|
{
|
|
_MouseDown = false;
|
|
//Console.WriteLine("^^^^^^^^^^ StepRTB Mouse Up id= {0}", MyItemInfo.ItemID);
|
|
|
|
if(this.Focused) // Only HandleSelectionChange if this control has focus.
|
|
{
|
|
HandleSelectionChange();
|
|
// save our context menu to add to the spell checker's context menu
|
|
ThisContextMenuStrip = this.ContextMenuStrip;
|
|
}
|
|
}
|
|
#endregion
|
|
#region ApplicationSupport
|
|
// Used in StepTabRibbon:
|
|
//public void ToggleEditView(E_ViewMode vwMode)
|
|
//{
|
|
// OnDoSaveContents(this, new EventArgs()); // SaveText();
|
|
// //ItemInfo tmp = MyItemInfo;
|
|
// //MyItemInfo = null;
|
|
// //ReadOnly = !ReadOnly;
|
|
// //EpMode = ReadOnly ? E_EditPrintMode.Print : E_EditPrintMode.Edit;
|
|
// VwMode = vwMode;
|
|
// ReadOnly = VwMode == E_ViewMode.View;
|
|
// ViewRTB = ReadOnly;
|
|
// Clear();
|
|
// RefreshDisplay(!ViewRTB);
|
|
// //MyItemInfo = tmp;
|
|
// SelectionStart = 0;
|
|
// SelectionLength = 0;
|
|
// //OnModeChange(this, new StepRTBModeChangeEventArgs(ViewRTB?E_ViewMode.View:E_ViewMode.Edit));
|
|
//}
|
|
public void InsertRO(string value, string link)
|
|
{
|
|
AddRtfLink(value, link);
|
|
}
|
|
public void InsertTran(string value, string link)
|
|
{
|
|
AddRtfLink(value, link);
|
|
}
|
|
public void InsertSymbol(int symbcode)
|
|
{
|
|
string sym = string.Format(symbcode < 256 ? "\'{0:X2}" : @"\u{0}", symbcode);
|
|
if (symbcode < 256)
|
|
AddText(((char)symbcode).ToString());
|
|
else
|
|
AddSymbol(sym); // Adds font commands around symbol, needed for higher codes
|
|
}
|
|
public void InsertSymbol(string symbol)
|
|
{
|
|
AddSymbol(symbol);
|
|
}
|
|
public void InsertIndent(string indentToken)
|
|
{
|
|
if (indentToken == null || indentToken == "0") indentToken = "\x5";
|
|
AddText(indentToken);
|
|
}
|
|
public void InsertText(string txt)
|
|
{
|
|
AddText(txt);
|
|
}
|
|
|
|
private void ToggleCase()
|
|
{
|
|
char type = 'l';
|
|
// do not change case on linked text
|
|
RangeStatus rs = FindRangeStatus();
|
|
string tmp = null;
|
|
if (rs != RangeStatus.NoContainedLinks)
|
|
{
|
|
int start = SelectionStart;
|
|
int ostart = SelectionStart;
|
|
int end = SelectionStart + SelectionLength;
|
|
bool processed = false;
|
|
while (!processed && start <= end)
|
|
{
|
|
foreach (LinkLocation ll in LinkLocations)
|
|
{
|
|
if (ll.Start >= start && ll.End <= end)
|
|
{
|
|
processed = true;
|
|
if (start < ll.Start)
|
|
{
|
|
SelectionStart = start;
|
|
SelectionLength = ll.Start - start;
|
|
}
|
|
start = ll.End + 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
string ostring = SelectedText;
|
|
if (ostring.Length == 0) return; // nothing selected
|
|
if (ostring.Length == 1)
|
|
type = char.IsUpper(ostring, 0) ? 'l' : 'U';
|
|
else if ((char.IsUpper(ostring, 0) && char.IsUpper(ostring, 1)) ||
|
|
(char.IsLower(ostring, 0) && char.IsUpper(ostring, 1))) type = 'l'; // lower case
|
|
else if ((char.IsUpper(ostring, 0) && char.IsLower(ostring, 1))) type = 'U'; // upper case
|
|
else type = 'T'; // Title case
|
|
SetSelectedCase(type);
|
|
}
|
|
|
|
public void SetSelectedCase(char type)
|
|
{
|
|
// do not change case on linked text
|
|
RangeStatus rs = FindRangeStatus();
|
|
string tmp = null;
|
|
if (rs == RangeStatus.NoContainedLinks)
|
|
SetCase(type);
|
|
else
|
|
{
|
|
int start = SelectionStart;
|
|
int ostart = SelectionStart;
|
|
int end = SelectionStart + SelectionLength;
|
|
StringBuilder sb = new StringBuilder();
|
|
while (start <= end)
|
|
{
|
|
bool processed = false;
|
|
foreach (LinkLocation ll in LinkLocations)
|
|
{
|
|
if (ll.Start >= start && ll.End <= end)
|
|
{
|
|
processed = true;
|
|
if (start < ll.Start)
|
|
{
|
|
SelectionStart = start;
|
|
SelectionLength = ll.Start - start;
|
|
SetCase(type);
|
|
}
|
|
start = ll.End + 1;
|
|
break;
|
|
}
|
|
}
|
|
// if none were processed, no more links, copy over any remaining text.
|
|
if (!processed)
|
|
{
|
|
SelectionStart = start;
|
|
SelectionLength = end-start;
|
|
SetCase(type);
|
|
start = end + 1;
|
|
}
|
|
}
|
|
SelectionStart = ostart;
|
|
SelectionLength = end - ostart;
|
|
}
|
|
}
|
|
|
|
private void SetCase(char type)
|
|
{
|
|
int ostart = SelectionStart;
|
|
int olen = SelectionLength;
|
|
string ostring = SelectedText;
|
|
string tmp = null;
|
|
bool docap = true;
|
|
// go character by character. Because of symbols, setting entire
|
|
// to upper or lower set symbols incorrectly some of time (depending
|
|
// on symbol) .
|
|
for (int i = 0; i < olen; i++)
|
|
{
|
|
SelectionStart = ostart + i;
|
|
SelectionLength = 1;
|
|
switch (type)
|
|
{
|
|
case 'l':
|
|
if (SelectedText[0] >= 'A' && SelectedText[0] <= 'Z')
|
|
SelectedText = SelectedText.ToLower();
|
|
break;
|
|
case 'U':
|
|
if (SelectedText[0] >= 'a' && SelectedText[0] <= 'z')
|
|
SelectedText = SelectedText.ToUpper();
|
|
break;
|
|
case 'T':
|
|
if (docap && SelectedText[0] >= 'a' && SelectedText[0] <= 'z')
|
|
SelectedText = SelectedText.ToUpper();
|
|
else if (!docap && SelectedText[0] >= 'A' && SelectedText[0] <= 'Z')
|
|
SelectedText = SelectedText.ToLower();
|
|
docap = ostring[i] == ' ';
|
|
break;
|
|
}
|
|
}
|
|
SelectionStart = ostart;
|
|
SelectionLength = olen;
|
|
}
|
|
#endregion
|
|
#region AddRtfTextAndStyles
|
|
private string _LastRtf = "";
|
|
public string LastRtf
|
|
{
|
|
get { return _LastRtf; }
|
|
set { _LastRtf = value; }
|
|
}
|
|
private bool _lastReadOnly = false;
|
|
private void AddRtfText(string txt)
|
|
{
|
|
//Console.WriteLine("ItemID:{0}", MyItemInfo.ItemID);
|
|
//if(MyItemInfo.ItemID==10256)
|
|
// Volian.Base.Library.vlnStackTrace.ShowStackLocal("ItemID:{0}", MyItemInfo.ItemID.ToString());
|
|
StringBuilder selectedRtfSB = new StringBuilder();
|
|
AddFontTable(selectedRtfSB, FormatFont, FontIsFixed(FormatFont));
|
|
_RtfPrefix = selectedRtfSB.ToString();
|
|
selectedRtfSB.Append(txt);
|
|
string newRtf = selectedRtfSB.ToString() + "}";
|
|
if(newRtf != _LastRtf || ReadOnly != _lastReadOnly)
|
|
{
|
|
//Console.WriteLine("ItemID:{0}\r\nOld:'{1}'\r\nNew:'{2}'\r\n", MyItemInfo.ItemID, Rtf, newRtf);
|
|
this.ContentsResized -= new ContentsResizedEventHandler(StepRTB_ContentsResized);
|
|
Text = "";
|
|
this.ContentsResized += new ContentsResizedEventHandler(StepRTB_ContentsResized);
|
|
// 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);
|
|
}
|
|
SelectedRtf = _LastRtf = newRtf;
|
|
_lastReadOnly = ReadOnly;
|
|
}
|
|
FindAllLinks();
|
|
if (txt == "") SelectionFont = FormatFont;
|
|
}
|
|
public void SetTableGridCellRTFPrefix(Font myfont)
|
|
{
|
|
if (_FormatFont == null)
|
|
_FormatFont = myfont;
|
|
|
|
if (_RtfPrefix == null)
|
|
{
|
|
StringBuilder selectedRtfSB = new StringBuilder();
|
|
AddFontTable(selectedRtfSB, myfont, FontIsFixed(myfont));
|
|
_RtfPrefix = selectedRtfSB.ToString();
|
|
}
|
|
}
|
|
// 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);
|
|
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
|
|
{
|
|
base.WndProc(ref m);
|
|
}
|
|
}
|
|
private static void AddFontTable(StringBuilder selectedRtfSB, Font myFont, bool isFixed)
|
|
{
|
|
StringBuilder sbbeg = new StringBuilder();
|
|
StringBuilder sbend = new StringBuilder();
|
|
if (myFont.Bold)
|
|
{
|
|
sbbeg.Append(@"\b");
|
|
sbend.Append(@"\b0");
|
|
}
|
|
if (myFont.Underline)
|
|
{
|
|
sbbeg.Append(@"\ul");
|
|
sbend.Insert(0, @"\ulnone");
|
|
}
|
|
if (myFont.Italic)
|
|
{
|
|
sbbeg.Append(@"\i");
|
|
sbend.Insert(0, @"\i0");
|
|
}
|
|
selectedRtfSB.Append(@"{\rtf1\ansi\ansicpg1252\deff0\deflang1033{\fonttbl{\f0\fnil\fcharset2 " + myFont.FontFamily.Name + @";}"); //}\f0\fs" + this.Font.SizeInPoints * 2 + @" " + myDisplayTextElement.Text + @"}}";
|
|
if (!isFixed)
|
|
selectedRtfSB.Append(@"{\f1\fnil\fcharset0 Arial Unicode MS;}}{\colortbl ;\red255\green0\blue0;}");
|
|
else
|
|
selectedRtfSB.Append(@"{\f1\fnil\fcharset0 FreeMono;}}{\colortbl ;\red255\green0\blue0;}"); // 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)
|
|
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;
|
|
SelectedRtf = RtfPrefixForSymbols + str + @"}";
|
|
Select(position, 1);
|
|
RTBAPI.SetFontStyle(this, fs);
|
|
Select(position + 1, 0);
|
|
if (FieldToEdit == E_FieldToEdit.StepText)
|
|
SelectionFont = MyItemInfo.GetItemFont().WindowsFont;
|
|
else
|
|
// if doing properties for folder, docversion, proc or sect, don't get item's font.
|
|
SelectionFont = locfont;
|
|
}
|
|
private string GetAddSymbolText(string symtxt)
|
|
{
|
|
return (@"{\f0\fs" + this.Font.SizeInPoints * 2 + @" " + symtxt + @"}");
|
|
}
|
|
public void AddRtfLink(string linkUrl, string linkValue)
|
|
{
|
|
if (CreateParams.ClassName == "RICHEDIT50W")
|
|
|
|
AddLink50(linkUrl, linkValue);
|
|
else
|
|
AddLink20(linkUrl, linkValue);
|
|
}
|
|
public string FontTable
|
|
{
|
|
get
|
|
{
|
|
StringBuilder sb = new StringBuilder();
|
|
sb.Append(@"{\fonttbl{\f0\fnil\fcharset2 " + this.Font.FontFamily.Name + @";}");
|
|
if (!FontIsFixed(this.Font))
|
|
sb.Append(@"{\f1\fnil\fcharset0 Arial Unicode MS;}}");
|
|
else
|
|
sb.Append(@"{\f1\fnil\fcharset0 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]*");
|
|
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("\\u916?", "\\f1\\u916?\\f0 ");
|
|
linkValue = linkValue.Replace(@"{", @"\{");
|
|
linkValue = linkValue.Replace(@"}", @"\}");
|
|
SelectedRtf = @"{\rtf1\ansi"+FontTable+@"{\colortbl ;\red255\green0\blue0;}\v"+FontSize+@" <START]\v0\cf1 " + linkValue + @"\cf0\v " + linkUrl + @"[END>\v0 }";
|
|
this.SelectionLength = 0;
|
|
this.SelectionStart = position;
|
|
FindAllLinks();
|
|
}
|
|
private void AddLink50(string linkValue, string linkUrl)
|
|
{
|
|
//this.DetectUrls = false;
|
|
int position = SelectionStart;
|
|
SelectionLength = 0;
|
|
SelectedRtf = string.Format(@"{{\rtf\field{{\*\fldinst{{HYPERLINK ""www.volian.com #{0}"" }}}}{{\fldrslt{{\cf2\ul {1}}}}}}}", linkUrl, linkValue);
|
|
this.SelectionStart = this.TextLength;
|
|
this.SelectionLength = 0;
|
|
}
|
|
private void AddRtfStyles()
|
|
{
|
|
if ((OrigDisplayText.TextFont.Style & E_Style.Bold) > 0)
|
|
{
|
|
this.SelectAll();
|
|
RTBAPI.ToggleBold(true, this, RTBAPI.RTBSelection.SCF_SELECTION);
|
|
this.Select(0, 0);
|
|
}
|
|
// Bug Fix
|
|
// The code below was changed to select all of the text and then
|
|
// apply the underlining to the selected text, because if the
|
|
// the underlining was applied to RTBAPI.RTBSelection.SCF_ALL
|
|
// the Links were changed so that they were no longer hidden.
|
|
if ((OrigDisplayText.TextFont.Style & E_Style.Underline) > 0)
|
|
// RTBAPI.ToggleUnderline(true, this, RTBAPI.RTBSelection.SCF_ALL);
|
|
{
|
|
this.SelectAll();
|
|
RTBAPI.ToggleUnderline(true, this, RTBAPI.RTBSelection.SCF_SELECTION);
|
|
this.Select(0, 0);
|
|
}
|
|
// Bug Fix
|
|
// The code below was changed to select all of the text and then
|
|
// apply the italics to the selected text, because if the
|
|
// the italics was applied to RTBAPI.RTBSelection.SCF_ALL
|
|
// the Links were changed so that they were no longer hidden.
|
|
if ((OrigDisplayText.TextFont.Style & E_Style.Italics) > 0)
|
|
// RTBAPI.ToggleItalic(true, this, RTBAPI.RTBSelection.SCF_ALL);
|
|
{
|
|
this.SelectAll();
|
|
RTBAPI.ToggleItalic(true, this, RTBAPI.RTBSelection.SCF_SELECTION);
|
|
this.Select(0, 0);
|
|
}
|
|
}
|
|
#endregion
|
|
#region HeightSupport
|
|
public event StepRTBEvent HeightChanged;
|
|
private void OnHeightChanged(object sender, EventArgs args)
|
|
{
|
|
if (HeightChanged != null) HeightChanged(sender, args);
|
|
}
|
|
private void AdjustSizeForContents(bool adjustWidth)
|
|
{
|
|
if (!_InitializingRTB)
|
|
{
|
|
Size offset = Size - ClientSize;
|
|
int widthNew = (this is TableCellEditor) ? Width : (ContentsSize.Width + offset.Width + AdjustSize.Width);
|
|
//int widthNew = Width;
|
|
//if (!(this is TableCellEditor))
|
|
// widthNew = ContentsSize.Width + offset.Width + AdjustSize.Width;
|
|
int heightNew = ContentsSize.Height + offset.Height + AdjustSize.Height;
|
|
// Don't make the window narrower unless it has text - RHM - 20100107
|
|
Size szNew = new Size(((Text != "" && adjustWidth) ? widthNew : (widthNew > Width ? widthNew : Width)), heightNew);
|
|
if (this.Size != szNew)
|
|
{
|
|
int heightOld = Height;
|
|
//Console.WriteLine("before {0}, {1}, {2}, {3}, {4}", Size, szNew, widthNew, Width, this.GetType().Name);
|
|
this.Size = szNew;
|
|
//Console.WriteLine("after {0}, {1}, {2}, {3}", Size, szNew, widthNew, Width);
|
|
if (heightOld != Height)
|
|
{
|
|
OnHeightChanged(this, new EventArgs());
|
|
if (ScrollPos.Y != 0) // Adjust ScrollPosition if it isn't Zero
|
|
ScrollPos = new Point(0, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
private float GetStringWidth(string strMeasureString)
|
|
{
|
|
using (Graphics g = Graphics.FromHwnd(Handle))
|
|
{
|
|
return g.MeasureString(strMeasureString, Font).Width;
|
|
}
|
|
}
|
|
private int Ceiling(float f)
|
|
{
|
|
return (int)(Math.Ceiling(f));
|
|
}
|
|
public int MaxTextWidth
|
|
{
|
|
get
|
|
{
|
|
int maxWidth = 0;
|
|
for (int i = 0; i < TextLength; i++)
|
|
{
|
|
int w = GetPositionFromCharIndex(i).X;
|
|
maxWidth = Math.Max(maxWidth, w);
|
|
}
|
|
return maxWidth+10; // add 10 to account for the last character
|
|
}
|
|
}
|
|
public void AdjustWidthForContent()
|
|
{
|
|
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 (_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 (MyRTBItem != null && MyRTBItem.MyStepPanel.SelectedStepRTB != this)
|
|
if (OnIsNotCurrentSelection(this, new EventArgs()))
|
|
return;
|
|
|
|
HandleSelectionChange();
|
|
}
|
|
private void HandleSelectionChange()
|
|
{
|
|
if (_HandlingCtrlA) return;
|
|
if (!_HandlingCtrlA && this.TextLength == this.SelectionLength && this.SelectedRtf.EndsWith("\\par\r\n}\r\n"))
|
|
{
|
|
_HandlingCtrlA = true;
|
|
SelectAll();
|
|
_HandlingCtrlA = false;
|
|
}
|
|
//HandleOverWrite();
|
|
//vlnStackTrace.ShowStackLocal("HandleSelectionChangeStack", 1, 10);
|
|
bool startingValue = _AdjustingSelection;
|
|
if (_IdentifyingLinks || _ProcessingDelete) return;
|
|
// If the cursor is beyond the end of the line then move the cursor back one character
|
|
if (CorrectSelectionAtEndOfLine())
|
|
return;
|
|
if (ProcessKeystrokes)
|
|
{
|
|
if (!_MouseDown && !_AdjustingSelection)
|
|
{
|
|
if (_LinkLocations != null)
|
|
{
|
|
DebugPrint("HSC===================>Beginning: SelectionStart {0}, SelectionLength {1}", SelectionStart, SelectionLength);
|
|
_AdjustingSelection = true;
|
|
LinkLocation ll = FindLinkLocation();
|
|
LinkLocation llend = null;
|
|
if (SelectionLength != 0)
|
|
llend = FindLinkLocation(SelectionStart + SelectionLength - 1);
|
|
if (ll != null)
|
|
{
|
|
if (SelectionStart == ll.Start && SelectionLength == 0)
|
|
{
|
|
if (SelectionStart >= 7)
|
|
{
|
|
// If the cursor is at the beginning of the line and a link is at the beginning of the line
|
|
// then select the link rather than postitioning the cursor at the end of the previous line
|
|
if (!_LastWasLeftArrow && GetFirstCharIndexOfCurrentLine() == SelectionStart)
|
|
SetSelection(ll);
|
|
else
|
|
{
|
|
DebugPrint("HSC===================>ll Insert: Sel {0}, Length {1}, Link Start {2}, Link Length {3}", SelectionStart, SelectionLength, ll.Start, ll.Length);
|
|
SelectionStart = ll.Start - 7;
|
|
}
|
|
}
|
|
}
|
|
else if (SelectionStart + SelectionLength > ll.End) // Beyond the end of the starting link
|
|
{
|
|
int end = SelectionStart + SelectionLength;
|
|
if (llend != null) end = llend.End; // If it extends into another link extend the end to the end of that link
|
|
DebugPrint("HSC===================>ll After: Sel {0}, Length {1}, Link Start {2}, Link Length {3}", SelectionStart, SelectionLength, ll.Start, ll.Length);
|
|
SetSelection(ll.Start, end - ll.Start);
|
|
}
|
|
else if (SelectionStart >= ll.Start || SelectionLength > 0)// Within the starting link
|
|
{
|
|
DebugPrint("HSC===================>ll: Sel {0}, Length {1}, Link Start {2}, Link Length {3}", SelectionStart, SelectionLength, ll.Start, ll.Length);
|
|
SetSelection(ll);
|
|
}
|
|
}
|
|
else if (llend != null)
|
|
{
|
|
DebugPrint("HSC===================>llend: Sel {0}, Length {1}, Link Start {2}, Link Length {3}", SelectionStart, SelectionLength, llend.Start, llend.Length);
|
|
// Check to see if the beginning starts before the <START] token. If it does, adjust the start
|
|
int newStart = SelectionStart + (SelectedText.StartsWith("<START]") ? 7 : 0);
|
|
SetSelection(newStart, llend.End - newStart);
|
|
}
|
|
else
|
|
{
|
|
if (SelectedText.EndsWith("<START]") && !SelectedText.EndsWith("[END><START]"))
|
|
{
|
|
DebugPrint("HSC===================>Removing ending <START] token");
|
|
SelectionLength = SelectionLength - 7;
|
|
}
|
|
if (SelectedText.StartsWith("<START]"))
|
|
{
|
|
DebugPrint("HSC===================>Removing starting <START] token");
|
|
SetSelection(SelectionStart + 7, SelectionLength - 7);
|
|
}
|
|
}
|
|
_AdjustingSelection = false;
|
|
}
|
|
}
|
|
}
|
|
if (startingValue != _AdjustingSelection)
|
|
DebugPrint("================> _AdjustingSelection problem");
|
|
DebugPrint("RS------ SelectionChange > {0}", FindRangeStatus());
|
|
if (SelectionLength > 0 && IsSelectionLinked(SelectionStart, SelectionLength))
|
|
{
|
|
if (SelectedText.IndexOf(@"[END>") > 0) MyLinkText = SelectedText.Substring(0, SelectedText.IndexOf(@"[END>"));
|
|
else MyLinkText = SelectedText;
|
|
}
|
|
else
|
|
MyLinkText = null;
|
|
OnRTBSelectionChanged(this, new EventArgs());
|
|
_LastWasLeftArrow = false;
|
|
}
|
|
/// <summary>
|
|
/// If the Selection is beyond the end of the line, move the selection back one character
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
private bool CorrectSelectionAtEndOfLine()
|
|
{
|
|
if (SelectionStart > 0 && SelectionLength == 0 &&
|
|
GetFirstCharIndexFromLine(GetLineFromCharIndex(SelectionStart)) >
|
|
GetFirstCharIndexOfCurrentLine())
|
|
{
|
|
SelectionStart--; // Move the cursor back one character
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//private void HandleOverWrite()
|
|
//{
|
|
// if (!_OverWrite) return;
|
|
// if (SelectionLength > 0) return;
|
|
// if (SelectionStart == TextLength) return;
|
|
// Console.WriteLine("Handle Overwrite, SelectionStart = {0}, SelectionLength = {1}", SelectionStart, SelectionLength);
|
|
// SelectionLength = 1;
|
|
//}
|
|
private bool _CheckSelection = false;
|
|
#endregion
|
|
#region Delete Handlers
|
|
private void HandleDeleteKeyWithSelectedText(KeyEventArgs e, string keychars)
|
|
{
|
|
_ProcessingDelete = true;
|
|
FindRangeStatus();
|
|
//DebugPrint("RS---------------- Delete > {0}", _RTBRangeStatus);
|
|
switch (_RTBRangeStatus)
|
|
{
|
|
case RangeStatus.NoContainedLinks:
|
|
case RangeStatus.Before_After:
|
|
case RangeStatus.Before_EndLink:
|
|
case RangeStatus.Before_EndBox:
|
|
default:
|
|
DeleteCurrentSelection(keychars);
|
|
e.SuppressKeyPress = true;
|
|
break;
|
|
case RangeStatus.Before_Between: //myRTB1.SelectedText.EndsWith(@"[END><START]")
|
|
DeleteEndBetweenLinks(keychars);
|
|
e.SuppressKeyPress = true;
|
|
break;
|
|
case RangeStatus.Between_EndBox:
|
|
case RangeStatus.Between_EndLink:
|
|
case RangeStatus.Between_After:
|
|
DeleteStartBetweenLinks(keychars);
|
|
e.SuppressKeyPress = true;
|
|
break;
|
|
case RangeStatus.Between_Between:
|
|
DeleteBetweenBetweenLinks(keychars);
|
|
e.SuppressKeyPress = true;
|
|
break;
|
|
case RangeStatus.StartLink_EndBox:
|
|
case RangeStatus.StartLink_EndLink:
|
|
case RangeStatus.StartLink_After:
|
|
ExpandSelectionToIncludeStart();
|
|
DeleteCurrentSelection(keychars);
|
|
e.SuppressKeyPress = true;
|
|
break;
|
|
case RangeStatus.StartLink_Between:
|
|
ExpandSelectionToIncludeStart();
|
|
DeleteEndBetweenLinks(keychars);
|
|
e.SuppressKeyPress = true;
|
|
break;
|
|
case RangeStatus.StartBox_EndLink:
|
|
case RangeStatus.StartBox_EndBox:
|
|
case RangeStatus.StartBox_After:
|
|
DeleteFromStartOfBox(keychars);
|
|
e.SuppressKeyPress = true;
|
|
break;
|
|
case RangeStatus.StartBox_Between:
|
|
DeleteFromStartOfBoxEndBetweenLinks(keychars);
|
|
e.SuppressKeyPress = true;
|
|
break;
|
|
// REMOVE THESE CASES OR PUT A MESSAGE OUT SAYING ERROR IN CODE - CASE
|
|
// NOT HANDLED
|
|
case RangeStatus.Before_StartLink:
|
|
case RangeStatus.Between_StartLink:
|
|
case RangeStatus.StartLink_StartLink:
|
|
case RangeStatus.StartBox_StartLink:
|
|
break;
|
|
}
|
|
_ProcessingDelete = false;
|
|
StepRTB_TextChanged(this, new EventArgs());
|
|
}
|
|
private void InsertCharBetweenLinks(LinkLocation ll)
|
|
{
|
|
InsertCharBetweenLinks(ll, ' ', false);
|
|
}
|
|
private void InsertCharBetweenLinks(LinkLocation ll, string strToAdd)
|
|
{
|
|
InsertCharBetweenLinks(ll, strToAdd, true);
|
|
}
|
|
private void InsertCharBetweenLinks(LinkLocation ll, string strToAdd, bool setSelect)
|
|
{
|
|
Rtf = Rtf.Substring(0, ll.StartRtf) + @"\v0 " + strToAdd + @"\v " + Rtf.Substring(ll.StartRtf);
|
|
if (setSelect)
|
|
SelectionStart = ll.Start - 6; // account for <START] - 1 for the character typed
|
|
}
|
|
/// <summary>
|
|
/// This inserts a space in between two links.
|
|
/// It actually inserts "\v0 {space}\v " between the END tag and the START tag
|
|
/// </summary>
|
|
/// <param name="ll"></param>
|
|
/// <param name="charToAdd"></param>
|
|
/// <param name="setSelect"></param>
|
|
private void InsertCharBetweenLinks(LinkLocation ll, char charToAdd, bool setSelect)
|
|
{
|
|
//_InsertingSpaceBetweenLinks = true;
|
|
DebugPrint("ICBLvvvvvvvvvvvvvvv>>>");
|
|
Rtf = Rtf.Substring(0, ll.StartRtf) + @"\v0 " + charToAdd.ToString() + @"\v " + Rtf.Substring(ll.StartRtf);
|
|
//_InsertingSpaceBetweenLinks = false;
|
|
if (setSelect)
|
|
SelectionStart = ll.Start - 6; // account for <START] - 1 for the character typed
|
|
DebugPrint("ICBL^^^^^^^^^^^^^^^>>>");
|
|
}
|
|
private void ExpandSelectionToIncludeStart()
|
|
{
|
|
//_AdjustingSelection = true;
|
|
SetSelection(SelectionStart - 7, SelectionLength + 7); // Expand selection to include start
|
|
//_AdjustingSelection = false;
|
|
}
|
|
public string GetSelectionForClipBoard()
|
|
{
|
|
string selTxtRTF = SelectedRtf;
|
|
LinkLocation llstart = FindLinkLocation();
|
|
if (llstart != null)
|
|
{
|
|
selTxtRTF = Rtf.Substring(llstart.StartRtf, llstart.EndRtf - llstart.StartRtf);
|
|
string lookfor = selTxtRTF.Substring(selTxtRTF.IndexOf(' '));
|
|
return SelectedRtf.Replace(lookfor, @"\v " + selTxtRTF);
|
|
}
|
|
return (selTxtRTF);
|
|
}
|
|
|
|
private void DeleteBetweenBetweenLinks(string keychars)
|
|
{
|
|
|
|
DebugSelection("DeleteBetweenBetweenLinks");
|
|
int selStart = SelectionStart - 7;
|
|
int selLength = SelectionLength + 2; // Include the two added spaces
|
|
InsertCharBetweenLinks(_RangeEndLink.NextLink); // Add a space at the end link
|
|
InsertCharBetweenLinks(_RangeStartLink); // Add a space a the start link
|
|
SetSelection(selStart, selLength);// Select everything including the spaces
|
|
DeleteCurrentSelection(keychars);// Delete Selection
|
|
}
|
|
/// <summary>
|
|
/// This is added to handle a glitch in richtextbox. Depending on
|
|
/// which direction that selection is made (left -> right or right -> left)
|
|
/// a replacement or delete may not work, you'll just get a 'beep'.
|
|
/// This approach consistently works.
|
|
/// </summary>
|
|
public bool WasXDelete = false;
|
|
private void DeleteCurrentSelection(string keys)
|
|
{
|
|
|
|
DebugPrint("vvvvvvvvvvvvxxxxxxxxxxxx>");
|
|
DebugSelection("Before X");
|
|
DebugPrint(keys == null ? "NULL" : "NOT NULL");
|
|
SelectedText = keys==null?"X":keys; // replace text with X
|
|
WasXDelete = (keys == null);
|
|
DebugSelection("After X");
|
|
DebugPrint("------------xxxxxxxxxxxx>");
|
|
if (keys == null)
|
|
{
|
|
_SendBackSpace = true;
|
|
RtbSendKeys("{BS}"); // remove X
|
|
//this.ClearUndo(); // undo was redisplay 'X' and then deleted text
|
|
Application.DoEvents();
|
|
DebugSelection("After BS");
|
|
}
|
|
DebugPrint("^^^^^^^^^^^^xxxxxxxxxxxx>");
|
|
}
|
|
private void DeleteSelection(int start, int length, string keychars)
|
|
{
|
|
SetSelection(start, length);
|
|
DeleteCurrentSelection(keychars);
|
|
}
|
|
private void DeleteEndBetweenLinks(string keychars)
|
|
{
|
|
_ProcessingKeys++;
|
|
DebugSelection("DeleteEndBetweenLinks");
|
|
int sstart = SelectionStart;
|
|
int slen = SelectionLength + 1 - 7;
|
|
// This puts a space at the link that starts at the end of the selection
|
|
InsertCharBetweenLinks(_RangeEndLink.NextLink);
|
|
//_AdjustingSelection = true;
|
|
DeleteSelection(sstart, slen, keychars);
|
|
//_AdjustingSelection = false;
|
|
_ProcessingKeys--;
|
|
}
|
|
private void DeleteStartBetweenLinks(string keychars)
|
|
{
|
|
_ProcessingKeys++;
|
|
DebugSelection("DeleteStartBetweenLinks");
|
|
int slen = SelectionLength + 8;
|
|
int sstart = SelectionStart - 7;
|
|
//LinkLocation ll = FindBetweenLinks(SelectionStart);
|
|
InsertCharBetweenLinks(_RangeStartLink);
|
|
DeleteSelection(sstart, slen, keychars);
|
|
_ProcessingKeys--;
|
|
}
|
|
private void DeleteFromStartOfBox(string keychars)
|
|
{
|
|
_ProcessingKeys++;
|
|
DebugSelection("DeleteFromStartOfBox");
|
|
int slen = SelectionLength;
|
|
SetSelection(0, 0);
|
|
//RtbSendKeys(" "); // open for space between links which separates END/START tokens
|
|
SelectedText = " ";
|
|
DeleteSelection(0, slen + 8, keychars);
|
|
_ProcessingKeys--;
|
|
}
|
|
private void DeleteFromStartOfBoxEndBetweenLinks(string keychars)
|
|
{
|
|
_ProcessingKeys++;
|
|
DebugSelection("DeleteFromStartOfBoxEndBetweenLinks");
|
|
// This puts a space at the link that starts at the end of the selection
|
|
int sLen = SelectionStart + SelectionLength - 7 + 2;// -7 for <START] + 2 for the spaces that are added
|
|
//LinkLocation ll = FindBetweenLinks(SelectionStart + SelectionLength);
|
|
InsertCharBetweenLinks(_RangeEndLink.NextLink);
|
|
//RtbSendKeys("{RIGHT} "); // open for space between links which separates END/START tokens
|
|
//int sLen = myRTB1.SelectionStart;
|
|
SetSelection(0, 0);
|
|
//RtbSendKeys(" "); // open for space between links which separates END/START tokens
|
|
SelectedText = " "; // open for space between links which separates END/START tokens
|
|
DeleteSelection(0, sLen, keychars);
|
|
_ProcessingKeys--;
|
|
}
|
|
#endregion
|
|
#region KeyboardHandling
|
|
void StepRTB_KeyUp(object sender, KeyEventArgs e)
|
|
{
|
|
if (e.Control)
|
|
{
|
|
if (e.Alt)
|
|
{
|
|
switch (e.KeyCode)
|
|
{
|
|
case Keys.M:
|
|
OnOpenAnnotations(this, new EventArgs());
|
|
e.Handled = true;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
if (e.Shift)
|
|
{
|
|
switch (e.KeyCode)
|
|
{
|
|
case Keys.F:
|
|
OnSetMenu(this, new StepRTBMenuEventArgs("InsFigure"));
|
|
e.Handled = true;
|
|
break;
|
|
case Keys.T:
|
|
OnSetMenu(this, new StepRTBMenuEventArgs("InsTable"));
|
|
e.Handled = true;
|
|
break;
|
|
case Keys.N:
|
|
OnSetMenu(this, new StepRTBMenuEventArgs("InsNote"));
|
|
e.Handled = true;
|
|
break;
|
|
case Keys.C:
|
|
OnSetMenu(this, new StepRTBMenuEventArgs("InsCaution"));
|
|
e.Handled = true;
|
|
break;
|
|
case Keys.S:
|
|
OnSetMenu(this, new StepRTBMenuEventArgs("InsSubStps"));
|
|
e.Handled = true;
|
|
break;
|
|
case Keys.H:
|
|
OnSetMenu(this, new StepRTBMenuEventArgs("InsHLS"));
|
|
e.Handled = true;
|
|
break;
|
|
case Keys.R:
|
|
OnSetMenu(this, new StepRTBMenuEventArgs("InsRNO"));
|
|
e.Handled = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!e.Shift) return;
|
|
switch (e.KeyCode)
|
|
{
|
|
// this was put here rather than in the KeyDown event like the others
|
|
// so that processing of keystroke (StepRTB_KeyDown) would position selectionstart
|
|
// and selectionlength
|
|
case Keys.Down:
|
|
int newend = FindEndDown();
|
|
if (newend > 0) SetSelection(SelectionStart, newend - SelectionStart);
|
|
break;
|
|
case Keys.Space:
|
|
if (e.Control) // Hardspace - Ctrl+Shift+Space
|
|
InsertSymbol(@"\u160?");
|
|
break;
|
|
case Keys.F3: // shift F3
|
|
e.Handled = true;
|
|
ToggleCase(); // toggle through Upper, Lower, and Title case
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
private string GetSelectedDisplayableText()
|
|
{
|
|
using (StepRTB srtb = new StepRTB())
|
|
{
|
|
srtb.Rtf = this.SelectedRtf.Replace(@"\u8209?", "-");
|
|
string rtnstr = "";
|
|
string ctxt = srtb.Text;//this.SelectedText;
|
|
if (ctxt.EndsWith("<START]"))
|
|
ctxt = ctxt.Substring(0, ctxt.Length - 7);
|
|
int idx = 0;
|
|
int strtidx = ctxt.IndexOf("<START]");
|
|
int lnkidx = ctxt.IndexOf("#Link");
|
|
int endidx = ctxt.IndexOf("[END>");
|
|
if ((strtidx == -1 || strtidx > lnkidx) && lnkidx > -1 && endidx > -1)
|
|
{
|
|
rtnstr += ctxt.Substring(idx, lnkidx);
|
|
idx = endidx + 5;
|
|
strtidx = ctxt.IndexOf("<START]", idx);
|
|
lnkidx = ctxt.IndexOf("#Link:", idx);
|
|
endidx = ctxt.IndexOf("[END>", idx);
|
|
}
|
|
while (strtidx > -1)
|
|
{
|
|
rtnstr += ctxt.Substring(idx, strtidx - idx);
|
|
idx = strtidx + 7;
|
|
rtnstr += ctxt.Substring(idx, lnkidx - idx);
|
|
idx = endidx + 5;
|
|
strtidx = ctxt.IndexOf("<START]", idx);
|
|
lnkidx = ctxt.IndexOf("#Link:", idx);
|
|
endidx = ctxt.IndexOf("[END>", idx);
|
|
}
|
|
if (idx < ctxt.Length)
|
|
rtnstr += ctxt.Substring(idx);
|
|
return rtnstr;
|
|
}
|
|
}
|
|
|
|
private bool IsControlChar = false;
|
|
private bool _SendBackSpace = false;
|
|
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"));
|
|
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();
|
|
if (iData.GetDataPresent(DataFormats.Dib)) // Device Independent Bitmap
|
|
{
|
|
System.Drawing.Image img = Clipboard.GetImage();
|
|
ImageWidth = img.Width;
|
|
Width = ImageWidth + 2;
|
|
Paste();
|
|
}
|
|
else
|
|
{
|
|
if (!iData.GetDataPresent(DataFormats.Text) && !iData.GetDataPresent(DataFormats.Rtf))
|
|
{
|
|
MessageBox.Show("Cannot paste, text has special characters or symbols that will not paste correctly.");
|
|
}
|
|
else
|
|
{
|
|
// if contains bad rtf (from Word), paste as text, otherwise, do the paste here.
|
|
if (!PasteRtfAsText(true)) Paste();
|
|
if (SelectionLength == 0) SelectionFont = MyStyleFont.WindowsFont;
|
|
}
|
|
}
|
|
e.Handled = true;
|
|
return;
|
|
case Keys.Home:
|
|
StepRTB_HomeEndPressed(e);
|
|
e.Handled = true;
|
|
break;
|
|
case Keys.End:
|
|
StepRTB_HomeEndPressed(e);
|
|
e.Handled = true;
|
|
break;
|
|
// 16bit Proms used 'ctrl-enter' for Hard returns. 32bit Proms uses 'shift-enter'
|
|
// because the richtextbox does this by default. Also Word uses 'shift-enter'
|
|
// for Hard return. And Word uses 'ctrl-enter' for inserting of page break. So
|
|
// 'ctrl-enter' for 32bit will insert page break
|
|
case Keys.Enter:
|
|
OnInsertPgBrk(this, new EventArgs());
|
|
e.Handled = true;
|
|
break;
|
|
// 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 || SelectionStart == this.Text.Length)
|
|
{
|
|
StepRTB_ArrowPressed(e.Control ? E_ArrowKeys.CtrlRight : E_ArrowKeys.Right);
|
|
e.Handled = true;
|
|
}
|
|
HandleLocalSelectionChange();
|
|
break;
|
|
case Keys.Down:
|
|
int l = GetLineFromCharIndex(SelectionStart);
|
|
Point pos = new Point();
|
|
pos.X = ClientRectangle.Width;
|
|
pos.Y = ClientRectangle.Height;
|
|
int lastIndex = this.GetCharIndexFromPosition(pos);
|
|
int lastLine = this.GetLineFromCharIndex(lastIndex);
|
|
if (e.Control || l >= lastLine)
|
|
{
|
|
StepRTB_ArrowPressed(e.Control ? E_ArrowKeys.CtrlDown : E_ArrowKeys.Down);
|
|
HandleLocalSelectionChange();
|
|
e.Handled = true;
|
|
return;
|
|
}
|
|
if (!e.Shift) HandleLocalSelectionChange();
|
|
// if shift-down & on link at beginning of box - do special processing (regular processing
|
|
// didn't handle it correctly.
|
|
if (e.Shift && lastLine > 0 && SelectionStart == 0 && _LinkLocations.Count > 0 && _LinkLocations[0].Start == 7)
|
|
{
|
|
Point cpos = GetPositionFromCharIndex(SelectionStart);
|
|
int addon = ClientRectangle.Height / (lastLine + 1);
|
|
cpos.Y = cpos.Y + addon;
|
|
int selend = GetCharIndexFromPosition(cpos);
|
|
Select(7, selend - 7);
|
|
e.Handled = true;
|
|
}
|
|
break;
|
|
case Keys.PageUp:
|
|
StepRTB_PageKeyPressed(e);
|
|
e.Handled = true;
|
|
break;
|
|
case Keys.PageDown:
|
|
StepRTB_PageKeyPressed(e);
|
|
e.Handled = true;
|
|
break;
|
|
case Keys.Delete:
|
|
if (SelectionLength == 0)
|
|
{
|
|
foreach (LinkLocation lls in _LinkLocations)
|
|
{
|
|
if (SelectionStart >= lls.Start - 7 && SelectionStart < lls.End)
|
|
{
|
|
SetSelection(lls);// Select the link to the right
|
|
HandleDeleteKeyWithSelectedText(e, null);
|
|
e.SuppressKeyPress = true;
|
|
return;
|
|
}
|
|
}
|
|
if (SelectionStart != TextLength)
|
|
{
|
|
SelectionStart++;// A Delete can be accomplished with a right arrow followed by a backspace.
|
|
RtbSendKeys("{BS}"); // This is done due to a glitch in the RichTextBox that sometimes causes a beep rather than a delete
|
|
e.SuppressKeyPress = true;
|
|
}
|
|
}
|
|
else
|
|
HandleDeleteKeyWithSelectedText(e, null);
|
|
break;
|
|
case Keys.Back:
|
|
if (_SendBackSpace)
|
|
{
|
|
_SendBackSpace = false;
|
|
return;
|
|
}
|
|
_CheckSelection = true;
|
|
if (SelectionLength == 0)
|
|
{
|
|
foreach (LinkLocation lls in _LinkLocations)
|
|
{
|
|
if (SelectionStart > lls.Start - 7 && SelectionStart <= lls.End)
|
|
{
|
|
SetSelection(lls);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (SelectionLength > 0) HandleDeleteKeyWithSelectedText(e, null);
|
|
break;
|
|
case Keys.Insert:
|
|
//_OverWrite = !_OverWrite;
|
|
//if (_OverWrite)
|
|
//{
|
|
// HandleSelectionChange();
|
|
//}
|
|
//else
|
|
//{
|
|
// SelectionLength = 0;
|
|
// HandleSelectionChange();
|
|
//}
|
|
// For now, don't allow for toggling between insert/overwrite mode - see
|
|
// comment on _OverWrite
|
|
e.Handled = true;
|
|
break;
|
|
case Keys.F5:
|
|
if (e.Shift)
|
|
{
|
|
e.Handled = true;
|
|
ItemInfo myCopyStep = (this.Parent.Parent.Parent as StepTabPanel).MyDisplayTabControl.MyCopyStep;
|
|
if (myCopyStep != null)
|
|
{
|
|
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"));
|
|
}
|
|
}
|
|
//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.Rows.Add(1);
|
|
myGrid.SelectNextCell();
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case Keys.Enter:
|
|
if (!e.Control && !e.Shift && !e.Alt)
|
|
{
|
|
OnEnterKeyPressed(sender, e);
|
|
}
|
|
break;
|
|
case Keys.F2:
|
|
if (e.Alt && !e.Control && !e.Shift) // toggle change bar
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
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 (Text == "" && Parent != null && Parent is VlnFlexGrid)
|
|
{
|
|
//ShowMyParentsFonts();
|
|
SelectionFont = Parent.Font;
|
|
}
|
|
// add the character with its font depending on the char....
|
|
if (!IsControlChar)
|
|
{
|
|
string strpressed = null;
|
|
if (e.KeyChar == '-')
|
|
strpressed = GetAddSymbolText(@"\u8209?");
|
|
else
|
|
strpressed = e.KeyChar.ToString();
|
|
if (e.KeyChar >= ' ')
|
|
{
|
|
LinkLocation ll = FindBetweenLinks();
|
|
if (ll != null && SelectionLength == 0) // SelectionLength = 0 means insert
|
|
{
|
|
if (e.KeyChar == '}')
|
|
strpressed = @"\}";
|
|
else if (e.KeyChar == '{')
|
|
strpressed = @"\{";
|
|
InsertCharBetweenLinks(ll, strpressed); // e.KeyChar);
|
|
e.Handled = true;
|
|
}
|
|
else if (SelectionLength != 0)
|
|
{
|
|
HandleDeleteKeyWithSelectedText(new KeyEventArgs(Keys.None), strpressed);
|
|
e.Handled = true;
|
|
}
|
|
}
|
|
if (!e.Handled)
|
|
{
|
|
if (e.KeyChar == '-')
|
|
AddSymbol(@"\u8209?");
|
|
else if (e.KeyChar == '{')
|
|
AddRtf(@"\{");
|
|
else if (e.KeyChar == '}')
|
|
AddRtf(@"\}");
|
|
else if (e.KeyChar == '\\')
|
|
AddRtf(@"\\");
|
|
else
|
|
return;
|
|
e.Handled = true; // flag that it's been handled, otherwise, will get 2 chars.
|
|
}
|
|
if (e.Handled && SelectionLength != 0) SelectionFont = MyStyleFont.WindowsFont;
|
|
}
|
|
IsControlChar = false;
|
|
}
|
|
}
|
|
private void RtbSendKeys(string keys)
|
|
{
|
|
Focus();
|
|
SendKeys.Send(keys); // With .Net Framework 3.0 this can be replaced with EditingCommands
|
|
// http://msdn.microsoft.com/en-us/library/ms771634.aspx
|
|
}
|
|
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;
|
|
}
|
|
|
|
public string GetPasteText(bool PasteNoReturnsSetting, IDataObject myDO)
|
|
{
|
|
// allowable symbols are those symbols between 127-256 that the proms editor supports that
|
|
// can be pasted from word as is. These symbols are (in the order they are in the following
|
|
// string): degree, plus/minus, exponent 2, exponent 3, micro, quarter, half, divide:
|
|
char[] allowableSymbols = { '\xb0', '\xb1', '\xb2', '\xb3', '\xb5', '\xbc', '\xbd', '\xf7' };
|
|
string ptext = myDO.GetData(DataFormats.Text).ToString();
|
|
ptext = ptext.TrimEnd("\r\n\t ".ToCharArray());
|
|
if (PasteNoReturnsSetting) ptext = ptext.Replace("\r\n", " ");
|
|
StringBuilder sb = new StringBuilder(ptext);
|
|
bool didCharReplace = false;
|
|
for (int i = 0; i < ptext.Length; i++)
|
|
{
|
|
// if allowable, allow for it to pasted. Otherwise, replace that character with a '?'.
|
|
if ((sb[i] > 0x7e))
|
|
if ((ptext.Substring(i, 1).IndexOfAny(allowableSymbols) < 0))
|
|
{
|
|
sb[i] = '?';
|
|
didCharReplace = true;
|
|
}
|
|
}
|
|
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
|
|
if (didCharReplace)
|
|
MessageBox.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()
|
|
{
|
|
//int oldRegexCacheSize = Regex.CacheSize;
|
|
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);
|
|
}
|
|
//Regex.CacheSize = 0;
|
|
GC.Collect(); // there is a memory leak in Regex this fixes it.
|
|
//Regex.CacheSize = oldRegexCacheSize;
|
|
}
|
|
private LinkLocation FindBetweenLinks()
|
|
{
|
|
return FindBetweenLinks(SelectionStart);
|
|
}
|
|
private LinkLocation FindBetweenLinks(int start)
|
|
{
|
|
DebugPrint("FL----------------Between>");
|
|
if (_LinkLocations == null) return null;
|
|
foreach (LinkLocation ll in _LinkLocations)
|
|
if (ll.Start == start && ll.StartsBetween)
|
|
return ll;
|
|
return null;
|
|
}
|
|
private LinkLocation FindLinkLocation()
|
|
{
|
|
return FindLinkLocation(SelectionStart);
|
|
}
|
|
private LinkLocation FindLinkLocation(int sel)
|
|
{
|
|
//DebugPrint("FL----------------Location>");
|
|
if (_LinkLocations == null) return null;
|
|
foreach (LinkLocation ll in _LinkLocations)
|
|
{
|
|
// Moving right:
|
|
// if less than, allows stopping between two links
|
|
if (ll.Start < sel && ll.End > sel)
|
|
{
|
|
DebugPrint("Greater Than {0} {1} {2}", sel, ll.Start, ll.End);
|
|
return ll;
|
|
}
|
|
// if less than or equal, does not stop between two links
|
|
if ((!ll.StartsBetween) && ll.Start <= sel && ll.End > sel)
|
|
{
|
|
DebugPrint("Greater Than or Equal {0} {1} {2}", sel, ll.Start, ll.End);
|
|
return ll;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
public DialogResult ReplaceText(string rpltxt, string fndstr, bool caseSensitive, bool matchWholeWord, bool reverse, bool prompt, IWin32Window fndrpldlg)
|
|
{
|
|
DialogResult dlgrslt = DialogResult.Yes;
|
|
if (SelectionLength > 0)
|
|
{
|
|
if (IsSelectionLinked(SelectionStart, SelectionLength))
|
|
{
|
|
MessageBox.Show(fndrpldlg,"Cannot replace linked text!", "Find/Replace");
|
|
dlgrslt = DialogResult.No;
|
|
}
|
|
else
|
|
{
|
|
if (prompt)
|
|
dlgrslt = MessageBox.Show(fndrpldlg,"Replace This Occurence?", "Replace Text", MessageBoxButtons.YesNoCancel);
|
|
if (dlgrslt == DialogResult.Yes)
|
|
SelectedText = rpltxt;
|
|
}
|
|
}
|
|
return dlgrslt;
|
|
}
|
|
private RichTextBoxFinds _FindOptions = RichTextBoxFinds.None;
|
|
public bool FindText(string str, bool caseSensitive, bool matchWholeWord, bool reverse)
|
|
{
|
|
using (StepRTB savRTF = new StepRTB())
|
|
{
|
|
int startpos = SelectionStart + SelectionLength;
|
|
savRTF.Text = this.Text;
|
|
|
|
_FindOptions = RichTextBoxFinds.None;
|
|
if (caseSensitive)
|
|
_FindOptions |= RichTextBoxFinds.MatchCase;
|
|
if (matchWholeWord)
|
|
_FindOptions |= RichTextBoxFinds.WholeWord;
|
|
if (reverse)
|
|
{
|
|
_FindOptions |= RichTextBoxFinds.Reverse;
|
|
savRTF.Text = this.Text.Substring(0, SelectionStart);
|
|
startpos = savRTF.Text.Length;
|
|
if (startpos == 0)
|
|
return false; // at beginning of rtfbox during a reverse find
|
|
}
|
|
else
|
|
{
|
|
if (startpos >= savRTF.Text.Length)
|
|
return false; // at end of rtfbox during a forward find
|
|
}
|
|
// look for the find string in the temporary rtfbox
|
|
// then set the cursor selection in the real rtfbox
|
|
bool keepgoing = true;
|
|
while (keepgoing)
|
|
{
|
|
int pos = savRTF.Find(str, startpos, _FindOptions);
|
|
keepgoing = false;
|
|
if (pos >= 0)
|
|
{
|
|
if (this.SkipLinkInfo(pos, str.Length))
|
|
{
|
|
if (reverse)
|
|
{
|
|
startpos--;
|
|
savRTF.Text = savRTF.Text.Substring(0, startpos);
|
|
}
|
|
else
|
|
startpos++;
|
|
if (startpos > 0 && startpos < savRTF.Text.Length)
|
|
keepgoing = true;
|
|
}
|
|
else
|
|
{
|
|
SelectionStart = pos;
|
|
SelectionLength = str.Length;
|
|
}
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
private int FindStart()
|
|
{
|
|
foreach (LinkLocation ll in _LinkLocations)
|
|
{
|
|
if (SelectionStart == ll.End) return ll.Start;
|
|
if (SelectionStart == ll.Start)
|
|
{
|
|
if (ll.Start == 7) return 7;
|
|
return ll.Start - 8;
|
|
}
|
|
}
|
|
if (SelectionStart > 0) return SelectionStart - 1;
|
|
return 0;
|
|
}
|
|
private int FindEnd()
|
|
{
|
|
foreach (LinkLocation ll in _LinkLocations)
|
|
{
|
|
if (SelectionStart + SelectionLength + 7 == ll.Start) return ll.Length + 7;
|
|
// this is for in-between links
|
|
if (SelectionStart + SelectionLength == ll.Start) return ll.Length;
|
|
}
|
|
if (SelectionStart + SelectionLength < TextLength) return 1;
|
|
return 0;
|
|
}
|
|
private int FindEndDown()
|
|
{
|
|
foreach (LinkLocation ll in _LinkLocations)
|
|
{
|
|
if (SelectionStart + SelectionLength >= ll.Start && SelectionStart + SelectionLength <= ll.End) return ll.End;
|
|
}
|
|
return 0;
|
|
}
|
|
// 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 bare the same instance of the dictionary.
|
|
// This allow all the StepRTB's to automatically update when a new word is added.
|
|
private static C1.Win.C1SpellChecker.C1SpellChecker _C1SpellChecker2;
|
|
|
|
private static C1.Win.C1SpellChecker.C1SpellChecker C1SpellChecker2
|
|
{
|
|
get
|
|
{
|
|
if (_C1SpellChecker2 == null)
|
|
{
|
|
_C1SpellChecker2 = new C1.Win.C1SpellChecker.C1SpellChecker();
|
|
_C1SpellChecker2.ContextMenuCreated += new C1.Win.C1SpellChecker.ContextMenuEventHandler(_C1SpellChecker2_ContextMenuCreated);
|
|
// The veproms.dct file is the main spell checker dictionary.
|
|
// We edited the C1 dictionary (C:\Program Files\ComponentOne\Dictionaries\C1Spell_en-US.dct) using ComponentOne's
|
|
// dictionary editor (C:\Program Files\ComponentOne\Studio for WinForms\C1SpellChecker\C1DictionaryEditor.exe)
|
|
// and added the veproms.words list as another word list in the dictionary. We saved the resulting file as veproms.dct.
|
|
string dictpath = string.Format(@"{0}\veproms.dct", Application.StartupPath);
|
|
|
|
// Only use the veproms.dct if it is found in the BIN folder. Otherwise, let it default to use the standard dictionary.
|
|
if (File.Exists(dictpath))
|
|
_C1SpellChecker2.MainDictionary.FileName = dictpath; // looks in the bin folder by default
|
|
|
|
// NOTE: By default, a "Custom.dct" file (UserDictionary) will be created in the BIN folder when a user adds words to the
|
|
// spell checker dictionary. The words that the user adds are not placed in the Volian.dct file.
|
|
//_C1SpellChecker2.UserDictionary.FileName = @"C:\Development\proms\VEPROMS User Interface\bin\Debug\MYDictionary.dct";
|
|
}
|
|
return StepRTB._C1SpellChecker2;
|
|
}
|
|
}
|
|
|
|
// the grid uses this to reference the same instance of the spell checker
|
|
public C1.Win.C1SpellChecker.C1SpellChecker SpellCheckerInstance
|
|
{
|
|
get { return C1SpellChecker2; }
|
|
}
|
|
|
|
// Get or Save our context menu
|
|
// This is added to the the spell checker's context menu for a mis-spelled word
|
|
private static ContextMenuStrip _ThisContextMenuStrip;
|
|
public ContextMenuStrip ThisContextMenuStrip
|
|
{
|
|
get { return _ThisContextMenuStrip; }
|
|
set { _ThisContextMenuStrip = value; }
|
|
}
|
|
|
|
private static StepRTB _ContextMenuStepRTB;
|
|
private static object _ContextMenuStrip;
|
|
|
|
static void _C1SpellChecker2_ContextMenuCreated(object sender, C1.Win.C1SpellChecker.ContextMenuEventArgs e)
|
|
{
|
|
// Adjust their bad word context menu
|
|
//Console.WriteLine("==========> spell check context menu {0}",e.Menu.Items[0].Text);
|
|
if (e.Menu.Equals(_ContextMenuStrip))
|
|
{
|
|
// Add an item for our "Edit Menu" context menu on their spell check context menu
|
|
// This gives the user access to our regular context menu when on a mis-spelled word
|
|
ToolStripItem tsi = e.Menu.Items.Add("Edit Menu");
|
|
tsi.Click += new EventHandler(tsi_Click);
|
|
//Now replace their "Spell" item with ours, so that we can display our custom spell check dialog
|
|
for (int i = 0; i < e.Menu.Items.Count; i++)
|
|
{
|
|
ToolStripItem tsi1 = e.Menu.Items[i];
|
|
if (tsi1 is ToolStripMenuItem && tsi1.Text == "Spell")
|
|
{
|
|
e.Menu.Items.RemoveAt(i); // remove their spell check dialog item
|
|
ToolStripMenuItem tsi2 = new ToolStripMenuItem("Spell");
|
|
tsi2.Click += new EventHandler(tsi2_Click);
|
|
e.Menu.Items.Insert(i, tsi2); // add our spell check dialog item
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void tsi2_Click(object sender, EventArgs e)
|
|
{
|
|
C1SpellChecker2.CheckControl(_ContextMenuStepRTB, true, MySpellCheckDlg);
|
|
}
|
|
|
|
// Click event to display our "Edit Menu" (StepRTB context menu)
|
|
static void tsi_Click(object sender, EventArgs e)
|
|
{
|
|
ToolStripMenuItem tsmi = sender as ToolStripMenuItem;
|
|
//_ContextMenuStepRTB.MyRTBItem.MyStepPanel.MyStepTabPanel.MyStepTabRibbon.OpenContextMenu(tsmi.Owner.Location);
|
|
_ContextMenuStepRTB.OnOpenContextMenu(sender, new StepRTBLocationEventArgs(tsmi.Owner.Location));
|
|
}
|
|
|
|
// This is our customized Spell Check dialog
|
|
// This is display when the use clicks the Spell button from the Ribbon
|
|
// or when the "Spell" item is selected from the context menu when on a mis-spelled word
|
|
static VlnSpellCheckDlg _MySpellCheckDlg;
|
|
public static VlnSpellCheckDlg MySpellCheckDlg
|
|
{
|
|
get
|
|
{
|
|
if (_MySpellCheckDlg == null)
|
|
_MySpellCheckDlg = new VlnSpellCheckDlg();
|
|
return _MySpellCheckDlg;
|
|
}
|
|
}
|
|
|
|
// This is used when walking through the section doing a spell check
|
|
// (from the Spell button on the ribbon)
|
|
public bool SpellCheckNext()
|
|
{
|
|
int nBad = C1SpellChecker2.CheckControl(this, false, MySpellCheckDlg);
|
|
return (nBad >= 0); // nBad = -1 means user pressed Cancel button
|
|
}
|
|
|
|
// This allows us to turn off/on the specll check context menu when we toggle in and out of View Mode.
|
|
// see btnToggleEditView_Click() in StepTabRibbon.cs
|
|
public void SpellCheckContextMenuOn(bool turnOnMenu)
|
|
{
|
|
C1SpellChecker2.Options.ShowSuggestionsInContextMenu = turnOnMenu;
|
|
}
|
|
#endregion
|
|
#region
|
|
public string DoNewLinkInGridCell()
|
|
{
|
|
// first find the new link and determine whether it's RO or transition.
|
|
int indx = Rtf.IndexOf(@"#Link:ReferencedObject:<NewID>");
|
|
if (indx > 0)
|
|
{
|
|
Match mro = Regex.Match(Rtf.Substring(indx, Rtf.Length - indx), @"([A-Za-z]*):(.*?)\[END>");
|
|
string linkstr = mro.Groups[2].Value;
|
|
string[] roparts = linkstr.Split(" ".ToCharArray());
|
|
ContentRoUsage rousg = null;
|
|
int oldid = -1;
|
|
using (Item itm = MyItemInfo.Get())
|
|
{
|
|
using (RODb rodb = RODb.GetJustRoDb(Convert.ToInt32(roparts[2])))
|
|
{
|
|
rousg = itm.MyContent.ContentRoUsages.Add(roparts[1], rodb);
|
|
}
|
|
//get temporary rousageid
|
|
oldid = rousg.ROUsageID;
|
|
Rtf = Rtf.Replace("<NewID>", string.Format("<CROUSGID={0}>", rousg.ROUsageID));
|
|
//save temporary rousageid to get real rousageid
|
|
itm.Save();
|
|
//replace temprorary rousageid with real rousageid
|
|
Rtf = Rtf.Replace(string.Format("<CROUSGID={0}>", oldid), rousg.ROUsageID.ToString());
|
|
//save real rousageid
|
|
itm.Save();
|
|
MyItemInfo.MyContent.RefreshContentRoUsages();
|
|
}
|
|
}
|
|
// Need to look for any 'New' transitions, don't include existing ones.
|
|
Match mt = Regex.Match(Rtf, @"#Link:Transition:([0-9]+) <NewID> ");
|
|
if (mt.Length <= 0) mt = Regex.Match(Rtf, @"#Link:TransitionRange:([0-9]+) <NewID> ");
|
|
if (mt.Length > 0)
|
|
{
|
|
indx = mt.Index+6; // get past '#Link:"
|
|
Match m = Regex.Match(Rtf.Substring(indx, Rtf.Length - indx), @"([A-Za-z]*):(.*?)\[END>");
|
|
bool isSingleTran = true;
|
|
if (Rtf.Substring(indx, 16).IndexOf("TransitionRange") >= 0) isSingleTran = false;
|
|
string linkstr = m.Groups[2].Value;
|
|
string[] tparts = linkstr.Split(" ".ToCharArray());
|
|
int type = System.Convert.ToInt32(tparts[0]);
|
|
int tr1 = System.Convert.ToInt32(tparts[2]); // tparts[2] is token for tranid
|
|
int tr2 = tr1;
|
|
if (tparts.Length > 3)
|
|
tr2 = System.Convert.ToInt32(tparts[3]); // tparts[3] is token for rangeid
|
|
bool dispose1 = false;
|
|
Item itm1 = null;
|
|
bool dispose2 = false;
|
|
Item itm2 = null;
|
|
using (Item itm = MyItemInfo.Get())
|
|
{
|
|
if (itm.ItemID == tr1)
|
|
itm1 = itm; // a transition that points to itself should not dispose
|
|
else
|
|
{
|
|
dispose1 = true;
|
|
itm1 = Item.Get(tr1);
|
|
}
|
|
if (itm.ItemID == tr2)
|
|
itm2 = itm; // a transition that points to itself should not dispose
|
|
else if (tr1 == tr2)
|
|
itm2 = itm1; // if both destinations are the same only dispose the first one
|
|
else
|
|
{
|
|
dispose2 = true;
|
|
itm2 = Item.Get(tr2);
|
|
}
|
|
ContentTransition ct = itm.MyContent.ContentTransitions.Add(itm1, itm2);
|
|
//Console.WriteLine("CT {0},{1},{2},{3}", ct.TransitionID, itm.ItemID, itm.MyContent.MyContentUnique, itm.MyContent.ContentTransitions.Count);
|
|
ct.TranType = type;
|
|
if (isSingleTran)
|
|
ct.IsRange = 0;
|
|
else if (tr1 != tr2)
|
|
ct.IsRange = 1;
|
|
else
|
|
ct.IsRange = 2;
|
|
|
|
int oldidt = ct.TransitionID;
|
|
Rtf = Rtf.Replace("<NewID>", string.Format("<CTID={0}>", ct.TransitionID));
|
|
itm.Save();
|
|
Rtf = Rtf.Replace(string.Format("<CTID={0}>", oldidt), ct.TransitionID.ToString());
|
|
itm.Save();
|
|
MyItemInfo.MyContent.RefreshContentTransitions();
|
|
}
|
|
|
|
if (dispose2) itm2.Dispose();
|
|
if (dispose1) itm1.Dispose();
|
|
}
|
|
return Rtf;
|
|
}
|
|
#endregion
|
|
#region RoInsertInterface
|
|
public void UpdateStepRtb(string linktxt, string valtxt)
|
|
{
|
|
int ss = SelectionStart; // Remember where the link is being added
|
|
int sl = SelectionLength;
|
|
OnReturnToEditor(this, new EventArgs());
|
|
Select(ss, sl);
|
|
InsertRO(valtxt, linktxt); // Insert the LINK
|
|
OnDoSaveContents(this, new EventArgs()); // .SaveText(); // Save the text with the LINK - This also moves the cursor to the end of the text
|
|
// By selecting a starting position within a link, StepRTB (HandleSelectionChange) will select the link
|
|
Select(ss + 7 + valtxt.Length, 0);// Select the link, Try 7 for "<Start]" plus the length of the value
|
|
//Console.WriteLine("'{0}'",MyRTB.Text.Substring(MyRTB.SelectionStart,MyRTB.SelectionLength));
|
|
string linkText = Text.Substring(SelectionStart, SelectionLength);
|
|
if (_MyLog.IsInfoEnabled && (linkText.Contains("NewID") || linkText.Contains("CROUSGID")))
|
|
_MyLog.InfoFormat("ItemID {0}, LinkText '{1}'", MyItemInfo.ItemID, linkText);
|
|
int sel = SelectionStart + SelectionLength;
|
|
Select(sel, 0);// Move cursor to end of LINK
|
|
Focus();
|
|
}
|
|
#endregion
|
|
#region Debug
|
|
private bool _ShowDebug = false;
|
|
public bool ShowDebug
|
|
{
|
|
get { return _ShowDebug; }
|
|
set { _ShowDebug = value; }
|
|
}
|
|
private void DebugPrint(string where, string format, params object[] myParams)
|
|
{
|
|
DebugPrint(where + string.Format(format, myParams));
|
|
}
|
|
private void DebugPrint(string format, params object[] myParams)
|
|
{
|
|
if (_ShowDebug)
|
|
Console.WriteLine(format, myParams);
|
|
}
|
|
private void DebugSelection(string where)
|
|
{
|
|
DebugPrint(where, ": {0} {1} '{2}'", SelectionStart, SelectionLength, SelectedText);
|
|
}
|
|
#endregion
|
|
private bool _LastWasLeftArrow = false;
|
|
private void StepRTB_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
|
|
{
|
|
if ((e.KeyCode == Keys.Tab) && (!e.Alt && !e.Control))
|
|
e.IsInputKey = true;
|
|
// Remember if the last key pressed was a left arrow. This is used in HandleSelectionChanged
|
|
// When a Link overlaps the beginning of a line. Normally a left arrow will move the cursor
|
|
// back one character, or if a Link is selected, it will move the cursor to the space before
|
|
// the link. Since the Link overlaps the line, special consideration must be given to assure
|
|
// that the cursor goes to the proper place.
|
|
_LastWasLeftArrow = (!e.Shift && !e.Control && !e.Alt && e.KeyCode == Keys.Left);
|
|
}
|
|
}
|
|
public partial class StepRTBModeChangeEventArgs : EventArgs
|
|
{
|
|
private E_ViewMode _ViewMode;
|
|
public E_ViewMode ViewMode
|
|
{
|
|
get { return _ViewMode; }
|
|
set { _ViewMode = value; }
|
|
}
|
|
public StepRTBModeChangeEventArgs(E_ViewMode vmode)
|
|
{
|
|
_ViewMode = vmode;
|
|
}
|
|
}
|
|
public partial class StepRTBMenuEventArgs
|
|
{
|
|
private string _MenuGroup;
|
|
public string MenuGroup
|
|
{
|
|
get { return _MenuGroup; }
|
|
set { _MenuGroup = value; }
|
|
}
|
|
public StepRTBMenuEventArgs(string menuGroup)
|
|
{
|
|
_MenuGroup = menuGroup;
|
|
}
|
|
}
|
|
public partial class StepRTBTableWidthEventArgs
|
|
{
|
|
bool _EditMode;
|
|
public bool EditMode
|
|
{
|
|
get { return _EditMode; }
|
|
set { _EditMode = value; }
|
|
}
|
|
public StepRTBTableWidthEventArgs(bool editMode)
|
|
{
|
|
_EditMode = editMode;
|
|
}
|
|
}
|
|
public class StepRTBCursorMovementEventArgs
|
|
{
|
|
private Point _CursorLocation;
|
|
public Point CursorLocation
|
|
{
|
|
get { return _CursorLocation; }
|
|
set { _CursorLocation = value; }
|
|
}
|
|
private E_ArrowKeys _Key;
|
|
public E_ArrowKeys Key
|
|
{
|
|
get { return _Key; }
|
|
set { _Key = value; }
|
|
}
|
|
public StepRTBCursorMovementEventArgs(Point pt, E_ArrowKeys key)
|
|
{
|
|
_CursorLocation = pt;
|
|
_Key = key;
|
|
}
|
|
}
|
|
public class StepRTBLocationEventArgs:EventArgs
|
|
{
|
|
private Point _Location;
|
|
public Point Location
|
|
{
|
|
get { return _Location; }
|
|
set { _Location = value; }
|
|
}
|
|
public StepRTBLocationEventArgs(Point location)
|
|
{
|
|
_Location = location;
|
|
}
|
|
}
|
|
public partial class StepRTBRoEventArgs : EventArgs
|
|
{
|
|
private string _ValText;
|
|
public string ValText
|
|
{
|
|
get { return _ValText; }
|
|
set { _ValText = value; }
|
|
}
|
|
private string _RawValText;
|
|
public string RawValText
|
|
{
|
|
get { return _RawValText; }
|
|
set { _RawValText = value; }
|
|
}
|
|
private string _LinkText;
|
|
public string LinkText
|
|
{
|
|
get { return _LinkText; }
|
|
set { _LinkText = value; }
|
|
}
|
|
private string _ROID;
|
|
public string ROID
|
|
{
|
|
get { return _ROID; }
|
|
set { _ROID = value; }
|
|
}
|
|
private int _RODbID;
|
|
public int RODbID
|
|
{
|
|
get { return _RODbID; }
|
|
set { _RODbID = value; }
|
|
}
|
|
public StepRTBRoEventArgs(string valtext, string rawvaltext, string linktext, string roid, int rodbid)
|
|
{
|
|
_ValText = valtext;
|
|
_RawValText = rawvaltext;
|
|
_LinkText = linktext;
|
|
_ROID = roid;
|
|
_RODbID = rodbid;
|
|
}
|
|
}
|
|
#region LinkLocation Class
|
|
public class LinkLocation
|
|
{
|
|
private int _Start;
|
|
public int Start
|
|
{
|
|
get { return _Start; }
|
|
set { _Start = value; }
|
|
}
|
|
private int _Length;
|
|
public int Length
|
|
{
|
|
get { return _Length; }
|
|
set { _Length = value; }
|
|
}
|
|
public int End
|
|
{
|
|
get { return _Length + _Start; }
|
|
}
|
|
private int _StartRtf;
|
|
public int StartRtf
|
|
{
|
|
get { return _StartRtf; }
|
|
set { _StartRtf = value; }
|
|
}
|
|
private int _LengthRtf;
|
|
public int LengthRtf
|
|
{
|
|
get { return _LengthRtf; }
|
|
set { _LengthRtf = value; }
|
|
}
|
|
public int EndRtf
|
|
{
|
|
get { return _LengthRtf + _StartRtf; }
|
|
}
|
|
private string _Text;
|
|
public string Text
|
|
{
|
|
get { return _Text; }
|
|
set { _Text = value; }
|
|
}
|
|
private LinkLocation _PreviousLink = null;
|
|
public LinkLocation PreviousLink
|
|
{
|
|
get { return _PreviousLink; }
|
|
set
|
|
{
|
|
_PreviousLink = value;
|
|
value.NextLink = this;
|
|
}
|
|
}
|
|
private LinkLocation _NextLink = null;
|
|
public LinkLocation NextLink
|
|
{
|
|
get { return _NextLink; }
|
|
set { _NextLink = value; }
|
|
}
|
|
public int PreviousEnd
|
|
{
|
|
get { return PreviousLink == null ? -1 : PreviousLink.End; }
|
|
}
|
|
public bool StartsBetween
|
|
{
|
|
get { return PreviousEnd == Start; }
|
|
}
|
|
public int NextStart
|
|
{
|
|
get { return NextLink == null ? -1 : NextLink.Start; }
|
|
}
|
|
public bool EndsBetween
|
|
{
|
|
get { return NextStart == End; }
|
|
}
|
|
public LinkLocation(int start, int length, string text, int startRtf, int lengthRtf, LinkLocation previousLink)
|
|
{
|
|
_Start = start;
|
|
_Length = length;
|
|
_Text = text;
|
|
_StartRtf = startRtf;
|
|
_LengthRtf = lengthRtf;
|
|
if (previousLink != null) PreviousLink = previousLink;
|
|
}
|
|
public override string ToString()
|
|
{
|
|
return (string.Format("{0}, {1}", Start, End));
|
|
}
|
|
public void Show(string str)
|
|
{
|
|
if (PreviousLink != null)
|
|
Console.WriteLine("LinkLocation: {0}.PreviousLink {1}", str, PreviousLink);
|
|
Console.WriteLine("LinkLocation: {0} {1}", str, this);
|
|
if (NextLink != null)
|
|
Console.WriteLine("LinkLocation: {0}.NextLink {1}", str, NextLink);
|
|
}
|
|
// #region ClipboardHandler
|
|
// private const int WM_CUT = 0x0300;
|
|
// private const int WM_COPY = 0x0301;
|
|
// private const int WM_PASTE = 0x0302;
|
|
|
|
// public delegate void ClipboardEventHandler(object sender, ClipboardEventArgs e);
|
|
|
|
// [Category("Clipboard")]
|
|
// public event ClipboardEventHandler CutText;
|
|
// [Category("Clipboard")]
|
|
// public event ClipboardEventHandler CopiedText;
|
|
// [Category("Clipboard")]
|
|
// public event ClipboardEventHandler PastedText;
|
|
|
|
// protected override void WndProc(ref Message m)
|
|
// {
|
|
// if (m.Msg == WM_CUT)
|
|
// {
|
|
// if (CutText != null)
|
|
// CutText(this, new ClipboardEventArgs(this.SelectedText));
|
|
// }
|
|
// else if (m.Msg == WM_COPY)
|
|
// {
|
|
// if (CopiedText != null)
|
|
// CopiedText(this, new ClipboardEventArgs(this.SelectedText));
|
|
// }
|
|
// else if (m.Msg == WM_PASTE)
|
|
// {
|
|
// if (PastedText != null)
|
|
// PastedText(this, new ClipboardEventArgs(Clipboard.GetText()));
|
|
// }
|
|
|
|
// base.WndProc(ref m);
|
|
// }
|
|
//}
|
|
|
|
//public class ClipboardEventArgs : EventArgs
|
|
//{
|
|
// private string clipboardText;
|
|
// public string ClipboardText
|
|
// {
|
|
// get
|
|
// {
|
|
// return clipboardText;
|
|
// }
|
|
|
|
// set
|
|
// {
|
|
// clipboardText = value;
|
|
// }
|
|
// }
|
|
|
|
// public ClipboardEventArgs(string clipboardText)
|
|
// {
|
|
// this.clipboardText = clipboardText;
|
|
// }
|
|
// #endregion
|
|
|
|
}
|
|
#endregion
|
|
}
|