~ubuntu-branches/ubuntu/wily/geany/wily

« back to all changes in this revision

Viewing changes to scintilla/ScintillaGTK.cxx

  • Committer: Package Import Robot
  • Author(s): Chow Loong Jin
  • Date: 2011-12-10 07:43:26 UTC
  • mfrom: (3.3.7 sid)
  • Revision ID: package-import@ubuntu.com-20111210074326-s8yqbew5i20h33tf
Tags: 0.21-1ubuntu1
* Merge from Debian Unstable, remaining changes:
  - debian/patches/20_use_evince_viewer.patch:
     + use evince as viewer for pdf and dvi files
  - debian/patches/20_use_x_terminal_emulator.patch:
     + use x-terminal-emulator as terminal
  - debian/control
     + Add breaks on geany-plugins-common << 0.20
* Also fixes bugs:
  - Filter for MATLAB/Octave files filters everythign (LP: 885505)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// Scintilla source code edit control
2
 
// ScintillaGTK.cxx - GTK+ specific subclass of ScintillaBase
3
 
// Copyright 1998-2004 by Neil Hodgson <neilh@scintilla.org>
4
 
// The License.txt file describes the conditions under which this software may be distributed.
5
 
 
6
 
#include <new>
7
 
#include <stdlib.h>
8
 
#include <string.h>
9
 
#include <stdio.h>
10
 
#include <ctype.h>
11
 
#include <time.h>
12
 
 
13
 
#include <string>
14
 
#include <vector>
15
 
 
16
 
#include <gtk/gtk.h>
17
 
#include <gdk/gdkkeysyms.h>
18
 
 
19
 
#include "Platform.h"
20
 
 
21
 
#if PLAT_GTK_WIN32
22
 
#include "windows.h"
23
 
#endif
24
 
 
25
 
#include "Scintilla.h"
26
 
#include "ScintillaWidget.h"
27
 
#ifdef SCI_LEXER
28
 
#include "SciLexer.h"
29
 
#include "PropSet.h"
30
 
#include "PropSetSimple.h"
31
 
#include "Accessor.h"
32
 
#include "KeyWords.h"
33
 
#endif
34
 
#include "SVector.h"
35
 
#include "SplitVector.h"
36
 
#include "Partitioning.h"
37
 
#include "RunStyles.h"
38
 
#include "ContractionState.h"
39
 
#include "CellBuffer.h"
40
 
#include "CallTip.h"
41
 
#include "KeyMap.h"
42
 
#include "Indicator.h"
43
 
#include "XPM.h"
44
 
#include "LineMarker.h"
45
 
#include "Style.h"
46
 
#include "AutoComplete.h"
47
 
#include "ViewStyle.h"
48
 
#include "Decoration.h"
49
 
#include "CharClassify.h"
50
 
#include "Document.h"
51
 
#include "Selection.h"
52
 
#include "PositionCache.h"
53
 
#include "Editor.h"
54
 
#include "ScintillaBase.h"
55
 
#include "UniConversion.h"
56
 
 
57
 
#include "gtk/gtksignal.h"
58
 
#include "gtk/gtkmarshal.h"
59
 
#include "scintilla-marshal.h"
60
 
 
61
 
#ifdef SCI_LEXER
62
 
#include <glib.h>
63
 
#include <gmodule.h>
64
 
#include "ExternalLexer.h"
65
 
#endif
66
 
 
67
 
#include "Converter.h"
68
 
 
69
 
#ifdef _MSC_VER
70
 
// Constant conditional expressions are because of GTK+ headers
71
 
#pragma warning(disable: 4127)
72
 
// Ignore unreferenced local functions in GTK+ headers
73
 
#pragma warning(disable: 4505)
74
 
#endif
75
 
 
76
 
#if GTK_CHECK_VERSION(2,6,0)
77
 
#define USE_GTK_CLIPBOARD
78
 
#endif
79
 
 
80
 
#define OBJECT_CLASS GObjectClass
81
 
 
82
 
#ifdef SCI_NAMESPACE
83
 
using namespace Scintilla;
84
 
#endif
85
 
 
86
 
extern char *UTF8FromLatin1(const char *s, int &len);
87
 
 
88
 
class ScintillaGTK : public ScintillaBase {
89
 
        _ScintillaObject *sci;
90
 
        Window wText;
91
 
        Window scrollbarv;
92
 
        Window scrollbarh;
93
 
        GtkObject *adjustmentv;
94
 
        GtkObject *adjustmenth;
95
 
        int scrollBarWidth;
96
 
        int scrollBarHeight;
97
 
 
98
 
        // Because clipboard access is asynchronous, copyText is created by Copy
99
 
#ifndef USE_GTK_CLIPBOARD
100
 
        SelectionText copyText;
101
 
#endif
102
 
 
103
 
        SelectionText primary;
104
 
 
105
 
        GdkEventButton evbtn;
106
 
        bool capturedMouse;
107
 
        bool dragWasDropped;
108
 
        int lastKey;
109
 
        int rectangularSelectionModifier;
110
 
 
111
 
        GtkWidgetClass *parentClass;
112
 
 
113
 
        static GdkAtom atomClipboard;
114
 
        static GdkAtom atomUTF8;
115
 
        static GdkAtom atomString;
116
 
        static GdkAtom atomUriList;
117
 
        static GdkAtom atomDROPFILES_DND;
118
 
        GdkAtom atomSought;
119
 
 
120
 
#if PLAT_GTK_WIN32
121
 
        CLIPFORMAT cfColumnSelect;
122
 
#endif
123
 
 
124
 
        Window wPreedit;
125
 
        Window wPreeditDraw;
126
 
        GtkIMContext *im_context;
127
 
 
128
 
        // Wheel mouse support
129
 
        unsigned int linesPerScroll;
130
 
        GTimeVal lastWheelMouseTime;
131
 
        gint lastWheelMouseDirection;
132
 
        gint wheelMouseIntensity;
133
 
 
134
 
        GdkRegion *rgnUpdate;
135
 
 
136
 
        // Private so ScintillaGTK objects can not be copied
137
 
        ScintillaGTK(const ScintillaGTK &);
138
 
        ScintillaGTK &operator=(const ScintillaGTK &);
139
 
 
140
 
public:
141
 
        ScintillaGTK(_ScintillaObject *sci_);
142
 
        virtual ~ScintillaGTK();
143
 
        static void ClassInit(OBJECT_CLASS* object_class, GtkWidgetClass *widget_class, GtkContainerClass *container_class);
144
 
private:
145
 
        virtual void Initialise();
146
 
        virtual void Finalise();
147
 
        virtual void DisplayCursor(Window::Cursor c);
148
 
        virtual bool DragThreshold(Point ptStart, Point ptNow);
149
 
        virtual void StartDrag();
150
 
        int TargetAsUTF8(char *text);
151
 
        int EncodedFromUTF8(char *utf8, char *encoded);
152
 
        virtual bool ValidCodePage(int codePage) const;
153
 
public:         // Public for scintilla_send_message
154
 
        virtual sptr_t WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
155
 
private:
156
 
        virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
157
 
        virtual void SetTicking(bool on);
158
 
        virtual bool SetIdle(bool on);
159
 
        virtual void SetMouseCapture(bool on);
160
 
        virtual bool HaveMouseCapture();
161
 
        virtual bool PaintContains(PRectangle rc);
162
 
        void FullPaint();
163
 
        virtual PRectangle GetClientRectangle();
164
 
        void SyncPaint(PRectangle rc);
165
 
        virtual void ScrollText(int linesToMove);
166
 
        virtual void SetVerticalScrollPos();
167
 
        virtual void SetHorizontalScrollPos();
168
 
        virtual bool ModifyScrollBars(int nMax, int nPage);
169
 
        void ReconfigureScrollBars();
170
 
        virtual void NotifyChange();
171
 
        virtual void NotifyFocus(bool focus);
172
 
        virtual void NotifyParent(SCNotification scn);
173
 
        void NotifyKey(int key, int modifiers);
174
 
        void NotifyURIDropped(const char *list);
175
 
        const char *CharacterSetID() const;
176
 
        virtual CaseFolder *CaseFolderForEncoding();
177
 
        virtual std::string CaseMapString(const std::string &s, int caseMapping);
178
 
        virtual int KeyDefault(int key, int modifiers);
179
 
        virtual void CopyToClipboard(const SelectionText &selectedText);
180
 
        virtual void Copy();
181
 
        virtual void Paste();
182
 
        virtual void CreateCallTipWindow(PRectangle rc);
183
 
        virtual void AddToPopUp(const char *label, int cmd = 0, bool enabled = true);
184
 
        bool OwnPrimarySelection();
185
 
        virtual void ClaimSelection();
186
 
        void GetGtkSelectionText(GtkSelectionData *selectionData, SelectionText &selText);
187
 
        void ReceivedSelection(GtkSelectionData *selection_data);
188
 
        void ReceivedDrop(GtkSelectionData *selection_data);
189
 
        static void GetSelection(GtkSelectionData *selection_data, guint info, SelectionText *selected);
190
 
#ifdef USE_GTK_CLIPBOARD
191
 
        void StoreOnClipboard(SelectionText *clipText);
192
 
        static void ClipboardGetSelection(GtkClipboard* clip, GtkSelectionData *selection_data, guint info, void *data);
193
 
        static void ClipboardClearSelection(GtkClipboard* clip, void *data);
194
 
#endif
195
 
 
196
 
        void UnclaimSelection(GdkEventSelection *selection_event);
197
 
        void Resize(int width, int height);
198
 
 
199
 
        // Callback functions
200
 
        void RealizeThis(GtkWidget *widget);
201
 
        static void Realize(GtkWidget *widget);
202
 
        void UnRealizeThis(GtkWidget *widget);
203
 
        static void UnRealize(GtkWidget *widget);
204
 
        void MapThis();
205
 
        static void Map(GtkWidget *widget);
206
 
        void UnMapThis();
207
 
        static void UnMap(GtkWidget *widget);
208
 
        static gint CursorMoved(GtkWidget *widget, int xoffset, int yoffset, ScintillaGTK *sciThis);
209
 
        gint FocusInThis(GtkWidget *widget);
210
 
        static gint FocusIn(GtkWidget *widget, GdkEventFocus *event);
211
 
        gint FocusOutThis(GtkWidget *widget);
212
 
        static gint FocusOut(GtkWidget *widget, GdkEventFocus *event);
213
 
        static void SizeRequest(GtkWidget *widget, GtkRequisition *requisition);
214
 
        static void SizeAllocate(GtkWidget *widget, GtkAllocation *allocation);
215
 
        gint Expose(GtkWidget *widget, GdkEventExpose *ose);
216
 
        static gint ExposeMain(GtkWidget *widget, GdkEventExpose *ose);
217
 
        static void Draw(GtkWidget *widget, GdkRectangle *area);
218
 
        void ForAll(GtkCallback callback, gpointer callback_data);
219
 
        static void MainForAll(GtkContainer *container, gboolean include_internals, GtkCallback callback, gpointer callback_data);
220
 
 
221
 
        static void ScrollSignal(GtkAdjustment *adj, ScintillaGTK *sciThis);
222
 
        static void ScrollHSignal(GtkAdjustment *adj, ScintillaGTK *sciThis);
223
 
        gint PressThis(GdkEventButton *event);
224
 
        static gint Press(GtkWidget *widget, GdkEventButton *event);
225
 
        static gint MouseRelease(GtkWidget *widget, GdkEventButton *event);
226
 
        static gint ScrollEvent(GtkWidget *widget, GdkEventScroll *event);
227
 
        static gint Motion(GtkWidget *widget, GdkEventMotion *event);
228
 
        gboolean KeyThis(GdkEventKey *event);
229
 
        static gboolean KeyPress(GtkWidget *widget, GdkEventKey *event);
230
 
        static gboolean KeyRelease(GtkWidget *widget, GdkEventKey *event);
231
 
        gboolean ExposePreeditThis(GtkWidget *widget, GdkEventExpose *ose);
232
 
        static gboolean ExposePreedit(GtkWidget *widget, GdkEventExpose *ose, ScintillaGTK *sciThis);
233
 
        void CommitThis(char *str);
234
 
        static void Commit(GtkIMContext *context, char *str, ScintillaGTK *sciThis);
235
 
        void PreeditChangedThis();
236
 
        static void PreeditChanged(GtkIMContext *context, ScintillaGTK *sciThis);
237
 
        static gint StyleSetText(GtkWidget *widget, GtkStyle *previous, void*);
238
 
        static gint RealizeText(GtkWidget *widget, void*);
239
 
        static void Destroy(GObject *object);
240
 
        static void SelectionReceived(GtkWidget *widget, GtkSelectionData *selection_data,
241
 
                                      guint time);
242
 
        static void SelectionGet(GtkWidget *widget, GtkSelectionData *selection_data,
243
 
                                 guint info, guint time);
244
 
        static gint SelectionClear(GtkWidget *widget, GdkEventSelection *selection_event);
245
 
        static void DragBegin(GtkWidget *widget, GdkDragContext *context);
246
 
        gboolean DragMotionThis(GdkDragContext *context, gint x, gint y, guint dragtime);
247
 
        static gboolean DragMotion(GtkWidget *widget, GdkDragContext *context,
248
 
                                   gint x, gint y, guint dragtime);
249
 
        static void DragLeave(GtkWidget *widget, GdkDragContext *context,
250
 
                              guint time);
251
 
        static void DragEnd(GtkWidget *widget, GdkDragContext *context);
252
 
        static gboolean Drop(GtkWidget *widget, GdkDragContext *context,
253
 
                             gint x, gint y, guint time);
254
 
        static void DragDataReceived(GtkWidget *widget, GdkDragContext *context,
255
 
                                     gint x, gint y, GtkSelectionData *selection_data, guint info, guint time);
256
 
        static void DragDataGet(GtkWidget *widget, GdkDragContext *context,
257
 
                                GtkSelectionData *selection_data, guint info, guint time);
258
 
        static gint TimeOut(ScintillaGTK *sciThis);
259
 
        static gboolean IdleCallback(ScintillaGTK *sciThis);
260
 
        static gboolean StyleIdle(ScintillaGTK *sciThis);
261
 
        virtual void QueueStyling(int upTo);
262
 
        static void PopUpCB(ScintillaGTK *sciThis, guint action, GtkWidget *widget);
263
 
 
264
 
        gint ExposeTextThis(GtkWidget *widget, GdkEventExpose *ose);
265
 
        static gint ExposeText(GtkWidget *widget, GdkEventExpose *ose, ScintillaGTK *sciThis);
266
 
 
267
 
        static gint ExposeCT(GtkWidget *widget, GdkEventExpose *ose, CallTip *ct);
268
 
        static gint PressCT(GtkWidget *widget, GdkEventButton *event, ScintillaGTK *sciThis);
269
 
 
270
 
        static sptr_t DirectFunction(ScintillaGTK *sciThis,
271
 
                                     unsigned int iMessage, uptr_t wParam, sptr_t lParam);
272
 
};
273
 
 
274
 
enum {
275
 
    COMMAND_SIGNAL,
276
 
    NOTIFY_SIGNAL,
277
 
    LAST_SIGNAL
278
 
};
279
 
 
280
 
static gint scintilla_signals[LAST_SIGNAL] = { 0 };
281
 
 
282
 
enum {
283
 
    TARGET_STRING,
284
 
    TARGET_TEXT,
285
 
    TARGET_COMPOUND_TEXT,
286
 
    TARGET_UTF8_STRING,
287
 
    TARGET_URI
288
 
};
289
 
 
290
 
GdkAtom ScintillaGTK::atomClipboard = 0;
291
 
GdkAtom ScintillaGTK::atomUTF8 = 0;
292
 
GdkAtom ScintillaGTK::atomString = 0;
293
 
GdkAtom ScintillaGTK::atomUriList = 0;
294
 
GdkAtom ScintillaGTK::atomDROPFILES_DND = 0;
295
 
 
296
 
static const GtkTargetEntry clipboardCopyTargets[] = {
297
 
        { (gchar *) "UTF8_STRING", 0, TARGET_UTF8_STRING },
298
 
        { (gchar *) "STRING", 0, TARGET_STRING },
299
 
};
300
 
static const gint nClipboardCopyTargets = sizeof(clipboardCopyTargets) / sizeof(clipboardCopyTargets[0]);
301
 
 
302
 
static const GtkTargetEntry clipboardPasteTargets[] = {
303
 
        { (gchar *) "text/uri-list", 0, TARGET_URI },
304
 
        { (gchar *) "UTF8_STRING", 0, TARGET_UTF8_STRING },
305
 
        { (gchar *) "STRING", 0, TARGET_STRING },
306
 
};
307
 
static const gint nClipboardPasteTargets = sizeof(clipboardPasteTargets) / sizeof(clipboardPasteTargets[0]);
308
 
 
309
 
static GtkWidget *PWidget(Window &w) {
310
 
        return reinterpret_cast<GtkWidget *>(w.GetID());
311
 
}
312
 
 
313
 
static ScintillaGTK *ScintillaFromWidget(GtkWidget *widget) {
314
 
        ScintillaObject *scio = reinterpret_cast<ScintillaObject *>(widget);
315
 
        return reinterpret_cast<ScintillaGTK *>(scio->pscin);
316
 
}
317
 
 
318
 
ScintillaGTK::ScintillaGTK(_ScintillaObject *sci_) :
319
 
                adjustmentv(0), adjustmenth(0),
320
 
                scrollBarWidth(30), scrollBarHeight(30),
321
 
                capturedMouse(false), dragWasDropped(false),
322
 
                lastKey(0), rectangularSelectionModifier(SCMOD_CTRL), parentClass(0),
323
 
                im_context(NULL),
324
 
                lastWheelMouseDirection(0),
325
 
                wheelMouseIntensity(0),
326
 
                rgnUpdate(0) {
327
 
        sci = sci_;
328
 
        wMain = GTK_WIDGET(sci);
329
 
 
330
 
#if PLAT_GTK_WIN32
331
 
        rectangularSelectionModifier = SCMOD_ALT;
332
 
#else
333
 
        rectangularSelectionModifier = SCMOD_CTRL;
334
 
#endif
335
 
 
336
 
#if PLAT_GTK_WIN32
337
 
        // There does not seem to be a real standard for indicating that the clipboard
338
 
        // contains a rectangular selection, so copy Developer Studio.
339
 
        cfColumnSelect = static_cast<CLIPFORMAT>(
340
 
                ::RegisterClipboardFormat("MSDEVColumnSelect"));
341
 
 
342
 
        // Get intellimouse parameters when running on win32; otherwise use
343
 
        // reasonable default
344
 
#ifndef SPI_GETWHEELSCROLLLINES
345
 
#define SPI_GETWHEELSCROLLLINES   104
346
 
#endif
347
 
        ::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &linesPerScroll, 0);
348
 
#else
349
 
        linesPerScroll = 4;
350
 
#endif
351
 
        lastWheelMouseTime.tv_sec = 0;
352
 
        lastWheelMouseTime.tv_usec = 0;
353
 
 
354
 
        Initialise();
355
 
}
356
 
 
357
 
ScintillaGTK::~ScintillaGTK() {
358
 
        g_idle_remove_by_data(this);
359
 
}
360
 
 
361
 
void ScintillaGTK::RealizeThis(GtkWidget *widget) {
362
 
        //Platform::DebugPrintf("ScintillaGTK::realize this\n");
363
 
        GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED);
364
 
        GdkWindowAttr attrs;
365
 
        attrs.window_type = GDK_WINDOW_CHILD;
366
 
        attrs.x = widget->allocation.x;
367
 
        attrs.y = widget->allocation.y;
368
 
        attrs.width = widget->allocation.width;
369
 
        attrs.height = widget->allocation.height;
370
 
        attrs.wclass = GDK_INPUT_OUTPUT;
371
 
        attrs.visual = gtk_widget_get_visual(widget);
372
 
        attrs.colormap = gtk_widget_get_colormap(widget);
373
 
        attrs.event_mask = gtk_widget_get_events(widget) | GDK_EXPOSURE_MASK;
374
 
        GdkCursor *cursor = gdk_cursor_new(GDK_XTERM);
375
 
        attrs.cursor = cursor;
376
 
        widget->window = gdk_window_new(gtk_widget_get_parent_window(widget), &attrs,
377
 
                GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP | GDK_WA_CURSOR);
378
 
        gdk_window_set_user_data(widget->window, widget);
379
 
        gdk_window_set_background(widget->window, &widget->style->bg[GTK_STATE_NORMAL]);
380
 
        gdk_window_show(widget->window);
381
 
        gdk_cursor_destroy(cursor);
382
 
        widget->style = gtk_style_attach(widget->style, widget->window);
383
 
        wPreedit = gtk_window_new(GTK_WINDOW_POPUP);
384
 
        wPreeditDraw = gtk_drawing_area_new();
385
 
        GtkWidget *predrw = PWidget(wPreeditDraw);      // No code inside the G_OBJECT macro
386
 
        g_signal_connect(G_OBJECT(predrw), "expose_event",
387
 
                G_CALLBACK(ExposePreedit), this);
388
 
        gtk_container_add(GTK_CONTAINER(PWidget(wPreedit)), predrw);
389
 
        gtk_widget_realize(PWidget(wPreedit));
390
 
        gtk_widget_realize(predrw);
391
 
        gtk_widget_show(predrw);
392
 
 
393
 
        im_context = gtk_im_multicontext_new();
394
 
        g_signal_connect(G_OBJECT(im_context), "commit",
395
 
                G_CALLBACK(Commit), this);
396
 
        g_signal_connect(G_OBJECT(im_context), "preedit_changed",
397
 
                G_CALLBACK(PreeditChanged), this);
398
 
        gtk_im_context_set_client_window(im_context, widget->window);
399
 
        GtkWidget *widtxt = PWidget(wText);     //      // No code inside the G_OBJECT macro
400
 
        g_signal_connect_after(G_OBJECT(widtxt), "style_set",
401
 
                G_CALLBACK(ScintillaGTK::StyleSetText), NULL);
402
 
        g_signal_connect_after(G_OBJECT(widtxt), "realize",
403
 
                G_CALLBACK(ScintillaGTK::RealizeText), NULL);
404
 
        gtk_widget_realize(widtxt);
405
 
        gtk_widget_realize(PWidget(scrollbarv));
406
 
        gtk_widget_realize(PWidget(scrollbarh));
407
 
}
408
 
 
409
 
void ScintillaGTK::Realize(GtkWidget *widget) {
410
 
        ScintillaGTK *sciThis = ScintillaFromWidget(widget);
411
 
        sciThis->RealizeThis(widget);
412
 
}
413
 
 
414
 
void ScintillaGTK::UnRealizeThis(GtkWidget *widget) {
415
 
        try {
416
 
                if (GTK_WIDGET_MAPPED(widget)) {
417
 
                        gtk_widget_unmap(widget);
418
 
                }
419
 
                GTK_WIDGET_UNSET_FLAGS(widget, GTK_REALIZED);
420
 
                gtk_widget_unrealize(PWidget(wText));
421
 
                gtk_widget_unrealize(PWidget(scrollbarv));
422
 
                gtk_widget_unrealize(PWidget(scrollbarh));
423
 
                gtk_widget_unrealize(PWidget(wPreedit));
424
 
                gtk_widget_unrealize(PWidget(wPreeditDraw));
425
 
                g_object_unref(im_context);
426
 
                im_context = NULL;
427
 
                if (GTK_WIDGET_CLASS(parentClass)->unrealize)
428
 
                        GTK_WIDGET_CLASS(parentClass)->unrealize(widget);
429
 
 
430
 
                Finalise();
431
 
        } catch (...) {
432
 
                errorStatus = SC_STATUS_FAILURE;
433
 
        }
434
 
}
435
 
 
436
 
void ScintillaGTK::UnRealize(GtkWidget *widget) {
437
 
        ScintillaGTK *sciThis = ScintillaFromWidget(widget);
438
 
        sciThis->UnRealizeThis(widget);
439
 
}
440
 
 
441
 
static void MapWidget(GtkWidget *widget) {
442
 
        if (widget &&
443
 
                GTK_WIDGET_VISIBLE(widget) &&
444
 
                !GTK_WIDGET_MAPPED(widget)) {
445
 
                gtk_widget_map(widget);
446
 
        }
447
 
}
448
 
 
449
 
void ScintillaGTK::MapThis() {
450
 
        try {
451
 
                //Platform::DebugPrintf("ScintillaGTK::map this\n");
452
 
                GTK_WIDGET_SET_FLAGS(PWidget(wMain), GTK_MAPPED);
453
 
                MapWidget(PWidget(wText));
454
 
                MapWidget(PWidget(scrollbarh));
455
 
                MapWidget(PWidget(scrollbarv));
456
 
                wMain.SetCursor(Window::cursorArrow);
457
 
                scrollbarv.SetCursor(Window::cursorArrow);
458
 
                scrollbarh.SetCursor(Window::cursorArrow);
459
 
                ChangeSize();
460
 
                gdk_window_show(PWidget(wMain)->window);
461
 
        } catch (...) {
462
 
                errorStatus = SC_STATUS_FAILURE;
463
 
        }
464
 
}
465
 
 
466
 
void ScintillaGTK::Map(GtkWidget *widget) {
467
 
        ScintillaGTK *sciThis = ScintillaFromWidget(widget);
468
 
        sciThis->MapThis();
469
 
}
470
 
 
471
 
void ScintillaGTK::UnMapThis() {
472
 
        try {
473
 
                //Platform::DebugPrintf("ScintillaGTK::unmap this\n");
474
 
                GTK_WIDGET_UNSET_FLAGS(PWidget(wMain), GTK_MAPPED);
475
 
                DropGraphics();
476
 
                gdk_window_hide(PWidget(wMain)->window);
477
 
                gtk_widget_unmap(PWidget(wText));
478
 
                gtk_widget_unmap(PWidget(scrollbarh));
479
 
                gtk_widget_unmap(PWidget(scrollbarv));
480
 
        } catch (...) {
481
 
                errorStatus = SC_STATUS_FAILURE;
482
 
        }
483
 
}
484
 
 
485
 
void ScintillaGTK::UnMap(GtkWidget *widget) {
486
 
        ScintillaGTK *sciThis = ScintillaFromWidget(widget);
487
 
        sciThis->UnMapThis();
488
 
}
489
 
 
490
 
void ScintillaGTK::ForAll(GtkCallback callback, gpointer callback_data) {
491
 
        try {
492
 
                (*callback) (PWidget(wText), callback_data);
493
 
                (*callback) (PWidget(scrollbarv), callback_data);
494
 
                (*callback) (PWidget(scrollbarh), callback_data);
495
 
        } catch (...) {
496
 
                errorStatus = SC_STATUS_FAILURE;
497
 
        }
498
 
}
499
 
 
500
 
void ScintillaGTK::MainForAll(GtkContainer *container, gboolean include_internals, GtkCallback callback, gpointer callback_data) {
501
 
        ScintillaGTK *sciThis = ScintillaFromWidget((GtkWidget *)container);
502
 
 
503
 
        if (callback != NULL && include_internals) {
504
 
                sciThis->ForAll(callback, callback_data);
505
 
        }
506
 
}
507
 
 
508
 
gint ScintillaGTK::CursorMoved(GtkWidget *, int xoffset, int yoffset, ScintillaGTK *sciThis) {
509
 
        GdkRectangle area;
510
 
        area.x = xoffset;
511
 
        area.y = yoffset;
512
 
        area.width = 1;
513
 
        area.height = 1;
514
 
        gtk_im_context_set_cursor_location(sciThis->im_context, &area);
515
 
        return FALSE;
516
 
}
517
 
 
518
 
gint ScintillaGTK::FocusInThis(GtkWidget *widget) {
519
 
        try {
520
 
                GTK_WIDGET_SET_FLAGS(widget, GTK_HAS_FOCUS);
521
 
                SetFocusState(true);
522
 
                if (im_context != NULL) {
523
 
                        gchar *str = NULL;
524
 
                        gint cursor_pos;
525
 
 
526
 
                        gtk_im_context_get_preedit_string(im_context, &str, NULL, &cursor_pos);
527
 
                        if (PWidget(wPreedit) != NULL) {
528
 
                                if (strlen(str) > 0) {
529
 
                                        gtk_widget_show(PWidget(wPreedit));
530
 
                                } else {
531
 
                                        gtk_widget_hide(PWidget(wPreedit));
532
 
                                }
533
 
                        }
534
 
                        g_free(str);
535
 
                        gtk_im_context_focus_in(im_context);
536
 
                }
537
 
 
538
 
        } catch (...) {
539
 
                errorStatus = SC_STATUS_FAILURE;
540
 
        }
541
 
        return FALSE;
542
 
}
543
 
 
544
 
gint ScintillaGTK::FocusIn(GtkWidget *widget, GdkEventFocus * /*event*/) {
545
 
        ScintillaGTK *sciThis = ScintillaFromWidget(widget);
546
 
        return sciThis->FocusInThis(widget);
547
 
}
548
 
 
549
 
gint ScintillaGTK::FocusOutThis(GtkWidget *widget) {
550
 
        try {
551
 
                GTK_WIDGET_UNSET_FLAGS(widget, GTK_HAS_FOCUS);
552
 
                SetFocusState(false);
553
 
 
554
 
                if (PWidget(wPreedit) != NULL)
555
 
                        gtk_widget_hide(PWidget(wPreedit));
556
 
                if (im_context != NULL)
557
 
                        gtk_im_context_focus_out(im_context);
558
 
 
559
 
        } catch (...) {
560
 
                errorStatus = SC_STATUS_FAILURE;
561
 
        }
562
 
        return FALSE;
563
 
}
564
 
 
565
 
gint ScintillaGTK::FocusOut(GtkWidget *widget, GdkEventFocus * /*event*/) {
566
 
        ScintillaGTK *sciThis = ScintillaFromWidget(widget);
567
 
        return sciThis->FocusOutThis(widget);
568
 
}
569
 
 
570
 
void ScintillaGTK::SizeRequest(GtkWidget *widget, GtkRequisition *requisition) {
571
 
        ScintillaGTK *sciThis = ScintillaFromWidget(widget);
572
 
        requisition->width = 600;
573
 
        requisition->height = gdk_screen_height();
574
 
        GtkRequisition child_requisition;
575
 
        gtk_widget_size_request(PWidget(sciThis->scrollbarh), &child_requisition);
576
 
        gtk_widget_size_request(PWidget(sciThis->scrollbarv), &child_requisition);
577
 
}
578
 
 
579
 
void ScintillaGTK::SizeAllocate(GtkWidget *widget, GtkAllocation *allocation) {
580
 
        ScintillaGTK *sciThis = ScintillaFromWidget(widget);
581
 
        try {
582
 
                widget->allocation = *allocation;
583
 
                if (GTK_WIDGET_REALIZED(widget))
584
 
                        gdk_window_move_resize(widget->window,
585
 
                                widget->allocation.x,
586
 
                                widget->allocation.y,
587
 
                                widget->allocation.width,
588
 
                                widget->allocation.height);
589
 
 
590
 
                sciThis->Resize(allocation->width, allocation->height);
591
 
 
592
 
        } catch (...) {
593
 
                sciThis->errorStatus = SC_STATUS_FAILURE;
594
 
        }
595
 
}
596
 
 
597
 
void ScintillaGTK::Initialise() {
598
 
        //Platform::DebugPrintf("ScintillaGTK::Initialise\n");
599
 
        parentClass = reinterpret_cast<GtkWidgetClass *>(
600
 
                          gtk_type_class(gtk_container_get_type()));
601
 
 
602
 
        GTK_WIDGET_SET_FLAGS(PWidget(wMain), GTK_CAN_FOCUS);
603
 
        GTK_WIDGET_SET_FLAGS(GTK_WIDGET(PWidget(wMain)), GTK_SENSITIVE);
604
 
        gtk_widget_set_events(PWidget(wMain),
605
 
                              GDK_EXPOSURE_MASK
606
 
                              | GDK_STRUCTURE_MASK
607
 
                              | GDK_KEY_PRESS_MASK
608
 
                              | GDK_KEY_RELEASE_MASK
609
 
                              | GDK_FOCUS_CHANGE_MASK
610
 
                              | GDK_LEAVE_NOTIFY_MASK
611
 
                              | GDK_BUTTON_PRESS_MASK
612
 
                              | GDK_BUTTON_RELEASE_MASK
613
 
                              | GDK_POINTER_MOTION_MASK
614
 
                              | GDK_POINTER_MOTION_HINT_MASK);
615
 
 
616
 
        wText = gtk_drawing_area_new();
617
 
        gtk_widget_set_parent(PWidget(wText), PWidget(wMain));
618
 
        GtkWidget *widtxt = PWidget(wText);     // No code inside the G_OBJECT macro
619
 
        gtk_widget_show(widtxt);
620
 
        g_signal_connect(G_OBJECT(widtxt), "expose_event",
621
 
                           G_CALLBACK(ScintillaGTK::ExposeText), this);
622
 
        gtk_widget_set_events(widtxt, GDK_EXPOSURE_MASK);
623
 
        // Avoid background drawing flash
624
 
        gtk_widget_set_double_buffered(widtxt, FALSE);
625
 
        gtk_drawing_area_size(GTK_DRAWING_AREA(widtxt),
626
 
                              100,100);
627
 
        adjustmentv = gtk_adjustment_new(0.0, 0.0, 201.0, 1.0, 20.0, 20.0);
628
 
        scrollbarv = gtk_vscrollbar_new(GTK_ADJUSTMENT(adjustmentv));
629
 
        GTK_WIDGET_UNSET_FLAGS(PWidget(scrollbarv), GTK_CAN_FOCUS);
630
 
        g_signal_connect(G_OBJECT(adjustmentv), "value_changed",
631
 
                           G_CALLBACK(ScrollSignal), this);
632
 
        gtk_widget_set_parent(PWidget(scrollbarv), PWidget(wMain));
633
 
        gtk_widget_show(PWidget(scrollbarv));
634
 
 
635
 
        adjustmenth = gtk_adjustment_new(0.0, 0.0, 101.0, 1.0, 20.0, 20.0);
636
 
        scrollbarh = gtk_hscrollbar_new(GTK_ADJUSTMENT(adjustmenth));
637
 
        GTK_WIDGET_UNSET_FLAGS(PWidget(scrollbarh), GTK_CAN_FOCUS);
638
 
        g_signal_connect(G_OBJECT(adjustmenth), "value_changed",
639
 
                           G_CALLBACK(ScrollHSignal), this);
640
 
        gtk_widget_set_parent(PWidget(scrollbarh), PWidget(wMain));
641
 
        gtk_widget_show(PWidget(scrollbarh));
642
 
 
643
 
        gtk_widget_grab_focus(PWidget(wMain));
644
 
 
645
 
        gtk_selection_add_targets(GTK_WIDGET(PWidget(wMain)), GDK_SELECTION_PRIMARY,
646
 
                                  clipboardCopyTargets, nClipboardCopyTargets);
647
 
 
648
 
#ifndef USE_GTK_CLIPBOARD
649
 
        gtk_selection_add_targets(GTK_WIDGET(PWidget(wMain)), atomClipboard,
650
 
                                  clipboardPasteTargets, nClipboardPasteTargets);
651
 
#endif
652
 
 
653
 
        gtk_drag_dest_set(GTK_WIDGET(PWidget(wMain)),
654
 
                          GTK_DEST_DEFAULT_ALL, clipboardPasteTargets, nClipboardPasteTargets,
655
 
                          static_cast<GdkDragAction>(GDK_ACTION_COPY | GDK_ACTION_MOVE));
656
 
 
657
 
        // Set caret period based on GTK settings
658
 
        gboolean blinkOn = false;
659
 
        if (g_object_class_find_property(G_OBJECT_GET_CLASS(
660
 
                        G_OBJECT(gtk_settings_get_default())), "gtk-cursor-blink")) {
661
 
                g_object_get(G_OBJECT(
662
 
                        gtk_settings_get_default()), "gtk-cursor-blink", &blinkOn, NULL);
663
 
        }
664
 
        if (blinkOn &&
665
 
                g_object_class_find_property(G_OBJECT_GET_CLASS(
666
 
                        G_OBJECT(gtk_settings_get_default())), "gtk-cursor-blink-time")) {
667
 
                gint value;
668
 
                g_object_get(G_OBJECT(
669
 
                        gtk_settings_get_default()), "gtk-cursor-blink-time", &value, NULL);
670
 
                caret.period = gint(value / 1.75);
671
 
        } else {
672
 
                caret.period = 0;
673
 
        }
674
 
 
675
 
        SetTicking(true);
676
 
}
677
 
 
678
 
void ScintillaGTK::Finalise() {
679
 
        SetTicking(false);
680
 
        ScintillaBase::Finalise();
681
 
}
682
 
 
683
 
void ScintillaGTK::DisplayCursor(Window::Cursor c) {
684
 
        if (cursorMode == SC_CURSORNORMAL)
685
 
                wText.SetCursor(c);
686
 
        else
687
 
                wText.SetCursor(static_cast<Window::Cursor>(cursorMode));
688
 
}
689
 
 
690
 
bool ScintillaGTK::DragThreshold(Point ptStart, Point ptNow) {
691
 
        return gtk_drag_check_threshold(GTK_WIDGET(PWidget(wMain)),
692
 
                ptStart.x, ptStart.y, ptNow.x, ptNow.y);
693
 
}
694
 
 
695
 
void ScintillaGTK::StartDrag() {
696
 
        dragWasDropped = false;
697
 
        inDragDrop = ddDragging;
698
 
        GtkTargetList *tl = gtk_target_list_new(clipboardCopyTargets, nClipboardCopyTargets);
699
 
        gtk_drag_begin(GTK_WIDGET(PWidget(wMain)),
700
 
                       tl,
701
 
                       static_cast<GdkDragAction>(GDK_ACTION_COPY | GDK_ACTION_MOVE),
702
 
                       evbtn.button,
703
 
                       reinterpret_cast<GdkEvent *>(&evbtn));
704
 
}
705
 
 
706
 
static char *ConvertText(int *lenResult, char *s, size_t len, const char *charSetDest,
707
 
        const char *charSetSource, bool transliterations, bool silent=false) {
708
 
        // s is not const because of different versions of iconv disagreeing about const
709
 
        *lenResult = 0;
710
 
        char *destForm = 0;
711
 
        Converter conv(charSetDest, charSetSource, transliterations);
712
 
        if (conv) {
713
 
                destForm = new char[len*3+1];
714
 
                char *pin = s;
715
 
                size_t inLeft = len;
716
 
                char *pout = destForm;
717
 
                size_t outLeft = len*3+1;
718
 
                size_t conversions = conv.Convert(&pin, &inLeft, &pout, &outLeft);
719
 
                if (conversions == ((size_t)(-1))) {
720
 
                        if (!silent)
721
 
                                fprintf(stderr, "iconv %s->%s failed for %s\n", 
722
 
                                        charSetSource, charSetDest, static_cast<char *>(s));
723
 
                        delete []destForm;
724
 
                        destForm = 0;
725
 
                } else {
726
 
//fprintf(stderr, "iconv OK %s %d\n", destForm, pout - destForm);
727
 
                        *pout = '\0';
728
 
                        *lenResult = pout - destForm;
729
 
                }
730
 
        } else {
731
 
fprintf(stderr, "Can not iconv %s %s\n", charSetDest, charSetSource);
732
 
        }
733
 
        if (!destForm) {
734
 
                destForm = new char[1];
735
 
                destForm[0] = '\0';
736
 
                *lenResult = 0;
737
 
        }
738
 
        return destForm;
739
 
}
740
 
 
741
 
// Returns the target converted to UTF8.
742
 
// Return the length in bytes.
743
 
int ScintillaGTK::TargetAsUTF8(char *text) {
744
 
        int targetLength = targetEnd - targetStart;
745
 
        if (IsUnicodeMode()) {
746
 
                if (text) {
747
 
                        pdoc->GetCharRange(text, targetStart, targetLength);
748
 
                }
749
 
        } else {
750
 
                // Need to convert
751
 
                const char *charSetBuffer = CharacterSetID();
752
 
                if (*charSetBuffer) {
753
 
//~ fprintf(stderr, "AsUTF8 %s %d  %0d-%0d\n", charSetBuffer, targetLength, targetStart, targetEnd);
754
 
                        char *s = new char[targetLength];
755
 
                        if (s) {
756
 
                                pdoc->GetCharRange(s, targetStart, targetLength);
757
 
//~ fprintf(stderr, "    \"%s\"\n", s);
758
 
                                if (text) {
759
 
                                        char *tmputf = ConvertText(&targetLength, s, targetLength, "UTF-8", charSetBuffer, false);
760
 
                                        memcpy(text, tmputf, targetLength);
761
 
                                        delete []tmputf;
762
 
//~ fprintf(stderr, "    \"%s\"\n", text);
763
 
                                }
764
 
                                delete []s;
765
 
                        }
766
 
                } else {
767
 
                        if (text) {
768
 
                                pdoc->GetCharRange(text, targetStart, targetLength);
769
 
                        }
770
 
                }
771
 
        }
772
 
//~ fprintf(stderr, "Length = %d bytes\n", targetLength);
773
 
        return targetLength;
774
 
}
775
 
 
776
 
// Translates a nul terminated UTF8 string into the document encoding.
777
 
// Return the length of the result in bytes.
778
 
int ScintillaGTK::EncodedFromUTF8(char *utf8, char *encoded) {
779
 
        int inputLength = (lengthForEncode >= 0) ? lengthForEncode : strlen(utf8);
780
 
        if (IsUnicodeMode()) {
781
 
                if (encoded) {
782
 
                        memcpy(encoded, utf8, inputLength);
783
 
                }
784
 
                return inputLength;
785
 
        } else {
786
 
                // Need to convert
787
 
                const char *charSetBuffer = CharacterSetID();
788
 
                if (*charSetBuffer) {
789
 
                        int outLength = 0;
790
 
                        char *tmpEncoded = ConvertText(&outLength, utf8, inputLength, charSetBuffer, "UTF-8", true);
791
 
                        if (tmpEncoded) {
792
 
                                if (encoded) {
793
 
                                        memcpy(encoded, tmpEncoded, outLength);
794
 
                                }
795
 
                                delete []tmpEncoded;
796
 
                        }
797
 
                        return outLength;
798
 
                } else {
799
 
                        if (encoded) {
800
 
                                memcpy(encoded, utf8, inputLength);
801
 
                        }
802
 
                        return inputLength;
803
 
                }
804
 
        }
805
 
        // Fail
806
 
        return 0;
807
 
}
808
 
 
809
 
bool ScintillaGTK::ValidCodePage(int codePage) const {
810
 
        return codePage == 0
811
 
        || codePage == SC_CP_UTF8
812
 
        || codePage == 932
813
 
        || codePage == 936
814
 
        || codePage == 950
815
 
        || codePage == SC_CP_DBCS;
816
 
}
817
 
 
818
 
sptr_t ScintillaGTK::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
819
 
        try {
820
 
                switch (iMessage) {
821
 
 
822
 
                case SCI_GRABFOCUS:
823
 
                        gtk_widget_grab_focus(PWidget(wMain));
824
 
                        break;
825
 
 
826
 
                case SCI_GETDIRECTFUNCTION:
827
 
                        return reinterpret_cast<sptr_t>(DirectFunction);
828
 
 
829
 
                case SCI_GETDIRECTPOINTER:
830
 
                        return reinterpret_cast<sptr_t>(this);
831
 
 
832
 
#ifdef SCI_LEXER
833
 
                case SCI_LOADLEXERLIBRARY:
834
 
                        LexerManager::GetInstance()->Load(reinterpret_cast<const char*>(lParam));
835
 
                        break;
836
 
#endif
837
 
                case SCI_TARGETASUTF8:
838
 
                        return TargetAsUTF8(reinterpret_cast<char*>(lParam));
839
 
 
840
 
                case SCI_ENCODEDFROMUTF8:
841
 
                        return EncodedFromUTF8(reinterpret_cast<char*>(wParam),
842
 
                                reinterpret_cast<char*>(lParam));
843
 
 
844
 
                case SCI_SETRECTANGULARSELECTIONMODIFIER:
845
 
                        rectangularSelectionModifier = wParam;
846
 
                        break;
847
 
 
848
 
                case SCI_GETRECTANGULARSELECTIONMODIFIER:
849
 
                        return rectangularSelectionModifier;
850
 
 
851
 
                default:
852
 
                        return ScintillaBase::WndProc(iMessage, wParam, lParam);
853
 
                }
854
 
        } catch (std::bad_alloc&) {
855
 
                errorStatus = SC_STATUS_BADALLOC;
856
 
        } catch (...) {
857
 
                errorStatus = SC_STATUS_FAILURE;
858
 
        }
859
 
        return 0l;
860
 
}
861
 
 
862
 
sptr_t ScintillaGTK::DefWndProc(unsigned int, uptr_t, sptr_t) {
863
 
        return 0;
864
 
}
865
 
 
866
 
void ScintillaGTK::SetTicking(bool on) {
867
 
        if (timer.ticking != on) {
868
 
                timer.ticking = on;
869
 
                if (timer.ticking) {
870
 
                        timer.tickerID = reinterpret_cast<TickerID>(gtk_timeout_add(timer.tickSize, (GtkFunction)TimeOut, this));
871
 
                } else {
872
 
                        gtk_timeout_remove(GPOINTER_TO_UINT(timer.tickerID));
873
 
                }
874
 
        }
875
 
        timer.ticksToWait = caret.period;
876
 
}
877
 
 
878
 
bool ScintillaGTK::SetIdle(bool on) {
879
 
        if (on) {
880
 
                // Start idler, if it's not running.
881
 
                if (!idler.state) {
882
 
                        idler.state = true;
883
 
                        idler.idlerID = reinterpret_cast<IdlerID>(
884
 
                                g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, 
885
 
                                        reinterpret_cast<GSourceFunc>(IdleCallback), this, NULL));
886
 
                }
887
 
        } else {
888
 
                // Stop idler, if it's running
889
 
                if (idler.state) {
890
 
                        idler.state = false;
891
 
                        g_source_remove(GPOINTER_TO_UINT(idler.idlerID));
892
 
                }
893
 
        }
894
 
        return true;
895
 
}
896
 
 
897
 
void ScintillaGTK::SetMouseCapture(bool on) {
898
 
        if (mouseDownCaptures) {
899
 
                if (on) {
900
 
                        gtk_grab_add(GTK_WIDGET(PWidget(wMain)));
901
 
                } else {
902
 
                        gtk_grab_remove(GTK_WIDGET(PWidget(wMain)));
903
 
                }
904
 
        }
905
 
        capturedMouse = on;
906
 
}
907
 
 
908
 
bool ScintillaGTK::HaveMouseCapture() {
909
 
        return capturedMouse;
910
 
}
911
 
 
912
 
bool ScintillaGTK::PaintContains(PRectangle rc) {
913
 
        bool contains = true;
914
 
        if (paintState == painting) {
915
 
                if (!rcPaint.Contains(rc)) {
916
 
                        contains = false;
917
 
                } else if (rgnUpdate) {
918
 
                        GdkRectangle grc = {rc.left, rc.top,
919
 
                                rc.right - rc.left, rc.bottom - rc.top};
920
 
                        if (gdk_region_rect_in(rgnUpdate, &grc) != GDK_OVERLAP_RECTANGLE_IN) {
921
 
                                contains = false;
922
 
                        }
923
 
                }
924
 
        }
925
 
        return contains;
926
 
}
927
 
 
928
 
// Redraw all of text area. This paint will not be abandoned.
929
 
void ScintillaGTK::FullPaint() {
930
 
        wText.InvalidateAll();
931
 
}
932
 
 
933
 
PRectangle ScintillaGTK::GetClientRectangle() {
934
 
        PRectangle rc = wMain.GetClientPosition();
935
 
        if (verticalScrollBarVisible)
936
 
                rc.right -= scrollBarWidth;
937
 
        if (horizontalScrollBarVisible && (wrapState == eWrapNone))
938
 
                rc.bottom -= scrollBarHeight;
939
 
        // Move to origin
940
 
        rc.right -= rc.left;
941
 
        rc.bottom -= rc.top;
942
 
        rc.left = 0;
943
 
        rc.top = 0;
944
 
        return rc;
945
 
}
946
 
 
947
 
// Synchronously paint a rectangle of the window.
948
 
void ScintillaGTK::SyncPaint(PRectangle rc) {
949
 
        paintState = painting;
950
 
        rcPaint = rc;
951
 
        PRectangle rcClient = GetClientRectangle();
952
 
        paintingAllText = rcPaint.Contains(rcClient);
953
 
        if ((PWidget(wText))->window) {
954
 
                Surface *sw = Surface::Allocate();
955
 
                if (sw) {
956
 
                        sw->Init(PWidget(wText)->window, PWidget(wText));
957
 
                        Paint(sw, rc);
958
 
                        sw->Release();
959
 
                        delete sw;
960
 
                }
961
 
        }
962
 
        if (paintState == paintAbandoned) {
963
 
                // Painting area was insufficient to cover new styling or brace highlight positions
964
 
                FullPaint();
965
 
        }
966
 
        paintState = notPainting;
967
 
}
968
 
 
969
 
void ScintillaGTK::ScrollText(int linesToMove) {
970
 
        int diff = vs.lineHeight * -linesToMove;
971
 
        //Platform::DebugPrintf("ScintillaGTK::ScrollText %d %d %0d,%0d %0d,%0d\n", linesToMove, diff,
972
 
        //      rc.left, rc.top, rc.right, rc.bottom);
973
 
        GtkWidget *wi = PWidget(wText);
974
 
 
975
 
        gdk_window_scroll(wi->window, 0, -diff);
976
 
        gdk_window_process_updates(wi->window, FALSE);
977
 
}
978
 
 
979
 
void ScintillaGTK::SetVerticalScrollPos() {
980
 
        DwellEnd(true);
981
 
        gtk_adjustment_set_value(GTK_ADJUSTMENT(adjustmentv), topLine);
982
 
}
983
 
 
984
 
void ScintillaGTK::SetHorizontalScrollPos() {
985
 
        DwellEnd(true);
986
 
        gtk_adjustment_set_value(GTK_ADJUSTMENT(adjustmenth), xOffset / 2);
987
 
}
988
 
 
989
 
bool ScintillaGTK::ModifyScrollBars(int nMax, int nPage) {
990
 
        bool modified = false;
991
 
        int pageScroll = LinesToScroll();
992
 
 
993
 
        if (GTK_ADJUSTMENT(adjustmentv)->upper != (nMax + 1) ||
994
 
                GTK_ADJUSTMENT(adjustmentv)->page_size != nPage ||
995
 
                GTK_ADJUSTMENT(adjustmentv)->page_increment != pageScroll) {
996
 
                GTK_ADJUSTMENT(adjustmentv)->upper = nMax + 1;
997
 
                GTK_ADJUSTMENT(adjustmentv)->page_size = nPage;
998
 
                GTK_ADJUSTMENT(adjustmentv)->page_increment = pageScroll;
999
 
                gtk_adjustment_changed(GTK_ADJUSTMENT(adjustmentv));
1000
 
                modified = true;
1001
 
        }
1002
 
 
1003
 
        PRectangle rcText = GetTextRectangle();
1004
 
        int horizEndPreferred = scrollWidth;
1005
 
        if (horizEndPreferred < 0)
1006
 
                horizEndPreferred = 0;
1007
 
        unsigned int pageWidth = rcText.Width();
1008
 
        unsigned int pageIncrement = pageWidth / 3;
1009
 
        unsigned int charWidth = vs.styles[STYLE_DEFAULT].aveCharWidth;
1010
 
        if (GTK_ADJUSTMENT(adjustmenth)->upper != horizEndPreferred ||
1011
 
                GTK_ADJUSTMENT(adjustmenth)->page_size != pageWidth ||
1012
 
                GTK_ADJUSTMENT(adjustmenth)->page_increment != pageIncrement ||
1013
 
                GTK_ADJUSTMENT(adjustmenth)->step_increment != charWidth) {
1014
 
                GTK_ADJUSTMENT(adjustmenth)->upper = horizEndPreferred;
1015
 
                GTK_ADJUSTMENT(adjustmenth)->step_increment = charWidth;
1016
 
                GTK_ADJUSTMENT(adjustmenth)->page_size = pageWidth;
1017
 
                GTK_ADJUSTMENT(adjustmenth)->page_increment = pageIncrement;
1018
 
                gtk_adjustment_changed(GTK_ADJUSTMENT(adjustmenth));
1019
 
                modified = true;
1020
 
        }
1021
 
        return modified;
1022
 
}
1023
 
 
1024
 
void ScintillaGTK::ReconfigureScrollBars() {
1025
 
        PRectangle rc = wMain.GetClientPosition();
1026
 
        Resize(rc.Width(), rc.Height());
1027
 
}
1028
 
 
1029
 
void ScintillaGTK::NotifyChange() {
1030
 
        g_signal_emit(G_OBJECT(sci), scintilla_signals[COMMAND_SIGNAL], 0,
1031
 
                        Platform::LongFromTwoShorts(GetCtrlID(), SCEN_CHANGE), PWidget(wMain));
1032
 
}
1033
 
 
1034
 
void ScintillaGTK::NotifyFocus(bool focus) {
1035
 
        g_signal_emit(G_OBJECT(sci), scintilla_signals[COMMAND_SIGNAL], 0,
1036
 
                        Platform::LongFromTwoShorts
1037
 
                                        (GetCtrlID(), focus ? SCEN_SETFOCUS : SCEN_KILLFOCUS), PWidget(wMain));
1038
 
}
1039
 
 
1040
 
void ScintillaGTK::NotifyParent(SCNotification scn) {
1041
 
        scn.nmhdr.hwndFrom = PWidget(wMain);
1042
 
        scn.nmhdr.idFrom = GetCtrlID();
1043
 
        g_signal_emit(G_OBJECT(sci), scintilla_signals[NOTIFY_SIGNAL], 0,
1044
 
                        GetCtrlID(), &scn);
1045
 
}
1046
 
 
1047
 
void ScintillaGTK::NotifyKey(int key, int modifiers) {
1048
 
        SCNotification scn = {0};
1049
 
        scn.nmhdr.code = SCN_KEY;
1050
 
        scn.ch = key;
1051
 
        scn.modifiers = modifiers;
1052
 
 
1053
 
        NotifyParent(scn);
1054
 
}
1055
 
 
1056
 
void ScintillaGTK::NotifyURIDropped(const char *list) {
1057
 
        SCNotification scn = {0};
1058
 
        scn.nmhdr.code = SCN_URIDROPPED;
1059
 
        scn.text = list;
1060
 
 
1061
 
        NotifyParent(scn);
1062
 
}
1063
 
 
1064
 
const char *CharacterSetID(int characterSet);
1065
 
 
1066
 
const char *ScintillaGTK::CharacterSetID() const {
1067
 
        return ::CharacterSetID(vs.styles[STYLE_DEFAULT].characterSet);
1068
 
}
1069
 
 
1070
 
class CaseFolderUTF8 : public CaseFolderTable {
1071
 
public:
1072
 
        CaseFolderUTF8() {
1073
 
                StandardASCII();
1074
 
        }
1075
 
        virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) {
1076
 
                if ((lenMixed == 1) && (sizeFolded > 0)) {
1077
 
                        folded[0] = mapping[static_cast<unsigned char>(mixed[0])];
1078
 
                        return 1;
1079
 
                } else {
1080
 
                        gchar *mapped = g_utf8_casefold(mixed, lenMixed);
1081
 
                        size_t lenMapped = strlen(mapped);
1082
 
                        if (lenMapped < sizeFolded) {
1083
 
                                memcpy(folded, mapped,  lenMapped);
1084
 
                        } else {
1085
 
                                lenMapped = 0;
1086
 
                        }
1087
 
                        g_free(mapped);
1088
 
                        return lenMapped;
1089
 
                }
1090
 
        }
1091
 
};
1092
 
 
1093
 
CaseFolder *ScintillaGTK::CaseFolderForEncoding() {
1094
 
        if (pdoc->dbcsCodePage == SC_CP_UTF8) {
1095
 
                return new CaseFolderUTF8();
1096
 
        } else {
1097
 
                CaseFolderTable *pcf = new CaseFolderTable();
1098
 
                const char *charSetBuffer = CharacterSetID();
1099
 
                if ((pdoc->dbcsCodePage == 0) && charSetBuffer) {
1100
 
                        pcf->StandardASCII();
1101
 
                        // Only for single byte encodings
1102
 
                        for (int i=0x80; i<0x100; i++) {
1103
 
                                char sCharacter[2] = "A";
1104
 
                                sCharacter[0] = i;
1105
 
                                int convertedLength = 1;
1106
 
                                const char *sUTF8 = ConvertText(&convertedLength, sCharacter, 1,
1107
 
                                        "UTF-8", charSetBuffer, false);
1108
 
                                if (sUTF8) {
1109
 
                                        gchar *mapped = g_utf8_casefold(sUTF8, strlen(sUTF8));
1110
 
                                        if (mapped) {
1111
 
                                                int mappedLength = strlen(mapped);
1112
 
                                                const char *mappedBack = ConvertText(&mappedLength, mapped,
1113
 
                                                        mappedLength, charSetBuffer, "UTF-8", false, true);
1114
 
                                                if (mappedBack && (strlen(mappedBack) == 1) && (mappedBack[0] != sCharacter[0])) {
1115
 
                                                        pcf->SetTranslation(sCharacter[0], mappedBack[0]);
1116
 
                                                }
1117
 
                                                delete []mappedBack;
1118
 
                                                g_free(mapped);
1119
 
                                        }
1120
 
                                }
1121
 
                                delete []sUTF8;
1122
 
                        }
1123
 
                }
1124
 
                return pcf;
1125
 
        }
1126
 
}
1127
 
 
1128
 
std::string ScintillaGTK::CaseMapString(const std::string &s, int caseMapping) {
1129
 
        if (s.size() == 0)
1130
 
                return std::string();
1131
 
 
1132
 
        if (caseMapping == cmSame)
1133
 
                return s;
1134
 
 
1135
 
        const char *needsFree1 = 0;     // Must be freed with delete []
1136
 
        const char *charSetBuffer = CharacterSetID();
1137
 
        const char *sUTF8 = s.c_str();
1138
 
        int rangeBytes = s.size();
1139
 
 
1140
 
        int convertedLength = rangeBytes;
1141
 
        // Change text to UTF-8
1142
 
        if (!IsUnicodeMode()) {
1143
 
                // Need to convert
1144
 
                if (*charSetBuffer) {
1145
 
                        sUTF8 = ConvertText(&convertedLength, const_cast<char *>(s.c_str()), rangeBytes,
1146
 
                                "UTF-8", charSetBuffer, false);
1147
 
                        needsFree1 = sUTF8;
1148
 
                }
1149
 
        }
1150
 
        gchar *mapped;  // Must be freed with g_free
1151
 
        if (caseMapping == cmUpper) {
1152
 
                mapped = g_utf8_strup(sUTF8, convertedLength);
1153
 
        } else {
1154
 
                mapped = g_utf8_strdown(sUTF8, convertedLength);
1155
 
        }
1156
 
        int mappedLength = strlen(mapped);
1157
 
        char *mappedBack = mapped;
1158
 
 
1159
 
        char *needsFree2 = 0;   // Must be freed with delete []
1160
 
        if (!IsUnicodeMode()) {
1161
 
                if (*charSetBuffer) {
1162
 
                        mappedBack = ConvertText(&mappedLength, mapped, mappedLength, charSetBuffer, "UTF-8", false);
1163
 
                        needsFree2 = mappedBack;
1164
 
                }
1165
 
        }
1166
 
 
1167
 
        std::string ret(mappedBack, mappedLength);
1168
 
        g_free(mapped);
1169
 
        delete []needsFree1;
1170
 
        delete []needsFree2;
1171
 
        return ret;
1172
 
}
1173
 
 
1174
 
int ScintillaGTK::KeyDefault(int key, int modifiers) {
1175
 
        if (!(modifiers & SCI_CTRL) && !(modifiers & SCI_ALT)) {
1176
 
                if (key < 256) {
1177
 
                        NotifyKey(key, modifiers);
1178
 
                        return 0;
1179
 
                } else {
1180
 
                        // Pass up to container in case it is an accelerator
1181
 
                        NotifyKey(key, modifiers);
1182
 
                        return 0;
1183
 
                }
1184
 
        } else {
1185
 
                // Pass up to container in case it is an accelerator
1186
 
                NotifyKey(key, modifiers);
1187
 
                return 0;
1188
 
        }
1189
 
        //Platform::DebugPrintf("SK-key: %d %x %x\n",key, modifiers);
1190
 
}
1191
 
 
1192
 
void ScintillaGTK::CopyToClipboard(const SelectionText &selectedText) {
1193
 
#ifndef USE_GTK_CLIPBOARD
1194
 
        copyText.Copy(selectedText);
1195
 
        gtk_selection_owner_set(GTK_WIDGET(PWidget(wMain)),
1196
 
                                atomClipboard,
1197
 
                                GDK_CURRENT_TIME);
1198
 
#else
1199
 
        SelectionText *clipText = new SelectionText();
1200
 
        clipText->Copy(selectedText);
1201
 
        StoreOnClipboard(clipText);
1202
 
#endif
1203
 
}
1204
 
 
1205
 
void ScintillaGTK::Copy() {
1206
 
        if (!sel.Empty()) {
1207
 
#ifndef USE_GTK_CLIPBOARD
1208
 
                CopySelectionRange(&copyText);
1209
 
                gtk_selection_owner_set(GTK_WIDGET(PWidget(wMain)),
1210
 
                                        atomClipboard,
1211
 
                                        GDK_CURRENT_TIME);
1212
 
#else
1213
 
                SelectionText *clipText = new SelectionText();
1214
 
                CopySelectionRange(clipText);
1215
 
                StoreOnClipboard(clipText);
1216
 
#endif
1217
 
#if PLAT_GTK_WIN32
1218
 
                if (sel.IsRectangular()) {
1219
 
                        ::OpenClipboard(NULL);
1220
 
                        ::SetClipboardData(cfColumnSelect, 0);
1221
 
                        ::CloseClipboard();
1222
 
                }
1223
 
#endif
1224
 
        }
1225
 
}
1226
 
 
1227
 
void ScintillaGTK::Paste() {
1228
 
        atomSought = atomUTF8;
1229
 
        gtk_selection_convert(GTK_WIDGET(PWidget(wMain)),
1230
 
                              atomClipboard, atomSought, GDK_CURRENT_TIME);
1231
 
}
1232
 
 
1233
 
void ScintillaGTK::CreateCallTipWindow(PRectangle rc) {
1234
 
        if (!ct.wCallTip.Created()) {
1235
 
                ct.wCallTip = gtk_window_new(GTK_WINDOW_POPUP);
1236
 
                ct.wDraw = gtk_drawing_area_new();
1237
 
                GtkWidget *widcdrw = PWidget(ct.wDraw); //      // No code inside the G_OBJECT macro
1238
 
                gtk_container_add(GTK_CONTAINER(PWidget(ct.wCallTip)), widcdrw);
1239
 
                g_signal_connect(G_OBJECT(widcdrw), "expose_event",
1240
 
                                   G_CALLBACK(ScintillaGTK::ExposeCT), &ct);
1241
 
                g_signal_connect(G_OBJECT(widcdrw), "button_press_event",
1242
 
                                   G_CALLBACK(ScintillaGTK::PressCT), static_cast<void *>(this));
1243
 
                gtk_widget_set_events(widcdrw,
1244
 
                        GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK);
1245
 
        }
1246
 
        gtk_drawing_area_size(GTK_DRAWING_AREA(PWidget(ct.wDraw)),
1247
 
                              rc.Width(), rc.Height());
1248
 
        ct.wDraw.Show();
1249
 
        if (PWidget(ct.wCallTip)->window) {
1250
 
                gdk_window_resize(PWidget(ct.wCallTip)->window, rc.Width(), rc.Height());
1251
 
        }
1252
 
}
1253
 
 
1254
 
void ScintillaGTK::AddToPopUp(const char *label, int cmd, bool enabled) {
1255
 
        char fulllabel[200];
1256
 
        strcpy(fulllabel, "/");
1257
 
        strcat(fulllabel, label);
1258
 
        GtkItemFactoryCallback menuSig = GtkItemFactoryCallback(PopUpCB);
1259
 
        GtkItemFactoryEntry itemEntry = {
1260
 
            fulllabel, NULL,
1261
 
            menuSig,
1262
 
            cmd,
1263
 
            const_cast<gchar *>(label[0] ? "<Item>" : "<Separator>"),
1264
 
            NULL
1265
 
        };
1266
 
        gtk_item_factory_create_item(GTK_ITEM_FACTORY(popup.GetID()),
1267
 
                                     &itemEntry, this, 1);
1268
 
        if (cmd) {
1269
 
                GtkWidget *item = gtk_item_factory_get_widget_by_action(
1270
 
                                      reinterpret_cast<GtkItemFactory *>(popup.GetID()), cmd);
1271
 
                if (item)
1272
 
                        gtk_widget_set_sensitive(item, enabled);
1273
 
        }
1274
 
}
1275
 
 
1276
 
bool ScintillaGTK::OwnPrimarySelection() {
1277
 
        return ((gdk_selection_owner_get(GDK_SELECTION_PRIMARY)
1278
 
                == GTK_WIDGET(PWidget(wMain))->window) &&
1279
 
                        (GTK_WIDGET(PWidget(wMain))->window != NULL));
1280
 
}
1281
 
 
1282
 
void ScintillaGTK::ClaimSelection() {
1283
 
        // X Windows has a 'primary selection' as well as the clipboard.
1284
 
        // Whenever the user selects some text, we become the primary selection
1285
 
        if (!sel.Empty() && GTK_WIDGET_REALIZED(GTK_WIDGET(PWidget(wMain)))) {
1286
 
                primarySelection = true;
1287
 
                gtk_selection_owner_set(GTK_WIDGET(PWidget(wMain)),
1288
 
                                        GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME);
1289
 
                primary.Free();
1290
 
        } else if (OwnPrimarySelection()) {
1291
 
                primarySelection = true;
1292
 
                if (primary.s == NULL)
1293
 
                        gtk_selection_owner_set(NULL, GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME);
1294
 
        } else {
1295
 
                primarySelection = false;
1296
 
                primary.Free();
1297
 
        }
1298
 
}
1299
 
 
1300
 
// Detect rectangular text, convert line ends to current mode, convert from or to UTF-8
1301
 
void ScintillaGTK::GetGtkSelectionText(GtkSelectionData *selectionData, SelectionText &selText) {
1302
 
        char *data = reinterpret_cast<char *>(selectionData->data);
1303
 
        int len = selectionData->length;
1304
 
        GdkAtom selectionTypeData = selectionData->type;
1305
 
 
1306
 
        // Return empty string if selection is not a string
1307
 
        if ((selectionTypeData != GDK_TARGET_STRING) && (selectionTypeData != atomUTF8)) {
1308
 
                char *empty = new char[1];
1309
 
                empty[0] = '\0';
1310
 
                selText.Set(empty, 0, SC_CP_UTF8, 0, false, false);
1311
 
                return;
1312
 
        }
1313
 
 
1314
 
        // Check for "\n\0" ending to string indicating that selection is rectangular
1315
 
        bool isRectangular;
1316
 
#if PLAT_GTK_WIN32
1317
 
        isRectangular = ::IsClipboardFormatAvailable(cfColumnSelect) != 0;
1318
 
#else
1319
 
        isRectangular = ((len > 2) && (data[len - 1] == 0 && data[len - 2] == '\n'));
1320
 
        if (isRectangular)
1321
 
                len--;  // Forget the extra '\0'
1322
 
#endif
1323
 
 
1324
 
        char *dest;
1325
 
        if (selectionTypeData == GDK_TARGET_STRING) {
1326
 
                dest = Document::TransformLineEnds(&len, data, len, pdoc->eolMode);
1327
 
                if (IsUnicodeMode()) {
1328
 
                        // Unknown encoding so assume in Latin1
1329
 
                        char *destPrevious = dest;
1330
 
                        dest = UTF8FromLatin1(dest, len);
1331
 
                        selText.Set(dest, len, SC_CP_UTF8, 0, selText.rectangular, false);
1332
 
                        delete []destPrevious;
1333
 
                } else {
1334
 
                        // Assume buffer is in same encoding as selection
1335
 
                        selText.Set(dest, len, pdoc->dbcsCodePage,
1336
 
                                vs.styles[STYLE_DEFAULT].characterSet, isRectangular, false);
1337
 
                }
1338
 
        } else {        // UTF-8
1339
 
                dest = Document::TransformLineEnds(&len, data, len, pdoc->eolMode);
1340
 
                selText.Set(dest, len, SC_CP_UTF8, 0, isRectangular, false);
1341
 
                const char *charSetBuffer = CharacterSetID();
1342
 
                if (!IsUnicodeMode() && *charSetBuffer) {
1343
 
                        // Convert to locale
1344
 
                        dest = ConvertText(&len, selText.s, selText.len, charSetBuffer, "UTF-8", true);
1345
 
                        selText.Set(dest, len, pdoc->dbcsCodePage,
1346
 
                                vs.styles[STYLE_DEFAULT].characterSet, selText.rectangular, false);
1347
 
                }
1348
 
        }
1349
 
}
1350
 
 
1351
 
void ScintillaGTK::ReceivedSelection(GtkSelectionData *selection_data) {
1352
 
        try {
1353
 
                if ((selection_data->selection == atomClipboard) ||
1354
 
                        (selection_data->selection == GDK_SELECTION_PRIMARY)) {
1355
 
                        if ((atomSought == atomUTF8) && (selection_data->length <= 0)) {
1356
 
                                atomSought = atomString;
1357
 
                                gtk_selection_convert(GTK_WIDGET(PWidget(wMain)),
1358
 
                                        selection_data->selection, atomSought, GDK_CURRENT_TIME);
1359
 
                        } else if ((selection_data->length > 0) &&
1360
 
                                ((selection_data->type == GDK_TARGET_STRING) || (selection_data->type == atomUTF8))) {
1361
 
                                SelectionText selText;
1362
 
                                GetGtkSelectionText(selection_data, selText);
1363
 
 
1364
 
                                UndoGroup ug(pdoc);
1365
 
                                if (selection_data->selection != GDK_SELECTION_PRIMARY) {
1366
 
                                        ClearSelection();
1367
 
                                }
1368
 
                                SelectionPosition selStart = sel.IsRectangular() ?
1369
 
                                        sel.Rectangular().Start() :
1370
 
                                        sel.Range(sel.Main()).Start();
1371
 
 
1372
 
                                if (selText.rectangular) {
1373
 
                                        PasteRectangular(selStart, selText.s, selText.len);
1374
 
                                } else {
1375
 
                                        InsertPaste(selStart, selText.s, selText.len);
1376
 
                                }
1377
 
                                EnsureCaretVisible();
1378
 
                        }
1379
 
                }
1380
 
//      else fprintf(stderr, "Target non string %d %d\n", (int)(selection_data->type),
1381
 
//              (int)(atomUTF8));
1382
 
                Redraw();
1383
 
        } catch (...) {
1384
 
                errorStatus = SC_STATUS_FAILURE;
1385
 
        }
1386
 
}
1387
 
 
1388
 
void ScintillaGTK::ReceivedDrop(GtkSelectionData *selection_data) {
1389
 
        dragWasDropped = true;
1390
 
        if (selection_data->type == atomUriList || selection_data->type == atomDROPFILES_DND) {
1391
 
                char *ptr = new char[selection_data->length + 1];
1392
 
                ptr[selection_data->length] = '\0';
1393
 
                memcpy(ptr, selection_data->data, selection_data->length);
1394
 
                NotifyURIDropped(ptr);
1395
 
                delete []ptr;
1396
 
        } else if ((selection_data->type == GDK_TARGET_STRING) || (selection_data->type == atomUTF8)) {
1397
 
                if (selection_data->length > 0) {
1398
 
                        SelectionText selText;
1399
 
                        GetGtkSelectionText(selection_data, selText);
1400
 
                        DropAt(posDrop, selText.s, false, selText.rectangular);
1401
 
                }
1402
 
        } else if (selection_data->length > 0) {
1403
 
                //~ fprintf(stderr, "ReceivedDrop other %p\n", static_cast<void *>(selection_data->type));
1404
 
        }
1405
 
        Redraw();
1406
 
}
1407
 
 
1408
 
 
1409
 
 
1410
 
void ScintillaGTK::GetSelection(GtkSelectionData *selection_data, guint info, SelectionText *text) {
1411
 
#if PLAT_GTK_WIN32
1412
 
        // GDK on Win32 expands any \n into \r\n, so make a copy of
1413
 
        // the clip text now with newlines converted to \n.  Use { } to hide symbols
1414
 
        // from code below
1415
 
        SelectionText *newline_normalized = NULL;
1416
 
        {
1417
 
                int tmpstr_len;
1418
 
                char *tmpstr = Document::TransformLineEnds(&tmpstr_len, text->s, text->len, SC_EOL_LF);
1419
 
                newline_normalized = new SelectionText();
1420
 
                newline_normalized->Set(tmpstr, tmpstr_len, SC_CP_UTF8, 0, text->rectangular, false);
1421
 
                text = newline_normalized;
1422
 
        }
1423
 
#endif
1424
 
 
1425
 
        // Convert text to utf8 if it isn't already
1426
 
        SelectionText *converted = 0;
1427
 
        if ((text->codePage != SC_CP_UTF8) && (info == TARGET_UTF8_STRING)) {
1428
 
                const char *charSet = ::CharacterSetID(text->characterSet);
1429
 
                if (*charSet) {
1430
 
                        int new_len;
1431
 
                        char* tmputf = ConvertText(&new_len, text->s, text->len, "UTF-8", charSet, false);
1432
 
                        converted = new SelectionText();
1433
 
                        converted->Set(tmputf, new_len, SC_CP_UTF8, 0, text->rectangular, false);
1434
 
                        text = converted;
1435
 
                }
1436
 
        }
1437
 
 
1438
 
        // Here is a somewhat evil kludge.
1439
 
        // As I can not work out how to store data on the clipboard in multiple formats
1440
 
        // and need some way to mark the clipping as being stream or rectangular,
1441
 
        // the terminating \0 is included in the length for rectangular clippings.
1442
 
        // All other tested aplications behave benignly by ignoring the \0.
1443
 
        // The #if is here because on Windows cfColumnSelect clip entry is used
1444
 
        // instead as standard indicator of rectangularness (so no need to kludge)
1445
 
        const char *textData = text->s ? text->s : "";
1446
 
        int len = strlen(textData);
1447
 
#if PLAT_GTK_WIN32 == 0
1448
 
        if (text->rectangular)
1449
 
                len++;
1450
 
#endif
1451
 
 
1452
 
        if (info == TARGET_UTF8_STRING) {
1453
 
                gtk_selection_data_set_text(selection_data, textData, len);
1454
 
        } else {
1455
 
                gtk_selection_data_set(selection_data,
1456
 
                        static_cast<GdkAtom>(GDK_SELECTION_TYPE_STRING),
1457
 
                        8, reinterpret_cast<const unsigned char *>(textData), len);
1458
 
        }
1459
 
        delete converted;
1460
 
 
1461
 
#if PLAT_GTK_WIN32
1462
 
        delete newline_normalized;
1463
 
#endif
1464
 
}
1465
 
 
1466
 
#ifdef USE_GTK_CLIPBOARD
1467
 
void ScintillaGTK::StoreOnClipboard(SelectionText *clipText) {
1468
 
        GtkClipboard *clipBoard =
1469
 
                gtk_widget_get_clipboard(GTK_WIDGET(PWidget(wMain)), atomClipboard);
1470
 
        if (clipBoard == NULL) // Occurs if widget isn't in a toplevel
1471
 
                return;
1472
 
 
1473
 
        if (gtk_clipboard_set_with_data(clipBoard, clipboardCopyTargets, nClipboardCopyTargets,
1474
 
                                    ClipboardGetSelection, ClipboardClearSelection, clipText)) {
1475
 
                gtk_clipboard_set_can_store(clipBoard, clipboardCopyTargets, nClipboardCopyTargets);
1476
 
        }
1477
 
}
1478
 
 
1479
 
void ScintillaGTK::ClipboardGetSelection(GtkClipboard *, GtkSelectionData *selection_data, guint info, void *data) {
1480
 
        GetSelection(selection_data, info, static_cast<SelectionText*>(data));
1481
 
}
1482
 
 
1483
 
void ScintillaGTK::ClipboardClearSelection(GtkClipboard *, void *data) {
1484
 
        SelectionText *obj = static_cast<SelectionText*>(data);
1485
 
        delete obj;
1486
 
}
1487
 
#endif
1488
 
 
1489
 
void ScintillaGTK::UnclaimSelection(GdkEventSelection *selection_event) {
1490
 
        try {
1491
 
                //Platform::DebugPrintf("UnclaimSelection\n");
1492
 
                if (selection_event->selection == GDK_SELECTION_PRIMARY) {
1493
 
                        //Platform::DebugPrintf("UnclaimPrimarySelection\n");
1494
 
                        if (!OwnPrimarySelection()) {
1495
 
                                primary.Free();
1496
 
                                primarySelection = false;
1497
 
                                FullPaint();
1498
 
                        }
1499
 
                }
1500
 
        } catch (...) {
1501
 
                errorStatus = SC_STATUS_FAILURE;
1502
 
        }
1503
 
}
1504
 
 
1505
 
void ScintillaGTK::Resize(int width, int height) {
1506
 
        //Platform::DebugPrintf("Resize %d %d\n", width, height);
1507
 
        //printf("Resize %d %d\n", width, height);
1508
 
 
1509
 
        // Not always needed, but some themes can have different sizes of scrollbars
1510
 
        scrollBarWidth = GTK_WIDGET(PWidget(scrollbarv))->requisition.width;
1511
 
        scrollBarHeight = GTK_WIDGET(PWidget(scrollbarh))->requisition.height;
1512
 
 
1513
 
        // These allocations should never produce negative sizes as they would wrap around to huge
1514
 
        // unsigned numbers inside GTK+ causing warnings.
1515
 
        bool showSBHorizontal = horizontalScrollBarVisible && (wrapState == eWrapNone);
1516
 
        int horizontalScrollBarHeight = scrollBarHeight;
1517
 
        if (!showSBHorizontal)
1518
 
                horizontalScrollBarHeight = 0;
1519
 
 
1520
 
        GtkAllocation alloc;
1521
 
        if (showSBHorizontal) {
1522
 
                gtk_widget_show(GTK_WIDGET(PWidget(scrollbarh)));
1523
 
                alloc.x = 0;
1524
 
                alloc.y = height - scrollBarHeight;
1525
 
                alloc.width = Platform::Maximum(1, width - scrollBarWidth) + 1;
1526
 
                alloc.height = horizontalScrollBarHeight;
1527
 
                gtk_widget_size_allocate(GTK_WIDGET(PWidget(scrollbarh)), &alloc);
1528
 
        } else {
1529
 
                gtk_widget_hide(GTK_WIDGET(PWidget(scrollbarh)));
1530
 
        }
1531
 
 
1532
 
        if (verticalScrollBarVisible) {
1533
 
                gtk_widget_show(GTK_WIDGET(PWidget(scrollbarv)));
1534
 
                alloc.x = width - scrollBarWidth;
1535
 
                alloc.y = 0;
1536
 
                alloc.width = scrollBarWidth;
1537
 
                alloc.height = Platform::Maximum(1, height - scrollBarHeight) + 1;
1538
 
                if (!showSBHorizontal)
1539
 
                        alloc.height += scrollBarWidth-1;
1540
 
                gtk_widget_size_allocate(GTK_WIDGET(PWidget(scrollbarv)), &alloc);
1541
 
        } else {
1542
 
                gtk_widget_hide(GTK_WIDGET(PWidget(scrollbarv)));
1543
 
        }
1544
 
        if (GTK_WIDGET_MAPPED(PWidget(wMain))) {
1545
 
                ChangeSize();
1546
 
        }
1547
 
 
1548
 
        alloc.x = 0;
1549
 
        alloc.y = 0;
1550
 
        alloc.width = Platform::Maximum(1, width - scrollBarWidth);
1551
 
        alloc.height = Platform::Maximum(1, height - scrollBarHeight);
1552
 
        if (!showSBHorizontal)
1553
 
                alloc.height += scrollBarHeight;
1554
 
        if (!verticalScrollBarVisible)
1555
 
                alloc.width += scrollBarWidth;
1556
 
        gtk_widget_size_allocate(GTK_WIDGET(PWidget(wText)), &alloc);
1557
 
}
1558
 
 
1559
 
static void SetAdjustmentValue(GtkObject *object, int value) {
1560
 
        GtkAdjustment *adjustment = GTK_ADJUSTMENT(object);
1561
 
        int maxValue = static_cast<int>(
1562
 
                adjustment->upper - adjustment->page_size);
1563
 
        if (value > maxValue)
1564
 
                value = maxValue;
1565
 
        if (value < 0)
1566
 
                value = 0;
1567
 
        gtk_adjustment_set_value(adjustment, value);
1568
 
}
1569
 
 
1570
 
static int modifierTranslated(int sciModifier) {
1571
 
        switch (sciModifier) {
1572
 
                case SCMOD_SHIFT:
1573
 
                        return GDK_SHIFT_MASK;
1574
 
                case SCMOD_CTRL:
1575
 
                        return GDK_CONTROL_MASK;
1576
 
                case SCMOD_ALT:
1577
 
                        return GDK_MOD1_MASK;
1578
 
                case SCMOD_SUPER:
1579
 
                        return GDK_MOD4_MASK;
1580
 
                default:
1581
 
                        return 0;
1582
 
        }
1583
 
}
1584
 
 
1585
 
gint ScintillaGTK::PressThis(GdkEventButton *event) {
1586
 
        try {
1587
 
                //Platform::DebugPrintf("Press %x time=%d state = %x button = %x\n",this,event->time, event->state, event->button);
1588
 
                // Do not use GTK+ double click events as Scintilla has its own double click detection
1589
 
                if (event->type != GDK_BUTTON_PRESS)
1590
 
                        return FALSE;
1591
 
 
1592
 
                evbtn = *event;
1593
 
                Point pt;
1594
 
                pt.x = int(event->x);
1595
 
                pt.y = int(event->y);
1596
 
                PRectangle rcClient = GetClientRectangle();
1597
 
                //Platform::DebugPrintf("Press %0d,%0d in %0d,%0d %0d,%0d\n",
1598
 
                //      pt.x, pt.y, rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
1599
 
                if ((pt.x > rcClient.right) || (pt.y > rcClient.bottom)) {
1600
 
                        Platform::DebugPrintf("Bad location\n");
1601
 
                        return FALSE;
1602
 
                }
1603
 
 
1604
 
                bool ctrl = (event->state & GDK_CONTROL_MASK) != 0;
1605
 
 
1606
 
                gtk_widget_grab_focus(PWidget(wMain));
1607
 
                if (event->button == 1) {
1608
 
                        // On X, instead of sending literal modifiers use the user specified
1609
 
                        // modifier, defaulting to control instead of alt.
1610
 
                        // This is because most X window managers grab alt + click for moving
1611
 
                        ButtonDown(pt, event->time,
1612
 
                                (event->state & GDK_SHIFT_MASK) != 0,
1613
 
                                (event->state & GDK_CONTROL_MASK) != 0,
1614
 
                                (event->state & modifierTranslated(rectangularSelectionModifier)) != 0);
1615
 
                } else if (event->button == 2) {
1616
 
                        // Grab the primary selection if it exists
1617
 
                        SelectionPosition pos = SPositionFromLocation(pt, false, false, UserVirtualSpace());
1618
 
                        if (OwnPrimarySelection() && primary.s == NULL)
1619
 
                                CopySelectionRange(&primary);
1620
 
 
1621
 
                        sel.Clear();
1622
 
                        SetSelection(pos, pos);
1623
 
                        atomSought = atomUTF8;
1624
 
                        gtk_selection_convert(GTK_WIDGET(PWidget(wMain)), GDK_SELECTION_PRIMARY,
1625
 
                                atomSought, event->time);
1626
 
                } else if (event->button == 3) {
1627
 
                        if (displayPopupMenu) {
1628
 
                                // PopUp menu
1629
 
                                // Convert to screen
1630
 
                                int ox = 0;
1631
 
                                int oy = 0;
1632
 
                                gdk_window_get_origin(PWidget(wMain)->window, &ox, &oy);
1633
 
                                ContextMenu(Point(pt.x + ox, pt.y + oy));
1634
 
                        } else {
1635
 
                                return FALSE;
1636
 
                        }
1637
 
                } else if (event->button == 4) {
1638
 
                        // Wheel scrolling up (only GTK 1.x does it this way)
1639
 
                        if (ctrl)
1640
 
                                SetAdjustmentValue(adjustmenth, (xOffset / 2) - 6);
1641
 
                        else
1642
 
                                SetAdjustmentValue(adjustmentv, topLine - 3);
1643
 
                } else if (event->button == 5) {
1644
 
                        // Wheel scrolling down (only GTK 1.x does it this way)
1645
 
                        if (ctrl)
1646
 
                                SetAdjustmentValue(adjustmenth, (xOffset / 2) + 6);
1647
 
                        else
1648
 
                                SetAdjustmentValue(adjustmentv, topLine + 3);
1649
 
                }
1650
 
        } catch (...) {
1651
 
                errorStatus = SC_STATUS_FAILURE;
1652
 
        }
1653
 
        return TRUE;
1654
 
}
1655
 
 
1656
 
gint ScintillaGTK::Press(GtkWidget *widget, GdkEventButton *event) {
1657
 
        if (event->window != widget->window)
1658
 
                return FALSE;
1659
 
        ScintillaGTK *sciThis = ScintillaFromWidget(widget);
1660
 
        return sciThis->PressThis(event);
1661
 
}
1662
 
 
1663
 
gint ScintillaGTK::MouseRelease(GtkWidget *widget, GdkEventButton *event) {
1664
 
        ScintillaGTK *sciThis = ScintillaFromWidget(widget);
1665
 
        try {
1666
 
                //Platform::DebugPrintf("Release %x %d %d\n",sciThis,event->time,event->state);
1667
 
                if (!sciThis->HaveMouseCapture())
1668
 
                        return FALSE;
1669
 
                if (event->button == 1) {
1670
 
                        Point pt;
1671
 
                        pt.x = int(event->x);
1672
 
                        pt.y = int(event->y);
1673
 
                        //Platform::DebugPrintf("Up %x %x %d %d %d\n",
1674
 
                        //      sciThis,event->window,event->time, pt.x, pt.y);
1675
 
                        if (event->window != PWidget(sciThis->wMain)->window)
1676
 
                                // If mouse released on scroll bar then the position is relative to the
1677
 
                                // scrollbar, not the drawing window so just repeat the most recent point.
1678
 
                                pt = sciThis->ptMouseLast;
1679
 
                        sciThis->ButtonUp(pt, event->time, (event->state & 4) != 0);
1680
 
                }
1681
 
        } catch (...) {
1682
 
                sciThis->errorStatus = SC_STATUS_FAILURE;
1683
 
        }
1684
 
        return FALSE;
1685
 
}
1686
 
 
1687
 
// win32gtk and GTK >= 2 use SCROLL_* events instead of passing the
1688
 
// button4/5/6/7 events to the GTK app
1689
 
gint ScintillaGTK::ScrollEvent(GtkWidget *widget,
1690
 
                               GdkEventScroll *event) {
1691
 
        ScintillaGTK *sciThis = ScintillaFromWidget(widget);
1692
 
        try {
1693
 
 
1694
 
                if (widget == NULL || event == NULL)
1695
 
                        return FALSE;
1696
 
 
1697
 
                // Compute amount and direction to scroll (even tho on win32 there is
1698
 
                // intensity of scrolling info in the native message, gtk doesn't
1699
 
                // support this so we simulate similarly adaptive scrolling)
1700
 
                // Note that this is disabled on OS X (Darwin) where the X11 server already has
1701
 
                // and adaptive scrolling algorithm that fights with this one
1702
 
                int cLineScroll;
1703
 
#if defined(__MWERKS__) || defined(__APPLE_CPP__) || defined(__APPLE_CC__)
1704
 
                cLineScroll = sciThis->linesPerScroll;
1705
 
                if (cLineScroll == 0)
1706
 
                        cLineScroll = 4;
1707
 
                sciThis->wheelMouseIntensity = cLineScroll;
1708
 
#else
1709
 
                int timeDelta = 1000000;
1710
 
                GTimeVal curTime;
1711
 
                g_get_current_time(&curTime);
1712
 
                if (curTime.tv_sec == sciThis->lastWheelMouseTime.tv_sec)
1713
 
                        timeDelta = curTime.tv_usec - sciThis->lastWheelMouseTime.tv_usec;
1714
 
                else if (curTime.tv_sec == sciThis->lastWheelMouseTime.tv_sec + 1)
1715
 
                        timeDelta = 1000000 + (curTime.tv_usec - sciThis->lastWheelMouseTime.tv_usec);
1716
 
                if ((event->direction == sciThis->lastWheelMouseDirection) && (timeDelta < 250000)) {
1717
 
                        if (sciThis->wheelMouseIntensity < 12)
1718
 
                                sciThis->wheelMouseIntensity++;
1719
 
                        cLineScroll = sciThis->wheelMouseIntensity;
1720
 
                } else {
1721
 
                        cLineScroll = sciThis->linesPerScroll;
1722
 
                        if (cLineScroll == 0)
1723
 
                                cLineScroll = 4;
1724
 
                        sciThis->wheelMouseIntensity = cLineScroll;
1725
 
                }
1726
 
#endif
1727
 
                if (event->direction == GDK_SCROLL_UP || event->direction == GDK_SCROLL_LEFT) {
1728
 
                        cLineScroll *= -1;
1729
 
                }
1730
 
                g_get_current_time(&sciThis->lastWheelMouseTime);
1731
 
                sciThis->lastWheelMouseDirection = event->direction;
1732
 
 
1733
 
                // Note:  Unpatched versions of win32gtk don't set the 'state' value so
1734
 
                // only regular scrolling is supported there.  Also, unpatched win32gtk
1735
 
                // issues spurious button 2 mouse events during wheeling, which can cause
1736
 
                // problems (a patch for both was submitted by archaeopteryx.com on 13Jun2001)
1737
 
 
1738
 
                // Data zoom not supported
1739
 
                if (event->state & GDK_SHIFT_MASK) {
1740
 
                        return FALSE;
1741
 
                }
1742
 
 
1743
 
                // Horizontal scrolling
1744
 
                if (event->direction == GDK_SCROLL_LEFT || event->direction == GDK_SCROLL_RIGHT) {
1745
 
                        sciThis->HorizontalScrollTo(sciThis->xOffset + cLineScroll);
1746
 
 
1747
 
                        // Text font size zoom
1748
 
                } else if (event->state & GDK_CONTROL_MASK) {
1749
 
                        if (cLineScroll < 0) {
1750
 
                                sciThis->KeyCommand(SCI_ZOOMIN);
1751
 
                        } else {
1752
 
                                sciThis->KeyCommand(SCI_ZOOMOUT);
1753
 
                        }
1754
 
 
1755
 
                        // Regular scrolling
1756
 
                } else {
1757
 
                        sciThis->ScrollTo(sciThis->topLine + cLineScroll);
1758
 
                }
1759
 
                return TRUE;
1760
 
        } catch (...) {
1761
 
                sciThis->errorStatus = SC_STATUS_FAILURE;
1762
 
        }
1763
 
        return FALSE;
1764
 
}
1765
 
 
1766
 
gint ScintillaGTK::Motion(GtkWidget *widget, GdkEventMotion *event) {
1767
 
        ScintillaGTK *sciThis = ScintillaFromWidget(widget);
1768
 
        try {
1769
 
                //Platform::DebugPrintf("Motion %x %d\n",sciThis,event->time);
1770
 
                if (event->window != widget->window)
1771
 
                        return FALSE;
1772
 
                int x = 0;
1773
 
                int y = 0;
1774
 
                GdkModifierType state;
1775
 
                if (event->is_hint) {
1776
 
                        gdk_window_get_pointer(event->window, &x, &y, &state);
1777
 
                } else {
1778
 
                        x = static_cast<int>(event->x);
1779
 
                        y = static_cast<int>(event->y);
1780
 
                        state = static_cast<GdkModifierType>(event->state);
1781
 
                }
1782
 
                //Platform::DebugPrintf("Move %x %x %d %c %d %d\n",
1783
 
                //      sciThis,event->window,event->time,event->is_hint? 'h' :'.', x, y);
1784
 
                Point pt(x, y);
1785
 
                sciThis->ButtonMove(pt);
1786
 
        } catch (...) {
1787
 
                sciThis->errorStatus = SC_STATUS_FAILURE;
1788
 
        }
1789
 
        return FALSE;
1790
 
}
1791
 
 
1792
 
// Map the keypad keys to their equivalent functions
1793
 
static int KeyTranslate(int keyIn) {
1794
 
        switch (keyIn) {
1795
 
        case GDK_ISO_Left_Tab:
1796
 
                return SCK_TAB;
1797
 
        case GDK_KP_Down:
1798
 
                return SCK_DOWN;
1799
 
        case GDK_KP_Up:
1800
 
                return SCK_UP;
1801
 
        case GDK_KP_Left:
1802
 
                return SCK_LEFT;
1803
 
        case GDK_KP_Right:
1804
 
                return SCK_RIGHT;
1805
 
        case GDK_KP_Home:
1806
 
                return SCK_HOME;
1807
 
        case GDK_KP_End:
1808
 
                return SCK_END;
1809
 
        case GDK_KP_Page_Up:
1810
 
                return SCK_PRIOR;
1811
 
        case GDK_KP_Page_Down:
1812
 
                return SCK_NEXT;
1813
 
        case GDK_KP_Delete:
1814
 
                return SCK_DELETE;
1815
 
        case GDK_KP_Insert:
1816
 
                return SCK_INSERT;
1817
 
        case GDK_KP_Enter:
1818
 
                return SCK_RETURN;
1819
 
 
1820
 
        case GDK_Down:
1821
 
                return SCK_DOWN;
1822
 
        case GDK_Up:
1823
 
                return SCK_UP;
1824
 
        case GDK_Left:
1825
 
                return SCK_LEFT;
1826
 
        case GDK_Right:
1827
 
                return SCK_RIGHT;
1828
 
        case GDK_Home:
1829
 
                return SCK_HOME;
1830
 
        case GDK_End:
1831
 
                return SCK_END;
1832
 
        case GDK_Page_Up:
1833
 
                return SCK_PRIOR;
1834
 
        case GDK_Page_Down:
1835
 
                return SCK_NEXT;
1836
 
        case GDK_Delete:
1837
 
                return SCK_DELETE;
1838
 
        case GDK_Insert:
1839
 
                return SCK_INSERT;
1840
 
        case GDK_Escape:
1841
 
                return SCK_ESCAPE;
1842
 
        case GDK_BackSpace:
1843
 
                return SCK_BACK;
1844
 
        case GDK_Tab:
1845
 
                return SCK_TAB;
1846
 
        case GDK_Return:
1847
 
                return SCK_RETURN;
1848
 
        case GDK_KP_Add:
1849
 
                return SCK_ADD;
1850
 
        case GDK_KP_Subtract:
1851
 
                return SCK_SUBTRACT;
1852
 
        case GDK_KP_Divide:
1853
 
                return SCK_DIVIDE;
1854
 
        case GDK_Super_L:
1855
 
                return SCK_WIN;
1856
 
        case GDK_Super_R:
1857
 
                return SCK_RWIN;
1858
 
        case GDK_Menu:
1859
 
                return SCK_MENU;
1860
 
        default:
1861
 
                return keyIn;
1862
 
        }
1863
 
}
1864
 
 
1865
 
gboolean ScintillaGTK::KeyThis(GdkEventKey *event) {
1866
 
        try {
1867
 
                //fprintf(stderr, "SC-key: %d %x [%s]\n",
1868
 
                //      event->keyval, event->state, (event->length > 0) ? event->string : "empty");
1869
 
                if (gtk_im_context_filter_keypress(im_context, event)) {
1870
 
                        return 1;
1871
 
                }
1872
 
                if (!event->keyval) {
1873
 
                        return true;
1874
 
                }
1875
 
 
1876
 
                bool shift = (event->state & GDK_SHIFT_MASK) != 0;
1877
 
                bool ctrl = (event->state & GDK_CONTROL_MASK) != 0;
1878
 
                bool alt = (event->state & GDK_MOD1_MASK) != 0;
1879
 
                guint key = event->keyval;
1880
 
                if (ctrl && (key < 128))
1881
 
                        key = toupper(key);
1882
 
                else if (!ctrl && (key >= GDK_KP_Multiply && key <= GDK_KP_9))
1883
 
                        key &= 0x7F;
1884
 
                // Hack for keys over 256 and below command keys but makes Hungarian work.
1885
 
                // This will have to change for Unicode
1886
 
                else if (key >= 0xFE00)
1887
 
                        key = KeyTranslate(key);
1888
 
 
1889
 
                bool consumed = false;
1890
 
                bool added = KeyDown(key, shift, ctrl, alt, &consumed) != 0;
1891
 
                if (!consumed)
1892
 
                        consumed = added;
1893
 
                //fprintf(stderr, "SK-key: %d %x %x\n",event->keyval, event->state, consumed);
1894
 
                if (event->keyval == 0xffffff && event->length > 0) {
1895
 
                        ClearSelection();
1896
 
                        if (pdoc->InsertCString(CurrentPosition(), event->string)) {
1897
 
                                MovePositionTo(CurrentPosition() + event->length);
1898
 
                        }
1899
 
                }
1900
 
                return consumed;
1901
 
        } catch (...) {
1902
 
                errorStatus = SC_STATUS_FAILURE;
1903
 
        }
1904
 
        return FALSE;
1905
 
}
1906
 
 
1907
 
gboolean ScintillaGTK::KeyPress(GtkWidget *widget, GdkEventKey *event) {
1908
 
        ScintillaGTK *sciThis = ScintillaFromWidget(widget);
1909
 
        return sciThis->KeyThis(event);
1910
 
}
1911
 
 
1912
 
gboolean ScintillaGTK::KeyRelease(GtkWidget *, GdkEventKey * /*event*/) {
1913
 
        //Platform::DebugPrintf("SC-keyrel: %d %x %3s\n",event->keyval, event->state, event->string);
1914
 
        return FALSE;
1915
 
}
1916
 
 
1917
 
gboolean ScintillaGTK::ExposePreeditThis(GtkWidget *widget, GdkEventExpose *ose) {
1918
 
        try {
1919
 
                gchar *str;
1920
 
                gint cursor_pos;
1921
 
                PangoAttrList *attrs;
1922
 
 
1923
 
                gtk_im_context_get_preedit_string(im_context, &str, &attrs, &cursor_pos);
1924
 
                PangoLayout *layout = gtk_widget_create_pango_layout(PWidget(wText), str);
1925
 
                pango_layout_set_attributes(layout, attrs);
1926
 
 
1927
 
                GdkGC *gc = gdk_gc_new(widget->window);
1928
 
                GdkColor color[2] = {   {0, 0x0000, 0x0000, 0x0000},
1929
 
                        {0, 0xffff, 0xffff, 0xffff}
1930
 
                };
1931
 
                gdk_color_alloc(gdk_colormap_get_system(), color);
1932
 
                gdk_color_alloc(gdk_colormap_get_system(), color + 1);
1933
 
 
1934
 
                gdk_gc_set_foreground(gc, color + 1);
1935
 
                gdk_draw_rectangle(widget->window, gc, TRUE, ose->area.x, ose->area.y,
1936
 
                        ose->area.width, ose->area.height);
1937
 
 
1938
 
                gdk_gc_set_foreground(gc, color);
1939
 
                gdk_gc_set_background(gc, color + 1);
1940
 
                gdk_draw_layout(widget->window, gc, 0, 0, layout);
1941
 
 
1942
 
                gdk_gc_unref(gc);
1943
 
                g_free(str);
1944
 
                pango_attr_list_unref(attrs);
1945
 
                g_object_unref(layout);
1946
 
        } catch (...) {
1947
 
                errorStatus = SC_STATUS_FAILURE;
1948
 
        }
1949
 
        return TRUE;
1950
 
}
1951
 
 
1952
 
gboolean ScintillaGTK::ExposePreedit(GtkWidget *widget, GdkEventExpose *ose, ScintillaGTK *sciThis) {
1953
 
        return sciThis->ExposePreeditThis(widget, ose);
1954
 
}
1955
 
 
1956
 
void ScintillaGTK::CommitThis(char *utfVal) {
1957
 
        try {
1958
 
                //~ fprintf(stderr, "Commit '%s'\n", utfVal);
1959
 
                if (IsUnicodeMode()) {
1960
 
                        AddCharUTF(utfVal, strlen(utfVal));
1961
 
                } else {
1962
 
                        const char *source = CharacterSetID();
1963
 
                        if (*source) {
1964
 
                                Converter conv(source, "UTF-8", true);
1965
 
                                if (conv) {
1966
 
                                        char localeVal[4] = "\0\0\0";
1967
 
                                        char *pin = utfVal;
1968
 
                                        size_t inLeft = strlen(utfVal);
1969
 
                                        char *pout = localeVal;
1970
 
                                        size_t outLeft = sizeof(localeVal);
1971
 
                                        size_t conversions = conv.Convert(&pin, &inLeft, &pout, &outLeft);
1972
 
                                        if (conversions != ((size_t)(-1))) {
1973
 
                                                *pout = '\0';
1974
 
                                                for (int i = 0; localeVal[i]; i++) {
1975
 
                                                        AddChar(localeVal[i]);
1976
 
                                                }
1977
 
                                        } else {
1978
 
                                                fprintf(stderr, "Conversion failed '%s'\n", utfVal);
1979
 
                                        }
1980
 
                                }
1981
 
                        }
1982
 
                }
1983
 
        } catch (...) {
1984
 
                errorStatus = SC_STATUS_FAILURE;
1985
 
        }
1986
 
}
1987
 
 
1988
 
void ScintillaGTK::Commit(GtkIMContext *, char  *str, ScintillaGTK *sciThis) {
1989
 
        sciThis->CommitThis(str);
1990
 
}
1991
 
 
1992
 
void ScintillaGTK::PreeditChangedThis() {
1993
 
        try {
1994
 
                gchar *str;
1995
 
                PangoAttrList *attrs;
1996
 
                gint cursor_pos;
1997
 
                gtk_im_context_get_preedit_string(im_context, &str, &attrs, &cursor_pos);
1998
 
                if (strlen(str) > 0) {
1999
 
                        PangoLayout *layout = gtk_widget_create_pango_layout(PWidget(wText), str);
2000
 
                        pango_layout_set_attributes(layout, attrs);
2001
 
 
2002
 
                        gint w, h;
2003
 
                        pango_layout_get_pixel_size(layout, &w, &h);
2004
 
                        g_object_unref(layout);
2005
 
 
2006
 
                        gint x, y;
2007
 
                        gdk_window_get_origin((PWidget(wText))->window, &x, &y);
2008
 
 
2009
 
                        Point pt = PointMainCaret();
2010
 
                        if (pt.x < 0)
2011
 
                                pt.x = 0;
2012
 
                        if (pt.y < 0)
2013
 
                                pt.y = 0;
2014
 
 
2015
 
                        gtk_window_move(GTK_WINDOW(PWidget(wPreedit)), x + pt.x, y + pt.y);
2016
 
                        gtk_window_resize(GTK_WINDOW(PWidget(wPreedit)), w, h);
2017
 
                        gtk_widget_show(PWidget(wPreedit));
2018
 
                        gtk_widget_queue_draw_area(PWidget(wPreeditDraw), 0, 0, w, h);
2019
 
                } else {
2020
 
                        gtk_widget_hide(PWidget(wPreedit));
2021
 
                }
2022
 
                g_free(str);
2023
 
                pango_attr_list_unref(attrs);
2024
 
        } catch (...) {
2025
 
                errorStatus = SC_STATUS_FAILURE;
2026
 
        }
2027
 
}
2028
 
 
2029
 
void ScintillaGTK::PreeditChanged(GtkIMContext *, ScintillaGTK *sciThis) {
2030
 
        sciThis->PreeditChangedThis();
2031
 
}
2032
 
 
2033
 
gint ScintillaGTK::StyleSetText(GtkWidget *widget, GtkStyle *, void*) {
2034
 
        if (widget->window != NULL)
2035
 
                gdk_window_set_back_pixmap(widget->window, NULL, FALSE);
2036
 
        return FALSE;
2037
 
}
2038
 
 
2039
 
gint ScintillaGTK::RealizeText(GtkWidget *widget, void*) {
2040
 
        if (widget->window != NULL)
2041
 
                gdk_window_set_back_pixmap(widget->window, NULL, FALSE);
2042
 
        return FALSE;
2043
 
}
2044
 
 
2045
 
void ScintillaGTK::Destroy(GObject *object) {
2046
 
        try {
2047
 
                ScintillaObject *scio = reinterpret_cast<ScintillaObject *>(object);
2048
 
                // This avoids a double destruction
2049
 
                if (!scio->pscin)
2050
 
                        return;
2051
 
                ScintillaGTK *sciThis = reinterpret_cast<ScintillaGTK *>(scio->pscin);
2052
 
                //Platform::DebugPrintf("Destroying %x %x\n", sciThis, object);
2053
 
                sciThis->Finalise();
2054
 
 
2055
 
                delete sciThis;
2056
 
                scio->pscin = 0;
2057
 
        } catch (...) {
2058
 
                // Its dead so nowhere to save the status
2059
 
        }
2060
 
}
2061
 
 
2062
 
static void DrawChild(GtkWidget *widget, GdkRectangle *area) {
2063
 
        GdkRectangle areaIntersect;
2064
 
        if (widget &&
2065
 
                GTK_WIDGET_DRAWABLE(widget) &&
2066
 
                gtk_widget_intersect(widget, area, &areaIntersect)) {
2067
 
                gtk_widget_draw(widget, &areaIntersect);
2068
 
        }
2069
 
}
2070
 
 
2071
 
void ScintillaGTK::Draw(GtkWidget *widget, GdkRectangle *area) {
2072
 
        ScintillaGTK *sciThis = ScintillaFromWidget(widget);
2073
 
        try {
2074
 
                //Platform::DebugPrintf("Draw %p %0d,%0d %0d,%0d\n", widget, area->x, area->y, area->width, area->height);
2075
 
                PRectangle rcPaint(area->x, area->y, area->x + area->width, area->y + area->height);
2076
 
                sciThis->SyncPaint(rcPaint);
2077
 
                if (GTK_WIDGET_DRAWABLE(PWidget(sciThis->wMain))) {
2078
 
                        DrawChild(PWidget(sciThis->scrollbarh), area);
2079
 
                        DrawChild(PWidget(sciThis->scrollbarv), area);
2080
 
                }
2081
 
 
2082
 
                Point pt = sciThis->PointMainCaret();
2083
 
                pt.y += sciThis->vs.lineHeight - 2;
2084
 
                if (pt.x < 0) pt.x = 0;
2085
 
                if (pt.y < 0) pt.y = 0;
2086
 
                CursorMoved(widget, pt.x, pt.y, sciThis);
2087
 
        } catch (...) {
2088
 
                sciThis->errorStatus = SC_STATUS_FAILURE;
2089
 
        }
2090
 
}
2091
 
 
2092
 
gint ScintillaGTK::ExposeTextThis(GtkWidget * /*widget*/, GdkEventExpose *ose) {
2093
 
        try {
2094
 
                paintState = painting;
2095
 
 
2096
 
                rcPaint.left = ose->area.x;
2097
 
                rcPaint.top = ose->area.y;
2098
 
                rcPaint.right = ose->area.x + ose->area.width;
2099
 
                rcPaint.bottom = ose->area.y + ose->area.height;
2100
 
 
2101
 
                PLATFORM_ASSERT(rgnUpdate == NULL);
2102
 
                rgnUpdate = gdk_region_copy(ose->region);
2103
 
                PRectangle rcClient = GetClientRectangle();
2104
 
                paintingAllText = rcPaint.Contains(rcClient);
2105
 
                Surface *surfaceWindow = Surface::Allocate();
2106
 
                if (surfaceWindow) {
2107
 
                        surfaceWindow->Init(PWidget(wText)->window, PWidget(wText));
2108
 
                        Paint(surfaceWindow, rcPaint);
2109
 
                        surfaceWindow->Release();
2110
 
                        delete surfaceWindow;
2111
 
                }
2112
 
                if (paintState == paintAbandoned) {
2113
 
                        // Painting area was insufficient to cover new styling or brace highlight positions
2114
 
                        FullPaint();
2115
 
                }
2116
 
                paintState = notPainting;
2117
 
 
2118
 
                if (rgnUpdate) {
2119
 
                        gdk_region_destroy(rgnUpdate);
2120
 
                }
2121
 
                rgnUpdate = 0;
2122
 
        } catch (...) {
2123
 
                errorStatus = SC_STATUS_FAILURE;
2124
 
        }
2125
 
 
2126
 
        return FALSE;
2127
 
}
2128
 
 
2129
 
gint ScintillaGTK::ExposeText(GtkWidget *widget, GdkEventExpose *ose, ScintillaGTK *sciThis) {
2130
 
        return sciThis->ExposeTextThis(widget, ose);
2131
 
}
2132
 
 
2133
 
gint ScintillaGTK::ExposeMain(GtkWidget *widget, GdkEventExpose *ose) {
2134
 
        ScintillaGTK *sciThis = ScintillaFromWidget(widget);
2135
 
        //Platform::DebugPrintf("Expose Main %0d,%0d %0d,%0d\n",
2136
 
        //ose->area.x, ose->area.y, ose->area.width, ose->area.height);
2137
 
        return sciThis->Expose(widget, ose);
2138
 
}
2139
 
 
2140
 
gint ScintillaGTK::Expose(GtkWidget *, GdkEventExpose *ose) {
2141
 
        try {
2142
 
                //fprintf(stderr, "Expose %0d,%0d %0d,%0d\n",
2143
 
                //ose->area.x, ose->area.y, ose->area.width, ose->area.height);
2144
 
 
2145
 
                // The text is painted in ExposeText
2146
 
                gtk_container_propagate_expose(
2147
 
                    GTK_CONTAINER(PWidget(wMain)), PWidget(scrollbarh), ose);
2148
 
                gtk_container_propagate_expose(
2149
 
                    GTK_CONTAINER(PWidget(wMain)), PWidget(scrollbarv), ose);
2150
 
 
2151
 
        } catch (...) {
2152
 
                errorStatus = SC_STATUS_FAILURE;
2153
 
        }
2154
 
        return FALSE;
2155
 
}
2156
 
 
2157
 
void ScintillaGTK::ScrollSignal(GtkAdjustment *adj, ScintillaGTK *sciThis) {
2158
 
        try {
2159
 
                sciThis->ScrollTo(static_cast<int>(adj->value), false);
2160
 
        } catch (...) {
2161
 
                sciThis->errorStatus = SC_STATUS_FAILURE;
2162
 
        }
2163
 
}
2164
 
 
2165
 
void ScintillaGTK::ScrollHSignal(GtkAdjustment *adj, ScintillaGTK *sciThis) {
2166
 
        try {
2167
 
                sciThis->HorizontalScrollTo(static_cast<int>(adj->value * 2));
2168
 
        } catch (...) {
2169
 
                sciThis->errorStatus = SC_STATUS_FAILURE;
2170
 
        }
2171
 
}
2172
 
 
2173
 
void ScintillaGTK::SelectionReceived(GtkWidget *widget,
2174
 
                                     GtkSelectionData *selection_data, guint) {
2175
 
        ScintillaGTK *sciThis = ScintillaFromWidget(widget);
2176
 
        //Platform::DebugPrintf("Selection received\n");
2177
 
        sciThis->ReceivedSelection(selection_data);
2178
 
}
2179
 
 
2180
 
void ScintillaGTK::SelectionGet(GtkWidget *widget,
2181
 
                                GtkSelectionData *selection_data, guint info, guint) {
2182
 
        ScintillaGTK *sciThis = ScintillaFromWidget(widget);
2183
 
        try {
2184
 
                //Platform::DebugPrintf("Selection get\n");
2185
 
                if (selection_data->selection == GDK_SELECTION_PRIMARY) {
2186
 
                        if (sciThis->primary.s == NULL) {
2187
 
                                sciThis->CopySelectionRange(&sciThis->primary);
2188
 
                        }
2189
 
                        sciThis->GetSelection(selection_data, info, &sciThis->primary);
2190
 
                }
2191
 
#ifndef USE_GTK_CLIPBOARD
2192
 
                else {
2193
 
                        sciThis->GetSelection(selection_data, info, &sciThis->copyText);
2194
 
                }
2195
 
#endif
2196
 
        } catch (...) {
2197
 
                sciThis->errorStatus = SC_STATUS_FAILURE;
2198
 
        }
2199
 
}
2200
 
 
2201
 
gint ScintillaGTK::SelectionClear(GtkWidget *widget, GdkEventSelection *selection_event) {
2202
 
        ScintillaGTK *sciThis = ScintillaFromWidget(widget);
2203
 
        //Platform::DebugPrintf("Selection clear\n");
2204
 
        sciThis->UnclaimSelection(selection_event);
2205
 
        return gtk_selection_clear(widget, selection_event);
2206
 
}
2207
 
 
2208
 
void ScintillaGTK::DragBegin(GtkWidget *, GdkDragContext *) {
2209
 
        //Platform::DebugPrintf("DragBegin\n");
2210
 
}
2211
 
 
2212
 
gboolean ScintillaGTK::DragMotionThis(GdkDragContext *context,
2213
 
                                 gint x, gint y, guint dragtime) {
2214
 
        try {
2215
 
                Point npt(x, y);
2216
 
                SetDragPosition(SPositionFromLocation(npt, false, false, UserVirtualSpace()));
2217
 
                GdkDragAction preferredAction = context->suggested_action;
2218
 
                SelectionPosition pos = SPositionFromLocation(npt);
2219
 
                if ((inDragDrop == ddDragging) && (PositionInSelection(pos.Position()))) {
2220
 
                        // Avoid dragging selection onto itself as that produces a move
2221
 
                        // with no real effect but which creates undo actions.
2222
 
                        preferredAction = static_cast<GdkDragAction>(0);
2223
 
                } else if (context->actions == static_cast<GdkDragAction>
2224
 
                        (GDK_ACTION_COPY | GDK_ACTION_MOVE)) {
2225
 
                        preferredAction = GDK_ACTION_MOVE;
2226
 
                }
2227
 
                gdk_drag_status(context, preferredAction, dragtime);
2228
 
        } catch (...) {
2229
 
                errorStatus = SC_STATUS_FAILURE;
2230
 
        }
2231
 
        return FALSE;
2232
 
}
2233
 
 
2234
 
gboolean ScintillaGTK::DragMotion(GtkWidget *widget, GdkDragContext *context,
2235
 
                                 gint x, gint y, guint dragtime) {
2236
 
        ScintillaGTK *sciThis = ScintillaFromWidget(widget);
2237
 
        return sciThis->DragMotionThis(context, x, y, dragtime);
2238
 
}
2239
 
 
2240
 
void ScintillaGTK::DragLeave(GtkWidget *widget, GdkDragContext * /*context*/, guint) {
2241
 
        ScintillaGTK *sciThis = ScintillaFromWidget(widget);
2242
 
        try {
2243
 
                sciThis->SetDragPosition(SelectionPosition(invalidPosition));
2244
 
                //Platform::DebugPrintf("DragLeave %x\n", sciThis);
2245
 
        } catch (...) {
2246
 
                sciThis->errorStatus = SC_STATUS_FAILURE;
2247
 
        }
2248
 
}
2249
 
 
2250
 
void ScintillaGTK::DragEnd(GtkWidget *widget, GdkDragContext * /*context*/) {
2251
 
        ScintillaGTK *sciThis = ScintillaFromWidget(widget);
2252
 
        try {
2253
 
                // If drag did not result in drop here or elsewhere
2254
 
                if (!sciThis->dragWasDropped)
2255
 
                        sciThis->SetEmptySelection(sciThis->posDrag);
2256
 
                sciThis->SetDragPosition(SelectionPosition(invalidPosition));
2257
 
                //Platform::DebugPrintf("DragEnd %x %d\n", sciThis, sciThis->dragWasDropped);
2258
 
                sciThis->inDragDrop = ddNone;
2259
 
        } catch (...) {
2260
 
                sciThis->errorStatus = SC_STATUS_FAILURE;
2261
 
        }
2262
 
}
2263
 
 
2264
 
gboolean ScintillaGTK::Drop(GtkWidget *widget, GdkDragContext * /*context*/,
2265
 
                            gint, gint, guint) {
2266
 
        ScintillaGTK *sciThis = ScintillaFromWidget(widget);
2267
 
        try {
2268
 
                //Platform::DebugPrintf("Drop %x\n", sciThis);
2269
 
                sciThis->SetDragPosition(SelectionPosition(invalidPosition));
2270
 
        } catch (...) {
2271
 
                sciThis->errorStatus = SC_STATUS_FAILURE;
2272
 
        }
2273
 
        return FALSE;
2274
 
}
2275
 
 
2276
 
void ScintillaGTK::DragDataReceived(GtkWidget *widget, GdkDragContext * /*context*/,
2277
 
                                    gint, gint, GtkSelectionData *selection_data, guint /*info*/, guint) {
2278
 
        ScintillaGTK *sciThis = ScintillaFromWidget(widget);
2279
 
        try {
2280
 
                sciThis->ReceivedDrop(selection_data);
2281
 
                sciThis->SetDragPosition(SelectionPosition(invalidPosition));
2282
 
        } catch (...) {
2283
 
                sciThis->errorStatus = SC_STATUS_FAILURE;
2284
 
        }
2285
 
}
2286
 
 
2287
 
void ScintillaGTK::DragDataGet(GtkWidget *widget, GdkDragContext *context,
2288
 
                               GtkSelectionData *selection_data, guint info, guint) {
2289
 
        ScintillaGTK *sciThis = ScintillaFromWidget(widget);
2290
 
        try {
2291
 
                sciThis->dragWasDropped = true;
2292
 
                if (!sciThis->sel.Empty()) {
2293
 
                        sciThis->GetSelection(selection_data, info, &sciThis->drag);
2294
 
                }
2295
 
                if (context->action == GDK_ACTION_MOVE) {
2296
 
                        for (size_t r=0; r<sciThis->sel.Count(); r++) {
2297
 
                                if (sciThis->posDrop >= sciThis->sel.Range(r).Start()) {
2298
 
                                        if (sciThis->posDrop > sciThis->sel.Range(r).End()) {
2299
 
                                                sciThis->posDrop.Add(-sciThis->sel.Range(r).Length());
2300
 
                                        } else {
2301
 
                                                sciThis->posDrop.Add(-SelectionRange(sciThis->posDrop, sciThis->sel.Range(r).Start()).Length());
2302
 
                                        }
2303
 
                                }
2304
 
                        }
2305
 
                        sciThis->ClearSelection();
2306
 
                }
2307
 
                sciThis->SetDragPosition(SelectionPosition(invalidPosition));
2308
 
        } catch (...) {
2309
 
                sciThis->errorStatus = SC_STATUS_FAILURE;
2310
 
        }
2311
 
}
2312
 
 
2313
 
int ScintillaGTK::TimeOut(ScintillaGTK *sciThis) {
2314
 
        sciThis->Tick();
2315
 
        return 1;
2316
 
}
2317
 
 
2318
 
gboolean ScintillaGTK::IdleCallback(ScintillaGTK *sciThis) {
2319
 
        // Idler will be automatically stopped, if there is nothing
2320
 
        // to do while idle.
2321
 
        bool ret = sciThis->Idle();
2322
 
        if (ret == false) {
2323
 
                // FIXME: This will remove the idler from GTK, we don't want to
2324
 
                // remove it as it is removed automatically when this function
2325
 
                // returns false (although, it should be harmless).
2326
 
                sciThis->SetIdle(false);
2327
 
        }
2328
 
        return ret;
2329
 
}
2330
 
 
2331
 
gboolean ScintillaGTK::StyleIdle(ScintillaGTK *sciThis) {
2332
 
        sciThis->IdleStyling();
2333
 
        // Idler will be automatically stopped
2334
 
        return FALSE;
2335
 
}
2336
 
 
2337
 
void ScintillaGTK::QueueStyling(int upTo) {
2338
 
        Editor::QueueStyling(upTo);
2339
 
        if (!styleNeeded.active) {
2340
 
                // Only allow one style needed to be queued
2341
 
                styleNeeded.active = true;
2342
 
                g_idle_add_full(G_PRIORITY_HIGH_IDLE, 
2343
 
                        reinterpret_cast<GSourceFunc>(StyleIdle), this, NULL);
2344
 
        }
2345
 
}
2346
 
 
2347
 
void ScintillaGTK::PopUpCB(ScintillaGTK *sciThis, guint action, GtkWidget *) {
2348
 
        if (action) {
2349
 
                sciThis->Command(action);
2350
 
        }
2351
 
}
2352
 
 
2353
 
gint ScintillaGTK::PressCT(GtkWidget *widget, GdkEventButton *event, ScintillaGTK *sciThis) {
2354
 
        try {
2355
 
                if (event->window != widget->window)
2356
 
                        return FALSE;
2357
 
                if (event->type != GDK_BUTTON_PRESS)
2358
 
                        return FALSE;
2359
 
                Point pt;
2360
 
                pt.x = int(event->x);
2361
 
                pt.y = int(event->y);
2362
 
                sciThis->ct.MouseClick(pt);
2363
 
                sciThis->CallTipClick();
2364
 
        } catch (...) {
2365
 
        }
2366
 
        return TRUE;
2367
 
}
2368
 
 
2369
 
gint ScintillaGTK::ExposeCT(GtkWidget *widget, GdkEventExpose * /*ose*/, CallTip *ctip) {
2370
 
        try {
2371
 
                Surface *surfaceWindow = Surface::Allocate();
2372
 
                if (surfaceWindow) {
2373
 
                        surfaceWindow->Init(widget->window, widget);
2374
 
                        surfaceWindow->SetUnicodeMode(SC_CP_UTF8 == ctip->codePage);
2375
 
                        surfaceWindow->SetDBCSMode(ctip->codePage);
2376
 
                        ctip->PaintCT(surfaceWindow);
2377
 
                        surfaceWindow->Release();
2378
 
                        delete surfaceWindow;
2379
 
                }
2380
 
        } catch (...) {
2381
 
                // No pointer back to Scintilla to save status
2382
 
        }
2383
 
        return TRUE;
2384
 
}
2385
 
 
2386
 
sptr_t ScintillaGTK::DirectFunction(
2387
 
    ScintillaGTK *sciThis, unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
2388
 
        return sciThis->WndProc(iMessage, wParam, lParam);
2389
 
}
2390
 
 
2391
 
sptr_t scintilla_send_message(ScintillaObject *sci, unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
2392
 
        ScintillaGTK *psci = reinterpret_cast<ScintillaGTK *>(sci->pscin);
2393
 
        return psci->WndProc(iMessage, wParam, lParam);
2394
 
}
2395
 
 
2396
 
static void scintilla_class_init(ScintillaClass *klass);
2397
 
static void scintilla_init(ScintillaObject *sci);
2398
 
 
2399
 
extern void Platform_Initialise();
2400
 
extern void Platform_Finalise();
2401
 
 
2402
 
GType scintilla_get_type() {
2403
 
        static GType scintilla_type = 0;
2404
 
        try {
2405
 
 
2406
 
                if (!scintilla_type) {
2407
 
                        scintilla_type = g_type_from_name("Scintilla");
2408
 
                        if (!scintilla_type) {
2409
 
                                static GTypeInfo scintilla_info = {
2410
 
                                        (guint16) sizeof (ScintillaClass),
2411
 
                                        NULL, //(GBaseInitFunc)
2412
 
                                        NULL, //(GBaseFinalizeFunc)
2413
 
                                        (GClassInitFunc) scintilla_class_init,
2414
 
                                        NULL, //(GClassFinalizeFunc)
2415
 
                                        NULL, //gconstpointer data
2416
 
                                        (guint16) sizeof (ScintillaObject),
2417
 
                                        0, //n_preallocs
2418
 
                                        (GInstanceInitFunc) scintilla_init,
2419
 
                                        NULL //(GTypeValueTable*)
2420
 
                                };
2421
 
 
2422
 
                                scintilla_type = g_type_register_static(
2423
 
                                            GTK_TYPE_CONTAINER, "Scintilla", &scintilla_info, (GTypeFlags) 0);
2424
 
                        }
2425
 
                }
2426
 
 
2427
 
        } catch (...) {
2428
 
        }
2429
 
        return scintilla_type;
2430
 
}
2431
 
 
2432
 
void ScintillaGTK::ClassInit(OBJECT_CLASS* object_class, GtkWidgetClass *widget_class, GtkContainerClass *container_class) {
2433
 
        Platform_Initialise();
2434
 
        atomClipboard = gdk_atom_intern("CLIPBOARD", FALSE);
2435
 
        atomUTF8 = gdk_atom_intern("UTF8_STRING", FALSE);
2436
 
        atomString = GDK_SELECTION_TYPE_STRING;
2437
 
        atomUriList = gdk_atom_intern("text/uri-list", FALSE);
2438
 
        atomDROPFILES_DND = gdk_atom_intern("DROPFILES_DND", FALSE);
2439
 
 
2440
 
        // Define default signal handlers for the class:  Could move more
2441
 
        // of the signal handlers here (those that currently attached to wDraw
2442
 
        // in Initialise() may require coordinate translation?)
2443
 
 
2444
 
        object_class->finalize = Destroy;
2445
 
        widget_class->size_request = SizeRequest;
2446
 
        widget_class->size_allocate = SizeAllocate;
2447
 
        widget_class->expose_event = ExposeMain;
2448
 
        widget_class->motion_notify_event = Motion;
2449
 
        widget_class->button_press_event = Press;
2450
 
        widget_class->button_release_event = MouseRelease;
2451
 
        widget_class->scroll_event = ScrollEvent;
2452
 
        widget_class->key_press_event = KeyPress;
2453
 
        widget_class->key_release_event = KeyRelease;
2454
 
        widget_class->focus_in_event = FocusIn;
2455
 
        widget_class->focus_out_event = FocusOut;
2456
 
        widget_class->selection_received = SelectionReceived;
2457
 
        widget_class->selection_get = SelectionGet;
2458
 
        widget_class->selection_clear_event = SelectionClear;
2459
 
 
2460
 
        widget_class->drag_data_received = DragDataReceived;
2461
 
        widget_class->drag_motion = DragMotion;
2462
 
        widget_class->drag_leave = DragLeave;
2463
 
        widget_class->drag_end = DragEnd;
2464
 
        widget_class->drag_drop = Drop;
2465
 
        widget_class->drag_data_get = DragDataGet;
2466
 
 
2467
 
        widget_class->realize = Realize;
2468
 
        widget_class->unrealize = UnRealize;
2469
 
        widget_class->map = Map;
2470
 
        widget_class->unmap = UnMap;
2471
 
 
2472
 
        container_class->forall = MainForAll;
2473
 
}
2474
 
 
2475
 
#define SIG_MARSHAL scintilla_marshal_NONE__INT_POINTER
2476
 
#define MARSHAL_ARGUMENTS G_TYPE_INT, G_TYPE_POINTER
2477
 
 
2478
 
static void scintilla_class_init(ScintillaClass *klass) {
2479
 
        try {
2480
 
                OBJECT_CLASS *object_class = (OBJECT_CLASS*) klass;
2481
 
                GtkWidgetClass *widget_class = (GtkWidgetClass*) klass;
2482
 
                GtkContainerClass *container_class = (GtkContainerClass*) klass;
2483
 
 
2484
 
                GSignalFlags sigflags = GSignalFlags(G_SIGNAL_ACTION | G_SIGNAL_RUN_LAST);
2485
 
                scintilla_signals[COMMAND_SIGNAL] = g_signal_new(
2486
 
                            "command",
2487
 
                            G_TYPE_FROM_CLASS(object_class),
2488
 
                            sigflags,
2489
 
                            G_STRUCT_OFFSET(ScintillaClass, command),
2490
 
                            NULL, //(GSignalAccumulator)
2491
 
                            NULL, //(gpointer)
2492
 
                            SIG_MARSHAL,
2493
 
                            G_TYPE_NONE,
2494
 
                            2, MARSHAL_ARGUMENTS);
2495
 
 
2496
 
                scintilla_signals[NOTIFY_SIGNAL] = g_signal_new(
2497
 
                            SCINTILLA_NOTIFY,
2498
 
                            G_TYPE_FROM_CLASS(object_class),
2499
 
                            sigflags,
2500
 
                            G_STRUCT_OFFSET(ScintillaClass, notify),
2501
 
                            NULL,
2502
 
                            NULL,
2503
 
                            SIG_MARSHAL,
2504
 
                            G_TYPE_NONE,
2505
 
                            2, MARSHAL_ARGUMENTS);
2506
 
 
2507
 
                klass->command = NULL;
2508
 
                klass->notify = NULL;
2509
 
 
2510
 
                ScintillaGTK::ClassInit(object_class, widget_class, container_class);
2511
 
        } catch (...) {
2512
 
        }
2513
 
}
2514
 
 
2515
 
static void scintilla_init(ScintillaObject *sci) {
2516
 
        try {
2517
 
                GTK_WIDGET_SET_FLAGS(sci, GTK_CAN_FOCUS);
2518
 
                sci->pscin = new ScintillaGTK(sci);
2519
 
        } catch (...) {
2520
 
        }
2521
 
}
2522
 
 
2523
 
GtkWidget* scintilla_new() {
2524
 
        return GTK_WIDGET(g_object_new(scintilla_get_type(), NULL));
2525
 
}
2526
 
 
2527
 
void scintilla_set_id(ScintillaObject *sci, uptr_t id) {
2528
 
        ScintillaGTK *psci = reinterpret_cast<ScintillaGTK *>(sci->pscin);
2529
 
        psci->ctrlID = id;
2530
 
}
2531
 
 
2532
 
void scintilla_release_resources(void) {
2533
 
        try {
2534
 
                Platform_Finalise();
2535
 
        } catch (...) {
2536
 
        }
2537
 
}