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