74
/// Set to true to highlight the caret line temporarly. It's
75
/// the same as the option, but is unset when the caret moves.
77
bool highlightCaretLine;
78
public bool HighlightCaretLine {
80
return highlightCaretLine;
83
highlightCaretLine = value;
84
RemoveCachedLine (Document.GetLine (Caret.Line));
85
Document.CommitLineUpdate (Caret.Line);
75
90
get { return textEditor.Caret; }
98
113
throw new ArgumentNullException ("textEditor");
99
114
this.textEditor = textEditor;
102
116
textEditor.Document.TextReplaced += delegate(object sender, ReplaceEventArgs e) {
103
117
if (mouseSelectionMode == MouseSelectionMode.Word && e.Offset < mouseWordStart) {
104
118
int delta = -e.Count;
127
141
markerLayout = new Pango.Layout (textEditor.PangoContext);
129
143
textEditor.Document.EndUndo += UpdateBracketHighlighting;
144
textEditor.Document.Undone += delegate {
145
UpdateBracketHighlighting (this, EventArgs.Empty);
147
textEditor.Document.Redone += delegate {
148
UpdateBracketHighlighting (this, EventArgs.Empty);
130
150
Caret.PositionChanged += UpdateBracketHighlighting;
149
169
linesToRemove.ForEach (line => RemoveCachedLine (line));
150
170
linesToRemove.Clear ();
172
textEditor.RequestResetCaretBlink ();
175
internal void ClearSearchMaker ()
177
selectedRegions.Clear ();
155
180
void HandleSearchChanged (object sender, EventArgs args)
216
241
void UpdateBracketHighlighting (object sender, EventArgs e)
243
HighlightCaretLine = false;
218
244
if (!textEditor.Options.HighlightMatchingBracket)
220
247
int offset = Caret.Offset - 1;
221
248
if (offset >= 0 && offset < Document.Length && !Document.IsBracket (Document.GetCharAt (offset)))
258
285
highlightBracketOffset = matchingBracket;
259
286
int line1 = oldIndex >= 0 ? Document.OffsetToLineNumber (oldIndex) : -1;
260
287
int line2 = highlightBracketOffset >= 0 ? Document.OffsetToLineNumber (highlightBracketOffset) : -1;
288
DocumentLocation matchingBracketLocation = Document.OffsetToLocation (matchingBracket);
261
289
Application.Invoke (delegate {
263
291
textEditor.RedrawLine (line1);
320
349
chunkDict.Clear ();
352
void EnsureCaretGc ()
356
caretGc = new Gdk.GC (textEditor.GdkWindow);
357
caretGc.RgbFgColor = new Color (255, 255, 255);
358
caretGc.Function = Gdk.Function.Xor;
323
361
void DisposeGCs ()
325
363
ShowTooltip (null, Gdk.Rectangle.Zero);
359
397
DisposeHighightBackgroundWorker ();
360
398
DisposeSearchPatternWorker ();
400
if (caretTimer != null) {
402
caretTimer.Dispose ();
363
caretTimer.Dispose ();
365
407
textEditor.Document.EndUndo -= UpdateBracketHighlighting;
366
408
Caret.PositionChanged -= UpdateBracketHighlighting;
395
437
#region Caret blinking
396
438
Timer caretTimer = null;
397
439
bool caretBlink = true;
398
int caretBlinkStatus;
440
// bool firstBlink = true;
441
object lockObject = new object ();
400
443
public void ResetCaretBlink ()
402
if (caretTimer == null) {
403
caretTimer = new Timer ();
404
caretTimer.Elapsed += UpdateCaret;
405
caretTimer.Interval = (uint)Gtk.Settings.Default.CursorBlinkTime / 2;
409
bool shouldRedraw = !caretBlink;
411
caretBlinkStatus = 0;
413
textEditor.RedrawMarginLine (this, Caret.Line);
446
if (caretTimer != null)
449
if (caretTimer == null) {
450
caretTimer = new Timer (Gtk.Settings.Default.CursorBlinkTime / 2);
451
caretTimer.Elapsed += UpdateCaret;
453
bool shouldRedraw = !caretBlink;
456
textEditor.RedrawMarginLine (this, Caret.Line);
457
// firstBlink = true;
462
internal void StopCaretThread ()
466
if (caretTimer != null)
417
472
void UpdateCaret (object sender, EventArgs args)
419
bool newCaretBlink = caretBlinkStatus < 4 || (caretBlinkStatus - 4) % 3 != 0;
420
if (newCaretBlink != caretBlink) {
421
caretBlink = newCaretBlink;
423
Application.Invoke (delegate {
425
textEditor.RedrawMarginLine (this, Caret.Line);
426
} catch (Exception) {
479
caretBlink = !caretBlink;
480
if (Caret.IsVisible) {
481
Application.Invoke (delegate {
483
textEditor.RedrawMarginLine (this, Caret.Line);
484
} catch (Exception) {
447
505
public static Gdk.Rectangle EmptyRectangle = new Gdk.Rectangle (0, 0, 0, 0);
448
public Gdk.Rectangle DrawCaret (Gdk.Drawable win)
506
public void DrawCaret (Gdk.Drawable win)
450
508
if (!this.textEditor.IsInDrag) {
451
if (!(this.caretX >= 0 && (!this.textEditor.IsSomethingSelected || this.textEditor.SelectionRange.Length == 0)))
452
return EmptyRectangle;
453
if (!textEditor.HasFocus)
454
return EmptyRectangle;
456
if (Settings.Default.CursorBlink && (!Caret.IsVisible || !caretBlink))
457
return EmptyRectangle;
458
if (caretGc == null) {
459
caretGc = new Gdk.GC (win);
460
caretGc.RgbFgColor = new Color (255, 255, 255);
461
caretGc.Function = Gdk.Function.Xor;
463
// Unlike the clip region for the backing store buffer, this needs
464
// to be clipped to the range of the visible area of the widget to
465
// prevent drawing outside the widget on some Gdk backends.
466
Gdk.Rectangle caretClipRectangle = GetCaretRectangle (Caret.Mode);
468
win.GetSize (out width, out height);
469
caretClipRectangle.Intersect (new Gdk.Rectangle (0, 0, width, height));
470
caretGc.ClipRectangle = caretClipRectangle;
509
if (!(this.caretX >= 0 && (!this.textEditor.IsSomethingSelected || this.textEditor.SelectionRange.Length == 0))) {
513
if (Settings.Default.CursorBlink && (!Caret.IsVisible || !caretBlink)) {
471
517
switch (Caret.Mode) {
472
518
case CaretMode.Insert:
473
if (caretX < this.XOffset || caretClipRectangle == Gdk.Rectangle.Zero)
474
return EmptyRectangle;
475
519
win.DrawLine (caretGc, caretX, caretY, caretX, caretY + LineHeight - 1);
477
521
case CaretMode.Block:
478
if (caretX + this.charWidth < this.XOffset)
479
return EmptyRectangle;
480
522
win.DrawRectangle (caretGc, true, new Gdk.Rectangle (caretX, caretY, this.charWidth, LineHeight));
481
523
/* textRenderer.BeginDraw (win);
482
524
// textRenderer.SetClip (clipRectangle);
486
528
textRenderer.EndDraw ();*/
488
530
case CaretMode.Underscore:
489
if (caretX + this.charWidth < this.XOffset)
490
return EmptyRectangle;
491
531
int bottom = caretY + lineHeight;
492
532
win.DrawLine (caretGc, caretX, bottom, caretX + this.charWidth, bottom);
495
return caretClipRectangle;
498
537
public Gdk.Rectangle GetCaretRectangle (Mono.TextEditor.CaretMode mode)
815
856
return Encoding.UTF8.GetString (bytes, 0, index).Length;
818
class LayoutWrapper : IDisposable
859
public class LayoutWrapper : IDisposable
820
861
public Pango.Layout Layout {
870
LayoutWrapper CreateLinePartLayout (SyntaxMode mode, LineSegment line, int offset, int length, int selectionStart, int selectionEnd)
911
public LayoutWrapper CreateLinePartLayout (SyntaxMode mode, LineSegment line, int offset, int length, int selectionStart, int selectionEnd)
872
913
return GetCachedLayout (line, offset, length, selectionStart, selectionEnd, delegate(LayoutWrapper wrapper) {
873
914
wrapper.Layout.Alignment = Pango.Alignment.Left;
900
941
while ((firstSearch = GetFirstSearchResult (o, offset + length)) != null) {
901
942
HandleSelection (line, selectionStart, selectionEnd, firstSearch.Offset, firstSearch.EndOffset, delegate(int start, int end) {
902
943
Pango.AttrBackground backGround = new Pango.AttrBackground (ColorStyle.SearchTextBg.Red, ColorStyle.SearchTextBg.Green, ColorStyle.SearchTextBg.Blue);
903
backGround.StartIndex = TranslateToUTF8Index (lineChars, (uint)(start - offset), ref curIndex, ref byteIndex);
904
backGround.EndIndex = TranslateToUTF8Index (lineChars, (uint)(end - offset), ref curIndex, ref byteIndex);
905
wrapper.Add (backGround);
944
uint startIndex = (uint)(start - offset);
945
uint endIndex = (uint)(end - offset);
946
if (startIndex < endIndex && endIndex < lineChars.Length) {
947
backGround.StartIndex = TranslateToUTF8Index (lineChars, startIndex, ref curIndex, ref byteIndex);
948
backGround.EndIndex = TranslateToUTF8Index (lineChars, endIndex, ref curIndex, ref byteIndex);
949
wrapper.Add (backGround);
908
953
o = System.Math.Max (firstSearch.EndOffset, o + 1);
936
981
foreGround.EndIndex = TranslateToUTF8Index (lineChars, (uint)(startIndex + end - chunk.Offset), ref curIndex, ref byteIndex);
937
982
wrapper.Add (foreGround);
939
if (!chunkStyle.TransparentBackround) {
984
if (!chunkStyle.TransparentBackround && GetPixel (ColorStyle.Default.BackgroundColor) != GetPixel (chunkStyle.BackgroundColor)) {
940
985
Pango.AttrBackground backGround = new Pango.AttrBackground (chunkStyle.BackgroundColor.Red, chunkStyle.BackgroundColor.Green, chunkStyle.BackgroundColor.Blue);
941
986
backGround.StartIndex = foreGround.StartIndex;
942
987
backGround.EndIndex = foreGround.EndIndex;
1030
1075
void DecorateMatchingBracket (Gdk.Drawable win, Pango.Layout layout, int offset, int length, int xPos, int y, int selectionStart, int selectionEnd)
1032
1077
uint curIndex = 0, byteIndex = 0;
1034
1079
if (offset <= highlightBracketOffset && highlightBracketOffset <= offset + length) {
1035
1080
int index = highlightBracketOffset - offset;
1036
1081
Pango.Rectangle rect = layout.IndexToPos ((int)TranslateToUTF8Index (lineText.ToCharArray (), (uint)index, ref curIndex, ref byteIndex));
1038
1083
Gdk.Rectangle bracketMatch = new Gdk.Rectangle (xPos + (int)(rect.X / Pango.Scale.PangoScale), y, (int)(rect.Width / Pango.Scale.PangoScale) - 1, (int)(rect.Height / Pango.Scale.PangoScale) - 1);
1039
win.DrawRectangle (GetGC (this.ColorStyle.BracketHighlightRectangle.BackgroundColor), true, bracketMatch);
1084
if (BackgroundRenderer == null)
1085
win.DrawRectangle (GetGC (this.ColorStyle.BracketHighlightRectangle.BackgroundColor), true, bracketMatch);
1040
1087
win.DrawRectangle (GetGC (this.ColorStyle.BracketHighlightRectangle.Color), false, bracketMatch);
1045
1091
void DrawLinePart (Gdk.Drawable win, LineSegment line, int offset, int length, ref int xPos, int y, int maxX)
1047
1093
SyntaxMode mode = Document.SyntaxMode != null && textEditor.Options.EnableSyntaxHighlighting ? Document.SyntaxMode : SyntaxMode.Default;
1048
1094
int selectionStart;
1049
1095
int selectionEnd;
1050
GetSelectionOffsets (line, out selectionStart, out selectionEnd);
1096
if (BackgroundRenderer != null) {
1097
selectionStart = selectionEnd = -1;
1099
GetSelectionOffsets (line, out selectionStart, out selectionEnd);
1052
1102
// ---- new renderer
1053
1103
LayoutWrapper layout = CreateLinePartLayout (mode, line, offset, length, selectionStart, selectionEnd);
1582
1632
void DrawRectangleWithRuler (Gdk.Drawable win, int x, Gdk.Rectangle area, Gdk.Color color, bool drawDefaultBackground)
1634
if (BackgroundRenderer != null)
1584
1636
bool isDefaultColor = (color.Red == defaultBgColor.Red && color.Green == defaultBgColor.Green && color.Blue == defaultBgColor.Blue);
1585
1637
if (isDefaultColor && !drawDefaultBackground)
1669
1721
// Draw the default back color for the whole line. Colors other than the default
1670
1722
// background will be drawn when rendering the text chunks.
1672
if (textEditor.Options.HighlightCaretLine && Caret.Line == lineNr)
1724
if (BackgroundRenderer != null)
1725
BackgroundRenderer.Draw (win, area, line, x, y);
1727
if ((HighlightCaretLine || textEditor.Options.HighlightCaretLine) && Caret.Line == lineNr)
1673
1728
defaultBgColor = ColorStyle.LineMarker;
1675
1730
defaultBgColor = ColorStyle.Default.BackgroundColor;
1712
1767
markerLayout.GetPixelSize (out width, out height);
1713
1768
bool isFoldingSelected = textEditor.IsSomethingSelected && textEditor.SelectionRange.Contains (folding);
1714
1769
Rectangle foldingRectangle = new Rectangle (xPos, y, width - 1, this.LineHeight - 1);
1715
win.DrawRectangle (GetGC (isFoldingSelected ? ColorStyle.Selection.BackgroundColor : defaultBgColor), true, foldingRectangle);
1770
if (BackgroundRenderer == null)
1771
win.DrawRectangle (GetGC (isFoldingSelected ? ColorStyle.Selection.BackgroundColor : defaultBgColor), true, foldingRectangle);
1773
using (Cairo.Context cr = Gdk.CairoHelper.Create (win)) {
1774
cr.Color = Mono.TextEditor.Highlighting.Style.ToCairoColor (isFoldingSelected ? ColorStyle.Selection.Color : ColorStyle.FoldLine.Color);
1775
cr.LineWidth = textEditor.Options.Zoom;
1776
FoldingScreenbackgroundRenderer.DrawRoundRectangle (cr, true, true,
1779
textEditor.LineHeight / 2,
1780
foldingRectangle.Width,
1781
foldingRectangle.Height);
1716
1784
win.DrawRectangle (GetGC (isFoldingSelected ? ColorStyle.Selection.Color : ColorStyle.FoldLine.Color), false, foldingRectangle);
1717
1785
win.DrawLayout (GetGC (isFoldingSelected ? ColorStyle.Selection.Color : ColorStyle.FoldLine.Color), xPos, y, markerLayout);
1801
1869
lastLineRenderWidth = xPos;
1872
internal IBackgroundRenderer BackgroundRenderer {
1803
1877
internal int lastLineRenderWidth = 0;
1806
1880
void SetClip (Gdk.Rectangle rect)
1808
1882
clipRectangle = rect;
1884
caretGc.ClipRectangle = rect;
1809
1885
foreach (Gdk.GC gc in gcDictionary.Values)
1810
1886
gc.ClipRectangle = rect;