refactoring widget library
[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_xml_file[] = "config.xml";
31 const char wgt_config_string_name[] = "name";
32 const char wgt_config_string_description[] = "description";
33 const char wgt_config_string_author[] = "author";
34 const char wgt_config_string_license[] = "license";
35 const char wgt_config_string_icon[] = "icon";
36 const char wgt_config_string_content[] = "content";
37 const char wgt_config_string_feature[] = "feature";
38 const char wgt_config_string_preference[] = "preference";
39 const char wgt_config_string_width[] = "width";
40 const char wgt_config_string_height[] = "height";
41
42
43 static struct wgt *configwgt = NULL;
44 static xmlDocPtr configxml = NULL;
45
46 static xmlNodePtr next(xmlNodePtr node, const char *type)
47 {
48         while (node && node->type != XML_ELEMENT_NODE && strcmp(type, node->name))
49                 node = node->next;
50         return node;
51 }
52
53 static xmlNodePtr first(const char *type)
54 {
55         xmlNodePtr root;
56         if (configxml) {
57                 root = xmlDocGetRootElement(configxml);
58                 if (root)
59                         return next(root->children, type);
60         }
61         return NULL;
62 }
63
64 static int scorelang(xmlNodePtr node)
65 {
66         char *lang = xmlNodeGetLang(node);
67         int score = wgt_locales_score(configwgt, lang);
68         xmlFree(lang);
69         return score;
70 }
71
72 static xmlNodePtr element_based_localisation(const char *type)
73 {
74         xmlNodePtr resu, elem;
75         int sr, s;
76
77         resu = first(type);
78         if (resu) {
79                 sr = scorelang(resu);
80                 elem = next(resu->next, type);
81                 while (resu) {
82                         s = scorelang(elem);
83                         if (s < sr) {
84                                 resu = elem;
85                                 sr = s;
86                         }
87                         elem = next(elem->next, type);
88                 }
89         }
90         return resu;
91 }
92
93 void wgt_config_close()
94 {
95         if (configxml) {
96                 xmlFreeDoc(configxml);
97                 configxml = NULL;
98                 configwgt = NULL;
99         }
100 }
101
102 int wgt_config_open(struct wgt *wgt)
103 {
104         int fd;
105         assert(!configxml);
106         fd = wgt_open_read(wgt, wgt_config_string_xml_file);
107         if (fd < 0) {
108                 syslog(LOG_ERR, "can't open config file %s", wgt_config_string_xml_file);
109                 return fd;
110         }
111         configxml = xmlReadFd(fd, wgt_config_string_xml_file, NULL, 0);
112         close(fd);
113         if (configxml == NULL) {
114                 syslog(LOG_ERR, "xml parse of config file %s failed", wgt_config_string_xml_file);
115                 return -1;
116         }
117         configwgt = wgt;
118         return 0;
119 }
120
121 /* elements based on localisation */
122 xmlNodePtr wgt_config_name()
123 {
124         return element_based_localisation(wgt_config_string_name);
125 }
126
127 xmlNodePtr wgt_config_description()
128 {
129         return element_based_localisation(wgt_config_string_description);
130 }
131
132 xmlNodePtr wgt_config_license()
133 {
134         return element_based_localisation(wgt_config_string_license);
135 }
136
137 /* elements based on path localisation */
138 xmlNodePtr wgt_config_author()
139 {
140         return first(wgt_config_string_author);
141 }
142
143 xmlNodePtr wgt_config_content()
144 {
145         return first(wgt_config_string_content);
146 }
147
148 /* element multiple */
149
150 xmlNodePtr wgt_config_first_feature()
151 {
152         return first(wgt_config_string_feature);
153 }
154
155 xmlNodePtr wgt_config_next_feature(xmlNodePtr node)
156 {
157         return next(node->next, wgt_config_string_feature);
158 }
159
160 xmlNodePtr wgt_config_first_preference()
161 {
162         return first(wgt_config_string_preference);
163 }
164
165 xmlNodePtr wgt_config_next_preference(xmlNodePtr node)
166 {
167         return next(node->next, wgt_config_string_preference);
168 }
169
170 xmlNodePtr wgt_config_first_icon()
171 {
172         return first(wgt_config_string_icon);
173 }
174
175 xmlNodePtr wgt_config_next_icon(xmlNodePtr node)
176 {
177         return next(node->next, wgt_config_string_icon);
178 }
179
180 /* best sized icon */
181
182 static int score_dim(xmlNodePtr ref, xmlNodePtr x, const char *dim, int request)
183 {
184         int r, iref, ix;
185         char *sref, *sx;
186
187         sref = xmlGetProp(ref, dim);
188         if (sref) {
189                 iref = atoi(sref);
190                 xmlFree(sref);
191                 sx = xmlGetProp(x, dim);
192                 if (sx) {
193                         /* sref && sx */
194                         ix = atoi(sx);
195                         xmlFree(sx);
196                         if (ix >= request) {
197                                 if (iref >= request)
198                                         r = ix - iref;
199                                 else
200                                         r = request - ix;
201                         } else {
202                                 if (iref >= request)
203                                         r = iref - request;
204                                 else
205                                         r = iref - ix;
206                         }
207                 } else {
208                         /* sref && !sx */
209                         if (iref >= request)
210                                 r = iref - request;
211                         else
212                                 r = 0;
213                 }
214         } else {
215                 sx = xmlGetProp(x, dim);
216                 if (sx) {
217                         /* !sref && sx */
218                         ix = atoi(sx);
219                         xmlFree(sx);
220                         if (ix >= request)
221                                 r = request - ix;
222                         else
223                                 r = 0;
224                 } else {
225                         /* !sref && !sx */
226                         r = 0;
227                 }
228         }
229         return r;
230 }
231
232 static int better_icon(xmlNodePtr ref, xmlNodePtr x, int width, int height)
233 {
234         int sw = score_dim(ref, x, wgt_config_string_width, width);
235         int sh = score_dim(ref, x, wgt_config_string_height, height);
236         return sw+sh < 0;
237 }
238
239 xmlNodePtr wgt_config_icon(int width, int height)
240 {
241         xmlNodePtr resu, icon;
242
243         resu = wgt_config_first_icon();
244         icon = wgt_config_next_icon(resu);
245         while (icon) {
246                 if (better_icon(resu, icon, width, height))
247                         resu = icon;
248                 icon = wgt_config_next_icon(icon);
249         }
250         return resu;
251 }
252