gui
[lbook_fbreader.git] / fbreader / src / formats / rtf / RtfBookReader.cpp
blob04d09443ce919ac9722c97505e9c660cb627670c
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 <cctype>
22 #include <ZLStringUtil.h>
24 #include "RtfBookReader.h"
25 #include "../../bookmodel/BookModel.h"
26 #include "RtfImage.h"
28 RtfBookReader::RtfBookReader(BookModel &model, const std::string &encoding) : RtfReader(encoding), myBookReader(model) {
31 static const size_t maxBufferSize = 1024;
33 void RtfBookReader::addCharData(const char *data, size_t len, bool convert) {
34 if (myCurrentState.ReadText) {
35 if (convert || myConverter.isNull()) {
36 myOutputBuffer.append(data, len);
37 if (myOutputBuffer.size() >= maxBufferSize) {
38 flushBuffer();
40 } else {
41 flushBuffer();
42 std::string newString(data, len);
43 characterDataHandler(newString);
48 void RtfBookReader::flushBuffer() {
49 if (!myOutputBuffer.empty()) {
50 if (myCurrentState.ReadText) {
51 if (!myConverter.isNull()) {
52 static std::string newString;
53 myConverter->convert(newString, myOutputBuffer.data(), myOutputBuffer.data() + myOutputBuffer.length());
54 characterDataHandler(newString);
55 newString.erase();
56 } else {
57 characterDataHandler(myOutputBuffer);
60 myOutputBuffer.erase();
64 void RtfBookReader::switchDestination(DestinationType destination, bool on) {
65 switch (destination) {
66 case DESTINATION_NONE:
67 break;
68 case DESTINATION_SKIP:
69 case DESTINATION_INFO:
70 case DESTINATION_TITLE:
71 case DESTINATION_AUTHOR:
72 case DESTINATION_STYLESHEET:
73 myCurrentState.ReadText = !on;
74 break;
75 case DESTINATION_PICTURE:
76 if (on) {
77 flushBuffer();
78 if (myBookReader.paragraphIsOpen()) {
79 myBookReader.endParagraph();
82 myCurrentState.ReadText = !on;
83 break;
84 case DESTINATION_FOOTNOTE:
85 flushBuffer();
86 if (on) {
87 std::string id;
88 ZLStringUtil::appendNumber(id, myFootnoteIndex++);
90 myStateStack.push(myCurrentState);
91 myCurrentState.Id = id;
92 myCurrentState.ReadText = true;
94 myBookReader.addHyperlinkControl(FOOTNOTE, id);
95 myBookReader.addData(id);
96 myBookReader.addControl(FOOTNOTE, false);
98 myBookReader.setFootnoteTextModel(id);
99 myBookReader.pushKind(REGULAR);
100 myBookReader.beginParagraph();
101 } else {
102 myBookReader.endParagraph();
103 myBookReader.popKind();
105 if (!myStateStack.empty()) {
106 myCurrentState = myStateStack.top();
107 myStateStack.pop();
110 if (myStateStack.empty()) {
111 myBookReader.setMainTextModel();
112 } else {
113 myBookReader.setFootnoteTextModel(myCurrentState.Id);
116 break;
120 void RtfBookReader::insertImage(const std::string &mimeType, const std::string &fileName, size_t startOffset, size_t size) {
121 std::string id;
122 ZLStringUtil::appendNumber(id, myImageIndex++);
123 myBookReader.addImageReference(id);
124 myBookReader.addImage(id, new RtfImage(mimeType, fileName, startOffset, size));
127 bool RtfBookReader::characterDataHandler(std::string &str) {
128 if (myCurrentState.ReadText) {
129 if (!myBookReader.paragraphIsOpen()) {
130 myBookReader.beginParagraph();
132 myBookReader.addData(str);
134 return true;
137 bool RtfBookReader::readDocument(const std::string &fileName) {
138 myImageIndex = 0;
139 myFootnoteIndex = 1;
141 myCurrentState.ReadText = true;
143 myBookReader.setMainTextModel();
144 myBookReader.pushKind(REGULAR);
145 myBookReader.beginParagraph();
147 bool code = RtfReader::readDocument(fileName);
149 flushBuffer();
150 myBookReader.endParagraph();
151 while (!myStateStack.empty()) {
152 myStateStack.pop();
155 return code;
158 void RtfBookReader::setFontProperty(FontProperty property) {
159 if (!myCurrentState.ReadText) {
160 //DPRINT("change style not in text.\n");
161 return;
163 flushBuffer();
165 switch (property) {
166 case FONT_BOLD:
167 if (myState.Bold) {
168 myBookReader.pushKind(STRONG);
169 } else {
170 myBookReader.popKind();
172 myBookReader.addControl(STRONG, myState.Bold);
173 break;
174 case FONT_ITALIC:
175 if (myState.Italic) {
176 if (!myState.Bold) {
177 //DPRINT("add style emphasis.\n");
178 myBookReader.pushKind(EMPHASIS);
179 myBookReader.addControl(EMPHASIS, true);
180 } else {
181 //DPRINT("add style emphasis and strong.\n");
182 myBookReader.popKind();
183 myBookReader.addControl(STRONG, false);
185 myBookReader.pushKind(EMPHASIS);
186 myBookReader.addControl(EMPHASIS, true);
187 myBookReader.pushKind(STRONG);
188 myBookReader.addControl(STRONG, true);
190 } else {
191 if (!myState.Bold) {
192 //DPRINT("remove style emphasis.\n");
193 myBookReader.addControl(EMPHASIS, false);
194 myBookReader.popKind();
195 } else {
196 //DPRINT("remove style strong n emphasis, add strong.\n");
197 myBookReader.addControl(STRONG, false);
198 myBookReader.popKind();
199 myBookReader.addControl(EMPHASIS, false);
200 myBookReader.popKind();
202 myBookReader.pushKind(STRONG);
203 myBookReader.addControl(STRONG, true);
206 break;
207 case FONT_UNDERLINED:
208 break;
212 void RtfBookReader::newParagraph() {
213 flushBuffer();
214 myBookReader.endParagraph();
215 myBookReader.beginParagraph();
216 if (myState.Alignment != ALIGN_UNDEFINED) {
217 setAlignment();
221 void RtfBookReader::setEncoding(int) {
224 void RtfBookReader::setAlignment() {
225 ZLTextForcedControlEntry entry;
226 entry.setAlignmentType(myState.Alignment);
227 myBookReader.addControl(entry);