/src/libmwaw/src/lib/MsWrdParser.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 <cstring> |
35 | | #include <iomanip> |
36 | | #include <iostream> |
37 | | #include <limits> |
38 | | #include <map> |
39 | | #include <set> |
40 | | #include <sstream> |
41 | | |
42 | | #include <librevenge/librevenge.h> |
43 | | |
44 | | #include "MWAWTextListener.hxx" |
45 | | #include "MWAWFont.hxx" |
46 | | #include "MWAWFontConverter.hxx" |
47 | | #include "MWAWHeader.hxx" |
48 | | #include "MWAWPosition.hxx" |
49 | | #include "MWAWPictMac.hxx" |
50 | | #include "MWAWPrinter.hxx" |
51 | | #include "MWAWSubDocument.hxx" |
52 | | |
53 | | #include "MsWrdParser.hxx" |
54 | | |
55 | | #include "MsWrdText.hxx" |
56 | | |
57 | | /** Internal: the structures of a MsWrdParser */ |
58 | | namespace MsWrdParserInternal |
59 | | { |
60 | | //////////////////////////////////////// |
61 | | //! Internal: the object of MsWrdParser |
62 | | struct Object { |
63 | | Object() |
64 | 1.98M | : m_textPos(-1) |
65 | 1.98M | , m_pos() |
66 | 1.98M | , m_name("") |
67 | 1.98M | , m_id(-1) |
68 | 1.98M | , m_annotation() |
69 | 1.98M | , m_extra("") |
70 | 1.98M | { |
71 | 3.97M | for (auto &id : m_ids) id=-1; |
72 | 3.97M | for (auto &idFlag : m_idsFlag) idFlag=0; |
73 | 3.97M | for (auto &flag : m_flags) flag=0; |
74 | 1.98M | } |
75 | | |
76 | | MsWrdEntry getEntry() const |
77 | 93.1k | { |
78 | 93.1k | MsWrdEntry res; |
79 | 93.1k | res.setBegin(m_pos.begin()); |
80 | 93.1k | res.setEnd(m_pos.end()); |
81 | 93.1k | res.setType("ObjectData"); |
82 | 93.1k | res.setId(m_id); |
83 | 93.1k | return res; |
84 | 93.1k | } |
85 | | |
86 | | //! operator<< |
87 | | friend std::ostream &operator<<(std::ostream &o, Object const &obj) |
88 | 0 | { |
89 | 0 | if (obj.m_textPos >= 0) |
90 | 0 | o << std::hex << "textPos?=" << obj.m_textPos << std::dec << ","; |
91 | 0 | if (obj.m_id >= 0) o << "Obj" << obj.m_id << ","; |
92 | 0 | if (obj.m_name.length()) o << obj.m_name << ","; |
93 | 0 | for (int st = 0; st < 2; st++) { |
94 | 0 | if (obj.m_ids[st] == -1 && obj.m_idsFlag[st] == 0) continue; |
95 | 0 | o << "id" << st << "=" << obj.m_ids[st]; |
96 | 0 | if (obj.m_idsFlag[st]) o << ":" << std::hex << obj.m_idsFlag[st] << std::dec << ","; |
97 | 0 | } |
98 | 0 | for (int st = 0; st < 2; st++) { |
99 | 0 | if (obj.m_flags[st]) |
100 | 0 | o << "fl" << st << "=" << std::hex << obj.m_flags[st] << std::dec << ","; |
101 | 0 | } |
102 | 0 |
|
103 | 0 | if (obj.m_extra.length()) o << "extras=[" << obj.m_extra << "],"; |
104 | 0 | return o; |
105 | 0 | } |
106 | | //! the text position |
107 | | long m_textPos; |
108 | | |
109 | | //! the object entry |
110 | | MWAWEntry m_pos; |
111 | | |
112 | | //! the object name |
113 | | std::string m_name; |
114 | | |
115 | | //! the id |
116 | | int m_id; |
117 | | |
118 | | //! some others id? |
119 | | int m_ids[2]; |
120 | | |
121 | | //! some flags link to m_ids |
122 | | int m_idsFlag[2]; |
123 | | |
124 | | //! some flags |
125 | | int m_flags[2]; |
126 | | |
127 | | //! the annotation entry |
128 | | MWAWEntry m_annotation; |
129 | | |
130 | | //! some extra data |
131 | | std::string m_extra; |
132 | | }; |
133 | | |
134 | | //////////////////////////////////////// |
135 | | //! Internal: the picture of a MsWrdParser |
136 | | struct Picture { |
137 | | struct Zone; |
138 | | Picture() |
139 | 73.2k | : m_dim() |
140 | 73.2k | , m_picturesList() |
141 | 73.2k | , m_flag(0) |
142 | 73.2k | { |
143 | 73.2k | } |
144 | | //! operator<< |
145 | | friend std::ostream &operator<<(std::ostream &o, Picture const &pict) |
146 | 0 | { |
147 | 0 | o << "dim=" << pict.m_dim << ","; |
148 | 0 | if (pict.m_flag) o << "f0=" << std::hex << pict.m_flag << std::dec << ","; |
149 | 0 | return o; |
150 | 0 | } |
151 | | |
152 | | //! the dimension |
153 | | MWAWBox2i m_dim; |
154 | | //! the list of picture |
155 | | std::vector<Zone> m_picturesList; |
156 | | //! an unknown flag |
157 | | int m_flag; |
158 | | |
159 | | // ! a small zone |
160 | | struct Zone { |
161 | | Zone() |
162 | 37.4k | : m_pos() |
163 | 37.4k | , m_dim() |
164 | 37.4k | { |
165 | 112k | for (auto &fl : m_flags) fl=0; |
166 | 37.4k | } |
167 | | //! operator<< |
168 | | friend std::ostream &operator<<(std::ostream &o, Zone const &pict) |
169 | 0 | { |
170 | 0 | o << "dim=" << pict.m_dim << ","; |
171 | 0 | if (pict.m_flags[0] != 8) o << "f0=" << pict.m_flags[0] << ","; |
172 | 0 | if (pict.m_flags[1]) o << "f1=" << pict.m_flags[1] << ","; |
173 | 0 | if (pict.m_flags[2] != 1) o << "f2=" << pict.m_flags[2] << ","; // or 0 |
174 | 0 | return o; |
175 | 0 | } |
176 | | //! the position in file |
177 | | MWAWEntry m_pos; |
178 | | //! the dimension |
179 | | MWAWBox2i m_dim; |
180 | | //! three unknown flags |
181 | | int m_flags[3]; |
182 | | }; |
183 | | |
184 | | }; |
185 | | |
186 | | //////////////////////////////////////// |
187 | | //! Internal: the state of a MsWrdParser |
188 | | struct State { |
189 | | //! constructor |
190 | | State() |
191 | 374k | : m_bot(-1) |
192 | 374k | , m_eot(-1) |
193 | 374k | , m_endNote(false) |
194 | 374k | , m_picturesMap() |
195 | 374k | , m_posToCommentMap() |
196 | 374k | , m_actPage(0) |
197 | 374k | , m_numPages(0) |
198 | 374k | , m_headersId() |
199 | 374k | , m_footersId() |
200 | 374k | , m_metaData() |
201 | 374k | { |
202 | 374k | } |
203 | | |
204 | | //! the begin of the text |
205 | | long m_bot; |
206 | | //! end of the text |
207 | | long m_eot; |
208 | | //! a flag to know if we must place the note at the end or in the foot part |
209 | | bool m_endNote; |
210 | | //! the map filePos -> Picture |
211 | | std::map<long, Picture> m_picturesMap; |
212 | | //! the map textPos -> comment entry |
213 | | std::map<long, MWAWEntry> m_posToCommentMap; |
214 | | |
215 | | //! the list of object ( mainZone, other zone) |
216 | | std::vector<Object> m_objectList[2]; |
217 | | |
218 | | int m_actPage /** the actual page */, m_numPages /** the number of page of the final document */; |
219 | | |
220 | | /** the list of header id which corresponds to each page */ |
221 | | std::vector<int> m_headersId; |
222 | | /** the list of footer id which corresponds to each page */ |
223 | | std::vector<int> m_footersId; |
224 | | /** the meta data */ |
225 | | librevenge::RVNGPropertyList m_metaData; |
226 | | }; |
227 | | |
228 | | //////////////////////////////////////// |
229 | | //! Internal: the subdocument of a MsWrdParser |
230 | | class SubDocument final : public MWAWSubDocument |
231 | | { |
232 | | public: |
233 | | //! constructor for footnote, comment |
234 | | SubDocument(MsWrdParser &pars, MWAWInputStreamPtr const &input, int id, libmwaw::SubDocumentType type) |
235 | 15.2k | : MWAWSubDocument(&pars, input, MWAWEntry()) |
236 | 15.2k | , m_id(id) |
237 | 15.2k | , m_type(type) |
238 | 15.2k | , m_pictFPos(-1) |
239 | 15.2k | , m_pictCPos(-1) |
240 | 15.2k | { |
241 | 15.2k | } |
242 | | //! constructor for header/footer |
243 | | SubDocument(MsWrdParser &pars, MWAWInputStreamPtr const &input, MWAWEntry const &entry, libmwaw::SubDocumentType type) |
244 | 7.57k | : MWAWSubDocument(&pars, input, entry) |
245 | 7.57k | , m_id(-1) |
246 | 7.57k | , m_type(type) |
247 | 7.57k | , m_pictFPos(-1) |
248 | 7.57k | , m_pictCPos(-1) |
249 | 7.57k | { |
250 | 7.57k | } |
251 | | //! constructor for picture |
252 | | SubDocument(MsWrdParser &pars, MWAWInputStreamPtr const &input, long fPos, int cPos) |
253 | 12.3k | : MWAWSubDocument(&pars, input, MWAWEntry()) |
254 | 12.3k | , m_id(-1) |
255 | 12.3k | , m_type(libmwaw::DOC_NONE) |
256 | 12.3k | , m_pictFPos(fPos) |
257 | 12.3k | , m_pictCPos(cPos) |
258 | 12.3k | { |
259 | 12.3k | } |
260 | | |
261 | | //! destructor |
262 | 0 | ~SubDocument() final {} |
263 | | |
264 | | //! operator!= |
265 | | bool operator!=(MWAWSubDocument const &doc) const final; |
266 | | |
267 | | //! the parser function |
268 | | void parse(MWAWListenerPtr &listener, libmwaw::SubDocumentType type) final; |
269 | | |
270 | | protected: |
271 | | //! the subdocument id |
272 | | int m_id; |
273 | | //! the subdocument type |
274 | | libmwaw::SubDocumentType m_type; |
275 | | //! the picture file position |
276 | | long m_pictFPos; |
277 | | //! the picture char position |
278 | | int m_pictCPos; |
279 | | }; |
280 | | |
281 | | void SubDocument::parse(MWAWListenerPtr &listener, libmwaw::SubDocumentType type) |
282 | 28.2k | { |
283 | 28.2k | if (!listener.get()) { |
284 | 0 | MWAW_DEBUG_MSG(("MsWrdParserInternal::SubDocument::parse: no listener\n")); |
285 | 0 | return; |
286 | 0 | } |
287 | 28.2k | auto *parser=dynamic_cast<MsWrdParser *>(m_parser); |
288 | 28.2k | if (!parser) { |
289 | 0 | MWAW_DEBUG_MSG(("MsWrdParserInternal::SubDocument::parse: no parser\n")); |
290 | 0 | return; |
291 | 0 | } |
292 | | |
293 | 28.2k | long pos = m_input->tell(); |
294 | 28.2k | if (m_type == libmwaw::DOC_NONE && m_pictCPos >= 0 && m_pictFPos > 0) |
295 | 12.3k | parser->sendPicture(m_pictFPos, m_pictCPos, MWAWPosition::Frame); |
296 | 15.8k | else if (m_type == libmwaw::DOC_HEADER_FOOTER) |
297 | 7.57k | parser->send(m_zone); |
298 | 8.28k | else if (m_type == libmwaw::DOC_COMMENT_ANNOTATION) |
299 | 0 | parser->sendSimpleTextZone(listener, m_zone); |
300 | 8.28k | else |
301 | 8.28k | parser->send(m_id, type); |
302 | 28.2k | m_input->seek(pos, librevenge::RVNG_SEEK_SET); |
303 | 28.2k | } |
304 | | |
305 | | bool SubDocument::operator!=(MWAWSubDocument const &doc) const |
306 | 3.43k | { |
307 | 3.43k | if (MWAWSubDocument::operator!=(doc)) return true; |
308 | 0 | auto const *sDoc = dynamic_cast<SubDocument const *>(&doc); |
309 | 0 | if (!sDoc) return true; |
310 | 0 | if (m_id != sDoc->m_id) return true; |
311 | 0 | if (m_type != sDoc->m_type) return true; |
312 | 0 | if (m_pictFPos != sDoc->m_pictFPos) return true; |
313 | 0 | if (m_pictCPos != sDoc->m_pictCPos) return true; |
314 | 0 | return false; |
315 | 0 | } |
316 | | } |
317 | | |
318 | | //////////////////////////////////////////////////////////// |
319 | | // MsWrdEntry |
320 | | //////////////////////////////////////////////////////////// |
321 | | MsWrdEntry::~MsWrdEntry() |
322 | 13.3M | { |
323 | 13.3M | } |
324 | | |
325 | | std::ostream &operator<<(std::ostream &o, MsWrdEntry const &entry) |
326 | 0 | { |
327 | 0 | if (entry.type().length()) { |
328 | 0 | o << entry.type(); |
329 | 0 | if (entry.m_id >= 0) o << "[" << entry.m_id << "]"; |
330 | 0 | o << "="; |
331 | 0 | } |
332 | 0 | return o; |
333 | 0 | } |
334 | | |
335 | | //////////////////////////////////////////////////////////// |
336 | | // constructor/destructor, ... |
337 | | //////////////////////////////////////////////////////////// |
338 | | MsWrdParser::MsWrdParser(MWAWInputStreamPtr const &input, MWAWRSRCParserPtr const &rsrcParser, MWAWHeader *header) |
339 | 155k | : MWAWTextParser(input, rsrcParser, header) |
340 | 155k | , m_state() |
341 | 155k | , m_entryMap() |
342 | 155k | , m_textParser() |
343 | 155k | { |
344 | 155k | init(); |
345 | 155k | } |
346 | | |
347 | | MsWrdParser::~MsWrdParser() |
348 | 155k | { |
349 | 155k | } |
350 | | |
351 | | void MsWrdParser::init() |
352 | 155k | { |
353 | 155k | resetTextListener(); |
354 | 155k | setAsciiName("main-1"); |
355 | | |
356 | 155k | m_state.reset(new MsWrdParserInternal::State); |
357 | | |
358 | | // reduce the margin (in case, the page is not defined) |
359 | 155k | getPageSpan().setMargins(0.1); |
360 | | |
361 | 155k | m_textParser.reset(new MsWrdText(*this)); |
362 | 155k | } |
363 | | |
364 | | //////////////////////////////////////////////////////////// |
365 | | // new page and color |
366 | | //////////////////////////////////////////////////////////// |
367 | | void MsWrdParser::newPage(int number) |
368 | 68.2k | { |
369 | 68.2k | if (number <= m_state->m_actPage || number > m_state->m_numPages) |
370 | 0 | return; |
371 | | |
372 | 136k | while (m_state->m_actPage < number) { |
373 | 68.2k | m_state->m_actPage++; |
374 | 68.2k | if (!getTextListener() || m_state->m_actPage == 1) |
375 | 4.15k | continue; |
376 | 64.1k | getTextListener()->insertBreak(MWAWTextListener::PageBreak); |
377 | 64.1k | } |
378 | 68.2k | } |
379 | | |
380 | | bool MsWrdParser::getColor(int id, MWAWColor &col) const |
381 | 38.6k | { |
382 | 38.6k | switch (id) { |
383 | 0 | case 0: |
384 | 0 | col=MWAWColor(0,0,0); |
385 | 0 | break; // black |
386 | 2.88k | case 1: |
387 | 2.88k | col=MWAWColor(0,0,255); |
388 | 2.88k | break; // blue |
389 | 3.45k | case 2: |
390 | 3.45k | col=MWAWColor(0, 255,255); |
391 | 3.45k | break; // cyan |
392 | 2.08k | case 3: |
393 | 2.08k | col=MWAWColor(0,255,0); |
394 | 2.08k | break; // green |
395 | 13.3k | case 4: |
396 | 13.3k | col=MWAWColor(255,0,255); |
397 | 13.3k | break; // magenta |
398 | 457 | case 5: |
399 | 457 | col=MWAWColor(255,0,0); |
400 | 457 | break; // red |
401 | 3.39k | case 6: |
402 | 3.39k | col=MWAWColor(255,255,0); |
403 | 3.39k | break; // yellow |
404 | 909 | case 7: |
405 | 909 | col=MWAWColor(255,255,255); |
406 | 909 | break; // white |
407 | 12.1k | default: |
408 | 12.1k | MWAW_DEBUG_MSG(("MsWrdParser::getColor: unknown color=%d\n", id)); |
409 | 12.1k | return false; |
410 | 38.6k | } |
411 | 26.4k | return true; |
412 | 38.6k | } |
413 | | |
414 | | void MsWrdParser::sendSimpleTextZone(MWAWListenerPtr &listener, MWAWEntry const &entry) |
415 | 0 | { |
416 | 0 | if (!listener || !entry.valid()) return; |
417 | 0 | auto input=getInput(); |
418 | 0 | if (input->size()<entry.end()) { |
419 | 0 | MWAW_DEBUG_MSG(("MsWrdParser::sendSimpleTextZone: entry seems bad\n")); |
420 | 0 | return; |
421 | 0 | } |
422 | 0 | long pos=input->tell(); |
423 | |
|
424 | 0 | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
425 | 0 | for (long i=0; i<entry.length(); ++i) { |
426 | 0 | char c=char(input->readULong(1)); |
427 | 0 | switch (c) { |
428 | 0 | case 0x9: |
429 | 0 | listener->insertTab(); |
430 | 0 | break; |
431 | 0 | case 0xd: // line break hard |
432 | 0 | if (i+1!=entry.length()) |
433 | 0 | listener->insertEOL(); |
434 | 0 | break; |
435 | 0 | default: // asume basic caracter, ie. will not works if Chinese, ... |
436 | 0 | listener->insertCharacter(static_cast<unsigned char>(c)); |
437 | 0 | break; |
438 | 0 | } |
439 | 0 | } |
440 | 0 | input->seek(pos, librevenge::RVNG_SEEK_SET); |
441 | 0 | } |
442 | | |
443 | | void MsWrdParser::sendFootnote(int id) |
444 | 15.2k | { |
445 | 15.2k | if (!getTextListener()) return; |
446 | | |
447 | 15.2k | MWAWSubDocumentPtr subdoc(new MsWrdParserInternal::SubDocument(*this, getInput(), id, libmwaw::DOC_NOTE)); |
448 | 15.2k | getTextListener()->insertNote |
449 | 15.2k | (MWAWNote(m_state->m_endNote ? MWAWNote::EndNote : MWAWNote::FootNote), subdoc); |
450 | 15.2k | } |
451 | | |
452 | | void MsWrdParser::sendFieldComment(int id) |
453 | 0 | { |
454 | 0 | if (!getTextListener()) return; |
455 | | |
456 | 0 | MWAWSubDocumentPtr subdoc(new MsWrdParserInternal::SubDocument(*this, getInput(), id, libmwaw::DOC_COMMENT_ANNOTATION)); |
457 | 0 | getTextListener()->insertComment(subdoc); |
458 | 0 | } |
459 | | |
460 | | void MsWrdParser::send(MWAWEntry const &entry) |
461 | 7.57k | { |
462 | 7.57k | m_textParser->sendText(entry, false); |
463 | 7.57k | } |
464 | | |
465 | | void MsWrdParser::send(int id, libmwaw::SubDocumentType type) |
466 | 8.28k | { |
467 | 8.28k | if (type==libmwaw::DOC_COMMENT_ANNOTATION) |
468 | 0 | m_textParser->sendFieldComment(id); |
469 | 8.28k | else if (type==libmwaw::DOC_NOTE) |
470 | 8.28k | m_textParser->sendFootnote(id); |
471 | 0 | else { |
472 | 0 | MWAW_DEBUG_MSG(("MsWrdParser::send: find unexpected type\n")); |
473 | 0 | } |
474 | 8.28k | } |
475 | | |
476 | | //////////////////////////////////////////////////////////// |
477 | | // the parser |
478 | | //////////////////////////////////////////////////////////// |
479 | | void MsWrdParser::parse(librevenge::RVNGTextInterface *docInterface) |
480 | 63.9k | { |
481 | 63.9k | if (!getInput().get() || !checkHeader(nullptr)) throw(libmwaw::ParseException()); |
482 | 63.9k | bool ok = true; |
483 | 63.9k | try { |
484 | | // create the asciiFile |
485 | 63.9k | ascii().setStream(getInput()); |
486 | 63.9k | ascii().open(asciiName()); |
487 | | |
488 | 63.9k | checkHeader(nullptr); |
489 | 63.9k | ascii().addPos(getInput()->tell()); |
490 | 63.9k | ascii().addNote("_"); |
491 | | |
492 | 63.9k | ok = createZones(); |
493 | 63.9k | if (ok) { |
494 | 63.6k | createDocument(docInterface); |
495 | 63.6k | m_textParser->sendMainText(); |
496 | | |
497 | 63.6k | m_textParser->flushExtra(); |
498 | 63.6k | } |
499 | | |
500 | 63.9k | ascii().reset(); |
501 | 63.9k | } |
502 | 63.9k | catch (...) { |
503 | 0 | MWAW_DEBUG_MSG(("MsWrdParser::parse: exception catched when parsing\n")); |
504 | 0 | ok = false; |
505 | 0 | } |
506 | | |
507 | 63.9k | resetTextListener(); |
508 | 63.9k | if (!ok) throw(libmwaw::ParseException()); |
509 | 63.9k | } |
510 | | |
511 | | //////////////////////////////////////////////////////////// |
512 | | // create the document |
513 | | //////////////////////////////////////////////////////////// |
514 | | void MsWrdParser::createDocument(librevenge::RVNGTextInterface *documentInterface) |
515 | 63.6k | { |
516 | 63.6k | if (!documentInterface) return; |
517 | 63.6k | if (getTextListener()) { |
518 | 0 | MWAW_DEBUG_MSG(("MsWrdParser::createDocument: listener already exist\n")); |
519 | 0 | return; |
520 | 0 | } |
521 | | |
522 | | // update the page |
523 | 63.6k | m_state->m_actPage = 0; |
524 | | |
525 | | // create the page list |
526 | 63.6k | MWAWPageSpan ps(getPageSpan()); |
527 | 63.6k | MWAWEntry entry = m_textParser->getHeader(); |
528 | 63.6k | if (entry.valid()) { |
529 | 4.41k | MWAWHeaderFooter header(MWAWHeaderFooter::HEADER, MWAWHeaderFooter::ALL); |
530 | 4.41k | header.m_subDocument.reset |
531 | 4.41k | (new MsWrdParserInternal::SubDocument(*this, getInput(), entry, libmwaw::DOC_HEADER_FOOTER)); |
532 | 4.41k | ps.setHeaderFooter(header); |
533 | 4.41k | } |
534 | 63.6k | entry = m_textParser->getFooter(); |
535 | 63.6k | if (entry.valid()) { |
536 | 3.15k | MWAWHeaderFooter footer(MWAWHeaderFooter::FOOTER, MWAWHeaderFooter::ALL); |
537 | 3.15k | footer.m_subDocument.reset |
538 | 3.15k | (new MsWrdParserInternal::SubDocument(*this, getInput(), entry, libmwaw::DOC_HEADER_FOOTER)); |
539 | 3.15k | ps.setHeaderFooter(footer); |
540 | 3.15k | } |
541 | 63.6k | int numPage = 1; |
542 | 63.6k | if (m_textParser->numPages() > numPage) |
543 | 6.03k | numPage = m_textParser->numPages(); |
544 | 63.6k | m_state->m_numPages = numPage; |
545 | | |
546 | 63.6k | ps.setPageSpan(m_state->m_numPages+1); |
547 | 63.6k | std::vector<MWAWPageSpan> pageList(1,ps); |
548 | | // |
549 | 63.6k | MWAWTextListenerPtr listen(new MWAWTextListener(*getParserState(), pageList, documentInterface)); |
550 | 63.6k | setTextListener(listen); |
551 | 63.6k | if (!m_state->m_metaData.empty()) |
552 | 2.43k | listen->setDocumentMetaData(m_state->m_metaData); |
553 | 63.6k | listen->startDocument(); |
554 | 63.6k | } |
555 | | |
556 | | |
557 | | //////////////////////////////////////////////////////////// |
558 | | // |
559 | | // Intermediate level |
560 | | // |
561 | | //////////////////////////////////////////////////////////// |
562 | | |
563 | | //////////////////////////////////////////////////////////// |
564 | | // try to find the different zone |
565 | | //////////////////////////////////////////////////////////// |
566 | | bool MsWrdParser::createZones() |
567 | 63.9k | { |
568 | 63.9k | if (!readZoneList()) return false; |
569 | 63.6k | MWAWInputStreamPtr input = getInput(); |
570 | 63.6k | long pos = input->tell(); |
571 | 63.6k | if (pos != m_state->m_bot) { |
572 | 50.2k | ascii().addPos(pos); |
573 | 50.2k | ascii().addNote("_"); |
574 | 50.2k | } |
575 | 63.6k | libmwaw::DebugStream f; |
576 | 63.6k | ascii().addPos(m_state->m_eot); |
577 | 63.6k | ascii().addNote("_"); |
578 | | |
579 | 63.6k | auto it = m_entryMap.find("PrintInfo"); |
580 | 63.6k | if (it != m_entryMap.end()) |
581 | 6.91k | readPrintInfo(it->second); |
582 | | |
583 | 63.6k | it = m_entryMap.find("DocSum"); |
584 | 63.6k | if (it != m_entryMap.end()) |
585 | 5.35k | readDocSum(it->second); |
586 | | |
587 | 63.6k | it = m_entryMap.find("Printer"); |
588 | 63.6k | if (it != m_entryMap.end()) |
589 | 4.63k | readPrinter(it->second); |
590 | | |
591 | 63.6k | readObjects(); |
592 | | |
593 | 63.6k | bool ok = m_textParser->createZones(m_state->m_bot); |
594 | | |
595 | 63.6k | it = m_entryMap.find("DocumentInfo"); |
596 | 63.6k | if (it != m_entryMap.end()) |
597 | 4.27k | readDocumentInfo(it->second); |
598 | | |
599 | 63.6k | it = m_entryMap.find("Zone17"); |
600 | 63.6k | if (it != m_entryMap.end()) |
601 | 2.86k | readZone17(it->second); |
602 | | |
603 | 63.6k | it = m_entryMap.find("Picture"); |
604 | 106k | while (it != m_entryMap.end()) { |
605 | 44.6k | if (!it->second.hasType("Picture")) break; |
606 | 42.9k | MsWrdEntry &entry=it++->second; |
607 | 42.9k | readPicture(entry); |
608 | 42.9k | } |
609 | | |
610 | 365k | for (auto const &fIt : m_entryMap) { |
611 | 365k | MsWrdEntry const &entry = fIt.second; |
612 | 365k | if (entry.isParsed()) continue; |
613 | 88.2k | ascii().addPos(entry.begin()); |
614 | 88.2k | f.str(""); |
615 | 88.2k | f << entry; |
616 | 88.2k | ascii().addNote(f.str().c_str()); |
617 | 88.2k | ascii().addPos(entry.end()); |
618 | 88.2k | ascii().addNote("_"); |
619 | | |
620 | 88.2k | } |
621 | 63.6k | return ok; |
622 | 63.9k | } |
623 | | |
624 | | //////////////////////////////////////////////////////////// |
625 | | // read the zone list ( FIB ) |
626 | | //////////////////////////////////////////////////////////// |
627 | | bool MsWrdParser::readZoneList() |
628 | 63.9k | { |
629 | 63.9k | MWAWInputStreamPtr input = getInput(); |
630 | 63.9k | int const vers = version(); |
631 | 63.9k | getInput()->seek(vers <= 3 ? 30 : 64, librevenge::RVNG_SEEK_SET); |
632 | 63.9k | int numData = vers <= 3 ? 15: 20; |
633 | 63.9k | std::stringstream s; |
634 | 1.17M | for (int i = 0; i < numData; i++) { |
635 | 1.11M | switch (i) { |
636 | | // the first two zone are often simillar : even/odd header/footer ? |
637 | 63.9k | case 0: // original styles zone, often invalid |
638 | 63.9k | readEntry("Styles", 0); |
639 | 63.9k | break; |
640 | 63.9k | case 1: // STSH |
641 | 63.9k | readEntry("Styles", 1); |
642 | 63.9k | break; |
643 | 63.9k | case 2: // FFNDRef |
644 | 63.9k | readEntry("FootnotePos"); |
645 | 63.9k | break; |
646 | 63.9k | case 3: // FFNDText |
647 | 63.9k | readEntry("FootnoteDef"); |
648 | 63.9k | break; |
649 | 63.9k | case 4: // SED |
650 | 63.9k | readEntry("Section"); |
651 | 63.9k | break; |
652 | 63.9k | case 5: // |
653 | 63.9k | readEntry("PageBreak"); |
654 | 63.9k | break; |
655 | 63.9k | case 6: // fandRef |
656 | 63.9k | readEntry("FieldName"); |
657 | 63.9k | break; |
658 | 63.9k | case 7: // fandText |
659 | 63.9k | readEntry("FieldPos"); |
660 | 63.9k | break; |
661 | 63.9k | case 8: // Hdd |
662 | 63.9k | readEntry("HeaderFooter"); |
663 | 63.9k | break; |
664 | 63.9k | case 9: // BteChpx |
665 | 63.9k | readEntry("CharList", 0); |
666 | 63.9k | break; |
667 | 63.9k | case 10: // BtePapx |
668 | 63.9k | readEntry("ParagList", 1); |
669 | 63.9k | break; |
670 | 63.9k | case 12: // SttbfFfn |
671 | 63.9k | readEntry("FontIds"); |
672 | 63.9k | break; |
673 | 63.9k | case 13: // PrDrvr: checkme: is it ok also for v3 file ? |
674 | 63.9k | readEntry("PrintInfo"); |
675 | 63.9k | break; |
676 | 63.9k | case 14: // Clx/Phe |
677 | 63.9k | readEntry(vers <= 3 ? "TextStruct" : "ParaInfo"); |
678 | 63.9k | break; |
679 | 31.0k | case 15: // Dop? |
680 | 31.0k | readEntry("DocumentInfo"); |
681 | 31.0k | break; |
682 | 31.0k | case 16: |
683 | 31.0k | readEntry("Printer"); |
684 | 31.0k | break; |
685 | 31.0k | case 18: // Clx (ie. a list of Pcd ) |
686 | 31.0k | readEntry("TextStruct"); |
687 | 31.0k | break; |
688 | 31.0k | case 19: |
689 | 31.0k | readEntry("FootnoteData"); |
690 | 31.0k | break; |
691 | 95.0k | default: |
692 | 95.0k | s.str(""); |
693 | 95.0k | s << "Zone" << i; |
694 | 95.0k | if (i < 4) s << "_"; |
695 | 95.0k | readEntry(s.str()); |
696 | 95.0k | break; |
697 | 1.11M | } |
698 | 1.11M | } |
699 | | |
700 | 63.9k | if (vers <= 3) return true; |
701 | 31.0k | long pos = input->tell(); |
702 | 31.0k | libmwaw::DebugStream f; |
703 | 31.0k | f << "Entries(ListZoneData)[0]:"; |
704 | 93.1k | for (int i = 0; i < 2; i++) // two small int |
705 | 62.0k | f << "f" << i << "=" << input->readLong(2) << ","; |
706 | | |
707 | 31.0k | ascii().addPos(pos); |
708 | 31.0k | ascii().addNote(f.str().c_str()); |
709 | 31.0k | if (vers <= 4) return true; |
710 | | |
711 | | // main |
712 | 25.1k | readEntry("ObjectName",0); |
713 | 25.1k | readEntry("FontNames"); |
714 | 25.1k | readEntry("ObjectList",0); |
715 | 25.1k | readEntry("ObjectFlags",0); |
716 | 25.1k | readEntry("DocSum",0); |
717 | 175k | for (int i = 25; i < 31; i++) { |
718 | | /* check me: Zone25, Zone26, Zone27: also some object name, list, flags ? */ |
719 | | // header/footer |
720 | 150k | if (i==28) readEntry("ObjectName",1); |
721 | 125k | else if (i==29) readEntry("ObjectList",1); |
722 | 100k | else if (i==30) readEntry("ObjectFlags",1); |
723 | 75.3k | else { |
724 | 75.3k | s.str(""); |
725 | 75.3k | s << "Zone" << i; |
726 | 75.3k | readEntry(s.str()); |
727 | 75.3k | } |
728 | 150k | } |
729 | | |
730 | 25.1k | pos = input->tell(); |
731 | 25.1k | f.str(""); |
732 | 25.1k | f << "ListZoneData[1]:"; |
733 | | |
734 | 25.1k | long val = input->readLong(2); |
735 | 25.1k | if (val) f << "unkn=" << val << ","; |
736 | 25.1k | ascii().addPos(pos); |
737 | 25.1k | ascii().addNote(f.str().c_str()); |
738 | | |
739 | 25.1k | if (input->isEnd()) { |
740 | 374 | MWAW_DEBUG_MSG(("MsWrdParser::readZoneList: can not read list zone\n")); |
741 | 374 | return false; |
742 | 374 | } |
743 | 24.7k | return true; |
744 | 25.1k | } |
745 | | |
746 | | //////////////////////////////////////////////////////////// |
747 | | // |
748 | | // Low level |
749 | | // |
750 | | //////////////////////////////////////////////////////////// |
751 | | |
752 | | |
753 | | |
754 | | //////////////////////////////////////////////////////////// |
755 | | // read the header |
756 | | //////////////////////////////////////////////////////////// |
757 | | bool MsWrdParser::checkHeader(MWAWHeader *header, bool strict) |
758 | 219k | { |
759 | 219k | *m_state = MsWrdParserInternal::State(); |
760 | | |
761 | 219k | MWAWInputStreamPtr input = getInput(); |
762 | 219k | if (!input || !input->hasDataFork()) |
763 | 0 | return false; |
764 | | |
765 | 219k | libmwaw::DebugStream f; |
766 | 219k | int headerSize=64; |
767 | 219k | if (!input->checkPosition(0x88)) { |
768 | 587 | MWAW_DEBUG_MSG(("MsWrdParser::checkHeader: file is too short\n")); |
769 | 587 | return false; |
770 | 587 | } |
771 | 218k | long pos = 0; |
772 | 218k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
773 | 218k | auto val = static_cast<int>(input->readULong(2)); |
774 | 218k | switch (val) { |
775 | 104k | case 0xfe34: |
776 | 104k | switch (input->readULong(2)) { |
777 | 104k | case 0x0: |
778 | 104k | headerSize = 30; |
779 | 104k | setVersion(3); |
780 | 104k | break; |
781 | 0 | default: |
782 | 0 | return false; |
783 | 104k | } |
784 | 104k | break; |
785 | 113k | case 0xfe37: |
786 | 113k | switch (input->readULong(2)) { |
787 | 24.1k | case 0x1c: |
788 | 24.1k | setVersion(4); |
789 | 24.1k | break; |
790 | 89.6k | case 0x23: |
791 | 89.6k | setVersion(5); |
792 | 89.6k | break; |
793 | 0 | default: |
794 | 0 | return false; |
795 | 113k | } |
796 | 113k | break; |
797 | 113k | default: |
798 | 7 | return false; |
799 | 218k | } |
800 | | |
801 | 218k | int const vers = version(); |
802 | 218k | f << "FileHeader:"; |
803 | 218k | val = static_cast<int>(input->readULong(1)); // v1: ab other 0 ? |
804 | 218k | if (val) f << "f0=" << val << ","; |
805 | 655k | for (int i = 1; i < 3; i++) { // always 0 |
806 | 437k | val = static_cast<int>(input->readLong(2)); |
807 | 437k | if (val) f << "f" << i << "=" << val << ","; |
808 | 437k | } |
809 | 218k | if (vers > 3) { |
810 | | // find 4, 8, c, 24, 2c |
811 | 113k | val = static_cast<int>(input->readLong(2)); |
812 | 113k | if (val) |
813 | 96.7k | f << "unkn=" << std::hex << val << std::dec << ","; |
814 | | // 0,0,0x19,0 |
815 | 569k | for (int i = 4; i < 8; i++) { |
816 | 455k | val = static_cast<int>(input->readLong(1)); |
817 | 455k | if (val) f << "f" << i << "=" << val << ","; |
818 | 455k | } |
819 | 113k | } |
820 | | |
821 | 1.31M | for (int i = 0; i < 5; i++) { // always 0 ? |
822 | 1.09M | val = static_cast<int>(input->readLong(1)); |
823 | 1.09M | if (val) f << "g" << i << "=" << val << ","; |
824 | 1.09M | } |
825 | | |
826 | 218k | m_state->m_bot = vers <= 3 ? 0x100 : long(input->readULong(4)); |
827 | 218k | m_state->m_eot = long(input->readULong(4)); |
828 | 218k | f << "text=" << std::hex << m_state->m_bot << "<->" << m_state->m_eot << ","; |
829 | 218k | if (m_state->m_bot > m_state->m_eot) { |
830 | 69.1k | f << "#text,"; |
831 | 69.1k | if (0x100 <= m_state->m_eot) { |
832 | 31.6k | MWAW_DEBUG_MSG(("MsWrdParser::checkHeader: problem with text position: reset begin to default\n")); |
833 | 31.6k | m_state->m_bot = 0x100; |
834 | 31.6k | } |
835 | 37.5k | else { |
836 | 37.5k | MWAW_DEBUG_MSG(("MsWrdParser::checkHeader: problem with text position: reset to empty\n")); |
837 | 37.5k | m_state->m_bot = m_state->m_eot = 0x100; |
838 | 37.5k | } |
839 | 69.1k | } |
840 | | |
841 | 218k | if (vers <= 3) { // always 0 |
842 | 733k | for (int i = 0; i < 6; i++) { |
843 | 628k | val = static_cast<int>(input->readLong(2)); |
844 | 628k | if (val) f << "h" << i << "=" << val << ","; |
845 | 628k | } |
846 | 104k | ascii().addPos(pos); |
847 | 104k | ascii().addNote(f.str().c_str()); |
848 | 104k | if (!readHeaderEndV3()) |
849 | 365 | return false; |
850 | 104k | if (header) |
851 | 38.4k | header->reset(MWAWDocument::MWAW_T_MICROSOFTWORD, vers); |
852 | 104k | return true; |
853 | 104k | } |
854 | | |
855 | 113k | auto endOfData = long(input->readULong(4)); |
856 | 113k | f << "eof=" << std::hex << endOfData << std::dec << ","; |
857 | 113k | if (endOfData < 100 || !input->checkPosition(endOfData)) { |
858 | 63.6k | MWAW_DEBUG_MSG(("MsWrdParser::checkHeader: end of file pos is too small\n")); |
859 | 63.6k | if (endOfData < m_state->m_eot || strict) |
860 | 16.9k | return false; |
861 | 46.7k | f << "#endOfData,"; |
862 | 46.7k | } |
863 | 96.9k | ascii().addPos(endOfData); |
864 | 96.9k | ascii().addNote("Entries(End)"); |
865 | | |
866 | 96.9k | val = static_cast<int>(input->readLong(4)); // always 0 ? |
867 | 96.9k | if (val) f << "unkn2=" << val << ","; |
868 | 96.9k | ascii().addPos(pos); |
869 | 96.9k | ascii().addNote(f.str().c_str()); |
870 | | |
871 | 96.9k | if (!m_textParser->readHeaderTextLength()) |
872 | 0 | return false; |
873 | | |
874 | 96.9k | pos = input->tell(); |
875 | 96.9k | f.str(""); |
876 | 96.9k | f << "FileHeader[A]:"; |
877 | 872k | for (int i = 0; i < 8; i++) { |
878 | 775k | val = static_cast<int>(input->readLong(2)); |
879 | 775k | if (val) f << "f" << i << "=" << val << ","; |
880 | 775k | } |
881 | | |
882 | | // ok, we can finish initialization |
883 | 96.9k | if (header) |
884 | 34.8k | header->reset(MWAWDocument::MWAW_T_MICROSOFTWORD, vers); |
885 | | |
886 | 96.9k | if (long(input->tell()) != headerSize) |
887 | 0 | ascii().addDelimiter(input->tell(), '|'); |
888 | | |
889 | 96.9k | ascii().addPos(pos); |
890 | 96.9k | ascii().addNote(f.str().c_str()); |
891 | | |
892 | 96.9k | return true; |
893 | 96.9k | } |
894 | | |
895 | | //////////////////////////////////////////////////////////// |
896 | | // try to the end of the header |
897 | | //////////////////////////////////////////////////////////// |
898 | | bool MsWrdParser::readHeaderEndV3() |
899 | 104k | { |
900 | 104k | MWAWInputStreamPtr input = getInput(); |
901 | 104k | if (!input->checkPosition(0xb8)) |
902 | 365 | return false; |
903 | 104k | libmwaw::DebugStream f; |
904 | 104k | input->seek(0x78, librevenge::RVNG_SEEK_SET); |
905 | 104k | long pos = input->tell(); |
906 | 104k | long val = input->readLong(4); // normally 0x100 |
907 | 104k | if (val != 0x100) |
908 | 101k | f << "FileHeader[A]:" << std::hex << val << std::dec << ","; |
909 | 2.65k | else |
910 | 2.65k | f << "_"; |
911 | 104k | ascii().addPos(pos); |
912 | 104k | ascii().addNote(f.str().c_str()); |
913 | 104k | if (!m_textParser->readHeaderTextLength()) |
914 | 0 | return false; |
915 | 104k | pos = input->tell(); |
916 | 104k | f << "FileHeader[B]:"; |
917 | 1.98M | for (int i = 0; i < 18; i++) { // always 0 ? |
918 | 1.87M | val = input->readLong(2); |
919 | 1.87M | if (val) |
920 | 1.29M | f << "f" << i << "=" << val << ","; |
921 | 1.87M | } |
922 | 104k | float dim[6]; // H, W+margin T, L, B, R |
923 | 626k | for (auto &d : dim) d = float(input->readLong(2))/1440.0f; |
924 | | |
925 | 104k | f << "page=" << dim[1] << "x" << dim[0] << ","; |
926 | 104k | f << "margins=" << dim[3] << "x" << dim[2] << "-" << dim[5] << "x" << dim[4] << ","; |
927 | 104k | bool dimOk = true; |
928 | 104k | if (dim[0]>0 && dim[1]>0) { |
929 | 187k | for (int i = 2; i < 6; i++) |
930 | 150k | if (dim[i] < 0) dimOk = false; |
931 | 37.5k | if (2*(dim[3]+dim[5]) > dim[1] || 2*(dim[2]+dim[4]) > dim[0]) dimOk = false; |
932 | 37.5k | if (!dimOk) { |
933 | 34.3k | f << "###"; |
934 | 34.3k | MWAW_DEBUG_MSG(("MsWrdParser::readHeaderEndV3: page dimensions seem bad\n")); |
935 | 34.3k | } |
936 | 3.26k | else { |
937 | 3.26k | getPageSpan().setMarginTop(double(dim[2])); |
938 | 3.26k | getPageSpan().setMarginLeft(double(dim[3])); |
939 | 3.26k | getPageSpan().setMarginBottom((dim[4]< 0.5f) ? 0.0 : double(dim[4])-0.5); |
940 | 3.26k | getPageSpan().setMarginRight((dim[5]< 0.5f) ? 0.0 : double(dim[5])-0.5); |
941 | 3.26k | getPageSpan().setFormLength(double(dim[0])); |
942 | 3.26k | getPageSpan().setFormWidth(double(dim[1])); |
943 | 3.26k | } |
944 | 37.5k | } |
945 | 66.7k | else |
946 | 66.7k | dimOk = false; |
947 | 104k | ascii().addPos(pos); |
948 | 104k | ascii().addNote(f.str().c_str()); |
949 | | |
950 | 104k | pos = input->tell(); |
951 | 104k | f.str(""); |
952 | 104k | f << "FileHeader[C]:"; |
953 | 104k | val = input->readLong(2); // always 0 ? |
954 | 104k | if (val) |
955 | 66.0k | f << "margins[binding]=" << float(val)/1440.f << ","; |
956 | 104k | val = input->readLong(2); |
957 | 104k | f << "defTabs=" << float(val)/1440.f << ","; |
958 | 104k | auto flags = static_cast<int>(input->readULong(1)); |
959 | 104k | if (flags & 0x80) // page vis a vis |
960 | 14.0k | f << "facingpage,"; |
961 | 104k | if (flags & 0x40) // ligne creuse |
962 | 20.3k | f << "defTabs[emptyline],"; |
963 | 104k | switch ((flags>>1) & 0x3) { |
964 | 63.4k | case 0: |
965 | 63.4k | if (dimOk) m_state->m_endNote = true; |
966 | 63.4k | f << "endnote,"; |
967 | 63.4k | break; |
968 | 9.28k | case 1: |
969 | 9.28k | f << "footnote,"; |
970 | 9.28k | break; |
971 | 12.2k | case 2: |
972 | 12.2k | f << "footnote[undertext],"; |
973 | 12.2k | break; |
974 | 19.3k | default: |
975 | 19.3k | f << "#notepos=3,"; |
976 | 19.3k | break; |
977 | 104k | } |
978 | 104k | if (flags&1) { |
979 | 32.0k | f << "landscape,"; |
980 | 32.0k | if (dimOk) |
981 | 611 | getPageSpan().setFormOrientation(MWAWPageSpan::LANDSCAPE); |
982 | 32.0k | } |
983 | 104k | flags &= 0x38; |
984 | 104k | if (flags) |
985 | 42.1k | f << "#flags=" << std::hex << flags << std::dec << ","; |
986 | 104k | flags = static_cast<int>(input->readULong(1)); |
987 | 104k | if (flags) // always 1 |
988 | 55.6k | f << "fl1=" << std::hex << flags << std::dec << ","; |
989 | 104k | char const *wh[] = { "note", "line", "page" }; |
990 | 313k | for (auto const *what : wh) { |
991 | 313k | val = long(input->readULong(2)); |
992 | 313k | if (val == 1) continue; |
993 | 298k | if (val & 0x8000) |
994 | 49.0k | f << what << "[firstNumber]=" << (val&0x7FFF) << "[auto],"; |
995 | 249k | else |
996 | 249k | f << what << "[firstNumber]=" << val << ","; |
997 | 298k | } |
998 | 313k | for (int i = 0; i < 2; i++) { // first flags often 0x40, second? |
999 | 208k | flags = static_cast<int>(input->readULong(1)); |
1000 | 208k | if (flags) // always 1 |
1001 | 104k | f << "fl" << 2+i << "=" << std::hex << flags << std::dec << ","; |
1002 | 208k | } |
1003 | 1.46M | for (int i = 0; i < 13; i++) { // always 0? |
1004 | 1.35M | val = input->readLong(2); |
1005 | 1.35M | if (val) |
1006 | 819k | f << "f" << i << "=" << val << ","; |
1007 | 1.35M | } |
1008 | 104k | ascii().addPos(pos); |
1009 | 104k | ascii().addNote(f.str().c_str()); |
1010 | | |
1011 | 104k | pos = input->tell(); |
1012 | 104k | f.str(""); |
1013 | 104k | f << "FileHeader[D]:"; |
1014 | 104k | auto sz = static_cast<int>(input->readULong(1)); |
1015 | 104k | if (sz == 0) { |
1016 | 50.7k | ascii().addPos(pos); |
1017 | 50.7k | ascii().addNote("_"); |
1018 | 50.7k | return true; |
1019 | 50.7k | } |
1020 | 53.5k | if (sz > 31) { |
1021 | 29.7k | f << "###"; |
1022 | 29.7k | MWAW_DEBUG_MSG(("MsWrdParser::readHeaderEndV3: next filename seems bad\n")); |
1023 | 29.7k | } |
1024 | 23.8k | else { |
1025 | 23.8k | std::string fName(""); |
1026 | 316k | for (int i = 0; i < sz; i++) |
1027 | 292k | fName += char(input->readULong(1)); |
1028 | 23.8k | f << "nextFile=" << fName; |
1029 | 23.8k | } |
1030 | 53.5k | ascii().addPos(pos); |
1031 | 53.5k | ascii().addNote(f.str().c_str()); |
1032 | 53.5k | input->seek(0x100, librevenge::RVNG_SEEK_SET); |
1033 | 53.5k | return true; |
1034 | 104k | } |
1035 | | |
1036 | | //////////////////////////////////////////////////////////// |
1037 | | // try to read an entry |
1038 | | //////////////////////////////////////////////////////////// |
1039 | | MsWrdEntry MsWrdParser::readEntry(std::string type, int id) |
1040 | 1.39M | { |
1041 | 1.39M | MWAWInputStreamPtr input = getInput(); |
1042 | 1.39M | MsWrdEntry entry; |
1043 | 1.39M | entry.setType(type); |
1044 | 1.39M | entry.setId(id); |
1045 | 1.39M | long pos = input->tell(); |
1046 | 1.39M | libmwaw::DebugStream f; |
1047 | | |
1048 | 1.39M | auto debPos = long(input->readULong(4)); |
1049 | 1.39M | auto sz = long(input->readULong(2)); |
1050 | 1.39M | if (id >= 0) f << "Entries(" << type << ")[" << id << "]:"; |
1051 | 959k | else f << "Entries(" << type << "):"; |
1052 | 1.39M | if (sz == 0) { |
1053 | 481k | ascii().addPos(pos); |
1054 | 481k | ascii().addNote("_"); |
1055 | 481k | return entry; |
1056 | 481k | } |
1057 | 909k | if (!input->checkPosition(debPos+sz)) { |
1058 | 680k | MWAW_DEBUG_MSG(("MsWrdParser::readEntry: problem reading entry: %s\n", type.c_str())); |
1059 | 680k | f << "#"; |
1060 | 680k | ascii().addPos(pos); |
1061 | 680k | ascii().addNote(f.str().c_str()); |
1062 | 680k | return entry; |
1063 | 680k | } |
1064 | | |
1065 | 229k | entry.setBegin(debPos); |
1066 | 229k | entry.setLength(sz); |
1067 | 229k | m_entryMap.insert |
1068 | 229k | (std::multimap<std::string, MsWrdEntry>::value_type(type, entry)); |
1069 | | |
1070 | 229k | f << std::hex << debPos << "[" << sz << "],"; |
1071 | 229k | ascii().addPos(pos); |
1072 | 229k | ascii().addNote(f.str().c_str()); |
1073 | | |
1074 | 229k | return entry; |
1075 | 909k | } |
1076 | | |
1077 | | //////////////////////////////////////////////////////////// |
1078 | | // read the document information |
1079 | | //////////////////////////////////////////////////////////// |
1080 | | bool MsWrdParser::readDocumentInfo(MsWrdEntry &entry) |
1081 | 4.27k | { |
1082 | 4.27k | if (entry.length() != 0x20) { |
1083 | 2.34k | MWAW_DEBUG_MSG(("MsWrdParser::readDocumentInfo: the zone size seems odd\n")); |
1084 | 2.34k | return false; |
1085 | 2.34k | } |
1086 | 1.92k | MWAWInputStreamPtr input = getInput(); |
1087 | 1.92k | long pos = entry.begin(); |
1088 | 1.92k | entry.setParsed(true); |
1089 | 1.92k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1090 | 1.92k | libmwaw::DebugStream f; |
1091 | 1.92k | f << "DocumentInfo:"; |
1092 | | |
1093 | 1.92k | float dim[2]; |
1094 | 3.85k | for (float &i : dim) i = float(input->readLong(2))/1440.f; |
1095 | 1.92k | f << "dim?=" << dim[1] << "x" << dim[0] << ","; |
1096 | | |
1097 | 1.92k | float margin[4]; |
1098 | 1.92k | f << ",marg=["; // top, left?, bottom, right? |
1099 | 7.71k | for (auto &marg : margin) { |
1100 | 7.71k | marg = float(input->readLong(2))/1440.f; |
1101 | 7.71k | f << marg << ","; |
1102 | 7.71k | if (marg < 0) marg *= -1.0f; |
1103 | 7.71k | } |
1104 | 1.92k | f << "],"; |
1105 | | |
1106 | 1.92k | if (dim[0] > margin[0]+margin[2] && dim[1] > margin[1]+margin[3]) { |
1107 | 1.31k | getPageSpan().setMarginTop(double(margin[0])); |
1108 | 1.31k | getPageSpan().setMarginLeft(double(margin[1])); |
1109 | | /* decrease a little the right/bottom margin to allow fonts discrepancy*/ |
1110 | 1.31k | getPageSpan().setMarginBottom((margin[2]< 0.5f) ? 0.0 : double(margin[2])-0.5); |
1111 | 1.31k | getPageSpan().setMarginRight((margin[3]< 0.5f) ? 0.0 : double(margin[3])-0.5); |
1112 | | |
1113 | 1.31k | getPageSpan().setFormLength(double(dim[0])); |
1114 | 1.31k | getPageSpan().setFormWidth(double(dim[1])); |
1115 | 1.31k | } |
1116 | 615 | else { |
1117 | 615 | MWAW_DEBUG_MSG(("MsWrdParser::readDocumentInfo: the page dimensions seems odd\n")); |
1118 | 615 | } |
1119 | | |
1120 | 1.92k | auto val = static_cast<int>(input->readLong(2)); // always 0 ? |
1121 | 1.92k | if (val) f << "unkn=" << val << ","; |
1122 | 1.92k | val = static_cast<int>(input->readLong(2)); // 0x2c5 or 0x2d0? |
1123 | 1.92k | f << "f0=" << val << ","; |
1124 | 9.64k | for (int i = 0; i < 4; i++) { //[a|12|40|42|4a|52|54|d2],0,0|80,1 |
1125 | 7.71k | val = static_cast<int>(input->readULong(1)); |
1126 | 7.71k | if (val) f << "fl" << i << "=" << std::hex << val << std::dec << ","; |
1127 | 7.71k | } |
1128 | 1.92k | val = static_cast<int>(input->readLong(2)); // always 1 ? |
1129 | 1.92k | if (val != 1) f << "f1=" << val << ","; |
1130 | | // a small number between 0 and 77 |
1131 | 1.92k | f << "f2=" << static_cast<int>(input->readLong(2)) << ","; |
1132 | 9.64k | for (int i = 0; i < 4; i++) { //[0|2|40|42|44|46|48|58],0|64,0|10|80,[0|2|5] |
1133 | 7.71k | val = static_cast<int>(input->readULong(1)); |
1134 | 7.71k | if (val) f << "flA" << i << "=" << std::hex << val << std::dec << ","; |
1135 | 7.71k | } |
1136 | 1.92k | val = static_cast<int>(input->readLong(2)); // always 0 ? |
1137 | 1.92k | if (val != 1) f << "f3=" << val << ","; |
1138 | 1.92k | val = static_cast<int>(input->readLong(2)); // 0, 48, 50 |
1139 | 1.92k | if (val) f << "f4=" << val << ","; |
1140 | | |
1141 | 1.92k | ascii().addPos(entry.begin()); |
1142 | 1.92k | ascii().addNote(f.str().c_str()); |
1143 | 1.92k | ascii().addPos(entry.end()); |
1144 | 1.92k | ascii().addNote("_"); |
1145 | 1.92k | return true; |
1146 | 4.27k | } |
1147 | | |
1148 | | //////////////////////////////////////////////////////////// |
1149 | | // read the zone 17 |
1150 | | //////////////////////////////////////////////////////////// |
1151 | | bool MsWrdParser::readZone17(MsWrdEntry &entry) |
1152 | 2.86k | { |
1153 | 2.86k | if (entry.length() != 0x2a) { |
1154 | 1.08k | MWAW_DEBUG_MSG(("MsWrdParser::readZone17: the zone size seems odd\n")); |
1155 | 1.08k | return false; |
1156 | 1.08k | } |
1157 | 1.77k | MWAWInputStreamPtr input = getInput(); |
1158 | 1.77k | long pos = entry.begin(); |
1159 | 1.77k | entry.setParsed(true); |
1160 | 1.77k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1161 | 1.77k | libmwaw::DebugStream f; |
1162 | 1.77k | f << "Zone17:"; |
1163 | 1.77k | if (version() < 5) { |
1164 | 21 | f << "bdbox?=["; |
1165 | 105 | for (int i = 0; i < 4; i++) |
1166 | 84 | f << input->readLong(2) << ","; |
1167 | 21 | f << "],"; |
1168 | 21 | f << "bdbox2?=["; |
1169 | 105 | for (int i = 0; i < 4; i++) |
1170 | 84 | f << input->readLong(2) << ","; |
1171 | 21 | f << "],"; |
1172 | 21 | } |
1173 | | |
1174 | | /* |
1175 | | f0=0, 80, 82, 84, b0, b4, c2, c4, f0, f2 : type and ? |
1176 | | f1=0|1|8|34|88 */ |
1177 | 1.77k | int val; |
1178 | 5.32k | for (int i = 0; i < 2; i++) { |
1179 | 3.54k | val = static_cast<int>(input->readULong(1)); |
1180 | 3.54k | if (val) f << "f" << i << "=" << std::hex << val << std::dec << ","; |
1181 | 3.54k | } |
1182 | | // 0 or 1, followed by 0 |
1183 | 5.32k | for (int i = 2; i < 4; i++) { |
1184 | 3.54k | val = static_cast<int>(input->readLong(1)); |
1185 | 3.54k | if (val) f << "f" << i << "=" << val << ","; |
1186 | 3.54k | } |
1187 | 1.77k | auto ptr = long(input->readULong(4)); // a text ptr ( often near to textLength ) |
1188 | 1.77k | f << "textPos[sel?]=" << std::hex << ptr << std::dec << ","; |
1189 | 1.77k | val = static_cast<int>(input->readULong(4)); // almost always ptr |
1190 | 1.77k | if (val != ptr) |
1191 | 822 | f << "textPos1=" << std::hex << val << std::dec << ","; |
1192 | | // a small int between 6 and b |
1193 | 1.77k | val = static_cast<int>(input->readLong(2)); |
1194 | 1.77k | if (val) f << "f4=" << val << ","; |
1195 | | |
1196 | 5.32k | for (int i = 5; i < 7; i++) { // 0,0 or 3,5 or 8000, 8000 |
1197 | 3.54k | val = static_cast<int>(input->readULong(2)); |
1198 | 3.54k | if (val) f << "f" << i << "=" << std::hex << val << std::dec << ","; |
1199 | 3.54k | } |
1200 | 1.77k | val = static_cast<int>(input->readULong(4)); // almost always ptr |
1201 | 1.77k | if (val != ptr) |
1202 | 680 | f << "textPos2=" << std::hex << val << std::dec << ","; |
1203 | | /* g0=[0,1,5,c], g1=[0,1,3,4] */ |
1204 | 5.32k | for (int i = 0; i < 2; i++) { |
1205 | 3.54k | val = static_cast<int>(input->readLong(2)); |
1206 | 3.54k | if (val) f << "g" << i << "=" << val << ","; |
1207 | 3.54k | } |
1208 | 1.77k | if (version() == 5) { |
1209 | 1.75k | f << "bdbox?=["; |
1210 | 8.76k | for (int i = 0; i < 4; i++) |
1211 | 7.01k | f << input->readLong(2) << ","; |
1212 | 1.75k | f << "],"; |
1213 | 1.75k | f << "bdbox2?=["; |
1214 | 8.76k | for (int i = 0; i < 4; i++) |
1215 | 7.01k | f << input->readLong(2) << ","; |
1216 | 1.75k | f << "],"; |
1217 | 1.75k | } |
1218 | 1.77k | ascii().addPos(pos); |
1219 | 1.77k | ascii().addNote(f.str().c_str()); |
1220 | 1.77k | ascii().addPos(entry.end()); |
1221 | 1.77k | ascii().addNote("_"); |
1222 | 1.77k | return true; |
1223 | 2.86k | } |
1224 | | |
1225 | | //////////////////////////////////////////////////////////// |
1226 | | // read the printer name |
1227 | | //////////////////////////////////////////////////////////// |
1228 | | bool MsWrdParser::readPrinter(MsWrdEntry &entry) |
1229 | 4.63k | { |
1230 | 4.63k | if (entry.length() < 2) { |
1231 | 159 | MWAW_DEBUG_MSG(("MsWrdParser::readPrinter: the zone seems to short\n")); |
1232 | 159 | return false; |
1233 | 159 | } |
1234 | | |
1235 | 4.47k | MWAWInputStreamPtr input = getInput(); |
1236 | 4.47k | long pos = entry.begin(); |
1237 | 4.47k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1238 | 4.47k | libmwaw::DebugStream f; |
1239 | 4.47k | f << "Printer:"; |
1240 | 4.47k | auto sz = static_cast<int>(input->readULong(2)); |
1241 | 4.47k | if (sz > entry.length()) { |
1242 | 2.52k | MWAW_DEBUG_MSG(("MsWrdParser::readPrinter: the zone seems to short\n")); |
1243 | 2.52k | return false; |
1244 | 2.52k | } |
1245 | 1.95k | auto strSz = static_cast<int>(input->readULong(1)); |
1246 | 1.95k | if (strSz+2> sz) { |
1247 | 352 | MWAW_DEBUG_MSG(("MsWrdParser::readPrinter: name seems to big\n")); |
1248 | 352 | return false; |
1249 | 352 | } |
1250 | 1.60k | std::string name(""); |
1251 | 39.9k | for (int i = 0; i < strSz; i++) |
1252 | 38.3k | name+=char(input->readLong(1)); |
1253 | 1.60k | f << name << ","; |
1254 | 1.60k | int i= 0; |
1255 | 1.14M | while (long(input->tell())+2 <= entry.end()) { // almost always a,0,0 |
1256 | 1.14M | auto val = static_cast<int>(input->readLong(2)); |
1257 | 1.14M | if (val) f << "f" << i << "=" << val << ","; |
1258 | 1.14M | i++; |
1259 | 1.14M | } |
1260 | 1.60k | if (long(input->tell()) != entry.end()) |
1261 | 210 | ascii().addDelimiter(input->tell(), '|'); |
1262 | | |
1263 | 1.60k | entry.setParsed(true); |
1264 | 1.60k | ascii().addPos(pos); |
1265 | 1.60k | ascii().addNote(f.str().c_str()); |
1266 | | |
1267 | 1.60k | ascii().addPos(entry.end()); |
1268 | 1.60k | ascii().addNote("_"); |
1269 | 1.60k | return true; |
1270 | 1.95k | } |
1271 | | |
1272 | | //////////////////////////////////////////////////////////// |
1273 | | // read the document summary |
1274 | | //////////////////////////////////////////////////////////// |
1275 | | bool MsWrdParser::readDocSum(MsWrdEntry &entry) |
1276 | 5.35k | { |
1277 | 5.35k | MWAWInputStreamPtr input = getInput(); |
1278 | 5.35k | if (entry.length() < 8 || !input->checkPosition(entry.end())) { |
1279 | 246 | MWAW_DEBUG_MSG(("MsWrdParser::readDocSum: the zone seems to short\n")); |
1280 | 246 | return false; |
1281 | 246 | } |
1282 | | |
1283 | 5.11k | long pos = entry.begin(); |
1284 | 5.11k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1285 | 5.11k | libmwaw::DebugStream f; |
1286 | 5.11k | f << "DocSum:"; |
1287 | 5.11k | auto sz = static_cast<int>(input->readULong(2)); |
1288 | 5.11k | if (sz > entry.length()) { |
1289 | 1.60k | MWAW_DEBUG_MSG(("MsWrdParser::readDocSum: the zone seems to short\n")); |
1290 | 1.60k | return false; |
1291 | 1.60k | } |
1292 | 3.51k | entry.setParsed(true); |
1293 | | |
1294 | 3.51k | if (sz != entry.length()) f << "#"; |
1295 | 3.51k | char const *what[] = { "title", "subject","author","version","keyword", |
1296 | 3.51k | "creator", "author1", "author2" // unsure why there are 4 authors... |
1297 | 3.51k | }; |
1298 | 3.51k | char const *attribNames[] = { "dc:title", "dc:subject", "meta:initial-creator", nullptr, |
1299 | 3.51k | "meta:keywords", "dc:creator", nullptr, nullptr |
1300 | 3.51k | }; |
1301 | 3.51k | auto fontConverter = getFontConverter(); |
1302 | 26.8k | for (int i = 0; i < 8; i++) { |
1303 | 24.7k | long actPos = input->tell(); |
1304 | 24.7k | if (actPos == entry.end()) break; |
1305 | | |
1306 | 24.0k | sz = static_cast<int>(input->readULong(1)); |
1307 | 24.0k | if (sz == 0 || sz == 0xFF) continue; |
1308 | | |
1309 | 9.28k | if (actPos+1+sz > entry.end()) { |
1310 | 723 | MWAW_DEBUG_MSG(("MsWrdParser::readDocSum: string %d to short...\n", i)); |
1311 | 723 | f << "#"; |
1312 | 723 | input->seek(actPos, librevenge::RVNG_SEEK_SET); |
1313 | 723 | break; |
1314 | 723 | } |
1315 | 8.55k | librevenge::RVNGString s; |
1316 | 323k | for (int j = 0; j < sz; j++) { |
1317 | 314k | auto c= static_cast<unsigned char>(input->readULong(1)); |
1318 | | // assume standart encoding here |
1319 | 314k | int unicode = fontConverter ? fontConverter->unicode(3, c) : -1; |
1320 | 314k | if (unicode!=-1) |
1321 | 174k | libmwaw::appendUnicode(uint32_t(unicode), s); |
1322 | 140k | else if (c<0x20) |
1323 | 140k | f << "##" << int(c); |
1324 | 0 | else |
1325 | 0 | s.append(char(c)); |
1326 | 314k | } |
1327 | 8.55k | if (!s.empty() && attribNames[i]!=nullptr) |
1328 | 5.01k | m_state->m_metaData.insert(attribNames[i],s); |
1329 | 8.55k | f << what[i] << "=" << s.cstr() << ","; |
1330 | 8.55k | } |
1331 | | |
1332 | 3.51k | ascii().addPos(pos); |
1333 | 3.51k | ascii().addNote(f.str().c_str()); |
1334 | | |
1335 | 3.51k | if (long(input->tell()) != entry.end()) |
1336 | 2.84k | ascii().addDelimiter(input->tell(), '|'); |
1337 | | |
1338 | 3.51k | ascii().addPos(entry.end()); |
1339 | 3.51k | ascii().addNote("_"); |
1340 | 3.51k | return true; |
1341 | 5.11k | } |
1342 | | |
1343 | | //////////////////////////////////////////////////////////// |
1344 | | // read a list of strings zone |
1345 | | //////////////////////////////////////////////////////////// |
1346 | | bool MsWrdParser::readStringsZone(MsWrdEntry &entry, std::vector<std::string> &list) |
1347 | 6.88k | { |
1348 | 6.88k | list.resize(0); |
1349 | 6.88k | MWAWInputStreamPtr input = getInput(); |
1350 | 6.88k | if (entry.length() < 2 || !input->checkPosition(entry.end())) { |
1351 | 491 | MWAW_DEBUG_MSG(("MsWrdParser::readStringsZone: the zone seems to short\n")); |
1352 | 491 | return false; |
1353 | 491 | } |
1354 | | |
1355 | 6.39k | long pos = entry.begin(); |
1356 | 6.39k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1357 | 6.39k | libmwaw::DebugStream f; |
1358 | 6.39k | f << entry; |
1359 | 6.39k | auto sz = static_cast<int>(input->readULong(2)); |
1360 | 6.39k | if (sz > entry.length()) { |
1361 | 2.09k | MWAW_DEBUG_MSG(("MsWrdParser::readStringsZone: the zone seems to short\n")); |
1362 | 2.09k | return false; |
1363 | 2.09k | } |
1364 | 4.30k | ascii().addPos(entry.begin()); |
1365 | 4.30k | ascii().addNote(f.str().c_str()); |
1366 | | |
1367 | 4.30k | int id = 0; |
1368 | 2.38M | while (long(input->tell()) != entry.end()) { |
1369 | 2.37M | pos = input->tell(); |
1370 | 2.37M | auto strSz = static_cast<int>(input->readULong(1)); |
1371 | 2.37M | if (pos+strSz+1> entry.end()) { |
1372 | 2.93k | MWAW_DEBUG_MSG(("MsWrdParser::readStringsZone: a string seems to big\n")); |
1373 | 2.93k | f << "#"; |
1374 | 2.93k | break; |
1375 | 2.93k | } |
1376 | 2.37M | std::string name(""); |
1377 | 24.0M | for (int i = 0; i < strSz; i++) |
1378 | 21.6M | name+=char(input->readLong(1)); |
1379 | 2.37M | list.push_back(name); |
1380 | 2.37M | f.str(""); |
1381 | 2.37M | f << entry << "id" << id++ << "," << name << ","; |
1382 | 2.37M | ascii().addPos(pos); |
1383 | 2.37M | ascii().addNote(f.str().c_str()); |
1384 | 2.37M | } |
1385 | | |
1386 | 4.30k | if (long(input->tell()) != entry.end()) { |
1387 | 2.83k | ascii().addPos(input->tell()); |
1388 | 2.83k | f.str(""); |
1389 | 2.83k | f << entry << "#"; |
1390 | 2.83k | ascii().addNote(f.str().c_str()); |
1391 | 2.83k | } |
1392 | | |
1393 | 4.30k | entry.setParsed(true); |
1394 | | |
1395 | 4.30k | ascii().addPos(entry.end()); |
1396 | 4.30k | ascii().addNote("_"); |
1397 | 4.30k | return true; |
1398 | 6.39k | } |
1399 | | |
1400 | | //////////////////////////////////////////////////////////// |
1401 | | // read the objects |
1402 | | //////////////////////////////////////////////////////////// |
1403 | | bool MsWrdParser::readObjects() |
1404 | 63.6k | { |
1405 | 63.6k | MWAWInputStreamPtr input = getInput(); |
1406 | | |
1407 | 63.6k | auto it = m_entryMap.find("ObjectList"); |
1408 | 72.4k | while (it != m_entryMap.end()) { |
1409 | 16.0k | if (!it->second.hasType("ObjectList")) break; |
1410 | 8.86k | MsWrdEntry &entry=it++->second; |
1411 | 8.86k | readObjectList(entry); |
1412 | 8.86k | } |
1413 | | |
1414 | 63.6k | it = m_entryMap.find("ObjectFlags"); |
1415 | 70.5k | while (it != m_entryMap.end()) { |
1416 | 12.8k | if (!it->second.hasType("ObjectFlags")) break; |
1417 | 6.91k | MsWrdEntry &entry=it++->second; |
1418 | 6.91k | readObjectFlags(entry); |
1419 | 6.91k | } |
1420 | | |
1421 | 63.6k | it = m_entryMap.find("ObjectName"); |
1422 | 70.4k | while (it != m_entryMap.end()) { |
1423 | 12.5k | if (!it->second.hasType("ObjectName")) break; |
1424 | 6.88k | MsWrdEntry &entry=it++->second; |
1425 | 6.88k | std::vector<std::string> list; |
1426 | 6.88k | readStringsZone(entry, list); |
1427 | | |
1428 | 6.88k | if (entry.id() < 0 || entry.id() > 1) { |
1429 | 0 | MWAW_DEBUG_MSG(("MsWrdParser::readObjects: unexpected entry id: %d\n", entry.id())); |
1430 | 0 | continue; |
1431 | 0 | } |
1432 | 6.88k | auto &listObject = m_state->m_objectList[entry.id()]; |
1433 | 6.88k | size_t numObjects = listObject.size(); |
1434 | 6.88k | if (list.size() != numObjects) { |
1435 | 4.27k | MWAW_DEBUG_MSG(("MsWrdParser::readObjects: unexpected number of name\n")); |
1436 | 4.27k | if (list.size() < numObjects) numObjects = list.size(); |
1437 | 4.27k | } |
1438 | 326k | for (size_t i = 0; i < numObjects; i++) |
1439 | 319k | listObject[i].m_name = list[i]; |
1440 | 6.88k | } |
1441 | | |
1442 | 63.6k | std::map<long, MWAWEntry> posToComments; |
1443 | 127k | for (auto &listObject : m_state->m_objectList) { |
1444 | 1.98M | for (auto &obj : listObject) { |
1445 | 1.98M | readObject(obj); |
1446 | 1.98M | if (obj.m_annotation.valid() && obj.m_textPos>=0) |
1447 | 0 | posToComments[obj.m_textPos]=obj.m_annotation; |
1448 | 1.98M | } |
1449 | 127k | } |
1450 | 63.6k | m_state->m_posToCommentMap=posToComments; |
1451 | 63.6k | return true; |
1452 | 63.6k | } |
1453 | | |
1454 | | bool MsWrdParser::readObjectList(MsWrdEntry &entry) |
1455 | 8.86k | { |
1456 | 8.86k | if (entry.id() < 0 || entry.id() > 1) { |
1457 | 0 | MWAW_DEBUG_MSG(("MsWrdParser::readObjectList: unexpected entry id: %d\n", entry.id())); |
1458 | 0 | return false; |
1459 | 0 | } |
1460 | 8.86k | std::vector<MsWrdParserInternal::Object> &listObject = m_state->m_objectList[entry.id()]; |
1461 | 8.86k | listObject.resize(0); |
1462 | 8.86k | if (entry.length() < 4 || (entry.length()%18) != 4) { |
1463 | 1.83k | MWAW_DEBUG_MSG(("MsWrdParser::readObjectList: the zone size seems odd\n")); |
1464 | 1.83k | return false; |
1465 | 1.83k | } |
1466 | 7.02k | MWAWInputStreamPtr input = getInput(); |
1467 | 7.02k | long pos = entry.begin(); |
1468 | 7.02k | entry.setParsed(true); |
1469 | 7.02k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1470 | 7.02k | libmwaw::DebugStream f; |
1471 | 7.02k | f << "ObjectList[" << entry.id() << "]:"; |
1472 | 7.02k | auto N=int(entry.length()/18); |
1473 | | |
1474 | 7.02k | auto &plcMap=m_textParser->getTextPLCMap(); |
1475 | 7.02k | MsWrdText::PLC plc(MsWrdText::PLC::Object); |
1476 | 7.02k | std::vector<long> textPos; // checkme |
1477 | 7.02k | textPos.resize(size_t(N)+1); |
1478 | 7.02k | f << "["; |
1479 | 1.99M | for (int i = 0; i < N+1; i++) { |
1480 | 1.99M | auto tPos = long(input->readULong(4)); |
1481 | 1.99M | textPos[size_t(i)] = tPos; |
1482 | 1.99M | f << std::hex << tPos << std::dec << ","; |
1483 | 1.99M | if (i == N) |
1484 | 7.02k | break; |
1485 | 1.98M | plc.m_id = i; |
1486 | 1.98M | plcMap.insert(std::multimap<long, MsWrdText::PLC>::value_type(tPos,plc)); |
1487 | 1.98M | } |
1488 | 7.02k | f << "],"; |
1489 | 7.02k | ascii().addPos(pos); |
1490 | 7.02k | ascii().addNote(f.str().c_str()); |
1491 | | |
1492 | 1.99M | for (int i = 0; i < N; i++) { |
1493 | 1.98M | MsWrdParserInternal::Object object; |
1494 | 1.98M | object.m_textPos = textPos[size_t(i)]; |
1495 | 1.98M | pos = input->tell(); |
1496 | 1.98M | f.str(""); |
1497 | 1.98M | object.m_id = static_cast<int>(input->readLong(2)); |
1498 | | // id0=<small number>:[8|48], id1: <small number>:60->normal, :7c?, 0->annotation ? |
1499 | 5.96M | for (int st = 0; st < 2; st++) { |
1500 | 3.97M | object.m_ids[st] = static_cast<int>(input->readLong(2)); |
1501 | 3.97M | object.m_idsFlag[st] = static_cast<int>(input->readULong(1)); |
1502 | 3.97M | } |
1503 | | |
1504 | 1.98M | object.m_pos.setBegin(long(input->readULong(4))); |
1505 | 1.98M | auto val = static_cast<int>(input->readLong(2)); // always 0 ? |
1506 | 1.98M | if (val) f << "#f1=" << val << ","; |
1507 | 1.98M | object.m_extra = f.str(); |
1508 | 1.98M | f.str(""); |
1509 | 1.98M | f << "ObjectList-" << i << ":" << object; |
1510 | 1.98M | if (!input->checkPosition(object.m_pos.begin())) { |
1511 | 1.13M | MWAW_DEBUG_MSG(("MsWrdParser::readObjectList: pb with ptr\n")); |
1512 | 1.13M | f << "#ptr=" << std::hex << object.m_pos.begin() << std::dec << ","; |
1513 | 1.13M | object.m_pos.setBegin(0); |
1514 | 1.13M | } |
1515 | | |
1516 | 1.98M | listObject.push_back(object); |
1517 | 1.98M | ascii().addPos(pos); |
1518 | 1.98M | ascii().addNote(f.str().c_str()); |
1519 | 1.98M | } |
1520 | | |
1521 | 7.02k | ascii().addPos(entry.end()); |
1522 | 7.02k | ascii().addNote("_"); |
1523 | 7.02k | return true; |
1524 | | |
1525 | 8.86k | } |
1526 | | |
1527 | | bool MsWrdParser::readObjectFlags(MsWrdEntry &entry) |
1528 | 6.91k | { |
1529 | 6.91k | if (entry.id() < 0 || entry.id() > 1) { |
1530 | 0 | MWAW_DEBUG_MSG(("MsWrdParser::readObjectFlags: unexpected entry id: %d\n", entry.id())); |
1531 | 0 | return false; |
1532 | 0 | } |
1533 | 6.91k | std::vector<MsWrdParserInternal::Object> &listObject = m_state->m_objectList[entry.id()]; |
1534 | 6.91k | auto numObject = static_cast<int>(listObject.size()); |
1535 | 6.91k | if (entry.length() < 4 || (entry.length()%6) != 4) { |
1536 | 2.30k | MWAW_DEBUG_MSG(("MsWrdParser::readObjectFlags: the zone size seems odd\n")); |
1537 | 2.30k | return false; |
1538 | 2.30k | } |
1539 | 4.61k | MWAWInputStreamPtr input = getInput(); |
1540 | 4.61k | long pos = entry.begin(); |
1541 | 4.61k | entry.setParsed(true); |
1542 | 4.61k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1543 | 4.61k | libmwaw::DebugStream f; |
1544 | 4.61k | f << "ObjectFlags[" << entry.id() << "]:"; |
1545 | 4.61k | auto N=int(entry.length()/6); |
1546 | 4.61k | if (N != numObject) { |
1547 | 3.00k | MWAW_DEBUG_MSG(("MsWrdParser::readObjectFlags: unexpected number of object\n")); |
1548 | 3.00k | } |
1549 | | |
1550 | 4.61k | f << "["; |
1551 | 1.81M | for (int i = 0; i < N+1; i++) { |
1552 | 1.80M | auto textPos = long(input->readULong(4)); |
1553 | 1.80M | if (i < numObject && textPos != listObject[size_t(i)].m_textPos && textPos != listObject[size_t(i)].m_textPos+1) |
1554 | 65.0k | f << "#"; |
1555 | 1.80M | f << std::hex << textPos << std::dec << ","; |
1556 | 1.80M | } |
1557 | 4.61k | f << "],"; |
1558 | 4.61k | ascii().addPos(pos); |
1559 | 4.61k | ascii().addNote(f.str().c_str()); |
1560 | | |
1561 | 1.80M | for (int i = 0; i < N; i++) { |
1562 | 1.80M | pos = input->tell(); |
1563 | 1.80M | int flags[2]; |
1564 | 3.60M | for (auto &flag : flags) flag = static_cast<int>(input->readULong(1)); |
1565 | 1.80M | f.str(""); |
1566 | 1.80M | f << "ObjectFlags-" << i << ":"; |
1567 | 1.80M | if (i < numObject) { |
1568 | 1.50M | for (int st = 0; st < 2; st++) listObject[size_t(i)].m_flags[st] = flags[st]; |
1569 | 501k | f << "Obj" << listObject[size_t(i)].m_id << ","; |
1570 | 501k | } |
1571 | | // indentical to ObjectList id0[low] ? |
1572 | 1.80M | if (flags[0] != 0x48) f << "fl0=" << std::hex << flags[0] << std::dec << ","; |
1573 | 1.80M | if (flags[1]) f << "fl1=" << std::hex << flags[1] << std::dec << ","; |
1574 | 1.80M | ascii().addPos(pos); |
1575 | 1.80M | ascii().addNote(f.str().c_str()); |
1576 | 1.80M | } |
1577 | | |
1578 | 4.61k | ascii().addPos(entry.end()); |
1579 | 4.61k | ascii().addNote("_"); |
1580 | 4.61k | return true; |
1581 | | |
1582 | 6.91k | } |
1583 | | |
1584 | | bool MsWrdParser::readObject(MsWrdParserInternal::Object &obj) |
1585 | 1.98M | { |
1586 | 1.98M | MWAWInputStreamPtr input = getInput(); |
1587 | 1.98M | libmwaw::DebugStream f; |
1588 | | |
1589 | 1.98M | long pos = obj.m_pos.begin(), beginPos = pos; |
1590 | 1.98M | if (!pos) return false; |
1591 | | |
1592 | 445k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1593 | 445k | auto sz = static_cast<int>(input->readULong(4)); |
1594 | | |
1595 | 445k | f << "Entries(ObjectData):Obj" << obj.m_id << ","; |
1596 | 445k | if (!input->checkPosition(pos+sz) || sz < 6) { |
1597 | 339k | MWAW_DEBUG_MSG(("MsWrdParser::readObject: pb finding object data sz\n")); |
1598 | 339k | f << "#"; |
1599 | 339k | ascii().addPos(beginPos); |
1600 | 339k | ascii().addNote(f.str().c_str()); |
1601 | 339k | return false; |
1602 | 339k | } |
1603 | 105k | obj.m_pos.setLength(sz); |
1604 | 105k | long endPos = obj.m_pos.end(); |
1605 | 105k | ascii().addPos(endPos); |
1606 | 105k | ascii().addNote("_"); |
1607 | | |
1608 | 105k | auto fSz = static_cast<int>(input->readULong(2)); |
1609 | 105k | if (fSz < 0 || fSz+6 > sz) { |
1610 | 12.7k | MWAW_DEBUG_MSG(("MsWrdParser::readObject: pb reading the name\n")); |
1611 | 12.7k | f << "#"; |
1612 | 12.7k | ascii().addPos(beginPos); |
1613 | 12.7k | ascii().addNote(f.str().c_str()); |
1614 | 12.7k | return false; |
1615 | 12.7k | } |
1616 | 93.1k | MsWrdEntry fileEntry = obj.getEntry(); |
1617 | 93.1k | fileEntry.setParsed(true); |
1618 | 93.1k | m_entryMap.insert |
1619 | 93.1k | (std::multimap<std::string, MsWrdEntry>::value_type(fileEntry.type(), fileEntry)); |
1620 | | |
1621 | 93.1k | long zoneEnd = pos+6+fSz; |
1622 | 93.1k | std::string name(""); // first equation, second "" or Equation Word? |
1623 | 86.5M | while (long(input->tell()) != zoneEnd) { |
1624 | 86.4M | auto c = static_cast<int>(input->readULong(1)); |
1625 | 86.4M | if (c == 0) { |
1626 | 36.0M | if (name.length()) f << name << ","; |
1627 | 36.0M | name = ""; |
1628 | 36.0M | continue; |
1629 | 36.0M | } |
1630 | 50.4M | name += char(c); |
1631 | 50.4M | } |
1632 | 93.1k | if (name.length()) f << name << ","; |
1633 | | |
1634 | 93.1k | pos = input->tell(); |
1635 | | // Equation Word? : often contains not other data |
1636 | 93.1k | if (pos==endPos) { |
1637 | 2.48k | ascii().addPos(beginPos); |
1638 | 2.48k | ascii().addNote(f.str().c_str()); |
1639 | 2.48k | return true; |
1640 | 2.48k | } |
1641 | | |
1642 | | // 0 or a small size c for annotation an equivalent of file type? |
1643 | 90.6k | fSz = static_cast<int>(input->readULong(1)); |
1644 | 90.6k | if (pos+fSz+1 > endPos) { |
1645 | 3.87k | MWAW_DEBUG_MSG(("MsWrdParser::readObject: pb reading the second field zone\n")); |
1646 | 3.87k | f << "#fSz=" << fSz; |
1647 | 3.87k | ascii().addPos(beginPos); |
1648 | 3.87k | ascii().addNote(f.str().c_str()); |
1649 | 3.87k | return false; |
1650 | 3.87k | } |
1651 | 86.7k | int val; |
1652 | 86.7k | bool isAnnotation=false; |
1653 | 86.7k | if (fSz==12) { // possible annotation |
1654 | 887 | f << "type=["; |
1655 | 4.43k | for (int i = 0; i < 4; i++) { // f0=f1=f2=0, f3=0x100 |
1656 | 3.54k | val = static_cast<int>(input->readLong(2)); |
1657 | 3.54k | if (val) f << "g0=" << std::hex << val << std::dec << ","; |
1658 | 3.54k | } |
1659 | 887 | std::string type(""); |
1660 | 4.43k | for (int i = 0; i < 4; i++) |
1661 | 3.54k | type += char(input->readULong(1)); |
1662 | 887 | f << type << "],"; |
1663 | 887 | isAnnotation=type=="ANOT"; |
1664 | 887 | } |
1665 | 85.8k | else if (fSz) { |
1666 | 22.2k | f << "##data2[sz]=" << fSz << ","; |
1667 | 22.2k | ascii().addDelimiter(input->tell(),'|'); |
1668 | 22.2k | input->seek(pos+fSz+1, librevenge::RVNG_SEEK_SET); |
1669 | 22.2k | ascii().addDelimiter(input->tell(),'|'); |
1670 | 22.2k | } |
1671 | 86.7k | pos = input->tell(); |
1672 | 86.7k | if (pos+2>endPos) { |
1673 | 2.61k | if (pos!= endPos) |
1674 | 1.48k | f << "###"; |
1675 | 2.61k | ascii().addPos(beginPos); |
1676 | 2.61k | ascii().addNote(f.str().c_str()); |
1677 | 2.61k | return true; |
1678 | 2.61k | } |
1679 | 84.1k | val = static_cast<int>(input->readLong(2)); |
1680 | 84.1k | if (val) f << "#f0=" << val << ","; |
1681 | | |
1682 | 84.1k | pos = input->tell(); |
1683 | 84.1k | if (pos+4>endPos) { |
1684 | 2.80k | if (pos!= endPos) |
1685 | 2.14k | f << "##"; |
1686 | 2.80k | ascii().addPos(beginPos); |
1687 | 2.80k | ascii().addNote(f.str().c_str()); |
1688 | 2.80k | return true; |
1689 | 2.80k | } |
1690 | 81.3k | auto dataSz = long(input->readULong(4)); |
1691 | 81.3k | pos = input->tell(); |
1692 | 81.3k | if (pos+dataSz > endPos) { |
1693 | 27.8k | MWAW_DEBUG_MSG(("MsWrdParser::readObject: pb reading the last field size zone\n")); |
1694 | 27.8k | f << "#fSz[last]=" << dataSz; |
1695 | 27.8k | ascii().addPos(beginPos); |
1696 | 27.8k | ascii().addNote(f.str().c_str()); |
1697 | 27.8k | return false; |
1698 | 27.8k | } |
1699 | 53.5k | if (isAnnotation && dataSz>9) { |
1700 | 0 | f << "annot=["; |
1701 | 0 | for (int i = 0; i < 3; i++) { // h0=1|2, h1,h2: big numbers |
1702 | 0 | val = static_cast<int>(input->readULong(2)); |
1703 | 0 | if (val) |
1704 | 0 | f << "h" << i << "=" << std::hex << val << std::dec << ","; |
1705 | 0 | } |
1706 | 0 | fSz = static_cast<int>(input->readULong(1)); |
1707 | 0 | bool ok=true; |
1708 | 0 | if (fSz+7 > dataSz) { |
1709 | 0 | MWAW_DEBUG_MSG(("MsWrdParser::readObject: can not read the annotation string\n")); |
1710 | 0 | f << "###"; |
1711 | 0 | ok = false; |
1712 | 0 | } |
1713 | 0 | else { |
1714 | 0 | std::string annotation(""); |
1715 | 0 | for (int i = 0; i < fSz; i++) |
1716 | 0 | annotation += char(input->readULong(1)); |
1717 | 0 | if (!annotation.empty()) |
1718 | 0 | f << "annot[inText]=" << annotation << ","; |
1719 | 0 | } |
1720 | |
|
1721 | 0 | if (ok) { |
1722 | 0 | val = static_cast<int>(input->readULong(1)); // always 0 |
1723 | 0 | if (val) |
1724 | 0 | f << "h3=" << std::hex << val << std::dec << ","; |
1725 | 0 | fSz = static_cast<int>(input->readULong(1)); |
1726 | 0 | } |
1727 | 0 | if (!ok) { |
1728 | 0 | } |
1729 | 0 | else if (fSz+9 > dataSz) { |
1730 | 0 | MWAW_DEBUG_MSG(("MsWrdParser::readObject: can not read the annotation comment\n")); |
1731 | 0 | f << "###"; |
1732 | 0 | } |
1733 | 0 | else { |
1734 | | // store the comment |
1735 | 0 | obj.m_annotation.setBegin(input->tell()); |
1736 | 0 | obj.m_annotation.setLength(fSz); |
1737 | 0 | std::string annotation(""); |
1738 | 0 | for (int i = 0; i < fSz; i++) |
1739 | 0 | annotation += char(input->readULong(1)); |
1740 | 0 | if (!annotation.empty()) |
1741 | 0 | f << "annot[comment]=" << annotation << ","; |
1742 | 0 | } |
1743 | 0 | } |
1744 | 53.5k | else if (dataSz) |
1745 | 44.8k | ascii().addDelimiter(pos, '|'); |
1746 | 53.5k | input->seek(pos+dataSz, librevenge::RVNG_SEEK_SET); |
1747 | | |
1748 | 53.5k | pos = input->tell(); |
1749 | 53.5k | ascii().addPos(beginPos); |
1750 | 53.5k | ascii().addNote(f.str().c_str()); |
1751 | 53.5k | if (pos != endPos) |
1752 | 15.5k | ascii().addDelimiter(pos, '#'); |
1753 | | |
1754 | 53.5k | return true; |
1755 | 81.3k | } |
1756 | | |
1757 | | //////////////////////////////////////////////////////////// |
1758 | | // check if a zone is a picture/read a picture |
1759 | | //////////////////////////////////////////////////////////// |
1760 | | bool MsWrdParser::checkPicturePos(long pos, int type) |
1761 | 160k | { |
1762 | 160k | MWAWInputStreamPtr input = getInput(); |
1763 | 160k | if (pos < 0x100 || !input->checkPosition(pos)) |
1764 | 69.4k | return false; |
1765 | | |
1766 | 91.0k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1767 | 91.0k | auto sz = long(input->readULong(4)); |
1768 | 91.0k | long endPos = pos+sz; |
1769 | 91.0k | if (sz < 14 || !input->checkPosition(sz+pos)) return false; |
1770 | 59.6k | auto num = static_cast<int>(input->readLong(1)); |
1771 | 59.6k | if (num < 0 || num > 4) return false; |
1772 | 54.3k | input->seek(pos+14, librevenge::RVNG_SEEK_SET); |
1773 | 94.0k | for (int n = 0; n < num; n++) { |
1774 | 43.7k | long actPos = input->tell(); |
1775 | 43.7k | auto pSz = long(input->readULong(4)); |
1776 | 43.7k | if (pSz+actPos > endPos) return false; |
1777 | 39.6k | input->seek(pSz+actPos, librevenge::RVNG_SEEK_SET); |
1778 | 39.6k | } |
1779 | 50.2k | if (input->tell() != endPos) |
1780 | 7.27k | return false; |
1781 | | |
1782 | 42.9k | static int id = 0; |
1783 | 42.9k | MsWrdEntry entry; |
1784 | 42.9k | entry.setBegin(pos); |
1785 | 42.9k | entry.setEnd(endPos); |
1786 | 42.9k | entry.setType("Picture"); |
1787 | 42.9k | entry.setPictType(type); |
1788 | 42.9k | entry.setId(id++); |
1789 | 42.9k | m_entryMap.insert |
1790 | 42.9k | (std::multimap<std::string, MsWrdEntry>::value_type(entry.type(), entry)); |
1791 | | |
1792 | 42.9k | return true; |
1793 | 50.2k | } |
1794 | | |
1795 | | bool MsWrdParser::readPicture(MsWrdEntry &entry) |
1796 | 42.9k | { |
1797 | 42.9k | if (m_state->m_picturesMap.find(entry.begin())!=m_state->m_picturesMap.end()) |
1798 | 5.11k | return true; |
1799 | 37.8k | if (entry.length() < 30 && entry.length() != 14) { |
1800 | 0 | MWAW_DEBUG_MSG(("MsWrdParser::readPicture: the zone seems too short\n")); |
1801 | 0 | return false; |
1802 | 0 | } |
1803 | 37.8k | MWAWInputStreamPtr input = getInput(); |
1804 | 37.8k | long pos = entry.begin(); |
1805 | 37.8k | entry.setParsed(true); |
1806 | 37.8k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1807 | 37.8k | libmwaw::DebugStream f; |
1808 | 37.8k | f << "Entries(Picture)[" << entry.pictType() << "-" << entry.id() << "]:"; |
1809 | 37.8k | auto sz = long(input->readULong(4)); |
1810 | 37.8k | if (sz > entry.length()) { |
1811 | 0 | MWAW_DEBUG_MSG(("MsWrdParser::readPicture: the zone size seems too big\n")); |
1812 | 0 | return false; |
1813 | 0 | } |
1814 | 37.8k | auto N = static_cast<int>(input->readULong(1)); |
1815 | 37.8k | f << "N=" << N << ","; |
1816 | 37.8k | MsWrdParserInternal::Picture pict; |
1817 | 37.8k | pict.m_flag = static_cast<int>(input->readULong(1)); // find 0 or 0x80 |
1818 | 37.8k | int dim[4]; |
1819 | 151k | for (auto &d : dim) d = static_cast<int>(input->readLong(2)); |
1820 | 37.8k | pict.m_dim=MWAWBox2i(MWAWVec2i(dim[1],dim[0]), MWAWVec2i(dim[3],dim[2])); |
1821 | 37.8k | f << pict; |
1822 | 37.8k | ascii().addPos(pos); |
1823 | 37.8k | ascii().addNote(f.str().c_str()); |
1824 | | |
1825 | 72.8k | for (int n=0; n < N; n++) { |
1826 | 37.4k | MsWrdParserInternal::Picture::Zone zone; |
1827 | 37.4k | pos = input->tell(); |
1828 | 37.4k | f.str(""); |
1829 | 37.4k | f << "Picture-" << n << "[" << entry.pictType() << "-" << entry.id() << "]:"; |
1830 | 37.4k | sz = long(input->readULong(4)); |
1831 | 37.4k | if (sz < 16 || sz+pos > entry.end()) { |
1832 | 2.48k | MWAW_DEBUG_MSG(("MsWrdParser::readPicture: pb with the picture size\n")); |
1833 | 2.48k | f << "#"; |
1834 | 2.48k | ascii().addPos(pos); |
1835 | 2.48k | ascii().addNote(f.str().c_str()); |
1836 | 2.48k | return false; |
1837 | 2.48k | } |
1838 | 139k | for (int i = 0; i < 3; ++i) zone.m_flags[i] = static_cast<int>(input->readULong((i==2) ? 2 : 1)); |
1839 | 139k | for (auto &d : dim) d = static_cast<int>(input->readLong(2)); |
1840 | 34.9k | zone.m_dim=MWAWBox2i(MWAWVec2i(dim[1],dim[0]), MWAWVec2i(dim[3],dim[2])); |
1841 | 34.9k | zone.m_pos.setBegin(pos+16); |
1842 | 34.9k | zone.m_pos.setLength(sz-16); |
1843 | 34.9k | f << zone; |
1844 | 34.9k | ascii().addPos(pos); |
1845 | 34.9k | ascii().addNote(f.str().c_str()); |
1846 | 34.9k | if (sz <= 16) |
1847 | 0 | continue; |
1848 | 34.9k | pict.m_picturesList.push_back(zone); |
1849 | | #ifdef DEBUG_WITH_FILES |
1850 | | ascii().skipZone(pos+16, pos+sz-1); |
1851 | | librevenge::RVNGBinaryData file; |
1852 | | input->seek(pos+16, librevenge::RVNG_SEEK_SET); |
1853 | | input->readDataBlock(sz-16, file); |
1854 | | static int volatile pictName = 0; |
1855 | | libmwaw::DebugStream f2; |
1856 | | f2 << "PICT-" << ++pictName << ".pct"; |
1857 | | libmwaw::Debug::dumpFile(file, f2.str().c_str()); |
1858 | | #endif |
1859 | | |
1860 | 34.9k | input->seek(pos+sz, librevenge::RVNG_SEEK_SET); |
1861 | 34.9k | } |
1862 | 35.3k | m_state->m_picturesMap[entry.begin()]=pict; |
1863 | 35.3k | pos = input->tell(); |
1864 | 35.3k | if (pos != entry.end()) |
1865 | 0 | ascii().addDelimiter(pos, '|'); |
1866 | 35.3k | ascii().addPos(entry.end()); |
1867 | 35.3k | ascii().addNote("_"); |
1868 | 35.3k | return true; |
1869 | 37.8k | } |
1870 | | |
1871 | | void MsWrdParser::sendPicture(long fPos, int cPos, MWAWPosition::AnchorTo anchor) |
1872 | 54.7k | { |
1873 | 54.7k | if (!getTextListener()) { |
1874 | 0 | MWAW_DEBUG_MSG(("MsWrdParser::sendPicture: listener is not set\n")); |
1875 | 0 | return; |
1876 | 0 | } |
1877 | 54.7k | if ((anchor == MWAWPosition::Char || anchor == MWAWPosition::CharBaseLine) && |
1878 | 42.3k | m_state->m_posToCommentMap.find(long(cPos-1))!=m_state->m_posToCommentMap.end()) { |
1879 | 0 | MWAWInputStreamPtr input = getInput(); |
1880 | 0 | std::shared_ptr<MWAWSubDocument> subdoc=std::make_shared<MsWrdParserInternal::SubDocument>(*this, input, m_state->m_posToCommentMap.find(long(cPos-1))->second, libmwaw::DOC_COMMENT_ANNOTATION); |
1881 | 0 | getTextListener()->insertComment(subdoc); |
1882 | 0 | return; |
1883 | 0 | } |
1884 | 54.7k | if (m_state->m_picturesMap.find(fPos)==m_state->m_picturesMap.end()) { |
1885 | 0 | MWAW_DEBUG_MSG(("MsWrdParser::sendPicture: can not find picture for pos %lx\n", static_cast<long unsigned int>(fPos))); |
1886 | 0 | return; |
1887 | 0 | } |
1888 | 54.7k | auto const &pict= m_state->m_picturesMap.find(fPos)->second; |
1889 | 54.7k | MWAWInputStreamPtr input = getInput(); |
1890 | 54.7k | if (pict.m_picturesList.size()!=1 && |
1891 | 24.6k | (anchor == MWAWPosition::Char || anchor == MWAWPosition::CharBaseLine)) { |
1892 | 12.3k | std::shared_ptr<MsWrdParserInternal::SubDocument> subdoc |
1893 | 12.3k | (new MsWrdParserInternal::SubDocument(*this, input, fPos, cPos)); |
1894 | 12.3k | MWAWPosition pictPos(MWAWVec2f(pict.m_dim.min()), MWAWVec2f(pict.m_dim.size()), librevenge::RVNG_POINT); |
1895 | 12.3k | pictPos.setRelativePosition(MWAWPosition::Char, |
1896 | 12.3k | MWAWPosition::XLeft, MWAWPosition::YTop); |
1897 | 12.3k | pictPos.m_wrapping = MWAWPosition::WBackground; |
1898 | 12.3k | getTextListener()->insertTextBox(pictPos, subdoc); |
1899 | 12.3k | return; |
1900 | 12.3k | } |
1901 | 42.3k | MWAWPosition basicPos(MWAWVec2f(0.,0.), MWAWVec2f(100.,100.), librevenge::RVNG_POINT); |
1902 | 42.3k | if (anchor != MWAWPosition::Page && anchor != MWAWPosition::Frame) { |
1903 | 30.0k | basicPos.setRelativePosition(anchor, MWAWPosition::XLeft, MWAWPosition::YCenter); |
1904 | 30.0k | basicPos.m_wrapping = MWAWPosition::WBackground; |
1905 | 30.0k | } |
1906 | 12.3k | else |
1907 | 12.3k | basicPos.setRelativePosition(anchor); |
1908 | | |
1909 | 42.3k | long actPos = input->tell(); |
1910 | 42.3k | MWAWBox2f naturalBox; |
1911 | 42.3k | int n=0; |
1912 | 42.3k | for (auto const &zone : pict.m_picturesList) { |
1913 | 30.0k | n++; |
1914 | 30.0k | if (!zone.m_pos.valid()) continue; |
1915 | 30.0k | MWAWPosition pos(basicPos); |
1916 | 30.0k | pos.setOrigin(pos.origin()+MWAWVec2f(zone.m_dim.min())); |
1917 | 30.0k | pos.setSize(MWAWVec2f(zone.m_dim.size())); |
1918 | | |
1919 | 30.0k | input->seek(zone.m_pos.begin(), librevenge::RVNG_SEEK_SET); |
1920 | 30.0k | MWAWPict::ReadResult res = MWAWPictData::check(input, static_cast<int>(zone.m_pos.length()), naturalBox); |
1921 | 30.0k | if (res == MWAWPict::MWAW_R_BAD) { |
1922 | 7 | MWAW_DEBUG_MSG(("MsWrdParser::sendPicture: can not find the picture %d\n", int(n-1))); |
1923 | 7 | continue; |
1924 | 7 | } |
1925 | | |
1926 | 30.0k | input->seek(zone.m_pos.begin(), librevenge::RVNG_SEEK_SET); |
1927 | 30.0k | std::shared_ptr<MWAWPict> thePict(MWAWPictData::get(input, static_cast<int>(zone.m_pos.length()))); |
1928 | 30.0k | if (!thePict) continue; |
1929 | 30.0k | MWAWEmbeddedObject picture; |
1930 | 30.0k | if (thePict->getBinary(picture)) |
1931 | 30.0k | getTextListener()->insertPicture(pos, picture); |
1932 | 30.0k | } |
1933 | 42.3k | input->seek(actPos, librevenge::RVNG_SEEK_SET); |
1934 | 42.3k | } |
1935 | | |
1936 | | //////////////////////////////////////////////////////////// |
1937 | | // read the print info |
1938 | | //////////////////////////////////////////////////////////// |
1939 | | bool MsWrdParser::readPrintInfo(MsWrdEntry &entry) |
1940 | 6.91k | { |
1941 | 6.91k | if (entry.length() < 0x78) { |
1942 | 3.21k | MWAW_DEBUG_MSG(("MsWrdParser::readPrintInfo: the zone seems to short\n")); |
1943 | 3.21k | return false; |
1944 | 3.21k | } |
1945 | 3.70k | MWAWInputStreamPtr input = getInput(); |
1946 | 3.70k | long pos = entry.begin(); |
1947 | 3.70k | entry.setParsed(true); |
1948 | 3.70k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1949 | 3.70k | libmwaw::DebugStream f; |
1950 | | // print info |
1951 | 3.70k | libmwaw::PrinterInfo info; |
1952 | 3.70k | if (!info.read(input)) return false; |
1953 | 1.83k | f << "PrintInfo:"<< info; |
1954 | | |
1955 | 1.83k | MWAWVec2i paperSize = info.paper().size(); |
1956 | 1.83k | MWAWVec2i pageSize = info.page().size(); |
1957 | 1.83k | if (pageSize.x() <= 0 || pageSize.y() <= 0 || |
1958 | 1.70k | paperSize.x() <= 0 || paperSize.y() <= 0) return false; |
1959 | | |
1960 | | // define margin from print info |
1961 | 1.64k | MWAWVec2i lTopMargin= -1 * info.paper().pos(0); |
1962 | 1.64k | MWAWVec2i rBotMargin=info.paper().size() - info.page().size(); |
1963 | | |
1964 | | // move margin left | top |
1965 | 1.64k | int decalX = lTopMargin.x() > 14 ? lTopMargin.x()-14 : 0; |
1966 | 1.64k | int decalY = lTopMargin.y() > 14 ? lTopMargin.y()-14 : 0; |
1967 | 1.64k | lTopMargin -= MWAWVec2i(decalX, decalY); |
1968 | 1.64k | rBotMargin += MWAWVec2i(decalX, decalY); |
1969 | | |
1970 | 1.64k | int leftMargin = lTopMargin.x(); |
1971 | 1.64k | int topMargin = lTopMargin.y(); |
1972 | | |
1973 | | // decrease right | bottom |
1974 | 1.64k | int rightMarg = rBotMargin.x() -50; |
1975 | 1.64k | if (rightMarg < 0) { |
1976 | 1.48k | leftMargin -= (-rightMarg); |
1977 | 1.48k | if (leftMargin < 0) leftMargin=0; |
1978 | 1.48k | rightMarg=0; |
1979 | 1.48k | } |
1980 | 1.64k | int botMarg = rBotMargin.y() -50; |
1981 | 1.64k | if (botMarg < 0) { |
1982 | 298 | topMargin -= (-botMarg); |
1983 | 298 | if (topMargin < 0) topMargin=0; |
1984 | 298 | botMarg=0; |
1985 | 298 | } |
1986 | | |
1987 | 1.64k | getPageSpan().setFormOrientation(MWAWPageSpan::PORTRAIT); |
1988 | 1.64k | getPageSpan().setMarginTop(topMargin/72.0); |
1989 | 1.64k | getPageSpan().setMarginBottom(botMarg/72.0); |
1990 | 1.64k | getPageSpan().setMarginLeft(leftMargin/72.0); |
1991 | 1.64k | getPageSpan().setMarginRight(rightMarg/72.0); |
1992 | 1.64k | getPageSpan().setFormLength(paperSize.y()/72.); |
1993 | 1.64k | getPageSpan().setFormWidth(paperSize.x()/72.); |
1994 | | |
1995 | 1.64k | ascii().addPos(pos); |
1996 | 1.64k | ascii().addNote(f.str().c_str()); |
1997 | | |
1998 | 1.64k | if (long(input->tell()) != entry.end()) |
1999 | 285 | ascii().addDelimiter(input->tell(), '|'); |
2000 | | |
2001 | 1.64k | ascii().addPos(entry.end()); |
2002 | 1.64k | ascii().addNote("_"); |
2003 | | |
2004 | 1.64k | return true; |
2005 | 1.83k | } |
2006 | | |
2007 | | // vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: |