Coverage Report

Created: 2026-06-13 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libetonyek/src/lib/contexts/IWORKTableInfoElement.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 libetonyek 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 "IWORKTableInfoElement.h"
11
12
#include <memory>
13
14
#include "libetonyek_xml.h"
15
#include "IWORKCollector.h"
16
#include "IWORKDictionary.h"
17
#include "IWORKFormulaElement.h"
18
#include "IWORKGeometryElement.h"
19
#include "IWORKMutableArrayElement.h"
20
#include "IWORKNumberElement.h"
21
#include "IWORKPushCollector.h"
22
#include "IWORKRefContext.h"
23
#include "IWORKStringElement.h"
24
#include "IWORKStyleContainer.h"
25
#include "IWORKTable.h"
26
#include "IWORKText.h"
27
#include "IWORKTextStorageElement.h"
28
#include "IWORKToken.h"
29
#include "IWORKWrapElement.h"
30
#include "IWORKXMLParserState.h"
31
#include "IWORKXMLContextBase.h"
32
33
34
namespace libetonyek
35
{
36
37
namespace
38
{
39
typedef IWORKStyleContainer<+IWORKToken::NS_URI_SF | IWORKToken::table_style, +IWORKToken::NS_URI_SF | IWORKToken::table_style_ref> TableStyleContext;
40
}
41
42
namespace
43
{
44
45
class TableCellContentElement : public IWORKXMLElementContextBase
46
{
47
public:
48
  explicit TableCellContentElement(IWORKXMLParserState &state);
49
50
private:
51
  void attribute(int name, const char *value) override;
52
  IWORKXMLContextPtr_t element(int name) override;
53
};
54
55
TableCellContentElement::TableCellContentElement(IWORKXMLParserState &state)
56
0
  : IWORKXMLElementContextBase(state)
57
0
{
58
0
  if (isCollector())
59
0
  {
60
0
    assert(!getState().m_currentText);
61
0
    getState().m_currentText = getCollector().createText(getState().m_langManager, false);
62
0
  }
63
0
}
64
65
void TableCellContentElement::attribute(const int name, const char *const value)
66
0
{
67
0
  switch (name)
68
0
  {
69
0
  case +IWORKToken::ID | IWORKToken::NS_URI_SFA :
70
0
    IWORKXMLElementContextBase::attribute(name, value);
71
0
    break;
72
0
  default :
73
0
    ETONYEK_DEBUG_MSG(("TableCellContentElement::attribute[IWORKTableInfoElement.cpp]: find some unknown attribute\n"));
74
0
    break;
75
0
  }
76
0
}
77
78
IWORKXMLContextPtr_t TableCellContentElement::element(const int name)
79
0
{
80
0
  switch (name)
81
0
  {
82
0
  case +IWORKToken::text_storage | IWORKToken::NS_URI_SF :
83
0
    getState().m_tableData->m_type = IWORK_CELL_TYPE_TEXT;
84
0
    return std::make_shared<IWORKTextStorageElement>(getState());
85
0
  default :
86
0
    ETONYEK_DEBUG_MSG(("TableCellContentElement::element[IWORKTableInfoElement.cpp]: find some unknown element\n"));
87
0
    break;
88
0
  }
89
90
0
  return IWORKXMLContextPtr_t();
91
0
}
92
93
}
94
95
namespace
96
{
97
98
class TableCellValueElement : public IWORKXMLEmptyContextBase
99
{
100
public:
101
  explicit TableCellValueElement(IWORKXMLParserState &state);
102
103
private:
104
  void attribute(int name, const char *value) override;
105
  IWORKXMLContextPtr_t element(int name) override;
106
  void endOfElement() override;
107
108
  boost::optional<double> m_value;
109
};
110
111
TableCellValueElement::TableCellValueElement(IWORKXMLParserState &state)
112
0
  : IWORKXMLEmptyContextBase(state)
113
0
  , m_value()
114
0
{
115
0
}
116
117
void TableCellValueElement::attribute(const int name, const char *const value)
118
0
{
119
0
  ETONYEK_DEBUG_MSG(("TableCellValueElement::attribute[IWORKTableInfoElement.cpp]: find some unknown attribute\n"));
120
0
  IWORKXMLEmptyContextBase::attribute(name, value);
121
0
}
122
123
IWORKXMLContextPtr_t TableCellValueElement::element(const int name)
124
0
{
125
0
  switch (name)
126
0
  {
127
0
  case +IWORKToken::number | IWORKToken::NS_URI_SF :
128
0
    getState().m_tableData->m_type = IWORK_CELL_TYPE_NUMBER;
129
0
    return std::make_shared<IWORKNumberElement<double> >(getState(), m_value);
130
0
  default:
131
0
    ETONYEK_DEBUG_MSG(("TableCellValueElement::element[IWORKTableInfoElement.cpp]: find some unknown element\n"));
132
0
  }
133
0
  return IWORKXMLContextPtr_t();
134
0
}
135
136
void TableCellValueElement::endOfElement()
137
0
{
138
0
  if (m_value)
139
0
  {
140
0
    std::stringstream s;
141
0
    s << get(m_value);
142
0
    getState().m_tableData->m_content = s.str();
143
0
  }
144
0
}
145
}
146
147
namespace
148
{
149
class TableCellElement : public IWORKXMLEmptyContextBase
150
{
151
public:
152
  explicit TableCellElement(IWORKXMLParserState &state, boost::optional<IWORKTableCell> &value);
153
private:
154
  void attribute(int name, const char *value) override;
155
  IWORKXMLContextPtr_t element(int name) override;
156
  void endOfElement() override;
157
  void emitCell();
158
159
  boost::optional<IWORKTableCell> &m_value;
160
  boost::optional<ID_t> m_styleRef;
161
  boost::optional<ID_t> m_minXBorderRef, m_maxXBorderRef, m_minYBorderRef, m_maxYBorderRef;
162
};
163
164
TableCellElement::TableCellElement(IWORKXMLParserState &state, boost::optional<IWORKTableCell> &value)
165
0
  : IWORKXMLEmptyContextBase(state)
166
0
  , m_value(value)
167
0
  , m_styleRef()
168
0
  , m_minXBorderRef()
169
0
  , m_maxXBorderRef()
170
0
  , m_minYBorderRef()
171
0
  , m_maxYBorderRef()
172
0
{
173
0
  m_value=IWORKTableCell();
174
0
}
175
176
void TableCellElement::attribute(const int name, const char *const value)
177
0
{
178
0
  switch (name)
179
0
  {
180
0
  case +IWORKToken::tableCellPreferredHeight | IWORKToken::NS_URI_SF :
181
0
    get(m_value).m_preferredHeight=try_double_cast(value);
182
0
    break;
183
0
  case +IWORKToken::ID | IWORKToken::NS_URI_SFA : // must we store this element ?
184
0
    IWORKXMLEmptyContextBase::attribute(name, value);
185
0
    break;
186
0
  default :
187
0
    ETONYEK_DEBUG_MSG(("TableCellElement::attribute[IWORKTableInfoElement.cpp]: find some unknown attribute\n"));
188
0
    IWORKXMLEmptyContextBase::attribute(name, value);
189
0
  }
190
0
}
191
192
IWORKXMLContextPtr_t TableCellElement::element(const int name)
193
0
{
194
0
  switch (name)
195
0
  {
196
0
  case +IWORKToken::tableCellStyle_ref | IWORKToken::NS_URI_SF :
197
0
    return std::make_shared<IWORKRefContext>(getState(), m_styleRef);
198
0
  case +IWORKToken::tableCellMinXSide_ref | IWORKToken::NS_URI_SF :
199
0
    return std::make_shared<IWORKRefContext>(getState(), m_minXBorderRef);
200
0
  case +IWORKToken::tableCellMaxXSide_ref | IWORKToken::NS_URI_SF :
201
0
    return std::make_shared<IWORKRefContext>(getState(), m_maxXBorderRef);
202
0
  case +IWORKToken::tableCellMinYSide_ref | IWORKToken::NS_URI_SF :
203
0
    return std::make_shared<IWORKRefContext>(getState(), m_minYBorderRef);
204
0
  case +IWORKToken::tableCellMaxYSide_ref | IWORKToken::NS_URI_SF :
205
0
    return std::make_shared<IWORKRefContext>(getState(), m_maxYBorderRef);
206
0
  case +IWORKToken::tableCellContent | IWORKToken::NS_URI_SF :
207
0
    return std::make_shared<TableCellContentElement>(getState());
208
0
  case +IWORKToken::tableCellFormula | IWORKToken::NS_URI_SF :
209
0
    return std::make_shared<IWORKTableCellFormulaElement>(getState());
210
0
  case +IWORKToken::tableCellValue | IWORKToken::NS_URI_SF :
211
0
    return std::make_shared<TableCellValueElement>(getState());
212
0
  default:
213
0
    ETONYEK_DEBUG_MSG(("TableCellElement::element[IWORKTableInfoElement.cpp]: find some unknown element\n"));
214
0
    break;
215
0
  }
216
0
  return IWORKXMLContextPtr_t();
217
0
}
218
219
void TableCellElement::endOfElement()
220
0
{
221
0
  IWORKTableCell &cell=get(m_value);
222
0
  if (m_styleRef)
223
0
    cell.m_style=getState().getStyleByName(get(m_styleRef).c_str(), getState().getDictionary().m_tableCellStyles);
224
0
  for (int i=0; i<4; ++i)
225
0
  {
226
0
    boost::optional<ID_t> const &ref=
227
0
      i==0 ? m_minXBorderRef : i==1 ? m_maxXBorderRef : i==2 ? m_minYBorderRef : m_maxYBorderRef;
228
0
    if (!ref) continue;
229
0
    const IWORKTableVectorMap_t::const_iterator it = getState().getDictionary().m_tableVectors.find(get(ref));
230
0
    if (it==getState().getDictionary().m_tableVectors.end())
231
0
    {
232
0
      ETONYEK_DEBUG_MSG(("TableCellElement::endOfElement[IWORKTableInfoElement.cpp]: can not find vector %s\n", get(ref).c_str()));
233
0
    }
234
0
    else if (i==0)
235
0
      cell.m_minXBorder=it->second;
236
0
    else if (i==1)
237
0
      cell.m_maxXBorder=it->second;
238
0
    else if (i==2)
239
0
      cell.m_minYBorder=it->second;
240
0
    else
241
0
      cell.m_maxYBorder=it->second;
242
0
  }
243
0
  if (getId())
244
0
    getState().getDictionary().m_tableCells[get(getId())]=cell;
245
0
  emitCell();
246
0
}
247
248
void TableCellElement::emitCell()
249
0
{
250
0
  const IWORKTableDataPtr_t tableData = getState().m_tableData;
251
0
  IWORKTableCell &cell=get(m_value);
252
0
  if (cell.m_minXBorder.m_along && cell.m_minYBorder.m_along
253
0
      && tableData->m_positionToHorizontalLineMap.find(get(cell.m_minXBorder.m_along))
254
0
      != tableData->m_positionToHorizontalLineMap.end()
255
0
      && tableData->m_positionToVerticalLineMap.find(get(cell.m_minYBorder.m_along))
256
0
      != tableData->m_positionToVerticalLineMap.end())
257
0
  {
258
    // column
259
0
    unsigned column=tableData->m_positionToHorizontalLineMap.find(get(cell.m_minXBorder.m_along))->second;
260
0
    unsigned columnSpan=0;
261
0
    auto numColumns=(unsigned) tableData->m_columnSizes.size();
262
0
    if (cell.m_maxXBorder.m_along && tableData->m_positionToHorizontalLineMap.find(get(cell.m_maxXBorder.m_along))
263
0
        != tableData->m_positionToHorizontalLineMap.end())
264
0
      columnSpan=unsigned(tableData->m_positionToHorizontalLineMap.find(get(cell.m_maxXBorder.m_along))->second-column);
265
0
    if (columnSpan+column>numColumns)
266
0
    {
267
0
      ETONYEK_DEBUG_MSG(("TableCellElement::endOfElement[IWORKTableInfoElement.cpp]: column span seems bad\n"));
268
0
      columnSpan=0;
269
0
    }
270
    // row
271
0
    unsigned row=tableData->m_positionToVerticalLineMap.find(get(cell.m_minYBorder.m_along))->second;
272
0
    unsigned rowSpan=0;
273
0
    auto numRows=(unsigned) tableData->m_rowSizes.size();
274
0
    if (cell.m_maxYBorder.m_along && tableData->m_positionToVerticalLineMap.find(get(cell.m_maxYBorder.m_along))
275
0
        != tableData->m_positionToVerticalLineMap.end())
276
0
      rowSpan=unsigned(tableData->m_positionToVerticalLineMap.find(get(cell.m_maxYBorder.m_along))->second-row);
277
0
    if (rowSpan+row>numRows)
278
0
    {
279
0
      ETONYEK_DEBUG_MSG(("TableCellElement::endOfElement[IWORKTableInfoElement.cpp]: row span seems bad\n"));
280
0
      rowSpan=0;
281
0
    }
282
0
    IWORKTextPtr_t text(getState().m_currentText);
283
0
    getState().m_currentText.reset();
284
0
    if (bool(tableData->m_content) && tableData->m_type == IWORK_CELL_TYPE_TEXT)
285
0
    {
286
0
      text = getCollector().createText(getState().m_langManager);
287
0
      text->insertText(get(tableData->m_content));
288
0
      text->flushParagraph();
289
0
    }
290
0
    getState().m_currentTable->insertCell(
291
0
      column, row,
292
0
      tableData->m_content, text, tableData->m_dateTime,
293
0
      columnSpan ? columnSpan : 1, rowSpan ? rowSpan : 1,
294
0
      tableData->m_formula, tableData->m_formulaHC, cell.m_style, tableData->m_type
295
0
    );
296
    // finally update the grid
297
0
    if (rowSpan && cell.m_minXBorder.m_style)
298
0
    {
299
0
      if (tableData->m_verticalLines.find(column)==tableData->m_verticalLines.end())
300
0
        tableData->m_verticalLines.insert(IWORKGridLineMap_t::value_type(column,IWORKGridLine_t(0, numRows+1, IWORKStylePtr_t())));
301
0
      IWORKGridLine_t &cLine=tableData->m_verticalLines.find(column)->second;
302
0
      cLine.insert_back(row, row+rowSpan, cell.m_minXBorder.m_style);
303
0
    }
304
0
    if (rowSpan && columnSpan && cell.m_maxXBorder.m_style)
305
0
    {
306
0
      if (tableData->m_verticalLines.find(column+columnSpan)==tableData->m_verticalLines.end())
307
0
        tableData->m_verticalLines.insert(IWORKGridLineMap_t::value_type(column+columnSpan,IWORKGridLine_t(0, numRows+1, IWORKStylePtr_t())));
308
0
      IWORKGridLine_t &cLine=tableData->m_verticalLines.find(column+columnSpan)->second;
309
0
      cLine.insert_back(row, row+rowSpan, cell.m_maxXBorder.m_style);
310
0
    }
311
0
    if (columnSpan && cell.m_minYBorder.m_style)
312
0
    {
313
0
      if (tableData->m_horizontalLines.find(row)==tableData->m_horizontalLines.end())
314
0
        tableData->m_horizontalLines.insert(IWORKGridLineMap_t::value_type(row,IWORKGridLine_t(0, numColumns+1, IWORKStylePtr_t())));
315
0
      IWORKGridLine_t &cLine=tableData->m_horizontalLines.find(row)->second;
316
0
      cLine.insert_back(column, column+columnSpan, cell.m_minYBorder.m_style);
317
0
    }
318
0
    if (rowSpan && columnSpan && cell.m_maxYBorder.m_style)
319
0
    {
320
0
      if (tableData->m_horizontalLines.find(row+rowSpan)==tableData->m_horizontalLines.end())
321
0
        tableData->m_horizontalLines.insert(IWORKGridLineMap_t::value_type(row+rowSpan,IWORKGridLine_t(0, numColumns+1, IWORKStylePtr_t())));
322
0
      IWORKGridLine_t &cLine=tableData->m_horizontalLines.find(row+rowSpan)->second;
323
0
      cLine.insert_back(column, column+columnSpan, cell.m_maxYBorder.m_style);
324
0
    }
325
0
  }
326
0
  else
327
0
  {
328
0
    ETONYEK_DEBUG_MSG(("TableCellElement::endOfElement[IWORKTableInfoElement.cpp]: can not find cell positions\n"));
329
0
  }
330
331
  // reset cell attributes
332
0
  tableData->m_columnSpan.reset();
333
0
  tableData->m_rowSpan.reset();
334
0
  tableData->m_content.reset();
335
0
  tableData->m_dateTime.reset();
336
0
  tableData->m_formula.reset();
337
0
  tableData->m_style.reset();
338
0
  tableData->m_type = IWORK_CELL_TYPE_TEXT;
339
0
}
340
}
341
342
namespace
343
{
344
typedef IWORKMutableArrayElement<IWORKTableCell, TableCellElement, IWORKPushCollector, +IWORKToken::NS_URI_SF | IWORKToken::table_cell, +IWORKToken::NS_URI_SF | IWORKToken::table_cell_ref> TableCellArrayElement;
345
}
346
347
namespace
348
{
349
class TableModelCellsElement : public IWORKXMLEmptyContextBase
350
{
351
public:
352
  explicit TableModelCellsElement(IWORKXMLParserState &state, std::deque<IWORKTableCell> &colCell, std::deque<IWORKTableCell> &rowCell);
353
private:
354
  IWORKXMLContextPtr_t element(int name) override;
355
  void endOfElement() override;
356
357
  std::unordered_map<ID_t, std::deque<IWORKTableCell> > m_dict;
358
  std::deque<IWORKTableCell> &m_columnsCell;
359
  std::deque<IWORKTableCell> &m_rowsCell;
360
};
361
362
TableModelCellsElement::TableModelCellsElement(IWORKXMLParserState &state, std::deque<IWORKTableCell> &colCell, std::deque<IWORKTableCell> &rowCell)
363
0
  : IWORKXMLEmptyContextBase(state)
364
0
  , m_dict()
365
0
  , m_columnsCell(colCell)
366
0
  , m_rowsCell(rowCell)
367
0
{
368
0
}
369
370
IWORKXMLContextPtr_t TableModelCellsElement::element(const int name)
371
0
{
372
0
  switch (name)
373
0
  {
374
0
  case +IWORKToken::tableCellArrayCellsByColumn | IWORKToken::NS_URI_SF :
375
0
    return std::make_shared<TableCellArrayElement>(getState(), m_dict, getState().getDictionary().m_tableCells, m_columnsCell);
376
0
  case +IWORKToken::tableCellArrayCellsByRow | IWORKToken::NS_URI_SF :
377
0
    return std::make_shared<TableCellArrayElement>(getState(), m_dict, getState().getDictionary().m_tableCells, m_rowsCell);
378
0
  default:
379
0
    ETONYEK_DEBUG_MSG(("TableModelCellsElement::element[IWORKTableInfoElement.cpp]: find some unknown element\n"));
380
0
    break;
381
0
  }
382
0
  return IWORKXMLContextPtr_t();
383
0
}
384
385
void TableModelCellsElement::endOfElement()
386
0
{
387
0
}
388
}
389
390
namespace
391
{
392
class TableVectorElement : public IWORKXMLEmptyContextBase
393
{
394
public:
395
  explicit TableVectorElement(IWORKXMLParserState &state, boost::optional<IWORKTableVector> &value);
396
private:
397
  void attribute(int name, const char *value) override;
398
  IWORKXMLContextPtr_t element(int name) override;
399
  void endOfElement() override;
400
401
  boost::optional<IWORKTableVector> &m_value;
402
  boost::optional<ID_t> m_styleRef;
403
};
404
405
TableVectorElement::TableVectorElement(IWORKXMLParserState &state, boost::optional<IWORKTableVector> &value)
406
0
  : IWORKXMLEmptyContextBase(state)
407
0
  , m_value(value)
408
0
  , m_styleRef()
409
0
{
410
0
  m_value=IWORKTableVector();
411
0
}
412
413
void TableVectorElement::attribute(const int name, const char *const value)
414
0
{
415
0
  switch (name)
416
0
  {
417
0
  case +IWORKToken::tableVectorAlong | IWORKToken::NS_URI_SF :
418
0
    get(m_value).m_along=try_double_cast(value);
419
0
    break;
420
0
  case +IWORKToken::tableVectorAxis | IWORKToken::NS_URI_SF :
421
0
    get(m_value).m_axis=try_int_cast(value);
422
0
    break;
423
0
  case +IWORKToken::tableVectorBegin | IWORKToken::NS_URI_SF :
424
0
    get(m_value).m_beginCell=try_int_cast(value);
425
0
    break;
426
0
  case +IWORKToken::tableVectorEnd | IWORKToken::NS_URI_SF :
427
0
    get(m_value).m_endCell=try_int_cast(value);
428
0
    break;
429
0
  case +IWORKToken::ID | IWORKToken::NS_URI_SFA :
430
0
    IWORKXMLEmptyContextBase::attribute(name, value);
431
0
    break;
432
0
  default :
433
0
    ETONYEK_DEBUG_MSG(("TableVectorElement::attribute[IWORKTableInfoElement.cpp]: find some unknown attribute\n"));
434
0
    IWORKXMLEmptyContextBase::attribute(name, value);
435
0
  }
436
0
}
437
438
IWORKXMLContextPtr_t TableVectorElement::element(const int name)
439
0
{
440
0
  switch (name)
441
0
  {
442
0
  case +IWORKToken::tableVectorStyle_ref | IWORKToken::NS_URI_SF :
443
0
    return std::make_shared<IWORKRefContext>(getState(), m_styleRef);
444
0
  default:
445
0
    ETONYEK_DEBUG_MSG(("TableVectorElement::element[IWORKTableInfoElement.cpp]: find some unknown element\n"));
446
0
    break;
447
0
  }
448
0
  return IWORKXMLContextPtr_t();
449
0
}
450
451
void TableVectorElement::endOfElement()
452
0
{
453
0
  if (m_styleRef)
454
0
    get(m_value).m_style=getState().getStyleByName(get(m_styleRef).c_str(), getState().getDictionary().m_tableVectorStyles);
455
0
  if (getId())
456
0
    getState().getDictionary().m_tableVectors[get(getId())]=get(m_value);
457
0
}
458
}
459
460
namespace
461
{
462
typedef IWORKMutableArrayElement<IWORKTableVector, TableVectorElement, IWORKPushCollector, +IWORKToken::NS_URI_SF | IWORKToken::table_vector> TableVectorArrayElement;
463
}
464
465
namespace
466
{
467
class TableModelVectorsElement : public IWORKXMLEmptyContextBase
468
{
469
public:
470
  explicit TableModelVectorsElement(IWORKXMLParserState &state, std::deque<IWORKTableVector> &colVector, std::deque<IWORKTableVector> &rowVector);
471
private:
472
  IWORKXMLContextPtr_t element(int name) override;
473
  void endOfElement() override;
474
475
  std::unordered_map<ID_t, std::deque<IWORKTableVector> > m_dict;
476
  std::deque<IWORKTableVector> &m_columnsVector;
477
  std::deque<IWORKTableVector> &m_rowsVector;
478
};
479
480
TableModelVectorsElement::TableModelVectorsElement(IWORKXMLParserState &state, std::deque<IWORKTableVector> &colVector, std::deque<IWORKTableVector> &rowVector)
481
0
  : IWORKXMLEmptyContextBase(state)
482
0
  , m_dict()
483
0
  , m_columnsVector(colVector)
484
0
  , m_rowsVector(rowVector)
485
0
{
486
0
}
487
488
IWORKXMLContextPtr_t TableModelVectorsElement::element(const int name)
489
0
{
490
0
  switch (name)
491
0
  {
492
0
  case +IWORKToken::tableVectorArrayColumnVectors | IWORKToken::NS_URI_SF :
493
0
    return std::make_shared<TableVectorArrayElement>(getState(), m_dict, getState().getDictionary().m_tableVectors, m_columnsVector);
494
0
  case +IWORKToken::tableVectorArrayRowVectors | IWORKToken::NS_URI_SF :
495
0
    return std::make_shared<TableVectorArrayElement>(getState(), m_dict, getState().getDictionary().m_tableVectors, m_rowsVector);
496
0
  default:
497
0
    ETONYEK_DEBUG_MSG(("TableModelVectorsElement::element[IWORKTableInfoElement.cpp]: find some unknown element\n"));
498
0
    break;
499
0
  }
500
0
  return IWORKXMLContextPtr_t();
501
0
}
502
503
void TableModelVectorsElement::endOfElement()
504
0
{
505
0
  const IWORKTableDataPtr_t tableData = getState().m_tableData;
506
507
  // normally the columns and rows are sorted
508
0
  double pos=0;
509
0
  bool posSet=false;
510
0
  unsigned line=0;
511
0
  for (auto &col : m_columnsVector)
512
0
  {
513
0
    if (!col.m_along)
514
0
      continue;
515
0
    if (!posSet)
516
0
    {
517
0
      pos=get(col.m_along);
518
0
      posSet=true;
519
0
      tableData->m_positionToHorizontalLineMap[pos]=line;
520
0
    }
521
0
    else if (get(col.m_along)>pos)
522
0
    {
523
0
      tableData->m_columnSizes.push_back(IWORKColumnRowSize(get(col.m_along)-pos));
524
0
      pos=get(col.m_along);
525
0
      tableData->m_positionToHorizontalLineMap[pos]=++line;
526
0
    }
527
0
  }
528
0
  posSet=false;
529
0
  line=0;
530
0
  for (auto &row : m_rowsVector)
531
0
  {
532
0
    if (!row.m_along)
533
0
      continue;
534
0
    if (!posSet)
535
0
    {
536
0
      pos=get(row.m_along);
537
0
      posSet=true;
538
0
      tableData->m_positionToVerticalLineMap[pos]=line;
539
0
    }
540
0
    else if (get(row.m_along)>pos)
541
0
    {
542
0
      tableData->m_rowSizes.push_back(IWORKColumnRowSize(get(row.m_along)-pos));
543
0
      pos=get(row.m_along);
544
0
      tableData->m_positionToVerticalLineMap[pos]=++line;
545
0
    }
546
0
  }
547
0
  if (getState().m_currentTable)
548
0
    getState().m_currentTable->setSizes(getState().m_tableData->m_columnSizes, getState().m_tableData->m_rowSizes);
549
0
}
550
}
551
552
namespace
553
{
554
class TableInfoTableElement : public IWORKXMLElementContextBase
555
{
556
public:
557
  explicit TableInfoTableElement(IWORKXMLParserState &state);
558
559
private:
560
  void attribute(int name, const char *value) override;
561
  void startOfElement() override;
562
  IWORKXMLContextPtr_t element(int name) override;
563
  void endOfElement() override;
564
565
private:
566
  boost::optional<ID_t> m_id;
567
  boost::optional<std::string> m_tableId;
568
  boost::optional<ID_t> m_styleRef;
569
  bool m_hasHeaderColumn;
570
  bool m_hasHeaderRow;
571
  std::deque<IWORKTableCell> m_columnsCell;
572
  std::deque<IWORKTableCell> m_rowsCell;
573
  std::deque<IWORKTableVector> m_columnsVector;
574
  std::deque<IWORKTableVector> m_rowsVector;
575
};
576
577
TableInfoTableElement::TableInfoTableElement(IWORKXMLParserState &state)
578
0
  : IWORKXMLElementContextBase(state)
579
0
  , m_id()
580
0
  , m_tableId()
581
0
  , m_styleRef()
582
0
  , m_hasHeaderColumn(false)
583
0
  , m_hasHeaderRow(false)
584
0
  , m_columnsCell()
585
0
  , m_rowsCell()
586
0
  , m_columnsVector()
587
0
  , m_rowsVector()
588
0
{
589
0
}
590
591
void TableInfoTableElement::attribute(const int name, const char *value)
592
0
{
593
0
  switch (name)
594
0
  {
595
0
  case +IWORKToken::ID | IWORKToken::NS_URI_SFA :
596
0
    m_id=value;
597
0
    break;
598
0
  case +IWORKToken::tableModelIsHeaderColumn | IWORKToken::NS_URI_SF :
599
0
    m_hasHeaderColumn =bool_cast(value);
600
0
    break;
601
0
  case +IWORKToken::tableModelIsHeaderRow | IWORKToken::NS_URI_SF :
602
0
    m_hasHeaderRow =bool_cast(value);
603
0
    break;
604
0
  default:
605
    // also tableModelResize, tableIsForPasteboardOnly
606
0
    break;
607
0
  }
608
0
}
609
610
void TableInfoTableElement::startOfElement()
611
0
{
612
0
  getState().m_tableData = std::make_shared<IWORKTableData>();
613
0
}
614
615
IWORKXMLContextPtr_t TableInfoTableElement::element(const int name)
616
0
{
617
0
  switch (name)
618
0
  {
619
0
  case +IWORKToken::tableModelStyle_ref | IWORKToken::NS_URI_SF :
620
0
    return std::make_shared<IWORKRefContext>(getState(), m_styleRef);
621
0
  case +IWORKToken::tableModelPartitionSource | IWORKToken::NS_URI_SF : // contains id + frame data
622
0
    break;
623
0
  case +IWORKToken::tableModelVectors | IWORKToken::NS_URI_SF :
624
0
    return std::make_shared<TableModelVectorsElement>(getState(), m_columnsVector, m_rowsVector);
625
0
  case +IWORKToken::tableModelCells | IWORKToken::NS_URI_SF :
626
0
    return std::make_shared<TableModelCellsElement>(getState(), m_columnsCell, m_rowsCell);
627
0
  case +IWORKToken::tableModelTableID | IWORKToken::NS_URI_SF :
628
0
    return std::make_shared<IWORKStringElement>(getState(), m_tableId);
629
0
  default:
630
0
    ETONYEK_DEBUG_MSG(("TableInfoTableElement::element[IWORKTableInfoElement.cpp]: find some unknown element\n"));
631
0
    break;
632
0
  }
633
0
  return IWORKXMLContextPtr_t();
634
0
}
635
636
void TableInfoTableElement::endOfElement()
637
0
{
638
0
  if (bool(getState().m_currentTable))
639
0
  {
640
0
    auto const &table=getState().m_currentTable;
641
0
    if (m_styleRef)
642
0
    {
643
0
      IWORKStylePtr_t style;
644
0
      style=getState().getStyleByName(get(m_styleRef).c_str(), getState().getDictionary().m_tableStyles);
645
0
      table->setStyle(style);
646
0
    }
647
0
    table->setRepeated(m_hasHeaderColumn, m_hasHeaderRow);
648
0
    table->setHeaders(0, 0, 0);
649
0
  }
650
0
}
651
}
652
653
IWORKTableInfoElement::IWORKTableInfoElement(IWORKXMLParserState &state)
654
0
  : IWORKXMLElementContextBase(state)
655
0
  , m_style()
656
0
  , m_wrap()
657
0
{
658
0
}
659
660
void IWORKTableInfoElement::startOfElement()
661
0
{
662
0
  assert(!getState().m_currentTable);
663
0
  getState().m_currentTable = getCollector().createTable(getState().m_tableNameMap, getState().m_formatNameMap, getState().m_langManager);
664
0
  if (isCollector())
665
0
    getCollector().startLevel();
666
0
}
667
668
IWORKXMLContextPtr_t IWORKTableInfoElement::element(const int name)
669
0
{
670
0
  switch (name)
671
0
  {
672
0
  case +IWORKToken::geometry | IWORKToken::NS_URI_SF :
673
0
    return std::make_shared<IWORKGeometryElement>(getState());
674
0
  case +IWORKToken::style | IWORKToken::NS_URI_SF :
675
0
    return std::make_shared<TableStyleContext>(getState(), m_style, getState().getDictionary().m_tableStyles);
676
0
  case +IWORKToken::tableInfoTable | IWORKToken::NS_URI_SF :
677
0
    return std::make_shared<TableInfoTableElement>(getState());
678
0
  case +IWORKToken::NS_URI_SF | IWORKToken::wrap : // USEME
679
0
    return std::make_shared<IWORKWrapElement>(getState(), m_wrap);
680
0
  default:
681
0
    ETONYEK_DEBUG_MSG(("IWORKTableInfoElement::element: find some unknown element\n"));
682
0
  }
683
684
0
  return IWORKXMLContextPtr_t();
685
0
}
686
687
void IWORKTableInfoElement::endOfElement()
688
0
{
689
0
  if (!isCollector())
690
0
    return;
691
692
0
  if (m_style && getState().m_currentTable)
693
0
    getState().m_currentTable->setStyle(m_style);
694
0
  getCollector().collectTable(getState().m_currentTable);
695
0
  getState().m_currentTable.reset();
696
697
0
  getCollector().endLevel();
698
0
}
699
700
}
701
702
/* vim:set shiftwidth=2 softtabstop=2 expandtab: */