diff --git a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/DefaultDocument.cs b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/DefaultDocument.cs
index 142868126c..e8c34fb808 100644
--- a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/DefaultDocument.cs
+++ b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/DefaultDocument.cs
@@ -274,6 +274,9 @@ namespace ICSharpCode.TextEditor.Document
public string GetText(int offset, int length)
{
+ #if DEBUG
+ if (length < 0) throw new ArgumentOutOfRangeException("length", length, "length < 0");
+ #endif
return textBufferStrategy.GetText(offset, length);
}
public string GetText(ISegment segment)
diff --git a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/Caret.cs b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/Caret.cs
index 2ad577612b..c17fb831c6 100644
--- a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/Caret.cs
+++ b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/Caret.cs
@@ -167,7 +167,7 @@ namespace ICSharpCode.TextEditor
caretCreated = CreateCaret(textArea.Handle, 0, 2, textArea.TextView.FontHeight);
break;
case CaretMode.OverwriteMode:
- caretCreated = CreateCaret(textArea.Handle, 0, (int)textArea.TextView.GetWidth(' '), textArea.TextView.FontHeight);
+ caretCreated = CreateCaret(textArea.Handle, 0, (int)textArea.TextView.SpaceWidth, textArea.TextView.FontHeight);
break;
}
}
diff --git a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/GutterMargin.cs b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/GutterMargin.cs
index e1e4409ef4..a544b24c94 100644
--- a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/GutterMargin.cs
+++ b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/GutterMargin.cs
@@ -43,7 +43,8 @@ namespace ICSharpCode.TextEditor
public override Size Size {
get {
- return new Size((int)(textArea.TextView.GetWidth('8') * Math.Max(3, (int)Math.Log10(textArea.Document.TotalNumberOfLines) + 1)),
+ return new Size((int)(textArea.TextView.WideSpaceWidth
+ * Math.Max(3, (int)Math.Log10(textArea.Document.TotalNumberOfLines) + 1)),
-1);
}
}
diff --git a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/HRuler.cs b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/HRuler.cs
index b73b1567c2..b185e536c8 100644
--- a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/HRuler.cs
+++ b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/HRuler.cs
@@ -27,7 +27,7 @@ namespace ICSharpCode.TextEditor
{
Graphics g = e.Graphics;
int num = 0;
- for (float x = textArea.TextView.DrawingPosition.Left; x < textArea.TextView.DrawingPosition.Right; x += textArea.TextView.GetWidth(' ')) {
+ for (float x = textArea.TextView.DrawingPosition.Left; x < textArea.TextView.DrawingPosition.Right; x += textArea.TextView.SpaceWidth) {
int offset = (Height * 2) / 3;
if (num % 5 == 0) {
offset = (Height * 4) / 5;
diff --git a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextArea.cs b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextArea.cs
index bc6c2fc713..8a1eaa84e2 100644
--- a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextArea.cs
+++ b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextArea.cs
@@ -253,12 +253,12 @@ namespace ICSharpCode.TextEditor
public void SetDesiredColumn()
{
- Caret.DesiredColumn = TextView.GetDrawingXPos(Caret.Line, Caret.Column) + (int)(VirtualTop.X * textView.GetWidth(' '));
+ Caret.DesiredColumn = TextView.GetDrawingXPos(Caret.Line, Caret.Column) + (int)(VirtualTop.X * textView.SpaceWidth);
}
public void SetCaretToDesiredColumn(int caretLine)
{
- Caret.Position = textView.GetLogicalColumn(Caret.Line, Caret.DesiredColumn + (int)(VirtualTop.X * textView.GetWidth(' ')));
+ Caret.Position = textView.GetLogicalColumn(Caret.Line, Caret.DesiredColumn + (int)(VirtualTop.X * textView.SpaceWidth));
}
public void OptionsChanged()
@@ -735,7 +735,7 @@ namespace ICSharpCode.TextEditor
// return;
// }
- InvalidateLines((int)(xPos * this.TextView.GetWidth(' ')), lineBegin, lineEnd);
+ InvalidateLines((int)(xPos * this.TextView.SpaceWidth), lineBegin, lineEnd);
}
void InvalidateLines(int xPos, int lineBegin, int lineEnd)
diff --git a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextAreaControl.cs b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextAreaControl.cs
index 3c79789ce0..35832596f5 100644
--- a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextAreaControl.cs
+++ b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextAreaControl.cs
@@ -152,7 +152,7 @@ namespace ICSharpCode.TextEditor
int max = 0;
foreach (ISegment lineSegment in Document.LineSegmentCollection) {
if(Document.FoldingManager.IsLineVisible(Document.GetLineNumberForOffset(lineSegment.Offset))) {
- max = Math.Max(lineSegment.Length, max);
+ max = Math.Max(max, textArea.TextView.GetVisualColumn(Document.GetLineNumberForOffset(lineSegment.Offset),lineSegment.Length));
}
}
hScrollBar.Minimum = 0;
@@ -162,7 +162,7 @@ namespace ICSharpCode.TextEditor
vScrollBar.SmallChange = Math.Max(0, textArea.TextView.FontHeight);
hScrollBar.LargeChange = Math.Max(0, textArea.TextView.VisibleColumnCount - 1);
- hScrollBar.SmallChange = Math.Max(0, (int)textArea.TextView.GetWidth(' '));
+ hScrollBar.SmallChange = Math.Max(0, (int)textArea.TextView.SpaceWidth);
}
public void OptionsChanged()
diff --git a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextEditorControl.cs b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextEditorControl.cs
index e6706fc756..0ea9837340 100644
--- a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextEditorControl.cs
+++ b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextEditorControl.cs
@@ -237,7 +237,7 @@ namespace ICSharpCode.TextEditor
// 100 should be enough for everyone ...err ?
float[] tabStops = new float[100];
for (int i = 0; i < tabStops.Length; ++i) {
- tabStops[i] = TabIndent * primaryTextArea.TextArea.TextView.GetWidth(' ');
+ tabStops[i] = TabIndent * primaryTextArea.TextArea.TextView.SpaceWidth;
}
printingStringFormat.SetTabStops(0, tabStops);
@@ -264,13 +264,13 @@ namespace ICSharpCode.TextEditor
foreach (TextWord word in line.Words) {
switch (word.Type) {
case TextWordType.Space:
- Advance(ref xPos, ref yPos, maxWidth, primaryTextArea.TextArea.TextView.GetWidth(' '), fontHeight);
+ Advance(ref xPos, ref yPos, maxWidth, primaryTextArea.TextArea.TextView.SpaceWidth, fontHeight);
// if (!gotNonWhitespace) {
// curTabIndent = xPos;
// }
break;
case TextWordType.Tab:
- Advance(ref xPos, ref yPos, maxWidth, TabIndent * primaryTextArea.TextArea.TextView.GetWidth(' '), fontHeight);
+ Advance(ref xPos, ref yPos, maxWidth, TabIndent * primaryTextArea.TextArea.TextView.SpaceWidth, fontHeight);
// if (!gotNonWhitespace) {
// curTabIndent = xPos;
// }
@@ -298,13 +298,13 @@ namespace ICSharpCode.TextEditor
foreach (TextWord word in line.Words) {
switch (word.Type) {
case TextWordType.Space:
- Advance(ref xPos, ref yPos, margin.Width, primaryTextArea.TextArea.TextView.GetWidth(' '), fontHeight);
+ Advance(ref xPos, ref yPos, margin.Width, primaryTextArea.TextArea.TextView.SpaceWidth, fontHeight);
// if (!gotNonWhitespace) {
// curTabIndent = xPos;
// }
break;
case TextWordType.Tab:
- Advance(ref xPos, ref yPos, margin.Width, TabIndent * primaryTextArea.TextArea.TextView.GetWidth(' '), fontHeight);
+ Advance(ref xPos, ref yPos, margin.Width, TabIndent * primaryTextArea.TextArea.TextView.SpaceWidth, fontHeight);
// if (!gotNonWhitespace) {
// curTabIndent = xPos;
// }
diff --git a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextView.cs b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextView.cs
index 677a0e1e22..13e11b850a 100644
--- a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextView.cs
+++ b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextView.cs
@@ -32,8 +32,8 @@ namespace ICSharpCode.TextEditor
public class TextView : AbstractMargin
{
int fontHeight;
- Hashtable charWitdh = new Hashtable();
- StringFormat measureStringFormat = (StringFormat)System.Drawing.StringFormat.GenericTypographic.Clone();
+ //Hashtable charWitdh = new Hashtable();
+ StringFormat measureStringFormat = (StringFormat)StringFormat.GenericTypographic.Clone();
Highlight highlight;
int physicalColumn = 0; // used for calculating physical column during paint
@@ -95,7 +95,7 @@ namespace ICSharpCode.TextEditor
public int VisibleColumnCount {
get {
- return (int)(DrawingPosition.Width / GetWidth(' ')) - 1;
+ return (int)(DrawingPosition.Width / SpaceWidth) - 1;
}
}
@@ -116,12 +116,41 @@ namespace ICSharpCode.TextEditor
return (h < 16) ? h + 1 : h;
}
+ float spaceWidth;
+
+ ///
+ /// Gets the width of a space character.
+ /// This value can be quite small in some fonts - consider using WideSpaceWidth instead.
+ ///
+ public float SpaceWidth {
+ get {
+ return spaceWidth;
+ }
+ }
+
+ float wideSpaceWidth;
+
+ ///
+ /// Gets the width of a 'wide space' (=one quarter of a tab, if tab is set to 4 spaces).
+ /// On monospaced fonts, this is the same value as spaceWidth.
+ ///
+ public float WideSpaceWidth {
+ get {
+ return wideSpaceWidth;
+ }
+ }
+
+ Font lastFont;
+
public void OptionsChanged()
{
- this.fontHeight = GetFontHeight(TextEditorProperties.Font);
- if (this.charWitdh != null) {
- this.charWitdh.Clear();
- }
+ this.lastFont = TextEditorProperties.Font;
+ this.fontHeight = GetFontHeight(lastFont);
+ // use mininum width - in some fonts, space has no width but kerning is used instead
+ // -> DivideByZeroException
+ this.spaceWidth = Math.Max(GetWidth(' ', lastFont), 1);
+ // tab should have the width of 4*'x'
+ this.wideSpaceWidth = Math.Max(spaceWidth, GetWidth('x', lastFont));
}
#region Paint functions
@@ -132,13 +161,12 @@ namespace ICSharpCode.TextEditor
}
// Just to ensure that fontHeight and char widths are always correct...
- if (fontHeight != GetFontHeight(TextEditorProperties.Font)) {
+ if (lastFont != TextEditorProperties.Font) {
OptionsChanged();
- base.TextArea.Refresh();
- return;
+ base.TextArea.BeginInvoke(new MethodInvoker(base.TextArea.Refresh));
}
- int horizontalDelta = (int)(textArea.VirtualTop.X * GetWidth(g, ' '));
+ int horizontalDelta = (int)(textArea.VirtualTop.X * SpaceWidth);
if (horizontalDelta > 0) {
g.SetClip(this.DrawingPosition);
}
@@ -221,7 +249,7 @@ namespace ICSharpCode.TextEditor
LineSegment currentLine = textArea.Document.GetLineSegment(lineNumber);
HighlightColor selectionColor = textArea.Document.HighlightingStrategy.GetColorFor("Selection");
- float spaceWidth = GetWidth(g, ' ');
+ float spaceWidth = SpaceWidth;
bool selectionBeyondEOL = selectionRange.EndColumn > currentLine.Length || ColumnRange.WholeColumn.Equals(selectionRange);
if (TextEditorProperties.ShowEOLMarker) {
@@ -339,7 +367,7 @@ namespace ICSharpCode.TextEditor
HighlightColor tabMarkerColor = textArea.Document.HighlightingStrategy.GetColorFor("TabMarkers");
HighlightColor spaceMarkerColor = textArea.Document.HighlightingStrategy.GetColorFor("SpaceMarkers");
- float spaceWidth = GetWidth(g, ' ');
+ float spaceWidth = SpaceWidth;
LineSegment currentLine = textArea.Document.GetLineSegment(lineNumber);
@@ -377,14 +405,10 @@ namespace ICSharpCode.TextEditor
List markers = Document.MarkerStrategy.GetMarkers(currentLine.Offset + wordOffset);
foreach (TextMarker marker in markers) {
if (marker.TextMarkerType == TextMarkerType.SolidBlock) {
-// if (unselectedBackgroundBrush != null) {
-// unselectedBackgroundBrush.Dispose();
-// }
unselectedBackgroundBrush = BrushRegistry.GetBrush(marker.Color);
break;
}
}
- // Clear old marker arrary
// TODO: cut the word if startColumn or endColimn is in the word;
@@ -427,11 +451,13 @@ namespace ICSharpCode.TextEditor
case TextWordType.Tab:
- int oldPhysicalColumn = physicalColumn;
physicalColumn += TextEditorProperties.TabIndent;
physicalColumn = (physicalColumn / TextEditorProperties.TabIndent) * TextEditorProperties.TabIndent;
- float tabWidth = (physicalColumn - oldPhysicalColumn) * spaceWidth;
- RectangleF tabRectangle = new RectangleF(physicalXPos, lineRectangle.Y, (float)Math.Ceiling(tabWidth), lineRectangle.Height);
+ // go to next tabstop
+ float physicalTabEnd = (int)((physicalXPos + MinTabWidth - drawingPosition.Left) / WideSpaceWidth / TextEditorProperties.TabIndent)
+ * WideSpaceWidth * TextEditorProperties.TabIndent + drawingPosition.Left;
+ 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) {
@@ -458,7 +484,7 @@ namespace ICSharpCode.TextEditor
}
}
- physicalXPos += tabWidth;
+ physicalXPos = physicalTabEnd;
++logicalColumn;
break;
@@ -521,9 +547,6 @@ namespace ICSharpCode.TextEditor
wordBackgroundBrush);
}
}
-// if (markerBrush != null) {
-// markerBrush.Dispose();
-// }
foreach (TextMarker marker in markers) {
if (marker.TextMarkerType != TextMarkerType.SolidBlock) {
DrawMarker(g, marker, new RectangleF(lastPos, lineRectangle.Y, (physicalXPos - lastPos), lineRectangle.Height));
@@ -541,55 +564,24 @@ namespace ICSharpCode.TextEditor
logicalColumn += word.Length;
break;
}
- //markers.Clear();
}
}
-// if (bgColorBrush != null) {
-// bgColorBrush.Dispose();
-// bgColorBrush = null;
-// }
-//
-// if (selectionBackgroundBrush != null) {
-// selectionBackgroundBrush.Dispose();
-// selectionBackgroundBrush = null;
-// }
-//
-// if (unselectedBackgroundBrush != null) {
-// unselectedBackgroundBrush.Dispose();
-// unselectedBackgroundBrush = null;
-// }
-
return physicalXPos;
}
+ //int num;
+
float DrawDocumentWord(Graphics g, string word, Point position, Font font, Color foreColor, Brush backBrush)
{
if (word == null || word.Length == 0) {
return 0f;
}
-// TextFormatFlags flags = TextFormatFlags.NoOverhangPadding |
-// TextFormatFlags.NoPrefix |
-// TextFormatFlags.NoFullWidthCharacterBreak |
-// TextFormatFlags.NoClipping |
-// TextFormatFlags.PreserveGraphicsClipping |
-// TextFormatFlags.PrefixOnly |
-// TextFormatFlags.SingleLine;
-// Size wordSize = TextRenderer.MeasureText(word, font, Size.Empty, flags);
-//
-// if (DrawingPosition.Left < position.X + DrawingPosition.X) {
-// TextRenderer.DrawText(g,
-// word,
-// font,
-// position,
-// foreColor,
-// ((SolidBrush)backBrush).Color,
-// flags
-// );
-// }
- float wordWidth = g.MeasureString(word, font, 32768, measureStringFormat).Width;
- g.FillRectangle(backBrush,
+ float wordWidth = MeasureStringWidth(g, word, font);
+
+ //num = ++num % 3;
+ g.FillRectangle(backBrush, //num == 0 ? Brushes.LightBlue : num == 1 ? Brushes.LightGreen : Brushes.Yellow,
new RectangleF(position.X, position.Y, (float)Math.Ceiling(wordWidth + 1), FontHeight));
g.DrawString(word,
@@ -600,37 +592,30 @@ namespace ICSharpCode.TextEditor
measureStringFormat);
return wordWidth;
}
- #endregion
-
- #region Conversion Functions
- public float GetWidth(char ch)
- {
- if (!charWitdh.ContainsKey(ch)) {
- using (Graphics g = textArea.CreateGraphics()) {
- return GetWidth(g, ch);
- }
- }
- return (float)charWitdh[ch];
- }
- public float GetWidth(string text)
+ float MeasureStringWidth(Graphics g, string word, Font font)
{
- float width = 0;
- for (int i = 0; i < text.Length; ++i) {
- width += GetWidth(text[i]);
- }
- return width;
+ if (word == null || word.Length == 0)
+ return 0;
+ // return g.MeasureString(word, font, 32768, measureStringFormat).Width;
+
+ // This code here provides better results than MeasureString!
+ // Example line that is measured wrong:
+ // txt.GetPositionFromCharIndex(txt.SelectionStart)
+ // (Verdana 10, highlighting makes GetP... bold) -> note the space between 'x' and '('
+ // this also fixes "jumping" characters when selecting in non-monospace fonts
+ Rectangle rect = new Rectangle(0, 0, 32768, 1000);
+ CharacterRange[] ranges = { new CharacterRange(0, word.Length) };
+ Region[] regions = new Region[1];
+ measureStringFormat.SetMeasurableCharacterRanges (ranges);
+ regions = g.MeasureCharacterRanges (word, font, rect, measureStringFormat);
+ return regions[0].GetBounds(g).Right;
}
+ #endregion
- public float GetWidth(Graphics g, char ch)
- {
- if (!charWitdh.ContainsKey(ch)) {
- charWitdh.Add(ch, g.MeasureString(ch.ToString(), TextEditorProperties.Font, 2000, measureStringFormat).Width);
- }
- return (float)charWitdh[ch];
- }
+ #region Conversion Functions
+ static Dictionary> fontBoundCharWidth = new Dictionary>();
- Dictionary> fontBoundCharWidth = new Dictionary>();
public float GetWidth(char ch, Font font)
{
if (!fontBoundCharWidth.ContainsKey(font)) {
@@ -644,22 +629,13 @@ namespace ICSharpCode.TextEditor
return (float)fontBoundCharWidth[font][ch];
}
- public float GetWidth(string text, Font font)
- {
- float width = 0;
- for (int i = 0; i < text.Length; ++i) {
- width += GetWidth(text[i], font);
- }
- return width;
- }
-
public float GetWidth(Graphics g, char ch, Font font)
{
if (!fontBoundCharWidth.ContainsKey(font)) {
fontBoundCharWidth.Add(font, new Dictionary());
}
if (!fontBoundCharWidth[font].ContainsKey(ch)) {
- fontBoundCharWidth[font].Add(ch, g.MeasureString(ch.ToString(), font, 2000, measureStringFormat).Width);
+ fontBoundCharWidth[font].Add(ch, MeasureStringWidth(g, ch.ToString(), font));
}
return (float)fontBoundCharWidth[font][ch];
}
@@ -699,7 +675,7 @@ namespace ICSharpCode.TextEditor
///
public Point GetLogicalPosition(int xPos, int yPos)
{
- xPos += (int)(textArea.VirtualTop.X * GetWidth(' '));
+ xPos += (int)(textArea.VirtualTop.X * SpaceWidth);
int clickedVisualLine = Math.Max(0, (yPos + this.textArea.VirtualTop.Y) / fontHeight);
int logicalLine = Document.GetFirstLogicalLine(clickedVisualLine);
Point pos = GetLogicalColumn(logicalLine, xPos);
@@ -717,7 +693,7 @@ namespace ICSharpCode.TextEditor
public Point GetLogicalColumn(int firstLogicalLine, int xPos)
{
- float spaceWidth = GetWidth(' ');
+ float spaceWidth = SpaceWidth;
LineSegment line = firstLogicalLine < Document.TotalNumberOfLines ? Document.GetLineSegment(firstLogicalLine) : null;
if (line == null) {
return new Point((int)(xPos / spaceWidth), firstLogicalLine);
@@ -765,7 +741,7 @@ namespace ICSharpCode.TextEditor
paintPos += (column - oldColumn) * spaceWidth;
break;
default:
- paintPos += GetWidth(ch);
+ paintPos += GetWidth(ch, TextEditorProperties.Font);
++column;
break;
}
@@ -784,7 +760,7 @@ namespace ICSharpCode.TextEditor
///
public FoldMarker GetFoldMarkerFromPosition(int xPos, int yPos)
{
- xPos += (int)(textArea.VirtualTop.X * GetWidth(' '));
+ xPos += (int)(textArea.VirtualTop.X * SpaceWidth);
int clickedVisualLine = (yPos + this.textArea.VirtualTop.Y) / fontHeight;
int logicalLine = Document.GetFirstLogicalLine(clickedVisualLine);
return GetFoldMarkerFromColumn(logicalLine, xPos);
@@ -792,7 +768,7 @@ namespace ICSharpCode.TextEditor
FoldMarker GetFoldMarkerFromColumn(int firstLogicalLine, int xPos)
{
- float spaceWidth = GetWidth(' ');
+ float spaceWidth = SpaceWidth;
LineSegment line = firstLogicalLine < Document.TotalNumberOfLines ? Document.GetLineSegment(firstLogicalLine) : null;
if (line == null) {
return null;
@@ -840,7 +816,7 @@ namespace ICSharpCode.TextEditor
paintPos += (column - oldColumn) * spaceWidth;
break;
default:
- paintPos += GetWidth(ch);
+ paintPos += GetWidth(ch, TextEditorProperties.Font);
++column;
break;
}
@@ -854,19 +830,65 @@ namespace ICSharpCode.TextEditor
}
}
- float CountColumns(ref int column, int start, int end, int logicalLine)
+ const float MinTabWidth = 4;
+
+ float CountColumns(ref int column, int start, int end, int logicalLine, Graphics g)
{
- float spaceWidth = GetWidth(' ');
+ if (start > end) throw new ArgumentException("start > end");
+ float spaceWidth = SpaceWidth;
float drawingPos = 0;
int tabIndent = Document.TextEditorProperties.TabIndent;
+ LineSegment currentLine = Document.GetLineSegment(logicalLine);
+ List words = currentLine.Words;
+ if (words == null) return 0;
+ int wordCount = words.Count;
+ int wordOffset = 0;
+ for (int i = 0; i < wordCount; i++) {
+ TextWord word = words[i];
+ if (wordOffset >= end)
+ break;
+ if (wordOffset + word.Length < start)
+ continue;
+ switch (word.Type) {
+ case TextWordType.Space:
+ ++column;
+ drawingPos += spaceWidth;
+ break;
+ case TextWordType.Tab:
+ int oldColumn = column;
+ column += tabIndent;
+ column = (column / tabIndent) * tabIndent;
+ // go to next tab position
+ drawingPos = (int)((drawingPos + MinTabWidth) / tabIndent / WideSpaceWidth) * tabIndent * WideSpaceWidth;
+ drawingPos += tabIndent * WideSpaceWidth;
+ break;
+ case TextWordType.Word:
+ if (word.Length == 1) {
+ ++column;
+ drawingPos += GetWidth(g, word.Word[0], word.Font ?? TextEditorProperties.Font);
+ } else {
+ int wordStart = Math.Max(wordOffset, start);
+ int wordLength = Math.Min(wordOffset + word.Length, end) - wordStart;
+ column += wordLength;
+ drawingPos += MeasureStringWidth(g, Document.GetText(currentLine.Offset + wordStart, wordLength), word.Font ?? TextEditorProperties.Font);
+ }
+ break;
+ }
+ wordOffset += word.Length;
+ }
+ for (int j = currentLine.Length; j < end; j++) {
+ ++column;
+ drawingPos += SpaceWidth;
+ }
+ /* OLD Code (does not work for fonts like Verdana)
for (int j = start; j < end; ++j) {
char ch;
- LineSegment line = Document.GetLineSegment(logicalLine);
if (j >= line.Length) {
ch = ' ';
} else {
ch = Document.GetCharAt(line.Offset + j);
}
+
switch (ch) {
case '\t':
int oldColumn = column;
@@ -878,19 +900,20 @@ namespace ICSharpCode.TextEditor
++column;
TextWord word = line.GetWord(j);
if (word == null || word.Font == null) {
- drawingPos += GetWidth(ch);
+ drawingPos += GetWidth(ch, TextEditorProperties.Font);
} else {
drawingPos += GetWidth(ch, word.Font);
}
break;
}
}
+ //*/
return drawingPos;
}
public int GetDrawingXPos(int logicalLine, int logicalColumn)
{
- float spaceWidth = GetWidth(' ');
+ float spaceWidth = SpaceWidth;
List foldings = Document.FoldingManager.GetTopLevelFoldedFoldings();
int i;
FoldMarker f = null;
@@ -906,9 +929,10 @@ namespace ICSharpCode.TextEditor
int column = 0;
int tabIndent = Document.TextEditorProperties.TabIndent;
float drawingPos;
+ Graphics g = textArea.CreateGraphics();
// if no folding is interresting
if (f == null || !(f.StartLine < logicalLine || f.StartLine == logicalLine && f.StartColumn < logicalColumn)) {
- drawingPos = CountColumns(ref column, 0, logicalColumn, logicalLine);
+ drawingPos = CountColumns(ref column, 0, logicalColumn, logicalLine, g);
return (int)(drawingPos - textArea.VirtualTop.X * spaceWidth);
}
@@ -930,7 +954,7 @@ namespace ICSharpCode.TextEditor
firstFolding = i + 1;
if (lastFolding < firstFolding) {
- drawingPos = CountColumns(ref column, 0, logicalColumn, logicalLine);
+ drawingPos = CountColumns(ref column, 0, logicalColumn, logicalLine, g);
return (int)(drawingPos - textArea.VirtualTop.X * spaceWidth);
}
@@ -938,13 +962,13 @@ namespace ICSharpCode.TextEditor
drawingPos = 0;
for (i = firstFolding; i <= lastFolding; ++i) {
f = (FoldMarker)foldings[i];
- drawingPos += CountColumns(ref column, foldEnd, f.StartColumn, f.StartLine);
+ drawingPos += CountColumns(ref column, foldEnd, f.StartColumn, f.StartLine, g);
foldEnd = f.EndColumn;
column += f.FoldText.Length;
- drawingPos += GetWidth(f.FoldText);
+ drawingPos += MeasureStringWidth(g, f.FoldText, TextEditorProperties.Font);
}
- drawingPos += CountColumns(ref column, foldEnd, logicalColumn, logicalLine);
-
+ drawingPos += CountColumns(ref column, foldEnd, logicalColumn, logicalLine, g);
+ g.Dispose();
return (int)(drawingPos - textArea.VirtualTop.X * spaceWidth);
}
#endregion
@@ -976,7 +1000,7 @@ namespace ICSharpCode.TextEditor
float DrawEOLMarker(Graphics g, Color color, Brush backBrush, float x, float y)
{
- float width = GetWidth(g, '\u00B6');
+ float width = GetWidth('\u00B6', TextEditorProperties.Font);
g.FillRectangle(backBrush,
new RectangleF(x, y, width, fontHeight));
@@ -993,7 +1017,7 @@ namespace ICSharpCode.TextEditor
}
HighlightColor vRulerColor = textArea.Document.HighlightingStrategy.GetColorFor("VRuler");
- int xpos = (int)(drawingPosition.Left + GetWidth(g, ' ') * (TextEditorProperties.VerticalRulerRow - textArea.VirtualTop.X));
+ int xpos = (int)(drawingPosition.Left + SpaceWidth * (TextEditorProperties.VerticalRulerRow - textArea.VirtualTop.X));
g.DrawLine(BrushRegistry.GetPen(vRulerColor.Color),
xpos,
lineRectangle.Top,