📄 scintillagtk.cxx.svn-base
字号:
// Scintilla source code edit control
// ScintillaGTK.cxx - GTK+ specific subclass of ScintillaBase
// Copyright 1998-2004 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 "SplitVector.h"
#include "Partitioning.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 "CharClassify.h"
#include "Document.h"
#include "Editor.h"
#include "SString.h"
#include "ScintillaBase.h"
#include "UniConversion.h"
#include "gtk/gtksignal.h"
#include "gtk/gtkmarshal.h"
#if GLIB_MAJOR_VERSION >= 2
#include "scintilla-marshal.h"
#endif
#ifdef SCI_LEXER
#include <glib.h>
#include <gmodule.h>
#include "ExternalLexer.h"
#endif
#define INTERNATIONAL_INPUT
#if !PLAT_GTK_WIN32 || GTK_MAJOR_VERSION >= 2
#define USE_CONVERTER
#endif
#ifdef USE_CONVERTER
#include "Converter.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
#if GTK_CHECK_VERSION(2,2,0)
#define USE_GTK_CLIPBOARD
#endif
#if GLIB_MAJOR_VERSION < 2
#define OBJECT_CLASS GtkObjectClass
#else
#define OBJECT_CLASS GObjectClass
#endif
extern char *UTF8FromLatin1(const char *s, int &len);
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
#ifndef USE_GTK_CLIPBOARD
SelectionText copyText;
#endif
SelectionText primary;
GdkEventButton evbtn;
bool capturedMouse;
bool dragWasDropped;
int lastKey;
GtkWidgetClass *parentClass;
static GdkAtom atomClipboard;
static GdkAtom atomUTF8;
static GdkAtom atomString;
static GdkAtom atomUriList;
static GdkAtom atomDROPFILES_DND;
GdkAtom atomSought;
#if PLAT_GTK_WIN32
CLIPFORMAT cfColumnSelect;
#endif
#ifdef INTERNATIONAL_INPUT
#if GTK_MAJOR_VERSION < 2
// Input context used for supporting internationalized key entry
GdkIC *ic;
GdkICAttr *ic_attr;
#else
Window wPreedit;
Window wPreeditDraw;
GtkIMContext *im_context;
#endif
#endif
// Wheel mouse support
unsigned int linesPerScroll;
GTimeVal lastWheelMouseTime;
gint lastWheelMouseDirection;
gint wheelMouseIntensity;
GdkRegion *rgnUpdate;
// 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(OBJECT_CLASS* object_class, GtkWidgetClass *widget_class, GtkContainerClass *container_class);
private:
virtual void Initialise();
virtual void Finalise();
virtual void DisplayCursor(Window::Cursor c);
virtual void StartDrag();
int TargetAsUTF8(char *text);
int EncodedFromUTF8(char *utf8, char *encoded);
virtual bool ValidCodePage(int codePage) const;
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 bool SetIdle(bool on);
virtual void SetMouseCapture(bool on);
virtual bool HaveMouseCapture();
virtual bool PaintContains(PRectangle rc);
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);
const char *CharacterSetID() const;
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();
void GetGtkSelectionText(GtkSelectionData *selectionData, SelectionText &selText);
void ReceivedSelection(GtkSelectionData *selection_data);
void ReceivedDrop(GtkSelectionData *selection_data);
static void GetSelection(GtkSelectionData *selection_data, guint info, SelectionText *selected);
#ifdef USE_GTK_CLIPBOARD
static void ClipboardGetSelection(GtkClipboard* clip, GtkSelectionData *selection_data, guint info, void *data);
static void ClipboardClearSelection(GtkClipboard* clip, void *data);
#endif
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);
void ForAll(GtkCallback callback, gpointer callback_data);
static void MainForAll(GtkContainer *container, gboolean include_internals, GtkCallback callback, gpointer callback_data);
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);
gboolean KeyThis(GdkEventKey *event);
static gboolean KeyPress(GtkWidget *widget, GdkEventKey *event);
static gboolean KeyRelease(GtkWidget *widget, GdkEventKey *event);
#if GTK_MAJOR_VERSION >= 2
static gboolean ExposePreedit(GtkWidget *widget, GdkEventExpose *ose, ScintillaGTK *sciThis);
gboolean ExposePreeditThis(GtkWidget *widget, GdkEventExpose *ose);
static void Commit(GtkIMContext *context, char *str, ScintillaGTK *sciThis);
void CommitThis(char *str);
static void PreeditChanged(GtkIMContext *context, ScintillaGTK *sciThis);
void PreeditChangedThis();
#endif
static gint StyleSetText(GtkWidget *widget, GtkStyle *previous, void*);
static gint RealizeText(GtkWidget *widget, void*);
#if GLIB_MAJOR_VERSION < 2
static void Destroy(GtkObject *object);
#else
static void Destroy(GObject *object);
#endif
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 gint IdleCallback(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 };
#if GLIB_MAJOR_VERSION < 2
static GtkWidgetClass *parent_class = NULL;
#endif
enum {
TARGET_STRING,
TARGET_TEXT,
TARGET_COMPOUND_TEXT,
TARGET_UTF8_STRING,
TARGET_URI
};
GdkAtom ScintillaGTK::atomClipboard = 0;
GdkAtom ScintillaGTK::atomUTF8 = 0;
GdkAtom ScintillaGTK::atomString = 0;
GdkAtom ScintillaGTK::atomUriList = 0;
GdkAtom ScintillaGTK::atomDROPFILES_DND = 0;
static const GtkTargetEntry clipboardTargets[] = {
{ "text/uri-list", 0, TARGET_URI },
{ "UTF8_STRING", 0, TARGET_UTF8_STRING },
{ "STRING", 0, TARGET_STRING },
};
static const gint nClipboardTargets = sizeof(clipboardTargets) / sizeof(clipboardTargets[0]);
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),
lastKey(0), parentClass(0),
#ifdef INTERNATIONAL_INPUT
#if GTK_MAJOR_VERSION < 2
ic(NULL),
ic_attr(NULL),
#else
im_context(NULL),
#endif
#endif
lastWheelMouseDirection(0),
wheelMouseIntensity(0),
rgnUpdate(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);
widget->style = gtk_style_attach(widget->style, widget->window);
#ifdef INTERNATIONAL_INPUT
#if GTK_MAJOR_VERSION < 2
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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -