/src/libmwaw/src/lib/WriteNowParser.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 <sstream> |
39 | | |
40 | | #include <librevenge/librevenge.h> |
41 | | |
42 | | #include "MWAWTextListener.hxx" |
43 | | #include "MWAWHeader.hxx" |
44 | | #include "MWAWFont.hxx" |
45 | | #include "MWAWPosition.hxx" |
46 | | #include "MWAWPictMac.hxx" |
47 | | #include "MWAWPrinter.hxx" |
48 | | |
49 | | #include "WriteNowEntry.hxx" |
50 | | #include "WriteNowText.hxx" |
51 | | |
52 | | #include "WriteNowParser.hxx" |
53 | | |
54 | | /** Internal: the structures of a WriteNowParser */ |
55 | | namespace WriteNowParserInternal |
56 | | { |
57 | | //////////////////////////////////////// |
58 | | //! Internal: the state of a WriteNowParser |
59 | | struct State { |
60 | | //! constructor |
61 | | State() |
62 | 196k | : m_endPos(-1) |
63 | 196k | , m_colorMap() |
64 | 196k | , m_picturesList() |
65 | 196k | , m_actPage(0) |
66 | 196k | , m_numPages(0) |
67 | 196k | , m_headerHeight(0) |
68 | 196k | , m_footerHeight(0) |
69 | 196k | , m_numColumns(1) |
70 | 196k | , m_columnWidth(-1) |
71 | 196k | { |
72 | 196k | } |
73 | | |
74 | | //! the last position |
75 | | long m_endPos; |
76 | | //! the color map |
77 | | std::vector<MWAWColor> m_colorMap; |
78 | | //! the list of picture entries |
79 | | std::vector<WriteNowEntry> m_picturesList; |
80 | | |
81 | | int m_actPage /** the actual page */, m_numPages /** the number of page of the final document */; |
82 | | |
83 | | int m_headerHeight /** the header height if known */, |
84 | | m_footerHeight /** the footer height if known */; |
85 | | |
86 | | int m_numColumns /** the number of columns */, m_columnWidth /** the columns size */; |
87 | | }; |
88 | | |
89 | | //////////////////////////////////////// |
90 | | //! Internal: the subdocument of a WriteNowParser |
91 | | class SubDocument final : public MWAWSubDocument |
92 | | { |
93 | | public: |
94 | | SubDocument(WriteNowParser &pars, MWAWInputStreamPtr const &input, WriteNowEntry const &pos) |
95 | 189k | : MWAWSubDocument(&pars, input, MWAWEntry()) |
96 | 189k | , m_pos(pos) |
97 | 189k | { |
98 | 189k | } |
99 | | |
100 | | //! destructor |
101 | 189k | ~SubDocument() final {} |
102 | | |
103 | | //! operator!= |
104 | | bool operator!=(MWAWSubDocument const &doc) const final; |
105 | | |
106 | | //! the parser function |
107 | | void parse(MWAWListenerPtr &listener, libmwaw::SubDocumentType type) final; |
108 | | |
109 | | protected: |
110 | | //! the subdocument file position |
111 | | WriteNowEntry m_pos; |
112 | | }; |
113 | | |
114 | | void SubDocument::parse(MWAWListenerPtr &listener, libmwaw::SubDocumentType /*type*/) |
115 | 189k | { |
116 | 189k | if (!listener.get()) { |
117 | 0 | MWAW_DEBUG_MSG(("WriteNowParserInternal::SubDocument::parse: no listener\n")); |
118 | 0 | return; |
119 | 0 | } |
120 | 189k | auto *parser=dynamic_cast<WriteNowParser *>(m_parser); |
121 | 189k | if (!parser) { |
122 | 0 | MWAW_DEBUG_MSG(("WriteNowParserInternal::SubDocument::parse: no parser\n")); |
123 | 0 | return; |
124 | 0 | } |
125 | | |
126 | 189k | long pos = m_input->tell(); |
127 | 189k | parser->send(m_pos); |
128 | 189k | m_input->seek(pos, librevenge::RVNG_SEEK_SET); |
129 | 189k | } |
130 | | |
131 | | bool SubDocument::operator!=(MWAWSubDocument const &doc) const |
132 | 0 | { |
133 | 0 | if (MWAWSubDocument::operator!=(doc)) return true; |
134 | 0 | auto const *sDoc = dynamic_cast<SubDocument const *>(&doc); |
135 | 0 | if (!sDoc) return true; |
136 | 0 | if (m_pos != sDoc->m_pos) return true; |
137 | 0 | return false; |
138 | 0 | } |
139 | | } |
140 | | |
141 | | |
142 | | //////////////////////////////////////////////////////////// |
143 | | // constructor/destructor, ... |
144 | | //////////////////////////////////////////////////////////// |
145 | | WriteNowParser::WriteNowParser(MWAWInputStreamPtr const &input, MWAWRSRCParserPtr const &rsrcParser, MWAWHeader *header) |
146 | 84.5k | : MWAWTextParser(input, rsrcParser, header) |
147 | 84.5k | , m_state() |
148 | 84.5k | , m_entryManager() |
149 | 84.5k | , m_textParser() |
150 | 84.5k | { |
151 | 84.5k | init(); |
152 | 84.5k | } |
153 | | |
154 | | WriteNowParser::~WriteNowParser() |
155 | 84.5k | { |
156 | 84.5k | } |
157 | | |
158 | | void WriteNowParser::init() |
159 | 84.5k | { |
160 | 84.5k | resetTextListener(); |
161 | 84.5k | setAsciiName("main-1"); |
162 | | |
163 | 84.5k | m_state.reset(new WriteNowParserInternal::State); |
164 | 84.5k | m_entryManager.reset(new WriteNowEntryManager); |
165 | | |
166 | | // reduce the margin (in case, the page is not defined) |
167 | 84.5k | getPageSpan().setMargins(0.1); |
168 | | |
169 | 84.5k | m_textParser.reset(new WriteNowText(*this)); |
170 | 84.5k | } |
171 | | |
172 | | //////////////////////////////////////////////////////////// |
173 | | // position and height |
174 | | //////////////////////////////////////////////////////////// |
175 | | void WriteNowParser::getColumnInfo(int &numColumns, int &width) const |
176 | 103k | { |
177 | 103k | numColumns = m_state->m_numColumns; |
178 | 103k | width = m_state->m_columnWidth; |
179 | 103k | } |
180 | | |
181 | | //////////////////////////////////////////////////////////// |
182 | | // new page and color |
183 | | //////////////////////////////////////////////////////////// |
184 | | void WriteNowParser::newPage(int number) |
185 | 23.2k | { |
186 | 23.2k | if (number <= m_state->m_actPage || number > m_state->m_numPages) |
187 | 0 | return; |
188 | | |
189 | 48.9k | while (m_state->m_actPage < number) { |
190 | 25.7k | m_state->m_actPage++; |
191 | 25.7k | if (!getTextListener() || m_state->m_actPage == 1) |
192 | 2.43k | continue; |
193 | 23.2k | getTextListener()->insertBreak(MWAWTextListener::PageBreak); |
194 | 23.2k | } |
195 | 23.2k | } |
196 | | |
197 | | bool WriteNowParser::getColor(int colId, MWAWColor &col) const |
198 | 1.14M | { |
199 | 1.14M | if (colId >= 0 && colId < int(m_state->m_colorMap.size())) { |
200 | 702 | col = m_state->m_colorMap[size_t(colId)]; |
201 | 702 | return true; |
202 | 702 | } |
203 | 1.14M | return false; |
204 | 1.14M | } |
205 | | |
206 | | void WriteNowParser::sendFootnote(WriteNowEntry const &entry) |
207 | 186k | { |
208 | 186k | if (!getTextListener()) return; |
209 | | |
210 | 186k | MWAWSubDocumentPtr subdoc(new WriteNowParserInternal::SubDocument(*this, getInput(), entry)); |
211 | 186k | getTextListener()->insertNote(MWAWNote(MWAWNote::FootNote), subdoc); |
212 | 186k | } |
213 | | |
214 | | void WriteNowParser::send(WriteNowEntry const &entry) |
215 | 189k | { |
216 | 189k | m_textParser->send(entry); |
217 | 189k | } |
218 | | |
219 | | bool WriteNowParser::sendGraphic(int gId, MWAWBox2i const &bdbox) |
220 | 3.30k | { |
221 | 3.30k | if (gId < 8 || (gId-8) >= int(m_state->m_picturesList.size())) { |
222 | 955 | MWAW_DEBUG_MSG(("WriteNowParser::sendGraphic: called with bad id=%d\n", gId)); |
223 | 955 | return false; |
224 | 955 | } |
225 | 2.35k | if (!m_state->m_picturesList[size_t(gId)-8].isZone()) { |
226 | 763 | MWAW_DEBUG_MSG(("WriteNowParser::sendGraphic: called with a no zone id=%d\n", gId)); |
227 | 763 | return false; |
228 | 763 | } |
229 | | |
230 | 1.58k | sendPicture(m_state->m_picturesList[size_t(gId)-8], bdbox); |
231 | 1.58k | return true; |
232 | 2.35k | } |
233 | | |
234 | | |
235 | | //////////////////////////////////////////////////////////// |
236 | | // the parser |
237 | | //////////////////////////////////////////////////////////// |
238 | | void WriteNowParser::parse(librevenge::RVNGTextInterface *docInterface) |
239 | 27.0k | { |
240 | 27.0k | if (!getInput().get() || !checkHeader(nullptr)) throw(libmwaw::ParseException()); |
241 | 27.0k | bool ok = true; |
242 | 27.0k | try { |
243 | | // create the asciiFile |
244 | 27.0k | ascii().setStream(getInput()); |
245 | 27.0k | ascii().open(asciiName()); |
246 | | |
247 | 27.0k | m_entryManager->reset(); |
248 | 27.0k | checkHeader(nullptr); |
249 | 27.0k | ascii().addPos(getInput()->tell()); |
250 | 27.0k | ascii().addNote("_"); |
251 | | |
252 | 27.0k | ok = createZones(); |
253 | 27.0k | if (ok) { |
254 | 25.7k | createDocument(docInterface); |
255 | 25.7k | m_textParser->sendZone(0); |
256 | | |
257 | | // ok, we can now send what is not send. |
258 | 25.7k | m_textParser->flushExtra(); |
259 | 25.7k | MWAWBox2i emptyBdBox; |
260 | 25.7k | for (auto &picture : m_state->m_picturesList) { |
261 | 8.06k | if (picture.isParsed() || !picture.isZone()) continue; |
262 | 5.45k | sendPicture(picture, emptyBdBox); |
263 | 5.45k | } |
264 | 25.7k | } |
265 | | |
266 | 27.0k | ascii().reset(); |
267 | 27.0k | } |
268 | 27.0k | catch (...) { |
269 | 0 | MWAW_DEBUG_MSG(("WriteNowParser::parse: exception catched when parsing\n")); |
270 | 0 | ok = false; |
271 | 0 | } |
272 | | |
273 | 27.0k | resetTextListener(); |
274 | 27.0k | if (!ok) throw(libmwaw::ParseException()); |
275 | 27.0k | } |
276 | | |
277 | | //////////////////////////////////////////////////////////// |
278 | | // create the document |
279 | | //////////////////////////////////////////////////////////// |
280 | | void WriteNowParser::createDocument(librevenge::RVNGTextInterface *documentInterface) |
281 | 25.7k | { |
282 | 25.7k | if (!documentInterface) return; |
283 | 25.7k | if (getTextListener()) { |
284 | 0 | MWAW_DEBUG_MSG(("WriteNowParser::createDocument: listener already exist\n")); |
285 | 0 | return; |
286 | 0 | } |
287 | | |
288 | | // update the page |
289 | 25.7k | m_state->m_actPage = 0; |
290 | | |
291 | | // create the page list |
292 | 25.7k | MWAWPageSpan ps(getPageSpan()); |
293 | | |
294 | 25.7k | WriteNowEntry entry = m_textParser->getHeader(); |
295 | 25.7k | if (entry.valid()) { |
296 | 1.35k | MWAWHeaderFooter header(MWAWHeaderFooter::HEADER, MWAWHeaderFooter::ALL); |
297 | 1.35k | header.m_subDocument.reset(new WriteNowParserInternal::SubDocument(*this, getInput(), entry)); |
298 | 1.35k | ps.setHeaderFooter(header); |
299 | 1.35k | } |
300 | | |
301 | 25.7k | entry = m_textParser->getFooter(); |
302 | 25.7k | if (entry.valid()) { |
303 | 1.60k | MWAWHeaderFooter footer(MWAWHeaderFooter::FOOTER, MWAWHeaderFooter::ALL); |
304 | 1.60k | footer.m_subDocument.reset(new WriteNowParserInternal::SubDocument(*this, getInput(), entry)); |
305 | 1.60k | ps.setHeaderFooter(footer); |
306 | 1.60k | } |
307 | | |
308 | 25.7k | int numPage = m_textParser->numPages(); |
309 | 25.7k | m_state->m_numPages = numPage; |
310 | 25.7k | ps.setPageSpan(m_state->m_numPages+1); |
311 | 25.7k | std::vector<MWAWPageSpan> pageList(1,ps); |
312 | | // |
313 | 25.7k | MWAWTextListenerPtr listen(new MWAWTextListener(*getParserState(), pageList, documentInterface)); |
314 | 25.7k | setTextListener(listen); |
315 | 25.7k | listen->startDocument(); |
316 | 25.7k | } |
317 | | |
318 | | |
319 | | //////////////////////////////////////////////////////////// |
320 | | // |
321 | | // Intermediate level |
322 | | // |
323 | | //////////////////////////////////////////////////////////// |
324 | | |
325 | | //////////////////////////////////////////////////////////// |
326 | | // try to find the different zone |
327 | | //////////////////////////////////////////////////////////// |
328 | | bool WriteNowParser::createZones() |
329 | 27.0k | { |
330 | 27.0k | if (version() < 3) { |
331 | 24.6k | if (!readDocEntriesV2()) |
332 | 765 | return false; |
333 | 24.6k | } |
334 | 2.37k | else if (!readDocEntries()) |
335 | 466 | return false; |
336 | | |
337 | | // the Color map zone |
338 | 25.7k | auto iter = m_entryManager->m_typeMap.find("ColMap"); |
339 | 25.7k | if (iter != m_entryManager->m_typeMap.end()) |
340 | 1.54k | readColorMap(*iter->second); |
341 | | |
342 | | // the graphic zone |
343 | 25.7k | iter = m_entryManager->m_typeMap.find("GraphZone"); |
344 | 25.7k | if (iter != m_entryManager->m_typeMap.end()) |
345 | 1.51k | parseGraphicZone(*iter->second); |
346 | | |
347 | | |
348 | 25.7k | iter = m_entryManager->m_typeMap.find("UnknZone1"); |
349 | 25.7k | if (iter != m_entryManager->m_typeMap.end()) |
350 | 1.53k | readGenericUnkn(*iter->second); |
351 | | |
352 | 25.7k | iter = m_entryManager->m_typeMap.find("PrintZone"); |
353 | 25.7k | if (iter != m_entryManager->m_typeMap.end()) |
354 | 8.92k | readPrintInfo(*iter->second); |
355 | | |
356 | | // checkme: never seens, but probably also a list of zone... |
357 | 25.7k | iter = m_entryManager->m_typeMap.find("UnknZone2"); |
358 | 25.7k | if (iter != m_entryManager->m_typeMap.end()) |
359 | 101 | readGenericUnkn(*iter->second); |
360 | | |
361 | 25.7k | bool ok = m_textParser->createZones(); |
362 | | |
363 | | // fixme: we must continue.... |
364 | 25.7k | libmwaw::DebugStream f; |
365 | 736k | for (auto const &it : m_entryManager->m_typeMap) { |
366 | 736k | WriteNowEntry const &ent = *it.second; |
367 | 736k | if (ent.isParsed()) continue; |
368 | 65.1k | ascii().addPos(ent.begin()); |
369 | 65.1k | f.str(""); |
370 | 65.1k | f << "Entries(" << it.first << ")"; |
371 | 65.1k | if (ent.id() >= 0) f << "[" << ent.id() << "]"; |
372 | 65.1k | ascii().addNote(f.str().c_str()); |
373 | 65.1k | ascii().addPos(ent.end()); |
374 | 65.1k | ascii().addNote("_"); |
375 | 65.1k | } |
376 | 25.7k | return ok; |
377 | 27.0k | } |
378 | | |
379 | | //////////////////////////////////////////////////////////// |
380 | | // |
381 | | // Low level |
382 | | // |
383 | | //////////////////////////////////////////////////////////// |
384 | | |
385 | | //////////////////////////////////////////////////////////// |
386 | | // try to read the document main zone |
387 | | //////////////////////////////////////////////////////////// |
388 | | bool WriteNowParser::readDocEntries() |
389 | 2.37k | { |
390 | 2.37k | MWAWInputStreamPtr input = getInput(); |
391 | | |
392 | 2.37k | auto it = m_entryManager->m_typeMap.find("DocEntries"); |
393 | 2.37k | if (it == m_entryManager->m_typeMap.end()) { |
394 | 21 | MWAW_DEBUG_MSG(("WriteNowParser::readDocEntries: can not find last zone\n")); |
395 | 21 | return false; |
396 | 21 | } |
397 | 2.34k | WriteNowEntry const &entry = *(it->second); |
398 | 2.34k | if (!entry.valid() || entry.length() < 148) { |
399 | 23 | MWAW_DEBUG_MSG(("WriteNowParser::readDocEntries: last entry is invalid\n")); |
400 | 23 | return false; |
401 | 23 | } |
402 | | |
403 | 2.32k | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
404 | 2.32k | bool ok = input->readLong(4) == entry.length(); |
405 | 2.32k | if (!ok || input->readLong(4) != entry.begin()) { |
406 | 422 | MWAW_DEBUG_MSG(("WriteNowParser::readDocEntries: bad begin of last zone\n")); |
407 | 422 | return false; |
408 | 422 | } |
409 | 1.90k | entry.setParsed(true); |
410 | 1.90k | libmwaw::DebugStream f; |
411 | 1.90k | f << "Entries(DocEntries):"; |
412 | | |
413 | 1.90k | long val; |
414 | 1.90k | long const expectedVal[] = { 0, 0x80, 0x40000000L}; |
415 | 1.90k | long freePos = 0; |
416 | 15.2k | for (int i = 0; i < 7; i++) { // 0, 80, 4000 |
417 | 13.3k | val = long(input->readULong(4)); |
418 | 13.3k | if (i == 3) { |
419 | 1.90k | freePos = val; |
420 | 1.90k | continue; |
421 | 1.90k | } |
422 | 11.4k | if ((i < 3 && val!= expectedVal[i]) || (i >=3 && val)) |
423 | 2.24k | f << "f" << i << "=" << std::hex << val << std::dec << ","; |
424 | 11.4k | } |
425 | 1.90k | if (freePos) { // checkme |
426 | 1.90k | if (freePos > m_state->m_endPos) { |
427 | 37 | MWAW_DEBUG_MSG(("WriteNowParser::readDocEntries: find odd freePos\n")); |
428 | 37 | } |
429 | 1.86k | else { |
430 | 1.86k | f << "freeZone?=" << std::hex << freePos << std::dec << ","; |
431 | 1.86k | ascii().addPos(freePos); |
432 | 1.86k | ascii().addNote("Entries(Free)"); |
433 | 1.86k | } |
434 | 1.90k | } |
435 | 1.90k | char const *entryName[] = { "TextZone", "TextZone", "TextZone", "UnknZone0", |
436 | 1.90k | "GraphZone", "ColMap", "StylZone", "FontZone", |
437 | 1.90k | "UnknZone1", "UnknZone2" |
438 | 1.90k | }; |
439 | 20.9k | for (int i = 0; i < 10; i++) { |
440 | 19.0k | WriteNowEntry zone = readEntry(); |
441 | 19.0k | zone.setType(entryName[i]); |
442 | 19.0k | if (i < 3) zone.setId(i); |
443 | 19.0k | if (zone.isZone()) |
444 | 13.5k | m_entryManager->add(zone); |
445 | 19.0k | f << zone; |
446 | 19.0k | } |
447 | 1.90k | ascii().addDelimiter(input->tell(), '|'); |
448 | 1.90k | ascii().addPos(entry.begin()); |
449 | 1.90k | ascii().addNote(f.str().c_str()); |
450 | 1.90k | if (entry.length() > 386) { |
451 | 1.90k | long pos = entry.begin()+376; |
452 | 1.90k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
453 | 1.90k | f.str(""); |
454 | 1.90k | f << "DocEntries-II:"; |
455 | 1.90k | m_state->m_numColumns = static_cast<int>(input->readLong(1)); |
456 | 1.90k | f << "nCol=" << m_state->m_numColumns << ","; |
457 | 1.90k | val = input->readLong(1); |
458 | 1.90k | if (val != 1) f << "unkn=" << val << ","; |
459 | 1.90k | m_state->m_columnWidth = static_cast<int>(input->readLong(2)); |
460 | 1.90k | f << "colWidth=" << m_state->m_columnWidth << ","; |
461 | | |
462 | 1.90k | ascii().addPos(pos); |
463 | 1.90k | ascii().addNote(f.str().c_str()); |
464 | | |
465 | 1.90k | if (long(input->tell()) != entry.end()) |
466 | 1.90k | ascii().addDelimiter(input->tell(), '|'); |
467 | 1.90k | } |
468 | 1.90k | ascii().addPos(entry.end()); |
469 | 1.90k | ascii().addNote("_"); |
470 | | |
471 | 1.90k | return true; |
472 | 2.32k | } |
473 | | |
474 | | //////////////////////////////////////////////////////////// |
475 | | // try to read the document main zone : v2 |
476 | | //////////////////////////////////////////////////////////// |
477 | | bool WriteNowParser::readDocEntriesV2() |
478 | 24.6k | { |
479 | 24.6k | MWAWInputStreamPtr input = getInput(); |
480 | 24.6k | long pos = input->tell(), debPos=pos; |
481 | 24.6k | libmwaw::DebugStream f; |
482 | 24.6k | std::stringstream s; |
483 | 24.6k | f << "Entries(DocEntries):"; |
484 | 145k | for (int i = 0; i < 5; i++) { |
485 | 121k | auto val=static_cast<int>(input->readLong(1)); |
486 | 121k | if (val != 4 && val != 0x44) { |
487 | 765 | MWAW_DEBUG_MSG(("WriteNowParser::readDocEntriesV2: can not find entries header:%d\n",i)); |
488 | 765 | return false; |
489 | 765 | } |
490 | 120k | auto dataPos = long(input->readULong(1)); |
491 | 120k | dataPos = (dataPos<<16)+long(input->readULong(2)); |
492 | 120k | if (!checkIfPositionValid(dataPos)) { |
493 | 46.5k | MWAW_DEBUG_MSG(("WriteNowParser::readDocEntriesV2: find an invalid position for entry:%d\n",i)); |
494 | 46.5k | continue; |
495 | 46.5k | } |
496 | 74.3k | WriteNowEntry entry; |
497 | 74.3k | entry.setBegin(dataPos); |
498 | 74.3k | switch (i) { |
499 | 22.9k | case 0: |
500 | 34.8k | case 1: |
501 | 52.3k | case 2: |
502 | 52.3k | entry.setType("TextZone"); |
503 | 52.3k | entry.setId(i); |
504 | 52.3k | break; |
505 | 10.8k | case 4: |
506 | 10.8k | entry.setType("PrintZone"); |
507 | 10.8k | break; |
508 | 11.1k | default: { // find 2 time 0006000800000000 |
509 | 11.1k | std::stringstream name; |
510 | 11.1k | s << "Unknown" << i; |
511 | 11.1k | entry.setType(name.str()); |
512 | 11.1k | } |
513 | 74.3k | } |
514 | 74.3k | long actPos = input->tell(); |
515 | 74.3k | input->seek(dataPos, librevenge::RVNG_SEEK_SET); |
516 | 74.3k | entry.setLength(long(input->readULong(2)+2)); |
517 | 74.3k | input->seek(actPos, librevenge::RVNG_SEEK_SET); |
518 | 74.3k | m_entryManager->add(entry); |
519 | 74.3k | } |
520 | 23.8k | f << "ptr=["; |
521 | 143k | for (int i = 0; i < 5; i++) |
522 | 119k | f << std::hex << input->readULong(4) << std::dec << ","; |
523 | 23.8k | f << "],"; |
524 | 23.8k | ascii().addPos(pos); |
525 | 23.8k | ascii().addNote(f.str().c_str()); |
526 | 23.8k | input->seek(debPos+0x6E,librevenge::RVNG_SEEK_SET); |
527 | 23.8k | pos=input->tell(); |
528 | 23.8k | f.str(""); |
529 | 23.8k | f << "DocEntries-II:"; |
530 | | |
531 | 23.8k | if (version()==2) { |
532 | 23.8k | m_state->m_numColumns = static_cast<int>(input->readLong(1)); |
533 | 23.8k | f << "nCol=" << m_state->m_numColumns << ","; |
534 | 23.8k | long val = input->readLong(1); |
535 | 23.8k | if (val != 1) f << "unkn=" << val << ","; |
536 | 23.8k | m_state->m_columnWidth = static_cast<int>(input->readLong(2)); |
537 | 23.8k | f << "colWidth=" << m_state->m_columnWidth << ","; |
538 | 23.8k | ascii().addDelimiter(input->tell(),'|'); |
539 | 23.8k | } |
540 | 23.8k | ascii().addPos(pos); |
541 | 23.8k | ascii().addNote(f.str().c_str()); |
542 | | // another copy (visibly the previous version) |
543 | 23.8k | ascii().addPos(debPos+0xFc); |
544 | 23.8k | ascii().addNote("DocEntries[Old]:"); |
545 | 23.8k | ascii().addPos(debPos+0x16a); |
546 | 23.8k | ascii().addNote("DocEntries-II[Old]:"); |
547 | 23.8k | ascii().addPos(debPos+0x1F8); |
548 | 23.8k | ascii().addNote("_"); |
549 | 23.8k | return true; |
550 | 24.6k | } |
551 | | //////////////////////////////////////////////////////////// |
552 | | // try to read a graphic list zone |
553 | | //////////////////////////////////////////////////////////// |
554 | | bool WriteNowParser::parseGraphicZone(WriteNowEntry const &entry) |
555 | 1.51k | { |
556 | 1.51k | MWAWInputStreamPtr input = getInput(); |
557 | | |
558 | 1.51k | if (!entry.valid() || entry.length() < 24) { |
559 | 13 | MWAW_DEBUG_MSG(("WriteNowParser::parseGraphicZone: zone size is invalid\n")); |
560 | 13 | return false; |
561 | 13 | } |
562 | | |
563 | 1.49k | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
564 | 1.49k | if (input->readLong(4) != entry.length()) { |
565 | 322 | MWAW_DEBUG_MSG(("WriteNowParser::parseGraphicZone: bad begin of last zone\n")); |
566 | 322 | return false; |
567 | 322 | } |
568 | 1.17k | libmwaw::DebugStream f; |
569 | 1.17k | f << "Entries(GraphicZone):"; |
570 | 1.17k | f << "ptr?=" << std::hex << input->readULong(4) << std::dec << ","; |
571 | 1.17k | f << "ptr2?=" << std::hex << input->readULong(4) << std::dec << ","; |
572 | 1.17k | long val; |
573 | 4.70k | for (int i = 0; i < 3; i++) { // always 3, 80, 0 ? |
574 | 3.52k | val = input->readLong(2); |
575 | 3.52k | if (val) f << "f" << i << "=" << val << ","; |
576 | 3.52k | } |
577 | 1.17k | auto N = static_cast<int>(input->readLong(2)); |
578 | 1.17k | f << "N?=" << N << ","; |
579 | 3.52k | for (int i = 4; i < 6; i++) { // alway 0 ? |
580 | 2.35k | val = input->readLong(2); |
581 | 2.35k | if (val) f << "f" << i << "=" << val << ","; |
582 | 2.35k | } |
583 | 1.17k | ascii().addPos(entry.begin()); |
584 | 1.17k | ascii().addNote(f.str().c_str()); |
585 | | |
586 | 1.17k | if (entry.length() != 24+12*N) { |
587 | 24 | MWAW_DEBUG_MSG(("WriteNowParser::parseGraphicZone: zone size is invalid(II)\n")); |
588 | 24 | return false; |
589 | 24 | } |
590 | 18.4k | for (int i = 0; i < N; i++) { |
591 | 17.2k | long pos = input->tell(); |
592 | 17.2k | WriteNowEntry zone = readEntry(); |
593 | 17.2k | f.str(""); |
594 | 17.2k | if (i < 8) |
595 | 9.21k | f << "GraphicZoneA-" << i << ":"; |
596 | 8.06k | else |
597 | 8.06k | f << "GraphicZone-" << i-8 << ":"; |
598 | | |
599 | 17.2k | zone.setId((i < 8) ? i : i-8); |
600 | 17.2k | if (zone.isZone()) { |
601 | 8.44k | if (i == 0) |
602 | 1.04k | zone.setType("PrintZone"); |
603 | 7.39k | else if (i < 8) { |
604 | 1.12k | std::stringstream s; |
605 | 1.12k | s << "GraphicUnkn" << i; |
606 | 1.12k | zone.setType(s.str()); |
607 | 1.12k | } |
608 | 6.27k | else |
609 | 6.27k | zone.setType("GraphicData"); |
610 | 8.44k | if (i < 8) |
611 | 2.16k | m_entryManager->add(zone); |
612 | 8.44k | } |
613 | 8.83k | else if (zone.m_val[2]==-1 && zone.m_val[3]==0x76543210L) { |
614 | 0 | zone.m_val[2]= zone.m_val[3]=0; |
615 | 0 | f << "*"; |
616 | 0 | } |
617 | 17.2k | if (i >= 8) |
618 | 8.06k | m_state->m_picturesList.push_back(zone); |
619 | 17.2k | f << zone; |
620 | | |
621 | 17.2k | ascii().addPos(pos); |
622 | 17.2k | ascii().addNote(f.str().c_str()); |
623 | 17.2k | } |
624 | | |
625 | 1.15k | entry.setParsed(true); |
626 | 1.15k | ascii().addPos(entry.end()); |
627 | 1.15k | ascii().addNote("_"); |
628 | 1.15k | return true; |
629 | 1.17k | } |
630 | | |
631 | | //////////////////////////////////////////////////////////// |
632 | | // try to read a graphic zone |
633 | | //////////////////////////////////////////////////////////// |
634 | | bool WriteNowParser::sendPicture(WriteNowEntry const &entry, MWAWBox2i const &bdbox) |
635 | 7.04k | { |
636 | 7.04k | MWAWInputStreamPtr input = getInput(); |
637 | | |
638 | 7.04k | if (!entry.valid() || entry.length() < 24) { |
639 | 46 | MWAW_DEBUG_MSG(("WriteNowParser::sendPicture: zone size is invalid\n")); |
640 | 46 | return false; |
641 | 46 | } |
642 | | |
643 | 6.99k | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
644 | 6.99k | if (input->readLong(4) != entry.length()) { |
645 | 4.95k | MWAW_DEBUG_MSG(("WriteNowParser::sendPicture: bad begin of last zone\n")); |
646 | 4.95k | return false; |
647 | 4.95k | } |
648 | 2.03k | libmwaw::DebugStream f; |
649 | 2.03k | f << "Entries(GraphicData):"; |
650 | 2.03k | f << "ptr?=" << std::hex << input->readULong(4) << std::dec << ","; |
651 | 2.03k | f << "ptr2?=" << std::hex << input->readULong(4) << std::dec << ","; |
652 | 2.03k | auto type = static_cast<int>(input->readLong(2)); |
653 | 2.03k | if (type != 14) f << "#type=" << type << ","; |
654 | 2.03k | long val; |
655 | | /* fl0 : 0[pict1] or 1[pict2] : graphic type ?, fl1 : always 0 |
656 | | */ |
657 | 6.10k | for (int i = 0; i < 2; i++) { |
658 | 4.07k | val = input->readLong(1); |
659 | 4.07k | if (val) f << "fl" << i << "=" << val << ","; |
660 | 4.07k | } |
661 | | |
662 | 2.03k | f << "ptr3?=" << std::hex << input->readULong(4) << std::dec << ","; |
663 | 6.10k | for (int i = 0; i < 2; i++) { // alway 0 ? |
664 | 4.07k | val = input->readLong(2); |
665 | 4.07k | if (val) f << "f" << i << "=" << val << ","; |
666 | 4.07k | } |
667 | | |
668 | 2.03k | ascii().addPos(entry.begin()); |
669 | 2.03k | ascii().addNote(f.str().c_str()); |
670 | | |
671 | 2.03k | int sz = static_cast<int>(entry.length())-24; |
672 | 2.03k | if (sz) { |
673 | 2.03k | long pos = input->tell(); |
674 | 2.03k | std::shared_ptr<MWAWPict> pict(MWAWPictData::get(input, sz)); |
675 | 2.03k | if (!pict) { |
676 | 4 | MWAW_DEBUG_MSG(("WriteNowParser::sendPicture: can not read the picture\n")); |
677 | 4 | ascii().addDelimiter(pos, '|'); |
678 | 4 | } |
679 | 2.03k | else { |
680 | 2.03k | if (getTextListener()) { |
681 | 2.03k | MWAWPosition pictPos; |
682 | 2.03k | if (bdbox.size().x() > 0 && bdbox.size().y() > 0) { |
683 | 824 | pictPos=MWAWPosition(MWAWVec2f(0,0),MWAWVec2f(bdbox.size()), librevenge::RVNG_POINT); |
684 | 824 | pictPos.setNaturalSize(pict->getBdBox().size()); |
685 | 824 | } |
686 | 1.20k | else |
687 | 1.20k | pictPos=MWAWPosition(MWAWVec2f(0,0),pict->getBdBox().size(), librevenge::RVNG_POINT); |
688 | 2.03k | pictPos.setRelativePosition(MWAWPosition::Char); |
689 | | |
690 | 2.03k | MWAWEmbeddedObject picture; |
691 | 2.03k | if (pict->getBinary(picture)) |
692 | 2.03k | getTextListener()->insertPicture(pictPos, picture); |
693 | 2.03k | } |
694 | | |
695 | | #ifdef DEBUG_WITH_FILES |
696 | | if (!entry.isParsed()) { |
697 | | ascii().skipZone(pos, entry.end()-1); |
698 | | librevenge::RVNGBinaryData file; |
699 | | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
700 | | input->readDataBlock(entry.length(), file); |
701 | | static int volatile pictName = 0; |
702 | | libmwaw::DebugStream f2; |
703 | | f2 << "PICT-" << ++pictName << ".pct"; |
704 | | libmwaw::Debug::dumpFile(file, f2.str().c_str()); |
705 | | } |
706 | | #endif |
707 | 2.03k | } |
708 | 2.03k | } |
709 | | |
710 | 2.03k | entry.setParsed(true); |
711 | 2.03k | ascii().addPos(entry.end()); |
712 | 2.03k | ascii().addNote("_"); |
713 | | |
714 | 2.03k | return true; |
715 | 6.99k | } |
716 | | |
717 | | |
718 | | //////////////////////////////////////////////////////////// |
719 | | // try to read the color map zone |
720 | | //////////////////////////////////////////////////////////// |
721 | | bool WriteNowParser::readColorMap(WriteNowEntry const &entry) |
722 | 1.54k | { |
723 | 1.54k | m_state->m_colorMap.resize(0); |
724 | | |
725 | 1.54k | MWAWInputStreamPtr input = getInput(); |
726 | | |
727 | 1.54k | if (!entry.valid() || entry.length() < 0x10) { |
728 | 8 | MWAW_DEBUG_MSG(("WriteNowParser::readColorMap: zone size is invalid\n")); |
729 | 8 | return false; |
730 | 8 | } |
731 | | |
732 | 1.54k | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
733 | 1.54k | if (input->readLong(4) != entry.length()) { |
734 | 258 | MWAW_DEBUG_MSG(("WriteNowParser::readColorMap: bad begin of last zone\n")); |
735 | 258 | return false; |
736 | 258 | } |
737 | 1.28k | libmwaw::DebugStream f; |
738 | 1.28k | f << "Entries(ColorMap):"; |
739 | 1.28k | f << "ptr?=" << std::hex << input->readULong(4) << std::dec << ","; |
740 | 1.28k | f << "ptr2?=" << std::hex << input->readULong(4) << std::dec << ","; |
741 | 1.28k | long pos, val; |
742 | 5.12k | for (int i = 0; i < 3; i++) { // always 4, 0, 0 ? |
743 | 3.84k | val = input->readLong(2); |
744 | 3.84k | if (val) f << "f" << i << "=" << val << ","; |
745 | 3.84k | } |
746 | 1.28k | auto N=static_cast<int>(input->readULong(2)); |
747 | 1.28k | f << "N=" << N << ","; |
748 | 3.84k | for (int i = 0; i < 2; i++) { // 0 |
749 | 2.56k | val = static_cast<int>(input->readLong(2)); |
750 | 2.56k | if (val) f << "g" << i << "=" << val << ","; |
751 | 2.56k | } |
752 | 1.28k | if (long(input->tell())+N*8 > entry.end()) { |
753 | 173 | MWAW_DEBUG_MSG(("WriteNowParser::readColorMap: the zone is too short\n")); |
754 | 173 | return false; |
755 | 173 | } |
756 | 1.10k | ascii().addPos(entry.begin()); |
757 | 1.10k | ascii().addNote(f.str().c_str()); |
758 | 1.10k | std::vector<long> defPos; |
759 | 11.5k | for (int n = 0; n < N; n++) { |
760 | 10.4k | pos = input->tell(); |
761 | 10.4k | f.str(""); |
762 | 10.4k | f << "ColorMap[" << n << "]:"; |
763 | 10.4k | auto type = static_cast<int>(input->readLong(1)); |
764 | 10.4k | switch (type) { |
765 | 1.65k | case 1: |
766 | 1.65k | f << "named(RGB),"; |
767 | 1.65k | break; |
768 | 100 | case 2: |
769 | 100 | f << "unamed,"; |
770 | 100 | break; // check me : are the color in RGB ? |
771 | 7.91k | case 3: |
772 | 7.91k | f << "unamed(RGB),"; |
773 | 7.91k | break; |
774 | 808 | default: |
775 | 808 | MWAW_DEBUG_MSG(("WriteNowParser::readColorMap: find unknown type %d\n", type)); |
776 | 808 | f << "#type=" << type << ","; |
777 | 808 | break; |
778 | 10.4k | } |
779 | 41.9k | for (int i = 0; i < 3; i++) { // always 0 |
780 | 31.4k | val = input->readLong(1); |
781 | 31.4k | if (val) f << "f" << i << "=" << std::hex << val << std::dec << ","; |
782 | 31.4k | } |
783 | 10.4k | val = long(input->readULong(4)); |
784 | 10.4k | defPos.push_back(pos+val); |
785 | | // fixme: used this to read the data... |
786 | 10.4k | f << "defPos=" << std::hex << pos+val << std::dec << ","; |
787 | 10.4k | ascii().addPos(pos); |
788 | 10.4k | ascii().addNote(f.str().c_str()); |
789 | 10.4k | } |
790 | | |
791 | 9.11k | for (int n = 0; n < N; n++) { |
792 | 8.51k | pos = defPos[size_t(n)]; |
793 | 8.51k | if (pos+12 > entry.end()) { |
794 | 452 | MWAW_DEBUG_MSG(("WriteNowParser::readColorMap: can not read entry : %d\n", n)); |
795 | 452 | return false; |
796 | 452 | } |
797 | | |
798 | 8.06k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
799 | 8.06k | f.str(""); |
800 | 8.06k | f << "ColorMapData[" << n << "]:"; |
801 | 8.06k | unsigned char col[4]; |
802 | 32.2k | for (auto &c : col) c = static_cast<unsigned char>(input->readULong(2)/256); |
803 | 8.06k | f << "col=" << MWAWColor(col[0],col[1],col[2],col[3]) << ","; |
804 | 8.06k | m_state->m_colorMap.push_back(MWAWColor(static_cast<unsigned char>(col[0]),static_cast<unsigned char>(col[1]),static_cast<unsigned char>(col[2]))); |
805 | | |
806 | 8.06k | auto sz = static_cast<int>(input->readULong(1)); |
807 | 8.06k | if (pos+8+1+sz > entry.end()) { |
808 | 58 | MWAW_DEBUG_MSG(("WriteNowParser::readColorMap: can not read end of entry : %d\n", n)); |
809 | 58 | return false; |
810 | 58 | } |
811 | 8.00k | std::string name(""); |
812 | 24.9k | for (int i = 0; i < sz; i++) name += char(input->readULong(1)); |
813 | | |
814 | 8.00k | if (name.length()) f << name; |
815 | 8.00k | ascii().addPos(pos); |
816 | 8.00k | ascii().addNote(f.str().c_str()); |
817 | 8.00k | } |
818 | | |
819 | 599 | entry.setParsed(true); |
820 | 599 | ascii().addPos(entry.end()); |
821 | 599 | ascii().addNote("_"); |
822 | 599 | return true; |
823 | 1.10k | } |
824 | | |
825 | | //////////////////////////////////////////////////////////// |
826 | | // try to read the print info zone |
827 | | //////////////////////////////////////////////////////////// |
828 | | bool WriteNowParser::readPrintInfo(WriteNowEntry const &entry) |
829 | 8.92k | { |
830 | 8.92k | MWAWInputStreamPtr input = getInput(); |
831 | 8.92k | int expectedLength = version() <= 2 ? 0x78+2 : 0x88; |
832 | 8.92k | if (!entry.valid() || entry.length() < expectedLength) { |
833 | 2.60k | MWAW_DEBUG_MSG(("WriteNowParser::readPrintInfo: zone size is invalid\n")); |
834 | 2.60k | return false; |
835 | 2.60k | } |
836 | | |
837 | 6.32k | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
838 | 6.32k | long sz = version() <= 2 ? 2+long(input->readULong(2)) : long(input->readULong(4)); |
839 | 6.32k | if (sz != entry.length()) { |
840 | 88 | MWAW_DEBUG_MSG(("WriteNowParser::readPrintInfo: bad begin of last zone\n")); |
841 | 88 | return false; |
842 | 88 | } |
843 | 6.23k | libmwaw::DebugStream f; |
844 | 6.23k | f << "Entries(PrintInfo):"; |
845 | 6.23k | if (version()>=3) { |
846 | 955 | f << "ptr?=" << std::hex << input->readULong(4) << std::dec << ","; |
847 | 955 | f << "ptr2?=" << std::hex << input->readULong(4) << std::dec << ","; |
848 | 955 | long val; |
849 | 4.77k | for (int i = 0; i < 4; i++) { // 15, 0, ??, ??? |
850 | 3.82k | val = input->readLong(2); |
851 | 3.82k | if (val) f << "f" << i << "=" << std::hex << val << std::dec << ","; |
852 | 3.82k | } |
853 | 2.86k | for (int i = 0; i < 2; i++) { // 0 |
854 | 1.91k | val = input->readLong(2); |
855 | 1.91k | if (val) f << "g" << i << "=" << val << ","; |
856 | 1.91k | } |
857 | 955 | } |
858 | 6.23k | libmwaw::PrinterInfo info; |
859 | 6.23k | if (!info.read(input)) { |
860 | 4.20k | MWAW_DEBUG_MSG(("WriteNowParser::readPrintInfo: can not read print info\n")); |
861 | 4.20k | return false; |
862 | 4.20k | } |
863 | 2.03k | f << info; |
864 | | |
865 | 2.03k | MWAWVec2i paperSize = info.paper().size(); |
866 | 2.03k | MWAWVec2i pageSize = info.page().size(); |
867 | 2.03k | if (pageSize.x() <= 0 || pageSize.y() <= 0 || |
868 | 1.36k | paperSize.x() <= 0 || paperSize.y() <= 0) return false; |
869 | | |
870 | | // define margin from print info |
871 | 1.18k | MWAWVec2i lTopMargin= -1 * info.paper().pos(0); |
872 | 1.18k | MWAWVec2i rBotMargin=info.paper().size() - info.page().size(); |
873 | | |
874 | | // move margin left | top |
875 | 1.18k | int decalX = lTopMargin.x() > 14 ? lTopMargin.x()-14 : 0; |
876 | 1.18k | int decalY = lTopMargin.y() > 14 ? lTopMargin.y()-14 : 0; |
877 | 1.18k | lTopMargin -= MWAWVec2i(decalX, decalY); |
878 | 1.18k | rBotMargin += MWAWVec2i(decalX, decalY); |
879 | | |
880 | | // decrease right | bottom |
881 | 1.18k | int rightMarg = rBotMargin.x() -50; |
882 | 1.18k | if (rightMarg < 0) rightMarg=0; |
883 | 1.18k | int botMarg = rBotMargin.y() -50; |
884 | 1.18k | if (botMarg < 0) botMarg=0; |
885 | | |
886 | 1.18k | getPageSpan().setMarginTop(lTopMargin.y()/72.0); |
887 | 1.18k | getPageSpan().setMarginBottom(botMarg/72.0); |
888 | 1.18k | getPageSpan().setMarginLeft(lTopMargin.x()/72.0); |
889 | 1.18k | getPageSpan().setMarginRight(rightMarg/72.0); |
890 | 1.18k | getPageSpan().setFormLength(paperSize.y()/72.); |
891 | 1.18k | getPageSpan().setFormWidth(paperSize.x()/72.); |
892 | | |
893 | 1.18k | entry.setParsed(true); |
894 | 1.18k | ascii().addPos(entry.begin()); |
895 | 1.18k | ascii().addNote(f.str().c_str()); |
896 | 1.18k | ascii().addPos(entry.end()); |
897 | 1.18k | ascii().addNote("_"); |
898 | 1.18k | return true; |
899 | 2.03k | } |
900 | | |
901 | | //////////////////////////////////////////////////////////// |
902 | | // try to read the last generic zone ( always find N=0 :-~) |
903 | | //////////////////////////////////////////////////////////// |
904 | | bool WriteNowParser::readGenericUnkn(WriteNowEntry const &entry) |
905 | 1.63k | { |
906 | 1.63k | MWAWInputStreamPtr input = getInput(); |
907 | | |
908 | 1.63k | if (!entry.valid() || entry.length() < 0x10) { |
909 | 4 | MWAW_DEBUG_MSG(("WriteNowParser::readGenericUnkn: zone size is invalid\n")); |
910 | 4 | return false; |
911 | 4 | } |
912 | | |
913 | 1.62k | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
914 | 1.62k | if (input->readLong(4) != entry.length()) { |
915 | 380 | MWAW_DEBUG_MSG(("WriteNowParser::readGenericUnkn: bad begin of last zone\n")); |
916 | 380 | return false; |
917 | 380 | } |
918 | 1.24k | libmwaw::DebugStream f; |
919 | 1.24k | f << "Entries(" << entry.type() << "):"; |
920 | 1.24k | f << "ptr?=" << std::hex << input->readULong(4) << std::dec << ","; |
921 | 1.24k | f << "ptr2?=" << std::hex << input->readULong(4) << std::dec << ","; |
922 | 1.24k | long pos, val; |
923 | 4.99k | for (int i = 0; i < 3; i++) { // 7, 0, 0 |
924 | 3.74k | val = input->readLong(2); |
925 | 3.74k | if (val) f << "f" << i << "=" << std::hex << val << std::dec << ","; |
926 | 3.74k | } |
927 | 1.24k | auto N=static_cast<int>(input->readULong(2)); |
928 | 1.24k | f << "N=" << N << ","; |
929 | 3.74k | for (int i = 0; i < 2; i++) { // 0 |
930 | 2.49k | val = input->readLong(2); |
931 | 2.49k | if (val) f << "g" << i << "=" << val << ","; |
932 | 2.49k | } |
933 | 1.24k | if (long(input->tell())+N*8 > entry.end()) { |
934 | 157 | MWAW_DEBUG_MSG(("WriteNowParser::readGenericUnkn: the zone is too short\n")); |
935 | 157 | return false; |
936 | 157 | } |
937 | 1.09k | ascii().addPos(entry.begin()); |
938 | 1.09k | ascii().addNote(f.str().c_str()); |
939 | 1.09k | std::vector<long> defPos; |
940 | 1.26k | for (int n = 0; n < N; n++) { |
941 | 174 | pos = input->tell(); |
942 | 174 | f.str(""); |
943 | 174 | f << entry.type() << "[" << n << "]:"; |
944 | 174 | auto type = static_cast<int>(input->readULong(1)); |
945 | 174 | switch (type) { |
946 | 86 | case 0: |
947 | 86 | f << "def,"; |
948 | 86 | break; |
949 | 88 | default: |
950 | 88 | MWAW_DEBUG_MSG(("WriteNowParser::readGenericUnkn: find unknown type %d\n", type)); |
951 | 88 | f << "#type=" << type << ","; |
952 | 88 | break; |
953 | 174 | } |
954 | 696 | for (int i = 0; i < 3; i++) { // always 0 |
955 | 522 | val = input->readLong(1); |
956 | 522 | if (val) f << "f" << i << "=" << std::hex << val << std::dec << ","; |
957 | 522 | } |
958 | 174 | val = long(input->readULong(4)); |
959 | 174 | defPos.push_back(pos+val); |
960 | | // fixme: used this to read the data... |
961 | 174 | f << "defPos=" << std::hex << pos+val << std::dec << ","; |
962 | 174 | ascii().addPos(pos); |
963 | 174 | ascii().addNote(f.str().c_str()); |
964 | 174 | } |
965 | | |
966 | 1.24k | for (int n = 0; n < N; n++) { |
967 | 159 | pos = defPos[size_t(n)]; |
968 | 159 | if (pos == entry.end()) continue; |
969 | 159 | if (pos+12 > entry.end()) { |
970 | 8 | MWAW_DEBUG_MSG(("WriteNowParser::readGenericUnkn: can not read entry : %d\n", n)); |
971 | 8 | return false; |
972 | 8 | } |
973 | | |
974 | 151 | input->seek(pos, librevenge::RVNG_SEEK_SET); |
975 | 151 | f.str(""); |
976 | 151 | f << entry.type() << "Data[" << n << "]:"; |
977 | | |
978 | 151 | ascii().addPos(pos); |
979 | 151 | ascii().addNote(f.str().c_str()); |
980 | 151 | } |
981 | | |
982 | 1.08k | entry.setParsed(true); |
983 | 1.08k | ascii().addPos(entry.end()); |
984 | 1.08k | ascii().addNote("_"); |
985 | 1.08k | return true; |
986 | 1.09k | } |
987 | | |
988 | | bool WriteNowParser::checkIfPositionValid(long pos) |
989 | 8.22M | { |
990 | 8.22M | if (pos <= m_state->m_endPos) |
991 | 3.24M | return true; |
992 | 4.97M | MWAWInputStreamPtr input = getInput(); |
993 | 4.97M | long actPos = input->tell(); |
994 | 4.97M | input->seek(pos, librevenge::RVNG_SEEK_SET); |
995 | 4.97M | bool ok = long(input->tell())==pos; |
996 | 4.97M | if (ok) m_state->m_endPos = pos; |
997 | | |
998 | 4.97M | input->seek(actPos, librevenge::RVNG_SEEK_SET); |
999 | 4.97M | return ok; |
1000 | 8.22M | } |
1001 | | |
1002 | | WriteNowEntry WriteNowParser::readEntry() |
1003 | 36.3k | { |
1004 | 36.3k | WriteNowEntry res; |
1005 | 36.3k | MWAWInputStreamPtr input = getInput(); |
1006 | 36.3k | auto val = static_cast<int>(input->readULong(2)); |
1007 | 36.3k | res.m_fileType = (val >> 12); |
1008 | 36.3k | res.m_val[0]= val & 0x0FFF; |
1009 | 36.3k | res.m_val[1]= static_cast<int>(input->readLong(2)); |
1010 | 36.3k | if (res.isZoneType()) { |
1011 | 23.6k | res.setBegin(long(input->readULong(4))); |
1012 | 23.6k | res.setLength(long(input->readULong(4))); |
1013 | 23.6k | if (!checkIfPositionValid(res.end())) { |
1014 | 1.59k | MWAW_DEBUG_MSG(("WriteNowParser::readEntry: find an invalid entry\n")); |
1015 | 1.59k | res.setLength(0); |
1016 | 1.59k | } |
1017 | 23.6k | } |
1018 | 12.6k | else { |
1019 | 12.6k | res.m_val[2]= static_cast<int>(input->readLong(4)); |
1020 | 12.6k | res.m_val[3]= static_cast<int>(input->readLong(4)); |
1021 | 12.6k | } |
1022 | 36.3k | return res; |
1023 | 36.3k | } |
1024 | | |
1025 | | //////////////////////////////////////////////////////////// |
1026 | | // read the header |
1027 | | //////////////////////////////////////////////////////////// |
1028 | | bool WriteNowParser::checkHeader(MWAWHeader *header, bool strict) |
1029 | 111k | { |
1030 | 111k | *m_state = WriteNowParserInternal::State(); |
1031 | | |
1032 | 111k | MWAWInputStreamPtr input = getInput(); |
1033 | 111k | if (!input || !input->hasDataFork()) |
1034 | 0 | return false; |
1035 | | |
1036 | 111k | libmwaw::DebugStream f; |
1037 | 111k | int headerSize=28; |
1038 | 111k | input->seek(headerSize,librevenge::RVNG_SEEK_SET); |
1039 | 111k | if (int(input->tell()) != headerSize) { |
1040 | 481 | MWAW_DEBUG_MSG(("WriteNowParser::checkHeader: file is too short\n")); |
1041 | 481 | return false; |
1042 | 481 | } |
1043 | 111k | input->seek(0, librevenge::RVNG_SEEK_SET); |
1044 | 111k | auto val = long(input->readULong(4)); |
1045 | 111k | int vers = 0; |
1046 | 111k | switch (val) { |
1047 | 102k | case 0: |
1048 | 102k | if (input->readULong(4) != 0) |
1049 | 0 | return false; |
1050 | 102k | vers = 2; |
1051 | 102k | break; |
1052 | 8.57k | case 0x57726974: // Writ |
1053 | 8.57k | if (input->readULong(4) != 0x654e6f77) // eNow |
1054 | 0 | return false; |
1055 | 8.57k | vers = 3; |
1056 | 8.57k | break; |
1057 | 0 | default: |
1058 | 0 | return false; |
1059 | 111k | } |
1060 | 111k | setVersion(vers); |
1061 | 111k | f << "FileHeader:"; |
1062 | | |
1063 | 111k | if (vers < 3) { |
1064 | 102k | if (strict) { |
1065 | 187k | for (int i=0; i < 4; ++i) { |
1066 | 160k | val = long(input->readLong(1)); |
1067 | 160k | if (val!=4 && val!=0x44) return false; |
1068 | 135k | input->seek(3, librevenge::RVNG_SEEK_CUR); |
1069 | 135k | } |
1070 | 27.3k | input->seek(8, librevenge::RVNG_SEEK_SET); |
1071 | 27.3k | } |
1072 | | |
1073 | 77.4k | ascii().addPos(0); |
1074 | 77.4k | ascii().addNote(f.str().c_str()); |
1075 | 77.4k | ascii().addPos(input->tell()); |
1076 | | |
1077 | 77.4k | return true; |
1078 | 102k | } |
1079 | | |
1080 | 8.57k | val = long(input->readULong(2)); |
1081 | 8.57k | if (strict && val > 3) |
1082 | 0 | return false; |
1083 | 8.57k | #ifndef DEBUG |
1084 | 8.57k | if (val != 2) return false; |
1085 | 8.57k | #endif |
1086 | 8.57k | f << "f0=" << val << ","; |
1087 | | |
1088 | 34.3k | for (int i = 1; i < 4; i++) { |
1089 | | // all zero, excepted f1=1 in one file... |
1090 | 25.7k | val = input->readLong(2); |
1091 | 25.7k | if (val) f << "f" << i << "=" << val << ","; |
1092 | 25.7k | } |
1093 | | |
1094 | | // a flag ?? |
1095 | 8.57k | val = long(input->readULong(2)); |
1096 | 8.57k | if (val != 0x4000) f << "fl=" << std::hex << val << std::dec << ","; |
1097 | 8.57k | val = long(input->readLong(2)); |
1098 | 8.57k | if (val) f << "f4=" << val << ","; |
1099 | | |
1100 | | // last entry |
1101 | 8.57k | WriteNowEntry entry; |
1102 | 8.57k | entry.setBegin(long(input->readULong(4))); |
1103 | 8.57k | entry.setLength(long(input->readULong(4))); |
1104 | 8.57k | entry.m_fileType = 4; |
1105 | | |
1106 | 8.57k | if (!checkIfPositionValid(entry.end())) { |
1107 | 1.24k | MWAW_DEBUG_MSG(("WriteNowParser::checkHeader: can not find final zone\n")); |
1108 | 1.24k | return false; |
1109 | 1.24k | } |
1110 | 7.33k | entry.setType("DocEntries"); |
1111 | 7.33k | m_entryManager->add(entry); |
1112 | | |
1113 | 7.33k | f << "entry=" << std::hex << entry.begin() << ":" << entry.end() << std::dec << ","; |
1114 | | |
1115 | | // ok, we can finish initialization |
1116 | 7.33k | if (header) |
1117 | 2.59k | header->reset(MWAWDocument::MWAW_T_WRITENOW, version()); |
1118 | | |
1119 | | // |
1120 | 7.33k | input->seek(headerSize, librevenge::RVNG_SEEK_SET); |
1121 | | |
1122 | 7.33k | ascii().addPos(0); |
1123 | 7.33k | ascii().addNote(f.str().c_str()); |
1124 | 7.33k | ascii().addPos(headerSize); |
1125 | | |
1126 | 7.33k | return true; |
1127 | 8.57k | } |
1128 | | |
1129 | | // vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: |