Coverage Report

Created: 2026-09-06 07:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libmwaw/src/lib/MoreParser.cxx
Line
Count
Source
1
/* -*- Mode: C++; c-default-style: "k&r"; indent-tabs-mode: nil; tab-width: 2; c-basic-offset: 2 -*- */
2
3
/* libmwaw
4
* Version: MPL 2.0 / LGPLv2+
5
*
6
* The contents of this file are subject to the Mozilla Public License Version
7
* 2.0 (the "License"); you may not use this file except in compliance with
8
* the License or as specified alternatively below. You may obtain a copy of
9
* the License at http://www.mozilla.org/MPL/
10
*
11
* Software distributed under the License is distributed on an "AS IS" basis,
12
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13
* for the specific language governing rights and limitations under the
14
* License.
15
*
16
* Major Contributor(s):
17
* Copyright (C) 2002 William Lachance (wrlach@gmail.com)
18
* Copyright (C) 2002,2004 Marc Maurer (uwog@uwog.net)
19
* Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba@bluewin.ch)
20
* Copyright (C) 2006, 2007 Andrew Ziem
21
* Copyright (C) 2011, 2012 Alonso Laurent (alonso@loria.fr)
22
*
23
*
24
* All Rights Reserved.
25
*
26
* For minor contributions see the git repository.
27
*
28
* Alternatively, the contents of this file may be used under the terms of
29
* the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"),
30
* in which case the provisions of the LGPLv2+ are applicable
31
* instead of those above.
32
*/
33
34
#include <iomanip>
35
#include <iostream>
36
#include <limits>
37
#include <map>
38
#include <set>
39
#include <sstream>
40
41
#include <librevenge/librevenge.h>
42
43
#include "MWAWTextListener.hxx"
44
#include "MWAWFontConverter.hxx"
45
#include "MWAWHeader.hxx"
46
#include "MWAWParagraph.hxx"
47
#include "MWAWPictData.hxx"
48
#include "MWAWPosition.hxx"
49
#include "MWAWPrinter.hxx"
50
#include "MWAWRSRCParser.hxx"
51
#include "MWAWSubDocument.hxx"
52
53
#include "MoreText.hxx"
54
55
#include "MoreParser.hxx"
56
57
/** Internal: the structures of a MoreParser */
58
namespace MoreParserInternal
59
{
60
////////////////////////////////////////
61
//! Internal: the state of a MoreParser
62
struct State {
63
  //! constructor
64
  State()
65
196k
    : m_typeEntryMap()
66
196k
    , m_backgroundColor(MWAWColor::white())
67
196k
    , m_colorList()
68
196k
    , m_actPage(0)
69
196k
    , m_numPages(0)
70
196k
  {
71
196k
  }
72
  //! set the default color map
73
  void setDefaultColorList(int version);
74
75
  //! a map type -> entry
76
  std::multimap<std::string, MWAWEntry> m_typeEntryMap;
77
  //! the organization back page color
78
  MWAWColor m_backgroundColor;
79
  //! a list colorId -> color
80
  std::vector<MWAWColor> m_colorList;
81
  int m_actPage /** the actual page */, m_numPages /** the number of page of the final document */;
82
};
83
84
void State::setDefaultColorList(int version)
85
0
{
86
0
  if (m_colorList.size()) return;
87
0
  if (version==3) {
88
0
    uint32_t const defCol[32] = {
89
0
      0x000000,0x333333,0x555555,0x7f7f7f,0x999999,0xbbbbbb,0xdddddd,0xffffff,
90
0
      0xfcf305,0xf20884,0xdd0806,0x02abea,0x008011,0x0000d4,0x7f007f,0x7f3f00,
91
0
      0xffff80,0xff80ff,0xff8080,0x80ffff,0x80ff80,0x8080ff,0x008080,0x006699,
92
0
      0xffcccc,0xcccccc,0xcc9999,0xcc9966,0xcc6633,0xcccc99,0x999966,0x666633
93
0
    };
94
0
    m_colorList.resize(32);
95
0
    for (size_t i = 0; i < 32; i++)
96
0
      m_colorList[i] = defCol[i];
97
0
    return;
98
0
  }
99
0
}
100
101
////////////////////////////////////////
102
//! Internal: the subdocument of a MoreParser
103
class SubDocument final : public MWAWSubDocument
104
{
105
public:
106
  SubDocument(MoreParser &pars, MWAWInputStreamPtr const &input)
107
    : MWAWSubDocument(&pars, input, MWAWEntry())
108
0
  {
109
0
  }
110
111
  //! destructor
112
0
  ~SubDocument() final {}
113
114
  //! operator!=
115
  bool operator!=(MWAWSubDocument const &doc) const final
116
0
  {
117
0
    if (MWAWSubDocument::operator!=(doc)) return true;
118
0
    auto const *sDoc = dynamic_cast<SubDocument const *>(&doc);
119
0
    if (!sDoc) return true;
120
0
    return false;
121
0
  }
122
123
  //! the parser function
124
  void parse(MWAWListenerPtr &listener, libmwaw::SubDocumentType type) final;
125
126
};
127
128
void SubDocument::parse(MWAWListenerPtr &listener, libmwaw::SubDocumentType /*type*/)
129
0
{
130
0
  if (!listener.get()) {
131
0
    MWAW_DEBUG_MSG(("MoreParserInternal::SubDocument::parse: no listener\n"));
132
0
    return;
133
0
  }
134
0
  MWAW_DEBUG_MSG(("MoreParserInternal::SubDocument::parse: not implemented\n"));
135
  //static_cast<MoreParser *>(m_parser)->sendHeaderFooter();
136
0
}
137
}
138
139
140
////////////////////////////////////////////////////////////
141
// constructor/destructor, ...
142
////////////////////////////////////////////////////////////
143
MoreParser::MoreParser(MWAWInputStreamPtr const &input, MWAWRSRCParserPtr const &rsrcParser, MWAWHeader *header)
144
83.9k
  : MWAWTextParser(input, rsrcParser, header)
145
83.9k
  , m_state()
146
83.9k
  , m_textParser()
147
83.9k
{
148
83.9k
  init();
149
83.9k
}
150
151
MoreParser::~MoreParser()
152
83.9k
{
153
83.9k
}
154
155
void MoreParser::init()
156
83.9k
{
157
83.9k
  resetTextListener();
158
83.9k
  setAsciiName("main-1");
159
160
83.9k
  m_state.reset(new MoreParserInternal::State);
161
162
  // reduce the margin (in case, the page is not defined)
163
83.9k
  getPageSpan().setMargins(0.1);
164
165
83.9k
  m_textParser.reset(new MoreText(*this));
166
83.9k
}
167
168
MWAWInputStreamPtr MoreParser::rsrcInput()
169
0
{
170
0
  return getRSRCParser()->getInput();
171
0
}
172
173
libmwaw::DebugFile &MoreParser::rsrcAscii()
174
0
{
175
0
  return getRSRCParser()->ascii();
176
0
}
177
178
////////////////////////////////////////////////////////////
179
// position and height
180
////////////////////////////////////////////////////////////
181
MWAWVec2f MoreParser::getPageLeftTop() const
182
0
{
183
0
  return MWAWVec2f(float(getPageSpan().getMarginLeft()),
184
0
                   float(getPageSpan().getMarginTop()));
185
0
}
186
187
bool MoreParser::checkAndStore(MWAWEntry const &entry)
188
327k
{
189
327k
  if (!entry.valid() || entry.begin() < 0x80 || !getInput()->checkPosition(entry.end()))
190
206k
    return false;
191
120k
  if (entry.type().empty()) {
192
0
    MWAW_DEBUG_MSG(("MoreParser::checkAndStore: entry type is not set\n"));
193
0
    return false;
194
0
  }
195
196
120k
  m_state->m_typeEntryMap.insert
197
120k
  (std::multimap<std::string, MWAWEntry>::value_type(entry.type(),entry));
198
120k
  return true;
199
120k
}
200
201
bool MoreParser::checkAndFindSize(MWAWEntry &entry)
202
16.3M
{
203
16.3M
  MWAWInputStreamPtr &input= getInput();
204
16.3M
  if (entry.begin()<0 || !input->checkPosition(entry.begin()+4))
205
10.8M
    return false;
206
5.52M
  long actPos=input->tell();
207
5.52M
  input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
208
5.52M
  entry.setLength(4+long(input->readULong(4)));
209
5.52M
  input->seek(actPos,librevenge::RVNG_SEEK_SET);
210
5.52M
  return input->checkPosition(entry.end());
211
16.3M
}
212
213
////////////////////////////////////////////////////////////
214
// interface with the text parser
215
////////////////////////////////////////////////////////////
216
217
////////////////////////////////////////////////////////////
218
// new page
219
////////////////////////////////////////////////////////////
220
void MoreParser::newPage(int number)
221
0
{
222
0
  if (number <= m_state->m_actPage || number > m_state->m_numPages)
223
0
    return;
224
225
0
  while (m_state->m_actPage < number) {
226
0
    m_state->m_actPage++;
227
0
    if (!getTextListener() || m_state->m_actPage == 1)
228
0
      continue;
229
0
    getTextListener()->insertBreak(MWAWTextListener::PageBreak);
230
0
  }
231
0
}
232
233
bool MoreParser::getColor(int id, MWAWColor &col) const
234
0
{
235
0
  auto numColor = static_cast<int>(m_state->m_colorList.size());
236
0
  if (!numColor) {
237
0
    m_state->setDefaultColorList(version());
238
0
    numColor = int(m_state->m_colorList.size());
239
0
  }
240
0
  if (id < 0 || id >= numColor)
241
0
    return false;
242
0
  col = m_state->m_colorList[size_t(id)];
243
0
  return true;
244
0
}
245
246
////////////////////////////////////////////////////////////
247
// the parser
248
////////////////////////////////////////////////////////////
249
void MoreParser::parse(librevenge::RVNGTextInterface *docInterface)
250
28.8k
{
251
28.8k
  if (!getInput().get() || !checkHeader(nullptr))  throw(libmwaw::ParseException());
252
28.8k
  bool ok = false;
253
28.8k
  try {
254
    // create the asciiFile
255
28.8k
    ascii().setStream(getInput());
256
28.8k
    ascii().open(asciiName());
257
258
28.8k
    checkHeader(nullptr);
259
28.8k
    ok = createZones();
260
28.8k
    if (ok) {
261
27.3k
      createDocument(docInterface);
262
27.3k
      m_textParser->sendMainText();
263
27.3k
    }
264
28.8k
    ascii().reset();
265
28.8k
  }
266
28.8k
  catch (...) {
267
0
    MWAW_DEBUG_MSG(("MoreParser::parse: exception catched when parsing\n"));
268
0
    ok = false;
269
0
  }
270
271
28.8k
  resetTextListener();
272
28.8k
  if (!ok) throw(libmwaw::ParseException());
273
28.8k
}
274
275
////////////////////////////////////////////////////////////
276
// create the document
277
////////////////////////////////////////////////////////////
278
void MoreParser::createDocument(librevenge::RVNGTextInterface *documentInterface)
279
27.3k
{
280
27.3k
  if (!documentInterface) return;
281
27.3k
  if (getTextListener()) {
282
0
    MWAW_DEBUG_MSG(("MoreParser::createDocument: listener already exist\n"));
283
0
    return;
284
0
  }
285
286
  // update the page
287
27.3k
  m_state->m_actPage = 0;
288
289
  // create the page list
290
27.3k
  int numPages = 1;
291
27.3k
  if (m_textParser->numPages() > numPages)
292
0
    numPages = m_textParser->numPages();
293
27.3k
  m_state->m_numPages = numPages;
294
295
27.3k
  MWAWPageSpan ps(getPageSpan());
296
27.3k
  ps.setPageSpan(m_state->m_numPages+1);
297
27.3k
  ps.setBackgroundColor(m_state->m_backgroundColor);
298
27.3k
  MWAWSubDocumentPtr doc=m_textParser->getHeaderFooter(true);
299
27.3k
  if (doc) {
300
255
    MWAWHeaderFooter header(MWAWHeaderFooter::HEADER, MWAWHeaderFooter::ALL);
301
255
    header.m_subDocument=doc;
302
255
    ps.setHeaderFooter(header);
303
255
  }
304
27.3k
  doc=m_textParser->getHeaderFooter(false);
305
27.3k
  if (doc) {
306
177
    MWAWHeaderFooter header(MWAWHeaderFooter::FOOTER, MWAWHeaderFooter::ALL);
307
177
    header.m_subDocument=doc;
308
177
    ps.setHeaderFooter(header);
309
177
  }
310
311
27.3k
  std::vector<MWAWPageSpan> pageList(1,ps);
312
27.3k
  MWAWTextListenerPtr listen(new MWAWTextListener(*getParserState(), pageList, documentInterface));
313
27.3k
  setTextListener(listen);
314
27.3k
  listen->startDocument();
315
27.3k
}
316
317
////////////////////////////////////////////////////////////
318
//
319
// Intermediate level
320
//
321
////////////////////////////////////////////////////////////
322
bool MoreParser::createZones()
323
28.8k
{
324
28.8k
  int vers=version();
325
28.8k
  if (vers<2) {
326
0
    MWAW_DEBUG_MSG(("MoreParser::createZones: do not know how to createZone for v1\n"));
327
0
    return false;
328
0
  }
329
28.8k
  if (!readZonesList())
330
946
    return false;
331
332
27.9k
  auto it = m_state->m_typeEntryMap.find("PrintInfo");
333
27.9k
  if (it != m_state->m_typeEntryMap.end())
334
2.33k
    readPrintInfo(it->second);
335
336
27.9k
  it = m_state->m_typeEntryMap.find("DocInfo");
337
27.9k
  if (it != m_state->m_typeEntryMap.end())
338
5.49k
    readDocumentInfo(it->second);
339
340
27.9k
  it = m_state->m_typeEntryMap.find("Fonts");
341
27.9k
  if (it != m_state->m_typeEntryMap.end())
342
6.14k
    m_textParser->readFonts(it->second);
343
344
27.9k
  bool ok=false;
345
27.9k
  it = m_state->m_typeEntryMap.find("Topic");
346
27.9k
  if (it != m_state->m_typeEntryMap.end())
347
27.4k
    ok=m_textParser->readTopic(it->second);
348
27.9k
  if (!ok) // no need to continue if we can not read the text position
349
608
    return false;
350
351
27.3k
  it = m_state->m_typeEntryMap.find("Comment");
352
27.3k
  if (it != m_state->m_typeEntryMap.end())
353
11.4k
    m_textParser->readComment(it->second);
354
355
27.3k
  it = m_state->m_typeEntryMap.find("SpeakerNote");
356
27.3k
  if (it != m_state->m_typeEntryMap.end())
357
7.11k
    m_textParser->readSpeakerNote(it->second);
358
359
27.3k
  it = m_state->m_typeEntryMap.find("Slide");
360
27.3k
  if (it != m_state->m_typeEntryMap.end())
361
11.4k
    readSlideList(it->second);
362
363
27.3k
  it = m_state->m_typeEntryMap.find("Outline");
364
27.3k
  if (it != m_state->m_typeEntryMap.end())
365
20.3k
    m_textParser->readOutlineList(it->second);
366
367
27.3k
  it = m_state->m_typeEntryMap.find("FreePos");
368
27.3k
  if (it != m_state->m_typeEntryMap.end())
369
9.70k
    readFreePos(it->second);
370
371
27.3k
  it = m_state->m_typeEntryMap.find("Unknown9");
372
27.3k
  if (it != m_state->m_typeEntryMap.end())
373
6.16k
    readUnknown9(it->second);
374
375
119k
  for (auto const &fIt : m_state->m_typeEntryMap) {
376
119k
    MWAWEntry const &entry=fIt.second;
377
119k
    if (entry.isParsed())
378
99.5k
      continue;
379
19.6k
    libmwaw::DebugStream f;
380
19.6k
    f << "Entries(" << entry.type() << "):";
381
19.6k
    ascii().addPos(entry.begin());
382
19.6k
    ascii().addNote(f.str().c_str());
383
19.6k
    ascii().addPos(entry.end());
384
19.6k
    ascii().addNote("_");
385
19.6k
  }
386
387
27.3k
  return m_textParser->createZones();
388
27.9k
}
389
390
bool MoreParser::readZonesList()
391
28.8k
{
392
28.8k
  int vers=version();
393
28.8k
  if (vers<2)
394
0
    return false;
395
28.8k
  MWAWInputStreamPtr input = getInput();
396
28.8k
  if (!input->checkPosition(0x80)) {
397
0
    MWAW_DEBUG_MSG(("MoreParser::readZonesList: file is too short\n"));
398
0
    return false;
399
0
  }
400
28.8k
  long pos=8;
401
28.8k
  input->seek(pos, librevenge::RVNG_SEEK_SET);
402
28.8k
  libmwaw::DebugStream f;
403
28.8k
  f << "Entries(Zones):";
404
288k
  for (int i=0; i < 9; i++) {
405
259k
    MWAWEntry entry;
406
259k
    entry.setBegin(long(input->readULong(4)));
407
259k
    entry.setLength(long(input->readULong(4)));
408
259k
    static char const* const names[]= {
409
259k
      "PrintInfo", "DocInfo", "Unknown2", "Topic",
410
259k
      "Comment", "Slide", "Outline", "FreePos", "SpeakerNote"
411
259k
    };
412
259k
    entry.setType(names[i]);
413
259k
    if (!entry.length())
414
45.3k
      continue;
415
214k
    f << names[i] << "(" << std::hex << entry.begin() << "<->" << entry.end()
416
214k
      << std::dec <<  "), ";
417
214k
    if (!checkAndStore(entry)) {
418
113k
      MWAW_DEBUG_MSG(("MoreParser::readZonesList: can not read entry %d\n", i));
419
113k
      f << "###";
420
113k
    }
421
214k
  }
422
28.8k
  auto unkn=long(input->readULong(4));
423
28.8k
  if (unkn) f << "unkn=" << unkn << ",";
424
  /* checkme: another list begins here, but I am not sure of its length :-~ */
425
173k
  for (int i=0; i < 5; i++) {
426
144k
    static char const* const names[]=
427
144k
    { "Unknown9", "Fonts", "UnknownB","UnknownC", "UnknownD" };
428
144k
    MWAWEntry entry;
429
144k
    entry.setBegin(long(input->readULong(4)));
430
144k
    entry.setLength(long(input->readULong(4)));
431
144k
    entry.setType(names[i]);
432
144k
    if (!entry.length())
433
31.1k
      continue;
434
113k
    f << names[i] << "(" << std::hex << entry.begin() << "<->" << entry.end()
435
113k
      << std::dec <<  "), ";
436
113k
    if (!checkAndStore(entry)) {
437
93.5k
      MWAW_DEBUG_MSG(("MoreParser::readZonesList: can not read entry %d\n", i));
438
93.5k
      f << "###";
439
93.5k
    }
440
113k
  }
441
28.8k
  unkn=long(input->readULong(4)); // always 0?
442
28.8k
  if (unkn) f << "unkn2=" << std::hex << unkn << std::dec << ",";
443
28.8k
  ascii().addPos(pos);
444
28.8k
  ascii().addNote(f.str().c_str());
445
446
28.8k
  return !m_state->m_typeEntryMap.empty();
447
28.8k
}
448
449
////////////////////////////////////////////////////////////
450
//
451
// Low level
452
//
453
////////////////////////////////////////////////////////////
454
455
////////////////////////////////////////////////////////////
456
// read the print info
457
////////////////////////////////////////////////////////////
458
bool MoreParser::readPrintInfo(MWAWEntry const &entry)
459
2.33k
{
460
2.33k
  if (!entry.valid() || entry.length() != 120) {
461
1.64k
    MWAW_DEBUG_MSG(("MoreParser::readPrintInfo: the entry is bad\n"));
462
1.64k
    return false;
463
1.64k
  }
464
465
685
  long pos = entry.begin();
466
685
  MWAWInputStreamPtr input = getInput();
467
685
  libmwaw::DebugStream f;
468
469
685
  input->seek(pos, librevenge::RVNG_SEEK_SET);
470
685
  libmwaw::PrinterInfo info;
471
685
  if (!info.read(input)) return false;
472
604
  f << "Entries(PrintInfo):"<< info;
473
604
  entry.setParsed(true);
474
475
604
  MWAWVec2i paperSize = info.paper().size();
476
604
  MWAWVec2i pageSize = info.page().size();
477
604
  if (pageSize.x() <= 0 || pageSize.y() <= 0 ||
478
550
      paperSize.x() <= 0 || paperSize.y() <= 0) return false;
479
480
  // define margin from print info
481
546
  MWAWVec2i lTopMargin= -1 * info.paper().pos(0);
482
546
  MWAWVec2i rBotMargin=info.paper().pos(1) - info.page().pos(1);
483
484
  // move margin left | top
485
546
  int decalX = lTopMargin.x() > 14 ? lTopMargin.x()-14 : 0;
486
546
  int decalY = lTopMargin.y() > 14 ? lTopMargin.y()-14 : 0;
487
546
  lTopMargin -= MWAWVec2i(decalX, decalY);
488
546
  rBotMargin += MWAWVec2i(decalX, decalY);
489
490
  // decrease right | bottom
491
546
  int rightMarg = rBotMargin.x() -10;
492
546
  if (rightMarg < 0) rightMarg=0;
493
546
  int botMarg = rBotMargin.y() -50;
494
546
  if (botMarg < 0) botMarg=0;
495
496
546
  getPageSpan().setMarginTop(lTopMargin.y()/72.0);
497
546
  getPageSpan().setMarginBottom(botMarg/72.0);
498
546
  getPageSpan().setMarginLeft(lTopMargin.x()/72.0);
499
546
  getPageSpan().setMarginRight(rightMarg/72.0);
500
546
  getPageSpan().setFormLength(paperSize.y()/72.);
501
546
  getPageSpan().setFormWidth(paperSize.x()/72.);
502
503
546
  ascii().addPos(pos);
504
546
  ascii().addNote(f.str().c_str());
505
546
  return true;
506
604
}
507
508
////////////////////////////////////////////////////////////
509
// read the document info
510
////////////////////////////////////////////////////////////
511
bool MoreParser::readDocumentInfo(MWAWEntry const &entry)
512
5.49k
{
513
5.49k
  if (!entry.valid() || entry.length() != 436) {
514
4.80k
    MWAW_DEBUG_MSG(("MoreParser::readDocumentInfo: the entry is bad\n"));
515
4.80k
    return false;
516
4.80k
  }
517
518
690
  long pos = entry.begin();
519
690
  MWAWInputStreamPtr input = getInput();
520
690
  libmwaw::DebugStream f;
521
522
690
  input->seek(pos, librevenge::RVNG_SEEK_SET);
523
690
  f << "Entries(DocInfo):";
524
690
  entry.setParsed(true);
525
690
  double margins[4]; // LR TB
526
2.76k
  for (auto &margin : margins) margin=double(input->readULong(2))/1440.;
527
690
  f << "margins=" << margins[0] << "x" << margins[2]
528
690
    << "<->" << margins[1] << "x" << margins[3] << ",";
529
690
  int val;
530
2.07k
  for (int i=0; i < 2; i++) { // always 1: related to header/footer?
531
1.38k
    val=static_cast<int>(input->readLong(1));
532
1.38k
    if (val!=1) f << "fl" << i << "=" << val << ",";
533
1.38k
  }
534
690
  double dim[3];
535
2.07k
  for (auto &d: dim) d=double(input->readULong(2))/72.;
536
690
  f << "dim=" << dim[0] << "x" << dim[1];
537
690
  if (dim[1]<dim[2]||dim[1]>dim[2])
538
311
    f << "[" << dim[2] << "],";
539
379
  else
540
379
    f << ",";
541
690
  if (dim[0]>0 && dim[1]>0 &&
542
627
      margins[0]>=0 && margins[1]>=0 && margins[2]>=0 && margins[3]>=0 &&
543
627
      2.*(margins[0]+margins[1])<dim[0] && 2.*(margins[2]+margins[3])<dim[1]) {
544
530
    getPageSpan().setMarginLeft(margins[0]);
545
530
    getPageSpan().setMarginRight(margins[1]);
546
530
    getPageSpan().setMarginTop(margins[2]);
547
530
    getPageSpan().setMarginBottom(margins[3]);
548
    // has we do not know how to retrieve the page orientation
549
530
    if ((dim[0]>=dim[1]) ==
550
530
        (getPageSpan().getFormWidth()>=getPageSpan().getFormLength())) {
551
481
      getPageSpan().setFormWidth(dim[0]);
552
481
      getPageSpan().setFormLength(dim[1]);
553
481
    }
554
530
  }
555
160
  else {
556
160
    MWAW_DEBUG_MSG(("MoreParser::readDocumentInfo: can not read the page dimension\n"));
557
160
    f << "###";
558
160
  }
559
690
  static int const expectedVal[4]= {0,3,1,0}; // unknown
560
3.45k
  for (int i=0; i < 4; i++) {
561
2.76k
    val=static_cast<int>(input->readLong(2));
562
2.76k
    if (val!=expectedVal[i])
563
1.09k
      f << "f" << i << "=" << val << ",";
564
2.76k
  }
565
690
  val=static_cast<int>(input->readLong(2));
566
690
  if (val!=3) f << "fId?=" << val << ",";
567
690
  val=static_cast<int>(input->readLong(2));
568
690
  if (val!=12) f << "fSz?=" << val << ",";
569
2.07k
  for (int i=0; i < 2; i++) { // always 1: related to font flag
570
1.38k
    val=static_cast<int>(input->readLong(1));
571
1.38k
    if (val!=1) f << "fl" << i+2 << "=" << val << ",";
572
1.38k
  }
573
574
690
  ascii().addDelimiter(input->tell(),'|');
575
690
  ascii().addPos(pos);
576
690
  ascii().addNote(f.str().c_str());
577
578
690
  pos=entry.begin()+160;
579
690
  input->seek(pos,librevenge::RVNG_SEEK_SET);
580
690
  f.str("");
581
690
  f << "DocInfo-II:";
582
690
  ascii().addPos(pos);
583
690
  ascii().addNote(f.str().c_str());
584
585
690
  pos=entry.begin()+268;
586
690
  input->seek(pos,librevenge::RVNG_SEEK_SET);
587
690
  f.str("");
588
690
  f << "DocInfo-III:";
589
5.52k
  for (int st=0; st <7; st++) {
590
    // normal white,white,black,white,black,background=white,white
591
4.83k
    unsigned char color[3];
592
14.4k
    for (auto &c : color) c=static_cast<unsigned char>(input->readULong(2)>>8);
593
4.83k
    MWAWColor col(color[0], color[1], color[2]);
594
4.83k
    if (st==2 || st==4) {
595
1.38k
      if (col.isBlack())
596
652
        continue;
597
1.38k
    }
598
3.45k
    else if (col.isWhite())
599
1.57k
      continue;
600
2.60k
    if (st==5) {
601
393
      m_state->m_backgroundColor=col;
602
393
      f << "backColor=" << col << ",";
603
393
    }
604
2.21k
    else
605
2.21k
      f << "color" << st << "?=" << col << ",";
606
2.60k
  }
607
42.0k
  for (int i=0; i < 60; i++) { // always 0 excepted f57=0|1 ?
608
41.4k
    val=static_cast<int>(input->readLong(2));
609
41.4k
    if (val)
610
20.1k
      f << "f" << i << "=" << val << ",";
611
41.4k
  }
612
2.76k
  for (int i=0; i < 3; i++) { // always 5,5,-1 ?
613
2.07k
    val=static_cast<int>(input->readLong(2));
614
2.07k
    int expVal=i==2?-1:5;
615
2.07k
    if (val!=expVal)
616
1.29k
      f << "g" << i << "=" << val << ",";
617
2.07k
  }
618
690
  ascii().addPos(pos);
619
690
  ascii().addNote(f.str().c_str());
620
690
  return true;
621
5.49k
}
622
623
////////////////////////////////////////////////////////////
624
// read the list of free position
625
////////////////////////////////////////////////////////////
626
bool MoreParser::readFreePos(MWAWEntry const &entry)
627
9.70k
{
628
9.70k
  if (!entry.valid() || entry.length()<4) {
629
207
    MWAW_DEBUG_MSG(("MoreParser::readFreePos: the entry is bad\n"));
630
207
    return false;
631
207
  }
632
633
9.50k
  long pos = entry.begin();
634
9.50k
  MWAWInputStreamPtr &input= getInput();
635
9.50k
  libmwaw::DebugStream f;
636
9.50k
  entry.setParsed(true);
637
638
9.50k
  input->seek(pos, librevenge::RVNG_SEEK_SET);
639
9.50k
  auto N=static_cast<int>(input->readULong(4));
640
9.50k
  f << "Entries(FreePos):N=" << N;
641
9.50k
  if (N > (entry.length() - 4) / 8) {
642
5.45k
    MWAW_DEBUG_MSG(("MoreParser::readFreePos: the number of entry seems bad\n"));
643
5.45k
    f << "###";
644
5.45k
    ascii().addPos(pos);
645
5.45k
    ascii().addNote(f.str().c_str());
646
5.45k
    return false;
647
5.45k
  }
648
4.05k
  ascii().addPos(pos);
649
4.05k
  ascii().addNote(f.str().c_str());
650
651
4.05k
  int val;
652
4.05k
  std::vector<MWAWEntry> filePositions;
653
4.05k
  std::set<long> seenPos;
654
8.93k
  for (int i=0; i < N; i++) {
655
5.97k
    if (input->isEnd())
656
0
      break;
657
5.97k
    pos = input->tell();
658
5.97k
    if (!input->checkPosition(pos+4)) {
659
0
      MWAW_DEBUG_MSG(("MoreParser::readFreePos: can not read some position\n"));
660
0
      break;
661
0
    }
662
5.97k
    long fPos = input->readLong(4);
663
5.97k
    f.str("");
664
5.97k
    f << "FreePos-" << i << ":";
665
5.97k
    f << std::hex << fPos << std::dec << ",";
666
5.97k
    if (fPos<0 || !input->checkPosition(fPos) || seenPos.find(fPos)!=seenPos.end()) {
667
1.08k
      MWAW_DEBUG_MSG(("MoreParser::readFreePos: find invalid position\n"));
668
1.08k
      f << "###";
669
1.08k
      ascii().addPos(pos);
670
1.08k
      ascii().addNote(f.str().c_str());
671
1.08k
      break;
672
1.08k
    }
673
4.88k
    seenPos.insert(fPos);
674
4.88k
    MWAWEntry tEntry;
675
4.88k
    tEntry.setBegin(fPos);
676
4.88k
    auto what=static_cast<int>(input->readULong(2));
677
4.88k
    if (what==0) {
678
4.11k
      tEntry.setLength(static_cast<int>(input->readULong(2)));
679
4.11k
      f << "length=" << tEntry.length() << ",";
680
4.11k
    }
681
773
    else {
682
773
      if (what!=0x7FFF) // 0x7FFF: last entry, fPos correspond to eof position
683
771
        f << "#wh=" << std::hex << what << std::dec << ",";
684
773
      val = static_cast<int>(input->readULong(2)); // probably junk
685
773
      if (val) f << "f0=" << std::hex << val << std::dec << ",";
686
773
    }
687
4.88k
    if (tEntry.valid()) {
688
3.83k
      if (!input->checkPosition(tEntry.end())) {
689
199
        MWAW_DEBUG_MSG(("MoreParser::readFreePos: the entry does not seems valid\n"));
690
199
        f << "###";
691
199
      }
692
3.63k
      else
693
3.63k
        filePositions.push_back(tEntry);
694
3.83k
    }
695
4.88k
    ascii().addPos(pos);
696
4.88k
    ascii().addNote(f.str().c_str());
697
4.88k
  }
698
699
4.05k
  if (input->tell()!=entry.end()) { // end can be junk field
700
3.93k
    ascii().addPos(input->tell());
701
3.93k
    ascii().addNote("FreePos-#");
702
3.93k
  }
703
4.05k
  ascii().addPos(entry.end());
704
4.05k
  ascii().addNote("_");
705
706
4.05k
  for (auto const &tEntry : filePositions) {
707
3.63k
    ascii().addPos(tEntry.begin());
708
3.63k
    ascii().addNote("FreePos-data:");
709
3.63k
    ascii().addPos(tEntry.end());
710
3.63k
    ascii().addNote("_");
711
3.63k
  }
712
713
4.05k
  return true;
714
9.50k
}
715
716
////////////////////////////////////////////////////////////
717
// read the header
718
////////////////////////////////////////////////////////////
719
bool MoreParser::checkHeader(MWAWHeader *header, bool strict)
720
112k
{
721
112k
  *m_state = MoreParserInternal::State();
722
112k
  MWAWInputStreamPtr input = getInput();
723
112k
  if (!input || !input->hasDataFork() || !input->checkPosition(0x80))
724
197
    return false;
725
726
112k
  libmwaw::DebugStream f;
727
112k
  f << "FileHeader:";
728
112k
  input->seek(0,librevenge::RVNG_SEEK_SET);
729
112k
  auto val=static_cast<int>(input->readLong(2));
730
112k
  int vers;
731
112k
  switch (val) {
732
110k
  case 3:
733
110k
    vers=2;
734
110k
    if (input->readULong(4)!=0x4d524949) // MRII
735
62
      return false;
736
110k
    break;
737
110k
  case 6:
738
2.38k
    vers=3;
739
2.38k
    if (input->readULong(4)!=0x4d4f5233) // MOR3
740
62
      return false;
741
2.32k
    break;
742
2.32k
  default:
743
129
    return false;
744
112k
  }
745
112k
  setVersion(vers);
746
112k
  val=static_cast<int>(input->readLong(2));
747
112k
  if (val!=0x80) {
748
93
    if (strict)
749
30
      return false;
750
63
    f << "f0=" << std::hex << val << std::dec << ",";
751
63
  }
752
112k
  if (strict) {
753
142k
    for (int i=0; i < 8; i++) {
754
132k
      MWAWEntry entry;
755
132k
      entry.setBegin(long(input->readULong(4)));
756
132k
      entry.setLength(long(input->readULong(4)));
757
132k
      if (!entry.length())
758
31.0k
        continue;
759
101k
      if (!input->checkPosition(entry.end()-1))
760
22.0k
        return false;
761
101k
    }
762
32.6k
  }
763
90.2k
  if (header)
764
32.5k
    header->reset(MWAWDocument::MWAW_T_MORE, vers);
765
90.2k
  ascii().addPos(0);
766
90.2k
  ascii().addNote(f.str().c_str());
767
90.2k
  return true;
768
112k
}
769
770
//////////////////////////////////////////////
771
// slide
772
//////////////////////////////////////////////
773
bool MoreParser::readSlideList(MWAWEntry const &entry)
774
11.4k
{
775
11.4k
  if (!entry.valid() || (entry.length()%8)) {
776
199
    MWAW_DEBUG_MSG(("MoreParser::readSlideList: the entry is bad\n"));
777
199
    return false;
778
199
  }
779
780
11.2k
  long pos = entry.begin();
781
11.2k
  MWAWInputStreamPtr &input= getInput();
782
11.2k
  libmwaw::DebugStream f;
783
784
11.2k
  input->seek(pos, librevenge::RVNG_SEEK_SET);
785
11.2k
  entry.setParsed(true);
786
787
11.2k
  ascii().addPos(pos);
788
11.2k
  ascii().addNote("Entries(Slide)");
789
790
11.2k
  auto N=int(entry.length()/8);
791
11.2k
  std::vector<MWAWEntry> filePositions;
792
7.42M
  for (int i=0; i < N; i++) {
793
7.41M
    pos=input->tell();
794
795
7.41M
    f.str("");
796
7.41M
    f << "Slide-" << i << ":";
797
7.41M
    long fPos = input->readLong(4);
798
7.41M
    f << "pos=" << std::hex << fPos << std::dec << ",";
799
7.41M
    MWAWEntry tEntry;
800
7.41M
    tEntry.setBegin(fPos);
801
7.41M
    if (fPos==0x50) // checkme: default or related to filePosition 0x50 ?
802
1.32k
      ;
803
7.41M
    else if (!checkAndFindSize(tEntry)) {
804
6.82M
      MWAW_DEBUG_MSG(("MoreParser::readSlideList: can not read a file position\n"));
805
6.82M
      f << "###";
806
6.82M
    }
807
582k
    else
808
582k
      filePositions.push_back(tEntry);
809
7.41M
    auto val = static_cast<int>(input->readLong(2)); // always -1 ?
810
7.41M
    if (val != -1)
811
7.21M
      f << "f0=" << val << ",";
812
7.41M
    val = static_cast<int>(input->readLong(2)); // always 0 ?
813
7.41M
    if (val)
814
5.28M
      f << "f1=" << val << ",";
815
816
7.41M
    ascii().addPos(pos);
817
7.41M
    ascii().addNote(f.str().c_str());
818
7.41M
    input->seek(pos+8, librevenge::RVNG_SEEK_SET);
819
7.41M
  }
820
11.2k
  int n=0;
821
582k
  for (auto const &tEntry : filePositions) {
822
582k
    if (readSlide(tEntry))
823
374k
      continue;
824
207k
    f.str("");
825
207k
    f << "Slide-###" << n++ << "[data]:";
826
207k
    ascii().addPos(tEntry.begin());
827
207k
    ascii().addNote(f.str().c_str());
828
207k
    ascii().addPos(tEntry.end());
829
207k
    ascii().addNote("_");
830
207k
  }
831
11.2k
  return true;
832
11.4k
}
833
834
bool MoreParser::readSlide(MWAWEntry const &entry)
835
582k
{
836
582k
  if (!entry.valid() || entry.length()<16) {
837
207k
    MWAW_DEBUG_MSG(("MoreParser::readSlide: the entry is bad\n"));
838
207k
    return false;
839
207k
  }
840
374k
  long pos = entry.begin();
841
374k
  long endPos = entry.end();
842
374k
  MWAWInputStreamPtr &input= getInput();
843
374k
  libmwaw::DebugStream f;
844
845
374k
  input->seek(pos+4, librevenge::RVNG_SEEK_SET); // skip size
846
374k
  entry.setParsed(true);
847
848
374k
  f << "Slide[data]:";
849
374k
  ascii().addPos(pos);
850
374k
  ascii().addNote(f.str().c_str());
851
374k
  input->seek(pos+16, librevenge::RVNG_SEEK_SET);
852
853
374k
  int n=0;
854
621k
  while (1) {
855
621k
    pos = input->tell();
856
621k
    if (pos+2 > endPos)
857
6.05k
      break;
858
615k
    auto type=static_cast<int>(input->readLong(2));
859
615k
    int dataSz=0;
860
615k
    if (type & 0x1)
861
247k
      dataSz=4;
862
367k
    else {
863
367k
      switch (type) {
864
621
      case 0x66: // group: arg num group
865
4.20k
      case 0x68: // group of num 6a,70* ?
866
4.46k
      case 0x72: // group of num 74* ?
867
5.01k
      case 0x74: // [ id : val ]
868
5.01k
        dataSz=4;
869
5.01k
        break;
870
2.11k
      case 0x6a: // pattern?, text, id, ...
871
3.25k
      case 0x70: // size=0x4a ?
872
3.25k
        dataSz=4+static_cast<int>(input->readULong(4));
873
3.25k
        break;
874
359k
      default:
875
359k
        MWAW_DEBUG_MSG(("MoreParser::readSlide: argh... find unexpected type %d\n", type));
876
359k
        break;
877
367k
      }
878
367k
    }
879
615k
    if (!dataSz || pos+2+dataSz > endPos) {
880
368k
      input->seek(pos, librevenge::RVNG_SEEK_SET);
881
368k
      break;
882
368k
    }
883
884
247k
    f.str("");
885
247k
    f << "Slide-" << n++ << "[data]:";
886
247k
    f << "type=" << std::hex << (type&0xFFFE) << std::dec;
887
247k
    if (type&1) f << "*";
888
247k
    f << ",";
889
247k
    if (dataSz==4)
890
245k
      f << "N=" << input->readLong(4) << ",";
891
247k
    if (type==0x6a) {
892
1.71k
      MWAWEntry dEntry;
893
1.71k
      dEntry.setBegin(pos+2+4);
894
1.71k
      dEntry.setLength(dataSz-4);
895
      // can also be some text and ?
896
1.71k
      if (m_textParser->parseUnknown(dEntry, -6))
897
627
        ;
898
1.08k
      else if (readGraphic(dEntry))
899
0
        f << "graphic,";
900
1.08k
      else
901
1.08k
        f << "#";
902
1.71k
    }
903
247k
    input->seek(pos+2+dataSz, librevenge::RVNG_SEEK_SET);
904
247k
    ascii().addPos(pos);
905
247k
    ascii().addNote(f.str().c_str());
906
247k
  }
907
374k
  pos = input->tell();
908
374k
  if (pos!=endPos) {
909
368k
    ascii().addPos(pos);
910
368k
    ascii().addNote("Slide-###[data]:");
911
368k
  }
912
913
374k
  ascii().addPos(endPos);
914
374k
  ascii().addNote("_");
915
916
374k
  return true;
917
374k
}
918
919
bool MoreParser::readGraphic(MWAWEntry const &entry)
920
1.08k
{
921
1.08k
  if (!entry.valid() || entry.length()<0xd)
922
983
    return false;
923
924
104
  long pos = entry.begin();
925
104
  MWAWInputStreamPtr input = getInput();
926
104
  input->seek(pos, librevenge::RVNG_SEEK_SET);
927
928
  // first check
929
104
  auto readSize = int(input->readULong(2));
930
104
  input->seek(8, librevenge::RVNG_SEEK_CUR); // skip dim
931
104
  long lastFlag = input->readLong(2);
932
104
  switch (lastFlag) {
933
0
  case 0x1101: {
934
0
    if (readSize+2 != entry.length() && readSize+3 != entry.length())
935
0
      return false;
936
0
    break;
937
0
  }
938
31
  case 0x0011: {
939
31
    if (entry.length() < 42) return false;
940
2
    if (input->readULong(2) != 0x2ff) return false;
941
0
    if (input->readULong(2) != 0xC00) return false;
942
0
    break;
943
0
  }
944
73
  default:
945
73
    return false;
946
104
  }
947
948
0
  input->seek(pos, librevenge::RVNG_SEEK_SET);
949
950
0
  MWAWBox2f box;
951
0
  if (MWAWPictData::check(input, static_cast<int>(entry.length()), box)==MWAWPict::MWAW_R_BAD)
952
0
    return false;
953
#ifdef DEBUG_WITH_FILES
954
  if (1) {
955
    librevenge::RVNGBinaryData file;
956
    input->seek(pos, librevenge::RVNG_SEEK_SET);
957
    input->readDataBlock(entry.length(), file);
958
    static int volatile pictName = 0;
959
    libmwaw::DebugStream f;
960
    f << "Pict-" << ++pictName << ".pct";
961
    libmwaw::Debug::dumpFile(file, f.str().c_str());
962
  }
963
#endif
964
0
  ascii().skipZone(pos, entry.end()-1);
965
0
  return true;
966
0
}
967
968
////////////////////////////////////////////////////////////
969
// read some unknow zone
970
////////////////////////////////////////////////////////////
971
972
// checkme: not sure...
973
bool MoreParser::readUnknown9(MWAWEntry const &entry)
974
6.16k
{
975
6.16k
  if (!entry.valid() || entry.length() < 26) {
976
67
    MWAW_DEBUG_MSG(("MoreParser::readUnknown9: the entry is bad\n"));
977
67
    return false;
978
67
  }
979
980
6.10k
  long pos = entry.begin();
981
6.10k
  long endPos = entry.end();
982
6.10k
  MWAWInputStreamPtr input = getInput();
983
6.10k
  libmwaw::DebugStream f;
984
6.10k
  entry.setParsed(true);
985
986
6.10k
  input->seek(pos, librevenge::RVNG_SEEK_SET);
987
6.10k
  f << "Entries(Unknown9):";
988
6.10k
  auto N=static_cast<int>(input->readLong(4));
989
6.10k
  f << "N=" << N << ",";
990
6.10k
  ascii().addPos(pos);
991
6.10k
  ascii().addNote(f.str().c_str());
992
993
14.0k
  for (int n=0; n<N; n++) {
994
12.6k
    pos=input->tell();
995
12.6k
    if (pos+6>endPos)
996
29
      break;
997
12.6k
    if (n==0) {
998
4.78k
      if (readColors(endPos))
999
290
        continue;
1000
4.49k
      input->seek(pos, librevenge::RVNG_SEEK_SET);
1001
4.49k
    }
1002
12.3k
    auto type=static_cast<int>(input->readULong(2)); // find 1: color 2:?
1003
12.3k
    if (type > 10) break;
1004
9.42k
    auto dataSz = long(input->readULong(4));
1005
9.42k
    if (dataSz<= 0 || pos+6+dataSz > endPos) {
1006
1.78k
      input->seek(pos, librevenge::RVNG_SEEK_SET);
1007
1.78k
      break;
1008
1.78k
    }
1009
1010
7.63k
    bool ok=false;
1011
7.63k
    long endFPos = pos+6+dataSz;
1012
1013
7.63k
    f.str("");
1014
7.63k
    f << "Unknown9-" << n << ":type=" << type << ",";
1015
7.63k
    if (type==2) {
1016
7.19k
      MoreStruct::Pattern pattern;
1017
7.19k
      ok=readPattern(endFPos, pattern);
1018
7.19k
      if (ok)
1019
5.62k
        f << pattern << ",";
1020
7.19k
      if (!ok) {
1021
1.57k
        std::string mess("");
1022
1.57k
        input->seek(pos+6, librevenge::RVNG_SEEK_SET);
1023
1.57k
        ok = readBackside(endFPos, mess);
1024
1.57k
        if (ok)
1025
191
          f << "backside," << mess;
1026
1.57k
      }
1027
7.19k
      if (!ok) {
1028
1.38k
        input->seek(pos+6, librevenge::RVNG_SEEK_SET);
1029
1.38k
        ok = readUnkn9Sub(endFPos);
1030
1.38k
        if (ok)
1031
893
          f << "Unkn9A,";
1032
1.38k
      }
1033
7.19k
    }
1034
7.63k
    if (!ok) {
1035
931
      MWAW_DEBUG_MSG(("MoreParser::readUnknown9: find some unknown structure\n"));
1036
931
      f << "###";
1037
931
    }
1038
6.70k
    else if (endFPos!=input->tell()) {
1039
321
      MWAW_DEBUG_MSG(("MoreParser::readUnknown9: find some extra data\n"));
1040
321
      f << "###";
1041
321
      ascii().addDelimiter(input->tell(),'|');
1042
321
    }
1043
7.63k
    input->seek(endFPos, librevenge::RVNG_SEEK_SET);
1044
1045
7.63k
    ascii().addPos(pos);
1046
7.63k
    ascii().addNote(f.str().c_str());
1047
7.63k
    ascii().addPos(endFPos);
1048
7.63k
    ascii().addNote("_");
1049
7.63k
  }
1050
6.10k
  pos=input->tell();
1051
6.10k
  if (pos!=endPos) {
1052
6.08k
    MWAW_DEBUG_MSG(("MoreParser::readUnknown9: the parsing stopped before end\n"));
1053
6.08k
    ascii().addPos(pos);
1054
6.08k
    ascii().addNote("Unknown9(II)");
1055
6.08k
  }
1056
6.10k
  return true;
1057
6.16k
}
1058
1059
// a list of colors ( the first zone of block9)
1060
bool MoreParser::readColors(long endPos)
1061
4.78k
{
1062
4.78k
  MWAWInputStreamPtr input = getInput();
1063
4.78k
  long pos = input->tell();
1064
4.78k
  if (pos+22 > endPos)
1065
0
    return false;
1066
4.78k
  if (input->readLong(2)!=1)
1067
3.88k
    return false;
1068
1069
898
  libmwaw::DebugStream f;
1070
898
  f << "Entries(ColorL):";
1071
898
  auto dataSz=long(input->readULong(4));
1072
898
  if (pos+6+dataSz > endPos)
1073
539
    return false;
1074
359
  long val= input->readLong(4); // 3ff or 413 a size ?
1075
359
  if (val) f << "f0=" << val << ",";
1076
359
  val= input->readLong(2); // always 0
1077
359
  if (val) f << "f1=" << val << ",";
1078
359
  auto maxCols=static_cast<int>(input->readLong(2));
1079
359
  f << "nCol=" << maxCols << ",";
1080
359
  if (maxCols<0 || 16+8*maxCols != dataSz)
1081
69
    return false;
1082
290
  ascii().addPos(pos);
1083
290
  ascii().addNote(f.str().c_str());
1084
9.22k
  for (int i=0; i <= maxCols; i++) {
1085
8.93k
    pos=input->tell();
1086
8.93k
    f.str("");
1087
8.93k
    f << "ColorL" << i << ",";
1088
8.93k
    auto id=static_cast<int>(input->readLong(2));
1089
8.93k
    if (id!=i) f << "#id=" << id << ",";
1090
8.93k
    unsigned char rgb[3];
1091
26.7k
    for (auto &c : rgb) c=static_cast<unsigned char>(input->readULong(2)>>8);
1092
8.93k
    MWAWColor col(rgb[0], rgb[1], rgb[2]);
1093
8.93k
    f << "col=" << col << ",";
1094
8.93k
    ascii().addPos(pos);
1095
8.93k
    ascii().addNote(f.str().c_str());
1096
8.93k
  }
1097
290
  return true;
1098
359
}
1099
1100
// a backside definition? ( the last zones of block9)
1101
bool MoreParser::readBackside(long endPos, std::string &extra)
1102
94.2M
{
1103
94.2M
  extra="";
1104
1105
94.2M
  MWAWInputStreamPtr input = getInput();
1106
94.2M
  long pos = input->tell();
1107
94.2M
  if (pos+0x2e > endPos)
1108
3.44M
    return false;
1109
1110
90.7M
  std::string name("");
1111
816M
  for (int i=0; i < 8; i++)
1112
726M
    name += char(input->readULong(1));
1113
90.7M
  if (name != "BACKSIDE")
1114
90.7M
    return false;
1115
1116
22.0k
  libmwaw::DebugStream f;
1117
22.0k
  auto val=static_cast<int>(input->readULong(1)); // small number between 1 and 8
1118
22.0k
  f << "f0=" << val << ",";
1119
22.0k
  val=static_cast<int>(input->readLong(1)); // always 0 ?
1120
22.0k
  if (val) f << "f1=" << val << ",";
1121
110k
  for (int i=0; i < 4; i++) { // always 0?
1122
88.3k
    val = static_cast<int>(input->readLong(2));
1123
88.3k
    if (val) f << "f" << i+2 << "=" << val << ",";
1124
88.3k
  }
1125
22.0k
  int center[2]; // checkme: xy
1126
44.1k
  for (auto &c : center) c=static_cast<int>(input->readLong(2));
1127
22.0k
  if (center[0]!=500 || center[1]!=500)
1128
20.3k
    f << "center=" << center[0] << "x" << center[1] << ",";
1129
22.0k
  int dim[4];
1130
88.3k
  for (auto &d : dim) d=static_cast<int>(input->readLong(2));
1131
22.0k
  if (dim[0] || dim[1] || dim[2]!=1000 || dim[3]!=1000)
1132
20.4k
    f << "dim=" << dim[0] << "x" << dim[1] << "<->" << dim[2] << "x" << dim[3] << ",";
1133
66.2k
  for (int i=0; i < 2; i++) { // g0: small number between 1 and a, g1:16*small number
1134
44.1k
    val = static_cast<int>(input->readLong(2));
1135
44.1k
    if (val) f << "g" << i << "=" << val << ",";
1136
44.1k
  }
1137
22.0k
  unsigned char rgb[3];
1138
66.2k
  for (auto &c: rgb) c=static_cast<unsigned char>(input->readULong(2)>>8);
1139
22.0k
  f << "col0=" << MWAWColor(rgb[0], rgb[1], rgb[2]) << ",";
1140
66.2k
  for (auto &c: rgb) c=static_cast<unsigned char>(input->readULong(2)>>8);
1141
22.0k
  f << "col1=" << MWAWColor(rgb[0], rgb[1], rgb[2]) << ",";
1142
22.0k
  extra=f.str();
1143
22.0k
  return true;
1144
90.7M
}
1145
1146
// a pattern ( the zones of block9 which follow color)
1147
bool MoreParser::readPattern(long endPos, MoreStruct::Pattern &pattern)
1148
94.2M
{
1149
94.2M
  pattern = MoreStruct::Pattern();
1150
94.2M
  MWAWInputStreamPtr input = getInput();
1151
94.2M
  long pos = input->tell();
1152
94.2M
  if (pos+0x1c > endPos)
1153
2.94M
    return false;
1154
1155
91.2M
  std::string name("");
1156
821M
  for (int i=0; i < 8; i++)
1157
730M
    name += char(input->readULong(1));
1158
91.2M
  if (name != "BACKPTRN")
1159
91.2M
    return false;
1160
1161
176k
  for (auto &data : pattern.m_pattern) data = static_cast<unsigned char>(input->readULong(1));
1162
1163
  // checkme: in general frontColor=backColor, but not always...
1164
22.0k
  unsigned char rgb[3];
1165
66.0k
  for (auto &c : rgb) c=static_cast<unsigned char>(input->readULong(2)>>8);
1166
22.0k
  pattern.m_frontColor=MWAWColor(rgb[0], rgb[1], rgb[2]);
1167
66.0k
  for (auto &c : rgb) c=static_cast<unsigned char>(input->readULong(2)>>8);
1168
22.0k
  pattern.m_backColor=MWAWColor(rgb[0], rgb[1], rgb[2]);
1169
22.0k
  return true;
1170
91.2M
}
1171
1172
/* a ? ( the middle zone of block9). checkme: structure */
1173
bool MoreParser::readUnkn9Sub(long endPos)
1174
1.38k
{
1175
1.38k
  MWAWInputStreamPtr input = getInput();
1176
1.38k
  long debPos = input->tell();
1177
1.38k
  if (debPos+118 > endPos)
1178
347
    return false;
1179
1180
1.03k
  long pos = debPos;
1181
1.03k
  libmwaw::DebugStream f;
1182
1.03k
  f << "Entries(Unkn9A):";
1183
1.03k
  long val=input->readLong(2); // always 1?
1184
1.03k
  if (val!=1) f << "f0=" << val << ",";
1185
1.03k
  val=input->readLong(4); // always 1c
1186
1.03k
  if (val!=0x1c) f << "f1=" << val << ",";
1187
1.03k
  val=input->readLong(4); // always 4e
1188
1.03k
  if (val!=0x4e) f << "f2=" << val << ",";
1189
6.22k
  for (int i=0; i < 5; i++) { // 0 excepted f5=-1
1190
5.19k
    val=input->readLong(2);
1191
5.19k
    if (val) f << "f" << i+3 << "=" << val << ",";
1192
5.19k
  }
1193
  /* find [0,2,2,2,2,2,7e,0] or [0,0,0,0,0,0,ff,0,] or [db,6d,b6,db,6d,b6,db,6d,]:
1194
     maybe a pattern */
1195
1.03k
  f << "pattern?=[";
1196
9.34k
  for (int i=0; i < 8; i++)
1197
8.30k
    f << std::hex << input->readULong(1) << std::dec << ",";
1198
1.03k
  f << "],";
1199
1200
1.03k
  static int const expectedVal[]= {0, 0, 0x8004, 0, 0, 8, 8 };
1201
8.30k
  for (int i=0; i < 7; i++) {
1202
7.26k
    val=long(input->readULong(2));
1203
7.26k
    if (val!=expectedVal[i]) f << "g" << i << "=" << val << ",";
1204
7.26k
  }
1205
10.3k
  for (int i=0; i < 9; i++) {
1206
9.34k
    val=input->readLong(2);
1207
9.34k
    int expected=(i==4||i==6) ? 0x48:0;
1208
9.34k
    if (val != expected) f << "h" << i << "=" << val << ",";
1209
9.34k
  }
1210
1211
1.03k
  ascii().addPos(pos);
1212
1.03k
  ascii().addNote(f.str().c_str());
1213
1214
1.03k
  pos=debPos+60;
1215
1.03k
  input->seek(pos, librevenge::RVNG_SEEK_SET);
1216
1.03k
  f.str("");
1217
1.03k
  f << "Unkn9A-II:";
1218
10.3k
  for (int i=0; i < 9; i++) {
1219
9.34k
    val=input->readLong(2);
1220
9.34k
    int expected= i==1 ? 1 : i<3 ? 4 : i==6 ? 0x6e : 0;
1221
9.34k
    if (val != expected) f << "f" << i << "=" << val << ",";
1222
9.34k
  }
1223
  /* now 8 uint32_t zones:
1224
     Z1,Z2,..,Z5: always similar, Z7: often 0
1225
     note: I only find in 0..3 in the 8 uint4_t which compose a uint32_t
1226
   */
1227
1.03k
  f << "unkn=[";
1228
9.34k
  for (int i=0; i < 8; i++) {
1229
8.30k
    val=long(input->readULong(4));
1230
8.30k
    if (val)
1231
5.91k
      f << std::hex << val << std::dec << ",";
1232
2.39k
    else
1233
2.39k
      f << "_,";
1234
8.30k
  }
1235
1.03k
  f << "],";
1236
4.15k
  for (int i=0; i < 3; i++) { // always 0?
1237
3.11k
    val=input->readLong(2);
1238
3.11k
    if (val)
1239
647
      f << "g=" << val << ",";
1240
3.11k
  }
1241
1.03k
  ascii().addPos(pos);
1242
1.03k
  ascii().addNote(f.str().c_str());
1243
1244
1.03k
  pos=debPos+116;
1245
1.03k
  input->seek(pos, librevenge::RVNG_SEEK_SET);
1246
1.03k
  auto N=static_cast<int>(input->readLong(2));
1247
1.03k
  f.str("");
1248
1.03k
  f << "Unkn9A-III:N=" << N << ",";
1249
1.03k
  if (pos+2+(N+1)*8 > endPos) {
1250
145
    MWAW_DEBUG_MSG(("MoreParser::readUnkn9Sub: can not read end of zone\n"));
1251
145
    f << "###";
1252
145
    ascii().addPos(pos);
1253
145
    ascii().addNote(f.str().c_str());
1254
145
    return false;
1255
145
  }
1256
893
  ascii().addPos(pos);
1257
893
  ascii().addNote(f.str().c_str());
1258
12.1k
  for (int n=0; n <= N; n++) {
1259
11.2k
    pos = input->tell();
1260
11.2k
    f.str("");
1261
11.2k
    f << "Unkn9A-III[" << n << "]:";
1262
11.2k
    val = input->readLong(2);
1263
11.2k
    if (int(val) != n) f << "#id=" << val << ",";
1264
1265
11.2k
    ascii().addDelimiter(input->tell(),'|');
1266
11.2k
    ascii().addPos(pos);
1267
11.2k
    ascii().addNote(f.str().c_str());
1268
11.2k
    input->seek(pos+8, librevenge::RVNG_SEEK_SET);
1269
11.2k
  }
1270
893
  return true;
1271
1.03k
}
1272
1273
////////////////////////////////////////////////////////////
1274
// MoreStruct implementation
1275
////////////////////////////////////////////////////////////
1276
1277
namespace MoreStruct
1278
{
1279
std::ostream &operator<<(std::ostream &o, Pattern const &pat)
1280
0
{
1281
0
  o << "pat=[" << std::hex;
1282
0
  for (auto data : pat.m_pattern)
1283
0
    o << data << ",";
1284
0
  o << std::dec << "],";
1285
0
  if (!pat.m_frontColor.isBlack())
1286
0
    o << "frontColor=" << pat.m_frontColor << ",";
1287
0
  if (!pat.m_backColor.isWhite())
1288
0
    o << "backColor=" << pat.m_backColor << ",";
1289
0
  return o;
1290
0
}
1291
}
1292
// vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: