Coverage Report

Created: 2026-09-14 06:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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: */