~ubuntu-branches/ubuntu/vivid/fbreader/vivid-proposed

« back to all changes in this revision

Viewing changes to fbreader/src/formats/oeb/XHTMLReader.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Joey Hess
  • Date: 2008-01-23 16:51:07 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20080123165107-5q19etahzd72c33a
Tags: 0.8.12-3
* Add libzlui-maemo which allows using fbreader on the maemo platform, on
  Debian. Thanks, Riku Voipio. Closes: #462299
* makefiles/arch/maemo.mk: Don't build with -thumb. (Riku)
* Loosen dependency versions some more, so it only depends on the current
  upstream version or higher, ignoring the Debian revision.
* Use binary:Version instead of deprecated Source-Version.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * FBReader -- electronic book reader
3
 
 * Copyright (C) 2004-2007 Nikolay Pultsin <geometer@mawhrin.net>
4
 
 * Copyright (C) 2005 Mikhail Sobolev <mss@mawhrin.net>
5
 
 *
6
 
 * This program is free software; you can redistribute it and/or modify
7
 
 * it under the terms of the GNU General Public License as published by
8
 
 * the Free Software Foundation; either version 2 of the License, or
9
 
 * (at your option) any later version.
10
 
 *
11
 
 * This program is distributed in the hope that it will be useful,
12
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 
 * GNU General Public License for more details.
15
 
 *
16
 
 * You should have received a copy of the GNU General Public License
17
 
 * along with this program; if not, write to the Free Software
18
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
 
 * 02110-1301, USA.
20
 
 */
21
 
 
22
 
#include <string.h>
23
 
 
24
 
#include <ZLFileImage.h>
25
 
#include <ZLUnicodeUtil.h>
26
 
 
27
 
#include "XHTMLReader.h"
28
 
#include "../util/EntityFilesCollector.h"
29
 
#include "../util/MiscUtil.h"
30
 
 
31
 
#include "../../bookmodel/BookReader.h"
32
 
#include "../../bookmodel/BookModel.h"
33
 
 
34
 
std::map<std::string,XHTMLTagAction*> XHTMLReader::ourTagActions;
35
 
 
36
 
XHTMLTagAction::~XHTMLTagAction() {
37
 
}
38
 
 
39
 
class XHTMLTagParagraphAction : public XHTMLTagAction {
40
 
 
41
 
public:
42
 
        void doAtStart(XHTMLReader &reader, const char **xmlattributes);
43
 
        void doAtEnd(XHTMLReader &reader);
44
 
};
45
 
 
46
 
class XHTMLTagRestartParagraphAction : public XHTMLTagAction {
47
 
 
48
 
public:
49
 
        void doAtStart(XHTMLReader &reader, const char **xmlattributes);
50
 
        void doAtEnd(XHTMLReader &reader);
51
 
};
52
 
 
53
 
class XHTMLTagImageAction : public XHTMLTagAction {
54
 
 
55
 
public:
56
 
        XHTMLTagImageAction(const std::string &nameAttribute);
57
 
 
58
 
        void doAtStart(XHTMLReader &reader, const char **xmlattributes);
59
 
        void doAtEnd(XHTMLReader &reader);
60
 
 
61
 
private:
62
 
        const std::string myNameAttribute;
63
 
};
64
 
 
65
 
class XHTMLTagItemAction : public XHTMLTagAction {
66
 
 
67
 
public:
68
 
        void doAtStart(XHTMLReader &reader, const char **xmlattributes);
69
 
        void doAtEnd(XHTMLReader &reader);
70
 
};
71
 
 
72
 
class XHTMLTagHyperlinkAction : public XHTMLTagAction {
73
 
 
74
 
public:
75
 
        void doAtStart(XHTMLReader &reader, const char **xmlattributes);
76
 
        void doAtEnd(XHTMLReader &reader);
77
 
 
78
 
private:
79
 
        std::stack<FBTextKind> myHyperlinkStack;
80
 
};
81
 
 
82
 
class XHTMLTagControlAction : public XHTMLTagAction {
83
 
 
84
 
public:
85
 
        XHTMLTagControlAction(FBTextKind control);
86
 
 
87
 
        void doAtStart(XHTMLReader &reader, const char **xmlattributes);
88
 
        void doAtEnd(XHTMLReader &reader);
89
 
 
90
 
private:
91
 
        FBTextKind myControl;
92
 
};
93
 
 
94
 
class XHTMLTagParagraphWithControlAction : public XHTMLTagAction {
95
 
 
96
 
public:
97
 
        XHTMLTagParagraphWithControlAction(FBTextKind control);
98
 
 
99
 
        void doAtStart(XHTMLReader &reader, const char **xmlattributes);
100
 
        void doAtEnd(XHTMLReader &reader);
101
 
 
102
 
private:
103
 
        FBTextKind myControl;
104
 
};
105
 
 
106
 
class XHTMLTagPreAction : public XHTMLTagAction {
107
 
 
108
 
public:
109
 
        void doAtStart(XHTMLReader &reader, const char **xmlattributes);
110
 
        void doAtEnd(XHTMLReader &reader);
111
 
};
112
 
 
113
 
void XHTMLTagParagraphAction::doAtStart(XHTMLReader &reader, const char**) {
114
 
        reader.myModelReader.beginParagraph();
115
 
}
116
 
 
117
 
void XHTMLTagParagraphAction::doAtEnd(XHTMLReader &reader) {
118
 
        reader.myModelReader.endParagraph();
119
 
}
120
 
 
121
 
void XHTMLTagRestartParagraphAction::doAtStart(XHTMLReader &reader, const char**) {
122
 
        reader.myModelReader.endParagraph();
123
 
        reader.myModelReader.beginParagraph();
124
 
}
125
 
 
126
 
void XHTMLTagRestartParagraphAction::doAtEnd(XHTMLReader&) {
127
 
}
128
 
 
129
 
void XHTMLTagItemAction::doAtStart(XHTMLReader &reader, const char**) {
130
 
        reader.myModelReader.endParagraph();
131
 
        // TODO: increase left indent
132
 
        reader.myModelReader.beginParagraph();
133
 
        // TODO: replace bullet sign by number inside OL tag
134
 
        const std::string bullet = "\xE2\x80\xA2\xC0\xA0";
135
 
        reader.myModelReader.addData(bullet);
136
 
}
137
 
 
138
 
void XHTMLTagItemAction::doAtEnd(XHTMLReader &reader) {
139
 
        reader.myModelReader.endParagraph();
140
 
}
141
 
 
142
 
XHTMLTagImageAction::XHTMLTagImageAction(const std::string &nameAttribute) : myNameAttribute(nameAttribute) {
143
 
}
144
 
 
145
 
void XHTMLTagImageAction::doAtStart(XHTMLReader &reader, const char **xmlattributes) {
146
 
        const char *fileName = reader.attributeValue(xmlattributes, myNameAttribute);
147
 
        if (fileName != 0) {
148
 
                bool flag = reader.myModelReader.paragraphIsOpen();
149
 
                if (flag) {
150
 
                        reader.myModelReader.endParagraph();
151
 
                }
152
 
                if ((strlen(fileName) > 2) && strncmp(fileName, "./", 2) == 0) {
153
 
                        fileName +=2;
154
 
                }
155
 
                reader.myModelReader.addImageReference(fileName);
156
 
                reader.myModelReader.addImage(fileName, new ZLFileImage("image/auto", reader.myPathPrefix + fileName, 0));
157
 
                if (flag) {
158
 
                        reader.myModelReader.beginParagraph();
159
 
                }
160
 
        }
161
 
}
162
 
 
163
 
void XHTMLTagImageAction::doAtEnd(XHTMLReader&) {
164
 
}
165
 
 
166
 
XHTMLTagControlAction::XHTMLTagControlAction(FBTextKind control) : myControl(control) {
167
 
}
168
 
 
169
 
void XHTMLTagControlAction::doAtStart(XHTMLReader &reader, const char**) {
170
 
        reader.myModelReader.pushKind(myControl);
171
 
        reader.myModelReader.addControl(myControl, true);
172
 
}
173
 
 
174
 
void XHTMLTagControlAction::doAtEnd(XHTMLReader &reader) {
175
 
        reader.myModelReader.addControl(myControl, false);
176
 
        reader.myModelReader.popKind();
177
 
}
178
 
 
179
 
void XHTMLTagHyperlinkAction::doAtStart(XHTMLReader &reader, const char **xmlattributes) {
180
 
        const char *href = reader.attributeValue(xmlattributes, "href");
181
 
        if (href != 0) {
182
 
                const std::string link = (*href == '#') ? (reader.myReferenceName + href) : href;
183
 
                FBTextKind hyperlinkType = MiscUtil::isReference(link) ? EXTERNAL_HYPERLINK : INTERNAL_HYPERLINK;
184
 
                myHyperlinkStack.push(hyperlinkType);
185
 
                reader.myModelReader.addHyperlinkControl(hyperlinkType, link);
186
 
        } else {
187
 
                myHyperlinkStack.push(REGULAR);
188
 
        }
189
 
        const char *name = reader.attributeValue(xmlattributes, "name");
190
 
        if (name != 0) {
191
 
                reader.myModelReader.addHyperlinkLabel(reader.myReferenceName + "#" + name);
192
 
        }
193
 
}
194
 
 
195
 
void XHTMLTagHyperlinkAction::doAtEnd(XHTMLReader &reader) {
196
 
        FBTextKind kind = myHyperlinkStack.top();
197
 
        if (kind != REGULAR) {
198
 
                reader.myModelReader.addControl(kind, false);
199
 
        }
200
 
        myHyperlinkStack.pop();
201
 
}
202
 
 
203
 
XHTMLTagParagraphWithControlAction::XHTMLTagParagraphWithControlAction(FBTextKind control) : myControl(control) {
204
 
}
205
 
 
206
 
void XHTMLTagParagraphWithControlAction::doAtStart(XHTMLReader &reader, const char**) {
207
 
        if ((myControl == TITLE) && (reader.myModelReader.model().bookTextModel()->paragraphsNumber() > 1)) {
208
 
                reader.myModelReader.insertEndOfSectionParagraph();
209
 
        }
210
 
        reader.myModelReader.beginParagraph();
211
 
        reader.myModelReader.addControl(myControl, true);
212
 
}
213
 
 
214
 
void XHTMLTagParagraphWithControlAction::doAtEnd(XHTMLReader &reader) {
215
 
        reader.myModelReader.addControl(myControl, false);
216
 
        reader.myModelReader.endParagraph();
217
 
}
218
 
 
219
 
void XHTMLTagPreAction::doAtStart(XHTMLReader &reader, const char**) {
220
 
        reader.myPreformatted = true;
221
 
        reader.myModelReader.beginParagraph();
222
 
        reader.myModelReader.addControl(CODE, true);
223
 
}
224
 
 
225
 
void XHTMLTagPreAction::doAtEnd(XHTMLReader &reader) {
226
 
        reader.myModelReader.addControl(CODE, false);
227
 
        reader.myModelReader.endParagraph();
228
 
        reader.myPreformatted = false;
229
 
}
230
 
 
231
 
void XHTMLReader::addAction(const std::string &tag, XHTMLTagAction *action) {
232
 
        ourTagActions.insert(std::pair<std::string,XHTMLTagAction*>(tag,action));
233
 
}
234
 
 
235
 
void XHTMLReader::fillTagTable() {
236
 
        if (ourTagActions.empty()) {
237
 
                //addAction("html",     new XHTMLTagAction());
238
 
                addAction("body",       new XHTMLTagParagraphAction());
239
 
                //addAction("title",    new XHTMLTagAction());
240
 
                //addAction("meta",     new XHTMLTagAction());
241
 
                //addAction("script",   new XHTMLTagAction());
242
 
 
243
 
                //addAction("font",     new XHTMLTagAction());
244
 
                //addAction("style",    new XHTMLTagAction());
245
 
 
246
 
                addAction("p",  new XHTMLTagParagraphAction());
247
 
                addAction("h1", new XHTMLTagParagraphWithControlAction(H1));
248
 
                addAction("h2", new XHTMLTagParagraphWithControlAction(H2));
249
 
                addAction("h3", new XHTMLTagParagraphWithControlAction(H3));
250
 
                addAction("h4", new XHTMLTagParagraphWithControlAction(H4));
251
 
                addAction("h5", new XHTMLTagParagraphWithControlAction(H5));
252
 
                addAction("h6", new XHTMLTagParagraphWithControlAction(H6));
253
 
 
254
 
                //addAction("ol",       new XHTMLTagAction());
255
 
                //addAction("ul",       new XHTMLTagAction());
256
 
                //addAction("dl",       new XHTMLTagAction());
257
 
                addAction("li", new XHTMLTagItemAction());
258
 
 
259
 
                addAction("strong",     new XHTMLTagControlAction(STRONG));
260
 
                addAction("b",  new XHTMLTagControlAction(BOLD));
261
 
                addAction("em", new XHTMLTagControlAction(EMPHASIS));
262
 
                addAction("i",  new XHTMLTagControlAction(ITALIC));
263
 
                addAction("code",       new XHTMLTagControlAction(CODE));
264
 
                addAction("tt", new XHTMLTagControlAction(CODE));
265
 
                addAction("kbd",        new XHTMLTagControlAction(CODE));
266
 
                addAction("var",        new XHTMLTagControlAction(CODE));
267
 
                addAction("samp",       new XHTMLTagControlAction(CODE));
268
 
                addAction("cite",       new XHTMLTagControlAction(CITE));
269
 
                addAction("sub",        new XHTMLTagControlAction(SUB));
270
 
                addAction("sup",        new XHTMLTagControlAction(SUP));
271
 
                addAction("dd", new XHTMLTagControlAction(DEFINITION_DESCRIPTION));
272
 
                addAction("dfn",        new XHTMLTagControlAction(DEFINITION));
273
 
                addAction("strike",     new XHTMLTagControlAction(STRIKETHROUGH));
274
 
 
275
 
                addAction("a",  new XHTMLTagHyperlinkAction());
276
 
 
277
 
                addAction("img",        new XHTMLTagImageAction("src"));
278
 
                addAction("object",     new XHTMLTagImageAction("data"));
279
 
 
280
 
                //addAction("area",     new XHTMLTagAction());
281
 
                //addAction("map",      new XHTMLTagAction());
282
 
 
283
 
                //addAction("base",     new XHTMLTagAction());
284
 
                //addAction("blockquote",       new XHTMLTagAction());
285
 
                addAction("br", new XHTMLTagRestartParagraphAction());
286
 
                //addAction("center",   new XHTMLTagAction());
287
 
                addAction("div",        new XHTMLTagParagraphAction());
288
 
                //addAction("dt",       new XHTMLTagAction());
289
 
                //addAction("head",     new XHTMLTagAction());
290
 
                //addAction("hr",       new XHTMLTagAction());
291
 
                //addAction("link",     new XHTMLTagAction());
292
 
                //addAction("param",    new XHTMLTagAction());
293
 
                //addAction("q",        new XHTMLTagAction());
294
 
                //addAction("s",        new XHTMLTagAction());
295
 
 
296
 
                addAction("pre",        new XHTMLTagPreAction());
297
 
                //addAction("big",      new XHTMLTagAction());
298
 
                //addAction("small",    new XHTMLTagAction());
299
 
                //addAction("u",        new XHTMLTagAction());
300
 
 
301
 
                //addAction("table",    new XHTMLTagAction());
302
 
                addAction("td", new XHTMLTagParagraphAction());
303
 
                addAction("th", new XHTMLTagParagraphAction());
304
 
                //addAction("tr",       new XHTMLTagAction());
305
 
                //addAction("caption",  new XHTMLTagAction());
306
 
                //addAction("span",     new XHTMLTagAction());
307
 
        }
308
 
}
309
 
 
310
 
XHTMLReader::XHTMLReader(BookReader &modelReader) : myModelReader(modelReader) {
311
 
}
312
 
 
313
 
bool XHTMLReader::readFile(const std::string &pathPrefix, const std::string &fileName, const std::string &referenceName) {
314
 
        myModelReader.addHyperlinkLabel(referenceName);
315
 
 
316
 
        fillTagTable();
317
 
 
318
 
        myPathPrefix = pathPrefix;
319
 
        myReferenceName = referenceName;
320
 
 
321
 
        myPreformatted = false;
322
 
 
323
 
        return readDocument(pathPrefix + fileName);
324
 
}
325
 
 
326
 
 
327
 
void XHTMLReader::startElementHandler(const char *tag, const char **attributes) {
328
 
        static const std::string HASH = "#";
329
 
        const char *id = attributeValue(attributes, "id");
330
 
        if (id != 0) {
331
 
                myModelReader.addHyperlinkLabel(myReferenceName + HASH + id);
332
 
        }
333
 
 
334
 
        XHTMLTagAction *action = ourTagActions[ZLUnicodeUtil::toLower(tag)];
335
 
        if (action != 0) {
336
 
                action->doAtStart(*this, attributes);
337
 
        }
338
 
}
339
 
 
340
 
void XHTMLReader::endElementHandler(const char *tag) {
341
 
        XHTMLTagAction *action = ourTagActions[ZLUnicodeUtil::toLower(tag)];
342
 
        if (action != 0) {
343
 
                action->doAtEnd(*this);
344
 
        }
345
 
}
346
 
 
347
 
void XHTMLReader::characterDataHandler(const char *text, int len) {
348
 
        if (myPreformatted) {
349
 
                if ((*text == '\r') || (*text == '\n')) {
350
 
                        myModelReader.addControl(CODE, false);
351
 
                        myModelReader.endParagraph();
352
 
                        myModelReader.beginParagraph();
353
 
                        myModelReader.addControl(CODE, true);
354
 
                }
355
 
                int spaceCounter = 0;
356
 
                while ((spaceCounter < len) && isspace((unsigned char)*text)) {
357
 
                        ++spaceCounter;
358
 
                }
359
 
                myModelReader.addFixedHSpace(spaceCounter);
360
 
                text += spaceCounter;
361
 
                len -= spaceCounter;
362
 
        }
363
 
        if (len > 0) {
364
 
                myModelReader.addData(std::string(text, len));
365
 
        }
366
 
}
367
 
 
368
 
const std::vector<std::string> &XHTMLReader::externalDTDs() const {
369
 
        return EntityFilesCollector::instance().externalDTDs("xhtml");
370
 
}