00001
00002
00003
00004
00005 #include <yajl/yajl_common.h>
00006 #include <yajl/yajl_gen.h>
00007 #include <yajl/yajl_parse.h>
00008 #include <yajl/yajl_version.h>
00009
00010 #include "all.h"
00011
00012
00013
00014 static char *last_key;
00015 static Con *json_node;
00016 static Con *to_focus;
00017 static bool parsing_swallows;
00018 static bool parsing_rect;
00019 static bool parsing_window_rect;
00020 static bool parsing_geometry;
00021 struct Match *current_swallow;
00022
00023 static int json_start_map(void *ctx) {
00024 LOG("start of map, last_key = %s\n", last_key);
00025 if (parsing_swallows) {
00026 LOG("creating new swallow\n");
00027 current_swallow = smalloc(sizeof(Match));
00028 match_init(current_swallow);
00029 TAILQ_INSERT_TAIL(&(json_node->swallow_head), current_swallow, matches);
00030 } else {
00031 if (!parsing_rect && !parsing_window_rect && !parsing_geometry) {
00032 if (last_key && strcasecmp(last_key, "floating_nodes") == 0) {
00033 DLOG("New floating_node\n");
00034 Con *ws = con_get_workspace(json_node);
00035 json_node = con_new(NULL, NULL);
00036 json_node->parent = ws;
00037 DLOG("Parent is workspace = %p\n", ws);
00038 } else {
00039 Con *parent = json_node;
00040 json_node = con_new(NULL, NULL);
00041 json_node->parent = parent;
00042 }
00043 }
00044 }
00045 return 1;
00046 }
00047
00048 static int json_end_map(void *ctx) {
00049 LOG("end of map\n");
00050 if (!parsing_swallows && !parsing_rect && !parsing_window_rect && !parsing_geometry) {
00051 LOG("attaching\n");
00052 con_attach(json_node, json_node->parent, true);
00053 json_node = json_node->parent;
00054 }
00055 if (parsing_rect)
00056 parsing_rect = false;
00057 if (parsing_window_rect)
00058 parsing_window_rect = false;
00059 if (parsing_geometry)
00060 parsing_geometry = false;
00061 return 1;
00062 }
00063
00064 static int json_end_array(void *ctx) {
00065 LOG("end of array\n");
00066 parsing_swallows = false;
00067 return 1;
00068 }
00069
00070 #if YAJL_MAJOR < 2
00071 static int json_key(void *ctx, const unsigned char *val, unsigned int len) {
00072 #else
00073 static int json_key(void *ctx, const unsigned char *val, size_t len) {
00074 #endif
00075 LOG("key: %.*s\n", (int)len, val);
00076 FREE(last_key);
00077 last_key = scalloc((len+1) * sizeof(char));
00078 memcpy(last_key, val, len);
00079 if (strcasecmp(last_key, "swallows") == 0) {
00080 parsing_swallows = true;
00081 }
00082 if (strcasecmp(last_key, "rect") == 0)
00083 parsing_rect = true;
00084 if (strcasecmp(last_key, "window_rect") == 0)
00085 parsing_window_rect = true;
00086 if (strcasecmp(last_key, "geometry") == 0)
00087 parsing_geometry = true;
00088 return 1;
00089 }
00090
00091 #if YAJL_MAJOR >= 2
00092 static int json_string(void *ctx, const unsigned char *val, size_t len) {
00093 #else
00094 static int json_string(void *ctx, const unsigned char *val, unsigned int len) {
00095 #endif
00096 LOG("string: %.*s for key %s\n", len, val, last_key);
00097 if (parsing_swallows) {
00098
00099 if (strcasecmp(last_key, "class") == 0) {
00100 current_swallow->class = scalloc((len+1) * sizeof(char));
00101 memcpy(current_swallow->class, val, len);
00102 }
00103 LOG("unhandled yet: swallow\n");
00104 } else {
00105 if (strcasecmp(last_key, "name") == 0) {
00106 json_node->name = scalloc((len+1) * sizeof(char));
00107 memcpy(json_node->name, val, len);
00108 } else if (strcasecmp(last_key, "sticky_group") == 0) {
00109 json_node->sticky_group = scalloc((len+1) * sizeof(char));
00110 memcpy(json_node->sticky_group, val, len);
00111 LOG("sticky_group of this container is %s\n", json_node->sticky_group);
00112 } else if (strcasecmp(last_key, "orientation") == 0) {
00113 char *buf = NULL;
00114 asprintf(&buf, "%.*s", (int)len, val);
00115 if (strcasecmp(buf, "none") == 0)
00116 json_node->orientation = NO_ORIENTATION;
00117 else if (strcasecmp(buf, "horizontal") == 0)
00118 json_node->orientation = HORIZ;
00119 else if (strcasecmp(buf, "vertical") == 0)
00120 json_node->orientation = VERT;
00121 else LOG("Unhandled orientation: %s\n", buf);
00122 free(buf);
00123 } else if (strcasecmp(last_key, "border") == 0) {
00124 char *buf = NULL;
00125 asprintf(&buf, "%.*s", (int)len, val);
00126 if (strcasecmp(buf, "none") == 0)
00127 json_node->border_style = BS_NONE;
00128 else if (strcasecmp(buf, "1pixel") == 0)
00129 json_node->border_style = BS_1PIXEL;
00130 else if (strcasecmp(buf, "normal") == 0)
00131 json_node->border_style = BS_NORMAL;
00132 else LOG("Unhandled \"border\": %s\n", buf);
00133 free(buf);
00134 } else if (strcasecmp(last_key, "layout") == 0) {
00135 char *buf = NULL;
00136 asprintf(&buf, "%.*s", (int)len, val);
00137 if (strcasecmp(buf, "default") == 0)
00138 json_node->layout = L_DEFAULT;
00139 else if (strcasecmp(buf, "stacked") == 0)
00140 json_node->layout = L_STACKED;
00141 else if (strcasecmp(buf, "tabbed") == 0)
00142 json_node->layout = L_TABBED;
00143 else if (strcasecmp(buf, "dockarea") == 0)
00144 json_node->layout = L_DOCKAREA;
00145 else if (strcasecmp(buf, "output") == 0)
00146 json_node->layout = L_OUTPUT;
00147 else LOG("Unhandled \"layout\": %s\n", buf);
00148 free(buf);
00149 }
00150 }
00151 return 1;
00152 }
00153
00154 #if YAJL_MAJOR >= 2
00155 static int json_int(void *ctx, long long val) {
00156 #else
00157 static int json_int(void *ctx, long val) {
00158 #endif
00159 LOG("int %d for key %s\n", val, last_key);
00160
00161 if (strcasecmp(last_key, "layout") == 0) {
00162 json_node->layout = val;
00163 }
00164 if (strcasecmp(last_key, "type") == 0) {
00165 json_node->type = val;
00166 }
00167 if (strcasecmp(last_key, "fullscreen_mode") == 0) {
00168 json_node->fullscreen_mode = val;
00169 }
00170 if (strcasecmp(last_key, "focused") == 0 && val == 1) {
00171 to_focus = json_node;
00172 }
00173
00174 if (strcasecmp(last_key, "num") == 0)
00175 json_node->num = val;
00176
00177 if (parsing_rect || parsing_window_rect || parsing_geometry) {
00178 Rect *r;
00179 if (parsing_rect)
00180 r = &(json_node->rect);
00181 else if (parsing_window_rect)
00182 r = &(json_node->window_rect);
00183 else r = &(json_node->geometry);
00184 if (strcasecmp(last_key, "x") == 0)
00185 r->x = val;
00186 else if (strcasecmp(last_key, "y") == 0)
00187 r->y = val;
00188 else if (strcasecmp(last_key, "width") == 0)
00189 r->width = val;
00190 else if (strcasecmp(last_key, "height") == 0)
00191 r->height = val;
00192 else printf("WARNING: unknown key %s in rect\n", last_key);
00193 printf("rect now: (%d, %d, %d, %d)\n",
00194 r->x, r->y, r->width, r->height);
00195 }
00196 if (parsing_swallows) {
00197 if (strcasecmp(last_key, "id") == 0) {
00198 current_swallow->id = val;
00199 }
00200 if (strcasecmp(last_key, "dock") == 0) {
00201 current_swallow->dock = val;
00202 }
00203 if (strcasecmp(last_key, "insert_where") == 0) {
00204 current_swallow->insert_where = val;
00205 }
00206 }
00207
00208 return 1;
00209 }
00210
00211 static int json_double(void *ctx, double val) {
00212 LOG("double %f for key %s\n", val, last_key);
00213 if (strcasecmp(last_key, "percent") == 0) {
00214 json_node->percent = val;
00215 }
00216 return 1;
00217 }
00218
00219 void tree_append_json(const char *filename) {
00220
00221 FILE *f;
00222 if ((f = fopen(filename, "r")) == NULL) {
00223 LOG("Cannot open file\n");
00224 return;
00225 }
00226 char *buf = malloc(65535);
00227 int n = fread(buf, 1, 65535, f);
00228 LOG("read %d bytes\n", n);
00229 yajl_gen g;
00230 yajl_handle hand;
00231 yajl_callbacks callbacks;
00232 memset(&callbacks, '\0', sizeof(yajl_callbacks));
00233 callbacks.yajl_start_map = json_start_map;
00234 callbacks.yajl_end_map = json_end_map;
00235 callbacks.yajl_end_array = json_end_array;
00236 callbacks.yajl_string = json_string;
00237 callbacks.yajl_map_key = json_key;
00238 callbacks.yajl_integer = json_int;
00239 callbacks.yajl_double = json_double;
00240 #if YAJL_MAJOR >= 2
00241 g = yajl_gen_alloc(NULL);
00242 hand = yajl_alloc(&callbacks, NULL, (void*)g);
00243 #else
00244 g = yajl_gen_alloc(NULL, NULL);
00245 hand = yajl_alloc(&callbacks, NULL, NULL, (void*)g);
00246 #endif
00247 yajl_status stat;
00248 json_node = focused;
00249 to_focus = NULL;
00250 parsing_rect = false;
00251 parsing_window_rect = false;
00252 parsing_geometry = false;
00253 setlocale(LC_NUMERIC, "C");
00254 stat = yajl_parse(hand, (const unsigned char*)buf, n);
00255 if (stat != yajl_status_ok)
00256 {
00257 unsigned char * str = yajl_get_error(hand, 1, (const unsigned char*)buf, n);
00258 fprintf(stderr, "%s\n", (const char *) str);
00259 yajl_free_error(hand, str);
00260 }
00261
00262 setlocale(LC_NUMERIC, "");
00263 #if YAJL_MAJOR >= 2
00264 yajl_complete_parse(hand);
00265 #else
00266 yajl_parse_complete(hand);
00267 #endif
00268
00269 fclose(f);
00270 if (to_focus)
00271 con_focus(to_focus);
00272 }