Example #1
0
        /// <summary>
        /// Validates that the sections are sorted correctly, and that they are not overlapping.
        /// </summary>
        /// <seealso cref="Sections"/>
        public void ValidateInvariants()
        {
            var line            = this;
            int lineStartOffset = line.DocumentLine.Offset;
            int lineEndOffset   = line.DocumentLine.EndOffset;

            for (int i = 0; i < line.Sections.Count; i++)
            {
                HighlightedSection s1 = line.Sections[i];
                if (s1.Offset < lineStartOffset || s1.Length < 0 || s1.Offset + s1.Length > lineEndOffset)
                {
                    throw new InvalidOperationException("Section is outside line bounds");
                }
                for (int j = i + 1; j < line.Sections.Count; j++)
                {
                    HighlightedSection s2 = line.Sections[j];
                    if (s2.Offset >= s1.Offset + s1.Length)
                    {
                        // s2 is after s1
                    }
                    else if (s2.Offset >= s1.Offset && s2.Offset + s2.Length <= s1.Offset + s1.Length)
                    {
                        // s2 is nested within s1
                    }
                    else
                    {
                        throw new InvalidOperationException("Sections are overlapping or incorrectly sorted.");
                    }
                }
            }
        }
 void PushColor(HighlightingColor color)
 {
     if (highlightedLine == null)
     {
         return;
     }
     if (color == null)
     {
         highlightedSectionStack.Push(null);
     }
     else if (lastPoppedSection != null && lastPoppedSection.Color == color &&
              lastPoppedSection.Offset + lastPoppedSection.Length == position + lineStartOffset)
     {
         highlightedSectionStack.Push(lastPoppedSection);
         lastPoppedSection = null;
     }
     else
     {
         HighlightedSection hs = new HighlightedSection {
             Offset = position + lineStartOffset,
             Color  = color
         };
         highlightedLine.Sections.Add(hs);
         highlightedSectionStack.Push(hs);
         lastPoppedSection = null;
     }
 }
Example #3
0
        /// <summary>
        /// Writes a part of the highlighted line to the RichTextWriter.
        /// </summary>
        internal void WriteTo(RichTextWriter writer, int startOffset, int endOffset)
        {
            if (writer == null)
            {
                throw new ArgumentNullException("writer");
            }
            int documentLineStartOffset = this.DocumentLine.Offset;
            int documentLineEndOffset   = documentLineStartOffset + this.DocumentLine.Length;

            if (startOffset < documentLineStartOffset || startOffset > documentLineEndOffset)
            {
                throw new ArgumentOutOfRangeException("startOffset", startOffset, "Value must be between " + documentLineStartOffset + " and " + documentLineEndOffset);
            }
            if (endOffset < startOffset || endOffset > documentLineEndOffset)
            {
                throw new ArgumentOutOfRangeException("endOffset", endOffset, "Value must be between startOffset and " + documentLineEndOffset);
            }
            ISegment requestedSegment = new SimpleSegment(startOffset, endOffset - startOffset);

            List <HtmlElement> elements = new List <HtmlElement>();

            for (int i = 0; i < this.Sections.Count; i++)
            {
                HighlightedSection s = this.Sections[i];
                if (SimpleSegment.GetOverlap(s, requestedSegment).Length > 0)
                {
                    elements.Add(new HtmlElement(s.Offset, i, false, s.Color));
                    elements.Add(new HtmlElement(s.Offset + s.Length, i, true, s.Color));
                }
            }
            elements.Sort();

            IDocument document   = this.Document;
            int       textOffset = startOffset;

            foreach (HtmlElement e in elements)
            {
                int newOffset = Math.Min(e.Offset, endOffset);
                if (newOffset > startOffset)
                {
                    document.WriteTextTo(writer, textOffset, newOffset - textOffset);
                }
                textOffset = Math.Max(textOffset, newOffset);
                if (e.IsEnd)
                {
                    writer.EndSpan();
                }
                else
                {
                    writer.BeginSpan(e.Color);
                }
            }
            document.WriteTextTo(writer, textOffset, endOffset - textOffset);
        }
 void ResetColorStack()
 {
     Debug.Assert(position == 0);
     lastPoppedSection = null;
     if (highlightedLine == null)
     {
         highlightedSectionStack = null;
     }
     else
     {
         highlightedSectionStack = new Stack <HighlightedSection>();
         foreach (HighlightingSpan span in spanStack.Reverse())
         {
             PushColor(span.SpanColor);
         }
     }
 }
        void PopColor()
        {
            if (highlightedLine == null)
            {
                return;
            }
            HighlightedSection s = highlightedSectionStack.Pop();

            if (s != null)
            {
                s.Length = (position + lineStartOffset) - s.Offset;
                if (s.Length == 0)
                {
                    highlightedLine.Sections.Remove(s);
                }
                else
                {
                    lastPoppedSection = s;
                }
            }
        }
Example #6
0
        /// <summary>
        /// Merges the additional line into this line.
        /// </summary>
        public void MergeWith(HighlightedLine additionalLine)
        {
            if (additionalLine == null)
            {
                return;
            }
#if DEBUG
            ValidateInvariants();
            additionalLine.ValidateInvariants();
#endif

            int         pos = 0;
            Stack <int> activeSectionEndOffsets = new Stack <int>();
            int         lineEndOffset           = this.DocumentLine.EndOffset;
            activeSectionEndOffsets.Push(lineEndOffset);
            foreach (HighlightedSection newSection in additionalLine.Sections)
            {
                int newSectionStart = newSection.Offset;
                // Track the existing sections using the stack, up to the point where
                // we need to insert the first part of the newSection
                while (pos < this.Sections.Count)
                {
                    HighlightedSection s = this.Sections[pos];
                    if (newSection.Offset < s.Offset)
                    {
                        break;
                    }
                    while (s.Offset > activeSectionEndOffsets.Peek())
                    {
                        activeSectionEndOffsets.Pop();
                    }
                    activeSectionEndOffsets.Push(s.Offset + s.Length);
                    pos++;
                }
                // Now insert the new section
                // Create a copy of the stack so that we can track the sections we traverse
                // during the insertion process:
                Stack <int> insertionStack = new Stack <int>(activeSectionEndOffsets.Reverse());
                // The stack enumerator reverses the order of the elements, so we call Reverse() to restore
                // the original order.
                int i;
                for (i = pos; i < this.Sections.Count; i++)
                {
                    HighlightedSection s = this.Sections[i];
                    if (newSection.Offset + newSection.Length <= s.Offset)
                    {
                        break;
                    }
                    // Insert a segment in front of s:
                    Insert(ref i, ref newSectionStart, s.Offset, newSection.Color, insertionStack);

                    while (s.Offset > insertionStack.Peek())
                    {
                        insertionStack.Pop();
                    }
                    insertionStack.Push(s.Offset + s.Length);
                }
                Insert(ref i, ref newSectionStart, newSection.Offset + newSection.Length, newSection.Color, insertionStack);
            }

#if DEBUG
            ValidateInvariants();
#endif
        }