예제 #1
0
        /// <summary>
        /// Offset of the first char of this line in the document
        /// </summary>
        public int FindStartOffsetOfLine(ITextLine line)
        {
            ReadOnlyTextLine roTextLine = line as ReadOnlyTextLine;

            if (roTextLine != null)
            {
                return(roTextLine.StartOffset);
            }
            else
            {
                return(-1);
            }
        }
예제 #2
0
        /// <summary>
        /// The first line has the index 0
        /// </summary>
        public int FindIndexOfLine(ITextLine line)
        {
            ReadOnlyTextLine roTextLine = line as ReadOnlyTextLine;

            if (roTextLine != null)
            {
                return(roTextLine.LineIndex);
            }
            else
            {
                return(-1);
            }
        }
예제 #3
0
        /// <summary>
        /// Gets the line containing the character at a specific offset in the document
        /// (first char at index 0 at the beginning of document)
        /// </summary>
        public ITextLine GetLineByOffset(int offset, out int indexOfCharInLine)
        {
            if (offset < 0 || offset >= charsCount)
            {
                throw new InvalidOperationException("offset must be a number between 0 and " + charsCount);
            }

            // Initialize binary search bounds
            int lineIndexStart = 0;
            int lineIndexEnd   = lines.Count - 1;

            // Optimization : fast path for fixed length lines of 80 characters
            int lineIndexMid = offset / 80;

            if (lineIndexMid >= lines.Count)
            {
                lineIndexMid = lineIndexStart + (lineIndexEnd - lineIndexStart) / 2;
            }

            // Execute binary search
            ReadOnlyTextLine line = null;

            while (lineIndexEnd > lineIndexStart)
            {
                line = lines[lineIndexMid];
                if (offset >= line.StartOffset)
                {
                    if (offset < (line.StartOffset + line.Length))
                    {
                        indexOfCharInLine = offset - line.StartOffset;
                        return(line);
                    }
                    else
                    {
                        lineIndexStart = lineIndexMid + 1;
                    }
                }
                else if (offset < line.StartOffset)
                {
                    lineIndexEnd = lineIndexMid - 1;
                }
                lineIndexMid = lineIndexStart + (lineIndexEnd - lineIndexStart) / 2;
            }

            // Line found
            line = lines[lineIndexStart];
            indexOfCharInLine = offset - line.StartOffset;
            return(line);
        }
예제 #4
0
        /// <summary>
        /// Part of the text between start offset and end offset (included),
        /// (first char at index 0 at the beginning of document)
        /// </summary>
        public string TextSegment(int startOffset, int endOffset)
        {
            if (startOffset < 0 || startOffset >= charsCount)
            {
                throw new InvalidOperationException("startOffset must be a number between 0 and " + charsCount);
            }
            if (endOffset < 0 || endOffset >= charsCount)
            {
                throw new InvalidOperationException("endOffset must be a number between 0 and " + charsCount);
            }

            int indexOfCharInLineStart;
            ReadOnlyTextLine lineStart = (ReadOnlyTextLine)GetLineByOffset(startOffset, out indexOfCharInLineStart);

            if (endOffset - startOffset + indexOfCharInLineStart < lineStart.Length)
            {
                return(lineStart.TextSegment(indexOfCharInLineStart, indexOfCharInLineStart + endOffset - startOffset));
            }
            else
            {
                int indexOfCharInLineEnd;
                ReadOnlyTextLine lineEnd = (ReadOnlyTextLine)GetLineByOffset(endOffset, out indexOfCharInLineEnd);

                StringBuilder sbSegment = new StringBuilder();
                // First line
                sbSegment.Append(lineStart.TextSegment(indexOfCharInLineStart, lineStart.Length - 1));
                // Intermediate lines
                for (int index = lineStart.LineIndex + 1; index < lineEnd.LineIndex; index++)
                {
                    sbSegment.Append(lines[index].Text);
                }
                // Last line
                sbSegment.Append(lineEnd.TextSegment(0, indexOfCharInLineEnd));
                return(sbSegment.ToString());
            }
        }
예제 #5
0
        /// <summary>
        /// Reloads the text document with new chars.
        /// The text source must be normalized as a sequence of Unicode chars with \r and/or \n end of line chars.
        /// </summary>
        public void LoadChars(IEnumerable <char> textSource)
        {
            // Reset document contents
            lines.Clear();

            // Build TextLines from chars enumerator
            charsCount = 0;
            int           lineIndex         = 0;
            StringBuilder currentLineText   = new StringBuilder();
            bool          previousCharWasCr = false;

            foreach (char chr in textSource)
            {
                if (chr == '\r')
                {
                    // If an end of line char is encountered, create a new line
                    ReadOnlyTextLine line = new ReadOnlyTextLine(lineIndex, charsCount, currentLineText.ToString(), null);
                    lines.Add(line);
                    lineIndex++;
                    charsCount += line.Length + 1; //+1 to add the \r char

                    // Reset StringBuilder contents for next line
                    currentLineText = new StringBuilder();

                    previousCharWasCr = true;
                }
                else if (chr == '\n')
                {
                    if (!previousCharWasCr)
                    {
                        // If an end of line char is encountered, create a new line
                        ReadOnlyTextLine line = new ReadOnlyTextLine(lineIndex, charsCount, currentLineText.ToString(), null);
                        lines.Add(line);
                        lineIndex++;
                        charsCount += line.Length + 1; //+1 to add the \n char

                        // Reset StringBuilder contents for next line
                        currentLineText = new StringBuilder();
                    }

                    charsCount++;
                    previousCharWasCr = false;
                }
                else
                {
                    // Append the current char to the text of the current line
                    currentLineText.Append(chr);

                    previousCharWasCr = false;
                }
            }
            // If the last line was not terminated with end of line chars
            if (currentLineText.Length > 0)
            {
                ReadOnlyTextLine line = new ReadOnlyTextLine(lineIndex, charsCount, currentLineText.ToString(), null);
                lines.Add(line);
                charsCount += line.Length;
            }

            // Send a notification of the change if enabled
            if (sendNextChangeEvents)
            {
                // Send document cleared event
                TextChangedEvent documentClearedEvent = new TextChangedEvent();
                documentClearedEvent.TextChanges.Add(new TextChange(TextChangeType.DocumentCleared, 0, null));

                EventHandler <TextChangedEvent> textChangedEvent = TextChanged;
                if (textChangedEvent != null)
                {
                    textChangedEvent(this, documentClearedEvent);
                }

                // Send all new text lines
                SendDocumentChangeEvent();
            }
        }
예제 #6
0
        /// <summary>
        /// Reloads the text document with new chars.
        /// The text source must be normalized as a sequence of Unicode chars with \r and/or \n end of line chars.
        /// </summary>
        public void LoadChars(IEnumerable<char> textSource)
        {
            // Reset document contents
            lines.Clear();

            // Build TextLines from chars enumerator
            charsCount = 0;
            int lineIndex = 0;
            StringBuilder currentLineText = new StringBuilder();
            bool previousCharWasCr = false;
            foreach (char chr in textSource)
            {
                if (chr == '\r')
                {
                    // If an end of line char is encountered, create a new line
                    ReadOnlyTextLine line = new ReadOnlyTextLine(lineIndex, charsCount, currentLineText.ToString(), null);
                    lines.Add(line);
                    lineIndex++;
                    charsCount += line.Length;

                    // Reset StringBuilder contents for next line
                    currentLineText = new StringBuilder();

                    previousCharWasCr = true;
                }
                else if (chr == '\n')
                {
                    if (!previousCharWasCr)
                    {
                        // If an end of line char is encountered, create a new line
                        ReadOnlyTextLine line = new ReadOnlyTextLine(lineIndex, charsCount, currentLineText.ToString(), null);
                        lines.Add(line);
                        lineIndex++;
                        charsCount += line.Length;

                        // Reset StringBuilder contents for next line
                        currentLineText = new StringBuilder();
                    }

                    previousCharWasCr = false;
                }
                else
                {
                    // Append the current char to the text of the current line
                    currentLineText.Append(chr);

                    previousCharWasCr = false;
                }
            }
            // If the last line was not terminated with end of line chars
            if (currentLineText.Length > 0)
            {
                ReadOnlyTextLine line = new ReadOnlyTextLine(lineIndex, charsCount, currentLineText.ToString(), null);
                lines.Add(line);
                charsCount += line.Length;
            }

            // Send a notification of the change if enabled
            if (sendNextChangeEvents)
            {
                // Send document cleared event
                TextChangedEvent documentClearedEvent = new TextChangedEvent();
                documentClearedEvent.TextChanges.Add(new TextChange(TextChangeType.DocumentCleared, 0, null));

                EventHandler<TextChangedEvent> textChangedEvent = TextChanged;
                if (textChangedEvent != null)
                {
                    textChangedEvent(this, documentClearedEvent);
                }

                // Send all new text lines
                SendDocumentChangeEvent();
            }
        }