notepad-plus-plus/scintilla/gtk/ScintillaGTK.h

338 lines
13 KiB
C++

// 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(GObject *obj G_GNUC_UNUSED) {
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