]> git.sur5r.net Git - i3/i3/blob - i3bar/src/workspaces.c
We don't need a callback for null-values
[i3/i3] / i3bar / src / workspaces.c
1 #include <string.h>
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <yajl/yajl_parse.h>
5
6 #include "common.h"
7
8 struct workspaces_json_params {
9     struct ws_head *workspaces;
10     i3_ws          *workspaces_walk;
11     char           *cur_key;
12     char           *json;
13 };
14
15 static int workspaces_boolean_cb(void *params_, bool val) {
16     struct workspaces_json_params *params = (struct workspaces_json_params*) params_;
17
18     if (!strcmp(params->cur_key, "visible")) {
19         params->workspaces_walk->visible = val;
20         FREE(params->cur_key);
21         return 1;
22     }
23
24     if (!strcmp(params->cur_key, "focused")) {
25         params->workspaces_walk->focused = val;
26         FREE(params->cur_key);
27         return 1;
28     }
29
30     if (!strcmp(params->cur_key, "urgent")) {
31         params->workspaces_walk->urgent = val;
32         FREE(params->cur_key);
33         return 1;
34     }
35
36     FREE(params->cur_key);
37
38     return 0;
39 }
40
41 static int workspaces_integer_cb(void *params_, long val) {
42     struct workspaces_json_params *params = (struct workspaces_json_params*) params_;
43
44     if (!strcmp(params->cur_key, "num")) {
45         params->workspaces_walk->num = (int) val;
46         FREE(params->cur_key);
47         return 1;
48     }
49
50     if (!strcmp(params->cur_key, "x")) {
51         params->workspaces_walk->rect.x = (int) val;
52         FREE(params->cur_key);
53         return 1;
54     }
55
56     if (!strcmp(params->cur_key, "y")) {
57         params->workspaces_walk->rect.y = (int) val;
58         FREE(params->cur_key);
59         return 1;
60     }
61
62     if (!strcmp(params->cur_key, "width")) {
63         params->workspaces_walk->rect.w = (int) val;
64         FREE(params->cur_key);
65         return 1;
66     }
67
68     if (!strcmp(params->cur_key, "height")) {
69         params->workspaces_walk->rect.h = (int) val;
70         FREE(params->cur_key);
71         return 1;
72     }
73
74     FREE(params->cur_key);
75     return 0;
76 }
77
78 static int workspaces_string_cb(void *params_, const unsigned char *val, unsigned int len) {
79
80         struct workspaces_json_params *params = (struct workspaces_json_params*) params_;
81
82         char *output_name;
83
84         if (!strcmp(params->cur_key, "name")) {
85             params->workspaces_walk->name = malloc(sizeof(const unsigned char) * (len + 1));
86             strncpy(params->workspaces_walk->name, (const char*) val, len);
87             params->workspaces_walk->name[len] = '\0';
88
89             int ucs2_len;
90             xcb_char2b_t *ucs2_name = (xcb_char2b_t*) convert_utf8_to_ucs2(params->workspaces_walk->name, &ucs2_len);
91             params->workspaces_walk->ucs2_name = ucs2_name;
92             params->workspaces_walk->name_glyphs = ucs2_len;
93             params->workspaces_walk->name_width = get_string_width(params->workspaces_walk->ucs2_name,
94                                                                    params->workspaces_walk->name_glyphs);
95
96             printf("Got Workspace %s, name_width: %d, glyphs: %d\n",
97                    params->workspaces_walk->name,
98                    params->workspaces_walk->name_width,
99                    params->workspaces_walk->name_glyphs);
100             FREE(params->cur_key);
101
102             return 1;
103         }
104
105         if (!strcmp(params->cur_key, "output")) {
106             output_name = malloc(sizeof(const unsigned char) * (len + 1));
107             strncpy(output_name, (const char*) val, len);
108             output_name[len] = '\0';
109             params->workspaces_walk->output = get_output_by_name(output_name);
110
111             TAILQ_INSERT_TAIL(params->workspaces_walk->output->workspaces,
112                               params->workspaces_walk,
113                               tailq);
114
115             FREE(output_name);
116             return 1;
117         }
118
119         return 0;
120 }
121
122 static int workspaces_start_map_cb(void *params_) {
123     struct workspaces_json_params *params = (struct workspaces_json_params*) params_;
124
125     i3_ws *new_workspace = NULL;
126
127     if (params->cur_key == NULL) {
128         new_workspace = malloc(sizeof(i3_ws));
129         new_workspace->num = -1;
130         new_workspace->name = NULL;
131         new_workspace->visible = 0;
132         new_workspace->focused = 0;
133         new_workspace->urgent = 0;
134         memset(&new_workspace->rect, 0, sizeof(rect));
135         new_workspace->output = NULL;
136
137         params->workspaces_walk = new_workspace;
138         return 1;
139     }
140
141     return 1;
142 }
143
144 static int workspaces_map_key_cb(void *params_, const unsigned char *keyVal, unsigned int keyLen) {
145     struct workspaces_json_params *params = (struct workspaces_json_params*) params_;
146     FREE(params->cur_key);
147
148     params->cur_key = malloc(sizeof(unsigned char) * (keyLen + 1));
149     if (params->cur_key == NULL) {
150         printf("ERROR: Could not allocate memory!\n");
151         exit(EXIT_FAILURE);
152     }
153     strncpy(params->cur_key, (const char*) keyVal, keyLen);
154     params->cur_key[keyLen] = '\0';
155
156     return 1;
157 }
158
159 yajl_callbacks workspaces_callbacks = {
160     NULL,
161     &workspaces_boolean_cb,
162     &workspaces_integer_cb,
163     NULL,
164     NULL,
165     &workspaces_string_cb,
166     &workspaces_start_map_cb,
167     &workspaces_map_key_cb,
168     NULL,
169     NULL,
170     NULL
171 };
172
173 void parse_workspaces_json(char *json) {
174     /* FIXME: Fasciliate stream-processing, i.e. allow starting to interpret
175      * JSON in chunks */
176     struct workspaces_json_params params;
177
178     free_workspaces();
179
180     params.workspaces_walk = NULL;
181     params.cur_key = NULL;
182     params.json = json;
183
184     yajl_handle handle;
185     yajl_parser_config parse_conf = { 0, 0 };
186     yajl_status state;
187
188     handle = yajl_alloc(&workspaces_callbacks, &parse_conf, NULL, (void*) &params);
189
190     state = yajl_parse(handle, (const unsigned char*) json, strlen(json));
191
192     /* FIXME: Propper errorhandling for JSON-parsing */
193     switch (state) {
194         case yajl_status_ok:
195             break;
196         case yajl_status_client_canceled:
197         case yajl_status_insufficient_data:
198         case yajl_status_error:
199             printf("ERROR: Could not parse workspaces-reply!\n");
200             exit(EXIT_FAILURE);
201             break;
202     }
203
204     yajl_free(handle);
205
206     FREE(params.cur_key);
207 }
208
209 void free_workspaces() {
210     i3_output *outputs_walk;
211     SLIST_FOREACH(outputs_walk, outputs, slist) {
212         if (outputs_walk->workspaces != NULL && !TAILQ_EMPTY(outputs_walk->workspaces)) {
213             FREE_TAILQ(outputs_walk->workspaces, i3_ws);
214         }
215     }
216 }