]> Dogcows Code - chaz/openbox/blobdiff - plugins/placement/history.c
ECKS EM ELL
[chaz/openbox] / plugins / placement / history.c
index ea3d60dfb5cf9a7b2d2d0b7d7b438390946dd543..9d932b9edfbe7e0ca292738f298f91ae0d6782ce 100644 (file)
@@ -3,41 +3,47 @@
 #include "kernel/frame.h"
 #include "kernel/client.h"
 #include "kernel/screen.h"
+#include "kernel/parse.h"
+#include "history.h"
 #include <glib.h>
 #include <string.h>
 #ifdef HAVE_STDLIB_H
 #  include <stdlib.h>
 #endif
 
+#define PLACED        (1 << 0)
+
+#define HAVE_POSITION (1 << 1)
+#define HAVE_SIZE     (1 << 2)
+#define HAVE_DESKTOP  (1 << 3)
+
 struct HistoryItem {
     char *name;
     char *class;
     char *role;
-    int x;
-    int y;
-    gboolean placed;
+
+    int flags;
+
+    int x, y;
+    int w, h;
+    guint desk;
 };
 
-static GSList *history = NULL;
+static GSList *history_list = NULL;
 static char *history_path = NULL;
 
-static struct HistoryItem *find_history(Client *c)
+static struct HistoryItem *history_find(const char *name, const char *class,
+                                 const char *role)
 {
     GSList *it;
     struct HistoryItem *hi = NULL;
 
     /* find the client */
-    for (it = history; it != NULL; it = it->next) {
+    for (it = history_list; it != NULL; it = it->next) {
         hi = it->data;
-        g_assert(hi->name != NULL);
-        g_assert(hi->class != NULL);
-        g_assert(hi->role != NULL);
-        g_assert(c->name != NULL);
-        g_assert(c->class != NULL);
-        g_assert(c->role != NULL);
-        if (!strcmp(hi->name, c->name) &&
-            !strcmp(hi->class, c->class) &&
-            !strcmp(hi->role, c->role))
+        if (!g_utf8_collate(hi->name, name) &&
+            !g_utf8_collate(hi->class, class) &&
+            !g_utf8_collate(hi->role, role))
             return hi;
     }
     return NULL;
@@ -46,57 +52,65 @@ static struct HistoryItem *find_history(Client *c)
 gboolean place_history(Client *c)
 {
     struct HistoryItem *hi;
-    int x, y;
+    int x, y, w, h;
 
-    hi = find_history(c);
+    hi = history_find(c->name, c->class, c->role);
 
-    if (hi != NULL && !hi->placed) {
-        hi->placed = TRUE;
+    if (hi && !(hi->flags & PLACED)) {
+        hi->flags |= PLACED;
         if (ob_state != State_Starting) {
-            x = hi->x;
-            y = hi->y;
-
-            frame_frame_gravity(c->frame, &x, &y); /* get where the client
-                                                      should be */
-            client_configure(c, Corner_TopLeft, x, y,
-                             c->area.width, c->area.height,
-                             TRUE, TRUE);
+            if (hi->flags & HAVE_POSITION ||
+                hi->flags & HAVE_SIZE) {
+                if (hi->flags & HAVE_POSITION) {
+                    x = hi->x;
+                    y = hi->y;
+                    /* get where the client should be */
+                    frame_frame_gravity(c->frame, &x, &y);
+                } else {
+                    x = c->area.x;
+                    y = c->area.y;
+                }
+                if (hi->flags & HAVE_SIZE) {
+                    w = hi->w * c->size_inc.width;
+                    h = hi->h * c->size_inc.height;
+                } else {
+                    w = c->area.width;
+                    h = c->area.height;
+                }
+                client_configure(c, Corner_TopLeft, x, y, w, h,
+                                 TRUE, TRUE);
+            }
+            if (hi->flags & HAVE_DESKTOP) {
+                client_set_desktop(c, hi->desk, FALSE);
+            }
         }
-        return TRUE;
+        return hi->flags & HAVE_POSITION;
     }
 
     return FALSE;
 }
 
-static void strip_tabs(char *s)
-{
-    while (*s != '\0') {
-        if (*s == '\t')
-            *s = ' ';
-        ++s;
-    }
-}
-
 static void set_history(Client *c)
 {
     struct HistoryItem *hi;
 
-    hi = find_history(c);
+    hi = history_find(c->name, c->class, c->role);
 
     if (hi == NULL) {
         hi = g_new(struct HistoryItem, 1);
-        history = g_slist_append(history, hi);
+        history_list = g_slist_append(history_list, hi);
         hi->name = g_strdup(c->name);
-        strip_tabs(hi->name);
         hi->class = g_strdup(c->class);
-        strip_tabs(hi->class);
         hi->role = g_strdup(c->role);
-        strip_tabs(hi->role);
+        hi->flags = HAVE_POSITION;
+    }
+
+    if (hi->flags & HAVE_POSITION) {
+        hi->x = c->frame->area.x;
+        hi->y = c->frame->area.y;
     }
 
-    hi->x = c->frame->area.x;
-    hi->y = c->frame->area.y;
-    hi->placed = FALSE;
+    hi->flags &= ~PLACED;
 }
 
 static void event(ObEvent *e, void *foo)
@@ -106,104 +120,140 @@ static void event(ObEvent *e, void *foo)
     set_history(e->data.c.client);
 }
 
+/*
+
+<entry name="name" class="class" role="role">
+  <x>0</x>
+  <y>0</y>
+  <width>300</width>
+  <height>200</height>
+  <desktop>1</desktop>
+</entry>
+
+*/
+
 static void save_history()
 {
-    GError *err = NULL;
-    GIOChannel *io;
-    GString *buf;
+    xmlDocPtr doc;
+    xmlNodePtr root, node;
+    char *s;
     GSList *it;
-    struct HistoryItem *hi;
-    gsize ret;
-
-    io = g_io_channel_new_file(history_path, "w", &err);
-    if (io != NULL) {
-        for (it = history; it != NULL; it = it->next) {
-            hi = it->data;
-            buf = g_string_sized_new(0);
-            buf=g_string_append(buf, hi->name);
-            g_string_append_c(buf, '\t');
-            buf=g_string_append(buf, hi->class);
-            g_string_append_c(buf, '\t');
-            buf=g_string_append(buf, hi->role);
-            g_string_append_c(buf, '\t');
-            g_string_append_printf(buf, "%d", hi->x);
-            buf=g_string_append_c(buf, '\t');
-            g_string_append_printf(buf, "%d", hi->y);
-            buf=g_string_append_c(buf, '\n');
-            if (g_io_channel_write_chars(io, buf->str, buf->len, &ret, &err) !=
-                G_IO_STATUS_NORMAL)
-                break;
-            g_string_free(buf, TRUE);
+
+    doc = xmlNewDoc(NULL);
+    root = xmlNewNode(NULL, (const xmlChar*) "openbox_history");
+    xmlDocSetRootElement(doc, root);
+
+    for (it = history_list; it; it = g_slist_next(it)) {
+        struct HistoryItem *hi = it->data;
+        g_message("adding %s", hi->name);
+        node = xmlNewChild(root, NULL, (const xmlChar*) "entry", NULL);
+        xmlNewProp(node, (const xmlChar*) "name", (const xmlChar*) hi->name);
+        xmlNewProp(node, (const xmlChar*) "class", (const xmlChar*) hi->class);
+        xmlNewProp(node, (const xmlChar*) "role", (const xmlChar*) hi->role);
+        if (hi->flags & HAVE_POSITION) {
+            s = g_strdup_printf("%d", hi->x);
+            xmlNewTextChild(node, NULL,
+                            (const xmlChar*) "x", (const xmlChar*) s);
+            g_free(s);
+            s = g_strdup_printf("%d", hi->y);
+            xmlNewTextChild(node, NULL,
+                            (const xmlChar*) "y", (const xmlChar*) s);
+            g_free(s);
+        }
+        if (hi->flags & HAVE_SIZE) {
+            s = g_strdup_printf("%d", hi->w);
+            xmlNewTextChild(node, NULL,
+                            (const xmlChar*) "width", (const xmlChar*) s);
+            g_free(s);
+            s = g_strdup_printf("%d", hi->h);
+            xmlNewTextChild(node, NULL,
+                            (const xmlChar*) "height", (const xmlChar*) s);
+            g_free(s);
+        }
+        if (hi->flags & HAVE_DESKTOP) {
+            s = g_strdup_printf("%d", hi->desk < 0 ? hi->desk : hi->desk + 1);
+            xmlNewTextChild(node, NULL,
+                            (const xmlChar*) "desktop", (const xmlChar*) s);
+            g_free(s);
         }
-        g_io_channel_unref(io);
     }
+
+    xmlIndentTreeOutput = 1;
+    xmlSaveFormatFile(history_path, doc, 1);
+
+    xmlFree(doc);
 }
 
 static void load_history()
 {
-    GError *err = NULL;
-    GIOChannel *io;
-    char *buf = NULL;
-    char *b, *c;
-    struct HistoryItem *hi = NULL;
-
-    io = g_io_channel_new_file(history_path, "r", &err);
-    if (io != NULL) {
-        while (g_io_channel_read_line(io, &buf, NULL, NULL, &err) ==
-               G_IO_STATUS_NORMAL) {
-            hi = g_new0(struct HistoryItem, 1);
-
-            b = buf;
-            if ((c = strchr(b, '\t')) == NULL) break;
-            *c = '\0';
-            hi->name = g_strdup(b);
-
-            b = c + 1;
-            if ((c = strchr(b, '\t')) == NULL) break;
-            *c = '\0';
-            hi->class = g_strdup(b);
-
-            b = c + 1;
-            if ((c = strchr(b, '\t')) == NULL) break;
-            *c = '\0';
-            hi->role = g_strdup(b);
-
-            b = c + 1;
-            if ((c = strchr(b, '\t')) == NULL) break;
-            *c = '\0';
-            hi->x = atoi(b);
-
-            b = c + 1;
-            if ((c = strchr(b, '\n')) == NULL) break;
-            *c = '\0';
-            hi->y = atoi(b);
-
-            hi->placed = FALSE;
-
-            g_free(buf);
-            buf = NULL;
+    xmlDocPtr doc;
+    xmlNodePtr node, n;
+    char *name;
+    char *class;
+    char *role;
+    struct HistoryItem *hi;
 
-            history = g_slist_append(history, hi);
-            hi = NULL;
-        }
-        g_io_channel_unref(io);
+    if (!(doc = xmlParseFile(history_path)))
+        return;
+    if (!(node = xmlDocGetRootElement(doc))) {
+        xmlFreeDoc(doc);
+        doc = NULL;
+        return;
+    }
+    if (xmlStrcasecmp(node->name, (const xmlChar*)"openbox_history")) {
+        xmlFreeDoc(doc);
+        doc = NULL;
+        return;
     }
-        
-    g_free(buf);
 
-    if (hi != NULL) {
-        g_free(hi->name);
-        g_free(hi->class);
-        g_free(hi->role);
+    node = parse_find_node("entry", node->xmlChildrenNode);
+    while (node) {
+        name = class = role = NULL;
+        if (parse_attr_string("name", node, &name) &&
+            parse_attr_string("class", node, &class) &&
+            parse_attr_string("role", node, &role)) {
+
+            hi = history_find(name, class, role);
+            if (!hi) {
+                hi = g_new(struct HistoryItem, 1);
+                hi->name = g_strdup(name);
+                hi->class = g_strdup(class);
+                hi->role = g_strdup(role);
+                hi->flags = 0;
+            }
+            if ((n = parse_find_node("x", node->xmlChildrenNode))) {
+                hi->x = parse_int(doc, n);
+                if ((n = parse_find_node("y", node->xmlChildrenNode))) {
+                    hi->y = parse_int(doc, n);
+                    hi->flags |= HAVE_POSITION;
+                }
+            }
+            if ((n = parse_find_node("width", node->xmlChildrenNode))) {
+                hi->w = parse_int(doc, n);
+                if ((n = parse_find_node("height", node->xmlChildrenNode))) {
+                    hi->h = parse_int(doc, n);
+                    hi->flags |= HAVE_SIZE;
+                }
+            }
+            if ((n = parse_find_node("desktop", node->xmlChildrenNode))) {
+                hi->desk = parse_int(doc, n);
+                if (hi->desk > 0) --hi->desk;
+                hi->flags |= HAVE_DESKTOP;
+            }
+
+            history_list = g_slist_append(history_list, hi);
+        }
+        g_free(name); g_free(class); g_free(role);
+        node = parse_find_node("entry", node->next);
     }
-    g_free(hi);
+    xmlFree(doc);
 }
 
 void history_startup()
 {
     char *path;
 
-    history = NULL;
+    history_list = NULL;
 
     path = g_build_filename(g_get_home_dir(), ".openbox", "history", NULL);
     history_path = g_strdup_printf("%s.%d", path, ob_screen);
@@ -219,9 +269,14 @@ void history_shutdown()
     GSList *it;
 
     save_history(); /* save to the historydb file */
-    for (it = history; it != NULL; it = it->next)
-        g_free(it->data);
-    g_slist_free(history);
+    for (it = history_list; it != NULL; it = it->next) {
+        struct HistoryItem *hi = it->data;
+        g_free(hi->name);
+        g_free(hi->class);
+        g_free(hi->role);
+        g_free(hi);
+    }
+    g_slist_free(history_list);
 
     dispatch_register(0, (EventHandler)event, NULL);
 
This page took 0.031871 seconds and 4 git commands to generate.