Commit for development environment setup
This commit is contained in:
881
PROMS/TestWndProc/TestWndProc/MyRTB.cs
Normal file
881
PROMS/TestWndProc/TestWndProc/MyRTB.cs
Normal file
@@ -0,0 +1,881 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Data;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace TestWndProc
|
||||
{
|
||||
public delegate void RTBEvent(object sender, EventArgs args);
|
||||
public partial class MyRTB : RichTextBox
|
||||
{
|
||||
#region Events
|
||||
public event RTBEvent RTBSelectionChanged;
|
||||
private void OnRTBSelectionChanged(object sender, EventArgs args)
|
||||
{
|
||||
if (RTBSelectionChanged != null) RTBSelectionChanged(sender, args);
|
||||
}
|
||||
public event RTBEvent LinkLocationsChanged;
|
||||
private void OnLinkLocationChanged(object sender, EventArgs args)
|
||||
{
|
||||
if(LinkLocationsChanged != null) LinkLocationsChanged(sender, args);
|
||||
}
|
||||
public event RTBEvent RTBRangeStatusChanged;
|
||||
private void OnRTBRangeStatusChanged(object sender, EventArgs args)
|
||||
{
|
||||
if (RTBRangeStatusChanged != null) RTBRangeStatusChanged(sender, args);
|
||||
}
|
||||
/// <summary>
|
||||
/// This event is not raised during all the in-between changes for link deletions
|
||||
/// </summary>
|
||||
public event RTBEvent RTBTextChanged;
|
||||
private void OnRTBTextChanged(object sender, EventArgs args)
|
||||
{
|
||||
if (RTBTextChanged != null) RTBTextChanged(sender, args);
|
||||
}
|
||||
#endregion
|
||||
#region public properties
|
||||
private bool _ProcessKeystrokes = true;
|
||||
public bool ProcessKeystrokes
|
||||
{
|
||||
get { return _ProcessKeystrokes; }
|
||||
set { _ProcessKeystrokes = value; }
|
||||
}
|
||||
#endregion
|
||||
#region CaretPosition
|
||||
//[DllImport("user32")]
|
||||
//private static extern IntPtr SendMessage(HandleRef hWnd, int msg, int wParam, int lParam);
|
||||
[DllImport("user32")]
|
||||
private static extern int GetCaretPos(ref Point lpPoint);
|
||||
[DllImport("user32")]
|
||||
private static extern bool SetCaretPos(int X, int Y);
|
||||
//private int EM_LINEINDEX = 0xbb;
|
||||
//private int EM_LINEFROMCHAR = 0xc9;
|
||||
//private int EM_GETSEL = 0xb0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the caret current (X, Y) position.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Point struct
|
||||
/// </value>
|
||||
public Point CaretXYPosition
|
||||
{
|
||||
get
|
||||
{
|
||||
Point pt = Point.Empty;
|
||||
// get a Point struct with the caret current (X, Y)
|
||||
// position
|
||||
GetCaretPos(ref pt);
|
||||
// return the Point struct with the caret current
|
||||
// (X, Y) position
|
||||
return pt;
|
||||
}
|
||||
}
|
||||
public int CaretIndex
|
||||
{
|
||||
get { return GetCharIndexFromPosition(CaretXYPosition); }
|
||||
}
|
||||
public void SetCaretPostoSelectionStart()
|
||||
{
|
||||
Point pt = GetPositionFromCharIndex(SelectionStart);
|
||||
//bool result = SetCaretPos(pt.X,pt.Y);
|
||||
bool result = SetCaretPos(-1, pt.Y);
|
||||
DebugPrint("SetCaretPos({0},{1}) = {2}", pt.X, pt.Y, result);
|
||||
}
|
||||
#endregion
|
||||
#region Constructors
|
||||
public MyRTB()
|
||||
{
|
||||
InitializeComponent();
|
||||
SetupEventHandlers();
|
||||
}
|
||||
public MyRTB(IContainer container)
|
||||
{
|
||||
container.Add(this);
|
||||
InitializeComponent();
|
||||
SetupEventHandlers();
|
||||
}
|
||||
private void SetupEventHandlers()
|
||||
{
|
||||
this.MouseDown += new MouseEventHandler(MyRTB_MouseDown);
|
||||
this.MouseUp += new MouseEventHandler(MyRTB_MouseUp);
|
||||
this.KeyDown += new KeyEventHandler(MyRTB_KeyDown);
|
||||
this.KeyPress += new KeyPressEventHandler(MyRTB_KeyPress);
|
||||
this.TextChanged += new EventHandler(MyRTB_TextChanged);
|
||||
this.SelectionChanged += new EventHandler(MyRTB_SelectionChanged);
|
||||
}
|
||||
#endregion
|
||||
#region Keyboard Handlers
|
||||
void MyRTB_KeyPress(object sender, KeyPressEventArgs e)
|
||||
{
|
||||
DebugPrint("KeyPress: {0},{1}", e.KeyChar, (int)e.KeyChar);
|
||||
if (e.KeyChar >= ' ')
|
||||
{
|
||||
LinkLocation ll = FindBetweenLinks();
|
||||
if (ll != null && SelectionLength == 0) // SelectionLength = 0 means insert
|
||||
{
|
||||
InsertCharBetweenLinks(ll, e.KeyChar);
|
||||
e.Handled = true;
|
||||
}
|
||||
else if (ll != null) // Otherwise it is an overstrike or a delete followed by inserting a character
|
||||
{
|
||||
DeleteStartBetweenLinks();
|
||||
}
|
||||
else if (SelectedText.EndsWith(@"[END><START]"))
|
||||
{
|
||||
DeleteEndBetweenLinks();
|
||||
}
|
||||
}
|
||||
}
|
||||
private bool _SendBackSpace = false;
|
||||
void MyRTB_KeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (_AdjustingSelection)
|
||||
DebugPrint("======================>AdjustingSelection is true in Keydown");
|
||||
if (_ProcessingKeys > 0)
|
||||
DebugPrint("Key down: {0} Shift {1} processing keys = {2}", e.KeyCode, e.Shift, _ProcessingKeys);
|
||||
if (!ProcessKeystrokes) return;
|
||||
switch (e.KeyCode)
|
||||
{
|
||||
case Keys.Left:
|
||||
DebugPrint("Key down: {0} Shift {1} processing keys = {2}", e.KeyCode, e.Shift, _ProcessingKeys);
|
||||
DebugSelection("Left");
|
||||
if (e.Shift) return;
|
||||
LinkLocation ll = FindLinkSelected();
|
||||
if (ll != null)
|
||||
{
|
||||
_AdjustingSelection = true;
|
||||
if (ll.StartsBetween || ll.Start == 7)
|
||||
SetSelection(ll.Start, 0);
|
||||
else
|
||||
SetSelection(ll.Start - 7, 0);
|
||||
_AdjustingSelection = false;
|
||||
e.SuppressKeyPress = true;
|
||||
}
|
||||
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)
|
||||
{
|
||||
//RtbSendKeys("{Left}");// This should select the ll
|
||||
SetSelection(lls);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (SelectionLength > 0) HandleDeleteKeyWithSelectedText(e);
|
||||
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);
|
||||
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);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#region Mouse Handlers
|
||||
void MyRTB_MouseUp(object sender, MouseEventArgs e)
|
||||
{
|
||||
_MouseDown = false;
|
||||
HandleSelectionChange();
|
||||
}
|
||||
void MyRTB_MouseDown(object sender, MouseEventArgs e)
|
||||
{
|
||||
_MouseDown = true;
|
||||
}
|
||||
#endregion
|
||||
#region Event Handlers
|
||||
void MyRTB_SelectionChanged(object sender, EventArgs e)
|
||||
{
|
||||
HandleSelectionChange();
|
||||
}
|
||||
private bool _ProcessingDelete;
|
||||
void MyRTB_TextChanged(object sender, EventArgs e)
|
||||
{
|
||||
if(!_IdentifyingLinks)
|
||||
FindAllLinks();
|
||||
if (!_ProcessingDelete && !_IdentifyingLinks)
|
||||
{
|
||||
OnRTBTextChanged(this, new EventArgs());
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#region SelectionStack
|
||||
Stack<SelectionData> _SelectionStack = new Stack<SelectionData>();
|
||||
public void PushSelection()
|
||||
{
|
||||
_SelectionStack.Push(new SelectionData(this));
|
||||
}
|
||||
public void PopSelection()
|
||||
{
|
||||
SelectionData selection = _SelectionStack.Pop();
|
||||
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
|
||||
bool _AdjustingSelection = false;
|
||||
private bool _CheckSelection = false;
|
||||
int _ProcessingKeys = 0;
|
||||
private bool _MouseDown = false;
|
||||
|
||||
List<LinkLocation> _linkLocations;
|
||||
public List<LinkLocation> LinkLocations
|
||||
{
|
||||
get { return _linkLocations; }
|
||||
}
|
||||
private int _FALLevel = 0;
|
||||
private bool _IdentifyingLinks = false;
|
||||
public void FindAllLinks()
|
||||
{
|
||||
if (_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>");
|
||||
MatchCollection matchesRtf = Regex.Matches(Rtf, "<START](.*?)[[]END>");
|
||||
LinkLocation thisLink = null;
|
||||
for (int i = 0; i < matches.Count; i++) //each (Match match in matches)
|
||||
{ //KBR
|
||||
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);
|
||||
} //KBR
|
||||
}
|
||||
private void IdentifyLinks()
|
||||
{
|
||||
_IdentifyingLinks = true;
|
||||
foreach (LinkLocation ll in _linkLocations)
|
||||
{
|
||||
SetSelection(ll); // subtract off start token!
|
||||
RTBAPI.CharFormatTwo charFormat = RTBAPI.GetCharFormat(this, RTBAPI.RTBSelection.SCF_SELECTION);
|
||||
//charFormat.crBackColor = Color.Blue;
|
||||
// Protect the link text to avoid manual changes
|
||||
charFormat.dwMask = RTBAPI.CharFormatMasks.CFM_LINK; // | RTBAPI.CharFormatMasks.CFM_PROTECTED;
|
||||
charFormat.dwEffects = RTBAPI.CharFormatEffects.CFE_LINK; // | RTBAPI.CharFormatEffects.CFE_PROTECTED;
|
||||
RTBAPI.SetCharFormat(this, RTBAPI.RTBSelection.SCF_SELECTION, charFormat);
|
||||
}
|
||||
_IdentifyingLinks = false;
|
||||
}
|
||||
private LinkLocation FindBetweenLinks()
|
||||
{
|
||||
return FindBetweenLinks(SelectionStart);
|
||||
}
|
||||
private LinkLocation FindBetweenLinks(int start)
|
||||
{
|
||||
DebugPrint("FL----------------Between>");
|
||||
foreach (LinkLocation ll in _linkLocations)
|
||||
if (ll.Start == start && ll.StartsBetween)
|
||||
return ll;
|
||||
return null;
|
||||
}
|
||||
private LinkLocation FindLinkSelected()
|
||||
{
|
||||
DebugPrint("FL----------------Selected>");
|
||||
if (_linkLocations == null) return null;
|
||||
foreach (LinkLocation ll in _linkLocations)
|
||||
if (ll.Start == SelectionStart && ll.Length == SelectionLength) 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 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 Selection Handlers
|
||||
private void HandleSelectionChange()
|
||||
{
|
||||
bool startingValue = _AdjustingSelection;
|
||||
if (_IdentifyingLinks || _ProcessingDelete) return;
|
||||
if (ProcessKeystrokes)
|
||||
{
|
||||
if (!_MouseDown && !_AdjustingSelection)
|
||||
{
|
||||
if (_linkLocations != null)
|
||||
{
|
||||
_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)
|
||||
{
|
||||
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());
|
||||
OnRTBSelectionChanged(this, new EventArgs());
|
||||
}
|
||||
#endregion
|
||||
#region Delete Handlers
|
||||
private void HandleDeleteKeyWithSelectedText(KeyEventArgs e)
|
||||
{
|
||||
_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();
|
||||
e.SuppressKeyPress = true;
|
||||
break;
|
||||
case RangeStatus.Before_Between: //myRTB1.SelectedText.EndsWith(@"[END><START]")
|
||||
DeleteEndBetweenLinks();
|
||||
e.SuppressKeyPress = true;
|
||||
break;
|
||||
case RangeStatus.Between_EndBox:
|
||||
case RangeStatus.Between_EndLink:
|
||||
case RangeStatus.Between_After:
|
||||
DeleteStartBetweenLinks();
|
||||
e.SuppressKeyPress = true;
|
||||
break;
|
||||
case RangeStatus.Between_Between:
|
||||
DeleteBetweenBetweenLinks();
|
||||
e.SuppressKeyPress=true;
|
||||
break;
|
||||
case RangeStatus.StartLink_EndBox:
|
||||
case RangeStatus.StartLink_EndLink:
|
||||
case RangeStatus.StartLink_After:
|
||||
ExpandSelectionToIncludeStart();
|
||||
DeleteCurrentSelection();
|
||||
e.SuppressKeyPress = true;
|
||||
break;
|
||||
case RangeStatus.StartLink_Between:
|
||||
ExpandSelectionToIncludeStart();
|
||||
DeleteEndBetweenLinks();
|
||||
e.SuppressKeyPress = true;
|
||||
break;
|
||||
case RangeStatus.StartBox_EndLink:
|
||||
case RangeStatus.StartBox_EndBox:
|
||||
case RangeStatus.StartBox_After:
|
||||
DeleteFromStartOfBox();
|
||||
e.SuppressKeyPress = true;
|
||||
break;
|
||||
case RangeStatus.StartBox_Between:
|
||||
DeleteFromStartOfBoxEndBetweenLinks();
|
||||
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;
|
||||
MyRTB_TextChanged(this, new EventArgs());
|
||||
}
|
||||
private void InsertCharBetweenLinks(LinkLocation ll)
|
||||
{
|
||||
InsertCharBetweenLinks(ll, ' ', false);
|
||||
}
|
||||
private void InsertCharBetweenLinks(LinkLocation ll, char charToAdd)
|
||||
{
|
||||
InsertCharBetweenLinks(ll, charToAdd, true);
|
||||
}
|
||||
/// <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;
|
||||
}
|
||||
private void DeleteBetweenBetweenLinks()
|
||||
{
|
||||
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();// 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>
|
||||
private void DeleteCurrentSelection()
|
||||
{
|
||||
DebugPrint("vvvvvvvvvvvvxxxxxxxxxxxx>");
|
||||
DebugSelection("Before X");
|
||||
SelectedText = "X"; // replace text with X
|
||||
DebugSelection("After X");
|
||||
DebugPrint("------------xxxxxxxxxxxx>");
|
||||
_SendBackSpace = true;
|
||||
RtbSendKeys("{BS}"); // remove X
|
||||
Application.DoEvents();
|
||||
DebugSelection("After BS");
|
||||
DebugPrint("^^^^^^^^^^^^xxxxxxxxxxxx>");
|
||||
}
|
||||
private void DeleteSelection(int start, int length)
|
||||
{
|
||||
SetSelection(start, length);
|
||||
DeleteCurrentSelection();
|
||||
}
|
||||
private void DeleteEndBetweenLinks()
|
||||
{
|
||||
_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);
|
||||
//_AdjustingSelection = false;
|
||||
_ProcessingKeys--;
|
||||
}
|
||||
private void DeleteStartBetweenLinks()
|
||||
{
|
||||
_ProcessingKeys++;
|
||||
DebugSelection("DeleteStartBetweenLinks");
|
||||
int slen = SelectionLength + 8;
|
||||
int sstart = SelectionStart - 7;
|
||||
//LinkLocation ll = FindBetweenLinks(SelectionStart);
|
||||
InsertCharBetweenLinks(_RangeStartLink);
|
||||
DeleteSelection(sstart, slen);
|
||||
_ProcessingKeys--;
|
||||
}
|
||||
private void DeleteFromStartOfBox()
|
||||
{
|
||||
_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);
|
||||
_ProcessingKeys--;
|
||||
}
|
||||
private void DeleteFromStartOfBoxEndBetweenLinks()
|
||||
{
|
||||
_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);
|
||||
_ProcessingKeys--;
|
||||
}
|
||||
#endregion
|
||||
#region Debug
|
||||
private bool _ShowDebug = true;
|
||||
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
|
||||
#region SendKeys
|
||||
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
|
||||
//DebugSelection(keys);
|
||||
}
|
||||
#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;
|
||||
private 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 (startLink != null)
|
||||
// startLink.Show("startLink");
|
||||
//if (endLink != null)
|
||||
// endLink.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 LinkLocation
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
}
|
Reference in New Issue
Block a user