i3
|
00001 /* 00002 * vim:ts=4:sw=4:expandtab 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 /* TODO: refactor the whole parsing thing */ 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 /* TODO: the other swallowing keys */ 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 // TODO: remove this after the next preview release 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 /* TODO: percent of other windows are not correctly fixed at the moment */ 00221 FILE *f; 00222 if ((f = fopen(filename, "r")) == NULL) { 00223 LOG("Cannot open file\n"); 00224 return; 00225 } 00226 char *buf = malloc(65535); /* TODO */ 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 }