diff options
Diffstat (limited to 'fbreader/src/bookmodel/BookReader.cpp')
-rw-r--r-- | fbreader/src/bookmodel/BookReader.cpp | 303 |
1 files changed, 303 insertions, 0 deletions
diff --git a/fbreader/src/bookmodel/BookReader.cpp b/fbreader/src/bookmodel/BookReader.cpp new file mode 100644 index 0000000..2982c43 --- /dev/null +++ b/fbreader/src/bookmodel/BookReader.cpp @@ -0,0 +1,303 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus <contact@geometerplus.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include <ZLImage.h> +#include <ZLLogger.h> +#include <ZLTextStyleEntry.h> + +#include "BookReader.h" +#include "BookModel.h" + +#include "../library/Book.h" + +BookReader::BookReader(BookModel &model) : myModel(model) { + myCurrentTextModel = 0; + myLastTOCParagraphIsEmpty = false; + + myContentsParagraphExists = false; + + myInsideTitle = false; + mySectionContainsRegularContents = false; +} + +BookReader::~BookReader() { +} + +void BookReader::setMainTextModel() { + myCurrentTextModel = myModel.myBookTextModel; +} + +void BookReader::setFootnoteTextModel(const std::string &id) { + std::map<std::string,shared_ptr<ZLTextModel> >::iterator it = myModel.myFootnotes.find(id); + if (it != myModel.myFootnotes.end()) { + myCurrentTextModel = (*it).second; + } else { + myCurrentTextModel = new ZLTextPlainModel(myModel.myBookTextModel->language(), 8192); + myModel.myFootnotes.insert(std::make_pair(id, myCurrentTextModel)); + } +} + +bool BookReader::paragraphIsOpen() const { + if (myCurrentTextModel.isNull()) { + return false; + } + for (std::list<shared_ptr<ZLTextModel> >::const_iterator it = myModelsWithOpenParagraphs.begin(); it != myModelsWithOpenParagraphs.end(); ++it) { + if (*it == myCurrentTextModel) { + return true; + } + } + return false; +} + +void BookReader::unsetTextModel() { + myCurrentTextModel.reset(); +} + +void BookReader::pushKind(FBTextKind kind) { + myKindStack.push_back(kind); +} + +bool BookReader::popKind() { + if (!myKindStack.empty()) { + myKindStack.pop_back(); + return true; + } + return false; +} + +bool BookReader::isKindStackEmpty() const { + return myKindStack.empty(); +} + +void BookReader::beginParagraph(ZLTextParagraph::Kind kind) { + endParagraph(); + if (myCurrentTextModel != 0) { + ((ZLTextPlainModel&)*myCurrentTextModel).createParagraph(kind); + for (std::vector<FBTextKind>::const_iterator it = myKindStack.begin(); it != myKindStack.end(); ++it) { + myCurrentTextModel->addControl(*it, true); + } + if (!myHyperlinkReference.empty()) { + myCurrentTextModel->addHyperlinkControl(myHyperlinkKind, myHyperlinkType, myHyperlinkReference); + } + myModelsWithOpenParagraphs.push_back(myCurrentTextModel); + } +} + +void BookReader::endParagraph() { + if (paragraphIsOpen()) { + flushTextBufferToParagraph(); + myModelsWithOpenParagraphs.remove(myCurrentTextModel); + } +} + +void BookReader::addControl(FBTextKind kind, bool start) { + if (paragraphIsOpen()) { + flushTextBufferToParagraph(); + myCurrentTextModel->addControl(kind, start); + } + if (!start && !myHyperlinkReference.empty() && (kind == myHyperlinkKind)) { + myHyperlinkReference.erase(); + } +} + +void BookReader::addStyleEntry(const ZLTextStyleEntry &entry) { + if (paragraphIsOpen()) { + flushTextBufferToParagraph(); + myCurrentTextModel->addStyleEntry(entry); + } +} + +void BookReader::addStyleCloseEntry() { + addControl(REGULAR, false); //used instead in XHTMLReader + //TODO implement ZLTextModel::addStyleCloseEntry() +// if (paragraphIsOpen()) { +// flushTextBufferToParagraph(); +// myCurrentTextModel->addStyleCloseEntry(); +// } +} + +void BookReader::addFixedHSpace(unsigned char length) { + if (paragraphIsOpen()) { + flushTextBufferToParagraph(); + myCurrentTextModel->addFixedHSpace(length); + } +} + +void BookReader::addHyperlinkControl(FBTextKind kind, const std::string &label) { + myHyperlinkKind = kind; + std::string type; + switch (myHyperlinkKind) { + case INTERNAL_HYPERLINK: + case FOOTNOTE: + myHyperlinkType = HYPERLINK_INTERNAL; + type = "internal"; + break; + case EXTERNAL_HYPERLINK: + myHyperlinkType = HYPERLINK_EXTERNAL; + type = "external"; + break; + case BOOK_HYPERLINK: + myHyperlinkType = HYPERLINK_BOOK; + type = "book"; + break; + default: + myHyperlinkType = HYPERLINK_NONE; + break; + } + ZLLogger::Instance().println( + "hyperlink", + " + control (" + type + "): " + label + ); + if (paragraphIsOpen()) { + flushTextBufferToParagraph(); + myCurrentTextModel->addHyperlinkControl(kind, myHyperlinkType, label); + } + myHyperlinkReference = label; +} + +void BookReader::addHyperlinkLabel(const std::string &label) { + if (!myCurrentTextModel.isNull()) { + int paragraphNumber = myCurrentTextModel->paragraphsNumber(); + if (paragraphIsOpen()) { + --paragraphNumber; + } + addHyperlinkLabel(label, paragraphNumber); + } +} + +void BookReader::addHyperlinkLabel(const std::string &label, int paragraphNumber) { + ZLLogger::Instance().println( + "hyperlink", + " + label: " + label + ); + myModel.myInternalHyperlinks.insert(std::make_pair( + label, BookModel::Label(myCurrentTextModel, paragraphNumber) + )); +} + +void BookReader::addData(const std::string &data) { + if (!data.empty() && paragraphIsOpen()) { + if (!myInsideTitle) { + mySectionContainsRegularContents = true; + } + myBuffer.push_back(data); + } +} + +void BookReader::addContentsData(const std::string &data) { + if (!data.empty() && !myTOCStack.empty()) { + myContentsBuffer.push_back(data); + } +} + +void BookReader::flushTextBufferToParagraph() { + myCurrentTextModel->addText(myBuffer); + myBuffer.clear(); +} + +void BookReader::addImage(const std::string &id, shared_ptr<const ZLImage> image) { + myModel.myImages[id] = image; +} + +void BookReader::insertEndParagraph(ZLTextParagraph::Kind kind) { + if ((myCurrentTextModel != 0) && mySectionContainsRegularContents) { + std::size_t size = myCurrentTextModel->paragraphsNumber(); + if ((size > 0) && (((*myCurrentTextModel)[(std::size_t)-1])->kind() != kind)) { + ((ZLTextPlainModel&)*myCurrentTextModel).createParagraph(kind); + mySectionContainsRegularContents = false; + } + } +} + +void BookReader::insertEndOfSectionParagraph() { + insertEndParagraph(ZLTextParagraph::END_OF_SECTION_PARAGRAPH); +} + +void BookReader::insertEndOfTextParagraph() { + insertEndParagraph(ZLTextParagraph::END_OF_TEXT_PARAGRAPH); +} + +void BookReader::addImageReference(const std::string &id, short vOffset) { + if (myCurrentTextModel != 0) { + mySectionContainsRegularContents = true; + if (paragraphIsOpen()) { + flushTextBufferToParagraph(); + myCurrentTextModel->addImage(id, myModel.imageMap(), vOffset); + } else { + beginParagraph(); + myCurrentTextModel->addControl(IMAGE, true); + myCurrentTextModel->addImage(id, myModel.imageMap(), vOffset); + myCurrentTextModel->addControl(IMAGE, false); + endParagraph(); + } + } +} + +void BookReader::beginContentsParagraph(int referenceNumber) { + if (myCurrentTextModel == myModel.myBookTextModel) { + ContentsModel &contentsModel = (ContentsModel&)*myModel.myContentsModel; + if (referenceNumber == -1) { + referenceNumber = myCurrentTextModel->paragraphsNumber(); + } + ZLTextTreeParagraph *peek = myTOCStack.empty() ? 0 : myTOCStack.top(); + if (!myContentsBuffer.empty()) { + contentsModel.addText(myContentsBuffer); + myContentsBuffer.clear(); + myLastTOCParagraphIsEmpty = false; + } + if (myLastTOCParagraphIsEmpty) { + contentsModel.addText("..."); + } + ZLTextTreeParagraph *para = contentsModel.createParagraph(peek); + contentsModel.addControl(CONTENTS_TABLE_ENTRY, true); + contentsModel.setReference(para, referenceNumber); + myTOCStack.push(para); + myLastTOCParagraphIsEmpty = true; + myContentsParagraphExists = true; + } +} + +void BookReader::endContentsParagraph() { + if (!myTOCStack.empty()) { + ContentsModel &contentsModel = (ContentsModel&)*myModel.myContentsModel; + if (!myContentsBuffer.empty()) { + contentsModel.addText(myContentsBuffer); + myContentsBuffer.clear(); + myLastTOCParagraphIsEmpty = false; + } + if (myLastTOCParagraphIsEmpty) { + contentsModel.addText("..."); + myLastTOCParagraphIsEmpty = false; + } + myTOCStack.pop(); + } + myContentsParagraphExists = false; +} + +void BookReader::setReference(std::size_t contentsParagraphNumber, int referenceNumber) { + ContentsModel &contentsModel = (ContentsModel&)*myModel.myContentsModel; + if (contentsParagraphNumber >= contentsModel.paragraphsNumber()) { + return; + } + contentsModel.setReference((const ZLTextTreeParagraph*)contentsModel[contentsParagraphNumber], referenceNumber); +} + +void BookReader::reset() { + myKindStack.clear(); +} |