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 <algorithm>
35 #include <iomanip>
36 #include <iostream>
37 #include <limits>
38 #include <map>
39 #include <sstream>
40 
41 #include <librevenge/librevenge.h>
42 
43 #include "MWAWTextListener.hxx"
44 #include "MWAWFont.hxx"
45 #include "MWAWFontConverter.hxx"
46 #include "MWAWHeader.hxx"
47 #include "MWAWParagraph.hxx"
48 #include "MWAWPictData.hxx"
49 #include "MWAWPosition.hxx"
50 #include "MWAWPrinter.hxx"
51 #include "MWAWRSRCParser.hxx"
52 #include "MWAWSubDocument.hxx"
53 
54 #include "libmwaw_internal.hxx"
55 
56 #include "MacDocParser.hxx"
57 
58 /** Internal: the structures of a MacDocParser */
59 namespace MacDocParserInternal
60 {
61 ////////////////////////////////////////
62 //! Internal: the index data of a MacDocParser
63 struct Index {
64   //! constructor
IndexMacDocParserInternal::Index65   Index()
66     : m_entry()
67     , m_level(0)
68     , m_numChild(0)
69     , m_page(0)
70     , m_box()
71     , m_extra("")
72   {
73   }
74   //! operator<<
operator <<(std::ostream & o,Index const & index)75   friend std::ostream &operator<<(std::ostream &o, Index const &index)
76   {
77     if (index.m_level) o << "level=" << index.m_level << ",";
78     if (index.m_page) o << "page=" << index.m_page << ",";
79     o << "box=" << index.m_box << ",";
80     if (index.m_numChild) o << "numChild=" << index.m_numChild << ",";
81     o << index.m_extra;
82     return o;
83   }
84   //! the text entry
85   MWAWEntry m_entry;
86   //! the entry level
87   int m_level;
88   //! the number of child
89   int m_numChild;
90   //! the page
91   int m_page;
92   //! the bdbox
93   MWAWBox2i m_box;
94   //! extra data
95   std::string m_extra;
96 };
97 
98 ////////////////////////////////////////
99 //! Internal: the state of a MacDocParser
100 struct State {
101   //! constructor
StateMacDocParserInternal::State102   State()
103     : m_idPictureMap()
104     , m_indexList()
105     , m_idFontMap()
106     , m_actPage(0)
107     , m_numPages(0)
108   {
109   }
110   //! the picture page map
111   std::map<int,MWAWEntry> m_idPictureMap;
112   //! the index list
113   std::vector<Index> m_indexList;
114   //! a map id to index font
115   std::map<int, MWAWFont> m_idFontMap;
116   int m_actPage /** the actual page */, m_numPages /** the number of page of the final document */;
117 };
118 
119 }
120 
121 ////////////////////////////////////////////////////////////
122 // constructor/destructor, ...
123 ////////////////////////////////////////////////////////////
MacDocParser(MWAWInputStreamPtr const & input,MWAWRSRCParserPtr const & rsrcParser,MWAWHeader * header)124 MacDocParser::MacDocParser(MWAWInputStreamPtr const &input, MWAWRSRCParserPtr const &rsrcParser, MWAWHeader *header)
125   : MWAWTextParser(input, rsrcParser, header)
126   , m_state()
127 {
128   init();
129 }
130 
~MacDocParser()131 MacDocParser::~MacDocParser()
132 {
133 }
134 
init()135 void MacDocParser::init()
136 {
137   resetTextListener();
138 
139   m_state.reset(new MacDocParserInternal::State);
140 
141   // no margins ( ie. the document is a set of picture corresponding to each page )
142   getPageSpan().setMargins(0.01);
143 }
144 
rsrcInput()145 MWAWInputStreamPtr MacDocParser::rsrcInput()
146 {
147   return getRSRCParser()->getInput();
148 }
149 
rsrcAscii()150 libmwaw::DebugFile &MacDocParser::rsrcAscii()
151 {
152   return getRSRCParser()->ascii();
153 }
154 
155 ////////////////////////////////////////////////////////////
156 // new page
157 ////////////////////////////////////////////////////////////
newPage(int number)158 void MacDocParser::newPage(int number)
159 {
160   if (number <= m_state->m_actPage || number > m_state->m_numPages)
161     return;
162 
163   while (m_state->m_actPage < number) {
164     m_state->m_actPage++;
165     if (!getTextListener() || m_state->m_actPage == 1)
166       continue;
167     getTextListener()->insertBreak(MWAWTextListener::PageBreak);
168   }
169 }
170 
171 ////////////////////////////////////////////////////////////
172 // the parser
173 ////////////////////////////////////////////////////////////
parse(librevenge::RVNGTextInterface * docInterface)174 void MacDocParser::parse(librevenge::RVNGTextInterface *docInterface)
175 {
176   if (!getInput().get() || !getRSRCParser() || !checkHeader(nullptr))  throw(libmwaw::ParseException());
177   bool ok = false;
178   try {
179     checkHeader(nullptr);
180     ok = createZones();
181     if (ok) {
182       createDocument(docInterface);
183       sendContents();
184     }
185     ascii().reset();
186   }
187   catch (...) {
188     MWAW_DEBUG_MSG(("MacDocParser::parse: exception catched when parsing\n"));
189     ok = false;
190   }
191 
192   resetTextListener();
193   if (!ok) throw(libmwaw::ParseException());
194 }
195 
196 ////////////////////////////////////////////////////////////
197 // create the document
198 ////////////////////////////////////////////////////////////
createDocument(librevenge::RVNGTextInterface * documentInterface)199 void MacDocParser::createDocument(librevenge::RVNGTextInterface *documentInterface)
200 {
201   if (!documentInterface) return;
202   if (getTextListener()) {
203     MWAW_DEBUG_MSG(("MacDocParser::createDocument: listener already exist\n"));
204     return;
205   }
206 
207   // update the page
208   m_state->m_actPage = 0;
209 
210   // create the page list
211   auto numPages = int(m_state->m_idPictureMap.size());
212   if (!m_state->m_indexList.empty())
213     numPages++;
214   MWAWPageSpan ps(getPageSpan());
215   ps.setPageSpan(numPages+1);
216   std::vector<MWAWPageSpan> pageList(1,ps);
217   //
218   MWAWTextListenerPtr listen(new MWAWTextListener(*getParserState(), pageList, documentInterface));
219   setTextListener(listen);
220   listen->startDocument();
221 }
222 
223 
224 ////////////////////////////////////////////////////////////
225 //
226 // Intermediate level
227 //
228 ////////////////////////////////////////////////////////////
createZones()229 bool MacDocParser::createZones()
230 {
231   MWAWRSRCParserPtr rsrcParser = getRSRCParser();
232   auto &entryMap = rsrcParser->getEntriesMap();
233 
234   // the index font zone: 1001, ...
235   auto it = entryMap.lower_bound("MDLv");
236   while (it != entryMap.end()) {
237     if (it->first != "MDLv")
238       break;
239     MWAWEntry const &entry = it++->second;
240     readFont(entry);
241   }
242   // index zone: 1 MDIx
243   it = entryMap.lower_bound("MDIx");
244   while (it != entryMap.end()) {
245     if (it->first != "MDIx")
246       break;
247     MWAWEntry const &entry = it++->second;
248     readIndex(entry);
249   }
250   // bookmark zone: Mdbk 1, ...
251   it = entryMap.lower_bound("MDbk");
252   while (it != entryMap.end()) {
253     if (it->first != "MDbk")
254       break;
255     MWAWEntry const &entry = it++->second;
256     readBookmark(entry);
257   }
258   // doc preference MDop:128 crypted ?
259 
260   // the picture zone: 1, ...
261   bool pageSizeSet=false;
262   it = entryMap.lower_bound("MDpg");
263   while (it != entryMap.end()) {
264     if (it->first != "MDpg")
265       break;
266     MWAWEntry const &entry = it++->second;
267     m_state->m_idPictureMap[entry.id()]=entry;
268     if (!pageSizeSet) {
269       // as we do not read MDop, use picture to find page size
270       librevenge::RVNGBinaryData data;
271       if (!getRSRCParser()->parsePICT(entry, data))
272         continue;
273       MWAWInputStreamPtr pictInput=MWAWInputStream::get(data, false);
274       if (!pictInput)
275         continue;
276       MWAWBox2f box;
277       auto res = MWAWPictData::check(pictInput,static_cast<int>(data.size()), box);
278       if (res != MWAWPict::MWAW_R_BAD && box.size()[0]>0 && box.size()[1]>0) {
279         pageSizeSet=true;
280         getPageSpan().setFormWidth(double(box.size()[0])/72.);
281         getPageSpan().setFormLength(double(box.size()[1])/72.);
282       }
283     }
284   }
285   // windows pos? 128
286   it = entryMap.lower_bound("MDwp");
287   while (it != entryMap.end()) {
288     if (it->first != "MDwp")
289       break;
290     MWAWEntry const &entry = it++->second;
291     readWP(entry);
292   }
293 
294 #ifdef DEBUG_WITH_FILES
295   // the file zone: 1, ...
296   it = entryMap.lower_bound("MDfi");
297   while (it != entryMap.end()) {
298     if (it->first != "MDfi")
299       break;
300     MWAWEntry const &entry = it++->second;
301     readFile(entry);
302   }
303 
304   // get rid of the default application resource
305   libmwaw::DebugFile &ascFile = rsrcAscii();
306   static char const *appliRsrc[]= {
307     "ALRT","BNDL","CNTL","CURS","CDEF", "CODE","DLOG","DLGX","DITL","FREF",
308     "ICON","ICN#","MENU","MBAR","MDEF", "SIZE","TMPL","WIND",
309     "acur","cicn","crsr","dctb","icl4", "icl8","ics4","ics8","ics#","ictb",
310     "mstr","snd ",
311     "DATA", "MDsr" /* srd: version string */
312   };
313   for (int r=0; r < 18+12+2; ++r) {
314     it = entryMap.lower_bound(appliRsrc[r]);
315     while (it != entryMap.end()) {
316       if (it->first != appliRsrc[r])
317         break;
318       MWAWEntry const &entry = it++->second;
319       if (entry.isParsed()) continue;
320       entry.setParsed(true);
321       ascFile.skipZone(entry.begin()-4,entry.end()-1);
322     }
323   }
324 #endif
325 
326   return !m_state->m_idPictureMap.empty();
327 }
328 
329 
sendContents()330 bool MacDocParser::sendContents()
331 {
332   MWAWTextListenerPtr listener=getTextListener();
333   if (!listener) {
334     MWAW_DEBUG_MSG(("MacDocParser::sendContents: can not find the listener\n"));
335     return false;
336   }
337   int actPage=0;
338   if (sendIndex())
339     newPage(++actPage);
340   listener->setParagraph(MWAWParagraph());
341   for (auto &it : m_state->m_idPictureMap) {
342     sendPicture(it.second);
343     newPage(++actPage);
344   }
345   return true;
346 }
347 
348 ////////////////////////////////////////////////////////////
349 //
350 // Low level
351 //
352 ////////////////////////////////////////////////////////////
353 
354 // font
readFont(MWAWEntry const & entry)355 bool MacDocParser::readFont(MWAWEntry const &entry)
356 {
357   MWAWInputStreamPtr input = rsrcInput();
358   if (entry.length()<12 || !input || !input->checkPosition(entry.end())) {
359     MWAW_DEBUG_MSG(("MacDocParser::readFont: the entry seems bad\n"));
360     return false;
361   }
362 
363   entry.setParsed(true);
364   input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
365   libmwaw::DebugFile &ascFile = rsrcAscii();
366   libmwaw::DebugStream f;
367   auto fSz=static_cast<int>(input->readULong(1));
368   if (fSz<0 || 1+long(fSz)+1-(fSz%2)+10>entry.length()) {
369     f << "Entries(Font):###fSz=" << fSz;
370     ascFile.addPos(entry.begin()-4);
371     ascFile.addNote(f.str().c_str());
372     return false;
373   }
374   MWAWFont font;
375   std::string name("");
376   for (int i=0; i<fSz; i++)
377     name+=char(input->readLong(1));
378   font.setId(getParserState()->m_fontConverter->getId(name));
379   if ((fSz%2)==0)
380     input->seek(1, librevenge::RVNG_SEEK_CUR);
381   font.setSize(float(input->readULong(2)));
382   auto flag = static_cast<int>(input->readULong(2));
383   uint32_t flags=0;
384   if (flag&0x1) flags |= MWAWFont::boldBit;
385   if (flag&0x2) flags |= MWAWFont::italicBit;
386   if (flag&0x4) font.setUnderlineStyle(MWAWFont::Line::Simple);
387   if (flag&0x8) flags |= MWAWFont::embossBit;
388   if (flag&0x10) flags |= MWAWFont::shadowBit;
389   if (flag&0x20) font.setDeltaLetterSpacing(-1);
390   if (flag&0x40) font.setDeltaLetterSpacing(1);
391   if (flag&0x80) f << "#flag0[0x80],";
392   font.setFlags(flags);
393   unsigned char col[3];
394   for (auto &c : col) c=static_cast<unsigned char>(input->readULong(2)>>8);
395   font.setColor(MWAWColor(col[0],col[1],col[2]));
396   font.m_extra = f.str();
397   f.str("");
398   f << "Entries(Font)[" << entry.id() << "]:"
399     << font.getDebugString(getParserState()->m_fontConverter);
400   m_state->m_idFontMap[entry.id()-999]=font;
401   ascFile.addPos(entry.begin()-4);
402   ascFile.addNote(f.str().c_str());
403   return true;
404 }
405 
406 //
407 // index functions
408 //
readIndex(MWAWEntry const & entry)409 bool MacDocParser::readIndex(MWAWEntry const &entry)
410 {
411   if (entry.length()<4) {
412     MWAW_DEBUG_MSG(("MacDocParser::readIndex: the entry seems bad\n"));
413     return false;
414   }
415   if (entry.id()!=1) {
416     MWAW_DEBUG_MSG(("MacDocParser::readIndex: the entry id seems bad\n"));
417   }
418   entry.setParsed(true);
419   MWAWInputStreamPtr input = rsrcInput();
420   input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
421 
422   libmwaw::DebugFile &ascFile = rsrcAscii();
423   ascFile.addPos(entry.begin()-4);
424   ascFile.addNote("Entries(Index)");
425   libmwaw::DebugStream f;
426   long pos;
427   while (!input->isEnd()) {
428     pos=input->tell();
429     if (pos+21>=entry.end())
430       break;
431 
432     f.str("");
433     MacDocParserInternal::Index index;
434     auto val=static_cast<int>(input->readLong(2));
435     if (val) f << "#f0=" << val << ",";
436     index.m_page=static_cast<int>(input->readLong(2));
437     if (index.m_page<=0) {
438       input->seek(pos, librevenge::RVNG_SEEK_SET);
439       break;
440     }
441     int dim[4];
442     for (auto &d : dim) d=static_cast<int>(input->readLong(2));
443     index.m_box=MWAWBox2i(MWAWVec2i(dim[1],dim[0]),MWAWVec2i(dim[3],dim[2]));
444     val=static_cast<int>(input->readLong(2));
445     if (val) f << "#f1=" << val << ",";
446     index.m_numChild=static_cast<int>(input->readLong(2));
447     for (int i=0; i<2; ++i) {
448       val=static_cast<int>(input->readLong(2));
449       if (val) f << "#f" << i+2 << "=" << val << ",";
450     }
451     index.m_extra=f.str();
452     f.str("");
453     f << "Index:" << index;
454     index.m_entry.setBegin(input->tell());
455     std::string name("");
456     bool ok=false;
457     while (!input->isEnd()) {
458       if (input->tell()>=entry.end())
459         break;
460       auto c=char(input->readLong(1));
461       if (c==0) {
462         ok = true;
463         break;
464       }
465       name+=c;
466     }
467     if (!ok) {
468       input->seek(pos, librevenge::RVNG_SEEK_SET);
469       break;
470     }
471     index.m_entry.setEnd(input->tell()-1);
472     m_state->m_indexList.push_back(index);
473     f << name;
474     ascFile.addPos(pos);
475     ascFile.addNote(f.str().c_str());
476   }
477   f.str("");
478   f << "Index[end]:";
479   pos=input->tell();
480   if (pos!=entry.end()-4) {
481     MWAW_DEBUG_MSG(("MacDocParser::readIndex: problem reading end\n"));
482     f << "###";
483   }
484   ascFile.addPos(pos);
485   ascFile.addNote(f.str().c_str());
486   return true;
487 }
488 
updateIndex(int actIndex,int actLevel)489 int MacDocParser::updateIndex(int actIndex, int actLevel)
490 {
491   auto numIndex=static_cast<int>(m_state->m_indexList.size());
492   if (actIndex < 0 || actIndex >= numIndex) {
493     MWAW_DEBUG_MSG(("MacDocParser::updateIndex: the actual index seems bad\n"));
494     return -1;
495   }
496   auto &index =  m_state->m_indexList[size_t(actIndex++)];
497   index.m_level=actLevel;
498   for (int c=0; c < index.m_numChild; ++c) {
499     actIndex=updateIndex(actIndex, actLevel+1);
500     if (actIndex==-1)
501       break;
502   }
503   return actIndex;
504 }
505 
sendIndex()506 bool MacDocParser::sendIndex()
507 {
508   MWAWTextListenerPtr listener=getTextListener();
509   if (!listener) {
510     MWAW_DEBUG_MSG(("MacDocParser::sendIndex: can not find the listener\n"));
511     return false;
512   }
513   if (m_state->m_indexList.empty())
514     return false;
515   int id=0;
516   auto numIndex=size_t(m_state->m_indexList.size());
517   do
518     id=updateIndex(id,1);
519   while (id>0 && id < static_cast<int>(numIndex));
520   listener->setFont(MWAWFont(3,12,MWAWFont::boldBit));
521   MWAWParagraph para;
522   para.m_justify = MWAWParagraph::JustificationCenter;
523   listener->setParagraph(para);
524   listener->insertUnicodeString(librevenge::RVNGString("Index"));
525   listener->insertEOL();
526   listener->insertEOL();
527 
528   MWAWInputStreamPtr input = rsrcInput();
529   para=MWAWParagraph();
530   double w = getPageWidth();
531   MWAWTabStop tab;
532   tab.m_alignment = MWAWTabStop::RIGHT;
533   tab.m_leaderCharacter='.';
534   tab.m_position = w-0.3;
535   para.m_tabs->push_back(tab);
536 #ifdef DEBUG
537   int n=0;
538 #endif
539   for (auto const &index : m_state->m_indexList) {
540 #ifdef DEBUG
541     ++n;
542 #endif
543     if (!index.m_entry.valid() || index.m_level<=0)
544       continue;
545     para.m_margins[1]=0.5*double(index.m_level);
546     listener->setParagraph(para);
547     if (m_state->m_idFontMap.find(index.m_level)!=m_state->m_idFontMap.end())
548       listener->setFont(m_state->m_idFontMap.find(index.m_level)->second);
549     else {
550       MWAW_DEBUG_MSG(("MacDocParser::sendIndex: can not find font for index %d\n", int(n-1)));
551       listener->setFont(MWAWFont());
552     }
553     input->seek(index.m_entry.begin(), librevenge::RVNG_SEEK_SET);
554     for (long c=0; c < index.m_entry.length(); ++c) {
555       auto ch=static_cast<unsigned char>(input->readULong(1));
556       if (ch==9)
557         listener->insertCharacter(' ');
558       else
559         listener->insertCharacter(ch);
560     }
561     if (index.m_page>0) {
562       std::stringstream s;
563       s << index.m_page;
564       listener->setFont(MWAWFont());
565       listener->insertTab();
566       listener->insertUnicodeString(librevenge::RVNGString(s.str().c_str()));
567     }
568     listener->insertEOL();
569   }
570   return true;
571 }
572 
573 // picture
sendPicture(MWAWEntry const & entry)574 bool MacDocParser::sendPicture(MWAWEntry const &entry)
575 {
576   if (!getTextListener()) {
577     MWAW_DEBUG_MSG(("MacDocParser::sendPicture: can not find the listener\n"));
578     return false;
579   }
580   librevenge::RVNGBinaryData data;
581   if (!getRSRCParser()->parsePICT(entry, data))
582     return false;
583 
584   entry.setParsed(true);
585   auto dataSz=int(data.size());
586   if (!dataSz)
587     return false;
588   MWAWInputStreamPtr pictInput=MWAWInputStream::get(data, false);
589   if (!pictInput) {
590     MWAW_DEBUG_MSG(("MacDocParser::sendPicture: oops can not find an input\n"));
591     return false;
592   }
593   MWAWBox2f box;
594   auto res = MWAWPictData::check(pictInput, dataSz,box);
595   if (res == MWAWPict::MWAW_R_BAD) {
596     MWAW_DEBUG_MSG(("MacDocParser::sendPicture: can not find the picture\n"));
597     return false;
598   }
599   pictInput->seek(0,librevenge::RVNG_SEEK_SET);
600   std::shared_ptr<MWAWPict> thePict(MWAWPictData::get(pictInput, dataSz));
601   MWAWPosition pictPos=MWAWPosition(MWAWVec2f(0,0),box.size(), librevenge::RVNG_POINT);
602   pictPos.setRelativePosition(MWAWPosition::Char);
603   if (thePict) {
604     MWAWEmbeddedObject picture;
605     if (thePict->getBinary(picture))
606       getTextListener()->insertPicture(pictPos, picture);
607   }
608   return true;
609 }
610 
611 // file: unknown format: 0002 0000 0000 00 + FileInfo + DataFrk + RSRCFork ?
readFile(MWAWEntry const & entry)612 bool MacDocParser::readFile(MWAWEntry const &entry)
613 {
614   entry.setParsed(true);
615 #ifdef DEBUG_WITH_FILES
616   MWAWInputStreamPtr input = rsrcInput();
617   input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
618   librevenge::RVNGBinaryData data;
619   input->readDataBlock(entry.length(), data);
620 
621   libmwaw::DebugFile &ascFile = rsrcAscii();
622 
623   static int volatile fileName = 0;
624   libmwaw::DebugStream f;
625   f << "FILE" << ++fileName;
626   libmwaw::Debug::dumpFile(data, f.str().c_str());
627 
628   ascFile.addPos(entry.begin()-4);
629   ascFile.addNote(f.str().c_str());
630   ascFile.skipZone(entry.begin(),entry.end()-1);
631 #endif
632 
633   return true;
634 }
635 
636 // bookmark. note the name is stored as resource name
readBookmark(MWAWEntry const & entry)637 bool MacDocParser::readBookmark(MWAWEntry const &entry)
638 {
639   if (entry.length()!=8) {
640     MWAW_DEBUG_MSG(("MacDocParser::readWP: the entry seems bad\n"));
641     return false;
642   }
643 
644   entry.setParsed(true);
645   MWAWInputStreamPtr input = rsrcInput();
646   input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
647   libmwaw::DebugFile &ascFile = rsrcAscii();
648   libmwaw::DebugStream f;
649   f << "Entries(BookMark)[" << entry.id() << "]:";
650   long val=input->readLong(4);
651   if (val) f << "page=" << val << ",";
652   val=input->readLong(4);
653   if (val) f << "yPos?=" << val << ",";
654   ascFile.addPos(entry.begin()-4);
655   ascFile.addNote(f.str().c_str());
656   return true;
657 }
658 
659 // unknown related to window position?
readWP(MWAWEntry const & entry)660 bool MacDocParser::readWP(MWAWEntry const &entry)
661 {
662   if (entry.length()!=4) {
663     MWAW_DEBUG_MSG(("MacDocParser::readWP: the entry seems bad\n"));
664     return false;
665   }
666 
667   entry.setParsed(true);
668   MWAWInputStreamPtr input = rsrcInput();
669   input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
670   libmwaw::DebugFile &ascFile = rsrcAscii();
671   libmwaw::DebugStream f;
672   f << "Entries(WP)[" << entry.id() << "]:";
673   for (int i=0; i < 2; ++i) { // f0=0|a6|c6, f1=0|1 show index ?
674     long val=input->readLong(2);
675     if (val)
676       f << "f" << i << "=" << val << ",";
677   }
678   ascFile.addPos(entry.begin()-4);
679   ascFile.addNote(f.str().c_str());
680   return true;
681 }
682 
683 ////////////////////////////////////////////////////////////
684 // read the header
685 ////////////////////////////////////////////////////////////
checkHeader(MWAWHeader * header,bool strict)686 bool MacDocParser::checkHeader(MWAWHeader *header, bool strict)
687 {
688   *m_state = MacDocParserInternal::State();
689   /** no data fork, may be ok, but this means
690       that the file contains no text, so... */
691   MWAWInputStreamPtr input = getInput();
692   if (!input || !getRSRCParser())
693     return false;
694   if (input->hasDataFork()) {
695     MWAW_DEBUG_MSG(("MacDocParser::checkHeader: find a datafork, odd!!!\n"));
696   }
697   if (strict) {
698     // check if at least one picture zone exists
699     auto &entryMap = getRSRCParser()->getEntriesMap();
700     if (entryMap.find("MDpg") == entryMap.end())
701       return false;
702   }
703   if (header)
704     header->reset(MWAWDocument::MWAW_T_MACDOC, version());
705 
706   return true;
707 }
708 
709 // vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab:
710