]> git.sur5r.net Git - i3/i3/blobdiff - src/config.c
Merge branch 'master' into next
[i3/i3] / src / config.c
index 80071d212f1cfea9fe125810bbb128bf6c736165..c979d8cdbfcc83ec5bda074a375611688aec4beb 100644 (file)
 
 /* We need Xlib for XStringToKeysym */
 #include <X11/Xlib.h>
-#include <wordexp.h>
 
 #include "all.h"
 
+char *current_configpath = NULL;
 Config config;
 struct modes_head modes;
 
@@ -141,7 +141,7 @@ void grab_all_keys(xcb_connection_t *conn, bool bind_mode_switch) {
 
                 xcb_keycode_t *walk = bind->translated_to;
                 for (int i = 0; i < bind->number_keycodes; i++)
-                        grab_keycode_for_binding(conn, bind, *walk);
+                        grab_keycode_for_binding(conn, bind, *walk++);
         }
 }
 
@@ -149,7 +149,7 @@ void grab_all_keys(xcb_connection_t *conn, bool bind_mode_switch) {
  * Switches the key bindings to the given mode, if the mode exists
  *
  */
-void switch_mode(xcb_connection_t *conn, const char *new_mode) {
+void switch_mode(const char *new_mode) {
         struct Mode *mode;
 
         LOG("Switching to mode %s\n", new_mode);
@@ -169,60 +169,73 @@ void switch_mode(xcb_connection_t *conn, const char *new_mode) {
 }
 
 /*
- * Get the path of the first configuration file found. Checks the home directory
- * first, then the system directory first, always taking into account the XDG
- * Base Directory Specification ($XDG_CONFIG_HOME, $XDG_CONFIG_DIRS)
+ * Get the path of the first configuration file found. If override_configpath
+ * is specified, that path is returned and saved for further calls. Otherwise,
+ * checks the home directory first, then the system directory first, always
+ * taking into account the XDG Base Directory Specification ($XDG_CONFIG_HOME,
+ * $XDG_CONFIG_DIRS)
  *
  */
-static char *get_config_path() {
-        char *xdg_config_home, *xdg_config_dirs, *config_path;
+static char *get_config_path(const char *override_configpath) {
+    char *xdg_config_home, *xdg_config_dirs, *config_path;
 
-        /* 1: check the traditional path under the home directory */
-        config_path = resolve_tilde("~/.i3/config");
-        if (path_exists(config_path))
-                return config_path;
-
-        /* 2: check for $XDG_CONFIG_HOME/i3/config */
-        if ((xdg_config_home = getenv("XDG_CONFIG_HOME")) == NULL)
-                xdg_config_home = "~/.config";
-
-        xdg_config_home = resolve_tilde(xdg_config_home);
-        if (asprintf(&config_path, "%s/i3/config", xdg_config_home) == -1)
-                die("asprintf() failed");
-        free(xdg_config_home);
+    static const char *saved_configpath = NULL;
 
-        if (path_exists(config_path))
-                return config_path;
-        free(config_path);
+    if (override_configpath != NULL) {
+        saved_configpath = override_configpath;
+        return sstrdup(saved_configpath);
+    }
 
-        /* 3: check the traditional path under /etc */
-        config_path = SYSCONFDIR "/i3/config";
-        if (path_exists(config_path))
-                return sstrdup(config_path);
-
-        /* 4: check for $XDG_CONFIG_DIRS/i3/config */
-        if ((xdg_config_dirs = getenv("XDG_CONFIG_DIRS")) == NULL)
-                xdg_config_dirs = "/etc/xdg";
-
-        char *buf = sstrdup(xdg_config_dirs);
-        char *tok = strtok(buf, ":");
-        while (tok != NULL) {
-                tok = resolve_tilde(tok);
-                if (asprintf(&config_path, "%s/i3/config", tok) == -1)
-                        die("asprintf() failed");
-                free(tok);
-                if (path_exists(config_path)) {
-                        free(buf);
-                        return config_path;
-                }
-                free(config_path);
-                tok = strtok(NULL, ":");
+    if (saved_configpath != NULL)
+        return sstrdup(saved_configpath);
+
+    /* 1: check the traditional path under the home directory */
+    config_path = resolve_tilde("~/.i3/config");
+    if (path_exists(config_path))
+        return config_path;
+    free(config_path);
+
+    /* 2: check for $XDG_CONFIG_HOME/i3/config */
+    if ((xdg_config_home = getenv("XDG_CONFIG_HOME")) == NULL)
+        xdg_config_home = "~/.config";
+
+    xdg_config_home = resolve_tilde(xdg_config_home);
+    if (asprintf(&config_path, "%s/i3/config", xdg_config_home) == -1)
+        die("asprintf() failed");
+    free(xdg_config_home);
+
+    if (path_exists(config_path))
+        return config_path;
+    free(config_path);
+
+    /* 3: check the traditional path under /etc */
+    config_path = SYSCONFDIR "/i3/config";
+    if (path_exists(config_path))
+        return sstrdup(config_path);
+
+    /* 4: check for $XDG_CONFIG_DIRS/i3/config */
+    if ((xdg_config_dirs = getenv("XDG_CONFIG_DIRS")) == NULL)
+        xdg_config_dirs = "/etc/xdg";
+
+    char *buf = sstrdup(xdg_config_dirs);
+    char *tok = strtok(buf, ":");
+    while (tok != NULL) {
+        tok = resolve_tilde(tok);
+        if (asprintf(&config_path, "%s/i3/config", tok) == -1)
+            die("asprintf() failed");
+        free(tok);
+        if (path_exists(config_path)) {
+            free(buf);
+            return config_path;
         }
-        free(buf);
+        free(config_path);
+        tok = strtok(NULL, ":");
+    }
+    free(buf);
 
-        die("Unable to find the configuration file (looked at "
-                "~/.i3/config, $XDG_CONFIG_HOME/i3/config, "
-                SYSCONFDIR "i3/config and $XDG_CONFIG_DIRS/i3/config)");
+    die("Unable to find the configuration file (looked at "
+            "~/.i3/config, $XDG_CONFIG_HOME/i3/config, "
+            SYSCONFDIR "i3/config and $XDG_CONFIG_DIRS/i3/config)");
 }
 
 /*
@@ -232,22 +245,11 @@ static char *get_config_path() {
  *
  */
 static void parse_configuration(const char *override_configpath) {
-    static const char *saved_configpath = NULL;
-
-    if (override_configpath != NULL) {
-        saved_configpath = override_configpath;
-        parse_file(override_configpath);
-        return;
-    }
-    else if (saved_configpath != NULL) {
-        parse_file(saved_configpath);
-        return;
-    }
-
-    char *path = get_config_path();
+    char *path = get_config_path(override_configpath);
     DLOG("Parsing configfile %s\n", path);
+    FREE(current_configpath);
+    current_configpath = path;
     parse_file(path);
-    free(path);
 }
 
 /*
@@ -255,109 +257,116 @@ static void parse_configuration(const char *override_configpath) {
  *
  */
 void load_configuration(xcb_connection_t *conn, const char *override_configpath, bool reload) {
-        if (reload) {
-                /* First ungrab the keys */
-                ungrab_all_keys(conn);
+    if (reload) {
+        /* First ungrab the keys */
+        ungrab_all_keys(conn);
 
-                struct Mode *mode;
-                Binding *bind;
-                while (!SLIST_EMPTY(&modes)) {
-                        mode = SLIST_FIRST(&modes);
-                        FREE(mode->name);
-
-                        /* Clear the old binding list */
-                        bindings = mode->bindings;
-                        while (!TAILQ_EMPTY(bindings)) {
-                                bind = TAILQ_FIRST(bindings);
-                                TAILQ_REMOVE(bindings, bind, bindings);
-                                FREE(bind->translated_to);
-                                FREE(bind->command);
-                                FREE(bind);
-                        }
-                        FREE(bindings);
-                        SLIST_REMOVE(&modes, mode, Mode, modes);
-                }
+        struct Mode *mode;
+        Binding *bind;
+        while (!SLIST_EMPTY(&modes)) {
+            mode = SLIST_FIRST(&modes);
+            FREE(mode->name);
+
+            /* Clear the old binding list */
+            bindings = mode->bindings;
+            while (!TAILQ_EMPTY(bindings)) {
+                bind = TAILQ_FIRST(bindings);
+                TAILQ_REMOVE(bindings, bind, bindings);
+                FREE(bind->translated_to);
+                FREE(bind->command);
+                FREE(bind);
+            }
+            FREE(bindings);
+            SLIST_REMOVE(&modes, mode, Mode, modes);
+        }
 
-#if 0
-                struct Assignment *assign;
-                while (!TAILQ_EMPTY(&assignments)) {
-                        assign = TAILQ_FIRST(&assignments);
-                        FREE(assign->windowclass_title);
-                        TAILQ_REMOVE(&assignments, assign, assignments);
-                        FREE(assign);
-                }
-#endif
+        struct Assignment *assign;
+        while (!TAILQ_EMPTY(&assignments)) {
+            assign = TAILQ_FIRST(&assignments);
+            if (assign->type == A_TO_WORKSPACE)
+                FREE(assign->dest.workspace);
+            else if (assign->type == A_TO_OUTPUT)
+                FREE(assign->dest.output);
+            else if (assign->type == A_COMMAND)
+                FREE(assign->dest.command);
+            match_free(&(assign->match));
+            TAILQ_REMOVE(&assignments, assign, assignments);
+            FREE(assign);
+        }
 
-                /* Clear workspace names */
+        /* Clear workspace names */
 #if 0
-                Workspace *ws;
-                TAILQ_FOREACH(ws, workspaces, workspaces)
-                        workspace_set_name(ws, NULL);
+        Workspace *ws;
+        TAILQ_FOREACH(ws, workspaces, workspaces)
+            workspace_set_name(ws, NULL);
 #endif
-        }
+    }
 
-        SLIST_INIT(&modes);
+    SLIST_INIT(&modes);
 
-        struct Mode *default_mode = scalloc(sizeof(struct Mode));
-        default_mode->name = sstrdup("default");
-        default_mode->bindings = scalloc(sizeof(struct bindings_head));
-        TAILQ_INIT(default_mode->bindings);
-        SLIST_INSERT_HEAD(&modes, default_mode, modes);
+    struct Mode *default_mode = scalloc(sizeof(struct Mode));
+    default_mode->name = sstrdup("default");
+    default_mode->bindings = scalloc(sizeof(struct bindings_head));
+    TAILQ_INIT(default_mode->bindings);
+    SLIST_INSERT_HEAD(&modes, default_mode, modes);
 
-        bindings = default_mode->bindings;
+    bindings = default_mode->bindings;
 
 #define REQUIRED_OPTION(name) \
-        if (config.name == NULL) \
-                die("You did not specify required configuration option " #name "\n");
+    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));
+    /* Clear the old config or initialize the data structure */
+    memset(&config, 0, sizeof(config));
 
-        /* Initialize default colors */
+    /* Initialize default colors */
 #define INIT_COLOR(x, cborder, cbackground, ctext) \
-        do { \
-                x.border = get_colorpixel(cborder); \
-                x.background = get_colorpixel(cbackground); \
-                x.text = get_colorpixel(ctext); \
-        } while (0)
-
-        config.client.background = get_colorpixel("#000000");
-        INIT_COLOR(config.client.focused, "#4c7899", "#285577", "#ffffff");
-        INIT_COLOR(config.client.focused_inactive, "#333333", "#5f676a", "#ffffff");
-        INIT_COLOR(config.client.unfocused, "#333333", "#222222", "#888888");
-        INIT_COLOR(config.client.urgent, "#2f343a", "#900000", "#ffffff");
-        INIT_COLOR(config.bar.focused, "#4c7899", "#285577", "#ffffff");
-        INIT_COLOR(config.bar.unfocused, "#333333", "#222222", "#888888");
-        INIT_COLOR(config.bar.urgent, "#2f343a", "#900000", "#ffffff");
-
-        config.default_border = BS_NORMAL;
-
-        parse_configuration(override_configpath);
-
-        if (reload) {
-                translate_keysyms();
-                grab_all_keys(conn, false);
-        }
+    do { \
+        x.border = get_colorpixel(cborder); \
+        x.background = get_colorpixel(cbackground); \
+        x.text = get_colorpixel(ctext); \
+    } while (0)
+
+    config.client.background = get_colorpixel("#000000");
+    INIT_COLOR(config.client.focused, "#4c7899", "#285577", "#ffffff");
+    INIT_COLOR(config.client.focused_inactive, "#333333", "#5f676a", "#ffffff");
+    INIT_COLOR(config.client.unfocused, "#333333", "#222222", "#888888");
+    INIT_COLOR(config.client.urgent, "#2f343a", "#900000", "#ffffff");
+    INIT_COLOR(config.bar.focused, "#4c7899", "#285577", "#ffffff");
+    INIT_COLOR(config.bar.unfocused, "#333333", "#222222", "#888888");
+    INIT_COLOR(config.bar.urgent, "#2f343a", "#900000", "#ffffff");
+
+    config.default_border = BS_NORMAL;
+    config.default_floating_border = BS_NORMAL;
+    /* Set default_orientation to NO_ORIENTATION for auto orientation. */
+    config.default_orientation = NO_ORIENTATION;
+
+    parse_configuration(override_configpath);
+
+    if (reload) {
+        translate_keysyms();
+        grab_all_keys(conn, false);
+    }
 
-        if (config.font.id == 0) {
-                ELOG("You did not specify required configuration option \"font\"\n");
-                config.font = load_font("fixed", true);
-        }
+    if (config.font.id == 0) {
+        ELOG("You did not specify required configuration option \"font\"\n");
+        config.font = load_font("fixed", true);
+    }
 
 #if 0
-        /* Set an empty name for every workspace which got no name */
-        Workspace *ws;
-        TAILQ_FOREACH(ws, workspaces, workspaces) {
-                if (ws->name != NULL) {
-                        /* If the font was not specified when the workspace name
-                         * was loaded, we need to predict the text width now */
-                        if (ws->text_width == 0)
-                                ws->text_width = predict_text_width(global_conn,
-                                                config.font, ws->name, ws->name_len);
-                        continue;
-                }
-
-                workspace_set_name(ws, NULL);
-        }
+    /* Set an empty name for every workspace which got no name */
+    Workspace *ws;
+    TAILQ_FOREACH(ws, workspaces, workspaces) {
+            if (ws->name != NULL) {
+                    /* If the font was not specified when the workspace name
+                     * was loaded, we need to predict the text width now */
+                    if (ws->text_width == 0)
+                            ws->text_width = predict_text_width(global_conn,
+                                            config.font, ws->name, ws->name_len);
+                    continue;
+            }
+
+            workspace_set_name(ws, NULL);
+    }
 #endif
 }