Initial commit of litehtml_viewer
[claws.git] / src / plugins / litehtml_viewer / litehtml / style.cpp
1 #include "html.h"\r
2 #include "style.h"\r
3 #include <functional>\r
4 #include <algorithm>\r
5 #ifndef WINCE\r
6 #include <locale>\r
7 #endif\r
8 \r
9 litehtml::string_map litehtml::style::m_valid_values =\r
10 {\r
11         { _t("white-space"), white_space_strings }\r
12 };\r
13 \r
14 litehtml::style::style()\r
15 {\r
16 }\r
17 \r
18 litehtml::style::style( const style& val )\r
19 {\r
20         m_properties = val.m_properties;\r
21 }\r
22 \r
23 litehtml::style::~style()\r
24 {\r
25 \r
26 }\r
27 \r
28 void litehtml::style::parse( const tchar_t* txt, const tchar_t* baseurl )\r
29 {\r
30         std::vector<tstring> properties;\r
31         split_string(txt, properties, _t(";"));\r
32 \r
33         for(std::vector<tstring>::const_iterator i = properties.begin(); i != properties.end(); i++)\r
34         {\r
35                 parse_property(*i, baseurl);\r
36         }\r
37 }\r
38 \r
39 void litehtml::style::parse_property( const tstring& txt, const tchar_t* baseurl )\r
40 {\r
41         tstring::size_type pos = txt.find_first_of(_t(":"));\r
42         if(pos != tstring::npos)\r
43         {\r
44                 tstring name    = txt.substr(0, pos);\r
45                 tstring val     = txt.substr(pos + 1);\r
46 \r
47                 trim(name);\r
48                 trim(val);\r
49 \r
50                 lcase(name);\r
51 \r
52                 if(!name.empty() && !val.empty())\r
53                 {\r
54                         string_vector vals;\r
55                         split_string(val, vals, _t("!"));\r
56                         if(vals.size() == 1)\r
57                         {\r
58                                 add_property(name.c_str(), val.c_str(), baseurl, false);\r
59                         } else if(vals.size() > 1)\r
60                         {\r
61                                 trim(vals[0]);\r
62                                 lcase(vals[1]);\r
63                                 if(vals[1] == _t("important"))\r
64                                 {\r
65                                         add_property(name.c_str(), vals[0].c_str(), baseurl, true);\r
66                                 } else\r
67                                 {\r
68                                         add_property(name.c_str(), vals[0].c_str(), baseurl, false);\r
69                                 }\r
70                         }\r
71                 }\r
72         }\r
73 }\r
74 \r
75 void litehtml::style::combine( const litehtml::style& src )\r
76 {\r
77         for(props_map::const_iterator i = src.m_properties.begin(); i != src.m_properties.end(); i++)\r
78         {\r
79                 add_parsed_property(i->first.c_str(), i->second.m_value.c_str(), i->second.m_important);\r
80         }\r
81 }\r
82 \r
83 void litehtml::style::add_property( const tchar_t* name, const tchar_t* val, const tchar_t* baseurl, bool important )\r
84 {\r
85         if(!name || !val)\r
86         {\r
87                 return;\r
88         }\r
89 \r
90         // Add baseurl for background image \r
91         if(     !t_strcmp(name, _t("background-image")))\r
92         {\r
93                 add_parsed_property(name, val, important);\r
94                 if(baseurl)\r
95                 {\r
96                         add_parsed_property(_t("background-image-baseurl"), baseurl, important);\r
97                 }\r
98         } else\r
99 \r
100         // Parse border spacing properties \r
101         if(     !t_strcmp(name, _t("border-spacing")))\r
102         {\r
103                 string_vector tokens;\r
104                 split_string(val, tokens, _t(" "));\r
105                 if(tokens.size() == 1)\r
106                 {\r
107                         add_property(_t("-litehtml-border-spacing-x"), tokens[0].c_str(), baseurl, important);\r
108                         add_property(_t("-litehtml-border-spacing-y"), tokens[0].c_str(), baseurl, important);\r
109                 } else if(tokens.size() == 2)\r
110                 {\r
111                         add_property(_t("-litehtml-border-spacing-x"), tokens[0].c_str(), baseurl, important);\r
112                         add_property(_t("-litehtml-border-spacing-y"), tokens[1].c_str(), baseurl, important);\r
113                 }\r
114         } else\r
115 \r
116         // Parse borders shorthand properties \r
117 \r
118         if(     !t_strcmp(name, _t("border")))\r
119         {\r
120                 string_vector tokens;\r
121                 split_string(val, tokens, _t(" "), _t(""), _t("("));\r
122                 int idx;\r
123                 tstring str;\r
124                 for(string_vector::const_iterator tok = tokens.begin(); tok != tokens.end(); tok++)\r
125                 {\r
126                         idx = value_index(tok->c_str(), border_style_strings, -1);\r
127                         if(idx >= 0)\r
128                         {\r
129                                 add_property(_t("border-left-style"), tok->c_str(), baseurl, important);\r
130                                 add_property(_t("border-right-style"), tok->c_str(), baseurl, important);\r
131                                 add_property(_t("border-top-style"), tok->c_str(), baseurl, important);\r
132                                 add_property(_t("border-bottom-style"), tok->c_str(), baseurl, important);\r
133                         } else\r
134                         {\r
135                                 if(web_color::is_color(tok->c_str()))\r
136                                 {\r
137                                         add_property(_t("border-left-color"), tok->c_str(), baseurl, important);\r
138                                         add_property(_t("border-right-color"), tok->c_str(), baseurl, important);\r
139                                         add_property(_t("border-top-color"), tok->c_str(), baseurl, important);\r
140                                         add_property(_t("border-bottom-color"), tok->c_str(), baseurl, important);\r
141                                 } else\r
142                                 {\r
143                                         add_property(_t("border-left-width"), tok->c_str(), baseurl, important);\r
144                                         add_property(_t("border-right-width"), tok->c_str(), baseurl, important);\r
145                                         add_property(_t("border-top-width"), tok->c_str(), baseurl, important);\r
146                                         add_property(_t("border-bottom-width"), tok->c_str(), baseurl, important);\r
147                                 }\r
148                         }\r
149                 }\r
150         } else if(      !t_strcmp(name, _t("border-left"))      ||\r
151                 !t_strcmp(name, _t("border-right"))     ||\r
152                 !t_strcmp(name, _t("border-top"))       ||\r
153                 !t_strcmp(name, _t("border-bottom")) )\r
154         {\r
155                 string_vector tokens;\r
156                 split_string(val, tokens, _t(" "), _t(""), _t("("));\r
157                 int idx;\r
158                 tstring str;\r
159                 for(string_vector::const_iterator tok = tokens.begin(); tok != tokens.end(); tok++)\r
160                 {\r
161                         idx = value_index(tok->c_str(), border_style_strings, -1);\r
162                         if(idx >= 0)\r
163                         {\r
164                                 str = name;\r
165                                 str += _t("-style");\r
166                                 add_property(str.c_str(), tok->c_str(), baseurl, important);\r
167                         } else\r
168                         {\r
169                                 if(web_color::is_color(tok->c_str()))\r
170                                 {\r
171                                         str = name;\r
172                                         str += _t("-color");\r
173                                         add_property(str.c_str(), tok->c_str(), baseurl, important);\r
174                                 } else\r
175                                 {\r
176                                         str = name;\r
177                                         str += _t("-width");\r
178                                         add_property(str.c_str(), tok->c_str(), baseurl, important);\r
179                                 }\r
180                         }\r
181                 }\r
182         } else \r
183 \r
184         // Parse border radius shorthand properties \r
185         if(!t_strcmp(name, _t("border-bottom-left-radius")))\r
186         {\r
187                 string_vector tokens;\r
188                 split_string(val, tokens, _t(" "));\r
189                 if(tokens.size() >= 2)\r
190                 {\r
191                         add_property(_t("border-bottom-left-radius-x"), tokens[0].c_str(), baseurl, important);\r
192                         add_property(_t("border-bottom-left-radius-y"), tokens[1].c_str(), baseurl, important);\r
193                 } else if(tokens.size() == 1)\r
194                 {\r
195                         add_property(_t("border-bottom-left-radius-x"), tokens[0].c_str(), baseurl, important);\r
196                         add_property(_t("border-bottom-left-radius-y"), tokens[0].c_str(), baseurl, important);\r
197                 }\r
198 \r
199         } else if(!t_strcmp(name, _t("border-bottom-right-radius")))\r
200         {\r
201                 string_vector tokens;\r
202                 split_string(val, tokens, _t(" "));\r
203                 if(tokens.size() >= 2)\r
204                 {\r
205                         add_property(_t("border-bottom-right-radius-x"), tokens[0].c_str(), baseurl, important);\r
206                         add_property(_t("border-bottom-right-radius-y"), tokens[1].c_str(), baseurl, important);\r
207                 } else if(tokens.size() == 1)\r
208                 {\r
209                         add_property(_t("border-bottom-right-radius-x"), tokens[0].c_str(), baseurl, important);\r
210                         add_property(_t("border-bottom-right-radius-y"), tokens[0].c_str(), baseurl, important);\r
211                 }\r
212 \r
213         } else if(!t_strcmp(name, _t("border-top-right-radius")))\r
214         {\r
215                 string_vector tokens;\r
216                 split_string(val, tokens, _t(" "));\r
217                 if(tokens.size() >= 2)\r
218                 {\r
219                         add_property(_t("border-top-right-radius-x"), tokens[0].c_str(), baseurl, important);\r
220                         add_property(_t("border-top-right-radius-y"), tokens[1].c_str(), baseurl, important);\r
221                 } else if(tokens.size() == 1)\r
222                 {\r
223                         add_property(_t("border-top-right-radius-x"), tokens[0].c_str(), baseurl, important);\r
224                         add_property(_t("border-top-right-radius-y"), tokens[0].c_str(), baseurl, important);\r
225                 }\r
226 \r
227         } else if(!t_strcmp(name, _t("border-top-left-radius")))\r
228         {\r
229                 string_vector tokens;\r
230                 split_string(val, tokens, _t(" "));\r
231                 if(tokens.size() >= 2)\r
232                 {\r
233                         add_property(_t("border-top-left-radius-x"), tokens[0].c_str(), baseurl, important);\r
234                         add_property(_t("border-top-left-radius-y"), tokens[1].c_str(), baseurl, important);\r
235                 } else if(tokens.size() == 1)\r
236                 {\r
237                         add_property(_t("border-top-left-radius-x"), tokens[0].c_str(), baseurl, important);\r
238                         add_property(_t("border-top-left-radius-y"), tokens[0].c_str(), baseurl, important);\r
239                 }\r
240 \r
241         } else \r
242 \r
243         // Parse border-radius shorthand properties \r
244         if(!t_strcmp(name, _t("border-radius")))\r
245         {\r
246                 string_vector tokens;\r
247                 split_string(val, tokens, _t("/"));\r
248                 if(tokens.size() == 1)\r
249                 {\r
250                         add_property(_t("border-radius-x"), tokens[0].c_str(), baseurl, important);\r
251                         add_property(_t("border-radius-y"), tokens[0].c_str(), baseurl, important);\r
252                 } else if(tokens.size() >= 2)\r
253                 {\r
254                         add_property(_t("border-radius-x"), tokens[0].c_str(), baseurl, important);\r
255                         add_property(_t("border-radius-y"), tokens[1].c_str(), baseurl, important);\r
256                 }\r
257         } else if(!t_strcmp(name, _t("border-radius-x")))\r
258         {\r
259                 string_vector tokens;\r
260                 split_string(val, tokens, _t(" "));\r
261                 if(tokens.size() == 1)\r
262                 {\r
263                         add_property(_t("border-top-left-radius-x"),            tokens[0].c_str(), baseurl, important);\r
264                         add_property(_t("border-top-right-radius-x"),           tokens[0].c_str(), baseurl, important);\r
265                         add_property(_t("border-bottom-right-radius-x"),        tokens[0].c_str(), baseurl, important);\r
266                         add_property(_t("border-bottom-left-radius-x"), tokens[0].c_str(), baseurl, important);\r
267                 } else if(tokens.size() == 2)\r
268                 {\r
269                         add_property(_t("border-top-left-radius-x"),            tokens[0].c_str(), baseurl, important);\r
270                         add_property(_t("border-top-right-radius-x"),           tokens[1].c_str(), baseurl, important);\r
271                         add_property(_t("border-bottom-right-radius-x"),        tokens[0].c_str(), baseurl, important);\r
272                         add_property(_t("border-bottom-left-radius-x"), tokens[1].c_str(), baseurl, important);\r
273                 } else if(tokens.size() == 3)\r
274                 {\r
275                         add_property(_t("border-top-left-radius-x"),            tokens[0].c_str(), baseurl, important);\r
276                         add_property(_t("border-top-right-radius-x"),           tokens[1].c_str(), baseurl, important);\r
277                         add_property(_t("border-bottom-right-radius-x"),        tokens[2].c_str(), baseurl, important);\r
278                         add_property(_t("border-bottom-left-radius-x"), tokens[1].c_str(), baseurl, important);\r
279                 } else if(tokens.size() == 4)\r
280                 {\r
281                         add_property(_t("border-top-left-radius-x"),            tokens[0].c_str(), baseurl, important);\r
282                         add_property(_t("border-top-right-radius-x"),           tokens[1].c_str(), baseurl, important);\r
283                         add_property(_t("border-bottom-right-radius-x"),        tokens[2].c_str(), baseurl, important);\r
284                         add_property(_t("border-bottom-left-radius-x"), tokens[3].c_str(), baseurl, important);\r
285                 }\r
286         } else if(!t_strcmp(name, _t("border-radius-y")))\r
287         {\r
288                 string_vector tokens;\r
289                 split_string(val, tokens, _t(" "));\r
290                 if(tokens.size() == 1)\r
291                 {\r
292                         add_property(_t("border-top-left-radius-y"),            tokens[0].c_str(), baseurl, important);\r
293                         add_property(_t("border-top-right-radius-y"),           tokens[0].c_str(), baseurl, important);\r
294                         add_property(_t("border-bottom-right-radius-y"),        tokens[0].c_str(), baseurl, important);\r
295                         add_property(_t("border-bottom-left-radius-y"), tokens[0].c_str(), baseurl, important);\r
296                 } else if(tokens.size() == 2)\r
297                 {\r
298                         add_property(_t("border-top-left-radius-y"),            tokens[0].c_str(), baseurl, important);\r
299                         add_property(_t("border-top-right-radius-y"),           tokens[1].c_str(), baseurl, important);\r
300                         add_property(_t("border-bottom-right-radius-y"),        tokens[0].c_str(), baseurl, important);\r
301                         add_property(_t("border-bottom-left-radius-y"), tokens[1].c_str(), baseurl, important);\r
302                 } else if(tokens.size() == 3)\r
303                 {\r
304                         add_property(_t("border-top-left-radius-y"),            tokens[0].c_str(), baseurl, important);\r
305                         add_property(_t("border-top-right-radius-y"),           tokens[1].c_str(), baseurl, important);\r
306                         add_property(_t("border-bottom-right-radius-y"),        tokens[2].c_str(), baseurl, important);\r
307                         add_property(_t("border-bottom-left-radius-y"), tokens[1].c_str(), baseurl, important);\r
308                 } else if(tokens.size() == 4)\r
309                 {\r
310                         add_property(_t("border-top-left-radius-y"),            tokens[0].c_str(), baseurl, important);\r
311                         add_property(_t("border-top-right-radius-y"),           tokens[1].c_str(), baseurl, important);\r
312                         add_property(_t("border-bottom-right-radius-y"),        tokens[2].c_str(), baseurl, important);\r
313                         add_property(_t("border-bottom-left-radius-y"), tokens[3].c_str(), baseurl, important);\r
314                 }\r
315         }\r
316         \r
317 \r
318         // Parse list-style shorthand properties \r
319         if(!t_strcmp(name, _t("list-style")))\r
320         {\r
321                 add_parsed_property(_t("list-style-type"),                      _t("disc"),             important);\r
322                 add_parsed_property(_t("list-style-position"),          _t("outside"),  important);\r
323                 add_parsed_property(_t("list-style-image"),                     _t(""),                 important);\r
324                 add_parsed_property(_t("list-style-image-baseurl"),     _t(""),                 important);\r
325 \r
326                 string_vector tokens;\r
327                 split_string(val, tokens, _t(" "), _t(""), _t("("));\r
328                 for(string_vector::iterator tok = tokens.begin(); tok != tokens.end(); tok++)\r
329                 {\r
330                         int idx = value_index(tok->c_str(), list_style_type_strings, -1);\r
331                         if(idx >= 0)\r
332                         {\r
333                                 add_parsed_property(_t("list-style-type"), *tok, important);\r
334                         } else\r
335                         {\r
336                                 idx = value_index(tok->c_str(), list_style_position_strings, -1);\r
337                                 if(idx >= 0)\r
338                                 {\r
339                                         add_parsed_property(_t("list-style-position"), *tok, important);\r
340                                 } else if(!t_strncmp(val, _t("url"), 3))\r
341                                 {\r
342                                         add_parsed_property(_t("list-style-image"), *tok, important);\r
343                                         if(baseurl)\r
344                                         {\r
345                                                 add_parsed_property(_t("list-style-image-baseurl"), baseurl, important);\r
346                                         }\r
347                                 }\r
348                         }\r
349                 }\r
350         } else \r
351 \r
352         // Add baseurl for background image \r
353         if(     !t_strcmp(name, _t("list-style-image")))\r
354         {\r
355                 add_parsed_property(name, val, important);\r
356                 if(baseurl)\r
357                 {\r
358                         add_parsed_property(_t("list-style-image-baseurl"), baseurl, important);\r
359                 }\r
360         } else\r
361                 \r
362         // Parse background shorthand properties \r
363         if(!t_strcmp(name, _t("background")))\r
364         {\r
365                 parse_short_background(val, baseurl, important);\r
366 \r
367         } else \r
368                 \r
369         // Parse margin and padding shorthand properties \r
370         if(!t_strcmp(name, _t("margin")) || !t_strcmp(name, _t("padding")))\r
371         {\r
372                 string_vector tokens;\r
373                 split_string(val, tokens, _t(" "));\r
374                 if(tokens.size() >= 4)\r
375                 {\r
376                         add_parsed_property(tstring(name) + _t("-top"),         tokens[0], important);\r
377                         add_parsed_property(tstring(name) + _t("-right"),               tokens[1], important);\r
378                         add_parsed_property(tstring(name) + _t("-bottom"),      tokens[2], important);\r
379                         add_parsed_property(tstring(name) + _t("-left"),                tokens[3], important);\r
380                 } else if(tokens.size() == 3)\r
381                 {\r
382                         add_parsed_property(tstring(name) + _t("-top"),         tokens[0], important);\r
383                         add_parsed_property(tstring(name) + _t("-right"),               tokens[1], important);\r
384                         add_parsed_property(tstring(name) + _t("-left"),                tokens[1], important);\r
385                         add_parsed_property(tstring(name) + _t("-bottom"),      tokens[2], important);\r
386                 } else if(tokens.size() == 2)\r
387                 {\r
388                         add_parsed_property(tstring(name) + _t("-top"),         tokens[0], important);\r
389                         add_parsed_property(tstring(name) + _t("-bottom"),      tokens[0], important);\r
390                         add_parsed_property(tstring(name) + _t("-right"),               tokens[1], important);\r
391                         add_parsed_property(tstring(name) + _t("-left"),                tokens[1], important);\r
392                 } else if(tokens.size() == 1)\r
393                 {\r
394                         add_parsed_property(tstring(name) + _t("-top"),         tokens[0], important);\r
395                         add_parsed_property(tstring(name) + _t("-bottom"),      tokens[0], important);\r
396                         add_parsed_property(tstring(name) + _t("-right"),               tokens[0], important);\r
397                         add_parsed_property(tstring(name) + _t("-left"),                tokens[0], important);\r
398                 }\r
399         } else \r
400                 \r
401                 \r
402         // Parse border-* shorthand properties \r
403         if(     !t_strcmp(name, _t("border-left")) || \r
404                 !t_strcmp(name, _t("border-right")) ||\r
405                 !t_strcmp(name, _t("border-top"))  || \r
406                 !t_strcmp(name, _t("border-bottom")))\r
407         {\r
408                 parse_short_border(name, val, important);\r
409         } else \r
410                 \r
411         // Parse border-width/style/color shorthand properties \r
412         if(     !t_strcmp(name, _t("border-width")) ||\r
413                 !t_strcmp(name, _t("border-style"))  ||\r
414                 !t_strcmp(name, _t("border-color")) )\r
415         {\r
416                 string_vector nametokens;\r
417                 split_string(name, nametokens, _t("-"));\r
418 \r
419                 string_vector tokens;\r
420                 split_string(val, tokens, _t(" "));\r
421                 if(tokens.size() >= 4)\r
422                 {\r
423                         add_parsed_property(nametokens[0] + _t("-top-")         + nametokens[1],        tokens[0], important);\r
424                         add_parsed_property(nametokens[0] + _t("-right-")       + nametokens[1],        tokens[1], important);\r
425                         add_parsed_property(nametokens[0] + _t("-bottom-")      + nametokens[1],        tokens[2], important);\r
426                         add_parsed_property(nametokens[0] + _t("-left-")        + nametokens[1],        tokens[3], important);\r
427                 } else if(tokens.size() == 3)\r
428                 {\r
429                         add_parsed_property(nametokens[0] + _t("-top-")         + nametokens[1],        tokens[0], important);\r
430                         add_parsed_property(nametokens[0] + _t("-right-")       + nametokens[1],        tokens[1], important);\r
431                         add_parsed_property(nametokens[0] + _t("-left-")        + nametokens[1],        tokens[1], important);\r
432                         add_parsed_property(nametokens[0] + _t("-bottom-")      + nametokens[1],        tokens[2], important);\r
433                 } else if(tokens.size() == 2)\r
434                 {\r
435                         add_parsed_property(nametokens[0] + _t("-top-")         + nametokens[1],        tokens[0], important);\r
436                         add_parsed_property(nametokens[0] + _t("-bottom-")      + nametokens[1],        tokens[0], important);\r
437                         add_parsed_property(nametokens[0] + _t("-right-")       + nametokens[1],        tokens[1], important);\r
438                         add_parsed_property(nametokens[0] + _t("-left-")        + nametokens[1],        tokens[1], important);\r
439                 } else if(tokens.size() == 1)\r
440                 {\r
441                         add_parsed_property(nametokens[0] + _t("-top-")         + nametokens[1],        tokens[0], important);\r
442                         add_parsed_property(nametokens[0] + _t("-bottom-")      + nametokens[1],        tokens[0], important);\r
443                         add_parsed_property(nametokens[0] + _t("-right-")       + nametokens[1],        tokens[0], important);\r
444                         add_parsed_property(nametokens[0] + _t("-left-")        + nametokens[1],        tokens[0], important);\r
445                 }\r
446         } else \r
447                 \r
448         // Parse font shorthand properties \r
449         if(!t_strcmp(name, _t("font")))\r
450         {\r
451                 parse_short_font(val, important);\r
452         } else \r
453         {\r
454                 add_parsed_property(name, val, important);\r
455         }\r
456 }\r
457 \r
458 void litehtml::style::parse_short_border( const tstring& prefix, const tstring& val, bool important )\r
459 {\r
460         string_vector tokens;\r
461         split_string(val, tokens, _t(" "), _t(""), _t("("));\r
462         if(tokens.size() >= 3)\r
463         {\r
464                 add_parsed_property(prefix + _t("-width"),      tokens[0], important);\r
465                 add_parsed_property(prefix + _t("-style"),      tokens[1], important);\r
466                 add_parsed_property(prefix + _t("-color"),      tokens[2], important);\r
467         } else if(tokens.size() == 2)\r
468         {\r
469                 if(iswdigit(tokens[0][0]) || value_index(val.c_str(), border_width_strings) >= 0)\r
470                 {\r
471                         add_parsed_property(prefix + _t("-width"),      tokens[0], important);\r
472                         add_parsed_property(prefix + _t("-style"),      tokens[1], important);\r
473                 } else\r
474                 {\r
475                         add_parsed_property(prefix + _t("-style"),      tokens[0], important);\r
476                         add_parsed_property(prefix + _t("-color"),      tokens[1], important);\r
477                 }\r
478         }\r
479 }\r
480 \r
481 void litehtml::style::parse_short_background( const tstring& val, const tchar_t* baseurl, bool important )\r
482 {\r
483         add_parsed_property(_t("background-color"),                     _t("transparent"),      important);\r
484         add_parsed_property(_t("background-image"),                     _t(""),                         important);\r
485         add_parsed_property(_t("background-image-baseurl"), _t(""),                             important);\r
486         add_parsed_property(_t("background-repeat"),            _t("repeat"),           important);\r
487         add_parsed_property(_t("background-origin"),            _t("padding-box"),      important);\r
488         add_parsed_property(_t("background-clip"),                      _t("border-box"),       important);\r
489         add_parsed_property(_t("background-attachment"),        _t("scroll"),           important);\r
490 \r
491         if(val == _t("none"))\r
492         {\r
493                 return;\r
494         }\r
495 \r
496         string_vector tokens;\r
497         split_string(val, tokens, _t(" "), _t(""), _t("("));\r
498         bool origin_found = false;\r
499         for(string_vector::iterator tok = tokens.begin(); tok != tokens.end(); tok++)\r
500         {\r
501                 if(web_color::is_color(tok->c_str()))\r
502                 {\r
503                         add_parsed_property(_t("background-color"), *tok, important);\r
504                 } else if(tok->substr(0, 3) == _t("url"))\r
505                 {\r
506                         add_parsed_property(_t("background-image"), *tok, important);\r
507                         if(baseurl)\r
508                         {\r
509                                 add_parsed_property(_t("background-image-baseurl"), baseurl, important);\r
510                         }\r
511 \r
512                 } else if( value_in_list(tok->c_str(), background_repeat_strings) )\r
513                 {\r
514                         add_parsed_property(_t("background-repeat"), *tok, important);\r
515                 } else if( value_in_list(tok->c_str(), background_attachment_strings) )\r
516                 {\r
517                         add_parsed_property(_t("background-attachment"), *tok, important);\r
518                 } else if( value_in_list(tok->c_str(), background_box_strings) )\r
519                 {\r
520                         if(!origin_found)\r
521                         {\r
522                                 add_parsed_property(_t("background-origin"), *tok, important);\r
523                                 origin_found = true;\r
524                         } else\r
525                         {\r
526                                 add_parsed_property(_t("background-clip"),*tok, important);\r
527                         }\r
528                 } else if(      value_in_list(tok->c_str(), _t("left;right;top;bottom;center")) ||\r
529                                         iswdigit((*tok)[0]) ||\r
530                                         (*tok)[0] == _t('-')    ||\r
531                                         (*tok)[0] == _t('.')    ||\r
532                                         (*tok)[0] == _t('+'))\r
533                 {\r
534                         if(m_properties.find(_t("background-position")) != m_properties.end())\r
535                         {\r
536                                 m_properties[_t("background-position")].m_value = m_properties[_t("background-position")].m_value + _t(" ") + *tok;\r
537                         } else\r
538                         {\r
539                                 add_parsed_property(_t("background-position"), *tok, important);\r
540                         }\r
541                 }\r
542         }\r
543 }\r
544 \r
545 void litehtml::style::parse_short_font( const tstring& val, bool important )\r
546 {\r
547         add_parsed_property(_t("font-style"),   _t("normal"),   important);\r
548         add_parsed_property(_t("font-variant"), _t("normal"),   important);\r
549         add_parsed_property(_t("font-weight"),  _t("normal"),   important);\r
550         add_parsed_property(_t("font-size"),            _t("medium"),   important);\r
551         add_parsed_property(_t("line-height"),  _t("normal"),   important);\r
552 \r
553         string_vector tokens;\r
554         split_string(val, tokens, _t(" "), _t(""), _t("\""));\r
555 \r
556         int idx = 0;\r
557         bool was_normal = false;\r
558         bool is_family = false;\r
559         tstring font_family;\r
560         for(string_vector::iterator tok = tokens.begin(); tok != tokens.end(); tok++)\r
561         {\r
562                 idx = value_index(tok->c_str(), font_style_strings);\r
563                 if(!is_family)\r
564                 {\r
565                         if(idx >= 0)\r
566                         {\r
567                                 if(idx == 0 && !was_normal)\r
568                                 {\r
569                                         add_parsed_property(_t("font-weight"),          *tok, important);\r
570                                         add_parsed_property(_t("font-variant"),         *tok, important);\r
571                                         add_parsed_property(_t("font-style"),           *tok, important);\r
572                                 } else\r
573                                 {\r
574                                         add_parsed_property(_t("font-style"),           *tok, important);\r
575                                 }\r
576                         } else\r
577                         {\r
578                                 if(value_in_list(tok->c_str(), font_weight_strings))\r
579                                 {\r
580                                         add_parsed_property(_t("font-weight"),          *tok, important);\r
581                                 } else\r
582                                 {\r
583                                         if(value_in_list(tok->c_str(), font_variant_strings))\r
584                                         {\r
585                                                 add_parsed_property(_t("font-variant"), *tok, important);\r
586                                         } else if( iswdigit((*tok)[0]) )\r
587                                         {\r
588                                                 string_vector szlh;\r
589                                                 split_string(*tok, szlh, _t("/"));\r
590 \r
591                                                 if(szlh.size() == 1)\r
592                                                 {\r
593                                                         add_parsed_property(_t("font-size"),    szlh[0], important);\r
594                                                 } else  if(szlh.size() >= 2)\r
595                                                 {\r
596                                                         add_parsed_property(_t("font-size"),    szlh[0], important);\r
597                                                         add_parsed_property(_t("line-height"),  szlh[1], important);\r
598                                                 }\r
599                                         } else\r
600                                         {\r
601                                                 is_family = true;\r
602                                                 font_family += *tok;\r
603                                         }\r
604                                 }\r
605                         }\r
606                 } else\r
607                 {\r
608                         font_family += *tok;\r
609                 }\r
610         }\r
611         add_parsed_property(_t("font-family"), font_family, important);\r
612 }\r
613 \r
614 void litehtml::style::add_parsed_property( const tstring& name, const tstring& val, bool important )\r
615 {\r
616         bool is_valid = true;\r
617         string_map::iterator vals = m_valid_values.find(name);\r
618         if (vals != m_valid_values.end())\r
619         {\r
620                 if (!value_in_list(val, vals->second))\r
621                 {\r
622                         is_valid = false;\r
623                 }\r
624         }\r
625 \r
626         if (is_valid)\r
627         {\r
628                 props_map::iterator prop = m_properties.find(name);\r
629                 if (prop != m_properties.end())\r
630                 {\r
631                         if (!prop->second.m_important || (important && prop->second.m_important))\r
632                         {\r
633                                 prop->second.m_value = val;\r
634                                 prop->second.m_important = important;\r
635                         }\r
636                 }\r
637                 else\r
638                 {\r
639                         m_properties[name] = property_value(val.c_str(), important);\r
640                 }\r
641         }\r
642 }\r
643 \r
644 void litehtml::style::remove_property( const tstring& name, bool important )\r
645 {\r
646         props_map::iterator prop = m_properties.find(name);\r
647         if(prop != m_properties.end())\r
648         {\r
649                 if( !prop->second.m_important || (important && prop->second.m_important) )\r
650                 {\r
651                         m_properties.erase(prop);\r
652                 }\r
653         }\r
654 }\r