]> git.sur5r.net Git - i3/i3/commitdiff
Implement configuration file parsing
authorMichael Stapelberg <michael+git@stapelberg.de>
Tue, 24 Feb 2009 23:50:30 +0000 (00:50 +0100)
committerMichael Stapelberg <michael+git@stapelberg.de>
Tue, 24 Feb 2009 23:50:30 +0000 (00:50 +0100)
i3.config [new file with mode: 0644]
include/config.h [new file with mode: 0644]
include/data.h
include/i3.h
src/config.c [new file with mode: 0644]
src/layout.c
src/mainx.c

diff --git a/i3.config b/i3.config
new file mode 100644 (file)
index 0000000..0e5ff21
--- /dev/null
+++ b/i3.config
@@ -0,0 +1,41 @@
+terminal /usr/pkg/bin/urxvt
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso8859-1
+
+# Fullscreen
+bind Mod1+41 f
+
+# Stacking
+bind Mod1+43 s
+
+# Default
+bind Mod1+26 d
+
+# Focus
+bind Mod1+44 h
+bind Mod1+45 j
+bind Mod1+46 k
+bind Mod1+47 l
+
+# Snap
+bind Mod1+Control+44 sh
+bind Mod1+Control+45 sj
+bind Mod1+Control+46 sk
+bind Mod1+Control+47 sl
+
+# Move
+bind Mod1+Shift+44 mh
+bind Mod1+Shift+45 mj
+bind Mod1+Shift+46 mk
+bind Mod1+Shift+47 ml
+
+# Workspaces
+bind Mod1+10 1
+bind Mod1+11 2
+bind Mod1+12 3
+bind Mod1+13 4
+bind Mod1+14 5
+bind Mod1+15 6
+bind Mod1+16 7
+bind Mod1+17 8
+bind Mod1+18 9
+bind Mod1+19 0
diff --git a/include/config.h b/include/config.h
new file mode 100644 (file)
index 0000000..5ebdc1d
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef _CONFIG_H
+#define _CONFIG_H
+
+typedef struct Config Config;
+extern Config config;
+
+struct Config {
+       const char *terminal;
+       const char *font;
+};
+
+void load_configuration(const char *configfile);
+
+#endif
index 6a430f2907aa380fc1145499cb1e98a4edd0d9e0..b183eadf676ff444cb5ef0bc5ff62ccd69a14769 100644 (file)
@@ -60,11 +60,11 @@ enum {
         BIND_NONE = 0,
         BIND_SHIFT = XCB_MOD_MASK_SHIFT,        /* (1 << 0) */
         BIND_CONTROL = XCB_MOD_MASK_CONTROL,    /* (1 << 2) */
-        BIND_MOD_1 = XCB_MOD_MASK_1,            /* (1 << 3) */
-        BIND_MOD_2 = XCB_MOD_MASK_2,            /* (1 << 4) */
-        BIND_MOD_3 = XCB_MOD_MASK_3,            /* (1 << 5) */
-        BIND_MOD_4 = XCB_MOD_MASK_4,            /* (1 << 6) */
-        BIND_MOD_5 = XCB_MOD_MASK_5,            /* (1 << 7) */
+        BIND_MOD1 = XCB_MOD_MASK_1,             /* (1 << 3) */
+        BIND_MOD2 = XCB_MOD_MASK_2,             /* (1 << 4) */
+        BIND_MOD3 = XCB_MOD_MASK_3,             /* (1 << 5) */
+        BIND_MOD4 = XCB_MOD_MASK_4,             /* (1 << 6) */
+        BIND_MOD5 = XCB_MOD_MASK_5,             /* (1 << 7) */
         BIND_MODE_SWITCH = (1 << 8)
 };
 
index c21d24a8140a7871dcdd60181309b165561ab773..9acf2c6584ac8dc7d3793a6067840b5eab64e0f7 100644 (file)
@@ -24,7 +24,6 @@ extern Display *xkbdpy;
 extern TAILQ_HEAD(bindings_head, Binding) bindings;
 extern SLIST_HEAD(stack_wins_head, Stack_Window) stack_wins;
 extern xcb_event_handlers_t evenths;
-extern char *pattern;
 extern int num_screens;
 extern xcb_atom_t atoms[NUM_ATOMS];
 
diff --git a/src/config.c b/src/config.c
new file mode 100644 (file)
index 0000000..1b4e1c3
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * vim:ts=8:expandtab
+ *
+ * i3 - an improved dynamic tiling window manager
+ *
+ * © 2009 Michael Stapelberg and contributors
+ *
+ * See file LICENSE for license information.
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+
+#include "i3.h"
+#include "util.h"
+#include "config.h"
+
+Config config;
+
+/*
+ * Reads the configuration from the given file
+ *
+ */
+void load_configuration(const char *configfile) {
+#define OPTION_STRING(name) \
+        if (strcasecmp(key, #name) == 0) { \
+                config.name = sstrdup(value); \
+                continue; \
+        }
+
+#define REQUIRED_OPTION(name) \
+        if (config.name == NULL) \
+                die("You did not specify required configuration option " #name "\n");
+
+        /* Clear the old config or initialize the data structure */
+        memset(&config, 0, sizeof(config));
+
+        /* check if the file exists */
+        struct stat buf;
+        if (stat(configfile, &buf) < 0)
+                return;
+
+        FILE *handle = fopen(configfile, "r");
+        if (handle == NULL)
+                die("Could not open configfile\n");
+        char key[512], value[512], buffer[1026];
+
+        while (!feof(handle)) {
+                if (fgets(buffer, 1024, handle) == NULL) {
+                        /* fgets returns NULL on EOF and on error, so see which one it is. */
+                        if (feof(handle))
+                                break;
+                        die("Could not read configuration file\n");
+                }
+
+                /* sscanf implicitly strips whitespace. Also, we skip comments and empty lines. */
+                if (sscanf(buffer, "%s %[^\n]", key, value) < 1 ||
+                    key[0] == '#' || strlen(key) < 3)
+                        continue;
+
+                OPTION_STRING(terminal);
+                OPTION_STRING(font);
+
+                if (strcasecmp(key, "bind") == 0) {
+                        #define CHECK_MODIFIER(name) \
+                                if (strncasecmp(walk, #name, strlen(#name)) == 0) { \
+                                        modifiers |= BIND_##name; \
+                                        walk += strlen(#name) + 1; \
+                                        continue; \
+                                }
+                        char *walk = value, *rest;
+                        uint32_t modifiers = 0;
+
+                        while (*walk != '\0') {
+                                /* Need to check for Mod1-5, Ctrl, Shift, Mode_switch */
+                                CHECK_MODIFIER(SHIFT);
+                                CHECK_MODIFIER(CONTROL);
+                                CHECK_MODIFIER(MODE_SWITCH);
+                                CHECK_MODIFIER(MOD1);
+                                CHECK_MODIFIER(MOD2);
+                                CHECK_MODIFIER(MOD3);
+                                CHECK_MODIFIER(MOD4);
+                                CHECK_MODIFIER(MOD5);
+
+                                /* No modifier found? Then we’re done with this step */
+                                break;
+                        }
+
+                        /* Now check for the keycode */
+                        int keycode = strtol(walk, &rest, 10);
+                        if (!rest || *rest != ' ')
+                                die("Invalid binding\n");
+                        rest++;
+                        printf("keycode = %d, modifiers = %d, command = *%s*\n", keycode, modifiers, rest);
+                        Binding *new = smalloc(sizeof(Binding));
+                        new->keycode = keycode;
+                        new->mods = modifiers;
+                        new->command = sstrdup(rest);
+                        TAILQ_INSERT_TAIL(&bindings, new, bindings);
+                        continue;
+                }
+
+                fprintf(stderr, "Unknown configfile option: %s\n", key);
+                exit(1);
+        }
+        fclose(handle);
+
+        REQUIRED_OPTION(terminal);
+        REQUIRED_OPTION(font);
+
+        return;
+}
index 131ce3c2bef74edda18afd1e50fa0a86a5fffc5d..b3eb14f0c9c2246162d26ffae95bab8e1656961e 100644 (file)
@@ -16,6 +16,7 @@
 #include <xcb/xcb.h>
 #include <assert.h>
 
+#include "config.h"
 #include "font.h"
 #include "i3.h"
 #include "xcb.h"
@@ -76,7 +77,7 @@ int get_unoccupied_y(Workspace *workspace, int col) {
  *
  */
 void decorate_window(xcb_connection_t *conn, Client *client, xcb_drawable_t drawable, xcb_gcontext_t gc, int offset) {
-        i3Font *font = load_font(conn, pattern);
+        i3Font *font = load_font(conn, config.font);
         uint32_t background_color,
                  text_color,
                  border_color;
@@ -143,7 +144,7 @@ static void reposition_client(xcb_connection_t *connection, Client *client) {
  *
  */
 static void resize_client(xcb_connection_t *connection, Client *client) {
-        i3Font *font = load_font(connection, pattern);
+        i3Font *font = load_font(connection, config.font);
 
         printf("resizing client to %d x %d\n", client->rect.width, client->rect.height);
         xcb_configure_window(connection, client->frame,
@@ -216,7 +217,7 @@ void render_container(xcb_connection_t *connection, Container *container) {
                         current_client++;
                 }
         } else {
-                i3Font *font = load_font(connection, pattern);
+                i3Font *font = load_font(connection, config.font);
                 int decoration_height = (font->height + 2 + 2);
                 struct Stack_Window *stack_win = &(container->stack_win);
 
index a37be683192b60e6541948080e7b1c1b124f2df3..c3a7bbcd589c232686d120a9ad743996f8094084 100644 (file)
@@ -32,6 +32,7 @@
 #include <xcb/xinerama.h>
 #include "data.h"
 
+#include "config.h"
 #include "queue.h"
 #include "table.h"
 #include "font.h"
@@ -43,8 +44,6 @@
 #include "xinerama.h"
 #include "i3.h"
 
-#define TERMINAL "/usr/pkg/bin/urxvt"
-
 /* This is our connection to X11 for use with XKB */
 Display *xkbdpy;
 
@@ -59,7 +58,6 @@ struct stack_wins_head stack_wins = SLIST_HEAD_INITIALIZER(stack_wins);
 xcb_event_handlers_t evenths;
 xcb_atom_t atoms[NUM_ATOMS];
 
-char *pattern = "-misc-fixed-medium-r-normal--13-120-75-75-C-70-iso8859-1";
 int num_screens = 0;
 
 /*
@@ -163,7 +161,7 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child,
 
         printf("Reparenting 0x%08x under 0x%08x.\n", child, new->frame);
 
-        i3Font *font = load_font(conn, pattern);
+        i3Font *font = load_font(conn, config.font);
         width = min(width, c_ws->rect.x + c_ws->rect.width);
         height = min(height, c_ws->rect.y + c_ws->rect.height);
 
@@ -290,6 +288,8 @@ int main(int argc, char *argv[], char *env[]) {
         byChild = alloc_table();
         byParent = alloc_table();
 
+        load_configuration("i3.config");
+
         c = xcb_connect(NULL, &screens);
 
         /* Place requests for the atoms we need as soon as possible */
@@ -407,50 +407,6 @@ int main(int argc, char *argv[], char *env[]) {
         xcb_change_property(c, XCB_PROP_MODE_REPLACE, root, atoms[_NET_SUPPORTING_WM_CHECK], WINDOW, 32, 1, &root);
         xcb_change_property(c, XCB_PROP_MODE_REPLACE, root, atoms[_NET_WM_NAME], atoms[UTF8_STRING], 8, strlen("i3"), "i3");
 
-        #define BIND(key, modifier, cmd) { \
-                Binding *new = malloc(sizeof(Binding)); \
-                new->keycode = key; \
-                new->mods = modifier; \
-                new->command = cmd; \
-                TAILQ_INSERT_TAIL(&bindings, new, bindings); \
-        }
-
-        /* 38 = 'a' */
-        BIND(38, BIND_MODE_SWITCH, "foo");
-
-        BIND(30, 0, "exec /usr/pkg/bin/urxvt");
-
-        BIND(41, BIND_MOD_1, "f");
-
-        BIND(43, BIND_MOD_1, "s");
-        BIND(26, BIND_MOD_1, "d");
-
-        BIND(44, BIND_MOD_1, "h");
-        BIND(45, BIND_MOD_1, "j");
-        BIND(46, BIND_MOD_1, "k");
-        BIND(47, BIND_MOD_1, "l");
-
-        BIND(44, BIND_MOD_1 | BIND_CONTROL, "sh");
-        BIND(45, BIND_MOD_1 | BIND_CONTROL, "sj");
-        BIND(46, BIND_MOD_1 | BIND_CONTROL, "sk");
-        BIND(47, BIND_MOD_1 | BIND_CONTROL, "sl");
-
-        BIND(44, BIND_MOD_1 | BIND_SHIFT, "mh");
-        BIND(45, BIND_MOD_1 | BIND_SHIFT, "mj");
-        BIND(46, BIND_MOD_1 | BIND_SHIFT, "mk");
-        BIND(47, BIND_MOD_1 | BIND_SHIFT, "ml");
-
-        BIND(10, BIND_MOD_1 , "1");
-        BIND(11, BIND_MOD_1 , "2");
-        BIND(12, BIND_MOD_1 , "3");
-        BIND(13, BIND_MOD_1 , "4");
-        BIND(14, BIND_MOD_1 , "5");
-        BIND(15, BIND_MOD_1 , "6");
-        BIND(16, BIND_MOD_1 , "7");
-        BIND(17, BIND_MOD_1 , "8");
-        BIND(18, BIND_MOD_1 , "9");
-        BIND(19, BIND_MOD_1 , "0");
-
         /* Grab the bound keys */
         Binding *bind;
         TAILQ_FOREACH(bind, &bindings, bindings) {
@@ -465,7 +421,7 @@ int main(int argc, char *argv[], char *env[]) {
         initialize_xinerama(c);
 
         /* DEBUG: Start a terminal */
-        start_application(TERMINAL);
+        start_application(config.terminal);
 
         xcb_flush(c);