1 // Scintilla source code edit control
\r
2 // ScintillaGTK.cxx - GTK+ specific subclass of ScintillaBase
\r
3 // Copyright 1998-2004 by Neil Hodgson <neilh@scintilla.org>
\r
4 // The License.txt file describes the conditions under which this software may be distributed.
\r
12 #include <gtk/gtk.h>
\r
13 #include <gdk/gdkkeysyms.h>
\r
15 #include "Platform.h"
\r
18 #include "windows.h"
\r
21 #include "Scintilla.h"
\r
22 #include "ScintillaWidget.h"
\r
24 #include "SciLexer.h"
\r
25 #include "PropSet.h"
\r
26 #include "Accessor.h"
\r
27 #include "KeyWords.h"
\r
29 #include "SVector.h"
\r
30 #include "SplitVector.h"
\r
31 #include "Partitioning.h"
\r
32 #include "RunStyles.h"
\r
33 #include "ContractionState.h"
\r
34 #include "CellBuffer.h"
\r
35 #include "CallTip.h"
\r
37 #include "Indicator.h"
\r
39 #include "LineMarker.h"
\r
41 #include "AutoComplete.h"
\r
42 #include "ViewStyle.h"
\r
43 #include "Decoration.h"
\r
44 #include "CharClassify.h"
\r
45 #include "Document.h"
\r
46 #include "PositionCache.h"
\r
48 #include "SString.h"
\r
49 #include "ScintillaBase.h"
\r
50 #include "UniConversion.h"
\r
52 #include "gtk/gtksignal.h"
\r
53 #include "gtk/gtkmarshal.h"
\r
54 #if GLIB_MAJOR_VERSION >= 2
\r
55 #include "scintilla-marshal.h"
\r
60 #include <gmodule.h>
\r
61 #include "ExternalLexer.h"
\r
64 #define INTERNATIONAL_INPUT
\r
66 #if !PLAT_GTK_WIN32 || GTK_MAJOR_VERSION >= 2
\r
67 #define USE_CONVERTER
\r
70 #ifdef USE_CONVERTER
\r
71 #include "Converter.h"
\r
75 // Constant conditional expressions are because of GTK+ headers
\r
76 #pragma warning(disable: 4127)
\r
77 // Ignore unreferenced local functions in GTK+ headers
\r
78 #pragma warning(disable: 4505)
\r
81 #if GTK_CHECK_VERSION(2,6,0)
\r
82 #define USE_GTK_CLIPBOARD
\r
85 #if GLIB_MAJOR_VERSION < 2
\r
86 #define OBJECT_CLASS GtkObjectClass
\r
88 #define OBJECT_CLASS GObjectClass
\r
91 extern char *UTF8FromLatin1(const char *s, int &len);
\r
93 class ScintillaGTK : public ScintillaBase {
\r
94 _ScintillaObject *sci;
\r
98 GtkObject *adjustmentv;
\r
99 GtkObject *adjustmenth;
\r
100 int scrollBarWidth;
\r
101 int scrollBarHeight;
\r
103 // Because clipboard access is asynchronous, copyText is created by Copy
\r
104 #ifndef USE_GTK_CLIPBOARD
\r
105 SelectionText copyText;
\r
108 SelectionText primary;
\r
110 GdkEventButton evbtn;
\r
111 bool capturedMouse;
\r
112 bool dragWasDropped;
\r
115 GtkWidgetClass *parentClass;
\r
117 static GdkAtom atomClipboard;
\r
118 static GdkAtom atomUTF8;
\r
119 static GdkAtom atomString;
\r
120 static GdkAtom atomUriList;
\r
121 static GdkAtom atomDROPFILES_DND;
\r
122 GdkAtom atomSought;
\r
125 CLIPFORMAT cfColumnSelect;
\r
128 #ifdef INTERNATIONAL_INPUT
\r
129 #if GTK_MAJOR_VERSION < 2
\r
130 // Input context used for supporting internationalized key entry
\r
132 GdkICAttr *ic_attr;
\r
135 Window wPreeditDraw;
\r
136 GtkIMContext *im_context;
\r
140 // Wheel mouse support
\r
141 unsigned int linesPerScroll;
\r
142 GTimeVal lastWheelMouseTime;
\r
143 gint lastWheelMouseDirection;
\r
144 gint wheelMouseIntensity;
\r
146 GdkRegion *rgnUpdate;
\r
148 // Private so ScintillaGTK objects can not be copied
\r
149 ScintillaGTK(const ScintillaGTK &) : ScintillaBase() {}
\r
150 ScintillaGTK &operator=(const ScintillaGTK &) { return * this; }
\r
153 ScintillaGTK(_ScintillaObject *sci_);
\r
154 virtual ~ScintillaGTK();
\r
155 static void ClassInit(OBJECT_CLASS* object_class, GtkWidgetClass *widget_class, GtkContainerClass *container_class);
\r
157 virtual void Initialise();
\r
158 virtual void Finalise();
\r
159 virtual void DisplayCursor(Window::Cursor c);
\r
160 virtual bool DragThreshold(Point ptStart, Point ptNow);
\r
161 virtual void StartDrag();
\r
162 int TargetAsUTF8(char *text);
\r
163 int EncodedFromUTF8(char *utf8, char *encoded);
\r
164 virtual bool ValidCodePage(int codePage) const;
\r
165 public: // Public for scintilla_send_message
\r
166 virtual sptr_t WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
\r
168 virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
\r
169 virtual void SetTicking(bool on);
\r
170 virtual bool SetIdle(bool on);
\r
171 virtual void SetMouseCapture(bool on);
\r
172 virtual bool HaveMouseCapture();
\r
173 virtual bool PaintContains(PRectangle rc);
\r
175 virtual PRectangle GetClientRectangle();
\r
176 void SyncPaint(PRectangle rc);
\r
177 virtual void ScrollText(int linesToMove);
\r
178 virtual void SetVerticalScrollPos();
\r
179 virtual void SetHorizontalScrollPos();
\r
180 virtual bool ModifyScrollBars(int nMax, int nPage);
\r
181 void ReconfigureScrollBars();
\r
182 virtual void NotifyChange();
\r
183 virtual void NotifyFocus(bool focus);
\r
184 virtual void NotifyParent(SCNotification scn);
\r
185 void NotifyKey(int key, int modifiers);
\r
186 void NotifyURIDropped(const char *list);
\r
187 const char *CharacterSetID() const;
\r
188 virtual int KeyDefault(int key, int modifiers);
\r
189 virtual void CopyToClipboard(const SelectionText &selectedText);
\r
190 virtual void Copy();
\r
191 virtual void Paste();
\r
192 virtual void CreateCallTipWindow(PRectangle rc);
\r
193 virtual void AddToPopUp(const char *label, int cmd = 0, bool enabled = true);
\r
194 bool OwnPrimarySelection();
\r
195 virtual void ClaimSelection();
\r
196 void GetGtkSelectionText(GtkSelectionData *selectionData, SelectionText &selText);
\r
197 void ReceivedSelection(GtkSelectionData *selection_data);
\r
198 void ReceivedDrop(GtkSelectionData *selection_data);
\r
199 static void GetSelection(GtkSelectionData *selection_data, guint info, SelectionText *selected);
\r
200 #ifdef USE_GTK_CLIPBOARD
\r
201 void StoreOnClipboard(SelectionText *clipText);
\r
202 static void ClipboardGetSelection(GtkClipboard* clip, GtkSelectionData *selection_data, guint info, void *data);
\r
203 static void ClipboardClearSelection(GtkClipboard* clip, void *data);
\r
206 void UnclaimSelection(GdkEventSelection *selection_event);
\r
207 void Resize(int width, int height);
\r
209 // Callback functions
\r
210 void RealizeThis(GtkWidget *widget);
\r
211 static void Realize(GtkWidget *widget);
\r
212 void UnRealizeThis(GtkWidget *widget);
\r
213 static void UnRealize(GtkWidget *widget);
\r
215 static void Map(GtkWidget *widget);
\r
217 static void UnMap(GtkWidget *widget);
\r
218 static gint CursorMoved(GtkWidget *widget, int xoffset, int yoffset, ScintillaGTK *sciThis);
\r
219 static gint FocusIn(GtkWidget *widget, GdkEventFocus *event);
\r
220 static gint FocusOut(GtkWidget *widget, GdkEventFocus *event);
\r
221 static void SizeRequest(GtkWidget *widget, GtkRequisition *requisition);
\r
222 static void SizeAllocate(GtkWidget *widget, GtkAllocation *allocation);
\r
223 gint Expose(GtkWidget *widget, GdkEventExpose *ose);
\r
224 static gint ExposeMain(GtkWidget *widget, GdkEventExpose *ose);
\r
225 static void Draw(GtkWidget *widget, GdkRectangle *area);
\r
226 void ForAll(GtkCallback callback, gpointer callback_data);
\r
227 static void MainForAll(GtkContainer *container, gboolean include_internals, GtkCallback callback, gpointer callback_data);
\r
229 static void ScrollSignal(GtkAdjustment *adj, ScintillaGTK *sciThis);
\r
230 static void ScrollHSignal(GtkAdjustment *adj, ScintillaGTK *sciThis);
\r
231 gint PressThis(GdkEventButton *event);
\r
232 static gint Press(GtkWidget *widget, GdkEventButton *event);
\r
233 static gint MouseRelease(GtkWidget *widget, GdkEventButton *event);
\r
234 #if PLAT_GTK_WIN32 || (GTK_MAJOR_VERSION >= 2)
\r
235 static gint ScrollEvent(GtkWidget *widget, GdkEventScroll *event);
\r
237 static gint Motion(GtkWidget *widget, GdkEventMotion *event);
\r
238 gboolean KeyThis(GdkEventKey *event);
\r
239 static gboolean KeyPress(GtkWidget *widget, GdkEventKey *event);
\r
240 static gboolean KeyRelease(GtkWidget *widget, GdkEventKey *event);
\r
241 #if GTK_MAJOR_VERSION >= 2
\r
242 static gboolean ExposePreedit(GtkWidget *widget, GdkEventExpose *ose, ScintillaGTK *sciThis);
\r
243 gboolean ExposePreeditThis(GtkWidget *widget, GdkEventExpose *ose);
\r
244 static void Commit(GtkIMContext *context, char *str, ScintillaGTK *sciThis);
\r
245 void CommitThis(char *str);
\r
246 static void PreeditChanged(GtkIMContext *context, ScintillaGTK *sciThis);
\r
247 void PreeditChangedThis();
\r
249 static gint StyleSetText(GtkWidget *widget, GtkStyle *previous, void*);
\r
250 static gint RealizeText(GtkWidget *widget, void*);
\r
251 #if GLIB_MAJOR_VERSION < 2
\r
252 static void Destroy(GtkObject *object);
\r
254 static void Destroy(GObject *object);
\r
256 static void SelectionReceived(GtkWidget *widget, GtkSelectionData *selection_data,
\r
258 static void SelectionGet(GtkWidget *widget, GtkSelectionData *selection_data,
\r
259 guint info, guint time);
\r
260 static gint SelectionClear(GtkWidget *widget, GdkEventSelection *selection_event);
\r
261 #if GTK_MAJOR_VERSION < 2
\r
262 static gint SelectionNotify(GtkWidget *widget, GdkEventSelection *selection_event);
\r
264 static void DragBegin(GtkWidget *widget, GdkDragContext *context);
\r
265 gboolean DragMotionThis(GdkDragContext *context, gint x, gint y, guint dragtime);
\r
266 static gboolean DragMotion(GtkWidget *widget, GdkDragContext *context,
\r
267 gint x, gint y, guint dragtime);
\r
268 static void DragLeave(GtkWidget *widget, GdkDragContext *context,
\r
270 static void DragEnd(GtkWidget *widget, GdkDragContext *context);
\r
271 static gboolean Drop(GtkWidget *widget, GdkDragContext *context,
\r
272 gint x, gint y, guint time);
\r
273 static void DragDataReceived(GtkWidget *widget, GdkDragContext *context,
\r
274 gint x, gint y, GtkSelectionData *selection_data, guint info, guint time);
\r
275 static void DragDataGet(GtkWidget *widget, GdkDragContext *context,
\r
276 GtkSelectionData *selection_data, guint info, guint time);
\r
277 static gint TimeOut(ScintillaGTK *sciThis);
\r
278 static gint IdleCallback(ScintillaGTK *sciThis);
\r
279 static void PopUpCB(ScintillaGTK *sciThis, guint action, GtkWidget *widget);
\r
281 gint ExposeTextThis(GtkWidget *widget, GdkEventExpose *ose);
\r
282 static gint ExposeText(GtkWidget *widget, GdkEventExpose *ose, ScintillaGTK *sciThis);
\r
284 static gint ExposeCT(GtkWidget *widget, GdkEventExpose *ose, CallTip *ct);
\r
285 static gint PressCT(GtkWidget *widget, GdkEventButton *event, ScintillaGTK *sciThis);
\r
287 static sptr_t DirectFunction(ScintillaGTK *sciThis,
\r
288 unsigned int iMessage, uptr_t wParam, sptr_t lParam);
\r
297 static gint scintilla_signals[LAST_SIGNAL] = { 0 };
\r
298 #if GLIB_MAJOR_VERSION < 2
\r
299 static GtkWidgetClass *parent_class = NULL;
\r
305 TARGET_COMPOUND_TEXT,
\r
306 TARGET_UTF8_STRING,
\r
310 GdkAtom ScintillaGTK::atomClipboard = 0;
\r
311 GdkAtom ScintillaGTK::atomUTF8 = 0;
\r
312 GdkAtom ScintillaGTK::atomString = 0;
\r
313 GdkAtom ScintillaGTK::atomUriList = 0;
\r
314 GdkAtom ScintillaGTK::atomDROPFILES_DND = 0;
\r
316 static const GtkTargetEntry clipboardCopyTargets[] = {
\r
317 { (gchar *) "UTF8_STRING", 0, TARGET_UTF8_STRING },
\r
318 { (gchar *) "STRING", 0, TARGET_STRING },
\r
320 static const gint nClipboardCopyTargets = sizeof(clipboardCopyTargets) / sizeof(clipboardCopyTargets[0]);
\r
322 static const GtkTargetEntry clipboardPasteTargets[] = {
\r
323 { (gchar *) "text/uri-list", 0, TARGET_URI },
\r
324 { (gchar *) "UTF8_STRING", 0, TARGET_UTF8_STRING },
\r
325 { (gchar *) "STRING", 0, TARGET_STRING },
\r
327 static const gint nClipboardPasteTargets = sizeof(clipboardPasteTargets) / sizeof(clipboardPasteTargets[0]);
\r
329 static GtkWidget *PWidget(Window &w) {
\r
330 return reinterpret_cast<GtkWidget *>(w.GetID());
\r
333 static ScintillaGTK *ScintillaFromWidget(GtkWidget *widget) {
\r
334 ScintillaObject *scio = reinterpret_cast<ScintillaObject *>(widget);
\r
335 return reinterpret_cast<ScintillaGTK *>(scio->pscin);
\r
338 ScintillaGTK::ScintillaGTK(_ScintillaObject *sci_) :
\r
339 adjustmentv(0), adjustmenth(0),
\r
340 scrollBarWidth(30), scrollBarHeight(30),
\r
341 capturedMouse(false), dragWasDropped(false),
\r
342 lastKey(0), parentClass(0),
\r
343 #ifdef INTERNATIONAL_INPUT
\r
344 #if GTK_MAJOR_VERSION < 2
\r
351 lastWheelMouseDirection(0),
\r
352 wheelMouseIntensity(0),
\r
355 wMain = GTK_WIDGET(sci);
\r
358 // There does not seem to be a real standard for indicating that the clipboard
\r
359 // contains a rectangular selection, so copy Developer Studio.
\r
360 cfColumnSelect = static_cast<CLIPFORMAT>(
\r
361 ::RegisterClipboardFormat("MSDEVColumnSelect"));
\r
363 // Get intellimouse parameters when running on win32; otherwise use
\r
364 // reasonable default
\r
365 #ifndef SPI_GETWHEELSCROLLLINES
\r
366 #define SPI_GETWHEELSCROLLLINES 104
\r
368 ::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &linesPerScroll, 0);
\r
370 linesPerScroll = 4;
\r
372 lastWheelMouseTime.tv_sec = 0;
\r
373 lastWheelMouseTime.tv_usec = 0;
\r
378 ScintillaGTK::~ScintillaGTK() {
\r
381 void ScintillaGTK::RealizeThis(GtkWidget *widget) {
\r
382 //Platform::DebugPrintf("ScintillaGTK::realize this\n");
\r
383 GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED);
\r
384 GdkWindowAttr attrs;
\r
385 attrs.window_type = GDK_WINDOW_CHILD;
\r
386 attrs.x = widget->allocation.x;
\r
387 attrs.y = widget->allocation.y;
\r
388 attrs.width = widget->allocation.width;
\r
389 attrs.height = widget->allocation.height;
\r
390 attrs.wclass = GDK_INPUT_OUTPUT;
\r
391 attrs.visual = gtk_widget_get_visual(widget);
\r
392 attrs.colormap = gtk_widget_get_colormap(widget);
\r
393 attrs.event_mask = gtk_widget_get_events(widget) | GDK_EXPOSURE_MASK;
\r
394 GdkCursor *cursor = gdk_cursor_new(GDK_XTERM);
\r
395 attrs.cursor = cursor;
\r
396 widget->window = gdk_window_new(gtk_widget_get_parent_window(widget), &attrs,
\r
397 GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP | GDK_WA_CURSOR);
\r
398 gdk_window_set_user_data(widget->window, widget);
\r
399 gdk_window_set_background(widget->window, &widget->style->bg[GTK_STATE_NORMAL]);
\r
400 gdk_window_show(widget->window);
\r
401 gdk_cursor_destroy(cursor);
\r
402 widget->style = gtk_style_attach(widget->style, widget->window);
\r
403 #ifdef INTERNATIONAL_INPUT
\r
404 #if GTK_MAJOR_VERSION < 2
\r
405 if (gdk_im_ready() && (ic_attr = gdk_ic_attr_new()) != NULL) {
\r
406 gint width, height;
\r
407 GdkColormap *colormap;
\r
409 GdkICAttr *attr = ic_attr;
\r
410 GdkICAttributesType attrmask = GDK_IC_ALL_REQ;
\r
412 GdkIMStyle supported_style = (GdkIMStyle) (GDK_IM_PREEDIT_NONE |
\r
413 GDK_IM_PREEDIT_NOTHING |
\r
414 GDK_IM_PREEDIT_POSITION |
\r
415 GDK_IM_STATUS_NONE |
\r
416 GDK_IM_STATUS_NOTHING);
\r
418 if (widget->style && widget->style->font->type != GDK_FONT_FONTSET)
\r
419 supported_style = (GdkIMStyle) ((int) supported_style & ~GDK_IM_PREEDIT_POSITION);
\r
421 attr->style = style = gdk_im_decide_style(supported_style);
\r
422 attr->client_window = widget->window;
\r
424 if ((colormap = gtk_widget_get_colormap (widget)) != gtk_widget_get_default_colormap ()) {
\r
425 attrmask = (GdkICAttributesType) ((int) attrmask | GDK_IC_PREEDIT_COLORMAP);
\r
426 attr->preedit_colormap = colormap;
\r
429 switch (style & GDK_IM_PREEDIT_MASK) {
\r
430 case GDK_IM_PREEDIT_POSITION:
\r
431 if (widget->style && widget->style->font->type != GDK_FONT_FONTSET) {
\r
432 g_warning("over-the-spot style requires fontset");
\r
436 attrmask = (GdkICAttributesType) ((int) attrmask | GDK_IC_PREEDIT_POSITION_REQ);
\r
437 gdk_window_get_size(widget->window, &width, &height);
\r
438 attr->spot_location.x = 0;
\r
439 attr->spot_location.y = height;
\r
440 attr->preedit_area.x = 0;
\r
441 attr->preedit_area.y = 0;
\r
442 attr->preedit_area.width = width;
\r
443 attr->preedit_area.height = height;
\r
444 attr->preedit_fontset = widget->style->font;
\r
448 ic = gdk_ic_new(attr, attrmask);
\r
451 g_warning("Can't create input context.");
\r
453 mask = gdk_window_get_events(widget->window);
\r
454 mask = (GdkEventMask) ((int) mask | gdk_ic_get_events(ic));
\r
455 gdk_window_set_events(widget->window, mask);
\r
457 if (GTK_WIDGET_HAS_FOCUS(widget))
\r
458 gdk_im_begin(ic, widget->window);
\r
462 wPreedit = gtk_window_new(GTK_WINDOW_POPUP);
\r
463 wPreeditDraw = gtk_drawing_area_new();
\r
464 GtkWidget *predrw = PWidget(wPreeditDraw); // No code inside the G_OBJECT macro
\r
465 g_signal_connect(G_OBJECT(predrw), "expose_event",
\r
466 G_CALLBACK(ExposePreedit), this);
\r
467 gtk_container_add(GTK_CONTAINER(PWidget(wPreedit)), predrw);
\r
468 gtk_widget_realize(PWidget(wPreedit));
\r
469 gtk_widget_realize(predrw);
\r
470 gtk_widget_show(predrw);
\r
472 im_context = gtk_im_multicontext_new();
\r
473 g_signal_connect(G_OBJECT(im_context), "commit",
\r
474 G_CALLBACK(Commit), this);
\r
475 g_signal_connect(G_OBJECT(im_context), "preedit_changed",
\r
476 G_CALLBACK(PreeditChanged), this);
\r
477 gtk_im_context_set_client_window(im_context, widget->window);
\r
480 GtkWidget *widtxt = PWidget(wText); // // No code inside the G_OBJECT macro
\r
481 #if GLIB_MAJOR_VERSION < 2
\r
482 gtk_signal_connect_after(GTK_OBJECT(widtxt), "style_set",
\r
483 GtkSignalFunc(ScintillaGTK::StyleSetText), NULL);
\r
484 gtk_signal_connect_after(GTK_OBJECT(widtxt), "realize",
\r
485 GtkSignalFunc(ScintillaGTK::RealizeText), NULL);
\r
487 g_signal_connect_after(G_OBJECT(widtxt), "style_set",
\r
488 G_CALLBACK(ScintillaGTK::StyleSetText), NULL);
\r
489 g_signal_connect_after(G_OBJECT(widtxt), "realize",
\r
490 G_CALLBACK(ScintillaGTK::RealizeText), NULL);
\r
492 gtk_widget_realize(widtxt);
\r
493 gtk_widget_realize(PWidget(scrollbarv));
\r
494 gtk_widget_realize(PWidget(scrollbarh));
\r
497 void ScintillaGTK::Realize(GtkWidget *widget) {
\r
498 ScintillaGTK *sciThis = ScintillaFromWidget(widget);
\r
499 sciThis->RealizeThis(widget);
\r
502 void ScintillaGTK::UnRealizeThis(GtkWidget *widget) {
\r
503 if (GTK_WIDGET_MAPPED(widget)) {
\r
504 gtk_widget_unmap(widget);
\r
506 GTK_WIDGET_UNSET_FLAGS(widget, GTK_REALIZED);
\r
507 gtk_widget_unrealize(PWidget(wText));
\r
508 gtk_widget_unrealize(PWidget(scrollbarv));
\r
509 gtk_widget_unrealize(PWidget(scrollbarh));
\r
510 #ifdef INTERNATIONAL_INPUT
\r
511 #if GTK_MAJOR_VERSION < 2
\r
513 gdk_ic_destroy(ic);
\r
517 gdk_ic_attr_destroy(ic_attr);
\r
521 gtk_widget_unrealize(PWidget(wPreedit));
\r
522 gtk_widget_unrealize(PWidget(wPreeditDraw));
\r
523 g_object_unref(im_context);
\r
527 if (GTK_WIDGET_CLASS(parentClass)->unrealize)
\r
528 GTK_WIDGET_CLASS(parentClass)->unrealize(widget);
\r
533 void ScintillaGTK::UnRealize(GtkWidget *widget) {
\r
534 ScintillaGTK *sciThis = ScintillaFromWidget(widget);
\r
535 sciThis->UnRealizeThis(widget);
\r
538 static void MapWidget(GtkWidget *widget) {
\r
540 GTK_WIDGET_VISIBLE(widget) &&
\r
541 !GTK_WIDGET_MAPPED(widget)) {
\r
542 gtk_widget_map(widget);
\r
546 void ScintillaGTK::MapThis() {
\r
547 //Platform::DebugPrintf("ScintillaGTK::map this\n");
\r
548 GTK_WIDGET_SET_FLAGS(PWidget(wMain), GTK_MAPPED);
\r
549 MapWidget(PWidget(wText));
\r
550 MapWidget(PWidget(scrollbarh));
\r
551 MapWidget(PWidget(scrollbarv));
\r
552 wMain.SetCursor(Window::cursorArrow);
\r
553 scrollbarv.SetCursor(Window::cursorArrow);
\r
554 scrollbarh.SetCursor(Window::cursorArrow);
\r
556 gdk_window_show(PWidget(wMain)->window);
\r
559 void ScintillaGTK::Map(GtkWidget *widget) {
\r
560 ScintillaGTK *sciThis = ScintillaFromWidget(widget);
\r
561 sciThis->MapThis();
\r
564 void ScintillaGTK::UnMapThis() {
\r
565 //Platform::DebugPrintf("ScintillaGTK::unmap this\n");
\r
566 GTK_WIDGET_UNSET_FLAGS(PWidget(wMain), GTK_MAPPED);
\r
568 gdk_window_hide(PWidget(wMain)->window);
\r
569 gtk_widget_unmap(PWidget(wText));
\r
570 gtk_widget_unmap(PWidget(scrollbarh));
\r
571 gtk_widget_unmap(PWidget(scrollbarv));
\r
574 void ScintillaGTK::UnMap(GtkWidget *widget) {
\r
575 ScintillaGTK *sciThis = ScintillaFromWidget(widget);
\r
576 sciThis->UnMapThis();
\r
579 void ScintillaGTK::ForAll(GtkCallback callback, gpointer callback_data) {
\r
580 (*callback) (PWidget(wText), callback_data);
\r
581 (*callback) (PWidget(scrollbarv), callback_data);
\r
582 (*callback) (PWidget(scrollbarh), callback_data);
\r
585 void ScintillaGTK::MainForAll(GtkContainer *container, gboolean include_internals, GtkCallback callback, gpointer callback_data) {
\r
586 ScintillaGTK *sciThis = ScintillaFromWidget((GtkWidget *)container);
\r
588 if (callback != NULL && include_internals) {
\r
589 sciThis->ForAll(callback, callback_data);
\r
593 #ifdef INTERNATIONAL_INPUT
\r
594 #if GTK_MAJOR_VERSION < 2
\r
595 gint ScintillaGTK::CursorMoved(GtkWidget *widget, int xoffset, int yoffset, ScintillaGTK *sciThis) {
\r
596 if (GTK_WIDGET_HAS_FOCUS(widget) && gdk_im_ready() && sciThis->ic &&
\r
597 (gdk_ic_get_style(sciThis->ic) & GDK_IM_PREEDIT_POSITION)) {
\r
598 sciThis->ic_attr->spot_location.x = xoffset;
\r
599 sciThis->ic_attr->spot_location.y = yoffset;
\r
600 gdk_ic_set_attr(sciThis->ic, sciThis->ic_attr, GDK_IC_SPOT_LOCATION);
\r
605 gint ScintillaGTK::CursorMoved(GtkWidget *, int xoffset, int yoffset, ScintillaGTK *sciThis) {
\r
611 gtk_im_context_set_cursor_location(sciThis->im_context, &area);
\r
616 gint ScintillaGTK::CursorMoved(GtkWidget *, int, int, ScintillaGTK *) {
\r
621 gint ScintillaGTK::FocusIn(GtkWidget *widget, GdkEventFocus * /*event*/) {
\r
622 ScintillaGTK *sciThis = ScintillaFromWidget(widget);
\r
623 //Platform::DebugPrintf("ScintillaGTK::focus in %x\n", sciThis);
\r
624 GTK_WIDGET_SET_FLAGS(widget, GTK_HAS_FOCUS);
\r
625 sciThis->SetFocusState(true);
\r
627 #ifdef INTERNATIONAL_INPUT
\r
628 #if GTK_MAJOR_VERSION < 2
\r
630 gdk_im_begin(sciThis->ic, widget->window);
\r
632 if (sciThis->im_context != NULL) {
\r
636 gtk_im_context_get_preedit_string(sciThis->im_context, &str, NULL, &cursor_pos);
\r
637 if (PWidget(sciThis->wPreedit) != NULL) {
\r
638 if (strlen(str) > 0) {
\r
639 gtk_widget_show(PWidget(sciThis->wPreedit));
\r
641 gtk_widget_hide(PWidget(sciThis->wPreedit));
\r
645 gtk_im_context_focus_in(sciThis->im_context);
\r
653 gint ScintillaGTK::FocusOut(GtkWidget *widget, GdkEventFocus * /*event*/) {
\r
654 ScintillaGTK *sciThis = ScintillaFromWidget(widget);
\r
655 //Platform::DebugPrintf("ScintillaGTK::focus out %x\n", sciThis);
\r
656 GTK_WIDGET_UNSET_FLAGS(widget, GTK_HAS_FOCUS);
\r
657 sciThis->SetFocusState(false);
\r
659 #ifdef INTERNATIONAL_INPUT
\r
660 #if GTK_MAJOR_VERSION < 2
\r
663 if (PWidget(sciThis->wPreedit) != NULL)
\r
664 gtk_widget_hide(PWidget(sciThis->wPreedit));
\r
665 if (sciThis->im_context != NULL)
\r
666 gtk_im_context_focus_out(sciThis->im_context);
\r
673 void ScintillaGTK::SizeRequest(GtkWidget *widget, GtkRequisition *requisition) {
\r
674 requisition->width = 600;
\r
675 requisition->height = gdk_screen_height();
\r
676 ScintillaGTK *sciThis = ScintillaFromWidget(widget);
\r
677 GtkRequisition child_requisition;
\r
678 gtk_widget_size_request(PWidget(sciThis->scrollbarh), &child_requisition);
\r
679 gtk_widget_size_request(PWidget(sciThis->scrollbarv), &child_requisition);
\r
682 void ScintillaGTK::SizeAllocate(GtkWidget *widget, GtkAllocation *allocation) {
\r
683 widget->allocation = *allocation;
\r
684 ScintillaGTK *sciThis = ScintillaFromWidget(widget);
\r
685 if (GTK_WIDGET_REALIZED(widget))
\r
686 gdk_window_move_resize(widget->window,
\r
687 widget->allocation.x,
\r
688 widget->allocation.y,
\r
689 widget->allocation.width,
\r
690 widget->allocation.height);
\r
692 sciThis->Resize(allocation->width, allocation->height);
\r
694 #ifdef INTERNATIONAL_INPUT
\r
695 #if GTK_MAJOR_VERSION < 2
\r
696 if (sciThis->ic && (gdk_ic_get_style(sciThis->ic) & GDK_IM_PREEDIT_POSITION)) {
\r
697 gint width, height;
\r
699 gdk_window_get_size(widget->window, &width, &height);
\r
700 sciThis->ic_attr->preedit_area.width = width;
\r
701 sciThis->ic_attr->preedit_area.height = height;
\r
703 gdk_ic_set_attr(sciThis->ic, sciThis->ic_attr, GDK_IC_PREEDIT_AREA);
\r
709 void ScintillaGTK::Initialise() {
\r
710 //Platform::DebugPrintf("ScintillaGTK::Initialise\n");
\r
711 parentClass = reinterpret_cast<GtkWidgetClass *>(
\r
712 gtk_type_class(gtk_container_get_type()));
\r
714 GTK_WIDGET_SET_FLAGS(PWidget(wMain), GTK_CAN_FOCUS);
\r
715 GTK_WIDGET_SET_FLAGS(GTK_WIDGET(PWidget(wMain)), GTK_SENSITIVE);
\r
716 gtk_widget_set_events(PWidget(wMain),
\r
718 | GDK_STRUCTURE_MASK
\r
719 | GDK_KEY_PRESS_MASK
\r
720 | GDK_KEY_RELEASE_MASK
\r
721 | GDK_FOCUS_CHANGE_MASK
\r
722 | GDK_LEAVE_NOTIFY_MASK
\r
723 | GDK_BUTTON_PRESS_MASK
\r
724 | GDK_BUTTON_RELEASE_MASK
\r
725 | GDK_POINTER_MOTION_MASK
\r
726 | GDK_POINTER_MOTION_HINT_MASK);
\r
728 wText = gtk_drawing_area_new();
\r
729 gtk_widget_set_parent(PWidget(wText), PWidget(wMain));
\r
730 GtkWidget *widtxt = PWidget(wText); // No code inside the G_OBJECT macro
\r
731 gtk_widget_show(widtxt);
\r
732 #if GLIB_MAJOR_VERSION < 2
\r
733 gtk_signal_connect(GTK_OBJECT(widtxt), "expose_event",
\r
734 GtkSignalFunc(ScintillaGTK::ExposeText), this);
\r
736 g_signal_connect(G_OBJECT(widtxt), "expose_event",
\r
737 G_CALLBACK(ScintillaGTK::ExposeText), this);
\r
739 gtk_widget_set_events(widtxt, GDK_EXPOSURE_MASK);
\r
740 #if GTK_MAJOR_VERSION >= 2
\r
741 // Avoid background drawing flash
\r
742 gtk_widget_set_double_buffered(widtxt, FALSE);
\r
744 gtk_drawing_area_size(GTK_DRAWING_AREA(widtxt),
\r
746 adjustmentv = gtk_adjustment_new(0.0, 0.0, 201.0, 1.0, 20.0, 20.0);
\r
747 scrollbarv = gtk_vscrollbar_new(GTK_ADJUSTMENT(adjustmentv));
\r
748 GTK_WIDGET_UNSET_FLAGS(PWidget(scrollbarv), GTK_CAN_FOCUS);
\r
749 #if GLIB_MAJOR_VERSION < 2
\r
750 gtk_signal_connect(adjustmentv, "value_changed",
\r
751 GtkSignalFunc(ScrollSignal), this);
\r
753 g_signal_connect(G_OBJECT(adjustmentv), "value_changed",
\r
754 G_CALLBACK(ScrollSignal), this);
\r
756 gtk_widget_set_parent(PWidget(scrollbarv), PWidget(wMain));
\r
757 gtk_widget_show(PWidget(scrollbarv));
\r
759 adjustmenth = gtk_adjustment_new(0.0, 0.0, 101.0, 1.0, 20.0, 20.0);
\r
760 scrollbarh = gtk_hscrollbar_new(GTK_ADJUSTMENT(adjustmenth));
\r
761 GTK_WIDGET_UNSET_FLAGS(PWidget(scrollbarh), GTK_CAN_FOCUS);
\r
762 #if GLIB_MAJOR_VERSION < 2
\r
763 gtk_signal_connect(adjustmenth, "value_changed",
\r
764 GtkSignalFunc(ScrollHSignal), this);
\r
766 g_signal_connect(G_OBJECT(adjustmenth), "value_changed",
\r
767 G_CALLBACK(ScrollHSignal), this);
\r
769 gtk_widget_set_parent(PWidget(scrollbarh), PWidget(wMain));
\r
770 gtk_widget_show(PWidget(scrollbarh));
\r
772 gtk_widget_grab_focus(PWidget(wMain));
\r
774 gtk_selection_add_targets(GTK_WIDGET(PWidget(wMain)), GDK_SELECTION_PRIMARY,
\r
775 clipboardCopyTargets, nClipboardCopyTargets);
\r
777 #ifndef USE_GTK_CLIPBOARD
\r
778 gtk_selection_add_targets(GTK_WIDGET(PWidget(wMain)), atomClipboard,
\r
779 clipboardPasteTargets, nClipboardPasteTargets);
\r
782 gtk_drag_dest_set(GTK_WIDGET(PWidget(wMain)),
\r
783 GTK_DEST_DEFAULT_ALL, clipboardPasteTargets, nClipboardPasteTargets,
\r
784 static_cast<GdkDragAction>(GDK_ACTION_COPY | GDK_ACTION_MOVE));
\r
786 #if GLIB_MAJOR_VERSION >= 2
\r
787 // Set caret period based on GTK settings
\r
788 gboolean blinkOn = false;
\r
789 if (g_object_class_find_property(G_OBJECT_GET_CLASS(
\r
790 G_OBJECT(gtk_settings_get_default())), "gtk-cursor-blink")) {
\r
791 g_object_get(G_OBJECT(
\r
792 gtk_settings_get_default()), "gtk-cursor-blink", &blinkOn, NULL);
\r
795 g_object_class_find_property(G_OBJECT_GET_CLASS(
\r
796 G_OBJECT(gtk_settings_get_default())), "gtk-cursor-blink-time")) {
\r
798 g_object_get(G_OBJECT(
\r
799 gtk_settings_get_default()), "gtk-cursor-blink-time", &value, NULL);
\r
800 caret.period = gint(value / 1.75);
\r
809 void ScintillaGTK::Finalise() {
\r
811 ScintillaBase::Finalise();
\r
814 void ScintillaGTK::DisplayCursor(Window::Cursor c) {
\r
815 if (cursorMode == SC_CURSORNORMAL)
\r
816 wText.SetCursor(c);
\r
818 wText.SetCursor(static_cast<Window::Cursor>(cursorMode));
\r
821 bool ScintillaGTK::DragThreshold(Point ptStart, Point ptNow) {
\r
822 #if GTK_MAJOR_VERSION < 2
\r
823 return Editor::DragThreshold(ptStart, ptNow);
\r
825 return gtk_drag_check_threshold(GTK_WIDGET(PWidget(wMain)),
\r
826 ptStart.x, ptStart.y, ptNow.x, ptNow.y);
\r
830 void ScintillaGTK::StartDrag() {
\r
831 dragWasDropped = false;
\r
832 inDragDrop = ddDragging;
\r
833 GtkTargetList *tl = gtk_target_list_new(clipboardCopyTargets, nClipboardCopyTargets);
\r
834 gtk_drag_begin(GTK_WIDGET(PWidget(wMain)),
\r
836 static_cast<GdkDragAction>(GDK_ACTION_COPY | GDK_ACTION_MOVE),
\r
838 reinterpret_cast<GdkEvent *>(&evbtn));
\r
841 #ifdef USE_CONVERTER
\r
842 static char *ConvertText(int *lenResult, char *s, size_t len, const char *charSetDest,
\r
843 const char *charSetSource, bool transliterations) {
\r
845 char *destForm = 0;
\r
846 Converter conv(charSetDest, charSetSource, transliterations);
\r
848 destForm = new char[len*3+1];
\r
850 size_t inLeft = len;
\r
851 char *pout = destForm;
\r
852 size_t outLeft = len*3+1;
\r
853 size_t conversions = conv.Convert(&pin, &inLeft, &pout, &outLeft);
\r
854 if (conversions == ((size_t)(-1))) {
\r
855 fprintf(stderr, "iconv %s->%s failed for %s\n", charSetSource, charSetDest, static_cast<char *>(s));
\r
859 //fprintf(stderr, "iconv OK %s %d\n", destForm, pout - destForm);
\r
861 *lenResult = pout - destForm;
\r
864 fprintf(stderr, "Can not iconv %s %s\n", charSetDest, charSetSource);
\r
867 destForm = new char[1];
\r
868 destForm[0] = '\0';
\r
875 // Returns the target converted to UTF8.
\r
876 // Return the length in bytes.
\r
877 int ScintillaGTK::TargetAsUTF8(char *text) {
\r
878 int targetLength = targetEnd - targetStart;
\r
879 if (IsUnicodeMode()) {
\r
881 pdoc->GetCharRange(text, targetStart, targetLength);
\r
885 #ifdef USE_CONVERTER
\r
886 const char *charSetBuffer = CharacterSetID();
\r
887 if (*charSetBuffer) {
\r
888 //~ fprintf(stderr, "AsUTF8 %s %d %0d-%0d\n", charSetBuffer, targetLength, targetStart, targetEnd);
\r
889 char *s = new char[targetLength];
\r
891 pdoc->GetCharRange(s, targetStart, targetLength);
\r
892 //~ fprintf(stderr, " \"%s\"\n", s);
\r
894 char *tmputf = ConvertText(&targetLength, s, targetLength, "UTF-8", charSetBuffer, false);
\r
895 memcpy(text, tmputf, targetLength);
\r
897 //~ fprintf(stderr, " \"%s\"\n", text);
\r
903 pdoc->GetCharRange(text, targetStart, targetLength);
\r
911 //~ fprintf(stderr, "Length = %d bytes\n", targetLength);
\r
912 return targetLength;
\r
915 // Translates a nul terminated UTF8 string into the document encoding.
\r
916 // Return the length of the result in bytes.
\r
917 int ScintillaGTK::EncodedFromUTF8(char *utf8, char *encoded) {
\r
918 int inputLength = (lengthForEncode >= 0) ? lengthForEncode : strlen(utf8);
\r
919 if (IsUnicodeMode()) {
\r
921 memcpy(encoded, utf8, inputLength);
\r
923 return inputLength;
\r
926 #ifdef USE_CONVERTER
\r
927 const char *charSetBuffer = CharacterSetID();
\r
928 if (*charSetBuffer) {
\r
929 //~ fprintf(stderr, "Encode %s %d\n", charSetBuffer, inputLength);
\r
931 char *tmpEncoded = ConvertText(&outLength, utf8, inputLength, charSetBuffer, "UTF-8", true);
\r
933 //~ fprintf(stderr, " \"%s\"\n", tmpEncoded);
\r
935 memcpy(encoded, tmpEncoded, outLength);
\r
937 delete []tmpEncoded;
\r
942 memcpy(encoded, utf8, inputLength);
\r
944 return inputLength;
\r
952 bool ScintillaGTK::ValidCodePage(int codePage) const {
\r
953 return codePage == 0 || codePage == SC_CP_UTF8 || codePage == SC_CP_DBCS;
\r
956 sptr_t ScintillaGTK::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
\r
957 switch (iMessage) {
\r
959 case SCI_GRABFOCUS:
\r
960 gtk_widget_grab_focus(PWidget(wMain));
\r
963 case SCI_GETDIRECTFUNCTION:
\r
964 return reinterpret_cast<sptr_t>(DirectFunction);
\r
966 case SCI_GETDIRECTPOINTER:
\r
967 return reinterpret_cast<sptr_t>(this);
\r
970 case SCI_LOADLEXERLIBRARY:
\r
971 LexerManager::GetInstance()->Load(reinterpret_cast<const char*>(wParam));
\r
974 case SCI_TARGETASUTF8:
\r
975 return TargetAsUTF8(reinterpret_cast<char*>(lParam));
\r
977 case SCI_ENCODEDFROMUTF8:
\r
978 return EncodedFromUTF8(reinterpret_cast<char*>(wParam),
\r
979 reinterpret_cast<char*>(lParam));
\r
982 return ScintillaBase::WndProc(iMessage, wParam, lParam);
\r
987 sptr_t ScintillaGTK::DefWndProc(unsigned int, uptr_t, sptr_t) {
\r
991 void ScintillaGTK::SetTicking(bool on) {
\r
992 if (timer.ticking != on) {
\r
993 timer.ticking = on;
\r
994 if (timer.ticking) {
\r
995 timer.tickerID = reinterpret_cast<TickerID>(gtk_timeout_add(timer.tickSize, (GtkFunction)TimeOut, this));
\r
997 gtk_timeout_remove(GPOINTER_TO_UINT(timer.tickerID));
\r
1000 timer.ticksToWait = caret.period;
\r
1003 bool ScintillaGTK::SetIdle(bool on) {
\r
1005 // Start idler, if it's not running.
\r
1006 if (idler.state == false) {
\r
1007 idler.state = true;
\r
1008 idler.idlerID = reinterpret_cast<IdlerID>
\r
1009 (gtk_idle_add((GtkFunction)IdleCallback, this));
\r
1012 // Stop idler, if it's running
\r
1013 if (idler.state == true) {
\r
1014 idler.state = false;
\r
1015 gtk_idle_remove(GPOINTER_TO_UINT(idler.idlerID));
\r
1021 void ScintillaGTK::SetMouseCapture(bool on) {
\r
1022 if (mouseDownCaptures) {
\r
1024 gtk_grab_add(GTK_WIDGET(PWidget(wMain)));
\r
1026 gtk_grab_remove(GTK_WIDGET(PWidget(wMain)));
\r
1029 capturedMouse = on;
\r
1032 bool ScintillaGTK::HaveMouseCapture() {
\r
1033 return capturedMouse;
\r
1036 bool ScintillaGTK::PaintContains(PRectangle rc) {
\r
1037 bool contains = true;
\r
1038 if (paintState == painting) {
\r
1039 if (!rcPaint.Contains(rc)) {
\r
1041 } else if (rgnUpdate) {
\r
1042 GdkRectangle grc = {rc.left, rc.top,
\r
1043 rc.right - rc.left, rc.bottom - rc.top};
\r
1044 if (gdk_region_rect_in(rgnUpdate, &grc) != GDK_OVERLAP_RECTANGLE_IN) {
\r
1052 // Redraw all of text area. This paint will not be abandoned.
\r
1053 void ScintillaGTK::FullPaint() {
\r
1054 #if GTK_MAJOR_VERSION < 2
\r
1055 paintState = painting;
\r
1056 rcPaint = GetClientRectangle();
\r
1057 //Platform::DebugPrintf("ScintillaGTK::FullPaint %0d,%0d %0d,%0d\n",
\r
1058 // rcPaint.left, rcPaint.top, rcPaint.right, rcPaint.bottom);
\r
1059 paintingAllText = true;
\r
1060 if ((PWidget(wText))->window) {
\r
1061 Surface *sw = Surface::Allocate();
\r
1063 sw->Init(PWidget(wText)->window, PWidget(wText));
\r
1064 Paint(sw, rcPaint);
\r
1069 paintState = notPainting;
\r
1071 wText.InvalidateAll();
\r
1075 PRectangle ScintillaGTK::GetClientRectangle() {
\r
1076 PRectangle rc = wMain.GetClientPosition();
\r
1077 if (verticalScrollBarVisible)
\r
1078 rc.right -= scrollBarWidth;
\r
1079 if (horizontalScrollBarVisible && (wrapState == eWrapNone))
\r
1080 rc.bottom -= scrollBarHeight;
\r
1082 rc.right -= rc.left;
\r
1083 rc.bottom -= rc.top;
\r
1089 // Synchronously paint a rectangle of the window.
\r
1090 void ScintillaGTK::SyncPaint(PRectangle rc) {
\r
1091 paintState = painting;
\r
1093 PRectangle rcClient = GetClientRectangle();
\r
1094 paintingAllText = rcPaint.Contains(rcClient);
\r
1095 if ((PWidget(wText))->window) {
\r
1096 Surface *sw = Surface::Allocate();
\r
1098 sw->Init(PWidget(wText)->window, PWidget(wText));
\r
1104 if (paintState == paintAbandoned) {
\r
1105 // Painting area was insufficient to cover new styling or brace highlight positions
\r
1108 paintState = notPainting;
\r
1111 void ScintillaGTK::ScrollText(int linesToMove) {
\r
1112 int diff = vs.lineHeight * -linesToMove;
\r
1113 //Platform::DebugPrintf("ScintillaGTK::ScrollText %d %d %0d,%0d %0d,%0d\n", linesToMove, diff,
\r
1114 // rc.left, rc.top, rc.right, rc.bottom);
\r
1115 GtkWidget *wi = PWidget(wText);
\r
1117 #if GTK_MAJOR_VERSION < 2
\r
1118 PRectangle rc = GetClientRectangle();
\r
1119 GdkGC *gc = gdk_gc_new(wi->window);
\r
1121 // Set up gc so we get GraphicsExposures from gdk_draw_pixmap
\r
1122 // which calls XCopyArea
\r
1123 gdk_gc_set_exposures(gc, TRUE);
\r
1125 // Redraw exposed bit : scrolling upwards
\r
1127 gdk_draw_pixmap(wi->window,
\r
1131 rc.Width()-1, rc.Height() - diff);
\r
1132 SyncPaint(PRectangle(0, rc.Height() - diff,
\r
1133 rc.Width(), rc.Height()+1));
\r
1135 // Redraw exposed bit : scrolling downwards
\r
1137 gdk_draw_pixmap(wi->window,
\r
1141 rc.Width()-1, rc.Height() + diff);
\r
1142 SyncPaint(PRectangle(0, 0, rc.Width(), -diff));
\r
1145 // Look for any graphics expose
\r
1147 while ((event = gdk_event_get_graphics_expose(wi->window)) != NULL) {
\r
1148 gtk_widget_event(wi, event);
\r
1149 if (event->expose.count == 0) {
\r
1150 gdk_event_free(event);
\r
1153 gdk_event_free(event);
\r
1158 gdk_window_scroll(wi->window, 0, -diff);
\r
1159 gdk_window_process_updates(wi->window, FALSE);
\r
1163 void ScintillaGTK::SetVerticalScrollPos() {
\r
1165 gtk_adjustment_set_value(GTK_ADJUSTMENT(adjustmentv), topLine);
\r
1168 void ScintillaGTK::SetHorizontalScrollPos() {
\r
1170 gtk_adjustment_set_value(GTK_ADJUSTMENT(adjustmenth), xOffset / 2);
\r
1173 bool ScintillaGTK::ModifyScrollBars(int nMax, int nPage) {
\r
1174 bool modified = false;
\r
1175 int pageScroll = LinesToScroll();
\r
1177 if (GTK_ADJUSTMENT(adjustmentv)->upper != (nMax + 1) ||
\r
1178 GTK_ADJUSTMENT(adjustmentv)->page_size != nPage ||
\r
1179 GTK_ADJUSTMENT(adjustmentv)->page_increment != pageScroll) {
\r
1180 GTK_ADJUSTMENT(adjustmentv)->upper = nMax + 1;
\r
1181 GTK_ADJUSTMENT(adjustmentv)->page_size = nPage;
\r
1182 GTK_ADJUSTMENT(adjustmentv)->page_increment = pageScroll;
\r
1183 gtk_adjustment_changed(GTK_ADJUSTMENT(adjustmentv));
\r
1187 PRectangle rcText = GetTextRectangle();
\r
1188 int horizEndPreferred = scrollWidth;
\r
1189 if (horizEndPreferred < 0)
\r
1190 horizEndPreferred = 0;
\r
1191 unsigned int pageWidth = rcText.Width();
\r
1192 unsigned int pageIncrement = pageWidth / 3;
\r
1193 unsigned int charWidth = vs.styles[STYLE_DEFAULT].aveCharWidth;
\r
1194 if (GTK_ADJUSTMENT(adjustmenth)->upper != horizEndPreferred ||
\r
1195 GTK_ADJUSTMENT(adjustmenth)->page_size != pageWidth ||
\r
1196 GTK_ADJUSTMENT(adjustmenth)->page_increment != pageIncrement ||
\r
1197 GTK_ADJUSTMENT(adjustmenth)->step_increment != charWidth) {
\r
1198 GTK_ADJUSTMENT(adjustmenth)->upper = horizEndPreferred;
\r
1199 GTK_ADJUSTMENT(adjustmenth)->step_increment = charWidth;
\r
1200 GTK_ADJUSTMENT(adjustmenth)->page_size = pageWidth;
\r
1201 GTK_ADJUSTMENT(adjustmenth)->page_increment = pageIncrement;
\r
1202 gtk_adjustment_changed(GTK_ADJUSTMENT(adjustmenth));
\r
1208 void ScintillaGTK::ReconfigureScrollBars() {
\r
1209 PRectangle rc = wMain.GetClientPosition();
\r
1210 Resize(rc.Width(), rc.Height());
\r
1213 void ScintillaGTK::NotifyChange() {
\r
1214 #if GLIB_MAJOR_VERSION < 2
\r
1215 gtk_signal_emit(GTK_OBJECT(sci), scintilla_signals[COMMAND_SIGNAL],
\r
1216 Platform::LongFromTwoShorts(GetCtrlID(), SCEN_CHANGE), PWidget(wMain));
\r
1218 g_signal_emit(G_OBJECT(sci), scintilla_signals[COMMAND_SIGNAL], 0,
\r
1219 Platform::LongFromTwoShorts(GetCtrlID(), SCEN_CHANGE), PWidget(wMain));
\r
1223 void ScintillaGTK::NotifyFocus(bool focus) {
\r
1224 #if GLIB_MAJOR_VERSION < 2
\r
1225 gtk_signal_emit(GTK_OBJECT(sci), scintilla_signals[COMMAND_SIGNAL],
\r
1226 Platform::LongFromTwoShorts
\r
1227 (GetCtrlID(), focus ? SCEN_SETFOCUS : SCEN_KILLFOCUS), PWidget(wMain));
\r
1229 g_signal_emit(G_OBJECT(sci), scintilla_signals[COMMAND_SIGNAL], 0,
\r
1230 Platform::LongFromTwoShorts
\r
1231 (GetCtrlID(), focus ? SCEN_SETFOCUS : SCEN_KILLFOCUS), PWidget(wMain));
\r
1235 void ScintillaGTK::NotifyParent(SCNotification scn) {
\r
1236 scn.nmhdr.hwndFrom = PWidget(wMain);
\r
1237 scn.nmhdr.idFrom = GetCtrlID();
\r
1238 #if GLIB_MAJOR_VERSION < 2
\r
1239 gtk_signal_emit(GTK_OBJECT(sci), scintilla_signals[NOTIFY_SIGNAL],
\r
1240 GetCtrlID(), &scn);
\r
1242 g_signal_emit(G_OBJECT(sci), scintilla_signals[NOTIFY_SIGNAL], 0,
\r
1243 GetCtrlID(), &scn);
\r
1247 void ScintillaGTK::NotifyKey(int key, int modifiers) {
\r
1248 SCNotification scn = {0};
\r
1249 scn.nmhdr.code = SCN_KEY;
\r
1251 scn.modifiers = modifiers;
\r
1253 NotifyParent(scn);
\r
1256 void ScintillaGTK::NotifyURIDropped(const char *list) {
\r
1257 SCNotification scn = {0};
\r
1258 scn.nmhdr.code = SCN_URIDROPPED;
\r
1261 NotifyParent(scn);
\r
1264 const char *CharacterSetID(int characterSet);
\r
1266 const char *ScintillaGTK::CharacterSetID() const {
\r
1267 return ::CharacterSetID(vs.styles[STYLE_DEFAULT].characterSet);
\r
1270 int ScintillaGTK::KeyDefault(int key, int modifiers) {
\r
1271 if (!(modifiers & SCI_CTRL) && !(modifiers & SCI_ALT)) {
\r
1273 NotifyKey(key, modifiers);
\r
1276 // Pass up to container in case it is an accelerator
\r
1277 NotifyKey(key, modifiers);
\r
1281 // Pass up to container in case it is an accelerator
\r
1282 NotifyKey(key, modifiers);
\r
1285 //Platform::DebugPrintf("SK-key: %d %x %x\n",key, modifiers);
\r
1288 void ScintillaGTK::CopyToClipboard(const SelectionText &selectedText) {
\r
1289 #ifndef USE_GTK_CLIPBOARD
\r
1290 copyText.Copy(selectedText);
\r
1291 gtk_selection_owner_set(GTK_WIDGET(PWidget(wMain)),
\r
1293 GDK_CURRENT_TIME);
\r
1295 SelectionText *clipText = new SelectionText();
\r
1296 clipText->Copy(selectedText);
\r
1297 StoreOnClipboard(clipText);
\r
1301 void ScintillaGTK::Copy() {
\r
1302 if (currentPos != anchor) {
\r
1303 #ifndef USE_GTK_CLIPBOARD
\r
1304 CopySelectionRange(©Text);
\r
1305 gtk_selection_owner_set(GTK_WIDGET(PWidget(wMain)),
\r
1307 GDK_CURRENT_TIME);
\r
1309 SelectionText *clipText = new SelectionText();
\r
1310 CopySelectionRange(clipText);
\r
1311 StoreOnClipboard(clipText);
\r
1313 #if PLAT_GTK_WIN32
\r
1314 if (selType == selRectangle) {
\r
1315 ::OpenClipboard(NULL);
\r
1316 ::SetClipboardData(cfColumnSelect, 0);
\r
1317 ::CloseClipboard();
\r
1323 void ScintillaGTK::Paste() {
\r
1324 atomSought = atomUTF8;
\r
1325 gtk_selection_convert(GTK_WIDGET(PWidget(wMain)),
\r
1326 atomClipboard, atomSought, GDK_CURRENT_TIME);
\r
1329 void ScintillaGTK::CreateCallTipWindow(PRectangle rc) {
\r
1330 if (!ct.wCallTip.Created()) {
\r
1331 ct.wCallTip = gtk_window_new(GTK_WINDOW_POPUP);
\r
1332 ct.wDraw = gtk_drawing_area_new();
\r
1333 GtkWidget *widcdrw = PWidget(ct.wDraw); // // No code inside the G_OBJECT macro
\r
1334 gtk_container_add(GTK_CONTAINER(PWidget(ct.wCallTip)), widcdrw);
\r
1335 #if GLIB_MAJOR_VERSION < 2
\r
1336 gtk_signal_connect(GTK_OBJECT(widcdrw), "expose_event",
\r
1337 GtkSignalFunc(ScintillaGTK::ExposeCT), &ct);
\r
1338 gtk_signal_connect(GTK_OBJECT(widcdrw), "button_press_event",
\r
1339 GtkSignalFunc(ScintillaGTK::PressCT), static_cast<void *>(this));
\r
1341 g_signal_connect(G_OBJECT(widcdrw), "expose_event",
\r
1342 G_CALLBACK(ScintillaGTK::ExposeCT), &ct);
\r
1343 g_signal_connect(G_OBJECT(widcdrw), "button_press_event",
\r
1344 G_CALLBACK(ScintillaGTK::PressCT), static_cast<void *>(this));
\r
1346 gtk_widget_set_events(widcdrw,
\r
1347 GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK);
\r
1349 gtk_drawing_area_size(GTK_DRAWING_AREA(PWidget(ct.wDraw)),
\r
1350 rc.Width(), rc.Height());
\r
1352 if (PWidget(ct.wCallTip)->window) {
\r
1353 gdk_window_resize(PWidget(ct.wCallTip)->window, rc.Width(), rc.Height());
\r
1357 void ScintillaGTK::AddToPopUp(const char *label, int cmd, bool enabled) {
\r
1358 char fulllabel[200];
\r
1359 strcpy(fulllabel, "/");
\r
1360 strcat(fulllabel, label);
\r
1361 GtkItemFactoryCallback menuSig = GtkItemFactoryCallback(PopUpCB);
\r
1362 GtkItemFactoryEntry itemEntry = {
\r
1366 const_cast<gchar *>(label[0] ? "<Item>" : "<Separator>"),
\r
1367 #if GTK_MAJOR_VERSION >= 2
\r
1371 gtk_item_factory_create_item(GTK_ITEM_FACTORY(popup.GetID()),
\r
1372 &itemEntry, this, 1);
\r
1374 GtkWidget *item = gtk_item_factory_get_widget_by_action(
\r
1375 reinterpret_cast<GtkItemFactory *>(popup.GetID()), cmd);
\r
1377 gtk_widget_set_sensitive(item, enabled);
\r
1381 bool ScintillaGTK::OwnPrimarySelection() {
\r
1382 return ((gdk_selection_owner_get(GDK_SELECTION_PRIMARY)
\r
1383 == GTK_WIDGET(PWidget(wMain))->window) &&
\r
1384 (GTK_WIDGET(PWidget(wMain))->window != NULL));
\r
1387 void ScintillaGTK::ClaimSelection() {
\r
1388 // X Windows has a 'primary selection' as well as the clipboard.
\r
1389 // Whenever the user selects some text, we become the primary selection
\r
1390 if (currentPos != anchor && GTK_WIDGET_REALIZED(GTK_WIDGET(PWidget(wMain)))) {
\r
1391 primarySelection = true;
\r
1392 gtk_selection_owner_set(GTK_WIDGET(PWidget(wMain)),
\r
1393 GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME);
\r
1395 } else if (OwnPrimarySelection()) {
\r
1396 primarySelection = true;
\r
1397 if (primary.s == NULL)
\r
1398 gtk_selection_owner_set(NULL, GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME);
\r
1400 primarySelection = false;
\r
1405 // Detect rectangular text, convert line ends to current mode, convert from or to UTF-8
\r
1406 void ScintillaGTK::GetGtkSelectionText(GtkSelectionData *selectionData, SelectionText &selText) {
\r
1407 char *data = reinterpret_cast<char *>(selectionData->data);
\r
1408 int len = selectionData->length;
\r
1409 GdkAtom selectionTypeData = selectionData->type;
\r
1411 // Return empty string if selection is not a string
\r
1412 if ((selectionTypeData != GDK_TARGET_STRING) && (selectionTypeData != atomUTF8)) {
\r
1413 char *empty = new char[1];
\r
1415 selText.Set(empty, 0, SC_CP_UTF8, 0, false, false);
\r
1419 // Check for "\n\0" ending to string indicating that selection is rectangular
\r
1420 bool isRectangular;
\r
1421 #if PLAT_GTK_WIN32
\r
1422 isRectangular = ::IsClipboardFormatAvailable(cfColumnSelect) != 0;
\r
1424 isRectangular = ((len > 2) && (data[len - 1] == 0 && data[len - 2] == '\n'));
\r
1428 if (selectionTypeData == GDK_TARGET_STRING) {
\r
1429 dest = Document::TransformLineEnds(&len, data, len, pdoc->eolMode);
\r
1430 if (IsUnicodeMode()) {
\r
1431 // Unknown encoding so assume in Latin1
\r
1432 char *destPrevious = dest;
\r
1433 dest = UTF8FromLatin1(dest, len);
\r
1434 selText.Set(dest, len, SC_CP_UTF8, 0, selText.rectangular, false);
\r
1435 delete []destPrevious;
\r
1437 // Assume buffer is in same encoding as selection
\r
1438 selText.Set(dest, len, pdoc->dbcsCodePage,
\r
1439 vs.styles[STYLE_DEFAULT].characterSet, isRectangular, false);
\r
1442 dest = Document::TransformLineEnds(&len, data, len, pdoc->eolMode);
\r
1443 selText.Set(dest, len, SC_CP_UTF8, 0, isRectangular, false);
\r
1444 #ifdef USE_CONVERTER
\r
1445 const char *charSetBuffer = CharacterSetID();
\r
1446 if (!IsUnicodeMode() && *charSetBuffer) {
\r
1447 //fprintf(stderr, "Convert to locale %s\n", CharacterSetID());
\r
1448 // Convert to locale
\r
1449 dest = ConvertText(&len, selText.s, selText.len, charSetBuffer, "UTF-8", true);
\r
1450 selText.Set(dest, len, pdoc->dbcsCodePage,
\r
1451 vs.styles[STYLE_DEFAULT].characterSet, selText.rectangular, false);
\r
1457 void ScintillaGTK::ReceivedSelection(GtkSelectionData *selection_data) {
\r
1458 if ((selection_data->selection == atomClipboard) ||
\r
1459 (selection_data->selection == GDK_SELECTION_PRIMARY)) {
\r
1460 if ((atomSought == atomUTF8) && (selection_data->length <= 0)) {
\r
1461 atomSought = atomString;
\r
1462 gtk_selection_convert(GTK_WIDGET(PWidget(wMain)),
\r
1463 selection_data->selection, atomSought, GDK_CURRENT_TIME);
\r
1464 } else if ((selection_data->length > 0) &&
\r
1465 ((selection_data->type == GDK_TARGET_STRING) || (selection_data->type == atomUTF8))) {
\r
1466 SelectionText selText;
\r
1467 GetGtkSelectionText(selection_data, selText);
\r
1469 pdoc->BeginUndoAction();
\r
1470 if (selection_data->selection != GDK_SELECTION_PRIMARY) {
\r
1473 int selStart = SelectionStart();
\r
1475 if (selText.rectangular) {
\r
1476 PasteRectangular(selStart, selText.s, selText.len);
\r
1478 pdoc->InsertString(currentPos, selText.s, selText.len);
\r
1479 SetEmptySelection(currentPos + selText.len);
\r
1481 pdoc->EndUndoAction();
\r
1482 EnsureCaretVisible();
\r
1485 // else fprintf(stderr, "Target non string %d %d\n", (int)(selection_data->type),
\r
1486 // (int)(atomUTF8));
\r
1490 void ScintillaGTK::ReceivedDrop(GtkSelectionData *selection_data) {
\r
1491 dragWasDropped = true;
\r
1492 if (selection_data->type == atomUriList || selection_data->type == atomDROPFILES_DND) {
\r
1493 char *ptr = new char[selection_data->length + 1];
\r
1494 ptr[selection_data->length] = '\0';
\r
1495 memcpy(ptr, selection_data->data, selection_data->length);
\r
1496 NotifyURIDropped(ptr);
\r
1498 } else if ((selection_data->type == GDK_TARGET_STRING) || (selection_data->type == atomUTF8)) {
\r
1499 if (selection_data->length > 0) {
\r
1500 SelectionText selText;
\r
1501 GetGtkSelectionText(selection_data, selText);
\r
1502 DropAt(posDrop, selText.s, false, selText.rectangular);
\r
1504 } else if (selection_data->length > 0) {
\r
1505 //~ fprintf(stderr, "ReceivedDrop other %p\n", static_cast<void *>(selection_data->type));
\r
1512 void ScintillaGTK::GetSelection(GtkSelectionData *selection_data, guint info, SelectionText *text) {
\r
1513 #if PLAT_GTK_WIN32
\r
1514 // GDK on Win32 expands any \n into \r\n, so make a copy of
\r
1515 // the clip text now with newlines converted to \n. Use { } to hide symbols
\r
1516 // from code below
\r
1517 SelectionText *newline_normalized = NULL;
\r
1520 char *tmpstr = Document::TransformLineEnds(&tmpstr_len, text->s, text->len, SC_EOL_LF);
\r
1521 newline_normalized = new SelectionText();
\r
1522 newline_normalized->Set(tmpstr, tmpstr_len, SC_CP_UTF8, 0, text->rectangular, false);
\r
1523 text = newline_normalized;
\r
1527 #if GTK_MAJOR_VERSION >= 2
\r
1528 // Convert text to utf8 if it isn't already
\r
1529 SelectionText *converted = 0;
\r
1530 if ((text->codePage != SC_CP_UTF8) && (info == TARGET_UTF8_STRING)) {
\r
1531 const char *charSet = ::CharacterSetID(text->characterSet);
\r
1534 char* tmputf = ConvertText(&new_len, text->s, text->len, "UTF-8", charSet, false);
\r
1535 converted = new SelectionText();
\r
1536 converted->Set(tmputf, new_len, SC_CP_UTF8, 0, text->rectangular, false);
\r
1541 // Here is a somewhat evil kludge.
\r
1542 // As I can not work out how to store data on the clipboard in multiple formats
\r
1543 // and need some way to mark the clipping as being stream or rectangular,
\r
1544 // the terminating \0 is included in the length for rectangular clippings.
\r
1545 // All other tested aplications behave benignly by ignoring the \0.
\r
1546 // The #if is here because on Windows cfColumnSelect clip entry is used
\r
1547 // instead as standard indicator of rectangularness (so no need to kludge)
\r
1548 int len = strlen(text->s);
\r
1549 #if PLAT_GTK_WIN32 == 0
\r
1550 if (text->rectangular)
\r
1554 if (info == TARGET_UTF8_STRING) {
\r
1555 gtk_selection_data_set_text(selection_data, text->s, len);
\r
1557 gtk_selection_data_set(selection_data,
\r
1558 static_cast<GdkAtom>(GDK_SELECTION_TYPE_STRING),
\r
1559 8, reinterpret_cast<unsigned char *>(text->s), len);
\r
1564 char *selBuffer = text->s;
\r
1567 if ((info == TARGET_UTF8_STRING) || (info == TARGET_STRING)) {
\r
1568 int len = strlen(selBuffer);
\r
1569 #ifdef USE_CONVERTER
\r
1570 // Possible character set conversion
\r
1571 const char *charSetBuffer = ::CharacterSetID(text->characterSet);
\r
1572 if (info == TARGET_UTF8_STRING) {
\r
1573 //fprintf(stderr, "Copy to clipboard as UTF-8\n");
\r
1574 if (text->codePage != SC_CP_UTF8) {
\r
1575 // Convert to UTF-8
\r
1576 //fprintf(stderr, "Convert to UTF-8 from %s\n", charSetBuffer);
\r
1577 tmputf = ConvertText(&len, selBuffer, len, "UTF-8", charSetBuffer, false);
\r
1578 selBuffer = tmputf;
\r
1580 } else if (info == TARGET_STRING) {
\r
1581 if (text->codePage == SC_CP_UTF8) {
\r
1582 //fprintf(stderr, "Convert to locale %s\n", charSetBuffer);
\r
1583 // Convert to locale
\r
1584 tmputf = ConvertText(&len, selBuffer, len, charSetBuffer, "UTF-8", true);
\r
1585 selBuffer = tmputf;
\r
1590 // Here is a somewhat evil kludge.
\r
1591 // As I can not work out how to store data on the clipboard in multiple formats
\r
1592 // and need some way to mark the clipping as being stream or rectangular,
\r
1593 // the terminating \0 is included in the length for rectangular clippings.
\r
1594 // All other tested aplications behave benignly by ignoring the \0.
\r
1595 // The #if is here because on Windows cfColumnSelect clip entry is used
\r
1596 // instead as standard indicator of rectangularness (so no need to kludge)
\r
1597 #if PLAT_GTK_WIN32 == 0
\r
1598 if (text->rectangular)
\r
1601 gtk_selection_data_set(selection_data,
\r
1602 (info == TARGET_STRING) ?
\r
1603 static_cast<GdkAtom>(GDK_SELECTION_TYPE_STRING) : atomUTF8,
\r
1604 8, reinterpret_cast<unsigned char *>(selBuffer),
\r
1606 } else if ((info == TARGET_TEXT) || (info == TARGET_COMPOUND_TEXT)) {
\r
1612 gdk_string_to_compound_text(reinterpret_cast<char *>(selBuffer),
\r
1613 &encoding, &format, &text, &new_length);
\r
1614 gtk_selection_data_set(selection_data, encoding, format, text, new_length);
\r
1615 gdk_free_compound_text(text);
\r
1619 #endif /* Gtk >= 2 */
\r
1621 #if PLAT_GTK_WIN32
\r
1622 delete newline_normalized;
\r
1626 #ifdef USE_GTK_CLIPBOARD
\r
1627 void ScintillaGTK::StoreOnClipboard(SelectionText *clipText) {
\r
1628 GtkClipboard *clipBoard =
\r
1629 gtk_widget_get_clipboard(GTK_WIDGET(PWidget(wMain)), atomClipboard);
\r
1630 if (clipBoard == NULL) // Occurs if widget isn't in a toplevel
\r
1633 if (gtk_clipboard_set_with_data(clipBoard, clipboardCopyTargets, nClipboardCopyTargets,
\r
1634 ClipboardGetSelection, ClipboardClearSelection, clipText)) {
\r
1635 gtk_clipboard_set_can_store(clipBoard, clipboardCopyTargets, nClipboardCopyTargets);
\r
1639 void ScintillaGTK::ClipboardGetSelection(GtkClipboard *, GtkSelectionData *selection_data, guint info, void *data) {
\r
1640 GetSelection(selection_data, info, static_cast<SelectionText*>(data));
\r
1643 void ScintillaGTK::ClipboardClearSelection(GtkClipboard *, void *data) {
\r
1644 SelectionText *obj = static_cast<SelectionText*>(data);
\r
1649 void ScintillaGTK::UnclaimSelection(GdkEventSelection *selection_event) {
\r
1650 //Platform::DebugPrintf("UnclaimSelection\n");
\r
1651 if (selection_event->selection == GDK_SELECTION_PRIMARY) {
\r
1652 //Platform::DebugPrintf("UnclaimPrimarySelection\n");
\r
1653 if (!OwnPrimarySelection()) {
\r
1655 primarySelection = false;
\r
1661 void ScintillaGTK::Resize(int width, int height) {
\r
1662 //Platform::DebugPrintf("Resize %d %d\n", width, height);
\r
1663 //printf("Resize %d %d\n", width, height);
\r
1665 // Not always needed, but some themes can have different sizes of scrollbars
\r
1666 scrollBarWidth = GTK_WIDGET(PWidget(scrollbarv))->requisition.width;
\r
1667 scrollBarHeight = GTK_WIDGET(PWidget(scrollbarh))->requisition.height;
\r
1669 // These allocations should never produce negative sizes as they would wrap around to huge
\r
1670 // unsigned numbers inside GTK+ causing warnings.
\r
1671 bool showSBHorizontal = horizontalScrollBarVisible && (wrapState == eWrapNone);
\r
1672 int horizontalScrollBarHeight = scrollBarHeight;
\r
1673 if (!showSBHorizontal)
\r
1674 horizontalScrollBarHeight = 0;
\r
1675 int verticalScrollBarHeight = scrollBarWidth;
\r
1676 if (!verticalScrollBarVisible)
\r
1677 verticalScrollBarHeight = 0;
\r
1679 GtkAllocation alloc;
\r
1680 if (showSBHorizontal) {
\r
1681 gtk_widget_show(GTK_WIDGET(PWidget(scrollbarh)));
\r
1683 alloc.y = height - scrollBarHeight;
\r
1684 alloc.width = Platform::Maximum(1, width - scrollBarWidth) + 1;
\r
1685 alloc.height = horizontalScrollBarHeight;
\r
1686 gtk_widget_size_allocate(GTK_WIDGET(PWidget(scrollbarh)), &alloc);
\r
1688 gtk_widget_hide(GTK_WIDGET(PWidget(scrollbarh)));
\r
1691 if (verticalScrollBarVisible) {
\r
1692 gtk_widget_show(GTK_WIDGET(PWidget(scrollbarv)));
\r
1693 alloc.x = width - scrollBarWidth;
\r
1695 alloc.width = scrollBarWidth;
\r
1696 alloc.height = Platform::Maximum(1, height - scrollBarHeight) + 1;
\r
1697 if (!showSBHorizontal)
\r
1698 alloc.height += scrollBarWidth-1;
\r
1699 gtk_widget_size_allocate(GTK_WIDGET(PWidget(scrollbarv)), &alloc);
\r
1701 gtk_widget_hide(GTK_WIDGET(PWidget(scrollbarv)));
\r
1703 if (GTK_WIDGET_MAPPED(PWidget(wMain))) {
\r
1709 alloc.width = Platform::Maximum(1, width - scrollBarWidth);
\r
1710 alloc.height = Platform::Maximum(1, height - scrollBarHeight);
\r
1711 if (!showSBHorizontal)
\r
1712 alloc.height += scrollBarHeight;
\r
1713 if (!verticalScrollBarVisible)
\r
1714 alloc.width += scrollBarWidth;
\r
1715 gtk_widget_size_allocate(GTK_WIDGET(PWidget(wText)), &alloc);
\r
1718 static void SetAdjustmentValue(GtkObject *object, int value) {
\r
1719 GtkAdjustment *adjustment = GTK_ADJUSTMENT(object);
\r
1720 int maxValue = static_cast<int>(
\r
1721 adjustment->upper - adjustment->page_size);
\r
1722 if (value > maxValue)
\r
1726 gtk_adjustment_set_value(adjustment, value);
\r
1729 gint ScintillaGTK::PressThis(GdkEventButton *event) {
\r
1730 //Platform::DebugPrintf("Press %x time=%d state = %x button = %x\n",this,event->time, event->state, event->button);
\r
1731 // Do not use GTK+ double click events as Scintilla has its own double click detection
\r
1732 if (event->type != GDK_BUTTON_PRESS)
\r
1737 pt.x = int(event->x);
\r
1738 pt.y = int(event->y);
\r
1739 PRectangle rcClient = GetClientRectangle();
\r
1740 //Platform::DebugPrintf("Press %0d,%0d in %0d,%0d %0d,%0d\n",
\r
1741 // pt.x, pt.y, rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
\r
1742 if ((pt.x > rcClient.right) || (pt.y > rcClient.bottom)) {
\r
1743 Platform::DebugPrintf("Bad location\n");
\r
1747 bool ctrl = (event->state & GDK_CONTROL_MASK) != 0;
\r
1749 gtk_widget_grab_focus(PWidget(wMain));
\r
1750 if (event->button == 1) {
\r
1751 // On X, instead of sending literal modifiers use control instead of alt
\r
1752 // This is because most X window managers grab alt + click for moving
\r
1753 #if !PLAT_GTK_WIN32
\r
1754 ButtonDown(pt, event->time,
\r
1755 (event->state & GDK_SHIFT_MASK) != 0,
\r
1756 (event->state & GDK_CONTROL_MASK) != 0,
\r
1757 (event->state & GDK_CONTROL_MASK) != 0);
\r
1759 ButtonDown(pt, event->time,
\r
1760 (event->state & GDK_SHIFT_MASK) != 0,
\r
1761 (event->state & GDK_CONTROL_MASK) != 0,
\r
1762 (event->state & GDK_MOD1_MASK) != 0);
\r
1764 } else if (event->button == 2) {
\r
1765 // Grab the primary selection if it exists
\r
1766 Position pos = PositionFromLocation(pt);
\r
1767 if (OwnPrimarySelection() && primary.s == NULL)
\r
1768 CopySelectionRange(&primary);
\r
1770 SetSelection(pos, pos);
\r
1771 atomSought = atomUTF8;
\r
1772 gtk_selection_convert(GTK_WIDGET(PWidget(wMain)), GDK_SELECTION_PRIMARY,
\r
1773 atomSought, event->time);
\r
1774 } else if (event->button == 3) {
\r
1775 if (displayPopupMenu) {
\r
1777 // Convert to screen
\r
1780 gdk_window_get_origin(PWidget(wMain)->window, &ox, &oy);
\r
1781 ContextMenu(Point(pt.x + ox, pt.y + oy));
\r
1785 } else if (event->button == 4) {
\r
1786 // Wheel scrolling up (only GTK 1.x does it this way)
\r
1788 SetAdjustmentValue(adjustmenth, (xOffset / 2) - 6);
\r
1790 SetAdjustmentValue(adjustmentv, topLine - 3);
\r
1791 } else if (event->button == 5) {
\r
1792 // Wheel scrolling down (only GTK 1.x does it this way)
\r
1794 SetAdjustmentValue(adjustmenth, (xOffset / 2) + 6);
\r
1796 SetAdjustmentValue(adjustmentv, topLine + 3);
\r
1798 #if GTK_MAJOR_VERSION >= 2
\r
1805 gint ScintillaGTK::Press(GtkWidget *widget, GdkEventButton *event) {
\r
1806 if (event->window != widget->window)
\r
1808 ScintillaGTK *sciThis = ScintillaFromWidget(widget);
\r
1809 return sciThis->PressThis(event);
\r
1812 gint ScintillaGTK::MouseRelease(GtkWidget *widget, GdkEventButton *event) {
\r
1813 ScintillaGTK *sciThis = ScintillaFromWidget(widget);
\r
1814 //Platform::DebugPrintf("Release %x %d %d\n",sciThis,event->time,event->state);
\r
1815 if (!sciThis->HaveMouseCapture())
\r
1817 if (event->button == 1) {
\r
1819 pt.x = int(event->x);
\r
1820 pt.y = int(event->y);
\r
1821 //Platform::DebugPrintf("Up %x %x %d %d %d\n",
\r
1822 // sciThis,event->window,event->time, pt.x, pt.y);
\r
1823 if (event->window != PWidget(sciThis->wMain)->window)
\r
1824 // If mouse released on scroll bar then the position is relative to the
\r
1825 // scrollbar, not the drawing window so just repeat the most recent point.
\r
1826 pt = sciThis->ptMouseLast;
\r
1827 sciThis->ButtonUp(pt, event->time, (event->state & 4) != 0);
\r
1832 // win32gtk and GTK >= 2 use SCROLL_* events instead of passing the
\r
1833 // button4/5/6/7 events to the GTK app
\r
1834 #if PLAT_GTK_WIN32 || (GTK_MAJOR_VERSION >= 2)
\r
1835 gint ScintillaGTK::ScrollEvent(GtkWidget *widget,
\r
1836 GdkEventScroll *event) {
\r
1837 ScintillaGTK *sciThis = ScintillaFromWidget(widget);
\r
1839 if (widget == NULL || event == NULL)
\r
1842 // Compute amount and direction to scroll (even tho on win32 there is
\r
1843 // intensity of scrolling info in the native message, gtk doesn't
\r
1844 // support this so we simulate similarly adaptive scrolling)
\r
1845 // Note that this is disabled on OS X (Darwin) where the X11 server already has
\r
1846 // and adaptive scrolling algorithm that fights with this one
\r
1848 #if defined(__MWERKS__) || defined(__APPLE_CPP__) || defined(__APPLE_CC__)
\r
1849 cLineScroll = sciThis->linesPerScroll;
\r
1850 if (cLineScroll == 0)
\r
1852 sciThis->wheelMouseIntensity = cLineScroll;
\r
1854 int timeDelta = 1000000;
\r
1856 g_get_current_time(&curTime);
\r
1857 if (curTime.tv_sec == sciThis->lastWheelMouseTime.tv_sec)
\r
1858 timeDelta = curTime.tv_usec - sciThis->lastWheelMouseTime.tv_usec;
\r
1859 else if (curTime.tv_sec == sciThis->lastWheelMouseTime.tv_sec + 1)
\r
1860 timeDelta = 1000000 + (curTime.tv_usec - sciThis->lastWheelMouseTime.tv_usec);
\r
1861 if ((event->direction == sciThis->lastWheelMouseDirection) && (timeDelta < 250000)) {
\r
1862 if (sciThis->wheelMouseIntensity < 12)
\r
1863 sciThis->wheelMouseIntensity++;
\r
1864 cLineScroll = sciThis->wheelMouseIntensity;
\r
1866 cLineScroll = sciThis->linesPerScroll;
\r
1867 if (cLineScroll == 0)
\r
1869 sciThis->wheelMouseIntensity = cLineScroll;
\r
1872 if (event->direction == GDK_SCROLL_UP || event->direction == GDK_SCROLL_LEFT) {
\r
1873 cLineScroll *= -1;
\r
1875 g_get_current_time(&sciThis->lastWheelMouseTime);
\r
1876 sciThis->lastWheelMouseDirection = event->direction;
\r
1878 // Note: Unpatched versions of win32gtk don't set the 'state' value so
\r
1879 // only regular scrolling is supported there. Also, unpatched win32gtk
\r
1880 // issues spurious button 2 mouse events during wheeling, which can cause
\r
1881 // problems (a patch for both was submitted by archaeopteryx.com on 13Jun2001)
\r
1883 // Data zoom not supported
\r
1884 if (event->state & GDK_SHIFT_MASK) {
\r
1888 // Horizontal scrolling
\r
1889 if (event->direction == GDK_SCROLL_LEFT || event->direction == GDK_SCROLL_RIGHT) {
\r
1890 sciThis->HorizontalScrollTo(sciThis->xOffset + cLineScroll);
\r
1892 // Text font size zoom
\r
1893 } else if (event->state & GDK_CONTROL_MASK) {
\r
1894 if (cLineScroll < 0) {
\r
1895 sciThis->KeyCommand(SCI_ZOOMIN);
\r
1897 sciThis->KeyCommand(SCI_ZOOMOUT);
\r
1900 // Regular scrolling
\r
1902 sciThis->ScrollTo(sciThis->topLine + cLineScroll);
\r
1908 gint ScintillaGTK::Motion(GtkWidget *widget, GdkEventMotion *event) {
\r
1909 ScintillaGTK *sciThis = ScintillaFromWidget(widget);
\r
1910 //Platform::DebugPrintf("Motion %x %d\n",sciThis,event->time);
\r
1911 if (event->window != widget->window)
\r
1915 GdkModifierType state;
\r
1916 if (event->is_hint) {
\r
1917 gdk_window_get_pointer(event->window, &x, &y, &state);
\r
1919 x = static_cast<int>(event->x);
\r
1920 y = static_cast<int>(event->y);
\r
1921 state = static_cast<GdkModifierType>(event->state);
\r
1923 //Platform::DebugPrintf("Move %x %x %d %c %d %d\n",
\r
1924 // sciThis,event->window,event->time,event->is_hint? 'h' :'.', x, y);
\r
1926 sciThis->ButtonMove(pt);
\r
1930 // Map the keypad keys to their equivalent functions
\r
1931 static int KeyTranslate(int keyIn) {
\r
1933 case GDK_ISO_Left_Tab:
\r
1941 case GDK_KP_Right:
\r
1947 case GDK_KP_Page_Up:
\r
1949 case GDK_KP_Page_Down:
\r
1951 case GDK_KP_Delete:
\r
1952 return SCK_DELETE;
\r
1953 case GDK_KP_Insert:
\r
1954 return SCK_INSERT;
\r
1955 case GDK_KP_Enter:
\r
1956 return SCK_RETURN;
\r
1972 case GDK_Page_Down:
\r
1975 return SCK_DELETE;
\r
1977 return SCK_INSERT;
\r
1979 return SCK_ESCAPE;
\r
1980 case GDK_BackSpace:
\r
1985 return SCK_RETURN;
\r
1988 case GDK_KP_Subtract:
\r
1989 return SCK_SUBTRACT;
\r
1990 case GDK_KP_Divide:
\r
1991 return SCK_DIVIDE;
\r
2003 gboolean ScintillaGTK::KeyThis(GdkEventKey *event) {
\r
2004 //fprintf(stderr, "SC-key: %d %x [%s]\n",
\r
2005 // event->keyval, event->state, (event->length > 0) ? event->string : "empty");
\r
2006 #if GTK_MAJOR_VERSION >= 2
\r
2007 if (gtk_im_context_filter_keypress(im_context, event)) {
\r
2011 if (!event->keyval) {
\r
2015 bool shift = (event->state & GDK_SHIFT_MASK) != 0;
\r
2016 bool ctrl = (event->state & GDK_CONTROL_MASK) != 0;
\r
2017 bool alt = (event->state & GDK_MOD1_MASK) != 0;
\r
2018 guint key = event->keyval;
\r
2019 if (ctrl && (key < 128))
\r
2020 key = toupper(key);
\r
2021 else if (!ctrl && (key >= GDK_KP_Multiply && key <= GDK_KP_9))
\r
2023 // Hack for keys over 256 and below command keys but makes Hungarian work.
\r
2024 // This will have to change for Unicode
\r
2025 else if (key >= 0xFE00)
\r
2026 key = KeyTranslate(key);
\r
2027 #if GTK_MAJOR_VERSION < 2
\r
2028 else if (!IsUnicodeMode() && (key >= 0x100) && (key < 0x1000))
\r
2032 bool consumed = false;
\r
2033 bool added = KeyDown(key, shift, ctrl, alt, &consumed) != 0;
\r
2036 //fprintf(stderr, "SK-key: %d %x %x\n",event->keyval, event->state, consumed);
\r
2037 if (event->keyval == 0xffffff && event->length > 0) {
\r
2039 if (pdoc->InsertCString(CurrentPosition(), event->string)) {
\r
2040 MovePositionTo(CurrentPosition() + event->length);
\r
2046 gboolean ScintillaGTK::KeyPress(GtkWidget *widget, GdkEventKey *event) {
\r
2047 ScintillaGTK *sciThis = ScintillaFromWidget(widget);
\r
2048 return sciThis->KeyThis(event);
\r
2051 gboolean ScintillaGTK::KeyRelease(GtkWidget *, GdkEventKey * /*event*/) {
\r
2052 //Platform::DebugPrintf("SC-keyrel: %d %x %3s\n",event->keyval, event->state, event->string);
\r
2056 #if GTK_MAJOR_VERSION >= 2
\r
2057 gboolean ScintillaGTK::ExposePreedit(GtkWidget *widget, GdkEventExpose *ose, ScintillaGTK *sciThis) {
\r
2058 return sciThis->ExposePreeditThis(widget, ose);
\r
2061 gboolean ScintillaGTK::ExposePreeditThis(GtkWidget *widget, GdkEventExpose *ose) {
\r
2064 PangoAttrList *attrs;
\r
2066 gtk_im_context_get_preedit_string(im_context, &str, &attrs, &cursor_pos);
\r
2067 PangoLayout *layout = gtk_widget_create_pango_layout(PWidget(wText), str);
\r
2068 pango_layout_set_attributes(layout, attrs);
\r
2070 GdkGC *gc = gdk_gc_new(widget->window);
\r
2071 GdkColor color[2] = { {0, 0x0000, 0x0000, 0x0000},
\r
2072 {0, 0xffff, 0xffff, 0xffff}};
\r
2073 gdk_color_alloc(gdk_colormap_get_system(), color);
\r
2074 gdk_color_alloc(gdk_colormap_get_system(), color + 1);
\r
2076 gdk_gc_set_foreground(gc, color + 1);
\r
2077 gdk_draw_rectangle(widget->window, gc, TRUE, ose->area.x, ose->area.y,
\r
2078 ose->area.width, ose->area.height);
\r
2080 gdk_gc_set_foreground(gc, color);
\r
2081 gdk_gc_set_background(gc, color + 1);
\r
2082 gdk_draw_layout(widget->window, gc, 0, 0, layout);
\r
2086 pango_attr_list_unref(attrs);
\r
2087 g_object_unref(layout);
\r
2091 void ScintillaGTK::Commit(GtkIMContext *, char *str, ScintillaGTK *sciThis) {
\r
2092 sciThis->CommitThis(str);
\r
2095 void ScintillaGTK::CommitThis(char *utfVal) {
\r
2096 //~ fprintf(stderr, "Commit '%s'\n", utfVal);
\r
2097 if (IsUnicodeMode()) {
\r
2098 AddCharUTF(utfVal,strlen(utfVal));
\r
2100 const char *source = CharacterSetID();
\r
2102 Converter conv(source, "UTF-8", true);
\r
2104 char localeVal[4]="\0\0\0";
\r
2105 char *pin = utfVal;
\r
2106 size_t inLeft = strlen(utfVal);
\r
2107 char *pout = localeVal;
\r
2108 size_t outLeft = sizeof(localeVal);
\r
2109 size_t conversions = conv.Convert(&pin, &inLeft, &pout, &outLeft);
\r
2110 if (conversions != ((size_t)(-1))) {
\r
2112 for (int i=0; localeVal[i]; i++) {
\r
2113 AddChar(localeVal[i]);
\r
2116 fprintf(stderr, "Conversion failed '%s'\n", utfVal);
\r
2123 void ScintillaGTK::PreeditChanged(GtkIMContext *, ScintillaGTK *sciThis) {
\r
2124 sciThis->PreeditChangedThis();
\r
2127 void ScintillaGTK::PreeditChangedThis() {
\r
2129 PangoAttrList *attrs;
\r
2131 gtk_im_context_get_preedit_string(im_context, &str, &attrs, &cursor_pos);
\r
2132 if (strlen(str) > 0){
\r
2133 PangoLayout *layout = gtk_widget_create_pango_layout(PWidget(wText), str);
\r
2134 pango_layout_set_attributes(layout, attrs);
\r
2137 pango_layout_get_pixel_size(layout, &w, &h);
\r
2138 g_object_unref(layout);
\r
2141 gdk_window_get_origin((PWidget(wText))->window, &x, &y);
\r
2143 Point pt = LocationFromPosition(currentPos);
\r
2149 gtk_window_move(GTK_WINDOW(PWidget(wPreedit)), x+pt.x, y+pt.y);
\r
2150 gtk_window_resize(GTK_WINDOW(PWidget(wPreedit)), w, h);
\r
2151 gtk_widget_show(PWidget(wPreedit));
\r
2152 gtk_widget_queue_draw_area(PWidget(wPreeditDraw), 0, 0, w, h);
\r
2154 gtk_widget_hide(PWidget(wPreedit));
\r
2157 pango_attr_list_unref(attrs);
\r
2161 gint ScintillaGTK::StyleSetText(GtkWidget *widget, GtkStyle *, void*) {
\r
2162 if (widget->window != NULL)
\r
2163 gdk_window_set_back_pixmap(widget->window, NULL, FALSE);
\r
2167 gint ScintillaGTK::RealizeText(GtkWidget *widget, void*) {
\r
2168 if (widget->window != NULL)
\r
2169 gdk_window_set_back_pixmap(widget->window, NULL, FALSE);
\r
2173 #if GLIB_MAJOR_VERSION < 2
\r
2174 void ScintillaGTK::Destroy(GtkObject *object)
\r
2176 void ScintillaGTK::Destroy(GObject *object)
\r
2179 ScintillaObject *scio = reinterpret_cast<ScintillaObject *>(object);
\r
2180 // This avoids a double destruction
\r
2183 ScintillaGTK *sciThis = reinterpret_cast<ScintillaGTK *>(scio->pscin);
\r
2184 //Platform::DebugPrintf("Destroying %x %x\n", sciThis, object);
\r
2185 sciThis->Finalise();
\r
2187 #if GLIB_MAJOR_VERSION < 2
\r
2188 if (GTK_OBJECT_CLASS(parent_class)->destroy)
\r
2189 (* GTK_OBJECT_CLASS(parent_class)->destroy)(object);
\r
2191 // IS ANYTHING NEEDED ?
\r
2198 static void DrawChild(GtkWidget *widget, GdkRectangle *area) {
\r
2199 GdkRectangle areaIntersect;
\r
2201 GTK_WIDGET_DRAWABLE(widget) &&
\r
2202 gtk_widget_intersect(widget, area, &areaIntersect)) {
\r
2203 gtk_widget_draw(widget, &areaIntersect);
\r
2207 void ScintillaGTK::Draw(GtkWidget *widget, GdkRectangle *area) {
\r
2208 ScintillaGTK *sciThis = ScintillaFromWidget(widget);
\r
2209 //Platform::DebugPrintf("Draw %p %0d,%0d %0d,%0d\n", widget, area->x, area->y, area->width, area->height);
\r
2210 PRectangle rcPaint(area->x, area->y, area->x + area->width, area->y + area->height);
\r
2211 sciThis->SyncPaint(rcPaint);
\r
2212 if (GTK_WIDGET_DRAWABLE(PWidget(sciThis->wMain))) {
\r
2213 DrawChild(PWidget(sciThis->scrollbarh), area);
\r
2214 DrawChild(PWidget(sciThis->scrollbarv), area);
\r
2217 #ifdef INTERNATIONAL_INPUT
\r
2218 Point pt = sciThis->LocationFromPosition(sciThis->currentPos);
\r
2219 pt.y += sciThis->vs.lineHeight - 2;
\r
2220 if (pt.x < 0) pt.x = 0;
\r
2221 if (pt.y < 0) pt.y = 0;
\r
2222 CursorMoved(widget, pt.x, pt.y, sciThis);
\r
2226 gint ScintillaGTK::ExposeTextThis(GtkWidget * /*widget*/, GdkEventExpose *ose) {
\r
2227 paintState = painting;
\r
2229 rcPaint.left = ose->area.x;
\r
2230 rcPaint.top = ose->area.y;
\r
2231 rcPaint.right = ose->area.x + ose->area.width;
\r
2232 rcPaint.bottom = ose->area.y + ose->area.height;
\r
2234 PLATFORM_ASSERT(rgnUpdate == NULL);
\r
2235 #if GTK_MAJOR_VERSION >= 2
\r
2236 rgnUpdate = gdk_region_copy(ose->region);
\r
2238 PRectangle rcClient = GetClientRectangle();
\r
2239 paintingAllText = rcPaint.Contains(rcClient);
\r
2240 Surface *surfaceWindow = Surface::Allocate();
\r
2241 if (surfaceWindow) {
\r
2242 surfaceWindow->Init(PWidget(wText)->window, PWidget(wText));
\r
2243 Paint(surfaceWindow, rcPaint);
\r
2244 surfaceWindow->Release();
\r
2245 delete surfaceWindow;
\r
2247 if (paintState == paintAbandoned) {
\r
2248 // Painting area was insufficient to cover new styling or brace highlight positions
\r
2251 paintState = notPainting;
\r
2254 gdk_region_destroy(rgnUpdate);
\r
2261 gint ScintillaGTK::ExposeText(GtkWidget *widget, GdkEventExpose *ose, ScintillaGTK *sciThis) {
\r
2262 return sciThis->ExposeTextThis(widget, ose);
\r
2265 gint ScintillaGTK::ExposeMain(GtkWidget *widget, GdkEventExpose *ose) {
\r
2266 ScintillaGTK *sciThis = ScintillaFromWidget(widget);
\r
2267 //Platform::DebugPrintf("Expose Main %0d,%0d %0d,%0d\n",
\r
2268 //ose->area.x, ose->area.y, ose->area.width, ose->area.height);
\r
2269 return sciThis->Expose(widget, ose);
\r
2272 gint ScintillaGTK::Expose(GtkWidget *, GdkEventExpose *ose) {
\r
2273 //fprintf(stderr, "Expose %0d,%0d %0d,%0d\n",
\r
2274 //ose->area.x, ose->area.y, ose->area.width, ose->area.height);
\r
2276 #if GTK_MAJOR_VERSION < 2
\r
2278 paintState = painting;
\r
2280 rcPaint.left = ose->area.x;
\r
2281 rcPaint.top = ose->area.y;
\r
2282 rcPaint.right = ose->area.x + ose->area.width;
\r
2283 rcPaint.bottom = ose->area.y + ose->area.height;
\r
2285 PRectangle rcClient = GetClientRectangle();
\r
2286 paintingAllText = rcPaint.Contains(rcClient);
\r
2287 Surface *surfaceWindow = Surface::Allocate();
\r
2288 if (surfaceWindow) {
\r
2289 surfaceWindow->Init(PWidget(wMain)->window, PWidget(wMain));
\r
2291 // Fill the corner between the scrollbars
\r
2292 if (verticalScrollBarVisible) {
\r
2293 if (horizontalScrollBarVisible && (wrapState == eWrapNone)) {
\r
2294 PRectangle rcCorner = wMain.GetClientPosition();
\r
2295 rcCorner.left = rcCorner.right - scrollBarWidth + 1;
\r
2296 rcCorner.top = rcCorner.bottom - scrollBarHeight + 1;
\r
2297 //fprintf(stderr, "Corner %0d,%0d %0d,%0d\n",
\r
2298 //rcCorner.left, rcCorner.top, rcCorner.right, rcCorner.bottom);
\r
2299 surfaceWindow->FillRectangle(rcCorner,
\r
2300 vs.styles[STYLE_LINENUMBER].back.allocated);
\r
2304 //Paint(surfaceWindow, rcPaint);
\r
2305 surfaceWindow->Release();
\r
2306 delete surfaceWindow;
\r
2308 if (paintState == paintAbandoned) {
\r
2309 // Painting area was insufficient to cover new styling or brace highlight positions
\r
2312 paintState = notPainting;
\r
2315 // For GTK+ 2, the text is painted in ExposeText
\r
2316 gtk_container_propagate_expose(
\r
2317 GTK_CONTAINER(PWidget(wMain)), PWidget(scrollbarh), ose);
\r
2318 gtk_container_propagate_expose(
\r
2319 GTK_CONTAINER(PWidget(wMain)), PWidget(scrollbarv), ose);
\r
2325 void ScintillaGTK::ScrollSignal(GtkAdjustment *adj, ScintillaGTK *sciThis) {
\r
2326 sciThis->ScrollTo(static_cast<int>(adj->value), false);
\r
2329 void ScintillaGTK::ScrollHSignal(GtkAdjustment *adj, ScintillaGTK *sciThis) {
\r
2330 sciThis->HorizontalScrollTo(static_cast<int>(adj->value * 2));
\r
2333 void ScintillaGTK::SelectionReceived(GtkWidget *widget,
\r
2334 GtkSelectionData *selection_data, guint) {
\r
2335 ScintillaGTK *sciThis = ScintillaFromWidget(widget);
\r
2336 //Platform::DebugPrintf("Selection received\n");
\r
2337 sciThis->ReceivedSelection(selection_data);
\r
2340 void ScintillaGTK::SelectionGet(GtkWidget *widget,
\r
2341 GtkSelectionData *selection_data, guint info, guint) {
\r
2342 ScintillaGTK *sciThis = ScintillaFromWidget(widget);
\r
2343 //Platform::DebugPrintf("Selection get\n");
\r
2344 if (selection_data->selection == GDK_SELECTION_PRIMARY) {
\r
2345 if (sciThis->primary.s == NULL) {
\r
2346 sciThis->CopySelectionRange(&sciThis->primary);
\r
2348 sciThis->GetSelection(selection_data, info, &sciThis->primary);
\r
2350 #ifndef USE_GTK_CLIPBOARD
\r
2352 sciThis->GetSelection(selection_data, info, &sciThis->copyText);
\r
2357 gint ScintillaGTK::SelectionClear(GtkWidget *widget, GdkEventSelection *selection_event) {
\r
2358 ScintillaGTK *sciThis = ScintillaFromWidget(widget);
\r
2359 //Platform::DebugPrintf("Selection clear\n");
\r
2360 sciThis->UnclaimSelection(selection_event);
\r
2361 return gtk_selection_clear(widget, selection_event);
\r
2364 #if GTK_MAJOR_VERSION < 2
\r
2365 gint ScintillaGTK::SelectionNotify(GtkWidget *widget, GdkEventSelection *selection_event) {
\r
2366 //Platform::DebugPrintf("Selection notify\n");
\r
2367 return gtk_selection_notify(widget, selection_event);
\r
2371 void ScintillaGTK::DragBegin(GtkWidget *, GdkDragContext *) {
\r
2372 //Platform::DebugPrintf("DragBegin\n");
\r
2375 gboolean ScintillaGTK::DragMotionThis(GdkDragContext *context,
\r
2376 gint x, gint y, guint dragtime) {
\r
2378 SetDragPosition(PositionFromLocation(npt));
\r
2379 GdkDragAction preferredAction = context->suggested_action;
\r
2380 int pos = PositionFromLocation(npt);
\r
2381 if ((inDragDrop == ddDragging) && (0 == PositionInSelection(pos))) {
\r
2382 // Avoid dragging selection onto itself as that produces a move
\r
2383 // with no real effect but which creates undo actions.
\r
2384 preferredAction = static_cast<GdkDragAction>(0);
\r
2385 } else if (context->actions == static_cast<GdkDragAction>
\r
2386 (GDK_ACTION_COPY | GDK_ACTION_MOVE)) {
\r
2387 preferredAction = GDK_ACTION_MOVE;
\r
2389 gdk_drag_status(context, preferredAction, dragtime);
\r
2393 gboolean ScintillaGTK::DragMotion(GtkWidget *widget, GdkDragContext *context,
\r
2394 gint x, gint y, guint dragtime) {
\r
2395 ScintillaGTK *sciThis = ScintillaFromWidget(widget);
\r
2396 return sciThis->DragMotionThis(context, x, y, dragtime);
\r
2399 void ScintillaGTK::DragLeave(GtkWidget *widget, GdkDragContext * /*context*/, guint) {
\r
2400 ScintillaGTK *sciThis = ScintillaFromWidget(widget);
\r
2401 sciThis->SetDragPosition(invalidPosition);
\r
2402 //Platform::DebugPrintf("DragLeave %x\n", sciThis);
\r
2405 void ScintillaGTK::DragEnd(GtkWidget *widget, GdkDragContext * /*context*/) {
\r
2406 ScintillaGTK *sciThis = ScintillaFromWidget(widget);
\r
2407 // If drag did not result in drop here or elsewhere
\r
2408 if (!sciThis->dragWasDropped)
\r
2409 sciThis->SetEmptySelection(sciThis->posDrag);
\r
2410 sciThis->SetDragPosition(invalidPosition);
\r
2411 //Platform::DebugPrintf("DragEnd %x %d\n", sciThis, sciThis->dragWasDropped);
\r
2412 sciThis->inDragDrop = ddNone;
\r
2415 gboolean ScintillaGTK::Drop(GtkWidget *widget, GdkDragContext * /*context*/,
\r
2416 gint, gint, guint) {
\r
2417 ScintillaGTK *sciThis = ScintillaFromWidget(widget);
\r
2418 //Platform::DebugPrintf("Drop %x\n", sciThis);
\r
2419 sciThis->SetDragPosition(invalidPosition);
\r
2423 void ScintillaGTK::DragDataReceived(GtkWidget *widget, GdkDragContext * /*context*/,
\r
2424 gint, gint, GtkSelectionData *selection_data, guint /*info*/, guint) {
\r
2425 ScintillaGTK *sciThis = ScintillaFromWidget(widget);
\r
2426 sciThis->ReceivedDrop(selection_data);
\r
2427 sciThis->SetDragPosition(invalidPosition);
\r
2430 void ScintillaGTK::DragDataGet(GtkWidget *widget, GdkDragContext *context,
\r
2431 GtkSelectionData *selection_data, guint info, guint) {
\r
2432 ScintillaGTK *sciThis = ScintillaFromWidget(widget);
\r
2433 sciThis->dragWasDropped = true;
\r
2434 if (sciThis->currentPos != sciThis->anchor) {
\r
2435 sciThis->GetSelection(selection_data, info, &sciThis->drag);
\r
2437 if (context->action == GDK_ACTION_MOVE) {
\r
2438 int selStart = sciThis->SelectionStart();
\r
2439 int selEnd = sciThis->SelectionEnd();
\r
2440 if (sciThis->posDrop > selStart) {
\r
2441 if (sciThis->posDrop > selEnd)
\r
2442 sciThis->posDrop = sciThis->posDrop - (selEnd - selStart);
\r
2444 sciThis->posDrop = selStart;
\r
2445 sciThis->posDrop = sciThis->pdoc->ClampPositionIntoDocument(sciThis->posDrop);
\r
2447 sciThis->ClearSelection();
\r
2449 sciThis->SetDragPosition(invalidPosition);
\r
2452 int ScintillaGTK::TimeOut(ScintillaGTK *sciThis) {
\r
2457 int ScintillaGTK::IdleCallback(ScintillaGTK *sciThis) {
\r
2458 // Idler will be automatically stoped, if there is nothing
\r
2459 // to do while idle.
\r
2460 bool ret = sciThis->Idle();
\r
2461 if (ret == false) {
\r
2462 // FIXME: This will remove the idler from GTK, we don't want to
\r
2463 // remove it as it is removed automatically when this function
\r
2464 // returns false (although, it should be harmless).
\r
2465 sciThis->SetIdle(false);
\r
2470 void ScintillaGTK::PopUpCB(ScintillaGTK *sciThis, guint action, GtkWidget *) {
\r
2472 sciThis->Command(action);
\r
2476 gint ScintillaGTK::PressCT(GtkWidget *widget, GdkEventButton *event, ScintillaGTK *sciThis) {
\r
2477 if (event->window != widget->window)
\r
2479 if (event->type != GDK_BUTTON_PRESS)
\r
2482 pt.x = int(event->x);
\r
2483 pt.y = int(event->y);
\r
2484 sciThis->ct.MouseClick(pt);
\r
2485 sciThis->CallTipClick();
\r
2486 #if GTK_MAJOR_VERSION >= 2
\r
2493 gint ScintillaGTK::ExposeCT(GtkWidget *widget, GdkEventExpose * /*ose*/, CallTip *ctip) {
\r
2494 Surface *surfaceWindow = Surface::Allocate();
\r
2495 if (surfaceWindow) {
\r
2496 surfaceWindow->Init(widget->window, widget);
\r
2497 ctip->PaintCT(surfaceWindow);
\r
2498 surfaceWindow->Release();
\r
2499 delete surfaceWindow;
\r
2504 sptr_t ScintillaGTK::DirectFunction(
\r
2505 ScintillaGTK *sciThis, unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
\r
2506 return sciThis->WndProc(iMessage, wParam, lParam);
\r
2509 sptr_t scintilla_send_message(ScintillaObject *sci, unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
\r
2510 ScintillaGTK *psci = reinterpret_cast<ScintillaGTK *>(sci->pscin);
\r
2511 return psci->WndProc(iMessage, wParam, lParam);
\r
2514 static void scintilla_class_init(ScintillaClass *klass);
\r
2515 static void scintilla_init(ScintillaObject *sci);
\r
2517 extern void Platform_Initialise();
\r
2518 extern void Platform_Finalise();
\r
2520 #if GLIB_MAJOR_VERSION < 2
\r
2521 GtkType scintilla_get_type() {
\r
2522 static GtkType scintilla_type = 0;
\r
2524 if (!scintilla_type) {
\r
2525 Platform_Initialise();
\r
2526 static GtkTypeInfo scintilla_info = {
\r
2528 sizeof (ScintillaObject),
\r
2529 sizeof (ScintillaClass),
\r
2530 (GtkClassInitFunc) scintilla_class_init,
\r
2531 (GtkObjectInitFunc) scintilla_init,
\r
2537 scintilla_type = gtk_type_unique(gtk_container_get_type(), &scintilla_info);
\r
2540 return scintilla_type;
\r
2543 GType scintilla_get_type() {
\r
2544 static GType scintilla_type = 0;
\r
2546 if (!scintilla_type) {
\r
2547 scintilla_type = g_type_from_name("Scintilla");
\r
2548 if (!scintilla_type) {
\r
2549 static GTypeInfo scintilla_info = {
\r
2550 (guint16) sizeof (ScintillaClass),
\r
2551 NULL, //(GBaseInitFunc)
\r
2552 NULL, //(GBaseFinalizeFunc)
\r
2553 (GClassInitFunc) scintilla_class_init,
\r
2554 NULL, //(GClassFinalizeFunc)
\r
2555 NULL, //gconstpointer data
\r
2556 (guint16) sizeof (ScintillaObject),
\r
2558 (GInstanceInitFunc) scintilla_init,
\r
2559 NULL //(GTypeValueTable*)
\r
2562 scintilla_type = g_type_register_static(
\r
2563 GTK_TYPE_CONTAINER, "Scintilla", &scintilla_info, (GTypeFlags) 0);
\r
2567 return scintilla_type;
\r
2571 void ScintillaGTK::ClassInit(OBJECT_CLASS* object_class, GtkWidgetClass *widget_class, GtkContainerClass *container_class) {
\r
2572 #if GLIB_MAJOR_VERSION >= 2
\r
2573 Platform_Initialise();
\r
2575 atomClipboard = gdk_atom_intern("CLIPBOARD", FALSE);
\r
2576 atomUTF8 = gdk_atom_intern("UTF8_STRING", FALSE);
\r
2577 atomString = GDK_SELECTION_TYPE_STRING;
\r
2578 atomUriList = gdk_atom_intern("text/uri-list", FALSE);
\r
2579 atomDROPFILES_DND = gdk_atom_intern("DROPFILES_DND", FALSE);
\r
2581 // Define default signal handlers for the class: Could move more
\r
2582 // of the signal handlers here (those that currently attached to wDraw
\r
2583 // in Initialise() may require coordinate translation?)
\r
2585 #if GLIB_MAJOR_VERSION < 2
\r
2586 object_class->destroy = Destroy;
\r
2588 object_class->finalize = Destroy;
\r
2590 widget_class->size_request = SizeRequest;
\r
2591 widget_class->size_allocate = SizeAllocate;
\r
2592 widget_class->expose_event = ExposeMain;
\r
2593 #if GTK_MAJOR_VERSION < 2
\r
2594 widget_class->draw = Draw;
\r
2596 widget_class->motion_notify_event = Motion;
\r
2597 widget_class->button_press_event = Press;
\r
2598 widget_class->button_release_event = MouseRelease;
\r
2599 #if PLAT_GTK_WIN32 || (GTK_MAJOR_VERSION >= 2)
\r
2600 widget_class->scroll_event = ScrollEvent;
\r
2602 widget_class->key_press_event = KeyPress;
\r
2603 widget_class->key_release_event = KeyRelease;
\r
2604 widget_class->focus_in_event = FocusIn;
\r
2605 widget_class->focus_out_event = FocusOut;
\r
2606 widget_class->selection_received = SelectionReceived;
\r
2607 widget_class->selection_get = SelectionGet;
\r
2608 widget_class->selection_clear_event = SelectionClear;
\r
2609 #if GTK_MAJOR_VERSION < 2
\r
2610 widget_class->selection_notify_event = SelectionNotify;
\r
2613 widget_class->drag_data_received = DragDataReceived;
\r
2614 widget_class->drag_motion = DragMotion;
\r
2615 widget_class->drag_leave = DragLeave;
\r
2616 widget_class->drag_end = DragEnd;
\r
2617 widget_class->drag_drop = Drop;
\r
2618 widget_class->drag_data_get = DragDataGet;
\r
2620 widget_class->realize = Realize;
\r
2621 widget_class->unrealize = UnRealize;
\r
2622 widget_class->map = Map;
\r
2623 widget_class->unmap = UnMap;
\r
2625 container_class->forall = MainForAll;
\r
2628 #if GLIB_MAJOR_VERSION < 2
\r
2629 #define GTK_CLASS_TYPE(c) (c->type)
\r
2630 #define SIG_MARSHAL gtk_marshal_NONE__INT_POINTER
\r
2631 #define MARSHAL_ARGUMENTS GTK_TYPE_INT, GTK_TYPE_POINTER
\r
2633 #define SIG_MARSHAL scintilla_marshal_NONE__INT_POINTER
\r
2634 #define MARSHAL_ARGUMENTS G_TYPE_INT, G_TYPE_POINTER
\r
2637 static void scintilla_class_init(ScintillaClass *klass) {
\r
2638 OBJECT_CLASS *object_class = (OBJECT_CLASS*) klass;
\r
2639 GtkWidgetClass *widget_class = (GtkWidgetClass*) klass;
\r
2640 GtkContainerClass *container_class = (GtkContainerClass*) klass;
\r
2642 #if GLIB_MAJOR_VERSION < 2
\r
2643 parent_class = (GtkWidgetClass*) gtk_type_class(gtk_container_get_type());
\r
2645 scintilla_signals[COMMAND_SIGNAL] = gtk_signal_new(
\r
2648 GTK_CLASS_TYPE(object_class),
\r
2649 GTK_SIGNAL_OFFSET(ScintillaClass, command),
\r
2652 2, MARSHAL_ARGUMENTS);
\r
2654 scintilla_signals[NOTIFY_SIGNAL] = gtk_signal_new(
\r
2657 GTK_CLASS_TYPE(object_class),
\r
2658 GTK_SIGNAL_OFFSET(ScintillaClass, notify),
\r
2661 2, MARSHAL_ARGUMENTS);
\r
2662 gtk_object_class_add_signals(object_class,
\r
2663 reinterpret_cast<unsigned int *>(scintilla_signals), LAST_SIGNAL);
\r
2665 GSignalFlags sigflags = GSignalFlags(G_SIGNAL_ACTION | G_SIGNAL_RUN_LAST);
\r
2666 scintilla_signals[COMMAND_SIGNAL] = g_signal_new(
\r
2668 G_TYPE_FROM_CLASS(object_class),
\r
2670 G_STRUCT_OFFSET(ScintillaClass, command),
\r
2671 NULL, //(GSignalAccumulator)
\r
2672 NULL, //(gpointer)
\r
2675 2, MARSHAL_ARGUMENTS);
\r
2677 scintilla_signals[NOTIFY_SIGNAL] = g_signal_new(
\r
2679 G_TYPE_FROM_CLASS(object_class),
\r
2681 G_STRUCT_OFFSET(ScintillaClass, notify),
\r
2686 2, MARSHAL_ARGUMENTS);
\r
2688 klass->command = NULL;
\r
2689 klass->notify = NULL;
\r
2691 ScintillaGTK::ClassInit(object_class, widget_class, container_class);
\r
2694 static void scintilla_init(ScintillaObject *sci) {
\r
2695 GTK_WIDGET_SET_FLAGS(sci, GTK_CAN_FOCUS);
\r
2696 sci->pscin = new ScintillaGTK(sci);
\r
2699 GtkWidget* scintilla_new() {
\r
2700 #if GLIB_MAJOR_VERSION < 2
\r
2701 return GTK_WIDGET(gtk_type_new(scintilla_get_type()));
\r
2703 return GTK_WIDGET(g_object_new(scintilla_get_type(), NULL));
\r
2707 void scintilla_set_id(ScintillaObject *sci, uptr_t id) {
\r
2708 ScintillaGTK *psci = reinterpret_cast<ScintillaGTK *>(sci->pscin);
\r
2709 psci->ctrlID = id;
\r
2712 void scintilla_release_resources(void) {
\r
2713 Platform_Finalise();
\r