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