/src/libmwaw/src/lib/ClarisDrawParser.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 | | |
40 | | #include <librevenge/librevenge.h> |
41 | | |
42 | | #include "MWAWFontConverter.hxx" |
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 "MWAWPrinter.hxx" |
51 | | #include "MWAWPosition.hxx" |
52 | | #include "MWAWSubDocument.hxx" |
53 | | |
54 | | #include "ClarisDrawStyleManager.hxx" |
55 | | #include "ClarisDrawGraph.hxx" |
56 | | #include "ClarisDrawText.hxx" |
57 | | #include "ClarisWksStruct.hxx" |
58 | | |
59 | | #include "ClarisDrawParser.hxx" |
60 | | |
61 | | /** Internal: the structures of a ClarisDrawParser */ |
62 | | namespace ClarisDrawParserInternal |
63 | | { |
64 | | // generic class used to defined a layer |
65 | | struct Layer { |
66 | | //! constructor |
67 | | Layer() |
68 | 5.47k | : m_groupId(0) |
69 | 5.47k | , m_isHidden(false) |
70 | 5.47k | , m_name("") |
71 | 5.47k | { |
72 | 5.47k | } |
73 | | //! the first group id |
74 | | int m_groupId; |
75 | | //! true if the layer is hidden |
76 | | bool m_isHidden; |
77 | | //! the layer name |
78 | | librevenge::RVNGString m_name; |
79 | | }; |
80 | | |
81 | | //////////////////////////////////////////// |
82 | | //! Internal: the state of a ClarisDrawParser |
83 | | struct State { |
84 | | //! constructor |
85 | | State() |
86 | 167k | : m_version(0) |
87 | 167k | , m_isLibrary(false) |
88 | 167k | , m_numDSET(0) |
89 | 167k | , m_EOF(-1) |
90 | 167k | , m_actualLayer(1) |
91 | 167k | , m_numLayers(1) |
92 | 167k | , m_createMasterPage(false) |
93 | 167k | , m_displayAsSlide(false) |
94 | 167k | , m_layerList() |
95 | 167k | , m_pageSpanSet(false) |
96 | 167k | , m_headerId(0) |
97 | 167k | , m_footerId(0) |
98 | 167k | , m_pages(1,1) |
99 | 167k | , m_zonesMap() |
100 | 167k | , m_zoneIdToFileTypeMap() |
101 | 167k | { |
102 | 167k | } |
103 | | //! the file version |
104 | | int m_version; |
105 | | //! flag to know if the file is a library or not |
106 | | bool m_isLibrary; |
107 | | //! the number of DSET+FNTM |
108 | | int m_numDSET; |
109 | | //! the last data zone size |
110 | | long m_EOF; |
111 | | //! the actual layer |
112 | | int m_actualLayer; |
113 | | //! the number of layer |
114 | | int m_numLayers; |
115 | | //! flag to know if we need or not to create a master |
116 | | bool m_createMasterPage; |
117 | | //! flag to know if we need to display data as slide |
118 | | bool m_displayAsSlide; |
119 | | //! the layer list |
120 | | std::vector<Layer> m_layerList; |
121 | | //! flag to know if the page has been set |
122 | | bool m_pageSpanSet; |
123 | | //! header id |
124 | | int m_headerId; |
125 | | //! footer id |
126 | | int m_footerId; |
127 | | //! the number of pages |
128 | | MWAWVec2i m_pages; |
129 | | /** the map of zone*/ |
130 | | std::map<int, std::shared_ptr<ClarisWksStruct::DSET> > m_zonesMap; |
131 | | /** map zone id to file type */ |
132 | | std::map<int, int> m_zoneIdToFileTypeMap; |
133 | | }; |
134 | | } |
135 | | |
136 | | //////////////////////////////////////////////////////////// |
137 | | // constructor/destructor, ... |
138 | | //////////////////////////////////////////////////////////// |
139 | | ClarisDrawParser::ClarisDrawParser(MWAWInputStreamPtr const &input, MWAWRSRCParserPtr const &rsrcParser, MWAWHeader *header) |
140 | 68.6k | : MWAWGraphicParser(input, rsrcParser, header) |
141 | 68.6k | , m_state() |
142 | 68.6k | , m_styleManager() |
143 | 68.6k | , m_graphParser() |
144 | 68.6k | , m_textParser() |
145 | 68.6k | { |
146 | 68.6k | init(); |
147 | 68.6k | } |
148 | | |
149 | | ClarisDrawParser::~ClarisDrawParser() |
150 | 68.6k | { |
151 | 68.6k | } |
152 | | |
153 | | void ClarisDrawParser::init() |
154 | 68.6k | { |
155 | 68.6k | resetGraphicListener(); |
156 | 68.6k | setAsciiName("main-1"); |
157 | 68.6k | m_state.reset(new ClarisDrawParserInternal::State); |
158 | 68.6k | m_styleManager.reset(new ClarisDrawStyleManager(*this)); |
159 | | |
160 | 68.6k | m_graphParser.reset(new ClarisDrawGraph(*this)); |
161 | 68.6k | m_textParser.reset(new ClarisDrawText(*this)); |
162 | | |
163 | 68.6k | getPageSpan().setMargins(0.1); |
164 | 68.6k | } |
165 | | |
166 | | int ClarisDrawParser::getFileType(int zoneId) const |
167 | 167k | { |
168 | 167k | if (m_state->m_zoneIdToFileTypeMap.find(zoneId) == m_state->m_zoneIdToFileTypeMap.end()) { |
169 | 75.4k | MWAW_DEBUG_MSG(("ClarisDrawParser::getFileType: zone %d does not exists!!!!\n", zoneId)); |
170 | 75.4k | return -1; |
171 | 75.4k | } |
172 | 91.7k | return m_state->m_zoneIdToFileTypeMap.find(zoneId)->second; |
173 | 167k | } |
174 | | |
175 | | bool ClarisDrawParser::sendTextZone(int number, int subZone) |
176 | 5.05k | { |
177 | 5.05k | return m_textParser->sendZone(number, subZone); |
178 | 5.05k | } |
179 | | |
180 | | MWAWVec2f ClarisDrawParser::getPageLeftTop() |
181 | 31.3k | { |
182 | 31.3k | return MWAWVec2f(float(getParserState()->m_pageSpan.getMarginLeft()), |
183 | 31.3k | float(getParserState()->m_pageSpan.getMarginTop())); |
184 | 31.3k | } |
185 | | |
186 | | //////////////////////////////////////////////////////////// |
187 | | // the parser |
188 | | //////////////////////////////////////////////////////////// |
189 | | void ClarisDrawParser::parse(librevenge::RVNGDrawingInterface *docInterface) |
190 | 30.5k | { |
191 | 30.5k | if (!getInput().get() || !checkHeader(nullptr)) throw(libmwaw::ParseException()); |
192 | 30.5k | bool ok = false; |
193 | 30.5k | try { |
194 | | // create the asciiFile |
195 | 30.5k | ascii().setStream(getInput()); |
196 | 30.5k | ascii().open(asciiName()); |
197 | 30.5k | checkHeader(nullptr); |
198 | 30.5k | ok = createZones(); |
199 | 30.5k | if (ok) { |
200 | 30.4k | createDocument(docInterface); |
201 | 30.4k | MWAWVec2f leftTop=72.0f*getPageLeftTop(); |
202 | 30.4k | MWAWPosition pos(leftTop,MWAWVec2f(0,0),librevenge::RVNG_POINT); |
203 | 30.4k | pos.setRelativePosition(MWAWPosition::Page); |
204 | 30.4k | MWAWGraphicListenerPtr listener=getGraphicListener(); |
205 | | |
206 | 30.4k | if (m_state->m_isLibrary) { |
207 | 25.3k | for (size_t i=0; i<m_state->m_layerList.size(); ++i) { |
208 | 0 | if (i>0) |
209 | 0 | listener->insertBreak(MWAWListener::PageBreak); |
210 | 0 | m_graphParser->sendMainGroupChild(int(i), pos); |
211 | 0 | } |
212 | 25.3k | } |
213 | 5.11k | else if (m_state->m_displayAsSlide) { |
214 | 1.02k | bool first=true; |
215 | 2.94k | for (size_t i=1; i< m_state->m_layerList.size(); ++i) { |
216 | 1.92k | if (m_graphParser->isEmptyGroup(m_state->m_layerList[i].m_groupId)) |
217 | 1.24k | continue; |
218 | 678 | if (!first) |
219 | 250 | listener->insertBreak(MWAWListener::PageBreak); |
220 | 678 | first=false; |
221 | 678 | m_graphParser->sendGroup(m_state->m_layerList[i].m_groupId, pos); |
222 | 678 | } |
223 | 1.02k | } |
224 | 4.08k | else { |
225 | 6.06k | for (size_t i=1; i< m_state->m_layerList.size(); ++i) { |
226 | 1.97k | if (m_graphParser->isEmptyGroup(m_state->m_layerList[i].m_groupId)) |
227 | 623 | continue; |
228 | 1.35k | bool openLayer=false; |
229 | 1.35k | if (!m_state->m_layerList[i].m_name.empty()) |
230 | 1.13k | openLayer=listener->openLayer(m_state->m_layerList[i].m_name); |
231 | 1.35k | m_graphParser->sendGroup(m_state->m_layerList[i].m_groupId, pos); |
232 | 1.35k | if (openLayer) |
233 | 1.13k | listener->closeLayer(); |
234 | 1.35k | } |
235 | 4.08k | } |
236 | | #ifdef DEBUG |
237 | | m_graphParser->flushExtra(); |
238 | | #endif |
239 | 30.4k | } |
240 | 30.5k | ascii().reset(); |
241 | 30.5k | } |
242 | 30.5k | catch (...) { |
243 | 20 | MWAW_DEBUG_MSG(("ClarisDrawParser::parse: exception catched when parsing\n")); |
244 | 20 | ok = false; |
245 | 20 | } |
246 | | |
247 | 30.5k | resetGraphicListener(); |
248 | 30.5k | if (!ok) throw(libmwaw::ParseException()); |
249 | 30.5k | } |
250 | | |
251 | | //////////////////////////////////////////////////////////// |
252 | | // create the document |
253 | | //////////////////////////////////////////////////////////// |
254 | | void ClarisDrawParser::createDocument(librevenge::RVNGDrawingInterface *documentInterface) |
255 | 30.4k | { |
256 | 30.4k | if (!documentInterface) return; |
257 | 30.4k | if (getGraphicListener()) { |
258 | 0 | MWAW_DEBUG_MSG(("ClarisDrawParser::createDocument: listener already exist\n")); |
259 | 0 | return; |
260 | 0 | } |
261 | | |
262 | 30.4k | m_graphParser->updateGroup(m_state->m_isLibrary); |
263 | | |
264 | | |
265 | | // create the page list |
266 | 30.4k | int numPages=1; |
267 | 30.4k | MWAWPageSpan ps(getPageSpan()); |
268 | 30.4k | ps.setPageSpan(1); |
269 | 30.4k | std::vector<librevenge::RVNGString> listNames; |
270 | 30.4k | if (m_state->m_isLibrary) { |
271 | 25.3k | numPages=static_cast<int>(m_state->m_layerList.size()); |
272 | 25.3k | if (numPages<1) numPages=1; |
273 | 25.3k | } |
274 | 5.11k | else { |
275 | 5.11k | m_state->m_createMasterPage=!m_state->m_layerList.empty() && |
276 | 1.57k | !m_graphParser->isEmptyGroup(m_state->m_layerList[0].m_groupId); |
277 | 5.11k | if (m_state->m_createMasterPage) |
278 | 911 | ps.setMasterPageName(librevenge::RVNGString("Master")); |
279 | 9.01k | for (size_t i=1; i<m_state->m_layerList.size(); ++i) { |
280 | 3.90k | if (!m_graphParser->isEmptyGroup(m_state->m_layerList[i].m_groupId)) |
281 | 2.03k | listNames.push_back(m_state->m_layerList[i].m_name); |
282 | 3.90k | } |
283 | 5.11k | if (m_state->m_displayAsSlide && !listNames.empty()) |
284 | 428 | numPages=static_cast<int>(listNames.size()); |
285 | 5.11k | } |
286 | 30.4k | std::vector<MWAWPageSpan> pageList; |
287 | 61.0k | for (int i=0; i<numPages; ++i) { |
288 | 30.6k | MWAWPageSpan page(ps); |
289 | 30.6k | if (m_state->m_isLibrary && i<static_cast<int>(m_state->m_layerList.size())) |
290 | 0 | page.setPageName(m_state->m_layerList[size_t(i)].m_name); |
291 | 30.6k | else if (m_state->m_displayAsSlide && i<static_cast<int>(listNames.size())) |
292 | 678 | page.setPageName(listNames[size_t(i)]); |
293 | 30.6k | pageList.push_back(page); |
294 | 30.6k | } |
295 | 30.4k | MWAWGraphicListenerPtr listen(new MWAWGraphicListener(*getParserState(), pageList, documentInterface)); |
296 | 30.4k | setGraphicListener(listen); |
297 | 30.4k | listen->startDocument(); |
298 | | |
299 | | |
300 | 30.4k | if (!m_state->m_createMasterPage) |
301 | 29.5k | return; |
302 | | |
303 | | // we need to send the master page |
304 | 911 | if (!listen->openMasterPage(ps)) { |
305 | 0 | MWAW_DEBUG_MSG(("ClarisDrawParser::createDocument: can not create the master page\n")); |
306 | 0 | m_state->m_createMasterPage=false; |
307 | 0 | return; |
308 | 0 | } |
309 | 911 | MWAWVec2f leftTop=72.0f*getPageLeftTop(); |
310 | 911 | MWAWPosition pos(leftTop,MWAWVec2f(0,0),librevenge::RVNG_POINT); |
311 | 911 | pos.setRelativePosition(MWAWPosition::Page); |
312 | 911 | m_graphParser->sendGroup(m_state->m_layerList[0].m_groupId, pos); |
313 | 911 | listen->closeMasterPage(); |
314 | 911 | } |
315 | | |
316 | | //////////////////////////////////////////////////////////// |
317 | | // |
318 | | // Intermediate level |
319 | | // |
320 | | //////////////////////////////////////////////////////////// |
321 | | bool ClarisDrawParser::createZones() |
322 | 30.5k | { |
323 | 30.5k | MWAWInputStreamPtr input = getInput(); |
324 | 30.5k | if ((m_state->m_isLibrary && !readLibraryHeader()) || |
325 | 30.5k | (!m_state->m_isLibrary && !readDocHeader())) |
326 | 143 | return false; |
327 | | |
328 | 30.4k | if (m_state->m_EOF>0) |
329 | 23.8k | input->pushLimit(m_state->m_EOF); |
330 | 350k | while (readZone()); |
331 | 30.4k | if (!input->isEnd()) { |
332 | 29.9k | ascii().addPos(input->tell()); |
333 | 29.9k | ascii().addNote("Entries(BAD)"); |
334 | 29.9k | } |
335 | 210M | while (!input->isEnd()) { |
336 | 210M | long pos=input->tell(); |
337 | 210M | if (input->readULong(4)!=0x44534554) { |
338 | 209M | input->seek(pos+1, librevenge::RVNG_SEEK_SET); |
339 | 209M | continue; |
340 | 209M | } |
341 | 1.01M | input->seek(pos, librevenge::RVNG_SEEK_SET); |
342 | 1.01M | long actPos=input->tell(); |
343 | 4.25M | while (readZone()) |
344 | 3.23M | actPos=input->tell(); |
345 | 1.01M | if (actPos==pos) { |
346 | 84.2k | input->seek(actPos+4, librevenge::RVNG_SEEK_SET); |
347 | 84.2k | continue; |
348 | 84.2k | } |
349 | 931k | input->seek(actPos, librevenge::RVNG_SEEK_SET); |
350 | 931k | if (input->isEnd()) break; |
351 | 910k | MWAW_DEBUG_MSG(("ClarisDrawParser::createZones: oops loose tracks of zones\n")); |
352 | 910k | ascii().addPos(input->tell()); |
353 | 910k | ascii().addNote("Entries(BAD):###"); |
354 | 910k | } |
355 | 30.4k | if (m_state->m_EOF>0) |
356 | 23.8k | input->popLimit(); |
357 | 30.4k | return true; |
358 | 30.5k | } |
359 | | |
360 | | bool ClarisDrawParser::readZone() |
361 | 4.60M | { |
362 | 4.60M | MWAWInputStreamPtr input = getInput(); |
363 | 4.60M | long pos=input->tell(); |
364 | 4.60M | if (!input->checkPosition(pos+4)) |
365 | 21.3k | return false; |
366 | 4.58M | auto zoneSz=long(input->readULong(4)); |
367 | 4.58M | if (zoneSz==0x44534554) { |
368 | 1.09M | input->seek(pos, librevenge::RVNG_SEEK_SET); |
369 | 1.09M | return readDSET().get()!=nullptr; |
370 | 1.09M | } |
371 | 3.49M | else if (zoneSz==0x464e544d) { |
372 | 18.9k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
373 | 18.9k | return m_styleManager->readFontNames(); |
374 | 18.9k | } |
375 | 3.47M | else if ((zoneSz>>16)>16) { |
376 | 852k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
377 | 852k | return false; |
378 | 852k | } |
379 | 2.61M | else if ((zoneSz>>16)!=0) { |
380 | 100k | ascii().addPos(pos); |
381 | 100k | ascii().addNote("Entries(Short)"); |
382 | 100k | input->seek(pos+2, librevenge::RVNG_SEEK_SET); |
383 | 100k | return true; |
384 | 100k | } |
385 | 2.51M | long endPos=input->tell()+zoneSz; |
386 | 2.51M | if (zoneSz<0 || ((zoneSz&1) && (zoneSz==0x4453 || zoneSz==0x464e)) || !input->checkPosition(endPos)) { |
387 | 72.1k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
388 | 72.1k | return false; |
389 | 72.1k | } |
390 | 2.44M | libmwaw::DebugStream f; |
391 | 2.44M | if (zoneSz==0) |
392 | 2.22M | f << "_"; |
393 | 220k | else |
394 | 220k | f << "Entries(Unknown)"; |
395 | 2.44M | ascii().addPos(pos); |
396 | 2.44M | ascii().addNote(f.str().c_str()); |
397 | 2.44M | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
398 | 2.44M | return true; |
399 | 2.51M | } |
400 | | |
401 | | bool ClarisDrawParser::readDocHeader() |
402 | 5.25k | { |
403 | 5.25k | MWAWInputStreamPtr input = getInput(); |
404 | 5.25k | if (!input->checkPosition(0x80A)) return false; |
405 | | |
406 | 5.25k | input->seek(8, librevenge::RVNG_SEEK_SET); |
407 | 5.25k | libmwaw::DebugStream f; |
408 | 5.25k | f << "Entries(DocHeader):"; |
409 | 5.25k | auto val = static_cast<int>(input->readLong(2)); // always find 1 |
410 | 5.25k | if (val != 1) |
411 | 3.38k | f << "#unkn=" << std::hex << val << std::dec << ","; |
412 | 26.2k | for (int i = 0; i < 4; i++) { |
413 | 21.0k | val = static_cast<int>(input->readULong(2)); |
414 | 21.0k | if (val) |
415 | 8.98k | f << std::hex << "f" << i << "=" << std::hex << val << std::dec << ","; |
416 | 21.0k | } |
417 | 5.25k | int dim[2]; |
418 | 10.5k | for (int &i : dim) i= static_cast<int>(input->readLong(2)); |
419 | 5.25k | f << "dim?=" << dim[1] << "x" << dim[0] << ","; |
420 | 5.25k | int margin[6]; |
421 | 5.25k | f << "margin?=["; |
422 | 31.5k | for (int &i : margin) { |
423 | 31.5k | i = static_cast<int>(input->readLong(2)); |
424 | 31.5k | if (i) |
425 | 12.8k | f << i << ","; |
426 | 18.6k | else |
427 | 18.6k | f << "_,"; |
428 | 31.5k | } |
429 | 5.25k | f << "],"; |
430 | | // seems a good indication that slide mode is choosen |
431 | 5.25k | if (dim[0] > 0 && dim[1] > 0 && |
432 | 3.45k | margin[0] >= 0 && margin[1] >= 0 && margin[2] >= 0 && margin[3] >= 0 && |
433 | 3.07k | dim[0] > margin[0]+margin[2] && dim[1] > margin[1]+margin[3]) { |
434 | | |
435 | 2.72k | MWAWVec2i paperSize(dim[1],dim[0]); |
436 | 2.72k | MWAWVec2i lTopMargin(margin[1], margin[0]); |
437 | 2.72k | MWAWVec2i rBotMargin(margin[3], margin[2]); |
438 | | |
439 | 2.72k | getPageSpan().setMarginTop(lTopMargin.y()/72.0); |
440 | 2.72k | getPageSpan().setMarginBottom(rBotMargin.y()/72.0); |
441 | 2.72k | getPageSpan().setMarginLeft(lTopMargin.x()/72.0); |
442 | 2.72k | getPageSpan().setMarginRight(rBotMargin.x()/72.0); |
443 | 2.72k | getPageSpan().setFormLength(paperSize.y()/72.); |
444 | 2.72k | getPageSpan().setFormWidth(paperSize.x()/72.); |
445 | 2.72k | m_state->m_pageSpanSet = true; |
446 | 2.72k | } |
447 | 5.25k | int dim2[2]; |
448 | 10.5k | for (int &i : dim2) i = static_cast<int>(input->readLong(2)); |
449 | 5.25k | f << "dim2?=" << dim2[1] << "x" << dim2[0] << ","; |
450 | 5.25k | int fl[4]; |
451 | 5.25k | f << "fl?=["; |
452 | 21.0k | for (int &i : fl) { |
453 | 21.0k | i = static_cast<int>(input->readULong(1)); |
454 | 21.0k | if (i) |
455 | 6.46k | f << i << ","; |
456 | 14.5k | else |
457 | 14.5k | f << "_,"; |
458 | 21.0k | } |
459 | 5.25k | f << "],"; |
460 | 52.5k | for (int i = 0; i < 9; i++) { |
461 | 47.2k | val = static_cast<int>(input->readLong(2)); |
462 | 47.2k | if (val) |
463 | 6.60k | f << "g" << i << "=" << val << ","; |
464 | 47.2k | } |
465 | | |
466 | 5.25k | ascii().addDelimiter(input->tell(), '|'); |
467 | 5.25k | ascii().addPos(8); |
468 | 5.25k | ascii().addNote(f.str().c_str()); |
469 | | |
470 | 5.25k | input->seek(8+132, librevenge::RVNG_SEEK_SET); |
471 | | |
472 | | /* zone 1 actual font, actul pos, .. */ |
473 | 5.25k | if (!m_textParser->readParagraph()) |
474 | 0 | return false; |
475 | 5.25k | long pos = input->tell(); |
476 | 5.25k | f.str(""); |
477 | 5.25k | f << "DocHeader:zone?=" << input->readULong(2) << ","; |
478 | 5.25k | ascii().addPos(pos); |
479 | 5.25k | ascii().addNote(f.str().c_str()); |
480 | 5.25k | MWAWFont font; |
481 | 5.25k | int posChar; |
482 | 5.25k | if (!m_textParser->readFont(-1, posChar, font)) |
483 | 0 | return false; |
484 | | |
485 | | /* zone 2, type, unknown */ |
486 | 5.25k | pos = input->tell(); |
487 | 5.25k | f.str(""); |
488 | 5.25k | f << "DocHeader-1:"; |
489 | 36.7k | for (int i = 0; i < 6; i++) { |
490 | 31.5k | val = static_cast<int>(input->readULong(2)); |
491 | 31.5k | if (val) f << "f" << i << "=" << val << ","; |
492 | 31.5k | } |
493 | 5.25k | ascii().addDelimiter(input->tell(), '|'); |
494 | 5.25k | input->seek(pos+20, librevenge::RVNG_SEEK_SET); |
495 | 5.25k | ascii().addPos(pos); |
496 | 5.25k | ascii().addNote(f.str().c_str()); |
497 | | |
498 | | // the document font ? |
499 | 5.25k | if (!m_textParser->readFont(-1, posChar, font)) |
500 | 0 | return false; |
501 | | |
502 | 5.25k | pos=input->tell(); |
503 | 5.25k | f.str(""); |
504 | 5.25k | f << "DocHeader-2:"; |
505 | 31.5k | for (int i=0; i<5; ++i) { |
506 | 26.2k | val=static_cast<int>(input->readULong(2)); |
507 | 26.2k | static int const expected[] = {0,1,2,2,0}; |
508 | 26.2k | if (val!=expected[i]) |
509 | 14.7k | f << "f" << i << "=" << val << ","; |
510 | 26.2k | } |
511 | 47.2k | for (int i=0; i<8; ++i) { |
512 | 42.0k | val=static_cast<int>(input->readULong(1)); |
513 | 42.0k | static int const expected[] = {1/*or 16*/,0,0,0,0,1,1, 0}; |
514 | 42.0k | if (val!=expected[i]) |
515 | 16.9k | f << "f" << i+5 << "=" << val << ","; |
516 | 42.0k | } |
517 | 26.2k | for (int i=0; i<4; ++i) { |
518 | 21.0k | val=static_cast<int>(input->readULong(2)); |
519 | 21.0k | static int const expected[] = {1,1,0x2d,0}; |
520 | 21.0k | if (val!=expected[i]) |
521 | 11.6k | f << "f" << i+13 << "=" << val << ","; |
522 | 21.0k | } |
523 | 5.25k | f << "fl=["; |
524 | 73.5k | for (int i=0; i<13; ++i) { |
525 | 68.3k | val=static_cast<int>(input->readULong(1)); |
526 | 68.3k | if (val==1) f << "*,"; |
527 | 48.8k | else if (val) f << val << ","; |
528 | 32.0k | else f << "_,"; |
529 | 68.3k | } |
530 | 5.25k | f << "],"; |
531 | 89.3k | for (int i=0; i<16; ++i) { // always 0 |
532 | 84.0k | val=static_cast<int>(input->readULong(2)); |
533 | 84.0k | if (val) |
534 | 28.1k | f << "g" << i << "=" << val << ","; |
535 | 84.0k | } |
536 | 31.5k | for (int i=0; i<5; ++i) { |
537 | 26.2k | val=static_cast<int>(input->readULong(2)); |
538 | 26.2k | static int const expected[] = {0,1,0,0x600,0x504}; |
539 | 26.2k | if (val!=expected[i]) |
540 | 14.3k | f << "h" << i << "=" << std::hex << val << std::dec << ","; |
541 | 26.2k | } |
542 | 5.25k | val=static_cast<int>(input->readULong(1)); // always 0 |
543 | 5.25k | if (val) f << "h5=" << val << ","; |
544 | 5.25k | int num[3]; |
545 | 21.0k | for (int i=0; i<3; ++i) { |
546 | 15.7k | num[i]=static_cast<int>(input->readULong(2)); |
547 | 15.7k | if (!num[i]) |
548 | 5.09k | continue; |
549 | 10.6k | static char const* const wh[]= {"color", "unkn1", "gradient"}; |
550 | 10.6k | f << "num[" << wh[i] << "]=" << num[i] << ","; |
551 | 10.6k | } |
552 | 5.25k | m_styleManager->setDefaultNumbers(num[0], num[2]); |
553 | | |
554 | 5.25k | ascii().addDelimiter(input->tell(),'|'); |
555 | 5.25k | ascii().addPos(pos); |
556 | 5.25k | ascii().addNote(f.str().c_str()); |
557 | 5.25k | input->seek(pos+124, librevenge::RVNG_SEEK_SET); |
558 | | |
559 | 5.25k | pos=input->tell(); |
560 | 5.25k | f.str(""); |
561 | 5.25k | f << "DocHeader(Col):"; |
562 | 5.25k | auto numCols = static_cast<int>(input->readLong(2)); |
563 | 5.25k | if (numCols < 1 || numCols > 9) { |
564 | 3.17k | MWAW_DEBUG_MSG(("ClarisDrawParser::readDocHeader: pb reading number of columns\n")); |
565 | 3.17k | f << "###numCols=" << numCols; |
566 | 3.17k | numCols = 1; |
567 | 3.17k | } |
568 | 5.25k | if (numCols != 1) |
569 | 196 | f << "numCols=" << numCols << ","; |
570 | 5.25k | f << "colsW=["; |
571 | 11.2k | for (int i = 0; i < numCols; i++) { |
572 | 5.96k | val = static_cast<int>(input->readULong(2)); |
573 | 5.96k | f << val << ","; |
574 | 5.96k | } |
575 | 5.25k | f << "],"; |
576 | 5.25k | input->seek(pos+20, librevenge::RVNG_SEEK_SET); |
577 | 5.25k | if (numCols > 1) { |
578 | 196 | f << "colsS=["; |
579 | 905 | for (int i = 0; i < numCols-1; i++) { |
580 | 709 | val = static_cast<int>(input->readULong(2)); |
581 | 709 | f << input->readULong(2); |
582 | 709 | if (val) f << ":" << val << ","; |
583 | 709 | } |
584 | 196 | f << "],"; |
585 | 196 | } |
586 | 5.25k | input->seek(pos+36, librevenge::RVNG_SEEK_SET); |
587 | 5.25k | val = static_cast<int>(input->readLong(2)); |
588 | 5.25k | if (val) f << "unkn=" << val << ","; |
589 | 5.25k | ascii().addPos(pos); |
590 | 5.25k | ascii().addNote(f.str().c_str()); |
591 | | |
592 | 5.25k | pos=input->tell(); |
593 | 5.25k | input->seek(pos+214, librevenge::RVNG_SEEK_SET); |
594 | 5.25k | ascii().addPos(pos); |
595 | 5.25k | ascii().addNote("DocHeader-3"); |
596 | | |
597 | 5.25k | pos=input->tell(); // only 0? |
598 | 5.25k | input->seek(pos+256, librevenge::RVNG_SEEK_SET); |
599 | 5.25k | ascii().addPos(pos); |
600 | 5.25k | ascii().addNote("DocHeader-4"); |
601 | | |
602 | 5.25k | pos=input->tell(); |
603 | 5.25k | input->seek(pos+190, librevenge::RVNG_SEEK_SET); |
604 | 5.25k | ascii().addPos(pos); |
605 | 5.25k | ascii().addNote("DocHeader-5"); |
606 | | |
607 | 5.25k | pos=input->tell(); // only 0? |
608 | 5.25k | input->seek(pos+256, librevenge::RVNG_SEEK_SET); |
609 | 5.25k | ascii().addPos(pos); |
610 | 5.25k | ascii().addNote("DocHeader-6"); |
611 | | |
612 | 5.25k | pos=input->tell(); |
613 | 5.25k | input->seek(pos+256+96, librevenge::RVNG_SEEK_SET); |
614 | 5.25k | ascii().addPos(pos); |
615 | 5.25k | ascii().addNote("DocHeader-7"); |
616 | | |
617 | 5.25k | pos=input->tell(); |
618 | 5.25k | f.str(""); |
619 | 5.25k | f << "DocHeader-8:"; |
620 | 5.25k | input->seek(pos+111, librevenge::RVNG_SEEK_SET); |
621 | 5.25k | val=static_cast<int>(input->readLong(1)); |
622 | 5.25k | if (val==1) { |
623 | 1.02k | f << "slide,"; |
624 | 1.02k | m_state->m_displayAsSlide=true; |
625 | 1.02k | } |
626 | 4.23k | else if (val) { |
627 | 1.63k | MWAW_DEBUG_MSG(("ClarisDrawParser::readDocHeader: pb reading the viewer style\n")); |
628 | 1.63k | f << "###slide=" << val << ","; |
629 | 1.63k | } |
630 | 5.25k | input->seek(pos+150, librevenge::RVNG_SEEK_SET); |
631 | 5.25k | ascii().addPos(pos); |
632 | 5.25k | ascii().addNote(f.str().c_str()); |
633 | | |
634 | 5.25k | pos=input->tell(); |
635 | 5.25k | input->seek(pos+130, librevenge::RVNG_SEEK_SET); |
636 | 5.25k | ascii().addPos(pos); |
637 | 5.25k | ascii().addNote("DocHeader-9"); |
638 | | |
639 | 5.25k | pos=input->tell(); |
640 | 5.25k | ascii().addPos(pos); |
641 | 5.25k | ascii().addNote("DocHeader-A"); |
642 | | |
643 | 5.25k | input->seek(0x80A, librevenge::RVNG_SEEK_SET); |
644 | | // now 25 zones |
645 | 66.2k | for (int i=0; i<25; ++i) { |
646 | 64.2k | if (input->isEnd()) |
647 | 128 | return false; |
648 | 64.0k | pos=input->tell(); |
649 | 64.0k | auto zoneSz=long(input->readULong(4)); |
650 | 64.0k | if (!zoneSz) { |
651 | 36.0k | ascii().addPos(pos); |
652 | 36.0k | ascii().addNote("_"); |
653 | 36.0k | continue; |
654 | 36.0k | } |
655 | 28.0k | if (!input->checkPosition(pos+4+zoneSz)) { |
656 | 3.04k | MWAW_DEBUG_MSG(("ClarisDrawParser::readDocHeader: can not find zone %d\n", i+1)); |
657 | 3.04k | ascii().addPos(pos); |
658 | 3.04k | ascii().addNote("###"); |
659 | 3.04k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
660 | 3.04k | return true; |
661 | 3.04k | } |
662 | 24.9k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
663 | 24.9k | bool done=false; |
664 | 24.9k | switch (i+1) { |
665 | 2.39k | case 1: |
666 | 2.39k | done=m_textParser->readParagraphs(); |
667 | 2.39k | break; |
668 | 2.08k | case 2: |
669 | 2.08k | done=readPrintInfo(); |
670 | 2.08k | break; |
671 | 200 | case 3: |
672 | 200 | done=m_styleManager->readPatternList(); |
673 | 200 | break; |
674 | 1.10k | case 4: |
675 | 1.10k | done=m_styleManager->readGradientList(); |
676 | 1.10k | break; |
677 | 2.05k | case 6: |
678 | 2.05k | done=m_styleManager->readFontStyles(); |
679 | 2.05k | break; |
680 | 1.80k | case 8: // never seens data: fieldData=4, headerSize=14 (always 1,5,0,100,101,0,101,0,1,12710?) |
681 | 1.80k | done = ClarisWksStruct::readStructZone(*getParserState(), "Zone8A", false); |
682 | 1.80k | break; |
683 | 1.80k | case 9: // never seens data: fieldData=12, headerSize=4 (1,id) |
684 | 1.80k | done = ClarisWksStruct::readStructZone(*getParserState(), "Zone9A", false); |
685 | 1.80k | break; |
686 | 1.79k | case 10: // never seens data: fieldData=4, headerSize=4 (1,id) |
687 | 1.79k | done = ClarisWksStruct::readStructZone(*getParserState(), "Zone10A", false); |
688 | 1.79k | break; |
689 | | // CHECKME |
690 | 1.76k | case 16: // Arrow |
691 | 1.76k | done=m_styleManager->readArrows(); |
692 | 1.76k | break; |
693 | 1.76k | case 17: // Dash |
694 | 1.76k | done=m_styleManager->readDashs(); |
695 | 1.76k | break; |
696 | 1.68k | case 18: // Ruler style |
697 | 1.68k | done=m_styleManager->readRulers(); |
698 | 1.68k | break; |
699 | 901 | case 20: |
700 | 901 | done = m_graphParser->readTransformations(); |
701 | 901 | break; |
702 | 1.64k | case 21: // fieldData=36 |
703 | 1.64k | done = ClarisWksStruct::readStructZone(*getParserState(), "Zone21A", false); |
704 | 1.64k | break; |
705 | 1.63k | case 22: // fieldData=4, headerSize=4 (1, consecutive id) |
706 | 1.63k | done = ClarisWksStruct::readStructZone(*getParserState(), "Zone22A", false); |
707 | 1.63k | break; |
708 | 2.32k | default: |
709 | 2.32k | break; |
710 | 24.9k | } |
711 | 24.9k | if (done) continue; |
712 | 4.23k | f.str(""); |
713 | 4.23k | f << "Entries(Zone" << i+1 << "A):"; |
714 | 4.23k | ascii().addPos(pos); |
715 | 4.23k | ascii().addNote(f.str().c_str()); |
716 | 4.23k | input->seek(pos+4+zoneSz, librevenge::RVNG_SEEK_SET); |
717 | 4.23k | } |
718 | | |
719 | 2.08k | pos=input->tell(); |
720 | 2.08k | if (!readDocInfo()) { |
721 | 33 | input->seek(pos, librevenge::RVNG_SEEK_SET); |
722 | 33 | return true; |
723 | 33 | } |
724 | 2.05k | pos=input->tell(); |
725 | 2.05k | if (!readLayouts()) { |
726 | 118 | MWAW_DEBUG_MSG(("ClarisDrawParser::readDocHeader: can not find layout zone\n")); |
727 | 118 | input->seek(pos, librevenge::RVNG_SEEK_SET); |
728 | 118 | return true; |
729 | 118 | } |
730 | 1.93k | pos=input->tell(); |
731 | 1.93k | input->seek(pos+4, librevenge::RVNG_SEEK_SET); |
732 | 1.93k | if (input->readULong(2)!=0x100) { |
733 | 740 | MWAW_DEBUG_MSG(("ClarisDrawParser::readDocHeader: can not find UnknZone zone\n")); |
734 | 740 | input->seek(pos, librevenge::RVNG_SEEK_SET); |
735 | 740 | return true; |
736 | 740 | } |
737 | 1.19k | ascii().addPos(pos); |
738 | 1.19k | ascii().addNote("Entries(UnknZone0)"); |
739 | 1.19k | input->seek(pos+832, librevenge::RVNG_SEEK_SET); |
740 | | |
741 | | // now 12 zones |
742 | 13.1k | for (int i=0; i<12; ++i) { |
743 | 12.3k | if (input->isEnd()) |
744 | 15 | return false; |
745 | 12.3k | pos=input->tell(); |
746 | 12.3k | auto zoneSz=long(input->readULong(4)); |
747 | 12.3k | if (!zoneSz) { |
748 | 8.77k | ascii().addPos(pos); |
749 | 8.77k | ascii().addNote("_"); |
750 | 8.77k | continue; |
751 | 8.77k | } |
752 | 3.57k | if (!input->checkPosition(pos+4+zoneSz)) { |
753 | 445 | MWAW_DEBUG_MSG(("ClarisDrawParser::readDocHeader: can not find zone %d\n", i+1)); |
754 | 445 | ascii().addPos(pos); |
755 | 445 | ascii().addNote("###"); |
756 | 445 | input->seek(pos, librevenge::RVNG_SEEK_SET); |
757 | 445 | return true; |
758 | 445 | } |
759 | 3.13k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
760 | 3.13k | bool done=false; |
761 | 3.13k | switch (i+1) { |
762 | 979 | case 1: // never seens data: fieldData=4, headerSize=4 (1,id) |
763 | 979 | done = ClarisWksStruct::readStructZone(*getParserState(), "ZoneB1A", false); |
764 | 979 | break; |
765 | 946 | case 3: // never seens data: fieldData=6, headerSize=0 |
766 | 946 | done = ClarisWksStruct::readStructZone(*getParserState(), "ZoneB3A", false); |
767 | 946 | break; |
768 | 21 | case 4:// never seens data: fieldData=14, headerSize=0 |
769 | 21 | done = ClarisWksStruct::readStructZone(*getParserState(), "ZoneB4A", false); |
770 | 21 | break; |
771 | 28 | case 5:// never seens data: fieldData=14, headerSize=0 |
772 | 28 | done = ClarisWksStruct::readStructZone(*getParserState(), "ZoneB5A", false); |
773 | 28 | break; |
774 | 34 | case 6:// never seens data: fieldData=8, headerSize=80 |
775 | 34 | done = ClarisWksStruct::readStructZone(*getParserState(), "ZoneB6A", false); |
776 | 34 | break; |
777 | 27 | case 7:// never seens data: fieldData=28, headerSize=80 |
778 | 27 | done = ClarisWksStruct::readStructZone(*getParserState(), "ZoneB7A", false); |
779 | 27 | break; |
780 | 30 | case 8:// never seens data: fieldData=1e, headerSize=0 |
781 | 30 | done = ClarisWksStruct::readStructZone(*getParserState(), "ZoneB8A", false); |
782 | 30 | break; |
783 | 64 | case 9:// TODO: fieldData=1c (2*double+), headerSize=0 |
784 | 64 | done = ClarisWksStruct::readStructZone(*getParserState(), "ZoneB9A", false); |
785 | 64 | break; |
786 | 924 | case 10: |
787 | 924 | done = m_styleManager->readColorList(); |
788 | 924 | break; |
789 | 25 | case 11:// never seens data: fieldData=c, headerSize=0 |
790 | 25 | done = ClarisWksStruct::readStructZone(*getParserState(), "ZoneB11A", false); |
791 | 25 | break; |
792 | 26 | case 12:// never seens data: fieldData=32, headerSize=0 |
793 | 26 | done = ClarisWksStruct::readStructZone(*getParserState(), "ZoneB12A", false); |
794 | 26 | break; |
795 | 30 | default: |
796 | 30 | break; |
797 | 3.13k | } |
798 | 3.13k | if (done) continue; |
799 | 415 | f.str(""); |
800 | 415 | f << "Entries(ZoneB" << i+1 << "A):"; |
801 | 415 | ascii().addPos(pos); |
802 | 415 | ascii().addNote(f.str().c_str()); |
803 | 415 | input->seek(pos+4+zoneSz, librevenge::RVNG_SEEK_SET); |
804 | 415 | } |
805 | 732 | pos=input->tell(); |
806 | 732 | f.str(""); |
807 | 732 | f << "Entries(NDSET):"; |
808 | 732 | m_state->m_numDSET=static_cast<int>(input->readLong(2)); |
809 | 732 | if (m_state->m_numDSET) f << "num=" << m_state->m_numDSET << ","; |
810 | 732 | ascii().addPos(pos); |
811 | 732 | ascii().addNote(f.str().c_str()); |
812 | | |
813 | 732 | return true; |
814 | 1.19k | } |
815 | | |
816 | | bool ClarisDrawParser::readLibraryHeader() |
817 | 25.3k | { |
818 | 25.3k | MWAWInputStreamPtr input = getInput(); |
819 | 25.3k | libmwaw::DebugStream f; |
820 | 25.3k | f << "Entries(LibHeader):"; |
821 | 25.3k | if (!input->checkPosition(846)) return false; |
822 | 25.3k | input->seek(8, librevenge::RVNG_SEEK_SET); |
823 | 25.3k | long val=input->readLong(4); // always 0 |
824 | 25.3k | if (val) f << "f0=" << val << ","; |
825 | 25.3k | f << "ID=" << std::hex << input->readULong(4) << std::dec << ","; // a big number |
826 | 25.3k | val=input->readLong(2); // always 0x100 |
827 | 25.3k | if (val!=0x100) f << "f1=" << val << ","; |
828 | 151k | for (int i=0; i<5; ++i) { // always 0 |
829 | 126k | val=input->readLong(2); |
830 | 126k | if (val) f << "f" << i+2 << "=" << val << ","; |
831 | 126k | } |
832 | 25.3k | auto N=static_cast<int>(input->readLong(2)); // checkme: the number of graphics ? |
833 | 25.3k | if (N) f << "N=" << N << ","; |
834 | 75.9k | for (long i=0; i<2; ++i) { // always 0,1 |
835 | 50.6k | val=input->readLong(2); |
836 | 50.6k | if (val!=i) f << "f" << i+7 << "=" << val << ","; |
837 | 50.6k | } |
838 | 25.3k | f << "ID1=["; |
839 | 75.9k | for (int i=0; i<2; ++i) { // two big number |
840 | 50.6k | f << std::hex << input->readULong(4) << std::dec << ","; |
841 | 50.6k | } |
842 | 25.3k | f << "],"; |
843 | 25.3k | val=input->readLong(2); // always 0x100 |
844 | 25.3k | if (val!=0x100) f << "f9=" << val << ","; |
845 | 25.3k | val=input->readLong(2); // always 0 |
846 | 25.3k | if (val) f << "f10=" << val << ","; |
847 | 25.3k | f << "ID2=" << std::hex << input->readULong(4) << std::dec << ","; // another big number |
848 | 1.44M | for (int i=0; i<56; ++i) { // always 0 |
849 | 1.41M | val=input->readLong(2); |
850 | 1.41M | if (val) f << "g" << i << "=" << val << ","; |
851 | 1.41M | } |
852 | 25.3k | ascii().addPos(8); |
853 | 25.3k | ascii().addNote(f.str().c_str()); |
854 | | |
855 | 25.3k | long pos=input->tell(); |
856 | 25.3k | f.str(""); |
857 | 25.3k | f << "LibHeader-A:"; |
858 | 75.9k | for (int i=0; i<2; ++i) { // f1=54,5c|5d |
859 | 50.6k | val=input->readLong(2); |
860 | 50.6k | if (val) f << "f" << i << "=" << val << ","; |
861 | 50.6k | } |
862 | 25.3k | f << "IDs=["; |
863 | 253k | for (int i=0; i<9; ++i) { // 7 or 9 big number |
864 | 227k | val=long(input->readULong(4)); |
865 | 227k | if (val) |
866 | 182k | f << std::hex << val << std::dec << ","; |
867 | 45.8k | else |
868 | 45.8k | f << "_,"; |
869 | 227k | } |
870 | 25.3k | f << "],"; |
871 | 177k | for (int i=0; i<6; ++i) { // always 0 |
872 | 151k | val=input->readLong(2); |
873 | 151k | if (val) f << "f" << i+2 << "=" << val << ","; |
874 | 151k | } |
875 | 75.9k | for (int i=0; i<2; ++i) { |
876 | 50.6k | f << "unkn" << i << "=["; |
877 | 151k | for (int j=0; j<2; ++j) { // _, small number |
878 | 101k | val=input->readLong(2); |
879 | 101k | if (val) |
880 | 70.2k | f << val << ","; |
881 | 31.0k | else |
882 | 31.0k | f << "_,"; |
883 | 101k | } |
884 | 50.6k | f << std::hex << input->readULong(4) << std::dec << ","; // big number or 0 |
885 | 50.6k | f << "],"; |
886 | 50.6k | } |
887 | 683k | for (int i=0; i<26; ++i) { // always 0 |
888 | 658k | val=input->readLong(2); |
889 | 658k | if (val) f << "g" << i << "=" << val << ","; |
890 | 658k | } |
891 | 25.3k | ascii().addPos(pos); |
892 | 25.3k | ascii().addNote(f.str().c_str()); |
893 | | |
894 | 25.3k | pos=input->tell(); |
895 | 25.3k | f.str(""); |
896 | 25.3k | f << "LibHeader-B:"; |
897 | 25.3k | auto fSz=static_cast<int>(input->readULong(1)); |
898 | 25.3k | if (fSz>63) { |
899 | 8.22k | MWAW_DEBUG_MSG(("ClarisDrawParser::readLibraryHeader: string size seems bad\n")); |
900 | 8.22k | f << "##fSz=" << fSz << ","; |
901 | 8.22k | fSz=0; |
902 | 8.22k | } |
903 | 25.3k | std::string text(""); |
904 | 131k | for (int i=0; i<fSz; ++i) text+=char(input->readULong(1)); |
905 | 25.3k | f << "filename=" << text << ","; |
906 | 25.3k | input->seek(pos+64, librevenge::RVNG_SEEK_SET); |
907 | 2.45M | for (int i=0; i<96; ++i) { // always 0 |
908 | 2.43M | val=input->readLong(2); |
909 | 2.43M | if (val) f << "f" << i << "=" << val << ","; |
910 | 2.43M | } |
911 | 25.3k | val=static_cast<int>(input->readULong(1)); // always filename size ? |
912 | 25.3k | if (val!=fSz) f << "#fSz1=" << fSz << ","; |
913 | 25.3k | val=static_cast<int>(input->readULong(1)); // always 0? |
914 | 25.3k | if (val) f << "f96=" << val << ","; |
915 | 25.3k | f << "ID=" << std::hex << input->readULong(4) << std::dec << ","; // big number |
916 | 25.3k | val=static_cast<int>(input->readLong(2)); // 0 | 0fcc |
917 | 25.3k | if (val) f << "g0=" << val << ","; |
918 | 25.3k | val=static_cast<int>(input->readULong(2)); // 80[89]3 |
919 | 25.3k | if (val) f << "fl=" << std::hex << val << std::dec << ","; |
920 | 25.3k | val=static_cast<int>(input->readLong(2)); // 0 |
921 | 25.3k | if (val) f << "g1=" << val << ","; |
922 | 25.3k | val=static_cast<int>(input->readULong(1)); // always filename size ? |
923 | 25.3k | if (val!=fSz) f << "#fSz2=" << fSz << ","; |
924 | 25.3k | val=static_cast<int>(input->readULong(1)); // always 0? |
925 | 25.3k | if (val) f << "g2=" << val << ","; |
926 | 25.3k | ascii().addPos(pos); |
927 | 25.3k | ascii().addNote(f.str().c_str()); |
928 | | |
929 | 25.3k | pos=input->tell(); |
930 | 25.3k | f.str(""); |
931 | 25.3k | f << "LibHeader-C:"; |
932 | 25.3k | fSz=static_cast<int>(input->readULong(1)); |
933 | 25.3k | if (fSz>63) { |
934 | 7.21k | MWAW_DEBUG_MSG(("ClarisDrawParser::readLibraryHeader: string size seems bad\n")); |
935 | 7.21k | f << "##fSz=" << fSz << ","; |
936 | 7.21k | fSz=0; |
937 | 7.21k | } |
938 | 25.3k | text=""; |
939 | 129k | for (int i=0; i<fSz; ++i) text+=char(input->readULong(1)); |
940 | 25.3k | f << "author?=" << text << ","; |
941 | 25.3k | input->seek(pos+64, librevenge::RVNG_SEEK_SET); |
942 | 2.45M | for (int i=0; i<96; ++i) { // always 0 |
943 | 2.43M | val=input->readLong(2); |
944 | 2.43M | if (val) f << "f" << i << "=" << val << ","; |
945 | 2.43M | } |
946 | 25.3k | ascii().addPos(pos); |
947 | 25.3k | ascii().addNote(f.str().c_str()); |
948 | | |
949 | 25.3k | pos=input->tell(); |
950 | 25.3k | f.str(""); |
951 | 25.3k | f << "LibHeader-D:"; |
952 | 430k | for (int i=0; i<16; ++i) { |
953 | 405k | val=static_cast<int>(input->readLong(2)); |
954 | 405k | static int const expected[]= {4,2,0/*35 or 3f*/,48, 9, 0/*78 or 8x*/, 0x42, 18, |
955 | 405k | 3, 0xd4, 0/*7b or 8e*/, 0x57, 3, 0xc4, 0/*7b or 8f*/, 0 |
956 | 405k | }; |
957 | 405k | if (val!=expected[i]) |
958 | 361k | f << "f" << i << "=" << val << ","; |
959 | 405k | } |
960 | 25.3k | int dim[2]; |
961 | 50.6k | for (auto &i : dim) i=static_cast<int>(input->readLong(2)); |
962 | 25.3k | f << "dim=" << MWAWVec2i(dim[0],dim[1]) << ","; // 64x64 or 72x72 |
963 | 25.3k | m_state->m_numDSET=static_cast<int>(input->readLong(2)); |
964 | 25.3k | if (m_state->m_numDSET) f << "num[DSET]=" << m_state->m_numDSET << ","; |
965 | 25.3k | ascii().addPos(pos); |
966 | 25.3k | ascii().addNote(f.str().c_str()); |
967 | | |
968 | 25.3k | input->seek(846, librevenge::RVNG_SEEK_SET); |
969 | | // the style are coded after the DSET zones, let try to find them |
970 | 25.3k | input->seek(-44, librevenge::RVNG_SEEK_END); |
971 | 5.07M | while (input->tell()>=846) { |
972 | 5.06M | pos=input->tell(); |
973 | 5.06M | auto c=static_cast<int>(input->readULong(1)); |
974 | 5.06M | bool find=false; |
975 | 5.06M | switch (c) { |
976 | 50.2k | case 0x44: |
977 | 50.2k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
978 | 50.2k | if (readDSET(pos==846)) |
979 | 23.8k | find=true; |
980 | 26.4k | else |
981 | 26.4k | input->seek(pos-4, librevenge::RVNG_SEEK_SET); |
982 | 50.2k | break; |
983 | 24.7k | case 0x53: |
984 | 24.7k | input->seek(pos-1, librevenge::RVNG_SEEK_SET); |
985 | 24.7k | break; |
986 | 25.7k | case 0x45: |
987 | 25.7k | input->seek(pos-2, librevenge::RVNG_SEEK_SET); |
988 | 25.7k | break; |
989 | 17.7k | case 0x54: |
990 | 17.7k | input->seek(pos-3, librevenge::RVNG_SEEK_SET); |
991 | 17.7k | break; |
992 | 4.95M | default: |
993 | 4.95M | input->seek(pos-4, librevenge::RVNG_SEEK_SET); |
994 | 4.95M | break; |
995 | 5.06M | } |
996 | 5.06M | if (!find) |
997 | 5.04M | continue; |
998 | 23.8k | m_state->m_EOF=input->tell(); |
999 | | // clean storage |
1000 | 23.8k | m_graphParser->resetState(); |
1001 | 23.8k | m_textParser->resetState(); |
1002 | 23.8k | m_state->m_zonesMap.clear(); |
1003 | 23.8k | m_state->m_zoneIdToFileTypeMap.clear(); |
1004 | 46.4k | while (!input->isEnd()) { |
1005 | 45.1k | pos=input->tell(); |
1006 | 45.1k | if (input->readULong(4)) { |
1007 | 22.4k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1008 | 22.4k | break; |
1009 | 22.4k | } |
1010 | 22.6k | ascii().addPos(pos); |
1011 | 22.6k | ascii().addNote("_"); |
1012 | 22.6k | } |
1013 | 23.8k | pos=input->tell(); |
1014 | 23.8k | bool ok=true; |
1015 | 23.8k | if (!m_textParser->readParagraphs()) { |
1016 | 23.0k | MWAW_DEBUG_MSG(("ClarisDrawParser::readLibraryHeader: can not read the paragraph style\n")); |
1017 | 23.0k | ascii().addPos(pos); |
1018 | 23.0k | ascii().addNote("Entries(RULR):###"); |
1019 | 23.0k | ok=false; |
1020 | 23.0k | } |
1021 | 28.2k | for (int i=0; ok && i<20; ++i) { |
1022 | 5.13k | pos=input->tell(); |
1023 | 5.13k | auto dSz=long(input->readULong(4)); |
1024 | 5.13k | if (!dSz) { |
1025 | 3.03k | ascii().addPos(pos); |
1026 | 3.03k | ascii().addNote("_"); |
1027 | 3.03k | continue; |
1028 | 3.03k | } |
1029 | 2.09k | if (!input->checkPosition(pos+4+dSz)) { |
1030 | 647 | MWAW_DEBUG_MSG(("ClarisDrawParser::readLibraryHeader: can not find style zone %d\n", i+1)); |
1031 | 647 | ascii().addPos(pos); |
1032 | 647 | ascii().addNote("###"); |
1033 | 647 | break; |
1034 | 647 | } |
1035 | 1.45k | bool done=false; |
1036 | 1.45k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1037 | 1.45k | switch (i+1) { |
1038 | 96 | case 1: |
1039 | 96 | done=m_styleManager->readArrows(); |
1040 | 96 | break; |
1041 | 71 | case 2: |
1042 | 71 | done=m_styleManager->readDashs(); |
1043 | 71 | break; |
1044 | 210 | case 3: |
1045 | 210 | done=m_styleManager->readPatternList(); |
1046 | 210 | break; |
1047 | 79 | case 4: |
1048 | 79 | done=m_styleManager->readGradientList(); |
1049 | 79 | break; |
1050 | 271 | case 5: |
1051 | 271 | done = m_graphParser->readTransformations(); |
1052 | 271 | break; |
1053 | 132 | case 6: |
1054 | 132 | done = m_styleManager->readRulers(); |
1055 | 132 | break; |
1056 | 182 | case 7: // two zones: pos and names |
1057 | 182 | done = readLibraryNames(); |
1058 | 182 | break; |
1059 | 100 | case 8: |
1060 | 100 | done = m_styleManager->readColorList(); |
1061 | 100 | break; |
1062 | 49 | case 9: // maybe zone 24 |
1063 | 49 | done = ClarisWksStruct::readStructZone(*getParserState(), "Style10A", false); |
1064 | 49 | break; |
1065 | 45 | case 10: // maybe zone 25 |
1066 | 45 | done = ClarisWksStruct::readStructZone(*getParserState(), "Style11A", false); |
1067 | 45 | break; |
1068 | 31 | case 11: // maybe readfontnames without header |
1069 | 31 | done = ClarisWksStruct::readStructZone(*getParserState(), "Style12A", false); |
1070 | 31 | break; |
1071 | 185 | default: |
1072 | 185 | break; |
1073 | 1.45k | } |
1074 | 1.45k | if (done) continue; |
1075 | 1.27k | f.str(""); |
1076 | 1.27k | f << "Entries(Style" << i+1 << "A):"; |
1077 | 1.27k | ascii().addPos(pos); |
1078 | 1.27k | ascii().addNote(f.str().c_str()); |
1079 | 1.27k | input->seek(pos+4+dSz, librevenge::RVNG_SEEK_SET); |
1080 | 1.27k | } |
1081 | 23.8k | break; |
1082 | 23.8k | } |
1083 | 25.3k | input->seek(846, librevenge::RVNG_SEEK_SET); |
1084 | 25.3k | if (!readDSET(true)) { |
1085 | 24.7k | MWAW_DEBUG_MSG(("ClarisDrawParser::readLibraryHeader:can not read main group\n")); |
1086 | 24.7k | input->seek(846, librevenge::RVNG_SEEK_SET); |
1087 | 24.7k | } |
1088 | 25.3k | return true; |
1089 | 25.3k | } |
1090 | | |
1091 | | //////////////////////////////////////////////////////////// |
1092 | | // read the header |
1093 | | //////////////////////////////////////////////////////////// |
1094 | | bool ClarisDrawParser::checkHeader(MWAWHeader *header, bool /*strict*/) |
1095 | 99.2k | { |
1096 | 99.2k | *m_state = ClarisDrawParserInternal::State(); |
1097 | 99.2k | MWAWInputStreamPtr input = getInput(); |
1098 | 99.2k | if (!input || !input->hasDataFork() || !input->checkPosition(846)) |
1099 | 246 | return false; |
1100 | | |
1101 | 99.0k | libmwaw::DebugStream f; |
1102 | 99.0k | f << "FileHeader:"; |
1103 | 99.0k | input->seek(0, librevenge::RVNG_SEEK_SET); |
1104 | 99.0k | auto val=static_cast<int>(input->readULong(1)); |
1105 | 99.0k | if (val==0x2) { |
1106 | 81.6k | m_state->m_isLibrary=true; |
1107 | 81.6k | f << "lib,"; |
1108 | 81.6k | } |
1109 | 17.3k | else if (val==0x1) { |
1110 | 17.2k | if (!input->checkPosition(0x80A)) |
1111 | 67 | return false; |
1112 | 17.2k | } |
1113 | 72 | else |
1114 | 72 | return false; |
1115 | 98.8k | val=static_cast<int>(input->readULong(2)); // a3-b1 |
1116 | 98.8k | if (val) f << "f0=" << std::hex << val << std::dec << ","; |
1117 | 98.8k | if (input->readULong(1) || input->readULong(4) != 0x45585057) return false; |
1118 | 98.7k | int vers=1; |
1119 | 98.7k | setVersion(vers); |
1120 | 98.7k | m_state->m_version=vers; |
1121 | 98.7k | if (header) |
1122 | 37.5k | header->reset(MWAWDocument::MWAW_T_CLARISDRAW, vers, MWAWDocument::MWAW_K_DRAW); |
1123 | 98.7k | input->seek(8,librevenge::RVNG_SEEK_SET); |
1124 | 98.7k | ascii().addPos(0); |
1125 | 98.7k | ascii().addNote(f.str().c_str()); |
1126 | | |
1127 | 98.7k | return true; |
1128 | 98.8k | } |
1129 | | |
1130 | | //////////////////////////////////////////////////////////// |
1131 | | // read the layout |
1132 | | //////////////////////////////////////////////////////////// |
1133 | | bool ClarisDrawParser::readLayouts() |
1134 | 2.05k | { |
1135 | 2.05k | MWAWInputStreamPtr input = getInput(); |
1136 | 2.05k | long pos=input->tell(); |
1137 | 2.05k | libmwaw::DebugFile &ascFile = ascii(); |
1138 | 2.05k | libmwaw::DebugStream f; |
1139 | 2.05k | f << "Entries(Layout):"; |
1140 | 2.05k | ClarisWksStruct::Struct header; |
1141 | 2.05k | if (!header.readHeader(input,true)) { |
1142 | 118 | MWAW_DEBUG_MSG(("ClarisDrawParser::readLayouts: the data size seems bad\n")); |
1143 | 118 | f << "###"; |
1144 | 118 | ascFile.addPos(pos); |
1145 | 118 | ascFile.addNote(f.str().c_str()); |
1146 | 118 | return false; |
1147 | 118 | } |
1148 | 1.93k | if (header.m_size==0) { |
1149 | 342 | ascFile.addPos(pos); |
1150 | 342 | ascFile.addNote("_"); |
1151 | 342 | return true; |
1152 | 342 | } |
1153 | 1.59k | long endPos = pos+4+header.m_size; |
1154 | 1.59k | f << header; |
1155 | 1.59k | if (header.m_headerSize) { |
1156 | 7 | ascFile.addDelimiter(input->tell(),'|'); |
1157 | 7 | input->seek(header.m_headerSize, librevenge::RVNG_SEEK_CUR); |
1158 | 7 | } |
1159 | 1.59k | ascFile.addPos(pos); |
1160 | 1.59k | ascFile.addNote(f.str().c_str()); |
1161 | | |
1162 | 1.59k | pos=input->tell(); |
1163 | 1.59k | if (header.m_dataSize!=336) { |
1164 | 14 | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
1165 | 14 | MWAW_DEBUG_MSG(("ClarisDrawParser::readLayouts: no sure how to read the data\n")); |
1166 | 14 | ascFile.addPos(pos); |
1167 | 14 | ascFile.addNote("Layout:###"); |
1168 | 14 | return true; |
1169 | 14 | } |
1170 | 7.05k | for (long i=0; i<header.m_numData; ++i) { |
1171 | 5.47k | pos=input->tell(); |
1172 | 5.47k | ClarisDrawParserInternal::Layer layer; |
1173 | 5.47k | f.str(""); |
1174 | 5.47k | f << "Layout-A" << i << ":"; |
1175 | 5.47k | auto cSz=static_cast<int>(input->readULong(1)); |
1176 | 5.47k | librevenge::RVNGString name(""); |
1177 | 100k | for (int c=0; c<cSz; ++c) { |
1178 | 95.2k | auto ch=char(input->readULong(1)); |
1179 | 95.2k | if (!ch) continue; |
1180 | 75.1k | f << ch; |
1181 | 75.1k | int unicode= getParserState()->m_fontConverter->unicode(3, static_cast<unsigned char>(ch)); |
1182 | 75.1k | if (unicode==-1) |
1183 | 6.37k | name.append(ch); |
1184 | 68.7k | else |
1185 | 68.7k | libmwaw::appendUnicode(static_cast<uint32_t>(unicode), name); |
1186 | 75.1k | } |
1187 | 5.47k | f << ","; |
1188 | 5.47k | layer.m_name=name; |
1189 | 5.47k | ascFile.addPos(pos); |
1190 | 5.47k | ascFile.addNote(f.str().c_str()); |
1191 | | |
1192 | 5.47k | input->seek(pos+256, librevenge::RVNG_SEEK_SET); |
1193 | 5.47k | pos=input->tell(); |
1194 | 5.47k | f.str(""); |
1195 | 5.47k | f << "Layout-B" << i << ":"; |
1196 | 5.47k | auto val=static_cast<int>(input->readULong(1)); // always 40|80 |
1197 | 5.47k | if (val&0x80) { |
1198 | 194 | f << "hidden,"; |
1199 | 194 | layer.m_isHidden=true; |
1200 | 194 | } |
1201 | 5.47k | val &=0x7F; |
1202 | 5.47k | if (val!=0x40) f << "fl0=" << std::hex << val << std::dec << ","; |
1203 | 5.47k | val=static_cast<int>(input->readULong(1)); // 0|1|2|6c|d8|fc|ff |
1204 | 5.47k | if (val) f << "fl1=" << std::hex << val << std::dec << ","; |
1205 | 16.4k | for (int j=0; j<2; ++j) { // always 0 |
1206 | 10.9k | val=static_cast<int>(input->readULong(2)); |
1207 | 10.9k | if (val) f << "f" << j << "=" << val << ","; |
1208 | 10.9k | } |
1209 | 5.47k | layer.m_groupId=static_cast<int>(input->readULong(2)); |
1210 | 5.47k | f << "id[group]=" << layer.m_groupId << ","; |
1211 | 5.47k | val=static_cast<int>(input->readLong(4)); |
1212 | 5.47k | if (val==-1) |
1213 | 2 | f << "locked,"; |
1214 | 5.47k | else if (val) |
1215 | 1.81k | f << "#lock=" << val << ","; |
1216 | 93.1k | for (int j=0; j<16; ++j) { // always 0 |
1217 | 87.6k | val=static_cast<int>(input->readULong(4)); |
1218 | 87.6k | if (val) f << "g" << j << "=" << val << ","; |
1219 | 87.6k | } |
1220 | 5.47k | val=static_cast<int>(input->readULong(4)); |
1221 | 5.47k | if (val) f << "ID=" << std::hex << val << std::dec << ","; |
1222 | 5.47k | ascFile.addPos(pos); |
1223 | 5.47k | ascFile.addNote(f.str().c_str()); |
1224 | 5.47k | input->seek(pos+80, librevenge::RVNG_SEEK_SET); |
1225 | 5.47k | m_state->m_layerList.push_back(layer); |
1226 | 5.47k | } |
1227 | 1.57k | return true; |
1228 | 1.59k | } |
1229 | | |
1230 | | bool ClarisDrawParser::readLibraryNames() |
1231 | 182 | { |
1232 | 182 | MWAWInputStreamPtr input = getInput(); |
1233 | 182 | long pos=input->tell(); |
1234 | 182 | if (!input->checkPosition(pos+8)) return false; |
1235 | 171 | libmwaw::DebugFile &ascFile = ascii(); |
1236 | 171 | libmwaw::DebugStream f; |
1237 | 171 | f << "Entries(LibraryName):"; |
1238 | 171 | ClarisWksStruct::Struct header; |
1239 | 171 | if (!header.readHeader(input,true)) { |
1240 | 124 | MWAW_DEBUG_MSG(("ClarisDrawParser::readLibraryNames: the data size seems bad\n")); |
1241 | 124 | f << "###"; |
1242 | 124 | ascFile.addPos(pos); |
1243 | 124 | ascFile.addNote(f.str().c_str()); |
1244 | 124 | return false; |
1245 | 124 | } |
1246 | 47 | if (header.m_size==0) { |
1247 | 0 | ascFile.addPos(pos); |
1248 | 0 | ascFile.addNote("_"); |
1249 | 0 | pos=input->tell(); |
1250 | 0 | auto sz = long(input->readULong(4)); |
1251 | 0 | if (!input->checkPosition(pos+4+sz)) { |
1252 | 0 | MWAW_DEBUG_MSG(("ClarisDrawParser::readLibraryNames: the name size seems bad\n")); |
1253 | 0 | f << "###"; |
1254 | 0 | ascFile.addPos(pos); |
1255 | 0 | ascFile.addNote(f.str().c_str()); |
1256 | 0 | return false; |
1257 | 0 | } |
1258 | 0 | if (!sz) { |
1259 | 0 | ascFile.addPos(pos); |
1260 | 0 | ascFile.addNote("_"); |
1261 | 0 | return true; |
1262 | 0 | } |
1263 | 0 | MWAW_DEBUG_MSG(("ClarisDrawParser::readLibraryNames: find a string but no position\n")); |
1264 | 0 | f << "###"; |
1265 | 0 | ascFile.addPos(pos); |
1266 | 0 | ascFile.addNote(f.str().c_str()); |
1267 | 0 | input->seek(pos+4+sz, librevenge::RVNG_SEEK_SET); |
1268 | 0 | return true; |
1269 | 0 | } |
1270 | | |
1271 | 47 | long endPos=pos+4+header.m_size; |
1272 | 47 | f << header; |
1273 | 47 | if (header.m_headerSize) { |
1274 | 1 | ascFile.addDelimiter(input->tell(),'|'); |
1275 | 1 | input->seek(header.m_headerSize, librevenge::RVNG_SEEK_CUR); |
1276 | 1 | } |
1277 | 47 | ascFile.addPos(pos); |
1278 | 47 | ascFile.addNote(f.str().c_str()); |
1279 | | |
1280 | 47 | pos=input->tell(); |
1281 | 47 | if (header.m_dataSize!=4) { |
1282 | 47 | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
1283 | 47 | MWAW_DEBUG_MSG(("ClarisDrawParser::readLibraryNames: no sure how to read the position\n")); |
1284 | 47 | ascFile.addPos(pos); |
1285 | 47 | ascFile.addNote("LibraryName:###"); |
1286 | 47 | return true; |
1287 | 47 | } |
1288 | | |
1289 | 0 | pos=input->tell(); |
1290 | 0 | f.str(""); |
1291 | 0 | f << "LibraryName-pos:"; |
1292 | 0 | std::vector<int> positions, lengths; |
1293 | 0 | for (long i=0; i<header.m_numData; ++i) { |
1294 | 0 | auto sSz=static_cast<int>(input->readULong(2)); |
1295 | 0 | auto position=static_cast<int>(input->readULong(2)); |
1296 | 0 | f << position << ":" << sSz << ","; |
1297 | 0 | positions.push_back(position); |
1298 | 0 | lengths.push_back(sSz); |
1299 | 0 | } |
1300 | 0 | ascFile.addPos(pos); |
1301 | 0 | ascFile.addNote(f.str().c_str()); |
1302 | |
|
1303 | 0 | pos=input->tell(); |
1304 | 0 | f.str(""); |
1305 | 0 | f << "LibraryName-name:"; |
1306 | 0 | auto sz = long(input->readULong(4)); |
1307 | 0 | if (sz==0 || !input->checkPosition(pos+4+sz)) { |
1308 | 0 | MWAW_DEBUG_MSG(("ClarisDrawParser::readLibraryNames: can not find the name\n")); |
1309 | 0 | f << "###"; |
1310 | 0 | ascFile.addPos(pos); |
1311 | 0 | ascFile.addNote(f.str().c_str()); |
1312 | 0 | return false; |
1313 | 0 | } |
1314 | | |
1315 | 0 | for (size_t i=0; i<positions.size(); ++i) { |
1316 | 0 | ClarisDrawParserInternal::Layer layer; |
1317 | 0 | if (positions[i]+lengths[i]>sz) { |
1318 | 0 | MWAW_DEBUG_MSG(("ClarisDrawParser::readLibraryNames: the name %d seems bad\n", int(i))); |
1319 | 0 | f << "###,"; |
1320 | 0 | m_state->m_layerList.push_back(layer); |
1321 | 0 | continue; |
1322 | 0 | } |
1323 | 0 | input->seek(pos+4+positions[i], librevenge::RVNG_SEEK_SET); |
1324 | 0 | librevenge::RVNGString name(""); |
1325 | 0 | for (int c=0; c<lengths[i]; ++c) { |
1326 | 0 | auto ch=char(input->readULong(1)); |
1327 | 0 | if (!ch) continue; |
1328 | 0 | f << ch; |
1329 | 0 | int unicode= getParserState()->m_fontConverter->unicode(3, static_cast<unsigned char>(ch)); |
1330 | 0 | if (unicode==-1) |
1331 | 0 | name.append(ch); |
1332 | 0 | else |
1333 | 0 | libmwaw::appendUnicode(static_cast<uint32_t>(unicode), name); |
1334 | 0 | } |
1335 | 0 | f << ","; |
1336 | 0 | layer.m_name = name; |
1337 | 0 | m_state->m_layerList.push_back(layer); |
1338 | 0 | } |
1339 | 0 | ascFile.addPos(pos); |
1340 | 0 | ascFile.addNote(f.str().c_str()); |
1341 | 0 | input->seek(pos+4+sz, librevenge::RVNG_SEEK_SET); |
1342 | 0 | return true; |
1343 | 0 | } |
1344 | | //////////////////////////////////////////////////////////// |
1345 | | // read the document information |
1346 | | //////////////////////////////////////////////////////////// |
1347 | | bool ClarisDrawParser::readDocInfo() |
1348 | 2.08k | { |
1349 | 2.08k | MWAWInputStreamPtr input = getInput(); |
1350 | 2.08k | libmwaw::DebugStream f; |
1351 | 2.08k | f << "Entries(DocInfo):"; |
1352 | 2.08k | long pos = input->tell(); |
1353 | 2.08k | long endPos=pos+428; |
1354 | 2.08k | if (!input->checkPosition(endPos)) return false; |
1355 | 2.05k | f << "ptr=" << std::hex << input->readULong(4) << std::dec << ","; |
1356 | 2.05k | int val; |
1357 | 14.3k | for (int i = 0; i < 6; i++) { |
1358 | 12.3k | val = static_cast<int>(input->readULong(2)); |
1359 | 12.3k | if (val) f << "f" << i << "=" << std::hex << val << std::dec << ","; |
1360 | 12.3k | } |
1361 | 2.05k | m_state->m_headerId = static_cast<int>(input->readLong(2)); |
1362 | 2.05k | if (m_state->m_headerId) f << "headerId=" << m_state->m_headerId << ","; |
1363 | 2.05k | val = static_cast<int>(input->readLong(2)); |
1364 | 2.05k | if (val) f << "unkn=" << val << ","; |
1365 | 2.05k | m_state->m_footerId = static_cast<int>(input->readLong(2)); |
1366 | 2.05k | if (m_state->m_footerId) f << "footerId=" << m_state->m_footerId << ","; |
1367 | 10.2k | for (int i=0; i < 4; ++i) { |
1368 | 8.20k | val = static_cast<int>(input->readLong(2)); |
1369 | 8.20k | if (val) f << "g" << i << "=" << val << ","; |
1370 | 8.20k | } |
1371 | 2.05k | int pages[2]; |
1372 | 4.10k | for (auto &page : pages) page=static_cast<int>(input->readLong(2)); |
1373 | 2.05k | if (pages[1]>=1 && pages[1] < 1000 && pages[0]>=1 && pages[0]<100) |
1374 | 1.59k | m_state->m_pages=MWAWVec2i(pages[0],pages[1]); |
1375 | 2.05k | if (pages[0]!=1 || pages[1]!=1) |
1376 | 472 | f << "pages[num]=" << pages[0] << "x" << pages[1] << ","; |
1377 | 2.05k | ascii().addDelimiter(input->tell(), '|'); |
1378 | 2.05k | ascii().addPos(pos); |
1379 | 2.05k | ascii().addNote(f.str().c_str()); |
1380 | 2.05k | ascii().addPos(pos+100); |
1381 | 2.05k | ascii().addNote("DocInfo-2"); |
1382 | 2.05k | ascii().addPos(pos+200); |
1383 | 2.05k | ascii().addNote("DocInfo-3"); |
1384 | 2.05k | ascii().addPos(pos+300); |
1385 | 2.05k | ascii().addNote("DocInfo-4"); |
1386 | 2.05k | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
1387 | 2.05k | return true; |
1388 | 2.08k | } |
1389 | | |
1390 | | //////////////////////////////////////////////////////////// |
1391 | | // try to read the print info zone |
1392 | | //////////////////////////////////////////////////////////// |
1393 | | bool ClarisDrawParser::readPrintInfo() |
1394 | 2.08k | { |
1395 | 2.08k | MWAWInputStreamPtr input = getInput(); |
1396 | 2.08k | long pos=input->tell(); |
1397 | 2.08k | long endPos=pos+124; |
1398 | 2.08k | if (input->readULong(4)!=120 || !input->checkPosition(endPos)) { |
1399 | 247 | MWAW_DEBUG_MSG(("ClarisDrawParser::readPrintInfo: file seems too short\n")); |
1400 | 247 | return false; |
1401 | 247 | } |
1402 | 1.83k | libmwaw::DebugStream f; |
1403 | 1.83k | f << "Entries(PrintInfo):"; |
1404 | 1.83k | libmwaw::PrinterInfo info; |
1405 | 1.83k | if (!info.read(input)) { |
1406 | 42 | MWAW_DEBUG_MSG(("ClarisDrawParser::readPrintInfo: can not read print info\n")); |
1407 | 42 | return false; |
1408 | 42 | } |
1409 | 1.79k | f << info; |
1410 | 1.79k | MWAWVec2i paperSize = info.paper().size(); |
1411 | 1.79k | MWAWVec2i pageSize = info.page().size(); |
1412 | 1.79k | if (pageSize.x() <= 0 || pageSize.y() <= 0 || |
1413 | 1.77k | paperSize.x() <= 0 || paperSize.y() <= 0) { |
1414 | 16 | ascii().addPos(pos); |
1415 | 16 | ascii().addNote(f.str().c_str()); |
1416 | 16 | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
1417 | 16 | return true; |
1418 | 16 | } |
1419 | | |
1420 | | // define margin from print info |
1421 | 1.77k | MWAWVec2i lTopMargin= -1 * info.paper().pos(0); |
1422 | 1.77k | MWAWVec2i rBotMargin=info.paper().size() - info.page().size(); |
1423 | | |
1424 | | // move margin left | top |
1425 | 1.77k | int decalX = lTopMargin.x() > 14 ? lTopMargin.x()-14 : 0; |
1426 | 1.77k | int decalY = lTopMargin.y() > 14 ? lTopMargin.y()-14 : 0; |
1427 | 1.77k | lTopMargin -= MWAWVec2i(decalX, decalY); |
1428 | 1.77k | rBotMargin += MWAWVec2i(decalX, decalY); |
1429 | | |
1430 | | // decrease right | bottom |
1431 | 1.77k | int rightMarg = rBotMargin.x() -50; |
1432 | 1.77k | if (rightMarg < 0) rightMarg=0; |
1433 | 1.77k | int botMarg = rBotMargin.y() -50; |
1434 | 1.77k | if (botMarg < 0) botMarg=0; |
1435 | | |
1436 | 1.77k | getPageSpan().setMarginTop(lTopMargin.y()/72.0); |
1437 | 1.77k | getPageSpan().setMarginBottom(botMarg/72.0); |
1438 | 1.77k | getPageSpan().setMarginLeft(lTopMargin.x()/72.0); |
1439 | 1.77k | getPageSpan().setMarginRight(rightMarg/72.0); |
1440 | 1.77k | getPageSpan().setFormLength(paperSize.y()/72.); |
1441 | 1.77k | getPageSpan().setFormWidth(paperSize.x()/72.); |
1442 | | |
1443 | 1.77k | ascii().addPos(pos); |
1444 | 1.77k | ascii().addNote(f.str().c_str()); |
1445 | 1.77k | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
1446 | 1.77k | return true; |
1447 | 1.79k | } |
1448 | | |
1449 | | //////////////////////////////////////////////////////////// |
1450 | | // read the document main part |
1451 | | //////////////////////////////////////////////////////////// |
1452 | | std::shared_ptr<ClarisWksStruct::DSET> ClarisDrawParser::readDSET(bool isLibHeader) |
1453 | 1.16M | { |
1454 | 1.16M | MWAWInputStreamPtr input = getInput(); |
1455 | 1.16M | long pos = input->tell(); |
1456 | 1.16M | libmwaw::DebugStream f; |
1457 | 1.16M | libmwaw::DebugFile &ascFile=ascii(); |
1458 | 1.16M | if (input->readULong(4) != 0x44534554L) |
1459 | 38.6k | return std::shared_ptr<ClarisWksStruct::DSET>(); |
1460 | 1.13M | auto sz = long(input->readULong(4)); |
1461 | 1.13M | MWAWEntry entry; |
1462 | 1.13M | entry.setBegin(pos); |
1463 | 1.13M | entry.setLength(sz+8); |
1464 | | |
1465 | 1.13M | long endPos = entry.end(); |
1466 | 1.13M | if (sz<16 || !input->checkPosition(entry.end())) { |
1467 | 99.8k | MWAW_DEBUG_MSG(("ClarisDrawParser::readDSET: file is too short\n")); |
1468 | 99.8k | return std::shared_ptr<ClarisWksStruct::DSET>(); |
1469 | 99.8k | } |
1470 | | |
1471 | 1.03M | ClarisWksStruct::DSET dset; |
1472 | 1.03M | dset.m_size = sz; |
1473 | 1.03M | dset.m_numData = static_cast<int>(input->readULong(2)); |
1474 | | |
1475 | 1.03M | input->seek(10, librevenge::RVNG_SEEK_CUR); |
1476 | 1.03M | dset.m_fileType = static_cast<int>(input->readULong(1)); |
1477 | 1.03M | input->seek(-11, librevenge::RVNG_SEEK_CUR); |
1478 | 1.03M | int nFlags = 0; |
1479 | 1.03M | switch (dset.m_fileType) { |
1480 | 274k | case 1: // text |
1481 | 274k | dset.m_beginSelection = static_cast<int>(input->readLong(4)); |
1482 | 274k | dset.m_endSelection = static_cast<int>(input->readLong(4)); |
1483 | 274k | dset.m_textType = static_cast<int>(input->readULong(1)); |
1484 | 274k | dset.m_flags[nFlags++] = static_cast<int>(input->readLong(1)); |
1485 | 274k | dset.m_headerSz = 44; |
1486 | 274k | dset.m_dataSz = 28; |
1487 | 274k | break; |
1488 | 756k | default: |
1489 | 756k | dset.m_flags[nFlags++] = static_cast<int>(input->readLong(2)); // normally -1 |
1490 | 756k | dset.m_flags[nFlags++] = static_cast<int>(input->readLong(2)); // the 0 |
1491 | 756k | dset.m_dataSz = static_cast<int>(input->readULong(2)); |
1492 | 756k | dset.m_headerSz = static_cast<int>(input->readULong(2)); |
1493 | 756k | dset.m_flags[nFlags++] = static_cast<int>(input->readLong(2)); |
1494 | 756k | break; |
1495 | 1.03M | } |
1496 | 1.03M | dset.m_flags[nFlags++] = static_cast<int>(input->readLong(2)); |
1497 | 1.03M | dset.m_id = static_cast<int>(input->readULong(2)); |
1498 | 1.03M | std::shared_ptr<ClarisWksStruct::DSET> zone; |
1499 | 1.03M | switch (dset.m_fileType) { |
1500 | 457k | case 0: |
1501 | 457k | zone=m_graphParser->readGroupZone(dset, entry, isLibHeader); |
1502 | 457k | break; |
1503 | 274k | case 1: |
1504 | 274k | zone=m_textParser->readDSETZone(dset, entry); |
1505 | 274k | break; |
1506 | 186k | case 4: |
1507 | 186k | zone=m_graphParser->readBitmapZone(dset, entry); |
1508 | 186k | break; |
1509 | 112k | default: |
1510 | 112k | break; |
1511 | 1.03M | } |
1512 | 1.03M | if (!zone) { |
1513 | 227k | MWAW_DEBUG_MSG(("ClarisDrawParser::readDSET: find unexpected type\n")); |
1514 | 227k | zone.reset(new ClarisWksStruct::DSET(dset)); |
1515 | 227k | f << "Entries(DSETU): " << *zone; |
1516 | | |
1517 | 227k | auto data0Length = static_cast<int>(zone->m_dataSz); |
1518 | 227k | auto N = static_cast<int>(zone->m_numData); |
1519 | | |
1520 | 227k | ascFile.addDelimiter(input->tell(), '|'); |
1521 | 227k | ascFile.addPos(pos); |
1522 | 227k | ascFile.addNote(f.str().c_str()); |
1523 | | |
1524 | 227k | const long dataSz = sz-12-zone->m_headerSz; |
1525 | 227k | if ((dataSz && (data0Length<=0 || (dataSz/data0Length)!=N || (dataSz%data0Length)!=0)) || (!dataSz && N)) { |
1526 | 206k | MWAW_DEBUG_MSG(("ClarisDrawParser::readDSET: unexpected size for zone definition, try to continue\n")); |
1527 | 206k | ascFile.addPos(pos); |
1528 | 206k | ascFile.addNote("###"); |
1529 | 206k | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
1530 | 206k | return zone; |
1531 | 206k | } |
1532 | | |
1533 | 20.9k | long debPos = endPos-N*data0Length; |
1534 | 39.9k | for (long i = 0; i < zone->m_numData; i++) { |
1535 | 19.0k | input->seek(debPos, librevenge::RVNG_SEEK_SET); |
1536 | 19.0k | f.str(""); |
1537 | 19.0k | f << "DSETU-" << i << ":"; |
1538 | | |
1539 | 19.0k | long actPos = input->tell(); |
1540 | 19.0k | if (actPos != debPos && actPos != debPos+data0Length) |
1541 | 0 | ascFile.addDelimiter(input->tell(),'|'); |
1542 | 19.0k | ascFile.addPos(debPos); |
1543 | 19.0k | ascFile.addNote(f.str().c_str()); |
1544 | 19.0k | debPos += data0Length; |
1545 | 19.0k | } |
1546 | | |
1547 | 20.9k | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
1548 | 20.9k | } |
1549 | | |
1550 | 824k | if (m_state->m_zonesMap.find(zone->m_id) != m_state->m_zonesMap.end()) { |
1551 | 686k | MWAW_DEBUG_MSG(("ClarisDrawParser::readDSET: zone %d already exists!!!!\n", |
1552 | 686k | zone->m_id)); |
1553 | 686k | } |
1554 | 137k | else { |
1555 | 137k | m_state->m_zonesMap[zone->m_id] = zone; |
1556 | 137k | m_state->m_zoneIdToFileTypeMap[zone->m_id] = dset.m_fileType; |
1557 | 137k | } |
1558 | 824k | return zone; |
1559 | 1.03M | } |
1560 | | |
1561 | | //////////////////////////////////////////////////////////// |
1562 | | // |
1563 | | // send data |
1564 | | // |
1565 | | //////////////////////////////////////////////////////////// |
1566 | | |
1567 | | |
1568 | | // vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: |