aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/interface.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/interface.h')
-rw-r--r--src/interface.h446
1 files changed, 123 insertions, 323 deletions
diff --git a/src/interface.h b/src/interface.h
index 607a42c..c396225 100644
--- a/src/interface.h
+++ b/src/interface.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2017 Robin Haberkorn
+ * Copyright (C) 2012-2021 Robin Haberkorn
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -14,9 +14,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
-#ifndef __INTERFACE_H
-#define __INTERFACE_H
+#pragma once
#include <stdarg.h>
#include <signal.h>
@@ -25,349 +23,151 @@
#include <Scintilla.h>
-#include "memory.h"
-#include "undo.h"
-#include "error.h"
-
-namespace SciTECO {
-
-/* avoid include dependency conflict */
-class QRegister;
-class Buffer;
-class Cmdline;
-extern sig_atomic_t sigint_occurred;
+#include "sciteco.h"
+#include "qreg.h"
+#include "ring.h"
+#include "cmdline.h"
+#include "view.h"
/**
- * Base class for all SciTECO views. This is a minimal
- * abstraction where the implementor only has to provide
- * a method for dispatching Scintilla messages.
- * Everything else is handled by other SciTECO classes.
+ * @file
+ * Abstract user interface.
*
- * This interface employs the Curiously Recurring Template
- * Pattern (CRTP). To implement it, one must derive from
- * View<DerivedClass>. The methods to implement actually
- * have an "_impl" suffix so as to avoid infinite recursion
- * if an implementation is missing.
- * Externally however, the methods as given in this interface
- * may be called.
+ * Interface of all SciTECO user interfaces (e.g. Curses or GTK+).
+ * All functions that must be provided are marked with the \@pure tag.
*
- * The CRTP has a runtime overhead at low optimization levels
- * (additional non-inlined calls), but should provide a
- * significant performance boost when inlining is enabled.
- *
- * Note that not all methods have to be defined in the
- * class. Explicit template instantiation is used to outsource
- * base-class implementations to interface.cpp.
+ * @note
+ * We do not provide default implementations for any of the interface
+ * functions by declaring them "weak" since this is a non-portable linker
+ * feature.
*/
-template <class ViewImpl>
-class View : public Object {
- inline ViewImpl &
- impl(void)
- {
- return *(ViewImpl *)this;
- }
-
- class UndoTokenMessage : public UndoToken {
- ViewImpl &view;
- unsigned int iMessage;
- uptr_t wParam;
- sptr_t lParam;
+/** @protected */
+extern teco_view_t *teco_interface_current_view;
- public:
- UndoTokenMessage(ViewImpl &_view, unsigned int _iMessage,
- uptr_t _wParam = 0, sptr_t _lParam = 0)
- : view(_view), iMessage(_iMessage),
- wParam(_wParam), lParam(_lParam) {}
+/** @pure */
+void teco_interface_init(void);
- void
- run(void)
- {
- view.ssm(iMessage, wParam, lParam);
- }
- };
+/** @pure */
+GOptionGroup *teco_interface_get_options(void);
- class UndoTokenSetRepresentations : public UndoToken {
- ViewImpl &view;
+/** @pure makes sense only on Curses */
+void teco_interface_init_color(guint color, guint32 rgb);
- public:
- UndoTokenSetRepresentations(ViewImpl &_view)
- : view(_view) {}
+typedef enum {
+ TECO_MSG_USER,
+ TECO_MSG_INFO,
+ TECO_MSG_WARNING,
+ TECO_MSG_ERROR
+} teco_msg_t;
- void
- run(void)
- {
- view.set_representations();
- }
- };
+/** @pure */
+void teco_interface_vmsg(teco_msg_t type, const gchar *fmt, va_list ap);
-public:
- /*
- * called after Interface initialization.
- * Should call setup()
- */
- inline void
- initialize(void)
- {
- impl().initialize_impl();
- }
+static inline void G_GNUC_PRINTF(2, 3)
+teco_interface_msg(teco_msg_t type, const gchar *fmt, ...)
+{
+ va_list ap;
- inline sptr_t
- ssm(unsigned int iMessage,
- uptr_t wParam = 0, sptr_t lParam = 0)
- {
- return impl().ssm_impl(iMessage, wParam, lParam);
- }
+ va_start(ap, fmt);
+ teco_interface_vmsg(type, fmt, ap);
+ va_end(ap);
+}
- inline void
- undo_ssm(unsigned int iMessage,
- uptr_t wParam = 0, sptr_t lParam = 0)
- {
- undo.push<UndoTokenMessage>(impl(), iMessage, wParam, lParam);
- }
+/** @pure */
+void teco_interface_msg_clear(void);
- void set_representations(void);
- inline void
- undo_set_representations(void)
- {
- undo.push<UndoTokenSetRepresentations>(impl());
- }
+/** @pure */
+void teco_interface_show_view(teco_view_t *view);
+void undo__teco_interface_show_view(teco_view_t *);
- inline void
- set_scintilla_undo(bool state)
- {
- ssm(SCI_EMPTYUNDOBUFFER);
- ssm(SCI_SETUNDOCOLLECTION, state);
- }
+static inline sptr_t
+teco_interface_ssm(unsigned int iMessage, uptr_t wParam, sptr_t lParam)
+{
+ return teco_view_ssm(teco_interface_current_view, iMessage, wParam, lParam);
+}
-protected:
- void setup(void);
-};
-
-/**
- * Base class and interface of all SciTECO user interfaces
- * (e.g. Curses or GTK+).
- *
- * This uses the same Curiously Recurring Template Pattern (CRTP)
- * as the View interface above, as there is only one type of
- * user interface at runtime.
+/*
+ * NOTE: You could simply call undo__teco_view_ssm(teco_interface_current_view, ...).
+ * undo__teco_interface_ssm(...) exists for brevity and aestethics.
*/
-template <class InterfaceImpl, class ViewImpl>
-class Interface : public Object {
- inline InterfaceImpl &
- impl(void)
- {
- return *(InterfaceImpl *)this;
- }
-
- class UndoTokenShowView : public UndoToken {
- ViewImpl *view;
-
- public:
- UndoTokenShowView(ViewImpl *_view)
- : view(_view) {}
-
- void run(void);
- };
-
- template <class Type>
- class UndoTokenInfoUpdate : public UndoToken {
- const Type *obj;
-
- public:
- UndoTokenInfoUpdate(const Type *_obj)
- : obj(_obj) {}
-
- void run(void);
- };
-
-protected:
- ViewImpl *current_view;
-
-public:
- Interface() : current_view(NULL) {}
-
- /* default implementation */
- inline GOptionGroup *
- get_options(void)
- {
- return NULL;
- }
-
- /* default implementation */
- inline void init(void) {}
-
- /* makes sense only on Curses */
- inline void init_color(guint color, guint32 rgb) {}
+void undo__teco_interface_ssm(unsigned int, uptr_t, sptr_t);
- enum MessageType {
- MSG_USER,
- MSG_INFO,
- MSG_WARNING,
- MSG_ERROR
- };
- inline void
- vmsg(MessageType type, const gchar *fmt, va_list ap)
- {
- impl().vmsg_impl(type, fmt, ap);
- }
- inline void
- msg(MessageType type, const gchar *fmt, ...) G_GNUC_PRINTF(3, 4)
- {
- va_list ap;
+/** @pure */
+void teco_interface_info_update_qreg(const teco_qreg_t *reg);
+/** @pure */
+void teco_interface_info_update_buffer(const teco_buffer_t *buffer);
- va_start(ap, fmt);
- vmsg(type, fmt, ap);
- va_end(ap);
- }
- /* default implementation */
- inline void msg_clear(void) {}
+#define teco_interface_info_update(X) \
+ (_Generic((X), teco_qreg_t * : teco_interface_info_update_qreg, \
+ const teco_qreg_t * : teco_interface_info_update_qreg, \
+ teco_buffer_t * : teco_interface_info_update_buffer, \
+ const teco_buffer_t * : teco_interface_info_update_buffer)(X))
- inline void
- show_view(ViewImpl *view)
- {
- impl().show_view_impl(view);
- }
- inline void
- undo_show_view(ViewImpl *view)
- {
- undo.push<UndoTokenShowView>(view);
- }
+void undo__teco_interface_info_update_qreg(const teco_qreg_t *);
+void undo__teco_interface_info_update_buffer(const teco_buffer_t *);
- inline ViewImpl *
- get_current_view(void)
- {
- return current_view;
- }
+/** @pure */
+void teco_interface_cmdline_update(const teco_cmdline_t *cmdline);
- inline sptr_t
- ssm(unsigned int iMessage, uptr_t wParam = 0, sptr_t lParam = 0)
- {
- return current_view->ssm(iMessage, wParam, lParam);
- }
- inline void
- undo_ssm(unsigned int iMessage,
- uptr_t wParam = 0, sptr_t lParam = 0)
- {
- current_view->undo_ssm(iMessage, wParam, lParam);
- }
-
- /*
- * NOTE: could be rolled into a template, but
- * this way it is explicit what must be implemented
- * by the deriving class.
- */
- inline void
- info_update(const QRegister *reg)
- {
- impl().info_update_impl(reg);
- }
- inline void
- info_update(const Buffer *buffer)
- {
- impl().info_update_impl(buffer);
- }
-
- inline void
- undo_info_update(const QRegister *reg)
- {
- undo.push<UndoTokenInfoUpdate<QRegister>>(reg);
- }
- inline void
- undo_info_update(const Buffer *buffer)
- {
- undo.push<UndoTokenInfoUpdate<Buffer>>(buffer);
- }
-
- inline void
- cmdline_update(const Cmdline *cmdline)
- {
- impl().cmdline_update_impl(cmdline);
- }
-
- /* default implementation */
- inline void
- set_clipboard(const gchar *name,
- const gchar *str = NULL, gssize str_len = -1)
- {
- throw Error("Setting clipboard unsupported");
- }
-
- /* default implementation */
- inline gchar *
- get_clipboard(const gchar *name, gsize *str_len = NULL)
- {
- throw Error("Getting clipboard unsupported");
- }
-
- enum PopupEntryType {
- POPUP_PLAIN,
- POPUP_FILE,
- POPUP_DIRECTORY
- };
- inline void
- popup_add(PopupEntryType type,
- const gchar *name, bool highlight = false)
- {
- impl().popup_add_impl(type, name, highlight);
- }
- inline void
- popup_show(void)
- {
- impl().popup_show_impl();
- }
- inline bool
- popup_is_shown(void)
- {
- return impl().popup_is_shown_impl();
- }
- inline void
- popup_clear(void)
- {
- impl().popup_clear_impl();
- }
-
- /* default implementation */
- inline bool
- is_interrupted(void)
- {
- return sigint_occurred != FALSE;
- }
-
- /* main entry point */
- inline void
- event_loop(void)
- {
- impl().event_loop_impl();
- }
-
- /*
- * Interfacing to the external SciTECO world
- */
-protected:
- void stdio_vmsg(MessageType type, const gchar *fmt, va_list ap);
-public:
- void process_notify(SCNotification *notify);
-};
-
-} /* namespace SciTECO */
-
-#ifdef INTERFACE_GTK
-#include "interface-gtk/interface-gtk.h"
-#elif defined(INTERFACE_CURSES)
-#include "interface-curses/interface-curses.h"
-#else
-#error No interface selected!
-#endif
-
-namespace SciTECO {
+/** @pure */
+gboolean teco_interface_set_clipboard(const gchar *name, const gchar *str, gsize str_len,
+ GError **error);
+void teco_interface_undo_set_clipboard(const gchar *name, gchar *str, gsize len);
+/**
+ * Semantics are compatible with teco_qreg_vtable_t::get_string() since that is the
+ * main user of this function.
+ *
+ * @pure
+ */
+gboolean teco_interface_get_clipboard(const gchar *name, gchar **str, gsize *len, GError **error);
+
+typedef enum {
+ TECO_POPUP_PLAIN,
+ TECO_POPUP_FILE,
+ TECO_POPUP_DIRECTORY
+} teco_popup_entry_type_t;
+
+/** @pure */
+void teco_interface_popup_add(teco_popup_entry_type_t type,
+ const gchar *name, gsize name_len, gboolean highlight);
+/** @pure */
+void teco_interface_popup_show(void);
+/** @pure */
+gboolean teco_interface_popup_is_shown(void);
+/** @pure */
+void teco_interface_popup_clear(void);
+
+/** @pure */
+gboolean teco_interface_is_interrupted(void);
+
+/** @pure main entry point */
+gboolean teco_interface_event_loop(GError **error);
-/* object defined in main.cpp */
-extern InterfaceCurrent interface;
+/*
+ * Interfacing to the external SciTECO world
+ */
+/** @protected */
+void teco_interface_stdio_vmsg(teco_msg_t type, const gchar *fmt, va_list ap);
+void teco_interface_process_notify(struct SCNotification *notify);
-extern template class View<ViewCurrent>;
-extern template class Interface<InterfaceCurrent, ViewCurrent>;
+/** @pure */
+void teco_interface_cleanup(void);
-} /* namespace SciTECO */
+/*
+ * The following functions are here for lack of a better place.
+ * They could also be in sciteco.h, but only if declared as non-inline
+ * since sciteco.h should not depend on interface.h.
+ */
-#endif
+static inline gboolean
+teco_validate_pos(teco_int_t n)
+{
+ return 0 <= n && n <= teco_interface_ssm(SCI_GETLENGTH, 0, 0);
+}
+
+static inline gboolean
+teco_validate_line(teco_int_t n)
+{
+ return 0 <= n && n < teco_interface_ssm(SCI_GETLINECOUNT, 0, 0);
+}