]> Dogcows Code - chaz/openbox/commitdiff
this is a big one! im putting stats in here just cuz!
authorDana Jansens <danakj@orodu.net>
Sat, 24 May 2003 21:47:06 +0000 (21:47 +0000)
committerDana Jansens <danakj@orodu.net>
Sat, 24 May 2003 21:47:06 +0000 (21:47 +0000)
 59 files changed, 1691 insertions(+), 607 deletions(-)
Adding the beginings of ObConf. Adding a resistance-config plugin for ObConf.
Creating an obparser library that obrender can use, the kernel can use, plugins can use, and ObConf and its plugins can use. (its just code for using libXml2)

40 files changed:
Makefile.am
configure.ac
openbox/Makefile.am
openbox/action.c
openbox/action.h
openbox/config.c
openbox/focus.c
openbox/openbox.c
openbox/parse.c [deleted file]
openbox/plugin.c
parser/.cvsignore [new file with mode: 0644]
parser/Makefile.am [new file with mode: 0644]
parser/parse.c [new file with mode: 0644]
parser/parse.h [moved from openbox/parse.h with 72% similarity]
plugins/Makefile.am
plugins/interface.h [new file with mode: 0644]
plugins/keyboard/keyboard.c
plugins/menu/Makefile.am
plugins/mouse/mouse.c
plugins/obconf_interface.h [new file with mode: 0644]
plugins/placement/history.c
plugins/placement/placement.c
plugins/resistance/.cvsignore [new file with mode: 0644]
plugins/resistance/Makefile.am [new file with mode: 0644]
plugins/resistance/resistance.c [moved from plugins/resistance.c with 98% similarity]
plugins/resistance/resistance.glade [new file with mode: 0644]
plugins/resistance/resistance.gladep [new file with mode: 0644]
plugins/resistance/resistance.h [new file with mode: 0644]
plugins/resistance/resistance_config.c [new file with mode: 0644]
tools/.cvsignore [new file with mode: 0644]
tools/Makefile.am [new file with mode: 0644]
tools/obconf/.cvsignore [new file with mode: 0644]
tools/obconf/Makefile.am [new file with mode: 0644]
tools/obconf/about.c [new file with mode: 0644]
tools/obconf/main.c [new file with mode: 0644]
tools/obconf/obconf.glade [new file with mode: 0644]
tools/obconf/obconf.gladep [new file with mode: 0644]
tools/obconf/obconf.h [new file with mode: 0644]
tools/obconf/plugins.c [new file with mode: 0644]
tools/obconf/plugins.h [new file with mode: 0644]

index 060cf7dcbf5a4bf3e36d5e9a87eec30d7d4b8720..433af840f589441e36f502da4f5f2c8c09592b91 100644 (file)
@@ -1,5 +1,4 @@
-#SUBDIRS = po themes doc render cwmcc obcl kernel plugins
-SUBDIRS = po themes data render kernel plugins
+SUBDIRS = po themes data render parser kernel plugins tools
 MAINTAINERCLEANFILES = aclocal.m4 config.h.in configure Makefile.in stamp-h.in
 
 doc:
index 21fc5219d65fa7628e13fb7368d5f824746d3134..dea5e17d3d7c57c8bcc102c9d32bca77114fb57b 100644 (file)
@@ -68,6 +68,31 @@ PKG_CHECK_MODULES(LIBSN, [libstartup-notification-1.0],
   ]
 )
 
+PKG_CHECK_MODULES(GTK, [gtk+-2.0],
+  [
+    AC_SUBST(GTK_CFLAGS)
+    AC_SUBST(GTK_LIBS)
+    use_gtk="yes"
+
+    PKG_CHECK_MODULES(GLADE, [libglade-2.0],
+      [
+        AC_SUBST(GLADE_CFLAGS)
+        AC_SUBST(GLADE_LIBS)
+        use_glade="yes"
+      ],
+      [
+        use_glade="no"
+        AC_MSG_WARN([disabling build of the configuration tool])
+      ]
+    )
+  ],
+  [
+    use_gtk="no"
+    AC_MSG_WARN([disabling build of the configuration tool])
+  ]
+)
+AM_CONDITIONAL(OBCONF, [test "$use_gtk" = "yes" && test "$use_glade" = "yes"])
+
 # Check for X11 extensions
 X11_EXT_XKB
 X11_EXT_XRANDR
@@ -82,12 +107,16 @@ AC_CONFIG_FILES([Makefile
                  themes/Makefile
                 data/Makefile
                  render/Makefile
+                parser/Makefile
                  kernel/Makefile
                 plugins/Makefile
+                plugins/resistance/Makefile
                 plugins/placement/Makefile
                 plugins/mouse/Makefile
                 plugins/keyboard/Makefile
-                plugins/menu/Makefile])
+                plugins/menu/Makefile
+                tools/Makefile
+                tools/obconf/Makefile])
 AC_OUTPUT
 
 AC_MSG_RESULT
index ecb72969bd0438a6774c7ef110cf39b9cf9ae05d..fc9f4ae3ec90fa1d55c019eb8b0030c999f7b30e 100644 (file)
@@ -1,15 +1,15 @@
 localedir=$(datadir)/locale
-plugindir=$(libdir)/openbox/plugins
 rcdir=$(datadir)/openbox
+plugindir=$(libdir)/openbox/plugins
 
 binary=openbox3
-url=http://icculus.org/openbox
+url=http://openbox.org/
 
 CPPFLAGS=$(X_CFLAGS) $(XFT_CFLAGS) $(GLIB_CFLAGS) $(GMODULE_CFLAGS) \
          $(LIBSN_CFLAGS) $(GL_CFLAGS) $(XML_CFLAGS) @CPPFLAGS@ \
          -DLOCALEDIR=\"$(localedir)\" \
-         -DRCDIR=\"$(rcdir)\" \
          -DPLUGINDIR=\"$(plugindir)\" \
+         -DRCDIR=\"$(rcdir)\" \
          -DG_LOG_DOMAIN=\"Openbox\" \
          -DBINARY=\"$(binary)\"
 
@@ -20,9 +20,9 @@ LIBS=$(X_LIBS) $(XFT_LIBS) $(XINERAMA_LIBS) $(XKB_LIBS) $(XRANDR_LIBS) \
 
 bin_PROGRAMS=$(binary)
 
-openbox3_LDADD=-lobrender -L../render
+openbox3_LDADD=-lobrender -L../render -lobparser -L../parser
 openbox3_LDFLAGS=-export-dynamic
-openbox3_SOURCES=action.c client.c config.c parse.c \
+openbox3_SOURCES=action.c client.c config.c \
                  extensions.c focus.c frame.c grab.c menu.c menu_render.c \
                  openbox.c framerender.c plugin.c prop.c screen.c \
                  stacking.c dispatch.c event.c group.c timer.c xerror.c \
@@ -32,7 +32,7 @@ noinst_HEADERS=action.h client.h config.h dispatch.h event.h extensions.h \
                focus.h frame.h framerender.h geom.h gettext.h grab.h group.h \
                menu.h openbox.h plugin.h prop.h screen.h \
                stacking.h timer.h xerror.h moveresize.h startup.h popup.h \
-               dock.h window.h parse.h
+               dock.h window.h
 
 MAINTAINERCLEANFILES=Makefile.in
 
index 9015939e854d5ef1e6fc0f5cc5b204f471cc6772..2dde0f0bdc997770d28276030065a1ec5972e3a4 100644 (file)
@@ -548,6 +548,56 @@ Action *action_from_string(char *name)
     return a;
 }
 
+Action *action_parse(xmlDocPtr doc, xmlNodePtr node)
+{
+    char *actname;
+    Action *act = NULL;
+    xmlNodePtr n;
+
+    if (parse_attr_string("name", node, &actname)) {
+        if ((act = action_from_string(actname))) {
+            if (act->func == action_execute || act->func == action_restart) {
+                if ((n = parse_find_node("execute", node->xmlChildrenNode)))
+                    act->data.execute.path = parse_string(doc, n);
+            } else if (act->func == action_showmenu) {
+                if ((n = parse_find_node("menu", node->xmlChildrenNode)))
+                    act->data.showmenu.name = parse_string(doc, n);
+            } else if (act->func == action_desktop) {
+                if ((n = parse_find_node("desktop", node->xmlChildrenNode)))
+                    act->data.desktop.desk = parse_int(doc, n);
+                if (act->data.desktop.desk > 0) act->data.desktop.desk--;
+            } else if (act->func == action_send_to_desktop) {
+                if ((n = parse_find_node("desktop", node->xmlChildrenNode)))
+                    act->data.sendto.desk = parse_int(doc, n);
+                if (act->data.sendto.desk > 0) act->data.sendto.desk--;
+            } else if (act->func == action_move_relative_horz ||
+                       act->func == action_move_relative_vert ||
+                       act->func == action_resize_relative_horz ||
+                       act->func == action_resize_relative_vert) {
+                if ((n = parse_find_node("delta", node->xmlChildrenNode)))
+                    act->data.relative.delta = parse_int(doc, n);
+            } else if (act->func == action_desktop_right ||
+                       act->func == action_desktop_left ||
+                       act->func == action_desktop_up ||
+                       act->func == action_desktop_down) {
+                if ((n = parse_find_node("wrap", node->xmlChildrenNode))) {
+                    g_message("WRAP %d", parse_bool(doc, n));
+                    act->data.desktopdir.wrap = parse_bool(doc, n);
+                }
+            } else if (act->func == action_send_to_desktop_right ||
+                       act->func == action_send_to_desktop_left ||
+                       act->func == action_send_to_desktop_up ||
+                       act->func == action_send_to_desktop_down) {
+                if ((n = parse_find_node("wrap", node->xmlChildrenNode)))
+                    act->data.sendtodir.wrap = parse_bool(doc, n);
+                if ((n = parse_find_node("follow", node->xmlChildrenNode)))
+                    act->data.sendtodir.follow = parse_bool(doc, n);
+            }
+        }
+    }
+    return act;
+}
+
 void action_execute(union ActionData *data)
 {
     GError *e = NULL;
index 5630f8f49e77202d93723c8ee67d43e8a3143fd2..6c1c4d32fa1c76f726c24a7502ff9bbb72fb253d 100644 (file)
@@ -2,6 +2,7 @@
 #define __action_h
 
 #include "client.h"
+#include "parser/parse.h"
 
 /* These have to all have a Client* at the top even if they don't use it, so
    that I can set it blindly later on. So every function will have a Client*
@@ -120,6 +121,7 @@ Action *action_new(void (*func)(union ActionData *data));
 */
 
 Action *action_from_string(char *name);
+Action *action_parse(xmlDocPtr doc, xmlNodePtr node);
 void action_free(Action *a);
 
 /* Execute */
index c3fa786cce71c09b1a9f03e21388305cb43550cb..491097e444f1ff663305a328eae03d83d92d51b5 100644 (file)
@@ -1,5 +1,5 @@
 #include "config.h"
-#include "parse.h"
+#include "parser/parse.h"
 
 gboolean config_focus_new;
 gboolean config_focus_follow;
index 1de349baaad7c9524a9a6647690fae0f25c8e04f..de98d63bacea38b3667f9e2177dd8e6d8ebab500 100644 (file)
@@ -10,7 +10,6 @@
 #include "prop.h"
 #include "dispatch.h"
 #include "focus.h"
-#include "parse.h"
 #include "stacking.h"
 #include "popup.h"
 
index 2b4dddced71679ae56163f53bcb2b0c0fd55bce8..0455e88c523406e929a1aba28a4745d89550b72a 100644 (file)
 #include "moveresize.h"
 #include "frame.h"
 #include "extensions.h"
-#include "parse.h"
 #include "grab.h"
 #include "plugin.h"
 #include "timer.h"
 #include "group.h"
 #include "config.h"
 #include "gettext.h"
+#include "parser/parse.h"
 #include "render/render.h"
 #include "render/font.h"
 #include "render/theme.h"
@@ -66,6 +66,8 @@ int main(int argc, char **argv)
     sigset_t sigset;
     char *path;
     char *theme;
+    xmlDocPtr doc;
+    xmlNodePtr node;
 
     ob_state = State_Starting;
 
@@ -180,7 +182,8 @@ int main(int argc, char **argv)
         /* set up the kernel config shit */
         config_startup();
         /* parse/load user options */
-        parse_config();
+        if (parse_load_rc(&doc, &node))
+            parse_tree(doc, node->xmlChildrenNode, NULL);
         /* we're done with parsing now, kill it */
         parse_shutdown();
 
diff --git a/openbox/parse.c b/openbox/parse.c
deleted file mode 100644 (file)
index 8f9c82f..0000000
+++ /dev/null
@@ -1,243 +0,0 @@
-#include "parse.h"
-#include <glib.h>
-
-struct Callback {
-    char *tag;
-    ParseCallback func;
-    void *data;
-};
-
-static GHashTable *callbacks;
-static xmlDocPtr doc_config = NULL;
-
-static void destfunc(struct Callback *c)
-{
-    g_free(c->tag);
-    g_free(c);
-}
-
-void parse_startup()
-{
-    callbacks = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
-                                      (GDestroyNotify)destfunc);
-}
-
-void parse_shutdown()
-{
-    xmlFree(doc_config);
-    doc_config = NULL;
-
-    g_hash_table_destroy(callbacks);
-}
-
-void parse_register(const char *tag, ParseCallback func, void *data)
-{
-    struct Callback *c;
-
-    if ((c = g_hash_table_lookup(callbacks, tag))) {
-        g_warning("tag '%s' already registered", tag);
-        return;
-    }
-
-    c = g_new(struct Callback, 1);
-    c->tag = g_strdup(tag);
-    c->func = func;
-    c->data = data;
-    g_hash_table_insert(callbacks, c->tag, c);
-}
-
-void parse_config()
-{
-    char *path;
-    xmlNodePtr node = NULL;
-
-    xmlLineNumbersDefault(1);
-
-    path = g_build_filename(g_get_home_dir(), ".openbox", "rc3", NULL);
-    if ((doc_config = xmlParseFile(path))) {
-        node = xmlDocGetRootElement(doc_config);
-        if (!node) {
-            xmlFreeDoc(doc_config);
-            doc_config = NULL;
-            g_warning("%s is an empty document", path);
-        } else {
-            if (xmlStrcasecmp(node->name, (const xmlChar*)"openbox_config")) {
-                xmlFreeDoc(doc_config);
-                doc_config = NULL;
-                g_warning("document %s is of wrong type. root node is "
-                          "not 'openbox_config'", path);
-            }
-        }
-    }
-    g_free(path);
-    if (!doc_config) {
-        path = g_build_filename(RCDIR, "rc3", NULL);
-        if ((doc_config = xmlParseFile(path))) {
-            node = xmlDocGetRootElement(doc_config);
-            if (!node) {
-                xmlFreeDoc(doc_config);
-                doc_config = NULL;
-                g_warning("%s is an empty document", path);
-            } else {
-                if (xmlStrcasecmp(node->name,
-                                  (const xmlChar*)"openbox_config")) {
-                    xmlFreeDoc(doc_config);
-                    doc_config = NULL;
-                    g_warning("document %s is of wrong type. root node is "
-                              "not 'openbox_config'", path);
-                }
-            }
-        }
-        g_free(path);
-    }
-    if (!doc_config) {
-        g_message("unable to find a valid config file, using defaults");
-    } else {
-        parse_tree(doc_config, node->xmlChildrenNode, NULL);
-    }
-}
-
-void parse_tree(xmlDocPtr doc, xmlNodePtr node, void *nothing)
-{
-    while (node) {
-        struct Callback *c = g_hash_table_lookup(callbacks, node->name);
-
-        if (c)
-            c->func(doc, node->xmlChildrenNode, c->data);
-
-        node = node->next;
-    }
-}
-
-char *parse_string(xmlDocPtr doc, xmlNodePtr node)
-{
-    xmlChar *c = xmlNodeListGetString(doc, node->xmlChildrenNode, TRUE);
-    char *s = g_strdup((char*)c);
-    xmlFree(c);
-    return s;
-}
-
-int parse_int(xmlDocPtr doc, xmlNodePtr node)
-{
-    xmlChar *c = xmlNodeListGetString(doc, node->xmlChildrenNode, TRUE);
-    int i = atoi((char*)c);
-    xmlFree(c);
-    return i;
-}
-
-gboolean parse_bool(xmlDocPtr doc, xmlNodePtr node)
-{
-    xmlChar *c = xmlNodeListGetString(doc, node->xmlChildrenNode, TRUE);
-    gboolean b = FALSE;
-    if (!xmlStrcasecmp(c, (const xmlChar*) "true"))
-        b = TRUE;
-    else if (!xmlStrcasecmp(c, (const xmlChar*) "yes"))
-        b = TRUE;
-    else if (!xmlStrcasecmp(c, (const xmlChar*) "on"))
-        b = TRUE;
-    xmlFree(c);
-    return b;
-}
-
-gboolean parse_contains(const char *val, xmlDocPtr doc, xmlNodePtr node)
-{
-    xmlChar *c = xmlNodeListGetString(doc, node->xmlChildrenNode, TRUE);
-    gboolean r;
-    r = !xmlStrcasecmp(c, (const xmlChar*) val);
-    xmlFree(c);
-    return r;
-}
-
-xmlNodePtr parse_find_node(const char *tag, xmlNodePtr node)
-{
-    while (node) {
-        if (!xmlStrcasecmp(node->name, (const xmlChar*) tag))
-            return node;
-        node = node->next;
-    }
-    return NULL;
-}
-
-gboolean parse_attr_int(const char *name, xmlNodePtr node, int *value)
-{
-    xmlChar *c = xmlGetProp(node, (const xmlChar*) name);
-    gboolean r = FALSE;
-    if (c) {
-        *value = atoi((char*)c);
-        r = TRUE;
-    }
-    xmlFree(c);
-    return r;
-}
-
-gboolean parse_attr_string(const char *name, xmlNodePtr node, char **value)
-{
-    xmlChar *c = xmlGetProp(node, (const xmlChar*) name);
-    gboolean r = FALSE;
-    if (c) {
-        *value = g_strdup((char*)c);
-        r = TRUE;
-    }
-    xmlFree(c);
-    return r;
-}
-
-Action *parse_action(xmlDocPtr doc, xmlNodePtr node)
-{
-    char *actname;
-    Action *act = NULL;
-    xmlNodePtr n;
-
-    if (parse_attr_string("name", node, &actname)) {
-        if ((act = action_from_string(actname))) {
-            if (act->func == action_execute || act->func == action_restart) {
-                if ((n = parse_find_node("execute", node->xmlChildrenNode)))
-                    act->data.execute.path = parse_string(doc, n);
-            } else if (act->func == action_showmenu) {
-                if ((n = parse_find_node("menu", node->xmlChildrenNode)))
-                    act->data.showmenu.name = parse_string(doc, n);
-            } else if (act->func == action_desktop) {
-                if ((n = parse_find_node("desktop", node->xmlChildrenNode)))
-                    act->data.desktop.desk = parse_int(doc, n);
-                if (act->data.desktop.desk > 0) act->data.desktop.desk--;
-            } else if (act->func == action_send_to_desktop) {
-                if ((n = parse_find_node("desktop", node->xmlChildrenNode)))
-                    act->data.sendto.desk = parse_int(doc, n);
-                if (act->data.sendto.desk > 0) act->data.sendto.desk--;
-            } else if (act->func == action_move_relative_horz ||
-                       act->func == action_move_relative_vert ||
-                       act->func == action_resize_relative_horz ||
-                       act->func == action_resize_relative_vert) {
-                if ((n = parse_find_node("delta", node->xmlChildrenNode)))
-                    act->data.relative.delta = parse_int(doc, n);
-            } else if (act->func == action_desktop_right ||
-                       act->func == action_desktop_left ||
-                       act->func == action_desktop_up ||
-                       act->func == action_desktop_down) {
-                if ((n = parse_find_node("wrap", node->xmlChildrenNode))) {
-                    g_message("WRAP %d", parse_bool(doc, n));
-                    act->data.desktopdir.wrap = parse_bool(doc, n);
-                }
-            } else if (act->func == action_send_to_desktop_right ||
-                       act->func == action_send_to_desktop_left ||
-                       act->func == action_send_to_desktop_up ||
-                       act->func == action_send_to_desktop_down) {
-                if ((n = parse_find_node("wrap", node->xmlChildrenNode)))
-                    act->data.sendtodir.wrap = parse_bool(doc, n);
-                if ((n = parse_find_node("follow", node->xmlChildrenNode)))
-                    act->data.sendtodir.follow = parse_bool(doc, n);
-            }
-        }
-    }
-    return act;
-}
-
-gboolean parse_attr_contains(const char *val, xmlNodePtr node,
-                             const char *name)
-{
-    xmlChar *c = xmlGetProp(node, (const xmlChar*) name);
-    gboolean r;
-    r = !xmlStrcasecmp(c, (const xmlChar*) val);
-    xmlFree(c);
-    return r;
-}
index a47052e4d8a023d9595ed942545c18850a0d52c6..747bde6f1ab47a18f0ffa9f4b277ac93c008e568 100644 (file)
@@ -1,12 +1,8 @@
+#include "plugins/interface.h"
+
 #include <glib.h>
 #include <gmodule.h>
 
-typedef void (*PluginSetupConfig)();
-typedef void (*PluginStartup)();
-typedef void (*PluginShutdown)();
-typedef void *(*PluginCreate)(/* TODO */);
-typedef void (*PluginDestroy)(void *);
-
 typedef struct {
     GModule *module;
     char *name;
diff --git a/parser/.cvsignore b/parser/.cvsignore
new file mode 100644 (file)
index 0000000..cb73789
--- /dev/null
@@ -0,0 +1,6 @@
+.deps
+.libs
+Makefile
+Makefile.in
+libobparser.la
+parse.lo
diff --git a/parser/Makefile.am b/parser/Makefile.am
new file mode 100644 (file)
index 0000000..fe80db1
--- /dev/null
@@ -0,0 +1,20 @@
+localedir=$(datadir)/locale
+rcdir=$(datadir)/openbox
+
+CPPFLAGS=$(GLIB_CFLAGS) $(XML_CFLAGS) @CPPFLAGS@ \
+         -DG_LOG_DOMAIN=\"Parser\" \
+         -DLOCALEDIR=\"$(localedir)\" \
+         -DRCDIR=\"$(rcdir)\"
+
+INCLUDES=-I..
+LIBS=$(GLIB_LIBS) $(XML_LIBS) @LIBS@
+
+lib_LTLIBRARIES=libobparser.la
+libobparser_la_SOURCES=parse.c
+
+noinst_HEADERS=parse.h
+
+MAINTAINERCLEANFILES=Makefile.in
+
+distclean-local:
+       $(RM) *\~ *.orig *.rej .\#*
diff --git a/parser/parse.c b/parser/parse.c
new file mode 100644 (file)
index 0000000..2b81594
--- /dev/null
@@ -0,0 +1,190 @@
+#include "parse.h"
+#include <glib.h>
+
+struct Callback {
+    char *tag;
+    ParseCallback func;
+    void *data;
+};
+
+static GHashTable *callbacks;
+
+static void destfunc(struct Callback *c)
+{
+    g_free(c->tag);
+    g_free(c);
+}
+
+void parse_startup()
+{
+    callbacks = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
+                                      (GDestroyNotify)destfunc);
+}
+
+void parse_shutdown()
+{
+    g_hash_table_destroy(callbacks);
+}
+
+void parse_register(const char *tag, ParseCallback func, void *data)
+{
+    struct Callback *c;
+
+    if ((c = g_hash_table_lookup(callbacks, tag))) {
+        g_warning("tag '%s' already registered", tag);
+        return;
+    }
+
+    c = g_new(struct Callback, 1);
+    c->tag = g_strdup(tag);
+    c->func = func;
+    c->data = data;
+    g_hash_table_insert(callbacks, c->tag, c);
+}
+
+gboolean parse_load_rc(xmlDocPtr *doc, xmlNodePtr *root)
+{
+    char *path;
+    gboolean r = FALSE;
+
+    path = g_build_filename(g_get_home_dir(), ".openbox", "rc3", NULL);
+    if (parse_load(path, "openbox_config", doc, root)) {
+        r = TRUE;
+    } else {
+        g_free(path);
+        path = g_build_filename(RCDIR, "rc3", NULL);
+        if (parse_load(path, "openbox_config", doc, root)) {
+            r = TRUE;
+        }
+    }
+    g_free(path);
+    if (!r)
+        g_message("unable to find a valid config file, using defaults");
+    return r;
+}
+
+gboolean parse_load(const char *path, const char *rootname,
+                    xmlDocPtr *doc, xmlNodePtr *root)
+{
+
+    xmlLineNumbersDefault(1);
+
+    if ((*doc = xmlParseFile(path))) {
+        *root = xmlDocGetRootElement(*doc);
+        if (!*root) {
+            xmlFreeDoc(*doc);
+            *doc = NULL;
+            g_warning("%s is an empty document", path);
+        } else {
+            if (xmlStrcasecmp((*root)->name, (const xmlChar*)rootname)) {
+                xmlFreeDoc(*doc);
+                *doc = NULL;
+                g_warning("document %s is of wrong type. root *root is "
+                          "not 'openbox_config'", path);
+            }
+        }
+    }
+    if (!*doc)
+        return FALSE;
+    return TRUE;
+}
+
+void parse_close(xmlDocPtr doc)
+{
+    xmlFree(doc);
+}
+
+void parse_tree(xmlDocPtr doc, xmlNodePtr node, void *nothing)
+{
+    while (node) {
+        struct Callback *c = g_hash_table_lookup(callbacks, node->name);
+
+        if (c)
+            c->func(doc, node->xmlChildrenNode, c->data);
+
+        node = node->next;
+    }
+}
+
+char *parse_string(xmlDocPtr doc, xmlNodePtr node)
+{
+    xmlChar *c = xmlNodeListGetString(doc, node->xmlChildrenNode, TRUE);
+    char *s = g_strdup((char*)c);
+    xmlFree(c);
+    return s;
+}
+
+int parse_int(xmlDocPtr doc, xmlNodePtr node)
+{
+    xmlChar *c = xmlNodeListGetString(doc, node->xmlChildrenNode, TRUE);
+    int i = atoi((char*)c);
+    xmlFree(c);
+    return i;
+}
+
+gboolean parse_bool(xmlDocPtr doc, xmlNodePtr node)
+{
+    xmlChar *c = xmlNodeListGetString(doc, node->xmlChildrenNode, TRUE);
+    gboolean b = FALSE;
+    if (!xmlStrcasecmp(c, (const xmlChar*) "true"))
+        b = TRUE;
+    else if (!xmlStrcasecmp(c, (const xmlChar*) "yes"))
+        b = TRUE;
+    else if (!xmlStrcasecmp(c, (const xmlChar*) "on"))
+        b = TRUE;
+    xmlFree(c);
+    return b;
+}
+
+gboolean parse_contains(const char *val, xmlDocPtr doc, xmlNodePtr node)
+{
+    xmlChar *c = xmlNodeListGetString(doc, node->xmlChildrenNode, TRUE);
+    gboolean r;
+    r = !xmlStrcasecmp(c, (const xmlChar*) val);
+    xmlFree(c);
+    return r;
+}
+
+xmlNodePtr parse_find_node(const char *tag, xmlNodePtr node)
+{
+    while (node) {
+        if (!xmlStrcasecmp(node->name, (const xmlChar*) tag))
+            return node;
+        node = node->next;
+    }
+    return NULL;
+}
+
+gboolean parse_attr_int(const char *name, xmlNodePtr node, int *value)
+{
+    xmlChar *c = xmlGetProp(node, (const xmlChar*) name);
+    gboolean r = FALSE;
+    if (c) {
+        *value = atoi((char*)c);
+        r = TRUE;
+    }
+    xmlFree(c);
+    return r;
+}
+
+gboolean parse_attr_string(const char *name, xmlNodePtr node, char **value)
+{
+    xmlChar *c = xmlGetProp(node, (const xmlChar*) name);
+    gboolean r = FALSE;
+    if (c) {
+        *value = g_strdup((char*)c);
+        r = TRUE;
+    }
+    xmlFree(c);
+    return r;
+}
+
+gboolean parse_attr_contains(const char *val, xmlNodePtr node,
+                             const char *name)
+{
+    xmlChar *c = xmlGetProp(node, (const xmlChar*) name);
+    gboolean r;
+    r = !xmlStrcasecmp(c, (const xmlChar*) val);
+    xmlFree(c);
+    return r;
+}
similarity index 72%
rename from openbox/parse.h
rename to parser/parse.h
index 199e8104d7d1abd81e232a97a1d308ec12bb606e..948bf4ba0e285935892e1b95153a369762290b3d 100644 (file)
@@ -1,8 +1,6 @@
 #ifndef __parse_h
 #define __parse_h
 
-#include "action.h"
-
 #include <libxml/parser.h>
 #include <glib.h>
 
@@ -11,13 +9,22 @@ typedef void (*ParseCallback)(xmlDocPtr doc, xmlNodePtr node, void *data);
 void parse_startup();
 void parse_shutdown();
 
-void parse_register(const char *tag, ParseCallback func, void *data);
+/* Loads Openbox's rc, from $HOME or $PREFIX as a fallback */
+gboolean parse_load_rc(xmlDocPtr *doc, xmlNodePtr *root);
 
-void parse_config();
+/* callbacks - must call parse_startup to use these */
 
+void parse_register(const char *tag, ParseCallback func, void *data);
 void parse_tree(xmlDocPtr doc, xmlNodePtr node, void *nothing);
 
 
+/* open/close */
+
+gboolean parse_load(const char *path, const char *rootname,
+                    xmlDocPtr *doc, xmlNodePtr *root);
+void parse_close(xmlDocPtr doc);
+
+
 /* helpers */
 
 xmlNodePtr parse_find_node(const char *tag, xmlNodePtr node);
@@ -33,6 +40,4 @@ gboolean parse_attr_contains(const char *val, xmlNodePtr node,
 gboolean parse_attr_string(const char *name, xmlNodePtr node, char **value);
 gboolean parse_attr_int(const char *name, xmlNodePtr node, int *value);
 
-Action *parse_action(xmlDocPtr doc, xmlNodePtr node);
-
 #endif
index b23259d621993cb7ddaab1780ff4c94596de4005..ec89616dce1ae009a5b7346b4b943e90f11a5f5c 100644 (file)
@@ -1,20 +1,6 @@
-plugindir=$(libdir)/openbox/plugins
+SUBDIRS = keyboard mouse placement menu resistance
 
-SUBDIRS = keyboard mouse placement menu
-
-CPPFLAGS=$(XFT_CFLAGS) $(GLIB_CFLAGS) $(LIBSN_CFLAGS) $(GL_CFLAGS) \
-         $(XML_CFLAGS)  @CPPFLAGS@ \
--DPLUGINDIR=\"$(plugindir)\"
-
-INCLUDES=-I..
-
-plugin_LTLIBRARIES=resistance.la
-
-resistance_la_CPPFLAGS=-DG_LOG_DOMAIN=\"Plugin-Resistance\"
-resistance_la_LDFLAGS=-module -avoid-version
-resistance_la_SOURCES=resistance.c
-
-noinst_HEADERS=
+noinst_HEADERS = interface.h obconf_interface.h
 
 MAINTAINERCLEANFILES= Makefile.in
 
diff --git a/plugins/interface.h b/plugins/interface.h
new file mode 100644 (file)
index 0000000..8c5c645
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef __plugins_interface_h
+#define __plugins_interface_h
+
+/* plugin_setup_config() */
+typedef void (*PluginSetupConfig)(void);
+
+/* plugin_startup() */
+typedef void (*PluginStartup)(void);
+
+/* plugin_shutdown() */
+typedef void (*PluginShutdown)(void);
+
+/* plugin_create() - for menu plugins only */
+typedef void *(*PluginCreate)(/* TODO */);
+
+/* plugin_destroy() - for menu plugins only */
+typedef void (*PluginDestroy)(void *);
+
+#endif
index d1d93241a77e5422ace3440325179aa475f3b341..374f24932e47078172990242f99fefe9516585f6 100644 (file)
@@ -5,8 +5,8 @@
 #include "kernel/grab.h"
 #include "kernel/action.h"
 #include "kernel/prop.h"
-#include "kernel/parse.h"
 #include "kernel/timer.h"
+#include "parser/parse.h"
 #include "tree.h"
 #include "keyboard.h"
 #include "translate.h"
@@ -45,7 +45,7 @@ static void parse_key(xmlDocPtr doc, xmlNodePtr node, GList *keylist)
     if (keylist) {
         nact = parse_find_node("action", node);
         while (nact) {
-            if ((action = parse_action(doc, nact))) {
+            if ((action = action_parse(doc, nact))) {
                 /* validate that its okay for a key binding */
                 if (action->func == action_moveresize &&
                     action->data.moveresize.corner !=
index 40b9b64d62294ffcb1732cdd75f488142719e84d..3ed9c5c60202a93bc0f30150edc75ea44f2877e0 100644 (file)
@@ -1,6 +1,7 @@
 plugindir=$(libdir)/openbox/plugins
 
-CPPFLAGS=$(XFT_CFLAGS) $(GLIB_CFLAGS) $(LIBSN_CFLAGS) @CPPFLAGS@ \
+CPPFLAGS=$(XFT_CFLAGS) $(GLIB_CFLAGS) $(LIBSN_CFLAGS) $(XML_CFLAGS)
+         \@CPPFLAGS@ \
          -DG_LOG_DOMAIN=\"Plugin-Timed-Menu\"
 
 INCLUDES=-I../..
index 0bfe602c7cb936647785a9a78d98b70b1356097c..a2b3d7e04d01578f4a21e994c83292ffc486eed4 100644 (file)
@@ -5,8 +5,8 @@
 #include "kernel/client.h"
 #include "kernel/prop.h"
 #include "kernel/grab.h"
-#include "kernel/parse.h"
 #include "kernel/frame.h"
+#include "parser/parse.h"
 #include "translate.h"
 #include "mouse.h"
 #include <glib.h>
@@ -59,7 +59,7 @@ static void parse_xml(xmlDocPtr doc, xmlNodePtr node, void *d)
                 goto next_nbut;
             nact = parse_find_node("action", nbut->xmlChildrenNode);
             while (nact) {
-                if ((action = parse_action(doc, nact))) {
+                if ((action = action_parse(doc, nact))) {
                     /* validate that its okay for a mouse binding*/
                     if (mact == MouseAction_Motion) {
                         if (action->func != action_moveresize ||
diff --git a/plugins/obconf_interface.h b/plugins/obconf_interface.h
new file mode 100644 (file)
index 0000000..52b19a8
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef __obconf_plugin_interface_h
+#define __obconf_plugin_interface_h
+
+#include "parser/parse.h"
+
+struct GtkWidget;
+
+#define OBCONF_INTERFACE_VERSION 1
+
+/* plugin_interface_version() */
+typedef int (*PluginInterfaceVersionFunc)(void);
+
+/* plugin_startup() */
+typedef void (*PluginStartupFunc)(void);
+
+/* plugin_shutdown() */
+typedef void (*PluginShutdownFunc)(void);
+
+/* plugin_name() - user friendly name of the plugin */
+typedef char* (*PluginNameFunc)(void);
+
+/* plugin_plugin_name() - the name of the plugin to load with openbox */
+typedef char* (*PluginPluginNameFunc)(void);
+
+/* plugin_icon() XXX FIXME */
+typedef void (*PluginIconFunc)(void);
+
+/* plugin_toplevel_widget() */
+typedef struct _GtkWidget* (*PluginToplevelWidgetFunc)(void);
+
+/* plugin_edited() */
+typedef gboolean (*PluginEditedFunc)(void);
+
+/* plugin_load() */
+typedef void (*PluginLoadFunc)(xmlDocPtr doc, xmlNodePtr root);
+
+/* plugin_save() */
+typedef void (*PluginSaveFunc)(xmlDocPtr doc, xmlNodePtr root);
+
+#endif
index 9d932b9edfbe7e0ca292738f298f91ae0d6782ce..716487b6e76a9d0dd49fa50b345e21dbe4a40f08 100644 (file)
@@ -3,7 +3,7 @@
 #include "kernel/frame.h"
 #include "kernel/client.h"
 #include "kernel/screen.h"
-#include "kernel/parse.h"
+#include "parser/parse.h"
 #include "history.h"
 #include <glib.h>
 #include <string.h>
@@ -193,18 +193,8 @@ static void load_history()
     char *role;
     struct HistoryItem *hi;
 
-    if (!(doc = xmlParseFile(history_path)))
+    if (!parse_load(history_path, "openbox_history", &doc, &node))
         return;
-    if (!(node = xmlDocGetRootElement(doc))) {
-        xmlFreeDoc(doc);
-        doc = NULL;
-        return;
-    }
-    if (xmlStrcasecmp(node->name, (const xmlChar*)"openbox_history")) {
-        xmlFreeDoc(doc);
-        doc = NULL;
-        return;
-    }
 
     node = parse_find_node("entry", node->xmlChildrenNode);
     while (node) {
index dd818970b0fef6b498be005a507bbb549607fe90..889168b941f49e68aff6c8b33c865fff10b4af34 100644 (file)
@@ -3,7 +3,7 @@
 #include "kernel/frame.h"
 #include "kernel/screen.h"
 #include "kernel/openbox.h"
-#include "kernel/parse.h"
+#include "parser/parse.h"
 #include "history.h"
 #include <glib.h>
 
diff --git a/plugins/resistance/.cvsignore b/plugins/resistance/.cvsignore
new file mode 100644 (file)
index 0000000..fe97c5f
--- /dev/null
@@ -0,0 +1,8 @@
+.deps
+.libs
+Makefile
+Makefile.in
+resistance-config.la
+resistance.la
+resistance_config_la-resistance_config.lo
+resistance_la-resistance.lo
diff --git a/plugins/resistance/Makefile.am b/plugins/resistance/Makefile.am
new file mode 100644 (file)
index 0000000..9f95f94
--- /dev/null
@@ -0,0 +1,32 @@
+plugindir=$(libdir)/openbox/plugins
+
+CPPFLAGS=$(XFT_CFLAGS) $(GLIB_CFLAGS) $(LIBSN_CFLAGS) $(GL_CFLAGS) \
+         $(XML_CFLAGS)  @CPPFLAGS@ \
+         -DPLUGINDIR=\"$(plugindir)\"
+
+INCLUDES=-I../.. -I../../tools
+
+plugin_LTLIBRARIES=resistance.la
+if OBCONF
+plugin_LTLIBRARIES+=resistance-config.la
+endif
+
+resistance_la_CPPFLAGS=-DG_LOG_DOMAIN=\"Plugin-Resistance\"
+resistance_la_LDFLAGS=-module -avoid-version
+resistance_la_SOURCES=resistance.c
+
+if OBCONF
+resistance_config_la_CPPFLAGS=-DG_LOG_DOMAIN=\"Plugin-Resistance\" \
+                              $(GTK_CFLAGS) $(GLADE_CFLAGS)
+resistance_config_la_LDFLAGS=-module -avoid-version
+resistance_config_la_SOURCES=resistance_config.c
+endif
+
+noinst_HEADERS=resistance.h
+
+noinst_DATA=resistance.glade resistance.gladep
+
+MAINTAINERCLEANFILES= Makefile.in
+
+distclean-local:
+       $(RM) *\~ *.orig *.rej .\#*
similarity index 98%
rename from plugins/resistance.c
rename to plugins/resistance/resistance.c
index ee6f6e1e6c5794ce5b9d1f1d555dcbae17ed7a65..91c10c0e54d468856b16e13661d06e8c31f80c97 100644 (file)
@@ -1,9 +1,10 @@
 #include "kernel/dispatch.h"
 #include "kernel/client.h"
 #include "kernel/frame.h"
-#include "kernel/parse.h"
 #include "kernel/stacking.h"
 #include "kernel/screen.h"
+#include "parser/parse.h"
+#include "resistance.h"
 #include <glib.h>
 
 static int resistance;
@@ -21,8 +22,8 @@ static void parse_xml(xmlDocPtr doc, xmlNodePtr node, void *d)
 
 void plugin_setup_config()
 {
-    resistance = 10;
-    resist_windows = TRUE;
+    resistance = DEFAULT_RESISTANCE;
+    resist_windows = DEFAULT_RESIST_WINDOWS;
 
     parse_register("resistance", parse_xml, NULL);
 }
diff --git a/plugins/resistance/resistance.glade b/plugins/resistance/resistance.glade
new file mode 100644 (file)
index 0000000..ecb52b0
--- /dev/null
@@ -0,0 +1,109 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
+
+<glade-interface>
+
+<widget class="GtkWindow" id="resistwindow">
+  <property name="title" translatable="yes"></property>
+  <property name="type">GTK_WINDOW_POPUP</property>
+  <property name="window_position">GTK_WIN_POS_NONE</property>
+  <property name="modal">False</property>
+  <property name="resizable">True</property>
+  <property name="destroy_with_parent">False</property>
+
+  <child>
+    <widget class="GtkVBox" id="vbox1">
+      <property name="visible">True</property>
+      <property name="homogeneous">False</property>
+      <property name="spacing">0</property>
+
+      <child>
+       <widget class="GtkHBox" id="hbox2">
+         <property name="visible">True</property>
+         <property name="homogeneous">False</property>
+         <property name="spacing">6</property>
+
+         <child>
+           <widget class="GtkLabel" id="label1">
+             <property name="visible">True</property>
+             <property name="label" translatable="yes">_Strength</property>
+             <property name="use_underline">True</property>
+             <property name="use_markup">False</property>
+             <property name="justify">GTK_JUSTIFY_LEFT</property>
+             <property name="wrap">False</property>
+             <property name="selectable">False</property>
+             <property name="xalign">0.49</property>
+             <property name="yalign">0.5</property>
+             <property name="xpad">0</property>
+             <property name="ypad">0</property>
+             <property name="mnemonic_widget">resist_strength</property>
+           </widget>
+           <packing>
+             <property name="padding">0</property>
+             <property name="expand">False</property>
+             <property name="fill">False</property>
+           </packing>
+         </child>
+
+         <child>
+           <widget class="GtkSpinButton" id="resist_strength">
+             <property name="visible">True</property>
+             <property name="tooltip" translatable="yes">Set to the amount of resistance to provide when moving or resizing a window past a screen or window edge. A value of 0 disables resistance.</property>
+             <property name="can_focus">True</property>
+             <property name="climb_rate">1</property>
+             <property name="digits">0</property>
+             <property name="numeric">True</property>
+             <property name="update_policy">GTK_UPDATE_ALWAYS</property>
+             <property name="snap_to_ticks">False</property>
+             <property name="wrap">False</property>
+             <property name="adjustment">1 0 30 1 10 10</property>
+           </widget>
+           <packing>
+             <property name="padding">0</property>
+             <property name="expand">False</property>
+             <property name="fill">True</property>
+           </packing>
+         </child>
+       </widget>
+       <packing>
+         <property name="padding">0</property>
+         <property name="expand">True</property>
+         <property name="fill">True</property>
+       </packing>
+      </child>
+
+      <child>
+       <widget class="GtkHBox" id="hbox1">
+         <property name="visible">True</property>
+         <property name="homogeneous">False</property>
+         <property name="spacing">6</property>
+
+         <child>
+           <widget class="GtkCheckButton" id="resist_windows">
+             <property name="visible">True</property>
+             <property name="can_focus">True</property>
+             <property name="label" translatable="yes">Resist other _Windows</property>
+             <property name="use_underline">True</property>
+             <property name="relief">GTK_RELIEF_NORMAL</property>
+             <property name="active">False</property>
+             <property name="inconsistent">False</property>
+             <property name="draw_indicator">True</property>
+           </widget>
+           <packing>
+             <property name="padding">0</property>
+             <property name="expand">False</property>
+             <property name="fill">False</property>
+           </packing>
+         </child>
+       </widget>
+       <packing>
+         <property name="padding">0</property>
+         <property name="expand">True</property>
+         <property name="fill">True</property>
+       </packing>
+      </child>
+    </widget>
+  </child>
+</widget>
+
+</glade-interface>
diff --git a/plugins/resistance/resistance.gladep b/plugins/resistance/resistance.gladep
new file mode 100644 (file)
index 0000000..1951d46
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<!DOCTYPE glade-project SYSTEM "http://glade.gnome.org/glade-project-2.0.dtd">
+
+<glade-project>
+  <name>resistance</name>
+  <program_name>resistance</program_name>
+  <gnome_support>FALSE</gnome_support>
+</glade-project>
diff --git a/plugins/resistance/resistance.h b/plugins/resistance/resistance.h
new file mode 100644 (file)
index 0000000..5bec224
--- /dev/null
@@ -0,0 +1,2 @@
+#define DEFAULT_RESISTANCE 10
+#define DEFAULT_RESIST_WINDOWS TRUE
diff --git a/plugins/resistance/resistance_config.c b/plugins/resistance/resistance_config.c
new file mode 100644 (file)
index 0000000..1384fe3
--- /dev/null
@@ -0,0 +1,64 @@
+#include "plugins/obconf_interface.h"
+#include "parser/parse.h"
+#include "resistance.h"
+#include <gtk/gtk.h>
+#include <glade/glade.h>
+
+static GtkWidget *conf_widget;
+static GtkCheckButton *conf_resist_windows;
+static GtkSpinButton *conf_resist_strength;
+static gboolean conf_edited = FALSE;
+
+int plugin_interface_version() { return OBCONF_INTERFACE_VERSION; }
+
+char *plugin_name() { return "Resistance"; }
+char *plugin_plugin_name() { return "resistance"; }
+void plugin_icon() {}
+
+GtkWidget *plugin_toplevel_widget() { return conf_widget; }
+
+gboolean plugin_edited() { return conf_edited; }
+
+void plugin_load(xmlDocPtr doc, xmlNodePtr root)
+{
+    xmlNodePtr node, n;
+
+    gtk_spin_button_set_value(conf_resist_strength, DEFAULT_RESISTANCE);
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(conf_resist_windows),
+                                 DEFAULT_RESIST_WINDOWS);
+
+    node = parse_find_node("resistance", root);
+    while (node) {
+        if ((n = parse_find_node("strength", node)))
+            gtk_spin_button_set_value(conf_resist_strength,
+                                      parse_int(doc, n));
+        if ((n = parse_find_node("windows", node)))
+            gtk_toggle_button_set_active
+                (GTK_TOGGLE_BUTTON(conf_resist_windows),
+                 parse_bool(doc, n));
+
+        node = parse_find_node("resistance", node->next);
+    }
+}
+
+void plugin_save(xmlDocPtr doc, xmlNodePtr root)
+{
+}
+
+void plugin_startup()
+{
+    GladeXML *xml;
+
+    xml = glade_xml_new("obconf.glade", NULL, NULL);
+    glade_xml_signal_autoconnect(xml);
+
+    conf_widget = glade_xml_get_widget(xml, "resistwindow");
+    conf_resist_strength =
+        GTK_SPIN_BUTTON(glade_xml_get_widget(xml, "resist_strength"));
+    conf_resist_windows =
+        GTK_CHECK_BUTTON(glade_xml_get_widget(xml, "resist_windows"));
+}
+
+void plugin_shutdown()
+{
+}
diff --git a/tools/.cvsignore b/tools/.cvsignore
new file mode 100644 (file)
index 0000000..282522d
--- /dev/null
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/tools/Makefile.am b/tools/Makefile.am
new file mode 100644 (file)
index 0000000..86eaea7
--- /dev/null
@@ -0,0 +1,5 @@
+SUBDIRS =
+
+if OBCONF
+SUBDIRS += obconf
+endif
diff --git a/tools/obconf/.cvsignore b/tools/obconf/.cvsignore
new file mode 100644 (file)
index 0000000..b35c97a
--- /dev/null
@@ -0,0 +1,5 @@
+.deps
+.libs
+Makefile
+Makefile.in
+obconf
diff --git a/tools/obconf/Makefile.am b/tools/obconf/Makefile.am
new file mode 100644 (file)
index 0000000..a83049f
--- /dev/null
@@ -0,0 +1,26 @@
+localedir=$(datadir)/locale
+plugindir=$(libdir)/openbox/plugins
+rcdir=$(datadir)/openbox
+
+CPPFLAGS=$(GTK_CFLAGS) $(GLADE_CFLAGS) $(GMODULE_CFLAGS) $(XML_CFLAGS) \
+         @CPPFLAGS@ \
+         -DLOCALEDIR=\"$(localedir)\" \
+         -DRCDIR=\"$(rcdir)\" \
+         -DPLUGINDIR=\"$(plugindir)\" \
+         -DG_LOG_DOMAIN=\"ObConf\"
+
+INCLUDES=-I../..
+LIBS=$(GTK_LIBS) $(GLADE_LIBS) $(GMODULE_LIBS) $(XML_LIBS) @LIBS@ @LIBINTL@
+
+bin_PROGRAMS=obconf
+
+obconf_LDADD=-lobparser -L../../parser
+obconf_LDFLAGS=-export-dynamic
+obconf_SOURCES=main.c about.c plugins.c
+
+noinst_HEADERS=obconf.h plugins.h
+
+MAINTAINERCLEANFILES=Makefile.in
+
+distclean-local:
+       $(RM) *\~ *.orig *.rej .\#*
diff --git a/tools/obconf/about.c b/tools/obconf/about.c
new file mode 100644 (file)
index 0000000..34de63f
--- /dev/null
@@ -0,0 +1,18 @@
+#include "obconf.h"
+
+void on_about_activate(GtkMenuItem *item, gpointer d)
+{
+    gtk_widget_show(GTK_WIDGET(obconf_about));
+}
+
+gboolean on_aboutdialog_delete_event(GtkWidget *w, GdkEvent *e, gpointer d)
+{
+    gtk_widget_hide(GTK_WIDGET(obconf_about));
+    return TRUE;
+}
+
+void on_about_closebutton_clicked(GtkButton *but, gpointer d)
+{
+    gtk_widget_hide(GTK_WIDGET(obconf_about));
+}
+
diff --git a/tools/obconf/main.c b/tools/obconf/main.c
new file mode 100644 (file)
index 0000000..f0eb730
--- /dev/null
@@ -0,0 +1,91 @@
+#include "obconf.h"
+#include "plugins.h"
+#include "parser/parse.h"
+
+#include <gtk/gtk.h>
+#include <glade/glade.h>
+
+/*#include <X11/Xlib.h>
+Display *ob_display;
+int ob_screen;
+Window ob_root;*/
+
+GtkWindow *obconf_win;
+GtkWindow *obconf_about = NULL;
+
+GtkTreeView *obconf_sections;
+GtkListStore *obconf_sections_store;
+static GtkCellRenderer *obconf_sections_renderer;
+static GtkTreeViewColumn *obconf_sections_column;
+
+GtkNotebook *obconf_options;
+
+static xmlDocPtr doc;
+static xmlNodePtr root;
+
+int main(int argc, char **argv)
+{
+    GladeXML *xml;
+
+    gtk_init(&argc, &argv);
+
+    xml = glade_xml_new("obconf.glade", NULL, NULL);
+    glade_xml_signal_autoconnect(xml);
+
+    obconf_win = GTK_WINDOW(glade_xml_get_widget(xml, "mainwindow"));
+    gtk_window_set_role(obconf_win, "main");
+    obconf_about = GTK_WINDOW(glade_xml_get_widget(xml, "aboutdialog"));
+    gtk_window_set_role(obconf_about, "about");
+    gtk_window_set_transient_for(obconf_about, obconf_win);
+    obconf_sections = GTK_TREE_VIEW(glade_xml_get_widget(xml, "sectiontree"));
+    obconf_options = GTK_NOTEBOOK(glade_xml_get_widget(xml,"optionsnotebook"));
+
+    obconf_sections_store = gtk_list_store_new(1, G_TYPE_STRING);
+    gtk_tree_view_set_model(obconf_sections,
+                            GTK_TREE_MODEL(obconf_sections_store));
+    obconf_sections_renderer = gtk_cell_renderer_text_new();
+    obconf_sections_column = gtk_tree_view_column_new_with_attributes
+        ("Section", obconf_sections_renderer, "text", 0, NULL);
+    gtk_tree_view_append_column (obconf_sections, obconf_sections_column);
+
+    parse_load_rc(&doc, &root);
+
+    plugins_load();
+
+    gtk_widget_show(GTK_WIDGET(obconf_win));
+
+    gtk_main();
+    return 0;
+}
+
+gboolean on_mainwindow_delete_event(GtkWidget *w, GdkEvent *e, gpointer d)
+{
+    gtk_main_quit();
+    return FALSE;
+}
+
+void on_quit_activate(GtkMenuItem *item, gpointer d)
+{
+    gtk_main_quit();
+}
+
+void on_applybutton_clicked(GtkButton *but, gpointer d)
+{
+    g_message("apply");
+}
+
+void on_revertbutton_clicked(GtkButton *but, gpointer d)
+{
+    g_message("revert");
+}
+
+void on_helpbutton_clicked(GtkButton *but, gpointer d)
+{
+    g_message("help");
+}
+
+void on_sectiontree_row_activated(GtkTreeView *tree, GtkTreePath *path,
+                                  GtkTreeViewColumn *col, gpointer p)
+{
+    g_message("activated");
+}
diff --git a/tools/obconf/obconf.glade b/tools/obconf/obconf.glade
new file mode 100644 (file)
index 0000000..205706b
--- /dev/null
@@ -0,0 +1,427 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
+
+<glade-interface>
+
+<widget class="GtkWindow" id="mainwindow">
+  <property name="title" translatable="yes">ObConf</property>
+  <property name="type">GTK_WINDOW_TOPLEVEL</property>
+  <property name="window_position">GTK_WIN_POS_NONE</property>
+  <property name="modal">False</property>
+  <property name="resizable">True</property>
+  <property name="destroy_with_parent">True</property>
+  <signal name="delete_event" handler="on_mainwindow_delete_event" last_modification_time="Sat, 24 May 2003 17:17:43 GMT"/>
+
+  <child>
+    <widget class="GtkVBox" id="vbox1">
+      <property name="visible">True</property>
+      <property name="homogeneous">False</property>
+      <property name="spacing">0</property>
+
+      <child>
+       <widget class="GtkMenuBar" id="menubar1">
+         <property name="visible">True</property>
+
+         <child>
+           <widget class="GtkMenuItem" id="menuitem1">
+             <property name="visible">True</property>
+             <property name="label" translatable="yes">_File</property>
+             <property name="use_underline">True</property>
+
+             <child>
+               <widget class="GtkMenu" id="menuitem1_menu">
+
+                 <child>
+                   <widget class="GtkImageMenuItem" id="quit">
+                     <property name="visible">True</property>
+                     <property name="label">gtk-quit</property>
+                     <property name="use_stock">True</property>
+                     <signal name="activate" handler="on_quit_activate" last_modification_time="Sat, 24 May 2003 17:00:32 GMT"/>
+                   </widget>
+                 </child>
+               </widget>
+             </child>
+           </widget>
+         </child>
+
+         <child>
+           <widget class="GtkMenuItem" id="menuitem4">
+             <property name="visible">True</property>
+             <property name="label" translatable="yes">_Help</property>
+             <property name="use_underline">True</property>
+
+             <child>
+               <widget class="GtkMenu" id="menuitem4_menu">
+
+                 <child>
+                   <widget class="GtkMenuItem" id="about">
+                     <property name="visible">True</property>
+                     <property name="label" translatable="yes">_About</property>
+                     <property name="use_underline">True</property>
+                     <signal name="activate" handler="on_about_activate" last_modification_time="Sat, 24 May 2003 17:00:32 GMT"/>
+                   </widget>
+                 </child>
+               </widget>
+             </child>
+           </widget>
+         </child>
+       </widget>
+       <packing>
+         <property name="padding">0</property>
+         <property name="expand">False</property>
+         <property name="fill">False</property>
+       </packing>
+      </child>
+
+      <child>
+       <widget class="GtkHPaned" id="hpaned1">
+         <property name="border_width">6</property>
+         <property name="visible">True</property>
+         <property name="can_focus">True</property>
+         <property name="position">121</property>
+
+         <child>
+           <widget class="GtkVBox" id="vbox2">
+             <property name="visible">True</property>
+             <property name="homogeneous">False</property>
+             <property name="spacing">0</property>
+
+             <child>
+               <widget class="GtkLabel" id="label2">
+                 <property name="visible">True</property>
+                 <property name="label" translatable="yes">Sections</property>
+                 <property name="use_underline">False</property>
+                 <property name="use_markup">False</property>
+                 <property name="justify">GTK_JUSTIFY_LEFT</property>
+                 <property name="wrap">False</property>
+                 <property name="selectable">False</property>
+                 <property name="xalign">0.5</property>
+                 <property name="yalign">0.5</property>
+                 <property name="xpad">0</property>
+                 <property name="ypad">0</property>
+               </widget>
+               <packing>
+                 <property name="padding">0</property>
+                 <property name="expand">False</property>
+                 <property name="fill">False</property>
+               </packing>
+             </child>
+
+             <child>
+               <widget class="GtkScrolledWindow" id="scrolledwindow1">
+                 <property name="visible">True</property>
+                 <property name="can_focus">True</property>
+                 <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+                 <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+                 <property name="shadow_type">GTK_SHADOW_IN</property>
+                 <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+                 <child>
+                   <widget class="GtkTreeView" id="sectiontree">
+                     <property name="visible">True</property>
+                     <property name="can_focus">True</property>
+                     <property name="headers_visible">False</property>
+                     <property name="rules_hint">False</property>
+                     <property name="reorderable">False</property>
+                     <property name="enable_search">True</property>
+                     <signal name="row_activated" handler="on_sectiontree_row_activated" last_modification_time="Sat, 24 May 2003 17:00:00 GMT"/>
+                   </widget>
+                 </child>
+               </widget>
+               <packing>
+                 <property name="padding">0</property>
+                 <property name="expand">True</property>
+                 <property name="fill">True</property>
+               </packing>
+             </child>
+           </widget>
+           <packing>
+             <property name="shrink">True</property>
+             <property name="resize">False</property>
+           </packing>
+         </child>
+
+         <child>
+           <widget class="GtkVBox" id="vbox3">
+             <property name="visible">True</property>
+             <property name="homogeneous">False</property>
+             <property name="spacing">0</property>
+
+             <child>
+               <widget class="GtkLabel" id="label3">
+                 <property name="visible">True</property>
+                 <property name="label" translatable="yes">Options</property>
+                 <property name="use_underline">False</property>
+                 <property name="use_markup">False</property>
+                 <property name="justify">GTK_JUSTIFY_LEFT</property>
+                 <property name="wrap">False</property>
+                 <property name="selectable">False</property>
+                 <property name="xalign">0.5</property>
+                 <property name="yalign">0.5</property>
+                 <property name="xpad">0</property>
+                 <property name="ypad">0</property>
+               </widget>
+               <packing>
+                 <property name="padding">0</property>
+                 <property name="expand">False</property>
+                 <property name="fill">False</property>
+               </packing>
+             </child>
+
+             <child>
+               <widget class="GtkNotebook" id="optionsnotebook">
+                 <property name="visible">True</property>
+                 <property name="show_tabs">False</property>
+                 <property name="show_border">False</property>
+                 <property name="tab_pos">GTK_POS_TOP</property>
+                 <property name="scrollable">False</property>
+                 <property name="enable_popup">False</property>
+
+                 <child>
+                   <placeholder/>
+                 </child>
+
+                 <child>
+                   <placeholder/>
+                 </child>
+               </widget>
+               <packing>
+                 <property name="padding">0</property>
+                 <property name="expand">True</property>
+                 <property name="fill">True</property>
+               </packing>
+             </child>
+           </widget>
+           <packing>
+             <property name="shrink">True</property>
+             <property name="resize">True</property>
+           </packing>
+         </child>
+       </widget>
+       <packing>
+         <property name="padding">0</property>
+         <property name="expand">True</property>
+         <property name="fill">True</property>
+       </packing>
+      </child>
+
+      <child>
+       <widget class="GtkHSeparator" id="hseparator1">
+         <property name="visible">True</property>
+       </widget>
+       <packing>
+         <property name="padding">0</property>
+         <property name="expand">False</property>
+         <property name="fill">True</property>
+       </packing>
+      </child>
+
+      <child>
+       <widget class="GtkHBox" id="hbox1">
+         <property name="visible">True</property>
+         <property name="homogeneous">False</property>
+         <property name="spacing">0</property>
+
+         <child>
+           <widget class="GtkHButtonBox" id="hbuttonbox1">
+             <property name="visible">True</property>
+             <property name="layout_style">GTK_BUTTONBOX_START</property>
+             <property name="spacing">0</property>
+
+             <child>
+               <widget class="GtkButton" id="helpbutton">
+                 <property name="visible">True</property>
+                 <property name="can_default">True</property>
+                 <property name="can_focus">True</property>
+                 <property name="label">gtk-help</property>
+                 <property name="use_stock">True</property>
+                 <property name="relief">GTK_RELIEF_NORMAL</property>
+                 <signal name="clicked" handler="on_helpbutton_clicked" last_modification_time="Sat, 24 May 2003 16:59:34 GMT"/>
+               </widget>
+             </child>
+           </widget>
+           <packing>
+             <property name="padding">6</property>
+             <property name="expand">True</property>
+             <property name="fill">True</property>
+           </packing>
+         </child>
+
+         <child>
+           <widget class="GtkHButtonBox" id="hbuttonbox2">
+             <property name="visible">True</property>
+             <property name="layout_style">GTK_BUTTONBOX_END</property>
+             <property name="spacing">6</property>
+
+             <child>
+               <widget class="GtkButton" id="revertbutton">
+                 <property name="visible">True</property>
+                 <property name="can_default">True</property>
+                 <property name="can_focus">True</property>
+                 <property name="relief">GTK_RELIEF_NORMAL</property>
+                 <signal name="clicked" handler="on_revertbutton_clicked" last_modification_time="Sat, 24 May 2003 16:59:29 GMT"/>
+
+                 <child>
+                   <widget class="GtkAlignment" id="alignment2">
+                     <property name="visible">True</property>
+                     <property name="xalign">0.5</property>
+                     <property name="yalign">0.5</property>
+                     <property name="xscale">0</property>
+                     <property name="yscale">0</property>
+
+                     <child>
+                       <widget class="GtkHBox" id="hbox3">
+                         <property name="visible">True</property>
+                         <property name="homogeneous">False</property>
+                         <property name="spacing">2</property>
+
+                         <child>
+                           <widget class="GtkImage" id="image2">
+                             <property name="visible">True</property>
+                             <property name="stock">gtk-cancel</property>
+                             <property name="icon_size">4</property>
+                             <property name="xalign">0.5</property>
+                             <property name="yalign">0.5</property>
+                             <property name="xpad">0</property>
+                             <property name="ypad">0</property>
+                           </widget>
+                           <packing>
+                             <property name="padding">0</property>
+                             <property name="expand">False</property>
+                             <property name="fill">False</property>
+                           </packing>
+                         </child>
+
+                         <child>
+                           <widget class="GtkLabel" id="label5">
+                             <property name="visible">True</property>
+                             <property name="label" translatable="yes">_Revert</property>
+                             <property name="use_underline">True</property>
+                             <property name="use_markup">False</property>
+                             <property name="justify">GTK_JUSTIFY_LEFT</property>
+                             <property name="wrap">False</property>
+                             <property name="selectable">False</property>
+                             <property name="xalign">0.5</property>
+                             <property name="yalign">0.5</property>
+                             <property name="xpad">0</property>
+                             <property name="ypad">0</property>
+                           </widget>
+                           <packing>
+                             <property name="padding">0</property>
+                             <property name="expand">False</property>
+                             <property name="fill">False</property>
+                           </packing>
+                         </child>
+                       </widget>
+                     </child>
+                   </widget>
+                 </child>
+               </widget>
+             </child>
+
+             <child>
+               <widget class="GtkButton" id="applybutton">
+                 <property name="visible">True</property>
+                 <property name="can_default">True</property>
+                 <property name="has_default">True</property>
+                 <property name="can_focus">True</property>
+                 <property name="label">gtk-apply</property>
+                 <property name="use_stock">True</property>
+                 <property name="relief">GTK_RELIEF_NORMAL</property>
+                 <signal name="clicked" handler="on_applybutton_clicked" last_modification_time="Sat, 24 May 2003 16:59:16 GMT"/>
+               </widget>
+             </child>
+           </widget>
+           <packing>
+             <property name="padding">6</property>
+             <property name="expand">True</property>
+             <property name="fill">True</property>
+             <property name="pack_type">GTK_PACK_END</property>
+           </packing>
+         </child>
+       </widget>
+       <packing>
+         <property name="padding">6</property>
+         <property name="expand">False</property>
+         <property name="fill">True</property>
+       </packing>
+      </child>
+    </widget>
+  </child>
+</widget>
+
+<widget class="GtkDialog" id="aboutdialog">
+  <property name="title" translatable="yes">About ObConf</property>
+  <property name="type">GTK_WINDOW_TOPLEVEL</property>
+  <property name="window_position">GTK_WIN_POS_NONE</property>
+  <property name="modal">False</property>
+  <property name="resizable">False</property>
+  <property name="destroy_with_parent">False</property>
+  <property name="has_separator">True</property>
+  <signal name="delete_event" handler="on_aboutdialog_delete_event" last_modification_time="Sat, 24 May 2003 17:29:16 GMT"/>
+
+  <child internal-child="vbox">
+    <widget class="GtkVBox" id="dialog-vbox1">
+      <property name="visible">True</property>
+      <property name="homogeneous">False</property>
+      <property name="spacing">0</property>
+
+      <child internal-child="action_area">
+       <widget class="GtkHButtonBox" id="dialog-action_area1">
+         <property name="visible">True</property>
+         <property name="layout_style">GTK_BUTTONBOX_END</property>
+
+         <child>
+           <widget class="GtkButton" id="about_closebutton">
+             <property name="visible">True</property>
+             <property name="can_default">True</property>
+             <property name="can_focus">True</property>
+             <property name="label">gtk-close</property>
+             <property name="use_stock">True</property>
+             <property name="relief">GTK_RELIEF_NORMAL</property>
+             <property name="response_id">-7</property>
+             <signal name="clicked" handler="on_about_closebutton_clicked" last_modification_time="Sat, 24 May 2003 17:24:49 GMT"/>
+           </widget>
+         </child>
+       </widget>
+       <packing>
+         <property name="padding">0</property>
+         <property name="expand">False</property>
+         <property name="fill">True</property>
+         <property name="pack_type">GTK_PACK_END</property>
+       </packing>
+      </child>
+
+      <child>
+       <widget class="GtkLabel" id="label6">
+         <property name="visible">True</property>
+         <property name="label" translatable="yes">ObConf
+
+ObConf is a configuration tool for the
+Openbox Window Manager.
+
+
+
+
+ObConf is (c) 2003 Ben Jansens</property>
+         <property name="use_underline">False</property>
+         <property name="use_markup">True</property>
+         <property name="justify">GTK_JUSTIFY_CENTER</property>
+         <property name="wrap">True</property>
+         <property name="selectable">False</property>
+         <property name="xalign">0.5</property>
+         <property name="yalign">0.5</property>
+         <property name="xpad">0</property>
+         <property name="ypad">0</property>
+       </widget>
+       <packing>
+         <property name="padding">0</property>
+         <property name="expand">True</property>
+         <property name="fill">True</property>
+       </packing>
+      </child>
+    </widget>
+  </child>
+</widget>
+
+</glade-interface>
diff --git a/tools/obconf/obconf.gladep b/tools/obconf/obconf.gladep
new file mode 100644 (file)
index 0000000..5ef3ad0
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<!DOCTYPE glade-project SYSTEM "http://glade.gnome.org/glade-project-2.0.dtd">
+
+<glade-project>
+  <name>ObConf</name>
+  <program_name>obconf</program_name>
+  <gnome_support>FALSE</gnome_support>
+</glade-project>
diff --git a/tools/obconf/obconf.h b/tools/obconf/obconf.h
new file mode 100644 (file)
index 0000000..5d7a2e6
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __obconf_h
+#define __obconf_h
+
+#include <gtk/gtk.h>
+
+extern GtkWindow *obconf_win;
+extern GtkWindow *obconf_about;
+extern GtkTreeView *obconf_sections;
+extern GtkListStore *obconf_sections_store;
+extern GtkNotebook *obconf_options;
+
+#endif
diff --git a/tools/obconf/plugins.c b/tools/obconf/plugins.c
new file mode 100644 (file)
index 0000000..f838b96
--- /dev/null
@@ -0,0 +1,157 @@
+#include "obconf.h"
+#include "plugins/obconf_interface.h"
+
+#include <sys/types.h>
+#include <dirent.h>
+#include <string.h>
+#include <gmodule.h>
+
+typedef struct ConfigPlugin {
+    GModule *module;
+    char *fname;
+    char *name;
+    char *plugin_name;
+
+    PluginStartupFunc start;
+    PluginShutdownFunc stop;
+    PluginInterfaceVersionFunc interface;
+    PluginNameFunc getname;
+    PluginPluginNameFunc getpname;
+    PluginIconFunc icon;
+    PluginToplevelWidgetFunc toplevel;
+    PluginEditedFunc edited;
+    PluginLoadFunc load;
+    PluginSaveFunc save;
+} ConfigPlugin;
+
+GSList *plugins_list = NULL;
+
+static gpointer load_sym(GModule *module, char *name, char *symbol,
+                        gboolean allow_fail)
+{
+    gpointer var;
+    if (!g_module_symbol(module, symbol, &var)) {
+        if (!allow_fail)
+           g_warning("Failed to load symbol '%s' from plugin '%s'",
+                     symbol, name);
+        var = NULL;
+    }
+    return var;
+}
+
+static void add_plugin(ConfigPlugin *p)
+{
+    GtkTreeIter it;
+
+    gtk_list_store_append(obconf_sections_store, &it);
+    gtk_list_store_set(obconf_sections_store, &it, 0, p->name, -1);
+    gtk_notebook_append_page(obconf_options, p->toplevel(), NULL);
+}
+
+void load_dir(char *path)
+{
+    char *fpath;
+    DIR *dir;
+    struct dirent *dirp;
+    ConfigPlugin *p;
+    GModule *mod;
+    GSList *it;
+    char *suffix;
+
+    suffix = g_strconcat("-config.", G_MODULE_SUFFIX, NULL);
+
+    if (!(dir = opendir(path)))
+        return;
+    while ((dirp = readdir(dir))) {
+        if (g_strrstr(dirp->d_name, suffix)) {
+            /* look for duplicates */
+            for (it = plugins_list; it; it = it->next)
+                if (!strcmp(((ConfigPlugin*)it->data)->fname, dirp->d_name))
+                    break;
+            if (!it) {
+                fpath = g_build_filename(path, dirp->d_name, NULL);
+        
+                if ((mod = g_module_open(fpath, 0))) {
+                    p = g_new(ConfigPlugin, 1);
+                    p->module = mod;
+                    p->fname = g_strdup(dirp->d_name);
+
+                    p->interface = (PluginInterfaceVersionFunc)
+                        load_sym(p->module, p->fname,
+                                 "plugin_interface_version",
+                                 FALSE);
+                    p->start = (PluginStartupFunc)
+                        load_sym(p->module, p->fname, "plugin_startup", FALSE);
+                    p->stop = (PluginShutdownFunc)
+                        load_sym(p->module, p->fname, "plugin_shutdown",FALSE);
+                    p->getname = (PluginNameFunc)
+                        load_sym(p->module, p->fname, "plugin_name", FALSE);
+                    p->getpname = (PluginNameFunc)
+                        load_sym(p->module, p->fname, "plugin_plugin_name",
+                                 FALSE);
+                    p->icon = (PluginIconFunc)
+                        load_sym(p->module, p->fname, "plugin_icon", FALSE);
+                    p->toplevel = (PluginToplevelWidgetFunc)
+                        load_sym(p->module, p->fname, "plugin_toplevel_widget",
+                                 FALSE);
+                    p->edited = (PluginEditedFunc)
+                        load_sym(p->module, p->fname, "plugin_edited", FALSE);
+                    p->load = (PluginLoadFunc)
+                        load_sym(p->module, p->fname, "plugin_load", FALSE);
+                    p->save = (PluginSaveFunc)
+                        load_sym(p->module, p->fname, "plugin_save", FALSE);
+
+                    if (!(p->start &&
+                          p->stop &&
+                          p->interface &&
+                          p->name &&
+                          p->icon &&
+                          p->toplevel &&
+                          p->edited &&
+                          p->load &&
+                          p->save)) {
+                        g_module_close(p->module);
+                        g_free(p->fname);
+                        g_free(p);
+                    } else {
+                        p->start();
+                        p->name = p->getname();
+                        p->plugin_name = p->getpname();
+                        plugins_list = g_slist_append(plugins_list, p);
+
+                        add_plugin(p); /* add to the gui */
+                    }
+                }
+                g_free(fpath);
+            }
+        }              
+    }
+
+    g_free(suffix);
+}
+
+void plugins_load()
+{
+    char *path;
+
+    path = g_build_filename(g_get_home_dir(), ".openbox", "plugins", NULL);
+    load_dir(path);
+    g_free(path);
+
+    load_dir(PLUGINDIR);
+}
+
+gboolean plugins_edited(ConfigPlugin *p)
+{
+    return p->edited();
+}
+
+void plugins_load_settings(ConfigPlugin *p, xmlDocPtr doc, xmlNodePtr root)
+{
+    p->load(doc, root);
+}
+
+void plugins_save_settings(ConfigPlugin *p, xmlDocPtr doc, xmlNodePtr root)
+{
+    p->save(doc, root);
+}
diff --git a/tools/obconf/plugins.h b/tools/obconf/plugins.h
new file mode 100644 (file)
index 0000000..485a8c2
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef __plugins_h
+#define __plugins_h
+
+#include <libxml/parser.h>
+
+typedef struct ConfigPlugin ConfigPlugin;
+
+extern GSList *plugins_list;
+
+void plugins_load();
+
+gboolean plugins_edited(ConfigPlugin *p);
+void plugins_load_settings(ConfigPlugin *p, xmlDocPtr doc, xmlNodePtr root);
+void plugins_save_settings(ConfigPlugin *p, xmlDocPtr doc, xmlNodePtr root);
+
+#endif
This page took 0.075648 seconds and 4 git commands to generate.