Using MoMa there were only 15 P/Invokes.
These resulted in surprisingly few changes.
MonoCaret.cs - A mono compatible caret
HighlightingDefinitionParser.cs - A bit of a hack to remove validation errors produced by the syntax file.
TextAreaControl.cs - Use MonoCaret instead of Caret.
TextView.cs - Use MonoCaret class
HighlightingDefinitionParser.cs
#if !MONO
if (errors != null) {
StringBuilder msg = new StringBuilder();
foreach (ValidationEventArgs args in errors) {
msg.AppendLine(args.Message);
}
throw new HighlightingDefinitionInvalidException(msg.ToString());
} else {
#endif
return highlighter;
#if !MONO
}
#endif
TextAreaControl.cs
#if MONO
public MonoCaret Caret {
get {
return textArea.Caret;
}
}
#else
public Caret Caret {
get {
return textArea.Caret;
}
}
#endif
TextView.cs
Brush fillBrush = selectionBeyondEOL && TextEditorProperties.AllowCaretBeyondEOL ? bgColorBrush : backgroundBrush;
g.FillRectangle(fillBrush,
new RectangleF(physicalXPos, lineRectangle.Y, lineRectangle.Width - physicalXPos + lineRectangle.X, lineRectangle.Height));
#if MONO
if (TextArea.Caret.Line == lineNumber)
{
DrawCaret(g, new PointF(GetDrawingXPos(TextArea.Caret.Line, TextArea.Caret.Column) + lineRectangle.X, lineRectangle.Y));
}
#endif
#if MONO
void DrawCaret(Graphics g, PointF point)
{
TextArea.Caret.PhysicalPosition = new Point((int)point.X, (int)point.Y);
TextArea.Caret.Paint(g);
}
#endif
TextArea.cs
#if MONO
MonoCaret caret;
#else
Caret caret;
#endif
#if MONO
public MonoCaret Caret {
get {
return caret;
}
}
#else
public Caret Caret {
get {
return caret;
}
}
#endif
#if MONO
caret = new MonoCaret(this);
#else
caret = new Caret(this);
#endif
MonoCaret.cs
using System;
using System.Drawing;
using System.Timers;
using ICSharpCode.TextEditor.Document;
namespace ICSharpCode.TextEditor
{
public class MonoCaret : IDisposable
{
int line = 0;
int column = 0;
int desiredColumn = 0;
Point physicalPosition;
CaretMode caretMode;
Timer timer;
int w_width;
bool hidden = false;
bool blinkShows = false;
TextArea textArea;
public int DesiredColumn
{
get { return desiredColumn; }
set { desiredColumn = value; }
}
public CaretMode CaretMode
{
get { return caretMode; }
set
{
caretMode = value;
OnCaretModeChanged(EventArgs.Empty);
}
}
public int Line
{
get { return line; }
set
{
int oldLine = line;
line = value;
ValidateCaretPos();
UpdateCaretPosition(oldLine, column, line, column);
OnPositionChanged(EventArgs.Empty);
}
}
public int Column
{
get { return column; }
set
{
int oldColumn = column;
column = value;
ValidateCaretPos();
UpdateCaretPosition(line, oldColumn, line, column);
OnPositionChanged(EventArgs.Empty);
}
}
public Point Position
{
get { return new Point(column, line); }
set
{
int oldLine = line;
int oldColumn = column;
line = value.Y;
column = value.X;
ValidateCaretPos();
UpdateCaretPosition(oldLine, oldColumn, line, column);
OnPositionChanged(EventArgs.Empty);
}
}
public Point ScreenPosition
{
get { return new Point(column, line); }
set
{
int oldLine = line;
int oldColumn = column;
line = value.Y;
column = value.X;
ValidateCaretPos();
UpdateCaretPosition(oldLine, oldColumn, line, column);
OnPositionChanged(EventArgs.Empty);
}
}
public Point PhysicalPosition
{
get { return physicalPosition; }
set { physicalPosition = value; }
}
public void Paint(Graphics g)
{
if (hidden || !blinkShows)
{
return;
}
if (caretMode == CaretMode.OverwriteMode)
{
g.DrawRectangle(Pens.Black, new Rectangle(physicalPosition.X - 2, physicalPosition.Y, w_width - 1, (int)textArea.TextView.FontHeight - 1));
}
else
{
g.DrawRectangle(Pens.Black, new Rectangle(physicalPosition.X - 2, physicalPosition.Y, 1, (int)textArea.TextView.FontHeight - 1));
}
}
public int Offset
{
get { return textArea.Document.PositionToOffset(Position); }
}
public MonoCaret(TextArea textArea)
{
this.textArea = textArea;
textArea.GotFocus += new EventHandler(GotFocus);
textArea.LostFocus += new EventHandler(LostFocus);
timer = new Timer(500);
timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
}
public void RecreateCaret() { }
private void timer_Elapsed(object sender, ElapsedEventArgs e)
{
DoBlink();
}
public void ValidateCaretPos()
{
line = Math.Max(0, Math.Min(textArea.Document.TotalNumberOfLines - 1, line));
column = Math.Max(0, column);
if (!textArea.TextEditorProperties.AllowCaretBeyondEOL)
{
LineSegment lineSegment = textArea.Document.GetLineSegment(line);
column = Math.Min(column, lineSegment.Length);
}
}
public Point ValidatePosition(Point pos)
{
int line = Math.Max(0, Math.Min(textArea.Document.TotalNumberOfLines - 1, pos.Y));
int column = Math.Max(0, pos.X);
if (column == int.MaxValue || !textArea.TextEditorProperties.AllowCaretBeyondEOL)
{
LineSegment lineSegment = textArea.Document.GetLineSegment(line);
column = Math.Min(column, lineSegment.Length);
}
return new Point(column, line);
}
void GotFocus(object sender, EventArgs e)
{
StartBlinking();
hidden = false;
}
void LostFocus(object sender, EventArgs e)
{
EndBlinking();
hidden = true;
}
bool DoBlink()
{
if (w_width == 0)
{
w_width = (int)textArea.TextView.GetWidth('w', textArea.Font);
}
textArea.Invalidate(new Rectangle(physicalPosition.X - 2, physicalPosition.Y, w_width + 1, (int)textArea.TextView.FontHeight));
blinkShows = !blinkShows;
return true;
}
void StartBlinking()
{
if (timer.Enabled)
{
return;
}
timer.Start();
}
void EndBlinking()
{
if (!timer.Enabled)
{
return;
}
timer.Stop();
}
public void UpdateCaretPosition() { }
public void UpdateCaretPosition(int oldLine, int oldColumn, int newLine, int newColumn)
{
if (hidden)
{
return;
}
try
{
textArea.UpdateLineToEnd(oldLine, 0);
if (newLine != oldLine)
{
textArea.UpdateLineToEnd(newLine, 0);
}
}
catch (Exception e)
{
Console.WriteLine("Exception updating caret position: " + e);
}
}
protected virtual void OnPositionChanged(EventArgs e)
{
EndBlinking();
blinkShows = true;
if (PositionChanged != null)
{
PositionChanged(this, e);
}
textArea.ScrollToCaret();
StartBlinking();
}
protected virtual void OnCaretModeChanged(EventArgs e)
{
if (CaretModeChanged != null)
{
CaretModeChanged(this, e);
}
}
public void Dispose() { }
public event EventHandler PositionChanged;
public event EventHandler CaretModeChanged;
}
}