Coverage Report

Created: 2026-03-12 06:42

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libetonyek/src/lib/contexts/IWORKTabularModelElement.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 "IWORKTabularModelElement.h"
11
12
#include <cassert>
13
#include <ctime>
14
#include <memory>
15
#include <sstream>
16
17
#include <boost/lexical_cast.hpp>
18
19
#include "libetonyek_xml.h"
20
#include "IWORKCollector.h"
21
#include "IWORKDictionary.h"
22
#include "IWORKFormatElement.h"
23
#include "IWORKFormulaElement.h"
24
#include "IWORKProperties.h"
25
#include "IWORKRefContext.h"
26
#include "IWORKStyle.h"
27
#include "IWORKTable.h"
28
#include "IWORKText.h"
29
#include "IWORKTextStorageElement.h"
30
#include "IWORKToken.h"
31
#include "IWORKXMLParserState.h"
32
#include "IWORKXMLContextBase.h"
33
34
35
namespace libetonyek
36
{
37
38
using boost::lexical_cast;
39
using boost::optional;
40
using std::shared_ptr;
41
using std::string;
42
namespace
43
{
44
45
class CellCoordinates: public IWORKXMLEmptyContextBase
46
{
47
public:
48
  CellCoordinates(IWORKXMLParserState &state, boost::optional<std::pair<unsigned,unsigned> > &coordinates)
49
0
    : IWORKXMLEmptyContextBase(state)
50
0
    , m_column()
51
0
    , m_row()
52
0
    , m_coordinates(coordinates)
53
0
  {
54
0
  }
55
protected:
56
  void attribute(int name, const char *value) final;
57
  void endOfElement() final;
58
59
  boost::optional<unsigned> m_column, m_row;
60
  boost::optional<std::pair<unsigned, unsigned> > &m_coordinates;
61
};
62
63
void CellCoordinates::attribute(const int name, const char *const value)
64
0
{
65
0
  switch (name)
66
0
  {
67
0
  case IWORKToken::column | IWORKToken::NS_URI_SF :
68
0
    m_column=lexical_cast<unsigned>(value);
69
0
    break;
70
0
  case IWORKToken::row | IWORKToken::NS_URI_SF :
71
0
    m_row=lexical_cast<unsigned>(value);
72
0
    break;
73
0
  default : // none
74
0
    IWORKXMLEmptyContextBase::attribute(name, value);
75
0
  }
76
0
}
77
78
void CellCoordinates::endOfElement()
79
0
{
80
0
  if (m_column && m_row)
81
0
    m_coordinates=std::make_pair(*m_column,*m_row);
82
0
  else
83
0
  {
84
0
    ETONYEK_DEBUG_MSG(("CellCoordinates[IWORKTabularModelElement.cpp]::endOfElement: uncomplet data\n"));
85
0
  }
86
0
}
87
class CellCommentMappingKey: public IWORKXMLEmptyContextBase
88
{
89
public:
90
  CellCommentMappingKey(IWORKXMLParserState &state, boost::optional<std::pair<unsigned,unsigned> > &coordinates)
91
0
    : IWORKXMLEmptyContextBase(state)
92
0
    , m_coordinates(coordinates)
93
0
  {
94
0
  }
95
protected:
96
  // attribute: sfa:ID sfa:class
97
  IWORKXMLContextPtr_t element(int name) final;
98
99
  boost::optional<std::pair<unsigned, unsigned> > &m_coordinates;
100
};
101
102
IWORKXMLContextPtr_t CellCommentMappingKey::element(int name)
103
0
{
104
0
  switch (name)
105
0
  {
106
0
  case IWORKToken::cell_coordinates | IWORKToken::NS_URI_SF :
107
0
    return std::make_shared<CellCoordinates>(getState(), m_coordinates);
108
0
  default:
109
0
    return IWORKXMLEmptyContextBase::element(name);
110
0
  }
111
0
}
112
113
class CellCommentMappingPair: public IWORKXMLEmptyContextBase
114
{
115
public:
116
  CellCommentMappingPair(IWORKXMLParserState &state, std::map<std::pair<unsigned,unsigned>,ID_t> &coordinateCommentRefMap)
117
0
    : IWORKXMLEmptyContextBase(state)
118
0
    , m_coordinates()
119
0
    , m_ref()
120
0
    , m_coordinateCommentRefMap(coordinateCommentRefMap)
121
0
  {
122
0
  }
123
protected:
124
  // attribute: none
125
  IWORKXMLContextPtr_t element(int name) final;
126
  void endOfElement() final;
127
128
  boost::optional<std::pair<unsigned, unsigned> > m_coordinates;
129
  boost::optional<ID_t> m_ref;
130
  std::map<std::pair<unsigned,unsigned>,ID_t> &m_coordinateCommentRefMap;
131
};
132
133
IWORKXMLContextPtr_t CellCommentMappingPair::element(int name)
134
0
{
135
0
  switch (name)
136
0
  {
137
0
  case IWORKToken::value_ref | IWORKToken::NS_URI_SFA : // attributes: sfa:IDREF and sfa:class
138
0
    return std::make_shared<IWORKRefContext>(getState(), m_ref);
139
0
  case IWORKToken::key | IWORKToken::NS_URI_SFA :
140
0
    return std::make_shared<CellCommentMappingKey>(getState(), m_coordinates);
141
0
  default:
142
0
    return IWORKXMLEmptyContextBase::element(name);
143
0
  }
144
0
}
145
146
void CellCommentMappingPair::endOfElement()
147
0
{
148
0
  if (m_coordinates && m_ref)
149
0
    m_coordinateCommentRefMap[*m_coordinates]=*m_ref;
150
0
  else
151
0
  {
152
0
    ETONYEK_DEBUG_MSG(("CellCommentMappingPair[IWORKTabularModelElement.cpp]::endOfElement: uncomplete data\n"));
153
0
  }
154
0
}
155
156
class CellCommentMapping: public IWORKXMLEmptyContextBase
157
{
158
public:
159
  CellCommentMapping(IWORKXMLParserState &state, std::map<std::pair<unsigned,unsigned>,ID_t> &coordinateCommentRefMap)
160
0
    : IWORKXMLEmptyContextBase(state)
161
0
    , m_coordinateCommentRefMap(coordinateCommentRefMap)
162
0
  {
163
0
  }
164
protected:
165
  // attribute: only ID ?
166
  IWORKXMLContextPtr_t element(int name) final;
167
168
  std::map<std::pair<unsigned,unsigned>,ID_t> &m_coordinateCommentRefMap;
169
};
170
171
IWORKXMLContextPtr_t CellCommentMapping::element(int name)
172
0
{
173
0
  switch (name)
174
0
  {
175
0
  case IWORKToken::pair | IWORKToken::NS_URI_SFA :
176
0
    return std::make_shared<CellCommentMappingPair>(getState(), m_coordinateCommentRefMap);
177
0
  default:
178
0
    return IWORKXMLEmptyContextBase::element(name);
179
0
  }
180
0
}
181
182
}
183
184
namespace
185
{
186
// cell format ?
187
class CfElement : public IWORKXMLEmptyContextBase
188
{
189
public:
190
  explicit CfElement(IWORKXMLParserState &state);
191
192
private:
193
  void attribute(int name, const char *value) override;
194
  IWORKXMLContextPtr_t element(int name) override;
195
196
  optional<IWORKDateTimeFormat> m_dateTimeFormat;
197
  optional<IWORKDurationFormat> m_durationFormat;
198
  optional<IWORKNumberFormat> m_numberFormat;
199
};
200
201
CfElement::CfElement(IWORKXMLParserState &state)
202
0
  : IWORKXMLEmptyContextBase(state)
203
0
  , m_dateTimeFormat()
204
0
  , m_durationFormat()
205
0
  , m_numberFormat()
206
0
{
207
0
}
208
209
void CfElement::attribute(const int name, const char *const value)
210
0
{
211
0
  switch (name)
212
0
  {
213
0
  case IWORKToken::implicit_format_type | IWORKToken::NS_URI_SF : // find 256|261|269
214
0
    break;
215
0
  case IWORKToken::ID | IWORKToken::NS_URI_SFA : // must we store this element ?
216
0
    IWORKXMLEmptyContextBase::attribute(name, value);
217
0
    break;
218
0
  default :
219
0
    ETONYEK_DEBUG_MSG(("CfElement::attribute[IWORKTabularModelElement.cpp]: find some unknown attribute\n"));
220
0
    IWORKXMLEmptyContextBase::attribute(name, value);
221
0
  }
222
0
}
223
224
IWORKXMLContextPtr_t CfElement::element(int name)
225
0
{
226
0
  switch (name)
227
0
  {
228
0
  case IWORKToken::date_format | IWORKToken::NS_URI_SF : // USEME
229
0
    return std::make_shared<IWORKDateTimeFormatElement>(getState(), m_dateTimeFormat);
230
0
  case IWORKToken::duration_format | IWORKToken::NS_URI_SF : // USEME
231
0
    return std::make_shared<IWORKDurationFormatElement>(getState(), m_durationFormat);
232
0
  case IWORKToken::number_format | IWORKToken::NS_URI_SF : // USEME
233
0
    return std::make_shared<IWORKNumberFormatElement>(getState(), m_numberFormat);
234
0
  default:
235
0
    ETONYEK_DEBUG_MSG(("CfElement::element[IWORKTabularModelElement.cpp]: find some unknown element\n"));
236
0
  }
237
0
  return IWORKXMLEmptyContextBase::element(name);
238
0
}
239
}
240
241
namespace
242
{
243
244
class CellContextBase : public IWORKXMLEmptyContextBase
245
{
246
protected:
247
  explicit CellContextBase(IWORKXMLParserState &state, bool isResult=false);
248
249
  void attribute(int name, const char *value) override;
250
  IWORKXMLContextPtr_t element(int name) override;
251
  void endOfElement() override;
252
253
  void emitCell(const bool covered = false);
254
255
  boost::optional<ID_t> m_ref;
256
  bool m_isResult;
257
};
258
259
CellContextBase::CellContextBase(IWORKXMLParserState &state, bool isResult)
260
0
  : IWORKXMLEmptyContextBase(state)
261
0
  , m_ref()
262
0
  , m_isResult(isResult)
263
0
{
264
0
}
265
266
void CellContextBase::attribute(const int name, const char *const value)
267
0
{
268
0
  switch (name)
269
0
  {
270
0
  case IWORKToken::col_span | IWORKToken::NS_URI_SF :
271
0
    getState().m_tableData->m_columnSpan = lexical_cast<unsigned>(value);
272
0
    break;
273
0
  case IWORKToken::ct | IWORKToken::NS_URI_SF :
274
0
    getState().m_tableData->m_cellMove = lexical_cast<unsigned>(value);
275
0
    break;
276
0
  case IWORKToken::row_span | IWORKToken::NS_URI_SF :
277
0
    getState().m_tableData->m_rowSpan = lexical_cast<unsigned>(value);
278
0
    break;
279
0
  case IWORKToken::s | IWORKToken::NS_URI_SF :
280
0
    getState().m_tableData->m_style = getState().getStyleByName(value, getState().getDictionary().m_cellStyles);
281
0
    break;
282
0
  case IWORKToken::f | IWORKToken::NS_URI_SF : // format?
283
0
  case IWORKToken::h | IWORKToken::NS_URI_SF : // height
284
0
  case IWORKToken::w | IWORKToken::NS_URI_SF : // width
285
0
    break;
286
0
  case IWORKToken::ID | IWORKToken::NS_URI_SFA : // can appear in result, store me?
287
0
    IWORKXMLEmptyContextBase::attribute(name,value);
288
0
    break;
289
0
  default:
290
0
    ETONYEK_DEBUG_MSG(("CellContextBase::attribute[IWORKTabularModelElement.cpp]: find some unknown attribute\n"));
291
0
  }
292
0
}
293
294
IWORKXMLContextPtr_t CellContextBase::element(int name)
295
0
{
296
0
  switch (name)
297
0
  {
298
0
  case IWORKToken::cf | IWORKToken::NS_URI_SF :
299
0
    return std::make_shared<CfElement>(getState());
300
0
  case IWORKToken::cf_ref | IWORKToken::NS_URI_SF:
301
0
    return std::make_shared<IWORKRefContext>(getState(), m_ref);
302
0
  default:
303
0
    ETONYEK_DEBUG_MSG(("CellContextBase::element[IWORKTabularModelElement.cpp]: find some unknown element\n"));
304
0
  }
305
0
  return IWORKXMLEmptyContextBase::element(name);
306
0
}
307
308
void CellContextBase::endOfElement()
309
0
{
310
0
  if (!m_isResult)
311
0
    emitCell();
312
0
}
313
314
void CellContextBase::emitCell(const bool covered)
315
0
{
316
0
  const IWORKTableDataPtr_t tableData = getState().m_tableData;
317
318
  // determine the cell's position
319
0
  if (tableData->m_cellMove)
320
0
  {
321
0
    const unsigned ct = get(tableData->m_cellMove);
322
0
    tableData->m_column += ct;
323
0
    if (tableData->m_column>=256)
324
0
    {
325
0
      tableData->m_row+=(tableData->m_column/256);
326
0
      tableData->m_column%=256;
327
0
    }
328
0
  }
329
0
  else
330
0
  {
331
0
    ++tableData->m_column;
332
0
    if (tableData->m_columnSizes.size() == tableData->m_column)
333
0
    {
334
0
      tableData->m_column = 0;
335
0
      ++tableData->m_row;
336
0
    }
337
0
  }
338
0
  assert(tableData->m_columnSizes.size() > tableData->m_column);
339
0
  assert(tableData->m_rowSizes.size() > tableData->m_row);
340
341
  // send the cell to collector
342
0
  if (bool(getState().m_currentTable))
343
0
  {
344
0
    if (covered)
345
0
    {
346
0
      getState().m_currentTable->insertCoveredCell(tableData->m_column, tableData->m_row);
347
0
    }
348
0
    else
349
0
    {
350
0
      IWORKTextPtr_t text(getState().m_currentText);
351
0
      getState().m_currentText.reset();
352
0
      if (bool(tableData->m_content) && tableData->m_type == IWORK_CELL_TYPE_TEXT)
353
0
      {
354
0
        text = getCollector().createText(getState().m_langManager);
355
0
        text->insertText(get(tableData->m_content));
356
0
        text->flushParagraph();
357
0
      }
358
0
      getState().m_currentTable->insertCell(
359
0
        tableData->m_column, tableData->m_row,
360
0
        tableData->m_content, text, tableData->m_dateTime,
361
0
        get_optional_value_or(tableData->m_columnSpan, 1), get_optional_value_or(tableData->m_rowSpan, 1),
362
0
        tableData->m_formula, tableData->m_formulaHC, tableData->m_style, tableData->m_type
363
0
      );
364
0
    }
365
0
  }
366
367
  // reset cell attributes
368
0
  tableData->m_columnSpan.reset();
369
0
  tableData->m_rowSpan.reset();
370
0
  tableData->m_cellMove.reset();
371
0
  tableData->m_content.reset();
372
0
  tableData->m_dateTime.reset();
373
0
  tableData->m_formula.reset();
374
0
  tableData->m_style.reset();
375
0
  tableData->m_type = IWORK_CELL_TYPE_TEXT;
376
0
}
377
378
}
379
380
namespace
381
{
382
383
class GridColumnElement : public IWORKXMLEmptyContextBase
384
{
385
public:
386
  explicit GridColumnElement(IWORKXMLParserState &state);
387
388
private:
389
  void attribute(int name, const char *value) override;
390
  IWORKXMLContextPtr_t element(int name) override;
391
};
392
393
GridColumnElement::GridColumnElement(IWORKXMLParserState &state)
394
0
  : IWORKXMLEmptyContextBase(state)
395
0
{
396
0
}
397
398
void GridColumnElement::attribute(const int name, const char *const value)
399
0
{
400
0
  switch (name)
401
0
  {
402
0
  case IWORKToken::fitting_width | IWORKToken::NS_URI_SF :
403
0
  case IWORKToken::nc | IWORKToken::NS_URI_SF : // look like the number of cells in column
404
0
  case IWORKToken::ncoc | IWORKToken::NS_URI_SF :
405
0
  case IWORKToken::nsc | IWORKToken::NS_URI_SF : // look like the number of special cells in column, ie covered cell
406
0
  case IWORKToken::manually_sized | IWORKToken::NS_URI_SF :
407
0
  case IWORKToken::preferred_width | IWORKToken::NS_URI_SF :
408
0
    break;
409
0
  case IWORKToken::width | IWORKToken::NS_URI_SF :
410
0
    getState().m_tableData->m_columnSizes.push_back(IWORKColumnRowSize(lexical_cast<double>(value)));
411
0
    break;
412
0
  default :
413
0
    ETONYEK_DEBUG_MSG(("GridColumnElement::attribute[IWORKTabularModelElement.cpp]: find some unknown attribute\n"));
414
0
    break;
415
0
  }
416
0
}
417
418
IWORKXMLContextPtr_t GridColumnElement::element(const int name)
419
0
{
420
0
  switch (name)
421
0
  {
422
0
  case IWORKToken::grouping_display | IWORKToken::NS_URI_SF :
423
0
  {
424
0
    static bool first=true;
425
0
    if (first)
426
0
    {
427
0
      ETONYEK_DEBUG_MSG(("GridColumnElement::element: find some grouping-display\n"));
428
0
      first=false;
429
0
    }
430
0
    return IWORKXMLContextPtr_t();
431
0
  }
432
0
  default:
433
0
    ETONYEK_DEBUG_MSG(("GridColumnElement::element[IWORKTabularModelElement.cpp]: find some unknown element\n"));
434
0
  }
435
436
0
  return IWORKXMLEmptyContextBase::element(name);
437
0
}
438
}
439
440
namespace
441
{
442
443
class ColumnsElement : public IWORKXMLElementContextBase
444
{
445
public:
446
  explicit ColumnsElement(IWORKXMLParserState &state);
447
448
private:
449
  IWORKXMLContextPtr_t element(int name) override;
450
};
451
452
ColumnsElement::ColumnsElement(IWORKXMLParserState &state)
453
0
  : IWORKXMLElementContextBase(state)
454
0
{
455
0
  assert(getState().m_tableData->m_columnSizes.empty());
456
0
}
457
458
IWORKXMLContextPtr_t ColumnsElement::element(const int name)
459
0
{
460
0
  switch (name)
461
0
  {
462
0
  case IWORKToken::grid_column | IWORKToken::NS_URI_SF :
463
0
    return std::make_shared<GridColumnElement>(getState());
464
0
  default:
465
0
    ETONYEK_DEBUG_MSG(("ColumnsElement::element[IWORKTabularModelElement.cpp]: find some unknown element\n"));
466
0
  }
467
468
0
  return IWORKXMLContextPtr_t();
469
0
}
470
471
}
472
473
namespace
474
{
475
476
class CbElement : public CellContextBase
477
{
478
public:
479
  explicit CbElement(IWORKXMLParserState &state);
480
private:
481
  void attribute(int name, const char *value) override;
482
};
483
484
CbElement::CbElement(IWORKXMLParserState &state)
485
0
  : CellContextBase(state)
486
0
{
487
0
  getState().m_tableData->m_type = IWORK_CELL_TYPE_BOOL;
488
0
}
489
490
void CbElement::attribute(const int name, const char *const value)
491
0
{
492
0
  switch (name)
493
0
  {
494
0
  case IWORKToken::v | IWORKToken::NS_URI_SF :
495
0
    getState().m_tableData->m_content = value;
496
0
    break;
497
0
  default :
498
0
    CellContextBase::attribute(name, value);
499
0
  }
500
0
}
501
502
}
503
504
namespace
505
{
506
507
class DElement : public CellContextBase
508
{
509
public:
510
  explicit DElement(IWORKXMLParserState &state, bool isResult=false);
511
512
private:
513
  void attribute(int name, const char *value) override;
514
};
515
516
DElement::DElement(IWORKXMLParserState &state, bool isResult)
517
0
  : CellContextBase(state, isResult)
518
0
{
519
0
  getState().m_tableData->m_type = IWORK_CELL_TYPE_DATE_TIME;
520
0
}
521
522
void DElement::attribute(const int name, const char *const value)
523
0
{
524
0
  switch (name)
525
0
  {
526
0
  case IWORKToken::cell_date | IWORKToken::NS_URI_SF :
527
0
    getState().m_tableData->m_content = value;
528
0
    break;
529
0
  default :
530
0
    CellContextBase::attribute(name, value);
531
0
  }
532
0
}
533
534
}
535
536
namespace
537
{
538
539
class DuElement : public CellContextBase
540
{
541
public:
542
  explicit DuElement(IWORKXMLParserState &state);
543
544
private:
545
  void attribute(int name, const char *value) override;
546
};
547
548
DuElement::DuElement(IWORKXMLParserState &state)
549
0
  : CellContextBase(state)
550
0
{
551
0
}
552
553
void DuElement::attribute(const int name, const char *const value)
554
0
{
555
0
  switch (name)
556
0
  {
557
0
  case IWORKToken::du | IWORKToken::NS_URI_SF :
558
0
    getState().m_tableData->m_content = value;
559
0
    getState().m_tableData->m_type = IWORK_CELL_TYPE_DURATION;
560
0
    break;
561
0
  default :
562
0
    CellContextBase::attribute(name, value);
563
0
  }
564
0
}
565
566
}
567
568
namespace
569
{
570
571
class CtElement : public IWORKXMLElementContextBase
572
{
573
public:
574
  explicit CtElement(IWORKXMLParserState &state);
575
576
private:
577
  void attribute(int name, const char *value) override;
578
  IWORKXMLContextPtr_t element(int name) override;
579
};
580
581
CtElement::CtElement(IWORKXMLParserState &state)
582
0
  : IWORKXMLElementContextBase(state)
583
0
{
584
0
}
585
586
void CtElement::attribute(const int name, const char *const value)
587
0
{
588
0
  switch (name)
589
0
  {
590
0
  case IWORKToken::s | IWORKToken::NS_URI_SFA :
591
0
  case IWORKToken::string | IWORKToken::NS_URI_SFA :
592
0
    getState().m_tableData->m_content = value;
593
0
    getState().m_tableData->m_type = IWORK_CELL_TYPE_TEXT;
594
0
    break;
595
0
  default :
596
0
    ETONYEK_DEBUG_MSG(("CtElement::attribute[IWORKTabularModelElement.cpp]: find some unknown attribute\n"));
597
0
    break;
598
0
  }
599
0
}
600
601
IWORKXMLContextPtr_t CtElement::element(const int name)
602
0
{
603
0
  switch (name)
604
0
  {
605
0
  case IWORKToken::so | IWORKToken::NS_URI_SF :
606
0
  case IWORKToken::cell_storage | IWORKToken::NS_URI_SF :
607
0
    if (getState().m_tableData->m_content)
608
0
    {
609
0
      ETONYEK_DEBUG_MSG(("found a text cell with both simple and formatted content\n"));
610
0
    }
611
0
    return std::make_shared<IWORKTextStorageElement>(getState());
612
0
  default :
613
0
    ETONYEK_DEBUG_MSG(("CtElement::element[IWORKTabularModelElement.cpp]: find some unknown element\n"));
614
0
    break;
615
0
  }
616
617
0
  return IWORKXMLContextPtr_t();
618
0
}
619
620
}
621
622
namespace
623
{
624
625
class NElement : public CellContextBase
626
{
627
public:
628
  explicit NElement(IWORKXMLParserState &state, bool isResult=false);
629
630
private:
631
  void attribute(int name, const char *value) override;
632
};
633
634
NElement::NElement(IWORKXMLParserState &state, bool isResult)
635
0
  : CellContextBase(state, isResult)
636
0
{
637
0
  getState().m_tableData->m_type = IWORK_CELL_TYPE_NUMBER;
638
0
}
639
640
void NElement::attribute(const int name, const char *const value)
641
0
{
642
0
  switch (name)
643
0
  {
644
0
  case IWORKToken::v | IWORKToken::NS_URI_SF :
645
0
    getState().m_tableData->m_content = value;
646
0
    break;
647
0
  default :
648
0
    CellContextBase::attribute(name, value);
649
0
  }
650
0
}
651
}
652
653
namespace
654
{
655
656
class OElement : public CellContextBase
657
{
658
public:
659
  explicit OElement(IWORKXMLParserState &state, bool isResult=false);
660
661
private:
662
  void attribute(int name, const char *value) override;
663
  void endOfElement() override;
664
};
665
666
OElement::OElement(IWORKXMLParserState &state, bool isResult)
667
0
  : CellContextBase(state, isResult)
668
0
{
669
0
}
670
671
void OElement::attribute(const int name, const char *const value)
672
0
{
673
0
  switch (name)
674
0
  {
675
0
  case IWORKToken::ho | IWORKToken::NS_URI_SF : // horizontal overlap?
676
0
    break;
677
0
  default :
678
0
    CellContextBase::attribute(name, value);
679
0
  }
680
0
}
681
682
void OElement::endOfElement()
683
0
{
684
0
  emitCell(true);
685
0
}
686
}
687
688
namespace
689
{
690
691
class TElement : public CellContextBase
692
{
693
public:
694
  explicit TElement(IWORKXMLParserState &state, bool isResult=false);
695
696
private:
697
  void startOfElement() override;
698
  IWORKXMLContextPtr_t element(int name) override;
699
};
700
701
TElement::TElement(IWORKXMLParserState &state, bool isResult)
702
0
  : CellContextBase(state, isResult)
703
0
{
704
0
}
705
706
void TElement::startOfElement()
707
0
{
708
0
  if (isCollector() && !m_isResult)
709
0
  {
710
    // CHECKME: can we move this code in the constructor ?
711
0
    assert(!getState().m_currentText);
712
0
    getState().m_currentText = getCollector().createText(getState().m_langManager, false);
713
0
  }
714
0
}
715
716
IWORKXMLContextPtr_t TElement::element(const int name)
717
0
{
718
0
  switch (name)
719
0
  {
720
0
  case IWORKToken::ct | IWORKToken::NS_URI_SF :
721
0
    if (m_isResult && !getState().m_currentText)
722
0
      getState().m_currentText = getCollector().createText(getState().m_langManager, false);
723
0
    return std::make_shared<CtElement>(getState());
724
0
  default:
725
0
    break;
726
0
  }
727
728
0
  return CellContextBase::element(name);
729
0
}
730
}
731
732
namespace
733
{
734
735
class RbElement : public CellContextBase
736
{
737
public:
738
  explicit RbElement(IWORKXMLParserState &state);
739
740
private:
741
  void attribute(int name, const char *value) override;
742
};
743
744
RbElement::RbElement(IWORKXMLParserState &state)
745
0
  : CellContextBase(state, true)
746
0
{
747
0
  getState().m_tableData->m_type = IWORK_CELL_TYPE_BOOL;
748
0
}
749
750
void RbElement::attribute(const int name, const char *const value)
751
0
{
752
0
  switch (name)
753
0
  {
754
0
  case IWORKToken::v | IWORKToken::NS_URI_SF :
755
0
    getState().m_tableData->m_content = value;
756
0
    break;
757
0
  default :
758
0
    CellContextBase::attribute(name, value);
759
0
  }
760
0
}
761
}
762
763
namespace
764
{
765
766
class RElement : public IWORKXMLElementContextBase
767
{
768
public:
769
  explicit RElement(IWORKXMLParserState &state);
770
771
private:
772
  IWORKXMLContextPtr_t element(int name) override;
773
};
774
775
RElement::RElement(IWORKXMLParserState &state)
776
0
  : IWORKXMLElementContextBase(state)
777
0
{
778
0
}
779
780
IWORKXMLContextPtr_t RElement::element(int name)
781
0
{
782
0
  switch (name)
783
0
  {
784
0
  case IWORKToken::rb | IWORKToken::NS_URI_SF :
785
0
    return std::make_shared<RbElement>(getState());
786
0
    break;
787
0
  case IWORKToken::rd | IWORKToken::NS_URI_SF :
788
0
    return std::make_shared<DElement>(getState(), true);
789
0
    break;
790
0
  case IWORKToken::rn | IWORKToken::NS_URI_SF :
791
0
    return std::make_shared<NElement>(getState(), true);
792
0
    break;
793
0
  case IWORKToken::rt | IWORKToken::NS_URI_SF :
794
0
    return std::make_shared<TElement>(getState(), true);
795
0
    break;
796
0
  default:
797
0
    break;
798
0
  }
799
800
0
  ETONYEK_DEBUG_MSG(("RElement::element: found unexpected element\n"));
801
0
  return IWORKXMLContextPtr_t();
802
0
}
803
804
}
805
806
namespace
807
{
808
809
class FElement : public CellContextBase
810
{
811
public:
812
  explicit FElement(IWORKXMLParserState &state);
813
814
private:
815
  IWORKXMLContextPtr_t element(int name) override;
816
};
817
818
FElement::FElement(IWORKXMLParserState &state)
819
0
  : CellContextBase(state)
820
0
{
821
0
}
822
823
IWORKXMLContextPtr_t FElement::element(int name)
824
0
{
825
0
  switch (name)
826
0
  {
827
0
  case IWORKToken::fo | IWORKToken::NS_URI_SF :
828
0
    return std::make_shared<IWORKFoElement>(getState());
829
0
  case IWORKToken::of | IWORKToken::NS_URI_SF :
830
0
    return std::make_shared<IWORKOfElement>(getState());
831
0
  case IWORKToken::r | IWORKToken::NS_URI_SF :
832
0
    return std::make_shared<RElement>(getState());
833
0
  default:
834
0
    break;
835
0
  }
836
837
0
  ETONYEK_DEBUG_MSG(("FElement::element: found unexpected element\n"));
838
0
  return IWORKXMLContextPtr_t();
839
0
}
840
841
}
842
843
namespace
844
{
845
846
class GElement : public CellContextBase
847
{
848
public:
849
  explicit GElement(IWORKXMLParserState &state);
850
};
851
852
GElement::GElement(IWORKXMLParserState &state)
853
0
  : CellContextBase(state)
854
0
{
855
0
}
856
857
}
858
859
namespace
860
{
861
862
class GroupingElement : public CellContextBase
863
{
864
public:
865
  explicit GroupingElement(IWORKXMLParserState &state);
866
private:
867
  void attribute(int name, const char *value) override;
868
  IWORKXMLContextPtr_t element(int name) override;
869
};
870
871
GroupingElement::GroupingElement(IWORKXMLParserState &state)
872
0
  : CellContextBase(state)
873
0
{
874
0
}
875
876
void GroupingElement::attribute(const int name, const char *const value)
877
0
{
878
0
  switch (name)
879
0
  {
880
0
  case IWORKToken::group_formula_string | IWORKToken::NS_URI_SF : // value
881
0
  case IWORKToken::group_formula_value | IWORKToken::NS_URI_SF : // value
882
0
  case IWORKToken::group_formula_value_valid | IWORKToken::NS_URI_SF : // true or false
883
0
    break;
884
0
  default :
885
0
    CellContextBase::attribute(name, value);
886
0
  }
887
0
}
888
889
IWORKXMLContextPtr_t GroupingElement::element(int name)
890
0
{
891
0
  switch (name)
892
0
  {
893
0
  case IWORKToken::groupings_element | IWORKToken::NS_URI_SF :
894
0
  {
895
0
    static bool first=true;
896
0
    if (first)
897
0
    {
898
0
      first=false;
899
0
      ETONYEK_DEBUG_MSG(("GroupingElement::element: oops, find some grouping elements\n"));
900
0
    }
901
0
    return IWORKXMLContextPtr_t();
902
0
  }
903
0
  case IWORKToken::fo | IWORKToken::NS_URI_SF :
904
0
    return std::make_shared<IWORKFoElement>(getState());
905
0
  default:
906
0
    break;
907
0
  }
908
909
0
  return CellContextBase::element(name);
910
0
}
911
}
912
913
namespace
914
{
915
916
struct CellData
917
{
918
  CellData()
919
0
    : m_content()
920
0
    , m_dateTime()
921
0
    , m_formula()
922
0
    , m_style()
923
    , m_type()
924
0
    , m_text()
925
0
  {
926
0
  }
927
928
  boost::optional<std::string> m_content;
929
  boost::optional<IWORKDateTimeData> m_dateTime;
930
  IWORKFormulaPtr_t m_formula;
931
  IWORKStylePtr_t m_style;
932
  IWORKCellType m_type;
933
  IWORKTextPtr_t m_text;
934
};
935
}
936
937
namespace
938
{
939
class PmElement : public CellContextBase
940
{
941
public:
942
  explicit PmElement(IWORKXMLParserState &state);
943
944
private:
945
  IWORKXMLContextPtr_t element(int name) override;
946
  void endOfElement() override;
947
948
private:
949
  std::map<ID_t,CellData> m_contentMap;
950
  boost::optional<ID_t> m_ref;
951
};
952
953
PmElement::PmElement(IWORKXMLParserState &state)
954
0
  : CellContextBase(state)
955
0
  , m_contentMap()
956
0
  , m_ref()
957
0
{
958
0
}
959
960
}
961
962
namespace
963
{
964
class TElementInMenu : public TElement
965
{
966
public:
967
  explicit TElementInMenu(IWORKXMLParserState &state, std::map<ID_t,CellData> &contentMap);
968
969
private:
970
  void endOfElement() override;
971
972
private:
973
  std::map<ID_t,CellData> &m_contentMap;
974
};
975
976
TElementInMenu::TElementInMenu(IWORKXMLParserState &state, std::map<ID_t,CellData> &contentMap)
977
0
  : TElement(state)
978
0
  , m_contentMap(contentMap)
979
0
{
980
0
}
981
982
void TElementInMenu::endOfElement()
983
0
{
984
0
  const IWORKTableDataPtr_t tableData = getState().m_tableData;
985
0
  if (getId())
986
0
  {
987
    // save data
988
0
    auto &data=m_contentMap[*getId()];
989
0
    data.m_content=tableData->m_content;
990
0
    data.m_dateTime=tableData->m_dateTime;
991
0
    data.m_formula=tableData->m_formula;
992
0
    data.m_type=tableData->m_type;
993
0
    data.m_text=getState().m_currentText;
994
0
  }
995
996
  // reset content attributes
997
0
  getState().m_currentText.reset();
998
0
  tableData->m_content.reset();
999
0
  tableData->m_dateTime.reset();
1000
0
  tableData->m_formula.reset();
1001
0
  tableData->m_style.reset();
1002
0
  tableData->m_type = IWORK_CELL_TYPE_TEXT;
1003
0
}
1004
}
1005
1006
namespace
1007
{
1008
1009
class MenuChoicesElement : public IWORKXMLElementContextBase
1010
{
1011
public:
1012
  explicit MenuChoicesElement(IWORKXMLParserState &state, std::map<ID_t,CellData> &contentMap);
1013
1014
private:
1015
  IWORKXMLContextPtr_t element(int name) override;
1016
1017
private:
1018
  std::map<ID_t,CellData> &m_contentMap;
1019
};
1020
1021
MenuChoicesElement::MenuChoicesElement(IWORKXMLParserState &state, std::map<ID_t,CellData> &contentMap)
1022
0
  : IWORKXMLElementContextBase(state)
1023
0
  , m_contentMap(contentMap)
1024
0
{
1025
0
}
1026
1027
IWORKXMLContextPtr_t MenuChoicesElement::element(int name)
1028
0
{
1029
0
  if (name == (IWORKToken::t | IWORKToken::NS_URI_SF))
1030
0
    return std::make_shared<TElementInMenu>(getState(), m_contentMap);
1031
1032
0
  return IWORKXMLContextPtr_t();
1033
0
}
1034
1035
}
1036
1037
namespace
1038
{
1039
IWORKXMLContextPtr_t PmElement::element(int name)
1040
0
{
1041
0
  switch (name)
1042
0
  {
1043
0
  case IWORKToken::menu_choices | IWORKToken::NS_URI_SF :
1044
0
    return std::make_shared<MenuChoicesElement>(getState(), m_contentMap);
1045
0
    break;
1046
0
  case IWORKToken::proxied_cell_ref | IWORKToken::NS_URI_SF :
1047
0
    return std::make_shared<IWORKRefContext>(getState(), m_ref);
1048
0
    break;
1049
0
  default:
1050
0
    ETONYEK_DEBUG_MSG(("PmElement::element[IWORKTabularModelElement.cpp]: found unexpected element\n"));
1051
0
    break;
1052
0
  }
1053
1054
0
  return IWORKXMLContextPtr_t();
1055
0
}
1056
1057
void PmElement::endOfElement()
1058
0
{
1059
0
  if (m_ref)
1060
0
  {
1061
0
    auto const it = m_contentMap.find(get(m_ref));
1062
0
    if (m_contentMap.end() != it)
1063
0
    {
1064
      // restore data
1065
0
      const IWORKTableDataPtr_t tableData = getState().m_tableData;
1066
0
      auto const &data=it->second;
1067
0
      tableData->m_content=data.m_content;
1068
0
      tableData->m_dateTime=data.m_dateTime;
1069
0
      tableData->m_formula=data.m_formula;
1070
0
      tableData->m_type=data.m_type;
1071
0
      getState().m_currentText=data.m_text;
1072
0
    }
1073
0
    else
1074
0
    {
1075
0
      ETONYEK_DEBUG_MSG(("PmElement::endOfElement[IWORKTabularModelElement.cpp]: can not found %s references\n", m_ref->c_str()));
1076
0
    }
1077
0
  }
1078
0
  CellContextBase::endOfElement();
1079
0
}
1080
}
1081
1082
namespace
1083
{
1084
1085
class SElement : public CellContextBase
1086
{
1087
public:
1088
  explicit SElement(IWORKXMLParserState &state);
1089
1090
private:
1091
  void attribute(int name, const char *value) override;
1092
  void endOfElement() override;
1093
};
1094
1095
SElement::SElement(IWORKXMLParserState &state)
1096
0
  : CellContextBase(state)
1097
0
{
1098
0
}
1099
1100
void SElement::attribute(const int name, const char *const value)
1101
0
{
1102
0
  switch (name)
1103
0
  {
1104
0
  case IWORKToken::ct | IWORKToken::NS_URI_SF :
1105
0
    getState().m_tableData->m_cellMove = lexical_cast<unsigned>(value);
1106
0
    break;
1107
0
  case IWORKToken::ho | IWORKToken::NS_URI_SF : // offset to main cell
1108
0
  case IWORKToken::vo | IWORKToken::NS_URI_SF :
1109
0
    break;
1110
0
  default :
1111
0
    CellContextBase::attribute(name,value);
1112
0
  }
1113
0
}
1114
1115
void SElement::endOfElement()
1116
0
{
1117
0
  emitCell(true);
1118
0
}
1119
1120
}
1121
1122
namespace
1123
{
1124
1125
class SlElement : public CellContextBase
1126
{
1127
public:
1128
  explicit SlElement(IWORKXMLParserState &state);
1129
1130
private:
1131
  void attribute(int name, const char *value) override;
1132
};
1133
1134
SlElement::SlElement(IWORKXMLParserState &state)
1135
0
  : CellContextBase(state)
1136
0
{
1137
0
  getState().m_tableData->m_type = IWORK_CELL_TYPE_NUMBER;
1138
0
}
1139
1140
void SlElement::attribute(const int name, const char *const value)
1141
0
{
1142
0
  switch (name)
1143
0
  {
1144
0
  case IWORKToken::v | IWORKToken::NS_URI_SF :
1145
0
    getState().m_tableData->m_content = value;
1146
0
    break;
1147
0
  case IWORKToken::increment | IWORKToken::NS_URI_SF :
1148
0
  case IWORKToken::min_value | IWORKToken::NS_URI_SF :
1149
0
  case IWORKToken::max_value | IWORKToken::NS_URI_SF :
1150
0
  case IWORKToken::slider_orientation | IWORKToken::NS_URI_SF :
1151
0
  case IWORKToken::slider_position | IWORKToken::NS_URI_SF :
1152
0
    break;
1153
0
  default :
1154
0
    CellContextBase::attribute(name, value);
1155
0
  }
1156
0
}
1157
1158
}
1159
1160
namespace
1161
{
1162
1163
class StElement : public CellContextBase
1164
{
1165
public:
1166
  explicit StElement(IWORKXMLParserState &state);
1167
1168
private:
1169
  void attribute(int name, const char *value) override;
1170
};
1171
1172
StElement::StElement(IWORKXMLParserState &state)
1173
0
  : CellContextBase(state)
1174
0
{
1175
0
  getState().m_tableData->m_type = IWORK_CELL_TYPE_NUMBER;
1176
0
}
1177
1178
void StElement::attribute(const int name, const char *const value)
1179
0
{
1180
0
  switch (name)
1181
0
  {
1182
0
  case IWORKToken::v | IWORKToken::NS_URI_SF :
1183
0
    getState().m_tableData->m_content = value;
1184
0
    break;
1185
0
  case IWORKToken::increment | IWORKToken::NS_URI_SF :
1186
0
  case IWORKToken::min_value | IWORKToken::NS_URI_SF :
1187
0
  case IWORKToken::max_value | IWORKToken::NS_URI_SF :
1188
0
    break;
1189
0
  default :
1190
0
    CellContextBase::attribute(name, value);
1191
0
  }
1192
0
}
1193
1194
}
1195
1196
namespace
1197
{
1198
class ContentSizeElement : public IWORKXMLElementContextBase
1199
{
1200
public:
1201
  explicit ContentSizeElement(IWORKXMLParserState &state);
1202
1203
private:
1204
  void attribute(int name, const char *value) override;
1205
  IWORKXMLContextPtr_t element(int name) override;
1206
};
1207
1208
ContentSizeElement::ContentSizeElement(IWORKXMLParserState &state)
1209
0
  : IWORKXMLElementContextBase(state)
1210
0
{
1211
0
}
1212
1213
void ContentSizeElement::attribute(const int name, const char *const /*value*/)
1214
0
{
1215
0
  switch (name)
1216
0
  {
1217
0
  case IWORKToken::h | IWORKToken::NS_URI_SFA : // horizontal size
1218
0
  case IWORKToken::w | IWORKToken::NS_URI_SFA : // vertical size
1219
0
    break;
1220
0
  default :
1221
0
    ETONYEK_DEBUG_MSG(("ContentSizeElement::attribute[IWORKTabularModelElement.cpp]: found unexpected attribute\n"));
1222
0
    break;
1223
0
  }
1224
0
}
1225
1226
#ifndef DEBUG
1227
IWORKXMLContextPtr_t ContentSizeElement::element(int)
1228
#else
1229
IWORKXMLContextPtr_t ContentSizeElement::element(int name)
1230
#endif
1231
0
{
1232
0
  ETONYEK_DEBUG_MSG(("ContentSizeElement::element[IWORKTabularModelElement.cpp]: found unexpected element %d\n", name));
1233
0
  return IWORKXMLContextPtr_t();
1234
0
}
1235
}
1236
1237
namespace
1238
{
1239
1240
class GenericCellElement : public IWORKXMLEmptyContextBase
1241
{
1242
public:
1243
  explicit GenericCellElement(IWORKXMLParserState &state, bool isResult=false);
1244
protected:
1245
  void emitCell(const bool covered);
1246
1247
  void attribute(int name, const char *value) override;
1248
  IWORKXMLContextPtr_t element(int name) override;
1249
  void endOfElement() override;
1250
1251
protected:
1252
  bool m_isResult;
1253
private:
1254
  boost::optional<std::string> m_id;
1255
  boost::optional<ID_t> m_styleRef;
1256
};
1257
1258
GenericCellElement::GenericCellElement(IWORKXMLParserState &state, bool isResult)
1259
0
  : IWORKXMLEmptyContextBase(state)
1260
0
  , m_isResult(isResult)
1261
0
  , m_id()
1262
0
  , m_styleRef()
1263
0
{
1264
0
}
1265
1266
void GenericCellElement::attribute(const int name, const char *const value)
1267
0
{
1268
0
  switch (name)
1269
0
  {
1270
0
  case IWORKToken::ID | IWORKToken::NS_URI_SFA :
1271
0
    if (!m_isResult)
1272
0
    {
1273
0
      ETONYEK_DEBUG_MSG(("GenericCellElement::attribute: found unexpected id field\n"));
1274
0
    }
1275
0
    m_id=value;
1276
0
    break;
1277
0
  case IWORKToken::col | IWORKToken::NS_URI_SF :
1278
0
    getState().m_tableData->m_column = (unsigned) int_cast(value);
1279
0
    break;
1280
0
  case IWORKToken::flags | IWORKToken::NS_URI_SF : // find 4 ?
1281
0
    break;
1282
0
  case IWORKToken::row | IWORKToken::NS_URI_SF :
1283
0
    getState().m_tableData->m_row = (unsigned) int_cast(value);
1284
0
    break;
1285
0
  case IWORKToken::col_span | IWORKToken::NS_URI_SF :
1286
0
    getState().m_tableData->m_columnSpan = lexical_cast<unsigned>(value);
1287
0
    break;
1288
0
  case IWORKToken::row_span | IWORKToken::NS_URI_SF :
1289
0
    getState().m_tableData->m_rowSpan = lexical_cast<unsigned>(value);
1290
0
    break;
1291
0
  default :
1292
0
    ETONYEK_DEBUG_MSG(("GenericCellElement::attribute[IWORKTabularModelElement.cpp]: found unexpected attribute\n"));
1293
0
  }
1294
0
}
1295
1296
IWORKXMLContextPtr_t GenericCellElement::element(int name)
1297
0
{
1298
0
  switch (name)
1299
0
  {
1300
0
  case IWORKToken::NS_URI_SF | IWORKToken::cell_style_ref :
1301
0
    return std::make_shared<IWORKRefContext>(getState(), m_styleRef);
1302
0
  case IWORKToken::NS_URI_SF | IWORKToken::content_size :
1303
0
    return std::make_shared<ContentSizeElement>(getState());
1304
0
  default:
1305
0
    break;
1306
0
  }
1307
0
  ETONYEK_DEBUG_MSG(("GenericCellElement::element[IWORKTabularModelElement.cpp]: found unexpected element\n"));
1308
0
  return IWORKXMLContextPtr_t();
1309
0
}
1310
1311
void GenericCellElement::endOfElement()
1312
0
{
1313
0
  if (!m_isResult)
1314
0
    emitCell(false);
1315
0
}
1316
1317
void GenericCellElement::emitCell(const bool covered)
1318
0
{
1319
  // determine the style
1320
0
  if (m_styleRef)
1321
0
    getState().m_tableData->m_style = getState().getStyleByName(get(m_styleRef).c_str(), getState().getDictionary().m_cellStyles);
1322
1323
0
  const IWORKTableDataPtr_t tableData = getState().m_tableData;
1324
0
  assert(tableData->m_columnSizes.size() > tableData->m_column);
1325
0
  assert(tableData->m_rowSizes.size() > tableData->m_row);
1326
1327
  // send the cell to collector
1328
0
  if (bool(getState().m_currentTable))
1329
0
  {
1330
0
    if (covered)
1331
0
    {
1332
0
      getState().m_currentTable->insertCoveredCell(tableData->m_column, tableData->m_row);
1333
0
    }
1334
0
    else
1335
0
    {
1336
0
      IWORKTextPtr_t text(getState().m_currentText);
1337
0
      getState().m_currentText.reset();
1338
0
      if (bool(tableData->m_content) && tableData->m_type == IWORK_CELL_TYPE_TEXT)
1339
0
      {
1340
0
        text = getCollector().createText(getState().m_langManager);
1341
0
        text->insertText(get(tableData->m_content));
1342
0
        text->flushParagraph();
1343
0
      }
1344
0
      getState().m_currentTable->insertCell(
1345
0
        tableData->m_column, tableData->m_row,
1346
0
        tableData->m_content, text, tableData->m_dateTime,
1347
0
        get_optional_value_or(tableData->m_columnSpan, 1), get_optional_value_or(tableData->m_rowSpan, 1),
1348
0
        tableData->m_formula, tableData->m_formulaHC, tableData->m_style, tableData->m_type
1349
0
      );
1350
0
    }
1351
0
  }
1352
1353
  // reset cell attributes
1354
0
  tableData->m_columnSpan.reset();
1355
0
  tableData->m_rowSpan.reset();
1356
0
  tableData->m_content.reset();
1357
0
  tableData->m_dateTime.reset();
1358
0
  tableData->m_formula.reset();
1359
0
  tableData->m_style.reset();
1360
0
  tableData->m_type = IWORK_CELL_TYPE_TEXT;
1361
0
}
1362
}
1363
1364
namespace
1365
{
1366
1367
class BoolCellElement : public GenericCellElement
1368
{
1369
public:
1370
  explicit BoolCellElement(IWORKXMLParserState &state, bool isResult=false);
1371
private:
1372
  void attribute(int name, const char *value) override;
1373
};
1374
1375
BoolCellElement::BoolCellElement(IWORKXMLParserState &state, bool isResult)
1376
0
  : GenericCellElement(state, isResult)
1377
0
{
1378
0
  if (!m_isResult)
1379
0
    getState().m_tableData->m_type = IWORK_CELL_TYPE_BOOL;
1380
0
}
1381
1382
void BoolCellElement::attribute(const int name, const char *const value)
1383
0
{
1384
0
  switch (name)
1385
0
  {
1386
0
  case IWORKToken::value | IWORKToken::NS_URI_SF :
1387
0
    getState().m_tableData->m_type = IWORK_CELL_TYPE_BOOL;
1388
0
    getState().m_tableData->m_content = value;
1389
0
    break;
1390
0
  default :
1391
0
    GenericCellElement::attribute(name, value);
1392
0
  }
1393
0
}
1394
1395
}
1396
1397
namespace
1398
{
1399
class DateCellElement : public GenericCellElement
1400
{
1401
public:
1402
  explicit DateCellElement(IWORKXMLParserState &state, bool isResult=false);
1403
1404
private:
1405
  void attribute(int name, const char *value) override;
1406
};
1407
1408
DateCellElement::DateCellElement(IWORKXMLParserState &state, bool isResult)
1409
0
  : GenericCellElement(state, isResult)
1410
0
{
1411
0
  if (!m_isResult)
1412
0
    getState().m_tableData->m_type = IWORK_CELL_TYPE_DATE_TIME;
1413
0
}
1414
1415
void DateCellElement::attribute(const int name, const char *const value)
1416
0
{
1417
0
  switch (name)
1418
0
  {
1419
0
  case IWORKToken::cell_date | IWORKToken::NS_URI_SF :
1420
0
  {
1421
0
    IWORKDateTimeData time;
1422
0
    if (value && sscanf(value,"%d-%d-%dT%d:%d:%f",&time.m_year, &time.m_month, &time.m_day, &time.m_hour, &time.m_minute, &time.m_second)==6)
1423
0
    {
1424
0
      getState().m_tableData->m_type = IWORK_CELL_TYPE_DATE_TIME;
1425
0
      getState().m_tableData->m_dateTime = time;
1426
0
    }
1427
0
    else
1428
0
    {
1429
0
      ETONYEK_DEBUG_MSG(("DateCellElement::attribute: can not convert %s\n", value));
1430
0
    }
1431
0
    break;
1432
0
  }
1433
0
  default:
1434
0
    return GenericCellElement::attribute(name,value);
1435
0
  }
1436
0
}
1437
}
1438
1439
namespace
1440
{
1441
class NumberCellElement : public GenericCellElement
1442
{
1443
public:
1444
  explicit NumberCellElement(IWORKXMLParserState &state, bool isResult=false);
1445
1446
private:
1447
  void attribute(int name, const char *value) override;
1448
};
1449
1450
NumberCellElement::NumberCellElement(IWORKXMLParserState &state, bool isResult)
1451
0
  : GenericCellElement(state, isResult)
1452
0
{
1453
0
  if (!m_isResult)
1454
0
    getState().m_tableData->m_type = IWORK_CELL_TYPE_NUMBER;
1455
0
}
1456
1457
void NumberCellElement::attribute(const int name, const char *const value)
1458
0
{
1459
0
  switch (name)
1460
0
  {
1461
0
  case IWORKToken::value | IWORKToken::NS_URI_SF :
1462
0
    getState().m_tableData->m_type = IWORK_CELL_TYPE_NUMBER;
1463
0
    getState().m_tableData->m_content = value;
1464
0
    break;
1465
0
  default:
1466
0
    return GenericCellElement::attribute(name,value);
1467
0
  }
1468
0
}
1469
}
1470
1471
namespace
1472
{
1473
class SpanCellElement : public GenericCellElement
1474
{
1475
public:
1476
  explicit SpanCellElement(IWORKXMLParserState &state);
1477
1478
private:
1479
  void attribute(int name, const char *value) override;
1480
  void endOfElement() override;
1481
};
1482
1483
SpanCellElement::SpanCellElement(IWORKXMLParserState &state)
1484
0
  : GenericCellElement(state)
1485
0
{
1486
0
}
1487
1488
void SpanCellElement::attribute(const int name, const char *const value)
1489
0
{
1490
0
  switch (name)
1491
0
  {
1492
0
  case IWORKToken::horizontal_offset | IWORKToken::NS_URI_SF :
1493
0
  case IWORKToken::vertical_offset | IWORKToken::NS_URI_SF :
1494
0
    break;
1495
0
  default:
1496
0
    return GenericCellElement::attribute(name,value);
1497
0
  }
1498
0
}
1499
1500
void SpanCellElement::endOfElement()
1501
0
{
1502
0
  emitCell(true);
1503
0
}
1504
}
1505
1506
namespace
1507
{
1508
class TextCellElement : public GenericCellElement
1509
{
1510
public:
1511
  explicit TextCellElement(IWORKXMLParserState &state, bool isResult=false);
1512
1513
private:
1514
  void startOfElement() override;
1515
  IWORKXMLContextPtr_t element(int name) override;
1516
};
1517
1518
TextCellElement::TextCellElement(IWORKXMLParserState &state, bool isResult)
1519
0
  : GenericCellElement(state, isResult)
1520
0
{
1521
0
}
1522
1523
void TextCellElement::startOfElement()
1524
0
{
1525
0
  if (isCollector())
1526
0
  {
1527
    // CHECKME: can we move this code in the constructor ?
1528
0
    assert(!getState().m_currentText);
1529
0
    getState().m_currentText = getCollector().createText(getState().m_langManager, false);
1530
0
  }
1531
0
}
1532
1533
IWORKXMLContextPtr_t TextCellElement::element(const int name)
1534
0
{
1535
0
  switch (name)
1536
0
  {
1537
0
  case IWORKToken::cell_text | IWORKToken::NS_URI_SF :
1538
0
    return std::make_shared<CtElement>(getState());
1539
0
  default:
1540
0
    break;
1541
0
  }
1542
1543
0
  return GenericCellElement::element(name);
1544
0
}
1545
1546
}
1547
1548
namespace
1549
{
1550
class ResultCellElement : public IWORKXMLEmptyContextBase
1551
{
1552
public:
1553
  explicit ResultCellElement(IWORKXMLParserState &state);
1554
1555
private:
1556
  IWORKXMLContextPtr_t element(int name) override;
1557
1558
  boost::optional<ID_t> m_resultRef;
1559
};
1560
1561
ResultCellElement::ResultCellElement(IWORKXMLParserState &state)
1562
0
  : IWORKXMLEmptyContextBase(state)
1563
0
  , m_resultRef()
1564
0
{
1565
0
}
1566
1567
IWORKXMLContextPtr_t ResultCellElement::element(int name)
1568
0
{
1569
0
  switch (name)
1570
0
  {
1571
0
  case IWORKToken::result_bool_cell | IWORKToken::NS_URI_SF :
1572
0
    return std::make_shared<BoolCellElement>(getState(), true);
1573
0
  case IWORKToken::result_date_cell | IWORKToken::NS_URI_SF :
1574
0
    return std::make_shared<DateCellElement>(getState(), true);
1575
0
  case IWORKToken::result_number_cell | IWORKToken::NS_URI_SF :
1576
0
    return std::make_shared<NumberCellElement>(getState(), true);
1577
0
  case IWORKToken::result_text_cell | IWORKToken::NS_URI_SF :
1578
0
    return std::make_shared<TextCellElement>(getState(), true);
1579
0
  default:
1580
0
    break;
1581
0
  }
1582
0
  ETONYEK_DEBUG_MSG(("ResultCellElement::element[IWORKTabularModelElement.cpp]: found unexpected element\n"));
1583
0
  return IWORKXMLContextPtr_t();
1584
0
}
1585
1586
}
1587
1588
namespace
1589
{
1590
class FormulaCellElement : public GenericCellElement
1591
{
1592
public:
1593
  explicit FormulaCellElement(IWORKXMLParserState &state);
1594
1595
private:
1596
  IWORKXMLContextPtr_t element(int name) override;
1597
};
1598
1599
FormulaCellElement::FormulaCellElement(IWORKXMLParserState &state)
1600
0
  : GenericCellElement(state)
1601
0
{
1602
0
}
1603
1604
IWORKXMLContextPtr_t FormulaCellElement::element(int name)
1605
0
{
1606
0
  switch (name)
1607
0
  {
1608
0
  case IWORKToken::formula | IWORKToken::NS_URI_SF :
1609
0
    return std::make_shared<IWORKFormulaElement>(getState());
1610
0
  case IWORKToken::result_cell | IWORKToken::NS_URI_SF :
1611
0
    return std::make_shared<ResultCellElement>(getState());
1612
0
  default:
1613
0
    break;
1614
0
  }
1615
1616
0
  return GenericCellElement::element(name);
1617
0
}
1618
}
1619
1620
namespace
1621
{
1622
1623
class DatasourceElement : public IWORKXMLElementContextBase
1624
{
1625
public:
1626
  explicit DatasourceElement(IWORKXMLParserState &state);
1627
1628
private:
1629
  void startOfElement() override;
1630
  IWORKXMLContextPtr_t element(int name) override;
1631
};
1632
1633
DatasourceElement::DatasourceElement(IWORKXMLParserState &state)
1634
0
  : IWORKXMLElementContextBase(state)
1635
0
{
1636
  // these must be defined before datasource, otherwise we have a problem
1637
0
  assert(!getState().m_tableData->m_columnSizes.empty());
1638
0
  assert(!getState().m_tableData->m_rowSizes.empty());
1639
0
}
1640
1641
void DatasourceElement::startOfElement()
1642
0
{
1643
0
  if (bool(getState().m_currentTable))
1644
0
  {
1645
0
    getState().m_currentTable->setSizes(getState().m_tableData->m_columnSizes, getState().m_tableData->m_rowSizes);
1646
0
    getState().m_currentTable->setBorders(getState().m_tableData->m_verticalLines, getState().m_tableData->m_horizontalLines);
1647
0
  }
1648
0
}
1649
1650
IWORKXMLContextPtr_t DatasourceElement::element(const int name)
1651
0
{
1652
0
  switch (name)
1653
0
  {
1654
0
  case IWORKToken::cb | IWORKToken::NS_URI_SF :
1655
0
    return std::make_shared<CbElement>(getState());
1656
0
  case IWORKToken::d | IWORKToken::NS_URI_SF :
1657
0
    return std::make_shared<DElement>(getState());
1658
0
  case IWORKToken::du | IWORKToken::NS_URI_SF :
1659
0
    return std::make_shared<DuElement>(getState());
1660
0
  case IWORKToken::f | IWORKToken::NS_URI_SF :
1661
0
    return std::make_shared<FElement>(getState());
1662
0
  case IWORKToken::g | IWORKToken::NS_URI_SF :
1663
0
    return std::make_shared<GElement>(getState());
1664
0
  case IWORKToken::grouping | IWORKToken::NS_URI_SF :
1665
0
    return std::make_shared<GroupingElement>(getState());
1666
0
  case IWORKToken::n | IWORKToken::NS_URI_SF :
1667
0
    return std::make_shared<NElement>(getState());
1668
0
  case IWORKToken::o | IWORKToken::NS_URI_SF :
1669
0
    return std::make_shared<OElement>(getState());
1670
0
  case IWORKToken::pm | IWORKToken::NS_URI_SF :
1671
0
    return std::make_shared<PmElement>(getState());
1672
0
  case IWORKToken::s | IWORKToken::NS_URI_SF :
1673
0
    return std::make_shared<SElement>(getState());
1674
0
  case IWORKToken::sl | IWORKToken::NS_URI_SF :
1675
0
    return std::make_shared<SlElement>(getState());
1676
0
  case IWORKToken::st | IWORKToken::NS_URI_SF :
1677
0
    return std::make_shared<StElement>(getState());
1678
0
  case IWORKToken::t | IWORKToken::NS_URI_SF :
1679
0
    return std::make_shared<TElement>(getState());
1680
0
  case IWORKToken::date_cell | IWORKToken::NS_URI_SF :
1681
0
    return std::make_shared<DateCellElement>(getState());
1682
0
  case IWORKToken::generic_cell | IWORKToken::NS_URI_SF :
1683
0
    return std::make_shared<GenericCellElement>(getState());
1684
0
  case IWORKToken::formula_cell | IWORKToken::NS_URI_SF :
1685
0
    return std::make_shared<FormulaCellElement>(getState());
1686
0
  case IWORKToken::number_cell | IWORKToken::NS_URI_SF :
1687
0
    return std::make_shared<NumberCellElement>(getState());
1688
0
  case IWORKToken::span_cell | IWORKToken::NS_URI_SF :
1689
0
    return std::make_shared<SpanCellElement>(getState());
1690
0
  case IWORKToken::text_cell | IWORKToken::NS_URI_SF :
1691
0
    return std::make_shared<TextCellElement>(getState());
1692
0
  default:
1693
0
    break;
1694
0
  }
1695
1696
0
  ETONYEK_DEBUG_MSG(("DatasourceElement::element[IWORKTabularModelElement.cpp]: found unexpected element\n"));
1697
0
  return IWORKXMLContextPtr_t();
1698
0
}
1699
1700
}
1701
1702
namespace
1703
{
1704
1705
class VectorStyleRefElement : public IWORKXMLEmptyContextBase
1706
{
1707
public:
1708
  explicit VectorStyleRefElement(IWORKXMLParserState &state, IWORKGridLine_t &line);
1709
1710
private:
1711
  void attribute(int name, const char *value) override;
1712
  void endOfElement() override;
1713
1714
private:
1715
  IWORKGridLine_t &m_line;
1716
  optional<unsigned> m_startIndex;
1717
  optional<unsigned> m_stopIndex;
1718
};
1719
1720
VectorStyleRefElement::VectorStyleRefElement(IWORKXMLParserState &state, IWORKGridLine_t &line)
1721
0
  : IWORKXMLEmptyContextBase(state)
1722
0
  , m_line(line)
1723
0
  , m_startIndex()
1724
0
  , m_stopIndex()
1725
0
{
1726
0
}
1727
1728
void VectorStyleRefElement::attribute(const int name, const char *const value)
1729
0
{
1730
0
  switch (name)
1731
0
  {
1732
0
  case IWORKToken::NS_URI_SF | IWORKToken::start_index :
1733
0
    m_startIndex = int_cast(value);
1734
0
    break;
1735
0
  case IWORKToken::NS_URI_SF | IWORKToken::stop_index :
1736
0
    m_stopIndex = int_cast(value);
1737
0
    break;
1738
0
  default:
1739
0
    IWORKXMLEmptyContextBase::attribute(name, value);
1740
0
  }
1741
0
}
1742
1743
void VectorStyleRefElement::endOfElement()
1744
0
{
1745
0
  if (getRef() && m_startIndex && m_stopIndex)
1746
0
  {
1747
0
    IWORKStylePtr_t style= getState().getStyleByName(get(getRef()).c_str(), getState().getDictionary().m_vectorStyles);
1748
0
    if (style) m_line.insert_back(m_startIndex.get(), m_stopIndex.get(), style);
1749
0
  }
1750
0
}
1751
1752
}
1753
1754
namespace
1755
{
1756
1757
class StyleRunElement : public IWORKXMLElementContextBase
1758
{
1759
public:
1760
  explicit StyleRunElement(IWORKXMLParserState &state, IWORKGridLineMap_t &gridLines, unsigned maxLines);
1761
1762
private:
1763
  void attribute(int name, const char *value) override;
1764
  IWORKXMLContextPtr_t element(int name) override;
1765
  void endOfElement() override;
1766
1767
private:
1768
  IWORKGridLineMap_t &m_gridLines;
1769
  IWORKGridLine_t m_line;
1770
  optional<unsigned> m_gridlineIndex_;
1771
  optional<unsigned> m_count;
1772
};
1773
1774
StyleRunElement::StyleRunElement(IWORKXMLParserState &state, IWORKGridLineMap_t &gridLines, unsigned maxLines)
1775
0
  : IWORKXMLElementContextBase(state)
1776
0
  , m_gridLines(gridLines)
1777
0
  , m_line(0, maxLines, IWORKStylePtr_t())
1778
0
  , m_gridlineIndex_()
1779
0
  , m_count()
1780
0
{
1781
0
}
1782
1783
void StyleRunElement::attribute(const int name, const char *const value)
1784
0
{
1785
0
  switch (name)
1786
0
  {
1787
0
  case IWORKToken::NS_URI_SF | IWORKToken::gridline_index :
1788
0
    m_gridlineIndex_=int_cast(value);
1789
0
    break;
1790
0
  case IWORKToken::NS_URI_SF | IWORKToken::count : // number of element
1791
0
    m_count=int_cast(value);
1792
0
    break;
1793
0
  default :
1794
0
    ETONYEK_DEBUG_MSG(("StyleRunElement::attribute[IWORKTabularModelElement.cpp]: find some unknown attribute\n"));
1795
0
    break;
1796
0
  }
1797
0
}
1798
1799
IWORKXMLContextPtr_t StyleRunElement::element(const int name)
1800
0
{
1801
0
  switch (name)
1802
0
  {
1803
0
  case IWORKToken::vector_style_ref | IWORKToken::NS_URI_SF :
1804
0
    return std::make_shared<VectorStyleRefElement>(getState(), m_line);
1805
0
  default:
1806
0
    ETONYEK_DEBUG_MSG(("StyleRunElement::element[IWORKTabularModelElement.cpp]: find some unknown element\n"));
1807
0
  }
1808
1809
0
  return IWORKXMLContextPtr_t();
1810
0
}
1811
1812
void StyleRunElement::endOfElement()
1813
0
{
1814
0
  if (m_gridlineIndex_==boost::none)
1815
0
  {
1816
0
    ETONYEK_DEBUG_MSG(("StyleRunElement::endOfElement: can not find the line index\n"));
1817
0
    unsigned lineId=0;
1818
0
    if (!m_gridLines.empty())
1819
0
    {
1820
0
      IWORKGridLineMap_t::const_iterator it=m_gridLines.end();
1821
0
      lineId=(--it)->first+1;
1822
0
    }
1823
0
    m_gridLines.insert(IWORKGridLineMap_t::value_type(lineId,m_line));
1824
0
  }
1825
0
  else
1826
0
  {
1827
0
    if (m_gridLines.find(*m_gridlineIndex_)!=m_gridLines.end())
1828
0
    {
1829
0
      ETONYEK_DEBUG_MSG(("StyleRunElement::endOfElement: oops, line index=%d is already defined\n", int(*m_gridlineIndex_)));
1830
0
    }
1831
0
    else
1832
0
      m_gridLines.insert(IWORKGridLineMap_t::value_type(*m_gridlineIndex_,m_line));
1833
0
  }
1834
0
}
1835
1836
}
1837
1838
1839
namespace
1840
{
1841
1842
class GridlineElement : public IWORKXMLElementContextBase
1843
{
1844
public:
1845
  explicit GridlineElement(IWORKXMLParserState &state, IWORKGridLineMap_t &gridLines, unsigned maxLines);
1846
1847
private:
1848
  IWORKXMLContextPtr_t element(int name) override;
1849
private:
1850
  IWORKGridLineMap_t &m_gridLines;
1851
  unsigned m_maxLines;
1852
};
1853
1854
GridlineElement::GridlineElement(IWORKXMLParserState &state, IWORKGridLineMap_t &gridLines, unsigned maxLines)
1855
0
  : IWORKXMLElementContextBase(state)
1856
0
  , m_gridLines(gridLines)
1857
0
  , m_maxLines(maxLines)
1858
0
{
1859
0
}
1860
1861
IWORKXMLContextPtr_t GridlineElement::element(const int name)
1862
0
{
1863
0
  switch (name)
1864
0
  {
1865
0
  case IWORKToken::style_run | IWORKToken::NS_URI_SF :
1866
0
    return std::make_shared<StyleRunElement>(getState(), m_gridLines, m_maxLines);
1867
0
  default:
1868
0
    ETONYEK_DEBUG_MSG(("GridlineElement::element[IWORKTabularModelElement.cpp]: find some unknown element\n"));
1869
0
  }
1870
1871
0
  return IWORKXMLContextPtr_t();
1872
0
}
1873
1874
}
1875
1876
namespace
1877
{
1878
1879
class GridRowElement : public IWORKXMLEmptyContextBase
1880
{
1881
public:
1882
  explicit GridRowElement(IWORKXMLParserState &state);
1883
1884
private:
1885
  void attribute(int name, const char *value) override;
1886
};
1887
1888
GridRowElement::GridRowElement(IWORKXMLParserState &state)
1889
0
  : IWORKXMLEmptyContextBase(state)
1890
0
{
1891
0
}
1892
1893
void GridRowElement::attribute(const int name, const char *const value)
1894
0
{
1895
0
  switch (name)
1896
0
  {
1897
0
  case IWORKToken::height | IWORKToken::NS_URI_SF :
1898
0
    getState().m_tableData->m_rowSizes.push_back(IWORKColumnRowSize(lexical_cast<double>(value)));
1899
0
    break;
1900
0
  case IWORKToken::fitting_height | IWORKToken::NS_URI_SF :
1901
0
  case IWORKToken::manually_sized | IWORKToken::NS_URI_SF :
1902
0
  case IWORKToken::nc | IWORKToken::NS_URI_SF : // look like the number of cells in row...
1903
0
  case IWORKToken::ncoc | IWORKToken::NS_URI_SF :
1904
0
  case IWORKToken::nsc | IWORKToken::NS_URI_SF : // look like the number of special cells in row, ie covered cell
1905
0
  case IWORKToken::preferred_height | IWORKToken::NS_URI_SF :
1906
0
    break;
1907
0
  default :
1908
0
    ETONYEK_DEBUG_MSG(("GridRowElement::attribute[IWORKTabularModelElement.cpp]: find some unknown attribute\n"));
1909
0
    break;
1910
0
  }
1911
0
}
1912
1913
}
1914
1915
namespace
1916
{
1917
1918
class RowsElement : public IWORKXMLElementContextBase
1919
{
1920
public:
1921
  explicit RowsElement(IWORKXMLParserState &state);
1922
1923
private:
1924
  IWORKXMLContextPtr_t element(int name) override;
1925
};
1926
1927
RowsElement::RowsElement(IWORKXMLParserState &state)
1928
0
  : IWORKXMLElementContextBase(state)
1929
0
{
1930
0
  assert(getState().m_tableData->m_rowSizes.empty());
1931
0
}
1932
1933
IWORKXMLContextPtr_t RowsElement::element(const int name)
1934
0
{
1935
0
  switch (name)
1936
0
  {
1937
0
  case IWORKToken::grid_row | IWORKToken::NS_URI_SF :
1938
0
    return std::make_shared<GridRowElement>(getState());
1939
0
  default:
1940
0
    ETONYEK_DEBUG_MSG(("RowsElement::element[IWORKTabularModelElement.cpp]: find some unknown element\n"));
1941
0
  }
1942
1943
0
  return IWORKXMLContextPtr_t();
1944
0
}
1945
1946
}
1947
1948
namespace
1949
{
1950
1951
class GridElement : public IWORKXMLElementContextBase
1952
{
1953
public:
1954
  explicit GridElement(IWORKXMLParserState &state);
1955
1956
private:
1957
  void attribute(int name, const char *value) override;
1958
  IWORKXMLContextPtr_t element(int name) override;
1959
};
1960
1961
GridElement::GridElement(IWORKXMLParserState &state)
1962
0
  : IWORKXMLElementContextBase(state)
1963
0
{
1964
0
}
1965
1966
void GridElement::attribute(const int name, const char *value)
1967
0
{
1968
0
  switch (name)
1969
0
  {
1970
0
  case IWORKToken::numcols | IWORKToken::NS_URI_SF :
1971
0
    getState().m_tableData->m_numColumns = (unsigned) int_cast(value);
1972
0
    break;
1973
0
  case IWORKToken::numrows | IWORKToken::NS_URI_SF :
1974
0
    getState().m_tableData->m_numRows = (unsigned) int_cast(value);
1975
0
    break;
1976
0
  default :
1977
    // also hiddennumcols hiddennumrows ncc ocnt
1978
0
    break;
1979
0
  }
1980
0
}
1981
1982
IWORKXMLContextPtr_t GridElement::element(const int name)
1983
0
{
1984
0
  switch (name)
1985
0
  {
1986
0
  case IWORKToken::columns | IWORKToken::NS_URI_SF :
1987
0
    return std::make_shared<ColumnsElement>(getState());
1988
0
  case IWORKToken::datasource | IWORKToken::NS_URI_SF :
1989
0
    return std::make_shared<DatasourceElement>(getState());
1990
0
  case IWORKToken::rows | IWORKToken::NS_URI_SF :
1991
0
    return std::make_shared<RowsElement>(getState());
1992
0
  case IWORKToken::vertical_gridline_styles | IWORKToken::NS_URI_SF :
1993
0
    return std::make_shared<GridlineElement>(getState(), getState().m_tableData->m_verticalLines, getState().m_tableData->m_numRows);
1994
0
  case IWORKToken::horizontal_gridline_styles | IWORKToken::NS_URI_SF :
1995
0
    return std::make_shared<GridlineElement>(getState(), getState().m_tableData->m_horizontalLines, getState().m_tableData->m_numColumns);
1996
0
  default:
1997
0
    ETONYEK_DEBUG_MSG(("GridElement::element[IWORKTabularModelElement.cpp]: find some unknown element\n"));
1998
0
  }
1999
2000
0
  return IWORKXMLContextPtr_t();
2001
0
}
2002
2003
}
2004
2005
IWORKTabularModelElement::IWORKTabularModelElement(IWORKXMLParserState &state, bool isDefinition)
2006
0
  : IWORKXMLElementContextBase(state)
2007
0
  , m_isDefinition(isDefinition)
2008
0
  , m_id()
2009
0
  , m_tableName()
2010
0
  , m_tableId()
2011
0
  , m_styleRef()
2012
0
  , m_headerColumns()
2013
0
  , m_headerRows()
2014
0
  , m_footerRows()
2015
0
  , m_coordinateCommentRefMap()
2016
0
{
2017
0
}
2018
2019
void IWORKTabularModelElement::attribute(const int name, const char *value)
2020
0
{
2021
0
  switch (name)
2022
0
  {
2023
0
  case IWORKToken::ID | IWORKToken::NS_URI_SFA :
2024
0
    m_id=value;
2025
0
    break;
2026
0
  case IWORKToken::name | IWORKToken::NS_URI_SF :
2027
0
    m_tableName = value;
2028
0
    break;
2029
0
  case IWORKToken::num_footer_rows | IWORKToken::NS_URI_SF :
2030
0
    m_footerRows = try_int_cast(value);
2031
0
    break;
2032
0
  case IWORKToken::num_header_columns | IWORKToken::NS_URI_SF :
2033
0
    m_headerColumns = try_int_cast(value);
2034
0
    break;
2035
0
  case IWORKToken::num_header_rows | IWORKToken::NS_URI_SF :
2036
0
    m_headerRows = try_int_cast(value);
2037
0
    break;
2038
0
  case IWORKToken::id | IWORKToken::NS_URI_SF :
2039
0
    m_tableId = "SFTGlobalID_" + string(value);
2040
0
    break;
2041
0
  default:
2042
    // also name-is-visible,grouping-enabled,header-rows-frozen,header-columns-frozen
2043
0
    break;
2044
0
  }
2045
0
}
2046
2047
void IWORKTabularModelElement::startOfElement()
2048
0
{
2049
0
  getState().m_tableData = std::make_shared<IWORKTableData>();
2050
0
  if (m_isDefinition)
2051
0
  {
2052
0
    assert(!getState().m_currentTable);
2053
0
    getState().m_currentTable = getCollector().createTable(getState().m_tableNameMap, getState().m_formatNameMap, getState().m_langManager);
2054
0
  }
2055
0
}
2056
2057
IWORKXMLContextPtr_t IWORKTabularModelElement::element(const int name)
2058
0
{
2059
0
  switch (name)
2060
0
  {
2061
0
  case IWORKToken::grid | IWORKToken::NS_URI_SF :
2062
0
    return std::make_shared<GridElement>(getState());
2063
0
  case IWORKToken::tabular_style_ref | IWORKToken::NS_URI_SF :
2064
0
    return std::make_shared<IWORKRefContext>(getState(), m_styleRef);
2065
2066
0
  case IWORKToken::cell_comment_mapping | IWORKToken::NS_URI_SF :
2067
0
    return std::make_shared<CellCommentMapping>(getState(), m_coordinateCommentRefMap);
2068
0
  case IWORKToken::error_warning_mapping | IWORKToken::NS_URI_SF :
2069
0
  case IWORKToken::filterset | IWORKToken::NS_URI_SF :
2070
0
  case IWORKToken::grouping_order | IWORKToken::NS_URI_SF :
2071
0
  case IWORKToken::grouping_state | IWORKToken::NS_URI_SF :
2072
0
  case IWORKToken::sort | IWORKToken::NS_URI_SF :
2073
0
    break;
2074
0
  default:
2075
0
    ETONYEK_DEBUG_MSG(("IWORKTabularModelElement::element: find some unknown element\n"));
2076
0
    break;
2077
0
  }
2078
2079
0
  return IWORKXMLContextPtr_t();
2080
0
}
2081
2082
void IWORKTabularModelElement::endOfElement()
2083
0
{
2084
0
  if (m_tableName && !get(m_tableName).empty())
2085
0
  {
2086
0
    auto &tableMap=*getState().m_tableNameMap;
2087
0
    std::string finalName;
2088
0
    if (bool(getCollector().getWorkSpaceName()))
2089
0
    {
2090
0
      std::stringstream s;
2091
0
      s << get(getCollector().getWorkSpaceName()) << "_" << get(m_tableName);
2092
0
      finalName=s.str();
2093
0
    }
2094
0
    else
2095
0
      finalName=get(m_tableName);
2096
0
    if (tableMap.find(finalName)!=tableMap.end())
2097
0
    {
2098
0
      ETONYEK_DEBUG_MSG(("IWORKTabularModelElement::endElement: a table with name %s already exists\n", finalName.c_str()));
2099
      // let create an unique name
2100
0
      int id=0;
2101
0
      while (true)
2102
0
      {
2103
0
        std::stringstream s;
2104
0
        s << finalName << "_" << ++id;
2105
0
        if (tableMap.find(s.str())!=tableMap.end()) continue;
2106
0
        finalName=s.str();
2107
0
        break;
2108
0
      }
2109
0
    }
2110
0
    tableMap[finalName]=finalName;
2111
0
    if (m_tableId)
2112
0
      tableMap[get(m_tableId)] = finalName;
2113
0
    if (bool(getState().m_currentTable))
2114
0
      getState().m_currentTable->setName(finalName);
2115
0
  }
2116
0
  if (bool(getState().m_currentTable))
2117
0
  {
2118
0
    IWORKStylePtr_t style;
2119
0
    if (m_styleRef)
2120
0
      style=getState().getStyleByName(get(m_styleRef).c_str(), getState().getDictionary().m_tabularStyles);
2121
0
    sendStyle(style, getState().m_currentTable);
2122
0
    getState().m_currentTable->setHeaders(
2123
0
      get_optional_value_or(m_headerColumns, 0), get_optional_value_or(m_headerRows, 0),
2124
0
      get_optional_value_or(m_footerRows, 0));
2125
0
    if (!m_coordinateCommentRefMap.empty())
2126
0
    {
2127
0
      auto &dico=getState().getDictionary().m_tableComments;
2128
0
      for (auto const &it : m_coordinateCommentRefMap)
2129
0
      {
2130
0
        auto dIt=dico.find(it.second);
2131
0
        if (dIt==dico.end() || !dIt->second)
2132
0
        {
2133
0
          ETONYEK_DEBUG_MSG(("IWORKTabularModelElement::endElement: can not find comment with name %s\n", it.second.c_str()));
2134
0
          continue;
2135
0
        }
2136
0
        IWORKOutputElements noteElements;
2137
        // FIXME: we must set the correct sheetref before calling this
2138
0
        dIt->second->draw(noteElements);
2139
0
        getState().m_currentTable->setComment(it.first.first, it.first.second, noteElements);
2140
0
      }
2141
0
    }
2142
0
  }
2143
0
  if (!m_isDefinition)
2144
0
    return;
2145
2146
0
  if (m_id)
2147
0
    getState().getDictionary().m_tabulars[get(m_id)]=getState().m_currentTable;
2148
0
  else
2149
0
  {
2150
0
    ETONYEK_DEBUG_MSG(("IWORKTabularModelElement::endOfElement: can not find the table id\n"));
2151
0
  }
2152
0
  getState().m_tableData.reset();
2153
0
  getState().m_currentTable.reset();
2154
0
}
2155
2156
void IWORKTabularModelElement::sendStyle(const IWORKStylePtr_t &style, const shared_ptr<IWORKTable> &table)
2157
0
{
2158
0
  assert(bool(table));
2159
2160
0
  table->setStyle(style);
2161
0
  if (style)
2162
0
  {
2163
0
    using namespace property;
2164
0
    if (style->has<SFTTableBandedRowsProperty>())
2165
0
      table->setBandedRows(style->get<SFTTableBandedRowsProperty>());
2166
0
    bool headerColumnRepeats = false;
2167
0
    if (style->has<SFTHeaderColumnRepeatsProperty>())
2168
0
      headerColumnRepeats = style->get<SFTHeaderColumnRepeatsProperty>();
2169
0
    bool headerRowRepeats = false;
2170
0
    if (style->has<SFTHeaderRowRepeatsProperty>())
2171
0
      headerRowRepeats = style->get<SFTHeaderRowRepeatsProperty>();
2172
0
    table->setRepeated(headerColumnRepeats, headerRowRepeats);
2173
0
    if (style->has<SFTDefaultBodyCellStyleProperty>())
2174
0
      table->setDefaultCellStyle(IWORKTable::CELL_TYPE_BODY, style->get<SFTDefaultBodyCellStyleProperty>());
2175
0
    if (style->has<SFTDefaultHeaderRowCellStyleProperty>())
2176
0
      table->setDefaultCellStyle(IWORKTable::CELL_TYPE_ROW_HEADER, style->get<SFTDefaultHeaderRowCellStyleProperty>());
2177
0
    if (style->has<SFTDefaultHeaderColumnCellStyleProperty>())
2178
0
      table->setDefaultCellStyle(IWORKTable::CELL_TYPE_COLUMN_HEADER, style->get<SFTDefaultHeaderColumnCellStyleProperty>());
2179
0
    if (style->has<SFTDefaultFooterRowCellStyleProperty>())
2180
0
      table->setDefaultCellStyle(IWORKTable::CELL_TYPE_ROW_FOOTER, style->get<SFTDefaultFooterRowCellStyleProperty>());
2181
0
  }
2182
0
}
2183
2184
}
2185
2186
/* vim:set shiftwidth=2 softtabstop=2 expandtab: */