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.
13 #include <gdk/gdkkeysyms.h>
21 #include "Scintilla.h"
22 #include "ScintillaWidget.h"
29 #include "ContractionState.h"
31 #include "CellBuffer.h"
34 #include "Indicator.h"
36 #include "LineMarker.h"
38 #include "AutoComplete.h"
39 #include "ViewStyle.h"
43 #include "ScintillaBase.h"
44 #include "UniConversion.h"
46 #include "gtk/gtksignal.h"
47 #include "gtk/gtkmarshal.h"
48 #if GTK_MAJOR_VERSION >= 2
49 #include "scintilla-marshal.h"
55 #include "ExternalLexer.h"
58 #define INTERNATIONAL_INPUT
60 #if !PLAT_GTK_WIN32 || GTK_MAJOR_VERSION >= 2
65 #include "Converter.h"
69 // Constant conditional expressions are because of GTK+ headers
70 #pragma warning(disable: 4127)
71 // Ignore unreferenced local functions in GTK+ headers
72 #pragma warning(disable: 4505)
75 #if GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 2
76 #define USE_GTK_CLIPBOARD
79 extern char *UTF8FromLatin1(const char *s
, int &len
);
81 class ScintillaGTK
: public ScintillaBase
{
82 _ScintillaObject
*sci
;
86 GtkObject
*adjustmentv
;
87 GtkObject
*adjustmenth
;
91 // Because clipboard access is asynchronous, copyText is created by Copy
92 #ifndef USE_GTK_CLIPBOARD
93 SelectionText copyText
;
96 SelectionText primary
;
103 GtkWidgetClass
*parentClass
;
105 static GdkAtom atomClipboard
;
106 static GdkAtom atomUTF8
;
107 static GdkAtom atomString
;
111 CLIPFORMAT cfColumnSelect
;
114 #ifdef INTERNATIONAL_INPUT
115 #if GTK_MAJOR_VERSION < 2
116 // Input context used for supporting internationalized key entry
122 GtkIMContext
*im_context
;
126 // Wheel mouse support
127 unsigned int linesPerScroll
;
128 GTimeVal lastWheelMouseTime
;
129 gint lastWheelMouseDirection
;
130 gint wheelMouseIntensity
;
132 // Private so ScintillaGTK objects can not be copied
133 ScintillaGTK(const ScintillaGTK
&) : ScintillaBase() {}
134 ScintillaGTK
&operator=(const ScintillaGTK
&) { return * this; }
137 ScintillaGTK(_ScintillaObject
*sci_
);
138 virtual ~ScintillaGTK();
139 static void ClassInit(GtkObjectClass
* object_class
, GtkWidgetClass
*widget_class
, GtkContainerClass
*container_class
);
142 virtual void Initialise();
143 virtual void Finalise();
144 virtual void DisplayCursor(Window::Cursor c
);
145 virtual void StartDrag();
146 int TargetAsUTF8(char *text
);
147 int EncodedFromUTF8(char *utf8
, char *encoded
);
148 public: // Public for scintilla_send_message
149 virtual sptr_t
WndProc(unsigned int iMessage
, uptr_t wParam
, sptr_t lParam
);
151 virtual sptr_t
DefWndProc(unsigned int iMessage
, uptr_t wParam
, sptr_t lParam
);
152 virtual void SetTicking(bool on
);
153 virtual bool SetIdle(bool on
);
154 virtual void SetMouseCapture(bool on
);
155 virtual bool HaveMouseCapture();
157 virtual PRectangle
GetClientRectangle();
158 void SyncPaint(PRectangle rc
);
159 virtual void ScrollText(int linesToMove
);
160 virtual void SetVerticalScrollPos();
161 virtual void SetHorizontalScrollPos();
162 virtual bool ModifyScrollBars(int nMax
, int nPage
);
163 void ReconfigureScrollBars();
164 virtual void NotifyChange();
165 virtual void NotifyFocus(bool focus
);
166 virtual void NotifyParent(SCNotification scn
);
167 void NotifyKey(int key
, int modifiers
);
168 void NotifyURIDropped(const char *list
);
169 bool UseInputMethod() const;
170 const char *CharacterSetID() const;
171 virtual int KeyDefault(int key
, int modifiers
);
172 virtual void CopyToClipboard(const SelectionText
&selectedText
);
174 virtual void Paste();
175 virtual void CreateCallTipWindow(PRectangle rc
);
176 virtual void AddToPopUp(const char *label
, int cmd
= 0, bool enabled
= true);
177 bool OwnPrimarySelection();
178 virtual void ClaimSelection();
179 void GetGtkSelectionText(GtkSelectionData
*selectionData
, SelectionText
&selText
);
180 void ReceivedSelection(GtkSelectionData
*selection_data
);
181 void ReceivedDrop(GtkSelectionData
*selection_data
);
182 static void GetSelection(GtkSelectionData
*selection_data
, guint info
, SelectionText
*selected
);
183 #ifdef USE_GTK_CLIPBOARD
184 static void ClipboardGetSelection(GtkClipboard
* clip
, GtkSelectionData
*selection_data
, guint info
, void *data
);
185 static void ClipboardClearSelection(GtkClipboard
* clip
, void *data
);
188 void UnclaimSelection(GdkEventSelection
*selection_event
);
189 void Resize(int width
, int height
);
191 // Callback functions
192 void RealizeThis(GtkWidget
*widget
);
193 static void Realize(GtkWidget
*widget
);
194 void UnRealizeThis(GtkWidget
*widget
);
195 static void UnRealize(GtkWidget
*widget
);
197 static void Map(GtkWidget
*widget
);
199 static void UnMap(GtkWidget
*widget
);
200 static gint
CursorMoved(GtkWidget
*widget
, int xoffset
, int yoffset
, ScintillaGTK
*sciThis
);
201 static gint
FocusIn(GtkWidget
*widget
, GdkEventFocus
*event
);
202 static gint
FocusOut(GtkWidget
*widget
, GdkEventFocus
*event
);
203 static void SizeRequest(GtkWidget
*widget
, GtkRequisition
*requisition
);
204 static void SizeAllocate(GtkWidget
*widget
, GtkAllocation
*allocation
);
205 gint
Expose(GtkWidget
*widget
, GdkEventExpose
*ose
);
206 static gint
ExposeMain(GtkWidget
*widget
, GdkEventExpose
*ose
);
207 static void Draw(GtkWidget
*widget
, GdkRectangle
*area
);
208 void ForAll(GtkCallback callback
, gpointer callback_data
);
209 static void MainForAll(GtkContainer
*container
, gboolean include_internals
, GtkCallback callback
, gpointer callback_data
);
211 static void ScrollSignal(GtkAdjustment
*adj
, ScintillaGTK
*sciThis
);
212 static void ScrollHSignal(GtkAdjustment
*adj
, ScintillaGTK
*sciThis
);
213 gint
PressThis(GdkEventButton
*event
);
214 static gint
Press(GtkWidget
*widget
, GdkEventButton
*event
);
215 static gint
MouseRelease(GtkWidget
*widget
, GdkEventButton
*event
);
216 #if PLAT_GTK_WIN32 || (GTK_MAJOR_VERSION >= 2)
217 static gint
ScrollEvent(GtkWidget
*widget
, GdkEventScroll
*event
);
219 static gint
Motion(GtkWidget
*widget
, GdkEventMotion
*event
);
220 gint
KeyThis(GdkEventKey
*event
);
221 static gint
KeyPress(GtkWidget
*widget
, GdkEventKey
*event
);
222 static gint
KeyRelease(GtkWidget
*widget
, GdkEventKey
*event
);
223 #if GTK_MAJOR_VERSION >= 2
224 static gint
ExposePreedit(GtkWidget
*widget
, GdkEventExpose
*ose
, ScintillaGTK
*sciThis
);
225 gint
ExposePreeditThis(GtkWidget
*widget
, GdkEventExpose
*ose
);
226 static void Commit(GtkIMContext
*context
, char *str
, ScintillaGTK
*sciThis
);
227 void CommitThis(char *str
);
228 static void PreeditChanged(GtkIMContext
*context
, ScintillaGTK
*sciThis
);
229 void PreeditChangedThis();
231 static gint
StyleSetText(GtkWidget
*widget
, GtkStyle
*previous
, void*);
232 static gint
RealizeText(GtkWidget
*widget
, void*);
233 static void Destroy(GtkObject
*object
);
234 static void SelectionReceived(GtkWidget
*widget
, GtkSelectionData
*selection_data
,
236 static void SelectionGet(GtkWidget
*widget
, GtkSelectionData
*selection_data
,
237 guint info
, guint time
);
238 static gint
SelectionClear(GtkWidget
*widget
, GdkEventSelection
*selection_event
);
239 #if GTK_MAJOR_VERSION < 2
240 static gint
SelectionNotify(GtkWidget
*widget
, GdkEventSelection
*selection_event
);
242 static void DragBegin(GtkWidget
*widget
, GdkDragContext
*context
);
243 static gboolean
DragMotion(GtkWidget
*widget
, GdkDragContext
*context
,
244 gint x
, gint y
, guint time
);
245 static void DragLeave(GtkWidget
*widget
, GdkDragContext
*context
,
247 static void DragEnd(GtkWidget
*widget
, GdkDragContext
*context
);
248 static gboolean
Drop(GtkWidget
*widget
, GdkDragContext
*context
,
249 gint x
, gint y
, guint time
);
250 static void DragDataReceived(GtkWidget
*widget
, GdkDragContext
*context
,
251 gint x
, gint y
, GtkSelectionData
*selection_data
, guint info
, guint time
);
252 static void DragDataGet(GtkWidget
*widget
, GdkDragContext
*context
,
253 GtkSelectionData
*selection_data
, guint info
, guint time
);
254 static gint
TimeOut(ScintillaGTK
*sciThis
);
255 static gint
IdleCallback(ScintillaGTK
*sciThis
);
256 static void PopUpCB(ScintillaGTK
*sciThis
, guint action
, GtkWidget
*widget
);
258 gint
ExposeTextThis(GtkWidget
*widget
, GdkEventExpose
*ose
);
259 static gint
ExposeText(GtkWidget
*widget
, GdkEventExpose
*ose
, ScintillaGTK
*sciThis
);
261 static gint
ExposeCT(GtkWidget
*widget
, GdkEventExpose
*ose
, CallTip
*ct
);
262 static gint
PressCT(GtkWidget
*widget
, GdkEventButton
*event
, ScintillaGTK
*sciThis
);
264 static sptr_t
DirectFunction(ScintillaGTK
*sciThis
,
265 unsigned int iMessage
, uptr_t wParam
, sptr_t lParam
);
274 static gint scintilla_signals
[LAST_SIGNAL
] = { 0 };
275 static GtkWidgetClass
* parent_class
= NULL
;
280 TARGET_COMPOUND_TEXT
,
284 GdkAtom
ScintillaGTK::atomClipboard
= 0;
285 GdkAtom
ScintillaGTK::atomUTF8
= 0;
286 GdkAtom
ScintillaGTK::atomString
= 0;
288 static const GtkTargetEntry clipboardTargets
[] = {
289 { "UTF8_STRING", 0, TARGET_UTF8_STRING
},
290 { "STRING", 0, TARGET_STRING
},
291 // { "TEXT", 0, TARGET_TEXT },
292 // { "COMPOUND_TEXT", 0, TARGET_COMPOUND_TEXT },
293 { "text/uri-list", 0, 0 },
295 static const gint nClipboardTargets
= sizeof(clipboardTargets
) / sizeof(clipboardTargets
[0]);
297 static GtkWidget
*PWidget(Window
&w
) {
298 return reinterpret_cast<GtkWidget
*>(w
.GetID());
301 static ScintillaGTK
*ScintillaFromWidget(GtkWidget
*widget
) {
302 ScintillaObject
*scio
= reinterpret_cast<ScintillaObject
*>(widget
);
303 return reinterpret_cast<ScintillaGTK
*>(scio
->pscin
);
306 ScintillaGTK::ScintillaGTK(_ScintillaObject
*sci_
) :
307 adjustmentv(0), adjustmenth(0),
308 scrollBarWidth(30), scrollBarHeight(30),
309 capturedMouse(false), dragWasDropped(false),
310 lastKey(0), parentClass(0),
311 #ifdef INTERNATIONAL_INPUT
312 #if GTK_MAJOR_VERSION < 2
319 lastWheelMouseDirection(0),
320 wheelMouseIntensity(0) {
322 wMain
= GTK_WIDGET(sci
);
325 // There does not seem to be a real standard for indicating that the clipboard
326 // contains a rectangular selection, so copy Developer Studio.
327 cfColumnSelect
= static_cast<CLIPFORMAT
>(
328 ::RegisterClipboardFormat("MSDEVColumnSelect"));
330 // Get intellimouse parameters when running on win32; otherwise use
331 // reasonable default
332 #ifndef SPI_GETWHEELSCROLLLINES
333 #define SPI_GETWHEELSCROLLLINES 104
335 ::SystemParametersInfo(SPI_GETWHEELSCROLLLINES
, 0, &linesPerScroll
, 0);
339 lastWheelMouseTime
.tv_sec
= 0;
340 lastWheelMouseTime
.tv_usec
= 0;
345 ScintillaGTK::~ScintillaGTK() {
348 void ScintillaGTK::RealizeThis(GtkWidget
*widget
) {
349 //Platform::DebugPrintf("ScintillaGTK::realize this\n");
350 GTK_WIDGET_SET_FLAGS(widget
, GTK_REALIZED
);
352 attrs
.window_type
= GDK_WINDOW_CHILD
;
353 attrs
.x
= widget
->allocation
.x
;
354 attrs
.y
= widget
->allocation
.y
;
355 attrs
.width
= widget
->allocation
.width
;
356 attrs
.height
= widget
->allocation
.height
;
357 attrs
.wclass
= GDK_INPUT_OUTPUT
;
358 attrs
.visual
= gtk_widget_get_visual(widget
);
359 attrs
.colormap
= gtk_widget_get_colormap(widget
);
360 attrs
.event_mask
= gtk_widget_get_events(widget
) | GDK_EXPOSURE_MASK
;
361 GdkCursor
*cursor
= gdk_cursor_new(GDK_XTERM
);
362 attrs
.cursor
= cursor
;
363 widget
->window
= gdk_window_new(gtk_widget_get_parent_window(widget
), &attrs
,
364 GDK_WA_X
| GDK_WA_Y
| GDK_WA_VISUAL
| GDK_WA_COLORMAP
| GDK_WA_CURSOR
);
365 gdk_window_set_user_data(widget
->window
, widget
);
366 gdk_window_set_background(widget
->window
, &widget
->style
->bg
[GTK_STATE_NORMAL
]);
367 gdk_window_show(widget
->window
);
368 gdk_cursor_destroy(cursor
);
369 widget
->style
= gtk_style_attach(widget
->style
, widget
->window
);
370 #ifdef INTERNATIONAL_INPUT
371 #if GTK_MAJOR_VERSION < 2
372 if (gdk_im_ready() && (ic_attr
= gdk_ic_attr_new()) != NULL
) {
374 GdkColormap
*colormap
;
376 GdkICAttr
*attr
= ic_attr
;
377 GdkICAttributesType attrmask
= GDK_IC_ALL_REQ
;
379 GdkIMStyle supported_style
= (GdkIMStyle
) (GDK_IM_PREEDIT_NONE
|
380 GDK_IM_PREEDIT_NOTHING
|
381 GDK_IM_PREEDIT_POSITION
|
383 GDK_IM_STATUS_NOTHING
);
385 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
386 supported_style
= (GdkIMStyle
) ((int) supported_style
& ~GDK_IM_PREEDIT_POSITION
);
388 attr
->style
= style
= gdk_im_decide_style(supported_style
);
389 attr
->client_window
= widget
->window
;
391 if ((colormap
= gtk_widget_get_colormap (widget
)) != gtk_widget_get_default_colormap ()) {
392 attrmask
= (GdkICAttributesType
) ((int) attrmask
| GDK_IC_PREEDIT_COLORMAP
);
393 attr
->preedit_colormap
= colormap
;
396 switch (style
& GDK_IM_PREEDIT_MASK
) {
397 case GDK_IM_PREEDIT_POSITION
:
398 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
) {
399 g_warning("over-the-spot style requires fontset");
403 attrmask
= (GdkICAttributesType
) ((int) attrmask
| GDK_IC_PREEDIT_POSITION_REQ
);
404 gdk_window_get_size(widget
->window
, &width
, &height
);
405 attr
->spot_location
.x
= 0;
406 attr
->spot_location
.y
= height
;
407 attr
->preedit_area
.x
= 0;
408 attr
->preedit_area
.y
= 0;
409 attr
->preedit_area
.width
= width
;
410 attr
->preedit_area
.height
= height
;
411 attr
->preedit_fontset
= widget
->style
->font
;
415 ic
= gdk_ic_new(attr
, attrmask
);
418 g_warning("Can't create input context.");
420 mask
= gdk_window_get_events(widget
->window
);
421 mask
= (GdkEventMask
) ((int) mask
| gdk_ic_get_events(ic
));
422 gdk_window_set_events(widget
->window
, mask
);
424 if (GTK_WIDGET_HAS_FOCUS(widget
))
425 gdk_im_begin(ic
, widget
->window
);
429 wPreedit
= gtk_window_new(GTK_WINDOW_POPUP
);
430 wPreeditDraw
= gtk_drawing_area_new();
431 gtk_signal_connect(GTK_OBJECT(PWidget(wPreeditDraw
)), "expose_event",
432 GtkSignalFunc(ExposePreedit
), this);
433 gtk_container_add(GTK_CONTAINER(PWidget(wPreedit
)), PWidget(wPreeditDraw
));
434 gtk_widget_realize(PWidget(wPreedit
));
435 gtk_widget_realize(PWidget(wPreeditDraw
));
436 gtk_widget_show(PWidget(wPreeditDraw
));
438 im_context
= gtk_im_multicontext_new();
439 g_signal_connect(im_context
, "commit",
440 G_CALLBACK(Commit
), this);
441 g_signal_connect(im_context
, "preedit_changed",
442 G_CALLBACK(PreeditChanged
), this);
443 gtk_im_context_set_client_window(im_context
, widget
->window
);
446 gtk_signal_connect_after(GTK_OBJECT(PWidget(wText
)), "style_set",
447 GtkSignalFunc(ScintillaGTK::StyleSetText
), NULL
);
448 gtk_signal_connect_after(GTK_OBJECT(PWidget(wText
)), "realize",
449 GtkSignalFunc(ScintillaGTK::RealizeText
), NULL
);
450 gtk_widget_realize(PWidget(wText
));
451 gtk_widget_realize(PWidget(scrollbarv
));
452 gtk_widget_realize(PWidget(scrollbarh
));
455 void ScintillaGTK::Realize(GtkWidget
*widget
) {
456 ScintillaGTK
*sciThis
= ScintillaFromWidget(widget
);
457 sciThis
->RealizeThis(widget
);
460 void ScintillaGTK::UnRealizeThis(GtkWidget
*widget
) {
461 if (GTK_WIDGET_MAPPED(widget
)) {
462 gtk_widget_unmap(widget
);
464 GTK_WIDGET_UNSET_FLAGS(widget
, GTK_REALIZED
);
465 gtk_widget_unrealize(PWidget(wText
));
466 gtk_widget_unrealize(PWidget(scrollbarv
));
467 gtk_widget_unrealize(PWidget(scrollbarh
));
468 #ifdef INTERNATIONAL_INPUT
469 #if GTK_MAJOR_VERSION < 2
475 gdk_ic_attr_destroy(ic_attr
);
479 gtk_widget_unrealize(PWidget(wPreedit
));
480 gtk_widget_unrealize(PWidget(wPreeditDraw
));
481 g_object_unref(im_context
);
484 if (GTK_WIDGET_CLASS(parentClass
)->unrealize
)
485 GTK_WIDGET_CLASS(parentClass
)->unrealize(widget
);
490 void ScintillaGTK::UnRealize(GtkWidget
*widget
) {
491 ScintillaGTK
*sciThis
= ScintillaFromWidget(widget
);
492 sciThis
->UnRealizeThis(widget
);
495 static void MapWidget(GtkWidget
*widget
) {
497 GTK_WIDGET_VISIBLE(widget
) &&
498 !GTK_WIDGET_MAPPED(widget
)) {
499 gtk_widget_map(widget
);
503 void ScintillaGTK::MapThis() {
504 //Platform::DebugPrintf("ScintillaGTK::map this\n");
505 GTK_WIDGET_SET_FLAGS(PWidget(wMain
), GTK_MAPPED
);
506 MapWidget(PWidget(wText
));
507 MapWidget(PWidget(scrollbarh
));
508 MapWidget(PWidget(scrollbarv
));
509 wMain
.SetCursor(Window::cursorArrow
);
510 scrollbarv
.SetCursor(Window::cursorArrow
);
511 scrollbarh
.SetCursor(Window::cursorArrow
);
513 gdk_window_show(PWidget(wMain
)->window
);
516 void ScintillaGTK::Map(GtkWidget
*widget
) {
517 ScintillaGTK
*sciThis
= ScintillaFromWidget(widget
);
521 void ScintillaGTK::UnMapThis() {
522 //Platform::DebugPrintf("ScintillaGTK::unmap this\n");
523 GTK_WIDGET_UNSET_FLAGS(PWidget(wMain
), GTK_MAPPED
);
524 gdk_window_hide(PWidget(wMain
)->window
);
525 gtk_widget_unmap(PWidget(wText
));
526 gtk_widget_unmap(PWidget(scrollbarh
));
527 gtk_widget_unmap(PWidget(scrollbarv
));
530 void ScintillaGTK::UnMap(GtkWidget
*widget
) {
531 ScintillaGTK
*sciThis
= ScintillaFromWidget(widget
);
532 sciThis
->UnMapThis();
535 void ScintillaGTK::ForAll(GtkCallback callback
, gpointer callback_data
) {
536 (*callback
) (PWidget(wText
), callback_data
);
537 (*callback
) (PWidget(scrollbarv
), callback_data
);
538 (*callback
) (PWidget(scrollbarh
), callback_data
);
541 void ScintillaGTK::MainForAll(GtkContainer
*container
, gboolean include_internals
, GtkCallback callback
, gpointer callback_data
) {
542 ScintillaGTK
*sciThis
= ScintillaFromWidget((GtkWidget
*)container
);
544 if (callback
!= NULL
&& include_internals
) {
545 sciThis
->ForAll(callback
, callback_data
);
549 #ifdef INTERNATIONAL_INPUT
550 #if GTK_MAJOR_VERSION < 2
551 gint
ScintillaGTK::CursorMoved(GtkWidget
*widget
, int xoffset
, int yoffset
, ScintillaGTK
*sciThis
) {
552 if (GTK_WIDGET_HAS_FOCUS(widget
) && gdk_im_ready() && sciThis
->ic
&&
553 (gdk_ic_get_style(sciThis
->ic
) & GDK_IM_PREEDIT_POSITION
)) {
554 sciThis
->ic_attr
->spot_location
.x
= xoffset
;
555 sciThis
->ic_attr
->spot_location
.y
= yoffset
;
556 gdk_ic_set_attr(sciThis
->ic
, sciThis
->ic_attr
, GDK_IC_SPOT_LOCATION
);
561 gint
ScintillaGTK::CursorMoved(GtkWidget
*, int xoffset
, int yoffset
, ScintillaGTK
*sciThis
) {
567 gtk_im_context_set_cursor_location(sciThis
->im_context
, &area
);
572 gint
ScintillaGTK::CursorMoved(GtkWidget
*, int, int, ScintillaGTK
*) {
577 gint
ScintillaGTK::FocusIn(GtkWidget
*widget
, GdkEventFocus
* /*event*/) {
578 ScintillaGTK
*sciThis
= ScintillaFromWidget(widget
);
579 //Platform::DebugPrintf("ScintillaGTK::focus in %x\n", sciThis);
580 GTK_WIDGET_SET_FLAGS(widget
, GTK_HAS_FOCUS
);
581 sciThis
->SetFocusState(true);
583 #ifdef INTERNATIONAL_INPUT
584 #if GTK_MAJOR_VERSION < 2
586 gdk_im_begin(sciThis
->ic
, widget
->window
);
590 gtk_im_context_get_preedit_string(sciThis
->im_context
, &str
, NULL
, &cursor_pos
);
591 if (PWidget(sciThis
->wPreedit
) != NULL
) {
592 if ((str
!= NULL
) && (strlen(str
) > 0)){
593 gtk_widget_show(PWidget(sciThis
->wPreedit
));
595 gtk_widget_hide(PWidget(sciThis
->wPreedit
));
599 gtk_im_context_focus_in(sciThis
->im_context
);
606 gint
ScintillaGTK::FocusOut(GtkWidget
*widget
, GdkEventFocus
* /*event*/) {
607 ScintillaGTK
*sciThis
= ScintillaFromWidget(widget
);
608 //Platform::DebugPrintf("ScintillaGTK::focus out %x\n", sciThis);
609 GTK_WIDGET_UNSET_FLAGS(widget
, GTK_HAS_FOCUS
);
610 sciThis
->SetFocusState(false);
612 #ifdef INTERNATIONAL_INPUT
613 #if GTK_MAJOR_VERSION < 2
616 if (PWidget(sciThis
->wPreedit
) != NULL
) {
617 gtk_widget_hide(PWidget(sciThis
->wPreedit
));
618 gtk_im_context_focus_out(sciThis
->im_context
);
626 void ScintillaGTK::SizeRequest(GtkWidget
*widget
, GtkRequisition
*requisition
) {
627 requisition
->width
= 600;
628 requisition
->height
= 2000;
629 ScintillaGTK
*sciThis
= ScintillaFromWidget(widget
);
630 GtkRequisition child_requisition
;
631 gtk_widget_size_request(PWidget(sciThis
->scrollbarh
), &child_requisition
);
632 gtk_widget_size_request(PWidget(sciThis
->scrollbarv
), &child_requisition
);
635 void ScintillaGTK::SizeAllocate(GtkWidget
*widget
, GtkAllocation
*allocation
) {
636 widget
->allocation
= *allocation
;
637 ScintillaGTK
*sciThis
= ScintillaFromWidget(widget
);
638 if (GTK_WIDGET_REALIZED(widget
))
639 gdk_window_move_resize(widget
->window
,
640 widget
->allocation
.x
,
641 widget
->allocation
.y
,
642 widget
->allocation
.width
,
643 widget
->allocation
.height
);
645 sciThis
->Resize(allocation
->width
, allocation
->height
);
647 #ifdef INTERNATIONAL_INPUT
648 #if GTK_MAJOR_VERSION < 2
649 if (sciThis
->ic
&& (gdk_ic_get_style(sciThis
->ic
) & GDK_IM_PREEDIT_POSITION
)) {
652 gdk_window_get_size(widget
->window
, &width
, &height
);
653 sciThis
->ic_attr
->preedit_area
.width
= width
;
654 sciThis
->ic_attr
->preedit_area
.height
= height
;
656 gdk_ic_set_attr(sciThis
->ic
, sciThis
->ic_attr
, GDK_IC_PREEDIT_AREA
);
662 void ScintillaGTK::Initialise() {
663 //Platform::DebugPrintf("ScintillaGTK::Initialise\n");
664 parentClass
= reinterpret_cast<GtkWidgetClass
*>(
665 gtk_type_class(gtk_container_get_type()));
667 GTK_WIDGET_SET_FLAGS(PWidget(wMain
), GTK_CAN_FOCUS
);
668 GTK_WIDGET_SET_FLAGS(GTK_WIDGET(PWidget(wMain
)), GTK_SENSITIVE
);
669 gtk_widget_set_events(PWidget(wMain
),
673 | GDK_KEY_RELEASE_MASK
674 | GDK_FOCUS_CHANGE_MASK
675 | GDK_LEAVE_NOTIFY_MASK
676 | GDK_BUTTON_PRESS_MASK
677 | GDK_BUTTON_RELEASE_MASK
678 | GDK_POINTER_MOTION_MASK
679 | GDK_POINTER_MOTION_HINT_MASK
);
681 wText
= gtk_drawing_area_new();
682 gtk_widget_set_parent(PWidget(wText
), PWidget(wMain
));
683 gtk_widget_show(PWidget(wText
));
684 gtk_signal_connect(GTK_OBJECT(PWidget(wText
)), "expose_event",
685 GtkSignalFunc(ScintillaGTK::ExposeText
), this);
686 gtk_widget_set_events(PWidget(wText
), GDK_EXPOSURE_MASK
);
687 #if GTK_MAJOR_VERSION >= 2
688 // Avoid background drawing flash
689 gtk_widget_set_double_buffered(PWidget(wText
), FALSE
);
691 gtk_drawing_area_size(GTK_DRAWING_AREA(PWidget(wText
)),
694 adjustmentv
= gtk_adjustment_new(0.0, 0.0, 201.0, 1.0, 20.0, 20.0);
695 scrollbarv
= gtk_vscrollbar_new(GTK_ADJUSTMENT(adjustmentv
));
696 GTK_WIDGET_UNSET_FLAGS(PWidget(scrollbarv
), GTK_CAN_FOCUS
);
697 gtk_signal_connect(GTK_OBJECT(adjustmentv
), "value_changed",
698 GTK_SIGNAL_FUNC(ScrollSignal
), this);
699 gtk_widget_set_parent(PWidget(scrollbarv
), PWidget(wMain
));
700 gtk_widget_show(PWidget(scrollbarv
));
702 adjustmenth
= gtk_adjustment_new(0.0, 0.0, 101.0, 1.0, 20.0, 20.0);
703 scrollbarh
= gtk_hscrollbar_new(GTK_ADJUSTMENT(adjustmenth
));
704 GTK_WIDGET_UNSET_FLAGS(PWidget(scrollbarh
), GTK_CAN_FOCUS
);
705 gtk_signal_connect(GTK_OBJECT(adjustmenth
), "value_changed",
706 GTK_SIGNAL_FUNC(ScrollHSignal
), this);
707 gtk_widget_set_parent(PWidget(scrollbarh
), PWidget(wMain
));
708 gtk_widget_show(PWidget(scrollbarh
));
710 gtk_widget_grab_focus(PWidget(wMain
));
712 gtk_selection_add_targets(GTK_WIDGET(PWidget(wMain
)), GDK_SELECTION_PRIMARY
,
713 clipboardTargets
, nClipboardTargets
);
715 #ifndef USE_GTK_CLIPBOARD
716 gtk_selection_add_targets(GTK_WIDGET(PWidget(wMain
)), atomClipboard
,
717 clipboardTargets
, nClipboardTargets
);
720 gtk_drag_dest_set(GTK_WIDGET(PWidget(wMain
)),
721 GTK_DEST_DEFAULT_ALL
, clipboardTargets
, nClipboardTargets
,
722 static_cast<GdkDragAction
>(GDK_ACTION_COPY
| GDK_ACTION_MOVE
));
727 void ScintillaGTK::Finalise() {
729 ScintillaBase::Finalise();
732 void ScintillaGTK::DisplayCursor(Window::Cursor c
) {
733 if (cursorMode
== SC_CURSORNORMAL
)
736 wText
.SetCursor(static_cast<Window::Cursor
>(cursorMode
));
739 void ScintillaGTK::StartDrag() {
740 dragWasDropped
= false;
741 static const GtkTargetEntry targets
[] = {
742 { "UTF8_STRING", 0, TARGET_UTF8_STRING
},
743 { "STRING", 0, TARGET_STRING
},
744 // { "TEXT", 0, TARGET_TEXT },
745 // { "COMPOUND_TEXT", 0, TARGET_COMPOUND_TEXT },
747 static const gint n_targets
= sizeof(targets
) / sizeof(targets
[0]);
748 GtkTargetList
*tl
= gtk_target_list_new(targets
, n_targets
);
749 gtk_drag_begin(GTK_WIDGET(PWidget(wMain
)),
751 static_cast<GdkDragAction
>(GDK_ACTION_COPY
| GDK_ACTION_MOVE
),
753 reinterpret_cast<GdkEvent
*>(&evbtn
));
757 static char *ConvertText(int *lenResult
, char *s
, size_t len
, const char *charSetDest
, const char *charSetSource
) {
760 Converter
conv(charSetDest
, charSetSource
);
762 destForm
= new char[len
*3+1];
765 char *pout
= destForm
;
766 size_t outLeft
= len
*3+1;
767 size_t conversions
= conv
.Convert(&pin
, &inLeft
, &pout
, &outLeft
);
768 if (conversions
== ((size_t)(-1))) {
769 fprintf(stderr
, "iconv %s->%s failed for %s\n", charSetSource
, charSetDest
, static_cast<char *>(s
));
773 //fprintf(stderr, "iconv OK %s %d\n", destForm, pout - destForm);
775 *lenResult
= pout
- destForm
;
778 fprintf(stderr
, "Can not iconv %s %s\n", charSetDest
, charSetSource
);
781 destForm
= new char[1];
789 // Returns the target converted to UTF8.
790 // Return the length in bytes.
791 int ScintillaGTK::TargetAsUTF8(char *text
) {
792 int targetLength
= targetEnd
- targetStart
;
793 if (IsUnicodeMode()) {
795 pdoc
->GetCharRange(text
, targetStart
, targetLength
);
800 const char *charSetBuffer
= CharacterSetID();
801 if (*charSetBuffer
) {
802 //~ fprintf(stderr, "AsUTF8 %s %d %0d-%0d\n", charSetBuffer, targetLength, targetStart, targetEnd);
803 char *s
= new char[targetLength
];
805 pdoc
->GetCharRange(s
, targetStart
, targetLength
);
806 //~ fprintf(stderr, " \"%s\"\n", s);
808 char *tmputf
= ConvertText(&targetLength
, s
, targetLength
, "UTF-8", charSetBuffer
);
809 memcpy(text
, tmputf
, targetLength
);
811 //~ fprintf(stderr, " \"%s\"\n", text);
817 pdoc
->GetCharRange(text
, targetStart
, targetLength
);
825 //~ fprintf(stderr, "Length = %d bytes\n", targetLength);
829 // Translates a nul terminated UTF8 string into the document encoding.
830 // Return the length of the result in bytes.
831 int ScintillaGTK::EncodedFromUTF8(char *utf8
, char *encoded
) {
832 int inputLength
= lengthForEncode
? lengthForEncode
: strlen(utf8
);
833 if (IsUnicodeMode()) {
835 memcpy(encoded
, utf8
, inputLength
);
841 const char *charSetBuffer
= CharacterSetID();
842 if (*charSetBuffer
) {
843 //~ fprintf(stderr, "Encode %s %d\n", charSetBuffer, inputLength);
845 char *tmpEncoded
= ConvertText(&outLength
, utf8
, inputLength
, charSetBuffer
, "UTF-8");
847 //~ fprintf(stderr, " \"%s\"\n", tmpEncoded);
849 memcpy(encoded
, tmpEncoded
, outLength
);
856 memcpy(encoded
, utf8
, inputLength
);
866 sptr_t
ScintillaGTK::WndProc(unsigned int iMessage
, uptr_t wParam
, sptr_t lParam
) {
870 gtk_widget_grab_focus(PWidget(wMain
));
873 case SCI_GETDIRECTFUNCTION
:
874 return reinterpret_cast<sptr_t
>(DirectFunction
);
876 case SCI_GETDIRECTPOINTER
:
877 return reinterpret_cast<sptr_t
>(this);
880 case SCI_LOADLEXERLIBRARY
:
881 LexerManager::GetInstance()->Load(reinterpret_cast<const char*>(wParam
));
884 case SCI_TARGETASUTF8
:
885 return TargetAsUTF8(reinterpret_cast<char*>(lParam
));
887 case SCI_ENCODEDFROMUTF8
:
888 return EncodedFromUTF8(reinterpret_cast<char*>(wParam
),
889 reinterpret_cast<char*>(lParam
));
892 return ScintillaBase::WndProc(iMessage
, wParam
, lParam
);
897 sptr_t
ScintillaGTK::DefWndProc(unsigned int, uptr_t
, sptr_t
) {
901 void ScintillaGTK::SetTicking(bool on
) {
902 if (timer
.ticking
!= on
) {
905 timer
.tickerID
= reinterpret_cast<TickerID
>(gtk_timeout_add(timer
.tickSize
, (GtkFunction
)TimeOut
, this));
907 gtk_timeout_remove(GPOINTER_TO_UINT(timer
.tickerID
));
910 timer
.ticksToWait
= caret
.period
;
913 bool ScintillaGTK::SetIdle(bool on
) {
915 // Start idler, if it's not running.
916 if (idler
.state
== false) {
918 idler
.idlerID
= reinterpret_cast<IdlerID
>
919 (gtk_idle_add((GtkFunction
)IdleCallback
, this));
922 // Stop idler, if it's running
923 if (idler
.state
== true) {
925 gtk_idle_remove(GPOINTER_TO_UINT(idler
.idlerID
));
931 void ScintillaGTK::SetMouseCapture(bool on
) {
932 if (mouseDownCaptures
) {
934 gtk_grab_add(GTK_WIDGET(PWidget(wMain
)));
936 gtk_grab_remove(GTK_WIDGET(PWidget(wMain
)));
942 bool ScintillaGTK::HaveMouseCapture() {
943 return capturedMouse
;
946 // Redraw all of text area. This paint will not be abandoned.
947 void ScintillaGTK::FullPaint() {
948 #if GTK_MAJOR_VERSION < 2
949 paintState
= painting
;
950 rcPaint
= GetClientRectangle();
951 //Platform::DebugPrintf("ScintillaGTK::FullPaint %0d,%0d %0d,%0d\n",
952 // rcPaint.left, rcPaint.top, rcPaint.right, rcPaint.bottom);
953 paintingAllText
= true;
954 if ((PWidget(wText
))->window
) {
955 Surface
*sw
= Surface::Allocate();
957 sw
->Init(PWidget(wText
)->window
, PWidget(wText
));
963 paintState
= notPainting
;
965 wText
.InvalidateAll();
969 PRectangle
ScintillaGTK::GetClientRectangle() {
970 PRectangle rc
= wMain
.GetClientPosition();
971 if (verticalScrollBarVisible
)
972 rc
.right
-= scrollBarWidth
;
973 if (horizontalScrollBarVisible
&& (wrapState
== eWrapNone
))
974 rc
.bottom
-= scrollBarHeight
;
983 // Synchronously paint a rectangle of the window.
984 void ScintillaGTK::SyncPaint(PRectangle rc
) {
985 paintState
= painting
;
987 PRectangle rcClient
= GetClientRectangle();
988 paintingAllText
= rcPaint
.Contains(rcClient
);
989 if ((PWidget(wText
))->window
) {
990 Surface
*sw
= Surface::Allocate();
992 sw
->Init(PWidget(wText
)->window
, PWidget(wText
));
998 if (paintState
== paintAbandoned
) {
999 // Painting area was insufficient to cover new styling or brace highlight positions
1002 paintState
= notPainting
;
1005 void ScintillaGTK::ScrollText(int linesToMove
) {
1006 int diff
= vs
.lineHeight
* -linesToMove
;
1007 //Platform::DebugPrintf("ScintillaGTK::ScrollText %d %d %0d,%0d %0d,%0d\n", linesToMove, diff,
1008 // rc.left, rc.top, rc.right, rc.bottom);
1009 GtkWidget
*wi
= PWidget(wText
);
1011 #if GTK_MAJOR_VERSION < 2
1012 PRectangle rc
= GetClientRectangle();
1013 GdkGC
*gc
= gdk_gc_new(wi
->window
);
1015 // Set up gc so we get GraphicsExposures from gdk_draw_pixmap
1016 // which calls XCopyArea
1017 gdk_gc_set_exposures(gc
, TRUE
);
1019 // Redraw exposed bit : scrolling upwards
1021 gdk_draw_pixmap(wi
->window
,
1025 rc
.Width()-1, rc
.Height() - diff
);
1026 SyncPaint(PRectangle(0, rc
.Height() - diff
,
1027 rc
.Width(), rc
.Height()+1));
1029 // Redraw exposed bit : scrolling downwards
1031 gdk_draw_pixmap(wi
->window
,
1035 rc
.Width()-1, rc
.Height() + diff
);
1036 SyncPaint(PRectangle(0, 0, rc
.Width(), -diff
));
1039 // Look for any graphics expose
1041 while ((event
= gdk_event_get_graphics_expose(wi
->window
)) != NULL
) {
1042 gtk_widget_event(wi
, event
);
1043 if (event
->expose
.count
== 0) {
1044 gdk_event_free(event
);
1047 gdk_event_free(event
);
1052 gdk_window_scroll(wi
->window
, 0, -diff
);
1053 gdk_window_process_updates(wi
->window
, FALSE
);
1057 void ScintillaGTK::SetVerticalScrollPos() {
1058 gtk_adjustment_set_value(GTK_ADJUSTMENT(adjustmentv
), topLine
);
1061 void ScintillaGTK::SetHorizontalScrollPos() {
1062 gtk_adjustment_set_value(GTK_ADJUSTMENT(adjustmenth
), xOffset
/ 2);
1065 bool ScintillaGTK::ModifyScrollBars(int nMax
, int nPage
) {
1066 bool modified
= false;
1067 int pageScroll
= LinesToScroll();
1069 if (GTK_ADJUSTMENT(adjustmentv
)->upper
!= (nMax
+ 1) ||
1070 GTK_ADJUSTMENT(adjustmentv
)->page_size
!= nPage
||
1071 GTK_ADJUSTMENT(adjustmentv
)->page_increment
!= pageScroll
) {
1072 GTK_ADJUSTMENT(adjustmentv
)->upper
= nMax
+ 1;
1073 GTK_ADJUSTMENT(adjustmentv
)->page_size
= nPage
;
1074 GTK_ADJUSTMENT(adjustmentv
)->page_increment
= pageScroll
;
1075 gtk_adjustment_changed(GTK_ADJUSTMENT(adjustmentv
));
1079 PRectangle rcText
= GetTextRectangle();
1080 int horizEndPreferred
= scrollWidth
;
1081 if (horizEndPreferred
< 0)
1082 horizEndPreferred
= 0;
1083 unsigned int pageWidth
= rcText
.Width();
1084 if (GTK_ADJUSTMENT(adjustmenth
)->upper
!= horizEndPreferred
||
1085 GTK_ADJUSTMENT(adjustmenth
)->page_size
!= pageWidth
) {
1086 GTK_ADJUSTMENT(adjustmenth
)->upper
= horizEndPreferred
;
1087 GTK_ADJUSTMENT(adjustmenth
)->page_size
= pageWidth
;
1088 gtk_adjustment_changed(GTK_ADJUSTMENT(adjustmenth
));
1094 void ScintillaGTK::ReconfigureScrollBars() {
1095 PRectangle rc
= wMain
.GetClientPosition();
1096 Resize(rc
.Width(), rc
.Height());
1099 void ScintillaGTK::NotifyChange() {
1100 gtk_signal_emit(GTK_OBJECT(sci
), scintilla_signals
[COMMAND_SIGNAL
],
1101 Platform::LongFromTwoShorts(GetCtrlID(), SCEN_CHANGE
), PWidget(wMain
));
1104 void ScintillaGTK::NotifyFocus(bool focus
) {
1105 gtk_signal_emit(GTK_OBJECT(sci
), scintilla_signals
[COMMAND_SIGNAL
],
1106 Platform::LongFromTwoShorts(GetCtrlID(), focus
? SCEN_SETFOCUS
: SCEN_KILLFOCUS
), PWidget(wMain
));
1109 void ScintillaGTK::NotifyParent(SCNotification scn
) {
1110 scn
.nmhdr
.hwndFrom
= PWidget(wMain
);
1111 scn
.nmhdr
.idFrom
= GetCtrlID();
1112 gtk_signal_emit(GTK_OBJECT(sci
), scintilla_signals
[NOTIFY_SIGNAL
],
1116 void ScintillaGTK::NotifyKey(int key
, int modifiers
) {
1118 scn
.nmhdr
.code
= SCN_KEY
;
1120 scn
.modifiers
= modifiers
;
1125 void ScintillaGTK::NotifyURIDropped(const char *list
) {
1127 scn
.nmhdr
.code
= SCN_URIDROPPED
;
1133 bool ScintillaGTK::UseInputMethod() const {
1134 switch (vs
.styles
[STYLE_DEFAULT
].characterSet
) {
1135 case SC_CHARSET_CHINESEBIG5
:
1136 case SC_CHARSET_GB2312
:
1137 case SC_CHARSET_HANGUL
:
1138 case SC_CHARSET_SHIFTJIS
:
1139 case SC_CHARSET_JOHAB
:
1140 case SC_CHARSET_HEBREW
:
1141 case SC_CHARSET_ARABIC
:
1142 case SC_CHARSET_VIETNAMESE
:
1143 case SC_CHARSET_THAI
:
1150 const char *CharacterSetID(int characterSet
);
1152 const char *ScintillaGTK::CharacterSetID() const {
1153 return ::CharacterSetID(vs
.styles
[STYLE_DEFAULT
].characterSet
);
1156 #if GTK_MAJOR_VERSION >= 2
1158 ((x) >= 65103 && (x) <= 65111)
1159 #define IS_CHAR(x) \
1160 ((x) >= 0 && (x) <= 128)
1162 #define IS_ACC_OR_CHAR(x) \
1163 (IS_CHAR(x)) || (IS_ACC(x))
1166 ((x) >= 65103 && (x) <= 65111)
1167 #define IS_CHAR(x) \
1168 ((x) >= 0 && (x) <= 128)
1170 #define IS_ACC_OR_CHAR(x) \
1171 (IS_CHAR(x)) || (IS_ACC(x))
1173 static int MakeAccent(int key
, int acc
) {
1174 const char *conv
[] = {
1183 for (idx
= 0; idx
< 15; ++idx
) {
1184 if (char(key
) == conv
[0][idx
]) {
1191 if (acc
== GDK_dead_tilde
) { // ~
1192 return int((unsigned char)(conv
[1][idx
]));
1193 } else if (acc
== GDK_dead_acute
) { // '
1194 return int((unsigned char)(conv
[2][idx
]));
1195 } else if (acc
== GDK_dead_grave
) { // `
1196 return int((unsigned char)(conv
[3][idx
]));
1197 } else if (acc
== GDK_dead_circumflex
) { // ^
1198 return int((unsigned char)(conv
[4][idx
]));
1199 } else if (acc
== GDK_dead_diaeresis
) { // "
1200 return int((unsigned char)(conv
[5][idx
]));
1206 int ScintillaGTK::KeyDefault(int key
, int modifiers
) {
1207 if (!(modifiers
& SCI_CTRL
) && !(modifiers
& SCI_ALT
)) {
1208 #if GTK_MAJOR_VERSION >= 2
1209 if (!UseInputMethod()) {
1210 char utfVal
[4]="\0\0\0";
1212 if (IS_CHAR(key
) && IS_ACC(lastKey
)) {
1213 lastKey
= key
= MakeAccent(key
, lastKey
);
1215 if (IS_ACC_OR_CHAR(key
)) {
1218 wcs
[0] = gdk_keyval_to_unicode(key
);
1220 UTF8FromUCS2(wcs
, 1, utfVal
, 3);
1221 if (key
<= 0xFE00) {
1222 if (IsUnicodeMode()) {
1223 AddCharUTF(utfVal
,strlen(utfVal
));
1226 const char *source
= CharacterSetID();
1228 Converter
conv(source
, "UTF-8");
1230 char localeVal
[4]="\0\0\0";
1232 size_t inLeft
= strlen(utfVal
);
1233 char *pout
= localeVal
;
1234 size_t outLeft
= sizeof(localeVal
);
1235 size_t conversions
= conv
.Convert(&pin
, &inLeft
, &pout
, &outLeft
);
1236 if (conversions
!= ((size_t)(-1))) {
1238 for (int i
=0; localeVal
[i
]; i
++) {
1239 AddChar(localeVal
[i
]);
1253 // Pass up to container in case it is an accelerator
1254 NotifyKey(key
, modifiers
);
1258 // Pass up to container in case it is an accelerator
1259 NotifyKey(key
, modifiers
);
1262 //Platform::DebugPrintf("SK-key: %d %x %x\n",key, modifiers);
1265 void ScintillaGTK::CopyToClipboard(const SelectionText
&selectedText
) {
1266 #ifndef USE_GTK_CLIPBOARD
1267 copyText
.Copy(selectedText
);
1268 gtk_selection_owner_set(GTK_WIDGET(PWidget(wMain
)),
1272 GtkClipboard
*clipBoard
;
1273 clipBoard
= gtk_widget_get_clipboard(GTK_WIDGET(PWidget(wMain
)), atomClipboard
);
1274 if (clipBoard
== NULL
) // Occurs if widget isn't in a toplevel
1277 SelectionText
*clipText
= new SelectionText();
1278 clipText
->Copy(selectedText
);
1280 gtk_clipboard_set_with_data(clipBoard
, clipboardTargets
, nClipboardTargets
,
1281 ClipboardGetSelection
, ClipboardClearSelection
, clipText
);
1286 void ScintillaGTK::Copy() {
1287 if (currentPos
!= anchor
) {
1288 #ifndef USE_GTK_CLIPBOARD
1289 CopySelectionRange(©Text
);
1290 gtk_selection_owner_set(GTK_WIDGET(PWidget(wMain
)),
1294 GtkClipboard
*clipBoard
;
1295 clipBoard
= gtk_widget_get_clipboard(GTK_WIDGET(PWidget(wMain
)), atomClipboard
);
1296 if (clipBoard
== NULL
) // Occurs if widget isn't in a toplevel
1299 SelectionText
*clipText
= new SelectionText();
1300 CopySelectionRange(clipText
);
1302 gtk_clipboard_set_with_data(clipBoard
, clipboardTargets
, nClipboardTargets
,
1303 ClipboardGetSelection
, ClipboardClearSelection
, clipText
);
1307 if (selType
== selRectangle
) {
1308 ::OpenClipboard(NULL
);
1309 ::SetClipboardData(cfColumnSelect
, 0);
1316 void ScintillaGTK::Paste() {
1317 atomSought
= atomUTF8
;
1318 gtk_selection_convert(GTK_WIDGET(PWidget(wMain
)),
1319 atomClipboard
, atomSought
, GDK_CURRENT_TIME
);
1322 void ScintillaGTK::CreateCallTipWindow(PRectangle rc
) {
1323 if (!ct
.wCallTip
.Created()) {
1324 ct
.wCallTip
= gtk_window_new(GTK_WINDOW_POPUP
);
1325 ct
.wDraw
= gtk_drawing_area_new();
1326 gtk_container_add(GTK_CONTAINER(PWidget(ct
.wCallTip
)), PWidget(ct
.wDraw
));
1327 gtk_signal_connect(GTK_OBJECT(PWidget(ct
.wDraw
)), "expose_event",
1328 GtkSignalFunc(ScintillaGTK::ExposeCT
), &ct
);
1329 gtk_signal_connect(GTK_OBJECT(PWidget(ct
.wDraw
)), "button_press_event",
1330 GtkSignalFunc(ScintillaGTK::PressCT
), static_cast<void *>(this));
1331 gtk_widget_set_events(PWidget(ct
.wDraw
),
1332 GDK_EXPOSURE_MASK
| GDK_BUTTON_PRESS_MASK
);
1334 gtk_drawing_area_size(GTK_DRAWING_AREA(PWidget(ct
.wDraw
)),
1335 rc
.Width(), rc
.Height());
1337 //ct.wCallTip.Show();
1338 //gtk_widget_set_usize(PWidget(ct.wCallTip), rc.Width(), rc.Height());
1339 gdk_window_resize(PWidget(ct
.wCallTip
)->window
, rc
.Width(), rc
.Height());
1342 void ScintillaGTK::AddToPopUp(const char *label
, int cmd
, bool enabled
) {
1343 char fulllabel
[200];
1344 strcpy(fulllabel
, "/");
1345 strcat(fulllabel
, label
);
1346 GtkItemFactoryCallback menuSig
= GtkItemFactoryCallback(PopUpCB
);
1347 GtkItemFactoryEntry itemEntry
= {
1351 const_cast<gchar
*>(label
[0] ? "<Item>" : "<Separator>"),
1352 #if GTK_MAJOR_VERSION >= 2
1356 gtk_item_factory_create_item(GTK_ITEM_FACTORY(popup
.GetID()),
1357 &itemEntry
, this, 1);
1359 GtkWidget
*item
= gtk_item_factory_get_widget_by_action(
1360 reinterpret_cast<GtkItemFactory
*>(popup
.GetID()), cmd
);
1362 gtk_widget_set_sensitive(item
, enabled
);
1366 bool ScintillaGTK::OwnPrimarySelection() {
1367 return ((gdk_selection_owner_get(GDK_SELECTION_PRIMARY
)
1368 == GTK_WIDGET(PWidget(wMain
))->window
) &&
1369 (GTK_WIDGET(PWidget(wMain
))->window
!= NULL
));
1372 void ScintillaGTK::ClaimSelection() {
1373 // X Windows has a 'primary selection' as well as the clipboard.
1374 // Whenever the user selects some text, we become the primary selection
1375 if (currentPos
!= anchor
) {
1376 primarySelection
= true;
1377 gtk_selection_owner_set(GTK_WIDGET(PWidget(wMain
)),
1378 GDK_SELECTION_PRIMARY
, GDK_CURRENT_TIME
);
1380 } else if (OwnPrimarySelection()) {
1381 primarySelection
= true;
1382 if (primary
.s
== NULL
)
1383 gtk_selection_owner_set(NULL
, GDK_SELECTION_PRIMARY
, GDK_CURRENT_TIME
);
1385 primarySelection
= false;
1390 // Detect rectangular text, convert line ends to current mode, convert from or to UTF-8
1391 void ScintillaGTK::GetGtkSelectionText(GtkSelectionData
*selectionData
, SelectionText
&selText
) {
1392 char *data
= reinterpret_cast<char *>(selectionData
->data
);
1393 int len
= selectionData
->length
;
1394 GdkAtom selectionType
= selectionData
->type
;
1396 // Return empty string if selection is not a string
1397 if ((selectionType
!= GDK_TARGET_STRING
) && (selectionType
!= atomUTF8
)) {
1398 char *empty
= new char[1];
1400 selText
.Set(empty
, 0, SC_CP_UTF8
, 0, false);
1404 // Check for "\n\0" ending to string indicating that selection is rectangular
1407 isRectangular
= ::IsClipboardFormatAvailable(cfColumnSelect
) != 0;
1409 isRectangular
= ((len
> 2) && (data
[len
- 1] == 0 && data
[len
- 2] == '\n'));
1413 if (selectionType
== GDK_TARGET_STRING
) {
1414 dest
= Document::TransformLineEnds(&len
, data
, len
, pdoc
->eolMode
);
1415 if (IsUnicodeMode()) {
1416 // Unknown encoding so assume in Latin1
1417 char *destPrevious
= dest
;
1418 dest
= UTF8FromLatin1(dest
, len
);
1419 selText
.Set(dest
, len
, SC_CP_UTF8
, 0, selText
.rectangular
);
1420 delete []destPrevious
;
1422 // Assume buffer is in same encoding as selection
1423 selText
.Set(dest
, len
, pdoc
->dbcsCodePage
,
1424 vs
.styles
[STYLE_DEFAULT
].characterSet
, isRectangular
);
1427 dest
= Document::TransformLineEnds(&len
, data
, len
, pdoc
->eolMode
);
1428 selText
.Set(dest
, len
, SC_CP_UTF8
, 0, isRectangular
);
1429 #ifdef USE_CONVERTER
1430 const char *charSetBuffer
= CharacterSetID();
1431 if (!IsUnicodeMode() && *charSetBuffer
) {
1432 //fprintf(stderr, "Convert to locale %s\n", CharacterSetID());
1433 // Convert to locale
1434 dest
= ConvertText(&len
, selText
.s
, selText
.len
, charSetBuffer
, "UTF-8");
1435 selText
.Set(dest
, len
, pdoc
->dbcsCodePage
,
1436 vs
.styles
[STYLE_DEFAULT
].characterSet
, selText
.rectangular
);
1442 void ScintillaGTK::ReceivedSelection(GtkSelectionData
*selection_data
) {
1443 if ((selection_data
->selection
== atomClipboard
) ||
1444 (selection_data
->selection
== GDK_SELECTION_PRIMARY
)) {
1445 if ((atomSought
== atomUTF8
) && (selection_data
->length
<= 0)) {
1446 atomSought
= atomString
;
1447 gtk_selection_convert(GTK_WIDGET(PWidget(wMain
)),
1448 selection_data
->selection
, atomSought
, GDK_CURRENT_TIME
);
1449 } else if ((selection_data
->length
> 0) &&
1450 ((selection_data
->type
== GDK_TARGET_STRING
) || (selection_data
->type
== atomUTF8
))) {
1451 SelectionText selText
;
1452 GetGtkSelectionText(selection_data
, selText
);
1454 pdoc
->BeginUndoAction();
1455 int selStart
= SelectionStart();
1456 if (selection_data
->selection
!= GDK_SELECTION_PRIMARY
) {
1460 if (selText
.rectangular
) {
1461 PasteRectangular(selStart
, selText
.s
, selText
.len
);
1463 pdoc
->InsertString(currentPos
, selText
.s
, selText
.len
);
1464 SetEmptySelection(currentPos
+ selText
.len
);
1466 pdoc
->EndUndoAction();
1469 // else fprintf(stderr, "Target non string %d %d\n", (int)(selection_data->type),
1470 // (int)(atomUTF8));
1474 void ScintillaGTK::ReceivedDrop(GtkSelectionData
*selection_data
) {
1475 dragWasDropped
= true;
1476 if ((selection_data
->type
== GDK_TARGET_STRING
) || (selection_data
->type
== atomUTF8
)) {
1477 if (selection_data
->length
> 0) {
1478 SelectionText selText
;
1479 GetGtkSelectionText(selection_data
, selText
);
1480 DropAt(posDrop
, selText
.s
, false, selText
.rectangular
);
1483 char *ptr
= reinterpret_cast<char *>(selection_data
->data
);
1484 NotifyURIDropped(ptr
);
1491 void ScintillaGTK::GetSelection(GtkSelectionData
*selection_data
, guint info
, SelectionText
*text
) {
1492 #if GTK_MAJOR_VERSION >= 2
1493 // Convert text to utf8 if it isn't already
1494 SelectionText
*converted
= 0;
1495 if ((text
->codePage
!= SC_CP_UTF8
) && (info
== TARGET_UTF8_STRING
)) {
1496 const char *charSet
= ::CharacterSetID(text
->characterSet
);
1499 char* tmputf
= ConvertText(&new_len
, text
->s
, text
->len
, "UTF-8", charSet
);
1500 converted
= new SelectionText();
1501 converted
->Set(tmputf
, new_len
, SC_CP_UTF8
, 0, text
->rectangular
);
1506 // Here is a somewhat evil kludge.
1507 // As I can not work out how to store data on the clipboard in multiple formats
1508 // and need some way to mark the clipping as being stream or rectangular,
1509 // the terminating \0 is included in the length for rectangular clippings.
1510 // All other tested aplications behave benignly by ignoring the \0.
1511 // The #if is here because on Windows cfColumnSelect clip entry is used
1512 // instead as standard indicator of rectangularness (so no need to kludge)
1513 int len
= strlen(text
->s
);
1514 #if PLAT_GTK_WIN32 == 0
1515 if (text
->rectangular
)
1519 if (info
== TARGET_UTF8_STRING
) {
1520 gtk_selection_data_set_text(selection_data
, text
->s
, len
);
1522 gtk_selection_data_set(selection_data
,
1523 static_cast<GdkAtom
>(GDK_SELECTION_TYPE_STRING
),
1524 8, reinterpret_cast<unsigned char *>(text
->s
), len
);
1529 char *selBuffer
= text
->s
;
1533 // Many native win32 programs require \n line endings,
1534 // so make a copy of the clip text now with newlines converted
1537 char *tmpstr
= Document::TransformLineEnds(&new_len
, selBuffer
, text
->len
, SC_EOL_LF
);
1541 if ((info
== TARGET_UTF8_STRING
) || (info
== TARGET_STRING
)) {
1542 int len
= strlen(selBuffer
);
1543 #ifdef USE_CONVERTER
1544 // Possible character set conversion
1545 const char *charSetBuffer
= ::CharacterSetID(text
->characterSet
);
1546 if (info
== TARGET_UTF8_STRING
) {
1547 //fprintf(stderr, "Copy to clipboard as UTF-8\n");
1548 if (text
->codePage
!= SC_CP_UTF8
) {
1550 //fprintf(stderr, "Convert to UTF-8 from %s\n", charSetBuffer);
1551 tmputf
= ConvertText(&len
, selBuffer
, len
, "UTF-8", charSetBuffer
);
1554 } else if (info
== TARGET_STRING
) {
1555 if (text
->codePage
== SC_CP_UTF8
) {
1556 //fprintf(stderr, "Convert to locale %s\n", charSetBuffer);
1557 // Convert to locale
1558 tmputf
= ConvertText(&len
, selBuffer
, len
, charSetBuffer
, "UTF-8");
1564 // Here is a somewhat evil kludge.
1565 // As I can not work out how to store data on the clipboard in multiple formats
1566 // and need some way to mark the clipping as being stream or rectangular,
1567 // the terminating \0 is included in the length for rectangular clippings.
1568 // All other tested aplications behave benignly by ignoring the \0.
1569 // The #if is here because on Windows cfColumnSelect clip entry is used
1570 // instead as standard indicator of rectangularness (so no need to kludge)
1571 #if PLAT_GTK_WIN32 == 0
1572 if (text
->rectangular
)
1575 gtk_selection_data_set(selection_data
,
1576 (info
== TARGET_STRING
) ?
1577 static_cast<GdkAtom
>(GDK_SELECTION_TYPE_STRING
) : atomUTF8
,
1578 8, reinterpret_cast<unsigned char *>(selBuffer
),
1580 } else if ((info
== TARGET_TEXT
) || (info
== TARGET_COMPOUND_TEXT
)) {
1586 gdk_string_to_compound_text(reinterpret_cast<char *>(selBuffer
),
1587 &encoding
, &format
, &text
, &new_length
);
1588 gtk_selection_data_set(selection_data
, encoding
, format
, text
, new_length
);
1589 gdk_free_compound_text(text
);
1596 #endif /* Gtk >= 2 */
1599 #ifdef USE_GTK_CLIPBOARD
1600 void ScintillaGTK::ClipboardGetSelection(GtkClipboard
*, GtkSelectionData
*selection_data
, guint info
, void *data
) {
1601 GetSelection(selection_data
, info
, static_cast<SelectionText
*>(data
));
1604 void ScintillaGTK::ClipboardClearSelection(GtkClipboard
*, void *data
) {
1605 SelectionText
*obj
= static_cast<SelectionText
*>(data
);
1610 void ScintillaGTK::UnclaimSelection(GdkEventSelection
*selection_event
) {
1611 //Platform::DebugPrintf("UnclaimSelection\n");
1612 if (selection_event
->selection
== GDK_SELECTION_PRIMARY
) {
1613 //Platform::DebugPrintf("UnclaimPrimarySelection\n");
1614 if (!OwnPrimarySelection()) {
1616 primarySelection
= false;
1622 void ScintillaGTK::Resize(int width
, int height
) {
1623 //Platform::DebugPrintf("Resize %d %d\n", width, height);
1624 //printf("Resize %d %d\n", width, height);
1626 // Not always needed, but some themes can have different sizes of scrollbars
1627 scrollBarWidth
= GTK_WIDGET(PWidget(scrollbarv
))->requisition
.width
;
1628 scrollBarHeight
= GTK_WIDGET(PWidget(scrollbarh
))->requisition
.height
;
1630 // These allocations should never produce negative sizes as they would wrap around to huge
1631 // unsigned numbers inside GTK+ causing warnings.
1632 bool showSBHorizontal
= horizontalScrollBarVisible
&& (wrapState
== eWrapNone
);
1633 int horizontalScrollBarHeight
= scrollBarHeight
;
1634 if (!showSBHorizontal
)
1635 horizontalScrollBarHeight
= 0;
1636 int verticalScrollBarHeight
= scrollBarWidth
;
1637 if (!verticalScrollBarVisible
)
1638 verticalScrollBarHeight
= 0;
1640 GtkAllocation alloc
;
1642 if (showSBHorizontal
) {
1643 alloc
.y
= height
- scrollBarHeight
;
1644 alloc
.width
= Platform::Maximum(1, width
- scrollBarWidth
) + 1;
1645 alloc
.height
= horizontalScrollBarHeight
;
1647 alloc
.y
= -scrollBarHeight
;
1651 gtk_widget_size_allocate(GTK_WIDGET(PWidget(scrollbarh
)), &alloc
);
1654 if (verticalScrollBarVisible
) {
1655 alloc
.x
= width
- scrollBarWidth
;
1656 alloc
.width
= scrollBarWidth
;
1657 alloc
.height
= Platform::Maximum(1, height
- scrollBarHeight
) + 1;
1658 if (!showSBHorizontal
)
1659 alloc
.height
+= scrollBarWidth
-1;
1661 alloc
.x
= -scrollBarWidth
;
1665 gtk_widget_size_allocate(GTK_WIDGET(PWidget(scrollbarv
)), &alloc
);
1666 if (GTK_WIDGET_MAPPED(PWidget(wMain
))) {
1672 alloc
.width
= Platform::Maximum(1, width
- scrollBarWidth
);
1673 alloc
.height
= Platform::Maximum(1, height
- scrollBarHeight
);
1674 if (!showSBHorizontal
)
1675 alloc
.height
+= scrollBarWidth
;
1676 gtk_widget_size_allocate(GTK_WIDGET(PWidget(wText
)), &alloc
);
1679 static void SetAdjustmentValue(GtkObject
*object
, int value
) {
1680 GtkAdjustment
*adjustment
= GTK_ADJUSTMENT(object
);
1681 int maxValue
= static_cast<int>(
1682 adjustment
->upper
- adjustment
->page_size
);
1683 if (value
> maxValue
)
1687 gtk_adjustment_set_value(adjustment
, value
);
1690 gint
ScintillaGTK::PressThis(GdkEventButton
*event
) {
1691 //Platform::DebugPrintf("Press %x time=%d state = %x button = %x\n",this,event->time, event->state, event->button);
1692 // Do not use GTK+ double click events as Scintilla has its own double click detection
1693 if (event
->type
!= GDK_BUTTON_PRESS
)
1698 pt
.x
= int(event
->x
);
1699 pt
.y
= int(event
->y
);
1700 PRectangle rcClient
= GetClientRectangle();
1701 //Platform::DebugPrintf("Press %0d,%0d in %0d,%0d %0d,%0d\n",
1702 // pt.x, pt.y, rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
1703 if ((pt
.x
> rcClient
.right
) || (pt
.y
> rcClient
.bottom
)) {
1704 Platform::DebugPrintf("Bad location\n");
1708 bool ctrl
= (event
->state
& GDK_CONTROL_MASK
) != 0;
1710 gtk_widget_grab_focus(PWidget(wMain
));
1711 if (event
->button
== 1) {
1712 // On X, instead of sending literal modifiers use control instead of alt
1713 // This is because most X window managers grab alt + click for moving
1715 ButtonDown(pt
, event
->time
,
1716 (event
->state
& GDK_SHIFT_MASK
) != 0,
1717 (event
->state
& GDK_CONTROL_MASK
) != 0,
1718 (event
->state
& GDK_CONTROL_MASK
) != 0);
1720 ButtonDown(pt
, event
->time
,
1721 (event
->state
& GDK_SHIFT_MASK
) != 0,
1722 (event
->state
& GDK_CONTROL_MASK
) != 0,
1723 (event
->state
& GDK_MOD1_MASK
) != 0);
1725 } else if (event
->button
== 2) {
1726 // Grab the primary selection if it exists
1727 Position pos
= PositionFromLocation(pt
);
1728 if (OwnPrimarySelection() && primary
.s
== NULL
)
1729 CopySelectionRange(&primary
);
1731 SetSelection(pos
, pos
);
1732 atomSought
= atomUTF8
;
1733 gtk_selection_convert(GTK_WIDGET(PWidget(wMain
)), GDK_SELECTION_PRIMARY
,
1734 atomSought
, event
->time
);
1735 } else if (event
->button
== 3) {
1736 if (displayPopupMenu
) {
1738 // Convert to screen
1741 gdk_window_get_origin(PWidget(wMain
)->window
, &ox
, &oy
);
1742 ContextMenu(Point(pt
.x
+ ox
, pt
.y
+ oy
));
1746 } else if (event
->button
== 4) {
1747 // Wheel scrolling up (only xwin gtk does it this way)
1749 SetAdjustmentValue(adjustmenth
, (xOffset
/ 2) - 6);
1751 SetAdjustmentValue(adjustmentv
, topLine
- 3);
1752 } else if (event
->button
== 5) {
1753 // Wheel scrolling down (only xwin gtk does it this way)
1755 SetAdjustmentValue(adjustmenth
, (xOffset
/ 2) + 6);
1757 SetAdjustmentValue(adjustmentv
, topLine
+ 3);
1759 #if GTK_MAJOR_VERSION >= 2
1766 gint
ScintillaGTK::Press(GtkWidget
*widget
, GdkEventButton
*event
) {
1767 if (event
->window
!= widget
->window
)
1769 ScintillaGTK
*sciThis
= ScintillaFromWidget(widget
);
1770 return sciThis
->PressThis(event
);
1773 gint
ScintillaGTK::MouseRelease(GtkWidget
*widget
, GdkEventButton
*event
) {
1774 ScintillaGTK
*sciThis
= ScintillaFromWidget(widget
);
1775 //Platform::DebugPrintf("Release %x %d %d\n",sciThis,event->time,event->state);
1776 if (!sciThis
->HaveMouseCapture())
1778 if (event
->button
== 1) {
1780 pt
.x
= int(event
->x
);
1781 pt
.y
= int(event
->y
);
1782 //Platform::DebugPrintf("Up %x %x %d %d %d\n",
1783 // sciThis,event->window,event->time, pt.x, pt.y);
1784 if (event
->window
!= PWidget(sciThis
->wMain
)->window
)
1785 // If mouse released on scroll bar then the position is relative to the
1786 // scrollbar, not the drawing window so just repeat the most recent point.
1787 pt
= sciThis
->ptMouseLast
;
1788 sciThis
->ButtonUp(pt
, event
->time
, (event
->state
& 4) != 0);
1793 // win32gtk has a special wheel mouse event for whatever reason and doesn't
1794 // use the button4/5 trick used under X windows.
1795 #if PLAT_GTK_WIN32 || (GTK_MAJOR_VERSION >= 2)
1796 gint
ScintillaGTK::ScrollEvent(GtkWidget
*widget
,
1797 GdkEventScroll
*event
) {
1798 ScintillaGTK
*sciThis
= ScintillaFromWidget(widget
);
1800 if (widget
== NULL
|| event
== NULL
)
1803 // Compute amount and direction to scroll (even tho on win32 there is
1804 // intensity of scrolling info in the native message, gtk doesn't
1805 // support this so we simulate similarly adaptive scrolling)
1807 int timeDelta
= 1000000;
1809 g_get_current_time(&curTime
);
1810 if (curTime
.tv_sec
== sciThis
->lastWheelMouseTime
.tv_sec
)
1811 timeDelta
= curTime
.tv_usec
- sciThis
->lastWheelMouseTime
.tv_usec
;
1812 else if (curTime
.tv_sec
== sciThis
->lastWheelMouseTime
.tv_sec
+ 1)
1813 timeDelta
= 1000000 + (curTime
.tv_usec
- sciThis
->lastWheelMouseTime
.tv_usec
);
1814 if ((event
->direction
== sciThis
->lastWheelMouseDirection
) && (timeDelta
< 250000)) {
1815 if (sciThis
->wheelMouseIntensity
< 12)
1816 sciThis
->wheelMouseIntensity
++;
1817 cLineScroll
= sciThis
->wheelMouseIntensity
;
1819 cLineScroll
= sciThis
->linesPerScroll
;
1820 if (cLineScroll
== 0)
1822 sciThis
->wheelMouseIntensity
= cLineScroll
;
1824 if (event
->direction
== GDK_SCROLL_UP
) {
1827 g_get_current_time(&sciThis
->lastWheelMouseTime
);
1828 sciThis
->lastWheelMouseDirection
= event
->direction
;
1830 // Note: Unpatched versions of win32gtk don't set the 'state' value so
1831 // only regular scrolling is supported there. Also, unpatched win32gtk
1832 // issues spurious button 2 mouse events during wheeling, which can cause
1833 // problems (a patch for both was submitted by archaeopteryx.com on 13Jun2001)
1835 // Data zoom not supported
1836 if (event
->state
& GDK_SHIFT_MASK
) {
1840 // Text font size zoom
1841 if (event
->state
& GDK_CONTROL_MASK
) {
1842 if (cLineScroll
< 0) {
1843 sciThis
->KeyCommand(SCI_ZOOMIN
);
1846 sciThis
->KeyCommand(SCI_ZOOMOUT
);
1850 // Regular scrolling
1852 sciThis
->ScrollTo(sciThis
->topLine
+ cLineScroll
);
1858 gint
ScintillaGTK::Motion(GtkWidget
*widget
, GdkEventMotion
*event
) {
1859 ScintillaGTK
*sciThis
= ScintillaFromWidget(widget
);
1860 //Platform::DebugPrintf("Motion %x %d\n",sciThis,event->time);
1861 if (event
->window
!= widget
->window
)
1865 GdkModifierType state
;
1866 if (event
->is_hint
) {
1867 gdk_window_get_pointer(event
->window
, &x
, &y
, &state
);
1869 x
= static_cast<int>(event
->x
);
1870 y
= static_cast<int>(event
->y
);
1871 state
= static_cast<GdkModifierType
>(event
->state
);
1873 //Platform::DebugPrintf("Move %x %x %d %c %d %d\n",
1874 // sciThis,event->window,event->time,event->is_hint? 'h' :'.', x, y);
1876 sciThis
->ButtonMove(pt
);
1880 // Map the keypad keys to their equivalent functions
1881 static int KeyTranslate(int keyIn
) {
1883 case GDK_ISO_Left_Tab
:
1897 case GDK_KP_Page_Up
:
1899 case GDK_KP_Page_Down
:
1938 case GDK_KP_Subtract
:
1939 return SCK_SUBTRACT
;
1947 gint
ScintillaGTK::KeyThis(GdkEventKey
*event
) {
1948 //Platform::DebugPrintf("SC-key: %d %x [%s]\n",
1949 // event->keyval, event->state, (event->length > 0) ? event->string : "empty");
1950 #if GTK_MAJOR_VERSION >= 2
1951 if (UseInputMethod()) {
1952 if (gtk_im_context_filter_keypress(im_context
, event
)) {
1957 if (!event
->keyval
) {
1961 bool shift
= (event
->state
& GDK_SHIFT_MASK
) != 0;
1962 bool ctrl
= (event
->state
& GDK_CONTROL_MASK
) != 0;
1963 bool alt
= (event
->state
& GDK_MOD1_MASK
) != 0;
1964 int key
= event
->keyval
;
1965 if (ctrl
&& (key
< 128))
1967 else if (!ctrl
&& (key
>= GDK_KP_Multiply
&& key
<= GDK_KP_9
))
1969 // Hack for keys over 256 and below command keys but makes Hungarian work.
1970 // This will have to change for Unicode
1971 else if (key
>= 0xFE00)
1972 key
= KeyTranslate(key
);
1973 else if (IsUnicodeMode())
1975 #if GTK_MAJOR_VERSION < 2
1976 else if ((key
>= 0x100) && (key
< 0x1000))
1980 bool consumed
= false;
1981 bool added
= KeyDown(key
, shift
, ctrl
, alt
, &consumed
) != 0;
1984 //Platform::DebugPrintf("SK-key: %d %x %x\n",event->keyval, event->state, consumed);
1985 if (event
->keyval
== 0xffffff && event
->length
> 0) {
1987 if (pdoc
->InsertString(CurrentPosition(), event
->string
)) {
1988 MovePositionTo(CurrentPosition() + event
->length
);
1994 gint
ScintillaGTK::KeyPress(GtkWidget
*widget
, GdkEventKey
*event
) {
1995 ScintillaGTK
*sciThis
= ScintillaFromWidget(widget
);
1996 return sciThis
->KeyThis(event
);
1999 gint
ScintillaGTK::KeyRelease(GtkWidget
*, GdkEventKey
* /*event*/) {
2000 //Platform::DebugPrintf("SC-keyrel: %d %x %3s\n",event->keyval, event->state, event->string);
2004 #if GTK_MAJOR_VERSION >= 2
2005 gint
ScintillaGTK::ExposePreedit(GtkWidget
*widget
, GdkEventExpose
*ose
, ScintillaGTK
*sciThis
) {
2006 return sciThis
->ExposePreeditThis(widget
, ose
);
2009 gint
ScintillaGTK::ExposePreeditThis(GtkWidget
*widget
, GdkEventExpose
*ose
) {
2012 PangoAttrList
*attrs
;
2014 gtk_im_context_get_preedit_string(im_context
, &str
, &attrs
, &cursor_pos
);
2015 PangoLayout
*layout
= gtk_widget_create_pango_layout(PWidget(wText
), str
);
2016 pango_layout_set_attributes(layout
, attrs
);
2018 GdkGC
*gc
= gdk_gc_new(widget
->window
);
2019 GdkColor color
[2] = { {0, 0x0000, 0x0000, 0x0000},
2020 {0, 0xffff, 0xffff, 0xffff}};
2021 gdk_color_alloc(gdk_colormap_get_system(), color
);
2022 gdk_color_alloc(gdk_colormap_get_system(), color
+ 1);
2024 gdk_gc_set_foreground(gc
, color
+ 1);
2025 gdk_draw_rectangle(widget
->window
, gc
, TRUE
, ose
->area
.x
, ose
->area
.y
,
2026 ose
->area
.width
, ose
->area
.height
);
2028 gdk_gc_set_foreground(gc
, color
);
2029 gdk_gc_set_background(gc
, color
+ 1);
2030 gdk_draw_layout(widget
->window
, gc
, 0, 0, layout
);
2034 pango_attr_list_unref(attrs
);
2035 g_object_unref(layout
);
2039 void ScintillaGTK::Commit(GtkIMContext
*, char *str
, ScintillaGTK
*sciThis
) {
2040 sciThis
->CommitThis(str
);
2043 void ScintillaGTK::CommitThis(char *str
) {
2044 AddCharUTF(str
, strlen(str
));
2047 void ScintillaGTK::PreeditChanged(GtkIMContext
*, ScintillaGTK
*sciThis
) {
2048 sciThis
->PreeditChangedThis();
2051 void ScintillaGTK::PreeditChangedThis() {
2053 PangoAttrList
*attrs
;
2055 gtk_im_context_get_preedit_string(im_context
, &str
, &attrs
, &cursor_pos
);
2056 if (strlen(str
) > 0){
2057 PangoLayout
*layout
= gtk_widget_create_pango_layout(PWidget(wText
), str
);
2058 pango_layout_set_attributes(layout
, attrs
);
2061 pango_layout_get_pixel_size(layout
, &w
, &h
);
2062 g_object_unref(layout
);
2065 gdk_window_get_origin((PWidget(wText
))->window
, &x
, &y
);
2067 Point pt
= LocationFromPosition(currentPos
);
2073 gtk_window_move(GTK_WINDOW(PWidget(wPreedit
)), x
+pt
.x
, y
+pt
.y
);
2074 gtk_window_resize(GTK_WINDOW(PWidget(wPreedit
)), w
, h
);
2075 gtk_widget_show(PWidget(wPreedit
));
2076 gtk_widget_queue_draw_area(PWidget(wPreeditDraw
), 0, 0, w
, h
);
2078 gtk_widget_hide(PWidget(wPreedit
));
2081 pango_attr_list_unref(attrs
);
2085 gint
ScintillaGTK::StyleSetText(GtkWidget
*widget
, GtkStyle
*, void*) {
2086 if (widget
->window
!= NULL
)
2087 gdk_window_set_back_pixmap(widget
->window
, NULL
, FALSE
);
2091 gint
ScintillaGTK::RealizeText(GtkWidget
*widget
, void*) {
2092 if (widget
->window
!= NULL
)
2093 gdk_window_set_back_pixmap(widget
->window
, NULL
, FALSE
);
2097 void ScintillaGTK::Destroy(GtkObject
* object
) {
2098 ScintillaObject
*scio
= reinterpret_cast<ScintillaObject
*>(object
);
2099 // This avoids a double destruction
2102 ScintillaGTK
*sciThis
= reinterpret_cast<ScintillaGTK
*>(scio
->pscin
);
2103 //Platform::DebugPrintf("Destroying %x %x\n", sciThis, object);
2104 sciThis
->Finalise();
2106 if (GTK_OBJECT_CLASS(parent_class
)->destroy
)
2107 (* GTK_OBJECT_CLASS(parent_class
)->destroy
)(object
);
2113 static void DrawChild(GtkWidget
*widget
, GdkRectangle
*area
) {
2114 GdkRectangle areaIntersect
;
2116 GTK_WIDGET_DRAWABLE(widget
) &&
2117 gtk_widget_intersect(widget
, area
, &areaIntersect
)) {
2118 gtk_widget_draw(widget
, &areaIntersect
);
2122 void ScintillaGTK::Draw(GtkWidget
*widget
, GdkRectangle
*area
) {
2123 ScintillaGTK
*sciThis
= ScintillaFromWidget(widget
);
2124 //Platform::DebugPrintf("Draw %p %0d,%0d %0d,%0d\n", widget, area->x, area->y, area->width, area->height);
2125 PRectangle
rcPaint(area
->x
, area
->y
, area
->x
+ area
->width
, area
->y
+ area
->height
);
2126 sciThis
->SyncPaint(rcPaint
);
2127 if (GTK_WIDGET_DRAWABLE(PWidget(sciThis
->wMain
))) {
2128 DrawChild(PWidget(sciThis
->scrollbarh
), area
);
2129 DrawChild(PWidget(sciThis
->scrollbarv
), area
);
2132 #ifdef INTERNATIONAL_INPUT
2133 Point pt
= sciThis
->LocationFromPosition(sciThis
->currentPos
);
2134 pt
.y
+= sciThis
->vs
.lineHeight
- 2;
2135 if (pt
.x
< 0) pt
.x
= 0;
2136 if (pt
.y
< 0) pt
.y
= 0;
2137 CursorMoved(widget
, pt
.x
, pt
.y
, sciThis
);
2141 gint
ScintillaGTK::ExposeTextThis(GtkWidget
* /*widget*/, GdkEventExpose
*ose
) {
2142 paintState
= painting
;
2144 rcPaint
.left
= ose
->area
.x
;
2145 rcPaint
.top
= ose
->area
.y
;
2146 rcPaint
.right
= ose
->area
.x
+ ose
->area
.width
;
2147 rcPaint
.bottom
= ose
->area
.y
+ ose
->area
.height
;
2149 PRectangle rcClient
= GetClientRectangle();
2150 paintingAllText
= rcPaint
.Contains(rcClient
);
2151 Surface
*surfaceWindow
= Surface::Allocate();
2152 if (surfaceWindow
) {
2153 surfaceWindow
->Init(PWidget(wText
)->window
, PWidget(wText
));
2154 Paint(surfaceWindow
, rcPaint
);
2155 surfaceWindow
->Release();
2156 delete surfaceWindow
;
2158 if (paintState
== paintAbandoned
) {
2159 // Painting area was insufficient to cover new styling or brace highlight positions
2162 paintState
= notPainting
;
2166 gint
ScintillaGTK::ExposeText(GtkWidget
*widget
, GdkEventExpose
*ose
, ScintillaGTK
*sciThis
) {
2167 return sciThis
->ExposeTextThis(widget
, ose
);
2170 gint
ScintillaGTK::ExposeMain(GtkWidget
*widget
, GdkEventExpose
*ose
) {
2171 ScintillaGTK
*sciThis
= ScintillaFromWidget(widget
);
2172 //Platform::DebugPrintf("Expose Main %0d,%0d %0d,%0d\n",
2173 //ose->area.x, ose->area.y, ose->area.width, ose->area.height);
2174 return sciThis
->Expose(widget
, ose
);
2177 gint
ScintillaGTK::Expose(GtkWidget
*, GdkEventExpose
*ose
) {
2178 //fprintf(stderr, "Expose %0d,%0d %0d,%0d\n",
2179 //ose->area.x, ose->area.y, ose->area.width, ose->area.height);
2181 #if GTK_MAJOR_VERSION < 2
2183 paintState
= painting
;
2185 rcPaint
.left
= ose
->area
.x
;
2186 rcPaint
.top
= ose
->area
.y
;
2187 rcPaint
.right
= ose
->area
.x
+ ose
->area
.width
;
2188 rcPaint
.bottom
= ose
->area
.y
+ ose
->area
.height
;
2190 PRectangle rcClient
= GetClientRectangle();
2191 paintingAllText
= rcPaint
.Contains(rcClient
);
2192 Surface
*surfaceWindow
= Surface::Allocate();
2193 if (surfaceWindow
) {
2194 surfaceWindow
->Init(PWidget(wMain
)->window
, PWidget(wMain
));
2196 // Fill the corner between the scrollbars
2197 if (verticalScrollBarVisible
) {
2198 if (horizontalScrollBarVisible
&& (wrapState
== eWrapNone
)) {
2199 PRectangle rcCorner
= wMain
.GetClientPosition();
2200 rcCorner
.left
= rcCorner
.right
- scrollBarWidth
+ 1;
2201 rcCorner
.top
= rcCorner
.bottom
- scrollBarHeight
+ 1;
2202 //fprintf(stderr, "Corner %0d,%0d %0d,%0d\n",
2203 //rcCorner.left, rcCorner.top, rcCorner.right, rcCorner.bottom);
2204 surfaceWindow
->FillRectangle(rcCorner
,
2205 vs
.styles
[STYLE_LINENUMBER
].back
.allocated
);
2209 //Paint(surfaceWindow, rcPaint);
2210 surfaceWindow
->Release();
2211 delete surfaceWindow
;
2213 if (paintState
== paintAbandoned
) {
2214 // Painting area was insufficient to cover new styling or brace highlight positions
2217 paintState
= notPainting
;
2220 // For GTK+ 2, the text is painted in ExposeText
2221 gtk_container_propagate_expose(
2222 GTK_CONTAINER(PWidget(wMain
)), PWidget(scrollbarh
), ose
);
2223 gtk_container_propagate_expose(
2224 GTK_CONTAINER(PWidget(wMain
)), PWidget(scrollbarv
), ose
);
2230 void ScintillaGTK::ScrollSignal(GtkAdjustment
*adj
, ScintillaGTK
*sciThis
) {
2231 sciThis
->ScrollTo(static_cast<int>(adj
->value
), false);
2234 void ScintillaGTK::ScrollHSignal(GtkAdjustment
*adj
, ScintillaGTK
*sciThis
) {
2235 sciThis
->HorizontalScrollTo(static_cast<int>(adj
->value
* 2));
2238 void ScintillaGTK::SelectionReceived(GtkWidget
*widget
,
2239 GtkSelectionData
*selection_data
, guint
) {
2240 ScintillaGTK
*sciThis
= ScintillaFromWidget(widget
);
2241 //Platform::DebugPrintf("Selection received\n");
2242 sciThis
->ReceivedSelection(selection_data
);
2245 void ScintillaGTK::SelectionGet(GtkWidget
*widget
,
2246 GtkSelectionData
*selection_data
, guint info
, guint
) {
2247 ScintillaGTK
*sciThis
= ScintillaFromWidget(widget
);
2248 //Platform::DebugPrintf("Selection get\n");
2249 if (selection_data
->selection
== GDK_SELECTION_PRIMARY
) {
2250 if (sciThis
->primary
.s
== NULL
) {
2251 sciThis
->CopySelectionRange(&sciThis
->primary
);
2253 sciThis
->GetSelection(selection_data
, info
, &sciThis
->primary
);
2255 #ifndef USE_GTK_CLIPBOARD
2257 sciThis
->GetSelection(selection_data
, info
, &sciThis
->copyText
);
2262 gint
ScintillaGTK::SelectionClear(GtkWidget
*widget
, GdkEventSelection
*selection_event
) {
2263 ScintillaGTK
*sciThis
= ScintillaFromWidget(widget
);
2264 //Platform::DebugPrintf("Selection clear\n");
2265 sciThis
->UnclaimSelection(selection_event
);
2266 return gtk_selection_clear(widget
, selection_event
);
2269 #if GTK_MAJOR_VERSION < 2
2270 gint
ScintillaGTK::SelectionNotify(GtkWidget
*widget
, GdkEventSelection
*selection_event
) {
2271 //Platform::DebugPrintf("Selection notify\n");
2272 return gtk_selection_notify(widget
, selection_event
);
2276 void ScintillaGTK::DragBegin(GtkWidget
*, GdkDragContext
*) {
2277 //Platform::DebugPrintf("DragBegin\n");
2280 gboolean
ScintillaGTK::DragMotion(GtkWidget
*widget
, GdkDragContext
*context
,
2281 gint x
, gint y
, guint dragtime
) {
2282 ScintillaGTK
*sciThis
= ScintillaFromWidget(widget
);
2283 //Platform::DebugPrintf("DragMotion %d %d %x %x %x\n", x, y,
2284 // context->actions, context->suggested_action, sciThis);
2286 sciThis
->inDragDrop
= true;
2287 sciThis
->SetDragPosition(sciThis
->PositionFromLocation(npt
));
2288 gdk_drag_status(context
, context
->suggested_action
, dragtime
);
2292 void ScintillaGTK::DragLeave(GtkWidget
*widget
, GdkDragContext
* /*context*/, guint
) {
2293 ScintillaGTK
*sciThis
= ScintillaFromWidget(widget
);
2294 sciThis
->SetDragPosition(invalidPosition
);
2295 //Platform::DebugPrintf("DragLeave %x\n", sciThis);
2298 void ScintillaGTK::DragEnd(GtkWidget
*widget
, GdkDragContext
* /*context*/) {
2299 ScintillaGTK
*sciThis
= ScintillaFromWidget(widget
);
2300 // If drag did not result in drop here or elsewhere
2301 if (!sciThis
->dragWasDropped
)
2302 sciThis
->SetEmptySelection(sciThis
->posDrag
);
2303 sciThis
->SetDragPosition(invalidPosition
);
2304 //Platform::DebugPrintf("DragEnd %x %d\n", sciThis, sciThis->dragWasDropped);
2307 gboolean
ScintillaGTK::Drop(GtkWidget
*widget
, GdkDragContext
* /*context*/,
2308 gint
, gint
, guint
) {
2309 ScintillaGTK
*sciThis
= ScintillaFromWidget(widget
);
2310 //Platform::DebugPrintf("Drop %x\n", sciThis);
2311 sciThis
->SetDragPosition(invalidPosition
);
2315 void ScintillaGTK::DragDataReceived(GtkWidget
*widget
, GdkDragContext
* /*context*/,
2316 gint
, gint
, GtkSelectionData
*selection_data
, guint
/*info*/, guint
) {
2317 ScintillaGTK
*sciThis
= ScintillaFromWidget(widget
);
2318 sciThis
->ReceivedDrop(selection_data
);
2319 sciThis
->SetDragPosition(invalidPosition
);
2322 void ScintillaGTK::DragDataGet(GtkWidget
*widget
, GdkDragContext
*context
,
2323 GtkSelectionData
*selection_data
, guint info
, guint
) {
2324 ScintillaGTK
*sciThis
= ScintillaFromWidget(widget
);
2325 sciThis
->dragWasDropped
= true;
2326 if (sciThis
->currentPos
!= sciThis
->anchor
) {
2327 sciThis
->GetSelection(selection_data
, info
, &sciThis
->drag
);
2329 if (context
->action
== GDK_ACTION_MOVE
) {
2330 int selStart
= sciThis
->SelectionStart();
2331 int selEnd
= sciThis
->SelectionEnd();
2332 if (sciThis
->posDrop
> selStart
) {
2333 if (sciThis
->posDrop
> selEnd
)
2334 sciThis
->posDrop
= sciThis
->posDrop
- (selEnd
- selStart
);
2336 sciThis
->posDrop
= selStart
;
2337 sciThis
->posDrop
= sciThis
->pdoc
->ClampPositionIntoDocument(sciThis
->posDrop
);
2339 sciThis
->ClearSelection();
2341 sciThis
->SetDragPosition(invalidPosition
);
2344 int ScintillaGTK::TimeOut(ScintillaGTK
*sciThis
) {
2349 int ScintillaGTK::IdleCallback(ScintillaGTK
*sciThis
) {
2350 // Idler will be automatically stoped, if there is nothing
2351 // to do while idle.
2352 bool ret
= sciThis
->Idle();
2354 // FIXME: This will remove the idler from GTK, we don't want to
2355 // remove it as it is removed automatically when this function
2356 // returns false (although, it should be harmless).
2357 sciThis
->SetIdle(false);
2362 void ScintillaGTK::PopUpCB(ScintillaGTK
*sciThis
, guint action
, GtkWidget
*) {
2364 sciThis
->Command(action
);
2368 gint
ScintillaGTK::PressCT(GtkWidget
*widget
, GdkEventButton
*event
, ScintillaGTK
*sciThis
) {
2369 if (event
->window
!= widget
->window
)
2371 if (event
->type
!= GDK_BUTTON_PRESS
)
2374 pt
.x
= int(event
->x
);
2375 pt
.y
= int(event
->y
);
2376 sciThis
->ct
.MouseClick(pt
);
2377 sciThis
->CallTipClick();
2378 #if GTK_MAJOR_VERSION >= 2
2385 gint
ScintillaGTK::ExposeCT(GtkWidget
*widget
, GdkEventExpose
* /*ose*/, CallTip
*ctip
) {
2386 Surface
*surfaceWindow
= Surface::Allocate();
2387 if (surfaceWindow
) {
2388 surfaceWindow
->Init(widget
->window
, widget
);
2389 ctip
->PaintCT(surfaceWindow
);
2390 surfaceWindow
->Release();
2391 delete surfaceWindow
;
2396 sptr_t
ScintillaGTK::DirectFunction(
2397 ScintillaGTK
*sciThis
, unsigned int iMessage
, uptr_t wParam
, sptr_t lParam
) {
2398 return sciThis
->WndProc(iMessage
, wParam
, lParam
);
2401 sptr_t
scintilla_send_message(ScintillaObject
*sci
, unsigned int iMessage
, uptr_t wParam
, sptr_t lParam
) {
2402 ScintillaGTK
*psci
= reinterpret_cast<ScintillaGTK
*>(sci
->pscin
);
2403 return psci
->WndProc(iMessage
, wParam
, lParam
);
2406 static void scintilla_class_init(ScintillaClass
*klass
);
2407 static void scintilla_init(ScintillaObject
*sci
);
2409 extern void Platform_Initialise();
2410 extern void Platform_Finalise();
2412 GtkType
scintilla_get_type() {
2413 static GtkType scintilla_type
= 0;
2415 if (!scintilla_type
) {
2416 Platform_Initialise();
2417 static GtkTypeInfo scintilla_info
= {
2419 sizeof (ScintillaObject
),
2420 sizeof (ScintillaClass
),
2421 (GtkClassInitFunc
) scintilla_class_init
,
2422 (GtkObjectInitFunc
) scintilla_init
,
2428 scintilla_type
= gtk_type_unique(gtk_container_get_type(), &scintilla_info
);
2431 return scintilla_type
;
2434 void ScintillaGTK::ClassInit(GtkObjectClass
* object_class
, GtkWidgetClass
*widget_class
, GtkContainerClass
*container_class
) {
2435 atomClipboard
= gdk_atom_intern("CLIPBOARD", FALSE
);
2436 atomUTF8
= gdk_atom_intern("UTF8_STRING", FALSE
);
2437 atomString
= GDK_SELECTION_TYPE_STRING
;
2439 // Define default signal handlers for the class: Could move more
2440 // of the signal handlers here (those that currently attached to wDraw
2441 // in Initialise() may require coordinate translation?)
2443 object_class
->destroy
= Destroy
;
2445 widget_class
->size_request
= SizeRequest
;
2446 widget_class
->size_allocate
= SizeAllocate
;
2447 widget_class
->expose_event
= ExposeMain
;
2448 #if GTK_MAJOR_VERSION < 2
2449 widget_class
->draw
= Draw
;
2452 widget_class
->motion_notify_event
= Motion
;
2453 widget_class
->button_press_event
= Press
;
2454 widget_class
->button_release_event
= MouseRelease
;
2455 #if PLAT_GTK_WIN32 || (GTK_MAJOR_VERSION >= 2)
2456 widget_class
->scroll_event
= ScrollEvent
;
2458 widget_class
->key_press_event
= KeyPress
;
2459 widget_class
->key_release_event
= KeyRelease
;
2460 widget_class
->focus_in_event
= FocusIn
;
2461 widget_class
->focus_out_event
= FocusOut
;
2462 widget_class
->selection_received
= SelectionReceived
;
2463 widget_class
->selection_get
= SelectionGet
;
2464 widget_class
->selection_clear_event
= SelectionClear
;
2465 #if GTK_MAJOR_VERSION < 2
2466 widget_class
->selection_notify_event
= SelectionNotify
;
2469 widget_class
->drag_data_received
= DragDataReceived
;
2470 widget_class
->drag_motion
= DragMotion
;
2471 widget_class
->drag_leave
= DragLeave
;
2472 widget_class
->drag_end
= DragEnd
;
2473 widget_class
->drag_drop
= Drop
;
2474 widget_class
->drag_data_get
= DragDataGet
;
2476 widget_class
->realize
= Realize
;
2477 widget_class
->unrealize
= UnRealize
;
2478 widget_class
->map
= Map
;
2479 widget_class
->unmap
= UnMap
;
2481 container_class
->forall
= MainForAll
;
2484 #if GTK_MAJOR_VERSION < 2
2485 #define GTK_CLASS_TYPE(c) (c->type)
2486 #define SIG_MARSHAL gtk_marshal_NONE__INT_POINTER
2488 #define SIG_MARSHAL scintilla_marshal_NONE__INT_POINTER
2490 #define MARSHAL_ARGUMENTS GTK_TYPE_INT, GTK_TYPE_POINTER
2492 static void scintilla_class_init(ScintillaClass
*klass
) {
2493 GtkObjectClass
*object_class
= (GtkObjectClass
*) klass
;
2494 GtkWidgetClass
*widget_class
= (GtkWidgetClass
*) klass
;
2495 GtkContainerClass
*container_class
= (GtkContainerClass
*) klass
;
2497 parent_class
= (GtkWidgetClass
*) gtk_type_class(gtk_container_get_type());
2499 scintilla_signals
[COMMAND_SIGNAL
] = gtk_signal_new(
2502 GTK_CLASS_TYPE(object_class
),
2503 GTK_SIGNAL_OFFSET(ScintillaClass
, command
),
2506 2, MARSHAL_ARGUMENTS
);
2508 scintilla_signals
[NOTIFY_SIGNAL
] = gtk_signal_new(
2511 GTK_CLASS_TYPE(object_class
),
2512 GTK_SIGNAL_OFFSET(ScintillaClass
, notify
),
2515 2, MARSHAL_ARGUMENTS
);
2516 #if GTK_MAJOR_VERSION < 2
2517 gtk_object_class_add_signals(object_class
,
2518 reinterpret_cast<unsigned int *>(scintilla_signals
), LAST_SIGNAL
);
2520 klass
->command
= NULL
;
2521 klass
->notify
= NULL
;
2523 ScintillaGTK::ClassInit(object_class
, widget_class
, container_class
);
2526 static void scintilla_init(ScintillaObject
*sci
) {
2527 GTK_WIDGET_SET_FLAGS(sci
, GTK_CAN_FOCUS
);
2528 sci
->pscin
= new ScintillaGTK(sci
);
2531 GtkWidget
* scintilla_new() {
2532 return GTK_WIDGET(gtk_type_new(scintilla_get_type()));
2535 void scintilla_set_id(ScintillaObject
*sci
, int id
) {
2536 ScintillaGTK
*psci
= reinterpret_cast<ScintillaGTK
*>(sci
->pscin
);
2540 void scintilla_release_resources(void) {
2541 Platform_Finalise();