/// <summary> /// Highlights the specified line in the specified document. /// /// Before calling this method, <see cref="CurrentSpanStack"/> must be set to the proper /// state for the beginning of this line. After highlighting has completed, /// <see cref="CurrentSpanStack"/> will be updated to represent the state after the line. /// </summary> public HighlightedLine HighlightLine(IDocument document, IDocumentLine line) { this.lineStartOffset = line.Offset; this.lineText = document.GetText(line); try { this.highlightedLine = new HighlightedLine(document, line); HighlightLineInternal(); return(this.highlightedLine); } finally { this.highlightedLine = null; this.lineText = null; this.lineStartOffset = 0; } }
/// <inheritdoc/> public HighlightedLine HighlightLine(int lineNumber) { ThrowUtil.CheckInRangeInclusive(lineNumber, "lineNumber", 1, document.LineCount); CheckIsHighlighting(); isHighlighting = true; try { HighlightUpTo(lineNumber - 1); IDocumentLine line = document.GetLineByNumber(lineNumber); HighlightedLine result = engine.HighlightLine(document, line); UpdateTreeList(lineNumber); return(result); } finally { isHighlighting = false; } }
/// <summary> /// Creates a HTML fragment from a part of a document. /// </summary> /// <param name="document">The document to create HTML from.</param> /// <param name="highlighter">The highlighter used to highlight the document. <c>null</c> is valid and will create HTML without any highlighting.</param> /// <param name="segment">The part of the document to create HTML for. You can pass <c>null</c> to create HTML for the whole document.</param> /// <param name="options">The options for the HTML creation.</param> /// <returns>HTML code for the document part.</returns> public static string CreateHtmlFragment(IDocument document, IHighlighter highlighter, ISegment segment, HtmlOptions options) { if (document == null) { throw new ArgumentNullException("document"); } if (options == null) { throw new ArgumentNullException("options"); } if (highlighter != null && highlighter.Document != document) { throw new ArgumentException("Highlighter does not belong to the specified document."); } if (segment == null) { segment = new SimpleSegment(0, document.TextLength); } StringBuilder html = new StringBuilder(); int segmentEndOffset = segment.EndOffset; IDocumentLine line = document.GetLineByOffset(segment.Offset); while (line != null && line.Offset < segmentEndOffset) { HighlightedLine highlightedLine; if (highlighter != null) { highlightedLine = highlighter.HighlightLine(line.LineNumber); } else { highlightedLine = new HighlightedLine(document, line); } SimpleSegment s = SimpleSegment.GetOverlap(segment, line); if (html.Length > 0) { html.AppendLine("<br>"); } html.Append(highlightedLine.ToHtml(s.Offset, s.EndOffset, options)); line = line.NextLine; } return(html.ToString()); }
/// <inheritdoc/> protected override void ColorizeLine(DocumentLine line) { if (highlighter != null) { lineNumberBeingColorized = line.LineNumber; HighlightedLine hl = highlighter.HighlightLine(lineNumberBeingColorized); lineNumberBeingColorized = 0; foreach (HighlightedSection section in hl.Sections) { if (IsEmptyColor(section.Color)) { continue; } ChangeLinePart(section.Offset, section.Offset + section.Length, visualLineElement => ApplyColorToElement(visualLineElement, section.Color)); } } this.lastColorizedLine = line; }
/// <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 }