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;
                    }
                }
            }
        }
        // -----------------------------------------------------------
        // Updating & Block managing
        // -----------------------------------------------------------

        private void UpdateTotalLineCount()
        {
            totalLineCount = TextUtilities.GetLineCount(Text);
        }