Coverage Report

Created: 2026-06-13 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libmwaw/src/lib/WriteNowParser.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 <iomanip>
35
#include <iostream>
36
#include <limits>
37
#include <map>
38
#include <sstream>
39
40
#include <librevenge/librevenge.h>
41
42
#include "MWAWTextListener.hxx"
43
#include "MWAWHeader.hxx"
44
#include "MWAWFont.hxx"
45
#include "MWAWPosition.hxx"
46
#include "MWAWPictMac.hxx"
47
#include "MWAWPrinter.hxx"
48
49
#include "WriteNowEntry.hxx"
50
#include "WriteNowText.hxx"
51
52
#include "WriteNowParser.hxx"
53
54
/** Internal: the structures of a WriteNowParser */
55
namespace WriteNowParserInternal
56
{
57
////////////////////////////////////////
58
//! Internal: the state of a WriteNowParser
59
struct State {
60
  //! constructor
61
  State()
62
196k
    : m_endPos(-1)
63
196k
    , m_colorMap()
64
196k
    , m_picturesList()
65
196k
    , m_actPage(0)
66
196k
    , m_numPages(0)
67
196k
    , m_headerHeight(0)
68
196k
    , m_footerHeight(0)
69
196k
    , m_numColumns(1)
70
196k
    , m_columnWidth(-1)
71
196k
  {
72
196k
  }
73
74
  //! the last position
75
  long m_endPos;
76
  //! the color map
77
  std::vector<MWAWColor> m_colorMap;
78
  //! the list of picture entries
79
  std::vector<WriteNowEntry> m_picturesList;
80
81
  int m_actPage /** the actual page */, m_numPages /** the number of page of the final document */;
82
83
  int m_headerHeight /** the header height if known */,
84
      m_footerHeight /** the footer height if known */;
85
86
  int m_numColumns /** the number of columns */, m_columnWidth /** the columns size */;
87
};
88
89
////////////////////////////////////////
90
//! Internal: the subdocument of a WriteNowParser
91
class SubDocument final : public MWAWSubDocument
92
{
93
public:
94
  SubDocument(WriteNowParser &pars, MWAWInputStreamPtr const &input, WriteNowEntry const &pos)
95
189k
    : MWAWSubDocument(&pars, input, MWAWEntry())
96
189k
    , m_pos(pos)
97
189k
  {
98
189k
  }
99
100
  //! destructor
101
189k
  ~SubDocument() final {}
102
103
  //! operator!=
104
  bool operator!=(MWAWSubDocument const &doc) const final;
105
106
  //! the parser function
107
  void parse(MWAWListenerPtr &listener, libmwaw::SubDocumentType type) final;
108
109
protected:
110
  //! the subdocument file position
111
  WriteNowEntry m_pos;
112
};
113
114
void SubDocument::parse(MWAWListenerPtr &listener, libmwaw::SubDocumentType /*type*/)
115
189k
{
116
189k
  if (!listener.get()) {
117
0
    MWAW_DEBUG_MSG(("WriteNowParserInternal::SubDocument::parse: no listener\n"));
118
0
    return;
119
0
  }
120
189k
  auto *parser=dynamic_cast<WriteNowParser *>(m_parser);
121
189k
  if (!parser) {
122
0
    MWAW_DEBUG_MSG(("WriteNowParserInternal::SubDocument::parse: no parser\n"));
123
0
    return;
124
0
  }
125
126
189k
  long pos = m_input->tell();
127
189k
  parser->send(m_pos);
128
189k
  m_input->seek(pos, librevenge::RVNG_SEEK_SET);
129
189k
}
130
131
bool SubDocument::operator!=(MWAWSubDocument const &doc) const
132
0
{
133
0
  if (MWAWSubDocument::operator!=(doc)) return true;
134
0
  auto const *sDoc = dynamic_cast<SubDocument const *>(&doc);
135
0
  if (!sDoc) return true;
136
0
  if (m_pos != sDoc->m_pos) return true;
137
0
  return false;
138
0
}
139
}
140
141
142
////////////////////////////////////////////////////////////
143
// constructor/destructor, ...
144
////////////////////////////////////////////////////////////
145
WriteNowParser::WriteNowParser(MWAWInputStreamPtr const &input, MWAWRSRCParserPtr const &rsrcParser, MWAWHeader *header)
146
84.5k
  : MWAWTextParser(input, rsrcParser, header)
147
84.5k
  , m_state()
148
84.5k
  , m_entryManager()
149
84.5k
  , m_textParser()
150
84.5k
{
151
84.5k
  init();
152
84.5k
}
153
154
WriteNowParser::~WriteNowParser()
155
84.5k
{
156
84.5k
}
157
158
void WriteNowParser::init()
159
84.5k
{
160
84.5k
  resetTextListener();
161
84.5k
  setAsciiName("main-1");
162
163
84.5k
  m_state.reset(new WriteNowParserInternal::State);
164
84.5k
  m_entryManager.reset(new WriteNowEntryManager);
165
166
  // reduce the margin (in case, the page is not defined)
167
84.5k
  getPageSpan().setMargins(0.1);
168
169
84.5k
  m_textParser.reset(new WriteNowText(*this));
170
84.5k
}
171
172
////////////////////////////////////////////////////////////
173
// position and height
174
////////////////////////////////////////////////////////////
175
void WriteNowParser::getColumnInfo(int &numColumns, int &width) const
176
103k
{
177
103k
  numColumns = m_state->m_numColumns;
178
103k
  width = m_state->m_columnWidth;
179
103k
}
180
181
////////////////////////////////////////////////////////////
182
// new page and color
183
////////////////////////////////////////////////////////////
184
void WriteNowParser::newPage(int number)
185
23.2k
{
186
23.2k
  if (number <= m_state->m_actPage || number > m_state->m_numPages)
187
0
    return;
188
189
48.9k
  while (m_state->m_actPage < number) {
190
25.7k
    m_state->m_actPage++;
191
25.7k
    if (!getTextListener() || m_state->m_actPage == 1)
192
2.43k
      continue;
193
23.2k
    getTextListener()->insertBreak(MWAWTextListener::PageBreak);
194
23.2k
  }
195
23.2k
}
196
197
bool WriteNowParser::getColor(int colId, MWAWColor &col) const
198
1.14M
{
199
1.14M
  if (colId >= 0 && colId < int(m_state->m_colorMap.size())) {
200
702
    col = m_state->m_colorMap[size_t(colId)];
201
702
    return true;
202
702
  }
203
1.14M
  return false;
204
1.14M
}
205
206
void WriteNowParser::sendFootnote(WriteNowEntry const &entry)
207
186k
{
208
186k
  if (!getTextListener()) return;
209
210
186k
  MWAWSubDocumentPtr subdoc(new WriteNowParserInternal::SubDocument(*this, getInput(), entry));
211
186k
  getTextListener()->insertNote(MWAWNote(MWAWNote::FootNote), subdoc);
212
186k
}
213
214
void WriteNowParser::send(WriteNowEntry const &entry)
215
189k
{
216
189k
  m_textParser->send(entry);
217
189k
}
218
219
bool WriteNowParser::sendGraphic(int gId, MWAWBox2i const &bdbox)
220
3.30k
{
221
3.30k
  if (gId < 8 || (gId-8) >= int(m_state->m_picturesList.size())) {
222
955
    MWAW_DEBUG_MSG(("WriteNowParser::sendGraphic: called with bad id=%d\n", gId));
223
955
    return false;
224
955
  }
225
2.35k
  if (!m_state->m_picturesList[size_t(gId)-8].isZone()) {
226
763
    MWAW_DEBUG_MSG(("WriteNowParser::sendGraphic: called with a no zone id=%d\n", gId));
227
763
    return false;
228
763
  }
229
230
1.58k
  sendPicture(m_state->m_picturesList[size_t(gId)-8], bdbox);
231
1.58k
  return true;
232
2.35k
}
233
234
235
////////////////////////////////////////////////////////////
236
// the parser
237
////////////////////////////////////////////////////////////
238
void WriteNowParser::parse(librevenge::RVNGTextInterface *docInterface)
239
27.0k
{
240
27.0k
  if (!getInput().get() || !checkHeader(nullptr))  throw(libmwaw::ParseException());
241
27.0k
  bool ok = true;
242
27.0k
  try {
243
    // create the asciiFile
244
27.0k
    ascii().setStream(getInput());
245
27.0k
    ascii().open(asciiName());
246
247
27.0k
    m_entryManager->reset();
248
27.0k
    checkHeader(nullptr);
249
27.0k
    ascii().addPos(getInput()->tell());
250
27.0k
    ascii().addNote("_");
251
252
27.0k
    ok = createZones();
253
27.0k
    if (ok) {
254
25.7k
      createDocument(docInterface);
255
25.7k
      m_textParser->sendZone(0);
256
257
      // ok, we can now send what is not send.
258
25.7k
      m_textParser->flushExtra();
259
25.7k
      MWAWBox2i emptyBdBox;
260
25.7k
      for (auto &picture : m_state->m_picturesList) {
261
8.06k
        if (picture.isParsed() || !picture.isZone()) continue;
262
5.45k
        sendPicture(picture, emptyBdBox);
263
5.45k
      }
264
25.7k
    }
265
266
27.0k
    ascii().reset();
267
27.0k
  }
268
27.0k
  catch (...) {
269
0
    MWAW_DEBUG_MSG(("WriteNowParser::parse: exception catched when parsing\n"));
270
0
    ok = false;
271
0
  }
272
273
27.0k
  resetTextListener();
274
27.0k
  if (!ok) throw(libmwaw::ParseException());
275
27.0k
}
276
277
////////////////////////////////////////////////////////////
278
// create the document
279
////////////////////////////////////////////////////////////
280
void WriteNowParser::createDocument(librevenge::RVNGTextInterface *documentInterface)
281
25.7k
{
282
25.7k
  if (!documentInterface) return;
283
25.7k
  if (getTextListener()) {
284
0
    MWAW_DEBUG_MSG(("WriteNowParser::createDocument: listener already exist\n"));
285
0
    return;
286
0
  }
287
288
  // update the page
289
25.7k
  m_state->m_actPage = 0;
290
291
  // create the page list
292
25.7k
  MWAWPageSpan ps(getPageSpan());
293
294
25.7k
  WriteNowEntry entry = m_textParser->getHeader();
295
25.7k
  if (entry.valid()) {
296
1.35k
    MWAWHeaderFooter header(MWAWHeaderFooter::HEADER, MWAWHeaderFooter::ALL);
297
1.35k
    header.m_subDocument.reset(new WriteNowParserInternal::SubDocument(*this, getInput(), entry));
298
1.35k
    ps.setHeaderFooter(header);
299
1.35k
  }
300
301
25.7k
  entry = m_textParser->getFooter();
302
25.7k
  if (entry.valid()) {
303
1.60k
    MWAWHeaderFooter footer(MWAWHeaderFooter::FOOTER, MWAWHeaderFooter::ALL);
304
1.60k
    footer.m_subDocument.reset(new WriteNowParserInternal::SubDocument(*this, getInput(), entry));
305
1.60k
    ps.setHeaderFooter(footer);
306
1.60k
  }
307
308
25.7k
  int numPage = m_textParser->numPages();
309
25.7k
  m_state->m_numPages = numPage;
310
25.7k
  ps.setPageSpan(m_state->m_numPages+1);
311
25.7k
  std::vector<MWAWPageSpan> pageList(1,ps);
312
  //
313
25.7k
  MWAWTextListenerPtr listen(new MWAWTextListener(*getParserState(), pageList, documentInterface));
314
25.7k
  setTextListener(listen);
315
25.7k
  listen->startDocument();
316
25.7k
}
317
318
319
////////////////////////////////////////////////////////////
320
//
321
// Intermediate level
322
//
323
////////////////////////////////////////////////////////////
324
325
////////////////////////////////////////////////////////////
326
// try to find the different zone
327
////////////////////////////////////////////////////////////
328
bool WriteNowParser::createZones()
329
27.0k
{
330
27.0k
  if (version() < 3) {
331
24.6k
    if (!readDocEntriesV2())
332
765
      return false;
333
24.6k
  }
334
2.37k
  else if (!readDocEntries())
335
466
    return false;
336
337
  // the Color map zone
338
25.7k
  auto iter = m_entryManager->m_typeMap.find("ColMap");
339
25.7k
  if (iter != m_entryManager->m_typeMap.end())
340
1.54k
    readColorMap(*iter->second);
341
342
  // the graphic zone
343
25.7k
  iter = m_entryManager->m_typeMap.find("GraphZone");
344
25.7k
  if (iter != m_entryManager->m_typeMap.end())
345
1.51k
    parseGraphicZone(*iter->second);
346
347
348
25.7k
  iter = m_entryManager->m_typeMap.find("UnknZone1");
349
25.7k
  if (iter != m_entryManager->m_typeMap.end())
350
1.53k
    readGenericUnkn(*iter->second);
351
352
25.7k
  iter = m_entryManager->m_typeMap.find("PrintZone");
353
25.7k
  if (iter != m_entryManager->m_typeMap.end())
354
8.92k
    readPrintInfo(*iter->second);
355
356
  // checkme: never seens, but probably also a list of zone...
357
25.7k
  iter = m_entryManager->m_typeMap.find("UnknZone2");
358
25.7k
  if (iter != m_entryManager->m_typeMap.end())
359
101
    readGenericUnkn(*iter->second);
360
361
25.7k
  bool ok = m_textParser->createZones();
362
363
  // fixme: we must continue....
364
25.7k
  libmwaw::DebugStream f;
365
736k
  for (auto const &it : m_entryManager->m_typeMap) {
366
736k
    WriteNowEntry const &ent = *it.second;
367
736k
    if (ent.isParsed()) continue;
368
65.1k
    ascii().addPos(ent.begin());
369
65.1k
    f.str("");
370
65.1k
    f << "Entries(" << it.first << ")";
371
65.1k
    if (ent.id() >= 0) f << "[" << ent.id() << "]";
372
65.1k
    ascii().addNote(f.str().c_str());
373
65.1k
    ascii().addPos(ent.end());
374
65.1k
    ascii().addNote("_");
375
65.1k
  }
376
25.7k
  return ok;
377
27.0k
}
378
379
////////////////////////////////////////////////////////////
380
//
381
// Low level
382
//
383
////////////////////////////////////////////////////////////
384
385
////////////////////////////////////////////////////////////
386
// try to read the document main zone
387
////////////////////////////////////////////////////////////
388
bool WriteNowParser::readDocEntries()
389
2.37k
{
390
2.37k
  MWAWInputStreamPtr input = getInput();
391
392
2.37k
  auto it = m_entryManager->m_typeMap.find("DocEntries");
393
2.37k
  if (it == m_entryManager->m_typeMap.end()) {
394
21
    MWAW_DEBUG_MSG(("WriteNowParser::readDocEntries: can not find last zone\n"));
395
21
    return false;
396
21
  }
397
2.34k
  WriteNowEntry const &entry = *(it->second);
398
2.34k
  if (!entry.valid() || entry.length() < 148) {
399
23
    MWAW_DEBUG_MSG(("WriteNowParser::readDocEntries: last entry is invalid\n"));
400
23
    return false;
401
23
  }
402
403
2.32k
  input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
404
2.32k
  bool ok = input->readLong(4) == entry.length();
405
2.32k
  if (!ok || input->readLong(4) != entry.begin()) {
406
422
    MWAW_DEBUG_MSG(("WriteNowParser::readDocEntries: bad begin of last zone\n"));
407
422
    return false;
408
422
  }
409
1.90k
  entry.setParsed(true);
410
1.90k
  libmwaw::DebugStream f;
411
1.90k
  f << "Entries(DocEntries):";
412
413
1.90k
  long val;
414
1.90k
  long const expectedVal[] = { 0, 0x80, 0x40000000L};
415
1.90k
  long freePos = 0;
416
15.2k
  for (int i = 0; i < 7; i++) { // 0, 80, 4000
417
13.3k
    val = long(input->readULong(4));
418
13.3k
    if (i == 3) {
419
1.90k
      freePos = val;
420
1.90k
      continue;
421
1.90k
    }
422
11.4k
    if ((i < 3 && val!= expectedVal[i]) || (i >=3 && val))
423
2.24k
      f << "f" << i << "=" << std::hex << val << std::dec << ",";
424
11.4k
  }
425
1.90k
  if (freePos) { // checkme
426
1.90k
    if (freePos > m_state->m_endPos) {
427
37
      MWAW_DEBUG_MSG(("WriteNowParser::readDocEntries: find odd freePos\n"));
428
37
    }
429
1.86k
    else {
430
1.86k
      f << "freeZone?=" << std::hex << freePos << std::dec << ",";
431
1.86k
      ascii().addPos(freePos);
432
1.86k
      ascii().addNote("Entries(Free)");
433
1.86k
    }
434
1.90k
  }
435
1.90k
  char const *entryName[] = { "TextZone", "TextZone", "TextZone", "UnknZone0",
436
1.90k
                              "GraphZone", "ColMap", "StylZone", "FontZone",
437
1.90k
                              "UnknZone1", "UnknZone2"
438
1.90k
                            };
439
20.9k
  for (int i = 0; i < 10; i++) {
440
19.0k
    WriteNowEntry zone = readEntry();
441
19.0k
    zone.setType(entryName[i]);
442
19.0k
    if (i < 3) zone.setId(i);
443
19.0k
    if (zone.isZone())
444
13.5k
      m_entryManager->add(zone);
445
19.0k
    f << zone;
446
19.0k
  }
447
1.90k
  ascii().addDelimiter(input->tell(), '|');
448
1.90k
  ascii().addPos(entry.begin());
449
1.90k
  ascii().addNote(f.str().c_str());
450
1.90k
  if (entry.length() > 386) {
451
1.90k
    long pos = entry.begin()+376;
452
1.90k
    input->seek(pos, librevenge::RVNG_SEEK_SET);
453
1.90k
    f.str("");
454
1.90k
    f << "DocEntries-II:";
455
1.90k
    m_state->m_numColumns = static_cast<int>(input->readLong(1));
456
1.90k
    f << "nCol=" << m_state->m_numColumns << ",";
457
1.90k
    val = input->readLong(1);
458
1.90k
    if (val != 1) f << "unkn=" << val << ",";
459
1.90k
    m_state->m_columnWidth = static_cast<int>(input->readLong(2));
460
1.90k
    f << "colWidth=" << m_state->m_columnWidth << ",";
461
462
1.90k
    ascii().addPos(pos);
463
1.90k
    ascii().addNote(f.str().c_str());
464
465
1.90k
    if (long(input->tell()) != entry.end())
466
1.90k
      ascii().addDelimiter(input->tell(), '|');
467
1.90k
  }
468
1.90k
  ascii().addPos(entry.end());
469
1.90k
  ascii().addNote("_");
470
471
1.90k
  return true;
472
2.32k
}
473
474
////////////////////////////////////////////////////////////
475
// try to read the document main zone : v2
476
////////////////////////////////////////////////////////////
477
bool WriteNowParser::readDocEntriesV2()
478
24.6k
{
479
24.6k
  MWAWInputStreamPtr input = getInput();
480
24.6k
  long pos = input->tell(), debPos=pos;
481
24.6k
  libmwaw::DebugStream f;
482
24.6k
  std::stringstream s;
483
24.6k
  f << "Entries(DocEntries):";
484
145k
  for (int i = 0; i < 5; i++) {
485
121k
    auto val=static_cast<int>(input->readLong(1));
486
121k
    if (val != 4 && val != 0x44) {
487
765
      MWAW_DEBUG_MSG(("WriteNowParser::readDocEntriesV2: can not find entries header:%d\n",i));
488
765
      return false;
489
765
    }
490
120k
    auto dataPos = long(input->readULong(1));
491
120k
    dataPos = (dataPos<<16)+long(input->readULong(2));
492
120k
    if (!checkIfPositionValid(dataPos)) {
493
46.5k
      MWAW_DEBUG_MSG(("WriteNowParser::readDocEntriesV2:  find an invalid position for entry:%d\n",i));
494
46.5k
      continue;
495
46.5k
    }
496
74.3k
    WriteNowEntry entry;
497
74.3k
    entry.setBegin(dataPos);
498
74.3k
    switch (i) {
499
22.9k
    case 0:
500
34.8k
    case 1:
501
52.3k
    case 2:
502
52.3k
      entry.setType("TextZone");
503
52.3k
      entry.setId(i);
504
52.3k
      break;
505
10.8k
    case 4:
506
10.8k
      entry.setType("PrintZone");
507
10.8k
      break;
508
11.1k
    default: { // find 2 time 0006000800000000
509
11.1k
      std::stringstream name;
510
11.1k
      s << "Unknown" << i;
511
11.1k
      entry.setType(name.str());
512
11.1k
    }
513
74.3k
    }
514
74.3k
    long actPos = input->tell();
515
74.3k
    input->seek(dataPos, librevenge::RVNG_SEEK_SET);
516
74.3k
    entry.setLength(long(input->readULong(2)+2));
517
74.3k
    input->seek(actPos, librevenge::RVNG_SEEK_SET);
518
74.3k
    m_entryManager->add(entry);
519
74.3k
  }
520
23.8k
  f << "ptr=[";
521
143k
  for (int i = 0; i < 5; i++)
522
119k
    f << std::hex << input->readULong(4) << std::dec << ",";
523
23.8k
  f << "],";
524
23.8k
  ascii().addPos(pos);
525
23.8k
  ascii().addNote(f.str().c_str());
526
23.8k
  input->seek(debPos+0x6E,librevenge::RVNG_SEEK_SET);
527
23.8k
  pos=input->tell();
528
23.8k
  f.str("");
529
23.8k
  f << "DocEntries-II:";
530
531
23.8k
  if (version()==2) {
532
23.8k
    m_state->m_numColumns = static_cast<int>(input->readLong(1));
533
23.8k
    f << "nCol=" << m_state->m_numColumns << ",";
534
23.8k
    long val = input->readLong(1);
535
23.8k
    if (val != 1) f << "unkn=" << val << ",";
536
23.8k
    m_state->m_columnWidth = static_cast<int>(input->readLong(2));
537
23.8k
    f << "colWidth=" << m_state->m_columnWidth << ",";
538
23.8k
    ascii().addDelimiter(input->tell(),'|');
539
23.8k
  }
540
23.8k
  ascii().addPos(pos);
541
23.8k
  ascii().addNote(f.str().c_str());
542
  // another copy (visibly the previous version)
543
23.8k
  ascii().addPos(debPos+0xFc);
544
23.8k
  ascii().addNote("DocEntries[Old]:");
545
23.8k
  ascii().addPos(debPos+0x16a);
546
23.8k
  ascii().addNote("DocEntries-II[Old]:");
547
23.8k
  ascii().addPos(debPos+0x1F8);
548
23.8k
  ascii().addNote("_");
549
23.8k
  return true;
550
24.6k
}
551
////////////////////////////////////////////////////////////
552
// try to read a graphic list zone
553
////////////////////////////////////////////////////////////
554
bool WriteNowParser::parseGraphicZone(WriteNowEntry const &entry)
555
1.51k
{
556
1.51k
  MWAWInputStreamPtr input = getInput();
557
558
1.51k
  if (!entry.valid() || entry.length() < 24) {
559
13
    MWAW_DEBUG_MSG(("WriteNowParser::parseGraphicZone: zone size is invalid\n"));
560
13
    return false;
561
13
  }
562
563
1.49k
  input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
564
1.49k
  if (input->readLong(4) != entry.length()) {
565
322
    MWAW_DEBUG_MSG(("WriteNowParser::parseGraphicZone: bad begin of last zone\n"));
566
322
    return false;
567
322
  }
568
1.17k
  libmwaw::DebugStream f;
569
1.17k
  f << "Entries(GraphicZone):";
570
1.17k
  f << "ptr?=" << std::hex << input->readULong(4) << std::dec << ",";
571
1.17k
  f << "ptr2?=" << std::hex << input->readULong(4) << std::dec << ",";
572
1.17k
  long val;
573
4.70k
  for (int i = 0; i < 3; i++) { // always 3, 80, 0 ?
574
3.52k
    val = input->readLong(2);
575
3.52k
    if (val)  f << "f" << i << "=" << val << ",";
576
3.52k
  }
577
1.17k
  auto N = static_cast<int>(input->readLong(2));
578
1.17k
  f << "N?=" << N << ",";
579
3.52k
  for (int i = 4; i < 6; i++) { // alway 0 ?
580
2.35k
    val = input->readLong(2);
581
2.35k
    if (val) f << "f" << i << "=" << val << ",";
582
2.35k
  }
583
1.17k
  ascii().addPos(entry.begin());
584
1.17k
  ascii().addNote(f.str().c_str());
585
586
1.17k
  if (entry.length() != 24+12*N) {
587
24
    MWAW_DEBUG_MSG(("WriteNowParser::parseGraphicZone: zone size is invalid(II)\n"));
588
24
    return false;
589
24
  }
590
18.4k
  for (int i = 0; i < N; i++) {
591
17.2k
    long pos = input->tell();
592
17.2k
    WriteNowEntry zone = readEntry();
593
17.2k
    f.str("");
594
17.2k
    if (i < 8)
595
9.21k
      f << "GraphicZoneA-" << i << ":";
596
8.06k
    else
597
8.06k
      f << "GraphicZone-" << i-8 << ":";
598
599
17.2k
    zone.setId((i < 8) ? i : i-8);
600
17.2k
    if (zone.isZone()) {
601
8.44k
      if (i == 0)
602
1.04k
        zone.setType("PrintZone");
603
7.39k
      else if (i < 8) {
604
1.12k
        std::stringstream s;
605
1.12k
        s << "GraphicUnkn" << i;
606
1.12k
        zone.setType(s.str());
607
1.12k
      }
608
6.27k
      else
609
6.27k
        zone.setType("GraphicData");
610
8.44k
      if (i < 8)
611
2.16k
        m_entryManager->add(zone);
612
8.44k
    }
613
8.83k
    else if (zone.m_val[2]==-1 && zone.m_val[3]==0x76543210L) {
614
0
      zone.m_val[2]= zone.m_val[3]=0;
615
0
      f << "*";
616
0
    }
617
17.2k
    if (i >= 8)
618
8.06k
      m_state->m_picturesList.push_back(zone);
619
17.2k
    f << zone;
620
621
17.2k
    ascii().addPos(pos);
622
17.2k
    ascii().addNote(f.str().c_str());
623
17.2k
  }
624
625
1.15k
  entry.setParsed(true);
626
1.15k
  ascii().addPos(entry.end());
627
1.15k
  ascii().addNote("_");
628
1.15k
  return true;
629
1.17k
}
630
631
////////////////////////////////////////////////////////////
632
// try to read a graphic zone
633
////////////////////////////////////////////////////////////
634
bool WriteNowParser::sendPicture(WriteNowEntry const &entry, MWAWBox2i const &bdbox)
635
7.04k
{
636
7.04k
  MWAWInputStreamPtr input = getInput();
637
638
7.04k
  if (!entry.valid() || entry.length() < 24) {
639
46
    MWAW_DEBUG_MSG(("WriteNowParser::sendPicture: zone size is invalid\n"));
640
46
    return false;
641
46
  }
642
643
6.99k
  input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
644
6.99k
  if (input->readLong(4) != entry.length()) {
645
4.95k
    MWAW_DEBUG_MSG(("WriteNowParser::sendPicture: bad begin of last zone\n"));
646
4.95k
    return false;
647
4.95k
  }
648
2.03k
  libmwaw::DebugStream f;
649
2.03k
  f << "Entries(GraphicData):";
650
2.03k
  f << "ptr?=" << std::hex << input->readULong(4) << std::dec << ",";
651
2.03k
  f << "ptr2?=" << std::hex << input->readULong(4) << std::dec << ",";
652
2.03k
  auto type = static_cast<int>(input->readLong(2));
653
2.03k
  if (type != 14) f << "#type=" << type << ",";
654
2.03k
  long val;
655
  /* fl0 : 0[pict1] or 1[pict2] : graphic type ?, fl1 : always 0
656
   */
657
6.10k
  for (int i = 0; i < 2; i++) {
658
4.07k
    val = input->readLong(1);
659
4.07k
    if (val) f << "fl" << i << "=" << val << ",";
660
4.07k
  }
661
662
2.03k
  f << "ptr3?=" << std::hex << input->readULong(4) << std::dec << ",";
663
6.10k
  for (int i = 0; i < 2; i++) { // alway 0 ?
664
4.07k
    val = input->readLong(2);
665
4.07k
    if (val) f << "f" << i << "=" << val << ",";
666
4.07k
  }
667
668
2.03k
  ascii().addPos(entry.begin());
669
2.03k
  ascii().addNote(f.str().c_str());
670
671
2.03k
  int sz = static_cast<int>(entry.length())-24;
672
2.03k
  if (sz) {
673
2.03k
    long pos = input->tell();
674
2.03k
    std::shared_ptr<MWAWPict> pict(MWAWPictData::get(input, sz));
675
2.03k
    if (!pict) {
676
4
      MWAW_DEBUG_MSG(("WriteNowParser::sendPicture: can not read the picture\n"));
677
4
      ascii().addDelimiter(pos, '|');
678
4
    }
679
2.03k
    else {
680
2.03k
      if (getTextListener()) {
681
2.03k
        MWAWPosition pictPos;
682
2.03k
        if (bdbox.size().x() > 0 && bdbox.size().y() > 0) {
683
824
          pictPos=MWAWPosition(MWAWVec2f(0,0),MWAWVec2f(bdbox.size()), librevenge::RVNG_POINT);
684
824
          pictPos.setNaturalSize(pict->getBdBox().size());
685
824
        }
686
1.20k
        else
687
1.20k
          pictPos=MWAWPosition(MWAWVec2f(0,0),pict->getBdBox().size(), librevenge::RVNG_POINT);
688
2.03k
        pictPos.setRelativePosition(MWAWPosition::Char);
689
690
2.03k
        MWAWEmbeddedObject picture;
691
2.03k
        if (pict->getBinary(picture))
692
2.03k
          getTextListener()->insertPicture(pictPos, picture);
693
2.03k
      }
694
695
#ifdef DEBUG_WITH_FILES
696
      if (!entry.isParsed()) {
697
        ascii().skipZone(pos, entry.end()-1);
698
        librevenge::RVNGBinaryData file;
699
        input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
700
        input->readDataBlock(entry.length(), file);
701
        static int volatile pictName = 0;
702
        libmwaw::DebugStream f2;
703
        f2 << "PICT-" << ++pictName << ".pct";
704
        libmwaw::Debug::dumpFile(file, f2.str().c_str());
705
      }
706
#endif
707
2.03k
    }
708
2.03k
  }
709
710
2.03k
  entry.setParsed(true);
711
2.03k
  ascii().addPos(entry.end());
712
2.03k
  ascii().addNote("_");
713
714
2.03k
  return true;
715
6.99k
}
716
717
718
////////////////////////////////////////////////////////////
719
// try to read the color map zone
720
////////////////////////////////////////////////////////////
721
bool WriteNowParser::readColorMap(WriteNowEntry const &entry)
722
1.54k
{
723
1.54k
  m_state->m_colorMap.resize(0);
724
725
1.54k
  MWAWInputStreamPtr input = getInput();
726
727
1.54k
  if (!entry.valid() || entry.length() < 0x10) {
728
8
    MWAW_DEBUG_MSG(("WriteNowParser::readColorMap: zone size is invalid\n"));
729
8
    return false;
730
8
  }
731
732
1.54k
  input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
733
1.54k
  if (input->readLong(4) != entry.length()) {
734
258
    MWAW_DEBUG_MSG(("WriteNowParser::readColorMap: bad begin of last zone\n"));
735
258
    return false;
736
258
  }
737
1.28k
  libmwaw::DebugStream f;
738
1.28k
  f << "Entries(ColorMap):";
739
1.28k
  f << "ptr?=" << std::hex << input->readULong(4) << std::dec << ",";
740
1.28k
  f << "ptr2?=" << std::hex << input->readULong(4) << std::dec << ",";
741
1.28k
  long pos, val;
742
5.12k
  for (int i = 0; i < 3; i++) { // always 4, 0, 0 ?
743
3.84k
    val = input->readLong(2);
744
3.84k
    if (val) f << "f" << i << "=" << val << ",";
745
3.84k
  }
746
1.28k
  auto N=static_cast<int>(input->readULong(2));
747
1.28k
  f << "N=" << N << ",";
748
3.84k
  for (int i = 0; i < 2; i++) { // 0
749
2.56k
    val = static_cast<int>(input->readLong(2));
750
2.56k
    if (val) f << "g" << i << "=" << val << ",";
751
2.56k
  }
752
1.28k
  if (long(input->tell())+N*8 > entry.end()) {
753
173
    MWAW_DEBUG_MSG(("WriteNowParser::readColorMap: the zone is too short\n"));
754
173
    return false;
755
173
  }
756
1.10k
  ascii().addPos(entry.begin());
757
1.10k
  ascii().addNote(f.str().c_str());
758
1.10k
  std::vector<long> defPos;
759
11.5k
  for (int n = 0; n < N; n++) {
760
10.4k
    pos = input->tell();
761
10.4k
    f.str("");
762
10.4k
    f << "ColorMap[" << n << "]:";
763
10.4k
    auto type = static_cast<int>(input->readLong(1));
764
10.4k
    switch (type) {
765
1.65k
    case 1:
766
1.65k
      f << "named(RGB),";
767
1.65k
      break;
768
100
    case 2:
769
100
      f << "unamed,";
770
100
      break; // check me : are the color in RGB ?
771
7.91k
    case 3:
772
7.91k
      f << "unamed(RGB),";
773
7.91k
      break;
774
808
    default:
775
808
      MWAW_DEBUG_MSG(("WriteNowParser::readColorMap: find unknown type %d\n", type));
776
808
      f << "#type=" << type << ",";
777
808
      break;
778
10.4k
    }
779
41.9k
    for (int i = 0; i < 3; i++) { // always 0
780
31.4k
      val = input->readLong(1);
781
31.4k
      if (val) f << "f" << i << "=" << std::hex << val << std::dec << ",";
782
31.4k
    }
783
10.4k
    val = long(input->readULong(4));
784
10.4k
    defPos.push_back(pos+val);
785
    // fixme: used this to read the data...
786
10.4k
    f << "defPos=" << std::hex << pos+val << std::dec << ",";
787
10.4k
    ascii().addPos(pos);
788
10.4k
    ascii().addNote(f.str().c_str());
789
10.4k
  }
790
791
9.11k
  for (int n = 0; n < N; n++) {
792
8.51k
    pos = defPos[size_t(n)];
793
8.51k
    if (pos+12 > entry.end()) {
794
452
      MWAW_DEBUG_MSG(("WriteNowParser::readColorMap: can not read entry : %d\n", n));
795
452
      return false;
796
452
    }
797
798
8.06k
    input->seek(pos, librevenge::RVNG_SEEK_SET);
799
8.06k
    f.str("");
800
8.06k
    f << "ColorMapData[" << n << "]:";
801
8.06k
    unsigned char col[4];
802
32.2k
    for (auto &c : col) c = static_cast<unsigned char>(input->readULong(2)/256);
803
8.06k
    f << "col=" << MWAWColor(col[0],col[1],col[2],col[3]) << ",";
804
8.06k
    m_state->m_colorMap.push_back(MWAWColor(static_cast<unsigned char>(col[0]),static_cast<unsigned char>(col[1]),static_cast<unsigned char>(col[2])));
805
806
8.06k
    auto sz = static_cast<int>(input->readULong(1));
807
8.06k
    if (pos+8+1+sz > entry.end()) {
808
58
      MWAW_DEBUG_MSG(("WriteNowParser::readColorMap: can not read end of entry : %d\n", n));
809
58
      return false;
810
58
    }
811
8.00k
    std::string name("");
812
24.9k
    for (int i = 0; i < sz; i++) name += char(input->readULong(1));
813
814
8.00k
    if (name.length()) f << name;
815
8.00k
    ascii().addPos(pos);
816
8.00k
    ascii().addNote(f.str().c_str());
817
8.00k
  }
818
819
599
  entry.setParsed(true);
820
599
  ascii().addPos(entry.end());
821
599
  ascii().addNote("_");
822
599
  return true;
823
1.10k
}
824
825
////////////////////////////////////////////////////////////
826
// try to read the print info zone
827
////////////////////////////////////////////////////////////
828
bool WriteNowParser::readPrintInfo(WriteNowEntry const &entry)
829
8.92k
{
830
8.92k
  MWAWInputStreamPtr input = getInput();
831
8.92k
  int expectedLength = version() <= 2 ? 0x78+2 : 0x88;
832
8.92k
  if (!entry.valid() || entry.length() < expectedLength) {
833
2.60k
    MWAW_DEBUG_MSG(("WriteNowParser::readPrintInfo: zone size is invalid\n"));
834
2.60k
    return false;
835
2.60k
  }
836
837
6.32k
  input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
838
6.32k
  long sz = version() <= 2 ? 2+long(input->readULong(2)) : long(input->readULong(4));
839
6.32k
  if (sz != entry.length()) {
840
88
    MWAW_DEBUG_MSG(("WriteNowParser::readPrintInfo: bad begin of last zone\n"));
841
88
    return false;
842
88
  }
843
6.23k
  libmwaw::DebugStream f;
844
6.23k
  f << "Entries(PrintInfo):";
845
6.23k
  if (version()>=3) {
846
955
    f << "ptr?=" << std::hex << input->readULong(4) << std::dec << ",";
847
955
    f << "ptr2?=" << std::hex << input->readULong(4) << std::dec << ",";
848
955
    long val;
849
4.77k
    for (int i = 0; i < 4; i++) { // 15, 0, ??, ???
850
3.82k
      val = input->readLong(2);
851
3.82k
      if (val) f << "f" << i << "=" << std::hex << val << std::dec << ",";
852
3.82k
    }
853
2.86k
    for (int i = 0; i < 2; i++) { // 0
854
1.91k
      val = input->readLong(2);
855
1.91k
      if (val) f << "g" << i << "=" << val << ",";
856
1.91k
    }
857
955
  }
858
6.23k
  libmwaw::PrinterInfo info;
859
6.23k
  if (!info.read(input)) {
860
4.20k
    MWAW_DEBUG_MSG(("WriteNowParser::readPrintInfo: can not read print info\n"));
861
4.20k
    return false;
862
4.20k
  }
863
2.03k
  f << info;
864
865
2.03k
  MWAWVec2i paperSize = info.paper().size();
866
2.03k
  MWAWVec2i pageSize = info.page().size();
867
2.03k
  if (pageSize.x() <= 0 || pageSize.y() <= 0 ||
868
1.36k
      paperSize.x() <= 0 || paperSize.y() <= 0) return false;
869
870
  // define margin from print info
871
1.18k
  MWAWVec2i lTopMargin= -1 * info.paper().pos(0);
872
1.18k
  MWAWVec2i rBotMargin=info.paper().size() - info.page().size();
873
874
  // move margin left | top
875
1.18k
  int decalX = lTopMargin.x() > 14 ? lTopMargin.x()-14 : 0;
876
1.18k
  int decalY = lTopMargin.y() > 14 ? lTopMargin.y()-14 : 0;
877
1.18k
  lTopMargin -= MWAWVec2i(decalX, decalY);
878
1.18k
  rBotMargin += MWAWVec2i(decalX, decalY);
879
880
  // decrease right | bottom
881
1.18k
  int rightMarg = rBotMargin.x() -50;
882
1.18k
  if (rightMarg < 0) rightMarg=0;
883
1.18k
  int botMarg = rBotMargin.y() -50;
884
1.18k
  if (botMarg < 0) botMarg=0;
885
886
1.18k
  getPageSpan().setMarginTop(lTopMargin.y()/72.0);
887
1.18k
  getPageSpan().setMarginBottom(botMarg/72.0);
888
1.18k
  getPageSpan().setMarginLeft(lTopMargin.x()/72.0);
889
1.18k
  getPageSpan().setMarginRight(rightMarg/72.0);
890
1.18k
  getPageSpan().setFormLength(paperSize.y()/72.);
891
1.18k
  getPageSpan().setFormWidth(paperSize.x()/72.);
892
893
1.18k
  entry.setParsed(true);
894
1.18k
  ascii().addPos(entry.begin());
895
1.18k
  ascii().addNote(f.str().c_str());
896
1.18k
  ascii().addPos(entry.end());
897
1.18k
  ascii().addNote("_");
898
1.18k
  return true;
899
2.03k
}
900
901
////////////////////////////////////////////////////////////
902
// try to read the last generic zone ( always find N=0 :-~)
903
////////////////////////////////////////////////////////////
904
bool WriteNowParser::readGenericUnkn(WriteNowEntry const &entry)
905
1.63k
{
906
1.63k
  MWAWInputStreamPtr input = getInput();
907
908
1.63k
  if (!entry.valid() || entry.length() < 0x10) {
909
4
    MWAW_DEBUG_MSG(("WriteNowParser::readGenericUnkn: zone size is invalid\n"));
910
4
    return false;
911
4
  }
912
913
1.62k
  input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
914
1.62k
  if (input->readLong(4) != entry.length()) {
915
380
    MWAW_DEBUG_MSG(("WriteNowParser::readGenericUnkn: bad begin of last zone\n"));
916
380
    return false;
917
380
  }
918
1.24k
  libmwaw::DebugStream f;
919
1.24k
  f << "Entries(" << entry.type() << "):";
920
1.24k
  f << "ptr?=" << std::hex << input->readULong(4) << std::dec << ",";
921
1.24k
  f << "ptr2?=" << std::hex << input->readULong(4) << std::dec << ",";
922
1.24k
  long pos, val;
923
4.99k
  for (int i = 0; i < 3; i++) { // 7, 0, 0
924
3.74k
    val = input->readLong(2);
925
3.74k
    if (val) f << "f" << i << "=" << std::hex << val << std::dec << ",";
926
3.74k
  }
927
1.24k
  auto N=static_cast<int>(input->readULong(2));
928
1.24k
  f << "N=" << N << ",";
929
3.74k
  for (int i = 0; i < 2; i++) { // 0
930
2.49k
    val = input->readLong(2);
931
2.49k
    if (val) f << "g" << i << "=" << val << ",";
932
2.49k
  }
933
1.24k
  if (long(input->tell())+N*8 > entry.end()) {
934
157
    MWAW_DEBUG_MSG(("WriteNowParser::readGenericUnkn: the zone is too short\n"));
935
157
    return false;
936
157
  }
937
1.09k
  ascii().addPos(entry.begin());
938
1.09k
  ascii().addNote(f.str().c_str());
939
1.09k
  std::vector<long> defPos;
940
1.26k
  for (int n = 0; n < N; n++) {
941
174
    pos = input->tell();
942
174
    f.str("");
943
174
    f << entry.type() << "[" << n << "]:";
944
174
    auto type = static_cast<int>(input->readULong(1));
945
174
    switch (type) {
946
86
    case 0:
947
86
      f << "def,";
948
86
      break;
949
88
    default:
950
88
      MWAW_DEBUG_MSG(("WriteNowParser::readGenericUnkn: find unknown type %d\n", type));
951
88
      f << "#type=" << type << ",";
952
88
      break;
953
174
    }
954
696
    for (int i = 0; i < 3; i++) { // always 0
955
522
      val = input->readLong(1);
956
522
      if (val) f << "f" << i << "=" << std::hex << val << std::dec << ",";
957
522
    }
958
174
    val = long(input->readULong(4));
959
174
    defPos.push_back(pos+val);
960
    // fixme: used this to read the data...
961
174
    f << "defPos=" << std::hex << pos+val << std::dec << ",";
962
174
    ascii().addPos(pos);
963
174
    ascii().addNote(f.str().c_str());
964
174
  }
965
966
1.24k
  for (int n = 0; n < N; n++) {
967
159
    pos = defPos[size_t(n)];
968
159
    if (pos == entry.end()) continue;
969
159
    if (pos+12 > entry.end()) {
970
8
      MWAW_DEBUG_MSG(("WriteNowParser::readGenericUnkn: can not read entry : %d\n", n));
971
8
      return false;
972
8
    }
973
974
151
    input->seek(pos, librevenge::RVNG_SEEK_SET);
975
151
    f.str("");
976
151
    f << entry.type() << "Data[" << n << "]:";
977
978
151
    ascii().addPos(pos);
979
151
    ascii().addNote(f.str().c_str());
980
151
  }
981
982
1.08k
  entry.setParsed(true);
983
1.08k
  ascii().addPos(entry.end());
984
1.08k
  ascii().addNote("_");
985
1.08k
  return true;
986
1.09k
}
987
988
bool WriteNowParser::checkIfPositionValid(long pos)
989
8.22M
{
990
8.22M
  if (pos <= m_state->m_endPos)
991
3.24M
    return true;
992
4.97M
  MWAWInputStreamPtr input = getInput();
993
4.97M
  long actPos = input->tell();
994
4.97M
  input->seek(pos, librevenge::RVNG_SEEK_SET);
995
4.97M
  bool ok = long(input->tell())==pos;
996
4.97M
  if (ok) m_state->m_endPos = pos;
997
998
4.97M
  input->seek(actPos, librevenge::RVNG_SEEK_SET);
999
4.97M
  return ok;
1000
8.22M
}
1001
1002
WriteNowEntry WriteNowParser::readEntry()
1003
36.3k
{
1004
36.3k
  WriteNowEntry res;
1005
36.3k
  MWAWInputStreamPtr input = getInput();
1006
36.3k
  auto val = static_cast<int>(input->readULong(2));
1007
36.3k
  res.m_fileType = (val >> 12);
1008
36.3k
  res.m_val[0]= val & 0x0FFF;
1009
36.3k
  res.m_val[1]= static_cast<int>(input->readLong(2));
1010
36.3k
  if (res.isZoneType()) {
1011
23.6k
    res.setBegin(long(input->readULong(4)));
1012
23.6k
    res.setLength(long(input->readULong(4)));
1013
23.6k
    if (!checkIfPositionValid(res.end())) {
1014
1.59k
      MWAW_DEBUG_MSG(("WriteNowParser::readEntry: find an invalid entry\n"));
1015
1.59k
      res.setLength(0);
1016
1.59k
    }
1017
23.6k
  }
1018
12.6k
  else {
1019
12.6k
    res.m_val[2]= static_cast<int>(input->readLong(4));
1020
12.6k
    res.m_val[3]= static_cast<int>(input->readLong(4));
1021
12.6k
  }
1022
36.3k
  return res;
1023
36.3k
}
1024
1025
////////////////////////////////////////////////////////////
1026
// read the header
1027
////////////////////////////////////////////////////////////
1028
bool WriteNowParser::checkHeader(MWAWHeader *header, bool strict)
1029
111k
{
1030
111k
  *m_state = WriteNowParserInternal::State();
1031
1032
111k
  MWAWInputStreamPtr input = getInput();
1033
111k
  if (!input || !input->hasDataFork())
1034
0
    return false;
1035
1036
111k
  libmwaw::DebugStream f;
1037
111k
  int headerSize=28;
1038
111k
  input->seek(headerSize,librevenge::RVNG_SEEK_SET);
1039
111k
  if (int(input->tell()) != headerSize) {
1040
481
    MWAW_DEBUG_MSG(("WriteNowParser::checkHeader: file is too short\n"));
1041
481
    return false;
1042
481
  }
1043
111k
  input->seek(0, librevenge::RVNG_SEEK_SET);
1044
111k
  auto val = long(input->readULong(4));
1045
111k
  int vers = 0;
1046
111k
  switch (val) {
1047
102k
  case 0:
1048
102k
    if (input->readULong(4) != 0)
1049
0
      return false;
1050
102k
    vers = 2;
1051
102k
    break;
1052
8.57k
  case 0x57726974: // Writ
1053
8.57k
    if (input->readULong(4) != 0x654e6f77) // eNow
1054
0
      return false;
1055
8.57k
    vers = 3;
1056
8.57k
    break;
1057
0
  default:
1058
0
    return false;
1059
111k
  }
1060
111k
  setVersion(vers);
1061
111k
  f << "FileHeader:";
1062
1063
111k
  if (vers < 3) {
1064
102k
    if (strict) {
1065
187k
      for (int i=0; i < 4; ++i) {
1066
160k
        val = long(input->readLong(1));
1067
160k
        if (val!=4 && val!=0x44) return false;
1068
135k
        input->seek(3, librevenge::RVNG_SEEK_CUR);
1069
135k
      }
1070
27.3k
      input->seek(8, librevenge::RVNG_SEEK_SET);
1071
27.3k
    }
1072
1073
77.4k
    ascii().addPos(0);
1074
77.4k
    ascii().addNote(f.str().c_str());
1075
77.4k
    ascii().addPos(input->tell());
1076
1077
77.4k
    return true;
1078
102k
  }
1079
1080
8.57k
  val = long(input->readULong(2));
1081
8.57k
  if (strict && val > 3)
1082
0
    return false;
1083
8.57k
#ifndef DEBUG
1084
8.57k
  if (val != 2) return false;
1085
8.57k
#endif
1086
8.57k
  f << "f0=" << val << ",";
1087
1088
34.3k
  for (int i = 1; i < 4; i++) {
1089
    // all zero, excepted f1=1 in one file...
1090
25.7k
    val = input->readLong(2);
1091
25.7k
    if (val) f << "f" << i << "=" << val << ",";
1092
25.7k
  }
1093
1094
  // a flag ??
1095
8.57k
  val = long(input->readULong(2));
1096
8.57k
  if (val != 0x4000) f << "fl=" << std::hex << val << std::dec << ",";
1097
8.57k
  val = long(input->readLong(2));
1098
8.57k
  if (val) f << "f4=" << val << ",";
1099
1100
  // last entry
1101
8.57k
  WriteNowEntry entry;
1102
8.57k
  entry.setBegin(long(input->readULong(4)));
1103
8.57k
  entry.setLength(long(input->readULong(4)));
1104
8.57k
  entry.m_fileType = 4;
1105
1106
8.57k
  if (!checkIfPositionValid(entry.end())) {
1107
1.24k
    MWAW_DEBUG_MSG(("WriteNowParser::checkHeader: can not find final zone\n"));
1108
1.24k
    return false;
1109
1.24k
  }
1110
7.33k
  entry.setType("DocEntries");
1111
7.33k
  m_entryManager->add(entry);
1112
1113
7.33k
  f << "entry=" << std::hex << entry.begin() << ":" << entry.end() << std::dec << ",";
1114
1115
  // ok, we can finish initialization
1116
7.33k
  if (header)
1117
2.59k
    header->reset(MWAWDocument::MWAW_T_WRITENOW, version());
1118
1119
  //
1120
7.33k
  input->seek(headerSize, librevenge::RVNG_SEEK_SET);
1121
1122
7.33k
  ascii().addPos(0);
1123
7.33k
  ascii().addNote(f.str().c_str());
1124
7.33k
  ascii().addPos(headerSize);
1125
1126
7.33k
  return true;
1127
8.57k
}
1128
1129
// vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: