Coverage Report

Created: 2026-09-14 06:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libstaroffice/src/lib/StarObjectSpreadsheet.cxx
Line
Count
Source
1
/* -*- Mode: C++; c-default-style: "k&r"; indent-tabs-mode: nil; tab-width: 2; c-basic-offset: 2 -*- */
2
3
/* libstaroffice
4
* Version: MPL 2.0 / LGPLv2+
5
*
6
* The contents of this file are subject to the Mozilla Public License Version
7
* 2.0 (the "License"); you may not use this file except in compliance with
8
* the License or as specified alternatively below. You may obtain a copy of
9
* the License at http://www.mozilla.org/MPL/
10
*
11
* Software distributed under the License is distributed on an "AS IS" basis,
12
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13
* for the specific language governing rights and limitations under the
14
* License.
15
*
16
* Major Contributor(s):
17
* Copyright (C) 2002 William Lachance (wrlach@gmail.com)
18
* Copyright (C) 2002,2004 Marc Maurer (uwog@uwog.net)
19
* Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba@bluewin.ch)
20
* Copyright (C) 2006, 2007 Andrew Ziem
21
* Copyright (C) 2011, 2012 Alonso Laurent (alonso@loria.fr)
22
*
23
*
24
* All Rights Reserved.
25
*
26
* For minor contributions see the git repository.
27
*
28
* Alternatively, the contents of this file may be used under the terms of
29
* the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"),
30
* in which case the provisions of the LGPLv2+ are applicable
31
* instead of those above.
32
*/
33
34
#include <cstring>
35
#include <iomanip>
36
#include <iostream>
37
#include <limits>
38
#include <set>
39
#include <sstream>
40
41
#include <librevenge/librevenge.h>
42
43
#include "StarAttribute.hxx"
44
#include "StarCellFormula.hxx"
45
#include "StarEncryption.hxx"
46
#include "StarFileManager.hxx"
47
#include "StarItemPool.hxx"
48
#include "StarObjectDraw.hxx"
49
#include "StarObjectModel.hxx"
50
#include "StarObjectSmallText.hxx"
51
#include "StarState.hxx"
52
#include "StarZone.hxx"
53
54
#include "STOFFCell.hxx"
55
#include "STOFFCellStyle.hxx"
56
#include "STOFFFont.hxx"
57
#include "STOFFGraphicStyle.hxx"
58
#include "STOFFOLEParser.hxx"
59
#include "STOFFPageSpan.hxx"
60
#include "STOFFSubDocument.hxx"
61
#include "STOFFSpreadsheetListener.hxx"
62
#include "STOFFTable.hxx"
63
64
#include "StarFormatManager.hxx"
65
66
#include "StarObjectSpreadsheet.hxx"
67
68
/** Internal: the structures of a StarObjectSpreadsheet */
69
namespace StarObjectSpreadsheetInternal
70
{
71
////////////////////////////////////////
72
//! Internal: a structure use to read ScMultiRecord zone of a StarObjectSpreadsheet
73
struct ScMultiRecord {
74
  //! constructor
75
  explicit ScMultiRecord(StarZone &zone)
76
111k
    : m_zone(zone)
77
111k
    , m_zoneOpened(false)
78
111k
    , m_actualRecord(0)
79
111k
    , m_numRecord(0)
80
111k
    , m_startPos(0)
81
111k
    , m_endPos(0)
82
111k
    , m_endContentPos(0)
83
111k
    , m_endRecordPos(0)
84
111k
    , m_offsetList()
85
111k
    , m_extra("")
86
111k
  {
87
111k
  }
88
  //! destructor
89
  ~ScMultiRecord()
90
111k
  {
91
111k
    if (m_zoneOpened) {
92
7.88k
      STOFF_DEBUG_MSG(("StarObjectSpreadsheetInternal::ScMultiRecord::~ScMultiRecord: INTERNAL PROBLEM\n"));
93
7.88k
      close("Entries(BADScMultiRecord):###");
94
7.88k
    }
95
111k
  }
96
  //! try to open a zone
97
  bool open()
98
111k
  {
99
111k
    if (m_zoneOpened) {
100
0
      STOFF_DEBUG_MSG(("StarObjectSpreadsheetInternal::ScMultiRecord: oops a record has been opened\n"));
101
0
      return false;
102
0
    }
103
111k
    m_actualRecord=m_numRecord=0;
104
111k
    m_startPos=m_endPos=m_endContentPos=m_endRecordPos=0;
105
111k
    m_offsetList.clear();
106
107
111k
    STOFFInputStreamPtr input=m_zone.input();
108
111k
    long pos=input->tell();
109
111k
    long lastPos=m_zone.getRecordLevel() ? m_zone.getRecordLastPosition() : input->size();
110
111k
    if (!m_zone.openSCRecord()) {
111
1.23k
      input->seek(pos, librevenge::RVNG_SEEK_SET);
112
1.23k
      return false;
113
1.23k
    }
114
110k
    m_zoneOpened=true;
115
110k
    m_startPos=input->tell();
116
110k
    m_endPos=m_zone.getRecordLastPosition();
117
    // sc_rechead.cxx ScMultipleReadHeader::ScMultipleReadHeader
118
110k
    if (m_endPos+6>lastPos) {
119
45
      STOFF_DEBUG_MSG(("StarObjectSpreadsheetInternal::ScMultiRecord::open: oops the zone seems too short\n"));
120
45
      m_extra="###zoneShort,";
121
45
      return false;
122
45
    }
123
110k
    input->seek(m_endPos, librevenge::RVNG_SEEK_SET);
124
110k
    uint16_t id;
125
110k
    uint32_t tableLen;
126
110k
    *input>>id >> tableLen;
127
110k
    m_endRecordPos=input->tell()+long(tableLen);
128
110k
    if (id!=0x4200 || m_endRecordPos > lastPos) {
129
7.84k
      STOFF_DEBUG_MSG(("StarObjectSpreadsheetInternal::ScMultiRecord::open: oops can not find the size data\n"));
130
7.84k
      m_extra="###zoneShort,";
131
7.84k
      m_endRecordPos=0;
132
7.84k
      return false;
133
7.84k
    }
134
102k
    m_numRecord=tableLen/4;
135
829k
    for (uint32_t i=0; i<m_numRecord; ++i)
136
727k
      m_offsetList.push_back(static_cast<uint32_t>(input->readULong(4)));
137
102k
    input->seek(m_startPos, librevenge::RVNG_SEEK_SET);
138
102k
    return true;
139
110k
  }
140
  //! try to close a zone
141
  void close(std::string const &wh)
142
220k
  try
143
220k
  {
144
220k
    if (!m_zoneOpened) {
145
0
      STOFF_DEBUG_MSG(("StarObjectSpreadsheetInternal::ScMultiRecord::close: can not find any opened zone\n"));
146
0
      return;
147
0
    }
148
220k
    if (m_endContentPos>0) {
149
1
      STOFF_DEBUG_MSG(("StarObjectSpreadsheetInternal::ScMultiRecord::close: argh, the current content is not closed, let close it\n"));
150
1
      closeContent(wh);
151
1
    }
152
153
220k
    m_zoneOpened=false;
154
220k
    STOFFInputStreamPtr input=m_zone.input();
155
220k
    if (input->tell()<m_endPos && input->tell()+4>=m_endPos) { // small diff is possible
156
6.28k
      m_zone.ascii().addDelimiter(input->tell(),'|');
157
6.28k
      input->seek(m_zone.getRecordLastPosition(), librevenge::RVNG_SEEK_SET);
158
6.28k
    }
159
214k
    else if (input->tell()==m_endPos)
160
83.9k
      input->seek(m_zone.getRecordLastPosition(), librevenge::RVNG_SEEK_SET);
161
220k
    m_zone.closeSCRecord(wh);
162
220k
    if (m_endRecordPos>0)
163
102k
      input->seek(m_endRecordPos, librevenge::RVNG_SEEK_SET);
164
220k
  }
165
220k
  catch (...)
166
220k
  {
167
0
    STOFF_DEBUG_MSG(("StarObjectSpreadsheetInternal::ScMultiRecord::close: catch an exception...\n"));
168
0
    m_zoneOpened=false;
169
0
  }
170
  //! returns true if a content is opened
171
  bool isContentOpened() const
172
65.4k
  {
173
65.4k
    return m_endContentPos>0;
174
65.4k
  }
175
  //! try to go to the new content positon
176
  bool openContent(std::string const &wh)
177
391k
  {
178
391k
    if (m_endContentPos>0) {
179
542
      STOFF_DEBUG_MSG(("StarObjectSpreadsheetInternal::ScMultiRecord::openContent: argh, the current content is not closed, let close it\n"));
180
542
      closeContent(wh);
181
542
    }
182
391k
    STOFFInputStreamPtr input=m_zone.input();
183
391k
    if (m_actualRecord >= m_numRecord || m_actualRecord >= uint32_t(m_offsetList.size()) ||
184
388k
        input->tell()+long(m_offsetList[size_t(m_actualRecord)])>m_endPos)
185
10.9k
      return false;
186
    // ScMultipleReadHeader::StartEntry
187
380k
    m_endContentPos=input->tell()+long(m_offsetList[size_t(m_actualRecord)]);
188
380k
    ++m_actualRecord;
189
380k
    return true;
190
391k
  }
191
  //! try to go to the new content positon
192
  bool closeContent(std::string const &wh)
193
380k
  {
194
380k
    if (m_endContentPos<=0) {
195
0
      STOFF_DEBUG_MSG(("StarObjectSpreadsheetInternal::ScMultiRecord::closeContent: no content opened\n"));
196
0
      return false;
197
0
    }
198
380k
    STOFFInputStreamPtr input=m_zone.input();
199
380k
    if (input->tell()<m_endContentPos && input->tell()+4>=m_endContentPos) { // small diff is possible ?
200
147
      m_zone.ascii().addDelimiter(input->tell(),'|');
201
147
      input->seek(m_endContentPos, librevenge::RVNG_SEEK_SET);
202
147
    }
203
380k
    else if (input->tell()!=m_endContentPos) {
204
25.1k
      STOFF_DEBUG_MSG(("StarObjectSpreadsheetInternal::ScMultiRecord::getContent: find extra data\n"));
205
25.1k
      m_zone.ascii().addPos(input->tell());
206
25.1k
      libstoff::DebugStream f;
207
25.1k
      f << wh << ":###extra";
208
25.1k
      m_zone.ascii().addNote(f.str().c_str());
209
25.1k
      input->seek(m_endContentPos, librevenge::RVNG_SEEK_SET);
210
25.1k
    }
211
380k
    m_endContentPos=0;
212
380k
    return true;
213
380k
  }
214
  //! returns the last content position
215
  long getContentLastPosition() const
216
379k
  {
217
379k
    if (m_endContentPos<=0) {
218
0
      STOFF_DEBUG_MSG(("StarObjectSpreadsheetInternal::ScMultiRecord::getContentLastPosition: no content opened\n"));
219
0
      return m_endPos;
220
0
    }
221
379k
    return m_endContentPos;
222
379k
  }
223
224
  //! basic operator<< ; print header data
225
  friend std::ostream &operator<<(std::ostream &o, ScMultiRecord const &r)
226
0
  {
227
0
    if (!r.m_zoneOpened) {
228
0
      o << r.m_extra;
229
0
      return o;
230
0
    }
231
0
    if (r.m_numRecord) o << "num[record]=" << r.m_numRecord << ",";
232
0
    if (!r.m_offsetList.empty()) {
233
0
      o << "offset=[";
234
0
      for (unsigned int i : r.m_offsetList) o << i << ",";
235
0
      o << "],";
236
0
    }
237
0
    o << r.m_extra;
238
0
    return o;
239
0
  }
240
protected:
241
  //! the main zone
242
  StarZone &m_zone;
243
  //! true if a SfxRecord has been opened
244
  bool m_zoneOpened;
245
  //! the actual record
246
  uint32_t m_actualRecord;
247
  //! the number of record
248
  uint32_t m_numRecord;
249
  //! the start of data position
250
  long m_startPos;
251
  //! the end of data position
252
  long m_endPos;
253
  //! the end of the content position
254
  long m_endContentPos;
255
  //! the end of the record position
256
  long m_endRecordPos;
257
  //! the list of offset
258
  std::vector<uint32_t> m_offsetList;
259
  //! extra data
260
  std::string m_extra;
261
private:
262
  ScMultiRecord(ScMultiRecord const &orig);
263
  ScMultiRecord &operator=(ScMultiRecord const &orig);
264
};
265
266
//! Internal: the cell of a StarObjectSpreadsheet
267
class Cell : public STOFFCell
268
{
269
public:
270
  //! constructor
271
  explicit Cell(STOFFVec2i pos=STOFFVec2i(0,0))
272
750k
    : STOFFCell()
273
750k
    , m_content()
274
750k
    , m_textZone()
275
750k
    , m_hasNote(false)
276
750k
  {
277
750k
    setPosition(pos);
278
750k
  }
279
  //! destructor
280
  ~Cell() override;
281
  //! the cell content
282
  STOFFCellContent m_content;
283
  //! the text zone(if set)
284
  std::shared_ptr<StarObjectSmallText> m_textZone;
285
  //! flag to know if the cell has some note
286
  bool m_hasNote;
287
  //! the notes text, date, author
288
  librevenge::RVNGString m_notes[3];
289
};
290
291
Cell::~Cell()
292
750k
{
293
750k
}
294
////////////////////////////////////////
295
//! Internal: structure used to store a row of a StarObjectSpreadsheet
296
class RowContent
297
{
298
public:
299
  //! constructor
300
  RowContent()
301
349k
    : m_colToCellMap()
302
349k
    , m_colToAttributeMap()
303
349k
  {
304
349k
  }
305
  //! try to compress the item list and create a attribute list
306
  void compressItemList()
307
180k
  {
308
180k
    std::map<STOFFVec2i,std::shared_ptr<StarAttribute> > oldMap=m_colToAttributeMap;
309
180k
    std::map<STOFFVec2i,std::shared_ptr<StarAttribute> >::const_iterator it=oldMap.begin();
310
180k
    m_colToAttributeMap.clear();
311
312
180k
    std::shared_ptr<StarAttribute> actAttribute;
313
180k
    STOFFVec2i actPos(0,-1);
314
2.98M
    while (it!=oldMap.end()) {
315
      // first check for not filled row
316
2.80M
      std::shared_ptr<StarAttribute> newAttrib=it->second;
317
2.80M
      if (it->first[0]!=actPos[1]+1 || newAttrib.get()!=actAttribute.get()) {
318
435k
        if (actAttribute)
319
330k
          m_colToAttributeMap[actPos]=actAttribute;
320
435k
        actAttribute=newAttrib;
321
435k
        actPos=STOFFVec2i(it->first[0], it->first[0]-1);
322
435k
      }
323
2.80M
      actPos[1]=it->first[1];
324
2.80M
      ++it;
325
2.80M
    }
326
180k
    if (actAttribute)
327
104k
      m_colToAttributeMap[actPos]=actAttribute;
328
180k
  }
329
  //! map col -> cell
330
  std::map<int, std::shared_ptr<Cell> > m_colToCellMap;
331
  //! map col -> attribute
332
  std::map<STOFFVec2i, std::shared_ptr<StarAttribute> > m_colToAttributeMap;
333
};
334
335
////////////////////////////////////////
336
//! Internal: a table of a StarObjectSpreadsheet
337
class Table : public STOFFTable
338
{
339
public:
340
  //! constructor
341
  Table(int loadingVers, int maxRow)
342
19.8k
    : m_loadingVersion(loadingVers)
343
19.8k
    , m_name("")
344
19.8k
    , m_pageStyle("")
345
19.8k
    , m_maxRow(maxRow)
346
19.8k
    , m_colWidthList()
347
19.8k
    , m_rowHeightMap()
348
19.8k
    , m_rowToRowContentMap()
349
19.8k
    , m_badCell()
350
19.8k
  {
351
19.8k
  }
352
  //! destructor
353
  ~Table() override;
354
  //! returns the load version
355
  int getLoadingVersion() const
356
292k
  {
357
292k
    return m_loadingVersion;
358
292k
  }
359
  //! returns the maximum number of columns
360
  static int getMaxCols()
361
20.4M
  {
362
20.4M
    return 255;
363
20.4M
  }
364
  //! returns the maximum number of row
365
  int getMaxRows() const
366
652k
  {
367
652k
    return m_maxRow;
368
652k
  }
369
  //! returns the col width dimension in inch
370
  std::vector<float> getColumnWidths(std::vector<int> &repeated) const
371
19.8k
  {
372
19.8k
    std::vector<float> widths;
373
19.8k
    repeated.clear();
374
19.8k
    size_t actPos=0;
375
19.8k
    int lastWidth=-1;
376
19.8M
    for (size_t i=0; i<=m_colWidthList.size(); ++i) {
377
19.8M
      if ((i==m_colWidthList.size() || lastWidth!=m_colWidthList[i]) && actPos<i) {
378
42.5k
        widths.push_back(float(lastWidth)/1440.f);
379
42.5k
        repeated.push_back(int(i-actPos));
380
42.5k
        actPos=i;
381
42.5k
      }
382
19.8M
      if (i==m_colWidthList.size()) break;
383
19.8M
      lastWidth=m_colWidthList[i];
384
19.8M
    }
385
19.8k
    return widths;
386
19.8k
  }
387
  //! returns the row size in point
388
  float getRowHeight(int row) const
389
210k
  {
390
210k
    auto rIt=m_rowHeightMap.lower_bound(STOFFVec2i(-1,row));
391
210k
    if (rIt!=m_rowHeightMap.end() && rIt->first[0]<=row && rIt->first[1]>=row)
392
193k
      return float(rIt->second)/20.f;
393
17.1k
    return 12.f;
394
210k
  }
395
  //! returns a row content
396
  RowContent *getRow(int row)
397
741k
  {
398
741k
    auto it=m_rowToRowContentMap.lower_bound(STOFFVec2i(-1,row));
399
741k
    if (it!=m_rowToRowContentMap.end() && it->first[0]<=row && row<=it->first[1])
400
712k
      return &it->second;
401
29.5k
    return nullptr;
402
741k
  }
403
  //! create a block of rows(if not created)
404
  void updateRowsBlocks(STOFFVec2i const &rows)
405
1.05M
  {
406
1.05M
    auto it=m_rowToRowContentMap.lower_bound(STOFFVec2i(-1,rows[0]));
407
1.05M
    if (it==m_rowToRowContentMap.end()) {
408
125k
      m_rowToRowContentMap[rows]=RowContent();
409
125k
      return;
410
125k
    }
411
930k
    if (it->first[0]<rows[0]) { // we must split this set of rows
412
2.58k
      STOFFVec2i oldRows=it->first;
413
2.58k
      RowContent const &content=it->second;
414
2.58k
      m_rowToRowContentMap[STOFFVec2i(oldRows[0],rows[0]-1)]=content;
415
2.58k
      m_rowToRowContentMap[STOFFVec2i(rows[0],oldRows[1])]=content;
416
2.58k
      m_rowToRowContentMap.erase(oldRows);
417
2.58k
    }
418
930k
    int actRow=rows[0];
419
3.99M
    while (actRow<=rows[1]) {
420
3.09M
      it=m_rowToRowContentMap.lower_bound(STOFFVec2i(-1,actRow));
421
3.09M
      if (it==m_rowToRowContentMap.end()) {
422
2.06k
        m_rowToRowContentMap[STOFFVec2i(actRow,rows[1])]=RowContent();
423
2.06k
        break;
424
2.06k
      }
425
3.09M
      if (it->first[0]!=actRow) {
426
31.8k
        if (it->first[0]-1<=rows[1]) {
427
14.9k
          m_rowToRowContentMap[STOFFVec2i(actRow,it->first[0]-1)]=RowContent();
428
14.9k
          actRow=it->first[0];
429
14.9k
          continue;
430
14.9k
        }
431
16.8k
        m_rowToRowContentMap[STOFFVec2i(actRow,rows[1])]=RowContent();
432
16.8k
        break;
433
31.8k
      }
434
3.06M
      if (it->first[1]<=rows[1]) {
435
3.05M
        actRow=it->first[1]+1;
436
3.05M
        continue;
437
3.05M
      }
438
      // we must split the last row
439
12.8k
      STOFFVec2i oldRows=it->first;
440
12.8k
      RowContent const &content=it->second;
441
12.8k
      m_rowToRowContentMap[STOFFVec2i(oldRows[0],rows[1])]=content;
442
12.8k
      m_rowToRowContentMap[STOFFVec2i(rows[1]+1,oldRows[1])]=content;
443
12.8k
      m_rowToRowContentMap.erase(oldRows);
444
12.8k
      break;
445
3.06M
    }
446
930k
  }
447
  //! returns a cell corresponding to a position
448
  Cell &getCell(STOFFVec2i const &pos)
449
535k
  {
450
535k
    if (pos[1]<0 || pos[1]>getMaxRows() || pos[0]<0 || pos[0]>getMaxCols()) {
451
3.82k
      STOFF_DEBUG_MSG(("StarObjectSpreadsheetInternal::Table::getCell: the position is bad (%d,%d)\n", pos[0], pos[1]));
452
3.82k
      return m_badCell;
453
3.82k
    }
454
531k
    updateRowsBlocks(STOFFVec2i(pos[1],pos[1]));
455
531k
    RowContent *row=getRow(pos[1]);
456
531k
    if (row->m_colToCellMap.find(pos[0]) == row->m_colToCellMap.end() || !row->m_colToCellMap.find(pos[0])->second) {
457
529k
      std::shared_ptr<Cell> newCell(new Cell(pos));
458
529k
      row->m_colToCellMap.insert(std::map<int, std::shared_ptr<Cell> >::value_type(pos[0],newCell));
459
529k
      return *newCell;
460
529k
    }
461
2.43k
    return *(row->m_colToCellMap.find(pos[0])->second);
462
531k
  }
463
464
  //! the loading version
465
  int m_loadingVersion;
466
  //! the table name
467
  librevenge::RVNGString m_name;
468
  //! the page style name
469
  librevenge::RVNGString m_pageStyle;
470
  //! the maximum number of row
471
  int m_maxRow;
472
  //! the columns width
473
  std::vector<int> m_colWidthList;
474
  //! the rows heights in TWIP
475
  std::map<STOFFVec2i, int> m_rowHeightMap;
476
  //! map (min row, max row) -> rowContent
477
  std::map<STOFFVec2i, RowContent> m_rowToRowContentMap;
478
  //! a cell uses to return an empty cell
479
  Cell m_badCell;
480
};
481
482
Table::~Table()
483
19.8k
{
484
19.8k
}
485
486
////////////////////////////////////////
487
//! Internal: the state of a StarObjectSpreadsheet
488
struct State {
489
  //! constructor
490
  State()
491
30.7k
    : m_model()
492
30.7k
    , m_tableList()
493
30.7k
    , m_sheetNames()
494
30.7k
    , m_pageStyle("")
495
30.7k
  {
496
30.7k
  }
497
  //! the model
498
  std::shared_ptr<StarObjectModel> m_model;
499
  //! the actual table
500
  std::vector<std::shared_ptr<Table> > m_tableList;
501
  //! the sheet names
502
  std::vector<librevenge::RVNGString> m_sheetNames;
503
  //! the main page style
504
  librevenge::RVNGString m_pageStyle;
505
};
506
507
////////////////////////////////////////
508
//! Internal: the subdocument of a StarObjectSpreadsheet
509
class SubDocument final : public STOFFSubDocument
510
{
511
public:
512
  explicit SubDocument(librevenge::RVNGString const &text) :
513
345
    STOFFSubDocument(nullptr, STOFFInputStreamPtr(), STOFFEntry()), m_text(text) {}
514
515
  //! destructor
516
345
  ~SubDocument() final {}
517
518
  //! operator!=
519
  bool operator!=(STOFFSubDocument const &doc) const override
520
0
  {
521
0
    if (STOFFSubDocument::operator!=(doc)) return true;
522
0
    auto const *sDoc = dynamic_cast<SubDocument const *>(&doc);
523
0
    if (!sDoc) return true;
524
0
    if (m_text != sDoc->m_text) return true;
525
0
    return false;
526
0
  }
527
528
  //! the parser function
529
  void parse(STOFFListenerPtr &listener, libstoff::SubDocumentType type) final;
530
531
protected:
532
  //! the note text
533
  librevenge::RVNGString m_text;
534
};
535
536
void SubDocument::parse(STOFFListenerPtr &listener, libstoff::SubDocumentType /*type*/)
537
345
{
538
345
  if (!listener.get()) {
539
0
    STOFF_DEBUG_MSG(("StarObjectSpreadsheetInternal::SubDocument::parse: no listener\n"));
540
0
    return;
541
0
  }
542
345
  if (!m_text.empty())
543
3
    listener->insertUnicodeString(m_text);
544
342
  else
545
342
    listener->insertChar(' ');
546
345
}
547
548
}
549
550
////////////////////////////////////////////////////////////
551
// constructor/destructor, ...
552
////////////////////////////////////////////////////////////
553
StarObjectSpreadsheet::StarObjectSpreadsheet(StarObject const &orig, bool duplicateState)
554
30.7k
  : StarObject(orig, duplicateState)
555
30.7k
  , m_spreadsheetState(new StarObjectSpreadsheetInternal::State)
556
30.7k
{
557
30.7k
}
558
559
StarObjectSpreadsheet::~StarObjectSpreadsheet()
560
30.7k
{
561
30.7k
  cleanPools();
562
30.7k
}
563
564
////////////////////////////////////////////////////////////
565
//
566
// send data
567
//
568
////////////////////////////////////////////////////////////
569
bool StarObjectSpreadsheet::updatePageSpans(std::vector<STOFFPageSpan> &pageSpan, int &numPages)
570
30.7k
{
571
30.7k
  if (m_spreadsheetState->m_tableList.empty()) return false;
572
6.76k
  numPages=int(m_spreadsheetState->m_tableList.size());
573
574
6.76k
  librevenge::RVNGString styleName("");
575
6.76k
  int nPages=0;
576
6.76k
  auto pool=const_cast<StarObjectSpreadsheet *>(this)->findItemPool(StarItemPool::T_SpreadsheetPool, false);
577
6.76k
  StarState state(pool.get(), *this);
578
26.6k
  for (size_t i=0; i<=m_spreadsheetState->m_tableList.size(); ++i) {
579
26.6k
    bool isEnd=(i==m_spreadsheetState->m_tableList.size());
580
26.6k
    if (!isEnd && m_spreadsheetState->m_tableList[i] && m_spreadsheetState->m_tableList[i]->m_pageStyle==styleName) {
581
8.76k
      ++nPages;
582
8.76k
      continue;
583
8.76k
    }
584
17.8k
    if (nPages) {
585
12.9k
      auto const *style=(pool&&!styleName.empty()) ? pool->findStyleWithFamily(styleName, StarItemStyle::F_Page) : nullptr;
586
12.9k
      if (!style && pool && !m_spreadsheetState->m_pageStyle.empty())
587
5.48k
        style=pool->findStyleWithFamily(m_spreadsheetState->m_pageStyle, StarItemStyle::F_Page);
588
12.9k
      state.m_global->m_page=STOFFPageSpan();
589
12.9k
      state.m_global->m_page.m_pageSpan=nPages;
590
12.9k
      if (style) {
591
57.9k
        for (auto it : style->m_itemSet.m_whichToItemMap) {
592
57.9k
          if (it.second && it.second->m_attribute)
593
54.2k
            it.second->m_attribute->addTo(state);
594
57.9k
        }
595
#if 0
596
        std::cerr << style->m_itemSet.printChild() << "\n";
597
#endif
598
5.89k
      }
599
12.9k
      pageSpan.push_back(state.m_global->m_page);
600
12.9k
    }
601
17.8k
    if (isEnd) break;
602
11.1k
    styleName=m_spreadsheetState->m_tableList[i] ? m_spreadsheetState->m_tableList[i]->m_pageStyle : "";
603
11.1k
    nPages=1;
604
11.1k
  }
605
6.76k
  return true;
606
30.7k
}
607
608
bool StarObjectSpreadsheet::send(STOFFSpreadsheetListenerPtr listener)
609
30.7k
{
610
30.7k
  if (m_spreadsheetState->m_tableList.empty() || !listener) {
611
23.9k
    STOFF_DEBUG_MSG(("StarObjectSpreadsheet::send: can not find the table\n"));
612
23.9k
    return false;
613
23.9k
  }
614
  // first creates the list of sheet names
615
6.76k
  m_spreadsheetState->m_sheetNames.clear();
616
19.8k
  for (auto const &t : m_spreadsheetState->m_tableList) {
617
19.8k
    if (!t)
618
0
      m_spreadsheetState->m_sheetNames.push_back("");
619
19.8k
    else
620
19.8k
      m_spreadsheetState->m_sheetNames.push_back(t->m_name);
621
19.8k
  }
622
623
26.6k
  for (size_t t=0; t<m_spreadsheetState->m_tableList.size(); ++t) {
624
19.8k
    if (t) listener->insertBreak(STOFFListener::PageBreak);
625
19.8k
    if (!m_spreadsheetState->m_tableList[t]) continue;
626
19.8k
    StarObjectSpreadsheetInternal::Table &sheet=*m_spreadsheetState->m_tableList[t];
627
19.8k
    std::vector<int> repeated;
628
19.8k
    std::vector<float> widths=sheet.getColumnWidths(repeated);
629
19.8k
    listener->openSheet(widths, librevenge::RVNG_INCH, repeated, sheet.m_name);
630
19.8k
    if (m_spreadsheetState->m_model)
631
12.1k
      m_spreadsheetState->m_model->sendPage(int(t), listener);
632
633
    /* create a set to know which row needed to be send, each value of
634
       the set corresponding to a position where the rows change
635
       excepted the last position */
636
19.8k
    std::set<int> newRowSet;
637
174k
    for (auto it : sheet.m_rowToRowContentMap) {
638
174k
      STOFFVec2i const &rows=it.first;
639
174k
      newRowSet.insert(rows[0]);
640
174k
      newRowSet.insert(rows[1]+1);
641
174k
    }
642
61.2k
    for (auto it : sheet.m_rowHeightMap) {
643
61.2k
      STOFFVec2i const &rows=it.first;
644
61.2k
      newRowSet.insert(rows[0]);
645
61.2k
      newRowSet.insert(rows[1]+1);
646
61.2k
    }
647
648
230k
    for (auto it=newRowSet.begin(); it!=newRowSet.end();) {
649
226k
      int row=*(it++);
650
226k
      if (row<0) {
651
0
        STOFF_DEBUG_MSG(("StarObjectSpreadsheet::sendSpreadsheet: find a negative row %d\n", row));
652
0
        continue;
653
0
      }
654
226k
      if (it==newRowSet.end())
655
16.7k
        break;
656
210k
      listener->openSheetRow(sheet.getRowHeight(row), librevenge::RVNG_POINT, *it-row);
657
210k
      sendRow(int(t), row, listener);
658
210k
      listener->closeSheetRow();
659
210k
    }
660
19.8k
    listener->closeSheet();
661
19.8k
  }
662
663
6.76k
  return true;
664
30.7k
}
665
666
bool StarObjectSpreadsheet::sendRow(int table, int row, STOFFSpreadsheetListenerPtr listener)
667
210k
{
668
210k
  if (!listener || table<0 || table>=int(m_spreadsheetState->m_tableList.size()) || !m_spreadsheetState->m_tableList[size_t(table)]) {
669
0
    STOFF_DEBUG_MSG(("StarObjectSpreadsheet::send: can not find the table %d\n", table));
670
0
    return false;
671
0
  }
672
210k
  auto &sheet=*m_spreadsheetState->m_tableList[size_t(table)];
673
210k
  auto *rowC=sheet.getRow(row);
674
210k
  if (!rowC) return true;
675
180k
  rowC->compressItemList();
676
677
  // we need to go through the row style list and the cell list in parallel
678
180k
  bool checkStyle=false;
679
180k
  int actStyleCol=0;
680
180k
  std::map<STOFFVec2i, std::shared_ptr<StarAttribute> >::const_iterator sIt;
681
180k
  if (!rowC->m_colToAttributeMap.empty()) {
682
104k
    checkStyle=true;
683
104k
    sIt=rowC->m_colToAttributeMap.begin();
684
104k
    actStyleCol=sIt->first[0];
685
104k
  }
686
180k
  bool checkCell=false;
687
180k
  std::map<int, std::shared_ptr<StarObjectSpreadsheetInternal::Cell> >::iterator cIt;
688
180k
  if (!rowC->m_colToCellMap.empty()) {
689
142k
    checkCell=true;
690
142k
    cIt=rowC->m_colToCellMap.begin();
691
142k
  }
692
693
180k
  StarObjectSpreadsheetInternal::Cell emptyCell;
694
994k
  while (checkStyle || checkCell) {
695
915k
    int newCol=checkCell ? cIt->first : -1;
696
915k
    if (checkStyle && sIt->first[1] < actStyleCol) {
697
435k
      ++sIt;
698
435k
      checkStyle=sIt!=rowC->m_colToAttributeMap.end();
699
435k
      actStyleCol=checkStyle ? sIt->first[0] : -1;
700
435k
    }
701
915k
    if (checkStyle && (!checkCell || actStyleCol<newCol)) {
702
285k
      emptyCell.setPosition(STOFFVec2i(actStyleCol, row));
703
285k
      int numRepeated=(checkCell && newCol<=sIt->first[1]) ? newCol-actStyleCol : sIt->first[1]-actStyleCol+1;
704
285k
      sendCell(emptyCell, sIt->second ? sIt->second.get() : nullptr, table, numRepeated, listener);
705
285k
      actStyleCol += numRepeated;
706
285k
      continue;
707
285k
    }
708
630k
    if (!checkCell)
709
101k
      break;
710
529k
    if (checkStyle && newCol==actStyleCol) {
711
306k
      sendCell(cIt->second ? *cIt->second : emptyCell, sIt->second ? sIt->second.get() : nullptr, table, 1, listener);
712
306k
      ++actStyleCol;
713
306k
    }
714
222k
    else
715
222k
      sendCell(cIt->second ? *cIt->second : emptyCell, nullptr, table, 1, listener);
716
529k
    ++cIt;
717
529k
    checkCell=cIt!=rowC->m_colToCellMap.end();
718
529k
  }
719
180k
  return true;
720
210k
}
721
722
bool StarObjectSpreadsheet::sendCell(StarObjectSpreadsheetInternal::Cell &cell, StarAttribute *attrib, int table, int numRepeated, STOFFSpreadsheetListenerPtr listener)
723
814k
{
724
814k
  if (!listener) {
725
0
    STOFF_DEBUG_MSG(("StarObjectSpreadsheet::send: can not find the listener\n"));
726
0
    return false;
727
0
  }
728
814k
  if (attrib) {
729
591k
    auto pool=findItemPool(StarItemPool::T_SpreadsheetPool, false);
730
591k
    StarState state(pool.get(), *this);
731
591k
    attrib->addTo(state);
732
591k
    cell.setFont(state.m_font);
733
591k
    cell.setCellStyle(state.m_cell);
734
    // checkme: we need the pool here
735
591k
    getFormatManager()->updateNumberingProperties(cell);
736
591k
  }
737
814k
  if (!cell.m_content.m_formula.empty())
738
54.1k
    StarCellFormula::updateFormula(cell.m_content, m_spreadsheetState->m_sheetNames, table);
739
740
814k
  listener->openSheetCell(cell, cell.m_content, numRepeated);
741
814k
  if (cell.m_content.m_contentType==STOFFCellContent::C_TEXT_BASIC)
742
111k
    listener->insertUnicodeList(cell.m_content.m_text);
743
702k
  else if (cell.m_content.m_contentType==STOFFCellContent::C_TEXT && cell.m_textZone)
744
9.42k
    cell.m_textZone->send(listener);
745
814k
  if (cell.m_hasNote) {
746
345
    std::shared_ptr<STOFFSubDocument> subDoc(new StarObjectSpreadsheetInternal::SubDocument(cell.m_notes[0]));
747
345
    listener->insertComment(subDoc, cell.m_notes[2], cell.m_notes[1]);
748
345
  }
749
814k
  listener->closeSheetCell();
750
814k
  return true;
751
814k
}
752
753
////////////////////////////////////////////////////////////
754
// main zone
755
////////////////////////////////////////////////////////////
756
bool StarObjectSpreadsheet::parse()
757
30.7k
{
758
30.7k
  if (!getOLEDirectory() || !getOLEDirectory()->m_input) {
759
0
    STOFF_DEBUG_MSG(("StarObjectSpreadsheet::parser: error, incomplete document\n"));
760
0
    return false;
761
0
  }
762
30.7k
  auto &directory=*getOLEDirectory();
763
30.7k
  StarObject::parse();
764
30.7k
  auto unparsedOLEs=directory.getUnparsedOles();
765
30.7k
  STOFFInputStreamPtr input=directory.m_input;
766
30.7k
  StarFileManager fileManager;
767
768
30.7k
  STOFFInputStreamPtr mainOle; // let store the StarCalcDocument to read it in last position
769
30.7k
  std::string mainName;
770
62.6k
  for (auto const &name : unparsedOLEs) {
771
62.6k
    STOFFInputStreamPtr ole = input->getSubStreamByName(name.c_str());
772
62.6k
    if (!ole.get()) {
773
11.8k
      STOFF_DEBUG_MSG(("StarObjectSpreadsheet::parse: error: can not find OLE part: \"%s\"\n", name.c_str()));
774
11.8k
      continue;
775
11.8k
    }
776
777
50.8k
    auto pos = name.find_last_of('/');
778
50.8k
    std::string base;
779
50.8k
    if (pos == std::string::npos) base = name;
780
356
    else base = name.substr(pos+1);
781
50.8k
    ole->setReadInverted(true);
782
50.8k
    if (base=="SfxStyleSheets") {
783
5.90k
      readSfxStyleSheets(ole,name);
784
5.90k
      continue;
785
5.90k
    }
786
44.9k
    if (base=="StarCalcDocument") {
787
33.6k
      mainOle=ole;
788
33.6k
      mainName=name;
789
33.6k
      continue;
790
33.6k
    }
791
11.2k
    if (base!="BasicManager2") {
792
9.61k
      STOFF_DEBUG_MSG(("StarObjectSpreadsheet::parse: find unexpected ole %s\n", name.c_str()));
793
9.61k
    }
794
11.2k
    libstoff::DebugFile asciiFile(ole);
795
11.2k
    asciiFile.open(name);
796
797
11.2k
    libstoff::DebugStream f;
798
11.2k
    f << "Entries(" << base << "):";
799
11.2k
    asciiFile.addPos(0);
800
11.2k
    asciiFile.addNote(f.str().c_str());
801
11.2k
    asciiFile.reset();
802
11.2k
  }
803
804
30.7k
  if (!mainOle) {
805
0
    STOFF_DEBUG_MSG(("StarObjectSpreadsheet::parser: can not find the main calc document\n"));
806
0
    return false;
807
0
  }
808
30.7k
  else
809
30.7k
    readCalcDocument(mainOle,mainName);
810
30.7k
  return true;
811
30.7k
}
812
813
bool StarObjectSpreadsheet::readCalcDocument(STOFFInputStreamPtr input, std::string const &name)
814
30.7k
try
815
30.7k
{
816
30.7k
  StarZone zone(input, name, "SWCalcDocument", getPassword()); // checkme: do we need to pass the password
817
30.7k
  libstoff::DebugFile &ascFile=zone.ascii();
818
30.7k
  ascFile.open(name);
819
820
30.7k
  libstoff::DebugStream f;
821
30.7k
  f << "Entries(SCCalcDocument):";
822
  // sc_docsh.cxx: ScDocShell::Load then sc_documen2.cxx ScDocument::Load
823
30.7k
  uint16_t nId;
824
30.7k
  *input>>nId;
825
30.7k
  if ((nId>>8)!=0x42) {
826
    /* if the zone has a password, we can retrieve it knowing that nId must begin by 0x42
827
828
       TODO: we must also check if the user has given a password and
829
       if the user mask does correspond to the real mask.
830
    */
831
23.6k
    input=StarEncryption::decodeStream(input, StarEncryption::getMaskToDecodeStream(uint8_t(nId>>8), 0x42));
832
23.6k
    if (input) {
833
23.6k
      zone.setInput(input);
834
23.6k
      input->seek(0, librevenge::RVNG_SEEK_SET);
835
23.6k
      *input>>nId;
836
23.6k
    }
837
23.6k
  }
838
30.7k
  if ((nId!=0x4220 && nId!=0x422d) || !zone.openSCRecord()) {
839
7.03k
    STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readCalcDocument: can not read the document id\n"));
840
7.03k
    f << "###";
841
7.03k
    ascFile.addPos(0);
842
7.03k
    ascFile.addNote(f.str().c_str());
843
7.03k
    return true;
844
7.03k
  }
845
23.6k
  ascFile.addPos(0);
846
23.6k
  ascFile.addNote(f.str().c_str());
847
23.6k
  long lastPos=zone.getRecordLastPosition();
848
23.6k
  int version=0, maxRow=8191;
849
169k
  while (!input->isEnd() && input->tell()<lastPos) {
850
162k
    long pos=input->tell();
851
162k
    uint16_t subId;
852
162k
    *input>>subId;
853
162k
    f.str("");
854
162k
    f << "SCCalcDocument[" << std::hex << subId << std::dec << "]:";
855
162k
    bool ok=false;
856
162k
    switch (subId) {
857
19.8k
    case 0x4222: {
858
19.8k
      f << "table,";
859
19.8k
      std::shared_ptr<StarObjectSpreadsheetInternal::Table> table;
860
19.8k
      table.reset(new StarObjectSpreadsheetInternal::Table(version, maxRow));
861
19.8k
      m_spreadsheetState->m_tableList.push_back(table);
862
19.8k
      ok=readSCTable(zone, *table);
863
19.8k
      break;
864
0
    }
865
9.24k
    case 0x4224: {
866
9.24k
      f << "rangeName,";
867
      // sc_rangenam.cxx ScRangeName::Load
868
9.24k
      StarObjectSpreadsheetInternal::ScMultiRecord scRecord(zone);
869
9.24k
      ok=scRecord.open();
870
9.24k
      if (!ok) break;
871
8.94k
      uint16_t count, sharedMaxIndex;
872
8.94k
      if (version >= 3)
873
6.90k
        *input >> sharedMaxIndex >> count;
874
2.04k
      else {
875
2.04k
        uint16_t dummy;
876
2.04k
        *input >> sharedMaxIndex >> dummy >> count;
877
2.04k
      }
878
8.94k
      f << "index[sharedMax]=" << sharedMaxIndex << ";";
879
8.94k
      ascFile.addPos(pos);
880
8.94k
      ascFile.addNote(f.str().c_str());
881
29.9k
      for (int i=0; i<int(count); ++i)  {
882
23.2k
        pos=input->tell();
883
23.2k
        f.str("");
884
23.2k
        f << "Entries(SCRange):";
885
23.2k
        if (!scRecord.openContent("SCCalcDocument")) {
886
2.27k
          f << "###";
887
2.27k
          STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readCalcDocument:can not find some content\n"));
888
2.27k
          ascFile.addPos(pos);
889
2.27k
          ascFile.addNote(f.str().c_str());
890
2.27k
          break;
891
2.27k
        }
892
        // sc_rangenam.cxx ScRangeData::ScRangeData
893
21.0k
        long endDataPos=scRecord.getContentLastPosition();
894
21.0k
        std::vector<uint32_t> string;
895
21.0k
        if (!zone.readString(string)) {
896
543
          STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readCalcDocument: can not read a string\n"));
897
543
          f << "###string";
898
543
          ascFile.addPos(pos);
899
543
          ascFile.addNote(f.str().c_str());
900
543
          continue;
901
543
        }
902
20.4k
        f << libstoff::getString(string).cstr() << ",";
903
20.4k
        StarObjectSpreadsheetInternal::Cell cell;
904
20.4k
        if (version >= 3) {
905
2.43k
          uint32_t nPos;
906
2.43k
          uint16_t rangeType, index;
907
2.43k
          uint8_t nData;
908
2.43k
          *input >> nPos >> rangeType >> index >> nData;
909
2.43k
          auto row=int(nPos&0xFFFF);
910
2.43k
          auto col=int((nPos>>16)&0xFF);
911
2.43k
          auto table=int((nPos>>24)&0xFF);
912
2.43k
          f << "pos=" << row << "x" << col;
913
2.43k
          if (table) f << "x" << table;
914
2.43k
          f << ",";
915
2.43k
          f << "range[type]=" << rangeType << ",";
916
2.43k
          f << "index=" << index << ",";
917
2.43k
          if (nData&0xf) input->seek((nData&0xf), librevenge::RVNG_SEEK_CUR);
918
2.43k
          if (!StarCellFormula::readSCFormula(zone, cell.m_content, version, endDataPos) || input->tell()>endDataPos)
919
2.43k
            f << "###";
920
2.43k
        }
921
18.0k
        else {
922
18.0k
          uint16_t row, col, table, tokLen, rangeType, index;
923
18.0k
          *input >> col >> row >> table >> rangeType >> index >> tokLen;
924
18.0k
          f << "pos=" << row << "x" << col;
925
18.0k
          if (table) f << "x" << table;
926
18.0k
          f << ",";
927
18.0k
          f << "range[type]=" << rangeType << ",";
928
18.0k
          f << "index=" << index << ",";
929
18.0k
          if (tokLen &&
930
16.3k
              (!StarCellFormula::readSCFormula3(zone, cell.m_content, version, endDataPos) || input->tell()>endDataPos))
931
16.3k
            f << "###";
932
18.0k
        }
933
20.4k
        ascFile.addPos(pos);
934
20.4k
        ascFile.addNote(f.str().c_str());
935
20.4k
        scRecord.closeContent("SCCalcDocument");
936
20.4k
      }
937
8.94k
      scRecord.close("SCCalcDocument");
938
8.94k
      pos=input->tell();
939
8.94k
      break;
940
9.24k
    }
941
10.6k
    case 0x4225:
942
15.1k
    case 0x4226:
943
18.5k
    case 0x4227:
944
21.2k
    case 0x422e:
945
23.9k
    case 0x422f:
946
23.9k
    case 0x4230:
947
24.0k
    case 0x4231:
948
24.0k
    case 0x4234:
949
24.1k
    case 0x4239: {
950
24.1k
      std::string what(subId==0x4225 ? "dbCollect" : subId==0x4226 ? "dbPivot" :
951
13.4k
                       subId==0x4227 ? "chartCol" : subId==0x422e ? "ddeLinks" :
952
5.55k
                       subId==0x422f ? "areaLinks" : subId==0x4230 ? "condFormats" :
953
186
                       subId==0x4231 ? "validation" : subId==0x4234 ? "detOp" : "dpCollection");
954
24.1k
      f << what << ",";
955
      // sc_dbcolect.cxx ScDBCollection::Load and ...
956
24.1k
      StarObjectSpreadsheetInternal::ScMultiRecord scRecord(zone);
957
24.1k
      ok=scRecord.open();
958
24.1k
      if (!ok) break;
959
960
23.2k
      long endDataPos=zone.getRecordLastPosition();
961
23.2k
      if (subId==0x4239 && input->readLong(4)!=6) {
962
29
        f << "###version";
963
29
        STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readCalcDocument:find unknown version\n"));
964
29
        input->seek(endDataPos, librevenge::RVNG_SEEK_SET);
965
29
        scRecord.close("SCCalcDocument");
966
29
        break;
967
29
      }
968
23.2k
      uint16_t count;
969
23.2k
      *input >> count;
970
23.2k
      ascFile.addPos(pos);
971
23.2k
      ascFile.addNote(f.str().c_str());
972
23.2k
      bool isOk=true;
973
23.2k
      std::vector<uint32_t> string;
974
88.6k
      for (int i=0; i<int(count); ++i)  {
975
69.2k
        pos=input->tell();
976
69.2k
        f.str("");
977
69.2k
        f << "SCCalcDocument:" << what << ",";
978
69.2k
        if (!scRecord.openContent("SCCalcDocument")) {
979
3.73k
          f << "###";
980
3.73k
          isOk=false;
981
3.73k
          STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readCalcDocument:can not find some content\n"));
982
3.73k
          ascFile.addPos(pos);
983
3.73k
          ascFile.addNote(f.str().c_str());
984
3.73k
          break;
985
3.73k
        }
986
65.4k
        bool parsed=false, addDebugFile=false;
987
65.4k
        long endData=scRecord.getContentLastPosition();
988
65.4k
        switch (subId) {
989
57.6k
        case 0x4225:
990
57.6k
          parsed=readSCDBData(zone, version, endData);
991
57.6k
          break;
992
99
        case 0x4226:
993
99
          parsed=readSCDBPivot(zone, version, endData);
994
99
          break;
995
6.46k
        case 0x4227: {
996
6.46k
          f << "chart,";
997
6.46k
          parsed=addDebugFile=true;
998
6.46k
          uint16_t nTab, nCol1, nRow1, nCol2, nRow2;
999
6.46k
          *input >> nTab >> nCol1 >> nRow1 >> nCol2 >> nRow2;
1000
6.46k
          f << "dim=" << nCol1 << "x" << nRow1 << "<->" << nCol2 << "x" << nRow2 << "[" << nTab << "],";
1001
6.46k
          if (!zone.readString(string) || input->tell()>endData) {
1002
295
            STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readCalcDocument: can not read a string\n"));
1003
295
            f << "###string";
1004
295
          }
1005
6.16k
          else {
1006
6.16k
            if (!string.empty()) f << libstoff::getString(string).cstr() << ",";
1007
6.16k
            bool bColHeaders, bRowHeaders;
1008
6.16k
            *input >> bColHeaders >> bRowHeaders;
1009
6.16k
            if (bColHeaders) f << "col[headers],";
1010
6.16k
            if (bRowHeaders) f << "row[headers],";
1011
6.16k
          }
1012
6.46k
          break;
1013
0
        }
1014
378
        case 0x422e: {
1015
378
          parsed=addDebugFile=true;
1016
476
          for (int j=0; j<3; ++j) {
1017
451
            if (!zone.readString(string) || input->tell()>endData) {
1018
353
              STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readCalcDocument: can not read a string\n"));
1019
353
              f << "###string";
1020
353
              parsed=false;
1021
353
              break;
1022
353
            }
1023
98
            if (string.empty()) continue;
1024
14
            f << (j==0 ? "appl" : j==1 ? "topic" : "item") << "=" << libstoff::getString(string).cstr() << ",";
1025
14
          }
1026
378
          if (!parsed)
1027
353
            break;
1028
25
          bool hasValue;
1029
25
          *input>>hasValue;
1030
25
          if (hasValue && !readSCMatrix(zone, version, endData)) {
1031
20
            STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readCalcDocument: can not read a matrix\n"));
1032
20
            f << "###matrix";
1033
20
            parsed=false;
1034
20
            break;
1035
20
          }
1036
5
          if (input->tell()>endData) f << "mode=" << input->readULong(1) << ",";
1037
5
          break;
1038
25
        }
1039
455
        case 0x422f: { // checkme
1040
455
          parsed=addDebugFile=true;
1041
786
          for (int j=0; j<3; ++j) {
1042
723
            if (!zone.readString(string) || input->tell()>endData) {
1043
392
              STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readCalcDocument: can not read a string\n"));
1044
392
              f << "###string";
1045
392
              parsed=false;
1046
392
              break;
1047
392
            }
1048
331
            if (string.empty()) continue;
1049
127
            f << (j==0 ? "file" : j==1 ? "filter" : "source") << "=" << libstoff::getString(string).cstr() << ",";
1050
127
          }
1051
455
          if (!parsed)
1052
392
            break;
1053
63
          f << "range=" << std::hex << input->readULong(4) << "<->" << input->readULong(4) << std::dec << ",";
1054
63
          if (input->tell()<endData) {
1055
59
            if (!zone.readString(string) || input->tell()>endData) {
1056
55
              STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readCalcDocument: can not read a string\n"));
1057
55
              f << "###string";
1058
55
              parsed=false;
1059
55
              break;
1060
55
            }
1061
4
            else if (!string.empty())
1062
1
              f << "options=" << libstoff::getString(string).cstr() << ",";
1063
59
          }
1064
8
          break;
1065
63
        }
1066
131
        case 0x4230: {
1067
131
          addDebugFile=parsed=true;
1068
          // sc_conditio.cxx ScConditionalFormat::ScConditionalFormat
1069
131
          uint32_t key;
1070
131
          uint16_t entryCount;
1071
131
          *input >> key >> entryCount;
1072
131
          f << "key=" << key << ",";
1073
131
          if (!entryCount) break;
1074
46
          scRecord.closeContent("SCCalcDocument");
1075
46
          f << "entries=[";
1076
209
          for (int e=0; e<int(entryCount); ++e) {
1077
189
            f << "[";
1078
189
            if (!scRecord.openContent("SCCalcDocument")) {
1079
15
              STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readCalcDocument:can not find some content\n"));
1080
15
              f << "###";
1081
15
              isOk=parsed=false;
1082
15
              break;
1083
15
            }
1084
174
            if (!zone.readString(string)) {
1085
11
              STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readCalcDocument:can not read a string\n"));
1086
11
              isOk=parsed=false;
1087
11
              f << "###string,";
1088
11
              break;
1089
11
            }
1090
163
            f << "],";
1091
163
            scRecord.closeContent("SCCalcDocument");
1092
163
          }
1093
46
          f << "],";
1094
46
          break;
1095
131
        }
1096
202
        case 0x4231: {
1097
202
          addDebugFile=parsed=true;
1098
          // sc_validat.cxx
1099
202
          uint32_t key;
1100
202
          uint16_t mode;
1101
202
          bool showInput;
1102
202
          *input >> key >> mode >> showInput;
1103
202
          f << "key=" << key << ",";
1104
202
          f << "mode=" << mode << ",";
1105
202
          if (showInput) f << "show[input],";
1106
214
          for (int j=0; j<2; ++j) {
1107
209
            if (!zone.readString(string) || input->tell()>endData) {
1108
197
              STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readCalcDocument: can not read a string\n"));
1109
197
              parsed=false;
1110
197
              f << "###string";
1111
197
              break;
1112
197
            }
1113
12
            if (string.empty()) continue;
1114
3
            f << (j==0 ? "title" : "message") << "=" << libstoff::getString(string).cstr() << ",";
1115
3
          }
1116
202
          if (!parsed) break;
1117
5
          bool showError;
1118
5
          *input >> showError;
1119
5
          if (showError) f << "show[error],";
1120
9
          for (int j=0; j<2; ++j) {
1121
8
            if (!zone.readString(string) || input->tell()>endData) {
1122
4
              STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readCalcDocument: can not read a string\n"));
1123
4
              parsed=false;
1124
4
              f << "###string";
1125
4
              break;
1126
4
            }
1127
4
            if (string.empty()) continue;
1128
1
            f << (j==0 ? "error[title]" : "error[message]") << "=" << libstoff::getString(string).cstr() << ",";
1129
1
          }
1130
5
          if (!parsed) break;
1131
1
          f << "style[error]=" << input->readULong(2) << ",";
1132
1
          break;
1133
5
        }
1134
75
        case 0x4234: {
1135
75
          addDebugFile=parsed=true;
1136
          // sc_detdata.cxx
1137
75
          f << "range=" << std::hex << input->readULong(4) << "<->" << input->readULong(4) << std::dec << ",";
1138
75
          f << "op=" << input->readULong(2) << ",";
1139
75
          break;
1140
5
        }
1141
0
        case 0x4239: {
1142
0
          addDebugFile=parsed=true;
1143
          // sc_dpobject.cxx ScDPObject::LoadNew
1144
0
          uint8_t dType;
1145
0
          *input >> dType;
1146
0
          switch (dType) {
1147
0
          case 0:
1148
0
            f << "range=" << std::hex << input->readULong(4) << "<->" << input->readULong(4) << std::dec << ",";
1149
0
            parsed=readSCQueryParam(zone, version, endData);
1150
0
            break;
1151
0
          case 1:
1152
0
            for (int j=0; j<2; ++j) {
1153
0
              if (!zone.readString(string) || input->tell()>endData) {
1154
0
                STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readCalcDocument: can not read a string\n"));
1155
0
                parsed=false;
1156
0
                f << "###string";
1157
0
                break;
1158
0
              }
1159
0
              if (string.empty()) continue;
1160
0
              f << (j==0 ? "name" : "object") << "=" << libstoff::getString(string).cstr() << ",";
1161
0
            }
1162
0
            if (!parsed) break;
1163
0
            f << "type=" << input->readULong(2) << ",";
1164
0
            if (input->readULong(1)) f << "native,";
1165
0
            break;
1166
0
          case 2:
1167
0
            for (int j=0; j<5; ++j) {
1168
0
              if (!zone.readString(string) || input->tell()>endData) {
1169
0
                STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readCalcDocument: can not read a string\n"));
1170
0
                parsed=false;
1171
0
                f << "###string";
1172
0
                break;
1173
0
              }
1174
0
              if (string.empty()) continue;
1175
0
              static char const* const wh[]= {"serviceName","source","name","user","pass"};
1176
0
              f << wh[j] << "=" << libstoff::getString(string).cstr() << ",";
1177
0
            }
1178
0
            break;
1179
0
          default:
1180
0
            STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readCalcDocument: unexpected sub type\n"));
1181
0
            f << "###subType=" << int(dType) << ",";
1182
0
            parsed=false;
1183
0
            break;
1184
0
          }
1185
0
          if (!parsed) break;
1186
0
          f << "out[range]=" << std::hex << input->readULong(4) << "<->" << input->readULong(4) << std::dec << ",";
1187
          // ScDPSaveData::Load
1188
0
          uint32_t nDim;
1189
0
          *input >> nDim;
1190
0
          for (uint32_t j=0; j<nDim; ++j) {
1191
0
            f << "dim" << j << "=[";
1192
0
            if (!zone.readString(string) || input->tell()>endData) {
1193
0
              STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readCalcDocument: can not read a string\n"));
1194
0
              parsed=false;
1195
0
              f << "###string";
1196
0
              break;
1197
0
            }
1198
0
            if (!string.empty()) f << libstoff::getString(string).cstr() << ",";
1199
0
            bool isDataLayout, dupFlag, subTotalDef;
1200
0
            uint16_t orientation, function, showEmptyMode, subTotalCount, extra;
1201
0
            int32_t hierarchy;
1202
0
            *input >> isDataLayout >> dupFlag >> orientation >> function >> hierarchy
1203
0
                   >> showEmptyMode >> subTotalDef >> subTotalCount;
1204
0
            if (isDataLayout) f << "isDataLayout,";
1205
0
            if (dupFlag) f << "dupFlag,";
1206
0
            if (orientation) f << "orientation=" << orientation << ",";
1207
0
            if (function) f << "function=" << function << ",";
1208
0
            if (hierarchy) f << "hierarchy=" << hierarchy << ",";
1209
0
            if (showEmptyMode) f << "showEmptyMode=" << showEmptyMode << ",";
1210
0
            if (subTotalDef) f << "subTotalDef,";
1211
0
            if (input->tell()+2*long(subTotalCount)>endData) {
1212
0
              STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readCalcDocument: can not read function list\n"));
1213
0
              parsed=false;
1214
0
              f << "###totalFuncs";
1215
0
              break;
1216
0
            }
1217
0
            f << "funcs=[";
1218
0
            for (int k=0; k<int(subTotalCount); ++k) f << input->readULong(2) << ",";
1219
0
            f << "],";
1220
0
            *input >> extra;
1221
0
            if (extra) input->seek(extra, librevenge::RVNG_SEEK_CUR);
1222
0
            uint32_t nMember;
1223
0
            *input >> nMember;
1224
0
            for (uint32_t k=0; k<nMember; ++k) {
1225
0
              f << "member" << k << "[";
1226
0
              if (!zone.readString(string) || input->tell()>endData) {
1227
0
                STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readCalcDocument: can not read a string\n"));
1228
0
                parsed=false;
1229
0
                f << "###string";
1230
0
                break;
1231
0
              }
1232
0
              if (!string.empty()) f << libstoff::getString(string).cstr() << ",";
1233
0
              uint16_t visibleMode, showDetailMode;
1234
0
              *input >> visibleMode >> showDetailMode >> extra;
1235
0
              if (visibleMode) f << "visibleMode=" << visibleMode << ",";
1236
0
              if (showDetailMode) f << "showDetailMode=" << showDetailMode << ",";
1237
0
              if (extra) input->seek(extra, librevenge::RVNG_SEEK_CUR);
1238
0
              f << "],";
1239
0
            }
1240
0
            if (!parsed) break;
1241
0
            f << "],";
1242
0
          }
1243
0
          if (!parsed) break;
1244
0
          uint16_t colGrandMode, rowGrandMode, ignoreEmptyMode, repeatEmptyMode, extra;
1245
0
          *input >> colGrandMode >> rowGrandMode >> ignoreEmptyMode >> repeatEmptyMode >> extra;
1246
0
          f << "grandMode=" << colGrandMode << "x" << rowGrandMode << ",";
1247
0
          if (ignoreEmptyMode) f << "ignoreEmptyMode=" << ignoreEmptyMode << ",";
1248
0
          if (repeatEmptyMode) f << "repeatEmptyMode=" << repeatEmptyMode << ",";
1249
0
          if (extra) input->seek(extra, librevenge::RVNG_SEEK_CUR);
1250
          //
1251
0
          if (input->tell()<endData) {
1252
0
            for (int j=0; j<2; ++j) {
1253
0
              if (!zone.readString(string) || input->tell()>endData) {
1254
0
                STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readCalcDocument: can not read a string\n"));
1255
0
                parsed=false;
1256
0
                f << "###string";
1257
0
                break;
1258
0
              }
1259
0
              if (string.empty()) continue;
1260
0
              f << (j==0 ? "tableName" : "tableTab") << "=" << libstoff::getString(string).cstr() << ",";
1261
0
            }
1262
0
          }
1263
0
          break;
1264
0
        }
1265
0
        default:
1266
0
          STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readCalcDocument: unexpected type\n"));
1267
0
          f << "###type,";
1268
0
          addDebugFile=parsed=true;
1269
0
          input->seek(endData, librevenge::RVNG_SEEK_SET);
1270
0
          break;
1271
65.4k
        }
1272
65.4k
        if (!parsed) {
1273
58.1k
          addDebugFile=true;
1274
58.1k
          f << "###";
1275
58.1k
          input->seek(endData, librevenge::RVNG_SEEK_SET);
1276
58.1k
        }
1277
65.4k
        if (addDebugFile) {
1278
64.8k
          ascFile.addPos(pos);
1279
64.8k
          ascFile.addNote(f.str().c_str());
1280
64.8k
        }
1281
65.4k
        if (scRecord.isContentOpened()) scRecord.closeContent("SCCalcDocument");
1282
65.4k
        if (!isOk) break;
1283
65.4k
      }
1284
23.2k
      if (isOk && subId==0x4225 && input->tell()<endDataPos) {
1285
6.74k
        pos=input->tell();
1286
6.74k
        f.str("");
1287
6.74k
        f << "SCCalcDocument:dbCollect, nEntry=" << input->readULong(2) << ",";
1288
6.74k
        ascFile.addPos(pos);
1289
6.74k
        ascFile.addNote(f.str().c_str());
1290
6.74k
      }
1291
23.2k
      scRecord.close("SCCalcDocument");
1292
23.2k
      pos=input->tell();
1293
23.2k
      break;
1294
23.2k
    }
1295
108k
    default:
1296
108k
      break;
1297
162k
    }
1298
162k
    if (ok) {
1299
51.7k
      if (pos!=input->tell()) {
1300
19.6k
        ascFile.addPos(pos);
1301
19.6k
        ascFile.addNote(f.str().c_str());
1302
19.6k
      }
1303
51.7k
      continue;
1304
51.7k
    }
1305
110k
    input->seek(pos+2, librevenge::RVNG_SEEK_SET);
1306
110k
    if (!zone.openSCRecord()) {
1307
16.4k
      STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readCalcDocument: can not open the zone record\n"));
1308
16.4k
      f << "###";
1309
16.4k
      ascFile.addPos(pos);
1310
16.4k
      ascFile.addNote(f.str().c_str());
1311
16.4k
      break;
1312
16.4k
    }
1313
93.7k
    long endPos=zone.getRecordLastPosition();
1314
93.7k
    std::vector<uint32_t> string;
1315
93.7k
    switch (subId) {
1316
17.2k
    case 0x4221: {
1317
17.2k
      f << "docFlags,";
1318
17.2k
      uint16_t vers;
1319
17.2k
      *input>>vers;
1320
17.2k
      version=int(vers);
1321
17.2k
      f << "vers=" << vers << ",";
1322
17.2k
      if (!zone.readString(string)) {
1323
366
        STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readCalcDocument: can not read a string\n"));
1324
366
        f << "###string";
1325
366
        break;
1326
366
      }
1327
16.8k
      else if (!string.empty()) {
1328
16.7k
        m_spreadsheetState->m_pageStyle=libstoff::getString(string);
1329
16.7k
        f << "pageStyle=" << m_spreadsheetState->m_pageStyle.cstr() << ",";
1330
16.7k
      }
1331
16.8k
      f << "protected=" << input->readULong(1) << ",";
1332
16.8k
      if (!zone.readString(string)) {
1333
9.22k
        STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readCalcDocument: can not read a string\n"));
1334
9.22k
        f << "###string";
1335
9.22k
        break;
1336
9.22k
      }
1337
7.67k
      else if (!string.empty())
1338
166
        f << "passwd=" << libstoff::getString(string).cstr() << ","; // the uncrypted table password, safe to ignore
1339
7.67k
      if (input->tell()<endPos) f << "language=" << input->readULong(2) << ",";
1340
7.67k
      if (input->tell()<endPos) f << "autoCalc=" << input->readULong(1) << ",";
1341
7.67k
      if (input->tell()<endPos) f << "visibleTab=" << input->readULong(2) << ",";
1342
7.67k
      if (input->tell()<endPos) {
1343
2.54k
        *input>>vers;
1344
2.54k
        version=int(vers);
1345
2.54k
        f << "vers=" << vers << ",";
1346
2.54k
      }
1347
7.67k
      if (input->tell()<endPos) {
1348
2.54k
        uint16_t nMaxRow;
1349
2.54k
        *input>>nMaxRow;
1350
2.54k
        maxRow=int(nMaxRow);
1351
2.54k
        if (nMaxRow!=8191) f << "maxRow=" << nMaxRow << ",";
1352
2.54k
      }
1353
7.67k
      break;
1354
16.8k
    }
1355
4.18k
    case 0x4223: {
1356
      // sc_documen9.cxx ScDocument::LoadDrawLayer, sc_drwlayer.cxx ScDrawLayer::Load
1357
4.18k
      f << "drawing,";
1358
12.8k
      while (input->tell()<endPos) {
1359
8.76k
        ascFile.addPos(pos);
1360
8.76k
        ascFile.addNote(f.str().c_str());
1361
1362
8.76k
        pos=input->tell();
1363
8.76k
        *input >> nId;
1364
8.76k
        f.str("");
1365
8.76k
        f << "SCCalcDocument[drawing-" << std::hex << nId << std::dec << "]:";
1366
8.76k
        if (!zone.openSCRecord()) {
1367
81
          STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readCalcDocument: can not open a record\n"));
1368
81
          f << "###record";
1369
81
          break;
1370
81
        }
1371
8.68k
        switch (nId) {
1372
3.73k
        case 0x4260: {
1373
3.73k
          f << "pool,";
1374
3.73k
          auto pool=getNewItemPool(StarItemPool::T_XOutdevPool);
1375
3.73k
          pool->addSecondaryPool(getNewItemPool(StarItemPool::T_EditEnginePool));
1376
3.73k
          if (!pool->read(zone))
1377
259
            input->seek(pos, librevenge::RVNG_SEEK_SET);
1378
3.73k
          break;
1379
0
        }
1380
4.09k
        case 0x4261: {
1381
4.09k
          f << "sdrModel,";
1382
4.09k
          std::shared_ptr<StarObjectModel> model(new StarObjectModel(*this, true));
1383
4.09k
          if (model->read(zone)) {
1384
4.07k
            if (m_spreadsheetState->m_model) {
1385
0
              STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readCalcDocument: the model is already set\n"));
1386
0
              f << "###model";
1387
0
            }
1388
4.07k
            else
1389
4.07k
              m_spreadsheetState->m_model=model;
1390
4.07k
          }
1391
20
          else
1392
20
            input->seek(pos, librevenge::RVNG_SEEK_SET);
1393
4.09k
          break;
1394
0
        }
1395
857
        default:
1396
857
          STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readCalcDocument: find unexpected type\n"));
1397
857
          f << "###unknown";
1398
857
          input->seek(zone.getRecordLastPosition(), librevenge::RVNG_SEEK_SET);
1399
857
          break;
1400
8.68k
        }
1401
8.68k
        zone.closeSCRecord("SCCalcDocument");
1402
8.68k
      }
1403
4.18k
      break;
1404
4.18k
    }
1405
7.13k
    case 0x4228: {
1406
7.13k
      f << "numFormats,";
1407
7.13k
      if (!getFormatManager()->readNumberFormatter(zone))
1408
936
        f << "###";
1409
7.13k
      break;
1410
4.18k
    }
1411
4.27k
    case 0x4229: {
1412
4.27k
      f << "docOptions,vers=" << version << ",";
1413
      // sc_docoptio.cxx void ScDocOptions::Load
1414
4.27k
      bool bIsIgnoreCase, bIsIter=false;
1415
4.27k
      uint16_t nIterCount, nPrecStandardFormat, nDay, nMonth, nYear;
1416
4.27k
      double fIterEps;
1417
4.27k
      *input >> bIsIgnoreCase;
1418
4.27k
      if (version>=2) {
1419
4.05k
        uint8_t val;
1420
4.05k
        *input >> val;
1421
4.05k
        if (val!=0 && val!=1)
1422
182
          input->seek(-1, librevenge::RVNG_SEEK_CUR);
1423
3.87k
        else
1424
3.87k
          bIsIter=(val!=0);
1425
4.05k
      }
1426
4.27k
      *input >> nIterCount;
1427
4.27k
      *input >> fIterEps >> nPrecStandardFormat >> nDay >> nMonth >> nYear;
1428
4.27k
      if (bIsIgnoreCase) f << "ignore[case],";
1429
4.27k
      if (bIsIter) f << "isIter,";
1430
4.27k
      if (nIterCount) f << "iterCount=" << nIterCount << ",";
1431
4.27k
      if (nPrecStandardFormat) f << "precStandartFormat=" << nPrecStandardFormat << ",";
1432
4.27k
      if (fIterEps<0||fIterEps>0) f << "iter[eps]=" << fIterEps << ",";
1433
4.27k
      f << "date=" << nMonth << "/" << nDay << "/" << nYear << ",";
1434
4.27k
      if (input->tell()+1==endPos)
1435
230
        f << "unkn=" << input->readULong(1) << ",";
1436
4.27k
      if (input->tell()<endPos)
1437
812
        f << "tabs[distance]=" << input->readULong(2) << ",";
1438
4.27k
      if (input->tell()<endPos)
1439
812
        f << "calc[asShown]=" << input->readULong(1) << ",";
1440
4.27k
      if (input->tell()<endPos)
1441
812
        f << "match[wholeCell]=" << input->readULong(1) << ",";
1442
4.27k
      if (input->tell()<endPos)
1443
812
        f << "autoSpell=" << input->readULong(1) << ",";
1444
4.27k
      if (input->tell()<endPos)
1445
811
        f << "lookUpColRowNames=" << input->readULong(1) << ",";
1446
4.27k
      if (input->tell()<endPos) {
1447
803
        uint16_t nYear2000;
1448
803
        *input >> nYear2000;
1449
803
        if (input->tell()<endPos)
1450
81
          *input >> nYear2000;
1451
722
        else
1452
722
          nYear2000 = uint16_t(nYear2000+1901);
1453
803
        f << "year[2000]=" << nYear2000 << ",";
1454
803
      }
1455
4.27k
      break;
1456
4.18k
    }
1457
4.26k
    case 0x422a: {
1458
4.26k
      f << "viewOptions,";
1459
      // sc_viewopti.cxx operator>>(... ScViewOptions)
1460
46.9k
      for (int i=0; i<=9; ++i) {
1461
42.6k
        bool val;
1462
42.6k
        *input >> val;
1463
42.6k
        if (val) f << "opt" << i << ",";
1464
42.6k
      }
1465
17.0k
      for (int i=0; i<3; ++i) {
1466
12.8k
        uint8_t type;
1467
12.8k
        *input >> type;
1468
12.8k
        if (type) f << "type" << i << "=" << int(type) << ",";
1469
12.8k
      }
1470
4.26k
      STOFFColor col;
1471
4.26k
      if (!input->readColor(col)) {
1472
122
        STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readCalcDocument: can not read a color\n"));
1473
122
        f << "###color";
1474
122
        break;
1475
122
      }
1476
4.14k
      f << "col=" << col << ",";
1477
4.14k
      if (!zone.readString(string)) {
1478
40
        STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readCalcDocument: can not read a string\n"));
1479
40
        f << "###string";
1480
40
        break;
1481
40
      }
1482
4.10k
      else if (!string.empty())
1483
3.48k
        f << "name=" << libstoff::getString(string).cstr() << ",";
1484
4.10k
      if (input->tell()<endPos)
1485
4.05k
        f << "opt[helplines]=" << input->readULong(1) << ",";
1486
4.10k
      if (input->tell()<endPos) {
1487
        // ScGridOptions operator >>
1488
4.05k
        uint32_t drawX, drawY, divisionX, divisionY, snapX, snapY;
1489
4.05k
        *input >> drawX >> drawY >> divisionX >> divisionY >> snapX >> snapY;
1490
4.05k
        f << "grid[draw]=" << drawX << "x" << drawY << ",";
1491
4.05k
        f << "grid[division]=" << divisionX << "x" << divisionY << ",";
1492
4.05k
        f << "grid[snap]=" << snapX << "x" << snapY << ",";
1493
4.05k
        bool useSnap, synchronize, visibleGrid, equalGrid;
1494
4.05k
        *input >> useSnap >> synchronize >> visibleGrid >> equalGrid;
1495
4.05k
        if (useSnap) f << "grid[useSnap],";
1496
4.05k
        if (synchronize) f << "grid[synchronize],";
1497
4.05k
        if (visibleGrid) f << "grid[visible],";
1498
4.05k
        if (equalGrid) f << "grid[equal],";
1499
4.05k
      }
1500
4.10k
      if (input->tell()<endPos)
1501
830
        f << "hideAutoSpell=" << input->readULong(1) << ",";
1502
4.10k
      if (input->tell()<endPos)
1503
823
        f << "opt[anchor]=" << input->readULong(1) << ",";
1504
4.10k
      if (input->tell()<endPos)
1505
821
        f << "opt[pageBreak]=" << input->readULong(1) << ",";
1506
4.10k
      if (input->tell()<endPos)
1507
821
        f << "opt[solidHandles]=" << input->readULong(1) << ",";
1508
4.10k
      if (input->tell()<endPos)
1509
805
        f << "opt[clipMarks]=" << input->readULong(1) << ",";
1510
4.10k
      if (input->tell()<endPos)
1511
43
        f << "opt[bigHandles]=" << input->readULong(1) << ",";
1512
4.10k
      break;
1513
4.14k
    }
1514
4.09k
    case 0x422b: {
1515
4.09k
      f << "printer,";
1516
4.09k
      StarFileManager fileManager;
1517
4.09k
      if (!fileManager.readJobSetUp(zone, false))
1518
0
        break;
1519
      // TODO store the page size
1520
4.09k
      break;
1521
4.09k
    }
1522
23.3k
    case 0x422c: {
1523
23.3k
      f << "charset,";
1524
23.3k
      auto guiType=int(input->readULong(1));
1525
23.3k
      f << "gui[type]=" << guiType << ",";
1526
23.3k
      zone.setGuiType(guiType);
1527
23.3k
      auto charSet=int(input->readULong(1));
1528
23.3k
      f << "set=" << charSet << ",";
1529
23.3k
      if (StarEncoding::getEncodingForId(charSet)!=StarEncoding::E_DONTKNOW)
1530
23.3k
        zone.setEncoding(StarEncoding::getEncodingForId(charSet));
1531
0
      else
1532
0
        f << "###,";
1533
23.3k
      break;
1534
4.09k
    }
1535
91
    case 0x4232:
1536
189
    case 0x4233: {
1537
189
      f << (subId==4232 ? "colNameRange" : "rowNameRange") << ",";
1538
      // sc_rangelst.cxx ScRangePairList::Load(
1539
189
      uint32_t n;
1540
189
      *input >> n;
1541
189
      if (!n) break;
1542
177
      f << "ranges=[";
1543
177
      if (version<0x12) {
1544
135
        if (uint32_t(endPos-input->tell())/8<n || input->tell()+8*long(n) > endPos) {
1545
126
          STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readCalcDocument: can not read some ranges\n"));
1546
126
          f << "###ranges";
1547
126
          break;
1548
126
        }
1549
63
        for (uint32_t i=0; i<n; ++i)
1550
54
          f << std::hex << input->readULong(4) << "<->" << input->readULong(4) << std::dec << ",";
1551
9
      }
1552
42
      else {
1553
42
        if (input->tell()+16*long(n) > endPos) {
1554
37
          STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readCalcDocument: can not read some ranges\n"));
1555
37
          f << "###ranges";
1556
37
          break;
1557
37
        }
1558
32
        for (uint32_t i=0; i<n; ++i)
1559
27
          f << std::hex << input->readULong(4) << "<->" << input->readULong(4) << std::dec << ":"
1560
27
            << std::hex << input->readULong(4) << "<->" << input->readULong(4) << std::dec << ",";
1561
5
      }
1562
14
      f << "],";
1563
14
      break;
1564
177
    }
1565
106
    case 0x4235: {
1566
106
      f << "consolidateParam,";
1567
106
      uint8_t funct;
1568
106
      uint16_t nCol, nRow, nTab, nCount;
1569
106
      bool byCol, byRow, byReference;
1570
106
      *input >> nCol >> nRow >> nTab >> byCol >> byRow >> byReference >> funct >> nCount;
1571
106
      f << "cell=" << nCol << "x" << nRow << "x" << nTab << ",";
1572
106
      if (byCol) f << "byCol,";
1573
106
      if (byRow) f << "byRow,";
1574
106
      if (byReference) f << "byReference,";
1575
106
      f << "funct=" << funct << ",";
1576
106
      if (!nCount) break;
1577
62
      if (input->tell()+10*long(nCount) > endPos) {
1578
46
        STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readCalcDocument: can not read some area\n"));
1579
46
        f << "###area";
1580
46
        break;
1581
46
      }
1582
59
      for (int i=0; i<int(nCount); ++i) {
1583
43
        uint16_t nCol2, nRow2;
1584
43
        *input >> nTab >> nCol >> nRow >> nCol2 >> nRow2;
1585
43
        f << nCol << "x" << nRow << "<->" << nCol2 << "x" << nRow2 << "[" << nTab << "],";
1586
43
      }
1587
16
      break;
1588
62
    }
1589
62
    case 0x4236: {
1590
62
      f << "changeTrack,";
1591
62
      uint16_t loadVers;
1592
62
      *input >> loadVers;
1593
62
      f << "load[version]=" << loadVers << ",";
1594
62
      if (loadVers&0xff00) {
1595
24
        STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readCalcDocument: unknown version\n"));
1596
24
        f << "###version";
1597
24
        break;
1598
24
      }
1599
      // sc_chgtrack.cxx ScChangeTrack::Load
1600
38
      if (!readSCChangeTrack(zone,int(loadVers),endPos))
1601
0
        f << "###";
1602
38
      break;
1603
62
    }
1604
163
    case 0x4237: {
1605
163
      f << "changeViewSetting,";
1606
      // sc_chgviset.cxx ScChangeViewSettings::Load
1607
163
      bool bShowIt, bIsDate, bIsAuthor, bEveryoneButMe, bIsRange;
1608
163
      uint8_t dateMode;
1609
163
      uint32_t date1, time1, date2, time2;
1610
163
      *input >> bShowIt >> bIsDate >> dateMode >> date1 >> time1 >> date2 >> time2 >> bIsAuthor >> bEveryoneButMe;
1611
163
      if (bShowIt) f << "show,";
1612
163
      if (bIsDate) f << "isDate,";
1613
163
      f << "mode[date]=" << int(dateMode) << ",";
1614
163
      f << "firstDate=" << date1 << ",";
1615
163
      f << "firstTime=" << time1 << ",";
1616
163
      f << "lastDate=" << date2 << ",";
1617
163
      f << "lastTime=" << time2 << ",";
1618
163
      if (bIsAuthor) f << "isAuthor,";
1619
163
      if (bEveryoneButMe) f << "everyoneButMe,";
1620
163
      if (!zone.readString(string)) {
1621
24
        STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readCalcDocument: can not read a string\n"));
1622
24
        f << "###string";
1623
24
        break;
1624
24
      }
1625
139
      else if (!string.empty())
1626
47
        f << "author=" << libstoff::getString(string).cstr() << ",";
1627
139
      *input >> bIsRange;
1628
139
      if (bIsRange) f << "isRange,";
1629
139
      if (!zone.openSCRecord()) {
1630
71
        STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readCalcDocument: can not open the range list record\n"));
1631
71
        f << "###";
1632
71
        break;
1633
71
      }
1634
68
      uint32_t nRange;
1635
68
      *input >> nRange;
1636
68
      if (uint32_t(zone.getRecordLastPosition()-input->tell())<nRange ||
1637
48
          static_cast<unsigned long>(input->tell())+8*static_cast<unsigned long>(nRange)<=static_cast<unsigned long>(zone.getRecordLastPosition())) {
1638
21
        f << "ranges=[";
1639
77.2M
        for (uint32_t j=0; j<nRange; ++j)
1640
77.2M
          f << std::hex << input->readULong(4) << "<->" << input->readULong(4) << std::dec << ",";
1641
21
        f << "],";
1642
21
      }
1643
47
      else {
1644
47
        STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readCalcDocument: bad num rangen"));
1645
47
        f << "###nRange=" << nRange << ",";
1646
47
      }
1647
68
      zone.closeSCRecord("SCCalcDocument");
1648
68
      if (input->tell()<lastPos) {
1649
68
        bool bShowAccepted, bShowRejected;
1650
68
        *input >> bShowAccepted >> bShowRejected;
1651
68
        if (bShowAccepted) f << "show[accepted],";
1652
68
        if (bShowRejected) f << "show[rejected],";
1653
68
      }
1654
68
      if (input->tell()<lastPos) {
1655
68
        bool isComment;
1656
68
        *input >> isComment;
1657
68
        if (isComment) f << "isComment,";
1658
68
      }
1659
68
      break;
1660
139
    }
1661
54
    case 0x4238:
1662
54
      f << "linkUp[mode]=" << input->readULong(1) << ",";
1663
54
      break;
1664
28.6k
    default:
1665
28.6k
      f << "##";
1666
28.6k
      input->seek(endPos, librevenge::RVNG_SEEK_SET);
1667
93.7k
    }
1668
93.7k
    if (pos!=endPos) {
1669
93.7k
      ascFile.addPos(pos);
1670
93.7k
      ascFile.addNote(f.str().c_str());
1671
93.7k
    }
1672
93.7k
    zone.closeSCRecord("SCCalcDocument");
1673
93.7k
  }
1674
23.6k
  zone.closeSCRecord("SCCalcDocument");
1675
23.6k
  return true;
1676
23.6k
}
1677
30.7k
catch (...)
1678
30.7k
{
1679
0
  return false;
1680
0
}
1681
1682
bool StarObjectSpreadsheet::readSfxStyleSheets(STOFFInputStreamPtr input, std::string const &name)
1683
5.90k
{
1684
5.90k
  StarZone zone(input, name, "SfxStyleSheets", getPassword());
1685
5.90k
  input->seek(0, librevenge::RVNG_SEEK_SET);
1686
5.90k
  libstoff::DebugFile &ascFile=zone.ascii();
1687
5.90k
  ascFile.open(name);
1688
1689
5.90k
  std::shared_ptr<StarItemPool> mainPool;
1690
  // sc_docsh.cxx ScDocShell::LoadCalc and sc_document.cxx: ScDocument::LoadPool
1691
5.90k
  long pos=0;
1692
5.90k
  libstoff::DebugStream f;
1693
5.90k
  uint16_t nId;
1694
5.90k
  *input >> nId;
1695
5.90k
  f << "Entries(SfxStyleSheets):id=" << std::hex << nId << std::dec << ",calc,";
1696
5.90k
  if (getDocumentKind()!=STOFFDocument::STOFF_K_SPREADSHEET || !zone.openSCRecord()) {
1697
895
    STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSfxStyleSheets: can not open main zone\n"));
1698
895
    f << "###";
1699
895
    ascFile.addPos(pos);
1700
895
    ascFile.addNote(f.str().c_str());
1701
895
  }
1702
5.90k
  ascFile.addPos(pos);
1703
5.90k
  ascFile.addNote(f.str().c_str());
1704
5.90k
  long lastPos=zone.getRecordLastPosition();
1705
5.90k
  auto oldEncoding=zone.getEncoding();
1706
22.0k
  while (input->tell()+6 < lastPos) {
1707
17.2k
    pos=input->tell();
1708
17.2k
    f.str("");
1709
17.2k
    *input >> nId;
1710
17.2k
    f << "SfxStyleSheets-1:id=" << std::hex << nId << std::dec << ",";
1711
17.2k
    if (!zone.openSCRecord()) {
1712
1.11k
      STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSfxStyleSheets: can not open second zone\n"));
1713
1.11k
      f << "###";
1714
1.11k
      ascFile.addPos(pos);
1715
1.11k
      ascFile.addNote(f.str().c_str());
1716
1.11k
      break;
1717
1.11k
    }
1718
16.1k
    switch (nId) {
1719
4.60k
    case 0x4211:
1720
6.40k
    case 0x4214: {
1721
6.40k
      f << (nId==0x4211 ? "pool" : "pool[edit]") << ",";
1722
6.40k
      auto pool=getNewItemPool(nId==0x4211 ? StarItemPool::T_SpreadsheetPool : StarItemPool::T_EditEnginePool);
1723
6.40k
      if (pool && pool->read(zone)) {
1724
6.23k
        if (nId==0x4214 || !mainPool) mainPool=pool;
1725
6.23k
      }
1726
169
      else {
1727
169
        STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSfxStyleSheets: can not readPoolZone\n"));
1728
169
        f << "###";
1729
169
        input->seek(zone.getRecordLastPosition(), librevenge::RVNG_SEEK_SET);
1730
169
        break;
1731
169
      }
1732
6.23k
      break;
1733
6.40k
    }
1734
6.23k
    case 0x4212: {
1735
4.08k
      f << "style[pool],";
1736
4.08k
      if (!mainPool || !mainPool->readStyles(zone, *this)) {
1737
103
        STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSfxStyleSheets: can not readStylePool\n"));
1738
103
        f << "###";
1739
103
        input->seek(zone.getRecordLastPosition(), librevenge::RVNG_SEEK_SET);
1740
103
      }
1741
4.08k
      break;
1742
6.40k
    }
1743
4.65k
    case 0x422c: {
1744
4.65k
      uint8_t cSet, cGUI;
1745
4.65k
      *input >> cGUI >> cSet;
1746
4.65k
      if (cSet) {
1747
4.64k
        f << "charset=" << int(cSet) << ",";
1748
4.64k
        if (StarEncoding::getEncodingForId(cSet)!=StarEncoding::E_DONTKNOW)
1749
4.64k
          zone.setEncoding(StarEncoding::getEncodingForId(cSet));
1750
4.64k
      }
1751
4.65k
      if (cGUI) {
1752
2.24k
        zone.setGuiType(cGUI);
1753
2.24k
        f << "gui=" << int(cGUI) << ",";
1754
2.24k
      }
1755
4.65k
      break;
1756
6.40k
    }
1757
1.04k
    default:
1758
1.04k
      STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSfxStyleSheets: find unexpected tag\n"));
1759
1.04k
      input->seek(zone.getRecordLastPosition(), librevenge::RVNG_SEEK_SET);
1760
1.04k
      f << "###";
1761
1.04k
      break;
1762
16.1k
    }
1763
16.1k
    ascFile.addPos(pos);
1764
16.1k
    ascFile.addNote(f.str().c_str());
1765
16.1k
    zone.closeSCRecord("SfxStyleSheets");
1766
16.1k
  }
1767
5.90k
  zone.closeSCRecord("SfxStyleSheets");
1768
5.90k
  zone.setEncoding(oldEncoding);
1769
1770
5.90k
  if (!input->isEnd()) {
1771
1.26k
    STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSfxStyleSheets: find extra data\n"));
1772
1.26k
    ascFile.addPos(input->tell());
1773
1.26k
    ascFile.addNote("SfxStyleSheets:###extra");
1774
1.26k
  }
1775
5.90k
  if (mainPool) mainPool->updateStyles();
1776
5.90k
  return true;
1777
5.90k
}
1778
1779
////////////////////////////////////////////////////////////
1780
//
1781
// Low level
1782
//
1783
////////////////////////////////////////////////////////////
1784
bool StarObjectSpreadsheet::readSCTable(StarZone &zone, StarObjectSpreadsheetInternal::Table &table)
1785
19.8k
{
1786
19.8k
  STOFFInputStreamPtr input=zone.input();
1787
19.8k
  long pos=input->tell();
1788
1789
  // sc_table2.cxx ScTable::Load
1790
19.8k
  if (!zone.openSCRecord()) {
1791
272
    input->seek(pos, librevenge::RVNG_SEEK_SET);
1792
272
    return false;
1793
272
  }
1794
19.6k
  libstoff::DebugFile &ascFile=zone.ascii();
1795
19.6k
  libstoff::DebugStream f;
1796
19.6k
  long lastPos=zone.getRecordLastPosition();
1797
19.6k
  f << "Entries(SCTable)[" << zone.getRecordLevel() << "]:";
1798
19.6k
  ascFile.addPos(pos);
1799
19.6k
  ascFile.addNote(f.str().c_str());
1800
1801
19.6k
  std::vector<uint32_t> string;
1802
69.7k
  while (input->tell()<lastPos) {
1803
54.2k
    pos=input->tell();
1804
54.2k
    uint16_t id;
1805
54.2k
    *input>>id;
1806
54.2k
    f.str("");
1807
54.2k
    f << "SCTable[" << std::hex << id << std::dec << "]:";
1808
54.2k
    if (id==0x4240) {
1809
19.3k
      StarObjectSpreadsheetInternal::ScMultiRecord scRecord(zone);
1810
19.3k
      f << "columns,";
1811
19.3k
      if (!scRecord.open()) {
1812
2.23k
        input->seek(pos,librevenge::RVNG_SEEK_SET);
1813
2.23k
        STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCTable: can not find the column header \n"));
1814
2.23k
        f << "###";
1815
2.23k
        ascFile.addPos(pos);
1816
2.23k
        ascFile.addNote(f.str().c_str());
1817
2.23k
        break;
1818
2.23k
      }
1819
17.1k
      ascFile.addPos(pos);
1820
17.1k
      ascFile.addNote(f.str().c_str());
1821
17.1k
      int nCol=0;
1822
17.1k
      long endDataPos=zone.getRecordLastPosition();
1823
252k
      while (input->tell()<endDataPos) {
1824
239k
        if (table.getLoadingVersion()>=6) {
1825
238k
          pos=input->tell();
1826
238k
          nCol=int(input->readULong(1));
1827
238k
          f.str("");
1828
238k
          f << "SCTable:C" << nCol << ",";
1829
238k
          ascFile.addPos(pos);
1830
238k
          ascFile.addNote(f.str().c_str());
1831
238k
        }
1832
1.27k
        else if (nCol>table.getMaxCols())
1833
1
          break;
1834
239k
        pos=input->tell();
1835
239k
        if (!scRecord.openContent("SCTable")) {
1836
3.90k
          STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCTable: can not open a column \n"));
1837
3.90k
          ascFile.addPos(pos);
1838
3.90k
          ascFile.addNote("SCTable-C###");
1839
3.90k
          break;
1840
3.90k
        }
1841
235k
        if (!readSCColumn(zone,table, nCol, scRecord.getContentLastPosition())) {
1842
0
          ascFile.addPos(pos);
1843
0
          ascFile.addNote("SCTable-C###");
1844
0
          input->seek(scRecord.getContentLastPosition(), librevenge::RVNG_SEEK_SET);
1845
0
        }
1846
235k
        scRecord.closeContent("SCTable");
1847
235k
        ++nCol;
1848
235k
      }
1849
17.1k
      scRecord.close("SCTable");
1850
17.1k
      continue;
1851
19.3k
    }
1852
34.9k
    if (!zone.openSCRecord()) {
1853
1.87k
      STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCTable: can not open the zone record\n"));
1854
1.87k
      f << "###";
1855
1.87k
      ascFile.addPos(pos);
1856
1.87k
      ascFile.addNote(f.str().c_str());
1857
1.87k
      break;
1858
1.87k
    }
1859
33.0k
    long endDataPos=zone.getRecordLastPosition();
1860
33.0k
    switch (id) {
1861
16.1k
    case 0x4241: { // SCID_COLROWFLAGS
1862
16.1k
      f << "dim,";
1863
16.1k
      f << "col[width]=[";
1864
16.1k
      uint16_t rep;
1865
16.1k
      bool ok=true;
1866
59.0k
      for (int i=0; i<=table.getMaxCols();) {
1867
42.8k
        uint16_t val;
1868
42.8k
        *input>>rep >> val;
1869
42.8k
        if (input->tell()>endDataPos) {
1870
21
          ok=false;
1871
21
          break;
1872
21
        }
1873
42.8k
        if (rep>1)
1874
21.5k
          f << val << "x" << rep << ",";
1875
21.3k
        else if (rep==1)
1876
21.1k
          f << val << ",";
1877
19.9M
        for (int j=0; j<int(rep); ++j) {
1878
19.8M
          if (i+j>int(rep)+table.getMaxCols())
1879
0
            break;
1880
19.8M
          table.m_colWidthList.push_back(int(val));
1881
19.8M
        }
1882
42.8k
        i+=int(rep);
1883
42.8k
      }
1884
16.1k
      f << "],col[flag]=[";
1885
32.7k
      for (int i=0; i<=table.getMaxCols();) {
1886
16.6k
        uint8_t flags;
1887
16.6k
        *input>>rep >> flags;
1888
16.6k
        if (input->tell()>endDataPos) {
1889
28
          ok=false;
1890
28
          break;
1891
28
        }
1892
16.5k
        if (rep>1)
1893
16.3k
          f << int(flags) << "x" << (rep+1) << ",";
1894
282
        else if (rep)
1895
163
          f << int(flags) << ",";
1896
16.5k
        i+=int(rep);
1897
16.5k
      }
1898
16.1k
      f << "],row[height]=[";
1899
78.0k
      for (int i=0; i<=table.getMaxRows();) {
1900
62.2k
        uint16_t val;
1901
62.2k
        *input>>rep >> val;
1902
62.2k
        if (input->tell()>endDataPos) {
1903
392
          ok=false;
1904
392
          break;
1905
392
        }
1906
61.8k
        if (rep>1)
1907
26.1k
          f << val << "x" << (rep+1) << ",";
1908
35.7k
        else if (rep==1)
1909
35.2k
          f << val << ",";
1910
61.8k
        if (rep>0) {
1911
61.3k
          table.m_rowHeightMap[STOFFVec2i(i,i+rep-1)]=int(val);
1912
61.3k
          i+=int(rep);
1913
61.3k
        }
1914
61.8k
      }
1915
16.1k
      f << "],row[flag]=[";
1916
39.1k
      for (int i=0; i<=table.getMaxRows();) {
1917
23.6k
        uint8_t flags;
1918
23.6k
        *input>>rep >> flags;
1919
23.6k
        if (input->tell()>endDataPos) {
1920
625
          ok=false;
1921
625
          break;
1922
625
        }
1923
22.9k
        if (rep>1)
1924
19.1k
          f << int(flags) << "x" << (rep+1) << ",";
1925
3.88k
        else if (rep==1)
1926
3.60k
          f << int(flags) << ",";
1927
22.9k
        i+=int(rep);
1928
22.9k
      }
1929
16.1k
      f << "],";
1930
16.1k
      if (!ok) {
1931
625
        STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCTable: somethings went bad\n"));
1932
625
        f << "###bound";
1933
625
        break;
1934
625
      }
1935
15.5k
      break;
1936
16.1k
    }
1937
15.5k
    case 0x4242: { // SCID_TABOPTIONS
1938
15.3k
      f << "tabOptions,";
1939
15.3k
      bool ok=true;
1940
15.3k
      bool bVal;
1941
45.5k
      for (int i=0; i<3; ++i) {
1942
45.5k
        if (!zone.readString(string) || input->tell()>endDataPos) {
1943
448
          STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCTable: can not read a string\n"));
1944
448
          f << "###string" << i;
1945
448
          ok=false;
1946
448
          break;
1947
448
        }
1948
45.1k
        if (!string.empty()) {
1949
15.2k
          static char const* const wh[]= {"name", "comment", "pass"};
1950
15.2k
          f << wh[i] << "=" << libstoff::getString(string).cstr() << ",";
1951
15.2k
          if (i==0 && !m_spreadsheetState->m_tableList.empty() && m_spreadsheetState->m_tableList.back())
1952
15.1k
            m_spreadsheetState->m_tableList.back()->m_name=libstoff::getString(string);
1953
15.2k
        }
1954
45.1k
        if (i==2) break;
1955
30.2k
        *input>>bVal;
1956
30.2k
        if (bVal) f << (i==0 ? "scenario," : "protected") << ",";
1957
30.2k
      }
1958
15.3k
      if (!ok) break;
1959
14.8k
      *input>> bVal;
1960
14.8k
      if (bVal) {
1961
149
        f << "outlineTable,";
1962
149
        ascFile.addPos(pos);
1963
149
        ascFile.addNote(f.str().c_str());
1964
1965
149
        for (int i=0; i<2; ++i) {
1966
149
          pos=input->tell();
1967
149
          if (!readSCOutlineArray(zone)) {
1968
149
            STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCTable: can not open the zone record\n"));
1969
149
            ok=false;
1970
149
            input->seek(pos,librevenge::RVNG_SEEK_SET);
1971
149
            break;
1972
149
          }
1973
149
        }
1974
149
        f.str("");
1975
149
        f << "SCTable[tabOptionsB]:";
1976
149
        pos=input->tell();
1977
149
        if (!ok) {
1978
149
          f << "###outline,";
1979
149
          break;
1980
149
        }
1981
149
      }
1982
14.7k
      if (input->tell()<endDataPos) {
1983
14.7k
        if (!zone.readString(string) || input->tell()>endDataPos) {
1984
478
          STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCTable: can not read a string\n"));
1985
478
          f << "###pageStyle";
1986
478
          break;
1987
478
        }
1988
14.2k
        table.m_pageStyle=libstoff::getString(string);
1989
14.2k
        if (!string.empty())
1990
14.1k
          f << "pageStyle=" << table.m_pageStyle.cstr() << ",";
1991
14.2k
      }
1992
14.2k
      if (input->tell()<endDataPos) {
1993
20.6k
        for (int i=0; i<3; ++i) {
1994
15.5k
          *input >> bVal;
1995
15.5k
          if (!bVal) continue;
1996
405
          f << "range" << i << "=" << std::hex << input->readULong(4) << "<->" << input->readULong(4) << std::dec << ",";
1997
405
        }
1998
5.16k
      }
1999
14.2k
      if (input->tell()<endDataPos)
2000
5.04k
        f << "isVisible=" << input->readULong(1);
2001
14.2k
      if (input->tell()<endDataPos) {
2002
5.04k
        uint16_t nCount;
2003
5.04k
        *input>>nCount;
2004
5.04k
        if (input->tell()+8*long(nCount)>endDataPos) {
2005
40
          STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCTable: bad nCount\n"));
2006
40
          f << "###nCount=" << nCount << ",";
2007
40
          break;
2008
40
        }
2009
5.00k
        f << "ranges=[";
2010
5.01k
        for (int i=0; i<int(nCount); ++i)
2011
8
          f << "range" << i << "=" << std::hex << input->readULong(4) << "<->" << input->readULong(4) << std::dec << ",";
2012
5.00k
        f << "],";
2013
5.00k
      }
2014
14.2k
      if (input->tell()<endDataPos) {
2015
4.92k
        STOFFColor color;
2016
4.92k
        if (!input->readColor(color)) {
2017
23
          STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCTable: can not read a color\n"));
2018
23
          f << "###color";
2019
23
          break;
2020
23
        }
2021
4.90k
        f << "scenario[color]=" << color << ",";
2022
4.90k
        f << "scenario[flags]=" << input->readULong(2) << ",";
2023
4.90k
        f << "scenario[active]=" << input->readULong(1) << ",";
2024
4.90k
      }
2025
14.1k
      break;
2026
14.2k
    }
2027
14.1k
    case 0x4243: {
2028
429
      f << "tabLink,";
2029
429
      f << "mode=" << input->readULong(1) << ",";
2030
429
      bool ok=true;
2031
1.60k
      for (int i=0; i<3; ++i) {
2032
1.22k
        if (!zone.readString(string) || input->tell()>endDataPos) {
2033
45
          STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCTable: can not read a string\n"));
2034
45
          f << "###string" << i;
2035
45
          ok=false;
2036
45
          break;
2037
45
        }
2038
1.17k
        if (string.empty()) continue;
2039
1.14k
        static char const* const wh[]= {"doc", "flt", "tab"};
2040
1.14k
        f << "link[" << wh[i] << "]=" << libstoff::getString(string).cstr() << ",";
2041
1.14k
      }
2042
429
      if (!ok) break;
2043
384
      if (input->tell()<endDataPos)
2044
384
        f << "bRelUrl=" << input->readULong(1) << ",";
2045
384
      if (input->tell()<endDataPos) {
2046
382
        if (!zone.readString(string) || input->tell()>endDataPos) {
2047
36
          STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCTable: can not read a string\n"));
2048
36
          f << "###opt";
2049
36
          break;
2050
36
        }
2051
346
        if (string.empty()) continue;
2052
2
        f << "link[opt]=" << libstoff::getString(string).cstr() << ",";
2053
2
      }
2054
4
      break;
2055
384
    }
2056
1.11k
    default:
2057
1.11k
      STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCTable: find unexpected type\n"));
2058
1.11k
      f << "###";
2059
1.11k
      input->seek(endDataPos, librevenge::RVNG_SEEK_SET);
2060
33.0k
    }
2061
32.7k
    ascFile.addPos(pos);
2062
32.7k
    ascFile.addNote(f.str().c_str());
2063
32.7k
    zone.closeSCRecord("SCTable");
2064
32.7k
  }
2065
19.6k
  zone.closeSCRecord("SCTable");
2066
19.6k
  return true;
2067
19.6k
}
2068
2069
bool StarObjectSpreadsheet::readSCColumn(StarZone &zone, StarObjectSpreadsheetInternal::Table &table,
2070
    int column, long lastPos)
2071
235k
{
2072
235k
  STOFFInputStreamPtr input=zone.input();
2073
235k
  long pos=input->tell();
2074
2075
  // sc_column2.cxx ScColumn::Load
2076
235k
  libstoff::DebugFile &ascFile=zone.ascii();
2077
235k
  libstoff::DebugStream f;
2078
235k
  f << "Entries(SCColumn)-C" << column << "[" << zone.getRecordLevel() << "]:";
2079
235k
  ascFile.addPos(pos);
2080
235k
  ascFile.addNote(f.str().c_str());
2081
235k
  std::vector<uint32_t> string;
2082
423k
  while (input->tell()<lastPos) {
2083
289k
    pos=input->tell();
2084
289k
    uint16_t id;
2085
289k
    *input>>id;
2086
289k
    f.str("");
2087
289k
    f << "SCColumn[" << std::hex << id << std::dec << "]:";
2088
289k
    if (id==0x4250 && readSCData(zone,table,column)) {
2089
53.0k
      f << "data,";
2090
53.0k
      ascFile.addPos(pos);
2091
53.0k
      ascFile.addNote(f.str().c_str());
2092
53.0k
      continue;
2093
53.0k
    }
2094
236k
    input->seek(pos+2, librevenge::RVNG_SEEK_SET);
2095
236k
    bool ok=zone.openSCRecord();
2096
236k
    if (!ok || zone.getRecordLastPosition()>lastPos) {
2097
101k
      STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCColumn:can not open record\n"));
2098
101k
      f << "###";
2099
101k
      if (ok) zone.closeSCRecord("SCColumn");
2100
101k
      ascFile.addPos(pos);
2101
101k
      ascFile.addNote(f.str().c_str());
2102
101k
      break;
2103
101k
    }
2104
134k
    long endDataPos=zone.getRecordLastPosition();
2105
134k
    switch (id) {
2106
367
    case 0x4251: {
2107
367
      f << "notes,";
2108
367
      uint16_t nCount;
2109
367
      *input >> nCount;
2110
367
      f << "n=" << nCount << ",";
2111
720
      for (int i=0; i<nCount; ++i) {
2112
714
        auto row=int(input->readULong(2));
2113
714
        f << "note" << i << "[R" << row << ",";
2114
714
        auto &cell=table.getCell(STOFFVec2i(column, row));
2115
        // sc_cell.cxx ScBaseCell::LoadNotes, ScPostIt operator>>
2116
1.80k
        for (int j=0; j<3; ++j) {
2117
1.45k
          if (!zone.readString(string)||input->tell()>endDataPos) {
2118
361
            STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCColumn:can not read a string\n"));
2119
361
            f << "###string" << j;
2120
361
            ok=false;
2121
361
            break;
2122
361
          }
2123
1.08k
          if (string.empty()) continue;
2124
378
          static char const* const wh[]= {"note","date","author"};
2125
378
          cell.m_notes[j]=libstoff::getString(string);
2126
378
          f << wh[j] << "=" << cell.m_notes[j].cstr()  << ",";
2127
378
        }
2128
714
        if (!ok) break;
2129
353
        cell.m_hasNote=true;
2130
353
        f << "],";
2131
353
      }
2132
367
      break;
2133
0
    }
2134
107k
    case 0x4252: {
2135
107k
      f << "attrib,";
2136
      // sc_attarray.cxx ScAttrArray::Load
2137
107k
      uint16_t nCount;
2138
107k
      *input >> nCount;
2139
107k
      f << "n=" << nCount << ",";
2140
107k
      std::shared_ptr<StarItemPool> pool=findItemPool(StarItemPool::T_SpreadsheetPool, false);
2141
107k
      if (!pool) {
2142
124
        STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCColumn:can not read the spreadsheet pool, create a new one\n"));
2143
124
        pool=getNewItemPool(StarItemPool::T_SpreadsheetPool);
2144
124
      }
2145
107k
      f << "attrib=[";
2146
#if 0
2147
      std::cerr << "Attrib\n";
2148
#endif
2149
702k
      for (int i=0,row=0; i<nCount; ++i) {
2150
596k
        auto newRow=int(input->readULong(2));
2151
596k
        f << newRow << ":";
2152
596k
        uint16_t nWhich=149;//StarAttribute::ATTR_SC_PATTERN-3;
2153
596k
        auto item=pool->loadSurrogate(zone, nWhich, false, f);
2154
596k
        if (!item || input->tell()>endDataPos) {
2155
750
          STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCColumn:can not read a attrib\n"));
2156
750
          f << "###attrib";
2157
750
          break;
2158
750
        }
2159
595k
        if (!item->m_attribute) {
2160
50.8k
          row=newRow+1;
2161
50.8k
          continue;
2162
50.8k
        }
2163
#if 0
2164
        libstoff::DebugStream f2;
2165
        std::set<StarAttribute const *> done;
2166
        item->m_attribute->print(f2, done);
2167
        std::cerr << "\tC" << column << "x" << STOFFVec2i(row, newRow) << ":" << f2.str().c_str() << "[" << item->m_attribute.get() << "]\n";
2168
#endif
2169
544k
        if (newRow>=row) {
2170
523k
          table.updateRowsBlocks(STOFFVec2i(row, newRow));
2171
523k
          auto it= table.m_rowToRowContentMap.lower_bound(STOFFVec2i(-1,row));
2172
3.21M
          while (it!=table.m_rowToRowContentMap.end() && it->first[1]<=newRow) {
2173
2.69M
            it->second.m_colToAttributeMap[STOFFVec2i(column, column)]=item->m_attribute;
2174
2.69M
            ++it;
2175
2.69M
          }
2176
523k
          row=newRow+1;
2177
523k
        }
2178
544k
      }
2179
107k
      f << "],";
2180
107k
      break;
2181
0
    }
2182
26.5k
    default:
2183
26.5k
      STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCColumn: find unexpected type\n"));
2184
26.5k
      f << "###";
2185
26.5k
      input->seek(endDataPos, librevenge::RVNG_SEEK_SET);
2186
134k
    }
2187
134k
    ascFile.addPos(pos);
2188
134k
    ascFile.addNote(f.str().c_str());
2189
134k
    zone.closeSCRecord("SCColumn");
2190
134k
  }
2191
235k
  input->seek(lastPos, librevenge::RVNG_SEEK_SET);
2192
235k
  return true;
2193
235k
}
2194
2195
bool StarObjectSpreadsheet::readSCData(StarZone &zone, StarObjectSpreadsheetInternal::Table &table, int column)
2196
58.6k
{
2197
58.6k
  STOFFInputStreamPtr input=zone.input();
2198
58.6k
  long pos=input->tell();
2199
2200
  // sc_column2.cxx ScColumn::LoadData
2201
58.6k
  StarObjectSpreadsheetInternal::ScMultiRecord scRecord(zone);
2202
58.6k
  if (!scRecord.open()) {
2203
5.52k
    input->seek(pos,librevenge::RVNG_SEEK_SET);
2204
5.52k
    return false;
2205
5.52k
  }
2206
53.0k
  libstoff::DebugFile &ascFile=zone.ascii();
2207
53.0k
  libstoff::DebugStream f;
2208
53.0k
  f << "Entries(SCData)[C" << column << "-" << zone.getRecordLevel() << "]:" << scRecord;
2209
53.0k
  auto count=int(input->readULong(2));
2210
53.0k
  f << "count=" << count << ",";
2211
53.0k
  ascFile.addPos(pos);
2212
53.0k
  ascFile.addNote(f.str().c_str());
2213
2214
53.0k
  long lastPos=zone.getRecordLastPosition();
2215
53.0k
  int const version=table.getLoadingVersion();
2216
579k
  for (int i=0; i<count; ++i) {
2217
535k
    pos=input->tell();
2218
535k
    f.str("");
2219
535k
    f << "SCData-" << i << ":";
2220
535k
    if (input->tell()+4>lastPos) {
2221
520
      STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCData:can not read some data\n"));
2222
520
      f << "###";
2223
520
      ascFile.addPos(pos);
2224
520
      ascFile.addNote(f.str().c_str());
2225
520
      break;
2226
520
    }
2227
534k
    auto row=int(input->readULong(2));
2228
534k
    f << "row=" << row << ",";
2229
534k
    uint8_t what;
2230
534k
    *input>>what;
2231
534k
    bool ok=true;
2232
534k
    auto &cell=table.getCell(STOFFVec2i(column, row));
2233
534k
    STOFFCell::Format format=cell.getFormat();
2234
534k
    switch (what) {
2235
343k
    case 1: { // value
2236
      // sc_cell2.cxx
2237
343k
      f << "value,";
2238
343k
      if (version>=7) {
2239
343k
        uint8_t unkn;
2240
343k
        *input>>unkn;
2241
343k
        if (unkn&0xf) input->seek((unkn&0xf), librevenge::RVNG_SEEK_CUR);
2242
343k
      }
2243
343k
      double value;
2244
343k
      *input >> value;
2245
343k
      format.m_format=STOFFCell::F_NUMBER;
2246
343k
      cell.m_content.m_contentType=STOFFCellContent::C_NUMBER;
2247
343k
      cell.m_content.setValue(value);
2248
343k
      f << "val=" << value << ",";
2249
343k
      break;
2250
0
    }
2251
113k
    case 2:
2252
113k
    case 6: {
2253
      // sc_cell2.cxx
2254
113k
      f << (what==2 ? "string" : "symbol") << ",";
2255
113k
      if (version>=7) {
2256
113k
        uint8_t unkn;
2257
113k
        *input>>unkn;
2258
113k
        if (unkn&0xf) input->seek((unkn&0xf), librevenge::RVNG_SEEK_CUR);
2259
113k
      }
2260
113k
      std::vector<uint32_t> text;
2261
113k
      if (!zone.readString(text)) {
2262
395
        STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCData: can not open some text \n"));
2263
395
        f << "###text";
2264
395
        ok=false;
2265
395
        break;
2266
395
      }
2267
      // checkme: never seems what==6, so unsure...
2268
112k
      format.m_format=STOFFCell::F_TEXT;
2269
112k
      cell.m_content.m_contentType=STOFFCellContent::C_TEXT_BASIC;
2270
112k
      cell.m_content.m_text=text;
2271
112k
      f << "val=" << libstoff::getString(text).cstr() << ",";
2272
112k
      break;
2273
113k
    }
2274
58.9k
    case 3: { // TODO
2275
      // sc_cell.cxx
2276
58.9k
      f << "formula,";
2277
58.9k
      if (!scRecord.openContent("SCData")) {
2278
981
        STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCData: can not open a formula \n"));
2279
981
        f << "###formula";
2280
981
        ok=false;
2281
981
        break;
2282
981
      }
2283
57.9k
      long endDataPos=scRecord.getContentLastPosition();
2284
57.9k
      if (version>=8) {
2285
57.8k
        auto cData=int(input->readULong(1));
2286
57.8k
        if ((cData&0x10) && (cData&0xf)>=4) {
2287
724
          f << "format=" <<input->readULong(4)<<",";
2288
724
          cData-=4;
2289
724
        }
2290
57.8k
        if (cData&0xf) input->seek((cData&0xf), librevenge::RVNG_SEEK_CUR);
2291
57.8k
        uint8_t cFlags;
2292
57.8k
        *input >> cFlags;
2293
57.8k
        f << "formatType=" << input->readLong(2) << ",";
2294
57.8k
        if (cFlags&8) {
2295
56.5k
          double ergValue;
2296
56.5k
          *input >> ergValue;
2297
56.5k
          format.m_format=STOFFCell::F_NUMBER;
2298
56.5k
          cell.m_content.m_contentType=STOFFCellContent::C_NUMBER;
2299
56.5k
          cell.m_content.setValue(ergValue);
2300
56.5k
          f << "ergValue=" << ergValue << ",";
2301
56.5k
        }
2302
57.8k
        if (cFlags&0x10) {
2303
1.00k
          std::vector<uint32_t> text;
2304
1.00k
          if (!zone.readString(text)) {
2305
41
            STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCData: can not open some text\n"));
2306
41
            f << "###text";
2307
41
            ascFile.addDelimiter(input->tell(),'|');
2308
41
            input->seek(endDataPos, librevenge::RVNG_SEEK_SET);
2309
41
            scRecord.closeContent("SCData");
2310
41
            break;
2311
41
          }
2312
964
          else if (!text.empty()) {
2313
907
            format.m_format=STOFFCell::F_TEXT;
2314
907
            cell.m_content.m_contentType=STOFFCellContent::C_TEXT_BASIC;
2315
907
            cell.m_content.m_text=text;
2316
907
            f << "val=" << libstoff::getString(text).cstr() << ",";
2317
907
          }
2318
1.00k
        }
2319
57.8k
        ascFile.addPos(pos);
2320
57.8k
        ascFile.addNote(f.str().c_str());
2321
57.8k
        pos=input->tell();
2322
57.8k
        f.str("");
2323
57.8k
        f << "SCData[formula]:";
2324
2325
57.8k
        if (!StarCellFormula::readSCFormula(zone, cell.m_content, version, endDataPos) || input->tell()>endDataPos) {
2326
3.75k
          f << "###";
2327
3.75k
          scRecord.closeContent("SCData");
2328
3.75k
          ascFile.addDelimiter(input->tell(),'|');
2329
3.75k
          input->seek(endDataPos, librevenge::RVNG_SEEK_SET);
2330
3.75k
          break;
2331
3.75k
        }
2332
54.0k
        pos=input->tell();
2333
54.0k
        if ((cFlags&3)==1 && input->tell()<endDataPos)
2334
46
          f << "cols=" << input->readULong(2) << ",rows=" << input->readULong(2) << ",";
2335
54.0k
      }
2336
59
      else {
2337
59
        if (version>=2) input->seek(2, librevenge::RVNG_SEEK_CUR);
2338
59
        f << "matrix[flags]=" << input->readULong(1) << ",";
2339
59
        uint16_t codeLen;
2340
59
        *input>>codeLen;
2341
59
        if (codeLen && (!StarCellFormula::readSCFormula3(zone, cell.m_content, version, endDataPos) || input->tell()>endDataPos))
2342
3
          f << "###";
2343
59
      }
2344
54.1k
      if (input->tell()!=endDataPos) {
2345
1.07k
        f << "##";
2346
1.07k
        ascFile.addDelimiter(input->tell(),'|');
2347
1.07k
        input->seek(endDataPos, librevenge::RVNG_SEEK_SET);
2348
1.07k
      }
2349
54.1k
      scRecord.closeContent("SCData");
2350
54.1k
      break;
2351
57.9k
    }
2352
2.75k
    case 4: {
2353
      // sc_cell2.cxx
2354
2.75k
      f << "note";
2355
2.75k
      if (version>=7) {
2356
2.74k
        uint8_t unkn;
2357
2.74k
        *input>>unkn;
2358
2.74k
        if (unkn&0xf) input->seek((unkn&0xf), librevenge::RVNG_SEEK_CUR);
2359
2.74k
      }
2360
2.75k
      break;
2361
57.9k
    }
2362
10.3k
    case 5: { // TODO
2363
      // sc_cell2.cxx
2364
10.3k
      f << "edit";
2365
10.3k
      if (version>=7) {
2366
10.3k
        uint8_t unkn;
2367
10.3k
        *input>>unkn;
2368
10.3k
        if (unkn&0xf) input->seek((unkn&0xf), librevenge::RVNG_SEEK_CUR);
2369
10.3k
      }
2370
10.3k
      std::shared_ptr<StarObjectSmallText> textZone(new StarObjectSmallText(*this, true));
2371
10.3k
      if (!textZone->read(zone, lastPos) || input->tell()>lastPos) {
2372
799
        STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCData: can not open some edit text \n"));
2373
799
        f << "###edit";
2374
799
        ok=false;
2375
799
        break;
2376
799
      }
2377
9.53k
      format.m_format=STOFFCell::F_TEXT;
2378
9.53k
      cell.m_content.m_contentType=STOFFCellContent::C_TEXT;
2379
9.53k
      cell.m_textZone=textZone;
2380
9.53k
      break;
2381
10.3k
    }
2382
6.15k
    default:
2383
6.15k
      STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCData: find unexpected type\n"));
2384
6.15k
      f << "###type=" << what;
2385
6.15k
      ok=false;
2386
6.15k
      break;
2387
534k
    }
2388
534k
    cell.setFormat(format);
2389
2390
534k
    if (!ok || pos!=input->tell()) {
2391
481k
      ascFile.addPos(pos);
2392
481k
      ascFile.addNote(f.str().c_str());
2393
481k
    }
2394
534k
    if (!ok) break;
2395
534k
  }
2396
53.0k
  scRecord.close("SCData");
2397
53.0k
  return true;
2398
53.0k
}
2399
2400
// sc_chgtrack.cxx ScChangeActionContent::ScChangeActionContent
2401
2402
bool StarObjectSpreadsheet::readSCChangeTrack(StarZone &zone, int /*version*/, long lastPos)
2403
38
{
2404
38
  STOFFInputStreamPtr input=zone.input();
2405
38
  long pos=input->tell();
2406
2407
38
  libstoff::DebugFile &ascFile=zone.ascii();
2408
38
  libstoff::DebugStream f;
2409
38
  f << "Entries(SCChangeTrack)[" << zone.getRecordLevel() << "]:";
2410
  // sc_chgtrack.cxx ScChangeTrack::Load
2411
2412
38
  if (!zone.openSCRecord()) {
2413
10
    STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCChangeTrack: can not find string collection\n"));
2414
10
    ascFile.addDelimiter(input->tell(),'|');
2415
10
    f << "###strings";
2416
10
    input->seek(lastPos, librevenge::RVNG_SEEK_SET);
2417
10
    return true;
2418
10
  }
2419
28
  bool bDup;
2420
28
  uint16_t count, limit, delta;
2421
28
  *input >> bDup >> count >> limit >> delta;
2422
28
  if (bDup) f << "bDups,";
2423
28
  if (limit) f << "limit=" << limit << ",";
2424
28
  if (delta) f << "delta=" << delta << ",";
2425
28
  long endData=zone.getRecordLastPosition();
2426
28
  std::vector<uint32_t> string;
2427
100
  for (uint16_t i=0; i<count; ++i) {
2428
89
    if (!zone.readString(string) || input->tell() > endData) {
2429
17
      STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCChangeTrack: can not open some string\n"));
2430
17
      f << "###string";
2431
17
      ascFile.addDelimiter(input->tell(),'|');
2432
17
      input->seek(endData, librevenge::RVNG_SEEK_SET);
2433
17
      break;
2434
17
    }
2435
72
    else if (!string.empty())
2436
13
      f << "string" << i << "=" << libstoff::getString(string).cstr() << ",";
2437
89
  }
2438
28
  zone.closeSCRecord("SCChangeTrack");
2439
2440
28
  uint32_t nCount, nActionMax, nLastAction, nGeneratedCount;
2441
28
  *input >> nCount >> nActionMax >> nLastAction >> nGeneratedCount;
2442
28
  if (nCount) f << "count=" << nCount << ",";
2443
28
  if (nActionMax) f << "actionMax=" << nActionMax << ",";
2444
28
  if (nLastAction) f << "lastAction=" << nLastAction << ",";
2445
2446
28
  for (int s=0; s<2; ++s) {
2447
28
    if (s==1) {
2448
0
      pos=input->tell();
2449
0
      f.str("");
2450
0
      f << "Entries(SCChangeTrack)[A]:";
2451
0
    }
2452
28
    StarObjectSpreadsheetInternal::ScMultiRecord scRecord(zone);
2453
28
    if (!scRecord.open()) {
2454
28
      STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCChangeTrack: can not find the action list\n"));
2455
28
      ascFile.addDelimiter(input->tell(),'|');
2456
28
      f << "###actions";
2457
28
      input->seek(lastPos, librevenge::RVNG_SEEK_SET);
2458
28
      return true;
2459
28
    }
2460
0
    ascFile.addPos(pos);
2461
0
    ascFile.addNote(f.str().c_str());
2462
2463
0
    for (uint32_t i=0; i<(s==0 ? nGeneratedCount:nCount); ++i) {
2464
0
      f.str("");
2465
0
      f << "Entries(SCChangeTrack)[A" << i << "]:";
2466
0
      if (!scRecord.openContent("SCChangeTrack")) {
2467
0
        f << "###";
2468
0
        ascFile.addPos(pos);
2469
0
        ascFile.addNote(f.str().c_str());
2470
0
        STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCChangeTrack:can not read an action\n"));
2471
0
        break;
2472
0
      }
2473
0
      endData=scRecord.getContentLastPosition();
2474
2475
0
      uint8_t type;
2476
0
      *input >> type;
2477
0
      uint32_t col, row, tab, date, time, action, rejAction, state;
2478
0
      *input >> col >> row >> tab >> date >> time >> action >> rejAction >> state;
2479
0
      f << "cell=" << col << "x" << row << "[" << tab << "],";
2480
0
      f << "date=" << date << ",";
2481
0
      f << "time=" << time << ",";
2482
0
      if (action) f << "action=" << action << ",";
2483
0
      if (rejAction) f << "rejAction=" << rejAction << ",";
2484
0
      if (state) f << "state=" << state << ",";
2485
0
      if (!zone.readString(string) || input->tell() > endData) {
2486
0
        STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCChangeTrack: can not open some string\n"));
2487
0
        f << "###string";
2488
0
        ascFile.addDelimiter(input->tell(),'|');
2489
0
        ascFile.addPos(pos);
2490
0
        ascFile.addNote(f.str().c_str());
2491
0
        scRecord.closeContent("SCChangeTrack");
2492
0
        continue;
2493
0
      }
2494
0
      if (!string.empty())
2495
0
        f << "comment" << i << "=" << libstoff::getString(string).cstr() << ",";
2496
0
      if (s==0 && type!=8) {
2497
0
        f << "###type";
2498
0
        STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCChangeTrack:the type seems bad\n"));
2499
0
      }
2500
0
      switch (type) {
2501
0
      case 1:
2502
0
      case 2:
2503
0
      case 3:
2504
0
      case 9:
2505
0
        f << "insert[" << (type==1 ? "cols" : type==2 ? "rows" : type==9 ? "tab" : "reject") << "],";
2506
0
        break;
2507
0
      case 4:
2508
0
      case 5:
2509
0
      case 6: {
2510
0
        f << "delete[" << (type==4 ? "cols" : type==5 ? "rows" : "tab") << "],";
2511
0
        uint32_t pCutOff;
2512
0
        uint16_t cutOff, dx, dy;
2513
0
        *input >> pCutOff >> cutOff >> dx >> dy;
2514
0
        if (pCutOff) f << "pCutOff=" << pCutOff << ",";
2515
0
        if (cutOff) f << "cutOff=" << cutOff << ",";
2516
0
        f << "delta=" << dx << "x" << dy << ",";
2517
0
        break;
2518
0
      }
2519
0
      case 7:
2520
0
        f << "move,";
2521
0
        *input >> col >> row >> tab;
2522
0
        f << "fromCell=" << col << "x" << row << "[" << tab << "],";
2523
0
        break;
2524
0
      case 8: {
2525
0
        bool ok=true;
2526
0
        for (int j=0; j<2; ++j) {
2527
0
          if (!zone.readString(string) || input->tell() > endData) {
2528
0
            STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCChangeTrack: can not open some string\n"));
2529
0
            f << "###string";
2530
0
            ok=false;
2531
0
            break;
2532
0
          }
2533
0
          if (string.empty()) continue;
2534
0
          f << (j==0 ? "oldValue" : "newValue") << "=" << libstoff::getString(string).cstr() << ",";
2535
0
        }
2536
0
        if (!ok) break;
2537
0
        uint32_t oldContent, newContent;
2538
0
        *input >> oldContent >> newContent;
2539
0
        if (oldContent) f << "oldContent=" << oldContent << ",";
2540
0
        if (newContent) f << "newContent=" << newContent << ",";
2541
0
        StarObjectSpreadsheetInternal::ScMultiRecord scRecord2(zone);
2542
0
        if (!scRecord2.open()) {
2543
0
          STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCChangeTrack: can not find the cell action\n"));
2544
0
          f << "###cells";
2545
0
          break;
2546
0
        }
2547
0
        STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCChangeTrack: reading cell action is not implemented\n"));
2548
0
        f << "###cells,";
2549
        // fixme: call readSCData with only one cell
2550
0
        input->seek(zone.getRecordLastPosition(), librevenge::RVNG_SEEK_SET);
2551
0
        scRecord2.close("SCChangeTrack");
2552
0
        break;
2553
0
      }
2554
0
      default:
2555
0
        STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCChangeTrack:unknown type\n"));
2556
0
        f << "###type=" << int(type) << ",";
2557
0
        break;
2558
0
      }
2559
0
      scRecord.closeContent("SCChangeTrack");
2560
0
      ascFile.addPos(pos);
2561
0
      ascFile.addNote(f.str().c_str());
2562
0
    }
2563
0
    scRecord.close("SCChangeTrack");
2564
0
  }
2565
2566
0
  pos=input->tell();
2567
0
  f.str("");
2568
0
  f << "Entries(SCChangeTrack)[L]:";
2569
0
  StarObjectSpreadsheetInternal::ScMultiRecord scRecord(zone);
2570
0
  if (!scRecord.open()) {
2571
0
    STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCChangeTrack: can not find the action list\n"));
2572
0
    ascFile.addDelimiter(input->tell(),'|');
2573
0
    f << "###link";
2574
0
    input->seek(lastPos, librevenge::RVNG_SEEK_SET);
2575
0
    return true;
2576
0
  }
2577
0
  while (scRecord.openContent("SCChangeTrack")) {
2578
0
    pos=input->tell();
2579
0
    f.str("");
2580
0
    f << "Entries(SCChangeTrack)[L]:###";
2581
0
    static bool first=true;
2582
0
    if (first) {
2583
0
      STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCChangeTrack: reading the action links is not implemented\n"));
2584
0
      first=false;
2585
0
    }
2586
0
    ascFile.addPos(pos);
2587
0
    ascFile.addNote(f.str().c_str());
2588
0
    input->seek(scRecord.getContentLastPosition(), librevenge::RVNG_SEEK_SET);
2589
0
    scRecord.closeContent("SCChangeTrack");
2590
0
  }
2591
0
  ascFile.addPos(pos);
2592
0
  ascFile.addNote(f.str().c_str());
2593
2594
0
  if (input->tell()!=lastPos) {
2595
0
    STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCChangeTrack: find extra data\n"));
2596
0
    ascFile.addDelimiter(input->tell(),'|');
2597
0
    f << "###extra";
2598
0
    input->seek(lastPos, librevenge::RVNG_SEEK_SET);
2599
0
  }
2600
0
  ascFile.addPos(pos);
2601
0
  ascFile.addNote(f.str().c_str());
2602
0
  return true;
2603
2604
0
}
2605
2606
bool StarObjectSpreadsheet::readSCDBData(StarZone &zone, int /*version*/, long lastPos)
2607
57.6k
{
2608
57.6k
  STOFFInputStreamPtr input=zone.input();
2609
57.6k
  long pos=input->tell();
2610
2611
57.6k
  libstoff::DebugFile &ascFile=zone.ascii();
2612
57.6k
  libstoff::DebugStream f;
2613
57.6k
  f << "Entries(SCDBData)[" << zone.getRecordLevel() << "]:";
2614
  // sc_dbcolect.cxx ScDBData::Load
2615
57.6k
  std::vector<uint32_t> string;
2616
57.6k
  if (!zone.readString(string)) {
2617
270
    STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCDBData: can not read some text\n"));
2618
270
    f << "###name";
2619
270
    ascFile.addDelimiter(input->tell(),'|');
2620
270
    ascFile.addPos(pos);
2621
270
    ascFile.addNote(f.str().c_str());
2622
270
    return false;
2623
270
  }
2624
57.4k
  f << "name=" << libstoff::getString(string).cstr() << ",";
2625
57.4k
  uint16_t nTable, nStartCol, nStartRow, nEndCol, nEndRow;
2626
57.4k
  *input >> nTable >> nStartCol >> nStartRow >> nEndCol >> nEndRow;
2627
57.4k
  if (nTable) f << "table=" << nTable << ",";
2628
57.4k
  f << "dim=" << nStartCol << "x" << nStartRow << "<->" << nEndCol << "x" << nEndRow << ",";
2629
57.4k
  bool bByRow, bHasHeader, bSortCaseSens, bIncludePattern, bSortInplace;
2630
57.4k
  *input >> bByRow >> bHasHeader >> bSortCaseSens >> bIncludePattern >> bSortInplace;
2631
57.4k
  if (bByRow) f << "byRow,";
2632
57.4k
  if (bHasHeader) f << "hasHeader,";
2633
57.4k
  if (bSortCaseSens) f << "sortCaseSens,";
2634
57.4k
  if (bIncludePattern) f << "includePattern,";
2635
57.4k
  if (bSortInplace) f << "sortInPlace,";
2636
57.4k
  uint16_t nSortDestTab, nSortDestCol, nSortDestRow;
2637
57.4k
  *input >> nSortDestTab >> nSortDestCol >> nSortDestRow;
2638
57.4k
  f << "dest[sort]=" << nSortDestCol << "x" << nSortDestCol << "x" << nSortDestTab << ",";
2639
57.4k
  bool bQueryInplace, bQueryCaseSen, bQueryRegExp, bQueryDuplicate;
2640
57.4k
  *input >> bQueryInplace >> bQueryCaseSen >> bQueryRegExp >> bQueryDuplicate;
2641
57.4k
  if (bQueryInplace) f << "query[inPlace],";
2642
57.4k
  if (bQueryCaseSen) f << "query[caseSen],";
2643
57.4k
  if (bQueryRegExp) f << "query[regExp],";
2644
57.4k
  if (bQueryDuplicate) f << "query[duplicate],";
2645
57.4k
  uint16_t nQueryDestTab, nQueryDestCol, nQueryDestRow;
2646
57.4k
  *input >> nQueryDestTab >> nQueryDestCol >> nQueryDestRow;
2647
57.4k
  f << "dest[query]=" << nQueryDestCol << "x" << nQueryDestCol << "x" << nQueryDestTab << ",";
2648
57.4k
  bool bSubRemoveOnly, bSubReplace, bSubPagebreak, bSubCaseSens, bSubDoSort,
2649
57.4k
       bSubAscending, bSubIncludePattern, bSubUserDef;
2650
57.4k
  bool bDBImport, bDBNative;
2651
57.4k
  *input >> bSubRemoveOnly >> bSubReplace >> bSubPagebreak >> bSubCaseSens
2652
57.4k
         >> bSubDoSort >> bSubAscending >> bSubIncludePattern >> bSubUserDef
2653
57.4k
         >> bDBImport;
2654
57.4k
  if (bSubRemoveOnly) f << "subRemoveOnly,";
2655
57.4k
  if (bSubReplace) f << "subReplace,";
2656
57.4k
  if (bSubPagebreak) f << "subPagebreak,";
2657
57.4k
  if (bSubCaseSens) f << "subCaseSens,";
2658
57.4k
  if (bSubDoSort) f << "subDoSort,";
2659
57.4k
  if (bSubAscending) f << "subAscending,";
2660
57.4k
  if (bSubIncludePattern) f << "subIncludePattern,";
2661
57.4k
  if (bSubUserDef) f << "subUserDef,";
2662
57.4k
  if (bDBImport) f << "dbImport,";
2663
146k
  for (int i=0; i<2; ++i) {
2664
114k
    if (!zone.readString(string)) {
2665
25.4k
      STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCDBData: can not read some text\n"));
2666
25.4k
      f << "###name";
2667
25.4k
      ascFile.addDelimiter(input->tell(),'|');
2668
25.4k
      ascFile.addPos(pos);
2669
25.4k
      ascFile.addNote(f.str().c_str());
2670
25.4k
      return false;
2671
25.4k
    }
2672
89.0k
    if (!string.empty())
2673
31.3k
      f << (i==0 ? "dbName" : "dbStatement") << "=" << libstoff::getString(string).cstr() << ",";
2674
89.0k
  }
2675
31.9k
  *input >> bDBNative;
2676
31.9k
  if (bDBNative) f << "dbNative,";
2677
31.9k
  ascFile.addPos(pos);
2678
31.9k
  ascFile.addNote(f.str().c_str());
2679
31.9k
  pos=input->tell();
2680
31.9k
  f.str("");
2681
31.9k
  f << "SCDBData:";
2682
31.9k
  if (input->tell()+3*4>lastPos) {
2683
31.1k
    STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCDBData: can not read sort data\n"));
2684
31.1k
    f << "###name";
2685
31.1k
    ascFile.addPos(pos);
2686
31.1k
    ascFile.addNote(f.str().c_str());
2687
31.1k
    return false;
2688
31.1k
  }
2689
3.04k
  for (int i=0; i<3; ++i) {
2690
2.28k
    bool doSort, doAscend;
2691
2.28k
    uint16_t sortField;
2692
2.28k
    *input>>doSort>>sortField >> doAscend;
2693
2.28k
    if (doSort) f << "sort" << i << "=" << sortField << "[" << int(doAscend) << "],";
2694
2.28k
  }
2695
6.53k
  for (int i=0; i<8; ++i) {
2696
5.82k
    bool doQuery, queryByString;
2697
5.82k
    uint16_t queryField;
2698
5.82k
    uint8_t queryOp, queryConnect;
2699
5.82k
    double val;
2700
5.82k
    *input >> doQuery >> queryField >> queryOp >> queryByString;
2701
5.82k
    if (!zone.readString(string)||input->tell()>lastPos) {
2702
52
      STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCDBData: can not read some text\n"));
2703
52
      f << "###name";
2704
52
      ascFile.addDelimiter(input->tell(),'|');
2705
52
      ascFile.addPos(pos);
2706
52
      ascFile.addNote(f.str().c_str());
2707
52
      return false;
2708
52
    }
2709
5.77k
    *input>>val >> queryConnect;
2710
5.77k
    if (!doQuery) continue;
2711
16
    f << "query" << i << "=[";
2712
16
    f << libstoff::getString(string).cstr() << ",";
2713
16
    f << "field=" << queryField << ",";
2714
16
    f << "op=" << int(queryOp) << ",";
2715
16
    if (queryByString) f << "byString,";
2716
16
    if (!string.empty()) f << libstoff::getString(string).cstr() << ",";
2717
16
    if (val<0 || val>0) f << "val=" << val << ",";
2718
16
    f << "connect=" << int(queryConnect) << ",";
2719
16
    f << "],";
2720
16
  }
2721
2.78k
  for (int i=0; i<3; ++i) {
2722
2.11k
    bool doSubTotal;
2723
2.11k
    uint16_t field, count;
2724
2.11k
    *input >> doSubTotal >> field >> count;
2725
2.11k
    if (input->tell() + 3*long(count) > lastPos) {
2726
41
      STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCDBData: can not read some subTotal\n"));
2727
41
      f << "###subTotal";
2728
41
      ascFile.addDelimiter(input->tell(),'|');
2729
41
      ascFile.addPos(pos);
2730
41
      ascFile.addNote(f.str().c_str());
2731
41
      return false;
2732
41
    }
2733
2.07k
    if (!doSubTotal && !count) continue;
2734
42
    f << "subTotal" << i << "=[";
2735
42
    f << "field=" << field  << ",[";
2736
185
    for (int c=0; c<int(count); ++c)
2737
143
      f << input->readULong(2) << ":" << input->readULong(1) << ",";
2738
42
    f << "],";
2739
42
  }
2740
668
  if (input->tell()<lastPos)
2741
667
    f << "index=" << input->readULong(2) << ",";
2742
668
  if (input->tell()<lastPos)
2743
666
    f << "dbSelect=" << input->readULong(1) << ",";
2744
668
  if (input->tell()<lastPos)
2745
666
    f << "dbSQL=" << input->readULong(1) << ",";
2746
668
  if (input->tell()<lastPos) {
2747
665
    f << "subUserIndex=" << input->readULong(2) << ",";
2748
665
    f << "sortUserDef=" << input->readULong(1) << ",";
2749
665
    f << "sortUserIndex=" << input->readULong(2) << ",";
2750
665
  }
2751
668
  if (input->tell()<lastPos) {
2752
662
    f << "doSize=" << input->readULong(1) << ",";
2753
662
    f << "keepFmt=" << input->readULong(1) << ",";
2754
662
  }
2755
668
  if (input->tell()<lastPos)
2756
662
    f << "stripData=" << input->readULong(1) << ",";
2757
668
  if (input->tell()<lastPos)
2758
662
    f << "dbType=" << input->readULong(1) << ",";
2759
668
  if (input->tell()<lastPos) {
2760
1
    bool isAdvanced;
2761
1
    *input >> isAdvanced;
2762
1
    if (isAdvanced)
2763
0
      f << "advSource=" << std::hex << input->readULong(4) << "x" << input->readULong(4) << std::dec << ",";
2764
1
  }
2765
668
  if (input->tell()!=lastPos) {
2766
4
    STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCDBData: find extra data\n"));
2767
4
    ascFile.addDelimiter(input->tell(),'|');
2768
4
    f << "###extra";
2769
4
    input->seek(lastPos, librevenge::RVNG_SEEK_SET);
2770
4
  }
2771
668
  ascFile.addPos(pos);
2772
668
  ascFile.addNote(f.str().c_str());
2773
668
  return true;
2774
709
}
2775
2776
bool StarObjectSpreadsheet::readSCDBPivot(StarZone &zone, int version, long lastPos)
2777
99
{
2778
99
  STOFFInputStreamPtr input=zone.input();
2779
99
  long pos=input->tell();
2780
2781
99
  libstoff::DebugFile &ascFile=zone.ascii();
2782
99
  libstoff::DebugStream f;
2783
99
  f << "Entries(SCDBPivot)[" << zone.getRecordLevel() << "]:";
2784
  // sc_pivot.cxx ScPivot::Load
2785
99
  bool hasHeader;
2786
99
  *input >> hasHeader;
2787
99
  if (hasHeader) f << "hasHeader,";
2788
297
  for (int i=0; i<2; ++i) {
2789
198
    uint16_t col1, row1, col2, row2, table;
2790
198
    *input >> col1 >> row1 >> col2 >> row2 >> table;
2791
198
    f << (i==0 ? "src":"dest") << "="
2792
198
      << col1 << "x" << row1 << "<->" << col2 << "x" << row2 << "[" << table << "],";
2793
198
  }
2794
99
  for (int i=0; i<3; ++i) {
2795
99
    uint16_t nCount;
2796
99
    *input >> nCount;
2797
99
    if (input->tell()+6*int(nCount) >lastPos) {
2798
99
      STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCDBData: can not read some fields\n"));
2799
99
      f << "###fields";
2800
99
      ascFile.addPos(pos);
2801
99
      ascFile.addNote(f.str().c_str());
2802
99
      return false;
2803
99
    }
2804
2805
0
    if (!nCount) continue;
2806
0
    f << (i==0 ? "col" : i==1 ? "row" : "data") << "=[";
2807
0
    for (int c=0; c<int(nCount); ++c) {
2808
0
      if (version >= 7) {
2809
0
        uint8_t unkn;
2810
0
        *input>>unkn;
2811
0
        if (unkn&0xf) input->seek((unkn&0xf), librevenge::RVNG_SEEK_CUR);
2812
0
      }
2813
0
      f << "[";
2814
0
      f << "col=" << input->readLong(2) << ",";
2815
0
      f << "mask=" << input->readULong(2) << ",";
2816
0
      f << "count=" << input->readULong(2) << ",";
2817
0
      f << "],";
2818
0
    }
2819
0
    f << "],";
2820
0
  }
2821
0
  ascFile.addPos(pos);
2822
0
  ascFile.addNote(f.str().c_str());
2823
0
  pos=input->tell();
2824
0
  f << "SCDBPivot:";
2825
0
  if (!readSCQueryParam(zone, version, lastPos)) {
2826
0
    f << "###query";
2827
0
    ascFile.addPos(pos);
2828
0
    ascFile.addNote(f.str().c_str());
2829
0
    return false;
2830
0
  }
2831
0
  pos=input->tell();
2832
0
  bool bIgnoreEmpty, bDectectCat;
2833
0
  *input >> bIgnoreEmpty >> bDectectCat;
2834
0
  if (bIgnoreEmpty) f << "ignore[empty],";
2835
0
  if (bDectectCat) f << "detect[cat],";
2836
0
  if (input->tell()<lastPos) {
2837
0
    bool makeTotalCol, makeTotalRow;
2838
0
    *input >> makeTotalCol >> makeTotalRow;
2839
0
    if (makeTotalCol) f << "make[totalCol],";
2840
0
    if (makeTotalRow) f << "make[totalRow],";
2841
0
  }
2842
0
  if (input->tell()<lastPos) {
2843
0
    std::vector<uint32_t> string;
2844
0
    for (int i=0; i<2; ++i) {
2845
0
      if (!zone.readString(string)||input->tell()>lastPos) {
2846
0
        STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCDBData: can not read some text\n"));
2847
0
        f << "###string";
2848
0
        ascFile.addPos(pos);
2849
0
        ascFile.addNote(f.str().c_str());
2850
0
        return false;
2851
0
      }
2852
0
      if (!string.empty())
2853
0
        f << (i==0 ? "name": "tag") << "=" << libstoff::getString(string).cstr() << ",";
2854
0
    }
2855
0
    uint16_t count;
2856
0
    *input >> count;
2857
0
    for (int i=0; i<int(count); ++i) {
2858
0
      if (!zone.readString(string)||input->tell()>lastPos) {
2859
0
        STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCDBData: can not read some text\n"));
2860
0
        f << "###string";
2861
0
        ascFile.addPos(pos);
2862
0
        ascFile.addNote(f.str().c_str());
2863
0
        return false;
2864
0
      }
2865
0
      if (!string.empty())
2866
0
        f << "colName" << i << "=" << libstoff::getString(string).cstr() << ",";
2867
0
    }
2868
0
  }
2869
0
  if (input->tell()!=lastPos) {
2870
0
    STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCDBPivot: find extra data\n"));
2871
0
    ascFile.addDelimiter(input->tell(),'|');
2872
0
    f << "###extra";
2873
0
    input->seek(lastPos, librevenge::RVNG_SEEK_SET);
2874
0
  }
2875
0
  ascFile.addPos(pos);
2876
0
  ascFile.addNote(f.str().c_str());
2877
0
  return true;
2878
0
}
2879
2880
bool StarObjectSpreadsheet::readSCMatrix(StarZone &zone, int /*version*/, long lastPos)
2881
21
{
2882
21
  STOFFInputStreamPtr input=zone.input();
2883
21
  long pos=input->tell();
2884
21
  libstoff::DebugFile &ascFile=zone.ascii();
2885
21
  libstoff::DebugStream f;
2886
21
  f << "Entries(SCMatrix)[" << zone.getRecordLevel() << "]:";
2887
  // sc_scmatrix.cxx ScMatrix::ScMatrix
2888
21
  uint16_t nCol, nRow;
2889
21
  *input >> nCol >> nRow;
2890
21
  f << "dim=" << nCol << "x" << nRow << ",";
2891
21
  int nCell=int(nCol)*int(nRow);
2892
21
  bool ok=true;
2893
21
  f << "values=[";
2894
43
  for (int i=0; i<nCell; ++i) {
2895
38
    uint8_t type;
2896
38
    *input>>type;
2897
38
    if ((i%nCol)==0) f << "[";
2898
38
    switch (type) {
2899
22
    case 0:
2900
22
      f << "_,";
2901
22
      break;
2902
2
    case 1: {
2903
2
      double val;
2904
2
      *input>>val;
2905
2
      f << val << ",";
2906
2
      break;
2907
0
    }
2908
7
    case 2: {
2909
7
      std::vector<uint32_t> string;
2910
7
      if (!zone.readString(string) || input->tell()>lastPos) {
2911
4
        STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCMatrix: can not read a string\n"));
2912
4
        f << "###string";
2913
4
        ok=false;
2914
4
        break;
2915
4
      }
2916
3
      f << libstoff::getString(string).cstr() << ",";
2917
3
      break;
2918
7
    }
2919
7
    default:
2920
7
      STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCMatrix: find unexpected type\n"));
2921
7
      f << "###type=" << int(type) << ",";
2922
7
      ok=false;
2923
7
      break;
2924
38
    }
2925
38
    if (!ok) break;
2926
27
    if (input->tell()>lastPos) {
2927
5
      STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCMatrix: the zone is too short\n"));
2928
5
      f << "###short,";
2929
5
      ok=false;
2930
5
      break;
2931
5
    }
2932
22
    if ((i%nCol)==0) f << "],";
2933
22
  }
2934
21
  f << "],";
2935
21
  ascFile.addPos(pos);
2936
21
  ascFile.addNote(f.str().c_str());
2937
21
  return ok && input->tell()<=lastPos;
2938
21
}
2939
bool StarObjectSpreadsheet::readSCQueryParam(StarZone &zone, int /*version*/, long lastPos)
2940
0
{
2941
0
  STOFFInputStreamPtr input=zone.input();
2942
0
  long pos=input->tell();
2943
2944
0
  if (!zone.openSCRecord()) return false;
2945
0
  libstoff::DebugFile &ascFile=zone.ascii();
2946
0
  libstoff::DebugStream f;
2947
0
  f << "Entries(SCQueryParam)[" << zone.getRecordLevel() << "]:";
2948
  // sc_global2.cxx ScQueryParam::Load
2949
0
  uint16_t nCol1, nRow1, nCol2, nRow2, nDestTab, nDestCol, nDestRow;
2950
0
  bool bHasHeader, bInplace, bCaseSens, bRegExp, bDuplicate, bByRow;
2951
0
  *input >> nCol1 >> nRow1 >> nCol2 >> nRow2 >> nDestTab >> nDestCol >> nDestRow;
2952
0
  f << "dim=" << nCol1 << "x" << nRow1 << "<->" << nCol2 << "x" << nRow2 << ",";
2953
0
  f << "dest=" << nDestCol << "x" << nDestRow << "x" << nDestTab << ",";
2954
0
  *input >> bHasHeader >> bInplace >> bCaseSens >> bRegExp >> bDuplicate >> bByRow;
2955
0
  if (bHasHeader) f << "hasHeader,";
2956
0
  if (bInplace) f << "inPlace,";
2957
0
  if (bCaseSens) f << "caseSens,";
2958
0
  if (bRegExp) f << "regExp,";
2959
0
  if (bDuplicate) f << "duplicate,";
2960
0
  if (bByRow) f << "byRow,";
2961
0
  std::vector<uint32_t> string;
2962
0
  for (int i=0; i<8; ++i) {
2963
0
    bool doQuery, queryByString;
2964
0
    uint8_t op, connect;
2965
0
    uint16_t nField;
2966
0
    double val;
2967
0
    *input >> doQuery >> queryByString >> op >> connect >> nField >> val;
2968
0
    if (!zone.readString(string)||input->tell()>lastPos) {
2969
0
      STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCDBData: can not read some text\n"));
2970
0
      f << "###string";
2971
0
      ascFile.addPos(pos);
2972
0
      ascFile.addNote(f.str().c_str());
2973
0
      zone.closeSCRecord("SCQueryParam");
2974
0
      return false;
2975
0
    }
2976
0
    if (!doQuery) continue;
2977
0
    f << "query" << i << "=[";
2978
0
    if (queryByString) f << "byString,";
2979
0
    f << "op=" << int(op) << ",";
2980
0
    f << "connect=" << int(connect) << ",";
2981
0
    f << "field=" << nField << ",";
2982
0
    f << "val=" << val << ",";
2983
0
    if (!string.empty()) f << libstoff::getString(string).cstr() << ",";
2984
0
    f << "],";
2985
0
  }
2986
0
  zone.closeSCRecord("SCQueryParam");
2987
0
  ascFile.addPos(pos);
2988
0
  ascFile.addNote(f.str().c_str());
2989
0
  return true;
2990
0
}
2991
2992
bool StarObjectSpreadsheet::readSCOutlineArray(StarZone &zone)
2993
149
{
2994
149
  STOFFInputStreamPtr input=zone.input();
2995
149
  long pos=input->tell();
2996
2997
149
  StarObjectSpreadsheetInternal::ScMultiRecord scRecord(zone);
2998
149
  if (!scRecord.open()) {
2999
149
    input->seek(pos,librevenge::RVNG_SEEK_SET);
3000
149
    return false;
3001
149
  }
3002
0
  libstoff::DebugFile &ascFile=zone.ascii();
3003
0
  libstoff::DebugStream f;
3004
0
  f << "Entries(SCOutlineArray)[" << zone.getRecordLevel() << "]:";
3005
0
  auto depth=int(input->readULong(2));
3006
0
  f << "depth=" << depth << ",";
3007
0
  ascFile.addPos(pos);
3008
0
  ascFile.addNote(f.str().c_str());
3009
3010
0
  for (int lev=0; lev<depth; ++lev) {
3011
0
    pos=input->tell();
3012
0
    f.str("");
3013
0
    f << "SCOutlineArray-" << lev << ",";
3014
0
    if (pos>zone.getRecordLastPosition()) {
3015
0
      f << "###";
3016
0
      STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCOutlineArray:can not find some content\n"));
3017
0
      ascFile.addPos(pos);
3018
0
      ascFile.addNote(f.str().c_str());
3019
0
      scRecord.close("SCOutlineArray");
3020
0
      return true;
3021
0
    }
3022
0
    auto count=int(input->readULong(2));
3023
0
    f << "entries=[";
3024
0
    for (int i=0; i<count; ++i) {
3025
0
      if (!scRecord.openContent("SCOutlineArray")) {
3026
0
        f << "###";
3027
0
        STOFF_DEBUG_MSG(("StarObjectSpreadsheet::readSCOutlineArray:can not find some content(II)\n"));
3028
0
        ascFile.addPos(pos);
3029
0
        ascFile.addNote(f.str().c_str());
3030
0
        scRecord.close("SCOutlineArray");
3031
0
        return true;
3032
0
      }
3033
0
      f << "[start=" << input->readULong(2) << ",sz=" << input->readULong(2) << ",";
3034
0
      bool hidden, visible;
3035
0
      *input >> hidden >> visible;
3036
0
      if (hidden) f << "hidden,";
3037
0
      if (visible) f << "visible,";
3038
0
      f << "],";
3039
0
      scRecord.closeContent("SCOutlineArray");
3040
0
    }
3041
0
    f << "],";
3042
0
    ascFile.addPos(pos);
3043
0
    ascFile.addNote(f.str().c_str());
3044
0
  }
3045
0
  scRecord.close("SCOutlineArray");
3046
0
  return true;
3047
0
}
3048
3049
// vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: