~ubuntu-branches/ubuntu/oneiric/monodevelop/oneiric

« back to all changes in this revision

Viewing changes to src/core/Mono.Texteditor/Mono.TextEditor/TextEditor.cs

  • Committer: Bazaar Package Importer
  • Author(s): Jo Shields
  • Date: 2011-06-27 17:03:13 UTC
  • mto: (1.8.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 54.
  • Revision ID: james.westby@ubuntu.com-20110627170313-6cvz3s19x6e9hqe9
ImportĀ upstreamĀ versionĀ 2.5.92+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
57
57
                protected TextViewMargin   textViewMargin;
58
58
                
59
59
                LineSegment longestLine      = null;
60
 
                int         longestLineWidth = -1;
 
60
                double      longestLineWidth = -1;
61
61
                
62
62
                List<Margin> margins = new List<Margin> ();
63
63
                int oldRequest = -1;
65
65
                bool isDisposed = false;
66
66
                IMMulticontext imContext;
67
67
                Gdk.EventKey lastIMEvent;
 
68
                Gdk.Key lastIMEventMappedKey;
 
69
                uint lastIMEventMappedChar;
 
70
                Gdk.ModifierType lastIMEventMappedModifier;
68
71
                bool imContextActive;
69
72
                
70
73
                string currentStyleName;
76
79
                                return textEditorData.Document;
77
80
                        }
78
81
                        set {
79
 
                                textEditorData.Document.TextReplaced -= OnDocumentStateChanged;
80
 
                                textEditorData.Document.TextSet -= OnTextSet;
 
82
                                var oldDoc = textEditorData.Document;
 
83
                                if (oldDoc != null) {
 
84
                                        oldDoc.TextReplaced -= OnDocumentStateChanged;
 
85
                                        oldDoc.TextSet -= OnTextSet;
 
86
                                        oldDoc.LineChanged -= UpdateLinesOnTextMarkerHeightChange; 
 
87
                                        oldDoc.MarkerAdded -= HandleTextEditorDataDocumentMarkerChange;
 
88
                                        oldDoc.MarkerRemoved -= HandleTextEditorDataDocumentMarkerChange;
 
89
                                }
 
90
                                
81
91
                                textEditorData.Document = value;
82
92
                                textEditorData.Document.TextReplaced += OnDocumentStateChanged;
83
93
                                textEditorData.Document.TextSet += OnTextSet;
 
94
                                textEditorData.Document.LineChanged += UpdateLinesOnTextMarkerHeightChange; 
 
95
                                textEditorData.Document.MarkerAdded += HandleTextEditorDataDocumentMarkerChange;
 
96
                                textEditorData.Document.MarkerRemoved += HandleTextEditorDataDocumentMarkerChange;
84
97
                        }
85
98
                }
86
99
                
90
103
                        }
91
104
                }
92
105
                
93
 
                protected IMMulticontext IMContext {
 
106
                protected internal IMMulticontext IMContext {
94
107
                        get { return imContext; }
95
108
                }
96
109
                
116
129
                                        OptionsChanged (null, null);
117
130
                        }
118
131
                }
119
 
                Dictionary<int, int> lineHeights = new Dictionary<int, int> ();
 
132
                Dictionary<int, double> lineHeights = new Dictionary<int, double> ();
120
133
                
121
134
                public TextEditor () : this(new Document ())
122
135
                {
123
 
                        // TODO: Enable accessibility factory
124
 
                        //                      new TextEditorAccessible.Factory ();
125
 
                        textEditorData.Document.LineChanged += UpdateLinesOnTextMarkerHeightChange; 
126
 
                }
127
 
                
128
 
                int oldHAdjustment = -1;
 
136
                }
 
137
 
 
138
                void HandleTextEditorDataDocumentMarkerChange (object sender, TextMarkerEvent e)
 
139
                {
 
140
                        TextViewMargin.RemoveCachedLine (e.Line);
 
141
                        Document.CommitLineUpdate (e.Line);
 
142
                }
129
143
                
130
144
                void HAdjustmentValueChanged (object sender, EventArgs args)
131
145
                {
134
148
                
135
149
                protected virtual void HAdjustmentValueChanged ()
136
150
                {
137
 
                        if (this.textEditorData.HAdjustment.Value != System.Math.Ceiling (this.textEditorData.HAdjustment.Value)) {
138
 
                                this.textEditorData.HAdjustment.Value = System.Math.Ceiling (this.textEditorData.HAdjustment.Value);
 
151
                        double value = this.textEditorData.HAdjustment.Value;
 
152
                        if (value != System.Math.Round (value)) {
 
153
                                this.textEditorData.HAdjustment.Value = System.Math.Round (value);
139
154
                                return;
140
155
                        }
141
 
/*                      if (this.containerChildren.Count > 0)
142
 
                                QueueResize ();*/
143
156
                        HideTooltip ();
144
157
                        textViewMargin.HideCodeSegmentPreviewWindow ();
145
 
                        int curHAdjustment = (int)this.textEditorData.HAdjustment.Value;
146
 
                        if (oldHAdjustment == curHAdjustment)
147
 
                                return;
148
 
                        
149
 
                        QueueDrawArea (this.textViewMargin.XOffset, 0, this.Allocation.Width - this.textViewMargin.XOffset, this.Allocation.Height);
 
158
                        QueueDrawArea ((int)this.textViewMargin.XOffset, 0, this.Allocation.Width - (int)this.textViewMargin.XOffset, this.Allocation.Height);
150
159
                        OnHScroll (EventArgs.Empty);
151
160
                }
152
161
                
153
162
                void VAdjustmentValueChanged (object sender, EventArgs args)
154
163
                {
 
164
                        
155
165
                        VAdjustmentValueChanged ();
156
166
                }
157
167
                
159
169
                {
160
170
                        HideTooltip ();
161
171
                        textViewMargin.HideCodeSegmentPreviewWindow ();
162
 
                        
163
 
                        if (this.textEditorData.VAdjustment.Value != System.Math.Ceiling (this.textEditorData.VAdjustment.Value)) {
164
 
                                this.textEditorData.VAdjustment.Value = System.Math.Ceiling (this.textEditorData.VAdjustment.Value);
 
172
                        double value = this.textEditorData.VAdjustment.Value;
 
173
                        if (value != System.Math.Round (value)) {
 
174
                                this.textEditorData.VAdjustment.Value = System.Math.Round (value);
165
175
                                return;
166
176
                        }
167
 
 
168
177
                        if (isMouseTrapped)
169
178
                                FireMotionEvent (mx + textViewMargin.XOffset, my, lastState);
170
179
                        
171
 
                        int delta = (int)(this.textEditorData.VAdjustment.Value - this.oldVadjustment);
172
 
                        oldVadjustment = this.textEditorData.VAdjustment.Value;
 
180
                        double delta = value - this.oldVadjustment;
 
181
                        oldVadjustment = value;
173
182
                        TextViewMargin.caretY -= delta;
174
183
                        
175
184
                        if (System.Math.Abs (delta) >= Allocation.Height - this.LineHeight * 2 || this.TextViewMargin.inSelectionDrag) {
179
188
                        }
180
189
                        
181
190
                        if (GdkWindow != null)
182
 
                                GdkWindow.Scroll (0, -delta);
183
 
/*                      if (delta > 0) {
184
 
                                delta += LineHeight;
185
 
//                              QueueDrawArea (0, Allocation.Height - delta, Allocation.Width, delta);
186
 
                        } else {
187
 
                                delta -= LineHeight;
188
 
//                              QueueDrawArea (0, 0, Allocation.Width, -delta);
189
 
                        }*/
 
191
                                GdkWindow.Scroll (0, (int)-delta);
190
192
                        
191
193
                        OnVScroll (EventArgs.Empty);
192
194
                }
251
253
                        };
252
254
                        doc.TextReplaced += OnDocumentStateChanged;
253
255
                        doc.TextSet += OnTextSet;
 
256
                        doc.LineChanged += UpdateLinesOnTextMarkerHeightChange; 
 
257
                        doc.MarkerAdded += HandleTextEditorDataDocumentMarkerChange;
 
258
                        doc.MarkerRemoved += HandleTextEditorDataDocumentMarkerChange;
254
259
 
255
260
                        textEditorData.CurrentMode = initialMode;
256
261
                        
257
262
//                      this.Events = EventMask.AllEventsMask;
258
263
                        this.Events = EventMask.PointerMotionMask | EventMask.ButtonPressMask | EventMask.ButtonReleaseMask | EventMask.EnterNotifyMask | EventMask.LeaveNotifyMask | EventMask.VisibilityNotifyMask | EventMask.FocusChangeMask | EventMask.ScrollMask | EventMask.KeyPressMask | EventMask.KeyReleaseMask;
259
264
                        this.DoubleBuffered = true;
260
 
                        this.AppPaintable = false;
261
265
                        base.CanFocus = true;
262
 
                        this.RedrawOnAllocate = false;
263
266
                        WidgetFlags |= WidgetFlags.NoWindow;
264
267
                        iconMargin = new IconMargin (this);
265
268
                        gutterMargin = new GutterMargin (this);
266
269
                        dashedLineMargin = new DashedLineMargin (this);
267
 
                        dashedLineMargin.UseBGColor = false;
268
270
                        foldMarkerMargin = new FoldMarkerMargin (this);
269
271
                        textViewMargin = new TextViewMargin (this);
270
272
 
300
302
                                this.textViewMargin.ForceInvalidateLine (Caret.Line);
301
303
                                this.textEditorData.Document.CommitLineUpdate (Caret.Line);
302
304
                        };
 
305
                        
303
306
                        imContext.PreeditChanged += delegate(object sender, EventArgs e) {
304
307
                                if (preeditOffset >= 0) {
305
308
                                        imContext.GetPreeditString (out preeditString, out preeditAttrs, out preeditCursorPos);
308
311
                                }
309
312
                        };
310
313
                        
 
314
                        imContext.RetrieveSurrounding += delegate (object o, RetrieveSurroundingArgs args) {
 
315
                                //use a single line of context, whole document would be very expensive
 
316
                                //FIXME: UTF16 surrogates handling for caret offset? only matters for astral plane
 
317
                                imContext.SetSurrounding (Document.GetLineText (Caret.Line, false), Caret.Column);
 
318
                                args.RetVal = true;
 
319
                        };
 
320
                        
 
321
                        imContext.SurroundingDeleted += delegate (object o, SurroundingDeletedArgs args) {
 
322
                                //FIXME: UTF16 surrogates handling for offset and NChars? only matters for astral plane
 
323
                                var line = Document.GetLine (Caret.Line);
 
324
                                ((IBuffer)Document).Remove (line.Offset + args.Offset, args.NChars);
 
325
                                args.RetVal = true;
 
326
                        };
 
327
                        
311
328
                        using (Pixmap inv = new Pixmap (null, 1, 1, 1)) {
312
329
                                invisibleCursor = new Cursor (inv, inv, Gdk.Color.Zero, Gdk.Color.Zero, 0, 0);
313
330
                        }
314
331
                        
315
332
                        InitAnimations ();
316
333
                        this.Document.EndUndo += HandleDocumenthandleEndUndo;
 
334
#if ATK
 
335
                        TextEditorAccessible.Factory.Init (this);
 
336
#endif
317
337
                }
318
338
 
319
339
                void HandleDocumenthandleEndUndo (object sender, Document.UndoOperationEventArgs e)
332
352
                
333
353
                public void ShowListWindow<T> (ListWindow<T> window, DocumentLocation loc)
334
354
                {
335
 
                        Gdk.Point p = TextViewMargin.LocationToDisplayCoordinates (loc);
 
355
                        var p = LocationToPoint (loc);
336
356
                        int ox = 0, oy = 0;
337
357
                        GdkWindow.GetOrigin (out ox, out oy);
338
358
        
339
 
                        window.Move (ox + p.X - window.TextOffset , oy + p.Y + LineHeight);
 
359
                        window.Move (ox + p.X - window.TextOffset , oy + p.Y + (int)LineHeight);
340
360
                        window.ShowAll ();
341
361
                }
342
362
                
344
364
                internal string preeditString;
345
365
                internal Pango.AttrList preeditAttrs;
346
366
                
 
367
                public int PreeditOffset {
 
368
                        get {
 
369
                                return this.preeditOffset;
 
370
                        }
 
371
                }
 
372
 
 
373
                public string PreeditString {
 
374
                        get {
 
375
                                return this.preeditString;
 
376
                        }
 
377
                }
 
378
 
347
379
                void CaretPositionChanged (object sender, DocumentLocationEventArgs args) 
348
380
                {
349
381
                        HideTooltip ();
435
467
                        OnSelectionChanged (EventArgs.Empty);
436
468
                }
437
469
                
438
 
                void ResetIMContext ()
 
470
                internal void ResetIMContext ()
439
471
                {
440
472
                        if (imContextActive) {
441
473
                                imContext.Reset ();
447
479
                {
448
480
                        try {
449
481
                                if (IsRealized && IsFocus) {
450
 
                                        uint lastChar = Keyval.ToUnicode (lastIMEvent.KeyValue);
451
 
                                        
452
482
                                        //this, if anywhere, is where we should handle UCS4 conversions
453
483
                                        for (int i = 0; i < ca.Str.Length; i++) {
454
484
                                                int utf32Char;
456
486
                                                        utf32Char = char.ConvertToUtf32 (ca.Str, i);
457
487
                                                        i++;
458
488
                                                } else {
459
 
                                                        utf32Char = (int) ca.Str[i];
 
489
                                                        utf32Char = (int)ca.Str [i];
460
490
                                                }
461
491
                                                
462
 
                                                //include the key & state if possible, i.e. if the char matches the unprocessed one
463
 
                                                if (lastChar == utf32Char)
464
 
                                                        OnIMProcessedKeyPressEvent (lastIMEvent.Key, lastChar, lastIMEvent.State);
465
 
                                                else
 
492
                                                //include the other pre-IM state *if* the post-IM char matches the pre-IM (key-mapped) one
 
493
                                                 if (lastIMEventMappedChar == utf32Char && lastIMEventMappedChar == (uint)lastIMEventMappedKey) {
 
494
                                                        OnIMProcessedKeyPressEvent (lastIMEventMappedKey, lastIMEventMappedChar, lastIMEventMappedModifier);
 
495
                                                } else {
466
496
                                                        OnIMProcessedKeyPressEvent ((Gdk.Key)0, (uint)utf32Char, Gdk.ModifierType.None);
 
497
                                                }
467
498
                                        }
468
499
                                }
469
500
                        } finally {
473
504
                
474
505
                protected override bool OnFocusInEvent (EventFocus evnt)
475
506
                {
 
507
                        var result = base.OnFocusInEvent (evnt);
476
508
                        IMContext.FocusIn ();
477
509
                        RequestResetCaretBlink ();
478
 
                        return base.OnFocusInEvent (evnt);
 
510
                        Document.CommitLineUpdate (Caret.Line);
 
511
                        return result;
479
512
                }
480
513
                
481
514
                protected override bool OnFocusOutEvent (EventFocus evnt)
482
515
                {
 
516
                        var result = base.OnFocusOutEvent (evnt);
483
517
                        imContext.FocusOut ();
484
518
                        GLib.Timeout.Add (10, delegate {
485
519
                                // Don't immediately hide the tooltip. Wait a bit and check if the tooltip has the focus.
488
522
                                return false;
489
523
                        });
490
524
                        TextViewMargin.StopCaretThread ();
491
 
                        return base.OnFocusOutEvent (evnt);
 
525
                        Document.CommitLineUpdate (Caret.Line);
 
526
                        return result;
492
527
                }
493
528
                
494
529
                protected override void OnRealized ()
593
628
 
594
629
                protected override void OnDestroyed ()
595
630
                {
596
 
                        base.OnDestroyed ();
597
 
                        
598
 
                        if (isDisposed)
599
 
                                return;
600
 
                        this.isDisposed = true;
601
 
                        
602
 
                        if (this.Document != null)
 
631
                        if (popupWindow != null)
 
632
                                popupWindow.Destroy ();
 
633
                        
 
634
                        if (this.Document != null) {
603
635
                                this.Document.EndUndo -= HandleDocumenthandleEndUndo;
 
636
                                this.Document.TextReplaced -= OnDocumentStateChanged;
 
637
                                this.Document.TextSet -= OnTextSet;
 
638
                                this.Document.LineChanged -= UpdateLinesOnTextMarkerHeightChange; 
 
639
                                this.Document.MarkerAdded -= HandleTextEditorDataDocumentMarkerChange;
 
640
                                this.Document.MarkerRemoved -= HandleTextEditorDataDocumentMarkerChange;
 
641
                        }
604
642
                        
605
643
                        DisposeAnimations ();
606
644
                        
607
645
                        RemoveScrollWindowTimer ();
608
 
                        if (invisibleCursor != null) {
 
646
                        if (invisibleCursor != null)
609
647
                                invisibleCursor.Dispose ();
610
 
                                invisibleCursor = null;
611
 
                        }
 
648
                        
612
649
                        Caret.PositionChanged -= CaretPositionChanged;
613
650
                        
614
651
                        Document.DocumentUpdated -= DocumentUpdatedHandler;
617
654
 
618
655
                        imContext = imContext.Kill (x => x.Commit -= IMCommit);
619
656
 
620
 
                        if (this.textEditorData.HAdjustment != null) {
 
657
                        if (this.textEditorData.HAdjustment != null)
621
658
                                this.textEditorData.HAdjustment.ValueChanged -= HAdjustmentValueChanged;
622
 
                                this.textEditorData.HAdjustment = null;
623
 
                        }
624
 
                        if (this.textEditorData.VAdjustment != null) {
 
659
                        
 
660
                        if (this.textEditorData.VAdjustment != null)
625
661
                                this.textEditorData.VAdjustment.ValueChanged -= VAdjustmentValueChanged;
626
 
                                this.textEditorData.VAdjustment = null;
 
662
                        
 
663
                        foreach (Margin margin in this.margins) {
 
664
                                if (margin is IDisposable)
 
665
                                        ((IDisposable)margin).Dispose ();
627
666
                        }
628
667
                        
629
 
                        if (margins != null) {
630
 
                                foreach (Margin margin in this.margins) {
631
 
                                        if (margin is IDisposable)
632
 
                                                ((IDisposable)margin).Dispose ();
633
 
                                }
634
 
                                this.margins = null;
635
 
                        }
636
 
 
637
 
                        iconMargin = null; 
638
 
                        gutterMargin = null;
639
 
                        dashedLineMargin = null;
640
 
                        foldMarkerMargin = null;
641
 
                        textViewMargin = null;
642
 
                        this.textEditorData = this.textEditorData.Kill (x => x.SelectionChanged -= TextEditorDataSelectionChanged);
 
668
                        this.textEditorData.SelectionChanged -= TextEditorDataSelectionChanged;
 
669
                        this.textEditorData.Dispose (); 
643
670
                        this.Realized -= OptionsChanged;
644
671
                        
 
672
                        base.OnDestroyed ();
645
673
                }
646
674
                
647
675
                internal void RedrawMargin (Margin margin)
648
676
                {
649
677
                        if (isDisposed)
650
678
                                return;
651
 
                        QueueDrawArea (margin.XOffset, 0, GetMarginWidth (margin),  this.Allocation.Height);
 
679
                        QueueDrawArea ((int)margin.XOffset, 0, GetMarginWidth (margin),  this.Allocation.Height);
652
680
                }
653
681
                
654
682
                public void RedrawMarginLine (Margin margin, int logicalLine)
656
684
                        if (isDisposed)
657
685
                                return;
658
686
                        
659
 
                        int y = LineToVisualY (logicalLine) - (int)this.textEditorData.VAdjustment.Value;
660
 
                        int h = GetLineHeight (logicalLine);
 
687
                        double y = LineToY (logicalLine) - this.textEditorData.VAdjustment.Value;
 
688
                        double h = GetLineHeight (logicalLine);
661
689
                        
662
690
                        if (y + h > 0)
663
 
                                QueueDrawArea (margin.XOffset, y, GetMarginWidth (margin), h);
 
691
                                QueueDrawArea ((int)margin.XOffset, (int)y, (int)GetMarginWidth (margin), (int)h);
664
692
                }
665
693
 
666
694
                int GetMarginWidth (Margin margin)
667
695
                {
668
696
                        if (margin.Width < 0)
669
 
                                return Allocation.Width - margin.XOffset;
670
 
                        return margin.Width;
 
697
                                return Allocation.Width - (int)margin.XOffset;
 
698
                        return (int)margin.Width;
671
699
                }
672
700
                
673
701
                internal void RedrawLine (int logicalLine)
675
703
                        if (isDisposed)
676
704
                                return;
677
705
                        
678
 
                        int y = LineToVisualY (logicalLine) - (int)this.textEditorData.VAdjustment.Value;
679
 
                        int h = GetLineHeight (logicalLine);
 
706
                        double y = LineToY (logicalLine) - this.textEditorData.VAdjustment.Value;
 
707
                        double h = GetLineHeight (logicalLine);
680
708
                        
681
709
                        if (y + h > 0)
682
 
                                QueueDrawArea (0, y, this.Allocation.Width, h);
 
710
                                QueueDrawArea (0, (int)y, this.Allocation.Width, (int)h);
683
711
                }
684
712
                
685
713
                public new void QueueDrawArea (int x, int y, int w, int h)
714
742
                                return;
715
743
                        if (start < 0)
716
744
                                start = 0;
717
 
                        int visualStart = (int)-this.textEditorData.VAdjustment.Value + LineToVisualY (start);
 
745
                        double visualStart = -this.textEditorData.VAdjustment.Value + LineToY (start);
718
746
                        if (end < 0)
719
 
                                end = Document.LineCount - 1;
720
 
                        int visualEnd   = (int)-this.textEditorData.VAdjustment.Value + LineToVisualY (end) + GetLineHeight (end);
721
 
                        QueueDrawArea (margin.XOffset, visualStart, GetMarginWidth (margin), visualEnd - visualStart);
 
747
                                end = Document.LineCount;
 
748
                        double visualEnd   = -this.textEditorData.VAdjustment.Value + LineToY (end) + GetLineHeight (end);
 
749
                        QueueDrawArea ((int)margin.XOffset, (int)visualStart, GetMarginWidth (margin), (int)(visualEnd - visualStart));
722
750
                }
723
751
                        
724
752
                internal void RedrawLines (int start, int end)
728
756
                                return;
729
757
                        if (start < 0)
730
758
                                start = 0;
731
 
                        int visualStart = (int)-this.textEditorData.VAdjustment.Value + Document.LogicalToVisualLine (start) * LineHeight;
 
759
                        double visualStart = -this.textEditorData.VAdjustment.Value +  LineToY (start);
732
760
                        if (end < 0)
733
 
                                end = Document.LineCount - 1;
734
 
                        int visualEnd   = (int)-this.textEditorData.VAdjustment.Value + Document.LogicalToVisualLine (end) * LineHeight + LineHeight;
735
 
                        QueueDrawArea (0, visualStart, this.Allocation.Width, visualEnd - visualStart);
 
761
                                end = Document.LineCount;
 
762
                        double visualEnd   = -this.textEditorData.VAdjustment.Value + LineToY (end) + GetLineHeight (end);
 
763
                        QueueDrawArea (0, (int)visualStart, this.Allocation.Width, (int)(visualEnd - visualStart));
736
764
                }
737
765
                
738
766
                public void RedrawFromLine (int logicalLine)
740
768
//                      Console.WriteLine ("Redraw from line: logicalLine={0}", logicalLine);
741
769
                        if (isDisposed)
742
770
                                return;
743
 
                        QueueDrawArea (0, (int)-this.textEditorData.VAdjustment.Value + LineToVisualY (logicalLine),
744
 
                                       this.Allocation.Width, this.Allocation.Height);
 
771
                        int y = System.Math.Max (0, (int)(-this.textEditorData.VAdjustment.Value + LineToY (logicalLine)));
 
772
                        QueueDrawArea (0, y,
 
773
                                       this.Allocation.Width, this.Allocation.Height - y);
745
774
                }
746
775
                
747
776
                public void RunAction (Action<TextEditorData> action)
753
782
                        }
754
783
                }
755
784
                
 
785
                /// <summary>Handles key input after key mapping and input methods.</summary>
 
786
                /// <param name="key">The mapped keycode.</param>
 
787
                /// <param name="unicodeChar">A UCS4 character. If this is nonzero, it overrides the keycode.</param>
 
788
                /// <param name="modifier">Keyboard modifier, excluding any consumed by key mapping or IM.</param>
756
789
                public void SimulateKeyPress (Gdk.Key key, uint unicodeChar, ModifierType modifier)
757
790
                {
758
 
                        ModifierType filteredModifiers = modifier & (ModifierType.ShiftMask | ModifierType.Mod1Mask | ModifierType.ControlMask | ModifierType.MetaMask | ModifierType.SuperMask);
759
 
                        
760
 
                        ModifierType modifiersThatPermitChars = ModifierType.ShiftMask;
761
 
                        if (Platform.IsMac)
762
 
                                modifiersThatPermitChars |= ModifierType.Mod1Mask;
763
 
                        
764
 
                        if ((filteredModifiers & ~modifiersThatPermitChars) != 0)
765
 
                                unicodeChar = 0;
766
 
                        
 
791
                        ModifierType filteredModifiers = modifier & (ModifierType.ShiftMask | ModifierType.Mod1Mask
 
792
                                 | ModifierType.ControlMask | ModifierType.MetaMask | ModifierType.SuperMask);
767
793
                        CurrentMode.InternalHandleKeypress (this, textEditorData, key, unicodeChar, filteredModifiers);
768
794
                        RequestResetCaretBlink ();
769
795
                }
770
796
                
771
 
                bool IMFilterKeyPress (Gdk.EventKey evt)
 
797
                bool IMFilterKeyPress (Gdk.EventKey evt, Gdk.Key mappedKey, uint mappedChar, Gdk.ModifierType mappedModifiers)
772
798
                {
773
799
                        if (lastIMEvent == evt)
774
800
                                return false;
775
801
                        
776
 
                        if (evt.Type == EventType.KeyPress)
 
802
                        if (evt.Type == EventType.KeyPress) {
777
803
                                lastIMEvent = evt;
 
804
                                lastIMEventMappedChar = mappedChar;
 
805
                                lastIMEventMappedKey = mappedKey;
 
806
                                lastIMEventMappedModifier = mappedModifiers;
 
807
                        }
778
808
                        
779
809
                        if (imContext.FilterKeypress (evt)) {
780
810
                                imContextActive = true;
796
826
                {
797
827
                        ModifierType mod;
798
828
                        Gdk.Key key;
799
 
                        Platform.MapRawKeys (evt, out key, out mod);
800
 
                        
 
829
                        uint keyVal;
 
830
                        Platform.MapRawKeys (evt, out key, out mod, out keyVal);
801
831
                        if (key == Gdk.Key.F1 && (mod & (ModifierType.ControlMask | ModifierType.ShiftMask)) == ModifierType.ControlMask) {
802
 
                                Point p = textViewMargin.LocationToDisplayCoordinates (Caret.Location);
 
832
                                var p = LocationToPoint (Caret.Location);
803
833
                                ShowTooltip (Gdk.ModifierType.None, Caret.Offset, p.X, p.Y);
804
834
                                return true;
805
835
                        }
809
839
                                return true;
810
840
                        }
811
841
                        
812
 
                        uint unicodeChar = Gdk.Keyval.ToUnicode (evt.KeyValue);
 
842
                        uint unicodeChar = Gdk.Keyval.ToUnicode (keyVal);
 
843
                        
813
844
                        if (CurrentMode.WantsToPreemptIM || CurrentMode.PreemptIM (key, unicodeChar, mod)) {
814
845
                                ResetIMContext ();      
815
846
                                SimulateKeyPress (key, unicodeChar, mod);
816
847
                                return true;
817
848
                        }
818
 
                        bool filter = IMFilterKeyPress (evt);
 
849
                        bool filter = IMFilterKeyPress (evt, key, unicodeChar, mod);
819
850
                        if (!filter) {
820
851
                                return OnIMProcessedKeyPressEvent (key, unicodeChar, mod);
821
852
                        }
833
864
                
834
865
                protected override bool OnKeyReleaseEvent (EventKey evnt)
835
866
                {
836
 
                        if (IMFilterKeyPress (evnt))
 
867
                        if (IMFilterKeyPress (evnt, 0, 0, ModifierType.None))
837
868
                                imContextActive = true;
838
869
                        return true;
839
870
                }
840
871
                
841
 
                int mouseButtonPressed = 0;
 
872
                uint mouseButtonPressed = 0;
842
873
                uint lastTime;
843
 
                int  pressPositionX, pressPositionY;
 
874
                double pressPositionX, pressPositionY;
844
875
                protected override bool OnButtonPressEvent (Gdk.EventButton e)
845
876
                {
846
 
                        pressPositionX = (int)e.X;
847
 
                        pressPositionY = (int)e.Y;
 
877
                        pressPositionX = e.X;
 
878
                        pressPositionY = e.Y;
848
879
                        base.IsFocus = true;
849
880
                        if (lastTime != e.Time) {// filter double clicks
850
881
                                if (e.Type == EventType.TwoButtonPress) {
852
883
                                }Ā else {
853
884
                                        lastTime = 0;
854
885
                                }
855
 
                                mouseButtonPressed = (int) e.Button;
856
 
                                int startPos;
857
 
                                Margin margin = GetMarginAtX ((int)e.X, out startPos);
858
 
                                if (margin != null) {
859
 
                                        margin.MousePressed (new MarginMouseEventArgs (this, (int)e.Button, (int)(e.X - startPos), (int)e.Y, e.Type, e.State));
860
 
                                }
 
886
                                mouseButtonPressed = e.Button;
 
887
                                double startPos;
 
888
                                Margin margin = GetMarginAtX (e.X, out startPos);
 
889
                                if (margin != null) 
 
890
                                        margin.MousePressed (new MarginMouseEventArgs (this, e.Button, e.X - startPos, e.Y, e.Type, e.State));
861
891
                        }
862
892
                        return base.OnButtonPressEvent (e);
863
893
                }
872
902
                        set;
873
903
                }
874
904
                
875
 
                Margin GetMarginAtX (int x, out int startingPos)
 
905
                Margin GetMarginAtX (double x, out double startingPos)
876
906
                {
877
 
                        int curX = 0;
 
907
                        double curX = 0;
878
908
                        foreach (Margin margin in this.margins) {
879
909
                                if (!margin.IsVisible)
880
910
                                        continue;
898
928
                protected override bool OnButtonReleaseEvent (EventButton e)
899
929
                {
900
930
                        RemoveScrollWindowTimer ();
901
 
                        int startPos;
902
 
                        Margin margin = GetMarginAtX ((int)e.X, out startPos);
 
931
                        double startPos;
 
932
                        Margin margin = GetMarginAtX (e.X, out startPos);
903
933
                        if (margin != null)
904
 
                                margin.MouseReleased (new MarginMouseEventArgs (this, (int)e.Button, (int)(e.X - startPos), (int)e.Y, EventType.ButtonRelease, e.State));
 
934
                                margin.MouseReleased (new MarginMouseEventArgs (this, e.Button, e.X - startPos, e.Y, EventType.ButtonRelease, e.State));
905
935
                        ResetMouseState ();
906
936
                        return base.OnButtonReleaseEvent (e);
907
937
                }
962
992
                                        textEditorData.DeleteSelection (selection);
963
993
                                        Caret.PreserveSelection = false;
964
994
 
965
 
                                        if (this.textEditorData.IsSomethingSelected && selection.GetSelectionRange (textEditorData).Offset <= this.textEditorData.SelectionRange.Offset) {
966
 
                                                this.textEditorData.SelectionRange = new Segment (this.textEditorData.SelectionRange.Offset - selection.GetSelectionRange (textEditorData).Length, this.textEditorData.SelectionRange.Length);
967
 
                                                this.textEditorData.SelectionMode = selection.SelectionMode;
968
 
                                        }
969
995
                                        selection = null;
970
996
                                }
971
997
                        }
986
1012
                                dragOver = false;
987
1013
                                context = null;
988
1014
                        }
 
1015
                        mouseButtonPressed = 0;
989
1016
                        textEditorData.Document.EndAtomicUndo ();
990
1017
                        base.OnDragDataReceived (context, x, y, selection_data, info, time_);
991
1018
                }
1001
1028
                        DocumentLocation oldLocation = Caret.Location;
1002
1029
                        dragOver = true;
1003
1030
                        Caret.PreserveSelection = true;
1004
 
                        dragCaretPos = VisualToDocumentLocation (x - textViewMargin.XOffset, y);
 
1031
                        dragCaretPos = PointToLocation (x - textViewMargin.XOffset, y);
1005
1032
                        int offset = Document.LocationToOffset (dragCaretPos);
1006
1033
                        if (selection != null && offset >= this.selection.GetSelectionRange (textEditorData).Offset && offset < this.selection.GetSelectionRange (textEditorData).EndOffset) {
1007
1034
                                Gdk.Drag.Status (context, DragAction.Default, time);
1025
1052
                        double x = e.X;
1026
1053
                        double y = e.Y;
1027
1054
                        Gdk.ModifierType mod = e.State;
1028
 
                        int startPos;
1029
 
                        Margin margin = GetMarginAtX ((int)x, out startPos);
1030
 
                        if (textViewMargin.inDrag && margin == this.textViewMargin && Gtk.Drag.CheckThreshold (this, pressPositionX, pressPositionY, (int)x, (int)y)) {
 
1055
                        double startPos;
 
1056
                        Margin margin = GetMarginAtX (x, out startPos);
 
1057
                        if (textViewMargin.inDrag && margin == this.textViewMargin && Gtk.Drag.CheckThreshold (this, (int)pressPositionX, (int)pressPositionY, (int)x, (int)y)) {
1031
1058
                                dragContents = new ClipboardActions.CopyOperation ();
1032
1059
                                dragContents.CopyData (textEditorData);
1033
1060
                                DragContext context = Gtk.Drag.Begin (this, ClipboardActions.CopyOperation.targetList, DragAction.Move | DragAction.Copy, 1, e);
1034
 
                                CodeSegmentPreviewWindow window = new CodeSegmentPreviewWindow (this, true, textEditorData.SelectionRange, 300, 300);
1035
 
 
1036
 
                                Gtk.Drag.SetIconWidget (context, window, 0, 0);
 
1061
                                if (!Platform.IsMac) {
 
1062
                                        CodeSegmentPreviewWindow window = new CodeSegmentPreviewWindow (this, true, textEditorData.SelectionRange, 300, 300);
 
1063
                                        Gtk.Drag.SetIconWidget (context, window, 0, 0);
 
1064
                                }
1037
1065
                                selection = Selection.Clone (MainSelection);
1038
1066
                                textViewMargin.inDrag = false;
1039
 
                                
1040
1067
                        } else {
1041
1068
                                FireMotionEvent (x, y, mod);
1042
1069
                                if (mouseButtonPressed != 0) {
1082
1109
 
1083
1110
                        ShowTooltip (state);
1084
1111
 
1085
 
                        int startPos;
 
1112
                        double startPos;
1086
1113
                        Margin margin;
1087
1114
                        if (textViewMargin.inSelectionDrag) {
1088
1115
                                margin = textViewMargin;
1089
1116
                                startPos = textViewMargin.XOffset;
1090
1117
                        } else {
1091
 
                                margin = GetMarginAtX ((int)x, out startPos);
 
1118
                                margin = GetMarginAtX (x, out startPos);
1092
1119
                                if (margin != null && GdkWindow != null)
1093
1120
                                        GdkWindow.Cursor = margin.MarginCursor;
1094
1121
                        }
1097
1124
                                oldMargin.MouseLeft ();
1098
1125
                        
1099
1126
                        if (margin != null) 
1100
 
                                margin.MouseHover (new MarginMouseEventArgs (this, mouseButtonPressed, (int)(x - startPos), (int)y, EventType.MotionNotify, state));
 
1127
                                margin.MouseHover (new MarginMouseEventArgs (this, mouseButtonPressed, x - startPos, y, EventType.MotionNotify, state));
1101
1128
                        oldMargin = margin;
1102
1129
                }
1103
1130
 
1141
1168
                        
1142
1169
                        textViewMargin.HideCodeSegmentPreviewWindow ();
1143
1170
                        
1144
 
                        if (e.Mode == CrossingMode.Normal) {
1145
 
                                if (GdkWindow != null)
1146
 
                                        GdkWindow.Cursor = null;
1147
 
                                if (oldMargin != null)
1148
 
                                        oldMargin.MouseLeft ();
1149
 
                        }
 
1171
                        if (GdkWindow != null)
 
1172
                                GdkWindow.Cursor = null;
 
1173
                        if (oldMargin != null)
 
1174
                                oldMargin.MouseLeft ();
 
1175
                        
1150
1176
                        return base.OnLeaveNotifyEvent (e); 
1151
1177
                }
1152
1178
 
1153
 
                public int LineHeight {
 
1179
                public double LineHeight {
1154
1180
                        get {
1155
1181
                                if (this.textViewMargin == null)
1156
1182
                                        return 16;
1168
1194
                        get { return iconMargin; }
1169
1195
                }
1170
1196
                
1171
 
                public Gdk.Point DocumentToVisualLocation (DocumentLocation loc)
1172
 
                {
1173
 
                        Gdk.Point result = new Point ();
1174
 
                        LineSegment lineSegment = Document.GetLine (loc.Line);
1175
 
                        result.X = textViewMargin.ColumnToVisualX (lineSegment, loc.Column);
1176
 
                        result.Y = LineToVisualY (loc.Line);
1177
 
                        return result;
1178
 
                }
1179
 
                
1180
 
                public DocumentLocation VisualToDocumentLocation (int x, int y)
1181
 
                {
1182
 
                        return this.textViewMargin.VisualToDocumentLocation (x, y);
1183
 
                }
1184
 
                
1185
1197
                public DocumentLocation LogicalToVisualLocation (DocumentLocation location)
1186
1198
                {
1187
1199
                        return Document.LogicalToVisualLocation (this.textEditorData, location);
1204
1216
                
1205
1217
                public void CenterTo (DocumentLocation p)
1206
1218
                {
1207
 
                        if (isDisposed || p.Line < 0 || p.Line >= Document.LineCount)
 
1219
                        if (isDisposed || p.Line < 0 || p.Line > Document.LineCount)
1208
1220
                                return;
1209
1221
                        SetAdjustments (this.Allocation);
1210
1222
                        //                      Adjustment adj;
1215
1227
                        }
1216
1228
                        
1217
1229
                        //      int yMargin = 1 * this.LineHeight;
1218
 
                        int caretPosition = LineToVisualY (p.Line);
 
1230
                        double caretPosition = LineToY (p.Line);
1219
1231
                        this.textEditorData.VAdjustment.Value = caretPosition - this.textEditorData.VAdjustment.PageSize / 2;
1220
1232
                        
1221
1233
                        if (this.textEditorData.HAdjustment.Upper < Allocation.Width)  {
1222
1234
                                this.textEditorData.HAdjustment.Value = 0;
1223
1235
                        } else {
1224
 
                                int caretX = textViewMargin.ColumnToVisualX (Document.GetLine (p.Line), p.Column);
1225
 
                                int textWith = Allocation.Width - textViewMargin.XOffset;
 
1236
                                double caretX = ColumnToX (Document.GetLine (p.Line), p.Column);
 
1237
                                double textWith = Allocation.Width - textViewMargin.XOffset;
1226
1238
                                if (this.textEditorData.HAdjustment.Value > caretX) {
1227
1239
                                        this.textEditorData.HAdjustment.Value = caretX;
1228
1240
                                } else if (this.textEditorData.HAdjustment.Value + textWith < caretX + TextViewMargin.CharWidth) {
1229
 
                                        int adjustment = System.Math.Max (0, caretX - textWith + TextViewMargin.CharWidth);
 
1241
                                        double adjustment = System.Math.Max (0, caretX - textWith + TextViewMargin.CharWidth);
1230
1242
                                        this.textEditorData.HAdjustment.Value = adjustment;
1231
1243
                                }
1232
1244
                        }
1244
1256
                
1245
1257
                public void ScrollTo (DocumentLocation p)
1246
1258
                {
1247
 
                        if (isDisposed || p.Line < 0 || p.Line >= Document.LineCount || inCaretScroll)
 
1259
                        if (isDisposed || p.Line < 0 || p.Line > Document.LineCount || inCaretScroll)
1248
1260
                                return;
1249
1261
                        inCaretScroll = true;
1250
1262
                        try {
1251
1263
                                if (this.textEditorData.VAdjustment.Upper < Allocation.Height) {
1252
1264
                                        this.textEditorData.VAdjustment.Value = 0;
1253
1265
                                } else {
1254
 
                                        int yMargin = 1 * this.LineHeight;
1255
 
                                        int caretPosition = LineToVisualY (p.Line);
 
1266
                                        double yMargin = 1 * this.LineHeight;
 
1267
                                        double caretPosition = LineToY (p.Line);
1256
1268
                                        if (this.textEditorData.VAdjustment.Value > caretPosition) {
1257
1269
                                                this.textEditorData.VAdjustment.Value = caretPosition;
1258
1270
                                        } else if (this.textEditorData.VAdjustment.Value + this.textEditorData.VAdjustment.PageSize - this.LineHeight < caretPosition + yMargin) {
1263
1275
                                if (this.textEditorData.HAdjustment.Upper < Allocation.Width)  {
1264
1276
                                        this.textEditorData.HAdjustment.Value = 0;
1265
1277
                                } else {
1266
 
                                        int caretX = textViewMargin.ColumnToVisualX (Document.GetLine (p.Line), p.Column);
1267
 
                                        int textWith = Allocation.Width - textViewMargin.XOffset;
 
1278
                                        double caretX = ColumnToX (Document.GetLine (p.Line), p.Column);
 
1279
                                        double textWith = Allocation.Width - textViewMargin.XOffset;
1268
1280
                                        if (this.textEditorData.HAdjustment.Value > caretX) {
1269
1281
                                                this.textEditorData.HAdjustment.Value = caretX;
1270
1282
                                        } else if (this.textEditorData.HAdjustment.Value + textWith < caretX + TextViewMargin.CharWidth) {
1271
 
                                                int adjustment = System.Math.Max (0, caretX - textWith + TextViewMargin.CharWidth);
 
1283
                                                double adjustment = System.Math.Max (0, caretX - textWith + TextViewMargin.CharWidth);
1272
1284
                                                this.textEditorData.HAdjustment.Value = adjustment;
1273
1285
                                        }
1274
1286
                                }
1285
1297
                
1286
1298
                public void TryToResetHorizontalScrollPosition ()
1287
1299
                {
1288
 
                        int caretX = textViewMargin.ColumnToVisualX (Document.GetLine (Caret.Line), Caret.Column);
1289
 
                        int textWith = Allocation.Width - textViewMargin.XOffset;
 
1300
                        int caretX = (int)ColumnToX (Document.GetLine (Caret.Line), Caret.Column);
 
1301
                        int textWith = Allocation.Width - (int)textViewMargin.XOffset;
1290
1302
                        if (caretX < textWith - TextViewMargin.CharWidth) 
1291
1303
                                this.textEditorData.HAdjustment.Value = 0;
1292
1304
                }
1304
1316
                                this.GdkWindow.MoveResize (allocation);
1305
1317
                        SetAdjustments (Allocation);
1306
1318
                        QueueDraw ();
1307
 
                        textViewMargin.SetClip ();
1308
1319
                }
1309
1320
                
1310
1321
                protected override bool OnScrollEvent (EventScroll evnt)
1334
1345
                                return;
1335
1346
                        textEditorData.HAdjustment.ValueChanged -= HAdjustmentValueChanged;
1336
1347
                        if (longestLine != null && this.textEditorData.HAdjustment != null) {
1337
 
                                int maxX = longestLineWidth;
 
1348
                                double maxX = longestLineWidth;
1338
1349
                                if (maxX > Allocation.Width)
1339
1350
                                        maxX += 2 * this.textViewMargin.CharWidth;
1340
 
                                int width = Allocation.Width - this.TextViewMargin.XOffset;
 
1351
                                double width = Allocation.Width - this.TextViewMargin.XOffset;
1341
1352
                                this.textEditorData.HAdjustment.SetBounds (0, maxX, this.textViewMargin.CharWidth, width, width);
1342
1353
                                if (maxX < width)
1343
1354
                                        this.textEditorData.HAdjustment.Value = 0;
1353
1364
                internal void SetAdjustments (Gdk.Rectangle allocation)
1354
1365
                {
1355
1366
                        if (this.textEditorData.VAdjustment != null) {
1356
 
                                int maxY = LineToVisualY (Document.LineCount - 1);
 
1367
                                double maxY = Document.LineCount > 1 ? LineToY (Document.LineCount) : 0;
 
1368
                                
 
1369
                                maxY += LineHeight;
 
1370
                                
1357
1371
                                if (maxY > allocation.Height)
1358
1372
                                        maxY += 5 * this.LineHeight;
1359
1373
                                
1373
1387
                        return this.textViewMargin.GetWidth (text);
1374
1388
                }
1375
1389
                
1376
 
                void RenderMargins (Gdk.Drawable win, Gdk.Rectangle area)
 
1390
                void UpdateMarginXOffsets ()
1377
1391
                {
1378
 
                        this.TextViewMargin.rulerX = Options.RulerColumn * this.TextViewMargin.CharWidth - (int)this.textEditorData.HAdjustment.Value;
1379
 
                        int reminder  = (int)this.textEditorData.VAdjustment.Value % LineHeight;
1380
 
                        int startLine = CalculateLineNumber (area.Top - reminder + (int)this.textEditorData.VAdjustment.Value);
1381
 
                        int startY = LineToVisualY (startLine);
1382
 
                        if (area.Top == 0 && startY > 0) {
1383
 
                                startLine--;
1384
 
                                startY -= GetLineHeight (Document.GetLine (startLine));
 
1392
                        double curX = 0;
 
1393
                        foreach (Margin margin in this.margins) {
 
1394
                                if (!margin.IsVisible)
 
1395
                                        continue;
 
1396
                                margin.XOffset = curX;
 
1397
                                curX += margin.Width;
1385
1398
                        }
1386
 
                        
1387
 
                        int curX = 0;
1388
 
                        int curY = startY - (int)this.textEditorData.VAdjustment.Value;
 
1399
                }
 
1400
                
 
1401
                void RenderMargins (Cairo.Context cr, Cairo.Context textViewCr, Cairo.Rectangle cairoRectangle)
 
1402
                {
 
1403
                        this.TextViewMargin.rulerX = Options.RulerColumn * this.TextViewMargin.CharWidth - this.textEditorData.HAdjustment.Value;
 
1404
                        int startLine = YToLine (cairoRectangle.Y + this.textEditorData.VAdjustment.Value);
 
1405
                        double startY = LineToY (startLine);
 
1406
                        double curY = startY - this.textEditorData.VAdjustment.Value;
1389
1407
                        bool setLongestLine = false;
1390
 
                        bool renderFirstLine = true;
1391
1408
                        for (int visualLineNumber = startLine; ; visualLineNumber++) {
1392
1409
                                int logicalLineNumber = visualLineNumber;
1393
1410
                                LineSegment line      = Document.GetLine (logicalLineNumber);
1394
 
                                int lineHeight        = GetLineHeight (line);
1395
 
                                int lastFold = -1;
 
1411
                                double lineHeight     = GetLineHeight (line);
 
1412
                                int lastFold = 0;
1396
1413
                                foreach (FoldSegment fs in Document.GetStartFoldings (line).Where (fs => fs.IsFolded)) {
1397
1414
                                        lastFold = System.Math.Max (fs.EndOffset, lastFold);
1398
1415
                                }
1399
 
                                if (lastFold > 0) 
 
1416
                                if (lastFold >= DocumentLocation.MinLine)
1400
1417
                                        visualLineNumber = Document.OffsetToLineNumber (lastFold);
1401
1418
                                foreach (Margin margin in this.margins) {
1402
1419
                                        if (!margin.IsVisible)
1403
1420
                                                continue;
1404
1421
                                        try {
1405
 
                                                if (renderFirstLine)
1406
 
                                                        margin.XOffset = curX;
1407
 
                                                margin.Draw (win, area, logicalLineNumber, margin.XOffset, curY, lineHeight);
1408
 
                                                margin.EndRender (win, area, margin.XOffset);
1409
 
                                                if (renderFirstLine)
1410
 
                                                        curX += margin.Width;
 
1422
                                                margin.Draw (margin == textViewMargin ? textViewCr : cr, cairoRectangle, line, logicalLineNumber, margin.XOffset, curY, lineHeight);
1411
1423
                                        } catch (Exception e) {
1412
1424
                                                System.Console.WriteLine (e);
1413
1425
                                        }
1414
1426
                                }
1415
 
                                renderFirstLine = false;
1416
1427
                                // take the line real render width from the text view margin rendering (a line can consist of more than 
1417
1428
                                // one line and be longer (foldings!) ex. : someLine1[...]someLine2[...]someLine3)
1418
 
                                int lineWidth = textViewMargin.lastLineRenderWidth + (int)HAdjustment.Value;
 
1429
                                double lineWidth = textViewMargin.lastLineRenderWidth + HAdjustment.Value;
1419
1430
                                if (longestLine == null || lineWidth > longestLineWidth) {
1420
1431
                                        longestLine = line;
1421
1432
                                        longestLineWidth = lineWidth;
1422
1433
                                        setLongestLine = true;
1423
1434
                                }
1424
1435
                                curY += lineHeight;
1425
 
                                if (curY > area.Bottom)
 
1436
                                if (curY > cairoRectangle.Y + cairoRectangle.Height)
1426
1437
                                        break;
1427
1438
                        }
1428
1439
                        
1430
1441
                                if (!margin.IsVisible)
1431
1442
                                        continue;
1432
1443
                                foreach (var drawer in margin.MarginDrawer)
1433
 
                                        drawer.Draw (win, area);
 
1444
                                        drawer.Draw (cr, cairoRectangle);
1434
1445
                        }
1435
1446
                        
1436
1447
                        if (setLongestLine) 
1437
1448
                                SetHAdjustment ();
1438
 
 
1439
1449
                }
 
1450
                
1440
1451
                /*
1441
1452
                protected override bool OnWidgetEvent (Event evnt)
1442
1453
                {
1448
1459
                
1449
1460
                void UpdateAdjustments ()
1450
1461
                {
1451
 
                        int lastVisibleLine = Document.LogicalToVisualLine (Document.LineCount - 1);
 
1462
                        int lastVisibleLine = Document.LogicalToVisualLine (Document.LineCount);
1452
1463
                        if (oldRequest != lastVisibleLine) {
1453
1464
                                SetAdjustments (this.Allocation);
1454
1465
                                oldRequest = lastVisibleLine;
1464
1475
                                return true;
1465
1476
                        UpdateAdjustments ();
1466
1477
                        
1467
 
                        RenderMargins (e.Window, e.Region.Clipbox);
 
1478
                        var area = e.Region.Clipbox;
 
1479
                        var cairoArea = new Cairo.Rectangle (area.X, area.Y, area.Width, area.Height);
 
1480
                        using (Cairo.Context cr = Gdk.CairoHelper.Create (e.Window))
 
1481
                        using (Cairo.Context textViewCr = Gdk.CairoHelper.Create (e.Window)) {
 
1482
                                UpdateMarginXOffsets ();
 
1483
                                
 
1484
                                cr.LineWidth = Options.Zoom;
 
1485
                                textViewCr.LineWidth = Options.Zoom;
 
1486
                                textViewCr.Rectangle (textViewMargin.XOffset, 0, Allocation.Width - textViewMargin.XOffset, Allocation.Height);
 
1487
                                textViewCr.Clip ();
 
1488
                                
 
1489
                                RenderMargins (cr, textViewCr, cairoArea);
1468
1490
                        
1469
1491
#if DEBUG_EXPOSE
1470
 
                        Console.WriteLine ("{0} expose {1},{2} {3}x{4}", (long)(DateTime.Now - started).TotalMilliseconds,
1471
 
                                           e.Area.X, e.Area.Y, e.Area.Width, e.Area.Height);
 
1492
                                Console.WriteLine ("{0} expose {1},{2} {3}x{4}", (long)(DateTime.Now - started).TotalMilliseconds,
 
1493
                                        e.Area.X, e.Area.Y, e.Area.Width, e.Area.Height);
1472
1494
#endif
1473
 
                        if (requestResetCaretBlink) {
1474
 
                                textViewMargin.ResetCaretBlink ();
1475
 
                                requestResetCaretBlink = false;
1476
 
                        }
1477
 
                        
1478
 
                        foreach (Animation animation in actors) {
1479
 
                                animation.Drawer.Draw (e.Window);
1480
 
                        }
1481
 
                        
1482
 
                        if (e.Area.Contains (TextViewMargin.caretX, TextViewMargin.caretY))
1483
 
                                textViewMargin.DrawCaret (e.Window);
 
1495
                                if (requestResetCaretBlink && HasFocus) {
 
1496
                                        textViewMargin.ResetCaretBlink ();
 
1497
                                        requestResetCaretBlink = false;
 
1498
                                }
 
1499
                                
 
1500
                                foreach (Animation animation in actors) {
 
1501
                                        animation.Drawer.Draw (cr);
 
1502
                                }
 
1503
                                
 
1504
                                if (HasFocus && e.Area.Contains ((int)TextViewMargin.caretX, (int)TextViewMargin.caretY))
 
1505
                                        textViewMargin.DrawCaret (e.Window);
 
1506
                                
 
1507
                                OnPainted (new PaintEventArgs (cr, cairoArea));
 
1508
                        }
1484
1509
                        
1485
1510
                        return true;
1486
1511
                }
1487
 
 
1488
 
                #region TextEditorData functions
 
1512
                
 
1513
                protected virtual void OnPainted (PaintEventArgs e)
 
1514
                {
 
1515
                        EventHandler<PaintEventArgs> handler = this.Painted;
 
1516
                        if (handler != null)
 
1517
                                handler (this, e);
 
1518
                }
 
1519
 
 
1520
                public event EventHandler<PaintEventArgs> Painted;
 
1521
 
 
1522
                #region TextEditorData delegation
 
1523
                public string EolMarker {
 
1524
                        get {
 
1525
                                return textEditorData.EolMarker;
 
1526
                        }
 
1527
                }
 
1528
                
1489
1529
                public Mono.TextEditor.Highlighting.Style ColorStyle {
1490
1530
                        get {
1491
1531
                                return this.textEditorData.ColorStyle;
1575
1615
                        return textEditorData.Insert (offset, value);
1576
1616
                }
1577
1617
                
 
1618
                public void Remove (ISegment removeSegment)
 
1619
                {
 
1620
                        textEditorData.Remove (removeSegment);
 
1621
                }
 
1622
                
1578
1623
                public void Remove (int offset, int count)
1579
1624
                {
1580
1625
                        textEditorData.Remove (offset, count);
1638
1683
                        return textEditorData.CanEdit (line);
1639
1684
                }
1640
1685
                
 
1686
                public string GetLineText (int line)
 
1687
                {
 
1688
                        return textEditorData.GetLineText (line);
 
1689
                }
 
1690
                
 
1691
                public string GetLineText (int line, bool includeDelimiter)
 
1692
                {
 
1693
                        return textEditorData.GetLineText (line, includeDelimiter);
 
1694
                }
1641
1695
                
1642
1696
                /// <summary>
1643
1697
                /// Use with care.
1659
1713
                }
1660
1714
                #endregion
1661
1715
                
 
1716
                #region Document delegation
 
1717
                public int Length {
 
1718
                        get {
 
1719
                                return Document.Length;
 
1720
                        }
 
1721
                }
 
1722
 
 
1723
                public string Text {
 
1724
                        get {
 
1725
                                return Document.Text;
 
1726
                        }
 
1727
                        set {
 
1728
                                Document.Text = value;
 
1729
                        }
 
1730
                }
 
1731
 
 
1732
                public string GetTextBetween (int startOffset, int endOffset)
 
1733
                {
 
1734
                        return Document.GetTextBetween (startOffset, endOffset);
 
1735
                }
 
1736
                
 
1737
                public string GetTextBetween (DocumentLocation start, DocumentLocation end)
 
1738
                {
 
1739
                        return Document.GetTextBetween (start, end);
 
1740
                }
 
1741
                
 
1742
                public string GetTextBetween (int startLine, int startColumn, int endLine, int endColumn)
 
1743
                {
 
1744
                        return Document.GetTextBetween (startLine, startColumn, endLine, endColumn);
 
1745
                }
 
1746
 
 
1747
                public string GetTextAt (int offset, int count)
 
1748
                {
 
1749
                        return Document.GetTextAt (offset, count);
 
1750
                }
 
1751
 
 
1752
                public string GetTextAt (ISegment segment)
 
1753
                {
 
1754
                        return Document.GetTextAt (segment);
 
1755
                }
 
1756
                
 
1757
                public char GetCharAt (int offset)
 
1758
                {
 
1759
                        return Document.GetCharAt (offset);
 
1760
                }
 
1761
                
 
1762
                public IEnumerable<LineSegment> Lines {
 
1763
                        get {
 
1764
                                return Document.Lines;
 
1765
                        }
 
1766
                }
 
1767
                
 
1768
                public int LineCount {
 
1769
                        get {
 
1770
                                return Document.LineCount;
 
1771
                        }
 
1772
                }
 
1773
                
 
1774
                public int LocationToOffset (int line, int column)
 
1775
                {
 
1776
                        return Document.LocationToOffset (line, column);
 
1777
                }
 
1778
                
 
1779
                public int LocationToOffset (DocumentLocation location)
 
1780
                {
 
1781
                        return Document.LocationToOffset (location);
 
1782
                }
 
1783
                
 
1784
                public DocumentLocation OffsetToLocation (int offset)
 
1785
                {
 
1786
                        return Document.OffsetToLocation (offset);
 
1787
                }
 
1788
 
 
1789
                public string GetLineIndent (int lineNumber)
 
1790
                {
 
1791
                        return Document.GetLineIndent (lineNumber);
 
1792
                }
 
1793
                
 
1794
                public string GetLineIndent (LineSegment segment)
 
1795
                {
 
1796
                        return Document.GetLineIndent (segment);
 
1797
                }
 
1798
                
 
1799
                public LineSegment GetLine (int lineNumber)
 
1800
                {
 
1801
                        return Document.GetLine (lineNumber);
 
1802
                }
 
1803
                
 
1804
                public LineSegment GetLineByOffset (int offset)
 
1805
                {
 
1806
                        return Document.GetLineByOffset (offset);
 
1807
                }
 
1808
                
 
1809
                public int OffsetToLineNumber (int offset)
 
1810
                {
 
1811
                        return Document.OffsetToLineNumber (offset);
 
1812
                }
 
1813
                #endregion
 
1814
                
1662
1815
                #region Search & Replace
1663
1816
                
1664
1817
                bool highlightSearchPattern = false;
1700
1853
                        }
1701
1854
                }
1702
1855
                
1703
 
                public bool IsCaseSensitive {
 
1856
                public bool IsCaseSensitive {
1704
1857
                        get {
1705
 
                                return this.textEditorData.SearchRequest.CaseSensitive;
1706
 
                        }
 
1858
                                return this.textEditorData.SearchRequest.CaseSensitive;
 
1859
                        }
1707
1860
                        set {
1708
 
                                this.textEditorData.SearchRequest.CaseSensitive = value;
1709
 
                        }
1710
 
                }
 
1861
                                this.textEditorData.SearchRequest.CaseSensitive = value;
 
1862
                        }
 
1863
                }
1711
1864
                
1712
 
                public bool IsWholeWordOnly {
1713
 
                        get {
1714
 
                                return this.textEditorData.SearchRequest.WholeWordOnly;
1715
 
                        }
1716
 
                        
1717
 
                        set {
1718
 
                                this.textEditorData.SearchRequest.WholeWordOnly = value;
1719
 
                        }
 
1865
                public bool IsWholeWordOnly {
 
1866
                        get {
 
1867
                                return this.textEditorData.SearchRequest.WholeWordOnly;
 
1868
                        }
 
1869
                        
 
1870
                        set {
 
1871
                                this.textEditorData.SearchRequest.WholeWordOnly = value;
 
1872
                        }
1720
1873
                }
1721
1874
                
1722
1875
                public SearchResult SearchForward (int fromOffset)
1729
1882
                        return textEditorData.SearchBackward (fromOffset);
1730
1883
                }
1731
1884
                
1732
 
                class HighlightSearchResultAnimation : IAnimationDrawer, IDisposable
1733
 
                {
1734
 
                        TextEditor editor;
1735
 
                        SearchResult result;
1736
 
                        Gdk.Pixbuf textImage = null;
1737
 
                        
1738
 
                        public double Percent { get; set; }
1739
 
                        
1740
 
                        public HighlightSearchResultAnimation (TextEditor editor, SearchResult result)
1741
 
                        {
1742
 
                                this.editor = editor;
1743
 
                                this.result = result;
1744
 
                        }
1745
 
                        
1746
 
                        public Gdk.Rectangle AnimationBounds {
1747
 
                                get {
1748
 
//                                      LineSegment line = editor.Document.GetLineByOffset (result.Offset);
1749
 
                                        int lineNr = editor.Document.OffsetToLineNumber (result.Offset);
1750
 
                                        int y = editor.LineToVisualY (lineNr) - (int)editor.VAdjustment.Value;
1751
 
                                        return new Gdk.Rectangle (0, y - editor.LineHeight , editor.Allocation.Width, editor.LineHeight * 3);
1752
 
                                }
1753
 
                        }
1754
 
                        
1755
 
                        public void Draw (Drawable drawable)
1756
 
                        {
1757
 
                                LineSegment line = editor.Document.GetLineByOffset (result.Offset);
1758
 
                                int lineNr = editor.Document.OffsetToLineNumber (result.Offset);
1759
 
                                SyntaxMode mode = editor.Document.SyntaxMode != null && editor.Options.EnableSyntaxHighlighting ? editor.Document.SyntaxMode : SyntaxMode.Default;
1760
 
                                
1761
 
                                TextViewMargin.LayoutWrapper lineLayout = editor.textViewMargin.CreateLinePartLayout (mode, line, line.Offset, line.EditableLength, -1, -1);
1762
 
                                if (lineLayout == null)
1763
 
                                        return;
1764
 
                                int l, x1, x2;
1765
 
                                int index = result.Offset - line.Offset - 1;
1766
 
                                if (index >= 0) {
1767
 
                                        lineLayout.Layout.IndexToLineX (index, true, out l, out x1);
1768
 
                                } else {
1769
 
                                        l = x1 = 0;
1770
 
                                }
1771
 
                                index = result.Offset - line.Offset - 1 + result.Length;
1772
 
                                if (index <= 0) 
1773
 
                                        index = 1;
1774
 
                                lineLayout.Layout.IndexToLineX (index, true, out l, out x2);
1775
 
                                x1 /= (int)Pango.Scale.PangoScale;
1776
 
                                x2 /= (int)Pango.Scale.PangoScale;
1777
 
                                int y = editor.LineToVisualY (lineNr) - (int)editor.VAdjustment.Value;
1778
 
                                using (Cairo.Context cr = Gdk.CairoHelper.Create (drawable)) {
1779
 
                                        cr.Rectangle (editor.TextViewMargin.XOffset, 0, editor.Allocation.Width - editor.TextViewMargin.XOffset, editor.Allocation.Height);
1780
 
                                        cr.Clip ();
1781
 
                        
1782
 
                                        
1783
 
                                        int width = (int)(x2 - x1);
1784
 
                                        int border = 2;
1785
 
                                        int rx = (int)(editor.TextViewMargin.XOffset - editor.HAdjustment.Value + x1 - border);
1786
 
                                        int ry = (int)(y) - border;
1787
 
                                        int rw = width + border * 2;
1788
 
                                        int rh = (int)(editor.LineHeight) + border * 2;
1789
 
                                        
1790
 
                                        int iw = width, ih = editor.LineHeight;
1791
 
                                        if (textImage == null) {
1792
 
                                                using (Gdk.Pixmap pixmap = new Gdk.Pixmap (drawable, iw, ih)) {
1793
 
                                                        using (var bgGc = new Gdk.GC(pixmap)) {
1794
 
                                                                bgGc.RgbFgColor = editor.ColorStyle.SearchTextMainBg;
1795
 
                                                                pixmap.DrawRectangle (bgGc, true, 0, 0, iw, ih);
1796
 
                                                                using (var layout = PangoUtil.CreateLayout (editor)) {
1797
 
                                                                        layout.FontDescription = editor.Options.Font;
1798
 
                                                                        layout.SetMarkup (editor.Document.SyntaxMode.GetMarkup (editor.Document, editor.Options, editor.ColorStyle, result.Offset, result.Length, true));
1799
 
                                                                        pixmap.DrawLayout (bgGc, 0, 0, layout);
1800
 
                                                                }
1801
 
                                                        }
1802
 
                                                        textImage = Pixbuf.FromDrawable (pixmap, Colormap.System, 0, 0, 0, 0, iw, ih);
1803
 
                                                }
1804
 
                                        }
1805
 
                                        
1806
 
                                        cr.Translate (rx + rw / 2, ry + rh / 2);
1807
 
                                        /*cr.Save ();
1808
 
                                        Cairo.Color color = Mono.TextEditor.Highlighting.Style.ToCairoColor (editor.ColorStyle.SearchTextBg);
1809
 
                                        cr.Color = color;
1810
 
                                        double scale2 = (1 + 1.1 * Percent / 6);
1811
 
                                        cr.Scale (scale2, scale2 * 1.2);
1812
 
                                        
1813
 
                                        FoldingScreenbackgroundRenderer.DrawRoundRectangle (cr, true, true, -rw / 2, -rh / 2, (int)(System.Math.Min (10, width ) * editor.Options.Zoom), rw, rh);
1814
 
                                        cr.Fill (); 
1815
 
                                        cr.Restore ();*/
1816
 
                                        
1817
 
                                        double scale = 1 + Percent / 12;
1818
 
                                        cr.Scale (scale, scale);
1819
 
                                        double textx = -rw / 2;
1820
 
                                        double texty = -rh / 2;
1821
 
                                        cr.TransformPoint (ref textx, ref texty);
1822
 
                                        
1823
 
                                        double textr = +rw / 2;
1824
 
                                        double textb = +rh / 2;
1825
 
                                        cr.TransformPoint (ref textr, ref textb);
1826
 
                                        
1827
 
                                        cr.Color = new Cairo.Color (0, 0, 0, 0.3);
1828
 
                                        //because the initial highlight is not rounded, so the rounding scales to make the transition smoother
1829
 
                                        int rounding = (int)(-rw / 2 + 2 * editor.Options.Zoom * Percent);
1830
 
                                        FoldingScreenbackgroundRenderer.DrawRoundRectangle (cr, true, true, rounding, (int)(-rh / 2 + 2 * editor.Options.Zoom), (int)(System.Math.Min (10, width ) * editor.Options.Zoom), rw, rh);
1831
 
                                        cr.Fill (); 
1832
 
                                        
1833
 
                                        cr.Color = Mono.TextEditor.Highlighting.Style.ToCairoColor (editor.ColorStyle.SearchTextMainBg);
1834
 
                                        FoldingScreenbackgroundRenderer.DrawRoundRectangle (cr, true, true, -rw / 2, -rh / 2, (int)(System.Math.Min (10, width ) * editor.Options.Zoom), rw, rh);
1835
 
                                        cr.Fill ();
1836
 
                                        
1837
 
                                        int tx, ty, tw, th;
1838
 
                                        tw = (int) System.Math.Ceiling (iw * scale);
1839
 
                                        th = (int) System.Math.Ceiling (ih * scale);
1840
 
                                        tx = rx - (int) System.Math.Ceiling ((double)(tw - iw) / 2) + border;
1841
 
                                        ty = ry - (int) System.Math.Ceiling ((double)(th - ih) / 2) + border;
1842
 
                                        try {
1843
 
                                                using (var scaled = textImage.ScaleSimple (tw, th, InterpType.Bilinear)) {
1844
 
                                                        if (scaled != null) {
1845
 
                                                                using (var gc = new Gdk.GC (drawable)) {
1846
 
                                                                        gc.ClipRectangle = new Rectangle (editor.TextViewMargin.XOffset, 0, editor.Allocation.Width - editor.TextViewMargin.XOffset, editor.Allocation.Height);
1847
 
                                                                        scaled.RenderToDrawable (drawable, gc, 0, 0, tx, ty, tw, th, RgbDither.None, 0, 0);
1848
 
                                                                }
1849
 
                                                        }
1850
 
                                                }
1851
 
                                        } catch (Exception e) {
1852
 
                                                Console.WriteLine ("got exception in search result animation:" + e);
1853
 
                                        }
1854
 
                                }
1855
 
                                
1856
 
                                if (lineLayout.IsUncached) 
1857
 
                                        lineLayout.Dispose ();
1858
 
                        }
1859
 
                        
1860
 
                        public void Dispose ()
1861
 
                        {
1862
 
                                if (this.textImage != null) {
1863
 
                                        this.textImage.Dispose ();
1864
 
                                        this.textImage = null;
1865
 
                                }
1866
 
                        }
1867
 
                        
1868
 
                }
1869
 
                
1870
1885
                class CaretPulseAnimation : IAnimationDrawer
1871
1886
                {
1872
1887
                        TextEditor editor;
1875
1890
                        
1876
1891
                        public Gdk.Rectangle AnimationBounds {
1877
1892
                                get {
1878
 
                                        int x = editor.TextViewMargin.caretX;
1879
 
                                        int y = editor.TextViewMargin.caretY;
 
1893
                                        double x = editor.TextViewMargin.caretX;
 
1894
                                        double y = editor.TextViewMargin.caretY;
1880
1895
                                        double extend = 100 * 5;
1881
1896
                                        int width = (int)(editor.TextViewMargin.charWidth + 2 * extend * editor.Options.Zoom / 2);
1882
1897
                                        return new Gdk.Rectangle ((int)(x - extend * editor.Options.Zoom / 2), 
1891
1906
                                this.editor = editor;
1892
1907
                        }
1893
1908
                        
1894
 
                        public void Draw (Drawable drawable)
 
1909
                        public void Draw (Cairo.Context cr)
1895
1910
                        {
1896
 
                                int x = editor.TextViewMargin.caretX;
1897
 
                                int y = editor.TextViewMargin.caretY;
 
1911
                                double x = editor.TextViewMargin.caretX;
 
1912
                                double y = editor.TextViewMargin.caretY;
1898
1913
                                if (editor.Caret.Mode != CaretMode.Block)
1899
1914
                                        x -= editor.TextViewMargin.charWidth / 2;
1900
 
                                using (Cairo.Context cr = Gdk.CairoHelper.Create (drawable)) {
1901
 
                                        cr.Rectangle (editor.TextViewMargin.XOffset, 0, editor.Allocation.Width - editor.TextViewMargin.XOffset, editor.Allocation.Height);
1902
 
                                        cr.Clip ();
 
1915
                                cr.Rectangle (editor.TextViewMargin.XOffset, 0, editor.Allocation.Width - editor.TextViewMargin.XOffset, editor.Allocation.Height);
 
1916
                                cr.Clip ();
1903
1917
 
1904
 
                                        double extend = Percent * 5;
1905
 
                                        int width = (int)(editor.TextViewMargin.charWidth + 2 * extend * editor.Options.Zoom / 2);
1906
 
                                        FoldingScreenbackgroundRenderer.DrawRoundRectangle (cr, true, true, 
1907
 
                                                                                            (int)(x - extend * editor.Options.Zoom / 2), 
1908
 
                                                                                            (int)(y - extend * editor.Options.Zoom), 
1909
 
                                                                                            System.Math.Min (editor.TextViewMargin.charWidth / 2, width), 
1910
 
                                                                                            width,
1911
 
                                                                                            (int)(editor.LineHeight + 2 * extend * editor.Options.Zoom));
1912
 
                                        Cairo.Color color = Mono.TextEditor.Highlighting.Style.ToCairoColor (editor.ColorStyle.Caret.Color);
1913
 
                                        color.A = 0.8;
1914
 
                                        cr.LineWidth = editor.Options.Zoom;
1915
 
                                        cr.Color = color;
1916
 
                                        cr.Stroke ();
1917
 
                                }
 
1918
                                double extend = Percent * 5;
 
1919
                                double width = editor.TextViewMargin.charWidth + 2 * extend * editor.Options.Zoom / 2;
 
1920
                                FoldingScreenbackgroundRenderer.DrawRoundRectangle (cr, true, true, 
 
1921
                                                                                    x - extend * editor.Options.Zoom / 2, 
 
1922
                                                                                    y - extend * editor.Options.Zoom, 
 
1923
                                                                                    System.Math.Min (editor.TextViewMargin.charWidth / 2, width), 
 
1924
                                                                                    width,
 
1925
                                                                                    editor.LineHeight + 2 * extend * editor.Options.Zoom);
 
1926
                                Cairo.Color color = Mono.TextEditor.Highlighting.Style.ToCairoColor (editor.ColorStyle.Caret.Color);
 
1927
                                color.A = 0.8;
 
1928
                                cr.LineWidth = editor.Options.Zoom;
 
1929
                                cr.Color = color;
 
1930
                                cr.Stroke ();
 
1931
                                cr.ResetClip ();
1918
1932
                        }
1919
1933
                }
1920
1934
                
1957
1971
                                this.region = region;
1958
1972
                        }
1959
1973
                        
1960
 
                        public void Draw (Drawable drawable)
 
1974
                        public void Draw (Cairo.Context cr)
1961
1975
                        {
1962
1976
                                int x = region.X;
1963
1977
                                int y = region.Y;
1964
1978
                                int animationPosition = (int)(Percent * 100);
1965
1979
                                
1966
 
                                using (Cairo.Context cr = Gdk.CairoHelper.Create (drawable)) {
1967
 
                                        cr.Rectangle (editor.TextViewMargin.XOffset, 0, editor.Allocation.Width - editor.TextViewMargin.XOffset, editor.Allocation.Height);
1968
 
                                        cr.Clip ();
 
1980
                                cr.Rectangle (editor.TextViewMargin.XOffset, 0, editor.Allocation.Width - editor.TextViewMargin.XOffset, editor.Allocation.Height);
 
1981
                                cr.Clip ();
1969
1982
 
1970
 
                                        int width = (int)(region.Width + 2 * animationPosition * editor.Options.Zoom / 2);
1971
 
                                        FoldingScreenbackgroundRenderer.DrawRoundRectangle (cr, true, true, 
1972
 
                                                                                            (int)(x - animationPosition * editor.Options.Zoom / 2), 
1973
 
                                                                                            (int)(y - animationPosition * editor.Options.Zoom), 
1974
 
                                                                                            System.Math.Min (editor.TextViewMargin.charWidth / 2, width), 
1975
 
                                                                                            width,
1976
 
                                                                                            (int)(region.Height + 2 * animationPosition * editor.Options.Zoom));
1977
 
                                        Cairo.Color color = Mono.TextEditor.Highlighting.Style.ToCairoColor (editor.ColorStyle.Caret.Color);
1978
 
                                        color.A = 0.8;
1979
 
                                        cr.LineWidth = editor.Options.Zoom;
1980
 
                                        cr.Color = color;
1981
 
                                        cr.Stroke ();
1982
 
                                }
 
1983
                                int width = (int)(region.Width + 2 * animationPosition * editor.Options.Zoom / 2);
 
1984
                                FoldingScreenbackgroundRenderer.DrawRoundRectangle (cr, true, true, 
 
1985
                                                                                    (int)(x - animationPosition * editor.Options.Zoom / 2), 
 
1986
                                                                                    (int)(y - animationPosition * editor.Options.Zoom), 
 
1987
                                                                                    System.Math.Min (editor.TextViewMargin.charWidth / 2, width), 
 
1988
                                                                                    width,
 
1989
                                                                                    (int)(region.Height + 2 * animationPosition * editor.Options.Zoom));
 
1990
                                Cairo.Color color = Mono.TextEditor.Highlighting.Style.ToCairoColor (editor.ColorStyle.Caret.Color);
 
1991
                                color.A = 0.8;
 
1992
                                cr.LineWidth = editor.Options.Zoom;
 
1993
                                cr.Color = color;
 
1994
                                cr.Stroke ();
 
1995
                                cr.ResetClip ();
1983
1996
                        }
1984
1997
                }
1985
1998
                
1986
 
        /*      Gdk.Rectangle RangeToRectangle (int offset, int length)
1987
 
                {
1988
 
                        DocumentLocation startLocation = Document.OffsetToLocation (offset);
1989
 
                        DocumentLocation endLocation = Document.OffsetToLocation (offset + length);
1990
 
                        
1991
 
                        if (startLocation.Column < 0 || startLocation.Line < 0 || endLocation.Column < 0 || endLocation.Line < 0)
1992
 
                                return Gdk.Rectangle.Zero;
1993
 
                        
1994
 
                        return RangeToRectangle (startLocation, endLocation);
1995
 
                }*/
1996
 
                
1997
1999
                Gdk.Rectangle RangeToRectangle (DocumentLocation start, DocumentLocation end)
1998
2000
                {
1999
2001
                        if (start.Column < 0 || start.Line < 0 || end.Column < 0 || end.Line < 0)
2000
2002
                                return Gdk.Rectangle.Zero;
2001
2003
                        
2002
 
                        Gdk.Point startPt = this.textViewMargin.LocationToDisplayCoordinates (start);
2003
 
                        Gdk.Point endPt = this.textViewMargin.LocationToDisplayCoordinates (end);
 
2004
                        var startPt = this.LocationToPoint (start);
 
2005
                        var endPt = this.LocationToPoint (end);
2004
2006
                        int width = endPt.X - startPt.X;
2005
2007
                        
2006
2008
                        if (startPt.Y != endPt.Y || startPt.X < 0 || startPt.Y < 0 || width < 0)
2007
2009
                                return Gdk.Rectangle.Zero;
2008
2010
                        
2009
 
                        return new Gdk.Rectangle (startPt.X, startPt.Y, width, this.textViewMargin.LineHeight);
 
2011
                        return new Gdk.Rectangle (startPt.X, startPt.Y, width, (int)this.textViewMargin.LineHeight);
2010
2012
                }
2011
2013
                
2012
 
        /*      void AnimationTimer (object sender, EventArgs args)
2013
 
                {
2014
 
                        if (animation != null) {
2015
 
                                animation.LifeTime--;
2016
 
                                if (animation.LifeTime < 0)
2017
 
                                        animation = null;
2018
 
                                Application.Invoke (delegate {
2019
 
                                        QueueDraw ();
2020
 
                                });
2021
 
                        } else {
2022
 
                                animationTimer.Stop ();
2023
 
                        }
2024
 
                }*/
2025
 
                
2026
2014
                /// <summary>
2027
2015
                /// Initiate a pulse at the specified document location
2028
2016
                /// </summary>
2047
2035
                        SearchResult result = textEditorData.FindNext (setSelection);
2048
2036
                        TryToResetHorizontalScrollPosition ();
2049
2037
                        AnimateSearchResult (result);
2050
 
                        
2051
2038
                        return result;
2052
2039
                }
2053
2040
 
2055
2042
                {
2056
2043
                        StartAnimation (new TextEditor.CaretPulseAnimation (this));
2057
2044
                }
2058
 
                
2059
 
                Animation searchResultAnimation;
 
2045
 
 
2046
                SearchHighlightPopupWindow popupWindow = null;
 
2047
                
 
2048
                public void StopSearchResultAnimation ()
 
2049
                {
 
2050
                        if (popupWindow == null)
 
2051
                                return;
 
2052
                        popupWindow.StopPlaying ();
 
2053
                }
 
2054
                
2060
2055
                public void AnimateSearchResult (SearchResult result)
2061
2056
                {
 
2057
                        if (!IsComposited || !Options.EnableAnimations)
 
2058
                                return;
2062
2059
                        TextViewMargin.MainSearchResult = result;
2063
2060
                        if (result != null) {
2064
 
                                if (searchResultAnimation != null) 
2065
 
                                        RemoveAnimation (searchResultAnimation);
2066
 
                                var anim = new TextEditor.HighlightSearchResultAnimation (this, result);
2067
 
                                searchResultAnimation = StartAnimation (anim, 180, Easing.Sine);
2068
 
                        }
2069
 
                }
2070
 
        
 
2061
                                if (popupWindow != null) {
 
2062
                                        popupWindow.StopPlaying ();
 
2063
                                        popupWindow.Destroy ();
 
2064
                                }
 
2065
                                popupWindow = new SearchHighlightPopupWindow (this);
 
2066
                                popupWindow.Result = result;
 
2067
                                popupWindow.Popup ();
 
2068
                                popupWindow.Destroyed += delegate {
 
2069
                                        popupWindow = null;
 
2070
                                };
 
2071
                        }
 
2072
                }
 
2073
                
 
2074
                class SearchHighlightPopupWindow : BounceFadePopupWindow
 
2075
                {
 
2076
                        public SearchResult Result {
 
2077
                                get;
 
2078
                                set;
 
2079
                        }
 
2080
                        
 
2081
                        public SearchHighlightPopupWindow (TextEditor editor) : base (editor)
 
2082
                        {
 
2083
                        }
 
2084
                        
 
2085
                        public override void Popup ()
 
2086
                        {
 
2087
                                ExpandWidth = (uint)Editor.LineHeight;
 
2088
                                ExpandHeight = (uint)Editor.LineHeight / 2;
 
2089
                                BounceEasing = Easing.Sine;
 
2090
                                Duration = 150;
 
2091
                                base.Popup ();
 
2092
                        }
 
2093
                        
 
2094
                        protected override void OnAnimationCompleted ()
 
2095
                        {
 
2096
                                Move (Screen.Width, Screen.Height);
 
2097
                                base.OnAnimationCompleted ();
 
2098
                                DetachEvents ();
 
2099
                                Destroy ();
 
2100
                        }
 
2101
                        
 
2102
                        internal override void StopPlaying ()
 
2103
                        {
 
2104
                                Move (Screen.Width, Screen.Height);
 
2105
                                base.StopPlaying ();
 
2106
                        }
 
2107
 
 
2108
                        protected override void OnDestroyed ()
 
2109
                        {
 
2110
                                base.OnDestroyed ();
 
2111
                                if (layout != null)
 
2112
                                        layout.Dispose ();
 
2113
                        }
 
2114
                        
 
2115
                        protected override Rectangle CalculateInitialBounds ()
 
2116
                        {
 
2117
                                LineSegment line = Editor.Document.GetLineByOffset (Result.Offset);
 
2118
                                int lineNr = Editor.Document.OffsetToLineNumber (Result.Offset);
 
2119
                                SyntaxMode mode = Editor.Document.SyntaxMode != null && Editor.Options.EnableSyntaxHighlighting ? Editor.Document.SyntaxMode : SyntaxMode.Default;
 
2120
                                int logicalRulerColumn = line.GetLogicalColumn(Editor.GetTextEditorData(), Editor.Options.RulerColumn);
 
2121
                                var lineLayout = Editor.textViewMargin.CreateLinePartLayout(mode, line, logicalRulerColumn, line.Offset, line.EditableLength, -1, -1);
 
2122
                                if (lineLayout == null)
 
2123
                                        return Gdk.Rectangle.Zero;
 
2124
                                
 
2125
                                int l, x1, x2;
 
2126
                                int index = Result.Offset - line.Offset - 1;
 
2127
                                if (index >= 0) {
 
2128
                                        lineLayout.Layout.IndexToLineX (index, true, out l, out x1);
 
2129
                                } else {
 
2130
                                        l = x1 = 0;
 
2131
                                }
 
2132
                                
 
2133
                                index = Result.Offset - line.Offset - 1 + Result.Length;
 
2134
                                if (index >= 0) {
 
2135
                                        lineLayout.Layout.IndexToLineX (index, true, out l, out x2);
 
2136
                                } else {
 
2137
                                        x2 = 0;
 
2138
                                        Console.WriteLine ("Invalid end index :" + index);
 
2139
                                }
 
2140
                                
 
2141
                                double y = Editor.LineToY (lineNr) - Editor.VAdjustment.Value ;
 
2142
                                double w = (x2 - x1) / Pango.Scale.PangoScale;
 
2143
                                double spaceX = System.Math.Ceiling (w / 3);
 
2144
                                double spaceY = Editor.LineHeight;
 
2145
                                if (layout != null)
 
2146
                                        layout.Dispose ();
 
2147
                                
 
2148
                                return new Gdk.Rectangle ((int)(x1 / Pango.Scale.PangoScale + Editor.TextViewMargin.XOffset + Editor.TextViewMargin.TextStartPosition - Editor.HAdjustment.Value - spaceX), 
 
2149
                                        (int)(y - spaceY), 
 
2150
                                        (int)(w + spaceX * 2), 
 
2151
                                        (int)(Editor.LineHeight + spaceY * 2));
 
2152
                        }
 
2153
                        
 
2154
                        Pango.Layout layout = null;
 
2155
                        int layoutWidth, layoutHeight;
 
2156
                        
 
2157
                        protected override bool OnExposeEvent (Gdk.EventExpose evnt)
 
2158
                        {
 
2159
                                try {
 
2160
                                        using (var cr = Gdk.CairoHelper.Create (evnt.Window)) {
 
2161
                                                cr.SetSourceRGBA (1, 1, 1, 0);
 
2162
                                                cr.Operator = Cairo.Operator.Source; 
 
2163
                                                cr.Paint ();
 
2164
                                        }
 
2165
                                        using (var cr = Gdk.CairoHelper.Create (evnt.Window)) {
 
2166
                                                cr.Translate (width / 2, height / 2);
 
2167
                                                cr.Scale (1 + scale / 4, 1 + scale / 4);
 
2168
                                                if (layout == null) {
 
2169
                                                        layout = cr.CreateLayout ();
 
2170
                                                        layout.FontDescription = Editor.Options.Font;
 
2171
                                                        string markup = Editor.Document.SyntaxMode.GetMarkup (Editor.Document, Editor.Options, Editor.ColorStyle, Result.Offset, Result.Length, true);
 
2172
                                                        layout.SetMarkup (markup);
 
2173
                                                        layout.GetPixelSize (out layoutWidth, out layoutHeight);
 
2174
                                                }
 
2175
                                                
 
2176
                                                FoldingScreenbackgroundRenderer.DrawRoundRectangle (cr, true, true, -layoutWidth / 2 - 2 + 2, -Editor.LineHeight / 2 + 2, System.Math.Min (10, layoutWidth), layoutWidth + 4, Editor.LineHeight);
 
2177
                                                var color = TextViewMargin.DimColor (Editor.ColorStyle.SearchTextMainBg, 0.3);
 
2178
                                                color.A = 0.5 * opacity;
 
2179
                                                cr.Color = color;
 
2180
                                                cr.Fill (); 
 
2181
                                                
 
2182
                                                FoldingScreenbackgroundRenderer.DrawRoundRectangle (cr, true, true, -layoutWidth / 2 -2, -Editor.LineHeight / 2, System.Math.Min (10, layoutWidth), layoutWidth + 4, Editor.LineHeight);
 
2183
                                                using (var gradient = new Cairo.LinearGradient (0, -Editor.LineHeight / 2, 0, Editor.LineHeight / 2)) {
 
2184
                                                        color = TextViewMargin.DimColor (Editor.ColorStyle.SearchTextMainBg, 1.1);
 
2185
                                                        color.A = opacity;
 
2186
                                                        gradient.AddColorStop (0, color);
 
2187
                                                        color = TextViewMargin.DimColor (Editor.ColorStyle.SearchTextMainBg, 0.9);
 
2188
                                                        color.A = opacity;
 
2189
                                                        gradient.AddColorStop (1, color);
 
2190
                                                        cr.Pattern = gradient;
 
2191
                                                        cr.Fill (); 
 
2192
                                                }
 
2193
                                                cr.Color = new Cairo.Color (0, 0, 0);
 
2194
                                                cr.Translate (-layoutWidth / 2, -layoutHeight / 2);
 
2195
                                                cr.ShowLayout (layout);
 
2196
                                        }
 
2197
                                        
 
2198
                                } catch (Exception e) {
 
2199
                                        Console.WriteLine ("Exception in animation:" + e);
 
2200
                                }
 
2201
                                return true;
 
2202
                        }
 
2203
                }
 
2204
                
2071
2205
                public SearchResult FindPrevious (bool setSelection)
2072
2206
                {
2073
2207
                        SearchResult result = textEditorData.FindPrevious (setSelection);
2113
2247
 
2114
2248
                void ShowTooltip (Gdk.ModifierType modifierState)
2115
2249
                {
 
2250
                        var loc = PointToLocation (mx, my);
 
2251
                        if (loc.IsEmpty)
 
2252
                                return;
 
2253
                        
 
2254
                        // Hide editor tooltips for text marker extended regions (message bubbles)
 
2255
                        double y = LineToY (loc.Line);
 
2256
                        if (y + LineHeight < my) {
 
2257
                                HideTooltip ();
 
2258
                                return;
 
2259
                        }
 
2260
                        
2116
2261
                        ShowTooltip (modifierState, 
2117
 
                                     Document.LocationToOffset (VisualToDocumentLocation ((int)mx, (int)my)),
 
2262
                                     Document.LocationToOffset (loc),
2118
2263
                                     (int)mx,
2119
2264
                                     (int)my);
2120
2265
                }
2223
2368
                        provider.GetRequiredPosition (this, liw, out w, out xalign);
2224
2369
                        w += 10;
2225
2370
                        
2226
 
                        int x = xloc + ox + textViewMargin.XOffset - (int) ((double)w * xalign);
 
2371
                        int x = xloc + ox + (int)textViewMargin.XOffset - (int) ((double)w * xalign);
2227
2372
                        Gdk.Rectangle geometry = Screen.GetMonitorGeometry (Screen.GetMonitorAtPoint (ox + xloc, oy + yloc));
2228
2373
                        
2229
2374
                        if (x + w >= geometry.Right)
2284
2429
                                        longest = line;
2285
2430
                        }
2286
2431
                        if (longest != longestLine) {
2287
 
                                int width = textViewMargin.ColumnToVisualX (longest, longest.EditableLength);
 
2432
                                int width = (int)(textViewMargin.GetLayout (longest).PangoWidth / Pango.Scale.PangoScale);
 
2433
                                
2288
2434
                                if (width > this.longestLineWidth) {
2289
2435
                                        this.longestLineWidth = width;
2290
2436
                                        this.longestLine = longest;
2292
2438
                        }
2293
2439
                }
2294
2440
                #endregion
2295
 
 
2296
 
                
2297
 
/*#region Container
2298
 
                public override ContainerChild this [Widget w] {
2299
 
                        get {
2300
 
                                foreach (EditorContainerChild info in containerChildren.ToArray ()) {
2301
 
                                        if (info.Child == w || (info.Child is AnimatedWidget && ((AnimatedWidget)info.Child).Widget == w))
2302
 
                                                return info;
2303
 
                                }
2304
 
                                return null;
2305
 
                        }
2306
 
                }
2307
 
                
2308
 
                public class EditorContainerChild : Container.ContainerChild
2309
 
                {
2310
 
                        public int X { get; set; }
2311
 
                        public int Y { get; set; }
2312
 
                        public bool FixedPosition { get; set; }
2313
 
                        public EditorContainerChild (Container parent, Widget child) : base (parent, child)
2314
 
                        {
2315
 
                        }
2316
 
                }
2317
 
                
2318
 
                public override GLib.GType ChildType ()
2319
 
                {
2320
 
                        return Gtk.Widget.GType;
2321
 
                }
2322
 
                
2323
 
                List<EditorContainerChild> containerChildren = new List<EditorContainerChild> ();
2324
 
                
2325
 
                public void AddTopLevelWidget (Gtk.Widget w, int x, int y)
2326
 
                {
2327
 
                        w.Parent = this;
2328
 
                        EditorContainerChild info = new EditorContainerChild (this, w);
2329
 
                        info.X = x;
2330
 
                        info.Y = y;
2331
 
                        containerChildren.Add (info);
2332
 
                }
2333
 
                
2334
 
                public void MoveTopLevelWidget (Gtk.Widget w, int x, int y)
2335
 
                {
2336
 
                        foreach (EditorContainerChild info in containerChildren.ToArray ()) {
2337
 
                                if (info.Child == w || (info.Child is AnimatedWidget && ((AnimatedWidget)info.Child).Widget == w)) {
2338
 
                                        info.X = x;
2339
 
                                        info.Y = y;
2340
 
                                        QueueResize ();
2341
 
                                        break;
2342
 
                                }
2343
 
                        }
2344
 
                }
2345
 
                
2346
 
                public void MoveTopLevelWidgetX (Gtk.Widget w, int x)
2347
 
                {
2348
 
                        foreach (EditorContainerChild info in containerChildren.ToArray ()) {
2349
 
                                if (info.Child == w || (info.Child is AnimatedWidget && ((AnimatedWidget)info.Child).Widget == w)) {
2350
 
                                        info.X = x;
2351
 
                                        QueueResize ();
2352
 
                                        break;
2353
 
                                }
2354
 
                        }
2355
 
                }
2356
 
                
2357
 
                
2358
 
                public void MoveToTop (Gtk.Widget w)
2359
 
                {
2360
 
                        EditorContainerChild editorContainerChild = containerChildren.FirstOrDefault (c => c.Child == w);
2361
 
                        if (editorContainerChild == null)
2362
 
                                throw new Exception ("child " + w + " not found.");
2363
 
                        List<EditorContainerChild> newChilds = new List<EditorContainerChild> (containerChildren.Where (child => child != editorContainerChild));
2364
 
                        newChilds.Add (editorContainerChild);
2365
 
                        this.containerChildren = newChilds;
2366
 
                        w.GdkWindow.Raise ();
2367
 
                }
2368
 
                
2369
 
                protected override void OnAdded (Widget widget)
2370
 
                {
2371
 
                        AddTopLevelWidget (widget, 0, 0);
2372
 
                }
2373
 
                
2374
 
                protected override void OnRemoved (Widget widget)
2375
 
                {
2376
 
                        foreach (EditorContainerChild info in containerChildren.ToArray ()) {
2377
 
                                if (info.Child == widget) {
2378
 
                                        widget.Unparent ();
2379
 
                                        containerChildren.Remove (info);
2380
 
                                        break;
2381
 
                                }
2382
 
                        }
2383
 
                }
2384
 
                
2385
 
                protected override void OnSizeRequested (ref Gtk.Requisition requisition)
2386
 
                {
2387
 
                        base.OnSizeRequested (ref requisition);
2388
 
                        
2389
 
                        // Ignore the size of top levels. They are supposed to fit the available space
2390
 
                        foreach (EditorContainerChild tchild in containerChildren.ToArray ())
2391
 
                                tchild.Child.SizeRequest ();
2392
 
                }
2393
 
 
2394
 
                
2395
 
                protected override void ForAll (bool include_internals, Gtk.Callback callback)
2396
 
                {
2397
 
                        foreach (EditorContainerChild child in containerChildren.ToArray ()) {
2398
 
                                callback (child.Child);
2399
 
                        }
2400
 
                }
2401
 
#endregion*/
 
2441
                
 
2442
                #region Coordinate transformation
 
2443
                public DocumentLocation PointToLocation (double xp, double yp)
 
2444
                {
 
2445
                        return TextViewMargin.PointToLocation (xp, yp);
 
2446
                }
 
2447
 
 
2448
                public DocumentLocation PointToLocation (Cairo.Point p)
 
2449
                {
 
2450
                        return TextViewMargin.PointToLocation (p);
 
2451
                }
 
2452
                
 
2453
                public DocumentLocation PointToLocation (Cairo.PointD p)
 
2454
                {
 
2455
                        return TextViewMargin.PointToLocation (p);
 
2456
                }
 
2457
 
 
2458
                public Cairo.Point LocationToPoint (DocumentLocation loc)
 
2459
                {
 
2460
                        return TextViewMargin.LocationToPoint (loc);
 
2461
                }
 
2462
 
 
2463
                public Cairo.Point LocationToPoint (int line, int column)
 
2464
                {
 
2465
                        return TextViewMargin.LocationToPoint (line, column);
 
2466
                }
 
2467
                
 
2468
                public Cairo.Point LocationToPoint (int line, int column, bool useAbsoluteCoordinates)
 
2469
                {
 
2470
                        return TextViewMargin.LocationToPoint (line, column, useAbsoluteCoordinates);
 
2471
                }
 
2472
                
 
2473
                public Cairo.Point LocationToPoint (DocumentLocation loc, bool useAbsoluteCoordinates)
 
2474
                {
 
2475
                        return TextViewMargin.LocationToPoint (loc, useAbsoluteCoordinates);
 
2476
                }
 
2477
 
 
2478
                public double ColumnToX (LineSegment line, int column)
 
2479
                {
 
2480
                        return TextViewMargin.ColumnToX (line, column);
 
2481
                }
 
2482
                
 
2483
                /// <summary>
 
2484
                /// Calculates the line number at line start (in one visual line could be several logical lines be displayed).
 
2485
                /// </summary>
 
2486
                public int YToLine (double yPos)
 
2487
                {
 
2488
                        return TextViewMargin.YToLine (yPos);
 
2489
                }
 
2490
                
 
2491
                public double LineToY (int logicalLine)
 
2492
                {
 
2493
                        return TextViewMargin.LineToY (logicalLine);
 
2494
                }
 
2495
                
 
2496
                public double GetLineHeight (LineSegment line)
 
2497
                {
 
2498
                        return TextViewMargin.GetLineHeight (line);
 
2499
                }
 
2500
                
 
2501
                public double GetLineHeight (int logicalLineNumber)
 
2502
                {
 
2503
                        return TextViewMargin.GetLineHeight (logicalLineNumber);
 
2504
                }
 
2505
                #endregion
2402
2506
                
2403
2507
                #region Animation
2404
2508
                Stage<Animation> animationStage = new Stage<Animation> ();
2491
2595
                }
2492
2596
                #endregion
2493
2597
                
2494
 
                internal void FireLinkEvent (string link, int button, ModifierType modifierState)
 
2598
                internal void FireLinkEvent (string link, uint button, ModifierType modifierState)
2495
2599
                {
2496
2600
                        if (LinkRequest != null)
2497
2601
                                LinkRequest (this, new LinkEventArgs (link, button, modifierState));
2530
2634
                                requestResetCaretBlink = true;
2531
2635
                }
2532
2636
 
2533
 
                public int CalculateLineNumber (int yPos)
2534
 
                {
2535
 
                        int delta = 0;
2536
 
                        foreach (LineSegment extendedTextMarkerLine in Document.LinesWithExtendingTextMarkers) {
2537
 
                                int lineNumber = Document.OffsetToLineNumber (extendedTextMarkerLine.Offset);
2538
 
                                int y = LineToVisualY (lineNumber);
2539
 
                                if (y < yPos) {
2540
 
                                        int curLineHeight = GetLineHeight (extendedTextMarkerLine);
2541
 
                                        delta += curLineHeight - LineHeight;
2542
 
                                        if (y <= yPos && yPos < y + curLineHeight)
2543
 
                                                return lineNumber;
2544
 
                                }
2545
 
                        }
2546
 
                        return Document.VisualToLogicalLine ((yPos - delta) / LineHeight);
2547
 
/*                      LineSegment logicalLineSegment = Document.GetLine (logicalLine);
2548
 
                        foreach (LineSegment extendedTextMarkerLine in Document.LinesWithExtendingTextMarkers) {
2549
 
                                if (logicalLineSegment != null && extendedTextMarkerLine.Offset > logicalLineSegment.Offset)
2550
 
                                        continue;
2551
 
                                int curLineHeight = GetLineHeight (extendedTextMarkerLine) - LineHeight;
2552
 
                                
2553
 
                                if (curLineHeight != 0) {
2554
 
                                        logicalLine -= curLineHeight / LineHeight;
2555
 
                                        logicalLineSegment = Document.GetLine (logicalLine - 1);
2556
 
                                }
2557
 
                        }
2558
 
                        
2559
 
                        return logicalLine;*/
2560
 
                }
2561
 
                
2562
 
                public int LineToVisualY (int logicalLine)
2563
 
                {
2564
 
                        int delta = 0;
2565
 
                        LineSegment logicalLineSegment = Document.GetLine (logicalLine);
2566
 
                        foreach (LineSegment extendedTextMarkerLine in Document.LinesWithExtendingTextMarkers) {
2567
 
                                if (extendedTextMarkerLine == null)
2568
 
                                        continue;
2569
 
                                if (logicalLineSegment != null && extendedTextMarkerLine.Offset >= logicalLineSegment.Offset)
2570
 
                                        continue;
2571
 
                                delta += GetLineHeight (extendedTextMarkerLine) - LineHeight;
2572
 
                        }
2573
 
                        
2574
 
                        int visualLine = Document.LogicalToVisualLine (logicalLine);
2575
 
                        return visualLine * LineHeight + delta;
2576
 
                }
2577
 
                
2578
 
                public int GetLineHeight (LineSegment line)
2579
 
                {
2580
 
                        if (line == null || line.MarkerCount == 0)
2581
 
                                return LineHeight;
2582
 
                        foreach (var marker in line.Markers) {
2583
 
                                IExtendingTextMarker extendingTextMarker = marker as IExtendingTextMarker;
2584
 
                                if (extendingTextMarker == null)
2585
 
                                        continue;
2586
 
                                return extendingTextMarker.GetLineHeight (this);
2587
 
                        }
2588
 
                        return LineHeight;
2589
 
                }
2590
 
                
2591
 
                public int GetLineHeight (int logicalLineNumber)
2592
 
                {
2593
 
                        return GetLineHeight (Document.GetLine (logicalLineNumber));
2594
 
                }
2595
 
                
2596
2637
                void UpdateLinesOnTextMarkerHeightChange (object sender, LineEventArgs e)
2597
2638
                {
2598
2639
                        if (!e.Line.Markers.Any (m => m is IExtendingTextMarker))
2599
2640
                                return;
2600
 
                        int currentHeight = GetLineHeight (e.Line);
2601
 
                        int h;
 
2641
                        double currentHeight = GetLineHeight (e.Line);
 
2642
                        double h;
2602
2643
                        if (!lineHeights.TryGetValue (e.Line.Offset, out h))
2603
2644
                                h = TextViewMargin.LineHeight;
2604
2645
                        if (h != currentHeight)
2605
2646
                                textEditorData.Document.CommitLineToEndUpdate (textEditorData.Document.OffsetToLineNumber (e.Line.Offset));
2606
2647
                        lineHeights[e.Line.Offset] = currentHeight;
2607
2648
                }
 
2649
 
 
2650
                class SetCaret 
 
2651
                {
 
2652
                        TextEditor view;
 
2653
                        int line, column;
 
2654
                        bool highlightCaretLine;
 
2655
                        
 
2656
                        public SetCaret (TextEditor view, int line, int column, bool highlightCaretLine)
 
2657
                        {
 
2658
                                this.view = view;
 
2659
                                this.line = line;
 
2660
                                this.column = column;
 
2661
                                this.highlightCaretLine = highlightCaretLine;
 
2662
                        }
 
2663
                        
 
2664
                        public void Run (object sender, EventArgs e)
 
2665
                        {
 
2666
                                if (view.isDisposed)
 
2667
                                        return;
 
2668
                                line = System.Math.Min (line, view.Document.LineCount);
 
2669
                                view.Caret.AutoScrollToCaret = false;
 
2670
                                try {
 
2671
                                        view.Caret.Location = new DocumentLocation (line, column);
 
2672
                                        view.GrabFocus ();
 
2673
                                        view.CenterToCaret ();
 
2674
                                        if (view.TextViewMargin.XOffset == 0)
 
2675
                                                view.HAdjustment.Value = 0;
 
2676
                                        view.SizeAllocated -= Run;
 
2677
                                } finally {
 
2678
                                        view.Caret.AutoScrollToCaret = true;
 
2679
                                        if (highlightCaretLine) {
 
2680
                                                view.TextViewMargin.HighlightCaretLine = true;
 
2681
                                                view.StartCaretPulseAnimation ();
 
2682
                                        }
 
2683
                                }
 
2684
                        }
 
2685
                }
 
2686
 
 
2687
                public void SetCaretTo (int line, int column)
 
2688
                {
 
2689
                        SetCaretTo (line, column, true);
 
2690
                }
 
2691
 
 
2692
                public void SetCaretTo (int line, int column, bool highlight)
 
2693
                {
 
2694
                        if (line < DocumentLocation.MinLine)
 
2695
                                throw new ArgumentException ("line < MinLine");
 
2696
                        if (column < DocumentLocation.MinColumn)
 
2697
                                throw new ArgumentException ("column < MinColumn");
 
2698
                        
 
2699
                        if (!IsRealized) {
 
2700
                                SetCaret setCaret = new SetCaret (this, line, column, highlight);
 
2701
                                SizeAllocated += setCaret.Run;
 
2702
                        } else {
 
2703
                                new SetCaret (this, line, column, highlight).Run (null, null);
 
2704
                        }
 
2705
                }
2608
2706
        }
2609
 
        
 
2707
 
2610
2708
        public interface ITextEditorDataProvider
2611
2709
        {
2612
2710
                TextEditorData GetTextEditorData ();
2613
2711
        }
 
2712
        
 
2713
        [Serializable]
 
2714
        public sealed class PaintEventArgs : EventArgs
 
2715
        {
 
2716
                public Cairo.Context Context {
 
2717
                        get;
 
2718
                        set;
 
2719
                }
 
2720
                
 
2721
                public Cairo.Rectangle Area {
 
2722
                        get;
 
2723
                        set;
 
2724
                }
 
2725
                
 
2726
                public PaintEventArgs (Cairo.Context context, Cairo.Rectangle area)
 
2727
                {
 
2728
                        this.Context = context;
 
2729
                        this.Area = area;
 
2730
                }
 
2731
        }
2614
2732
}
 
2733
 
 
2734