Coverage Report

Created: 2026-06-13 06:44

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
149k
    : m_id(-1)
75
149k
    , m_fileId(0)
76
149k
    , m_type(Z_Unknown)
77
149k
    , m_endNote(false)
78
149k
    , m_height(0)
79
149k
    , m_RBpos(0,0)
80
149k
    , m_dim()
81
149k
    , m_pageDim()
82
149k
    , m_pageTextDim()
83
149k
    , m_section()
84
149k
    , m_backgroundColor(MWAWColor::white())
85
149k
    , m_extra("")
86
149k
  {
87
149k
  }
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
206k
    : m_zonesList()
177
206k
    , m_fileToZoneMap()
178
206k
    , m_actPage(0)
179
206k
    , m_numPages(0)
180
206k
    , m_firstPageFooter(false)
181
206k
    , m_hasOddEvenHeaderFooter(false)
182
206k
  {
183
206k
  }
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
2.45k
    : MWAWSubDocument(&pars, input, MWAWEntry())
203
2.45k
    , m_id(zoneId)
204
2.45k
  {
205
2.45k
  }
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
2.27k
{
230
2.27k
  if (!listener.get()) {
231
0
    MWAW_DEBUG_MSG(("MarinerWrtParserInternal::SubDocument::parse: no listener\n"));
232
0
    return;
233
0
  }
234
2.27k
  auto *parser=dynamic_cast<MarinerWrtParser *>(m_parser);
235
2.27k
  if (!parser) {
236
0
    MWAW_DEBUG_MSG(("MarinerWrtParserInternal::SubDocument::parse: no parser\n"));
237
0
    return;
238
0
  }
239
2.27k
  long pos = m_input->tell();
240
2.27k
  parser->sendText(m_id);
241
2.27k
  m_input->seek(pos, librevenge::RVNG_SEEK_SET);
242
2.27k
}
243
}
244
245
////////////////////////////////////////////////////////////
246
// constructor/destructor + basic interface ...
247
////////////////////////////////////////////////////////////
248
MarinerWrtParser::MarinerWrtParser(MWAWInputStreamPtr const &input, MWAWRSRCParserPtr const &rsrcParser, MWAWHeader *header)
249
88.6k
  : MWAWTextParser(input, rsrcParser, header)
250
88.6k
  , m_state()
251
88.6k
  , m_pageMarginsSpanSet(false)
252
88.6k
  , m_graphParser()
253
88.6k
  , m_textParser()
254
88.6k
{
255
88.6k
  init();
256
88.6k
}
257
258
MarinerWrtParser::~MarinerWrtParser()
259
88.6k
{
260
88.6k
}
261
262
void MarinerWrtParser::init()
263
88.6k
{
264
88.6k
  resetTextListener();
265
88.6k
  setAsciiName("main-1");
266
267
88.6k
  m_state.reset(new MarinerWrtParserInternal::State);
268
269
  // reduce the margin (in case, the page is not defined)
270
88.6k
  getPageSpan().setMargins(0.1);
271
272
88.6k
  m_graphParser.reset(new MarinerWrtGraph(*this));
273
88.6k
  m_textParser.reset(new MarinerWrtText(*this));
274
88.6k
}
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
6.91k
{
287
6.91k
  if (zId >= 0 && zId < int(m_state->m_zonesList.size()))
288
6.91k
    return m_state->m_zonesList[size_t(zId)].m_section;
289
0
  return MWAWSection();
290
6.91k
}
291
292
////////////////////////////////////////////////////////////
293
// new page
294
////////////////////////////////////////////////////////////
295
void MarinerWrtParser::newPage(int number)
296
45.2k
{
297
45.2k
  if (number <= m_state->m_actPage || number > m_state->m_numPages)
298
26.8k
    return;
299
300
36.8k
  while (m_state->m_actPage < number) {
301
18.4k
    m_state->m_actPage++;
302
18.4k
    if (!getTextListener() || m_state->m_actPage == 1)
303
6.91k
      continue;
304
11.4k
    getTextListener()->insertBreak(MWAWTextListener::PageBreak);
305
11.4k
  }
306
18.4k
}
307
308
////////////////////////////////////////////////////////////
309
// interface
310
////////////////////////////////////////////////////////////
311
int MarinerWrtParser::getZoneId(uint32_t fileId, bool &endNote)
312
5.34k
{
313
5.34k
  if (m_state->m_fileToZoneMap.find(fileId)==m_state->m_fileToZoneMap.end()) {
314
4.32k
    MWAW_DEBUG_MSG(("MarinerWrtParser::getZoneId: can not find zone for %x\n", fileId));
315
4.32k
    return -1;
316
4.32k
  }
317
1.01k
  int id=m_state->m_fileToZoneMap.find(fileId)->second;
318
1.01k
  endNote=false;
319
1.01k
  if (id>=0 && id < int(m_state->m_zonesList.size()))
320
1.01k
    endNote = m_state->m_zonesList[size_t(id)].m_endNote;
321
1.01k
  return id;
322
5.34k
}
323
324
void MarinerWrtParser::sendText(int zoneId)
325
7.60k
{
326
7.60k
  MWAWInputStreamPtr input = getInput();
327
7.60k
  long actPos = input->tell();
328
7.60k
  m_textParser->send(zoneId);
329
7.60k
  input->seek(actPos, librevenge::RVNG_SEEK_SET);
330
7.60k
}
331
332
float MarinerWrtParser::getPatternPercent(int id) const
333
511k
{
334
511k
  return m_graphParser->getPatternPercent(id);
335
511k
}
336
337
void MarinerWrtParser::sendToken(int zoneId, long tokenId)
338
30.2k
{
339
30.2k
  MWAWInputStreamPtr input = getInput();
340
30.2k
  long actPos = input->tell();
341
30.2k
  m_graphParser->sendToken(zoneId, tokenId);
342
30.2k
  input->seek(actPos, librevenge::RVNG_SEEK_SET);
343
30.2k
}
344
345
////////////////////////////////////////////////////////////
346
// the parser
347
////////////////////////////////////////////////////////////
348
void MarinerWrtParser::parse(librevenge::RVNGTextInterface *docInterface)
349
28.8k
{
350
28.8k
  if (!getInput().get() || !checkHeader(nullptr)) throw(libmwaw::ParseException());
351
28.8k
  bool ok = true;
352
28.8k
  try {
353
    // create the asciiFile
354
28.8k
    ascii().setStream(getInput());
355
28.8k
    ascii().open(asciiName());
356
357
28.8k
    checkHeader(nullptr);
358
28.8k
    ok = createZones();
359
28.8k
    if (ok) {
360
9.25k
      createDocument(docInterface);
361
9.25k
      m_graphParser->sendPageGraphics();
362
9.25k
      m_textParser->send(0);
363
364
#ifdef DEBUG
365
      m_textParser->flushExtra();
366
      m_graphParser->flushExtra();
367
#endif
368
9.25k
    }
369
28.8k
    ascii().reset();
370
28.8k
  }
371
28.8k
  catch (...) {
372
0
    MWAW_DEBUG_MSG(("MarinerWrtParser::parse: exception catched when parsing\n"));
373
0
    ok = false;
374
0
  }
375
376
28.8k
  resetTextListener();
377
28.8k
  if (!ok) throw(libmwaw::ParseException());
378
28.8k
}
379
380
////////////////////////////////////////////////////////////
381
// create the document
382
////////////////////////////////////////////////////////////
383
void MarinerWrtParser::createDocument(librevenge::RVNGTextInterface *documentInterface)
384
9.25k
{
385
9.25k
  if (!documentInterface) return;
386
9.25k
  if (getTextListener()) {
387
0
    MWAW_DEBUG_MSG(("MarinerWrtParser::createDocument: listener already exist\n"));
388
0
    return;
389
0
  }
390
391
  // update the page
392
9.25k
  m_state->m_actPage = 0;
393
394
9.25k
  int numPage = m_textParser->numPages();
395
9.25k
  if (m_graphParser->numPages() > numPage)
396
0
    numPage = m_graphParser->numPages();
397
9.25k
  m_state->m_numPages = numPage;
398
399
  // create the page list
400
9.25k
  MWAWPageSpan ps(getPageSpan());
401
9.25k
  if (m_state->m_zonesList.size())
402
9.25k
    ps.setBackgroundColor(m_state->m_zonesList[0].m_backgroundColor);
403
404
  // look for an header/footer
405
9.25k
  int headerId[4] = { -1, -1, -1, -1}, footerId[4] = { -1, -1, -1, -1};
406
105k
  for (size_t z = 0; z < m_state->m_zonesList.size(); z++) {
407
96.4k
    auto const &zone=m_state->m_zonesList[z];
408
96.4k
    if (zone.m_type==MarinerWrtParserInternal::Zone::Z_Header) {
409
2.15k
      if (zone.m_fileId < 4)
410
2.13k
        headerId[zone.m_fileId]=int(z);
411
2.15k
    }
412
94.2k
    else if (zone.m_type==MarinerWrtParserInternal::Zone::Z_Footer) {
413
1.66k
      if (zone.m_fileId < 4)
414
1.16k
        footerId[zone.m_fileId]=int(z);
415
1.66k
    }
416
96.4k
  }
417
9.25k
  MWAWPageSpan firstPs(ps);
418
9.25k
  if (m_state->m_firstPageFooter) {
419
2.46k
    if (headerId[3]>0) {
420
663
      MWAWHeaderFooter header(MWAWHeaderFooter::HEADER, MWAWHeaderFooter::ALL);
421
663
      header.m_subDocument.reset(new MarinerWrtParserInternal::SubDocument(*this, getInput(), int(headerId[3])));
422
663
      firstPs.setHeaderFooter(header);
423
663
    }
424
2.46k
    if (footerId[3]>0) {
425
293
      MWAWHeaderFooter footer(MWAWHeaderFooter::FOOTER, MWAWHeaderFooter::ALL);
426
293
      footer.m_subDocument.reset(new MarinerWrtParserInternal::SubDocument(*this, getInput(), int(footerId[3])));
427
293
      firstPs.setHeaderFooter(footer);
428
293
    }
429
2.46k
  }
430
9.34k
  for (int st = 0; st < 2; st++) {
431
9.29k
    MWAWHeaderFooter::Occurrence what=
432
9.29k
      !m_state->m_hasOddEvenHeaderFooter ? MWAWHeaderFooter::ALL : st==0 ? MWAWHeaderFooter::ODD : MWAWHeaderFooter::EVEN;
433
9.29k
    int which= !m_state->m_hasOddEvenHeaderFooter ? 0 : 1+st;
434
9.29k
    if (headerId[which]>0) {
435
935
      MWAWHeaderFooter header(MWAWHeaderFooter::HEADER, what);
436
935
      header.m_subDocument.reset(new MarinerWrtParserInternal::SubDocument(*this, getInput(), int(headerId[which])));
437
935
      ps.setHeaderFooter(header);
438
935
    }
439
9.29k
    if (footerId[which]>0) {
440
565
      MWAWHeaderFooter footer(MWAWHeaderFooter::FOOTER, what);
441
565
      footer.m_subDocument.reset(new MarinerWrtParserInternal::SubDocument(*this, getInput(), int(footerId[which])));
442
565
      ps.setHeaderFooter(footer);
443
565
    }
444
9.29k
    if (!m_state->m_hasOddEvenHeaderFooter)
445
9.20k
      break;
446
9.29k
  }
447
448
9.25k
  std::vector<MWAWPageSpan> pageList;
449
9.25k
  if (m_state->m_firstPageFooter) {
450
2.46k
    pageList.push_back(firstPs);
451
2.46k
    ps.setPageSpan(m_state->m_numPages);
452
2.46k
  }
453
6.78k
  else
454
6.78k
    ps.setPageSpan(m_state->m_numPages+1);
455
9.25k
  if (ps.getPageSpan())
456
9.25k
    pageList.push_back(ps);
457
  //
458
9.25k
  MWAWTextListenerPtr listen(new MWAWTextListener(*getParserState(), pageList, documentInterface));
459
9.25k
  setTextListener(listen);
460
9.25k
  listen->startDocument();
461
9.25k
}
462
463
464
////////////////////////////////////////////////////////////
465
//
466
// Intermediate level
467
//
468
////////////////////////////////////////////////////////////
469
470
// ------ read the different zones ---------
471
bool MarinerWrtParser::createZones()
472
28.8k
{
473
28.8k
  MWAWInputStreamPtr input = getInput();
474
28.8k
  long pos = input->tell();
475
28.8k
  int actZone=-1;
476
754k
  while (readZone(actZone))
477
725k
    pos = input->tell();
478
28.8k
  ascii().addPos(pos);
479
28.8k
  ascii().addNote("Entries(Loose)");
480
28.8k
  return m_state->m_zonesList.size();
481
28.8k
}
482
483
bool MarinerWrtParser::readZone(int &actZone, bool onlyTest)
484
911k
{
485
911k
  MWAWInputStreamPtr input = getInput();
486
911k
  if (input->isEnd())
487
3.78k
    return false;
488
908k
  long pos = input->tell();
489
908k
  MarinerWrtEntry zone;
490
908k
  if (!readEntryHeader(zone)) {
491
31.7k
    input->seek(pos, librevenge::RVNG_SEEK_SET);
492
31.7k
    return false;
493
31.7k
  }
494
495
876k
  libmwaw::DebugStream f;
496
876k
  f << "Entries(" << zone.name() << "):" << zone;
497
498
876k
  bool done = false;
499
876k
  switch (zone.m_fileType) {
500
260k
  case -1: // separator
501
264k
  case -2: // last file
502
264k
    done = readSeparator(zone);
503
264k
    if (onlyTest)
504
91.6k
      break;
505
173k
    actZone++;
506
173k
    break;
507
77.1k
  case 0:
508
77.1k
    done = readZoneHeader(zone, actZone, onlyTest);
509
77.1k
    break;
510
51.7k
  case 1:
511
51.7k
    done = m_textParser->readTextStruct(zone, actZone);
512
51.7k
    break;
513
15.0k
  case 2:
514
15.0k
    done = m_textParser->readZone(zone, actZone);
515
15.0k
    break;
516
16.8k
  case 4:
517
40.8k
  case 5:
518
40.8k
    done = m_textParser->readPLCZone(zone, actZone);
519
40.8k
    break;
520
23.1k
  case 6:
521
23.1k
    done = m_textParser->readFonts(zone, actZone);
522
23.1k
    break;
523
73.5k
  case 7:
524
73.5k
    done = m_textParser->readRulers(zone, actZone);
525
73.5k
    break;
526
57.5k
  case 8:
527
57.5k
    done = m_textParser->readFontNames(zone, actZone);
528
57.5k
    break;
529
8.73k
  case 9: // zone size
530
8.73k
    done = readZoneDim(zone, actZone);
531
8.73k
    break;
532
14.2k
  case 0xa: // zone size with margins removal
533
14.2k
    done = readZoneDim(zone, actZone);
534
14.2k
    break;
535
10.0k
  case 0xb: // border dim?
536
10.0k
    done = readZoneb(zone, actZone);
537
10.0k
    break;
538
17.6k
  case 0xc:
539
17.6k
    done = readZonec(zone, actZone);
540
17.6k
    break;
541
61.0k
  case 0xf:
542
61.0k
    done = readDocInfo(zone, actZone);
543
61.0k
    break;
544
15.7k
  case 0x13:
545
15.7k
    done = readZone13(zone, actZone);
546
15.7k
    break;
547
72.5k
  case 0x14:
548
72.5k
    done = m_graphParser->readToken(zone, actZone);
549
72.5k
    break;
550
15.9k
  case 0x1a:
551
15.9k
    done = m_textParser->readStyleNames(zone, actZone);
552
15.9k
    break;
553
4.41k
  case 0x1f:
554
4.41k
    done = readPrintInfo(zone);
555
4.41k
    break;
556
5.12k
  case 0x24:
557
5.12k
    done = readCPRT(zone);
558
5.12k
    break;
559
  /* 0x41a: docInfo */
560
8.04k
  case 0x420:
561
8.04k
    done = m_graphParser->readPostscript(zone, actZone);
562
8.04k
    break;
563
39.0k
  default:
564
39.0k
    break;
565
876k
  }
566
876k
  if (done) {
567
699k
    ascii().addPos(pos);
568
699k
    ascii().addNote(f.str().c_str());
569
699k
    input->seek(zone.end(), librevenge::RVNG_SEEK_SET);
570
699k
    return true;
571
699k
  }
572
176k
  if (onlyTest)
573
13.3k
    return false;
574
162k
  input->seek(zone.begin(), librevenge::RVNG_SEEK_SET);
575
162k
  input->pushLimit(zone.end());
576
162k
  std::vector<MarinerWrtStruct> dataList;
577
162k
  decodeZone(dataList);
578
162k
  input->popLimit();
579
580
162k
  size_t numData = dataList.size();
581
162k
  f << "numData=" << numData << ",";
582
162k
  ascii().addPos(pos);
583
162k
  ascii().addNote(f.str().c_str());
584
585
162k
  int numDataByField = zone.m_fileType==1 ? 22 : 10;
586
9.43M
  for (size_t d = 0; d < numData; d++) {
587
9.27M
    MarinerWrtStruct const &dt = dataList[d];
588
9.27M
    if ((int(d)%numDataByField)==0) {
589
1.01M
      if (d)
590
888k
        ascii().addNote(f.str().c_str());
591
1.01M
      f.str("");
592
1.01M
      f << zone.name() << "-" << d << ":";
593
1.01M
      ascii().addPos(dt.m_filePos);
594
1.01M
    }
595
9.27M
    f << dt << ",";
596
9.27M
  }
597
162k
  if (numData)
598
130k
    ascii().addNote(f.str().c_str());
599
600
162k
  if (input->tell() != zone.end()) {
601
100k
    f.str("");
602
100k
    if (input->tell() == zone.end()-1)
603
6.79k
      f << "_";
604
93.2k
    else
605
93.2k
      f << zone.name() << ":###";
606
100k
    ascii().addPos(input->tell());
607
100k
    ascii().addNote(f.str().c_str());
608
100k
  }
609
162k
  input->seek(zone.end(), librevenge::RVNG_SEEK_SET);
610
162k
  return true;
611
176k
}
612
613
// --------- zone separator ----------
614
615
// read the zone separator
616
bool MarinerWrtParser::readSeparator(MarinerWrtEntry const &entry)
617
264k
{
618
264k
  if (entry.length() < 0x3) {
619
4.33k
    MWAW_DEBUG_MSG(("MarinerWrtParser::readSeparator: data seems to short\n"));
620
4.33k
    return false;
621
4.33k
  }
622
260k
  MWAWInputStreamPtr input = getInput();
623
260k
  input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
624
260k
  input->pushLimit(entry.end());
625
260k
  std::vector<MarinerWrtStruct> dataList;
626
260k
  decodeZone(dataList);
627
260k
  input->popLimit();
628
629
260k
  if (dataList.size() != 1) {
630
4.92k
    MWAW_DEBUG_MSG(("MarinerWrtParser::readSeparator: can find my data\n"));
631
4.92k
    return false;
632
4.92k
  }
633
634
255k
  MarinerWrtStruct const &data = dataList[0]; // always 0x77aa
635
255k
  libmwaw::DebugStream f;
636
255k
  f << entry.name() << "[data]:";
637
255k
  if (data.m_data.size() != 1 || data.m_data[0] != 0x77aa)
638
173k
    f << "#" << data;
639
255k
  ascii().addPos(entry.begin());
640
255k
  ascii().addNote(f.str().c_str());
641
642
255k
  return true;
643
260k
}
644
645
bool MarinerWrtParser::readZoneHeader(MarinerWrtEntry const &entry, int actId, bool onlyTest)
646
77.1k
{
647
77.1k
  if (entry.length() < 3) {
648
2.89k
    MWAW_DEBUG_MSG(("MarinerWrtParser::readZoneHeader: data seems to short\n"));
649
2.89k
    return false;
650
2.89k
  }
651
74.2k
  MWAWInputStreamPtr input = getInput();
652
74.2k
  input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
653
74.2k
  input->pushLimit(entry.end());
654
74.2k
  std::vector<MarinerWrtStruct> dataList;
655
74.2k
  decodeZone(dataList);
656
74.2k
  input->popLimit();
657
658
74.2k
  size_t numData = dataList.size();
659
74.2k
  if (numData < 47) {
660
11.3k
    MWAW_DEBUG_MSG(("MarinerWrtParser::readZoneHeader: find unexpected number of data\n"));
661
11.3k
    return false;
662
11.3k
  }
663
62.8k
  if (onlyTest)
664
9.51k
    return true;
665
53.3k
  size_t d = 0;
666
53.3k
  long val;
667
53.3k
  libmwaw::DebugStream f;
668
53.3k
  MarinerWrtParserInternal::Zone zone;
669
2.17M
  for (int j = 0; j < 47; j++) {
670
2.11M
    MarinerWrtStruct const &data = dataList[d++];
671
2.11M
    if (!data.isBasic()) {
672
226k
      f << "###f" << j << "=" << data << ",";
673
226k
      continue;
674
226k
    }
675
1.89M
    long sel[4]= {0,0,0,0};
676
1.89M
    int dim[4]= {0,0,0,0};
677
1.89M
    unsigned char color[3];
678
1.89M
    switch (j) {
679
44.9k
    case 0: // version?
680
44.9k
      val = data.value(0);
681
44.9k
      if ((val>>16)==1) // checkme v1.6 -> 1[29] while v3.5->1[33]
682
11.4k
        setVersion((val&0xFFFF)<30 ? 1 : 2);
683
44.9k
      f << "vers?=" << (val>>16) << "[" << (val&0xFFFF) << "],";
684
44.9k
      break;
685
48.6k
    case 1:
686
48.6k
      val = data.value(0);
687
48.6k
      if (val>>16) // 0 or 1000
688
11.7k
        f << "f1[high]=" << std::hex << (val>>16) << std::dec << ",";
689
48.6k
      if ((val&0xFFFF)!=1)
690
32.3k
        f << "f1[low]=" << (val& 0xFFFF) << ",";
691
48.6k
      break;
692
48.6k
    case 2: { // find 8[01]0[0145]8120 or a0808120
693
48.6k
      uint32_t high = uint32_t(data.value(0))>>16;
694
      // high&4: no odd/even header/footer ?
695
48.6k
      if (high) f << "fl2[high]=" << std::hex << high << std::dec << ",";
696
48.6k
      uint32_t low = uint32_t(data.value(0))&0xFFFF;
697
48.6k
      if (low) f << "fl2[low]=" << std::hex << low << std::dec << ",";
698
48.6k
      break;
699
0
    }
700
48.6k
    case 3: { // 80000[01] or 800000[01]
701
48.6k
      auto value=uint32_t(data.value(0));
702
48.6k
      if (value&0x2000000) {
703
1.88k
        zone.m_endNote=true;
704
1.88k
        value &= ~uint32_t(0x2000000);
705
1.88k
      }
706
      // value&1: firstPage[header/footer] ?
707
48.6k
      if (value)
708
43.2k
        f << "fl3=" << std::hex << value << std::dec << ",";
709
48.6k
      break;
710
0
    }
711
48.6k
    case 4: {
712
48.6k
      auto v = uint32_t(data.value(0));
713
48.6k
      switch (v>>28) {
714
42.1k
      case 0: // main
715
42.1k
        zone.m_type = MarinerWrtParserInternal::Zone::Z_Main;
716
42.1k
        break;
717
2.16k
      case 0xc:
718
2.16k
        zone.m_type = MarinerWrtParserInternal::Zone::Z_Header;
719
2.16k
        break;
720
1.73k
      case 0xd:
721
1.73k
        zone.m_type = MarinerWrtParserInternal::Zone::Z_Footer;
722
1.73k
        break;
723
2.01k
      case 0xe:
724
2.01k
        zone.m_type = MarinerWrtParserInternal::Zone::Z_Footnote;
725
2.01k
        break;
726
579
      default:
727
579
        f << "#type=" << (v>>28) << ",";
728
579
        break;
729
48.6k
      }
730
48.6k
      zone.m_fileId=(v&0xFFFFFFF);
731
48.6k
      m_state->m_fileToZoneMap[v]=actId;
732
48.6k
      break;
733
48.6k
    }
734
48.5k
    case 9: // real bottom margin
735
48.5k
      if (data.value(0))
736
43.1k
        f << "y[bottom+footer?]=" << data.value(0) << ",";
737
48.5k
      break;
738
48.5k
    case 10:
739
48.5k
      zone.m_height = data.value(0);
740
48.5k
      break;
741
48.5k
    case 13: // right margin
742
97.0k
    case 14: // bottom margin
743
97.0k
      zone.m_RBpos[j-13] = data.value(0);
744
97.0k
      break;
745
48.5k
    case 21:
746
48.5k
      if (data.value(0))
747
38.0k
        f << "h[act]=" << data.value(0) << ",";
748
48.5k
      break;
749
48.6k
    case 5: // 0|14|90
750
97.2k
    case 6: // 0|11-14
751
145k
    case 15: // -2: main?|-1
752
194k
    case 16: // -2: main?|-1
753
242k
    case 25: // 0|43
754
291k
    case 41: // 0|5|26
755
291k
      if (data.value(0))
756
233k
        f << "f" << j << "=" << data.value(0) << ",";
757
291k
      break;
758
48.6k
    case 7: // two units ?
759
48.6k
      if (data.value(0) != 0x480048)
760
37.5k
        f << "f" << j << "=" << std::hex << data.value(0) << std::dec << ",";
761
48.6k
      break;
762
48.5k
    case 8: // always -2?
763
48.5k
      if (data.value(0) != -2)
764
37.4k
        f << "#f" << j << "=" << data.value(0) << ",";
765
48.5k
      break;
766
48.5k
    case 12: // always 16
767
48.5k
      if (data.value(0) != 16)
768
36.4k
        f << "#f" << j << "=" << data.value(0) << ",";
769
48.5k
      break;
770
48.5k
    case 17:
771
48.5k
    case 18:
772
48.5k
    case 19:
773
48.5k
    case 20:
774
48.5k
      sel[j-17] = data.value(0);
775
194k
      while (j<20)
776
145k
        sel[++j-17] = dataList[d++].value(0);
777
48.5k
      if (sel[0]||sel[1])
778
37.9k
        f << "sel0=" << std::hex << sel[0] << "x" << sel[1] << std::dec << ",";
779
48.5k
      if (sel[2]||sel[3])
780
38.0k
        f << "sel1=" << std::hex << sel[2] << "x" << sel[3] << std::dec << ",";
781
48.5k
      break;
782
48.5k
    case 28: // left margin
783
48.5k
    case 29: // top margin
784
48.5k
    case 30:
785
48.6k
    case 31:
786
48.6k
      dim[j-28] = static_cast<int>(data.value(0));
787
194k
      while (j<31)
788
145k
        dim[++j-28] = static_cast<int>(dataList[d++].value(0));
789
48.6k
      zone.m_dim = MWAWBox2l(MWAWVec2l(dim[1],dim[0]), MWAWVec2l(dim[3],dim[2]));
790
48.6k
      break;
791
48.5k
    case 32:
792
48.6k
    case 33:
793
50.8k
    case 34: { // 35,36,37: front color?
794
50.8k
      color[0]=color[1]=color[2]=0xFF;
795
50.8k
      color[j-32]=static_cast<unsigned char>(data.value(0)>>8);
796
147k
      while (j < 34)
797
97.1k
        color[++j-32] = static_cast<unsigned char>(dataList[d++].value(0)>>8);
798
50.8k
      zone.m_backgroundColor = MWAWColor(color[0],color[1],color[2]);
799
50.8k
      break;
800
48.6k
    }
801
48.5k
    case 38:
802
48.5k
      if (data.value(0)!=1)
803
33.0k
        f << "#f" << j << "=" << data.value(0) << ",";
804
48.5k
      break;
805
48.6k
    case 39:
806
48.6k
      if (data.value(0) && data.value(0)!=0x4d4d4242) // MMBB: creator
807
31.9k
        f << "#creator=" << std::hex << uint32_t(data.value(0)) << std::dec << ",";
808
48.6k
      break;
809
48.6k
    case 40: // normally 0 or pretty small, but can also be very very big
810
48.6k
      if (data.value(0))
811
39.6k
        f << "f" << j << "=" << std::hex << data.value(0) << std::dec << ",";
812
48.6k
      break;
813
48.6k
    case 42:
814
48.6k
      if (data.value(0)!=43)
815
38.0k
        f << "#f" << j << "=" << data.value(0) << ",";
816
48.6k
      break;
817
48.6k
    case 44:
818
48.6k
      if (data.value(0))
819
42.9k
        f << "sel[pt]=" << std::hex << data.value(0) << std::dec << ",";
820
48.6k
      break;
821
48.6k
    case 45:
822
48.6k
      if (data.value(0)!=72)
823
38.0k
        f << "#f" << j << "=" << data.value(0) << ",";
824
48.6k
      break;
825
534k
    default:
826
534k
      if (data.value(0))
827
353k
        f << "#f" << j << "=" << data.value(0) << ",";
828
534k
      break;
829
1.89M
    }
830
1.89M
  }
831
6.77M
  while (d < numData) {
832
6.72M
    f << "#f" << d << "=" << dataList[d] << ",";
833
6.72M
    d++;
834
6.72M
  }
835
53.3k
  zone.m_extra = f.str();
836
53.3k
  if (actId < 0) {
837
4.71k
    MWAW_DEBUG_MSG(("MarinerWrtParser::readZoneHeader: called with negative id\n"));
838
4.71k
  }
839
48.6k
  else {
840
48.6k
    if (actId >= int(m_state->m_zonesList.size()))
841
37.8k
      m_state->m_zonesList.resize(size_t(actId)+1);
842
48.6k
    m_state->m_zonesList[size_t(actId)] = zone;
843
48.6k
  }
844
53.3k
  f.str("");
845
53.3k
  f << entry.name() << ":" << zone;
846
847
53.3k
  ascii().addPos(entry.begin());
848
53.3k
  ascii().addNote(f.str().c_str());
849
53.3k
  return true;
850
53.3k
}
851
852
bool MarinerWrtParser::readZoneDim(MarinerWrtEntry const &entry, int zoneId)
853
23.0k
{
854
23.0k
  if (entry.length() < entry.m_N) {
855
577
    MWAW_DEBUG_MSG(("MarinerWrtParser::readZoneDim: data seems to short\n"));
856
577
    return false;
857
577
  }
858
22.4k
  MWAWInputStreamPtr input = getInput();
859
22.4k
  input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
860
22.4k
  input->pushLimit(entry.end());
861
22.4k
  std::vector<MarinerWrtStruct> dataList;
862
22.4k
  decodeZone(dataList, 1+4*entry.m_N);
863
22.4k
  input->popLimit();
864
865
22.4k
  if (int(dataList.size()) != 4*entry.m_N) {
866
1.83k
    MWAW_DEBUG_MSG(("MarinerWrtParser::readZoneDim: find unexpected number of data\n"));
867
1.83k
    return false;
868
1.83k
  }
869
870
20.6k
  libmwaw::DebugStream f;
871
20.6k
  size_t d = 0;
872
20.6k
  std::vector<int> colPos;
873
61.6k
  for (int i = 0; i < entry.m_N; i++) {
874
41.0k
    f.str("");
875
41.0k
    f << entry.name() << "-" << i << ":";
876
41.0k
    ascii().addPos(dataList[d].m_filePos);
877
878
41.0k
    int dim[4] = { 0, 0, 0, 0 };
879
205k
    for (int j = 0; j < 4; j++) {
880
164k
      MarinerWrtStruct const &data = dataList[d++];
881
164k
      if (!data.isBasic()) {
882
5.65k
        MWAW_DEBUG_MSG(("MarinerWrtParser::readZoneDim: find unexpected dim data type\n"));
883
5.65k
        f << "###dim" << j << "=" << data << ",";
884
5.65k
      }
885
158k
      else
886
158k
        dim[j] = static_cast<int>(data.value(0));
887
164k
    }
888
    // checkme
889
41.0k
    MWAWBox2i dimension(MWAWVec2i(dim[1],dim[0]), MWAWVec2i(dim[3],dim[2]));
890
41.0k
    f << "pos=" << dimension << ",";
891
41.0k
    bool dimOk=dim[0] >= 0 && dim[0] < dim[2] && dim[1] >= 0 && dim[1] < dim[3];
892
41.0k
    if (i==0 && dimOk) {
893
14.4k
      if (zoneId < 0 || zoneId >= int(m_state->m_zonesList.size())) {
894
1.45k
        MWAW_DEBUG_MSG(("MarinerWrtParser::readZoneDim: can not find the zone storage\n"));
895
1.45k
      }
896
12.9k
      else if (entry.m_fileType == 9)
897
6.54k
        m_state->m_zonesList[size_t(zoneId)].m_pageDim = dimension;
898
6.42k
      else if (entry.m_fileType == 0xa)
899
6.42k
        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
14.4k
    }
904
26.6k
    else if (i && dimOk) {
905
16.7k
      if (!colPos.size() || colPos.back() <= dim[1]) {
906
16.7k
        colPos.push_back(dim[1]);
907
16.7k
        colPos.push_back(dim[3]);
908
16.7k
      }
909
66
      else
910
66
        f << "###";
911
16.7k
    }
912
41.0k
    ascii().addNote(f.str().c_str());
913
41.0k
  }
914
20.6k
  if (entry.m_fileType == 0xa && zoneId >= 0 &&
915
11.3k
      zoneId < int(m_state->m_zonesList.size()) &&
916
6.47k
      colPos.size() > 2 && int(colPos.size())==2*(entry.m_N-1)) {
917
1.60k
    auto numCols=size_t(entry.m_N-1);
918
1.60k
    MWAWSection &sec=m_state->m_zonesList[size_t(zoneId)].m_section;
919
1.60k
    sec.m_columns.resize(numCols);
920
4.81k
    for (size_t c=0; c < numCols; c++) {
921
3.21k
      MWAWSection::Column &col = sec.m_columns[c];
922
3.21k
      int prevPos= c==0 ? colPos[0] : (colPos[2*c-1]+colPos[2*c])/2;
923
3.21k
      int nextPos= c+1==numCols ? colPos[2*c+1] :
924
3.21k
                   (colPos[2*c+1]+colPos[2*c+2])/2;
925
3.21k
      col.m_width=double(nextPos-prevPos);
926
3.21k
      col.m_widthUnit=librevenge::RVNG_POINT;
927
3.21k
      col.m_margins[libmwaw::Left]=double(colPos[2*c]-prevPos)/72.;
928
3.21k
      col.m_margins[libmwaw::Right]=double(nextPos-colPos[2*c+1])/72.;
929
3.21k
    }
930
1.60k
  }
931
20.6k
  input->seek(entry.end(), librevenge::RVNG_SEEK_SET);
932
933
20.6k
  return true;
934
22.4k
}
935
936
bool MarinerWrtParser::readDocInfo(MarinerWrtEntry const &entry, int zoneId)
937
61.0k
{
938
61.0k
  if (entry.length() < 3) {
939
4.74k
    MWAW_DEBUG_MSG(("MarinerWrtParser::readDocInfo: data seems to short\n"));
940
4.74k
    return false;
941
4.74k
  }
942
56.2k
  MWAWInputStreamPtr input = getInput();
943
56.2k
  input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
944
56.2k
  input->pushLimit(entry.end());
945
56.2k
  std::vector<MarinerWrtStruct> dataList;
946
56.2k
  decodeZone(dataList);
947
56.2k
  input->popLimit();
948
949
56.2k
  auto numDatas = int(dataList.size());
950
56.2k
  if (numDatas < 60) {
951
24.4k
    MWAW_DEBUG_MSG(("MarinerWrtParser::readDocInfo: find unexpected number of data\n"));
952
24.4k
    return false;
953
24.4k
  }
954
955
31.8k
  libmwaw::DebugStream f;
956
31.8k
  f << entry.name() << ":";
957
958
31.8k
  int dim[2], margins[4]= {0,0,0,0};
959
31.8k
  unsigned char color[3];
960
31.8k
  size_t d=0;
961
3.42M
  for (int j=0; j < numDatas; j++, d++) {
962
3.39M
    MarinerWrtStruct const &dt = dataList[d];
963
3.39M
    if (!dt.isBasic()) {
964
287k
      f << "#f" << d << "=" << dt << ",";
965
287k
      static bool first=true;
966
287k
      if (first) {
967
36
        MWAW_DEBUG_MSG(("MarinerWrtParser::readDocInfo: find some struct block\n"));
968
36
        first = false;
969
36
      }
970
287k
      continue;
971
287k
    }
972
3.10M
    switch (j) {
973
31.2k
    case 0: { // 15|40
974
31.2k
      auto val=uint32_t(dt.value(0));
975
31.2k
      if (val&0x4000) {
976
3.50k
        if (zoneId==0)
977
955
          m_state->m_hasOddEvenHeaderFooter=true;
978
3.50k
        f << "hasOddEven[header/footer],";
979
3.50k
        val &= ~uint32_t(0x4000);
980
3.50k
      }
981
31.2k
      if (val&0x20000) {
982
2.72k
        if (zoneId==0 && m_state->m_zonesList.size()) {
983
43
          MWAWSection &sec=m_state->m_zonesList[0].m_section;
984
43
          sec.m_columnSeparator = MWAWBorder();
985
43
        }
986
2.72k
        f << "colSep,";
987
2.72k
        val &= ~uint32_t(0x20000);
988
2.72k
      }
989
31.2k
      if (val)
990
24.4k
        f << "f0=" << std::hex << val << std::dec << ",";
991
31.2k
      break;
992
0
    }
993
31.3k
    case 2: // small number between 108 and 297
994
62.1k
    case 3: // f3=f2-24?
995
92.6k
    case 5: // small number between -18 and 57
996
121k
    case 6: // f6~=f5 ?
997
151k
    case 13: // a small number 1|2|3|4|58|61|283
998
182k
    case 35: // 1|2|31|60|283
999
213k
    case 44: // 0 or 1
1000
244k
    case 46: // 0 or 1
1001
275k
    case 47: // 0 or 1
1002
305k
    case 48: // 0 or 1
1003
336k
    case 51: // always 1
1004
336k
      if (dt.value(0))
1005
260k
        f << "f" << j << "=" << dt.value(0) << ",";
1006
336k
      break;
1007
31.3k
    case 1: // 1
1008
31.3k
      if (dt.value(0)!=1)
1009
24.0k
        f << "f" << j << "=" << dt.value(0) << ",";
1010
31.3k
      break;
1011
28.9k
    case 7:
1012
29.6k
    case 8: // a dim?
1013
29.6k
      dim[0] = dim[1] = 0;
1014
29.6k
      dim[j-7]= static_cast<int>(dt.value(0));
1015
29.6k
      if (j!=8)
1016
28.9k
        dim[++j-7] = static_cast<int>(dataList[++d].value(0));
1017
29.6k
      f << "dim?=" << dim[1] << "x" << dim[0] << ",";
1018
29.6k
      break;
1019
28.6k
    case 9:
1020
30.4k
    case 10:
1021
30.6k
    case 11:
1022
31.4k
    case 12:
1023
31.4k
      margins[j-9]=static_cast<int>(dt.value(0));
1024
121k
      while (j<12)
1025
89.7k
        margins[++j-9]= static_cast<int>(dataList[++d].value(0));
1026
31.4k
      f << "margins=" << margins[1] << "x" << margins[0]
1027
31.4k
        << "<->"  << margins[3] << "x" << margins[2] << ",";
1028
31.4k
      break;
1029
29.6k
    case 14: // a very big number
1030
29.6k
      if (dt.value(0))
1031
21.5k
        f << "id?=" << std::hex << dt.value(0) << std::dec << ",";
1032
29.6k
      break;
1033
29.6k
    case 15: { // border type?
1034
29.6k
      long val = dt.value(0);
1035
29.6k
      if (!val) break;
1036
19.0k
      int depl = 24;
1037
19.0k
      f << "border?=[";
1038
95.1k
      for (int b = 0; b < 4; b++) {
1039
76.0k
        if ((val>>depl)&0xFF)
1040
40.3k
          f << ((val>>depl)&0xFF) << ",";
1041
35.7k
        else
1042
35.7k
          f << "_";
1043
76.0k
        depl -= 8;
1044
76.0k
      }
1045
19.0k
      f << "],";
1046
19.0k
      break;
1047
29.6k
    }
1048
29.6k
    case 16:
1049
31.4k
    case 17:
1050
31.5k
    case 18: {
1051
31.5k
      color[0]=color[1]=color[2]=0;
1052
31.5k
      color[j-16]=static_cast<unsigned char>(dt.value(0)>>8);
1053
92.5k
      while (j < 18)
1054
61.0k
        color[++j-16] = static_cast<unsigned char>(dataList[++d].value(0)>>8);
1055
31.5k
      MWAWColor col(color[0],color[1],color[2]);
1056
31.5k
      if (!col.isBlack()) f << "color=" << col << ",";
1057
31.5k
      break;
1058
31.4k
    }
1059
12.7k
    case 76: // a very big number
1060
25.4k
    case 79:
1061
25.4k
      if (dt.value(0))
1062
16.5k
        f << "f" << j << "=" << std::hex << uint32_t(dt.value(0)) << std::dec << ",";
1063
25.4k
      break;
1064
2.52M
    default:
1065
2.52M
      if (dt.value(0))
1066
1.56M
        f << "#f" << j << "=" << dt.value(0) << ",";
1067
2.52M
      break;
1068
3.10M
    }
1069
3.10M
  }
1070
31.8k
  if (zoneId==0 && margins[0] > 0 && margins[1] > 0 &&
1071
7.46k
      margins[2] > 0 && margins[3] > 0) {
1072
6.84k
    m_pageMarginsSpanSet= true;
1073
6.84k
    getPageSpan().setMarginTop(double(margins[0])/72.0);
1074
6.84k
    if (margins[2]>80)
1075
3.94k
      getPageSpan().setMarginBottom(double(margins[2]-40)/72.0);
1076
2.89k
    else
1077
2.89k
      getPageSpan().setMarginBottom(double(margins[2]/2)/72.0);
1078
6.84k
    getPageSpan().setMarginLeft(double(margins[1])/72.0);
1079
6.84k
    getPageSpan().setMarginRight(double(margins[3])/72.0);
1080
1081
6.84k
  }
1082
31.8k
  ascii().addPos(entry.begin());
1083
31.8k
  ascii().addNote(f.str().c_str());
1084
31.8k
  return true;
1085
31.8k
}
1086
bool MarinerWrtParser::readZoneb(MarinerWrtEntry const &entry, int)
1087
10.0k
{
1088
10.0k
  if (entry.length() < entry.m_N) {
1089
225
    MWAW_DEBUG_MSG(("MarinerWrtParser::readZoneb: data seems to short\n"));
1090
225
    return false;
1091
225
  }
1092
9.82k
  MWAWInputStreamPtr input = getInput();
1093
9.82k
  input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
1094
9.82k
  input->pushLimit(entry.end());
1095
9.82k
  std::vector<MarinerWrtStruct> dataList;
1096
9.82k
  decodeZone(dataList, 1+4*entry.m_N);
1097
9.82k
  input->popLimit();
1098
1099
9.82k
  if (int(dataList.size()) != 4*entry.m_N) {
1100
1.81k
    MWAW_DEBUG_MSG(("MarinerWrtParser::readZoneb: find unexpected number of data\n"));
1101
1.81k
    return false;
1102
1.81k
  }
1103
1104
8.01k
  libmwaw::DebugStream f;
1105
8.01k
  size_t d = 0;
1106
24.4k
  for (int i = 0; i < entry.m_N; i++) {
1107
16.3k
    f.str("");
1108
16.3k
    f << entry.name() << "-" << i << ":";
1109
16.3k
    ascii().addPos(dataList[d].m_filePos);
1110
1111
81.9k
    for (int j = 0; j < 4; j++) { // always 0, 0, 0, 0?
1112
65.5k
      MarinerWrtStruct const &data = dataList[d++];
1113
65.5k
      if (!data.isBasic()) {
1114
2.45k
        MWAW_DEBUG_MSG(("MarinerWrtParser::readZoneb: find unexpected dim data type\n"));
1115
2.45k
        f << "###dim" << j << "=" << data << ",";
1116
2.45k
      }
1117
63.0k
      else if (data.value(0))
1118
599
        f << "f" << j << "=" << data.value(0) << ",";
1119
65.5k
    }
1120
16.3k
    ascii().addNote(f.str().c_str());
1121
16.3k
  }
1122
8.01k
  input->seek(entry.end(), librevenge::RVNG_SEEK_SET);
1123
1124
8.01k
  return true;
1125
9.82k
}
1126
1127
bool MarinerWrtParser::readZonec(MarinerWrtEntry const &entry, int zoneId)
1128
17.6k
{
1129
17.6k
  if (entry.length() < entry.m_N) {
1130
1.74k
    MWAW_DEBUG_MSG(("MarinerWrtParser::readZonec: data seems to short\n"));
1131
1.74k
    return false;
1132
1.74k
  }
1133
15.9k
  MWAWInputStreamPtr input = getInput();
1134
15.9k
  input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
1135
15.9k
  input->pushLimit(entry.end());
1136
15.9k
  std::vector<MarinerWrtStruct> dataList;
1137
15.9k
  decodeZone(dataList, 1+9*entry.m_N);
1138
15.9k
  input->popLimit();
1139
1140
15.9k
  if (int(dataList.size()) != 9*entry.m_N) {
1141
7.37k
    MWAW_DEBUG_MSG(("MarinerWrtParser::readZonec: find unexpected number of data\n"));
1142
7.37k
    return false;
1143
7.37k
  }
1144
1145
8.54k
  libmwaw::DebugStream f;
1146
8.54k
  size_t d = 0;
1147
18.3k
  for (int i = 0; i < entry.m_N; i++) {
1148
9.82k
    f.str("");
1149
9.82k
    f << entry.name() << "-" << i << ":";
1150
9.82k
    ascii().addPos(dataList[d].m_filePos);
1151
1152
98.2k
    for (int j = 0; j < 9; j++) {
1153
88.4k
      MarinerWrtStruct const &data = dataList[d++];
1154
88.4k
      if (!data.isBasic()) {
1155
977
        MWAW_DEBUG_MSG(("MarinerWrtParser::readZonec: find unexpected dim data type\n"));
1156
977
        f << "###dim" << j << "=" << data << ",";
1157
977
      }
1158
87.4k
      else if (j==8) {
1159
9.77k
        if (!data.value(0)) {
1160
4.12k
          f << "firstPage[header/footer],";
1161
4.12k
          if (zoneId==0)
1162
3.53k
            m_state->m_firstPageFooter=true;
1163
4.12k
        }
1164
5.65k
        else if (data.value(0)!=1)
1165
714
          f << "#f8=" << "=" << data.value(0) << ",";
1166
9.77k
      }
1167
77.6k
      else if (data.value(0))
1168
43.2k
        f << "f" << j << "=" << data.value(0) << ",";
1169
88.4k
    }
1170
9.82k
    ascii().addNote(f.str().c_str());
1171
9.82k
  }
1172
8.54k
  input->seek(entry.end(), librevenge::RVNG_SEEK_SET);
1173
1174
8.54k
  return true;
1175
15.9k
}
1176
1177
bool MarinerWrtParser::readZone13(MarinerWrtEntry const &entry, int)
1178
15.7k
{
1179
15.7k
  if (entry.length() < 3) {
1180
88
    MWAW_DEBUG_MSG(("MarinerWrtParser::readZone13: data seems to short\n"));
1181
88
    return false;
1182
88
  }
1183
15.6k
  MWAWInputStreamPtr input = getInput();
1184
15.6k
  input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
1185
15.6k
  input->pushLimit(entry.end());
1186
15.6k
  std::vector<MarinerWrtStruct> dataList;
1187
15.6k
  decodeZone(dataList, 1+23);
1188
15.6k
  input->popLimit();
1189
1190
15.6k
  if (int(dataList.size()) != 23) {
1191
594
    MWAW_DEBUG_MSG(("MarinerWrtParser::readZone13: find unexpected number of data\n"));
1192
594
    return false;
1193
594
  }
1194
1195
15.0k
  libmwaw::DebugStream f;
1196
15.0k
  size_t d = 0;
1197
15.0k
  f << entry.name() << ":";
1198
15.0k
  ascii().addPos(dataList[d].m_filePos);
1199
1200
15.0k
  int val;
1201
309k
  for (int j = 0; j < 23; j++) {
1202
294k
    MarinerWrtStruct const &data = dataList[d++];
1203
294k
    if ((j!=14 && !data.isBasic()) || (j==14 && data.m_type)) {
1204
129k
      MWAW_DEBUG_MSG(("MarinerWrtParser::readZone13: find unexpected struct data type\n"));
1205
129k
      f << "#f" << j << "=" << data << ",";
1206
129k
      continue;
1207
129k
    }
1208
164k
    if (j < 14) {
1209
104k
      int const expectedValues[]= {13,10,9,31,8,12,14,28,29,30,31,0x7f,27,0};
1210
104k
      if (static_cast<int>(data.value(0)) != expectedValues[j])
1211
2.30k
        f << "f" << j << "=" << data.value(0) << ",";
1212
104k
      continue;
1213
104k
    }
1214
59.8k
    if (j == 14) {
1215
7.42k
      if (!data.m_pos.valid())
1216
0
        f << "#f" << j << "=" << data << ",";
1217
7.42k
      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
7.42k
        f << "bl=[";
1222
7.42k
        input->seek(data.m_pos.begin(), librevenge::RVNG_SEEK_SET);
1223
7.42k
        auto N = int(data.m_pos.length()/2);
1224
258k
        for (int k = 0; k < N; k++) {
1225
251k
          val = static_cast<int>(input->readLong(2));
1226
251k
          if (val) f << val << ",";
1227
124k
          else f << "_,";
1228
251k
        }
1229
7.42k
        f << "],";
1230
7.42k
      }
1231
7.42k
      continue;
1232
7.42k
    }
1233
52.3k
    unsigned char color[3];
1234
52.3k
    MWAWColor col;
1235
52.3k
    switch (j) {
1236
14.7k
    case 15:
1237
14.8k
    case 16:
1238
14.8k
    case 17:
1239
14.8k
      color[0]=color[1]=color[2]=0xFF;
1240
14.8k
      color[j-15]=static_cast<unsigned char>(data.value(0)>>8);
1241
44.4k
      while (j < 17)
1242
29.6k
        color[++j-15] = static_cast<unsigned char>(dataList[d++].value(0)>>8);
1243
14.8k
      col = MWAWColor(color[0],color[1],color[2]);
1244
14.8k
      if (!col.isWhite())
1245
7.58k
        f << "col0=" << col << ",";
1246
14.8k
      break;
1247
7.58k
    case 19:
1248
14.8k
    case 20:
1249
14.9k
    case 21:
1250
14.9k
      color[0]=color[1]=color[2]=0xFF;
1251
14.9k
      color[j-19]=static_cast<unsigned char>(data.value(0)>>8);
1252
37.3k
      while (j < 21)
1253
22.4k
        color[++j-19] = static_cast<unsigned char>(dataList[d++].value(0)>>8);
1254
14.9k
      col = MWAWColor(color[0],color[1],color[2]);
1255
14.9k
      if (!col.isWhite())
1256
7.60k
        f << "col1=" << col << ",";
1257
14.9k
      break;
1258
22.5k
    default:
1259
22.5k
      if (data.value(0))
1260
7.66k
        f << "#f" << j << "=" << data.value(0) << ",";
1261
52.3k
    }
1262
52.3k
  }
1263
15.0k
  ascii().addNote(f.str().c_str());
1264
15.0k
  input->seek(entry.end(), librevenge::RVNG_SEEK_SET);
1265
1266
15.0k
  return true;
1267
15.0k
}
1268
1269
// --------- print info ----------
1270
1271
// read the print info xml data
1272
bool MarinerWrtParser::readCPRT(MarinerWrtEntry const &entry)
1273
5.12k
{
1274
5.12k
  if (entry.length() < 0x10) {
1275
3.84k
    MWAW_DEBUG_MSG(("MarinerWrtParser::readCPRT: data seems to short\n"));
1276
3.84k
    return false;
1277
3.84k
  }
1278
1279
1.28k
  MWAWInputStreamPtr input = getInput();
1280
1.28k
  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
1.28k
  input->seek(entry.end(), librevenge::RVNG_SEEK_SET);
1294
1.28k
  return true;
1295
5.12k
}
1296
1297
// read the print info data
1298
bool MarinerWrtParser::readPrintInfo(MarinerWrtEntry const &entry)
1299
4.41k
{
1300
4.41k
  if (entry.length() < 0x77) {
1301
1.19k
    MWAW_DEBUG_MSG(("MarinerWrtParser::readPrintInfo: data seems to short\n"));
1302
1.19k
    return false;
1303
1.19k
  }
1304
1305
3.22k
  MWAWInputStreamPtr input = getInput();
1306
3.22k
  input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
1307
1308
3.22k
  libmwaw::PrinterInfo info;
1309
3.22k
  if (!info.read(input))
1310
454
    return false;
1311
1312
2.76k
  libmwaw::DebugStream f;
1313
2.76k
  f << "PrintInfo:"<< info;
1314
2.76k
  MWAWVec2i paperSize = info.paper().size();
1315
2.76k
  MWAWVec2i pageSize = info.page().size();
1316
2.76k
  if (pageSize.x() <= 0 || pageSize.y() <= 0 ||
1317
2.44k
      paperSize.x() <= 0 || paperSize.y() <= 0) return false;
1318
1319
2.30k
  if (!m_pageMarginsSpanSet) {
1320
    // define margin from print info
1321
1.50k
    MWAWVec2i lTopMargin= -1 * info.paper().pos(0);
1322
1.50k
    MWAWVec2i rBotMargin=info.paper().size() - info.page().size();
1323
1324
    // move margin left | top
1325
1.50k
    int decalX = lTopMargin.x() > 14 ? lTopMargin.x()-14 : 0;
1326
1.50k
    int decalY = lTopMargin.y() > 14 ? lTopMargin.y()-14 : 0;
1327
1.50k
    lTopMargin -= MWAWVec2i(decalX, decalY);
1328
1.50k
    rBotMargin += MWAWVec2i(decalX, decalY);
1329
1330
    // decrease right | bottom
1331
1.50k
    int rightMarg = rBotMargin.x() -50;
1332
1.50k
    if (rightMarg < 0) rightMarg=0;
1333
1.50k
    int botMarg = rBotMargin.y() -50;
1334
1.50k
    if (botMarg < 0) botMarg=0;
1335
1336
1.50k
    getPageSpan().setMarginTop(lTopMargin.y()/72.0);
1337
1.50k
    getPageSpan().setMarginBottom(botMarg/72.0);
1338
1.50k
    getPageSpan().setMarginLeft(lTopMargin.x()/72.0);
1339
1.50k
    getPageSpan().setMarginRight(rightMarg/72.0);
1340
1.50k
  }
1341
2.30k
  getPageSpan().setFormLength(paperSize.y()/72.);
1342
2.30k
  getPageSpan().setFormWidth(paperSize.x()/72.);
1343
2.30k
  getPageSpan().checkMargins();
1344
1345
2.30k
  ascii().addPos(entry.begin());
1346
2.30k
  ascii().addNote(f.str().c_str());
1347
1348
2.30k
  input->seek(entry.end(), librevenge::RVNG_SEEK_SET);
1349
2.30k
  return true;
1350
2.76k
}
1351
1352
////////////////////////////////////////////////////////////
1353
// low level
1354
////////////////////////////////////////////////////////////
1355
1356
// ---- field decoder ---------
1357
bool MarinerWrtParser::readEntryHeader(MarinerWrtEntry &entry)
1358
908k
{
1359
908k
  MWAWInputStreamPtr input = getInput();
1360
908k
  long pos = input->tell();
1361
908k
  std::vector<long> dataList;
1362
908k
  if (!readNumbersString(4,dataList)||dataList.size()<5) {
1363
24.0k
    MWAW_DEBUG_MSG(("MarinerWrtParser::readEntryHeader: oops can not find header entry\n"));
1364
24.0k
    input->seek(pos, librevenge::RVNG_SEEK_SET);
1365
24.0k
    return false;
1366
24.0k
  }
1367
884k
  long length = dataList[1] >= 0 ? (dataList[1]<<16)+dataList[2] : -1;
1368
884k
  if (length < 0 || !input->checkPosition(input->tell()+length)) {
1369
7.68k
    MWAW_DEBUG_MSG(("MarinerWrtParser::readEntryHeader: the header data seems to short\n"));
1370
7.68k
    input->seek(pos, librevenge::RVNG_SEEK_SET);
1371
7.68k
    return false;
1372
7.68k
  }
1373
876k
  entry.setBegin(input->tell());
1374
876k
  entry.setLength(length);
1375
876k
  entry.m_fileType = static_cast<int>(int16_t(dataList[0]));
1376
876k
  entry.m_N = static_cast<int>(dataList[4]);
1377
876k
  entry.m_value = static_cast<int>(dataList[3]);
1378
1379
876k
  return true;
1380
884k
}
1381
1382
bool MarinerWrtParser::readNumbersString(int num, std::vector<long> &res)
1383
12.1M
{
1384
12.1M
  res.resize(0);
1385
  // first read the string
1386
12.1M
  MWAWInputStreamPtr input = getInput();
1387
12.1M
  std::string str("");
1388
59.6M
  while (!input->isEnd()) {
1389
59.5M
    auto ch = int(input->readULong(1));
1390
59.5M
    if (ch=='-' || (ch >= 'A' && ch <= 'F') || (ch >= '0' && ch <= '9')) {
1391
47.5M
      str += char(ch);
1392
47.5M
      continue;
1393
47.5M
    }
1394
11.9M
    input->seek(-1, librevenge::RVNG_SEEK_CUR);
1395
11.9M
    break;
1396
59.5M
  }
1397
12.1M
  if (!str.length()) return false;
1398
1399
  // ok we have the string, let decodes it
1400
12.0M
  size_t sz = str.length(), i = sz;
1401
12.0M
  int nBytes = 0;
1402
12.0M
  long val=0;
1403
58.1M
  while (1) {
1404
58.1M
    if (i==0) {
1405
11.8M
      if (nBytes)
1406
10.7M
        res.insert(res.begin(),val);
1407
11.8M
      break;
1408
11.8M
    }
1409
46.2M
    char c = str[--i];
1410
46.2M
    if (c=='-') {
1411
1.37M
      if (!nBytes) {
1412
127k
        MWAW_DEBUG_MSG(("MarinerWrtParser::readNumbersString find '-' with no val\n"));
1413
127k
        break;
1414
127k
      }
1415
1.24M
      res.insert(res.begin(), -val);
1416
1.24M
      val = 0;
1417
1.24M
      nBytes = 0;
1418
1.24M
      continue;
1419
1.37M
    }
1420
1421
44.8M
    if (nBytes==num) {
1422
3.98M
      res.insert(res.begin(),val);
1423
3.98M
      val = 0;
1424
3.98M
      nBytes = 0;
1425
3.98M
    }
1426
1427
44.8M
    if (c >= '0' && c <= '9')
1428
35.9M
      val += (long(c-'0')<<(4*nBytes));
1429
8.96M
    else if (c >= 'A' && c <= 'F')
1430
8.96M
      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
44.8M
    nBytes++;
1436
44.8M
  }
1437
12.0M
  return true;
1438
12.1M
}
1439
1440
bool MarinerWrtParser::decodeZone(std::vector<MarinerWrtStruct> &dataList, long numData)
1441
968k
{
1442
968k
  dataList.clear();
1443
1444
968k
  MWAWInputStreamPtr input = getInput();
1445
968k
  long pos = input->tell();
1446
18.9M
  while (!input->isEnd()) {
1447
18.8M
    size_t numVal = dataList.size();
1448
18.8M
    if (numVal >= size_t(numData))
1449
4.23k
      break;
1450
18.7M
    MarinerWrtStruct data;
1451
18.7M
    data.m_filePos = pos;
1452
18.7M
    auto type = int(input->readULong(1));
1453
18.7M
    data.m_type = (type&3);
1454
18.7M
    if (type == 3)
1455
329k
      return true;
1456
18.4M
    if ((type & 0x3c) || (type && !(type&0x3)))
1457
362k
      break;
1458
18.1M
    if ((type>>4)==0xc) {
1459
3.06M
      if (input->isEnd()) break;
1460
3.06M
      auto num = int(input->readULong(1));
1461
3.06M
      if (!num) break;
1462
3.06M
      if (numVal==0) {
1463
76.3k
        MWAW_DEBUG_MSG(("MarinerWrtParser::decodeZone: no previous data to copy\n"));
1464
76.3k
      }
1465
2.99M
      else   // checkme
1466
2.99M
        data = dataList[numVal-1];
1467
1468
106M
      for (int j = 0; j < num; j++)
1469
103M
        dataList.push_back(data);
1470
3.06M
      pos = input->tell();
1471
3.06M
      continue;
1472
3.06M
    }
1473
15.0M
    if ((type>>4)==0x8) {
1474
3.83M
      if (numVal==0) {
1475
21.6k
        MWAW_DEBUG_MSG(("MarinerWrtParser::decodeZone: no previous data to copy(II)\n"));
1476
21.6k
        dataList.push_back(data);
1477
21.6k
      }
1478
3.81M
      else
1479
3.81M
        dataList.push_back(dataList[numVal-1]);
1480
3.83M
      pos = input->tell();
1481
3.83M
      continue;
1482
3.83M
    }
1483
11.2M
    std::vector<long> &numbers = data.m_data;
1484
11.2M
    if (!readNumbersString(data.m_type==1 ? 4: 8, numbers))
1485
88.1k
      break;
1486
11.1M
    if (type==0) {
1487
266k
      if (numbers.size() != 1 || numbers[0] < 0 || input->readULong(1) != 0x2c)
1488
4.86k
        break;
1489
261k
      data.m_pos.setBegin(input->tell());
1490
261k
      data.m_pos.setLength(numbers[0]);
1491
261k
      if (!input->checkPosition(data.m_pos.end()))
1492
1.60k
        break;
1493
259k
      input->seek(data.m_pos.end(), librevenge::RVNG_SEEK_SET);
1494
259k
      numbers.resize(0);
1495
259k
    }
1496
1497
11.1M
    dataList.push_back(data);
1498
11.1M
    pos = input->tell();
1499
11.1M
  }
1500
639k
  input->seek(pos, librevenge::RVNG_SEEK_SET);
1501
639k
  return dataList.size();
1502
968k
}
1503
1504
////////////////////////////////////////////////////////////
1505
// read the header
1506
////////////////////////////////////////////////////////////
1507
bool MarinerWrtParser::checkHeader(MWAWHeader *header, bool strict)
1508
117k
{
1509
117k
  *m_state = MarinerWrtParserInternal::State();
1510
117k
  MWAWInputStreamPtr input = getInput();
1511
117k
  if (!input || !input->hasDataFork())
1512
2
    return false;
1513
1514
117k
  long const headerSize=0x2e;
1515
117k
  if (!input->checkPosition(headerSize)) {
1516
205
    MWAW_DEBUG_MSG(("MarinerWrtParser::checkHeader: file is too short\n"));
1517
205
    return false;
1518
205
  }
1519
117k
  input->seek(0,librevenge::RVNG_SEEK_SET);
1520
1521
117k
  int actZone = -1;
1522
117k
  if (!readZone(actZone, true))
1523
6.94k
    return false;
1524
110k
  if (strict && !readZone(actZone, true))
1525
13.1k
    return false;
1526
1527
97.1k
  input->seek(0, librevenge::RVNG_SEEK_SET);
1528
97.1k
  if (header)
1529
39.4k
    header->reset(MWAWDocument::MWAW_T_MARINERWRITE, 1);
1530
1531
97.1k
  return true;
1532
110k
}
1533
1534
////////////////////////////////////////////////////////////
1535
// MarinerWrtEntry/MarinerWrtStruct function
1536
////////////////////////////////////////////////////////////
1537
MarinerWrtEntry::~MarinerWrtEntry()
1538
908k
{
1539
908k
}
1540
1541
std::string MarinerWrtEntry::name() const
1542
3.59M
{
1543
3.59M
  switch (m_fileType) {
1544
569k
  case -1:
1545
569k
    return "Separator";
1546
13.3k
  case -2:
1547
13.3k
    return "EndZone";
1548
145k
  case 0:
1549
145k
    return "ZoneHeader";
1550
129k
  case 1:
1551
129k
    return "TextStruct";
1552
36.1k
  case 2:
1553
36.1k
    return "TEXT";
1554
61.2k
  case 4:
1555
61.2k
    return "CharPLC";
1556
56.6k
  case 5:
1557
56.6k
    return "ParagPLC";
1558
616k
  case 6:
1559
616k
    return "Fonts";
1560
802k
  case 7:
1561
802k
    return "Paragraphs";
1562
246k
  case 8:
1563
246k
    return "FontNames";
1564
31.5k
  case 9:
1565
31.5k
    return "PaperSize";
1566
45.0k
  case 0xa:
1567
45.0k
    return "ColDim";
1568
148k
  case 0xf:
1569
148k
    return "DocInfo";
1570
225k
  case 0x14: // token, picture, ...
1571
225k
    return "Token";
1572
58.3k
  case 0x1a:
1573
58.3k
    return "StyleNames";
1574
8.64k
  case 0x1f:
1575
8.64k
    return "PrintInfo";
1576
41.3k
  case 0x24:
1577
41.3k
    return "CPRT";
1578
2.13k
  case 0x41a:
1579
2.13k
    return "DocInf2";
1580
16.1k
  case 0x420:
1581
16.1k
    return "PSFile";
1582
338k
  default:
1583
338k
    break;
1584
3.59M
  }
1585
338k
  std::stringstream s;
1586
338k
  if (m_fileType >= 0)
1587
256k
    s << "Zone" << std::hex << std::setfill('0') << std::setw(2) << m_fileType << std::dec;
1588
82.2k
  else
1589
82.2k
    s << "Zone-" << std::hex << std::setfill('0') << std::setw(2) << -m_fileType << std::dec;
1590
1591
338k
  return s.str();
1592
3.59M
}
1593
1594
long MarinerWrtStruct::value(int i) const
1595
98.4M
{
1596
98.4M
  if (i < 0 || i >= int(m_data.size())) {
1597
8.97M
    if (i) {
1598
0
      MWAW_DEBUG_MSG(("MarinerWrtStruct::value: can not find value %d\n", i));
1599
0
    }
1600
8.97M
    return 0;
1601
8.97M
  }
1602
89.4M
  return m_data[size_t(i)];
1603
98.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: