Coverage Report

Created: 2026-03-12 06:42

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libmwaw/src/lib/MarinerWrtParser.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 <string.h>
35
36
#include <iomanip>
37
#include <iostream>
38
#include <limits>
39
#include <map>
40
#include <set>
41
#include <sstream>
42
#include <string>
43
44
#include <librevenge/librevenge.h>
45
46
#include "MWAWCell.hxx"
47
#include "MWAWTextListener.hxx"
48
#include "MWAWFont.hxx"
49
#include "MWAWFontConverter.hxx"
50
#include "MWAWHeader.hxx"
51
#include "MWAWList.hxx"
52
#include "MWAWParagraph.hxx"
53
#include "MWAWPosition.hxx"
54
#include "MWAWPictMac.hxx"
55
#include "MWAWPrinter.hxx"
56
#include "MWAWSection.hxx"
57
#include "MWAWSubDocument.hxx"
58
59
#include "MarinerWrtGraph.hxx"
60
#include "MarinerWrtText.hxx"
61
62
#include "MarinerWrtParser.hxx"
63
64
/** Internal: the structures of a MarinerWrtParser */
65
namespace MarinerWrtParserInternal
66
{
67
////////////////////////////////////////
68
//! Internal: the struct used to store the zone of a MarinerWrtParser
69
struct Zone {
70
  //! a enum to define the diffent zone type
71
  enum Type { Z_Main, Z_Footnote, Z_Header, Z_Footer, Z_Unknown };
72
  //! constructor
73
  Zone()
74
115k
    : m_id(-1)
75
115k
    , m_fileId(0)
76
115k
    , m_type(Z_Unknown)
77
115k
    , m_endNote(false)
78
115k
    , m_height(0)
79
115k
    , m_RBpos(0,0)
80
115k
    , m_dim()
81
115k
    , m_pageDim()
82
115k
    , m_pageTextDim()
83
115k
    , m_section()
84
115k
    , m_backgroundColor(MWAWColor::white())
85
115k
    , m_extra("")
86
115k
  {
87
115k
  }
88
  //! operator<<
89
  friend std::ostream &operator<<(std::ostream &o, Zone const &zone);
90
  //! the zone id
91
  int m_id;
92
  //! the file zone id
93
  uint32_t m_fileId;
94
  //! the zone type
95
  Type m_type;
96
  //! a flag to know if this an endnote
97
  bool m_endNote;
98
  //! height of the zone
99
  long m_height;
100
  //! right/bottom position
101
  MWAWVec2l m_RBpos;
102
  //! the zone total position
103
  MWAWBox2l m_dim;
104
  //! the page dimension (?)
105
  MWAWBox2i m_pageDim;
106
  //! the zone of text dimension ( ie page less margins)
107
  MWAWBox2i m_pageTextDim;
108
  //! the section
109
  MWAWSection m_section;
110
  //! the background color
111
  MWAWColor m_backgroundColor;
112
  //! extra data
113
  std::string m_extra;
114
};
115
116
std::ostream &operator<<(std::ostream &o, Zone const &zone)
117
0
{
118
0
  switch (zone.m_type) {
119
0
  case Zone::Z_Main:
120
0
    o << "main,";
121
0
    break;
122
0
  case Zone::Z_Footnote:
123
0
    if (zone.m_endNote)
124
0
      o <<  "endnote,";
125
0
    else
126
0
      o << "footnote,";
127
0
    break;
128
0
  case Zone::Z_Header:
129
0
    o << "header,";
130
0
    break;
131
0
  case Zone::Z_Footer:
132
0
    o << "footer,";
133
0
    break;
134
0
  case Zone::Z_Unknown:
135
#if !defined(__clang__)
136
  default:
137
#endif
138
0
    break;
139
0
  }
140
0
  if (zone.m_type==Zone::Z_Header || zone.m_type==Zone::Z_Footer) {
141
0
    switch (zone.m_fileId) {
142
0
    case 0:
143
0
      break; // main
144
0
    case 1:
145
0
      o << "left,";
146
0
      break;
147
0
    case 2:
148
0
      o << "right,";
149
0
      break;
150
0
    case 3:
151
0
      o << "firstpage,";
152
0
      break;
153
0
    default:
154
0
      o << "#fileId" << zone.m_fileId << ",";
155
0
      break;
156
0
    }
157
0
  }
158
0
  else if (zone.m_fileId & 0xFFFFFF)
159
0
    o << "fileId=" << std::hex << (zone.m_fileId&0xFFFFFF) << std::dec << ",";
160
0
  if (zone.m_RBpos[0] || zone.m_RBpos[1])
161
0
    o << "RBpos=" << zone.m_RBpos << ",";
162
0
  if (zone.m_height)
163
0
    o << "height=" << zone.m_height << ",";
164
0
  if (zone.m_dim.size()[0] || zone.m_dim.size()[1])
165
0
    o << "dim=" << zone.m_dim << ",";
166
0
  if (!zone.m_backgroundColor.isWhite())
167
0
    o << "background=" << zone.m_backgroundColor << ",";
168
0
  o << zone.m_extra;
169
0
  return o;
170
0
}
171
////////////////////////////////////////
172
//! Internal: the state of a MarinerWrtParser
173
struct State {
174
  //! constructor
175
  State()
176
172k
    : m_zonesList()
177
172k
    , m_fileToZoneMap()
178
172k
    , m_actPage(0)
179
172k
    , m_numPages(0)
180
172k
    , m_firstPageFooter(false)
181
172k
    , m_hasOddEvenHeaderFooter(false)
182
172k
  {
183
172k
  }
184
185
  //! the list of zone
186
  std::vector<Zone> m_zonesList;
187
  //! a map fileZoneId -> localZoneId
188
  std::map<uint32_t,int> m_fileToZoneMap;
189
  int m_actPage /** the actual page */, m_numPages /** the number of page of the final document */;
190
  /** a flag to know if we have a first page footer */
191
  bool m_firstPageFooter;
192
  /** a flag to know if we have odd/even header footer */
193
  bool m_hasOddEvenHeaderFooter;
194
};
195
196
////////////////////////////////////////
197
//! Internal: the subdocument of a MarinerWrtParser
198
class SubDocument final : public MWAWSubDocument
199
{
200
public:
201
  SubDocument(MarinerWrtParser &pars, MWAWInputStreamPtr const &input, int zoneId)
202
1.44k
    : MWAWSubDocument(&pars, input, MWAWEntry())
203
1.44k
    , m_id(zoneId)
204
1.44k
  {
205
1.44k
  }
206
207
  //! destructor
208
0
  ~SubDocument() final {}
209
210
  //! operator!=
211
  bool operator!=(MWAWSubDocument const &doc) const final
212
0
  {
213
0
    if (MWAWSubDocument::operator!=(doc)) return true;
214
0
    auto const *sDoc = dynamic_cast<SubDocument const *>(&doc);
215
0
    if (!sDoc) return true;
216
0
    if (m_id != sDoc->m_id) return true;
217
0
    return false;
218
0
  }
219
220
  //! the parser function
221
  void parse(MWAWListenerPtr &listener, libmwaw::SubDocumentType type) final;
222
223
protected:
224
  //! the subdocument id
225
  int m_id;
226
};
227
228
void SubDocument::parse(MWAWListenerPtr &listener, libmwaw::SubDocumentType /*type*/)
229
1.35k
{
230
1.35k
  if (!listener.get()) {
231
0
    MWAW_DEBUG_MSG(("MarinerWrtParserInternal::SubDocument::parse: no listener\n"));
232
0
    return;
233
0
  }
234
1.35k
  auto *parser=dynamic_cast<MarinerWrtParser *>(m_parser);
235
1.35k
  if (!parser) {
236
0
    MWAW_DEBUG_MSG(("MarinerWrtParserInternal::SubDocument::parse: no parser\n"));
237
0
    return;
238
0
  }
239
1.35k
  long pos = m_input->tell();
240
1.35k
  parser->sendText(m_id);
241
1.35k
  m_input->seek(pos, librevenge::RVNG_SEEK_SET);
242
1.35k
}
243
}
244
245
////////////////////////////////////////////////////////////
246
// constructor/destructor + basic interface ...
247
////////////////////////////////////////////////////////////
248
MarinerWrtParser::MarinerWrtParser(MWAWInputStreamPtr const &input, MWAWRSRCParserPtr const &rsrcParser, MWAWHeader *header)
249
74.0k
  : MWAWTextParser(input, rsrcParser, header)
250
74.0k
  , m_state()
251
74.0k
  , m_pageMarginsSpanSet(false)
252
74.0k
  , m_graphParser()
253
74.0k
  , m_textParser()
254
74.0k
{
255
74.0k
  init();
256
74.0k
}
257
258
MarinerWrtParser::~MarinerWrtParser()
259
74.0k
{
260
74.0k
}
261
262
void MarinerWrtParser::init()
263
74.0k
{
264
74.0k
  resetTextListener();
265
74.0k
  setAsciiName("main-1");
266
267
74.0k
  m_state.reset(new MarinerWrtParserInternal::State);
268
269
  // reduce the margin (in case, the page is not defined)
270
74.0k
  getPageSpan().setMargins(0.1);
271
272
74.0k
  m_graphParser.reset(new MarinerWrtGraph(*this));
273
74.0k
  m_textParser.reset(new MarinerWrtText(*this));
274
74.0k
}
275
276
////////////////////////////////////////////////////////////
277
// position and height
278
////////////////////////////////////////////////////////////
279
MWAWVec2f MarinerWrtParser::getPageLeftTop() const
280
0
{
281
0
  return MWAWVec2f(float(getPageSpan().getMarginLeft()),
282
0
                   float(getPageSpan().getMarginTop()));
283
0
}
284
285
MWAWSection MarinerWrtParser::getSection(int zId) const
286
4.83k
{
287
4.83k
  if (zId >= 0 && zId < int(m_state->m_zonesList.size()))
288
4.83k
    return m_state->m_zonesList[size_t(zId)].m_section;
289
0
  return MWAWSection();
290
4.83k
}
291
292
////////////////////////////////////////////////////////////
293
// new page
294
////////////////////////////////////////////////////////////
295
void MarinerWrtParser::newPage(int number)
296
38.1k
{
297
38.1k
  if (number <= m_state->m_actPage || number > m_state->m_numPages)
298
24.6k
    return;
299
300
27.0k
  while (m_state->m_actPage < number) {
301
13.5k
    m_state->m_actPage++;
302
13.5k
    if (!getTextListener() || m_state->m_actPage == 1)
303
4.83k
      continue;
304
8.70k
    getTextListener()->insertBreak(MWAWTextListener::PageBreak);
305
8.70k
  }
306
13.5k
}
307
308
////////////////////////////////////////////////////////////
309
// interface
310
////////////////////////////////////////////////////////////
311
int MarinerWrtParser::getZoneId(uint32_t fileId, bool &endNote)
312
2.95k
{
313
2.95k
  if (m_state->m_fileToZoneMap.find(fileId)==m_state->m_fileToZoneMap.end()) {
314
2.41k
    MWAW_DEBUG_MSG(("MarinerWrtParser::getZoneId: can not find zone for %x\n", fileId));
315
2.41k
    return -1;
316
2.41k
  }
317
543
  int id=m_state->m_fileToZoneMap.find(fileId)->second;
318
543
  endNote=false;
319
543
  if (id>=0 && id < int(m_state->m_zonesList.size()))
320
543
    endNote = m_state->m_zonesList[size_t(id)].m_endNote;
321
543
  return id;
322
2.95k
}
323
324
void MarinerWrtParser::sendText(int zoneId)
325
4.30k
{
326
4.30k
  MWAWInputStreamPtr input = getInput();
327
4.30k
  long actPos = input->tell();
328
4.30k
  m_textParser->send(zoneId);
329
4.30k
  input->seek(actPos, librevenge::RVNG_SEEK_SET);
330
4.30k
}
331
332
float MarinerWrtParser::getPatternPercent(int id) const
333
403k
{
334
403k
  return m_graphParser->getPatternPercent(id);
335
403k
}
336
337
void MarinerWrtParser::sendToken(int zoneId, long tokenId)
338
16.6k
{
339
16.6k
  MWAWInputStreamPtr input = getInput();
340
16.6k
  long actPos = input->tell();
341
16.6k
  m_graphParser->sendToken(zoneId, tokenId);
342
16.6k
  input->seek(actPos, librevenge::RVNG_SEEK_SET);
343
16.6k
}
344
345
////////////////////////////////////////////////////////////
346
// the parser
347
////////////////////////////////////////////////////////////
348
void MarinerWrtParser::parse(librevenge::RVNGTextInterface *docInterface)
349
24.1k
{
350
24.1k
  if (!getInput().get() || !checkHeader(nullptr)) throw(libmwaw::ParseException());
351
24.1k
  bool ok = true;
352
24.1k
  try {
353
    // create the asciiFile
354
24.1k
    ascii().setStream(getInput());
355
24.1k
    ascii().open(asciiName());
356
357
24.1k
    checkHeader(nullptr);
358
24.1k
    ok = createZones();
359
24.1k
    if (ok) {
360
6.90k
      createDocument(docInterface);
361
6.90k
      m_graphParser->sendPageGraphics();
362
6.90k
      m_textParser->send(0);
363
364
#ifdef DEBUG
365
      m_textParser->flushExtra();
366
      m_graphParser->flushExtra();
367
#endif
368
6.90k
    }
369
24.1k
    ascii().reset();
370
24.1k
  }
371
24.1k
  catch (...) {
372
0
    MWAW_DEBUG_MSG(("MarinerWrtParser::parse: exception catched when parsing\n"));
373
0
    ok = false;
374
0
  }
375
376
24.1k
  resetTextListener();
377
24.1k
  if (!ok) throw(libmwaw::ParseException());
378
24.1k
}
379
380
////////////////////////////////////////////////////////////
381
// create the document
382
////////////////////////////////////////////////////////////
383
void MarinerWrtParser::createDocument(librevenge::RVNGTextInterface *documentInterface)
384
6.90k
{
385
6.90k
  if (!documentInterface) return;
386
6.90k
  if (getTextListener()) {
387
0
    MWAW_DEBUG_MSG(("MarinerWrtParser::createDocument: listener already exist\n"));
388
0
    return;
389
0
  }
390
391
  // update the page
392
6.90k
  m_state->m_actPage = 0;
393
394
6.90k
  int numPage = m_textParser->numPages();
395
6.90k
  if (m_graphParser->numPages() > numPage)
396
0
    numPage = m_graphParser->numPages();
397
6.90k
  m_state->m_numPages = numPage;
398
399
  // create the page list
400
6.90k
  MWAWPageSpan ps(getPageSpan());
401
6.90k
  if (m_state->m_zonesList.size())
402
6.90k
    ps.setBackgroundColor(m_state->m_zonesList[0].m_backgroundColor);
403
404
  // look for an header/footer
405
6.90k
  int headerId[4] = { -1, -1, -1, -1}, footerId[4] = { -1, -1, -1, -1};
406
82.3k
  for (size_t z = 0; z < m_state->m_zonesList.size(); z++) {
407
75.4k
    auto const &zone=m_state->m_zonesList[z];
408
75.4k
    if (zone.m_type==MarinerWrtParserInternal::Zone::Z_Header) {
409
1.24k
      if (zone.m_fileId < 4)
410
1.22k
        headerId[zone.m_fileId]=int(z);
411
1.24k
    }
412
74.2k
    else if (zone.m_type==MarinerWrtParserInternal::Zone::Z_Footer) {
413
1.14k
      if (zone.m_fileId < 4)
414
723
        footerId[zone.m_fileId]=int(z);
415
1.14k
    }
416
75.4k
  }
417
6.90k
  MWAWPageSpan firstPs(ps);
418
6.90k
  if (m_state->m_firstPageFooter) {
419
1.21k
    if (headerId[3]>0) {
420
367
      MWAWHeaderFooter header(MWAWHeaderFooter::HEADER, MWAWHeaderFooter::ALL);
421
367
      header.m_subDocument.reset(new MarinerWrtParserInternal::SubDocument(*this, getInput(), int(headerId[3])));
422
367
      firstPs.setHeaderFooter(header);
423
367
    }
424
1.21k
    if (footerId[3]>0) {
425
173
      MWAWHeaderFooter footer(MWAWHeaderFooter::FOOTER, MWAWHeaderFooter::ALL);
426
173
      footer.m_subDocument.reset(new MarinerWrtParserInternal::SubDocument(*this, getInput(), int(footerId[3])));
427
173
      firstPs.setHeaderFooter(footer);
428
173
    }
429
1.21k
  }
430
6.98k
  for (int st = 0; st < 2; st++) {
431
6.94k
    MWAWHeaderFooter::Occurrence what=
432
6.94k
      !m_state->m_hasOddEvenHeaderFooter ? MWAWHeaderFooter::ALL : st==0 ? MWAWHeaderFooter::ODD : MWAWHeaderFooter::EVEN;
433
6.94k
    int which= !m_state->m_hasOddEvenHeaderFooter ? 0 : 1+st;
434
6.94k
    if (headerId[which]>0) {
435
566
      MWAWHeaderFooter header(MWAWHeaderFooter::HEADER, what);
436
566
      header.m_subDocument.reset(new MarinerWrtParserInternal::SubDocument(*this, getInput(), int(headerId[which])));
437
566
      ps.setHeaderFooter(header);
438
566
    }
439
6.94k
    if (footerId[which]>0) {
440
343
      MWAWHeaderFooter footer(MWAWHeaderFooter::FOOTER, what);
441
343
      footer.m_subDocument.reset(new MarinerWrtParserInternal::SubDocument(*this, getInput(), int(footerId[which])));
442
343
      ps.setHeaderFooter(footer);
443
343
    }
444
6.94k
    if (!m_state->m_hasOddEvenHeaderFooter)
445
6.86k
      break;
446
6.94k
  }
447
448
6.90k
  std::vector<MWAWPageSpan> pageList;
449
6.90k
  if (m_state->m_firstPageFooter) {
450
1.21k
    pageList.push_back(firstPs);
451
1.21k
    ps.setPageSpan(m_state->m_numPages);
452
1.21k
  }
453
5.69k
  else
454
5.69k
    ps.setPageSpan(m_state->m_numPages+1);
455
6.90k
  if (ps.getPageSpan())
456
6.90k
    pageList.push_back(ps);
457
  //
458
6.90k
  MWAWTextListenerPtr listen(new MWAWTextListener(*getParserState(), pageList, documentInterface));
459
6.90k
  setTextListener(listen);
460
6.90k
  listen->startDocument();
461
6.90k
}
462
463
464
////////////////////////////////////////////////////////////
465
//
466
// Intermediate level
467
//
468
////////////////////////////////////////////////////////////
469
470
// ------ read the different zones ---------
471
bool MarinerWrtParser::createZones()
472
24.1k
{
473
24.1k
  MWAWInputStreamPtr input = getInput();
474
24.1k
  long pos = input->tell();
475
24.1k
  int actZone=-1;
476
579k
  while (readZone(actZone))
477
555k
    pos = input->tell();
478
24.1k
  ascii().addPos(pos);
479
24.1k
  ascii().addNote("Entries(Loose)");
480
24.1k
  return m_state->m_zonesList.size();
481
24.1k
}
482
483
bool MarinerWrtParser::readZone(int &actZone, bool onlyTest)
484
710k
{
485
710k
  MWAWInputStreamPtr input = getInput();
486
710k
  if (input->isEnd())
487
3.32k
    return false;
488
706k
  long pos = input->tell();
489
706k
  MarinerWrtEntry zone;
490
706k
  if (!readEntryHeader(zone)) {
491
26.4k
    input->seek(pos, librevenge::RVNG_SEEK_SET);
492
26.4k
    return false;
493
26.4k
  }
494
495
680k
  libmwaw::DebugStream f;
496
680k
  f << "Entries(" << zone.name() << "):" << zone;
497
498
680k
  bool done = false;
499
680k
  switch (zone.m_fileType) {
500
215k
  case -1: // separator
501
219k
  case -2: // last file
502
219k
    done = readSeparator(zone);
503
219k
    if (onlyTest)
504
76.1k
      break;
505
143k
    actZone++;
506
143k
    break;
507
59.2k
  case 0:
508
59.2k
    done = readZoneHeader(zone, actZone, onlyTest);
509
59.2k
    break;
510
28.0k
  case 1:
511
28.0k
    done = m_textParser->readTextStruct(zone, actZone);
512
28.0k
    break;
513
10.2k
  case 2:
514
10.2k
    done = m_textParser->readZone(zone, actZone);
515
10.2k
    break;
516
10.2k
  case 4:
517
29.7k
  case 5:
518
29.7k
    done = m_textParser->readPLCZone(zone, actZone);
519
29.7k
    break;
520
18.1k
  case 6:
521
18.1k
    done = m_textParser->readFonts(zone, actZone);
522
18.1k
    break;
523
58.9k
  case 7:
524
58.9k
    done = m_textParser->readRulers(zone, actZone);
525
58.9k
    break;
526
49.8k
  case 8:
527
49.8k
    done = m_textParser->readFontNames(zone, actZone);
528
49.8k
    break;
529
4.95k
  case 9: // zone size
530
4.95k
    done = readZoneDim(zone, actZone);
531
4.95k
    break;
532
10.4k
  case 0xa: // zone size with margins removal
533
10.4k
    done = readZoneDim(zone, actZone);
534
10.4k
    break;
535
6.53k
  case 0xb: // border dim?
536
6.53k
    done = readZoneb(zone, actZone);
537
6.53k
    break;
538
13.3k
  case 0xc:
539
13.3k
    done = readZonec(zone, actZone);
540
13.3k
    break;
541
51.8k
  case 0xf:
542
51.8k
    done = readDocInfo(zone, actZone);
543
51.8k
    break;
544
11.0k
  case 0x13:
545
11.0k
    done = readZone13(zone, actZone);
546
11.0k
    break;
547
50.1k
  case 0x14:
548
50.1k
    done = m_graphParser->readToken(zone, actZone);
549
50.1k
    break;
550
12.0k
  case 0x1a:
551
12.0k
    done = m_textParser->readStyleNames(zone, actZone);
552
12.0k
    break;
553
3.45k
  case 0x1f:
554
3.45k
    done = readPrintInfo(zone);
555
3.45k
    break;
556
3.94k
  case 0x24:
557
3.94k
    done = readCPRT(zone);
558
3.94k
    break;
559
  /* 0x41a: docInfo */
560
7.15k
  case 0x420:
561
7.15k
    done = m_graphParser->readPostscript(zone, actZone);
562
7.15k
    break;
563
31.5k
  default:
564
31.5k
    break;
565
680k
  }
566
680k
  if (done) {
567
538k
    ascii().addPos(pos);
568
538k
    ascii().addNote(f.str().c_str());
569
538k
    input->seek(zone.end(), librevenge::RVNG_SEEK_SET);
570
538k
    return true;
571
538k
  }
572
141k
  if (onlyTest)
573
11.8k
    return false;
574
129k
  input->seek(zone.begin(), librevenge::RVNG_SEEK_SET);
575
129k
  input->pushLimit(zone.end());
576
129k
  std::vector<MarinerWrtStruct> dataList;
577
129k
  decodeZone(dataList);
578
129k
  input->popLimit();
579
580
129k
  size_t numData = dataList.size();
581
129k
  f << "numData=" << numData << ",";
582
129k
  ascii().addPos(pos);
583
129k
  ascii().addNote(f.str().c_str());
584
585
129k
  int numDataByField = zone.m_fileType==1 ? 22 : 10;
586
6.16M
  for (size_t d = 0; d < numData; d++) {
587
6.03M
    MarinerWrtStruct const &dt = dataList[d];
588
6.03M
    if ((int(d)%numDataByField)==0) {
589
681k
      if (d)
590
573k
        ascii().addNote(f.str().c_str());
591
681k
      f.str("");
592
681k
      f << zone.name() << "-" << d << ":";
593
681k
      ascii().addPos(dt.m_filePos);
594
681k
    }
595
6.03M
    f << dt << ",";
596
6.03M
  }
597
129k
  if (numData)
598
108k
    ascii().addNote(f.str().c_str());
599
600
129k
  if (input->tell() != zone.end()) {
601
74.5k
    f.str("");
602
74.5k
    if (input->tell() == zone.end()-1)
603
5.19k
      f << "_";
604
69.4k
    else
605
69.4k
      f << zone.name() << ":###";
606
74.5k
    ascii().addPos(input->tell());
607
74.5k
    ascii().addNote(f.str().c_str());
608
74.5k
  }
609
129k
  input->seek(zone.end(), librevenge::RVNG_SEEK_SET);
610
129k
  return true;
611
141k
}
612
613
// --------- zone separator ----------
614
615
// read the zone separator
616
bool MarinerWrtParser::readSeparator(MarinerWrtEntry const &entry)
617
219k
{
618
219k
  if (entry.length() < 0x3) {
619
4.34k
    MWAW_DEBUG_MSG(("MarinerWrtParser::readSeparator: data seems to short\n"));
620
4.34k
    return false;
621
4.34k
  }
622
215k
  MWAWInputStreamPtr input = getInput();
623
215k
  input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
624
215k
  input->pushLimit(entry.end());
625
215k
  std::vector<MarinerWrtStruct> dataList;
626
215k
  decodeZone(dataList);
627
215k
  input->popLimit();
628
629
215k
  if (dataList.size() != 1) {
630
3.11k
    MWAW_DEBUG_MSG(("MarinerWrtParser::readSeparator: can find my data\n"));
631
3.11k
    return false;
632
3.11k
  }
633
634
212k
  MarinerWrtStruct const &data = dataList[0]; // always 0x77aa
635
212k
  libmwaw::DebugStream f;
636
212k
  f << entry.name() << "[data]:";
637
212k
  if (data.m_data.size() != 1 || data.m_data[0] != 0x77aa)
638
146k
    f << "#" << data;
639
212k
  ascii().addPos(entry.begin());
640
212k
  ascii().addNote(f.str().c_str());
641
642
212k
  return true;
643
215k
}
644
645
bool MarinerWrtParser::readZoneHeader(MarinerWrtEntry const &entry, int actId, bool onlyTest)
646
59.2k
{
647
59.2k
  if (entry.length() < 3) {
648
2.19k
    MWAW_DEBUG_MSG(("MarinerWrtParser::readZoneHeader: data seems to short\n"));
649
2.19k
    return false;
650
2.19k
  }
651
57.0k
  MWAWInputStreamPtr input = getInput();
652
57.0k
  input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
653
57.0k
  input->pushLimit(entry.end());
654
57.0k
  std::vector<MarinerWrtStruct> dataList;
655
57.0k
  decodeZone(dataList);
656
57.0k
  input->popLimit();
657
658
57.0k
  size_t numData = dataList.size();
659
57.0k
  if (numData < 47) {
660
9.68k
    MWAW_DEBUG_MSG(("MarinerWrtParser::readZoneHeader: find unexpected number of data\n"));
661
9.68k
    return false;
662
9.68k
  }
663
47.3k
  if (onlyTest)
664
6.98k
    return true;
665
40.3k
  size_t d = 0;
666
40.3k
  long val;
667
40.3k
  libmwaw::DebugStream f;
668
40.3k
  MarinerWrtParserInternal::Zone zone;
669
1.63M
  for (int j = 0; j < 47; j++) {
670
1.59M
    MarinerWrtStruct const &data = dataList[d++];
671
1.59M
    if (!data.isBasic()) {
672
138k
      f << "###f" << j << "=" << data << ",";
673
138k
      continue;
674
138k
    }
675
1.45M
    long sel[4]= {0,0,0,0};
676
1.45M
    int dim[4]= {0,0,0,0};
677
1.45M
    unsigned char color[3];
678
1.45M
    switch (j) {
679
33.7k
    case 0: // version?
680
33.7k
      val = data.value(0);
681
33.7k
      if ((val>>16)==1) // checkme v1.6 -> 1[29] while v3.5->1[33]
682
7.30k
        setVersion((val&0xFFFF)<30 ? 1 : 2);
683
33.7k
      f << "vers?=" << (val>>16) << "[" << (val&0xFFFF) << "],";
684
33.7k
      break;
685
37.4k
    case 1:
686
37.4k
      val = data.value(0);
687
37.4k
      if (val>>16) // 0 or 1000
688
7.90k
        f << "f1[high]=" << std::hex << (val>>16) << std::dec << ",";
689
37.4k
      if ((val&0xFFFF)!=1)
690
25.7k
        f << "f1[low]=" << (val& 0xFFFF) << ",";
691
37.4k
      break;
692
37.4k
    case 2: { // find 8[01]0[0145]8120 or a0808120
693
37.4k
      uint32_t high = uint32_t(data.value(0))>>16;
694
      // high&4: no odd/even header/footer ?
695
37.4k
      if (high) f << "fl2[high]=" << std::hex << high << std::dec << ",";
696
37.4k
      uint32_t low = uint32_t(data.value(0))&0xFFFF;
697
37.4k
      if (low) f << "fl2[low]=" << std::hex << low << std::dec << ",";
698
37.4k
      break;
699
0
    }
700
37.4k
    case 3: { // 80000[01] or 800000[01]
701
37.4k
      auto value=uint32_t(data.value(0));
702
37.4k
      if (value&0x2000000) {
703
1.19k
        zone.m_endNote=true;
704
1.19k
        value &= ~uint32_t(0x2000000);
705
1.19k
      }
706
      // value&1: firstPage[header/footer] ?
707
37.4k
      if (value)
708
33.0k
        f << "fl3=" << std::hex << value << std::dec << ",";
709
37.4k
      break;
710
0
    }
711
37.4k
    case 4: {
712
37.4k
      auto v = uint32_t(data.value(0));
713
37.4k
      switch (v>>28) {
714
33.3k
      case 0: // main
715
33.3k
        zone.m_type = MarinerWrtParserInternal::Zone::Z_Main;
716
33.3k
        break;
717
1.24k
      case 0xc:
718
1.24k
        zone.m_type = MarinerWrtParserInternal::Zone::Z_Header;
719
1.24k
        break;
720
1.19k
      case 0xd:
721
1.19k
        zone.m_type = MarinerWrtParserInternal::Zone::Z_Footer;
722
1.19k
        break;
723
1.25k
      case 0xe:
724
1.25k
        zone.m_type = MarinerWrtParserInternal::Zone::Z_Footnote;
725
1.25k
        break;
726
404
      default:
727
404
        f << "#type=" << (v>>28) << ",";
728
404
        break;
729
37.4k
      }
730
37.4k
      zone.m_fileId=(v&0xFFFFFFF);
731
37.4k
      m_state->m_fileToZoneMap[v]=actId;
732
37.4k
      break;
733
37.4k
    }
734
37.4k
    case 9: // real bottom margin
735
37.4k
      if (data.value(0))
736
32.9k
        f << "y[bottom+footer?]=" << data.value(0) << ",";
737
37.4k
      break;
738
37.4k
    case 10:
739
37.4k
      zone.m_height = data.value(0);
740
37.4k
      break;
741
37.3k
    case 13: // right margin
742
74.7k
    case 14: // bottom margin
743
74.7k
      zone.m_RBpos[j-13] = data.value(0);
744
74.7k
      break;
745
37.4k
    case 21:
746
37.4k
      if (data.value(0))
747
29.9k
        f << "h[act]=" << data.value(0) << ",";
748
37.4k
      break;
749
37.4k
    case 5: // 0|14|90
750
74.9k
    case 6: // 0|11-14
751
112k
    case 15: // -2: main?|-1
752
149k
    case 16: // -2: main?|-1
753
187k
    case 25: // 0|43
754
224k
    case 41: // 0|5|26
755
224k
      if (data.value(0))
756
181k
        f << "f" << j << "=" << data.value(0) << ",";
757
224k
      break;
758
37.4k
    case 7: // two units ?
759
37.4k
      if (data.value(0) != 0x480048)
760
30.4k
        f << "f" << j << "=" << std::hex << data.value(0) << std::dec << ",";
761
37.4k
      break;
762
37.4k
    case 8: // always -2?
763
37.4k
      if (data.value(0) != -2)
764
30.3k
        f << "#f" << j << "=" << data.value(0) << ",";
765
37.4k
      break;
766
37.4k
    case 12: // always 16
767
37.4k
      if (data.value(0) != 16)
768
29.5k
        f << "#f" << j << "=" << data.value(0) << ",";
769
37.4k
      break;
770
37.3k
    case 17:
771
37.4k
    case 18:
772
37.4k
    case 19:
773
37.4k
    case 20:
774
37.4k
      sel[j-17] = data.value(0);
775
149k
      while (j<20)
776
112k
        sel[++j-17] = dataList[d++].value(0);
777
37.4k
      if (sel[0]||sel[1])
778
29.9k
        f << "sel0=" << std::hex << sel[0] << "x" << sel[1] << std::dec << ",";
779
37.4k
      if (sel[2]||sel[3])
780
29.9k
        f << "sel1=" << std::hex << sel[2] << "x" << sel[3] << std::dec << ",";
781
37.4k
      break;
782
37.4k
    case 28: // left margin
783
37.4k
    case 29: // top margin
784
37.4k
    case 30:
785
37.4k
    case 31:
786
37.4k
      dim[j-28] = static_cast<int>(data.value(0));
787
149k
      while (j<31)
788
112k
        dim[++j-28] = static_cast<int>(dataList[d++].value(0));
789
37.4k
      zone.m_dim = MWAWBox2l(MWAWVec2l(dim[1],dim[0]), MWAWVec2l(dim[3],dim[2]));
790
37.4k
      break;
791
37.3k
    case 32:
792
37.4k
    case 33:
793
39.2k
    case 34: { // 35,36,37: front color?
794
39.2k
      color[0]=color[1]=color[2]=0xFF;
795
39.2k
      color[j-32]=static_cast<unsigned char>(data.value(0)>>8);
796
114k
      while (j < 34)
797
74.8k
        color[++j-32] = static_cast<unsigned char>(dataList[d++].value(0)>>8);
798
39.2k
      zone.m_backgroundColor = MWAWColor(color[0],color[1],color[2]);
799
39.2k
      break;
800
37.4k
    }
801
37.4k
    case 38:
802
37.4k
      if (data.value(0)!=1)
803
26.3k
        f << "#f" << j << "=" << data.value(0) << ",";
804
37.4k
      break;
805
37.4k
    case 39:
806
37.4k
      if (data.value(0) && data.value(0)!=0x4d4d4242) // MMBB: creator
807
25.8k
        f << "#creator=" << std::hex << uint32_t(data.value(0)) << std::dec << ",";
808
37.4k
      break;
809
37.4k
    case 40: // normally 0 or pretty small, but can also be very very big
810
37.4k
      if (data.value(0))
811
30.8k
        f << "f" << j << "=" << std::hex << data.value(0) << std::dec << ",";
812
37.4k
      break;
813
37.4k
    case 42:
814
37.4k
      if (data.value(0)!=43)
815
30.8k
        f << "#f" << j << "=" << data.value(0) << ",";
816
37.4k
      break;
817
37.4k
    case 44:
818
37.4k
      if (data.value(0))
819
32.8k
        f << "sel[pt]=" << std::hex << data.value(0) << std::dec << ",";
820
37.4k
      break;
821
37.4k
    case 45:
822
37.4k
      if (data.value(0)!=72)
823
30.8k
        f << "#f" << j << "=" << data.value(0) << ",";
824
37.4k
      break;
825
411k
    default:
826
411k
      if (data.value(0))
827
285k
        f << "#f" << j << "=" << data.value(0) << ",";
828
411k
      break;
829
1.45M
    }
830
1.45M
  }
831
5.41M
  while (d < numData) {
832
5.37M
    f << "#f" << d << "=" << dataList[d] << ",";
833
5.37M
    d++;
834
5.37M
  }
835
40.3k
  zone.m_extra = f.str();
836
40.3k
  if (actId < 0) {
837
3.74k
    MWAW_DEBUG_MSG(("MarinerWrtParser::readZoneHeader: called with negative id\n"));
838
3.74k
  }
839
36.6k
  else {
840
36.6k
    if (actId >= int(m_state->m_zonesList.size()))
841
28.5k
      m_state->m_zonesList.resize(size_t(actId)+1);
842
36.6k
    m_state->m_zonesList[size_t(actId)] = zone;
843
36.6k
  }
844
40.3k
  f.str("");
845
40.3k
  f << entry.name() << ":" << zone;
846
847
40.3k
  ascii().addPos(entry.begin());
848
40.3k
  ascii().addNote(f.str().c_str());
849
40.3k
  return true;
850
40.3k
}
851
852
bool MarinerWrtParser::readZoneDim(MarinerWrtEntry const &entry, int zoneId)
853
15.3k
{
854
15.3k
  if (entry.length() < entry.m_N) {
855
535
    MWAW_DEBUG_MSG(("MarinerWrtParser::readZoneDim: data seems to short\n"));
856
535
    return false;
857
535
  }
858
14.8k
  MWAWInputStreamPtr input = getInput();
859
14.8k
  input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
860
14.8k
  input->pushLimit(entry.end());
861
14.8k
  std::vector<MarinerWrtStruct> dataList;
862
14.8k
  decodeZone(dataList, 1+4*entry.m_N);
863
14.8k
  input->popLimit();
864
865
14.8k
  if (int(dataList.size()) != 4*entry.m_N) {
866
1.51k
    MWAW_DEBUG_MSG(("MarinerWrtParser::readZoneDim: find unexpected number of data\n"));
867
1.51k
    return false;
868
1.51k
  }
869
870
13.3k
  libmwaw::DebugStream f;
871
13.3k
  size_t d = 0;
872
13.3k
  std::vector<int> colPos;
873
39.6k
  for (int i = 0; i < entry.m_N; i++) {
874
26.3k
    f.str("");
875
26.3k
    f << entry.name() << "-" << i << ":";
876
26.3k
    ascii().addPos(dataList[d].m_filePos);
877
878
26.3k
    int dim[4] = { 0, 0, 0, 0 };
879
131k
    for (int j = 0; j < 4; j++) {
880
105k
      MarinerWrtStruct const &data = dataList[d++];
881
105k
      if (!data.isBasic()) {
882
4.90k
        MWAW_DEBUG_MSG(("MarinerWrtParser::readZoneDim: find unexpected dim data type\n"));
883
4.90k
        f << "###dim" << j << "=" << data << ",";
884
4.90k
      }
885
100k
      else
886
100k
        dim[j] = static_cast<int>(data.value(0));
887
105k
    }
888
    // checkme
889
26.3k
    MWAWBox2i dimension(MWAWVec2i(dim[1],dim[0]), MWAWVec2i(dim[3],dim[2]));
890
26.3k
    f << "pos=" << dimension << ",";
891
26.3k
    bool dimOk=dim[0] >= 0 && dim[0] < dim[2] && dim[1] >= 0 && dim[1] < dim[3];
892
26.3k
    if (i==0 && dimOk) {
893
8.01k
      if (zoneId < 0 || zoneId >= int(m_state->m_zonesList.size())) {
894
755
        MWAW_DEBUG_MSG(("MarinerWrtParser::readZoneDim: can not find the zone storage\n"));
895
755
      }
896
7.26k
      else if (entry.m_fileType == 9)
897
3.65k
        m_state->m_zonesList[size_t(zoneId)].m_pageDim = dimension;
898
3.60k
      else if (entry.m_fileType == 0xa)
899
3.60k
        m_state->m_zonesList[size_t(zoneId)].m_pageTextDim = dimension;
900
0
      else {
901
0
        MWAW_DEBUG_MSG(("MarinerWrtParser::readZoneDim: unknown zone type\n"));
902
0
      }
903
8.01k
    }
904
18.2k
    else if (i && dimOk) {
905
9.43k
      if (!colPos.size() || colPos.back() <= dim[1]) {
906
9.39k
        colPos.push_back(dim[1]);
907
9.39k
        colPos.push_back(dim[3]);
908
9.39k
      }
909
46
      else
910
46
        f << "###";
911
9.43k
    }
912
26.3k
    ascii().addNote(f.str().c_str());
913
26.3k
  }
914
13.3k
  if (entry.m_fileType == 0xa && zoneId >= 0 &&
915
7.82k
      zoneId < int(m_state->m_zonesList.size()) &&
916
3.66k
      colPos.size() > 2 && int(colPos.size())==2*(entry.m_N-1)) {
917
862
    auto numCols=size_t(entry.m_N-1);
918
862
    MWAWSection &sec=m_state->m_zonesList[size_t(zoneId)].m_section;
919
862
    sec.m_columns.resize(numCols);
920
2.58k
    for (size_t c=0; c < numCols; c++) {
921
1.72k
      MWAWSection::Column &col = sec.m_columns[c];
922
1.72k
      int prevPos= c==0 ? colPos[0] : (colPos[2*c-1]+colPos[2*c])/2;
923
1.72k
      int nextPos= c+1==numCols ? colPos[2*c+1] :
924
1.72k
                   (colPos[2*c+1]+colPos[2*c+2])/2;
925
1.72k
      col.m_width=double(nextPos-prevPos);
926
1.72k
      col.m_widthUnit=librevenge::RVNG_POINT;
927
1.72k
      col.m_margins[libmwaw::Left]=double(colPos[2*c]-prevPos)/72.;
928
1.72k
      col.m_margins[libmwaw::Right]=double(nextPos-colPos[2*c+1])/72.;
929
1.72k
    }
930
862
  }
931
13.3k
  input->seek(entry.end(), librevenge::RVNG_SEEK_SET);
932
933
13.3k
  return true;
934
14.8k
}
935
936
bool MarinerWrtParser::readDocInfo(MarinerWrtEntry const &entry, int zoneId)
937
51.8k
{
938
51.8k
  if (entry.length() < 3) {
939
4.70k
    MWAW_DEBUG_MSG(("MarinerWrtParser::readDocInfo: data seems to short\n"));
940
4.70k
    return false;
941
4.70k
  }
942
47.1k
  MWAWInputStreamPtr input = getInput();
943
47.1k
  input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
944
47.1k
  input->pushLimit(entry.end());
945
47.1k
  std::vector<MarinerWrtStruct> dataList;
946
47.1k
  decodeZone(dataList);
947
47.1k
  input->popLimit();
948
949
47.1k
  auto numDatas = int(dataList.size());
950
47.1k
  if (numDatas < 60) {
951
21.0k
    MWAW_DEBUG_MSG(("MarinerWrtParser::readDocInfo: find unexpected number of data\n"));
952
21.0k
    return false;
953
21.0k
  }
954
955
26.0k
  libmwaw::DebugStream f;
956
26.0k
  f << entry.name() << ":";
957
958
26.0k
  int dim[2], margins[4]= {0,0,0,0};
959
26.0k
  unsigned char color[3];
960
26.0k
  size_t d=0;
961
2.79M
  for (int j=0; j < numDatas; j++, d++) {
962
2.77M
    MarinerWrtStruct const &dt = dataList[d];
963
2.77M
    if (!dt.isBasic()) {
964
250k
      f << "#f" << d << "=" << dt << ",";
965
250k
      static bool first=true;
966
250k
      if (first) {
967
34
        MWAW_DEBUG_MSG(("MarinerWrtParser::readDocInfo: find some struct block\n"));
968
34
        first = false;
969
34
      }
970
250k
      continue;
971
250k
    }
972
2.52M
    switch (j) {
973
25.5k
    case 0: { // 15|40
974
25.5k
      auto val=uint32_t(dt.value(0));
975
25.5k
      if (val&0x4000) {
976
2.87k
        if (zoneId==0)
977
884
          m_state->m_hasOddEvenHeaderFooter=true;
978
2.87k
        f << "hasOddEven[header/footer],";
979
2.87k
        val &= ~uint32_t(0x4000);
980
2.87k
      }
981
25.5k
      if (val&0x20000) {
982
2.41k
        if (zoneId==0 && m_state->m_zonesList.size()) {
983
40
          MWAWSection &sec=m_state->m_zonesList[0].m_section;
984
40
          sec.m_columnSeparator = MWAWBorder();
985
40
        }
986
2.41k
        f << "colSep,";
987
2.41k
        val &= ~uint32_t(0x20000);
988
2.41k
      }
989
25.5k
      if (val)
990
19.6k
        f << "f0=" << std::hex << val << std::dec << ",";
991
25.5k
      break;
992
0
    }
993
25.6k
    case 2: // small number between 108 and 297
994
50.9k
    case 3: // f3=f2-24?
995
75.8k
    case 5: // small number between -18 and 57
996
99.4k
    case 6: // f6~=f5 ?
997
123k
    case 13: // a small number 1|2|3|4|58|61|283
998
149k
    case 35: // 1|2|31|60|283
999
174k
    case 44: // 0 or 1
1000
199k
    case 46: // 0 or 1
1001
224k
    case 47: // 0 or 1
1002
250k
    case 48: // 0 or 1
1003
275k
    case 51: // always 1
1004
275k
      if (dt.value(0))
1005
220k
        f << "f" << j << "=" << dt.value(0) << ",";
1006
275k
      break;
1007
25.6k
    case 1: // 1
1008
25.6k
      if (dt.value(0)!=1)
1009
21.5k
        f << "f" << j << "=" << dt.value(0) << ",";
1010
25.6k
      break;
1011
23.7k
    case 7:
1012
24.3k
    case 8: // a dim?
1013
24.3k
      dim[0] = dim[1] = 0;
1014
24.3k
      dim[j-7]= static_cast<int>(dt.value(0));
1015
24.3k
      if (j!=8)
1016
23.7k
        dim[++j-7] = static_cast<int>(dataList[++d].value(0));
1017
24.3k
      f << "dim?=" << dim[1] << "x" << dim[0] << ",";
1018
24.3k
      break;
1019
23.5k
    case 9:
1020
24.8k
    case 10:
1021
24.9k
    case 11:
1022
25.7k
    case 12:
1023
25.7k
      margins[j-9]=static_cast<int>(dt.value(0));
1024
99.2k
      while (j<12)
1025
73.4k
        margins[++j-9]= static_cast<int>(dataList[++d].value(0));
1026
25.7k
      f << "margins=" << margins[1] << "x" << margins[0]
1027
25.7k
        << "<->"  << margins[3] << "x" << margins[2] << ",";
1028
25.7k
      break;
1029
24.3k
    case 14: // a very big number
1030
24.3k
      if (dt.value(0))
1031
18.3k
        f << "id?=" << std::hex << dt.value(0) << std::dec << ",";
1032
24.3k
      break;
1033
24.3k
    case 15: { // border type?
1034
24.3k
      long val = dt.value(0);
1035
24.3k
      if (!val) break;
1036
17.1k
      int depl = 24;
1037
17.1k
      f << "border?=[";
1038
85.5k
      for (int b = 0; b < 4; b++) {
1039
68.4k
        if ((val>>depl)&0xFF)
1040
36.2k
          f << ((val>>depl)&0xFF) << ",";
1041
32.1k
        else
1042
32.1k
          f << "_";
1043
68.4k
        depl -= 8;
1044
68.4k
      }
1045
17.1k
      f << "],";
1046
17.1k
      break;
1047
24.3k
    }
1048
24.3k
    case 16:
1049
25.7k
    case 17:
1050
25.8k
    case 18: {
1051
25.8k
      color[0]=color[1]=color[2]=0;
1052
25.8k
      color[j-16]=static_cast<unsigned char>(dt.value(0)>>8);
1053
75.8k
      while (j < 18)
1054
50.0k
        color[++j-16] = static_cast<unsigned char>(dataList[++d].value(0)>>8);
1055
25.8k
      MWAWColor col(color[0],color[1],color[2]);
1056
25.8k
      if (!col.isBlack()) f << "color=" << col << ",";
1057
25.8k
      break;
1058
25.7k
    }
1059
8.88k
    case 76: // a very big number
1060
17.7k
    case 79:
1061
17.7k
      if (dt.value(0))
1062
11.7k
        f << "f" << j << "=" << std::hex << uint32_t(dt.value(0)) << std::dec << ",";
1063
17.7k
      break;
1064
2.05M
    default:
1065
2.05M
      if (dt.value(0))
1066
1.37M
        f << "#f" << j << "=" << dt.value(0) << ",";
1067
2.05M
      break;
1068
2.52M
    }
1069
2.52M
  }
1070
26.0k
  if (zoneId==0 && margins[0] > 0 && margins[1] > 0 &&
1071
5.71k
      margins[2] > 0 && margins[3] > 0) {
1072
5.15k
    m_pageMarginsSpanSet= true;
1073
5.15k
    getPageSpan().setMarginTop(double(margins[0])/72.0);
1074
5.15k
    if (margins[2]>80)
1075
3.28k
      getPageSpan().setMarginBottom(double(margins[2]-40)/72.0);
1076
1.87k
    else
1077
1.87k
      getPageSpan().setMarginBottom(double(margins[2]/2)/72.0);
1078
5.15k
    getPageSpan().setMarginLeft(double(margins[1])/72.0);
1079
5.15k
    getPageSpan().setMarginRight(double(margins[3])/72.0);
1080
1081
5.15k
  }
1082
26.0k
  ascii().addPos(entry.begin());
1083
26.0k
  ascii().addNote(f.str().c_str());
1084
26.0k
  return true;
1085
26.0k
}
1086
bool MarinerWrtParser::readZoneb(MarinerWrtEntry const &entry, int)
1087
6.53k
{
1088
6.53k
  if (entry.length() < entry.m_N) {
1089
205
    MWAW_DEBUG_MSG(("MarinerWrtParser::readZoneb: data seems to short\n"));
1090
205
    return false;
1091
205
  }
1092
6.32k
  MWAWInputStreamPtr input = getInput();
1093
6.32k
  input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
1094
6.32k
  input->pushLimit(entry.end());
1095
6.32k
  std::vector<MarinerWrtStruct> dataList;
1096
6.32k
  decodeZone(dataList, 1+4*entry.m_N);
1097
6.32k
  input->popLimit();
1098
1099
6.32k
  if (int(dataList.size()) != 4*entry.m_N) {
1100
1.70k
    MWAW_DEBUG_MSG(("MarinerWrtParser::readZoneb: find unexpected number of data\n"));
1101
1.70k
    return false;
1102
1.70k
  }
1103
1104
4.62k
  libmwaw::DebugStream f;
1105
4.62k
  size_t d = 0;
1106
13.9k
  for (int i = 0; i < entry.m_N; i++) {
1107
9.35k
    f.str("");
1108
9.35k
    f << entry.name() << "-" << i << ":";
1109
9.35k
    ascii().addPos(dataList[d].m_filePos);
1110
1111
46.7k
    for (int j = 0; j < 4; j++) { // always 0, 0, 0, 0?
1112
37.4k
      MarinerWrtStruct const &data = dataList[d++];
1113
37.4k
      if (!data.isBasic()) {
1114
1.39k
        MWAW_DEBUG_MSG(("MarinerWrtParser::readZoneb: find unexpected dim data type\n"));
1115
1.39k
        f << "###dim" << j << "=" << data << ",";
1116
1.39k
      }
1117
36.0k
      else if (data.value(0))
1118
465
        f << "f" << j << "=" << data.value(0) << ",";
1119
37.4k
    }
1120
9.35k
    ascii().addNote(f.str().c_str());
1121
9.35k
  }
1122
4.62k
  input->seek(entry.end(), librevenge::RVNG_SEEK_SET);
1123
1124
4.62k
  return true;
1125
6.32k
}
1126
1127
bool MarinerWrtParser::readZonec(MarinerWrtEntry const &entry, int zoneId)
1128
13.3k
{
1129
13.3k
  if (entry.length() < entry.m_N) {
1130
1.55k
    MWAW_DEBUG_MSG(("MarinerWrtParser::readZonec: data seems to short\n"));
1131
1.55k
    return false;
1132
1.55k
  }
1133
11.8k
  MWAWInputStreamPtr input = getInput();
1134
11.8k
  input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
1135
11.8k
  input->pushLimit(entry.end());
1136
11.8k
  std::vector<MarinerWrtStruct> dataList;
1137
11.8k
  decodeZone(dataList, 1+9*entry.m_N);
1138
11.8k
  input->popLimit();
1139
1140
11.8k
  if (int(dataList.size()) != 9*entry.m_N) {
1141
6.74k
    MWAW_DEBUG_MSG(("MarinerWrtParser::readZonec: find unexpected number of data\n"));
1142
6.74k
    return false;
1143
6.74k
  }
1144
1145
5.07k
  libmwaw::DebugStream f;
1146
5.07k
  size_t d = 0;
1147
11.2k
  for (int i = 0; i < entry.m_N; i++) {
1148
6.13k
    f.str("");
1149
6.13k
    f << entry.name() << "-" << i << ":";
1150
6.13k
    ascii().addPos(dataList[d].m_filePos);
1151
1152
61.3k
    for (int j = 0; j < 9; j++) {
1153
55.1k
      MarinerWrtStruct const &data = dataList[d++];
1154
55.1k
      if (!data.isBasic()) {
1155
766
        MWAW_DEBUG_MSG(("MarinerWrtParser::readZonec: find unexpected dim data type\n"));
1156
766
        f << "###dim" << j << "=" << data << ",";
1157
766
      }
1158
54.4k
      else if (j==8) {
1159
6.10k
        if (!data.value(0)) {
1160
2.51k
          f << "firstPage[header/footer],";
1161
2.51k
          if (zoneId==0)
1162
2.07k
            m_state->m_firstPageFooter=true;
1163
2.51k
        }
1164
3.58k
        else if (data.value(0)!=1)
1165
566
          f << "#f8=" << "=" << data.value(0) << ",";
1166
6.10k
      }
1167
48.3k
      else if (data.value(0))
1168
25.1k
        f << "f" << j << "=" << data.value(0) << ",";
1169
55.1k
    }
1170
6.13k
    ascii().addNote(f.str().c_str());
1171
6.13k
  }
1172
5.07k
  input->seek(entry.end(), librevenge::RVNG_SEEK_SET);
1173
1174
5.07k
  return true;
1175
11.8k
}
1176
1177
bool MarinerWrtParser::readZone13(MarinerWrtEntry const &entry, int)
1178
11.0k
{
1179
11.0k
  if (entry.length() < 3) {
1180
81
    MWAW_DEBUG_MSG(("MarinerWrtParser::readZone13: data seems to short\n"));
1181
81
    return false;
1182
81
  }
1183
11.0k
  MWAWInputStreamPtr input = getInput();
1184
11.0k
  input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
1185
11.0k
  input->pushLimit(entry.end());
1186
11.0k
  std::vector<MarinerWrtStruct> dataList;
1187
11.0k
  decodeZone(dataList, 1+23);
1188
11.0k
  input->popLimit();
1189
1190
11.0k
  if (int(dataList.size()) != 23) {
1191
531
    MWAW_DEBUG_MSG(("MarinerWrtParser::readZone13: find unexpected number of data\n"));
1192
531
    return false;
1193
531
  }
1194
1195
10.4k
  libmwaw::DebugStream f;
1196
10.4k
  size_t d = 0;
1197
10.4k
  f << entry.name() << ":";
1198
10.4k
  ascii().addPos(dataList[d].m_filePos);
1199
1200
10.4k
  int val;
1201
216k
  for (int j = 0; j < 23; j++) {
1202
205k
    MarinerWrtStruct const &data = dataList[d++];
1203
205k
    if ((j!=14 && !data.isBasic()) || (j==14 && data.m_type)) {
1204
107k
      MWAW_DEBUG_MSG(("MarinerWrtParser::readZone13: find unexpected struct data type\n"));
1205
107k
      f << "#f" << j << "=" << data << ",";
1206
107k
      continue;
1207
107k
    }
1208
98.1k
    if (j < 14) {
1209
58.6k
      int const expectedValues[]= {13,10,9,31,8,12,14,28,29,30,31,0x7f,27,0};
1210
58.6k
      if (static_cast<int>(data.value(0)) != expectedValues[j])
1211
1.72k
        f << "f" << j << "=" << data.value(0) << ",";
1212
58.6k
      continue;
1213
58.6k
    }
1214
39.5k
    if (j == 14) {
1215
4.15k
      if (!data.m_pos.valid())
1216
0
        f << "#f" << j << "=" << data << ",";
1217
4.15k
      else {
1218
        /* find v_{2i}=0 and v_{2i+1}=
1219
           {301,302,422,450,454,422,421,418,302,295,290,468,469,466,467,457,448}
1220
        */
1221
4.15k
        f << "bl=[";
1222
4.15k
        input->seek(data.m_pos.begin(), librevenge::RVNG_SEEK_SET);
1223
4.15k
        auto N = int(data.m_pos.length()/2);
1224
144k
        for (int k = 0; k < N; k++) {
1225
140k
          val = static_cast<int>(input->readLong(2));
1226
140k
          if (val) f << val << ",";
1227
69.2k
          else f << "_,";
1228
140k
        }
1229
4.15k
        f << "],";
1230
4.15k
      }
1231
4.15k
      continue;
1232
4.15k
    }
1233
35.3k
    unsigned char color[3];
1234
35.3k
    MWAWColor col;
1235
35.3k
    switch (j) {
1236
10.2k
    case 15:
1237
10.2k
    case 16:
1238
10.2k
    case 17:
1239
10.2k
      color[0]=color[1]=color[2]=0xFF;
1240
10.2k
      color[j-15]=static_cast<unsigned char>(data.value(0)>>8);
1241
30.8k
      while (j < 17)
1242
20.5k
        color[++j-15] = static_cast<unsigned char>(dataList[d++].value(0)>>8);
1243
10.2k
      col = MWAWColor(color[0],color[1],color[2]);
1244
10.2k
      if (!col.isWhite())
1245
6.25k
        f << "col0=" << col << ",";
1246
10.2k
      break;
1247
4.28k
    case 19:
1248
10.3k
    case 20:
1249
10.3k
    case 21:
1250
10.3k
      color[0]=color[1]=color[2]=0xFF;
1251
10.3k
      color[j-19]=static_cast<unsigned char>(data.value(0)>>8);
1252
24.9k
      while (j < 21)
1253
14.5k
        color[++j-19] = static_cast<unsigned char>(dataList[d++].value(0)>>8);
1254
10.3k
      col = MWAWColor(color[0],color[1],color[2]);
1255
10.3k
      if (!col.isWhite())
1256
6.27k
        f << "col1=" << col << ",";
1257
10.3k
      break;
1258
14.7k
    default:
1259
14.7k
      if (data.value(0))
1260
6.32k
        f << "#f" << j << "=" << data.value(0) << ",";
1261
35.3k
    }
1262
35.3k
  }
1263
10.4k
  ascii().addNote(f.str().c_str());
1264
10.4k
  input->seek(entry.end(), librevenge::RVNG_SEEK_SET);
1265
1266
10.4k
  return true;
1267
10.4k
}
1268
1269
// --------- print info ----------
1270
1271
// read the print info xml data
1272
bool MarinerWrtParser::readCPRT(MarinerWrtEntry const &entry)
1273
3.94k
{
1274
3.94k
  if (entry.length() < 0x10) {
1275
3.23k
    MWAW_DEBUG_MSG(("MarinerWrtParser::readCPRT: data seems to short\n"));
1276
3.23k
    return false;
1277
3.23k
  }
1278
1279
704
  MWAWInputStreamPtr input = getInput();
1280
704
  input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
1281
#ifdef DEBUG_WITH_FILES
1282
  librevenge::RVNGBinaryData file;
1283
  input->readDataBlock(entry.length(), file);
1284
1285
  static int volatile cprtName = 0;
1286
  libmwaw::DebugStream f;
1287
  f << "CPRT" << ++cprtName << ".plist";
1288
  libmwaw::Debug::dumpFile(file, f.str().c_str());
1289
1290
  ascii().skipZone(entry.begin(),entry.end()-1);
1291
#endif
1292
1293
704
  input->seek(entry.end(), librevenge::RVNG_SEEK_SET);
1294
704
  return true;
1295
3.94k
}
1296
1297
// read the print info data
1298
bool MarinerWrtParser::readPrintInfo(MarinerWrtEntry const &entry)
1299
3.45k
{
1300
3.45k
  if (entry.length() < 0x77) {
1301
1.13k
    MWAW_DEBUG_MSG(("MarinerWrtParser::readPrintInfo: data seems to short\n"));
1302
1.13k
    return false;
1303
1.13k
  }
1304
1305
2.32k
  MWAWInputStreamPtr input = getInput();
1306
2.32k
  input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
1307
1308
2.32k
  libmwaw::PrinterInfo info;
1309
2.32k
  if (!info.read(input))
1310
431
    return false;
1311
1312
1.88k
  libmwaw::DebugStream f;
1313
1.88k
  f << "PrintInfo:"<< info;
1314
1.88k
  MWAWVec2i paperSize = info.paper().size();
1315
1.88k
  MWAWVec2i pageSize = info.page().size();
1316
1.88k
  if (pageSize.x() <= 0 || pageSize.y() <= 0 ||
1317
1.59k
      paperSize.x() <= 0 || paperSize.y() <= 0) return false;
1318
1319
1.46k
  if (!m_pageMarginsSpanSet) {
1320
    // define margin from print info
1321
994
    MWAWVec2i lTopMargin= -1 * info.paper().pos(0);
1322
994
    MWAWVec2i rBotMargin=info.paper().size() - info.page().size();
1323
1324
    // move margin left | top
1325
994
    int decalX = lTopMargin.x() > 14 ? lTopMargin.x()-14 : 0;
1326
994
    int decalY = lTopMargin.y() > 14 ? lTopMargin.y()-14 : 0;
1327
994
    lTopMargin -= MWAWVec2i(decalX, decalY);
1328
994
    rBotMargin += MWAWVec2i(decalX, decalY);
1329
1330
    // decrease right | bottom
1331
994
    int rightMarg = rBotMargin.x() -50;
1332
994
    if (rightMarg < 0) rightMarg=0;
1333
994
    int botMarg = rBotMargin.y() -50;
1334
994
    if (botMarg < 0) botMarg=0;
1335
1336
994
    getPageSpan().setMarginTop(lTopMargin.y()/72.0);
1337
994
    getPageSpan().setMarginBottom(botMarg/72.0);
1338
994
    getPageSpan().setMarginLeft(lTopMargin.x()/72.0);
1339
994
    getPageSpan().setMarginRight(rightMarg/72.0);
1340
994
  }
1341
1.46k
  getPageSpan().setFormLength(paperSize.y()/72.);
1342
1.46k
  getPageSpan().setFormWidth(paperSize.x()/72.);
1343
1.46k
  getPageSpan().checkMargins();
1344
1345
1.46k
  ascii().addPos(entry.begin());
1346
1.46k
  ascii().addNote(f.str().c_str());
1347
1348
1.46k
  input->seek(entry.end(), librevenge::RVNG_SEEK_SET);
1349
1.46k
  return true;
1350
1.88k
}
1351
1352
////////////////////////////////////////////////////////////
1353
// low level
1354
////////////////////////////////////////////////////////////
1355
1356
// ---- field decoder ---------
1357
bool MarinerWrtParser::readEntryHeader(MarinerWrtEntry &entry)
1358
706k
{
1359
706k
  MWAWInputStreamPtr input = getInput();
1360
706k
  long pos = input->tell();
1361
706k
  std::vector<long> dataList;
1362
706k
  if (!readNumbersString(4,dataList)||dataList.size()<5) {
1363
19.6k
    MWAW_DEBUG_MSG(("MarinerWrtParser::readEntryHeader: oops can not find header entry\n"));
1364
19.6k
    input->seek(pos, librevenge::RVNG_SEEK_SET);
1365
19.6k
    return false;
1366
19.6k
  }
1367
687k
  long length = dataList[1] >= 0 ? (dataList[1]<<16)+dataList[2] : -1;
1368
687k
  if (length < 0 || !input->checkPosition(input->tell()+length)) {
1369
6.74k
    MWAW_DEBUG_MSG(("MarinerWrtParser::readEntryHeader: the header data seems to short\n"));
1370
6.74k
    input->seek(pos, librevenge::RVNG_SEEK_SET);
1371
6.74k
    return false;
1372
6.74k
  }
1373
680k
  entry.setBegin(input->tell());
1374
680k
  entry.setLength(length);
1375
680k
  entry.m_fileType = static_cast<int>(int16_t(dataList[0]));
1376
680k
  entry.m_N = static_cast<int>(dataList[4]);
1377
680k
  entry.m_value = static_cast<int>(dataList[3]);
1378
1379
680k
  return true;
1380
687k
}
1381
1382
bool MarinerWrtParser::readNumbersString(int num, std::vector<long> &res)
1383
7.49M
{
1384
7.49M
  res.resize(0);
1385
  // first read the string
1386
7.49M
  MWAWInputStreamPtr input = getInput();
1387
7.49M
  std::string str("");
1388
40.0M
  while (!input->isEnd()) {
1389
39.9M
    auto ch = int(input->readULong(1));
1390
39.9M
    if (ch=='-' || (ch >= 'A' && ch <= 'F') || (ch >= '0' && ch <= '9')) {
1391
32.5M
      str += char(ch);
1392
32.5M
      continue;
1393
32.5M
    }
1394
7.37M
    input->seek(-1, librevenge::RVNG_SEEK_CUR);
1395
7.37M
    break;
1396
39.9M
  }
1397
7.49M
  if (!str.length()) return false;
1398
1399
  // ok we have the string, let decodes it
1400
7.41M
  size_t sz = str.length(), i = sz;
1401
7.41M
  int nBytes = 0;
1402
7.41M
  long val=0;
1403
38.8M
  while (1) {
1404
38.8M
    if (i==0) {
1405
7.31M
      if (nBytes)
1406
6.66M
        res.insert(res.begin(),val);
1407
7.31M
      break;
1408
7.31M
    }
1409
31.5M
    char c = str[--i];
1410
31.5M
    if (c=='-') {
1411
881k
      if (!nBytes) {
1412
101k
        MWAW_DEBUG_MSG(("MarinerWrtParser::readNumbersString find '-' with no val\n"));
1413
101k
        break;
1414
101k
      }
1415
779k
      res.insert(res.begin(),-val);
1416
779k
      val = 0;
1417
779k
      nBytes = 0;
1418
779k
      continue;
1419
881k
    }
1420
1421
30.6M
    if (nBytes==num) {
1422
3.11M
      res.insert(res.begin(),val);
1423
3.11M
      val = 0;
1424
3.11M
      nBytes = 0;
1425
3.11M
    }
1426
1427
30.6M
    if (c >= '0' && c <= '9')
1428
24.6M
      val += (long(c-'0')<<(4*nBytes));
1429
5.95M
    else if (c >= 'A' && c <= 'F')
1430
5.95M
      val += (long(c+10-'A')<<(4*nBytes));
1431
0
    else {
1432
0
      MWAW_DEBUG_MSG(("MarinerWrtParser::readNumbersString find odd char %x\n", static_cast<unsigned int>(c)));
1433
0
      break;
1434
0
    }
1435
30.6M
    nBytes++;
1436
30.6M
  }
1437
7.41M
  return true;
1438
7.49M
}
1439
1440
bool MarinerWrtParser::decodeZone(std::vector<MarinerWrtStruct> &dataList, long numData)
1441
750k
{
1442
750k
  dataList.clear();
1443
1444
750k
  MWAWInputStreamPtr input = getInput();
1445
750k
  long pos = input->tell();
1446
11.5M
  while (!input->isEnd()) {
1447
11.4M
    size_t numVal = dataList.size();
1448
11.4M
    if (numVal >= size_t(numData))
1449
3.52k
      break;
1450
11.4M
    MarinerWrtStruct data;
1451
11.4M
    data.m_filePos = pos;
1452
11.4M
    auto type = int(input->readULong(1));
1453
11.4M
    data.m_type = (type&3);
1454
11.4M
    if (type == 3)
1455
230k
      return true;
1456
11.1M
    if ((type & 0x3c) || (type && !(type&0x3)))
1457
287k
      break;
1458
10.8M
    if ((type>>4)==0xc) {
1459
1.90M
      if (input->isEnd()) break;
1460
1.89M
      auto num = int(input->readULong(1));
1461
1.89M
      if (!num) break;
1462
1.89M
      if (numVal==0) {
1463
60.0k
        MWAW_DEBUG_MSG(("MarinerWrtParser::decodeZone: no previous data to copy\n"));
1464
60.0k
      }
1465
1.83M
      else   // checkme
1466
1.83M
        data = dataList[numVal-1];
1467
1468
83.7M
      for (int j = 0; j < num; j++)
1469
81.8M
        dataList.push_back(data);
1470
1.89M
      pos = input->tell();
1471
1.89M
      continue;
1472
1.89M
    }
1473
8.99M
    if ((type>>4)==0x8) {
1474
2.20M
      if (numVal==0) {
1475
19.5k
        MWAW_DEBUG_MSG(("MarinerWrtParser::decodeZone: no previous data to copy(II)\n"));
1476
19.5k
        dataList.push_back(data);
1477
19.5k
      }
1478
2.18M
      else
1479
2.18M
        dataList.push_back(dataList[numVal-1]);
1480
2.20M
      pos = input->tell();
1481
2.20M
      continue;
1482
2.20M
    }
1483
6.78M
    std::vector<long> &numbers = data.m_data;
1484
6.78M
    if (!readNumbersString(data.m_type==1 ? 4: 8, numbers))
1485
71.3k
      break;
1486
6.71M
    if (type==0) {
1487
150k
      if (numbers.size() != 1 || numbers[0] < 0 || input->readULong(1) != 0x2c)
1488
4.04k
        break;
1489
146k
      data.m_pos.setBegin(input->tell());
1490
146k
      data.m_pos.setLength(numbers[0]);
1491
146k
      if (!input->checkPosition(data.m_pos.end()))
1492
1.16k
        break;
1493
144k
      input->seek(data.m_pos.end(), librevenge::RVNG_SEEK_SET);
1494
144k
      numbers.resize(0);
1495
144k
    }
1496
1497
6.71M
    dataList.push_back(data);
1498
6.71M
    pos = input->tell();
1499
6.71M
  }
1500
519k
  input->seek(pos, librevenge::RVNG_SEEK_SET);
1501
519k
  return dataList.size();
1502
750k
}
1503
1504
////////////////////////////////////////////////////////////
1505
// read the header
1506
////////////////////////////////////////////////////////////
1507
bool MarinerWrtParser::checkHeader(MWAWHeader *header, bool strict)
1508
98.1k
{
1509
98.1k
  *m_state = MarinerWrtParserInternal::State();
1510
98.1k
  MWAWInputStreamPtr input = getInput();
1511
98.1k
  if (!input || !input->hasDataFork())
1512
0
    return false;
1513
1514
98.1k
  long const headerSize=0x2e;
1515
98.1k
  if (!input->checkPosition(headerSize)) {
1516
104
    MWAW_DEBUG_MSG(("MarinerWrtParser::checkHeader: file is too short\n"));
1517
104
    return false;
1518
104
  }
1519
98.0k
  input->seek(0,librevenge::RVNG_SEEK_SET);
1520
1521
98.0k
  int actZone = -1;
1522
98.0k
  if (!readZone(actZone, true))
1523
6.13k
    return false;
1524
91.9k
  if (strict && !readZone(actZone, true))
1525
11.2k
    return false;
1526
1527
80.6k
  input->seek(0, librevenge::RVNG_SEEK_SET);
1528
80.6k
  if (header)
1529
32.3k
    header->reset(MWAWDocument::MWAW_T_MARINERWRITE, 1);
1530
1531
80.6k
  return true;
1532
91.9k
}
1533
1534
////////////////////////////////////////////////////////////
1535
// MarinerWrtEntry/MarinerWrtStruct function
1536
////////////////////////////////////////////////////////////
1537
MarinerWrtEntry::~MarinerWrtEntry()
1538
706k
{
1539
706k
}
1540
1541
std::string MarinerWrtEntry::name() const
1542
2.64M
{
1543
2.64M
  switch (m_fileType) {
1544
449k
  case -1:
1545
449k
    return "Separator";
1546
12.3k
  case -2:
1547
12.3k
    return "EndZone";
1548
111k
  case 0:
1549
111k
    return "ZoneHeader";
1550
73.2k
  case 1:
1551
73.2k
    return "TextStruct";
1552
25.7k
  case 2:
1553
25.7k
    return "TEXT";
1554
39.1k
  case 4:
1555
39.1k
    return "CharPLC";
1556
45.4k
  case 5:
1557
45.4k
    return "ParagPLC";
1558
382k
  case 6:
1559
382k
    return "Fonts";
1560
617k
  case 7:
1561
617k
    return "Paragraphs";
1562
216k
  case 8:
1563
216k
    return "FontNames";
1564
20.3k
  case 9:
1565
20.3k
    return "PaperSize";
1566
31.7k
  case 0xa:
1567
31.7k
    return "ColDim";
1568
129k
  case 0xf:
1569
129k
    return "DocInfo";
1570
156k
  case 0x14: // token, picture, ...
1571
156k
    return "Token";
1572
37.8k
  case 0x1a:
1573
37.8k
    return "StyleNames";
1574
7.17k
  case 0x1f:
1575
7.17k
    return "PrintInfo";
1576
34.3k
  case 0x24:
1577
34.3k
    return "CPRT";
1578
1.25k
  case 0x41a:
1579
1.25k
    return "DocInf2";
1580
14.3k
  case 0x420:
1581
14.3k
    return "PSFile";
1582
239k
  default:
1583
239k
    break;
1584
2.64M
  }
1585
239k
  std::stringstream s;
1586
239k
  if (m_fileType >= 0)
1587
168k
    s << "Zone" << std::hex << std::setfill('0') << std::setw(2) << m_fileType << std::dec;
1588
71.2k
  else
1589
71.2k
    s << "Zone-" << std::hex << std::setfill('0') << std::setw(2) << -m_fileType << std::dec;
1590
1591
239k
  return s.str();
1592
2.64M
}
1593
1594
long MarinerWrtStruct::value(int i) const
1595
76.4M
{
1596
76.4M
  if (i < 0 || i >= int(m_data.size())) {
1597
7.24M
    if (i) {
1598
0
      MWAW_DEBUG_MSG(("MarinerWrtStruct::value: can not find value %d\n", i));
1599
0
    }
1600
7.24M
    return 0;
1601
7.24M
  }
1602
69.1M
  return m_data[size_t(i)];
1603
76.4M
}
1604
std::ostream &operator<<(std::ostream &o, MarinerWrtStruct const &dt)
1605
0
{
1606
0
  switch (dt.m_type) {
1607
0
  case 0: // data
1608
0
    o << "sz=" << std::hex << dt.m_pos.length() << std::dec;
1609
0
    return o;
1610
0
  case 3: // end of data
1611
0
    return o;
1612
0
  case 1: // int?
1613
0
  case 2: // long?
1614
0
    break;
1615
0
  default:
1616
0
    if (dt.m_type) o << ":" << dt.m_type;
1617
0
    break;
1618
0
  }
1619
0
  size_t numData = dt.m_data.size();
1620
0
  if (!numData) {
1621
0
    o << "_";
1622
0
    return o;
1623
0
  }
1624
0
  if (numData > 1) o << "[";
1625
0
  for (size_t d = 0; d < numData; d++) {
1626
0
    long val = dt.m_data[d];
1627
0
    if (val > -100 && val < 100)
1628
0
      o << val;
1629
0
    else if (val > 0)
1630
0
      o << "0x" << std::hex << val << std::dec;
1631
0
    else
1632
0
      o << "-0x" << std::hex << -val << std::dec;
1633
0
    if (d+1 != numData) o << ",";
1634
0
  }
1635
0
  if (numData > 1) o << "]";
1636
0
  return o;
1637
0
}
1638
1639
1640
// vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: