gui
[lbook_fbreader.git] / fbreader / src / formats / openreader / ORBookReader.cpp
blobc4aa33c0b259fe326c6a3592c4daeae560354b6c
1 /*
2 * Copyright (C) 2004-2008 Geometer Plus <contact@geometerplus.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
20 #include <string.h>
21 #include <stdlib.h>
23 #include <algorithm>
25 #include <ZLUnicodeUtil.h>
26 #include <ZLFileImage.h>
28 #include "ORBookReader.h"
29 #include "../xhtml/XHTMLReader.h"
30 #include "../util/MiscUtil.h"
31 #include "../../bookmodel/BookModel.h"
33 ORBookReader::ORBookReader(BookModel &model) : myModelReader(model) {
36 void ORBookReader::characterDataHandler(const char *data, int len) {
37 if (myState == READ_TOCTITLE) {
38 myTOCTitle.append(data, len);
42 static const std::string TAG_RESOURCES = "resources";
43 static const std::string TAG_USERSET = "userset";
44 static const std::string TAG_NAVIGATION = "primarynav";
46 static const std::string TAG_SPINE = "spine";
47 static const std::string TAG_COVER = "cover";
49 static const std::string TAG_ITEM = "item";
50 static const std::string TAG_ITEMREF = "itemref";
51 static const std::string TAG_POINTER = "pointer";
52 static const std::string TAG_TITLE = "title";
54 static const std::string xhtmlMediaType = "application/x-orp-bcd1+xml";
56 void ORBookReader::startElementHandler(const char *tag, const char **xmlattributes) {
57 const std::string tagString = ZLUnicodeUtil::toLower(tag);
58 if (TAG_RESOURCES == tagString) {
59 myState = READ_RESOURCES;
60 } else if (TAG_USERSET == tagString) {
61 myState = READ_USERSET;
62 } else if ((myState == READ_RESOURCES) && (TAG_ITEM == tagString)) {
63 const char *resid = attributeValue(xmlattributes, "resid");
64 const char *resource = attributeValue(xmlattributes, "resource");
65 const char *mediaType = attributeValue(xmlattributes, "media-type");
66 if ((resid != 0) && (resource != 0)) {
67 myResources[resid] = resource;
68 if (mediaType != 0) {
69 if (xhtmlMediaType == mediaType) {
70 myHtmlFileIDs.insert(resid);
71 } else if (std::string(mediaType, 6) == "image/") {
72 myImageIDs[resid] = mediaType;
76 } else if (myState == READ_USERSET) {
77 if (TAG_NAVIGATION == tagString) {
78 myState = READ_NAVIGATION;
79 } else if (TAG_SPINE == tagString) {
80 const char *residrefs = attributeValue(xmlattributes, "residrefs");
81 if (residrefs != 0) {
82 while (1) {
83 const char *nextSpace = strchr(residrefs, ' ');
84 if (nextSpace == 0) {
85 if (*residrefs != '\0') {
86 myHtmlFilesOrder.push_back(residrefs);
88 break;
90 if (nextSpace != residrefs) {
91 myHtmlFilesOrder.push_back(std::string(residrefs, nextSpace - residrefs));
93 residrefs = nextSpace + 1;
96 } else if (TAG_COVER == tagString) {
97 const char *residrefs = attributeValue(xmlattributes, "residrefs");
98 if (residrefs != 0) {
99 myCoverReference = residrefs;
102 } else if ((myState == READ_NAVIGATION) && (TAG_POINTER == tagString)) {
103 const char *ref = attributeValue(xmlattributes, "elemrefs");
104 const char *level = attributeValue(xmlattributes, "level");
105 if ((ref != 0) && (level != 0)) {
106 myTOCReference = ref;
107 myTOCLevel = atoi(level);
108 myState = READ_POINTER;
110 } else if ((myState == READ_POINTER) && (TAG_TITLE == tagString)) {
111 myState = READ_TOCTITLE;
115 void ORBookReader::endElementHandler(const char *tag) {
116 const std::string tagString = ZLUnicodeUtil::toLower(tag);
117 if ((TAG_RESOURCES == tagString) || (TAG_USERSET == tagString)) {
118 myState = READ_NONE;
119 } else if ((myState == READ_NAVIGATION) && (TAG_NAVIGATION == tagString)) {
120 myState = READ_USERSET;
121 } else if ((myState == READ_POINTER) && (TAG_POINTER == tagString)) {
122 myState = READ_NAVIGATION;
123 } else if ((myState == READ_TOCTITLE) && (TAG_TITLE == tagString)) {
124 myTOC.push_back(TOCItem(myTOCReference, myTOCTitle, myTOCLevel));
125 myTOCTitle.erase();
126 myState = READ_POINTER;
130 bool ORBookReader::readBook(const std::string &fileName) {
131 myFilePrefix = MiscUtil::htmlDirectoryPrefix(fileName);
133 myResources.clear();
134 myCoverReference.erase();
135 myHtmlFileIDs.clear();
136 myImageIDs.clear();
137 myHtmlFilesOrder.clear();
138 myTOC.clear();
139 myState = READ_NONE;
141 if (!readDocument(fileName)) {
142 return false;
145 myModelReader.setMainTextModel();
146 myModelReader.pushKind(REGULAR);
148 if (!myCoverReference.empty()) {
149 myModelReader.addImageReference(myCoverReference);
152 for (std::vector<std::string>::const_iterator it = myHtmlFilesOrder.begin(); it != myHtmlFilesOrder.end(); ++it) {
153 myHtmlFileIDs.erase(*it);
154 XHTMLReader(myModelReader).readFile(myFilePrefix, myResources[*it], *it);
157 int level = 1;
158 for (std::vector<TOCItem>::const_iterator it = myTOC.begin(); it != myTOC.end(); ++it) {
159 int index = myModelReader.model().label(it->Reference).ParagraphNumber;
160 if (index != -1) {
161 for (; level > it->Level; --level) {
162 myModelReader.endContentsParagraph();
164 ++level;
165 myModelReader.beginContentsParagraph(index);
166 myModelReader.addContentsData(it->Text);
169 for (; level > 1; --level) {
170 myModelReader.endContentsParagraph();
173 for (std::set<std::string>::const_iterator it = myHtmlFileIDs.begin(); it != myHtmlFileIDs.end(); ++it) {
174 myModelReader.setFootnoteTextModel(*it);
175 myModelReader.pushKind(REGULAR);
176 XHTMLReader(myModelReader).readFile(myFilePrefix, myResources[*it], *it);
179 for (std::map<std::string,std::string>::const_iterator it = myImageIDs.begin(); it != myImageIDs.end(); ++it) {
180 myModelReader.addImage(it->first, new ZLFileImage(it->second, myFilePrefix + myResources[it->first], 0));
183 return true;