2023-11-21 23:05:03 +08:00

525 lines
21 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Text.RegularExpressions;
namespace ST.Library.UI.STTextBox
{
public partial class STTextBox
{
protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
switch (keyData) {
case Keys.Back:
this.ProcessBackSpaceKey();
return true;
case Keys.Tab:
this.ProcessTabKey();
return true;
case Keys.Enter:
this.ProcessEnter();
return true;
//========================================================
case Keys.Left:
this.ProcessLeftKey(false);
return true;
case Keys.Right:
this.ProcessRightKey(false);
return true;
case Keys.Up:
this.ProcessUpKey(false);
return true;
case Keys.Down:
this.ProcessDownKey(false);
return true;
case Keys.Home:
this.ProcessHomeKey(false);
return true;
case Keys.End:
this.ProcessEndKey(false);
return true;
case Keys.PageUp:
this.ProcessPageUpKey(false);
return true;
case Keys.PageDown:
this.ProcessPageDownKey(false);
return true;
//========================================================
case Keys.Shift | Keys.Tab:
this.ProcessShiftTabKey();
return true;
case Keys.Shift | Keys.Up:
this.ProcessUpKey(true);
return true;
case Keys.Shift | Keys.Down:
this.ProcessDownKey(true);
return true;
case Keys.Shift | Keys.Left:
this.ProcessLeftKey(true);
return true;
case Keys.Shift | Keys.Right:
this.ProcessRightKey(true);
return true;
case Keys.Shift | Keys.Home:
this.ProcessHomeKey(true);
return true;
case Keys.Shift | Keys.End:
this.ProcessEndKey(true);
return true;
case Keys.Shift | Keys.PageUp:
this.ProcessPageUpKey(true);
return true;
case Keys.Shift | Keys.PageDown:
this.ProcessPageDownKey(true);
return true;
//========================================================
case Keys.Control | Keys.A:
this.SelectAll();
return true;
case Keys.Control | Keys.C:
this.Copy();
return true;
case Keys.Control | Keys.X:
this.Cut();
return true;
case Keys.Control | Keys.V:
this.Paste();
return true;
case Keys.Control | Keys.Z:
this.Undo();
return true;
case Keys.Control | Keys.Y:
this.Redo();
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
protected override void OnKeyPress(KeyPressEventArgs e) {
base.OnKeyPress(e);
if (e.KeyChar < 32/* || e.KeyChar > 126*/) {
return;
}
this.EnterText(e.KeyChar.ToString());
}
//==================================================================================
private void ProcessEnter() {
var c = m_core;
string strText = "\r\n";
if (this._AutoIndent) {
strText += Regex.Match(
c.TextManager[c.TextManager.GetLineIndexFromCharIndex(c.Caret.IndexOfChar)].RawString,
@"^[ \t]+" //Space,TAB
).Value;
}
this.EnterText(strText);
}
private void ProcessTabKey() {
var c = m_core;
int nIndexStartLine = 0, nIndexEndLine = 0;
if (!c.Selection.IsEmptySelection) {
nIndexStartLine = c.TextManager.GetLineIndexFromCharIndex(c.Selection.StartIndex);
nIndexEndLine = c.TextManager.GetLineIndexFromCharIndex(c.Selection.EndIndex);
}
if (nIndexStartLine == nIndexEndLine) {
if (!this._TabToSpace) {
this.EnterText("\t");
} else {
float fSpaceCount = c.ITextBoxRender.GetTabSpaceCount(c.ITextView.GetCurrentCharOffset(), this._TabSize);
this.EnterText("".PadLeft((int)Math.Ceiling(fSpaceCount)));
}
} else {
string strInsert = this._TabToSpace ? "".PadLeft(this._TabSize) : "\t";
var histories = c.TextManager.InsertAtStart(nIndexStartLine, nIndexEndLine - nIndexStartLine + 1, strInsert);
c.ITextHistory.SetHistory(histories);
var lineStart = c.TextManager[nIndexStartLine];
var lineEnd = c.TextManager[nIndexEndLine];
c.Selection.SetSelection(lineStart.IndexOfFirstChar, lineEnd.IndexOfFirstChar + lineEnd.GetLengthWithoutNewline());
c.Caret.IndexOfChar = c.Selection.EndIndex;
c.ITextView.SetCaretPostion(c.Caret.IndexOfChar);
}
}
private void ProcessShiftTabKey() {
var c = m_core;
int nIndexStartLine = 0, nIndexEndLine = 0;
nIndexStartLine = c.TextManager.GetLineIndexFromCharIndex(c.Selection.StartIndex);
nIndexEndLine = c.TextManager.GetLineIndexFromCharIndex(c.Selection.EndIndex);
if (nIndexStartLine == nIndexEndLine) {
var line = c.TextManager[nIndexStartLine];
for (int i = 0; i < line.RawString.Length; i++) {
switch (line.RawString[i]) {
case ' ':
case '\t':
continue;
default:
break;
}
if (i == 0 || i + line.IndexOfFirstChar < c.Selection.StartIndex) {
return;
}
}
}
var histories = c.TextManager.TrimStartTab(nIndexStartLine, nIndexEndLine - nIndexStartLine + 1, this._TabSize);
c.ITextHistory.SetHistory(histories.ToArray());
var lineStart = c.TextManager[nIndexStartLine];
var lineEnd = c.TextManager[nIndexEndLine];
c.Selection.SetSelection(lineStart.IndexOfFirstChar, lineEnd.IndexOfFirstChar + lineEnd.GetLengthWithoutNewline());
c.Caret.IndexOfChar = c.Selection.EndIndex;
c.ITextView.SetCaretPostion(c.Caret.IndexOfChar);
}
private void ProcessBackSpaceKey() {
var c = m_core;
if (c.Caret.IndexOfChar == 0 && c.Selection.IsEmptySelection) {
return;
}
if (c.Selection.IsEmptySelection) {
//c.Selection.SetIndex(c.Caret.IndexOfChar);
int nLineIndex = c.TextManager.GetLineIndexFromCharIndex(c.Caret.IndexOfChar);
TextLine stLine = c.TextManager[nLineIndex];
if (c.Caret.IndexOfChar == stLine.IndexOfFirstChar) {//if the index is the line start index
stLine = c.TextManager[nLineIndex - 1];
//c.Selection.StartIndex -= stLine.RawString.Length - stLine.GetLengthWithoutNewline();
c.Selection.SetSelection(c.Caret.IndexOfChar, c.Caret.IndexOfChar - (stLine.RawString.Length - stLine.GetLengthWithoutNewline()));
} else {
int nIndex = stLine.IndexOfFirstChar;
c.IGraphemeSplitter.Each(stLine.RawString, (str, nStart, nLen) => {
if (nIndex + nLen >= c.Caret.IndexOfChar) {
return false;
}
nIndex += nLen;
return true;
});
//c.Selection.StartIndex = nIndex;
c.Selection.SetSelection(nIndex, c.Caret.IndexOfChar);
}
}
this.EnterText("");
}
private void ProcessUpKey(bool bShiftDown) {
var c = m_core;
if (c.Scroll.YValue == 0 && c.Caret.Y - m_core.ViewRectangle.Y < m_core.LineHeight) {
return;
}
c.Caret.Y -= c.LineHeight;// c.ITextRender.GetFontHeight();
var fi = c.ITextView.FindFromPoint(c.Caret.Location);
if (!c.Caret.CopyFromFindInfo(fi)) {
return;
}
bool bRedraw = false;
if (bShiftDown) {
c.Selection.SetSelection(c.Caret.IndexOfChar);
bRedraw = true;
} else {
if (!c.Selection.IsEmptySelection) {
bRedraw = true;
c.Caret.IndexOfChar = c.Selection.StartIndex;
}
c.Selection.SetIndex(c.Caret.IndexOfChar);
}
c.ITextView.SetCaretPostion(c.Caret.IndexOfChar);
if (c.ITextView.ScrollToCaret() || bRedraw) {
this.Invalidate();
}
}
private void ProcessDownKey(bool bShiftDown) {
var c = m_core;
if (c.Caret.IndexOfLine >= c.TextManager.LineCount - 1) {
//return;
}
c.Caret.Y += c.LineHeight;// c.ITextRender.GetFontHeight();
var fi = c.ITextView.FindFromPoint(c.Caret.Location);
if (!c.Caret.CopyFromFindInfo(fi)) {
return;
}
bool bRedraw = false;
if (bShiftDown) {
c.Selection.SetSelection(c.Caret.IndexOfChar);
bRedraw = true;
} else {
if (!c.Selection.IsEmptySelection) {
bRedraw = true;
c.Caret.IndexOfChar = c.Selection.EndIndex;
}
c.Selection.SetIndex(c.Caret.IndexOfChar);
}
c.ITextView.SetCaretPostion(c.Caret.IndexOfChar);
if (c.ITextView.ScrollToCaret() || bRedraw) {
this.Invalidate();
}
}
private void ProcessLeftKey(bool bShiftDown) {
var c = m_core;
bool bRedraw = false;
if (bShiftDown) {
var nIndex = c.TextBox.FindLeftIndex(c.Caret.IndexOfChar);
if (nIndex == c.Caret.IndexOfChar) {
return;
}
c.Caret.IndexOfChar = nIndex;
c.Selection.SetSelection(c.Caret.IndexOfChar);
bRedraw = true;
} else {
if (!c.Selection.IsEmptySelection) {
bRedraw = true;
c.Caret.IndexOfChar = c.Selection.StartIndex;
} else {
var nIndex = c.TextBox.FindLeftIndex(c.Caret.IndexOfChar);
if (nIndex == c.Caret.IndexOfChar) {
return;
}
c.Caret.IndexOfChar = nIndex;
}
c.Selection.SetIndex(c.Caret.IndexOfChar);
}
c.ITextView.SetCaretPostion(c.Caret.IndexOfChar);
if (c.ITextView.ScrollToCaret() || bRedraw) {
this.Invalidate();
}
}
private void ProcessRightKey(bool bShiftDown) {
var c = m_core;
bool bRedraw = false;
if (bShiftDown) {
var nIndex = c.TextBox.FindRightIndex(c.Caret.IndexOfChar);
if (nIndex == c.Caret.IndexOfChar) {
return;
}
c.Caret.IndexOfChar = nIndex;
c.Selection.SetSelection(nIndex);
bRedraw = true;
} else {
if (!c.Selection.IsEmptySelection) {
bRedraw = true;
c.Caret.IndexOfChar = c.Selection.EndIndex;
} else {
var nIndex = c.TextBox.FindRightIndex(c.Caret.IndexOfChar);
if (nIndex == c.Caret.IndexOfChar) {
return;
}
c.Caret.IndexOfChar = nIndex;
}
c.Selection.SetIndex(c.Caret.IndexOfChar);
}
c.ITextView.SetCaretPostion(c.Caret.IndexOfChar);
if (c.ITextView.ScrollToCaret() || bRedraw) {
this.Invalidate();
}
}
private void ProcessHomeKey(bool bShiftDown) {
var c = m_core;
bool bRedraw = false;
var stLine = c.TextManager.GetLineFromCharIndex(c.Caret.IndexOfChar);
c.Caret.IndexOfChar = stLine.IndexOfFirstChar;
if (bShiftDown) {
c.Selection.SetSelection(c.Caret.IndexOfChar);
bRedraw = true;
} else {
if (!c.Selection.IsEmptySelection) {
bRedraw = true;
}
c.Selection.SetIndex(c.Caret.IndexOfChar);
}
c.ITextView.SetCaretPostion(c.Caret.IndexOfChar);
if (c.ITextView.ScrollToCaret() || bRedraw) {
this.Invalidate();
}
}
private void ProcessEndKey(bool bShiftDown) {
var c = m_core;
bool bRedraw = false;
var stLine = c.TextManager.GetLineFromCharIndex(c.Caret.IndexOfChar);
//c.Caret.IndexOfChar = stLine.IndexOfFirstChar + stLine.RawString.Length;
c.Caret.IndexOfChar = stLine.IndexOfFirstChar + stLine.GetLengthWithoutNewline();
if (bShiftDown) {
c.Selection.SetSelection(c.Caret.IndexOfChar);
bRedraw = true;
} else {
if (!c.Selection.IsEmptySelection) {
bRedraw = true;
}
c.Selection.SetIndex(c.Caret.IndexOfChar);
}
c.ITextView.SetCaretPostion(c.Caret.IndexOfChar);
if (c.ITextView.ScrollToCaret() || bRedraw) {
this.Invalidate();
}
}
private void ProcessPageUpKey(bool bShiftDown) {
var c = m_core;
if (c.Scroll.YValue == 0) {
return;
}
int nCurrentLineCount = this.Height / c.LineHeight;
c.Scroll.YValue -= nCurrentLineCount;
if (c.Scroll.YValue < 0) {
c.Scroll.YValue = 0;
c.Caret.Y = 0;
}
var fi = c.ITextView.SetCaretPostion(c.Caret.Location);// c.ITextView.FindFromPoint(c.Caret.Location);
if (!fi.Find) {
return;
}
//c.Caret.CopyFromFindInfo(fi);
if (bShiftDown) {
c.Selection.SetSelection(c.Caret.IndexOfChar);
} else {
if (!c.Selection.IsEmptySelection) {
c.Selection.SetIndex(c.Caret.IndexOfChar);
this.Invalidate();
} else {
c.Selection.SetIndex(c.Caret.IndexOfChar);
}
}
//c.ITextView.SetCaretPostion(c.Caret.X, c.Caret.Y);
this.Invalidate();
}
private void ProcessPageDownKey(bool bShiftDown) {
var c = m_core;
if (c.Scroll.YValue == c.Scroll.MaxYValue) {
return;
}
int nCurrentLineCount = this.Height / c.LineHeight;
c.Scroll.YValue += nCurrentLineCount;
if (c.Scroll.YValue > c.Scroll.MaxYValue) {
c.Scroll.YValue = c.Scroll.MaxYValue;
}
var fi = c.ITextView.SetCaretPostion(c.Caret.Location);// c.ITextView.FindFromPoint(c.Caret.Location);
if (!fi.Find) {
return;
}
//c.Caret.CopyFromFindInfo(fi);
if (bShiftDown) {
c.Selection.SetSelection(c.Caret.IndexOfChar);
} else {
if (!c.Selection.IsEmptySelection) {
c.Selection.SetIndex(c.Caret.IndexOfChar);
this.Invalidate();
} else {
c.Selection.SetIndex(c.Caret.IndexOfChar);
}
}
//c.ITextView.SetCaretPostion(c.Caret.X, c.Caret.Y);
this.Invalidate();
}
private void EnterText(string strText) {
var c = m_core;
var history = c.TextManager.SetText(c.Selection.StartIndex, c.Selection.Length, strText);
if (history != TextHistoryRecord.Empty) {
c.ITextHistory.SetHistory(new TextHistoryRecord[] { history });
}
c.Caret.IndexOfChar = c.Selection.StartIndex + strText.Length;
c.ITextView.SetCaretPostion(c.Caret.IndexOfChar);
c.Selection.SetIndex(c.Caret.IndexOfChar);
c.ITextView.ScrollToCaret();
//this.Invalidate();
}
//==================================================
private int FindRightIndex(int nIndex) {
var c = m_core;
if (nIndex >= c.TextManager.TextLength) {
return c.TextManager.TextLength;
}
int nLineIndex = c.TextManager.GetLineIndexFromCharIndex(nIndex);
var line = c.TextManager[nLineIndex];
c.IGraphemeSplitter.Each(line.RawString, nIndex - line.IndexOfFirstChar, (str, nStart, nLen) => {
nIndex += nLen;
return false;
});
return nIndex;
}
//private FindInfo FindRightChar(int nIndex) {
// //TODO: add location for return;
// var c = m_core;
// if (nIndex >= c.TextManager.TextLength) {
// return FindInfo.Empty;
// }
// int nLineIndex = c.TextManager.GetLineIndexFromCharIndex(nIndex);
// var line = c.TextManager[nLineIndex];
// c.IGraphemeSplitter.Each(line.RawString, nIndex - line.IndexOfFirstChar, (str, nStart, nLen) => {
// nIndex += nLen;
// return false;
// });
// return new FindInfo() {
// Find = true,
// Line = line,
// IndexOfCharInLine = nIndex - line.IndexOfFirstChar,
// IndexOfLine = nLineIndex,
// };
//}
public int FindLeftIndex(int nIndex) {
var c = m_core;
if (nIndex <= 1) return 0;
int nLineIndex = c.TextManager.GetLineIndexFromCharIndex(nIndex);
TextLine line = c.TextManager[nLineIndex];
if (nIndex == line.IndexOfFirstChar) {
line = c.TextManager[--nLineIndex];
if (line.RawString.Length > 1 && line.RawString[line.RawString.Length - 2] == '\r') {
nIndex -= 2;
} else {
nIndex -= 1;
}
} else {
int nIndexRet = line.IndexOfFirstChar;
c.IGraphemeSplitter.Each(line.RawString, (str, nStart, nLen) => {
if (nIndexRet + nLen >= nIndex) {
return false;
}
nIndexRet += nLen;
return true;
});
nIndex = nIndexRet;
}
return nIndex;
}
//private FindInfo FindLeftChar(int nIndex) {
// //TODO: add location for return;
// var c = m_core;
// if (nIndex <= 1) return new FindInfo() {
// Find = true,
// Line = c.TextManager[0]
// };
// int nLineIndex = c.TextManager.GetLineIndexFromCharIndex(nIndex);
// TextLine line = c.TextManager[nLineIndex];
// if (nIndex == line.IndexOfFirstChar) {
// line = c.TextManager[--nLineIndex];
// if (line.RawString.Length > 1 && line.RawString[line.RawString.Length - 2] == '\r') {
// nIndex -= 2;
// } else {
// nIndex -= 1;
// }
// } else {
// int nIndexRet = line.IndexOfFirstChar;
// c.IGraphemeSplitter.Each(line.RawString, (str, nStart, nLen) => {
// if (nIndexRet + nLen >= nIndex) {
// return false;
// }
// nIndexRet += nLen;
// return true;
// });
// nIndex = nIndexRet;
// }
// return new FindInfo() {
// Find = true,
// Line = line,
// IndexOfCharInLine = nIndex - line.IndexOfFirstChar,
// IndexOfLine = nLineIndex
// };
//}
}
}