From e77ebb6c7166f040c7c8d5e89c1be5e62eaa98cf Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Wed, 25 Feb 2009 00:50:30 +0100 Subject: [PATCH] Implement configuration file parsing --- i3.config | 41 +++++++++++++++++ include/config.h | 14 ++++++ include/data.h | 10 ++--- include/i3.h | 1 - src/config.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++ src/layout.c | 7 +-- src/mainx.c | 54 +++------------------- 7 files changed, 183 insertions(+), 58 deletions(-) create mode 100644 i3.config create mode 100644 include/config.h create mode 100644 src/config.c diff --git a/i3.config b/i3.config new file mode 100644 index 00000000..0e5ff21b --- /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 index 00000000..5ebdc1db --- /dev/null +++ b/include/config.h @@ -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 diff --git a/include/data.h b/include/data.h index 6a430f29..b183eadf 100644 --- a/include/data.h +++ b/include/data.h @@ -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) }; diff --git a/include/i3.h b/include/i3.h index c21d24a8..9acf2c65 100644 --- a/include/i3.h +++ b/include/i3.h @@ -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 index 00000000..1b4e1c34 --- /dev/null +++ b/src/config.c @@ -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 +#include +#include +#include + +#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; +} diff --git a/src/layout.c b/src/layout.c index 131ce3c2..b3eb14f0 100644 --- a/src/layout.c +++ b/src/layout.c @@ -16,6 +16,7 @@ #include #include +#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); diff --git a/src/mainx.c b/src/mainx.c index a37be683..c3a7bbcd 100644 --- a/src/mainx.c +++ b/src/mainx.c @@ -32,6 +32,7 @@ #include #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); -- 2.39.5