
Fixed Find and Replace logic to keep it from getting into an infinite loop Used new CSLA code to hanndle deletion of procedures with external transitions New Enhanced Document properties
3594 lines
123 KiB
C#
3594 lines
123 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.IO;
|
|
using System.Drawing;
|
|
using System.Data;
|
|
using System.Text;
|
|
using System.Windows.Forms;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text.RegularExpressions;
|
|
using VEPROMS.CSLA.Library;
|
|
using Volian.Base.Library;
|
|
|
|
namespace Volian.Controls.Library
|
|
{
|
|
public delegate void StepRTBEvent(object sender, EventArgs args);
|
|
public delegate void StepRTBCursorKeysEvent(object sender, KeyEventArgs args);
|
|
public delegate void StepRTBCursorMovementEvent(object sender, StepRTBCursorMovementEventArgs args);
|
|
public delegate void StepRTBModeChangeEvent(object sender, StepRTBModeChangeEventArgs args);
|
|
public delegate void StepRTBMenuEvent(object sender, StepRTBMenuEventArgs args);
|
|
public delegate void StepRTBTableWidthEvent(object sender, StepRTBTableWidthEventArgs args);
|
|
public delegate bool StepRTBBooleanEvent(object sender, EventArgs args);
|
|
public delegate void StepRTBLocationEvent(object sender, StepRTBLocationEventArgs args);
|
|
public delegate void StepRTBMouseEvent(object sender, MouseEventArgs args);
|
|
public delegate void StepRTBRoEvent(object sender, StepRTBRoEventArgs args);
|
|
//public delegate void StepRTBMouseWheelEvent(object sender, MouseEventArgs args);
|
|
public partial class StepRTB : RichTextBox // , IStepRTB
|
|
{
|
|
private static readonly log4net.ILog _MyLog = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
|
|
|
private bool _Disposed = false;
|
|
private static int _CountCreated = 0;
|
|
private static int _CountDisposed = 0;
|
|
private static int _CountFinalized = 0;
|
|
private static int IncrementCountCreated
|
|
{ get { return ++_CountCreated; } }
|
|
private int _CountWhenCreated = IncrementCountCreated;
|
|
public static int CountCreated
|
|
{ get { return _CountCreated; } }
|
|
public static int CountNotDisposed
|
|
{ get { return _CountCreated - _CountDisposed; } }
|
|
public static int CountNotFinalized
|
|
{ get { return _CountCreated - _CountFinalized; } }
|
|
private bool _Finalized = false;
|
|
~StepRTB()
|
|
{
|
|
if (!_Finalized) _CountFinalized++;
|
|
_Finalized = true;
|
|
}
|
|
#region Events
|
|
public event StepRTBRoEvent RoInsert;
|
|
public void OnRoInsert(object sender, StepRTBRoEventArgs args)
|
|
{
|
|
if (RoInsert != null) RoInsert(sender, args);
|
|
}
|
|
public event StepRTBEvent ReturnToEditor;
|
|
public void OnReturnToEditor(object sender, EventArgs args)
|
|
{
|
|
if (ReturnToEditor != null) ReturnToEditor(sender, args);
|
|
}
|
|
public event StepRTBEvent EditModeChanged;
|
|
public void OnEditModeChanged(object sender, EventArgs args)
|
|
{
|
|
if (EditModeChanged != null) EditModeChanged(sender, args);
|
|
}
|
|
public event StepRTBEvent DoSaveContents;
|
|
public void OnDoSaveContents(object sender, EventArgs args)
|
|
{
|
|
if (DoSaveContents != null) DoSaveContents(sender, args);
|
|
}
|
|
public event StepRTBMouseEvent DoMouseWheel;
|
|
public void OnDoMouseWheel(object sender, MouseEventArgs args)
|
|
{
|
|
if (DoMouseWheel != null) DoMouseWheel(sender, args);
|
|
}
|
|
public event StepRTBLocationEvent OpenContextMenu;
|
|
public void OnOpenContextMenu(object sender, StepRTBLocationEventArgs args)
|
|
{
|
|
if (OpenContextMenu != null) OpenContextMenu(sender, args);
|
|
}
|
|
public event StepRTBEvent CopyStep;
|
|
public void OnCopyStep(object sender, EventArgs args)
|
|
{
|
|
if (CopyStep != null) CopyStep(sender, args);
|
|
}
|
|
public event StepRTBBooleanEvent CheckClipboard;
|
|
public bool OnCheckClipboard(object sender, EventArgs args)
|
|
{
|
|
if (CheckClipboard != null) return CheckClipboard(sender, args);
|
|
return false;
|
|
}
|
|
public event StepRTBCursorKeysEvent EnterKeyPressed;
|
|
public void OnEnterKeyPressed(object sender, KeyEventArgs args)
|
|
{
|
|
if (EnterKeyPressed != null) EnterKeyPressed(sender, args);
|
|
}
|
|
public event StepRTBEvent InsertPgBrk;
|
|
public void OnInsertPgBrk(object sender, EventArgs args)
|
|
{
|
|
if (InsertPgBrk != null) InsertPgBrk(sender, args);
|
|
}
|
|
public event StepRTBEvent OpenAnnotations;
|
|
public void OnOpenAnnotations(object sender, EventArgs args)
|
|
{
|
|
if (OpenAnnotations != null) OpenAnnotations(sender, args);
|
|
}
|
|
public event StepRTBBooleanEvent IsNotCurrentSelection;
|
|
public bool OnIsNotCurrentSelection(object sender, EventArgs args)
|
|
{
|
|
if (IsNotCurrentSelection != null) return IsNotCurrentSelection(sender, args);
|
|
return false;
|
|
}
|
|
public event StepRTBTableWidthEvent AdjustTableWidth;
|
|
public void OnAdjustTableWidth(object sender, StepRTBTableWidthEventArgs args)
|
|
{
|
|
if (AdjustTableWidth != null) AdjustTableWidth(sender, args);
|
|
}
|
|
public event StepRTBMenuEvent SetMenu;
|
|
private void OnSetMenu(object sender, StepRTBMenuEventArgs args)
|
|
{
|
|
if (SetMenu != null) SetMenu(sender, args);
|
|
}
|
|
public event StepRTBEvent RTBSelectionChanged;
|
|
private void OnRTBSelectionChanged(object sender, EventArgs args)
|
|
{
|
|
if (RTBSelectionChanged != null) RTBSelectionChanged(sender, args);
|
|
}
|
|
public event StepRTBEvent LinkLocationsChanged;
|
|
private void OnLinkLocationChanged(object sender, EventArgs args)
|
|
{
|
|
if (LinkLocationsChanged != null) LinkLocationsChanged(sender, args);
|
|
}
|
|
public event StepRTBEvent RTBRangeStatusChanged;
|
|
private void OnRTBRangeStatusChanged(object sender, EventArgs args)
|
|
{
|
|
if (RTBRangeStatusChanged != null) RTBRangeStatusChanged(sender, args);
|
|
}
|
|
public event StepRTBCursorKeysEvent CursorKeyPress;
|
|
private void OnCursorKeyPress(object sender, KeyEventArgs args)
|
|
{
|
|
if (CursorKeyPress != null) CursorKeyPress(sender, args);
|
|
}
|
|
public event StepRTBCursorMovementEvent CursorMovement;
|
|
private void OnCursorMovement(object sender, StepRTBCursorMovementEventArgs args)
|
|
{
|
|
if (CursorMovement != null) CursorMovement(sender, args);
|
|
}
|
|
//public event StepRTBModeChangeEvent ModeChange;
|
|
//private void OnModeChange(object sender, StepRTBModeChangeEventArgs args)
|
|
//{
|
|
// //_MyModeChangeEventArgs = args;
|
|
// if (ModeChange != null) ModeChange(sender, args);
|
|
// else MessageBox.Show("StepRTB - no mode change defined");
|
|
//}
|
|
//public event StepRTBMouseWheelEvent MouseWheel;
|
|
//private void OnMouseWheel(object sender, MouseEventArgs args)
|
|
//{
|
|
// if (MouseWheel != null) MouseWheel(sender, args);
|
|
//}
|
|
|
|
/// <summary>
|
|
/// This event is not raised during all the in-between changes for link deletions
|
|
/// </summary>
|
|
public event StepRTBEvent RTBTextChanged;
|
|
private void OnRTBTextChanged(object sender, EventArgs args)
|
|
{
|
|
if (RTBTextChanged != null) RTBTextChanged(sender, args);
|
|
}
|
|
#endregion
|
|
#region Properties and Variables
|
|
|
|
public bool IsRoTable
|
|
{
|
|
get { return (Parent is VlnFlexGrid && (Parent as VlnFlexGrid).IsRoTable); }
|
|
}
|
|
public bool HasVScroll
|
|
{
|
|
get
|
|
{
|
|
return RTBAPI.HasVertScroll(this);
|
|
}
|
|
|
|
}
|
|
public bool HasHScroll
|
|
{
|
|
get
|
|
{
|
|
return RTBAPI.HasHorzScroll(this);
|
|
}
|
|
|
|
}
|
|
private bool _EditMode = true;
|
|
/// <summary>
|
|
/// Allows insert of links. If false, don't allow selection of links.
|
|
/// </summary>
|
|
public bool EditMode
|
|
{
|
|
get { return _EditMode; }
|
|
set
|
|
{
|
|
_EditMode = value;
|
|
OnEditModeChanged(this, new EventArgs());
|
|
}
|
|
}
|
|
private static string _MySymbolFontName;
|
|
public static string MySymbolFontName
|
|
{
|
|
get { return StepRTB._MySymbolFontName; }
|
|
set { StepRTB._MySymbolFontName = value; }
|
|
}
|
|
private static FontFamily _MyFontFamily = null;
|
|
public static FontFamily MyFontFamily
|
|
{
|
|
get { return StepRTB._MyFontFamily; }
|
|
set
|
|
{
|
|
_MyFontFamily = value;
|
|
if (value != null)
|
|
{
|
|
Font font;
|
|
if (value.IsStyleAvailable(FontStyle.Regular))
|
|
font = new Font(value, 10);
|
|
else if (value.IsStyleAvailable(FontStyle.Bold))
|
|
font = new Font(value, 10, FontStyle.Bold);
|
|
else // (value.IsStyleAvailable(FontStyle.Italic))
|
|
font = new Font(value, 10, FontStyle.Italic);
|
|
using (StepRTB srtb = new StepRTB())
|
|
{
|
|
if (srtb.FontIsFixed(font)) MySymbolFontName = "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)
|
|
{
|
|
_MouseDown = true;
|
|
//Console.WriteLine("vvvvvvvvvv StepRTB Mouse Down id= {0}",MyItemInfo.ItemID);
|
|
bool inPsi = this.Parent.FindForm().Name.Contains("frmPSI");
|
|
if (!_ContextMenuStripChanged)
|
|
OnSetMenu(this, new StepRTBMenuEventArgs(inPsi?"PSI":"OpenContextMenu"));
|
|
_ContextMenuStripChanged = false;
|
|
CorrectSelectionAtEndOfLine();
|
|
}
|
|
void StepRTB_MouseUp(object sender, MouseEventArgs e)
|
|
{
|
|
_MouseDown = false;
|
|
//Console.WriteLine("^^^^^^^^^^ StepRTB Mouse Up id= {0}", MyItemInfo.ItemID);
|
|
|
|
if(this.Focused) // Only HandleSelectionChange if this control has focus.
|
|
{
|
|
HandleSelectionChange();
|
|
// save our context menu to add to the spell checker's context menu
|
|
ThisContextMenuStrip = this.ContextMenuStrip;
|
|
}
|
|
}
|
|
#endregion
|
|
#region ApplicationSupport
|
|
// Used in StepTabRibbon:
|
|
//public void ToggleEditView(E_ViewMode vwMode)
|
|
//{
|
|
// OnDoSaveContents(this, new EventArgs()); // SaveText();
|
|
// //ItemInfo tmp = MyItemInfo;
|
|
// //MyItemInfo = null;
|
|
// //ReadOnly = !ReadOnly;
|
|
// //EpMode = ReadOnly ? E_EditPrintMode.Print : E_EditPrintMode.Edit;
|
|
// VwMode = vwMode;
|
|
// ReadOnly = VwMode == E_ViewMode.View;
|
|
// ViewRTB = ReadOnly;
|
|
// Clear();
|
|
// RefreshDisplay(!ViewRTB);
|
|
// //MyItemInfo = tmp;
|
|
// SelectionStart = 0;
|
|
// SelectionLength = 0;
|
|
// //OnModeChange(this, new StepRTBModeChangeEventArgs(ViewRTB?E_ViewMode.View:E_ViewMode.Edit));
|
|
//}
|
|
public void InsertRO(string value, string link)
|
|
{
|
|
AddRtfLink(value, link);
|
|
}
|
|
public void InsertTran(string value, string link)
|
|
{
|
|
AddRtfLink(value, link);
|
|
}
|
|
public void InsertSymbol(int symbcode)
|
|
{
|
|
string sym = string.Format(symbcode < 256 ? "\'{0:X2}" : @"\u{0}", symbcode);
|
|
if (symbcode < 256)
|
|
AddText(((char)symbcode).ToString());
|
|
else
|
|
AddSymbol(sym); // Adds font commands around symbol, needed for higher codes
|
|
}
|
|
public void InsertSymbol(string symbol)
|
|
{
|
|
AddSymbol(symbol);
|
|
}
|
|
public void InsertIndent(string indentToken)
|
|
{
|
|
if (indentToken == null || indentToken == "0") indentToken = "\x5";
|
|
AddText(indentToken);
|
|
}
|
|
public void InsertText(string txt)
|
|
{
|
|
AddText(txt);
|
|
}
|
|
|
|
private void ToggleCase()
|
|
{
|
|
char type = 'l';
|
|
// do not change case on linked text
|
|
RangeStatus rs = FindRangeStatus();
|
|
string tmp = null;
|
|
if (rs != RangeStatus.NoContainedLinks)
|
|
{
|
|
int start = SelectionStart;
|
|
int ostart = SelectionStart;
|
|
int end = SelectionStart + SelectionLength;
|
|
bool processed = false;
|
|
while (!processed && start <= end)
|
|
{
|
|
foreach (LinkLocation ll in LinkLocations)
|
|
{
|
|
if (ll.Start >= start && ll.End <= end)
|
|
{
|
|
processed = true;
|
|
if (start < ll.Start)
|
|
{
|
|
SelectionStart = start;
|
|
SelectionLength = ll.Start - start;
|
|
}
|
|
start = ll.End + 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
string ostring = SelectedText;
|
|
if (ostring.Length == 0) return; // nothing selected
|
|
if (ostring.Length == 1)
|
|
type = char.IsUpper(ostring, 0) ? 'l' : 'U';
|
|
else if ((char.IsUpper(ostring, 0) && char.IsUpper(ostring, 1)) ||
|
|
(char.IsLower(ostring, 0) && char.IsUpper(ostring, 1))) type = 'l'; // lower case
|
|
else if ((char.IsUpper(ostring, 0) && char.IsLower(ostring, 1))) type = 'U'; // upper case
|
|
else type = 'T'; // Title case
|
|
SetSelectedCase(type);
|
|
}
|
|
|
|
public void SetSelectedCase(char type)
|
|
{
|
|
// do not change case on linked text
|
|
RangeStatus rs = FindRangeStatus();
|
|
string tmp = null;
|
|
if (rs == RangeStatus.NoContainedLinks)
|
|
SetCase(type);
|
|
else
|
|
{
|
|
int start = SelectionStart;
|
|
int ostart = SelectionStart;
|
|
int end = SelectionStart + SelectionLength;
|
|
StringBuilder sb = new StringBuilder();
|
|
while (start <= end)
|
|
{
|
|
bool processed = false;
|
|
foreach (LinkLocation ll in LinkLocations)
|
|
{
|
|
if (ll.Start >= start && ll.End <= end)
|
|
{
|
|
processed = true;
|
|
if (start < ll.Start)
|
|
{
|
|
SelectionStart = start;
|
|
SelectionLength = ll.Start - start;
|
|
SetCase(type);
|
|
}
|
|
start = ll.End + 1;
|
|
break;
|
|
}
|
|
}
|
|
// if none were processed, no more links, copy over any remaining text.
|
|
if (!processed)
|
|
{
|
|
SelectionStart = start;
|
|
SelectionLength = end-start;
|
|
SetCase(type);
|
|
start = end + 1;
|
|
}
|
|
}
|
|
SelectionStart = ostart;
|
|
SelectionLength = end - ostart;
|
|
}
|
|
}
|
|
|
|
private void SetCase(char type)
|
|
{
|
|
int ostart = SelectionStart;
|
|
int olen = SelectionLength;
|
|
string ostring = SelectedText;
|
|
string tmp = null;
|
|
bool docap = true;
|
|
// go character by character. Because of symbols, setting entire
|
|
// to upper or lower set symbols incorrectly some of time (depending
|
|
// on symbol) .
|
|
for (int i = 0; i < olen; i++)
|
|
{
|
|
SelectionStart = ostart + i;
|
|
SelectionLength = 1;
|
|
switch (type)
|
|
{
|
|
case 'l':
|
|
if (SelectedText[0] >= 'A' && SelectedText[0] <= 'Z')
|
|
SelectedText = SelectedText.ToLower();
|
|
break;
|
|
case 'U':
|
|
if (SelectedText[0] >= 'a' && SelectedText[0] <= 'z')
|
|
SelectedText = SelectedText.ToUpper();
|
|
break;
|
|
case 'T':
|
|
if (docap && SelectedText[0] >= 'a' && SelectedText[0] <= 'z')
|
|
SelectedText = SelectedText.ToUpper();
|
|
else if (!docap && SelectedText[0] >= 'A' && SelectedText[0] <= 'Z')
|
|
SelectedText = SelectedText.ToLower();
|
|
docap = ostring[i] == ' ';
|
|
break;
|
|
}
|
|
}
|
|
SelectionStart = ostart;
|
|
SelectionLength = olen;
|
|
}
|
|
#endregion
|
|
#region AddRtfTextAndStyles
|
|
private string _LastRtf = "";
|
|
public string LastRtf
|
|
{
|
|
get { return _LastRtf; }
|
|
set { _LastRtf = value; }
|
|
}
|
|
private bool _lastReadOnly = false;
|
|
private void AddRtfText(string txt)
|
|
{
|
|
//Console.WriteLine("ItemID:{0}", MyItemInfo.ItemID);
|
|
//if(MyItemInfo.ItemID==10256)
|
|
// Volian.Base.Library.vlnStackTrace.ShowStackLocal("ItemID:{0}", MyItemInfo.ItemID.ToString());
|
|
StringBuilder selectedRtfSB = new StringBuilder();
|
|
AddFontTable(selectedRtfSB, FormatFont, FontIsFixed(FormatFont));
|
|
_RtfPrefix = selectedRtfSB.ToString();
|
|
selectedRtfSB.Append(txt);
|
|
string newRtf = selectedRtfSB.ToString() + "}";
|
|
if(newRtf != _LastRtf || ReadOnly != _lastReadOnly)
|
|
{
|
|
//Console.WriteLine("ItemID:{0}\r\nOld:'{1}'\r\nNew:'{2}'\r\n", MyItemInfo.ItemID, Rtf, newRtf);
|
|
this.ContentsResized -= new ContentsResizedEventHandler(StepRTB_ContentsResized);
|
|
Text = "";
|
|
this.ContentsResized += new ContentsResizedEventHandler(StepRTB_ContentsResized);
|
|
// 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;
|
|
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.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 newstart = FindStart(); // find start of link ending on.
|
|
// if not link, don't do special processing
|
|
if (newstart == SelectionStart - 1) return;
|
|
int len = SelectionLength + SelectionStart - newstart;
|
|
SetSelection(newstart, len);
|
|
e.Handled = true;
|
|
return;
|
|
}
|
|
if (e.Control || SelectionStart == 0)
|
|
{
|
|
StepRTB_ArrowPressed(e.Control ? E_ArrowKeys.CtrlLeft : E_ArrowKeys.Left);
|
|
e.Handled = true;
|
|
}
|
|
HandleLocalSelectionChange();
|
|
break;
|
|
case Keys.Up:
|
|
int ln = GetLineFromCharIndex(SelectionStart);
|
|
if (e.Control || ln == 0)
|
|
{
|
|
StepRTB_ArrowPressed(e.Control ? E_ArrowKeys.CtrlUp : E_ArrowKeys.Up);
|
|
e.Handled = true;
|
|
}
|
|
// if shift-up & at selection had a link, handle this as special case.
|
|
if (e.Shift && SelectionLength > 0)
|
|
{
|
|
RangeStatus rs = FindRangeStatus();
|
|
if (rs != RangeStatus.NoContainedLinks)
|
|
{
|
|
int curend = SelectionStart + SelectionLength;
|
|
SelectionLength = 0;
|
|
RtbSendKeys("{Up}");
|
|
Application.DoEvents();
|
|
Select(SelectionStart, curend - SelectionStart);
|
|
e.Handled = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
HandleLocalSelectionChange();
|
|
}
|
|
break;
|
|
case Keys.Right:
|
|
// If at beginning of box that starts with a link, don't worry about shift or not,
|
|
// because selection is first character or link without any other selection. Don't
|
|
// need to write code to handle link at beginning of box in Shift Right code because
|
|
// it's handled in HandleSelectionChange.
|
|
if (e.Shift && ((SelectionStart > 0) || (SelectionStart == 0 && _LinkLocations.Count > 0 && _LinkLocations[0].Start != 7)))
|
|
{
|
|
int newlen = FindEnd();
|
|
int len = SelectionLength + newlen;
|
|
SetSelection(SelectionStart, len);
|
|
e.Handled = true;
|
|
return;
|
|
}
|
|
if (e.Control || SelectionStart == this.Text.Length)
|
|
{
|
|
StepRTB_ArrowPressed(e.Control ? E_ArrowKeys.CtrlRight : E_ArrowKeys.Right);
|
|
e.Handled = true;
|
|
}
|
|
HandleLocalSelectionChange();
|
|
break;
|
|
case Keys.Down:
|
|
int l = GetLineFromCharIndex(SelectionStart);
|
|
Point pos = new Point();
|
|
pos.X = ClientRectangle.Width;
|
|
pos.Y = ClientRectangle.Height;
|
|
int lastIndex = this.GetCharIndexFromPosition(pos);
|
|
int lastLine = this.GetLineFromCharIndex(lastIndex);
|
|
if (e.Control || l >= lastLine)
|
|
{
|
|
StepRTB_ArrowPressed(e.Control ? E_ArrowKeys.CtrlDown : E_ArrowKeys.Down);
|
|
HandleLocalSelectionChange();
|
|
e.Handled = true;
|
|
return;
|
|
}
|
|
if (!e.Shift) HandleLocalSelectionChange();
|
|
// if shift-down & on link at beginning of box - do special processing (regular processing
|
|
// didn't handle it correctly.
|
|
if (e.Shift && lastLine > 0 && SelectionStart == 0 && _LinkLocations.Count > 0 && _LinkLocations[0].Start == 7)
|
|
{
|
|
Point cpos = GetPositionFromCharIndex(SelectionStart);
|
|
int addon = ClientRectangle.Height / (lastLine + 1);
|
|
cpos.Y = cpos.Y + addon;
|
|
int selend = GetCharIndexFromPosition(cpos);
|
|
Select(7, selend - 7);
|
|
e.Handled = true;
|
|
}
|
|
break;
|
|
case Keys.PageUp:
|
|
StepRTB_PageKeyPressed(e);
|
|
e.Handled = true;
|
|
break;
|
|
case Keys.PageDown:
|
|
StepRTB_PageKeyPressed(e);
|
|
e.Handled = true;
|
|
break;
|
|
case Keys.Delete:
|
|
if (SelectionLength == 0)
|
|
{
|
|
foreach (LinkLocation lls in _LinkLocations)
|
|
{
|
|
if (SelectionStart >= lls.Start - 7 && SelectionStart < lls.End)
|
|
{
|
|
SetSelection(lls);// Select the link to the right
|
|
HandleDeleteKeyWithSelectedText(e, null);
|
|
e.SuppressKeyPress = true;
|
|
return;
|
|
}
|
|
}
|
|
if (SelectionStart != TextLength)
|
|
{
|
|
SelectionStart++;// A Delete can be accomplished with a right arrow followed by a backspace.
|
|
RtbSendKeys("{BS}"); // This is done due to a glitch in the RichTextBox that sometimes causes a beep rather than a delete
|
|
e.SuppressKeyPress = true;
|
|
}
|
|
}
|
|
else
|
|
HandleDeleteKeyWithSelectedText(e, null);
|
|
break;
|
|
case Keys.Back:
|
|
if (_SendBackSpace)
|
|
{
|
|
_SendBackSpace = false;
|
|
return;
|
|
}
|
|
_CheckSelection = true;
|
|
if (SelectionLength == 0)
|
|
{
|
|
foreach (LinkLocation lls in _LinkLocations)
|
|
{
|
|
if (SelectionStart > lls.Start - 7 && SelectionStart <= lls.End)
|
|
{
|
|
SetSelection(lls);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (SelectionLength > 0) HandleDeleteKeyWithSelectedText(e, null);
|
|
break;
|
|
case Keys.Insert:
|
|
//_OverWrite = !_OverWrite;
|
|
//if (_OverWrite)
|
|
//{
|
|
// HandleSelectionChange();
|
|
//}
|
|
//else
|
|
//{
|
|
// SelectionLength = 0;
|
|
// HandleSelectionChange();
|
|
//}
|
|
// For now, don't allow for toggling between insert/overwrite mode - see
|
|
// comment on _OverWrite
|
|
e.Handled = true;
|
|
break;
|
|
case Keys.F5:
|
|
if (e.Shift)
|
|
{
|
|
e.Handled = true;
|
|
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
|
|
{
|
|
if (e.Shift)
|
|
{
|
|
e.SuppressKeyPress = true;
|
|
e.Handled = true;
|
|
if (!myGrid.SelectPrevCell())
|
|
{
|
|
// don't do anything if at top (for now)
|
|
}
|
|
}
|
|
else
|
|
{
|
|
e.SuppressKeyPress = true;
|
|
e.Handled = true;
|
|
if (!myGrid.SelectNextCell())
|
|
{
|
|
myGrid.MyBorders.InsertRow(myGrid.Rows.Count - 1);
|
|
myGrid.Rows.Add(1);
|
|
myGrid.SelectNextCell();
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case Keys.Enter:
|
|
if (!e.Control && !e.Shift && !e.Alt)
|
|
{
|
|
OnEnterKeyPressed(sender, e);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
private static Form ParentForm(Control ctrl)
|
|
{
|
|
while (!(ctrl.Parent is Form || ctrl.Parent is EditItem))
|
|
ctrl = ctrl.Parent;
|
|
return ctrl.Parent as Form;
|
|
}
|
|
private void StepRTB_HomeEndPressed(KeyEventArgs keyargs)
|
|
{
|
|
if (MyItemInfo.IsProcedure || MyItemInfo.IsSection) return;
|
|
// Cursor moves out of box only if control is pressed too - otherwise key is
|
|
// handled in rtb.
|
|
//if (keyargs.Control)MyRTBItem.MyStepPanel.StepCursorKeys(this, keyargs); // Replaced with an event
|
|
if (keyargs.Control) OnCursorKeyPress(this, keyargs);
|
|
}
|
|
private void StepRTB_PageKeyPressed(KeyEventArgs keyargs)
|
|
{
|
|
if (MyItemInfo.IsProcedure || MyItemInfo.IsSection) return;
|
|
//MyRTBItem.MyStepPanel.StepCursorKeys(this, keyargs); Replaced with an event
|
|
OnCursorKeyPress(this, keyargs);
|
|
}
|
|
public void StepRTB_ArrowPressed(E_ArrowKeys key)
|
|
{
|
|
Point cp = PointToClient(Cursor.Position);
|
|
//MyRTBItem.MyStepPanel.CursorMovement(this, cp, key); Replaced with an event
|
|
OnCursorMovement(this, new StepRTBCursorMovementEventArgs(cp, key));
|
|
}
|
|
private void StepRTB_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
|
|
{
|
|
if (!ReadOnly)
|
|
{
|
|
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);
|
|
}
|
|
public class SelectionData
|
|
{
|
|
int _SelectionStart;
|
|
public int SelectionStart
|
|
{
|
|
get { return _SelectionStart; }
|
|
set { _SelectionStart = value; }
|
|
}
|
|
int _SelectionLength;
|
|
public int SelectionLength
|
|
{
|
|
get { return _SelectionLength; }
|
|
set { _SelectionLength = value; }
|
|
}
|
|
public SelectionData(RichTextBox richTextBox)
|
|
{
|
|
_SelectionStart = richTextBox.SelectionStart;
|
|
_SelectionLength = richTextBox.SelectionLength;
|
|
}
|
|
}
|
|
#endregion
|
|
#region Link Support
|
|
int _ProcessingKeys = 0;
|
|
|
|
List<LinkLocation> _LinkLocations;
|
|
public List<LinkLocation> LinkLocations
|
|
{
|
|
get { return _LinkLocations; }
|
|
}
|
|
private int _FALLevel = 0;
|
|
private bool _IdentifyingLinks = false;
|
|
public void FindAllLinks()
|
|
{
|
|
if (_IdentifyingLinks || _ProcessingDelete) return;
|
|
//DebugPrint("FAL{0}vvvvvvvvvvvvvvvvvvvvvvvvv>>", ++_FALLevel);
|
|
_AdjustingSelection = true;
|
|
PushSelection();
|
|
FindLinks();
|
|
//IdentifyLinks();
|
|
PopSelection();
|
|
LinkLocation llx = FindLinkLocation();
|
|
if (_CheckSelection)
|
|
{
|
|
if (llx != null) SetSelection(llx.End, 0);
|
|
_CheckSelection = false;
|
|
}
|
|
_AdjustingSelection = false;
|
|
if (!_ProcessingDelete)
|
|
OnLinkLocationChanged(this, new EventArgs());
|
|
//DebugPrint("FAL{0}^^^^^^^^^^^^^^^^^^^^^^^^^>>", _FALLevel--);
|
|
|
|
}
|
|
private void FindLinks()
|
|
{
|
|
string str = Text;
|
|
_LinkLocations = new List<LinkLocation>();
|
|
MatchCollection matches = Regex.Matches(str, @"<START](.*?)[[]END>", RegexOptions.Singleline);
|
|
MatchCollection matchesRtf = Regex.Matches(Rtf, "<START](.*?)[[]END>", RegexOptions.Singleline);
|
|
LinkLocation thisLink = null;
|
|
for (int i = 0; i < matches.Count; i++) //each (Match match in matches)
|
|
{
|
|
Match match = matches[i];
|
|
Match matchrtf = matchesRtf[i];
|
|
thisLink = new LinkLocation(match.Index + 7, // If the [END> is immediately followed by <START] include it
|
|
match.Length - (((match.Index + match.Length + 7 <= str.Length) && (str.Substring(match.Index + match.Length, 7) == "<START]")) ? 0 : 7),
|
|
match.Value, matchrtf.Index, matchrtf.Length, thisLink);
|
|
_LinkLocations.Add(thisLink);
|
|
}
|
|
}
|
|
private LinkLocation FindBetweenLinks()
|
|
{
|
|
return FindBetweenLinks(SelectionStart);
|
|
}
|
|
private LinkLocation FindBetweenLinks(int start)
|
|
{
|
|
DebugPrint("FL----------------Between>");
|
|
if (_LinkLocations == null) return null;
|
|
foreach (LinkLocation ll in _LinkLocations)
|
|
if (ll.Start == start && ll.StartsBetween)
|
|
return ll;
|
|
return null;
|
|
}
|
|
private LinkLocation FindLinkLocation()
|
|
{
|
|
return FindLinkLocation(SelectionStart);
|
|
}
|
|
private LinkLocation FindLinkLocation(int sel)
|
|
{
|
|
//DebugPrint("FL----------------Location>");
|
|
if (_LinkLocations == null) return null;
|
|
foreach (LinkLocation ll in _LinkLocations)
|
|
{
|
|
// Moving right:
|
|
// if less than, allows stopping between two links
|
|
if (ll.Start < sel && ll.End > sel)
|
|
{
|
|
DebugPrint("Greater Than {0} {1} {2}", sel, ll.Start, ll.End);
|
|
return ll;
|
|
}
|
|
// if less than or equal, does not stop between two links
|
|
if ((!ll.StartsBetween) && ll.Start <= sel && ll.End > sel)
|
|
{
|
|
DebugPrint("Greater Than or Equal {0} {1} {2}", sel, ll.Start, ll.End);
|
|
return ll;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
public DialogResult ReplaceText(string rpltxt, string fndstr, bool caseSensitive, bool matchWholeWord, bool reverse, bool prompt, IWin32Window fndrpldlg)
|
|
{
|
|
DialogResult dlgrslt = DialogResult.Yes;
|
|
if (SelectionLength > 0)
|
|
{
|
|
if (IsSelectionLinked(SelectionStart, SelectionLength))
|
|
{
|
|
MessageBox.Show(fndrpldlg,"Cannot replace linked text!", "Find/Replace");
|
|
dlgrslt = DialogResult.No;
|
|
}
|
|
else
|
|
{
|
|
if (prompt)
|
|
dlgrslt = MessageBox.Show(fndrpldlg,"Replace This Occurence?", "Replace Text", MessageBoxButtons.YesNoCancel);
|
|
if (dlgrslt == DialogResult.Yes)
|
|
SelectedText = rpltxt;
|
|
}
|
|
}
|
|
return dlgrslt;
|
|
}
|
|
private RichTextBoxFinds _FindOptions = RichTextBoxFinds.None;
|
|
public bool FindText(string str, bool caseSensitive, bool matchWholeWord, bool reverse)
|
|
{
|
|
using (StepRTB savRTF = new StepRTB())
|
|
{
|
|
int startpos = SelectionStart + SelectionLength;
|
|
savRTF.Text = this.Text;
|
|
|
|
_FindOptions = RichTextBoxFinds.None;
|
|
if (caseSensitive)
|
|
_FindOptions |= RichTextBoxFinds.MatchCase;
|
|
if (matchWholeWord)
|
|
_FindOptions |= RichTextBoxFinds.WholeWord;
|
|
if (reverse)
|
|
{
|
|
_FindOptions |= RichTextBoxFinds.Reverse;
|
|
savRTF.Text = this.Text.Substring(0, SelectionStart);
|
|
startpos = savRTF.Text.Length;
|
|
if (startpos == 0)
|
|
return false; // at beginning of rtfbox during a reverse find
|
|
}
|
|
else
|
|
{
|
|
if (startpos >= savRTF.Text.Length)
|
|
return false; // at end of rtfbox during a forward find
|
|
}
|
|
// look for the find string in the temporary rtfbox
|
|
// then set the cursor selection in the real rtfbox
|
|
bool keepgoing = true;
|
|
while (keepgoing)
|
|
{
|
|
int pos = savRTF.Find(str, startpos, _FindOptions);
|
|
keepgoing = false;
|
|
if (pos >= 0)
|
|
{
|
|
if (this.SkipLinkInfo(pos, str.Length))
|
|
{
|
|
if (reverse)
|
|
{
|
|
startpos--;
|
|
savRTF.Text = savRTF.Text.Substring(0, startpos);
|
|
}
|
|
else
|
|
startpos++;
|
|
if (startpos > 0 && startpos < savRTF.Text.Length)
|
|
keepgoing = true;
|
|
}
|
|
else
|
|
{
|
|
SelectionStart = pos;
|
|
SelectionLength = str.Length;
|
|
}
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
private int FindStart()
|
|
{
|
|
foreach (LinkLocation ll in _LinkLocations)
|
|
{
|
|
if (SelectionStart == ll.End) return ll.Start;
|
|
if (SelectionStart == ll.Start)
|
|
{
|
|
if (ll.Start == 7) return 7;
|
|
return ll.Start - 8;
|
|
}
|
|
}
|
|
if (SelectionStart > 0) return SelectionStart - 1;
|
|
return 0;
|
|
}
|
|
private int FindEnd()
|
|
{
|
|
foreach (LinkLocation ll in _LinkLocations)
|
|
{
|
|
if (SelectionStart + SelectionLength + 7 == ll.Start) return ll.Length + 7;
|
|
// this is for in-between links
|
|
if (SelectionStart + SelectionLength == ll.Start) return ll.Length;
|
|
}
|
|
if (SelectionStart + SelectionLength < TextLength) return 1;
|
|
return 0;
|
|
}
|
|
private int FindEndDown()
|
|
{
|
|
foreach (LinkLocation ll in _LinkLocations)
|
|
{
|
|
if (SelectionStart + SelectionLength >= ll.Start && SelectionStart + SelectionLength <= ll.End) return ll.End;
|
|
}
|
|
return 0;
|
|
}
|
|
private int FindStartUp()
|
|
{
|
|
foreach (LinkLocation ll in _LinkLocations)
|
|
{
|
|
if ((SelectionStart >= ll.Start) && (SelectionStart <= ll.End)) return ll.Start;
|
|
}
|
|
return -1;
|
|
}
|
|
public void SetSelection(LinkLocation ll)
|
|
{
|
|
SetSelection(ll.Start, ll.Length);
|
|
}
|
|
public void SetSelection(int locStart, int locLength)
|
|
{
|
|
//Application.DoEvents(); // Not needed since SendKeys is always done last.
|
|
if (_IdentifyingLinks)
|
|
DebugPrint("SS------------------------> {0} {1}", locStart, locLength);
|
|
else
|
|
DebugPrint("SS========================> {0} {1}", locStart, locLength);
|
|
Select(locStart, locLength);
|
|
}
|
|
#endregion
|
|
//#region FontAndStylesSupport
|
|
//private void ToggleFontStyle(FontStyle style, bool att_on)
|
|
//{
|
|
// int start = SelectionStart;
|
|
// int len = SelectionLength;
|
|
// System.Drawing.Font currentFont;
|
|
// FontStyle fs;
|
|
// for (int i = 0; i < len; ++i)
|
|
// {
|
|
// Select(start + i, 1);
|
|
// currentFont = SelectionFont;
|
|
// fs = currentFont.Style;
|
|
// //add or remove style
|
|
// if (!att_on)fs = fs | style;
|
|
// else fs = fs & ~style;
|
|
|
|
// SelectionFont = new Font(
|
|
// currentFont.FontFamily,
|
|
// currentFont.Size,
|
|
// fs
|
|
// );
|
|
// }
|
|
//}
|
|
/// <summary>
|
|
/// Returns a Font with:
|
|
/// 1) The font applying to the entire selection, if none is the default font.
|
|
/// 2) The font size applying to the entire selection, if none is the size of the default font.
|
|
/// 3) A style containing the attributes that are common to the entire selection, default regular.
|
|
/// </summary>
|
|
///
|
|
//public Font GetFontDetails()
|
|
//{
|
|
// //This method should handle cases that occur when multiple fonts/styles are selected
|
|
|
|
// int start = SelectionStart;
|
|
// int len = SelectionLength;
|
|
// int TempStart = 0;
|
|
|
|
// if (len <= 1)
|
|
// {
|
|
// // Return the selection or default font
|
|
// if (SelectionFont != null)
|
|
// return SelectionFont;
|
|
// else
|
|
// return Font; // should be default from format.
|
|
// }
|
|
|
|
// // Step through the selected text one char at a time
|
|
// // after setting defaults from first char
|
|
// _rtbTemp.Rtf = SelectedRtf;
|
|
|
|
// //Turn everything on so we can turn it off one by one
|
|
// FontStyle replystyle =
|
|
// FontStyle.Bold | FontStyle.Italic | FontStyle.Underline;
|
|
|
|
// // Set reply font, size and style to that of first char in selection.
|
|
// _rtbTemp.Select(TempStart, 1);
|
|
// string replyfont = _rtbTemp.SelectionFont.Name;
|
|
// float replyfontsize = _rtbTemp.SelectionFont.Size;
|
|
// replystyle = replystyle & _rtbTemp.SelectionFont.Style;
|
|
|
|
// // Search the rest of the selection
|
|
// for (int i = 1; i < len; ++i)
|
|
// {
|
|
// _rtbTemp.Select(TempStart + i, 1);
|
|
|
|
// // Check reply for different style
|
|
// replystyle = replystyle & _rtbTemp.SelectionFont.Style;
|
|
|
|
// // Check font
|
|
// if (replyfont != _rtbTemp.SelectionFont.FontFamily.Name)
|
|
// replyfont = "";
|
|
|
|
// // Check font size
|
|
// if (replyfontsize != _rtbTemp.SelectionFont.Size)
|
|
// replyfontsize = (float)0.0;
|
|
// }
|
|
|
|
// // Now set font and size if more than one font or font size was selected
|
|
// if (replyfont == "")
|
|
// replyfont = _rtbTemp.Font.FontFamily.Name;
|
|
|
|
// if (replyfontsize == 0.0)
|
|
// replyfontsize = _rtbTemp.Font.Size;
|
|
|
|
// // generate reply font
|
|
// Font reply
|
|
// = new Font(replyfont, replyfontsize, replystyle);
|
|
|
|
// return reply;
|
|
//}
|
|
//#endregion
|
|
#region EnumsSelectionRange
|
|
private enum StartStatus : int
|
|
{
|
|
Before = 100,
|
|
Between = 200,
|
|
StartLink = 300,
|
|
StartBox = 400
|
|
};
|
|
private enum EndStatus : int
|
|
{
|
|
After = 1,
|
|
Between = 2,
|
|
EndLink = 3,
|
|
EndBox = 4,
|
|
StartLink = 5
|
|
};
|
|
public enum RangeStatus : int
|
|
{
|
|
NoContainedLinks = 0,
|
|
Before_After = StartStatus.Before + EndStatus.After,
|
|
Before_Between = StartStatus.Before + EndStatus.Between,
|
|
Before_EndLink = StartStatus.Before + EndStatus.EndLink,
|
|
Before_EndBox = StartStatus.Before + EndStatus.EndBox,
|
|
Before_StartLink = StartStatus.Before + EndStatus.StartLink,
|
|
Between_After = StartStatus.Between + EndStatus.After,
|
|
Between_Between = StartStatus.Between + EndStatus.Between,
|
|
Between_EndLink = StartStatus.Between + EndStatus.EndLink,
|
|
Between_EndBox = StartStatus.Between + EndStatus.EndBox,
|
|
Between_StartLink = StartStatus.Between + EndStatus.StartLink,
|
|
StartLink_After = StartStatus.StartLink + EndStatus.After,
|
|
StartLink_Between = StartStatus.StartLink + EndStatus.Between,
|
|
StartLink_EndLink = StartStatus.StartLink + EndStatus.EndLink,
|
|
StartLink_EndBox = StartStatus.StartLink + EndStatus.EndBox,
|
|
StartLink_StartLink = StartStatus.StartLink + EndStatus.StartLink,
|
|
StartBox_After = StartStatus.StartBox + EndStatus.After,
|
|
StartBox_Between = StartStatus.StartBox + EndStatus.Between,
|
|
StartBox_EndLink = StartStatus.StartBox + EndStatus.EndLink,
|
|
StartBox_EndBox = StartStatus.StartBox + EndStatus.EndBox,
|
|
StartBox_StartLink = StartStatus.StartBox + EndStatus.StartLink
|
|
};
|
|
private RangeStatus _RTBRangeStatus;
|
|
public RangeStatus RTBRangeStatus
|
|
{
|
|
get { return _RTBRangeStatus; }
|
|
set
|
|
{
|
|
_RTBRangeStatus = value;
|
|
if (!_ProcessingDelete) OnRTBRangeStatusChanged(this, new EventArgs());
|
|
}
|
|
}
|
|
private LinkLocation _RangeStartLink = null;
|
|
private LinkLocation _RangeEndLink = null;
|
|
public RangeStatus FindRangeStatus()
|
|
{
|
|
_RangeStartLink = null;
|
|
_RangeEndLink = null;
|
|
if (_LinkLocations == null || _LinkLocations.Count == 0)
|
|
{
|
|
return RTBRangeStatus = RangeStatus.NoContainedLinks;
|
|
}
|
|
LinkLocation foundLink = null;
|
|
int start = SelectionStart;
|
|
int end = start + SelectionLength;
|
|
|
|
foreach (LinkLocation ll in _LinkLocations)
|
|
{
|
|
if (foundLink == null && ((ll.Start >= start && ll.Start < end) || (ll.End >= start && ll.End < end)))
|
|
foundLink = ll;
|
|
if (_RangeStartLink == null && start >= ll.Start - 7 && start < ll.End)
|
|
_RangeStartLink = ll;
|
|
if (_RangeEndLink == null && end >= ll.Start && end <= ll.End)
|
|
_RangeEndLink = ll;
|
|
}
|
|
DebugPrint("SelectionStart {0}, SelectionEnd {1}, TextLength {2}",
|
|
SelectionStart, SelectionStart + SelectionLength,
|
|
TextLength);
|
|
//if (_RangeStartLink != null)
|
|
// _RangeStartLink.Show("startLink");
|
|
//if (_RangeEndLink != null)
|
|
// _RangeEndLink.Show("endLink");
|
|
//if (foundLink != null)
|
|
// foundLink.Show("foundLink");
|
|
|
|
if (foundLink == null)
|
|
return RTBRangeStatus = RangeStatus.NoContainedLinks;
|
|
|
|
StartStatus myStartStatus = StartStatus.Before;
|
|
EndStatus myEndStatus = EndStatus.After;
|
|
if (_RangeStartLink != null)
|
|
{
|
|
if (_RangeStartLink.Start == 7)
|
|
myStartStatus = StartStatus.StartBox;
|
|
else if (_RangeStartLink.StartsBetween)
|
|
myStartStatus = StartStatus.Between;
|
|
else
|
|
myStartStatus = StartStatus.StartLink;
|
|
}
|
|
if (_RangeEndLink != null)
|
|
{
|
|
if (_RangeEndLink.End == TextLength)
|
|
myEndStatus = EndStatus.EndBox;
|
|
else if (_RangeEndLink.NextStart == _RangeEndLink.End)
|
|
myEndStatus = EndStatus.Between;
|
|
else if (end == _RangeEndLink.Start)
|
|
myEndStatus = EndStatus.StartLink; // Should not happen because of code in HandleSelectionChange
|
|
else //if (end == endLink.End)
|
|
myEndStatus = EndStatus.EndLink;
|
|
}
|
|
return RTBRangeStatus = (RangeStatus)((int)myStartStatus + (int)myEndStatus);
|
|
}
|
|
#endregion
|
|
#region OutlineTable
|
|
private string _CheckRight = "-\u2500\u2011";
|
|
public string CheckRight
|
|
{
|
|
get { return _CheckRight; }
|
|
set { _CheckRight = value; }
|
|
}
|
|
private string _CheckAbove = "|\u2502\u2514\u252c\u253c\u251c\u250c\u2534\u2510\u2524";
|
|
public string CheckAbove
|
|
{
|
|
get { return _CheckAbove; }
|
|
set { _CheckAbove = value; }
|
|
}
|
|
private string _CheckLeft = "-\u2500\u2524\u252c\u251c\u253c\u250c\u2510\u2514\u2011";
|
|
public string CheckLeft
|
|
{
|
|
get { return _CheckLeft; }
|
|
set { _CheckLeft = value; }
|
|
}
|
|
private string _CheckBelow = "|\u2502";
|
|
public string CheckBelow
|
|
{
|
|
get { return _CheckBelow; }
|
|
set { _CheckBelow = value; }
|
|
}
|
|
// This is a table of graphics characters
|
|
// The index into this table (0-15) is a bitmask with each bit representing
|
|
// a different direction from the current character.
|
|
// Right is Bit 0 (0 or 1)
|
|
// Above is Bit 1 (0 or 2)
|
|
// Left is Bit 2 (0 or 4)
|
|
// Below is Bit 3 (0 or 8)
|
|
// The index is contolled in the following way:
|
|
// If there is a graphics character to the right, then you add 1
|
|
// If there is a graphics character above, then you add 2
|
|
// If there is a graphics character left, then you add 4
|
|
// If there is a graphics character below, then you add 8
|
|
// The total results in an index into this array and gives the appropriate character
|
|
// combining horizontal and vertical lines.
|
|
|
|
static private string [] TableCharsU = {
|
|
"\x0", // HEX"\x0", // No character
|
|
@"\u9472", // HEX@"\u2500",// - Horizontal line - 16-bit char: '\xC4'
|
|
@"\u9474", // HEX@"\u2502",// | Vertical line - 16-bit char: '\xB3'
|
|
@"\u9492", // HEX@"\u2514",// L Bottom Left corner - 16-bit char: '\xC0'
|
|
@"\u9472", // HEX@"\u2500",// - Horizontal line - 16-bit char: '\xC4'
|
|
@"\u9472", // HEX@"\u2500",// - Horizontal line - 16-bit char: '\xC4'
|
|
@"\u9496", // HEX@"\u2518",// Bottom Right Corner - 16-bit char: '\xD9'
|
|
@"\u9524", // HEX@"\u2534",// Bottom Tee - 16-bit char: '\xC1'
|
|
@"\u9474", // HEX@"\u2502",// | Vertical Bar - 16-bit char: '\xB3'
|
|
@"\u9484", // HEX@"\u250c",// Upper Left corner - 16-bit char: '\xDA'
|
|
@"\u9474", // HEX@"\u2502",// | Vertical Bar - 16-bit char: '\xB3'
|
|
@"\u9500", // HEX@"\u251c",// Left Tee - 16-bit char: '\xC3'
|
|
@"\u9488", // HEX@"\u2510",// Upper Right corner - 16-bit char: '\xBF'
|
|
@"\u9516", // HEX@"\u252c",// T Top Tee - 16-bit char: '\xC2'
|
|
@"\u9508", // HEX@"\u2524",// Right Tee - 16-bit char: '\xB4'
|
|
@"\u9532", // HEX@"\u253c" // + Plus - 16-bit char: '\xC5'
|
|
};
|
|
|
|
private int MaxCharacterWidth()
|
|
{
|
|
// loop through lines and get the width in characters
|
|
int w = 0;
|
|
foreach (string line in Lines)
|
|
{
|
|
string cleanLine = RemoveLinkComments(line);
|
|
if (w < cleanLine.Length)
|
|
w = cleanLine.Length;
|
|
}
|
|
return w;
|
|
}
|
|
internal static string RemoveLinkComments(string line)
|
|
{
|
|
StringBuilder sb = new StringBuilder();
|
|
int lastIndex = 0;
|
|
MatchCollection mc = Regex.Matches(line, @"<START\](.*?)#Link.*?\[END>", 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
|
|
}
|