Coverage Report

Created: 2026-09-14 06:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libmwaw/src/lib/ClarisDrawParser.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
/* libmwaw
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 <cmath>
35
#include <iomanip>
36
#include <iostream>
37
#include <limits>
38
#include <sstream>
39
40
#include <librevenge/librevenge.h>
41
42
#include "MWAWFontConverter.hxx"
43
#include "MWAWGraphicListener.hxx"
44
#include "MWAWGraphicShape.hxx"
45
#include "MWAWGraphicStyle.hxx"
46
#include "MWAWHeader.hxx"
47
#include "MWAWParagraph.hxx"
48
#include "MWAWPictBitmap.hxx"
49
#include "MWAWPictData.hxx"
50
#include "MWAWPrinter.hxx"
51
#include "MWAWPosition.hxx"
52
#include "MWAWSubDocument.hxx"
53
54
#include "ClarisDrawStyleManager.hxx"
55
#include "ClarisDrawGraph.hxx"
56
#include "ClarisDrawText.hxx"
57
#include "ClarisWksStruct.hxx"
58
59
#include "ClarisDrawParser.hxx"
60
61
/** Internal: the structures of a ClarisDrawParser */
62
namespace ClarisDrawParserInternal
63
{
64
// generic class used to defined a layer
65
struct Layer {
66
  //! constructor
67
  Layer()
68
5.47k
    : m_groupId(0)
69
5.47k
    , m_isHidden(false)
70
5.47k
    , m_name("")
71
5.47k
  {
72
5.47k
  }
73
  //! the first group id
74
  int m_groupId;
75
  //! true if the layer is hidden
76
  bool m_isHidden;
77
  //! the layer name
78
  librevenge::RVNGString m_name;
79
};
80
81
////////////////////////////////////////////
82
//! Internal: the state of a ClarisDrawParser
83
struct State {
84
  //! constructor
85
  State()
86
167k
    : m_version(0)
87
167k
    , m_isLibrary(false)
88
167k
    , m_numDSET(0)
89
167k
    , m_EOF(-1)
90
167k
    , m_actualLayer(1)
91
167k
    , m_numLayers(1)
92
167k
    , m_createMasterPage(false)
93
167k
    , m_displayAsSlide(false)
94
167k
    , m_layerList()
95
167k
    , m_pageSpanSet(false)
96
167k
    , m_headerId(0)
97
167k
    , m_footerId(0)
98
167k
    , m_pages(1,1)
99
167k
    , m_zonesMap()
100
167k
    , m_zoneIdToFileTypeMap()
101
167k
  {
102
167k
  }
103
  //! the file version
104
  int m_version;
105
  //! flag to know if the file is a library or not
106
  bool m_isLibrary;
107
  //! the number of DSET+FNTM
108
  int m_numDSET;
109
  //! the last data zone size
110
  long m_EOF;
111
  //! the actual layer
112
  int m_actualLayer;
113
  //! the number of layer
114
  int m_numLayers;
115
  //! flag to know if we need or not to create a master
116
  bool m_createMasterPage;
117
  //! flag to know if we need to display data as slide
118
  bool m_displayAsSlide;
119
  //! the layer list
120
  std::vector<Layer> m_layerList;
121
  //! flag to know if the page has been set
122
  bool m_pageSpanSet;
123
  //! header id
124
  int m_headerId;
125
  //! footer id
126
  int m_footerId;
127
  //! the number of pages
128
  MWAWVec2i m_pages;
129
  /** the map of zone*/
130
  std::map<int, std::shared_ptr<ClarisWksStruct::DSET> > m_zonesMap;
131
  /** map zone id to file type */
132
  std::map<int, int> m_zoneIdToFileTypeMap;
133
};
134
}
135
136
////////////////////////////////////////////////////////////
137
// constructor/destructor, ...
138
////////////////////////////////////////////////////////////
139
ClarisDrawParser::ClarisDrawParser(MWAWInputStreamPtr const &input, MWAWRSRCParserPtr const &rsrcParser, MWAWHeader *header)
140
68.6k
  : MWAWGraphicParser(input, rsrcParser, header)
141
68.6k
  , m_state()
142
68.6k
  , m_styleManager()
143
68.6k
  , m_graphParser()
144
68.6k
  , m_textParser()
145
68.6k
{
146
68.6k
  init();
147
68.6k
}
148
149
ClarisDrawParser::~ClarisDrawParser()
150
68.6k
{
151
68.6k
}
152
153
void ClarisDrawParser::init()
154
68.6k
{
155
68.6k
  resetGraphicListener();
156
68.6k
  setAsciiName("main-1");
157
68.6k
  m_state.reset(new ClarisDrawParserInternal::State);
158
68.6k
  m_styleManager.reset(new ClarisDrawStyleManager(*this));
159
160
68.6k
  m_graphParser.reset(new ClarisDrawGraph(*this));
161
68.6k
  m_textParser.reset(new ClarisDrawText(*this));
162
163
68.6k
  getPageSpan().setMargins(0.1);
164
68.6k
}
165
166
int ClarisDrawParser::getFileType(int zoneId) const
167
167k
{
168
167k
  if (m_state->m_zoneIdToFileTypeMap.find(zoneId) == m_state->m_zoneIdToFileTypeMap.end()) {
169
75.4k
    MWAW_DEBUG_MSG(("ClarisDrawParser::getFileType: zone %d does not exists!!!!\n", zoneId));
170
75.4k
    return -1;
171
75.4k
  }
172
91.7k
  return m_state->m_zoneIdToFileTypeMap.find(zoneId)->second;
173
167k
}
174
175
bool ClarisDrawParser::sendTextZone(int number, int subZone)
176
5.05k
{
177
5.05k
  return m_textParser->sendZone(number, subZone);
178
5.05k
}
179
180
MWAWVec2f ClarisDrawParser::getPageLeftTop()
181
31.3k
{
182
31.3k
  return MWAWVec2f(float(getParserState()->m_pageSpan.getMarginLeft()),
183
31.3k
                   float(getParserState()->m_pageSpan.getMarginTop()));
184
31.3k
}
185
186
////////////////////////////////////////////////////////////
187
// the parser
188
////////////////////////////////////////////////////////////
189
void ClarisDrawParser::parse(librevenge::RVNGDrawingInterface *docInterface)
190
30.5k
{
191
30.5k
  if (!getInput().get() || !checkHeader(nullptr))  throw(libmwaw::ParseException());
192
30.5k
  bool ok = false;
193
30.5k
  try {
194
    // create the asciiFile
195
30.5k
    ascii().setStream(getInput());
196
30.5k
    ascii().open(asciiName());
197
30.5k
    checkHeader(nullptr);
198
30.5k
    ok = createZones();
199
30.5k
    if (ok) {
200
30.4k
      createDocument(docInterface);
201
30.4k
      MWAWVec2f leftTop=72.0f*getPageLeftTop();
202
30.4k
      MWAWPosition pos(leftTop,MWAWVec2f(0,0),librevenge::RVNG_POINT);
203
30.4k
      pos.setRelativePosition(MWAWPosition::Page);
204
30.4k
      MWAWGraphicListenerPtr listener=getGraphicListener();
205
206
30.4k
      if (m_state->m_isLibrary) {
207
25.3k
        for (size_t i=0; i<m_state->m_layerList.size(); ++i) {
208
0
          if (i>0)
209
0
            listener->insertBreak(MWAWListener::PageBreak);
210
0
          m_graphParser->sendMainGroupChild(int(i), pos);
211
0
        }
212
25.3k
      }
213
5.11k
      else if (m_state->m_displayAsSlide) {
214
1.02k
        bool first=true;
215
2.94k
        for (size_t i=1; i< m_state->m_layerList.size(); ++i) {
216
1.92k
          if (m_graphParser->isEmptyGroup(m_state->m_layerList[i].m_groupId))
217
1.24k
            continue;
218
678
          if (!first)
219
250
            listener->insertBreak(MWAWListener::PageBreak);
220
678
          first=false;
221
678
          m_graphParser->sendGroup(m_state->m_layerList[i].m_groupId, pos);
222
678
        }
223
1.02k
      }
224
4.08k
      else {
225
6.06k
        for (size_t i=1; i< m_state->m_layerList.size(); ++i) {
226
1.97k
          if (m_graphParser->isEmptyGroup(m_state->m_layerList[i].m_groupId))
227
623
            continue;
228
1.35k
          bool openLayer=false;
229
1.35k
          if (!m_state->m_layerList[i].m_name.empty())
230
1.13k
            openLayer=listener->openLayer(m_state->m_layerList[i].m_name);
231
1.35k
          m_graphParser->sendGroup(m_state->m_layerList[i].m_groupId, pos);
232
1.35k
          if (openLayer)
233
1.13k
            listener->closeLayer();
234
1.35k
        }
235
4.08k
      }
236
#ifdef DEBUG
237
      m_graphParser->flushExtra();
238
#endif
239
30.4k
    }
240
30.5k
    ascii().reset();
241
30.5k
  }
242
30.5k
  catch (...) {
243
20
    MWAW_DEBUG_MSG(("ClarisDrawParser::parse: exception catched when parsing\n"));
244
20
    ok = false;
245
20
  }
246
247
30.5k
  resetGraphicListener();
248
30.5k
  if (!ok) throw(libmwaw::ParseException());
249
30.5k
}
250
251
////////////////////////////////////////////////////////////
252
// create the document
253
////////////////////////////////////////////////////////////
254
void ClarisDrawParser::createDocument(librevenge::RVNGDrawingInterface *documentInterface)
255
30.4k
{
256
30.4k
  if (!documentInterface) return;
257
30.4k
  if (getGraphicListener()) {
258
0
    MWAW_DEBUG_MSG(("ClarisDrawParser::createDocument: listener already exist\n"));
259
0
    return;
260
0
  }
261
262
30.4k
  m_graphParser->updateGroup(m_state->m_isLibrary);
263
264
265
  // create the page list
266
30.4k
  int numPages=1;
267
30.4k
  MWAWPageSpan ps(getPageSpan());
268
30.4k
  ps.setPageSpan(1);
269
30.4k
  std::vector<librevenge::RVNGString> listNames;
270
30.4k
  if (m_state->m_isLibrary) {
271
25.3k
    numPages=static_cast<int>(m_state->m_layerList.size());
272
25.3k
    if (numPages<1) numPages=1;
273
25.3k
  }
274
5.11k
  else {
275
5.11k
    m_state->m_createMasterPage=!m_state->m_layerList.empty() &&
276
1.57k
                                !m_graphParser->isEmptyGroup(m_state->m_layerList[0].m_groupId);
277
5.11k
    if (m_state->m_createMasterPage)
278
911
      ps.setMasterPageName(librevenge::RVNGString("Master"));
279
9.01k
    for (size_t i=1; i<m_state->m_layerList.size(); ++i) {
280
3.90k
      if (!m_graphParser->isEmptyGroup(m_state->m_layerList[i].m_groupId))
281
2.03k
        listNames.push_back(m_state->m_layerList[i].m_name);
282
3.90k
    }
283
5.11k
    if (m_state->m_displayAsSlide && !listNames.empty())
284
428
      numPages=static_cast<int>(listNames.size());
285
5.11k
  }
286
30.4k
  std::vector<MWAWPageSpan> pageList;
287
61.0k
  for (int i=0; i<numPages; ++i) {
288
30.6k
    MWAWPageSpan page(ps);
289
30.6k
    if (m_state->m_isLibrary && i<static_cast<int>(m_state->m_layerList.size()))
290
0
      page.setPageName(m_state->m_layerList[size_t(i)].m_name);
291
30.6k
    else if (m_state->m_displayAsSlide && i<static_cast<int>(listNames.size()))
292
678
      page.setPageName(listNames[size_t(i)]);
293
30.6k
    pageList.push_back(page);
294
30.6k
  }
295
30.4k
  MWAWGraphicListenerPtr listen(new MWAWGraphicListener(*getParserState(), pageList, documentInterface));
296
30.4k
  setGraphicListener(listen);
297
30.4k
  listen->startDocument();
298
299
300
30.4k
  if (!m_state->m_createMasterPage)
301
29.5k
    return;
302
303
  // we need to send the master page
304
911
  if (!listen->openMasterPage(ps)) {
305
0
    MWAW_DEBUG_MSG(("ClarisDrawParser::createDocument: can not create the master page\n"));
306
0
    m_state->m_createMasterPage=false;
307
0
    return;
308
0
  }
309
911
  MWAWVec2f leftTop=72.0f*getPageLeftTop();
310
911
  MWAWPosition pos(leftTop,MWAWVec2f(0,0),librevenge::RVNG_POINT);
311
911
  pos.setRelativePosition(MWAWPosition::Page);
312
911
  m_graphParser->sendGroup(m_state->m_layerList[0].m_groupId, pos);
313
911
  listen->closeMasterPage();
314
911
}
315
316
////////////////////////////////////////////////////////////
317
//
318
// Intermediate level
319
//
320
////////////////////////////////////////////////////////////
321
bool ClarisDrawParser::createZones()
322
30.5k
{
323
30.5k
  MWAWInputStreamPtr input = getInput();
324
30.5k
  if ((m_state->m_isLibrary && !readLibraryHeader()) ||
325
30.5k
      (!m_state->m_isLibrary && !readDocHeader()))
326
143
    return false;
327
328
30.4k
  if (m_state->m_EOF>0)
329
23.8k
    input->pushLimit(m_state->m_EOF);
330
350k
  while (readZone());
331
30.4k
  if (!input->isEnd()) {
332
29.9k
    ascii().addPos(input->tell());
333
29.9k
    ascii().addNote("Entries(BAD)");
334
29.9k
  }
335
210M
  while (!input->isEnd()) {
336
210M
    long pos=input->tell();
337
210M
    if (input->readULong(4)!=0x44534554) {
338
209M
      input->seek(pos+1, librevenge::RVNG_SEEK_SET);
339
209M
      continue;
340
209M
    }
341
1.01M
    input->seek(pos, librevenge::RVNG_SEEK_SET);
342
1.01M
    long actPos=input->tell();
343
4.25M
    while (readZone())
344
3.23M
      actPos=input->tell();
345
1.01M
    if (actPos==pos) {
346
84.2k
      input->seek(actPos+4, librevenge::RVNG_SEEK_SET);
347
84.2k
      continue;
348
84.2k
    }
349
931k
    input->seek(actPos, librevenge::RVNG_SEEK_SET);
350
931k
    if (input->isEnd()) break;
351
910k
    MWAW_DEBUG_MSG(("ClarisDrawParser::createZones: oops loose tracks of zones\n"));
352
910k
    ascii().addPos(input->tell());
353
910k
    ascii().addNote("Entries(BAD):###");
354
910k
  }
355
30.4k
  if (m_state->m_EOF>0)
356
23.8k
    input->popLimit();
357
30.4k
  return true;
358
30.5k
}
359
360
bool ClarisDrawParser::readZone()
361
4.60M
{
362
4.60M
  MWAWInputStreamPtr input = getInput();
363
4.60M
  long pos=input->tell();
364
4.60M
  if (!input->checkPosition(pos+4))
365
21.3k
    return false;
366
4.58M
  auto zoneSz=long(input->readULong(4));
367
4.58M
  if (zoneSz==0x44534554) {
368
1.09M
    input->seek(pos, librevenge::RVNG_SEEK_SET);
369
1.09M
    return readDSET().get()!=nullptr;
370
1.09M
  }
371
3.49M
  else if (zoneSz==0x464e544d) {
372
18.9k
    input->seek(pos, librevenge::RVNG_SEEK_SET);
373
18.9k
    return m_styleManager->readFontNames();
374
18.9k
  }
375
3.47M
  else if ((zoneSz>>16)>16) {
376
852k
    input->seek(pos, librevenge::RVNG_SEEK_SET);
377
852k
    return false;
378
852k
  }
379
2.61M
  else if ((zoneSz>>16)!=0) {
380
100k
    ascii().addPos(pos);
381
100k
    ascii().addNote("Entries(Short)");
382
100k
    input->seek(pos+2, librevenge::RVNG_SEEK_SET);
383
100k
    return true;
384
100k
  }
385
2.51M
  long endPos=input->tell()+zoneSz;
386
2.51M
  if (zoneSz<0 || ((zoneSz&1) && (zoneSz==0x4453 || zoneSz==0x464e)) || !input->checkPosition(endPos)) {
387
72.1k
    input->seek(pos, librevenge::RVNG_SEEK_SET);
388
72.1k
    return false;
389
72.1k
  }
390
2.44M
  libmwaw::DebugStream f;
391
2.44M
  if (zoneSz==0)
392
2.22M
    f << "_";
393
220k
  else
394
220k
    f << "Entries(Unknown)";
395
2.44M
  ascii().addPos(pos);
396
2.44M
  ascii().addNote(f.str().c_str());
397
2.44M
  input->seek(endPos, librevenge::RVNG_SEEK_SET);
398
2.44M
  return true;
399
2.51M
}
400
401
bool ClarisDrawParser::readDocHeader()
402
5.25k
{
403
5.25k
  MWAWInputStreamPtr input = getInput();
404
5.25k
  if (!input->checkPosition(0x80A)) return false;
405
406
5.25k
  input->seek(8, librevenge::RVNG_SEEK_SET);
407
5.25k
  libmwaw::DebugStream f;
408
5.25k
  f << "Entries(DocHeader):";
409
5.25k
  auto val = static_cast<int>(input->readLong(2)); // always find 1
410
5.25k
  if (val != 1)
411
3.38k
    f << "#unkn=" << std::hex << val << std::dec << ",";
412
26.2k
  for (int i = 0; i < 4; i++) {
413
21.0k
    val = static_cast<int>(input->readULong(2));
414
21.0k
    if (val)
415
8.98k
      f << std::hex << "f" << i << "="  << std::hex << val << std::dec << ",";
416
21.0k
  }
417
5.25k
  int dim[2];
418
10.5k
  for (int &i : dim) i= static_cast<int>(input->readLong(2));
419
5.25k
  f << "dim?=" << dim[1] << "x" << dim[0] << ",";
420
5.25k
  int margin[6];
421
5.25k
  f << "margin?=[";
422
31.5k
  for (int &i : margin) {
423
31.5k
    i = static_cast<int>(input->readLong(2));
424
31.5k
    if (i)
425
12.8k
      f << i << ",";
426
18.6k
    else
427
18.6k
      f << "_,";
428
31.5k
  }
429
5.25k
  f << "],";
430
  // seems a good indication that slide mode is choosen
431
5.25k
  if (dim[0] > 0 && dim[1] > 0 &&
432
3.45k
      margin[0] >= 0 && margin[1] >= 0 && margin[2] >= 0 && margin[3] >= 0 &&
433
3.07k
      dim[0] > margin[0]+margin[2] && dim[1] > margin[1]+margin[3]) {
434
435
2.72k
    MWAWVec2i paperSize(dim[1],dim[0]);
436
2.72k
    MWAWVec2i lTopMargin(margin[1], margin[0]);
437
2.72k
    MWAWVec2i rBotMargin(margin[3], margin[2]);
438
439
2.72k
    getPageSpan().setMarginTop(lTopMargin.y()/72.0);
440
2.72k
    getPageSpan().setMarginBottom(rBotMargin.y()/72.0);
441
2.72k
    getPageSpan().setMarginLeft(lTopMargin.x()/72.0);
442
2.72k
    getPageSpan().setMarginRight(rBotMargin.x()/72.0);
443
2.72k
    getPageSpan().setFormLength(paperSize.y()/72.);
444
2.72k
    getPageSpan().setFormWidth(paperSize.x()/72.);
445
2.72k
    m_state->m_pageSpanSet = true;
446
2.72k
  }
447
5.25k
  int dim2[2];
448
10.5k
  for (int &i : dim2) i = static_cast<int>(input->readLong(2));
449
5.25k
  f << "dim2?=" << dim2[1] << "x" << dim2[0] << ",";
450
5.25k
  int fl[4];
451
5.25k
  f << "fl?=[";
452
21.0k
  for (int &i : fl) {
453
21.0k
    i = static_cast<int>(input->readULong(1));
454
21.0k
    if (i)
455
6.46k
      f << i << ",";
456
14.5k
    else
457
14.5k
      f << "_,";
458
21.0k
  }
459
5.25k
  f << "],";
460
52.5k
  for (int i = 0; i < 9; i++) {
461
47.2k
    val = static_cast<int>(input->readLong(2));
462
47.2k
    if (val)
463
6.60k
      f << "g" << i << "="  << val << ",";
464
47.2k
  }
465
466
5.25k
  ascii().addDelimiter(input->tell(), '|');
467
5.25k
  ascii().addPos(8);
468
5.25k
  ascii().addNote(f.str().c_str());
469
470
5.25k
  input->seek(8+132, librevenge::RVNG_SEEK_SET);
471
472
  /* zone 1 actual font, actul pos, .. */
473
5.25k
  if (!m_textParser->readParagraph())
474
0
    return false;
475
5.25k
  long pos = input->tell();
476
5.25k
  f.str("");
477
5.25k
  f << "DocHeader:zone?=" << input->readULong(2) << ",";
478
5.25k
  ascii().addPos(pos);
479
5.25k
  ascii().addNote(f.str().c_str());
480
5.25k
  MWAWFont font;
481
5.25k
  int posChar;
482
5.25k
  if (!m_textParser->readFont(-1, posChar, font))
483
0
    return false;
484
485
  /* zone 2, type, unknown */
486
5.25k
  pos = input->tell();
487
5.25k
  f.str("");
488
5.25k
  f << "DocHeader-1:";
489
36.7k
  for (int i = 0; i < 6; i++) {
490
31.5k
    val = static_cast<int>(input->readULong(2));
491
31.5k
    if (val) f << "f" << i << "=" << val << ",";
492
31.5k
  }
493
5.25k
  ascii().addDelimiter(input->tell(), '|');
494
5.25k
  input->seek(pos+20, librevenge::RVNG_SEEK_SET);
495
5.25k
  ascii().addPos(pos);
496
5.25k
  ascii().addNote(f.str().c_str());
497
498
  // the document font ?
499
5.25k
  if (!m_textParser->readFont(-1, posChar, font))
500
0
    return false;
501
502
5.25k
  pos=input->tell();
503
5.25k
  f.str("");
504
5.25k
  f << "DocHeader-2:";
505
31.5k
  for (int i=0; i<5; ++i) {
506
26.2k
    val=static_cast<int>(input->readULong(2));
507
26.2k
    static int const expected[] = {0,1,2,2,0};
508
26.2k
    if (val!=expected[i])
509
14.7k
      f << "f" << i << "=" << val << ",";
510
26.2k
  }
511
47.2k
  for (int i=0; i<8; ++i) {
512
42.0k
    val=static_cast<int>(input->readULong(1));
513
42.0k
    static int const expected[] = {1/*or 16*/,0,0,0,0,1,1, 0};
514
42.0k
    if (val!=expected[i])
515
16.9k
      f << "f" << i+5 << "=" << val << ",";
516
42.0k
  }
517
26.2k
  for (int i=0; i<4; ++i) {
518
21.0k
    val=static_cast<int>(input->readULong(2));
519
21.0k
    static int const expected[] = {1,1,0x2d,0};
520
21.0k
    if (val!=expected[i])
521
11.6k
      f << "f" << i+13 << "=" << val << ",";
522
21.0k
  }
523
5.25k
  f << "fl=[";
524
73.5k
  for (int i=0; i<13; ++i) {
525
68.3k
    val=static_cast<int>(input->readULong(1));
526
68.3k
    if (val==1) f << "*,";
527
48.8k
    else if (val) f << val << ",";
528
32.0k
    else f << "_,";
529
68.3k
  }
530
5.25k
  f << "],";
531
89.3k
  for (int i=0; i<16; ++i) { // always 0
532
84.0k
    val=static_cast<int>(input->readULong(2));
533
84.0k
    if (val)
534
28.1k
      f << "g" << i << "=" << val << ",";
535
84.0k
  }
536
31.5k
  for (int i=0; i<5; ++i) {
537
26.2k
    val=static_cast<int>(input->readULong(2));
538
26.2k
    static int const expected[] = {0,1,0,0x600,0x504};
539
26.2k
    if (val!=expected[i])
540
14.3k
      f << "h" << i << "=" << std::hex << val << std::dec << ",";
541
26.2k
  }
542
5.25k
  val=static_cast<int>(input->readULong(1)); // always 0
543
5.25k
  if (val) f << "h5=" << val << ",";
544
5.25k
  int num[3];
545
21.0k
  for (int i=0; i<3; ++i) {
546
15.7k
    num[i]=static_cast<int>(input->readULong(2));
547
15.7k
    if (!num[i])
548
5.09k
      continue;
549
10.6k
    static char const* const wh[]= {"color", "unkn1", "gradient"};
550
10.6k
    f << "num[" << wh[i] << "]=" << num[i] << ",";
551
10.6k
  }
552
5.25k
  m_styleManager->setDefaultNumbers(num[0], num[2]);
553
554
5.25k
  ascii().addDelimiter(input->tell(),'|');
555
5.25k
  ascii().addPos(pos);
556
5.25k
  ascii().addNote(f.str().c_str());
557
5.25k
  input->seek(pos+124, librevenge::RVNG_SEEK_SET);
558
559
5.25k
  pos=input->tell();
560
5.25k
  f.str("");
561
5.25k
  f << "DocHeader(Col):";
562
5.25k
  auto numCols = static_cast<int>(input->readLong(2));
563
5.25k
  if (numCols < 1 || numCols > 9) {
564
3.17k
    MWAW_DEBUG_MSG(("ClarisDrawParser::readDocHeader: pb reading number of columns\n"));
565
3.17k
    f << "###numCols=" << numCols;
566
3.17k
    numCols = 1;
567
3.17k
  }
568
5.25k
  if (numCols != 1)
569
196
    f << "numCols=" << numCols << ",";
570
5.25k
  f << "colsW=[";
571
11.2k
  for (int i = 0; i < numCols; i++) {
572
5.96k
    val = static_cast<int>(input->readULong(2));
573
5.96k
    f << val << ",";
574
5.96k
  }
575
5.25k
  f << "],";
576
5.25k
  input->seek(pos+20, librevenge::RVNG_SEEK_SET);
577
5.25k
  if (numCols > 1) {
578
196
    f << "colsS=[";
579
905
    for (int i = 0; i < numCols-1; i++) {
580
709
      val = static_cast<int>(input->readULong(2));
581
709
      f << input->readULong(2);
582
709
      if (val) f << ":" << val << ",";
583
709
    }
584
196
    f << "],";
585
196
  }
586
5.25k
  input->seek(pos+36, librevenge::RVNG_SEEK_SET);
587
5.25k
  val = static_cast<int>(input->readLong(2));
588
5.25k
  if (val) f << "unkn=" << val << ",";
589
5.25k
  ascii().addPos(pos);
590
5.25k
  ascii().addNote(f.str().c_str());
591
592
5.25k
  pos=input->tell();
593
5.25k
  input->seek(pos+214, librevenge::RVNG_SEEK_SET);
594
5.25k
  ascii().addPos(pos);
595
5.25k
  ascii().addNote("DocHeader-3");
596
597
5.25k
  pos=input->tell(); // only 0?
598
5.25k
  input->seek(pos+256, librevenge::RVNG_SEEK_SET);
599
5.25k
  ascii().addPos(pos);
600
5.25k
  ascii().addNote("DocHeader-4");
601
602
5.25k
  pos=input->tell();
603
5.25k
  input->seek(pos+190, librevenge::RVNG_SEEK_SET);
604
5.25k
  ascii().addPos(pos);
605
5.25k
  ascii().addNote("DocHeader-5");
606
607
5.25k
  pos=input->tell(); // only 0?
608
5.25k
  input->seek(pos+256, librevenge::RVNG_SEEK_SET);
609
5.25k
  ascii().addPos(pos);
610
5.25k
  ascii().addNote("DocHeader-6");
611
612
5.25k
  pos=input->tell();
613
5.25k
  input->seek(pos+256+96, librevenge::RVNG_SEEK_SET);
614
5.25k
  ascii().addPos(pos);
615
5.25k
  ascii().addNote("DocHeader-7");
616
617
5.25k
  pos=input->tell();
618
5.25k
  f.str("");
619
5.25k
  f << "DocHeader-8:";
620
5.25k
  input->seek(pos+111, librevenge::RVNG_SEEK_SET);
621
5.25k
  val=static_cast<int>(input->readLong(1));
622
5.25k
  if (val==1) {
623
1.02k
    f << "slide,";
624
1.02k
    m_state->m_displayAsSlide=true;
625
1.02k
  }
626
4.23k
  else if (val) {
627
1.63k
    MWAW_DEBUG_MSG(("ClarisDrawParser::readDocHeader: pb reading the viewer style\n"));
628
1.63k
    f << "###slide=" << val << ",";
629
1.63k
  }
630
5.25k
  input->seek(pos+150, librevenge::RVNG_SEEK_SET);
631
5.25k
  ascii().addPos(pos);
632
5.25k
  ascii().addNote(f.str().c_str());
633
634
5.25k
  pos=input->tell();
635
5.25k
  input->seek(pos+130, librevenge::RVNG_SEEK_SET);
636
5.25k
  ascii().addPos(pos);
637
5.25k
  ascii().addNote("DocHeader-9");
638
639
5.25k
  pos=input->tell();
640
5.25k
  ascii().addPos(pos);
641
5.25k
  ascii().addNote("DocHeader-A");
642
643
5.25k
  input->seek(0x80A, librevenge::RVNG_SEEK_SET);
644
  // now 25 zones
645
66.2k
  for (int i=0; i<25; ++i) {
646
64.2k
    if (input->isEnd())
647
128
      return false;
648
64.0k
    pos=input->tell();
649
64.0k
    auto zoneSz=long(input->readULong(4));
650
64.0k
    if (!zoneSz) {
651
36.0k
      ascii().addPos(pos);
652
36.0k
      ascii().addNote("_");
653
36.0k
      continue;
654
36.0k
    }
655
28.0k
    if (!input->checkPosition(pos+4+zoneSz)) {
656
3.04k
      MWAW_DEBUG_MSG(("ClarisDrawParser::readDocHeader: can not find zone %d\n", i+1));
657
3.04k
      ascii().addPos(pos);
658
3.04k
      ascii().addNote("###");
659
3.04k
      input->seek(pos, librevenge::RVNG_SEEK_SET);
660
3.04k
      return true;
661
3.04k
    }
662
24.9k
    input->seek(pos, librevenge::RVNG_SEEK_SET);
663
24.9k
    bool done=false;
664
24.9k
    switch (i+1) {
665
2.39k
    case 1:
666
2.39k
      done=m_textParser->readParagraphs();
667
2.39k
      break;
668
2.08k
    case 2:
669
2.08k
      done=readPrintInfo();
670
2.08k
      break;
671
200
    case 3:
672
200
      done=m_styleManager->readPatternList();
673
200
      break;
674
1.10k
    case 4:
675
1.10k
      done=m_styleManager->readGradientList();
676
1.10k
      break;
677
2.05k
    case 6:
678
2.05k
      done=m_styleManager->readFontStyles();
679
2.05k
      break;
680
1.80k
    case 8: // never seens data: fieldData=4, headerSize=14 (always 1,5,0,100,101,0,101,0,1,12710?)
681
1.80k
      done = ClarisWksStruct::readStructZone(*getParserState(), "Zone8A", false);
682
1.80k
      break;
683
1.80k
    case 9: // never seens data: fieldData=12, headerSize=4 (1,id)
684
1.80k
      done = ClarisWksStruct::readStructZone(*getParserState(), "Zone9A", false);
685
1.80k
      break;
686
1.79k
    case 10: // never seens data: fieldData=4, headerSize=4 (1,id)
687
1.79k
      done = ClarisWksStruct::readStructZone(*getParserState(), "Zone10A", false);
688
1.79k
      break;
689
    // CHECKME
690
1.76k
    case 16: // Arrow
691
1.76k
      done=m_styleManager->readArrows();
692
1.76k
      break;
693
1.76k
    case 17: // Dash
694
1.76k
      done=m_styleManager->readDashs();
695
1.76k
      break;
696
1.68k
    case 18: // Ruler style
697
1.68k
      done=m_styleManager->readRulers();
698
1.68k
      break;
699
901
    case 20:
700
901
      done = m_graphParser->readTransformations();
701
901
      break;
702
1.64k
    case 21: // fieldData=36
703
1.64k
      done = ClarisWksStruct::readStructZone(*getParserState(), "Zone21A", false);
704
1.64k
      break;
705
1.63k
    case 22: // fieldData=4, headerSize=4 (1, consecutive id)
706
1.63k
      done = ClarisWksStruct::readStructZone(*getParserState(), "Zone22A", false);
707
1.63k
      break;
708
2.32k
    default:
709
2.32k
      break;
710
24.9k
    }
711
24.9k
    if (done) continue;
712
4.23k
    f.str("");
713
4.23k
    f << "Entries(Zone" << i+1 << "A):";
714
4.23k
    ascii().addPos(pos);
715
4.23k
    ascii().addNote(f.str().c_str());
716
4.23k
    input->seek(pos+4+zoneSz, librevenge::RVNG_SEEK_SET);
717
4.23k
  }
718
719
2.08k
  pos=input->tell();
720
2.08k
  if (!readDocInfo()) {
721
33
    input->seek(pos, librevenge::RVNG_SEEK_SET);
722
33
    return true;
723
33
  }
724
2.05k
  pos=input->tell();
725
2.05k
  if (!readLayouts()) {
726
118
    MWAW_DEBUG_MSG(("ClarisDrawParser::readDocHeader: can not find layout zone\n"));
727
118
    input->seek(pos, librevenge::RVNG_SEEK_SET);
728
118
    return true;
729
118
  }
730
1.93k
  pos=input->tell();
731
1.93k
  input->seek(pos+4, librevenge::RVNG_SEEK_SET);
732
1.93k
  if (input->readULong(2)!=0x100) {
733
740
    MWAW_DEBUG_MSG(("ClarisDrawParser::readDocHeader: can not find UnknZone zone\n"));
734
740
    input->seek(pos, librevenge::RVNG_SEEK_SET);
735
740
    return true;
736
740
  }
737
1.19k
  ascii().addPos(pos);
738
1.19k
  ascii().addNote("Entries(UnknZone0)");
739
1.19k
  input->seek(pos+832, librevenge::RVNG_SEEK_SET);
740
741
  // now 12 zones
742
13.1k
  for (int i=0; i<12; ++i) {
743
12.3k
    if (input->isEnd())
744
15
      return false;
745
12.3k
    pos=input->tell();
746
12.3k
    auto zoneSz=long(input->readULong(4));
747
12.3k
    if (!zoneSz) {
748
8.77k
      ascii().addPos(pos);
749
8.77k
      ascii().addNote("_");
750
8.77k
      continue;
751
8.77k
    }
752
3.57k
    if (!input->checkPosition(pos+4+zoneSz)) {
753
445
      MWAW_DEBUG_MSG(("ClarisDrawParser::readDocHeader: can not find zone %d\n", i+1));
754
445
      ascii().addPos(pos);
755
445
      ascii().addNote("###");
756
445
      input->seek(pos, librevenge::RVNG_SEEK_SET);
757
445
      return true;
758
445
    }
759
3.13k
    input->seek(pos, librevenge::RVNG_SEEK_SET);
760
3.13k
    bool done=false;
761
3.13k
    switch (i+1) {
762
979
    case 1: // never seens data: fieldData=4, headerSize=4 (1,id)
763
979
      done = ClarisWksStruct::readStructZone(*getParserState(), "ZoneB1A", false);
764
979
      break;
765
946
    case 3: // never seens data: fieldData=6, headerSize=0
766
946
      done = ClarisWksStruct::readStructZone(*getParserState(), "ZoneB3A", false);
767
946
      break;
768
21
    case 4:// never seens data: fieldData=14, headerSize=0
769
21
      done = ClarisWksStruct::readStructZone(*getParserState(), "ZoneB4A", false);
770
21
      break;
771
28
    case 5:// never seens data: fieldData=14, headerSize=0
772
28
      done = ClarisWksStruct::readStructZone(*getParserState(), "ZoneB5A", false);
773
28
      break;
774
34
    case 6:// never seens data: fieldData=8, headerSize=80
775
34
      done = ClarisWksStruct::readStructZone(*getParserState(), "ZoneB6A", false);
776
34
      break;
777
27
    case 7:// never seens data: fieldData=28, headerSize=80
778
27
      done = ClarisWksStruct::readStructZone(*getParserState(), "ZoneB7A", false);
779
27
      break;
780
30
    case 8:// never seens data: fieldData=1e, headerSize=0
781
30
      done = ClarisWksStruct::readStructZone(*getParserState(), "ZoneB8A", false);
782
30
      break;
783
64
    case 9:// TODO: fieldData=1c (2*double+), headerSize=0
784
64
      done = ClarisWksStruct::readStructZone(*getParserState(), "ZoneB9A", false);
785
64
      break;
786
924
    case 10:
787
924
      done = m_styleManager->readColorList();
788
924
      break;
789
25
    case 11:// never seens data: fieldData=c, headerSize=0
790
25
      done = ClarisWksStruct::readStructZone(*getParserState(), "ZoneB11A", false);
791
25
      break;
792
26
    case 12:// never seens data: fieldData=32, headerSize=0
793
26
      done = ClarisWksStruct::readStructZone(*getParserState(), "ZoneB12A", false);
794
26
      break;
795
30
    default:
796
30
      break;
797
3.13k
    }
798
3.13k
    if (done) continue;
799
415
    f.str("");
800
415
    f << "Entries(ZoneB" << i+1 << "A):";
801
415
    ascii().addPos(pos);
802
415
    ascii().addNote(f.str().c_str());
803
415
    input->seek(pos+4+zoneSz, librevenge::RVNG_SEEK_SET);
804
415
  }
805
732
  pos=input->tell();
806
732
  f.str("");
807
732
  f << "Entries(NDSET):";
808
732
  m_state->m_numDSET=static_cast<int>(input->readLong(2));
809
732
  if (m_state->m_numDSET) f << "num=" << m_state->m_numDSET << ",";
810
732
  ascii().addPos(pos);
811
732
  ascii().addNote(f.str().c_str());
812
813
732
  return true;
814
1.19k
}
815
816
bool ClarisDrawParser::readLibraryHeader()
817
25.3k
{
818
25.3k
  MWAWInputStreamPtr input = getInput();
819
25.3k
  libmwaw::DebugStream f;
820
25.3k
  f << "Entries(LibHeader):";
821
25.3k
  if (!input->checkPosition(846)) return false;
822
25.3k
  input->seek(8, librevenge::RVNG_SEEK_SET);
823
25.3k
  long val=input->readLong(4); // always 0
824
25.3k
  if (val) f << "f0=" << val << ",";
825
25.3k
  f << "ID=" << std::hex << input->readULong(4) << std::dec << ","; // a big number
826
25.3k
  val=input->readLong(2); // always 0x100
827
25.3k
  if (val!=0x100) f << "f1=" << val << ",";
828
151k
  for (int i=0; i<5; ++i) { // always 0
829
126k
    val=input->readLong(2);
830
126k
    if (val) f << "f" << i+2 << "=" << val << ",";
831
126k
  }
832
25.3k
  auto N=static_cast<int>(input->readLong(2)); // checkme: the number of graphics ?
833
25.3k
  if (N) f << "N=" << N << ",";
834
75.9k
  for (long i=0; i<2; ++i) { // always 0,1
835
50.6k
    val=input->readLong(2);
836
50.6k
    if (val!=i) f << "f" << i+7 << "=" << val << ",";
837
50.6k
  }
838
25.3k
  f << "ID1=[";
839
75.9k
  for (int i=0; i<2; ++i) { // two big number
840
50.6k
    f << std::hex << input->readULong(4) << std::dec << ",";
841
50.6k
  }
842
25.3k
  f << "],";
843
25.3k
  val=input->readLong(2); // always 0x100
844
25.3k
  if (val!=0x100) f << "f9=" << val << ",";
845
25.3k
  val=input->readLong(2); // always 0
846
25.3k
  if (val) f << "f10=" << val << ",";
847
25.3k
  f << "ID2=" << std::hex << input->readULong(4) << std::dec << ","; // another big number
848
1.44M
  for (int i=0; i<56; ++i) { // always 0
849
1.41M
    val=input->readLong(2);
850
1.41M
    if (val) f << "g" << i << "=" << val << ",";
851
1.41M
  }
852
25.3k
  ascii().addPos(8);
853
25.3k
  ascii().addNote(f.str().c_str());
854
855
25.3k
  long pos=input->tell();
856
25.3k
  f.str("");
857
25.3k
  f << "LibHeader-A:";
858
75.9k
  for (int i=0; i<2; ++i) { // f1=54,5c|5d
859
50.6k
    val=input->readLong(2);
860
50.6k
    if (val) f << "f" << i << "=" << val << ",";
861
50.6k
  }
862
25.3k
  f << "IDs=[";
863
253k
  for (int i=0; i<9; ++i) { // 7 or 9 big number
864
227k
    val=long(input->readULong(4));
865
227k
    if (val)
866
182k
      f << std::hex << val << std::dec << ",";
867
45.8k
    else
868
45.8k
      f << "_,";
869
227k
  }
870
25.3k
  f << "],";
871
177k
  for (int i=0; i<6; ++i) { // always 0
872
151k
    val=input->readLong(2);
873
151k
    if (val) f << "f" << i+2 << "=" << val << ",";
874
151k
  }
875
75.9k
  for (int i=0; i<2; ++i) {
876
50.6k
    f << "unkn" << i << "=[";
877
151k
    for (int j=0; j<2; ++j) { // _, small number
878
101k
      val=input->readLong(2);
879
101k
      if (val)
880
70.2k
        f << val << ",";
881
31.0k
      else
882
31.0k
        f << "_,";
883
101k
    }
884
50.6k
    f << std::hex << input->readULong(4) << std::dec << ","; // big number or 0
885
50.6k
    f << "],";
886
50.6k
  }
887
683k
  for (int i=0; i<26; ++i) { // always 0
888
658k
    val=input->readLong(2);
889
658k
    if (val) f << "g" << i << "=" << val << ",";
890
658k
  }
891
25.3k
  ascii().addPos(pos);
892
25.3k
  ascii().addNote(f.str().c_str());
893
894
25.3k
  pos=input->tell();
895
25.3k
  f.str("");
896
25.3k
  f << "LibHeader-B:";
897
25.3k
  auto fSz=static_cast<int>(input->readULong(1));
898
25.3k
  if (fSz>63) {
899
8.22k
    MWAW_DEBUG_MSG(("ClarisDrawParser::readLibraryHeader: string size seems bad\n"));
900
8.22k
    f << "##fSz=" << fSz << ",";
901
8.22k
    fSz=0;
902
8.22k
  }
903
25.3k
  std::string text("");
904
131k
  for (int i=0; i<fSz; ++i) text+=char(input->readULong(1));
905
25.3k
  f << "filename=" << text << ",";
906
25.3k
  input->seek(pos+64, librevenge::RVNG_SEEK_SET);
907
2.45M
  for (int i=0; i<96; ++i) { // always 0
908
2.43M
    val=input->readLong(2);
909
2.43M
    if (val) f << "f" << i << "=" << val << ",";
910
2.43M
  }
911
25.3k
  val=static_cast<int>(input->readULong(1)); // always filename size ?
912
25.3k
  if (val!=fSz) f << "#fSz1=" << fSz << ",";
913
25.3k
  val=static_cast<int>(input->readULong(1)); // always 0?
914
25.3k
  if (val) f << "f96=" << val << ",";
915
25.3k
  f << "ID=" << std::hex << input->readULong(4) << std::dec << ","; // big number
916
25.3k
  val=static_cast<int>(input->readLong(2)); // 0 | 0fcc
917
25.3k
  if (val) f << "g0=" << val << ",";
918
25.3k
  val=static_cast<int>(input->readULong(2)); //  80[89]3
919
25.3k
  if (val) f << "fl=" << std::hex << val << std::dec << ",";
920
25.3k
  val=static_cast<int>(input->readLong(2)); // 0
921
25.3k
  if (val) f << "g1=" << val << ",";
922
25.3k
  val=static_cast<int>(input->readULong(1)); // always filename size ?
923
25.3k
  if (val!=fSz) f << "#fSz2=" << fSz << ",";
924
25.3k
  val=static_cast<int>(input->readULong(1)); // always 0?
925
25.3k
  if (val) f << "g2=" << val << ",";
926
25.3k
  ascii().addPos(pos);
927
25.3k
  ascii().addNote(f.str().c_str());
928
929
25.3k
  pos=input->tell();
930
25.3k
  f.str("");
931
25.3k
  f << "LibHeader-C:";
932
25.3k
  fSz=static_cast<int>(input->readULong(1));
933
25.3k
  if (fSz>63) {
934
7.21k
    MWAW_DEBUG_MSG(("ClarisDrawParser::readLibraryHeader: string size seems bad\n"));
935
7.21k
    f << "##fSz=" << fSz << ",";
936
7.21k
    fSz=0;
937
7.21k
  }
938
25.3k
  text="";
939
129k
  for (int i=0; i<fSz; ++i) text+=char(input->readULong(1));
940
25.3k
  f << "author?=" << text << ",";
941
25.3k
  input->seek(pos+64, librevenge::RVNG_SEEK_SET);
942
2.45M
  for (int i=0; i<96; ++i) { // always 0
943
2.43M
    val=input->readLong(2);
944
2.43M
    if (val) f << "f" << i << "=" << val << ",";
945
2.43M
  }
946
25.3k
  ascii().addPos(pos);
947
25.3k
  ascii().addNote(f.str().c_str());
948
949
25.3k
  pos=input->tell();
950
25.3k
  f.str("");
951
25.3k
  f << "LibHeader-D:";
952
430k
  for (int i=0; i<16; ++i) {
953
405k
    val=static_cast<int>(input->readLong(2));
954
405k
    static int const expected[]= {4,2,0/*35 or 3f*/,48, 9, 0/*78 or 8x*/, 0x42, 18,
955
405k
                                  3, 0xd4, 0/*7b or 8e*/, 0x57, 3, 0xc4, 0/*7b or 8f*/, 0
956
405k
                                 };
957
405k
    if (val!=expected[i])
958
361k
      f << "f" << i << "=" << val << ",";
959
405k
  }
960
25.3k
  int dim[2];
961
50.6k
  for (auto &i : dim) i=static_cast<int>(input->readLong(2));
962
25.3k
  f << "dim=" << MWAWVec2i(dim[0],dim[1]) << ","; // 64x64 or 72x72
963
25.3k
  m_state->m_numDSET=static_cast<int>(input->readLong(2));
964
25.3k
  if (m_state->m_numDSET) f << "num[DSET]=" << m_state->m_numDSET << ",";
965
25.3k
  ascii().addPos(pos);
966
25.3k
  ascii().addNote(f.str().c_str());
967
968
25.3k
  input->seek(846, librevenge::RVNG_SEEK_SET);
969
  // the style are coded after the DSET zones, let try to find them
970
25.3k
  input->seek(-44, librevenge::RVNG_SEEK_END);
971
5.07M
  while (input->tell()>=846) {
972
5.06M
    pos=input->tell();
973
5.06M
    auto c=static_cast<int>(input->readULong(1));
974
5.06M
    bool find=false;
975
5.06M
    switch (c) {
976
50.2k
    case 0x44:
977
50.2k
      input->seek(pos, librevenge::RVNG_SEEK_SET);
978
50.2k
      if (readDSET(pos==846))
979
23.8k
        find=true;
980
26.4k
      else
981
26.4k
        input->seek(pos-4, librevenge::RVNG_SEEK_SET);
982
50.2k
      break;
983
24.7k
    case 0x53:
984
24.7k
      input->seek(pos-1, librevenge::RVNG_SEEK_SET);
985
24.7k
      break;
986
25.7k
    case 0x45:
987
25.7k
      input->seek(pos-2, librevenge::RVNG_SEEK_SET);
988
25.7k
      break;
989
17.7k
    case 0x54:
990
17.7k
      input->seek(pos-3, librevenge::RVNG_SEEK_SET);
991
17.7k
      break;
992
4.95M
    default:
993
4.95M
      input->seek(pos-4, librevenge::RVNG_SEEK_SET);
994
4.95M
      break;
995
5.06M
    }
996
5.06M
    if (!find)
997
5.04M
      continue;
998
23.8k
    m_state->m_EOF=input->tell();
999
    // clean storage
1000
23.8k
    m_graphParser->resetState();
1001
23.8k
    m_textParser->resetState();
1002
23.8k
    m_state->m_zonesMap.clear();
1003
23.8k
    m_state->m_zoneIdToFileTypeMap.clear();
1004
46.4k
    while (!input->isEnd()) {
1005
45.1k
      pos=input->tell();
1006
45.1k
      if (input->readULong(4)) {
1007
22.4k
        input->seek(pos, librevenge::RVNG_SEEK_SET);
1008
22.4k
        break;
1009
22.4k
      }
1010
22.6k
      ascii().addPos(pos);
1011
22.6k
      ascii().addNote("_");
1012
22.6k
    }
1013
23.8k
    pos=input->tell();
1014
23.8k
    bool ok=true;
1015
23.8k
    if (!m_textParser->readParagraphs()) {
1016
23.0k
      MWAW_DEBUG_MSG(("ClarisDrawParser::readLibraryHeader: can not read the paragraph style\n"));
1017
23.0k
      ascii().addPos(pos);
1018
23.0k
      ascii().addNote("Entries(RULR):###");
1019
23.0k
      ok=false;
1020
23.0k
    }
1021
28.2k
    for (int i=0; ok && i<20; ++i) {
1022
5.13k
      pos=input->tell();
1023
5.13k
      auto dSz=long(input->readULong(4));
1024
5.13k
      if (!dSz) {
1025
3.03k
        ascii().addPos(pos);
1026
3.03k
        ascii().addNote("_");
1027
3.03k
        continue;
1028
3.03k
      }
1029
2.09k
      if (!input->checkPosition(pos+4+dSz)) {
1030
647
        MWAW_DEBUG_MSG(("ClarisDrawParser::readLibraryHeader: can not find style zone %d\n", i+1));
1031
647
        ascii().addPos(pos);
1032
647
        ascii().addNote("###");
1033
647
        break;
1034
647
      }
1035
1.45k
      bool done=false;
1036
1.45k
      input->seek(pos, librevenge::RVNG_SEEK_SET);
1037
1.45k
      switch (i+1) {
1038
96
      case 1:
1039
96
        done=m_styleManager->readArrows();
1040
96
        break;
1041
71
      case 2:
1042
71
        done=m_styleManager->readDashs();
1043
71
        break;
1044
210
      case 3:
1045
210
        done=m_styleManager->readPatternList();
1046
210
        break;
1047
79
      case 4:
1048
79
        done=m_styleManager->readGradientList();
1049
79
        break;
1050
271
      case 5:
1051
271
        done = m_graphParser->readTransformations();
1052
271
        break;
1053
132
      case 6:
1054
132
        done = m_styleManager->readRulers();
1055
132
        break;
1056
182
      case 7: // two zones: pos and names
1057
182
        done = readLibraryNames();
1058
182
        break;
1059
100
      case 8:
1060
100
        done = m_styleManager->readColorList();
1061
100
        break;
1062
49
      case 9: // maybe zone 24
1063
49
        done = ClarisWksStruct::readStructZone(*getParserState(), "Style10A", false);
1064
49
        break;
1065
45
      case 10: // maybe zone 25
1066
45
        done = ClarisWksStruct::readStructZone(*getParserState(), "Style11A", false);
1067
45
        break;
1068
31
      case 11: // maybe readfontnames without header
1069
31
        done = ClarisWksStruct::readStructZone(*getParserState(), "Style12A", false);
1070
31
        break;
1071
185
      default:
1072
185
        break;
1073
1.45k
      }
1074
1.45k
      if (done) continue;
1075
1.27k
      f.str("");
1076
1.27k
      f << "Entries(Style" << i+1 << "A):";
1077
1.27k
      ascii().addPos(pos);
1078
1.27k
      ascii().addNote(f.str().c_str());
1079
1.27k
      input->seek(pos+4+dSz, librevenge::RVNG_SEEK_SET);
1080
1.27k
    }
1081
23.8k
    break;
1082
23.8k
  }
1083
25.3k
  input->seek(846, librevenge::RVNG_SEEK_SET);
1084
25.3k
  if (!readDSET(true)) {
1085
24.7k
    MWAW_DEBUG_MSG(("ClarisDrawParser::readLibraryHeader:can not read main group\n"));
1086
24.7k
    input->seek(846, librevenge::RVNG_SEEK_SET);
1087
24.7k
  }
1088
25.3k
  return true;
1089
25.3k
}
1090
1091
////////////////////////////////////////////////////////////
1092
// read the header
1093
////////////////////////////////////////////////////////////
1094
bool ClarisDrawParser::checkHeader(MWAWHeader *header, bool /*strict*/)
1095
99.2k
{
1096
99.2k
  *m_state = ClarisDrawParserInternal::State();
1097
99.2k
  MWAWInputStreamPtr input = getInput();
1098
99.2k
  if (!input || !input->hasDataFork() || !input->checkPosition(846))
1099
246
    return false;
1100
1101
99.0k
  libmwaw::DebugStream f;
1102
99.0k
  f << "FileHeader:";
1103
99.0k
  input->seek(0, librevenge::RVNG_SEEK_SET);
1104
99.0k
  auto val=static_cast<int>(input->readULong(1));
1105
99.0k
  if (val==0x2) {
1106
81.6k
    m_state->m_isLibrary=true;
1107
81.6k
    f << "lib,";
1108
81.6k
  }
1109
17.3k
  else if (val==0x1) {
1110
17.2k
    if (!input->checkPosition(0x80A))
1111
67
      return false;
1112
17.2k
  }
1113
72
  else
1114
72
    return false;
1115
98.8k
  val=static_cast<int>(input->readULong(2)); // a3-b1
1116
98.8k
  if (val) f << "f0=" << std::hex << val << std::dec << ",";
1117
98.8k
  if (input->readULong(1) || input->readULong(4) != 0x45585057) return false;
1118
98.7k
  int vers=1;
1119
98.7k
  setVersion(vers);
1120
98.7k
  m_state->m_version=vers;
1121
98.7k
  if (header)
1122
37.5k
    header->reset(MWAWDocument::MWAW_T_CLARISDRAW, vers, MWAWDocument::MWAW_K_DRAW);
1123
98.7k
  input->seek(8,librevenge::RVNG_SEEK_SET);
1124
98.7k
  ascii().addPos(0);
1125
98.7k
  ascii().addNote(f.str().c_str());
1126
1127
98.7k
  return true;
1128
98.8k
}
1129
1130
////////////////////////////////////////////////////////////
1131
// read the layout
1132
////////////////////////////////////////////////////////////
1133
bool ClarisDrawParser::readLayouts()
1134
2.05k
{
1135
2.05k
  MWAWInputStreamPtr input = getInput();
1136
2.05k
  long pos=input->tell();
1137
2.05k
  libmwaw::DebugFile &ascFile = ascii();
1138
2.05k
  libmwaw::DebugStream f;
1139
2.05k
  f << "Entries(Layout):";
1140
2.05k
  ClarisWksStruct::Struct header;
1141
2.05k
  if (!header.readHeader(input,true)) {
1142
118
    MWAW_DEBUG_MSG(("ClarisDrawParser::readLayouts: the data size seems bad\n"));
1143
118
    f << "###";
1144
118
    ascFile.addPos(pos);
1145
118
    ascFile.addNote(f.str().c_str());
1146
118
    return false;
1147
118
  }
1148
1.93k
  if (header.m_size==0) {
1149
342
    ascFile.addPos(pos);
1150
342
    ascFile.addNote("_");
1151
342
    return true;
1152
342
  }
1153
1.59k
  long endPos = pos+4+header.m_size;
1154
1.59k
  f << header;
1155
1.59k
  if (header.m_headerSize) {
1156
7
    ascFile.addDelimiter(input->tell(),'|');
1157
7
    input->seek(header.m_headerSize, librevenge::RVNG_SEEK_CUR);
1158
7
  }
1159
1.59k
  ascFile.addPos(pos);
1160
1.59k
  ascFile.addNote(f.str().c_str());
1161
1162
1.59k
  pos=input->tell();
1163
1.59k
  if (header.m_dataSize!=336) {
1164
14
    input->seek(endPos, librevenge::RVNG_SEEK_SET);
1165
14
    MWAW_DEBUG_MSG(("ClarisDrawParser::readLayouts: no sure how to read the data\n"));
1166
14
    ascFile.addPos(pos);
1167
14
    ascFile.addNote("Layout:###");
1168
14
    return true;
1169
14
  }
1170
7.05k
  for (long i=0; i<header.m_numData; ++i) {
1171
5.47k
    pos=input->tell();
1172
5.47k
    ClarisDrawParserInternal::Layer layer;
1173
5.47k
    f.str("");
1174
5.47k
    f << "Layout-A" << i << ":";
1175
5.47k
    auto cSz=static_cast<int>(input->readULong(1));
1176
5.47k
    librevenge::RVNGString name("");
1177
100k
    for (int c=0; c<cSz; ++c) {
1178
95.2k
      auto ch=char(input->readULong(1));
1179
95.2k
      if (!ch) continue;
1180
75.1k
      f << ch;
1181
75.1k
      int unicode= getParserState()->m_fontConverter->unicode(3, static_cast<unsigned char>(ch));
1182
75.1k
      if (unicode==-1)
1183
6.37k
        name.append(ch);
1184
68.7k
      else
1185
68.7k
        libmwaw::appendUnicode(static_cast<uint32_t>(unicode), name);
1186
75.1k
    }
1187
5.47k
    f << ",";
1188
5.47k
    layer.m_name=name;
1189
5.47k
    ascFile.addPos(pos);
1190
5.47k
    ascFile.addNote(f.str().c_str());
1191
1192
5.47k
    input->seek(pos+256, librevenge::RVNG_SEEK_SET);
1193
5.47k
    pos=input->tell();
1194
5.47k
    f.str("");
1195
5.47k
    f << "Layout-B" << i << ":";
1196
5.47k
    auto val=static_cast<int>(input->readULong(1)); // always 40|80
1197
5.47k
    if (val&0x80) {
1198
194
      f << "hidden,";
1199
194
      layer.m_isHidden=true;
1200
194
    }
1201
5.47k
    val &=0x7F;
1202
5.47k
    if (val!=0x40) f << "fl0=" << std::hex << val << std::dec << ",";
1203
5.47k
    val=static_cast<int>(input->readULong(1)); // 0|1|2|6c|d8|fc|ff
1204
5.47k
    if (val) f << "fl1=" << std::hex << val << std::dec << ",";
1205
16.4k
    for (int j=0; j<2; ++j) { // always 0
1206
10.9k
      val=static_cast<int>(input->readULong(2));
1207
10.9k
      if (val) f << "f" << j << "=" << val << ",";
1208
10.9k
    }
1209
5.47k
    layer.m_groupId=static_cast<int>(input->readULong(2));
1210
5.47k
    f << "id[group]=" << layer.m_groupId << ",";
1211
5.47k
    val=static_cast<int>(input->readLong(4));
1212
5.47k
    if (val==-1)
1213
2
      f << "locked,";
1214
5.47k
    else if (val)
1215
1.81k
      f << "#lock=" << val << ",";
1216
93.1k
    for (int j=0; j<16; ++j) { // always 0
1217
87.6k
      val=static_cast<int>(input->readULong(4));
1218
87.6k
      if (val) f << "g" << j << "=" << val << ",";
1219
87.6k
    }
1220
5.47k
    val=static_cast<int>(input->readULong(4));
1221
5.47k
    if (val) f << "ID=" << std::hex << val << std::dec << ",";
1222
5.47k
    ascFile.addPos(pos);
1223
5.47k
    ascFile.addNote(f.str().c_str());
1224
5.47k
    input->seek(pos+80, librevenge::RVNG_SEEK_SET);
1225
5.47k
    m_state->m_layerList.push_back(layer);
1226
5.47k
  }
1227
1.57k
  return true;
1228
1.59k
}
1229
1230
bool ClarisDrawParser::readLibraryNames()
1231
182
{
1232
182
  MWAWInputStreamPtr input = getInput();
1233
182
  long pos=input->tell();
1234
182
  if (!input->checkPosition(pos+8)) return false;
1235
171
  libmwaw::DebugFile &ascFile = ascii();
1236
171
  libmwaw::DebugStream f;
1237
171
  f << "Entries(LibraryName):";
1238
171
  ClarisWksStruct::Struct header;
1239
171
  if (!header.readHeader(input,true)) {
1240
124
    MWAW_DEBUG_MSG(("ClarisDrawParser::readLibraryNames: the data size seems bad\n"));
1241
124
    f << "###";
1242
124
    ascFile.addPos(pos);
1243
124
    ascFile.addNote(f.str().c_str());
1244
124
    return false;
1245
124
  }
1246
47
  if (header.m_size==0) {
1247
0
    ascFile.addPos(pos);
1248
0
    ascFile.addNote("_");
1249
0
    pos=input->tell();
1250
0
    auto sz = long(input->readULong(4));
1251
0
    if (!input->checkPosition(pos+4+sz)) {
1252
0
      MWAW_DEBUG_MSG(("ClarisDrawParser::readLibraryNames: the name size seems bad\n"));
1253
0
      f << "###";
1254
0
      ascFile.addPos(pos);
1255
0
      ascFile.addNote(f.str().c_str());
1256
0
      return false;
1257
0
    }
1258
0
    if (!sz) {
1259
0
      ascFile.addPos(pos);
1260
0
      ascFile.addNote("_");
1261
0
      return true;
1262
0
    }
1263
0
    MWAW_DEBUG_MSG(("ClarisDrawParser::readLibraryNames: find a string but no position\n"));
1264
0
    f << "###";
1265
0
    ascFile.addPos(pos);
1266
0
    ascFile.addNote(f.str().c_str());
1267
0
    input->seek(pos+4+sz, librevenge::RVNG_SEEK_SET);
1268
0
    return true;
1269
0
  }
1270
1271
47
  long endPos=pos+4+header.m_size;
1272
47
  f << header;
1273
47
  if (header.m_headerSize) {
1274
1
    ascFile.addDelimiter(input->tell(),'|');
1275
1
    input->seek(header.m_headerSize, librevenge::RVNG_SEEK_CUR);
1276
1
  }
1277
47
  ascFile.addPos(pos);
1278
47
  ascFile.addNote(f.str().c_str());
1279
1280
47
  pos=input->tell();
1281
47
  if (header.m_dataSize!=4) {
1282
47
    input->seek(endPos, librevenge::RVNG_SEEK_SET);
1283
47
    MWAW_DEBUG_MSG(("ClarisDrawParser::readLibraryNames: no sure how to read the position\n"));
1284
47
    ascFile.addPos(pos);
1285
47
    ascFile.addNote("LibraryName:###");
1286
47
    return true;
1287
47
  }
1288
1289
0
  pos=input->tell();
1290
0
  f.str("");
1291
0
  f << "LibraryName-pos:";
1292
0
  std::vector<int> positions, lengths;
1293
0
  for (long i=0; i<header.m_numData; ++i) {
1294
0
    auto sSz=static_cast<int>(input->readULong(2));
1295
0
    auto position=static_cast<int>(input->readULong(2));
1296
0
    f << position << ":" << sSz << ",";
1297
0
    positions.push_back(position);
1298
0
    lengths.push_back(sSz);
1299
0
  }
1300
0
  ascFile.addPos(pos);
1301
0
  ascFile.addNote(f.str().c_str());
1302
1303
0
  pos=input->tell();
1304
0
  f.str("");
1305
0
  f << "LibraryName-name:";
1306
0
  auto sz = long(input->readULong(4));
1307
0
  if (sz==0 || !input->checkPosition(pos+4+sz)) {
1308
0
    MWAW_DEBUG_MSG(("ClarisDrawParser::readLibraryNames: can not find the name\n"));
1309
0
    f << "###";
1310
0
    ascFile.addPos(pos);
1311
0
    ascFile.addNote(f.str().c_str());
1312
0
    return false;
1313
0
  }
1314
1315
0
  for (size_t i=0; i<positions.size(); ++i) {
1316
0
    ClarisDrawParserInternal::Layer layer;
1317
0
    if (positions[i]+lengths[i]>sz) {
1318
0
      MWAW_DEBUG_MSG(("ClarisDrawParser::readLibraryNames: the name %d seems bad\n", int(i)));
1319
0
      f << "###,";
1320
0
      m_state->m_layerList.push_back(layer);
1321
0
      continue;
1322
0
    }
1323
0
    input->seek(pos+4+positions[i], librevenge::RVNG_SEEK_SET);
1324
0
    librevenge::RVNGString name("");
1325
0
    for (int c=0; c<lengths[i]; ++c) {
1326
0
      auto ch=char(input->readULong(1));
1327
0
      if (!ch) continue;
1328
0
      f << ch;
1329
0
      int unicode= getParserState()->m_fontConverter->unicode(3, static_cast<unsigned char>(ch));
1330
0
      if (unicode==-1)
1331
0
        name.append(ch);
1332
0
      else
1333
0
        libmwaw::appendUnicode(static_cast<uint32_t>(unicode), name);
1334
0
    }
1335
0
    f << ",";
1336
0
    layer.m_name = name;
1337
0
    m_state->m_layerList.push_back(layer);
1338
0
  }
1339
0
  ascFile.addPos(pos);
1340
0
  ascFile.addNote(f.str().c_str());
1341
0
  input->seek(pos+4+sz, librevenge::RVNG_SEEK_SET);
1342
0
  return true;
1343
0
}
1344
////////////////////////////////////////////////////////////
1345
// read the document information
1346
////////////////////////////////////////////////////////////
1347
bool ClarisDrawParser::readDocInfo()
1348
2.08k
{
1349
2.08k
  MWAWInputStreamPtr input = getInput();
1350
2.08k
  libmwaw::DebugStream f;
1351
2.08k
  f << "Entries(DocInfo):";
1352
2.08k
  long pos = input->tell();
1353
2.08k
  long endPos=pos+428;
1354
2.08k
  if (!input->checkPosition(endPos)) return false;
1355
2.05k
  f << "ptr=" << std::hex << input->readULong(4) << std::dec << ",";
1356
2.05k
  int val;
1357
14.3k
  for (int i = 0; i < 6; i++) {
1358
12.3k
    val = static_cast<int>(input->readULong(2));
1359
12.3k
    if (val) f << "f" << i << "=" << std::hex << val << std::dec << ",";
1360
12.3k
  }
1361
2.05k
  m_state->m_headerId = static_cast<int>(input->readLong(2));
1362
2.05k
  if (m_state->m_headerId) f << "headerId=" << m_state->m_headerId << ",";
1363
2.05k
  val = static_cast<int>(input->readLong(2));
1364
2.05k
  if (val) f << "unkn=" << val << ",";
1365
2.05k
  m_state->m_footerId = static_cast<int>(input->readLong(2));
1366
2.05k
  if (m_state->m_footerId) f << "footerId=" << m_state->m_footerId << ",";
1367
10.2k
  for (int i=0; i < 4; ++i) {
1368
8.20k
    val = static_cast<int>(input->readLong(2));
1369
8.20k
    if (val) f << "g" << i << "=" << val << ",";
1370
8.20k
  }
1371
2.05k
  int pages[2];
1372
4.10k
  for (auto &page : pages) page=static_cast<int>(input->readLong(2));
1373
2.05k
  if (pages[1]>=1 && pages[1] < 1000 && pages[0]>=1 && pages[0]<100)
1374
1.59k
    m_state->m_pages=MWAWVec2i(pages[0],pages[1]);
1375
2.05k
  if (pages[0]!=1 || pages[1]!=1)
1376
472
    f << "pages[num]=" << pages[0] << "x" << pages[1] << ",";
1377
2.05k
  ascii().addDelimiter(input->tell(), '|');
1378
2.05k
  ascii().addPos(pos);
1379
2.05k
  ascii().addNote(f.str().c_str());
1380
2.05k
  ascii().addPos(pos+100);
1381
2.05k
  ascii().addNote("DocInfo-2");
1382
2.05k
  ascii().addPos(pos+200);
1383
2.05k
  ascii().addNote("DocInfo-3");
1384
2.05k
  ascii().addPos(pos+300);
1385
2.05k
  ascii().addNote("DocInfo-4");
1386
2.05k
  input->seek(endPos, librevenge::RVNG_SEEK_SET);
1387
2.05k
  return true;
1388
2.08k
}
1389
1390
////////////////////////////////////////////////////////////
1391
// try to read the print info zone
1392
////////////////////////////////////////////////////////////
1393
bool ClarisDrawParser::readPrintInfo()
1394
2.08k
{
1395
2.08k
  MWAWInputStreamPtr input = getInput();
1396
2.08k
  long pos=input->tell();
1397
2.08k
  long endPos=pos+124;
1398
2.08k
  if (input->readULong(4)!=120 || !input->checkPosition(endPos)) {
1399
247
    MWAW_DEBUG_MSG(("ClarisDrawParser::readPrintInfo: file seems too short\n"));
1400
247
    return false;
1401
247
  }
1402
1.83k
  libmwaw::DebugStream f;
1403
1.83k
  f << "Entries(PrintInfo):";
1404
1.83k
  libmwaw::PrinterInfo info;
1405
1.83k
  if (!info.read(input)) {
1406
42
    MWAW_DEBUG_MSG(("ClarisDrawParser::readPrintInfo: can not read print info\n"));
1407
42
    return false;
1408
42
  }
1409
1.79k
  f << info;
1410
1.79k
  MWAWVec2i paperSize = info.paper().size();
1411
1.79k
  MWAWVec2i pageSize = info.page().size();
1412
1.79k
  if (pageSize.x() <= 0 || pageSize.y() <= 0 ||
1413
1.77k
      paperSize.x() <= 0 || paperSize.y() <= 0) {
1414
16
    ascii().addPos(pos);
1415
16
    ascii().addNote(f.str().c_str());
1416
16
    input->seek(endPos, librevenge::RVNG_SEEK_SET);
1417
16
    return true;
1418
16
  }
1419
1420
  // define margin from print info
1421
1.77k
  MWAWVec2i lTopMargin= -1 * info.paper().pos(0);
1422
1.77k
  MWAWVec2i rBotMargin=info.paper().size() - info.page().size();
1423
1424
  // move margin left | top
1425
1.77k
  int decalX = lTopMargin.x() > 14 ? lTopMargin.x()-14 : 0;
1426
1.77k
  int decalY = lTopMargin.y() > 14 ? lTopMargin.y()-14 : 0;
1427
1.77k
  lTopMargin -= MWAWVec2i(decalX, decalY);
1428
1.77k
  rBotMargin += MWAWVec2i(decalX, decalY);
1429
1430
  // decrease right | bottom
1431
1.77k
  int rightMarg = rBotMargin.x() -50;
1432
1.77k
  if (rightMarg < 0) rightMarg=0;
1433
1.77k
  int botMarg = rBotMargin.y() -50;
1434
1.77k
  if (botMarg < 0) botMarg=0;
1435
1436
1.77k
  getPageSpan().setMarginTop(lTopMargin.y()/72.0);
1437
1.77k
  getPageSpan().setMarginBottom(botMarg/72.0);
1438
1.77k
  getPageSpan().setMarginLeft(lTopMargin.x()/72.0);
1439
1.77k
  getPageSpan().setMarginRight(rightMarg/72.0);
1440
1.77k
  getPageSpan().setFormLength(paperSize.y()/72.);
1441
1.77k
  getPageSpan().setFormWidth(paperSize.x()/72.);
1442
1443
1.77k
  ascii().addPos(pos);
1444
1.77k
  ascii().addNote(f.str().c_str());
1445
1.77k
  input->seek(endPos, librevenge::RVNG_SEEK_SET);
1446
1.77k
  return true;
1447
1.79k
}
1448
1449
////////////////////////////////////////////////////////////
1450
// read the document main part
1451
////////////////////////////////////////////////////////////
1452
std::shared_ptr<ClarisWksStruct::DSET> ClarisDrawParser::readDSET(bool isLibHeader)
1453
1.16M
{
1454
1.16M
  MWAWInputStreamPtr input = getInput();
1455
1.16M
  long pos = input->tell();
1456
1.16M
  libmwaw::DebugStream f;
1457
1.16M
  libmwaw::DebugFile &ascFile=ascii();
1458
1.16M
  if (input->readULong(4) != 0x44534554L)
1459
38.6k
    return std::shared_ptr<ClarisWksStruct::DSET>();
1460
1.13M
  auto sz = long(input->readULong(4));
1461
1.13M
  MWAWEntry entry;
1462
1.13M
  entry.setBegin(pos);
1463
1.13M
  entry.setLength(sz+8);
1464
1465
1.13M
  long endPos = entry.end();
1466
1.13M
  if (sz<16 || !input->checkPosition(entry.end())) {
1467
99.8k
    MWAW_DEBUG_MSG(("ClarisDrawParser::readDSET: file is too short\n"));
1468
99.8k
    return std::shared_ptr<ClarisWksStruct::DSET>();
1469
99.8k
  }
1470
1471
1.03M
  ClarisWksStruct::DSET dset;
1472
1.03M
  dset.m_size = sz;
1473
1.03M
  dset.m_numData = static_cast<int>(input->readULong(2));
1474
1475
1.03M
  input->seek(10, librevenge::RVNG_SEEK_CUR);
1476
1.03M
  dset.m_fileType = static_cast<int>(input->readULong(1));
1477
1.03M
  input->seek(-11, librevenge::RVNG_SEEK_CUR);
1478
1.03M
  int nFlags = 0;
1479
1.03M
  switch (dset.m_fileType) {
1480
274k
  case 1: // text
1481
274k
    dset.m_beginSelection = static_cast<int>(input->readLong(4));
1482
274k
    dset.m_endSelection = static_cast<int>(input->readLong(4));
1483
274k
    dset.m_textType = static_cast<int>(input->readULong(1));
1484
274k
    dset.m_flags[nFlags++] = static_cast<int>(input->readLong(1));
1485
274k
    dset.m_headerSz = 44;
1486
274k
    dset.m_dataSz = 28;
1487
274k
    break;
1488
756k
  default:
1489
756k
    dset.m_flags[nFlags++] = static_cast<int>(input->readLong(2)); // normally -1
1490
756k
    dset.m_flags[nFlags++] = static_cast<int>(input->readLong(2)); // the 0
1491
756k
    dset.m_dataSz = static_cast<int>(input->readULong(2));
1492
756k
    dset.m_headerSz = static_cast<int>(input->readULong(2));
1493
756k
    dset.m_flags[nFlags++] = static_cast<int>(input->readLong(2));
1494
756k
    break;
1495
1.03M
  }
1496
1.03M
  dset.m_flags[nFlags++] = static_cast<int>(input->readLong(2));
1497
1.03M
  dset.m_id = static_cast<int>(input->readULong(2));
1498
1.03M
  std::shared_ptr<ClarisWksStruct::DSET> zone;
1499
1.03M
  switch (dset.m_fileType)  {
1500
457k
  case 0:
1501
457k
    zone=m_graphParser->readGroupZone(dset, entry, isLibHeader);
1502
457k
    break;
1503
274k
  case 1:
1504
274k
    zone=m_textParser->readDSETZone(dset, entry);
1505
274k
    break;
1506
186k
  case 4:
1507
186k
    zone=m_graphParser->readBitmapZone(dset, entry);
1508
186k
    break;
1509
112k
  default:
1510
112k
    break;
1511
1.03M
  }
1512
1.03M
  if (!zone) {
1513
227k
    MWAW_DEBUG_MSG(("ClarisDrawParser::readDSET: find unexpected type\n"));
1514
227k
    zone.reset(new ClarisWksStruct::DSET(dset));
1515
227k
    f << "Entries(DSETU): " << *zone;
1516
1517
227k
    auto data0Length = static_cast<int>(zone->m_dataSz);
1518
227k
    auto N = static_cast<int>(zone->m_numData);
1519
1520
227k
    ascFile.addDelimiter(input->tell(), '|');
1521
227k
    ascFile.addPos(pos);
1522
227k
    ascFile.addNote(f.str().c_str());
1523
1524
227k
    const long dataSz = sz-12-zone->m_headerSz;
1525
227k
    if ((dataSz && (data0Length<=0 || (dataSz/data0Length)!=N || (dataSz%data0Length)!=0)) || (!dataSz && N)) {
1526
206k
      MWAW_DEBUG_MSG(("ClarisDrawParser::readDSET: unexpected size for zone definition, try to continue\n"));
1527
206k
      ascFile.addPos(pos);
1528
206k
      ascFile.addNote("###");
1529
206k
      input->seek(endPos, librevenge::RVNG_SEEK_SET);
1530
206k
      return zone;
1531
206k
    }
1532
1533
20.9k
    long debPos = endPos-N*data0Length;
1534
39.9k
    for (long i = 0; i < zone->m_numData; i++) {
1535
19.0k
      input->seek(debPos, librevenge::RVNG_SEEK_SET);
1536
19.0k
      f.str("");
1537
19.0k
      f << "DSETU-" << i << ":";
1538
1539
19.0k
      long actPos = input->tell();
1540
19.0k
      if (actPos != debPos && actPos != debPos+data0Length)
1541
0
        ascFile.addDelimiter(input->tell(),'|');
1542
19.0k
      ascFile.addPos(debPos);
1543
19.0k
      ascFile.addNote(f.str().c_str());
1544
19.0k
      debPos += data0Length;
1545
19.0k
    }
1546
1547
20.9k
    input->seek(endPos, librevenge::RVNG_SEEK_SET);
1548
20.9k
  }
1549
1550
824k
  if (m_state->m_zonesMap.find(zone->m_id) != m_state->m_zonesMap.end()) {
1551
686k
    MWAW_DEBUG_MSG(("ClarisDrawParser::readDSET: zone %d already exists!!!!\n",
1552
686k
                    zone->m_id));
1553
686k
  }
1554
137k
  else {
1555
137k
    m_state->m_zonesMap[zone->m_id] = zone;
1556
137k
    m_state->m_zoneIdToFileTypeMap[zone->m_id] = dset.m_fileType;
1557
137k
  }
1558
824k
  return zone;
1559
1.03M
}
1560
1561
////////////////////////////////////////////////////////////
1562
//
1563
// send data
1564
//
1565
////////////////////////////////////////////////////////////
1566
1567
1568
// vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: