Coverage Report

Created: 2026-07-20 07:04

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
38.8k
    : m_designStudio(false)
72
38.8k
    , m_numLayouts(1)
73
38.8k
    , m_numGlossary(0)
74
38.8k
    , m_numObjectGlossary(0)
75
38.8k
    , m_numStyles(0)
76
38.8k
    , m_hasCustomColors(false)
77
38.8k
    , m_hasFontsBlock2(false)
78
38.8k
  {
79
38.8k
  }
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
18.7k
  : MWAWGraphicParser(input, rsrcParser, header)
103
18.7k
  , m_graphParser()
104
18.7k
  , m_styleManager()
105
18.7k
  , m_state(new ReadySetGoParserInternal::State)
106
18.7k
{
107
18.7k
  m_styleManager.reset(new ReadySetGoStyleManager(*this));
108
18.7k
  m_graphParser.reset(new ReadySetGoGraph(*this));
109
18.7k
  setAsciiName("main-1");
110
18.7k
  getPageSpan().setMargins(0.1);
111
18.7k
}
112
113
ReadySetGoParser::~ReadySetGoParser()
114
18.7k
{
115
18.7k
}
116
117
bool ReadySetGoParser::isDesignStudioFile() const
118
2.07k
{
119
2.07k
  return m_state->m_designStudio;
120
2.07k
}
121
122
////////////////////////////////////////////////////////////
123
// the parser
124
////////////////////////////////////////////////////////////
125
void ReadySetGoParser::parse(librevenge::RVNGDrawingInterface *docInterface)
126
1.35k
{
127
1.35k
  if (!getInput().get() || !checkHeader(nullptr))  throw(libmwaw::ParseException());
128
1.35k
  bool ok = false;
129
1.35k
  try {
130
    // create the asciiFile
131
1.35k
    ascii().setStream(getInput());
132
1.35k
    ascii().open(asciiName());
133
1.35k
    checkHeader(nullptr);
134
135
    // update the style manager, ...
136
1.35k
    ok = createZones();
137
1.35k
    if (ok) {
138
73
      createDocument(docInterface);
139
73
      ok=getGraphicListener() && m_graphParser->sendPages();
140
73
    }
141
1.35k
    ascii().reset();
142
1.35k
  }
143
1.35k
  catch (...) {
144
0
    MWAW_DEBUG_MSG(("ReadySetGoParser::parse: exception catched when parsing\n"));
145
0
    ok = false;
146
0
  }
147
148
1.35k
  resetGraphicListener();
149
1.35k
  if (!ok) throw(libmwaw::ParseException());
150
1.35k
}
151
152
////////////////////////////////////////////////////////////
153
// create the document
154
////////////////////////////////////////////////////////////
155
void ReadySetGoParser::createDocument(librevenge::RVNGDrawingInterface *documentInterface)
156
73
{
157
73
  if (!documentInterface) return;
158
73
  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
73
  std::vector<MWAWPageSpan> pageList;
165
73
  m_graphParser->updatePageSpanList(pageList);
166
73
  MWAWGraphicListenerPtr listen(new MWAWGraphicListener(*getParserState(), pageList, documentInterface));
167
73
  setGraphicListener(listen);
168
73
  listen->startDocument();
169
73
  m_graphParser->sendMasterPages();
170
73
}
171
172
////////////////////////////////////////////////////////////
173
//
174
// Intermediate level
175
//
176
////////////////////////////////////////////////////////////
177
bool ReadySetGoParser::createZones()
178
1.35k
{
179
1.35k
  auto input=getInput();
180
1.35k
  int const vers=version();
181
1.35k
  bool const designStudio=isDesignStudioFile();
182
1.35k
  if (!input) {
183
0
    MWAW_DEBUG_MSG(("ReadySetGoParser::createZones: no input\n"));
184
0
    return false;
185
0
  }
186
1.35k
  libmwaw::DebugStream f;
187
1.35k
  if (vers<3)
188
163
    input->seek(0, librevenge::RVNG_SEEK_SET);
189
1.19k
  else if (vers==3) {
190
574
    input->seek(2, librevenge::RVNG_SEEK_SET);
191
574
    if (!readDocument())
192
15
      return false;
193
574
  }
194
618
  else {
195
618
    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
618
    input->seek(2, librevenge::RVNG_SEEK_SET);
200
618
    f.str("");
201
618
    f << "Entries(ZonePos):";
202
618
    std::map<long, int> posToId;
203
618
    f << "pos=[";
204
1.73k
    for (int i=0; i<(vers==4 ? 2 : vers==5 ? 5 : 12); ++i) { // Style, ????
205
1.21k
      long posi=input->readLong(4);
206
1.21k
      f << std::hex << posi << std::dec << ",";
207
1.21k
      if (posi<(vers==4 ? 0x100 : 0x300) || !input->checkPosition(posi)) {
208
93
        MWAW_DEBUG_MSG(("ReadySetGoParser::createZones: the %d th positions seems bad\n", i));
209
93
        f << "###";
210
93
        ascii().addPos(2);
211
93
        ascii().addNote(f.str().c_str());
212
93
        return false;
213
93
      }
214
1.11k
      posToId[posi]=i;
215
1.11k
    }
216
525
    f << "],";
217
24.1k
    for (int i=0; i<(vers==4 ? 45 : vers==5 ? 39 : 75); ++i) {
218
23.6k
      int val=int(input->readLong(2));
219
23.6k
      if (val)
220
17.8k
        f << "f" << i << "=" << val << ",";
221
23.6k
    }
222
525
    ascii().addPos(2);
223
525
    ascii().addNote(f.str().c_str());
224
225
    // first zone
226
525
    if (!readDocument() || !readPrintInfo() || !m_graphParser->readLayoutsList(m_state->m_numLayouts))
227
525
      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
722
  if (!readPrintInfo())
338
593
    return false;
339
340
129
  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
129
  if (!m_graphParser->readShapes())
366
56
    return false;
367
368
73
  if (!input->isEnd()) {
369
0
    MWAW_DEBUG_MSG(("ReadySetGoParser::createZones: find extra data\n"));
370
0
    ascii().addPos(input->tell());
371
0
    ascii().addNote("Entries(Extra):###");
372
0
  }
373
73
  return true;
374
129
}
375
376
377
////////////////////////////////////////////////////////////
378
// read the header
379
////////////////////////////////////////////////////////////
380
bool ReadySetGoParser::checkHeader(MWAWHeader *header, bool strict)
381
20.0k
{
382
20.0k
  *m_state = ReadySetGoParserInternal::State();
383
20.0k
  MWAWInputStreamPtr input = getInput();
384
20.0k
  if (!input || !input->hasDataFork() || !input->checkPosition(126))
385
1.35k
    return false;
386
387
18.7k
  libmwaw::DebugStream f;
388
18.7k
  f << "FileHeader:";
389
18.7k
  input->seek(0, librevenge::RVNG_SEEK_SET);
390
18.7k
  int val=int(input->readULong(2));
391
18.7k
  f << "vers=" << val << ",";
392
18.7k
  int vers=1;
393
18.7k
  m_state->m_designStudio=false;
394
18.7k
  if (val==0x1e) { // 30
395
4.10k
    if (input->readULong(2) || input->readULong(2)!=0x86)
396
0
      return false;
397
4.10k
    vers=3;
398
4.10k
  }
399
14.6k
  else if (val>=400 && val<=402) // I only see 400
400
5.15k
    vers=4;
401
9.47k
  else if (val>=5000 && val<=5005) // I only see 5003 v4.5
402
327
    vers=5;
403
9.15k
  else if (val>=6000 && val<=6003) //I only see 6000
404
248
    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.90k
  else if (val==7100) // 7100 v7.1
409
937
    vers=7;
410
7.96k
  else if (val==0x13e4) { // Design Studio, visibly was forked between RSG 4.5 and RSG 6
411
205
    f << "designStudio,";
412
205
    m_state->m_designStudio=true;
413
205
    vers=6;
414
205
  }
415
7.76k
  else if (val!=0x78)
416
31
    return false;
417
18.7k
  ascii().addPos(0);
418
18.7k
  ascii().addNote(f.str().c_str());
419
420
18.7k
  if (vers<3) {
421
    // we need to retrieve the version v1 or v2
422
7.73k
    input->seek(2+120, librevenge::RVNG_SEEK_SET);
423
7.73k
    int n=int(input->readULong(2));
424
7.73k
    if (n<=0)
425
272
      return false;
426
427
    //
428
    // first test for version 2, the more structured
429
    //
430
7.45k
    bool ok=true;
431
7.45k
    vers=2;
432
7.45k
    int nShapes=0;
433
661k
    for (int p=0; p<n; ++p) {
434
658k
      long pos=input->tell();
435
658k
      if (!input->checkPosition(pos+2)) {
436
1.07k
        ok=false;
437
1.07k
        break;
438
1.07k
      }
439
657k
      val=int(input->readLong(2));
440
657k
      if (val<0) {
441
3.87k
        ok=false;
442
3.87k
        break;
443
3.87k
      }
444
653k
      nShapes+=val;
445
653k
    }
446
7.82k
    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.91k
        ok=false;
450
3.91k
        break;
451
3.91k
      }
452
1.97k
      int type=int(input->readULong(2));
453
1.97k
      if (type<0 || type>6) {
454
902
        ok=false;
455
902
        break;
456
902
      }
457
1.06k
      input->seek(2, librevenge::RVNG_SEEK_CUR);
458
1.92k
      for (int i=0; i<2; ++i) {
459
1.54k
        pos=input->tell();
460
1.54k
        int len=int(input->readULong(2));
461
1.54k
        if ((i==0 && len!=0x1c) || !input->checkPosition(pos+2+len)) {
462
689
          ok=false;
463
689
          break;
464
689
        }
465
856
        input->seek(pos+2+len, librevenge::RVNG_SEEK_SET);
466
856
      }
467
1.06k
      if (!ok)
468
689
        break;
469
379
      if (type==3 && !input->isEnd()) {
470
        // we must check if there is a picture
471
41
        pos=input->tell();
472
41
        int len=int(input->readULong(2));
473
41
        if (len<10)
474
17
          input->seek(pos, librevenge::RVNG_SEEK_SET);
475
24
        else {
476
24
          if (!input->checkPosition(pos+2+len)) {
477
15
            ok=false;
478
15
            break;
479
15
          }
480
9
          input->seek(pos+2+len, librevenge::RVNG_SEEK_SET);
481
9
        }
482
41
      }
483
364
      if (type!=4)
484
135
        continue;
485
490
      for (int st=0; st<2; ++st) { // zone1=[text, style], zone2=[para]
486
394
        pos=input->tell();
487
394
        int len=int(input->readULong(2));
488
394
        if (!input->checkPosition(pos+2+len)) {
489
133
          ok=false;
490
133
          break;
491
133
        }
492
261
        input->seek(pos+2+len, librevenge::RVNG_SEEK_SET);
493
261
      }
494
229
    }
495
7.45k
    if (ok && nShapes<=10 && !input->isEnd())
496
301
      ok=false;
497
498
7.45k
    if (!ok) {
499
      // test for version 1
500
7.19k
      ok=true;
501
7.19k
      vers=1;
502
7.19k
      input->seek(2+120+2, librevenge::RVNG_SEEK_SET);
503
12.6k
      for (int i=0; i<std::min(10,n); ++i) {
504
12.1k
        long pos=input->tell();
505
12.1k
        if (!input->checkPosition(pos+26)) {
506
2.45k
          ok=false;
507
2.45k
          break;
508
2.45k
        }
509
9.66k
        int type=int(input->readLong(2));
510
9.66k
        if (type<0 || type>5 || type==2) {
511
2.48k
          ok=false;
512
2.48k
          break;
513
2.48k
        }
514
7.18k
        int const expectedSize[]= {26, 74, 0, 30, 28, 28};
515
7.18k
        if (expectedSize[type]<=0 || !input->checkPosition(pos+expectedSize[type])) {
516
180
          ok=false;
517
180
          break;
518
180
        }
519
7.00k
        input->seek(pos+expectedSize[type], librevenge::RVNG_SEEK_SET);
520
7.00k
        if (type==0 && i+1!=n) {
521
1.14k
          ok=false;
522
1.14k
          break;
523
1.14k
        }
524
5.86k
        if (type==5 && !input->isEnd()) {
525
          // we must check if there is a picture
526
2.52k
          pos=input->tell();
527
2.52k
          int len=int(input->readULong(2));
528
2.52k
          if (len<10)
529
1.71k
            input->seek(pos, librevenge::RVNG_SEEK_SET);
530
812
          else {
531
812
            if (!input->checkPosition(pos+2+len)) {
532
404
              ok=false;
533
404
              break;
534
404
            }
535
408
            input->seek(pos+2+len, librevenge::RVNG_SEEK_SET);
536
408
          }
537
2.52k
        }
538
5.45k
        if (type!=1)
539
4.05k
          continue;
540
2.82k
        for (int st=0; st<2; ++st) {
541
2.34k
          pos=input->tell();
542
2.34k
          int len=int(input->readULong(2));
543
2.34k
          if (!input->checkPosition(pos+2+len)) {
544
926
            ok=false;
545
926
            break;
546
926
          }
547
1.41k
          input->seek(pos+2+len, librevenge::RVNG_SEEK_SET);
548
1.41k
        }
549
1.40k
      }
550
7.19k
      if (ok && n<=10 && !input->isEnd())
551
178
        ok=false;
552
7.19k
    }
553
7.45k
    if (!ok)
554
6.89k
      return false;
555
7.45k
  }
556
10.9k
  else if (vers==3) {
557
4.10k
    if (strict) {
558
1.60k
      input->seek(2, librevenge::RVNG_SEEK_SET);
559
3.43k
      for (int i=0; i<3; ++i) {
560
3.34k
        long pos=input->tell();
561
3.34k
        long len=long(input->readLong(4));
562
3.34k
        if ((long)((unsigned long)pos+4+(unsigned long)len)<pos+4 || !input->checkPosition(pos+4+len))
563
1.46k
          return false;
564
1.87k
        if (len==0 && i<2)
565
43
          return false;
566
1.83k
        input->seek(pos+4+len, librevenge::RVNG_SEEK_SET);
567
1.83k
      }
568
1.60k
    }
569
4.10k
  }
570
6.86k
  else { // vers>3
571
6.86k
    if (vers>=6 && !input->checkPosition(200+20))
572
230
      return false;
573
574
6.63k
    input->seek(2, librevenge::RVNG_SEEK_SET);
575
    // first check the initial list of pointers
576
6.63k
    int emptyZone=0;
577
18.7k
    for (int i=0; i<(vers==4 ? 2 : vers==5 ? 5 : 12); ++i) {
578
14.7k
      long pos=long(input->readLong(4));
579
14.7k
      if (pos==0)
580
5.31k
        ++emptyZone;
581
9.45k
      else if (pos<(vers==4 ? 0x100 : 0x300) || !input->checkPosition(pos))
582
2.64k
        return false;
583
14.7k
    }
584
3.99k
    if (emptyZone>1)
585
144
      return false;
586
3.85k
    if (strict) {
587
1.36k
      input->seek(vers<=5 ? 100 : 200, librevenge::RVNG_SEEK_SET);
588
1.67k
      for (int step=0; step<4; ++step) {
589
1.67k
        long pos=input->tell();
590
1.67k
        long len=long(input->readLong(4));
591
1.67k
        if (pos+4+len<pos+len || !input->checkPosition(pos+4+len))
592
1.24k
          return false;
593
437
        if (step==0 && len<(vers==4 ? 0xcc : vers==5 ? 0x188 : vers==6 ? (m_state->m_designStudio ? 0x2be : 0x58c) : 0x5a0))
594
60
          return false;
595
377
        if (step==1 && len!=0x78)
596
59
          return false;
597
318
        input->seek(pos+4+len, librevenge::RVNG_SEEK_SET);
598
318
      }
599
1.36k
    }
600
3.85k
  }
601
5.65k
  setVersion(vers);
602
5.65k
  if (header)
603
2.94k
    header->reset(MWAWDocument::MWAW_T_READYSETGO, vers, MWAWDocument::MWAW_K_DRAW);
604
605
5.65k
  return true;
606
18.7k
}
607
608
////////////////////////////////////////////////////////////
609
// try to read the main zone
610
////////////////////////////////////////////////////////////
611
bool ReadySetGoParser::readDocument()
612
1.09k
{
613
1.09k
  int const vers=version();
614
1.09k
  if (vers<3) {
615
0
    MWAW_DEBUG_MSG(("ReadySetGoParser::readDocument: unexpected version\n"));
616
0
    return false;
617
0
  }
618
1.09k
  MWAWInputStreamPtr input = getInput();
619
1.09k
  if (!input)
620
0
    return false;
621
1.09k
  long pos=input->tell();
622
1.09k
  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.09k
  libmwaw::DebugStream f;
627
1.09k
  f << "Entries(Document):";
628
1.09k
  long len=long(input->readLong(4));
629
1.09k
  long endPos=pos+4+len;
630
1.09k
  if (len<0 || !input->checkPosition(endPos)) {
631
408
    MWAW_DEBUG_MSG(("ReadySetGoParser::readDocument: can not read the zone length\n"));
632
408
    f << "###";
633
408
    ascii().addPos(pos);
634
408
    ascii().addNote(f.str().c_str());
635
408
    return false;
636
408
  }
637
691
  bool const designStudio=isDesignStudioFile();
638
691
  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
691
  if (len<expectedLength) {
640
10
    MWAW_DEBUG_MSG(("ReadySetGoParser::readDocument: unexpected zone length\n"));
641
10
    f << "###";
642
10
    ascii().addPos(pos);
643
10
    ascii().addNote(f.str().c_str());
644
10
    input->seek(endPos, librevenge::RVNG_SEEK_SET);
645
10
    return true;
646
10
  }
647
681
  if (len>expectedLength) {
648
122
    MWAW_DEBUG_MSG(("ReadySetGoParser::readDocument: find extra data\n"));
649
122
    ascii().addPos(pos+4+expectedLength);
650
122
    ascii().addNote("Document-extra:###");
651
122
  }
652
681
  f << "ID=" << std::hex << input->readULong(4) << std::dec << ",";
653
681
  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
681
  int val=int(input->readLong(2));
689
681
  if (val!=1)
690
681
    f << "first[page]=" << val << ",";
691
681
  m_state->m_numLayouts=int(input->readLong(2));
692
681
  if (m_state->m_numLayouts)
693
602
    f << "num[layout]=" << m_state->m_numLayouts << ",";
694
681
  val=int(input->readLong(2));
695
681
  if (val+1!=m_state->m_numLayouts)
696
681
    f << "act[layout]=" << val << ",";
697
681
  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
681
  else {
711
681
    f << "IDS=[";
712
2.72k
    for (int i=0; i<3; ++i)
713
2.04k
      f << std::hex << input->readULong(4) << std::dec << ",";
714
681
    f << "],";
715
681
  }
716
681
  val=int(input->readLong(2));
717
681
  if (val) {
718
579
    m_state->m_numGlossary=val;
719
579
    f << "num[glossary]=" << val << ",";
720
579
  }
721
681
  f << "ID1=" << std::hex << input->readULong(4) << std::dec << ",";
722
681
  if (vers>3) {
723
122
    m_state->m_numStyles=int(input->readLong(2));
724
122
    if (m_state->m_numStyles)
725
95
      f << "num[styles]=" << m_state->m_numStyles << ",";
726
122
    f << "ID2=" << std::hex << input->readULong(4) << std::dec << ",";
727
122
  }
728
681
  f << "margins=[";
729
3.40k
  for (int i=0; i<4; ++i) f << float(input->readLong(4))/65536 << ",";
730
681
  f << "],";
731
681
  f << "unkns=[";
732
2.04k
  for (int i=0; i<2; ++i) f << float(input->readLong(4))/65536 << ",";
733
681
  f << "],";
734
2.04k
  for (int i=0; i<2; ++i) {
735
1.36k
    val=int(input->readLong(2));
736
1.36k
    int const expected[]= {4,2};
737
1.36k
    if (val!=expected[i])
738
1.36k
      f << "f" << i+3 << "=" << val << ",";
739
1.36k
  }
740
681
  if (vers>3) {
741
366
    for (int i=0; i<2; ++i) {
742
244
      val=int(input->readLong(1));
743
244
      if (val==-1)
744
15
        f << "fl" << i << ",";
745
229
      else if (val)
746
180
        f << "fl" << i << "=" << val << ",";
747
244
    }
748
122
  }
749
681
  f << "ID3=" << std::hex << input->readULong(4) << std::dec << ",";
750
681
  val=int(input->readLong(2));
751
681
  if (val)
752
577
    f << "f4=" << val << ",";
753
681
  ascii().addPos(pos);
754
681
  ascii().addNote(f.str().c_str());
755
756
681
  pos=input->tell();
757
681
  f.str("");
758
681
  f << "Document-A:";
759
681
  if (vers>3) {
760
122
    int cLen=int(input->readULong(1));
761
122
    if (cLen>61) {
762
15
      f << "###";
763
15
      MWAW_DEBUG_MSG(("ReadySetGoParser::readDocument: unexpected file name len\n"));
764
15
      cLen=0;
765
15
    }
766
122
    std::string name;
767
1.12k
    for (int i=0; i<cLen; ++i) {
768
1.06k
      char c=char(input->readLong(1));
769
1.06k
      if (c==0)
770
61
        break;
771
1.00k
      name+=c;
772
1.00k
    }
773
122
    f << "file=" << name << ",";
774
122
    input->seek(pos+62, librevenge::RVNG_SEEK_SET);
775
122
    ascii().addDelimiter(input->tell(),'|');
776
122
    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
122
    ascii().addPos(pos);
784
122
    ascii().addNote(f.str().c_str());
785
786
122
    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
122
    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
122
    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
122
    input->seek(endPos, librevenge::RVNG_SEEK_SET);
889
122
    return true;
890
122
  }
891
  // vers <= 3
892
559
  std::string name;
893
9.87k
  for (int i=0; i<62; ++i) { // checkme, maybe a string of size 32, followed by...
894
9.82k
    char c=char(input->readLong(1));
895
9.82k
    if (c==0)
896
507
      break;
897
9.32k
    name+=c;
898
9.32k
  }
899
559
  f << "file=" << name << ",";
900
559
  input->seek(pos+62, librevenge::RVNG_SEEK_SET);
901
559
  int dim[2];
902
1.11k
  for (auto &d : dim) d=int(input->readLong(2));
903
559
  f << "dim=" << MWAWVec2i(dim[0],dim[1]) << ",";
904
559
  val=int(input->readLong(2));
905
559
  if (val!=1) f << "unit=" << val << ","; // inch, centimeters, pica
906
2.79k
  for (int i=0; i<4; ++i) {
907
2.23k
    val=int(input->readLong(1));
908
2.23k
    if (val==-1)
909
213
      continue;
910
2.02k
    if (i==0)
911
511
      f << "hide[ruler]";
912
1.51k
    else if (i==1)
913
504
      f << "hide[grid]";
914
1.00k
    else
915
1.00k
      f << "fl" << i;
916
2.02k
    if (val!=0)
917
1.38k
      f << "=" << val << ",";
918
635
    else
919
635
      f << ",";
920
2.02k
  }
921
559
  ascii().addPos(pos);
922
559
  ascii().addNote(f.str().c_str());
923
924
559
  input->seek(endPos, librevenge::RVNG_SEEK_SET);
925
559
  return true;
926
681
}
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
854
{
1393
854
  MWAWInputStreamPtr input = getInput();
1394
854
  int const vers=version();
1395
854
  long pos=input->tell();
1396
854
  long endPos=pos+120+(vers<3 ? 2 : 4);
1397
854
  if (!input->checkPosition(endPos) || input->readULong((vers<3 ? 2 : 4))!=0x78) {
1398
691
    MWAW_DEBUG_MSG(("ReadySetGoParser::readPrintInfo: file seems too short\n"));
1399
691
    return false;
1400
691
  }
1401
163
  libmwaw::DebugStream f;
1402
163
  f << "Entries(PrintInfo):";
1403
163
  libmwaw::PrinterInfo info;
1404
163
  if (!info.read(input)) {
1405
34
    MWAW_DEBUG_MSG(("ReadySetGoParser::readPrintInfo: can not read print info\n"));
1406
34
    return false;
1407
34
  }
1408
129
  f << info;
1409
129
  MWAWVec2i paperSize = info.paper().size();
1410
129
  MWAWVec2i pageSize = info.page().size();
1411
129
  if (pageSize.x() <= 0 || pageSize.y() <= 0 ||
1412
93
      paperSize.x() <= 0 || paperSize.y() <= 0) {
1413
93
    ascii().addPos(pos);
1414
93
    ascii().addNote(f.str().c_str());
1415
93
    input->seek(endPos, librevenge::RVNG_SEEK_SET);
1416
93
    return true;
1417
93
  }
1418
1419
  // define margin from print info
1420
36
  MWAWVec2i lTopMargin= -1 * info.paper().pos(0);
1421
36
  MWAWVec2i rBotMargin=info.paper().size() - info.page().size();
1422
1423
  // move margin left | top
1424
36
  int decalX = lTopMargin.x() > 14 ? lTopMargin.x()-14 : 0;
1425
36
  int decalY = lTopMargin.y() > 14 ? lTopMargin.y()-14 : 0;
1426
36
  lTopMargin -= MWAWVec2i(decalX, decalY);
1427
36
  rBotMargin += MWAWVec2i(decalX, decalY);
1428
1429
  // decrease right | bottom
1430
36
  int rightMarg = rBotMargin.x() -50;
1431
36
  if (rightMarg < 0) rightMarg=0;
1432
36
  int botMarg = rBotMargin.y() -50;
1433
36
  if (botMarg < 0) botMarg=0;
1434
1435
36
  getPageSpan().setMarginTop(lTopMargin.y()/72.0);
1436
36
  getPageSpan().setMarginBottom(botMarg/72.0);
1437
36
  getPageSpan().setMarginLeft(lTopMargin.x()/72.0);
1438
36
  getPageSpan().setMarginRight(rightMarg/72.0);
1439
36
  getPageSpan().setFormLength(paperSize.y()/72.);
1440
36
  getPageSpan().setFormWidth(paperSize.x()/72.);
1441
1442
36
  ascii().addPos(pos);
1443
36
  ascii().addNote(f.str().c_str());
1444
36
  input->seek(endPos, librevenge::RVNG_SEEK_SET);
1445
36
  return true;
1446
129
}
1447
1448
// vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: