Initial commit. FBReader 0.8.12
[lbook_fbreader.git] / fbreader / src / formats / chm / CHMPlugin.cpp
blob2654b8af6f11e27745bf1d4b3092cb3c04358026
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 <ZLUnicodeUtil.h>
21 #include <ZLStringUtil.h>
22 #include <ZLFile.h>
23 #include <ZLInputStream.h>
25 #include "CHMPlugin.h"
26 #include "CHMFile.h"
27 #include "CHMFileImage.h"
28 #include "CHMReferenceCollection.h"
29 #include "HHCReader.h"
30 #include "../txt/PlainTextFormat.h"
31 #include "HtmlSectionReader.h"
32 #include "../../description/BookDescription.h"
34 bool CHMPlugin::acceptsFile(const ZLFile &file) const {
35 const std::string &extension = file.extension();
36 return (extension == "CHM") || (extension == "chm");
39 bool CHMPlugin::readDescription(const std::string &path, BookDescription &description) const {
40 ZLFile file(path);
41 shared_ptr<ZLInputStream> stream = file.inputStream();
42 if (stream.isNull() || !stream->open()) {
43 return false;
46 CHMFileInfo chmFile(path);
47 if (!chmFile.init(*stream)) {
48 return false;
51 CHMFileInfo::FileNames names = chmFile.sectionNames(stream);
52 if (names.empty()) {
53 return false;
56 shared_ptr<ZLInputStream> entryStream = chmFile.entryStream(stream, names.Start);
57 if (entryStream.isNull()) {
58 entryStream = chmFile.entryStream(stream, names.Home);
60 if (entryStream.isNull()) {
61 entryStream = chmFile.entryStream(stream, names.TOC);
64 if (entryStream.isNull()) {
65 chmFile.entryStream(stream, names.Index);
68 if (entryStream.isNull()) {
69 return false;
72 detectEncodingAndLanguage(description, *entryStream);
73 if (description.encoding().empty()) {
74 return false;
77 return true;
80 bool CHMPlugin::readModel(const BookDescription &description, BookModel &model) const {
81 shared_ptr<ZLInputStream> stream = ZLFile(description.fileName()).inputStream();
82 if (stream.isNull() || !stream->open()) {
83 return false;
86 shared_ptr<CHMFileInfo> info = new CHMFileInfo(description.fileName());
87 if (!info->init(*stream)) {
88 return false;
91 CHMFileInfo::FileNames names = info->sectionNames(stream);
92 if (names.empty()) {
93 return false;
96 CHMReferenceCollection referenceCollection;
98 referenceCollection.addReference(names.Start, false);
99 referenceCollection.addReference(names.Home, false);
101 shared_ptr<ZLInputStream> tocStream = info->entryStream(stream, names.TOC);
102 HHCReader hhcReader(referenceCollection, model, description.encoding());
103 if (!tocStream.isNull() && tocStream->open()) {
104 referenceCollection.setPrefix(names.TOC);
105 hhcReader.readDocument(*tocStream);
109 if (!tocStream.isNull() && tocStream->open()) {
110 std::string buf;
111 buf.append(tocStream->sizeOfOpened(), '\0');
112 tocStream->read((char*)buf.data(), buf.length());
113 std::cerr << "[ " << names.TOC << " ]\n" << buf << "\n";
117 int contentCounter = 0;
118 PlainTextFormat format(description.fileName());
119 HtmlSectionReader reader(model, format, description.encoding(), info, referenceCollection);
120 while (referenceCollection.containsNonProcessedReferences()) {
121 const std::string fileName = referenceCollection.nextReference();
122 if (ZLStringUtil::stringEndsWith(fileName, ".jpg") ||
123 ZLStringUtil::stringEndsWith(fileName, ".gif")) {
124 std::string lowerCasedFileName = ZLUnicodeUtil::toLower(fileName);
125 BookReader bookReader(model);
126 bookReader.setMainTextModel();
127 bookReader.addHyperlinkLabel(lowerCasedFileName);
128 bookReader.pushKind(REGULAR);
129 bookReader.beginParagraph();
130 bookReader.addImageReference(lowerCasedFileName);
131 bookReader.addImage(fileName, new CHMFileImage(info, fileName));
132 bookReader.endParagraph();
133 bookReader.insertEndOfTextParagraph();
134 } else {
135 shared_ptr<ZLInputStream> entryStream = info->entryStream(stream, fileName);
136 if (!entryStream.isNull() && entryStream->open()) {
138 std::string buf;
139 buf.append(entryStream->sizeOfOpened(), '\0');
140 entryStream->read((char*)buf.data(), buf.length());
141 std::cerr << "[ " << fileName << " ]\n" << buf << "\n";
142 entryStream->open();
144 reader.setSectionName(fileName);
145 reader.readDocument(*entryStream);
146 ++contentCounter;
150 if (contentCounter == 0) {
151 return false;
154 hhcReader.setReferences();
156 return true;
159 const std::string &CHMPlugin::iconName() const {
160 static const std::string ICON_NAME = "html";
161 return ICON_NAME;