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