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