+
+//-----------------------------------------------------------------------------
+// wxHtmlParser::ExtractCharsetInformation
+//-----------------------------------------------------------------------------
+
+class wxMetaTagParser : public wxHtmlParser
+{
+public:
+ wxMetaTagParser() { }
+
+ wxObject* GetProduct() { return NULL; }
+
+protected:
+ virtual void AddText(const wxString& WXUNUSED(txt)) {}
+
+ wxDECLARE_NO_COPY_CLASS(wxMetaTagParser);
+};
+
+class wxMetaTagHandler : public wxHtmlTagHandler
+{
+public:
+ wxMetaTagHandler(wxString *retval) : wxHtmlTagHandler(), m_retval(retval) {}
+ wxString GetSupportedTags() { return wxT("META,BODY"); }
+ bool HandleTag(const wxHtmlTag& tag);
+
+private:
+ wxString *m_retval;
+
+ wxDECLARE_NO_COPY_CLASS(wxMetaTagHandler);
+};
+
+bool wxMetaTagHandler::HandleTag(const wxHtmlTag& tag)
+{
+ if (tag.GetName() == wxT("BODY"))
+ {
+ m_Parser->StopParsing();
+ return false;
+ }
+
+ if (tag.HasParam(wxT("HTTP-EQUIV")) &&
+ tag.GetParam(wxT("HTTP-EQUIV")).IsSameAs(wxT("Content-Type"), false) &&
+ tag.HasParam(wxT("CONTENT")))
+ {
+ wxString content = tag.GetParam(wxT("CONTENT")).Lower();
+ if (content.Left(19) == wxT("text/html; charset="))
+ {
+ *m_retval = content.Mid(19);
+ m_Parser->StopParsing();
+ }
+ }
+ return false;
+}
+
+
+/*static*/
+wxString wxHtmlParser::ExtractCharsetInformation(const wxString& markup)
+{
+ wxString charset;
+ wxMetaTagParser *parser = new wxMetaTagParser();
+ if(parser)
+ {
+ parser->AddTagHandler(new wxMetaTagHandler(&charset));
+ parser->Parse(markup);
+ delete parser;
+ }
+ return charset;
+}
+
+/* static */
+bool
+wxHtmlParser::SkipCommentTag(wxString::const_iterator& start,
+ wxString::const_iterator end)
+{
+ wxASSERT_MSG( *start == '<', wxT("should be called on the tag start") );
+
+ wxString::const_iterator p = start;
+
+ // Comments begin with "<!--" in HTML 4.0; anything shorter or not containing
+ // these characters is not a comment and we're not going to skip it.
+ if ( ++p == end || *p != '!' )
+ return false;
+ if ( ++p == end || *p != '-' )
+ return false;
+ if ( ++p == end || *p != '-' )
+ return false;
+
+ // skip the start of the comment tag in any case, if we don't find the
+ // closing tag we should ignore broken markup
+ start = p;
+
+ // comments end with "--[ \t\r\n]*>", i.e. white space is allowed between
+ // comment delimiter and the closing tag character (section 3.2.4 of
+ // http://www.w3.org/TR/html401/)
+ int dashes = 0;
+ while ( ++p < end )
+ {
+ const wxChar c = *p;
+
+ if ( (c == wxT(' ') || c == wxT('\n') ||
+ c == wxT('\r') || c == wxT('\t')) && dashes >= 2 )
+ {
+ // ignore white space before potential tag end
+ continue;
+ }
+
+ if ( c == wxT('>') && dashes >= 2 )
+ {
+ // found end of comment
+ start = p;
+ break;
+ }
+
+ if ( c == wxT('-') )
+ dashes++;
+ else
+ dashes = 0;
+ }
+
+ return true;
+}
+
+#endif // wxUSE_HTML