1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxHtmlHelpData
4 // Notes: Based on htmlhelp.cpp, implementing a monolithic
5 // HTML Help controller class, by Vaclav Slavik
6 // Author: Harm van der Heijden and Vaclav Slavik
8 // Copyright: (c) Harm van der Heijden and Vaclav Slavik
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
13 #pragma implementation "helpdata.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
25 #if wxUSE_HTML && wxUSE_STREAMS
34 #include "wx/html/helpdata.h"
35 #include "wx/tokenzr.h"
36 #include "wx/wfstream.h"
37 #include "wx/busyinfo.h"
38 #include "wx/encconv.h"
39 #include "wx/fontmap.h"
41 #include "wx/html/htmlpars.h"
42 #include "wx/html/htmldefs.h"
43 #include "wx/html/htmlfilt.h"
44 #include "wx/filename.h"
46 #include "wx/arrimpl.cpp"
47 WX_DEFINE_OBJARRAY(wxHtmlBookRecArray
)
49 //-----------------------------------------------------------------------------
50 // static helper functions
51 //-----------------------------------------------------------------------------
53 // Reads one line, stores it into buf and returns pointer to new line or NULL.
54 static const wxChar
* ReadLine(const wxChar
*line
, wxChar
*buf
, size_t bufsize
)
56 wxChar
*writeptr
= buf
;
57 wxChar
*endptr
= buf
+ bufsize
- 1;
58 const wxChar
*readptr
= line
;
60 while (*readptr
!= 0 && *readptr
!= _T('\r') && *readptr
!= _T('\n') &&
62 *(writeptr
++) = *(readptr
++);
64 while (*readptr
== _T('\r') || *readptr
== _T('\n'))
74 extern "C" int LINKAGEMODE
75 wxHtmlHelpIndexCompareFunc(const void *a
, const void *b
)
77 return ((wxHtmlContentsItem
*)a
)->m_Name
.CmpNoCase(((wxHtmlContentsItem
*)b
)->m_Name
);
82 static T
* ReallocArray(T
*arr
, size_t oldsize
, size_t newsize
)
84 T
*newarr
= new T
[newsize
];
85 for (size_t i
= 0; i
< oldsize
; i
++)
91 //-----------------------------------------------------------------------------
93 //-----------------------------------------------------------------------------
95 class HP_Parser
: public wxHtmlParser
100 wxObject
* GetProduct() { return NULL
; }
103 virtual void AddText(const wxChar
* WXUNUSED(txt
)) {}
105 DECLARE_NO_COPY_CLASS(HP_Parser
)
109 //-----------------------------------------------------------------------------
111 //-----------------------------------------------------------------------------
113 class HP_TagHandler
: public wxHtmlTagHandler
116 wxString m_Name
, m_Page
;
120 wxHtmlContentsItem
*m_Items
;
122 wxHtmlBookRecord
*m_Book
;
125 HP_TagHandler(wxHtmlBookRecord
*b
) : wxHtmlTagHandler()
126 { m_Book
= b
; m_Items
= NULL
; m_ItemsCnt
= 0; m_Name
= m_Page
= wxEmptyString
;
127 m_Level
= 0; m_ID
= -1; }
128 wxString
GetSupportedTags() { return wxT("UL,OBJECT,PARAM"); }
129 bool HandleTag(const wxHtmlTag
& tag
);
130 void WriteOut(wxHtmlContentsItem
*& array
, int& size
);
131 void ReadIn(wxHtmlContentsItem
* array
, int size
);
133 DECLARE_NO_COPY_CLASS(HP_TagHandler
)
137 bool HP_TagHandler::HandleTag(const wxHtmlTag
& tag
)
139 if (tag
.GetName() == wxT("UL"))
146 else if (tag
.GetName() == wxT("OBJECT"))
148 m_Name
= m_Page
= wxEmptyString
;
152 if (!m_Page
.IsEmpty())
153 /* Valid HHW's file may contain only two object tags:
155 <OBJECT type="text/site properties">
156 <param name="ImageType" value="Folder">
161 <OBJECT type="text/sitemap">
162 <param name="Name" value="main page">
163 <param name="Local" value="another.htm">
166 We're interested in the latter. !m_Page.IsEmpty() is valid
167 condition because text/site properties does not contain Local param
170 if (tag
.GetParam(wxT("TYPE")) == wxT("text/sitemap"))
172 if (m_ItemsCnt
% wxHTML_REALLOC_STEP
== 0)
173 m_Items
= ReallocArray(m_Items
, m_ItemsCnt
,
174 m_ItemsCnt
+ wxHTML_REALLOC_STEP
);
176 m_Items
[m_ItemsCnt
].m_Level
= m_Level
;
177 m_Items
[m_ItemsCnt
].m_ID
= m_ID
;
178 m_Items
[m_ItemsCnt
].m_Page
= m_Page
;
179 m_Items
[m_ItemsCnt
].m_Name
= m_Name
;
180 m_Items
[m_ItemsCnt
].m_Book
= m_Book
;
188 if (m_Name
== wxEmptyString
&& tag
.GetParam(wxT("NAME")) == wxT("Name"))
189 m_Name
= tag
.GetParam(wxT("VALUE"));
190 if (tag
.GetParam(wxT("NAME")) == wxT("Local"))
191 m_Page
= tag
.GetParam(wxT("VALUE"));
192 if (tag
.GetParam(wxT("NAME")) == wxT("ID"))
193 tag
.GetParamAsInt(wxT("VALUE"), &m_ID
);
200 void HP_TagHandler::WriteOut(wxHtmlContentsItem
*& array
, int& size
)
208 void HP_TagHandler::ReadIn(wxHtmlContentsItem
* array
, int size
)
217 //-----------------------------------------------------------------------------
219 //-----------------------------------------------------------------------------
221 wxString
wxHtmlBookRecord::GetFullPath(const wxString
&page
) const
223 if (wxIsAbsolutePath(page
))
226 return m_BasePath
+ page
;
231 IMPLEMENT_DYNAMIC_CLASS(wxHtmlHelpData
, wxObject
)
233 wxHtmlHelpData::wxHtmlHelpData()
235 m_TempPath
= wxEmptyString
;
243 wxHtmlHelpData::~wxHtmlHelpData()
245 m_BookRecords
.Empty();
250 bool wxHtmlHelpData::LoadMSProject(wxHtmlBookRecord
*book
, wxFileSystem
& fsys
, const wxString
& indexfile
, const wxString
& contentsfile
)
253 wxHtmlFilterHTML filter
;
258 HP_TagHandler
*handler
= new HP_TagHandler(book
);
259 parser
.AddTagHandler(handler
);
261 f
= ( contentsfile
.IsEmpty() ? (wxFSFile
*) NULL
: fsys
.OpenFile(contentsfile
) );
265 buf
= filter
.ReadFile(*f
);
267 handler
->ReadIn(m_Contents
, m_ContentsCnt
);
269 handler
->WriteOut(m_Contents
, m_ContentsCnt
);
273 wxLogError(_("Cannot open contents file: %s"), contentsfile
.c_str());
276 f
= ( indexfile
.IsEmpty() ? (wxFSFile
*) NULL
: fsys
.OpenFile(indexfile
) );
280 buf
= filter
.ReadFile(*f
);
282 handler
->ReadIn(m_Index
, m_IndexCnt
);
284 handler
->WriteOut(m_Index
, m_IndexCnt
);
286 else if (!indexfile
.IsEmpty())
288 wxLogError(_("Cannot open index file: %s"), indexfile
.c_str());
293 inline static void CacheWriteInt32(wxOutputStream
*f
, wxInt32 value
)
295 wxInt32 x
= wxINT32_SWAP_ON_BE(value
);
296 f
->Write(&x
, sizeof(x
));
299 inline static wxInt32
CacheReadInt32(wxInputStream
*f
)
302 f
->Read(&x
, sizeof(x
));
303 return wxINT32_SWAP_ON_BE(x
);
306 inline static void CacheWriteString(wxOutputStream
*f
, const wxString
& str
)
308 const wxWX2MBbuf mbstr
= str
.mb_str(wxConvUTF8
);
309 size_t len
= strlen((const char*)mbstr
)+1;
310 CacheWriteInt32(f
, len
);
311 f
->Write((const char*)mbstr
, len
);
314 inline static wxString
CacheReadString(wxInputStream
*f
)
316 size_t len
= (size_t)CacheReadInt32(f
);
317 wxCharBuffer
str(len
-1);
318 f
->Read(str
.data(), len
);
319 return wxString(str
, wxConvUTF8
);
322 #define CURRENT_CACHED_BOOK_VERSION 4
324 // Additional flags to detect incompatibilities of the runtime environment:
325 #define CACHED_BOOK_FORMAT_FLAGS \
329 bool wxHtmlHelpData::LoadCachedBook(wxHtmlBookRecord
*book
, wxInputStream
*f
)
334 /* load header - version info : */
335 version
= CacheReadInt32(f
);
337 if (version
!= CURRENT_CACHED_BOOK_VERSION
)
339 // NB: We can just silently return FALSE here and don't worry about
340 // it anymore, because AddBookParam will load the MS project in
341 // absence of (properly versioned) .cached file and automatically
342 // create new .cached file immediately afterward.
346 if (CacheReadInt32(f
) != CACHED_BOOK_FORMAT_FLAGS
)
349 /* load contents : */
351 m_ContentsCnt
+= CacheReadInt32(f
);
352 m_Contents
= ReallocArray(m_Contents
, st
,
353 (m_ContentsCnt
/ wxHTML_REALLOC_STEP
+ 1) *
354 wxHTML_REALLOC_STEP
);
355 for (i
= st
; i
< m_ContentsCnt
; i
++)
357 m_Contents
[i
].m_Level
= CacheReadInt32(f
);
358 m_Contents
[i
].m_ID
= CacheReadInt32(f
);
359 m_Contents
[i
].m_Name
= CacheReadString(f
);
360 m_Contents
[i
].m_Page
= CacheReadString(f
);
361 m_Contents
[i
].m_Book
= book
;
366 m_IndexCnt
+= CacheReadInt32(f
);
367 m_Index
= ReallocArray(m_Index
, st
,
368 (m_IndexCnt
/ wxHTML_REALLOC_STEP
+ 1) *
369 wxHTML_REALLOC_STEP
);
370 for (i
= st
; i
< m_IndexCnt
; i
++)
372 m_Index
[i
].m_Name
= CacheReadString(f
);
373 m_Index
[i
].m_Page
= CacheReadString(f
);
374 m_Index
[i
].m_Book
= book
;
380 bool wxHtmlHelpData::SaveCachedBook(wxHtmlBookRecord
*book
, wxOutputStream
*f
)
385 /* save header - version info : */
386 CacheWriteInt32(f
, CURRENT_CACHED_BOOK_VERSION
);
387 CacheWriteInt32(f
, CACHED_BOOK_FORMAT_FLAGS
);
389 /* save contents : */
390 for (cnt
= 0, i
= 0; i
< m_ContentsCnt
; i
++)
391 if (m_Contents
[i
].m_Book
== book
&& m_Contents
[i
].m_Level
> 0)
393 CacheWriteInt32(f
, cnt
);
395 for (i
= 0; i
< m_ContentsCnt
; i
++)
397 if (m_Contents
[i
].m_Book
!= book
|| m_Contents
[i
].m_Level
== 0)
399 CacheWriteInt32(f
, m_Contents
[i
].m_Level
);
400 CacheWriteInt32(f
, m_Contents
[i
].m_ID
);
401 CacheWriteString(f
, m_Contents
[i
].m_Name
);
402 CacheWriteString(f
, m_Contents
[i
].m_Page
);
406 for (cnt
= 0, i
= 0; i
< m_IndexCnt
; i
++)
407 if (m_Index
[i
].m_Book
== book
&& m_Index
[i
].m_Level
> 0)
409 CacheWriteInt32(f
, cnt
);
411 for (i
= 0; i
< m_IndexCnt
; i
++)
413 if (m_Index
[i
].m_Book
!= book
|| m_Index
[i
].m_Level
== 0)
415 CacheWriteString(f
, m_Index
[i
].m_Name
);
416 CacheWriteString(f
, m_Index
[i
].m_Page
);
422 void wxHtmlHelpData::SetTempDir(const wxString
& path
)
424 if (path
== wxEmptyString
) m_TempPath
= path
;
427 if (wxIsAbsolutePath(path
)) m_TempPath
= path
;
428 else m_TempPath
= wxGetCwd() + _T("/") + path
;
430 if (m_TempPath
[m_TempPath
.Length() - 1] != _T('/'))
431 m_TempPath
<< _T('/');
437 static wxString
SafeFileName(const wxString
& s
)
440 res
.Replace(wxT("#"), wxT("_"));
441 res
.Replace(wxT(":"), wxT("_"));
442 res
.Replace(wxT("\\"), wxT("_"));
443 res
.Replace(wxT("/"), wxT("_"));
447 #ifdef WXWIN_COMPATIBILITY_2_4
448 bool wxHtmlHelpData::AddBookParam(const wxFSFile
& bookfile
,
449 wxFontEncoding encoding
,
450 const wxString
& title
, const wxString
& contfile
,
451 const wxString
& indexfile
, const wxString
& deftopic
,
452 const wxString
& path
)
456 if (encoding
!= wxFONTENCODING_SYSTEM
)
457 charset
= wxFontMapper::Get()->GetEncodingName(encoding
);
459 return AddBookParam(bookfile
, charset
, title
, contfile
, indexfile
,
462 #endif // WXWIN_COMPATIBILITY_2_4
464 bool wxHtmlHelpData::AddBookParam(const wxFSFile
& bookfile
,
465 const wxString
& charset
,
466 const wxString
& title
, const wxString
& contfile
,
467 const wxString
& indexfile
, const wxString
& deftopic
,
468 const wxString
& path
)
472 wxHtmlBookRecord
*bookr
;
474 int IndexOld
= m_IndexCnt
,
475 ContentsOld
= m_ContentsCnt
;
478 fsys
.ChangePathTo(path
, TRUE
);
480 size_t booksCnt
= m_BookRecords
.GetCount();
481 for (size_t i
= 0; i
< booksCnt
; i
++)
483 if ( m_BookRecords
[i
].GetBookFile() == bookfile
.GetLocation() )
484 return TRUE
; // book is (was) loaded
487 bookr
= new wxHtmlBookRecord(bookfile
.GetLocation(), fsys
.GetPath(), title
, deftopic
);
489 if (m_ContentsCnt
% wxHTML_REALLOC_STEP
== 0)
490 m_Contents
= ReallocArray(m_Contents
, m_ContentsCnt
,
491 m_ContentsCnt
+ wxHTML_REALLOC_STEP
);
492 m_Contents
[m_ContentsCnt
].m_Level
= 0;
493 m_Contents
[m_ContentsCnt
].m_ID
= 0;
494 m_Contents
[m_ContentsCnt
].m_Page
= deftopic
;
495 m_Contents
[m_ContentsCnt
].m_Name
= title
;
496 m_Contents
[m_ContentsCnt
].m_Book
= bookr
;
498 // store the contents index for later
499 int cont_start
= m_ContentsCnt
++;
501 // Try to find cached binary versions:
502 // 1. save file as book, but with .hhp.cached extension
503 // 2. same as 1. but in temp path
504 // 3. otherwise or if cache load failed, load it from MS.
506 fi
= fsys
.OpenFile(bookfile
.GetLocation() + wxT(".cached"));
510 fi
->GetModificationTime() < bookfile
.GetModificationTime() ||
511 #endif // wxUSE_DATETIME
512 !LoadCachedBook(bookr
, fi
->GetStream()))
514 if (fi
!= NULL
) delete fi
;
515 fi
= fsys
.OpenFile(m_TempPath
+ wxFileNameFromPath(bookfile
.GetLocation()) + wxT(".cached"));
516 if (m_TempPath
== wxEmptyString
|| fi
== NULL
||
518 fi
->GetModificationTime() < bookfile
.GetModificationTime() ||
519 #endif // wxUSE_DATETIME
520 !LoadCachedBook(bookr
, fi
->GetStream()))
522 LoadMSProject(bookr
, fsys
, indexfile
, contfile
);
523 if (m_TempPath
!= wxEmptyString
)
525 wxFileOutputStream
*outs
= new wxFileOutputStream(m_TempPath
+
526 SafeFileName(wxFileNameFromPath(bookfile
.GetLocation())) + wxT(".cached"));
527 SaveCachedBook(bookr
, outs
);
533 if (fi
!= NULL
) delete fi
;
535 // Now store the contents range
536 bookr
->SetContentsRange(cont_start
, m_ContentsCnt
);
539 // MS HTML Help files [written by MS HTML Help Workshop] are broken
540 // in that the data are iso-8859-1 (including HTML entities), but must
541 // be interpreted as being in language's windows charset. Correct the
542 // differences here and also convert to wxConvLocal in ANSI build
543 if (!charset
.empty())
546 #define CORRECT_STR(str, conv) \
547 str = wxString((str).mb_str(wxConvISO8859_1), conv)
549 #define CORRECT_STR(str, conv) \
550 str = wxString((str).wc_str(conv), wxConvLocal)
552 wxCSConv
conv(charset
);
554 for (i
= IndexOld
; i
< m_IndexCnt
; i
++)
556 CORRECT_STR(m_Index
[i
].m_Name
, conv
);
558 for (i
= ContentsOld
; i
< m_ContentsCnt
; i
++)
560 CORRECT_STR(m_Contents
[i
].m_Name
, conv
);
565 wxUnusedVar(IndexOld
);
566 wxUnusedVar(ContentsOld
);
567 wxASSERT_MSG(charset
.empty(), wxT("Help files need charset conversion, but wxUSE_WCHAR_T is 0"));
568 #endif // wxUSE_WCHAR_T/!wxUSE_WCHAR_T
570 m_BookRecords
.Add(bookr
);
572 qsort(m_Index
, m_IndexCnt
, sizeof(wxHtmlContentsItem
), wxHtmlHelpIndexCompareFunc
);
578 bool wxHtmlHelpData::AddBook(const wxString
& book
)
580 wxString
extension(book
.Right(4).Lower());
581 if (extension
== wxT(".zip") ||
583 extension
== wxT(".chm") /*compressed html help book*/ ||
585 extension
== wxT(".htb") /*html book*/)
592 if (extension
== wxT(".chm"))
593 s
= fsys
.FindFirst(book
+ wxT("#chm:*.hhp"), wxFILE
);
596 s
= fsys
.FindFirst(book
+ wxT("#zip:*.hhp"), wxFILE
);
600 if (AddBook(s
)) rt
= TRUE
;
610 wxString title
= _("noname"),
612 start
= wxEmptyString
,
613 contents
= wxEmptyString
,
614 index
= wxEmptyString
,
615 charset
= wxEmptyString
;
617 fi
= fsys
.OpenFile(book
);
620 wxLogError(_("Cannot open HTML help book: %s"), book
.c_str());
623 fsys
.ChangePathTo(book
);
625 const wxChar
*lineptr
;
628 wxHtmlFilterPlainText filter
;
629 tmp
= filter
.ReadFile(*fi
);
630 lineptr
= tmp
.c_str();
634 lineptr
= ReadLine(lineptr
, linebuf
, 300);
636 for (wxChar
*ch
= linebuf
; *ch
!= wxT('\0') && *ch
!= wxT('='); ch
++)
639 if (wxStrstr(linebuf
, _T("title=")) == linebuf
)
640 title
= linebuf
+ wxStrlen(_T("title="));
641 if (wxStrstr(linebuf
, _T("default topic=")) == linebuf
)
642 start
= linebuf
+ wxStrlen(_T("default topic="));
643 if (wxStrstr(linebuf
, _T("index file=")) == linebuf
)
644 index
= linebuf
+ wxStrlen(_T("index file="));
645 if (wxStrstr(linebuf
, _T("contents file=")) == linebuf
)
646 contents
= linebuf
+ wxStrlen(_T("contents file="));
647 if (wxStrstr(linebuf
, _T("charset=")) == linebuf
)
648 charset
= linebuf
+ wxStrlen(_T("charset="));
649 } while (lineptr
!= NULL
);
651 bool rtval
= AddBookParam(*fi
, charset
,
652 title
, contents
, index
, start
, fsys
.GetPath());
657 wxString
wxHtmlHelpData::FindPageByName(const wxString
& x
)
663 wxString
url(wxEmptyString
);
665 /* 1. try to open given file: */
667 cnt
= m_BookRecords
.GetCount();
668 for (i
= 0; i
< cnt
; i
++)
670 f
= fsys
.OpenFile(m_BookRecords
[i
].GetFullPath(x
));
673 url
= m_BookRecords
[i
].GetFullPath(x
);
680 /* 2. try to find a book: */
682 for (i
= 0; i
< cnt
; i
++)
684 if (m_BookRecords
[i
].GetTitle() == x
)
686 url
= m_BookRecords
[i
].GetFullPath(m_BookRecords
[i
].GetStart());
691 /* 3. try to find in contents: */
694 for (i
= 0; i
< cnt
; i
++)
696 if (m_Contents
[i
].m_Name
== x
)
698 url
= m_Contents
[i
].GetFullPath();
704 /* 4. try to find in index: */
707 for (i
= 0; i
< cnt
; i
++)
709 if (m_Index
[i
].m_Name
== x
)
711 url
= m_Index
[i
].GetFullPath();
719 wxString
wxHtmlHelpData::FindPageById(int id
)
722 wxString
url(wxEmptyString
);
724 for (i
= 0; i
< m_ContentsCnt
; i
++)
726 if (m_Contents
[i
].m_ID
== id
)
728 url
= m_Contents
[i
].GetFullPath();
736 //----------------------------------------------------------------------------------
737 // wxHtmlSearchStatus functions
738 //----------------------------------------------------------------------------------
740 wxHtmlSearchStatus::wxHtmlSearchStatus(wxHtmlHelpData
* data
, const wxString
& keyword
,
741 bool case_sensitive
, bool whole_words_only
,
742 const wxString
& book
)
746 wxHtmlBookRecord
* bookr
= NULL
;
747 if (book
!= wxEmptyString
)
749 // we have to search in a specific book. Find it first
750 int i
, cnt
= data
->m_BookRecords
.GetCount();
751 for (i
= 0; i
< cnt
; i
++)
752 if (data
->m_BookRecords
[i
].GetTitle() == book
)
754 bookr
= &(data
->m_BookRecords
[i
]);
755 m_CurIndex
= bookr
->GetContentsStart();
756 m_MaxIndex
= bookr
->GetContentsEnd();
759 // check; we won't crash if the book doesn't exist, but it's Bad Anyway.
764 // no book specified; search all books
766 m_MaxIndex
= m_Data
->m_ContentsCnt
;
768 m_Engine
.LookFor(keyword
, case_sensitive
, whole_words_only
);
769 m_Active
= (m_CurIndex
< m_MaxIndex
);
772 bool wxHtmlSearchStatus::Search()
775 int i
= m_CurIndex
; // shortcut
781 // sanity check. Illegal use, but we'll try to prevent a crash anyway
786 m_Name
= wxEmptyString
;
787 m_ContentsItem
= NULL
;
788 thepage
= m_Data
->m_Contents
[i
].m_Page
;
790 m_Active
= (++m_CurIndex
< m_MaxIndex
);
791 // check if it is same page with different anchor:
792 if (!m_LastPage
.empty())
794 const wxChar
*p1
, *p2
;
795 for (p1
= thepage
.c_str(), p2
= m_LastPage
.c_str();
796 *p1
!= 0 && *p1
!= _T('#') && *p1
== *p2
; p1
++, p2
++) {}
798 m_LastPage
= thepage
;
800 if (*p1
== 0 || *p1
== _T('#'))
803 else m_LastPage
= thepage
;
806 file
= fsys
.OpenFile(m_Data
->m_Contents
[i
].m_Book
->GetFullPath(thepage
));
809 if (m_Engine
.Scan(*file
))
811 m_Name
= m_Data
->m_Contents
[i
].m_Name
;
812 m_ContentsItem
= m_Data
->m_Contents
+ i
;
827 //--------------------------------------------------------------------------------
828 // wxHtmlSearchEngine
829 //--------------------------------------------------------------------------------
831 void wxHtmlSearchEngine::LookFor(const wxString
& keyword
, bool case_sensitive
, bool whole_words_only
)
833 m_CaseSensitive
= case_sensitive
;
834 m_WholeWords
= whole_words_only
;
838 m_Keyword
.LowerCase();
842 static inline bool WHITESPACE(wxChar c
)
844 return c
== _T(' ') || c
== _T('\n') || c
== _T('\r') || c
== _T('\t');
847 bool wxHtmlSearchEngine::Scan(const wxFSFile
& file
)
849 wxASSERT_MSG(!m_Keyword
.empty(), wxT("wxHtmlSearchEngine::LookFor must be called before scanning!"));
852 int wrd
= m_Keyword
.Length();
854 wxHtmlFilterHTML filter
;
855 wxString tmp
= filter
.ReadFile(file
);
856 int lng
= tmp
.length();
857 const wxChar
*buf
= tmp
.c_str();
859 if (!m_CaseSensitive
)
862 const wxChar
*kwd
= m_Keyword
.c_str();
866 for (i
= 0; i
< lng
- wrd
; i
++)
868 if (WHITESPACE(buf
[i
])) continue;
870 while ((j
< wrd
) && (buf
[i
+ j
] == kwd
[j
])) j
++;
871 if (j
== wrd
&& WHITESPACE(buf
[i
+ j
])) { found
= true; break; }
877 for (i
= 0; i
< lng
- wrd
; i
++)
880 while ((j
< wrd
) && (buf
[i
+ j
] == kwd
[j
])) j
++;
881 if (j
== wrd
) { found
= true; break; }