Skip to content

Commit d0027f2

Browse files
committed
Fix Git Extensions #8211: Incorrect EOL in diff
- allow the text editor to differentiate between various types of end-of-lines when displaying the EOL marker
1 parent 94b943d commit d0027f2

File tree

4 files changed

+62
-14
lines changed

4 files changed

+62
-14
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace ICSharpCode.TextEditor.Document
2+
{
3+
public enum EolMarker
4+
{
5+
None,
6+
Cr, // "\r"
7+
CrLf, // "\r\n"
8+
Lf // "\n"
9+
}
10+
}

Project/Src/Document/LineManager/LineManager.cs

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ private void InsertInternal(int offset, string text)
168168
lineCollection.SetSegmentLength(segment, lineBreakOffset - segmentOffset);
169169
var newSegment = lineCollection.InsertSegmentAfter(segment, lengthAfterInsertionPos);
170170
segment.DelimiterLength = ds.Length;
171+
segment.EolMarker = ds.EolMarker;
171172

172173
segment = newSegment;
173174
lastDelimiterEnd = ds.Offset + ds.Length;
@@ -309,25 +310,35 @@ public int GetNextVisibleLineBelow(int lineNumber, int lineCount)
309310
private DelimiterSegment NextDelimiter(string text, int offset)
310311
{
311312
for (var i = offset; i < text.Length; i++)
313+
{
314+
bool newLineSet = false;
312315
switch (text[i])
313316
{
314317
case '\r':
315-
if (i + 1 < text.Length)
316-
if (text[i + 1] == '\n')
317-
{
318-
delimiterSegment.Offset = i;
319-
delimiterSegment.Length = 2;
320-
return delimiterSegment;
321-
}
318+
if (i + 1 < text.Length && text[i + 1] == '\n')
319+
{
320+
delimiterSegment.Offset = i;
321+
delimiterSegment.Length = 2;
322+
delimiterSegment.EolMarker = EolMarker.CrLf;
323+
return delimiterSegment;
324+
}
325+
322326
#if DATACONSISTENCYTEST
323327
Debug.Assert(condition: false, "Found lone \\r, data consistency problems?");
324328
#endif
329+
newLineSet = true;
330+
delimiterSegment.EolMarker = EolMarker.Cr;
325331
goto case '\n';
326332
case '\n':
327333
delimiterSegment.Offset = i;
328334
delimiterSegment.Length = 1;
335+
if (!newLineSet)
336+
{
337+
delimiterSegment.EolMarker = EolMarker.Lf;
338+
}
329339
return delimiterSegment;
330340
}
341+
}
331342
return null;
332343
}
333344

@@ -352,8 +363,9 @@ private void OnLineDeleted(LineEventArgs e)
352363

353364
private sealed class DelimiterSegment
354365
{
366+
internal EolMarker EolMarker = EolMarker.None;
355367
internal int Length;
356368
internal int Offset;
357369
}
358370
}
359-
}
371+
}

Project/Src/Document/LineManager/LineSegment.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ public sealed class LineSegment : ISegment
1717
{
1818
internal LineSegmentTree.Enumerator treeEntry;
1919

20+
public EolMarker EolMarker { get; set; }
21+
2022
public bool IsDeleted => !treeEntry.IsValid;
2123

2224
public int LineNumber => treeEntry.CurrentIndex;

Project/Src/Gui/TextView.cs

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ private void PaintDocumentLine(Graphics g, int lineNumber, Rectangle lineRectang
200200
if (TextEditorProperties.ShowEOLMarker)
201201
{
202202
var eolMarkerColor = textArea.Document.HighlightingStrategy.GetColorFor("EOLMarkers");
203-
physicalXPos += DrawEOLMarker(g, eolMarkerColor.Color, selectionBeyondEOL ? bgColorBrush : backgroundBrush, physicalXPos, lineRectangle.Y);
203+
physicalXPos += DrawEOLMarker(g, eolMarkerColor.Color, selectionBeyondEOL ? bgColorBrush : backgroundBrush, physicalXPos, lineRectangle.Y, currentLine.EolMarker);
204204
}
205205
else
206206
{
@@ -1062,17 +1062,41 @@ private void DrawTabMarker(Graphics g, Color color, int x, int y)
10621062
DrawString(g, "\u00BB", tabMarkerColor.GetFont(TextEditorProperties.FontContainer), color, x, y);
10631063
}
10641064

1065-
private int DrawEOLMarker(Graphics g, Color color, Brush backBrush, int x, int y)
1065+
private int DrawEOLMarker(Graphics g, Color color, Brush backBrush, int x, int y, EolMarker eolMarker)
10661066
{
10671067
var eolMarkerColor = textArea.Document.HighlightingStrategy.GetColorFor("EOLMarkers");
10681068

1069-
var width = GetWidth(ch: '\u00B6', eolMarkerColor.GetFont(TextEditorProperties.FontContainer));
1069+
int eolMarkerWidth = 0;
1070+
string representation = "";
1071+
1072+
int backslashWidth = GetWidth(ch: '\\', eolMarkerColor.GetFont(TextEditorProperties.FontContainer));
1073+
int nWidth = GetWidth(ch: 'n', eolMarkerColor.GetFont(TextEditorProperties.FontContainer));
1074+
int rWidth = GetWidth(ch: 'r', eolMarkerColor.GetFont(TextEditorProperties.FontContainer));
1075+
switch (eolMarker)
1076+
{
1077+
case EolMarker.Cr:
1078+
eolMarkerWidth = backslashWidth + rWidth;
1079+
representation = "\\r";
1080+
break;
1081+
case EolMarker.CrLf:
1082+
eolMarkerWidth = backslashWidth + rWidth + backslashWidth + nWidth;
1083+
representation = "\\r\\n";
1084+
break;
1085+
case EolMarker.Lf:
1086+
eolMarkerWidth = backslashWidth + nWidth;
1087+
representation = "\\n";
1088+
break;
1089+
case EolMarker.None:
1090+
default:
1091+
return 0;
1092+
}
1093+
10701094
g.FillRectangle(
10711095
backBrush,
1072-
new RectangleF(x, y, width, FontHeight));
1096+
new RectangleF(x, y, eolMarkerWidth, FontHeight));
10731097

1074-
DrawString(g, "\u00B6", eolMarkerColor.GetFont(TextEditorProperties.FontContainer), color, x, y);
1075-
return width;
1098+
DrawString(g, representation, eolMarkerColor.GetFont(TextEditorProperties.FontContainer), color, x, y);
1099+
return eolMarkerWidth;
10761100
}
10771101

10781102
private void DrawVerticalRuler(Graphics g, Rectangle lineRectangle)

0 commit comments

Comments
 (0)