]> git.saurik.com Git - wxWidgets.git/blame - src/html/helpdata.cpp
PageUp/PageDown scroll by 2/3 of client area height (was 1)
[wxWidgets.git] / src / html / helpdata.cpp
CommitLineData
8ec2b484
HH
1/////////////////////////////////////////////////////////////////////////////
2// Name: helpdata.cpp
3// Purpose: wxHtmlHelpData
f42b1601 4// Notes: Based on htmlhelp.cpp, implementing a monolithic
8ec2b484
HH
5// HTML Help controller class, by Vaclav Slavik
6// Author: Harm van der Heijden and Vaclav Slavik
69941f05 7// RCS-ID: $Id$
8ec2b484
HH
8// Copyright: (c) Harm van der Heijden and Vaclav Slavik
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
69941f05 13#pragma implementation
8ec2b484
HH
14#endif
15
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18
19#ifdef __BORLANDC__
20#pragma hdrstop
21#endif
22
23#include "wx/defs.h"
24
25#if wxUSE_HTML
26
27#ifndef WXPRECOMP
28#include "wx/wx.h"
29#endif
30
31#include "wx/html/helpdata.h"
32#include "wx/tokenzr.h"
33#include "wx/wfstream.h"
34#include "wx/busyinfo.h"
69941f05 35#include "wx/html/htmlpars.h"
8ec2b484
HH
36#include "wx/html/htmldefs.h"
37
38#include "wx/arrimpl.cpp"
39WX_DEFINE_OBJARRAY(wxHtmlBookRecArray)
40
41//-----------------------------------------------------------------------------
42// static helper functions
43//-----------------------------------------------------------------------------
44
45// Reads one line, stores it into buf and returns pointer to new line or NULL.
46static char* ReadLine(char *line, char *buf)
47{
48 char *writeptr = buf, *readptr = line;
49
50 while (*readptr != 0 && *readptr != '\r' && *readptr != '\n') *(writeptr++) = *(readptr++);
51 *writeptr = 0;
52 while (*readptr == '\r' || *readptr == '\n') readptr++;
53 if (*readptr == 0) return NULL;
54 else return readptr;
55}
56
57
58static wxString SafeFileName(const wxString& s)
59{
60 wxString res = s;
66a77a74
OK
61 res.Replace(wxT(":"), wxT("_"), TRUE);
62 res.Replace(wxT(" "), wxT("_"), TRUE);
63 res.Replace(wxT("/"), wxT("_"), TRUE);
64 res.Replace(wxT("\\"), wxT("_"), TRUE);
65 res.Replace(wxT("#"), wxT("_"), TRUE);
66 res.Replace(wxT("."), wxT("_"), TRUE);
8ec2b484
HH
67 return res;
68}
69
70
16a12a3d 71static int LINKAGEMODE IndexCompareFunc(const void *a, const void *b)
8ec2b484 72{
66a77a74 73 return wxStrcmp(((wxHtmlContentsItem*)a) -> m_Name, ((wxHtmlContentsItem*)b) -> m_Name);
8ec2b484
HH
74}
75
76
77//-----------------------------------------------------------------------------
78// HP_Parser
79//-----------------------------------------------------------------------------
80
81class HP_Parser : public wxHtmlParser
82{
83 public:
0c5d3e1c
VZ
84 void AddText(const char* WXUNUSED(text)) { }
85 wxObject* GetProduct() { return NULL; }
8ec2b484
HH
86};
87
88
89//-----------------------------------------------------------------------------
90// HP_TagHandler
91//-----------------------------------------------------------------------------
92
93class HP_TagHandler : public wxHtmlTagHandler
94{
95 private:
96 wxString m_Name, m_Page;
97 int m_Level;
d5bb85a0 98 int m_ID;
8ec2b484
HH
99 int m_Index;
100 wxHtmlContentsItem *m_Items;
101 int m_ItemsCnt;
102 wxHtmlBookRecord *m_Book;
103
104 public:
d5bb85a0 105 HP_TagHandler(wxHtmlBookRecord *b) : wxHtmlTagHandler() {m_Book = b; m_Items = NULL; m_ItemsCnt = 0; m_Name = m_Page = wxEmptyString; m_Level = 0; }
66a77a74 106 wxString GetSupportedTags() { return wxT("UL,OBJECT,PARAM"); }
8ec2b484
HH
107 bool HandleTag(const wxHtmlTag& tag);
108 void WriteOut(wxHtmlContentsItem*& array, int& size);
109 void ReadIn(wxHtmlContentsItem* array, int size);
110};
111
112
113bool HP_TagHandler::HandleTag(const wxHtmlTag& tag)
114{
0413cec5 115 if (tag.GetName() == wxT("UL")) {
8ec2b484
HH
116 m_Level++;
117 ParseInner(tag);
118 m_Level--;
119 return TRUE;
120 }
66a77a74 121 else if (tag.GetName() == wxT("OBJECT")) {
8ec2b484
HH
122 m_Name = m_Page = wxEmptyString;
123 ParseInner(tag);
50494a55 124
4157f43f
VS
125 if (!m_Page.IsEmpty())
126 /* should be 'if (tag.GetParam("TYPE") == "text/sitemap")'
127 but this works fine. Valid HHW's file may contain only two
128 object tags:
129
130 <OBJECT type="text/site properties">
131 <param name="ImageType" value="Folder">
132 </OBJECT>
133
134 or
135
136 <OBJECT type="text/sitemap">
137 <param name="Name" value="main page">
138 <param name="Local" value="another.htm">
139 </OBJECT>
140
141 We're interested in the latter. !m_Page.IsEmpty() is valid
142 condition because text/site properties does not contain Local param
143 */
144 {
145 if (m_ItemsCnt % wxHTML_REALLOC_STEP == 0)
146 m_Items = (wxHtmlContentsItem*) realloc(m_Items, (m_ItemsCnt + wxHTML_REALLOC_STEP) * sizeof(wxHtmlContentsItem));
147 m_Items[m_ItemsCnt].m_Level = m_Level;
148 m_Items[m_ItemsCnt].m_ID = m_ID;
149 m_Items[m_ItemsCnt].m_Page = new wxChar[m_Page.Length() + 1];
150 wxStrcpy(m_Items[m_ItemsCnt].m_Page, m_Page.c_str());
151 m_Items[m_ItemsCnt].m_Name = new wxChar [m_Name.Length() + 1];
152 wxStrcpy(m_Items[m_ItemsCnt].m_Name, m_Name.c_str());
153 m_Items[m_ItemsCnt].m_Book = m_Book;
154 m_ItemsCnt++;
155 }
50494a55 156
8ec2b484
HH
157 return TRUE;
158 }
8ec2b484 159 else { // "PARAM"
66a77a74
OK
160 if (m_Name == wxEmptyString && tag.GetParam(wxT("NAME")) == wxT("Name")) m_Name = tag.GetParam(wxT("VALUE"));
161 if (tag.GetParam(wxT("NAME")) == wxT("Local")) m_Page = tag.GetParam(wxT("VALUE"));
162 if (tag.GetParam(wxT("NAME")) == wxT("ID")) tag.ScanParam(wxT("VALUE"), wxT("%i"), &m_ID);
8ec2b484
HH
163 return FALSE;
164 }
165}
166
167
168
169void HP_TagHandler::WriteOut(wxHtmlContentsItem*& array, int& size)
170{
171 array = m_Items;
172 size = m_ItemsCnt;
173 m_Items = NULL;
174 m_ItemsCnt = 0;
175}
176
177void HP_TagHandler::ReadIn(wxHtmlContentsItem* array, int size)
178{
179 m_Items = array;
180 m_ItemsCnt = size;
181}
182
d5bb85a0
VS
183
184
185
8ec2b484
HH
186//-----------------------------------------------------------------------------
187// wxHtmlHelpData
188//-----------------------------------------------------------------------------
189
190IMPLEMENT_DYNAMIC_CLASS(wxHtmlHelpData, wxObject)
191
f42b1601 192wxHtmlHelpData::wxHtmlHelpData()
8ec2b484
HH
193{
194 m_TempPath = wxEmptyString;
195
196 m_Contents = NULL;
197 m_ContentsCnt = 0;
198 m_Index = NULL;
199 m_IndexCnt = 0;
200}
201
202wxHtmlHelpData::~wxHtmlHelpData()
203{
204 int i;
205
206 m_BookRecords.Empty();
207 if (m_Contents) {
208 for (i = 0; i < m_ContentsCnt; i++) {
209 delete[] m_Contents[i].m_Page;
210 delete[] m_Contents[i].m_Name;
211 }
212 free(m_Contents);
213 }
214 if (m_Index) {
215 for (i = 0; i < m_IndexCnt; i++) {
216 delete[] m_Index[i].m_Page;
217 delete[] m_Index[i].m_Name;
218 }
219 free(m_Index);
220 }
221}
222
223bool wxHtmlHelpData::LoadMSProject(wxHtmlBookRecord *book, wxFileSystem& fsys, const wxString& indexfile, const wxString& contentsfile)
224{
225 wxFSFile *f;
226 char *buf;
227 int sz;
228 wxString string;
f42b1601 229
8ec2b484
HH
230 HP_Parser parser;
231 HP_TagHandler *handler = new HP_TagHandler(book);
232 parser.AddTagHandler(handler);
233
af111fc3 234 f = ( contentsfile.IsEmpty() ? 0 : fsys.OpenFile(contentsfile) );
8ec2b484
HH
235 if (f) {
236 sz = f -> GetStream() -> GetSize();
d5bb85a0 237 buf = new char[sz + 1];
8ec2b484
HH
238 buf[sz] = 0;
239 f -> GetStream() -> Read(buf, sz);
240 delete f;
241 handler -> ReadIn(m_Contents, m_ContentsCnt);
242 parser.Parse(buf);
243 handler -> WriteOut(m_Contents, m_ContentsCnt);
244 delete[] buf;
245 }
246
af111fc3 247 f = ( indexfile.IsEmpty() ? 0 : fsys.OpenFile(indexfile) );
8ec2b484
HH
248 if (f) {
249 sz = f -> GetStream() -> GetSize();
d5bb85a0 250 buf = new char[sz + 1];
8ec2b484
HH
251 buf[sz] = 0;
252 f -> GetStream() -> Read(buf, sz);
253 delete f;
254 handler -> ReadIn(m_Index, m_IndexCnt);
255 parser.Parse(buf);
256 handler -> WriteOut(m_Index, m_IndexCnt);
257 delete[] buf;
258 }
259 return TRUE;
260}
261
262
263bool wxHtmlHelpData::LoadCachedBook(wxHtmlBookRecord *book, wxInputStream *f)
264{
265 int i, st;
266 int x;
267
268 /* load contents : */
269
270 f -> Read(&x, sizeof(x));
271 st = m_ContentsCnt;
272 m_ContentsCnt += x;
efba2b89 273 m_Contents = (wxHtmlContentsItem*) realloc(m_Contents, (m_ContentsCnt / wxHTML_REALLOC_STEP + 1) * wxHTML_REALLOC_STEP * sizeof(wxHtmlContentsItem));
8ec2b484
HH
274 for (i = st; i < m_ContentsCnt; i++) {
275 f -> Read(&x, sizeof(x));
276 m_Contents[i].m_Level = x;
277 f -> Read(&x, sizeof(x));
278 m_Contents[i].m_ID = x;
279 f -> Read(&x, sizeof(x));
66a77a74
OK
280 m_Contents[i].m_Name = new wxChar[x];
281 f -> Read(m_Contents[i].m_Name, x*sizeof(wxChar));
8ec2b484 282 f -> Read(&x, sizeof(x));
66a77a74
OK
283 m_Contents[i].m_Page = new wxChar[x];
284 f -> Read(m_Contents[i].m_Page, x*sizeof(wxChar));
8ec2b484
HH
285 m_Contents[i].m_Book = book;
286 }
287
288 /* load index : */
289
290 f -> Read(&x, sizeof(x));
291 st = m_IndexCnt;
292 m_IndexCnt += x;
efba2b89 293 m_Index = (wxHtmlContentsItem*) realloc(m_Index, (m_IndexCnt / wxHTML_REALLOC_STEP + 1) * wxHTML_REALLOC_STEP * sizeof(wxHtmlContentsItem));
8ec2b484
HH
294 for (i = st; i < m_IndexCnt; i++) {
295 f -> Read(&x, sizeof(x));
66a77a74
OK
296 m_Index[i].m_Name = new wxChar[x];
297 f -> Read(m_Index[i].m_Name, x*sizeof(wxChar));
8ec2b484 298 f -> Read(&x, sizeof(x));
66a77a74
OK
299 m_Index[i].m_Page = new wxChar[x];
300 f -> Read(m_Index[i].m_Page, x*sizeof(wxChar));
8ec2b484
HH
301 m_Index[i].m_Book = book;
302 }
303 return TRUE;
304}
305
306
307bool wxHtmlHelpData::SaveCachedBook(wxHtmlBookRecord *book, wxOutputStream *f)
308{
309 int i;
310 int x;
311
312 /* save contents : */
313
314 x = 0;
315 for (i = 0; i < m_ContentsCnt; i++) if (m_Contents[i].m_Book == book && m_Contents[i].m_Level > 0) x++;
316 f -> Write(&x, sizeof(x));
317 for (i = 0; i < m_ContentsCnt; i++) {
318 if (m_Contents[i].m_Book != book || m_Contents[i].m_Level == 0) continue;
319 x = m_Contents[i].m_Level;
320 f -> Write(&x, sizeof(x));
321 x = m_Contents[i].m_ID;
322 f -> Write(&x, sizeof(x));
66a77a74 323 x = wxStrlen(m_Contents[i].m_Name) + 1;
8ec2b484 324 f -> Write(&x, sizeof(x));
66a77a74
OK
325 f -> Write(m_Contents[i].m_Name, x*sizeof(wxChar));
326 x = wxStrlen(m_Contents[i].m_Page) + 1;
8ec2b484 327 f -> Write(&x, sizeof(x));
66a77a74 328 f -> Write(m_Contents[i].m_Page, x*sizeof(wxChar));
8ec2b484
HH
329 }
330
331 /* save index : */
332
333 x = 0;
334 for (i = 0; i < m_IndexCnt; i++) if (m_Index[i].m_Book == book && m_Index[i].m_Level > 0) x++;
335 f -> Write(&x, sizeof(x));
336 for (i = 0; i < m_IndexCnt; i++) {
337 if (m_Index[i].m_Book != book || m_Index[i].m_Level == 0) continue;
66a77a74 338 x = wxStrlen(m_Index[i].m_Name) + 1;
8ec2b484 339 f -> Write(&x, sizeof(x));
66a77a74
OK
340 f -> Write(m_Index[i].m_Name, x*sizeof(wxChar));
341 x = wxStrlen(m_Index[i].m_Page) + 1;
8ec2b484 342 f -> Write(&x, sizeof(x));
66a77a74 343 f -> Write(m_Index[i].m_Page, x*sizeof(wxChar));
8ec2b484
HH
344 }
345 return TRUE;
346}
347
348
349void wxHtmlHelpData::SetTempDir(const wxString& path)
350{
351 if (path == wxEmptyString) m_TempPath = path;
352 else {
d5bb85a0
VS
353 if (wxIsAbsolutePath(path)) m_TempPath = path;
354 else m_TempPath = wxGetCwd() + "/" + path;
8ec2b484 355
d5bb85a0 356 if (m_TempPath[m_TempPath.Length() - 1] != '/')
8ec2b484
HH
357 m_TempPath << "/";
358 }
359}
360
361
f42b1601 362bool wxHtmlHelpData::AddBookParam(const wxString& title, const wxString& contfile,
d5bb85a0
VS
363 const wxString& indexfile, const wxString& deftopic,
364 const wxString& path)
8ec2b484
HH
365{
366 wxFileSystem fsys;
367 wxFSFile *fi;
368 wxHtmlBookRecord *bookr;
369 wxString safetitle;
f42b1601 370
8ec2b484 371 if (! path.IsEmpty())
d5bb85a0 372 fsys.ChangePathTo(path, TRUE);
8ec2b484 373
68364659 374 bookr = new wxHtmlBookRecord(fsys.GetPath(), title, deftopic);
8ec2b484 375
efba2b89
VS
376 if (m_ContentsCnt % wxHTML_REALLOC_STEP == 0)
377 m_Contents = (wxHtmlContentsItem*) realloc(m_Contents, (m_ContentsCnt + wxHTML_REALLOC_STEP) * sizeof(wxHtmlContentsItem));
8ec2b484
HH
378 m_Contents[m_ContentsCnt].m_Level = 0;
379 m_Contents[m_ContentsCnt].m_ID = 0;
66a77a74
OK
380 m_Contents[m_ContentsCnt].m_Page = new wxChar[deftopic.Length() + 1];
381 wxStrcpy(m_Contents[m_ContentsCnt].m_Page, deftopic.c_str());
382 m_Contents[m_ContentsCnt].m_Name = new wxChar [title.Length() + 1];
383 wxStrcpy(m_Contents[m_ContentsCnt].m_Name, title.c_str());
8ec2b484
HH
384 m_Contents[m_ContentsCnt].m_Book = bookr;
385
386 // store the contents index for later
387 int cont_start = m_ContentsCnt++;
388
389 // Try to find cached binary versions:
390 safetitle = SafeFileName(title);
68364659
VS
391 fi = fsys.OpenFile(safetitle + wxT(".cached"));
392 if (fi == NULL) fi = fsys.OpenFile(m_TempPath + safetitle + wxT(".cached"));
8ec2b484
HH
393 if ((fi == NULL) || (m_TempPath == wxEmptyString)) {
394 LoadMSProject(bookr, fsys, indexfile, contfile);
395 if (m_TempPath != wxEmptyString) {
68364659 396 wxFileOutputStream *outs = new wxFileOutputStream(m_TempPath + safetitle + wxT(".cached"));
8ec2b484
HH
397 SaveCachedBook(bookr, outs);
398 delete outs;
d5bb85a0
VS
399 }
400 } else {
8ec2b484
HH
401 LoadCachedBook(bookr, fi -> GetStream());
402 delete fi;
403 }
404
405 // Now store the contents range
406 bookr->SetContentsRange(cont_start, m_ContentsCnt);
407
408 m_BookRecords.Add(bookr);
409 if (m_IndexCnt > 0)
410 qsort(m_Index, m_IndexCnt, sizeof(wxHtmlContentsItem), IndexCompareFunc);
f42b1601 411
8ec2b484
HH
412 return TRUE;
413}
414
415
416bool wxHtmlHelpData::AddBook(const wxString& book)
417{
68364659
VS
418 if (book.Right(4).Lower() == wxT(".zip") ||
419 book.Right(4).Lower() == wxT(".htb") /*html book*/)
420
421 {
422 wxFileSystem fsys;
423 wxString s;
424 bool rt = FALSE;
425
426 s = fsys.FindFirst(book + wxT("#zip:") + wxT("*.hhp"), wxFILE);
427 while (!s.IsEmpty())
428 {
429 if (AddBook(s)) rt = TRUE;
430 s = fsys.FindNext();
431 }
432
433 return rt;
434 }
8ec2b484 435
68364659
VS
436
437 else
438 {
439 wxFSFile *fi;
440 wxFileSystem fsys;
441 wxInputStream *s;
442 wxString bookFull;
443
444 int sz;
445 char *buff, *lineptr;
446 char linebuf[300];
447
448 wxString title = _("noname"),
449 safetitle,
450 start = wxEmptyString,
451 contents = wxEmptyString, index = wxEmptyString;
452
453 if (wxIsAbsolutePath(book)) bookFull = book;
454 else bookFull = wxGetCwd() + "/" + book;
455
456 fi = fsys.OpenFile(bookFull);
457 if (fi == NULL) return FALSE;
458 fsys.ChangePathTo(bookFull);
459 s = fi -> GetStream();
460 sz = s -> GetSize();
461 buff = new char[sz + 1];
462 buff[sz] = 0;
463 s -> Read(buff, sz);
464 lineptr = buff;
465 delete fi;
466
467 do {
468 lineptr = ReadLine(lineptr, linebuf);
469
470 if (strstr(linebuf, "Title=") == linebuf)
471 title = linebuf + strlen("Title=");
472 if (strstr(linebuf, "Default topic=") == linebuf)
473 start = linebuf + strlen("Default topic=");
474 if (strstr(linebuf, "Index file=") == linebuf)
475 index = linebuf + strlen("Index file=");
476 if (strstr(linebuf, "Contents file=") == linebuf)
477 contents = linebuf + strlen("Contents file=");
478 } while (lineptr != NULL);
479 delete[] buff;
480
481 return AddBookParam(title, contents, index, start, fsys.GetPath());
482 }
8ec2b484
HH
483}
484
485wxString wxHtmlHelpData::FindPageByName(const wxString& x)
486{
487 int cnt;
488 int i;
489 wxFileSystem fsys;
490 wxFSFile *f;
491 wxString url(wxEmptyString);
492
493 /* 1. try to open given file: */
494
495 cnt = m_BookRecords.GetCount();
496 for (i = 0; i < cnt; i++) {
497 f = fsys.OpenFile(m_BookRecords[i].GetBasePath() + x);
498 if (f) {
499 url = m_BookRecords[i].GetBasePath() + x;
500 delete f;
501 return url;
502 }
503 }
504
505
506 /* 2. try to find a book: */
507
508 for (i = 0; i < cnt; i++) {
509 if (m_BookRecords[i].GetTitle() == x) {
510 url = m_BookRecords[i].GetBasePath() + m_BookRecords[i].GetStart();
511 return url;
512 }
513 }
514
515 /* 3. try to find in contents: */
516
517 cnt = m_ContentsCnt;
518 for (i = 0; i < cnt; i++) {
66a77a74 519 if (wxStrcmp(m_Contents[i].m_Name, x) == 0) {
8ec2b484
HH
520 url = m_Contents[i].m_Book -> GetBasePath() + m_Contents[i].m_Page;
521 return url;
522 }
523 }
524
525
526 /* 4. try to find in index: */
527
528 cnt = m_IndexCnt;
529 for (i = 0; i < cnt; i++) {
66a77a74 530 if (wxStrcmp(m_Index[i].m_Name, x) == 0) {
8ec2b484
HH
531 url = m_Index[i].m_Book -> GetBasePath() + m_Index[i].m_Page;
532 return url;
533 }
534 }
535
536 return url;
537}
538
539wxString wxHtmlHelpData::FindPageById(int id)
f42b1601 540{
8ec2b484
HH
541 int i;
542 wxString url(wxEmptyString);
543
544 for (i = 0; i < m_ContentsCnt; i++) {
545 if (m_Contents[i].m_ID == id) {
546 url = m_Contents[i].m_Book -> GetBasePath() + m_Contents[i].m_Page;
547 return url;
548 }
549 }
550
551 return url;
552}
553
554//----------------------------------------------------------------------------------
555// wxHtmlSearchStatus functions
556//----------------------------------------------------------------------------------
557
558wxHtmlSearchStatus::wxHtmlSearchStatus(wxHtmlHelpData* data, const wxString& keyword,
c4971147 559 bool case_sensitive, bool whole_words_only,
d5bb85a0 560 const wxString& book)
8ec2b484
HH
561{
562 m_Data = data;
563 m_Keyword = keyword;
564 wxHtmlBookRecord* bookr = NULL;
565 if (book != wxEmptyString) {
d5bb85a0
VS
566 // we have to search in a specific book. Find it first
567 int i, cnt = data->m_BookRecords.GetCount();
568 for (i = 0; i < cnt; i++)
569 if (data->m_BookRecords[i].GetTitle() == book) {
570 bookr = &(data->m_BookRecords[i]);
571 m_CurIndex = bookr->GetContentsStart();
572 m_MaxIndex = bookr->GetContentsEnd();
573 break;
574 }
575 // check; we won't crash if the book doesn't exist, but it's Bad Anyway.
576 wxASSERT(bookr);
8ec2b484
HH
577 }
578 if (! bookr) {
d5bb85a0
VS
579 // no book specified; search all books
580 m_CurIndex = 0;
581 m_MaxIndex = m_Data->m_ContentsCnt;
8ec2b484 582 }
c4971147 583 m_Engine.LookFor(keyword, case_sensitive, whole_words_only);
8ec2b484 584 m_Active = (m_CurIndex < m_MaxIndex);
b5a7b000 585 m_LastPage = NULL;
8ec2b484
HH
586}
587
588bool wxHtmlSearchStatus::Search()
589{
590 wxFileSystem fsys;
591 wxFSFile *file;
d5bb85a0 592 int i = m_CurIndex; // shortcut
8ec2b484 593 bool found = FALSE;
b5a7b000 594 wxChar *thepage;
8ec2b484 595
50494a55
VS
596 if (!m_Active) {
597 // sanity check. Illegal use, but we'll try to prevent a crash anyway
16a12a3d 598#if !defined(__VISAGECPP__)
50494a55 599 wxASSERT(0);
16a12a3d 600#else
50494a55 601 wxASSERT(m_Active);
16a12a3d 602#endif
50494a55 603 return FALSE;
8ec2b484
HH
604 }
605
8ec2b484 606 m_Name = wxEmptyString;
b5a7b000
VS
607 m_ContentsItem = NULL;
608 thepage = m_Data->m_Contents[i].m_Page;
8ec2b484 609
b5a7b000
VS
610 m_Active = (++m_CurIndex < m_MaxIndex);
611 // check if it is same page with different anchor:
612 if (m_LastPage != NULL)
613 {
614 wxChar *p1, *p2;
615 for (p1 = thepage, p2 = m_LastPage;
616 *p1 != 0 && *p1 != _T('#') && *p1 == *p2; p1++, p2++) {}
617
618 m_LastPage = thepage;
619
620 if (*p1 == 0 || *p1 == _T('#'))
621 return FALSE;
622 }
623 else m_LastPage = thepage;
624
625 file = fsys.OpenFile(m_Data->m_Contents[i].m_Book -> GetBasePath() + thepage);
626 if (file)
627 {
628 if (m_Engine.Scan(file -> GetStream())) {
629 m_Name = m_Data->m_Contents[i].m_Name;
630 m_ContentsItem = m_Data->m_Contents + i;
631 found = TRUE;
d5bb85a0
VS
632 }
633 delete file;
8ec2b484 634 }
8ec2b484
HH
635 return found;
636}
637
d5bb85a0
VS
638
639
640
641
642
643
644
645//--------------------------------------------------------------------------------
646// wxSearchEngine
647//--------------------------------------------------------------------------------
648
c4971147 649void wxSearchEngine::LookFor(const wxString& keyword, bool case_sensitive, bool whole_words_only)
d5bb85a0 650{
c4971147
VS
651 m_CaseSensitive = case_sensitive;
652 m_WholeWords = whole_words_only;
d5bb85a0 653 if (m_Keyword) delete[] m_Keyword;
66a77a74
OK
654 m_Keyword = new wxChar[keyword.Length() + 1];
655 wxStrcpy(m_Keyword, keyword.c_str());
c4971147
VS
656
657 if (!m_CaseSensitive)
658 for (int i = wxStrlen(m_Keyword) - 1; i >= 0; i--)
659 if ((m_Keyword[i] >= wxT('A')) && (m_Keyword[i] <= wxT('Z')))
660 m_Keyword[i] += wxT('a') - wxT('A');
d5bb85a0
VS
661}
662
663
664
c4971147
VS
665#define WHITESPACE(c) (c == ' ' || c == '\n' || c == '\r' || c == '\t')
666
d5bb85a0
VS
667bool wxSearchEngine::Scan(wxInputStream *stream)
668{
50494a55 669 wxASSERT_MSG(m_Keyword != NULL, wxT("wxSearchEngine::LookFor must be called before scanning!"));
d5bb85a0
VS
670
671 int i, j;
672 int lng = stream ->GetSize();
66a77a74 673 int wrd = wxStrlen(m_Keyword);
d5bb85a0
VS
674 bool found = FALSE;
675 char *buf = new char[lng + 1];
676 stream -> Read(buf, lng);
677 buf[lng] = 0;
678
c4971147
VS
679 if (!m_CaseSensitive)
680 for (i = 0; i < lng; i++)
681 if ((buf[i] >= 'A') && (buf[i] <= 'Z')) buf[i] += 'a' - 'A';
d5bb85a0 682
c4971147
VS
683 if (m_WholeWords)
684 {
685 for (i = 0; i < lng - wrd; i++) {
686 if (WHITESPACE(buf[i])) continue;
687 j = 0;
688 while ((j < wrd) && (buf[i + j] == m_Keyword[j])) j++;
689 if (j == wrd && WHITESPACE(buf[i + j])) {found = TRUE; break; }
690 }
691 }
692
693 else
694 {
695 for (i = 0; i < lng - wrd; i++) {
696 j = 0;
697 while ((j < wrd) && (buf[i + j] == m_Keyword[j])) j++;
698 if (j == wrd) {found = TRUE; break; }
699 }
d5bb85a0
VS
700 }
701
702 delete[] buf;
703 return found;
704}
705
706
707
708
8ec2b484 709#endif