SF.net SVN: geany:[3391] trunk
eht16 at users.sourceforge.net
eht16 at xxxxx
Wed Dec 17 16:00:18 UTC 2008
Revision: 3391
http://geany.svn.sourceforge.net/geany/?rev=3391&view=rev
Author: eht16
Date: 2008-12-17 16:00:18 +0000 (Wed, 17 Dec 2008)
Log Message:
-----------
Add "editor-notify" to the plugin API.
This signal is emitted whenever something in an editor widget changes, e.g. a character was typed.
Modified Paths:
--------------
trunk/ChangeLog
trunk/doc/Doxyfile.in
trunk/doc/plugins.dox
trunk/plugins/demoplugin.c
trunk/src/document.c
trunk/src/editor.c
trunk/src/editor.h
trunk/src/geany.h
trunk/src/geanyobject.c
trunk/src/geanyobject.h
trunk/src/plugindata.h
Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog 2008-12-17 15:59:25 UTC (rev 3390)
+++ trunk/ChangeLog 2008-12-17 16:00:18 UTC (rev 3391)
@@ -6,6 +6,12 @@
Retitle the Terminal/VTE preferences tab section.
Change (again) the key combinations for creating
rectangular selections.
+ * doc/Doxyfile.in, doc/plugins.dox, plugins/demoplugin.c, src/editor.c,
+ src/editor.h, src/document.c, src/geanyobject.c, src/geanyobject.h,
+ src/geany.h, src/plugindata.h:
+ Add "editor-notify" to the plugin API.
+ This signal is emitted whenever something in an editor widget
+ changes, e.g. a character was typed.
2008-12-16 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
Modified: trunk/doc/Doxyfile.in
===================================================================
--- trunk/doc/Doxyfile.in 2008-12-17 15:59:25 UTC (rev 3390)
+++ trunk/doc/Doxyfile.in 2008-12-17 16:00:18 UTC (rev 3391)
@@ -40,7 +40,7 @@
"endsignaldef= " \
"signalproto=@code " \
"endsignalproto=@endcode " \
- "signaldesc=@par Description: " \
+ "signaldesc=" \
"signals=@b Signals: " \
"endsignals= "
OPTIMIZE_OUTPUT_FOR_C = YES
Modified: trunk/doc/plugins.dox
===================================================================
--- trunk/doc/plugins.dox 2008-12-17 15:59:25 UTC (rev 3390)
+++ trunk/doc/plugins.dox 2008-12-17 16:00:18 UTC (rev 3391)
@@ -56,6 +56,7 @@
*
* To use plugin signals in Geany, you simply create a PluginCallback array, list the signals
* you want to listen to and create the appropiate signal callbacks for each signal.
+ * The callback array is read @a after plugin_init() has been called.
* @note The PluginCallback array has to be ended with a final NULL entry.
*
* The following code demonstrates how to use signals in Geany plugins. The code can be inserted
@@ -185,8 +186,46 @@
* @param user_data user data.
* @endsignaldef
*
+ * @signaldef editor-notify
+ * @signalproto
+ * gboolean user_function(GObject *obj, GeanyEditor *editor, SCNotification *nt,
+ * gpointer user_data);
+ * @endsignalproto
+ * @signaldesc
+ * This signal is sent whenever something in the editor widget changes (character added,
+ * fold level changes, clicks to the line number margin, ...).
+ * A detailed description of possible notifications and the SCNotification can be found at
+ * http://www.scintilla.org/ScintillaDoc.html#Notifications.
*
+ * If you connect to this signal, you must check @c nt->nmhdr.code for the notification type
+ * to prevent handling unwanted notifications. This is important because for instance SCN_UPDATEUI
+ * is sent very often whereas you probably don't want to handle this notification.
*
+ * By default, the signal is sent before Geany's default handler is processing the event.
+ * Your callback function should return FALSE to allow Geany processing the event as well. If you
+ * want to prevent this for some reason, return TRUE.
+ * Please use this with care as it can break basic functionality of Geany.
+ *
+ * The signal can be sent after Geany's default handler has been run when you set
+ * PluginCallback::after field to TRUE.
+ *
+ * An example callback implemention of this signal can be found in the Demo plugin.
+ *
+ * @warning This signal has much power and should be used carefully. You should especially
+ * care about the return value; make sure to return TRUE only if it is necessary
+ * and in the correct situations.
+ *
+ * @param obj a GeanyObject instance, should be ignored.
+ * @param editor The current GeanyEditor.
+ * @param nt A pointer to the SCNotification struct which holds additional information for
+ * the event.
+ * @param user_data user data.
+ * @return @c TRUE to stop other handlers from being invoked for the event.
+ * @c FALSE to propagate the event further.
+ * @endsignaldef
+ *
+ *
+ *
* @page howto Plugin Howto
*
* @section intro Introduction
Modified: trunk/plugins/demoplugin.c
===================================================================
--- trunk/plugins/demoplugin.c 2008-12-17 15:59:25 UTC (rev 3390)
+++ trunk/plugins/demoplugin.c 2008-12-17 16:00:18 UTC (rev 3391)
@@ -38,11 +38,13 @@
#include "geany.h" /* for the GeanyApp data type */
#include "support.h" /* for the _() translation macro (see also po/POTFILES.in) */
#include "ui_utils.h"
+#include "Scintilla.h" /* for the SCNotification struct */
#include "plugindata.h" /* this defines the plugin API */
#include "geanyfunctions.h" /* this wraps geany_functions function pointers */
+
/* These items are set by Geany before plugin_init() is called. */
GeanyPlugin *geany_plugin;
GeanyData *geany_data;
@@ -62,6 +64,61 @@
static gchar *welcome_text = NULL;
+
+static gboolean on_editor_notify(GObject *object, GeanyEditor *editor,
+ SCNotification *nt, gpointer data)
+{
+ /* For detailed documentation about the SCNotification struct, please see
+ * http://www.scintilla.org/ScintillaDoc.html#Notifications. */
+ switch (nt->nmhdr.code)
+ {
+ case SCN_UPDATEUI:
+ /* This notification is sent very often, you should not do time-consuming tasks here */
+ break;
+ case SCN_CHARADDED:
+ /* For demonstrating purposes simply print the typed character in the status bar */
+ ui_set_statusbar(FALSE, _("Typed character: %c"), nt->ch);
+ break;
+ case SCN_URIDROPPED:
+ {
+ /* Show a message dialog with the dropped URI list when files (i.e. a list of
+ * filenames) is dropped to the editor widget) */
+ if (nt->text != NULL)
+ {
+ GtkWidget *dialog;
+
+ dialog = gtk_message_dialog_new(
+ GTK_WINDOW(geany->main_widgets->window),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_INFO,
+ GTK_BUTTONS_OK,
+ _("The following files were dropped:"));
+ gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
+ "%s", nt->text);
+
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
+ }
+ /* we return TRUE here which prevents Geany from processing the SCN_URIDROPPED
+ * notification, i.e. Geany won't open the passed files */
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+PluginCallback plugin_callbacks[] =
+{
+ /* Set 'after' (third field) to TRUE to run the callback @a after the default handler.
+ * If 'after' is FALSE, the callback is run @a before the default handler, so the plugin
+ * can prevent Geany from processing the notification. Use this with care. */
+ { "editor-notify", (GCallback) &on_editor_notify, FALSE, NULL },
+ { NULL, NULL, FALSE, NULL }
+};
+
+
/* Callback when the menu item is clicked. */
static void
item_activate(GtkMenuItem *menuitem, gpointer gdata)
Modified: trunk/src/document.c
===================================================================
--- trunk/src/document.c 2008-12-17 15:59:25 UTC (rev 3390)
+++ trunk/src/document.c 2008-12-17 16:00:18 UTC (rev 3391)
@@ -595,7 +595,7 @@
sci_goto_pos(doc->editor->sci, 0, TRUE);
/* "the" SCI signal (connect after initial setup(i.e. adding text)) */
- g_signal_connect(doc->editor->sci, "sci-notify", G_CALLBACK(on_editor_notification), doc);
+ g_signal_connect(doc->editor->sci, "sci-notify", G_CALLBACK(editor_sci_notify_cb), doc);
g_signal_emit_by_name(geany_object, "document-new", doc);
@@ -1118,7 +1118,7 @@
doc->real_path = get_real_path_from_utf8(doc->file_name);
/* "the" SCI signal (connect after initial setup(i.e. adding text)) */
- g_signal_connect(doc->editor->sci, "sci-notify", G_CALLBACK(on_editor_notification), doc);
+ g_signal_connect(doc->editor->sci, "sci-notify", G_CALLBACK(editor_sci_notify_cb), doc);
use_ft = (ft != NULL) ? ft : filetypes_detect_from_document(doc);
}
Modified: trunk/src/editor.c
===================================================================
--- trunk/src/editor.c 2008-12-17 15:59:25 UTC (rev 3390)
+++ trunk/src/editor.c 2008-12-17 16:00:18 UTC (rev 3391)
@@ -249,8 +249,6 @@
}
-typedef struct SCNotification SCNotification;
-
static void fold_symbol_click(ScintillaObject *sci, SCNotification *nt)
{
gint line = sci_get_line_from_position(sci, nt->position);
@@ -624,18 +622,29 @@
}
-/* callback func called by all editors when a signal arises */
-void on_editor_notification(GtkWidget *widget, gint scn, gpointer lscn, gpointer user_data)
+/* Callback for the "sci-notify" signal to emit a "editor-notify" signal.
+ * Plugins can connect to the "editor-notify" signal. */
+void editor_sci_notify_cb(G_GNUC_UNUSED GtkWidget *widget, G_GNUC_UNUSED gint scn,
+ gpointer scnt, gpointer data)
{
- SCNotification *nt;
+ GeanyDocument *doc = data;
+ gboolean retval;
+
+ g_return_if_fail(doc != NULL);
+
+ g_signal_emit_by_name(geany_object, "editor-notify", doc->editor, scnt, &retval);
+}
+
+
+static gboolean on_editor_notify(G_GNUC_UNUSED GeanyObject *object, GeanyEditor *editor,
+ SCNotification *nt, gpointer data)
+{
ScintillaObject *sci;
- GeanyDocument *doc = user_data;
- GeanyEditor *editor;
+ GeanyDocument *doc = editor->document;
editor = doc->editor;
sci = editor->sci;
- nt = lscn;
switch (nt->nmhdr.code)
{
case SCN_SAVEPOINTLEFT:
@@ -754,6 +763,8 @@
break;
}
}
+ /* we always return FALSE here to let plugins handle the event to */
+ return FALSE;
}
@@ -4158,6 +4169,10 @@
memset(&editor_prefs, 0, sizeof(GeanyEditorPrefs));
memset(&indent_prefs, 0, sizeof(GeanyIndentPrefs));
editor_prefs.indentation = &indent_prefs;
+
+ /* use g_signal_connect_after() to allow plugins connecting to the signal before the default
+ * handler (on_editor_notify) is called */
+ g_signal_connect_after(geany_object, "editor-notify", G_CALLBACK(on_editor_notify), NULL);
}
Modified: trunk/src/editor.h
===================================================================
--- trunk/src/editor.h 2008-12-17 15:59:25 UTC (rev 3390)
+++ trunk/src/editor.h 2008-12-17 16:00:18 UTC (rev 3391)
@@ -131,7 +131,7 @@
/** Editor-owned fields for each document. */
-typedef struct GeanyEditor
+struct GeanyEditor
{
GeanyDocument *document; /**< The document associated with the editor. */
ScintillaObject *sci; /**< The Scintilla editor @c GtkWidget. */
@@ -141,8 +141,7 @@
gfloat scroll_percent;
GeanyIndentType indent_type; /* Use editor_get_indent_prefs() instead. */
gboolean line_breaking; /**< Whether to split long lines as you type. */
-}
-GeanyEditor;
+};
typedef struct
@@ -153,9 +152,9 @@
extern EditorInfo editor_info;
+typedef struct SCNotification SCNotification;
-
void editor_init(void);
GeanyEditor *editor_create(GeanyDocument *doc);
@@ -164,7 +163,7 @@
ScintillaObject *editor_create_widget(GeanyEditor *editor);
-void on_editor_notification(GtkWidget* editor, gint scn, gpointer lscn, gpointer user_data);
+void editor_sci_notify_cb(GtkWidget *widget, gint scn, gpointer scnt, gpointer data);
gboolean editor_start_auto_complete(GeanyEditor *editor, gint pos, gboolean force);
Modified: trunk/src/geany.h
===================================================================
--- trunk/src/geany.h 2008-12-17 15:59:25 UTC (rev 3390)
+++ trunk/src/geany.h 2008-12-17 16:00:18 UTC (rev 3391)
@@ -56,6 +56,7 @@
/* Common forward declarations */
typedef struct GeanyDocument GeanyDocument;
+typedef struct GeanyEditor GeanyEditor;
typedef struct GeanyFiletype GeanyFiletype;
Modified: trunk/src/geanyobject.c
===================================================================
--- trunk/src/geanyobject.c 2008-12-17 15:59:25 UTC (rev 3390)
+++ trunk/src/geanyobject.c 2008-12-17 16:00:18 UTC (rev 3391)
@@ -81,10 +81,10 @@
static void geany_cclosure_marshal_VOID__STRING_INT_POINTER(GClosure *closure, GValue *ret_val,
guint n_param_vals, const GValue *param_values, gpointer hint, gpointer mdata)
{
- typedef gboolean (*GMarshalFunc_VOID__STRING_INT_POINTER)
+ typedef gboolean (*GeanyMarshalFunc_VOID__STRING_INT_POINTER)
(gpointer data1, gconstpointer arg_1, gint arg_2, gpointer arg_3, gpointer data2);
- register GMarshalFunc_VOID__STRING_INT_POINTER callback;
+ register GeanyMarshalFunc_VOID__STRING_INT_POINTER callback;
register GCClosure* cc = (GCClosure*) closure;
register gpointer data1, data2;
@@ -100,7 +100,7 @@
data1 = g_value_peek_pointer(param_values + 0);
data2 = closure->data;
}
- callback = (GMarshalFunc_VOID__STRING_INT_POINTER) (mdata ? mdata : cc->callback);
+ callback = (GeanyMarshalFunc_VOID__STRING_INT_POINTER) (mdata ? mdata : cc->callback);
callback(data1,
g_value_get_string(param_values + 1),
g_value_get_int(param_values + 2),
@@ -109,8 +109,59 @@
}
+static gboolean boolean_handled_accumulator(GSignalInvocationHint *ihint, GValue *return_accu,
+ const GValue *handler_return, gpointer dummy)
+{
+ gboolean continue_emission, signal_handled;
+
+ signal_handled = g_value_get_boolean(handler_return);
+ g_value_set_boolean(return_accu, signal_handled);
+ continue_emission = !signal_handled;
+
+ return continue_emission;
+}
+
+
+static void geany_cclosure_marshal_BOOL__POINTER_POINTER( GClosure *closure, GValue *return_value,
+ guint n_param_values, const GValue *param_values,
+ gpointer invocation_hint G_GNUC_UNUSED, gpointer marshal_data)
+{
+ typedef gboolean (*GeanyMarshalFunc_BOOLEAN__POINTER_POINTER)
+ (gpointer data1, gpointer arg_1, gpointer arg_2, gpointer data2);
+
+ register GeanyMarshalFunc_BOOLEAN__POINTER_POINTER callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+ gboolean v_return;
+
+ g_return_if_fail(return_value != NULL);
+ g_return_if_fail(n_param_values == 3);
+
+ if (G_CCLOSURE_SWAP_DATA(closure))
+ {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer(param_values + 0);
+ }
+ else
+ {
+ data1 = g_value_peek_pointer(param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (GeanyMarshalFunc_BOOLEAN__POINTER_POINTER)
+ (marshal_data ? marshal_data : cc->callback);
+
+ v_return = callback(data1,
+ g_value_get_pointer(param_values + 1),
+ g_value_get_pointer(param_values + 2),
+ data2);
+
+ g_value_set_boolean(return_value, v_return);
+}
+
+
static void create_signals(GObjectClass *g_object_class)
{
+ /* Document signals */
geany_object_signals[GCB_DOCUMENT_NEW] = g_signal_new (
"document-new",
G_OBJECT_CLASS_TYPE (g_object_class),
@@ -157,6 +208,7 @@
G_TYPE_NONE, 1,
G_TYPE_POINTER);
+ /* Project signals */
geany_object_signals[GCB_PROJECT_OPEN] = g_signal_new (
"project-open",
G_OBJECT_CLASS_TYPE (g_object_class),
@@ -184,6 +236,7 @@
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
+ /* Editor signals */
geany_object_signals[GCB_UPDATE_EDITOR_MENU] = g_signal_new (
"update-editor-menu",
G_OBJECT_CLASS_TYPE (g_object_class),
@@ -193,6 +246,15 @@
geany_cclosure_marshal_VOID__STRING_INT_POINTER,
G_TYPE_NONE, 3,
G_TYPE_STRING, G_TYPE_INT, G_TYPE_POINTER);
+ geany_object_signals[GCB_EDITOR_NOTIFY] = g_signal_new (
+ "editor-notify",
+ G_OBJECT_CLASS_TYPE (g_object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GeanyObjectClass, update_editor_menu),
+ boolean_handled_accumulator, NULL,
+ geany_cclosure_marshal_BOOL__POINTER_POINTER,
+ G_TYPE_BOOLEAN, 2,
+ G_TYPE_POINTER, G_TYPE_POINTER);
}
Modified: trunk/src/geanyobject.h
===================================================================
--- trunk/src/geanyobject.h 2008-12-17 15:59:25 UTC (rev 3390)
+++ trunk/src/geanyobject.h 2008-12-17 16:00:18 UTC (rev 3391)
@@ -43,6 +43,7 @@
GCB_PROJECT_SAVE,
GCB_PROJECT_CLOSE,
GCB_UPDATE_EDITOR_MENU,
+ GCB_EDITOR_NOTIFY,
GCB_MAX
} GeanyCallbackId;
@@ -81,6 +82,7 @@
void (*project_save)(GKeyFile *keyfile);
void (*project_close)(void);
void (*update_editor_menu)(const gchar *word, gint click_pos, GeanyDocument *doc);
+ gboolean (*editor_notify)(GeanyEditor *editor, gpointer scnt);
};
GType geany_object_get_type (void);
Modified: trunk/src/plugindata.h
===================================================================
--- trunk/src/plugindata.h 2008-12-17 15:59:25 UTC (rev 3390)
+++ trunk/src/plugindata.h 2008-12-17 16:00:18 UTC (rev 3391)
@@ -45,7 +45,7 @@
enum {
/** The Application Programming Interface (API) version, incremented
* whenever any plugin data types are modified or appended to. */
- GEANY_API_VERSION = 118,
+ GEANY_API_VERSION = 119,
/** The Application Binary Interface (ABI) version, incremented whenever
* existing fields in the plugin data types have to be changed or reordered. */
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the Commits
mailing list