+
+
+
+
+
+
+
+//--------------------------------------------------------------------------------
+// wxHtmlSearchEngine
+//--------------------------------------------------------------------------------
+
+void wxHtmlSearchEngine::LookFor(const wxString& keyword, bool case_sensitive, bool whole_words_only)
+{
+    m_CaseSensitive = case_sensitive;
+    m_WholeWords = whole_words_only;
+    m_Keyword = keyword;
+
+    if (!m_CaseSensitive)
+        m_Keyword.LowerCase();
+}
+
+
+static inline bool WHITESPACE(wxChar c)
+{
+    return c == wxT(' ') || c == wxT('\n') || c == wxT('\r') || c == wxT('\t');
+}
+
+// replace continuous spaces by one single space
+static inline wxString CompressSpaces(const wxString & str)
+{
+    wxString buf;
+    buf.reserve( str.size() );
+
+    bool space_counted = false;
+    for( const wxChar * pstr = str.c_str(); *pstr; ++pstr )
+    {
+        wxChar ch = *pstr;
+        if( WHITESPACE( ch ) )
+        {
+            if( space_counted )
+            {
+                continue;
+            }
+            ch = wxT(' ');
+            space_counted = true;
+        }
+        else
+        {
+            space_counted = false;
+        }
+        buf += ch;
+    }
+
+    return buf;
+}
+
+bool wxHtmlSearchEngine::Scan(const wxFSFile& file)
+{
+    wxASSERT_MSG(!m_Keyword.empty(), wxT("wxHtmlSearchEngine::LookFor must be called before scanning!"));
+
+    wxHtmlFilterHTML filter;
+    wxString bufStr = filter.ReadFile(file);
+
+    if (!m_CaseSensitive)
+        bufStr.LowerCase();
+
+    {   // remove html tags
+        wxString bufStrCopy;
+        bufStrCopy.reserve( bufStr.size() );
+        bool insideTag = false;
+        for (const wxChar * pBufStr = bufStr.c_str(); *pBufStr; ++pBufStr)
+        {
+            wxChar c = *pBufStr;
+            if (insideTag)
+            {
+                if (c == wxT('>'))
+                {
+                    insideTag = false;
+                    // replace the tag by an empty space
+                    c = wxT(' ');
+                }
+                else
+                    continue;
+            }
+            else if (c == wxT('<'))
+            {
+                wxChar nextCh = *(pBufStr + 1);
+                if (nextCh == wxT('/') || !WHITESPACE(nextCh))
+                {
+                    insideTag = true;
+                    continue;
+                }
+            }
+            bufStrCopy += c;
+        }
+        bufStr.swap( bufStrCopy );
+    }
+
+    wxString keyword = m_Keyword;
+
+    if (m_WholeWords)
+    {
+        // insert ' ' at the beginning and at the end
+        keyword.insert( 0, wxT(" ") );
+        keyword.append( wxT(" ") );
+        bufStr.insert( 0, wxT(" ") );
+        bufStr.append( wxT(" ") );
+    }
+
+    // remove continuous spaces
+    keyword = CompressSpaces( keyword );
+    bufStr = CompressSpaces( bufStr );
+
+    // finally do the search
+    return bufStr.find( keyword ) != wxString::npos;
+}
+