2 * vim:ts=4:sw=4:expandtab
4 * i3bar - an xcb-based status- and ws-bar for i3
5 * © 2010-2011 Axel Wagner and contributors (see also: LICENSE)
7 * config.c: Parses the configuration (received from i3).
15 #include <yajl/yajl_parse.h>
16 #include <yajl/yajl_version.h>
25 * Essentially we just save it in cur_key.
29 static int config_map_key_cb(void *params_, const unsigned char *keyVal, size_t keyLen) {
31 static int config_map_key_cb(void *params_, const unsigned char *keyVal, unsigned keyLen) {
35 cur_key = smalloc(sizeof(unsigned char) * (keyLen + 1));
36 strncpy(cur_key, (const char*) keyVal, keyLen);
37 cur_key[keyLen] = '\0';
43 * Parse a null-value (current_workspace)
46 static int config_null_cb(void *params_) {
47 if (!strcmp(cur_key, "id")) {
48 /* If 'id' is NULL, the bar config was not found. Error out. */
49 ELOG("No such bar config. Use 'i3-msg -t get_bar_config' to get the available configs.\n");
50 ELOG("Are you starting i3bar by hand? You should not:\n");
51 ELOG("Configure a 'bar' block in your i3 config and i3 will launch i3bar automatically.\n");
63 static int config_string_cb(void *params_, const unsigned char *val, size_t _len) {
65 static int config_string_cb(void *params_, const unsigned char *val, unsigned int _len) {
68 /* The id is ignored, we already have it in config.bar_id */
69 if (!strcmp(cur_key, "id"))
72 if (!strcmp(cur_key, "mode")) {
73 DLOG("mode = %.*s, len = %d\n", len, val, len);
74 config.hide_on_modifier = (len == 4 && !strncmp((const char*)val, "hide", strlen("hide")));
78 if (!strcmp(cur_key, "position")) {
79 DLOG("position = %.*s\n", len, val);
80 config.position = (len == 3 && !strncmp((const char*)val, "top", strlen("top")) ? POS_TOP : POS_BOT);
84 if (!strcmp(cur_key, "status_command")) {
85 /* We cannot directly start the child here, because start_child() also
86 * needs to be run when no command was specified (to setup stdin).
87 * Therefore we save the command in 'config' and access it later in
89 DLOG("command = %.*s\n", len, val);
90 sasprintf(&config.command, "%.*s", len, val);
94 if (!strcmp(cur_key, "font")) {
95 DLOG("font = %.*s\n", len, val);
96 sasprintf(&config.fontname, "%.*s", len, val);
100 if (!strcmp(cur_key, "outputs")) {
101 DLOG("+output %.*s\n", len, val);
102 int new_num_outputs = config.num_outputs + 1;
103 config.outputs = srealloc(config.outputs, sizeof(char*) * new_num_outputs);
104 sasprintf(&config.outputs[config.num_outputs], "%.*s", len, val);
105 config.num_outputs = new_num_outputs;
109 if (!strcmp(cur_key, "tray_output")) {
110 DLOG("tray_output %.*s\n", len, val);
111 FREE(config.tray_output);
112 sasprintf(&config.tray_output, "%.*s", len, val);
116 #define COLOR(json_name, struct_name) \
118 if (!strcmp(cur_key, #json_name)) { \
119 DLOG(#json_name " = " #struct_name " = %.*s\n", len, val); \
120 sasprintf(&(config.colors.struct_name), "%.*s", len, val); \
125 COLOR(statusline, bar_fg);
126 COLOR(background, bar_bg);
127 COLOR(focused_workspace_text, focus_ws_fg);
128 COLOR(focused_workspace_bg, focus_ws_bg);
129 COLOR(active_workspace_text, active_ws_fg);
130 COLOR(active_workspace_bg, active_ws_bg);
131 COLOR(inactive_workspace_text, inactive_ws_fg);
132 COLOR(inactive_workspace_bg, inactive_ws_bg);
133 COLOR(urgent_workspace_text, urgent_ws_fg);
134 COLOR(urgent_workspace_bg, urgent_ws_bg);
136 printf("got unexpected string %.*s for cur_key = %s\n", len, val, cur_key);
142 * Parse a boolean value
145 static int config_boolean_cb(void *params_, int val) {
146 if (!strcmp(cur_key, "workspace_buttons")) {
147 DLOG("workspace_buttons = %d\n", val);
148 config.disable_ws = !val;
152 if (!strcmp(cur_key, "verbose")) {
153 DLOG("verbose = %d\n", val);
154 config.verbose = val;
161 /* A datastructure to pass all these callbacks to yajl */
162 static yajl_callbacks outputs_callbacks = {
177 * Start parsing the received bar configuration json-string
180 void parse_config_json(char *json) {
184 yajl_parser_config parse_conf = { 0, 0 };
186 handle = yajl_alloc(&outputs_callbacks, &parse_conf, NULL, NULL);
188 handle = yajl_alloc(&outputs_callbacks, NULL, NULL);
191 state = yajl_parse(handle, (const unsigned char*) json, strlen(json));
193 /* FIXME: Proper errorhandling for JSON-parsing */
197 case yajl_status_client_canceled:
199 case yajl_status_insufficient_data:
201 case yajl_status_error:
202 ELOG("Could not parse config-reply!\n");
211 * free()s the color strings as soon as they are not needed anymore.
214 void free_colors(struct xcb_color_strings_t *colors) {
215 #define FREE_COLOR(x) \
222 FREE_COLOR(active_ws_fg);
223 FREE_COLOR(active_ws_bg);
224 FREE_COLOR(inactive_ws_fg);
225 FREE_COLOR(inactive_ws_bg);
226 FREE_COLOR(urgent_ws_fg);
227 FREE_COLOR(urgent_ws_bg);
228 FREE_COLOR(focus_ws_fg);
229 FREE_COLOR(focus_ws_bg);