da1e54af529664666157f3ef3c09677c05cefa5f
[profile/ivi/weekeyboard.git] / src / wkb-ibus-helper.c
1 /*
2  * Copyright © 2013 Intel Corporation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20
21 #include "wkb-ibus-helper.h"
22 #include "wkb-log.h"
23
24 struct wkb_ibus_serializable
25 {
26    /*
27     * All messages sent by IBus will start with the sa{sv} signature, but
28     * those fields don't seem useful for us, this struct is used to help
29     * on deserializing those fields
30     */
31    char *text;
32    Eldbus_Message_Iter *variant;
33 };
34
35 typedef void (*_free_func) (void*);
36
37 static void
38 _free_eina_array(Eina_Array *array, _free_func free_cb)
39 {
40    if (!array)
41       return;
42
43    while (eina_array_count(array))
44       free_cb(eina_array_pop(array));
45
46    eina_array_free(array);
47 }
48
49 struct wkb_ibus_attr *
50 wkb_ibus_attr_from_message_iter(Eldbus_Message_Iter *iter)
51 {
52    struct wkb_ibus_attr *attr = calloc(1, sizeof(*attr));
53
54    EINA_SAFETY_ON_NULL_RETURN_VAL(attr, NULL);
55
56    DBG("Attribute iter signature '%s'", eldbus_message_iter_signature_get(iter));
57
58    if (!eldbus_message_iter_arguments_get(iter, "uuuu", &attr->type,
59                                           &attr->value, &attr->start_idx,
60                                           &attr->end_idx))
61      {
62         ERR("Error deserializing IBusAttribute");
63         wkb_ibus_attr_free(attr);
64         attr = NULL;
65      }
66
67    return attr;
68 }
69
70 void
71 wkb_ibus_attr_free(struct wkb_ibus_attr *attr)
72 {
73    free(attr);
74 }
75
76 void
77 wkb_ibus_text_free(struct wkb_ibus_text *text)
78 {
79    if (!text)
80       return;
81
82    _free_eina_array(text->attrs, (_free_func) free);
83    free(text->text);
84    free(text);
85 }
86
87 struct wkb_ibus_text *
88 wkb_ibus_text_from_message_iter(Eldbus_Message_Iter *iter)
89 {
90    struct wkb_ibus_serializable ignore = { 0 };
91    struct wkb_ibus_text *text = calloc(1, sizeof(*text));
92    struct wkb_ibus_attr *attr = NULL;
93    Eldbus_Message_Iter *attrs = NULL, *a = NULL;
94
95    EINA_SAFETY_ON_NULL_RETURN_VAL(text, NULL);
96
97    DBG("Text iter signature '%s'", eldbus_message_iter_signature_get(iter));
98
99    if (!eldbus_message_iter_arguments_get(iter, "(sa{sv}sv)", &ignore.text,
100                                           &ignore.variant, &text->text, &attrs))
101      {
102         ERR("Error deserializing IBusText");
103         free(text);
104         text = NULL;
105         goto end;
106      }
107
108    /* Check for attributes */
109    if (attrs == NULL)
110      {
111         INF("Text has no attributes");
112         goto end;
113      }
114
115    while (eldbus_message_iter_get_and_next(attrs, 'v', &a))
116      {
117         if (!text->attrs)
118            text->attrs = eina_array_new(10);
119
120         if (!(attr = wkb_ibus_attr_from_message_iter(a)))
121           {
122              wkb_ibus_text_free(text);
123              text = NULL;
124              goto end;
125           }
126
127         eina_array_push(text->attrs, attr);
128      }
129
130 end:
131    return text;
132 }
133
134 void
135 wkb_ibus_lookup_table_free(struct wkb_ibus_lookup_table *table)
136 {
137    if (!table)
138       return;
139
140    _free_eina_array(table->candidates, (_free_func) wkb_ibus_text_free);
141    _free_eina_array(table->labels, (_free_func) wkb_ibus_text_free);
142    free(table);
143 }
144
145 struct wkb_ibus_lookup_table *
146 wkb_ibus_lookup_table_from_message_iter(Eldbus_Message_Iter *iter)
147 {
148    struct wkb_ibus_serializable ignore = { 0 };
149    struct wkb_ibus_lookup_table *table = calloc(1, sizeof(*table));
150    struct wkb_ibus_text *text = NULL;
151    Eldbus_Message_Iter *candidates = NULL, *labels = NULL, *t = NULL;
152
153    EINA_SAFETY_ON_NULL_RETURN_VAL(table, NULL);
154
155    DBG("LookupTable iter signature '%s'", eldbus_message_iter_signature_get(iter));
156
157    if (!eldbus_message_iter_arguments_get(iter, "(sa{sv}uubbiavav)",
158                                           &ignore.text, &ignore.variant,
159                                           &table->page_size, &table->cursor_pos,
160                                           &table->cursor_visible, &table->round,
161                                           &table->orientation, &candidates,
162                                           &labels))
163      {
164         ERR("Error deserializing IBusLookupTable");
165         free(table);
166         table = NULL;
167         goto end;
168      }
169
170    DBG("Lookup table:");
171    DBG("\tPage size.......: '%d'", table->page_size);
172    DBG("\tCursor position.: '%d'", table->cursor_pos);
173    DBG("\tCursor visible..: '%d'", table->cursor_visible);
174    DBG("\tRound...........: '%d'", table->round);
175    DBG("\tOrientation.....: '%d'", table->orientation);
176    DBG("\tCandidates......: '%p'", candidates);
177    DBG("\tLabels..........: '%p'", labels);
178
179    if (!candidates)
180      {
181         INF("Lookup table has no candidates");
182         goto labels;
183      }
184
185    while (eldbus_message_iter_get_and_next(candidates, 'v', &t))
186      {
187         if (!table->candidates)
188            table->candidates = eina_array_new(10);
189
190         if (!(text = wkb_ibus_text_from_message_iter(t)))
191           {
192              wkb_ibus_lookup_table_free(table);
193              table = NULL;
194              goto end;
195           }
196
197         DBG("Appending new candidate %s", text->text);
198         eina_array_push(table->candidates, text);
199      }
200
201 labels:
202    if (!labels)
203      {
204         INF("Lookup table has no labels");
205         goto end;
206      }
207
208    while (eldbus_message_iter_get_and_next(labels, 'v', &t))
209      {
210         if (!table->labels)
211            table->labels = eina_array_new(10);
212
213         if (!(text = wkb_ibus_text_from_message_iter(t)))
214           {
215              wkb_ibus_lookup_table_free(table);
216              table = NULL;
217              goto end;
218           }
219
220         DBG("Appending new label %s", text->text);
221         eina_array_push(table->labels, text);
222      }
223
224 end:
225    return table;
226 }
227
228 void
229 wkb_ibus_property_free(struct wkb_ibus_property *property)
230 {
231    if (!property)
232       return;
233
234    free(property->key);
235    free(property->icon);
236    wkb_ibus_text_free(property->label);
237    wkb_ibus_text_free(property->symbol);
238    wkb_ibus_text_free(property->tooltip);
239    _free_eina_array(property->sub_properties, (_free_func) wkb_ibus_property_free);
240    free(property);
241 }
242
243 struct wkb_ibus_property *
244 wkb_ibus_property_from_message_iter(Eldbus_Message_Iter *iter)
245 {
246    struct wkb_ibus_serializable ignore = { 0 };
247    struct wkb_ibus_property *prop = calloc(1, sizeof(*prop));
248    Eldbus_Message_Iter *label = NULL, *symbol = NULL, *tooltip = NULL, *sub_props = NULL;
249
250    EINA_SAFETY_ON_NULL_RETURN_VAL(prop, NULL);
251
252    DBG("Property iter signature '%s'", eldbus_message_iter_signature_get(iter));
253
254    if (!eldbus_message_iter_arguments_get(iter, "(sa{sv}suvsvbbuvv)",
255                                           &ignore.text, &ignore.variant,
256                                           &prop->key, &prop->type,
257                                           &label, &prop->icon, &tooltip,
258                                           &prop->sensitive, &prop->visible,
259                                           &prop->state, &sub_props, &symbol))
260      {
261         ERR("Error deserializing IBusProperty");
262         free(prop);
263         prop = NULL;
264         goto end;
265      }
266
267    DBG("Property :");
268    DBG("\tKey.............: '%s'", prop->key);
269    DBG("\tType............: '%d'", prop->type);
270    DBG("\tLabel...........: '%p'", label);
271    DBG("\tIcon............: '%s'", prop->icon);
272    DBG("\tTooltip.........: '%p'", tooltip);
273    DBG("\tSensitive.......: '%d'", prop->sensitive);
274    DBG("\tVisible.........: '%d'", prop->visible);
275    DBG("\tState...........: '%d'", prop->state);
276    DBG("\tSub Properties..: '%p'", sub_props);
277    DBG("\tSymbol..........: '%p'", symbol);
278
279    if (!label)
280      {
281         INF("Property has no label");
282         goto symbol;
283      }
284
285    if (!(prop->label = wkb_ibus_text_from_message_iter(label)))
286      {
287         wkb_ibus_property_free(prop);
288         prop = NULL;
289         goto end;
290      }
291
292 symbol:
293    if (!symbol)
294      {
295         INF("Property has no symbol");
296         goto tooltip;
297      }
298
299    if (!(prop->symbol = wkb_ibus_text_from_message_iter(symbol)))
300      {
301         wkb_ibus_property_free(prop);
302         prop = NULL;
303         goto end;
304      }
305
306 tooltip:
307    if (!tooltip)
308      {
309         INF("Property has no tooltip");
310         goto sub_props;
311      }
312
313    if (!(prop->tooltip = wkb_ibus_text_from_message_iter(tooltip)))
314      {
315         wkb_ibus_property_free(prop);
316         prop = NULL;
317         goto end;
318      }
319
320 sub_props:
321    if (!sub_props)
322      {
323         INF("Property has no sub properties");
324         goto end;
325      }
326
327    prop->sub_properties = wkb_ibus_properties_from_message_iter(sub_props);
328
329 end:
330    return prop;
331 }
332
333 void
334 wkb_ibus_properties_free(Eina_Array *properties)
335 {
336    _free_eina_array(properties, (_free_func) wkb_ibus_property_free);
337 }
338
339 Eina_Array *
340 wkb_ibus_properties_from_message_iter(Eldbus_Message_Iter *iter)
341 {
342    Eina_Array *properties = NULL;
343    Eldbus_Message_Iter *props = NULL, *prop = NULL;
344    struct wkb_ibus_serializable ignore = { 0 };
345    struct wkb_ibus_property *property = NULL;
346
347    DBG("PropList iter signature '%s'", eldbus_message_iter_signature_get(iter));
348
349    if (!eldbus_message_iter_arguments_get(iter, "(sa{sv}av)", &ignore.text, &ignore.variant, &props))
350      {
351         ERR("Error deserializing IBusPropList");
352         goto end;
353      }
354
355    if (!props)
356      {
357         INF("PropList has no property");
358         goto end;
359      }
360
361    while (eldbus_message_iter_get_and_next(props, 'v', &prop))
362      {
363         if (!properties)
364            properties = eina_array_new(10);
365
366         if (!(property = wkb_ibus_property_from_message_iter(prop)))
367           {
368              wkb_ibus_properties_free(properties);
369              properties = NULL;
370              goto end;
371           }
372
373         DBG("Appending new property %p", property);
374         eina_array_push(properties, property);
375      }
376
377 end:
378    return properties;
379 }
380