Coverage Report

Created: 2026-07-20 07:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libstaroffice/src/lib/StarObjectModel.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 "STOFFFrameStyle.hxx"
44
#include "STOFFGraphicListener.hxx"
45
#include "STOFFListener.hxx"
46
#include "STOFFOLEParser.hxx"
47
#include "STOFFPageSpan.hxx"
48
49
#include "StarAttribute.hxx"
50
#include "StarItemPool.hxx"
51
#include "StarObject.hxx"
52
#include "StarObjectSmallGraphic.hxx"
53
#include "StarState.hxx"
54
#include "StarZone.hxx"
55
56
#include "StarObjectModel.hxx"
57
58
/** Internal: the structures of a StarObjectModel */
59
namespace StarObjectModelInternal
60
{
61
//! small function used to convert a list of uint8_t to a bool vector
62
static bool convertUint8ListToBoolList(std::vector<int> const &orig, std::vector<bool> &res)
63
16.3k
{
64
16.3k
  size_t n=orig.size();
65
16.3k
  res.resize(n*8);
66
540k
  for (size_t i=0, j=0; i<n; ++i) {
67
524k
    int val=orig[i];
68
4.71M
    for (int k=0, depl=0x80; k<8; depl>>=1, ++k)
69
4.19M
      res[j++]=(val&depl);
70
524k
  }
71
16.3k
  return true;
72
16.3k
}
73
////////////////////////////////////////
74
//! Internal: class used to store a layer and its data
75
class Layer
76
{
77
public:
78
  //! constructor
79
  Layer()
80
203k
    : m_name("")
81
203k
    , m_id(0)
82
203k
    , m_type(0)
83
203k
  {
84
203k
  }
85
  //! operator<<
86
  friend std::ostream &operator<<(std::ostream &o, Layer const &layer)
87
0
  {
88
0
    o << "id=" << layer.m_id << ",";
89
0
    if (!layer.m_name.empty()) o << layer.m_name.cstr() << ",";
90
0
    if (layer.m_type==0) o << "user,";
91
0
    return o;
92
0
  }
93
  //! the layer name
94
  librevenge::RVNGString m_name;
95
  //! the layer id
96
  int m_id;
97
  //! the layer type
98
  int m_type;
99
};
100
////////////////////////////////////////
101
//! Internal: class used to store a layer set and its data
102
class LayerSet
103
{
104
public:
105
  //! constructor
106
  LayerSet()
107
58.1k
    : m_name("")
108
58.1k
    , m_memberList()
109
58.1k
    , m_excludeList()
110
58.1k
  {
111
58.1k
  }
112
  //! operator<<
113
  friend std::ostream &operator<<(std::ostream &o, LayerSet const &layer)
114
0
  {
115
0
    if (!layer.m_name.empty()) o << layer.m_name.cstr() << ",";
116
0
    o << "members=[";
117
0
    for (size_t i=0; i<layer.m_memberList.size(); ++i) {
118
0
      if (layer.m_memberList[i]) o << i << ",";
119
0
    }
120
0
    o << "],";
121
0
    o << "excludes=[";
122
0
    for (size_t i=0; i<layer.m_excludeList.size(); ++i) {
123
0
      if (layer.m_excludeList[i]) o << i << ",";
124
0
    }
125
0
    o << "],";
126
0
    return o;
127
0
  }
128
  //! the layer name
129
  librevenge::RVNGString m_name;
130
  //! the list of member
131
  std::vector<bool> m_memberList;
132
  //! the list of exclude
133
  std::vector<bool> m_excludeList;
134
};
135
136
////////////////////////////////////////
137
//! Internal: class used to store a page and its data
138
class Page
139
{
140
public:
141
  ////////////////////////////////////////
142
  //! Internal: class used to store a page descriptor
143
  struct Descriptor {
144
    //! constructor
145
    Descriptor()
146
14.7k
      : m_masterId(1)
147
14.7k
      , m_layerList()
148
14.7k
    {
149
14.7k
    }
150
    //! operator<<
151
    friend std::ostream &operator<<(std::ostream &o, Descriptor const &desc)
152
0
    {
153
0
      o << "id[master]=" << desc.m_masterId << ",";
154
0
      o << "inVisLayer=[";
155
0
      for (size_t i=0; i<desc.m_layerList.size(); ++i) {
156
0
        if (!desc.m_layerList[i])
157
0
          o << i << ",";
158
0
      }
159
0
      o << "],";
160
0
      return o;
161
0
    }
162
    //! the page number
163
    int m_masterId;
164
    //! a list of layer
165
    std::vector<bool> m_layerList;
166
  };
167
  //! constructor
168
  Page()
169
55.9k
    : m_masterPage(false)
170
55.9k
    , m_name("")
171
55.9k
    , m_size(0,0)
172
55.9k
    , m_masterPageDescList()
173
55.9k
    , m_layer()
174
55.9k
    , m_layerSet()
175
55.9k
    , m_objectList()
176
55.9k
    , m_background()
177
55.9k
  {
178
223k
    for (int &border : m_borders) border=0;
179
55.9k
  }
180
  //! returns the master page id
181
  int getMasterPageId() const
182
17.1k
  {
183
17.1k
    if (m_masterPage || m_masterPageDescList.empty()) return -1;
184
14.4k
    return m_masterPageDescList[0].m_masterId;
185
17.1k
  }
186
  //! update pagespan properties
187
  void updatePageSpan(STOFFPageSpan &page, double relUnit) const
188
14.0k
  {
189
14.0k
    if (m_size[0]>0 && m_size[0]!=0x7fffffff)
190
13.4k
      page.m_propertiesList[0].insert("fo:page-width", relUnit*m_size[0], librevenge::RVNG_POINT);
191
14.0k
    if (m_size[1]>0 && m_size[1]!=0x7fffffff)
192
13.2k
      page.m_propertiesList[0].insert("fo:page-height", relUnit*m_size[1], librevenge::RVNG_POINT);
193
70.1k
    for (int i=0; i<4; ++i) {
194
56.0k
      if (m_borders[i]<0 || m_borders[i]==0x7fffffff) continue;
195
53.7k
      char const *wh[]= {"left", "top", "right", "bottom"};
196
53.7k
      page.m_propertiesList[0].insert((std::string("fo:margin-")+wh[i]).c_str(),
197
53.7k
                                      relUnit*m_borders[i], librevenge::RVNG_POINT);
198
53.7k
    }
199
14.0k
    if (m_background) {
200
1
      STOFF_DEBUG_MSG(("StarObjectModelInternal::Page::updatePageSpan: sorry sending background object is not implemented\n"));
201
1
    }
202
14.0k
  }
203
  //! operator<<
204
  friend std::ostream &operator<<(std::ostream &o, Page const &page)
205
0
  {
206
0
    if (page.m_masterPage) o << "master,";
207
0
    if (!page.m_name.empty()) o << "name=" << page.m_name.cstr() << ",";
208
0
    o << "sz=" << page.m_size << ",";
209
0
    o << "borders=[";
210
0
    for (int border : page.m_borders) o << border << ",";
211
0
    o << "],";
212
0
    if (!page.m_masterPageDescList.empty()) {
213
0
      o << "desc=[";
214
0
      for (auto const &desc : page.m_masterPageDescList)
215
0
        o << "[" << desc << "],";
216
0
      o << "],";
217
0
    }
218
0
    o << "layer=[" << page.m_layer << "],";
219
0
    o << "layerSet=[" << page.m_layerSet << "],";
220
0
    if (page.m_background) o << "hasBackground,";
221
0
#if 1
222
0
    for (auto &obj : page.m_objectList) {
223
0
      if (obj)
224
0
        o << "\n\t\t" << *obj;
225
0
    }
226
0
    o << "\n";
227
#else
228
    o << "num[object]=" << page.m_objectList.size() << ",";
229
#endif
230
0
    return o;
231
0
  }
232
  //! a flag to know if the page is a master page
233
  bool m_masterPage;
234
  //! the page name
235
  librevenge::RVNGString m_name;
236
  //! the page size
237
  STOFFVec2i m_size;
238
  //! the border size: left, up, right, bottom
239
  int m_borders[4];
240
  //! the list of master page descriptor
241
  std::vector<Descriptor> m_masterPageDescList;
242
  //! the layer
243
  Layer m_layer;
244
  //! the layer set
245
  LayerSet m_layerSet;
246
  //! the list of object
247
  std::vector<std::shared_ptr<StarObjectSmallGraphic> > m_objectList;
248
  //! the background object
249
  std::shared_ptr<StarObjectSmallGraphic> m_background;
250
};
251
252
////////////////////////////////////////
253
//! Internal: the state of a StarObjectModel
254
struct State {
255
  //! constructor
256
  State()
257
49.6k
    : m_previewMasterPage(-1)
258
49.6k
    , m_pageList()
259
49.6k
    , m_masterPageList()
260
49.6k
    , m_idToLayerMap()
261
49.6k
    , m_layerSetList()
262
49.6k
    , m_pageToSendList()
263
49.6k
    , m_masterPageToSendSet()
264
49.6k
    , m_idToObjectMap()
265
49.6k
  {
266
49.6k
  }
267
  //! small operator<< to print the content of the state
268
  friend std::ostream &operator<<(std::ostream &o, State const &state)
269
0
  {
270
0
    if (state.m_previewMasterPage>=0)
271
0
      o << "prev[masterPage]=" << state.m_previewMasterPage << ",";
272
0
    if (!state.m_pageList.empty()) {
273
0
      o << "pages=[\n";
274
0
      for (auto &page : state.m_pageList) {
275
0
        if (!page)
276
0
          continue;
277
0
        o << "\t" << *page << "\n";
278
0
      }
279
0
      o << "]\n";
280
0
    }
281
0
    if (!state.m_masterPageList.empty()) {
282
0
      o << "masterPages=[\n";
283
0
      for (auto &page : state.m_masterPageList) {
284
0
        if (!page)
285
0
          continue;
286
0
        o << "\t" << *page << "\n";
287
0
      }
288
0
      o << "]\n";
289
0
    }
290
0
    if (!state.m_idToLayerMap.empty()) {
291
0
      o << "layers=[";
292
0
      for (auto it : state.m_idToLayerMap)
293
0
        o << "[" << it.second << "],";
294
0
      o << "]\n";
295
0
    }
296
0
    if (!state.m_layerSetList.empty()) {
297
0
      o << "layerSets=[\n";
298
0
      for (auto const &layer : state.m_layerSetList)
299
0
        o << "\t" << layer << "\n";
300
0
      o << "]\n";
301
0
    }
302
0
    return o;
303
0
  }
304
305
  //! the default master page: -1 means not found, in general 1 in StarDrawDocument
306
  int m_previewMasterPage;
307
  /*
308
    in general: page0(master0), nothing
309
    after by pair:
310
       page 2*i+1(master 2*k+1): page content
311
       page 2*i+2(master 2*k+2): a page graphic+a text zone(double click to add note)
312
   */
313
  //! list of pages
314
  std::vector<std::shared_ptr<Page> > m_pageList;
315
  /*
316
    in general: master0 contains 4 small box associated with a page graphic 1,3,5,7
317
    after by pair:
318
        master 2*i+1: the content of the master page
319
        master 2*i+2: a title text+text: maybe default text
320
   */
321
  //! list of master pages
322
  std::vector<std::shared_ptr<Page> > m_masterPageList;
323
  //! a map layerId to layer
324
  std::map<int, Layer> m_idToLayerMap;
325
  //! the list of layer set
326
  std::vector<LayerSet> m_layerSetList;
327
  //! the list of page to send
328
  std::vector<int> m_pageToSendList;
329
  //! the list of master page to send
330
  std::set<int> m_masterPageToSendSet;
331
  //! a map objectId to object
332
  std::map<int, std::shared_ptr<StarObjectSmallGraphic> > m_idToObjectMap;
333
334
};
335
336
}
337
338
////////////////////////////////////////////////////////////
339
// constructor/destructor, ...
340
////////////////////////////////////////////////////////////
341
StarObjectModel::StarObjectModel(StarObject const &orig, bool duplicateState)
342
49.6k
  : StarObject(orig, duplicateState)
343
49.6k
  , m_modelState(new StarObjectModelInternal::State)
344
49.6k
{
345
49.6k
}
346
347
StarObjectModel::~StarObjectModel()
348
49.6k
{
349
49.6k
}
350
351
std::ostream &operator<<(std::ostream &o, StarObjectModel const &model)
352
0
{
353
0
  o << *model.m_modelState;
354
0
  return o;
355
0
}
356
357
////////////////////////////////////////////////////////////
358
// send data
359
////////////////////////////////////////////////////////////
360
bool StarObjectModel::updatePageSpans(std::vector<STOFFPageSpan> &pageSpan, int &number, bool usePage0) const
361
13.2k
{
362
13.2k
  m_modelState->m_pageToSendList.clear();
363
13.2k
  m_modelState->m_masterPageToSendSet.clear();
364
365
13.2k
  auto pool=const_cast<StarObjectModel *>(this)->findItemPool(StarItemPool::T_XOutdevPool, false);
366
13.2k
  double const relUnit=pool ? pool->getRelativeUnit() : 0.028346457;
367
13.2k
  pageSpan.clear();
368
13.2k
  if (usePage0) {
369
2.45k
    if (m_modelState->m_pageList.empty() || !m_modelState->m_pageList[0])
370
339
      return false;
371
2.11k
    STOFFPageSpan ps;
372
2.11k
    m_modelState->m_pageList[0]->updatePageSpan(ps, relUnit);
373
2.11k
    pageSpan.push_back(ps);
374
2.11k
    return true;
375
2.45k
  }
376
10.8k
  auto numMasterPage=int(m_modelState->m_masterPageList.size());
377
27.9k
  for (size_t i=0; i<m_modelState->m_pageList.size(); ++i) {
378
17.1k
    if (!m_modelState->m_pageList[i])
379
0
      continue;
380
17.1k
    auto const &page=*m_modelState->m_pageList[i];
381
17.1k
    int id=page.getMasterPageId();
382
17.1k
    if (id<=0 || (id&1)!=1) continue;
383
8.42k
    m_modelState->m_pageToSendList.push_back(int(i));
384
8.42k
    STOFFPageSpan ps;
385
8.42k
    page.updatePageSpan(ps, relUnit);
386
8.42k
    if (id<numMasterPage && m_modelState->m_masterPageList[size_t(id)]) {
387
4.60k
      m_modelState->m_masterPageToSendSet.insert(id);
388
4.60k
      librevenge::RVNGString masterName;
389
4.60k
      masterName.sprintf("Master%d", id);
390
4.60k
      ps.m_propertiesList[0].insert("librevenge:master-page-name", masterName);
391
4.60k
    }
392
8.42k
    pageSpan.push_back(ps);
393
8.42k
  }
394
10.8k
  number=int(m_modelState->m_pageToSendList.size());
395
10.8k
  return number!=0;
396
13.2k
}
397
398
void StarObjectModel::updateObjectIds(std::set<long> &unusedId)
399
3
{
400
3
  if (m_modelState->m_pageList.empty() || !m_modelState->m_pageList[0])
401
0
    return;
402
3
  int actId=0;
403
6
  for (auto &obj : m_modelState->m_pageList[0]->m_objectList) {
404
6
    while (unusedId.find(long(actId))!=unusedId.end())
405
0
      ++actId;
406
6
    if (obj)
407
6
      m_modelState->m_idToObjectMap[actId]=obj;
408
6
    ++actId;
409
6
  }
410
3
}
411
412
bool StarObjectModel::sendObject(int id, STOFFListenerPtr listener, StarState const &state)
413
6
{
414
6
  auto it=m_modelState->m_idToObjectMap.find(id);
415
6
  if (it==m_modelState->m_idToObjectMap.end() || !it->second) {
416
0
    STOFF_DEBUG_MSG(("StarObjectModel::sendObject: can not find object %d\n", id));
417
0
    return false;
418
0
  }
419
6
  return it->second->send(listener, state.m_frame, *this);
420
6
}
421
422
bool StarObjectModel::sendPages(STOFFListenerPtr listener)
423
10.7k
{
424
10.7k
  if (!listener) {
425
0
    STOFF_DEBUG_MSG(("StarObjectModel::sendPages: can not find the listener\n"));
426
0
    return false;
427
0
  }
428
10.7k
  bool first=true;
429
10.7k
  for (auto &page : m_modelState->m_pageToSendList) {
430
8.41k
    if (!first)
431
1.60k
      listener->insertBreak(STOFFListener::PageBreak);
432
6.80k
    else
433
6.80k
      first=false;
434
8.41k
    sendPage(page, listener, false);
435
8.41k
  }
436
10.7k
  return true;
437
10.7k
}
438
439
bool StarObjectModel::sendMasterPages(STOFFGraphicListenerPtr listener)
440
10.2k
{
441
10.2k
  if (!listener) {
442
0
    STOFF_DEBUG_MSG(("StarObjectModel::sendMasterPages: can not find the listener\n"));
443
0
    return false;
444
0
  }
445
10.2k
  auto pool=const_cast<StarObjectModel *>(this)->findItemPool(StarItemPool::T_XOutdevPool, false);
446
10.2k
  double const relUnit=pool ? pool->getRelativeUnit() : 0.028346457;
447
10.2k
  auto numMasters=int(m_modelState->m_masterPageList.size());
448
10.2k
  for (auto id : m_modelState->m_masterPageToSendSet) {
449
3.48k
    if (id<0 || id>=numMasters || !m_modelState->m_masterPageList[size_t(id)]) {
450
0
      STOFF_DEBUG_MSG(("StarObjectModel::sendMasterPages: can not find master page %d\n", id));
451
0
      continue;
452
0
    }
453
3.48k
    auto const &page=*m_modelState->m_masterPageList[size_t(id)];
454
3.48k
    STOFFPageSpan ps;
455
3.48k
    page.updatePageSpan(ps, relUnit);
456
3.48k
    librevenge::RVNGString masterName;
457
3.48k
    masterName.sprintf("Master%d", id);
458
3.48k
    ps.m_propertiesList[0].insert("librevenge:master-page-name", masterName);
459
3.48k
    listener->openMasterPage(ps);
460
3.48k
    sendPage(id, listener, true);
461
3.48k
    listener->closeMasterPage();
462
3.48k
  }
463
10.2k
  return true;
464
10.2k
}
465
466
bool StarObjectModel::sendPage(int pageId, STOFFListenerPtr listener, bool masterPage)
467
25.1k
{
468
25.1k
  if (!listener) {
469
0
    STOFF_DEBUG_MSG(("StarObjectModel::sendPage: can not find the listener\n"));
470
0
    return false;
471
0
  }
472
25.1k
  std::vector<std::shared_ptr<StarObjectModelInternal::Page> > const &pageList=
473
25.1k
    masterPage ? m_modelState->m_masterPageList : m_modelState->m_pageList;
474
25.1k
  if (pageId<0) {
475
0
    STOFF_DEBUG_MSG(("StarObjectModel::sendPage: can not find page %d\n", pageId));
476
0
    return false;
477
0
  }
478
25.1k
  if (pageId>=int(pageList.size()) || !pageList[size_t(pageId)])
479
1.24k
    return false;
480
23.8k
  StarObjectModelInternal::Page &page=*pageList[size_t(pageId)];
481
23.8k
  STOFFFrameStyle frame;
482
23.8k
  frame.m_position.m_anchorTo=STOFFPosition::Page;
483
23.8k
  if (!masterPage) frame.m_position.m_propertyList.insert("text:anchor-page-number", pageId+1);
484
76.9k
  for (auto pag : page.m_objectList) {
485
76.9k
    if (pag)
486
76.9k
      pag->send(listener, frame, *this, masterPage);
487
76.9k
  }
488
23.8k
  return true;
489
25.1k
}
490
491
////////////////////////////////////////////////////////////
492
// the parser
493
////////////////////////////////////////////////////////////
494
bool StarObjectModel::read(StarZone &zone)
495
49.6k
{
496
49.6k
  STOFFInputStreamPtr input=zone.input();
497
  // first check magic
498
49.6k
  std::string magic("");
499
49.6k
  long pos=input->tell();
500
248k
  for (int i=0; i<4; ++i) magic+=char(input->readULong(1));
501
49.6k
  input->seek(pos, librevenge::RVNG_SEEK_SET);
502
49.6k
  if (magic!="DrMd") return false;
503
504
17.5k
  libstoff::DebugFile &ascFile=zone.ascii();
505
17.5k
  libstoff::DebugStream f;
506
17.5k
  f << "Entries(SdrModel)[" << zone.getRecordLevel() << "]:";
507
  // svdmodel.cxx operator>>(..., SdrModel &)
508
17.5k
  if (!zone.openSDRHeader(magic)) {
509
323
    input->seek(pos, librevenge::RVNG_SEEK_SET);
510
323
    STOFF_DEBUG_MSG(("StarObjectModel::read: can not open the SDR Header\n"));
511
323
    f << "###";
512
323
    ascFile.addPos(pos);
513
323
    ascFile.addNote(f.str().c_str());
514
323
    return false;
515
323
  }
516
17.2k
  int version=zone.getHeaderVersion();
517
17.2k
  f << magic << ",nVers=" << version << ",";
518
519
17.2k
  if (magic!="DrMd" || version>17) {
520
33
    STOFF_DEBUG_MSG(("StarObjectModel::read: unexpected magic data\n"));
521
33
    f << "###";
522
33
    ascFile.addPos(pos);
523
33
    ascFile.addNote(f.str().c_str());
524
33
    return false;
525
33
  }
526
17.1k
  ascFile.addPos(pos);
527
17.1k
  ascFile.addNote(f.str().c_str());
528
17.1k
  pos=input->tell();
529
530
17.1k
  f.str("");
531
17.1k
  f << "SdrModelA[" << zone.getRecordLevel() << "]:";
532
  // SdrModel::ReadData
533
17.1k
  if (!zone.openRecord()) { // SdrModelA1
534
255
    STOFF_DEBUG_MSG(("StarObjectModel::read: can not open downCompat\n"));
535
255
    f << "###";
536
255
    ascFile.addPos(pos);
537
255
    ascFile.addNote(f.str().c_str());
538
255
    zone.closeSDRHeader("SdrModel");
539
255
    return true;
540
255
  }
541
542
16.9k
  ascFile.addPos(pos);
543
16.9k
  ascFile.addNote(f.str().c_str());
544
16.9k
  pos=input->tell();
545
16.9k
  f.str("");
546
16.9k
  f << "SdrModelA[" << zone.getRecordLevel() << "]:";
547
16.9k
  bool ok=true;
548
16.9k
  if (version>=11) {
549
16.5k
    magic="";
550
82.6k
    for (int i=0; i<4; ++i) magic+=char(input->readULong(1));
551
16.5k
    f << "joeM";
552
16.5k
    if (magic!="JoeM" || !zone.openRecord()) { // SdrModelA2
553
86
      STOFF_DEBUG_MSG(("StarObjectModel::read: unexpected magic2 data\n"));
554
86
      f << "###magic" << magic;
555
86
      ascFile.addPos(pos);
556
86
      ascFile.addNote(f.str().c_str());
557
86
      zone.closeRecord("SdrModelA1");
558
86
      zone.closeSDRHeader("SdrModel");
559
86
      return true;
560
86
    }
561
16.4k
    ascFile.addPos(pos);
562
16.4k
    ascFile.addNote(f.str().c_str());
563
564
16.4k
    pos=input->tell();
565
16.4k
    f.str("");
566
16.4k
    f << "SdrModelInfo[" << zone.getRecordLevel() << "]:";
567
16.4k
    if (!zone.openRecord()) { // SdrModelInfo
568
1.32k
      STOFF_DEBUG_MSG(("StarObjectModel::read: can not read model info\n"));
569
1.32k
      f << "###";
570
1.32k
      ok=false;
571
1.32k
    }
572
15.1k
    else {
573
      /* operator>>(..., SdrModelInfo&)
574
575
         normally, this document also contains a SfxDocumentInfo, so it is safe to ignore them
576
       */
577
15.1k
      uint32_t date, time;
578
15.1k
      uint8_t enc;
579
15.1k
      *input >> date >> time >> enc;
580
15.1k
      f << "date=" << date << ",time=" << time << ",encoding=" << int(enc) << ",";
581
15.1k
      input->seek(3, librevenge::RVNG_SEEK_CUR); // creationGUI, creationCPU, creationSys
582
15.1k
      *input >> date >> time >> enc;
583
15.1k
      f << "modDate=" << date << ", modTime=" << time << ",encoding[mod]=" << int(enc) << ",";
584
15.1k
      input->seek(3, librevenge::RVNG_SEEK_CUR); // writeGUI, writeCPU, writeSys
585
15.1k
      *input >> date >> time >> enc;
586
15.1k
      f << "lastReadDate=" << date << ", lastReadTime=" << time << ",encoding[lastRead]=" << int(enc) << ",";
587
15.1k
      input->seek(3, librevenge::RVNG_SEEK_CUR); // lastReadGUI, lastReadCPU, lastReadSys
588
15.1k
      *input >> date >> time;
589
15.1k
      f << "lastPrintDate=" << date << ", lastPrintTime=" << time << ",";
590
15.1k
      ascFile.addPos(pos);
591
15.1k
      ascFile.addNote(f.str().c_str());
592
593
15.1k
      zone.closeRecord("SdrModelInfo");
594
15.1k
      pos=input->tell();
595
15.1k
      f.str("");
596
15.1k
      f << "SdrModelStats[" << zone.getRecordLevel() << "]:";
597
15.1k
      if (!zone.openRecord()) {
598
4.19k
        STOFF_DEBUG_MSG(("StarObjectModel::read: can not read model statistic\n"));
599
4.19k
        f << "###";
600
4.19k
        ok=false;
601
4.19k
      }
602
10.9k
      else {
603
10.9k
        zone.closeRecord("SdrModelStat");
604
10.9k
        ascFile.addPos(pos);
605
10.9k
        ascFile.addNote(f.str().c_str());
606
607
10.9k
        pos=input->tell();
608
10.9k
        f.str("");
609
10.9k
        f << "SdrModelFormatCompat[" << zone.getRecordLevel() << "]:";
610
10.9k
      }
611
15.1k
    }
612
16.4k
    if (ok&&!zone.openRecord()) {
613
457
      STOFF_DEBUG_MSG(("StarObjectModel::read: can not read model format compat\n"));
614
457
      f << "###";
615
457
      ok=false;
616
457
    }
617
15.9k
    else if (ok) {
618
10.4k
      if (input->tell()+6<=zone.getRecordLastPosition()) {
619
1.58k
        int16_t nTmp; // find 0
620
1.58k
        *input >> nTmp;
621
1.58k
        if (nTmp) f << "unk=" << nTmp << ",";
622
1.58k
      }
623
10.4k
      if (input->tell()+4<=zone.getRecordLastPosition()) {
624
10.4k
        auto compressedMode=int(input->readULong(2));
625
10.4k
        if (compressedMode) // checkme: find 0 or 16-17, do not seems to cause problem
626
891
          f << "#streamCompressed=" << compressedMode << ",";
627
10.4k
        f << "nStreamNumberFormat=" << input->readULong(2) << ",";
628
10.4k
      }
629
10.4k
      zone.closeRecord("SdrModelFormatCompat");
630
10.4k
    }
631
632
16.4k
    ascFile.addPos(pos);
633
16.4k
    ascFile.addNote(f.str().c_str());
634
16.4k
    pos=input->tell();
635
16.4k
    f.str("");
636
16.4k
    f << "SdrModelA[" << zone.getRecordLevel() << "]-data:";
637
16.4k
  }
638
16.8k
  if (ok) {
639
10.8k
    int32_t nNum, nDen;
640
10.8k
    uint16_t nTmp;
641
10.8k
    uint8_t nTmp8;
642
10.8k
    *input>> nNum >> nDen >> nTmp;
643
10.8k
    f << "objectUnit=" << nNum << "/" << nDen << ",";
644
10.8k
    if (nTmp) f << "eObjUnit=" << nTmp << ",";
645
10.8k
    input->seek(2, librevenge::RVNG_SEEK_CUR); // collapsed?
646
10.8k
    *input>>nTmp8;
647
10.8k
    if (nTmp8==1) f << "pageNotValid,";
648
10.8k
    input->seek(1, librevenge::RVNG_SEEK_CUR); // dummy
649
650
10.8k
    if (version<1) {
651
9
      STOFF_DEBUG_MSG(("StarObjectModel::read: reading model format for version 0 is not implemented\n"));
652
9
      f << "###version0";
653
9
      ok=false;
654
9
    }
655
10.8k
    else {
656
10.8k
      if (version<11) {
657
402
        auto charSet=int(input->readLong(2));
658
402
        if (StarEncoding::getEncodingForId(charSet)!=StarEncoding::E_DONTKNOW)
659
402
          zone.setEncoding(StarEncoding::getEncodingForId(charSet));
660
0
        else
661
0
          f << "###nCharSet=" << charSet << ",";
662
402
      }
663
10.8k
      std::vector<uint32_t> string;
664
69.3k
      for (int i=0; i<6; ++i) {
665
60.3k
        if (!zone.readString(string)) {
666
1.84k
          STOFF_DEBUG_MSG(("StarObjectModel::read: can not read a string\n"));
667
1.84k
          f << "###string";
668
1.84k
          ok=false;
669
1.84k
          break;
670
1.84k
        }
671
58.4k
        if (string.empty()) continue;
672
2.05k
        static char const* const wh[]= {"cTableName", "dashName", "lineEndName", "hashName", "gradientName", "bitmapName"};
673
2.05k
        f << wh[i] << "=" << libstoff::getString(string).cstr() << ",";
674
2.05k
      }
675
10.8k
    }
676
10.8k
  }
677
16.8k
  if (ok && version>=12 && input->tell()<zone.getRecordLastPosition()) {
678
4.70k
    int32_t nNum, nDen;
679
4.70k
    uint16_t nTmp;
680
4.70k
    *input>> nNum >> nDen >> nTmp;
681
4.70k
    f << "UIUnit=" << nNum << "/" << nDen << ",";
682
4.70k
    if (nTmp) f << "eUIUnit=" << nTmp << ",";
683
4.70k
  }
684
16.8k
  if (ok && version>=13 && input->tell()<zone.getRecordLastPosition()) {
685
2.84k
    int32_t nNum1, nNum2;
686
2.84k
    *input>> nNum1 >> nNum2;
687
2.84k
    if (nNum1) f << "nDefTextHgt=" << nNum1 << ",";
688
2.84k
    if (nNum2) f << "nDefTab=" << nNum2 << ",";
689
2.84k
  }
690
16.8k
  if (ok && version>=14 && input->tell()<zone.getRecordLastPosition()) {
691
2.84k
    uint16_t pNum;
692
2.84k
    *input>> pNum;
693
2.84k
    if (pNum!=0xFFFF) {
694
2.20k
      m_modelState->m_previewMasterPage=int(pNum);
695
2.20k
      f << "nStartPageNum=" << pNum << ",";
696
2.20k
    }
697
2.84k
  }
698
16.8k
  ascFile.addPos(pos);
699
16.8k
  ascFile.addNote(f.str().c_str());
700
16.8k
  if (version>=11) {
701
16.4k
    zone.closeRecord("SdrModelA2");
702
16.4k
    ok=true;
703
16.4k
  }
704
134k
  while (ok) {
705
134k
    pos=input->tell();
706
134k
    if (pos+4>zone.getRecordLastPosition())
707
6.70k
      break;
708
127k
    magic="";
709
637k
    for (int i=0; i<4; ++i) magic+=char(input->readULong(1));
710
127k
    input->seek(pos, librevenge::RVNG_SEEK_SET);
711
127k
    if (magic=="DrLy") {
712
50.9k
      StarObjectModelInternal::Layer layer;
713
50.9k
      if (readSdrLayer(zone, layer)) {
714
50.7k
        if (m_modelState->m_idToLayerMap.find(layer.m_id)!=m_modelState->m_idToLayerMap.end()) {
715
5.94k
          STOFF_DEBUG_MSG(("StarObjectModel::read: layer %d already exists\n", layer.m_id));
716
5.94k
        }
717
44.8k
        else
718
44.8k
          m_modelState->m_idToLayerMap[layer.m_id]=layer;
719
50.7k
        continue;
720
50.7k
      }
721
50.9k
    }
722
76.7k
    if (magic=="DrLS") {
723
988
      StarObjectModelInternal::LayerSet layers;
724
988
      if (readSdrLayerSet(zone, layers)) {
725
943
        m_modelState->m_layerSetList.push_back(layers);
726
943
        continue;
727
943
      }
728
988
    }
729
75.8k
    if ((magic=="DrPg" || magic=="DrMP")) {
730
57.3k
      auto page=readSdrPage(zone);
731
57.3k
      if (page) {
732
47.3k
        if (magic=="DrPg")
733
29.4k
          m_modelState->m_pageList.push_back(page);
734
17.8k
        else
735
17.8k
          m_modelState->m_masterPageList.push_back(page);
736
47.3k
        continue;
737
47.3k
      }
738
57.3k
    }
739
740
28.5k
    input->seek(pos, librevenge::RVNG_SEEK_SET);
741
28.5k
    if (!zone.openSDRHeader(magic)) {
742
9.74k
      input->seek(pos, librevenge::RVNG_SEEK_SET);
743
9.74k
      break;
744
9.74k
    }
745
18.7k
    f.str("");
746
18.7k
    f << "SdrModel[" << magic << "-" << zone.getRecordLevel() << "]:";
747
18.7k
    if (magic!="DrXX") {
748
12.4k
      STOFF_DEBUG_MSG(("StarObjectModel::read: find unexpected child\n"));
749
12.4k
      f << "###type";
750
12.4k
      input->seek(zone.getRecordLastPosition(), librevenge::RVNG_SEEK_SET);
751
12.4k
    }
752
18.7k
    ascFile.addPos(pos);
753
18.7k
    ascFile.addNote(f.str().c_str());
754
18.7k
    zone.closeSDRHeader("SdrModel");
755
18.7k
  }
756
757
16.8k
  zone.closeRecord("SdrModelA1");
758
  // in DrawingLayer, find also 0500000001 and 060000000[01]00
759
16.8k
  pos=input->tell();
760
16.8k
  if (pos+4<=zone.getRecordLastPosition()) {
761
4.14k
    auto sz=long(input->readULong(4));
762
4.14k
    if (pos+sz==zone.getRecordLastPosition()) {
763
1.71k
      ascFile.addPos(pos);
764
1.71k
      ascFile.addNote("SdrModel:#extra");
765
1.71k
      input->seek(zone.getRecordLastPosition(), librevenge::RVNG_SEEK_SET);
766
1.71k
    }
767
2.42k
    else
768
2.42k
      input->seek(pos, librevenge::RVNG_SEEK_SET);
769
4.14k
  }
770
16.8k
  zone.closeSDRHeader("SdrModel");
771
16.8k
  return true;
772
16.9k
}
773
774
bool StarObjectModel::readSdrLayer(StarZone &zone, StarObjectModelInternal::Layer &layer)
775
51.7k
{
776
51.7k
  layer=StarObjectModelInternal::Layer();
777
51.7k
  STOFFInputStreamPtr input=zone.input();
778
  // first check magic
779
51.7k
  std::string magic("");
780
51.7k
  long pos=input->tell();
781
258k
  for (int i=0; i<4; ++i) magic+=char(input->readULong(1));
782
51.7k
  input->seek(pos, librevenge::RVNG_SEEK_SET);
783
51.7k
  if (magic!="DrLy") return false;
784
785
51.7k
  libstoff::DebugFile &ascFile=zone.ascii();
786
51.7k
  libstoff::DebugStream f;
787
51.7k
  f << "Entries(SdrLayerDef)[" << zone.getRecordLevel() << "]:";
788
  // svdlayer.cxx operator>>(..., SdrLayer &)
789
51.7k
  if (!zone.openSDRHeader(magic)) {
790
275
    input->seek(pos, librevenge::RVNG_SEEK_SET);
791
275
    STOFF_DEBUG_MSG(("StarObjectModel::readSdrLayer: can not open the SDR Header\n"));
792
275
    f << "###";
793
275
    ascFile.addPos(pos);
794
275
    ascFile.addNote(f.str().c_str());
795
275
    return false;
796
275
  }
797
51.4k
  int version=zone.getHeaderVersion();
798
51.4k
  f << magic << ",nVers=" << version << ",";
799
800
51.4k
  if (magic!="DrLy") {
801
0
    STOFF_DEBUG_MSG(("StarObjectModel::readSdrLayer: unexpected magic data\n"));
802
0
    f << "###";
803
0
    ascFile.addPos(pos);
804
0
    ascFile.addNote(f.str().c_str());
805
0
    return false;
806
0
  }
807
51.4k
  layer.m_id=int(input->readULong(1));
808
51.4k
  std::vector<uint32_t> string;
809
51.4k
  if (!zone.readString(string)) {
810
1.98k
    STOFF_DEBUG_MSG(("StarObjectModel::readSdrLayer: can not read a string\n"));
811
1.98k
    f << "###string";
812
1.98k
    ascFile.addPos(pos);
813
1.98k
    ascFile.addNote(f.str().c_str());
814
1.98k
    zone.closeSDRHeader("SdrLayerDef");
815
1.98k
    return true;
816
1.98k
  }
817
49.5k
  layer.m_name=libstoff::getString(string);
818
49.5k
  if (version>=1) layer.m_type=int(input->readULong(2));
819
49.5k
  f << layer;
820
49.5k
  ascFile.addPos(pos);
821
49.5k
  ascFile.addNote(f.str().c_str());
822
49.5k
  zone.closeSDRHeader("SdrLayerDef");
823
49.5k
  return true;
824
51.4k
}
825
826
bool StarObjectModel::readSdrLayerSet(StarZone &zone, StarObjectModelInternal::LayerSet &layers)
827
1.21k
{
828
1.21k
  layers=StarObjectModelInternal::LayerSet();
829
1.21k
  STOFFInputStreamPtr input=zone.input();
830
  // first check magic
831
1.21k
  std::string magic("");
832
1.21k
  long pos=input->tell();
833
6.09k
  for (int i=0; i<4; ++i) magic+=char(input->readULong(1));
834
1.21k
  input->seek(pos, librevenge::RVNG_SEEK_SET);
835
1.21k
  if (magic!="DrLS") return false;
836
837
1.21k
  libstoff::DebugFile &ascFile=zone.ascii();
838
1.21k
  libstoff::DebugStream f;
839
1.21k
  f << "Entries(SdrLayerSet)[" << zone.getRecordLevel() << "]:";
840
  // svdlayer.cxx operator>>(..., SdrLayerSet &)
841
1.21k
  if (!zone.openSDRHeader(magic)) {
842
158
    input->seek(pos, librevenge::RVNG_SEEK_SET);
843
158
    STOFF_DEBUG_MSG(("StarObjectModel::readSdrLayerSet: can not open the SDR Header\n"));
844
158
    f << "###";
845
158
    ascFile.addPos(pos);
846
158
    ascFile.addNote(f.str().c_str());
847
158
    return false;
848
158
  }
849
1.06k
  int version=zone.getHeaderVersion();
850
1.06k
  f << magic << ",nVers=" << version << ",";
851
852
1.06k
  if (magic!="DrLS") {
853
0
    STOFF_DEBUG_MSG(("StarObjectModel::readSdrLayerSet: unexpected magic data\n"));
854
0
    f << "###";
855
0
    ascFile.addPos(pos);
856
0
    ascFile.addNote(f.str().c_str());
857
0
    return false;
858
0
  }
859
3.18k
  for (int i=0; i<2; ++i) {
860
2.12k
    std::vector<int> layerList;
861
69.9k
    for (int j=0; j<32; ++j) layerList.push_back(int(input->readULong(1)));
862
2.12k
    StarObjectModelInternal::convertUint8ListToBoolList(layerList, i==0 ? layers.m_memberList : layers.m_excludeList);
863
2.12k
  }
864
1.06k
  std::vector<uint32_t> string;
865
1.06k
  if (!zone.readString(string)) {
866
346
    STOFF_DEBUG_MSG(("StarObjectModel::readSdrLayerSet: can not read a string\n"));
867
346
    f << layers << "###string";
868
346
    ascFile.addPos(pos);
869
346
    ascFile.addNote(f.str().c_str());
870
346
    zone.closeSDRHeader("SdrLayerSet");
871
346
    return true;
872
346
  }
873
714
  layers.m_name=libstoff::getString(string).cstr();
874
714
  f << layers;
875
714
  ascFile.addPos(pos);
876
714
  ascFile.addNote(f.str().c_str());
877
714
  zone.closeSDRHeader("SdrLayerSet");
878
714
  return true;
879
1.06k
}
880
881
std::shared_ptr<StarObjectModelInternal::Page> StarObjectModel::readSdrPage(StarZone &zone)
882
57.3k
{
883
57.3k
  STOFFInputStreamPtr input=zone.input();
884
  // first check magic
885
57.3k
  std::string magic("");
886
57.3k
  long pos=input->tell();
887
286k
  for (int i=0; i<4; ++i) magic+=char(input->readULong(1));
888
57.3k
  input->seek(pos, librevenge::RVNG_SEEK_SET);
889
57.3k
  if (magic!="DrPg" && magic!="DrMP") return std::shared_ptr<StarObjectModelInternal::Page>();
890
891
  // svdpage.cxx operator>>
892
57.3k
  libstoff::DebugFile &ascFile=zone.ascii();
893
57.3k
  libstoff::DebugStream f;
894
57.3k
  f << "Entries(SdrPageDef)[" << zone.getRecordLevel() << "]:";
895
57.3k
  if (magic=="DrMP") f << "master,";
896
57.3k
  if (!zone.openSDRHeader(magic)) {
897
1.35k
    input->seek(pos, librevenge::RVNG_SEEK_SET);
898
1.35k
    STOFF_DEBUG_MSG(("StarObjectModel::readSdrPage: can not open the SDR Header\n"));
899
1.35k
    f << "###";
900
1.35k
    ascFile.addPos(pos);
901
1.35k
    ascFile.addNote(f.str().c_str());
902
1.35k
    return std::shared_ptr<StarObjectModelInternal::Page>();
903
1.35k
  }
904
55.9k
  int version=zone.getHeaderVersion();
905
55.9k
  f << magic << ",nVers=" << version << ",";
906
907
55.9k
  if (magic!="DrPg" && magic!="DrMP") {
908
0
    input->seek(pos, librevenge::RVNG_SEEK_SET);
909
0
    STOFF_DEBUG_MSG(("StarObjectModel::readSdrPage: unexpected magic data\n"));
910
0
    f << "###";
911
0
    ascFile.addPos(pos);
912
0
    ascFile.addNote(f.str().c_str());
913
0
    return std::shared_ptr<StarObjectModelInternal::Page>();
914
0
  }
915
55.9k
  ascFile.addPos(pos);
916
55.9k
  ascFile.addNote(f.str().c_str());
917
55.9k
  pos=input->tell();
918
919
55.9k
  std::shared_ptr<StarObjectModelInternal::Page> page(new StarObjectModelInternal::Page);
920
55.9k
  page->m_masterPage=magic=="DrMP";
921
55.9k
  f.str("");
922
55.9k
  f << "SdrPageDefA[" << zone.getRecordLevel() << "]:";
923
  // svdpage.cxx SdrPage::ReadData
924
55.9k
  bool hasExtraData=false;
925
106k
  for (int tr=0; tr<2; ++tr) {
926
    /* sometimes there is one or two block which appears before the
927
       SdrPage::ReadData data, so try to find them*/
928
106k
    long lastPos=zone.getRecordLastPosition();
929
106k
    if (!zone.openRecord()) { // SdrPageDefA1
930
5.83k
      STOFF_DEBUG_MSG(("StarObjectModel::readSdrPage: can not open downCompat\n"));
931
5.83k
      f << "###";
932
5.83k
      ascFile.addPos(pos);
933
5.83k
      ascFile.addNote(f.str().c_str());
934
5.83k
      zone.closeSDRHeader("SdrPageDef");
935
5.83k
      return std::shared_ptr<StarObjectModelInternal::Page>();
936
5.83k
    }
937
101k
    if (tr==1 || zone.getRecordLastPosition()==lastPos)
938
50.1k
      break;
939
    // unsure, how we can have some dim and pool here but seems frequent in DrawingLayer
940
50.8k
    uint16_t n;
941
50.8k
    *input >> n;
942
50.8k
    bool ok=false;
943
50.8k
    if (n>1) {
944
2.00k
      STOFF_DEBUG_MSG(("StarObjectModel::readSdrPage: bad version\n"));
945
2.00k
      f << "###n=" << n << ",";
946
2.00k
      ok=false;
947
2.00k
    }
948
48.8k
    else
949
48.8k
      hasExtraData=true;
950
50.8k
    if (n==1 && input->tell()+8<=zone.getRecordLastPosition())  {
951
15.7k
      f << "dim=[";
952
78.7k
      for (int i=0; i<4; ++i) f << input->readLong(2) << ((i%2) ? "," : "x");
953
15.7k
      f << "],";
954
15.7k
      *input >> n;
955
15.7k
      ok=true;
956
15.7k
    }
957
50.8k
    if (ok && n>1 && input->tell()+2<=zone.getRecordLastPosition()) {
958
549
      STOFF_DEBUG_MSG(("StarObjectModel::readSdrPage: bad version2\n"));
959
549
      f << "###n2=" << n << ",";
960
549
      ok=false;
961
549
    }
962
50.8k
    if (ok && n==1) {
963
14.4k
      long actPos=input->tell();
964
14.4k
      auto pool=getNewItemPool(StarItemPool::T_VCControlPool);
965
14.4k
      if (!pool || !pool->read(zone))
966
2.79k
        input->seek(actPos, librevenge::RVNG_SEEK_SET);
967
14.4k
    }
968
50.8k
    ascFile.addPos(pos);
969
50.8k
    ascFile.addNote(f.str().c_str());
970
971
50.8k
    zone.closeRecord("SdrPageDef");
972
50.8k
    pos=input->tell();
973
50.8k
    f.str("");
974
50.8k
    f << "SdrPageDefA[" << zone.getRecordLevel() << "]:";
975
50.8k
  }
976
50.1k
  ascFile.addPos(pos);
977
50.1k
  ascFile.addNote(f.str().c_str());
978
50.1k
  pos=input->tell();
979
50.1k
  f.str("");
980
50.1k
  f << "SdrPageDefA[" << zone.getRecordLevel() << "]:";
981
50.1k
  if (version>=11) {
982
49.4k
    magic="";
983
247k
    for (int i=0; i<4; ++i) magic+=char(input->readULong(1));
984
49.4k
    f << "joeM";
985
49.4k
    if (magic!="JoeM" || !zone.openRecord()) { // SdrPageDefA2
986
2.79k
      STOFF_DEBUG_MSG(("StarObjectModel::readSdrPage: unexpected magic2 data\n"));
987
2.79k
      f << "###magic" << magic;
988
2.79k
      ascFile.addPos(pos);
989
2.79k
      ascFile.addNote(f.str().c_str());
990
2.79k
      zone.closeRecord("SdrPageDefA1");
991
2.79k
      zone.closeSDRHeader("SdrPageDef");
992
2.79k
      return std::shared_ptr<StarObjectModelInternal::Page>();
993
2.79k
    }
994
46.6k
    ascFile.addPos(pos);
995
46.6k
    ascFile.addNote(f.str().c_str());
996
997
46.6k
    pos=input->tell();
998
46.6k
    f.str("");
999
46.6k
    f << "SdrPageDefData[" << zone.getRecordLevel() << "]:";
1000
46.6k
  }
1001
47.3k
  int32_t nWdt, nHgt;
1002
47.3k
  int32_t borders[4];
1003
47.3k
  uint16_t n;
1004
47.3k
  *input >> nWdt >> nHgt >> borders[0] >> borders[1] >> borders[2] >> borders[3] >> n;
1005
47.3k
  f << "dim=" << nWdt << "x" << nHgt << ",";
1006
47.3k
  f << "border=[" << borders[0] << "x" << borders[1] << "-" << borders[2] << "x" << borders[3] << "],";
1007
47.3k
  page->m_size=STOFFVec2i(int(nWdt), int(nHgt));
1008
236k
  for (int i=0; i<4; ++i) page->m_borders[i]=int(borders[i]);
1009
47.3k
  if (n) f << "n=" << n << ","; // link to page name?
1010
47.3k
  ascFile.addPos(pos);
1011
47.3k
  ascFile.addNote(f.str().c_str());
1012
47.3k
  if (version>=11)
1013
46.6k
    zone.closeRecord("SdrPageDefData");
1014
1015
47.3k
  long lastPos=zone.getRecordLastPosition();
1016
47.3k
  bool ok=true;
1017
90.9k
  while (ok) {
1018
90.9k
    pos=input->tell();
1019
90.9k
    if (pos+4>lastPos)
1020
203
      break;
1021
90.7k
    magic="";
1022
453k
    for (int i=0; i<4; ++i) magic+=char(input->readULong(1));
1023
90.7k
    input->seek(pos, librevenge::RVNG_SEEK_SET);
1024
90.7k
    if (magic=="DrLy" && readSdrLayer(zone, page->m_layer)) continue;
1025
90.0k
    if (magic=="DrLS" && readSdrLayerSet(zone, page->m_layerSet)) continue;
1026
89.8k
    if (magic=="DrMP" && readSdrMPageDesc(zone, *page)) continue;
1027
89.8k
    if (magic=="DrML" && readSdrMPageDescList(zone, *page)) continue;
1028
47.1k
    break;
1029
89.8k
  }
1030
47.3k
  if (ok && version==0) {
1031
659
    pos=input->tell();
1032
659
    f.str("");
1033
659
    f << "SdrPageDef[masterPage]:";
1034
659
    *input >> n;
1035
659
    if (pos+2+2*n>lastPos) {
1036
170
      STOFF_DEBUG_MSG(("StarObjectModel::readSdrPage: n is bad\n"));
1037
170
      f << "###n=" << n << ",";
1038
170
      ok=false;
1039
170
    }
1040
489
    else {
1041
489
      f << "pages=[";
1042
489
      StarObjectModelInternal::Page::Descriptor desc;
1043
26.8k
      for (int i=0; i<int(n); ++i) {
1044
26.3k
        auto id=int(input->readULong(2));
1045
26.3k
        f << id << ",";
1046
26.3k
        desc.m_masterId=id;
1047
26.3k
        page->m_masterPageDescList.push_back(desc);
1048
26.3k
      }
1049
489
      f << "],";
1050
489
    }
1051
659
    ascFile.addPos(pos);
1052
659
    ascFile.addNote(f.str().c_str());
1053
659
  }
1054
  // SdrObjList::Load
1055
157k
  while (ok) {
1056
157k
    pos=input->tell();
1057
157k
    if (pos+4>lastPos)
1058
372
      break;
1059
157k
    std::shared_ptr<StarObjectSmallGraphic> smallGraphic(new StarObjectSmallGraphic(*this, true));
1060
157k
    if (smallGraphic->readSdrObject(zone)) {
1061
110k
      page->m_objectList.push_back(smallGraphic);
1062
110k
      continue;
1063
110k
    }
1064
1065
46.7k
    magic="";
1066
233k
    for (int i=0; i<4; ++i) magic+=char(input->readULong(1));
1067
46.7k
    input->seek(pos, librevenge::RVNG_SEEK_SET);
1068
46.7k
    if (magic=="DrXX" && zone.openSDRHeader(magic)) {
1069
26.1k
      f.str("");
1070
26.1k
      f << "SdrPageDef[DrXX-" << zone.getRecordLevel() << "]:";
1071
26.1k
      ascFile.addPos(pos);
1072
26.1k
      ascFile.addNote(f.str().c_str());
1073
26.1k
      zone.closeSDRHeader("SdrPageDef");
1074
26.1k
      break;
1075
26.1k
    }
1076
20.6k
    ok=false;
1077
20.6k
    STOFF_DEBUG_MSG(("StarObjectModel::readSdrPage: can not find end object zone\n"));
1078
20.6k
    input->seek(pos, librevenge::RVNG_SEEK_SET);
1079
20.6k
    break;
1080
46.7k
  }
1081
47.3k
  if (ok && version>=16) {
1082
10.2k
    pos=input->tell();
1083
10.2k
    f.str("");
1084
10.2k
    f << "SdrPageDef[background-" << zone.getRecordLevel() << "]:";
1085
10.2k
    bool background;
1086
10.2k
    *input>>background;
1087
10.2k
    ascFile.addPos(pos);
1088
10.2k
    ascFile.addNote(f.str().c_str());
1089
1090
10.2k
    if (background) {
1091
356
      std::shared_ptr<StarObjectSmallGraphic> smallGraphic(new StarObjectSmallGraphic(*this, true));
1092
356
      if (smallGraphic->readSdrObject(zone))
1093
40
        page->m_background=smallGraphic;
1094
316
      else {
1095
316
        STOFF_DEBUG_MSG(("StarObjectModel::readSdrPage: can not find backgroound object\n"));
1096
316
        input->seek(pos, librevenge::RVNG_SEEK_SET);
1097
316
        ok=false;
1098
316
      }
1099
356
    }
1100
10.2k
  }
1101
47.3k
  zone.closeRecord("SdrPageDefA1");
1102
47.3k
  if (ok && hasExtraData) {
1103
25.3k
    lastPos=zone.getRecordLastPosition();
1104
25.3k
    n=0;
1105
75.7k
    while (input->tell()<lastPos) {
1106
52.6k
      pos=input->tell();
1107
52.6k
      if (!zone.openRecord()) break;
1108
50.4k
      f.str("");
1109
50.4k
      f << "SdrPageDefB" << ++n << "[" << zone.getRecordLevel() << "]:";
1110
50.4k
      if (n==1) {
1111
24.7k
        std::vector<uint32_t> string;
1112
24.7k
        if (!zone.readString(string)) {
1113
159
          STOFF_DEBUG_MSG(("StarObjectModel::readSdrPage: can not find read a string\n"));
1114
159
          f << "###string";
1115
159
        }
1116
24.5k
        else {
1117
          // Controls or sheet name
1118
24.5k
          page->m_name=libstoff::getString(string);
1119
24.5k
          f << page->m_name.cstr() << ",";
1120
24.5k
        }
1121
        // then if vers>={13|14|15|16}  671905111105671901000800000000000000
1122
24.7k
      }
1123
25.7k
      else if (n==2 && pos+12==zone.getRecordLastPosition()) {
1124
9.04k
        f << "empty,";
1125
45.2k
        for (int i=0; i<4; ++i) { // always 0
1126
36.1k
          auto val=int(input->readLong(2));
1127
36.1k
          if (val) f << "f" << i << "=" << val << ",";
1128
36.1k
        }
1129
9.04k
      }
1130
16.6k
      else if (!readSdrPageUnknownZone1(zone, zone.getRecordLastPosition())) {
1131
5.73k
        input->seek(pos+4, librevenge::RVNG_SEEK_SET);
1132
5.73k
        STOFF_DEBUG_MSG(("StarObjectModel::readSdrPage: find some unknown zone\n"));
1133
5.73k
        f << "###unknown";
1134
5.73k
      }
1135
      // for version>=16?, find another zone: either an empty zone or a zone which contains many string...
1136
50.4k
      if (zone.getRecordLastPosition()!=input->tell()) {
1137
15.6k
        ascFile.addDelimiter(input->tell(),'|');
1138
15.6k
        f << "#";
1139
15.6k
        input->seek(zone.getRecordLastPosition(), librevenge::RVNG_SEEK_SET);
1140
15.6k
      }
1141
50.4k
      ascFile.addPos(pos);
1142
50.4k
      ascFile.addNote(f.str().c_str());
1143
50.4k
      zone.closeRecord("SdrPageDefB");
1144
50.4k
    }
1145
25.3k
  }
1146
1147
47.3k
  zone.closeSDRHeader("SdrPageDef");
1148
47.3k
  return page;
1149
50.1k
}
1150
1151
bool StarObjectModel::readSdrPageUnknownZone1(StarZone &zone, long lastPos)
1152
16.6k
{
1153
  // checkme: probably as draw pres: schheader: first a schheader, then 3 bool
1154
16.6k
  STOFFInputStreamPtr input=zone.input();
1155
16.6k
  long pos=input->tell()-4;
1156
16.6k
  libstoff::DebugFile &ascFile=zone.ascii();
1157
16.6k
  libstoff::DebugStream f;
1158
16.6k
  f << "Entries(SdrPageUnkn1)[" << zone.getRecordLevel() << "]:";
1159
16.6k
  if (pos+28>lastPos) return false;
1160
15.8k
  auto val=int(input->readULong(2));
1161
15.8k
  if (val!=3 && val!=7)
1162
4.19k
    return false;
1163
11.6k
  f << "f0=" << val << ",";
1164
46.5k
  for (int i=0; i<3; ++i) { // 1
1165
34.9k
    val=int(input->readULong(1));
1166
34.9k
    if (val!=1) f << "f" << i+1 << "=" << val << ",";
1167
34.9k
  }
1168
69.8k
  for (int i=0; i<5; ++i) { // g0=14|15|19, g1=1, g3=0-10,
1169
58.2k
    val=int(input->readLong(2));
1170
58.2k
    if (val) f << "g" << i << "=" << val << ",";
1171
58.2k
  }
1172
11.6k
  val=int(input->readLong(1)); // always 1
1173
11.6k
  if (val!=1) f << "f6=" << val << ",";
1174
46.5k
  for (int i=0; i<3; ++i) { // g5=1|1e
1175
34.9k
    val=int(input->readLong(2));
1176
34.9k
    if (val) f << "g" << i+5 << "=" << val << ",";
1177
34.9k
  }
1178
11.6k
  std::vector<uint32_t> string;
1179
11.6k
  if (!zone.readString(string) || input->tell()>lastPos)
1180
317
    return false;
1181
11.3k
  f << libstoff::getString(string).cstr() << ",";
1182
11.3k
  auto n=int(input->readULong(4));
1183
11.3k
  if (n<0 || (lastPos-input->tell())/8<n || input->tell()+8*n>lastPos)
1184
389
    return false;
1185
10.9k
  f << "unk=[";
1186
29.4k
  for (int i=0; i<n; ++i) {
1187
18.5k
    f << "[";
1188
92.5k
    for (int j=0; j<4; ++j) {
1189
74.0k
      val=int(input->readLong(2));
1190
74.0k
      if (val)
1191
29.4k
        f << val << ",";
1192
44.5k
      else
1193
44.5k
        f << "_,";
1194
74.0k
    }
1195
18.5k
    f << "],";
1196
18.5k
  }
1197
10.9k
  f << "],";
1198
10.9k
  int n1=int(lastPos-input->tell())/2;
1199
10.9k
  f << "unkn1=[";
1200
107k
  for (int i=0; i<n1; ++i) {
1201
96.6k
    val=int(input->readLong(2));
1202
96.6k
    if (val)
1203
32.5k
      f << val << ",";
1204
64.1k
    else
1205
64.1k
      f << "_,";
1206
96.6k
  }
1207
10.9k
  f << "],";
1208
10.9k
  if (lastPos>input->tell()) {
1209
104
    ascFile.addDelimiter(input->tell(),'|');
1210
104
    input->seek(lastPos, librevenge::RVNG_SEEK_SET);
1211
104
  }
1212
10.9k
  ascFile.addPos(pos);
1213
10.9k
  ascFile.addNote(f.str().c_str());
1214
10.9k
  return true;
1215
11.3k
}
1216
1217
bool StarObjectModel::readSdrMPageDesc(StarZone &zone, StarObjectModelInternal::Page &page)
1218
16.4k
{
1219
16.4k
  STOFFInputStreamPtr input=zone.input();
1220
  // first check magic
1221
16.4k
  std::string magic("");
1222
16.4k
  long pos=input->tell();
1223
82.0k
  for (int i=0; i<4; ++i) magic+=char(input->readULong(1));
1224
16.4k
  input->seek(pos, librevenge::RVNG_SEEK_SET);
1225
16.4k
  if (magic!="DrMD") return false;
1226
1227
15.7k
  libstoff::DebugFile &ascFile=zone.ascii();
1228
15.7k
  libstoff::DebugStream f;
1229
15.7k
  f << "Entries(SdrMPageDesc)[" << zone.getRecordLevel() << "]:";
1230
  // svdpage.cxx operator>>(..., SdrMaterPageDescriptor &)
1231
15.7k
  if (!zone.openSDRHeader(magic)) {
1232
1.52k
    input->seek(pos, librevenge::RVNG_SEEK_SET);
1233
1.52k
    STOFF_DEBUG_MSG(("StarObjectModel::readSdrMPageDesc: can not open the SDR Header\n"));
1234
1.52k
    f << "###";
1235
1.52k
    ascFile.addPos(pos);
1236
1.52k
    ascFile.addNote(f.str().c_str());
1237
1.52k
    return false;
1238
1.52k
  }
1239
14.2k
  int version=zone.getHeaderVersion();
1240
14.2k
  f << magic << ",nVers=" << version << ",";
1241
14.2k
  StarObjectModelInternal::Page::Descriptor desc;
1242
14.2k
  desc.m_masterId=int(input->readULong(2));
1243
14.2k
  std::vector<int> layers;
1244
470k
  for (int i=0; i<32; ++i)
1245
456k
    layers.push_back(int(input->readULong(1)));
1246
14.2k
  StarObjectModelInternal::convertUint8ListToBoolList(layers, desc.m_layerList);
1247
14.2k
  f << desc;
1248
14.2k
  page.m_masterPageDescList.push_back(desc);
1249
14.2k
  ascFile.addPos(pos);
1250
14.2k
  ascFile.addNote(f.str().c_str());
1251
14.2k
  zone.closeSDRHeader("SdrMPageDesc");
1252
14.2k
  return true;
1253
15.7k
}
1254
1255
bool StarObjectModel::readSdrMPageDescList(StarZone &zone, StarObjectModelInternal::Page &page)
1256
43.7k
{
1257
43.7k
  STOFFInputStreamPtr input=zone.input();
1258
  // first check magic
1259
43.7k
  std::string magic("");
1260
43.7k
  long pos=input->tell();
1261
218k
  for (int i=0; i<4; ++i) magic+=char(input->readULong(1));
1262
43.7k
  input->seek(pos, librevenge::RVNG_SEEK_SET);
1263
43.7k
  if (magic!="DrML") return false;
1264
1265
43.7k
  libstoff::DebugFile &ascFile=zone.ascii();
1266
43.7k
  libstoff::DebugStream f;
1267
43.7k
  f << "Entries(SdrMPageList)[" << zone.getRecordLevel() << "]:";
1268
  // svdpage.cxx operator>>(..., SdrMaterPageDescListriptor &)
1269
43.7k
  if (!zone.openSDRHeader(magic)) {
1270
1.00k
    input->seek(pos, librevenge::RVNG_SEEK_SET);
1271
1.00k
    STOFF_DEBUG_MSG(("StarObjectModel::readSdrMPageDescList: can not open the SDR Header\n"));
1272
1.00k
    f << "###";
1273
1.00k
    ascFile.addPos(pos);
1274
1.00k
    ascFile.addNote(f.str().c_str());
1275
1.00k
    return false;
1276
1.00k
  }
1277
42.7k
  int version=zone.getHeaderVersion();
1278
42.7k
  uint16_t n;
1279
42.7k
  *input>>n;
1280
42.7k
  f << magic << ",nVers=" << version << ",N=" << n << ",";
1281
42.7k
  ascFile.addPos(pos);
1282
42.7k
  ascFile.addNote(f.str().c_str());
1283
1284
42.7k
  long lastPos=zone.getRecordLastPosition();
1285
57.0k
  for (int i=0; i<n; ++i) {
1286
17.2k
    pos=input->tell();
1287
17.2k
    if (pos<lastPos && readSdrMPageDesc(zone, page)) continue;
1288
3.00k
    STOFF_DEBUG_MSG(("StarObjectModel::readSdrMPageDescList: can not find a page desc\n"));
1289
3.00k
    ascFile.addPos(pos);
1290
3.00k
    ascFile.addNote("SdrMPageList:###pageDesc");
1291
3.00k
    input->seek(pos, librevenge::RVNG_SEEK_SET);
1292
3.00k
    break;
1293
17.2k
  }
1294
1295
42.7k
  zone.closeSDRHeader("SdrMPageList");
1296
42.7k
  return true;
1297
43.7k
}
1298
1299
// vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: