summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/gdm-control/Makefile4
-rw-r--r--tools/gdm-control/gdm-control.c295
-rw-r--r--tools/gnome-panel-control/Makefile4
-rw-r--r--tools/gnome-panel-control/gnome-panel-control.c100
-rw-r--r--tools/obxprop/Makefile4
-rw-r--r--tools/obxprop/obxprop.c351
-rwxr-xr-xtools/themeupdate/themeupdate.py410
7 files changed, 1168 insertions, 0 deletions
diff --git a/tools/gdm-control/Makefile b/tools/gdm-control/Makefile
new file mode 100644
index 0000000..cfc4653
--- /dev/null
+++ b/tools/gdm-control/Makefile
@@ -0,0 +1,4 @@
+all clean install:
+ $(MAKE) -C ../.. -$(MAKEFLAGS) $@
+
+.PHONY: all clean install
diff --git a/tools/gdm-control/gdm-control.c b/tools/gdm-control/gdm-control.c
new file mode 100644
index 0000000..db28841
--- /dev/null
+++ b/tools/gdm-control/gdm-control.c
@@ -0,0 +1,295 @@
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xauth.h>
+
+#include <glib.h>
+
+typedef enum
+{
+ INVALID,
+ NONE,
+ SHUTDOWN,
+ REBOOT,
+ SUSPEND,
+ SWITCHUSER
+} Action;
+
+#define GDM_PROTOCOL_SOCKET_PATH1 "/var/run/gdm_socket"
+#define GDM_PROTOCOL_SOCKET_PATH2 "/tmp/.gdm_socket"
+
+#define GDM_PROTOCOL_MSG_CLOSE "CLOSE"
+#define GDM_PROTOCOL_MSG_VERSION "VERSION"
+#define GDM_PROTOCOL_MSG_AUTHENTICATE "AUTH_LOCAL"
+#define GDM_PROTOCOL_MSG_QUERY_ACTION "QUERY_LOGOUT_ACTION"
+#define GDM_PROTOCOL_MSG_SET_ACTION "SET_SAFE_LOGOUT_ACTION"
+#define GDM_PROTOCOL_MSG_FLEXI_XSERVER "FLEXI_XSERVER"
+
+#define GDM_ACTION_STR_NONE GDM_PROTOCOL_MSG_SET_ACTION" NONE"
+#define GDM_ACTION_STR_SHUTDOWN GDM_PROTOCOL_MSG_SET_ACTION" HALT"
+#define GDM_ACTION_STR_REBOOT GDM_PROTOCOL_MSG_SET_ACTION" REBOOT"
+#define GDM_ACTION_STR_SUSPEND GDM_PROTOCOL_MSG_SET_ACTION" SUSPEND"
+
+#define GDM_MIT_MAGIC_COOKIE_LEN 16
+
+static int fd = 0;
+
+static void gdm_disconnect()
+{
+ if (fd > 0)
+ close(fd);
+ fd = 0;
+}
+
+static char* get_display_number(void)
+{
+ char *display_name;
+ char *retval;
+ char *p;
+
+ display_name = XDisplayName(NULL);
+
+ p = strchr(display_name, ':');
+ if (!p)
+ return g_strdup ("0");
+
+ while (*p == ':') p++;
+
+ retval = g_strdup (p);
+
+ p = strchr (retval, '.');
+ if (p != NULL)
+ *p = '\0';
+
+ return retval;
+}
+
+static char* gdm_send_protocol_msg (const char *msg)
+{
+ GString *retval;
+ char buf[256];
+ char *p;
+ int len;
+
+ p = g_strconcat(msg, "\n", NULL);
+ if (write (fd, p, strlen(p)) < 0) {
+ g_free (p);
+
+ g_warning ("Failed to send message to GDM: %s",
+ g_strerror (errno));
+ return NULL;
+ }
+ g_free (p);
+
+ p = NULL;
+ retval = NULL;
+ while ((len = read(fd, buf, sizeof(buf) - 1)) > 0) {
+ buf[len] = '\0';
+
+ if (!retval)
+ retval = g_string_new(buf);
+ else
+ retval = g_string_append(retval, buf);
+
+ if ((p = strchr(retval->str, '\n')))
+ break;
+ }
+
+ if (p) *p = '\0';
+
+ return retval ? g_string_free(retval, FALSE) : NULL;
+}
+
+static gboolean gdm_authenticate()
+{
+ FILE *f;
+ Xauth *xau;
+ const char *xau_path;
+ char *display_number;
+ gboolean retval;
+
+ if (!(xau_path = XauFileName()))
+ return FALSE;
+
+ if (!(f = fopen(xau_path, "r")))
+ return FALSE;
+
+ retval = FALSE;
+ display_number = get_display_number();
+
+ while ((xau = XauReadAuth(f))) {
+ char buffer[40]; /* 2*16 == 32, so 40 is enough */
+ char *msg;
+ char *response;
+ int i;
+
+ if (xau->family != FamilyLocal ||
+ strncmp (xau->number, display_number, xau->number_length) ||
+ strncmp (xau->name, "MIT-MAGIC-COOKIE-1", xau->name_length) ||
+ xau->data_length != GDM_MIT_MAGIC_COOKIE_LEN)
+ {
+ XauDisposeAuth(xau);
+ continue;
+ }
+
+ for (i = 0; i < GDM_MIT_MAGIC_COOKIE_LEN; i++)
+ g_snprintf(buffer + 2*i, 3, "%02x", (guint)(guchar)xau->data[i]);
+
+ XauDisposeAuth(xau);
+
+ msg = g_strdup_printf(GDM_PROTOCOL_MSG_AUTHENTICATE " %s", buffer);
+ response = gdm_send_protocol_msg(msg);
+ g_free (msg);
+
+ if (response && !strcmp(response, "OK")) {
+ /*auth_cookie = g_strdup(buffer);*/
+ g_free(response);
+ retval = TRUE;
+ break;
+ }
+
+ g_free (response);
+ }
+
+ fclose(f);
+ return retval;
+}
+
+static gboolean gdm_connect()
+{
+ struct sockaddr_un addr;
+ char *response;
+
+ assert(fd <= 0);
+
+ fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (fd < 0) {
+ g_warning("Failed to create GDM socket: %s", g_strerror (errno));
+ gdm_disconnect();
+ return FALSE;
+ }
+
+ if (g_file_test(GDM_PROTOCOL_SOCKET_PATH1, G_FILE_TEST_EXISTS))
+ strcpy(addr.sun_path, GDM_PROTOCOL_SOCKET_PATH1);
+ else
+ strcpy(addr.sun_path, GDM_PROTOCOL_SOCKET_PATH2);
+
+ addr.sun_family = AF_UNIX;
+
+ if (connect(fd, (struct sockaddr *) &addr, sizeof (addr)) < 0) {
+ g_warning("Failed to establish a connection with GDM: %s",
+ g_strerror(errno));
+ gdm_disconnect();
+ return FALSE;
+ }
+
+ response = gdm_send_protocol_msg(GDM_PROTOCOL_MSG_VERSION);
+ if (!response || strncmp(response, "GDM ", strlen("GDM ") != 0)) {
+ g_free(response);
+
+ g_warning("Failed to get protocol version from GDM");
+ gdm_disconnect();
+ return FALSE;
+ }
+ g_free(response);
+
+ if (!gdm_authenticate()) {
+ g_warning("Failed to authenticate with GDM");
+ gdm_disconnect();
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+int main(int argc, char **argv)
+{
+ int i;
+ Action a = INVALID;
+
+ for (i = 1; i < argc; ++i) {
+ if (!strcmp(argv[i], "--help")) {
+ a = INVALID;
+ break;
+ }
+ if (!strcmp(argv[i], "--none")) {
+ a = NONE;
+ break;
+ }
+ if (!strcmp(argv[i], "--shutdown")) {
+ a = SHUTDOWN;
+ break;
+ }
+ if (!strcmp(argv[i], "--reboot")) {
+ a = REBOOT;
+ break;
+ }
+ if (!strcmp(argv[i], "--suspend")) {
+ a = SUSPEND;
+ break;
+ }
+ if (!strcmp(argv[i], "--switch-user")) {
+ a = SWITCHUSER;
+ break;
+ }
+ }
+
+ if (!a) {
+ printf("Usage: gdm-control ACTION\n\n");
+ printf("Actions:\n");
+ printf(" --help Display this help and exit\n");
+ printf(" --none Do nothing special when the current session ends\n");
+ printf(" --shutdown Shutdown the computer when the current session ends\n");
+ printf(" --reboot Reboot the computer when the current session ends\n");
+ printf(" --suspend Suspend the computer when the current session ends\n");
+ printf(" --switch-user Log in as a new user (this works immediately)\n\n");
+ return 0;
+ }
+
+ {
+ char *d, *response;
+ const char *action_string;
+
+ d = XDisplayName(NULL);
+ if (!d) {
+ fprintf(stderr,
+ "Unable to find the X display specified by the DISPLAY "
+ "environment variable. Ensure that it is set correctly.");
+ return 1;
+ }
+
+ switch (a) {
+ case NONE:
+ action_string = GDM_ACTION_STR_NONE;
+ break;
+ case SHUTDOWN:
+ action_string = GDM_ACTION_STR_SHUTDOWN;
+ break;
+ case REBOOT:
+ action_string = GDM_ACTION_STR_REBOOT;
+ break;
+ case SUSPEND:
+ action_string = GDM_ACTION_STR_SUSPEND;
+ break;
+ case SWITCHUSER:
+ action_string = GDM_PROTOCOL_MSG_FLEXI_XSERVER;
+ break;
+ default:
+ assert(0);
+ }
+
+ if (gdm_connect()) {
+ response = gdm_send_protocol_msg(action_string);
+ g_free(response);
+ gdm_disconnect();
+ }
+ }
+
+ return 0;
+}
diff --git a/tools/gnome-panel-control/Makefile b/tools/gnome-panel-control/Makefile
new file mode 100644
index 0000000..cfc4653
--- /dev/null
+++ b/tools/gnome-panel-control/Makefile
@@ -0,0 +1,4 @@
+all clean install:
+ $(MAKE) -C ../.. -$(MAKEFLAGS) $@
+
+.PHONY: all clean install
diff --git a/tools/gnome-panel-control/gnome-panel-control.c b/tools/gnome-panel-control/gnome-panel-control.c
new file mode 100644
index 0000000..67aa039
--- /dev/null
+++ b/tools/gnome-panel-control/gnome-panel-control.c
@@ -0,0 +1,100 @@
+#include <X11/Xlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+
+typedef enum
+{
+ NONE,
+ MAIN_MENU,
+ RUN_DIALOG
+} Action;
+
+int main(int argc, char **argv)
+{
+ int i;
+ Action a = NONE;
+
+ for (i = 1; i < argc; ++i) {
+ if (!strcmp(argv[i], "--help")) {
+ a = NONE;
+ break;
+ }
+ if (!strcmp(argv[i], "--main-menu")) {
+ a = MAIN_MENU;
+ break;
+ }
+ if (!strcmp(argv[i], "--run-dialog")) {
+ a = RUN_DIALOG;
+ break;
+ }
+ }
+
+ if (!a) {
+ printf("Usage: gnome-panel-control ACTION\n\n");
+ printf("Actions:\n");
+ printf(" --help Display this help and exit\n");
+ printf(" --main-menu Show the main menu\n");
+ printf(" --run-dialog Show the run dialog\n\n");
+ return 0;
+ }
+
+ {
+ Display *d;
+ Window root;
+ XClientMessageEvent ce;
+ Atom act_atom;
+ Time timestamp;
+
+ d = XOpenDisplay(NULL);
+ if (!d) {
+ fprintf(stderr,
+ "Unable to open the X display specified by the DISPLAY "
+ "environment variable. Ensure you have permission to "
+ "connect to the display.");
+ return 1;
+ }
+ root = RootWindowOfScreen(DefaultScreenOfDisplay(d));
+
+ switch (a) {
+ case MAIN_MENU:
+ act_atom = XInternAtom(d, "_GNOME_PANEL_ACTION_MAIN_MENU", False);
+ break;
+ case RUN_DIALOG:
+ act_atom = XInternAtom(d, "_GNOME_PANEL_ACTION_RUN_DIALOG", False);
+ break;
+ default:
+ assert(0);
+ }
+
+ /* Generate a timestamp */
+ {
+ XEvent event;
+ Window win;
+
+ win = XCreateSimpleWindow(d, root, 0, 0, 1, 1, 0, 0, 0);
+
+ XSelectInput(d, win, PropertyChangeMask);
+
+ XChangeProperty(d, win, act_atom, act_atom, 8,
+ PropModeAppend, NULL, 0);
+ XWindowEvent(d, win, PropertyChangeMask, &event);
+
+ XDestroyWindow(d, win);
+
+ timestamp = event.xproperty.time;
+ }
+
+ ce.type = ClientMessage;
+ ce.window = root;
+ ce.message_type = XInternAtom(d, "_GNOME_PANEL_ACTION", False);
+ ce.format = 32;
+ ce.data.l[0] = act_atom;
+ ce.data.l[1] = timestamp;
+ XSendEvent(d, root, False, StructureNotifyMask, (XEvent*) &ce);
+
+ XCloseDisplay(d);
+ }
+
+ return 0;
+}
diff --git a/tools/obxprop/Makefile b/tools/obxprop/Makefile
new file mode 100644
index 0000000..cfc4653
--- /dev/null
+++ b/tools/obxprop/Makefile
@@ -0,0 +1,4 @@
+all clean install:
+ $(MAKE) -C ../.. -$(MAKEFLAGS) $@
+
+.PHONY: all clean install
diff --git a/tools/obxprop/obxprop.c b/tools/obxprop/obxprop.c
new file mode 100644
index 0000000..83ff54a
--- /dev/null
+++ b/tools/obxprop/obxprop.c
@@ -0,0 +1,351 @@
+#include <X11/Xlib.h>
+#include <X11/cursorfont.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+#include <glib.h>
+
+gint fail(const gchar *s) {
+ if (s)
+ fprintf(stderr, "%s\n", s);
+ else
+ fprintf
+ (stderr,
+ "Usage: obxprop [OPTIONS] [--] [PROPERTIES ...]\n\n"
+ "Options:\n"
+ " --help Display this help and exit\n"
+ " --display DISPLAY Connect to this X display\n"
+ " --id ID Show the properties for this window\n"
+ " --root Show the properties for the root window\n");
+ return 1;
+}
+
+gint parse_hex(gchar *s) {
+ gint result = 0;
+ while (*s) {
+ gint add;
+ if (*s >= '0' && *s <='9')
+ add = *s-'0';
+ else if (*s >= 'A' && *s <='F')
+ add = *s-'A'+10;
+ else if (*s >= 'a' && *s <='f')
+ add = *s-'a'+10;
+ else
+ break;
+
+ result *= 16;
+ result += add;
+ ++s;
+ }
+ return result;
+}
+
+Window find_client(Display *d, Window win)
+{
+ Window r, *children;
+ guint n, i;
+ Atom state = XInternAtom(d, "WM_STATE", True);
+ Atom ret_type;
+ gint ret_format, res;
+ gulong ret_items, ret_bytesleft, *xdata;
+
+ XQueryTree(d, win, &r, &r, &children, &n);
+ for (i = 0; i < n; ++i) {
+ Window w = find_client(d, children[i]);
+ if (w) return w;
+ }
+
+ // try me
+ res = XGetWindowProperty(d, win, state, 0, 1,
+ False, state, &ret_type, &ret_format,
+ &ret_items, &ret_bytesleft,
+ (unsigned char**) &xdata);
+ XFree(xdata);
+ if (res != Success || ret_type == None || ret_items < 1)
+ return None;
+ return win; // found it!
+}
+
+static gboolean get_all(Display *d, Window win, Atom prop,
+ Atom *type, gint *size,
+ guchar **data, guint *num)
+{
+ gboolean ret = FALSE;
+ gint res;
+ guchar *xdata = NULL;
+ gulong ret_items, bytes_left;
+
+ res = XGetWindowProperty(d, win, prop, 0l, G_MAXLONG,
+ FALSE, AnyPropertyType, type, size,
+ &ret_items, &bytes_left, &xdata);
+ if (res == Success) {
+ if (ret_items > 0) {
+ guint i;
+
+ *data = g_malloc(ret_items * (*size / 8));
+ for (i = 0; i < ret_items; ++i)
+ switch (*size) {
+ case 8:
+ (*data)[i] = xdata[i];
+ break;
+ case 16:
+ ((guint16*)*data)[i] = ((gushort*)xdata)[i];
+ break;
+ case 32:
+ ((guint32*)*data)[i] = ((gulong*)xdata)[i];
+ break;
+ default:
+ g_assert_not_reached(); /* unhandled size */
+ }
+ }
+ *num = ret_items;
+ ret = TRUE;
+ XFree(xdata);
+ }
+ return ret;
+}
+
+gchar *append_string(gchar *before, gchar *after, gboolean quote)
+{
+ gchar *tmp;
+ const gchar *q = quote ? "\"" : "";
+ if (before)
+ tmp = g_strdup_printf("%s, %s%s%s", before, q, after, q);
+ else
+ tmp = g_strdup_printf("%s%s%s", q, after, q);
+ g_free(before);
+ return tmp;
+}
+
+gchar *append_int(gchar *before, guint after)
+{
+ gchar *tmp;
+ if (before)
+ tmp = g_strdup_printf("%s, %u", before, after);
+ else
+ tmp = g_strdup_printf("%u", after);
+ g_free(before);
+ return tmp;
+}
+
+gchar* read_strings(gchar *val, guint n, gboolean utf8)
+{
+ GSList *strs = NULL, *it;
+ gchar *ret, *p;
+ guint i;
+
+ p = val;
+ while (p < val + n) {
+ strs = g_slist_append(strs, g_strndup(p, n - (p - val)));
+ p += strlen(p) + 1; /* next string */
+ }
+
+ ret = NULL;
+ for (i = 0, it = strs; it; ++i, it = g_slist_next(it)) {
+ char *data;
+
+ if (utf8) {
+ if (g_utf8_validate(it->data, -1, NULL))
+ data = g_strdup(it->data);
+ else
+ data = g_strdup("");
+ }
+ else
+ data = g_locale_to_utf8(it->data, -1, NULL, NULL, NULL);
+
+ ret = append_string(ret, data, TRUE);
+ g_free(data);
+ }
+
+ while (strs) {
+ g_free(strs->data);
+ strs = g_slist_delete_link(strs, strs);
+ }
+ return ret;
+}
+
+gchar* read_atoms(Display *d, guchar *val, guint n)
+{
+ gchar *ret;
+ guint i;
+
+ ret = NULL;
+ for (i = 0; i < n; ++i)
+ ret = append_string(ret, XGetAtomName(d, ((guint32*)val)[i]), FALSE);
+ return ret;
+}
+
+gchar* read_numbers(guchar *val, guint n, guint size)
+{
+ gchar *ret;
+ guint i;
+
+ ret = NULL;
+ for (i = 0; i < n; ++i)
+ switch (size) {
+ case 8:
+ ret = append_int(ret, ((guint8*)val)[i]);
+ break;
+ case 16:
+ ret = append_int(ret, ((guint16*)val)[i]);
+ break;
+ case 32:
+ ret = append_int(ret, ((guint32*)val)[i]);
+ break;
+ default:
+ g_assert_not_reached(); /* unhandled size */
+ }
+
+ return ret;
+}
+
+gboolean read_prop(Display *d, Window w, Atom prop, const gchar **type, gchar **val)
+{
+ guchar *ret;
+ guint nret;
+ gint size;
+ Atom ret_type;
+
+ ret = NULL;
+ if (get_all(d, w, prop, &ret_type, &size, &ret, &nret)) {
+ *type = XGetAtomName(d, ret_type);
+
+ if (strcmp(*type, "STRING") == 0)
+ *val = read_strings((gchar*)ret, nret, FALSE);
+ else if (strcmp(*type, "UTF8_STRING") == 0)
+ *val = read_strings((gchar*)ret, nret, TRUE);
+ else if (strcmp(*type, "ATOM") == 0) {
+ g_assert(size == 32);
+ *val = read_atoms(d, ret, nret);
+ }
+ else
+ *val = read_numbers(ret, nret, size);
+
+ g_free(ret);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void show_properties(Display *d, Window w, int argc, char **argv)
+{
+ Atom* props;
+ int i, n;
+
+ props = XListProperties(d, w, &n);
+
+ for (i = 0; i < n; ++i) {
+ const char *type;
+ char *name, *val;
+
+ name = XGetAtomName(d, props[i]);
+
+ if (read_prop(d, w, props[i], &type, &val)) {
+ int found = 1;
+ if (argc) {
+ int i;
+
+ found = 0;
+ for (i = 0; i < argc; i++)
+ if (!strcmp(name, argv[i])) {
+ found = 1;
+ break;
+ }
+ }
+ if (found)
+ g_print("%s(%s) = %s\n", name, type, (val ? val : ""));
+ g_free(val);
+ }
+
+ XFree(name);
+ }
+
+ XFree(props);
+}
+
+int main(int argc, char **argv)
+{
+ Display *d;
+ Window id, userid = None;
+ int i;
+ char *dname = NULL;
+ gboolean root = FALSE;
+
+ for (i = 1; i < argc; ++i) {
+ if (!strcmp(argv[i], "--help")) {
+ return fail(NULL);
+ }
+ else if (!strcmp(argv[i], "--root"))
+ root = TRUE;
+ else if (!strcmp(argv[i], "--id")) {
+ if (++i == argc)
+ return fail(NULL);
+ if (argv[i][0] == '0' && argv[i][1] == 'x') {
+ /* hex */
+ userid = parse_hex(argv[i]+2);
+ }
+ else {
+ /* decimal */
+ userid = atoi(argv[i]);
+ }
+ if (!userid)
+ return fail("Unable to parse argument to --id.");
+ }
+ else if (!strcmp(argv[i], "--display")) {
+ if (++i == argc)
+ return fail(NULL);
+ dname = argv[i];
+ }
+ else if (*argv[i] != '-')
+ break;
+ else if (!strcmp(argv[i], "--")) {
+ i++;
+ break;
+ }
+ else
+ return fail(NULL);
+ }
+
+ d = XOpenDisplay(dname);
+ if (!d) {
+ return fail("Unable to find an X display. "
+ "Ensure you have permission to connect to the display.");
+ }
+
+ if (root)
+ userid = RootWindow(d, DefaultScreen(d));
+
+ if (userid == None) {
+ int j;
+ j = XGrabPointer(d, RootWindow(d, DefaultScreen(d)),
+ False, ButtonPressMask,
+ GrabModeAsync, GrabModeAsync,
+ None, XCreateFontCursor(d, XC_crosshair),
+ CurrentTime);
+ if (j != GrabSuccess)
+ return fail("Unable to grab the pointer device");
+ while (1) {
+ XEvent ev;
+
+ XNextEvent(d, &ev);
+ if (ev.type == ButtonPress) {
+ XUngrabPointer(d, CurrentTime);
+ userid = ev.xbutton.subwindow;
+ break;
+ }
+ }
+ id = find_client(d, userid);
+ }
+ else
+ id = userid; /* they picked this one */
+
+ if (id == None)
+ return fail("Unable to find window with the requested ID");
+
+ show_properties(d, id, argc - i, &argv[i]);
+
+ XCloseDisplay(d);
+
+ return 0;
+}
diff --git a/tools/themeupdate/themeupdate.py b/tools/themeupdate/themeupdate.py
new file mode 100755
index 0000000..c2ad6a7
--- /dev/null
+++ b/tools/themeupdate/themeupdate.py
@@ -0,0 +1,410 @@
+#! /usr/bin/python
+
+# themeupdate.py for the Openbox window manager
+# This utility is for updating old themes from Blackbox, Fluxbox, and Openbox2
+# to Openbox3
+#
+# Copyright (c) 2003-2007 Dana Jansens
+#
+# 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.
+
+import sys
+
+data = []
+valid = True
+
+def out(str):
+ sys.stderr.write(str)
+ sys.stderr.flush()
+
+def read_bool():
+ while True:
+ inp = sys.stdin.readline(1).strip()
+ if inp == 'y' or inp == '': return True
+ if inp == 'n': return False
+
+def getkeyval(line):
+ key = line[:line.find(':')].strip()
+ value = line[line.find(':') + 1:].strip()
+ if not (key and value):
+ key = value = None
+ return key, value
+
+def find_key(data, keysubstr, exact = False):
+ i = 0
+ n = len(data)
+ while i < n:
+ l = data[i]
+ key, value = getkeyval(l)
+ if key and value:
+ if (exact and key == keysubstr) or \
+ (not exact and key.find(keysubstr) != -1):
+ return i, key, value
+ i += 1
+ return -1, None, None
+
+def simple_replace(data):
+ pairs = {}
+ pairs['.picColor'] = '.imageColor'
+ pairs['menu.frame'] = 'menu.items'
+ pairs['menu.hilite'] = 'menu.selected'
+ pairs['borderColor'] = 'border.color'
+ pairs['imageColor'] = 'image.color'
+ pairs['textColor'] = 'text.color'
+ pairs['interlaceColor'] = 'interlace.color'
+
+ for k in pairs.keys():
+ while 1:
+ i, key, nul = find_key(data, k);
+ if i >= 0:
+ newl = data[i].replace(k, pairs[k])
+ out('Updating "' + key +
+ '" to "' + key.replace(k, pairs[k]) + '"\n')
+ data[i] = newl
+ else:
+ break
+
+ pairs = {}
+ pairs['window.focus.font'] = 'window.active.label.text.font'
+ pairs['window.unfocus.font'] = 'window.inactive.label.text.font'
+ pairs['window.justify'] = 'window.label.justify'
+ pairs['menu.frame.disableColor'] = 'menu.disabled.textColor'
+ pairs['window.label.focus.font'] = 'window.active.label.text.font'
+ pairs['window.label.unfocus.font'] = 'window.inactive.label.text.font'
+ pairs['window.label.justify'] = 'window.label.text.justify'
+ pairs['menu.title.font'] = 'menu.title.text.font'
+ pairs['menu.title.justify'] = 'menu.title.text.justify'
+ pairs['menuOverlap'] = 'menu.overlap'
+ pairs['handleWidth'] = 'window.handle.width'
+ pairs['borderWidth'] = 'border.width'
+ pairs['bevelWidth'] = 'padding.width'
+ pairs['frameWidth'] = 'window.client.padding.width'
+ pairs['window.frame.focusColor'] = 'window.active.client.color'
+ pairs['window.frame.unfocusColor'] = 'window.inactive.client.color'
+ pairs['window.title.focus'] = 'window.active.title.bg'
+ pairs['window.title.unfocus'] = 'window.inactive.title.bg'
+ pairs['window.label.focus'] = 'window.active.label.bg'
+ pairs['window.label.unfocus'] = 'window.inactive.label.bg'
+ pairs['window.handle.focus'] = 'window.active.handle.bg'
+ pairs['window.handle.unfocus'] = 'window.inactive.handle.bg'
+ pairs['window.grip.focus'] = 'window.active.grip.bg'
+ pairs['window.grip.unfocus'] = 'window.inactive.grip.bg'
+ pairs['menu.items'] = 'menu.items.bg'
+ pairs['menu.title'] = 'menu.title.bg'
+ pairs['menu.selected'] = 'menu.items.active.bg'
+ pairs['window.title.focus'] = 'window.active.title.bg'
+ pairs['window.label.focus'] = 'window.active.label.bg'
+ pairs['window.title.unfocus'] = 'window.inactive.title.bg'
+ pairs['window.label.unfocus'] = 'window.inactive.label.bg'
+ pairs['window.button.disabled.focus'] = 'window.active.button.disabled.bg'
+ pairs['window.button.disabled.unfocus'] = \
+ 'window.inactive.button.disabled.bg'
+ pairs['window.button.pressed.focus'] = 'window.active.button.pressed.bg'
+ pairs['window.button.pressed.unfocus'] = \
+ 'window.inactive.button.pressed.bg'
+ pairs['window.button.toggled.focus'] = 'window.active.button.toggled.bg'
+ pairs['window.button.toggled.unfocus'] = \
+ 'window.inactive.button.toggled.bg'
+ pairs['window.button.focus'] = 'window.active.button.unpressed.bg'
+ pairs['window.button.unfocus'] = 'window.inactive.button.unpressed.bg'
+ pairs['window.button.hover.focus'] = 'window.active.button.hover.bg'
+ pairs['window.button.hover.unfocus'] = 'window.inactive.button.hover.bg'
+
+ for k in pairs.keys():
+ while 1:
+ i, key, nul = find_key(data, k, True);
+ if i >= 0:
+ newl = data[i].replace(k, pairs[k])
+ out('Updating "' + key +
+ '" to "' + key.replace(k, pairs[k]) + '"\n')
+ data[i] = newl
+ else:
+ break
+
+ pairs = {}
+ pairs['window.title.focus'] = 'window.active.title'
+ pairs['window.title.unfocus'] = 'window.inactive.title'
+ pairs['window.label.focus'] = 'window.active.label'
+ pairs['window.label.unfocus'] = 'window.inactive.label'
+ pairs['window.handle.focus'] = 'window.active.handle'
+ pairs['window.handle.unfocus'] = 'window.inactive.handle'
+ pairs['window.grip.focus'] = 'window.active.grip'
+ pairs['window.grip.unfocus'] = 'window.inactive.grip'
+ pairs['menu.selected'] = 'menu.items.active'
+ pairs['window.title.focus'] = 'window.active.title'
+ pairs['window.label.focus'] = 'window.active.label'
+ pairs['window.title.unfocus'] = 'window.inactive.title'
+ pairs['window.label.unfocus'] = 'window.inactive.label'
+ pairs['window.button.disabled.focus'] = 'window.active.button.disabled'
+ pairs['window.button.disabled.unfocus'] = \
+ 'window.inactive.button.disabled'
+ pairs['window.button.pressed.focus'] = 'window.active.button.pressed'
+ pairs['window.button.pressed.unfocus'] = \
+ 'window.inactive.button.pressed'
+ pairs['window.button.toggled.focus'] = 'window.active.button.toggled'
+ pairs['window.button.toggled.unfocus'] = \
+ 'window.inactive.button.toggled'
+ pairs['window.button.focus'] = 'window.active.button'
+ pairs['window.button.unfocus'] = 'window.inactive.button'
+ pairs['window.button.hover.focus'] = 'window.active.button.hover'
+ pairs['window.button.hover.unfocus'] = 'window.inactive.button.hover'
+ pairs['window.label.unfocus'] = 'window.inactive.label'
+ pairs['window.label.focus'] = 'window.active.label'
+ pairs['window.button.focus'] = 'window.active.button.unpressed'
+ pairs['menu.disabled'] = 'menu.items.disabled'
+ pairs['menu.selected'] = 'menu.items.active'
+ pairs['window.button.unfocus'] = 'window.inactive.button.unpressed'
+ pairs['window.button.pressed.focus'] = 'window.active.button.pressed'
+ pairs['window.button.pressed.unfocus'] = 'window.inactive.button.pressed'
+ pairs['window.button.disabled.focus'] = 'window.active.button.disabled'
+ pairs['window.button.disabled.unfocus'] = 'window.inactive.button.disabled'
+ pairs['window.button.hover.focus'] = 'window.active.button.hover'
+ pairs['window.button.hover.unfocus'] = 'window.inactive.button.hover'
+ pairs['window.button.toggled.focus'] = 'window.active.button.toggled'
+ pairs['window.button.toggled.unfocus'] = 'window.inactive.button.toggled'
+
+ for k in pairs.keys():
+ while 1:
+ i, key, nul = find_key(data, k);
+ if i >= 0:
+ newl = data[i].replace(k, pairs[k])
+ out('Updating "' + key +
+ '" to "' + key.replace(k, pairs[k]) + '"\n')
+ data[i] = newl
+ else:
+ break
+
+def replace_colors(data):
+ i = 0
+ n = len(data)
+ while i < n:
+ l = data[i]
+ key, value = getkeyval(l)
+ if key and value:
+ if key.find('.color') != -1:
+ if key.find('client.color') == -1 \
+ and key.find('image.color') == -1 \
+ and key.find('bg.color') == -1 \
+ and key.find('border.color') == -1 \
+ and key.find('interlace.color') == -1 \
+ and key.find('text.color') == -1:
+ newl = data[i].replace('.color', '.bg.color')
+ out('Updating "' + key +
+ '" to "' + key.replace('.color', '.bg.color') + '"\n')
+ data[i] = newl
+ if key.find('.border.color') != -1 \
+ and key.find('bg.border.color') == -1:
+ newl = data[i].replace('.border.color', '.bg.border.color')
+ out('Updating "' + key +
+ '" to "' + key.replace('.border.color',
+ '.bg.border.color') + '"\n')
+ data[i] = newl
+ if key.find('.interlace.color') != -1 \
+ and key.find('bg.interlace.color') == -1:
+ newl = data[i].replace('.interlace.color',
+ '.bg.interlace.color')
+ out('Updating "' + key +
+ '" to "' + key.replace('.interlace.color',
+ '.bg.interlace.color') + '"\n')
+ data[i] = newl
+ i += 1
+
+def remove(data):
+ invalid = []
+ invalid.append('toolbar')
+ for inv in invalid:
+ while 1:
+ i, key, nul = find_key(data, inv)
+ if i >= 0:
+ out(key + ' is no longer supported.\nRemove (Y/n)? ')
+ if read_bool():
+ out('Removing "' + key + '"\n')
+ data.pop(i)
+ else:
+ break
+ invalid.append('rootCommand')
+ invalid.append('menu.bullet')
+ invalid.append('menu.bullet.image.color')
+ invalid.append('menu.bullet.selected.image.color')
+ invalid.append('menu.frame.justify')
+ for inv in invalid:
+ while 1:
+ i, key, nul = find_key(data, inv, True)
+ if i >= 0:
+ out(key + ' is no longer supported.\nRemove (Y/n)? ')
+ if read_bool():
+ out('Removing "' + key + '"\n')
+ data.pop(i)
+ else:
+ break
+
+def pressed(data):
+ i, nul, nul = find_key(data, 'window.button.pressed', True)
+ if i >= 0:
+ out('The window.button.pressed option has been replaced by ' +
+ 'window.button.pressed.focus and ' +
+ 'window.button.pressed.unfocus.\nUpdate (Y/n)? ')
+ if read_bool():
+ l = data[i]
+ out('Removing "window.button.pressed"\n')
+ data.pop(i)
+ out('Adding "window.button.pressed.unfocus"\n')
+ data.insert(i, l.replace('window.button.pressed',
+ 'window.button.pressed.unfocus'))
+ out('Adding "window.button.pressed.focus"\n')
+ data.insert(i, l.replace('window.button.pressed',
+ 'window.button.pressed.focus'))
+
+def x_fonts(data):
+ i, nul, nul = find_key(data, 'window.font')
+ if i >= 0:
+ out('You appear to specify fonts using the old X fonts ' +
+ 'syntax.\nShall I remove all fonts from the theme (Y/n)? ')
+ if not read_bool():
+ return
+ else: return
+ while 1:
+ i, key, nul = find_key(data, '.font')
+ if i < 0:
+ break
+ out('Removing "' + key + '"\n')
+ data.pop(i)
+
+def xft_fonts(data):
+ i, nul, nul = find_key(data, '.xft.')
+ if i >= 0:
+ out('You appear to specify fonts using the old Xft fonts ' +
+ 'syntax.\nShall I update these to the new syntax (Y/n)? ')
+ if not read_bool():
+ return
+ else: return
+ fonts = {}
+ fonts['window'] = 'window.label.focus.font'
+ fonts['menu.items'] = 'menu.items.font'
+ fonts['menu.title'] = 'menu.title.font'
+ for f in fonts.keys():
+ li, nul, flags = find_key(data, f + '.xft.flags')
+ if li < 0:
+ li, nul, flags = find_key(data, '*.xft.flags')
+ else:
+ out('Removing ' + f + '.xft.flags\n')
+ data.pop(li)
+ oi, nul, offset = find_key(data, f + '.xft.shadow.offset')
+ if oi < 0:
+ oi, nul, offset = find_key(data, '*.xft.shadow.offset')
+ else:
+ out('Removing ' + f + '.xft.shadow.offset\n')
+ data.pop(oi)
+ ti, nul, tint = find_key(data, f + '.xft.shadow.tint')
+ if ti < 0:
+ ti, nul, tint = find_key(data, '*.xft.shadow.tint')
+ else:
+ out('Removing ' + f + '.xft.shadow.tint\n')
+ data.pop(ti)
+ fi, nul, face = find_key(data, f + '.xft.font')
+ if fi < 0:
+ fi, nul, face = find_key(data, '*.xft.font')
+ if fi >= 0: fi = len(data) - 1
+ else:
+ out('Removing ' + f + '.xft.font\n')
+ data.pop(fi)
+
+ if fi >= 0:
+ s = face
+ if li >= 0:
+ if flags.find('bold'):
+ s = s + ':bold'
+ if flags.find('shadow'):
+ s = s + ':shadow=y'
+ if oi >= 0:
+ s = s + ':shadowoffset=' + offset
+ if ti >= 0:
+ s = s + ':shadowtint=' + tint
+ out('Adding ' + fonts[f] + '\n')
+ data.insert(fi, fonts[f] + ': ' + s)
+
+ for stars in ('*.xft.flags', '*.xft.shadow.offset' ,
+ '*.xft.shadow.tint', '*.xft.font'):
+ i, key, nul = find_key(data, stars)
+ if i >= 0:
+ out('Removing ' + key + '\n')
+ data.pop(i)
+
+def pixelsize(data):
+ fonts = ('window.label.focus.font',
+ 'menu.items.font',
+ 'menu.title.font')
+ for f in fonts:
+ i, key, value = find_key(data, f, True)
+ if value:
+ if value.find('pixelsize') == -1:
+ out('*** ERROR *** The ' + key + ' font size is not being '
+ 'specified by pixelsize. It is recommended that you use '
+ 'pixelsize instead of pointsize for specifying theme '
+ 'fonts. e.g. "sans:pixelsize=12"\n')
+ global valid
+ valid = False
+
+def warn_missing(data):
+ need = ('window.active.button.hover', 'window.inactive.button.hover',
+ 'menu.overlap')
+ for n in need:
+ i, nul, nul = find_key(data, n)
+ if i < 0:
+ out('The ' + n + ' value was not found in the theme, but it '
+ 'can optionally be set.\n')
+
+def err_missing(data):
+ need = ('window.active.button.disabled',
+ 'window.inactive.button.disabled',
+ 'window.active.client.color',
+ 'window.inactive.client.color')
+ for n in need:
+ i, nul, nul = find_key(data, n)
+ if i < 0:
+ out('*** ERROR *** The ' + n + ' value was not found in the '
+ 'theme, but it is required to be set.\n')
+ global valid
+ valid = False
+
+
+def usage():
+ out('Usage: themupdate.py /path/to/themerc > newthemerc\n\n')
+ sys.exit()
+
+try:
+ file = open(sys.argv[1])
+except IndexError:
+ usage()
+except IOError:
+ out('Unable to open file "' + sys.argv[1] + '"\n\n')
+ usage()
+
+data = file.readlines()
+for i in range(len(data)):
+ data[i] = data[i].strip()
+
+simple_replace(data)
+replace_colors(data)
+remove(data)
+pressed(data)
+x_fonts(data)
+xft_fonts(data)
+pixelsize(data)
+warn_missing(data)
+err_missing(data)
+
+for l in data:
+ print l
+
+sys.exit(not valid)