~s-cecilio/lenmus/v5.3

« back to all changes in this revision

Viewing changes to src/app/lenmus_book_reader.cpp

  • Committer: cecilios
  • Date: 2007-05-19 11:39:03 UTC
  • Revision ID: svn-v4:2587a929-2f0e-0410-ae78-fe6f687d5efe:trunk:236

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
//---------------------------------------------------------------------------------------
2
 
//    LenMus Phonascus: The teacher of music
3
 
//    Copyright (c) 2002-2012 LenMus project
4
 
//
5
 
//    This program is free software; you can redistribute it and/or modify it under the
6
 
//    terms of the GNU General Public License as published by the Free Software Foundation,
7
 
//    either version 3 of the License, or (at your option) any later version.
8
 
//
9
 
//    This program is distributed in the hope that it will be useful, but WITHOUT ANY
10
 
//    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
11
 
//    PARTICULAR PURPOSE.  See the GNU General Public License for more details.
12
 
//
13
 
//    You should have received a copy of the GNU General Public License along with this
14
 
//    program. If not, see <http://www.gnu.org/licenses/>.
15
 
//
16
 
//    For any comment, suggestion or feature request, please contact the manager of
17
 
//    the project at cecilios@users.sourceforge.net
18
 
//
19
 
//---------------------------------------------------------------------------------------
20
 
 
21
 
#include "lenmus_book_reader.h"
22
 
 
23
 
//wxWidgets
24
 
#include <wx/wxprec.h>
25
 
#include <wx/defs.h>
26
 
#include <wx/log.h>
27
 
#include <wx/zipstrm.h>
28
 
 
29
 
 
30
 
namespace lenmus
31
 
{
32
 
 
33
 
 
34
 
//---------------------------------------------------------------------------------------
35
 
static int wxHtmlHelpIndexCompareFunc(BookIndexItem **a, BookIndexItem **b)
36
 
{
37
 
    BookIndexItem *ia = *a;
38
 
    BookIndexItem *ib = *b;
39
 
 
40
 
    if (ia == NULL)
41
 
        return -1;
42
 
    if (ib == NULL)
43
 
        return 1;
44
 
 
45
 
    if (ia->parent == ib->parent)
46
 
    {
47
 
        return ia->title.CmpNoCase(ib->title);
48
 
    }
49
 
    else if (ia->level == ib->level)
50
 
    {
51
 
        return wxHtmlHelpIndexCompareFunc(&ia->parent, &ib->parent);
52
 
    }
53
 
    else
54
 
    {
55
 
        BookIndexItem *ia2 = ia;
56
 
        BookIndexItem *ib2 = ib;
57
 
 
58
 
        while (ia2->level > ib2->level)
59
 
        {
60
 
            ia2 = ia2->parent;
61
 
        }
62
 
        while (ib2->level > ia2->level)
63
 
        {
64
 
            ib2 = ib2->parent;
65
 
        }
66
 
 
67
 
        wxASSERT(ia2);
68
 
        wxASSERT(ib2);
69
 
        int res = wxHtmlHelpIndexCompareFunc(&ia2, &ib2);
70
 
        if (res != 0)
71
 
            return res;
72
 
        else if (ia->level > ib->level)
73
 
            return 1;
74
 
        else
75
 
            return -1;
76
 
    }
77
 
}
78
 
 
79
 
 
80
 
//---------------------------------------------------------------------------------------
81
 
// BookRecord
82
 
//---------------------------------------------------------------------------------------
83
 
 
84
 
BookRecord::BookRecord(const wxString& bookfile, const wxString& basepath,
85
 
                     const wxString& title, const wxString& start)
86
 
{
87
 
    m_sBookFile = bookfile;
88
 
    m_sBasePath = basepath;
89
 
    m_sTitle = title;
90
 
    m_sCoverPage = start;
91
 
    // for debugging, give the contents index obvious default values
92
 
    m_ContentsStart = m_ContentsEnd = -1;
93
 
}
94
 
 
95
 
//---------------------------------------------------------------------------------------
96
 
BookRecord::~BookRecord()
97
 
{
98
 
}
99
 
 
100
 
//---------------------------------------------------------------------------------------
101
 
wxString BookRecord::GetFullPath(const wxString &page) const
102
 
{
103
 
    // returns full filename of page (which is part of the book),
104
 
    // i.e. with book's basePath prepended. If page is already absolute
105
 
    // path, basePath is _not_ prepended.
106
 
 
107
 
    if (page != _T(""))
108
 
    {
109
 
        if (wxIsAbsolutePath(page))
110
 
            return page;
111
 
        else
112
 
            return m_sBasePath + page;
113
 
        }
114
 
    else
115
 
        return wxEmptyString;
116
 
}
117
 
 
118
 
//---------------------------------------------------------------------------------------
119
 
// BookIndexItem
120
 
//---------------------------------------------------------------------------------------
121
 
 
122
 
wxString BookIndexItem::GetIndentedName() const
123
 
{
124
 
    wxString s;
125
 
    for (int i = 1; i < level; i++)
126
 
        s << _T("   ");
127
 
    s << title;
128
 
    return s;
129
 
}
130
 
 
131
 
 
132
 
//---------------------------------------------------------------------------------------
133
 
// BookReader
134
 
// BookReader object stores and manages all book indexes.
135
 
// Html pages are not processed. When a page display is requested, the page is
136
 
// directtly loaded by the wxHtmlWindowd, LoadPage() method.
137
 
//---------------------------------------------------------------------------------------
138
 
BookReader::BookReader()
139
 
{
140
 
    m_pParser = LENMUS_NEW XmlParser();
141
 
}
142
 
 
143
 
//---------------------------------------------------------------------------------------
144
 
BookReader::~BookReader()
145
 
{
146
 
    delete m_pParser;
147
 
    int i;
148
 
    for(i = m_bookRecords.GetCount(); i > 0; i--) {
149
 
        delete m_bookRecords[i-1];
150
 
        m_bookRecords.RemoveAt(i-1);
151
 
    }
152
 
    for (i = m_index.GetCount(); i > 0; i--) {
153
 
        delete m_index[i-1];
154
 
        m_index.RemoveAt(i-1);
155
 
    }
156
 
    for(i = m_contents.GetCount(); i > 0; i--) {
157
 
        delete m_contents[i-1];
158
 
        m_contents.RemoveAt(i-1);
159
 
    }
160
 
    for(i = m_pagelist.GetCount(); i > 0; i--) {
161
 
        delete m_pagelist[i-1];
162
 
        m_pagelist.RemoveAt(i-1);
163
 
    }
164
 
 
165
 
}
166
 
 
167
 
//---------------------------------------------------------------------------------------
168
 
void BookReader::SetTempDir(const wxString& path)
169
 
{
170
 
    if (path.empty())
171
 
        m_tempPath = path;
172
 
    else
173
 
    {
174
 
        if (wxIsAbsolutePath(path)) m_tempPath = path;
175
 
        else m_tempPath = wxGetCwd() + _T("/") + path;
176
 
 
177
 
        if (m_tempPath[m_tempPath.length() - 1] != _T('/'))
178
 
            m_tempPath << _T('/');
179
 
    }
180
 
}
181
 
 
182
 
//---------------------------------------------------------------------------------------
183
 
bool BookReader::AddBook(const wxFileName& oFilename)
184
 
{
185
 
    //Reads a book (either a .lmb or .toc file) and loads its content
186
 
    //Returns true if success.
187
 
 
188
 
   if (oFilename.GetExt() == _T("lmb")) {
189
 
        //add html page names to the pagelist table
190
 
        AddBookPagesToList(oFilename);
191
 
    }
192
 
 
193
 
    // Process the TOC file (.toc)
194
 
    BookRecord* pBookr = ProcessTOCFile(oFilename);
195
 
    if (!pBookr) {
196
 
        return false;       //error
197
 
    }
198
 
 
199
 
    // process an optional index file
200
 
    wxFileName* pFN = LENMUS_NEW wxFileName(oFilename);
201
 
    pFN->SetExt(_T("idx"));
202
 
    bool fSuccess = true;
203
 
    if (pFN->FileExists())
204
 
        fSuccess = ProcessIndexFile(*pFN, pBookr);
205
 
 
206
 
    delete pFN;
207
 
    return fSuccess;
208
 
}
209
 
 
210
 
//---------------------------------------------------------------------------------------
211
 
bool BookReader::AddBookPagesToList(const wxFileName& oFilename)
212
 
{
213
 
    // Returns true if error.
214
 
//    wxLogMessage(_T("[BookReader::AddBookPagesToList] starting"));
215
 
 
216
 
    // open the zip file
217
 
    wxString sBookPath = oFilename.GetFullPath();
218
 
    wxFFileInputStream in(sBookPath);
219
 
    wxZipInputStream zip(in);
220
 
    if (!zip.IsOk()) {
221
 
        wxLogMessage(_T("[BookReader::AddBookPagesToList] Loading eBook. Error: can not open file '%s'."),
222
 
            sBookPath.c_str());
223
 
        return true;   //error
224
 
    }
225
 
 
226
 
    // loop to get all files
227
 
    wxZipEntry* pEntry = zip.GetNextEntry();
228
 
    while (pEntry)
229
 
    {
230
 
        //get its name
231
 
        wxString sPageName = pEntry->GetName();
232
 
        if (sPageName.Find(_T(".lms")) != wxNOT_FOUND) {
233
 
            //add entry to pagelist
234
 
//            wxLogMessage(_T("[BookReader::AddBookPagesToList] Adding page '%s'"), sPageName.c_str());
235
 
            lmPageIndexItem *pItem = LENMUS_NEW lmPageIndexItem();
236
 
            pItem->page = sPageName;
237
 
            pItem->book = sBookPath;
238
 
            m_pagelist.Add(pItem);
239
 
        }
240
 
        delete pEntry;      //we have ownership of entry object
241
 
        pEntry = zip.GetNextEntry();
242
 
    }
243
 
 
244
 
    return false;   //no error
245
 
 
246
 
}
247
 
 
248
 
//---------------------------------------------------------------------------------------
249
 
bool BookReader::ProcessIndexFile(const wxFileName& oFilename, BookRecord* pBookr)
250
 
{
251
 
    // Returns true if success.
252
 
 
253
 
 
254
 
//    wxLogMessage(_T("[BookReader::ProcessIndexFile] Processing file %s"),
255
 
//            oFilename.GetFullPath().c_str() );
256
 
 
257
 
    wxString sTitle = _T(""),
258
 
             sDefaultPage = _T(""),
259
 
             sContentsFile = _T(""),
260
 
             sIndexFile = _T("");
261
 
 
262
 
    // load the XML file as tree of nodes
263
 
    wxXmlDocument xdoc;
264
 
    if (!xdoc.Load(oFilename.GetFullPath()) ) {
265
 
        wxLogMessage(_T("[BookReader::ProcessIndexFile] Loading eBook. Error parsing index file %s"),
266
 
            oFilename.GetFullPath().c_str() );
267
 
        return false;   //error
268
 
    }
269
 
 
270
 
    //Verify type of document. Must be <BookIndex>
271
 
    wxXmlNode *pNode = xdoc.GetRoot();
272
 
    wxString sTag = _T("BookIndex");
273
 
    wxString sElement = pNode->GetName();
274
 
    if (sElement != sTag) {
275
 
        wxLogMessage(_T("[BookReader::ProcessIndexFile] Loading eBook. Error: First tag is not <%s> but <%s>"),
276
 
            sTag.c_str(), sElement.c_str());
277
 
        return false;   //error
278
 
    }
279
 
 
280
 
    //process children nodes: <entry>
281
 
    pNode = m_pParser->GetFirstChild(pNode);
282
 
    wxXmlNode* pElement = pNode;
283
 
    sElement = pElement->GetName();
284
 
    sTag = _T("entry");
285
 
    if (sElement != sTag) {
286
 
        wxLogMessage(_T("[BookReader::ProcessIndexFile] Loading eBook. Error: Expected tag <%s> but found <%s>"),
287
 
            sTag.c_str(), sElement.c_str());
288
 
        return false;   //error
289
 
    }
290
 
    ProcessIndexEntries(pElement, pBookr);
291
 
 
292
 
    // Sort index table
293
 
    if (!m_index.empty()) {
294
 
        m_index.Sort(wxHtmlHelpIndexCompareFunc);
295
 
    }
296
 
 
297
 
    return true;
298
 
}
299
 
 
300
 
 
301
 
//---------------------------------------------------------------------------------------
302
 
void BookReader::ProcessIndexEntries(wxXmlNode* pNode, BookRecord *pBookr)
303
 
{
304
 
    // Parse the index entries and adds its data to the m_index array
305
 
    // pNode points to <entry> node
306
 
 
307
 
    //get first index entry
308
 
    wxXmlNode* pElement = pNode;
309
 
    wxString sTag = _T("entry");
310
 
    while (pElement) {
311
 
        if (sTag == pElement->GetName()) {
312
 
            BookIndexItem *pItem = LENMUS_NEW BookIndexItem();
313
 
            pItem->parent = NULL;
314
 
            pItem->level = 1;               //todo
315
 
            pItem->id = m_pParser->GetAttribute(pElement, _T("id"));
316
 
            pItem->page = m_pParser->GetAttribute(pElement, _T("page"));
317
 
            pItem->title = m_pParser->GetText(pElement);
318
 
            pItem->titlenum = _T("");
319
 
            pItem->image = _T("");
320
 
            pItem->pBookRecord = pBookr;
321
 
            m_index.Add(pItem);
322
 
        }
323
 
 
324
 
        // Find next entry
325
 
        pNode = m_pParser->GetNextSibling(pNode);
326
 
        pElement = pNode;
327
 
    }
328
 
 
329
 
}
330
 
 
331
 
//---------------------------------------------------------------------------------------
332
 
BookRecord* BookReader::ProcessTOCFile(const wxFileName& oFilename)
333
 
{
334
 
    // Returns ptr to created book record if success, NULL if failure
335
 
 
336
 
//    wxLogMessage(_T("[BookReader::ProcessTOCFile] Processing file %s"),
337
 
//                 oFilename.GetFullPath().c_str());
338
 
 
339
 
    wxString sTitle = _T(""),
340
 
             sPage = _T(""),
341
 
             sContents = _T(""),
342
 
             sIndex = _T("");
343
 
 
344
 
 
345
 
    // wxXmlDocument::Load(filename) uses a wxTextStreamFile and it doesn't support
346
 
    // virtual files. So, when using LMB files we have to allocate
347
 
    // a wxZipTextStream and pass it to wxXmlDocument::Load(stream)
348
 
    wxXmlDocument xdoc;
349
 
    bool fOK;
350
 
    wxString sFullName, sFileName, sPath, sNameExt;
351
 
    if (oFilename.GetExt() == _T("toc"))
352
 
    {
353
 
        sFullName = oFilename.GetFullPath();
354
 
        sFileName = oFilename.GetName();
355
 
        sPath = oFilename.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR , wxPATH_NATIVE);
356
 
        fOK = xdoc.Load(sFullName);
357
 
    }
358
 
    else if (oFilename.GetExt() == _T("lmb"))
359
 
    {
360
 
        //lenmus compressed book (zip file)
361
 
        sFileName = oFilename.GetName();
362
 
        sPath = oFilename.GetFullPath() + _T("#zip:");
363
 
        sNameExt = sFileName + _T(".toc");
364
 
        sFullName = sPath + sNameExt;
365
 
 
366
 
        // convert the local name we are looking for into the zip internal format
367
 
        wxString sInternalName = wxZipEntry::GetInternalName( sNameExt );
368
 
 
369
 
        // open the zip
370
 
        wxFFileInputStream in( oFilename.GetFullPath() );
371
 
        wxZipInputStream zip(in);
372
 
        if (!zip.IsOk()) {
373
 
            wxLogMessage(_T("[BookReader::ProcessTOCFile] Loading eBook. Error: TOC file '%s' not found."),
374
 
                oFilename.GetFullPath().c_str());
375
 
            return (BookRecord*) NULL;   //error
376
 
        }
377
 
 
378
 
        // call GetNextEntry() until the required internal name is found
379
 
        wxZipEntry* pEntry = (wxZipEntry*)NULL;
380
 
        do {
381
 
            if (pEntry) delete pEntry;      //delete previous entry
382
 
            pEntry = zip.GetNextEntry();    //now we have ownership of object *pEntry
383
 
        }
384
 
        while (pEntry && pEntry->GetInternalName() != sInternalName);
385
 
 
386
 
        if (!pEntry) {
387
 
            wxLogMessage(_T("[BookReader::ProcessTOCFile] Loading eBook. Error: TOC file '%s' not found."),
388
 
                sFullName.c_str());
389
 
            return (BookRecord*) NULL;   //error
390
 
        }
391
 
        zip.OpenEntry(*pEntry);
392
 
        fOK = xdoc.Load(zip);    //asumes utf-8
393
 
        zip.CloseEntry();
394
 
        delete pEntry;
395
 
    }
396
 
    else {
397
 
        wxLogMessage(_T("[BookReader::ProcessTOCFile] Loading eBook. Error in TOC file '%s'. Extension is neither LMB nor TOC."),
398
 
            oFilename.GetFullPath().c_str());
399
 
        return (BookRecord*) NULL;   //error
400
 
    }
401
 
 
402
 
    // load the XML file as tree of nodes
403
 
    if (!fOK)
404
 
    {
405
 
        wxLogMessage(_T("[BookReader::ProcessTOCFile] Loading eBook. Error parsing TOC file ") + sFullName);
406
 
        return (BookRecord*) NULL;   //error
407
 
    }
408
 
 
409
 
    //Verify type of document. Must be <BookTOC>
410
 
    wxXmlNode *pNode = xdoc.GetRoot();
411
 
    wxString sTag = _T("lmBookTOC");
412
 
    wxString sElement = pNode->GetName();
413
 
    if (sElement != sTag) {
414
 
        wxLogMessage(_T("[BookReader::ProcessTOCFile] Loading eBook. Error: First tag is not <%s> but <%s>"),
415
 
            sTag.c_str(), sElement.c_str());
416
 
        return (BookRecord*) NULL;   //error
417
 
    }
418
 
 
419
 
    // firts node: title
420
 
    pNode = m_pParser->GetFirstChild(pNode);
421
 
    wxXmlNode* pElement = pNode;
422
 
    sElement = pElement->GetName();
423
 
    sTag = _T("title");
424
 
    if (sElement != sTag) {
425
 
        wxLogMessage(_T("[BookReader::ProcessTOCFile] Loading eBook. Error: Expected tag <%s> but found <%s>"),
426
 
            sTag.c_str(), sElement.c_str());
427
 
        return (BookRecord*) NULL;   //error
428
 
    }
429
 
    sTitle = m_pParser->GetText(pNode);
430
 
 
431
 
    // next node: coverpage
432
 
    pNode = m_pParser->GetNextSibling(pNode);
433
 
    pElement = pNode;
434
 
    sElement = pElement->GetName();
435
 
    sTag = _T("coverpage");
436
 
    if (sElement != sTag) {
437
 
        wxLogMessage(_T("[BookReader::ProcessTOCFile] Loading eBook. Error: Expected tag <%s> but found <%s>"),
438
 
            sTag.c_str(), sElement.c_str());
439
 
        return (BookRecord*) NULL;   //error
440
 
    }
441
 
    sPage = m_pParser->GetText(pNode);
442
 
 
443
 
    //Create the book record object
444
 
    BookRecord *pBookr;
445
 
    pBookr = LENMUS_NEW BookRecord(sFileName, sPath, sTitle, sPage);
446
 
 
447
 
    // creates the book entry in the contents table
448
 
    int nContentStart = m_contents.size();          // save the contents index for later
449
 
    BookIndexItem *bookitem = LENMUS_NEW BookIndexItem;
450
 
    bookitem->level = 0;
451
 
    bookitem->id = _T("");
452
 
    bookitem->page = sPage;
453
 
    bookitem->title = sTitle;
454
 
    bookitem->titlenum = _T("");
455
 
    bookitem->image = _T("");
456
 
    bookitem->pBookRecord = pBookr;
457
 
    m_contents.Add(bookitem);
458
 
 
459
 
    //process other children nodes: <entry>
460
 
    pNode = m_pParser->GetNextSibling(pNode);
461
 
    pElement = pNode;
462
 
    sTag = _T("entry");
463
 
    while (pElement) {
464
 
        sElement = pElement->GetName();
465
 
        if (sElement != sTag) {
466
 
            wxLogMessage(_T("[BookReader::ProcessTOCFile] Loading eBook. Error: Expected tag <%s> but found <%s>"),
467
 
                sTag.c_str(), sElement.c_str());
468
 
            delete pBookr;
469
 
            return (BookRecord*) NULL;   //error
470
 
        }
471
 
        if (!ProcessTOCEntry(pElement, pBookr, 1)) return false;     //error
472
 
 
473
 
        // get next entry
474
 
        pNode = m_pParser->GetNextSibling(pNode);
475
 
        pElement = pNode;
476
 
    }
477
 
 
478
 
    // store the contents range in the book record
479
 
    pBookr->SetContentsRange(nContentStart, m_contents.size());
480
 
 
481
 
    // Add the LENMUS_NEW book record to the table
482
 
    m_bookRecords.Add(pBookr);
483
 
 
484
 
    return pBookr;        // no error
485
 
}
486
 
 
487
 
//---------------------------------------------------------------------------------------
488
 
bool BookReader::ProcessTOCEntry(wxXmlNode* pNode, BookRecord *pBookr, int nLevel)
489
 
{
490
 
    // Parse one entry. Recursive for sub-entries
491
 
    // Add entry data to the m_contents array
492
 
 
493
 
        //process children nodes
494
 
 
495
 
    wxString sTitle = _T(""),
496
 
             sPage = _T(""),
497
 
             sName = _T(""),
498
 
             sImage = _T(""),
499
 
             sTitlenum = _T(""),
500
 
             sId = _T("");
501
 
 
502
 
    // Get entry id
503
 
    sId = m_pParser->GetAttribute(pNode, _T("id"));
504
 
 
505
 
    // process children
506
 
    pNode = m_pParser->GetFirstChild(pNode);
507
 
    wxXmlNode* pElement = pNode;
508
 
    bool fTitleImage = false;        //to control that title or image exists
509
 
    wxString sElement;
510
 
    while (pElement)
511
 
    {
512
 
        sElement = pElement->GetName();
513
 
        if (sElement == _T("image")) {
514
 
            sImage = m_pParser->GetText(pElement);
515
 
            fTitleImage = true;
516
 
        }
517
 
        else if (sElement == _T("title")) {
518
 
            sTitle = m_pParser->GetText(pElement);
519
 
            fTitleImage = true;
520
 
            #ifdef _MBCS    //if Win95/98/Me release
521
 
                //change encoding from utf-8 to local encoding
522
 
                wxCSConv conv(_T("utf-8"));
523
 
                sTitle = wxString(sTitle.wc_str(conv), convLocal);     //wxConvLocal);
524
 
            #endif
525
 
        }
526
 
        else if (sElement == _T("page")) {
527
 
            sPage = m_pParser->GetText(pElement);
528
 
        }
529
 
        else if (sElement == _T("titlenum")) {
530
 
            sTitlenum = m_pParser->GetText(pElement);
531
 
        }
532
 
        else {
533
 
            break;
534
 
        }
535
 
        pNode = m_pParser->GetNextSibling(pNode);
536
 
        pElement = pNode;
537
 
    }
538
 
    if (!fTitleImage) {
539
 
        wxLogMessage(_T("[BookReader::ProcessTOCEntry] Loading eBook. Error: Expected tag <title>/<Image> but none of them found."));
540
 
        return false;   //error
541
 
    }
542
 
 
543
 
    // create the entry in the contents table
544
 
    BookIndexItem *bookitem = LENMUS_NEW BookIndexItem;
545
 
    bookitem->level = nLevel;
546
 
    bookitem->id = sId;
547
 
    bookitem->page = sPage;
548
 
    bookitem->title = sTitle;
549
 
    bookitem->titlenum = sTitlenum;
550
 
    bookitem->image = sImage;
551
 
    bookitem->pBookRecord = pBookr;
552
 
    m_contents.Add(bookitem);
553
 
 
554
 
    //process sub-entries, if exist
555
 
    nLevel++;
556
 
    wxString sTag = _T("entry");
557
 
    while (pElement)
558
 
    {
559
 
        sElement = pElement->GetName();
560
 
        if (sElement != sTag) {
561
 
            wxLogMessage(_T("[BookReader::ProcessTOCEntry] Loading eBook. Error: Expected tag <%s> but found <%s>"),
562
 
                sTag.c_str(), sElement.c_str());
563
 
            return false;   //error
564
 
        }
565
 
        if (!ProcessTOCEntry(pElement, pBookr, nLevel)) return false;     //error
566
 
 
567
 
        // get next
568
 
        pNode = m_pParser->GetNextSibling(pNode);
569
 
        pElement = pNode;
570
 
    }
571
 
 
572
 
    return true;        // no error
573
 
 
574
 
}
575
 
 
576
 
 
577
 
//---------------------------------------------------------------------------------------
578
 
wxString BookReader::FindPageByName(const wxString& x)
579
 
{
580
 
    // Find a page:
581
 
    // - By book filename: i.e. 'SingleExercises.lmb' (returns the cover page)
582
 
    // - By page filename: i.e. 'SingleExercises_ch0.lms'
583
 
    // - By page title: i.e. 'Exercises for aural training'
584
 
    // - By index enty:
585
 
    //
586
 
    // Returns the url to the page (the full path)
587
 
    //    i.e. 'c:\lenmus\books\en\SingleExercises.lmb#zip:SingleExercises_ch0.lms'
588
 
 
589
 
    int i;
590
 
    wxFileSystem fsys;
591
 
    wxFSFile* pFile;
592
 
 
593
 
    // 1. try to interpret x as a file name (i.e. 'SingleExercises.lmb')
594
 
    if (x.Right(4) == _T(".lmb")) {
595
 
        // Try to open it
596
 
        int nNumBooks = m_bookRecords.GetCount();
597
 
        for (i = 0; i < nNumBooks; i++)
598
 
        {
599
 
            pFile = fsys.OpenFile(m_bookRecords[i]->GetFullPath(x));
600
 
            if (pFile) {
601
 
                wxString url = m_bookRecords[i]->GetFullPath(m_bookRecords[i]->GetCoverPage());
602
 
                delete pFile;
603
 
                return url;
604
 
            }
605
 
        }
606
 
    }
607
 
 
608
 
    // 2. Try to interpret x as the filename of a book page (i.e. 'SingleExercises_0.lms')
609
 
    if (x.Right(4) == _T(".lms")) {
610
 
        // Try to find the book page
611
 
        int nNumEntries = m_pagelist.size();
612
 
        for (i = 0; i < nNumEntries; i++)
613
 
        {
614
 
            //wxLogMessage(_T("[BookReader::FindPageByName] page %d, name = %s"),
615
 
            //    i, (m_pagelist[i]->page).c_str() );
616
 
            if (m_pagelist[i]->page == x)
617
 
                return m_pagelist[i]->GetFullPath();
618
 
        }
619
 
    }
620
 
 
621
 
    // 3. Try to interpret it as a title, and so try find in toc (i.e. 'Exercises for
622
 
    //    aural training'). This is the less secure method as titles can be repeated
623
 
    //    in different books. In these cases this will retutn the first one found
624
 
    int nNumEntries = m_contents.size();
625
 
    for (i = 0; i < nNumEntries; i++)
626
 
    {
627
 
        if (m_contents[i]->title == x)
628
 
            return m_contents[i]->GetFullPath();
629
 
    }
630
 
 
631
 
    // 4. try to find it in index
632
 
    nNumEntries = m_index.size();
633
 
    for (i = 0; i < nNumEntries; i++)
634
 
    {
635
 
        if (m_index[i]->title == x)
636
 
            return m_index[i]->GetFullPath();
637
 
    }
638
 
 
639
 
    //wxLogMessage(_T("[BookReader::FindPageByName] Page '%s' not found."), x.c_str());
640
 
    return _T("");
641
 
}
642
 
 
643
 
//---------------------------------------------------------------------------------------
644
 
wxString BookReader::FindPageById(int id)
645
 
{
646
 
    //size_t cnt = m_contents.size();
647
 
    //for (size_t i = 0; i < cnt; i++)
648
 
    //{
649
 
    //    if (m_contents[i].id == id)
650
 
    //    {
651
 
    //        return m_contents[i].GetFullPath();
652
 
    //    }
653
 
    //}
654
 
 
655
 
    return _T("");
656
 
}
657
 
 
658
 
 
659
 
////---------------------------------------------------------------------------------------
660
 
//// lmSearchStatus functions
661
 
////---------------------------------------------------------------------------------------
662
 
//
663
 
//lmSearchStatus::lmSearchStatus(BookReader* data, const wxString& keyword,
664
 
//                                       bool case_sensitive, bool whole_words_only,
665
 
//                                       const wxString& book)
666
 
//{
667
 
//    m_Data = data;
668
 
//    m_Keyword = keyword;
669
 
//    BookRecord* bookr = NULL;
670
 
//    if (book != _T(""))
671
 
//    {
672
 
//        // we have to search in a specific book. Find it first
673
 
//        int i, cnt = data->m_bookRecords.GetCount();
674
 
//        for (i = 0; i < cnt; i++)
675
 
//            if (data->m_bookRecords[i]->GetTitle() == book)
676
 
//            {
677
 
//                bookr = data->m_bookRecords[i];
678
 
//                m_CurIndex = bookr->GetContentsStart();
679
 
//                m_MaxIndex = bookr->GetContentsEnd();
680
 
//                break;
681
 
//            }
682
 
//        // check; we won't crash if the book doesn't exist, but it's Bad Anyway.
683
 
//        wxASSERT(bookr);
684
 
//    }
685
 
//    if (! bookr)
686
 
//    {
687
 
//        // no book specified; search all books
688
 
//        m_CurIndex = 0;
689
 
//        m_MaxIndex = m_Data->m_contents.size();
690
 
//    }
691
 
//    m_Engine.LookFor(keyword, case_sensitive, whole_words_only);
692
 
//    m_Active = (m_CurIndex < m_MaxIndex);
693
 
//}
694
 
//
695
 
////---------------------------------------------------------------------------------------
696
 
//bool lmSearchStatus::Search()
697
 
//{
698
 
//    //wxFSFile *file;
699
 
//    //int i = m_CurIndex;  // shortcut
700
 
//    //bool found = false;
701
 
//    //wxString thepage;
702
 
//
703
 
//    //if (!m_Active)
704
 
//    //{
705
 
//    //    // sanity check. Illegal use, but we'll try to prevent a crash anyway
706
 
//    //    wxASSERT(m_Active);
707
 
//    //    return false;
708
 
//    //}
709
 
//
710
 
//    //m_Name = _T("");
711
 
//    //m_CurItem = NULL;
712
 
//    //thepage = m_Data->m_contents[i].page;
713
 
//
714
 
//    //m_Active = (++m_CurIndex < m_MaxIndex);
715
 
//    //// check if it is same page with different anchor:
716
 
//    //if (!m_LastPage.empty())
717
 
//    //{
718
 
//    //    const wxChar *p1, *p2;
719
 
//    //    for (p1 = thepage.c_str(), p2 = m_LastPage.c_str();
720
 
//    //         *p1 != 0 && *p1 != _T('#') && *p1 == *p2; p1++, p2++) {}
721
 
//
722
 
//    //    m_LastPage = thepage;
723
 
//
724
 
//    //    if (*p1 == 0 || *p1 == _T('#'))
725
 
//    //        return false;
726
 
//    //}
727
 
//    //else m_LastPage = thepage;
728
 
//
729
 
//    //wxFileSystem fsys;
730
 
//    //file = fsys.OpenFile(m_Data->m_contents[i].pBookRecord->GetFullPath(thepage));
731
 
//    //if (file)
732
 
//    //{
733
 
//    //    if (m_Engine.Scan(*file))
734
 
//    //    {
735
 
//    //        m_Name = m_Data->m_contents[i].title;
736
 
//    //        m_CurItem = &m_Data->m_contents[i];
737
 
//    //        found = true;
738
 
//    //    }
739
 
//    //    delete file;
740
 
//    //}
741
 
//    //return found;
742
 
//    return false;
743
 
//}
744
 
//
745
 
//
746
 
//
747
 
//
748
 
//
749
 
//
750
 
//
751
 
//
752
 
////---------------------------------------------------------------------------------------
753
 
//// BookSearchEngine
754
 
////---------------------------------------------------------------------------------------
755
 
//
756
 
//void BookSearchEngine::LookFor(const wxString& keyword, bool case_sensitive, bool whole_words_only)
757
 
//{
758
 
//    m_CaseSensitive = case_sensitive;
759
 
//    m_WholeWords = whole_words_only;
760
 
//    m_Keyword = keyword;
761
 
//
762
 
//    if (!m_CaseSensitive)
763
 
//        m_Keyword.MakeLower();
764
 
//}
765
 
//
766
 
//
767
 
//static inline bool WHITESPACE(wxChar c)
768
 
//{
769
 
//    return c == _T(' ') || c == _T('\n') || c == _T('\r') || c == _T('\t');
770
 
//}
771
 
//
772
 
////---------------------------------------------------------------------------------------
773
 
//bool BookSearchEngine::Scan(const wxFSFile& file)
774
 
//{
775
 
//    //wxASSERT_MSG(!m_Keyword.empty(), wxT("BookSearchEngine::LookFor must be called before scanning!"));
776
 
//
777
 
//    //int i, j;
778
 
//    //int wrd = m_Keyword.length();
779
 
//    //bool found = false;
780
 
//    //wxHtmlFilterHTML filter;
781
 
//    //wxString tmp = filter.ReadFile(file);
782
 
//    //int lng = tmp.length();
783
 
//    //const wxChar *buf = tmp.c_str();
784
 
//
785
 
//    //if (!m_CaseSensitive)
786
 
//    //    tmp.MakeLower();
787
 
//
788
 
//    //const wxChar *kwd = m_Keyword.c_str();
789
 
//
790
 
//    //if (m_WholeWords)
791
 
//    //{
792
 
//    //    for (i = 0; i < lng - wrd; i++)
793
 
//    //    {
794
 
//    //        if (WHITESPACE(buf[i])) continue;
795
 
//    //        j = 0;
796
 
//    //        while ((j < wrd) && (buf[i + j] == kwd[j])) j++;
797
 
//    //        if (j == wrd && WHITESPACE(buf[i + j])) { found = true; break; }
798
 
//    //    }
799
 
//    //}
800
 
//
801
 
//    //else
802
 
//    //{
803
 
//    //    for (i = 0; i < lng - wrd; i++)
804
 
//    //    {
805
 
//    //        j = 0;
806
 
//    //        while ((j < wrd) && (buf[i + j] == kwd[j])) j++;
807
 
//    //        if (j == wrd) { found = true; break; }
808
 
//    //    }
809
 
//    //}
810
 
//
811
 
//    //return found;
812
 
//    return false;
813
 
//}
814
 
 
815
 
 
816
 
}   //namespace lenmus