summaryrefslogtreecommitdiffstats
path: root/fbreader/src/bookmodel/BookReader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'fbreader/src/bookmodel/BookReader.cpp')
-rw-r--r--fbreader/src/bookmodel/BookReader.cpp303
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();
+}