📄 scintillagtk.cxx
字号:
// Scintilla source code edit control
// ScintillaGTK.cxx - GTK+ specific subclass of ScintillaBase
// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <time.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include "Platform.h"
#if PLAT_GTK_WIN32
#include "Windows.h"
#endif
#include "Scintilla.h"
#include "ScintillaWidget.h"
#ifdef SCI_LEXER
#include "SciLexer.h"
#include "PropSet.h"
#include "Accessor.h"
#include "KeyWords.h"
#endif
#include "ContractionState.h"
#include "SVector.h"
#include "CellBuffer.h"
#include "CallTip.h"
#include "KeyMap.h"
#include "Indicator.h"
#include "XPM.h"
#include "LineMarker.h"
#include "Style.h"
#include "AutoComplete.h"
#include "ViewStyle.h"
#include "Document.h"
#include "Editor.h"
#include "SString.h"
#include "ScintillaBase.h"
#include "UniConversion.h"
#include "gtk/gtksignal.h"
#include "gtk/gtkmarshal.h"
#ifdef SCI_LEXER
#include <glib.h>
#include <gmodule.h>
#include "ExternalLexer.h"
#endif
#if GTK_MAJOR_VERSION < 2
#define INTERNATIONAL_INPUT
#else
#include <iconv.h>
#endif
#ifdef _MSC_VER
// Constant conditional expressions are because of GTK+ headers
#pragma warning(disable: 4127)
// Ignore unreferenced local functions in GTK+ headers
#pragma warning(disable: 4505)
#endif
class ScintillaGTK : public ScintillaBase {
_ScintillaObject *sci;
Window wText;
Window scrollbarv;
Window scrollbarh;
GtkObject *adjustmentv;
GtkObject *adjustmenth;
int scrollBarWidth;
int scrollBarHeight;
// Because clipboard access is asynchronous, copyText is created by Copy
SelectionText copyText;
SelectionText primary;
GdkEventButton evbtn;
bool capturedMouse;
bool dragWasDropped;
GtkWidgetClass *parentClass;
static GdkAtom clipboard_atom;
#if PLAT_GTK_WIN32
CLIPFORMAT cfColumnSelect;
#endif
#ifdef INTERNATIONAL_INPUT
// Input context used for supporting internationalized key entry
GdkIC *ic;
GdkICAttr *ic_attr;
#endif
// Wheel mouse support
unsigned int linesPerScroll;
GTimeVal lastWheelMouseTime;
gint lastWheelMouseDirection;
gint wheelMouseIntensity;
// Private so ScintillaGTK objects can not be copied
ScintillaGTK(const ScintillaGTK &) : ScintillaBase() {}
ScintillaGTK &operator=(const ScintillaGTK &) { return * this; }
public:
ScintillaGTK(_ScintillaObject *sci_);
virtual ~ScintillaGTK();
static void ClassInit(GtkObjectClass* object_class, GtkWidgetClass *widget_class);
private:
virtual void Initialise();
virtual void Finalise();
virtual void DisplayCursor(Window::Cursor c);
virtual void StartDrag();
public: // Public for scintilla_send_message
virtual sptr_t WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
private:
virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
virtual void SetTicking(bool on);
virtual void SetMouseCapture(bool on);
virtual bool HaveMouseCapture();
void FullPaint();
virtual PRectangle GetClientRectangle();
void SyncPaint(PRectangle rc);
virtual void ScrollText(int linesToMove);
virtual void SetVerticalScrollPos();
virtual void SetHorizontalScrollPos();
virtual bool ModifyScrollBars(int nMax, int nPage);
void ReconfigureScrollBars();
virtual void NotifyChange();
virtual void NotifyFocus(bool focus);
virtual void NotifyParent(SCNotification scn);
void NotifyKey(int key, int modifiers);
void NotifyURIDropped(const char *list);
virtual int KeyDefault(int key, int modifiers);
virtual void CopyToClipboard(const SelectionText &selectedText);
virtual void Copy();
virtual void Paste();
virtual void CreateCallTipWindow(PRectangle rc);
virtual void AddToPopUp(const char *label, int cmd = 0, bool enabled = true);
bool OwnPrimarySelection();
virtual void ClaimSelection();
char *GetGtkSelectionText(const GtkSelectionData *selectionData, unsigned int *len, bool *isRectangular);
void ReceivedSelection(GtkSelectionData *selection_data);
void ReceivedDrop(GtkSelectionData *selection_data);
void GetSelection(GtkSelectionData *selection_data, guint info, SelectionText *selected);
void UnclaimSelection(GdkEventSelection *selection_event);
void Resize(int width, int height);
// Callback functions
void RealizeThis(GtkWidget *widget);
static void Realize(GtkWidget *widget);
void UnRealizeThis(GtkWidget *widget);
static void UnRealize(GtkWidget *widget);
void MapThis();
static void Map(GtkWidget *widget);
void UnMapThis();
static void UnMap(GtkWidget *widget);
static gint CursorMoved(GtkWidget *widget, int xoffset, int yoffset, ScintillaGTK *sciThis);
static gint FocusIn(GtkWidget *widget, GdkEventFocus *event);
static gint FocusOut(GtkWidget *widget, GdkEventFocus *event);
static void SizeRequest(GtkWidget *widget, GtkRequisition *requisition);
static void SizeAllocate(GtkWidget *widget, GtkAllocation *allocation);
gint Expose(GtkWidget *widget, GdkEventExpose *ose);
static gint ExposeMain(GtkWidget *widget, GdkEventExpose *ose);
static void Draw(GtkWidget *widget, GdkRectangle *area);
static void ScrollSignal(GtkAdjustment *adj, ScintillaGTK *sciThis);
static void ScrollHSignal(GtkAdjustment *adj, ScintillaGTK *sciThis);
gint PressThis(GdkEventButton *event);
static gint Press(GtkWidget *widget, GdkEventButton *event);
static gint MouseRelease(GtkWidget *widget, GdkEventButton *event);
#if PLAT_GTK_WIN32 || (GTK_MAJOR_VERSION >= 2)
static gint ScrollEvent(GtkWidget *widget, GdkEventScroll *event);
#endif
static gint Motion(GtkWidget *widget, GdkEventMotion *event);
gint KeyThis(GdkEventKey *event);
static gint KeyPress(GtkWidget *widget, GdkEventKey *event);
static gint KeyRelease(GtkWidget *widget, GdkEventKey *event);
static void Destroy(GtkObject *object);
static void SelectionReceived(GtkWidget *widget, GtkSelectionData *selection_data,
guint time);
static void SelectionGet(GtkWidget *widget, GtkSelectionData *selection_data,
guint info, guint time);
static gint SelectionClear(GtkWidget *widget, GdkEventSelection *selection_event);
#if GTK_MAJOR_VERSION < 2
static gint SelectionNotify(GtkWidget *widget, GdkEventSelection *selection_event);
#endif
static void DragBegin(GtkWidget *widget, GdkDragContext *context);
static gboolean DragMotion(GtkWidget *widget, GdkDragContext *context,
gint x, gint y, guint time);
static void DragLeave(GtkWidget *widget, GdkDragContext *context,
guint time);
static void DragEnd(GtkWidget *widget, GdkDragContext *context);
static gboolean Drop(GtkWidget *widget, GdkDragContext *context,
gint x, gint y, guint time);
static void DragDataReceived(GtkWidget *widget, GdkDragContext *context,
gint x, gint y, GtkSelectionData *selection_data, guint info, guint time);
static void DragDataGet(GtkWidget *widget, GdkDragContext *context,
GtkSelectionData *selection_data, guint info, guint time);
static gint TimeOut(ScintillaGTK *sciThis);
static void PopUpCB(ScintillaGTK *sciThis, guint action, GtkWidget *widget);
gint ExposeTextThis(GtkWidget *widget, GdkEventExpose *ose);
static gint ExposeText(GtkWidget *widget, GdkEventExpose *ose, ScintillaGTK *sciThis);
static gint ExposeCT(GtkWidget *widget, GdkEventExpose *ose, CallTip *ct);
static gint PressCT(GtkWidget *widget, GdkEventButton *event, ScintillaGTK *sciThis);
static sptr_t DirectFunction(ScintillaGTK *sciThis,
unsigned int iMessage, uptr_t wParam, sptr_t lParam);
};
enum {
COMMAND_SIGNAL,
NOTIFY_SIGNAL,
LAST_SIGNAL
};
static gint scintilla_signals[LAST_SIGNAL] = { 0 };
static GtkWidgetClass* parent_class = NULL;
GdkAtom ScintillaGTK::clipboard_atom = GDK_NONE;
enum {
TARGET_STRING,
TARGET_TEXT,
TARGET_COMPOUND_TEXT
};
static GtkWidget *PWidget(Window &w) {
return reinterpret_cast<GtkWidget *>(w.GetID());
}
static ScintillaGTK *ScintillaFromWidget(GtkWidget *widget) {
ScintillaObject *scio = reinterpret_cast<ScintillaObject *>(widget);
return reinterpret_cast<ScintillaGTK *>(scio->pscin);
}
ScintillaGTK::ScintillaGTK(_ScintillaObject *sci_) :
adjustmentv(0), adjustmenth(0),
scrollBarWidth(30), scrollBarHeight(30),
capturedMouse(false), dragWasDropped(false),
parentClass(0),
#ifdef INTERNATIONAL_INPUT
ic(NULL),
ic_attr(NULL),
#endif
lastWheelMouseDirection(0),
wheelMouseIntensity(0) {
sci = sci_;
wMain = GTK_WIDGET(sci);
#if PLAT_GTK_WIN32
// There does not seem to be a real standard for indicating that the clipboard
// contains a rectangular selection, so copy Developer Studio.
cfColumnSelect = static_cast<CLIPFORMAT>(
::RegisterClipboardFormat("MSDEVColumnSelect"));
// Get intellimouse parameters when running on win32; otherwise use
// reasonable default
#ifndef SPI_GETWHEELSCROLLLINES
#define SPI_GETWHEELSCROLLLINES 104
#endif
::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &linesPerScroll, 0);
#else
linesPerScroll = 4;
#endif
lastWheelMouseTime.tv_sec = 0;
lastWheelMouseTime.tv_usec = 0;
Initialise();
}
ScintillaGTK::~ScintillaGTK() {
}
void ScintillaGTK::RealizeThis(GtkWidget *widget) {
//Platform::DebugPrintf("ScintillaGTK::realize this\n");
GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED);
GdkWindowAttr attrs;
attrs.window_type = GDK_WINDOW_CHILD;
attrs.x = widget->allocation.x;
attrs.y = widget->allocation.y;
attrs.width = widget->allocation.width;
attrs.height = widget->allocation.height;
attrs.wclass = GDK_INPUT_OUTPUT;
attrs.visual = gtk_widget_get_visual(widget);
attrs.colormap = gtk_widget_get_colormap(widget);
attrs.event_mask = gtk_widget_get_events(widget) | GDK_EXPOSURE_MASK;
GdkCursor *cursor = gdk_cursor_new(GDK_XTERM);
attrs.cursor = cursor;
widget->window = gdk_window_new(gtk_widget_get_parent_window(widget), &attrs,
GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP | GDK_WA_CURSOR);
gdk_window_set_user_data(widget->window, widget);
gdk_window_set_background(widget->window, &widget->style->bg[GTK_STATE_NORMAL]);
gdk_window_show(widget->window);
gdk_cursor_destroy(cursor);
#ifdef INTERNATIONAL_INPUT
if (gdk_im_ready() && (ic_attr = gdk_ic_attr_new()) != NULL) {
gint width, height;
GdkColormap *colormap;
GdkEventMask mask;
GdkICAttr *attr = ic_attr;
GdkICAttributesType attrmask = GDK_IC_ALL_REQ;
GdkIMStyle style;
GdkIMStyle supported_style = (GdkIMStyle) (GDK_IM_PREEDIT_NONE |
GDK_IM_PREEDIT_NOTHING |
GDK_IM_PREEDIT_POSITION |
GDK_IM_STATUS_NONE |
GDK_IM_STATUS_NOTHING);
if (widget->style && widget->style->font->type != GDK_FONT_FONTSET)
supported_style = (GdkIMStyle) ((int) supported_style & ~GDK_IM_PREEDIT_POSITION);
attr->style = style = gdk_im_decide_style(supported_style);
attr->client_window = widget->window;
if ((colormap = gtk_widget_get_colormap (widget)) != gtk_widget_get_default_colormap ()) {
attrmask = (GdkICAttributesType) ((int) attrmask | GDK_IC_PREEDIT_COLORMAP);
attr->preedit_colormap = colormap;
}
switch (style & GDK_IM_PREEDIT_MASK) {
case GDK_IM_PREEDIT_POSITION:
if (widget->style && widget->style->font->type != GDK_FONT_FONTSET) {
g_warning("over-the-spot style requires fontset");
break;
}
attrmask = (GdkICAttributesType) ((int) attrmask | GDK_IC_PREEDIT_POSITION_REQ);
gdk_window_get_size(widget->window, &width, &height);
attr->spot_location.x = 0;
attr->spot_location.y = height;
attr->preedit_area.x = 0;
attr->preedit_area.y = 0;
attr->preedit_area.width = width;
attr->preedit_area.height = height;
attr->preedit_fontset = widget->style->font;
break;
}
ic = gdk_ic_new(attr, attrmask);
if (ic == NULL) {
g_warning("Can't create input context.");
} else {
mask = gdk_window_get_events(widget->window);
mask = (GdkEventMask) ((int) mask | gdk_ic_get_events(ic));
gdk_window_set_events(widget->window, mask);
if (GTK_WIDGET_HAS_FOCUS(widget))
gdk_im_begin(ic, widget->window);
}
}
#endif
gtk_widget_realize(PWidget(wText));
gtk_widget_realize(PWidget(scrollbarv));
gtk_widget_realize(PWidget(scrollbarh));
}
void ScintillaGTK::Realize(GtkWidget *widget) {
ScintillaGTK *sciThis = ScintillaFromWidget(widget);
sciThis->RealizeThis(widget);
}
void ScintillaGTK::UnRealizeThis(GtkWidget *widget) {
if (GTK_WIDGET_MAPPED(widget)) {
gtk_widget_unmap(widget);
}
GTK_WIDGET_UNSET_FLAGS(widget, GTK_REALIZED);
gtk_widget_unrealize(PWidget(wText));
gtk_widget_unrealize(PWidget(scrollbarv));
gtk_widget_unrealize(PWidget(scrollbarh));
#ifdef INTERNATIONAL_INPUT
if (ic) {
gdk_ic_destroy(ic);
ic = NULL;
}
if (ic_attr) {
gdk_ic_attr_destroy(ic_attr);
ic_attr = NULL;
}
#endif
if (GTK_WIDGET_CLASS(parentClass)->unrealize)
GTK_WIDGET_CLASS(parentClass)->unrealize(widget);
Finalise();
}
void ScintillaGTK::UnRealize(GtkWidget *widget) {
ScintillaGTK *sciThis = ScintillaFromWidget(widget);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -