split handlers.c into a bunch of files
authorDana Jansens <danakj@orodu.net>
Thu, 31 May 2007 05:58:07 +0000 (05:58 +0000)
committerDana Jansens <danakj@orodu.net>
Thu, 31 May 2007 05:58:07 +0000 (05:58 +0000)
20 files changed:
Makefile.am
src/about.c [new file with mode: 0644]
src/appearance.c [new file with mode: 0644]
src/appearance.h [new file with mode: 0644]
src/archive.c [new file with mode: 0644]
src/archive.h [new file with mode: 0644]
src/behavior.c [new file with mode: 0644]
src/behavior.h [new file with mode: 0644]
src/desktops.c [new file with mode: 0644]
src/desktops.h [new file with mode: 0644]
src/dock.c [new file with mode: 0644]
src/dock.h [new file with mode: 0644]
src/handlers.c [deleted file]
src/handlers.h [deleted file]
src/main.c
src/main.h
src/preview_update.c [new file with mode: 0644]
src/preview_update.h [new file with mode: 0644]
src/theme.c
src/theme.h

index 420aaec42a8db571129ad55ff5a6ae16f0dd8f28..f66313dc9244b5d79e8e4fd0cb5f22b822c95774 100644 (file)
@@ -38,12 +38,23 @@ src_obconf_LDADD = \
        $(LIBTAR_LIBS)
 src_obconf_SOURCES = \
        src/gettext.h \
+       src/about.c \
+       src/archive.c \
+       src/archive.h \
+       src/behavior.c \
+       src/behavior.h \
+       src/desktops.c \
+       src/desktops.h \
+       src/dock.h \
+       src/dock.c \
        src/main.c \
        src/main.h \
-       src/handlers.c \
-       src/handlers.h \
+       src/appearance.c \
+       src/appearance.h \
        src/preview.c \
        src/preview.h \
+       src/preview_update.c \
+       src/preview_update.h \
        src/theme.c \
        src/theme.h \
        src/tree.c \
diff --git a/src/about.c b/src/about.c
new file mode 100644 (file)
index 0000000..c56eb26
--- /dev/null
@@ -0,0 +1,16 @@
+#include "main.h"
+
+void on_about_clicked()
+{
+    gtk_widget_show(get_widget("about_window"));
+}
+
+void on_about_close_clicked()
+{
+    gtk_widget_hide(get_widget("about_window"));
+}
+
+void on_about_window_delete_event()
+{
+    gtk_widget_hide(get_widget("about_window"));
+}
diff --git a/src/appearance.c b/src/appearance.c
new file mode 100644 (file)
index 0000000..d67b7d6
--- /dev/null
@@ -0,0 +1,296 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+   appearance.c for ObConf, the configuration tool for Openbox
+   Copyright (c) 2003-2007   Dana Jansens
+   Copyright (c) 2003        Tim Riley
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   See the COPYING file for a copy of the GNU General Public License.
+*/
+
+#include "main.h"
+#include "tree.h"
+#include "preview_update.h"
+
+static gboolean mapping = FALSE;
+
+static RrFont *appr_setup_font(GtkWidget *w, const gchar *place);
+static RrFont *appr_set_font(GtkFontButton *w, const gchar *place);
+
+void appr_setup_window_border(GtkWidget *w)
+{
+    gboolean border;
+
+    mapping = TRUE;
+
+    border = tree_get_bool("theme/keepBorder", TRUE);
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), border);
+
+    mapping = FALSE;
+}
+
+void appr_setup_title_layout(GtkWidget *w)
+{
+    gchar *layout;
+
+    mapping = TRUE;
+
+    layout = tree_get_string("theme/titleLayout", "NLIMC");
+    gtk_entry_set_text(GTK_ENTRY(w), layout);
+    preview_update_set_title_layout(layout);
+    g_free(layout);
+
+    mapping = FALSE;
+}
+
+void appr_setup_font_active(GtkWidget *w)
+{
+    preview_update_set_active_font(appr_setup_font(w, "ActiveWindow"));
+}
+
+void appr_setup_font_inactive(GtkWidget *w)
+{
+    preview_update_set_inactive_font(appr_setup_font(w, "InactiveWindow"));
+}
+
+void appr_setup_font_menu_header(GtkWidget *w)
+{
+    preview_update_set_menu_header_font(appr_setup_font(w, "MenuHeader"));
+}
+
+void appr_setup_font_menu_item(GtkWidget *w)
+{
+    preview_update_set_menu_item_font(appr_setup_font(w, "MenuItem"));
+}
+
+void appr_setup_font_display(GtkWidget *w)
+{
+    preview_update_set_osd_font(appr_setup_font(w, "OnScreenDisplay"));
+}
+
+void on_window_border_toggled(GtkToggleButton *w, gpointer data)
+{
+    gboolean b;
+
+    if (mapping) return;
+
+    b = gtk_toggle_button_get_active(w);
+    tree_set_bool("theme/keepBorder", b);
+}
+
+void on_title_layout_changed(GtkEntry *w, gpointer data)
+{
+    gchar *layout;
+    gchar *it, *it2;
+    gboolean n, d, s, l, i, m, c;
+
+    if (mapping) return;
+
+    layout = g_strdup(gtk_entry_get_text(w));
+
+    n = d = s = l = i = m = c = FALSE;
+
+    for (it = layout; *it; ++it) {
+        gboolean *b;
+
+        switch (*it) {
+        case 'N':
+        case 'n':
+            b = &n;
+            break;
+        case 'd':
+        case 'D':
+            b = &d;
+            break;
+        case 's':
+        case 'S':
+            b = &s;
+            break;
+        case 'l':
+        case 'L':
+            b = &l;
+            break;
+        case 'i':
+        case 'I':
+            b = &i;
+            break;
+        case 'm':
+        case 'M':
+            b = &m;
+            break;
+        case 'c':
+        case 'C':
+            b = &c;
+            break;
+        default:
+            b = NULL;
+            break;
+        }
+
+        if (!b || *b) {
+            /* drop the letter */
+            for (it2 = it; *it2; ++it2)
+                *it2 = *(it2+1);
+        } else {
+            *it = toupper(*it);
+            *b = TRUE;
+        }
+    }
+
+    gtk_entry_set_text(w, layout);
+    tree_set_string("theme/titleLayout", layout);
+    preview_update_set_title_layout(layout);
+
+    g_free(layout);
+}
+
+void on_font_active_font_set(GtkFontButton *w, gpointer data)
+{
+    preview_update_set_active_font(appr_set_font(w, "ActiveWindow"));
+}
+
+void on_font_inactive_font_set(GtkFontButton *w, gpointer data)
+{
+    preview_update_set_inactive_font(appr_set_font(w, "InactiveWindow"));
+}
+
+void on_font_menu_header_font_set(GtkFontButton *w, gpointer data)
+{
+    preview_update_set_menu_header_font(appr_set_font(w, "MenuHeader"));
+}
+
+void on_font_menu_item_font_set(GtkFontButton *w, gpointer data)
+{
+    preview_update_set_menu_item_font(appr_set_font(w, "MenuItem"));
+}
+
+void on_font_display_font_set(GtkFontButton *w, gpointer data)
+{
+    preview_update_set_osd_font(appr_set_font(w, "OnScreenDisplay"));
+}
+
+static RrFont *appr_setup_font(GtkWidget *w, const gchar *place)
+{
+    RrFont *font;
+    gchar *fontstring, *node;
+    gchar *name, **names;
+    gchar *size;
+    gchar *weight;
+    gchar *slant;
+
+    RrFontWeight rr_weight = RR_FONTWEIGHT_NORMAL;
+    RrFontSlant rr_slant = RR_FONTSLANT_NORMAL;
+
+    mapping = TRUE;
+
+    node = g_strdup_printf("theme/font:place=%s/name", place);
+    name = tree_get_string(node, "Sans");
+    g_free(node);
+
+    node = g_strdup_printf("theme/font:place=%s/size", place);
+    size = tree_get_string(node, "8");
+    g_free(node);
+
+    node = g_strdup_printf("theme/font:place=%s/weight", place);
+    weight = tree_get_string(node, "");
+    g_free(node);
+
+    node = g_strdup_printf("theme/font:place=%s/slant", place);
+    slant = tree_get_string(node, "");
+    g_free(node);
+
+    /* get only the first font in the string */
+    names = g_strsplit(name, ",", 0);
+    g_free(name);
+    name = g_strdup(names[0]);
+    g_strfreev(names);
+
+    /* don't use "normal" in the gtk string */
+    if (!g_ascii_strcasecmp(weight, "normal")) {
+        g_free(weight); weight = g_strdup("");
+    }
+    if (!g_ascii_strcasecmp(slant, "normal")) {
+        g_free(slant); slant = g_strdup("");
+    }
+
+    fontstring = g_strdup_printf("%s %s %s %s", name, weight, slant, size);
+    gtk_font_button_set_font_name(GTK_FONT_BUTTON(w), fontstring);
+
+    if (!g_ascii_strcasecmp(weight, "Bold")) rr_weight = RR_FONTWEIGHT_BOLD;
+    if (!g_ascii_strcasecmp(slant, "Italic")) rr_slant = RR_FONTSLANT_ITALIC;
+    if (!g_ascii_strcasecmp(slant, "Oblique")) rr_slant = RR_FONTSLANT_OBLIQUE;
+
+    font = RrFontOpen(rrinst, name, atoi(size), rr_weight, rr_slant);
+    g_free(fontstring);
+    g_free(slant);
+    g_free(weight);
+    g_free(size);
+    g_free(name);
+
+    mapping = FALSE;
+
+    return font;
+}
+
+static RrFont *appr_set_font(GtkFontButton *w, const gchar *place)
+{
+    gchar *c;
+    gchar *font, *node;
+    const gchar *size = NULL;
+    const gchar *bold = NULL;
+    const gchar *italic = NULL;
+
+    RrFontWeight weight = RR_FONTWEIGHT_NORMAL;
+    RrFontSlant slant = RR_FONTSLANT_NORMAL;
+
+    if (mapping) return;
+
+    font = g_strdup(gtk_font_button_get_font_name(w));
+    while ((c = strrchr(font, ' '))) {
+        if (!bold && !italic && !size && atoi(c+1))
+            size = c+1;
+        else if (!bold && !italic && !g_ascii_strcasecmp(c+1, "italic"))
+            italic = c+1;
+        else if (!bold && !g_ascii_strcasecmp(c+1, "bold"))
+            bold = c+1;
+        else
+            break;
+        *c = '\0';
+    }
+    if (!bold) bold = "Normal";
+    if (!italic) italic = "Normal";
+
+    node = g_strdup_printf("theme/font:place=%s/name", place);
+    tree_set_string(node, font);
+    g_free(node);
+
+    node = g_strdup_printf("theme/font:place=%s/size", place);
+    tree_set_string(node, size);
+    g_free(node);
+
+    node = g_strdup_printf("theme/font:place=%s/weight", place);
+    tree_set_string(node, bold);
+    g_free(node);
+
+    node = g_strdup_printf("theme/font:place=%s/slant", place);
+    tree_set_string(node, italic);
+    g_free(node);
+
+    if (!g_ascii_strcasecmp(bold, "Bold")) weight = RR_FONTWEIGHT_BOLD;
+    if (!g_ascii_strcasecmp(italic, "Italic")) slant = RR_FONTSLANT_ITALIC;
+    if (!g_ascii_strcasecmp(italic, "Oblique")) slant = RR_FONTSLANT_OBLIQUE;
+
+    return RrFontOpen(rrinst, font, atoi(size), weight, slant);
+
+    g_free(font);
+
+}
diff --git a/src/appearance.h b/src/appearance.h
new file mode 100644 (file)
index 0000000..16e475c
--- /dev/null
@@ -0,0 +1,32 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+   appearance.h for ObConf, the configuration tool for Openbox
+   Copyright (c) 2003-2007   Dana Jansens
+   Copyright (c) 2003        Tim Riley
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   See the COPYING file for a copy of the GNU General Public License.
+*/
+
+#ifndef obconf__appearance_h
+#define obconf__appearance_h
+
+void appr_setup_window_border    (GtkWidget *w);
+void appr_setup_title_layout     (GtkWidget *w);
+
+void appr_setup_font_active      (GtkWidget *w);
+void appr_setup_font_inactive    (GtkWidget *w);
+void appr_setup_font_menu_header (GtkWidget *w);
+void appr_setup_font_menu_item   (GtkWidget *w);
+void appr_setup_font_display     (GtkWidget *w);
+
+#endif
diff --git a/src/archive.c b/src/archive.c
new file mode 100644 (file)
index 0000000..04ea3e5
--- /dev/null
@@ -0,0 +1,228 @@
+#include "theme.h"
+#include "main.h"
+#include "gettext.h"
+
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#define gtk_msg(type, args...) \
+{                                                                        \
+    GtkWidget *msgw;                                                     \
+    msgw = gtk_message_dialog_new(GTK_WINDOW(mainwin),                   \
+                                  GTK_DIALOG_DESTROY_WITH_PARENT |       \
+                                  GTK_DIALOG_MODAL,                      \
+                                  type,                                  \
+                                  GTK_BUTTONS_OK,                        \
+                                  args);                                 \
+    gtk_dialog_run(GTK_DIALOG(msgw));                                    \
+    gtk_widget_destroy(msgw);                                            \
+}
+
+static gchar *get_theme_dir();
+static gboolean change_dir(const gchar *dir);
+static gchar* name_from_file(const gchar *path);
+static gchar* name_from_dir(const gchar *dir);
+static gboolean install_theme_to(const gchar *name, const gchar *file,
+                                 const gchar *to);
+static gboolean create_theme_archive(const gchar *dir, const gchar *name,
+                                     const gchar *to);
+
+gchar* archive_install(const gchar *path)
+{
+    gchar *dest;
+    gchar *name;
+
+    if (!(dest = get_theme_dir()))
+        return NULL;
+
+    if (!(name = name_from_file(path)))
+        return NULL;
+
+    if (install_theme_to(name, path, dest)) {
+        gtk_msg(GTK_MESSAGE_INFO, _("\"%s\" was installed to %s"), name, dest);
+    } else {
+        g_free(name);
+        name = NULL;
+    }
+
+    g_free(dest);
+
+    return name;
+}
+
+void archive_create(const gchar *path)
+{
+    gchar *name;
+    gchar *dest;
+
+    if (!(name = name_from_dir(path)))
+        return;
+
+    {
+        gchar *file;
+        file = g_strdup_printf("%s.obt", name);
+        dest = g_build_path(G_DIR_SEPARATOR_S,
+                            g_get_current_dir(), file, NULL);
+        g_free(file);
+    }
+
+    if (create_theme_archive(path, name, dest))
+        gtk_msg(GTK_MESSAGE_INFO, _("\"%s\" was successfully created"),
+                dest);
+
+    g_free(dest);
+    g_free(name);
+}
+
+static gboolean create_theme_archive(const gchar *dir, const gchar *name,
+                                     const gchar *to)
+{
+    gchar *glob;
+    gchar **argv;
+    gchar *errtxt = NULL;
+    gchar *parentdir;
+    gint exitcode;
+    GError *e = NULL;
+
+    glob = g_strdup_printf("%s/openbox-3/", name);
+
+    parentdir = g_build_path(G_DIR_SEPARATOR_S, dir, "..", NULL);
+
+    argv = g_new(gchar*, 7);
+    argv[0] = g_strdup("tar");
+    argv[1] = g_strdup("-c");
+    argv[2] = g_strdup("-z");
+    argv[3] = g_strdup("-f");
+    argv[4] = g_strdup(to);
+    argv[5] = g_strdup(glob);
+    argv[6] = NULL;
+    if (g_spawn_sync(parentdir, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL,
+                     NULL, &errtxt, &exitcode, &e))
+    {
+        if (exitcode != EXIT_SUCCESS)
+            gtk_msg(GTK_MESSAGE_ERROR,
+                    _("Unable to create the theme archive \"%s\".\nThe following errors were reported:\n%s"),
+                    to, errtxt);
+
+    }
+    else
+        gtk_msg(GTK_MESSAGE_ERROR, _("Unable to run the \"tar\" command: %s"),
+                e->message);
+
+    g_strfreev(argv);
+    if (e) g_error_free(e);
+    g_free(errtxt);
+    g_free(parentdir);
+    g_free(glob);
+    return exitcode == EXIT_SUCCESS;
+}
+
+static gchar *get_theme_dir()
+{
+    gchar *dir;
+    gint r;
+
+    dir = g_build_path(G_DIR_SEPARATOR_S, g_get_home_dir(), ".themes", NULL);
+    r = mkdir(dir, 0777);
+    if (r == -1 && errno != EEXIST) {
+        gtk_msg(GTK_MESSAGE_ERROR,
+                _("Unable to create directory \"%s\": %s"),
+                dir, strerror(errno));
+        g_free(dir);
+        dir = NULL;
+    }
+
+    return dir;
+}
+
+static gchar* name_from_dir(const gchar *dir)
+{
+    gchar *rc;
+    struct stat st;
+    gboolean r;
+
+    rc = g_build_path(G_DIR_SEPARATOR_S, dir, "openbox-3", "themerc", NULL);
+
+    r = (stat(rc, &st) == 0 && S_ISREG(st.st_mode));
+    g_free(rc);
+
+    if (!r) {
+        gtk_msg(GTK_MESSAGE_ERROR,
+                _("\"%s\" does not appear to be a valid Openbox theme directory"),
+                dir);
+        return NULL;
+    }
+    return g_path_get_basename(dir);
+}
+
+static gchar* name_from_file(const gchar *path)
+{
+    /* decipher the theme name from the file name */
+    gchar *fname = g_path_get_basename(path);
+    gint len = strlen(fname);
+    gchar *name = NULL;
+
+    if (len > 4 &&
+        (fname[len-4] == '.' && fname[len-3] == 'o' &&
+         fname[len-2] == 'b' && fname[len-1] == 't'))
+    {
+        fname[len-4] = '\0';
+        name = g_strdup(fname);
+        fname[len-4] = '.';
+    }
+
+    if (name == NULL)
+        gtk_msg(GTK_MESSAGE_ERROR,
+                _("Unable to determine the theme's name from \"%s\".  File name should be ThemeName.obt."), fname);
+
+    return name;
+}
+
+static gboolean change_dir(const gchar *dir)
+{
+    if (chdir(dir) == -1) {
+        gtk_msg(GTK_MESSAGE_ERROR, _("Unable to move to directory \"%s\": %s"),
+                dir, strerror(errno));
+        return FALSE;
+    }
+    return TRUE;
+}
+
+static gboolean install_theme_to(const gchar *name, const gchar *file,
+                                 const gchar *to)
+{
+    gchar *glob;
+    gchar **argv;
+    gchar *errtxt = NULL;
+    gint exitcode;
+    GError *e = NULL;
+
+    glob = g_strdup_printf("%s/openbox-3/", name);
+
+    argv = g_new(gchar*, 7);
+    argv[0] = g_strdup("tar");
+    argv[1] = g_strdup("-x");
+    argv[2] = g_strdup("-z");
+    argv[3] = g_strdup("-f");
+    argv[4] = g_strdup(file);
+    argv[5] = g_strdup(glob);
+    argv[6] = NULL;
+    if (!g_spawn_sync(to, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL,
+                      NULL, &errtxt, &exitcode, &e))
+        gtk_msg(GTK_MESSAGE_ERROR, _("Unable to run the \"tar\" command: %s"),
+                e->message);
+    g_strfreev(argv);
+    if (e) g_error_free(e);
+
+    if (exitcode != EXIT_SUCCESS)
+        gtk_msg(GTK_MESSAGE_ERROR,
+                _("Unable to extract the file \"%s\".\nPlease ensure that \"%s\" is writable and that the file is a valid Openbox theme archive.\nThe following errors were reported:\n%s"),
+                file, to, errtxt);
+
+    g_free(errtxt);
+    g_free(glob);
+    return exitcode == EXIT_SUCCESS;
+}
diff --git a/src/archive.h b/src/archive.h
new file mode 100644 (file)
index 0000000..3fcfe65
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef __install_h
+#define __install_h
+
+#include <glib.h>
+
+gchar* archive_install (const gchar *path);
+void   archive_create  (const gchar *path);
+
+#endif
diff --git a/src/behavior.c b/src/behavior.c
new file mode 100644 (file)
index 0000000..d87e977
--- /dev/null
@@ -0,0 +1,203 @@
+#include "main.h"
+#include "tree.h"
+
+static gboolean mapping = FALSE;
+
+void behavior_setup_tab()
+{
+    GtkWidget *winresist, *edgeresist;
+    GtkWidget *winresist_l, *edgeresist_l;
+    GtkSizeGroup *group1, *group2;
+
+    winresist  = get_widget("resist_window");
+    edgeresist = get_widget("resist_edge");
+    group1     = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
+
+    gtk_size_group_add_widget(group1, winresist);
+    gtk_size_group_add_widget(group1, edgeresist);
+
+    winresist_l  = get_widget("resist_window_label");
+    edgeresist_l = get_widget("resist_edge_label");
+    group2       = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
+
+    gtk_size_group_add_widget(group2, winresist_l);
+    gtk_size_group_add_widget(group2, edgeresist_l);
+}
+
+void behavior_setup_focus_mouse(GtkWidget *w)
+{
+    gboolean b;
+
+    mapping = TRUE;
+
+    b = tree_get_bool("focus/followMouse", FALSE);
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), b);
+
+    {
+        GtkWidget *delay   = get_widget("focus_delay");
+        GtkWidget *delay_l = get_widget("focus_delay_label");
+        GtkWidget *delay_u = get_widget("focus_delay_label_units");
+        GtkWidget *raise   = get_widget("focus_raise");
+        GtkWidget *last    = get_widget("focus_last");
+
+        gtk_widget_set_sensitive(delay, b);
+        gtk_widget_set_sensitive(delay_l, b);
+        gtk_widget_set_sensitive(delay_u, b);
+        gtk_widget_set_sensitive(raise, b);
+        gtk_widget_set_sensitive(last, b);
+    }
+
+    mapping = FALSE;
+}
+
+void behavior_setup_focus_delay(GtkWidget *w)
+{
+    mapping = TRUE;
+    gtk_spin_button_set_value(GTK_SPIN_BUTTON(w),
+                              tree_get_int("focus/focusDelay", 0));
+    mapping = FALSE;
+}
+
+void behavior_setup_focus_raise(GtkWidget *w)
+{
+    mapping = TRUE;
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w),
+                                 tree_get_bool("focus/raiseOnFocus", FALSE));
+    mapping = FALSE;
+}
+
+void behavior_setup_focus_last(GtkWidget *w)
+{
+    mapping = TRUE;
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w),
+                                 tree_get_bool("focus/focusLast", FALSE));
+    mapping = FALSE;
+}
+
+void behavior_setup_focus_new(GtkWidget *w)
+{
+    mapping = TRUE;
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w),
+                                 tree_get_bool("focus/focusNew", TRUE));
+    mapping = FALSE;
+}
+
+void behavior_setup_place_mouse(GtkWidget *w)
+{
+    gchar *s;
+
+    mapping = TRUE;
+    s = tree_get_string("placement/policy", "Smart");
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w),
+                                 !g_ascii_strcasecmp(s, "UnderMouse"));
+    g_free(s);
+    mapping = FALSE;
+}
+
+void behavior_setup_resist_window(GtkWidget *w)
+{
+    mapping = TRUE;
+    gtk_spin_button_set_value(GTK_SPIN_BUTTON(w),
+                              tree_get_int("resistance/strength", 10));
+    mapping = FALSE;
+}
+
+void behavior_setup_resist_edge(GtkWidget *w)
+{
+    mapping = TRUE;
+    gtk_spin_button_set_value(GTK_SPIN_BUTTON(w),
+                              tree_get_int("resistance/screen_edge_strength",
+                                           20));
+    mapping = FALSE;
+}
+
+void behavior_setup_resize_contents(GtkWidget *w)
+{
+    mapping = TRUE;
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w),
+                                 tree_get_bool("resize/drawContents", TRUE));
+    mapping = FALSE;
+}
+
+void on_focus_mouse_toggled(GtkToggleButton *w, gpointer data)
+{
+    gboolean b;
+
+    if (mapping) return;
+
+    b = gtk_toggle_button_get_active(w);
+    tree_set_bool("focus/followMouse", b);
+
+    {
+        GtkWidget *delay   = get_widget("focus_delay");
+        GtkWidget *delay_l = get_widget("focus_delay_label");
+        GtkWidget *delay_u = get_widget("focus_delay_label_units");
+        GtkWidget *raise   = get_widget("focus_raise");
+        GtkWidget *last    = get_widget("focus_last");
+        gtk_widget_set_sensitive(delay, b);
+        gtk_widget_set_sensitive(delay_l, b);
+        gtk_widget_set_sensitive(delay_u, b);
+        gtk_widget_set_sensitive(raise, b);
+        gtk_widget_set_sensitive(last, b);
+    }
+}
+
+void on_focus_delay_value_changed(GtkSpinButton *w, gpointer data)
+{
+    if (mapping) return;
+
+    tree_set_int("focus/focusDelay",
+                 gtk_spin_button_get_value_as_int(w));
+}
+
+void on_focus_raise_toggled(GtkToggleButton *w, gpointer data)
+{
+    if (mapping) return;
+
+    tree_set_bool("focus/raiseOnFocus", gtk_toggle_button_get_active(w));
+}
+
+void on_focus_last_toggled(GtkToggleButton *w, gpointer data)
+{
+    if (mapping) return;
+
+    tree_set_bool("focus/focusLast", gtk_toggle_button_get_active(w));
+}
+
+void on_focus_new_toggled(GtkToggleButton *w, gpointer data)
+{
+    if (mapping) return;
+
+    tree_set_bool("focus/focusNew", gtk_toggle_button_get_active(w));
+}
+
+void on_place_mouse_toggled(GtkToggleButton *w, gpointer data)
+{
+    if (mapping) return;
+
+    tree_set_string("placement/policy",
+                    (gtk_toggle_button_get_active(w) ?
+                     "UnderMouse" : "Smart"));
+}
+
+void on_resist_window_value_changed(GtkSpinButton *w, gpointer data)
+{
+    if (mapping) return;
+
+    tree_set_int("resistance/strength", gtk_spin_button_get_value_as_int(w));
+}
+
+void on_resist_edge_value_changed(GtkSpinButton *w, gpointer data)
+{
+    if (mapping) return;
+
+    tree_set_int("resistance/screen_edge_strength",
+                 gtk_spin_button_get_value_as_int(w));
+}
+
+void on_resize_contents_toggled(GtkToggleButton *w, gpointer data)
+{
+    if (mapping) return;
+
+    tree_set_bool("resize/drawContents", gtk_toggle_button_get_active(w));
+}
diff --git a/src/behavior.h b/src/behavior.h
new file mode 100644 (file)
index 0000000..65b1a5f
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef obconf__behavior_h
+#define obconf__behavior_h
+
+void behavior_setup_tab();
+
+#endif
diff --git a/src/desktops.c b/src/desktops.c
new file mode 100644 (file)
index 0000000..9686c56
--- /dev/null
@@ -0,0 +1,203 @@
+#include "main.h"
+#include "tree.h"
+#include "gettext.h"
+
+#include <gdk/gdkx.h>
+
+static gboolean mapping = FALSE;
+
+static GtkListStore *desktop_store;
+static int num_desktops;
+static GList *desktop_names;
+
+static void reset_desktop_names();
+static void desktops_set_names();
+static void desktops_set_number();
+static void on_desktop_names_cell_edited(GtkCellRendererText *cell,
+                                         const gchar *path_string,
+                                         const gchar *new_text,
+                                         gpointer data);
+
+void desktops_setup_num(GtkWidget *w)
+{
+    mapping = TRUE;
+
+    num_desktops = tree_get_int("desktops/number", 4);
+    gtk_spin_button_set_value(GTK_SPIN_BUTTON(w), num_desktops);
+
+    mapping = FALSE;
+}
+
+void desktops_setup_names(GtkWidget *w)
+{
+    GtkCellRenderer *render;
+    GtkTreeViewColumn *column;
+
+    mapping = TRUE;
+
+    desktop_store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_BOOLEAN);
+    gtk_tree_view_set_model(GTK_TREE_VIEW(w), GTK_TREE_MODEL(desktop_store));
+    g_object_unref (desktop_store);
+
+    gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(w)),
+                                GTK_SELECTION_SINGLE);
+
+    render = gtk_cell_renderer_text_new();
+    g_signal_connect(render, "edited",
+                     G_CALLBACK (on_desktop_names_cell_edited),
+                     NULL);
+
+    column = gtk_tree_view_column_new_with_attributes
+        ("Name", render, "text", 0, "editable", 1, NULL);
+    gtk_tree_view_append_column(GTK_TREE_VIEW(w), column);
+
+    reset_desktop_names();
+
+    mapping = FALSE;
+}
+
+void on_desktop_num_value_changed(GtkSpinButton *w, gpointer data)
+{
+    if (mapping) return;
+
+    num_desktops = gtk_spin_button_get_value(w);
+
+    desktops_set_number();
+
+    reset_desktop_names();
+}
+
+static void on_desktop_names_cell_edited(GtkCellRendererText *cell,
+                                         const gchar *path_string,
+                                         const gchar *new_text,
+                                         gpointer data)
+{
+    GtkTreePath *path;
+    GtkTreeIter it;
+    gchar *old_text;
+    GList *lit;
+    gint i;
+
+    if (mapping) return;
+
+    path = gtk_tree_path_new_from_string (path_string);
+    gtk_tree_model_get_iter(GTK_TREE_MODEL(desktop_store), &it, path);
+
+    gtk_tree_model_get(GTK_TREE_MODEL(desktop_store), &it, 0, &old_text, -1);
+    g_free(old_text);
+
+    i = gtk_tree_path_get_indices(path)[0];
+    lit = g_list_nth(desktop_names, i);
+
+    g_free(lit->data);
+    lit->data = g_strdup(new_text);
+    if (new_text[0]) /* not empty */
+        gtk_list_store_set(desktop_store, &it, 0, lit->data, -1);
+    else
+        gtk_list_store_set(desktop_store, &it, 0, _("(Unnamed desktop)"), -1);
+
+    desktops_set_names();
+}
+
+static void reset_desktop_names()
+{
+    GtkTreeIter it;
+    xmlNodePtr n;
+    gint i;
+    GList *lit;
+
+    gtk_list_store_clear(desktop_store);
+
+    for (lit = desktop_names; lit; lit = g_list_next(lit))
+        g_free(lit->data);
+    g_list_free(desktop_names);
+    desktop_names = NULL;
+
+    i = 0;
+    n = tree_get_node("desktops/names", NULL)->children;
+    while (n) {
+        gchar *name;
+
+        if (!xmlStrcmp(n->name, (const xmlChar*)"name")) {
+            name = parse_string(doc, n);
+
+            desktop_names = g_list_append(desktop_names, name);
+
+            gtk_list_store_append(desktop_store, &it);
+            gtk_list_store_set(desktop_store, &it,
+                               0, (name[0] ? name : _("(Unnamed desktop)")),
+                               1, TRUE,
+                               -1);
+            ++i;
+        }
+
+        n = n->next;
+    }
+
+    while (i < num_desktops) {
+        gchar *name = g_strdup("");
+
+        desktop_names = g_list_append(desktop_names, name);
+
+        gtk_list_store_append(desktop_store, &it);
+        gtk_list_store_set(desktop_store, &it,
+                           0, _("(Unnamed desktop)"),
+                           1, TRUE,
+                           -1);
+        ++i;
+    }
+}
+
+static void desktops_set_names()
+{
+    gchar **s;
+    GList *lit;
+    xmlNodePtr n, c;
+    gint num = 0, last = -1;
+
+    n = tree_get_node("desktops/names", NULL);
+    while ((c = n->children)) {
+        xmlUnlinkNode(c);
+        xmlFreeNode(c);
+    }
+
+    for (lit = desktop_names; lit; lit = g_list_next(lit)) {
+        if (((gchar*)lit->data)[0]) /* not empty */
+            last = num;
+        ++num;
+    }
+
+    num = 0;
+    for (lit = desktop_names; lit && num <= last; lit = g_list_next(lit)) {
+        xmlNewTextChild(n, NULL, "name", lit->data);
+        ++num;
+    }
+    tree_apply();
+
+    /* make openbox re-set the property */
+    XDeleteProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(),
+                    XInternAtom(GDK_DISPLAY(), "_NET_DESKTOP_NAMES", FALSE));
+}
+
+static void desktops_set_number()
+{
+    XEvent ce;
+
+    tree_set_int("desktops/number", num_desktops);
+
+    ce.xclient.type = ClientMessage;
+    ce.xclient.message_type = XInternAtom(GDK_DISPLAY(),
+                                          "_NET_NUMBER_OF_DESKTOPS",
+                                          FALSE);
+    ce.xclient.display = GDK_DISPLAY();
+    ce.xclient.window = GDK_ROOT_WINDOW();
+    ce.xclient.format = 32;
+    ce.xclient.data.l[0] = num_desktops;
+    ce.xclient.data.l[1] = 0;
+    ce.xclient.data.l[2] = 0;
+    ce.xclient.data.l[3] = 0;
+    ce.xclient.data.l[4] = 0;
+    XSendEvent(GDK_DISPLAY(), GDK_ROOT_WINDOW(), FALSE,
+               SubstructureNotifyMask | SubstructureRedirectMask,
+               &ce);
+}
diff --git a/src/desktops.h b/src/desktops.h
new file mode 100644 (file)
index 0000000..96acc0c
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef obconf__desktops_h
+#define obconf__desktops_h
+
+#include <gtk/gtk.h>
+
+void desktops_setup_num(GtkWidget *w);
+void desktops_setup_names(GtkWidget *w);
+
+#endif
diff --git a/src/dock.c b/src/dock.c
new file mode 100644 (file)
index 0000000..f5c4638
--- /dev/null
@@ -0,0 +1,426 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+   handlers.h for ObConf, the configuration tool for Openbox
+   Copyright (c) 2003-2007   Dana Jansens
+   Copyright (c) 2003        Tim Riley
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   See the COPYING file for a copy of the GNU General Public License.
+*/
+
+#include "main.h"
+#include "tree.h"
+
+static gboolean mapping = FALSE;
+
+void dock_setup_tab()
+{
+    GtkWidget *posi, *dir;
+    GtkWidget *posi_l, *dir_l;
+    GtkSizeGroup *group1, *group2;
+
+    posi   = get_widget("dock_position");
+    dir    = get_widget("dock_direction");
+    group1 = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
+
+    gtk_size_group_add_widget(group1, posi);
+    gtk_size_group_add_widget(group1, dir);
+
+    posi_l = get_widget("dock_position_label");
+    dir_l  = get_widget("dock_direction_label");
+    group2 = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
+
+    gtk_size_group_add_widget(group2, posi_l);
+    gtk_size_group_add_widget(group2, dir_l);
+}
+
+void dock_setup_position(GtkWidget *w)
+{
+    gchar *s;
+    gboolean f;
+
+    mapping = TRUE;
+
+    s = tree_get_string("dock/position", "TopLeft");
+    f = FALSE;
+
+    if (!strcasecmp(s, "Top"))
+        gtk_option_menu_set_history(GTK_OPTION_MENU(w), 1);
+    else if (!strcasecmp(s, "TopRight"))
+        gtk_option_menu_set_history(GTK_OPTION_MENU(w), 2);
+    else if (!strcasecmp(s, "Left"))
+        gtk_option_menu_set_history(GTK_OPTION_MENU(w), 3);
+    else if (!strcasecmp(s, "Right"))
+        gtk_option_menu_set_history(GTK_OPTION_MENU(w), 4);
+    else if (!strcasecmp(s, "BottomLeft"))
+        gtk_option_menu_set_history(GTK_OPTION_MENU(w), 5);
+    else if (!strcasecmp(s, "Bottom"))
+        gtk_option_menu_set_history(GTK_OPTION_MENU(w), 6);
+    else if (!strcasecmp(s, "BottomRight"))
+        gtk_option_menu_set_history(GTK_OPTION_MENU(w), 7);
+    else if (!strcasecmp(s, "Floating")) {
+        gtk_option_menu_set_history(GTK_OPTION_MENU(w), 8);
+        f = TRUE;
+    } else
+        gtk_option_menu_set_history(GTK_OPTION_MENU(w), 0);
+    g_free(s);
+
+    {
+        GtkWidget *s;
+        s = get_widget("dock_float_x");
+        gtk_widget_set_sensitive(s, f);
+        s = get_widget("dock_float_y");
+        gtk_widget_set_sensitive(s, f);
+        s = get_widget("dock_float_label");
+        gtk_widget_set_sensitive(s, f);
+        s = get_widget("dock_float_label_x");
+        gtk_widget_set_sensitive(s, f);
+    }
+
+    mapping = FALSE;
+}
+
+void dock_setup_float_x(GtkWidget *w)
+{
+    mapping = TRUE;
+
+    gtk_spin_button_set_value(GTK_SPIN_BUTTON(w),
+                              tree_get_int("dock/floatingX", 0));
+
+    mapping = FALSE;
+}
+
+void dock_setup_float_y(GtkWidget *w)
+{
+    mapping = TRUE;
+
+    gtk_spin_button_set_value(GTK_SPIN_BUTTON(w),
+                              tree_get_int("dock/floatingY", 0));
+
+    mapping = FALSE;
+}
+
+void dock_setup_stacking(GtkWidget *top, GtkWidget *normal, GtkWidget *bottom)
+{
+    gchar *s;
+
+    mapping = TRUE;
+
+    s = tree_get_string("dock/stacking", "Top");
+
+    if(!strcasecmp(s, "Normal"))
+        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(normal), TRUE);
+    else if(!strcasecmp(s, "Bottom"))
+        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(bottom), TRUE);
+    else
+        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(top), TRUE);
+    g_free(s);
+    
+    mapping = FALSE;
+}
+
+void dock_setup_direction(GtkWidget *w)
+{
+    gchar *s;
+
+    mapping = TRUE;
+
+    s = tree_get_string("dock/direction", "Vertical");
+
+    if (!strcasecmp(s, "Horizontal"))
+        gtk_option_menu_set_history(GTK_OPTION_MENU(w), 1);
+    else
+        gtk_option_menu_set_history(GTK_OPTION_MENU(w), 0);
+    g_free(s);
+
+    mapping = FALSE;
+}
+
+void dock_setup_hide(GtkWidget *w)
+{
+    gboolean b;
+
+    mapping = TRUE;
+
+    b = tree_get_bool("dock/autoHide", FALSE);
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), b);
+
+    {
+        GtkWidget *delay   = get_widget("dock_hide_delay");
+        GtkWidget *delay_l = get_widget("dock_hide_label");
+        GtkWidget *delay_u = get_widget("dock_hide_label_units");
+        gtk_widget_set_sensitive(delay, b);
+        gtk_widget_set_sensitive(delay_l, b);
+        gtk_widget_set_sensitive(delay_u, b);
+    }
+
+    mapping = FALSE;
+}
+
+void dock_setup_hide_delay(GtkWidget *w)
+{
+    mapping = TRUE;
+
+    gtk_spin_button_set_value(GTK_SPIN_BUTTON(w),
+                              tree_get_int("dock/hideDelay", 300));
+
+    mapping = FALSE;
+}
+
+
+void on_dock_top_left_activate(GtkMenuItem *w, gpointer data)
+{
+    if (mapping) return;
+
+    tree_set_string("dock/position", "TopLeft");
+
+    {
+        GtkWidget *s;
+        s = get_widget("dock_float_x");
+        gtk_widget_set_sensitive(s, FALSE);
+        s = get_widget("dock_float_y");
+        gtk_widget_set_sensitive(s, FALSE);
+        s = get_widget("dock_float_label");
+        gtk_widget_set_sensitive(s, FALSE);
+        s = get_widget("dock_float_label_x");
+        gtk_widget_set_sensitive(s, FALSE);
+    }
+}
+
+void on_dock_top_activate(GtkMenuItem *w, gpointer data)
+{
+    if (mapping) return;
+
+    tree_set_string("dock/position", "Top");
+
+    {
+        GtkWidget *s;
+        s = get_widget("dock_float_x");
+        gtk_widget_set_sensitive(s, FALSE);
+        s = get_widget("dock_float_y");
+        gtk_widget_set_sensitive(s, FALSE);
+        s = get_widget("dock_float_label");
+        gtk_widget_set_sensitive(s, FALSE);
+        s = get_widget("dock_float_label_x");
+        gtk_widget_set_sensitive(s, FALSE);
+    }
+}
+
+void on_dock_top_right_activate(GtkMenuItem *w, gpointer data)
+{
+    if (mapping) return;
+
+    tree_set_string("dock/position", "TopRight");
+
+    {
+        GtkWidget *s;
+        s = get_widget("dock_float_x");
+        gtk_widget_set_sensitive(s, FALSE);
+        s = get_widget("dock_float_y");
+        gtk_widget_set_sensitive(s, FALSE);
+        s = get_widget("dock_float_label");
+        gtk_widget_set_sensitive(s, FALSE);
+        s = get_widget("dock_float_label_x");
+        gtk_widget_set_sensitive(s, FALSE);
+    }
+}
+
+void on_dock_left_activate(GtkMenuItem *w, gpointer data)
+{
+    if (mapping) return;
+
+    tree_set_string("dock/position", "Left");
+
+    {
+        GtkWidget *s;
+        s = get_widget("dock_float_x");
+        gtk_widget_set_sensitive(s, FALSE);
+        s = get_widget("dock_float_y");
+        gtk_widget_set_sensitive(s, FALSE);
+        s = get_widget("dock_float_label");
+        gtk_widget_set_sensitive(s, FALSE);
+        s = get_widget("dock_float_label_x");
+        gtk_widget_set_sensitive(s, FALSE);
+    }
+}
+
+void on_dock_right_activate(GtkMenuItem *w, gpointer data)
+{
+    if (mapping) return;
+
+    tree_set_string("dock/position", "Right");
+
+    {
+        GtkWidget *s;
+        s = get_widget("dock_float_x");
+        gtk_widget_set_sensitive(s, FALSE);
+        s = get_widget("dock_float_y");
+        gtk_widget_set_sensitive(s, FALSE);
+        s = get_widget("dock_float_label");
+        gtk_widget_set_sensitive(s, FALSE);
+        s = get_widget("dock_float_label_x");
+        gtk_widget_set_sensitive(s, FALSE);
+    }
+}
+
+void on_dock_bottom_left_activate(GtkMenuItem *w, gpointer data)
+{
+    if (mapping) return;
+
+    tree_set_string("dock/position", "BottomLeft");
+
+    {
+        GtkWidget *s;
+        s = get_widget("dock_float_x");
+        gtk_widget_set_sensitive(s, FALSE);
+        s = get_widget("dock_float_y");
+        gtk_widget_set_sensitive(s, FALSE);
+        s = get_widget("dock_float_label");
+        gtk_widget_set_sensitive(s, FALSE);
+        s = get_widget("dock_float_label_x");
+        gtk_widget_set_sensitive(s, FALSE);
+    }
+}
+
+void on_dock_bottom_activate(GtkMenuItem *w, gpointer data)
+{
+    if (mapping) return;
+
+    tree_set_string("dock/position", "Bottom");
+
+    {
+        GtkWidget *s;
+        s = get_widget("dock_float_x");
+        gtk_widget_set_sensitive(s, FALSE);
+        s = get_widget("dock_float_y");
+        gtk_widget_set_sensitive(s, FALSE);
+        s = get_widget("dock_float_label");
+        gtk_widget_set_sensitive(s, FALSE);
+        s = get_widget("dock_float_label_x");
+        gtk_widget_set_sensitive(s, FALSE);
+    }
+}
+
+void on_dock_bottom_right_activate(GtkMenuItem *w, gpointer data)
+{
+    if (mapping) return;
+
+    tree_set_string("dock/position", "BottomRight");
+
+    {
+        GtkWidget *s;
+        s = get_widget("dock_float_x");
+        gtk_widget_set_sensitive(s, FALSE);
+        s = get_widget("dock_float_y");
+        gtk_widget_set_sensitive(s, FALSE);
+        s = get_widget("dock_float_label");
+        gtk_widget_set_sensitive(s, FALSE);
+        s = get_widget("dock_float_label_x");
+        gtk_widget_set_sensitive(s, FALSE);
+    }
+}
+
+void on_dock_floating_activate(GtkMenuItem *w, gpointer data)
+{
+    if (mapping) return;
+
+    tree_set_string("dock/position", "Floating");
+
+    {
+        GtkWidget *s;
+        s = get_widget("dock_float_x");
+        gtk_widget_set_sensitive(s, TRUE);
+        s = get_widget("dock_float_y");
+        gtk_widget_set_sensitive(s, TRUE);
+        s = get_widget("dock_float_label");
+        gtk_widget_set_sensitive(s, TRUE);
+        s = get_widget("dock_float_label_x");
+        gtk_widget_set_sensitive(s, TRUE);
+    }
+}
+
+void on_dock_float_x_value_changed(GtkSpinButton *w, gpointer data)
+{
+    if (mapping) return;
+
+    tree_set_int("dock/floatingX", gtk_spin_button_get_value_as_int(w));
+}
+
+void on_dock_float_y_value_changed(GtkSpinButton *w, gpointer data)
+{
+    if (mapping) return;
+
+    tree_set_int("dock/floatingY", gtk_spin_button_get_value_as_int(w));
+}
+
+void on_dock_stacking_top_toggled(GtkToggleButton *w, gpointer data)
+{
+    if (mapping) return;
+
+    if(gtk_toggle_button_get_active(w))
+        tree_set_string("dock/stacking", "Top");
+}
+
+void on_dock_stacking_normal_toggled(GtkToggleButton *w, gpointer data)
+{
+    if (mapping) return;
+
+    if(gtk_toggle_button_get_active(w))
+        tree_set_string("dock/stacking", "Normal");
+}
+
+void on_dock_stacking_bottom_toggled(GtkToggleButton *w, gpointer data)
+{
+    if (mapping) return;
+
+    if(gtk_toggle_button_get_active(w))
+        tree_set_string("dock/stacking", "Bottom");
+}
+
+void on_dock_horizontal_activate(GtkMenuItem *w, gpointer data)
+{
+    if (mapping) return;
+
+    tree_set_string("dock/direction", "Horizontal");
+}
+
+void on_dock_vertical_activate(GtkMenuItem *w, gpointer data)
+{
+    if (mapping) return;
+
+    tree_set_string("dock/direction", "Vertical");
+}
+
+void on_dock_hide_toggled(GtkToggleButton *w, gpointer data)
+{
+    if (mapping) return;
+
+    tree_set_bool("dock/autoHide", gtk_toggle_button_get_active(w));
+    {
+        GtkWidget *delay   = glade_xml_get_widget(glade, "dock_hide_delay");
+        GtkWidget *delay_l = glade_xml_get_widget(glade, "dock_hide_label");
+        GtkWidget *delay_u = glade_xml_get_widget(glade, 
+                                                  "dock_hide_label_units");
+        gtk_widget_set_sensitive(delay, gtk_toggle_button_get_active(w));
+        gtk_widget_set_sensitive(delay_l, gtk_toggle_button_get_active(w));
+        gtk_widget_set_sensitive(delay_u, gtk_toggle_button_get_active(w));
+    }
+}
+
+void on_dock_hide_delay_value_changed(GtkSpinButton *w, gpointer data)
+{
+    if (mapping) return;
+
+    tree_set_int("dock/hideDelay",
+                 gtk_spin_button_get_value_as_int(w));
+}
+
diff --git a/src/dock.h b/src/dock.h
new file mode 100644 (file)
index 0000000..8d4035a
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef obconf__dock_h
+#define obconf__dock_h
+
+#include <gtk/gtk.h>
+
+void dock_setup_position   (GtkWidget *w);
+void dock_setup_float_x    (GtkWidget *w);
+void dock_setup_float_y    (GtkWidget *w);
+void dock_setup_stacking   (GtkWidget *top,
+                            GtkWidget *normal, GtkWidget *bottom);
+void dock_setup_direction  (GtkWidget *w);
+void dock_setup_hide       (GtkWidget *w);
+void dock_setup_hide_delay (GtkWidget *w);
+
+#endif
diff --git a/src/handlers.c b/src/handlers.c
deleted file mode 100644 (file)
index 084151e..0000000
+++ /dev/null
@@ -1,1449 +0,0 @@
-/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
-
-   handlers.h for ObConf, the configuration tool for Openbox
-   Copyright (c) 2003-2007   Dana Jansens
-   Copyright (c) 2003        Tim Riley
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   See the COPYING file for a copy of the GNU General Public License.
-*/
-
-#include "main.h"
-#include "handlers.h"
-#include "tree.h"
-#include "theme.h"
-#include "gettext.h"
-
-#include <openbox/render.h>
-#include <string.h>
-#include <ctype.h>
-#include <gdk/gdkx.h>
-
-static gboolean mapping;
-static GList *themes;
-static GtkListStore *desktop_store;
-static int num_desktops;
-static GList *desktop_names;
-static GtkListStore *theme_store;
-
-static RrFont *active_window_font, *inactive_window_font, *menu_title_font, *menu_item_font, *osd_font;
-
-static gchar *titlelayout;
-
-static void on_desktop_names_cell_edited(GtkCellRendererText *cell,
-                                         const gchar *path_string,
-                                         const gchar *new_text,
-                                         gpointer data);
-
-static void on_theme_names_selection_changed(GtkTreeSelection *sel, 
-                                             gpointer data);
-static void handlers_update_theme_previews();
-
-
-void setup_behavior_tab()
-{
-    GtkWidget *winresist, *edgeresist;
-    GtkWidget *winresist_l, *edgeresist_l;
-    GtkSizeGroup *group1, *group2;
-
-    winresist  = glade_xml_get_widget(glade, "resist_window");
-    edgeresist = glade_xml_get_widget(glade, "resist_edge");
-    group1     = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
-
-    gtk_size_group_add_widget(group1, winresist);
-    gtk_size_group_add_widget(group1, edgeresist);
-
-    winresist_l  = glade_xml_get_widget(glade, "resist_window_label");
-    edgeresist_l = glade_xml_get_widget(glade, "resist_edge_label");
-    group2       = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
-
-    gtk_size_group_add_widget(group2, winresist_l);
-    gtk_size_group_add_widget(group2, edgeresist_l);
-}
-
-void setup_dock_tab()
-{
-    GtkWidget *posi, *dir;
-    GtkWidget *posi_l, *dir_l;
-    GtkSizeGroup *group1, *group2;
-
-    posi   = glade_xml_get_widget(glade, "dock_position");
-    dir    = glade_xml_get_widget(glade, "dock_direction");
-    group1 = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
-
-    gtk_size_group_add_widget(group1, posi);
-    gtk_size_group_add_widget(group1, dir);
-
-    posi_l = glade_xml_get_widget(glade, "dock_position_label");
-    dir_l  = glade_xml_get_widget(glade, "dock_direction_label");
-    group2 = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
-
-    gtk_size_group_add_widget(group2, posi_l);
-    gtk_size_group_add_widget(group2, dir_l);
-}
-
-
-
-gboolean on_main_window_delete_event(GtkWidget *w, GdkEvent *e, gpointer d)
-{
-    gtk_main_quit();
-    return FALSE;
-}
-
-void on_close_clicked()
-{
-    gtk_main_quit();
-}
-
-void on_about_clicked()
-{
-    gtk_widget_show(glade_xml_get_widget(glade, "about_window"));
-}
-
-void on_about_close_clicked()
-{
-    GtkWidget *about;
-    
-    about = glade_xml_get_widget(glade, "about_window");
-    
-    gtk_widget_hide(about);
-}
-
-void on_about_window_delete_event()
-{
-    GtkWidget *about;
-
-    about = glade_xml_get_widget(glade, "about_window");
-
-    gtk_widget_hide(about);
-}
-
-void setup_focus_mouse(GtkWidget *w)
-{
-    gboolean b;
-
-    mapping = TRUE;
-
-    b = tree_get_bool("focus/followMouse", FALSE);
-    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), b);
-
-    {
-        GtkWidget *delay   = glade_xml_get_widget(glade, "focus_delay");
-        GtkWidget *delay_l = glade_xml_get_widget(glade, "focus_delay_label");
-        GtkWidget *delay_u = glade_xml_get_widget(glade,
-                                                  "focus_delay_label_units");
-        GtkWidget *raise   = glade_xml_get_widget(glade, "focus_raise");
-        GtkWidget *last    = glade_xml_get_widget(glade, "focus_last");
-        gtk_widget_set_sensitive(delay, b);
-        gtk_widget_set_sensitive(delay_l, b);
-        gtk_widget_set_sensitive(delay_u, b);
-        gtk_widget_set_sensitive(raise, b);
-        gtk_widget_set_sensitive(last, b);
-    }
-
-    mapping = FALSE;
-}
-
-void setup_focus_delay(GtkWidget *w)
-{
-    mapping = TRUE;
-    gtk_spin_button_set_value(GTK_SPIN_BUTTON(w),
-                              tree_get_int("focus/focusDelay", 0));
-    mapping = FALSE;
-}
-
-void setup_focus_raise(GtkWidget *w)
-{
-    mapping = TRUE;
-    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w),
-                                 tree_get_bool("focus/raiseOnFocus", FALSE));
-    mapping = FALSE;
-}
-
-void setup_focus_last(GtkWidget *w)
-{
-    mapping = TRUE;
-    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w),
-                                 tree_get_bool("focus/focusLast", FALSE));
-    mapping = FALSE;
-}
-
-void setup_focus_new(GtkWidget *w)
-{
-    mapping = TRUE;
-    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w),
-                                 tree_get_bool("focus/focusNew", TRUE));
-    mapping = FALSE;
-}
-
-void setup_place_mouse(GtkWidget *w)
-{
-    gchar *s;
-
-    mapping = TRUE;
-    s = tree_get_string("placement/policy", "Smart");
-    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w),
-                                 !g_ascii_strcasecmp(s, "UnderMouse"));
-    g_free(s);
-    mapping = FALSE;
-}
-
-void setup_resist_window(GtkWidget *w)
-{
-    mapping = TRUE;
-    gtk_spin_button_set_value(GTK_SPIN_BUTTON(w),
-                              tree_get_int("resistance/strength", 10));
-    mapping = FALSE;
-}
-
-void setup_resist_edge(GtkWidget *w)
-{
-    mapping = TRUE;
-    gtk_spin_button_set_value(GTK_SPIN_BUTTON(w),
-                              tree_get_int("resistance/screen_edge_strength",
-                                           20));
-    mapping = FALSE;
-}
-
-void setup_resize_contents(GtkWidget *w)
-{
-    mapping = TRUE;
-    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w),
-                                 tree_get_bool("resize/drawContents", TRUE));
-    mapping = FALSE;
-}
-
-void setup_dock_position(GtkWidget *w)
-{
-    gchar *s;
-    gboolean f;
-
-    mapping = TRUE;
-
-    s = tree_get_string("dock/position", "TopLeft");
-    f = FALSE;
-
-    if (!strcasecmp(s, "Top"))
-        gtk_option_menu_set_history(GTK_OPTION_MENU(w), 1);
-    else if (!strcasecmp(s, "TopRight"))
-        gtk_option_menu_set_history(GTK_OPTION_MENU(w), 2);
-    else if (!strcasecmp(s, "Left"))
-        gtk_option_menu_set_history(GTK_OPTION_MENU(w), 3);
-    else if (!strcasecmp(s, "Right"))
-        gtk_option_menu_set_history(GTK_OPTION_MENU(w), 4);
-    else if (!strcasecmp(s, "BottomLeft"))
-        gtk_option_menu_set_history(GTK_OPTION_MENU(w), 5);
-    else if (!strcasecmp(s, "Bottom"))
-        gtk_option_menu_set_history(GTK_OPTION_MENU(w), 6);
-    else if (!strcasecmp(s, "BottomRight"))
-        gtk_option_menu_set_history(GTK_OPTION_MENU(w), 7);
-    else if (!strcasecmp(s, "Floating")) {
-        gtk_option_menu_set_history(GTK_OPTION_MENU(w), 8);
-        f = TRUE;
-    } else
-        gtk_option_menu_set_history(GTK_OPTION_MENU(w), 0);
-    g_free(s);
-
-    {
-        GtkWidget *s;
-        s = glade_xml_get_widget(glade, "dock_float_x");
-        gtk_widget_set_sensitive(s, f);
-        s = glade_xml_get_widget(glade, "dock_float_y");
-        gtk_widget_set_sensitive(s, f);
-        s = glade_xml_get_widget(glade, "dock_float_label");
-        gtk_widget_set_sensitive(s, f);
-        s = glade_xml_get_widget(glade, "dock_float_label_x");
-        gtk_widget_set_sensitive(s, f);
-    }
-
-    mapping = FALSE;
-}
-
-void setup_dock_float_x(GtkWidget *w)
-{
-    mapping = TRUE;
-
-    gtk_spin_button_set_value(GTK_SPIN_BUTTON(w),
-                              tree_get_int("dock/floatingX", 0));
-
-    mapping = FALSE;
-}
-
-void setup_dock_float_y(GtkWidget *w)
-{
-    mapping = TRUE;
-
-    gtk_spin_button_set_value(GTK_SPIN_BUTTON(w),
-                              tree_get_int("dock/floatingY", 0));
-
-    mapping = FALSE;
-}
-
-void setup_dock_stacking(GtkWidget *top, GtkWidget *normal, GtkWidget *bottom)
-{
-    gchar *s;
-
-    mapping = TRUE;
-
-    s = tree_get_string("dock/stacking", "Top");
-
-    if(!strcasecmp(s, "Normal"))
-        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(normal), TRUE);
-    else if(!strcasecmp(s, "Bottom"))
-        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(bottom), TRUE);
-    else
-        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(top), TRUE);
-    g_free(s);
-    
-    mapping = FALSE;
-}
-
-void setup_dock_direction(GtkWidget *w)
-{
-    gchar *s;
-
-    mapping = TRUE;
-
-    s = tree_get_string("dock/direction", "Vertical");
-
-    if (!strcasecmp(s, "Horizontal"))
-        gtk_option_menu_set_history(GTK_OPTION_MENU(w), 1);
-    else
-        gtk_option_menu_set_history(GTK_OPTION_MENU(w), 0);
-    g_free(s);
-
-    mapping = FALSE;
-}
-
-void setup_dock_hide(GtkWidget *w)
-{
-    gboolean b;
-
-    mapping = TRUE;
-
-    b = tree_get_bool("dock/autoHide", FALSE);
-    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), b);
-
-    {
-        GtkWidget *delay   = glade_xml_get_widget(glade, "dock_hide_delay");
-        GtkWidget *delay_l = glade_xml_get_widget(glade, "dock_hide_label");
-        GtkWidget *delay_u = glade_xml_get_widget(glade, 
-                                                  "dock_hide_label_units");
-        gtk_widget_set_sensitive(delay, b);
-        gtk_widget_set_sensitive(delay_l, b);
-        gtk_widget_set_sensitive(delay_u, b);
-    }
-
-    mapping = FALSE;
-}
-
-void setup_dock_hide_delay(GtkWidget *w)
-{
-    mapping = TRUE;
-
-    gtk_spin_button_set_value(GTK_SPIN_BUTTON(w),
-                              tree_get_int("dock/hideDelay", 300));
-
-    mapping = FALSE;
-}
-
-static void add_theme_dir(const gchar *dirname)
-{
-    GDir *dir;
-    const gchar *n;
-
-    if ((dir = g_dir_open(dirname, 0, NULL))) {
-        while ((n = g_dir_read_name(dir))) {
-            {
-                gchar *full;
-                full = g_build_filename(dirname, n, "openbox-3",
-                                        "themerc", NULL);
-                if (!g_file_test(full,
-                                 G_FILE_TEST_IS_REGULAR |
-                                 G_FILE_TEST_IS_SYMLINK))
-                    n = NULL;
-                g_free(full);
-            }
-
-            if (n) {
-                themes = g_list_append(themes, g_strdup(n));
-            }
-        }
-        g_dir_close(dir);
-    }
-}
-
-static void reset_theme_names(GtkWidget *w)
-{
-    gchar *name;
-    gchar *p;
-    GList *it, *next;
-    gint i;
-
-    RrFont *active, *inactive, *menu_t, *menu_i, *osd;
-
-    name = tree_get_string("theme/name", "TheBear");
-
-    for (it = themes; it; it = g_list_next(it))
-        g_free(it->data);
-    g_list_free(themes);
-    themes = NULL;
-
-    p = g_build_filename(g_get_home_dir(), ".themes", NULL);
-    add_theme_dir(p);
-    g_free(p);
-
-    {
-        GSList *it;
-        for (it = parse_xdg_data_dir_paths(); it; it = g_slist_next(it)) {
-            p = g_build_filename(it->data, "themes", NULL);
-            add_theme_dir(p);
-            g_free(p);
-        }
-    }
-
-    add_theme_dir(THEMEDIR);
-
-    themes = g_list_sort(themes, (GCompareFunc) strcasecmp);
-
-    gtk_list_store_clear(theme_store);
-
-    /* return to regular scheduled programming */
-    i = 0;
-    for (it = themes; it; it = next) {
-        GtkTreeIter iter;
-
-        next = g_list_next(it);
-
-        /* remove duplicates */
-        if (next && !strcmp(it->data, next->data)) {
-            g_free(it->data);
-            themes = g_list_delete_link(themes, it);
-            continue;
-        }
-
-        gtk_list_store_append(theme_store, &iter);
-        gtk_list_store_set(theme_store, &iter,
-                           0, it->data,
-                           1, NULL,
-                           -1);
-
-        if(!strcmp(name, it->data)) {
-            GtkTreePath *path;
-            path = gtk_tree_path_new_from_indices(i, -1);
-            gtk_tree_view_set_cursor(GTK_TREE_VIEW(w), path, NULL, FALSE);
-            gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(w), path, NULL,
-                                         FALSE, 0, 0);
-        }
-
-
-        ++i;
-    }
-
-    handlers_update_theme_previews();
-
-    g_free(name);
-}
-
-void setup_theme_names(GtkWidget *w)
-{
-    GtkCellRenderer *render;
-    GtkTreeViewColumn *column;
-    GtkTreeSelection *select;
-
-    mapping = TRUE;
-
-    /* widget setup */
-    theme_store = gtk_list_store_new(2, G_TYPE_STRING, GDK_TYPE_PIXBUF);
-    gtk_tree_view_set_model(GTK_TREE_VIEW(w), GTK_TREE_MODEL(theme_store));
-    g_object_unref (theme_store);
-
-    gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(w)),
-                                GTK_SELECTION_SINGLE);
-
-    /* text column for the names */
-    render = gtk_cell_renderer_text_new();
-    column = gtk_tree_view_column_new_with_attributes
-        ("Name", render, "text", 0, NULL);
-    gtk_tree_view_append_column(GTK_TREE_VIEW(w), column);
-
-    /* pixbuf column, for theme previews */
-    render = gtk_cell_renderer_pixbuf_new();
-    g_object_set(render, "xalign", 1.0);
-    column = gtk_tree_view_column_new_with_attributes
-        ("Preview", render, "pixbuf", 1, NULL);
-    gtk_tree_view_append_column(GTK_TREE_VIEW(w), column);
-
-
-    /* setup the selection handler */
-    select = gtk_tree_view_get_selection(GTK_TREE_VIEW (w));
-    gtk_tree_selection_set_mode(select, GTK_SELECTION_SINGLE);
-    g_signal_connect (G_OBJECT(select), "changed",
-                      G_CALLBACK(on_theme_names_selection_changed),
-                      NULL);
-
-    reset_theme_names(w);
-
-    mapping = FALSE;
-}
-
-void setup_title_layout(GtkWidget *w)
-{
-    gchar *layout;
-
-    mapping = TRUE;
-
-    layout = tree_get_string("theme/titleLayout", "NLIMC");
-    titlelayout = g_strdup(layout);
-    gtk_entry_set_text(GTK_ENTRY(w), layout);
-    g_free(layout);
-
-    mapping = FALSE;
-}
-
-void setup_desktop_num(GtkWidget *w)
-{
-    mapping = TRUE;
-
-    num_desktops = tree_get_int("desktops/number", 4);
-    gtk_spin_button_set_value(GTK_SPIN_BUTTON(w), num_desktops);
-
-    mapping = FALSE;
-}
-
-void setup_window_border(GtkWidget *w)
-{
-    gboolean border;
-
-    mapping = TRUE;
-
-    border = tree_get_bool("theme/keepBorder", TRUE);
-    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), border);
-
-    mapping = FALSE;
-}
-
-static RrFont *setup_font(GtkWidget *w, const gchar *place)
-{
-    RrFont *font;
-    gchar *fontstring, *node;
-    gchar *name, **names;
-    gchar *size;
-    gchar *weight;
-    gchar *slant;
-
-    RrFontWeight rr_weight = RR_FONTWEIGHT_NORMAL;
-    RrFontSlant rr_slant = RR_FONTSLANT_NORMAL;
-
-    mapping = TRUE;
-
-    node = g_strdup_printf("theme/font:place=%s/name", place);
-    name = tree_get_string(node, "Sans");
-    g_free(node);
-
-    node = g_strdup_printf("theme/font:place=%s/size", place);
-    size = tree_get_string(node, "8");
-    g_free(node);
-
-    node = g_strdup_printf("theme/font:place=%s/weight", place);
-    weight = tree_get_string(node, "");
-    g_free(node);
-
-    node = g_strdup_printf("theme/font:place=%s/slant", place);
-    slant = tree_get_string(node, "");
-    g_free(node);
-
-    /* get only the first font in the string */
-    names = g_strsplit(name, ",", 0);
-    g_free(name);
-    name = g_strdup(names[0]);
-    g_strfreev(names);
-
-    /* don't use "normal" in the gtk string */
-    if (!g_ascii_strcasecmp(weight, "normal")) {
-        g_free(weight); weight = g_strdup("");
-    }
-    if (!g_ascii_strcasecmp(slant, "normal")) {
-        g_free(slant); slant = g_strdup("");
-    }
-
-    fontstring = g_strdup_printf("%s %s %s %s", name, weight, slant, size);
-    gtk_font_button_set_font_name(GTK_FONT_BUTTON(w), fontstring);
-
-    if (!g_ascii_strcasecmp(weight, "Bold")) rr_weight = RR_FONTWEIGHT_BOLD;
-    if (!g_ascii_strcasecmp(slant, "Italic")) rr_slant = RR_FONTSLANT_ITALIC;
-    if (!g_ascii_strcasecmp(slant, "Oblique")) rr_slant = RR_FONTSLANT_OBLIQUE;
-
-    font = RrFontOpen(rrinst, name, atoi(size), rr_weight, rr_slant);
-    g_free(fontstring);
-    g_free(slant);
-    g_free(weight);
-    g_free(size);
-    g_free(name);
-
-    mapping = FALSE;
-
-    return font;
-}
-
-void setup_font_active(GtkWidget *w)
-{
-    active_window_font = setup_font(w, "ActiveWindow");
-}
-
-void setup_font_inactive(GtkWidget *w)
-{
-    inactive_window_font = setup_font(w, "InactiveWindow");
-}
-
-void setup_font_menu_header(GtkWidget *w)
-{
-    menu_title_font = setup_font(w, "MenuHeader");
-}
-
-void setup_font_menu_item(GtkWidget *w)
-{
-    menu_item_font = setup_font(w, "MenuItem");
-}
-
-void setup_font_display(GtkWidget *w)
-{
-    osd_font = setup_font(w, "OnScreenDisplay");
-}
-
-
-static void reset_desktop_names()
-{
-    GtkTreeIter it;
-    xmlNodePtr n;
-    gint i;
-    GList *lit;
-
-    gtk_list_store_clear(desktop_store);
-
-    for (lit = desktop_names; lit; lit = g_list_next(lit))
-        g_free(lit->data);
-    g_list_free(desktop_names);
-    desktop_names = NULL;
-
-    i = 0;
-    n = tree_get_node("desktops/names", NULL)->children;
-    while (n) {
-        gchar *name;
-
-        if (!xmlStrcmp(n->name, (const xmlChar*)"name")) {
-            name = parse_string(doc, n);
-
-            desktop_names = g_list_append(desktop_names, name);
-
-            gtk_list_store_append(desktop_store, &it);
-            gtk_list_store_set(desktop_store, &it,
-                               0, (name[0] ? name : _("(Unnamed desktop)")),
-                               1, TRUE,
-                               -1);
-            ++i;
-        }
-
-        n = n->next;
-    }
-
-    while (i < num_desktops) {
-        gchar *name = g_strdup("");
-
-        desktop_names = g_list_append(desktop_names, name);
-
-        gtk_list_store_append(desktop_store, &it);
-        gtk_list_store_set(desktop_store, &it,
-                           0, _("(Unnamed desktop)"),
-                           1, TRUE,
-                           -1);
-        ++i;
-    }
-}
-
-void setup_desktop_names(GtkWidget *w)
-{
-    GtkCellRenderer *render;
-    GtkTreeViewColumn *column;
-
-    mapping = TRUE;
-
-    desktop_store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_BOOLEAN);
-    gtk_tree_view_set_model(GTK_TREE_VIEW(w), GTK_TREE_MODEL(desktop_store));
-    g_object_unref (desktop_store);
-
-    gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(w)),
-                                GTK_SELECTION_SINGLE);
-
-    render = gtk_cell_renderer_text_new();
-    g_signal_connect(render, "edited",
-                     G_CALLBACK (on_desktop_names_cell_edited),
-                     NULL);
-
-    column = gtk_tree_view_column_new_with_attributes
-        ("Name", render, "text", 0, "editable", 1, NULL);
-    gtk_tree_view_append_column(GTK_TREE_VIEW(w), column);
-
-    reset_desktop_names();
-
-    mapping = FALSE;
-}
-
-
-/***********************************************************************/
-
-void on_window_border_toggled(GtkToggleButton *w, gpointer data)
-{
-    gboolean b;
-
-    if (mapping) return;
-
-    b = gtk_toggle_button_get_active(w);
-    tree_set_bool("theme/keepBorder", b);
-}
-
-static RrFont *on_font_set(GtkFontButton *w, const gchar *place)
-{
-    gchar *c;
-    gchar *font, *node;
-    const gchar *size = NULL;
-    const gchar *bold = NULL;
-    const gchar *italic = NULL;
-
-    RrFontWeight weight = RR_FONTWEIGHT_NORMAL;
-    RrFontSlant slant = RR_FONTSLANT_NORMAL;
-
-    if (mapping) return;
-
-    font = g_strdup(gtk_font_button_get_font_name(w));
-    while ((c = strrchr(font, ' '))) {
-        if (!bold && !italic && !size && atoi(c+1))
-            size = c+1;
-        else if (!bold && !italic && !g_ascii_strcasecmp(c+1, "italic"))
-            italic = c+1;
-        else if (!bold && !g_ascii_strcasecmp(c+1, "bold"))
-            bold = c+1;
-        else
-            break;
-        *c = '\0';
-    }
-    if (!bold) bold = "Normal";
-    if (!italic) italic = "Normal";
-
-    node = g_strdup_printf("theme/font:place=%s/name", place);
-    tree_set_string(node, font);
-    g_free(node);
-
-    node = g_strdup_printf("theme/font:place=%s/size", place);
-    tree_set_string(node, size);
-    g_free(node);
-
-    node = g_strdup_printf("theme/font:place=%s/weight", place);
-    tree_set_string(node, bold);
-    g_free(node);
-
-    node = g_strdup_printf("theme/font:place=%s/slant", place);
-    tree_set_string(node, italic);
-    g_free(node);
-
-    if (!g_ascii_strcasecmp(bold, "Bold")) weight = RR_FONTWEIGHT_BOLD;
-    if (!g_ascii_strcasecmp(italic, "Italic")) slant = RR_FONTSLANT_ITALIC;
-    if (!g_ascii_strcasecmp(italic, "Oblique")) slant = RR_FONTSLANT_OBLIQUE;
-
-    return RrFontOpen(rrinst, font, atoi(size), weight, slant);
-
-    g_free(font);
-
-}
-
-void on_font_active_font_set(GtkFontButton *w, gpointer data)
-{
-    RrFontClose(active_window_font);
-    active_window_font = on_font_set(w, "ActiveWindow");
-    handlers_update_theme_previews();
-}
-
-void on_font_inactive_font_set(GtkFontButton *w, gpointer data)
-{
-    RrFontClose(inactive_window_font);
-    inactive_window_font = on_font_set(w, "InactiveWindow");
-    handlers_update_theme_previews();
-}
-
-void on_font_menu_header_font_set(GtkFontButton *w, gpointer data)
-{
-    RrFontClose(menu_title_font);
-    menu_title_font = on_font_set(w, "MenuHeader");
-    handlers_update_theme_previews();
-}
-
-void on_font_menu_item_font_set(GtkFontButton *w, gpointer data)
-{
-    RrFontClose(menu_item_font);
-    menu_item_font = on_font_set(w, "MenuItem");
-    handlers_update_theme_previews();
-}
-
-void on_font_display_font_set(GtkFontButton *w, gpointer data)
-{
-    RrFontClose(osd_font);
-    osd_font = on_font_set(w, "OnScreenDisplay");
-    handlers_update_theme_previews();
-}
-
-void on_focus_mouse_toggled(GtkToggleButton *w, gpointer data)
-{
-    gboolean b;
-
-    if (mapping) return;
-
-    b = gtk_toggle_button_get_active(w);
-    tree_set_bool("focus/followMouse", b);
-
-    {
-        GtkWidget *delay   = glade_xml_get_widget(glade, "focus_delay");
-        GtkWidget *delay_l = glade_xml_get_widget(glade, "focus_delay_label");
-        GtkWidget *delay_u = glade_xml_get_widget(glade,
-                                                  "focus_delay_label_units");
-        GtkWidget *raise   = glade_xml_get_widget(glade, "focus_raise");
-        GtkWidget *last    = glade_xml_get_widget(glade, "focus_last");
-        gtk_widget_set_sensitive(delay, b);
-        gtk_widget_set_sensitive(delay_l, b);
-        gtk_widget_set_sensitive(delay_u, b);
-        gtk_widget_set_sensitive(raise, b);
-        gtk_widget_set_sensitive(last, b);
-    }
-}
-
-void on_focus_delay_value_changed(GtkSpinButton *w, gpointer data)
-{
-    if (mapping) return;
-
-    tree_set_int("focus/focusDelay",
-                 gtk_spin_button_get_value_as_int(w));
-}
-
-void on_focus_raise_toggled(GtkToggleButton *w, gpointer data)
-{
-    if (mapping) return;
-
-    tree_set_bool("focus/raiseOnFocus", gtk_toggle_button_get_active(w));
-}
-
-void on_focus_last_toggled(GtkToggleButton *w, gpointer data)
-{
-    if (mapping) return;
-
-    tree_set_bool("focus/focusLast", gtk_toggle_button_get_active(w));
-}
-
-void on_focus_new_toggled(GtkToggleButton *w, gpointer data)
-{
-    if (mapping) return;
-
-    tree_set_bool("focus/focusNew", gtk_toggle_button_get_active(w));
-}
-
-void on_place_mouse_toggled(GtkToggleButton *w, gpointer data)
-{
-    if (mapping) return;
-
-    tree_set_string("placement/policy",
-                    (gtk_toggle_button_get_active(w) ?
-                     "UnderMouse" : "Smart"));
-}
-
-void on_resist_window_value_changed(GtkSpinButton *w, gpointer data)
-{
-    if (mapping) return;
-
-    tree_set_int("resistance/strength", gtk_spin_button_get_value_as_int(w));
-}
-
-void on_resist_edge_value_changed(GtkSpinButton *w, gpointer data)
-{
-    if (mapping) return;
-
-    tree_set_int("resistance/screen_edge_strength",
-                 gtk_spin_button_get_value_as_int(w));
-}
-
-void on_resize_contents_toggled(GtkToggleButton *w, gpointer data)
-{
-    if (mapping) return;
-
-    tree_set_bool("resize/drawContents", gtk_toggle_button_get_active(w));
-}
-
-void on_dock_top_left_activate(GtkMenuItem *w, gpointer data)
-{
-    if (mapping) return;
-
-    tree_set_string("dock/position", "TopLeft");
-
-    {
-        GtkWidget *s;
-        s = glade_xml_get_widget(glade, "dock_float_x");
-        gtk_widget_set_sensitive(s, FALSE);
-        s = glade_xml_get_widget(glade, "dock_float_y");
-        gtk_widget_set_sensitive(s, FALSE);
-        s = glade_xml_get_widget(glade, "dock_float_label");
-        gtk_widget_set_sensitive(s, FALSE);
-        s = glade_xml_get_widget(glade, "dock_float_label_x");
-        gtk_widget_set_sensitive(s, FALSE);
-    }
-}
-
-void on_dock_top_activate(GtkMenuItem *w, gpointer data)
-{
-    if (mapping) return;
-
-    tree_set_string("dock/position", "Top");
-
-    {
-        GtkWidget *s;
-        s = glade_xml_get_widget(glade, "dock_float_x");
-        gtk_widget_set_sensitive(s, FALSE);
-        s = glade_xml_get_widget(glade, "dock_float_y");
-        gtk_widget_set_sensitive(s, FALSE);
-        s = glade_xml_get_widget(glade, "dock_float_label");
-        gtk_widget_set_sensitive(s, FALSE);
-        s = glade_xml_get_widget(glade, "dock_float_label_x");
-        gtk_widget_set_sensitive(s, FALSE);
-    }
-}
-
-void on_dock_top_right_activate(GtkMenuItem *w, gpointer data)
-{
-    if (mapping) return;
-
-    tree_set_string("dock/position", "TopRight");
-
-    {
-        GtkWidget *s;
-        s = glade_xml_get_widget(glade, "dock_float_x");
-        gtk_widget_set_sensitive(s, FALSE);
-        s = glade_xml_get_widget(glade, "dock_float_y");
-        gtk_widget_set_sensitive(s, FALSE);
-        s = glade_xml_get_widget(glade, "dock_float_label");
-        gtk_widget_set_sensitive(s, FALSE);
-        s = glade_xml_get_widget(glade, "dock_float_label_x");
-        gtk_widget_set_sensitive(s, FALSE);
-    }
-}
-
-void on_dock_left_activate(GtkMenuItem *w, gpointer data)
-{
-    if (mapping) return;
-
-    tree_set_string("dock/position", "Left");
-
-    {
-        GtkWidget *s;
-        s = glade_xml_get_widget(glade, "dock_float_x");
-        gtk_widget_set_sensitive(s, FALSE);
-        s = glade_xml_get_widget(glade, "dock_float_y");
-        gtk_widget_set_sensitive(s, FALSE);
-        s = glade_xml_get_widget(glade, "dock_float_label");
-        gtk_widget_set_sensitive(s, FALSE);
-        s = glade_xml_get_widget(glade, "dock_float_label_x");
-        gtk_widget_set_sensitive(s, FALSE);
-    }
-}
-
-void on_dock_right_activate(GtkMenuItem *w, gpointer data)
-{
-    if (mapping) return;
-
-    tree_set_string("dock/position", "Right");
-
-    {
-        GtkWidget *s;
-        s = glade_xml_get_widget(glade, "dock_float_x");
-        gtk_widget_set_sensitive(s, FALSE);
-        s = glade_xml_get_widget(glade, "dock_float_y");
-        gtk_widget_set_sensitive(s, FALSE);
-        s = glade_xml_get_widget(glade, "dock_float_label");
-        gtk_widget_set_sensitive(s, FALSE);
-        s = glade_xml_get_widget(glade, "dock_float_label_x");
-        gtk_widget_set_sensitive(s, FALSE);
-        
-    }
-}
-
-void on_dock_bottom_left_activate(GtkMenuItem *w, gpointer data)
-{
-    if (mapping) return;
-
-    tree_set_string("dock/position", "BottomLeft");
-
-    {
-        GtkWidget *s;
-        s = glade_xml_get_widget(glade, "dock_float_x");
-        gtk_widget_set_sensitive(s, FALSE);
-        s = glade_xml_get_widget(glade, "dock_float_y");
-        gtk_widget_set_sensitive(s, FALSE);
-        s = glade_xml_get_widget(glade, "dock_float_label");
-        gtk_widget_set_sensitive(s, FALSE);
-        s = glade_xml_get_widget(glade, "dock_float_label_x");
-        gtk_widget_set_sensitive(s, FALSE);
-    }
-}
-
-void on_dock_bottom_activate(GtkMenuItem *w, gpointer data)
-{
-    if (mapping) return;
-
-    tree_set_string("dock/position", "Bottom");
-
-    {
-        GtkWidget *s;
-        s = glade_xml_get_widget(glade, "dock_float_x");
-        gtk_widget_set_sensitive(s, FALSE);
-        s = glade_xml_get_widget(glade, "dock_float_y");
-        gtk_widget_set_sensitive(s, FALSE);
-        s = glade_xml_get_widget(glade, "dock_float_label");
-        gtk_widget_set_sensitive(s, FALSE);
-        s = glade_xml_get_widget(glade, "dock_float_label_x");
-        gtk_widget_set_sensitive(s, FALSE);
-    }
-}
-
-void on_dock_bottom_right_activate(GtkMenuItem *w, gpointer data)
-{
-    if (mapping) return;
-
-    tree_set_string("dock/position", "BottomRight");
-
-    {
-        GtkWidget *s;
-        s = glade_xml_get_widget(glade, "dock_float_x");
-        gtk_widget_set_sensitive(s, FALSE);
-        s = glade_xml_get_widget(glade, "dock_float_y");
-        gtk_widget_set_sensitive(s, FALSE);
-        s = glade_xml_get_widget(glade, "dock_float_label");
-        gtk_widget_set_sensitive(s, FALSE);
-        s = glade_xml_get_widget(glade, "dock_float_label_x");
-        gtk_widget_set_sensitive(s, FALSE);
-    }
-}
-
-void on_dock_floating_activate(GtkMenuItem *w, gpointer data)
-{
-    if (mapping) return;
-
-    tree_set_string("dock/position", "Floating");
-
-    {
-        GtkWidget *s;
-        s = glade_xml_get_widget(glade, "dock_float_x");
-        gtk_widget_set_sensitive(s, TRUE);
-        s = glade_xml_get_widget(glade, "dock_float_y");
-        gtk_widget_set_sensitive(s, TRUE);
-         s = glade_xml_get_widget(glade, "dock_float_label");
-        gtk_widget_set_sensitive(s, TRUE);
-         s = glade_xml_get_widget(glade, "dock_float_label_x");
-        gtk_widget_set_sensitive(s, TRUE);
-    }
-}
-
-void on_dock_float_x_value_changed(GtkSpinButton *w, gpointer data)
-{
-    if (mapping) return;
-
-    tree_set_int("dock/floatingX", gtk_spin_button_get_value_as_int(w));
-}
-
-void on_dock_float_y_value_changed(GtkSpinButton *w, gpointer data)
-{
-    if (mapping) return;
-
-    tree_set_int("dock/floatingY", gtk_spin_button_get_value_as_int(w));
-}
-
-void on_dock_stacking_top_toggled(GtkToggleButton *w, gpointer data)
-{
-    if (mapping) return;
-
-    if(gtk_toggle_button_get_active(w))
-        tree_set_string("dock/stacking", "Top");
-}
-
-void on_dock_stacking_normal_toggled(GtkToggleButton *w, gpointer data)
-{
-    if (mapping) return;
-
-    if(gtk_toggle_button_get_active(w))
-        tree_set_string("dock/stacking", "Normal");
-}
-
-void on_dock_stacking_bottom_toggled(GtkToggleButton *w, gpointer data)
-{
-    if (mapping) return;
-
-    if(gtk_toggle_button_get_active(w))
-        tree_set_string("dock/stacking", "Bottom");
-}
-
-void on_dock_horizontal_activate(GtkMenuItem *w, gpointer data)
-{
-    if (mapping) return;
-
-    tree_set_string("dock/direction", "Horizontal");
-}
-
-void on_dock_vertical_activate(GtkMenuItem *w, gpointer data)
-{
-    if (mapping) return;
-
-    tree_set_string("dock/direction", "Vertical");
-}
-
-void on_dock_hide_toggled(GtkToggleButton *w, gpointer data)
-{
-    if (mapping) return;
-
-    tree_set_bool("dock/autoHide", gtk_toggle_button_get_active(w));
-    {
-        GtkWidget *delay   = glade_xml_get_widget(glade, "dock_hide_delay");
-        GtkWidget *delay_l = glade_xml_get_widget(glade, "dock_hide_label");
-        GtkWidget *delay_u = glade_xml_get_widget(glade, 
-                                                  "dock_hide_label_units");
-        gtk_widget_set_sensitive(delay, gtk_toggle_button_get_active(w));
-        gtk_widget_set_sensitive(delay_l, gtk_toggle_button_get_active(w));
-        gtk_widget_set_sensitive(delay_u, gtk_toggle_button_get_active(w));
-    }
-}
-
-void on_dock_hide_delay_value_changed(GtkSpinButton *w, gpointer data)
-{
-    if (mapping) return;
-
-    tree_set_int("dock/hideDelay",
-                 gtk_spin_button_get_value_as_int(w));
-}
-
-void on_theme_name_changed(GtkOptionMenu *w, gpointer data)
-{
-    const gchar *name;
-
-    if (mapping) return;
-
-    name = g_list_nth_data(themes, gtk_option_menu_get_history(w));
-
-    if (name)
-        tree_set_string("theme/name", name);
-}
-
-void on_theme_names_selection_changed(GtkTreeSelection *sel, gpointer data)
-{
-    GtkTreeIter iter;
-    GtkTreeModel *model;
-    const gchar *name;
-
-    if (mapping) return;
-
-    if(gtk_tree_selection_get_selected(sel, &model, &iter)) {
-        gtk_tree_model_get(model, &iter, 0, &name, -1);
-    }
-
-    if(name)
-      tree_set_string("theme/name", name);
-}
-
-void on_title_layout_changed(GtkEntry *w, gpointer data)
-{
-    gchar *layout;
-    gchar *it, *it2;
-    gboolean n, d, s, l, i, m, c;
-
-    if (mapping) return;
-
-    layout = g_strdup(gtk_entry_get_text(w));
-
-    n = d = s = l = i = m = c = FALSE;
-
-    for (it = layout; *it; ++it) {
-        gboolean *b;
-
-        switch (*it) {
-        case 'N':
-        case 'n':
-            b = &n;
-            break;
-        case 'd':
-        case 'D':
-            b = &d;
-            break;
-        case 's':
-        case 'S':
-            b = &s;
-            break;
-        case 'l':
-        case 'L':
-            b = &l;
-            break;
-        case 'i':
-        case 'I':
-            b = &i;
-            break;
-        case 'm':
-        case 'M':
-            b = &m;
-            break;
-        case 'c':
-        case 'C':
-            b = &c;
-            break;
-        default:
-            b = NULL;
-            break;
-        }
-
-        if (!b || *b) {
-            /* drop the letter */
-            for (it2 = it; *it2; ++it2)
-                *it2 = *(it2+1);
-        } else {
-            *it = toupper(*it);
-            *b = TRUE;
-        }
-    }
-
-    gtk_entry_set_text(w, layout);
-    tree_set_string("theme/titleLayout", layout);
-
-    g_free(titlelayout);
-    titlelayout = g_strdup(layout);
-    g_free(layout);
-
-    handlers_update_theme_previews();    
-}
-
-static void set_desktop_names()
-{
-    gchar **s;
-    GList *lit;
-    xmlNodePtr n, c;
-    gint num = 0, last = -1;
-
-    n = tree_get_node("desktops/names", NULL);
-    while ((c = n->children)) {
-        xmlUnlinkNode(c);
-        xmlFreeNode(c);
-    }
-
-    for (lit = desktop_names; lit; lit = g_list_next(lit)) {
-        if (((gchar*)lit->data)[0]) /* not empty */
-            last = num;
-        ++num;
-    }
-
-    num = 0;
-    for (lit = desktop_names; lit && num <= last; lit = g_list_next(lit)) {
-        xmlNewTextChild(n, NULL, "name", lit->data);
-        ++num;
-    }
-    tree_apply();
-
-    /* make openbox re-set the property */
-    XDeleteProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(),
-                    XInternAtom(GDK_DISPLAY(), "_NET_DESKTOP_NAMES", FALSE));
-}
-
-static void set_desktop_number()
-{
-    XEvent ce;
-
-    tree_set_int("desktops/number", num_desktops);
-
-    ce.xclient.type = ClientMessage;
-    ce.xclient.message_type = XInternAtom(GDK_DISPLAY(),
-                                          "_NET_NUMBER_OF_DESKTOPS",
-                                          FALSE);
-    ce.xclient.display = GDK_DISPLAY();
-    ce.xclient.window = GDK_ROOT_WINDOW();
-    ce.xclient.format = 32;
-    ce.xclient.data.l[0] = num_desktops;
-    ce.xclient.data.l[1] = 0;
-    ce.xclient.data.l[2] = 0;
-    ce.xclient.data.l[3] = 0;
-    ce.xclient.data.l[4] = 0;
-    XSendEvent(GDK_DISPLAY(), GDK_ROOT_WINDOW(), FALSE,
-               SubstructureNotifyMask | SubstructureRedirectMask,
-               &ce);
-}
-
-void on_desktop_num_value_changed(GtkSpinButton *w, gpointer data)
-{
-    if (mapping) return;
-
-    num_desktops = gtk_spin_button_get_value(w);
-
-    set_desktop_number();
-
-    reset_desktop_names();
-}
-
-static void on_desktop_names_cell_edited(GtkCellRendererText *cell,
-                                         const gchar *path_string,
-                                         const gchar *new_text,
-                                         gpointer data)
-{
-    GtkTreePath *path;
-    GtkTreeIter it;
-    gchar *old_text;
-    GList *lit;
-    gint i;
-
-    if (mapping) return;
-
-    path = gtk_tree_path_new_from_string (path_string);
-    gtk_tree_model_get_iter(GTK_TREE_MODEL(desktop_store), &it, path);
-
-    gtk_tree_model_get(GTK_TREE_MODEL(desktop_store), &it, 0, &old_text, -1);
-    g_free(old_text);
-
-    i = gtk_tree_path_get_indices(path)[0];
-    lit = g_list_nth(desktop_names, i);
-
-    g_free(lit->data);
-    lit->data = g_strdup(new_text);
-    if (new_text[0]) /* not empty */
-        gtk_list_store_set(desktop_store, &it, 0, lit->data, -1);
-    else
-        gtk_list_store_set(desktop_store, &it, 0, _("(Unnamed desktop)"), -1);
-
-    set_desktop_names();
-}
-
-void on_install_theme_clicked(GtkButton *w, gpointer data)
-{
-    GtkWidget *d;
-    gint r;
-    gchar *path = NULL;
-    GtkFileFilter *filter;
-
-    d = gtk_file_chooser_dialog_new(_("Choose an Openbox theme"),
-                                    GTK_WINDOW(mainwin),
-                                    GTK_FILE_CHOOSER_ACTION_OPEN,
-                                    GTK_STOCK_OK, GTK_RESPONSE_OK,
-                                    GTK_STOCK_CANCEL, GTK_RESPONSE_NONE,
-                                    NULL);
-
-    gtk_file_chooser_set_show_hidden(GTK_FILE_CHOOSER(d), FALSE);
-    filter = gtk_file_filter_new();
-    gtk_file_filter_set_name(filter, _("Openbox theme archives"));
-    gtk_file_filter_add_pattern(filter, "*.obt");
-    //gtk_file_filter_add_pattern(filter, "*.tgz");
-    //gtk_file_filter_add_pattern(filter, "*.tar.gz");
-    gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(d), filter);
-
-    r = gtk_dialog_run(GTK_DIALOG(d));
-    if (r == GTK_RESPONSE_OK)
-        path = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(d));
-    gtk_widget_destroy(d);
-
-    if (path != NULL) {
-        handlers_install_theme(path);
-        g_free(path);
-    }
-}
-
-void on_theme_archive_clicked(GtkButton *w, gpointer data)
-{
-    GtkWidget *d;
-    gint r;
-    gchar *path = NULL;
-
-    d = gtk_file_chooser_dialog_new(_("Choose an Openbox theme"),
-                                    GTK_WINDOW(mainwin),
-                                    GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
-                                    GTK_STOCK_OK, GTK_RESPONSE_OK,
-                                    GTK_STOCK_CANCEL, GTK_RESPONSE_NONE,
-                                    NULL);
-
-    gtk_file_chooser_set_show_hidden(GTK_FILE_CHOOSER(d), TRUE);
-    r = gtk_dialog_run(GTK_DIALOG(d));
-    if (r == GTK_RESPONSE_OK)
-        path = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(d));
-    gtk_widget_destroy(d);
-
-    if (path != NULL) {
-        theme_archive(path);
-        g_free(path);
-    }
-}
-
-void handlers_install_theme(gchar *path)
-{
-    gchar *name;
-
-    if ((name = theme_install(path))) {
-        GtkWidget *w;
-        GtkTreePath *path;
-        GList *it;
-        gint i;
-
-        w = glade_xml_get_widget(glade, "theme_names");
-        mapping = TRUE;
-        reset_theme_names(w);
-        mapping = FALSE;
-
-        /* go to the newly installed theme */
-        for (it = themes, i = 0; it; it = g_list_next(it), ++i)
-            if (!strcmp(it->data, name)) break;
-        if (it) {
-            path = gtk_tree_path_new_from_indices(i, -1);
-            gtk_tree_view_set_cursor(GTK_TREE_VIEW(w), path, NULL, FALSE);
-            gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(w), path, NULL,
-                                         FALSE, 0, 0);
-        }
-
-        g_free(name);
-    }
-}
-
-
-static gboolean update_theme_preview_iterate(gpointer data)
-{
-    GtkListStore *ls = data;
-    static GtkTreeIter iter;
-    static gboolean restart = TRUE;
-    gchar *name;
-
-    if (restart) {
-        if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(ls), &iter))
-            return;
-        restart = FALSE;
-    } else {
-        if (!gtk_tree_model_iter_next(GTK_TREE_MODEL(ls), &iter)) {
-            restart = TRUE;
-            return;
-        }
-    }
-
-    gtk_tree_model_get(GTK_TREE_MODEL(ls), &iter, 0, &name, -1);
-
-    gtk_list_store_set(GTK_LIST_STORE(ls), &iter, 1,
-                       preview_theme(name, titlelayout, active_window_font,
-                                     inactive_window_font, menu_title_font,
-                                     menu_item_font, osd_font),
-                       -1);
-}
-
-static void handlers_update_theme_previews()
-{
-    g_idle_remove_by_data(theme_store);
-    g_idle_add_full(G_PRIORITY_LOW, update_theme_preview_iterate,
-                    theme_store, NULL);
-}
diff --git a/src/handlers.h b/src/handlers.h
deleted file mode 100644 (file)
index 2721b84..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
-
-   handlers.h for ObConf, the configuration tool for Openbox
-   Copyright (c) 2003-2007   Dana Jansens
-   Copyright (c) 2003        Tim Riley
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   See the COPYING file for a copy of the GNU General Public License.
-*/
-
-#ifndef obconf__handlers_h
-#define obconf__handlers_h
-
-void setup_behavior_tab();
-void setup_dock_tab();
-void setup_focus_mouse(GtkWidget *w);
-void setup_focus_delay(GtkWidget *w);
-void setup_focus_new(GtkWidget *w);
-void setup_focus_raise(GtkWidget *w);
-void setup_focus_desktop(GtkWidget *w);
-void setup_place_mouse(GtkWidget *w);
-void setup_resist_window(GtkWidget *w);
-void setup_resist_edge(GtkWidget *w);
-void setup_resize_contents(GtkWidget *w);
-void setup_dock_position(GtkWidget *w);
-void setup_dock_float_x(GtkWidget *w);
-void setup_dock_float_y(GtkWidget *w);
-void setup_dock_stacking(GtkWidget *top, GtkWidget *normal, GtkWidget *bottom);
-void setup_dock_direction(GtkWidget *w);
-void setup_dock_hide(GtkWidget *w);
-void setup_dock_hide_delay(GtkWidget *w);
-void setup_theme_names(GtkWidget *w);
-void setup_title_layout(GtkWidget *w);
-void setup_window_border(GtkWidget *w);
-void setup_font_active(GtkWidget *w);
-void setup_font_inactive(GtkWidget *w);
-void setup_font_menu_header(GtkWidget *w);
-void setup_font_menu_item(GtkWidget *w);
-void setup_font_display(GtkWidget *w);
-void setup_desktop_num(GtkWidget *w);
-void setup_desktop_names(GtkWidget *w);
-
-void handlers_install_theme(gchar *path);
-
-#endif
index 96c5ad5be55e163beae7103695bf48a514e8766c..d9f578d9ca3bc6236dcfb1484d2f14be8d7bf267 100644 (file)
 */
 
 #include "main.h"
-#include "handlers.h"
+#include "archive.h"
 #include "theme.h"
+#include "appearance.h"
+#include "behavior.h"
+#include "desktops.h"
+#include "dock.h"
+#include "preview_update.h"
 #include "gettext.h"
 
 #include <gdk/gdkx.h>
@@ -116,7 +121,7 @@ int main(int argc, char **argv)
     parse_args(argc, argv);
 
     if (obc_theme_archive) {
-        theme_archive(obc_theme_archive);
+        archive_create(obc_theme_archive);
         return;
     }
 
@@ -151,38 +156,42 @@ int main(int argc, char **argv)
         g_free(s);
     }
 
-    setup_behavior_tab();
-    setup_dock_tab();
-    setup_focus_mouse(glade_xml_get_widget(glade, "focus_mouse"));
-    setup_focus_raise(glade_xml_get_widget(glade, "focus_raise"));
-    setup_focus_last(glade_xml_get_widget(glade, "focus_raise"));
-    setup_focus_delay(glade_xml_get_widget(glade, "focus_delay"));
-    setup_focus_new(glade_xml_get_widget(glade, "focus_new"));
-    setup_place_mouse(glade_xml_get_widget(glade, "place_mouse"));
-    setup_resist_window(glade_xml_get_widget(glade, "resist_window"));
-    setup_resist_edge(glade_xml_get_widget(glade, "resist_edge"));
-    setup_resize_contents(glade_xml_get_widget(glade, "resize_contents"));
-    setup_dock_position(glade_xml_get_widget(glade, "dock_position"));
-    setup_dock_float_x(glade_xml_get_widget(glade, "dock_float_x"));
-    setup_dock_float_y(glade_xml_get_widget(glade, "dock_float_y"));
-    setup_dock_stacking(glade_xml_get_widget(glade, "dock_stack_top"),
-                        glade_xml_get_widget(glade, "dock_stack_normal"),
-                        glade_xml_get_widget(glade, "dock_stack_bottom"));
-    setup_dock_direction(glade_xml_get_widget(glade, "dock_direction"));
-    setup_dock_hide(glade_xml_get_widget(glade, "dock_hide"));
-    setup_dock_hide_delay(glade_xml_get_widget(glade, "dock_hide_delay"));
-    setup_theme_names(glade_xml_get_widget(glade, "theme_names"));
-    setup_title_layout(glade_xml_get_widget(glade, "title_layout"));
-    setup_desktop_num(glade_xml_get_widget(glade, "desktop_num"));
-    setup_desktop_names(glade_xml_get_widget(glade, "desktop_names"));
-    setup_window_border(glade_xml_get_widget(glade, "window_border"));
-    setup_font_active(glade_xml_get_widget(glade, "font_active"));
-    setup_font_inactive(glade_xml_get_widget(glade, "font_inactive"));
-    setup_font_menu_header(glade_xml_get_widget(glade, "font_menu_header"));
-    setup_font_menu_item(glade_xml_get_widget(glade, "font_menu_item"));
-    setup_font_display(glade_xml_get_widget(glade, "font_display"));
-
-    mainwin = glade_xml_get_widget(glade, "main_window");
+    theme_setup_names(get_widget("theme_names"));
+
+    appr_setup_window_border(get_widget("window_border"));
+    appr_setup_title_layout(get_widget("title_layout"));
+    appr_setup_font_active(get_widget("font_active"));
+    appr_setup_font_inactive(get_widget("font_inactive"));
+    appr_setup_font_menu_header(get_widget("font_menu_header"));
+    appr_setup_font_menu_item(get_widget("font_menu_item"));
+    appr_setup_font_display(get_widget("font_display"));
+
+    behavior_setup_tab();
+    behavior_setup_focus_mouse(get_widget("focus_mouse"));
+    behavior_setup_focus_raise(get_widget("focus_raise"));
+    behavior_setup_focus_last(get_widget("focus_raise"));
+    behavior_setup_focus_delay(get_widget("focus_delay"));
+    behavior_setup_focus_new(get_widget("focus_new"));
+    behavior_setup_place_mouse(get_widget("place_mouse"));
+    behavior_setup_resist_window(get_widget("resist_window"));
+    behavior_setup_resist_edge(get_widget("resist_edge"));
+    behavior_setup_resize_contents(get_widget("resize_contents"));
+
+    desktops_setup_num(get_widget("desktop_num"));
+    desktops_setup_names(get_widget("desktop_names"));
+
+    dock_setup_tab();
+    dock_setup_position(get_widget("dock_position"));
+    dock_setup_float_x(get_widget("dock_float_x"));
+    dock_setup_float_y(get_widget("dock_float_y"));
+    dock_setup_stacking(get_widget("dock_stack_top"),
+                        get_widget("dock_stack_normal"),
+                        get_widget("dock_stack_bottom"));
+    dock_setup_direction(get_widget("dock_direction"));
+    dock_setup_hide(get_widget("dock_hide"));
+    dock_setup_hide_delay(get_widget("dock_hide_delay"));
+
+    mainwin = get_widget("main_window");
 
     sn_d = sn_display_new(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()),
                           NULL, NULL);
@@ -205,13 +214,32 @@ int main(int argc, char **argv)
     sn_display_unref(sn_d);
 
     if (obc_theme_install)
-        handlers_install_theme(obc_theme_install);
+        theme_install(obc_theme_install);
 
     gtk_main();
 
+    preview_update_set_list_store(NULL);
+    preview_update_set_active_font(NULL);
+    preview_update_set_inactive_font(NULL);
+    preview_update_set_menu_header_font(NULL);
+    preview_update_set_menu_item_font(NULL);
+    preview_update_set_osd_font(NULL);
+    preview_update_set_title_layout(NULL);
+
     RrInstanceFree(rrinst);
     parse_paths_shutdown();
 
     xmlFreeDoc(doc);
     return 0;
 }
+
+gboolean on_main_window_delete_event(GtkWidget *w, GdkEvent *e, gpointer d)
+{
+    gtk_main_quit();
+    return FALSE;
+}
+
+void on_close_clicked()
+{
+    gtk_main_quit();
+}
index b560e55399ff8919c90929393bbcbf008af9dd4f..9a1bf2cd8e95a088d4cb970199f9759831d949e8 100644 (file)
@@ -32,6 +32,8 @@ extern xmlNodePtr root;
 extern RrInstance *rrinst;
 extern GtkWidget *mainwin;
 
+#define get_widget(s) glade_xml_get_widget(glade, s)
+
 void obconf_error(gchar *msg);
 
 #endif
diff --git a/src/preview_update.c b/src/preview_update.c
new file mode 100644 (file)
index 0000000..64a5fec
--- /dev/null
@@ -0,0 +1,106 @@
+#include "preview_update.h"
+
+static gboolean restart_theme_preview_update = TRUE;
+
+static GtkListStore *list_store           = NULL;
+static gchar        *title_layout         = NULL;
+static RrFont       *active_window_font   = NULL;
+static RrFont       *inactive_window_font = NULL;
+static RrFont       *menu_title_font      = NULL;
+static RrFont       *menu_item_font       = NULL;
+static RrFont       *osd_font             = NULL;
+
+static gboolean update_theme_preview_iterate(gpointer data);
+
+void preview_update_all()
+{
+    if (!list_store) return;
+
+    g_idle_remove_by_data(list_store);
+
+    if (!(title_layout && active_window_font && inactive_window_font &&
+          menu_title_font && menu_item_font && osd_font))
+        return; /* not set up */
+
+    restart_theme_preview_update = TRUE;
+    g_idle_add_full(G_PRIORITY_LOW,
+                    update_theme_preview_iterate,
+                    list_store, NULL);
+}
+
+void preview_update_set_list_store(GtkListStore *ls)
+{
+    if (list_store) g_idle_remove_by_data(list_store);
+
+    list_store = ls;
+
+    if (list_store) preview_update_all();
+}
+
+void preview_update_set_active_font(RrFont *f)
+{
+    RrFontClose(active_window_font);
+    active_window_font = f;
+    preview_update_all();
+}
+
+void preview_update_set_inactive_font(RrFont *f)
+{
+    RrFontClose(inactive_window_font);
+    inactive_window_font = f;
+    preview_update_all();
+}
+
+void preview_update_set_menu_header_font(RrFont *f)
+{
+    RrFontClose(menu_title_font);
+    menu_title_font = f;
+    preview_update_all();
+}
+
+void preview_update_set_menu_item_font(RrFont *f)
+{
+    RrFontClose(menu_item_font);
+    menu_item_font = f;
+    preview_update_all();
+}
+
+void preview_update_set_osd_font(RrFont *f)
+{
+    RrFontClose(osd_font);
+    osd_font = f;
+    preview_update_all();
+}
+
+void preview_update_set_title_layout(const gchar *layout)
+{
+    g_free(title_layout);
+    title_layout = g_strdup(layout);
+    preview_update_all();
+}
+
+static gboolean update_theme_preview_iterate(gpointer data)
+{
+    GtkListStore *ls = data;
+    static GtkTreeIter iter;
+    gchar *name;
+
+    if (restart_theme_preview_update) {
+        if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(ls), &iter))
+            return;
+        restart_theme_preview_update = FALSE;
+    } else {
+        if (!gtk_tree_model_iter_next(GTK_TREE_MODEL(ls), &iter)) {
+            restart_theme_preview_update = TRUE;
+            return;
+        }
+    }
+
+    gtk_tree_model_get(GTK_TREE_MODEL(ls), &iter, 0, &name, -1);
+
+    gtk_list_store_set(GTK_LIST_STORE(ls), &iter, 1,
+                       preview_theme(name, title_layout, active_window_font,
+                                     inactive_window_font, menu_title_font,
+                                     menu_item_font, osd_font),
+                       -1);
+}
diff --git a/src/preview_update.h b/src/preview_update.h
new file mode 100644 (file)
index 0000000..6d5b788
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef obconf__preview_update_h
+#define obconf__preview_update_h
+
+#include <openbox/render.h>
+#include <gtk/gtk.h>
+
+void preview_update_all();
+
+void preview_update_set_list_store       (GtkListStore *ls);
+void preview_update_set_active_font      (RrFont *f);
+void preview_update_set_inactive_font    (RrFont *f);
+void preview_update_set_menu_header_font (RrFont *f);
+void preview_update_set_menu_item_font   (RrFont *f);
+void preview_update_set_osd_font         (RrFont *f);
+void preview_update_set_title_layout     (const gchar *layout);
+
+#endif
index 9abb6b23b67c8792e8cf40c1588ad641eb2dfeeb..3aa9605426f59d442521490aa1fd8a9b6fc6c95a 100644 (file)
-#include "theme.h"
 #include "main.h"
+#include "tree.h"
+#include "preview_update.h"
 #include "gettext.h"
+#include "archive.h"
+#include "theme.h"
 
-#include <string.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#define gtk_msg(type, args...) \
-{                                                                        \
-    GtkWidget *msgw;                                                     \
-    msgw = gtk_message_dialog_new(GTK_WINDOW(mainwin),                   \
-                                  GTK_DIALOG_DESTROY_WITH_PARENT |       \
-                                  GTK_DIALOG_MODAL,                      \
-                                  type,                                  \
-                                  GTK_BUTTONS_OK,                        \
-                                  args);                                 \
-    gtk_dialog_run(GTK_DIALOG(msgw));                                    \
-    gtk_widget_destroy(msgw);                                            \
-}
+static gboolean mapping = FALSE;
 
-static gchar *get_theme_dir();
-static gboolean change_dir(const gchar *dir);
-static gchar* name_from_file(const gchar *path);
-static gchar* name_from_dir(const gchar *dir);
-static gboolean install_theme_to(const gchar *name, const gchar *file,
-                                 const gchar *to);
-static gboolean create_theme_archive(const gchar *dir, const gchar *name,
-                                     const gchar *to);
+static GList *themes;
+static GtkListStore *theme_store;
 
-gchar* theme_install(gchar *path)
+static void add_theme_dir(const gchar *dirname);
+static void reset_theme_names(GtkWidget *w);
+static void on_theme_names_selection_changed(GtkTreeSelection *sel,
+                                             gpointer data);
+
+void theme_setup_names(GtkWidget *w)
 {
-    gchar *dest;
-    gchar *name;
+    GtkCellRenderer *render;
+    GtkTreeViewColumn *column;
+    GtkTreeSelection *select;
 
-    if (!(dest = get_theme_dir()))
-        return NULL;
+    mapping = TRUE;
 
-    if (!(name = name_from_file(path)))
-        return NULL;
+    /* widget setup */
+    theme_store = gtk_list_store_new(2, G_TYPE_STRING, GDK_TYPE_PIXBUF);
+    gtk_tree_view_set_model(GTK_TREE_VIEW(w), GTK_TREE_MODEL(theme_store));
+    preview_update_set_list_store(theme_store);
+    g_object_unref (theme_store);
 
-    if (install_theme_to(name, path, dest)) {
-        gtk_msg(GTK_MESSAGE_INFO, _("\"%s\" was installed to %s"), name, dest);
-    } else {
-        g_free(name);
-        name = NULL;
-    }
+    gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(w)),
+                                GTK_SELECTION_SINGLE);
+
+    /* text column for the names */
+    render = gtk_cell_renderer_text_new();
+    column = gtk_tree_view_column_new_with_attributes
+        ("Name", render, "text", 0, NULL);
+    gtk_tree_view_append_column(GTK_TREE_VIEW(w), column);
+
+    /* pixbuf column, for theme previews */
+    render = gtk_cell_renderer_pixbuf_new();
+    g_object_set(render, "xalign", 1.0);
+    column = gtk_tree_view_column_new_with_attributes
+        ("Preview", render, "pixbuf", 1, NULL);
+    gtk_tree_view_append_column(GTK_TREE_VIEW(w), column);
 
-    g_free(dest);
 
-    return name;
+    /* setup the selection handler */
+    select = gtk_tree_view_get_selection(GTK_TREE_VIEW (w));
+    gtk_tree_selection_set_mode(select, GTK_SELECTION_SINGLE);
+    g_signal_connect (G_OBJECT(select), "changed",
+                      G_CALLBACK(on_theme_names_selection_changed),
+                      NULL);
+
+    reset_theme_names(w);
+
+    mapping = FALSE;
 }
 
-void theme_archive(gchar *path)
+static void on_theme_names_selection_changed(GtkTreeSelection *sel,
+                                             gpointer data)
 {
-    gchar *name;
-    gchar *dest;
+    GtkTreeIter iter;
+    GtkTreeModel *model;
+    const gchar *name;
 
-    if (!(name = name_from_dir(path)))
-        return;
+    if (mapping) return;
 
-    {
-        gchar *file;
-        file = g_strdup_printf("%s.obt", name);
-        dest = g_build_path(G_DIR_SEPARATOR_S,
-                            g_get_current_dir(), file, NULL);
-        g_free(file);
+    if(gtk_tree_selection_get_selected(sel, &model, &iter)) {
+        gtk_tree_model_get(model, &iter, 0, &name, -1);
     }
 
-    if (create_theme_archive(path, name, dest))
-        gtk_msg(GTK_MESSAGE_INFO, _("\"%s\" was successfully created"),
-                dest);
-
-    g_free(dest);
-    g_free(name);
+    if(name)
+      tree_set_string("theme/name", name);
 }
 
-static gboolean create_theme_archive(const gchar *dir, const gchar *name,
-                                     const gchar *to)
+void on_install_theme_clicked(GtkButton *w, gpointer data)
 {
-    gchar *glob;
-    gchar **argv;
-    gchar *errtxt = NULL;
-    gchar *parentdir;
-    gint exitcode;
-    GError *e = NULL;
-
-    glob = g_strdup_printf("%s/openbox-3/", name);
-
-    parentdir = g_build_path(G_DIR_SEPARATOR_S, dir, "..", NULL);
-
-    argv = g_new(gchar*, 7);
-    argv[0] = g_strdup("tar");
-    argv[1] = g_strdup("-c");
-    argv[2] = g_strdup("-z");
-    argv[3] = g_strdup("-f");
-    argv[4] = g_strdup(to);
-    argv[5] = g_strdup(glob);
-    argv[6] = NULL;
-    if (g_spawn_sync(parentdir, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL,
-                     NULL, &errtxt, &exitcode, &e))
-    {
-        if (exitcode != EXIT_SUCCESS)
-            gtk_msg(GTK_MESSAGE_ERROR,
-                    _("Unable to create the theme archive \"%s\".\nThe following errors were reported:\n%s"),
-                    to, errtxt);
-
+    GtkWidget *d;
+    gint r;
+    gchar *path = NULL;
+    GtkFileFilter *filter;
+
+    d = gtk_file_chooser_dialog_new(_("Choose an Openbox theme"),
+                                    GTK_WINDOW(mainwin),
+                                    GTK_FILE_CHOOSER_ACTION_OPEN,
+                                    GTK_STOCK_OK, GTK_RESPONSE_OK,
+                                    GTK_STOCK_CANCEL, GTK_RESPONSE_NONE,
+                                    NULL);
+
+    gtk_file_chooser_set_show_hidden(GTK_FILE_CHOOSER(d), FALSE);
+    filter = gtk_file_filter_new();
+    gtk_file_filter_set_name(filter, _("Openbox theme archives"));
+    gtk_file_filter_add_pattern(filter, "*.obt");
+    //gtk_file_filter_add_pattern(filter, "*.tgz");
+    //gtk_file_filter_add_pattern(filter, "*.tar.gz");
+    gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(d), filter);
+
+    r = gtk_dialog_run(GTK_DIALOG(d));
+    if (r == GTK_RESPONSE_OK)
+        path = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(d));
+    gtk_widget_destroy(d);
+
+    if (path != NULL) {
+        theme_install(path);
+        g_free(path);
     }
-    else
-        gtk_msg(GTK_MESSAGE_ERROR, _("Unable to run the \"tar\" command: %s"),
-                e->message);
-
-    g_strfreev(argv);
-    if (e) g_error_free(e);
-    g_free(errtxt);
-    g_free(parentdir);
-    g_free(glob);
-    return exitcode == EXIT_SUCCESS;
 }
 
-static gchar *get_theme_dir()
+void on_theme_archive_clicked(GtkButton *w, gpointer data)
 {
-    gchar *dir;
+    GtkWidget *d;
     gint r;
-
-    dir = g_build_path(G_DIR_SEPARATOR_S, g_get_home_dir(), ".themes", NULL);
-    r = mkdir(dir, 0777);
-    if (r == -1 && errno != EEXIST) {
-        gtk_msg(GTK_MESSAGE_ERROR,
-                _("Unable to create directory \"%s\": %s"),
-                dir, strerror(errno));
-        g_free(dir);
-        dir = NULL;
+    gchar *path = NULL;
+
+    d = gtk_file_chooser_dialog_new(_("Choose an Openbox theme"),
+                                    GTK_WINDOW(mainwin),
+                                    GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
+                                    GTK_STOCK_OK, GTK_RESPONSE_OK,
+                                    GTK_STOCK_CANCEL, GTK_RESPONSE_NONE,
+                                    NULL);
+
+    gtk_file_chooser_set_show_hidden(GTK_FILE_CHOOSER(d), TRUE);
+    r = gtk_dialog_run(GTK_DIALOG(d));
+    if (r == GTK_RESPONSE_OK)
+        path = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(d));
+    gtk_widget_destroy(d);
+
+    if (path != NULL) {
+        archive_create(path);
+        g_free(path);
     }
-
-    return dir;
 }
 
-static gchar* name_from_dir(const gchar *dir)
+void theme_install(const gchar *path)
 {
-    gchar *rc;
-    struct stat st;
-    gboolean r;
-
-    rc = g_build_path(G_DIR_SEPARATOR_S, dir, "openbox-3", "themerc", NULL);
+    gchar *name;
 
-    r = (stat(rc, &st) == 0 && S_ISREG(st.st_mode));
-    g_free(rc);
+    if ((name = archive_install(path))) {
+        GtkWidget *w;
+        GtkTreePath *path;
+        GList *it;
+        gint i;
+
+        w = glade_xml_get_widget(glade, "theme_names");
+        mapping = TRUE;
+        reset_theme_names(w);
+        mapping = FALSE;
+
+        /* go to the newly installed theme */
+        for (it = themes, i = 0; it; it = g_list_next(it), ++i)
+            if (!strcmp(it->data, name)) break;
+        if (it) {
+            path = gtk_tree_path_new_from_indices(i, -1);
+            gtk_tree_view_set_cursor(GTK_TREE_VIEW(w), path, NULL, FALSE);
+            gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(w), path, NULL,
+                                         FALSE, 0, 0);
+        }
 
-    if (!r) {
-        gtk_msg(GTK_MESSAGE_ERROR,
-                _("\"%s\" does not appear to be a valid Openbox theme directory"),
-                dir);
-        return NULL;
+        g_free(name);
     }
-    return g_path_get_basename(dir);
 }
 
-static gchar* name_from_file(const gchar *path)
+
+
+
+
+
+static void reset_theme_names(GtkWidget *w)
 {
-    /* decipher the theme name from the file name */
-    gchar *fname = g_path_get_basename(path);
-    gint len = strlen(fname);
-    gchar *name = NULL;
-
-    if (len > 4 &&
-        (fname[len-4] == '.' && fname[len-3] == 'o' &&
-         fname[len-2] == 'b' && fname[len-1] == 't'))
+    gchar *name;
+    gchar *p;
+    GList *it, *next;
+    gint i;
+
+    RrFont *active, *inactive, *menu_t, *menu_i, *osd;
+
+    name = tree_get_string("theme/name", "TheBear");
+
+    for (it = themes; it; it = g_list_next(it))
+        g_free(it->data);
+    g_list_free(themes);
+    themes = NULL;
+
+    p = g_build_filename(g_get_home_dir(), ".themes", NULL);
+    add_theme_dir(p);
+    g_free(p);
+
     {
-        fname[len-4] = '\0';
-        name = g_strdup(fname);
-        fname[len-4] = '.';
+        GSList *it;
+        for (it = parse_xdg_data_dir_paths(); it; it = g_slist_next(it)) {
+            p = g_build_filename(it->data, "themes", NULL);
+            add_theme_dir(p);
+            g_free(p);
+        }
     }
 
-    if (name == NULL)
-        gtk_msg(GTK_MESSAGE_ERROR,
-                _("Unable to determine the theme's name from \"%s\".  File name should be ThemeName.obt."), fname);
+    add_theme_dir(THEMEDIR);
 
-    return name;
-}
+    themes = g_list_sort(themes, (GCompareFunc) strcasecmp);
 
-static gboolean change_dir(const gchar *dir)
-{
-    if (chdir(dir) == -1) {
-        gtk_msg(GTK_MESSAGE_ERROR, _("Unable to move to directory \"%s\": %s"),
-                dir, strerror(errno));
-        return FALSE;
+    gtk_list_store_clear(theme_store);
+
+    /* return to regular scheduled programming */
+    i = 0;
+    for (it = themes; it; it = next) {
+        GtkTreeIter iter;
+
+        next = g_list_next(it);
+
+        /* remove duplicates */
+        if (next && !strcmp(it->data, next->data)) {
+            g_free(it->data);
+            themes = g_list_delete_link(themes, it);
+            continue;
+        }
+
+        gtk_list_store_append(theme_store, &iter);
+        gtk_list_store_set(theme_store, &iter,
+                           0, it->data,
+                           1, NULL,
+                           -1);
+
+        if(!strcmp(name, it->data)) {
+            GtkTreePath *path;
+            path = gtk_tree_path_new_from_indices(i, -1);
+            gtk_tree_view_set_cursor(GTK_TREE_VIEW(w), path, NULL, FALSE);
+            gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(w), path, NULL,
+                                         FALSE, 0, 0);
+        }
+
+
+        ++i;
     }
-    return TRUE;
+
+    preview_update_all();
+
+    g_free(name);
 }
 
-static gboolean install_theme_to(const gchar *name, const gchar *file,
-                                 const gchar *to)
+static void add_theme_dir(const gchar *dirname)
 {
-    gchar *glob;
-    gchar **argv;
-    gchar *errtxt = NULL;
-    gint exitcode;
-    GError *e = NULL;
-
-    glob = g_strdup_printf("%s/openbox-3/", name);
-
-    argv = g_new(gchar*, 7);
-    argv[0] = g_strdup("tar");
-    argv[1] = g_strdup("-x");
-    argv[2] = g_strdup("-z");
-    argv[3] = g_strdup("-f");
-    argv[4] = g_strdup(file);
-    argv[5] = g_strdup(glob);
-    argv[6] = NULL;
-    if (!g_spawn_sync(to, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL,
-                      NULL, &errtxt, &exitcode, &e))
-        gtk_msg(GTK_MESSAGE_ERROR, _("Unable to run the \"tar\" command: %s"),
-                e->message);
-    g_strfreev(argv);
-    if (e) g_error_free(e);
-
-    if (exitcode != EXIT_SUCCESS)
-        gtk_msg(GTK_MESSAGE_ERROR,
-                _("Unable to extract the file \"%s\".\nPlease ensure that \"%s\" is writable and that the file is a valid Openbox theme archive.\nThe following errors were reported:\n%s"),
-                file, to, errtxt);
-
-    g_free(errtxt);
-    g_free(glob);
-    return exitcode == EXIT_SUCCESS;
+    GDir *dir;
+    const gchar *n;
+
+    if ((dir = g_dir_open(dirname, 0, NULL))) {
+        while ((n = g_dir_read_name(dir))) {
+            {
+                gchar *full;
+                full = g_build_filename(dirname, n, "openbox-3",
+                                        "themerc", NULL);
+                if (!g_file_test(full,
+                                 G_FILE_TEST_IS_REGULAR |
+                                 G_FILE_TEST_IS_SYMLINK))
+                    n = NULL;
+                g_free(full);
+            }
+
+            if (n) {
+                themes = g_list_append(themes, g_strdup(n));
+            }
+        }
+        g_dir_close(dir);
+    }
 }
+
index 2d45b9cbf954b66b35dd0bc194c8cb1552671527..e86bbf91e5ea0504def20310037acb523a1c2a52 100644 (file)
@@ -1,10 +1,10 @@
-#ifndef __install_h
-#define __install_h
+#ifndef obconf__theme_h
+#define obconf__theme_h
 
-#include <glib.h>
+#include <gtk/gtk.h>
 
-gchar* theme_install(gchar *path);
+void theme_setup_names (GtkWidget *w);
 
-void theme_archive(gchar *path);
+void theme_install     (const gchar *path);
 
 #endif