]> git.sur5r.net Git - i3/i3/blob - src/load_layout.c
Also store/load window_rect when restarting
[i3/i3] / src / load_layout.c
1 /*
2  * vim:ts=4:sw=4:expandtab
3  *
4  */
5 #include <yajl/yajl_common.h>
6 #include <yajl/yajl_gen.h>
7 #include <yajl/yajl_parse.h>
8
9 #include "all.h"
10
11 /* TODO: refactor the whole parsing thing */
12
13 static char *last_key;
14 static Con *json_node;
15 static Con *to_focus;
16 static bool parsing_swallows;
17 static bool parsing_rect;
18 static bool parsing_window_rect;
19 struct Match *current_swallow;
20
21 static int json_start_map(void *ctx) {
22     LOG("start of map\n");
23     if (parsing_swallows) {
24         LOG("TODO: create new swallow\n");
25         current_swallow = smalloc(sizeof(Match));
26         match_init(current_swallow);
27         TAILQ_INSERT_TAIL(&(json_node->swallow_head), current_swallow, matches);
28     } else {
29         if (!parsing_rect && !parsing_window_rect)
30             json_node = con_new(json_node);
31     }
32     return 1;
33 }
34
35 static int json_end_map(void *ctx) {
36     LOG("end of map\n");
37     if (!parsing_swallows && !parsing_rect && !parsing_window_rect)
38         json_node = json_node->parent;
39     if (parsing_rect)
40         parsing_rect = false;
41     if (parsing_window_rect)
42         parsing_window_rect = false;
43     return 1;
44 }
45
46 static int json_end_array(void *ctx) {
47     LOG("end of array\n");
48     parsing_swallows = false;
49     return 1;
50 }
51
52 static int json_key(void *ctx, const unsigned char *val, unsigned int len) {
53     LOG("key: %.*s\n", len, val);
54     FREE(last_key);
55     last_key = scalloc((len+1) * sizeof(char));
56     memcpy(last_key, val, len);
57     if (strcasecmp(last_key, "swallows") == 0) {
58         parsing_swallows = true;
59     }
60     if (strcasecmp(last_key, "rect") == 0)
61         parsing_rect = true;
62     if (strcasecmp(last_key, "window_rect") == 0)
63         parsing_window_rect = true;
64     return 1;
65 }
66
67 static int json_string(void *ctx, const unsigned char *val, unsigned int len) {
68     LOG("string: %.*s for key %s\n", len, val, last_key);
69     if (parsing_swallows) {
70         /* TODO: the other swallowing keys */
71         if (strcasecmp(last_key, "class") == 0) {
72             current_swallow->class = scalloc((len+1) * sizeof(char));
73             memcpy(current_swallow->class, val, len);
74         }
75         LOG("unhandled yet: swallow\n");
76     } else {
77         if (strcasecmp(last_key, "name") == 0) {
78             json_node->name = scalloc((len+1) * sizeof(char));
79             memcpy(json_node->name, val, len);
80         } else if (strcasecmp(last_key, "sticky_group") == 0) {
81             json_node->sticky_group = scalloc((len+1) * sizeof(char));
82             memcpy(json_node->sticky_group, val, len);
83             LOG("sticky_group of this container is %s\n", json_node->sticky_group);
84         }
85     }
86     return 1;
87 }
88
89 static int json_int(void *ctx, long val) {
90     LOG("int %d for key %s\n", val, last_key);
91     if (strcasecmp(last_key, "orientation") == 0) {
92         json_node->orientation = val;
93     }
94     if (strcasecmp(last_key, "layout") == 0) {
95         json_node->layout = val;
96     }
97     if (strcasecmp(last_key, "type") == 0) {
98         json_node->type = val;
99     }
100     if (strcasecmp(last_key, "fullscreen_mode") == 0) {
101         json_node->fullscreen_mode = val;
102     }
103     if (strcasecmp(last_key, "focused") == 0 && val == 1) {
104         to_focus = json_node;
105     }
106
107     if (parsing_rect || parsing_window_rect) {
108         Rect *r = (parsing_rect ? &(json_node->rect) : &(json_node->window_rect));
109         if (strcasecmp(last_key, "x") == 0)
110             r->x = val;
111         else if (strcasecmp(last_key, "y") == 0)
112             r->y = val;
113         else if (strcasecmp(last_key, "width") == 0)
114             r->width = val;
115         else if (strcasecmp(last_key, "height") == 0)
116             r->height = val;
117         else printf("WARNING: unknown key %s in rect\n", last_key);
118         printf("rect now: (%d, %d, %d, %d)\n",
119                 r->x, r->y, r->width, r->height);
120     }
121     if (parsing_swallows) {
122         if (strcasecmp(last_key, "id") == 0) {
123             current_swallow->id = val;
124         }
125         if (strcasecmp(last_key, "dock") == 0) {
126             current_swallow->dock = true;
127         }
128     }
129
130     return 1;
131 }
132
133 static int json_double(void *ctx, double val) {
134     LOG("double %f for key %s\n", val, last_key);
135     if (strcasecmp(last_key, "percent") == 0) {
136         json_node->percent = val;
137     }
138     return 1;
139 }
140
141 void tree_append_json(const char *filename) {
142     /* TODO: percent of other windows are not correctly fixed at the moment */
143     FILE *f;
144     if ((f = fopen(filename, "r")) == NULL) {
145         LOG("Cannot open file\n");
146         return;
147     }
148     char *buf = malloc(65535); /* TODO */
149     int n = fread(buf, 1, 65535, f);
150     LOG("read %d bytes\n", n);
151     yajl_gen g;
152     yajl_handle hand;
153     yajl_callbacks callbacks;
154     memset(&callbacks, '\0', sizeof(yajl_callbacks));
155     callbacks.yajl_start_map = json_start_map;
156     callbacks.yajl_end_map = json_end_map;
157     callbacks.yajl_end_array = json_end_array;
158     callbacks.yajl_string = json_string;
159     callbacks.yajl_map_key = json_key;
160     callbacks.yajl_integer = json_int;
161     callbacks.yajl_double = json_double;
162     g = yajl_gen_alloc(NULL, NULL);
163     hand = yajl_alloc(&callbacks, NULL, NULL, (void*)g);
164     yajl_status stat;
165     json_node = focused;
166     to_focus = NULL;
167     parsing_rect = false;
168     parsing_window_rect = false;
169     setlocale(LC_NUMERIC, "C");
170     stat = yajl_parse(hand, (const unsigned char*)buf, n);
171     if (stat != yajl_status_ok &&
172         stat != yajl_status_insufficient_data)
173     {
174         unsigned char * str = yajl_get_error(hand, 1, (const unsigned char*)buf, n);
175         fprintf(stderr, (const char *) str);
176         yajl_free_error(hand, str);
177     }
178
179     setlocale(LC_NUMERIC, "");
180     yajl_parse_complete(hand);
181
182     fclose(f);
183     if (to_focus)
184         con_focus(to_focus);
185 }