39f72ceffbf9210baf78168c960de1f9f9470386
[src/app-framework-main.git] / src / wgt-config.c
1 /*
2  Copyright 2015, 2016 IoT.bzh
3
4  author: José Bollo <jose.bollo@iot.bzh>
5
6  Licensed under the Apache License, Version 2.0 (the "License");
7  you may not use this file except in compliance with the License.
8  You may obtain a copy of the License at
9
10      http://www.apache.org/licenses/LICENSE-2.0
11
12  Unless required by applicable law or agreed to in writing, software
13  distributed under the License is distributed on an "AS IS" BASIS,
14  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  See the License for the specific language governing permissions and
16  limitations under the License.
17 */
18
19 #include <unistd.h>
20 #include <string.h>
21 #include <assert.h>
22 #include <errno.h>
23
24 #include <libxml/parser.h>
25 #include <libxml/tree.h>
26 #include <libxml/uri.h>
27
28 #include "verbose.h"
29 #include "wgt.h"
30 #include "wgt-config.h"
31
32 const char wgt_config_string_author[] = "author";
33 const char wgt_config_string_content[] = "content";
34 const char wgt_config_string_defaultlocale[] = "defaultlocale";
35 const char wgt_config_string_description[] = "description";
36 const char wgt_config_string_email[] = "email";
37 const char wgt_config_string_encoding[] = "encoding";
38 const char wgt_config_string_feature[] = "feature";
39 const char wgt_config_string_height[] = "height";
40 const char wgt_config_string_href[] = "href";
41 const char wgt_config_string_icon[] = "icon";
42 const char wgt_config_string_id[] = "id";
43 const char wgt_config_string_license[] = "license";
44 const char wgt_config_string_name[] = "name";
45 const char wgt_config_string_param[] = "param";
46 const char wgt_config_string_preference[] = "preference";
47 const char wgt_config_string_readonly[] = "readonly";
48 const char wgt_config_string_required[] = "required";
49 const char wgt_config_string_short[] = "short";
50 const char wgt_config_string_src[] = "src";
51 const char wgt_config_string_type[] = "type";
52 const char wgt_config_string_value[] = "value";
53 const char wgt_config_string_version[] = "version";
54 const char wgt_config_string_viewmodes[] = "viewmodes";
55 const char wgt_config_string_widget[] = "widget";
56 const char wgt_config_string_width[] = "width";
57 const char wgt_config_string_xml_file[] = "config.xml";
58
59 static struct wgt *configwgt = NULL;
60 static xmlDocPtr configxml = NULL;
61
62 static xmlNodePtr next(xmlNodePtr node, const char *type)
63 {
64         while (node && (node->type != XML_ELEMENT_NODE || strcmp(type, node->name)))
65                 node = node->next;
66         return node;
67 }
68
69 static xmlNodePtr first(const char *type)
70 {
71         assert(configxml);
72         assert(xmlDocGetRootElement(configxml));
73         return next(xmlDocGetRootElement(configxml)->children, type);
74 }
75
76 static unsigned int scorelang(xmlNodePtr node)
77 {
78         char *lang = xmlNodeGetLang(node);
79         unsigned int score = wgt_locales_score(configwgt, lang);
80         xmlFree(lang);
81         return score;
82 }
83
84 static xmlNodePtr element_based_localisation(const char *type)
85 {
86         xmlNodePtr resu, elem;
87         unsigned int sr, s;
88
89         resu = first(type);
90         if (resu) {
91                 sr = scorelang(resu);
92                 elem = next(resu->next, type);
93                 while (elem) {
94                         s = scorelang(elem);
95                         if (s < sr) {
96                                 resu = elem;
97                                 sr = s;
98                         }
99                         elem = next(elem->next, type);
100                 }
101         }
102         return resu;
103 }
104
105 void wgt_config_close()
106 {
107         if (configxml) {
108                 xmlFreeDoc(configxml);
109                 configxml = NULL;
110                 configwgt = NULL;
111         }
112 }
113
114 int wgt_config_open(struct wgt *wgt)
115 {
116         int fd;
117         assert(!configxml);
118         fd = wgt_open_read(wgt, wgt_config_string_xml_file);
119         if (fd < 0) {
120                 ERROR("can't open config file %s", wgt_config_string_xml_file);
121                 return fd;
122         }
123         configxml = xmlReadFd(fd, wgt_config_string_xml_file, NULL, 0);
124         close(fd);
125         if (configxml == NULL) {
126                 ERROR("xml parse of config file %s failed", wgt_config_string_xml_file);
127                 return -1;
128         }
129         assert(xmlDocGetRootElement(configxml));
130         configwgt = wgt;
131         return 0;
132 }
133
134 xmlNodePtr wgt_config_widget()
135 {
136         xmlNodePtr root;
137         assert(configxml);
138         root = xmlDocGetRootElement(configxml);
139         return strcmp(wgt_config_string_widget, root->name) ? NULL : root;
140 }
141
142 /* elements based on localisation */
143 xmlNodePtr wgt_config_name()
144 {
145         assert(configxml);
146         return element_based_localisation(wgt_config_string_name);
147 }
148
149 xmlNodePtr wgt_config_description()
150 {
151         assert(configxml);
152         return element_based_localisation(wgt_config_string_description);
153 }
154
155 xmlNodePtr wgt_config_license()
156 {
157         assert(configxml);
158         return element_based_localisation(wgt_config_string_license);
159 }
160
161 /* elements based on path localisation */
162 xmlNodePtr wgt_config_author()
163 {
164         assert(configxml);
165         return first(wgt_config_string_author);
166 }
167
168 xmlNodePtr wgt_config_content()
169 {
170         assert(configxml);
171         return first(wgt_config_string_content);
172 }
173
174 /* element multiple */
175
176 xmlNodePtr wgt_config_first_feature()
177 {
178         assert(configxml);
179         return first(wgt_config_string_feature);
180 }
181
182 xmlNodePtr wgt_config_next_feature(xmlNodePtr node)
183 {
184         assert(configxml);
185         assert(node);
186         return next(node->next, wgt_config_string_feature);
187 }
188
189 xmlNodePtr wgt_config_first_preference()
190 {
191         assert(configxml);
192         return first(wgt_config_string_preference);
193 }
194
195 xmlNodePtr wgt_config_next_preference(xmlNodePtr node)
196 {
197         assert(configxml);
198         assert(node);
199         return next(node->next, wgt_config_string_preference);
200 }
201
202 xmlNodePtr wgt_config_first_icon()
203 {
204         assert(configxml);
205         return first(wgt_config_string_icon);
206 }
207
208 xmlNodePtr wgt_config_next_icon(xmlNodePtr node)
209 {
210         assert(configxml);
211         assert(node);
212         return next(node->next, wgt_config_string_icon);
213 }
214
215 xmlNodePtr wgt_config_first_param(xmlNodePtr node)
216 {
217         assert(configxml);
218         assert(node);
219         return next(node->children, wgt_config_string_param);
220 }
221
222 xmlNodePtr wgt_config_next_param(xmlNodePtr node)
223 {
224         assert(configxml);
225         assert(node);
226         return next(node->next, wgt_config_string_param);
227 }
228
229 /* best sized icon */
230
231 static int score_dim(xmlNodePtr ref, xmlNodePtr x, const char *dim, int request)
232 {
233         int r, iref, ix;
234         char *sref, *sx;
235
236         sref = xmlGetProp(ref, dim);
237         if (sref) {
238                 iref = atoi(sref);
239                 xmlFree(sref);
240                 sx = xmlGetProp(x, dim);
241                 if (sx) {
242                         /* sref && sx */
243                         ix = atoi(sx);
244                         xmlFree(sx);
245                         if (ix >= request) {
246                                 if (iref >= request)
247                                         r = ix - iref;
248                                 else
249                                         r = request - ix;
250                         } else {
251                                 if (iref >= request)
252                                         r = iref - request;
253                                 else
254                                         r = iref - ix;
255                         }
256                 } else {
257                         /* sref && !sx */
258                         if (iref >= request)
259                                 r = iref - request;
260                         else
261                                 r = 0;
262                 }
263         } else {
264                 sx = xmlGetProp(x, dim);
265                 if (sx) {
266                         /* !sref && sx */
267                         ix = atoi(sx);
268                         xmlFree(sx);
269                         if (ix >= request)
270                                 r = request - ix;
271                         else
272                                 r = 0;
273                 } else {
274                         /* !sref && !sx */
275                         r = 0;
276                 }
277         }
278         return r;
279 }
280
281 static int is_better_icon(xmlNodePtr ref, xmlNodePtr x, int width, int height)
282 {
283         int sw = score_dim(ref, x, wgt_config_string_width, width);
284         int sh = score_dim(ref, x, wgt_config_string_height, height);
285         return sw+sh < 0;
286 }
287
288 xmlNodePtr wgt_config_icon(int width, int height)
289 {
290         assert(configxml);
291         xmlNodePtr resu, icon;
292
293         resu = wgt_config_first_icon();
294         icon = wgt_config_next_icon(resu);
295         while (icon) {
296                 if (is_better_icon(resu, icon, width, height))
297                         resu = icon;
298                 icon = wgt_config_next_icon(icon);
299         }
300         return resu;
301 }
302