diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageHighlighter.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageHighlighter.cs index 02ac80b2a6..63849fba3c 100644 --- a/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageHighlighter.cs +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageHighlighter.cs @@ -40,14 +40,14 @@ namespace ICSharpCode.CodeCoverage if (sequencePoint.EndLine == sequencePoint.Line) { LineSegment lineSegment = markerStrategy.Document.GetLineSegment(sequencePoint.Line - 1); - markerStrategy.AddMarker(new CodeCoverageTextMarker(lineSegment.Offset + sequencePoint.Column, sequencePoint)); + markerStrategy.AddMarker(new CodeCoverageTextMarker(lineSegment.Offset + sequencePoint.Column - 1, sequencePoint)); } else { // Sequence point spread across lines. for (int line = sequencePoint.Line; line <= sequencePoint.EndLine; ++line) { LineSegment lineSegment = markerStrategy.Document.GetLineSegment(line - 1); if (line == sequencePoint.Line) { // First line. - markerStrategy.AddMarker(new CodeCoverageTextMarker(lineSegment.Offset + sequencePoint.Column, lineSegment.Length - (lineSegment.DelimiterLength - 1) - sequencePoint.Column, sequencePoint)); + markerStrategy.AddMarker(new CodeCoverageTextMarker(lineSegment.Offset + sequencePoint.Column - 1, lineSegment.Length - (lineSegment.DelimiterLength - 1) - sequencePoint.Column, sequencePoint)); } else if (line == sequencePoint.EndLine) { // Last line. markerStrategy.AddMarker(new CodeCoverageTextMarker(lineSegment.Offset, sequencePoint.EndColumn - 1, sequencePoint)); diff --git a/src/AddIns/Misc/HighlightingEditor/Project/Src/EditorHighlightColor.cs b/src/AddIns/Misc/HighlightingEditor/Project/Src/EditorHighlightColor.cs index 239ff26417..6c13ac9c6a 100644 --- a/src/AddIns/Misc/HighlightingEditor/Project/Src/EditorHighlightColor.cs +++ b/src/AddIns/Misc/HighlightingEditor/Project/Src/EditorHighlightColor.cs @@ -148,7 +148,7 @@ namespace ICSharpCode.SharpDevelop.AddIns.HighlightingEditor.Nodes public static EditorHighlightColor FromTextEditor(ICSharpCode.TextEditor.Document.HighlightColor color) { - return new EditorHighlightColor(color.HasForgeground, color.Color, color.HasBackground, color.BackgroundColor, color.Bold, color.Italic); + return new EditorHighlightColor(color.HasForeground, color.Color, color.HasBackground, color.BackgroundColor, color.Bold, color.Italic); } public EditorHighlightColor(bool hascolor, Color Color, bool hasbackcolor, Color BackColor, bool bold, bool italic) diff --git a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/HighlightColor.cs b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/HighlightColor.cs index 9ccd42b59d..f464b7faf0 100644 --- a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/HighlightColor.cs +++ b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/HighlightColor.cs @@ -33,12 +33,12 @@ namespace ICSharpCode.TextEditor.Document bool bold = false; bool italic = false; - bool hasForgeground = false; + bool hasForeground = false; bool hasBackground = false; - public bool HasForgeground { + public bool HasForeground { get { - return hasForgeground; + return hasForeground; } } @@ -144,7 +144,7 @@ namespace ICSharpCode.TextEditor.Document } else { color = (Color)(Color.GetType()).InvokeMember(c, BindingFlags.GetProperty, null, Color, new object[0]); } - hasForgeground = true; + hasForeground = true; } else { color = Color.Transparent; // to set it to the default value. } @@ -191,7 +191,7 @@ namespace ICSharpCode.TextEditor.Document } else { color = (Color)(Color.GetType()).InvokeMember(c, BindingFlags.GetProperty, null, Color, new object[0]); } - hasForgeground = true; + hasForeground = true; } else { color = defaultColor.color; } @@ -217,7 +217,7 @@ namespace ICSharpCode.TextEditor.Document /// public HighlightColor(Color color, bool bold, bool italic) { - hasForgeground = true; + hasForeground = true; this.color = color; this.bold = bold; this.italic = italic; @@ -228,7 +228,7 @@ namespace ICSharpCode.TextEditor.Document /// public HighlightColor(Color color, Color backgroundcolor, bool bold, bool italic) { - hasForgeground = true; + hasForeground = true; hasBackground = true; this.color = color; this.backgroundcolor = backgroundcolor; @@ -242,7 +242,7 @@ namespace ICSharpCode.TextEditor.Document /// public HighlightColor(string systemColor, string systemBackgroundColor, bool bold, bool italic) { - hasForgeground = true; + hasForeground = true; hasBackground = true; this.systemColor = true; diff --git a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/SpanStack.cs b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/SpanStack.cs index ef02447d40..6ad89b8fa9 100644 --- a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/SpanStack.cs +++ b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/SpanStack.cs @@ -77,7 +77,7 @@ namespace ICSharpCode.TextEditor.Document return this.GetEnumerator(); } - public sealed class Enumerator : IEnumerator + public struct Enumerator : IEnumerator { StackNode c; diff --git a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/TextWord.cs b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/TextWord.cs index 6312789fda..67898e94cf 100644 --- a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/TextWord.cs +++ b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/TextWord.cs @@ -18,7 +18,7 @@ namespace ICSharpCode.TextEditor.Document } /// - /// This class represents single words with color information, two special versions of a word are + /// This class represents single words with color information, two special versions of a word are /// spaces and tabs. /// public class TextWord @@ -120,6 +120,25 @@ namespace ICSharpCode.TextEditor.Document } } + /// + /// Splits the into two parts: the part before is assigned to + /// the reference parameter , the part after is returned. + /// + public static TextWord Split(ref TextWord word, int pos) + { + #if DEBUG + if (word.Type != TextWordType.Word) + throw new ArgumentException("word.Type must be Word"); + if (pos <= 0) + throw new ArgumentOutOfRangeException("pos", pos, "pos must be > 0"); + if (pos >= word.Length) + throw new ArgumentOutOfRangeException("pos", pos, "pos must be < word.Length"); + #endif + TextWord after = new TextWord(word.document, word.line, word.offset + pos, word.length - pos, word.color, word.hasDefaultColor); + word = new TextWord(word.document, word.line, word.offset, pos, word.color, word.hasDefaultColor); + return after; + } + public bool HasDefaultColor { get { return hasDefaultColor; @@ -149,7 +168,10 @@ namespace ICSharpCode.TextEditor.Document public Color Color { get { - return color.Color; + if (color == null) + return Color.Black; + else + return color.Color; } } diff --git a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/MarkerStrategy/MarkerStrategy.cs b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/MarkerStrategy/MarkerStrategy.cs index cdccdf28bd..7b5abe2b36 100644 --- a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/MarkerStrategy/MarkerStrategy.cs +++ b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/MarkerStrategy/MarkerStrategy.cs @@ -14,9 +14,9 @@ using System.Collections.Generic; namespace ICSharpCode.TextEditor.Document { /// - /// Description of MarkerStrategy. + /// Manages the list of markers and provides ways to retrieve markers for specific positions. /// - public class MarkerStrategy + public sealed class MarkerStrategy { List textMarker = new List(); IDocument document; @@ -29,7 +29,7 @@ namespace ICSharpCode.TextEditor.Document public IEnumerable TextMarker { get { - return textMarker; + return textMarker.AsReadOnly(); } } @@ -71,7 +71,7 @@ namespace ICSharpCode.TextEditor.Document List markers = new List(); for (int i = 0; i < textMarker.Count; ++i) { TextMarker marker = (TextMarker)textMarker[i]; - if (marker.Offset <= offset && offset <= marker.Offset + marker.Length) { + if (marker.Offset <= offset && offset <= marker.EndOffset) { markers.Add(marker); } } @@ -82,14 +82,20 @@ namespace ICSharpCode.TextEditor.Document public List GetMarkers(int offset, int length) { + int endOffset = offset + length - 1; List markers = new List(); for (int i = 0; i < textMarker.Count; ++i) { TextMarker marker = (TextMarker)textMarker[i]; - if (marker.Offset <= offset && offset <= marker.Offset + marker.Length || - marker.Offset <= offset + length && offset + length <= marker.Offset + marker.Length || - offset <= marker.Offset && marker.Offset <= offset + length || - offset <= marker.Offset + marker.Length && marker.Offset + marker.Length <= offset + length - ) { + if (// start in marker region + marker.Offset <= offset && offset <= marker.EndOffset || + // end in marker region + marker.Offset <= endOffset && endOffset <= marker.EndOffset || + // marker start in region + offset <= marker.Offset && marker.Offset <= endOffset || + // marker end in region + offset <= marker.EndOffset && marker.EndOffset <= endOffset + ) + { markers.Add(marker); } } diff --git a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/MarkerStrategy/TextMarker.cs b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/MarkerStrategy/TextMarker.cs index 5224977885..b97ada1fab 100644 --- a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/MarkerStrategy/TextMarker.cs +++ b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/MarkerStrategy/TextMarker.cs @@ -1,7 +1,7 @@ // // // -// +// // $Revision$ // @@ -12,14 +12,15 @@ using System.Collections; namespace ICSharpCode.TextEditor.Document { - public enum TextMarkerType { - SolidBlock, + public enum TextMarkerType + { + SolidBlock, Underlined, WaveLine } /// - /// Description of TextMarker. + /// Marks a part of a document. /// public class TextMarker : AbstractSegment { @@ -62,12 +63,23 @@ namespace ICSharpCode.TextEditor.Document } } + /// + /// Gets the last offset that is inside the marker region. + /// + public int EndOffset { + get { + return Offset + Length - 1; + } + } + public TextMarker(int offset, int length, TextMarkerType textMarkerType) : this(offset, length, textMarkerType, Color.Red) { } public TextMarker(int offset, int length, TextMarkerType textMarkerType, Color color) { + if (length < 1) + throw new ArgumentOutOfRangeException("length", length, "length must be >= 1"); this.offset = offset; this.length = length; this.textMarkerType = textMarkerType; @@ -76,6 +88,8 @@ namespace ICSharpCode.TextEditor.Document public TextMarker(int offset, int length, TextMarkerType textMarkerType, Color color, Color foreColor) { + if (length < 1) + throw new ArgumentOutOfRangeException("length", length, "length must be >= 1"); this.offset = offset; this.length = length; this.textMarkerType = textMarkerType; diff --git a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextEditorControlBase.cs b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextEditorControlBase.cs index af773287f0..d1597cbd99 100644 --- a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextEditorControlBase.cs +++ b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextEditorControlBase.cs @@ -59,6 +59,8 @@ namespace ICSharpCode.TextEditor /// /// Current file's character encoding /// + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public Encoding Encoding { get { if (encoding == null) diff --git a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextView.cs b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextView.cs index 22297f7d58..9c02911bc3 100644 --- a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextView.cs +++ b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextView.cs @@ -1,7 +1,7 @@ // // // -// +// // $Revision$ // @@ -190,6 +190,8 @@ namespace ICSharpCode.TextEditor } } + DrawMarkerDraw(g); + if (horizontalDelta > 0) { g.ResetClip(); } @@ -325,24 +327,50 @@ namespace ICSharpCode.TextEditor return ceiling; } + struct MarkerToDraw { + internal TextMarker marker; + internal RectangleF drawingRect; + + public MarkerToDraw(TextMarker marker, RectangleF drawingRect) + { + this.marker = marker; + this.drawingRect = drawingRect; + } + } + + List markersToDraw = new List(); + void DrawMarker(Graphics g, TextMarker marker, RectangleF drawingRect) { - float drawYPos = drawingRect.Bottom - 1; - switch (marker.TextMarkerType) { - case TextMarkerType.Underlined: - g.DrawLine(BrushRegistry.GetPen(marker.Color), drawingRect.X, drawYPos, drawingRect.Right, drawYPos); - break; - case TextMarkerType.WaveLine: - int reminder = ((int)drawingRect.X) % 6; - for (float i = drawingRect.X - reminder; i < drawingRect.Right + reminder; i+= 6) { - g.DrawLine(BrushRegistry.GetPen(marker.Color), i, drawYPos + 3 - 4, i + 3, drawYPos + 1 - 4); - g.DrawLine(BrushRegistry.GetPen(marker.Color), i + 3, drawYPos + 1 - 4, i + 6, drawYPos + 3 - 4); - } - break; - case TextMarkerType.SolidBlock: - g.FillRectangle(BrushRegistry.GetBrush(marker.Color), drawingRect); - break; + // draw markers later so they can overdraw the following text + markersToDraw.Add(new MarkerToDraw(marker, drawingRect)); + } + + void DrawMarkerDraw(Graphics g) + { + foreach (MarkerToDraw m in markersToDraw) { + TextMarker marker = m.marker; + RectangleF drawingRect = m.drawingRect; + float drawYPos = drawingRect.Bottom - 1; + switch (marker.TextMarkerType) { + case TextMarkerType.Underlined: + g.DrawLine(BrushRegistry.GetPen(marker.Color), drawingRect.X, drawYPos, drawingRect.Right, drawYPos); + break; + case TextMarkerType.WaveLine: + int reminder = ((int)drawingRect.X) % 6; + for (float i = (int)drawingRect.X - reminder; i < drawingRect.Right; i += 6) { + g.DrawLine(BrushRegistry.GetPen(marker.Color), i, drawYPos + 3 - 4, i + 3, drawYPos + 1 - 4); + if (i + 3 < drawingRect.Right) { + g.DrawLine(BrushRegistry.GetPen(marker.Color), i + 3, drawYPos + 1 - 4, i + 6, drawYPos + 3 - 4); + } + } + break; + case TextMarkerType.SolidBlock: + g.FillRectangle(BrushRegistry.GetBrush(marker.Color), drawingRect); + break; + } } + markersToDraw.Clear(); } /// @@ -352,7 +380,7 @@ namespace ICSharpCode.TextEditor /// The length. /// All markers that have been found. /// The Brush or null when no marker was found. - Brush GetMarkerBrushAt(int offset, int length, ref Color foreColor, out List markers) + Brush GetMarkerBrushAt(int offset, int length, ref Color foreColor, out IList markers) { markers = Document.MarkerStrategy.GetMarkers(offset, length); foreach (TextMarker marker in markers) { @@ -369,8 +397,7 @@ namespace ICSharpCode.TextEditor float PaintLinePart(Graphics g, int lineNumber, int startColumn, int endColumn, Rectangle lineRectangle, float physicalXPos) { bool drawLineMarker = DrawLineMarkerAtLine(lineNumber); - Brush bgColorBrush = GetBgColorBrush(lineNumber); - Brush backgroundBrush = textArea.Enabled ? bgColorBrush : SystemBrushes.InactiveBorder; + Brush backgroundBrush = textArea.Enabled ? GetBgColorBrush(lineNumber) : SystemBrushes.InactiveBorder; HighlightColor selectionColor = textArea.Document.HighlightingStrategy.GetColorFor("Selection"); ColumnRange selectionRange = textArea.SelectionManager.GetSelectionAtLine(lineNumber); @@ -379,208 +406,178 @@ namespace ICSharpCode.TextEditor LineSegment currentLine = textArea.Document.GetLineSegment(lineNumber); - int logicalColumn = startColumn; - Brush selectionBackgroundBrush = BrushRegistry.GetBrush(selectionColor.BackgroundColor); - Brush unselectedBackgroundBrush = backgroundBrush; - if (currentLine.Words != null) { - int startword = 0; - // search the first word after startColumn and update physicalColumn if a word is Tab - int wordOffset = 0; - for (; startword < currentLine.Words.Count; ++startword) { - if (wordOffset >= startColumn) { - break; + if (currentLine.Words == null) { + return physicalXPos; + } + + int currentWordOffset = 0; // we cannot use currentWord.Offset because it is not set on space words + + TextWord currentWord; + TextWord nextCurrentWord = null; + for (int wordIdx = 0; wordIdx < currentLine.Words.Count; wordIdx++) { + currentWord = currentLine.Words[wordIdx]; + if (currentWordOffset < startColumn) { + // TODO: maybe we need to split at startColumn when we support fold markers + // inside words + currentWordOffset += currentWord.Length; + continue; + } + repeatDrawCurrentWord: + //physicalXPos += 10; // leave room between drawn words - useful for debugging the drawing code + if (currentWordOffset >= endColumn || physicalXPos >= lineRectangle.Right) { + break; + } + int currentWordEndOffset = currentWordOffset + currentWord.Length - 1; + TextWordType currentWordType = currentWord.Type; + + IList markers; + Color wordForeColor; + if (currentWordType == TextWordType.Space) + wordForeColor = spaceMarkerColor.Color; + else if (currentWordType == TextWordType.Tab) + wordForeColor = tabMarkerColor.Color; + else + wordForeColor = currentWord.Color; + Brush wordBackBrush = GetMarkerBrushAt(currentLine.Offset + currentWordOffset, currentWord.Length, ref wordForeColor, out markers); + + // It is possible that we have to split the current word because a marker/the selection begins/ends inside it + if (currentWord.Length > 1) { + int splitPos = int.MaxValue; + if (highlight != null) { + // split both before and after highlight + if (highlight.OpenBrace.Y == lineNumber) { + if (highlight.OpenBrace.X >= currentWordOffset && highlight.OpenBrace.X <= currentWordEndOffset) { + splitPos = Math.Min(splitPos, highlight.OpenBrace.X - currentWordOffset); + } + } + if (highlight.CloseBrace.Y == lineNumber) { + if (highlight.CloseBrace.X >= currentWordOffset && highlight.CloseBrace.X <= currentWordEndOffset) { + splitPos = Math.Min(splitPos, highlight.CloseBrace.X - currentWordOffset); + } + } + if (splitPos == 0) { + splitPos = 1; // split after highlight + } + } + if (endColumn < currentWordEndOffset) { // split when endColumn is reached + splitPos = Math.Min(splitPos, endColumn - currentWordOffset); } - TextWord currentWord = ((TextWord)currentLine.Words[startword]); - if (currentWord.Type == TextWordType.Tab) { - ++wordOffset; - } else if (currentWord.Type == TextWordType.Space) { - ++wordOffset; - } else { - wordOffset += currentWord.Length; + if (selectionRange.StartColumn > currentWordOffset && selectionRange.StartColumn <= currentWordEndOffset) { + splitPos = Math.Min(splitPos, selectionRange.StartColumn - currentWordOffset); + } else if (selectionRange.EndColumn > currentWordOffset && selectionRange.EndColumn <= currentWordEndOffset) { + splitPos = Math.Min(splitPos, selectionRange.EndColumn - currentWordOffset); } + foreach (TextMarker marker in markers) { + int markerColumn = marker.Offset - currentLine.Offset; + int markerEndColumn = marker.EndOffset - currentLine.Offset + 1; // make end offset exclusive + if (markerColumn > currentWordOffset && markerColumn <= currentWordEndOffset) { + splitPos = Math.Min(splitPos, markerColumn - currentWordOffset); + } else if (markerEndColumn > currentWordOffset && markerEndColumn <= currentWordEndOffset) { + splitPos = Math.Min(splitPos, markerEndColumn - currentWordOffset); + } + } + if (splitPos != int.MaxValue) { + if (nextCurrentWord != null) + throw new ApplicationException("split part invalid: first part cannot be splitted further"); + nextCurrentWord = TextWord.Split(ref currentWord, splitPos); + goto repeatDrawCurrentWord; // get markers for first word part + } + } + + // get colors from selection status: + if (ColumnRange.WholeColumn.Equals(selectionRange) || (selectionRange.StartColumn <= currentWordOffset + && selectionRange.EndColumn > currentWordEndOffset)) + { + // word is completely selected + wordBackBrush = selectionBackgroundBrush; + if (selectionColor.HasForeground) { + wordForeColor = selectionColor.Color; + } + } else if (drawLineMarker) { + wordBackBrush = backgroundBrush; } + if (wordBackBrush == null) { // use default background if no other background is set + if (currentWord.SyntaxColor != null && currentWord.SyntaxColor.HasBackground) + wordBackBrush = BrushRegistry.GetBrush(currentWord.SyntaxColor.BackgroundColor); + else + wordBackBrush = backgroundBrush; + } + + RectangleF wordRectangle; - for (int i = startword; i < currentLine.Words.Count && physicalXPos < lineRectangle.Right; ++i) { + if (currentWord.Type == TextWordType.Space) { + ++physicalColumn; - // if already all words before endColumn are drawen: break - if (logicalColumn >= endColumn) { - break; - } + wordRectangle = new RectangleF(physicalXPos, lineRectangle.Y, (float)Math.Ceiling(SpaceWidth), lineRectangle.Height); + g.FillRectangle(wordBackBrush, wordRectangle); - List markers = Document.MarkerStrategy.GetMarkers(currentLine.Offset + wordOffset); - foreach (TextMarker marker in markers) { - if (marker.TextMarkerType == TextMarkerType.SolidBlock) { - unselectedBackgroundBrush = BrushRegistry.GetBrush(marker.Color); - break; - } + if (TextEditorProperties.ShowSpaces) { + DrawSpaceMarker(g, wordForeColor, physicalXPos, lineRectangle.Y); } + physicalXPos += SpaceWidth; + } else if (currentWord.Type == TextWordType.Tab) { + physicalColumn += TextEditorProperties.TabIndent; + physicalColumn = (physicalColumn / TextEditorProperties.TabIndent) * TextEditorProperties.TabIndent; + // go to next tabstop + float physicalTabEnd = (int)((physicalXPos + MinTabWidth - lineRectangle.X) + / WideSpaceWidth / TextEditorProperties.TabIndent) + * WideSpaceWidth * TextEditorProperties.TabIndent + lineRectangle.X; + physicalTabEnd += WideSpaceWidth * TextEditorProperties.TabIndent; - // TODO: cut the word if startColumn or endColimn is in the word; - // needed for foldings wich can start or end in the middle of a word - TextWord currentWord = ((TextWord)currentLine.Words[i]); - switch (currentWord.Type) { - case TextWordType.Space: - RectangleF spaceRectangle = new RectangleF(physicalXPos, lineRectangle.Y, (float)Math.Ceiling(SpaceWidth), lineRectangle.Height); - - Brush spaceBackgroundBrush; - Color spaceMarkerForeColor = spaceMarkerColor.Color; - if (ColumnRange.WholeColumn.Equals(selectionRange) || logicalColumn >= selectionRange.StartColumn && logicalColumn < selectionRange.EndColumn) { - spaceBackgroundBrush = selectionBackgroundBrush; - } else { - Brush markerBrush = GetMarkerBrushAt(currentLine.Offset + logicalColumn, 1, ref spaceMarkerForeColor, out markers); - if (!drawLineMarker && markerBrush != null) { - spaceBackgroundBrush = markerBrush; - } else if (!drawLineMarker && currentWord.SyntaxColor != null && currentWord.SyntaxColor.HasBackground) { - spaceBackgroundBrush = BrushRegistry.GetBrush(currentWord.SyntaxColor.BackgroundColor); - } else { - spaceBackgroundBrush = unselectedBackgroundBrush; - } - } - g.FillRectangle(spaceBackgroundBrush, spaceRectangle); - - if (TextEditorProperties.ShowSpaces) { - DrawSpaceMarker(g, spaceMarkerForeColor, physicalXPos, lineRectangle.Y); - } - foreach (TextMarker marker in markers) { - if (marker.TextMarkerType != TextMarkerType.SolidBlock) { - DrawMarker(g, marker, spaceRectangle); - } - } - - physicalXPos += SpaceWidth; - - ++logicalColumn; - ++physicalColumn; - break; - - case TextWordType.Tab: - - physicalColumn += TextEditorProperties.TabIndent; - physicalColumn = (physicalColumn / TextEditorProperties.TabIndent) * TextEditorProperties.TabIndent; - // go to next tabstop - float physicalTabEnd = (int)((physicalXPos + MinTabWidth - lineRectangle.X) - / WideSpaceWidth / TextEditorProperties.TabIndent) - * WideSpaceWidth * TextEditorProperties.TabIndent + lineRectangle.X; - physicalTabEnd += WideSpaceWidth * TextEditorProperties.TabIndent; - RectangleF tabRectangle = new RectangleF(physicalXPos, lineRectangle.Y, (float)Math.Ceiling(physicalTabEnd - physicalXPos), lineRectangle.Height); - Color tabMarkerForeColor = tabMarkerColor.Color; - - if (ColumnRange.WholeColumn.Equals(selectionRange) || logicalColumn >= selectionRange.StartColumn && logicalColumn <= selectionRange.EndColumn - 1) { - spaceBackgroundBrush = selectionBackgroundBrush; - } else { - Brush markerBrush = GetMarkerBrushAt(currentLine.Offset + logicalColumn, 1, ref tabMarkerForeColor, out markers); - if (!drawLineMarker && markerBrush != null) { - spaceBackgroundBrush = markerBrush; - } else if (!drawLineMarker && currentWord.SyntaxColor != null && currentWord.SyntaxColor.HasBackground) { - spaceBackgroundBrush = BrushRegistry.GetBrush(currentWord.SyntaxColor.BackgroundColor); - } else { - spaceBackgroundBrush = unselectedBackgroundBrush; - } - } - g.FillRectangle(spaceBackgroundBrush, tabRectangle); - - if (TextEditorProperties.ShowTabs) { - DrawTabMarker(g, tabMarkerForeColor, physicalXPos, lineRectangle.Y); - } - - foreach (TextMarker marker in markers) { - if (marker.TextMarkerType != TextMarkerType.SolidBlock) { - DrawMarker(g, marker, tabRectangle); - } - } - - physicalXPos = physicalTabEnd; - - ++logicalColumn; - break; - - case TextWordType.Word: - string word = currentWord.Word; - float lastPos = physicalXPos; - - Color wordForeColor = currentWord.Color; - Brush bgMarkerBrush = GetMarkerBrushAt(currentLine.Offset + logicalColumn, word.Length, ref wordForeColor, out markers); - Brush wordBackgroundBrush; - if (!drawLineMarker && bgMarkerBrush != null) { - wordBackgroundBrush = bgMarkerBrush; - } else if (!drawLineMarker && currentWord.SyntaxColor.HasBackground) { - wordBackgroundBrush = BrushRegistry.GetBrush(currentWord.SyntaxColor.BackgroundColor); - } else { - wordBackgroundBrush = unselectedBackgroundBrush; - } - - - if (ColumnRange.WholeColumn.Equals(selectionRange) || selectionRange.EndColumn - 1 >= word.Length + logicalColumn && - selectionRange.StartColumn <= logicalColumn) { - physicalXPos += DrawDocumentWord(g, - word, - new Point((int)physicalXPos, lineRectangle.Y), - currentWord.Font, - selectionColor.HasForgeground ? selectionColor.Color : wordForeColor, - selectionBackgroundBrush); - } else { - if (ColumnRange.NoColumn.Equals(selectionRange) /* || selectionRange.StartColumn > logicalColumn + word.Length || selectionRange.EndColumn - 1 <= logicalColumn */) { - physicalXPos += DrawDocumentWord(g, - word, - new Point((int)physicalXPos, lineRectangle.Y), - currentWord.Font, - wordForeColor, - wordBackgroundBrush); - } else { - int offset1 = Math.Min(word.Length, Math.Max(0, selectionRange.StartColumn - logicalColumn )); - int offset2 = Math.Max(offset1, Math.Min(word.Length, selectionRange.EndColumn - logicalColumn)); - - physicalXPos += DrawDocumentWord(g, - word.Substring(0, offset1), - new Point((int)physicalXPos, lineRectangle.Y), - currentWord.Font, - wordForeColor, - wordBackgroundBrush); - - physicalXPos += DrawDocumentWord(g, - word.Substring(offset1, offset2 - offset1), - new Point((int)physicalXPos, lineRectangle.Y), - currentWord.Font, - selectionColor.HasForgeground ? selectionColor.Color : wordForeColor, - selectionBackgroundBrush); - - physicalXPos += DrawDocumentWord(g, - word.Substring(offset2), - new Point((int)physicalXPos, lineRectangle.Y), - currentWord.Font, - wordForeColor, - wordBackgroundBrush); - } - } - foreach (TextMarker marker in markers) { - if (marker.TextMarkerType != TextMarkerType.SolidBlock) { - DrawMarker(g, marker, new RectangleF(lastPos, lineRectangle.Y, (physicalXPos - lastPos), lineRectangle.Height)); - } - } - - // draw bracket highlight - if (highlight != null) { - if (highlight.OpenBrace.Y == lineNumber && highlight.OpenBrace.X == logicalColumn || - highlight.CloseBrace.Y == lineNumber && highlight.CloseBrace.X == logicalColumn) { - DrawBracketHighlight(g, new Rectangle((int)lastPos, lineRectangle.Y, (int)(physicalXPos - lastPos) - 1, lineRectangle.Height - 1)); - } - } - physicalColumn += word.Length; - logicalColumn += word.Length; - break; + wordRectangle = new RectangleF(physicalXPos, lineRectangle.Y, (float)Math.Ceiling(physicalTabEnd - physicalXPos), lineRectangle.Height); + g.FillRectangle(wordBackBrush, wordRectangle); + + if (TextEditorProperties.ShowTabs) { + DrawTabMarker(g, wordForeColor, physicalXPos, lineRectangle.Y); + } + physicalXPos = physicalTabEnd; + } else { + float wordWidth = DrawDocumentWord(g, + currentWord.Word, + new Point((int)physicalXPos, lineRectangle.Y), + currentWord.Font, + wordForeColor, + wordBackBrush); + wordRectangle = new RectangleF(physicalXPos, lineRectangle.Y, wordWidth, lineRectangle.Height); + physicalXPos += wordWidth; + } + foreach (TextMarker marker in markers) { + if (marker.TextMarkerType != TextMarkerType.SolidBlock) { + DrawMarker(g, marker, wordRectangle); + } + } + + // draw bracket highlight + if (highlight != null) { + if (highlight.OpenBrace.Y == lineNumber && highlight.OpenBrace.X == currentWordOffset || + highlight.CloseBrace.Y == lineNumber && highlight.CloseBrace.X == currentWordOffset) { + DrawBracketHighlight(g, new Rectangle((int)wordRectangle.X, lineRectangle.Y, (int)wordRectangle.Width - 1, lineRectangle.Height - 1)); + } + } + + currentWordOffset += currentWord.Length; + if (nextCurrentWord != null) { + currentWord = nextCurrentWord; + nextCurrentWord = null; + goto repeatDrawCurrentWord; + } + } + if (physicalXPos < lineRectangle.Right && endColumn >= currentLine.Length) { + // draw markers at line end + IList markers = Document.MarkerStrategy.GetMarkers(currentLine.Offset + currentLine.Length); + foreach (TextMarker marker in markers) { + if (marker.TextMarkerType != TextMarkerType.SolidBlock) { + DrawMarker(g, marker, new RectangleF(physicalXPos, lineRectangle.Y, WideSpaceWidth, lineRectangle.Height)); } } } - return physicalXPos; } - //int num; - float DrawDocumentWord(Graphics g, string word, Point position, Font font, Color foreColor, Brush backBrush) { if (word == null || word.Length == 0) { diff --git a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/ErrorDrawer.cs b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/ErrorDrawer.cs index cf3f19c5a2..eb6c2fd2c6 100644 --- a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/ErrorDrawer.cs +++ b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/ErrorDrawer.cs @@ -149,21 +149,19 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor if (task.Line >= 0 && task.Line < textEditor.Document.TotalNumberOfLines) { LineSegment line = textEditor.Document.GetLineSegment(task.Line); int offset = line.Offset + task.Column; + int length = 1; if (line.Words != null) { foreach (TextWord tw in line.Words) { - if (task.Column >= tw.Offset && task.Column < (tw.Offset + tw.Length)) { - textEditor.Document.MarkerStrategy.AddMarker(new VisualError(offset, tw.Length, task)); - if (refresh) { - textEditor.Refresh(); - } - return; + if (task.Column == tw.Offset) { + length = tw.Length; + break; } } } - offset = Math.Min(offset, textEditor.Document.TextLength); - int startOffset = offset; - int endOffset = Math.Max(1, TextUtilities.FindWordEnd(textEditor.Document, offset)); - textEditor.Document.MarkerStrategy.AddMarker(new VisualError(startOffset, endOffset - startOffset + 1, task)); + if (length == 1 && task.Column < line.Length) { + length = 2; // use minimum length + } + textEditor.Document.MarkerStrategy.AddMarker(new VisualError(offset, length, task)); if (refresh) { textEditor.Refresh(); }