diff --git a/.gitignore b/.gitignore
index bdc3535f..28b806ee 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,108 +1,108 @@
-# Build Folders (you can keep bin if you'd like, to store dlls and pdbs)
-[Bb]in/
-[Oo]bj/
-
-# mstest test results
-TestResults
-
-## Ignore Visual Studio temporary files, build results, and
-## files generated by popular Visual Studio add-ons.
-
-# User-specific files
-*.suo
-*.user
-*.sln.docstates
-
-# Build results
-[Dd]ebug/
-[Rr]elease/
-x64/
-*_i.c
-*_p.c
-*.ilk
-*.meta
-*.obj
-*.pch
-*.pdb
-*.pgc
-*.pgd
-*.rsp
-*.sbr
-*.tlb
-*.tli
-*.tlh
-*.tmp
-*.log
-*.vspscc
-*.vssscc
-.builds
-
-# Visual C++ cache files
-ipch/
-*.aps
-*.ncb
-*.opensdf
-*.sdf
-
-# Visual Studio profiler
-*.psess
-*.vsp
-*.vspx
-
-# Guidance Automation Toolkit
-*.gpState
-
-# ReSharper is a .NET coding add-in
-_ReSharper*
-
-# NCrunch
-*.ncrunch*
-.*crunch*.local.xml
-
-# Installshield output folder
-[Ee]xpress
-
-# DocProject is a documentation generator add-in
-DocProject/buildhelp/
-DocProject/Help/*.HxT
-DocProject/Help/*.HxC
-DocProject/Help/*.hhc
-DocProject/Help/*.hhk
-DocProject/Help/*.hhp
-DocProject/Help/Html2
-DocProject/Help/html
-
-# Click-Once directory
-publish
-
-# Publish Web Output
-*.Publish.xml
-
-# NuGet Packages Directory
-packages
-
-# Windows Azure Build Output
-csx
-*.build.csdef
-
-# Windows Store app package directory
-AppPackages/
-
-# Others
-[Bb]in
-[Oo]bj
-sql
-TestResults
-[Tt]est[Rr]esult*
-*.Cache
-ClientBin
-[Ss]tyle[Cc]op.*
-~$*
-*.dbmdl
-Generated_Code #added for RIA/Silverlight projects
-
-# Backup & report files from converting an old project file to a newer
-# Visual Studio version. Backup files are not needed, because we have git ;-)
-_UpgradeReport_Files/
-Backup*/
-UpgradeLog*.XML
+# Build Folders (you can keep bin if you'd like, to store dlls and pdbs)
+[Bb]in/
+[Oo]bj/
+
+# mstest test results
+TestResults
+
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+
+# User-specific files
+*.suo
+*.user
+*.sln.docstates
+
+# Build results
+[Dd]ebug/
+[Rr]elease/
+x64/
+*_i.c
+*_p.c
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.log
+*.vspscc
+*.vssscc
+.builds
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opensdf
+*.sdf
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*
+
+# NCrunch
+*.ncrunch*
+.*crunch*.local.xml
+
+# Installshield output folder
+[Ee]xpress
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish
+
+# Publish Web Output
+*.Publish.xml
+
+# NuGet Packages Directory
+packages
+
+# Windows Azure Build Output
+csx
+*.build.csdef
+
+# Windows Store app package directory
+AppPackages/
+
+# Others
+[Bb]in
+[Oo]bj
+sql
+TestResults
+[Tt]est[Rr]esult*
+*.Cache
+ClientBin
+[Ss]tyle[Cc]op.*
+~$*
+*.dbmdl
+Generated_Code #added for RIA/Silverlight projects
+
+# Backup & report files from converting an old project file to a newer
+# Visual Studio version. Backup files are not needed, because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
diff --git a/Binary/FastColoredTextBox.dll b/Binary/FastColoredTextBox.dll
deleted file mode 100644
index 4c895334..00000000
Binary files a/Binary/FastColoredTextBox.dll and /dev/null differ
diff --git a/Binary/FastColoredTextBox.xml b/Binary/FastColoredTextBox.xml
deleted file mode 100644
index d9852c9c..00000000
--- a/Binary/FastColoredTextBox.xml
+++ /dev/null
@@ -1,3280 +0,0 @@
-
-
-
- FastColoredTextBox
-
-
-
-
- Item of autocomplete menu
-
-
-
-
- Returns text for inserting into Textbox
-
-
-
-
- Compares fragment text with this item
-
-
-
-
- Returns text for display into popup menu
-
-
-
-
- This method is called after item inserted into text
-
-
-
-
- Title for tooltip.
-
- Return null for disable tooltip for this item
-
-
-
- Tooltip text.
-
- For display tooltip text, ToolTipTitle must be not null
-
-
-
- Menu text. This text is displayed in the drop-down menu.
-
-
-
-
- Fore color of text of item
-
-
-
-
- Back color of item
-
-
-
-
- Item do not appears
-
-
-
-
- Item appears
-
-
-
-
- Item appears and will selected
-
-
-
-
- Autocomplete item for code snippets
-
- Snippet can contain special char ^ for caret position.
-
-
-
- Compares fragment text with this item
-
-
-
-
- This autocomplete item appears after dot
-
-
-
-
- This Item does not check correspondence to current text fragment.
- SuggestItem is intended for dynamic menus.
-
-
-
-
- Popup menu for autocomplete
-
-
-
-
- Regex pattern for serach fragment around caret
-
-
-
-
- Minimum fragment length for popup
-
-
-
-
- User selects item
-
-
-
-
- It fires after item inserting
-
-
-
-
- Occurs when popup menu is opening
-
-
-
-
- Allow TAB for select menu item
-
-
-
-
- Interval of menu appear (ms)
-
-
-
-
- Sets the max tooltip window size
-
-
-
-
- Tooltip will perm show and duration will be ignored
-
-
-
-
- Back color of selected item
-
-
-
-
- Border color of hovered item
-
-
-
-
- Shows popup menu immediately
-
- If True - MinFragmentLength will be ignored
-
-
-
- Minimal size of menu
-
-
-
-
- Image list of menu
-
-
-
-
- Tooltip duration (ms)
-
-
-
-
- Tooltip
-
-
-
-
- Base class for bookmark collection
-
-
-
-
- Collection of bookmarks
-
-
-
-
- Removes bookmark by line index
-
-
-
-
- Returns Bookmark by index.
-
-
-
-
- Bookmark of FastColoredTextbox
-
-
-
-
- Name of bookmark
-
-
-
-
- Line index
-
-
-
-
- Color of bookmark sign
-
-
-
-
- Scroll textbox to the bookmark
-
-
-
-
- Char and style
-
-
-
-
- Unicode character
-
-
-
-
- Style bit mask
-
- Bit 1 in position n means that this char will rendering by FastColoredTextBox.Styles[n]
-
-
-
- Shows document map of FCTB
-
-
-
-
- Scale
-
-
-
-
- Scrollbar visibility
-
-
-
-
- Exports colored text as HTML
-
- At this time only TextStyle renderer is supported. Other styles is not exported.
-
-
-
- Use nbsp; instead space
-
-
-
-
- Use nbsp; instead space in beginning of line
-
-
-
-
- Use original font
-
-
-
-
- Use style tag instead style attribute
-
-
-
-
- Use 'br' tag instead of '\n'
-
-
-
-
- Includes line numbers
-
-
-
-
- Exports colored text as RTF
-
- At this time only TextStyle renderer is supported. Other styles are not exported.
-
-
-
- Includes line numbers
-
-
-
-
- Use original font
-
-
-
-
- Required designer variable.
-
-
-
-
- Clean up any resources being used.
-
- true if managed resources should be disposed; otherwise, false.
-
-
-
- Required method for Designer support - do not modify
- the contents of this method with the code editor.
-
-
-
-
- Collection of Hints.
- This is temporary buffer for currently displayed hints.
-
-
-
-
- Clears all displayed hints
-
-
-
-
- Add and shows the hint
-
-
-
-
-
- Is collection contains the hint?
-
-
-
-
- Count of hints
-
-
-
-
- Hint of FastColoredTextbox
-
-
-
-
- Text of simple hint
-
-
-
-
- Linked range
-
-
-
-
- Backcolor
-
-
-
-
- Second backcolor
-
-
-
-
- Border color
-
-
-
-
- Fore color
-
-
-
-
- Text alignment
-
-
-
-
- Font
-
-
-
-
- Occurs when user click on simple hint
-
-
-
-
- Inner control
-
-
-
-
- Docking (allows None and Fill only)
-
-
-
-
- Width of hint (if Dock is None)
-
-
-
-
- Height of hint
-
-
-
-
- Host panel
-
-
-
-
- Tag
-
-
-
-
- Cursor
-
-
-
-
- Inlining. If True then hint will moves apart text.
-
-
-
-
- Scroll textbox to the hint
-
-
-
-
- Creates Hint
-
- Linked range
- Text for simple hint
- Inlining. If True then hint will moves apart text
- Docking. If True then hint will fill whole line
-
-
-
- Creates Hint
-
- Linked range
- Text for simple hint
-
-
-
- Creates Hint
-
- Linked range
- Inner control
- Inlining. If True then hint will moves apart text
- Docking. If True then hint will fill whole line
-
-
-
- Creates Hint
-
- Linked range
- Inner control
-
-
-
- Returns edited hotkey map
-
-
-
-
-
- Required designer variable.
-
-
-
-
- Clean up any resources being used.
-
- true if managed resources should be disposed; otherwise, false.
-
-
-
- Required method for Designer support - do not modify
- the contents of this method with the code editor.
-
-
-
-
- Customize how we display the line numbers
-
-
-
-
- Defines how line number is displayed
-
-
-
-
-
-
- Recover the line number from the formatted string
-
-
-
-
-
-
-
- This class records, stores and executes the macros.
-
-
-
-
- Allows to user to record macros
-
-
-
-
- Returns current recording state. Set to True/False to start/stop recording programmatically.
-
-
-
-
- FCTB
-
-
-
-
- Executes recorded macro
-
-
-
-
-
- Adds the char to current macro
-
-
-
-
- Adds keyboard key to current macro
-
-
-
-
- Clears last recorded macro
-
-
-
-
- Returns True if last macro is empty
-
-
-
-
- Macros as string.
-
-
-
-
- Dictionary of shortcuts for FCTB
-
-
-
-
- Actions for shortcuts
-
-
-
-
- Required designer variable.
-
-
-
-
- Clean up any resources being used.
-
- true if managed resources should be disposed; otherwise, false.
-
-
-
- Required method for Designer support - do not modify
- the contents of this method with the code editor.
-
-
-
-
- Highlights syntax for given language
-
-
-
-
- Highlights syntax for given XML description file
-
-
-
-
- Uses the given to parse a XML description and adds it as syntax descriptor.
- The syntax descriptor is used for highlighting when
-
- - Language property of FCTB is set to
- - DescriptionFile property of FCTB has the same value as the method parameter
-
-
- Name of the description file
- XmlDocument to parse
-
-
-
- Adds the given as resilient style. A resilient style is additionally available when highlighting is
- based on a syntax descriptor that has been derived from a XML description file. In the run of the highlighting routine
- the styles used by the FCTB are always dropped and replaced with the (initial) ones from the syntax descriptor. Resilient styles are
- added afterwards and can be used anyway.
-
- Style to add
-
-
-
- Highlights C# code
-
-
-
-
-
- Highlights VB code
-
-
-
-
-
- Highlights HTML code
-
-
-
-
-
- Highlights XML code
-
-
-
-
-
- Highlights SQL code
-
-
-
-
-
- Highlights PHP code
-
-
-
-
-
- Highlights JavaScript code
-
-
-
-
-
- Highlights Lua code
-
-
-
-
-
- Highlights JSON code
-
-
-
-
-
- String style
-
-
-
-
- Comment style
-
-
-
-
- Number style
-
-
-
-
- C# attribute style
-
-
-
-
- Class name style
-
-
-
-
- Keyword style
-
-
-
-
- Style of tags in comments of C#
-
-
-
-
- HTML attribute value style
-
-
-
-
- HTML tag brackets style
-
-
-
-
- HTML tag name style
-
-
-
-
- HTML Entity style
-
-
-
-
- XML attribute style
-
-
-
-
- XML attribute value style
-
-
-
-
- XML tag brackets style
-
-
-
-
- XML tag name style
-
-
-
-
- XML Entity style
-
-
-
-
- XML CData style
-
-
-
-
- Variable style
-
-
-
-
- Specific PHP keyword style
-
-
-
-
- Specific PHP keyword style
-
-
-
-
- SQL Statements style
-
-
-
-
- SQL Functions style
-
-
-
-
- SQL Types style
-
-
-
-
- Language
-
-
-
-
- Required designer variable.
-
-
-
-
- Clean up any resources being used.
-
- true if managed resources should be disposed; otherwise, false.
-
-
-
- Required method for Designer support - do not modify
- the contents of this method with the code editor.
-
-
-
-
- Fast colored textbox
-
-
-
-
- Constructor
-
-
-
-
- AutoComplete brackets
-
-
-
-
- Colors of some service visual markers
-
-
-
-
- Contains UniqueId of start lines of folded blocks
-
- This dictionary remembers folding state of blocks.
- It is needed to restore child folding after user collapsed/expanded top-level folding block.
-
-
-
- Strategy of search of brackets to highlighting
-
-
-
-
- Automatically shifts secondary wordwrap lines on the shift amount of the first line
-
-
-
-
- Indent of secondary wordwrap lines (in chars)
-
-
-
-
- MacrosManager records, stores and executes the macroses
-
-
-
-
- Allows drag and drop
-
-
-
-
- Collection of Hints.
- This is temporary buffer for currently displayed hints.
-
- You can asynchronously add, remove and clear hints. Appropriate hints will be shown or hidden from the screen.
-
-
-
- Delay (ms) of ToolTip
-
-
-
-
- ToolTip component
-
-
-
-
- Color of bookmarks
-
-
-
-
- Bookmarks
-
-
-
-
- Enables virtual spaces
-
-
-
-
- Strategy of search of end of folding block
-
-
-
-
- Indicates if tab characters are accepted as input
-
-
-
-
- Indicates if return characters are accepted as input
-
-
-
-
- Shows or hides the caret
-
-
-
-
- Enables caret blinking
-
-
-
-
- Draw caret when the control is not focused
-
-
-
-
- Color of border of text area
-
-
-
-
- Type of border of text area
-
-
-
-
- Background color for current line
-
-
-
-
- Background color for highlighting of changed lines
-
-
-
-
- Fore color (default style color)
-
-
-
-
- Height of char in pixels (includes LineInterval)
-
-
-
-
- Interval between lines (in pixels)
-
-
-
-
- Width of char in pixels
-
-
-
-
- Spaces count for tab
-
-
-
-
- Text was changed
-
-
-
-
- Text version
-
- This counter is incremented each time changes the text
-
-
-
- Read only
-
-
-
-
- Shows line numbers.
-
-
-
-
- Shows vertical lines between folding start line and folding end line.
-
-
-
-
- Rectangle where located text
-
-
-
-
- Color of line numbers.
-
-
-
-
- Start value of first line number.
-
-
-
-
- To create your own line number formatting, you have to implement the abstract LineNumberFormatting class
-
-
-
-
- Background color of indent area
-
-
-
-
- Background color of padding area
-
-
-
-
- Color of disabled component
-
-
-
-
- Color of caret
-
-
-
-
- Wide caret
-
-
-
-
- Color of service lines (folding lines, borders of blocks etc.)
-
-
-
-
- Padings of text area
-
-
-
-
- --Do not use this property--
-
-
-
-
- Color of folding area indicator
-
-
-
-
- Enables folding indicator (left vertical line between folding bounds)
-
-
-
-
- Left distance to text beginning
-
-
-
-
- Left padding in pixels
-
-
-
-
- This property draws vertical line after defined char position.
- Set to 0 for disable drawing of vertical line.
-
-
-
-
- Styles
-
-
-
-
- Hotkeys. Do not use this property in your code, use HotkeysMapping property.
-
-
-
-
- Hotkeys mapping
-
-
-
-
- Default text style
- This style is using when no one other TextStyle is not defined in Char.style
-
-
-
-
- Style for rendering Selection area
-
-
-
-
- Style for folded block rendering
-
-
-
-
- Style for brackets highlighting
-
-
-
-
- Style for alternative brackets highlighting
-
-
-
-
- Opening bracket for brackets highlighting.
- Set to '\x0' for disable brackets highlighting.
-
-
-
-
- Closing bracket for brackets highlighting.
- Set to '\x0' for disable brackets highlighting.
-
-
-
-
- Alternative opening bracket for brackets highlighting.
- Set to '\x0' for disable brackets highlighting.
-
-
-
-
- Alternative closing bracket for brackets highlighting.
- Set to '\x0' for disable brackets highlighting.
-
-
-
-
- Comment line prefix.
-
-
-
-
- This property specifies which part of the text will be highlighted as you type (by built-in highlighter).
-
- When a user enters text, a component refreshes highlighting (because the text was changed).
- This property specifies exactly which section of the text will be re-highlighted.
- This can be useful to highlight multi-line comments, for example.
-
-
-
- Is keyboard in replace mode (wide caret) ?
-
-
-
-
- Allows text rendering several styles same time.
-
-
-
-
- Allows to record macros.
-
-
-
-
- Allows AutoIndent. Inserts spaces before new line.
-
-
-
-
- Does autoindenting in existing lines. It works only if AutoIndent is True.
-
-
-
-
- Minimal delay(ms) for delayed events (except TextChangedDelayed).
-
-
-
-
- Minimal delay(ms) for TextChangedDelayed event.
-
-
-
-
- Language for highlighting by built-in highlighter.
-
-
-
-
- Syntax Highlighter
-
-
-
-
- XML file with description of syntax highlighting.
- This property works only with Language == Language.Custom.
-
-
-
-
- Position of left highlighted bracket.
-
-
-
-
- Position of right highlighted bracket.
-
-
-
-
- Position of left highlighted alternative bracket.
-
-
-
-
- Position of right highlighted alternative bracket.
-
-
-
-
- Start line index of current highlighted folding area. Return -1 if start of area is not found.
-
-
-
-
- End line index of current highlighted folding area. Return -1 if end of area is not found.
-
-
-
-
- TextSource
-
-
-
-
- The source of the text.
- Allows to get text from other FastColoredTextBox.
-
-
-
-
- Returns current visible range of text
-
-
-
-
- Current selection range
-
-
-
-
- Background color.
- It is used if BackBrush is null.
-
-
-
-
- Background brush.
- If Null then BackColor is used.
-
-
-
-
- Multiline
-
-
-
-
- WordWrap.
-
-
-
-
- WordWrap mode.
-
-
-
-
- If true then line breaks included into the selection will be selected too.
- Then line breaks will be shown as selected blank character.
-
-
-
-
- Do not change this property
-
-
-
-
- Count of lines
-
-
-
-
- Gets or sets char and styleId for given place
- This property does not fire OnTextChanged event
-
-
-
-
- Gets Line
-
-
-
-
- Text of control
-
-
-
-
- Text lines
-
-
-
-
- Gets colored text as HTML
-
- For more flexibility you can use ExportToHTML class also
-
-
-
- Gets colored text as RTF
-
- For more flexibility you can use ExportToRTF class also
-
-
-
- Text of current selection
-
-
-
-
- Start position of selection
-
-
-
-
- Length of selected text
-
-
-
-
- Font
-
- Use only monospaced font
-
-
-
- Font
-
- Use only monospaced font
-
-
-
- Indicates that IME is allowed (for CJK language entering)
-
-
-
-
- Is undo enabled?
-
-
-
-
- Is redo enabled?
-
-
-
-
- Range of all text
-
-
-
-
- Color of selected area
-
-
-
-
- Reserved space for line number characters.
- If smaller than needed (e. g. line count >= 10 and this value set to 1) this value will have no impact.
- If you want to reserve space, e. g. for line numbers >= 10 or >= 100 than you can set this value to 2 or 3 or higher.
-
-
-
-
- Occurs when mouse is moving over text and tooltip is needed
-
-
-
-
- Removes all hints
-
-
-
-
- Add and shows the hint
-
- Linked range
- Inner control
- Scrolls textbox to the hint
- Inlining. If True then hint will moves apart text
- Docking. If True then hint will fill whole line
-
-
-
- Add and shows the hint
-
- Linked range
- Inner control
-
-
-
- Add and shows simple text hint
-
- Linked range
- Text of simple hint
- Scrolls textbox to the hint
- Inlining. If True then hint will moves apart text
- Docking. If True then hint will fill whole line
-
-
-
- Add and shows simple text hint
-
- Linked range
- Text of simple hint
-
-
-
- Occurs when user click on the hint
-
-
-
-
-
- Occurs when VisibleRange is changed
-
-
-
-
- Invalidates the entire surface of the control and causes the control to be redrawn.
- This method is thread safe and does not require Invoke.
-
-
-
-
- HintClick event.
- It occurs if user click on the hint.
-
-
-
-
- TextChanged event.
- It occurs after insert, delete, clear, undo and redo operations.
-
-
-
-
- Fake event for correct data binding
-
-
-
-
- Occurs when user paste text from clipboard
-
-
-
-
- TextChanging event.
- It occurs before insert, delete, clear, undo and redo operations.
-
-
-
-
- SelectionChanged event.
- It occurs after changing of selection.
-
-
-
-
- VisibleRangeChanged event.
- It occurs after changing of visible range.
-
-
-
-
- TextChangedDelayed event.
- It occurs after insert, delete, clear, undo and redo operations.
- This event occurs with a delay relative to TextChanged, and fires only once.
-
-
-
-
- SelectionChangedDelayed event.
- It occurs after changing of selection.
- This event occurs with a delay relative to SelectionChanged, and fires only once.
-
-
-
-
- VisibleRangeChangedDelayed event.
- It occurs after changing of visible range.
- This event occurs with a delay relative to VisibleRangeChanged, and fires only once.
-
-
-
-
- It occurs when user click on VisualMarker.
-
-
-
-
- It occurs when visible char is enetering (alphabetic, digit, punctuation, DEL, BACKSPACE)
-
- Set Handle to True for cancel key
-
-
-
- It occurs when visible char is enetered (alphabetic, digit, punctuation, DEL, BACKSPACE)
-
-
-
-
- It occurs when calculates AutoIndent for new line
-
-
-
-
- It occurs when line background is painting
-
-
-
-
- Occurs when line was inserted/added
-
-
-
-
- Occurs when line was removed
-
-
-
-
- Occurs when current highlighted folding area is changed.
- Current folding area see in StartFoldingLine and EndFoldingLine.
-
-
-
-
-
- Occurs when undo/redo stack is changed
-
-
-
-
-
- Occurs when component was zoomed
-
-
-
-
- Occurs when user pressed key, that specified as CustomAction
-
-
-
-
- Occurs when scroolbars are updated
-
-
-
-
- Occurs when custom wordwrap is needed
-
-
-
-
- Returns list of styles of given place
-
-
-
-
- Call this method if the recalc of the position of lines is needed.
-
-
-
-
- Call this method if the recalc of the position of lines is needed.
-
-
-
-
- Call this method if the recalc of the position of lines is needed.
-
-
-
-
- Navigates forward (by Line.LastVisit property)
-
-
-
-
- Navigates backward (by Line.LastVisit property)
-
-
-
-
- Navigates to defined line, without Line.LastVisit reseting
-
-
-
-
- Add new style
-
- Layer index of this style
-
-
-
- Checks if the styles buffer has enough space to add one
- more element. If not, an exception is thrown. Otherwise,
- the index of a free slot is returned.
-
- Index of free styles buffer slot
- If maximum count of styles is exceeded
-
-
-
- Shows find dialog
-
-
-
-
- Shows find dialog
-
-
-
-
- Shows replace dialog
-
-
-
-
- Shows replace dialog
-
-
-
-
- Gets length of given line
-
- Line index
- Length of line
-
-
-
- Get range of line
-
- Line index
-
-
-
- Copy selected text into Clipboard
-
-
-
-
- Cut selected text into Clipboard
-
-
-
-
- Paste text from clipboard into selected position
-
-
-
-
- Select all chars of text
-
-
-
-
- Move caret to end of text
-
-
-
-
- Move caret to first position
-
-
-
-
- Clear text, styles, history, caches
-
-
-
-
- Clear buffer of styles
-
-
-
-
- Clear style of all text
-
-
-
-
- Clears undo and redo stacks
-
-
-
-
- Insert text into current selected position
-
-
-
-
- Insert text into current selected position
-
-
-
-
-
- Insert text into current selection position (with predefined style)
-
-
-
-
-
- Insert text into current selection position (with predefined style)
-
-
-
-
- Insert text into replaceRange and restore previous selection
-
-
-
-
- Append string to end of the Text
-
-
-
-
- Append string to end of the Text
-
-
-
-
- Returns index of the style in Styles
- -1 otherwise
-
-
- Index of the style in Styles
-
-
-
- Returns StyleIndex mask of given styles
-
-
- StyleIndex mask of given styles
-
-
-
- Deletes selected chars
-
-
-
-
- Deletes current line(s)
-
-
-
-
- Calculates wordwrap cutoffs
-
-
-
-
- Scroll control for display defined rectangle
-
-
-
-
-
- Updates scrollbar position after Value changed
-
-
-
-
- Scroll control for display caret
-
-
-
-
- Scroll control left
-
-
-
-
- Scroll control for display selection area
-
-
-
-
- Scroll control for display given range
-
-
-
-
- Scroll control for display given range
-
-
-
-
- Process control keys
-
-
-
-
- Scrolls to nearest bookmark or to first bookmark
-
- Current bookmark line index
-
-
-
- Scrolls to nearest previous bookmark or to last bookmark
-
- Current bookmark line index
-
-
-
- Bookmarks line
-
-
-
-
- Unbookmarks current line
-
-
-
-
- Moves selected lines down
-
-
-
-
- Moves selected lines up
-
-
-
-
- Convert selected text to upper case
-
-
-
-
- Convert selected text to lower case
-
-
-
-
- Convert selected text to title case
-
-
-
-
- Convert selected text to sentence case
-
-
-
-
- Insert/remove comment prefix into selected lines
-
-
-
-
- Insert/remove comment prefix into selected lines
-
-
-
-
- Process "real" keys (no control)
-
-
-
-
- Enables AutoIndentChars mode
-
-
-
-
- Regex patterns for AutoIndentChars (one regex per line)
-
-
-
-
- Do AutoIndentChars
-
-
-
-
- Finds given char after current caret position, moves the caret to found pos.
-
-
-
-
-
- Inserts autoindent's spaces in the line
-
-
-
-
- Returns needed start space count for the line
-
-
-
-
- Undo last operation
-
-
-
-
- Redo
-
-
-
-
- Draws text to given Graphics
-
-
- Start place of drawing text
- Size of drawing
-
-
-
- Draw control
-
-
-
-
- Gets the value for the system control panel mouse wheel scroll settings.
- The value returns the number of lines that shall be scolled if the user turns the mouse wheet one step.
-
-
- This methods gets the "WheelScrollLines" value our from the registry key "HKEY_CURRENT_USER\Control Panel\Desktop".
- If the value of this option is 0, the screen will not scroll when the mouse wheel is turned.
- If the value of this option is -1 or is greater than the number of lines visible in the window,
- the screen will scroll up or down by one page.
-
-
- Number of lines to scrol l when the mouse wheel is turned
-
-
-
-
- Zooming (in percentages)
-
-
-
-
- Gets nearest line and char position from coordinates
-
- Point
- Line and char position
-
-
-
- Gets nearest absolute text position for given point
-
- Point
- Position
-
-
-
- Fires TextChanging event
-
-
-
-
- Fires TextChanged event
-
-
-
-
- Fires TextChanged event
-
-
-
-
- Fires TextChanged event
-
-
-
-
- Call this method before multiple text changing
-
-
-
-
- Call this method after multiple text changing
-
-
-
-
- Fires TextChanged event
-
-
-
-
- Clears folding state for range of text
-
-
-
-
- Fires SelectionChanged event
-
-
-
-
- Gets absolute text position from line and char position
-
- Line and char position
- Point of char
-
-
-
- Gets line and char position from absolute text position
-
-
-
-
- Gets absolute char position from char position
-
-
-
-
- Gets point for given line and char position
-
- Line and char position
- Coordiantes
-
-
-
- Get range of text
-
- Absolute start position
- Absolute finish position
- Range
-
-
-
- Get range of text
-
- Line and char position
- Line and char position
- Range
-
-
-
- Finds ranges for given regex pattern
-
- Regex pattern
- Enumeration of ranges
-
-
-
- Finds ranges for given regex pattern
-
- Regex pattern
- Enumeration of ranges
-
-
-
- Get text of given line
-
- Line index
- Text
-
-
-
- Exapnds folded block
-
- Start line
-
-
-
- Collapse folding blocks using FoldedBlocks dictionary.
-
-
-
-
- Expand collapsed block
-
-
-
-
- Expand collapsed block
-
- Any line inside collapsed block
-
-
-
- Collapses all folding blocks
-
-
-
-
- Exapnds all folded blocks
-
-
-
-
-
- Collapses folding block
-
- Start folding line
-
-
-
- Start foilding marker for the line
-
-
-
-
- End foilding marker for the line
-
-
-
-
- Collapse text block
-
-
-
-
- Insert TAB into front of seletcted lines.
-
-
-
-
- Remove TAB from front of seletcted lines.
-
-
-
-
- Remove TAB in front of the caret ot the selected line.
-
-
-
-
- Insert autoindents into selected lines
-
-
-
-
- Insert prefix into front of seletcted lines
-
-
-
-
- Remove prefix from front of selected lines
- This method ignores forward spaces of the line
-
-
-
-
- Begins AutoUndo block.
- All changes of text between BeginAutoUndo() and EndAutoUndo() will be canceled in one operation Undo.
-
-
-
-
- Ends AutoUndo block.
- All changes of text between BeginAutoUndo() and EndAutoUndo() will be canceled in one operation Undo.
-
-
-
-
- Highlights brackets around caret
-
-
-
-
- Returns range between brackets (or null if not found)
-
-
-
-
- Selectes next fragment for given regex.
-
-
-
-
- Prints range of text
-
-
-
-
- Prints all text
-
-
-
-
- Prints all text, without any dialog windows
-
-
-
-
- Open text file
-
-
-
-
- Open text file (with automatic encoding detector)
-
-
-
-
- Open file binding mode
-
-
-
-
-
-
- Close file binding mode
-
-
-
-
- Save text to the file
-
-
-
-
-
-
- Set VisibleState of line
-
-
-
-
- Returns VisibleState of the line
-
-
-
-
- Shows Goto dialog form
-
-
-
-
- Set current line number and make it visible
-
-
-
-
-
- Occurs when undo/redo stack is changed
-
-
-
-
- Search lines by regex pattern
-
-
-
-
- Removes given lines
-
-
-
-
- Activates the scrolling mode (middle click button).
-
- MouseEventArgs
-
-
-
- Deactivates the scrolling mode (middle click button).
-
-
-
-
- Restore scrolls
-
-
-
-
- Inserted line index
-
-
-
-
- Count of inserted lines
-
-
-
-
- Removed line index
-
-
-
-
- Count of removed lines
-
-
-
-
- UniqueIds of removed lines
-
-
-
-
- TextChanged event argument
-
-
-
-
- Constructor
-
-
-
-
- This range contains changed area of text
-
-
-
-
- Set to true if you want to cancel text inserting
-
-
-
-
- Word wrapping by control width
-
-
-
-
- Word wrapping by preferred line width (PreferredLineWidth)
-
-
-
-
- Char wrapping by control width
-
-
-
-
- Char wrapping by preferred line width (PreferredLineWidth)
-
-
-
-
- Custom wrap (by event WordWrapNeeded)
-
-
-
-
- Title of page. If you want to print Title on the page, insert code &w in Footer or Header.
-
-
-
-
- Footer of page.
- Here you can use special codes: &w (Window title), &D, &d (Date), &t(), &4 (Time), &p (Current page number), &P (Total number of pages), && (A single ampersand), &b (Right justify text, Center text. If &b occurs once, then anything after the &b is right justified. If &b occurs twice, then anything between the two &b is centered, and anything after the second &b is right justified).
- More detailed see here
-
-
-
-
- Header of page
- Here you can use special codes: &w (Window title), &D, &d (Date), &t(), &4 (Time), &p (Current page number), &P (Total number of pages), && (A single ampersand), &b (Right justify text, Center text. If &b occurs once, then anything after the &b is right justified. If &b occurs twice, then anything between the two &b is centered, and anything after the second &b is right justified).
- More detailed see here
-
-
-
-
- Prints line numbers
-
-
-
-
- Additional spaces count for this line, relative to previous line
-
-
-
-
- Additional spaces count for next line, relative to previous line
-
-
-
-
- Absolute indentation of current line. You can change this property if you want to set absolute indentation.
-
-
-
-
- Type of highlighting
-
-
-
-
- Highlight only changed range of text. Highest performance.
-
-
-
-
- Highlight visible range of text. Middle performance.
-
-
-
-
- Highlight all (visible and invisible) text. Lowest performance.
-
-
-
-
- Strategy of search of end of folding block
-
-
-
-
- Strategy of search of brackets to highlighting
-
-
-
-
- ToolTipNeeded event args
-
-
-
-
- HintClick event args
-
-
-
-
- CustomAction event args
-
-
-
-
- Style index mask (16 styles)
-
-
-
-
- Insert single char
-
- This operation includes also insertion of new line and removing char by backspace
-
-
-
- Constructor
-
- Underlaying textbox
- Inserting char
-
-
-
- Undo operation
-
-
-
-
- Execute operation
-
-
-
-
- Merge lines i and i+1
-
-
-
-
- Insert text
-
-
-
-
- Constructor
-
- Underlaying textbox
- Text for inserting
-
-
-
- Undo operation
-
-
-
-
- Execute operation
-
-
-
-
- Insert text into given ranges
-
-
-
-
- Constructor
-
- Underlaying textbox
- List of ranges for replace
- Text for inserting
-
-
-
- Undo operation
-
-
-
-
- Execute operation
-
-
-
-
- Clear selected text
-
-
-
-
- Construstor
-
- Underlaying textbox
-
-
-
- Undo operation
-
-
-
-
- Execute operation
-
-
-
-
- Replaces text
-
-
-
-
- Constructor
-
- Underlaying textsource
- List of ranges for replace
-
-
-
- Undo operation
-
-
-
-
- Execute operation
-
-
-
-
- Removes lines
-
-
-
-
- Constructor
-
- Underlaying textbox
- List of ranges for replace
- Text for inserting
-
-
-
- Undo operation
-
-
-
-
- Execute operation
-
-
-
-
- Wrapper for multirange commands
-
-
-
-
- Remembers current selection and restore it after Undo
-
-
-
-
- Required designer variable.
-
-
-
-
- Clean up any resources being used.
-
- true if managed resources should be disposed; otherwise, false.
-
-
-
- Required method for Designer support - do not modify
- the contents of this method with the code editor.
-
-
-
-
- Limited stack
-
-
-
-
- Max stack length
-
-
-
-
- Current length of stack
-
-
-
-
- Constructor
-
- Maximum length of stack
-
-
-
- Pop item
-
-
-
-
- Peek item
-
-
-
-
- Push item
-
-
-
-
- Clear stack
-
-
-
-
- Line of text
-
-
-
-
- Text of line was changed
-
-
-
-
- Time of last visit of caret in this line
-
- This property can be used for forward/backward navigating
-
-
-
- Background brush.
-
-
-
-
- Unique ID
-
-
-
-
- Count of needed start spaces for AutoIndent
-
-
-
-
- Clears style of chars, delete folding markers
-
-
-
-
- Text of the line
-
-
-
-
- Clears folding markers
-
-
-
-
- Count of start spaces
-
-
-
-
- Chars count
-
-
-
-
- Visible state
-
-
-
-
- Positions for wordwrap cutoffs
-
-
-
-
- Count of wordwrap string count for this line
-
-
-
-
- Gets index of wordwrap string for given char position
-
-
-
-
- Line index and char index
-
-
-
-
- Diapason of text chars
-
-
-
-
- Constructor
-
-
-
-
- Return true if no selected text
-
-
-
-
- Column selection mode
-
-
-
-
- Constructor
-
-
-
-
- Constructor
-
-
-
-
- Constructor. Creates range of the line
-
-
-
-
- Returns intersection with other range,
- empty range returned otherwise
-
-
-
-
-
-
- Returns union with other range.
-
-
-
-
-
-
- Select all chars of control
-
-
-
-
- Start line and char position
-
-
-
-
- Finish line and char position
-
-
-
-
- Text of range
-
- This property has not 'set' accessor because undo/redo stack works only with
- FastColoredTextBox.Selection range. So, if you want to set text, you need to use FastColoredTextBox.Selection
- and FastColoredTextBox.InsertText() mehtod.
-
-
-
-
- Returns first char after Start place
-
-
-
-
- Returns first char before Start place
-
-
-
-
- Returns required char's number before start of the Range
-
-
-
-
- Returns required char's number after start of the Range
-
-
-
-
- Clone range
-
-
-
-
-
- Return minimum of end.X and start.X
-
-
-
-
- Return maximum of end.X and start.X
-
-
-
-
- Move range right
-
- This method jump over folded blocks
-
-
-
- Move range left
-
- This method can to go inside folded blocks
-
-
-
- Move range left
-
- This method jump over folded blocks
-
-
-
- Move range left
-
- This method can to go inside folded blocks
-
-
-
- Set style for range
-
-
-
-
- Set style for given regex pattern
-
-
-
-
- Set style for given regex
-
-
-
-
- Set style for given regex pattern
-
-
-
-
- Set style for given regex pattern
-
-
-
-
- Set style for given regex pattern
-
-
-
-
- Appends style to chars of range
-
-
-
-
- Sets folding markers
-
- Pattern for start folding line
- Pattern for finish folding line
-
-
-
- Sets folding markers
-
- Pattern for start folding line
- Pattern for finish folding line
-
-
-
- Sets folding markers
-
- Pattern for start and end folding line
-
-
-
- Finds ranges for given regex pattern
-
- Regex pattern
- Enumeration of ranges
-
-
-
- Finds ranges for given regex pattern
-
- Regex pattern
- Enumeration of ranges
-
-
-
- Finds ranges for given regex pattern.
- Search is separately in each line.
- This method requires less memory than GetRanges().
-
- Regex pattern
- Enumeration of ranges
-
-
-
- Finds ranges for given regex.
- Search is separately in each line.
- This method requires less memory than GetRanges().
-
- Regex
- Enumeration of ranges
-
-
-
- Finds ranges for given regex pattern.
- Search is separately in each line (order of lines is reversed).
- This method requires less memory than GetRanges().
-
- Regex pattern
- Enumeration of ranges
-
-
-
- Finds ranges for given regex
-
- Enumeration of ranges
-
-
-
- Clear styles of range
-
-
-
-
- Clear styles of range
-
-
-
-
- Clear folding markers of all lines of range
-
-
-
-
- Starts selection position updating
-
-
-
-
- Ends selection position updating
-
-
-
-
- Exchanges Start and End if End appears before Start
-
-
-
-
- Exchanges Start and End
-
-
-
-
- Expands range from first char of Start line to last char of End line
-
-
-
-
- Chars of range (exclude \n)
-
-
-
-
- Get fragment of text around Start place. Returns maximal matched to pattern fragment.
-
- Allowed chars pattern for fragment
- Range of found fragment
-
-
-
- Get fragment of text around Start place. Returns maximal matched to given Style.
-
- Allowed style for fragment
- Range of found fragment
-
-
-
- Get fragment of text around Start place. Returns maximal mathed to pattern fragment.
-
- Allowed chars pattern for fragment
- Range of found fragment
-
-
-
- Range is readonly?
- This property return True if any char of the range contains ReadOnlyStyle.
- Set this property to True/False to mark chars of the range as Readonly/Writable.
-
-
-
-
- Is char before range readonly
-
-
-
-
-
- Is char after range readonly
-
-
-
-
-
- Style of chars
-
- This is base class for all text and design renderers
-
-
-
- This style is exported to outer formats (HTML for example)
-
-
-
-
- Occurs when user click on StyleVisualMarker joined to this style
-
-
-
-
- Constructor
-
-
-
-
- Renders given range of text
-
- Graphics object
- Position of the range in absolute control coordinates
- Rendering range of text
-
-
-
- Occurs when user click on StyleVisualMarker joined to this style
-
-
-
-
- Shows VisualMarker
- Call this method in Draw method, when you need to show VisualMarker for your style
-
-
-
-
- Returns CSS for export to HTML
-
-
-
-
-
- Returns RTF descriptor for export to RTF
-
-
-
-
-
- Style for chars rendering
- This renderer can draws chars, with defined fore and back colors
-
-
-
-
- Renderer for folded block
-
-
-
-
- Renderer for selected area
-
-
-
-
- Marker style
- Draws background color for text
-
-
-
-
- Draws small rectangle for popup menu
-
-
-
-
- This style draws a wavy line below a given text range.
-
- Thanks for Yallie
-
-
-
- This style is used to mark range of text as ReadOnly block
-
- You can inherite this style to add visual effects of readonly text
-
-
-
- This class contains the source text (chars and styles).
- It stores a text lines, the manager of commands, undo/redo stack, styles.
-
-
-
-
- Styles
-
-
-
-
- Occurs when line was inserted/added
-
-
-
-
- Occurs when line was removed
-
-
-
-
- Occurs when text was changed
-
-
-
-
- Occurs when recalc is needed
-
-
-
-
- Occurs when recalc wordwrap is needed
-
-
-
-
- Occurs before text changing
-
-
-
-
- Occurs after CurrentTB was changed
-
-
-
-
- Current focused FastColoredTextBox
-
-
-
-
- Default text style
- This style is using when no one other TextStyle is not defined in Char.style
-
-
-
-
- Text lines
-
-
-
-
- Lines count
-
-
-
-
- These classes are required for correct data binding to Text property of FastColoredTextbox
-
-
-
-
- This class contains the source text (chars and styles).
- It stores a text lines, the manager of commands, undo/redo stack, styles.
-
-
-
-
- Occurs when need to display line in the textbox
-
-
-
-
- Occurs when need to save line in the file
-
-
-
-
- End Of Line characters used for saving
-
-
-
-
- This text will be displayed in textbox
-
-
-
-
- This property contains only changed text.
- If text of line is not changed, this property contains null.
-
-
-
-
- This text will be saved in the file
-
-
-
-
diff --git a/Binary/TabStrip.dll b/Binary/TabStrip.dll
deleted file mode 100644
index 5e2b2c70..00000000
Binary files a/Binary/TabStrip.dll and /dev/null differ
diff --git a/Binary/Tester.exe b/Binary/Tester.exe
deleted file mode 100644
index b086b8be..00000000
Binary files a/Binary/Tester.exe and /dev/null differ
diff --git a/Binary/htmlDesc.xml b/Binary/htmlDesc.xml
deleted file mode 100644
index 76a1e178..00000000
--- a/Binary/htmlDesc.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
-
-
-
-
- (<!--.*?-->)|(<!--.*)
- (<!--.*?-->)|(.*-->)
- <|/>|</|>
- <|/>|</|>
- <(?<range>[!\w\d]+)
- </(?<range>[\w\d]+)>
- (?<range>\S+?)='[^']*'|(?<range>\S+)="[^"]*"|(?<range>\S+)=\S+
-
-
-
\ No newline at end of file
diff --git a/FastColoredTextBox.sln b/FastColoredTextBox.sln
index 17b7d834..ef8213b6 100644
--- a/FastColoredTextBox.sln
+++ b/FastColoredTextBox.sln
@@ -1,54 +1,55 @@
-
-Microsoft Visual Studio Solution File, Format Version 11.00
-# Visual Studio 2010
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tester", "Tester\Tester.csproj", "{EBE443EE-F4C7-49E6-AC22-959CA62FAA05}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FastColoredTextBox", "FastColoredTextBox\FastColoredTextBox.csproj", "{6DD14A85-CCFC-4774-BD26-0F5772512319}"
-EndProject
-Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "TesterVB", "TesterVB\TesterVB.vbproj", "{3EF3A5A0-2365-41FD-97A0-254A2CFC6577}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Debug|Mixed Platforms = Debug|Mixed Platforms
- Debug|x86 = Debug|x86
- Release|Any CPU = Release|Any CPU
- Release|Mixed Platforms = Release|Mixed Platforms
- Release|x86 = Release|x86
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {EBE443EE-F4C7-49E6-AC22-959CA62FAA05}.Debug|Any CPU.ActiveCfg = Debug|x86
- {EBE443EE-F4C7-49E6-AC22-959CA62FAA05}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
- {EBE443EE-F4C7-49E6-AC22-959CA62FAA05}.Debug|Mixed Platforms.Build.0 = Debug|x86
- {EBE443EE-F4C7-49E6-AC22-959CA62FAA05}.Debug|x86.ActiveCfg = Debug|x86
- {EBE443EE-F4C7-49E6-AC22-959CA62FAA05}.Debug|x86.Build.0 = Debug|x86
- {EBE443EE-F4C7-49E6-AC22-959CA62FAA05}.Release|Any CPU.ActiveCfg = Release|x86
- {EBE443EE-F4C7-49E6-AC22-959CA62FAA05}.Release|Mixed Platforms.ActiveCfg = Release|x86
- {EBE443EE-F4C7-49E6-AC22-959CA62FAA05}.Release|Mixed Platforms.Build.0 = Release|x86
- {EBE443EE-F4C7-49E6-AC22-959CA62FAA05}.Release|x86.ActiveCfg = Release|x86
- {EBE443EE-F4C7-49E6-AC22-959CA62FAA05}.Release|x86.Build.0 = Release|x86
- {6DD14A85-CCFC-4774-BD26-0F5772512319}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {6DD14A85-CCFC-4774-BD26-0F5772512319}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {6DD14A85-CCFC-4774-BD26-0F5772512319}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {6DD14A85-CCFC-4774-BD26-0F5772512319}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
- {6DD14A85-CCFC-4774-BD26-0F5772512319}.Debug|x86.ActiveCfg = Debug|Any CPU
- {6DD14A85-CCFC-4774-BD26-0F5772512319}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {6DD14A85-CCFC-4774-BD26-0F5772512319}.Release|Any CPU.Build.0 = Release|Any CPU
- {6DD14A85-CCFC-4774-BD26-0F5772512319}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {6DD14A85-CCFC-4774-BD26-0F5772512319}.Release|Mixed Platforms.Build.0 = Release|Any CPU
- {6DD14A85-CCFC-4774-BD26-0F5772512319}.Release|x86.ActiveCfg = Release|Any CPU
- {3EF3A5A0-2365-41FD-97A0-254A2CFC6577}.Debug|Any CPU.ActiveCfg = Debug|x86
- {3EF3A5A0-2365-41FD-97A0-254A2CFC6577}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
- {3EF3A5A0-2365-41FD-97A0-254A2CFC6577}.Debug|Mixed Platforms.Build.0 = Debug|x86
- {3EF3A5A0-2365-41FD-97A0-254A2CFC6577}.Debug|x86.ActiveCfg = Debug|x86
- {3EF3A5A0-2365-41FD-97A0-254A2CFC6577}.Debug|x86.Build.0 = Debug|x86
- {3EF3A5A0-2365-41FD-97A0-254A2CFC6577}.Release|Any CPU.ActiveCfg = Release|x86
- {3EF3A5A0-2365-41FD-97A0-254A2CFC6577}.Release|Mixed Platforms.ActiveCfg = Release|x86
- {3EF3A5A0-2365-41FD-97A0-254A2CFC6577}.Release|Mixed Platforms.Build.0 = Release|x86
- {3EF3A5A0-2365-41FD-97A0-254A2CFC6577}.Release|x86.ActiveCfg = Release|x86
- {3EF3A5A0-2365-41FD-97A0-254A2CFC6577}.Release|x86.Build.0 = Release|x86
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
-EndGlobal
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tester", "Tester\Tester.csproj", "{EBE443EE-F4C7-49E6-AC22-959CA62FAA05}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FastColoredTextBox", "FastColoredTextBox\FastColoredTextBox.csproj", "{6DD14A85-CCFC-4774-BD26-0F5772512319}"
+EndProject
+Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "TesterVB", "TesterVB\TesterVB.vbproj", "{3EF3A5A0-2365-41FD-97A0-254A2CFC6577}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|Mixed Platforms = Debug|Mixed Platforms
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|Mixed Platforms = Release|Mixed Platforms
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {EBE443EE-F4C7-49E6-AC22-959CA62FAA05}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+ {EBE443EE-F4C7-49E6-AC22-959CA62FAA05}.Debug|Mixed Platforms.Build.0 = Debug|x86
+ {EBE443EE-F4C7-49E6-AC22-959CA62FAA05}.Debug|x86.ActiveCfg = Debug|x86
+ {EBE443EE-F4C7-49E6-AC22-959CA62FAA05}.Debug|x86.Build.0 = Debug|x86
+ {EBE443EE-F4C7-49E6-AC22-959CA62FAA05}.Release|Any CPU.ActiveCfg = Release|x86
+ {EBE443EE-F4C7-49E6-AC22-959CA62FAA05}.Release|Mixed Platforms.ActiveCfg = Release|x86
+ {EBE443EE-F4C7-49E6-AC22-959CA62FAA05}.Release|Mixed Platforms.Build.0 = Release|x86
+ {EBE443EE-F4C7-49E6-AC22-959CA62FAA05}.Release|x86.ActiveCfg = Release|x86
+ {EBE443EE-F4C7-49E6-AC22-959CA62FAA05}.Release|x86.Build.0 = Release|x86
+ {EBE443EE-F4C7-49E6-AC22-959CA62FAA05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {EBE443EE-F4C7-49E6-AC22-959CA62FAA05}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6DD14A85-CCFC-4774-BD26-0F5772512319}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6DD14A85-CCFC-4774-BD26-0F5772512319}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6DD14A85-CCFC-4774-BD26-0F5772512319}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {6DD14A85-CCFC-4774-BD26-0F5772512319}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {6DD14A85-CCFC-4774-BD26-0F5772512319}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {6DD14A85-CCFC-4774-BD26-0F5772512319}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6DD14A85-CCFC-4774-BD26-0F5772512319}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6DD14A85-CCFC-4774-BD26-0F5772512319}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {6DD14A85-CCFC-4774-BD26-0F5772512319}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {6DD14A85-CCFC-4774-BD26-0F5772512319}.Release|x86.ActiveCfg = Release|Any CPU
+ {3EF3A5A0-2365-41FD-97A0-254A2CFC6577}.Debug|Any CPU.ActiveCfg = Debug|x86
+ {3EF3A5A0-2365-41FD-97A0-254A2CFC6577}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+ {3EF3A5A0-2365-41FD-97A0-254A2CFC6577}.Debug|Mixed Platforms.Build.0 = Debug|x86
+ {3EF3A5A0-2365-41FD-97A0-254A2CFC6577}.Debug|x86.ActiveCfg = Debug|x86
+ {3EF3A5A0-2365-41FD-97A0-254A2CFC6577}.Debug|x86.Build.0 = Debug|x86
+ {3EF3A5A0-2365-41FD-97A0-254A2CFC6577}.Release|Any CPU.ActiveCfg = Release|x86
+ {3EF3A5A0-2365-41FD-97A0-254A2CFC6577}.Release|Mixed Platforms.ActiveCfg = Release|x86
+ {3EF3A5A0-2365-41FD-97A0-254A2CFC6577}.Release|Mixed Platforms.Build.0 = Release|x86
+ {3EF3A5A0-2365-41FD-97A0-254A2CFC6577}.Release|x86.ActiveCfg = Release|x86
+ {3EF3A5A0-2365-41FD-97A0-254A2CFC6577}.Release|x86.Build.0 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/FastColoredTextBox/AutocompleteItem.cs b/FastColoredTextBox/AutocompleteItem.cs
index 59feec4d..ce9c5a08 100644
--- a/FastColoredTextBox/AutocompleteItem.cs
+++ b/FastColoredTextBox/AutocompleteItem.cs
@@ -1,266 +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;
- }
- }
-}
+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/FastColoredTextBox/AutocompleteListView.cs b/FastColoredTextBox/AutocompleteListView.cs
new file mode 100644
index 00000000..65c62d44
--- /dev/null
+++ b/FastColoredTextBox/AutocompleteListView.cs
@@ -0,0 +1,649 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Text.RegularExpressions;
+using System.Windows.Forms;
+
+namespace FastColoredTextBoxNS
+{
+ [System.ComponentModel.ToolboxItem(false)]
+ public class AutocompleteListView : UserControl, IDisposable
+ {
+ 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; }
+ internal Size MaxToolTipSize { get; set; }
+ internal bool AlwaysShowTooltip
+ {
+ get { return toolTip.ShowAlways; }
+ set { toolTip.ShowAlways = value; }
+ }
+
+ 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;
+ toolTip.Popup += ToolTip_Popup;
+
+ 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 += delegate { SafetyClose(); };
+ form.ResizeBegin += delegate { SafetyClose(); };
+ form.FormClosing += delegate { SafetyClose(); };
+ form.LostFocus += delegate { SafetyClose(); };
+ }
+
+ tb.LostFocus += (o, e) =>
+ {
+ if (Menu != null && !Menu.IsDisposed)
+ if (!Menu.Focused)
+ SafetyClose();
+ };
+
+ tb.Scroll += delegate { SafetyClose(); };
+
+ this.VisibleChanged += (o, e) =>
+ {
+ if (this.Visible)
+ DoSelectedVisible();
+ };
+
+ }
+
+ protected override void OnParentChanged(EventArgs e)
+ {
+ if (Menu != null)
+ {
+ Menu.SizeChanged += MenuOnSizeChanged;
+ }
+
+ }
+
+ private void MenuOnSizeChanged(object? sender, EventArgs e)
+ {
+ Range fragment = tb.Selection.GetFragment(Menu.SearchPattern);
+ string text = fragment.Text;
+ //calc screen point for popup menu
+ Point point = tb.PlaceToPoint(fragment.End);
+
+ Menu.Location = tb.PointToScreen(FixIfPointIsCloseToTheBottom(point));
+ }
+
+ private void ToolTip_Popup(object sender, PopupEventArgs e)
+ {
+ if (MaxToolTipSize.Height > 0 && MaxToolTipSize.Width > 0)
+ e.ToolTipSize = MaxToolTipSize;
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (toolTip != null)
+ {
+ toolTip.Popup -= ToolTip_Popup;
+ toolTip.Dispose();
+ }
+ if (tb != null)
+ {
+ tb.KeyDown -= tb_KeyDown;
+ tb.KeyPressed -= tb_KeyPressed;
+ tb.SelectionChanged -= tb_SelectionChanged;
+ }
+
+ if (timer != null)
+ {
+ timer.Stop();
+ timer.Tick -= timer_Tick;
+ timer.Dispose();
+ }
+
+ if (Menu != null)
+ {
+ Menu.SizeChanged -= MenuOnSizeChanged;
+ }
+
+ base.Dispose(disposing);
+ }
+
+ void SafetyClose()
+ {
+ if (Menu != null && !Menu.IsDisposed)
+ Menu.Close();
+ }
+
+ 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();
+ }
+ }
+
+ if (Count == 1 && forced)
+ {
+ OnSelecting();
+ Menu.Close();
+ return;
+ }
+
+ //show popup menu
+ if (Count > 0)
+ {
+ if (!Menu.Visible)
+ {
+ CancelEventArgs args = new CancelEventArgs();
+ Menu.OnOpening(args);
+ if (!args.Cancel)
+ {
+ Menu.CalcSize();
+ Trace.WriteLine($"Original point: {point}");
+ var fixedPoint = FixIfPointIsCloseToTheBottom(point);
+ Trace.WriteLine($"Fixed point before on show: {fixedPoint}");
+ Menu.Show(tb, fixedPoint);
+ }
+ }
+
+ Menu.Location = tb.PointToScreen(FixIfPointIsCloseToTheBottom(point));
+ Trace.WriteLine($"Menu location: {Menu.Location}");
+ DoSelectedVisible();
+ Invalidate();
+ }
+ else
+ Menu.Close();
+ }
+
+ private Point FixIfPointIsCloseToTheBottom(Point point)
+ {
+ var tbCoordinates = tb.PointToScreen(new Point(0, 0)); // checking left upper corner of the TB
+ var requestedPoint = tb.PointToScreen(point);
+ var currentScreen = Screen.FromControl(tb);
+ if (requestedPoint.Y > currentScreen.Bounds.Height / 2)
+ {
+ Trace.WriteLine("Point FIXED.");
+ // in case if current position is higher than half of the screen - show menu over the caret
+ Trace.WriteLine($"tbCoordinates.Y: {tbCoordinates.Y} Size.Height:{Size.Height} - ItemHeight: {ItemHeight} + point.Y:{point.Y}");
+ return new Point(point.X, // get the same X
+ tb.PointToClient(new Point(point.X,
+ tbCoordinates.Y - Menu.Height - ItemHeight + point.Y)).Y); // calc current Y Position
+ }
+
+ Trace.WriteLine("Point NOT fixed.");
+ return point;
+ }
+
+ 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(true);
+ 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 SolidBrush(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;
+ }
+
+ if (this.Parent != null)
+ {
+ IWin32Window window = this.Parent ?? this;
+ Point location;
+
+ if ((this.PointToScreen(this.Location).X + MaxToolTipSize.Width + 105) < Screen.FromControl(this.Parent).WorkingArea.Right)
+ location = new Point(Right + 5, 0);
+ else
+ location = new Point(Left - 105 - MaximumSize.Width, 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;
+ }
+ }
+}
\ No newline at end of file
diff --git a/FastColoredTextBox/AutocompleteMenu.cs b/FastColoredTextBox/AutocompleteMenu.cs
index 829783ac..e4421c49 100644
--- a/FastColoredTextBox/AutocompleteMenu.cs
+++ b/FastColoredTextBox/AutocompleteMenu.cs
@@ -1,792 +1,227 @@
-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, IDisposable
- {
- 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; } }
- ///
- /// Sets the max tooltip window size
- ///
- public Size MaxTooltipSize { get { return listView.MaxToolTipSize; } set { listView.MaxToolTipSize = value; } }
- ///
- /// Tooltip will perm show and duration will be ignored
- ///
- public bool AlwaysShowTooltip { get { return listView.AlwaysShowTooltip; } set { listView.AlwaysShowTooltip = 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; }
- }
-
- protected override void Dispose(bool disposing)
- {
- base.Dispose(disposing);
- if (listView != null && !listView.IsDisposed)
- listView.Dispose();
- }
- }
-
- [System.ComponentModel.ToolboxItem(false)]
- public class AutocompleteListView : UserControl, IDisposable
- {
- 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; }
- internal Size MaxToolTipSize { get; set; }
- internal bool AlwaysShowTooltip
- {
- get { return toolTip.ShowAlways; }
- set { toolTip.ShowAlways = value; }
- }
-
- 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;
- toolTip.Popup += ToolTip_Popup;
-
- 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 += delegate { SafetyClose(); };
- form.ResizeBegin += delegate { SafetyClose(); };
- form.FormClosing += delegate { SafetyClose(); };
- form.LostFocus += delegate { SafetyClose(); };
- }
-
- tb.LostFocus += (o, e) =>
- {
- if (Menu != null && !Menu.IsDisposed)
- if (!Menu.Focused)
- SafetyClose();
- };
-
- tb.Scroll += delegate { SafetyClose(); };
-
- this.VisibleChanged += (o, e) =>
- {
- if (this.Visible)
- DoSelectedVisible();
- };
- }
-
- private void ToolTip_Popup(object sender, PopupEventArgs e)
- {
- if (MaxToolTipSize.Height > 0 && MaxToolTipSize.Width > 0)
- e.ToolTipSize = MaxToolTipSize;
- }
-
- protected override void Dispose(bool disposing)
- {
- if (toolTip != null)
- {
- toolTip.Popup -= ToolTip_Popup;
- toolTip.Dispose();
- }
- if (tb != null)
- {
- tb.KeyDown -= tb_KeyDown;
- tb.KeyPressed -= tb_KeyPressed;
- tb.SelectionChanged -= tb_SelectionChanged;
- }
-
- if (timer != null)
- {
- timer.Stop();
- timer.Tick -= timer_Tick;
- timer.Dispose();
- }
-
- base.Dispose(disposing);
- }
-
- void SafetyClose()
- {
- if (Menu != null && !Menu.IsDisposed)
- Menu.Close();
- }
-
- 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);
- }
-
- DoSelectedVisible();
- 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;
- }
-
- if (this.Parent != null)
- {
- IWin32Window window = this.Parent ?? this;
- Point location;
-
- if ((this.PointToScreen(this.Location).X + MaxToolTipSize.Width + 105) < Screen.FromControl(this.Parent).WorkingArea.Right)
- location = new Point(Right + 5, 0);
- else
- location = new Point(Left - 105 - MaximumSize.Width, 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; }
- }
-}
+using System;
+using System.Windows.Forms;
+using System.Drawing;
+using System.ComponentModel;
+using System.Diagnostics;
+
+namespace FastColoredTextBoxNS
+{
+ ///
+ /// Popup menu for autocomplete
+ ///
+ [Browsable(false)]
+ public class AutocompleteMenu : ToolStripDropDown, IDisposable
+ {
+ 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;
+
+ private event Action SizeChanged = () => { };
+ ///
+ /// 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; } }
+ ///
+ /// Sets the max tooltip window size
+ ///
+ public Size MaxTooltipSize { get { return listView.MaxToolTipSize; } set { listView.MaxToolTipSize = value; } }
+ ///
+ /// Tooltip will perm show and duration will be ignored
+ ///
+ public bool AlwaysShowTooltip { get { return listView.AlwaysShowTooltip; } set { listView.AlwaysShowTooltip = value; } }
+
+ private new Size Size
+ {
+ get => base.Size;
+ set
+ {
+ Trace.WriteLine($"Size changed from {base.Size} to {value}");
+ base.Size = value;
+ SizeChanged();
+ }
+ }
+
+ ///
+ /// 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; }
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ base.Dispose(disposing);
+ if (listView != null && !listView.IsDisposed)
+ listView.Dispose();
+ }
+ }
+
+ 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/FastColoredTextBox/Bookmarks.cs b/FastColoredTextBox/Bookmarks.cs
index ad220d98..491fc7f2 100644
--- a/FastColoredTextBox/Bookmarks.cs
+++ b/FastColoredTextBox/Bookmarks.cs
@@ -1,256 +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);
- }
- }
-}
+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/FastColoredTextBox/Char.cs b/FastColoredTextBox/Char.cs
index 9f848c97..eb2d3e65 100644
--- a/FastColoredTextBox/Char.cs
+++ b/FastColoredTextBox/Char.cs
@@ -1,26 +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;
- }
- }
-}
+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/FastColoredTextBox/CommandManager.cs b/FastColoredTextBox/CommandManager.cs
index ce1e1bf5..0aa72cb3 100644
--- a/FastColoredTextBox/CommandManager.cs
+++ b/FastColoredTextBox/CommandManager.cs
@@ -1,245 +1,245 @@
-using System.Collections.Generic;
-using System;
-
-namespace FastColoredTextBoxNS
-{
- public class CommandManager
- {
- public static int MaxHistoryLength = 200;
-
- LimitedStack history;
- Stack redoStack = new Stack();
- public TextSource TextSource{ get; private set; }
- public bool UndoRedoStackIsEnabled { get; set; }
-
- public event EventHandler RedoCompleted = delegate { };
-
- 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();
- }
-
- //call event
- RedoCompleted(this, EventArgs.Empty);
-
- //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();
- }
+using System.Collections.Generic;
+using System;
+
+namespace FastColoredTextBoxNS
+{
+ public class CommandManager
+ {
+ public static int MaxHistoryLength = 200;
+
+ LimitedStack history;
+ Stack redoStack = new Stack();
+ public TextSource TextSource{ get; private set; }
+ public bool UndoRedoStackIsEnabled { get; set; }
+
+ public event EventHandler RedoCompleted = delegate { };
+
+ 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();
+ }
+
+ //call event
+ RedoCompleted(this, EventArgs.Empty);
+
+ //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/FastColoredTextBox/Commands.cs b/FastColoredTextBox/Commands.cs
index c83ac962..de127f12 100644
--- a/FastColoredTextBox/Commands.cs
+++ b/FastColoredTextBox/Commands.cs
@@ -1,809 +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;
- }
- }
-}
+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/FastColoredTextBox/DocumentMap.cs b/FastColoredTextBox/DocumentMap.cs
index f3eb38a7..b801e0a3 100644
--- a/FastColoredTextBox/DocumentMap.cs
+++ b/FastColoredTextBox/DocumentMap.cs
@@ -1,250 +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);
- }
- }
-}
+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/FastColoredTextBox/EncodingDetector.cs b/FastColoredTextBox/EncodingDetector.cs
index 2dc202d0..6d85da9e 100644
--- a/FastColoredTextBox/EncodingDetector.cs
+++ b/FastColoredTextBox/EncodingDetector.cs
@@ -1,363 +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;
- }
- }
-}
+// 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/FastColoredTextBox/ExportToHTML.cs b/FastColoredTextBox/ExportToHTML.cs
index c2e07b9b..b6ebdfd5 100644
--- a/FastColoredTextBox/ExportToHTML.cs
+++ b/FastColoredTextBox/ExportToHTML.cs
@@ -1,222 +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";
+
+ ///
+ /// 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