~ubuntu-branches/ubuntu/natty/geany/natty

« back to all changes in this revision

Viewing changes to scintilla/ScintillaGTK.cxx

  • Committer: Bazaar Package Importer
  • Author(s): Chow Loong Jin
  • Date: 2010-08-07 03:23:12 UTC
  • mfrom: (1.4.3 upstream)
  • mto: This revision was merged to the branch mainline in revision 22.
  • Revision ID: james.westby@ubuntu.com-20100807032312-ot70ac9d50cn79we
Tags: upstream-0.19
ImportĀ upstreamĀ versionĀ 0.19

Show diffs side-by-side

added added

removed removed

Lines of Context:
10
10
#include <ctype.h>
11
11
#include <time.h>
12
12
 
 
13
#include <string>
 
14
#include <vector>
 
15
 
13
16
#include <gtk/gtk.h>
14
17
#include <gdk/gdkkeysyms.h>
15
18
 
24
27
#ifdef SCI_LEXER
25
28
#include "SciLexer.h"
26
29
#include "PropSet.h"
 
30
#include "PropSetSimple.h"
27
31
#include "Accessor.h"
28
32
#include "KeyWords.h"
29
33
#endif
44
48
#include "Decoration.h"
45
49
#include "CharClassify.h"
46
50
#include "Document.h"
 
51
#include "Selection.h"
47
52
#include "PositionCache.h"
48
53
#include "Editor.h"
49
 
#include "SString.h"
50
54
#include "ScintillaBase.h"
51
55
#include "UniConversion.h"
52
56
 
53
57
#include "gtk/gtksignal.h"
54
58
#include "gtk/gtkmarshal.h"
55
 
#if GLIB_MAJOR_VERSION >= 2
56
59
#include "scintilla-marshal.h"
57
 
#endif
58
60
 
59
61
#ifdef SCI_LEXER
60
62
#include <glib.h>
62
64
#include "ExternalLexer.h"
63
65
#endif
64
66
 
65
 
#define INTERNATIONAL_INPUT
66
 
 
67
 
#if !PLAT_GTK_WIN32 || GTK_MAJOR_VERSION >= 2
68
 
#define USE_CONVERTER
69
 
#endif
70
 
 
71
 
#ifdef USE_CONVERTER
72
67
#include "Converter.h"
73
 
#endif
74
68
 
75
69
#ifdef _MSC_VER
76
70
// Constant conditional expressions are because of GTK+ headers
83
77
#define USE_GTK_CLIPBOARD
84
78
#endif
85
79
 
86
 
#if GLIB_MAJOR_VERSION < 2
87
 
#define OBJECT_CLASS GtkObjectClass
88
 
#else
89
80
#define OBJECT_CLASS GObjectClass
90
 
#endif
91
81
 
92
82
#ifdef SCI_NAMESPACE
93
83
using namespace Scintilla;
116
106
        bool capturedMouse;
117
107
        bool dragWasDropped;
118
108
        int lastKey;
 
109
        int rectangularSelectionModifier;
119
110
 
120
111
        GtkWidgetClass *parentClass;
121
112
 
130
121
        CLIPFORMAT cfColumnSelect;
131
122
#endif
132
123
 
133
 
#ifdef INTERNATIONAL_INPUT
134
 
#if GTK_MAJOR_VERSION < 2
135
 
        // Input context used for supporting internationalized key entry
136
 
        GdkIC *ic;
137
 
        GdkICAttr *ic_attr;
138
 
#else
139
124
        Window wPreedit;
140
125
        Window wPreeditDraw;
141
126
        GtkIMContext *im_context;
142
 
#endif
143
 
#endif
144
127
 
145
128
        // Wheel mouse support
146
129
        unsigned int linesPerScroll;
151
134
        GdkRegion *rgnUpdate;
152
135
 
153
136
        // Private so ScintillaGTK objects can not be copied
154
 
        ScintillaGTK(const ScintillaGTK &) : ScintillaBase() {}
155
 
        ScintillaGTK &operator=(const ScintillaGTK &) { return * this; }
 
137
        ScintillaGTK(const ScintillaGTK &);
 
138
        ScintillaGTK &operator=(const ScintillaGTK &);
156
139
 
157
140
public:
158
141
        ScintillaGTK(_ScintillaObject *sci_);
190
173
        void NotifyKey(int key, int modifiers);
191
174
        void NotifyURIDropped(const char *list);
192
175
        const char *CharacterSetID() const;
 
176
        virtual CaseFolder *CaseFolderForEncoding();
 
177
        virtual std::string CaseMapString(const std::string &s, int caseMapping);
193
178
        virtual int KeyDefault(int key, int modifiers);
194
179
        virtual void CopyToClipboard(const SelectionText &selectedText);
195
180
        virtual void Copy();
238
223
        gint PressThis(GdkEventButton *event);
239
224
        static gint Press(GtkWidget *widget, GdkEventButton *event);
240
225
        static gint MouseRelease(GtkWidget *widget, GdkEventButton *event);
241
 
#if PLAT_GTK_WIN32 || (GTK_MAJOR_VERSION >= 2)
242
226
        static gint ScrollEvent(GtkWidget *widget, GdkEventScroll *event);
243
 
#endif
244
227
        static gint Motion(GtkWidget *widget, GdkEventMotion *event);
245
228
        gboolean KeyThis(GdkEventKey *event);
246
229
        static gboolean KeyPress(GtkWidget *widget, GdkEventKey *event);
247
230
        static gboolean KeyRelease(GtkWidget *widget, GdkEventKey *event);
248
 
#if GTK_MAJOR_VERSION >= 2
249
231
        gboolean ExposePreeditThis(GtkWidget *widget, GdkEventExpose *ose);
250
232
        static gboolean ExposePreedit(GtkWidget *widget, GdkEventExpose *ose, ScintillaGTK *sciThis);
251
233
        void CommitThis(char *str);
252
234
        static void Commit(GtkIMContext *context, char *str, ScintillaGTK *sciThis);
253
235
        void PreeditChangedThis();
254
236
        static void PreeditChanged(GtkIMContext *context, ScintillaGTK *sciThis);
255
 
#endif
256
237
        static gint StyleSetText(GtkWidget *widget, GtkStyle *previous, void*);
257
238
        static gint RealizeText(GtkWidget *widget, void*);
258
 
#if GLIB_MAJOR_VERSION < 2
259
 
        static void Destroy(GtkObject *object);
260
 
#else
261
239
        static void Destroy(GObject *object);
262
 
#endif
263
240
        static void SelectionReceived(GtkWidget *widget, GtkSelectionData *selection_data,
264
241
                                      guint time);
265
242
        static void SelectionGet(GtkWidget *widget, GtkSelectionData *selection_data,
266
243
                                 guint info, guint time);
267
244
        static gint SelectionClear(GtkWidget *widget, GdkEventSelection *selection_event);
268
 
#if GTK_MAJOR_VERSION < 2
269
 
        static gint SelectionNotify(GtkWidget *widget, GdkEventSelection *selection_event);
270
 
#endif
271
245
        static void DragBegin(GtkWidget *widget, GdkDragContext *context);
272
246
        gboolean DragMotionThis(GdkDragContext *context, gint x, gint y, guint dragtime);
273
247
        static gboolean DragMotion(GtkWidget *widget, GdkDragContext *context,
282
256
        static void DragDataGet(GtkWidget *widget, GdkDragContext *context,
283
257
                                GtkSelectionData *selection_data, guint info, guint time);
284
258
        static gint TimeOut(ScintillaGTK *sciThis);
285
 
        static gint IdleCallback(ScintillaGTK *sciThis);
 
259
        static gboolean IdleCallback(ScintillaGTK *sciThis);
 
260
        static gboolean StyleIdle(ScintillaGTK *sciThis);
 
261
        virtual void QueueStyling(int upTo);
286
262
        static void PopUpCB(ScintillaGTK *sciThis, guint action, GtkWidget *widget);
287
263
 
288
264
        gint ExposeTextThis(GtkWidget *widget, GdkEventExpose *ose);
302
278
};
303
279
 
304
280
static gint scintilla_signals[LAST_SIGNAL] = { 0 };
305
 
#if GLIB_MAJOR_VERSION < 2
306
 
static GtkWidgetClass *parent_class = NULL;
307
 
#endif
308
281
 
309
282
enum {
310
283
    TARGET_STRING,
346
319
                adjustmentv(0), adjustmenth(0),
347
320
                scrollBarWidth(30), scrollBarHeight(30),
348
321
                capturedMouse(false), dragWasDropped(false),
349
 
                lastKey(0), parentClass(0),
350
 
#ifdef INTERNATIONAL_INPUT
351
 
#if GTK_MAJOR_VERSION < 2
352
 
                ic(NULL),
353
 
                ic_attr(NULL),
354
 
#else
 
322
                lastKey(0), rectangularSelectionModifier(SCMOD_CTRL), parentClass(0),
355
323
                im_context(NULL),
356
 
#endif
357
 
#endif
358
324
                lastWheelMouseDirection(0),
359
325
                wheelMouseIntensity(0),
360
326
                rgnUpdate(0) {
362
328
        wMain = GTK_WIDGET(sci);
363
329
 
364
330
#if PLAT_GTK_WIN32
 
331
        rectangularSelectionModifier = SCMOD_ALT;
 
332
#else
 
333
        rectangularSelectionModifier = SCMOD_CTRL;
 
334
#endif
 
335
 
 
336
#if PLAT_GTK_WIN32
365
337
        // There does not seem to be a real standard for indicating that the clipboard
366
338
        // contains a rectangular selection, so copy Developer Studio.
367
339
        cfColumnSelect = static_cast<CLIPFORMAT>(
407
379
        gdk_window_show(widget->window);
408
380
        gdk_cursor_destroy(cursor);
409
381
        widget->style = gtk_style_attach(widget->style, widget->window);
410
 
#ifdef INTERNATIONAL_INPUT
411
 
#if GTK_MAJOR_VERSION < 2
412
 
        if (gdk_im_ready() && (ic_attr = gdk_ic_attr_new()) != NULL) {
413
 
                gint width, height;
414
 
                GdkColormap *colormap;
415
 
                GdkEventMask mask;
416
 
                GdkICAttr *attr = ic_attr;
417
 
                GdkICAttributesType attrmask = GDK_IC_ALL_REQ;
418
 
                GdkIMStyle style;
419
 
                GdkIMStyle supported_style = (GdkIMStyle) (GDK_IM_PREEDIT_NONE |
420
 
                        GDK_IM_PREEDIT_NOTHING |
421
 
                        GDK_IM_PREEDIT_POSITION |
422
 
                        GDK_IM_STATUS_NONE |
423
 
                        GDK_IM_STATUS_NOTHING);
424
 
 
425
 
                if (widget->style && widget->style->font->type != GDK_FONT_FONTSET)
426
 
                        supported_style = (GdkIMStyle) ((int) supported_style & ~GDK_IM_PREEDIT_POSITION);
427
 
 
428
 
                attr->style = style = gdk_im_decide_style(supported_style);
429
 
                attr->client_window = widget->window;
430
 
 
431
 
                if ((colormap = gtk_widget_get_colormap (widget)) != gtk_widget_get_default_colormap ()) {
432
 
                        attrmask = (GdkICAttributesType) ((int) attrmask | GDK_IC_PREEDIT_COLORMAP);
433
 
                        attr->preedit_colormap = colormap;
434
 
                }
435
 
 
436
 
                switch (style & GDK_IM_PREEDIT_MASK) {
437
 
                case GDK_IM_PREEDIT_POSITION:
438
 
                        if (widget->style && widget->style->font->type != GDK_FONT_FONTSET)     {
439
 
                                g_warning("over-the-spot style requires fontset");
440
 
                                break;
441
 
                        }
442
 
 
443
 
                        attrmask = (GdkICAttributesType) ((int) attrmask | GDK_IC_PREEDIT_POSITION_REQ);
444
 
                        gdk_window_get_size(widget->window, &width, &height);
445
 
                        attr->spot_location.x = 0;
446
 
                        attr->spot_location.y = height;
447
 
                        attr->preedit_area.x = 0;
448
 
                        attr->preedit_area.y = 0;
449
 
                        attr->preedit_area.width = width;
450
 
                        attr->preedit_area.height = height;
451
 
                        attr->preedit_fontset = widget->style->font;
452
 
 
453
 
                        break;
454
 
                }
455
 
                ic = gdk_ic_new(attr, attrmask);
456
 
 
457
 
                if (ic == NULL) {
458
 
                        g_warning("Can't create input context.");
459
 
                } else {
460
 
                        mask = gdk_window_get_events(widget->window);
461
 
                        mask = (GdkEventMask) ((int) mask | gdk_ic_get_events(ic));
462
 
                        gdk_window_set_events(widget->window, mask);
463
 
 
464
 
                        if (GTK_WIDGET_HAS_FOCUS(widget))
465
 
                                gdk_im_begin(ic, widget->window);
466
 
                }
467
 
        }
468
 
#else
469
382
        wPreedit = gtk_window_new(GTK_WINDOW_POPUP);
470
383
        wPreeditDraw = gtk_drawing_area_new();
471
384
        GtkWidget *predrw = PWidget(wPreeditDraw);      // No code inside the G_OBJECT macro
482
395
        g_signal_connect(G_OBJECT(im_context), "preedit_changed",
483
396
                G_CALLBACK(PreeditChanged), this);
484
397
        gtk_im_context_set_client_window(im_context, widget->window);
485
 
#endif
486
 
#endif
487
398
        GtkWidget *widtxt = PWidget(wText);     //      // No code inside the G_OBJECT macro
488
 
#if GLIB_MAJOR_VERSION < 2
489
 
        gtk_signal_connect_after(GTK_OBJECT(widtxt), "style_set",
490
 
                GtkSignalFunc(ScintillaGTK::StyleSetText), NULL);
491
 
        gtk_signal_connect_after(GTK_OBJECT(widtxt), "realize",
492
 
                GtkSignalFunc(ScintillaGTK::RealizeText), NULL);
493
 
#else
494
399
        g_signal_connect_after(G_OBJECT(widtxt), "style_set",
495
400
                G_CALLBACK(ScintillaGTK::StyleSetText), NULL);
496
401
        g_signal_connect_after(G_OBJECT(widtxt), "realize",
497
402
                G_CALLBACK(ScintillaGTK::RealizeText), NULL);
498
 
#endif
499
403
        gtk_widget_realize(widtxt);
500
404
        gtk_widget_realize(PWidget(scrollbarv));
501
405
        gtk_widget_realize(PWidget(scrollbarh));
515
419
                gtk_widget_unrealize(PWidget(wText));
516
420
                gtk_widget_unrealize(PWidget(scrollbarv));
517
421
                gtk_widget_unrealize(PWidget(scrollbarh));
518
 
#ifdef INTERNATIONAL_INPUT
519
 
#if GTK_MAJOR_VERSION < 2
520
 
                if (ic) {
521
 
                        gdk_ic_destroy(ic);
522
 
                        ic = NULL;
523
 
                }
524
 
                if (ic_attr) {
525
 
                        gdk_ic_attr_destroy(ic_attr);
526
 
                        ic_attr = NULL;
527
 
                }
528
 
#else
529
422
                gtk_widget_unrealize(PWidget(wPreedit));
530
423
                gtk_widget_unrealize(PWidget(wPreeditDraw));
531
424
                g_object_unref(im_context);
532
425
                im_context = NULL;
533
 
#endif
534
 
#endif
535
426
                if (GTK_WIDGET_CLASS(parentClass)->unrealize)
536
427
                        GTK_WIDGET_CLASS(parentClass)->unrealize(widget);
537
428
 
613
504
        }
614
505
}
615
506
 
616
 
#ifdef INTERNATIONAL_INPUT
617
 
#if GTK_MAJOR_VERSION < 2
618
 
gint ScintillaGTK::CursorMoved(GtkWidget *widget, int xoffset, int yoffset, ScintillaGTK *sciThis) {
619
 
        if (GTK_WIDGET_HAS_FOCUS(widget) && gdk_im_ready() && sciThis->ic &&
620
 
                (gdk_ic_get_style(sciThis->ic) & GDK_IM_PREEDIT_POSITION)) {
621
 
                sciThis->ic_attr->spot_location.x = xoffset;
622
 
                sciThis->ic_attr->spot_location.y = yoffset;
623
 
                gdk_ic_set_attr(sciThis->ic, sciThis->ic_attr, GDK_IC_SPOT_LOCATION);
624
 
        }
625
 
        return FALSE;
626
 
}
627
 
#else
628
507
gint ScintillaGTK::CursorMoved(GtkWidget *, int xoffset, int yoffset, ScintillaGTK *sciThis) {
629
508
        GdkRectangle area;
630
509
        area.x = xoffset;
634
513
        gtk_im_context_set_cursor_location(sciThis->im_context, &area);
635
514
        return FALSE;
636
515
}
637
 
#endif
638
 
#else
639
 
gint ScintillaGTK::CursorMoved(GtkWidget *, int, int, ScintillaGTK *) {
640
 
        return FALSE;
641
 
}
642
 
#endif
643
516
 
644
517
gint ScintillaGTK::FocusInThis(GtkWidget *widget) {
645
518
        try {
646
519
                GTK_WIDGET_SET_FLAGS(widget, GTK_HAS_FOCUS);
647
520
                SetFocusState(true);
648
 
#ifdef INTERNATIONAL_INPUT
649
 
#if GTK_MAJOR_VERSION < 2
650
 
                if (ic)
651
 
                        gdk_im_begin(ic, widget->window);
652
 
#else
653
521
                if (im_context != NULL) {
654
522
                        gchar *str = NULL;
655
523
                        gint cursor_pos;
665
533
                        g_free(str);
666
534
                        gtk_im_context_focus_in(im_context);
667
535
                }
668
 
#endif
669
 
#endif
670
536
 
671
537
        } catch (...) {
672
538
                errorStatus = SC_STATUS_FAILURE;
684
550
                GTK_WIDGET_UNSET_FLAGS(widget, GTK_HAS_FOCUS);
685
551
                SetFocusState(false);
686
552
 
687
 
#ifdef INTERNATIONAL_INPUT
688
 
#if GTK_MAJOR_VERSION < 2
689
 
                gdk_im_end();
690
 
#else
691
553
                if (PWidget(wPreedit) != NULL)
692
554
                        gtk_widget_hide(PWidget(wPreedit));
693
555
                if (im_context != NULL)
694
556
                        gtk_im_context_focus_out(im_context);
695
 
#endif
696
 
#endif
697
557
 
698
558
        } catch (...) {
699
559
                errorStatus = SC_STATUS_FAILURE;
728
588
 
729
589
                sciThis->Resize(allocation->width, allocation->height);
730
590
 
731
 
#ifdef INTERNATIONAL_INPUT
732
 
#if GTK_MAJOR_VERSION < 2
733
 
                if (sciThis->ic && (gdk_ic_get_style(sciThis->ic) & GDK_IM_PREEDIT_POSITION)) {
734
 
                        gint width, height;
735
 
 
736
 
                        gdk_window_get_size(widget->window, &width, &height);
737
 
                        sciThis->ic_attr->preedit_area.width = width;
738
 
                        sciThis->ic_attr->preedit_area.height = height;
739
 
 
740
 
                        gdk_ic_set_attr(sciThis->ic, sciThis->ic_attr, GDK_IC_PREEDIT_AREA);
741
 
                }
742
 
#endif
743
 
#endif
744
591
        } catch (...) {
745
592
                sciThis->errorStatus = SC_STATUS_FAILURE;
746
593
        }
769
616
        gtk_widget_set_parent(PWidget(wText), PWidget(wMain));
770
617
        GtkWidget *widtxt = PWidget(wText);     // No code inside the G_OBJECT macro
771
618
        gtk_widget_show(widtxt);
772
 
#if GLIB_MAJOR_VERSION < 2
773
 
        gtk_signal_connect(GTK_OBJECT(widtxt), "expose_event",
774
 
                           GtkSignalFunc(ScintillaGTK::ExposeText), this);
775
 
#else
776
619
        g_signal_connect(G_OBJECT(widtxt), "expose_event",
777
620
                           G_CALLBACK(ScintillaGTK::ExposeText), this);
778
 
#endif
779
621
        gtk_widget_set_events(widtxt, GDK_EXPOSURE_MASK);
780
 
#if GTK_MAJOR_VERSION >= 2
781
622
        // Avoid background drawing flash
782
623
        gtk_widget_set_double_buffered(widtxt, FALSE);
783
 
#endif
784
624
        gtk_drawing_area_size(GTK_DRAWING_AREA(widtxt),
785
625
                              100,100);
786
626
        adjustmentv = gtk_adjustment_new(0.0, 0.0, 201.0, 1.0, 20.0, 20.0);
787
627
        scrollbarv = gtk_vscrollbar_new(GTK_ADJUSTMENT(adjustmentv));
788
628
        GTK_WIDGET_UNSET_FLAGS(PWidget(scrollbarv), GTK_CAN_FOCUS);
789
 
#if GLIB_MAJOR_VERSION < 2
790
 
        gtk_signal_connect(adjustmentv, "value_changed",
791
 
                           GtkSignalFunc(ScrollSignal), this);
792
 
#else
793
629
        g_signal_connect(G_OBJECT(adjustmentv), "value_changed",
794
630
                           G_CALLBACK(ScrollSignal), this);
795
 
#endif
796
631
        gtk_widget_set_parent(PWidget(scrollbarv), PWidget(wMain));
797
632
        gtk_widget_show(PWidget(scrollbarv));
798
633
 
799
634
        adjustmenth = gtk_adjustment_new(0.0, 0.0, 101.0, 1.0, 20.0, 20.0);
800
635
        scrollbarh = gtk_hscrollbar_new(GTK_ADJUSTMENT(adjustmenth));
801
636
        GTK_WIDGET_UNSET_FLAGS(PWidget(scrollbarh), GTK_CAN_FOCUS);
802
 
#if GLIB_MAJOR_VERSION < 2
803
 
        gtk_signal_connect(adjustmenth, "value_changed",
804
 
                           GtkSignalFunc(ScrollHSignal), this);
805
 
#else
806
637
        g_signal_connect(G_OBJECT(adjustmenth), "value_changed",
807
638
                           G_CALLBACK(ScrollHSignal), this);
808
 
#endif
809
639
        gtk_widget_set_parent(PWidget(scrollbarh), PWidget(wMain));
810
640
        gtk_widget_show(PWidget(scrollbarh));
811
641
 
823
653
                          GTK_DEST_DEFAULT_ALL, clipboardPasteTargets, nClipboardPasteTargets,
824
654
                          static_cast<GdkDragAction>(GDK_ACTION_COPY | GDK_ACTION_MOVE));
825
655
 
826
 
#if GLIB_MAJOR_VERSION >= 2
827
656
        // Set caret period based on GTK settings
828
657
        gboolean blinkOn = false;
829
658
        if (g_object_class_find_property(G_OBJECT_GET_CLASS(
841
670
        } else {
842
671
                caret.period = 0;
843
672
        }
844
 
#endif
845
673
 
846
674
        SetTicking(true);
847
675
}
859
687
}
860
688
 
861
689
bool ScintillaGTK::DragThreshold(Point ptStart, Point ptNow) {
862
 
#if GTK_MAJOR_VERSION < 2
863
 
        return Editor::DragThreshold(ptStart, ptNow);
864
 
#else
865
690
        return gtk_drag_check_threshold(GTK_WIDGET(PWidget(wMain)),
866
691
                ptStart.x, ptStart.y, ptNow.x, ptNow.y);
867
 
#endif
868
692
}
869
693
 
870
694
void ScintillaGTK::StartDrag() {
878
702
                       reinterpret_cast<GdkEvent *>(&evbtn));
879
703
}
880
704
 
881
 
#ifdef USE_CONVERTER
882
705
static char *ConvertText(int *lenResult, char *s, size_t len, const char *charSetDest,
883
 
        const char *charSetSource, bool transliterations) {
 
706
        const char *charSetSource, bool transliterations, bool silent=false) {
 
707
        // s is not const because of different versions of iconv disagreeing about const
884
708
        *lenResult = 0;
885
709
        char *destForm = 0;
886
710
        Converter conv(charSetDest, charSetSource, transliterations);
892
716
                size_t outLeft = len*3+1;
893
717
                size_t conversions = conv.Convert(&pin, &inLeft, &pout, &outLeft);
894
718
                if (conversions == ((size_t)(-1))) {
895
 
fprintf(stderr, "iconv %s->%s failed for %s\n", charSetSource, charSetDest, static_cast<char *>(s));
 
719
                        if (!silent)
 
720
                                fprintf(stderr, "iconv %s->%s failed for %s\n", 
 
721
                                        charSetSource, charSetDest, static_cast<char *>(s));
896
722
                        delete []destForm;
897
723
                        destForm = 0;
898
724
                } else {
910
736
        }
911
737
        return destForm;
912
738
}
913
 
#endif
914
739
 
915
740
// Returns the target converted to UTF8.
916
741
// Return the length in bytes.
922
747
                }
923
748
        } else {
924
749
                // Need to convert
925
 
#ifdef USE_CONVERTER
926
750
                const char *charSetBuffer = CharacterSetID();
927
751
                if (*charSetBuffer) {
928
752
//~ fprintf(stderr, "AsUTF8 %s %d  %0d-%0d\n", charSetBuffer, targetLength, targetStart, targetEnd);
943
767
                                pdoc->GetCharRange(text, targetStart, targetLength);
944
768
                        }
945
769
                }
946
 
#else
947
 
                // Fail
948
 
                return 0;
949
 
#endif
950
770
        }
951
771
//~ fprintf(stderr, "Length = %d bytes\n", targetLength);
952
772
        return targetLength;
963
783
                return inputLength;
964
784
        } else {
965
785
                // Need to convert
966
 
#ifdef USE_CONVERTER
967
786
                const char *charSetBuffer = CharacterSetID();
968
787
                if (*charSetBuffer) {
969
 
//~ fprintf(stderr, "Encode %s %d\n", charSetBuffer, inputLength);
970
788
                        int outLength = 0;
971
789
                        char *tmpEncoded = ConvertText(&outLength, utf8, inputLength, charSetBuffer, "UTF-8", true);
972
790
                        if (tmpEncoded) {
973
 
//~ fprintf(stderr, "    \"%s\"\n", tmpEncoded);
974
791
                                if (encoded) {
975
792
                                        memcpy(encoded, tmpEncoded, outLength);
976
793
                                }
983
800
                        }
984
801
                        return inputLength;
985
802
                }
986
 
#endif
987
803
        }
988
804
        // Fail
989
805
        return 0;
990
806
}
991
807
 
992
808
bool ScintillaGTK::ValidCodePage(int codePage) const {
993
 
        return codePage == 0 || codePage == SC_CP_UTF8 || codePage == SC_CP_DBCS;
 
809
        return codePage == 0
 
810
        || codePage == SC_CP_UTF8
 
811
        || codePage == 932
 
812
        || codePage == 936
 
813
        || codePage == 950
 
814
        || codePage == SC_CP_DBCS;
994
815
}
995
816
 
996
817
sptr_t ScintillaGTK::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
1009
830
 
1010
831
#ifdef SCI_LEXER
1011
832
                case SCI_LOADLEXERLIBRARY:
1012
 
                        LexerManager::GetInstance()->Load(reinterpret_cast<const char*>(wParam));
 
833
                        LexerManager::GetInstance()->Load(reinterpret_cast<const char*>(lParam));
1013
834
                        break;
1014
835
#endif
1015
836
                case SCI_TARGETASUTF8:
1019
840
                        return EncodedFromUTF8(reinterpret_cast<char*>(wParam),
1020
841
                                reinterpret_cast<char*>(lParam));
1021
842
 
 
843
                case SCI_SETRECTANGULARSELECTIONMODIFIER:
 
844
                        rectangularSelectionModifier = wParam;
 
845
                        break;
 
846
 
 
847
                case SCI_GETRECTANGULARSELECTIONMODIFIER:
 
848
                        return rectangularSelectionModifier;
 
849
 
1022
850
                default:
1023
851
                        return ScintillaBase::WndProc(iMessage, wParam, lParam);
1024
852
                }
1049
877
bool ScintillaGTK::SetIdle(bool on) {
1050
878
        if (on) {
1051
879
                // Start idler, if it's not running.
1052
 
                if (idler.state == false) {
 
880
                if (!idler.state) {
1053
881
                        idler.state = true;
1054
 
                        idler.idlerID = reinterpret_cast<IdlerID>
1055
 
                                (gtk_idle_add((GtkFunction)IdleCallback, this));
 
882
                        idler.idlerID = reinterpret_cast<IdlerID>(
 
883
                                g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, 
 
884
                                        reinterpret_cast<GSourceFunc>(IdleCallback), this, NULL));
1056
885
                }
1057
886
        } else {
1058
887
                // Stop idler, if it's running
1059
 
                if (idler.state == true) {
 
888
                if (idler.state) {
1060
889
                        idler.state = false;
1061
 
                        gtk_idle_remove(GPOINTER_TO_UINT(idler.idlerID));
 
890
                        g_source_remove(GPOINTER_TO_UINT(idler.idlerID));
1062
891
                }
1063
892
        }
1064
893
        return true;
1097
926
 
1098
927
// Redraw all of text area. This paint will not be abandoned.
1099
928
void ScintillaGTK::FullPaint() {
1100
 
#if GTK_MAJOR_VERSION < 2
1101
 
        paintState = painting;
1102
 
        rcPaint = GetClientRectangle();
1103
 
        //Platform::DebugPrintf("ScintillaGTK::FullPaint %0d,%0d %0d,%0d\n",
1104
 
        //      rcPaint.left, rcPaint.top, rcPaint.right, rcPaint.bottom);
1105
 
        paintingAllText = true;
1106
 
        if ((PWidget(wText))->window) {
1107
 
                Surface *sw = Surface::Allocate();
1108
 
                if (sw) {
1109
 
                        sw->Init(PWidget(wText)->window, PWidget(wText));
1110
 
                        Paint(sw, rcPaint);
1111
 
                        sw->Release();
1112
 
                        delete sw;
1113
 
                }
1114
 
        }
1115
 
        paintState = notPainting;
1116
 
#else
1117
929
        wText.InvalidateAll();
1118
 
#endif
1119
930
}
1120
931
 
1121
932
PRectangle ScintillaGTK::GetClientRectangle() {
1160
971
        //      rc.left, rc.top, rc.right, rc.bottom);
1161
972
        GtkWidget *wi = PWidget(wText);
1162
973
 
1163
 
#if GTK_MAJOR_VERSION < 2
1164
 
        PRectangle rc = GetClientRectangle();
1165
 
        GdkGC *gc = gdk_gc_new(wi->window);
1166
 
 
1167
 
        // Set up gc so we get GraphicsExposures from gdk_draw_pixmap
1168
 
        //  which calls XCopyArea
1169
 
        gdk_gc_set_exposures(gc, TRUE);
1170
 
 
1171
 
        // Redraw exposed bit : scrolling upwards
1172
 
        if (diff > 0) {
1173
 
                gdk_draw_pixmap(wi->window,
1174
 
                                gc, wi->window,
1175
 
                                0, diff,
1176
 
                                0, 0,
1177
 
                                rc.Width()-1, rc.Height() - diff);
1178
 
                SyncPaint(PRectangle(0, rc.Height() - diff,
1179
 
                                     rc.Width(), rc.Height()+1));
1180
 
 
1181
 
        // Redraw exposed bit : scrolling downwards
1182
 
        } else {
1183
 
                gdk_draw_pixmap(wi->window,
1184
 
                                gc, wi->window,
1185
 
                                0, 0,
1186
 
                                0, -diff,
1187
 
                                rc.Width()-1, rc.Height() + diff);
1188
 
                SyncPaint(PRectangle(0, 0, rc.Width(), -diff));
1189
 
        }
1190
 
 
1191
 
        // Look for any graphics expose
1192
 
        GdkEvent* event;
1193
 
        while ((event = gdk_event_get_graphics_expose(wi->window)) != NULL) {
1194
 
                gtk_widget_event(wi, event);
1195
 
                if (event->expose.count == 0) {
1196
 
                        gdk_event_free(event);
1197
 
                        break;
1198
 
                }
1199
 
                gdk_event_free(event);
1200
 
        }
1201
 
 
1202
 
        gdk_gc_unref(gc);
1203
 
#else
1204
974
        gdk_window_scroll(wi->window, 0, -diff);
1205
975
        gdk_window_process_updates(wi->window, FALSE);
1206
 
#endif
1207
976
}
1208
977
 
1209
978
void ScintillaGTK::SetVerticalScrollPos() {
1257
1026
}
1258
1027
 
1259
1028
void ScintillaGTK::NotifyChange() {
1260
 
#if GLIB_MAJOR_VERSION < 2
1261
 
        gtk_signal_emit(GTK_OBJECT(sci), scintilla_signals[COMMAND_SIGNAL],
1262
 
                        Platform::LongFromTwoShorts(GetCtrlID(), SCEN_CHANGE), PWidget(wMain));
1263
 
#else
1264
1029
        g_signal_emit(G_OBJECT(sci), scintilla_signals[COMMAND_SIGNAL], 0,
1265
1030
                        Platform::LongFromTwoShorts(GetCtrlID(), SCEN_CHANGE), PWidget(wMain));
1266
 
#endif
1267
1031
}
1268
1032
 
1269
1033
void ScintillaGTK::NotifyFocus(bool focus) {
1270
 
#if GLIB_MAJOR_VERSION < 2
1271
 
        gtk_signal_emit(GTK_OBJECT(sci), scintilla_signals[COMMAND_SIGNAL],
1272
 
                        Platform::LongFromTwoShorts
1273
 
                                        (GetCtrlID(), focus ? SCEN_SETFOCUS : SCEN_KILLFOCUS), PWidget(wMain));
1274
 
#else
1275
1034
        g_signal_emit(G_OBJECT(sci), scintilla_signals[COMMAND_SIGNAL], 0,
1276
1035
                        Platform::LongFromTwoShorts
1277
1036
                                        (GetCtrlID(), focus ? SCEN_SETFOCUS : SCEN_KILLFOCUS), PWidget(wMain));
1278
 
#endif
1279
1037
}
1280
1038
 
1281
1039
void ScintillaGTK::NotifyParent(SCNotification scn) {
1282
1040
        scn.nmhdr.hwndFrom = PWidget(wMain);
1283
1041
        scn.nmhdr.idFrom = GetCtrlID();
1284
 
#if GLIB_MAJOR_VERSION < 2
1285
 
        gtk_signal_emit(GTK_OBJECT(sci), scintilla_signals[NOTIFY_SIGNAL],
1286
 
                        GetCtrlID(), &scn);
1287
 
#else
1288
1042
        g_signal_emit(G_OBJECT(sci), scintilla_signals[NOTIFY_SIGNAL], 0,
1289
1043
                        GetCtrlID(), &scn);
1290
 
#endif
1291
1044
}
1292
1045
 
1293
1046
void ScintillaGTK::NotifyKey(int key, int modifiers) {
1313
1066
        return ::CharacterSetID(vs.styles[STYLE_DEFAULT].characterSet);
1314
1067
}
1315
1068
 
 
1069
class CaseFolderUTF8 : public CaseFolderTable {
 
1070
public:
 
1071
        CaseFolderUTF8() {
 
1072
                StandardASCII();
 
1073
        }
 
1074
        virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) {
 
1075
                if ((lenMixed == 1) && (sizeFolded > 0)) {
 
1076
                        folded[0] = mapping[static_cast<unsigned char>(mixed[0])];
 
1077
                        return 1;
 
1078
                } else {
 
1079
                        gchar *mapped = g_utf8_casefold(mixed, lenMixed);
 
1080
                        size_t lenMapped = strlen(mapped);
 
1081
                        if (lenMapped < sizeFolded) {
 
1082
                                memcpy(folded, mapped,  lenMapped);
 
1083
                        } else {
 
1084
                                lenMapped = 0;
 
1085
                        }
 
1086
                        g_free(mapped);
 
1087
                        return lenMapped;
 
1088
                }
 
1089
        }
 
1090
};
 
1091
 
 
1092
CaseFolder *ScintillaGTK::CaseFolderForEncoding() {
 
1093
        if (pdoc->dbcsCodePage == SC_CP_UTF8) {
 
1094
                return new CaseFolderUTF8();
 
1095
        } else {
 
1096
                CaseFolderTable *pcf = new CaseFolderTable();
 
1097
                const char *charSetBuffer = CharacterSetID();
 
1098
                if ((pdoc->dbcsCodePage == 0) && charSetBuffer) {
 
1099
                        pcf->StandardASCII();
 
1100
                        // Only for single byte encodings
 
1101
                        for (int i=0x80; i<0x100; i++) {
 
1102
                                char sCharacter[2] = "A";
 
1103
                                sCharacter[0] = i;
 
1104
                                int convertedLength = 1;
 
1105
                                const char *sUTF8 = ConvertText(&convertedLength, sCharacter, 1,
 
1106
                                        "UTF-8", charSetBuffer, false);
 
1107
                                if (sUTF8) {
 
1108
                                        gchar *mapped = g_utf8_casefold(sUTF8, strlen(sUTF8));
 
1109
                                        if (mapped) {
 
1110
                                                int mappedLength = strlen(mapped);
 
1111
                                                const char *mappedBack = ConvertText(&mappedLength, mapped,
 
1112
                                                        mappedLength, charSetBuffer, "UTF-8", false, true);
 
1113
                                                if (mappedBack && (strlen(mappedBack) == 1) && (mappedBack[0] != sCharacter[0])) {
 
1114
                                                        pcf->SetTranslation(sCharacter[0], mappedBack[0]);
 
1115
                                                }
 
1116
                                                delete []mappedBack;
 
1117
                                                g_free(mapped);
 
1118
                                        }
 
1119
                                }
 
1120
                                delete []sUTF8;
 
1121
                        }
 
1122
                }
 
1123
                return pcf;
 
1124
        }
 
1125
}
 
1126
 
 
1127
std::string ScintillaGTK::CaseMapString(const std::string &s, int caseMapping) {
 
1128
        if (s.size() == 0)
 
1129
                return std::string();
 
1130
 
 
1131
        if (caseMapping == cmSame)
 
1132
                return s;
 
1133
 
 
1134
        const char *needsFree1 = 0;     // Must be freed with delete []
 
1135
        const char *charSetBuffer = CharacterSetID();
 
1136
        const char *sUTF8 = s.c_str();
 
1137
        int rangeBytes = s.size();
 
1138
 
 
1139
        int convertedLength = rangeBytes;
 
1140
        // Change text to UTF-8
 
1141
        if (!IsUnicodeMode()) {
 
1142
                // Need to convert
 
1143
                if (*charSetBuffer) {
 
1144
                        sUTF8 = ConvertText(&convertedLength, const_cast<char *>(s.c_str()), rangeBytes,
 
1145
                                "UTF-8", charSetBuffer, false);
 
1146
                        needsFree1 = sUTF8;
 
1147
                }
 
1148
        }
 
1149
        gchar *mapped;  // Must be freed with g_free
 
1150
        if (caseMapping == cmUpper) {
 
1151
                mapped = g_utf8_strup(sUTF8, convertedLength);
 
1152
        } else {
 
1153
                mapped = g_utf8_strdown(sUTF8, convertedLength);
 
1154
        }
 
1155
        int mappedLength = strlen(mapped);
 
1156
        char *mappedBack = mapped;
 
1157
 
 
1158
        char *needsFree2 = 0;   // Must be freed with delete []
 
1159
        if (!IsUnicodeMode()) {
 
1160
                if (*charSetBuffer) {
 
1161
                        mappedBack = ConvertText(&mappedLength, mapped, mappedLength, charSetBuffer, "UTF-8", false);
 
1162
                        needsFree2 = mappedBack;
 
1163
                }
 
1164
        }
 
1165
 
 
1166
        std::string ret(mappedBack, mappedLength);
 
1167
        g_free(mapped);
 
1168
        delete []needsFree1;
 
1169
        delete []needsFree2;
 
1170
        return ret;
 
1171
}
 
1172
 
1316
1173
int ScintillaGTK::KeyDefault(int key, int modifiers) {
1317
1174
        if (!(modifiers & SCI_CTRL) && !(modifiers & SCI_ALT)) {
1318
1175
                if (key < 256) {
1345
1202
}
1346
1203
 
1347
1204
void ScintillaGTK::Copy() {
1348
 
        if (currentPos != anchor) {
 
1205
        if (!sel.Empty()) {
1349
1206
#ifndef USE_GTK_CLIPBOARD
1350
1207
                CopySelectionRange(&copyText);
1351
1208
                gtk_selection_owner_set(GTK_WIDGET(PWidget(wMain)),
1357
1214
                StoreOnClipboard(clipText);
1358
1215
#endif
1359
1216
#if PLAT_GTK_WIN32
1360
 
                if (selType == selRectangle) {
 
1217
                if (sel.IsRectangular()) {
1361
1218
                        ::OpenClipboard(NULL);
1362
1219
                        ::SetClipboardData(cfColumnSelect, 0);
1363
1220
                        ::CloseClipboard();
1378
1235
                ct.wDraw = gtk_drawing_area_new();
1379
1236
                GtkWidget *widcdrw = PWidget(ct.wDraw); //      // No code inside the G_OBJECT macro
1380
1237
                gtk_container_add(GTK_CONTAINER(PWidget(ct.wCallTip)), widcdrw);
1381
 
#if GLIB_MAJOR_VERSION < 2
1382
 
                gtk_signal_connect(GTK_OBJECT(widcdrw), "expose_event",
1383
 
                                   GtkSignalFunc(ScintillaGTK::ExposeCT), &ct);
1384
 
                gtk_signal_connect(GTK_OBJECT(widcdrw), "button_press_event",
1385
 
                                   GtkSignalFunc(ScintillaGTK::PressCT), static_cast<void *>(this));
1386
 
#else
1387
1238
                g_signal_connect(G_OBJECT(widcdrw), "expose_event",
1388
1239
                                   G_CALLBACK(ScintillaGTK::ExposeCT), &ct);
1389
1240
                g_signal_connect(G_OBJECT(widcdrw), "button_press_event",
1390
1241
                                   G_CALLBACK(ScintillaGTK::PressCT), static_cast<void *>(this));
1391
 
#endif
1392
1242
                gtk_widget_set_events(widcdrw,
1393
1243
                        GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK);
1394
1244
        }
1410
1260
            menuSig,
1411
1261
            cmd,
1412
1262
            const_cast<gchar *>(label[0] ? "<Item>" : "<Separator>"),
1413
 
#if GTK_MAJOR_VERSION >= 2
1414
1263
            NULL
1415
 
#endif
1416
1264
        };
1417
1265
        gtk_item_factory_create_item(GTK_ITEM_FACTORY(popup.GetID()),
1418
1266
                                     &itemEntry, this, 1);
1433
1281
void ScintillaGTK::ClaimSelection() {
1434
1282
        // X Windows has a 'primary selection' as well as the clipboard.
1435
1283
        // Whenever the user selects some text, we become the primary selection
1436
 
        if (currentPos != anchor && GTK_WIDGET_REALIZED(GTK_WIDGET(PWidget(wMain)))) {
 
1284
        if (!sel.Empty() && GTK_WIDGET_REALIZED(GTK_WIDGET(PWidget(wMain)))) {
1437
1285
                primarySelection = true;
1438
1286
                gtk_selection_owner_set(GTK_WIDGET(PWidget(wMain)),
1439
1287
                                        GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME);
1468
1316
        isRectangular = ::IsClipboardFormatAvailable(cfColumnSelect) != 0;
1469
1317
#else
1470
1318
        isRectangular = ((len > 2) && (data[len - 1] == 0 && data[len - 2] == '\n'));
 
1319
        if (isRectangular)
 
1320
                len--;  // Forget the extra '\0'
1471
1321
#endif
1472
1322
 
1473
1323
        char *dest;
1487
1337
        } else {        // UTF-8
1488
1338
                dest = Document::TransformLineEnds(&len, data, len, pdoc->eolMode);
1489
1339
                selText.Set(dest, len, SC_CP_UTF8, 0, isRectangular, false);
1490
 
#ifdef USE_CONVERTER
1491
1340
                const char *charSetBuffer = CharacterSetID();
1492
1341
                if (!IsUnicodeMode() && *charSetBuffer) {
1493
 
//fprintf(stderr, "Convert to locale %s\n", CharacterSetID());
1494
 
                                // Convert to locale
1495
 
                                dest = ConvertText(&len, selText.s, selText.len, charSetBuffer, "UTF-8", true);
1496
 
                                selText.Set(dest, len, pdoc->dbcsCodePage,
1497
 
                                        vs.styles[STYLE_DEFAULT].characterSet, selText.rectangular, false);
 
1342
                        // Convert to locale
 
1343
                        dest = ConvertText(&len, selText.s, selText.len, charSetBuffer, "UTF-8", true);
 
1344
                        selText.Set(dest, len, pdoc->dbcsCodePage,
 
1345
                                vs.styles[STYLE_DEFAULT].characterSet, selText.rectangular, false);
1498
1346
                }
1499
 
#endif
1500
1347
        }
1501
1348
}
1502
1349
 
1513
1360
                                SelectionText selText;
1514
1361
                                GetGtkSelectionText(selection_data, selText);
1515
1362
 
1516
 
                                pdoc->BeginUndoAction();
 
1363
                                UndoGroup ug(pdoc);
1517
1364
                                if (selection_data->selection != GDK_SELECTION_PRIMARY) {
1518
1365
                                        ClearSelection();
1519
1366
                                }
1520
 
                                int selStart = SelectionStart();
 
1367
                                SelectionPosition selStart = sel.IsRectangular() ?
 
1368
                                        sel.Rectangular().Start() :
 
1369
                                        sel.Range(sel.Main()).Start();
1521
1370
 
1522
1371
                                if (selText.rectangular) {
1523
1372
                                        PasteRectangular(selStart, selText.s, selText.len);
1524
1373
                                } else {
1525
 
                                        pdoc->InsertString(currentPos, selText.s, selText.len);
1526
 
                                        SetEmptySelection(currentPos + selText.len);
 
1374
                                        InsertPaste(selStart, selText.s, selText.len);
1527
1375
                                }
1528
 
                                pdoc->EndUndoAction();
1529
1376
                                EnsureCaretVisible();
1530
1377
                        }
1531
1378
                }
1574
1421
        }
1575
1422
#endif
1576
1423
 
1577
 
#if GTK_MAJOR_VERSION >= 2
1578
1424
        // Convert text to utf8 if it isn't already
1579
1425
        SelectionText *converted = 0;
1580
1426
        if ((text->codePage != SC_CP_UTF8) && (info == TARGET_UTF8_STRING)) {
1595
1441
        // All other tested aplications behave benignly by ignoring the \0.
1596
1442
        // The #if is here because on Windows cfColumnSelect clip entry is used
1597
1443
        // instead as standard indicator of rectangularness (so no need to kludge)
1598
 
        int len = strlen(text->s);
 
1444
        const char *textData = text->s ? text->s : "";
 
1445
        int len = strlen(textData);
1599
1446
#if PLAT_GTK_WIN32 == 0
1600
1447
        if (text->rectangular)
1601
1448
                len++;
1602
1449
#endif
1603
1450
 
1604
1451
        if (info == TARGET_UTF8_STRING) {
1605
 
                gtk_selection_data_set_text(selection_data, text->s, len);
 
1452
                gtk_selection_data_set_text(selection_data, textData, len);
1606
1453
        } else {
1607
1454
                gtk_selection_data_set(selection_data,
1608
1455
                        static_cast<GdkAtom>(GDK_SELECTION_TYPE_STRING),
1609
 
                        8, reinterpret_cast<unsigned char *>(text->s), len);
 
1456
                        8, reinterpret_cast<const unsigned char *>(textData), len);
1610
1457
        }
1611
1458
        delete converted;
1612
1459
 
1613
 
#else /* Gtk 1 */
1614
 
        char *selBuffer = text->s;
1615
 
 
1616
 
        char *tmputf = 0;
1617
 
        if ((info == TARGET_UTF8_STRING) || (info == TARGET_STRING)) {
1618
 
                int len = strlen(selBuffer);
1619
 
#ifdef USE_CONVERTER
1620
 
                // Possible character set conversion
1621
 
                const char *charSetBuffer = ::CharacterSetID(text->characterSet);
1622
 
                if (info == TARGET_UTF8_STRING) {
1623
 
                        //fprintf(stderr, "Copy to clipboard as UTF-8\n");
1624
 
                        if (text->codePage != SC_CP_UTF8) {
1625
 
                                // Convert to UTF-8
1626
 
                                //fprintf(stderr, "Convert to UTF-8 from %s\n", charSetBuffer);
1627
 
                                tmputf = ConvertText(&len, selBuffer, len, "UTF-8", charSetBuffer, false);
1628
 
                                selBuffer = tmputf;
1629
 
                        }
1630
 
                } else if (info == TARGET_STRING) {
1631
 
                        if (text->codePage == SC_CP_UTF8) {
1632
 
                                //fprintf(stderr, "Convert to locale %s\n", charSetBuffer);
1633
 
                                // Convert to locale
1634
 
                                tmputf = ConvertText(&len, selBuffer, len, charSetBuffer, "UTF-8", true);
1635
 
                                selBuffer = tmputf;
1636
 
                        }
1637
 
                }
1638
 
#endif
1639
 
 
1640
 
                // Here is a somewhat evil kludge.
1641
 
                // As I can not work out how to store data on the clipboard in multiple formats
1642
 
                // and need some way to mark the clipping as being stream or rectangular,
1643
 
                // the terminating \0 is included in the length for rectangular clippings.
1644
 
                // All other tested aplications behave benignly by ignoring the \0.
1645
 
                // The #if is here because on Windows cfColumnSelect clip entry is used
1646
 
                // instead as standard indicator of rectangularness (so no need to kludge)
1647
 
#if PLAT_GTK_WIN32 == 0
1648
 
                if (text->rectangular)
1649
 
                        len++;
1650
 
#endif
1651
 
                gtk_selection_data_set(selection_data,
1652
 
                                        (info == TARGET_STRING) ?
1653
 
                                        static_cast<GdkAtom>(GDK_SELECTION_TYPE_STRING) : atomUTF8,
1654
 
                                       8, reinterpret_cast<unsigned char *>(selBuffer),
1655
 
                                       len);
1656
 
        } else if ((info == TARGET_TEXT) || (info == TARGET_COMPOUND_TEXT)) {
1657
 
                guchar *text;
1658
 
                GdkAtom encoding;
1659
 
                gint format;
1660
 
                gint new_length;
1661
 
 
1662
 
                gdk_string_to_compound_text(reinterpret_cast<char *>(selBuffer),
1663
 
                                            &encoding, &format, &text, &new_length);
1664
 
                gtk_selection_data_set(selection_data, encoding, format, text, new_length);
1665
 
                gdk_free_compound_text(text);
1666
 
        }
1667
 
 
1668
 
        delete []tmputf;
1669
 
#endif /* Gtk >= 2 */
1670
 
 
1671
1460
#if PLAT_GTK_WIN32
1672
1461
        delete newline_normalized;
1673
1462
#endif
1726
1515
        int horizontalScrollBarHeight = scrollBarHeight;
1727
1516
        if (!showSBHorizontal)
1728
1517
                horizontalScrollBarHeight = 0;
1729
 
        int verticalScrollBarHeight = scrollBarWidth;
1730
 
        if (!verticalScrollBarVisible)
1731
 
                verticalScrollBarHeight = 0;
1732
1518
 
1733
1519
        GtkAllocation alloc;
1734
1520
        if (showSBHorizontal) {
1780
1566
        gtk_adjustment_set_value(adjustment, value);
1781
1567
}
1782
1568
 
 
1569
static int modifierTranslated(int sciModifier) {
 
1570
        switch (sciModifier) {
 
1571
                case SCMOD_SHIFT:
 
1572
                        return GDK_SHIFT_MASK;
 
1573
                case SCMOD_CTRL:
 
1574
                        return GDK_CONTROL_MASK;
 
1575
                case SCMOD_ALT:
 
1576
                        return GDK_MOD1_MASK;
 
1577
                case SCMOD_SUPER:
 
1578
                        return GDK_MOD4_MASK;
 
1579
                default:
 
1580
                        return 0;
 
1581
        }
 
1582
}
 
1583
 
1783
1584
gint ScintillaGTK::PressThis(GdkEventButton *event) {
1784
1585
        try {
1785
1586
                //Platform::DebugPrintf("Press %x time=%d state = %x button = %x\n",this,event->time, event->state, event->button);
1803
1604
 
1804
1605
                gtk_widget_grab_focus(PWidget(wMain));
1805
1606
                if (event->button == 1) {
1806
 
                        // On X, instead of sending literal modifiers use control instead of alt
 
1607
                        // On X, instead of sending literal modifiers use the user specified
 
1608
                        // modifier, defaulting to control instead of alt.
1807
1609
                        // This is because most X window managers grab alt + click for moving
1808
 
#if !PLAT_GTK_WIN32
1809
 
                        ButtonDown(pt, event->time,
1810
 
                                (event->state & GDK_SHIFT_MASK) != 0,
1811
 
                                (event->state & GDK_CONTROL_MASK) != 0,
1812
 
                                (event->state & GDK_CONTROL_MASK) != 0);
1813
 
#else
1814
 
                        ButtonDown(pt, event->time,
1815
 
                                (event->state & GDK_SHIFT_MASK) != 0,
1816
 
                                (event->state & GDK_CONTROL_MASK) != 0,
1817
 
                                (event->state & GDK_MOD1_MASK) != 0);
1818
 
#endif
 
1610
                        ButtonDown(pt, event->time,
 
1611
                                (event->state & GDK_SHIFT_MASK) != 0,
 
1612
                                (event->state & GDK_CONTROL_MASK) != 0,
 
1613
                                (event->state & modifierTranslated(rectangularSelectionModifier)) != 0);
1819
1614
                } else if (event->button == 2) {
1820
1615
                        // Grab the primary selection if it exists
1821
 
                        Position pos = PositionFromLocation(pt);
 
1616
                        SelectionPosition pos = SPositionFromLocation(pt, false, false, UserVirtualSpace());
1822
1617
                        if (OwnPrimarySelection() && primary.s == NULL)
1823
1618
                                CopySelectionRange(&primary);
1824
1619
 
 
1620
                        sel.Clear();
1825
1621
                        SetSelection(pos, pos);
1826
1622
                        atomSought = atomUTF8;
1827
1623
                        gtk_selection_convert(GTK_WIDGET(PWidget(wMain)), GDK_SELECTION_PRIMARY,
1853
1649
        } catch (...) {
1854
1650
                errorStatus = SC_STATUS_FAILURE;
1855
1651
        }
1856
 
#if GTK_MAJOR_VERSION >= 2
1857
1652
        return TRUE;
1858
 
#else
1859
 
        return FALSE;
1860
 
#endif
1861
1653
}
1862
1654
 
1863
1655
gint ScintillaGTK::Press(GtkWidget *widget, GdkEventButton *event) {
1893
1685
 
1894
1686
// win32gtk and GTK >= 2 use SCROLL_* events instead of passing the
1895
1687
// button4/5/6/7 events to the GTK app
1896
 
#if PLAT_GTK_WIN32 || (GTK_MAJOR_VERSION >= 2)
1897
1688
gint ScintillaGTK::ScrollEvent(GtkWidget *widget,
1898
1689
                               GdkEventScroll *event) {
1899
1690
        ScintillaGTK *sciThis = ScintillaFromWidget(widget);
1970
1761
        }
1971
1762
        return FALSE;
1972
1763
}
1973
 
#endif
1974
1764
 
1975
1765
gint ScintillaGTK::Motion(GtkWidget *widget, GdkEventMotion *event) {
1976
1766
        ScintillaGTK *sciThis = ScintillaFromWidget(widget);
2075
1865
        try {
2076
1866
                //fprintf(stderr, "SC-key: %d %x [%s]\n",
2077
1867
                //      event->keyval, event->state, (event->length > 0) ? event->string : "empty");
2078
 
#if GTK_MAJOR_VERSION >= 2
2079
1868
                if (gtk_im_context_filter_keypress(im_context, event)) {
2080
1869
                        return 1;
2081
1870
                }
2082
 
#endif
2083
1871
                if (!event->keyval) {
2084
1872
                        return true;
2085
1873
                }
2096
1884
                // This will have to change for Unicode
2097
1885
                else if (key >= 0xFE00)
2098
1886
                        key = KeyTranslate(key);
2099
 
#if GTK_MAJOR_VERSION < 2
2100
 
                else if (!IsUnicodeMode() && (key >= 0x100) && (key < 0x1000))
2101
 
                        key &= 0xff;
2102
 
#endif
2103
1887
 
2104
1888
                bool consumed = false;
2105
1889
                bool added = KeyDown(key, shift, ctrl, alt, &consumed) != 0;
2129
1913
        return FALSE;
2130
1914
}
2131
1915
 
2132
 
#if GTK_MAJOR_VERSION >= 2
2133
1916
gboolean ScintillaGTK::ExposePreeditThis(GtkWidget *widget, GdkEventExpose *ose) {
2134
1917
        try {
2135
1918
                gchar *str;
2222
2005
                        gint x, y;
2223
2006
                        gdk_window_get_origin((PWidget(wText))->window, &x, &y);
2224
2007
 
2225
 
                        Point pt = LocationFromPosition(currentPos);
 
2008
                        Point pt = PointMainCaret();
2226
2009
                        if (pt.x < 0)
2227
2010
                                pt.x = 0;
2228
2011
                        if (pt.y < 0)
2245
2028
void ScintillaGTK::PreeditChanged(GtkIMContext *, ScintillaGTK *sciThis) {
2246
2029
        sciThis->PreeditChangedThis();
2247
2030
}
2248
 
#endif
2249
2031
 
2250
2032
gint ScintillaGTK::StyleSetText(GtkWidget *widget, GtkStyle *, void*) {
2251
2033
        if (widget->window != NULL)
2259
2041
        return FALSE;
2260
2042
}
2261
2043
 
2262
 
#if GLIB_MAJOR_VERSION < 2
2263
 
void ScintillaGTK::Destroy(GtkObject *object)
2264
 
#else
2265
 
void ScintillaGTK::Destroy(GObject *object)
2266
 
#endif
2267
 
{
 
2044
void ScintillaGTK::Destroy(GObject *object) {
2268
2045
        try {
2269
2046
                ScintillaObject *scio = reinterpret_cast<ScintillaObject *>(object);
2270
2047
                // This avoids a double destruction
2274
2051
                //Platform::DebugPrintf("Destroying %x %x\n", sciThis, object);
2275
2052
                sciThis->Finalise();
2276
2053
 
2277
 
#if GLIB_MAJOR_VERSION < 2
2278
 
                if (GTK_OBJECT_CLASS(parent_class)->destroy)
2279
 
                        (* GTK_OBJECT_CLASS(parent_class)->destroy)(object);
2280
 
#else
2281
 
                // IS ANYTHING NEEDED ?
2282
 
#endif
2283
 
 
2284
2054
                delete sciThis;
2285
2055
                scio->pscin = 0;
2286
2056
        } catch (...) {
2308
2078
                        DrawChild(PWidget(sciThis->scrollbarv), area);
2309
2079
                }
2310
2080
 
2311
 
#ifdef INTERNATIONAL_INPUT
2312
 
                Point pt = sciThis->LocationFromPosition(sciThis->currentPos);
 
2081
                Point pt = sciThis->PointMainCaret();
2313
2082
                pt.y += sciThis->vs.lineHeight - 2;
2314
2083
                if (pt.x < 0) pt.x = 0;
2315
2084
                if (pt.y < 0) pt.y = 0;
2316
2085
                CursorMoved(widget, pt.x, pt.y, sciThis);
2317
 
#endif
2318
2086
        } catch (...) {
2319
2087
                sciThis->errorStatus = SC_STATUS_FAILURE;
2320
2088
        }
2330
2098
                rcPaint.bottom = ose->area.y + ose->area.height;
2331
2099
 
2332
2100
                PLATFORM_ASSERT(rgnUpdate == NULL);
2333
 
#if GTK_MAJOR_VERSION >= 2
2334
2101
                rgnUpdate = gdk_region_copy(ose->region);
2335
 
#endif
2336
2102
                PRectangle rcClient = GetClientRectangle();
2337
2103
                paintingAllText = rcPaint.Contains(rcClient);
2338
2104
                Surface *surfaceWindow = Surface::Allocate();
2375
2141
                //fprintf(stderr, "Expose %0d,%0d %0d,%0d\n",
2376
2142
                //ose->area.x, ose->area.y, ose->area.width, ose->area.height);
2377
2143
 
2378
 
#if GTK_MAJOR_VERSION < 2
2379
 
 
2380
 
                paintState = painting;
2381
 
 
2382
 
                rcPaint.left = ose->area.x;
2383
 
                rcPaint.top = ose->area.y;
2384
 
                rcPaint.right = ose->area.x + ose->area.width;
2385
 
                rcPaint.bottom = ose->area.y + ose->area.height;
2386
 
 
2387
 
                PRectangle rcClient = GetClientRectangle();
2388
 
                paintingAllText = rcPaint.Contains(rcClient);
2389
 
                Surface *surfaceWindow = Surface::Allocate();
2390
 
                if (surfaceWindow) {
2391
 
                        surfaceWindow->Init(PWidget(wMain)->window, PWidget(wMain));
2392
 
 
2393
 
                        // Fill the corner between the scrollbars
2394
 
                        if (verticalScrollBarVisible) {
2395
 
                                if (horizontalScrollBarVisible && (wrapState == eWrapNone)) {
2396
 
                                        PRectangle rcCorner = wMain.GetClientPosition();
2397
 
                                        rcCorner.left = rcCorner.right - scrollBarWidth + 1;
2398
 
                                        rcCorner.top = rcCorner.bottom - scrollBarHeight + 1;
2399
 
                                        //fprintf(stderr, "Corner %0d,%0d %0d,%0d\n",
2400
 
                                        //rcCorner.left, rcCorner.top, rcCorner.right, rcCorner.bottom);
2401
 
                                        surfaceWindow->FillRectangle(rcCorner,
2402
 
                                                vs.styles[STYLE_LINENUMBER].back.allocated);
2403
 
                                }
2404
 
                        }
2405
 
 
2406
 
                        //Paint(surfaceWindow, rcPaint);
2407
 
                        surfaceWindow->Release();
2408
 
                        delete surfaceWindow;
2409
 
                }
2410
 
                if (paintState == paintAbandoned) {
2411
 
                        // Painting area was insufficient to cover new styling or brace highlight positions
2412
 
                        FullPaint();
2413
 
                }
2414
 
                paintState = notPainting;
2415
 
 
2416
 
#else
2417
 
                // For GTK+ 2, the text is painted in ExposeText
 
2144
                // The text is painted in ExposeText
2418
2145
                gtk_container_propagate_expose(
2419
2146
                    GTK_CONTAINER(PWidget(wMain)), PWidget(scrollbarh), ose);
2420
2147
                gtk_container_propagate_expose(
2421
2148
                    GTK_CONTAINER(PWidget(wMain)), PWidget(scrollbarv), ose);
2422
 
#endif
2423
2149
 
2424
2150
        } catch (...) {
2425
2151
                errorStatus = SC_STATUS_FAILURE;
2478
2204
        return gtk_selection_clear(widget, selection_event);
2479
2205
}
2480
2206
 
2481
 
#if GTK_MAJOR_VERSION < 2
2482
 
gint ScintillaGTK::SelectionNotify(GtkWidget *widget, GdkEventSelection *selection_event) {
2483
 
        //Platform::DebugPrintf("Selection notify\n");
2484
 
        return gtk_selection_notify(widget, selection_event);
2485
 
}
2486
 
#endif
2487
 
 
2488
2207
void ScintillaGTK::DragBegin(GtkWidget *, GdkDragContext *) {
2489
2208
        //Platform::DebugPrintf("DragBegin\n");
2490
2209
}
2493
2212
                                 gint x, gint y, guint dragtime) {
2494
2213
        try {
2495
2214
                Point npt(x, y);
2496
 
                SetDragPosition(PositionFromLocation(npt));
 
2215
                SetDragPosition(SPositionFromLocation(npt, false, false, UserVirtualSpace()));
2497
2216
                GdkDragAction preferredAction = context->suggested_action;
2498
 
                int pos = PositionFromLocation(npt);
2499
 
                if ((inDragDrop == ddDragging) && (0 == PositionInSelection(pos))) {
 
2217
                SelectionPosition pos = SPositionFromLocation(npt);
 
2218
                if ((inDragDrop == ddDragging) && (PositionInSelection(pos.Position()))) {
2500
2219
                        // Avoid dragging selection onto itself as that produces a move
2501
2220
                        // with no real effect but which creates undo actions.
2502
2221
                        preferredAction = static_cast<GdkDragAction>(0);
2520
2239
void ScintillaGTK::DragLeave(GtkWidget *widget, GdkDragContext * /*context*/, guint) {
2521
2240
        ScintillaGTK *sciThis = ScintillaFromWidget(widget);
2522
2241
        try {
2523
 
                sciThis->SetDragPosition(invalidPosition);
 
2242
                sciThis->SetDragPosition(SelectionPosition(invalidPosition));
2524
2243
                //Platform::DebugPrintf("DragLeave %x\n", sciThis);
2525
2244
        } catch (...) {
2526
2245
                sciThis->errorStatus = SC_STATUS_FAILURE;
2533
2252
                // If drag did not result in drop here or elsewhere
2534
2253
                if (!sciThis->dragWasDropped)
2535
2254
                        sciThis->SetEmptySelection(sciThis->posDrag);
2536
 
                sciThis->SetDragPosition(invalidPosition);
 
2255
                sciThis->SetDragPosition(SelectionPosition(invalidPosition));
2537
2256
                //Platform::DebugPrintf("DragEnd %x %d\n", sciThis, sciThis->dragWasDropped);
2538
2257
                sciThis->inDragDrop = ddNone;
2539
2258
        } catch (...) {
2546
2265
        ScintillaGTK *sciThis = ScintillaFromWidget(widget);
2547
2266
        try {
2548
2267
                //Platform::DebugPrintf("Drop %x\n", sciThis);
2549
 
                sciThis->SetDragPosition(invalidPosition);
 
2268
                sciThis->SetDragPosition(SelectionPosition(invalidPosition));
2550
2269
        } catch (...) {
2551
2270
                sciThis->errorStatus = SC_STATUS_FAILURE;
2552
2271
        }
2558
2277
        ScintillaGTK *sciThis = ScintillaFromWidget(widget);
2559
2278
        try {
2560
2279
                sciThis->ReceivedDrop(selection_data);
2561
 
                sciThis->SetDragPosition(invalidPosition);
 
2280
                sciThis->SetDragPosition(SelectionPosition(invalidPosition));
2562
2281
        } catch (...) {
2563
2282
                sciThis->errorStatus = SC_STATUS_FAILURE;
2564
2283
        }
2569
2288
        ScintillaGTK *sciThis = ScintillaFromWidget(widget);
2570
2289
        try {
2571
2290
                sciThis->dragWasDropped = true;
2572
 
                if (sciThis->currentPos != sciThis->anchor) {
 
2291
                if (!sciThis->sel.Empty()) {
2573
2292
                        sciThis->GetSelection(selection_data, info, &sciThis->drag);
2574
2293
                }
2575
2294
                if (context->action == GDK_ACTION_MOVE) {
2576
 
                        int selStart = sciThis->SelectionStart();
2577
 
                        int selEnd = sciThis->SelectionEnd();
2578
 
                        if (sciThis->posDrop > selStart) {
2579
 
                                if (sciThis->posDrop > selEnd)
2580
 
                                        sciThis->posDrop = sciThis->posDrop - (selEnd - selStart);
2581
 
                                else
2582
 
                                        sciThis->posDrop = selStart;
2583
 
                                sciThis->posDrop = sciThis->pdoc->ClampPositionIntoDocument(sciThis->posDrop);
 
2295
                        for (size_t r=0; r<sciThis->sel.Count(); r++) {
 
2296
                                if (sciThis->posDrop >= sciThis->sel.Range(r).Start()) {
 
2297
                                        if (sciThis->posDrop > sciThis->sel.Range(r).End()) {
 
2298
                                                sciThis->posDrop.Add(-sciThis->sel.Range(r).Length());
 
2299
                                        } else {
 
2300
                                                sciThis->posDrop.Add(-SelectionRange(sciThis->posDrop, sciThis->sel.Range(r).Start()).Length());
 
2301
                                        }
 
2302
                                }
2584
2303
                        }
2585
2304
                        sciThis->ClearSelection();
2586
2305
                }
2587
 
                sciThis->SetDragPosition(invalidPosition);
 
2306
                sciThis->SetDragPosition(SelectionPosition(invalidPosition));
2588
2307
        } catch (...) {
2589
2308
                sciThis->errorStatus = SC_STATUS_FAILURE;
2590
2309
        }
2595
2314
        return 1;
2596
2315
}
2597
2316
 
2598
 
int ScintillaGTK::IdleCallback(ScintillaGTK *sciThis) {
2599
 
        // Idler will be automatically stoped, if there is nothing
 
2317
gboolean ScintillaGTK::IdleCallback(ScintillaGTK *sciThis) {
 
2318
        // Idler will be automatically stopped, if there is nothing
2600
2319
        // to do while idle.
2601
2320
        bool ret = sciThis->Idle();
2602
2321
        if (ret == false) {
2608
2327
        return ret;
2609
2328
}
2610
2329
 
 
2330
gboolean ScintillaGTK::StyleIdle(ScintillaGTK *sciThis) {
 
2331
        sciThis->IdleStyling();
 
2332
        // Idler will be automatically stopped
 
2333
        return FALSE;
 
2334
}
 
2335
 
 
2336
void ScintillaGTK::QueueStyling(int upTo) {
 
2337
        Editor::QueueStyling(upTo);
 
2338
        if (!styleNeeded.active) {
 
2339
                // Only allow one style needed to be queued
 
2340
                styleNeeded.active = true;
 
2341
                g_idle_add_full(G_PRIORITY_HIGH_IDLE, 
 
2342
                        reinterpret_cast<GSourceFunc>(StyleIdle), this, NULL);
 
2343
        }
 
2344
}
 
2345
 
2611
2346
void ScintillaGTK::PopUpCB(ScintillaGTK *sciThis, guint action, GtkWidget *) {
2612
2347
        if (action) {
2613
2348
                sciThis->Command(action);
2627
2362
                sciThis->CallTipClick();
2628
2363
        } catch (...) {
2629
2364
        }
2630
 
#if GTK_MAJOR_VERSION >= 2
2631
2365
        return TRUE;
2632
 
#else
2633
 
        return FALSE;
2634
 
#endif
2635
2366
}
2636
2367
 
2637
2368
gint ScintillaGTK::ExposeCT(GtkWidget *widget, GdkEventExpose * /*ose*/, CallTip *ctip) {
2667
2398
extern void Platform_Initialise();
2668
2399
extern void Platform_Finalise();
2669
2400
 
2670
 
#if GLIB_MAJOR_VERSION < 2
2671
 
GtkType scintilla_get_type() {
2672
 
        static GtkType scintilla_type = 0;
2673
 
        try {
2674
 
 
2675
 
                if (!scintilla_type) {
2676
 
                        Platform_Initialise();
2677
 
                        static GtkTypeInfo scintilla_info = {
2678
 
                                "Scintilla",
2679
 
                                sizeof (ScintillaObject),
2680
 
                                sizeof (ScintillaClass),
2681
 
                                (GtkClassInitFunc) scintilla_class_init,
2682
 
                                (GtkObjectInitFunc) scintilla_init,
2683
 
                                (gpointer) NULL,
2684
 
                                (gpointer) NULL,
2685
 
                                0
2686
 
                        };
2687
 
 
2688
 
                        scintilla_type = gtk_type_unique(gtk_container_get_type(), &scintilla_info);
2689
 
                }
2690
 
 
2691
 
        } catch (...) {
2692
 
        }
2693
 
        return scintilla_type;
2694
 
}
2695
 
#else
2696
2401
GType scintilla_get_type() {
2697
2402
        static GType scintilla_type = 0;
2698
2403
        try {
2722
2427
        }
2723
2428
        return scintilla_type;
2724
2429
}
2725
 
#endif
2726
2430
 
2727
2431
void ScintillaGTK::ClassInit(OBJECT_CLASS* object_class, GtkWidgetClass *widget_class, GtkContainerClass *container_class) {
2728
 
#if GLIB_MAJOR_VERSION >= 2
2729
2432
        Platform_Initialise();
2730
 
#endif
2731
2433
        atomClipboard = gdk_atom_intern("CLIPBOARD", FALSE);
2732
2434
        atomUTF8 = gdk_atom_intern("UTF8_STRING", FALSE);
2733
2435
        atomString = GDK_SELECTION_TYPE_STRING;
2738
2440
        // of the signal handlers here (those that currently attached to wDraw
2739
2441
        // in Initialise() may require coordinate translation?)
2740
2442
 
2741
 
#if GLIB_MAJOR_VERSION < 2
2742
 
        object_class->destroy = Destroy;
2743
 
#else
2744
2443
        object_class->finalize = Destroy;
2745
 
#endif
2746
2444
        widget_class->size_request = SizeRequest;
2747
2445
        widget_class->size_allocate = SizeAllocate;
2748
2446
        widget_class->expose_event = ExposeMain;
2749
 
#if GTK_MAJOR_VERSION < 2
2750
 
        widget_class->draw = Draw;
2751
 
#endif
2752
2447
        widget_class->motion_notify_event = Motion;
2753
2448
        widget_class->button_press_event = Press;
2754
2449
        widget_class->button_release_event = MouseRelease;
2755
 
#if PLAT_GTK_WIN32 || (GTK_MAJOR_VERSION >= 2)
2756
2450
        widget_class->scroll_event = ScrollEvent;
2757
 
#endif
2758
2451
        widget_class->key_press_event = KeyPress;
2759
2452
        widget_class->key_release_event = KeyRelease;
2760
2453
        widget_class->focus_in_event = FocusIn;
2762
2455
        widget_class->selection_received = SelectionReceived;
2763
2456
        widget_class->selection_get = SelectionGet;
2764
2457
        widget_class->selection_clear_event = SelectionClear;
2765
 
#if GTK_MAJOR_VERSION < 2
2766
 
        widget_class->selection_notify_event = SelectionNotify;
2767
 
#endif
2768
2458
 
2769
2459
        widget_class->drag_data_received = DragDataReceived;
2770
2460
        widget_class->drag_motion = DragMotion;
2781
2471
        container_class->forall = MainForAll;
2782
2472
}
2783
2473
 
2784
 
#if GLIB_MAJOR_VERSION < 2
2785
 
#define GTK_CLASS_TYPE(c) (c->type)
2786
 
#define SIG_MARSHAL gtk_marshal_NONE__INT_POINTER
2787
 
#define MARSHAL_ARGUMENTS GTK_TYPE_INT, GTK_TYPE_POINTER
2788
 
#else
2789
2474
#define SIG_MARSHAL scintilla_marshal_NONE__INT_POINTER
2790
2475
#define MARSHAL_ARGUMENTS G_TYPE_INT, G_TYPE_POINTER
2791
 
#endif
2792
2476
 
2793
2477
static void scintilla_class_init(ScintillaClass *klass) {
2794
2478
        try {
2796
2480
                GtkWidgetClass *widget_class = (GtkWidgetClass*) klass;
2797
2481
                GtkContainerClass *container_class = (GtkContainerClass*) klass;
2798
2482
 
2799
 
#if GLIB_MAJOR_VERSION < 2
2800
 
                parent_class = (GtkWidgetClass*) gtk_type_class(gtk_container_get_type());
2801
 
 
2802
 
                scintilla_signals[COMMAND_SIGNAL] = gtk_signal_new(
2803
 
                            "command",
2804
 
                            GTK_RUN_LAST,
2805
 
                            GTK_CLASS_TYPE(object_class),
2806
 
                            GTK_SIGNAL_OFFSET(ScintillaClass, command),
2807
 
                            SIG_MARSHAL,
2808
 
                            GTK_TYPE_NONE,
2809
 
                            2, MARSHAL_ARGUMENTS);
2810
 
 
2811
 
                scintilla_signals[NOTIFY_SIGNAL] = gtk_signal_new(
2812
 
                            SCINTILLA_NOTIFY,
2813
 
                            GTK_RUN_LAST,
2814
 
                            GTK_CLASS_TYPE(object_class),
2815
 
                            GTK_SIGNAL_OFFSET(ScintillaClass, notify),
2816
 
                            SIG_MARSHAL,
2817
 
                            GTK_TYPE_NONE,
2818
 
                            2, MARSHAL_ARGUMENTS);
2819
 
                gtk_object_class_add_signals(object_class,
2820
 
                        reinterpret_cast<unsigned int *>(scintilla_signals), LAST_SIGNAL);
2821
 
#else
2822
2483
                GSignalFlags sigflags = GSignalFlags(G_SIGNAL_ACTION | G_SIGNAL_RUN_LAST);
2823
2484
                scintilla_signals[COMMAND_SIGNAL] = g_signal_new(
2824
2485
                            "command",
2841
2502
                            SIG_MARSHAL,
2842
2503
                            G_TYPE_NONE,
2843
2504
                            2, MARSHAL_ARGUMENTS);
2844
 
#endif
 
2505
 
2845
2506
                klass->command = NULL;
2846
2507
                klass->notify = NULL;
2847
2508
 
2859
2520
}
2860
2521
 
2861
2522
GtkWidget* scintilla_new() {
2862
 
#if GLIB_MAJOR_VERSION < 2
2863
 
        return GTK_WIDGET(gtk_type_new(scintilla_get_type()));
2864
 
#else
2865
2523
        return GTK_WIDGET(g_object_new(scintilla_get_type(), NULL));
2866
 
#endif
2867
2524
}
2868
2525
 
2869
2526
void scintilla_set_id(ScintillaObject *sci, uptr_t id) {