]> git.saurik.com Git - wxWidgets.git/blobdiff - src/html/htmlpars.cpp
Add ClearSelection for msw ie and gtk webkit, with a stub for osx webkit. Document...
[wxWidgets.git] / src / html / htmlpars.cpp
index 01e1b306719810dc819060174f26211d51dc7de1..ed99a443b69d5f3b89858becad6c98ec097890f5 100644 (file)
@@ -38,7 +38,7 @@
 // DLL options compatibility check:
 WX_CHECK_BUILD_OPTIONS("wxHTML")
 
-const wxChar *wxTRACE_HTML_DEBUG = _T("htmldebug");
+const wxChar *wxTRACE_HTML_DEBUG = wxT("htmldebug");
 
 //-----------------------------------------------------------------------------
 // wxHtmlParser helpers
@@ -77,8 +77,8 @@ public:
 IMPLEMENT_ABSTRACT_CLASS(wxHtmlParser,wxObject)
 
 wxHtmlParser::wxHtmlParser()
-    : wxObject(), m_HandlersHash(wxKEY_STRING),
-      m_FS(NULL), m_HandlersStack(NULL)
+    : wxObject(),
+      m_FS(NULL)
 {
     m_Source = NULL;
     m_entitiesParser = new wxHtmlEntitiesParser;
@@ -94,17 +94,8 @@ wxHtmlParser::~wxHtmlParser()
     while (RestoreState()) {}
     DestroyDOMTree();
 
-    if (m_HandlersStack)
-    {
-        wxList& tmp = *m_HandlersStack;
-        wxList::iterator it, en;
-        for( it = tmp.begin(), en = tmp.end(); it != en; ++it )
-            delete (wxHashTable*)*it;
-        tmp.clear();
-    }
-    delete m_HandlersStack;
-    m_HandlersHash.Clear();
-    WX_CLEAR_LIST(wxList, m_HandlersList);
+    WX_CLEAR_ARRAY(m_HandlersStack);
+    WX_CLEAR_HASH_SET(wxHtmlTagHandlersSet, m_HandlersSet);
     delete m_entitiesParser;
     delete m_Source;
 }
@@ -132,8 +123,13 @@ void wxHtmlParser::DoneParser()
 void wxHtmlParser::SetSource(const wxString& src)
 {
     DestroyDOMTree();
-    // NB: this is allocated on heap because wxHtmlTag keeps a pointer to
-    //     this string if WXWIN_COMPATIBILITY_2_8
+    // NB: This is allocated on heap because wxHtmlTag uses iterators and
+    //     making a copy of m_Source string in SetSourceAndSaveState() and
+    //     RestoreState() would invalidate them (because wxString::m_impl's
+    //     memory would change completely twice and iterators use pointers
+    //     into it). So instead, we keep the string object intact and only
+    //     store/restore pointer to it, for which we need it to be allocated
+    //     on the heap.
     delete m_Source;
     m_Source = new wxString(src);
     CreateDOMTree();
@@ -231,7 +227,7 @@ void wxHtmlParser::CreateDOMSubTree(wxHtmlTag *cur,
             else
             {
                 while (i < end_pos && *i != wxT('>')) ++i;
-                textBeginning = i+1;
+                textBeginning = i < end_pos ? i+1 : i;
             }
         }
         else ++i;
@@ -254,8 +250,7 @@ void wxHtmlParser::DestroyDOMTree()
     }
     m_Tags = m_CurTag = NULL;
 
-    delete m_TextPieces;
-    m_TextPieces = NULL;
+    wxDELETE(m_TextPieces);
 }
 
 void wxHtmlParser::DoParsing()
@@ -313,13 +308,12 @@ void wxHtmlParser::DoParsing(const wxString::const_iterator& begin_pos_,
 
 void wxHtmlParser::AddTag(const wxHtmlTag& tag)
 {
-    wxHtmlTagHandler *h;
     bool inner = false;
 
-    h = (wxHtmlTagHandler*) m_HandlersHash.Get(tag.GetName());
-    if (h)
+    wxHtmlTagHandlersHash::const_iterator h = m_HandlersHash.find(tag.GetName());
+    if (h != m_HandlersHash.end())
     {
-        inner = h->HandleTag(tag);
+        inner = h->second->HandleTag(tag);
         if (m_stopParsing)
             return;
     }
@@ -336,10 +330,9 @@ void wxHtmlParser::AddTagHandler(wxHtmlTagHandler *handler)
     wxStringTokenizer tokenizer(s, wxT(", "));
 
     while (tokenizer.HasMoreTokens())
-        m_HandlersHash.Put(tokenizer.GetNextToken(), handler);
+        m_HandlersHash[tokenizer.GetNextToken()] = handler;
 
-    if (m_HandlersList.IndexOf(handler) == wxNOT_FOUND)
-        m_HandlersList.Append(handler);
+    m_HandlersSet.insert(handler);
 
     handler->SetParser(this);
 }
@@ -349,39 +342,24 @@ void wxHtmlParser::PushTagHandler(wxHtmlTagHandler *handler, const wxString& tag
     wxStringTokenizer tokenizer(tags, wxT(", "));
     wxString key;
 
-    if (m_HandlersStack == NULL)
-    {
-        m_HandlersStack = new wxList;
-    }
-
-    m_HandlersStack->Insert((wxObject*)new wxHashTable(m_HandlersHash));
+    m_HandlersStack.push_back(new wxHtmlTagHandlersHash(m_HandlersHash));
 
     while (tokenizer.HasMoreTokens())
     {
         key = tokenizer.GetNextToken();
-        m_HandlersHash.Delete(key);
-        m_HandlersHash.Put(key, handler);
+        m_HandlersHash[key] = handler;
     }
 }
 
 void wxHtmlParser::PopTagHandler()
 {
-    wxList::compatibility_iterator first;
+    wxCHECK_RET( !m_HandlersStack.empty(),
+                 "attempt to remove HTML tag handler from empty stack" );
 
-    if ( !m_HandlersStack ||
-#if wxUSE_STL
-         !(first = m_HandlersStack->GetFirst())
-#else // !wxUSE_STL
-         ((first = m_HandlersStack->GetFirst()) == NULL)
-#endif // wxUSE_STL/!wxUSE_STL
-        )
-    {
-        wxLogWarning(_("Warning: attempt to remove HTML tag handler from empty stack."));
-        return;
-    }
-    m_HandlersHash = *((wxHashTable*) first->GetData());
-    delete (wxHashTable*) first->GetData();
-    m_HandlersStack->Erase(first);
+    wxHtmlTagHandlersHash *prev = m_HandlersStack.back();
+    m_HandlersStack.pop_back();
+    m_HandlersHash = *prev;
+    delete prev;
 }
 
 void wxHtmlParser::SetSourceAndSaveState(const wxString& src)
@@ -411,6 +389,7 @@ bool wxHtmlParser::RestoreState()
     if (!m_SavedStates) return false;
 
     DestroyDOMTree();
+    delete m_Source;
 
     wxHtmlParserState *s = m_SavedStates;
     m_SavedStates = s->m_nextState;
@@ -453,7 +432,7 @@ void wxHtmlTagHandler::ParseInnerSource(const wxString& source)
 IMPLEMENT_DYNAMIC_CLASS(wxHtmlEntitiesParser,wxObject)
 
 wxHtmlEntitiesParser::wxHtmlEntitiesParser()
-#if wxUSE_WCHAR_T && !wxUSE_UNICODE
+#if !wxUSE_UNICODE
     : m_conv(NULL), m_encoding(wxFONTENCODING_SYSTEM)
 #endif
 {
@@ -461,14 +440,14 @@ wxHtmlEntitiesParser::wxHtmlEntitiesParser()
 
 wxHtmlEntitiesParser::~wxHtmlEntitiesParser()
 {
-#if wxUSE_WCHAR_T && !wxUSE_UNICODE
+#if !wxUSE_UNICODE
     delete m_conv;
 #endif
 }
 
+#if !wxUSE_UNICODE
 void wxHtmlEntitiesParser::SetEncoding(wxFontEncoding encoding)
 {
-#if wxUSE_WCHAR_T && !wxUSE_UNICODE
     if (encoding == m_encoding)
         return;
 
@@ -479,10 +458,8 @@ void wxHtmlEntitiesParser::SetEncoding(wxFontEncoding encoding)
         m_conv = NULL;
     else
         m_conv = new wxCSConv(wxFontMapper::GetEncodingName(m_encoding));
-#else
-    (void) encoding;
-#endif
 }
+#endif // !wxUSE_UNICODE
 
 wxString wxHtmlEntitiesParser::Parse(const wxString& input) const
 {
@@ -543,7 +520,6 @@ wxString wxHtmlEntitiesParser::Parse(const wxString& input) const
 #if !wxUSE_UNICODE
 wxChar wxHtmlEntitiesParser::GetCharForCode(unsigned code) const
 {
-#if wxUSE_WCHAR_T
     char buf[2];
     wchar_t wbuf[2];
     wbuf[0] = (wchar_t)code;
@@ -552,9 +528,6 @@ wxChar wxHtmlEntitiesParser::GetCharForCode(unsigned code) const
     if (conv->WC2MB(buf, wbuf, 2) == (size_t)-1)
         return '?';
     return buf[0];
-#else
-    return (code < 256) ? (wxChar)code : '?';
-#endif
 }
 #endif
 
@@ -577,6 +550,9 @@ wxChar wxHtmlEntitiesParser::GetEntityChar(const wxString& entity) const
 {
     unsigned code = 0;
 
+    if (entity.empty())
+      return 0; // invalid entity reference
+
     if (entity[0] == wxT('#'))
     {
         // NB: parsed value is a number, so it's OK to use wx_str(), internal
@@ -584,13 +560,13 @@ wxChar wxHtmlEntitiesParser::GetEntityChar(const wxString& entity) const
         const wxStringCharType *ent_s = entity.wx_str();
         const wxStringCharType *format;
 
-        if (ent_s[1] == wxSTRING_TEXT('x') || ent_s[1] == wxSTRING_TEXT('X'))
+        if (ent_s[1] == wxS('x') || ent_s[1] == wxS('X'))
         {
-            format = wxSTRING_TEXT("%x");
+            format = wxS("%x");
             ent_s++;
         }
         else
-            format = wxSTRING_TEXT("%u");
+            format = wxS("%u");
         ent_s++;
 
         if (wxSscanf(ent_s, format, &code) != 1)
@@ -600,7 +576,7 @@ wxChar wxHtmlEntitiesParser::GetEntityChar(const wxString& entity) const
     {
         // store the literals in wx's internal representation (either char*
         // in UTF-8 or wchar_t*) for best performance:
-        #define ENTITY(name, code) { wxSTRING_TEXT(name), code }
+        #define ENTITY(name, code) { wxS(name), code }
 
         static wxHtmlEntityInfo substitutions[] = {
             ENTITY("AElig", 198),
@@ -672,6 +648,7 @@ wxChar wxHtmlEntitiesParser::GetEntityChar(const wxString& entity) const
             ENTITY("amp", 38),
             ENTITY("and", 8743),
             ENTITY("ang", 8736),
+            ENTITY("apos", 39),
             ENTITY("aring", 229),
             ENTITY("asymp", 8776),
             ENTITY("atilde", 227),
@@ -863,9 +840,10 @@ wxChar wxHtmlEntitiesParser::GetEntityChar(const wxString& entity) const
             while (substitutions[substitutions_cnt].code != 0)
                 substitutions_cnt++;
 
-        wxHtmlEntityInfo *info = NULL;
+        wxHtmlEntityInfo *info;
 #ifdef __WXWINCE__
         // bsearch crashes under WinCE for some reason
+        info = NULL;
         size_t i;
         for (i = 0; i < substitutions_cnt; i++)
         {
@@ -891,10 +869,14 @@ wxChar wxHtmlEntitiesParser::GetEntityChar(const wxString& entity) const
         return GetCharForCode(code);
 }
 
-wxFSFile *wxHtmlParser::OpenURL(wxHtmlURLType WXUNUSED(type),
+wxFSFile *wxHtmlParser::OpenURL(wxHtmlURLType type,
                                 const wxString& url) const
 {
-    return m_FS ? m_FS->OpenFile(url) : NULL;
+    int flags = wxFS_READ;
+    if (type == wxHTML_URL_IMAGE)
+        flags |= wxFS_SEEKABLE;
+
+    return m_FS ? m_FS->OpenFile(url, flags) : NULL;
 
 }
 
@@ -913,7 +895,7 @@ public:
 protected:
     virtual void AddText(const wxString& WXUNUSED(txt)) {}
 
-    DECLARE_NO_COPY_CLASS(wxMetaTagParser)
+    wxDECLARE_NO_COPY_CLASS(wxMetaTagParser);
 };
 
 class wxMetaTagHandler : public wxHtmlTagHandler
@@ -926,23 +908,23 @@ public:
 private:
     wxString *m_retval;
 
-    DECLARE_NO_COPY_CLASS(wxMetaTagHandler)
+    wxDECLARE_NO_COPY_CLASS(wxMetaTagHandler);
 };
 
 bool wxMetaTagHandler::HandleTag(const wxHtmlTag& tag)
 {
-    if (tag.GetName() == _T("BODY"))
+    if (tag.GetName() == wxT("BODY"))
     {
         m_Parser->StopParsing();
         return false;
     }
 
-    if (tag.HasParam(_T("HTTP-EQUIV")) &&
-        tag.GetParam(_T("HTTP-EQUIV")).IsSameAs(_T("Content-Type"), false) &&
-        tag.HasParam(_T("CONTENT")))
+    if (tag.HasParam(wxT("HTTP-EQUIV")) &&
+        tag.GetParam(wxT("HTTP-EQUIV")).IsSameAs(wxT("Content-Type"), false) &&
+        tag.HasParam(wxT("CONTENT")))
     {
-        wxString content = tag.GetParam(_T("CONTENT")).Lower();
-        if (content.Left(19) == _T("text/html; charset="))
+        wxString content = tag.GetParam(wxT("CONTENT")).Lower();
+        if (content.Left(19) == wxT("text/html; charset="))
         {
             *m_retval = content.Mid(19);
             m_Parser->StopParsing();
@@ -971,12 +953,12 @@ bool
 wxHtmlParser::SkipCommentTag(wxString::const_iterator& start,
                              wxString::const_iterator end)
 {
-    wxASSERT_MSG( *start == '<', _T("should be called on the tag start") );
+    wxASSERT_MSG( *start == '<', wxT("should be called on the tag start") );
 
     wxString::const_iterator p = start;
 
     // comments begin with "<!--" in HTML 4.0
-    if ( p > end - 3 || *++p != '!' || *++p != '-' || *++p != '-' )
+    if ( end - start < 4 || *++p != '!' || *++p != '-' || *++p != '-' )
     {
         // not a comment at all
         return false;