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
23 #include <ZLInputStream.h>
24 #include <ZLStringUtil.h>
26 #include <ZLTextParagraph.h>
28 #include "FB2BookReader.h"
29 #include "Base64EncodedImage.h"
30 #include "../../bookmodel/BookModel.h"
32 FB2BookReader::FB2BookReader(BookModel
&model
) : myModelReader(model
) {
33 myInsideCoverpage
= false;
34 myParagraphsBeforeBodyNumber
= (size_t)-1;
38 myReadMainText
= false;
40 myProcessingImage
= false;
41 mySectionStarted
= false;
42 myInsideTitle
= false;
45 void FB2BookReader::characterDataHandler(const char *text
, int len
) {
46 if ((len
> 0) && (myProcessingImage
|| myModelReader
.paragraphIsOpen())) {
47 std::string
str(text
, len
);
48 if (myProcessingImage
) {
49 myImageBuffer
.push_back(str
);
51 myModelReader
.addData(str
);
53 myModelReader
.addContentsData(str
);
59 void FB2BookReader::startElementHandler(int tag
, const char **xmlattributes
) {
60 const char *id
= attributeValue(xmlattributes
, "id");
62 if (!myReadMainText
) {
63 myModelReader
.setFootnoteTextModel(id
);
65 myModelReader
.addHyperlinkLabel(id
);
69 if (mySectionStarted
) {
70 mySectionStarted
= false;
71 } else if (myInsideTitle
) {
72 static const std::string SPACE
= " ";
73 myModelReader
.addContentsData(SPACE
);
75 myModelReader
.beginParagraph();
78 myModelReader
.pushKind(VERSE
);
79 myModelReader
.beginParagraph();
82 myModelReader
.pushKind(SUBTITLE
);
83 myModelReader
.beginParagraph();
86 myModelReader
.pushKind(AUTHOR
);
87 myModelReader
.beginParagraph();
90 myModelReader
.pushKind(DATE
);
91 myModelReader
.beginParagraph();
94 myModelReader
.pushKind(CITE
);
98 myModelReader
.insertEndOfSectionParagraph();
100 myModelReader
.beginContentsParagraph();
101 mySectionStarted
= true;
106 myModelReader
.pushKind(POEM_TITLE
);
107 } else if (mySectionDepth
== 0) {
108 myModelReader
.insertEndOfSectionParagraph();
109 myModelReader
.pushKind(TITLE
);
111 myModelReader
.pushKind(SECTION_TITLE
);
112 myModelReader
.enterTitle();
113 myInsideTitle
= true;
120 myModelReader
.pushKind(STANZA
);
121 myModelReader
.beginParagraph(ZLTextParagraph::BEFORE_SKIP_PARAGRAPH
);
122 myModelReader
.endParagraph();
125 myModelReader
.pushKind(EPIGRAPH
);
128 if (myBodyCounter
== 0) {
129 myModelReader
.setMainTextModel();
131 myModelReader
.pushKind(ANNOTATION
);
134 if (myBodyCounter
== 0) {
135 myInsideCoverpage
= true;
136 myModelReader
.setMainTextModel();
140 myModelReader
.addControl(SUB
, true);
143 myModelReader
.addControl(SUP
, true);
146 myModelReader
.addControl(CODE
, true);
149 myModelReader
.addControl(STRIKETHROUGH
, true);
152 myModelReader
.addControl(STRONG
, true);
155 myModelReader
.addControl(EMPHASIS
, true);
159 const char *ref
= attributeValue(xmlattributes
, myHrefAttributeName
.c_str());
161 const char *type
= attributeValue(xmlattributes
, "type");
162 if((type
!= 0 && !strncmp(type
, "note", 4)) || strstr(ref
, "note"))
163 myHyperlinkType
= FOOTNOTE
;
164 else if(ref
[0] == '#')
165 myHyperlinkType
= INTERNAL_HYPERLINK
;
167 myHyperlinkType
= EXTERNAL_HYPERLINK
;
172 * if (ref[0] == '#') {
173 myHyperlinkType = FOOTNOTE;
176 myHyperlinkType = EXTERNAL_HYPERLINK;
179 myModelReader
.addHyperlinkControl(myHyperlinkType
, ref
);
181 myHyperlinkType
= FOOTNOTE
;
182 myModelReader
.addControl(myHyperlinkType
, true);
188 const char *ref
= attributeValue(xmlattributes
, myHrefAttributeName
.c_str());
189 const char *vOffset
= attributeValue(xmlattributes
, "voffset");
190 char offset
= (vOffset
!= 0) ? atoi(vOffset
) : 0;
191 if ((ref
!= 0) && (*ref
== '#')) {
193 if ((myCoverImageReference
!= ref
) ||
194 (myParagraphsBeforeBodyNumber
!= myModelReader
.model().bookTextModel()->paragraphsNumber())) {
195 myModelReader
.addImageReference(ref
);
197 if (myInsideCoverpage
) {
198 myCoverImageReference
= ref
;
205 const char *contentType
= attributeValue(xmlattributes
, "content-type");
206 if ((contentType
!= 0) && (id
!= 0)) {
207 myCurrentImage
= new Base64EncodedImage(contentType
);
208 myModelReader
.addImage(id
, myCurrentImage
);
209 myProcessingImage
= true;
214 myModelReader
.beginParagraph(ZLTextParagraph::EMPTY_LINE_PARAGRAPH
);
215 myModelReader
.endParagraph();
219 myParagraphsBeforeBodyNumber
= myModelReader
.model().bookTextModel()->paragraphsNumber();
220 if ((myBodyCounter
== 1) || (attributeValue(xmlattributes
, "name") == 0)) {
221 myModelReader
.setMainTextModel();
222 myReadMainText
= true;
224 myModelReader
.pushKind(REGULAR
);
231 void FB2BookReader::endElementHandler(int tag
) {
234 myModelReader
.endParagraph();
240 myModelReader
.popKind();
241 myModelReader
.endParagraph();
244 myModelReader
.popKind();
247 if (myReadMainText
) {
248 myModelReader
.endContentsParagraph();
250 mySectionStarted
= false;
252 myModelReader
.unsetTextModel();
256 myModelReader
.exitTitle();
257 myModelReader
.popKind();
258 myInsideTitle
= false;
261 myInsidePoem
= false;
264 myModelReader
.beginParagraph(ZLTextParagraph::AFTER_SKIP_PARAGRAPH
);
265 myModelReader
.endParagraph();
266 myModelReader
.popKind();
269 myModelReader
.popKind();
272 myModelReader
.popKind();
273 if (myBodyCounter
== 0) {
274 myModelReader
.insertEndOfSectionParagraph();
275 myModelReader
.unsetTextModel();
279 if (myBodyCounter
== 0) {
280 myInsideCoverpage
= false;
281 myModelReader
.insertEndOfSectionParagraph();
282 myModelReader
.unsetTextModel();
286 myModelReader
.addControl(SUB
, false);
289 myModelReader
.addControl(SUP
, false);
292 myModelReader
.addControl(CODE
, false);
295 myModelReader
.addControl(STRIKETHROUGH
, false);
298 myModelReader
.addControl(STRONG
, false);
301 myModelReader
.addControl(EMPHASIS
, false);
304 myModelReader
.addControl(myHyperlinkType
, false);
307 if (!myImageBuffer
.empty() && (myCurrentImage
!= 0)) {
308 myCurrentImage
->addData(myImageBuffer
);
309 myImageBuffer
.clear();
312 myProcessingImage
= false;
315 myModelReader
.popKind();
316 myModelReader
.unsetTextModel();
317 myReadMainText
= false;
324 bool FB2BookReader::processNamespaces() const {
328 void FB2BookReader::namespaceListChangedHandler() {
329 const std::string XLINK_REFERENCE
= "http://www.w3.org/1999/xlink";
330 const std::map
<std::string
,std::string
> namespaceMap
= namespaces();
331 for (std::map
<std::string
,std::string
>::const_iterator it
= namespaceMap
.begin(); it
!= namespaceMap
.end(); ++it
) {
332 if (ZLStringUtil::stringStartsWith(it
->second
, XLINK_REFERENCE
)) {
333 myHrefAttributeName
= it
->first
+ ":href";
337 myHrefAttributeName
= "";
340 bool FB2BookReader::readBook(const std::string
&fileName
) {
341 myHrefAttributeName
= "";
342 return readDocument(fileName
);