Update current version of litehtml. Fix a crash when document contains no fonts
[claws.git] / src / plugins / litehtml_viewer / litehtml / style.cpp
index 60b873837976d43f69cddef1b171b7d431bdd153..be0687073a967a90f0a3bf5ad9ad83d91980560d 100644 (file)
-#include "html.h"\r
-#include "style.h"\r
-#include <functional>\r
-#include <algorithm>\r
-#ifndef WINCE\r
-#include <locale>\r
-#endif\r
-\r
-litehtml::string_map litehtml::style::m_valid_values =\r
-{\r
-       { _t("white-space"), white_space_strings }\r
-};\r
-\r
-litehtml::style::style()\r
-{\r
-}\r
-\r
-litehtml::style::style( const style& val )\r
-{\r
-       m_properties = val.m_properties;\r
-}\r
-\r
-litehtml::style::~style()\r
-{\r
-\r
-}\r
-\r
-void litehtml::style::parse( const tchar_t* txt, const tchar_t* baseurl )\r
-{\r
-       std::vector<tstring> properties;\r
-       split_string(txt, properties, _t(";"));\r
-\r
-       for(std::vector<tstring>::const_iterator i = properties.begin(); i != properties.end(); i++)\r
-       {\r
-               parse_property(*i, baseurl);\r
-       }\r
-}\r
-\r
-void litehtml::style::parse_property( const tstring& txt, const tchar_t* baseurl )\r
-{\r
-       tstring::size_type pos = txt.find_first_of(_t(":"));\r
-       if(pos != tstring::npos)\r
-       {\r
-               tstring name    = txt.substr(0, pos);\r
-               tstring val     = txt.substr(pos + 1);\r
-\r
-               trim(name);\r
-               trim(val);\r
-\r
-               lcase(name);\r
-\r
-               if(!name.empty() && !val.empty())\r
-               {\r
-                       string_vector vals;\r
-                       split_string(val, vals, _t("!"));\r
-                       if(vals.size() == 1)\r
-                       {\r
-                               add_property(name.c_str(), val.c_str(), baseurl, false);\r
-                       } else if(vals.size() > 1)\r
-                       {\r
-                               trim(vals[0]);\r
-                               lcase(vals[1]);\r
-                               if(vals[1] == _t("important"))\r
-                               {\r
-                                       add_property(name.c_str(), vals[0].c_str(), baseurl, true);\r
-                               } else\r
-                               {\r
-                                       add_property(name.c_str(), vals[0].c_str(), baseurl, false);\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-}\r
-\r
-void litehtml::style::combine( const litehtml::style& src )\r
-{\r
-       for(props_map::const_iterator i = src.m_properties.begin(); i != src.m_properties.end(); i++)\r
-       {\r
-               add_parsed_property(i->first.c_str(), i->second.m_value.c_str(), i->second.m_important);\r
-       }\r
-}\r
-\r
-void litehtml::style::add_property( const tchar_t* name, const tchar_t* val, const tchar_t* baseurl, bool important )\r
-{\r
-       if(!name || !val)\r
-       {\r
-               return;\r
-       }\r
-\r
-       // Add baseurl for background image \r
-       if(     !t_strcmp(name, _t("background-image")))\r
-       {\r
-               add_parsed_property(name, val, important);\r
-               if(baseurl)\r
-               {\r
-                       add_parsed_property(_t("background-image-baseurl"), baseurl, important);\r
-               }\r
-       } else\r
-\r
-       // Parse border spacing properties \r
-       if(     !t_strcmp(name, _t("border-spacing")))\r
-       {\r
-               string_vector tokens;\r
-               split_string(val, tokens, _t(" "));\r
-               if(tokens.size() == 1)\r
-               {\r
-                       add_property(_t("-litehtml-border-spacing-x"), tokens[0].c_str(), baseurl, important);\r
-                       add_property(_t("-litehtml-border-spacing-y"), tokens[0].c_str(), baseurl, important);\r
-               } else if(tokens.size() == 2)\r
-               {\r
-                       add_property(_t("-litehtml-border-spacing-x"), tokens[0].c_str(), baseurl, important);\r
-                       add_property(_t("-litehtml-border-spacing-y"), tokens[1].c_str(), baseurl, important);\r
-               }\r
-       } else\r
-\r
-       // Parse borders shorthand properties \r
-\r
-       if(     !t_strcmp(name, _t("border")))\r
-       {\r
-               string_vector tokens;\r
-               split_string(val, tokens, _t(" "), _t(""), _t("("));\r
-               int idx;\r
-               tstring str;\r
-               for(string_vector::const_iterator tok = tokens.begin(); tok != tokens.end(); tok++)\r
-               {\r
-                       idx = value_index(tok->c_str(), border_style_strings, -1);\r
-                       if(idx >= 0)\r
-                       {\r
-                               add_property(_t("border-left-style"), tok->c_str(), baseurl, important);\r
-                               add_property(_t("border-right-style"), tok->c_str(), baseurl, important);\r
-                               add_property(_t("border-top-style"), tok->c_str(), baseurl, important);\r
-                               add_property(_t("border-bottom-style"), tok->c_str(), baseurl, important);\r
-                       } else\r
-                       {\r
-                               if(web_color::is_color(tok->c_str()))\r
-                               {\r
-                                       add_property(_t("border-left-color"), tok->c_str(), baseurl, important);\r
-                                       add_property(_t("border-right-color"), tok->c_str(), baseurl, important);\r
-                                       add_property(_t("border-top-color"), tok->c_str(), baseurl, important);\r
-                                       add_property(_t("border-bottom-color"), tok->c_str(), baseurl, important);\r
-                               } else\r
-                               {\r
-                                       add_property(_t("border-left-width"), tok->c_str(), baseurl, important);\r
-                                       add_property(_t("border-right-width"), tok->c_str(), baseurl, important);\r
-                                       add_property(_t("border-top-width"), tok->c_str(), baseurl, important);\r
-                                       add_property(_t("border-bottom-width"), tok->c_str(), baseurl, important);\r
-                               }\r
-                       }\r
-               }\r
-       } else if(      !t_strcmp(name, _t("border-left"))      ||\r
-               !t_strcmp(name, _t("border-right"))     ||\r
-               !t_strcmp(name, _t("border-top"))       ||\r
-               !t_strcmp(name, _t("border-bottom")) )\r
-       {\r
-               string_vector tokens;\r
-               split_string(val, tokens, _t(" "), _t(""), _t("("));\r
-               int idx;\r
-               tstring str;\r
-               for(string_vector::const_iterator tok = tokens.begin(); tok != tokens.end(); tok++)\r
-               {\r
-                       idx = value_index(tok->c_str(), border_style_strings, -1);\r
-                       if(idx >= 0)\r
-                       {\r
-                               str = name;\r
-                               str += _t("-style");\r
-                               add_property(str.c_str(), tok->c_str(), baseurl, important);\r
-                       } else\r
-                       {\r
-                               if(web_color::is_color(tok->c_str()))\r
-                               {\r
-                                       str = name;\r
-                                       str += _t("-color");\r
-                                       add_property(str.c_str(), tok->c_str(), baseurl, important);\r
-                               } else\r
-                               {\r
-                                       str = name;\r
-                                       str += _t("-width");\r
-                                       add_property(str.c_str(), tok->c_str(), baseurl, important);\r
-                               }\r
-                       }\r
-               }\r
-       } else \r
-\r
-       // Parse border radius shorthand properties \r
-       if(!t_strcmp(name, _t("border-bottom-left-radius")))\r
-       {\r
-               string_vector tokens;\r
-               split_string(val, tokens, _t(" "));\r
-               if(tokens.size() >= 2)\r
-               {\r
-                       add_property(_t("border-bottom-left-radius-x"), tokens[0].c_str(), baseurl, important);\r
-                       add_property(_t("border-bottom-left-radius-y"), tokens[1].c_str(), baseurl, important);\r
-               } else if(tokens.size() == 1)\r
-               {\r
-                       add_property(_t("border-bottom-left-radius-x"), tokens[0].c_str(), baseurl, important);\r
-                       add_property(_t("border-bottom-left-radius-y"), tokens[0].c_str(), baseurl, important);\r
-               }\r
-\r
-       } else if(!t_strcmp(name, _t("border-bottom-right-radius")))\r
-       {\r
-               string_vector tokens;\r
-               split_string(val, tokens, _t(" "));\r
-               if(tokens.size() >= 2)\r
-               {\r
-                       add_property(_t("border-bottom-right-radius-x"), tokens[0].c_str(), baseurl, important);\r
-                       add_property(_t("border-bottom-right-radius-y"), tokens[1].c_str(), baseurl, important);\r
-               } else if(tokens.size() == 1)\r
-               {\r
-                       add_property(_t("border-bottom-right-radius-x"), tokens[0].c_str(), baseurl, important);\r
-                       add_property(_t("border-bottom-right-radius-y"), tokens[0].c_str(), baseurl, important);\r
-               }\r
-\r
-       } else if(!t_strcmp(name, _t("border-top-right-radius")))\r
-       {\r
-               string_vector tokens;\r
-               split_string(val, tokens, _t(" "));\r
-               if(tokens.size() >= 2)\r
-               {\r
-                       add_property(_t("border-top-right-radius-x"), tokens[0].c_str(), baseurl, important);\r
-                       add_property(_t("border-top-right-radius-y"), tokens[1].c_str(), baseurl, important);\r
-               } else if(tokens.size() == 1)\r
-               {\r
-                       add_property(_t("border-top-right-radius-x"), tokens[0].c_str(), baseurl, important);\r
-                       add_property(_t("border-top-right-radius-y"), tokens[0].c_str(), baseurl, important);\r
-               }\r
-\r
-       } else if(!t_strcmp(name, _t("border-top-left-radius")))\r
-       {\r
-               string_vector tokens;\r
-               split_string(val, tokens, _t(" "));\r
-               if(tokens.size() >= 2)\r
-               {\r
-                       add_property(_t("border-top-left-radius-x"), tokens[0].c_str(), baseurl, important);\r
-                       add_property(_t("border-top-left-radius-y"), tokens[1].c_str(), baseurl, important);\r
-               } else if(tokens.size() == 1)\r
-               {\r
-                       add_property(_t("border-top-left-radius-x"), tokens[0].c_str(), baseurl, important);\r
-                       add_property(_t("border-top-left-radius-y"), tokens[0].c_str(), baseurl, important);\r
-               }\r
-\r
-       } else \r
-\r
-       // Parse border-radius shorthand properties \r
-       if(!t_strcmp(name, _t("border-radius")))\r
-       {\r
-               string_vector tokens;\r
-               split_string(val, tokens, _t("/"));\r
-               if(tokens.size() == 1)\r
-               {\r
-                       add_property(_t("border-radius-x"), tokens[0].c_str(), baseurl, important);\r
-                       add_property(_t("border-radius-y"), tokens[0].c_str(), baseurl, important);\r
-               } else if(tokens.size() >= 2)\r
-               {\r
-                       add_property(_t("border-radius-x"), tokens[0].c_str(), baseurl, important);\r
-                       add_property(_t("border-radius-y"), tokens[1].c_str(), baseurl, important);\r
-               }\r
-       } else if(!t_strcmp(name, _t("border-radius-x")))\r
-       {\r
-               string_vector tokens;\r
-               split_string(val, tokens, _t(" "));\r
-               if(tokens.size() == 1)\r
-               {\r
-                       add_property(_t("border-top-left-radius-x"),            tokens[0].c_str(), baseurl, important);\r
-                       add_property(_t("border-top-right-radius-x"),           tokens[0].c_str(), baseurl, important);\r
-                       add_property(_t("border-bottom-right-radius-x"),        tokens[0].c_str(), baseurl, important);\r
-                       add_property(_t("border-bottom-left-radius-x"), tokens[0].c_str(), baseurl, important);\r
-               } else if(tokens.size() == 2)\r
-               {\r
-                       add_property(_t("border-top-left-radius-x"),            tokens[0].c_str(), baseurl, important);\r
-                       add_property(_t("border-top-right-radius-x"),           tokens[1].c_str(), baseurl, important);\r
-                       add_property(_t("border-bottom-right-radius-x"),        tokens[0].c_str(), baseurl, important);\r
-                       add_property(_t("border-bottom-left-radius-x"), tokens[1].c_str(), baseurl, important);\r
-               } else if(tokens.size() == 3)\r
-               {\r
-                       add_property(_t("border-top-left-radius-x"),            tokens[0].c_str(), baseurl, important);\r
-                       add_property(_t("border-top-right-radius-x"),           tokens[1].c_str(), baseurl, important);\r
-                       add_property(_t("border-bottom-right-radius-x"),        tokens[2].c_str(), baseurl, important);\r
-                       add_property(_t("border-bottom-left-radius-x"), tokens[1].c_str(), baseurl, important);\r
-               } else if(tokens.size() == 4)\r
-               {\r
-                       add_property(_t("border-top-left-radius-x"),            tokens[0].c_str(), baseurl, important);\r
-                       add_property(_t("border-top-right-radius-x"),           tokens[1].c_str(), baseurl, important);\r
-                       add_property(_t("border-bottom-right-radius-x"),        tokens[2].c_str(), baseurl, important);\r
-                       add_property(_t("border-bottom-left-radius-x"), tokens[3].c_str(), baseurl, important);\r
-               }\r
-       } else if(!t_strcmp(name, _t("border-radius-y")))\r
-       {\r
-               string_vector tokens;\r
-               split_string(val, tokens, _t(" "));\r
-               if(tokens.size() == 1)\r
-               {\r
-                       add_property(_t("border-top-left-radius-y"),            tokens[0].c_str(), baseurl, important);\r
-                       add_property(_t("border-top-right-radius-y"),           tokens[0].c_str(), baseurl, important);\r
-                       add_property(_t("border-bottom-right-radius-y"),        tokens[0].c_str(), baseurl, important);\r
-                       add_property(_t("border-bottom-left-radius-y"), tokens[0].c_str(), baseurl, important);\r
-               } else if(tokens.size() == 2)\r
-               {\r
-                       add_property(_t("border-top-left-radius-y"),            tokens[0].c_str(), baseurl, important);\r
-                       add_property(_t("border-top-right-radius-y"),           tokens[1].c_str(), baseurl, important);\r
-                       add_property(_t("border-bottom-right-radius-y"),        tokens[0].c_str(), baseurl, important);\r
-                       add_property(_t("border-bottom-left-radius-y"), tokens[1].c_str(), baseurl, important);\r
-               } else if(tokens.size() == 3)\r
-               {\r
-                       add_property(_t("border-top-left-radius-y"),            tokens[0].c_str(), baseurl, important);\r
-                       add_property(_t("border-top-right-radius-y"),           tokens[1].c_str(), baseurl, important);\r
-                       add_property(_t("border-bottom-right-radius-y"),        tokens[2].c_str(), baseurl, important);\r
-                       add_property(_t("border-bottom-left-radius-y"), tokens[1].c_str(), baseurl, important);\r
-               } else if(tokens.size() == 4)\r
-               {\r
-                       add_property(_t("border-top-left-radius-y"),            tokens[0].c_str(), baseurl, important);\r
-                       add_property(_t("border-top-right-radius-y"),           tokens[1].c_str(), baseurl, important);\r
-                       add_property(_t("border-bottom-right-radius-y"),        tokens[2].c_str(), baseurl, important);\r
-                       add_property(_t("border-bottom-left-radius-y"), tokens[3].c_str(), baseurl, important);\r
-               }\r
-       }\r
-       \r
-\r
-       // Parse list-style shorthand properties \r
-       if(!t_strcmp(name, _t("list-style")))\r
-       {\r
-               add_parsed_property(_t("list-style-type"),                      _t("disc"),             important);\r
-               add_parsed_property(_t("list-style-position"),          _t("outside"),  important);\r
-               add_parsed_property(_t("list-style-image"),                     _t(""),                 important);\r
-               add_parsed_property(_t("list-style-image-baseurl"),     _t(""),                 important);\r
-\r
-               string_vector tokens;\r
-               split_string(val, tokens, _t(" "), _t(""), _t("("));\r
-               for(string_vector::iterator tok = tokens.begin(); tok != tokens.end(); tok++)\r
-               {\r
-                       int idx = value_index(tok->c_str(), list_style_type_strings, -1);\r
-                       if(idx >= 0)\r
-                       {\r
-                               add_parsed_property(_t("list-style-type"), *tok, important);\r
-                       } else\r
-                       {\r
-                               idx = value_index(tok->c_str(), list_style_position_strings, -1);\r
-                               if(idx >= 0)\r
-                               {\r
-                                       add_parsed_property(_t("list-style-position"), *tok, important);\r
-                               } else if(!t_strncmp(val, _t("url"), 3))\r
-                               {\r
-                                       add_parsed_property(_t("list-style-image"), *tok, important);\r
-                                       if(baseurl)\r
-                                       {\r
-                                               add_parsed_property(_t("list-style-image-baseurl"), baseurl, important);\r
-                                       }\r
-                               }\r
-                       }\r
-               }\r
-       } else \r
-\r
-       // Add baseurl for background image \r
-       if(     !t_strcmp(name, _t("list-style-image")))\r
-       {\r
-               add_parsed_property(name, val, important);\r
-               if(baseurl)\r
-               {\r
-                       add_parsed_property(_t("list-style-image-baseurl"), baseurl, important);\r
-               }\r
-       } else\r
-               \r
-       // Parse background shorthand properties \r
-       if(!t_strcmp(name, _t("background")))\r
-       {\r
-               parse_short_background(val, baseurl, important);\r
-\r
-       } else \r
-               \r
-       // Parse margin and padding shorthand properties \r
-       if(!t_strcmp(name, _t("margin")) || !t_strcmp(name, _t("padding")))\r
-       {\r
-               string_vector tokens;\r
-               split_string(val, tokens, _t(" "));\r
-               if(tokens.size() >= 4)\r
-               {\r
-                       add_parsed_property(tstring(name) + _t("-top"),         tokens[0], important);\r
-                       add_parsed_property(tstring(name) + _t("-right"),               tokens[1], important);\r
-                       add_parsed_property(tstring(name) + _t("-bottom"),      tokens[2], important);\r
-                       add_parsed_property(tstring(name) + _t("-left"),                tokens[3], important);\r
-               } else if(tokens.size() == 3)\r
-               {\r
-                       add_parsed_property(tstring(name) + _t("-top"),         tokens[0], important);\r
-                       add_parsed_property(tstring(name) + _t("-right"),               tokens[1], important);\r
-                       add_parsed_property(tstring(name) + _t("-left"),                tokens[1], important);\r
-                       add_parsed_property(tstring(name) + _t("-bottom"),      tokens[2], important);\r
-               } else if(tokens.size() == 2)\r
-               {\r
-                       add_parsed_property(tstring(name) + _t("-top"),         tokens[0], important);\r
-                       add_parsed_property(tstring(name) + _t("-bottom"),      tokens[0], important);\r
-                       add_parsed_property(tstring(name) + _t("-right"),               tokens[1], important);\r
-                       add_parsed_property(tstring(name) + _t("-left"),                tokens[1], important);\r
-               } else if(tokens.size() == 1)\r
-               {\r
-                       add_parsed_property(tstring(name) + _t("-top"),         tokens[0], important);\r
-                       add_parsed_property(tstring(name) + _t("-bottom"),      tokens[0], important);\r
-                       add_parsed_property(tstring(name) + _t("-right"),               tokens[0], important);\r
-                       add_parsed_property(tstring(name) + _t("-left"),                tokens[0], important);\r
-               }\r
-       } else \r
-               \r
-               \r
-       // Parse border-* shorthand properties \r
-       if(     !t_strcmp(name, _t("border-left")) || \r
-               !t_strcmp(name, _t("border-right")) ||\r
-               !t_strcmp(name, _t("border-top"))  || \r
-               !t_strcmp(name, _t("border-bottom")))\r
-       {\r
-               parse_short_border(name, val, important);\r
-       } else \r
-               \r
-       // Parse border-width/style/color shorthand properties \r
-       if(     !t_strcmp(name, _t("border-width")) ||\r
-               !t_strcmp(name, _t("border-style"))  ||\r
-               !t_strcmp(name, _t("border-color")) )\r
-       {\r
-               string_vector nametokens;\r
-               split_string(name, nametokens, _t("-"));\r
-\r
-               string_vector tokens;\r
-               split_string(val, tokens, _t(" "));\r
-               if(tokens.size() >= 4)\r
-               {\r
-                       add_parsed_property(nametokens[0] + _t("-top-")         + nametokens[1],        tokens[0], important);\r
-                       add_parsed_property(nametokens[0] + _t("-right-")       + nametokens[1],        tokens[1], important);\r
-                       add_parsed_property(nametokens[0] + _t("-bottom-")      + nametokens[1],        tokens[2], important);\r
-                       add_parsed_property(nametokens[0] + _t("-left-")        + nametokens[1],        tokens[3], important);\r
-               } else if(tokens.size() == 3)\r
-               {\r
-                       add_parsed_property(nametokens[0] + _t("-top-")         + nametokens[1],        tokens[0], important);\r
-                       add_parsed_property(nametokens[0] + _t("-right-")       + nametokens[1],        tokens[1], important);\r
-                       add_parsed_property(nametokens[0] + _t("-left-")        + nametokens[1],        tokens[1], important);\r
-                       add_parsed_property(nametokens[0] + _t("-bottom-")      + nametokens[1],        tokens[2], important);\r
-               } else if(tokens.size() == 2)\r
-               {\r
-                       add_parsed_property(nametokens[0] + _t("-top-")         + nametokens[1],        tokens[0], important);\r
-                       add_parsed_property(nametokens[0] + _t("-bottom-")      + nametokens[1],        tokens[0], important);\r
-                       add_parsed_property(nametokens[0] + _t("-right-")       + nametokens[1],        tokens[1], important);\r
-                       add_parsed_property(nametokens[0] + _t("-left-")        + nametokens[1],        tokens[1], important);\r
-               } else if(tokens.size() == 1)\r
-               {\r
-                       add_parsed_property(nametokens[0] + _t("-top-")         + nametokens[1],        tokens[0], important);\r
-                       add_parsed_property(nametokens[0] + _t("-bottom-")      + nametokens[1],        tokens[0], important);\r
-                       add_parsed_property(nametokens[0] + _t("-right-")       + nametokens[1],        tokens[0], important);\r
-                       add_parsed_property(nametokens[0] + _t("-left-")        + nametokens[1],        tokens[0], important);\r
-               }\r
-       } else \r
-               \r
-       // Parse font shorthand properties \r
-       if(!t_strcmp(name, _t("font")))\r
-       {\r
-               parse_short_font(val, important);\r
-       } else \r
-       {\r
-               add_parsed_property(name, val, important);\r
-       }\r
-}\r
-\r
-void litehtml::style::parse_short_border( const tstring& prefix, const tstring& val, bool important )\r
-{\r
-       string_vector tokens;\r
-       split_string(val, tokens, _t(" "), _t(""), _t("("));\r
-       if(tokens.size() >= 3)\r
-       {\r
-               add_parsed_property(prefix + _t("-width"),      tokens[0], important);\r
-               add_parsed_property(prefix + _t("-style"),      tokens[1], important);\r
-               add_parsed_property(prefix + _t("-color"),      tokens[2], important);\r
-       } else if(tokens.size() == 2)\r
-       {\r
-               if(iswdigit(tokens[0][0]) || value_index(val.c_str(), border_width_strings) >= 0)\r
-               {\r
-                       add_parsed_property(prefix + _t("-width"),      tokens[0], important);\r
-                       add_parsed_property(prefix + _t("-style"),      tokens[1], important);\r
-               } else\r
-               {\r
-                       add_parsed_property(prefix + _t("-style"),      tokens[0], important);\r
-                       add_parsed_property(prefix + _t("-color"),      tokens[1], important);\r
-               }\r
-       }\r
-}\r
-\r
-void litehtml::style::parse_short_background( const tstring& val, const tchar_t* baseurl, bool important )\r
-{\r
-       add_parsed_property(_t("background-color"),                     _t("transparent"),      important);\r
-       add_parsed_property(_t("background-image"),                     _t(""),                         important);\r
-       add_parsed_property(_t("background-image-baseurl"), _t(""),                             important);\r
-       add_parsed_property(_t("background-repeat"),            _t("repeat"),           important);\r
-       add_parsed_property(_t("background-origin"),            _t("padding-box"),      important);\r
-       add_parsed_property(_t("background-clip"),                      _t("border-box"),       important);\r
-       add_parsed_property(_t("background-attachment"),        _t("scroll"),           important);\r
-\r
-       if(val == _t("none"))\r
-       {\r
-               return;\r
-       }\r
-\r
-       string_vector tokens;\r
-       split_string(val, tokens, _t(" "), _t(""), _t("("));\r
-       bool origin_found = false;\r
-       for(string_vector::iterator tok = tokens.begin(); tok != tokens.end(); tok++)\r
-       {\r
-               if(web_color::is_color(tok->c_str()))\r
-               {\r
-                       add_parsed_property(_t("background-color"), *tok, important);\r
-               } else if(tok->substr(0, 3) == _t("url"))\r
-               {\r
-                       add_parsed_property(_t("background-image"), *tok, important);\r
-                       if(baseurl)\r
-                       {\r
-                               add_parsed_property(_t("background-image-baseurl"), baseurl, important);\r
-                       }\r
-\r
-               } else if( value_in_list(tok->c_str(), background_repeat_strings) )\r
-               {\r
-                       add_parsed_property(_t("background-repeat"), *tok, important);\r
-               } else if( value_in_list(tok->c_str(), background_attachment_strings) )\r
-               {\r
-                       add_parsed_property(_t("background-attachment"), *tok, important);\r
-               } else if( value_in_list(tok->c_str(), background_box_strings) )\r
-               {\r
-                       if(!origin_found)\r
-                       {\r
-                               add_parsed_property(_t("background-origin"), *tok, important);\r
-                               origin_found = true;\r
-                       } else\r
-                       {\r
-                               add_parsed_property(_t("background-clip"),*tok, important);\r
-                       }\r
-               } else if(      value_in_list(tok->c_str(), _t("left;right;top;bottom;center")) ||\r
-                                       iswdigit((*tok)[0]) ||\r
-                                       (*tok)[0] == _t('-')    ||\r
-                                       (*tok)[0] == _t('.')    ||\r
-                                       (*tok)[0] == _t('+'))\r
-               {\r
-                       if(m_properties.find(_t("background-position")) != m_properties.end())\r
-                       {\r
-                               m_properties[_t("background-position")].m_value = m_properties[_t("background-position")].m_value + _t(" ") + *tok;\r
-                       } else\r
-                       {\r
-                               add_parsed_property(_t("background-position"), *tok, important);\r
-                       }\r
-               }\r
-       }\r
-}\r
-\r
-void litehtml::style::parse_short_font( const tstring& val, bool important )\r
-{\r
-       add_parsed_property(_t("font-style"),   _t("normal"),   important);\r
-       add_parsed_property(_t("font-variant"), _t("normal"),   important);\r
-       add_parsed_property(_t("font-weight"),  _t("normal"),   important);\r
-       add_parsed_property(_t("font-size"),            _t("medium"),   important);\r
-       add_parsed_property(_t("line-height"),  _t("normal"),   important);\r
-\r
-       string_vector tokens;\r
-       split_string(val, tokens, _t(" "), _t(""), _t("\""));\r
-\r
-       int idx = 0;\r
-       bool was_normal = false;\r
-       bool is_family = false;\r
-       tstring font_family;\r
-       for(string_vector::iterator tok = tokens.begin(); tok != tokens.end(); tok++)\r
-       {\r
-               idx = value_index(tok->c_str(), font_style_strings);\r
-               if(!is_family)\r
-               {\r
-                       if(idx >= 0)\r
-                       {\r
-                               if(idx == 0 && !was_normal)\r
-                               {\r
-                                       add_parsed_property(_t("font-weight"),          *tok, important);\r
-                                       add_parsed_property(_t("font-variant"),         *tok, important);\r
-                                       add_parsed_property(_t("font-style"),           *tok, important);\r
-                               } else\r
-                               {\r
-                                       add_parsed_property(_t("font-style"),           *tok, important);\r
-                               }\r
-                       } else\r
-                       {\r
-                               if(value_in_list(tok->c_str(), font_weight_strings))\r
-                               {\r
-                                       add_parsed_property(_t("font-weight"),          *tok, important);\r
-                               } else\r
-                               {\r
-                                       if(value_in_list(tok->c_str(), font_variant_strings))\r
-                                       {\r
-                                               add_parsed_property(_t("font-variant"), *tok, important);\r
-                                       } else if( iswdigit((*tok)[0]) )\r
-                                       {\r
-                                               string_vector szlh;\r
-                                               split_string(*tok, szlh, _t("/"));\r
-\r
-                                               if(szlh.size() == 1)\r
-                                               {\r
-                                                       add_parsed_property(_t("font-size"),    szlh[0], important);\r
-                                               } else  if(szlh.size() >= 2)\r
-                                               {\r
-                                                       add_parsed_property(_t("font-size"),    szlh[0], important);\r
-                                                       add_parsed_property(_t("line-height"),  szlh[1], important);\r
-                                               }\r
-                                       } else\r
-                                       {\r
-                                               is_family = true;\r
-                                               font_family += *tok;\r
-                                       }\r
-                               }\r
-                       }\r
-               } else\r
-               {\r
-                       font_family += *tok;\r
-               }\r
-       }\r
-       add_parsed_property(_t("font-family"), font_family, important);\r
-}\r
-\r
-void litehtml::style::add_parsed_property( const tstring& name, const tstring& val, bool important )\r
-{\r
-       bool is_valid = true;\r
-       string_map::iterator vals = m_valid_values.find(name);\r
-       if (vals != m_valid_values.end())\r
-       {\r
-               if (!value_in_list(val, vals->second))\r
-               {\r
-                       is_valid = false;\r
-               }\r
-       }\r
-\r
-       if (is_valid)\r
-       {\r
-               props_map::iterator prop = m_properties.find(name);\r
-               if (prop != m_properties.end())\r
-               {\r
-                       if (!prop->second.m_important || (important && prop->second.m_important))\r
-                       {\r
-                               prop->second.m_value = val;\r
-                               prop->second.m_important = important;\r
-                       }\r
-               }\r
-               else\r
-               {\r
-                       m_properties[name] = property_value(val.c_str(), important);\r
-               }\r
-       }\r
-}\r
-\r
-void litehtml::style::remove_property( const tstring& name, bool important )\r
-{\r
-       props_map::iterator prop = m_properties.find(name);\r
-       if(prop != m_properties.end())\r
-       {\r
-               if( !prop->second.m_important || (important && prop->second.m_important) )\r
-               {\r
-                       m_properties.erase(prop);\r
-               }\r
-       }\r
-}\r
+#include "html.h"
+#include "style.h"
+#include <functional>
+#include <algorithm>
+#ifndef WINCE
+#include <locale>
+#endif
+
+litehtml::string_map litehtml::style::m_valid_values =
+{
+       { _t("white-space"), white_space_strings }
+};
+
+litehtml::style::style()
+{
+}
+
+litehtml::style::style( const style& val )
+{
+       m_properties = val.m_properties;
+}
+
+litehtml::style::~style()
+{
+
+}
+
+void litehtml::style::parse( const tchar_t* txt, const tchar_t* baseurl )
+{
+       std::vector<tstring> properties;
+       split_string(txt, properties, _t(";"));
+
+       for(std::vector<tstring>::const_iterator i = properties.begin(); i != properties.end(); i++)
+       {
+               parse_property(*i, baseurl);
+       }
+}
+
+void litehtml::style::parse_property( const tstring& txt, const tchar_t* baseurl )
+{
+       tstring::size_type pos = txt.find_first_of(_t(":"));
+       if(pos != tstring::npos)
+       {
+               tstring name    = txt.substr(0, pos);
+               tstring val     = txt.substr(pos + 1);
+
+               trim(name);
+               trim(val);
+
+               lcase(name);
+
+               if(!name.empty() && !val.empty())
+               {
+                       string_vector vals;
+                       split_string(val, vals, _t("!"));
+                       if(vals.size() == 1)
+                       {
+                               add_property(name.c_str(), val.c_str(), baseurl, false);
+                       } else if(vals.size() > 1)
+                       {
+                               trim(vals[0]);
+                               lcase(vals[1]);
+                               if(vals[1] == _t("important"))
+                               {
+                                       add_property(name.c_str(), vals[0].c_str(), baseurl, true);
+                               } else
+                               {
+                                       add_property(name.c_str(), vals[0].c_str(), baseurl, false);
+                               }
+                       }
+               }
+       }
+}
+
+void litehtml::style::combine( const litehtml::style& src )
+{
+       for(props_map::const_iterator i = src.m_properties.begin(); i != src.m_properties.end(); i++)
+       {
+               add_parsed_property(i->first.c_str(), i->second.m_value.c_str(), i->second.m_important);
+       }
+}
+
+void litehtml::style::add_property( const tchar_t* name, const tchar_t* val, const tchar_t* baseurl, bool important )
+{
+       if(!name || !val)
+       {
+               return;
+       }
+
+       // Add baseurl for background image 
+       if(     !t_strcmp(name, _t("background-image")))
+       {
+               add_parsed_property(name, val, important);
+               if(baseurl)
+               {
+                       add_parsed_property(_t("background-image-baseurl"), baseurl, important);
+               }
+       } else
+
+       // Parse border spacing properties 
+       if(     !t_strcmp(name, _t("border-spacing")))
+       {
+               string_vector tokens;
+               split_string(val, tokens, _t(" "));
+               if(tokens.size() == 1)
+               {
+                       add_property(_t("-litehtml-border-spacing-x"), tokens[0].c_str(), baseurl, important);
+                       add_property(_t("-litehtml-border-spacing-y"), tokens[0].c_str(), baseurl, important);
+               } else if(tokens.size() == 2)
+               {
+                       add_property(_t("-litehtml-border-spacing-x"), tokens[0].c_str(), baseurl, important);
+                       add_property(_t("-litehtml-border-spacing-y"), tokens[1].c_str(), baseurl, important);
+               }
+       } else
+
+       // Parse borders shorthand properties 
+
+       if(     !t_strcmp(name, _t("border")))
+       {
+               string_vector tokens;
+               split_string(val, tokens, _t(" "), _t(""), _t("("));
+               int idx;
+               tstring str;
+               for(string_vector::const_iterator tok = tokens.begin(); tok != tokens.end(); tok++)
+               {
+                       idx = value_index(tok->c_str(), border_style_strings, -1);
+                       if(idx >= 0)
+                       {
+                               add_property(_t("border-left-style"), tok->c_str(), baseurl, important);
+                               add_property(_t("border-right-style"), tok->c_str(), baseurl, important);
+                               add_property(_t("border-top-style"), tok->c_str(), baseurl, important);
+                               add_property(_t("border-bottom-style"), tok->c_str(), baseurl, important);
+                       } else
+                       {
+                               if (t_isdigit((*tok)[0]) || (*tok)[0] == _t('.') ||
+                                       value_in_list((*tok), _t("thin;medium;thick")))
+                               {
+                                       add_property(_t("border-left-width"), tok->c_str(), baseurl, important);
+                                       add_property(_t("border-right-width"), tok->c_str(), baseurl, important);
+                                       add_property(_t("border-top-width"), tok->c_str(), baseurl, important);
+                                       add_property(_t("border-bottom-width"), tok->c_str(), baseurl, important);
+                               } 
+                               else
+                               {
+                                       add_property(_t("border-left-color"), tok->c_str(), baseurl, important);
+                                       add_property(_t("border-right-color"), tok->c_str(), baseurl, important);
+                                       add_property(_t("border-top-color"), tok->c_str(), baseurl, important);
+                                       add_property(_t("border-bottom-color"), tok->c_str(), baseurl, important);
+                               }
+                       }
+               }
+       } else if(      !t_strcmp(name, _t("border-left"))      ||
+               !t_strcmp(name, _t("border-right"))     ||
+               !t_strcmp(name, _t("border-top"))       ||
+               !t_strcmp(name, _t("border-bottom")) )
+       {
+               string_vector tokens;
+               split_string(val, tokens, _t(" "), _t(""), _t("("));
+               int idx;
+               tstring str;
+               for(string_vector::const_iterator tok = tokens.begin(); tok != tokens.end(); tok++)
+               {
+                       idx = value_index(tok->c_str(), border_style_strings, -1);
+                       if(idx >= 0)
+                       {
+                               str = name;
+                               str += _t("-style");
+                               add_property(str.c_str(), tok->c_str(), baseurl, important);
+                       } else
+                       {
+                               if(web_color::is_color(tok->c_str()))
+                               {
+                                       str = name;
+                                       str += _t("-color");
+                                       add_property(str.c_str(), tok->c_str(), baseurl, important);
+                               } else
+                               {
+                                       str = name;
+                                       str += _t("-width");
+                                       add_property(str.c_str(), tok->c_str(), baseurl, important);
+                               }
+                       }
+               }
+       } else 
+
+       // Parse border radius shorthand properties 
+       if(!t_strcmp(name, _t("border-bottom-left-radius")))
+       {
+               string_vector tokens;
+               split_string(val, tokens, _t(" "));
+               if(tokens.size() >= 2)
+               {
+                       add_property(_t("border-bottom-left-radius-x"), tokens[0].c_str(), baseurl, important);
+                       add_property(_t("border-bottom-left-radius-y"), tokens[1].c_str(), baseurl, important);
+               } else if(tokens.size() == 1)
+               {
+                       add_property(_t("border-bottom-left-radius-x"), tokens[0].c_str(), baseurl, important);
+                       add_property(_t("border-bottom-left-radius-y"), tokens[0].c_str(), baseurl, important);
+               }
+
+       } else if(!t_strcmp(name, _t("border-bottom-right-radius")))
+       {
+               string_vector tokens;
+               split_string(val, tokens, _t(" "));
+               if(tokens.size() >= 2)
+               {
+                       add_property(_t("border-bottom-right-radius-x"), tokens[0].c_str(), baseurl, important);
+                       add_property(_t("border-bottom-right-radius-y"), tokens[1].c_str(), baseurl, important);
+               } else if(tokens.size() == 1)
+               {
+                       add_property(_t("border-bottom-right-radius-x"), tokens[0].c_str(), baseurl, important);
+                       add_property(_t("border-bottom-right-radius-y"), tokens[0].c_str(), baseurl, important);
+               }
+
+       } else if(!t_strcmp(name, _t("border-top-right-radius")))
+       {
+               string_vector tokens;
+               split_string(val, tokens, _t(" "));
+               if(tokens.size() >= 2)
+               {
+                       add_property(_t("border-top-right-radius-x"), tokens[0].c_str(), baseurl, important);
+                       add_property(_t("border-top-right-radius-y"), tokens[1].c_str(), baseurl, important);
+               } else if(tokens.size() == 1)
+               {
+                       add_property(_t("border-top-right-radius-x"), tokens[0].c_str(), baseurl, important);
+                       add_property(_t("border-top-right-radius-y"), tokens[0].c_str(), baseurl, important);
+               }
+
+       } else if(!t_strcmp(name, _t("border-top-left-radius")))
+       {
+               string_vector tokens;
+               split_string(val, tokens, _t(" "));
+               if(tokens.size() >= 2)
+               {
+                       add_property(_t("border-top-left-radius-x"), tokens[0].c_str(), baseurl, important);
+                       add_property(_t("border-top-left-radius-y"), tokens[1].c_str(), baseurl, important);
+               } else if(tokens.size() == 1)
+               {
+                       add_property(_t("border-top-left-radius-x"), tokens[0].c_str(), baseurl, important);
+                       add_property(_t("border-top-left-radius-y"), tokens[0].c_str(), baseurl, important);
+               }
+
+       } else 
+
+       // Parse border-radius shorthand properties 
+       if(!t_strcmp(name, _t("border-radius")))
+       {
+               string_vector tokens;
+               split_string(val, tokens, _t("/"));
+               if(tokens.size() == 1)
+               {
+                       add_property(_t("border-radius-x"), tokens[0].c_str(), baseurl, important);
+                       add_property(_t("border-radius-y"), tokens[0].c_str(), baseurl, important);
+               } else if(tokens.size() >= 2)
+               {
+                       add_property(_t("border-radius-x"), tokens[0].c_str(), baseurl, important);
+                       add_property(_t("border-radius-y"), tokens[1].c_str(), baseurl, important);
+               }
+       } else if(!t_strcmp(name, _t("border-radius-x")))
+       {
+               string_vector tokens;
+               split_string(val, tokens, _t(" "));
+               if(tokens.size() == 1)
+               {
+                       add_property(_t("border-top-left-radius-x"),            tokens[0].c_str(), baseurl, important);
+                       add_property(_t("border-top-right-radius-x"),           tokens[0].c_str(), baseurl, important);
+                       add_property(_t("border-bottom-right-radius-x"),        tokens[0].c_str(), baseurl, important);
+                       add_property(_t("border-bottom-left-radius-x"), tokens[0].c_str(), baseurl, important);
+               } else if(tokens.size() == 2)
+               {
+                       add_property(_t("border-top-left-radius-x"),            tokens[0].c_str(), baseurl, important);
+                       add_property(_t("border-top-right-radius-x"),           tokens[1].c_str(), baseurl, important);
+                       add_property(_t("border-bottom-right-radius-x"),        tokens[0].c_str(), baseurl, important);
+                       add_property(_t("border-bottom-left-radius-x"), tokens[1].c_str(), baseurl, important);
+               } else if(tokens.size() == 3)
+               {
+                       add_property(_t("border-top-left-radius-x"),            tokens[0].c_str(), baseurl, important);
+                       add_property(_t("border-top-right-radius-x"),           tokens[1].c_str(), baseurl, important);
+                       add_property(_t("border-bottom-right-radius-x"),        tokens[2].c_str(), baseurl, important);
+                       add_property(_t("border-bottom-left-radius-x"), tokens[1].c_str(), baseurl, important);
+               } else if(tokens.size() == 4)
+               {
+                       add_property(_t("border-top-left-radius-x"),            tokens[0].c_str(), baseurl, important);
+                       add_property(_t("border-top-right-radius-x"),           tokens[1].c_str(), baseurl, important);
+                       add_property(_t("border-bottom-right-radius-x"),        tokens[2].c_str(), baseurl, important);
+                       add_property(_t("border-bottom-left-radius-x"), tokens[3].c_str(), baseurl, important);
+               }
+       } else if(!t_strcmp(name, _t("border-radius-y")))
+       {
+               string_vector tokens;
+               split_string(val, tokens, _t(" "));
+               if(tokens.size() == 1)
+               {
+                       add_property(_t("border-top-left-radius-y"),            tokens[0].c_str(), baseurl, important);
+                       add_property(_t("border-top-right-radius-y"),           tokens[0].c_str(), baseurl, important);
+                       add_property(_t("border-bottom-right-radius-y"),        tokens[0].c_str(), baseurl, important);
+                       add_property(_t("border-bottom-left-radius-y"), tokens[0].c_str(), baseurl, important);
+               } else if(tokens.size() == 2)
+               {
+                       add_property(_t("border-top-left-radius-y"),            tokens[0].c_str(), baseurl, important);
+                       add_property(_t("border-top-right-radius-y"),           tokens[1].c_str(), baseurl, important);
+                       add_property(_t("border-bottom-right-radius-y"),        tokens[0].c_str(), baseurl, important);
+                       add_property(_t("border-bottom-left-radius-y"), tokens[1].c_str(), baseurl, important);
+               } else if(tokens.size() == 3)
+               {
+                       add_property(_t("border-top-left-radius-y"),            tokens[0].c_str(), baseurl, important);
+                       add_property(_t("border-top-right-radius-y"),           tokens[1].c_str(), baseurl, important);
+                       add_property(_t("border-bottom-right-radius-y"),        tokens[2].c_str(), baseurl, important);
+                       add_property(_t("border-bottom-left-radius-y"), tokens[1].c_str(), baseurl, important);
+               } else if(tokens.size() == 4)
+               {
+                       add_property(_t("border-top-left-radius-y"),            tokens[0].c_str(), baseurl, important);
+                       add_property(_t("border-top-right-radius-y"),           tokens[1].c_str(), baseurl, important);
+                       add_property(_t("border-bottom-right-radius-y"),        tokens[2].c_str(), baseurl, important);
+                       add_property(_t("border-bottom-left-radius-y"), tokens[3].c_str(), baseurl, important);
+               }
+       }
+       
+
+       // Parse list-style shorthand properties 
+       if(!t_strcmp(name, _t("list-style")))
+       {
+               add_parsed_property(_t("list-style-type"),                      _t("disc"),             important);
+               add_parsed_property(_t("list-style-position"),          _t("outside"),  important);
+               add_parsed_property(_t("list-style-image"),                     _t(""),                 important);
+               add_parsed_property(_t("list-style-image-baseurl"),     _t(""),                 important);
+
+               string_vector tokens;
+               split_string(val, tokens, _t(" "), _t(""), _t("("));
+               for(string_vector::iterator tok = tokens.begin(); tok != tokens.end(); tok++)
+               {
+                       int idx = value_index(tok->c_str(), list_style_type_strings, -1);
+                       if(idx >= 0)
+                       {
+                               add_parsed_property(_t("list-style-type"), *tok, important);
+                       } else
+                       {
+                               idx = value_index(tok->c_str(), list_style_position_strings, -1);
+                               if(idx >= 0)
+                               {
+                                       add_parsed_property(_t("list-style-position"), *tok, important);
+                               } else if(!t_strncmp(val, _t("url"), 3))
+                               {
+                                       add_parsed_property(_t("list-style-image"), *tok, important);
+                                       if(baseurl)
+                                       {
+                                               add_parsed_property(_t("list-style-image-baseurl"), baseurl, important);
+                                       }
+                               }
+                       }
+               }
+       } else 
+
+       // Add baseurl for background image 
+       if(     !t_strcmp(name, _t("list-style-image")))
+       {
+               add_parsed_property(name, val, important);
+               if(baseurl)
+               {
+                       add_parsed_property(_t("list-style-image-baseurl"), baseurl, important);
+               }
+       } else
+               
+       // Parse background shorthand properties 
+       if(!t_strcmp(name, _t("background")))
+       {
+               parse_short_background(val, baseurl, important);
+
+       } else 
+               
+       // Parse margin and padding shorthand properties 
+       if(!t_strcmp(name, _t("margin")) || !t_strcmp(name, _t("padding")))
+       {
+               string_vector tokens;
+               split_string(val, tokens, _t(" "));
+               if(tokens.size() >= 4)
+               {
+                       add_parsed_property(tstring(name) + _t("-top"),         tokens[0], important);
+                       add_parsed_property(tstring(name) + _t("-right"),               tokens[1], important);
+                       add_parsed_property(tstring(name) + _t("-bottom"),      tokens[2], important);
+                       add_parsed_property(tstring(name) + _t("-left"),                tokens[3], important);
+               } else if(tokens.size() == 3)
+               {
+                       add_parsed_property(tstring(name) + _t("-top"),         tokens[0], important);
+                       add_parsed_property(tstring(name) + _t("-right"),               tokens[1], important);
+                       add_parsed_property(tstring(name) + _t("-left"),                tokens[1], important);
+                       add_parsed_property(tstring(name) + _t("-bottom"),      tokens[2], important);
+               } else if(tokens.size() == 2)
+               {
+                       add_parsed_property(tstring(name) + _t("-top"),         tokens[0], important);
+                       add_parsed_property(tstring(name) + _t("-bottom"),      tokens[0], important);
+                       add_parsed_property(tstring(name) + _t("-right"),               tokens[1], important);
+                       add_parsed_property(tstring(name) + _t("-left"),                tokens[1], important);
+               } else if(tokens.size() == 1)
+               {
+                       add_parsed_property(tstring(name) + _t("-top"),         tokens[0], important);
+                       add_parsed_property(tstring(name) + _t("-bottom"),      tokens[0], important);
+                       add_parsed_property(tstring(name) + _t("-right"),               tokens[0], important);
+                       add_parsed_property(tstring(name) + _t("-left"),                tokens[0], important);
+               }
+       } else 
+               
+               
+       // Parse border-* shorthand properties 
+       if(     !t_strcmp(name, _t("border-left")) || 
+               !t_strcmp(name, _t("border-right")) ||
+               !t_strcmp(name, _t("border-top"))  || 
+               !t_strcmp(name, _t("border-bottom")))
+       {
+               parse_short_border(name, val, important);
+       } else 
+               
+       // Parse border-width/style/color shorthand properties 
+       if(     !t_strcmp(name, _t("border-width")) ||
+               !t_strcmp(name, _t("border-style"))  ||
+               !t_strcmp(name, _t("border-color")) )
+       {
+               string_vector nametokens;
+               split_string(name, nametokens, _t("-"));
+
+               string_vector tokens;
+               split_string(val, tokens, _t(" "));
+               if(tokens.size() >= 4)
+               {
+                       add_parsed_property(nametokens[0] + _t("-top-")         + nametokens[1],        tokens[0], important);
+                       add_parsed_property(nametokens[0] + _t("-right-")       + nametokens[1],        tokens[1], important);
+                       add_parsed_property(nametokens[0] + _t("-bottom-")      + nametokens[1],        tokens[2], important);
+                       add_parsed_property(nametokens[0] + _t("-left-")        + nametokens[1],        tokens[3], important);
+               } else if(tokens.size() == 3)
+               {
+                       add_parsed_property(nametokens[0] + _t("-top-")         + nametokens[1],        tokens[0], important);
+                       add_parsed_property(nametokens[0] + _t("-right-")       + nametokens[1],        tokens[1], important);
+                       add_parsed_property(nametokens[0] + _t("-left-")        + nametokens[1],        tokens[1], important);
+                       add_parsed_property(nametokens[0] + _t("-bottom-")      + nametokens[1],        tokens[2], important);
+               } else if(tokens.size() == 2)
+               {
+                       add_parsed_property(nametokens[0] + _t("-top-")         + nametokens[1],        tokens[0], important);
+                       add_parsed_property(nametokens[0] + _t("-bottom-")      + nametokens[1],        tokens[0], important);
+                       add_parsed_property(nametokens[0] + _t("-right-")       + nametokens[1],        tokens[1], important);
+                       add_parsed_property(nametokens[0] + _t("-left-")        + nametokens[1],        tokens[1], important);
+               } else if(tokens.size() == 1)
+               {
+                       add_parsed_property(nametokens[0] + _t("-top-")         + nametokens[1],        tokens[0], important);
+                       add_parsed_property(nametokens[0] + _t("-bottom-")      + nametokens[1],        tokens[0], important);
+                       add_parsed_property(nametokens[0] + _t("-right-")       + nametokens[1],        tokens[0], important);
+                       add_parsed_property(nametokens[0] + _t("-left-")        + nametokens[1],        tokens[0], important);
+               }
+       } else 
+               
+       // Parse font shorthand properties 
+       if(!t_strcmp(name, _t("font")))
+       {
+               parse_short_font(val, important);
+       } else 
+       {
+               add_parsed_property(name, val, important);
+       }
+}
+
+void litehtml::style::parse_short_border( const tstring& prefix, const tstring& val, bool important )
+{
+       string_vector tokens;
+       split_string(val, tokens, _t(" "), _t(""), _t("("));
+       if(tokens.size() >= 3)
+       {
+               add_parsed_property(prefix + _t("-width"),      tokens[0], important);
+               add_parsed_property(prefix + _t("-style"),      tokens[1], important);
+               add_parsed_property(prefix + _t("-color"),      tokens[2], important);
+       } else if(tokens.size() == 2)
+       {
+               if(iswdigit(tokens[0][0]) || value_index(val.c_str(), border_width_strings) >= 0)
+               {
+                       add_parsed_property(prefix + _t("-width"),      tokens[0], important);
+                       add_parsed_property(prefix + _t("-style"),      tokens[1], important);
+               } else
+               {
+                       add_parsed_property(prefix + _t("-style"),      tokens[0], important);
+                       add_parsed_property(prefix + _t("-color"),      tokens[1], important);
+               }
+       }
+}
+
+void litehtml::style::parse_short_background( const tstring& val, const tchar_t* baseurl, bool important )
+{
+       add_parsed_property(_t("background-color"),                     _t("transparent"),      important);
+       add_parsed_property(_t("background-image"),                     _t(""),                         important);
+       add_parsed_property(_t("background-image-baseurl"), _t(""),                             important);
+       add_parsed_property(_t("background-repeat"),            _t("repeat"),           important);
+       add_parsed_property(_t("background-origin"),            _t("padding-box"),      important);
+       add_parsed_property(_t("background-clip"),                      _t("border-box"),       important);
+       add_parsed_property(_t("background-attachment"),        _t("scroll"),           important);
+
+       if(val == _t("none"))
+       {
+               return;
+       }
+
+       string_vector tokens;
+       split_string(val, tokens, _t(" "), _t(""), _t("("));
+       bool origin_found = false;
+       for(string_vector::iterator tok = tokens.begin(); tok != tokens.end(); tok++)
+       {
+               if(tok->substr(0, 3) == _t("url"))
+               {
+                       add_parsed_property(_t("background-image"), *tok, important);
+                       if(baseurl)
+                       {
+                               add_parsed_property(_t("background-image-baseurl"), baseurl, important);
+                       }
+
+               } else if( value_in_list(tok->c_str(), background_repeat_strings) )
+               {
+                       add_parsed_property(_t("background-repeat"), *tok, important);
+               } else if( value_in_list(tok->c_str(), background_attachment_strings) )
+               {
+                       add_parsed_property(_t("background-attachment"), *tok, important);
+               } else if( value_in_list(tok->c_str(), background_box_strings) )
+               {
+                       if(!origin_found)
+                       {
+                               add_parsed_property(_t("background-origin"), *tok, important);
+                               origin_found = true;
+                       } else
+                       {
+                               add_parsed_property(_t("background-clip"),*tok, important);
+                       }
+               } else if(      value_in_list(tok->c_str(), _t("left;right;top;bottom;center")) ||
+                                       iswdigit((*tok)[0]) ||
+                                       (*tok)[0] == _t('-')    ||
+                                       (*tok)[0] == _t('.')    ||
+                                       (*tok)[0] == _t('+'))
+               {
+                       if(m_properties.find(_t("background-position")) != m_properties.end())
+                       {
+                               m_properties[_t("background-position")].m_value = m_properties[_t("background-position")].m_value + _t(" ") + *tok;
+                       } else
+                       {
+                               add_parsed_property(_t("background-position"), *tok, important);
+                       }
+               } else if (web_color::is_color(tok->c_str()))
+               {
+                       add_parsed_property(_t("background-color"), *tok, important);
+               }
+       }
+}
+
+void litehtml::style::parse_short_font( const tstring& val, bool important )
+{
+       add_parsed_property(_t("font-style"),   _t("normal"),   important);
+       add_parsed_property(_t("font-variant"), _t("normal"),   important);
+       add_parsed_property(_t("font-weight"),  _t("normal"),   important);
+       add_parsed_property(_t("font-size"),            _t("medium"),   important);
+       add_parsed_property(_t("line-height"),  _t("normal"),   important);
+
+       string_vector tokens;
+       split_string(val, tokens, _t(" "), _t(""), _t("\""));
+
+       int idx = 0;
+       bool was_normal = false;
+       bool is_family = false;
+       tstring font_family;
+       for(string_vector::iterator tok = tokens.begin(); tok != tokens.end(); tok++)
+       {
+               idx = value_index(tok->c_str(), font_style_strings);
+               if(!is_family)
+               {
+                       if(idx >= 0)
+                       {
+                               if(idx == 0 && !was_normal)
+                               {
+                                       add_parsed_property(_t("font-weight"),          *tok, important);
+                                       add_parsed_property(_t("font-variant"),         *tok, important);
+                                       add_parsed_property(_t("font-style"),           *tok, important);
+                               } else
+                               {
+                                       add_parsed_property(_t("font-style"),           *tok, important);
+                               }
+                       } else
+                       {
+                               if(value_in_list(tok->c_str(), font_weight_strings))
+                               {
+                                       add_parsed_property(_t("font-weight"),          *tok, important);
+                               } else
+                               {
+                                       if(value_in_list(tok->c_str(), font_variant_strings))
+                                       {
+                                               add_parsed_property(_t("font-variant"), *tok, important);
+                                       } else if( iswdigit((*tok)[0]) )
+                                       {
+                                               string_vector szlh;
+                                               split_string(*tok, szlh, _t("/"));
+
+                                               if(szlh.size() == 1)
+                                               {
+                                                       add_parsed_property(_t("font-size"),    szlh[0], important);
+                                               } else  if(szlh.size() >= 2)
+                                               {
+                                                       add_parsed_property(_t("font-size"),    szlh[0], important);
+                                                       add_parsed_property(_t("line-height"),  szlh[1], important);
+                                               }
+                                       } else
+                                       {
+                                               is_family = true;
+                                               font_family += *tok;
+                                       }
+                               }
+                       }
+               } else
+               {
+                       font_family += *tok;
+               }
+       }
+       add_parsed_property(_t("font-family"), font_family, important);
+}
+
+void litehtml::style::add_parsed_property( const tstring& name, const tstring& val, bool important )
+{
+       bool is_valid = true;
+       string_map::iterator vals = m_valid_values.find(name);
+       if (vals != m_valid_values.end())
+       {
+               if (!value_in_list(val, vals->second))
+               {
+                       is_valid = false;
+               }
+       }
+
+       if (is_valid)
+       {
+               props_map::iterator prop = m_properties.find(name);
+               if (prop != m_properties.end())
+               {
+                       if (!prop->second.m_important || (important && prop->second.m_important))
+                       {
+                               prop->second.m_value = val;
+                               prop->second.m_important = important;
+                       }
+               }
+               else
+               {
+                       m_properties[name] = property_value(val.c_str(), important);
+               }
+       }
+}
+
+void litehtml::style::remove_property( const tstring& name, bool important )
+{
+       props_map::iterator prop = m_properties.find(name);
+       if(prop != m_properties.end())
+       {
+               if( !prop->second.m_important || (important && prop->second.m_important) )
+               {
+                       m_properties.erase(prop);
+               }
+       }
+}