You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
337 lines
13 KiB
337 lines
13 KiB
// Scintilla source code edit control |
|
// ScintillaGTK.h - 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. |
|
|
|
#ifndef SCINTILLAGTK_H |
|
#define SCINTILLAGTK_H |
|
|
|
namespace Scintilla::Internal { |
|
|
|
class ScintillaGTKAccessible; |
|
|
|
#define OBJECT_CLASS GObjectClass |
|
|
|
struct FontOptions { |
|
cairo_antialias_t antialias {}; |
|
cairo_subpixel_order_t order {}; |
|
cairo_hint_style_t hint {}; |
|
FontOptions() noexcept = default; |
|
explicit FontOptions(GtkWidget *widget) noexcept; |
|
bool operator==(const FontOptions &other) const noexcept; |
|
}; |
|
|
|
class ScintillaGTK : public ScintillaBase { |
|
friend class ScintillaGTKAccessible; |
|
|
|
_ScintillaObject *sci; |
|
Window wText; |
|
Window scrollbarv; |
|
Window scrollbarh; |
|
GtkAdjustment *adjustmentv; |
|
GtkAdjustment *adjustmenth; |
|
int verticalScrollBarWidth; |
|
int horizontalScrollBarHeight; |
|
|
|
PRectangle rectangleClient; |
|
|
|
SelectionText primary; |
|
SelectionPosition posPrimary; |
|
|
|
UniqueGdkEvent evbtn; |
|
guint buttonMouse; |
|
bool capturedMouse; |
|
bool dragWasDropped; |
|
int lastKey; |
|
int rectangularSelectionModifier; |
|
|
|
GtkWidgetClass *parentClass; |
|
|
|
static inline GdkAtom atomUTF8 {}; |
|
static inline GdkAtom atomUTF8Mime {}; |
|
static inline GdkAtom atomString {}; |
|
static inline GdkAtom atomUriList {}; |
|
static inline GdkAtom atomDROPFILES_DND {}; |
|
GdkAtom atomSought; |
|
size_t inClearSelection = 0; |
|
|
|
#if PLAT_GTK_WIN32 |
|
CLIPFORMAT cfColumnSelect; |
|
#endif |
|
|
|
bool preeditInitialized; |
|
Window wPreedit; |
|
Window wPreeditDraw; |
|
UniqueIMContext im_context; |
|
GUnicodeScript lastNonCommonScript; |
|
|
|
GtkSettings *settings; |
|
gulong settingsHandlerId; |
|
|
|
// Wheel mouse support |
|
unsigned int linesPerScroll; |
|
gint64 lastWheelMouseTime; |
|
gint lastWheelMouseDirection; |
|
gint wheelMouseIntensity; |
|
gdouble smoothScrollY; |
|
gdouble smoothScrollX; |
|
|
|
#if GTK_CHECK_VERSION(3,0,0) |
|
cairo_rectangle_list_t *rgnUpdate; |
|
#else |
|
GdkRegion *rgnUpdate; |
|
#endif |
|
bool repaintFullWindow; |
|
|
|
guint styleIdleID; |
|
guint scrollBarIdleID = 0; |
|
FontOptions fontOptionsPrevious; |
|
int accessibilityEnabled; |
|
AtkObject *accessible; |
|
|
|
public: |
|
explicit ScintillaGTK(_ScintillaObject *sci_); |
|
// Deleted so ScintillaGTK objects can not be copied. |
|
ScintillaGTK(const ScintillaGTK &) = delete; |
|
ScintillaGTK(ScintillaGTK &&) = delete; |
|
ScintillaGTK &operator=(const ScintillaGTK &) = delete; |
|
ScintillaGTK &operator=(ScintillaGTK &&) = delete; |
|
~ScintillaGTK() override; |
|
static ScintillaGTK *FromWidget(GtkWidget *widget) noexcept; |
|
static void ClassInit(OBJECT_CLASS *object_class, GtkWidgetClass *widget_class, GtkContainerClass *container_class); |
|
private: |
|
void Init(); |
|
void Finalise() override; |
|
bool AbandonPaint() override; |
|
void DisplayCursor(Window::Cursor c) override; |
|
bool DragThreshold(Point ptStart, Point ptNow) override; |
|
void StartDrag() override; |
|
Sci::Position TargetAsUTF8(char *text) const; |
|
Sci::Position EncodedFromUTF8(const char *utf8, char *encoded) const; |
|
bool ValidCodePage(int codePage) const override; |
|
std::string UTF8FromEncoded(std::string_view encoded) const override; |
|
std::string EncodedFromUTF8(std::string_view utf8) const override; |
|
public: // Public for scintilla_send_message |
|
sptr_t WndProc(Scintilla::Message iMessage, Scintilla::uptr_t wParam, Scintilla::sptr_t lParam) override; |
|
private: |
|
sptr_t DefWndProc(Scintilla::Message iMessage, Scintilla::uptr_t wParam, Scintilla::sptr_t lParam) override; |
|
struct TimeThunk { |
|
TickReason reason; |
|
ScintillaGTK *scintilla; |
|
guint timer; |
|
TimeThunk() noexcept : reason(TickReason::caret), scintilla(nullptr), timer(0) {} |
|
}; |
|
TimeThunk timers[static_cast<size_t>(TickReason::dwell)+1]; |
|
bool FineTickerRunning(TickReason reason) override; |
|
void FineTickerStart(TickReason reason, int millis, int tolerance) override; |
|
void FineTickerCancel(TickReason reason) override; |
|
bool SetIdle(bool on) override; |
|
void SetMouseCapture(bool on) override; |
|
bool HaveMouseCapture() override; |
|
bool PaintContains(PRectangle rc) override; |
|
void FullPaint(); |
|
void SetClientRectangle(); |
|
PRectangle GetClientRectangle() const override; |
|
void ScrollText(Sci::Line linesToMove) override; |
|
void SetVerticalScrollPos() override; |
|
void SetHorizontalScrollPos() override; |
|
bool ModifyScrollBars(Sci::Line nMax, Sci::Line nPage) override; |
|
void ReconfigureScrollBars() override; |
|
void SetScrollBars() override; |
|
void NotifyChange() override; |
|
void NotifyFocus(bool focus) override; |
|
void NotifyParent(Scintilla::NotificationData scn) override; |
|
void NotifyKey(Scintilla::Keys key, Scintilla::KeyMod modifiers); |
|
void NotifyURIDropped(const char *list); |
|
const char *CharacterSetID() const; |
|
std::unique_ptr<CaseFolder> CaseFolderForEncoding() override; |
|
std::string CaseMapString(const std::string &s, CaseMapping caseMapping) override; |
|
int KeyDefault(Scintilla::Keys key, Scintilla::KeyMod modifiers) override; |
|
void CopyToClipboard(const SelectionText &selectedText) override; |
|
void Copy() override; |
|
void RequestSelection(GdkAtom atomSelection); |
|
void Paste() override; |
|
void CreateCallTipWindow(PRectangle rc) override; |
|
void AddToPopUp(const char *label, int cmd = 0, bool enabled = true) override; |
|
bool OwnPrimarySelection(); |
|
void ClaimSelection() override; |
|
static bool IsStringAtom(GdkAtom type); |
|
void GetGtkSelectionText(GtkSelectionData *selectionData, SelectionText &selText); |
|
void InsertSelection(GtkClipboard *clipBoard, GtkSelectionData *selectionData); |
|
public: // Public for SelectionReceiver |
|
GObject *MainObject() const noexcept; |
|
void ReceivedClipboard(GtkClipboard *clipBoard, GtkSelectionData *selection_data) noexcept; |
|
private: |
|
void ReceivedSelection(GtkSelectionData *selection_data); |
|
void ReceivedDrop(GtkSelectionData *selection_data); |
|
static void GetSelection(GtkSelectionData *selection_data, guint info, SelectionText *text); |
|
void StoreOnClipboard(SelectionText *clipText); |
|
static void ClipboardGetSelection(GtkClipboard *clip, GtkSelectionData *selection_data, guint info, void *data); |
|
static void ClipboardClearSelection(GtkClipboard *clip, void *data); |
|
|
|
void ClearPrimarySelection(); |
|
void PrimaryGetSelectionThis(GtkClipboard *clip, GtkSelectionData *selection_data, guint info); |
|
static void PrimaryGetSelection(GtkClipboard *clip, GtkSelectionData *selection_data, guint info, gpointer pSci); |
|
void PrimaryClearSelectionThis(GtkClipboard *clip); |
|
static void PrimaryClearSelection(GtkClipboard *clip, gpointer pSci); |
|
|
|
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); |
|
gint FocusInThis(GtkWidget *widget); |
|
static gint FocusIn(GtkWidget *widget, GdkEventFocus *event); |
|
gint FocusOutThis(GtkWidget *widget); |
|
static gint FocusOut(GtkWidget *widget, GdkEventFocus *event); |
|
static void SizeRequest(GtkWidget *widget, GtkRequisition *requisition); |
|
#if GTK_CHECK_VERSION(3,0,0) |
|
static void GetPreferredWidth(GtkWidget *widget, gint *minimalWidth, gint *naturalWidth); |
|
static void GetPreferredHeight(GtkWidget *widget, gint *minimalHeight, gint *naturalHeight); |
|
#endif |
|
static void SizeAllocate(GtkWidget *widget, GtkAllocation *allocation); |
|
void CheckForFontOptionChange(); |
|
#if GTK_CHECK_VERSION(3,0,0) |
|
gboolean DrawTextThis(cairo_t *cr); |
|
static gboolean DrawText(GtkWidget *widget, cairo_t *cr, ScintillaGTK *sciThis); |
|
gboolean DrawThis(cairo_t *cr); |
|
static gboolean DrawMain(GtkWidget *widget, cairo_t *cr); |
|
#else |
|
gboolean ExposeTextThis(GtkWidget *widget, GdkEventExpose *ose); |
|
static gboolean ExposeText(GtkWidget *widget, GdkEventExpose *ose, ScintillaGTK *sciThis); |
|
gboolean Expose(GtkWidget *widget, GdkEventExpose *ose); |
|
static gboolean ExposeMain(GtkWidget *widget, GdkEventExpose *ose); |
|
#endif |
|
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); |
|
static gint ScrollEvent(GtkWidget *widget, GdkEventScroll *event); |
|
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_CHECK_VERSION(3,0,0) |
|
gboolean DrawPreeditThis(GtkWidget *widget, cairo_t *cr); |
|
static gboolean DrawPreedit(GtkWidget *widget, cairo_t *cr, ScintillaGTK *sciThis); |
|
#else |
|
gboolean ExposePreeditThis(GtkWidget *widget, GdkEventExpose *ose); |
|
static gboolean ExposePreedit(GtkWidget *widget, GdkEventExpose *ose, ScintillaGTK *sciThis); |
|
#endif |
|
AtkObject *GetAccessibleThis(GtkWidget *widget); |
|
static AtkObject *GetAccessible(GtkWidget *widget); |
|
|
|
bool KoreanIME(); |
|
void CommitThis(char *commitStr); |
|
static void Commit(GtkIMContext *context, char *str, ScintillaGTK *sciThis); |
|
void PreeditChangedInlineThis(); |
|
void PreeditChangedWindowedThis(); |
|
static void PreeditChanged(GtkIMContext *context, ScintillaGTK *sciThis); |
|
bool RetrieveSurroundingThis(GtkIMContext *context); |
|
static gboolean RetrieveSurrounding(GtkIMContext *context, ScintillaGTK *sciThis); |
|
bool DeleteSurroundingThis(GtkIMContext *context, gint characterOffset, gint characterCount); |
|
static gboolean DeleteSurrounding(GtkIMContext *context, gint characterOffset, gint characterCount, |
|
ScintillaGTK *sciThis); |
|
void MoveImeCarets(Sci::Position pos); |
|
void DrawImeIndicator(int indicator, Sci::Position len); |
|
void SetCandidateWindowPos(); |
|
|
|
static void StyleSetText(GtkWidget *widget, GtkStyle *previous, void *); |
|
static void RealizeText(GtkWidget *widget, void *); |
|
static void Dispose(GObject *object); |
|
static void Destroy(GObject *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); |
|
gboolean DragMotionThis(GdkDragContext *context, gint x, gint y, guint dragtime); |
|
static gboolean DragMotion(GtkWidget *widget, GdkDragContext *context, |
|
gint x, gint y, guint dragtime); |
|
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 gboolean TimeOut(gpointer ptt); |
|
static gboolean IdleCallback(gpointer pSci); |
|
static gboolean StyleIdle(gpointer pSci); |
|
void IdleWork() override; |
|
void QueueIdleWork(WorkItems items, Sci::Position upTo) override; |
|
void SetDocPointer(Document *document) override; |
|
static void PopUpCB(GtkMenuItem *menuItem, ScintillaGTK *sciThis); |
|
|
|
#if GTK_CHECK_VERSION(3,0,0) |
|
static gboolean DrawCT(GtkWidget *widget, cairo_t *cr, CallTip *ctip); |
|
#else |
|
static gboolean ExposeCT(GtkWidget *widget, GdkEventExpose *ose, CallTip *ctip); |
|
#endif |
|
static gboolean PressCT(GtkWidget *widget, GdkEventButton *event, ScintillaGTK *sciThis); |
|
|
|
static sptr_t DirectFunction(sptr_t ptr, |
|
unsigned int iMessage, uptr_t wParam, sptr_t lParam); |
|
static sptr_t DirectStatusFunction(sptr_t ptr, |
|
unsigned int iMessage, uptr_t wParam, sptr_t lParam, int *pStatus); |
|
}; |
|
|
|
// helper class to watch a GObject lifetime and get notified when it dies |
|
class GObjectWatcher { |
|
GObject *weakRef; |
|
|
|
void WeakNotifyThis([[maybe_unused]] GObject *obj) { |
|
PLATFORM_ASSERT(obj == weakRef); |
|
|
|
Destroyed(); |
|
weakRef = nullptr; |
|
} |
|
|
|
static void WeakNotify(gpointer data, GObject *obj) { |
|
static_cast<GObjectWatcher *>(data)->WeakNotifyThis(obj); |
|
} |
|
|
|
public: |
|
GObjectWatcher(GObject *obj) : |
|
weakRef(obj) { |
|
g_object_weak_ref(weakRef, WeakNotify, this); |
|
} |
|
|
|
// Deleted so GObjectWatcher objects can not be copied. |
|
GObjectWatcher(const GObjectWatcher&) = delete; |
|
GObjectWatcher(GObjectWatcher&&) = delete; |
|
GObjectWatcher&operator=(const GObjectWatcher&) = delete; |
|
GObjectWatcher&operator=(GObjectWatcher&&) = delete; |
|
|
|
virtual ~GObjectWatcher() { |
|
if (weakRef) { |
|
g_object_weak_unref(weakRef, WeakNotify, this); |
|
} |
|
} |
|
|
|
virtual void Destroyed() {} |
|
|
|
bool IsDestroyed() const { |
|
return weakRef != nullptr; |
|
} |
|
}; |
|
|
|
std::string ConvertText(const char *s, size_t len, const char *charSetDest, |
|
const char *charSetSource, bool transliterations, bool silent=false); |
|
|
|
} |
|
|
|
#endif
|
|
|