/src/libabw/src/lib/ABWParser.cpp
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* |
3 | | * This file is part of the libabw project. |
4 | | * |
5 | | * This Source Code Form is subject to the terms of the Mozilla Public |
6 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
7 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
8 | | */ |
9 | | |
10 | | #include <string.h> |
11 | | |
12 | | #include <set> |
13 | | #include <stack> |
14 | | #include <utility> |
15 | | |
16 | | #include <libxml/xmlIO.h> |
17 | | #include <libxml/xmlstring.h> |
18 | | #include <librevenge-stream/librevenge-stream.h> |
19 | | #include <boost/spirit/include/qi.hpp> |
20 | | #include "ABWParser.h" |
21 | | #include "ABWContentCollector.h" |
22 | | #include "ABWStylesCollector.h" |
23 | | #include "libabw_internal.h" |
24 | | #include "ABWXMLHelper.h" |
25 | | #include "ABWXMLTokenMap.h" |
26 | | |
27 | | |
28 | | namespace libabw |
29 | | { |
30 | | |
31 | | namespace |
32 | | { |
33 | | |
34 | | static bool findBool(const std::string &str, bool &res) |
35 | 0 | { |
36 | 0 | using namespace boost::spirit::qi; |
37 | |
|
38 | 0 | if (str.empty()) |
39 | 0 | return false; |
40 | | |
41 | 0 | symbols<char, bool> bools; |
42 | 0 | bools.add |
43 | 0 | ("true", true) |
44 | 0 | ("false", false) |
45 | 0 | ("yes", true) |
46 | 0 | ("no", false) |
47 | 0 | ; |
48 | |
|
49 | 0 | auto it = str.cbegin(); |
50 | 0 | return phrase_parse(it, str.cend(), no_case[bools], space, res) && it == str.cend(); |
51 | 0 | } |
52 | | |
53 | | // small function needed to call the xml BAD_CAST on a char const * |
54 | | static xmlChar *call_BAD_CAST_OnConst(char const *str) |
55 | 0 | { |
56 | 0 | return BAD_CAST(const_cast<char *>(str)); |
57 | 0 | } |
58 | | |
59 | | /** try to find the parent's level corresponding to a level with some id |
60 | | and use its original id to define the list id. |
61 | | |
62 | | Seen corresponds to the list of level that we have already examined, |
63 | | it is used to check also for loop |
64 | | */ |
65 | | static int _findAndUpdateListElementId(std::map<int, std::shared_ptr<ABWListElement>> &listElements, int id, std::set<int> &seen) |
66 | 0 | { |
67 | 0 | if (listElements.find(id)==listElements.end() || !listElements.find(id)->second) |
68 | 0 | return 0; |
69 | 0 | const std::shared_ptr<ABWListElement> &tmpElement= listElements.find(id)->second; |
70 | 0 | if (tmpElement->m_listId) |
71 | 0 | return tmpElement->m_listId; |
72 | 0 | if (seen.find(id)!=seen.end()) |
73 | 0 | { |
74 | | // oops, this means that we have a loop |
75 | 0 | tmpElement->m_parentId=0; |
76 | 0 | } |
77 | 0 | else |
78 | 0 | seen.insert(id); |
79 | 0 | if (!tmpElement->m_parentId) |
80 | 0 | { |
81 | 0 | tmpElement->m_listId=id; |
82 | 0 | return id; |
83 | 0 | } |
84 | 0 | tmpElement->m_listId=_findAndUpdateListElementId(listElements, tmpElement->m_parentId, seen); |
85 | 0 | return tmpElement->m_listId; |
86 | 0 | } |
87 | | |
88 | | /** try to update the final list id for each list elements */ |
89 | | static void updateListElementIds(std::map<int, std::shared_ptr<ABWListElement>> &listElements) |
90 | 0 | { |
91 | 0 | std::set<int> seens; |
92 | 0 | for (const auto &elem : listElements) |
93 | 0 | { |
94 | 0 | if (!elem.second) continue; |
95 | 0 | _findAndUpdateListElementId(listElements, elem.first, seens); |
96 | 0 | } |
97 | 0 | } |
98 | | |
99 | | } // anonymous namespace |
100 | | |
101 | | struct ABWParserState |
102 | | { |
103 | | ABWParserState(); |
104 | | ~ABWParserState(); |
105 | | std::map<int, int> m_tableSizes; |
106 | | std::map<std::string, ABWData> m_data; |
107 | | std::map<int, std::shared_ptr<ABWListElement>> m_listElements; |
108 | | |
109 | | bool m_inMetadata; |
110 | | std::string m_currentMetadataKey; |
111 | | bool m_inStyleParsing; |
112 | | std::stack<std::unique_ptr<ABWCollector> > m_collectorStack; |
113 | | }; |
114 | | |
115 | | ABWParserState::ABWParserState() |
116 | 0 | : m_tableSizes() |
117 | 0 | , m_data() |
118 | 0 | , m_listElements() |
119 | 0 | , m_inMetadata(false) |
120 | 0 | , m_currentMetadataKey() |
121 | 0 | , m_inStyleParsing(false) |
122 | 0 | , m_collectorStack() |
123 | 0 | { |
124 | 0 | } |
125 | | |
126 | | ABWParserState::~ABWParserState() |
127 | 0 | { |
128 | 0 | } |
129 | | } // namespace libabw |
130 | | |
131 | | libabw::ABWParser::ABWParser(librevenge::RVNGInputStream *input, librevenge::RVNGTextInterface *iface) |
132 | 0 | : m_input(input), m_iface(iface), m_collector(), m_state(new ABWParserState()) |
133 | 0 | { |
134 | 0 | } |
135 | | |
136 | | libabw::ABWParser::~ABWParser() |
137 | 0 | { |
138 | 0 | } |
139 | | |
140 | | bool libabw::ABWParser::parse() |
141 | 0 | { |
142 | 0 | if (!m_input) |
143 | 0 | return false; |
144 | | |
145 | 0 | try |
146 | 0 | { |
147 | 0 | m_collector.reset(new ABWStylesCollector(m_state->m_tableSizes, m_state->m_data, m_state->m_listElements)); |
148 | 0 | m_input->seek(0, librevenge::RVNG_SEEK_SET); |
149 | 0 | m_state->m_inStyleParsing=true; |
150 | 0 | if (!processXmlDocument(m_input)) |
151 | 0 | return false; |
152 | 0 | updateListElementIds(m_state->m_listElements); |
153 | 0 | m_collector.reset(new ABWContentCollector(m_iface, m_state->m_tableSizes, m_state->m_data, m_state->m_listElements)); |
154 | 0 | m_input->seek(0, librevenge::RVNG_SEEK_SET); |
155 | 0 | m_state->m_inStyleParsing=false; |
156 | 0 | return processXmlDocument(m_input) && m_state->m_collectorStack.empty(); |
157 | 0 | } |
158 | 0 | catch (...) |
159 | 0 | { |
160 | 0 | } |
161 | 0 | return false; |
162 | 0 | } |
163 | | |
164 | | bool libabw::ABWParser::processXmlDocument(librevenge::RVNGInputStream *input) |
165 | 0 | { |
166 | 0 | if (!input) |
167 | 0 | return false; |
168 | | |
169 | 0 | ABWXMLProgressWatcher watcher; |
170 | 0 | auto reader(xmlReaderForStream(input, &watcher)); |
171 | 0 | if (!reader) |
172 | 0 | return false; |
173 | 0 | int ret = xmlTextReaderRead(reader.get()); |
174 | 0 | while (1 == ret && !watcher.isStuck()) |
175 | 0 | { |
176 | 0 | ret = processXmlNode(reader.get()); |
177 | 0 | if (ret == 1) |
178 | 0 | ret = xmlTextReaderRead(reader.get()); |
179 | 0 | } |
180 | |
|
181 | 0 | if (m_collector) |
182 | 0 | m_collector->endDocument(); |
183 | 0 | return ret == 0 && !watcher.isStuck(); |
184 | 0 | } |
185 | | |
186 | | int libabw::ABWParser::processXmlNode(xmlTextReaderPtr reader) |
187 | 0 | { |
188 | 0 | if (!reader) |
189 | 0 | return -1; |
190 | 0 | int tokenId = getElementToken(reader); |
191 | 0 | int tokenType = xmlTextReaderNodeType(reader); |
192 | 0 | int emptyToken = xmlTextReaderIsEmptyElement(reader); |
193 | 0 | if (XML_READER_TYPE_SIGNIFICANT_WHITESPACE == tokenType) |
194 | 0 | { |
195 | 0 | const auto *text = (const char *)xmlTextReaderConstValue(reader); |
196 | 0 | if (!m_state->m_inMetadata && text && text[0]==' ' && text[1]==0) |
197 | 0 | m_collector->insertText(text); |
198 | 0 | return 1; |
199 | 0 | } |
200 | 0 | else if (XML_READER_TYPE_TEXT == tokenType) |
201 | 0 | { |
202 | 0 | const auto *text = (const char *)xmlTextReaderConstValue(reader); |
203 | 0 | ABW_DEBUG_MSG(("ABWParser::processXmlNode: text %s\n", text)); |
204 | 0 | if (m_state->m_inMetadata) |
205 | 0 | { |
206 | 0 | if (m_state->m_currentMetadataKey.empty()) |
207 | 0 | { |
208 | 0 | ABW_DEBUG_MSG(("there is no key for metadata entry '%s'\n", text)); |
209 | 0 | } |
210 | 0 | else |
211 | 0 | { |
212 | 0 | m_collector->addMetadataEntry(m_state->m_currentMetadataKey.c_str(), text); |
213 | 0 | m_state->m_currentMetadataKey.clear(); |
214 | 0 | } |
215 | 0 | } |
216 | 0 | else |
217 | 0 | { |
218 | 0 | m_collector->insertText(text); |
219 | 0 | } |
220 | 0 | } |
221 | | |
222 | 0 | int ret = 1; |
223 | |
|
224 | 0 | switch (tokenId) |
225 | 0 | { |
226 | 0 | case XML_ABIWORD: |
227 | 0 | if (XML_READER_TYPE_ELEMENT == tokenType) |
228 | 0 | readAbiword(reader); |
229 | 0 | break; |
230 | 0 | case XML_METADATA: |
231 | 0 | if (XML_READER_TYPE_ELEMENT == tokenType) |
232 | 0 | m_state->m_inMetadata = true; |
233 | 0 | if ((XML_READER_TYPE_END_ELEMENT == tokenType) || (emptyToken > 0)) |
234 | 0 | m_state->m_inMetadata = false; |
235 | 0 | break; |
236 | 0 | case XML_M: |
237 | 0 | if (XML_READER_TYPE_ELEMENT == tokenType) |
238 | 0 | readM(reader); |
239 | 0 | break; |
240 | 0 | case XML_HISTORY: |
241 | 0 | if (XML_READER_TYPE_ELEMENT == tokenType) |
242 | 0 | ret = readHistory(reader); |
243 | 0 | break; |
244 | 0 | case XML_REVISIONS: |
245 | 0 | if (XML_READER_TYPE_ELEMENT == tokenType) |
246 | 0 | ret = readRevisions(reader); |
247 | 0 | break; |
248 | 0 | case XML_IGNOREDWORDS: |
249 | 0 | if (XML_READER_TYPE_ELEMENT == tokenType) |
250 | 0 | ret = readIgnoredWords(reader); |
251 | 0 | break; |
252 | 0 | case XML_S: |
253 | 0 | if (XML_READER_TYPE_ELEMENT == tokenType) |
254 | 0 | readS(reader); |
255 | 0 | break; |
256 | 0 | case XML_L: |
257 | 0 | if (XML_READER_TYPE_ELEMENT == tokenType) |
258 | 0 | readL(reader); |
259 | 0 | break; |
260 | 0 | case XML_PAGESIZE: |
261 | 0 | if (XML_READER_TYPE_ELEMENT == tokenType) |
262 | 0 | readPageSize(reader); |
263 | 0 | break; |
264 | 0 | case XML_SECTION: |
265 | 0 | if (XML_READER_TYPE_ELEMENT == tokenType) |
266 | 0 | readSection(reader); |
267 | 0 | if (XML_READER_TYPE_END_ELEMENT == tokenType || emptyToken > 0) |
268 | 0 | if (m_collector) |
269 | 0 | m_collector->endSection(); |
270 | 0 | break; |
271 | 0 | case XML_D: |
272 | 0 | if (XML_READER_TYPE_ELEMENT == tokenType) |
273 | 0 | ret = readD(reader); |
274 | 0 | break; |
275 | 0 | case XML_P: |
276 | 0 | if (XML_READER_TYPE_ELEMENT == tokenType) |
277 | 0 | readP(reader); |
278 | 0 | if (XML_READER_TYPE_END_ELEMENT == tokenType || emptyToken > 0) |
279 | 0 | if (m_collector) |
280 | 0 | m_collector->closeParagraphOrListElement(); |
281 | 0 | break; |
282 | 0 | case XML_C: |
283 | 0 | if (XML_READER_TYPE_ELEMENT == tokenType) |
284 | 0 | readC(reader); |
285 | 0 | if (XML_READER_TYPE_END_ELEMENT == tokenType || emptyToken > 0) |
286 | 0 | if (m_collector) |
287 | 0 | m_collector->closeSpan(); |
288 | 0 | break; |
289 | 0 | case XML_CBR: |
290 | 0 | if (XML_READER_TYPE_ELEMENT == tokenType) |
291 | 0 | m_collector->insertColumnBreak(); |
292 | 0 | break; |
293 | 0 | case XML_PBR: |
294 | 0 | if (XML_READER_TYPE_ELEMENT == tokenType) |
295 | 0 | m_collector->insertPageBreak(); |
296 | 0 | break; |
297 | 0 | case XML_BR: |
298 | 0 | if (XML_READER_TYPE_ELEMENT == tokenType) |
299 | 0 | m_collector->insertLineBreak(); |
300 | 0 | break; |
301 | 0 | case XML_A: |
302 | 0 | if (XML_READER_TYPE_ELEMENT == tokenType) |
303 | 0 | readA(reader); |
304 | 0 | if (XML_READER_TYPE_END_ELEMENT == tokenType || emptyToken > 0) |
305 | 0 | m_collector->closeLink(); |
306 | 0 | break; |
307 | 0 | case XML_FOOT: |
308 | 0 | if (XML_READER_TYPE_ELEMENT == tokenType) |
309 | 0 | readFoot(reader); |
310 | 0 | if (XML_READER_TYPE_END_ELEMENT == tokenType || emptyToken > 0) |
311 | 0 | m_collector->closeFoot(); |
312 | 0 | break; |
313 | 0 | case XML_ENDNOTE: |
314 | 0 | if (XML_READER_TYPE_ELEMENT == tokenType) |
315 | 0 | readEndnote(reader); |
316 | 0 | if (XML_READER_TYPE_END_ELEMENT == tokenType || emptyToken > 0) |
317 | 0 | m_collector->closeEndnote(); |
318 | 0 | break; |
319 | 0 | case XML_FIELD: |
320 | 0 | if (XML_READER_TYPE_ELEMENT == tokenType) |
321 | 0 | readField(reader); |
322 | 0 | if (XML_READER_TYPE_END_ELEMENT == tokenType || emptyToken > 0) |
323 | 0 | m_collector->closeField(); |
324 | 0 | break; |
325 | 0 | case XML_TABLE: |
326 | 0 | if (XML_READER_TYPE_ELEMENT == tokenType) |
327 | 0 | readTable(reader); |
328 | 0 | if (XML_READER_TYPE_END_ELEMENT == tokenType || emptyToken > 0) |
329 | 0 | m_collector->closeTable(); |
330 | 0 | break; |
331 | 0 | case XML_CELL: |
332 | 0 | if (XML_READER_TYPE_ELEMENT == tokenType) |
333 | 0 | readCell(reader); |
334 | 0 | if (XML_READER_TYPE_END_ELEMENT == tokenType || emptyToken > 0) |
335 | 0 | m_collector->closeCell(); |
336 | 0 | break; |
337 | 0 | case XML_IMAGE: |
338 | 0 | if (XML_READER_TYPE_ELEMENT == tokenType) |
339 | 0 | readImage(reader); |
340 | 0 | break; |
341 | 0 | case XML_FRAME: |
342 | 0 | if (XML_READER_TYPE_ELEMENT == tokenType) |
343 | 0 | readFrame(reader); |
344 | 0 | if (XML_READER_TYPE_END_ELEMENT == tokenType || emptyToken > 0) |
345 | 0 | readCloseFrame(); |
346 | 0 | break; |
347 | 0 | default: |
348 | 0 | break; |
349 | 0 | } |
350 | | |
351 | | #ifdef DEBUG |
352 | | const xmlChar *name = xmlTextReaderConstName(reader); |
353 | | const xmlChar *value = xmlTextReaderConstValue(reader); |
354 | | int isEmptyElement = xmlTextReaderIsEmptyElement(reader); |
355 | | |
356 | | ABW_DEBUG_MSG(("%i %i %s", isEmptyElement, tokenType, name ? (const char *)name : "")); |
357 | | if (xmlTextReaderNodeType(reader) == 1) |
358 | | { |
359 | | while (xmlTextReaderMoveToNextAttribute(reader)) |
360 | | { |
361 | | const xmlChar *name1 = xmlTextReaderConstName(reader); |
362 | | const xmlChar *value1 = xmlTextReaderConstValue(reader); |
363 | | ABW_DEBUG_MSG((" %s=\"%s\"", name1, value1)); |
364 | | } |
365 | | } |
366 | | |
367 | | if (!value) |
368 | | ABW_DEBUG_MSG(("\n")); |
369 | | else |
370 | | { |
371 | | ABW_DEBUG_MSG((" %s\n", value)); |
372 | | } |
373 | | #endif |
374 | | |
375 | 0 | return ret; |
376 | 0 | } |
377 | | |
378 | | int libabw::ABWParser::getElementToken(xmlTextReaderPtr reader) |
379 | 0 | { |
380 | 0 | return ABWXMLTokenMap::getTokenId(xmlTextReaderConstName(reader)); |
381 | 0 | } |
382 | | |
383 | | void libabw::ABWParser::readAbiword(xmlTextReaderPtr reader) |
384 | 0 | { |
385 | 0 | const ABWXMLString props = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("props")); |
386 | 0 | if (m_collector) |
387 | 0 | m_collector->collectDocumentProperties(static_cast<const char *>(props)); |
388 | 0 | } |
389 | | |
390 | | void libabw::ABWParser::readM(xmlTextReaderPtr reader) |
391 | 0 | { |
392 | 0 | const ABWXMLString key = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("key")); |
393 | 0 | if (key) |
394 | 0 | m_state->m_currentMetadataKey = static_cast<const char *>(key); |
395 | 0 | } |
396 | | |
397 | | int libabw::ABWParser::readHistory(xmlTextReaderPtr reader) |
398 | 0 | { |
399 | 0 | int ret = 1; |
400 | 0 | int tokenId = XML_TOKEN_INVALID; |
401 | 0 | int tokenType = -1; |
402 | 0 | do |
403 | 0 | { |
404 | 0 | ret = xmlTextReaderRead(reader); |
405 | 0 | tokenId = getElementToken(reader); |
406 | 0 | if (XML_TOKEN_INVALID == tokenId) |
407 | 0 | { |
408 | 0 | ABW_DEBUG_MSG(("ABWParser::readHistory: unknown token %s\n", xmlTextReaderConstName(reader))); |
409 | 0 | } |
410 | 0 | tokenType = xmlTextReaderNodeType(reader); |
411 | 0 | switch (tokenId) |
412 | 0 | { |
413 | 0 | default: |
414 | 0 | break; |
415 | 0 | } |
416 | 0 | } |
417 | 0 | while ((XML_HISTORY != tokenId || XML_READER_TYPE_END_ELEMENT != tokenType) && 1 == ret); |
418 | 0 | return ret; |
419 | 0 | } |
420 | | |
421 | | int libabw::ABWParser::readRevisions(xmlTextReaderPtr reader) |
422 | 0 | { |
423 | 0 | int ret = 1; |
424 | 0 | int tokenId = XML_TOKEN_INVALID; |
425 | 0 | int tokenType = -1; |
426 | 0 | do |
427 | 0 | { |
428 | 0 | ret = xmlTextReaderRead(reader); |
429 | 0 | tokenId = getElementToken(reader); |
430 | 0 | if (XML_TOKEN_INVALID == tokenId) |
431 | 0 | { |
432 | 0 | ABW_DEBUG_MSG(("ABWParser::readRevisions: unknown token %s\n", xmlTextReaderConstName(reader))); |
433 | 0 | } |
434 | 0 | tokenType = xmlTextReaderNodeType(reader); |
435 | 0 | (void)tokenType; |
436 | 0 | switch (tokenId) |
437 | 0 | { |
438 | 0 | default: |
439 | 0 | break; |
440 | 0 | } |
441 | 0 | } |
442 | 0 | while ((XML_REVISIONS != tokenId || XML_READER_TYPE_END_ELEMENT != tokenType) && 1 == ret); |
443 | 0 | return ret; |
444 | 0 | } |
445 | | |
446 | | int libabw::ABWParser::readIgnoredWords(xmlTextReaderPtr reader) |
447 | 0 | { |
448 | 0 | int ret = 1; |
449 | 0 | int tokenId = XML_TOKEN_INVALID; |
450 | 0 | int tokenType = -1; |
451 | 0 | do |
452 | 0 | { |
453 | 0 | ret = xmlTextReaderRead(reader); |
454 | 0 | tokenId = getElementToken(reader); |
455 | 0 | if (XML_TOKEN_INVALID == tokenId) |
456 | 0 | { |
457 | 0 | ABW_DEBUG_MSG(("ABWParser::readIgnoreWords: unknown token %s\n", xmlTextReaderConstName(reader))); |
458 | 0 | } |
459 | 0 | tokenType = xmlTextReaderNodeType(reader); |
460 | 0 | switch (tokenId) |
461 | 0 | { |
462 | 0 | default: |
463 | 0 | break; |
464 | 0 | } |
465 | 0 | } |
466 | 0 | while ((XML_IGNOREDWORDS != tokenId || XML_READER_TYPE_END_ELEMENT != tokenType) && 1 == ret); |
467 | 0 | return ret; |
468 | 0 | } |
469 | | |
470 | | void libabw::ABWParser::readPageSize(xmlTextReaderPtr reader) |
471 | 0 | { |
472 | 0 | ABWXMLString width = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("width")); |
473 | 0 | ABWXMLString height = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("height")); |
474 | 0 | ABWXMLString units = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("units")); |
475 | 0 | ABWXMLString pageScale = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("page-scale")); |
476 | 0 | if (m_collector) |
477 | 0 | m_collector->collectPageSize((const char *)width, (const char *)height, (const char *)units, (const char *)pageScale); |
478 | 0 | } |
479 | | |
480 | | void libabw::ABWParser::readSection(xmlTextReaderPtr reader) |
481 | 0 | { |
482 | 0 | ABWXMLString id = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("id")); |
483 | 0 | ABWXMLString type = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("type")); |
484 | 0 | ABWXMLString footer = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("footer")); |
485 | 0 | ABWXMLString footerLeft = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("footer-even")); |
486 | 0 | ABWXMLString footerFirst = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("footer-first")); |
487 | 0 | ABWXMLString footerLast = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("footer-last")); |
488 | 0 | ABWXMLString header = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("header")); |
489 | 0 | ABWXMLString headerLeft = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("header-even")); |
490 | 0 | ABWXMLString headerFirst = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("header-first")); |
491 | 0 | ABWXMLString headerLast = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("header-last")); |
492 | 0 | ABWXMLString props = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("props")); |
493 | |
|
494 | 0 | if (!type || (xmlStrncmp(type.get(), call_BAD_CAST_OnConst("header"), 6) && xmlStrncmp(type.get(), call_BAD_CAST_OnConst("footer"), 6))) |
495 | 0 | { |
496 | 0 | if (m_collector) |
497 | 0 | m_collector->collectSectionProperties((const char *)footer, (const char *)footerLeft, |
498 | 0 | (const char *)footerFirst, (const char *)footerLast, |
499 | 0 | (const char *)header, (const char *)headerLeft, |
500 | 0 | (const char *)headerFirst, (const char *)headerLast, |
501 | 0 | (const char *)props); |
502 | 0 | } |
503 | 0 | else |
504 | 0 | { |
505 | 0 | if (m_collector) |
506 | 0 | m_collector->collectHeaderFooter((const char *)id, (const char *)type); |
507 | 0 | } |
508 | 0 | } |
509 | | |
510 | | int libabw::ABWParser::readD(xmlTextReaderPtr reader) |
511 | 0 | { |
512 | 0 | ABWXMLString name = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("name")); |
513 | 0 | ABWXMLString mimeType = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("mime-type")); |
514 | |
|
515 | 0 | ABWXMLString tmpBase64 = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("base64")); |
516 | 0 | bool base64(false); |
517 | 0 | if (tmpBase64) |
518 | 0 | { |
519 | 0 | findBool((const char *)tmpBase64, base64); |
520 | 0 | } |
521 | |
|
522 | 0 | int ret = 1; |
523 | 0 | int tokenId = XML_TOKEN_INVALID; |
524 | 0 | int tokenType = -1; |
525 | 0 | do |
526 | 0 | { |
527 | 0 | ret = xmlTextReaderRead(reader); |
528 | 0 | tokenId = getElementToken(reader); |
529 | 0 | if (XML_TOKEN_INVALID == tokenId) |
530 | 0 | { |
531 | 0 | ABW_DEBUG_MSG(("ABWParser::readD: unknown token %s\n", xmlTextReaderConstName(reader))); |
532 | 0 | } |
533 | 0 | tokenType = xmlTextReaderNodeType(reader); |
534 | 0 | switch (tokenType) |
535 | 0 | { |
536 | 0 | case XML_READER_TYPE_TEXT: |
537 | 0 | case XML_READER_TYPE_CDATA: |
538 | 0 | { |
539 | 0 | const xmlChar *data = xmlTextReaderConstValue(reader); |
540 | 0 | if (data) |
541 | 0 | { |
542 | 0 | librevenge::RVNGBinaryData binaryData; |
543 | 0 | if (base64) |
544 | 0 | binaryData.appendBase64Data((const char *)data); |
545 | 0 | else |
546 | 0 | binaryData.append(data, (unsigned long) xmlStrlen(data)); |
547 | 0 | if (m_collector) |
548 | 0 | m_collector->collectData((const char *)name, (const char *)mimeType, binaryData); |
549 | 0 | } |
550 | 0 | break; |
551 | 0 | } |
552 | 0 | default: |
553 | 0 | break; |
554 | 0 | } |
555 | 0 | } |
556 | 0 | while ((XML_D != tokenId || XML_READER_TYPE_END_ELEMENT != tokenType) && 1 == ret); |
557 | 0 | return ret; |
558 | 0 | } |
559 | | |
560 | | void libabw::ABWParser::readS(xmlTextReaderPtr reader) |
561 | 0 | { |
562 | 0 | ABWXMLString type = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("type")); |
563 | 0 | ABWXMLString name = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("name")); |
564 | 0 | ABWXMLString basedon = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("basedon")); |
565 | 0 | ABWXMLString followedby = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("followedby")); |
566 | 0 | ABWXMLString props = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("props")); |
567 | 0 | if (type) |
568 | 0 | { |
569 | 0 | if (m_collector) |
570 | 0 | { |
571 | 0 | switch (type[0]) |
572 | 0 | { |
573 | 0 | case 'P': |
574 | 0 | case 'C': |
575 | 0 | m_collector->collectTextStyle((const char *)name, (const char *)basedon, (const char *)followedby, (const char *)props); |
576 | 0 | break; |
577 | 0 | default: |
578 | 0 | break; |
579 | 0 | } |
580 | 0 | } |
581 | 0 | } |
582 | 0 | } |
583 | | |
584 | | void libabw::ABWParser::readA(xmlTextReaderPtr reader) |
585 | 0 | { |
586 | 0 | ABWXMLString href = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("xlink:href")); |
587 | 0 | if (m_collector) |
588 | 0 | m_collector->openLink((const char *)href); |
589 | 0 | } |
590 | | |
591 | | void libabw::ABWParser::readP(xmlTextReaderPtr reader) |
592 | 0 | { |
593 | 0 | ABWXMLString level = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("level")); |
594 | 0 | ABWXMLString listid = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("listid")); |
595 | 0 | ABWXMLString parentid = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("parentid")); |
596 | 0 | ABWXMLString style = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("style")); |
597 | 0 | ABWXMLString props = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("props")); |
598 | 0 | if (m_collector) |
599 | 0 | m_collector->collectParagraphProperties((const char *)level, (const char *)listid, (const char *)parentid, |
600 | 0 | (const char *)style, (const char *)props); |
601 | 0 | } |
602 | | |
603 | | void libabw::ABWParser::readC(xmlTextReaderPtr reader) |
604 | 0 | { |
605 | 0 | ABWXMLString style = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("style")); |
606 | 0 | ABWXMLString props = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("props")); |
607 | 0 | if (m_collector) |
608 | 0 | m_collector->collectCharacterProperties((const char *)style, (const char *)props); |
609 | |
|
610 | 0 | } |
611 | | |
612 | | void libabw::ABWParser::readEndnote(xmlTextReaderPtr reader) |
613 | 0 | { |
614 | 0 | ABWXMLString id = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("endnote-id")); |
615 | 0 | if (m_collector) |
616 | 0 | m_collector->openEndnote((const char *)id); |
617 | 0 | } |
618 | | |
619 | | void libabw::ABWParser::readField(xmlTextReaderPtr reader) |
620 | 0 | { |
621 | 0 | ABWXMLString type = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("type")); |
622 | | //ABWXMLString style = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("style")); |
623 | | //ABWXMLString props = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("props")); |
624 | 0 | ABWXMLString id = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("xid")); |
625 | 0 | if (m_collector) |
626 | 0 | m_collector->openField(type, id); |
627 | 0 | } |
628 | | |
629 | | void libabw::ABWParser::readFoot(xmlTextReaderPtr reader) |
630 | 0 | { |
631 | 0 | ABWXMLString id = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("footnote-id")); |
632 | 0 | if (m_collector) |
633 | 0 | m_collector->openFoot((const char *)id); |
634 | 0 | } |
635 | | |
636 | | void libabw::ABWParser::readTable(xmlTextReaderPtr reader) |
637 | 0 | { |
638 | 0 | ABWXMLString props = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("props")); |
639 | 0 | if (m_collector) |
640 | 0 | m_collector->openTable((const char *)props); |
641 | 0 | } |
642 | | |
643 | | void libabw::ABWParser::readCell(xmlTextReaderPtr reader) |
644 | 0 | { |
645 | 0 | ABWXMLString props = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("props")); |
646 | 0 | if (m_collector) |
647 | 0 | m_collector->openCell((const char *)props); |
648 | 0 | } |
649 | | |
650 | | void libabw::ABWParser::readImage(xmlTextReaderPtr reader) |
651 | 0 | { |
652 | 0 | ABWXMLString props = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("props")); |
653 | 0 | ABWXMLString dataid = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("dataid")); |
654 | 0 | if (m_collector) |
655 | 0 | m_collector->insertImage((const char *)dataid, (const char *)props); |
656 | 0 | } |
657 | | |
658 | | void libabw::ABWParser::readFrame(xmlTextReaderPtr reader) |
659 | 0 | { |
660 | 0 | if (!m_collector) |
661 | 0 | return; |
662 | 0 | ABWXMLString props = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("props")); |
663 | 0 | ABWXMLString imageId = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("strux-image-dataid")); |
664 | 0 | ABWXMLString title = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("title")); |
665 | 0 | ABWXMLString alt = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("alt")); |
666 | 0 | if (!m_state->m_inStyleParsing) |
667 | 0 | { |
668 | 0 | m_state->m_collectorStack.push(std::move(m_collector)); |
669 | 0 | m_collector.reset(new ABWContentCollector(m_iface, m_state->m_tableSizes, m_state->m_data, m_state->m_listElements)); |
670 | 0 | } |
671 | 0 | m_collector->openFrame((const char *)props, (const char *) imageId, (const char *) title, (const char *) alt); |
672 | 0 | } |
673 | | |
674 | | void libabw::ABWParser::readCloseFrame() |
675 | 0 | { |
676 | 0 | if (!m_collector) |
677 | 0 | return; |
678 | 0 | ABWOutputElements *elements=nullptr; |
679 | 0 | bool pageFrame=false; |
680 | 0 | m_collector->closeFrame(elements,pageFrame); |
681 | 0 | if (m_state->m_inStyleParsing) |
682 | 0 | return; |
683 | 0 | if (m_state->m_collectorStack.empty()) |
684 | 0 | { |
685 | 0 | ABW_DEBUG_MSG(("libabw::ABWParser::readCloseFrame: oops, the collector stack is empty\n")); |
686 | 0 | return; // throw ? |
687 | 0 | } |
688 | 0 | if (elements) |
689 | 0 | m_state->m_collectorStack.top()->addFrameElements(*elements, pageFrame); |
690 | 0 | m_collector.swap(m_state->m_collectorStack.top()); |
691 | 0 | m_state->m_collectorStack.pop(); |
692 | 0 | } |
693 | | |
694 | | void libabw::ABWParser::readL(xmlTextReaderPtr reader) |
695 | 0 | { |
696 | 0 | ABWXMLString id = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("id")); |
697 | 0 | ABWXMLString listDecimal = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("list-decimal")); |
698 | 0 | if (!listDecimal) |
699 | 0 | listDecimal = xmlCharStrdup("NULL"); |
700 | 0 | ABWXMLString listDelim = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("list-delim")); |
701 | 0 | ABWXMLString parentid = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("parentid")); |
702 | 0 | ABWXMLString startValue = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("start-value")); |
703 | 0 | ABWXMLString type = xmlTextReaderGetAttribute(reader, call_BAD_CAST_OnConst("type")); |
704 | 0 | if (m_collector) |
705 | 0 | m_collector->collectList((const char *)id, (const char *)listDecimal, (const char *)listDelim, |
706 | 0 | (const char *)parentid, (const char *)startValue, (const char *)type); |
707 | 0 | } |
708 | | |
709 | | /* vim:set shiftwidth=2 softtabstop=2 expandtab: */ |