Coverage Report

Created: 2026-10-28 06:34

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libmwaw/src/lib/ReadySetGoParser.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 <algorithm>
35
#include <cmath>
36
#include <iomanip>
37
#include <iostream>
38
#include <limits>
39
#include <map>
40
#include <set>
41
#include <sstream>
42
43
#include <librevenge/librevenge.h>
44
45
#include "MWAWFontConverter.hxx"
46
#include "MWAWGraphicListener.hxx"
47
#include "MWAWGraphicShape.hxx"
48
#include "MWAWGraphicStyle.hxx"
49
#include "MWAWHeader.hxx"
50
#include "MWAWParagraph.hxx"
51
#include "MWAWPictBitmap.hxx"
52
#include "MWAWPictData.hxx"
53
#include "MWAWPrinter.hxx"
54
#include "MWAWPosition.hxx"
55
#include "MWAWSubDocument.hxx"
56
57
#include "ReadySetGoParser.hxx"
58
59
#include "ReadySetGoGraph.hxx"
60
#include "ReadySetGoStyleManager.hxx"
61
62
/** Internal: the structures of a ReadySetGoParser */
63
namespace ReadySetGoParserInternal
64
{
65
66
////////////////////////////////////////
67
//! Internal: the state of a ReadySetGoParser
68
struct State {
69
  //! constructor
70
  State()
71
37.2k
    : m_designStudio(false)
72
37.2k
    , m_numLayouts(1)
73
37.2k
    , m_numGlossary(0)
74
37.2k
    , m_numObjectGlossary(0)
75
37.2k
    , m_numStyles(0)
76
37.2k
    , m_hasCustomColors(false)
77
37.2k
    , m_hasFontsBlock2(false)
78
37.2k
  {
79
37.2k
  }
80
  //! a flag to descriminate between ReadySetGo and Design Studio
81
  bool m_designStudio;
82
  //! the number of layouts: used for v3
83
  int m_numLayouts;
84
  //! the number of glossary: used for v4
85
  int m_numGlossary;
86
  //! the number of object glossary: used for v6
87
  int m_numObjectGlossary;
88
  //! the number of styles: v4
89
  int m_numStyles;
90
  //! a flag to know if the document has custom colors: v5
91
  bool m_hasCustomColors;
92
  //! a unknown zone : v6
93
  bool m_hasFontsBlock2;
94
};
95
96
}
97
98
////////////////////////////////////////////////////////////
99
// constructor/destructor, ...
100
////////////////////////////////////////////////////////////
101
ReadySetGoParser::ReadySetGoParser(MWAWInputStreamPtr const &input, MWAWRSRCParserPtr const &rsrcParser, MWAWHeader *header)
102
17.7k
  : MWAWGraphicParser(input, rsrcParser, header)
103
17.7k
  , m_graphParser()
104
17.7k
  , m_styleManager()
105
17.7k
  , m_state(new ReadySetGoParserInternal::State)
106
17.7k
{
107
17.7k
  m_styleManager.reset(new ReadySetGoStyleManager(*this));
108
17.7k
  m_graphParser.reset(new ReadySetGoGraph(*this));
109
17.7k
  setAsciiName("main-1");
110
17.7k
  getPageSpan().setMargins(0.1);
111
17.7k
}
112
113
ReadySetGoParser::~ReadySetGoParser()
114
17.7k
{
115
17.7k
}
116
117
bool ReadySetGoParser::isDesignStudioFile() const
118
2.70k
{
119
2.70k
  return m_state->m_designStudio;
120
2.70k
}
121
122
////////////////////////////////////////////////////////////
123
// the parser
124
////////////////////////////////////////////////////////////
125
void ReadySetGoParser::parse(librevenge::RVNGDrawingInterface *docInterface)
126
1.67k
{
127
1.67k
  if (!getInput().get() || !checkHeader(nullptr))  throw(libmwaw::ParseException());
128
1.67k
  bool ok = false;
129
1.67k
  try {
130
    // create the asciiFile
131
1.67k
    ascii().setStream(getInput());
132
1.67k
    ascii().open(asciiName());
133
1.67k
    checkHeader(nullptr);
134
135
    // update the style manager, ...
136
1.67k
    ok = createZones();
137
1.67k
    if (ok) {
138
200
      createDocument(docInterface);
139
200
      ok=getGraphicListener() && m_graphParser->sendPages();
140
200
    }
141
1.67k
    ascii().reset();
142
1.67k
  }
143
1.67k
  catch (...) {
144
0
    MWAW_DEBUG_MSG(("ReadySetGoParser::parse: exception catched when parsing\n"));
145
0
    ok = false;
146
0
  }
147
148
1.67k
  resetGraphicListener();
149
1.67k
  if (!ok) throw(libmwaw::ParseException());
150
1.67k
}
151
152
////////////////////////////////////////////////////////////
153
// create the document
154
////////////////////////////////////////////////////////////
155
void ReadySetGoParser::createDocument(librevenge::RVNGDrawingInterface *documentInterface)
156
200
{
157
200
  if (!documentInterface) return;
158
200
  if (getGraphicListener()) {
159
0
    MWAW_DEBUG_MSG(("ReadySetGoParser::createDocument: listener already exist\n"));
160
0
    return;
161
0
  }
162
163
  // create the page list
164
200
  std::vector<MWAWPageSpan> pageList;
165
200
  m_graphParser->updatePageSpanList(pageList);
166
200
  MWAWGraphicListenerPtr listen(new MWAWGraphicListener(*getParserState(), pageList, documentInterface));
167
200
  setGraphicListener(listen);
168
200
  listen->startDocument();
169
200
  m_graphParser->sendMasterPages();
170
200
}
171
172
////////////////////////////////////////////////////////////
173
//
174
// Intermediate level
175
//
176
////////////////////////////////////////////////////////////
177
bool ReadySetGoParser::createZones()
178
1.67k
{
179
1.67k
  auto input=getInput();
180
1.67k
  int const vers=version();
181
1.67k
  bool const designStudio=isDesignStudioFile();
182
1.67k
  if (!input) {
183
0
    MWAW_DEBUG_MSG(("ReadySetGoParser::createZones: no input\n"));
184
0
    return false;
185
0
  }
186
1.67k
  libmwaw::DebugStream f;
187
1.67k
  if (vers<3)
188
371
    input->seek(0, librevenge::RVNG_SEEK_SET);
189
1.30k
  else if (vers==3) {
190
647
    input->seek(2, librevenge::RVNG_SEEK_SET);
191
647
    if (!readDocument())
192
10
      return false;
193
647
  }
194
654
  else {
195
654
    if (!input->checkPosition(vers<=5 ? 100 : 200)) {
196
0
      MWAW_DEBUG_MSG(("ReadySetGoParser::createZones: the file seems too short\n"));
197
0
      return false;
198
0
    }
199
654
    input->seek(2, librevenge::RVNG_SEEK_SET);
200
654
    f.str("");
201
654
    f << "Entries(ZonePos):";
202
654
    std::map<long, int> posToId;
203
654
    f << "pos=[";
204
1.86k
    for (int i=0; i<(vers==4 ? 2 : vers==5 ? 5 : 12); ++i) { // Style, ????
205
1.28k
      long posi=input->readLong(4);
206
1.28k
      f << std::hex << posi << std::dec << ",";
207
1.28k
      if (posi<(vers==4 ? 0x100 : 0x300) || !input->checkPosition(posi)) {
208
72
        MWAW_DEBUG_MSG(("ReadySetGoParser::createZones: the %d th positions seems bad\n", i));
209
72
        f << "###";
210
72
        ascii().addPos(2);
211
72
        ascii().addNote(f.str().c_str());
212
72
        return false;
213
72
      }
214
1.21k
      posToId[posi]=i;
215
1.21k
    }
216
582
    f << "],";
217
26.7k
    for (int i=0; i<(vers==4 ? 45 : vers==5 ? 39 : 75); ++i) {
218
26.1k
      int val=int(input->readLong(2));
219
26.1k
      if (val)
220
19.6k
        f << "f" << i << "=" << val << ",";
221
26.1k
    }
222
582
    ascii().addPos(2);
223
582
    ascii().addNote(f.str().c_str());
224
225
    // first zone
226
582
    if (!readDocument() || !readPrintInfo() || !m_graphParser->readLayoutsList(m_state->m_numLayouts))
227
582
      return false;
228
    // 26 master possible A to Z times 2 (left or right)
229
0
    if (vers>=6 && !designStudio && !m_graphParser->readLayoutsList(52, true))
230
0
      return false;
231
0
    if (!readIdsList() || input->tell()>posToId.begin()->first)
232
0
      return false;
233
0
    if (input->tell()<posToId.begin()->first) {
234
0
      MWAW_DEBUG_MSG(("ReadySetGoParser::createZones: find extra data for the beginning zone\n"));
235
0
      ascii().addPos(input->tell());
236
0
      ascii().addNote("ZonePos:extra###");
237
0
    }
238
0
    for (auto posIdIt=posToId.begin(); posIdIt!=posToId.end();) {
239
0
      long pos=posIdIt->first;
240
0
      input->seek(pos, librevenge::RVNG_SEEK_SET);
241
0
      int id=posIdIt->second, origId=id;
242
0
      if (vers>=6) {
243
0
        if (id<3 || (id>=7 && id<=9) || id==11)
244
0
          ;
245
        // 2: color list?, 3: color name?
246
0
        else if (id>=4 && id<=5)
247
0
          --id;
248
        // 6: N, -1, -256 + Nx[8 bytes?]
249
0
        else
250
0
          id=-1;
251
0
      }
252
0
      ++posIdIt;
253
0
      long endPos=posIdIt==posToId.end() ? -1 : posIdIt->first;
254
0
      if (endPos>0)
255
0
        input->pushLimit(endPos);
256
0
      bool ok=true;
257
0
      switch (id) {
258
0
      case 0:
259
0
        ok=m_styleManager->readStyles(m_state->m_numStyles);
260
0
        break;
261
0
      case 1:
262
0
        ok=readGlossary();
263
0
        break;
264
0
      case 2:
265
0
        if (!m_state->m_hasCustomColors) {
266
0
          if (!input->checkPosition(pos+4)) {
267
0
            MWAW_DEBUG_MSG(("ReadySetGoParser::createZones[color]: can not find the data\n"));
268
0
            ok=false;
269
0
            break;
270
0
          }
271
          // normally followed by 0
272
0
          ascii().addPos(pos);
273
0
          ascii().addNote("_");
274
0
          break;
275
0
        }
276
0
        ok=m_styleManager->readColors();
277
0
        break;
278
0
      case 3:
279
0
        ok=m_styleManager->readColorNames();
280
0
        break;
281
0
      case 4:
282
0
        ok=m_styleManager->readFontsBlock();
283
0
        break;
284
0
      case 7:
285
0
        ok=m_styleManager->readFontsName();
286
0
        break;
287
0
      case 8:
288
0
        ok=readFontsUnknown();
289
0
        break;
290
0
      case 9:
291
0
        ok=readObjectGlossary();
292
0
        break;
293
0
      case 11:
294
0
        ok=readZone11();
295
0
        break;
296
      // 9: N?x40char, then ? maybe link to templates data
297
      // 10: find len=4c, 2 IDS + 6 small values b,b,c,d,a,a
298
0
      default:
299
0
        if (vers>=6) {
300
0
          input->seek(pos, librevenge::RVNG_SEEK_SET);
301
0
          f.str("");
302
0
          f << "Entries(Zone" << origId << "A):";
303
0
          long len=long(input->readLong(4));
304
0
          long zEndPos=pos+4+len;
305
0
          if (zEndPos<pos+4 || (endPos>0 && zEndPos>endPos) || (endPos<=0 && !input->checkPosition(zEndPos))) {
306
0
            MWAW_DEBUG_MSG(("ReadySetGoParser::createZones[unknown, last]: can not find the data\n"));
307
0
            ok=false;
308
0
            break;
309
0
          }
310
0
          ascii().addPos(pos);
311
0
          ascii().addNote(f.str().c_str());
312
0
          input->seek(zEndPos, librevenge::RVNG_SEEK_SET);
313
0
          break;
314
0
        }
315
0
        MWAW_DEBUG_MSG(("ReadySetGoParser::createZones: find unexpected zone=%d\n", id));
316
0
        ok=false;
317
0
        break;
318
0
      }
319
0
      if (endPos>0)
320
0
        input->popLimit();
321
0
      if (ok) {
322
0
        input->popLimit();
323
0
        if (endPos>0)
324
0
          input->seek(endPos, librevenge::RVNG_SEEK_SET);
325
0
        continue;
326
0
      }
327
0
      ascii().addPos(pos);
328
0
      ascii().addNote("Entries(Bad):###");
329
0
      if (endPos==-1) // no way to continue
330
0
        return false;
331
0
    }
332
0
    if (m_state->m_hasFontsBlock2 && !m_styleManager->readFontsBlock2())
333
0
      return false;
334
0
    return m_graphParser->readShapes();
335
0
  }
336
337
1.00k
  if (!readPrintInfo())
338
678
    return false;
339
340
330
  if (vers==3) {
341
0
    if (!m_graphParser->readLayoutsList(m_state->m_numLayouts) || !readIdsList())
342
0
      return false;
343
    // always empty
344
0
    long pos=input->tell();
345
0
    long len=long(input->readLong(4));
346
0
    f.str("");
347
0
    f << "Entries(Zone0):";
348
0
    if ((long)((unsigned long)pos+4+(unsigned long)len)<pos+4 || !input->checkPosition(pos+4+len)) {
349
0
      MWAW_DEBUG_MSG(("ReadySetGoParser::createZones: can not find a initial zone0\n"));
350
0
      f << "###";
351
0
      ascii().addPos(pos);
352
0
      ascii().addNote(f.str().c_str());
353
0
      return false;
354
0
    }
355
0
    if (len==0) {
356
0
      ascii().addPos(pos);
357
0
      ascii().addNote("_");
358
0
    }
359
0
    else {
360
0
      ascii().addPos(pos);
361
0
      ascii().addNote(f.str().c_str());
362
0
      input->seek(pos+4+len, librevenge::RVNG_SEEK_SET);
363
0
    }
364
0
  }
365
330
  if (!m_graphParser->readShapes())
366
130
    return false;
367
368
200
  if (!input->isEnd()) {
369
85
    MWAW_DEBUG_MSG(("ReadySetGoParser::createZones: find extra data\n"));
370
85
    ascii().addPos(input->tell());
371
85
    ascii().addNote("Entries(Extra):###");
372
85
  }
373
200
  return true;
374
330
}
375
376
377
////////////////////////////////////////////////////////////
378
// read the header
379
////////////////////////////////////////////////////////////
380
bool ReadySetGoParser::checkHeader(MWAWHeader *header, bool strict)
381
19.4k
{
382
19.4k
  *m_state = ReadySetGoParserInternal::State();
383
19.4k
  MWAWInputStreamPtr input = getInput();
384
19.4k
  if (!input || !input->hasDataFork() || !input->checkPosition(126))
385
1.15k
    return false;
386
387
18.3k
  libmwaw::DebugStream f;
388
18.3k
  f << "FileHeader:";
389
18.3k
  input->seek(0, librevenge::RVNG_SEEK_SET);
390
18.3k
  int val=int(input->readULong(2));
391
18.3k
  f << "vers=" << val << ",";
392
18.3k
  int vers=1;
393
18.3k
  m_state->m_designStudio=false;
394
18.3k
  if (val==0x1e) { // 30
395
4.24k
    if (input->readULong(2) || input->readULong(2)!=0x86)
396
0
      return false;
397
4.24k
    vers=3;
398
4.24k
  }
399
14.0k
  else if (val>=400 && val<=402) // I only see 400
400
4.99k
    vers=4;
401
9.07k
  else if (val>=5000 && val<=5005) // I only see 5003 v4.5
402
413
    vers=5;
403
8.65k
  else if (val>=6000 && val<=6003) //I only see 6000
404
223
    vers=6;
405
  // I only find some demo files, these files look very simillar to v6 files
406
  //   I try to modified the parser to parse them, but there remains some
407
  //   problems at least colors' problems
408
8.43k
  else if (val==7100) // 7100 v7.1
409
887
    vers=7;
410
7.54k
  else if (val==0x13e4) { // Design Studio, visibly was forked between RSG 4.5 and RSG 6
411
235
    f << "designStudio,";
412
235
    m_state->m_designStudio=true;
413
235
    vers=6;
414
235
  }
415
7.31k
  else if (val!=0x78)
416
34
    return false;
417
18.2k
  ascii().addPos(0);
418
18.2k
  ascii().addNote(f.str().c_str());
419
420
18.2k
  if (vers<3) {
421
    // we need to retrieve the version v1 or v2
422
7.27k
    input->seek(2+120, librevenge::RVNG_SEEK_SET);
423
7.27k
    int n=int(input->readULong(2));
424
7.27k
    if (n<=0)
425
247
      return false;
426
427
    //
428
    // first test for version 2, the more structured
429
    //
430
7.03k
    bool ok=true;
431
7.03k
    vers=2;
432
7.03k
    int nShapes=0;
433
374k
    for (int p=0; p<n; ++p) {
434
371k
      long pos=input->tell();
435
371k
      if (!input->checkPosition(pos+2)) {
436
978
        ok=false;
437
978
        break;
438
978
      }
439
370k
      val=int(input->readLong(2));
440
370k
      if (val<0) {
441
3.31k
        ok=false;
442
3.31k
        break;
443
3.31k
      }
444
367k
      nShapes+=val;
445
367k
    }
446
7.50k
    for (int s=0; s<nShapes; ++s) {
447
5.88k
      long pos=input->tell();
448
5.88k
      if (!ok || !input->checkPosition(pos+4)) {
449
3.69k
        ok=false;
450
3.69k
        break;
451
3.69k
      }
452
2.19k
      int type=int(input->readULong(2));
453
2.19k
      if (type<0 || type>6) {
454
844
        ok=false;
455
844
        break;
456
844
      }
457
1.35k
      input->seek(2, librevenge::RVNG_SEEK_CUR);
458
2.46k
      for (int i=0; i<2; ++i) {
459
1.95k
        pos=input->tell();
460
1.95k
        int len=int(input->readULong(2));
461
1.95k
        if ((i==0 && len!=0x1c) || !input->checkPosition(pos+2+len)) {
462
835
          ok=false;
463
835
          break;
464
835
        }
465
1.11k
        input->seek(pos+2+len, librevenge::RVNG_SEEK_SET);
466
1.11k
      }
467
1.35k
      if (!ok)
468
835
        break;
469
518
      if (type==3 && !input->isEnd()) {
470
        // we must check if there is a picture
471
122
        pos=input->tell();
472
122
        int len=int(input->readULong(2));
473
122
        if (len<10)
474
43
          input->seek(pos, librevenge::RVNG_SEEK_SET);
475
79
        else {
476
79
          if (!input->checkPosition(pos+2+len)) {
477
49
            ok=false;
478
49
            break;
479
49
          }
480
30
          input->seek(pos+2+len, librevenge::RVNG_SEEK_SET);
481
30
        }
482
122
      }
483
469
      if (type!=4)
484
221
        continue;
485
522
      for (int st=0; st<2; ++st) { // zone1=[text, style], zone2=[para]
486
425
        pos=input->tell();
487
425
        int len=int(input->readULong(2));
488
425
        if (!input->checkPosition(pos+2+len)) {
489
151
          ok=false;
490
151
          break;
491
151
        }
492
274
        input->seek(pos+2+len, librevenge::RVNG_SEEK_SET);
493
274
      }
494
248
    }
495
7.03k
    if (ok && nShapes<=10 && !input->isEnd())
496
336
      ok=false;
497
498
7.03k
    if (!ok) {
499
      // test for version 1
500
6.69k
      ok=true;
501
6.69k
      vers=1;
502
6.69k
      input->seek(2+120+2, librevenge::RVNG_SEEK_SET);
503
17.4k
      for (int i=0; i<std::min(10,n); ++i) {
504
16.3k
        long pos=input->tell();
505
16.3k
        if (!input->checkPosition(pos+26)) {
506
2.23k
          ok=false;
507
2.23k
          break;
508
2.23k
        }
509
14.0k
        int type=int(input->readLong(2));
510
14.0k
        if (type<0 || type>5 || type==2) {
511
1.72k
          ok=false;
512
1.72k
          break;
513
1.72k
        }
514
12.3k
        int const expectedSize[]= {26, 74, 0, 30, 28, 28};
515
12.3k
        if (expectedSize[type]<=0 || !input->checkPosition(pos+expectedSize[type])) {
516
167
          ok=false;
517
167
          break;
518
167
        }
519
12.1k
        input->seek(pos+expectedSize[type], librevenge::RVNG_SEEK_SET);
520
12.1k
        if (type==0 && i+1!=n) {
521
1.09k
          ok=false;
522
1.09k
          break;
523
1.09k
        }
524
11.0k
        if (type==5 && !input->isEnd()) {
525
          // we must check if there is a picture
526
4.54k
          pos=input->tell();
527
4.54k
          int len=int(input->readULong(2));
528
4.54k
          if (len<10)
529
3.64k
            input->seek(pos, librevenge::RVNG_SEEK_SET);
530
899
          else {
531
899
            if (!input->checkPosition(pos+2+len)) {
532
357
              ok=false;
533
357
              break;
534
357
            }
535
542
            input->seek(pos+2+len, librevenge::RVNG_SEEK_SET);
536
542
          }
537
4.54k
        }
538
10.7k
        if (type!=1)
539
9.08k
          continue;
540
3.57k
        for (int st=0; st<2; ++st) {
541
2.83k
          pos=input->tell();
542
2.83k
          int len=int(input->readULong(2));
543
2.83k
          if (!input->checkPosition(pos+2+len)) {
544
900
            ok=false;
545
900
            break;
546
900
          }
547
1.93k
          input->seek(pos+2+len, librevenge::RVNG_SEEK_SET);
548
1.93k
        }
549
1.64k
      }
550
6.69k
      if (ok && n<=10 && !input->isEnd())
551
195
        ok=false;
552
6.69k
    }
553
7.03k
    if (!ok)
554
5.82k
      return false;
555
7.03k
  }
556
10.9k
  else if (vers==3) {
557
4.24k
    if (strict) {
558
1.59k
      input->seek(2, librevenge::RVNG_SEEK_SET);
559
3.43k
      for (int i=0; i<3; ++i) {
560
3.33k
        long pos=input->tell();
561
3.33k
        long len=long(input->readLong(4));
562
3.33k
        if ((long)((unsigned long)pos+4+(unsigned long)len)<pos+4 || !input->checkPosition(pos+4+len))
563
1.44k
          return false;
564
1.88k
        if (len==0 && i<2)
565
44
          return false;
566
1.84k
        input->seek(pos+4+len, librevenge::RVNG_SEEK_SET);
567
1.84k
      }
568
1.59k
    }
569
4.24k
  }
570
6.75k
  else { // vers>3
571
6.75k
    if (vers>=6 && !input->checkPosition(200+20))
572
232
      return false;
573
574
6.51k
    input->seek(2, librevenge::RVNG_SEEK_SET);
575
    // first check the initial list of pointers
576
6.51k
    int emptyZone=0;
577
18.1k
    for (int i=0; i<(vers==4 ? 2 : vers==5 ? 5 : 12); ++i) {
578
14.5k
      long pos=long(input->readLong(4));
579
14.5k
      if (pos==0)
580
5.20k
        ++emptyZone;
581
9.32k
      else if (pos<(vers==4 ? 0x100 : 0x300) || !input->checkPosition(pos))
582
2.85k
        return false;
583
14.5k
    }
584
3.66k
    if (emptyZone>1)
585
153
      return false;
586
3.51k
    if (strict) {
587
1.12k
      input->seek(vers<=5 ? 100 : 200, librevenge::RVNG_SEEK_SET);
588
1.35k
      for (int step=0; step<4; ++step) {
589
1.35k
        long pos=input->tell();
590
1.35k
        long len=long(input->readLong(4));
591
1.35k
        if (pos+4+len<pos+len || !input->checkPosition(pos+4+len))
592
1.01k
          return false;
593
341
        if (step==0 && len<(vers==4 ? 0xcc : vers==5 ? 0x188 : vers==6 ? (m_state->m_designStudio ? 0x2be : 0x58c) : 0x5a0))
594
59
          return false;
595
282
        if (step==1 && len!=0x78)
596
50
          return false;
597
232
        input->seek(pos+4+len, librevenge::RVNG_SEEK_SET);
598
232
      }
599
1.12k
    }
600
3.51k
  }
601
6.34k
  setVersion(vers);
602
6.34k
  if (header)
603
3.00k
    header->reset(MWAWDocument::MWAW_T_READYSETGO, vers, MWAWDocument::MWAW_K_DRAW);
604
605
6.34k
  return true;
606
18.2k
}
607
608
////////////////////////////////////////////////////////////
609
// try to read the main zone
610
////////////////////////////////////////////////////////////
611
bool ReadySetGoParser::readDocument()
612
1.22k
{
613
1.22k
  int const vers=version();
614
1.22k
  if (vers<3) {
615
0
    MWAW_DEBUG_MSG(("ReadySetGoParser::readDocument: unexpected version\n"));
616
0
    return false;
617
0
  }
618
1.22k
  MWAWInputStreamPtr input = getInput();
619
1.22k
  if (!input)
620
0
    return false;
621
1.22k
  long pos=input->tell();
622
1.22k
  if (!input->checkPosition(pos+4)) {
623
0
    MWAW_DEBUG_MSG(("ReadySetGoParser::readDocument: can not read the zone length\n"));
624
0
    return false;
625
0
  }
626
1.22k
  libmwaw::DebugStream f;
627
1.22k
  f << "Entries(Document):";
628
1.22k
  long len=long(input->readLong(4));
629
1.22k
  long endPos=pos+4+len;
630
1.22k
  if (len<0 || !input->checkPosition(endPos)) {
631
476
    MWAW_DEBUG_MSG(("ReadySetGoParser::readDocument: can not read the zone length\n"));
632
476
    f << "###";
633
476
    ascii().addPos(pos);
634
476
    ascii().addNote(f.str().c_str());
635
476
    return false;
636
476
  }
637
753
  bool const designStudio=isDesignStudioFile();
638
753
  long const expectedLength=vers==3 ? 0x86 : vers==4 ? 0xcc : vers==5 ? 0x188 : vers== 6 ? (designStudio ? 0x2be : 0x58c) : 0x5a0; // v7.1: I find len=5a0 or len=211b
639
753
  if (len<expectedLength) {
640
14
    MWAW_DEBUG_MSG(("ReadySetGoParser::readDocument: unexpected zone length\n"));
641
14
    f << "###";
642
14
    ascii().addPos(pos);
643
14
    ascii().addNote(f.str().c_str());
644
14
    input->seek(endPos, librevenge::RVNG_SEEK_SET);
645
14
    return true;
646
14
  }
647
739
  if (len>expectedLength) {
648
102
    MWAW_DEBUG_MSG(("ReadySetGoParser::readDocument: find extra data\n"));
649
102
    ascii().addPos(pos+4+expectedLength);
650
102
    ascii().addNote("Document-extra:###");
651
102
  }
652
739
  f << "ID=" << std::hex << input->readULong(4) << std::dec << ",";
653
739
  if (vers>=6) {
654
0
    int cLen=int(input->readULong(1));
655
0
    if (cLen>63) {
656
0
      f << "###";
657
0
      MWAW_DEBUG_MSG(("ReadySetGoParser::readDocument: unexpected file name len\n"));
658
0
      cLen=0;
659
0
    }
660
0
    std::string name;
661
0
    for (int i=0; i<cLen; ++i) {
662
0
      char c=char(input->readLong(1));
663
0
      if (c==0)
664
0
        break;
665
0
      name+=c;
666
0
    }
667
0
    f << "printer=" << name << ",";
668
0
    input->seek(pos+4+4+64, librevenge::RVNG_SEEK_SET);
669
0
    for (int i=0; i<8; ++i) { // f2=0|6|8
670
0
      int val=int(input->readLong(2));
671
0
      int const expected[]= {0,0,0,100,0,256,2,0};
672
0
      if (val!=expected[i])
673
0
        f << "f" << i << "=" << val << ",";
674
0
    }
675
0
    for (int i=0; i<12; ++i) {
676
0
      int val=int(input->readLong(2));
677
0
      if (val)
678
0
        f << "g" << i << "=" << val << ",";
679
0
    }
680
0
    ascii().addPos(pos);
681
0
    ascii().addNote(f.str().c_str());
682
0
    input->seek(pos+4+108, librevenge::RVNG_SEEK_SET);
683
684
0
    pos=input->tell();
685
0
    f.str("");
686
0
    f << "Document-0:";
687
0
  }
688
739
  int val=int(input->readLong(2));
689
739
  if (val!=1)
690
739
    f << "first[page]=" << val << ",";
691
739
  m_state->m_numLayouts=int(input->readLong(2));
692
739
  if (m_state->m_numLayouts)
693
663
    f << "num[layout]=" << m_state->m_numLayouts << ",";
694
739
  val=int(input->readLong(2));
695
739
  if (val+1!=m_state->m_numLayouts)
696
738
    f << "act[layout]=" << val << ",";
697
739
  if (vers>=6 && !designStudio) {
698
0
    f << "IDS=[";
699
0
    for (int i=0; i<2; ++i)
700
0
      f << std::hex << input->readULong(4) << std::dec << ",";
701
0
    f << "],";
702
0
    val=int(input->readLong(2));
703
0
    if (val)
704
0
      f << "num[unkn]=" << val << ",";
705
0
    f << "ID0=[";
706
0
    for (int i=0; i<2; ++i)
707
0
      f << std::hex << input->readULong(4) << std::dec << ",";
708
0
    f << "],";
709
0
  }
710
739
  else {
711
739
    f << "IDS=[";
712
2.95k
    for (int i=0; i<3; ++i)
713
2.21k
      f << std::hex << input->readULong(4) << std::dec << ",";
714
739
    f << "],";
715
739
  }
716
739
  val=int(input->readLong(2));
717
739
  if (val) {
718
612
    m_state->m_numGlossary=val;
719
612
    f << "num[glossary]=" << val << ",";
720
612
  }
721
739
  f << "ID1=" << std::hex << input->readULong(4) << std::dec << ",";
722
739
  if (vers>3) {
723
102
    m_state->m_numStyles=int(input->readLong(2));
724
102
    if (m_state->m_numStyles)
725
84
      f << "num[styles]=" << m_state->m_numStyles << ",";
726
102
    f << "ID2=" << std::hex << input->readULong(4) << std::dec << ",";
727
102
  }
728
739
  f << "margins=[";
729
3.69k
  for (int i=0; i<4; ++i) f << float(input->readLong(4))/65536 << ",";
730
739
  f << "],";
731
739
  f << "unkns=[";
732
2.21k
  for (int i=0; i<2; ++i) f << float(input->readLong(4))/65536 << ",";
733
739
  f << "],";
734
2.21k
  for (int i=0; i<2; ++i) {
735
1.47k
    val=int(input->readLong(2));
736
1.47k
    int const expected[]= {4,2};
737
1.47k
    if (val!=expected[i])
738
1.47k
      f << "f" << i+3 << "=" << val << ",";
739
1.47k
  }
740
739
  if (vers>3) {
741
306
    for (int i=0; i<2; ++i) {
742
204
      val=int(input->readLong(1));
743
204
      if (val==-1)
744
11
        f << "fl" << i << ",";
745
193
      else if (val)
746
150
        f << "fl" << i << "=" << val << ",";
747
204
    }
748
102
  }
749
739
  f << "ID3=" << std::hex << input->readULong(4) << std::dec << ",";
750
739
  val=int(input->readLong(2));
751
739
  if (val)
752
594
    f << "f4=" << val << ",";
753
739
  ascii().addPos(pos);
754
739
  ascii().addNote(f.str().c_str());
755
756
739
  pos=input->tell();
757
739
  f.str("");
758
739
  f << "Document-A:";
759
739
  if (vers>3) {
760
102
    int cLen=int(input->readULong(1));
761
102
    if (cLen>61) {
762
11
      f << "###";
763
11
      MWAW_DEBUG_MSG(("ReadySetGoParser::readDocument: unexpected file name len\n"));
764
11
      cLen=0;
765
11
    }
766
102
    std::string name;
767
992
    for (int i=0; i<cLen; ++i) {
768
937
      char c=char(input->readLong(1));
769
937
      if (c==0)
770
47
        break;
771
890
      name+=c;
772
890
    }
773
102
    f << "file=" << name << ",";
774
102
    input->seek(pos+62, librevenge::RVNG_SEEK_SET);
775
102
    ascii().addDelimiter(input->tell(),'|');
776
102
    if (vers>=6) {
777
0
      input->seek(pos+62+12, librevenge::RVNG_SEEK_SET);
778
0
      ascii().addDelimiter(input->tell(),'|');
779
0
      input->seek(pos+62+12+25*6, librevenge::RVNG_SEEK_SET);
780
0
      ascii().addDelimiter(input->tell(),'|');
781
      // then something like 0009206000088000000b00000001000000020003
782
0
    }
783
102
    ascii().addPos(pos);
784
102
    ascii().addNote(f.str().c_str());
785
786
102
    if (vers>=5) {
787
0
      input->seek(pos+(vers<=5 ? 134 : 244), librevenge::RVNG_SEEK_SET);
788
0
      pos=input->tell();
789
0
      f.str("");
790
0
      f << "Document-B:";
791
0
      f << "IDS=[";
792
0
      for (int i=0; i<4; ++i)
793
0
        f << std::hex << input->readULong(4) << std::dec << ",";
794
0
      f << "],";
795
0
      ascii().addDelimiter(input->tell(),'|');
796
0
      input->seek(pos+24, librevenge::RVNG_SEEK_SET);
797
0
      ascii().addDelimiter(input->tell(),'|');
798
0
      val=int(input->readULong(4));
799
0
      if (val) {
800
0
        m_state->m_hasCustomColors=true;
801
0
        f << "color[IDS]=" << std::hex << val << std::dec << ",";
802
0
      }
803
0
      if (vers>=6) {
804
0
        val=int(input->readULong(4));
805
0
        if (val)
806
0
          f << "color[IDS,unkn]=" << std::hex << val << std::dec << ",";
807
0
      }
808
0
      val=int(input->readULong(4));
809
0
      if (val)
810
0
        f << "color[IDS,name]=" << std::hex << val << std::dec << ",";
811
0
      ascii().addDelimiter(input->tell(),'|');
812
0
      ascii().addPos(pos);
813
0
      ascii().addNote(f.str().c_str());
814
0
    }
815
102
    if (vers>=6) {
816
0
      input->seek(pos+188, librevenge::RVNG_SEEK_SET);
817
0
      pos=input->tell();
818
0
      f.str("");
819
0
      f << "Document-C:";
820
0
      f << "IDS=[";
821
0
      for (int i=0; i<4; ++i)
822
0
        f << std::hex << input->readULong(4) << std::dec << ",";
823
0
      f << "],";
824
0
      for (int i=0; i<2; ++i) { // f0=0|2bc
825
0
        val=int(input->readULong(2));
826
0
        int const expected[]= { 0, 0x1f21};
827
0
        if (val!=expected[i])
828
0
          f << "f" << i << "=" << val << ",";
829
0
      }
830
0
      int dim[2];
831
0
      for (auto &d : dim) d=int(input->readULong(2));
832
0
      f << "dim=" << MWAWVec2i(dim[1],dim[0]) << ",";
833
0
      f << "margins?=[";
834
0
      for (int i=0; i<4; ++i) f << input->readLong(2) << ",";
835
0
      f << "],";
836
0
      for (int i=0; i<4; ++i) {
837
0
        val=int(input->readULong(2));
838
0
        if (val!=(i==2 ? 90 : 0))
839
0
          f << "f" << i+2 << "=" << val << ",";
840
0
      }
841
0
      if (designStudio)
842
0
        ascii().addDelimiter(input->tell(),'|');
843
0
      ascii().addPos(pos);
844
0
      ascii().addNote(f.str().c_str());
845
0
    }
846
102
    if (vers>=6 && !designStudio) {
847
0
      for (int i=0; i<26; ++i) {
848
0
        pos=input->tell();
849
0
        f.str("");
850
0
        f << "Document-D" << i << ":";
851
        // 000600008000000080000000800000008000000040000002ff8[01]
852
0
        input->seek(pos+26, librevenge::RVNG_SEEK_SET);
853
0
        ascii().addPos(pos);
854
0
        ascii().addNote(f.str().c_str());
855
0
      }
856
0
      pos=input->tell();
857
0
      f.str("");
858
0
      f << "Document-E:";
859
0
      m_state->m_numObjectGlossary=int(input->readLong(2));
860
0
      if (m_state->m_numObjectGlossary) f << "num[object,glossary]=" << m_state->m_numObjectGlossary << ",";
861
0
      f << "ID0=" << std::hex << input->readULong(4) << std::dec << ",";
862
0
      for (int i=0; i<3; ++i) {
863
0
        val=int(input->readLong(2));
864
0
        if (val) f << "f" << i << "=" << val << ",";
865
0
      }
866
0
      f << "ID1=" << std::hex << input->readULong(4) << std::dec << ",";
867
0
      for (int i=0; i<7; ++i) { // f4=0|256
868
0
        val=int(input->readLong(2));
869
0
        if (val) f << "f" << i+4 << "=" << val << ",";
870
0
      }
871
0
      for (int i=0; i<7; ++i) {
872
0
        val=int(input->readLong(2));
873
0
        int const expected[]= {-1, 45, 0, 60, 0, 0, 300};
874
0
        if (val!=expected[i]) f << "f" << i+11 << "=" << val << ",";
875
0
      }
876
0
      val=int(input->readULong(4));
877
0
      if (val) { // checkme
878
0
        f << "ID2[font]=" << std::hex << val << std::dec << ",";
879
0
        m_state->m_hasFontsBlock2=true;
880
0
      }
881
882
0
      ascii().addDelimiter(input->tell(),'|');
883
      // endPos-4: int16: ragzone percent, a flag:0,1 related to ragged method?
884
0
      ascii().addPos(pos);
885
0
      ascii().addNote(f.str().c_str());
886
0
    }
887
888
102
    input->seek(endPos, librevenge::RVNG_SEEK_SET);
889
102
    return true;
890
102
  }
891
  // vers <= 3
892
637
  std::string name;
893
9.68k
  for (int i=0; i<62; ++i) { // checkme, maybe a string of size 32, followed by...
894
9.63k
    char c=char(input->readLong(1));
895
9.63k
    if (c==0)
896
589
      break;
897
9.04k
    name+=c;
898
9.04k
  }
899
637
  f << "file=" << name << ",";
900
637
  input->seek(pos+62, librevenge::RVNG_SEEK_SET);
901
637
  int dim[2];
902
1.27k
  for (auto &d : dim) d=int(input->readLong(2));
903
637
  f << "dim=" << MWAWVec2i(dim[0],dim[1]) << ",";
904
637
  val=int(input->readLong(2));
905
637
  if (val!=1) f << "unit=" << val << ","; // inch, centimeters, pica
906
3.18k
  for (int i=0; i<4; ++i) {
907
2.54k
    val=int(input->readLong(1));
908
2.54k
    if (val==-1)
909
273
      continue;
910
2.27k
    if (i==0)
911
576
      f << "hide[ruler]";
912
1.69k
    else if (i==1)
913
575
      f << "hide[grid]";
914
1.12k
    else
915
1.12k
      f << "fl" << i;
916
2.27k
    if (val!=0)
917
1.46k
      f << "=" << val << ",";
918
806
    else
919
806
      f << ",";
920
2.27k
  }
921
637
  ascii().addPos(pos);
922
637
  ascii().addNote(f.str().c_str());
923
924
637
  input->seek(endPos, librevenge::RVNG_SEEK_SET);
925
637
  return true;
926
739
}
927
928
bool ReadySetGoParser::readIdsList()
929
0
{
930
0
  if (version()<3) {
931
0
    MWAW_DEBUG_MSG(("ReadySetGoParser::readIdsList: unexpected version\n"));
932
0
    return false;
933
0
  }
934
0
  MWAWInputStreamPtr input = getInput();
935
0
  if (!input)
936
0
    return false;
937
0
  long pos=input->tell();
938
0
  if (!input->checkPosition(pos+4)) {
939
0
    MWAW_DEBUG_MSG(("ReadySetGoParser::readIdsList: can not read the zone length\n"));
940
0
    return false;
941
0
  }
942
0
  libmwaw::DebugStream f;
943
0
  f << "Entries(IDLists):";
944
0
  long len=long(input->readLong(4));
945
0
  long endPos=pos+4+len;
946
0
  if (len<0 || endPos<pos+4 || !input->checkPosition(endPos)) {
947
0
    MWAW_DEBUG_MSG(("ReadySetGoParser::readIdsList: can not read the zone length\n"));
948
0
    f << "###";
949
0
    ascii().addPos(pos);
950
0
    ascii().addNote(f.str().c_str());
951
0
    return false;
952
0
  }
953
0
  if (len==0) {
954
0
    ascii().addPos(pos);
955
0
    ascii().addNote("_");
956
0
    return true;
957
0
  }
958
0
  if (len%4) {
959
0
    MWAW_DEBUG_MSG(("ReadySetGoParser::readIdsList: can not determine the number of IDS\n"));
960
0
    f << "###";
961
0
    ascii().addPos(pos);
962
0
    ascii().addNote(f.str().c_str());
963
0
    input->seek(endPos, librevenge::RVNG_SEEK_SET);
964
0
    return true;
965
0
  }
966
0
  f << "ids=[";
967
0
  for (int i=0; i<len/4; ++i) {
968
0
    auto val=input->readULong(4);
969
0
    if (val)
970
0
      f << std::hex << val << std::dec << ",";
971
0
    else
972
0
      f << "_,";
973
0
  }
974
0
  f << "],";
975
0
  ascii().addPos(pos);
976
0
  ascii().addNote(f.str().c_str());
977
0
  input->seek(endPos, librevenge::RVNG_SEEK_SET);
978
979
0
  return true;
980
0
}
981
982
////////////////////////////////////////////////////////////
983
// try to read the shapes zone
984
////////////////////////////////////////////////////////////
985
bool ReadySetGoParser::readGlossary()
986
0
{
987
0
  MWAWInputStreamPtr input = getInput();
988
0
  if (!input)
989
0
    return false;
990
0
  int const vers=version();
991
0
  long pos=input->tell();
992
0
  libmwaw::DebugStream f;
993
0
  f << "Entries(Glossary):";
994
0
  if (vers<4) {
995
0
    f << "###";
996
0
    ascii().addPos(pos);
997
0
    ascii().addNote(f.str().c_str());
998
0
    MWAW_DEBUG_MSG(("ReadySetGoParser::readGlossary: unexpected version\n"));
999
0
    return false;
1000
0
  }
1001
0
  long len=long(input->readLong(4));
1002
0
  long endPos=pos+4+len;
1003
0
  if (m_state->m_numGlossary<0 || len<52*m_state->m_numGlossary || endPos<pos+4 || !input->checkPosition(endPos)) {
1004
0
    f << "###";
1005
0
    ascii().addPos(pos);
1006
0
    ascii().addNote(f.str().c_str());
1007
0
    MWAW_DEBUG_MSG(("ReadySetGoParser::readGlossary: the zone's length seems bad\n"));
1008
0
    return false;
1009
0
  }
1010
1011
0
  if (len==0) {
1012
0
    ascii().addPos(pos);
1013
0
    ascii().addNote("_");
1014
0
    return true;
1015
0
  }
1016
0
  ascii().addPos(pos);
1017
0
  ascii().addNote(f.str().c_str());
1018
0
  std::vector<bool> hasTabs;
1019
0
  for (int i=0; i<m_state->m_numGlossary; ++i) {
1020
0
    pos=input->tell();
1021
0
    f.str("");
1022
0
    f << "Glossary-" << i << ":";
1023
0
    int cLen=int(input->readULong(1));
1024
0
    if (cLen>35) {
1025
0
      MWAW_DEBUG_MSG(("ReadySetGoParser::readGlossary: the name's length seems bad\n"));
1026
0
      f << "###";
1027
0
      cLen=0;
1028
0
    }
1029
0
    std::string name;
1030
0
    for (int c=0; c<cLen; ++c) {
1031
0
      char ch=char(input->readLong(1));
1032
0
      if (!ch)
1033
0
        break;
1034
0
      name+=ch;
1035
0
    }
1036
0
    f << name << ",";
1037
0
    input->seek(pos+36, librevenge::RVNG_SEEK_SET);
1038
0
    f << "IDS=[";
1039
0
    for (int j=0; j<4; ++j) {
1040
0
      auto id=input->readULong(4);
1041
0
      if (j==2)
1042
0
        hasTabs.push_back(id!=0);
1043
0
      if (!id)
1044
0
        f << "_,";
1045
0
      else
1046
0
        f << std::hex << id << std::dec << ",";
1047
0
    }
1048
0
    f << "],";
1049
0
    input->seek(pos+52, librevenge::RVNG_SEEK_SET);
1050
0
    ascii().addPos(pos);
1051
0
    ascii().addNote(f.str().c_str());
1052
0
  }
1053
0
  input->seek(endPos, librevenge::RVNG_SEEK_SET);
1054
1055
0
  for (size_t i=0; i<size_t(m_state->m_numGlossary); ++i) {
1056
0
    for (int step=0; step<(hasTabs[i] ? 3 : 2); ++step) {
1057
0
      pos=input->tell();
1058
0
      len=long(input->readLong(4));
1059
0
      f.str("");
1060
0
      f << "Glossary-" << (step==0 ? "text" : step==1 ? "style" : "tabs") << "[" << i << "]:";
1061
0
      endPos=pos+4+len;
1062
0
      if (endPos<pos+4 || !input->checkPosition(endPos)) {
1063
0
        MWAW_DEBUG_MSG(("ReadySetGoParser::readGlossary: can not find a data block\n"));
1064
0
        f << "###";
1065
0
        ascii().addPos(pos);
1066
0
        ascii().addNote(f.str().c_str());
1067
0
        return false;
1068
0
      }
1069
0
      switch (step) {
1070
0
      case 0: {
1071
0
        int const begTextPos=vers<6 ? 18 : 58;
1072
0
        if (len<begTextPos+2) {
1073
0
          MWAW_DEBUG_MSG(("ReadySetGoParser::readGlossary[text]: the zone length seems bad\n"));
1074
0
          f << "###";
1075
0
          break;
1076
0
        }
1077
0
        int cLen=int(input->readULong(4));
1078
0
        f << "N=" << cLen << ",";
1079
0
        if (cLen+begTextPos>len || (long)((unsigned long)cLen+(unsigned long)begTextPos)<begTextPos) {
1080
0
          MWAW_DEBUG_MSG(("ReadySetGoParser::readGlossary: can not read the number of caracters\n"));
1081
0
          f << "###";
1082
0
          cLen=0;
1083
0
        }
1084
0
        for (int j=0; j<2; ++j) { // maybe last change font/para
1085
0
          int val=int(input->readLong(4));
1086
0
          if (val!=cLen)
1087
0
            f << "N" << j+1 << "=" << val << ",";
1088
0
        }
1089
0
        f << "IDS=[";
1090
0
        for (int j=0; j<2; ++j) {
1091
0
          auto val=input->readULong(4);
1092
0
          if (val)
1093
0
            f << std::hex << val << std::dec << ",";
1094
0
          else
1095
0
            f << "_,";
1096
0
        }
1097
0
        f << "],";
1098
0
        if (vers>=6) {
1099
0
          ascii().addDelimiter(input->tell(),'|');
1100
0
          input->seek(38, librevenge::RVNG_SEEK_CUR);
1101
0
          ascii().addDelimiter(input->tell(),'|');
1102
0
        }
1103
0
        for (int c=0; c<cLen; ++c) {
1104
0
          unsigned char ch=(unsigned char)input->readULong(1);
1105
0
          if (ch<0x1f && ch!=0x9)
1106
0
            f << "[#" << std::hex << int(ch) << std::dec << "]";
1107
0
          else
1108
0
            f << ch;
1109
0
        }
1110
0
        break;
1111
0
      }
1112
0
      case 1: {
1113
0
        if (len<4) {
1114
0
          MWAW_DEBUG_MSG(("ReadySetGoParser::readGlossary[style]: the zone length seems bad\n"));
1115
0
          f << "###";
1116
0
          break;
1117
0
        }
1118
0
        int N=int(input->readULong(4));
1119
0
        f << "N=" << N << ",";
1120
0
        if (N<0 || (len-4)/(vers==4 ? 30 : vers==5 ? 38 : 48)<N) {
1121
0
          MWAW_DEBUG_MSG(("ReadySetGoParser::readGlossary[style]: can not detect the number of styles\n"));
1122
0
          f << "###";
1123
0
          break;
1124
0
        }
1125
0
        for (int j=0; j<N; ++j) {
1126
0
          int cPos;
1127
0
          MWAWFont font;
1128
0
          MWAWParagraph para;
1129
0
          if (!m_styleManager->readStyle(font, para, &cPos))
1130
0
            break;
1131
0
        }
1132
0
        break;
1133
0
      }
1134
0
      case 2: {
1135
0
        if (len<2) {
1136
0
          MWAW_DEBUG_MSG(("ReadySetGoParser::readGlossary[tab]: the zone length seems bad\n"));
1137
0
          f << "###";
1138
0
          break;
1139
0
        }
1140
0
        int N=int(input->readULong(2));
1141
0
        f << "N=" << N << ",";
1142
0
        if (N<0 || (len-2)/148<N) {
1143
0
          MWAW_DEBUG_MSG(("ReadySetGoParser::readGlossary[tab]: can not detect the number of tabulations\n"));
1144
0
          f << "###";
1145
0
          break;
1146
0
        }
1147
0
        for (int j=0; j<N; ++j) {
1148
0
          int cPos;
1149
0
          std::vector<MWAWTabStop> tabs;
1150
0
          if (!m_styleManager->readTabulations(tabs, 148, &cPos))
1151
0
            break;
1152
0
        }
1153
0
        break;
1154
0
      }
1155
0
      default:
1156
0
        break;
1157
0
      }
1158
0
      ascii().addPos(pos);
1159
0
      ascii().addNote(f.str().c_str());
1160
0
      input->seek(endPos, librevenge::RVNG_SEEK_SET);
1161
0
    }
1162
0
  }
1163
1164
0
  return true;
1165
0
}
1166
1167
bool ReadySetGoParser::readObjectGlossary()
1168
0
{
1169
0
  MWAWInputStreamPtr input = getInput();
1170
0
  if (!input)
1171
0
    return false;
1172
0
  int const vers=version();
1173
0
  long pos=input->tell();
1174
0
  libmwaw::DebugStream f;
1175
0
  f << "Entries(ObjGloss):";
1176
0
  if (vers<6) {
1177
0
    f << "###";
1178
0
    ascii().addPos(pos);
1179
0
    ascii().addNote(f.str().c_str());
1180
0
    MWAW_DEBUG_MSG(("ReadySetGoParser::readObjectGlossary: unexpected version\n"));
1181
0
    return false;
1182
0
  }
1183
0
  long len=long(input->readLong(4));
1184
0
  long endPos=pos+4+len;
1185
0
  if (m_state->m_numObjectGlossary<0 || len<40*m_state->m_numObjectGlossary || endPos<pos+4 || !input->checkPosition(endPos)) {
1186
0
    f << "###";
1187
0
    ascii().addPos(pos);
1188
0
    ascii().addNote(f.str().c_str());
1189
0
    MWAW_DEBUG_MSG(("ReadySetGoParser::readObjectGlossary: the zone's length seems bad\n"));
1190
0
    return false;
1191
0
  }
1192
1193
0
  if (len==0) {
1194
0
    ascii().addPos(pos);
1195
0
    ascii().addNote("_");
1196
0
    return true;
1197
0
  }
1198
0
  ascii().addPos(pos);
1199
0
  ascii().addNote(f.str().c_str());
1200
0
  for (int i=0; i<m_state->m_numObjectGlossary; ++i) {
1201
0
    pos=input->tell();
1202
0
    f.str("");
1203
0
    f << "ObjGloss-" << i << ":";
1204
0
    int cLen=int(input->readULong(1));
1205
0
    if (cLen>35) {
1206
0
      MWAW_DEBUG_MSG(("ReadySetGoParser::readObjectGlossary: the name's length seems bad\n"));
1207
0
      f << "###";
1208
0
      cLen=0;
1209
0
    }
1210
0
    std::string name;
1211
0
    for (int c=0; c<cLen; ++c) {
1212
0
      char ch=char(input->readLong(1));
1213
0
      if (!ch)
1214
0
        break;
1215
0
      name+=ch;
1216
0
    }
1217
0
    f << name << ",";
1218
0
    input->seek(pos+36, librevenge::RVNG_SEEK_SET);
1219
0
    f << "IDS=[";
1220
0
    for (int j=0; j<1; ++j) {
1221
0
      auto id=input->readULong(4);
1222
0
      if (!id)
1223
0
        f << "_,";
1224
0
      else
1225
0
        f << std::hex << id << std::dec << ",";
1226
0
    }
1227
0
    f << "],";
1228
0
    input->seek(pos+40, librevenge::RVNG_SEEK_SET);
1229
0
    ascii().addPos(pos);
1230
0
    ascii().addNote(f.str().c_str());
1231
0
  }
1232
0
  input->seek(endPos, librevenge::RVNG_SEEK_SET);
1233
0
  for (int i=0; i<m_state->m_numObjectGlossary; ++i) {
1234
0
    if (!m_graphParser->readShapesInObject())
1235
0
      return false;
1236
0
  }
1237
1238
0
  return true;
1239
0
}
1240
1241
bool ReadySetGoParser::readFontsUnknown()
1242
0
{
1243
0
  MWAWInputStreamPtr input = getInput();
1244
0
  if (!input)
1245
0
    return false;
1246
0
  int const vers=version();
1247
0
  long pos=input->tell();
1248
0
  libmwaw::DebugStream f;
1249
0
  f << "Entries(FontUnkn):";
1250
0
  if (vers<6) {
1251
0
    f << "###";
1252
0
    ascii().addPos(pos);
1253
0
    ascii().addNote(f.str().c_str());
1254
0
    MWAW_DEBUG_MSG(("ReadySetGoParser::readFontsUnknown: unexpected version\n"));
1255
0
    return false;
1256
0
  }
1257
0
  long len=long(input->readLong(4));
1258
0
  long endPos=pos+4+len;
1259
0
  if ((len && (len%8)!=2) || endPos<pos+4 || !input->checkPosition(endPos)) {
1260
0
    f << "###";
1261
0
    ascii().addPos(pos);
1262
0
    ascii().addNote(f.str().c_str());
1263
0
    MWAW_DEBUG_MSG(("ReadySetGoParser::readFontsUnknown: the zone's length seems bad\n"));
1264
0
    return false;
1265
0
  }
1266
1267
0
  if (len==0) {
1268
0
    ascii().addPos(pos);
1269
0
    ascii().addNote("_");
1270
0
    return true;
1271
0
  }
1272
1273
0
  int N=int(input->readULong(2));
1274
0
  f << "N=" << N << ",";
1275
0
  if (8*N+2 != len) {
1276
0
    f << "###";
1277
0
    ascii().addPos(pos);
1278
0
    ascii().addNote(f.str().c_str());
1279
0
    MWAW_DEBUG_MSG(("ReadySetGoParser::readFontsUnknown: can not read the number of elements\n"));
1280
0
    return false;
1281
0
  }
1282
0
  f << "fonts=[";
1283
0
  for (int i=0; i<N; ++i) {
1284
0
    f << "[";
1285
0
    f << "fId=" << input->readULong(2) << ",";
1286
0
    int val=int(input->readULong(1));
1287
0
    if (val) f << "fFlags=" << std::hex << val << std::dec << ",";
1288
0
    val=int(input->readULong(1));
1289
0
    if (val)
1290
0
      f << "fl=" << val << ",";
1291
0
    val=int(input->readULong(4));
1292
0
    if (val)
1293
0
      f << "ID=" << std::hex << val << std::dec << ",";
1294
0
    f << "],";
1295
0
  }
1296
0
  f << "],";
1297
0
  ascii().addPos(pos);
1298
0
  ascii().addNote(f.str().c_str());
1299
0
  for (int i=0; i<N; ++i) {
1300
0
    pos=input->tell();
1301
0
    f.str("");
1302
0
    f << "FontUnkn-" << i << ":";
1303
0
    len=long(input->readLong(4));
1304
0
    endPos=pos+4+len;
1305
0
    if (endPos<pos+4 || len<2 || !input->checkPosition(endPos)) {
1306
0
      f << "###";
1307
0
      ascii().addPos(pos);
1308
0
      ascii().addNote(f.str().c_str());
1309
0
      MWAW_DEBUG_MSG(("ReadySetGoParser::readFontsUnknown: can not find a sub zone\n"));
1310
0
      return false;
1311
0
    }
1312
0
    int N1=int(input->readULong(2));
1313
0
    f << "N=" << N1 << ",";
1314
0
    if (2+4*N1>len) {
1315
0
      f << "###";
1316
0
      ascii().addPos(pos);
1317
0
      ascii().addNote(f.str().c_str());
1318
0
      MWAW_DEBUG_MSG(("ReadySetGoParser::readFontsUnknown: can not find the number of data\n"));
1319
0
      return false;
1320
0
    }
1321
0
    ascii().addDelimiter(input->tell(),'|');
1322
0
    ascii().addPos(pos);
1323
0
    ascii().addNote(f.str().c_str());
1324
0
    input->seek(endPos, librevenge::RVNG_SEEK_SET);
1325
0
  }
1326
0
  return true;
1327
0
}
1328
1329
bool ReadySetGoParser::readZone11()
1330
0
{
1331
0
  MWAWInputStreamPtr input = getInput();
1332
0
  if (!input)
1333
0
    return false;
1334
0
  int const vers=version();
1335
0
  long pos=input->tell();
1336
0
  libmwaw::DebugStream f;
1337
0
  f << "Entries(Zone11A):";
1338
0
  if (vers<6) {
1339
0
    f << "###";
1340
0
    ascii().addPos(pos);
1341
0
    ascii().addNote(f.str().c_str());
1342
0
    MWAW_DEBUG_MSG(("ReadySetGoParser::readZone11: unexpected version\n"));
1343
0
    return false;
1344
0
  }
1345
0
  long len=long(input->readLong(4));
1346
0
  long endPos=pos+4+len;
1347
0
  if ((len && len<0x138) || endPos<pos+4 || !input->checkPosition(endPos)) {
1348
0
    f << "###";
1349
0
    ascii().addPos(pos);
1350
0
    ascii().addNote(f.str().c_str());
1351
0
    MWAW_DEBUG_MSG(("ReadySetGoParser::readZone11: the zone's length seems bad\n"));
1352
0
    return false;
1353
0
  }
1354
1355
0
  if (len==0) {
1356
0
    ascii().addPos(pos);
1357
0
    ascii().addNote("_");
1358
0
    return true;
1359
0
  }
1360
1361
0
  input->seek(pos+300, librevenge::RVNG_SEEK_SET);
1362
0
  ascii().addDelimiter(input->tell(), '|');
1363
0
  int N=int(input->readULong(2));
1364
0
  f << "N=" << N << ",";
1365
0
  if (len<0x138+28*N) {
1366
0
    f << "###";
1367
0
    ascii().addPos(pos);
1368
0
    ascii().addNote(f.str().c_str());
1369
0
    MWAW_DEBUG_MSG(("ReadySetGoParser::readZone11: can not read the number of data\n"));
1370
0
    return false;
1371
0
  }
1372
0
  ascii().addPos(pos);
1373
0
  ascii().addNote(f.str().c_str());
1374
1375
0
  input->seek(pos+4+0x138, librevenge::RVNG_SEEK_SET);
1376
0
  for (int i=0; i<N; ++i) {
1377
0
    pos=input->tell();
1378
0
    f.str("");
1379
0
    f << "Zone11A-" << i << ":";
1380
0
    input->seek(pos+28, librevenge::RVNG_SEEK_SET);
1381
0
    ascii().addPos(pos);
1382
0
    ascii().addNote(f.str().c_str());
1383
0
  }
1384
0
  input->seek(endPos, librevenge::RVNG_SEEK_SET);
1385
0
  return true;
1386
0
}
1387
1388
////////////////////////////////////////////////////////////
1389
// try to read the print info zone
1390
////////////////////////////////////////////////////////////
1391
bool ReadySetGoParser::readPrintInfo()
1392
1.12k
{
1393
1.12k
  MWAWInputStreamPtr input = getInput();
1394
1.12k
  int const vers=version();
1395
1.12k
  long pos=input->tell();
1396
1.12k
  long endPos=pos+120+(vers<3 ? 2 : 4);
1397
1.12k
  if (!input->checkPosition(endPos) || input->readULong((vers<3 ? 2 : 4))!=0x78) {
1398
753
    MWAW_DEBUG_MSG(("ReadySetGoParser::readPrintInfo: file seems too short\n"));
1399
753
    return false;
1400
753
  }
1401
371
  libmwaw::DebugStream f;
1402
371
  f << "Entries(PrintInfo):";
1403
371
  libmwaw::PrinterInfo info;
1404
371
  if (!info.read(input)) {
1405
41
    MWAW_DEBUG_MSG(("ReadySetGoParser::readPrintInfo: can not read print info\n"));
1406
41
    return false;
1407
41
  }
1408
330
  f << info;
1409
330
  MWAWVec2i paperSize = info.paper().size();
1410
330
  MWAWVec2i pageSize = info.page().size();
1411
330
  if (pageSize.x() <= 0 || pageSize.y() <= 0 ||
1412
275
      paperSize.x() <= 0 || paperSize.y() <= 0) {
1413
275
    ascii().addPos(pos);
1414
275
    ascii().addNote(f.str().c_str());
1415
275
    input->seek(endPos, librevenge::RVNG_SEEK_SET);
1416
275
    return true;
1417
275
  }
1418
1419
  // define margin from print info
1420
55
  MWAWVec2i lTopMargin= -1 * info.paper().pos(0);
1421
55
  MWAWVec2i rBotMargin=info.paper().size() - info.page().size();
1422
1423
  // move margin left | top
1424
55
  int decalX = lTopMargin.x() > 14 ? lTopMargin.x()-14 : 0;
1425
55
  int decalY = lTopMargin.y() > 14 ? lTopMargin.y()-14 : 0;
1426
55
  lTopMargin -= MWAWVec2i(decalX, decalY);
1427
55
  rBotMargin += MWAWVec2i(decalX, decalY);
1428
1429
  // decrease right | bottom
1430
55
  int rightMarg = rBotMargin.x() -50;
1431
55
  if (rightMarg < 0) rightMarg=0;
1432
55
  int botMarg = rBotMargin.y() -50;
1433
55
  if (botMarg < 0) botMarg=0;
1434
1435
55
  getPageSpan().setMarginTop(lTopMargin.y()/72.0);
1436
55
  getPageSpan().setMarginBottom(botMarg/72.0);
1437
55
  getPageSpan().setMarginLeft(lTopMargin.x()/72.0);
1438
55
  getPageSpan().setMarginRight(rightMarg/72.0);
1439
55
  getPageSpan().setFormLength(paperSize.y()/72.);
1440
55
  getPageSpan().setFormWidth(paperSize.x()/72.);
1441
1442
55
  ascii().addPos(pos);
1443
55
  ascii().addNote(f.str().c_str());
1444
55
  input->seek(endPos, librevenge::RVNG_SEEK_SET);
1445
55
  return true;
1446
330
}
1447
1448
// vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: