// /** // ******** // * // * 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 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 UndoStack; private Stack 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(); this.UndoStack = new Stack(); this.RedoStack = new Stack(); 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 the word typed so far if (strKeyWord.Length == 0 || this.blnEscape) { this.TooltipListBox.Visible = false; this.GListBoxWindow.Visible = false; this.Focus(); return; } List list; if (Properties.Settings.Default.CodeCompletion) list = keyWords.KeyWordSearch(strKeyWord, IsRegularExpression); else list = new List(); 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 annoys 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 list = new Dictionary(); 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; } } }