Coverage Report

Created: 2026-03-12 06:42

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libmwaw/src/lib/DocMkrParser.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 <set>
38
#include <sstream>
39
40
#include <librevenge/librevenge.h>
41
42
#include "MWAWTextListener.hxx"
43
#include "MWAWFontConverter.hxx"
44
#include "MWAWHeader.hxx"
45
#include "MWAWPictData.hxx"
46
#include "MWAWPosition.hxx"
47
#include "MWAWPrinter.hxx"
48
#include "MWAWRSRCParser.hxx"
49
#include "MWAWSubDocument.hxx"
50
51
#include "DocMkrText.hxx"
52
53
#include "DocMkrParser.hxx"
54
55
/** Internal: the structures of a DocMkrParser */
56
namespace DocMkrParserInternal
57
{
58
////////////////////////////////////////
59
//! Internal: store a picture information in DocMkrParser
60
struct PictInfo {
61
  //! constructor
62
  PictInfo()
63
0
    : m_id(-1)
64
0
    , m_sndId(-1)
65
0
    , m_align(1)
66
0
    , m_print(false)
67
0
    , m_invert(false)
68
0
    , m_action(0)
69
0
    , m_actionString("")
70
0
    , m_extra("")
71
0
  {
72
0
    for (auto &next : m_next) next=0;
73
0
  }
74
  //! operator<<
75
  friend std::ostream &operator<<(std::ostream &o, PictInfo const &info);
76
  //! the picture id
77
  int m_id;
78
  //! the sound id
79
  int m_sndId;
80
  //! the alignment ( 1:center, ... )
81
  int m_align;
82
  //! true if the picture is printed
83
  bool m_print;
84
  //! true if we must invert the picture
85
  bool m_invert;
86
  //! the action
87
  int m_action;
88
  //! the action string
89
  std::string m_actionString;
90
  //! the next chapter/paragraph position for goChapter
91
  int m_next[2];
92
  //! the applescript type
93
  std::string m_appleScript[3];
94
  //! extra data
95
  std::string m_extra;
96
};
97
98
std::ostream &operator<<(std::ostream &o, PictInfo const &info)
99
0
{
100
0
  if (info.m_id >= 0) o << "pictId=" << info.m_id << ",";
101
0
  switch (info.m_align) {
102
0
  case 1:
103
0
    o << "center,";
104
0
    break;
105
0
  case 2:
106
0
    o << "left,";
107
0
    break;
108
0
  case 3:
109
0
    o << "right,";
110
0
    break;
111
0
  default:
112
0
    o << "#align=" << info.m_align << ",";
113
0
    break;
114
0
  }
115
0
  if (info.m_action >= 0 && info.m_action <= 16) {
116
0
    static char const* const wh[]= {
117
0
      "", "goTo", "aboutDialog", "print", "quit", "launch", "sound", "QMOV",
118
0
      "note", "export[asText]", "last[chapter]", "TOC[show]", "find", "appleEvent",
119
0
      "next[chapter]", "prev[chapter]", "script"
120
0
    };
121
0
    o << wh[info.m_action];
122
0
  }
123
0
  else
124
0
    o << "#action=" << info.m_action << ",";
125
0
  switch (info.m_action) {
126
0
  case 1:
127
0
    o << "[chapter=" << info.m_next[0];
128
0
    if (info.m_next[1]) o << ",para=" << info.m_next[1] << "]";
129
0
    else o << "]";
130
0
    break;
131
0
  case 5:
132
0
  case 7:
133
0
  case 8:
134
0
  case 0x10:
135
0
    o << "[" << info.m_actionString << "]";
136
0
    break;
137
0
  case 6:
138
0
    o << "[id=" << info.m_sndId << "]";
139
0
    break;
140
0
  case 0xd:
141
0
    o << "[appli=" << info.m_appleScript[0] << ",class=" << info.m_appleScript[1]
142
0
      << ",eventid=" << info.m_appleScript[2];
143
0
    if (info.m_actionString.size())
144
0
      o << ",data=" <<info.m_actionString;
145
0
    o << "]";
146
0
    break;
147
0
  default:
148
0
    break;
149
0
  }
150
0
  o << "],";
151
0
  if (!info.m_print) o << "noPrint,";
152
0
  if (info.m_invert) o << "invert,";
153
0
  o << info.m_extra;
154
0
  return o;
155
0
}
156
////////////////////////////////////////
157
//! Internal: the state of a DocMkrParser
158
struct State {
159
  //! constructor
160
  State()
161
2.64k
    : m_idPictEntryMap()
162
2.64k
    , m_idPictInfoMap()
163
2.64k
    , m_zonePictInfoUnit(100)
164
2.64k
    , m_actPage(0)
165
2.64k
    , m_numPages(0)
166
2.64k
    , m_headerHeight(0)
167
2.64k
    , m_footerHeight(0)
168
2.64k
  {
169
2.64k
  }
170
  //! return a pictinfo id corresponding to a zone and a local if
171
  int pictInfoId(int zId, int lId) const
172
11
  {
173
11
    return (zId+2)*m_zonePictInfoUnit+lId;
174
11
  }
175
  //! try to find the picture info unit (fixme: a hack)
176
  void findPictInfoUnit(int nZones);
177
  //! a map id->pictEntry
178
  std::map<int,MWAWEntry> m_idPictEntryMap;
179
  //! a map id->pictInfo
180
  std::map<int,PictInfo> m_idPictInfoMap;
181
  //! the zone unit to retrieve pictInfo
182
  int m_zonePictInfoUnit;
183
  int m_actPage /** the actual page */, m_numPages /** the number of page of the final document */;
184
185
  int m_headerHeight /** the header height if known */,
186
      m_footerHeight /** the footer height if known */;
187
};
188
189
void State::findPictInfoUnit(int nZones)
190
314
{
191
314
  if (m_idPictInfoMap.empty())
192
314
    return;
193
0
  bool is100=true, is1000=true;
194
0
  for (auto const &it : m_idPictInfoMap) {
195
0
    int id=it.first;
196
0
    if (id > (nZones+3)*100 || id < 200)
197
0
      is100=false;
198
0
    if (id > (nZones+3)*1000 || id < 2000)
199
0
      is1000=false;
200
0
  }
201
0
  if (is100 && !is1000)
202
0
    m_zonePictInfoUnit=100;
203
0
  else if (is1000 && !is100)
204
0
    m_zonePictInfoUnit=1000;
205
0
  else {
206
0
    MWAW_DEBUG_MSG(("DocMkrParserInternal::State::findPictInfoUnit can not find unit\n"));
207
0
  }
208
0
}
209
}
210
211
////////////////////////////////////////////////////////////
212
// constructor/destructor, ...
213
////////////////////////////////////////////////////////////
214
DocMkrParser::DocMkrParser(MWAWInputStreamPtr const &input, MWAWRSRCParserPtr const &rsrcParser, MWAWHeader *header)
215
1.10k
  : MWAWTextParser(input, rsrcParser, header)
216
1.10k
  , m_state()
217
1.10k
  , m_textParser()
218
1.10k
{
219
1.10k
  init();
220
1.10k
}
221
222
DocMkrParser::~DocMkrParser()
223
1.10k
{
224
1.10k
}
225
226
void DocMkrParser::init()
227
1.10k
{
228
1.10k
  resetTextListener();
229
230
1.10k
  m_state.reset(new DocMkrParserInternal::State);
231
232
1.10k
  m_textParser.reset(new DocMkrText(*this));
233
1.10k
}
234
235
MWAWInputStreamPtr DocMkrParser::rsrcInput()
236
2.39k
{
237
2.39k
  return getRSRCParser()->getInput();
238
2.39k
}
239
240
libmwaw::DebugFile &DocMkrParser::rsrcAscii()
241
1.81k
{
242
1.81k
  return getRSRCParser()->ascii();
243
1.81k
}
244
245
////////////////////////////////////////////////////////////
246
// new page
247
////////////////////////////////////////////////////////////
248
void DocMkrParser::newPage(int number)
249
215k
{
250
215k
  if (number <= m_state->m_actPage || number > m_state->m_numPages)
251
214
    return;
252
253
431k
  while (m_state->m_actPage < number) {
254
215k
    m_state->m_actPage++;
255
215k
    if (!getTextListener() || m_state->m_actPage == 1)
256
214
      continue;
257
215k
    getTextListener()->insertBreak(MWAWTextListener::PageBreak);
258
215k
  }
259
215k
}
260
261
////////////////////////////////////////////////////////////
262
// the parser
263
////////////////////////////////////////////////////////////
264
void DocMkrParser::parse(librevenge::RVNGTextInterface *docInterface)
265
434
{
266
434
  if (!getInput().get() || !getRSRCParser() || !checkHeader(nullptr))  throw(libmwaw::ParseException());
267
434
  bool ok = false;
268
434
  try {
269
434
    checkHeader(nullptr);
270
434
    ok = createZones();
271
434
    if (ok) {
272
314
      createDocument(docInterface);
273
314
      m_textParser->sendMainText();
274
314
      m_textParser->sendTOC();
275
#ifdef DEBUG
276
      m_textParser->flushExtra();
277
      flushExtra();
278
#endif
279
314
    }
280
434
    ascii().reset();
281
434
  }
282
434
  catch (...) {
283
0
    MWAW_DEBUG_MSG(("DocMkrParser::parse: exception catched when parsing\n"));
284
0
    ok = false;
285
0
  }
286
287
434
  resetTextListener();
288
434
  if (!ok) throw(libmwaw::ParseException());
289
434
}
290
291
////////////////////////////////////////////////////////////
292
// create the document
293
////////////////////////////////////////////////////////////
294
void DocMkrParser::createDocument(librevenge::RVNGTextInterface *documentInterface)
295
314
{
296
314
  if (!documentInterface) return;
297
314
  if (getTextListener()) {
298
0
    MWAW_DEBUG_MSG(("DocMkrParser::createDocument: listener already exist\n"));
299
0
    return;
300
0
  }
301
302
  // update the page
303
314
  m_state->m_actPage = 0;
304
305
  // create the page list
306
314
  std::vector<MWAWPageSpan> pageList;
307
314
  m_textParser->updatePageSpanList(pageList);
308
314
  m_state->m_numPages = int(pageList.size());
309
310
  //
311
314
  MWAWTextListenerPtr listen(new MWAWTextListener(*getParserState(), pageList, documentInterface));
312
314
  setTextListener(listen);
313
314
  listen->startDocument();
314
314
}
315
316
317
////////////////////////////////////////////////////////////
318
//
319
// Intermediate level
320
//
321
////////////////////////////////////////////////////////////
322
bool DocMkrParser::createZones()
323
434
{
324
434
  MWAWRSRCParserPtr rsrcParser = getRSRCParser();
325
434
  auto const &entryMap = rsrcParser->getEntriesMap();
326
327
434
  if (!m_textParser->createZones())
328
120
    return false;
329
  // the different pict zones
330
314
  auto it = entryMap.lower_bound("PICT");
331
628
  while (it != entryMap.end()) {
332
628
    if (it->first != "PICT")
333
314
      break;
334
314
    MWAWEntry const &entry = it++->second;
335
314
    m_state->m_idPictEntryMap[entry.id()]=entry;
336
314
  }
337
314
  it = entryMap.lower_bound("conp"); // local picture 5000-...?
338
5.94k
  while (it != entryMap.end()) {
339
5.94k
    if (it->first != "conp")
340
314
      break;
341
5.63k
    MWAWEntry const &entry = it++->second;
342
5.63k
    librevenge::RVNGBinaryData data;
343
5.63k
    rsrcParser->parsePICT(entry, data);
344
5.63k
  }
345
314
  it = entryMap.lower_bound("pInf"); // 201|202,301..309,401..410,501..
346
314
  while (it != entryMap.end()) {
347
314
    if (it->first != "pInf")
348
314
      break;
349
0
    MWAWEntry const &entry = it++->second;
350
0
    readPictInfo(entry);
351
0
  }
352
353
  // chapiter name STR 2000..
354
  // entry 0: copyright
355
314
  it = entryMap.lower_bound("Dk@P");
356
627
  while (it != entryMap.end()) {
357
627
    if (it->first != "Dk@P")
358
314
      break;
359
313
    MWAWEntry const &entry = it++->second;
360
313
    std::string str;
361
313
    rsrcParser->parseSTR(entry, str);
362
313
  }
363
314
  it = entryMap.lower_bound("sTwD");
364
623
  while (it != entryMap.end()) {
365
623
    if (it->first != "sTwD")
366
314
      break;
367
309
    MWAWEntry const &entry = it++->second;
368
309
    readSTwD(entry);
369
309
  }
370
314
  it = entryMap.lower_bound("xtr2");
371
628
  while (it != entryMap.end()) {
372
390
    if (it->first != "xtr2")
373
76
      break;
374
314
    MWAWEntry const &entry = it++->second;
375
314
    readXtr2(entry);
376
314
  }
377
  //  1000:docname, 1001:footer name, 2001-... chapter name, others ...
378
314
  it = entryMap.lower_bound("STR ");
379
1.25k
  while (it != entryMap.end()) {
380
1.25k
    if (it->first != "STR ")
381
314
      break;
382
942
    MWAWEntry const &entry = it++->second;
383
942
    std::string str;
384
942
    rsrcParser->parseSTR(entry, str);
385
942
  }
386
387
314
  m_state->findPictInfoUnit(m_textParser->numChapters());
388
389
#ifdef DEBUG_WITH_FILES
390
  // get rid of the default application resource
391
  libmwaw::DebugFile &ascFile = rsrcAscii();
392
  static char const* const appliRsrc[]= {
393
    // default, Dialog (3000: DLOG,DITL,DLGX,dctb","ictb","STR ")
394
    "ALRT","BNDL","CNTL","CURS","CDEF", "DLOG","DLGX","DITL","FREF","ICON", "ICN#","MENU","SIZE",
395
    "crsr","dctb","icl4","icl8","ics4", "ics8","ics#","ictb","snd ",
396
    // local
397
    "mstr" /* menu string */, "aete" /* some function name?*/
398
  };
399
  for (int r=0; r < 13+9+2; r++) {
400
    it = entryMap.lower_bound(appliRsrc[r]);
401
    while (it != entryMap.end()) {
402
      if (it->first != appliRsrc[r])
403
        break;
404
      MWAWEntry const &entry = it++->second;
405
      if (entry.isParsed()) continue;
406
      entry.setParsed(true);
407
      ascFile.skipZone(entry.begin()-4,entry.end()-1);
408
    }
409
  }
410
#endif
411
314
  return true;
412
434
}
413
414
void DocMkrParser::flushExtra()
415
0
{
416
0
  MWAWRSRCParserPtr rsrcParser = getRSRCParser();
417
0
  for (auto const &it : m_state->m_idPictEntryMap) {
418
0
    MWAWEntry const &entry=it.second;
419
0
    if (entry.isParsed()) continue;
420
0
    librevenge::RVNGBinaryData data;
421
0
    rsrcParser->parsePICT(entry,data);
422
0
  }
423
0
}
424
425
////////////////////////////////////////////////////////////
426
//
427
// Low level
428
//
429
////////////////////////////////////////////////////////////
430
bool DocMkrParser::sendPicture(int zId, int lId, double /*lineW*/)
431
11
{
432
11
  int pictId=m_state->pictInfoId(zId,lId);
433
11
  auto it=m_state->m_idPictInfoMap.find(pictId);
434
11
  if (it==m_state->m_idPictInfoMap.end()) {
435
11
    MWAW_DEBUG_MSG(("DocMkrText::sendPicture: can not find picture for zone=%d, id=%d\n",zId,lId));
436
11
    return false;
437
11
  }
438
0
  DocMkrParserInternal::PictInfo const &info=it->second;
439
0
  if (m_state->m_idPictEntryMap.find(info.m_id)==m_state->m_idPictEntryMap.end()) {
440
0
    MWAW_DEBUG_MSG(("DocMkrText::sendPicture: can not find picture for id=%d\n",info.m_id));
441
0
    return false;
442
0
  }
443
0
  if (!getTextListener()) {
444
0
    MWAW_DEBUG_MSG(("DocMkrText::sendPicture: can not find the listener\n"));
445
0
    return false;
446
0
  }
447
448
0
  if (info.m_action==8 && info.m_actionString.size())
449
0
    m_textParser->sendComment(info.m_actionString);
450
0
  MWAWInputStreamPtr input = rsrcInput();
451
0
  MWAWRSRCParserPtr rsrcParser = getRSRCParser();
452
0
  MWAWEntry const &entry=m_state->m_idPictEntryMap.find(info.m_id)->second;
453
454
0
  librevenge::RVNGBinaryData data;
455
0
  long pos = input->tell();
456
0
  rsrcParser->parsePICT(entry,data);
457
0
  input->seek(pos,librevenge::RVNG_SEEK_SET);
458
459
0
  auto dataSz=int(data.size());
460
0
  if (!dataSz) {
461
0
    return false;
462
0
  }
463
0
  MWAWInputStreamPtr pictInput=MWAWInputStream::get(data, false);
464
0
  if (!pictInput) {
465
0
    MWAW_DEBUG_MSG(("DocMkrText::sendPicture: oops can not find an input\n"));
466
0
    return false;
467
0
  }
468
0
  MWAWBox2f box;
469
0
  auto res = MWAWPictData::check(pictInput, dataSz,box);
470
0
  if (res == MWAWPict::MWAW_R_BAD) {
471
0
    MWAW_DEBUG_MSG(("DocMkrText::sendPicture: can not find the picture\n"));
472
0
    return false;
473
0
  }
474
0
  pictInput->seek(0,librevenge::RVNG_SEEK_SET);
475
0
  std::shared_ptr<MWAWPict> thePict(MWAWPictData::get(pictInput, dataSz));
476
0
  MWAWPosition pictPos=MWAWPosition(MWAWVec2f(0,0),box.size(), librevenge::RVNG_POINT);
477
0
  auto xpos= (info.m_align==1) ? MWAWPosition::XCenter :
478
0
             (info.m_align==3) ? MWAWPosition::XRight  : MWAWPosition::XLeft;
479
0
  pictPos.setRelativePosition(MWAWPosition::Paragraph, xpos);
480
0
  pictPos.m_wrapping = MWAWPosition::WRunThrough;
481
0
  if (thePict) {
482
0
    MWAWEmbeddedObject picture;
483
0
    if (thePict->getBinary(picture))
484
0
      getTextListener()->insertPicture(pictPos, picture);
485
0
  }
486
0
  return true;
487
0
}
488
489
bool DocMkrParser::readPictInfo(MWAWEntry const &entry)
490
0
{
491
0
  long length = entry.length();
492
0
  if (!entry.valid() || length<8) {
493
0
    MWAW_DEBUG_MSG(("DocMkrText::readPictInfo: the entry seems very short\n"));
494
0
    return false;
495
0
  }
496
497
0
  entry.setParsed(true);
498
0
  long pos = entry.begin();
499
0
  long endPos = entry.end();
500
0
  MWAWInputStreamPtr input = rsrcInput();
501
0
  libmwaw::DebugFile &ascFile = rsrcAscii();
502
0
  input->seek(pos, librevenge::RVNG_SEEK_SET);
503
504
0
  libmwaw::DebugStream f;
505
0
  DocMkrParserInternal::PictInfo info;
506
0
  info.m_id = static_cast<int>(input->readULong(2));
507
0
  info.m_align = static_cast<int>(input->readLong(2));
508
0
  auto val =static_cast<int>(input->readLong(2)); // 0|1
509
0
  if (val) f << "unkn=" << val << ",";
510
511
0
  auto action =static_cast<int>(input->readLong(2)); // 0..b
512
0
  auto extraN = int(endPos-input->tell());
513
0
  if (action < 0) {
514
0
    info.m_invert=true;
515
0
    action = -action;
516
0
  }
517
0
  info.m_action=action;
518
0
  switch (action) {
519
0
  case 1:
520
0
    if (extraN < 2) {
521
0
      f << "actionArg##,";
522
0
      break;
523
0
    }
524
0
    info.m_next[0]=static_cast<int>(input->readLong(2));
525
0
    if (extraN < 4)
526
0
      break;
527
0
    info.m_next[1]=static_cast<int>(input->readLong(2));
528
0
    break;
529
0
  case 5:
530
0
  case 7:
531
0
  case 8:
532
0
  case 0x10: {
533
0
    if (extraN < 1) {
534
0
      f << "actionArg##,";
535
0
    }
536
0
    auto fSz=static_cast<int>(input->readULong(1));
537
0
    if (extraN < fSz+1) {
538
0
      f << "##[N=" << fSz << "],";
539
0
      break;
540
0
    }
541
0
    std::string name("");
542
0
    for (int i = 0; i < fSz; i++)
543
0
      name += char(input->readULong(1));
544
0
    info.m_actionString=name;
545
0
    break;
546
0
  }
547
0
  case 6: {
548
0
    if (extraN < 4) {
549
0
      f << "actionArg##,";
550
0
      break;
551
0
    }
552
0
    info.m_sndId=static_cast<int>(input->readULong(2));
553
0
    val = static_cast<int>(input->readULong(2)); // loop?
554
0
    if (val)
555
0
      f << "sndFlag=" << val << ",";
556
0
    break;
557
0
  }
558
0
  case 0xd: {
559
0
    if (extraN < 13) {
560
0
      f << "actionArg##,";
561
0
      break;
562
0
    }
563
0
    for (auto &w : info.m_appleScript) {
564
0
      std::string name("");
565
0
      for (int i = 0; i < 4; i++)
566
0
        name += char(input->readULong(1));
567
0
      w=name;
568
0
    }
569
0
    auto fSz=static_cast<int>(input->readULong(1));
570
0
    if (extraN < fSz+13) {
571
0
      f << "##[N=" << fSz << "],";
572
0
      break;
573
0
    }
574
0
    std::string name("");
575
0
    for (int i = 0; i < fSz; i++)
576
0
      name += char(input->readULong(1));
577
0
    info.m_actionString=name;
578
0
    break;
579
0
  }
580
0
  default:
581
0
    break;
582
0
  }
583
0
  extraN = int(endPos-input->tell())/2;
584
0
  if (extraN==1) {
585
0
    val =static_cast<int>(input->readLong(2));
586
0
    if (val==0)
587
0
      info.m_print = false;
588
0
    else if (val==1)
589
0
      info.m_print = true;
590
0
    else if (val) {
591
0
      f << "#print=" << val << ",";
592
0
    }
593
0
  }
594
0
  else {
595
0
    for (int i = 0; i < extraN; i++) { // g0=0|1
596
0
      val =static_cast<int>(input->readLong(2));
597
0
      if (val)
598
0
        f << "#g" << i << "=" << val << ",";
599
0
    }
600
0
  }
601
0
  info.m_extra=f.str();
602
0
  m_state->m_idPictInfoMap[entry.id()]=info;
603
0
  f.str("");
604
0
  f << "Entries(PctInfo)[" << entry.type() << "-" << entry.id() << "]:" << info;
605
606
0
  if (input->tell()!=entry.end())
607
0
    ascFile.addDelimiter(input->tell(),'|');
608
0
  ascFile.addPos(pos-4);
609
0
  ascFile.addNote(f.str().c_str());
610
0
  return true;
611
0
}
612
613
////////////////////////////////////////////////////////////
614
// read some unknown zone
615
////////////////////////////////////////////////////////////
616
bool DocMkrParser::readSTwD(MWAWEntry const &entry)
617
309
{
618
309
  if (!entry.valid() || entry.length()<10) {
619
138
    MWAW_DEBUG_MSG(("DocMkrText::readSTwD: the entry seems very short\n"));
620
138
    return false;
621
138
  }
622
623
171
  entry.setParsed(true);
624
171
  long pos = entry.begin();
625
171
  MWAWInputStreamPtr input = rsrcInput();
626
171
  libmwaw::DebugFile &ascFile = rsrcAscii();
627
171
  input->seek(pos, librevenge::RVNG_SEEK_SET);
628
629
171
  libmwaw::DebugStream f;
630
171
  f << "Entries(STwD)[" << entry.type() << "-" << entry.id() << "]:";
631
171
  int val;
632
513
  for (int i=0; i < 2; i++) { // f0=2, f1=1|2
633
342
    val =static_cast<int>(input->readLong(2));
634
342
    if (val)
635
188
      f << "f" << i << "=" << val << ",";
636
342
  }
637
171
  auto flag =static_cast<int>(input->readLong(2)); // 320|7d0|1388 ?
638
171
  f << "fl=" << std::hex << flag << std::dec << ",";
639
171
  f << "dim=" << static_cast<int>(input->readLong(2)) << ","; // 0x1Fa|0x200
640
513
  for (int i=0; i < 2; i++) { // f0=1, f1=0|1
641
342
    val =static_cast<int>(input->readLong(1));
642
342
    if (val)
643
172
      f << "f" << i+2 << "=" << val << ",";
644
342
  }
645
171
  f << "],";
646
171
  if (input->tell()!=entry.end())
647
162
    ascFile.addDelimiter(input->tell(),'|');
648
171
  ascFile.addPos(pos-4);
649
171
  ascFile.addNote(f.str().c_str());
650
171
  return true;
651
309
}
652
653
bool DocMkrParser::readXtr2(MWAWEntry const &entry)
654
314
{
655
314
  if (!entry.valid() || entry.length()<1) {
656
134
    MWAW_DEBUG_MSG(("DocMkrText::readXtr2: the entry seems very short\n"));
657
134
    return false;
658
134
  }
659
660
180
  entry.setParsed(true);
661
180
  long pos = entry.begin();
662
180
  MWAWInputStreamPtr input = rsrcInput();
663
180
  libmwaw::DebugFile &ascFile = rsrcAscii();
664
180
  input->seek(pos, librevenge::RVNG_SEEK_SET);
665
666
180
  libmwaw::DebugStream f;
667
180
  f << "Entries(Xtr2)[" << entry.type() << "-" << entry.id() << "]:";
668
180
  int N=1;
669
180
  if (entry.length() != 1) {
670
171
    MWAW_DEBUG_MSG(("DocMkrText::readXtr2: find more than one flag\n"));
671
171
    N = entry.length()>20 ? 20 : int(entry.length());
672
171
  }
673
  // f0=79|a8|b9|99
674
3.59k
  for (int i=0; i < N; i++) {
675
3.41k
    auto val =static_cast<int>(input->readULong(1));
676
3.41k
    if (val)
677
2.40k
      f << "f" << i << "=" << std::hex << val << std::dec << ",";
678
3.41k
  }
679
180
  if (input->tell()!=entry.end())
680
170
    ascFile.addDelimiter(input->tell(),'|');
681
180
  ascFile.addPos(pos-4);
682
180
  ascFile.addNote(f.str().c_str());
683
180
  return true;
684
314
}
685
686
////////////////////////////////////////////////////////////
687
// read the header
688
////////////////////////////////////////////////////////////
689
bool DocMkrParser::checkHeader(MWAWHeader *header, bool /*strict*/)
690
1.53k
{
691
1.53k
  *m_state = DocMkrParserInternal::State();
692
  /** no data fork, may be ok, but this means
693
      that the file contains no text, so... */
694
1.53k
  MWAWInputStreamPtr input = getInput();
695
1.53k
  if (!input || !getRSRCParser())
696
96
    return false;
697
1.44k
  if (input->hasDataFork()) {
698
0
    MWAW_DEBUG_MSG(("DocMkrParser::checkHeader: find a datafork, odd!!!\n"));
699
0
  }
700
1.44k
  MWAWRSRCParser::Version vers;
701
  // read the Docmaker version
702
1.44k
  int docmakerVersion = 1;
703
1.44k
  MWAWEntry entry = getRSRCParser()->getEntry("vers", 2);
704
1.44k
  if (entry.valid() && getRSRCParser()->parseVers(entry, vers))
705
238
    docmakerVersion = vers.m_majorVersion;
706
1.20k
  else  {
707
1.20k
    MWAW_DEBUG_MSG(("DocMkrParser::checkHeader: can not find the DocMaker version\n"));
708
1.20k
  }
709
1.44k
  setVersion(docmakerVersion);
710
1.44k
  if (header)
711
573
    header->reset(MWAWDocument::MWAW_T_DOCMAKER, version());
712
713
1.44k
  return true;
714
1.53k
}
715
716
// vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: