Coverage Report

Created: 2026-03-12 06:42

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libmwaw/src/lib/HanMacWrdKParser.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
#include <string>
41
42
#include <librevenge/librevenge.h>
43
44
#include "MWAWCell.hxx"
45
#include "MWAWTextListener.hxx"
46
#include "MWAWFont.hxx"
47
#include "MWAWFontConverter.hxx"
48
#include "MWAWHeader.hxx"
49
#include "MWAWList.hxx"
50
#include "MWAWParagraph.hxx"
51
#include "MWAWPosition.hxx"
52
#include "MWAWPictMac.hxx"
53
#include "MWAWPrinter.hxx"
54
#include "MWAWSubDocument.hxx"
55
56
#include "HanMacWrdKGraph.hxx"
57
#include "HanMacWrdKText.hxx"
58
59
#include "HanMacWrdKParser.hxx"
60
61
/** Internal: the structures of a HanMacWrdKParser */
62
namespace HanMacWrdKParserInternal
63
{
64
////////////////////////////////////////
65
//! Internal: the state of a HanMacWrdKParser
66
struct State {
67
  //! constructor
68
  State()
69
22.0k
    : m_zonesListBegin(-1)
70
22.0k
    , m_zonesMap()
71
22.0k
    , m_actPage(0)
72
22.0k
    , m_numPages(0)
73
22.0k
    , m_headerHeight(0)
74
22.0k
    , m_footerHeight(0)
75
22.0k
  {
76
22.0k
  }
77
78
  //! the list of zone begin
79
  long m_zonesListBegin;
80
  //! a map of entry: zoneId->zone
81
  std::multimap<long,std::shared_ptr<HanMacWrdKZone> > m_zonesMap;
82
83
  int m_actPage /** the actual page */, m_numPages /** the number of page of the final document */;
84
  int m_headerHeight /** the header height if known */,
85
      m_footerHeight /** the footer height if known */;
86
};
87
88
////////////////////////////////////////
89
//! Internal: the subdocument of a HanMacWrdKParser
90
class SubDocument final : public MWAWSubDocument
91
{
92
public:
93
  SubDocument(HanMacWrdKParser &pars, MWAWInputStreamPtr const &input, long zoneId)
94
4.89k
    : MWAWSubDocument(&pars, input, MWAWEntry())
95
4.89k
    , m_id(zoneId) {}
96
97
  //! destructor
98
0
  ~SubDocument() final {}
99
100
  //! operator!=
101
  bool operator!=(MWAWSubDocument const &doc) const final
102
0
  {
103
0
    if (MWAWSubDocument::operator!=(doc)) return true;
104
0
    auto const *sDoc = dynamic_cast<SubDocument const *>(&doc);
105
0
    if (!sDoc) return true;
106
0
    if (m_id != sDoc->m_id) return true;
107
0
    return false;
108
0
  }
109
110
  //! the parser function
111
  void parse(MWAWListenerPtr &listener, libmwaw::SubDocumentType type) final;
112
113
protected:
114
  //! the subdocument id
115
  long m_id;
116
};
117
118
void SubDocument::parse(MWAWListenerPtr &listener, libmwaw::SubDocumentType type)
119
4.89k
{
120
4.89k
  if (!listener.get()) {
121
0
    MWAW_DEBUG_MSG(("HanMacWrdKParserInternal::SubDocument::parse: no listener\n"));
122
0
    return;
123
0
  }
124
4.89k
  if (type != libmwaw::DOC_HEADER_FOOTER) {
125
0
    MWAW_DEBUG_MSG(("HanMacWrdKParserInternal::SubDocument::parse: unexpected document type\n"));
126
0
    return;
127
0
  }
128
4.89k
  auto *parser=dynamic_cast<HanMacWrdKParser *>(m_parser);
129
4.89k
  if (!parser) {
130
0
    MWAW_DEBUG_MSG(("HanMacWrdKParserInternal::SubDocument::parse: no listener\n"));
131
0
    return;
132
0
  }
133
4.89k
  long pos = m_input->tell();
134
4.89k
  parser->sendText(m_id, 0);
135
4.89k
  m_input->seek(pos, librevenge::RVNG_SEEK_SET);
136
4.89k
}
137
}
138
139
////////////////////////////////////////////////////////////
140
// constructor/destructor + basic interface ...
141
////////////////////////////////////////////////////////////
142
HanMacWrdKParser::HanMacWrdKParser(MWAWInputStreamPtr const &input, MWAWRSRCParserPtr const &rsrcParser, MWAWHeader *header)
143
9.16k
  : MWAWTextParser(input, rsrcParser, header)
144
9.16k
  , m_state()
145
9.16k
  , m_graphParser()
146
9.16k
  , m_textParser()
147
9.16k
{
148
9.16k
  init();
149
9.16k
}
150
151
HanMacWrdKParser::~HanMacWrdKParser()
152
9.16k
{
153
9.16k
}
154
155
void HanMacWrdKParser::init()
156
9.16k
{
157
9.16k
  resetTextListener();
158
9.16k
  setAsciiName("main-1");
159
160
9.16k
  m_state.reset(new HanMacWrdKParserInternal::State);
161
162
  // reduce the margin (in case, the page is not defined)
163
9.16k
  getPageSpan().setMarginTop(0.1);
164
9.16k
  getPageSpan().setMarginBottom(0.1);
165
9.16k
  getPageSpan().setMarginLeft(0.1);
166
9.16k
  getPageSpan().setMarginRight(0.1);
167
168
9.16k
  m_graphParser.reset(new HanMacWrdKGraph(*this));
169
9.16k
  m_textParser.reset(new HanMacWrdKText(*this));
170
9.16k
}
171
172
bool HanMacWrdKParser::sendText(long id, long subId, MWAWListenerPtr listener)
173
4.95k
{
174
4.95k
  return m_textParser->sendText(id, subId, listener);
175
4.95k
}
176
177
bool HanMacWrdKParser::canSendTextAsGraphic(long id, long subId)
178
1
{
179
1
  return m_textParser->canSendTextAsGraphic(id, subId);
180
1
}
181
182
bool HanMacWrdKParser::sendZone(long zId)
183
61
{
184
61
  MWAWPosition pos(MWAWVec2f(0,0), MWAWVec2f(0,0), librevenge::RVNG_POINT);
185
61
  pos.setRelativePosition(MWAWPosition::Char);
186
61
  return m_graphParser->sendFrame(zId, pos);
187
61
}
188
189
bool HanMacWrdKParser::getColor(int colId, int patternId, MWAWColor &color) const
190
112k
{
191
112k
  return m_graphParser->getColor(colId, patternId, color);
192
112k
}
193
194
////////////////////////////////////////////////////////////
195
// position and height
196
////////////////////////////////////////////////////////////
197
MWAWVec2f HanMacWrdKParser::getPageLeftTop() const
198
0
{
199
0
  return MWAWVec2f(float(getPageSpan().getMarginLeft()),
200
0
                   float(getPageSpan().getMarginTop()+m_state->m_headerHeight/72.0));
201
0
}
202
203
////////////////////////////////////////////////////////////
204
// new page
205
////////////////////////////////////////////////////////////
206
void HanMacWrdKParser::newPage(int number)
207
4.05k
{
208
4.05k
  if (number <= m_state->m_actPage || number > m_state->m_numPages)
209
145
    return;
210
211
7.83k
  while (m_state->m_actPage < number) {
212
3.93k
    m_state->m_actPage++;
213
3.93k
    if (!getTextListener() || m_state->m_actPage == 1)
214
2.22k
      continue;
215
1.70k
    getTextListener()->insertBreak(MWAWTextListener::PageBreak);
216
1.70k
  }
217
3.90k
}
218
219
////////////////////////////////////////////////////////////
220
// the parser
221
////////////////////////////////////////////////////////////
222
void HanMacWrdKParser::parse(librevenge::RVNGTextInterface *docInterface)
223
3.69k
{
224
3.69k
  if (!getInput().get() || !checkHeader(nullptr)) throw(libmwaw::ParseException());
225
3.69k
  bool ok = true;
226
3.69k
  try {
227
    // create the asciiFile
228
3.69k
    ascii().setStream(getInput());
229
3.69k
    ascii().open(asciiName());
230
231
3.69k
    checkHeader(nullptr);
232
3.69k
    ok = createZones();
233
3.69k
    if (ok) {
234
3.43k
      createDocument(docInterface);
235
3.43k
      auto const &tokenIds = m_textParser->getTokenIdList();
236
3.43k
      m_graphParser->sendPageGraphics(tokenIds);
237
3.43k
      m_textParser->sendMainText();
238
239
#ifdef DEBUG
240
      m_textParser->flushExtra();
241
      m_graphParser->flushExtra();
242
#endif
243
3.43k
    }
244
3.69k
    ascii().reset();
245
3.69k
  }
246
3.69k
  catch (...) {
247
0
    MWAW_DEBUG_MSG(("HanMacWrdKParser::parse: exception catched when parsing\n"));
248
0
    ok = false;
249
0
  }
250
251
3.69k
  resetTextListener();
252
3.69k
  if (!ok) throw(libmwaw::ParseException());
253
3.69k
}
254
255
////////////////////////////////////////////////////////////
256
// create the document
257
////////////////////////////////////////////////////////////
258
void HanMacWrdKParser::createDocument(librevenge::RVNGTextInterface *documentInterface)
259
3.43k
{
260
3.43k
  if (!documentInterface) return;
261
3.43k
  if (getTextListener()) {
262
0
    MWAW_DEBUG_MSG(("HanMacWrdKParser::createDocument: listener already exist\n"));
263
0
    return;
264
0
  }
265
266
  // update the page
267
3.43k
  m_state->m_actPage = 0;
268
269
3.43k
  int numPage = m_textParser->numPages();
270
3.43k
  if (m_graphParser->numPages() > numPage)
271
1
    numPage = m_graphParser->numPages();
272
3.43k
  m_state->m_numPages = numPage;
273
274
  // create the page list
275
3.43k
  MWAWPageSpan ps(getPageSpan());
276
3.43k
  long headerId, footerId;
277
3.43k
  m_textParser->getHeaderFooterId(headerId, footerId);
278
3.43k
  if (headerId) {
279
2.44k
    MWAWHeaderFooter header(MWAWHeaderFooter::HEADER, MWAWHeaderFooter::ALL);
280
2.44k
    header.m_subDocument.reset(new HanMacWrdKParserInternal::SubDocument
281
2.44k
                               (*this, getInput(), headerId));
282
2.44k
    ps.setHeaderFooter(header);
283
2.44k
  }
284
3.43k
  if (footerId) {
285
2.44k
    MWAWHeaderFooter footer(MWAWHeaderFooter::FOOTER, MWAWHeaderFooter::ALL);
286
2.44k
    footer.m_subDocument.reset(new HanMacWrdKParserInternal::SubDocument
287
2.44k
                               (*this, getInput(), footerId));
288
2.44k
    ps.setHeaderFooter(footer);
289
2.44k
  }
290
291
3.43k
  ps.setPageSpan(m_state->m_numPages+1);
292
3.43k
  std::vector<MWAWPageSpan> pageList(1,ps);
293
  //
294
3.43k
  MWAWTextListenerPtr listen(new MWAWTextListener(*getParserState(), pageList, documentInterface));
295
3.43k
  setTextListener(listen);
296
3.43k
  listen->startDocument();
297
3.43k
}
298
299
300
////////////////////////////////////////////////////////////
301
//
302
// Intermediate level
303
//
304
////////////////////////////////////////////////////////////
305
bool HanMacWrdKParser::createZones()
306
3.69k
{
307
3.69k
  if (!HanMacWrdKParser::readZonesList())
308
259
    return false;
309
310
3.43k
  libmwaw::DebugStream f;
311
3.43k
  for (auto const &it : m_state->m_zonesMap)
312
124k
    readZone(it.second);
313
124k
  for (auto const &it : m_state->m_zonesMap) {
314
124k
    std::shared_ptr<HanMacWrdKZone> const &zone = it.second;
315
124k
    if (!zone || !zone->valid() || zone->m_parsed)
316
116k
      continue;
317
8.51k
    f.str("");
318
8.51k
    f << "Entries(" << std::hex << zone->name() << std::dec << "):";
319
8.51k
    zone->ascii().addPos(0);
320
8.51k
    zone->ascii().addNote(f.str().c_str());
321
8.51k
  }
322
323
  // retrieve the text type and pass information to text parser
324
3.43k
  m_graphParser->prepareStructures();
325
3.43k
  auto idTypeMap = m_graphParser->getTextFrameInformations();
326
3.43k
  m_textParser->updateTextZoneTypes(idTypeMap);
327
328
3.43k
  return true;
329
3.69k
}
330
331
////////////////////////////////////////////////////////////
332
//
333
// Low level
334
//
335
////////////////////////////////////////////////////////////
336
bool HanMacWrdKParser::readZonesList()
337
3.69k
{
338
3.69k
  MWAWInputStreamPtr input = getInput();
339
3.69k
  if (m_state->m_zonesListBegin <= 0 || !input->checkPosition(m_state->m_zonesListBegin)) {
340
0
    MWAW_DEBUG_MSG(("HanMacWrdKParser::readZonesList: the list entry is not set \n"));
341
0
    return false;
342
0
  }
343
3.69k
  libmwaw::DebugStream f;
344
345
3.69k
  long debZone = m_state->m_zonesListBegin;
346
3.69k
  std::set<long> seeDebZone;
347
3.70k
  while (debZone) {
348
3.70k
    if (seeDebZone.find(debZone) != seeDebZone.end()) {
349
0
      MWAW_DEBUG_MSG(("HanMacWrdKParser::readZonesList: oops, we have already see this zone\n"));
350
0
      break;
351
0
    }
352
3.70k
    seeDebZone.insert(debZone);
353
3.70k
    long pos = debZone;
354
3.70k
    input->seek(pos, librevenge::RVNG_SEEK_SET);
355
3.70k
    auto numZones = int(input->readULong(1));
356
3.70k
    f.str("");
357
3.70k
    f << "Entries(Zones):";
358
3.70k
    f << "N=" << numZones << ",";
359
3.70k
    if (!numZones || !input->checkPosition(pos+16*(numZones+1))) {
360
149
      MWAW_DEBUG_MSG(("HanMacWrdKParser::readZonesList: can not read the number of zones\n"));
361
149
      ascii().addPos(pos);
362
149
      ascii().addNote(f.str().c_str());
363
149
      break;
364
149
    }
365
3.55k
    int val;
366
14.2k
    for (int i = 0; i < 3; i++) {
367
10.6k
      val = int(input->readLong(1));
368
10.6k
      if (val) f << "f" << i << "=" << val << ",";
369
10.6k
    }
370
3.55k
    auto ptr = long(input->readULong(4));
371
3.55k
    if (ptr != debZone) {
372
115
      MWAW_DEBUG_MSG(("HanMacWrdKParser::readZonesList: can not read the zone begin ptr\n"));
373
115
      f << "#ptr=" << std::hex << ptr << std::dec << ",";
374
115
      ascii().addPos(pos);
375
115
      ascii().addNote(f.str().c_str());
376
115
      break;
377
115
    }
378
3.43k
    auto nextPtr = long(input->readULong(4));
379
3.43k
    if (nextPtr) {
380
31
      f << "nextPtr=" << std::hex << nextPtr << std::dec;
381
31
      if (!input->checkPosition(nextPtr)) {
382
26
        MWAW_DEBUG_MSG(("HanMacWrdKParser::readZonesList: can not read the next zone begin ptr\n"));
383
26
        nextPtr = 0;
384
26
        f << "###";
385
26
      }
386
31
      f << ",";
387
31
    }
388
10.3k
    for (int i = 0; i < 2; i++) { // always 0,0?
389
6.87k
      val = int(input->readLong(2));
390
6.87k
      if (val) f << "f" << i+3 << "=" << val << ",";
391
6.87k
    }
392
3.43k
    ascii().addPos(pos);
393
3.43k
    ascii().addNote(f.str().c_str());
394
3.43k
    input->seek(pos+16, librevenge::RVNG_SEEK_SET);
395
396
128k
    for (int i = 0; i < numZones; i++) {
397
124k
      pos = input->tell();
398
124k
      f.str("");
399
124k
      std::shared_ptr<HanMacWrdKZone> zone(new HanMacWrdKZone(std::shared_ptr<libmwaw::DebugFile>(new libmwaw::DebugFile(MWAWInputStreamPtr()))));
400
124k
      zone->m_type = int(input->readLong(2));
401
124k
      val = int(input->readLong(2));
402
124k
      if (val) f << "f0=" << val << ",";
403
124k
      zone->setFileBeginPos(long(input->readULong(4)));
404
124k
      zone->m_id = long(input->readULong(4));
405
124k
      zone->m_subId = long(input->readULong(4));
406
124k
      zone->m_extra = f.str();
407
124k
      f.str("");
408
124k
      f << "Zones-" << i << ":" << *zone;
409
124k
      if (!input->checkPosition(ptr)) {
410
0
        MWAW_DEBUG_MSG(("HanMacWrdKParser::readZonesList: can not read the %d zone address\n", i));
411
0
        f << ",#Ptr";
412
0
      }
413
124k
      else
414
124k
        m_state->m_zonesMap.insert
415
124k
        (std::multimap<long,std::shared_ptr<HanMacWrdKZone> >::value_type(zone->m_id,zone));
416
124k
      ascii().addDelimiter(input->tell(), '|');
417
124k
      ascii().addPos(pos);
418
124k
      ascii().addNote(f.str().c_str());
419
124k
      input->seek(pos+16, librevenge::RVNG_SEEK_SET);
420
124k
    }
421
422
3.43k
    ascii().addPos(input->tell());
423
3.43k
    ascii().addNote("_");
424
3.43k
    if (!nextPtr) break;
425
5
    debZone = nextPtr;
426
5
  }
427
3.69k
  return m_state->m_zonesMap.size();
428
3.69k
}
429
430
bool HanMacWrdKParser::readZone(std::shared_ptr<HanMacWrdKZone> zone)
431
124k
{
432
124k
  if (!zone) {
433
0
    MWAW_DEBUG_MSG(("HanMacWrdKParser::readZone: can not find the zone\n"));
434
0
    return false;
435
0
  }
436
437
124k
  MWAWInputStreamPtr input = getInput();
438
124k
  libmwaw::DebugStream f;
439
124k
  long pos = zone->fileBeginPos();
440
124k
  input->seek(pos, librevenge::RVNG_SEEK_SET);
441
124k
  f << "Entries(" << zone->name() << "):";
442
124k
  auto n = int(input->readLong(2));
443
124k
  f << "n?=" << n << ",";
444
124k
  auto val = long(input->readLong(2));
445
124k
  if (val) f << "unkn=" << val << ",";
446
447
124k
  auto totalSz = long(input->readULong(4));
448
124k
  auto dataSz = long(input->readULong(4));
449
124k
  if (totalSz != dataSz+12 || !input->checkPosition(pos+totalSz)) {
450
96.1k
    MWAW_DEBUG_MSG(("HanMacWrdKParser::readZone: can not read the zone size\n"));
451
96.1k
    f << "###";
452
96.1k
    ascii().addPos(pos);
453
96.1k
    ascii().addNote(f.str().c_str());
454
96.1k
    return false;
455
96.1k
  }
456
28.6k
  zone->setFileLength(totalSz);
457
28.6k
  ascii().addPos(pos);
458
28.6k
  ascii().addNote(f.str().c_str());
459
460
28.6k
  decodeZone(zone);
461
28.6k
  if (!zone->valid())
462
3
    return false;
463
464
28.6k
  switch (zone->m_type) {
465
6.34k
  case 1:
466
6.34k
    if (m_textParser->readTextZone(zone))
467
6.34k
      return true;
468
0
    break;
469
344
  case 2:
470
344
    if (m_graphParser->readFrames(zone))
471
342
      return true;
472
2
    break;
473
3.16k
  case 3:
474
3.16k
    if (m_textParser->readStyles(zone))
475
729
      return true;
476
2.43k
    break;
477
2.88k
  case 4:
478
2.88k
    if (m_textParser->readSections(zone))
479
2.71k
      return true;
480
176
    break;
481
2.48k
  case 5:
482
2.48k
    if (m_textParser->readFontNames(zone))
483
1.74k
      return true;
484
741
    break;
485
1.77k
  case 6:
486
1.77k
    if (readZone6(zone))
487
1.32k
      return true;
488
443
    break;
489
1.70k
  case 7:
490
1.70k
    if (readPrintInfo(*zone))
491
1.31k
      return true;
492
390
    break;
493
1.93k
  case 8:
494
1.93k
    if (readZone8(zone))
495
1.76k
      return true;
496
163
    break;
497
163
  case 9:
498
79
    if (readFramesUnkn(zone))
499
66
      return true;
500
13
    break;
501
1.79k
  case 0xa:
502
1.79k
    if (readZonea(zone))
503
1.51k
      return true;
504
285
    break;
505
1.83k
  case 0xb:
506
1.83k
    if (readZoneb(*zone))
507
1.65k
      return true;
508
181
    break;
509
3.31k
  case 0xc:
510
3.31k
    if (readZonec(zone))
511
2.94k
      return true;
512
374
    MWAW_FALLTHROUGH;
513
467
  case 0xd:
514
467
    if (m_graphParser->readPicture(zone))
515
44
      return true;
516
423
    break;
517
937
  default:
518
937
    break;
519
28.6k
  }
520
  /** type1: text, type7: printInfo: typed: graphic */
521
6.19k
  f.str("");
522
6.19k
  f << zone->name() << "[data]:PTR=" << std::hex << zone->fileBeginPos() << std::dec << ",";
523
6.19k
  zone->ascii().addPos(0);
524
6.19k
  zone->ascii().addNote(f.str().c_str());
525
526
6.19k
  return true;
527
28.6k
}
528
529
// read the print info data
530
bool HanMacWrdKParser::readPrintInfo(HanMacWrdKZone &zone)
531
1.70k
{
532
1.70k
  long dataSz = zone.length();
533
1.70k
  MWAWInputStreamPtr input = zone.m_input;
534
1.70k
  libmwaw::DebugFile &asciiFile = zone.ascii();
535
1.70k
  long pos = zone.begin();
536
537
1.70k
  if (dataSz < 192 || !input->checkPosition(zone.end())) {
538
35
    MWAW_DEBUG_MSG(("HanMacWrdKParser::readPrintInfo: the zone seems too short\n"));
539
35
    return false;
540
35
  }
541
542
1.66k
  input->seek(pos, librevenge::RVNG_SEEK_SET);
543
1.66k
  libmwaw::DebugStream f;
544
1.66k
  zone.m_parsed = true;
545
546
1.66k
  f << zone.name() << "(A):PTR=" << std::hex << zone.fileBeginPos() << std::dec << ",";
547
1.66k
  long val;
548
1.66k
  f << "margins?=[";
549
1.66k
  float margins[4]; // L, T, R, B
550
6.67k
  for (auto &margin : margins) {
551
6.67k
    margin = float(input->readLong(4))/65536.f;
552
6.67k
    f << margin << ",";
553
6.67k
  }
554
1.66k
  f << "],";
555
1.66k
  int dim[4];
556
6.67k
  for (auto &d : dim) d=int(input->readLong(2));
557
1.66k
  f << "paper=[" << dim[1] << "x" << dim[0] << " " << dim[3] << "x" << dim[2] << "],";
558
1.66k
  val = long(input->readULong(2));
559
1.66k
  if (val != 1) f << "firstSectNumber=" << val << ",";
560
1.66k
  val = long(input->readULong(2));
561
1.66k
  if (val) f << "f0=" << val << ",";
562
563
  // after unknown
564
1.66k
  asciiFile.addDelimiter(input->tell(),'|');
565
1.66k
  asciiFile.addPos(pos);
566
1.66k
  asciiFile.addNote(f.str().c_str());
567
1.66k
  pos += 68;
568
1.66k
  input->seek(pos, librevenge::RVNG_SEEK_SET);
569
1.66k
  f.str("");
570
1.66k
  f << zone.name() << "(B):";
571
1.66k
  auto sz = long(input->readULong(4));
572
1.66k
  if (sz < 0x78) {
573
52
    MWAW_DEBUG_MSG(("HanMacWrdKParser::readPrintInfo: the print info data zone seems too short\n"));
574
52
    f << "###";
575
52
    asciiFile.addPos(pos);
576
52
    asciiFile.addNote(f.str().c_str());
577
52
    return false;
578
52
  }
579
580
  // print info
581
1.61k
  libmwaw::PrinterInfo info;
582
1.61k
  if (!info.read(input)) {
583
303
    f << "###";
584
303
    asciiFile.addPos(pos);
585
303
    asciiFile.addNote(f.str().c_str());
586
303
    return false;
587
303
  }
588
589
1.31k
  MWAWVec2i paperSize = info.paper().size();
590
1.31k
  MWAWVec2i pageSize = info.page().size();
591
592
1.31k
  bool useDocInfo = (float(dim[3]-dim[1])>margins[2]+margins[0]) &&
593
1.25k
                    (float(dim[2]-dim[0])>margins[3]+margins[1]);
594
1.31k
  bool usePrintInfo = pageSize.x() > 0 && pageSize.y() > 0 &&
595
1.22k
                      paperSize.x() > 0 && paperSize.y() > 0;
596
597
1.31k
  MWAWVec2f lTopMargin(margins[0],margins[1]), rBotMargin(margins[2],margins[3]);
598
  // define margin from print info
599
1.31k
  if (useDocInfo)
600
1.23k
    paperSize = MWAWVec2i(dim[3]-dim[1],dim[2]-dim[0]);
601
77
  else if (usePrintInfo) {
602
24
    lTopMargin= MWAWVec2f(-float(info.paper().pos(0)[0]), -float(info.paper().pos(0)[1]));
603
24
    rBotMargin= MWAWVec2f(info.paper().pos(1) - info.page().pos(1));
604
605
    // move margin left | top
606
24
    float decalX = lTopMargin.x() > 14 ? 14 : 0;
607
24
    float decalY = lTopMargin.y() > 14 ? 14 : 0;
608
24
    lTopMargin -= MWAWVec2f(decalX, decalY);
609
24
    rBotMargin += MWAWVec2f(decalX, decalY);
610
24
  }
611
612
  // decrease right | bottom
613
1.31k
  float rightMarg = rBotMargin.x() -10;
614
1.31k
  if (rightMarg < 0) rightMarg=0;
615
1.31k
  float botMarg = rBotMargin.y() -50;
616
1.31k
  if (botMarg < 0) botMarg=0;
617
618
1.31k
  if (useDocInfo || usePrintInfo) {
619
1.26k
    getPageSpan().setMarginTop(double(lTopMargin.y())/72.0);
620
1.26k
    getPageSpan().setMarginBottom(double(botMarg)/72.0);
621
1.26k
    getPageSpan().setMarginLeft(double(lTopMargin.x())/72.0);
622
1.26k
    getPageSpan().setMarginRight(double(rightMarg)/72.0);
623
1.26k
    getPageSpan().setFormLength(paperSize.y()/72.);
624
1.26k
    getPageSpan().setFormWidth(paperSize.x()/72.);
625
626
1.26k
    f << info;
627
1.26k
  }
628
53
  else
629
53
    f << "###";
630
631
1.31k
  asciiFile.addPos(pos);
632
1.31k
  asciiFile.addNote(f.str().c_str());
633
1.31k
  if (input->tell()!=zone.end()) {
634
1.28k
    asciiFile.addDelimiter(input->tell(),'|');
635
1.28k
    input->seek(zone.end(), librevenge::RVNG_SEEK_SET);
636
1.28k
  }
637
1.31k
  return true;
638
1.61k
}
639
640
// a small unknown zone: link to table, frame?
641
bool HanMacWrdKParser::readFramesUnkn(std::shared_ptr<HanMacWrdKZone> zone)
642
79
{
643
79
  if (!zone) {
644
0
    MWAW_DEBUG_MSG(("HanMacWrdKParser::readFramesUnkn: called without any zone\n"));
645
0
    return false;
646
0
  }
647
79
  long dataSz = zone->length();
648
79
  if (dataSz < 2) {
649
0
    MWAW_DEBUG_MSG(("HanMacWrdKParser::readFramesUnkn: the zone seems too short\n"));
650
0
    return false;
651
0
  }
652
653
79
  MWAWInputStreamPtr input = zone->m_input;
654
79
  libmwaw::DebugFile &asciiFile = zone->ascii();
655
79
  libmwaw::DebugStream f;
656
79
  zone->m_parsed = true;
657
658
79
  f << zone->name() << ":PTR=" << std::hex << zone->fileBeginPos() << std::dec << ",";
659
79
  input->seek(0, librevenge::RVNG_SEEK_SET);
660
79
  auto N= static_cast<int>(input->readLong(2)); // always find val=0, so :-~
661
79
  f << "N?=" << N << ",";
662
79
  long expectedSz = N*6+2;
663
79
  if (expectedSz != dataSz && expectedSz+1 != dataSz) {
664
13
    MWAW_DEBUG_MSG(("HanMacWrdKParser::readFramesUnkn: the zone size seems odd\n"));
665
13
    return false;
666
13
  }
667
66
  asciiFile.addPos(0);
668
66
  asciiFile.addNote(f.str().c_str());
669
670
66
  for (int i = 0; i < N; i++) {
671
0
    long pos = input->tell();
672
0
    f.str("");
673
0
    f << zone->name() << "-" << i << ":";
674
0
    long id = input->readLong(4);
675
0
    f << "id=" << std::hex << id << std::dec << ",";
676
0
    auto type = static_cast<int>(input->readLong(2));
677
0
    switch (type) {
678
0
    case 4:
679
0
      f << "textbox,";
680
0
      break;
681
0
    case 6:
682
0
      f << "picture,";
683
0
      break;
684
0
    case 8:
685
0
      f << "basicGraphic,";
686
0
      break;
687
0
    case 9:
688
0
      f << "table,";
689
0
      break;
690
0
    case 10:
691
0
      f << "textbox[withHeader],";
692
0
      break;
693
0
    case 11:
694
0
      f << "group";
695
0
      break;
696
0
    default:
697
0
      f << "#type=" << type << ",";
698
0
      break;
699
0
    }
700
0
    asciiFile.addPos(pos);
701
0
    asciiFile.addNote(f.str().c_str());
702
0
    input->seek(pos+6, librevenge::RVNG_SEEK_SET);
703
0
  }
704
66
  if (!input->isEnd())
705
66
    asciiFile.addDelimiter(input->tell(),'|');
706
66
  return true;
707
66
}
708
709
// a unknown zone
710
bool HanMacWrdKParser::readZone6(std::shared_ptr<HanMacWrdKZone> zone)
711
1.77k
{
712
1.77k
  if (!zone) {
713
0
    MWAW_DEBUG_MSG(("HanMacWrdKParser::readZone6: called without any zone\n"));
714
0
    return false;
715
0
  }
716
717
1.77k
  long dataSz = zone->length();
718
1.77k
  if (dataSz < 8) {
719
0
    MWAW_DEBUG_MSG(("HanMacWrdKParser::readZone6: the zone seems too short\n"));
720
0
    return false;
721
0
  }
722
723
1.77k
  MWAWInputStreamPtr input = zone->m_input;
724
1.77k
  libmwaw::DebugFile &asciiFile = zone->ascii();
725
1.77k
  libmwaw::DebugStream f;
726
1.77k
  zone->m_parsed = true;
727
1.77k
  long pos=0;
728
1.77k
  input->seek(pos, librevenge::RVNG_SEEK_SET);
729
730
  // no sure, checkme
731
4.81k
  for (int st = 0; st < 2; st++) {
732
3.49k
    pos = input->tell();
733
3.49k
    auto sz = long(input->readULong(4));
734
3.49k
    if (sz<0 || pos+sz+4 > dataSz) {
735
443
      MWAW_DEBUG_MSG(("HanMacWrdKParser::readZone6: zone%d ptr seems bad\n", st));
736
443
      return false;
737
443
    }
738
739
3.04k
    f.str("");
740
3.04k
    if (st==0)
741
1.72k
      f << zone->name() << "(A):PTR=" << std::hex << zone->fileBeginPos() << std::dec << ",";
742
1.32k
    else
743
1.32k
      f << zone->name() << "(B):";
744
745
3.04k
    asciiFile.addDelimiter(input->tell(),'|');
746
3.04k
    asciiFile.addPos(pos);
747
3.04k
    asciiFile.addNote(f.str().c_str());
748
3.04k
    input->seek(pos+4+sz, librevenge::RVNG_SEEK_SET);
749
3.04k
  }
750
1.32k
  return true;
751
1.77k
}
752
753
// a small unknown zone
754
bool HanMacWrdKParser::readZone8(std::shared_ptr<HanMacWrdKZone> zone)
755
1.93k
{
756
1.93k
  if (!zone) {
757
0
    MWAW_DEBUG_MSG(("HanMacWrdKParser::readZone8: called without any zone\n"));
758
0
    return false;
759
0
  }
760
1.93k
  long dataSz = zone->length();
761
1.93k
  if (dataSz < 78) {
762
163
    MWAW_DEBUG_MSG(("HanMacWrdKParser::readZone8: the zone seems too short\n"));
763
163
    return false;
764
163
  }
765
766
1.76k
  MWAWInputStreamPtr input = zone->m_input;
767
1.76k
  libmwaw::DebugFile &asciiFile = zone->ascii();
768
1.76k
  libmwaw::DebugStream f;
769
1.76k
  zone->m_parsed = true;
770
771
1.76k
  f << zone->name() << ":PTR=" << std::hex << zone->fileBeginPos() << std::dec << ",";
772
1.76k
  input->seek(0, librevenge::RVNG_SEEK_SET);
773
  // find f0=1 (N?), f3=1, f20=8, f22=6, f24=2, f26=144, f28=1, f30=1
774
70.7k
  for (int i = 0; i < 39; i++) {
775
68.9k
    long val = input->readLong(2);
776
68.9k
    if (val) f << "f" << i << "=" << val << ",";
777
68.9k
  }
778
779
1.76k
  asciiFile.addPos(0);
780
1.76k
  asciiFile.addNote(f.str().c_str());
781
1.76k
  if (!input->isEnd())
782
1.63k
    asciiFile.addDelimiter(input->tell(),'|');
783
1.76k
  return true;
784
1.93k
}
785
786
// a small unknown zone
787
bool HanMacWrdKParser::readZonea(std::shared_ptr<HanMacWrdKZone> zone)
788
1.79k
{
789
1.79k
  if (!zone) {
790
0
    MWAW_DEBUG_MSG(("HanMacWrdKParser::readZonea: called without any zone\n"));
791
0
    return false;
792
0
  }
793
1.79k
  long dataSz = zone->length();
794
1.79k
  if (dataSz < 114) {
795
285
    MWAW_DEBUG_MSG(("HanMacWrdKParser::readZonea: the zone seems too short\n"));
796
285
    return false;
797
285
  }
798
799
1.51k
  MWAWInputStreamPtr input = zone->m_input;
800
1.51k
  libmwaw::DebugFile &asciiFile = zone->ascii();
801
1.51k
  libmwaw::DebugStream f;
802
1.51k
  zone->m_parsed = true;
803
804
1.51k
  f << zone->name() << ":PTR=" << std::hex << zone->fileBeginPos() << std::dec << ",";
805
1.51k
  input->seek(0, librevenge::RVNG_SEEK_SET);
806
1.51k
  long val;
807
62.0k
  for (int i = 0; i < 40; i++) { // always 0 ?
808
60.5k
    val = input->readLong(2);
809
60.5k
    if (!val) continue;
810
300
    f << "f" << i << "=" << val << ",";
811
300
  }
812
6.05k
  for (int i = 0; i < 3; i++) { // g0=g1=g2=a665
813
4.53k
    val = long(input->readULong(2));
814
4.53k
    if (!val) continue;
815
4.47k
    f << "g" << i << "=" << std::hex << val << std::dec << ",";
816
4.47k
  }
817
22.6k
  for (int i = 0; i < 14; i++) { // h5=h6=h8=h9=-1
818
21.1k
    val = input->readLong(2);
819
21.1k
    if (!val) continue;
820
10.7k
    f << "h" << i << "=" << val << ",";
821
10.7k
  }
822
823
1.51k
  asciiFile.addPos(0);
824
1.51k
  asciiFile.addNote(f.str().c_str());
825
1.51k
  if (!input->isEnd())
826
1.04k
    asciiFile.addDelimiter(input->tell(),'|');
827
1.51k
  return true;
828
1.79k
}
829
830
// a small unknown zone
831
bool HanMacWrdKParser::readZoneb(HanMacWrdKZone &zone)
832
1.83k
{
833
1.83k
  long dataSz = zone.length();
834
1.83k
  MWAWInputStreamPtr input = zone.m_input;
835
1.83k
  libmwaw::DebugFile &asciiFile = zone.ascii();
836
1.83k
  long pos=zone.begin();
837
838
1.83k
  if (dataSz < 34 || !input->checkPosition(zone.end())) {
839
181
    MWAW_DEBUG_MSG(("HanMacWrdKParser::readZoneb: the zone seems too short\n"));
840
181
    return false;
841
181
  }
842
843
1.65k
  input->seek(pos, librevenge::RVNG_SEEK_SET);
844
1.65k
  libmwaw::DebugStream f;
845
1.65k
  zone.m_parsed = true;
846
847
1.65k
  f << zone.name() << ":PTR=" << std::hex << zone.fileBeginPos() << std::dec << ",";
848
849
1.65k
  long val = input->readLong(4); // 1c58b4
850
1.65k
  f << "dim?=" << float(val)/65536.f << ",";
851
852
8.27k
  for (int i = 0; i < 4; i++) { // always 7,7,0,0
853
6.61k
    val = input->readLong(2);
854
6.61k
    if (!val) continue;
855
3.49k
    f << "f" << i << "=" << val << ",";
856
3.49k
  }
857
1.65k
  val = input->readLong(4); // 2d5ab ~dim/10.
858
1.65k
  f << "dim2?=" << float(val)/65536.f << ",";
859
8.27k
  for (int i = 0; i < 4; i++) { // 0,4,0, 0
860
6.61k
    val = long(input->readULong(2));
861
6.61k
    if (!val) continue;
862
2.07k
    f << "g" << i << "=" << val << ",";
863
2.07k
  }
864
8.27k
  for (int i = 0; i < 4; i++) { // 1,1,1,0
865
6.61k
    val = input->readLong(1);
866
6.61k
    if (!val) continue;
867
4.94k
    f << "h" << i << "=" << val << ",";
868
4.94k
  }
869
6.61k
  for (int i = 0; i < 3; i++) { // always 6,0,0
870
4.96k
    val = input->readLong(2);
871
4.96k
    if (!val) continue;
872
2.24k
    f << "j" << i << "=" << val << ",";
873
2.24k
  }
874
1.65k
  if (dataSz >= 36) {
875
1.53k
    val = input->readLong(2);
876
1.53k
    if (val) f << "j3=" << val << ",";
877
1.53k
  }
878
879
1.65k
  asciiFile.addPos(pos);
880
1.65k
  asciiFile.addNote(f.str().c_str());
881
1.65k
  if (input->tell()!=zone.end()) {
882
1.44k
    asciiFile.addDelimiter(input->tell(),'|');
883
1.44k
    input->seek(zone.end(), librevenge::RVNG_SEEK_SET);
884
1.44k
  }
885
1.65k
  return true;
886
1.83k
}
887
888
// a small unknown zone
889
bool HanMacWrdKParser::readZonec(std::shared_ptr<HanMacWrdKZone> zone)
890
3.31k
{
891
3.31k
  if (!zone) {
892
0
    MWAW_DEBUG_MSG(("HanMacWrdKParser::readZonec: called without any zone\n"));
893
0
    return false;
894
0
  }
895
3.31k
  long dataSz = zone->length();
896
3.31k
  if (dataSz < 52) {
897
374
    MWAW_DEBUG_MSG(("HanMacWrdKParser::readZonec: the zone seems too short\n"));
898
374
    return false;
899
374
  }
900
901
2.94k
  MWAWInputStreamPtr input = zone->m_input;
902
2.94k
  libmwaw::DebugFile &asciiFile = zone->ascii();
903
2.94k
  libmwaw::DebugStream f;
904
2.94k
  zone->m_parsed = true;
905
906
2.94k
  f << zone->name() << ":PTR=" << std::hex << zone->fileBeginPos() << std::dec << ",";
907
2.94k
  input->seek(0, librevenge::RVNG_SEEK_SET);
908
2.94k
  long val = input->readLong(2); // 1|4
909
2.94k
  if (val != 1) f << "f0=" << val << ",";
910
17.6k
  for (int j = 0; j < 5; j++) { // always 0 expect f2=0|800
911
14.7k
    val = input->readLong(2);
912
14.7k
    if (val) f << "f" << j+1 << "=" << val << ",";
913
14.7k
  }
914
2.94k
  f << "id=" << std::hex << input->readULong(4) << std::dec << ",";
915
20.6k
  for (int j = 0; j < 6; j++) { // always 0
916
17.6k
    val = input->readLong(2);
917
17.6k
    if (val) f << "g" << j << "=" << val << ",";
918
17.6k
  }
919
  // two similar number: selection?
920
2.94k
  long sel[2];
921
5.88k
  for (auto &s : sel) s = input->readLong(4);
922
2.94k
  if (sel[0] || sel[1]) {
923
2.82k
    f << "sel?=" << sel[0];
924
2.82k
    if (sel[1] != sel[0]) f << "<->" << sel[1] << ",";
925
2.82k
    f << ",";
926
2.82k
  }
927
26.4k
  for (int j = 0; j < 8; j++) { // always 0
928
23.5k
    val = input->readLong(2);
929
23.5k
    if (val) f << "h" << j << "=" << val << ",";
930
23.5k
  }
931
2.94k
  asciiFile.addDelimiter(input->tell(),'|');
932
2.94k
  asciiFile.addPos(0);
933
2.94k
  asciiFile.addNote(f.str().c_str());
934
935
2.94k
  input->seek(52, librevenge::RVNG_SEEK_SET);
936
2.94k
  return true;
937
3.31k
}
938
////////////////////////////////////////////////////////////
939
// code to uncompress a zone
940
////////////////////////////////////////////////////////////
941
/* implementation of a basic splay tree to decode a block
942
   freely inspired from: ftp://ftp.cs.uiowa.edu/pub/jones/compress/minunsplay.c :
943
944
   Author: Douglas Jones, Dept. of Comp. Sci., U. of Iowa, Iowa City, IA 52242.
945
   Date: Nov. 5, 1990.
946
         (derived from the Feb. 14 1990 version by stripping out irrelevancies)
947
         (minor revision of Feb. 20, 1989 to add exit(0) at end of program).
948
         (minor revision of Nov. 14, 1988 to detect corrupt input better).
949
         (minor revision of Aug. 8, 1988 to eliminate unused vars, fix -c).
950
   Copyright:  This material is derived from code Copyrighted 1988 by
951
         Jeffrey Chilton and Douglas Jones.  That code contained a copyright
952
         notice allowing copying for personal or research purposes, so long
953
         as copies of the code were not sold for direct commercial advantage.
954
         This version of the code has been stripped of most of the material
955
         added by Jeff Chilton, and this release of the code may be used or
956
         copied for any purpose, public or private.
957
   Patents:  The algorithm central to this code is entirely the invention of
958
         Douglas Jones, and it has not been patented.  Any patents claiming
959
         to cover this material are invalid.
960
   Exportability:  Splay-tree based compression algorithms may be used for
961
         cryptography, and when used as such, they may not be exported from
962
         the United States without appropriate approval.  All cryptographic
963
         features of the original version of this code have been removed.
964
   Language: C
965
   Purpose: Data uncompression program, a companion to minsplay.c
966
   Algorithm: Uses a splay-tree based prefix code.  For a full understanding
967
          of the operation of this data compression scheme, refer to the paper
968
          "Applications of Splay Trees to Data Compression" by Douglas W. Jones
969
          in Communications of the ACM, Aug. 1988, pages 996-1007.
970
*/
971
std::shared_ptr<HanMacWrdKZone> HanMacWrdKParser::decodeZone(std::shared_ptr<HanMacWrdKZone> zone)
972
28.6k
{
973
28.6k
  if (!zone || zone->fileBeginPos()+12 >= zone->fileEndPos()) {
974
3
    MWAW_DEBUG_MSG(("HanMacWrdKParser::decodeZone: called with an invalid zone\n"));
975
3
    return zone;
976
3
  }
977
28.6k
  short const maxChar=256;
978
28.6k
  short const maxSucc=maxChar+1;
979
28.6k
  short const twoMaxChar=2*maxChar+1;
980
28.6k
  short const twoMaxSucc=2*maxSucc;
981
982
  // first build the tree data
983
28.6k
  short left[maxSucc];
984
28.6k
  short right[maxSucc];
985
28.6k
  short up[twoMaxSucc];
986
14.7M
  for (short i = 0; i <= twoMaxChar; ++i)
987
14.7M
    up[i] = i/2;
988
7.40M
  for (short j = 0; j <= maxChar; ++j) {
989
7.37M
    left[j] = short(2 * j);
990
7.37M
    right[j] = short(2 * j + 1);
991
7.37M
  }
992
993
28.6k
  short const root = 0;
994
28.6k
  short const sizeBit = 8;
995
28.6k
  short const highBit=128; /* mask for the most sig bit of 8 bit byte */
996
997
28.6k
  short bitbuffer = 0;       /* buffer to hold a byte for unpacking bits */
998
28.6k
  short bitcounter = 0;  /* count of remaining bits in buffer */
999
1000
28.6k
  MWAWInputStreamPtr input = getInput();
1001
28.6k
  input->seek(zone->fileBeginPos()+12, librevenge::RVNG_SEEK_SET);
1002
28.6k
  librevenge::RVNGBinaryData &dt = zone->getBinaryData();
1003
44.8M
  while (!input->isEnd() && input->tell() < zone->fileEndPos()) {
1004
44.7M
    short a = root;
1005
44.7M
    bool ok = true;
1006
86.2M
    do {  /* once for each bit on path */
1007
86.2M
      if (bitcounter == 0) {
1008
10.8M
        if (input->isEnd() || input->tell() >= zone->fileEndPos()) {
1009
1.09k
          MWAW_DEBUG_MSG(("HanMacWrdKParser::decodeZone: find some uncomplete data for zone%lx\n", static_cast<long unsigned int>(zone->fileBeginPos())));
1010
1.09k
          dt.append(static_cast<unsigned char>(a));
1011
1.09k
          ok = false;
1012
1.09k
          break;
1013
1.09k
        }
1014
1015
10.8M
        bitbuffer = short(input->readULong(1));
1016
10.8M
        bitcounter = sizeBit;
1017
10.8M
      }
1018
86.2M
      --bitcounter;
1019
86.2M
      if ((bitbuffer & highBit) != 0)
1020
39.1M
        a = right[a];
1021
47.1M
      else
1022
47.1M
        a = left[a];
1023
86.2M
      bitbuffer = short(bitbuffer << 1);
1024
86.2M
    }
1025
86.2M
    while (a <= maxChar);
1026
44.7M
    if (!ok)
1027
1.09k
      break;
1028
44.7M
    dt.append(static_cast<unsigned char>(a - maxSucc));
1029
1030
    /* now splay tree about leaf a */
1031
61.0M
    do {    /* walk up the tree semi-rotating pairs of nodes */
1032
61.0M
      short c;
1033
61.0M
      if ((c = up[a]) != root) {      /* a pair remains */
1034
24.3M
        short d = up[c];
1035
24.3M
        short b = left[d];
1036
24.3M
        if (c == b) {
1037
13.5M
          b = right[d];
1038
13.5M
          right[d] = a;
1039
13.5M
        }
1040
10.7M
        else
1041
10.7M
          left[d] = a;
1042
24.3M
        if (left[c] == a)
1043
13.2M
          left[c] = b;
1044
11.0M
        else
1045
11.0M
          right[c] = b;
1046
24.3M
        up[a] = d;
1047
24.3M
        up[b] = c;
1048
24.3M
        a = d;
1049
24.3M
      }
1050
36.7M
      else
1051
36.7M
        a = c;
1052
61.0M
    }
1053
61.0M
    while (a != root);
1054
44.7M
  }
1055
28.6k
  if (dt.size()==0) {
1056
0
    MWAW_DEBUG_MSG(("HanMacWrdKParser::decodeZone: oops an empty zone\n"));
1057
0
    zone.reset();
1058
0
    return zone;
1059
0
  }
1060
1061
28.6k
  zone->m_input=MWAWInputStream::get(zone->getBinaryData(), false);
1062
28.6k
  if (!zone->m_input) {
1063
0
    MWAW_DEBUG_MSG(("HanMacWrdKParser::decodeZone: can not find my input\n"));
1064
0
    zone.reset();
1065
0
    return zone;
1066
0
  }
1067
1068
28.6k
  zone->m_input->seek(0,librevenge::RVNG_SEEK_SET);
1069
28.6k
  zone->ascii().setStream(zone->m_input);
1070
28.6k
  static int fId = 0;
1071
28.6k
  std::stringstream s;
1072
28.6k
  s << zone->name() << "-" << fId++;
1073
28.6k
  zone->ascii().open(s.str());
1074
1075
28.6k
  ascii().skipZone(zone->fileBeginPos()+12, zone->fileEndPos()-1);
1076
28.6k
  return zone;
1077
28.6k
}
1078
1079
////////////////////////////////////////////////////////////
1080
// read the header
1081
////////////////////////////////////////////////////////////
1082
bool HanMacWrdKParser::checkHeader(MWAWHeader *header, bool strict)
1083
12.8k
{
1084
12.8k
  *m_state = HanMacWrdKParserInternal::State();
1085
1086
12.8k
  MWAWInputStreamPtr input = getInput();
1087
12.8k
  if (!input || !input->hasDataFork())
1088
2
    return false;
1089
12.8k
  libmwaw::DebugStream f;
1090
12.8k
  f << "FileHeader:";
1091
12.8k
  long const headerSize=0x33c;
1092
12.8k
  if (!input->checkPosition(headerSize)) {
1093
60
    MWAW_DEBUG_MSG(("HanMacWrdKParser::checkHeader: file is too short\n"));
1094
60
    return false;
1095
60
  }
1096
12.8k
  input->seek(0,librevenge::RVNG_SEEK_SET);
1097
12.8k
  int head[3];
1098
12.8k
  for (int &i : head)
1099
38.4k
    i = static_cast<int>(input->readULong(2));
1100
12.8k
  if (head[0] != 0x4859 || head[1] != 0x4c53 || head[2] != 0x0210)
1101
160
    return false;
1102
12.6k
  auto val = static_cast<int>(input->readLong(1));
1103
12.6k
  if (val==1) f << "hasPassword,";
1104
12.6k
  else if (val) {
1105
107
    if (strict) return false;
1106
52
    f << "#hasPassword=" << val << ",";
1107
52
  }
1108
12.5k
  val = static_cast<int>(input->readLong(1));
1109
12.5k
  if (val) {
1110
208
    if (strict && (val<0||val>2)) return false;
1111
141
    f << "f0=" << val << ",";
1112
141
  }
1113
1114
12.5k
  m_state->m_zonesListBegin = static_cast<int>(input->readULong(4)); // always 0x042c ?
1115
12.5k
  if (m_state->m_zonesListBegin<0x14 || !input->checkPosition(m_state->m_zonesListBegin))
1116
169
    return false;
1117
12.3k
  if (m_state->m_zonesListBegin < 0x33c) {
1118
2
    MWAW_DEBUG_MSG(("HanMacWrdKParser::checkHeader: the header size seems short\n"));
1119
2
  }
1120
12.3k
  f << "zonesBeg=" << std::hex << m_state->m_zonesListBegin << std::dec << ",";
1121
12.3k
  auto fLength = long(input->readULong(4));
1122
12.3k
  if (fLength < m_state->m_zonesListBegin)
1123
78
    return false;
1124
12.2k
  if (!input->checkPosition(fLength)) {
1125
4.28k
    if (!input->checkPosition(fLength/2)) return false;
1126
4.07k
    MWAW_DEBUG_MSG(("HanMacWrdKParser::checkHeader: file seems incomplete, try to continue\n"));
1127
4.07k
    f << "#len=" << std::hex << fLength << std::dec << ",";
1128
4.07k
  }
1129
12.0k
  auto tLength = long(input->readULong(4));
1130
12.0k
  f << "textLength=" << tLength << ",";
1131
12.0k
  ascii().addPos(0);
1132
12.0k
  ascii().addNote(f.str().c_str());
1133
1134
12.0k
  long pos;
1135
  // title, subject, author, revision, remark, [2 documents tags], mail:
1136
12.0k
  int const fieldSizes[] = { 128, 128, 32, 32, 256, 40, 64, 64, 64 };
1137
118k
  for (int i = 0; i < 9; i++) {
1138
106k
    pos=input->tell();
1139
106k
    if (i == 5) {
1140
11.7k
      ascii().addPos(pos);
1141
11.7k
      ascii().addNote("FileHeader[DocTags]:");
1142
11.7k
      input->seek(pos+fieldSizes[i], librevenge::RVNG_SEEK_SET);
1143
11.7k
      continue;
1144
11.7k
    }
1145
94.7k
    auto fSz = static_cast<int>(input->readULong(1));
1146
94.7k
    if (fSz >= fieldSizes[i]) {
1147
2.85k
      if (strict)
1148
458
        return false;
1149
2.39k
      MWAW_DEBUG_MSG(("HanMacWrdKParser::checkHeader: can not read field size %i\n", i));
1150
2.39k
      ascii().addPos(pos);
1151
2.39k
      ascii().addNote("FileHeader#");
1152
2.39k
      input->seek(pos+fieldSizes[i], librevenge::RVNG_SEEK_SET);
1153
2.39k
      continue;
1154
2.85k
    }
1155
91.8k
    f.str("");
1156
91.8k
    if (fSz == 0)
1157
45.9k
      f << "_";
1158
45.9k
    else {
1159
45.9k
      std::string name("");
1160
639k
      for (int c = 0; c < fSz; c++)
1161
593k
        name+=char(input->readULong(1));
1162
45.9k
      f.str("");
1163
45.9k
      f << "FileHeader[field"<<i<< "]:" << name;
1164
45.9k
    }
1165
91.8k
    ascii().addPos(pos);
1166
91.8k
    ascii().addNote(f.str().c_str());
1167
91.8k
    input->seek(pos+fieldSizes[i], librevenge::RVNG_SEEK_SET);
1168
91.8k
  }
1169
11.6k
  pos=input->tell();
1170
11.6k
  f.str("");
1171
11.6k
  f << "FileHeader(B):"; // 240(K) bytes
1172
11.6k
  ascii().addPos(pos);
1173
11.6k
  ascii().addNote(f.str().c_str());
1174
1175
11.6k
  input->seek(m_state->m_zonesListBegin, librevenge::RVNG_SEEK_SET);
1176
11.6k
  if (header)
1177
4.21k
    header->reset(MWAWDocument::MWAW_T_HANMACWORDK, 1);
1178
1179
11.6k
  return true;
1180
12.0k
}
1181
1182
////////////////////////////////////////////////////////////
1183
// HanMacWrdKZone
1184
////////////////////////////////////////////////////////////
1185
HanMacWrdKZone::HanMacWrdKZone(MWAWInputStreamPtr const &input, libmwaw::DebugFile &asciiFile)
1186
0
  : m_type(-1)
1187
0
  , m_id(-1)
1188
0
  , m_subId(-1)
1189
0
  , m_input(input)
1190
0
  , m_extra("")
1191
0
  , m_parsed(false)
1192
0
  , m_filePos(-1)
1193
0
  , m_endFilePos(-1)
1194
0
  , m_data()
1195
0
  , m_asciiFile(&asciiFile)
1196
0
  , m_asciiFilePtr()
1197
0
{
1198
0
}
1199
1200
HanMacWrdKZone::HanMacWrdKZone(std::shared_ptr<libmwaw::DebugFile> const &asciiFile)
1201
124k
  : m_type(-1)
1202
124k
  , m_id(-1)
1203
124k
  , m_subId(-1)
1204
124k
  , m_input()
1205
124k
  , m_extra("")
1206
124k
  , m_parsed(false)
1207
124k
  , m_filePos(-1)
1208
124k
  , m_endFilePos(-1)
1209
124k
  , m_data()
1210
124k
  , m_asciiFile(asciiFile.get())
1211
124k
  , m_asciiFilePtr(asciiFile)
1212
124k
{
1213
124k
}
1214
1215
HanMacWrdKZone::~HanMacWrdKZone()
1216
124k
{
1217
124k
  if (m_asciiFilePtr)
1218
124k
    ascii().reset();
1219
124k
}
1220
1221
std::ostream &operator<<(std::ostream &o, HanMacWrdKZone const &zone)
1222
0
{
1223
0
  o << zone.name();
1224
0
  if (zone.m_id > 0) o << "[" << std::hex << zone.m_id << std::dec << "]";
1225
0
  if (zone.m_subId > 0) o << "[subId=" << std::hex << zone.m_subId << std::dec << "]";
1226
0
  if (zone.m_extra.length()) o << "," << zone.m_extra;
1227
0
  return o;
1228
0
}
1229
1230
std::string HanMacWrdKZone::name(int type)
1231
279k
{
1232
279k
  switch (type) {
1233
87.2k
  case 1:
1234
87.2k
    return "TextZone";
1235
1.13k
  case 2:
1236
1.13k
    return "FrameDef";
1237
25.8k
  case 3:
1238
25.8k
    return "Style";
1239
12.5k
  case 4:
1240
12.5k
    return "Section";
1241
15.7k
  case 5:
1242
15.7k
    return "FontsName";
1243
8.62k
  case 7:
1244
8.62k
    return "PrintInfo";
1245
3.01k
  case 9:
1246
3.01k
    return "FrameExt";
1247
401
  case 0xd:
1248
401
    return "Picture";
1249
124k
  default:
1250
124k
    break;
1251
279k
  }
1252
124k
  std::stringstream s;
1253
124k
  s << "Zone" << std::hex << type << std::dec;
1254
124k
  return s.str();
1255
279k
}
1256
1257
// vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: