/src/libmwaw/src/lib/SpringBoardParser.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 <cmath> |
35 | | #include <iomanip> |
36 | | #include <iostream> |
37 | | #include <limits> |
38 | | #include <sstream> |
39 | | #include <utility> |
40 | | |
41 | | #include <librevenge/librevenge.h> |
42 | | |
43 | | #include "MWAWGraphicListener.hxx" |
44 | | #include "MWAWGraphicShape.hxx" |
45 | | #include "MWAWGraphicStyle.hxx" |
46 | | #include "MWAWHeader.hxx" |
47 | | #include "MWAWParagraph.hxx" |
48 | | #include "MWAWPictBitmap.hxx" |
49 | | #include "MWAWPictData.hxx" |
50 | | #include "MWAWPosition.hxx" |
51 | | #include "MWAWSection.hxx" |
52 | | #include "MWAWSubDocument.hxx" |
53 | | |
54 | | #include "SpringBoardParser.hxx" |
55 | | |
56 | | /** Internal: the structures of a SpringBoardParser */ |
57 | | namespace SpringBoardParserInternal |
58 | | { |
59 | | //! Internal: a structure used to store the frame property in SpringBoardParserInternal |
60 | | struct Frame { |
61 | | //! constructor |
62 | | Frame() |
63 | 0 | : m_type(-1) |
64 | 0 | , m_style(MWAWGraphicStyle::emptyStyle()) |
65 | 0 | , m_numSubZones(0) |
66 | 0 | , m_numColumns(1) |
67 | 0 | , m_columnBoxes() |
68 | 0 | { |
69 | 0 | } |
70 | | //! the frame type: 0: layout, 1: text, 2: graphic |
71 | | int m_type; |
72 | | //! the frame style |
73 | | MWAWGraphicStyle m_style; |
74 | | //! the number of sub zone (for a text frame) |
75 | | int m_numSubZones; |
76 | | //! the external and the internal box |
77 | | MWAWBox2i m_boxes[2]; |
78 | | //! the number of columns: for a text frame |
79 | | int m_numColumns; |
80 | | //! the child box: one by column for text and layout |
81 | | std::vector<MWAWBox2i> m_columnBoxes; |
82 | | }; |
83 | | |
84 | | //! Internal: a structure used to store a link in SpringBoardParserInternal |
85 | | struct Link { |
86 | | //! constructor |
87 | | Link() |
88 | 0 | : m_font() |
89 | 0 | { |
90 | 0 | for (auto &lnk : m_links) |
91 | 0 | lnk=std::make_pair(-1, -1); |
92 | 0 | } |
93 | | //! returns true if the link stores somme text |
94 | | bool hasText() const |
95 | 0 | { |
96 | 0 | for (auto const &entry : m_texts) { |
97 | 0 | if (entry.valid()) return true; |
98 | 0 | } |
99 | 0 | return false; |
100 | 0 | } |
101 | | //! the font |
102 | | MWAWFont m_font; |
103 | | //! the top and bottom text |
104 | | MWAWEntry m_texts[2]; |
105 | | //! the next and previous link |
106 | | std::pair<int, int> m_links[2]; |
107 | | }; |
108 | | //! Internal: a structure used to store the shape data in SpringBoardParserInternal |
109 | | struct Shape { |
110 | | //! a paragraph contained in a SpringBoardParserInternal::Shape |
111 | | struct Paragraph { |
112 | | //! constructor |
113 | | Paragraph() |
114 | 0 | : m_numChars(0) |
115 | 0 | , m_firstChar(0) |
116 | 0 | , m_newColumn(false) |
117 | 0 | , m_numCharStyles(0) |
118 | 0 | , m_textZoneId(-1) |
119 | 0 | , m_paragraphStyle(-1) |
120 | 0 | , m_charEntry() |
121 | 0 | { |
122 | 0 | } |
123 | | //! the number of character |
124 | | int m_numChars; |
125 | | //! the first character |
126 | | int m_firstChar; |
127 | | //! a flag to know if we need to change column: USEME |
128 | | bool m_newColumn; |
129 | | //! the number of character style |
130 | | int m_numCharStyles; |
131 | | //! the text zone id |
132 | | int m_textZoneId; |
133 | | //! the paragraph style |
134 | | int m_paragraphStyle; |
135 | | //! the character style zone |
136 | | MWAWEntry m_charEntry; |
137 | | }; |
138 | | //! constructor |
139 | | Shape() |
140 | 0 | : m_type(0) |
141 | 0 | , m_paragraphs() |
142 | 0 | , m_pictEntry() |
143 | 0 | { |
144 | 0 | } |
145 | | //! the shape type: 0: layout, 1: text, 2: graphic |
146 | | int m_type; |
147 | | //! the list of paragraph |
148 | | std::vector<Paragraph> m_paragraphs; |
149 | | //! the picture entry: graphic only |
150 | | MWAWEntry m_pictEntry; |
151 | | }; |
152 | | |
153 | | //////////////////////////////////////// |
154 | | //! Internal: the Header/Footer of a SpringBoardParser |
155 | | struct HeaderFooter { |
156 | | //! constructor |
157 | | HeaderFooter() |
158 | 0 | : m_position(0) |
159 | 0 | , m_type(0) |
160 | 0 | , m_pageNumber(0) |
161 | 0 | , m_font() |
162 | 0 | { |
163 | 0 | } |
164 | | //! the header/footer position 1: TC, TR, TL, BC, BR, BL, FacingT, FacingB |
165 | | int m_position; |
166 | | //! the numbering type: 0: numeric, 1/2: small/big roman, 3/4: small/big alpha, 5-7: full minu,MAJU,Title, 8: none |
167 | | int m_type; |
168 | | //! the first page numbering |
169 | | int m_pageNumber; |
170 | | //! the font |
171 | | MWAWFont m_font; |
172 | | //! the prefix/postfix zones string |
173 | | MWAWEntry m_zones[2]; |
174 | | }; |
175 | | |
176 | | //////////////////////////////////////// |
177 | | //! Internal: the state of a SpringBoardParser |
178 | | struct State { |
179 | | //! constructor |
180 | | State() |
181 | 290 | : m_numPages(1) |
182 | 290 | , m_entriesListMap() |
183 | 290 | , m_entries2ListMap() |
184 | 290 | , m_pageIdToDimensionMap() |
185 | 290 | , m_pageIdToHeaderFooterMap() |
186 | 290 | , m_idToFrameMap() |
187 | 290 | , m_idToShapeMap() |
188 | 290 | , m_idToLinkMap() |
189 | 290 | , m_idToTextEntriesMap() |
190 | 290 | , m_idToParagraphMap() |
191 | | |
192 | 290 | , m_parsedZonesMap() |
193 | 290 | { |
194 | 290 | } |
195 | | |
196 | | //! returns the name of a data zone |
197 | | std::string getDataZoneName(int id) const |
198 | 0 | { |
199 | 0 | char const *wh[]= {"Doc", "Page", "FramStyle", "FramLink", nullptr, |
200 | 0 | nullptr, nullptr, nullptr, "ParaStyle", "Text" |
201 | 0 | }; |
202 | 0 | if (id>=0 && id<10 && wh[id]) |
203 | 0 | return wh[id]; |
204 | 0 | std::stringstream s; |
205 | 0 | s << "List" << id; |
206 | 0 | return s.str(); |
207 | 0 | } |
208 | | //! the number of pages |
209 | | int m_numPages; |
210 | | //! a map zone id to list's entry |
211 | | std::map<int, MWAWEntry> m_entriesListMap; |
212 | | //! a map id to the last zone entries |
213 | | std::map<int, MWAWEntry> m_entries2ListMap; |
214 | | //! the map pageId to page dimension |
215 | | std::map<int, MWAWBox2i> m_pageIdToDimensionMap; |
216 | | //! the map pageId to header footer |
217 | | std::map<int, HeaderFooter> m_pageIdToHeaderFooterMap; |
218 | | //! the map (page,id) to frame map |
219 | | std::map<std::pair<int, int>, Frame> m_idToFrameMap; |
220 | | //! the map (page,id) to shape map |
221 | | std::map<std::pair<int, int>, Shape> m_idToShapeMap; |
222 | | //! the map (page,id) to link map |
223 | | std::map<std::pair<int, int>, Link> m_idToLinkMap; |
224 | | //! the map id to text entries |
225 | | std::map<int, MWAWEntry> m_idToTextEntriesMap; |
226 | | //! the map id to paragraph |
227 | | std::map<int, MWAWParagraph> m_idToParagraphMap; |
228 | | |
229 | | //! the list of parsed zone |
230 | | std::map<long, long> m_parsedZonesMap; |
231 | | }; |
232 | | |
233 | | //////////////////////////////////////// |
234 | | //! Internal: the subdocument of a SpringBoardParser |
235 | | class SubDocument final : public MWAWSubDocument |
236 | | { |
237 | | public: |
238 | | //! constructor knowning the header/footer id |
239 | | SubDocument(SpringBoardParser &pars, MWAWInputStreamPtr const &input, int hfId) |
240 | 0 | : MWAWSubDocument(&pars, input, MWAWEntry()) |
241 | 0 | , m_hfId(hfId) |
242 | 0 | , m_linkId({-1, -1}) |
243 | 0 | , m_linkTop(true) |
244 | 0 | , m_pageId({-1, -1}) |
245 | 0 | , m_minParagraph(-1) |
246 | 0 | , m_maxParagraph(-1) |
247 | 0 | { |
248 | 0 | } |
249 | | |
250 | | //! constructor corresponding to a layout/textbox shape |
251 | | SubDocument(SpringBoardParser &pars, MWAWInputStreamPtr const &input, std::pair<int, int> const &pageId, |
252 | | std::pair<int, int> const ¶s= {-1, -1}) |
253 | 0 | : MWAWSubDocument(&pars, input, MWAWEntry()) |
254 | 0 | , m_hfId(-1) |
255 | 0 | , m_linkId({-1, -1}) |
256 | 0 | , m_linkTop(true) |
257 | 0 | , m_pageId(pageId) |
258 | 0 | , m_minParagraph(paras.first) |
259 | 0 | , m_maxParagraph(paras.second) |
260 | 0 | { |
261 | 0 | } |
262 | | //! constructor corresponding to a link shape |
263 | | SubDocument(SpringBoardParser &pars, MWAWInputStreamPtr const &input, std::pair<int, int> const &linkId, |
264 | | bool isTop) |
265 | 0 | : MWAWSubDocument(&pars, input, MWAWEntry()) |
266 | 0 | , m_hfId(-1) |
267 | 0 | , m_linkId(linkId) |
268 | 0 | , m_linkTop(isTop) |
269 | 0 | , m_pageId({-1, -1}) |
270 | 0 | , m_minParagraph(-1) |
271 | 0 | , m_maxParagraph(-1) |
272 | 0 | { |
273 | 0 | } |
274 | | //! destructor |
275 | 0 | ~SubDocument() final {} |
276 | | |
277 | | //! operator!= |
278 | | bool operator!=(MWAWSubDocument const &doc) const final |
279 | 0 | { |
280 | 0 | if (MWAWSubDocument::operator!=(doc)) return true; |
281 | 0 | auto const *sDoc = dynamic_cast<SubDocument const *>(&doc); |
282 | 0 | if (!sDoc) return true; |
283 | 0 | if (sDoc->m_hfId != m_hfId) return true; |
284 | 0 | if (sDoc->m_linkId != m_linkId) return true; |
285 | 0 | if (sDoc->m_linkTop != m_linkTop) return true; |
286 | 0 | if (sDoc->m_pageId != m_pageId) return true; |
287 | 0 | if (sDoc->m_minParagraph != m_minParagraph) return true; |
288 | 0 | if (sDoc->m_maxParagraph != m_maxParagraph) return true; |
289 | 0 | return false; |
290 | 0 | } |
291 | | |
292 | | //! the parser function |
293 | | void parse(MWAWListenerPtr &listener, libmwaw::SubDocumentType type) final; |
294 | | |
295 | | protected: |
296 | | //! the header/footer zone id |
297 | | int m_hfId; |
298 | | //! the text link id |
299 | | std::pair<int, int> m_linkId; |
300 | | //! a flag to know if we need to send the top or the bottom text |
301 | | bool m_linkTop; |
302 | | //! the text page id |
303 | | std::pair<int, int> m_pageId; |
304 | | //! the minimum and maximum paragraph |
305 | | int m_minParagraph, m_maxParagraph; |
306 | | private: |
307 | | SubDocument(SubDocument const &orig) = delete; |
308 | | SubDocument &operator=(SubDocument const &orig) = delete; |
309 | | }; |
310 | | |
311 | | void SubDocument::parse(MWAWListenerPtr &listener, libmwaw::SubDocumentType) |
312 | 0 | { |
313 | 0 | if (!listener || !listener->canWriteText()) { |
314 | 0 | MWAW_DEBUG_MSG(("SpringBoardParserInternal::SubDocument::parse: no listener\n")); |
315 | 0 | return; |
316 | 0 | } |
317 | 0 | auto parser=dynamic_cast<SpringBoardParser *>(m_parser); |
318 | 0 | if (!parser) { |
319 | 0 | MWAW_DEBUG_MSG(("SpringBoardParserInternal::SubDocument::parse: no parser\n")); |
320 | 0 | return; |
321 | 0 | } |
322 | 0 | long pos = m_input->tell(); |
323 | 0 | if (m_hfId>=0) |
324 | 0 | parser->sendHeaderFooter(m_hfId); |
325 | 0 | else if (m_linkId.first != -1) |
326 | 0 | parser->sendLinkShape(m_linkId, m_linkTop); |
327 | 0 | else |
328 | 0 | parser->sendTextShape(m_pageId, m_minParagraph, m_maxParagraph); |
329 | 0 | m_input->seek(pos, librevenge::RVNG_SEEK_SET); |
330 | 0 | } |
331 | | |
332 | | |
333 | | } |
334 | | |
335 | | //////////////////////////////////////////////////////////// |
336 | | // constructor/destructor, ... |
337 | | //////////////////////////////////////////////////////////// |
338 | | SpringBoardParser::SpringBoardParser(MWAWInputStreamPtr const &input, MWAWRSRCParserPtr const &rsrcParser, MWAWHeader *header) |
339 | 138 | : MWAWGraphicParser(input, rsrcParser, header) |
340 | 138 | , m_state(new SpringBoardParserInternal::State) |
341 | 138 | { |
342 | 138 | setAsciiName("main-1"); |
343 | | |
344 | 138 | getPageSpan().setMargins(0.1); |
345 | 138 | } |
346 | | |
347 | | SpringBoardParser::~SpringBoardParser() |
348 | 138 | { |
349 | 138 | } |
350 | | |
351 | | bool SpringBoardParser::isPositionValid(long pos) const |
352 | 0 | { |
353 | 0 | MWAWEntry entry; |
354 | 0 | entry.setBegin(pos); |
355 | 0 | entry.setLength(0); |
356 | 0 | return isEntryValid(entry); |
357 | 0 | } |
358 | | |
359 | | bool SpringBoardParser::isEntryValid(MWAWEntry const &entry) const |
360 | 7 | { |
361 | 7 | auto input=const_cast<SpringBoardParser *>(this)->getInput(); |
362 | 7 | if (!input || entry.begin()<0x80 || !input->checkPosition(entry.end())) |
363 | 6 | return false; |
364 | 1 | auto it=m_state->m_parsedZonesMap.upper_bound(entry.begin()); |
365 | 1 | if (it!=m_state->m_parsedZonesMap.begin()) |
366 | 0 | --it; |
367 | 1 | while (it!=m_state->m_parsedZonesMap.end()) { |
368 | 0 | if (it->first>=entry.end()) |
369 | 0 | return true; |
370 | 0 | if (it->second>entry.begin()) |
371 | 0 | return false; |
372 | 0 | ++it; |
373 | 0 | } |
374 | 1 | return true; |
375 | 1 | } |
376 | | |
377 | | //////////////////////////////////////////////////////////// |
378 | | // the parser |
379 | | //////////////////////////////////////////////////////////// |
380 | | void SpringBoardParser::parse(librevenge::RVNGDrawingInterface *docInterface) |
381 | 14 | { |
382 | 14 | if (!getInput().get() || !checkHeader(nullptr)) throw(libmwaw::ParseException()); |
383 | 14 | bool ok = false; |
384 | 14 | try { |
385 | | // create the asciiFile |
386 | 14 | ascii().setStream(getInput()); |
387 | 14 | ascii().open(asciiName()); |
388 | 14 | checkHeader(nullptr); |
389 | 14 | ok = createZones(); |
390 | 14 | if (ok) { |
391 | 0 | createDocument(docInterface); |
392 | |
|
393 | 0 | auto listener=getGraphicListener(); |
394 | 0 | if (!listener) |
395 | 0 | ok=false; |
396 | 0 | else { |
397 | 0 | for (int pg=0; pg<m_state->m_numPages; ++pg) { |
398 | 0 | if (pg) |
399 | 0 | listener->insertBreak(MWAWListener::PageBreak); |
400 | 0 | auto fIt=m_state->m_idToFrameMap.lower_bound(std::make_pair(pg+1, -1)); |
401 | 0 | while (fIt!=m_state->m_idToFrameMap.end() && fIt->first.first==pg+1) |
402 | 0 | sendFrame(fIt++->first); |
403 | 0 | } |
404 | 0 | } |
405 | 0 | } |
406 | 14 | ascii().reset(); |
407 | 14 | } |
408 | 14 | catch (...) { |
409 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::parse: exception catched when parsing\n")); |
410 | 0 | ok = false; |
411 | 0 | } |
412 | | |
413 | 14 | resetGraphicListener(); |
414 | 14 | if (!ok) throw(libmwaw::ParseException()); |
415 | 14 | } |
416 | | |
417 | | //////////////////////////////////////////////////////////// |
418 | | // create the document |
419 | | //////////////////////////////////////////////////////////// |
420 | | void SpringBoardParser::createDocument(librevenge::RVNGDrawingInterface *documentInterface) |
421 | 0 | { |
422 | 0 | if (!documentInterface) return; |
423 | 0 | if (getGraphicListener()) { |
424 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::createDocument: listener already exist\n")); |
425 | 0 | return; |
426 | 0 | } |
427 | | |
428 | | // create the page list |
429 | 0 | int numPages=std::max<int>(1,m_state->m_numPages); |
430 | 0 | auto fIt=m_state->m_idToFrameMap.rbegin(); |
431 | 0 | if (fIt!=m_state->m_idToFrameMap.rend()) { |
432 | 0 | if (fIt->first.first>numPages) { |
433 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::createDocument: oops, find some frame which are on unknown page\n")); |
434 | 0 | } |
435 | 0 | else if (fIt->first.first<numPages && fIt->first.first>1) |
436 | 0 | numPages=fIt->first.first; |
437 | 0 | } |
438 | | // FIXME: we must also look if we find some page numbering with pageId>numPages |
439 | 0 | m_state->m_numPages=numPages; |
440 | 0 | std::vector<MWAWPageSpan> pageList; |
441 | 0 | MWAWPageSpan ps; |
442 | 0 | for (int pg=1; pg<=numPages; ++pg) { |
443 | 0 | ps=getPageSpan(); |
444 | 0 | auto dimIt=m_state->m_pageIdToDimensionMap.find(pg); |
445 | 0 | if (dimIt!=m_state->m_pageIdToDimensionMap.end()) { |
446 | 0 | auto const &sz=dimIt->second[1]; |
447 | 0 | if (sz[0]>0 && sz[1]>0) { |
448 | 0 | ps.setFormWidth(double(sz[0])/72); |
449 | 0 | ps.setFormLength(double(sz[1])/72); |
450 | 0 | } |
451 | 0 | } |
452 | | // FIXME: look like a header/footer in page N is also replicated as header/footer for page N+1, N+2, ... |
453 | 0 | auto hfIt=m_state->m_pageIdToHeaderFooterMap.find(pg); |
454 | 0 | if (hfIt!=m_state->m_pageIdToHeaderFooterMap.end()) { |
455 | 0 | auto const &hf=hfIt->second; |
456 | 0 | if (hf.m_type>0 && hf.m_type<=8) { |
457 | 0 | MWAWHeaderFooter hF((hf.m_type<=3 || hf.m_type==7) ? MWAWHeaderFooter::HEADER : MWAWHeaderFooter::FOOTER, |
458 | 0 | MWAWHeaderFooter::ALL); |
459 | 0 | auto subdoc=std::make_shared<SpringBoardParserInternal::SubDocument>(*this, getInput(), pg); |
460 | 0 | hF.m_subDocument=subdoc; |
461 | 0 | ps.setHeaderFooter(hF); |
462 | 0 | } |
463 | 0 | else { |
464 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::createDocument: oops, find unknown hf type=%d\n", hf.m_type)); |
465 | 0 | } |
466 | 0 | } |
467 | 0 | pageList.push_back(ps); |
468 | 0 | } |
469 | |
|
470 | 0 | MWAWGraphicListenerPtr listen(new MWAWGraphicListener(*getParserState(), pageList, documentInterface)); |
471 | 0 | setGraphicListener(listen); |
472 | 0 | listen->startDocument(); |
473 | 0 | } |
474 | | |
475 | | |
476 | | //////////////////////////////////////////////////////////// |
477 | | // |
478 | | // Intermediate level |
479 | | // |
480 | | //////////////////////////////////////////////////////////// |
481 | | bool SpringBoardParser::createZones() |
482 | 14 | { |
483 | 14 | MWAWInputStreamPtr input = getInput(); |
484 | 14 | input->seek(4, librevenge::RVNG_SEEK_SET); |
485 | | |
486 | 14 | libmwaw::DebugStream f; |
487 | 14 | f << "limits=["; |
488 | 28 | for (int i=0; i<2; ++i) { |
489 | 22 | long ptr=long(input->readULong(4)); |
490 | 22 | f << std::hex << ptr << std::dec << ","; |
491 | 22 | if (ptr<0x80 || !input->checkPosition(ptr)) { |
492 | 8 | MWAW_DEBUG_MSG(("SpringBoardParser::createZones: find bad limits\n")); |
493 | 8 | f << "###"; |
494 | 8 | ascii().addPos(0); |
495 | 8 | ascii().addNote(f.str().c_str()); |
496 | 8 | return false; |
497 | 8 | } |
498 | 14 | ascii().addPos(ptr); |
499 | 14 | ascii().addNote(i==0 ? "[A]" : "[B]"); |
500 | 14 | } |
501 | 6 | f << "],"; |
502 | | |
503 | 6 | int val; |
504 | 6 | MWAWEntry entry; |
505 | 6 | entry.setBegin(long(input->readULong(4))); |
506 | 6 | entry.setLength(long(input->readULong(4))); |
507 | 6 | if (entry.valid()) { |
508 | 2 | f << "pagNumb=" << std::hex << entry.begin() << "<->" << entry.end() << std::dec << ","; |
509 | 2 | if (!isEntryValid(entry)) { |
510 | 1 | MWAW_DEBUG_MSG(("SpringBoardParser::createZones: find bad entries for page numbering\n")); |
511 | 1 | f << "###"; |
512 | 1 | return false; |
513 | 1 | } |
514 | 1 | m_state->m_parsedZonesMap[entry.begin()]=entry.end(); |
515 | 1 | long actPos=input->tell(); |
516 | 1 | parsePageNumbering(entry); |
517 | 1 | input->seek(actPos, librevenge::RVNG_SEEK_SET); |
518 | 1 | } |
519 | 23 | for (int i=0; i<10; ++i) { |
520 | 23 | entry.setBegin(long(input->readULong(4))); |
521 | 23 | entry.setLength(long(input->readULong(2))); |
522 | 23 | if (!entry.valid()) |
523 | 18 | continue; |
524 | 5 | char const *wh[]= { |
525 | 5 | "doc", "page", "framstyle", "framlink", nullptr, |
526 | 5 | nullptr, nullptr, nullptr, "parastyle", "text" |
527 | 5 | }; |
528 | 5 | if (wh[i]) |
529 | 4 | f << wh[i] << "=" << std::hex << entry.begin() << "<->" << entry.end() << std::dec << ","; |
530 | 1 | else |
531 | 1 | f << "list" << i << "=" << std::hex << entry.begin() << "<->" << entry.end() << std::dec << ","; |
532 | 5 | if (!isEntryValid(entry)) { |
533 | 5 | MWAW_DEBUG_MSG(("SpringBoardParser::createZones: find bad entries %d\n", i)); |
534 | 5 | f << "###"; |
535 | 5 | ascii().addPos(0); |
536 | 5 | ascii().addNote(f.str().c_str()); |
537 | 5 | return false; |
538 | 5 | } |
539 | 0 | m_state->m_parsedZonesMap[entry.begin()]=entry.end(); |
540 | 0 | m_state->m_entriesListMap[i]=entry; |
541 | 0 | } |
542 | 0 | for (int i=0; i<3; ++i) { |
543 | 0 | val=int(input->readLong(2)); |
544 | 0 | if (val) |
545 | 0 | f << "f" << i+4 << "=" << val << ","; |
546 | 0 | } |
547 | 0 | for (int i=0; i<3; ++i) { |
548 | 0 | entry.setBegin(long(input->readULong(4))); |
549 | 0 | entry.setLength(long(input->readULong(4))); |
550 | 0 | if (!entry.valid()) |
551 | 0 | continue; |
552 | 0 | f << (i==0 ? "shape" : i==1 ? "txtPos" : "frame") << "=" << std::hex << entry.begin() << "<->" << entry.end() << std::dec << ","; |
553 | 0 | if (!isEntryValid(entry)) { |
554 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::createZones: find bad entries %d\n", i)); |
555 | 0 | f << "###"; |
556 | 0 | ascii().addPos(0); |
557 | 0 | ascii().addNote(f.str().c_str()); |
558 | 0 | return false; |
559 | 0 | } |
560 | 0 | m_state->m_parsedZonesMap[entry.begin()]=entry.end(); |
561 | 0 | m_state->m_entries2ListMap[i]=entry; |
562 | 0 | } |
563 | 0 | for (int i=0; i<3; ++i) { |
564 | 0 | val=int(input->readLong(2)); |
565 | 0 | if (val) |
566 | 0 | f << "g" << i << "=" << val << ","; |
567 | 0 | } |
568 | 0 | val=int(input->readULong(4)); // 0 or 68ad08 |
569 | 0 | if (val) |
570 | 0 | f << "unkn=" << std::hex << val << std::dec << ","; |
571 | 0 | for (int i=0; i<3; ++i) { // g3=0|8 |
572 | 0 | val=int(input->readLong(2)); |
573 | 0 | if (val) |
574 | 0 | f << "g" << i+3 << "=" << val << ","; |
575 | 0 | } |
576 | 0 | f << "num[shapes]=" << input->readLong(2) << ","; |
577 | 0 | ascii().addPos(0); |
578 | 0 | ascii().addNote(f.str().c_str()); |
579 | |
|
580 | 0 | for (auto const &it : m_state->m_entriesListMap) |
581 | 0 | parseDataList(it.first, it.second); |
582 | |
|
583 | 0 | for (auto const &it : m_state->m_entries2ListMap) |
584 | 0 | parseLastZone(it.first, it.second); |
585 | 0 | return true; |
586 | 0 | } |
587 | | |
588 | | bool SpringBoardParser::readFont(MWAWFont &font, int szFieldSize) |
589 | 0 | { |
590 | 0 | font=MWAWFont(); |
591 | 0 | MWAWInputStreamPtr input = getInput(); |
592 | 0 | if (!input) |
593 | 0 | return false; |
594 | 0 | long pos=input->tell(); |
595 | 0 | if ((szFieldSize!=1 && szFieldSize!=2) || !input->checkPosition(pos+4+szFieldSize)) { |
596 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::readFont: the zone seems bad\n")); |
597 | 0 | return false; |
598 | 0 | } |
599 | | |
600 | 0 | libmwaw::DebugStream f; |
601 | 0 | font.setId(int(input->readULong(2))); |
602 | 0 | int val=int(input->readULong(2)); |
603 | 0 | uint32_t flags=0; |
604 | 0 | if (val&0x1) flags |= MWAWFont::boldBit; |
605 | 0 | if (val&0x2) flags |= MWAWFont::italicBit; |
606 | 0 | if (val&0x4) { |
607 | 0 | font.setUnderlineStyle(MWAWFont::Line::Simple); |
608 | 0 | if (val&0x80) |
609 | 0 | f << "underline[char],"; |
610 | 0 | if (val&0x100) |
611 | 0 | f << "underline[word],"; |
612 | | // &0x8000 all |
613 | 0 | val&=0x7e7f; |
614 | 0 | } |
615 | 0 | if (val&0x8) flags |= MWAWFont::embossBit; |
616 | 0 | if (val&0x10) flags |= MWAWFont::shadowBit; |
617 | 0 | if (val&0x20) |
618 | 0 | font.set(MWAWFont::Script::super100()); |
619 | 0 | if (val&0x40) |
620 | 0 | font.set(MWAWFont::Script::sub100()); |
621 | 0 | if ((val&0x600)==0x600) { |
622 | 0 | flags |= MWAWFont::reverseVideoBit; |
623 | 0 | f << "pat[inverse]=" << ((val&0x7800)>>11) << ","; // FIXME use pattern |
624 | 0 | val &= 0x81ff; |
625 | 0 | } |
626 | 0 | if (val&0xff80) f << "font[fl]=#" << std::hex << (val&0xff80) << std::dec << ","; |
627 | 0 | font.setSize(float(input->readLong(szFieldSize))); |
628 | 0 | font.setFlags(flags); |
629 | 0 | font.m_extra=f.str(); |
630 | 0 | return true; |
631 | 0 | } |
632 | | |
633 | | bool SpringBoardParser::parsePageNumbering(MWAWEntry const &entry) |
634 | 1 | { |
635 | 1 | MWAWInputStreamPtr input = getInput(); |
636 | 1 | if (!input) |
637 | 0 | return false; |
638 | 1 | if (!entry.valid() || (entry.length()%98)!=0 || !input->checkPosition(entry.end())) { |
639 | 1 | MWAW_DEBUG_MSG(("SpringBoardParser::parsePageNumbering: find unvalid entry\n")); |
640 | 1 | return false; |
641 | 1 | } |
642 | 0 | ascii().addPos(entry.end()); |
643 | 0 | ascii().addNote("_"); |
644 | |
|
645 | 0 | libmwaw::DebugStream f; |
646 | 0 | f << "Entries(PagNumbering):"; |
647 | 0 | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
648 | 0 | ascii().addPos(entry.begin()); |
649 | 0 | ascii().addNote(f.str().c_str()); |
650 | 0 | int N=int(entry.length()/98); |
651 | 0 | int val; |
652 | 0 | for (int i=0; i<N; ++i) { |
653 | 0 | long pos=input->tell(); |
654 | 0 | f.str(""); |
655 | 0 | f << "PagNumbering-" << i << ":"; |
656 | 0 | int pg=int(input->readLong(2)); |
657 | 0 | f << "page=" << pg << ","; |
658 | 0 | SpringBoardParserInternal::HeaderFooter hf; |
659 | 0 | hf.m_type=int(input->readLong(2)); |
660 | 0 | if (hf.m_type) f << "number[format]=" << hf.m_type << ","; |
661 | 0 | hf.m_pageNumber=int(input->readLong(2)); |
662 | 0 | if (hf.m_pageNumber!=pg) f << "page[number]=" << hf.m_pageNumber << ","; |
663 | 0 | hf.m_position=int(input->readLong(2)); |
664 | 0 | f << "pos=" << hf.m_position << ","; |
665 | |
|
666 | 0 | readFont(hf.m_font, 2); |
667 | 0 | f << hf.m_font.getDebugString(getFontConverter()) << ","; |
668 | 0 | for (int j=0; j<2; ++j) { |
669 | 0 | long actPos=input->tell(); |
670 | 0 | int cLen=int(input->readULong(1)); |
671 | 0 | if (cLen>40) { |
672 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::parsePageNumbering: can not read a string\n")); |
673 | 0 | f << "###cLen" << j << "=" << cLen << ","; |
674 | 0 | cLen=0; |
675 | 0 | } |
676 | 0 | hf.m_zones[j].setBegin(actPos+1); |
677 | 0 | hf.m_zones[j].setLength(cLen); |
678 | 0 | std::string text; |
679 | 0 | for (int c=0; c<cLen; ++c) |
680 | 0 | text+=char(input->readULong(1)); |
681 | 0 | f << text << ","; |
682 | 0 | input->seek(actPos+40, librevenge::RVNG_SEEK_SET); |
683 | 0 | } |
684 | 0 | for (int j=0; j<2; ++j) { |
685 | 0 | val=int(input->readLong(2)); |
686 | 0 | if (val!=(j==0 ? 50 : 90)) |
687 | 0 | f << "from[" << (j==0 ? "bottom" : "right") << "]=" << val << ","; |
688 | 0 | } |
689 | 0 | if (m_state->m_pageIdToHeaderFooterMap.count(pg)) { |
690 | 0 | f << "###dup"; |
691 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::parsePageNumbering: an header/footer already exists for the page %d\n", pg)); |
692 | 0 | } |
693 | 0 | else |
694 | 0 | m_state->m_pageIdToHeaderFooterMap[pg]=hf; |
695 | 0 | ascii().addPos(pos); |
696 | 0 | ascii().addNote(f.str().c_str()); |
697 | 0 | input->seek(pos+98, librevenge::RVNG_SEEK_SET); |
698 | 0 | } |
699 | 0 | return true; |
700 | 1 | } |
701 | | |
702 | | bool SpringBoardParser::parseDataList(int id, MWAWEntry const &entry) |
703 | 0 | { |
704 | 0 | MWAWInputStreamPtr input = getInput(); |
705 | 0 | if (!input) |
706 | 0 | return false; |
707 | 0 | if (id<0 || id>=10 || !entry.valid() || !input->checkPosition(entry.end())) { |
708 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::parseDataList: find unvalid entry for id=%d\n", id)); |
709 | 0 | return false; |
710 | 0 | } |
711 | 0 | ascii().addPos(entry.end()); |
712 | 0 | ascii().addNote("_"); |
713 | |
|
714 | 0 | libmwaw::DebugStream f; |
715 | 0 | std::string const what=m_state->getDataZoneName(id); |
716 | 0 | f << "Entries(" << what << "):"; |
717 | 0 | if ((entry.length()%16)!=0) { |
718 | 0 | f << "###"; |
719 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::parseDataList: find unexpected size for zone %s\n", what.c_str())); |
720 | 0 | ascii().addPos(entry.begin()); |
721 | 0 | ascii().addNote(f.str().c_str()); |
722 | 0 | return false; |
723 | 0 | } |
724 | | |
725 | 0 | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
726 | 0 | int num=int(entry.length()/16); |
727 | 0 | std::map<int, std::pair<MWAWVec2i, MWAWEntry> > listZones; |
728 | 0 | for (int st=0; st<num; ++st) { |
729 | 0 | long pos=input->tell(); |
730 | 0 | f.str(""); |
731 | 0 | if (st==0) |
732 | 0 | f << "Entries(" << what << "):"; |
733 | 0 | else |
734 | 0 | f << what << "[st=" << st << "]:"; |
735 | 0 | int firstId=int(input->readLong(4)); |
736 | 0 | if (firstId) |
737 | 0 | f << "id[first]=" << firstId << ","; |
738 | 0 | MWAWEntry data; |
739 | 0 | data.setBegin(long(input->readULong(4))); |
740 | 0 | data.setLength(long(input->readULong(4))); |
741 | 0 | f << "zone=" << std::hex << data.begin() << "x" << data.end() << std::dec << ","; |
742 | 0 | int nextId=int(input->readLong(4)); |
743 | 0 | f << "next[id]=" << nextId << ","; |
744 | 0 | if (!isEntryValid(data)) { |
745 | 0 | f << "###"; |
746 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::parseDataList: find unexpected zone for zone %s\n", what.c_str())); |
747 | 0 | return false; |
748 | 0 | } |
749 | 0 | m_state->m_parsedZonesMap[entry.begin()]=entry.end(); |
750 | 0 | listZones[st]=std::make_pair(MWAWVec2i(firstId,nextId), data); |
751 | 0 | ascii().addPos(pos); |
752 | 0 | ascii().addNote(f.str().c_str()); |
753 | 0 | } |
754 | 0 | for (auto const &it : listZones) { |
755 | 0 | MWAWEntry data; |
756 | 0 | MWAWVec2i indices; |
757 | 0 | std::tie(indices,data)=it.second; |
758 | 0 | if (id==8) |
759 | 0 | parseParagraphStyle(data, indices); |
760 | 0 | else |
761 | 0 | parseData(id, data, indices); |
762 | 0 | } |
763 | 0 | return true; |
764 | 0 | } |
765 | | |
766 | | bool SpringBoardParser::parseData(int id, MWAWEntry const &entry, MWAWVec2i const &indices) |
767 | 0 | { |
768 | 0 | MWAWInputStreamPtr input = getInput(); |
769 | 0 | if (!input) |
770 | 0 | return false; |
771 | 0 | if (id<0 || id>=10 || !entry.valid() || !input->checkPosition(entry.end())) { |
772 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::parseData: find unvalid entry for id=%d\n", id)); |
773 | 0 | return false; |
774 | 0 | } |
775 | | |
776 | 0 | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
777 | 0 | long pos=input->tell(); |
778 | 0 | ascii().addPos(entry.end()); |
779 | 0 | ascii().addNote("_"); |
780 | |
|
781 | 0 | libmwaw::DebugStream f; |
782 | 0 | std::string const what=m_state->getDataZoneName(id); |
783 | 0 | int const expectedSize[]= {6, 10, 26, 182, -1, |
784 | 0 | -1, -1, -1, -1, 512 |
785 | 0 | }; |
786 | 0 | if (expectedSize[id]<=0) { |
787 | 0 | f << what << "[header,index=" << indices << "]:"; |
788 | 0 | ascii().addPos(pos); |
789 | 0 | ascii().addNote(f.str().c_str()); |
790 | 0 | return true; |
791 | 0 | } |
792 | 0 | if (indices[1]<indices[0] || indices[1]-indices[0]<entry.length()/expectedSize[id]) { |
793 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::parseData: find unexpected length for data zone %s\n", what.c_str())); |
794 | 0 | ascii().addPos(pos); |
795 | 0 | ascii().addNote("###"); |
796 | 0 | return false; |
797 | 0 | } |
798 | 0 | for (int i=indices[0]; i<indices[1]; ++i) { |
799 | 0 | pos=input->tell(); |
800 | 0 | f.str(""); |
801 | 0 | f << what << "-dt" << i << "]:"; |
802 | 0 | int val; |
803 | 0 | switch (id) { |
804 | 0 | case 0: { // Doc |
805 | 0 | for (int j=0; j<3; ++j) { |
806 | 0 | val=int(input->readLong(2)); |
807 | 0 | if (val==1) |
808 | 0 | continue; |
809 | 0 | if (j==2) { |
810 | 0 | m_state->m_numPages=val; |
811 | 0 | f << "num[pages]=" << val << ","; |
812 | 0 | } |
813 | 0 | else |
814 | 0 | f << "num" << j << "=" << val << ","; |
815 | 0 | } |
816 | 0 | break; |
817 | 0 | } |
818 | 0 | case 1: { // Page |
819 | 0 | for (int j=0; j<5; ++j) { |
820 | 0 | val=int(input->readLong(2)); |
821 | 0 | int const expected[]= {0,0,0,0, -1}; |
822 | 0 | if (val==expected[j]) |
823 | 0 | continue; |
824 | 0 | if (j==0) |
825 | 0 | f << "page=" << val << ","; |
826 | 0 | else if (j==3) |
827 | 0 | f << "first[shape]=" << val << ","; |
828 | 0 | else |
829 | 0 | f << "f" << j << "=" << val << ","; |
830 | 0 | } |
831 | 0 | break; |
832 | 0 | } |
833 | 0 | case 2: { // FrameStyle |
834 | 0 | SpringBoardParserInternal::Frame frame; |
835 | 0 | int pageId=int(input->readLong(1)); |
836 | 0 | f << "page[id]=" << pageId << ","; |
837 | 0 | val=int(input->readULong(1)); |
838 | 0 | frame.m_type=val&3; |
839 | 0 | f << "type=" << frame.m_type << ","; |
840 | 0 | if (val&0x80) f << "crop[image],"; |
841 | 0 | val&=0x7c; |
842 | | // checkme what means type+0x10: multicolumn? |
843 | 0 | f << "fl=" << std::hex << val << std::dec << ","; // 0: layout, 1: text, 2: graphic |
844 | 0 | val=int(input->readULong(1)); |
845 | 0 | if (val==0x40) |
846 | 0 | f << "crop[image],"; // checkme |
847 | 0 | else if (val) |
848 | 0 | f << "f0=" << val << ","; |
849 | 0 | auto &style=frame.m_style; |
850 | 0 | int bStyle=int(input->readLong(1)); |
851 | 0 | f << "border[style]=" << bStyle << ","; // 0: single, 1: double, 2: 2,1,1, 3: 1,1,2, 4: 1,1,2,1,1, 5: dashed, 6; dotted, 7: big dotted |
852 | 0 | style.m_lineWidth=float(input->readLong(1)); |
853 | 0 | if (style.m_lineWidth>0) { |
854 | 0 | f << "line[width]=" << style.m_lineWidth << ","; |
855 | 0 | if (bStyle>=1 && bStyle<=4) |
856 | 0 | style.m_lineWidth*=2; |
857 | 0 | else if (bStyle==5) |
858 | 0 | style.m_lineDashWidth= {10,10}; |
859 | 0 | else if (bStyle>=6 && bStyle<=7) |
860 | 0 | style.m_lineDashWidth= {2,2}; |
861 | 0 | } |
862 | 0 | val=int(input->readLong(1)); |
863 | 0 | if (val!=1) f << "line[pat]=" << val << ","; |
864 | 0 | int page=int(input->readLong(2)); |
865 | 0 | f << "page=" << page << ","; |
866 | 0 | for (int j=0; j<5; ++j) { // f5=0|b, f6=0|12, f7=0|100 |
867 | 0 | val=int(input->readLong(2)); |
868 | 0 | if (!val) |
869 | 0 | continue; |
870 | 0 | if (j==1) { |
871 | 0 | frame.m_numSubZones=val; |
872 | 0 | f << "num[subZones]=" << val << ","; |
873 | 0 | } |
874 | 0 | else if (j==4) |
875 | 0 | f << "gray[scale]=" << val << ","; |
876 | 0 | else |
877 | 0 | f << "f" << j+3 << "=" << val << ","; |
878 | 0 | } |
879 | 0 | for (int j=0; j<2; ++j) { |
880 | 0 | val=int(input->readLong(2)); |
881 | 0 | if (val==-1) |
882 | 0 | continue; |
883 | 0 | f << "g" << j << "=" << val << ","; |
884 | 0 | } |
885 | 0 | val=int(input->readLong(4)); |
886 | 0 | if (val!=-1) f << "next=F" << val << ","; |
887 | 0 | auto index=std::make_pair(page, pageId); |
888 | 0 | if (m_state->m_idToFrameMap.count(index)==0) |
889 | 0 | m_state->m_idToFrameMap[index]=frame; |
890 | 0 | else { |
891 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::parseData: find a duplicated frame with id=%dx%d\n", page, pageId)); |
892 | 0 | f << "###dup,"; |
893 | 0 | } |
894 | 0 | break; |
895 | 0 | } |
896 | 0 | case 3: { // frame header/footer link |
897 | 0 | SpringBoardParserInternal::Link link; |
898 | 0 | f << "unkn=" << std::hex << input->readLong(2) << std::dec << ","; |
899 | 0 | val=int(input->readULong(2)); |
900 | 0 | if (val!=1) |
901 | 0 | f << "f0=" << val << ","; |
902 | 0 | readFont(link.m_font, 2); |
903 | 0 | f << link.m_font.getDebugString(getFontConverter()) << ","; |
904 | |
|
905 | 0 | for (int j=0; j<2; ++j) { |
906 | 0 | long actPos=input->tell(); |
907 | 0 | int cLen=int(input->readULong(1)); |
908 | 0 | if (cLen>80) { |
909 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::parseData: can not read a string\n")); |
910 | 0 | f << "###cLen" << j << "=" << cLen << ","; |
911 | 0 | cLen=0; |
912 | 0 | } |
913 | 0 | link.m_texts[j].setBegin(actPos+1); |
914 | 0 | link.m_texts[j].setLength(cLen); |
915 | 0 | std::string text; |
916 | 0 | for (int c=0; c<cLen; ++c) text+=char(input->readULong(1)); |
917 | 0 | if (!text.empty()) |
918 | 0 | f << (j==0 ? "top" : "bottom") << "[text]=" << text << ","; |
919 | 0 | input->seek(actPos+80, librevenge::RVNG_SEEK_SET); |
920 | 0 | } |
921 | 0 | std::pair<int, int> index; |
922 | 0 | for (int j=0; j<3; ++j) { |
923 | 0 | int pageId[2]; |
924 | 0 | for (auto &w : pageId) w=int(input->readLong(2)); |
925 | 0 | if (pageId[0]==-1 && pageId[1]==-1) continue; |
926 | 0 | char const *wh[]= {"id", "prev[id]", "next[id]"}; |
927 | 0 | if (j==0) |
928 | 0 | index=std::make_pair(pageId[0], pageId[1]); |
929 | 0 | else |
930 | 0 | link.m_links[j-1]=std::make_pair(pageId[0], pageId[1]); |
931 | 0 | f << wh[j] << "=" << MWAWVec2i(pageId[0], pageId[1]) << ","; |
932 | 0 | } |
933 | 0 | if (m_state->m_idToLinkMap.count(index)==0) |
934 | 0 | m_state->m_idToLinkMap[index]=link; |
935 | 0 | else { |
936 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::parseData: find a duplicated link with id=%dx%d\n", index.first, index.second)); |
937 | 0 | f << "###dup,"; |
938 | 0 | } |
939 | 0 | break; |
940 | 0 | } |
941 | | // 8: paragraph style, already done |
942 | 0 | case 9: { // Text |
943 | 0 | if (m_state->m_idToTextEntriesMap.count(i)) { |
944 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::parseData: a text entry with id=%d already exists\n", i)); |
945 | 0 | } |
946 | 0 | else { |
947 | 0 | MWAWEntry textEntry; |
948 | 0 | textEntry.setBegin(pos); |
949 | 0 | textEntry.setLength(512); |
950 | 0 | m_state->m_idToTextEntriesMap[i]=textEntry; |
951 | 0 | } |
952 | 0 | std::string text; |
953 | 0 | for (int j=0; j<512; ++j) { |
954 | 0 | char c=char(input->readULong(1)); |
955 | 0 | if (!c) |
956 | 0 | break; |
957 | 0 | text+=c; |
958 | 0 | } |
959 | 0 | f << text << ","; |
960 | 0 | break; |
961 | 0 | } |
962 | 0 | default: |
963 | 0 | break; |
964 | 0 | } |
965 | 0 | input->seek(pos+expectedSize[id], librevenge::RVNG_SEEK_SET); |
966 | 0 | ascii().addPos(pos); |
967 | 0 | ascii().addNote(f.str().c_str()); |
968 | 0 | } |
969 | 0 | return true; |
970 | 0 | } |
971 | | |
972 | | bool SpringBoardParser::parseParagraphStyle(MWAWEntry const &entry, MWAWVec2i const &indices) |
973 | 0 | { |
974 | 0 | MWAWInputStreamPtr input = getInput(); |
975 | 0 | if (!input) |
976 | 0 | return false; |
977 | 0 | int const N=indices[1]-indices[0]; |
978 | 0 | if (!entry.valid() || !input->checkPosition(entry.end()) || N<0 || entry.length()<4*N) { |
979 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::parseParagraphStyle: find invalid entry\n")); |
980 | 0 | return false; |
981 | 0 | } |
982 | 0 | ascii().addPos(entry.end()); |
983 | 0 | ascii().addNote("_"); |
984 | |
|
985 | 0 | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
986 | 0 | long pos=input->tell(); |
987 | 0 | libmwaw::DebugStream f; |
988 | 0 | f << "ParaStyle[" << N << "]:zones=["; |
989 | 0 | std::map<int, long> ptrs; |
990 | 0 | for (int i=indices[0]; i<indices[1]; ++i) { |
991 | 0 | long ptr=long(input->readULong(4)); |
992 | 0 | f << std::hex << ptr << std::dec << ","; |
993 | 0 | if (ptr>=entry.begin()+4*N && ptr+16<=entry.end()) |
994 | 0 | ptrs[i]=ptr; |
995 | 0 | else { |
996 | 0 | f << "###"; |
997 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::parseParagraphStyle: find bad ptr\n")); |
998 | 0 | } |
999 | 0 | } |
1000 | 0 | f << "],"; |
1001 | 0 | ascii().addPos(pos); |
1002 | 0 | ascii().addNote(f.str().c_str()); |
1003 | 0 | int val; |
1004 | 0 | for (auto const &it : ptrs) { |
1005 | 0 | f.str(""); |
1006 | 0 | f << "ParaStyle-P" << it.first << ":"; |
1007 | 0 | MWAWParagraph para; |
1008 | 0 | for (int i=0; i<4; ++i) { |
1009 | 0 | val=int(input->readULong(1)); |
1010 | 0 | if (val==(i==3 ? 1 : 0)) continue; |
1011 | 0 | if (i==0) { |
1012 | 0 | switch (val) { |
1013 | 0 | case 1: |
1014 | 0 | para.m_justify = MWAWParagraph::JustificationCenter; |
1015 | 0 | break; |
1016 | 0 | case 2: |
1017 | 0 | para.m_justify = MWAWParagraph::JustificationRight; |
1018 | 0 | break; |
1019 | 0 | case 3: |
1020 | 0 | para.m_justify = MWAWParagraph::JustificationFull; |
1021 | 0 | break; |
1022 | 0 | default: |
1023 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::parseParagraphStyle: find unknown justification\n")); |
1024 | 0 | f << "###align=" << val << ","; // 1: center, 2:right, 3: justify? |
1025 | 0 | break; |
1026 | 0 | } |
1027 | 0 | } |
1028 | 0 | else if (i==1 || i==2) |
1029 | 0 | para.m_spacings[i]=12*float(val)/72; // in percent, so asume font size=12 |
1030 | 0 | else |
1031 | 0 | f << "f0=" << val << ","; |
1032 | 0 | } |
1033 | 0 | para.m_marginsUnit=librevenge::RVNG_POINT; |
1034 | 0 | for (int i=0; i<5; ++i) { |
1035 | 0 | val=int(input->readULong(2)); |
1036 | 0 | int const expected[]= {1,0,0,0,0}; |
1037 | 0 | if (val==expected[i]) |
1038 | 0 | continue; |
1039 | 0 | if (i==1) { |
1040 | 0 | if (val&0x8000) |
1041 | 0 | para.m_spacings[2]=12*float(val&0x7fff)/72; |
1042 | 0 | else |
1043 | 0 | para.setInterline(1+float(val), librevenge::RVNG_PERCENT); |
1044 | 0 | } |
1045 | 0 | else if (i>=2 && i<=4) |
1046 | 0 | para.m_margins[i-2]=float(val); |
1047 | 0 | else |
1048 | 0 | f << "f" << i+1 << "=" << val << ","; // 8: related to char style |
1049 | 0 | } |
1050 | 0 | int nTabs=int(input->readULong(2)); |
1051 | 0 | if (nTabs) { |
1052 | 0 | if (pos+16+4*nTabs>entry.end()) { |
1053 | 0 | f << "###nTabs=" << nTabs << ","; |
1054 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::parseParagraphStyle: the number of tabs seems bad\n")); |
1055 | 0 | nTabs=0; |
1056 | 0 | } |
1057 | 0 | for (int i=0; i<nTabs; ++i) { |
1058 | 0 | MWAWTabStop tab; |
1059 | 0 | char c=char(input->readLong(1)); |
1060 | 0 | if (c>=0x20 && c<0x7f) |
1061 | 0 | tab.m_leaderCharacter=uint16_t(c); |
1062 | 0 | else { |
1063 | 0 | static bool first=true; |
1064 | 0 | if (first) { |
1065 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::parseParagraphStyle: find unexpected leader characters\n")); |
1066 | 0 | first=false; |
1067 | 0 | } |
1068 | 0 | f << "###tab" << i << "=" << int(c) << ","; |
1069 | 0 | } |
1070 | 0 | input->seek(1, librevenge::RVNG_SEEK_CUR); |
1071 | 0 | tab.m_position=float(input->readLong(2))/72; |
1072 | 0 | } |
1073 | 0 | } |
1074 | 0 | f << para; |
1075 | 0 | if (m_state->m_idToParagraphMap.count(it.first)) { |
1076 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::parseParagraphStyle: oops a paragraph with id=%d already exists\n", it.first)); |
1077 | 0 | f << "###dup"; |
1078 | 0 | } |
1079 | 0 | else |
1080 | 0 | m_state->m_idToParagraphMap[it.first]=para; |
1081 | 0 | ascii().addPos(it.second); |
1082 | 0 | ascii().addNote(f.str().c_str()); |
1083 | 0 | } |
1084 | 0 | return true; |
1085 | 0 | } |
1086 | | |
1087 | | bool SpringBoardParser::parseLastZone(int id, MWAWEntry const &entry) |
1088 | 0 | { |
1089 | 0 | MWAWInputStreamPtr input = getInput(); |
1090 | 0 | if (!input) |
1091 | 0 | return false; |
1092 | 0 | if (id<0 || id>=3 || !entry.valid() || !input->checkPosition(entry.end())) { |
1093 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::parseLastZone: find invalid entry for id=%d\n", id)); |
1094 | 0 | return false; |
1095 | 0 | } |
1096 | 0 | ascii().addPos(entry.end()); |
1097 | 0 | ascii().addNote("_"); |
1098 | |
|
1099 | 0 | libmwaw::DebugStream f, f2; |
1100 | 0 | char const *wh[]= {"Shape", "TxtPos", "Frame"}; |
1101 | 0 | std::string const what(wh[id]); |
1102 | 0 | f << "Entries(" << what << "):"; |
1103 | 0 | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
1104 | 0 | switch (id) { |
1105 | 0 | case 0: { |
1106 | 0 | if ((entry.length()%8)!=0) { |
1107 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::parseLastZone: unexpected size\n")); |
1108 | 0 | f << "###"; |
1109 | 0 | break; |
1110 | 0 | } |
1111 | 0 | int N=int(entry.length()/8); |
1112 | 0 | std::map<std::pair<int, int>, long> idToPtrs; |
1113 | 0 | for (int i=0; i<N; ++i) { |
1114 | 0 | long pos=input->tell(); |
1115 | 0 | f2.str(""); |
1116 | 0 | f2 << what << "-" << i << ":"; |
1117 | 0 | long beg=long(input->readULong(4)); |
1118 | 0 | f2 << "pos=" << std::hex << beg << std::dec << ","; |
1119 | 0 | int pg=int(input->readLong(2)); |
1120 | 0 | int pgId=int(input->readLong(2)); |
1121 | 0 | if (!isPositionValid(beg) || !input->checkPosition(beg+4)) { |
1122 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::parseLastZone: a shape position seems bad\n")); |
1123 | 0 | f2 << "###"; |
1124 | 0 | } |
1125 | 0 | else |
1126 | 0 | idToPtrs[std::make_pair(pg,pgId)]=beg; |
1127 | 0 | f2 << "page=" << pg << ","; |
1128 | 0 | f2 << "id=" << pgId << ","; |
1129 | 0 | ascii().addPos(pos); |
1130 | 0 | ascii().addNote(f2.str().c_str()); |
1131 | 0 | } |
1132 | 0 | for (auto const &it : idToPtrs) |
1133 | 0 | parseShape(it.second, it.first); |
1134 | 0 | break; |
1135 | 0 | } |
1136 | 0 | case 1: { // checkme maybe link |
1137 | 0 | if ((entry.length()%6)!=0) { |
1138 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::parseLastZone: unexpected size\n")); |
1139 | 0 | f << "###"; |
1140 | 0 | break; |
1141 | 0 | } |
1142 | 0 | int N=int(entry.length()/6); |
1143 | 0 | f << "unkn=["; |
1144 | 0 | for (int i=0; i<N; ++i) { |
1145 | 0 | int val=int(input->readLong(4)); |
1146 | 0 | f << "last[char]=" << input->readLong(2); |
1147 | 0 | if (val!=-1) |
1148 | 0 | f << ":" << val; |
1149 | 0 | f << ","; |
1150 | 0 | } |
1151 | 0 | f << "],"; |
1152 | 0 | break; |
1153 | 0 | } |
1154 | 0 | case 2: { // a list of pages |
1155 | 0 | f << "list,"; |
1156 | 0 | if (entry.length()<2) { |
1157 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::parseLastZone: unexpected size\n")); |
1158 | 0 | f << "###"; |
1159 | 0 | break; |
1160 | 0 | } |
1161 | 0 | int N=int(input->readLong(2)); |
1162 | 0 | f << "N=" << N << ","; |
1163 | 0 | if (2+8*N>entry.length()) { |
1164 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::parseLastZone: unexpected N\n")); |
1165 | 0 | f << "###"; |
1166 | 0 | break; |
1167 | 0 | } |
1168 | 0 | std::map<int, long> positions; |
1169 | 0 | for (int i=0; i<N; ++i) { |
1170 | 0 | long pos=input->tell(); |
1171 | 0 | f2.str(""); |
1172 | 0 | f2 << what << "-" << i << "[list]:"; |
1173 | 0 | int pg=int(input->readLong(2)); |
1174 | 0 | f2 << "page=" << pg << ","; |
1175 | 0 | int val=int(input->readLong(2)); |
1176 | 0 | if (val!=pg) f2 << "page2=" << val << ","; |
1177 | 0 | long beg=long(input->readULong(4)); |
1178 | 0 | f2 << "pos=" << std::hex << beg << std::dec << ","; |
1179 | 0 | if (beg<entry.begin() || beg>=entry.end()) { |
1180 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::parseLastZone: a position seems bad\n")); |
1181 | 0 | f2 << "###"; |
1182 | 0 | } |
1183 | 0 | else |
1184 | 0 | positions[pg]=beg; |
1185 | 0 | ascii().addPos(pos); |
1186 | 0 | ascii().addNote(f2.str().c_str()); |
1187 | 0 | } |
1188 | 0 | for (auto const &it : positions) |
1189 | 0 | parseFrames(it.first, it.second); |
1190 | 0 | break; |
1191 | 0 | } |
1192 | 0 | default: |
1193 | 0 | break; |
1194 | 0 | } |
1195 | 0 | ascii().addPos(entry.begin()); |
1196 | 0 | ascii().addNote(f.str().c_str()); |
1197 | 0 | return true; |
1198 | 0 | } |
1199 | | |
1200 | | bool SpringBoardParser::parseShape(long begPos, std::pair<int, int> const &pageId) |
1201 | 0 | { |
1202 | 0 | MWAWInputStreamPtr input = getInput(); |
1203 | 0 | if (!input) |
1204 | 0 | return false; |
1205 | 0 | if (begPos<0x80 || !input->checkPosition(begPos+4)) { |
1206 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::parseShape: the begin position seems bad\n")); |
1207 | 0 | return false; |
1208 | 0 | } |
1209 | 0 | input->seek(begPos, librevenge::RVNG_SEEK_SET); |
1210 | 0 | int type=-1; |
1211 | 0 | auto const fIt=m_state->m_idToFrameMap.find(pageId); |
1212 | 0 | if (fIt==m_state->m_idToFrameMap.end()) { |
1213 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::parseShape: can not find the shape %d-%d\n", pageId.first, pageId.second)); |
1214 | 0 | } |
1215 | 0 | else |
1216 | 0 | type=fIt->second.m_type; |
1217 | 0 | SpringBoardParserInternal::Shape shape; |
1218 | 0 | shape.m_type=type; |
1219 | |
|
1220 | 0 | libmwaw::DebugStream f; |
1221 | 0 | f << "Shape-" << pageId.first << "x" << pageId.second << "[type=" << type << "]:"; |
1222 | 0 | input->seek(begPos, librevenge::RVNG_SEEK_SET); |
1223 | 0 | bool asciiUpdated=false; |
1224 | 0 | switch (type) { |
1225 | 0 | case 0: |
1226 | 0 | case 1: { |
1227 | 0 | int N=int(input->readULong(4)); |
1228 | 0 | f << "N=" << N << ","; |
1229 | 0 | if (N<0 || N+1>(input->size()-begPos)/4 || !isPositionValid(begPos+4+4*N)) { |
1230 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::parseShape: can not read the number of shapes\n")); |
1231 | 0 | f << "###"; |
1232 | 0 | N=0; |
1233 | 0 | } |
1234 | 0 | std::vector<long> listPtrs; |
1235 | 0 | for (int i=0; i<N; ++i) listPtrs.push_back(long(input->readULong(4))); |
1236 | 0 | ascii().addPos(begPos); |
1237 | 0 | ascii().addNote(f.str().c_str()); |
1238 | 0 | asciiUpdated=true; |
1239 | |
|
1240 | 0 | for (long ptr : listPtrs) { |
1241 | 0 | if (!isPositionValid(ptr) || !input->checkPosition(ptr+24)) { |
1242 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::parseShape: a text pointer seems bad\n")); |
1243 | 0 | if (ptr>0) |
1244 | 0 | break; |
1245 | 0 | continue; |
1246 | 0 | } |
1247 | 0 | f.str(""); |
1248 | 0 | f << "Shape-" << pageId.first << "x" << pageId.second << ":text,"; |
1249 | 0 | SpringBoardParserInternal::Shape::Paragraph para; |
1250 | 0 | input->seek(ptr, librevenge::RVNG_SEEK_SET); |
1251 | 0 | int val=int(input->readULong(2)); |
1252 | 0 | if (val&0x8000) { |
1253 | 0 | para.m_newColumn=true; |
1254 | 0 | f << "new[column],"; |
1255 | 0 | val &= 0x7fff; |
1256 | 0 | } |
1257 | 0 | if (val) |
1258 | 0 | f << "fl=" << std::hex << val << std::dec << ","; |
1259 | 0 | para.m_numChars=int(input->readULong(2)); |
1260 | 0 | f << "num[char]=" << para.m_numChars << ","; |
1261 | 0 | for (int i=0; i<2; ++i) { |
1262 | 0 | val=int(input->readLong(2)); |
1263 | 0 | if (!val) continue; |
1264 | 0 | if (i==0) { |
1265 | 0 | para.m_firstChar=val; |
1266 | 0 | f << "first[char]=" << val << ","; |
1267 | 0 | } |
1268 | 0 | else |
1269 | 0 | f << "y[pos]=" << val << ","; |
1270 | 0 | } |
1271 | 0 | val=int(input->readLong(4)); |
1272 | 0 | if (val!=ptr) f << "ptr=" << std::hex << val << std::dec << ","; |
1273 | 0 | para.m_numCharStyles=int(input->readLong(4)); |
1274 | 0 | f << "num[style]=" << para.m_numCharStyles << ","; |
1275 | 0 | para.m_paragraphStyle=int(input->readLong(4)); |
1276 | 0 | f << "para[style]=" << para.m_paragraphStyle << ","; |
1277 | 0 | para.m_textZoneId=int(input->readLong(4)); |
1278 | 0 | if (para.m_textZoneId!=-1) |
1279 | 0 | f << "text[id]=" << para.m_textZoneId << ","; |
1280 | 0 | if (ptr+24+10*para.m_numCharStyles<ptr+24 || (input->size()-24-ptr)/10<para.m_numCharStyles || |
1281 | 0 | !input->checkPosition(ptr+24+10*para.m_numCharStyles)) { |
1282 | 0 | f << "###"; |
1283 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::parseShape: the number of style seems bad\n")); |
1284 | 0 | para.m_numCharStyles=0; |
1285 | 0 | } |
1286 | 0 | para.m_charEntry.setBegin(input->tell()); |
1287 | 0 | para.m_charEntry.setLength(10*para.m_numCharStyles); |
1288 | 0 | shape.m_paragraphs.push_back(para); |
1289 | 0 | ascii().addPos(ptr); |
1290 | 0 | ascii().addNote(f.str().c_str()); |
1291 | 0 | } |
1292 | 0 | break; |
1293 | 0 | } |
1294 | 0 | case 2: { |
1295 | 0 | int val=int(input->readULong(4)); |
1296 | 0 | if (val) |
1297 | 0 | f << "f0=" << val << ","; |
1298 | 0 | long len=long(input->readULong(4)); |
1299 | 0 | f << "len=" << len << ","; |
1300 | 0 | if ((len && len<10) || begPos+12+len<begPos+12 || !input->checkPosition(begPos+12+len)) { |
1301 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::parseShape: can not read the picture length\n")); |
1302 | 0 | f << "###"; |
1303 | 0 | break; |
1304 | 0 | } |
1305 | 0 | shape.m_pictEntry.setBegin(begPos+12); |
1306 | 0 | shape.m_pictEntry.setLength(len); |
1307 | 0 | val=int(input->readULong(4)); |
1308 | 0 | if (val) |
1309 | 0 | f << "f1=" << val << ","; |
1310 | 0 | break; |
1311 | 0 | } |
1312 | 0 | default: |
1313 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::parseShape: find unknown type of shapes\n")); |
1314 | 0 | f << "###"; |
1315 | 0 | break; |
1316 | 0 | } |
1317 | 0 | if (m_state->m_idToShapeMap.count(pageId)) { |
1318 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::parseShape: find a duplicated shape %d:%d\n", pageId.first, pageId.second)); |
1319 | 0 | f << "###"; |
1320 | 0 | } |
1321 | 0 | else |
1322 | 0 | m_state->m_idToShapeMap[pageId]=shape; |
1323 | 0 | if (!asciiUpdated) { |
1324 | 0 | ascii().addPos(begPos); |
1325 | 0 | ascii().addNote(f.str().c_str()); |
1326 | 0 | } |
1327 | 0 | return true; |
1328 | 0 | } |
1329 | | |
1330 | | bool SpringBoardParser::parseFrames(int page, long begPos) |
1331 | 0 | { |
1332 | 0 | MWAWInputStreamPtr input = getInput(); |
1333 | 0 | if (!input) |
1334 | 0 | return false; |
1335 | 0 | if (begPos<0x80 || !input->checkPosition(begPos+14)) { |
1336 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::parseFrames: the begin position seems bad\n")); |
1337 | 0 | return false; |
1338 | 0 | } |
1339 | 0 | libmwaw::DebugStream f; |
1340 | 0 | f << "Entries(Frame):page=" << page << ","; |
1341 | 0 | input->seek(begPos, librevenge::RVNG_SEEK_SET); |
1342 | 0 | int val; |
1343 | 0 | for (int i=0; i<2; ++i) { // f0=0|-4|10 |
1344 | 0 | val=int(input->readLong(2)); |
1345 | 0 | if (val!=i) |
1346 | 0 | f << "f" << i << "=" << val << ","; |
1347 | 0 | } |
1348 | 0 | int dim[4]; |
1349 | 0 | for (auto &d : dim) d=int(input->readLong(2)); |
1350 | 0 | MWAWBox2i dimension=MWAWBox2i(MWAWVec2i(dim[1], dim[0]),MWAWVec2i(dim[3], dim[2])); |
1351 | 0 | f << "box=" << dimension << ","; |
1352 | 0 | if (m_state->m_pageIdToDimensionMap.count(page)) { |
1353 | 0 | f << "###dupl,"; |
1354 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::parseFrames: the page %d dimension is already set\n", page)); |
1355 | 0 | } |
1356 | 0 | else |
1357 | 0 | m_state->m_pageIdToDimensionMap[page]=dimension; |
1358 | 0 | int N=int(input->readULong(2)); |
1359 | 0 | f << "N=" << N << ","; |
1360 | 0 | if (!input->checkPosition(begPos+14+N*28)) { |
1361 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::parseFrames: can not read N\n")); |
1362 | 0 | f << "###"; |
1363 | 0 | ascii().addPos(begPos); |
1364 | 0 | ascii().addNote(f.str().c_str()); |
1365 | 0 | return false; |
1366 | 0 | } |
1367 | 0 | ascii().addPos(begPos); |
1368 | 0 | ascii().addNote(f.str().c_str()); |
1369 | |
|
1370 | 0 | SpringBoardParserInternal::Frame dummy; |
1371 | 0 | for (int i=0; i<N; ++i) { |
1372 | 0 | long pos=input->tell(); |
1373 | 0 | f.str(""); |
1374 | 0 | int id=int(input->readLong(1)); |
1375 | 0 | f << "Frame-" << page << "x" << id << ":"; |
1376 | 0 | auto fIt=m_state->m_idToFrameMap.find(std::make_pair(page,id)); |
1377 | 0 | auto &frame=fIt!=m_state->m_idToFrameMap.end() ? fIt->second : dummy; |
1378 | 0 | if (fIt==m_state->m_idToFrameMap.end() && (page!=0 || id!=0)) { // 0x0 seems to be the default layout |
1379 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::parseFrames: can not find frame %dx%d\n", page, id)); |
1380 | 0 | } |
1381 | 0 | val=int(input->readLong(1)); |
1382 | 0 | switch (val) { |
1383 | 0 | case 0: |
1384 | 0 | f << "layout,"; |
1385 | 0 | break; |
1386 | 0 | case 1: |
1387 | 0 | f << "text,"; |
1388 | 0 | break; |
1389 | 0 | case 2: |
1390 | 0 | f << "graphics,"; |
1391 | 0 | break; |
1392 | 0 | default: |
1393 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::parseFrames: find unknown frame type\n")); |
1394 | 0 | f << "###type=" << val << ","; |
1395 | 0 | break; |
1396 | 0 | } |
1397 | 0 | for (int st=0; st<2; ++st) { |
1398 | 0 | for (auto &d : dim) d=int(input->readLong(2)); |
1399 | 0 | frame.m_boxes[st]=MWAWBox2i(MWAWVec2i(dim[1], dim[0]),MWAWVec2i(dim[3], dim[2])); |
1400 | 0 | if (st==0) |
1401 | 0 | f << "box=" << frame.m_boxes[0] << ","; |
1402 | 0 | else if (frame.m_boxes[0]!=frame.m_boxes[1]) |
1403 | 0 | f << "box[internal]=" << frame.m_boxes[1] << ","; |
1404 | 0 | } |
1405 | 0 | for (int j=0; j<4; ++j) { |
1406 | 0 | val=int(input->readLong(2)); |
1407 | 0 | if (val==0) continue; |
1408 | 0 | f << "f" << j << "=" << val << ","; |
1409 | 0 | } |
1410 | 0 | frame.m_numColumns=int(input->readULong(2)); |
1411 | 0 | if (frame.m_numColumns!=1) |
1412 | 0 | f << "N[col]=" << frame.m_numColumns << ","; |
1413 | 0 | if (!input->checkPosition(pos+28+frame.m_numColumns*10)) { |
1414 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::parseFrames: find unexpected subzone N\n")); |
1415 | 0 | f << "###"; |
1416 | 0 | ascii().addPos(pos); |
1417 | 0 | ascii().addNote(f.str().c_str()); |
1418 | 0 | return false; |
1419 | 0 | } |
1420 | 0 | ascii().addPos(pos); |
1421 | 0 | ascii().addNote(f.str().c_str()); |
1422 | |
|
1423 | 0 | for (int col=0; col<frame.m_numColumns; ++col) { |
1424 | 0 | pos=input->tell(); |
1425 | 0 | f.str(""); |
1426 | 0 | f << "Frame-" << page << "x" << id << "[" << col << "]:"; |
1427 | 0 | val=int(input->readULong(1)); |
1428 | 0 | if (val) |
1429 | 0 | f << "f0=" << val << ","; |
1430 | 0 | val=int(input->readULong(1)); |
1431 | 0 | if (val!=1) |
1432 | 0 | f << "col=" << val << ","; |
1433 | 0 | for (auto &d : dim) d=int(input->readLong(2)); |
1434 | | // checkme can we have some non increasing columns ? |
1435 | 0 | frame.m_columnBoxes.push_back(MWAWBox2i(MWAWVec2i(dim[1], dim[0]),MWAWVec2i(dim[3], dim[2]))); |
1436 | 0 | f << "box=" << frame.m_columnBoxes.back() << ","; |
1437 | 0 | ascii().addPos(pos); |
1438 | 0 | ascii().addNote(f.str().c_str()); |
1439 | 0 | } |
1440 | 0 | } |
1441 | 0 | return true; |
1442 | 0 | } |
1443 | | |
1444 | | //////////////////////////////////////////////////////////// |
1445 | | // send shapes |
1446 | | //////////////////////////////////////////////////////////// |
1447 | | bool SpringBoardParser::sendFrame(std::pair<int, int> const &pageId) |
1448 | 0 | { |
1449 | 0 | auto input=getInput(); |
1450 | 0 | auto listener=getGraphicListener(); |
1451 | 0 | if (!input || !listener) { |
1452 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::sendFrame: can not find the listener\n")); |
1453 | 0 | return false; |
1454 | 0 | } |
1455 | 0 | auto fIt=m_state->m_idToFrameMap.find(pageId); |
1456 | 0 | if (fIt==m_state->m_idToFrameMap.end()) { |
1457 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::sendFrame: can not find any frame for %d:%d\n", pageId.first, pageId.second)); |
1458 | 0 | return false; |
1459 | 0 | } |
1460 | 0 | auto lIt=m_state->m_idToLinkMap.find(pageId); |
1461 | 0 | int whichBox = (lIt!=m_state->m_idToLinkMap.end() && lIt->second.hasText()) ? 1 : 0; |
1462 | 0 | SpringBoardParserInternal::Frame const &frame=fIt->second; |
1463 | 0 | MWAWPosition pos(MWAWVec2f(frame.m_boxes[whichBox][0]), MWAWVec2f(frame.m_boxes[whichBox].size()), librevenge::RVNG_POINT); |
1464 | 0 | pos.setRelativePosition(MWAWPosition::Page); |
1465 | |
|
1466 | 0 | auto sIt=m_state->m_idToShapeMap.find(pageId); |
1467 | 0 | if (sIt==m_state->m_idToShapeMap.end()) { |
1468 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::sendFrame: can not find any shape for %d:%d\n", pageId.first, pageId.second)); |
1469 | 0 | auto gShape=MWAWGraphicShape::rectangle(MWAWBox2f(frame.m_boxes[whichBox])); |
1470 | 0 | listener->insertShape(pos, gShape, frame.m_style); |
1471 | 0 | return false; |
1472 | 0 | } |
1473 | | |
1474 | 0 | if (whichBox==1) { |
1475 | 0 | auto const &link=lIt->second; |
1476 | 0 | for (int p=0; p<2; ++p) { |
1477 | 0 | if (!link.m_texts[p].valid()) |
1478 | 0 | continue; |
1479 | 0 | int limits[]= {p==0 ? frame.m_boxes[0][0][1] : frame.m_boxes[1][1][1], |
1480 | 0 | p==0 ? frame.m_boxes[1][0][1] : frame.m_boxes[0][1][1] |
1481 | 0 | }; |
1482 | 0 | MWAWPosition posL(MWAWVec2f((float)frame.m_boxes[0][0][0], (float)limits[0]), |
1483 | 0 | MWAWVec2f((float)frame.m_boxes[0].size()[0],float(limits[1]-limits[0])), librevenge::RVNG_POINT); |
1484 | 0 | posL.setRelativePosition(MWAWPosition::Page); |
1485 | 0 | auto subdoc=std::make_shared<SpringBoardParserInternal::SubDocument>(*this, getInput(), pageId, p==0); |
1486 | 0 | listener->insertTextBox(posL, subdoc, MWAWGraphicStyle::emptyStyle()); |
1487 | 0 | } |
1488 | 0 | } |
1489 | 0 | SpringBoardParserInternal::Shape const &shape=sIt->second; |
1490 | 0 | switch (shape.m_type) { |
1491 | 0 | case 0: { // layout |
1492 | 0 | auto subdoc=std::make_shared<SpringBoardParserInternal::SubDocument>(*this, getInput(), pageId); |
1493 | 0 | listener->insertTextBox(pos, subdoc, frame.m_style); |
1494 | 0 | return true; |
1495 | 0 | } |
1496 | 0 | case 1: { // text zone |
1497 | 0 | size_t numCols=frame.m_columnBoxes.size(); |
1498 | 0 | std::vector<int> paraLimits; |
1499 | 0 | paraLimits.push_back(0); |
1500 | 0 | for (size_t p=0; p<shape.m_paragraphs.size(); ++p) { |
1501 | 0 | if (shape.m_paragraphs[p].m_newColumn) |
1502 | 0 | paraLimits.push_back(int(p)); |
1503 | 0 | } |
1504 | 0 | if (paraLimits.size()>numCols) |
1505 | 0 | paraLimits.resize(numCols); |
1506 | |
|
1507 | 0 | for (size_t c=0; c<std::max<size_t>(1,numCols); ++c) { |
1508 | 0 | MWAWPosition posi; |
1509 | 0 | if (numCols) { |
1510 | 0 | posi.setUnit(librevenge::RVNG_POINT); |
1511 | 0 | posi.setOrigin(MWAWVec2f(frame.m_boxes[whichBox][0]+frame.m_columnBoxes[c][0])); |
1512 | 0 | posi.setSize(MWAWVec2f(frame.m_columnBoxes[c].size())); |
1513 | 0 | posi.setRelativePosition(MWAWPosition::Page); |
1514 | 0 | } |
1515 | 0 | int limits[]= {0, -1}; // ie. all |
1516 | 0 | if (c+1<paraLimits.size()) { |
1517 | 0 | limits[0]=paraLimits[c]; |
1518 | 0 | limits[1]=paraLimits[c+1]-1; |
1519 | 0 | } |
1520 | 0 | else if (c<paraLimits.size()) { |
1521 | 0 | limits[0]=paraLimits[c]; |
1522 | 0 | limits[1]=-1; // ie. to last paragraph |
1523 | 0 | } |
1524 | 0 | else if (c) |
1525 | 0 | limits[0]=int(paraLimits.size()); // ie. nothing to retrieve |
1526 | 0 | auto subdoc=std::make_shared<SpringBoardParserInternal::SubDocument>(*this, getInput(), pageId, std::make_pair(limits[0], limits[1])); |
1527 | 0 | listener->insertTextBox(numCols==0 ? pos : posi, subdoc, frame.m_style); |
1528 | 0 | } |
1529 | 0 | return true; |
1530 | 0 | } |
1531 | 0 | case 2: { |
1532 | 0 | if (!shape.m_pictEntry.valid()) |
1533 | 0 | break; |
1534 | 0 | input->seek(shape.m_pictEntry.begin(), librevenge::RVNG_SEEK_SET); |
1535 | 0 | std::shared_ptr<MWAWPict> pict(MWAWPictData::get(input, int(shape.m_pictEntry.length()))); |
1536 | 0 | MWAWEmbeddedObject image; |
1537 | 0 | if (pict && pict->getBinary(image) && !image.m_dataList.empty()) { |
1538 | | #ifdef DEBUG_WITH_FILES |
1539 | | static int volatile pictName = 0; |
1540 | | libmwaw::DebugStream f2; |
1541 | | f2 << "PICT-" << ++pictName << ".pct"; |
1542 | | libmwaw::Debug::dumpFile(image.m_dataList[0], f2.str().c_str()); |
1543 | | ascii().skipZone(shape.m_pictEntry.begin(), shape.m_pictEntry.end()-1); |
1544 | | #endif |
1545 | 0 | listener->insertPicture(pos, image, frame.m_style); |
1546 | 0 | return true; |
1547 | 0 | } |
1548 | 0 | else { |
1549 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::parseShape: sorry, can not retrieve a picture\n")); |
1550 | 0 | } |
1551 | 0 | break; |
1552 | 0 | } |
1553 | 0 | default: |
1554 | 0 | break; |
1555 | 0 | } |
1556 | 0 | auto gShape=MWAWGraphicShape::rectangle(MWAWBox2f(frame.m_boxes[0])); |
1557 | 0 | listener->insertShape(pos, gShape, frame.m_style); |
1558 | 0 | return true; |
1559 | 0 | } |
1560 | | |
1561 | | bool SpringBoardParser::sendLinkShape(std::pair<int, int> const &linkId, bool isTop) |
1562 | 0 | { |
1563 | 0 | auto input=getInput(); |
1564 | 0 | auto listener=getGraphicListener(); |
1565 | 0 | if (!input || !listener) { |
1566 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::sendTextLink: can not find the listener\n")); |
1567 | 0 | return false; |
1568 | 0 | } |
1569 | 0 | auto lIt=m_state->m_idToLinkMap.find(linkId); |
1570 | 0 | if (lIt==m_state->m_idToLinkMap.end()) { |
1571 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::sendTextLink: can not find any link for %d:%d\n", linkId.first, linkId.second)); |
1572 | 0 | return false; |
1573 | 0 | } |
1574 | 0 | SpringBoardParserInternal::Link const &link=lIt->second; |
1575 | 0 | listener->setFont(link.m_font); |
1576 | |
|
1577 | 0 | MWAWEntry const &entry=link.m_texts[isTop ? 0 : 1]; |
1578 | 0 | if (!entry.valid()) { |
1579 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::sendTextLink: can not find text for link for %d:%d\n", linkId.first, linkId.second)); |
1580 | 0 | return false; |
1581 | 0 | } |
1582 | 0 | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
1583 | 0 | for (long i=0; i<entry.length(); ++i) { |
1584 | 0 | unsigned char c=(unsigned char)(input->readLong(1)); |
1585 | 0 | if (c == 0x9) |
1586 | 0 | listener->insertTab(); |
1587 | 0 | else if (c == 0xd) |
1588 | 0 | listener->insertEOL(); |
1589 | 0 | else if (c<0x1f) { |
1590 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::sendTextLink: find bad character %d\n", int(c))); |
1591 | 0 | } |
1592 | 0 | else |
1593 | 0 | listener->insertCharacter(c); |
1594 | 0 | } |
1595 | 0 | return true; |
1596 | 0 | } |
1597 | | |
1598 | | bool SpringBoardParser::sendTextShape(std::pair<int, int> const &pageId, int minParagraph, int maxParagraph) |
1599 | 0 | { |
1600 | 0 | auto input=getInput(); |
1601 | 0 | auto listener=getGraphicListener(); |
1602 | 0 | if (!input || !listener) { |
1603 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::sendTextShape: can not find the listener\n")); |
1604 | 0 | return false; |
1605 | 0 | } |
1606 | 0 | auto sIt=m_state->m_idToShapeMap.find(pageId); |
1607 | 0 | if (sIt==m_state->m_idToShapeMap.end()) { |
1608 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::sendTextShape: can not find any shape for %d:%d\n", pageId.first, pageId.second)); |
1609 | 0 | return false; |
1610 | 0 | } |
1611 | 0 | SpringBoardParserInternal::Shape const &shape=sIt->second; |
1612 | 0 | if (shape.m_paragraphs.empty() || minParagraph>=int(shape.m_paragraphs.size())) |
1613 | 0 | return true; |
1614 | 0 | if (minParagraph<0) minParagraph=0; |
1615 | 0 | if (maxParagraph<minParagraph || maxParagraph>=int(shape.m_paragraphs.size())) |
1616 | 0 | maxParagraph=int(shape.m_paragraphs.size()-1); |
1617 | 0 | int textZoneId=-1; |
1618 | 0 | for (int p=0; p<minParagraph; ++p) { |
1619 | 0 | auto const ¶ = shape.m_paragraphs[size_t(p)]; |
1620 | 0 | if (para.m_textZoneId!=-1) |
1621 | 0 | textZoneId=para.m_textZoneId; |
1622 | 0 | } |
1623 | 0 | for (int p=minParagraph; p<=maxParagraph; ++p) { |
1624 | 0 | auto const ¶ = shape.m_paragraphs[size_t(p)]; |
1625 | 0 | auto const &pIt=m_state->m_idToParagraphMap.find(para.m_paragraphStyle); |
1626 | 0 | if (pIt==m_state->m_idToParagraphMap.end()) { |
1627 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::sendTextShape: unknown paragraph=%d\n", para.m_paragraphStyle)); |
1628 | 0 | } |
1629 | 0 | else |
1630 | 0 | listener->setParagraph(pIt->second); |
1631 | 0 | if (para.m_textZoneId!=-1) |
1632 | 0 | textZoneId=para.m_textZoneId; |
1633 | 0 | if (textZoneId==-1) |
1634 | 0 | continue; |
1635 | 0 | auto const &tIt=m_state->m_idToTextEntriesMap.find(textZoneId); |
1636 | 0 | if (tIt==m_state->m_idToTextEntriesMap.end() || !tIt->second.valid()) { |
1637 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::sendTextShape: unknown text id=%d\n", textZoneId)); |
1638 | 0 | continue; |
1639 | 0 | } |
1640 | | |
1641 | | // now retrieve the font styles |
1642 | 0 | input->seek(para.m_charEntry.begin(), librevenge::RVNG_SEEK_SET); |
1643 | 0 | std::map<int, MWAWFont> posToCharMap; |
1644 | 0 | int cPos=0; |
1645 | 0 | libmwaw::DebugStream f; |
1646 | 0 | for (int i=0; i<para.m_numCharStyles; ++i) { |
1647 | 0 | long pos=input->tell(); |
1648 | 0 | f.str(""); |
1649 | 0 | f << "Shape-char[" << i << "]:"; |
1650 | 0 | f << "cPos=" << cPos << ","; |
1651 | 0 | int newPos=cPos+int(input->readLong(2)); |
1652 | 0 | MWAWFont font; |
1653 | 0 | readFont(font,1); |
1654 | 0 | int val=int(input->readLong(2)); |
1655 | 0 | if (val) { |
1656 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::sendTextShape: unknown styles=%d\n", val)); |
1657 | 0 | f << "#f0=" << val << ","; |
1658 | 0 | } |
1659 | 0 | val=int(input->readLong(1)); |
1660 | 0 | if (val>=0 && val<63) |
1661 | 0 | font.setDeltaLetterSpacing(float(val)); |
1662 | 0 | else { |
1663 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::sendTextShape: unexpected char spacing=%d\n", val)); |
1664 | 0 | f << "##char[spacing]=" << val << ","; |
1665 | 0 | } |
1666 | 0 | f << font.getDebugString(getFontConverter()) << ","; |
1667 | 0 | input->seek(pos+10, librevenge::RVNG_SEEK_SET); |
1668 | 0 | posToCharMap[cPos]=font; |
1669 | 0 | cPos=newPos; |
1670 | 0 | ascii().addPos(pos); |
1671 | 0 | ascii().addNote(f.str().c_str()); |
1672 | 0 | } |
1673 | |
|
1674 | 0 | MWAWEntry const textZone=tIt->second; |
1675 | 0 | input->seek(textZone.begin()+para.m_firstChar, librevenge::RVNG_SEEK_SET); |
1676 | 0 | for (int l=0; l<para.m_numChars; ++l) { |
1677 | 0 | auto cIt=posToCharMap.find(l); |
1678 | 0 | if (cIt!=posToCharMap.end()) |
1679 | 0 | listener->setFont(cIt->second); |
1680 | 0 | unsigned char c=(unsigned char)(input->readLong(1)); |
1681 | 0 | if (c == 0x9) |
1682 | 0 | listener->insertTab(); |
1683 | 0 | else if (c == 0xd) |
1684 | 0 | listener->insertEOL(); |
1685 | 0 | else if (c<0x1f) { |
1686 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::sendTextShape: find bad character %d\n", int(c))); |
1687 | 0 | } |
1688 | 0 | else |
1689 | 0 | listener->insertCharacter(c); |
1690 | 0 | } |
1691 | 0 | } |
1692 | 0 | return true; |
1693 | 0 | } |
1694 | | |
1695 | | bool SpringBoardParser::sendHeaderFooter(int hfId) |
1696 | 0 | { |
1697 | 0 | auto input=getInput(); |
1698 | 0 | auto listener=getGraphicListener(); |
1699 | 0 | if (!input || !listener) { |
1700 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::sendHeaderFooter: can not find the listener\n")); |
1701 | 0 | return false; |
1702 | 0 | } |
1703 | 0 | auto hfIt=m_state->m_pageIdToHeaderFooterMap.find(hfId); |
1704 | 0 | if (hfIt==m_state->m_pageIdToHeaderFooterMap.end()) { |
1705 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::sendHeaderFooter: can not find the header footer for id=%d\n", hfId)); |
1706 | 0 | return false; |
1707 | 0 | } |
1708 | 0 | auto const &hf=hfIt->second; |
1709 | 0 | listener->setFont(hf.m_font); |
1710 | 0 | MWAWParagraph para; // FIXME: this does nothing, find another way to send center and right header/footer |
1711 | 0 | if (hf.m_type==1 || hf.m_type==4) |
1712 | 0 | para.m_justify = MWAWParagraph::JustificationCenter; |
1713 | 0 | else if (hf.m_type==2 || hf.m_type==5) |
1714 | 0 | para.m_justify = MWAWParagraph::JustificationRight; |
1715 | 0 | listener->setParagraph(para); |
1716 | 0 | if (hf.m_zones[0].valid()) { // prefix |
1717 | 0 | input->seek(hf.m_zones[0].begin(), librevenge::RVNG_SEEK_SET); |
1718 | 0 | for (long l=0; l<hf.m_zones[0].length(); ++l) { |
1719 | 0 | unsigned char c=(unsigned char)(input->readLong(1)); |
1720 | 0 | if (c == 0x9) |
1721 | 0 | listener->insertTab(); |
1722 | 0 | else if (c == 0xd) |
1723 | 0 | listener->insertEOL(); |
1724 | 0 | else if (c<0x1f) { |
1725 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::sendHeaderFooter: find bad character %d\n", int(c))); |
1726 | 0 | } |
1727 | 0 | else |
1728 | 0 | listener->insertCharacter(c); |
1729 | 0 | } |
1730 | 0 | } |
1731 | 0 | MWAWField pageNumber(MWAWField::PageNumber); |
1732 | 0 | switch (hf.m_type) { |
1733 | 0 | case 1: |
1734 | 0 | pageNumber.m_numberingType=libmwaw::LOWERCASE_ROMAN; |
1735 | 0 | break; |
1736 | 0 | case 2: |
1737 | 0 | pageNumber.m_numberingType=libmwaw::UPPERCASE_ROMAN; |
1738 | 0 | break; |
1739 | 0 | case 3: |
1740 | 0 | pageNumber.m_numberingType=libmwaw::LOWERCASE; |
1741 | 0 | break; |
1742 | 0 | case 4: |
1743 | 0 | pageNumber.m_numberingType=libmwaw::UPPERCASE; |
1744 | 0 | break; |
1745 | 0 | default: // also 5-7 full number minuscule, majuscule, title |
1746 | 0 | break; |
1747 | 0 | } |
1748 | 0 | if (pageNumber.m_type!=8) |
1749 | 0 | listener->insertField(pageNumber); |
1750 | 0 | if (hf.m_zones[1].valid()) { // suffix |
1751 | 0 | input->seek(hf.m_zones[1].begin(), librevenge::RVNG_SEEK_SET); |
1752 | 0 | for (long l=0; l<hf.m_zones[1].length(); ++l) { |
1753 | 0 | unsigned char c=(unsigned char)(input->readLong(1)); |
1754 | 0 | if (c == 0x9) |
1755 | 0 | listener->insertTab(); |
1756 | 0 | else if (c == 0xd) |
1757 | 0 | listener->insertEOL(); |
1758 | 0 | else if (c<0x1f) { |
1759 | 0 | MWAW_DEBUG_MSG(("SpringBoardParser::sendHeaderFooter: find bad character %d\n", int(c))); |
1760 | 0 | } |
1761 | 0 | else |
1762 | 0 | listener->insertCharacter(c); |
1763 | 0 | } |
1764 | 0 | } |
1765 | 0 | return true; |
1766 | 0 | } |
1767 | | |
1768 | | |
1769 | | //////////////////////////////////////////////////////////// |
1770 | | // read shapes |
1771 | | //////////////////////////////////////////////////////////// |
1772 | | |
1773 | | //////////////////////////////////////////////////////////// |
1774 | | // read the header |
1775 | | //////////////////////////////////////////////////////////// |
1776 | | bool SpringBoardParser::checkHeader(MWAWHeader *header, bool strict) |
1777 | 152 | { |
1778 | 152 | *m_state = SpringBoardParserInternal::State(); |
1779 | 152 | MWAWInputStreamPtr input = getInput(); |
1780 | 152 | if (!input || !input->hasDataFork() || !input->checkPosition(128)) |
1781 | 19 | return false; |
1782 | | |
1783 | 133 | libmwaw::DebugStream f; |
1784 | 133 | f << "FileHeader:"; |
1785 | 133 | input->seek(0, librevenge::RVNG_SEEK_SET); |
1786 | 133 | if (input->readULong(2)!=0xcd90) |
1787 | 0 | return false; |
1788 | 399 | for (int i=0; i<2; ++i) { |
1789 | 266 | int val=int(input->readLong(1)); |
1790 | 266 | if (val==i) continue; |
1791 | 159 | if (i==0) |
1792 | 46 | f << "rev" << val << ","; // look like a counter (modulo 10) |
1793 | 113 | else |
1794 | 113 | f << "f" << i << "=" << val << ","; |
1795 | 159 | } |
1796 | 133 | if ((input->readULong(2)&0xff00)!=0) return false; |
1797 | | |
1798 | 133 | if (strict) { |
1799 | 55 | input->seek(20, librevenge::RVNG_SEEK_SET); |
1800 | 204 | for (int i=0; i<10; ++i) { |
1801 | 202 | long beg=long(input->readULong(4)); |
1802 | 202 | long len=long(input->readULong(2)); |
1803 | 202 | if (!len) |
1804 | 118 | continue; |
1805 | 84 | if (beg<=0 || beg+len<=0 || !input->checkPosition(beg+len)) { |
1806 | 53 | MWAW_DEBUG_MSG(("SpringBoardParser::checkHeader: find unexpected position: %d\n", int(i))); |
1807 | 53 | f << "###"; |
1808 | 53 | ascii().addPos(0); |
1809 | 53 | ascii().addNote(f.str().c_str()); |
1810 | | |
1811 | 53 | return false; |
1812 | 53 | } |
1813 | 84 | } |
1814 | 55 | } |
1815 | | |
1816 | 80 | ascii().addPos(0); |
1817 | 80 | ascii().addNote(f.str().c_str()); |
1818 | 80 | if (header) |
1819 | 52 | header->reset(MWAWDocument::MWAW_T_SPRINGBOARD_PUBLISHER, 2, MWAWDocument::MWAW_K_DRAW); |
1820 | 80 | input->seek(4, librevenge::RVNG_SEEK_SET); |
1821 | | |
1822 | 80 | return true; |
1823 | 133 | } |
1824 | | |
1825 | | // vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: |