Browse Source

Caret is now displayed at the correct position when using non-monospaced fonts. (but selecting with the mouse still doesn't work)

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@537 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 20 years ago
parent
commit
8f8218c216
  1. 3
      src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/DefaultDocument.cs
  2. 2
      src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/Caret.cs
  3. 3
      src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/GutterMargin.cs
  4. 2
      src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/HRuler.cs
  5. 6
      src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextArea.cs
  6. 4
      src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextAreaControl.cs
  7. 10
      src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextEditorControl.cs
  8. 256
      src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextView.cs

3
src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/DefaultDocument.cs

@ -274,6 +274,9 @@ namespace ICSharpCode.TextEditor.Document @@ -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)

2
src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/Caret.cs

@ -167,7 +167,7 @@ namespace ICSharpCode.TextEditor @@ -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;
}
}

3
src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/GutterMargin.cs

@ -43,7 +43,8 @@ namespace ICSharpCode.TextEditor @@ -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);
}
}

2
src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/HRuler.cs

@ -27,7 +27,7 @@ namespace ICSharpCode.TextEditor @@ -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;

6
src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextArea.cs

@ -253,12 +253,12 @@ namespace ICSharpCode.TextEditor @@ -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 @@ -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)

4
src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextAreaControl.cs

@ -152,7 +152,7 @@ namespace ICSharpCode.TextEditor @@ -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 @@ -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()

10
src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextEditorControl.cs

@ -237,7 +237,7 @@ namespace ICSharpCode.TextEditor @@ -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 @@ -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 @@ -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;
// }

256
src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextView.cs

@ -32,8 +32,8 @@ namespace ICSharpCode.TextEditor @@ -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 @@ -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 @@ -116,12 +116,41 @@ namespace ICSharpCode.TextEditor
return (h < 16) ? h + 1 : h;
}
float spaceWidth;
/// <summary>
/// Gets the width of a space character.
/// This value can be quite small in some fonts - consider using WideSpaceWidth instead.
/// </summary>
public float SpaceWidth {
get {
return spaceWidth;
}
}
float wideSpaceWidth;
/// <summary>
/// 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.
/// </summary>
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 @@ -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 @@ -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 @@ -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 @@ -377,14 +405,10 @@ namespace ICSharpCode.TextEditor
List<TextMarker> 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 @@ -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 @@ -458,7 +484,7 @@ namespace ICSharpCode.TextEditor
}
}
physicalXPos += tabWidth;
physicalXPos = physicalTabEnd;
++logicalColumn;
break;
@ -521,9 +547,6 @@ namespace ICSharpCode.TextEditor @@ -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 @@ -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 @@ -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<Font, Dictionary<char, float>> fontBoundCharWidth = new Dictionary<Font, Dictionary<char, float>>();
Dictionary<Font, Dictionary<char, float>> fontBoundCharWidth = new Dictionary<Font, Dictionary<char, float>>();
public float GetWidth(char ch, Font font)
{
if (!fontBoundCharWidth.ContainsKey(font)) {
@ -644,22 +629,13 @@ namespace ICSharpCode.TextEditor @@ -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<char, float>());
}
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 @@ -699,7 +675,7 @@ namespace ICSharpCode.TextEditor
/// </summary>
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 @@ -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 @@ -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 @@ -784,7 +760,7 @@ namespace ICSharpCode.TextEditor
/// </summary>
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 @@ -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 @@ -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 @@ -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<TextWord> 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 @@ -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<FoldMarker> foldings = Document.FoldingManager.GetTopLevelFoldedFoldings();
int i;
FoldMarker f = null;
@ -906,9 +929,10 @@ namespace ICSharpCode.TextEditor @@ -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 @@ -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 @@ -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 @@ -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 @@ -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,

Loading…
Cancel
Save