Example #1
0
        private void UpdateBlocks()
        {
            if (blocks.Count == 0)
            {
                return;
            }

            // While something is visible after last block...
            while (!blocks.Last().IsLast&& blocks.Last().Position.Y + blockHeight - VerticalOffset < ActualHeight)
            {
                int firstLineIndex = blocks.Last().LineEndIndex + 1;
                int lastLineIndex  = firstLineIndex + maxLineCountInBlock - 1;
                lastLineIndex = lastLineIndex <= totalLineCount - 1 ? lastLineIndex : totalLineCount - 1;

                int fisrCharIndex = blocks.Last().CharEndIndex + 1;
                int lastCharIndex = TextUtilities.GetLastCharIndexFromLineIndex(Text, lastLineIndex);                 // to be optimized (forward search)

                if (lastCharIndex <= fisrCharIndex)
                {
                    blocks.Last().IsLast = true;
                    return;
                }

                InnerTextBlock block = new InnerTextBlock(
                    fisrCharIndex,
                    lastCharIndex,
                    blocks.Last().LineEndIndex + 1,
                    lastLineIndex,
                    LineHeight);
                block.RawText     = block.GetSubString(Text);
                block.LineNumbers = GetFormattedLineNumbers(block.LineStartIndex, block.LineEndIndex);
                blocks.Add(block);
                FormatBlock(block, blocks.Count > 1 ? blocks[blocks.Count - 2] : null);
            }
        }
 /// <summary>
 /// Formats and Highlights the text of a block.
 /// </summary>
 private void FormatBlock(InnerTextBlock currentBlock, InnerTextBlock previousBlock)
 {
     currentBlock.FormattedText = GetFormattedText(currentBlock.RawText);
     Dispatcher.Invoke(() => {
         CodeEditorContent.Instance.Highlight(currentBlock.FormattedText,
                                              openBracketPos, closeBracketPos);
         currentBlock.Code = -1;
     });
 }
 /// <summary>
 /// Formats and Highlights the text of a block.
 /// </summary>
 private void FormatBlock(InnerTextBlock currentBlock, InnerTextBlock previousBlock)
 {
     currentBlock.FormattedText = GetFormattedText(currentBlock.RawText);
     if (CurrentHighlighter != null)
     {
         var previousCode = previousBlock?.Code ?? -1;
         currentBlock.Code = CurrentHighlighter.Highlight(currentBlock.FormattedText, previousCode);
     }
 }
Example #4
0
 /// <summary>
 /// Formats and Highlights the text of a block.
 /// </summary>
 private void FormatBlock(InnerTextBlock currentBlock, InnerTextBlock previousBlock)
 {
     currentBlock.FormattedText = this.GetFormattedText(currentBlock.RawText);
     ThreadPool.QueueUserWorkItem(p =>
     {
         int previousCode  = previousBlock != null ? previousBlock.Code : -1;
         currentBlock.Code = this.CurrentHighlighter.Highlight(currentBlock.FormattedText, previousCode);
     });
 }
Example #5
0
 /// <summary>
 /// Formats and Highlights the text of a block.
 /// </summary>
 private void FormatBlock(InnerTextBlock currentBlock)
 {
     currentBlock.FormattedText = GetFormattedText(currentBlock.RawText);
     Dispatcher.Invoke(() => {
         HiglightContent.Highlight(currentBlock.FormattedText,
                                   openBracketPos, closeBracketPos, BracketBrush);
         HiglightContent.HighlightErrors(currentBlock.FormattedText, Errors, blocks);
         currentBlock.Code = -1;
     });
 }
Example #6
0
 /// <summary>
 /// Formats and Highlights the text of a block.
 /// </summary>
 private void FormatBlock(InnerTextBlock currentBlock, DpiScale dpi)
 {
     currentBlock.FormattedText = GetFormattedText(currentBlock.RawText, dpi);
     if (CurrentHighlighter != null)
     {
         ThreadPool.QueueUserWorkItem(p =>
         {
             CurrentHighlighter.Highlight(currentBlock.FormattedText);
             currentBlock.Code = -1;
         });
     }
 }
Example #7
0
 // Formats and Highlights the text of a block.
 private void FormatTextBlock(InnerTextBlock currentBlock, InnerTextBlock previousBlock)
 {
     currentBlock.FormattedText = GetFormattedText(currentBlock.RawText);
     if (Highlighter != null)
     {
         ThreadPool.QueueUserWorkItem(p =>
         {
             blocksRunningCount++;
             Highlighter.Highlight(currentBlock.FormattedText);
             blocksRunningCount--;
         });
     }
 }
        private void DrawBlocks()
        {
            if (!IsLoaded || renderCanvas == null || lineNumbersCanvas == null)
            {
                return;
            }
            var dc  = renderCanvas.GetContext();
            var dc2 = lineNumbersCanvas.GetContext();

            for (int i = 0; i < blocks.Count; i++)
            {
                InnerTextBlock block    = blocks[i];
                Point          blockPos = block.Position;
                double         top      = blockPos.Y - VerticalOffset;
                double         bottom   = top + blockHeight;
                if (top < ActualHeight && bottom > 0)
                {
                    try
                    {
                        if (TextToHighlight != null)
                        {
                            foreach (Match m in TextToHighlight.Matches(block.FormattedText.Text))
                            {
                                Geometry highlight = block.FormattedText.BuildHighlightGeometry(
                                    new Point(2 - HorizontalOffset, block.Position.Y - this.VerticalOffset),
                                    m.Index, m.Length);
                                if (highlight != null)
                                {
                                    Brush brush = new SolidColorBrush(Brushes.LightCyan.Color);
                                    brush.Opacity = 0.5;
                                    dc.DrawGeometry(brush, null, highlight);
                                }
                            }
                        }
                        dc.DrawText(block.FormattedText, new Point(2 -
                                                                   HorizontalOffset, block.Position.Y - VerticalOffset));
                        lineNumbersCanvas.Width = GetFormattedTextWidth(string.Format("{0:0000}",
                                                                                      totalLineCount)) + 5;
                        dc2.DrawText(block.LineNumbers, new Point(lineNumbersCanvas.ActualWidth, 1 +
                                                                  block.Position.Y - VerticalOffset));
                    }
                    catch
                    {
                        //Strange exception with large Copy
                    }
                }
            }
            dc.Close();
            dc2.Close();
        }
Example #9
0
        // -----------------------------------------------------------
        // Rendering
        // -----------------------------------------------------------

        private void DrawBlocks()
        {
            if (!this.IsLoaded || this.renderCanvas == null || this.lineNumbersCanvas == null)
            {
                return;
            }

            this.CurrentHighlighter = HighlighterManager.Instance.Highlighters[this.SyntaxLanguage];

            var dc  = this.renderCanvas.GetContext();
            var dc2 = this.lineNumbersCanvas.GetContext();

            for (int i = 0; i < this.blocks.Count; i++)
            {
                InnerTextBlock block    = this.blocks[i];
                Point          blockPos = block.Position;
                double         top      = blockPos.Y - this.VerticalOffset;
                double         bottom   = top + this.blockHeight;
                if (top < this.ActualHeight && bottom > 0)
                {
                    try
                    {
                        dc.DrawText(block.FormattedText, new Point(2 - this.HorizontalOffset, block.Position.Y - this.VerticalOffset));
                        if (this.IsLineNumbersMarginVisible)
                        {
                            this.lineNumbersCanvas.Width = this.GetFormattedTextWidth(string.Format("{0:0000}", this.totalLineCount)) + 5;
                            dc2.DrawText(block.LineNumbers, new Point(this.lineNumbersCanvas.ActualWidth, 1 + block.Position.Y - this.VerticalOffset));
                        }
                    }
                    catch
                    {
                        // Don't know why this exception is raised sometimes.
                        // Reproduce steps:
                        // - Sets a valid syntax highlighter on the box.
                        // - Copy a large chunk of code in the clipboard.
                        // - Paste it using ctrl+v and keep these buttons pressed.
                    }
                }
            }

            dc.Close();
            dc2.Close();
        }
Example #10
0
        // -----------------------------------------------------------
        // Rendering
        // -----------------------------------------------------------

        private void DrawBlocks()
        {
            Debug.WriteLine("DrawBlocks: IsLoaded={0}, renderCanvas={1}, lineNumbersCanvas={2}",
                            new Object[] { IsLoaded, renderCanvas == null, lineNumbersCanvas == null });

            if (renderCanvas == null || lineNumbersCanvas == null)
            {
                return;
            }

            var dc  = renderCanvas.GetContext();
            var dc2 = lineNumbersCanvas.GetContext();

            for (int i = 0; i < blocks.Count; i++)
            {
                InnerTextBlock block    = blocks[i];
                Point          blockPos = block.Position;
                double         top      = blockPos.Y - VerticalOffset;
                double         bottom   = top + blockHeight;
                if (top < ActualHeight && bottom > 0)
                {
                    try {
                        dc.DrawText(block.FormattedText, new Point(2 - HorizontalOffset, block.Position.Y - VerticalOffset));
                        if (IsLineNumbersMarginVisible)
                        {
                            lineNumbersCanvas.Width = GetFormattedTextWidth(string.Format("{0:0000}", totalLineCount)) + 5;
                            dc2.DrawText(block.LineNumbers, new Point(lineNumbersCanvas.ActualWidth, 1 + block.Position.Y - VerticalOffset));
                        }
                    } catch {
                        // Don't know why this exception is raised sometimes.
                        // Reproduce steps:
                        // - Sets a valid syntax highlighter on the box.
                        // - Copy a large chunk of code in the clipboard.
                        // - Paste it using ctrl+v and keep these buttons pressed.
                    }
                }
            }
            dc.Close();
            dc2.Close();
        }
        // -----------------------------------------------------------
        // Updating & Block managing
        // -----------------------------------------------------------

        private void UpdateBlocks()
        {
            if (blocks.Count == 0)
                return;

            // While something is visible after last block...
            while (!blocks.Last().IsLast && blocks.Last().Position.Y + blockHeight - VerticalOffset < ActualHeight)
            {
                int firstLineIndex = blocks.Last().LineEndIndex + 1;
                int lastLineIndex = firstLineIndex + maxLineCountInBlock - 1;
                lastLineIndex = lastLineIndex <= totalLineCount - 1 ? lastLineIndex : totalLineCount - 1;

                int fisrCharIndex = blocks.Last().CharEndIndex + 1;
                int lastCharIndex = TextUtilities.GetLastCharIndexFromLineIndex(Text, lastLineIndex); // to be optimized (forward search)

                if (lastCharIndex <= fisrCharIndex)
                {
                    blocks.Last().IsLast = true;
                    return;
                }

                InnerTextBlock block = new InnerTextBlock(
                    fisrCharIndex,
                    lastCharIndex,
                    blocks.Last().LineEndIndex + 1,
                    lastLineIndex,
                    LineHeight);

                block.RawText = block.GetSubString(Text);
                block.LineNumbers = GetFormattedLineNumbers(block.LineStartIndex, block.LineEndIndex);
                blocks.Add(block);
                FormatBlock(block);
            }
        }
Example #12
0
		/// <summary>
		/// Formats and Highlights the text of a block.
		/// </summary>
		private void FormatBlock(InnerTextBlock currentBlock, InnerTextBlock previousBlock) {
			currentBlock.FormattedText = GetFormattedText(currentBlock.RawText);
			if (CurrentHighlighter != null) {
				ThreadPool.QueueUserWorkItem(p => {
					int previousCode = previousBlock != null ? previousBlock.Code : -1;
					currentBlock.Code = CurrentHighlighter.Highlight(currentBlock.FormattedText, previousCode);
				    Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(InvalidateVisual));
				});
			}
		}
Example #13
0
        private void InvalidateBlocks(int changeOffset)
        {
            InnerTextBlock blockChanged = null;

            for (int i = 0; i < blocks.Count; i++)
            {
                if (blocks[i].CharStartIndex <= changeOffset && changeOffset <= blocks[i].CharEndIndex + 1)
                {
                    blockChanged = blocks[i];
                    break;
                }
            }

            if (blockChanged == null && changeOffset > 0)
            {
                blockChanged = blocks.Last();
            }

            int fvline = blockChanged != null ? blockChanged.LineStartIndex : 0;
            int lvline = GetIndexOfLastVisibleLine();
            int fvchar = blockChanged != null ? blockChanged.CharStartIndex : 0;
            int lvchar = TextUtilities.GetLastCharIndexFromLineIndex(Text, lvline);

            if (blockChanged != null)
            {
                blocks.RemoveRange(blocks.IndexOf(blockChanged), blocks.Count - blocks.IndexOf(blockChanged));
            }

            int localLineCount = 1;
            int charStart      = fvchar;
            int lineStart      = fvline;

            for (int i = fvchar; i < Text.Length; i++)
            {
                if (Text[i] == '\n')
                {
                    localLineCount += 1;
                }
                if (i == Text.Length - 1)
                {
                    string         blockText = Text.Substring(charStart);
                    InnerTextBlock block     = new InnerTextBlock(
                        charStart,
                        i, lineStart,
                        lineStart + TextUtilities.GetLineCount(blockText) - 1,
                        LineHeight);
                    block.RawText     = block.GetSubString(Text);
                    block.LineNumbers = GetFormattedLineNumbers(block.LineStartIndex, block.LineEndIndex);
                    block.IsLast      = true;

                    foreach (InnerTextBlock b in blocks)
                    {
                        if (b.LineStartIndex == block.LineStartIndex)
                        {
                            throw new Exception();
                        }
                    }

                    blocks.Add(block);
                    FormatBlock(block, blocks.Count > 1 ? blocks[blocks.Count - 2] : null);
                    break;
                }
                if (localLineCount > maxLineCountInBlock)
                {
                    InnerTextBlock block = new InnerTextBlock(
                        charStart,
                        i,
                        lineStart,
                        lineStart + maxLineCountInBlock - 1,
                        LineHeight);
                    block.RawText     = block.GetSubString(Text);
                    block.LineNumbers = GetFormattedLineNumbers(block.LineStartIndex, block.LineEndIndex);

                    foreach (InnerTextBlock b in blocks)
                    {
                        if (b.LineStartIndex == block.LineStartIndex)
                        {
                            throw new Exception();
                        }
                    }

                    blocks.Add(block);
                    FormatBlock(block, blocks.Count > 1 ? blocks[blocks.Count - 2] : null);

                    charStart      = i + 1;
                    lineStart     += maxLineCountInBlock;
                    localLineCount = 1;

                    if (i > lvchar)
                    {
                        break;
                    }
                }
            }
        }
Example #14
0
 public CodeEditor()
 {
     InitializeComponent();
     HiglightContent     = new CodeEditorContent();
     Errors              = new List <SyntaxError>();
     MaxLineCountInBlock = 100;
     LineHeight          = FontSize * 1.3;
     TabSize             = 4;
     totalLineCount      = 1;
     blocks              = new List <InnerTextBlock>();
     ToolTip             = new ToolTip
     {
         IsOpen = false
     };
     Loaded += (s, e) => {
         ApplyTemplate();
         Text                        = Text.Replace("\t", new string(' ', TabSize));
         renderCanvas                = (DrawingControl)Template.FindName("PART_RenderCanvas", this);
         lineNumbersCanvas           = (DrawingControl)Template.FindName("PART_LineNumbersCanvas", this);
         scrollViewer                = (ScrollViewer)Template.FindName("PART_ContentHost", this);
         lineNumbersCanvas.Width     = GetFormattedTextWidth($"{totalLineCount:0000}") + 5;
         scrollViewer.ScrollChanged += OnScrollChanged;
         InvalidateBlocks(0);
         InvalidateVisual();
     };
     SizeChanged += (s, e) => {
         if (e.HeightChanged == false)
         {
             return;
         }
         UpdateBlocks();
         InvalidateVisual();
     };
     TextChanged += (s, e) => {
         UpdateTotalLineCount();
         InvalidateBlocks(e.Changes.First().Offset);
         InvalidateVisual();
         //If navigator exists, update its visuals
         if (navigator == null)
         {
             return;
         }
         navigator.LinkedScrollViewerHeight = scrollViewer.ViewportHeight;
         navigator.UpdateText(GetFormattedText(Text),
                              new Point(2 - HorizontalOffset, VerticalOffset),
                              scrollViewer.VerticalOffset);
     };
     PreviewTextInput += (s, e) => {
         if (e.Text.Contains("{"))
         {
             WaitingForClosingBracket = true;
         }
         if (e.Text.Contains("}"))
         {
             WaitingForClosingBracket = false;
         }
     };
     PreviewKeyDown          += CodeEditor_OnPreviewKeyDown;
     SelectionChanged        += CodeEditor_SelectionChanged;
     PreviewMouseDoubleClick += CodeEditor_MouseDoubleClick;
     MouseMove += (s, e) =>
     {
         ToolTip localtool = ToolTip as ToolTip;
         if (localtool == null)
         {
             return;
         }
         Point          mousePos = Mouse.GetPosition(renderCanvas);
         InnerTextBlock block    = blocks.FirstOrDefault(b =>
                                                         new Rect(b.Position, new Size(b.FormattedText.Width,
                                                                                       b.FormattedText.Height)).Contains(mousePos));
         if (block == null)
         {
             localtool.IsOpen = false;
             return;
         }
         SyntaxError error = Errors.FirstOrDefault(ev =>
         {
             int Line   = ev.Line ?? -1;
             int Column = ev.Column ?? -1;
             int TagPos = CodeHelper.getStartCharOfPos(Text, Line, Column);
             return(TagPos >= block.CharStartIndex && TagPos <= block.CharEndIndex);
         });
         if (error == null)
         {
             localtool.IsOpen = false;
         }
         else
         {
             localtool.HorizontalOffset = e.GetPosition(this).X;
             localtool.VerticalOffset   = e.GetPosition(this).Y;
             localtool.IsOpen           = true;
             localtool.Content          = error.InnerMessage;
         }
     };
 }
 /// <summary>
 /// Formats and Highlights the text of a block.
 /// </summary>
 private void FormatBlock(InnerTextBlock currentBlock, InnerTextBlock previousBlock)
 {
     currentBlock.FormattedText = GetFormattedText(currentBlock.RawText);
     if (CurrentHighlighter != null)
     {
         ThreadPool.QueueUserWorkItem(p =>
         {
             int previousCode = previousBlock != null ? previousBlock.Code : -1;
             currentBlock.Code = CurrentHighlighter.Highlight(currentBlock.FormattedText, previousCode);
         });
     }
 }
Example #16
0
        private void InvalidateBlocks(int changeOffset)
        {
            InnerTextBlock blockChanged = blocks.FirstOrDefault(t => t.CharStartIndex <=
                                                                changeOffset && changeOffset <= t.CharEndIndex + 1);

            if (blockChanged == null && changeOffset > 0)
            {
                blockChanged = blocks.Last();
            }
            int fvline = blockChanged?.LineStartIndex ?? 0;
            int lvline = GetIndexOfLastVisibleLine();
            int fvchar = blockChanged?.CharStartIndex ?? 0;
            int lvchar = CodeHelper.GetLastCharIndexFromLineIndex(Text, lvline);

            if (blockChanged != null)
            {
                blocks.RemoveRange(blocks.IndexOf(blockChanged), blocks.Count -
                                   blocks.IndexOf(blockChanged));
            }
            int localLineCount = 1;
            int charStart      = fvchar;
            int lineStart      = fvline;

            for (int i = fvchar; i < Text.Length; i++)
            {
                if (Text[i] == '\n')
                {
                    localLineCount += 1;
                }
                if (i == Text.Length - 1)
                {
                    string         blockText = Text.Substring(charStart);
                    InnerTextBlock block     = new InnerTextBlock(
                        charStart,
                        i, lineStart,
                        lineStart + CodeHelper.GetLineCount(blockText) - 1,
                        LineHeight);
                    block.RawText     = block.GetSubString(Text);
                    block.LineNumbers = GetFormattedLineNumbers(block.LineStartIndex,
                                                                block.LineEndIndex);
                    block.IsLast = true;
                    if (blocks.Any(b => b.LineStartIndex == block.LineStartIndex))
                    {
                        throw new Exception();
                    }
                    blocks.Add(block);
                    FormatBlock(block);
                    break;
                }
                if (localLineCount <= maxLineCountInBlock)
                {
                    continue;
                }
                {
                    InnerTextBlock block = new InnerTextBlock(
                        charStart,
                        i,
                        lineStart,
                        lineStart + maxLineCountInBlock - 1,
                        LineHeight);
                    block.RawText     = block.GetSubString(Text);
                    block.LineNumbers = GetFormattedLineNumbers(block.LineStartIndex, block.LineEndIndex);
                    if (blocks.Any(b => b.LineStartIndex == block.LineStartIndex))
                    {
                        throw new Exception();
                    }
                    blocks.Add(block);
                    FormatBlock(block);
                    charStart      = i + 1;
                    lineStart     += maxLineCountInBlock;
                    localLineCount = 1;
                    if (i > lvchar)
                    {
                        break;
                    }
                }
            }
        }
        private void InvalidateBlocks(int changeOffset)
        {
            InnerTextBlock blockChanged = blocks.FirstOrDefault(b=>b.CharStartIndex <= changeOffset && changeOffset <= b.CharEndIndex + 1);

            if (blockChanged == null && changeOffset > 0)
                blockChanged = blocks.Last();

            int fvline = blockChanged != null ? blockChanged.LineStartIndex : 0;
            int lvline = GetIndexOfLastVisibleLine();
            int fvchar = blockChanged != null ? blockChanged.CharStartIndex : 0;
            int lvchar = TextUtilities.GetLastCharIndexFromLineIndex(Text, lvline);

            if (blockChanged != null)
                blocks.RemoveRange(blocks.IndexOf(blockChanged), blocks.Count - blocks.IndexOf(blockChanged));

            int localLineCount = 1;
            int charStart = fvchar;
            int lineStart = fvline;
            for (int i = fvchar; i < Text.Length; i++)
            {
                if (Text[i] == '\n')
                {
                    localLineCount += 1;
                }
                if (i == Text.Length - 1)
                {
                    string blockText = Text.Substring(charStart);
                    InnerTextBlock block = new InnerTextBlock(
                        charStart,
                        i, lineStart,
                        lineStart + TextUtilities.GetLineCount(blockText) - 1,
                        LineHeight);
                    block.RawText = block.GetSubString(Text);
                    block.LineNumbers = GetFormattedLineNumbers(block.LineStartIndex, block.LineEndIndex);
                    block.IsLast = true;

                    foreach (InnerTextBlock b in blocks)
                        if (b.LineStartIndex == block.LineStartIndex)
                            throw new Exception();

                    blocks.Add(block);
                    FormatBlock(block);
                    break;
                }
                if (localLineCount > maxLineCountInBlock)
                {
                    InnerTextBlock block = new InnerTextBlock(
                        charStart,
                        i,
                        lineStart,
                        lineStart + maxLineCountInBlock - 1,
                        LineHeight);
                    block.RawText = block.GetSubString(Text);
                    block.LineNumbers = GetFormattedLineNumbers(block.LineStartIndex, block.LineEndIndex);

                    foreach (InnerTextBlock b in blocks)
                        if (b.LineStartIndex == block.LineStartIndex)
                            throw new Exception();

                    blocks.Add(block);
                    FormatBlock(block);

                    charStart = i + 1;
                    lineStart += maxLineCountInBlock;
                    localLineCount = 1;

                    if (i > lvchar)
                        break;
                }
            }
        }
 /// <summary>
 /// Formats and Highlights the text of a block.
 /// </summary>
 private void FormatBlock(InnerTextBlock currentBlock)
 {
     currentBlock.FormattedText = GetFormattedText(currentBlock.RawText);
     if (CurrentHighlighter != null)
     {
         ThreadPool.QueueUserWorkItem(p =>
         {
             CurrentHighlighter.Highlight(currentBlock.FormattedText);
             currentBlock.Code = -1;
         });
     }
 }
        private void InvalidateBlocks(int changeOffset)
        {
            InnerTextBlock blockChanged = null;

            for (var i = 0; i < _blocks.Count; i++)
            {
                if (_blocks[i].CharStartIndex <= changeOffset && changeOffset <= _blocks[i].CharEndIndex + 1)
                {
                    blockChanged = _blocks[i];
                    break;
                }
            }

            if (blockChanged == null && changeOffset > 0)
            {
                blockChanged = _blocks.Last();
            }

            var fvline = blockChanged?.LineStartIndex ?? 0;
            var lvline = GetIndexOfLastVisibleLine();
            var fvchar = blockChanged?.CharStartIndex ?? 0;
            var lvchar = Text.GetLastCharIndexFromLineIndex(lvline);

            if (blockChanged != null)
            {
                _blocks.RemoveRange(_blocks.IndexOf(blockChanged), _blocks.Count - _blocks.IndexOf(blockChanged));
            }

            var localLineCount = 1;
            var charStart      = fvchar;
            var lineStart      = fvline;

            for (var i = fvchar; i < Text.Length; i++)
            {
                if (Text[i] == '\n')
                {
                    localLineCount += 1;
                }
                if (i == Text.Length - 1)
                {
                    var blockText = Text.Substring(charStart);
                    var block     = new InnerTextBlock(
                        charStart,
                        i, lineStart,
                        lineStart + blockText.GetLineCount() - 1,
                        LineHeight);
                    block.RawText     = block.GetSubString(Text);
                    block.LineNumbers = GetFormattedLineNumbers(block.LineStartIndex, block.LineEndIndex);
                    block.IsLast      = true;

                    if (_blocks.Any(b => b.LineStartIndex == block.LineStartIndex))
                    {
                        throw new Exception();
                    }

                    _blocks.Add(block);
                    FormatBlock(block, _blocks.Count > 1 ? _blocks[_blocks.Count - 2] : null);
                    break;
                }
                if (localLineCount > _maxLineCountInBlock)
                {
                    var block = new InnerTextBlock(
                        charStart,
                        i,
                        lineStart,
                        lineStart + _maxLineCountInBlock - 1,
                        LineHeight);
                    block.RawText     = block.GetSubString(Text);
                    block.LineNumbers = GetFormattedLineNumbers(block.LineStartIndex, block.LineEndIndex);

                    if (_blocks.Any(b => b.LineStartIndex == block.LineStartIndex))
                    {
                        throw new Exception();
                    }

                    _blocks.Add(block);
                    FormatBlock(block, _blocks.Count > 1 ? _blocks[_blocks.Count - 2] : null);

                    charStart      = i + 1;
                    lineStart     += _maxLineCountInBlock;
                    localLineCount = 1;

                    if (i > lvchar)
                    {
                        break;
                    }
                }
            }
        }