/src/libmwaw/src/lib/MarinerWrtParser.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 <string.h> |
35 | | |
36 | | #include <iomanip> |
37 | | #include <iostream> |
38 | | #include <limits> |
39 | | #include <map> |
40 | | #include <set> |
41 | | #include <sstream> |
42 | | #include <string> |
43 | | |
44 | | #include <librevenge/librevenge.h> |
45 | | |
46 | | #include "MWAWCell.hxx" |
47 | | #include "MWAWTextListener.hxx" |
48 | | #include "MWAWFont.hxx" |
49 | | #include "MWAWFontConverter.hxx" |
50 | | #include "MWAWHeader.hxx" |
51 | | #include "MWAWList.hxx" |
52 | | #include "MWAWParagraph.hxx" |
53 | | #include "MWAWPosition.hxx" |
54 | | #include "MWAWPictMac.hxx" |
55 | | #include "MWAWPrinter.hxx" |
56 | | #include "MWAWSection.hxx" |
57 | | #include "MWAWSubDocument.hxx" |
58 | | |
59 | | #include "MarinerWrtGraph.hxx" |
60 | | #include "MarinerWrtText.hxx" |
61 | | |
62 | | #include "MarinerWrtParser.hxx" |
63 | | |
64 | | /** Internal: the structures of a MarinerWrtParser */ |
65 | | namespace MarinerWrtParserInternal |
66 | | { |
67 | | //////////////////////////////////////// |
68 | | //! Internal: the struct used to store the zone of a MarinerWrtParser |
69 | | struct Zone { |
70 | | //! a enum to define the diffent zone type |
71 | | enum Type { Z_Main, Z_Footnote, Z_Header, Z_Footer, Z_Unknown }; |
72 | | //! constructor |
73 | | Zone() |
74 | 115k | : m_id(-1) |
75 | 115k | , m_fileId(0) |
76 | 115k | , m_type(Z_Unknown) |
77 | 115k | , m_endNote(false) |
78 | 115k | , m_height(0) |
79 | 115k | , m_RBpos(0,0) |
80 | 115k | , m_dim() |
81 | 115k | , m_pageDim() |
82 | 115k | , m_pageTextDim() |
83 | 115k | , m_section() |
84 | 115k | , m_backgroundColor(MWAWColor::white()) |
85 | 115k | , m_extra("") |
86 | 115k | { |
87 | 115k | } |
88 | | //! operator<< |
89 | | friend std::ostream &operator<<(std::ostream &o, Zone const &zone); |
90 | | //! the zone id |
91 | | int m_id; |
92 | | //! the file zone id |
93 | | uint32_t m_fileId; |
94 | | //! the zone type |
95 | | Type m_type; |
96 | | //! a flag to know if this an endnote |
97 | | bool m_endNote; |
98 | | //! height of the zone |
99 | | long m_height; |
100 | | //! right/bottom position |
101 | | MWAWVec2l m_RBpos; |
102 | | //! the zone total position |
103 | | MWAWBox2l m_dim; |
104 | | //! the page dimension (?) |
105 | | MWAWBox2i m_pageDim; |
106 | | //! the zone of text dimension ( ie page less margins) |
107 | | MWAWBox2i m_pageTextDim; |
108 | | //! the section |
109 | | MWAWSection m_section; |
110 | | //! the background color |
111 | | MWAWColor m_backgroundColor; |
112 | | //! extra data |
113 | | std::string m_extra; |
114 | | }; |
115 | | |
116 | | std::ostream &operator<<(std::ostream &o, Zone const &zone) |
117 | 0 | { |
118 | 0 | switch (zone.m_type) { |
119 | 0 | case Zone::Z_Main: |
120 | 0 | o << "main,"; |
121 | 0 | break; |
122 | 0 | case Zone::Z_Footnote: |
123 | 0 | if (zone.m_endNote) |
124 | 0 | o << "endnote,"; |
125 | 0 | else |
126 | 0 | o << "footnote,"; |
127 | 0 | break; |
128 | 0 | case Zone::Z_Header: |
129 | 0 | o << "header,"; |
130 | 0 | break; |
131 | 0 | case Zone::Z_Footer: |
132 | 0 | o << "footer,"; |
133 | 0 | break; |
134 | 0 | case Zone::Z_Unknown: |
135 | | #if !defined(__clang__) |
136 | | default: |
137 | | #endif |
138 | 0 | break; |
139 | 0 | } |
140 | 0 | if (zone.m_type==Zone::Z_Header || zone.m_type==Zone::Z_Footer) { |
141 | 0 | switch (zone.m_fileId) { |
142 | 0 | case 0: |
143 | 0 | break; // main |
144 | 0 | case 1: |
145 | 0 | o << "left,"; |
146 | 0 | break; |
147 | 0 | case 2: |
148 | 0 | o << "right,"; |
149 | 0 | break; |
150 | 0 | case 3: |
151 | 0 | o << "firstpage,"; |
152 | 0 | break; |
153 | 0 | default: |
154 | 0 | o << "#fileId" << zone.m_fileId << ","; |
155 | 0 | break; |
156 | 0 | } |
157 | 0 | } |
158 | 0 | else if (zone.m_fileId & 0xFFFFFF) |
159 | 0 | o << "fileId=" << std::hex << (zone.m_fileId&0xFFFFFF) << std::dec << ","; |
160 | 0 | if (zone.m_RBpos[0] || zone.m_RBpos[1]) |
161 | 0 | o << "RBpos=" << zone.m_RBpos << ","; |
162 | 0 | if (zone.m_height) |
163 | 0 | o << "height=" << zone.m_height << ","; |
164 | 0 | if (zone.m_dim.size()[0] || zone.m_dim.size()[1]) |
165 | 0 | o << "dim=" << zone.m_dim << ","; |
166 | 0 | if (!zone.m_backgroundColor.isWhite()) |
167 | 0 | o << "background=" << zone.m_backgroundColor << ","; |
168 | 0 | o << zone.m_extra; |
169 | 0 | return o; |
170 | 0 | } |
171 | | //////////////////////////////////////// |
172 | | //! Internal: the state of a MarinerWrtParser |
173 | | struct State { |
174 | | //! constructor |
175 | | State() |
176 | 172k | : m_zonesList() |
177 | 172k | , m_fileToZoneMap() |
178 | 172k | , m_actPage(0) |
179 | 172k | , m_numPages(0) |
180 | 172k | , m_firstPageFooter(false) |
181 | 172k | , m_hasOddEvenHeaderFooter(false) |
182 | 172k | { |
183 | 172k | } |
184 | | |
185 | | //! the list of zone |
186 | | std::vector<Zone> m_zonesList; |
187 | | //! a map fileZoneId -> localZoneId |
188 | | std::map<uint32_t,int> m_fileToZoneMap; |
189 | | int m_actPage /** the actual page */, m_numPages /** the number of page of the final document */; |
190 | | /** a flag to know if we have a first page footer */ |
191 | | bool m_firstPageFooter; |
192 | | /** a flag to know if we have odd/even header footer */ |
193 | | bool m_hasOddEvenHeaderFooter; |
194 | | }; |
195 | | |
196 | | //////////////////////////////////////// |
197 | | //! Internal: the subdocument of a MarinerWrtParser |
198 | | class SubDocument final : public MWAWSubDocument |
199 | | { |
200 | | public: |
201 | | SubDocument(MarinerWrtParser &pars, MWAWInputStreamPtr const &input, int zoneId) |
202 | 1.44k | : MWAWSubDocument(&pars, input, MWAWEntry()) |
203 | 1.44k | , m_id(zoneId) |
204 | 1.44k | { |
205 | 1.44k | } |
206 | | |
207 | | //! destructor |
208 | 0 | ~SubDocument() final {} |
209 | | |
210 | | //! operator!= |
211 | | bool operator!=(MWAWSubDocument const &doc) const final |
212 | 0 | { |
213 | 0 | if (MWAWSubDocument::operator!=(doc)) return true; |
214 | 0 | auto const *sDoc = dynamic_cast<SubDocument const *>(&doc); |
215 | 0 | if (!sDoc) return true; |
216 | 0 | if (m_id != sDoc->m_id) return true; |
217 | 0 | return false; |
218 | 0 | } |
219 | | |
220 | | //! the parser function |
221 | | void parse(MWAWListenerPtr &listener, libmwaw::SubDocumentType type) final; |
222 | | |
223 | | protected: |
224 | | //! the subdocument id |
225 | | int m_id; |
226 | | }; |
227 | | |
228 | | void SubDocument::parse(MWAWListenerPtr &listener, libmwaw::SubDocumentType /*type*/) |
229 | 1.35k | { |
230 | 1.35k | if (!listener.get()) { |
231 | 0 | MWAW_DEBUG_MSG(("MarinerWrtParserInternal::SubDocument::parse: no listener\n")); |
232 | 0 | return; |
233 | 0 | } |
234 | 1.35k | auto *parser=dynamic_cast<MarinerWrtParser *>(m_parser); |
235 | 1.35k | if (!parser) { |
236 | 0 | MWAW_DEBUG_MSG(("MarinerWrtParserInternal::SubDocument::parse: no parser\n")); |
237 | 0 | return; |
238 | 0 | } |
239 | 1.35k | long pos = m_input->tell(); |
240 | 1.35k | parser->sendText(m_id); |
241 | 1.35k | m_input->seek(pos, librevenge::RVNG_SEEK_SET); |
242 | 1.35k | } |
243 | | } |
244 | | |
245 | | //////////////////////////////////////////////////////////// |
246 | | // constructor/destructor + basic interface ... |
247 | | //////////////////////////////////////////////////////////// |
248 | | MarinerWrtParser::MarinerWrtParser(MWAWInputStreamPtr const &input, MWAWRSRCParserPtr const &rsrcParser, MWAWHeader *header) |
249 | 74.0k | : MWAWTextParser(input, rsrcParser, header) |
250 | 74.0k | , m_state() |
251 | 74.0k | , m_pageMarginsSpanSet(false) |
252 | 74.0k | , m_graphParser() |
253 | 74.0k | , m_textParser() |
254 | 74.0k | { |
255 | 74.0k | init(); |
256 | 74.0k | } |
257 | | |
258 | | MarinerWrtParser::~MarinerWrtParser() |
259 | 74.0k | { |
260 | 74.0k | } |
261 | | |
262 | | void MarinerWrtParser::init() |
263 | 74.0k | { |
264 | 74.0k | resetTextListener(); |
265 | 74.0k | setAsciiName("main-1"); |
266 | | |
267 | 74.0k | m_state.reset(new MarinerWrtParserInternal::State); |
268 | | |
269 | | // reduce the margin (in case, the page is not defined) |
270 | 74.0k | getPageSpan().setMargins(0.1); |
271 | | |
272 | 74.0k | m_graphParser.reset(new MarinerWrtGraph(*this)); |
273 | 74.0k | m_textParser.reset(new MarinerWrtText(*this)); |
274 | 74.0k | } |
275 | | |
276 | | //////////////////////////////////////////////////////////// |
277 | | // position and height |
278 | | //////////////////////////////////////////////////////////// |
279 | | MWAWVec2f MarinerWrtParser::getPageLeftTop() const |
280 | 0 | { |
281 | 0 | return MWAWVec2f(float(getPageSpan().getMarginLeft()), |
282 | 0 | float(getPageSpan().getMarginTop())); |
283 | 0 | } |
284 | | |
285 | | MWAWSection MarinerWrtParser::getSection(int zId) const |
286 | 4.83k | { |
287 | 4.83k | if (zId >= 0 && zId < int(m_state->m_zonesList.size())) |
288 | 4.83k | return m_state->m_zonesList[size_t(zId)].m_section; |
289 | 0 | return MWAWSection(); |
290 | 4.83k | } |
291 | | |
292 | | //////////////////////////////////////////////////////////// |
293 | | // new page |
294 | | //////////////////////////////////////////////////////////// |
295 | | void MarinerWrtParser::newPage(int number) |
296 | 38.1k | { |
297 | 38.1k | if (number <= m_state->m_actPage || number > m_state->m_numPages) |
298 | 24.6k | return; |
299 | | |
300 | 27.0k | while (m_state->m_actPage < number) { |
301 | 13.5k | m_state->m_actPage++; |
302 | 13.5k | if (!getTextListener() || m_state->m_actPage == 1) |
303 | 4.83k | continue; |
304 | 8.70k | getTextListener()->insertBreak(MWAWTextListener::PageBreak); |
305 | 8.70k | } |
306 | 13.5k | } |
307 | | |
308 | | //////////////////////////////////////////////////////////// |
309 | | // interface |
310 | | //////////////////////////////////////////////////////////// |
311 | | int MarinerWrtParser::getZoneId(uint32_t fileId, bool &endNote) |
312 | 2.95k | { |
313 | 2.95k | if (m_state->m_fileToZoneMap.find(fileId)==m_state->m_fileToZoneMap.end()) { |
314 | 2.41k | MWAW_DEBUG_MSG(("MarinerWrtParser::getZoneId: can not find zone for %x\n", fileId)); |
315 | 2.41k | return -1; |
316 | 2.41k | } |
317 | 543 | int id=m_state->m_fileToZoneMap.find(fileId)->second; |
318 | 543 | endNote=false; |
319 | 543 | if (id>=0 && id < int(m_state->m_zonesList.size())) |
320 | 543 | endNote = m_state->m_zonesList[size_t(id)].m_endNote; |
321 | 543 | return id; |
322 | 2.95k | } |
323 | | |
324 | | void MarinerWrtParser::sendText(int zoneId) |
325 | 4.30k | { |
326 | 4.30k | MWAWInputStreamPtr input = getInput(); |
327 | 4.30k | long actPos = input->tell(); |
328 | 4.30k | m_textParser->send(zoneId); |
329 | 4.30k | input->seek(actPos, librevenge::RVNG_SEEK_SET); |
330 | 4.30k | } |
331 | | |
332 | | float MarinerWrtParser::getPatternPercent(int id) const |
333 | 403k | { |
334 | 403k | return m_graphParser->getPatternPercent(id); |
335 | 403k | } |
336 | | |
337 | | void MarinerWrtParser::sendToken(int zoneId, long tokenId) |
338 | 16.6k | { |
339 | 16.6k | MWAWInputStreamPtr input = getInput(); |
340 | 16.6k | long actPos = input->tell(); |
341 | 16.6k | m_graphParser->sendToken(zoneId, tokenId); |
342 | 16.6k | input->seek(actPos, librevenge::RVNG_SEEK_SET); |
343 | 16.6k | } |
344 | | |
345 | | //////////////////////////////////////////////////////////// |
346 | | // the parser |
347 | | //////////////////////////////////////////////////////////// |
348 | | void MarinerWrtParser::parse(librevenge::RVNGTextInterface *docInterface) |
349 | 24.1k | { |
350 | 24.1k | if (!getInput().get() || !checkHeader(nullptr)) throw(libmwaw::ParseException()); |
351 | 24.1k | bool ok = true; |
352 | 24.1k | try { |
353 | | // create the asciiFile |
354 | 24.1k | ascii().setStream(getInput()); |
355 | 24.1k | ascii().open(asciiName()); |
356 | | |
357 | 24.1k | checkHeader(nullptr); |
358 | 24.1k | ok = createZones(); |
359 | 24.1k | if (ok) { |
360 | 6.90k | createDocument(docInterface); |
361 | 6.90k | m_graphParser->sendPageGraphics(); |
362 | 6.90k | m_textParser->send(0); |
363 | | |
364 | | #ifdef DEBUG |
365 | | m_textParser->flushExtra(); |
366 | | m_graphParser->flushExtra(); |
367 | | #endif |
368 | 6.90k | } |
369 | 24.1k | ascii().reset(); |
370 | 24.1k | } |
371 | 24.1k | catch (...) { |
372 | 0 | MWAW_DEBUG_MSG(("MarinerWrtParser::parse: exception catched when parsing\n")); |
373 | 0 | ok = false; |
374 | 0 | } |
375 | | |
376 | 24.1k | resetTextListener(); |
377 | 24.1k | if (!ok) throw(libmwaw::ParseException()); |
378 | 24.1k | } |
379 | | |
380 | | //////////////////////////////////////////////////////////// |
381 | | // create the document |
382 | | //////////////////////////////////////////////////////////// |
383 | | void MarinerWrtParser::createDocument(librevenge::RVNGTextInterface *documentInterface) |
384 | 6.90k | { |
385 | 6.90k | if (!documentInterface) return; |
386 | 6.90k | if (getTextListener()) { |
387 | 0 | MWAW_DEBUG_MSG(("MarinerWrtParser::createDocument: listener already exist\n")); |
388 | 0 | return; |
389 | 0 | } |
390 | | |
391 | | // update the page |
392 | 6.90k | m_state->m_actPage = 0; |
393 | | |
394 | 6.90k | int numPage = m_textParser->numPages(); |
395 | 6.90k | if (m_graphParser->numPages() > numPage) |
396 | 0 | numPage = m_graphParser->numPages(); |
397 | 6.90k | m_state->m_numPages = numPage; |
398 | | |
399 | | // create the page list |
400 | 6.90k | MWAWPageSpan ps(getPageSpan()); |
401 | 6.90k | if (m_state->m_zonesList.size()) |
402 | 6.90k | ps.setBackgroundColor(m_state->m_zonesList[0].m_backgroundColor); |
403 | | |
404 | | // look for an header/footer |
405 | 6.90k | int headerId[4] = { -1, -1, -1, -1}, footerId[4] = { -1, -1, -1, -1}; |
406 | 82.3k | for (size_t z = 0; z < m_state->m_zonesList.size(); z++) { |
407 | 75.4k | auto const &zone=m_state->m_zonesList[z]; |
408 | 75.4k | if (zone.m_type==MarinerWrtParserInternal::Zone::Z_Header) { |
409 | 1.24k | if (zone.m_fileId < 4) |
410 | 1.22k | headerId[zone.m_fileId]=int(z); |
411 | 1.24k | } |
412 | 74.2k | else if (zone.m_type==MarinerWrtParserInternal::Zone::Z_Footer) { |
413 | 1.14k | if (zone.m_fileId < 4) |
414 | 723 | footerId[zone.m_fileId]=int(z); |
415 | 1.14k | } |
416 | 75.4k | } |
417 | 6.90k | MWAWPageSpan firstPs(ps); |
418 | 6.90k | if (m_state->m_firstPageFooter) { |
419 | 1.21k | if (headerId[3]>0) { |
420 | 367 | MWAWHeaderFooter header(MWAWHeaderFooter::HEADER, MWAWHeaderFooter::ALL); |
421 | 367 | header.m_subDocument.reset(new MarinerWrtParserInternal::SubDocument(*this, getInput(), int(headerId[3]))); |
422 | 367 | firstPs.setHeaderFooter(header); |
423 | 367 | } |
424 | 1.21k | if (footerId[3]>0) { |
425 | 173 | MWAWHeaderFooter footer(MWAWHeaderFooter::FOOTER, MWAWHeaderFooter::ALL); |
426 | 173 | footer.m_subDocument.reset(new MarinerWrtParserInternal::SubDocument(*this, getInput(), int(footerId[3]))); |
427 | 173 | firstPs.setHeaderFooter(footer); |
428 | 173 | } |
429 | 1.21k | } |
430 | 6.98k | for (int st = 0; st < 2; st++) { |
431 | 6.94k | MWAWHeaderFooter::Occurrence what= |
432 | 6.94k | !m_state->m_hasOddEvenHeaderFooter ? MWAWHeaderFooter::ALL : st==0 ? MWAWHeaderFooter::ODD : MWAWHeaderFooter::EVEN; |
433 | 6.94k | int which= !m_state->m_hasOddEvenHeaderFooter ? 0 : 1+st; |
434 | 6.94k | if (headerId[which]>0) { |
435 | 566 | MWAWHeaderFooter header(MWAWHeaderFooter::HEADER, what); |
436 | 566 | header.m_subDocument.reset(new MarinerWrtParserInternal::SubDocument(*this, getInput(), int(headerId[which]))); |
437 | 566 | ps.setHeaderFooter(header); |
438 | 566 | } |
439 | 6.94k | if (footerId[which]>0) { |
440 | 343 | MWAWHeaderFooter footer(MWAWHeaderFooter::FOOTER, what); |
441 | 343 | footer.m_subDocument.reset(new MarinerWrtParserInternal::SubDocument(*this, getInput(), int(footerId[which]))); |
442 | 343 | ps.setHeaderFooter(footer); |
443 | 343 | } |
444 | 6.94k | if (!m_state->m_hasOddEvenHeaderFooter) |
445 | 6.86k | break; |
446 | 6.94k | } |
447 | | |
448 | 6.90k | std::vector<MWAWPageSpan> pageList; |
449 | 6.90k | if (m_state->m_firstPageFooter) { |
450 | 1.21k | pageList.push_back(firstPs); |
451 | 1.21k | ps.setPageSpan(m_state->m_numPages); |
452 | 1.21k | } |
453 | 5.69k | else |
454 | 5.69k | ps.setPageSpan(m_state->m_numPages+1); |
455 | 6.90k | if (ps.getPageSpan()) |
456 | 6.90k | pageList.push_back(ps); |
457 | | // |
458 | 6.90k | MWAWTextListenerPtr listen(new MWAWTextListener(*getParserState(), pageList, documentInterface)); |
459 | 6.90k | setTextListener(listen); |
460 | 6.90k | listen->startDocument(); |
461 | 6.90k | } |
462 | | |
463 | | |
464 | | //////////////////////////////////////////////////////////// |
465 | | // |
466 | | // Intermediate level |
467 | | // |
468 | | //////////////////////////////////////////////////////////// |
469 | | |
470 | | // ------ read the different zones --------- |
471 | | bool MarinerWrtParser::createZones() |
472 | 24.1k | { |
473 | 24.1k | MWAWInputStreamPtr input = getInput(); |
474 | 24.1k | long pos = input->tell(); |
475 | 24.1k | int actZone=-1; |
476 | 579k | while (readZone(actZone)) |
477 | 555k | pos = input->tell(); |
478 | 24.1k | ascii().addPos(pos); |
479 | 24.1k | ascii().addNote("Entries(Loose)"); |
480 | 24.1k | return m_state->m_zonesList.size(); |
481 | 24.1k | } |
482 | | |
483 | | bool MarinerWrtParser::readZone(int &actZone, bool onlyTest) |
484 | 710k | { |
485 | 710k | MWAWInputStreamPtr input = getInput(); |
486 | 710k | if (input->isEnd()) |
487 | 3.32k | return false; |
488 | 706k | long pos = input->tell(); |
489 | 706k | MarinerWrtEntry zone; |
490 | 706k | if (!readEntryHeader(zone)) { |
491 | 26.4k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
492 | 26.4k | return false; |
493 | 26.4k | } |
494 | | |
495 | 680k | libmwaw::DebugStream f; |
496 | 680k | f << "Entries(" << zone.name() << "):" << zone; |
497 | | |
498 | 680k | bool done = false; |
499 | 680k | switch (zone.m_fileType) { |
500 | 215k | case -1: // separator |
501 | 219k | case -2: // last file |
502 | 219k | done = readSeparator(zone); |
503 | 219k | if (onlyTest) |
504 | 76.1k | break; |
505 | 143k | actZone++; |
506 | 143k | break; |
507 | 59.2k | case 0: |
508 | 59.2k | done = readZoneHeader(zone, actZone, onlyTest); |
509 | 59.2k | break; |
510 | 28.0k | case 1: |
511 | 28.0k | done = m_textParser->readTextStruct(zone, actZone); |
512 | 28.0k | break; |
513 | 10.2k | case 2: |
514 | 10.2k | done = m_textParser->readZone(zone, actZone); |
515 | 10.2k | break; |
516 | 10.2k | case 4: |
517 | 29.7k | case 5: |
518 | 29.7k | done = m_textParser->readPLCZone(zone, actZone); |
519 | 29.7k | break; |
520 | 18.1k | case 6: |
521 | 18.1k | done = m_textParser->readFonts(zone, actZone); |
522 | 18.1k | break; |
523 | 58.9k | case 7: |
524 | 58.9k | done = m_textParser->readRulers(zone, actZone); |
525 | 58.9k | break; |
526 | 49.8k | case 8: |
527 | 49.8k | done = m_textParser->readFontNames(zone, actZone); |
528 | 49.8k | break; |
529 | 4.95k | case 9: // zone size |
530 | 4.95k | done = readZoneDim(zone, actZone); |
531 | 4.95k | break; |
532 | 10.4k | case 0xa: // zone size with margins removal |
533 | 10.4k | done = readZoneDim(zone, actZone); |
534 | 10.4k | break; |
535 | 6.53k | case 0xb: // border dim? |
536 | 6.53k | done = readZoneb(zone, actZone); |
537 | 6.53k | break; |
538 | 13.3k | case 0xc: |
539 | 13.3k | done = readZonec(zone, actZone); |
540 | 13.3k | break; |
541 | 51.8k | case 0xf: |
542 | 51.8k | done = readDocInfo(zone, actZone); |
543 | 51.8k | break; |
544 | 11.0k | case 0x13: |
545 | 11.0k | done = readZone13(zone, actZone); |
546 | 11.0k | break; |
547 | 50.1k | case 0x14: |
548 | 50.1k | done = m_graphParser->readToken(zone, actZone); |
549 | 50.1k | break; |
550 | 12.0k | case 0x1a: |
551 | 12.0k | done = m_textParser->readStyleNames(zone, actZone); |
552 | 12.0k | break; |
553 | 3.45k | case 0x1f: |
554 | 3.45k | done = readPrintInfo(zone); |
555 | 3.45k | break; |
556 | 3.94k | case 0x24: |
557 | 3.94k | done = readCPRT(zone); |
558 | 3.94k | break; |
559 | | /* 0x41a: docInfo */ |
560 | 7.15k | case 0x420: |
561 | 7.15k | done = m_graphParser->readPostscript(zone, actZone); |
562 | 7.15k | break; |
563 | 31.5k | default: |
564 | 31.5k | break; |
565 | 680k | } |
566 | 680k | if (done) { |
567 | 538k | ascii().addPos(pos); |
568 | 538k | ascii().addNote(f.str().c_str()); |
569 | 538k | input->seek(zone.end(), librevenge::RVNG_SEEK_SET); |
570 | 538k | return true; |
571 | 538k | } |
572 | 141k | if (onlyTest) |
573 | 11.8k | return false; |
574 | 129k | input->seek(zone.begin(), librevenge::RVNG_SEEK_SET); |
575 | 129k | input->pushLimit(zone.end()); |
576 | 129k | std::vector<MarinerWrtStruct> dataList; |
577 | 129k | decodeZone(dataList); |
578 | 129k | input->popLimit(); |
579 | | |
580 | 129k | size_t numData = dataList.size(); |
581 | 129k | f << "numData=" << numData << ","; |
582 | 129k | ascii().addPos(pos); |
583 | 129k | ascii().addNote(f.str().c_str()); |
584 | | |
585 | 129k | int numDataByField = zone.m_fileType==1 ? 22 : 10; |
586 | 6.16M | for (size_t d = 0; d < numData; d++) { |
587 | 6.03M | MarinerWrtStruct const &dt = dataList[d]; |
588 | 6.03M | if ((int(d)%numDataByField)==0) { |
589 | 681k | if (d) |
590 | 573k | ascii().addNote(f.str().c_str()); |
591 | 681k | f.str(""); |
592 | 681k | f << zone.name() << "-" << d << ":"; |
593 | 681k | ascii().addPos(dt.m_filePos); |
594 | 681k | } |
595 | 6.03M | f << dt << ","; |
596 | 6.03M | } |
597 | 129k | if (numData) |
598 | 108k | ascii().addNote(f.str().c_str()); |
599 | | |
600 | 129k | if (input->tell() != zone.end()) { |
601 | 74.5k | f.str(""); |
602 | 74.5k | if (input->tell() == zone.end()-1) |
603 | 5.19k | f << "_"; |
604 | 69.4k | else |
605 | 69.4k | f << zone.name() << ":###"; |
606 | 74.5k | ascii().addPos(input->tell()); |
607 | 74.5k | ascii().addNote(f.str().c_str()); |
608 | 74.5k | } |
609 | 129k | input->seek(zone.end(), librevenge::RVNG_SEEK_SET); |
610 | 129k | return true; |
611 | 141k | } |
612 | | |
613 | | // --------- zone separator ---------- |
614 | | |
615 | | // read the zone separator |
616 | | bool MarinerWrtParser::readSeparator(MarinerWrtEntry const &entry) |
617 | 219k | { |
618 | 219k | if (entry.length() < 0x3) { |
619 | 4.34k | MWAW_DEBUG_MSG(("MarinerWrtParser::readSeparator: data seems to short\n")); |
620 | 4.34k | return false; |
621 | 4.34k | } |
622 | 215k | MWAWInputStreamPtr input = getInput(); |
623 | 215k | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
624 | 215k | input->pushLimit(entry.end()); |
625 | 215k | std::vector<MarinerWrtStruct> dataList; |
626 | 215k | decodeZone(dataList); |
627 | 215k | input->popLimit(); |
628 | | |
629 | 215k | if (dataList.size() != 1) { |
630 | 3.11k | MWAW_DEBUG_MSG(("MarinerWrtParser::readSeparator: can find my data\n")); |
631 | 3.11k | return false; |
632 | 3.11k | } |
633 | | |
634 | 212k | MarinerWrtStruct const &data = dataList[0]; // always 0x77aa |
635 | 212k | libmwaw::DebugStream f; |
636 | 212k | f << entry.name() << "[data]:"; |
637 | 212k | if (data.m_data.size() != 1 || data.m_data[0] != 0x77aa) |
638 | 146k | f << "#" << data; |
639 | 212k | ascii().addPos(entry.begin()); |
640 | 212k | ascii().addNote(f.str().c_str()); |
641 | | |
642 | 212k | return true; |
643 | 215k | } |
644 | | |
645 | | bool MarinerWrtParser::readZoneHeader(MarinerWrtEntry const &entry, int actId, bool onlyTest) |
646 | 59.2k | { |
647 | 59.2k | if (entry.length() < 3) { |
648 | 2.19k | MWAW_DEBUG_MSG(("MarinerWrtParser::readZoneHeader: data seems to short\n")); |
649 | 2.19k | return false; |
650 | 2.19k | } |
651 | 57.0k | MWAWInputStreamPtr input = getInput(); |
652 | 57.0k | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
653 | 57.0k | input->pushLimit(entry.end()); |
654 | 57.0k | std::vector<MarinerWrtStruct> dataList; |
655 | 57.0k | decodeZone(dataList); |
656 | 57.0k | input->popLimit(); |
657 | | |
658 | 57.0k | size_t numData = dataList.size(); |
659 | 57.0k | if (numData < 47) { |
660 | 9.68k | MWAW_DEBUG_MSG(("MarinerWrtParser::readZoneHeader: find unexpected number of data\n")); |
661 | 9.68k | return false; |
662 | 9.68k | } |
663 | 47.3k | if (onlyTest) |
664 | 6.98k | return true; |
665 | 40.3k | size_t d = 0; |
666 | 40.3k | long val; |
667 | 40.3k | libmwaw::DebugStream f; |
668 | 40.3k | MarinerWrtParserInternal::Zone zone; |
669 | 1.63M | for (int j = 0; j < 47; j++) { |
670 | 1.59M | MarinerWrtStruct const &data = dataList[d++]; |
671 | 1.59M | if (!data.isBasic()) { |
672 | 138k | f << "###f" << j << "=" << data << ","; |
673 | 138k | continue; |
674 | 138k | } |
675 | 1.45M | long sel[4]= {0,0,0,0}; |
676 | 1.45M | int dim[4]= {0,0,0,0}; |
677 | 1.45M | unsigned char color[3]; |
678 | 1.45M | switch (j) { |
679 | 33.7k | case 0: // version? |
680 | 33.7k | val = data.value(0); |
681 | 33.7k | if ((val>>16)==1) // checkme v1.6 -> 1[29] while v3.5->1[33] |
682 | 7.30k | setVersion((val&0xFFFF)<30 ? 1 : 2); |
683 | 33.7k | f << "vers?=" << (val>>16) << "[" << (val&0xFFFF) << "],"; |
684 | 33.7k | break; |
685 | 37.4k | case 1: |
686 | 37.4k | val = data.value(0); |
687 | 37.4k | if (val>>16) // 0 or 1000 |
688 | 7.90k | f << "f1[high]=" << std::hex << (val>>16) << std::dec << ","; |
689 | 37.4k | if ((val&0xFFFF)!=1) |
690 | 25.7k | f << "f1[low]=" << (val& 0xFFFF) << ","; |
691 | 37.4k | break; |
692 | 37.4k | case 2: { // find 8[01]0[0145]8120 or a0808120 |
693 | 37.4k | uint32_t high = uint32_t(data.value(0))>>16; |
694 | | // high&4: no odd/even header/footer ? |
695 | 37.4k | if (high) f << "fl2[high]=" << std::hex << high << std::dec << ","; |
696 | 37.4k | uint32_t low = uint32_t(data.value(0))&0xFFFF; |
697 | 37.4k | if (low) f << "fl2[low]=" << std::hex << low << std::dec << ","; |
698 | 37.4k | break; |
699 | 0 | } |
700 | 37.4k | case 3: { // 80000[01] or 800000[01] |
701 | 37.4k | auto value=uint32_t(data.value(0)); |
702 | 37.4k | if (value&0x2000000) { |
703 | 1.19k | zone.m_endNote=true; |
704 | 1.19k | value &= ~uint32_t(0x2000000); |
705 | 1.19k | } |
706 | | // value&1: firstPage[header/footer] ? |
707 | 37.4k | if (value) |
708 | 33.0k | f << "fl3=" << std::hex << value << std::dec << ","; |
709 | 37.4k | break; |
710 | 0 | } |
711 | 37.4k | case 4: { |
712 | 37.4k | auto v = uint32_t(data.value(0)); |
713 | 37.4k | switch (v>>28) { |
714 | 33.3k | case 0: // main |
715 | 33.3k | zone.m_type = MarinerWrtParserInternal::Zone::Z_Main; |
716 | 33.3k | break; |
717 | 1.24k | case 0xc: |
718 | 1.24k | zone.m_type = MarinerWrtParserInternal::Zone::Z_Header; |
719 | 1.24k | break; |
720 | 1.19k | case 0xd: |
721 | 1.19k | zone.m_type = MarinerWrtParserInternal::Zone::Z_Footer; |
722 | 1.19k | break; |
723 | 1.25k | case 0xe: |
724 | 1.25k | zone.m_type = MarinerWrtParserInternal::Zone::Z_Footnote; |
725 | 1.25k | break; |
726 | 404 | default: |
727 | 404 | f << "#type=" << (v>>28) << ","; |
728 | 404 | break; |
729 | 37.4k | } |
730 | 37.4k | zone.m_fileId=(v&0xFFFFFFF); |
731 | 37.4k | m_state->m_fileToZoneMap[v]=actId; |
732 | 37.4k | break; |
733 | 37.4k | } |
734 | 37.4k | case 9: // real bottom margin |
735 | 37.4k | if (data.value(0)) |
736 | 32.9k | f << "y[bottom+footer?]=" << data.value(0) << ","; |
737 | 37.4k | break; |
738 | 37.4k | case 10: |
739 | 37.4k | zone.m_height = data.value(0); |
740 | 37.4k | break; |
741 | 37.3k | case 13: // right margin |
742 | 74.7k | case 14: // bottom margin |
743 | 74.7k | zone.m_RBpos[j-13] = data.value(0); |
744 | 74.7k | break; |
745 | 37.4k | case 21: |
746 | 37.4k | if (data.value(0)) |
747 | 29.9k | f << "h[act]=" << data.value(0) << ","; |
748 | 37.4k | break; |
749 | 37.4k | case 5: // 0|14|90 |
750 | 74.9k | case 6: // 0|11-14 |
751 | 112k | case 15: // -2: main?|-1 |
752 | 149k | case 16: // -2: main?|-1 |
753 | 187k | case 25: // 0|43 |
754 | 224k | case 41: // 0|5|26 |
755 | 224k | if (data.value(0)) |
756 | 181k | f << "f" << j << "=" << data.value(0) << ","; |
757 | 224k | break; |
758 | 37.4k | case 7: // two units ? |
759 | 37.4k | if (data.value(0) != 0x480048) |
760 | 30.4k | f << "f" << j << "=" << std::hex << data.value(0) << std::dec << ","; |
761 | 37.4k | break; |
762 | 37.4k | case 8: // always -2? |
763 | 37.4k | if (data.value(0) != -2) |
764 | 30.3k | f << "#f" << j << "=" << data.value(0) << ","; |
765 | 37.4k | break; |
766 | 37.4k | case 12: // always 16 |
767 | 37.4k | if (data.value(0) != 16) |
768 | 29.5k | f << "#f" << j << "=" << data.value(0) << ","; |
769 | 37.4k | break; |
770 | 37.3k | case 17: |
771 | 37.4k | case 18: |
772 | 37.4k | case 19: |
773 | 37.4k | case 20: |
774 | 37.4k | sel[j-17] = data.value(0); |
775 | 149k | while (j<20) |
776 | 112k | sel[++j-17] = dataList[d++].value(0); |
777 | 37.4k | if (sel[0]||sel[1]) |
778 | 29.9k | f << "sel0=" << std::hex << sel[0] << "x" << sel[1] << std::dec << ","; |
779 | 37.4k | if (sel[2]||sel[3]) |
780 | 29.9k | f << "sel1=" << std::hex << sel[2] << "x" << sel[3] << std::dec << ","; |
781 | 37.4k | break; |
782 | 37.4k | case 28: // left margin |
783 | 37.4k | case 29: // top margin |
784 | 37.4k | case 30: |
785 | 37.4k | case 31: |
786 | 37.4k | dim[j-28] = static_cast<int>(data.value(0)); |
787 | 149k | while (j<31) |
788 | 112k | dim[++j-28] = static_cast<int>(dataList[d++].value(0)); |
789 | 37.4k | zone.m_dim = MWAWBox2l(MWAWVec2l(dim[1],dim[0]), MWAWVec2l(dim[3],dim[2])); |
790 | 37.4k | break; |
791 | 37.3k | case 32: |
792 | 37.4k | case 33: |
793 | 39.2k | case 34: { // 35,36,37: front color? |
794 | 39.2k | color[0]=color[1]=color[2]=0xFF; |
795 | 39.2k | color[j-32]=static_cast<unsigned char>(data.value(0)>>8); |
796 | 114k | while (j < 34) |
797 | 74.8k | color[++j-32] = static_cast<unsigned char>(dataList[d++].value(0)>>8); |
798 | 39.2k | zone.m_backgroundColor = MWAWColor(color[0],color[1],color[2]); |
799 | 39.2k | break; |
800 | 37.4k | } |
801 | 37.4k | case 38: |
802 | 37.4k | if (data.value(0)!=1) |
803 | 26.3k | f << "#f" << j << "=" << data.value(0) << ","; |
804 | 37.4k | break; |
805 | 37.4k | case 39: |
806 | 37.4k | if (data.value(0) && data.value(0)!=0x4d4d4242) // MMBB: creator |
807 | 25.8k | f << "#creator=" << std::hex << uint32_t(data.value(0)) << std::dec << ","; |
808 | 37.4k | break; |
809 | 37.4k | case 40: // normally 0 or pretty small, but can also be very very big |
810 | 37.4k | if (data.value(0)) |
811 | 30.8k | f << "f" << j << "=" << std::hex << data.value(0) << std::dec << ","; |
812 | 37.4k | break; |
813 | 37.4k | case 42: |
814 | 37.4k | if (data.value(0)!=43) |
815 | 30.8k | f << "#f" << j << "=" << data.value(0) << ","; |
816 | 37.4k | break; |
817 | 37.4k | case 44: |
818 | 37.4k | if (data.value(0)) |
819 | 32.8k | f << "sel[pt]=" << std::hex << data.value(0) << std::dec << ","; |
820 | 37.4k | break; |
821 | 37.4k | case 45: |
822 | 37.4k | if (data.value(0)!=72) |
823 | 30.8k | f << "#f" << j << "=" << data.value(0) << ","; |
824 | 37.4k | break; |
825 | 411k | default: |
826 | 411k | if (data.value(0)) |
827 | 285k | f << "#f" << j << "=" << data.value(0) << ","; |
828 | 411k | break; |
829 | 1.45M | } |
830 | 1.45M | } |
831 | 5.41M | while (d < numData) { |
832 | 5.37M | f << "#f" << d << "=" << dataList[d] << ","; |
833 | 5.37M | d++; |
834 | 5.37M | } |
835 | 40.3k | zone.m_extra = f.str(); |
836 | 40.3k | if (actId < 0) { |
837 | 3.74k | MWAW_DEBUG_MSG(("MarinerWrtParser::readZoneHeader: called with negative id\n")); |
838 | 3.74k | } |
839 | 36.6k | else { |
840 | 36.6k | if (actId >= int(m_state->m_zonesList.size())) |
841 | 28.5k | m_state->m_zonesList.resize(size_t(actId)+1); |
842 | 36.6k | m_state->m_zonesList[size_t(actId)] = zone; |
843 | 36.6k | } |
844 | 40.3k | f.str(""); |
845 | 40.3k | f << entry.name() << ":" << zone; |
846 | | |
847 | 40.3k | ascii().addPos(entry.begin()); |
848 | 40.3k | ascii().addNote(f.str().c_str()); |
849 | 40.3k | return true; |
850 | 40.3k | } |
851 | | |
852 | | bool MarinerWrtParser::readZoneDim(MarinerWrtEntry const &entry, int zoneId) |
853 | 15.3k | { |
854 | 15.3k | if (entry.length() < entry.m_N) { |
855 | 535 | MWAW_DEBUG_MSG(("MarinerWrtParser::readZoneDim: data seems to short\n")); |
856 | 535 | return false; |
857 | 535 | } |
858 | 14.8k | MWAWInputStreamPtr input = getInput(); |
859 | 14.8k | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
860 | 14.8k | input->pushLimit(entry.end()); |
861 | 14.8k | std::vector<MarinerWrtStruct> dataList; |
862 | 14.8k | decodeZone(dataList, 1+4*entry.m_N); |
863 | 14.8k | input->popLimit(); |
864 | | |
865 | 14.8k | if (int(dataList.size()) != 4*entry.m_N) { |
866 | 1.51k | MWAW_DEBUG_MSG(("MarinerWrtParser::readZoneDim: find unexpected number of data\n")); |
867 | 1.51k | return false; |
868 | 1.51k | } |
869 | | |
870 | 13.3k | libmwaw::DebugStream f; |
871 | 13.3k | size_t d = 0; |
872 | 13.3k | std::vector<int> colPos; |
873 | 39.6k | for (int i = 0; i < entry.m_N; i++) { |
874 | 26.3k | f.str(""); |
875 | 26.3k | f << entry.name() << "-" << i << ":"; |
876 | 26.3k | ascii().addPos(dataList[d].m_filePos); |
877 | | |
878 | 26.3k | int dim[4] = { 0, 0, 0, 0 }; |
879 | 131k | for (int j = 0; j < 4; j++) { |
880 | 105k | MarinerWrtStruct const &data = dataList[d++]; |
881 | 105k | if (!data.isBasic()) { |
882 | 4.90k | MWAW_DEBUG_MSG(("MarinerWrtParser::readZoneDim: find unexpected dim data type\n")); |
883 | 4.90k | f << "###dim" << j << "=" << data << ","; |
884 | 4.90k | } |
885 | 100k | else |
886 | 100k | dim[j] = static_cast<int>(data.value(0)); |
887 | 105k | } |
888 | | // checkme |
889 | 26.3k | MWAWBox2i dimension(MWAWVec2i(dim[1],dim[0]), MWAWVec2i(dim[3],dim[2])); |
890 | 26.3k | f << "pos=" << dimension << ","; |
891 | 26.3k | bool dimOk=dim[0] >= 0 && dim[0] < dim[2] && dim[1] >= 0 && dim[1] < dim[3]; |
892 | 26.3k | if (i==0 && dimOk) { |
893 | 8.01k | if (zoneId < 0 || zoneId >= int(m_state->m_zonesList.size())) { |
894 | 755 | MWAW_DEBUG_MSG(("MarinerWrtParser::readZoneDim: can not find the zone storage\n")); |
895 | 755 | } |
896 | 7.26k | else if (entry.m_fileType == 9) |
897 | 3.65k | m_state->m_zonesList[size_t(zoneId)].m_pageDim = dimension; |
898 | 3.60k | else if (entry.m_fileType == 0xa) |
899 | 3.60k | m_state->m_zonesList[size_t(zoneId)].m_pageTextDim = dimension; |
900 | 0 | else { |
901 | 0 | MWAW_DEBUG_MSG(("MarinerWrtParser::readZoneDim: unknown zone type\n")); |
902 | 0 | } |
903 | 8.01k | } |
904 | 18.2k | else if (i && dimOk) { |
905 | 9.43k | if (!colPos.size() || colPos.back() <= dim[1]) { |
906 | 9.39k | colPos.push_back(dim[1]); |
907 | 9.39k | colPos.push_back(dim[3]); |
908 | 9.39k | } |
909 | 46 | else |
910 | 46 | f << "###"; |
911 | 9.43k | } |
912 | 26.3k | ascii().addNote(f.str().c_str()); |
913 | 26.3k | } |
914 | 13.3k | if (entry.m_fileType == 0xa && zoneId >= 0 && |
915 | 7.82k | zoneId < int(m_state->m_zonesList.size()) && |
916 | 3.66k | colPos.size() > 2 && int(colPos.size())==2*(entry.m_N-1)) { |
917 | 862 | auto numCols=size_t(entry.m_N-1); |
918 | 862 | MWAWSection &sec=m_state->m_zonesList[size_t(zoneId)].m_section; |
919 | 862 | sec.m_columns.resize(numCols); |
920 | 2.58k | for (size_t c=0; c < numCols; c++) { |
921 | 1.72k | MWAWSection::Column &col = sec.m_columns[c]; |
922 | 1.72k | int prevPos= c==0 ? colPos[0] : (colPos[2*c-1]+colPos[2*c])/2; |
923 | 1.72k | int nextPos= c+1==numCols ? colPos[2*c+1] : |
924 | 1.72k | (colPos[2*c+1]+colPos[2*c+2])/2; |
925 | 1.72k | col.m_width=double(nextPos-prevPos); |
926 | 1.72k | col.m_widthUnit=librevenge::RVNG_POINT; |
927 | 1.72k | col.m_margins[libmwaw::Left]=double(colPos[2*c]-prevPos)/72.; |
928 | 1.72k | col.m_margins[libmwaw::Right]=double(nextPos-colPos[2*c+1])/72.; |
929 | 1.72k | } |
930 | 862 | } |
931 | 13.3k | input->seek(entry.end(), librevenge::RVNG_SEEK_SET); |
932 | | |
933 | 13.3k | return true; |
934 | 14.8k | } |
935 | | |
936 | | bool MarinerWrtParser::readDocInfo(MarinerWrtEntry const &entry, int zoneId) |
937 | 51.8k | { |
938 | 51.8k | if (entry.length() < 3) { |
939 | 4.70k | MWAW_DEBUG_MSG(("MarinerWrtParser::readDocInfo: data seems to short\n")); |
940 | 4.70k | return false; |
941 | 4.70k | } |
942 | 47.1k | MWAWInputStreamPtr input = getInput(); |
943 | 47.1k | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
944 | 47.1k | input->pushLimit(entry.end()); |
945 | 47.1k | std::vector<MarinerWrtStruct> dataList; |
946 | 47.1k | decodeZone(dataList); |
947 | 47.1k | input->popLimit(); |
948 | | |
949 | 47.1k | auto numDatas = int(dataList.size()); |
950 | 47.1k | if (numDatas < 60) { |
951 | 21.0k | MWAW_DEBUG_MSG(("MarinerWrtParser::readDocInfo: find unexpected number of data\n")); |
952 | 21.0k | return false; |
953 | 21.0k | } |
954 | | |
955 | 26.0k | libmwaw::DebugStream f; |
956 | 26.0k | f << entry.name() << ":"; |
957 | | |
958 | 26.0k | int dim[2], margins[4]= {0,0,0,0}; |
959 | 26.0k | unsigned char color[3]; |
960 | 26.0k | size_t d=0; |
961 | 2.79M | for (int j=0; j < numDatas; j++, d++) { |
962 | 2.77M | MarinerWrtStruct const &dt = dataList[d]; |
963 | 2.77M | if (!dt.isBasic()) { |
964 | 250k | f << "#f" << d << "=" << dt << ","; |
965 | 250k | static bool first=true; |
966 | 250k | if (first) { |
967 | 34 | MWAW_DEBUG_MSG(("MarinerWrtParser::readDocInfo: find some struct block\n")); |
968 | 34 | first = false; |
969 | 34 | } |
970 | 250k | continue; |
971 | 250k | } |
972 | 2.52M | switch (j) { |
973 | 25.5k | case 0: { // 15|40 |
974 | 25.5k | auto val=uint32_t(dt.value(0)); |
975 | 25.5k | if (val&0x4000) { |
976 | 2.87k | if (zoneId==0) |
977 | 884 | m_state->m_hasOddEvenHeaderFooter=true; |
978 | 2.87k | f << "hasOddEven[header/footer],"; |
979 | 2.87k | val &= ~uint32_t(0x4000); |
980 | 2.87k | } |
981 | 25.5k | if (val&0x20000) { |
982 | 2.41k | if (zoneId==0 && m_state->m_zonesList.size()) { |
983 | 40 | MWAWSection &sec=m_state->m_zonesList[0].m_section; |
984 | 40 | sec.m_columnSeparator = MWAWBorder(); |
985 | 40 | } |
986 | 2.41k | f << "colSep,"; |
987 | 2.41k | val &= ~uint32_t(0x20000); |
988 | 2.41k | } |
989 | 25.5k | if (val) |
990 | 19.6k | f << "f0=" << std::hex << val << std::dec << ","; |
991 | 25.5k | break; |
992 | 0 | } |
993 | 25.6k | case 2: // small number between 108 and 297 |
994 | 50.9k | case 3: // f3=f2-24? |
995 | 75.8k | case 5: // small number between -18 and 57 |
996 | 99.4k | case 6: // f6~=f5 ? |
997 | 123k | case 13: // a small number 1|2|3|4|58|61|283 |
998 | 149k | case 35: // 1|2|31|60|283 |
999 | 174k | case 44: // 0 or 1 |
1000 | 199k | case 46: // 0 or 1 |
1001 | 224k | case 47: // 0 or 1 |
1002 | 250k | case 48: // 0 or 1 |
1003 | 275k | case 51: // always 1 |
1004 | 275k | if (dt.value(0)) |
1005 | 220k | f << "f" << j << "=" << dt.value(0) << ","; |
1006 | 275k | break; |
1007 | 25.6k | case 1: // 1 |
1008 | 25.6k | if (dt.value(0)!=1) |
1009 | 21.5k | f << "f" << j << "=" << dt.value(0) << ","; |
1010 | 25.6k | break; |
1011 | 23.7k | case 7: |
1012 | 24.3k | case 8: // a dim? |
1013 | 24.3k | dim[0] = dim[1] = 0; |
1014 | 24.3k | dim[j-7]= static_cast<int>(dt.value(0)); |
1015 | 24.3k | if (j!=8) |
1016 | 23.7k | dim[++j-7] = static_cast<int>(dataList[++d].value(0)); |
1017 | 24.3k | f << "dim?=" << dim[1] << "x" << dim[0] << ","; |
1018 | 24.3k | break; |
1019 | 23.5k | case 9: |
1020 | 24.8k | case 10: |
1021 | 24.9k | case 11: |
1022 | 25.7k | case 12: |
1023 | 25.7k | margins[j-9]=static_cast<int>(dt.value(0)); |
1024 | 99.2k | while (j<12) |
1025 | 73.4k | margins[++j-9]= static_cast<int>(dataList[++d].value(0)); |
1026 | 25.7k | f << "margins=" << margins[1] << "x" << margins[0] |
1027 | 25.7k | << "<->" << margins[3] << "x" << margins[2] << ","; |
1028 | 25.7k | break; |
1029 | 24.3k | case 14: // a very big number |
1030 | 24.3k | if (dt.value(0)) |
1031 | 18.3k | f << "id?=" << std::hex << dt.value(0) << std::dec << ","; |
1032 | 24.3k | break; |
1033 | 24.3k | case 15: { // border type? |
1034 | 24.3k | long val = dt.value(0); |
1035 | 24.3k | if (!val) break; |
1036 | 17.1k | int depl = 24; |
1037 | 17.1k | f << "border?=["; |
1038 | 85.5k | for (int b = 0; b < 4; b++) { |
1039 | 68.4k | if ((val>>depl)&0xFF) |
1040 | 36.2k | f << ((val>>depl)&0xFF) << ","; |
1041 | 32.1k | else |
1042 | 32.1k | f << "_"; |
1043 | 68.4k | depl -= 8; |
1044 | 68.4k | } |
1045 | 17.1k | f << "],"; |
1046 | 17.1k | break; |
1047 | 24.3k | } |
1048 | 24.3k | case 16: |
1049 | 25.7k | case 17: |
1050 | 25.8k | case 18: { |
1051 | 25.8k | color[0]=color[1]=color[2]=0; |
1052 | 25.8k | color[j-16]=static_cast<unsigned char>(dt.value(0)>>8); |
1053 | 75.8k | while (j < 18) |
1054 | 50.0k | color[++j-16] = static_cast<unsigned char>(dataList[++d].value(0)>>8); |
1055 | 25.8k | MWAWColor col(color[0],color[1],color[2]); |
1056 | 25.8k | if (!col.isBlack()) f << "color=" << col << ","; |
1057 | 25.8k | break; |
1058 | 25.7k | } |
1059 | 8.88k | case 76: // a very big number |
1060 | 17.7k | case 79: |
1061 | 17.7k | if (dt.value(0)) |
1062 | 11.7k | f << "f" << j << "=" << std::hex << uint32_t(dt.value(0)) << std::dec << ","; |
1063 | 17.7k | break; |
1064 | 2.05M | default: |
1065 | 2.05M | if (dt.value(0)) |
1066 | 1.37M | f << "#f" << j << "=" << dt.value(0) << ","; |
1067 | 2.05M | break; |
1068 | 2.52M | } |
1069 | 2.52M | } |
1070 | 26.0k | if (zoneId==0 && margins[0] > 0 && margins[1] > 0 && |
1071 | 5.71k | margins[2] > 0 && margins[3] > 0) { |
1072 | 5.15k | m_pageMarginsSpanSet= true; |
1073 | 5.15k | getPageSpan().setMarginTop(double(margins[0])/72.0); |
1074 | 5.15k | if (margins[2]>80) |
1075 | 3.28k | getPageSpan().setMarginBottom(double(margins[2]-40)/72.0); |
1076 | 1.87k | else |
1077 | 1.87k | getPageSpan().setMarginBottom(double(margins[2]/2)/72.0); |
1078 | 5.15k | getPageSpan().setMarginLeft(double(margins[1])/72.0); |
1079 | 5.15k | getPageSpan().setMarginRight(double(margins[3])/72.0); |
1080 | | |
1081 | 5.15k | } |
1082 | 26.0k | ascii().addPos(entry.begin()); |
1083 | 26.0k | ascii().addNote(f.str().c_str()); |
1084 | 26.0k | return true; |
1085 | 26.0k | } |
1086 | | bool MarinerWrtParser::readZoneb(MarinerWrtEntry const &entry, int) |
1087 | 6.53k | { |
1088 | 6.53k | if (entry.length() < entry.m_N) { |
1089 | 205 | MWAW_DEBUG_MSG(("MarinerWrtParser::readZoneb: data seems to short\n")); |
1090 | 205 | return false; |
1091 | 205 | } |
1092 | 6.32k | MWAWInputStreamPtr input = getInput(); |
1093 | 6.32k | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
1094 | 6.32k | input->pushLimit(entry.end()); |
1095 | 6.32k | std::vector<MarinerWrtStruct> dataList; |
1096 | 6.32k | decodeZone(dataList, 1+4*entry.m_N); |
1097 | 6.32k | input->popLimit(); |
1098 | | |
1099 | 6.32k | if (int(dataList.size()) != 4*entry.m_N) { |
1100 | 1.70k | MWAW_DEBUG_MSG(("MarinerWrtParser::readZoneb: find unexpected number of data\n")); |
1101 | 1.70k | return false; |
1102 | 1.70k | } |
1103 | | |
1104 | 4.62k | libmwaw::DebugStream f; |
1105 | 4.62k | size_t d = 0; |
1106 | 13.9k | for (int i = 0; i < entry.m_N; i++) { |
1107 | 9.35k | f.str(""); |
1108 | 9.35k | f << entry.name() << "-" << i << ":"; |
1109 | 9.35k | ascii().addPos(dataList[d].m_filePos); |
1110 | | |
1111 | 46.7k | for (int j = 0; j < 4; j++) { // always 0, 0, 0, 0? |
1112 | 37.4k | MarinerWrtStruct const &data = dataList[d++]; |
1113 | 37.4k | if (!data.isBasic()) { |
1114 | 1.39k | MWAW_DEBUG_MSG(("MarinerWrtParser::readZoneb: find unexpected dim data type\n")); |
1115 | 1.39k | f << "###dim" << j << "=" << data << ","; |
1116 | 1.39k | } |
1117 | 36.0k | else if (data.value(0)) |
1118 | 465 | f << "f" << j << "=" << data.value(0) << ","; |
1119 | 37.4k | } |
1120 | 9.35k | ascii().addNote(f.str().c_str()); |
1121 | 9.35k | } |
1122 | 4.62k | input->seek(entry.end(), librevenge::RVNG_SEEK_SET); |
1123 | | |
1124 | 4.62k | return true; |
1125 | 6.32k | } |
1126 | | |
1127 | | bool MarinerWrtParser::readZonec(MarinerWrtEntry const &entry, int zoneId) |
1128 | 13.3k | { |
1129 | 13.3k | if (entry.length() < entry.m_N) { |
1130 | 1.55k | MWAW_DEBUG_MSG(("MarinerWrtParser::readZonec: data seems to short\n")); |
1131 | 1.55k | return false; |
1132 | 1.55k | } |
1133 | 11.8k | MWAWInputStreamPtr input = getInput(); |
1134 | 11.8k | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
1135 | 11.8k | input->pushLimit(entry.end()); |
1136 | 11.8k | std::vector<MarinerWrtStruct> dataList; |
1137 | 11.8k | decodeZone(dataList, 1+9*entry.m_N); |
1138 | 11.8k | input->popLimit(); |
1139 | | |
1140 | 11.8k | if (int(dataList.size()) != 9*entry.m_N) { |
1141 | 6.74k | MWAW_DEBUG_MSG(("MarinerWrtParser::readZonec: find unexpected number of data\n")); |
1142 | 6.74k | return false; |
1143 | 6.74k | } |
1144 | | |
1145 | 5.07k | libmwaw::DebugStream f; |
1146 | 5.07k | size_t d = 0; |
1147 | 11.2k | for (int i = 0; i < entry.m_N; i++) { |
1148 | 6.13k | f.str(""); |
1149 | 6.13k | f << entry.name() << "-" << i << ":"; |
1150 | 6.13k | ascii().addPos(dataList[d].m_filePos); |
1151 | | |
1152 | 61.3k | for (int j = 0; j < 9; j++) { |
1153 | 55.1k | MarinerWrtStruct const &data = dataList[d++]; |
1154 | 55.1k | if (!data.isBasic()) { |
1155 | 766 | MWAW_DEBUG_MSG(("MarinerWrtParser::readZonec: find unexpected dim data type\n")); |
1156 | 766 | f << "###dim" << j << "=" << data << ","; |
1157 | 766 | } |
1158 | 54.4k | else if (j==8) { |
1159 | 6.10k | if (!data.value(0)) { |
1160 | 2.51k | f << "firstPage[header/footer],"; |
1161 | 2.51k | if (zoneId==0) |
1162 | 2.07k | m_state->m_firstPageFooter=true; |
1163 | 2.51k | } |
1164 | 3.58k | else if (data.value(0)!=1) |
1165 | 566 | f << "#f8=" << "=" << data.value(0) << ","; |
1166 | 6.10k | } |
1167 | 48.3k | else if (data.value(0)) |
1168 | 25.1k | f << "f" << j << "=" << data.value(0) << ","; |
1169 | 55.1k | } |
1170 | 6.13k | ascii().addNote(f.str().c_str()); |
1171 | 6.13k | } |
1172 | 5.07k | input->seek(entry.end(), librevenge::RVNG_SEEK_SET); |
1173 | | |
1174 | 5.07k | return true; |
1175 | 11.8k | } |
1176 | | |
1177 | | bool MarinerWrtParser::readZone13(MarinerWrtEntry const &entry, int) |
1178 | 11.0k | { |
1179 | 11.0k | if (entry.length() < 3) { |
1180 | 81 | MWAW_DEBUG_MSG(("MarinerWrtParser::readZone13: data seems to short\n")); |
1181 | 81 | return false; |
1182 | 81 | } |
1183 | 11.0k | MWAWInputStreamPtr input = getInput(); |
1184 | 11.0k | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
1185 | 11.0k | input->pushLimit(entry.end()); |
1186 | 11.0k | std::vector<MarinerWrtStruct> dataList; |
1187 | 11.0k | decodeZone(dataList, 1+23); |
1188 | 11.0k | input->popLimit(); |
1189 | | |
1190 | 11.0k | if (int(dataList.size()) != 23) { |
1191 | 531 | MWAW_DEBUG_MSG(("MarinerWrtParser::readZone13: find unexpected number of data\n")); |
1192 | 531 | return false; |
1193 | 531 | } |
1194 | | |
1195 | 10.4k | libmwaw::DebugStream f; |
1196 | 10.4k | size_t d = 0; |
1197 | 10.4k | f << entry.name() << ":"; |
1198 | 10.4k | ascii().addPos(dataList[d].m_filePos); |
1199 | | |
1200 | 10.4k | int val; |
1201 | 216k | for (int j = 0; j < 23; j++) { |
1202 | 205k | MarinerWrtStruct const &data = dataList[d++]; |
1203 | 205k | if ((j!=14 && !data.isBasic()) || (j==14 && data.m_type)) { |
1204 | 107k | MWAW_DEBUG_MSG(("MarinerWrtParser::readZone13: find unexpected struct data type\n")); |
1205 | 107k | f << "#f" << j << "=" << data << ","; |
1206 | 107k | continue; |
1207 | 107k | } |
1208 | 98.1k | if (j < 14) { |
1209 | 58.6k | int const expectedValues[]= {13,10,9,31,8,12,14,28,29,30,31,0x7f,27,0}; |
1210 | 58.6k | if (static_cast<int>(data.value(0)) != expectedValues[j]) |
1211 | 1.72k | f << "f" << j << "=" << data.value(0) << ","; |
1212 | 58.6k | continue; |
1213 | 58.6k | } |
1214 | 39.5k | if (j == 14) { |
1215 | 4.15k | if (!data.m_pos.valid()) |
1216 | 0 | f << "#f" << j << "=" << data << ","; |
1217 | 4.15k | else { |
1218 | | /* find v_{2i}=0 and v_{2i+1}= |
1219 | | {301,302,422,450,454,422,421,418,302,295,290,468,469,466,467,457,448} |
1220 | | */ |
1221 | 4.15k | f << "bl=["; |
1222 | 4.15k | input->seek(data.m_pos.begin(), librevenge::RVNG_SEEK_SET); |
1223 | 4.15k | auto N = int(data.m_pos.length()/2); |
1224 | 144k | for (int k = 0; k < N; k++) { |
1225 | 140k | val = static_cast<int>(input->readLong(2)); |
1226 | 140k | if (val) f << val << ","; |
1227 | 69.2k | else f << "_,"; |
1228 | 140k | } |
1229 | 4.15k | f << "],"; |
1230 | 4.15k | } |
1231 | 4.15k | continue; |
1232 | 4.15k | } |
1233 | 35.3k | unsigned char color[3]; |
1234 | 35.3k | MWAWColor col; |
1235 | 35.3k | switch (j) { |
1236 | 10.2k | case 15: |
1237 | 10.2k | case 16: |
1238 | 10.2k | case 17: |
1239 | 10.2k | color[0]=color[1]=color[2]=0xFF; |
1240 | 10.2k | color[j-15]=static_cast<unsigned char>(data.value(0)>>8); |
1241 | 30.8k | while (j < 17) |
1242 | 20.5k | color[++j-15] = static_cast<unsigned char>(dataList[d++].value(0)>>8); |
1243 | 10.2k | col = MWAWColor(color[0],color[1],color[2]); |
1244 | 10.2k | if (!col.isWhite()) |
1245 | 6.25k | f << "col0=" << col << ","; |
1246 | 10.2k | break; |
1247 | 4.28k | case 19: |
1248 | 10.3k | case 20: |
1249 | 10.3k | case 21: |
1250 | 10.3k | color[0]=color[1]=color[2]=0xFF; |
1251 | 10.3k | color[j-19]=static_cast<unsigned char>(data.value(0)>>8); |
1252 | 24.9k | while (j < 21) |
1253 | 14.5k | color[++j-19] = static_cast<unsigned char>(dataList[d++].value(0)>>8); |
1254 | 10.3k | col = MWAWColor(color[0],color[1],color[2]); |
1255 | 10.3k | if (!col.isWhite()) |
1256 | 6.27k | f << "col1=" << col << ","; |
1257 | 10.3k | break; |
1258 | 14.7k | default: |
1259 | 14.7k | if (data.value(0)) |
1260 | 6.32k | f << "#f" << j << "=" << data.value(0) << ","; |
1261 | 35.3k | } |
1262 | 35.3k | } |
1263 | 10.4k | ascii().addNote(f.str().c_str()); |
1264 | 10.4k | input->seek(entry.end(), librevenge::RVNG_SEEK_SET); |
1265 | | |
1266 | 10.4k | return true; |
1267 | 10.4k | } |
1268 | | |
1269 | | // --------- print info ---------- |
1270 | | |
1271 | | // read the print info xml data |
1272 | | bool MarinerWrtParser::readCPRT(MarinerWrtEntry const &entry) |
1273 | 3.94k | { |
1274 | 3.94k | if (entry.length() < 0x10) { |
1275 | 3.23k | MWAW_DEBUG_MSG(("MarinerWrtParser::readCPRT: data seems to short\n")); |
1276 | 3.23k | return false; |
1277 | 3.23k | } |
1278 | | |
1279 | 704 | MWAWInputStreamPtr input = getInput(); |
1280 | 704 | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
1281 | | #ifdef DEBUG_WITH_FILES |
1282 | | librevenge::RVNGBinaryData file; |
1283 | | input->readDataBlock(entry.length(), file); |
1284 | | |
1285 | | static int volatile cprtName = 0; |
1286 | | libmwaw::DebugStream f; |
1287 | | f << "CPRT" << ++cprtName << ".plist"; |
1288 | | libmwaw::Debug::dumpFile(file, f.str().c_str()); |
1289 | | |
1290 | | ascii().skipZone(entry.begin(),entry.end()-1); |
1291 | | #endif |
1292 | | |
1293 | 704 | input->seek(entry.end(), librevenge::RVNG_SEEK_SET); |
1294 | 704 | return true; |
1295 | 3.94k | } |
1296 | | |
1297 | | // read the print info data |
1298 | | bool MarinerWrtParser::readPrintInfo(MarinerWrtEntry const &entry) |
1299 | 3.45k | { |
1300 | 3.45k | if (entry.length() < 0x77) { |
1301 | 1.13k | MWAW_DEBUG_MSG(("MarinerWrtParser::readPrintInfo: data seems to short\n")); |
1302 | 1.13k | return false; |
1303 | 1.13k | } |
1304 | | |
1305 | 2.32k | MWAWInputStreamPtr input = getInput(); |
1306 | 2.32k | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
1307 | | |
1308 | 2.32k | libmwaw::PrinterInfo info; |
1309 | 2.32k | if (!info.read(input)) |
1310 | 431 | return false; |
1311 | | |
1312 | 1.88k | libmwaw::DebugStream f; |
1313 | 1.88k | f << "PrintInfo:"<< info; |
1314 | 1.88k | MWAWVec2i paperSize = info.paper().size(); |
1315 | 1.88k | MWAWVec2i pageSize = info.page().size(); |
1316 | 1.88k | if (pageSize.x() <= 0 || pageSize.y() <= 0 || |
1317 | 1.59k | paperSize.x() <= 0 || paperSize.y() <= 0) return false; |
1318 | | |
1319 | 1.46k | if (!m_pageMarginsSpanSet) { |
1320 | | // define margin from print info |
1321 | 994 | MWAWVec2i lTopMargin= -1 * info.paper().pos(0); |
1322 | 994 | MWAWVec2i rBotMargin=info.paper().size() - info.page().size(); |
1323 | | |
1324 | | // move margin left | top |
1325 | 994 | int decalX = lTopMargin.x() > 14 ? lTopMargin.x()-14 : 0; |
1326 | 994 | int decalY = lTopMargin.y() > 14 ? lTopMargin.y()-14 : 0; |
1327 | 994 | lTopMargin -= MWAWVec2i(decalX, decalY); |
1328 | 994 | rBotMargin += MWAWVec2i(decalX, decalY); |
1329 | | |
1330 | | // decrease right | bottom |
1331 | 994 | int rightMarg = rBotMargin.x() -50; |
1332 | 994 | if (rightMarg < 0) rightMarg=0; |
1333 | 994 | int botMarg = rBotMargin.y() -50; |
1334 | 994 | if (botMarg < 0) botMarg=0; |
1335 | | |
1336 | 994 | getPageSpan().setMarginTop(lTopMargin.y()/72.0); |
1337 | 994 | getPageSpan().setMarginBottom(botMarg/72.0); |
1338 | 994 | getPageSpan().setMarginLeft(lTopMargin.x()/72.0); |
1339 | 994 | getPageSpan().setMarginRight(rightMarg/72.0); |
1340 | 994 | } |
1341 | 1.46k | getPageSpan().setFormLength(paperSize.y()/72.); |
1342 | 1.46k | getPageSpan().setFormWidth(paperSize.x()/72.); |
1343 | 1.46k | getPageSpan().checkMargins(); |
1344 | | |
1345 | 1.46k | ascii().addPos(entry.begin()); |
1346 | 1.46k | ascii().addNote(f.str().c_str()); |
1347 | | |
1348 | 1.46k | input->seek(entry.end(), librevenge::RVNG_SEEK_SET); |
1349 | 1.46k | return true; |
1350 | 1.88k | } |
1351 | | |
1352 | | //////////////////////////////////////////////////////////// |
1353 | | // low level |
1354 | | //////////////////////////////////////////////////////////// |
1355 | | |
1356 | | // ---- field decoder --------- |
1357 | | bool MarinerWrtParser::readEntryHeader(MarinerWrtEntry &entry) |
1358 | 706k | { |
1359 | 706k | MWAWInputStreamPtr input = getInput(); |
1360 | 706k | long pos = input->tell(); |
1361 | 706k | std::vector<long> dataList; |
1362 | 706k | if (!readNumbersString(4,dataList)||dataList.size()<5) { |
1363 | 19.6k | MWAW_DEBUG_MSG(("MarinerWrtParser::readEntryHeader: oops can not find header entry\n")); |
1364 | 19.6k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1365 | 19.6k | return false; |
1366 | 19.6k | } |
1367 | 687k | long length = dataList[1] >= 0 ? (dataList[1]<<16)+dataList[2] : -1; |
1368 | 687k | if (length < 0 || !input->checkPosition(input->tell()+length)) { |
1369 | 6.74k | MWAW_DEBUG_MSG(("MarinerWrtParser::readEntryHeader: the header data seems to short\n")); |
1370 | 6.74k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1371 | 6.74k | return false; |
1372 | 6.74k | } |
1373 | 680k | entry.setBegin(input->tell()); |
1374 | 680k | entry.setLength(length); |
1375 | 680k | entry.m_fileType = static_cast<int>(int16_t(dataList[0])); |
1376 | 680k | entry.m_N = static_cast<int>(dataList[4]); |
1377 | 680k | entry.m_value = static_cast<int>(dataList[3]); |
1378 | | |
1379 | 680k | return true; |
1380 | 687k | } |
1381 | | |
1382 | | bool MarinerWrtParser::readNumbersString(int num, std::vector<long> &res) |
1383 | 7.49M | { |
1384 | 7.49M | res.resize(0); |
1385 | | // first read the string |
1386 | 7.49M | MWAWInputStreamPtr input = getInput(); |
1387 | 7.49M | std::string str(""); |
1388 | 40.0M | while (!input->isEnd()) { |
1389 | 39.9M | auto ch = int(input->readULong(1)); |
1390 | 39.9M | if (ch=='-' || (ch >= 'A' && ch <= 'F') || (ch >= '0' && ch <= '9')) { |
1391 | 32.5M | str += char(ch); |
1392 | 32.5M | continue; |
1393 | 32.5M | } |
1394 | 7.37M | input->seek(-1, librevenge::RVNG_SEEK_CUR); |
1395 | 7.37M | break; |
1396 | 39.9M | } |
1397 | 7.49M | if (!str.length()) return false; |
1398 | | |
1399 | | // ok we have the string, let decodes it |
1400 | 7.41M | size_t sz = str.length(), i = sz; |
1401 | 7.41M | int nBytes = 0; |
1402 | 7.41M | long val=0; |
1403 | 38.8M | while (1) { |
1404 | 38.8M | if (i==0) { |
1405 | 7.31M | if (nBytes) |
1406 | 6.66M | res.insert(res.begin(),val); |
1407 | 7.31M | break; |
1408 | 7.31M | } |
1409 | 31.5M | char c = str[--i]; |
1410 | 31.5M | if (c=='-') { |
1411 | 881k | if (!nBytes) { |
1412 | 101k | MWAW_DEBUG_MSG(("MarinerWrtParser::readNumbersString find '-' with no val\n")); |
1413 | 101k | break; |
1414 | 101k | } |
1415 | 779k | res.insert(res.begin(),-val); |
1416 | 779k | val = 0; |
1417 | 779k | nBytes = 0; |
1418 | 779k | continue; |
1419 | 881k | } |
1420 | | |
1421 | 30.6M | if (nBytes==num) { |
1422 | 3.11M | res.insert(res.begin(),val); |
1423 | 3.11M | val = 0; |
1424 | 3.11M | nBytes = 0; |
1425 | 3.11M | } |
1426 | | |
1427 | 30.6M | if (c >= '0' && c <= '9') |
1428 | 24.6M | val += (long(c-'0')<<(4*nBytes)); |
1429 | 5.95M | else if (c >= 'A' && c <= 'F') |
1430 | 5.95M | val += (long(c+10-'A')<<(4*nBytes)); |
1431 | 0 | else { |
1432 | 0 | MWAW_DEBUG_MSG(("MarinerWrtParser::readNumbersString find odd char %x\n", static_cast<unsigned int>(c))); |
1433 | 0 | break; |
1434 | 0 | } |
1435 | 30.6M | nBytes++; |
1436 | 30.6M | } |
1437 | 7.41M | return true; |
1438 | 7.49M | } |
1439 | | |
1440 | | bool MarinerWrtParser::decodeZone(std::vector<MarinerWrtStruct> &dataList, long numData) |
1441 | 750k | { |
1442 | 750k | dataList.clear(); |
1443 | | |
1444 | 750k | MWAWInputStreamPtr input = getInput(); |
1445 | 750k | long pos = input->tell(); |
1446 | 11.5M | while (!input->isEnd()) { |
1447 | 11.4M | size_t numVal = dataList.size(); |
1448 | 11.4M | if (numVal >= size_t(numData)) |
1449 | 3.52k | break; |
1450 | 11.4M | MarinerWrtStruct data; |
1451 | 11.4M | data.m_filePos = pos; |
1452 | 11.4M | auto type = int(input->readULong(1)); |
1453 | 11.4M | data.m_type = (type&3); |
1454 | 11.4M | if (type == 3) |
1455 | 230k | return true; |
1456 | 11.1M | if ((type & 0x3c) || (type && !(type&0x3))) |
1457 | 287k | break; |
1458 | 10.8M | if ((type>>4)==0xc) { |
1459 | 1.90M | if (input->isEnd()) break; |
1460 | 1.89M | auto num = int(input->readULong(1)); |
1461 | 1.89M | if (!num) break; |
1462 | 1.89M | if (numVal==0) { |
1463 | 60.0k | MWAW_DEBUG_MSG(("MarinerWrtParser::decodeZone: no previous data to copy\n")); |
1464 | 60.0k | } |
1465 | 1.83M | else // checkme |
1466 | 1.83M | data = dataList[numVal-1]; |
1467 | | |
1468 | 83.7M | for (int j = 0; j < num; j++) |
1469 | 81.8M | dataList.push_back(data); |
1470 | 1.89M | pos = input->tell(); |
1471 | 1.89M | continue; |
1472 | 1.89M | } |
1473 | 8.99M | if ((type>>4)==0x8) { |
1474 | 2.20M | if (numVal==0) { |
1475 | 19.5k | MWAW_DEBUG_MSG(("MarinerWrtParser::decodeZone: no previous data to copy(II)\n")); |
1476 | 19.5k | dataList.push_back(data); |
1477 | 19.5k | } |
1478 | 2.18M | else |
1479 | 2.18M | dataList.push_back(dataList[numVal-1]); |
1480 | 2.20M | pos = input->tell(); |
1481 | 2.20M | continue; |
1482 | 2.20M | } |
1483 | 6.78M | std::vector<long> &numbers = data.m_data; |
1484 | 6.78M | if (!readNumbersString(data.m_type==1 ? 4: 8, numbers)) |
1485 | 71.3k | break; |
1486 | 6.71M | if (type==0) { |
1487 | 150k | if (numbers.size() != 1 || numbers[0] < 0 || input->readULong(1) != 0x2c) |
1488 | 4.04k | break; |
1489 | 146k | data.m_pos.setBegin(input->tell()); |
1490 | 146k | data.m_pos.setLength(numbers[0]); |
1491 | 146k | if (!input->checkPosition(data.m_pos.end())) |
1492 | 1.16k | break; |
1493 | 144k | input->seek(data.m_pos.end(), librevenge::RVNG_SEEK_SET); |
1494 | 144k | numbers.resize(0); |
1495 | 144k | } |
1496 | | |
1497 | 6.71M | dataList.push_back(data); |
1498 | 6.71M | pos = input->tell(); |
1499 | 6.71M | } |
1500 | 519k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1501 | 519k | return dataList.size(); |
1502 | 750k | } |
1503 | | |
1504 | | //////////////////////////////////////////////////////////// |
1505 | | // read the header |
1506 | | //////////////////////////////////////////////////////////// |
1507 | | bool MarinerWrtParser::checkHeader(MWAWHeader *header, bool strict) |
1508 | 98.1k | { |
1509 | 98.1k | *m_state = MarinerWrtParserInternal::State(); |
1510 | 98.1k | MWAWInputStreamPtr input = getInput(); |
1511 | 98.1k | if (!input || !input->hasDataFork()) |
1512 | 0 | return false; |
1513 | | |
1514 | 98.1k | long const headerSize=0x2e; |
1515 | 98.1k | if (!input->checkPosition(headerSize)) { |
1516 | 104 | MWAW_DEBUG_MSG(("MarinerWrtParser::checkHeader: file is too short\n")); |
1517 | 104 | return false; |
1518 | 104 | } |
1519 | 98.0k | input->seek(0,librevenge::RVNG_SEEK_SET); |
1520 | | |
1521 | 98.0k | int actZone = -1; |
1522 | 98.0k | if (!readZone(actZone, true)) |
1523 | 6.13k | return false; |
1524 | 91.9k | if (strict && !readZone(actZone, true)) |
1525 | 11.2k | return false; |
1526 | | |
1527 | 80.6k | input->seek(0, librevenge::RVNG_SEEK_SET); |
1528 | 80.6k | if (header) |
1529 | 32.3k | header->reset(MWAWDocument::MWAW_T_MARINERWRITE, 1); |
1530 | | |
1531 | 80.6k | return true; |
1532 | 91.9k | } |
1533 | | |
1534 | | //////////////////////////////////////////////////////////// |
1535 | | // MarinerWrtEntry/MarinerWrtStruct function |
1536 | | //////////////////////////////////////////////////////////// |
1537 | | MarinerWrtEntry::~MarinerWrtEntry() |
1538 | 706k | { |
1539 | 706k | } |
1540 | | |
1541 | | std::string MarinerWrtEntry::name() const |
1542 | 2.64M | { |
1543 | 2.64M | switch (m_fileType) { |
1544 | 449k | case -1: |
1545 | 449k | return "Separator"; |
1546 | 12.3k | case -2: |
1547 | 12.3k | return "EndZone"; |
1548 | 111k | case 0: |
1549 | 111k | return "ZoneHeader"; |
1550 | 73.2k | case 1: |
1551 | 73.2k | return "TextStruct"; |
1552 | 25.7k | case 2: |
1553 | 25.7k | return "TEXT"; |
1554 | 39.1k | case 4: |
1555 | 39.1k | return "CharPLC"; |
1556 | 45.4k | case 5: |
1557 | 45.4k | return "ParagPLC"; |
1558 | 382k | case 6: |
1559 | 382k | return "Fonts"; |
1560 | 617k | case 7: |
1561 | 617k | return "Paragraphs"; |
1562 | 216k | case 8: |
1563 | 216k | return "FontNames"; |
1564 | 20.3k | case 9: |
1565 | 20.3k | return "PaperSize"; |
1566 | 31.7k | case 0xa: |
1567 | 31.7k | return "ColDim"; |
1568 | 129k | case 0xf: |
1569 | 129k | return "DocInfo"; |
1570 | 156k | case 0x14: // token, picture, ... |
1571 | 156k | return "Token"; |
1572 | 37.8k | case 0x1a: |
1573 | 37.8k | return "StyleNames"; |
1574 | 7.17k | case 0x1f: |
1575 | 7.17k | return "PrintInfo"; |
1576 | 34.3k | case 0x24: |
1577 | 34.3k | return "CPRT"; |
1578 | 1.25k | case 0x41a: |
1579 | 1.25k | return "DocInf2"; |
1580 | 14.3k | case 0x420: |
1581 | 14.3k | return "PSFile"; |
1582 | 239k | default: |
1583 | 239k | break; |
1584 | 2.64M | } |
1585 | 239k | std::stringstream s; |
1586 | 239k | if (m_fileType >= 0) |
1587 | 168k | s << "Zone" << std::hex << std::setfill('0') << std::setw(2) << m_fileType << std::dec; |
1588 | 71.2k | else |
1589 | 71.2k | s << "Zone-" << std::hex << std::setfill('0') << std::setw(2) << -m_fileType << std::dec; |
1590 | | |
1591 | 239k | return s.str(); |
1592 | 2.64M | } |
1593 | | |
1594 | | long MarinerWrtStruct::value(int i) const |
1595 | 76.4M | { |
1596 | 76.4M | if (i < 0 || i >= int(m_data.size())) { |
1597 | 7.24M | if (i) { |
1598 | 0 | MWAW_DEBUG_MSG(("MarinerWrtStruct::value: can not find value %d\n", i)); |
1599 | 0 | } |
1600 | 7.24M | return 0; |
1601 | 7.24M | } |
1602 | 69.1M | return m_data[size_t(i)]; |
1603 | 76.4M | } |
1604 | | std::ostream &operator<<(std::ostream &o, MarinerWrtStruct const &dt) |
1605 | 0 | { |
1606 | 0 | switch (dt.m_type) { |
1607 | 0 | case 0: // data |
1608 | 0 | o << "sz=" << std::hex << dt.m_pos.length() << std::dec; |
1609 | 0 | return o; |
1610 | 0 | case 3: // end of data |
1611 | 0 | return o; |
1612 | 0 | case 1: // int? |
1613 | 0 | case 2: // long? |
1614 | 0 | break; |
1615 | 0 | default: |
1616 | 0 | if (dt.m_type) o << ":" << dt.m_type; |
1617 | 0 | break; |
1618 | 0 | } |
1619 | 0 | size_t numData = dt.m_data.size(); |
1620 | 0 | if (!numData) { |
1621 | 0 | o << "_"; |
1622 | 0 | return o; |
1623 | 0 | } |
1624 | 0 | if (numData > 1) o << "["; |
1625 | 0 | for (size_t d = 0; d < numData; d++) { |
1626 | 0 | long val = dt.m_data[d]; |
1627 | 0 | if (val > -100 && val < 100) |
1628 | 0 | o << val; |
1629 | 0 | else if (val > 0) |
1630 | 0 | o << "0x" << std::hex << val << std::dec; |
1631 | 0 | else |
1632 | 0 | o << "-0x" << std::hex << -val << std::dec; |
1633 | 0 | if (d+1 != numData) o << ","; |
1634 | 0 | } |
1635 | 0 | if (numData > 1) o << "]"; |
1636 | 0 | return o; |
1637 | 0 | } |
1638 | | |
1639 | | |
1640 | | // vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: |