From c3a52dce42a8b9c601474e1b361f2787ae476851 Mon Sep 17 00:00:00 2001 From: Mika Palmu Date: Thu, 11 Jun 2015 22:30:26 +0300 Subject: [PATCH 01/12] Win32 fixes and minor tweaks... --- .../ASCompletion/CustomControls/StateSavingTreeView.cs | 4 ++-- PluginCore/PluginCore/Controls/ScrollBarEx.cs | 4 ++-- PluginCore/PluginCore/Utilities/DataConverter.cs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/External/Plugins/ASCompletion/CustomControls/StateSavingTreeView.cs b/External/Plugins/ASCompletion/CustomControls/StateSavingTreeView.cs index ed46bf5f14..e3845c9ee7 100644 --- a/External/Plugins/ASCompletion/CustomControls/StateSavingTreeView.cs +++ b/External/Plugins/ASCompletion/CustomControls/StateSavingTreeView.cs @@ -53,14 +53,14 @@ public void EndStatefulUpdate() new public void BeginUpdate() { - Win32.SendMessage(Handle, Win32.WM_SETREDRAW, IntPtr.Zero, IntPtr.Zero); + if (Win32.ShouldUseWin32()) Win32.SendMessage(Handle, Win32.WM_SETREDRAW, IntPtr.Zero, IntPtr.Zero); base.BeginUpdate(); } new public void EndUpdate() { base.EndUpdate(); - Win32.SendMessage(Handle, Win32.WM_SETREDRAW, new IntPtr(1), IntPtr.Zero); + if (Win32.ShouldUseWin32()) Win32.SendMessage(Handle, Win32.WM_SETREDRAW, new IntPtr(1), IntPtr.Zero); } #region Expanded State Saving diff --git a/PluginCore/PluginCore/Controls/ScrollBarEx.cs b/PluginCore/PluginCore/Controls/ScrollBarEx.cs index 7cb0ce9362..810ac9b5df 100644 --- a/PluginCore/PluginCore/Controls/ScrollBarEx.cs +++ b/PluginCore/PluginCore/Controls/ScrollBarEx.cs @@ -956,7 +956,7 @@ public double Opacity /// public void BeginUpdate() { - Win32.SendMessage(this.Handle, Win32.WM_SETREDRAW, 0, 0); + if (Win32.ShouldUseWin32()) Win32.SendMessage(this.Handle, Win32.WM_SETREDRAW, 0, 0); this.inUpdate = true; } @@ -965,7 +965,7 @@ public void BeginUpdate() /// public void EndUpdate() { - Win32.SendMessage(this.Handle, Win32.WM_SETREDRAW, 1, 0); + if (Win32.ShouldUseWin32()) Win32.SendMessage(this.Handle, Win32.WM_SETREDRAW, 1, 0); this.inUpdate = false; this.SetUpScrollBar(); this.Refresh(); diff --git a/PluginCore/PluginCore/Utilities/DataConverter.cs b/PluginCore/PluginCore/Utilities/DataConverter.cs index 2ed265af24..fcadbd4c8f 100644 --- a/PluginCore/PluginCore/Utilities/DataConverter.cs +++ b/PluginCore/PluginCore/Utilities/DataConverter.cs @@ -109,7 +109,7 @@ public static String ColorToHex(Color color) /// /// Converts a integer (BGR order) to a color /// - private static Color BGRToColor(Int32 bgr) + public static Color BGRToColor(Int32 bgr) { return Color.FromArgb((bgr >> 0) & 0xff, (bgr >> 8) & 0xff, (bgr >> 16) & 0xff); } From 6a9e9e3ccec0b91e56275b045b4b3b239de80f27 Mon Sep 17 00:00:00 2001 From: Mika Palmu Date: Thu, 11 Jun 2015 22:30:54 +0300 Subject: [PATCH 02/12] Some progress... --- FlashDevelop/Docking/TabbedDocument.cs | 3 +- FlashDevelop/Managers/FileStateManager.cs | 1 + PluginCore/PluginCore.csproj | 61 + PluginCore/ScintillaNet/ScintillaControl.cs | 1235 ++++++++++++++----- 4 files changed, 982 insertions(+), 318 deletions(-) diff --git a/FlashDevelop/Docking/TabbedDocument.cs b/FlashDevelop/Docking/TabbedDocument.cs index 31655caa46..359e693798 100644 --- a/FlashDevelop/Docking/TabbedDocument.cs +++ b/FlashDevelop/Docking/TabbedDocument.cs @@ -136,8 +136,7 @@ public Boolean IsAloneInPane int count = 0; foreach (ITabbedDocument document in Globals.MainForm.Documents) { - if (document.DockHandler.PanelPane == DockHandler.PanelPane) - count++; + if (document.DockHandler.PanelPane == DockHandler.PanelPane) count++; } return count <= 1; } diff --git a/FlashDevelop/Managers/FileStateManager.cs b/FlashDevelop/Managers/FileStateManager.cs index 1a77de5266..bdf59c60c4 100644 --- a/FlashDevelop/Managers/FileStateManager.cs +++ b/FlashDevelop/Managers/FileStateManager.cs @@ -142,6 +142,7 @@ private static StateObject GetStateObject(ScintillaControl sci) so.LineCount = sci.LineCount; so.Position = sci.CurrentPos; so.FileName = sci.FileName; + return so; // FIX THIS for (Int32 line = 0;; line++) { Int32 lineNext = sci.ContractedFoldNext(line); diff --git a/PluginCore/PluginCore.csproj b/PluginCore/PluginCore.csproj index f8d4ac4e4b..3b8ad5b654 100644 --- a/PluginCore/PluginCore.csproj +++ b/PluginCore/PluginCore.csproj @@ -279,6 +279,62 @@ Code + + + Component + + + + + + + Component + + + + + + UserControl + + + + Form + + + + Form + + + + + + Form + + + + + + + + + + + Form + + + + UserControl + + + + + + + + + UserControl + + @@ -531,6 +587,11 @@ ResXFileCodeGenerator Strings.Designer.cs + + + + + Designer diff --git a/PluginCore/ScintillaNet/ScintillaControl.cs b/PluginCore/ScintillaNet/ScintillaControl.cs index 065c5423bf..8abdf80893 100644 --- a/PluginCore/ScintillaNet/ScintillaControl.cs +++ b/PluginCore/ScintillaNet/ScintillaControl.cs @@ -201,6 +201,161 @@ private void RemoveScrollBars(ScintillaControl sender) #endregion + #region FastColoredTB + + private FastColoredTextBoxNS.FastColoredTextBox fctb; + + private void InitCustomEditor() + { + this.fctb = new FastColoredTextBoxNS.FastColoredTextBox(); + this.fctb.Language = FastColoredTextBoxNS.Language.JS; + this.fctb.Dock = DockStyle.Fill; + this.fctb.ShowLineNumbers = true; + this.fctb.ShowFoldingLines = true; + this.fctb.HighlightFoldingIndicator = false; + this.fctb.KeyDown += this.OnEditorKeyDown; + this.fctb.DoubleClick += this.OnEditorDoubleClick; + this.fctb.GotFocus += this.OnEditorFocusChanged; + this.fctb.LostFocus += this.OnEditorFocusChanged; + this.fctb.ZoomChanged += this.OnEditorZoomChanged; + this.fctb.TextChangedDelayed += this.OnEditorTextChanged; + this.fctb.SelectionChangedDelayed += this.OnEditorSelectionChanged; + this.fctb.UndoRedoStateChanged += this.OnEditorUndoRedoStateChanged; + this.fctb.TextChanging += this.OnEditorTextChanging; + this.fctb.Paint += this.OnEditorPaint; + this.fctb.Paddings = new Padding(4); + this.fctb.LeftPadding = 10; + this.Controls.Add(this.fctb); + } + + private void ApplyEditorStyles(string language) + { + Language lang = sciConfiguration.GetLanguage(language); + this.fctb.Font = new Font("Consolas", 9f, FontStyle.Regular); + this.fctb.DisabledColor = Color.Lime; + foreach (UseStyle style in lang.usestyles) + { + // TODO: Fix this + style.key = (int)Enum.Parse(typeof(Lexers.CPP), style.name, true); + if (style.key == 0) // Default + { + FontStyle fontStyle = FontStyle.Regular; + if (style.IsBold) fontStyle |= FontStyle.Bold; + if (style.IsItalics) fontStyle |= FontStyle.Italic; + Color fore = DataConverter.BGRToColor(style.ForegroundColor); + Color back = DataConverter.BGRToColor(style.BackgroundColor); + this.fctb.DefaultStyle = new FastColoredTextBoxNS.TextStyle(new SolidBrush(fore), new SolidBrush(back), fontStyle); + this.fctb.BackColor = this.fctb.ChangedLineColor = this.fctb.PaddingBackColor = back; + this.fctb.IndentBackColor = back; + this.fctb.FoldingIndicatorColor = Color.Lime; + } + else if (style.key == (Int32)ScintillaNet.Enums.StylesCommon.LineNumber) + { + this.fctb.LineNumberColor = DataConverter.BGRToColor(style.ForegroundColor); + } + else if (style.key == (Int32)ScintillaNet.Enums.StylesCommon.IndentGuide) + { + this.fctb.ServiceLinesColor = DataConverter.BGRToColor(style.ForegroundColor); + } + else if (style.key == (Int32)ScintillaNet.Enums.StylesCommon.BraceLight) + { + Color color = DataConverter.BGRToColor(style.BackgroundColor); + this.fctb.BracketsStyle = new FastColoredTextBoxNS.MarkerStyle(new SolidBrush(color)); + this.fctb.BracketsStyle2 = new FastColoredTextBoxNS.MarkerStyle(new SolidBrush(color)); + } + } + this.fctb.ServiceColors.CollapseMarkerBackColor = DataConverter.BGRToColor(lang.editorstyle.MarkerForegroundColor); + this.fctb.ServiceColors.CollapseMarkerBorderColor = DataConverter.BGRToColor(lang.editorstyle.MarkerBackgroundColor); + this.fctb.ServiceColors.CollapseMarkerForeColor = DataConverter.BGRToColor(lang.editorstyle.MarkerBackgroundColor); + this.fctb.ServiceColors.ExpandMarkerBackColor = DataConverter.BGRToColor(lang.editorstyle.MarkerForegroundColor); + this.fctb.ServiceColors.ExpandMarkerBorderColor = DataConverter.BGRToColor(lang.editorstyle.MarkerBackgroundColor); + this.fctb.ServiceColors.ExpandMarkerForeColor = DataConverter.BGRToColor(lang.editorstyle.MarkerBackgroundColor); + this.fctb.CaretColor = DataConverter.BGRToColor(lang.editorstyle.CaretForegroundColor); + // + this.fctb.CurrentLineColor = DataConverter.BGRToColor(lang.editorstyle.CaretLineBackgroundColor); + this.fctb.SelectionColor = DataConverter.BGRToColor(lang.editorstyle.SelectionBackgroundColor); + //this.fctb.ChangedLineColor = DataConverter.BGRToColor(lang.editorstyle.ModifiedLineColor); + this.fctb.BookmarkColor = DataConverter.BGRToColor(lang.editorstyle.BookmarkLineColor); + /* + EdgeColour = lang.editorstyle.PrintMarginColor; + */ + } + + private FastColoredTextBoxNS.Language LanguageToFCTB(string language) + { + switch (language) + { + case "jscript": return FastColoredTextBoxNS.Language.JS; + case "csharp": return FastColoredTextBoxNS.Language.CSharp; + case "html": return FastColoredTextBoxNS.Language.HTML; + case "php": return FastColoredTextBoxNS.Language.PHP; + case "xml": return FastColoredTextBoxNS.Language.XML; + default: return FastColoredTextBoxNS.Language.JS; + } + } + + private void OnEditorDoubleClick(object sender, EventArgs e) + { + if (DoubleClick != null) DoubleClick(this); + } + + private void OnEditorKeyDown(object sender, KeyEventArgs e) + { + if (Key != null) Key(this, (int)e.KeyData, (int)e.Modifiers); + } + + private void OnEditorFocusChanged(object sender, EventArgs e) + { + if (FocusChanged != null) FocusChanged(this); + } + + private void OnEditorZoomChanged(object sender, EventArgs e) + { + if (Zoom != null) Zoom(this); + } + + private void OnEditorSelectionChanged(object sender, EventArgs e) + { + if (SelectionChanged != null) SelectionChanged(this); + } + + private void OnEditorUndoRedoStateChanged(object sender, EventArgs e) + { + if (this.fctb.UndoEnabled && this.IsModify) + { + if (SavePointLeft != null) SavePointLeft(this); + } + if (!this.fctb.UndoEnabled) + { + if (SavePointReached != null) SavePointReached(this); + } + } + + private void OnEditorTextChanged(object sender, FastColoredTextBoxNS.TextChangedEventArgs e) + { + int linesAdded = e.ChangedRange.Text.Split('\n').Length; + if (TextInserted != null) TextInserted(this, e.ChangedRange.Start.iChar, e.ChangedRange.Text.Length, linesAdded); + if (TextDeleted != null) TextDeleted(this, e.ChangedRange.Start.iChar, e.ChangedRange.Text.Length, linesAdded); + if (e.ChangedRange.Text.Length == 1 && CharAdded != null) CharAdded(this, e.ChangedRange.Text[0]); + // + //if (Modified != null) Modified(this, this.CurrentPos, 1, e.ChangedRange.Text, e.ChangedRange.Text.Length, e.ChangedRange.FromLine - e.ChangedRange.ToLine, this.CurrentLine, 1, 1); + } + + private void OnEditorTextChanging(object sender, FastColoredTextBoxNS.TextChangingEventArgs e) + { + bool insert = !String.IsNullOrEmpty(e.InsertingText); + if (insert && BeforeInsert != null) BeforeInsert(this, this.CurrentPos, e.InsertingText.Length); + if (!insert && BeforeDelete != null) BeforeDelete(this, this.CurrentPos, e.InsertingText.Length); + } + + private void OnEditorPaint(object sender, PaintEventArgs e) + { + if (UpdateUI != null) UpdateUI(this); + if (Painted != null) Painted(this); + } + + #endregion + #region Scintilla Main public ScintillaControl() : this("SciLexer.dll") @@ -219,13 +374,14 @@ public ScintillaControl(string fullpath) directPointer = (int)SlowPerform(2185, 0, 0); directPointer = DirectPointer; } - UpdateUI += new UpdateUIHandler(OnUpdateUI); + /*UpdateUI += new UpdateUIHandler(OnUpdateUI); UpdateUI += new UpdateUIHandler(OnBraceMatch); UpdateUI += new UpdateUIHandler(OnCancelHighlight); DoubleClick += new DoubleClickHandler(OnBlockSelect); CharAdded += new CharAddedHandler(OnSmartIndent); Resize += new EventHandler(OnResize); - this.InitScrollBars(this); + this.InitScrollBars(this);*/ + this.InitCustomEditor(); } catch (Exception ex) { @@ -251,20 +407,20 @@ public void OnResize(object sender, EventArgs e) #region Scintilla Event Members - public event KeyHandler Key; - public event ZoomHandler Zoom; - public event FocusHandler FocusChanged; + public event KeyHandler Key; // + public event ZoomHandler Zoom; // + public event FocusHandler FocusChanged; // public event StyleNeededHandler StyleNeeded; - public event CharAddedHandler CharAdded; - public event SavePointReachedHandler SavePointReached; - public event SavePointLeftHandler SavePointLeft; + public event CharAddedHandler CharAdded; // + public event SavePointReachedHandler SavePointReached; // + public event SavePointLeftHandler SavePointLeft; // public event ModifyAttemptROHandler ModifyAttemptRO; - public event UpdateUIHandler UpdateUI; + public event UpdateUIHandler UpdateUI; // public event ModifiedHandler Modified; public event MacroRecordHandler MacroRecord; public event MarginClickHandler MarginClick; public event NeedShownHandler NeedShown; - public event PaintedHandler Painted; + public event PaintedHandler Painted; // public event UserListSelectionHandler UserListSelection; public event URIDroppedHandler URIDropped; public event DwellStartHandler DwellStart; @@ -273,16 +429,16 @@ public void OnResize(object sender, EventArgs e) public event HotSpotDoubleClickHandler HotSpotDoubleClick; public event CallTipClickHandler CallTipClick; public event AutoCSelectionHandler AutoCSelection; - public event TextInsertedHandler TextInserted; - public event TextDeletedHandler TextDeleted; + public event TextInsertedHandler TextInserted; // + public event TextDeletedHandler TextDeleted; // public event FoldChangedHandler FoldChanged; public event UserPerformedHandler UserPerformed; public event UndoPerformedHandler UndoPerformed; public event RedoPerformedHandler RedoPerformed; public event LastStepInUndoRedoHandler LastStepInUndoRedo; public event MarkerChangedHandler MarkerChanged; - public event BeforeInsertHandler BeforeInsert; - public event BeforeDeleteHandler BeforeDelete; + public event BeforeInsertHandler BeforeInsert; // + public event BeforeDeleteHandler BeforeDelete; // public event SmartIndentHandler SmartIndent; public new event StyleChangedHandler StyleChanged; public new event DoubleClickHandler DoubleClick; @@ -290,8 +446,8 @@ public void OnResize(object sender, EventArgs e) public event IndicatorReleaseHandler IndicatorRelease; public event AutoCCancelledHandler AutoCCancelled; public event AutoCCharDeletedHandler AutoCCharDeleted; - public event UpdateSyncHandler UpdateSync; - public event SelectionChangedHandler SelectionChanged; + public event UpdateSyncHandler UpdateSync; // + public event SelectionChangedHandler SelectionChanged; // #endregion @@ -310,14 +466,8 @@ public IntPtr HandleSci /// static public Scintilla Configuration { - get - { - return sciConfiguration; - } - set - { - sciConfiguration = value; - } + get { return sciConfiguration; } + set { sciConfiguration = value; } } /// @@ -325,14 +475,8 @@ static public Scintilla Configuration /// public Enums.IndentView IndentView { - get - { - return this.indentView; - } - set - { - this.indentView = value; - } + get { return this.indentView; } + set { this.indentView = value; } } /// @@ -340,14 +484,17 @@ public Enums.IndentView IndentView /// public string ConfigurationLanguage { - get - { - return this.configLanguage; - } + get { return this.configLanguage; } set { if (string.IsNullOrEmpty(value)) return; - this.SetLanguage(value); + if (this.fctb != null) + { + this.configLanguage = value; + this.fctb.Language = LanguageToFCTB(value); + this.ApplyEditorStyles(value); + } + else this.SetLanguage(value); } } @@ -357,11 +504,13 @@ public string ConfigurationLanguage public string GetFileExtension() { string extension = Path.GetExtension(FileName); - if (!string.IsNullOrEmpty(extension)) - extension = extension.Substring(1); // remove dot + if (!string.IsNullOrEmpty(extension)) extension = extension.Substring(1); // remove dot return extension; } + /// + /// Save the extension to syntax files and remove from others + /// public void SaveExtensionToSyntaxConfig(string extension) { List languages = sciConfiguration.GetLanguages(); @@ -379,24 +528,25 @@ public void SaveExtensionToSyntaxConfig(string extension) language.SaveExtensions(); } } - foreach (ITabbedDocument document in PluginBase.MainForm.Documents) { ScintillaControl sci = document.SciControl; if (sci.GetFileExtension() == extension) + { sci.ConfigurationLanguage = ConfigurationLanguage; + } } } + /// + /// Sets the language and applies correct styling + /// private void SetLanguage(String value) { Language lang = sciConfiguration.GetLanguage(value); if (lang == null) return; StyleClearAll(); - try - { - lang.lexer.key = (int)Enum.Parse(typeof(Enums.Lexer), lang.lexer.name, true); - } + try { lang.lexer.key = (int)Enum.Parse(typeof(Enums.Lexer), lang.lexer.name, true); } catch { /* If not found, uses the lang.lexer.key directly. */ } this.configLanguage = value; Lexer = lang.lexer.key; @@ -691,10 +841,7 @@ private void SetLanguage(String value) theType = typeof(Lexers.SML); break; } - try - { - usestyle.key = (int)Enum.Parse(theType, usestyle.name, true); - } + try { usestyle.key = (int)Enum.Parse(theType, usestyle.name, true); } catch (Exception ex) { String info; @@ -757,11 +904,11 @@ public string FileName { get { - return fileName; + return this.fileName; } set - { - fileName = value; + { + this.fileName = value; if (UpdateSync != null) this.UpdateSync(this); } } @@ -772,7 +919,8 @@ public string FileName public override bool Focused { get - { + { + if (this.fctb != null) return this.fctb.Focused; return IsFocus; } } @@ -783,12 +931,12 @@ public override bool Focused public bool IgnoreAllKeys { get - { - return ignoreAllKeys; + { + return this.ignoreAllKeys; } set - { - ignoreAllKeys = value; + { + this.ignoreAllKeys = value; } } @@ -799,11 +947,11 @@ public bool IsHiliteSelected { get { - return isHiliteSelected; + return this.isHiliteSelected; } set { - isHiliteSelected = value; + this.isHiliteSelected = value; if (UpdateSync != null) this.UpdateSync(this); } } @@ -814,12 +962,12 @@ public bool IsHiliteSelected public bool IsBraceMatching { get - { - return isBraceMatching; + { + return this.isBraceMatching; } set - { - isBraceMatching = value; + { + this.isBraceMatching = value; if (UpdateSync != null) this.UpdateSync(this); } } @@ -831,11 +979,11 @@ public bool UseHighlightGuides { get { - return useHighlightGuides; + return this.useHighlightGuides; } set { - useHighlightGuides = value; + this.useHighlightGuides = value; if (UpdateSync != null) this.UpdateSync(this); } } @@ -846,12 +994,12 @@ public bool UseHighlightGuides public Enums.SmartIndent SmartIndentType { get - { - return smartIndent; + { + return this.smartIndent; } set - { - smartIndent = value; + { + this.smartIndent = value; if (UpdateSync != null) this.UpdateSync(this); } } @@ -863,12 +1011,12 @@ public Enums.SmartIndent SmartIndentType public Enums.WhiteSpace ViewWhitespace { get - { - return (Enums.WhiteSpace)ViewWS; + { + return (Enums.WhiteSpace)this.ViewWS; } set - { - ViewWS = (int)value; + { + this.ViewWS = (int)value; } } @@ -879,26 +1027,47 @@ public int CaretLineBackAlpha { get { - return (int)SPerform(2471, 0, 0); + if (this.fctb != null) return this.fctb.CurrentLineColor.A; + else return (int)SPerform(2471, 0, 0); } set { - SPerform(2470, (uint)value, 0); + if (this.fctb != null) + { + Color color = Color.FromArgb(value > 0 && value < 255 ? value : 255, this.fctb.CurrentLineColor); + this.fctb.CurrentLineColor = color; + } + else SPerform(2470, (uint)value, 0); } } /// - /// Get or sets the background alpha of the caret line. + /// Get or sets the style of the caret. /// public int CaretStyle { get { - return (int)SPerform(2513, 0, 0); + if (this.fctb != null) + { + if (this.fctb.WideCaret) return (int)Enums.CaretStyle.Block; + else if (this.fctb.CaretColor.A == 1) return (int)Enums.CaretStyle.Invisible; + else return (int)Enums.CaretStyle.Line; + } + else return (int)SPerform(2513, 0, 0); } set { - SPerform(2512, (uint)value, 0); + if (this.fctb != null) + { + if (value == (int)Enums.CaretStyle.Block) this.fctb.WideCaret = true; + else if (value == (int)Enums.CaretStyle.Invisible) + { + this.fctb.CaretColor = Color.FromArgb(1, this.fctb.CaretColor); + } + else this.fctb.WideCaret = false; + } + else SPerform(2512, (uint)value, 0); } } @@ -909,6 +1078,7 @@ public int CurrentIndicator { get { + // TODO, implement return (int)SPerform(2501, 0, 0); } set @@ -924,6 +1094,7 @@ public int PositionCache { get { + // TODO, implement return (int)SPerform(2515, 0, 0); } set @@ -939,6 +1110,7 @@ public int IndicatorValue { get { + // TODO, implement return (int)SPerform(2503, 0, 0); } set @@ -970,7 +1142,8 @@ public int CurLineSize { get { - return (int)SPerform(2027, 0 , 0); + if (this.fctb != null) return this.fctb.GetLineLength(this.CurrentLine); + else return (int)SPerform(2027, 0, 0); } } @@ -982,7 +1155,8 @@ public int LineSize { get { - return (int)SPerform(2153, 0, 0); + if (this.fctb != null) return this.fctb.GetLineLength(this.CurrentLine); + else return (int)SPerform(2153, 0, 0); } } @@ -994,7 +1168,8 @@ public int SelTextSize { get { - return (int)SPerform(2161, 0, 0) - 1; + if (this.fctb != null) return this.fctb.SelectionLength; + else return (int)SPerform(2161, 0, 0) - 1; } } @@ -1006,7 +1181,8 @@ public int TextSize { get { - return (int)SPerform(2182, 0, 0); + if (this.fctb != null) return this.fctb.Text.Length; + else return (int)SPerform(2182, 0, 0); } } @@ -1017,7 +1193,8 @@ public bool CanRedo { get { - return SPerform(2016, 0, 0) != 0; + if (this.fctb != null) return this.fctb.RedoEnabled; + else return SPerform(2016, 0, 0) != 0; } } @@ -1028,7 +1205,8 @@ public bool IsAutoCActive { get { - return SPerform(2102, 0, 0) != 0; + if (this.fctb != null) return this.fctb.Hints.Count > 1; + else return SPerform(2102, 0, 0) != 0; } } @@ -1039,76 +1217,83 @@ public int AutoCPosStart { get { + // TODO return (int)SPerform(2103, 0, 0); } - } - - /// - /// Will a paste succeed? - /// - public bool CanPaste - { - get - { - return SPerform(2173, 0, 0) != 0; - } - } + } /// - /// Are there any undoable actions in the undo history? + /// Get currently selected item position in the auto-completion list /// - public bool CanUndo + public int AutoCGetCurrent { - get + get { - return SPerform(2174, 0, 0) != 0; + // TODO + return (int)SPerform(2445, 0, 0); } - } + } /// /// Is there an active call tip? /// public bool IsCallTipActive { - get + get { + // TODO return SPerform(2202, 0, 0) != 0; } - } + } /// /// Retrieve the position where the caret was before displaying the call tip. /// public int CallTipPosStart { - get + get { + // TODO return (int)SPerform(2203, 0, 0); } } - + /// - /// Create a new document object. - /// Starts with reference count of 1 and not selected into editor. + /// Will a paste succeed? /// - public int CreateDocument + public bool CanPaste { get { - return (int)SPerform(2375, 0, 0); + // TODO: ok? + if (this.fctb != null) return this.fctb.Focused && Clipboard.ContainsText(); + else return SPerform(2173, 0, 0) != 0; } } /// - /// Get currently selected item position in the auto-completion list + /// Are there any undoable actions in the undo history? /// - public int AutoCGetCurrent + public bool CanUndo { get { - return (int)SPerform(2445, 0, 0); + if (this.fctb != null) return this.fctb.UndoEnabled; + else return SPerform(2174, 0, 0) != 0; } } + + /// + /// Create a new document object. + /// Starts with reference count of 1 and not selected into editor. + /// + public int CreateDocument + { + get + { + return (int)SPerform(2375, 0, 0); + } + } /// /// Returns the number of characters in the document. @@ -1117,6 +1302,7 @@ public int Length { get { + if (this.fctb != null) return this.fctb.Text.Length; return (int)SPerform(2006, 0, 0); } } @@ -1128,6 +1314,7 @@ public bool PasteConvertEndings { get { + // TODO return SPerform(2468, 0, 0) != 0; } set @@ -1143,7 +1330,8 @@ public int CurrentPos { get { - return (int)SPerform(2008, 0, 0); + if (this.fctb != null) return this.fctb.SelectionStart; + else return (int)SPerform(2008, 0, 0); } set { @@ -1180,11 +1368,29 @@ public int AnchorPosition { get { - return (int)SPerform(2009, 0, 0); + if (this.fctb != null) + { + if (this.fctb.SelectionStart == this.CurrentPos) + { + return this.fctb.SelectionStart + this.fctb.SelectionLength; + } + else return this.fctb.SelectionStart; + } + else return (int)SPerform(2009, 0, 0); } set { - SPerform(2026, (uint)value , 0); + if (this.fctb != null) + { + if (this.fctb.SelectionStart < value) + { + int start = this.fctb.SelectionStart; + this.fctb.Selection.Start = this.fctb.PositionToPlace(value); + this.fctb.Selection.End = this.fctb.PositionToPlace(start); + } + else this.fctb.Selection.End = this.fctb.PositionToPlace(value); + } + else SPerform(2026, (uint)value, 0); } } @@ -1195,11 +1401,13 @@ public bool IsUndoCollection { get { - return SPerform(2019, 0, 0)!=0; + if (this.fctb != null) return this.fctb.TextSource.Manager.UndoRedoStackIsEnabled; + else return SPerform(2019, 0, 0) != 0; } set { - SPerform(2012 , (uint)(value ? 1 : 0), 0); + if (this.fctb != null) this.fctb.TextSource.Manager.UndoRedoStackIsEnabled = value; + else SPerform(2012, (uint)(value ? 1 : 0), 0); } } @@ -1211,6 +1419,7 @@ public int ViewWS { get { + // TODO return (int)SPerform(2020, 0, 0); } set @@ -1226,6 +1435,7 @@ public int EndStyled { get { + // TODO return (int)SPerform(2028, 0, 0); } } @@ -1237,6 +1447,7 @@ public int EOLMode { get { + // TODO return (int)SPerform(2030, 0, 0); } set @@ -1252,11 +1463,13 @@ public bool IsBufferedDraw { get { - return SPerform(2034, 0, 0)!=0; + if (this.fctb != null) return this.DoubleBuffered; + else return SPerform(2034, 0, 0) != 0; } set { - SPerform(2035 , (uint)(value ? 1 : 0), 0); + if (this.fctb != null) this.DoubleBuffered = value; + else SPerform(2035, (uint)(value ? 1 : 0), 0); } } @@ -1267,11 +1480,13 @@ public int TabWidth { get { - return (int)SPerform(2121, 0, 0); + if (this.fctb != null) return this.fctb.TabLength; + else return (int)SPerform(2121, 0, 0); } set { - SPerform(2036, (uint)value, 0); + if (this.fctb != null) this.fctb.TabLength = value; + else SPerform(2036, (uint)value, 0); } } @@ -1282,11 +1497,14 @@ public int CaretPeriod { get { - return (int)SPerform(2075, 0, 0); + // TODO: Customize? + if (this.fctb != null) return SystemInformation.CaretBlinkTime; + else return (int)SPerform(2075, 0, 0); } set { - SPerform(2076, (uint)value, 0); + if (this.fctb != null) return; + else SPerform(2076, (uint)value, 0); } } @@ -1297,11 +1515,13 @@ public int StyleBits { get { - return (int)SPerform(2091, 0, 0); + if (this.fctb != null) return this.fctb.Styles.Length; + else return (int)SPerform(2091, 0, 0); } set { - SPerform(2090, (uint)value, 0); + if (this.fctb != null) return; // MAX is 64 + else SPerform(2090, (uint)value, 0); } } @@ -1312,6 +1532,7 @@ public int MaxLineState { get { + // TODO return (int)SPerform(2094, 0, 0); } } @@ -1323,11 +1544,17 @@ public bool IsCaretLineVisible { get { - return SPerform(2095, 0, 0) != 0; + if (this.fctb != null) return this.fctb.CurrentLineColor != Color.Transparent; + else return SPerform(2095, 0, 0) != 0; } set { - SPerform(2096, (uint)(value ? 1 : 0), 0); + if (this.fctb != null) + { + if (!value) this.fctb.CurrentLineColor = Color.Transparent; + else return; // AUTOMATIC, set color + } + else SPerform(2096, (uint)(value ? 1 : 0), 0); } } @@ -1338,11 +1565,13 @@ public int CaretLineBack { get { - return (int)SPerform(2097, 0, 0); + if (this.fctb != null) return DataConverter.ColorToBGR(this.fctb.CurrentLineColor); + else return (int)SPerform(2097, 0, 0); } set { - SPerform(2098, (uint)value, 0); + if (this.fctb != null) this.fctb.CurrentLineColor = DataConverter.BGRToColor(value); + else SPerform(2098, (uint)value, 0); } } @@ -1353,6 +1582,7 @@ public int AutoCSeparator { get { + // TODO return (int)SPerform(2107, 0, 0); } set @@ -1368,6 +1598,7 @@ public bool IsAutoCGetCancelAtStart { get { + // TODO return SPerform(2111, 0, 0) != 0; } set @@ -1383,6 +1614,7 @@ public bool IsAutoCGetChooseSingle { get { + // TODO return SPerform(2114, 0, 0) != 0; } set @@ -1398,6 +1630,7 @@ public bool IsAutoCGetIgnoreCase { get { + // TODO return SPerform(2116, 0, 0) != 0; } set @@ -1413,6 +1646,7 @@ public bool IsAutoCGetAutoHide { get { + // TODO return SPerform(2119, 0, 0) != 0; } set @@ -1429,6 +1663,7 @@ public bool IsAutoCGetDropRestOfWord { get { + // TODO return SPerform(2271, 0, 0) != 0; } set @@ -1444,6 +1679,7 @@ public int AutoCTypeSeparator { get { + // TODO return (int)SPerform(2285, 0, 0); } set @@ -1459,11 +1695,13 @@ public int Indent { get { - return (int)SPerform(2123, 0, 0); + if (this.fctb != null) return 1; // FIXED + else return (int)SPerform(2123, 0, 0); } set { - SPerform(2122, (uint)value, 0); + if (this.fctb != null) return; + else SPerform(2122, (uint)value, 0); } } @@ -1474,11 +1712,13 @@ public bool IsUseTabs { get { - return SPerform(2125, 0, 0) != 0; + if (this.fctb != null) return !this.fctb.VirtualSpace; + else return SPerform(2125, 0, 0) != 0; } set { - SPerform(2124 , (uint)(value ? 1 : 0), 0); + if (this.fctb != null) this.fctb.VirtualSpace = !value; + else SPerform(2124, (uint)(value ? 1 : 0), 0); } } @@ -1489,11 +1729,13 @@ public bool IsIndentationGuides { get { - return SPerform(2133, 0, 0) != 0; + if (this.fctb != null) return this.fctb.ShowFoldingLines; + else return SPerform(2133, 0, 0) != 0; } set { - SPerform(2132, (uint)(value ? (int)this.indentView : 0), 0); + if (this.fctb != null) this.fctb.ShowFoldingLines = value; + else SPerform(2132, (uint)(value ? (int)this.indentView : 0), 0); } } @@ -1504,11 +1746,13 @@ public int HighlightGuide { get { - return (int)SPerform(2135, 0, 0); + if (this.fctb != null) return 1; // AUTOMATIC + else return (int)SPerform(2135, 0, 0); } set { - SPerform(2134, (uint)value, 0); + if (this.fctb != null) this.fctb.HighlightFoldingIndicator = value > 0; + else SPerform(2134, (uint)value, 0); } } @@ -1519,11 +1763,13 @@ public int CodePage { get { - return (int)SPerform(2137, 0, 0); + if (this.fctb != null) return 65001; // AUTOMATIC + else return (int)SPerform(2137, 0, 0); } set { - SPerform(2037, (uint)value, 0); + if (this.fctb != null) return; + else SPerform(2037, (uint)value, 0); } } @@ -1534,28 +1780,24 @@ public int CaretFore { get { - return (int)SPerform(2138, 0, 0); + if (this.fctb != null) return DataConverter.ColorToBGR(this.fctb.CaretColor); + else return (int)SPerform(2138, 0, 0); } set { - SPerform(2069, (uint)value, 0); + if (this.fctb != null) this.fctb.CaretColor = DataConverter.BGRToColor(value); + else SPerform(2069, (uint)value, 0); } } /// - /// In palette mode? + /// In palette mode? Deprecated, the last version to support palettes was 2.29. /// public bool IsUsePalette { - get - { - return SPerform(2139, 0, 0) != 0; - } - set - { - SPerform(2039, (uint)(value ? 1 : 0), 0); - } - } + get { return true; } + set { return; } + } /// /// In read-only mode? @@ -1564,11 +1806,13 @@ public bool IsReadOnly { get { - return SPerform(2140, 0, 0) != 0; + if (this.fctb != null) return this.fctb.ReadOnly; + else return SPerform(2140, 0, 0) != 0; } set { - SPerform(2171, (uint)(value ? 1 : 0), 0); + if (this.fctb != null) this.fctb.ReadOnly = value; + else SPerform(2171, (uint)(value ? 1 : 0), 0); } } @@ -1579,11 +1823,13 @@ public int SelectionStart { get { - return (int)SPerform(2143, 0, 0); + if (this.fctb != null) return this.fctb.SelectionStart; + else return (int)SPerform(2143, 0, 0); } set { - SPerform(2142, (uint)value, 0); + if (this.fctb != null) this.fctb.SelectionStart = value; + else SPerform(2142, (uint)value, 0); } } @@ -1594,11 +1840,13 @@ public int SelectionEnd { get { - return (int)SPerform(2145, 0, 0); + if (this.fctb != null) return this.fctb.PlaceToPosition(this.fctb.Selection.End); + else return (int)SPerform(2145, 0, 0); } set { - SPerform(2144, (uint)value, 0); + if (this.fctb != null) this.fctb.Selection.End = this.fctb.PositionToPlace(value); + else SPerform(2144, (uint)value, 0); } } @@ -1620,6 +1868,7 @@ public int PrintMagnification { get { + // TODO return (int)SPerform(2147, 0, 0); } set @@ -1635,6 +1884,7 @@ public int PrintColourMode { get { + // TODO return (int)SPerform(2149, 0, 0); } set @@ -1650,11 +1900,18 @@ public int FirstVisibleLine { set { - SPerform(2613, (uint)value, 0); + if (this.fctb != null) + { + if (value < 0 || value > this.LineCount) return; + FastColoredTextBoxNS.Range range = new FastColoredTextBoxNS.Range(this.fctb, value); + this.fctb.DoRangeVisible(range); + } + else SPerform(2613, (uint)value, 0); } get { - return (int)SPerform(2152, 0, 0); + if (this.fctb != null) return this.fctb.FindPrevVisibleLine(this.CurrentLine); + else return (int)SPerform(2152, 0, 0); } } @@ -1665,6 +1922,7 @@ public int LineCount { get { + if (this.fctb != null) return this.fctb.LinesCount; return (int)SPerform(2154, 0, 0); } } @@ -1676,11 +1934,13 @@ public int MarginLeft { get { - return (int)SPerform(2156, 0, 0); + if (this.fctb != null) return this.fctb.LeftPadding; + else return (int)SPerform(2156, 0, 0); } set { - SPerform(2155, 0, (uint)value); + if (this.fctb != null) this.fctb.LeftPadding = value; + else SPerform(2155, 0, (uint)value); } } @@ -1691,11 +1951,13 @@ public int MarginRight { get { - return (int)SPerform(2158, 0, 0); + if (this.fctb != null) return 0; // FIXED + else return (int)SPerform(2158, 0, 0); } set { - SPerform(2157, 0, (uint)value); + if (this.fctb != null) return; + else SPerform(2157, 0, (uint)value); } } @@ -1706,7 +1968,8 @@ public bool IsModify { get { - return SPerform(2159, 0, 0) != 0; + if (this.fctb != null) return this.fctb.IsChanged; + else return SPerform(2159, 0, 0) != 0; } } @@ -1717,7 +1980,8 @@ public int TextLength { get { - return (int)SPerform(2183, 0, 0); + if (this.fctb != null) return this.fctb.Text.Length; + else return (int)SPerform(2183, 0, 0); } } @@ -1728,7 +1992,8 @@ public int DirectFunction { get { - return (int)SPerform(2184, 0, 0); + if (this.fctb != null) return 0; // INVALID + else return (int)SPerform(2184, 0, 0); } } @@ -1740,7 +2005,8 @@ public int DirectPointer { get { - return (int)SPerform(2185, 0, 0); + if (this.fctb != null) return 0; // INVALID + else return (int)SPerform(2185, 0, 0); } } @@ -1751,11 +2017,13 @@ public bool IsOvertype { get { - return SPerform(2187, 0, 0) != 0; + if (this.fctb != null) return this.fctb.IsReplaceMode; + else return SPerform(2187, 0, 0) != 0; } set { - SPerform(2186 , (uint)(value ? 1 : 0), 0); + if (this.fctb != null) this.fctb.IsReplaceMode = value; + else SPerform(2186, (uint)(value ? 1 : 0), 0); } } @@ -1766,11 +2034,13 @@ public int CaretWidth { get { - return (int)SPerform(2189, 0, 0); + if (this.fctb != null) return this.fctb.CaretWidth; + else return (int)SPerform(2189, 0, 0); } set { - SPerform(2188, (uint)value, 0); + if (this.fctb != null) this.fctb.CaretWidth = value; + else SPerform(2188, (uint)value, 0); } } @@ -1781,6 +2051,7 @@ public int TargetStart { get { + // TODO return (int)SPerform(2191, 0, 0); } set @@ -1796,6 +2067,7 @@ public int TargetEnd { get { + // TODO return (int)SPerform(2193, 0, 0); } set @@ -1811,6 +2083,7 @@ public int SearchFlags { get { + // TODO return (int)SPerform(2199, 0, 0); } set @@ -1826,11 +2099,13 @@ public bool IsTabIndents { get { - return SPerform(2261, 0, 0) != 0; + if (this.fctb != null) return true; // AUTOMATIC? + else return SPerform(2261, 0, 0) != 0; } set { - SPerform(2260, (uint)(value ? 1 : 0), 0); + if (this.fctb != null) return; + else SPerform(2260, (uint)(value ? 1 : 0), 0); } } @@ -1841,11 +2116,13 @@ public bool IsBackSpaceUnIndents { get { - return SPerform(2263, 0, 0) != 0; + if (this.fctb != null) return true; // AUTOMATIC? + else return SPerform(2263, 0, 0) != 0; } set { - SPerform(2262, (uint)(value ? 1 : 0), 0); + if (this.fctb != null) return; + else SPerform(2262, (uint)(value ? 1 : 0), 0); } } @@ -1856,6 +2133,7 @@ public int MouseDwellTime { get { + // TODO return (int)SPerform(2265, 0, 0); } set @@ -1871,11 +2149,23 @@ public int WrapMode { get { - return (int)SPerform(2269, 0, 0); + if (this.fctb != null) + { + if (this.fctb.WordWrapMode == FastColoredTextBoxNS.WordWrapMode.WordWrapControlWidth) return 1; + else if (this.fctb.WordWrapMode == FastColoredTextBoxNS.WordWrapMode.CharWrapControlWidth) return 2; + else return 0; // NONE + } + else return (int)SPerform(2269, 0, 0); } set { - SPerform(2268, (uint)value, 0); + if (this.fctb != null) + { + if (value == 1) this.fctb.WordWrapMode = FastColoredTextBoxNS.WordWrapMode.WordWrapControlWidth; + else if (value == 2) this.fctb.WordWrapMode = FastColoredTextBoxNS.WordWrapMode.CharWrapControlWidth; + else this.fctb.WordWrap = false; + } + else SPerform(2268, (uint)value, 0); } } @@ -1886,6 +2176,7 @@ public int WrapVisualFlags { get { + // TODO return (int)SPerform(2461, 0, 0); } set @@ -1901,6 +2192,7 @@ public int WrapVisualFlagsLocation { get { + // TODO return (int)SPerform(2463, 0, 0); } set @@ -1916,11 +2208,13 @@ public int WrapStartIndent { get { - return (int)SPerform(2465, 0, 0); + if (this.fctb != null) return this.fctb.WordWrapIndent; + else return (int)SPerform(2465, 0, 0); } set { - SPerform(2464, (uint)value, 0); + if (this.fctb != null) this.fctb.WordWrapIndent = value; + else SPerform(2464, (uint)value, 0); } } @@ -1931,11 +2225,13 @@ public int LayoutCache { get { - return (int)SPerform(2273, 0, 0); + if (this.fctb != null) return 0; // INVALID + else return (int)SPerform(2273, 0, 0); } set { - SPerform(2272, (uint)value, 0); + if (this.fctb != null) return; + else SPerform(2272, (uint)value, 0); } } @@ -1946,11 +2242,13 @@ public int ScrollWidth { get { - return (int)SPerform(2275, 0, 0); + if (this.fctb != null) return 0; // INVALID? + else return (int)SPerform(2275, 0, 0); } set { - SPerform(2274, (uint)value, 0); + if (this.fctb != null) return; + else SPerform(2274, (uint)value, 0); } } @@ -1962,11 +2260,13 @@ public int EndAtLastLine { get { - return (int)SPerform(2278, 0, 0); + if (this.fctb != null) return 0; // AUTOMATIC? FIX? + else return (int)SPerform(2278, 0, 0); } set { - SPerform(2277, (uint)value , 0); + if (this.fctb != null) return; + else SPerform(2277, (uint)value, 0); } } @@ -1977,11 +2277,13 @@ public bool IsTwoPhaseDraw { get { - return SPerform(2283, 0, 0)!=0; + if (this.fctb != null) return true; // INVALID? AUTOMATIC? + else return SPerform(2283, 0, 0) != 0; } set { - SPerform(2284, (uint)(value ? 1 : 0), 0); + if (this.fctb != null) return; + else SPerform(2284, (uint)(value ? 1 : 0), 0); } } @@ -1992,6 +2294,7 @@ public bool IsViewEOL { get { + // TODO return SPerform(2355, 0, 0) != 0; } set @@ -2007,6 +2310,7 @@ public int DocPointer { get { + // TODO return (int)SPerform(2357, 0, 0); } set @@ -2022,6 +2326,7 @@ public int EdgeColumn { get { + // TODO return (int)SPerform(2360, 0, 0); } set @@ -2037,6 +2342,7 @@ public int EdgeMode { get { + // TODO return (int)SPerform(2362, 0, 0); } set @@ -2052,6 +2358,7 @@ public int EdgeColour { get { + // TODO return (int)SPerform(2364, 0, 0); } set @@ -2067,7 +2374,8 @@ public int LinesOnScreen { get { - return (int)SPerform(2370, 0, 0); + if (this.fctb != null) return this.fctb.VisibleRange.ToLine - this.fctb.VisibleRange.FromLine; + else return (int)SPerform(2370, 0, 0); } } @@ -2078,7 +2386,8 @@ public bool IsSelectionRectangle { get { - return SPerform(2372, 0, 0) != 0; + if (this.fctb != null) return this.fctb.Selection.ColumnSelectionMode; + else return SPerform(2372, 0, 0) != 0; } } @@ -2090,11 +2399,13 @@ public int ZoomLevel { get { - return (int)SPerform(2374, 0, 0); + if (this.fctb != null) return this.fctb.Zoom; // CHECK? + else return (int)SPerform(2374, 0, 0); } set { - SPerform(2373, (uint)value, 0); + if (this.fctb != null) this.fctb.Zoom = value; + else SPerform(2373, (uint)value, 0); } } @@ -2105,6 +2416,7 @@ public int ModEventMask { get { + // TODO return (int)SPerform(2378, 0, 0); } set @@ -2120,11 +2432,13 @@ public bool IsFocus { get { - return SPerform(2381, 0, 0) != 0; + if (this.fctb != null) return this.fctb.Focused; + else return SPerform(2381, 0, 0) != 0; } set { - SPerform(2380 , (uint)(value ? 1 : 0), 0); + if (this.fctb != null) this.fctb.Focus(); + else SPerform(2380, (uint)(value ? 1 : 0), 0); } } @@ -2135,11 +2449,13 @@ public int Status { get { - return (int)SPerform(2383, 0, 0); + if (this.fctb != null) return 0; // INVALID + else return (int)SPerform(2383, 0, 0); } set { - SPerform(2382, (uint)value, 0); + if (this.fctb != null) return; + else SPerform(2382, (uint)value, 0); } } @@ -2150,6 +2466,7 @@ public bool IsMouseDownCaptures { get { + // TODO, true? return SPerform(2385, 0, 0) != 0; } set @@ -2165,11 +2482,21 @@ public int CursorType { get { - return (int)SPerform(2387, 0, 0); + if (this.fctb != null) + { + if (this.fctb.Cursor == Cursors.WaitCursor) return (int)Enums.CursorShape.Wait; + else return (int)Enums.CursorShape.Normal; // Arrow + } + else return (int)SPerform(2387, 0, 0); } set { - SPerform(2386, (uint)value, 0); + if (this.fctb != null) + { + if (value == (int)Enums.CursorShape.Wait) this.fctb.Cursor = Cursors.WaitCursor; + else this.fctb.Cursor = Cursors.Arrow; + } + else SPerform(2386, (uint)value, 0); } } @@ -2182,6 +2509,7 @@ public int ControlCharSymbol { get { + // TODO, automatic false? return (int)SPerform(2389, 0, 0); } set @@ -2197,11 +2525,13 @@ public int XOffset { get { - return (int)SPerform(2398, 0, 0); + if (this.fctb != null) return this.fctb.VerticalScroll.Value; + else return (int)SPerform(2398, 0, 0); } set { - SPerform(2397, (uint)value, 0); + if (this.fctb != null) this.fctb.VerticalScroll.Value = value; + else SPerform(2397, (uint)value, 0); } } @@ -2212,6 +2542,7 @@ public int PrintWrapMode { get { + // TODO return (int)SPerform(2407, 0, 0); } set @@ -2227,11 +2558,17 @@ public int SelectionMode { get { - return (int)SPerform(2423, 0, 0); + if (this.fctb != null) + { + if (this.fctb.Selection.ColumnSelectionMode) return (int)Enums.SelectionMode.Rectangle; + else return (int)Enums.SelectionMode.Stream; + } + else return (int)SPerform(2423, 0, 0); } set { - SPerform(2422, (uint)value, 0); + if (this.fctb != null) this.fctb.Selection.ColumnSelectionMode = (value == (int)Enums.SelectionMode.Rectangle); + else SPerform(2422, (uint)value, 0); } } @@ -2242,6 +2579,7 @@ public int Lexer { get { + // TODO return (int)SPerform(4002, 0, 0); } set @@ -2281,11 +2619,13 @@ public bool UnicodeKeys { get { - return SPerform(2522, 0, 0) != 0; + if (this.fctb != null) return true; // FIXED + else return SPerform(2522, 0, 0) != 0; } set { - SPerform(2521, (uint)(value ? 1 : 0), 0); + if (this.fctb != null) return; + else SPerform(2521, (uint)(value ? 1 : 0), 0); } } @@ -2296,6 +2636,7 @@ public int ExtraAscent { get { + // TODO return (int)SPerform(2526, 0, 0); } set @@ -2311,6 +2652,7 @@ public int ExtraDescent { get { + // TODO return (int)SPerform(2528, 0, 0); } set @@ -2326,6 +2668,7 @@ public int MarginStyleOffset { get { + // TODO return (int)SPerform(2538, 0, 0); } set @@ -2341,6 +2684,7 @@ public int AnnotationStyleOffset { get { + // TODO return (int)SPerform(2551, 0, 0); } set @@ -2356,6 +2700,7 @@ public bool AnnotationVisible { get { + // TODO return SPerform(2549, 0, 0) != 0; } set @@ -2371,11 +2716,13 @@ public bool ScrollWidthTracking { get { - return SPerform(2517, 0, 0) != 0; + if (this.fctb != null) return true; // AUTOMATIC + else return SPerform(2517, 0, 0) != 0; } set { - SPerform(2516, (uint)(value ? 1 : 0), 0); + if (this.fctb != null) return; + else SPerform(2516, (uint)(value ? 1 : 0), 0); } } @@ -2416,11 +2763,12 @@ public virtual bool ContainsIgnoredKeys(Keys keys) } /// - /// Sets the focud to the control + /// Sets the focus to the control /// public new bool Focus() { - return SetFocus(hwndScintilla) != IntPtr.Zero; + if (this.fctb != null) return this.fctb.Focus(); + else return SetFocus(hwndScintilla) != IntPtr.Zero; } /// @@ -2429,7 +2777,26 @@ public virtual bool ContainsIgnoredKeys(Keys keys) /// public void SelectionDuplicate() { - SPerform(2469, 0, 0); + if (this.fctb != null) + { + if (this.fctb.SelectionLength > 0) + { + int pos = this.fctb.SelectionStart; + int lenght = this.fctb.SelectionLength; + this.fctb.InsertText(this.fctb.SelectedText + this.fctb.SelectedText); + this.fctb.Selection.Start = this.fctb.PositionToPlace(pos + lenght); + this.fctb.Selection.End = this.fctb.PositionToPlace(pos); + } + else + { + int pos = this.fctb.SelectionStart; + string text = this.fctb.GetLineText(this.CurrentLine); + this.fctb.Selection.GoEnd(false); + this.fctb.InsertText(this.NewLineMarker + text); + this.fctb.Selection.Start = this.fctb.PositionToPlace(pos); + } + } + else SPerform(2469, 0, 0); } /// @@ -2441,8 +2808,7 @@ public void SmartSelectionDuplicate() bool wholeLine = SelectionStart == SelectionEnd; int selectionLength = SelectionEnd - SelectionStart; SelectionDuplicate(); - if (wholeLine) - LineDown(); + if (wholeLine) LineDown(); else { SelectionStart += selectionLength; @@ -2455,7 +2821,8 @@ public void SmartSelectionDuplicate() /// public bool GetCaretSticky() { - return SPerform(2457, 0, 0) != 0; + if (this.fctb != null) return false; // FIXED + else return SPerform(2457, 0, 0) != 0; } /// @@ -2463,7 +2830,8 @@ public bool GetCaretSticky() /// public void SetCaretSticky(bool useSetting) { - SPerform(2458, (uint)(useSetting ? 1 : 0), 0); + if (this.fctb != null) return; // FIXED + else SPerform(2458, (uint)(useSetting ? 1 : 0), 0); } /// @@ -2471,16 +2839,24 @@ public void SetCaretSticky(bool useSetting) /// public void ToggleCaretSticky() { - SPerform(2459, 0, 0); + if (this.fctb != null) return; // FIXED + else SPerform(2459, 0, 0); } - /// /// Retrieve the fold level of a line. /// public int GetFoldLevel(int line) { - return (int)SPerform(2223, (uint)line, 0); + if (this.fctb != null) // CHECK + { + if (this.fctb.TextSource.LineHasFoldingStartMarker(line)) + { + return (int)Enums.FoldLevel.HeaderFlag; + } + else return (int)Enums.FoldLevel.Base; + } + else return (int)SPerform(2223, (uint)line, 0); } /// @@ -2490,7 +2866,16 @@ public int GetFoldLevel(int line) /// public void SetFoldLevel(int line, int level) { - SPerform(2222, (uint)line, (uint)level); + if (this.fctb != null) // CHECK + { + int id = this.fctb[line - 1].UniqueId; + int fold = level & (int)Enums.FoldLevel.HeaderFlag; + if (fold == (int)Enums.FoldLevel.HeaderFlag) + { + this.fctb.FoldedBlocks[id] = id; + } + } + else SPerform(2222, (uint)line, (uint)level); } /// @@ -2498,7 +2883,8 @@ public void SetFoldLevel(int line, int level) /// public int LastChild(int line, int level) { - return (int)SPerform(2224, (uint)line, (uint)level); + if (this.fctb != null) return this.fctb.FindEndOfFoldingBlock(line); // CHECK + else return (int)SPerform(2224, (uint)line, (uint)level); } /// @@ -2506,7 +2892,8 @@ public int LastChild(int line, int level) /// public int LastChild(int line) { - return (int)SPerform(2224, (uint)line, 0); + if (this.fctb != null) return this.fctb.FindEndOfFoldingBlock(line); // CHECK + else return (int)SPerform(2224, (uint)line, 0); } /// @@ -2514,7 +2901,11 @@ public int LastChild(int line) /// public bool GetLineVisible(Int32 line) { - return SPerform(2228, (uint)line, 0) != 0; + if (this.fctb != null) + { + return this.fctb.GetVisibleState(line) == FastColoredTextBoxNS.VisibleState.Visible; + } + else return SPerform(2228, (uint)line, 0) != 0; } /// @@ -2522,7 +2913,15 @@ public bool GetLineVisible(Int32 line) /// public int FoldParent(int line) { - return (int)SPerform(2225, (uint)line, 0); + if (this.fctb != null) // CHECK + { + for (int i = line - 1; i > 1; i--) + { + if (this.fctb.TextSource.LineHasFoldingStartMarker(i)) return i; + } + return -1; + } + else return (int)SPerform(2225, (uint)line, 0); } /// @@ -2530,7 +2929,11 @@ public int FoldParent(int line) /// public bool FoldExpanded(int line) { - return SPerform(2230, (uint)line, 0) != 0; + if (this.fctb != null) + { + return this.fctb.GetVisibleState(line) == FastColoredTextBoxNS.VisibleState.Visible; + } + else return SPerform(2230, (uint)line, 0) != 0; } /// @@ -2538,7 +2941,16 @@ public bool FoldExpanded(int line) /// public void FoldExpanded(int line, bool expanded) { - SPerform(2229, (uint)line, (uint)(expanded ? 1 : 0)); + if (this.fctb != null) + { + if (this.fctb.TextSource.LineHasFoldingStartMarker(line)) + { + if (expanded) this.fctb.ExpandFoldedBlock(line); + else this.fctb.CollapseFoldingBlock(line); + this.fctb.AdjustFolding(); + } + } + else SPerform(2229, (uint)line, (uint)(expanded ? 1 : 0)); } /// @@ -2814,7 +3226,12 @@ public void SetLineIndentation(int line, int indentSize) /// public int LineIndentPosition(int line) { - return (int)SPerform(2128, (uint)line, 0); + if (this.fctb != null) + { + int columns = this.fctb.CalcAutoIndent(line); + return this.fctb.PlaceToPosition(new FastColoredTextBoxNS.Place(columns, line)); + } + else return (int)SPerform(2128, (uint)line, 0); } /// @@ -2822,7 +3239,8 @@ public int LineIndentPosition(int line) /// public int Column(int pos) { - return (int)SPerform(2129, (uint)pos, 0); + if (this.fctb != null) return this.fctb.PositionToPlace(pos).iChar; + else return (int)SPerform(2129, (uint)pos, 0); } /// @@ -2838,7 +3256,12 @@ public int LineEndPosition(int line) /// public int CharAt(int pos) { - return (int)SPerform(2007, (uint)pos, 0); + if (this.fctb != null) + { + if (pos < 0 || pos > this.Length - 1) return 0; + return (int)this.fctb.Text[pos]; + } + else return (int)SPerform(2007, (uint)pos, 0); } /// @@ -2950,10 +3373,18 @@ public void SetIndicFore(int indic, int fore) /// unsafe public void AddText(int length, string text ) { - if (text == null || text.Equals("")) text = "\0\0"; - fixed (byte* b = Encoding.GetEncoding(this.CodePage).GetBytes(text)) + if (this.fctb != null) { - SPerform(2001,(uint)length, (uint)b); + this.fctb.Selection.Start = this.fctb.PositionToPlace(length); + this.fctb.InsertText(text, true); + } + else + { + if (text == null || text.Equals("")) text = "\0\0"; + fixed (byte* b = Encoding.GetEncoding(this.CodePage).GetBytes(text)) + { + SPerform(2001, (uint)length, (uint)b); + } } } @@ -2962,10 +3393,18 @@ unsafe public void AddText(int length, string text ) /// unsafe public void InsertText(int pos, string text ) { - if (text == null || text.Equals("")) text = "\0\0"; - fixed (byte* b = Encoding.GetEncoding(this.CodePage).GetBytes(text)) + if (this.fctb != null) { - SPerform(2003, (uint)pos, (uint)b); + this.fctb.Selection.Start = this.fctb.PositionToPlace(pos); + this.fctb.InsertText(text, true); + } + else + { + if (text == null || text.Equals("")) text = "\0\0"; + fixed (byte* b = Encoding.GetEncoding(this.CodePage).GetBytes(text)) + { + SPerform(2003, (uint)pos, (uint)b); + } } } @@ -3006,7 +3445,8 @@ public void StyleSetCase(int style, Enums.CaseVisible caseForce) /// public void ClearAll() { - SPerform(2004, 0, 0); + if (this.fctb != null) this.fctb.Clear(); + else SPerform(2004, 0, 0); } /// @@ -3022,7 +3462,8 @@ public void ClearDocumentStyle() /// public void Redo() { - SPerform(2011, 0, 0); + if (this.fctb != null) this.fctb.Redo(); + else SPerform(2011, 0, 0); } /// @@ -3030,7 +3471,8 @@ public void Redo() /// public void SelectAll() { - SPerform(2013, 0, 0); + if (this.fctb != null) this.fctb.SelectAll(); + else SPerform(2013, 0, 0); } /// @@ -3039,7 +3481,12 @@ public void SelectAll() /// public void SetSavePoint() { - SPerform(2014, 0, 0); + if (this.fctb != null) + { + this.fctb.ClearUndo(); + this.fctb.IsChanged = false; + } + else SPerform(2014, 0, 0); } /// @@ -3063,7 +3510,8 @@ public void MarkerDeleteHandle(int handle) /// public int PositionFromPoint(int x, int y) { - return (int)SPerform(2022, (uint)x, (uint)y); + if (this.fctb != null) return this.fctb.PointToPosition(new Point(x, y)); + else return (int)SPerform(2022, (uint)x, (uint)y); } /// @@ -3080,7 +3528,13 @@ public int PositionFromPointClose(int x, int y) /// public void GotoLine(int line) { - SPerform(2024, (uint)line, 0); + if (this.fctb != null) + { + Int32 nl = Math.Min(this.fctb.LinesCount - 1, Math.Max(0, line - 1)); + this.fctb.Selection = new FastColoredTextBoxNS.Range(this.fctb, 0, nl, 0, nl); + this.fctb.DoSelectionVisible(); + } + else SPerform(2024, (uint)line, 0); } /// @@ -3088,7 +3542,12 @@ public void GotoLine(int line) /// public void GotoPos(int pos) { - SPerform(2025, (uint)pos, 0); + if (this.fctb != null) + { + this.fctb.Selection.Start = this.fctb.PositionToPlace(pos); + this.fctb.DoSelectionVisible(); + } + else SPerform(2025, (uint)pos, 0); } /// @@ -3097,10 +3556,15 @@ public void GotoPos(int pos) /// unsafe public string GetCurLine(int length) { - int sz = (int)SPerform(2027, (uint)length, 0); - byte[] buffer = new byte[sz+1]; - fixed (byte* b = buffer) SPerform(2027, (uint)length+1, (uint)b); - return Encoding.GetEncoding(this.CodePage).GetString(buffer, 0, sz-1); + // TODO: Fix this + if (this.fctb != null) return this.GetLine(this.CurrentLine); + else + { + int sz = (int)SPerform(2027, (uint)length, 0); + byte[] buffer = new byte[sz + 1]; + fixed (byte* b = buffer) SPerform(2027, (uint)length + 1, (uint)b); + return Encoding.GetEncoding(this.CodePage).GetString(buffer, 0, sz - 1); + } } /// @@ -3219,15 +3683,13 @@ unsafe public void MarkerDefinePixmap(int markerNumber, string pixmap ) unsafe public void MarkerDefineRGBAImage(int markerNumber, Bitmap image) { var rgba = RGBA.ConvertToRGBA(image); - - //SCI_RGBAIMAGESETWIDTH + // SCI_RGBAIMAGESETWIDTH SPerform(2624, (uint)image.Width, 0); - //SCI_RGBAIMAGESETHEIGHT + // SCI_RGBAIMAGESETHEIGHT SPerform(2625, (uint)image.Height, 0); - fixed (byte* b = rgba) { - //SCI_MARKERDEFINERGBAIMAGE + // SCI_MARKERDEFINERGBAIMAGE SPerform(2626, (uint)markerNumber, (uint)b); } } @@ -3298,7 +3760,8 @@ unsafe public void SetStylingEx(int length, string styles) /// public void BeginUndoAction() { - SPerform(2078, 0, 0); + if (this.fctb != null) this.fctb.BeginAutoUndo(); + else SPerform(2078, 0, 0); } /// @@ -3306,7 +3769,8 @@ public void BeginUndoAction() /// public void EndUndoAction() { - SPerform(2079, 0, 0); + if (this.fctb != null) this.fctb.EndAutoUndo(); + else SPerform(2079, 0, 0); } /// @@ -3416,19 +3880,28 @@ public void ClearRegisteredImages() /// unsafe public string GetLine(int line) { - int sz = (int)SPerform(2153, (uint)line, 0); - byte[] buffer = new byte[sz + 1]; - fixed (byte* b = buffer) SPerform(2153, (uint)line, (uint)b); - if (sz == 0) return ""; // Empty last line - return Encoding.GetEncoding(this.CodePage).GetString(buffer, 0, sz); + if (this.fctb != null) return (line < 0 || line > this.LineCount - 1) ? this.fctb.GetLineText(line) : ""; + else + { + int sz = (int)SPerform(2153, (uint)line, 0); + byte[] buffer = new byte[sz + 1]; + fixed (byte* b = buffer) SPerform(2153, (uint)line, (uint)b); + if (sz == 0) return ""; // Empty last line + return Encoding.GetEncoding(this.CodePage).GetString(buffer, 0, sz); + } } /// /// Select a range of text. /// public void SetSel(int start, int end) - { - SPerform(2160, (uint)start, (uint)end); + { + if (this.fctb != null) + { + this.fctb.Selection.Start = this.fctb.PositionToPlace(start); + this.fctb.Selection.End = this.fctb.PositionToPlace(end); + } + else SPerform(2160, (uint)start, (uint)end); } /// @@ -3439,13 +3912,17 @@ unsafe public string SelText { get { - int sz = (int)SPerform(2161,0 ,0); - byte[] buffer = new byte[sz+1]; - fixed (byte* b = buffer) + if (this.fctb != null) return this.fctb.SelectedText; + else { - SPerform(2161, (UInt32)sz + 1, (uint)b); + int sz = (int)SPerform(2161, 0, 0); + byte[] buffer = new byte[sz + 1]; + fixed (byte* b = buffer) + { + SPerform(2161, (UInt32)sz + 1, (uint)b); + } + return Encoding.GetEncoding(this.CodePage).GetString(buffer, 0, sz - 1); } - return Encoding.GetEncoding(this.CodePage).GetString(buffer, 0, sz-1); } } @@ -3462,7 +3939,8 @@ public void HideSelection(bool normal) /// public int PointXFromPosition(int pos) { - return (int) SPerform(2164, 0, (uint)pos); + if (this.fctb != null) return this.fctb.PositionToPoint(pos).X; + else return (int)SPerform(2164, 0, (uint)pos); } /// @@ -3470,7 +3948,8 @@ public int PointXFromPosition(int pos) /// public int PointYFromPosition(int pos) { - return (int) SPerform(2165, 0, (uint)pos); + if (this.fctb != null) return this.fctb.PositionToPoint(pos).Y; + else return (int)SPerform(2165, 0, (uint)pos); } /// @@ -3478,7 +3957,8 @@ public int PointYFromPosition(int pos) /// public int LineFromPosition(int pos) { - return (int) SPerform(2166, (uint)pos, 0); + if (this.fctb != null) return this.fctb.PositionToPlace(pos).iLine; + else return (int)SPerform(2166, (uint)pos, 0); } /// @@ -3486,7 +3966,8 @@ public int LineFromPosition(int pos) /// public int PositionFromLine(int line) { - return (int) SPerform(2167, (uint)line, 0); + if (this.fctb != null) return this.fctb.PlaceToPosition(new FastColoredTextBoxNS.Place(0, line)); + else return (int) SPerform(2167, (uint)line, 0); } /// @@ -3507,7 +3988,12 @@ public String GetLineUntilPosition(int pos) /// public void LineScroll(int columns, int lines) { - SPerform(2168, (uint)columns, (uint)lines); + if (this.fctb != null) + { + this.fctb.VerticalScroll.Value += this.fctb.CharHeight; + this.fctb.HorizontalScroll.Value += this.fctb.CharWidth; + } + else SPerform(2168, (uint)columns, (uint)lines); } /// @@ -3515,7 +4001,8 @@ public void LineScroll(int columns, int lines) /// public void ScrollCaret() { - SPerform(2169, 0, 0); + if (this.fctb != null) this.fctb.DoCaretVisible(); + else SPerform(2169, 0, 0); } /// @@ -3523,10 +4010,14 @@ public void ScrollCaret() /// unsafe public void ReplaceSel(string text) { - if (text == null || text.Equals("")) text = "\0\0"; - fixed (byte* b = Encoding.GetEncoding(this.CodePage).GetBytes(text)) + if (this.fctb != null) this.fctb.InsertText(text); + else { - SPerform(2170,0 , (uint)b); + if (text == null || text.Equals("")) text = "\0\0"; + fixed (byte* b = Encoding.GetEncoding(this.CodePage).GetBytes(text)) + { + SPerform(2170, 0, (uint)b); + } } } @@ -3535,7 +4026,7 @@ unsafe public void ReplaceSel(string text) /// public void Null() { - SPerform(2172, 0, 0); + if (this.fctb == null) SPerform(2172, 0, 0); } /// @@ -3543,7 +4034,8 @@ public void Null() /// public void EmptyUndoBuffer() { - SPerform(2175, 0, 0); + if (this.fctb != null) this.fctb.ClearUndo(); + else SPerform(2175, 0, 0); } /// @@ -3551,7 +4043,8 @@ public void EmptyUndoBuffer() /// public void Undo() { - SPerform(2176, 0, 0); + if (this.fctb != null) this.fctb.Undo(); + else SPerform(2176, 0, 0); } /// @@ -3559,7 +4052,8 @@ public void Undo() /// public void Cut() { - SPerform(2177, 0, 0); + if (this.fctb != null) this.fctb.Cut(); + else SPerform(2177, 0, 0); } /// @@ -3567,9 +4061,13 @@ public void Cut() /// public void Copy() { - SPerform(2178, 0, 0); - // Invoke UI update after copy... - if (UpdateUI != null) UpdateUI(this); + if (this.fctb != null) this.fctb.Copy(); + else + { + SPerform(2178, 0, 0); + // Invoke UI update after copy... + if (UpdateUI != null) UpdateUI(this); + } } /// @@ -3577,9 +4075,13 @@ public void Copy() /// public void CopyRTF() { - Language language = ScintillaControl.Configuration.GetLanguage(this.configLanguage); - String conversion = RTF.GetConversion(language, this, this.SelectionStart, this.SelectionEnd); - Clipboard.SetText(conversion, TextDataFormat.Rtf); + if (this.fctb != null) Clipboard.SetText(this.fctb.Rtf, TextDataFormat.Rtf); + else + { + Language language = ScintillaControl.Configuration.GetLanguage(this.configLanguage); + String conversion = RTF.GetConversion(language, this, this.SelectionStart, this.SelectionEnd); + Clipboard.SetText(conversion, TextDataFormat.Rtf); + } } /// @@ -3587,7 +4089,8 @@ public void CopyRTF() /// public void Paste() { - SPerform(2179, 0, 0); + if (this.fctb != null) this.fctb.Paste(); + else SPerform(2179, 0, 0); } /// @@ -3595,7 +4098,8 @@ public void Paste() /// public void Clear() { - SPerform(2180, 0, 0); + if (this.fctb != null) this.fctb.SelectedText = ""; + else SPerform(2180, 0, 0); } /// @@ -3603,6 +4107,11 @@ public void Clear() /// unsafe public void SetText(string text) { + if (this.fctb != null) + { + this.fctb.Text = text; + return; + } if (text == null || text.Equals("")) text = "\0\0"; fixed (byte* b = Encoding.GetEncoding(this.CodePage).GetBytes(text)) { @@ -3615,6 +4124,7 @@ unsafe public void SetText(string text) /// unsafe public string GetText(int length) { + if (this.fctb != null) return this.fctb.Text; int sz = (int)SPerform(2182, (uint)length, 0); byte[] buffer = new byte[sz+1]; fixed (byte* b = buffer)SPerform(2182, (uint)length+1, (uint)b); @@ -3763,7 +4273,8 @@ public void ToggleFold(int line) /// public void EnsureVisible(int line) { - SPerform(2232, (uint)line, 0); + if (this.fctb != null) this.fctb.DoRangeVisible(new FastColoredTextBoxNS.Range(this.fctb, line)); + else SPerform(2232, (uint)line, 0); } /// @@ -3818,6 +4329,7 @@ unsafe public int TextWidth(int style, string text) /// public int TextHeight(int line) { + if (this.fctb != null) return this.fctb.TextHeight; return (int) SPerform(2279, (uint)line, 0); } @@ -3826,6 +4338,11 @@ public int TextHeight(int line) /// unsafe public void AppendText(int length, string text) { + if (this.fctb != null) + { + this.fctb.AppendText(text); + return; + } if (text == null || text.Equals("")) text = "\0\0"; fixed (byte* b = Encoding.GetEncoding(this.CodePage).GetBytes(text)) { @@ -3850,8 +4367,7 @@ public void LinesJoin() } /// - /// Split the lines in the target into lines that are less wide than pixelWidth - /// where possible. + /// Split the lines in the target into lines that are less wide than pixelWidth where possible. /// public void LinesSplit(int pixelWidth) { @@ -3863,7 +4379,15 @@ public void LinesSplit(int pixelWidth) /// public void SetFoldMarginColour(bool useSetting, int back) { - SPerform(2290,(uint)(useSetting ? 1 : 0), (uint)back); + if (this.fctb != null) + { + if (!useSetting) return; + this.fctb.ServiceColors.CollapseMarkerBorderColor = DataConverter.BGRToColor(back); + this.fctb.ServiceColors.CollapseMarkerForeColor = DataConverter.BGRToColor(back); + this.fctb.ServiceColors.ExpandMarkerBorderColor = DataConverter.BGRToColor(back); + this.fctb.ServiceColors.ExpandMarkerForeColor = DataConverter.BGRToColor(back); + } + else SPerform(2290, (uint)(useSetting ? 1 : 0), (uint)back); } /// @@ -3871,7 +4395,13 @@ public void SetFoldMarginColour(bool useSetting, int back) /// public void SetFoldMarginHiColour(bool useSetting, int fore) { - SPerform(2291,(uint)(useSetting ? 1 : 0), (uint)fore); + if (this.fctb != null) + { + if (!useSetting) return; + this.fctb.ServiceColors.CollapseMarkerBackColor = DataConverter.BGRToColor(fore); + this.fctb.ServiceColors.ExpandMarkerBackColor = DataConverter.BGRToColor(fore); + } + else SPerform(2291, (uint)(useSetting ? 1 : 0), (uint)fore); } /// @@ -3879,7 +4409,12 @@ public void SetFoldMarginHiColour(bool useSetting, int fore) /// public void LineDown() { - SPerform(2300, 0, 0); + if (this.fctb != null) + { + if (this.fctb.Selection.ColumnSelectionMode) this.fctb.Selection.GoDown_ColumnSelectionMode(); + else this.fctb.Selection.GoDown(false); + } + else SPerform(2300, 0, 0); } /// @@ -3887,7 +4422,12 @@ public void LineDown() /// public void LineDownExtend() { - SPerform(2301, 0, 0); + if (this.fctb != null) + { + if (this.fctb.Selection.ColumnSelectionMode) this.fctb.Selection.GoDown_ColumnSelectionMode(); + else this.fctb.Selection.GoDown(true); + } + else SPerform(2301, 0, 0); } /// @@ -3895,7 +4435,12 @@ public void LineDownExtend() /// public void LineUp() { - SPerform(2302, 0, 0); + if (this.fctb != null) + { + if (this.fctb.Selection.ColumnSelectionMode) this.fctb.Selection.GoUp_ColumnSelectionMode(); + else this.fctb.Selection.GoUp(false); + } + else SPerform(2302, 0, 0); } /// @@ -3903,7 +4448,12 @@ public void LineUp() /// public void LineUpExtend() { - SPerform(2303, 0, 0); + if (this.fctb != null) + { + if (this.fctb.Selection.ColumnSelectionMode) this.fctb.Selection.GoUp_ColumnSelectionMode(); + else this.fctb.Selection.GoUp(true); + } + else SPerform(2303, 0, 0); } /// @@ -3911,7 +4461,12 @@ public void LineUpExtend() /// public void CharLeft() { - SPerform(2304, 0, 0); + if (this.fctb != null) + { + if (this.fctb.Selection.ColumnSelectionMode) this.fctb.Selection.GoLeft_ColumnSelectionMode(); + else this.fctb.Selection.GoLeft(false); + } + else SPerform(2304, 0, 0); } /// @@ -3919,7 +4474,12 @@ public void CharLeft() /// public void CharLeftExtend() { - SPerform(2305, 0, 0); + if (this.fctb != null) + { + if (this.fctb.Selection.ColumnSelectionMode) this.fctb.Selection.GoLeft_ColumnSelectionMode(); + else this.fctb.Selection.GoLeft(true); + } + else SPerform(2305, 0, 0); } /// @@ -3927,7 +4487,12 @@ public void CharLeftExtend() /// public void CharRight() { - SPerform(2306, 0, 0); + if (this.fctb != null) + { + if (this.fctb.Selection.ColumnSelectionMode) this.fctb.Selection.GoRight_ColumnSelectionMode(); + else this.fctb.Selection.GoRight(false); + } + else SPerform(2306, 0, 0); } /// @@ -3935,7 +4500,12 @@ public void CharRight() /// public void CharRightExtend() { - SPerform(2307, 0, 0); + if (this.fctb != null) + { + if (this.fctb.Selection.ColumnSelectionMode) this.fctb.Selection.GoRight_ColumnSelectionMode(); + else this.fctb.Selection.GoRight(true); + } + else SPerform(2307, 0, 0); } /// @@ -3943,7 +4513,8 @@ public void CharRightExtend() /// public void WordLeft() { - SPerform(2308, 0, 0); + if (this.fctb != null) this.fctb.Selection.GoWordLeft(false); + else SPerform(2308, 0, 0); } /// @@ -3951,7 +4522,8 @@ public void WordLeft() /// public void WordLeftExtend() { - SPerform(2309, 0, 0); + if (this.fctb != null) this.fctb.Selection.GoWordLeft(true); + else SPerform(2309, 0, 0); } /// @@ -3959,7 +4531,8 @@ public void WordLeftExtend() /// public void WordRight() { - SPerform(2310, 0, 0); + if (this.fctb != null) this.fctb.Selection.GoRight(false); + else SPerform(2310, 0, 0); } /// @@ -3967,7 +4540,8 @@ public void WordRight() /// public void WordRightExtend() { - SPerform(2311, 0, 0); + if (this.fctb != null) this.fctb.Selection.GoRight(true); + else SPerform(2311, 0, 0); } /// @@ -3975,7 +4549,8 @@ public void WordRightExtend() /// public void Home() { - SPerform(2312, 0, 0); + if (this.fctb != null) this.fctb.Selection.GoHome(false); + else SPerform(2312, 0, 0); } /// @@ -3983,7 +4558,8 @@ public void Home() /// public void HomeExtend() { - SPerform(2313, 0, 0); + if (this.fctb != null) this.fctb.Selection.GoHome(true); + else SPerform(2313, 0, 0); } /// @@ -3991,7 +4567,8 @@ public void HomeExtend() /// public void LineEnd() { - SPerform(2314, 0, 0); + if (this.fctb != null) this.fctb.Selection.GoEnd(false); + else SPerform(2314, 0, 0); } /// @@ -3999,7 +4576,8 @@ public void LineEnd() /// public void LineEndExtend() { - SPerform(2315, 0, 0); + if (this.fctb != null) this.fctb.Selection.GoEnd(true); + else SPerform(2315, 0, 0); } /// @@ -4007,7 +4585,8 @@ public void LineEndExtend() /// public void DocumentStart() { - SPerform(2316, 0, 0); + if (this.fctb != null) this.fctb.Selection.GoFirst(false); + else SPerform(2316, 0, 0); } /// @@ -4015,7 +4594,8 @@ public void DocumentStart() /// public void DocumentStartExtend() { - SPerform(2317, 0, 0); + if (this.fctb != null) this.fctb.Selection.GoFirst(true); + else SPerform(2317, 0, 0); } /// @@ -4023,7 +4603,8 @@ public void DocumentStartExtend() /// public void DocumentEnd() { - SPerform(2318, 0, 0); + if (this.fctb != null) this.fctb.Selection.GoLast(false); + else SPerform(2318, 0, 0); } /// @@ -4031,7 +4612,8 @@ public void DocumentEnd() /// public void DocumentEndExtend() { - SPerform(2319, 0, 0); + if (this.fctb != null) this.fctb.Selection.GoLast(true); + else SPerform(2319, 0, 0); } /// @@ -4039,7 +4621,8 @@ public void DocumentEndExtend() /// public void PageUp() { - SPerform(2320, 0, 0); + if (this.fctb != null) this.fctb.Selection.GoPageUp(false); + else SPerform(2320, 0, 0); } /// @@ -4047,7 +4630,8 @@ public void PageUp() /// public void PageUpExtend() { - SPerform(2321, 0, 0); + if (this.fctb != null) this.fctb.Selection.GoPageUp(true); + else SPerform(2321, 0, 0); } /// @@ -4055,7 +4639,8 @@ public void PageUpExtend() /// public void PageDown() { - SPerform(2322, 0, 0); + if (this.fctb != null) this.fctb.Selection.GoPageDown(false); + else SPerform(2322, 0, 0); } /// @@ -4063,7 +4648,8 @@ public void PageDown() /// public void PageDownExtend() { - SPerform(2323, 0, 0); + if (this.fctb != null) this.fctb.Selection.GoPageDown(true); + else SPerform(2323, 0, 0); } /// @@ -4071,7 +4657,8 @@ public void PageDownExtend() /// public void EditToggleOvertype() { - SPerform(2324, 0, 0); + if (this.fctb != null) this.fctb.IsReplaceMode = !this.fctb.IsReplaceMode; + else SPerform(2324, 0, 0); } /// @@ -4087,7 +4674,16 @@ public void Cancel() /// public void DeleteBack() { - SPerform(2326, 0, 0); + if (this.fctb != null) + { + if (!this.fctb.Selection.IsEmpty) this.fctb.ClearSelected(); + else + { + this.SetSel(this.CurrentPos - 1, this.CurrentPos); + this.fctb.ClearSelected(); + } + } + else SPerform(2326, 0, 0); } /// @@ -4105,7 +4701,8 @@ public void DeleteForward() /// public void Tab() { - SPerform(2327, 0, 0); + if (this.fctb != null) this.fctb.IncreaseIndent(); + else SPerform(2327, 0, 0); } /// @@ -4113,7 +4710,8 @@ public void Tab() /// public void BackTab() { - SPerform(2328, 0, 0); + if (this.fctb != null) this.fctb.DecreaseIndent(); + else SPerform(2328, 0, 0); } /// @@ -4121,7 +4719,12 @@ public void BackTab() /// public void NewLine() { - SPerform(2329, 0, 0); + if (this.fctb != null) + { + int index = this.CurrentLine - 1; + this.fctb.TextSource.Insert(index, this.fctb.TextSource.CreateLine()); + } + else SPerform(2329, 0, 0); } /// @@ -5311,7 +5914,7 @@ protected override void WndProc(ref System.Windows.Forms.Message m) if (FocusChanged != null) FocusChanged(this); } } - else if (m.Msg == WM_NOTIFY) + else if (this.fctb == null && m.Msg == WM_NOTIFY) { SCNotification scn = (SCNotification)Marshal.PtrToStructure(m.LParam, typeof(SCNotification)); if (scn.nmhdr.hwndFrom == hwndScintilla && !this.DisableAllSciEvents) From 05e1c08b733da29f5e0ce18951085a70eb6d4c44 Mon Sep 17 00:00:00 2001 From: Mika Palmu Date: Fri, 12 Jun 2015 13:21:03 +0300 Subject: [PATCH 03/12] More progress and missing files added... --- PluginCore/FastColoredTB/AutocompleteItem.cs | 266 + PluginCore/FastColoredTB/AutocompleteMenu.cs | 723 ++ PluginCore/FastColoredTB/Bookmarks.cs | 256 + PluginCore/FastColoredTB/Char.cs | 26 + PluginCore/FastColoredTB/CommandManager.cs | 239 + PluginCore/FastColoredTB/Commands.cs | 809 ++ PluginCore/FastColoredTB/CustomHighlighter.cs | 95 + PluginCore/FastColoredTB/DocumentMap.cs | 250 + PluginCore/FastColoredTB/EncodingDetector.cs | 363 + PluginCore/FastColoredTB/ExportToHTML.cs | 222 + PluginCore/FastColoredTB/ExportToRTF.cs | 217 + .../FastColoredTB/FastColoredTextBox.cs | 8572 +++++++++++++++++ .../FastColoredTB/FastColoredTextBox.resx | 120 + PluginCore/FastColoredTB/FileTextSource.cs | 453 + PluginCore/FastColoredTB/FindForm.Designer.cs | 146 + PluginCore/FastColoredTB/FindForm.cs | 129 + PluginCore/FastColoredTB/FindForm.resx | 120 + PluginCore/FastColoredTB/GoToForm.Designer.cs | 110 + PluginCore/FastColoredTB/GoToForm.cs | 53 + PluginCore/FastColoredTB/GoToForm.resx | 120 + PluginCore/FastColoredTB/Hints.cs | 364 + PluginCore/FastColoredTB/Hotkeys.cs | 251 + .../HotkeysEditorForm.Designer.cs | 210 + PluginCore/FastColoredTB/HotkeysEditorForm.cs | 179 + .../FastColoredTB/HotkeysEditorForm.resx | 129 + PluginCore/FastColoredTB/LimitedStack.cs | 105 + PluginCore/FastColoredTB/Line.cs | 289 + PluginCore/FastColoredTB/LinesAccessor.cs | 98 + PluginCore/FastColoredTB/MacrosManager.cs | 183 + PluginCore/FastColoredTB/Place.cs | 99 + PluginCore/FastColoredTB/PlatformType.cs | 75 + PluginCore/FastColoredTB/Range.cs | 1678 ++++ .../FastColoredTB/ReplaceForm.Designer.cs | 196 + PluginCore/FastColoredTB/ReplaceForm.cs | 187 + PluginCore/FastColoredTB/ReplaceForm.resx | 120 + PluginCore/FastColoredTB/Ruler.Designer.cs | 37 + PluginCore/FastColoredTB/Ruler.cs | 138 + PluginCore/FastColoredTB/Style.cs | 430 + PluginCore/FastColoredTB/SyntaxDescriptor.cs | 51 + PluginCore/FastColoredTB/SyntaxHighlighter.cs | 1381 +++ PluginCore/FastColoredTB/TextSource.cs | 339 + PluginCore/FastColoredTB/TypeDescriptor.cs | 96 + PluginCore/FastColoredTB/UnfocusablePanel.cs | 41 + PluginCore/FastColoredTB/VisualMarker.cs | 106 + PluginCore/PluginCore.csproj | 1 + .../PluginCore/Utilities/DataConverter.cs | 4 + PluginCore/ScintillaNet/ScintillaControl.cs | 162 +- 47 files changed, 20206 insertions(+), 32 deletions(-) create mode 100644 PluginCore/FastColoredTB/AutocompleteItem.cs create mode 100644 PluginCore/FastColoredTB/AutocompleteMenu.cs create mode 100644 PluginCore/FastColoredTB/Bookmarks.cs create mode 100644 PluginCore/FastColoredTB/Char.cs create mode 100644 PluginCore/FastColoredTB/CommandManager.cs create mode 100644 PluginCore/FastColoredTB/Commands.cs create mode 100644 PluginCore/FastColoredTB/CustomHighlighter.cs create mode 100644 PluginCore/FastColoredTB/DocumentMap.cs create mode 100644 PluginCore/FastColoredTB/EncodingDetector.cs create mode 100644 PluginCore/FastColoredTB/ExportToHTML.cs create mode 100644 PluginCore/FastColoredTB/ExportToRTF.cs create mode 100644 PluginCore/FastColoredTB/FastColoredTextBox.cs create mode 100644 PluginCore/FastColoredTB/FastColoredTextBox.resx create mode 100644 PluginCore/FastColoredTB/FileTextSource.cs create mode 100644 PluginCore/FastColoredTB/FindForm.Designer.cs create mode 100644 PluginCore/FastColoredTB/FindForm.cs create mode 100644 PluginCore/FastColoredTB/FindForm.resx create mode 100644 PluginCore/FastColoredTB/GoToForm.Designer.cs create mode 100644 PluginCore/FastColoredTB/GoToForm.cs create mode 100644 PluginCore/FastColoredTB/GoToForm.resx create mode 100644 PluginCore/FastColoredTB/Hints.cs create mode 100644 PluginCore/FastColoredTB/Hotkeys.cs create mode 100644 PluginCore/FastColoredTB/HotkeysEditorForm.Designer.cs create mode 100644 PluginCore/FastColoredTB/HotkeysEditorForm.cs create mode 100644 PluginCore/FastColoredTB/HotkeysEditorForm.resx create mode 100644 PluginCore/FastColoredTB/LimitedStack.cs create mode 100644 PluginCore/FastColoredTB/Line.cs create mode 100644 PluginCore/FastColoredTB/LinesAccessor.cs create mode 100644 PluginCore/FastColoredTB/MacrosManager.cs create mode 100644 PluginCore/FastColoredTB/Place.cs create mode 100644 PluginCore/FastColoredTB/PlatformType.cs create mode 100644 PluginCore/FastColoredTB/Range.cs create mode 100644 PluginCore/FastColoredTB/ReplaceForm.Designer.cs create mode 100644 PluginCore/FastColoredTB/ReplaceForm.cs create mode 100644 PluginCore/FastColoredTB/ReplaceForm.resx create mode 100644 PluginCore/FastColoredTB/Ruler.Designer.cs create mode 100644 PluginCore/FastColoredTB/Ruler.cs create mode 100644 PluginCore/FastColoredTB/Style.cs create mode 100644 PluginCore/FastColoredTB/SyntaxDescriptor.cs create mode 100644 PluginCore/FastColoredTB/SyntaxHighlighter.cs create mode 100644 PluginCore/FastColoredTB/TextSource.cs create mode 100644 PluginCore/FastColoredTB/TypeDescriptor.cs create mode 100644 PluginCore/FastColoredTB/UnfocusablePanel.cs create mode 100644 PluginCore/FastColoredTB/VisualMarker.cs diff --git a/PluginCore/FastColoredTB/AutocompleteItem.cs b/PluginCore/FastColoredTB/AutocompleteItem.cs new file mode 100644 index 0000000000..59feec4d63 --- /dev/null +++ b/PluginCore/FastColoredTB/AutocompleteItem.cs @@ -0,0 +1,266 @@ +using System; +using System.Drawing; +using System.Drawing.Printing; + +namespace FastColoredTextBoxNS +{ + /// + /// Item of autocomplete menu + /// + public class AutocompleteItem + { + public string Text; + public int ImageIndex = -1; + public object Tag; + string toolTipTitle; + string toolTipText; + string menuText; + public AutocompleteMenu Parent { get; internal set; } + + + public AutocompleteItem() + { + } + + public AutocompleteItem(string text) + { + Text = text; + } + + public AutocompleteItem(string text, int imageIndex) + : this(text) + { + this.ImageIndex = imageIndex; + } + + public AutocompleteItem(string text, int imageIndex, string menuText) + : this(text, imageIndex) + { + this.menuText = menuText; + } + + public AutocompleteItem(string text, int imageIndex, string menuText, string toolTipTitle, string toolTipText) + : this(text, imageIndex, menuText) + { + this.toolTipTitle = toolTipTitle; + this.toolTipText = toolTipText; + } + + /// + /// Returns text for inserting into Textbox + /// + public virtual string GetTextForReplace() + { + return Text; + } + + /// + /// Compares fragment text with this item + /// + public virtual CompareResult Compare(string fragmentText) + { + if (Text.StartsWith(fragmentText, StringComparison.InvariantCultureIgnoreCase) && + Text != fragmentText) + return CompareResult.VisibleAndSelected; + + return CompareResult.Hidden; + } + + /// + /// Returns text for display into popup menu + /// + public override string ToString() + { + return menuText ?? Text; + } + + /// + /// This method is called after item inserted into text + /// + public virtual void OnSelected(AutocompleteMenu popupMenu, SelectedEventArgs e) + { + ; + } + + /// + /// Title for tooltip. + /// + /// Return null for disable tooltip for this item + public virtual string ToolTipTitle + { + get { return toolTipTitle; } + set { toolTipTitle = value; } + } + + /// + /// Tooltip text. + /// + /// For display tooltip text, ToolTipTitle must be not null + public virtual string ToolTipText + { + get{ return toolTipText; } + set { toolTipText = value; } + } + + /// + /// Menu text. This text is displayed in the drop-down menu. + /// + public virtual string MenuText + { + get { return menuText; } + set { menuText = value; } + } + + /// + /// Fore color of text of item + /// + public virtual Color ForeColor + { + get { return Color.Transparent; } + set { throw new NotImplementedException("Override this property to change color"); } + } + + /// + /// Back color of item + /// + public virtual Color BackColor + { + get { return Color.Transparent; } + set { throw new NotImplementedException("Override this property to change color"); } + } + } + + public enum CompareResult + { + /// + /// Item do not appears + /// + Hidden, + /// + /// Item appears + /// + Visible, + /// + /// Item appears and will selected + /// + VisibleAndSelected + } + + /// + /// Autocomplete item for code snippets + /// + /// Snippet can contain special char ^ for caret position. + public class SnippetAutocompleteItem : AutocompleteItem + { + public SnippetAutocompleteItem(string snippet) + { + Text = snippet.Replace("\r", ""); + ToolTipTitle = "Code snippet:"; + ToolTipText = Text; + } + + public override string ToString() + { + return MenuText ?? Text.Replace("\n", " ").Replace("^", ""); + } + + public override string GetTextForReplace() + { + return Text; + } + + public override void OnSelected(AutocompleteMenu popupMenu, SelectedEventArgs e) + { + e.Tb.BeginUpdate(); + e.Tb.Selection.BeginUpdate(); + //remember places + var p1 = popupMenu.Fragment.Start; + var p2 = e.Tb.Selection.Start; + //do auto indent + if (e.Tb.AutoIndent) + { + for (int iLine = p1.iLine + 1; iLine <= p2.iLine; iLine++) + { + e.Tb.Selection.Start = new Place(0, iLine); + e.Tb.DoAutoIndent(iLine); + } + } + e.Tb.Selection.Start = p1; + //move caret position right and find char ^ + while (e.Tb.Selection.CharBeforeStart != '^') + if (!e.Tb.Selection.GoRightThroughFolded()) + break; + //remove char ^ + e.Tb.Selection.GoLeft(true); + e.Tb.InsertText(""); + // + e.Tb.Selection.EndUpdate(); + e.Tb.EndUpdate(); + } + + /// + /// Compares fragment text with this item + /// + public override CompareResult Compare(string fragmentText) + { + if (Text.StartsWith(fragmentText, StringComparison.InvariantCultureIgnoreCase) && + Text != fragmentText) + return CompareResult.Visible; + + return CompareResult.Hidden; + } + } + + /// + /// This autocomplete item appears after dot + /// + public class MethodAutocompleteItem : AutocompleteItem + { + string firstPart; + string lowercaseText; + + public MethodAutocompleteItem(string text) + : base(text) + { + lowercaseText = Text.ToLower(); + } + + public override CompareResult Compare(string fragmentText) + { + int i = fragmentText.LastIndexOf('.'); + if (i < 0) + return CompareResult.Hidden; + string lastPart = fragmentText.Substring(i + 1); + firstPart = fragmentText.Substring(0, i); + + if(lastPart=="") return CompareResult.Visible; + if(Text.StartsWith(lastPart, StringComparison.InvariantCultureIgnoreCase)) + return CompareResult.VisibleAndSelected; + if(lowercaseText.Contains(lastPart.ToLower())) + return CompareResult.Visible; + + return CompareResult.Hidden; + } + + public override string GetTextForReplace() + { + return firstPart + "." + Text; + } + } + + /// + /// This Item does not check correspondence to current text fragment. + /// SuggestItem is intended for dynamic menus. + /// + public class SuggestItem : AutocompleteItem + { + public SuggestItem(string text, int imageIndex):base(text, imageIndex) + { + } + + public override CompareResult Compare(string fragmentText) + { + return CompareResult.Visible; + } + } +} diff --git a/PluginCore/FastColoredTB/AutocompleteMenu.cs b/PluginCore/FastColoredTB/AutocompleteMenu.cs new file mode 100644 index 0000000000..0e4705af10 --- /dev/null +++ b/PluginCore/FastColoredTB/AutocompleteMenu.cs @@ -0,0 +1,723 @@ +using System; +using System.Collections.Generic; +using System.Windows.Forms; +using System.Drawing; +using System.ComponentModel; +using System.Drawing.Drawing2D; +using System.Text.RegularExpressions; + +namespace FastColoredTextBoxNS +{ + /// + /// Popup menu for autocomplete + /// + [Browsable(false)] + public class AutocompleteMenu : ToolStripDropDown + { + AutocompleteListView listView; + public ToolStripControlHost host; + public Range Fragment { get; internal set; } + + /// + /// Regex pattern for serach fragment around caret + /// + public string SearchPattern { get; set; } + /// + /// Minimum fragment length for popup + /// + public int MinFragmentLength { get; set; } + /// + /// User selects item + /// + public event EventHandler Selecting; + /// + /// It fires after item inserting + /// + public event EventHandler Selected; + /// + /// Occurs when popup menu is opening + /// + public new event EventHandler Opening; + /// + /// Allow TAB for select menu item + /// + public bool AllowTabKey { get { return listView.AllowTabKey; } set { listView.AllowTabKey = value; } } + /// + /// Interval of menu appear (ms) + /// + public int AppearInterval { get { return listView.AppearInterval; } set { listView.AppearInterval = value; } } + + /// + /// Back color of selected item + /// + [DefaultValue(typeof(Color), "Orange")] + public Color SelectedColor + { + get { return listView.SelectedColor; } + set { listView.SelectedColor = value; } + } + + /// + /// Border color of hovered item + /// + [DefaultValue(typeof(Color), "Red")] + public Color HoveredColor + { + get { return listView.HoveredColor; } + set { listView.HoveredColor = value; } + } + + public AutocompleteMenu(FastColoredTextBox tb) + { + // create a new popup and add the list view to it + AutoClose = false; + AutoSize = false; + Margin = Padding.Empty; + Padding = Padding.Empty; + BackColor = Color.White; + listView = new AutocompleteListView(tb); + host = new ToolStripControlHost(listView); + host.Margin = new Padding(2, 2, 2, 2); + host.Padding = Padding.Empty; + host.AutoSize = false; + host.AutoToolTip = false; + CalcSize(); + base.Items.Add(host); + listView.Parent = this; + SearchPattern = @"[\w\.]"; + MinFragmentLength = 2; + + } + + public new Font Font + { + get { return listView.Font; } + set { listView.Font = value; } + } + + new internal void OnOpening(CancelEventArgs args) + { + if (Opening != null) + Opening(this, args); + } + + public new void Close() + { + listView.toolTip.Hide(listView); + base.Close(); + } + + internal void CalcSize() + { + host.Size = listView.Size; + Size = new System.Drawing.Size(listView.Size.Width + 4, listView.Size.Height + 4); + } + + public virtual void OnSelecting() + { + listView.OnSelecting(); + } + + public void SelectNext(int shift) + { + listView.SelectNext(shift); + } + + internal void OnSelecting(SelectingEventArgs args) + { + if (Selecting != null) + Selecting(this, args); + } + + public void OnSelected(SelectedEventArgs args) + { + if (Selected != null) + Selected(this, args); + } + + public new AutocompleteListView Items + { + get { return listView; } + } + + /// + /// Shows popup menu immediately + /// + /// If True - MinFragmentLength will be ignored + public void Show(bool forced) + { + Items.DoAutocomplete(forced); + } + + /// + /// Minimal size of menu + /// + public new Size MinimumSize + { + get { return Items.MinimumSize; } + set { Items.MinimumSize = value; } + } + + /// + /// Image list of menu + /// + public new ImageList ImageList + { + get { return Items.ImageList; } + set { Items.ImageList = value; } + } + + /// + /// Tooltip duration (ms) + /// + public int ToolTipDuration + { + get { return Items.ToolTipDuration; } + set { Items.ToolTipDuration = value; } + } + + /// + /// Tooltip + /// + public ToolTip ToolTip + { + get { return Items.toolTip; } + set { Items.toolTip = value; } + } + } + + [System.ComponentModel.ToolboxItem(false)] + public class AutocompleteListView : UserControl + { + public event EventHandler FocussedItemIndexChanged; + + internal List visibleItems; + IEnumerable sourceItems = new List(); + int focussedItemIndex = 0; + int hoveredItemIndex = -1; + + private int ItemHeight + { + get { return Font.Height + 2; } + } + + AutocompleteMenu Menu { get { return Parent as AutocompleteMenu; } } + int oldItemCount = 0; + FastColoredTextBox tb; + internal ToolTip toolTip = new ToolTip(); + System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer(); + + internal bool AllowTabKey { get; set; } + public ImageList ImageList { get; set; } + internal int AppearInterval { get { return timer.Interval; } set { timer.Interval = value; } } + internal int ToolTipDuration { get; set; } + + public Color SelectedColor { get; set; } + public Color HoveredColor { get; set; } + public int FocussedItemIndex + { + get { return focussedItemIndex; } + set + { + if (focussedItemIndex != value) + { + focussedItemIndex = value; + if (FocussedItemIndexChanged != null) + FocussedItemIndexChanged(this, EventArgs.Empty); + } + } + } + + public AutocompleteItem FocussedItem + { + get + { + if (FocussedItemIndex >= 0 && focussedItemIndex < visibleItems.Count) + return visibleItems[focussedItemIndex]; + return null; + } + set + { + FocussedItemIndex = visibleItems.IndexOf(value); + } + } + + internal AutocompleteListView(FastColoredTextBox tb) + { + SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint, true); + base.Font = new Font(FontFamily.GenericSansSerif, 9); + visibleItems = new List(); + VerticalScroll.SmallChange = ItemHeight; + MaximumSize = new Size(Size.Width, 180); + toolTip.ShowAlways = false; + AppearInterval = 500; + timer.Tick += new EventHandler(timer_Tick); + SelectedColor = Color.Orange; + HoveredColor = Color.Red; + ToolTipDuration = 3000; + + this.tb = tb; + + tb.KeyDown += new KeyEventHandler(tb_KeyDown); + tb.SelectionChanged += new EventHandler(tb_SelectionChanged); + tb.KeyPressed += new KeyPressEventHandler(tb_KeyPressed); + + Form form = tb.FindForm(); + if (form != null) + { + form.LocationChanged += (o, e) => Menu.Close(); + form.ResizeBegin += (o, e) => Menu.Close(); + form.FormClosing += (o, e) => Menu.Close(); + form.LostFocus += (o, e) => Menu.Close(); + } + + tb.LostFocus += (o, e) => + { + if (!Menu.Focused) Menu.Close(); + }; + + tb.Scroll += (o, e) => Menu.Close(); + + this.VisibleChanged += (o, e) => + { + if (this.Visible) + DoSelectedVisible(); + }; + } + + void tb_KeyPressed(object sender, KeyPressEventArgs e) + { + bool backspaceORdel = e.KeyChar == '\b' || e.KeyChar == 0xff; + + /* + if (backspaceORdel) + prevSelection = tb.Selection.Start;*/ + + if (Menu.Visible && !backspaceORdel) + DoAutocomplete(false); + else + ResetTimer(timer); + } + + void timer_Tick(object sender, EventArgs e) + { + timer.Stop(); + DoAutocomplete(false); + } + + void ResetTimer(System.Windows.Forms.Timer timer) + { + timer.Stop(); + timer.Start(); + } + + internal void DoAutocomplete() + { + DoAutocomplete(false); + } + + internal void DoAutocomplete(bool forced) + { + if (!Menu.Enabled) + { + Menu.Close(); + return; + } + + visibleItems.Clear(); + FocussedItemIndex = 0; + VerticalScroll.Value = 0; + //some magic for update scrolls + AutoScrollMinSize -= new Size(1, 0); + AutoScrollMinSize += new Size(1, 0); + //get fragment around caret + Range fragment = tb.Selection.GetFragment(Menu.SearchPattern); + string text = fragment.Text; + //calc screen point for popup menu + Point point = tb.PlaceToPoint(fragment.End); + point.Offset(2, tb.CharHeight); + // + if (forced || (text.Length >= Menu.MinFragmentLength + && tb.Selection.IsEmpty /*pops up only if selected range is empty*/ + && (tb.Selection.Start > fragment.Start || text.Length == 0/*pops up only if caret is after first letter*/))) + { + Menu.Fragment = fragment; + bool foundSelected = false; + //build popup menu + foreach (var item in sourceItems) + { + item.Parent = Menu; + CompareResult res = item.Compare(text); + if(res != CompareResult.Hidden) + visibleItems.Add(item); + if (res == CompareResult.VisibleAndSelected && !foundSelected) + { + foundSelected = true; + FocussedItemIndex = visibleItems.Count - 1; + } + } + + if (foundSelected) + { + AdjustScroll(); + DoSelectedVisible(); + } + } + + //show popup menu + if (Count > 0) + { + if (!Menu.Visible) + { + CancelEventArgs args = new CancelEventArgs(); + Menu.OnOpening(args); + if(!args.Cancel) + Menu.Show(tb, point); + } + else + Invalidate(); + } + else + Menu.Close(); + } + + void tb_SelectionChanged(object sender, EventArgs e) + { + /* + FastColoredTextBox tb = sender as FastColoredTextBox; + + if (Math.Abs(prevSelection.iChar - tb.Selection.Start.iChar) > 1 || + prevSelection.iLine != tb.Selection.Start.iLine) + Menu.Close(); + prevSelection = tb.Selection.Start;*/ + if (Menu.Visible) + { + bool needClose = false; + + if (!tb.Selection.IsEmpty) + needClose = true; + else + if (!Menu.Fragment.Contains(tb.Selection.Start)) + { + if (tb.Selection.Start.iLine == Menu.Fragment.End.iLine && tb.Selection.Start.iChar == Menu.Fragment.End.iChar + 1) + { + //user press key at end of fragment + char c = tb.Selection.CharBeforeStart; + if (!Regex.IsMatch(c.ToString(), Menu.SearchPattern))//check char + needClose = true; + } + else + needClose = true; + } + + if (needClose) + Menu.Close(); + } + + } + + void tb_KeyDown(object sender, KeyEventArgs e) + { + var tb = sender as FastColoredTextBox; + + if (Menu.Visible) + if (ProcessKey(e.KeyCode, e.Modifiers)) + e.Handled = true; + + if (!Menu.Visible) + { + if (tb.HotkeysMapping.ContainsKey(e.KeyData) && tb.HotkeysMapping[e.KeyData] == FCTBAction.AutocompleteMenu) + { + DoAutocomplete(); + e.Handled = true; + } + else + { + if (e.KeyCode == Keys.Escape && timer.Enabled) + timer.Stop(); + } + } + } + + void AdjustScroll() + { + if (oldItemCount == visibleItems.Count) + return; + + int needHeight = ItemHeight * visibleItems.Count + 1; + Height = Math.Min(needHeight, MaximumSize.Height); + Menu.CalcSize(); + + AutoScrollMinSize = new Size(0, needHeight); + oldItemCount = visibleItems.Count; + } + + protected override void OnPaint(PaintEventArgs e) + { + AdjustScroll(); + + var itemHeight = ItemHeight; + int startI = VerticalScroll.Value / itemHeight - 1; + int finishI = (VerticalScroll.Value + ClientSize.Height) / itemHeight + 1; + startI = Math.Max(startI, 0); + finishI = Math.Min(finishI, visibleItems.Count); + int y = 0; + int leftPadding = 18; + for (int i = startI; i < finishI; i++) + { + y = i * itemHeight - VerticalScroll.Value; + + var item = visibleItems[i]; + + if(item.BackColor != Color.Transparent) + using (var brush = new SolidBrush(item.BackColor)) + e.Graphics.FillRectangle(brush, 1, y, ClientSize.Width - 1 - 1, itemHeight - 1); + + if (ImageList != null && visibleItems[i].ImageIndex >= 0) + e.Graphics.DrawImage(ImageList.Images[item.ImageIndex], 1, y); + + if (i == FocussedItemIndex) + using (var selectedBrush = new LinearGradientBrush(new Point(0, y - 3), new Point(0, y + itemHeight), Color.Transparent, SelectedColor)) + using (var pen = new Pen(SelectedColor)) + { + e.Graphics.FillRectangle(selectedBrush, leftPadding, y, ClientSize.Width - 1 - leftPadding, itemHeight - 1); + e.Graphics.DrawRectangle(pen, leftPadding, y, ClientSize.Width - 1 - leftPadding, itemHeight - 1); + } + + if (i == hoveredItemIndex) + using(var pen = new Pen(HoveredColor)) + e.Graphics.DrawRectangle(pen, leftPadding, y, ClientSize.Width - 1 - leftPadding, itemHeight - 1); + + using (var brush = new SolidBrush(item.ForeColor != Color.Transparent ? item.ForeColor : ForeColor)) + e.Graphics.DrawString(item.ToString(), Font, brush, leftPadding, y); + } + } + + protected override void OnScroll(ScrollEventArgs se) + { + base.OnScroll(se); + Invalidate(); + } + + protected override void OnMouseClick(MouseEventArgs e) + { + base.OnMouseClick(e); + + if (e.Button == System.Windows.Forms.MouseButtons.Left) + { + FocussedItemIndex = PointToItemIndex(e.Location); + DoSelectedVisible(); + Invalidate(); + } + } + + protected override void OnMouseDoubleClick(MouseEventArgs e) + { + base.OnMouseDoubleClick(e); + FocussedItemIndex = PointToItemIndex(e.Location); + Invalidate(); + OnSelecting(); + } + + internal virtual void OnSelecting() + { + if (FocussedItemIndex < 0 || FocussedItemIndex >= visibleItems.Count) + return; + tb.TextSource.Manager.BeginAutoUndoCommands(); + try + { + AutocompleteItem item = FocussedItem; + SelectingEventArgs args = new SelectingEventArgs() + { + Item = item, + SelectedIndex = FocussedItemIndex + }; + + Menu.OnSelecting(args); + + if (args.Cancel) + { + FocussedItemIndex = args.SelectedIndex; + Invalidate(); + return; + } + + if (!args.Handled) + { + var fragment = Menu.Fragment; + DoAutocomplete(item, fragment); + } + + Menu.Close(); + // + SelectedEventArgs args2 = new SelectedEventArgs() + { + Item = item, + Tb = Menu.Fragment.tb + }; + item.OnSelected(Menu, args2); + Menu.OnSelected(args2); + } + finally + { + tb.TextSource.Manager.EndAutoUndoCommands(); + } + } + + private void DoAutocomplete(AutocompleteItem item, Range fragment) + { + string newText = item.GetTextForReplace(); + + //replace text of fragment + var tb = fragment.tb; + + tb.BeginAutoUndo(); + tb.TextSource.Manager.ExecuteCommand(new SelectCommand(tb.TextSource)); + if (tb.Selection.ColumnSelectionMode) + { + var start = tb.Selection.Start; + var end = tb.Selection.End; + start.iChar = fragment.Start.iChar; + end.iChar = fragment.End.iChar; + tb.Selection.Start = start; + tb.Selection.End = end; + } + else + { + tb.Selection.Start = fragment.Start; + tb.Selection.End = fragment.End; + } + tb.InsertText(newText); + tb.TextSource.Manager.ExecuteCommand(new SelectCommand(tb.TextSource)); + tb.EndAutoUndo(); + tb.Focus(); + } + + int PointToItemIndex(Point p) + { + return (p.Y + VerticalScroll.Value) / ItemHeight; + } + + protected override bool ProcessCmdKey(ref Message msg, Keys keyData) + { + ProcessKey(keyData, Keys.None); + + return base.ProcessCmdKey(ref msg, keyData); + } + + private bool ProcessKey(Keys keyData, Keys keyModifiers) + { + if (keyModifiers == Keys.None) + switch (keyData) + { + case Keys.Down: + SelectNext(+1); + return true; + case Keys.PageDown: + SelectNext(+10); + return true; + case Keys.Up: + SelectNext(-1); + return true; + case Keys.PageUp: + SelectNext(-10); + return true; + case Keys.Enter: + OnSelecting(); + return true; + case Keys.Tab: + if (!AllowTabKey) + break; + OnSelecting(); + return true; + case Keys.Escape: + Menu.Close(); + return true; + } + + return false; + } + + public void SelectNext(int shift) + { + FocussedItemIndex = Math.Max(0, Math.Min(FocussedItemIndex + shift, visibleItems.Count - 1)); + DoSelectedVisible(); + // + Invalidate(); + } + + private void DoSelectedVisible() + { + if (FocussedItem != null) + SetToolTip(FocussedItem); + + var y = FocussedItemIndex * ItemHeight - VerticalScroll.Value; + if (y < 0) + VerticalScroll.Value = FocussedItemIndex * ItemHeight; + if (y > ClientSize.Height - ItemHeight) + VerticalScroll.Value = Math.Min(VerticalScroll.Maximum, FocussedItemIndex * ItemHeight - ClientSize.Height + ItemHeight); + //some magic for update scrolls + AutoScrollMinSize -= new Size(1, 0); + AutoScrollMinSize += new Size(1, 0); + } + + private void SetToolTip(AutocompleteItem autocompleteItem) + { + var title = autocompleteItem.ToolTipTitle; + var text = autocompleteItem.ToolTipText; + + if (string.IsNullOrEmpty(title)) + { + toolTip.ToolTipTitle = null; + toolTip.SetToolTip(this, null); + return; + } + + IWin32Window window = this.Parent ?? this; + Point location = new Point((window == this ? Width : Right) + 3, 0); + + if (string.IsNullOrEmpty(text)) + { + toolTip.ToolTipTitle = null; + toolTip.Show(title, window, location.X, location.Y, ToolTipDuration); + } + else + { + toolTip.ToolTipTitle = title; + toolTip.Show(text, window, location.X, location.Y, ToolTipDuration); + } + } + + public int Count + { + get { return visibleItems.Count; } + } + + public void SetAutocompleteItems(ICollection items) + { + List list = new List(items.Count); + foreach (var item in items) + list.Add(new AutocompleteItem(item)); + SetAutocompleteItems(list); + } + + public void SetAutocompleteItems(IEnumerable items) + { + sourceItems = items; + } + } + + public class SelectingEventArgs : EventArgs + { + public AutocompleteItem Item { get; internal set; } + public bool Cancel {get;set;} + public int SelectedIndex{get;set;} + public bool Handled { get; set; } + } + + public class SelectedEventArgs : EventArgs + { + public AutocompleteItem Item { get; internal set; } + public FastColoredTextBox Tb { get; set; } + } +} diff --git a/PluginCore/FastColoredTB/Bookmarks.cs b/PluginCore/FastColoredTB/Bookmarks.cs new file mode 100644 index 0000000000..ad220d98e3 --- /dev/null +++ b/PluginCore/FastColoredTB/Bookmarks.cs @@ -0,0 +1,256 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Text; + +namespace FastColoredTextBoxNS +{ + /// + /// Base class for bookmark collection + /// + public abstract class BaseBookmarks : ICollection, IDisposable + { + #region ICollection + public abstract void Add(Bookmark item); + public abstract void Clear(); + public abstract bool Contains(Bookmark item); + public abstract void CopyTo(Bookmark[] array, int arrayIndex); + public abstract int Count { get; } + public abstract bool IsReadOnly { get; } + public abstract bool Remove(Bookmark item); + public abstract IEnumerator GetEnumerator(); + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + #endregion + + #region IDisposable + public abstract void Dispose(); + #endregion + + #region Additional properties + + public abstract void Add(int lineIndex, string bookmarkName); + public abstract void Add(int lineIndex); + public abstract bool Contains(int lineIndex); + public abstract bool Remove(int lineIndex); + public abstract Bookmark GetBookmark(int i); + + #endregion + } + + /// + /// Collection of bookmarks + /// + public class Bookmarks : BaseBookmarks + { + protected FastColoredTextBox tb; + protected List items = new List(); + protected int counter; + + public Bookmarks(FastColoredTextBox tb) + { + this.tb = tb; + tb.LineInserted += tb_LineInserted; + tb.LineRemoved += tb_LineRemoved; + } + + protected virtual void tb_LineRemoved(object sender, LineRemovedEventArgs e) + { + for(int i=0; i= e.Index) + { + if (items[i].LineIndex >= e.Index + e.Count) + { + items[i].LineIndex = items[i].LineIndex - e.Count; + continue; + } + + var was = e.Index <= 0; + foreach (var b in items) + if (b.LineIndex == e.Index - 1) + was = true; + + if(was) + { + items.RemoveAt(i); + i--; + }else + items[i].LineIndex = e.Index - 1; + + //if (items[i].LineIndex == e.Index + e.Count - 1) + //{ + // items[i].LineIndex = items[i].LineIndex - e.Count; + // continue; + //} + // + //items.RemoveAt(i); + //i--; + } + } + + protected virtual void tb_LineInserted(object sender, LineInsertedEventArgs e) + { + for (int i = 0; i < Count; i++) + if (items[i].LineIndex >= e.Index) + { + items[i].LineIndex = items[i].LineIndex + e.Count; + }else + if (items[i].LineIndex == e.Index - 1 && e.Count == 1) + { + if(tb[e.Index - 1].StartSpacesCount == tb[e.Index - 1].Count) + items[i].LineIndex = items[i].LineIndex + e.Count; + } + } + + public override void Dispose() + { + tb.LineInserted -= tb_LineInserted; + tb.LineRemoved -= tb_LineRemoved; + } + + public override IEnumerator GetEnumerator() + { + foreach (var item in items) + yield return item; + } + + public override void Add(int lineIndex, string bookmarkName) + { + Add(new Bookmark(tb, bookmarkName ?? "Bookmark " + counter, lineIndex)); + } + + public override void Add(int lineIndex) + { + Add(new Bookmark(tb, "Bookmark " + counter, lineIndex)); + } + + public override void Clear() + { + items.Clear(); + counter = 0; + } + + public override void Add(Bookmark bookmark) + { + foreach (var bm in items) + if (bm.LineIndex == bookmark.LineIndex) + return; + + items.Add(bookmark); + counter++; + tb.Invalidate(); + } + + public override bool Contains(Bookmark item) + { + return items.Contains(item); + } + + public override bool Contains(int lineIndex) + { + foreach (var item in items) + if (item.LineIndex == lineIndex) + return true; + return false; + } + + public override void CopyTo(Bookmark[] array, int arrayIndex) + { + items.CopyTo(array, arrayIndex); + } + + public override int Count + { + get { return items.Count; } + } + + public override bool IsReadOnly + { + get { return false; } + } + + public override bool Remove(Bookmark item) + { + tb.Invalidate(); + return items.Remove(item); + } + + /// + /// Removes bookmark by line index + /// + public override bool Remove(int lineIndex) + { + bool was = false; + for (int i = 0; i < Count; i++) + if (items[i].LineIndex == lineIndex) + { + items.RemoveAt(i); + i--; + was = true; + } + tb.Invalidate(); + + return was; + } + + /// + /// Returns Bookmark by index. + /// + public override Bookmark GetBookmark(int i) + { + return items[i]; + } + } + + /// + /// Bookmark of FastColoredTextbox + /// + public class Bookmark + { + public FastColoredTextBox TB { get; private set; } + /// + /// Name of bookmark + /// + public string Name { get; set; } + /// + /// Line index + /// + public int LineIndex {get; set; } + /// + /// Color of bookmark sign + /// + public Color Color { get; set; } + + /// + /// Scroll textbox to the bookmark + /// + public virtual void DoVisible() + { + TB.Selection.Start = new Place(0, LineIndex); + TB.DoRangeVisible(TB.Selection, true); + TB.Invalidate(); + } + + public Bookmark(FastColoredTextBox tb, string name, int lineIndex) + { + this.TB = tb; + this.Name = name; + this.LineIndex = lineIndex; + Color = tb.BookmarkColor; + } + + public virtual void Paint(Graphics gr, Rectangle lineRect) + { + var size = TB.CharHeight - 1; + using (var brush = new LinearGradientBrush(new Rectangle(0, lineRect.Top, size, size), Color.White, Color, 45)) + gr.FillEllipse(brush, 0, lineRect.Top, size, size); + using (var pen = new Pen(Color)) + gr.DrawEllipse(pen, 0, lineRect.Top, size, size); + } + } +} diff --git a/PluginCore/FastColoredTB/Char.cs b/PluginCore/FastColoredTB/Char.cs new file mode 100644 index 0000000000..9f848c9793 --- /dev/null +++ b/PluginCore/FastColoredTB/Char.cs @@ -0,0 +1,26 @@ +using System; + +namespace FastColoredTextBoxNS +{ + /// + /// Char and style + /// + public struct Char + { + /// + /// Unicode character + /// + public char c; + /// + /// Style bit mask + /// + /// Bit 1 in position n means that this char will rendering by FastColoredTextBox.Styles[n] + public StyleIndex style; + + public Char(char c) + { + this.c = c; + style = StyleIndex.None; + } + } +} diff --git a/PluginCore/FastColoredTB/CommandManager.cs b/PluginCore/FastColoredTB/CommandManager.cs new file mode 100644 index 0000000000..7e61a6133a --- /dev/null +++ b/PluginCore/FastColoredTB/CommandManager.cs @@ -0,0 +1,239 @@ +using System.Collections.Generic; +using System; + +namespace FastColoredTextBoxNS +{ + public class CommandManager + { + readonly int maxHistoryLength = 200; + LimitedStack history; + Stack redoStack = new Stack(); + public TextSource TextSource{ get; private set; } + public bool UndoRedoStackIsEnabled { get; set; } + + public CommandManager(TextSource ts) + { + history = new LimitedStack(maxHistoryLength); + TextSource = ts; + UndoRedoStackIsEnabled = true; + } + + public virtual void ExecuteCommand(Command cmd) + { + if (disabledCommands > 0) + return; + + //multirange ? + if (cmd.ts.CurrentTB.Selection.ColumnSelectionMode) + if (cmd is UndoableCommand) + //make wrapper + cmd = new MultiRangeCommand((UndoableCommand)cmd); + + + if (cmd is UndoableCommand) + { + //if range is ColumnRange, then create wrapper + (cmd as UndoableCommand).autoUndo = autoUndoCommands > 0; + history.Push(cmd as UndoableCommand); + } + + try + { + cmd.Execute(); + } + catch (ArgumentOutOfRangeException) + { + //OnTextChanging cancels enter of the text + if (cmd is UndoableCommand) + history.Pop(); + } + // + if (!UndoRedoStackIsEnabled) + ClearHistory(); + // + redoStack.Clear(); + // + TextSource.CurrentTB.OnUndoRedoStateChanged(); + } + + public void Undo() + { + if (history.Count > 0) + { + var cmd = history.Pop(); + // + BeginDisableCommands();//prevent text changing into handlers + try + { + cmd.Undo(); + } + finally + { + EndDisableCommands(); + } + // + redoStack.Push(cmd); + } + + //undo next autoUndo command + if (history.Count > 0) + { + if (history.Peek().autoUndo) + Undo(); + } + + TextSource.CurrentTB.OnUndoRedoStateChanged(); + } + + protected int disabledCommands = 0; + + private void EndDisableCommands() + { + disabledCommands--; + } + + private void BeginDisableCommands() + { + disabledCommands++; + } + + int autoUndoCommands = 0; + + public void EndAutoUndoCommands() + { + autoUndoCommands--; + if (autoUndoCommands == 0) + if (history.Count > 0) + history.Peek().autoUndo = false; + } + + public void BeginAutoUndoCommands() + { + autoUndoCommands++; + } + + internal void ClearHistory() + { + history.Clear(); + redoStack.Clear(); + TextSource.CurrentTB.OnUndoRedoStateChanged(); + } + + internal void Redo() + { + if (redoStack.Count == 0) + return; + UndoableCommand cmd; + BeginDisableCommands();//prevent text changing into handlers + try + { + cmd = redoStack.Pop(); + if (TextSource.CurrentTB.Selection.ColumnSelectionMode) + TextSource.CurrentTB.Selection.ColumnSelectionMode = false; + TextSource.CurrentTB.Selection.Start = cmd.sel.Start; + TextSource.CurrentTB.Selection.End = cmd.sel.End; + cmd.Execute(); + history.Push(cmd); + } + finally + { + EndDisableCommands(); + } + + //redo command after autoUndoable command + if (cmd.autoUndo) + Redo(); + + TextSource.CurrentTB.OnUndoRedoStateChanged(); + } + + public bool UndoEnabled + { + get + { + return history.Count > 0; + } + } + + public bool RedoEnabled + { + get + { + return redoStack.Count > 0; + } + } + } + + public abstract class Command + { + public TextSource ts; + public abstract void Execute(); + } + + internal class RangeInfo + { + public Place Start { get; set; } + public Place End { get; set; } + + public RangeInfo(Range r) + { + Start = r.Start; + End = r.End; + } + + internal int FromX + { + get + { + if (End.iLine < Start.iLine) return End.iChar; + if (End.iLine > Start.iLine) return Start.iChar; + return Math.Min(End.iChar, Start.iChar); + } + } + } + + public abstract class UndoableCommand : Command + { + internal RangeInfo sel; + internal RangeInfo lastSel; + internal bool autoUndo; + + public UndoableCommand(TextSource ts) + { + this.ts = ts; + sel = new RangeInfo(ts.CurrentTB.Selection); + } + + public virtual void Undo() + { + OnTextChanged(true); + } + + public override void Execute() + { + lastSel = new RangeInfo(ts.CurrentTB.Selection); + OnTextChanged(false); + } + + protected virtual void OnTextChanged(bool invert) + { + bool b = sel.Start.iLine < lastSel.Start.iLine; + if (invert) + { + if (b) + ts.OnTextChanged(sel.Start.iLine, sel.Start.iLine); + else + ts.OnTextChanged(sel.Start.iLine, lastSel.Start.iLine); + } + else + { + if (b) + ts.OnTextChanged(sel.Start.iLine, lastSel.Start.iLine); + else + ts.OnTextChanged(lastSel.Start.iLine, lastSel.Start.iLine); + } + } + + public abstract UndoableCommand Clone(); + } +} \ No newline at end of file diff --git a/PluginCore/FastColoredTB/Commands.cs b/PluginCore/FastColoredTB/Commands.cs new file mode 100644 index 0000000000..c83ac9621a --- /dev/null +++ b/PluginCore/FastColoredTB/Commands.cs @@ -0,0 +1,809 @@ +using System; +using System.Collections.Generic; + +namespace FastColoredTextBoxNS +{ + /// + /// Insert single char + /// + /// This operation includes also insertion of new line and removing char by backspace + public class InsertCharCommand : UndoableCommand + { + public char c; + char deletedChar = '\x0'; + + /// + /// Constructor + /// + /// Underlaying textbox + /// Inserting char + public InsertCharCommand(TextSource ts, char c): base(ts) + { + this.c = c; + } + + /// + /// Undo operation + /// + public override void Undo() + { + ts.OnTextChanging(); + switch (c) + { + case '\n': MergeLines(sel.Start.iLine, ts); break; + case '\r': break; + case '\b': + ts.CurrentTB.Selection.Start = lastSel.Start; + char cc = '\x0'; + if (deletedChar != '\x0') + { + ts.CurrentTB.ExpandBlock(ts.CurrentTB.Selection.Start.iLine); + InsertChar(deletedChar, ref cc, ts); + } + break; + case '\t': + ts.CurrentTB.ExpandBlock(sel.Start.iLine); + for (int i = sel.FromX; i < lastSel.FromX; i++) + ts[sel.Start.iLine].RemoveAt(sel.Start.iChar); + ts.CurrentTB.Selection.Start = sel.Start; + break; + default: + ts.CurrentTB.ExpandBlock(sel.Start.iLine); + ts[sel.Start.iLine].RemoveAt(sel.Start.iChar); + ts.CurrentTB.Selection.Start = sel.Start; + break; + } + + ts.NeedRecalc(new TextSource.TextChangedEventArgs(sel.Start.iLine, sel.Start.iLine)); + + base.Undo(); + } + + /// + /// Execute operation + /// + public override void Execute() + { + ts.CurrentTB.ExpandBlock(ts.CurrentTB.Selection.Start.iLine); + string s = c.ToString(); + ts.OnTextChanging(ref s); + if (s.Length == 1) + c = s[0]; + + if (String.IsNullOrEmpty(s)) + throw new ArgumentOutOfRangeException(); + + + if (ts.Count == 0) + InsertLine(ts); + InsertChar(c, ref deletedChar, ts); + + ts.NeedRecalc(new TextSource.TextChangedEventArgs(ts.CurrentTB.Selection.Start.iLine, ts.CurrentTB.Selection.Start.iLine)); + base.Execute(); + } + + internal static void InsertChar(char c, ref char deletedChar, TextSource ts) + { + var tb = ts.CurrentTB; + + switch (c) + { + case '\n': + if (!ts.CurrentTB.AllowInsertRemoveLines) + throw new ArgumentOutOfRangeException("Cant insert this char in ColumnRange mode"); + if (ts.Count == 0) + InsertLine(ts); + InsertLine(ts); + break; + case '\r': break; + case '\b'://backspace + if (tb.Selection.Start.iChar == 0 && tb.Selection.Start.iLine == 0) + return; + if (tb.Selection.Start.iChar == 0) + { + if (!ts.CurrentTB.AllowInsertRemoveLines) + throw new ArgumentOutOfRangeException("Cant insert this char in ColumnRange mode"); + if (tb.LineInfos[tb.Selection.Start.iLine - 1].VisibleState != VisibleState.Visible) + tb.ExpandBlock(tb.Selection.Start.iLine - 1); + deletedChar = '\n'; + MergeLines(tb.Selection.Start.iLine - 1, ts); + } + else + { + deletedChar = ts[tb.Selection.Start.iLine][tb.Selection.Start.iChar - 1].c; + ts[tb.Selection.Start.iLine].RemoveAt(tb.Selection.Start.iChar - 1); + tb.Selection.Start = new Place(tb.Selection.Start.iChar - 1, tb.Selection.Start.iLine); + } + break; + case '\t': + int spaceCountNextTabStop = tb.TabLength - (tb.Selection.Start.iChar % tb.TabLength); + if (spaceCountNextTabStop == 0) + spaceCountNextTabStop = tb.TabLength; + + for (int i = 0; i < spaceCountNextTabStop; i++) + ts[tb.Selection.Start.iLine].Insert(tb.Selection.Start.iChar, new Char(' ')); + + tb.Selection.Start = new Place(tb.Selection.Start.iChar + spaceCountNextTabStop, tb.Selection.Start.iLine); + break; + default: + ts[tb.Selection.Start.iLine].Insert(tb.Selection.Start.iChar, new Char(c)); + tb.Selection.Start = new Place(tb.Selection.Start.iChar + 1, tb.Selection.Start.iLine); + break; + } + } + + internal static void InsertLine(TextSource ts) + { + var tb = ts.CurrentTB; + + if (!tb.Multiline && tb.LinesCount > 0) + return; + + if (ts.Count == 0) + ts.InsertLine(0, ts.CreateLine()); + else + BreakLines(tb.Selection.Start.iLine, tb.Selection.Start.iChar, ts); + + tb.Selection.Start = new Place(0, tb.Selection.Start.iLine + 1); + ts.NeedRecalc(new TextSource.TextChangedEventArgs(0, 1)); + } + + /// + /// Merge lines i and i+1 + /// + internal static void MergeLines(int i, TextSource ts) + { + var tb = ts.CurrentTB; + + if (i + 1 >= ts.Count) + return; + tb.ExpandBlock(i); + tb.ExpandBlock(i + 1); + int pos = ts[i].Count; + // + /* + if(ts[i].Count == 0) + ts.RemoveLine(i); + else*/ + if (ts[i + 1].Count == 0) + ts.RemoveLine(i + 1); + else + { + ts[i].AddRange(ts[i + 1]); + ts.RemoveLine(i + 1); + } + tb.Selection.Start = new Place(pos, i); + ts.NeedRecalc(new TextSource.TextChangedEventArgs(0, 1)); + } + + internal static void BreakLines(int iLine, int pos, TextSource ts) + { + Line newLine = ts.CreateLine(); + for(int i=pos;i + /// Insert text + /// + public class InsertTextCommand : UndoableCommand + { + public string InsertedText; + + /// + /// Constructor + /// + /// Underlaying textbox + /// Text for inserting + public InsertTextCommand(TextSource ts, string insertedText): base(ts) + { + this.InsertedText = insertedText; + } + + /// + /// Undo operation + /// + public override void Undo() + { + ts.CurrentTB.Selection.Start = sel.Start; + ts.CurrentTB.Selection.End = lastSel.Start; + ts.OnTextChanging(); + ClearSelectedCommand.ClearSelected(ts); + base.Undo(); + } + + /// + /// Execute operation + /// + public override void Execute() + { + ts.OnTextChanging(ref InsertedText); + InsertText(InsertedText, ts); + base.Execute(); + } + + internal static void InsertText(string insertedText, TextSource ts) + { + var tb = ts.CurrentTB; + try + { + tb.Selection.BeginUpdate(); + char cc = '\x0'; + + if (ts.Count == 0) + { + InsertCharCommand.InsertLine(ts); + tb.Selection.Start = Place.Empty; + } + tb.ExpandBlock(tb.Selection.Start.iLine); + var len = insertedText.Length; + for (int i = 0; i < len; i++) + { + var c = insertedText[i]; + if(c == '\r' && (i >= len - 1 || insertedText[i + 1] != '\n')) + InsertCharCommand.InsertChar('\n', ref cc, ts); + else + InsertCharCommand.InsertChar(c, ref cc, ts); + } + ts.NeedRecalc(new TextSource.TextChangedEventArgs(0, 1)); + } + finally { + tb.Selection.EndUpdate(); + } + } + + public override UndoableCommand Clone() + { + return new InsertTextCommand(ts, InsertedText); + } + } + + /// + /// Insert text into given ranges + /// + public class ReplaceTextCommand : UndoableCommand + { + string insertedText; + List ranges; + List prevText = new List(); + + /// + /// Constructor + /// + /// Underlaying textbox + /// List of ranges for replace + /// Text for inserting + public ReplaceTextCommand(TextSource ts, List ranges, string insertedText) + : base(ts) + { + //sort ranges by place + ranges.Sort((r1, r2)=> + { + if (r1.Start.iLine == r2.Start.iLine) + return r1.Start.iChar.CompareTo(r2.Start.iChar); + return r1.Start.iLine.CompareTo(r2.Start.iLine); + }); + // + this.ranges = ranges; + this.insertedText = insertedText; + lastSel = sel = new RangeInfo(ts.CurrentTB.Selection); + } + + /// + /// Undo operation + /// + public override void Undo() + { + var tb = ts.CurrentTB; + + ts.OnTextChanging(); + tb.BeginUpdate(); + + tb.Selection.BeginUpdate(); + for (int i = 0; i 0) + ts.OnTextChanged(ranges[0].Start.iLine, ranges[ranges.Count - 1].End.iLine); + + ts.NeedRecalc(new TextSource.TextChangedEventArgs(0, 1)); + } + + /// + /// Execute operation + /// + public override void Execute() + { + var tb = ts.CurrentTB; + prevText.Clear(); + + ts.OnTextChanging(ref insertedText); + + tb.Selection.BeginUpdate(); + tb.BeginUpdate(); + for (int i = ranges.Count - 1; i >= 0; i--) + { + tb.Selection.Start = ranges[i].Start; + tb.Selection.End = ranges[i].End; + prevText.Add(tb.Selection.Text); + ClearSelected(ts); + if (insertedText != "") + InsertTextCommand.InsertText(insertedText, ts); + } + if(ranges.Count > 0) + ts.OnTextChanged(ranges[0].Start.iLine, ranges[ranges.Count - 1].End.iLine); + tb.EndUpdate(); + tb.Selection.EndUpdate(); + ts.NeedRecalc(new TextSource.TextChangedEventArgs(0, 1)); + + lastSel = new RangeInfo(tb.Selection); + } + + public override UndoableCommand Clone() + { + return new ReplaceTextCommand(ts, new List(ranges), insertedText); + } + + internal static void ClearSelected(TextSource ts) + { + var tb = ts.CurrentTB; + + tb.Selection.Normalize(); + + Place start = tb.Selection.Start; + Place end = tb.Selection.End; + int fromLine = Math.Min(end.iLine, start.iLine); + int toLine = Math.Max(end.iLine, start.iLine); + int fromChar = tb.Selection.FromX; + int toChar = tb.Selection.ToX; + if (fromLine < 0) return; + // + if (fromLine == toLine) + ts[fromLine].RemoveRange(fromChar, toChar - fromChar); + else + { + ts[fromLine].RemoveRange(fromChar, ts[fromLine].Count - fromChar); + ts[toLine].RemoveRange(0, toChar); + ts.RemoveLine(fromLine + 1, toLine - fromLine - 1); + InsertCharCommand.MergeLines(fromLine, ts); + } + } + } + + /// + /// Clear selected text + /// + public class ClearSelectedCommand : UndoableCommand + { + string deletedText; + + /// + /// Construstor + /// + /// Underlaying textbox + public ClearSelectedCommand(TextSource ts): base(ts) + { + } + + /// + /// Undo operation + /// + public override void Undo() + { + ts.CurrentTB.Selection.Start = new Place(sel.FromX, Math.Min(sel.Start.iLine, sel.End.iLine)); + ts.OnTextChanging(); + InsertTextCommand.InsertText(deletedText, ts); + ts.OnTextChanged(sel.Start.iLine, sel.End.iLine); + ts.CurrentTB.Selection.Start = sel.Start; + ts.CurrentTB.Selection.End = sel.End; + } + + /// + /// Execute operation + /// + public override void Execute() + { + var tb = ts.CurrentTB; + + string temp = null; + ts.OnTextChanging(ref temp); + if (temp == "") + throw new ArgumentOutOfRangeException(); + + deletedText = tb.Selection.Text; + ClearSelected(ts); + lastSel = new RangeInfo(tb.Selection); + ts.OnTextChanged(lastSel.Start.iLine, lastSel.Start.iLine); + } + + internal static void ClearSelected(TextSource ts) + { + var tb = ts.CurrentTB; + + Place start = tb.Selection.Start; + Place end = tb.Selection.End; + int fromLine = Math.Min(end.iLine, start.iLine); + int toLine = Math.Max(end.iLine, start.iLine); + int fromChar = tb.Selection.FromX; + int toChar = tb.Selection.ToX; + if (fromLine < 0) return; + // + if (fromLine == toLine) + ts[fromLine].RemoveRange(fromChar, toChar - fromChar); + else + { + ts[fromLine].RemoveRange(fromChar, ts[fromLine].Count - fromChar); + ts[toLine].RemoveRange(0, toChar); + ts.RemoveLine(fromLine + 1, toLine - fromLine - 1); + InsertCharCommand.MergeLines(fromLine, ts); + } + // + tb.Selection.Start = new Place(fromChar, fromLine); + // + ts.NeedRecalc(new TextSource.TextChangedEventArgs(fromLine, toLine)); + } + + public override UndoableCommand Clone() + { + return new ClearSelectedCommand(ts); + } + } + + /// + /// Replaces text + /// + public class ReplaceMultipleTextCommand : UndoableCommand + { + List ranges; + List prevText = new List(); + + public class ReplaceRange + { + public Range ReplacedRange { get; set; } + public String ReplaceText { get; set; } + } + + /// + /// Constructor + /// + /// Underlaying textsource + /// List of ranges for replace + public ReplaceMultipleTextCommand(TextSource ts, List ranges) + : base(ts) + { + //sort ranges by place + ranges.Sort((r1, r2) => + { + if (r1.ReplacedRange.Start.iLine == r2.ReplacedRange.Start.iLine) + return r1.ReplacedRange.Start.iChar.CompareTo(r2.ReplacedRange.Start.iChar); + return r1.ReplacedRange.Start.iLine.CompareTo(r2.ReplacedRange.Start.iLine); + }); + // + this.ranges = ranges; + lastSel = sel = new RangeInfo(ts.CurrentTB.Selection); + } + + /// + /// Undo operation + /// + public override void Undo() + { + var tb = ts.CurrentTB; + + ts.OnTextChanging(); + + tb.Selection.BeginUpdate(); + for (int i = 0; i < ranges.Count; i++) + { + tb.Selection.Start = ranges[i].ReplacedRange.Start; + for (int j = 0; j < ranges[i].ReplaceText.Length; j++) + tb.Selection.GoRight(true); + ClearSelectedCommand.ClearSelected(ts); + var prevTextIndex = ranges.Count - 1 - i; + InsertTextCommand.InsertText(prevText[prevTextIndex], ts); + ts.OnTextChanged(ranges[i].ReplacedRange.Start.iLine, ranges[i].ReplacedRange.Start.iLine); + } + tb.Selection.EndUpdate(); + + ts.NeedRecalc(new TextSource.TextChangedEventArgs(0, 1)); + } + + /// + /// Execute operation + /// + public override void Execute() + { + var tb = ts.CurrentTB; + prevText.Clear(); + + ts.OnTextChanging(); + + tb.Selection.BeginUpdate(); + for (int i = ranges.Count - 1; i >= 0; i--) + { + tb.Selection.Start = ranges[i].ReplacedRange.Start; + tb.Selection.End = ranges[i].ReplacedRange.End; + prevText.Add(tb.Selection.Text); + ClearSelectedCommand.ClearSelected(ts); + InsertTextCommand.InsertText(ranges[i].ReplaceText, ts); + ts.OnTextChanged(ranges[i].ReplacedRange.Start.iLine, ranges[i].ReplacedRange.End.iLine); + } + tb.Selection.EndUpdate(); + ts.NeedRecalc(new TextSource.TextChangedEventArgs(0, 1)); + + lastSel = new RangeInfo(tb.Selection); + } + + public override UndoableCommand Clone() + { + return new ReplaceMultipleTextCommand(ts, new List(ranges)); + } + } + + /// + /// Removes lines + /// + public class RemoveLinesCommand : UndoableCommand + { + List iLines; + List prevText = new List(); + + /// + /// Constructor + /// + /// Underlaying textbox + /// List of ranges for replace + /// Text for inserting + public RemoveLinesCommand(TextSource ts, List iLines) + : base(ts) + { + //sort iLines + iLines.Sort(); + // + this.iLines = iLines; + lastSel = sel = new RangeInfo(ts.CurrentTB.Selection); + } + + /// + /// Undo operation + /// + public override void Undo() + { + var tb = ts.CurrentTB; + + ts.OnTextChanging(); + + tb.Selection.BeginUpdate(); + //tb.BeginUpdate(); + for (int i = 0; i < iLines.Count; i++) + { + var iLine = iLines[i]; + + if(iLine < ts.Count) + tb.Selection.Start = new Place(0, iLine); + else + tb.Selection.Start = new Place(ts[ts.Count - 1].Count, ts.Count - 1); + + InsertCharCommand.InsertLine(ts); + tb.Selection.Start = new Place(0, iLine); + var text = prevText[prevText.Count - i - 1]; + InsertTextCommand.InsertText(text, ts); + ts[iLine].IsChanged = true; + if (iLine < ts.Count - 1) + ts[iLine + 1].IsChanged = true; + else + ts[iLine - 1].IsChanged = true; + if(text.Trim() != string.Empty) + ts.OnTextChanged(iLine, iLine); + } + //tb.EndUpdate(); + tb.Selection.EndUpdate(); + + ts.NeedRecalc(new TextSource.TextChangedEventArgs(0, 1)); + } + + /// + /// Execute operation + /// + public override void Execute() + { + var tb = ts.CurrentTB; + prevText.Clear(); + + ts.OnTextChanging(); + + tb.Selection.BeginUpdate(); + for(int i = iLines.Count - 1; i >= 0; i--) + { + var iLine = iLines[i]; + + prevText.Add(ts[iLine].Text);//backward + ts.RemoveLine(iLine); + //ts.OnTextChanged(ranges[i].Start.iLine, ranges[i].End.iLine); + } + tb.Selection.Start = new Place(0, 0); + tb.Selection.EndUpdate(); + ts.NeedRecalc(new TextSource.TextChangedEventArgs(0, 1)); + + lastSel = new RangeInfo(tb.Selection); + } + + public override UndoableCommand Clone() + { + return new RemoveLinesCommand(ts, new List(iLines)); + } + } + + /// + /// Wrapper for multirange commands + /// + public class MultiRangeCommand : UndoableCommand + { + private UndoableCommand cmd; + private Range range; + private List commandsByRanges = new List(); + + public MultiRangeCommand(UndoableCommand command):base(command.ts) + { + this.cmd = command; + range = ts.CurrentTB.Selection.Clone(); + } + + public override void Execute() + { + commandsByRanges.Clear(); + var prevSelection = range.Clone(); + var iChar = -1; + var iStartLine = prevSelection.Start.iLine; + var iEndLine = prevSelection.End.iLine; + ts.CurrentTB.Selection.ColumnSelectionMode = false; + ts.CurrentTB.Selection.BeginUpdate(); + ts.CurrentTB.BeginUpdate(); + ts.CurrentTB.AllowInsertRemoveLines = false; + try + { + if (cmd is InsertTextCommand) + ExecuteInsertTextCommand(ref iChar, (cmd as InsertTextCommand).InsertedText); + else + if (cmd is InsertCharCommand && (cmd as InsertCharCommand).c != '\x0' && (cmd as InsertCharCommand).c != '\b')//if not DEL or BACKSPACE + ExecuteInsertTextCommand(ref iChar, (cmd as InsertCharCommand).c.ToString()); + else + ExecuteCommand(ref iChar); + } + catch (ArgumentOutOfRangeException) + { + } + finally + { + ts.CurrentTB.AllowInsertRemoveLines = true; + ts.CurrentTB.EndUpdate(); + + ts.CurrentTB.Selection = range; + if (iChar >= 0) + { + ts.CurrentTB.Selection.Start = new Place(iChar, iStartLine); + ts.CurrentTB.Selection.End = new Place(iChar, iEndLine); + } + ts.CurrentTB.Selection.ColumnSelectionMode = true; + ts.CurrentTB.Selection.EndUpdate(); + } + } + + private void ExecuteInsertTextCommand(ref int iChar, string text) + { + var lines = text.Split('\n'); + var iLine = 0; + foreach (var r in range.GetSubRanges(true)) + { + var line = ts.CurrentTB[r.Start.iLine]; + var lineIsEmpty = r.End < r.Start && line.StartSpacesCount == line.Count; + if (!lineIsEmpty) + { + var insertedText = lines[iLine%lines.Length]; + if (r.End < r.Start && insertedText!="") + { + //add forwarding spaces + insertedText = new string(' ', r.Start.iChar - r.End.iChar) + insertedText; + r.Start = r.End; + } + ts.CurrentTB.Selection = r; + var c = new InsertTextCommand(ts, insertedText); + c.Execute(); + if (ts.CurrentTB.Selection.End.iChar > iChar) + iChar = ts.CurrentTB.Selection.End.iChar; + commandsByRanges.Add(c); + } + iLine++; + } + } + + private void ExecuteCommand(ref int iChar) + { + foreach (var r in range.GetSubRanges(false)) + { + ts.CurrentTB.Selection = r; + var c = cmd.Clone(); + c.Execute(); + if (ts.CurrentTB.Selection.End.iChar > iChar) + iChar = ts.CurrentTB.Selection.End.iChar; + commandsByRanges.Add(c); + } + } + + public override void Undo() + { + ts.CurrentTB.BeginUpdate(); + ts.CurrentTB.Selection.BeginUpdate(); + try + { + for (int i = commandsByRanges.Count - 1; i >= 0; i--) + commandsByRanges[i].Undo(); + } + finally + { + ts.CurrentTB.Selection.EndUpdate(); + ts.CurrentTB.EndUpdate(); + } + ts.CurrentTB.Selection = range.Clone(); + ts.CurrentTB.OnTextChanged(range); + ts.CurrentTB.OnSelectionChanged(); + ts.CurrentTB.Selection.ColumnSelectionMode = true; + } + + public override UndoableCommand Clone() + { + throw new NotImplementedException(); + } + } + + /// + /// Remembers current selection and restore it after Undo + /// + public class SelectCommand : UndoableCommand + { + public SelectCommand(TextSource ts):base(ts) + { + } + + public override void Execute() + { + //remember selection + lastSel = new RangeInfo(ts.CurrentTB.Selection); + } + + protected override void OnTextChanged(bool invert) + { + } + + public override void Undo() + { + //restore selection + ts.CurrentTB.Selection = new Range(ts.CurrentTB, lastSel.Start, lastSel.End); + } + + public override UndoableCommand Clone() + { + var result = new SelectCommand(ts); + if(lastSel!=null) + result.lastSel = new RangeInfo(new Range(ts.CurrentTB, lastSel.Start, lastSel.End)); + return result; + } + } +} diff --git a/PluginCore/FastColoredTB/CustomHighlighter.cs b/PluginCore/FastColoredTB/CustomHighlighter.cs new file mode 100644 index 0000000000..06e4472c14 --- /dev/null +++ b/PluginCore/FastColoredTB/CustomHighlighter.cs @@ -0,0 +1,95 @@ +using System; +using System.Linq; +using System.Text; +using System.Drawing; +using System.Text.RegularExpressions; +using System.Collections.Generic; + +namespace FastColoredTextBoxNS +{ + public static class CustomHighlighter + { + private static FastColoredTextBox editor; + private static Regex[] regexes = new Regex[32]; + private static Style[] styles = new Style[32]; + + /* + DEFAULT = 0, + COMMENT = 1, + COMMENTLINE = 2, + COMMENTDOC = 3, + NUMBER = 4, + WORD = 5, + STRING = 6, + CHARACTER = 7, + UUID = 8, + PREPROCESSOR = 9, + OPERATOR = 10, + IDENTIFIER = 11, + STRINGEOL = 12, + VERBATIM = 13, + REGEX = 14, + COMMENTLINEDOC = 15, + WORD2 = 16, + COMMENTDOCKEYWORD = 17, + COMMENTDOCKEYWORDERROR = 18, + GLOBALCLASS = 19, + STRINGRAW = 20, + TRIPLEVERBATIM = 21, + HASHQUOTEDSTRING = 22, + PREPROCESSORCOMMENT = 23, + WORD3 = 24, + WORD4 = 25, + WORD5 = 26, + GDEFAULT = 32, + LINENUMBER = 33, + BRACELIGHT = 34, + BRACEBAD = 35, + CONTROLCHAR = 36, + INDENTGUIDE = 37, + LASTPREDEFINED = 39 + */ + + public static void Init(FastColoredTextBox fctb) + { + editor = fctb; + styles = new Style[32]; + regexes = new Regex[32]; + for (int i = 0; i < 32; i++) + { + regexes[i] = new Regex(""); + styles[i] = new TextStyle(new SolidBrush(SystemColors.Highlight), null, System.Drawing.FontStyle.Regular); + } + editor.TextChanged += OnTextChangedDelayed; + } + + private static void OnTextChangedDelayed(Object sender, TextChangedEventArgs e) + { + Range range = editor.Range; + + // set options + range.tb.CommentPrefix = "//"; + range.tb.LeftBracket = '('; + range.tb.RightBracket = ')'; + range.tb.LeftBracket2 = '{'; + range.tb.RightBracket2 = '}'; + range.tb.LeftBracket3 = '['; + range.tb.RightBracket3 = ']'; + range.tb.AutoIndentCharsPatterns = @"^\s*[\w\.]+(\s\w+)?\s*(?=)\s*(?[^;]+);^\s*(case|default)\s*[^:]*(?:)\s*(?[^;]+);"; + range.tb.BracketsHighlightStrategy = BracketsHighlightStrategy.Strategy2; + + // set styles + range.ClearStyle(styles); + range.SetStyle(styles[31], @"\b(class|var|else|if)\b"); + + // set folding markers + range.ClearFoldingMarkers(); + range.SetFoldingMarkers("{", "}"); //allow to collapse brackets block + range.SetFoldingMarkers(@"//{", @"//}"); //allow to collapse #region blocks + range.SetFoldingMarkers(@"/\*", @"\*/"); //allow to collapse comment block + } + + } + +} + diff --git a/PluginCore/FastColoredTB/DocumentMap.cs b/PluginCore/FastColoredTB/DocumentMap.cs new file mode 100644 index 0000000000..f3eb38a79f --- /dev/null +++ b/PluginCore/FastColoredTB/DocumentMap.cs @@ -0,0 +1,250 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Data; +using System.Drawing.Drawing2D; +using System.Text; +using System.Windows.Forms; + +namespace FastColoredTextBoxNS +{ + /// + /// Shows document map of FCTB + /// + public class DocumentMap : Control + { + public EventHandler TargetChanged; + + FastColoredTextBox target; + private float scale = 0.3f; + private bool needRepaint = true; + private Place startPlace = Place.Empty; + private bool scrollbarVisible = true; + + [Description("Target FastColoredTextBox")] + public FastColoredTextBox Target + { + get { return target; } + set + { + if (target != null) + UnSubscribe(target); + + target = value; + if (value != null) + { + Subscribe(target); + } + OnTargetChanged(); + } + } + + /// + /// Scale + /// + [Description("Scale")] + [DefaultValue(0.3f)] + public float Scale + { + get { return scale; } + set + { + scale = value; + NeedRepaint(); + } + } + + /// + /// Scrollbar visibility + /// + [Description("Scrollbar visibility")] + [DefaultValue(true)] + public bool ScrollbarVisible + { + get { return scrollbarVisible; } + set + { + scrollbarVisible = value; + NeedRepaint(); + } + } + + public DocumentMap() + { + ForeColor = Color.Maroon; + SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint | ControlStyles.ResizeRedraw, true); + Application.Idle += Application_Idle; + } + + void Application_Idle(object sender, EventArgs e) + { + if(needRepaint) + Invalidate(); + } + + protected virtual void OnTargetChanged() + { + NeedRepaint(); + + if (TargetChanged != null) + TargetChanged(this, EventArgs.Empty); + } + + protected virtual void UnSubscribe(FastColoredTextBox target) + { + target.Scroll -= new ScrollEventHandler(Target_Scroll); + target.SelectionChangedDelayed -= new EventHandler(Target_SelectionChanged); + target.VisibleRangeChanged -= new EventHandler(Target_VisibleRangeChanged); + } + + protected virtual void Subscribe(FastColoredTextBox target) + { + target.Scroll += new ScrollEventHandler(Target_Scroll); + target.SelectionChangedDelayed += new EventHandler(Target_SelectionChanged); + target.VisibleRangeChanged += new EventHandler(Target_VisibleRangeChanged); + } + + protected virtual void Target_VisibleRangeChanged(object sender, EventArgs e) + { + NeedRepaint(); + } + + protected virtual void Target_SelectionChanged(object sender, EventArgs e) + { + NeedRepaint(); + } + + protected virtual void Target_Scroll(object sender, ScrollEventArgs e) + { + NeedRepaint(); + } + + protected override void OnResize(EventArgs e) + { + base.OnResize(e); + NeedRepaint(); + } + + public void NeedRepaint() + { + needRepaint = true; + } + + protected override void OnPaint(PaintEventArgs e) + { + if (target == null) + return; + + var zoom = this.Scale * 100 / target.Zoom; + + if (zoom <= float.Epsilon) + return; + + //calc startPlace + var r = target.VisibleRange; + if (startPlace.iLine > r.Start.iLine) + startPlace.iLine = r.Start.iLine; + else + { + var endP = target.PlaceToPoint(r.End); + endP.Offset(0, -(int)(ClientSize.Height / zoom) + target.CharHeight); + var pp = target.PointToPlace(endP); + if (pp.iLine > startPlace.iLine) + startPlace.iLine = pp.iLine; + } + startPlace.iChar = 0; + //calc scroll pos + var linesCount = target.Lines.Count; + var sp1 = (float)r.Start.iLine / linesCount; + var sp2 = (float)r.End.iLine / linesCount; + + //scale graphics + e.Graphics.ScaleTransform(zoom, zoom); + //draw text + var size = new SizeF(ClientSize.Width / zoom, ClientSize.Height / zoom); + target.DrawText(e.Graphics, startPlace, size.ToSize()); + + //draw visible rect + var p0 = target.PlaceToPoint(startPlace); + var p1 = target.PlaceToPoint(r.Start); + var p2 = target.PlaceToPoint(r.End); + var y1 = p1.Y - p0.Y; + var y2 = p2.Y + target.CharHeight - p0.Y; + + e.Graphics.SmoothingMode = SmoothingMode.HighQuality; + + using (var brush = new SolidBrush(Color.FromArgb(50, ForeColor))) + using (var pen = new Pen(brush, 1 / zoom)) + { + var rect = new Rectangle(0, y1, (int)((ClientSize.Width - 1) / zoom), y2 - y1); + e.Graphics.FillRectangle(brush, rect); + e.Graphics.DrawRectangle(pen, rect); + } + + //draw scrollbar + if (scrollbarVisible) + { + e.Graphics.ResetTransform(); + e.Graphics.SmoothingMode = SmoothingMode.None; + + using (var brush = new SolidBrush(Color.FromArgb(200, ForeColor))) + { + var rect = new RectangleF(ClientSize.Width - 3, ClientSize.Height*sp1, 2, + ClientSize.Height*(sp2 - sp1)); + e.Graphics.FillRectangle(brush, rect); + } + } + + needRepaint = false; + } + + protected override void OnMouseDown(MouseEventArgs e) + { + if (e.Button == System.Windows.Forms.MouseButtons.Left) + Scroll(e.Location); + base.OnMouseDown(e); + } + + protected override void OnMouseMove(MouseEventArgs e) + { + if (e.Button == System.Windows.Forms.MouseButtons.Left) + Scroll(e.Location); + base.OnMouseMove(e); + } + + private void Scroll(Point point) + { + if (target == null) + return; + + var zoom = this.Scale*100/target.Zoom; + + if (zoom <= float.Epsilon) + return; + + var p0 = target.PlaceToPoint(startPlace); + p0 = new Point(0, p0.Y + (int) (point.Y/zoom)); + var pp = target.PointToPlace(p0); + target.DoRangeVisible(new Range(target, pp, pp), true); + BeginInvoke((MethodInvoker)OnScroll); + } + + private void OnScroll() + { + Refresh(); + target.Refresh(); + } + + protected override void Dispose(bool disposing) + { + if (disposing) + { + Application.Idle -= Application_Idle; + if (target != null) + UnSubscribe(target); + } + base.Dispose(disposing); + } + } +} diff --git a/PluginCore/FastColoredTB/EncodingDetector.cs b/PluginCore/FastColoredTB/EncodingDetector.cs new file mode 100644 index 0000000000..2dc202d0ad --- /dev/null +++ b/PluginCore/FastColoredTB/EncodingDetector.cs @@ -0,0 +1,363 @@ +// Copyright Tao Klerks, 2010-2012, tao@klerks.biz +// Licensed under the modified BSD license. + + +using System; +using System.IO; +using System.Text; +using System.Text.RegularExpressions; + +namespace FastColoredTextBoxNS +{ + public static class EncodingDetector + { + const long _defaultHeuristicSampleSize = 0x10000; //completely arbitrary - inappropriate for high numbers of files / high speed requirements + + public static Encoding DetectTextFileEncoding(string InputFilename) + { + using (FileStream textfileStream = File.OpenRead(InputFilename)) + { + return DetectTextFileEncoding(textfileStream, _defaultHeuristicSampleSize); + } + } + + public static Encoding DetectTextFileEncoding(FileStream InputFileStream, long HeuristicSampleSize) + { + bool uselessBool = false; + return DetectTextFileEncoding(InputFileStream, _defaultHeuristicSampleSize, out uselessBool); + } + + public static Encoding DetectTextFileEncoding(FileStream InputFileStream, long HeuristicSampleSize, out bool HasBOM) + { + Encoding encodingFound = null; + + long originalPos = InputFileStream.Position; + + InputFileStream.Position = 0; + + + //First read only what we need for BOM detection + byte[] bomBytes = new byte[InputFileStream.Length > 4 ? 4 : InputFileStream.Length]; + InputFileStream.Read(bomBytes, 0, bomBytes.Length); + + encodingFound = DetectBOMBytes(bomBytes); + + if (encodingFound != null) + { + InputFileStream.Position = originalPos; + HasBOM = true; + return encodingFound; + } + + + //BOM Detection failed, going for heuristics now. + // create sample byte array and populate it + byte[] sampleBytes = new byte[HeuristicSampleSize > InputFileStream.Length ? InputFileStream.Length : HeuristicSampleSize]; + Array.Copy(bomBytes, sampleBytes, bomBytes.Length); + if (InputFileStream.Length > bomBytes.Length) + InputFileStream.Read(sampleBytes, bomBytes.Length, sampleBytes.Length - bomBytes.Length); + InputFileStream.Position = originalPos; + + //test byte array content + encodingFound = DetectUnicodeInByteSampleByHeuristics(sampleBytes); + + HasBOM = false; + return encodingFound; + } + + public static Encoding DetectBOMBytes(byte[] BOMBytes) + { + if (BOMBytes.Length < 2) + return null; + + if (BOMBytes[0] == 0xff + && BOMBytes[1] == 0xfe + && (BOMBytes.Length < 4 + || BOMBytes[2] != 0 + || BOMBytes[3] != 0 + ) + ) + return Encoding.Unicode; + + if (BOMBytes[0] == 0xfe + && BOMBytes[1] == 0xff + ) + return Encoding.BigEndianUnicode; + + if (BOMBytes.Length < 3) + return null; + + if (BOMBytes[0] == 0xef && BOMBytes[1] == 0xbb && BOMBytes[2] == 0xbf) + return Encoding.UTF8; + + if (BOMBytes[0] == 0x2b && BOMBytes[1] == 0x2f && BOMBytes[2] == 0x76) + return Encoding.UTF7; + + if (BOMBytes.Length < 4) + return null; + + if (BOMBytes[0] == 0xff && BOMBytes[1] == 0xfe && BOMBytes[2] == 0 && BOMBytes[3] == 0) + return Encoding.UTF32; + + if (BOMBytes[0] == 0 && BOMBytes[1] == 0 && BOMBytes[2] == 0xfe && BOMBytes[3] == 0xff) + return Encoding.GetEncoding(12001); + + return null; + } + + public static Encoding DetectUnicodeInByteSampleByHeuristics(byte[] SampleBytes) + { + long oddBinaryNullsInSample = 0; + long evenBinaryNullsInSample = 0; + long suspiciousUTF8SequenceCount = 0; + long suspiciousUTF8BytesTotal = 0; + long likelyUSASCIIBytesInSample = 0; + + //Cycle through, keeping count of binary null positions, possible UTF-8 + // sequences from upper ranges of Windows-1252, and probable US-ASCII + // character counts. + + long currentPos = 0; + int skipUTF8Bytes = 0; + + while (currentPos < SampleBytes.Length) + { + //binary null distribution + if (SampleBytes[currentPos] == 0) + { + if (currentPos % 2 == 0) + evenBinaryNullsInSample++; + else + oddBinaryNullsInSample++; + } + + //likely US-ASCII characters + if (IsCommonUSASCIIByte(SampleBytes[currentPos])) + likelyUSASCIIBytesInSample++; + + //suspicious sequences (look like UTF-8) + if (skipUTF8Bytes == 0) + { + int lengthFound = DetectSuspiciousUTF8SequenceLength(SampleBytes, currentPos); + + if (lengthFound > 0) + { + suspiciousUTF8SequenceCount++; + suspiciousUTF8BytesTotal += lengthFound; + skipUTF8Bytes = lengthFound - 1; + } + } + else + { + skipUTF8Bytes--; + } + + currentPos++; + } + + //1: UTF-16 LE - in english / european environments, this is usually characterized by a + // high proportion of odd binary nulls (starting at 0), with (as this is text) a low + // proportion of even binary nulls. + // The thresholds here used (less than 20% nulls where you expect non-nulls, and more than + // 60% nulls where you do expect nulls) are completely arbitrary. + + if (((evenBinaryNullsInSample * 2.0) / SampleBytes.Length) < 0.2 + && ((oddBinaryNullsInSample * 2.0) / SampleBytes.Length) > 0.6 + ) + return Encoding.Unicode; + + + //2: UTF-16 BE - in english / european environments, this is usually characterized by a + // high proportion of even binary nulls (starting at 0), with (as this is text) a low + // proportion of odd binary nulls. + // The thresholds here used (less than 20% nulls where you expect non-nulls, and more than + // 60% nulls where you do expect nulls) are completely arbitrary. + + if (((oddBinaryNullsInSample * 2.0) / SampleBytes.Length) < 0.2 + && ((evenBinaryNullsInSample * 2.0) / SampleBytes.Length) > 0.6 + ) + return Encoding.BigEndianUnicode; + + + //3: UTF-8 - Martin Dürst outlines a method for detecting whether something CAN be UTF-8 content + // using regexp, in his w3c.org unicode FAQ entry: + // http://www.w3.org/International/questions/qa-forms-utf-8 + // adapted here for C#. + string potentiallyMangledString = Encoding.ASCII.GetString(SampleBytes); + Regex UTF8Validator = new Regex(@"\A(" + + @"[\x09\x0A\x0D\x20-\x7E]" + + @"|[\xC2-\xDF][\x80-\xBF]" + + @"|\xE0[\xA0-\xBF][\x80-\xBF]" + + @"|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}" + + @"|\xED[\x80-\x9F][\x80-\xBF]" + + @"|\xF0[\x90-\xBF][\x80-\xBF]{2}" + + @"|[\xF1-\xF3][\x80-\xBF]{3}" + + @"|\xF4[\x80-\x8F][\x80-\xBF]{2}" + + @")*\z"); + if (UTF8Validator.IsMatch(potentiallyMangledString)) + { + //Unfortunately, just the fact that it CAN be UTF-8 doesn't tell you much about probabilities. + //If all the characters are in the 0-127 range, no harm done, most western charsets are same as UTF-8 in these ranges. + //If some of the characters were in the upper range (western accented characters), however, they would likely be mangled to 2-byte by the UTF-8 encoding process. + // So, we need to play stats. + + // The "Random" likelihood of any pair of randomly generated characters being one + // of these "suspicious" character sequences is: + // 128 / (256 * 256) = 0.2%. + // + // In western text data, that is SIGNIFICANTLY reduced - most text data stays in the <127 + // character range, so we assume that more than 1 in 500,000 of these character + // sequences indicates UTF-8. The number 500,000 is completely arbitrary - so sue me. + // + // We can only assume these character sequences will be rare if we ALSO assume that this + // IS in fact western text - in which case the bulk of the UTF-8 encoded data (that is + // not already suspicious sequences) should be plain US-ASCII bytes. This, I + // arbitrarily decided, should be 80% (a random distribution, eg binary data, would yield + // approx 40%, so the chances of hitting this threshold by accident in random data are + // VERY low). + + if ((suspiciousUTF8SequenceCount * 500000.0 / SampleBytes.Length >= 1) //suspicious sequences + && ( + //all suspicious, so cannot evaluate proportion of US-Ascii + SampleBytes.Length - suspiciousUTF8BytesTotal == 0 + || + likelyUSASCIIBytesInSample * 1.0 / (SampleBytes.Length - suspiciousUTF8BytesTotal) >= 0.8 + ) + ) + return Encoding.UTF8; + } + + return null; + } + + private static bool IsCommonUSASCIIByte(byte testByte) + { + if (testByte == 0x0A //lf + || testByte == 0x0D //cr + || testByte == 0x09 //tab + || (testByte >= 0x20 && testByte <= 0x2F) //common punctuation + || (testByte >= 0x30 && testByte <= 0x39) //digits + || (testByte >= 0x3A && testByte <= 0x40) //common punctuation + || (testByte >= 0x41 && testByte <= 0x5A) //capital letters + || (testByte >= 0x5B && testByte <= 0x60) //common punctuation + || (testByte >= 0x61 && testByte <= 0x7A) //lowercase letters + || (testByte >= 0x7B && testByte <= 0x7E) //common punctuation + ) + return true; + else + return false; + } + + private static int DetectSuspiciousUTF8SequenceLength(byte[] SampleBytes, long currentPos) + { + int lengthFound = 0; + + if (SampleBytes.Length >= currentPos + 1 + && SampleBytes[currentPos] == 0xC2 + ) + { + if (SampleBytes[currentPos + 1] == 0x81 + || SampleBytes[currentPos + 1] == 0x8D + || SampleBytes[currentPos + 1] == 0x8F + ) + lengthFound = 2; + else if (SampleBytes[currentPos + 1] == 0x90 + || SampleBytes[currentPos + 1] == 0x9D + ) + lengthFound = 2; + else if (SampleBytes[currentPos + 1] >= 0xA0 + && SampleBytes[currentPos + 1] <= 0xBF + ) + lengthFound = 2; + } + else if (SampleBytes.Length >= currentPos + 1 + && SampleBytes[currentPos] == 0xC3 + ) + { + if (SampleBytes[currentPos + 1] >= 0x80 + && SampleBytes[currentPos + 1] <= 0xBF + ) + lengthFound = 2; + } + else if (SampleBytes.Length >= currentPos + 1 + && SampleBytes[currentPos] == 0xC5 + ) + { + if (SampleBytes[currentPos + 1] == 0x92 + || SampleBytes[currentPos + 1] == 0x93 + ) + lengthFound = 2; + else if (SampleBytes[currentPos + 1] == 0xA0 + || SampleBytes[currentPos + 1] == 0xA1 + ) + lengthFound = 2; + else if (SampleBytes[currentPos + 1] == 0xB8 + || SampleBytes[currentPos + 1] == 0xBD + || SampleBytes[currentPos + 1] == 0xBE + ) + lengthFound = 2; + } + else if (SampleBytes.Length >= currentPos + 1 + && SampleBytes[currentPos] == 0xC6 + ) + { + if (SampleBytes[currentPos + 1] == 0x92) + lengthFound = 2; + } + else if (SampleBytes.Length >= currentPos + 1 + && SampleBytes[currentPos] == 0xCB + ) + { + if (SampleBytes[currentPos + 1] == 0x86 + || SampleBytes[currentPos + 1] == 0x9C + ) + lengthFound = 2; + } + else if (SampleBytes.Length >= currentPos + 2 + && SampleBytes[currentPos] == 0xE2 + ) + { + if (SampleBytes[currentPos + 1] == 0x80) + { + if (SampleBytes[currentPos + 2] == 0x93 + || SampleBytes[currentPos + 2] == 0x94 + ) + lengthFound = 3; + if (SampleBytes[currentPos + 2] == 0x98 + || SampleBytes[currentPos + 2] == 0x99 + || SampleBytes[currentPos + 2] == 0x9A + ) + lengthFound = 3; + if (SampleBytes[currentPos + 2] == 0x9C + || SampleBytes[currentPos + 2] == 0x9D + || SampleBytes[currentPos + 2] == 0x9E + ) + lengthFound = 3; + if (SampleBytes[currentPos + 2] == 0xA0 + || SampleBytes[currentPos + 2] == 0xA1 + || SampleBytes[currentPos + 2] == 0xA2 + ) + lengthFound = 3; + if (SampleBytes[currentPos + 2] == 0xA6) + lengthFound = 3; + if (SampleBytes[currentPos + 2] == 0xB0) + lengthFound = 3; + if (SampleBytes[currentPos + 2] == 0xB9 + || SampleBytes[currentPos + 2] == 0xBA + ) + lengthFound = 3; + } + else if (SampleBytes[currentPos + 1] == 0x82 + && SampleBytes[currentPos + 2] == 0xAC + ) + lengthFound = 3; + else if (SampleBytes[currentPos + 1] == 0x84 + && SampleBytes[currentPos + 2] == 0xA2 + ) + lengthFound = 3; + } + + return lengthFound; + } + } +} diff --git a/PluginCore/FastColoredTB/ExportToHTML.cs b/PluginCore/FastColoredTB/ExportToHTML.cs new file mode 100644 index 0000000000..c2e07b9b85 --- /dev/null +++ b/PluginCore/FastColoredTB/ExportToHTML.cs @@ -0,0 +1,222 @@ +using System.Text; +using System.Drawing; +using System.Collections.Generic; + +namespace FastColoredTextBoxNS +{ + /// + /// Exports colored text as HTML + /// + /// At this time only TextStyle renderer is supported. Other styles is not exported. + public class ExportToHTML + { + public string LineNumbersCSS = ""; + + /// + /// Use nbsp; instead space + /// + public bool UseNbsp { get; set; } + /// + /// Use nbsp; instead space in beginning of line + /// + public bool UseForwardNbsp { get; set; } + /// + /// Use original font + /// + public bool UseOriginalFont { get; set; } + /// + /// Use style tag instead style attribute + /// + public bool UseStyleTag { get; set; } + /// + /// Use 'br' tag instead of '\n' + /// + public bool UseBr { get; set; } + /// + /// Includes line numbers + /// + public bool IncludeLineNumbers { get; set; } + + FastColoredTextBox tb; + + public ExportToHTML() + { + UseNbsp = true; + UseOriginalFont = true; + UseStyleTag = true; + UseBr = true; + } + + public string GetHtml(FastColoredTextBox tb) + { + this.tb = tb; + Range sel = new Range(tb); + sel.SelectAll(); + return GetHtml(sel); + } + + public string GetHtml(Range r) + { + this.tb = r.tb; + Dictionary styles = new Dictionary(); + StringBuilder sb = new StringBuilder(); + StringBuilder tempSB = new StringBuilder(); + StyleIndex currentStyleId = StyleIndex.None; + r.Normalize(); + int currentLine = r.Start.iLine; + styles[currentStyleId] = null; + // + if (UseOriginalFont) + sb.AppendFormat("", + r.tb.Font.Name, r.tb.Font.SizeInPoints, r.tb.CharHeight); + + // + if (IncludeLineNumbers) + tempSB.AppendFormat("{0} ", currentLine + 1); + // + bool hasNonSpace = false; + foreach (Place p in r) + { + Char c = r.tb[p.iLine][p.iChar]; + if (c.style != currentStyleId) + { + Flush(sb, tempSB, currentStyleId); + currentStyleId = c.style; + styles[currentStyleId] = null; + } + + if (p.iLine != currentLine) + { + for (int i = currentLine; i < p.iLine; i++) + { + tempSB.Append(UseBr ? "
" : "\r\n"); + if (IncludeLineNumbers) + tempSB.AppendFormat("{0} ", i + 2); + } + currentLine = p.iLine; + hasNonSpace = false; + } + switch (c.c) + { + case ' ': + if ((hasNonSpace || !UseForwardNbsp) && !UseNbsp) + goto default; + + tempSB.Append(" "); + break; + case '<': + tempSB.Append("<"); + break; + case '>': + tempSB.Append(">"); + break; + case '&': + tempSB.Append("&"); + break; + default: + hasNonSpace = true; + tempSB.Append(c.c); + break; + } + } + Flush(sb, tempSB, currentStyleId); + + if (UseOriginalFont) + sb.Append("
"); + + //build styles + if (UseStyleTag) + { + tempSB.Length = 0; + tempSB.Append(""); + + sb.Insert(0, tempSB.ToString()); + } + + if (IncludeLineNumbers) + sb.Insert(0, LineNumbersCSS); + + return sb.ToString(); + } + + private string GetCss(StyleIndex styleIndex) + { + List