private void updateBlocks()
        {
            if (_blocks.Count == 0)
            {
                return;
            }

            // While something is visible after last block...
            while (!_blocks.Last().IsLast&& _blocks.Last().Position.Y + _blockHeight - this.TextBox1.VerticalOffset < ActualHeight)
            {
                int firstLineIndex = _blocks.Last().LineEndIndex + 1;
                int lastLineIndex  = firstLineIndex + _maxLineCountInBlock - 1;
                lastLineIndex = lastLineIndex <= _totalLineCount - 1 ? lastLineIndex : _totalLineCount - 1;

                int charStart     = _blocks.Last().CharEndIndex + 1;
                int lastCharIndex = TextUtilities.GetLastCharIndexFromLineIndex(this.TextBox1.Text, lastLineIndex); // to be optimized (forward search)

                if (lastCharIndex <= charStart)
                {
                    _blocks.Last().IsLast = true;
                    return;
                }

                var block = new InnerTextBlock(
                    charStart,
                    lastCharIndex,
                    _blocks.Last().LineEndIndex + 1,
                    lastLineIndex,
                    LineHeight);
                block.RawText     = block.GetSubString(this.TextBox1.Text);
                block.LineNumbers = getFormattedLineNumbers(block.LineStartIndex, block.LineEndIndex);
                _blocks.Add(block);
                formatBlock(block, _blocks.Count > 1 ? _blocks[_blocks.Count - 2] : null);
            }
        }
        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(this.TextBox1.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 < this.TextBox1.Text.Length; i++)
            {
                if (this.TextBox1.Text[i] == '\n')
                {
                    localLineCount += 1;
                }
                if (i == this.TextBox1.Text.Length - 1)
                {
                    string blockText = this.TextBox1.Text.Substring(charStart);
                    var    block     = new InnerTextBlock(
                        charStart,
                        i, lineStart,
                        lineStart + TextUtilities.GetLineCount(blockText) - 1,
                        LineHeight);
                    block.RawText     = block.GetSubString(this.TextBox1.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)
                {
                    var block = new InnerTextBlock(
                        charStart,
                        i,
                        lineStart,
                        lineStart + _maxLineCountInBlock - 1,
                        LineHeight);
                    block.RawText     = block.GetSubString(this.TextBox1.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;
                    }
                }
            }
        }