-#include "html.h"\r
-#include "css_selector.h"\r
-#include "document.h"\r
-\r
-void litehtml::css_element_selector::parse( const tstring& txt )\r
-{\r
- tstring::size_type el_end = txt.find_first_of(_t(".#[:"));\r
- m_tag = txt.substr(0, el_end);\r
- litehtml::lcase(m_tag);\r
- while(el_end != tstring::npos)\r
- {\r
- if(txt[el_end] == _t('.'))\r
- {\r
- css_attribute_selector attribute;\r
-\r
- tstring::size_type pos = txt.find_first_of(_t(".#[:"), el_end + 1);\r
- attribute.val = txt.substr(el_end + 1, pos - el_end - 1);\r
- split_string( attribute.val, attribute.class_val, _t(" ") );\r
- attribute.condition = select_equal;\r
- attribute.attribute = _t("class");\r
- m_attrs.push_back(attribute);\r
- el_end = pos;\r
- } else if(txt[el_end] == _t(':'))\r
- {\r
- css_attribute_selector attribute;\r
-\r
- if(txt[el_end + 1] == _t(':'))\r
- {\r
- tstring::size_type pos = txt.find_first_of(_t(".#[:"), el_end + 2);\r
- attribute.val = txt.substr(el_end + 2, pos - el_end - 2);\r
- attribute.condition = select_pseudo_element;\r
- litehtml::lcase(attribute.val);\r
- attribute.attribute = _t("pseudo-el");\r
- m_attrs.push_back(attribute);\r
- el_end = pos;\r
- } else\r
- {\r
- tstring::size_type pos = txt.find_first_of(_t(".#[:("), el_end + 1);\r
- if(pos != tstring::npos && txt.at(pos) == _t('('))\r
- {\r
- pos = find_close_bracket(txt, pos);\r
- if(pos != tstring::npos)\r
- {\r
- pos++;\r
- } else\r
- {\r
- int iii = 0;\r
- iii++;\r
- }\r
- }\r
- if(pos != tstring::npos)\r
- {\r
- attribute.val = txt.substr(el_end + 1, pos - el_end - 1);\r
- } else\r
- {\r
- attribute.val = txt.substr(el_end + 1);\r
- }\r
- litehtml::lcase(attribute.val);\r
- if(attribute.val == _t("after") || attribute.val == _t("before"))\r
- {\r
- attribute.condition = select_pseudo_element;\r
- } else\r
- {\r
- attribute.condition = select_pseudo_class;\r
- }\r
- attribute.attribute = _t("pseudo");\r
- m_attrs.push_back(attribute);\r
- el_end = pos;\r
- }\r
- } else if(txt[el_end] == _t('#'))\r
- {\r
- css_attribute_selector attribute;\r
-\r
- tstring::size_type pos = txt.find_first_of(_t(".#[:"), el_end + 1);\r
- attribute.val = txt.substr(el_end + 1, pos - el_end - 1);\r
- attribute.condition = select_equal;\r
- attribute.attribute = _t("id");\r
- m_attrs.push_back(attribute);\r
- el_end = pos;\r
- } else if(txt[el_end] == _t('['))\r
- {\r
- css_attribute_selector attribute;\r
-\r
- tstring::size_type pos = txt.find_first_of(_t("]~=|$*^"), el_end + 1);\r
- tstring attr = txt.substr(el_end + 1, pos - el_end - 1);\r
- trim(attr);\r
- litehtml::lcase(attr);\r
- if(pos != tstring::npos)\r
- {\r
- if(txt[pos] == _t(']'))\r
- {\r
- attribute.condition = select_exists;\r
- } else if(txt[pos] == _t('='))\r
- {\r
- attribute.condition = select_equal;\r
- pos++;\r
- } else if(txt.substr(pos, 2) == _t("~="))\r
- {\r
- attribute.condition = select_contain_str;\r
- pos += 2;\r
- } else if(txt.substr(pos, 2) == _t("|="))\r
- {\r
- attribute.condition = select_start_str;\r
- pos += 2;\r
- } else if(txt.substr(pos, 2) == _t("^="))\r
- {\r
- attribute.condition = select_start_str;\r
- pos += 2;\r
- } else if(txt.substr(pos, 2) == _t("$="))\r
- {\r
- attribute.condition = select_end_str;\r
- pos += 2;\r
- } else if(txt.substr(pos, 2) == _t("*="))\r
- {\r
- attribute.condition = select_contain_str;\r
- pos += 2;\r
- } else\r
- {\r
- attribute.condition = select_exists;\r
- pos += 1;\r
- }\r
- pos = txt.find_first_not_of(_t(" \t"), pos);\r
- if(pos != tstring::npos)\r
- {\r
- if(txt[pos] == _t('"'))\r
- {\r
- tstring::size_type pos2 = txt.find_first_of(_t("\""), pos + 1);\r
- attribute.val = txt.substr(pos + 1, pos2 == tstring::npos ? pos2 : (pos2 - pos - 1));\r
- pos = pos2 == tstring::npos ? pos2 : (pos2 + 1);\r
- } else if(txt[pos] == _t(']'))\r
- {\r
- pos ++;\r
- } else\r
- {\r
- tstring::size_type pos2 = txt.find_first_of(_t("]"), pos + 1);\r
- attribute.val = txt.substr(pos, pos2 == tstring::npos ? pos2 : (pos2 - pos));\r
- trim(attribute.val);\r
- pos = pos2 == tstring::npos ? pos2 : (pos2 + 1);\r
- }\r
- }\r
- } else\r
- {\r
- attribute.condition = select_exists;\r
- }\r
- attribute.attribute = attr;\r
- m_attrs.push_back(attribute);\r
- el_end = pos;\r
- } else\r
- {\r
- el_end++;\r
- }\r
- el_end = txt.find_first_of(_t(".#[:"), el_end);\r
- }\r
-}\r
-\r
-\r
-bool litehtml::css_selector::parse( const tstring& text )\r
-{\r
- if(text.empty())\r
- {\r
- return false;\r
- }\r
- string_vector tokens;\r
- split_string(text, tokens, _t(""), _t(" \t>+~"), _t("(["));\r
-\r
- if(tokens.empty())\r
- {\r
- return false;\r
- }\r
-\r
- tstring left;\r
- tstring right = tokens.back();\r
- tchar_t combinator = 0;\r
-\r
- tokens.pop_back();\r
- while(!tokens.empty() && (tokens.back() == _t(" ") || tokens.back() == _t("\t") || tokens.back() == _t("+") || tokens.back() == _t("~") || tokens.back() == _t(">")))\r
- {\r
- if(combinator == _t(' ') || combinator == 0)\r
- {\r
- combinator = tokens.back()[0];\r
- }\r
- tokens.pop_back();\r
- }\r
-\r
- for(string_vector::const_iterator i = tokens.begin(); i != tokens.end(); i++)\r
- {\r
- left += *i;\r
- }\r
-\r
- trim(left);\r
- trim(right);\r
-\r
- if(right.empty())\r
- {\r
- return false;\r
- }\r
-\r
- m_right.parse(right);\r
-\r
- switch(combinator)\r
- {\r
- case _t('>'):\r
- m_combinator = combinator_child;\r
- break;\r
- case _t('+'):\r
- m_combinator = combinator_adjacent_sibling;\r
- break;\r
- case _t('~'):\r
- m_combinator = combinator_general_sibling;\r
- break;\r
- default:\r
- m_combinator = combinator_descendant;\r
- break;\r
- }\r
-\r
- m_left = 0;\r
-\r
- if(!left.empty())\r
- {\r
- m_left = std::make_shared<css_selector>(media_query_list::ptr(0));\r
- if(!m_left->parse(left))\r
- {\r
- return false;\r
- }\r
- }\r
-\r
- return true;\r
-}\r
-\r
-void litehtml::css_selector::calc_specificity()\r
-{\r
- if(!m_right.m_tag.empty() && m_right.m_tag != _t("*"))\r
- {\r
- m_specificity.d = 1;\r
- }\r
- for(css_attribute_selector::vector::iterator i = m_right.m_attrs.begin(); i != m_right.m_attrs.end(); i++)\r
- {\r
- if(i->attribute == _t("id"))\r
- {\r
- m_specificity.b++;\r
- } else\r
- {\r
- if(i->attribute == _t("class"))\r
- {\r
- m_specificity.c += (int) i->class_val.size();\r
- } else\r
- {\r
- m_specificity.c++;\r
- }\r
- } \r
- }\r
- if(m_left)\r
- {\r
- m_left->calc_specificity();\r
- m_specificity += m_left->m_specificity;\r
- }\r
-}\r
-\r
-void litehtml::css_selector::add_media_to_doc( document* doc ) const\r
-{\r
- if(m_media_query && doc)\r
- {\r
- doc->add_media_list(m_media_query);\r
- }\r
-}\r
-\r
+#include "html.h"
+#include "css_selector.h"
+#include "document.h"
+
+void litehtml::css_element_selector::parse( const tstring& txt )
+{
+ tstring::size_type el_end = txt.find_first_of(_t(".#[:"));
+ m_tag = txt.substr(0, el_end);
+ litehtml::lcase(m_tag);
+ while(el_end != tstring::npos)
+ {
+ if(txt[el_end] == _t('.'))
+ {
+ css_attribute_selector attribute;
+
+ tstring::size_type pos = txt.find_first_of(_t(".#[:"), el_end + 1);
+ attribute.val = txt.substr(el_end + 1, pos - el_end - 1);
+ split_string( attribute.val, attribute.class_val, _t(" ") );
+ attribute.condition = select_equal;
+ attribute.attribute = _t("class");
+ m_attrs.push_back(attribute);
+ el_end = pos;
+ } else if(txt[el_end] == _t(':'))
+ {
+ css_attribute_selector attribute;
+
+ if(txt[el_end + 1] == _t(':'))
+ {
+ tstring::size_type pos = txt.find_first_of(_t(".#[:"), el_end + 2);
+ attribute.val = txt.substr(el_end + 2, pos - el_end - 2);
+ attribute.condition = select_pseudo_element;
+ litehtml::lcase(attribute.val);
+ attribute.attribute = _t("pseudo-el");
+ m_attrs.push_back(attribute);
+ el_end = pos;
+ } else
+ {
+ tstring::size_type pos = txt.find_first_of(_t(".#[:("), el_end + 1);
+ if(pos != tstring::npos && txt.at(pos) == _t('('))
+ {
+ pos = find_close_bracket(txt, pos);
+ if(pos != tstring::npos)
+ {
+ pos++;
+ } else
+ {
+ int iii = 0;
+ iii++;
+ }
+ }
+ if(pos != tstring::npos)
+ {
+ attribute.val = txt.substr(el_end + 1, pos - el_end - 1);
+ } else
+ {
+ attribute.val = txt.substr(el_end + 1);
+ }
+ litehtml::lcase(attribute.val);
+ if(attribute.val == _t("after") || attribute.val == _t("before"))
+ {
+ attribute.condition = select_pseudo_element;
+ } else
+ {
+ attribute.condition = select_pseudo_class;
+ }
+ attribute.attribute = _t("pseudo");
+ m_attrs.push_back(attribute);
+ el_end = pos;
+ }
+ } else if(txt[el_end] == _t('#'))
+ {
+ css_attribute_selector attribute;
+
+ tstring::size_type pos = txt.find_first_of(_t(".#[:"), el_end + 1);
+ attribute.val = txt.substr(el_end + 1, pos - el_end - 1);
+ attribute.condition = select_equal;
+ attribute.attribute = _t("id");
+ m_attrs.push_back(attribute);
+ el_end = pos;
+ } else if(txt[el_end] == _t('['))
+ {
+ css_attribute_selector attribute;
+
+ tstring::size_type pos = txt.find_first_of(_t("]~=|$*^"), el_end + 1);
+ tstring attr = txt.substr(el_end + 1, pos - el_end - 1);
+ trim(attr);
+ litehtml::lcase(attr);
+ if(pos != tstring::npos)
+ {
+ if(txt[pos] == _t(']'))
+ {
+ attribute.condition = select_exists;
+ } else if(txt[pos] == _t('='))
+ {
+ attribute.condition = select_equal;
+ pos++;
+ } else if(txt.substr(pos, 2) == _t("~="))
+ {
+ attribute.condition = select_contain_str;
+ pos += 2;
+ } else if(txt.substr(pos, 2) == _t("|="))
+ {
+ attribute.condition = select_start_str;
+ pos += 2;
+ } else if(txt.substr(pos, 2) == _t("^="))
+ {
+ attribute.condition = select_start_str;
+ pos += 2;
+ } else if(txt.substr(pos, 2) == _t("$="))
+ {
+ attribute.condition = select_end_str;
+ pos += 2;
+ } else if(txt.substr(pos, 2) == _t("*="))
+ {
+ attribute.condition = select_contain_str;
+ pos += 2;
+ } else
+ {
+ attribute.condition = select_exists;
+ pos += 1;
+ }
+ pos = txt.find_first_not_of(_t(" \t"), pos);
+ if(pos != tstring::npos)
+ {
+ if(txt[pos] == _t('"'))
+ {
+ tstring::size_type pos2 = txt.find_first_of(_t("\""), pos + 1);
+ attribute.val = txt.substr(pos + 1, pos2 == tstring::npos ? pos2 : (pos2 - pos - 1));
+ pos = pos2 == tstring::npos ? pos2 : (pos2 + 1);
+ } else if(txt[pos] == _t(']'))
+ {
+ pos ++;
+ } else
+ {
+ tstring::size_type pos2 = txt.find_first_of(_t("]"), pos + 1);
+ attribute.val = txt.substr(pos, pos2 == tstring::npos ? pos2 : (pos2 - pos));
+ trim(attribute.val);
+ pos = pos2 == tstring::npos ? pos2 : (pos2 + 1);
+ }
+ }
+ } else
+ {
+ attribute.condition = select_exists;
+ }
+ attribute.attribute = attr;
+ m_attrs.push_back(attribute);
+ el_end = pos;
+ } else
+ {
+ el_end++;
+ }
+ el_end = txt.find_first_of(_t(".#[:"), el_end);
+ }
+}
+
+
+bool litehtml::css_selector::parse( const tstring& text )
+{
+ if(text.empty())
+ {
+ return false;
+ }
+ string_vector tokens;
+ split_string(text, tokens, _t(""), _t(" \t>+~"), _t("(["));
+
+ if(tokens.empty())
+ {
+ return false;
+ }
+
+ tstring left;
+ tstring right = tokens.back();
+ tchar_t combinator = 0;
+
+ tokens.pop_back();
+ while(!tokens.empty() && (tokens.back() == _t(" ") || tokens.back() == _t("\t") || tokens.back() == _t("+") || tokens.back() == _t("~") || tokens.back() == _t(">")))
+ {
+ if(combinator == _t(' ') || combinator == 0)
+ {
+ combinator = tokens.back()[0];
+ }
+ tokens.pop_back();
+ }
+
+ for(string_vector::const_iterator i = tokens.begin(); i != tokens.end(); i++)
+ {
+ left += *i;
+ }
+
+ trim(left);
+ trim(right);
+
+ if(right.empty())
+ {
+ return false;
+ }
+
+ m_right.parse(right);
+
+ switch(combinator)
+ {
+ case _t('>'):
+ m_combinator = combinator_child;
+ break;
+ case _t('+'):
+ m_combinator = combinator_adjacent_sibling;
+ break;
+ case _t('~'):
+ m_combinator = combinator_general_sibling;
+ break;
+ default:
+ m_combinator = combinator_descendant;
+ break;
+ }
+
+ m_left = 0;
+
+ if(!left.empty())
+ {
+ m_left = std::make_shared<css_selector>(media_query_list::ptr(0));
+ if(!m_left->parse(left))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void litehtml::css_selector::calc_specificity()
+{
+ if(!m_right.m_tag.empty() && m_right.m_tag != _t("*"))
+ {
+ m_specificity.d = 1;
+ }
+ for(css_attribute_selector::vector::iterator i = m_right.m_attrs.begin(); i != m_right.m_attrs.end(); i++)
+ {
+ if(i->attribute == _t("id"))
+ {
+ m_specificity.b++;
+ } else
+ {
+ if(i->attribute == _t("class"))
+ {
+ m_specificity.c += (int) i->class_val.size();
+ } else
+ {
+ m_specificity.c++;
+ }
+ }
+ }
+ if(m_left)
+ {
+ m_left->calc_specificity();
+ m_specificity += m_left->m_specificity;
+ }
+}
+
+void litehtml::css_selector::add_media_to_doc( document* doc ) const
+{
+ if(m_media_query && doc)
+ {
+ doc->add_media_list(m_media_query);
+ }
+}
+