Update current version of litehtml. Fix a crash when document contains no fonts
[claws.git] / src / plugins / litehtml_viewer / litehtml / stylesheet.cpp
index 7f0a2be1ace09524453b4aa5d40044e27cca37a4..08ace6205ee06100dc5344b348caf6ca2cbeaa9f 100644 (file)
-#include "html.h"\r
-#include "stylesheet.h"\r
-#include <algorithm>\r
-#include "document.h"\r
-\r
-\r
-void litehtml::css::parse_stylesheet(const tchar_t* str, const tchar_t* baseurl, const std::shared_ptr<document>& doc, const media_query_list::ptr& media)\r
-{\r
-       tstring text = str;\r
-\r
-       // remove comments\r
-       tstring::size_type c_start = text.find(_t("/*"));\r
-       while(c_start != tstring::npos)\r
-       {\r
-               tstring::size_type c_end = text.find(_t("*/"), c_start + 2);\r
-               text.erase(c_start, c_end - c_start + 2);\r
-               c_start = text.find(_t("/*"));\r
-       }\r
-\r
-       tstring::size_type pos = text.find_first_not_of(_t(" \n\r\t"));\r
-       while(pos != tstring::npos)\r
-       {\r
-               while(pos != tstring::npos && text[pos] == _t('@'))\r
-               {\r
-                       tstring::size_type sPos = pos;\r
-                       pos = text.find_first_of(_t("{"), pos);\r
-                       if(pos != tstring::npos && text[pos] == _t('{'))\r
-                       {\r
-                               pos = find_close_bracket(text, pos, _t('{'), _t('}'));\r
-                       }\r
-                       if(pos != tstring::npos)\r
-                       {\r
-                               parse_atrule(text.substr(sPos, pos - sPos + 1), baseurl, doc, media);\r
-                       } else\r
-                       {\r
-                               parse_atrule(text.substr(sPos), baseurl, doc, media);\r
-                       }\r
-\r
-                       if(pos != tstring::npos)\r
-                       {\r
-                               pos = text.find_first_not_of(_t(" \n\r\t"), pos + 1);\r
-                       }\r
-               }\r
-\r
-               if(pos == tstring::npos)\r
-               {\r
-                       break;\r
-               }\r
-\r
-               tstring::size_type style_start = text.find(_t("{"), pos);\r
-               tstring::size_type style_end    = text.find(_t("}"), pos);\r
-               if(style_start != tstring::npos && style_end != tstring::npos)\r
-               {\r
-                       style::ptr st = std::make_shared<style>();\r
-                       st->add(text.substr(style_start + 1, style_end - style_start - 1).c_str(), baseurl);\r
-\r
-                       parse_selectors(text.substr(pos, style_start - pos), st, media);\r
-\r
-                       if(media && doc)\r
-                       {\r
-                               doc->add_media_list(media);\r
-                       }\r
-\r
-                       pos = style_end + 1;\r
-               } else\r
-               {\r
-                       pos = tstring::npos;\r
-               }\r
-\r
-               if(pos != tstring::npos)\r
-               {\r
-                       pos = text.find_first_not_of(_t(" \n\r\t"), pos);\r
-               }\r
-       }\r
-}\r
-\r
-void litehtml::css::parse_css_url( const tstring& str, tstring& url )\r
-{\r
-       url = _t("");\r
-       size_t pos1 = str.find(_t('('));\r
-       size_t pos2 = str.find(_t(')'));\r
-       if(pos1 != tstring::npos && pos2 != tstring::npos)\r
-       {\r
-               url = str.substr(pos1 + 1, pos2 - pos1 - 1);\r
-               if(url.length())\r
-               {\r
-                       if(url[0] == _t('\'') || url[0] == _t('"'))\r
-                       {\r
-                               url.erase(0, 1);\r
-                       }\r
-               }\r
-               if(url.length())\r
-               {\r
-                       if(url[url.length() - 1] == _t('\'') || url[url.length() - 1] == _t('"'))\r
-                       {\r
-                               url.erase(url.length() - 1, 1);\r
-                       }\r
-               }\r
-       }\r
-}\r
-\r
-bool litehtml::css::parse_selectors( const tstring& txt, const litehtml::style::ptr& styles, const media_query_list::ptr& media )\r
-{\r
-       tstring selector = txt;\r
-       trim(selector);\r
-       string_vector tokens;\r
-       split_string(selector, tokens, _t(","));\r
-\r
-       bool added_something = false;\r
-\r
-       for(string_vector::iterator tok = tokens.begin(); tok != tokens.end(); tok++)\r
-       {\r
-               css_selector::ptr selector = std::make_shared<css_selector>(media);\r
-               selector->m_style = styles;\r
-               trim(*tok);\r
-               if(selector->parse(*tok))\r
-               {\r
-                       selector->calc_specificity();\r
-                       add_selector(selector);\r
-                       added_something = true;\r
-               }\r
-       }\r
-\r
-       return added_something;\r
-}\r
-\r
-void litehtml::css::sort_selectors()\r
-{\r
-       std::sort(m_selectors.begin(), m_selectors.end(),\r
-                [](const css_selector::ptr& v1, const css_selector::ptr& v2)\r
-                {\r
-                        return (*v1) < (*v2);\r
-                }\r
-       );\r
-}\r
-\r
-void litehtml::css::parse_atrule(const tstring& text, const tchar_t* baseurl, const std::shared_ptr<document>& doc, const media_query_list::ptr& media)\r
-{\r
-       if(text.substr(0, 7) == _t("@import"))\r
-       {\r
-               int sPos = 7;\r
-               tstring iStr;\r
-               iStr = text.substr(sPos);\r
-               if(iStr[iStr.length() - 1] == _t(';'))\r
-               {\r
-                       iStr.erase(iStr.length() - 1);\r
-               }\r
-               trim(iStr);\r
-               string_vector tokens;\r
-               split_string(iStr, tokens, _t(" "), _t(""), _t("(\""));\r
-               if(!tokens.empty())\r
-               {\r
-                       tstring url;\r
-                       parse_css_url(tokens.front(), url);\r
-                       if(url.empty())\r
-                       {\r
-                               url = tokens.front();\r
-                       }\r
-                       tokens.erase(tokens.begin());\r
-                       if(doc)\r
-                       {\r
-                               document_container* doc_cont = doc->container();\r
-                               if(doc_cont)\r
-                               {\r
-                                       tstring css_text;\r
-                                       tstring css_baseurl;\r
-                                       if(baseurl)\r
-                                       {\r
-                                               css_baseurl = baseurl;\r
-                                       }\r
-                                       doc_cont->import_css(css_text, url, css_baseurl);\r
-                                       if(!css_text.empty())\r
-                                       {\r
-                                               media_query_list::ptr new_media = media;\r
-                                               if(!tokens.empty())\r
-                                               {\r
-                                                       tstring media_str;\r
-                                                       for(string_vector::iterator iter = tokens.begin(); iter != tokens.end(); iter++)\r
-                                                       {\r
-                                                               if(iter != tokens.begin())\r
-                                                               {\r
-                                                                       media_str += _t(" ");\r
-                                                               }\r
-                                                               media_str += (*iter);\r
-                                                       }\r
-                                                       new_media = media_query_list::create_from_string(media_str, doc);\r
-                                                       if(!new_media)\r
-                                                       {\r
-                                                               new_media = media;\r
-                                                       }\r
-                                               }\r
-                                               parse_stylesheet(css_text.c_str(), css_baseurl.c_str(), doc, new_media);\r
-                                       }\r
-                               }\r
-                       }\r
-               }\r
-       } else if(text.substr(0, 6) == _t("@media"))\r
-       {\r
-               tstring::size_type b1 = text.find_first_of(_t('{'));\r
-               tstring::size_type b2 = text.find_last_of(_t('}'));\r
-               if(b1 != tstring::npos)\r
-               {\r
-                       tstring media_type = text.substr(6, b1 - 6);\r
-                       trim(media_type);\r
-                       media_query_list::ptr new_media = media_query_list::create_from_string(media_type, doc);\r
-\r
-                       tstring media_style;\r
-                       if(b2 != tstring::npos)\r
-                       {\r
-                               media_style = text.substr(b1 + 1, b2 - b1 - 1);\r
-                       } else\r
-                       {\r
-                               media_style = text.substr(b1 + 1);\r
-                       }\r
-\r
-                       parse_stylesheet(media_style.c_str(), baseurl, doc, new_media);\r
-               }\r
-       }\r
-}\r
+#include "html.h"
+#include "stylesheet.h"
+#include <algorithm>
+#include "document.h"
+
+
+void litehtml::css::parse_stylesheet(const tchar_t* str, const tchar_t* baseurl, const std::shared_ptr<document>& doc, const media_query_list::ptr& media)
+{
+       tstring text = str;
+
+       // remove comments
+       tstring::size_type c_start = text.find(_t("/*"));
+       while(c_start != tstring::npos)
+       {
+               tstring::size_type c_end = text.find(_t("*/"), c_start + 2);
+               text.erase(c_start, c_end - c_start + 2);
+               c_start = text.find(_t("/*"));
+       }
+
+       tstring::size_type pos = text.find_first_not_of(_t(" \n\r\t"));
+       while(pos != tstring::npos)
+       {
+               while(pos != tstring::npos && text[pos] == _t('@'))
+               {
+                       tstring::size_type sPos = pos;
+                       pos = text.find_first_of(_t("{;"), pos);
+                       if(pos != tstring::npos && text[pos] == _t('{'))
+                       {
+                               pos = find_close_bracket(text, pos, _t('{'), _t('}'));
+                       }
+                       if(pos != tstring::npos)
+                       {
+                               parse_atrule(text.substr(sPos, pos - sPos + 1), baseurl, doc, media);
+                       } else
+                       {
+                               parse_atrule(text.substr(sPos), baseurl, doc, media);
+                       }
+
+                       if(pos != tstring::npos)
+                       {
+                               pos = text.find_first_not_of(_t(" \n\r\t"), pos + 1);
+                       }
+               }
+
+               if(pos == tstring::npos)
+               {
+                       break;
+               }
+
+               tstring::size_type style_start = text.find(_t("{"), pos);
+               tstring::size_type style_end    = text.find(_t("}"), pos);
+               if(style_start != tstring::npos && style_end != tstring::npos)
+               {
+                       style::ptr st = std::make_shared<style>();
+                       st->add(text.substr(style_start + 1, style_end - style_start - 1).c_str(), baseurl);
+
+                       parse_selectors(text.substr(pos, style_start - pos), st, media);
+
+                       if(media && doc)
+                       {
+                               doc->add_media_list(media);
+                       }
+
+                       pos = style_end + 1;
+               } else
+               {
+                       pos = tstring::npos;
+               }
+
+               if(pos != tstring::npos)
+               {
+                       pos = text.find_first_not_of(_t(" \n\r\t"), pos);
+               }
+       }
+}
+
+void litehtml::css::parse_css_url( const tstring& str, tstring& url )
+{
+       url = _t("");
+       size_t pos1 = str.find(_t('('));
+       size_t pos2 = str.find(_t(')'));
+       if(pos1 != tstring::npos && pos2 != tstring::npos)
+       {
+               url = str.substr(pos1 + 1, pos2 - pos1 - 1);
+               if(url.length())
+               {
+                       if(url[0] == _t('\'') || url[0] == _t('"'))
+                       {
+                               url.erase(0, 1);
+                       }
+               }
+               if(url.length())
+               {
+                       if(url[url.length() - 1] == _t('\'') || url[url.length() - 1] == _t('"'))
+                       {
+                               url.erase(url.length() - 1, 1);
+                       }
+               }
+       }
+}
+
+bool litehtml::css::parse_selectors( const tstring& txt, const litehtml::style::ptr& styles, const media_query_list::ptr& media )
+{
+       tstring selector = txt;
+       trim(selector);
+       string_vector tokens;
+       split_string(selector, tokens, _t(","));
+
+       bool added_something = false;
+
+       for(string_vector::iterator tok = tokens.begin(); tok != tokens.end(); tok++)
+       {
+               css_selector::ptr selector = std::make_shared<css_selector>(media);
+               selector->m_style = styles;
+               trim(*tok);
+               if(selector->parse(*tok))
+               {
+                       selector->calc_specificity();
+                       add_selector(selector);
+                       added_something = true;
+               }
+       }
+
+       return added_something;
+}
+
+void litehtml::css::sort_selectors()
+{
+       std::sort(m_selectors.begin(), m_selectors.end(),
+                [](const css_selector::ptr& v1, const css_selector::ptr& v2)
+                {
+                        return (*v1) < (*v2);
+                }
+       );
+}
+
+void litehtml::css::parse_atrule(const tstring& text, const tchar_t* baseurl, const std::shared_ptr<document>& doc, const media_query_list::ptr& media)
+{
+       if(text.substr(0, 7) == _t("@import"))
+       {
+               int sPos = 7;
+               tstring iStr;
+               iStr = text.substr(sPos);
+               if(iStr[iStr.length() - 1] == _t(';'))
+               {
+                       iStr.erase(iStr.length() - 1);
+               }
+               trim(iStr);
+               string_vector tokens;
+               split_string(iStr, tokens, _t(" "), _t(""), _t("(\""));
+               if(!tokens.empty())
+               {
+                       tstring url;
+                       parse_css_url(tokens.front(), url);
+                       if(url.empty())
+                       {
+                               url = tokens.front();
+                       }
+                       tokens.erase(tokens.begin());
+                       if(doc)
+                       {
+                               document_container* doc_cont = doc->container();
+                               if(doc_cont)
+                               {
+                                       tstring css_text;
+                                       tstring css_baseurl;
+                                       if(baseurl)
+                                       {
+                                               css_baseurl = baseurl;
+                                       }
+                                       doc_cont->import_css(css_text, url, css_baseurl);
+                                       if(!css_text.empty())
+                                       {
+                                               media_query_list::ptr new_media = media;
+                                               if(!tokens.empty())
+                                               {
+                                                       tstring media_str;
+                                                       for(string_vector::iterator iter = tokens.begin(); iter != tokens.end(); iter++)
+                                                       {
+                                                               if(iter != tokens.begin())
+                                                               {
+                                                                       media_str += _t(" ");
+                                                               }
+                                                               media_str += (*iter);
+                                                       }
+                                                       new_media = media_query_list::create_from_string(media_str, doc);
+                                                       if(!new_media)
+                                                       {
+                                                               new_media = media;
+                                                       }
+                                               }
+                                               parse_stylesheet(css_text.c_str(), css_baseurl.c_str(), doc, new_media);
+                                       }
+                               }
+                       }
+               }
+       } else if(text.substr(0, 6) == _t("@media"))
+       {
+               tstring::size_type b1 = text.find_first_of(_t('{'));
+               tstring::size_type b2 = text.find_last_of(_t('}'));
+               if(b1 != tstring::npos)
+               {
+                       tstring media_type = text.substr(6, b1 - 6);
+                       trim(media_type);
+                       media_query_list::ptr new_media = media_query_list::create_from_string(media_type, doc);
+
+                       tstring media_style;
+                       if(b2 != tstring::npos)
+                       {
+                               media_style = text.substr(b1 + 1, b2 - b1 - 1);
+                       } else
+                       {
+                               media_style = text.substr(b1 + 1);
+                       }
+
+                       parse_stylesheet(media_style.c_str(), baseurl, doc, new_media);
+               }
+       }
+}