cf890efb51c3efe7a0361359bbbde3ccfad4016b
[src/app-framework-main.git] / wgt-config.c
1 /*
2  Copyright (C) 2015-2019 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 #include "wgt-strings.h"
32
33
34 static struct wgt *configwgt = NULL;
35 static xmlDocPtr configxml = NULL;
36
37 static xmlNodePtr next(xmlNodePtr node, const char *type)
38 {
39         while (node && (node->type != XML_ELEMENT_NODE || strcmp(type, node->name)))
40                 node = node->next;
41         return node;
42 }
43
44 static xmlNodePtr first(const char *type)
45 {
46         assert(configxml);
47         assert(xmlDocGetRootElement(configxml));
48         return next(xmlDocGetRootElement(configxml)->children, type);
49 }
50
51 static unsigned int scorelang(xmlNodePtr node)
52 {
53         char *lang = xmlNodeGetLang(node);
54         unsigned int score = wgt_locales_score(configwgt, lang);
55         xmlFree(lang);
56         return score;
57 }
58
59 static xmlNodePtr element_based_localisation(const char *type)
60 {
61         xmlNodePtr resu, elem;
62         unsigned int sr, s;
63
64         resu = first(type);
65         if (resu) {
66                 sr = scorelang(resu);
67                 elem = next(resu->next, type);
68                 while (elem) {
69                         s = scorelang(elem);
70                         if (s < sr) {
71                                 resu = elem;
72                                 sr = s;
73                         }
74                         elem = next(elem->next, type);
75                 }
76         }
77         return resu;
78 }
79
80 void wgt_config_close()
81 {
82         if (configxml) {
83                 xmlFreeDoc(configxml);
84                 configxml = NULL;
85                 configwgt = NULL;
86         }
87 }
88
89 int wgt_config_open(struct wgt *wgt)
90 {
91         int fd;
92         assert(!configxml);
93         fd = wgt_open_read(wgt, string_config_dot_xml);
94         if (fd < 0) {
95                 ERROR("can't open config file %s", string_config_dot_xml);
96                 return fd;
97         }
98         configxml = xmlReadFd(fd, string_config_dot_xml, NULL, 0);
99         close(fd);
100         if (configxml == NULL) {
101                 ERROR("xml parse of config file %s failed", string_config_dot_xml);
102                 return -1;
103         }
104         assert(xmlDocGetRootElement(configxml));
105         configwgt = wgt;
106         return 0;
107 }
108
109 xmlNodePtr wgt_config_widget()
110 {
111         xmlNodePtr root;
112         assert(configxml);
113         root = xmlDocGetRootElement(configxml);
114         return strcmp(string_widget, root->name) ? NULL : root;
115 }
116
117 /* elements based on localisation */
118 xmlNodePtr wgt_config_name()
119 {
120         assert(configxml);
121         return element_based_localisation(string_name);
122 }
123
124 xmlNodePtr wgt_config_description()
125 {
126         assert(configxml);
127         return element_based_localisation(string_description);
128 }
129
130 xmlNodePtr wgt_config_license()
131 {
132         assert(configxml);
133         return element_based_localisation(string_license);
134 }
135
136 /* elements based on path localisation */
137 xmlNodePtr wgt_config_author()
138 {
139         assert(configxml);
140         return first(string_author);
141 }
142
143 xmlNodePtr wgt_config_content()
144 {
145         assert(configxml);
146         return first(string_content);
147 }
148
149 /* element multiple */
150
151 xmlNodePtr wgt_config_first_feature()
152 {
153         assert(configxml);
154         return first(string_feature);
155 }
156
157 xmlNodePtr wgt_config_next_feature(xmlNodePtr node)
158 {
159         assert(configxml);
160         assert(node);
161         return next(node->next, string_feature);
162 }
163
164 xmlNodePtr wgt_config_first_preference()
165 {
166         assert(configxml);
167         return first(string_preference);
168 }
169
170 xmlNodePtr wgt_config_next_preference(xmlNodePtr node)
171 {
172         assert(configxml);
173         assert(node);
174         return next(node->next, string_preference);
175 }
176
177 xmlNodePtr wgt_config_first_icon()
178 {
179         assert(configxml);
180         return first(string_icon);
181 }
182
183 xmlNodePtr wgt_config_next_icon(xmlNodePtr node)
184 {
185         assert(configxml);
186         assert(node);
187         return next(node->next, string_icon);
188 }
189
190 xmlNodePtr wgt_config_first_param(xmlNodePtr node)
191 {
192         assert(configxml);
193         assert(node);
194         return next(node->children, string_param);
195 }
196
197 xmlNodePtr wgt_config_next_param(xmlNodePtr node)
198 {
199         assert(configxml);
200         assert(node);
201         return next(node->next, string_param);
202 }
203
204 /* best sized icon */
205
206 static int score_dim(xmlNodePtr ref, xmlNodePtr x, const char *dim, int request)
207 {
208         int r, iref, ix;
209         char *sref, *sx;
210
211         sref = xmlGetProp(ref, dim);
212         if (sref) {
213                 iref = atoi(sref);
214                 xmlFree(sref);
215                 sx = xmlGetProp(x, dim);
216                 if (sx) {
217                         /* sref && sx */
218                         ix = atoi(sx);
219                         xmlFree(sx);
220                         if (ix >= request) {
221                                 if (iref >= request)
222                                         r = ix - iref;
223                                 else
224                                         r = request - ix;
225                         } else {
226                                 if (iref >= request)
227                                         r = iref - request;
228                                 else
229                                         r = iref - ix;
230                         }
231                 } else {
232                         /* sref && !sx */
233                         if (iref >= request)
234                                 r = iref - request;
235                         else
236                                 r = 0;
237                 }
238         } else {
239                 sx = xmlGetProp(x, dim);
240                 if (sx) {
241                         /* !sref && sx */
242                         ix = atoi(sx);
243                         xmlFree(sx);
244                         if (ix >= request)
245                                 r = request - ix;
246                         else
247                                 r = 0;
248                 } else {
249                         /* !sref && !sx */
250                         r = 0;
251                 }
252         }
253         return r;
254 }
255
256 static int is_better_icon(xmlNodePtr ref, xmlNodePtr x, int width, int height)
257 {
258         int sw = score_dim(ref, x, string_width, width);
259         int sh = score_dim(ref, x, string_height, height);
260         return sw+sh < 0;
261 }
262
263 xmlNodePtr wgt_config_icon(int width, int height)
264 {
265         assert(configxml);
266         xmlNodePtr resu, icon;
267
268         resu = wgt_config_first_icon();
269         icon = wgt_config_next_icon(resu);
270         while (icon) {
271                 if (is_better_icon(resu, icon, width, height))
272                         resu = icon;
273                 icon = wgt_config_next_icon(icon);
274         }
275         return resu;
276 }
277