gedit r6434 - in branches/new_plugins: bindings/python gedit
- From: jessevdk svn gnome org
- To: svn-commits-list gnome org
- Subject: gedit r6434 - in branches/new_plugins: bindings/python gedit
- Date: Wed, 20 Aug 2008 09:53:09 +0000 (UTC)
Author: jessevdk
Date: Wed Aug 20 09:53:09 2008
New Revision: 6434
URL: http://svn.gnome.org/viewvc/gedit?rev=6434&view=rev
Log:
Implemented message system
Added:
branches/new_plugins/gedit/gedit-message-bus.c
branches/new_plugins/gedit/gedit-message-bus.h
branches/new_plugins/gedit/gedit-message.c
branches/new_plugins/gedit/gedit-message.h
Modified:
branches/new_plugins/bindings/python/Makefile.am
branches/new_plugins/bindings/python/gedit.defs
branches/new_plugins/bindings/python/gedit.override
branches/new_plugins/gedit/Makefile.am
Modified: branches/new_plugins/bindings/python/Makefile.am
==============================================================================
--- branches/new_plugins/bindings/python/Makefile.am (original)
+++ branches/new_plugins/bindings/python/Makefile.am Wed Aug 20 09:53:09 2008
@@ -58,13 +58,15 @@
gedit/gedit-encodings.h \
gedit/gedit-plugin.h \
gedit/gedit-view.h \
- gedit/gedit-status-bar.h \
+ gedit/gedit-statusbar.h \
gedit/gedit-tab.h \
gedit/gedit-panel.h \
gedit/gedit-window.h \
gedit/gedit-help.h \
gedit/gedit-debug.h \
- gedit/gedit-language-manager.h
+ gedit/gedit-language-manager.h \
+ gedit/gedit-message-bus.h \
+ gedit/gedit-message.h
BINDING_UTILS_HEADERS_SRCDIR_IN = \
gedit/gedit-utils.h
Modified: branches/new_plugins/bindings/python/gedit.defs
==============================================================================
--- branches/new_plugins/bindings/python/gedit.defs (original)
+++ branches/new_plugins/bindings/python/gedit.defs Wed Aug 20 09:53:09 2008
@@ -14,6 +14,20 @@
(gtype-id "GEDIT_TYPE_DOCUMENT")
)
+(define-object Message
+ (in-module "Gedit")
+ (parent "GObject")
+ (c-name "GeditMessage")
+ (gtype-id "GEDIT_TYPE_MESSAGE")
+)
+
+(define-object MessageBus
+ (in-module "Gedit")
+ (parent "GObject")
+ (c-name "GeditMessageBus")
+ (gtype-id "GEDIT_TYPE_MESSAGE_BUS")
+)
+
(define-object Panel
(in-module "Gedit")
(parent "GtkVBox")
@@ -971,6 +985,254 @@
)
)
+
+;; From gedit-message-bus.h
+
+(define-function gedit_message_bus_get_type
+ (c-name "gedit_message_bus_get_type")
+ (return-type "GType")
+)
+
+(define-function message_bus_get
+ (c-name "gedit_message_bus_get")
+ (return-type "GeditMessageBus*")
+)
+
+(define-method connect
+ (of-object "GeditMessageBus")
+ (c-name "gedit_message_bus_connect")
+ (return-type "guint")
+ (parameters
+ '("const-gchar*" "domain")
+ '("const-gchar*" "name")
+ '("GeditMessageCallback" "callback")
+ '("gpointer" "userdata")
+ )
+)
+
+(define-method disconnect
+ (of-object "GeditMessageBus")
+ (c-name "gedit_message_bus_disconnect")
+ (return-type "none")
+ (parameters
+ '("guint" "id")
+ )
+)
+
+(define-method disconnect_by_func
+ (of-object "GeditMessageBus")
+ (c-name "gedit_message_bus_disconnect_by_func")
+ (return-type "none")
+ (parameters
+ '("const-gchar*" "domain")
+ '("const-gchar*" "name")
+ '("GeditMessageCallback" "callback")
+ '("gpointer" "userdata")
+ )
+)
+
+(define-method block
+ (of-object "GeditMessageBus")
+ (c-name "gedit_message_bus_block")
+ (return-type "none")
+ (parameters
+ '("guint" "id")
+ )
+)
+
+(define-method block_by_func
+ (of-object "GeditMessageBus")
+ (c-name "gedit_message_bus_block_by_func")
+ (return-type "none")
+ (parameters
+ '("const-gchar*" "domain")
+ '("const-gchar*" "name")
+ '("GeditMessageCallback" "callback")
+ '("gpointer" "userdata")
+ )
+)
+
+(define-method unblock
+ (of-object "GeditMessageBus")
+ (c-name "gedit_message_bus_unblock")
+ (return-type "none")
+ (parameters
+ '("guint" "id")
+ )
+)
+
+(define-method unblock_by_func
+ (of-object "GeditMessageBus")
+ (c-name "gedit_message_bus_unblock_by_func")
+ (return-type "none")
+ (parameters
+ '("const-gchar*" "domain")
+ '("const-gchar*" "name")
+ '("GeditMessageCallback" "callback")
+ '("gpointer" "userdata")
+ )
+)
+
+(define-method send_message
+ (of-object "GeditMessageBus")
+ (c-name "gedit_message_bus_send_message")
+ (return-type "none")
+ (parameters
+ '("GeditMessage*" "message")
+ )
+)
+
+(define-method send_message_sync
+ (of-object "GeditMessageBus")
+ (c-name "gedit_message_bus_send_message_sync")
+ (return-type "none")
+ (parameters
+ '("GeditMessage*" "message")
+ )
+)
+
+(define-method send
+ (of-object "GeditMessageBus")
+ (c-name "gedit_message_bus_send")
+ (return-type "none")
+ (parameters
+ '("const-gchar*" "domain")
+ '("const-gchar*" "name")
+ )
+ (varargs #t)
+)
+
+(define-method send_sync
+ (of-object "GeditMessageBus")
+ (c-name "gedit_message_bus_send_sync")
+ (return-type "GeditMessage*")
+ (parameters
+ '("const-gchar*" "domain")
+ '("const-gchar*" "name")
+ )
+ (varargs #t)
+)
+
+
+
+;; From gedit-message.h
+
+(define-function gedit_message_get_type
+ (c-name "gedit_message_get_type")
+ (return-type "GType")
+)
+
+(define-function gedit_message_new
+ (c-name "gedit_message_new")
+ (is-constructor-of "GeditMessage")
+ (return-type "GeditMessage*")
+ (parameters
+ '("const-gchar*" "domain")
+ '("const-gchar*" "name")
+ )
+ (varargs #t)
+)
+
+(define-function gedit_message_new_valist
+ (c-name "gedit_message_new_valist")
+ (return-type "GeditMessage*")
+ (parameters
+ '("const-gchar*" "domain")
+ '("const-gchar*" "name")
+ '("va_list" "var_args")
+ )
+)
+
+(define-method set_types
+ (of-object "GeditMessage")
+ (c-name "gedit_message_set_types")
+ (return-type "none")
+ (parameters
+ '("const-gchar**" "keys")
+ '("GType*" "types")
+ '("gint" "n_types")
+ )
+)
+
+(define-method get_domain
+ (of-object "GeditMessage")
+ (c-name "gedit_message_get_domain")
+ (return-type "const-gchar*")
+)
+
+(define-method get_name
+ (of-object "GeditMessage")
+ (c-name "gedit_message_get_name")
+ (return-type "const-gchar*")
+)
+
+(define-method get
+ (of-object "GeditMessage")
+ (c-name "gedit_message_get")
+ (return-type "none")
+ (parameters
+ )
+ (varargs #t)
+)
+
+(define-method get_valist
+ (of-object "GeditMessage")
+ (c-name "gedit_message_get_valist")
+ (return-type "none")
+ (parameters
+ '("va_list" "var_args")
+ )
+)
+
+(define-method get_value
+ (of-object "GeditMessage")
+ (c-name "gedit_message_get_value")
+ (return-type "none")
+ (parameters
+ '("const-gchar*" "key")
+ '("GValue*" "value")
+ )
+)
+
+(define-method set
+ (of-object "GeditMessage")
+ (c-name "gedit_message_set")
+ (return-type "none")
+ (parameters
+ )
+ (varargs #t)
+)
+
+(define-method set_valist
+ (of-object "GeditMessage")
+ (c-name "gedit_message_set_valist")
+ (return-type "none")
+ (parameters
+ '("va_list" "var_args")
+ )
+)
+
+(define-method set_value
+ (of-object "GeditMessage")
+ (c-name "gedit_message_set_value")
+ (return-type "none")
+ (parameters
+ '("const-gchar*" "key")
+ '("GValue*" "value")
+ )
+)
+
+(define-method set_valuesv
+ (of-object "GeditMessage")
+ (c-name "gedit_message_set_valuesv")
+ (return-type "none")
+ (parameters
+ '("const-gchar**" "keys")
+ '("GValue*" "values")
+ '("gint" "n_values")
+ )
+)
+
;; From ../../gedit/gedit-debug.h
(define-function debug
Modified: branches/new_plugins/bindings/python/gedit.override
==============================================================================
--- branches/new_plugins/bindings/python/gedit.override (original)
+++ branches/new_plugins/bindings/python/gedit.override Wed Aug 20 09:53:09 2008
@@ -11,6 +11,8 @@
#include "gedit-enum-types.h"
#include "gedit-statusbar.h"
#include "gedit-debug.h"
+#include "gedit-message-bus.h"
+#include "gedit-message.h"
void pygedit_register_classes (PyObject *d);
void pygedit_add_constants (PyObject *module, const gchar *strip_prefix);
@@ -58,6 +60,213 @@
}
return py_list;
}
+
+static int
+_helper_wrap_message_types(PyObject *args, const gchar ***keys, GType **types, gint *num, gboolean direct)
+{
+ guint len, i;
+
+ len = PyTuple_Size(args);
+
+ if (len == 1 && PyDict_Check(PyTuple_GetItem(args, 0)))
+ {
+ /* get key -> gtype from mapping */
+ PyObject *dict = PyTuple_GetItem(args, 0);
+ PyObject *key;
+ PyObject *value;
+
+ *num = PyDict_Size(dict);
+ *types = g_new(GType, num);
+ *keys = g_new(const gchar *, num);
+
+ while (PyDict_Next(dict, &i, &key, &value)) {
+ *keys[i] = PyString_AsString(key);
+
+ if (direct) {
+ *types[i] = pyg_type_from_object(value);
+ } else {
+ PyObject *pytype = PyObject_Type(value);
+ *types[i] = pytype ? pyg_type_from_object(pytype) : 0;
+ Py_DECREF(pytype);
+ }
+
+ if (*types[i] == 0 || *keys[i] == NULL) {
+ g_free(*types);
+ g_free(*keys);
+ return 0;
+ }
+ }
+ }
+ else
+ {
+ if (len % 2 != 0) {
+ PyErr_SetString(PyExc_TypeError,
+ "Even number of arguments expected (name/type pairs)");
+ return 0;
+ }
+
+ *num = len / 2;
+ *types = g_new(GType, *num);
+ *keys = g_new(const gchar *, *num);
+
+ for (i = 0; i < *num; i++) {
+ PyObject *key = PyTuple_GetItem(args, i * 2);
+ PyObject *value = PyTuple_GetItem(args, i * 2 + 1);
+
+ *keys[i] = PyString_AsString(key);
+
+ if (direct) {
+ *types[i] = pyg_type_from_object(value);
+ } else {
+ PyObject *pytype = PyObject_Type(value);
+ *types[i] = pytype ? pyg_type_from_object(pytype) : 0;
+ Py_DECREF(pytype);
+ }
+
+ if (*types[i] == 0 || *keys[i] == NULL) {
+ g_free(*types);
+ g_free(*keys);
+ return 0;
+ }
+ }
+ }
+
+ return 1;
+}
+
+static int
+_helper_wrap_message_set_value(PyGObject *self, PyObject *pykey, PyObject *pyvalue)
+{
+ const gchar *key;
+ GType gtype;
+ GValue value = {0,};
+
+ key = PyString_AsString(pykey);
+
+ if (key == NULL)
+ return 0;
+
+ gtype = gedit_message_get_key_type(GEDIT_MESSAGE(self->obj), key);
+
+ if (gtype == 0) {
+ PyErr_SetString(PyExc_TypeError, "invalid key");
+ return 0;
+ }
+
+ g_value_init(&value, gtype);
+
+ if (pyg_value_from_pyobject(&value, pyvalue)) {
+ PyErr_SetString(PyExc_TypeError,
+ "value is of the wrong type for this key");
+ return 0;
+ }
+
+ gedit_message_set_value(GEDIT_MESSAGE(self->obj), key, &value);
+ g_value_unset(&value);
+
+ return 1;
+}
+
+static int
+_helper_wrap_message_set_values(PyGObject *self, PyObject *args)
+{
+ guint len, i;
+
+ len = PyTuple_Size(args);
+
+ if (len == 1 && PyDict_Check(PyTuple_GetItem(args, 0)))
+ {
+ /* do key -> value from mapping */
+ PyObject *dict = PyTuple_GetItem(args, 0);
+ PyObject *pykey, *pyvalue;
+
+ while (PyDict_Next(dict, &i, &pykey, &pyvalue)) {
+ if (!_helper_wrap_message_set_value(self, pykey, pyvalue))
+ return 0;
+ }
+ } else {
+ if (len % 2 != 0) {
+ PyErr_SetString(PyExc_TypeError,
+ "Even number of arguments expected (name/type pairs)");
+ return 0;
+ }
+
+ for (i = 0; i < len / 2; i++) {
+ PyObject *pykey = PyTuple_GetItem(args, i * 2);
+ PyObject *pyvalue = PyTuple_GetItem(args, i * 2 + 1);
+
+ if (!_helper_wrap_message_set_value(self, pykey, pyvalue))
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static GeditMessage *
+_helper_wrap_create_message(PyObject *args)
+{
+ guint len, num;
+ const gchar *domain;
+ const gchar *name;
+ GType *types;
+ const gchar **keys;
+ PyObject *slice;
+ GeditMessage *message;
+
+ len = PyTuple_Size(args);
+
+ if (len < 2) {
+ PyErr_SetString(PyExc_TypeError,
+ "GeditMessage requires at least two arguments");
+ return NULL;
+ }
+
+ domain = PyString_AsString(PyTuple_GetItem(args, 0));
+ name = PyString_AsString(PyTuple_GetItem(args, 1));
+
+ if (!domain || !name) {
+ PyErr_SetString(PyExc_TypeError,
+ "First two arguments need to be strings");
+ return NULL;
+ }
+
+ slice = PyTuple_GetSlice (args, 2, len);
+
+ if (!_helper_wrap_message_types (slice, &keys, &types, &num, FALSE)) {
+ Py_DECREF(slice);
+ return NULL;
+ }
+
+ message = g_object_new(GEDIT_TYPE_MESSAGE, "domain", domain, "name", name, NULL);
+ gedit_message_set_types (message, keys, types, num);
+
+ g_free(types);
+ g_free(keys);
+
+ return message;
+}
+
+typedef struct {
+ PyObject *func;
+ PyObject *data;
+} PyGeditCustomNotify;
+
+static void
+pygedit_custom_destroy_notify(gpointer user_data)
+{
+ PyGeditCustomNotify *cunote = user_data;
+ PyGILState_STATE state;
+
+ g_return_if_fail(user_data);
+ state = pyg_gil_state_ensure();
+ Py_XDECREF(cunote->func);
+ Py_XDECREF(cunote->data);
+ pyg_gil_state_release(state);
+
+ g_free(cunote);
+}
+
%%
modulename gedit
%%
@@ -77,6 +286,13 @@
*_get_type
gedit_document_error_quark
gedit_panel_add_item_with_stock_icon
+ gedit_message_new_valist
+ gedit_message_get_valist
+ gedit_message_set_valist
+ gedit_message_set_valuesv
+ gedit_message_bus_disconnect_by_func
+ gedit_message_bus_block_by_func
+ gedit_message_bus_unblock_by_func
%%
override gedit_app_create_window kwargs
static PyObject *
@@ -435,3 +651,220 @@
return Py_None;
}
%%
+override gedit_message_new
+static int
+_wrap_gedit_message_new(PyGObject *self, PyObject *args)
+{
+ self->obj = (GObject *)_helper_wrap_create_message(args);
+
+ if (!self->obj) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "could not create GeditMessage object");
+ return -1;
+ }
+ pygobject_register_wrapper((PyObject *)self);
+
+ return 0;
+}
+%%
+override gedit_message_set_types args
+static PyObject *
+_wrap_gedit_message_set_types(PyGObject *self, PyObject *args)
+{
+ guint num;
+ GType *types;
+ const gchar **keys;
+
+ if (!_helper_wrap_message_types (args, &keys, &types, &num, TRUE)) {
+ return NULL;
+ }
+
+ gedit_message_set_types (GEDIT_MESSAGE(self->obj), keys, types, num);
+
+ g_free(types);
+ g_free(keys);
+
+ Py_INCREF (Py_None);
+ return Py_None;
+}
+%%
+override gedit_message_get args
+static PyObject *
+_wrap_gedit_message_get(PyGObject *self, PyObject *args)
+{
+ guint len, i;
+ PyObject *ret;
+
+ len = PyTuple_Size(args);
+
+ ret = PyTuple_New(len);
+
+ for (i = 0; i < len; i++) {
+ GValue value = { 0, };
+ PyObject *py_key = PyTuple_GetItem(args, i);
+ const gchar *key;
+
+ if (!PyString_Check(py_key)) {
+ PyErr_SetString(PyExc_TypeError, "keys must be strings");
+ Py_DECREF(ret);
+ return NULL;
+ }
+
+ key = PyString_AsString(py_key);
+ gedit_message_get_value (GEDIT_MESSAGE (self->obj), key, &value);
+
+ PyTuple_SetItem(ret, i, pyg_value_as_pyobject(&value, TRUE));
+ g_value_unset(&value);
+ }
+
+ return ret;
+}
+%%
+override gedit_message_get_value kwargs
+static PyObject *
+_wrap_gedit_message_get_value(PyGObject *self, PyObject *args, PyObject *kwargs)
+{
+ static char *kwlist[] = { "key", NULL };
+ const gchar *key;
+ PyObject *ret;
+ GValue value = { 0, };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s:GeditMessage.get_value", kwlist, &key))
+ return NULL;
+
+ gedit_message_get_value(GEDIT_MESSAGE(self->obj), key, &value);
+ ret = pyg_value_as_pyobject(&value, TRUE);
+ g_value_unset(&value);
+
+ return ret;
+}
+%%
+override gedit_message_set_value kwargs
+static PyObject *
+_wrap_gedit_message_set_value(PyGObject *self, PyObject *args, PyObject *kwargs)
+{
+ static char *kwlist[] = { "key", "value", NULL };
+ PyObject *ret, *pykey, *pyvalue;
+ GValue value = { 0, };
+ GType gtype;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO:GeditMessage.set_value", kwlist, &pykey, &pyvalue))
+ return NULL;
+
+ if (!_helper_wrap_message_set_value(self, pykey, pyvalue))
+ return NULL;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+%%
+override gedit_message_set args
+static PyObject *
+_wrap_gedit_message_set (PyGObject *self, PyObject *args) {
+ if (!_helper_wrap_message_set_values(self, args))
+ return NULL;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+%%
+override gedit_message_bus_connect kwargs
+static void
+pygedit_message_bus_connect_cb(GeditMessageBus *bus, GeditMessage *message, gpointer data)
+{
+ PyGILState_STATE state;
+ PyGeditCustomNotify *cunote = data;
+ PyObject *pybus, *pymessage, *retobj;
+ gboolean ret = FALSE;
+
+ g_assert(cunote->func);
+
+ state = pyg_gil_state_ensure();
+
+ pybus = pygobject_new((GObject *)bus);
+ pymessage = pygobject_new((GObject *)message);
+
+ if (cunote->data) {
+ retobj = PyEval_CallFunction(cunote->func, "(NNO)", pybus, pymessage, cunote->data);
+ } else {
+ retobj = PyEval_CallFunction(cunote->func, "(NN)", pybus, pymessage);
+ }
+
+ if (PyErr_Occurred()) {
+ PyErr_Print();
+ }
+
+ Py_XDECREF(retobj);
+
+ pyg_gil_state_release(state);
+}
+
+static PyObject *
+_wrap_gedit_message_bus_connect(PyGObject *self, PyObject *args, PyObject *kwargs)
+{
+ static char *kwlist[] = { "domain", "name", "func", "data", NULL };
+ PyObject *pyfunc, *pyarg = NULL;
+ const gchar *domain;
+ const gchar *name;
+ PyGeditCustomNotify *cunote;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "ssO|O:GeditMessageBus.connect",
+ kwlist, &domain, &name, &pyfunc, &pyarg))
+ return NULL;
+
+ if (!PyCallable_Check(pyfunc)) {
+ PyErr_SetString(PyExc_TypeError, "func must be a callable object");
+ return NULL;
+ }
+ cunote = g_new(PyGeditCustomNotify, 1);
+ Py_INCREF(pyfunc);
+ cunote->func = pyfunc;
+ Py_XINCREF(pyarg);
+ cunote->data = pyarg;
+
+ gedit_message_bus_connect(GEDIT_MESSAGE_BUS(self->obj),
+ domain,
+ name,
+ pygedit_message_bus_connect_cb,
+ (gpointer)cunote,
+ pygedit_custom_destroy_notify);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+%%
+override gedit_message_bus_send args
+static PyObject *
+_wrap_gedit_message_bus_send (PyGObject *self, PyObject *args)
+{
+ /* create a new message object */
+ GeditMessage *message;
+
+ message = _helper_wrap_create_message(args);
+
+ if (!message)
+ return NULL;
+
+ gedit_message_bus_send_message(GEDIT_MESSAGE_BUS(self->obj), message);
+ g_object_unref (message);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+%%
+override gedit_message_bus_send_sync args
+static PyObject *
+_wrap_gedit_message_bus_send_sync (PyGObject *self, PyObject *args)
+{
+ /* create a new message object */
+ GeditMessage *message;
+
+ message = _helper_wrap_create_message(args);
+
+ if (!message)
+ return NULL;
+
+ gedit_message_bus_send_message_sync(GEDIT_MESSAGE_BUS(self->obj), message);
+ return pygobject_new((GObject *)message);
+}
+%%
Modified: branches/new_plugins/gedit/Makefile.am
==============================================================================
--- branches/new_plugins/gedit/Makefile.am (original)
+++ branches/new_plugins/gedit/Makefile.am Wed Aug 20 09:53:09 2008
@@ -93,6 +93,8 @@
gedit-encodings-option-menu.h \
gedit-file-chooser-dialog.h \
gedit-help.h \
+ gedit-message.h \
+ gedit-message-bus.h \
gedit-message-area.h \
gedit-metadata-manager.h \
gedit-notebook.h \
@@ -140,6 +142,8 @@
gedit-history-entry.c \
gedit-io-error-message-area.c \
gedit-language-manager.c \
+ gedit-message.c \
+ gedit-message-bus.c \
gedit-message-area.c \
gedit-metadata-manager.c \
gedit-module.c \
Added: branches/new_plugins/gedit/gedit-message-bus.c
==============================================================================
--- (empty file)
+++ branches/new_plugins/gedit/gedit-message-bus.c Wed Aug 20 09:53:09 2008
@@ -0,0 +1,564 @@
+#include "gedit-message-bus.h"
+
+#include <string.h>
+#include <stdarg.h>
+#include <gobject/gvaluecollector.h>
+
+#define GEDIT_MESSAGE_BUS_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GEDIT_TYPE_MESSAGE_BUS, GeditMessageBusPrivate))
+
+typedef struct
+{
+ gchar *domain;
+ gchar *name;
+
+ GList *listeners;
+} Message;
+
+typedef struct
+{
+ guint id;
+ gboolean blocked;
+
+ GDestroyNotify destroy_data;
+ GeditMessageCallback callback;
+ gpointer userdata;
+} Listener;
+
+typedef struct
+{
+ Message *message;
+ GList *listener;
+} IdMap;
+
+struct _GeditMessageBusPrivate
+{
+ GHashTable *messages;
+ GHashTable *idmap;
+
+ GList *message_queue;
+ guint idle_id;
+
+ guint next_id;
+};
+
+G_DEFINE_TYPE(GeditMessageBus, gedit_message_bus, G_TYPE_OBJECT)
+
+static void
+listener_free (Listener *listener)
+{
+ if (listener->destroy_data)
+ listener->destroy_data (listener->userdata);
+
+ g_free (listener);
+}
+
+static void
+message_free (Message *message)
+{
+ g_free (message->name);
+ g_free (message->domain);
+
+ g_list_foreach (message->listeners, (GFunc)listener_free, NULL);
+ g_list_free (message->listeners);
+
+ g_free (message);
+}
+
+static void
+message_queue_free (GList *queue)
+{
+ g_list_foreach (queue, (GFunc)g_object_unref, NULL);
+ g_list_free (queue);
+}
+
+static void
+gedit_message_bus_finalize (GObject *object)
+{
+ GeditMessageBus *bus = GEDIT_MESSAGE_BUS (object);
+
+ if (bus->priv->idle_id != 0)
+ g_source_remove (bus->priv->idle_id);
+
+ message_queue_free (bus->priv->message_queue);
+
+ G_OBJECT_CLASS (gedit_message_bus_parent_class)->finalize (object);
+}
+
+static void
+gedit_message_bus_class_init (GeditMessageBusClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gedit_message_bus_finalize;
+
+ g_type_class_add_private (object_class, sizeof(GeditMessageBusPrivate));
+}
+
+inline static gchar *
+msg_identifier (const gchar *domain,
+ const gchar *name)
+{
+ return g_strconcat (domain, "::", name, NULL);
+}
+
+static Message *
+message_new (GeditMessageBus *bus,
+ const gchar *domain,
+ const gchar *name)
+{
+ Message *message = g_new (Message, 1);
+
+ message->domain = g_strdup (domain);
+ message->name = g_strdup (name);
+ message->listeners = NULL;
+
+ g_hash_table_insert (bus->priv->messages,
+ msg_identifier (domain, name),
+ message);
+ return message;
+}
+
+static Message *
+lookup_message (GeditMessageBus *bus,
+ const gchar *domain,
+ const gchar *name,
+ gboolean create)
+{
+ gchar *identifier;
+ Message *message;
+
+ identifier = msg_identifier (domain, name);
+ message = (Message *)g_hash_table_lookup (bus->priv->messages, identifier);
+ g_free (identifier);
+
+ if (!message && !create)
+ return NULL;
+
+ if (!message)
+ message = message_new (bus, domain, name);
+
+ return message;
+}
+
+static guint
+add_listener (GeditMessageBus *bus,
+ Message *message,
+ GeditMessageCallback callback,
+ gpointer userdata,
+ GDestroyNotify destroy_data)
+{
+ Listener *listener;
+ IdMap *idmap;
+
+ listener = g_new (Listener, 1);
+ listener->id = ++bus->priv->next_id;
+ listener->callback = callback;
+ listener->userdata = userdata;
+ listener->blocked = FALSE;
+ listener->destroy_data = destroy_data;
+
+ message->listeners = g_list_append (message->listeners, listener);
+
+ idmap = g_new (IdMap, 1);
+ idmap->message = message;
+ idmap->listener = g_list_last (message->listeners);
+
+ g_hash_table_insert (bus->priv->idmap, GINT_TO_POINTER (listener->id), idmap);
+ return listener->id;
+}
+
+static void
+remove_listener (GeditMessageBus *bus,
+ Message *message,
+ GList *listener)
+{
+ Listener *lst;
+
+ lst = (Listener *)listener->data;
+
+ /* remove from idmap */
+ g_hash_table_remove (bus->priv->idmap, GINT_TO_POINTER (lst->id));
+ listener_free (lst);
+
+ /* remove from list of listeners */
+ message->listeners = g_list_delete_link (message->listeners, listener);
+
+ if (!message->listeners)
+ {
+ /* remove message because it does not have any listeners */
+ g_hash_table_remove (bus->priv->messages, message);
+ }
+}
+
+static void
+block_listener (GeditMessageBus *bus,
+ Message *message,
+ GList *listener)
+{
+ Listener *lst;
+
+ lst = (Listener *)listener->data;
+ lst->blocked = TRUE;
+}
+
+static void
+unblock_listener (GeditMessageBus *bus,
+ Message *message,
+ GList *listener)
+{
+ Listener *lst;
+
+ lst = (Listener *)listener->data;
+ lst->blocked = FALSE;
+}
+
+static void
+dispatch_message_real (GeditMessageBus *bus,
+ Message *msg,
+ GeditMessage *message)
+{
+ GList *item;
+
+ for (item = msg->listeners; item; item = item->next)
+ {
+ Listener *listener = (Listener *)item->data;
+
+ if (!listener->blocked)
+ listener->callback (bus, message, listener->userdata);
+ }
+}
+
+static void
+dispatch_message (GeditMessageBus *bus,
+ GeditMessage *message)
+{
+ Message *msg;
+ const gchar *domain;
+ const gchar *name;
+
+ domain = gedit_message_get_domain (message);
+ name = gedit_message_get_name (message);
+
+ msg = lookup_message (bus, domain, name, FALSE);
+
+ if (!msg)
+ return;
+
+ dispatch_message_real (bus, msg, message);
+}
+
+static gboolean
+idle_dispatch (GeditMessageBus *bus)
+{
+ GList *list;
+ GList *item;
+
+ /* make sure to set idle_id to 0 first so that any new async messages
+ will be queued properly */
+ bus->priv->idle_id = 0;
+
+ /* reverse queue to get correct delivery order */
+ list = g_list_reverse (bus->priv->message_queue);
+ bus->priv->message_queue = NULL;
+
+ for (item = list; item; item = item->next)
+ {
+ GeditMessage *msg = GEDIT_MESSAGE (item->data);
+
+ dispatch_message (bus, msg);
+ }
+
+ message_queue_free (list);
+ return FALSE;
+}
+
+typedef void (*MatchCallback) (GeditMessageBus *, Message *, GList *);
+
+static void
+process_by_id (GeditMessageBus *bus,
+ guint id,
+ MatchCallback processor)
+{
+ IdMap *idmap;
+
+ idmap = (IdMap *)g_hash_table_lookup (bus->priv->idmap, GINT_TO_POINTER (id));
+
+ if (idmap == NULL)
+ {
+ g_warning ("No handler registered with id `%d'", id);
+ return;
+ }
+
+ processor (bus, idmap->message, idmap->listener);
+}
+
+static void
+process_by_match (GeditMessageBus *bus,
+ const gchar *domain,
+ const gchar *name,
+ GeditMessageCallback callback,
+ gpointer userdata,
+ MatchCallback processor)
+{
+ Message *message;
+ GList *item;
+
+ message = lookup_message (bus, domain, name, FALSE);
+
+ if (!message)
+ {
+ g_warning ("No such handler registered for %s::%s", domain, name);
+ return;
+ }
+
+ for (item = message->listeners; item; item = item->next)
+ {
+ Listener *listener = (Listener *)item->data;
+
+ if (listener->callback == callback &&
+ listener->userdata == userdata)
+ {
+ processor (bus, message, item);
+ return;
+ }
+ }
+
+ g_warning ("No such handler registered for %s::%s", domain, name);
+}
+
+static void
+gedit_message_bus_init (GeditMessageBus *self)
+{
+ self->priv = GEDIT_MESSAGE_BUS_GET_PRIVATE (self);
+
+ self->priv->messages = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ (GDestroyNotify)g_free,
+ (GDestroyNotify)message_free);
+
+ self->priv->idmap = g_hash_table_new_full (g_direct_hash,
+ g_direct_equal,
+ NULL,
+ (GDestroyNotify)g_free);
+}
+
+GeditMessageBus *
+gedit_message_bus_get (void)
+{
+ static GeditMessageBus *bus = NULL;
+
+ if (G_UNLIKELY (!bus))
+ bus = g_object_new (GEDIT_TYPE_MESSAGE_BUS, NULL);
+
+ return bus;
+}
+
+guint
+gedit_message_bus_connect (GeditMessageBus *bus,
+ const gchar *domain,
+ const gchar *name,
+ GeditMessageCallback callback,
+ gpointer userdata,
+ GDestroyNotify destroy_data)
+{
+ Message *message;
+
+ g_return_val_if_fail (GEDIT_IS_MESSAGE_BUS (bus), 0);
+ g_return_val_if_fail (domain != NULL, 0);
+ g_return_val_if_fail (name != NULL, 0);
+ g_return_val_if_fail (callback != NULL, 0);
+
+ /* lookup the message and create if it does not exist yet */
+ message = lookup_message (bus, domain, name, TRUE);
+
+ return add_listener (bus, message, callback, userdata, destroy_data);
+}
+
+void
+gedit_message_bus_disconnect (GeditMessageBus *bus,
+ guint id)
+{
+ g_return_if_fail (GEDIT_IS_MESSAGE_BUS (bus));
+
+ process_by_id (bus, id, remove_listener);
+}
+
+void
+gedit_message_bus_disconnect_by_func (GeditMessageBus *bus,
+ const gchar *domain,
+ const gchar *name,
+ GeditMessageCallback callback,
+ gpointer userdata)
+{
+ g_return_if_fail (GEDIT_IS_MESSAGE_BUS (bus));
+
+ process_by_match (bus, domain, name, callback, userdata, remove_listener);
+}
+
+void
+gedit_message_bus_block (GeditMessageBus *bus,
+ guint id)
+{
+ g_return_if_fail (GEDIT_IS_MESSAGE_BUS (bus));
+
+ process_by_id (bus, id, block_listener);
+}
+
+void
+gedit_message_bus_block_by_func (GeditMessageBus *bus,
+ const gchar *domain,
+ const gchar *name,
+ GeditMessageCallback callback,
+ gpointer userdata)
+{
+ g_return_if_fail (GEDIT_IS_MESSAGE_BUS (bus));
+
+ process_by_match (bus, domain, name, callback, userdata, block_listener);
+}
+
+void
+gedit_message_bus_unblock (GeditMessageBus *bus,
+ guint id)
+{
+ g_return_if_fail (GEDIT_IS_MESSAGE_BUS (bus));
+
+ process_by_id (bus, id, unblock_listener);
+}
+
+void
+gedit_message_bus_unblock_by_func (GeditMessageBus *bus,
+ const gchar *domain,
+ const gchar *name,
+ GeditMessageCallback callback,
+ gpointer userdata)
+{
+ g_return_if_fail (GEDIT_IS_MESSAGE_BUS (bus));
+
+ process_by_match (bus, domain, name, callback, userdata, unblock_listener);
+}
+
+void
+gedit_message_bus_send_message (GeditMessageBus *bus,
+ GeditMessage *message)
+{
+ g_return_if_fail (GEDIT_IS_MESSAGE_BUS (bus));
+ g_return_if_fail (GEDIT_IS_MESSAGE (message));
+
+ bus->priv->message_queue = g_list_prepend (bus->priv->message_queue,
+ g_object_ref (message));
+
+ if (bus->priv->idle_id == 0)
+ bus->priv->idle_id = g_idle_add_full (G_PRIORITY_HIGH,
+ (GSourceFunc)idle_dispatch,
+ bus,
+ NULL);
+}
+
+void
+gedit_message_bus_send_message_sync (GeditMessageBus *bus,
+ GeditMessage *message)
+{
+ g_return_if_fail (GEDIT_IS_MESSAGE_BUS (bus));
+ g_return_if_fail (GEDIT_IS_MESSAGE (message));
+
+ dispatch_message (bus, message);
+}
+
+static GeditMessage *
+create_message (const gchar *domain,
+ const gchar *name,
+ va_list var_args)
+{
+ const gchar **keys = NULL;
+ GType *types = NULL;
+ GValue *values = NULL;
+ gint num = 0;
+ const gchar *key;
+ GeditMessage *message;
+ gint i;
+
+ while ((key = va_arg (var_args, const gchar *)) != NULL)
+ {
+ gchar *error = NULL;
+ GType gtype;
+ GValue value = {0,};
+
+ gtype = va_arg (var_args, GType);
+ g_value_init (&value, gtype);
+ G_VALUE_COLLECT (&value, var_args, 0, &error);
+
+ if (error)
+ {
+ g_warning ("%s: %s", G_STRLOC, error);
+ g_free (error);
+
+ /* leak value, might have gone bad */
+ continue;
+ }
+
+ num++;
+
+ keys = g_realloc (keys, sizeof(gchar *) * num);
+ types = g_realloc (types, sizeof(GType) * num);
+ values = g_realloc (values, sizeof(GValue) * num);
+
+ keys[num - 1] = key;
+ types[num - 1] = gtype;
+
+ memset (&values[num - 1], 0, sizeof(GValue));
+ g_value_init (&values[num - 1], types[num - 1]);
+ g_value_copy (&value, &values[num - 1]);
+
+ g_value_unset (&value);
+ }
+
+ message = gedit_message_new (domain, name, NULL);
+ gedit_message_set_types (message, keys, types, num);
+ gedit_message_set_valuesv (message, keys, values, num);
+
+ g_free (keys);
+ g_free (types);
+
+ for (i = 0; i < num; i++)
+ g_value_unset (&values[i]);
+
+ g_free (values);
+
+ return message;
+}
+
+void
+gedit_message_bus_send (GeditMessageBus *bus,
+ const gchar *domain,
+ const gchar *name,
+ ...)
+{
+ va_list var_args;
+ GeditMessage *message;
+
+ va_start (var_args, name);
+ message = create_message (domain, name, var_args);
+
+ gedit_message_bus_send_message (bus, message);
+ va_end (var_args);
+
+ g_object_unref (message);
+}
+
+GeditMessage *
+gedit_message_bus_send_sync (GeditMessageBus *bus,
+ const gchar *domain,
+ const gchar *name,
+ ...)
+{
+ va_list var_args;
+ GeditMessage *message;
+
+ va_start (var_args, name);
+ message = create_message (domain, name, var_args);
+
+ gedit_message_bus_send_message_sync (bus, message);
+ va_end (var_args);
+
+ return message;
+}
Added: branches/new_plugins/gedit/gedit-message-bus.h
==============================================================================
--- (empty file)
+++ branches/new_plugins/gedit/gedit-message-bus.h Wed Aug 20 09:53:09 2008
@@ -0,0 +1,86 @@
+#ifndef __GEDIT_MESSAGE_BUS_H__
+#define __GEDIT_MESSAGE_BUS_H__
+
+#include <glib-object.h>
+#include <gedit/gedit-message.h>
+
+G_BEGIN_DECLS
+
+#define GEDIT_TYPE_MESSAGE_BUS (gedit_message_bus_get_type ())
+#define GEDIT_MESSAGE_BUS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_MESSAGE_BUS, GeditMessageBus))
+#define GEDIT_MESSAGE_BUS_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_MESSAGE_BUS, GeditMessageBus const))
+#define GEDIT_MESSAGE_BUS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GEDIT_TYPE_MESSAGE_BUS, GeditMessageBusClass))
+#define GEDIT_IS_MESSAGE_BUS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEDIT_TYPE_MESSAGE_BUS))
+#define GEDIT_IS_MESSAGE_BUS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_MESSAGE_BUS))
+#define GEDIT_MESSAGE_BUS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GEDIT_TYPE_MESSAGE_BUS, GeditMessageBusClass))
+
+typedef struct _GeditMessageBus GeditMessageBus;
+typedef struct _GeditMessageBusClass GeditMessageBusClass;
+typedef struct _GeditMessageBusPrivate GeditMessageBusPrivate;
+
+struct _GeditMessageBus {
+ GObject parent;
+
+ GeditMessageBusPrivate *priv;
+};
+
+struct _GeditMessageBusClass {
+ GObjectClass parent_class;
+};
+
+typedef void (* GeditMessageCallback) (GeditMessageBus *bus,
+ GeditMessage *message,
+ gpointer userdata);
+
+GType gedit_message_bus_get_type (void) G_GNUC_CONST;
+
+GeditMessageBus *gedit_message_bus_get (void);
+guint gedit_message_bus_connect (GeditMessageBus *bus,
+ const gchar *domain,
+ const gchar *name,
+ GeditMessageCallback callback,
+ gpointer userdata,
+ GDestroyNotify destroy_data);
+
+void gedit_message_bus_disconnect (GeditMessageBus *bus,
+ guint id);
+
+void gedit_message_bus_disconnect_by_func (GeditMessageBus *bus,
+ const gchar *domain,
+ const gchar *name,
+ GeditMessageCallback callback,
+ gpointer userdata);
+
+void gedit_message_bus_block (GeditMessageBus *bus,
+ guint id);
+void gedit_message_bus_block_by_func (GeditMessageBus *bus,
+ const gchar *domain,
+ const gchar *name,
+ GeditMessageCallback callback,
+ gpointer userdata);
+
+void gedit_message_bus_unblock (GeditMessageBus *bus,
+ guint id);
+void gedit_message_bus_unblock_by_func (GeditMessageBus *bus,
+ const gchar *domain,
+ const gchar *name,
+ GeditMessageCallback callback,
+ gpointer userdata);
+
+void gedit_message_bus_send_message (GeditMessageBus *bus,
+ GeditMessage *message);
+
+void gedit_message_bus_send_message_sync (GeditMessageBus *bus,
+ GeditMessage *message);
+
+void gedit_message_bus_send (GeditMessageBus *bus,
+ const gchar *domain,
+ const gchar *name,
+ ...) G_GNUC_NULL_TERMINATED;
+GeditMessage *gedit_message_bus_send_sync (GeditMessageBus *bus,
+ const gchar *domain,
+ const gchar *name,
+ ...) G_GNUC_NULL_TERMINATED;
+G_END_DECLS
+
+#endif /* __GEDIT_MESSAGE_BUS_H__ */
Added: branches/new_plugins/gedit/gedit-message.c
==============================================================================
--- (empty file)
+++ branches/new_plugins/gedit/gedit-message.c Wed Aug 20 09:53:09 2008
@@ -0,0 +1,502 @@
+#include "gedit-message.h"
+
+#include <string.h>
+#include <gobject/gvaluecollector.h>
+
+#define GEDIT_MESSAGE_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GEDIT_TYPE_MESSAGE, GeditMessagePrivate))
+
+enum {
+ PROP_0,
+
+ PROP_DOMAIN,
+ PROP_NAME
+};
+
+struct _GeditMessagePrivate
+{
+ gchar *domain;
+ gchar *name;
+
+ GHashTable *values;
+};
+
+G_DEFINE_TYPE (GeditMessage, gedit_message, G_TYPE_OBJECT)
+
+static void
+gedit_message_finalize (GObject *object)
+{
+ GeditMessage *message = GEDIT_MESSAGE (object);
+
+ g_free (message->priv->domain);
+ g_free (message->priv->name);
+
+ g_hash_table_destroy (message->priv->values);
+
+ G_OBJECT_CLASS (gedit_message_parent_class)->finalize (object);
+}
+
+static void
+gedit_message_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GeditMessage *msg = GEDIT_MESSAGE (object);
+
+ switch (prop_id)
+ {
+ case PROP_DOMAIN:
+ g_value_set_string (value, msg->priv->domain);
+ break;
+ case PROP_NAME:
+ g_value_set_string (value, msg->priv->name);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gedit_message_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GeditMessage *msg = GEDIT_MESSAGE (object);
+
+ switch (prop_id)
+ {
+ case PROP_DOMAIN:
+ msg->priv->domain = g_strdup (g_value_get_string (value));
+ break;
+ case PROP_NAME:
+ msg->priv->name = g_strdup (g_value_get_string (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gedit_message_class_init (GeditMessageClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS(klass);
+
+ object_class->finalize = gedit_message_finalize;
+ object_class->get_property = gedit_message_get_property;
+ object_class->set_property = gedit_message_set_property;
+
+ g_object_class_install_property (object_class, PROP_DOMAIN,
+ g_param_spec_string ("domain",
+ "DOMAIN",
+ "The message domain",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS |
+ G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (object_class, PROP_NAME,
+ g_param_spec_string ("name",
+ "NAME",
+ "The message name",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS |
+ G_PARAM_CONSTRUCT_ONLY));
+
+ g_type_class_add_private (object_class, sizeof(GeditMessagePrivate));
+}
+
+static void
+destroy_value (GValue *value)
+{
+ g_value_unset (value);
+ g_free (value);
+}
+
+static void
+gedit_message_init (GeditMessage *self)
+{
+ self->priv = GEDIT_MESSAGE_GET_PRIVATE (self);
+
+ self->priv->values = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ (GDestroyNotify)g_free,
+ (GDestroyNotify)destroy_value);
+}
+
+static gboolean
+gtype_supported (GType type)
+{
+ gint i = 0;
+
+ static const GType type_list[] =
+ {
+ G_TYPE_BOOLEAN,
+ G_TYPE_CHAR,
+ G_TYPE_UCHAR,
+ G_TYPE_INT,
+ G_TYPE_UINT,
+ G_TYPE_LONG,
+ G_TYPE_ULONG,
+ G_TYPE_INT64,
+ G_TYPE_UINT64,
+ G_TYPE_ENUM,
+ G_TYPE_FLAGS,
+ G_TYPE_FLOAT,
+ G_TYPE_DOUBLE,
+ G_TYPE_STRING,
+ G_TYPE_POINTER,
+ G_TYPE_BOXED,
+ G_TYPE_OBJECT,
+ G_TYPE_INVALID
+ };
+
+ if (!G_TYPE_IS_VALUE_TYPE (type))
+ return FALSE;
+
+ while (type_list[i] != G_TYPE_INVALID)
+ {
+ if (g_type_is_a (type, type_list[i]))
+ return TRUE;
+ i++;
+ }
+
+ return FALSE;
+}
+
+static void
+add_value (GeditMessage *message,
+ const gchar *key,
+ GType gtype)
+{
+ GValue *value;
+
+ value = g_new0 (GValue, 1);
+ g_value_init (value, gtype);
+ g_value_reset (value);
+
+ g_hash_table_insert (message->priv->values, g_strdup (key), value);
+}
+
+static gboolean
+set_value_real (GValue *to,
+ const GValue *from)
+{
+ GType from_type;
+ GType to_type;
+
+ from_type = G_VALUE_TYPE (from);
+ to_type = G_VALUE_TYPE (to);
+
+ if (!g_type_is_a (from_type, to_type))
+ {
+ if (!g_value_transform (from, to))
+ {
+ g_warning ("%s: Unable to make conversion from %s to %s",
+ G_STRLOC,
+ g_type_name (from_type),
+ g_type_name (to_type));
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ g_value_copy (from, to);
+ return TRUE;
+}
+
+inline static GValue *
+value_lookup (GeditMessage *message,
+ const gchar *key)
+{
+ return (GValue *)g_hash_table_lookup (message->priv->values, key);
+}
+
+GeditMessage*
+gedit_message_new (const gchar *domain,
+ const gchar *name,
+ ...)
+{
+ va_list var_args;
+ GeditMessage *message;
+
+ va_start (var_args, name);
+ message = gedit_message_new_valist (domain, name, var_args);
+ va_end (var_args);
+
+ return message;
+}
+
+GeditMessage *
+gedit_message_new_valist (const gchar *domain,
+ const gchar *name,
+ va_list var_args)
+{
+ GeditMessage *message;
+ const gchar *key;
+ GArray *keys;
+ GArray *types;
+
+ message = g_object_new (GEDIT_TYPE_MESSAGE, "domain", domain, "name", name, NULL);
+
+ keys = g_array_new (FALSE, FALSE, sizeof (const gchar *));
+ types = g_array_new (FALSE, FALSE, sizeof (GType));
+
+ while ((key = va_arg (var_args, const gchar *)) != NULL)
+ {
+ /* get corresponding GType */
+ GType gtype = va_arg (var_args, GType);
+
+ g_array_append_val (keys, key);
+ g_array_append_val (types, gtype);
+ }
+
+ gedit_message_set_types (message,
+ (const gchar **)keys->data,
+ (GType *)types->data,
+ keys->len);
+
+ g_array_free (keys, TRUE);
+ g_array_free (types, TRUE);
+
+ return message;
+}
+
+void
+gedit_message_set_types (GeditMessage *message,
+ const gchar **keys,
+ GType *types,
+ gint n_types)
+{
+ gint i;
+
+ g_return_if_fail (GEDIT_IS_MESSAGE (message));
+
+ g_hash_table_ref (message->priv->values);
+ g_hash_table_destroy (message->priv->values);
+
+ for (i = 0; i < n_types; i++)
+ {
+ if (!gtype_supported (types[i]))
+ {
+ g_warning ("GType %s is not supported, ignoring key %s", g_type_name (types[i]), keys[i]);
+ continue;
+ }
+
+ add_value (message, keys[i], types[i]);
+ }
+}
+
+const gchar *
+gedit_message_get_name (GeditMessage *message)
+{
+ g_return_val_if_fail (GEDIT_IS_MESSAGE (message), NULL);
+
+ return message->priv->name;
+}
+
+const gchar *
+gedit_message_get_domain (GeditMessage *message)
+{
+ g_return_val_if_fail (GEDIT_IS_MESSAGE (message), NULL);
+
+ return message->priv->domain;
+}
+
+void
+gedit_message_set (GeditMessage *message,
+ ...)
+{
+ va_list ap;
+
+ g_return_if_fail (GEDIT_IS_MESSAGE (message));
+
+ va_start (ap, message);
+ gedit_message_set_valist (message, ap);
+ va_end (ap);
+}
+
+void
+gedit_message_set_valist (GeditMessage *message,
+ va_list var_args)
+{
+ const gchar *key;
+
+ g_return_if_fail (GEDIT_IS_MESSAGE (message));
+
+ while ((key = va_arg (var_args, const gchar *)) != NULL)
+ {
+ /* lookup the key */
+ GValue *container = value_lookup (message, key);
+ GValue value = {0,};
+ gchar *error = NULL;
+
+ if (!container)
+ {
+ g_warning ("%s: Cannot set value for %s, does not exist",
+ G_STRLOC,
+ key);
+
+ /* skip value */
+ va_arg (var_args, gpointer);
+ continue;
+ }
+
+ g_value_init (&value, G_VALUE_TYPE (container));
+ G_VALUE_COLLECT (&value, var_args, 0, &error);
+
+ if (error)
+ {
+ g_warning ("%s: %s", G_STRLOC, error);
+ continue;
+ }
+
+ set_value_real (container, &value);
+ g_value_unset (&value);
+ }
+}
+
+void
+gedit_message_set_value (GeditMessage *message,
+ const gchar *key,
+ GValue *value)
+{
+ GValue *container;
+ g_return_if_fail (GEDIT_IS_MESSAGE (message));
+
+ container = value_lookup (message, key);
+
+ if (!container)
+ {
+ g_warning ("%s: Cannot set value for %s, does not exist",
+ G_STRLOC,
+ key);
+ return;
+ }
+
+ set_value_real (container, value);
+}
+
+void
+gedit_message_set_valuesv (GeditMessage *message,
+ const gchar **keys,
+ GValue *values,
+ gint n_values)
+{
+ gint i;
+
+ g_return_if_fail (GEDIT_IS_MESSAGE (message));
+
+ for (i = 0; i < n_values; i++)
+ {
+ gedit_message_set_value (message, keys[i], &values[i]);
+ }
+}
+
+void
+gedit_message_get (GeditMessage *message,
+ ...)
+{
+ va_list ap;
+
+ g_return_if_fail (GEDIT_IS_MESSAGE (message));
+
+ va_start (ap, message);
+ gedit_message_get_valist (message, ap);
+ va_end (ap);
+}
+
+void
+gedit_message_get_valist (GeditMessage *message,
+ va_list var_args)
+{
+ const gchar *key;
+
+ g_return_if_fail (GEDIT_IS_MESSAGE (message));
+
+ while ((key = va_arg (var_args, const gchar *)) != NULL)
+ {
+ GValue *container;
+ GValue copy = {0,};
+ gchar *error = NULL;
+
+ container = value_lookup (message, key);
+
+ if (!container)
+ {
+ g_warning ("%s: Invalid key `%s'",
+ G_STRLOC,
+ key);
+
+ /* skip value */
+ va_arg (var_args, gpointer);
+ continue;
+ }
+
+ /* copy the value here, to be sure it isn't tainted */
+ g_value_init (©, G_VALUE_TYPE (container));
+ g_value_copy (container, ©);
+
+ G_VALUE_LCOPY (©, var_args, 0, &error);
+
+ if (error)
+ {
+ g_warning ("%s: %s", G_STRLOC, error);
+ g_free (error);
+
+ /* purposely leak the value here, because it might
+ be in a bad state */
+ continue;
+ }
+
+ g_value_unset (©);
+ }
+}
+
+void
+gedit_message_get_value (GeditMessage *message,
+ const gchar *key,
+ GValue *value)
+{
+ GValue *container;
+
+ g_return_if_fail (GEDIT_IS_MESSAGE (message));
+
+ container = value_lookup (message, key);
+
+ if (!container)
+ {
+ g_warning ("%s: Invalid key `%s'",
+ G_STRLOC,
+ key);
+ return;
+ }
+
+ g_value_init (value, G_VALUE_TYPE (container));
+ set_value_real (value, container);
+}
+
+GType
+gedit_message_get_key_type (GeditMessage *message,
+ const gchar *key)
+{
+ GValue *container;
+
+ g_return_val_if_fail (GEDIT_IS_MESSAGE (message), 0);
+
+ container = value_lookup (message, key);
+
+ if (!container)
+ {
+ g_warning ("%s: Invalid key `%s'",
+ G_STRLOC,
+ key);
+ return 0;
+ }
+
+ return G_VALUE_TYPE (container);
+}
Added: branches/new_plugins/gedit/gedit-message.h
==============================================================================
--- (empty file)
+++ branches/new_plugins/gedit/gedit-message.h Wed Aug 20 09:53:09 2008
@@ -0,0 +1,72 @@
+#ifndef __GEDIT_MESSAGE_H__
+#define __GEDIT_MESSAGE_H__
+
+#include <glib-object.h>
+#include <stdarg.h>
+
+G_BEGIN_DECLS
+
+#define GEDIT_TYPE_MESSAGE (gedit_message_get_type ())
+#define GEDIT_MESSAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_MESSAGE, GeditMessage))
+#define GEDIT_MESSAGE_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_MESSAGE, GeditMessage const))
+#define GEDIT_MESSAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GEDIT_TYPE_MESSAGE, GeditMessageClass))
+#define GEDIT_IS_MESSAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEDIT_TYPE_MESSAGE))
+#define GEDIT_IS_MESSAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_MESSAGE))
+#define GEDIT_MESSAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GEDIT_TYPE_MESSAGE, GeditMessageClass))
+
+typedef struct _GeditMessage GeditMessage;
+typedef struct _GeditMessageClass GeditMessageClass;
+typedef struct _GeditMessagePrivate GeditMessagePrivate;
+
+struct _GeditMessage {
+ GObject parent;
+
+ GeditMessagePrivate *priv;
+};
+
+struct _GeditMessageClass {
+ GObjectClass parent_class;
+};
+
+GType gedit_message_get_type (void) G_GNUC_CONST;
+
+GeditMessage *gedit_message_new (const gchar *domain,
+ const gchar *name,
+ ...) G_GNUC_NULL_TERMINATED;
+GeditMessage *gedit_message_new_valist (const gchar *domain,
+ const gchar *name,
+ va_list var_args);
+
+void gedit_message_set_types (GeditMessage *message,
+ const gchar **keys,
+ GType *types,
+ gint n_types);
+
+const gchar *gedit_message_get_domain (GeditMessage *message);
+const gchar *gedit_message_get_name (GeditMessage *message);
+
+void gedit_message_get (GeditMessage *message,
+ ...) G_GNUC_NULL_TERMINATED;
+void gedit_message_get_valist (GeditMessage *message,
+ va_list var_args);
+void gedit_message_get_value (GeditMessage *message,
+ const gchar *key,
+ GValue *value);
+
+void gedit_message_set (GeditMessage *message,
+ ...) G_GNUC_NULL_TERMINATED;
+void gedit_message_set_valist (GeditMessage *message,
+ va_list var_args);
+void gedit_message_set_value (GeditMessage *message,
+ const gchar *key,
+ GValue *value);
+void gedit_message_set_valuesv (GeditMessage *message,
+ const gchar **keys,
+ GValue *values,
+ gint n_values);
+
+GType gedit_message_get_key_type (GeditMessage *message,
+ const gchar *key);
+G_END_DECLS
+
+#endif /* __GEDIT_MESSAGE_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]