LSLEditor/trunk/Editor/SyntaxRichTextBox.cs

2261 lines
61 KiB
C#

// /**
// ********
// *
// * ORIGINAL CODE BASE IS Copyright (C) 2006-2010 by Alphons van der Heijden
// * The code was donated on 4/28/2010 by Alphons van der Heijden
// * To Brandon 'Dimentox Travanti' Husbands & Malcolm J. Kudra, who in turn License under the GPLv2.
// * In agreement with Alphons van der Heijden's wishes.
// *
// * The community would like to thank Alphons for all of his hard work, blood sweat and tears.
// * Without his work the community would be stuck with crappy editors.
// *
// * The source code in this file ("Source Code") is provided by The LSLEditor Group
// * to you under the terms of the GNU General Public License, version 2.0
// * ("GPL"), unless you have obtained a separate licensing agreement
// * ("Other License"), formally executed by you and The LSLEditor Group. Terms of
// * the GPL can be found in the gplv2.txt document.
// *
// ********
// * GPLv2 Header
// ********
// * LSLEditor, a External editor for the LSL Language.
// * Copyright (C) 2010 The LSLEditor Group.
//
// * This program is free software; you can redistribute it and/or
// * modify it under the terms of the GNU General Public License
// * as published by the Free Software Foundation; either version 2
// * of the License, or (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// *
// * You should have received a copy of the GNU General Public License
// * along with this program; if not, write to the Free Software
// * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
// ********
// *
// * The above copyright notice and this permission notice shall be included in all
// * copies or substantial portions of the Software.
// *
// ********
// */
using System;
using System.IO;
using System.Xml;
using System.Text;
using System.Drawing;
using System.Collections.Generic;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing.Printing;
using System.Text.RegularExpressions;
using System.Runtime.InteropServices;
using System.Diagnostics;
using LSLEditor.Helpers;
namespace LSLEditor
{
public delegate void IsDirtyHandler(object sender, EventArgs e);
public class SyntaxRichTextBox : RichTextBox
{
private const int WM_SETREDRAW = 0x000B;
private const int WM_USER = 0x400;
private const int EM_GETEVENTMASK = (WM_USER + 59);
private const int EM_SETEVENTMASK = (WM_USER + 69);
// Scroll position
[DllImport("user32.dll")]
private static extern int SendMessage(IntPtr hwndLock, Int32 wMsg, Int32 wParam, ref Point pt);
// Anti flicker
[DllImport("user32", CharSet = CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, IntPtr lParam);
// Tabs
[DllImport("User32", CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(IntPtr h, int msg, int wParam, int[] lParam);
private bool m_Dirty;
private bool blnEscape;
private bool blnInsert;
// for tooltipping
private bool m_blnToolTipping;
private System.Windows.Forms.Timer timer1;
private GListBoxWindow GListBoxWindow;
private TooltipWindow TooltipMouse;
private TooltipWindow TooltipKeyboard;
private TooltipWindow TooltipListBox;
private Point OldMouseLocation;
private int intKeyWordLength;
// needed for flicker-free updates
private int intUpdate;
private IntPtr eventMask;
private int intOldLines;
// colored words
private KeyWords keyWords;
private Helpers.CodeCompletion codeCompletion;
// after clicking on error
private int HighLightLine;
// bracket highlighting
private List<int> HighLightList;
public EditForm p;
public float CharWidth;
public int LineHeight;
// undo
private struct UndoElement
{
public int SelectionStart;
public int SelectionLength;
public string SelectedText;
public string RedoText;
public UndoElement(int SelectionStart, string SelectedText, int SelectionLength, string RedoText)
{
this.SelectionStart = SelectionStart;
this.SelectionLength = SelectionLength;
this.SelectedText = SelectedText;
this.RedoText = RedoText;
}
}
private Stack<UndoElement> UndoStack;
private Stack<UndoElement> RedoStack;
#region printing
//Convert the unit used by the .NET framework (1/100 inch)
//and the unit used by Win32 API calls (twips 1/1440 inch)
private const double anInch = 14.4;
[StructLayout(LayoutKind.Sequential)]
private struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
[StructLayout(LayoutKind.Sequential)]
private struct CHARRANGE
{
public int cpMin; //First character of range (0 for start of doc)
public int cpMax; //Last character of range (-1 for end of doc)
}
[StructLayout(LayoutKind.Sequential)]
private struct FORMATRANGE
{
public IntPtr hdc; //Actual DC to draw on
public IntPtr hdcTarget; //Target DC for determining text formatting
public RECT rc; //Region of the DC to draw to (in twips)
public RECT rcPage; //Region of the whole DC (page size) (in twips)
public CHARRANGE chrg; //Range of text to draw (see earlier declaration)
}
private const int EM_FORMATRANGE = WM_USER + 57;
[DllImport("user32", CharSet = CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
// Render the contents of the RichTextBox for printing
// Return the last character printed + 1 (printing start from this point for next page)
public int Print(int charFrom, int charTo, PrintPageEventArgs e)
{
//Calculate the area to render and print
RECT rectToPrint;
rectToPrint.Top = (int)(e.MarginBounds.Top * anInch);
rectToPrint.Bottom = (int)(e.MarginBounds.Bottom * anInch);
rectToPrint.Left = (int)(e.MarginBounds.Left * anInch);
rectToPrint.Right = (int)(e.MarginBounds.Right * anInch);
//Calculate the size of the page
RECT rectPage;
rectPage.Top = (int)(e.PageBounds.Top * anInch);
rectPage.Bottom = (int)(e.PageBounds.Bottom * anInch);
rectPage.Left = (int)(e.PageBounds.Left * anInch);
rectPage.Right = (int)(e.PageBounds.Right * anInch);
IntPtr hdc = e.Graphics.GetHdc();
FORMATRANGE fmtRange;
fmtRange.chrg.cpMax = charTo; //Indicate character from to character to
fmtRange.chrg.cpMin = charFrom;
fmtRange.hdc = hdc; //Use the same DC for measuring and rendering
fmtRange.hdcTarget = hdc; //Point at printer hDC
fmtRange.rc = rectToPrint; //Indicate the area on page to print
fmtRange.rcPage = rectPage; //Indicate size of page
IntPtr wparam = new IntPtr(1);
//Get the pointer to the FORMATRANGE structure in memory
IntPtr lparam = Marshal.AllocCoTaskMem(Marshal.SizeOf(fmtRange));
Marshal.StructureToPtr(fmtRange, lparam, false);
//Send the rendered data for printing
IntPtr res = SendMessage(Handle, EM_FORMATRANGE, wparam, lparam);
//Free the block of memory allocated
Marshal.FreeCoTaskMem(lparam);
//Release the device context handle obtained by a previous call
e.Graphics.ReleaseHdc(hdc);
//Return last + 1 character printer
return res.ToInt32();
}
#endregion
public event IsDirtyHandler OnDirtyChanged;
public event EventHandler OnPaintNumbers;
public delegate void CursorPositionChangedHandler(object sender, CursorPositionEventArgs e);
public event CursorPositionChangedHandler OnCursorPositionChanged;
public class CursorPositionEventArgs : EventArgs
{
public int Line;
public int Column;
public int Char;
public int Total;
public bool Insert;
public bool Caps;
public CursorPositionEventArgs(int intLine, int intColumn, int intChar, int intTotal, bool blnInsert, bool blnCaps)
{
this.Line = intLine;
this.Column = intColumn;
this.Char = intChar;
this.Total = intTotal;
this.Insert = blnInsert;
this.Caps = blnCaps;
}
}
public SyntaxRichTextBox()
{
this.intUpdate = 0;
this.eventMask = IntPtr.Zero;
this.m_blnToolTipping = false;
this.intKeyWordLength = 0;
this.AcceptsTab = true;
this.BorderStyle = BorderStyle.None;
this.DetectUrls = false;
this.Dirty = false;
this.ScrollBars = RichTextBoxScrollBars.ForcedBoth;
this.WordWrap = false;
this.FontChanged += new EventHandler(SyntaxRichTextBox_FontChanged);
this.MouseMove += new MouseEventHandler(SyntaxRichTextBox_MouseMove);
this.VScroll += new EventHandler(SyntaxRichTextBox_Position);
this.HScroll += new EventHandler(SyntaxRichTextBox_Position);
this.HighLightLine = -1;
this.HighLightList = new List<int>();
this.UndoStack = new Stack<UndoElement>();
this.RedoStack = new Stack<UndoElement>();
this.blnEscape = false;
this.blnInsert = true;
this.intOldLines = -1;
this.CharWidth = 10; //TODO
this.LineHeight = 16;
this.OldMouseLocation = Point.Empty;
this.codeCompletion = new Helpers.CodeCompletion();
this.HideSelection = false;
// are these of any use?
//this.DoubleBuffered = true;
//SetStyle(ControlStyles.AllPaintingInWmPaint, true);
//SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
//SetStyle(ControlStyles.Opaque, true);
}
public void setEditform(EditForm ed)
{
p = ed;
}
public void Init(LSLEditorForm parent, XmlDocument xml)
{
if (parent != null)
{
this.ToolTipping = true;
this.GListBoxWindow = parent.GListBoxWindow;
this.TooltipMouse = parent.TooltipMouse;
this.TooltipKeyboard = parent.TooltipKeyboard;
this.TooltipListBox = parent.TooltipListBox;
// p = this.Parent as EditForm;
// p = parent; moved to edit form
}
string ColorScheme = "color";
if (this.ToolTipping)
{
if (Properties.Settings.Default.SLColorScheme)
{
ColorScheme = "sl" + ColorScheme;
}
XmlNode BackgroundColorNode = xml.SelectSingleNode("/Conf");
if (BackgroundColorNode != null)
{
Color bgColor = Color.FromArgb(255, Color.FromArgb(int.Parse(BackgroundColorNode.Attributes[ColorScheme].InnerText.Replace("#", ""), System.Globalization.NumberStyles.HexNumber)));
this.BackColor = bgColor;
}
}
keyWords = new KeyWords(ColorScheme, xml);
}
private void MeasureFont()
{
Size size = TextRenderer.MeasureText("MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM", this.Font);
CharWidth = (int)(size.Width / 50.0F);
LineHeight = size.Height;
}
void SyntaxRichTextBox_FontChanged(object sender, EventArgs e)
{
this.SelectAll();
TabStops();
// recolor all
ColorLine(0, this.Text.Length);
}
private void TabStops()
{
MeasureFont();
const int EM_SETTABSTOPS = 0xCB;
int intNumberOfChars = Properties.Settings.Default.TabStops;
int[] tabs = new int[30]; // TODO
float fltTabWidth = intNumberOfChars * CharWidth;
float totalWidth = 0.0F;
for (int intI = 0; intI < tabs.Length; intI++)
{
totalWidth += fltTabWidth;
tabs[intI] = (int)totalWidth;
}
SendMessage(this.Handle, EM_SETTABSTOPS, 0, null);
SendMessage(this.Handle, EM_SETTABSTOPS, tabs.Length, tabs);
this.SelectionTabs = tabs;
}
private void PaintNumbers()
{
if (OnPaintNumbers != null)
OnPaintNumbers(null, null);
}
protected override void OnVScroll(EventArgs e)
{
base.OnVScroll(e);
PaintNumbers();
}
private Point RTBScrollPos
{
get
{
const int EM_GETSCROLLPOS = 0x0400 + 221;
Point pt = new Point();
SendMessage(this.Handle, EM_GETSCROLLPOS, 0, ref pt);
return pt;
}
set
{
const int EM_SETSCROLLPOS = 0x0400 + 222;
SendMessage(this.Handle, EM_SETSCROLLPOS, 0, ref value);
}
}
public bool Dirty
{
get
{
return m_Dirty;
}
set
{
if (this.m_Dirty == value)
return;
this.m_Dirty = value;
if (OnDirtyChanged == null)
return;
OnDirtyChanged(this, new EventArgs());
}
}
private void SyntaxRichTextBox_Position(object sender, EventArgs e)
{
SetPosition(Screen.GetWorkingArea(this));
}
private void SyntaxRichTextBox_MouseMove(object sender, MouseEventArgs e)
{
if (!ToolTipping)
return;
if (this.timer1 == null)
return;
this.timer1.Stop();
if (OldMouseLocation != e.Location)
{
OldMouseLocation = e.Location;
this.timer1.Start();
}
}
private int GetLine()
{
return 1 + this.GetLineFromCharIndex(this.SelectionStart);
}
private int GetChar()
{
return 1 + this.SelectionStart - this.GetFirstCharIndexOfCurrentLine();
}
private int GetColumn()
{
Point p1 = this.GetPositionFromCharIndex(this.GetFirstCharIndexOfCurrentLine());
Point p2 = this.GetPositionFromCharIndex(this.SelectionStart);
int intColumn = (int)((p2.X - p1.X) / this.CharWidth);
return 1+ intColumn;
}
private int GetTotal()
{
return this.Text.Length;
}
public void Goto(int Line, int Char)
{
BeginUpdate();
LineDownlighting();
try
{
int intLine = Line - 1;
if (intLine < 0)
intLine = 0;
if (intLine >= this.Lines.Length)
intLine = this.Lines.Length - 1;
if (intLine >= 0 && intLine < this.Lines.Length)
{
int intLength = this.Lines[intLine].Length;
int intStart = GetFirstCharIndexFromLine(intLine);
int intIndex = intStart + Char - 1;
HighLightLine = intLine;
this.SelectionStart = intStart;
this.SelectionLength = intLength;
this.SelectionBackColor = Color.LightBlue;
this.SelectionLength = 0;
this.SelectionStart = intIndex;
}
}
catch
{
}
EndUpdate(false);
this.Focus();
}
protected override void OnSelectionChanged(EventArgs e)
{
base.OnSelectionChanged(e);
if (!IsUpdating)
CursorPositionChanged(); // show cursor position
}
private bool IsUpdating
{
get
{
return (intUpdate > 0);
}
}
Point backupScrollPoint;
private void BeginUpdate()
{
++intUpdate;
if (intUpdate > 1) // once is enough
return;
backupScrollPoint = this.RTBScrollPos;
// Disable redrawing
SendMessage(this.Handle, WM_SETREDRAW, 0, IntPtr.Zero);
// Disable generating events
eventMask = SendMessage(this.Handle, EM_GETEVENTMASK, 0, IntPtr.Zero);
}
private void EndUpdate(bool update_outline)
{
if(update_outline) doOutline();
intUpdate = Math.Max(0, intUpdate - 1);
if (intUpdate > 0) // only the last one
return;
// Enable events
SendMessage(this.Handle, EM_SETEVENTMASK, 0, eventMask);
// Enable redrawing
SendMessage(this.Handle, WM_SETREDRAW, 1, IntPtr.Zero);
// also draw when linenumbers are shifted
if (intOldLines != this.Lines.Length || backupScrollPoint != this.RTBScrollPos)
{
intOldLines = this.Lines.Length;
PaintNumbers();
}
Invalidate();
}
private bool IsAlpha(char chrC)
{
return (char.IsLetterOrDigit(chrC) || chrC == '_');
}
// used for F1 key, help and tooltipping, use Mouse of begin-selection
public string GetCurrentKeyWord(bool blnUserMousePosition, out Point PositionFirstCharacter)
{
PositionFirstCharacter = Point.Empty;
int intIndex = this.SelectionStart;
if (blnUserMousePosition)
{
Point mp = this.PointToClient(Control.MousePosition);
intIndex = this.GetCharIndexFromPosition(mp);
// check if mouse is in region of index
Point mpControle = this.GetPositionFromCharIndex(intIndex);
if (Math.Abs(mp.X - mpControle.X) > 5 || Math.Abs(mp.Y - mpControle.Y) > this.LineHeight)
return "";
}
int intLineNr = this.GetLineFromCharIndex(intIndex);
int intFirstChar = this.GetFirstCharIndexFromLine(intLineNr);
int intColumn = intIndex - intFirstChar;
string strLine = this.Lines[intLineNr];
int intStart = intColumn;
while ((intStart > 0) && (IsAlpha(strLine[intStart - 1])))
intStart--;
// 22 jun 2007
PositionFirstCharacter = this.GetPositionFromCharIndex(intFirstChar + intStart + 2);
int intEnd = intColumn;
while ((intEnd < strLine.Length) && (IsAlpha(strLine[intEnd])))
intEnd++;
// Calculate the length of the keyword.
int intLength = intEnd - intStart;
// return the keyword
return strLine.Substring(intStart, intLength);
}
private string GetCurrentFunction(out int Argument, out bool DoWild)
{
DoWild = false;
Argument = 0;
int intIndex = this.SelectionStart;
int intLineNumber = this.GetLineFromCharIndex(intIndex);
int intStartChar = this.GetFirstCharIndexFromLine(intLineNumber);
int intColumn = intIndex - intStartChar;
string strLine = this.Lines[intLineNumber];
// Find the end of the current function
int intEnd = intColumn - 1;
while (intEnd > 0 &&
strLine[intEnd] != '(' &&
strLine[intEnd] != ')' &&
strLine[intEnd] != '\n')
{
if (strLine[intEnd] == ',')
{
Argument++;
if (Argument == 1)
DoWild = (intColumn - intEnd) == 1;
}
intEnd--;
}
if (intEnd <= 0)
return "";
if (strLine[intEnd] != '(')
return "";
if (Argument == 0)
DoWild = (intColumn - intEnd) == 1;
intEnd--;
// Find the begin of the current function.
int intStart = intEnd;
while ((intStart > 0) && (IsAlpha(strLine[intStart])))
intStart--;
// Calculate the length of the function.
int intLength = intEnd - intStart;
// return the Function name
return strLine.Substring(intStart + 1, intLength);
}
private string GetNewWhiteSpace(int intOffset)
{
int intIndex = this.GetLineFromCharIndex(this.SelectionStart);
return AutoFormatter.GetNewWhiteSpace(this.Lines, intIndex + intOffset);
}
private void AutoFormatFromLineToLine(int intLineStart, int intLineEnd)
{
BeginUpdate();
int intStart = this.GetFirstCharIndexFromLine(intLineStart);
int intLength = this.GetFirstCharIndexFromLine(intLineEnd) +
this.Lines[intLineEnd].Length + 1 - intStart;
this.SelectionStart = intStart;
this.SelectionLength = intLength;
AutoFormat(true);
EndUpdate(true);
}
private void ProcessEnter()
{
BeginUpdate();
this.ColoredText = "\n";
if (ToolTipping)
{
if (Properties.Settings.Default.Indent)
{
if (Properties.Settings.Default.IndentFullAuto)
{
int intLine = this.GetLineFromCharIndex(this.SelectionStart);
AutoFormatFromLineToLine(intLine - 1, intLine - 1);
this.ColoredText = GetNewWhiteSpace(-1);
}
else if (Properties.Settings.Default.IndentCursorPlacement)
{
this.ColoredText = GetNewWhiteSpace(-1);
}
}
}
EndUpdate(true);
}
private void SmartIndenting()
{
int intFirstLine, intC;
int intLastLine = this.GetLineFromCharIndex(this.SelectionStart);
int intColumn = this.SelectionStart - this.GetFirstCharIndexFromLine(intLastLine);
intColumn--; // because we are at position '}'
if (MatchingBracket(intLastLine, intColumn, '}', '{', -1, out intFirstLine, out intC))
{
if ((intLastLine - intFirstLine) >= 1)
AutoFormatFromLineToLine(intFirstLine + 1, intLastLine);
}
}
private void ProcessBraces(char keyChar)
{
BeginUpdate();
int intStart = this.SelectionStart;
this.ColoredText = keyChar.ToString();
if (Properties.Settings.Default.Indent)
{
int intLength = this.Text.Length;
if (Properties.Settings.Default.IndentFullAuto)
{
if (keyChar == '}')
{
SmartIndenting();
}
else
{
int intCurrentLine = this.GetLineFromCharIndex(this.SelectionStart);
AutoFormatFromLineToLine(intCurrentLine, intCurrentLine);
}
}
int intDelta = 1 + this.Text.Length - intLength;
this.SelectionStart = intStart + intDelta;
BracketHighlichting();
}
EndUpdate(false);
}
public void Delete()
{
BeginUpdate();
if (this.SelectionLength == 0)
this.SelectionLength = 1;
this.ColoredText = "";
EndUpdate(true);
OnTextChanged(null);
}
public new void Cut()
{
BeginUpdate();
this.Copy();
this.ColoredText = "";
EndUpdate(true);
OnTextChanged(null);
}
private void SaveUndo(UndoElement el)
{
if (RedoStack.Count > 0)
RedoStack.Clear();
UndoStack.Push(el);
}
public new void Redo()
{
if (RedoStack.Count == 0)
return;
MakeAllInvis();
BeginUpdate();
this.Dirty = true;
UndoElement el = RedoStack.Pop();
this.SelectionStart = el.SelectionStart;
this.SelectionLength = el.SelectedText.Length;
this.SelectedText = el.RedoText;
el.RedoText = null; // dont need it anymore
UndoStack.Push(el);
int intStartLine = this.GetLineFromCharIndex(el.SelectionStart);
int intStart = this.GetFirstCharIndexFromLine(intStartLine);
int intStopLine = this.GetLineFromCharIndex(el.SelectionStart + el.SelectedText.Length);
if (intStopLine < this.Lines.Length)
{
int intLengthStopLine = this.Lines[intStopLine].Length;
int intStop = this.GetFirstCharIndexFromLine(intStopLine) + intLengthStopLine;
ColorLine(intStart, intStop - intStart);
}
EndUpdate(true);
this.Focus();
}
public new void Undo()
{
if (UndoStack.Count == 0)
return;
MakeAllInvis();
BeginUpdate();
UndoElement el = UndoStack.Pop();
this.Dirty = (UndoStack.Count != 0);
this.SelectionStart = el.SelectionStart;
this.SelectionLength = el.SelectionLength;
el.RedoText = this.SelectedText; // save redo text!!!!
this.SelectedText = el.SelectedText;
RedoStack.Push(el);
int intStartLine = this.GetLineFromCharIndex(el.SelectionStart);
int intStart = this.GetFirstCharIndexFromLine(intStartLine);
int intStopLine = this.GetLineFromCharIndex(el.SelectionStart + el.SelectedText.Length);
if (intStopLine < this.Lines.Length)
{
int intLengthStopLine = this.Lines[intStopLine].Length;
int intStop = this.GetFirstCharIndexFromLine(intStopLine) + intLengthStopLine;
ColorLine(intStart, intStop - intStart);
}
EndUpdate(true);
this.Focus();
}
public void ToClipBoard()
{
bool backup = Properties.Settings.Default.SL4SpacesIndent;
Properties.Settings.Default.SL4SpacesIndent = true;
string strFormattedText = AutoFormatter.ApplyFormatting(0, this.Text);
Properties.Settings.Default.SL4SpacesIndent = backup;
try
{
Clipboard.SetDataObject(strFormattedText, true);
}
catch(Exception exception)
{
// error
Console.WriteLine(exception.Message);
}
}
public void ReplaceSelectedText(string strReplacement)
{
this.blnEscape = true; // prevent windows popping up
this.ColoredText = strReplacement;
}
public void MakeAllInvis()
{
if (!ToolTipping)
return;
this.TooltipKeyboard.Visible = false;
this.TooltipListBox.Visible = false;
this.TooltipMouse.Visible = false;
this.GListBoxWindow.Visible = false;
this.Focus();
}
private void LineDownlighting()
{
if (this.HighLightLine < 0)
return;
// doof line
BeginUpdate();
int intBackupSelectionStart = this.SelectionStart;
int intBackupSelectionLength = this.SelectionLength;
this.SelectionStart = this.GetFirstCharIndexFromLine(this.HighLightLine);
this.SelectionLength = this.Lines[this.HighLightLine].Length;
this.SelectionBackColor = this.BackColor;
this.SelectionStart = intBackupSelectionStart;
this.SelectionLength = intBackupSelectionLength;
this.HighLightLine = -1;
EndUpdate(false);
}
private void CursorPositionChanged()
{
BracketHighlichting();
LineDownlighting();
if (OnCursorPositionChanged != null)
OnCursorPositionChanged(this, new CursorPositionEventArgs(this.GetLine(), this.GetColumn(), this.GetChar(), this.GetTotal(), this.blnInsert, Control.IsKeyLocked(Keys.CapsLock)));
}
public new void Paste()
{
ResetHighlighting();
// First try with Unicode
if (Clipboard.GetDataObject().GetDataPresent(DataFormats.UnicodeText, true))
{
string strTextToPaste = Clipboard.GetDataObject().GetData(DataFormats.UnicodeText, true).ToString().Replace("\r", "");
this.ColoredText = strTextToPaste;
} // failing that try ANSI text.
else if (Clipboard.GetDataObject().GetDataPresent(DataFormats.Text, true))
{
string strTextToPaste = Clipboard.GetDataObject().GetData(DataFormats.Text, true).ToString().Replace("\r", "");
this.ColoredText = strTextToPaste;
#if DEBUG
// TODO Add code to show encoding used in a dialogue or the status bar.
#endif
}
}
private void GoEnd(bool blnShift)
{
if (this.Lines.Length == 0)
return;
int intLast = this.SelectionStart + this.SelectionLength;
int intLine = this.GetLineFromCharIndex(intLast);
int intColumn = intLast - this.GetFirstCharIndexFromLine(intLine);
string strLine = this.Lines[intLine];
int intAdd = strLine.Length - intColumn;
if (blnShift)
this.SelectionLength += intAdd;
else
{
this.SelectionStart = intLast+intAdd;
this.SelectionLength = 0;
}
}
private void GoHome(bool blnShift)
{
if (this.Lines.Length == 0)
return;
int intLine = this.GetLineFromCharIndex(this.SelectionStart);
string strLine = this.Lines[intLine];
for (int intColumn = 0; intColumn <= strLine.Length; intColumn++)
{
// now we are at the front of the line, ex whitespace
if (intColumn == strLine.Length || strLine[intColumn] > ' ')
{
int intStart = this.GetFirstCharIndexFromLine(intLine) + intColumn;
if (intStart == this.SelectionStart) // already here
intStart = this.GetFirstCharIndexFromLine(intLine);
// intStart has now got the new start position
if (blnShift)
{
int intAddToLength = this.SelectionStart - intStart;
this.SelectionStart = intStart;
// can + of -
this.SelectionLength = Math.Max(0, this.SelectionLength + intAddToLength);
}
else
{
this.SelectionStart = intStart;
this.SelectionLength = 0;
}
return;
}
}
}
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
if (this.TooltipMouse != null)
{
if (this.TooltipMouse.Visible)
{
this.TooltipMouse.Visible = false;
this.Focus();
}
}
if (this.GListBoxWindow != null && this.GListBoxWindow.Visible)
{
this.GListBoxWindow.KeyDownHandler(e);
}
else
{
if (e.KeyCode == Keys.Tab)
{
int intLineStart = this.GetLineFromCharIndex(this.SelectionStart);
int intLineStop = this.GetLineFromCharIndex(this.SelectionStart + this.SelectionLength);
if (intLineStart != intLineStop)
MultiLineTab(!e.Shift);
else
SingleLineTab(!e.Shift);
e.Handled = true;
}
}
if (e.KeyCode == Keys.Insert)
{
blnInsert = !blnInsert;
CursorPositionChanged();
}
if (e.KeyCode == Keys.Left ||
e.KeyCode == Keys.Right ||
e.KeyCode == Keys.End ||
e.KeyCode == Keys.Home)
MakeAllInvis();
if (e.KeyCode == Keys.Home)
{
if (!e.Control)
{
GoHome(e.Shift);
e.Handled = true;
}
}
if (e.KeyCode == Keys.End)
{
if (!e.Control)
{
GoEnd(e.Shift);
e.Handled = true;
}
}
if (e.KeyCode == Keys.Delete)
{
if (e.Control)
{
int intWissel = 0;
int intIndex = this.SelectionStart;
if (intIndex < this.Text.Length)
{
bool blnWhiteSpace = (this.Text[intIndex] <= ' ');
while (intIndex < this.Text.Length)
{
if (this.Text[intIndex] > ' ')
{
if (blnWhiteSpace)
{
blnWhiteSpace = false;
intWissel++;
}
}
else // whitespace
{
if (!blnWhiteSpace)
{
blnWhiteSpace = true;
intWissel++;
}
}
if (intWissel == 2)
break;
intIndex++;
}
this.SelectionLength = intIndex - this.SelectionStart;
}
} // control
else
{
if (e.Shift)
{
if (this.SelectionLength == 0)
{
if (this.Lines.Length > 0)
{
BeginUpdate();
this.SelectionStart = this.GetFirstCharIndexOfCurrentLine();
int intLine = this.GetLineFromCharIndex(this.SelectionStart);
this.SelectionLength = this.Lines[intLine].Length + 1;
EndUpdate(true);
}
}
this.Copy();
} // shift
else
{
if (this.SelectionLength == 0)
this.SelectionLength = 1;
} // no shift
}
this.Delete();
e.Handled = true;
}
if (e.KeyCode == Keys.X && e.Control)
{
this.Cut();
e.Handled = true;
}
if (this.TooltipKeyboard != null)
{
if (this.TooltipKeyboard.Visible)
{
if (e.KeyCode == Keys.Up ||
e.KeyCode == Keys.Down)
{
this.TooltipKeyboard.Visible = false;
this.Focus();
}
}
}
// 16 maart 2008
if (e.KeyCode == Keys.Back && e.Alt)
this.Undo();
if (e.KeyCode == Keys.Return || e.KeyCode == Keys.Back)
e.Handled = true;
if (e.Control)
{
if (e.KeyCode == Keys.R)
{
e.Handled = true;
}
if (e.KeyCode == Keys.V)
{
this.Paste();
e.Handled = true;
}
if (e.KeyCode == Keys.C)
{
this.Copy();
e.Handled = true;
}
}
if (e.KeyData == Keys.CapsLock)
CursorPositionChanged();
}
private void ProcessBackSpace()
{
if (this.SelectionStart == 0 && this.SelectionLength == 0)
return;
BeginUpdate();
if (this.SelectionStart > 0 && this.SelectionLength == 0)
this.SelectionStart--;
if (this.SelectionLength == 0)
this.SelectionLength = 1;
this.ColoredText = "";
EndUpdate(true);
OnTextChanged(null);
CursorPositionChanged();
}
protected override void OnKeyPress(KeyPressEventArgs e)
{
ResetHighlighting();
char keyChar = e.KeyChar;
switch (e.KeyChar)
{
case '\r': // Return
if (this.GListBoxWindow.Visible)
InsertSelectedWord();
else
ProcessEnter();
e.Handled = true;
break;
case '\t': // TAB
if (this.GListBoxWindow.Visible)
InsertSelectedWord();
e.Handled = true;
break;
case '{':
case '}':
ProcessBraces(keyChar);
e.Handled = true;
break;
case '\b':
ProcessBackSpace();
MakeAllInvis();
e.Handled = true;
break;
case (char)27:
this.blnEscape = !this.blnEscape;
MakeAllInvis();
break;
default:
if (keyChar >= 32)
{
if (this.SelectionLength != 0)
this.Delete();
SaveUndo(new UndoElement(this.SelectionStart, "", 1, null));
}
if (keyChar > 32 && !Char.IsLetterOrDigit(keyChar))
this.blnEscape = false;
break;
}
base.OnKeyPress(e);
}
// event generated, make list of codecompletion words
private void CodeCompletion(string strKeyWord, bool IsRegularExpression)
{
if (!ToolTipping)
return;
intKeyWordLength = strKeyWord.Length;
if (IsRegularExpression)
intKeyWordLength = 0; // else it would delete typed keyword
if (strKeyWord.Length == 0 || this.blnEscape)
{
this.TooltipListBox.Visible = false;
this.GListBoxWindow.Visible = false;
this.Focus();
return;
}
List<KeyWordInfo> list;
if (Properties.Settings.Default.CodeCompletion)
list = keyWords.KeyWordSearch(strKeyWord, IsRegularExpression);
else
list = new List<KeyWordInfo>();
if (Properties.Settings.Default.CodeCompletionUserVar && !IsRegularExpression)
codeCompletion.CodeCompletionUserVar(strKeyWord, this.Text, this.SelectionStart, list);
if (list.Count == 0)
{
this.TooltipListBox.Visible = false;
this.GListBoxWindow.Visible = false;
this.Focus();
return;
}
if (list.Count == 1)
{
// single keyword has been typed, make listbox invisible
if (list[0].name == strKeyWord)
{
/*
// this autocompletes 1 word, backspace is a problem, use escape
this.GListBoxWindow.GListBox.Items.Clear();
KeyWordInfo keyWordInfo = list[0];
GListBoxItem glbi = new GListBoxItem(keyWordInfo.name, (int)keyWordInfo.type);
this.GListBoxWindow.GListBox.Items.Add(glbi);
this.GListBoxWindow.GListBox.SelectedIndex = 0;
InsertSelectedWord();
*/
if (strKeyWord == "else") // else autocompletion enoys people!!! TODO
{
this.TooltipListBox.Visible = false;
this.GListBoxWindow.Visible = false;
this.Focus();
return;
}
}
}
// Hide argument typing
this.TooltipKeyboard.Visible = false;
this.Focus();
this.GListBoxWindow.GListBox.Items.Clear();
foreach (KeyWordInfo keyWordInfo in list)
{
GListBoxItem glbi = new GListBoxItem(keyWordInfo.name, (int)keyWordInfo.type);
this.GListBoxWindow.GListBox.Items.Add(glbi);
}
this.GListBoxWindow.GListBox.SelectedIndex = 0;
this.GListBoxWindow.GListBox.Height = Math.Min(list.Count + 1, 11) * this.GListBoxWindow.GListBox.ItemHeight;
this.GListBoxWindow.SetPosition(Screen.GetWorkingArea(this), this);
// Just in case it pops up
this.TooltipListBox.SetPosition(Screen.GetWorkingArea(this), this);
this.GListBoxWindow.Visible = true;
this.Focus();
}
private void SelectWordByDoubleClick()
{
int intSelectionStartBackup = this.SelectionStart;
int intLineNumber = this.GetLineFromCharIndex(intSelectionStartBackup);
int intFirstChar = this.GetFirstCharIndexFromLine(intLineNumber);
int intColumn = intSelectionStartBackup - intFirstChar;
string strLine = this.Lines[intLineNumber];
// start or ending in underscore then expand
int intStart = intColumn;
while ((intStart > 0) && IsAlpha(strLine[intStart - 1]))
intStart--;
int intEnd = intColumn;
while ((intEnd < strLine.Length) && IsAlpha(strLine[intEnd]))
intEnd++;
if (intStart != intColumn || intEnd != (intStart + this.SelectionLength))
{
this.SelectionStart = intFirstChar + intStart;
this.SelectionLength = intEnd - intStart;
}
}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
BracketHighlichting();
// this sucks!!!!
this.AutoWordSelection = true;
this.AutoWordSelection = Properties.Settings.Default.AutoWordSelection;
if (this.ToolTipping)
MakeAllInvis();
if (e.Clicks == 2)
SelectWordByDoubleClick();
}
private void ShowKeyBoardHint()
{
if (!ToolTipping)
return;
if (this.GListBoxWindow.Visible)
return;
if (this.blnEscape)
return;
int intArgument;
bool DoWild;
string strFunction = GetCurrentFunction(out intArgument, out DoWild);
if (strFunction == "")
{
this.TooltipKeyboard.Visible = false;
this.Focus();
return;
}
SetArgumentListOnRichLabel(this.TooltipKeyboard, strFunction, intArgument);
if (DoWild && this.TooltipKeyboard.Wild != "")
{
CodeCompletion(this.TooltipKeyboard.Wild , true);
this.Focus();
return;
}
if (this.TooltipKeyboard.Text == "")
{
this.TooltipKeyboard.Visible = false;
}
else
{
this.TooltipKeyboard.SetPosition(Screen.GetWorkingArea(this), this);
this.TooltipKeyboard.Visible = true;
//this.SelectionColor = this.ForeColor;
}
this.Focus();
}
private bool IsInComment(string strLine, int intIndex)
{
bool blnInString = false;
for (int intI = 0; intI < intIndex; intI++)
{
char chrC = strLine[intI];
if (chrC == '"')
blnInString = !blnInString;
if (blnInString)
{
if (chrC == '\\')
intI++;
continue;
}
if (chrC == '/')
{
if ((intI + 1) < intIndex)
if (strLine[intI + 1] == '/')
return true;
}
}
return false;
}
private bool IsInString(string strLine, int intIndex)
{
int intQuotes = 0;
for (int intI = intIndex - 1; intI >= 0; intI--)
{
char chrC = strLine[intI];
if (chrC == '"')
{
if ((intI - 1) >= 0)
if (strLine[intI - 1] != '\\')
intQuotes++;
}
}
return ((intQuotes % 2) != 0);
}
///
/// OnTextChanged
///
protected override void OnTextChanged(EventArgs e)
{
if (IsUpdating)
return;
if (this.Lines.Length == 0)
{
TabStops();
return;
}
this.Dirty = true;
int intSelectionStartBackup = this.SelectionStart;
int intLineNumber = this.GetLineFromCharIndex(intSelectionStartBackup);
int intFirstChar = this.GetFirstCharIndexFromLine(intLineNumber);
int intColumn = intSelectionStartBackup - intFirstChar;
string strLine = this.Lines[intLineNumber];
ColorLine(intFirstChar, strLine.Length);
if (IsInComment(strLine, intColumn))
return;
if (IsInString(strLine, intColumn))
return;
// not in comment and not in string, find the start of a word
int intStart = intColumn;
while ((intStart > 0) && IsAlpha(strLine[intStart - 1]))
intStart--;
string strTypedWord = strLine.Substring(intStart, intColumn - intStart);
CodeCompletion(strTypedWord , false);
ShowKeyBoardHint();
}
///
/// Color a line
///
private void ColorLine(int intStart, int intLength)
{
if (!ToolTipping)
return;
if (intLength <= 0)
return;
BeginUpdate();
// Backup position
int SelectionStartBackup = this.SelectionStart;
// get the line
string strLine = this.Text.Substring(intStart, intLength);
// highlight all keywords
foreach (Match m in keyWords.Matches(strLine))
{
Group g = m.Groups[1];
string strKeyWord = g.Value;
this.SelectionStart = intStart + g.Index;
this.SelectionLength = g.Length;
// normal keywords
if (keyWords.ContainsKeyWord(strKeyWord))
this.SelectionColor = keyWords.GetColorFromKeyWordList(strKeyWord);
else
this.SelectionColor = keyWords.GetColorFromRegex(strKeyWord);
}
// Restore position
this.SelectionLength = 0;
this.SelectionStart = SelectionStartBackup;
this.SelectionColor = this.ForeColor;
EndUpdate(false);
}
private int AutoFormat(bool OnlySelectedText)
{
int intTabs;
if (OnlySelectedText)
{
string strW = GetNewWhiteSpace(-1);
intTabs = (int)(strW.Length / AutoFormatter.GetTab().Length);
}
else
{
this.SelectionStart = 0;
this.SelectionLength = this.Text.Length;
intTabs = 0;
}
string strFormattedText = AutoFormatter.ApplyFormatting(intTabs, this.SelectedText);
this.ColoredText = strFormattedText;
return strFormattedText.Length;
}
public void AutoFormatSelectedText()
{
BeginUpdate();
Point scrollPoint = this.RTBScrollPos;
int intBackupStart = this.SelectionStart;
int intSelectionLength = AutoFormat(true);
this.SelectionStart = intBackupStart;
this.SelectionLength = intSelectionLength;
this.RTBScrollPos = scrollPoint;
EndUpdate(false);
}
public void FormatDocument()
{
BeginUpdate();
Point scrollPoint = this.RTBScrollPos;
int intLine = this.GetLineFromCharIndex(this.SelectionStart);
AutoFormat(false);
this.SelectionStart = Math.Max(0,this.GetFirstCharIndexFromLine(intLine));
this.RTBScrollPos = scrollPoint;
EndUpdate(false);
}
public void ClearUndoStack()
{
UndoStack.Clear();
Dirty = false;
}
public override string Text
{
get
{
return base.Text;
}
set
{
BeginUpdate();
int intBackup = this.SelectionStart;
this.SelectionStart = 0;
this.SelectionLength = this.Text.Length; //TODO
this.ColoredText = value;
this.SelectionStart = intBackup;
EndUpdate(true);
}
}
private string GetWhiteSpaceFromCurrentLine()
{
int intIndex = this.GetLineFromCharIndex(this.SelectionStart);
if (intIndex < this.Lines.Length)
return AutoFormatter.GetWhiteSpaceFromLine(this.Lines[intIndex]);
return "";
}
// code-completion word is selected
// also comes from mainform (doubleclick), must be public
public void InsertSelectedWord()
{
this.GListBoxWindow.Visible = false;
this.TooltipListBox.Visible = false;
if (this.GListBoxWindow.GListBox.SelectedIndex < 0)
return;
int intOffset = 0;
GListBoxItem glbi = this.GListBoxWindow.Selected;
string strSelected = glbi.ToString();
if (strSelected == "")
{
this.Focus();
return;
}
if (glbi.ImageIndex == (int)KeyWordTypeEnum.Events
|| strSelected == "default" && this.Text.IndexOf("default")<0)
{
if (strSelected != "default")
strSelected = keyWords.GetEvent(strSelected);
string strW = GetWhiteSpaceFromCurrentLine();
strSelected += "\n" + strW + "{\n" + strW + AutoFormatter.GetTab() + "\n" + strW + "}";
intOffset = -(strW.Length + 2);
}
else if (glbi.ImageIndex == (int)KeyWordTypeEnum.Functions)
{
if(keyWords.GetNumberOfArguments(strSelected) == 0)
strSelected += "()";
else
strSelected += "(";
}
else if (glbi.ImageIndex == (int)KeyWordTypeEnum.Properties)
{
strSelected = "\"" + strSelected.Trim() +"\"";
}
BeginUpdate();
this.SelectionStart -= intKeyWordLength;
this.SelectionLength = intKeyWordLength;
this.ColoredText = strSelected;
this.SelectionStart += intOffset;
EndUpdate(true);
// if any
ShowKeyBoardHint();
this.Focus();
}
// this comes from the main form
public void ShowTooltipOnListBox()
{
string strSelected = this.GListBoxWindow.Selected.ToString();
string strDescription = keyWords.GetDescription(strSelected);
if (strDescription != "")
{
this.TooltipListBox.Tag = strSelected;
this.TooltipListBox.Text = strDescription;
this.TooltipListBox.XOffset = this.GListBoxWindow.Width;
this.TooltipListBox.SetPosition(Screen.GetWorkingArea(this), this);
this.TooltipListBox.Visible = true;
this.Focus();
}
else
{
this.TooltipListBox.Visible = false;
this.Focus();
}
}
// Tooltip mouse by (Windows.Forms) timer
private void timer1_Tick(object sender, EventArgs e)
{
this.timer1.Stop();
if (this.Disposing || this.IsDisposed)
return;
if (!this.Visible)
return;
if (!ToolTipping)
return;
if (!Properties.Settings.Default.ToolTip)
return;
if (Control.MouseButtons != MouseButtons.None)
return;
Point point;
string strKeyWord = this.GetCurrentKeyWord(true, out point);
if (strKeyWord == "")
{
this.TooltipMouse.Visible = false;
return;
}
if (this.TooltipMouse.Tag.ToString() != strKeyWord)
{
this.TooltipMouse.Tag = strKeyWord;
this.TooltipMouse.Text = keyWords.GetDescription(strKeyWord);
}
if (this.TooltipMouse.Text == "")
{
this.TooltipMouse.Visible = false;
return;
}
this.TooltipMouse.SetPosition(this, point);
this.TooltipMouse.Visible = true;
this.Focus();
}
public bool ToolTipping
{
get
{
return m_blnToolTipping;
}
set
{
m_blnToolTipping = value;
if (m_blnToolTipping)
{
this.timer1 = new System.Windows.Forms.Timer();
this.timer1.Interval = Properties.Settings.Default.ToolTipDelay;
this.timer1.Tick += new EventHandler(timer1_Tick);
}
}
}
public void SetPosition(Rectangle rect)
{
if (!ToolTipping)
return;
if (this.GListBoxWindow.Visible)
this.GListBoxWindow.SetPosition(rect, this);
if (this.TooltipListBox.Visible)
this.TooltipListBox.SetPosition(rect, this);
if (this.TooltipKeyboard.Visible)
this.TooltipKeyboard.SetPosition(rect, this);
}
private void SetArgumentListOnRichLabel(TooltipWindow window, string strKeyWord, int intArgument)
{
if (window.Tag.ToString() == (strKeyWord + intArgument))
return; // cached information
string strWild = "";
window.Wild = "";
window.Tag = (strKeyWord + intArgument);
window.Text = keyWords.GetFunctionAndHiglightArgument(strKeyWord, intArgument, out strWild);
if(Properties.Settings.Default.CodeCompletionArguments)
window.Wild = strWild;
}
public void Goto(int intLine)
{
this.SelectionStart = this.GetFirstCharIndexFromLine(intLine - 1);
this.Focus();
}
public void MultiLineComment(bool blnAdd)
{
BeginUpdate();
ResetHighlighting();
string strW = GetNewWhiteSpace(-1);
int intTabs = (int)(strW.Length / AutoFormatter.GetTab().Length);
int intLastLine = this.GetLineFromCharIndex(this.SelectionStart + this.SelectionLength);
int intLine = this.GetLineFromCharIndex(this.SelectionStart);
this.SelectionStart = this.GetFirstCharIndexFromLine(intLine);
int intLength = 0;
do
{
intLength += this.Lines[intLine].Length + 1;
intLine++;
} while (intLine <= intLastLine);
this.SelectionLength = intLength;
string strSelectedText = AutoFormatter.MultiLineComment(blnAdd, intTabs, this.SelectedText);
int intBackup = this.SelectionStart;
this.ColoredText = strSelectedText;
this.SelectionStart = intBackup;
this.SelectionLength = strSelectedText.Length;
EndUpdate(true);
}
public void MultiLineTab(bool blnAdd)
{
string strSelectedText = AutoFormatter.MultiLineTab(blnAdd, this.SelectedText);
int intBackup = this.SelectionStart;
this.ColoredText = strSelectedText;
this.SelectionStart = intBackup;
this.SelectionLength = strSelectedText.Length;
}
private void SingleLineTab(bool blnAdd)
{
if (blnAdd)
{
this.SelectedText = AutoFormatter.GetTab();
}
else
{
// Shift tab on single line
string strTab = AutoFormatter.GetTab();
if (this.SelectionStart > strTab.Length)
{
string strBefore = this.Text.Substring(this.SelectionStart - strTab.Length, strTab.Length);
if (strBefore == strTab)
{
int intBackupLength = this.SelectionLength;
this.SelectionStart -= strTab.Length;
this.SelectionLength = strTab.Length;
this.SelectedText = "";
this.SelectionLength = intBackupLength;
}
else
{
// space remove? TODO
}
}
}
}
private void HighLightCharAt(int intIndex, Color color)
{
this.SelectionStart = intIndex;
this.SelectionLength = 1;
this.SelectionBackColor = color;
if (color != this.BackColor)
HighLightList.Add(intIndex);
}
private void HighLightCharAt(int intLine, int intColumn, Color color)
{
int intIndex = this.GetFirstCharIndexFromLine(intLine) + intColumn;
HighLightCharAt(intIndex, color);
}
private bool MatchingBracket(int intCurrentLine, int intCurrentColumn, char chrOpening, char chrClosing, int intDirection, out int intLine, out int intColumn)
{
if (this.Lines.Length == 0)
{
intLine = 0;
intColumn = 0;
return false;
}
intLine = intCurrentLine;
intColumn = intCurrentColumn;
string strLine = AutoFormatter.RemoveComment(this.Lines[intLine]);
int intNumber = 1;
bool blnWithinString = false;
while (true)
{
intColumn += intDirection;
while (intColumn < 0)
{
intLine--;
if (intLine < 0)
return false; // nothing to do
strLine = AutoFormatter.RemoveComment(this.Lines[intLine]); // get new previous line
intColumn = strLine.Length - 1; // place on end of line
}
while (intColumn >= strLine.Length)
{
intLine++;
if (intLine >= this.Lines.Length)
return false; // nothing to do
strLine = AutoFormatter.RemoveComment(this.Lines[intLine]); // get new previous line
intColumn = 0; // place on begin of line
}
char chrC = strLine[intColumn];
if (chrC == '"')
{
if (intDirection < 0 && intColumn > 0)
{
if (strLine[intColumn - 1] == '\\')
{
intColumn += intDirection;
continue;
}
}
blnWithinString = !blnWithinString;
}
if (blnWithinString)
{
if (intDirection > 0 && chrC == '\\')
intColumn += intDirection;
continue;
}
if (chrC == chrOpening)
intNumber++;
else if (chrC == chrClosing)
{
intNumber--;
if (intNumber == 0)
return true;
}
}
}
private void ResetHighlighting()
{
if (HighLightList.Count == 0)
return;
BeginUpdate();
Point scrollPoint = this.RTBScrollPos;
int intBackupStart = this.SelectionStart;
int intBackupLength = this.SelectionLength;
foreach (int intIndex in HighLightList)
HighLightCharAt(intIndex, this.BackColor);
HighLightList.Clear();
this.SelectionStart = intBackupStart;
this.SelectionLength = intBackupLength;
this.RTBScrollPos = scrollPoint;
EndUpdate(false);
}
private void BracketHighlichting()
{
if (this.TextLength == 0)
return;
if (this.SelectionLength != 0)
return;
BeginUpdate();
Point scrollPoint = this.RTBScrollPos;
int intSelectionStart = this.SelectionStart;
// ResetHighlichting without the overhead
if (HighLightList.Count > 0)
{
foreach (int intI in HighLightList)
HighLightCharAt(intI, this.BackColor);
HighLightList.Clear();
}
int intIndex;
int intType;
const string Uppers = "<({[";
const string Downers = ">)}]";
int intLine = this.GetLineFromCharIndex(intSelectionStart);
int intColumn = intSelectionStart - this.GetFirstCharIndexFromLine(intLine);
string strLine = AutoFormatter.RemoveComment(this.Lines[intLine]);
if (intColumn <= strLine.Length)
{
intIndex = intColumn - 1;
if (intIndex >= 0)
{
intType = Downers.IndexOf(strLine[intIndex]);
if (intType >= 0)
{
int intL, intC;
if (MatchingBracket(intLine, intIndex, Downers[intType], Uppers[intType], -1, out intL, out intC))
{
HighLightCharAt(intLine, intIndex, Properties.Settings.Default.BracketHighlight);
HighLightCharAt(intL, intC, Properties.Settings.Default.BracketHighlight);
}
}
}
intIndex = intColumn;
if (intIndex < strLine.Length)
{
intType = Uppers.IndexOf(strLine[intIndex]);
if (intType >= 0)
{
int intL, intC;
if (MatchingBracket(intLine, intIndex, Uppers[intType], Downers[intType], 1, out intL, out intC))
{
HighLightCharAt(intLine, intIndex, Properties.Settings.Default.BracketHighlight);
HighLightCharAt(intL, intC, Properties.Settings.Default.BracketHighlight);
}
}
}
}
this.SelectionStart = intSelectionStart;
this.SelectionLength = 0;
this.RTBScrollPos = scrollPoint;
EndUpdate(false);
}
public override string SelectedText
{
get
{
return base.SelectedText;
}
set
{
if (!IsUpdating)
SaveUndo(new UndoElement(this.SelectionStart, this.SelectedText, value.Length, null));
base.SelectedText = value;
}
}
private string ColoredText
{
set
{
BeginUpdate();
int intFirstCharOfStartLine = this.GetFirstCharIndexOfCurrentLine();
int intBackup = this.SelectionStart;
if (this.SelectedText != value)
{
this.Dirty = true;
string strTmp = value.Replace("\r", "");
SaveUndo(new UndoElement(this.SelectionStart, this.SelectedText, strTmp.Length, null));
this.SelectedText = strTmp;
if (this.Lines.Length > 0)
{
int intEndLine = this.GetLineFromCharIndex(intBackup + strTmp.Length);
int intLastCharOfEndLine = this.GetFirstCharIndexFromLine(intEndLine) + this.Lines[intEndLine].Length;
int intLength = intLastCharOfEndLine - intFirstCharOfStartLine;
ColorLine(intFirstCharOfStartLine, intLength);
this.SelectionStart = intBackup + strTmp.Length;
}
}
else
{
this.SelectionLength = 0;
this.SelectionStart += value.Length;
}
EndUpdate(true);
}
}
public void doOutline()
{
//TODO: finish the outline class and such
// still a work in progress trying to figure out exactly how i wanna do this.
int len = this.Lines.Length;
if (len < 1)
{
return;
}
Dictionary<int, Helpers.OutlineHelper> list = new Dictionary<int, LSLEditor.Helpers.OutlineHelper>();
string ttext = this.Text;
ttext.Replace("\r\n", "");
using (StringReader reader = new StringReader(ttext))
{
string line;
int lineNumber = 0;
while ((line = reader.ReadLine()) != null)
{
line = line.Trim();
line = line.Split('(')[0];
string[] words = line.Split(' ');
foreach (string word in words)
{
//Debug.WriteLine("ww:" + word);
if (keyWords.ContainsKeyWord(word))
{
KeyWordInfo k = keyWords.GetKeyWordInfo(word);
// Debug.WriteLine("w:" + word);
//Debug.WriteLine("k:" + k.type);
if (!list.ContainsKey(lineNumber))
{
switch (k.type)
{
case KeyWordTypeEnum.Functions:
list.Add(lineNumber, new LSLEditor.Helpers.OutlineHelper(k, lineNumber));
// Debug.WriteLine(k);
break;
case KeyWordTypeEnum.Events:
list.Add(lineNumber, new LSLEditor.Helpers.OutlineHelper(k, lineNumber));
break;
case KeyWordTypeEnum.Constants:
list.Add(lineNumber, new LSLEditor.Helpers.OutlineHelper(k, lineNumber));
break;
case KeyWordTypeEnum.Class:
list.Add(lineNumber, new LSLEditor.Helpers.OutlineHelper(k, lineNumber));
break;
case KeyWordTypeEnum.Vars:
list.Add(lineNumber, new LSLEditor.Helpers.OutlineHelper(k, lineNumber));
break;
case KeyWordTypeEnum.States:
list.Add(lineNumber, new LSLEditor.Helpers.OutlineHelper(k, lineNumber));
break;
default:
//Debug.WriteLine(k);
break;
}
}
}
}
lineNumber++;
}
}
//TODO: parse dict and create the outline in the treeview
//WILL SOMEONE PLEASE FUCKING FINISH THIS!
if (p != null) //It gives the parent-scriptwindow as null when you try to run it
{
p.tvOutline.BeginUpdate();
p.tvOutline.Nodes.Clear();
TreeNode lastState = null;
TreeNode lastEvent = null;
TreeNode lastScope = null;
foreach (LSLEditor.Helpers.OutlineHelper k in list.Values)
{
switch (k.info.type)
{
case KeyWordTypeEnum.States:
lastState = createOutlineNode(k);
lastScope = lastState;
p.tvOutline.Nodes.Add(lastState);
break;
case KeyWordTypeEnum.Events:
if (lastState != null) //we need a state for every event!
{
lastEvent = createOutlineNode(k);
lastScope = lastEvent;
lastState.Nodes.Add(lastEvent);
}
break;
case KeyWordTypeEnum.Functions:
if (lastScope != null)
{
lastScope.Nodes.Add(createOutlineNode(k));
}
break;
case KeyWordTypeEnum.Class:
if (lastScope != null)
{
lastScope.Nodes.Add(createOutlineNode(k));
}
else
{
p.tvOutline.Nodes.Add(createOutlineNode(k));
}
break;
default:
p.tvOutline.Nodes.Add(createOutlineNode(k));
break;
}
}
p.tvOutline.EndUpdate();
// p.tvOutline.Nodes.Add(states);
p.tvOutline.ExpandAll();
}
}
TreeNode createOutlineNode(Helpers.OutlineHelper ohOutline)
{
TreeNode result = null;
int ImageKey = (int)ohOutline.info.type;
result = new TreeNode(string.Format("{0} [{1}]", ohOutline.info.name, ohOutline.line + 1), ImageKey, ImageKey);
result.Tag = ohOutline;
return result;
}
public void SaveCurrentFile(string strPath, Encoding enc)
{
try
{
//Encoding enc = null;
if (!Directory.Exists(Path.GetDirectoryName(strPath)))
Directory.CreateDirectory(Path.GetDirectoryName(strPath));
/*
{
switch (Properties.Settings.Default.OutputFormat)
{
case "UTF8":
enc = Encoding.UTF8;
break;
case "Unicode":
enc = Encoding.Unicode;
break;
case "BigEndianUnicode":
enc = Encoding.BigEndianUnicode;
break;
default:
enc = Encoding.Default;
break;
}
}
else
{
enc = Encoding.UTF8;
}
* */
StreamWriter sw;
if (enc != Encoding.UTF8)
{
sw = new StreamWriter(strPath, false, enc);
}
else
{
sw = new StreamWriter(strPath);
}
sw.Write(this.Text);
sw.Close();
//this.SaveFile(strPath, RichTextBoxStreamType.PlainText);
this.Dirty = false;
}
catch // (Exception exception)
{
MessageBox.Show("Error saving file, check pathname: " + strPath, "Oops...", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
public new Encoding LoadFile(string path)
{
Encoding fileEncoding = null;
if (path.StartsWith("http://"))
{
System.Net.WebClient webClient = new System.Net.WebClient();
this.Text = webClient.DownloadString(path);
}
else
{
if (File.Exists(path))
{
// TODO needs to be refactored to read the file in once and pass the byte array to be checked.
fileEncoding = TextFileEncodingDetector.DetectTextFileEncoding(path, Encoding.UTF8);
try
{
StreamReader sr = new StreamReader(path, fileEncoding);
this.Text = sr.ReadToEnd();
sr.Close();
}
catch
{
}
}
}
// Fresh files can not be dirty
ClearUndoStack();
return fileEncoding;
}
}
}