/src/libmwaw/src/lib/StyleParser.cxx
Line | Count | Source |
1 | | /* -*- Mode: C++; c-default-style: "k&r"; indent-tabs-mode: nil; tab-width: 2; c-basic-offset: 2 -*- */ |
2 | | |
3 | | /* libmwaw |
4 | | * Version: MPL 2.0 / LGPLv2+ |
5 | | * |
6 | | * The contents of this file are subject to the Mozilla Public License Version |
7 | | * 2.0 (the "License"); you may not use this file except in compliance with |
8 | | * the License or as specified alternatively below. You may obtain a copy of |
9 | | * the License at http://www.mozilla.org/MPL/ |
10 | | * |
11 | | * Software distributed under the License is distributed on an "AS IS" basis, |
12 | | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
13 | | * for the specific language governing rights and limitations under the |
14 | | * License. |
15 | | * |
16 | | * Major Contributor(s): |
17 | | * Copyright (C) 2002 William Lachance (wrlach@gmail.com) |
18 | | * Copyright (C) 2002,2004 Marc Maurer (uwog@uwog.net) |
19 | | * Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba@bluewin.ch) |
20 | | * Copyright (C) 2006, 2007 Andrew Ziem |
21 | | * Copyright (C) 2011, 2012 Alonso Laurent (alonso@loria.fr) |
22 | | * |
23 | | * |
24 | | * All Rights Reserved. |
25 | | * |
26 | | * For minor contributions see the git repository. |
27 | | * |
28 | | * Alternatively, the contents of this file may be used under the terms of |
29 | | * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"), |
30 | | * in which case the provisions of the LGPLv2+ are applicable |
31 | | * instead of those above. |
32 | | */ |
33 | | |
34 | | #include <iomanip> |
35 | | #include <iostream> |
36 | | #include <limits> |
37 | | #include <set> |
38 | | #include <sstream> |
39 | | |
40 | | #include <librevenge/librevenge.h> |
41 | | |
42 | | #include "MWAWTextListener.hxx" |
43 | | #include "MWAWFont.hxx" |
44 | | #include "MWAWFontConverter.hxx" |
45 | | #include "MWAWHeader.hxx" |
46 | | #include "MWAWParagraph.hxx" |
47 | | #include "MWAWPictData.hxx" |
48 | | #include "MWAWPosition.hxx" |
49 | | #include "MWAWPrinter.hxx" |
50 | | #include "MWAWRSRCParser.hxx" |
51 | | #include "MWAWSubDocument.hxx" |
52 | | |
53 | | #include "StyleParser.hxx" |
54 | | |
55 | | /** Internal: the structures of a StyleParser */ |
56 | | namespace StyleParserInternal |
57 | | { |
58 | | //! small structure used to store picture data in StyleParser |
59 | | struct Picture { |
60 | | //! constructor |
61 | | Picture() |
62 | 63.9k | : m_size(0,0) |
63 | 63.9k | , m_entry() |
64 | 63.9k | { |
65 | 63.9k | } |
66 | | //! returns true if the picture is valid |
67 | | bool valid() const |
68 | 21.0k | { |
69 | 21.0k | return m_entry.valid(); |
70 | 21.0k | } |
71 | | //! the picture size in point |
72 | | MWAWVec2i m_size; |
73 | | //! the picture entry |
74 | | MWAWEntry m_entry; |
75 | | }; |
76 | | |
77 | | //! small structure used to store a font and a picture |
78 | | struct Font { |
79 | | //! constructor |
80 | | Font() |
81 | 55.6k | : m_font() |
82 | 55.6k | , m_picture() |
83 | 55.6k | { |
84 | 55.6k | } |
85 | | //! returns true if the picture is valid |
86 | | bool hasPicture() const |
87 | 20.8k | { |
88 | 20.8k | return m_picture.valid(); |
89 | 20.8k | } |
90 | | //! the font |
91 | | MWAWFont m_font; |
92 | | //! the picture |
93 | | Picture m_picture; |
94 | | }; |
95 | | |
96 | | //////////////////////////////////////// |
97 | | //! Internal: the state of a StyleParser |
98 | | struct State { |
99 | | //! constructor |
100 | | State() |
101 | 66.3k | : m_entryMap() |
102 | 66.3k | , m_unicodeChar(false) |
103 | 66.3k | , m_textEntry() |
104 | 66.3k | , m_backgroundColor(MWAWColor::white()) |
105 | 66.3k | , m_fontIdToFinalIdList() |
106 | 66.3k | , m_fontList() |
107 | 66.3k | , m_paragraphList() |
108 | 66.3k | , m_posFontIdMap() |
109 | 66.3k | , m_posParagraphIdMap() |
110 | 66.3k | , m_posPictureMap() |
111 | 66.3k | , m_actPage(0) |
112 | 66.3k | , m_numPages(0) |
113 | 66.3k | { |
114 | 66.3k | } |
115 | | //! the map type to entry |
116 | | std::map<std::string, MWAWEntry> m_entryMap; |
117 | | //! true if the character are unicode character |
118 | | bool m_unicodeChar; |
119 | | //! the text entry |
120 | | MWAWEntry m_textEntry; |
121 | | //! the background color |
122 | | MWAWColor m_backgroundColor; |
123 | | //! list of font final id |
124 | | std::vector<int> m_fontIdToFinalIdList; |
125 | | //! the list of font style |
126 | | std::vector<Font> m_fontList; |
127 | | //! the list of paragraph style |
128 | | std::vector<MWAWParagraph> m_paragraphList; |
129 | | //! a map pos->font id |
130 | | std::map<long, int> m_posFontIdMap; |
131 | | //! a map pos->paragraphId |
132 | | std::map<long, int> m_posParagraphIdMap; |
133 | | //! a map pos->pictEntry |
134 | | std::map<long, Picture> m_posPictureMap; |
135 | | int m_actPage /** the actual page */, m_numPages /** the number of page of the final document */; |
136 | | }; |
137 | | |
138 | | } |
139 | | |
140 | | //////////////////////////////////////////////////////////// |
141 | | // constructor/destructor, ... |
142 | | //////////////////////////////////////////////////////////// |
143 | | StyleParser::StyleParser(MWAWInputStreamPtr const &input, MWAWRSRCParserPtr const &rsrcParser, MWAWHeader *header) |
144 | 27.8k | : MWAWTextParser(input, rsrcParser, header) |
145 | 27.8k | , m_state(new StyleParserInternal::State) |
146 | 27.8k | { |
147 | 27.8k | getPageSpan().setMargins(0.1); |
148 | 27.8k | } |
149 | | |
150 | | StyleParser::~StyleParser() |
151 | 27.8k | { |
152 | 27.8k | } |
153 | | |
154 | | //////////////////////////////////////////////////////////// |
155 | | // new page |
156 | | //////////////////////////////////////////////////////////// |
157 | | void StyleParser::newPage(int number) |
158 | 26.9k | { |
159 | 26.9k | if (number <= m_state->m_actPage || number > m_state->m_numPages) |
160 | 0 | return; |
161 | | |
162 | 54.9k | while (m_state->m_actPage < number) { |
163 | 28.0k | m_state->m_actPage++; |
164 | 28.0k | if (!getTextListener() || m_state->m_actPage == 1) |
165 | 1.11k | continue; |
166 | 26.9k | getTextListener()->insertBreak(MWAWTextListener::PageBreak); |
167 | 26.9k | } |
168 | 26.9k | } |
169 | | |
170 | | //////////////////////////////////////////////////////////// |
171 | | // the parser |
172 | | //////////////////////////////////////////////////////////// |
173 | | void StyleParser::parse(librevenge::RVNGTextInterface *docInterface) |
174 | 10.6k | { |
175 | 10.6k | if (!getInput().get() || !checkHeader(nullptr)) throw(libmwaw::ParseException()); |
176 | 10.6k | bool ok = false; |
177 | 10.6k | try { |
178 | | // create the asciiFile |
179 | 10.6k | ascii().setStream(getInput()); |
180 | 10.6k | ascii().open("main-1"); |
181 | 10.6k | checkHeader(nullptr); |
182 | 10.6k | ok = createZones(); |
183 | 10.6k | if (ok) { |
184 | 6.24k | createDocument(docInterface); |
185 | 6.24k | sendText(m_state->m_textEntry, m_state->m_unicodeChar); |
186 | 6.24k | } |
187 | 10.6k | ascii().reset(); |
188 | 10.6k | } |
189 | 10.6k | catch (...) { |
190 | 0 | MWAW_DEBUG_MSG(("StyleParser::parse: exception catched when parsing\n")); |
191 | 0 | ok = false; |
192 | 0 | } |
193 | | |
194 | 10.6k | resetTextListener(); |
195 | 10.6k | if (!ok) throw(libmwaw::ParseException()); |
196 | 10.6k | } |
197 | | |
198 | | //////////////////////////////////////////////////////////// |
199 | | // create the document |
200 | | //////////////////////////////////////////////////////////// |
201 | | void StyleParser::createDocument(librevenge::RVNGTextInterface *documentInterface) |
202 | 6.24k | { |
203 | 6.24k | if (!documentInterface) return; |
204 | 6.24k | if (getTextListener()) { |
205 | 0 | MWAW_DEBUG_MSG(("StyleParser::createDocument: listener already exist\n")); |
206 | 0 | return; |
207 | 0 | } |
208 | | |
209 | | // update the page |
210 | 6.24k | m_state->m_actPage = 0; |
211 | | |
212 | | // create the page list |
213 | 6.24k | int numPages=m_state->m_textEntry.valid() ? computeNumPages(m_state->m_textEntry, m_state->m_unicodeChar) : 1; |
214 | 6.24k | m_state->m_numPages = numPages; |
215 | 6.24k | MWAWPageSpan ps(getPageSpan()); |
216 | 6.24k | ps.setPageSpan(m_state->m_numPages+1); |
217 | 6.24k | if (!m_state->m_backgroundColor.isWhite()) |
218 | 1.15k | ps.setBackgroundColor(m_state->m_backgroundColor); |
219 | 6.24k | std::vector<MWAWPageSpan> pageList(1,ps); |
220 | 6.24k | MWAWTextListenerPtr listen(new MWAWTextListener(*getParserState(), pageList, documentInterface)); |
221 | 6.24k | setTextListener(listen); |
222 | 6.24k | listen->startDocument(); |
223 | 6.24k | } |
224 | | |
225 | | |
226 | | //////////////////////////////////////////////////////////// |
227 | | // |
228 | | // Intermediate level |
229 | | // |
230 | | //////////////////////////////////////////////////////////// |
231 | | bool StyleParser::createZones() |
232 | 10.6k | { |
233 | 10.6k | if (!readTypeEntryMap()) |
234 | 1.44k | return false; |
235 | 9.21k | libmwaw::DebugStream f; |
236 | 9.21k | auto &entryMap = m_state->m_entryMap; |
237 | | |
238 | | // basic data |
239 | 9.21k | auto it = entryMap.find("vers"); |
240 | 9.21k | if (it != entryMap.end()) { |
241 | 3.00k | MWAWEntry const &entry = it++->second; |
242 | 3.00k | readVersion(entry); |
243 | 3.00k | } |
244 | 9.21k | it = entryMap.find("bgcl"); |
245 | 9.21k | if (it != entryMap.end()) { |
246 | 1.56k | MWAWEntry const &entry = it++->second; |
247 | 1.56k | readBackgroundColor(entry); |
248 | 1.56k | } |
249 | 9.21k | it = entryMap.find("marg"); |
250 | 9.21k | if (it != entryMap.end()) { |
251 | 1.65k | MWAWEntry const &entry = it++->second; |
252 | 1.65k | readMargins(entry); |
253 | 1.65k | } |
254 | 9.21k | it = entryMap.find("prec"); |
255 | 9.21k | if (it != entryMap.end()) { |
256 | 1.96k | MWAWEntry const &entry = it++->second; |
257 | 1.96k | readPrintInfo(entry); |
258 | 1.96k | } |
259 | 9.21k | it = entryMap.find("stat"); |
260 | 9.21k | if (it != entryMap.end()) { |
261 | 1.29k | MWAWEntry const &entry = it++->second; |
262 | 1.29k | readStat(entry); |
263 | 1.29k | } |
264 | 9.21k | it = entryMap.find("tabw"); |
265 | 9.21k | if (it != entryMap.end()) { |
266 | 1.15k | MWAWEntry const &entry = it++->second; |
267 | 1.15k | readTabWidth(entry); |
268 | 1.15k | } |
269 | 9.21k | bool findTextEntry=false; |
270 | 9.21k | it = entryMap.find("text"); |
271 | 9.21k | if (it != entryMap.end()) { |
272 | 1.52k | findTextEntry=true; |
273 | 1.52k | MWAWEntry const &entry = it++->second; |
274 | 1.52k | entry.setParsed(true); |
275 | 1.52k | m_state->m_unicodeChar=false; |
276 | 1.52k | m_state->m_textEntry=entry; |
277 | 1.52k | } |
278 | 9.21k | it = entryMap.find("utxt"); |
279 | 9.21k | if (it != entryMap.end()) { |
280 | 4.72k | findTextEntry=true; |
281 | 4.72k | MWAWEntry const &entry = it++->second; |
282 | 4.72k | entry.setParsed(true); |
283 | 4.72k | m_state->m_unicodeChar=true; |
284 | 4.72k | m_state->m_textEntry=entry; |
285 | 4.72k | } |
286 | | |
287 | | // font |
288 | | |
289 | | // v1.9 |
290 | 9.21k | it = entryMap.find("cfor"); |
291 | 9.21k | if (it != entryMap.end()) { |
292 | 2.07k | MWAWEntry const &entry = it++->second; |
293 | 2.07k | readFormats(entry); |
294 | 2.07k | } |
295 | | // or v1.6 |
296 | 9.21k | it = entryMap.find("font"); |
297 | 9.21k | if (it != entryMap.end()) { |
298 | 877 | MWAWEntry const &entry = it++->second; |
299 | 877 | readFontCorr(entry); |
300 | 877 | } |
301 | 9.21k | it = entryMap.find("fntb"); |
302 | 9.21k | if (it != entryMap.end()) { |
303 | 1.15k | MWAWEntry const &entry = it++->second; |
304 | 1.15k | readFontNames(entry); |
305 | 1.15k | } |
306 | 9.21k | it = entryMap.find("styl"); |
307 | 9.21k | if (it != entryMap.end()) { |
308 | 1.38k | MWAWEntry const &entry = it++->second; |
309 | 1.38k | readStyleTable(entry); |
310 | 1.38k | } |
311 | | // v1.6 or v1.9 |
312 | 9.21k | it = entryMap.find("runa"); |
313 | 9.21k | if (it != entryMap.end()) { |
314 | 4.39k | MWAWEntry const &entry = it++->second; |
315 | 4.39k | readPLCs(entry, false); |
316 | 4.39k | } |
317 | | |
318 | | // para |
319 | 9.21k | it = entryMap.find("rule"); |
320 | 9.21k | if (it != entryMap.end()) { |
321 | 1.93k | MWAWEntry const &entry = it++->second; |
322 | 1.93k | readRules(entry); |
323 | 1.93k | } |
324 | 9.21k | it = entryMap.find("para"); |
325 | 9.21k | if (it != entryMap.end()) { |
326 | 3.88k | MWAWEntry const &entry = it++->second; |
327 | 3.88k | readPLCs(entry, true); |
328 | 3.88k | } |
329 | | |
330 | | // image |
331 | 9.21k | it = entryMap.find("soup"); |
332 | 9.21k | if (it != entryMap.end()) { |
333 | 1.83k | MWAWEntry const &entry = it++->second; |
334 | 1.83k | readPictures(entry); |
335 | 1.83k | } |
336 | | |
337 | | // extra |
338 | 9.21k | it = entryMap.find("xprc"); |
339 | 9.21k | if (it != entryMap.end()) { |
340 | 1.38k | MWAWEntry const &entry = it++->second; |
341 | 1.38k | readExtraProperties(entry); |
342 | 1.38k | } |
343 | | |
344 | | // other |
345 | 42.5k | for (auto const &iter : entryMap) { |
346 | 42.5k | MWAWEntry const &entry=iter.second; |
347 | 42.5k | if (entry.isParsed()) continue; |
348 | 9.23k | f.str(""); |
349 | 9.23k | f << "Entries(" << entry.type() << "):"; |
350 | 9.23k | ascii().addPos(entry.begin()); |
351 | 9.23k | ascii().addNote(f.str().c_str()); |
352 | 9.23k | ascii().addPos(entry.end()); |
353 | 9.23k | ascii().addNote("_"); |
354 | 9.23k | } |
355 | 9.21k | return m_state->m_textEntry.valid() || findTextEntry; |
356 | 10.6k | } |
357 | | |
358 | | bool StyleParser::readTypeEntryMap() |
359 | 24.7k | { |
360 | 24.7k | MWAWInputStreamPtr input = getInput(); |
361 | 24.7k | if (!input->checkPosition(16)) return false; |
362 | 24.7k | input->seek(8, librevenge::RVNG_SEEK_SET); |
363 | 24.7k | long pos=input->tell(); |
364 | 24.7k | libmwaw::DebugStream f; |
365 | 24.7k | f << "Entries(ZoneList):"; |
366 | 24.7k | int val; |
367 | 24.7k | auto N=static_cast<int>(input->readLong(2)); |
368 | 24.7k | f << "N=" << N+1 << ","; |
369 | 24.7k | if (!input->checkPosition(16+16*(N+1))) return false; |
370 | 97.4k | for (int i=0; i<3; ++i) { // always 0 |
371 | 73.0k | val=static_cast<int>(input->readLong(2)); |
372 | 73.0k | if (val) |
373 | 15.4k | f << "f" << i << "=" << val << ","; |
374 | 73.0k | } |
375 | 24.3k | ascii().addPos(pos); |
376 | 24.3k | ascii().addNote(f.str().c_str()); |
377 | 24.3k | m_state->m_entryMap.clear(); |
378 | 24.3k | bool ok=false; |
379 | 4.09M | for (int i=0; i<=N; ++i) { |
380 | 4.07M | pos=input->tell(); |
381 | 4.07M | f.str(""); |
382 | 4.07M | f << "ZoneList-" << i << ":"; |
383 | 4.07M | std::string wh(""); |
384 | 20.3M | for (int c=0; c<4; ++c) wh+=char(input->readULong(1)); |
385 | 4.07M | f << wh << ","; |
386 | 4.07M | if (wh=="text" || wh=="utxt") ok=true; |
387 | 12.2M | for (int j=0; j<2; ++j) { |
388 | | // always 0 |
389 | 8.14M | val=static_cast<int>(input->readLong(2)); |
390 | 8.14M | if (val) |
391 | 5.29M | f << "f" << i << "=" << val << ","; |
392 | 8.14M | } |
393 | 4.07M | MWAWEntry entry; |
394 | 4.07M | entry.setType(wh); |
395 | 4.07M | entry.setBegin(long(input->readLong(4))); |
396 | 4.07M | entry.setLength(long(input->readLong(4))); |
397 | 4.07M | f << std::hex << entry.begin() << "<->" << entry.end() << ","; |
398 | 4.07M | if (!entry.length()) { |
399 | | // ok if the document is empty |
400 | 745k | if (wh=="text" || wh=="utxt") |
401 | 4.80k | m_state->m_entryMap[wh]=entry; |
402 | 745k | } |
403 | 3.32M | else if (entry.begin()<16+16*(N+1) || !input->checkPosition(entry.end()) || |
404 | 3.22M | m_state->m_entryMap.find(wh)!=m_state->m_entryMap.end()) { |
405 | 3.22M | MWAW_DEBUG_MSG(("StyleParser::readTypeEntryMap: find some bad entry")); |
406 | 3.22M | f << "###"; |
407 | 3.22M | } |
408 | 104k | else |
409 | 104k | m_state->m_entryMap[wh]=entry; |
410 | 4.07M | ascii().addPos(pos); |
411 | 4.07M | ascii().addNote(f.str().c_str()); |
412 | 4.07M | } |
413 | 24.3k | ascii().addPos(input->tell()); |
414 | 24.3k | ascii().addNote("_"); |
415 | 24.3k | return ok && !m_state->m_entryMap.empty(); |
416 | 24.7k | } |
417 | | |
418 | | //////////////////////////////////////////////////////////// |
419 | | // font |
420 | | //////////////////////////////////////////////////////////// |
421 | | bool StyleParser::readFontNames(MWAWEntry const &entry) |
422 | 1.15k | { |
423 | 1.15k | MWAWInputStreamPtr input = getInput(); |
424 | 1.15k | if (!entry.valid() || !input->checkPosition(entry.end())) { |
425 | 42 | MWAW_DEBUG_MSG(("StyleParser::readFontNames: the entry seems bad\n")); |
426 | 42 | return false; |
427 | 42 | } |
428 | 1.11k | entry.setParsed(true); |
429 | 1.11k | libmwaw::DebugStream f; |
430 | 1.11k | f << "Entries(Font)[names]:"; |
431 | 1.11k | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
432 | 1.11k | long endPos=entry.end(); |
433 | 8.81k | while (input->tell()<endPos) { |
434 | 8.38k | long actPos=input->tell(); |
435 | 8.38k | auto dSz=static_cast<int>(input->readULong(1)); |
436 | 8.38k | if (!dSz || actPos+1+dSz > endPos) { |
437 | 683 | MWAW_DEBUG_MSG(("StyleParser::readFontNames: can not read some entry\n")); |
438 | 683 | ascii().addDelimiter(input->tell(),'|'); |
439 | 683 | f << "###"; |
440 | 683 | break; |
441 | 683 | } |
442 | 7.70k | std::string name(""); |
443 | 112k | for (int i=0; i<dSz; ++i) name+=char(input->readULong(1)); |
444 | 7.70k | f << name << ","; |
445 | 7.70k | m_state->m_fontIdToFinalIdList.push_back(getFontConverter()->getId(name)); |
446 | 7.70k | } |
447 | 1.11k | ascii().addPos(entry.begin()); |
448 | 1.11k | ascii().addNote(f.str().c_str()); |
449 | 1.11k | ascii().addPos(entry.end()); |
450 | 1.11k | ascii().addNote("_"); |
451 | 1.11k | return true; |
452 | 1.15k | } |
453 | | |
454 | | bool StyleParser::readFontCorr(MWAWEntry const &entry) |
455 | 877 | { |
456 | 877 | MWAWInputStreamPtr input = getInput(); |
457 | 877 | if (!entry.valid() || !input->checkPosition(entry.end())) { |
458 | 19 | MWAW_DEBUG_MSG(("StyleParser::readFontCorr: the entry seems bad\n")); |
459 | 19 | return false; |
460 | 19 | } |
461 | 858 | entry.setParsed(true); |
462 | 858 | libmwaw::DebugStream f; |
463 | 858 | f << "Entries(Font)[correspondance]:"; |
464 | 858 | if (entry.length()%32) { |
465 | 15 | MWAW_DEBUG_MSG(("StyleParser::readFontCorr: the entry size seems bad\n")); |
466 | 15 | f << "###"; |
467 | 15 | ascii().addPos(entry.begin()); |
468 | 15 | ascii().addNote(f.str().c_str()); |
469 | 15 | ascii().addPos(entry.end()); |
470 | 15 | ascii().addNote("_"); |
471 | 15 | return true; |
472 | 15 | } |
473 | | |
474 | 843 | ascii().addPos(entry.begin()); |
475 | 843 | ascii().addNote(f.str().c_str()); |
476 | 843 | ascii().addPos(entry.end()); |
477 | 843 | ascii().addNote("_"); |
478 | | |
479 | 843 | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
480 | 843 | auto N=int(entry.length()/30); |
481 | 5.11k | for (int j=0; j<N; ++j) { |
482 | 4.26k | long pos=input->tell(); |
483 | 4.26k | f.str(""); |
484 | 4.26k | f << "Font-" << j << ":"; |
485 | 4.26k | f << "id=" << input->readULong(2); |
486 | 68.2k | for (int i=0; i<15; ++i) { // except f5, always 0 |
487 | 64.0k | auto val=static_cast<int>(input->readULong(2)); |
488 | 64.0k | if (!val) |
489 | 28.4k | continue; |
490 | 35.5k | if (i==5) // pos in fntb |
491 | 2.28k | f << "pos=" << val << ","; |
492 | 33.2k | else |
493 | 33.2k | f << "f" << i << "=" << val << ","; |
494 | 35.5k | } |
495 | 4.26k | ascii().addPos(pos); |
496 | 4.26k | ascii().addNote(f.str().c_str()); |
497 | 4.26k | input->seek(pos+32, librevenge::RVNG_SEEK_SET); |
498 | 4.26k | } |
499 | 843 | return true; |
500 | 858 | } |
501 | | |
502 | | bool StyleParser::readStyleTable(MWAWEntry const &entry) |
503 | 1.38k | { |
504 | 1.38k | MWAWInputStreamPtr input = getInput(); |
505 | 1.38k | if (!entry.valid() || !input->checkPosition(entry.end())) { |
506 | 145 | MWAW_DEBUG_MSG(("StyleParser::readStyleTable: the entry seems bad\n")); |
507 | 145 | return false; |
508 | 145 | } |
509 | 1.24k | entry.setParsed(true); |
510 | 1.24k | libmwaw::DebugStream f; |
511 | 1.24k | f << "Entries(Style):"; |
512 | 1.24k | if (entry.length()%20) { |
513 | 96 | MWAW_DEBUG_MSG(("StyleParser::readStyleTable: the entry size seems bad\n")); |
514 | 96 | f << "###"; |
515 | 96 | ascii().addPos(entry.begin()); |
516 | 96 | ascii().addNote(f.str().c_str()); |
517 | 96 | ascii().addPos(entry.end()); |
518 | 96 | ascii().addNote("_"); |
519 | 96 | return true; |
520 | 96 | } |
521 | | |
522 | 1.14k | ascii().addPos(entry.begin()); |
523 | 1.14k | ascii().addNote(f.str().c_str()); |
524 | 1.14k | ascii().addPos(entry.end()); |
525 | 1.14k | ascii().addNote("_"); |
526 | | |
527 | 1.14k | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
528 | 1.14k | auto N=int(entry.length()/20); |
529 | 1.14k | m_state->m_fontList.clear(); |
530 | 39.3k | for (int i=0; i<N; ++i) { |
531 | 38.1k | long pos=input->tell(); |
532 | 38.1k | StyleParserInternal::Font font; |
533 | 38.1k | f.str(""); |
534 | 38.1k | long used = input->readLong(4); |
535 | 38.1k | int dim[2]; |
536 | 76.3k | for (auto &d : dim) d = static_cast<int>(input->readLong(2)); |
537 | 38.1k | f << "height?=" << dim[0] << ":" << dim[1] << ","; |
538 | 38.1k | auto fId=static_cast<int>(input->readLong(2)); |
539 | 38.1k | if (fId < 0 && -fId<=static_cast<int>(m_state->m_fontIdToFinalIdList.size())) |
540 | 1.66k | font.m_font.setId(m_state->m_fontIdToFinalIdList[size_t(-fId-1)]); |
541 | 36.5k | else if (fId>0) // checkme, never seen |
542 | 18.9k | font.m_font.setId(fId); |
543 | 17.5k | else { |
544 | 17.5k | MWAW_DEBUG_MSG(("StyleParser::readStyleTable: the font id seems bad\n")); |
545 | 17.5k | f << "##fId=" << fId << ","; |
546 | 17.5k | } |
547 | 38.1k | auto flag=static_cast<int>(input->readULong(1)); |
548 | 38.1k | uint32_t flags = 0; |
549 | 38.1k | if (flag&0x1) flags |= MWAWFont::boldBit; |
550 | 38.1k | if (flag&0x2) flags |= MWAWFont::italicBit; |
551 | 38.1k | if (flag&0x4) font.m_font.setUnderlineStyle(MWAWFont::Line::Simple); |
552 | 38.1k | if (flag&0x8) flags |= MWAWFont::embossBit; |
553 | 38.1k | if (flag&0x10) flags |= MWAWFont::shadowBit; |
554 | 38.1k | if (flag&0x20) font.m_font.setDeltaLetterSpacing(-1.); |
555 | 38.1k | if (flag&0x40) font.m_font.setDeltaLetterSpacing(1.); |
556 | 38.1k | if (flag&0x80) f << "#flags=" << std::hex << (flag&0x80) << std::dec << ","; |
557 | 38.1k | flag=static_cast<int>(input->readULong(1)); |
558 | 38.1k | if (flag) f << "#flags1=" << std::hex << flag << std::dec << ","; |
559 | 38.1k | font.m_font.setSize(float(input->readULong(2))); |
560 | 38.1k | font.m_font.setFlags(flags); |
561 | 38.1k | unsigned char col[3]; |
562 | 114k | for (auto &c : col) c = static_cast<unsigned char>(input->readULong(2)>>8); |
563 | 38.1k | font.m_font.setColor(MWAWColor(col[0],col[1],col[2])); |
564 | 38.1k | font.m_font.m_extra=f.str(); |
565 | 38.1k | m_state->m_fontList.push_back(font); |
566 | | |
567 | 38.1k | f.str(""); |
568 | 38.1k | f << "Style-" << i << ":"; |
569 | 38.1k | if (used!=1) f << "used?=" << used << ","; |
570 | | #ifdef DEBUG |
571 | | f << ",font=[" << font.m_font.getDebugString(getFontConverter()) << "]"; |
572 | | #endif |
573 | 38.1k | ascii().addPos(pos); |
574 | 38.1k | ascii().addNote(f.str().c_str()); |
575 | 38.1k | input->seek(pos+20, librevenge::RVNG_SEEK_SET); |
576 | 38.1k | } |
577 | 1.14k | return true; |
578 | 1.24k | } |
579 | | |
580 | | bool StyleParser::readFormats(MWAWEntry const &entry) |
581 | 2.07k | { |
582 | 2.07k | MWAWInputStreamPtr input = getInput(); |
583 | 2.07k | if (!entry.valid() || !input->checkPosition(entry.end()) || entry.length()<24) { |
584 | 206 | MWAW_DEBUG_MSG(("StyleParser::readFormats: the entry seems bad\n")); |
585 | 206 | return false; |
586 | 206 | } |
587 | 1.86k | entry.setParsed(true); |
588 | 1.86k | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
589 | 1.86k | ascii().addPos(entry.end()); |
590 | 1.86k | ascii().addNote("_"); |
591 | 1.86k | libmwaw::DebugStream f; |
592 | 1.86k | f << "Entries(Format):"; |
593 | 1.86k | int val; |
594 | 13.0k | for (int i=0; i<6; ++i) { // f5=0|18 |
595 | 11.2k | val=static_cast<int>(input->readLong(2)); |
596 | 11.2k | if (val) |
597 | 1.33k | f << "f" << i << "=" << val << ","; |
598 | 11.2k | } |
599 | 1.86k | std::string marker(""); |
600 | 9.34k | for (int i=0; i<4; ++i) marker+=char(input->readULong(1)); |
601 | 1.86k | if (marker!="list") { |
602 | 334 | MWAW_DEBUG_MSG(("StyleParser::readFormats: can not find the list marker\n")); |
603 | 334 | f << "###"; |
604 | 334 | ascii().addPos(entry.begin()); |
605 | 334 | ascii().addNote(f.str().c_str()); |
606 | 334 | return false; |
607 | 334 | } |
608 | 1.53k | auto N=static_cast<int>(input->readLong(4)); |
609 | 1.53k | f << "N=" << N << ","; |
610 | 4.60k | for (int i=0; i<2; ++i) { // always 0 |
611 | 3.06k | val=static_cast<int>(input->readLong(2)); |
612 | 3.06k | if (val) |
613 | 69 | f << "g" << i << "=" << val << ","; |
614 | 3.06k | } |
615 | | |
616 | 1.53k | input->seek(entry.begin()+24, librevenge::RVNG_SEEK_SET); |
617 | 1.53k | ascii().addPos(entry.begin()); |
618 | 1.53k | ascii().addNote(f.str().c_str()); |
619 | | |
620 | 19.0k | for (int form=0; form<N; ++form) { |
621 | 18.5k | long pos=input->tell(); |
622 | 18.5k | marker=""; |
623 | 92.5k | for (int c=0; c<4; ++c) marker+=char(input->readLong(1)); |
624 | 18.5k | long dSz=static_cast<int>(input->readLong(4)); |
625 | 18.5k | long endPos=pos+8+dSz; |
626 | 18.5k | if (marker!="reco" || dSz<8 || endPos>entry.end()) { |
627 | 994 | input->seek(pos, librevenge::RVNG_SEEK_SET); |
628 | 994 | MWAW_DEBUG_MSG(("StyleParser::readFormats: can not read some format\n")); |
629 | 994 | break; |
630 | 994 | } |
631 | 17.5k | StyleParserInternal::Font font; |
632 | 17.5k | f.str(""); |
633 | 17.5k | f << "Format-C" << form << ":"; |
634 | 17.5k | long N1=static_cast<int>(input->readULong(4)); |
635 | 17.5k | f << "N1=" << N1 << ","; |
636 | 52.5k | for (int i=0; i<2; ++i) { // always 0 |
637 | 35.0k | val=static_cast<int>(input->readLong(2)); |
638 | 35.0k | if (val) |
639 | 630 | f << "f" << i << "=" << val << ","; |
640 | 35.0k | } |
641 | 17.5k | if (dSz<8+12*N1) { |
642 | 768 | MWAW_DEBUG_MSG(("StyleParser::readFormats: N1 is bad\n")); |
643 | 768 | f << "###N1,"; |
644 | 768 | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
645 | 768 | ascii().addPos(pos); |
646 | 768 | ascii().addNote(f.str().c_str()); |
647 | 768 | m_state->m_fontList.push_back(font); |
648 | 768 | continue; |
649 | 768 | } |
650 | 16.7k | ascii().addPos(pos); |
651 | 16.7k | ascii().addNote(f.str().c_str()); |
652 | 16.7k | std::string type(""); |
653 | 87.3k | for (long i=0; i<N1; ++i) { |
654 | 74.0k | pos=input->tell(); |
655 | 74.0k | f.str(""); |
656 | 74.0k | f << "Format-C" << form << "-" << i << ":"; |
657 | 74.0k | marker=type=""; |
658 | 370k | for (int c=0; c<4; ++c) marker+=char(input->readULong(1)); |
659 | 370k | for (int c=0; c<4; ++c) type+=char(input->readULong(1)); |
660 | 74.0k | f << marker << "[" << type << "],"; |
661 | 74.0k | dSz=input->readLong(4); |
662 | 74.0k | if (dSz<0 || pos+12+dSz>endPos) { |
663 | 3.48k | MWAW_DEBUG_MSG(("StyleParser::readFormats: can not read a subformat\n")); |
664 | 3.48k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
665 | 3.48k | break; |
666 | 3.48k | } |
667 | 70.5k | if (type=="enum" || type=="TEXT") { |
668 | | // font |
669 | 14.1k | std::string string(""); |
670 | 121k | for (long c=0; c<dSz; ++c) string+=char(input->readULong(1)); |
671 | 14.1k | f << string; |
672 | 14.1k | if (marker=="font") |
673 | 13.7k | font.m_font.setId(getFontConverter()->getId(string)); |
674 | 335 | else { |
675 | 335 | MWAW_DEBUG_MSG(("StyleParser::readFormats: unknown marker\n")); |
676 | 335 | f << "###"; |
677 | 335 | } |
678 | 14.1k | } |
679 | 56.4k | else if (dSz==1 && type=="bool") { |
680 | 5.86k | val=static_cast<int>(input->readLong(1)); |
681 | 5.86k | f << val; |
682 | 5.86k | if (val<0 || val>1) { |
683 | 171 | MWAW_DEBUG_MSG(("StyleParser::readFormats: find some old bool value\n")); |
684 | 171 | f << "###"; |
685 | 171 | } |
686 | 5.69k | else if (val==0) |
687 | 9 | ; |
688 | 5.68k | else if (marker=="bold") |
689 | 539 | font.m_font.setFlags(font.m_font.flags()|MWAWFont::boldBit); |
690 | 5.14k | else if (marker=="cond") |
691 | 583 | font.m_font.setDeltaLetterSpacing(-1.); |
692 | 4.56k | else if (marker=="ital") |
693 | 847 | font.m_font.setFlags(font.m_font.flags()|MWAWFont::italicBit); |
694 | 3.71k | else if (marker=="outl") |
695 | 770 | font.m_font.setFlags(font.m_font.flags()|MWAWFont::embossBit); |
696 | 2.94k | else if (marker=="pexp") |
697 | 607 | font.m_font.setDeltaLetterSpacing(1.); |
698 | 2.33k | else if (marker=="shad") |
699 | 731 | font.m_font.setFlags(font.m_font.flags()|MWAWFont::shadowBit); |
700 | 1.60k | else if (marker=="strk") |
701 | 453 | font.m_font.setStrikeOutStyle(MWAWFont::Line::Simple); |
702 | 1.15k | else if (marker=="undl") |
703 | 762 | font.m_font.setUnderlineStyle(MWAWFont::Line::Simple); |
704 | 391 | else { |
705 | 391 | MWAW_DEBUG_MSG(("StyleParser::readFormats: unknown marker\n")); |
706 | 391 | f << "###"; |
707 | 391 | } |
708 | 5.86k | } |
709 | 50.5k | else if (dSz==2 && type=="shor") { |
710 | 15.8k | val=static_cast<int>(input->readLong(2)); |
711 | 15.8k | f << val; |
712 | 15.8k | if (marker=="fnt#") // fontId, ok to ignore |
713 | 13.4k | ; |
714 | 2.34k | else if (marker=="objb" || marker=="pptm") // CHECKME |
715 | 982 | f << "##"; |
716 | 1.36k | else { |
717 | 1.36k | MWAW_DEBUG_MSG(("StyleParser::readFormats: unknown marker\n")); |
718 | 1.36k | f << "###"; |
719 | 1.36k | } |
720 | 15.8k | } |
721 | 34.7k | else if (dSz==4 && type=="long") { |
722 | 15.8k | val=static_cast<int>(input->readLong(4)); |
723 | 15.8k | if (marker=="ptxe") // always 2000? |
724 | 14.7k | f << float(val)/65536.f; |
725 | 1.09k | else { |
726 | 1.09k | MWAW_DEBUG_MSG(("StyleParser::readFormats: unknown marker\n")); |
727 | 1.09k | f << "###" << val; |
728 | 1.09k | } |
729 | 15.8k | } |
730 | 18.8k | else if (dSz==4 && type=="fixd") { |
731 | 13.8k | float value=float(input->readLong(4))/65536.f; |
732 | 13.8k | f << value; |
733 | 13.8k | if (marker=="ptsz") |
734 | 12.8k | font.m_font.setSize(value); |
735 | 991 | else if (marker=="xshf") |
736 | 485 | font.m_font.set(MWAWFont::Script(value,librevenge::RVNG_POINT)); |
737 | 506 | else { |
738 | 506 | MWAW_DEBUG_MSG(("StyleParser::readFormats: unknown marker\n")); |
739 | 506 | f << "###"; |
740 | 506 | } |
741 | 13.8k | } |
742 | 4.99k | else if (dSz==4 && type=="QDpt") { |
743 | | // objs |
744 | 27 | int dim[2]; |
745 | 54 | for (int &j : dim) j=static_cast<int>(input->readLong(2)); |
746 | 27 | font.m_picture.m_size=MWAWVec2i(dim[1],dim[0]); |
747 | 27 | f << font.m_picture.m_size; |
748 | 27 | } |
749 | 4.96k | else if (dSz==6 && type=="cRGB") { |
750 | 1.82k | unsigned char col[3]; |
751 | 5.46k | for (auto &c : col) c=static_cast<unsigned char>(input->readULong(2)>>8); |
752 | 1.82k | MWAWColor color(col[0],col[1],col[2]); |
753 | 1.82k | f << color; |
754 | 1.82k | if (marker=="colr") |
755 | 770 | font.m_font.setColor(color); |
756 | 1.05k | else if (marker=="pbcl") |
757 | 963 | font.m_font.setBackgroundColor(color); |
758 | 90 | else { |
759 | 90 | MWAW_DEBUG_MSG(("StyleParser::readFormats: unknown marker\n")); |
760 | 90 | f << "###"; |
761 | 90 | } |
762 | 1.82k | } |
763 | 3.14k | else if (type=="PICT" && dSz) { |
764 | 480 | if (marker=="obj ") { |
765 | 460 | font.m_picture.m_entry.setBegin(pos+12); |
766 | 460 | font.m_picture.m_entry.setLength(dSz); |
767 | 460 | } |
768 | 20 | else { |
769 | 20 | MWAW_DEBUG_MSG(("StyleParser::readFormats: unknown marker\n")); |
770 | 20 | f << "###"; |
771 | 20 | } |
772 | | #ifdef DEBUG_WITH_FILES |
773 | | ascii().skipZone(pos+12, pos+12+dSz-1); |
774 | | librevenge::RVNGBinaryData file; |
775 | | input->seek(pos+12, librevenge::RVNG_SEEK_SET); |
776 | | input->readDataBlock(dSz, file); |
777 | | static int volatile pictName = 0; |
778 | | libmwaw::DebugStream f2; |
779 | | f2 << "PICT-" << ++pictName << ".pct"; |
780 | | libmwaw::Debug::dumpFile(file, f2.str().c_str()); |
781 | | #endif |
782 | 480 | } |
783 | 2.66k | else { |
784 | 2.66k | MWAW_DEBUG_MSG(("StyleParser::readFormats: unknown type\n")); |
785 | 2.66k | f << "###type"; |
786 | 2.66k | } |
787 | 70.5k | if (dSz%2) ++dSz; |
788 | 70.5k | input->seek(pos+12+dSz, librevenge::RVNG_SEEK_SET); |
789 | 70.5k | ascii().addPos(pos); |
790 | 70.5k | ascii().addNote(f.str().c_str()); |
791 | 70.5k | } |
792 | 16.7k | m_state->m_fontList.push_back(font); |
793 | 16.7k | if (input->tell()==endPos) continue; |
794 | | |
795 | 3.64k | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
796 | 3.64k | MWAW_DEBUG_MSG(("StyleParser::readFormats: find extra data\n")); |
797 | 3.64k | f.str(""); |
798 | 3.64k | f << "Format-" << form << ":###extra"; |
799 | 3.64k | ascii().addPos(pos); |
800 | 3.64k | ascii().addNote(f.str().c_str()); |
801 | 3.64k | } |
802 | 1.53k | if (input->tell()!=entry.end()) { |
803 | 1.01k | MWAW_DEBUG_MSG(("StyleParser::readFormats: find extra data\n")); |
804 | 1.01k | ascii().addPos(input->tell()); |
805 | 1.01k | ascii().addNote("Format:###extra"); |
806 | 1.01k | } |
807 | 1.53k | return true; |
808 | 1.86k | } |
809 | | //////////////////////////////////////////////////////////// |
810 | | // rules/plc |
811 | | //////////////////////////////////////////////////////////// |
812 | | bool StyleParser::readRules(MWAWEntry const &entry) |
813 | 1.93k | { |
814 | 1.93k | MWAWInputStreamPtr input = getInput(); |
815 | 1.93k | if (!entry.valid() || !input->checkPosition(entry.end()) || entry.length()<24) { |
816 | 125 | MWAW_DEBUG_MSG(("StyleParser::readRules: the entry seems bad\n")); |
817 | 125 | return false; |
818 | 125 | } |
819 | | |
820 | 1.81k | entry.setParsed(true); |
821 | 1.81k | ascii().addPos(entry.end()); |
822 | 1.81k | ascii().addNote("_"); |
823 | | |
824 | 1.81k | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
825 | 1.81k | long pos=input->tell(); |
826 | 1.81k | libmwaw::DebugStream f; |
827 | 1.81k | f << "Entries(Rule):"; |
828 | 1.81k | int val; |
829 | 10.8k | for (int i=0; i<5; ++i) { |
830 | 9.05k | val=static_cast<int>(input->readLong(2)); |
831 | 9.05k | if (val) |
832 | 4.83k | f << "f" << i << "=" << val << ","; |
833 | 9.05k | } |
834 | 1.81k | val=static_cast<int>(input->readLong(2)); |
835 | 1.81k | if (val!=24) // always 18? |
836 | 1.42k | f << "f5=" << val << ","; |
837 | 1.81k | std::string marker(""); |
838 | 9.05k | for (int i=0; i<4; ++i) marker+=char(input->readULong(1)); |
839 | 1.81k | if (marker!="list") { |
840 | 1.24k | MWAW_DEBUG_MSG(("StyleParser::readRules: can not find the list marker\n")); |
841 | 1.24k | f << "###"; |
842 | 1.24k | ascii().addPos(pos); |
843 | 1.24k | ascii().addNote(f.str().c_str()); |
844 | 1.24k | return false; |
845 | 1.24k | } |
846 | 564 | auto N=static_cast<int>(input->readLong(4)); |
847 | 564 | f << "N=" << N << ","; |
848 | 1.69k | for (int i=0; i<2; ++i) { // always 0 |
849 | 1.12k | val=static_cast<int>(input->readLong(2)); |
850 | 1.12k | if (val) |
851 | 11 | f << "g" << i << "=" << val << ","; |
852 | 1.12k | } |
853 | 564 | ascii().addPos(pos); |
854 | 564 | ascii().addNote(f.str().c_str()); |
855 | | |
856 | 564 | m_state->m_paragraphList.clear(); |
857 | 3.57k | for (int r=0; r<N; ++r) { |
858 | 3.41k | pos=input->tell(); |
859 | 3.41k | if (!input->checkPosition(pos+8)) |
860 | 2 | break; |
861 | 3.40k | f.str(""); |
862 | 3.40k | f << "Rule-P" << r << ":"; |
863 | 3.40k | marker=""; |
864 | 17.0k | for (int i=0; i<4; ++i) marker+=char(input->readULong(1)); |
865 | 3.40k | long dSz=input->readLong(4); |
866 | 3.40k | long endPos=pos+8+dSz; |
867 | 3.40k | if (marker!="reco" || dSz<8 || !input->checkPosition(endPos)) { |
868 | 397 | MWAW_DEBUG_MSG(("StyleParser::readRules: can not read a rule\n")); |
869 | 397 | input->seek(pos, librevenge::RVNG_SEEK_SET); |
870 | 397 | break; |
871 | 397 | } |
872 | 3.01k | long N1=static_cast<int>(input->readULong(4)); |
873 | 3.01k | f << "N1=" << N1 << ","; |
874 | 9.03k | for (int i=0; i<2; ++i) { // always 0 |
875 | 6.02k | val=static_cast<int>(input->readLong(2)); |
876 | 6.02k | if (val) |
877 | 299 | f << "f" << i << "=" << val << ","; |
878 | 6.02k | } |
879 | 3.01k | MWAWParagraph para; |
880 | 3.01k | if (dSz<8+12*N1) { |
881 | 113 | MWAW_DEBUG_MSG(("StyleParser::readRules: N1 is bad\n")); |
882 | 113 | f << "###N1,"; |
883 | 113 | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
884 | 113 | ascii().addPos(pos); |
885 | 113 | ascii().addNote(f.str().c_str()); |
886 | 113 | m_state->m_paragraphList.push_back(para); |
887 | 113 | continue; |
888 | 113 | } |
889 | 2.89k | ascii().addPos(pos); |
890 | 2.89k | ascii().addNote(f.str().c_str()); |
891 | | |
892 | 2.89k | std::string type(""); |
893 | 7.62k | for (long i=0; i<N1; ++i) { |
894 | 5.03k | pos=input->tell(); |
895 | 5.03k | f.str(""); |
896 | 5.03k | f << "Rule-P" << r << "-" << i << ":"; |
897 | 5.03k | marker=type=""; |
898 | 25.1k | for (int c=0; c<4; ++c) marker+=char(input->readULong(1)); |
899 | 25.1k | for (int c=0; c<4; ++c) type+=char(input->readULong(1)); |
900 | 5.03k | f << marker << "[" << type << "],"; |
901 | 5.03k | dSz=input->readLong(4); |
902 | 5.03k | if (dSz<0 || pos+12+dSz>endPos) { |
903 | 308 | MWAW_DEBUG_MSG(("StyleParser::readRules: can not read a subrule\n")); |
904 | 308 | input->seek(pos, librevenge::RVNG_SEEK_SET); |
905 | 308 | break; |
906 | 308 | } |
907 | 4.73k | if (type=="enum") { |
908 | 2.41k | std::string string(""); |
909 | 12.2k | for (long c=0; c<dSz; ++c) string+=char(input->readULong(1)); |
910 | 2.41k | f << string; |
911 | 2.41k | if (marker=="pjst") { |
912 | 2.17k | if (string=="cent") |
913 | 187 | para.m_justify = MWAWParagraph::JustificationCenter; |
914 | 1.98k | else if (string=="rght") |
915 | 359 | para.m_justify = MWAWParagraph::JustificationRight; |
916 | 1.62k | else if (string=="full") |
917 | 508 | para.m_justify = MWAWParagraph::JustificationFull; |
918 | 1.11k | else if (string!="left") { |
919 | 476 | MWAW_DEBUG_MSG(("StyleParser::readRules: find unexpected align\n")); |
920 | 476 | f << "###align,"; |
921 | 476 | } |
922 | 2.17k | } |
923 | 244 | else if (marker=="BBRD") { // bottom border |
924 | 125 | if (string=="DTDL") { |
925 | 43 | MWAWBorder border; |
926 | 43 | border.m_style=MWAWBorder::Dot; |
927 | 43 | para.m_borders.resize(libmwaw::Bottom+1); |
928 | 43 | para.m_borders[libmwaw::Bottom]=border; |
929 | 43 | } |
930 | 82 | else if (string=="SLDL") { |
931 | 51 | para.m_borders.resize(libmwaw::Bottom+1); |
932 | 51 | para.m_borders[libmwaw::Bottom]=MWAWBorder(); |
933 | 51 | } |
934 | 31 | else if (string=="THKL") { |
935 | 25 | MWAWBorder border; |
936 | 25 | border.m_width=2; |
937 | 25 | para.m_borders.resize(libmwaw::Bottom+1); |
938 | 25 | para.m_borders[libmwaw::Bottom]=border; |
939 | 25 | } |
940 | 6 | else { |
941 | 6 | MWAW_DEBUG_MSG(("StyleParser::readRules: sorry, unknown bottom border\n")); |
942 | 6 | f << "###"; |
943 | 6 | } |
944 | 125 | } |
945 | 119 | else { |
946 | 119 | MWAW_DEBUG_MSG(("StyleParser::readRules: unexpected marker\n")); |
947 | 119 | f << "###"; |
948 | 119 | } |
949 | 2.41k | } |
950 | 2.31k | else if (type=="fixd" && dSz==4) { |
951 | | // riin[right], lein[left], fidt[firstIndent], spaf[after], spbe[before] |
952 | 1.40k | double value=double(input->readLong(4))/65536.; |
953 | 1.40k | f << value; |
954 | 1.40k | if (marker=="ledg") |
955 | 308 | para.setInterline(1.0+value, librevenge::RVNG_PERCENT); |
956 | 1.09k | else if (marker=="lein") |
957 | 324 | para.m_margins[1]=value/72.; |
958 | 768 | else if (marker=="riin") |
959 | 77 | para.m_margins[2]=value/72.; |
960 | 691 | else if (marker=="fidt") |
961 | 174 | para.m_margins[0]=value/72.; |
962 | 517 | else if (marker=="spbe") |
963 | 40 | para.m_spacings[1]=value/72.; |
964 | 477 | else if (marker=="spaf") |
965 | 85 | para.m_spacings[2]=value/72.; |
966 | 392 | else { |
967 | 392 | MWAW_DEBUG_MSG(("StyleParser::readRules: unexpected marker\n")); |
968 | 392 | f << "###"; |
969 | 392 | } |
970 | 1.40k | } |
971 | 915 | else { |
972 | 915 | MWAW_DEBUG_MSG(("StyleParser::readRules: unknown type\n")); |
973 | 915 | f << "###type"; |
974 | 915 | } |
975 | 4.73k | if (dSz%2) ++dSz; |
976 | 4.73k | input->seek(pos+12+dSz, librevenge::RVNG_SEEK_SET); |
977 | 4.73k | ascii().addPos(pos); |
978 | 4.73k | ascii().addNote(f.str().c_str()); |
979 | 4.73k | } |
980 | 2.89k | m_state->m_paragraphList.push_back(para); |
981 | 2.89k | if (input->tell()==endPos) continue; |
982 | | |
983 | 412 | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
984 | 412 | MWAW_DEBUG_MSG(("StyleParser::readRules: find extra data\n")); |
985 | 412 | f.str(""); |
986 | 412 | f << "Rule-P" << r << ":###extra"; |
987 | 412 | ascii().addPos(pos); |
988 | 412 | ascii().addNote(f.str().c_str()); |
989 | 412 | } |
990 | 564 | if (input->tell()!=entry.end()) { |
991 | 384 | MWAW_DEBUG_MSG(("StyleParser::readRules: find extra data\n")); |
992 | 384 | ascii().addPos(input->tell()); |
993 | 384 | ascii().addNote("Rule:###extra"); |
994 | 384 | } |
995 | 564 | return true; |
996 | 1.81k | } |
997 | | |
998 | | bool StyleParser::readPLCs(MWAWEntry const &entry, bool para) |
999 | 8.27k | { |
1000 | 8.27k | MWAWInputStreamPtr input = getInput(); |
1001 | 8.27k | if (!entry.valid() || !input->checkPosition(entry.end()) || (entry.length()%8)!=0) { |
1002 | 133 | MWAW_DEBUG_MSG(("StyleParser::readPLCs: the entry seems bad\n")); |
1003 | 133 | return false; |
1004 | 133 | } |
1005 | 8.13k | entry.setParsed(true); |
1006 | 8.13k | libmwaw::DebugStream f; |
1007 | 8.13k | if (!para) |
1008 | 4.29k | f << "Entries(PLC)[char]:"; |
1009 | 3.84k | else |
1010 | 3.84k | f << "Entries(PLC)[para]:"; |
1011 | 8.13k | std::map<long, int> &map=para ? m_state->m_posParagraphIdMap : m_state->m_posFontIdMap; |
1012 | 8.13k | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
1013 | 8.13k | char wh=para ? 'P' : 'S'; |
1014 | 8.13k | auto N=int(entry.length()/8); |
1015 | 4.23M | for (int i=0; i<N; ++i) { |
1016 | 4.22M | auto pos=long(input->readULong(4)); |
1017 | 4.22M | auto id=static_cast<int>(input->readLong(4)); |
1018 | 4.22M | f << pos; |
1019 | 4.22M | if (id!=-1) f << ":" << wh << id; |
1020 | 4.22M | f << ","; |
1021 | 4.22M | if (map.find(pos)!=map.end()) { |
1022 | 3.21M | MWAW_DEBUG_MSG(("StyleParser::readPLCs: pos %ld already exists\n", pos)); |
1023 | 3.21M | f << "###"; |
1024 | 3.21M | } |
1025 | 1.00M | else |
1026 | 1.00M | map[pos]=id; |
1027 | 4.22M | } |
1028 | 8.13k | ascii().addPos(entry.begin()); |
1029 | 8.13k | ascii().addNote(f.str().c_str()); |
1030 | 8.13k | ascii().addPos(entry.end()); |
1031 | 8.13k | ascii().addNote("_"); |
1032 | 8.13k | return true; |
1033 | 8.27k | } |
1034 | | |
1035 | | //////////////////////////////////////////////////////////// |
1036 | | // picture |
1037 | | //////////////////////////////////////////////////////////// |
1038 | | bool StyleParser::readPictures(MWAWEntry const &entry) |
1039 | 1.83k | { |
1040 | 1.83k | MWAWInputStreamPtr input = getInput(); |
1041 | 1.83k | if (!entry.valid() || !input->checkPosition(entry.end())) { |
1042 | 21 | MWAW_DEBUG_MSG(("StyleParser::readPictures: the entry seems bad\n")); |
1043 | 21 | return false; |
1044 | 21 | } |
1045 | | |
1046 | 1.81k | entry.setParsed(true); |
1047 | 1.81k | ascii().addPos(entry.begin()); |
1048 | 1.81k | ascii().addNote("Entries(Picture):"); |
1049 | 1.81k | ascii().addPos(entry.end()); |
1050 | 1.81k | ascii().addNote("_"); |
1051 | 1.81k | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
1052 | | |
1053 | 1.81k | std::string type; |
1054 | 6.15k | while (input->tell()<entry.end()) { |
1055 | 5.82k | long pos=input->tell(); |
1056 | 5.82k | if (!input->checkPosition(pos+24)) |
1057 | 77 | break; |
1058 | 5.75k | libmwaw::DebugStream f; |
1059 | 5.75k | f << "Picture:"; |
1060 | 5.75k | auto pictPos=long(input->readULong(4)); |
1061 | 5.75k | if (pictPos) f << "pictPos=" << pictPos << ","; |
1062 | 5.75k | StyleParserInternal::Picture pict; |
1063 | 5.75k | type=""; |
1064 | 28.7k | for (int i=0; i<4; ++i) type+=char(input->readULong(1)); |
1065 | 5.75k | f << type << ","; |
1066 | 5.75k | int val; |
1067 | 17.2k | for (int i=0; i<2; ++i) { // always 0? |
1068 | 11.5k | val=static_cast<int>(input->readLong(2)); |
1069 | 11.5k | if (val) |
1070 | 4.47k | f << "f" << i << "=" << val << ","; |
1071 | 11.5k | } |
1072 | 5.75k | long dSz=input->readLong(4); |
1073 | 5.75k | if (dSz<0 || !input->checkPosition(pos+24+dSz)) { |
1074 | 1.40k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1075 | 1.40k | break; |
1076 | 1.40k | } |
1077 | 4.34k | int dim[2]; |
1078 | 8.69k | for (auto &d : dim) d=static_cast<int>(input->readULong(2)); |
1079 | 4.34k | pict.m_size = MWAWVec2i(dim[1],dim[0]); |
1080 | 4.34k | f << "sz=" << pict.m_size << ","; |
1081 | 13.0k | for (int i=0; i<2; ++i) { // always 0 |
1082 | 8.69k | val=static_cast<int>(input->readLong(2)); |
1083 | 8.69k | if (val) |
1084 | 4.46k | f << "f" << i+2 << "=" << val << ","; |
1085 | 8.69k | } |
1086 | | |
1087 | 4.34k | ascii().addPos(pos); |
1088 | 4.34k | ascii().addNote(f.str().c_str()); |
1089 | 4.34k | if (!dSz) continue; |
1090 | | |
1091 | 2.65k | pict.m_entry.setBegin(pos+24); |
1092 | 2.65k | pict.m_entry.setLength(dSz); |
1093 | 2.65k | if (m_state->m_posPictureMap.find(pictPos) != m_state->m_posPictureMap.end()) { |
1094 | 123 | MWAW_DEBUG_MSG(("StyleParser::readPictures: a picture already exist at %ld\n", pictPos)); |
1095 | 123 | } |
1096 | 2.53k | else |
1097 | 2.53k | m_state->m_posPictureMap[pictPos]=pict; |
1098 | | #ifdef DEBUG_WITH_FILES |
1099 | | ascii().skipZone(pos+24, pos+24+dSz-1); |
1100 | | librevenge::RVNGBinaryData file; |
1101 | | input->seek(pos+24, librevenge::RVNG_SEEK_SET); |
1102 | | input->readDataBlock(dSz, file); |
1103 | | static int volatile pictName = 0; |
1104 | | libmwaw::DebugStream f2; |
1105 | | f2 << "PICT-" << ++pictName << ".pct"; |
1106 | | libmwaw::Debug::dumpFile(file, f2.str().c_str()); |
1107 | | #endif |
1108 | 2.65k | input->seek(pos+24+dSz, librevenge::RVNG_SEEK_SET); |
1109 | 2.65k | } |
1110 | 1.81k | if (input->tell()!=entry.end()) { |
1111 | 1.66k | MWAW_DEBUG_MSG(("StyleParser::readPictures: find extra data\n")); |
1112 | 1.66k | ascii().addPos(input->tell()); |
1113 | 1.66k | ascii().addNote("Picture:###extra"); |
1114 | 1.66k | } |
1115 | 1.81k | return true; |
1116 | | |
1117 | 1.83k | } |
1118 | | //////////////////////////////////////////////////////////// |
1119 | | // other |
1120 | | //////////////////////////////////////////////////////////// |
1121 | | bool StyleParser::readExtraProperties(MWAWEntry const &entry) |
1122 | 1.38k | { |
1123 | 1.38k | MWAWInputStreamPtr input = getInput(); |
1124 | 1.38k | if (!entry.valid() || !input->checkPosition(entry.end()) || entry.length()<16) { |
1125 | 76 | MWAW_DEBUG_MSG(("StyleParser::readExtraProperties: the entry seems bad\n")); |
1126 | 76 | return false; |
1127 | 76 | } |
1128 | 1.31k | entry.setParsed(true); |
1129 | 1.31k | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
1130 | 1.31k | ascii().addPos(entry.end()); |
1131 | 1.31k | ascii().addNote("_"); |
1132 | 1.31k | libmwaw::DebugStream f; |
1133 | 1.31k | f << "Entries(XProp):"; |
1134 | 1.31k | std::string marker(""); |
1135 | 6.56k | for (int c=0; c<4; ++c) marker+=char(input->readULong(1)); |
1136 | 1.31k | if (marker!="grow" && marker!="More") { |
1137 | 619 | MWAW_DEBUG_MSG(("StyleParser::readExtraProperties: can not find main marker\n")); |
1138 | 619 | f << "###marker=" << marker << ","; |
1139 | 619 | ascii().addPos(entry.begin()); |
1140 | 619 | ascii().addNote(f.str().c_str()); |
1141 | 619 | return true; |
1142 | 619 | } |
1143 | 693 | f << marker << ","; |
1144 | 693 | int val; |
1145 | 4.15k | for (int i=0; i<5; ++i) { |
1146 | 3.46k | val=static_cast<int>(input->readLong(2)); |
1147 | 3.46k | static const int expected[]= {1,0,0x4000,0,0}; |
1148 | 3.46k | if (val!=expected[i]) |
1149 | 1.89k | f << "f" << i << "=" << val << ","; |
1150 | 3.46k | } |
1151 | 693 | auto N=static_cast<int>(input->readULong(2)); |
1152 | 693 | f << "N=" << N << ","; |
1153 | 693 | if (16*(N+1)>entry.length()) { |
1154 | 24 | MWAW_DEBUG_MSG(("StyleParser::readExtraProperties: can not read the number of entry\n")); |
1155 | 24 | f << "###"; |
1156 | 24 | ascii().addPos(entry.begin()); |
1157 | 24 | ascii().addNote(f.str().c_str()); |
1158 | 24 | return true; |
1159 | 24 | } |
1160 | 669 | ascii().addPos(entry.begin()); |
1161 | 669 | ascii().addNote(f.str().c_str()); |
1162 | 669 | std::vector<MWAWEntry> entryList; |
1163 | 3.27k | for (int x=0; x<N; ++x) { |
1164 | 2.60k | long pos=input->tell(); |
1165 | 2.60k | f.str(""); |
1166 | 2.60k | f << "XProp-" << x << ":"; |
1167 | 2.60k | marker=""; |
1168 | 13.0k | for (int c=0; c<4; ++c) marker+=char(input->readULong(1)); |
1169 | 2.60k | f << marker << ","; |
1170 | 2.60k | int id=1; |
1171 | 2.60k | if (marker!="Info") { |
1172 | 2.40k | id=static_cast<int>(input->readLong(4)); |
1173 | 2.40k | if (id!=1) f << "id=" << id << ","; |
1174 | 2.40k | } |
1175 | 195 | else { |
1176 | 195 | std::string type; |
1177 | 975 | for (int c=0; c<4; ++c) type+=char(input->readULong(1)); |
1178 | 195 | f << type << ","; |
1179 | 195 | } |
1180 | 7.80k | for (int i=0; i<2; ++i) { |
1181 | 5.20k | val=static_cast<int>(input->readLong(2)); |
1182 | 5.20k | static const int expected[]= {0x4000,0}; |
1183 | 5.20k | if (val==expected[i]) |
1184 | 1.19k | continue; |
1185 | 4.01k | f << "f" << i << "=" << val << ","; |
1186 | 4.01k | } |
1187 | 2.60k | long dPos=input->readLong(4); |
1188 | 2.60k | f << "pos=" << dPos << ","; |
1189 | 2.60k | ascii().addPos(pos); |
1190 | 2.60k | ascii().addNote(f.str().c_str()); |
1191 | | |
1192 | 2.60k | if (dPos>0 && 16*(N+1)+dPos<entry.length()) { |
1193 | 720 | MWAWEntry dEntry; |
1194 | 720 | dEntry.setType(marker); |
1195 | 720 | dEntry.setId(id); |
1196 | 720 | dEntry.setBegin(entry.begin()+16*(N+1)+dPos); |
1197 | 720 | entryList.push_back(dEntry); |
1198 | 720 | } |
1199 | 1.88k | else if (dPos) { |
1200 | 1.41k | ascii().addPos(pos); |
1201 | 1.41k | ascii().addNote("###"); |
1202 | 1.41k | MWAW_DEBUG_MSG(("StyleParser::readExtraProperties: dataPos seems bad\n")); |
1203 | 1.41k | } |
1204 | 2.60k | } |
1205 | | |
1206 | 669 | long pos=input->tell(); |
1207 | 669 | if (pos==entry.end() && entryList.empty()) |
1208 | 100 | return true; |
1209 | 569 | auto dSize=long(input->readULong(4)); |
1210 | 569 | f.str(""); |
1211 | 569 | f << "XProp[dataSz]:sz=" << dSize << ","; |
1212 | 569 | if (dSize<0 || !input->checkPosition(pos+4+dSize)) { |
1213 | 144 | MWAW_DEBUG_MSG(("StyleParser::readExtraProperties: can not read data size\n")); |
1214 | 144 | f << "###"; |
1215 | 144 | ascii().addPos(pos); |
1216 | 144 | ascii().addNote(f.str().c_str()); |
1217 | 144 | return true; |
1218 | 144 | } |
1219 | 425 | ascii().addPos(pos); |
1220 | 425 | ascii().addNote(f.str().c_str()); |
1221 | | |
1222 | 665 | for (auto const &dEntry : entryList) { |
1223 | 665 | f.str(""); |
1224 | 665 | f << "XProp[" << dEntry.type() << "-" << dEntry.id() << "]:"; |
1225 | 665 | input->seek(dEntry.begin(), librevenge::RVNG_SEEK_SET); |
1226 | 665 | dSize=long(input->readULong(4)); |
1227 | 665 | long endPos=dEntry.begin()+4+dSize; |
1228 | 665 | if (dSize<0 || !input->checkPosition(endPos)) { |
1229 | 193 | MWAW_DEBUG_MSG(("StyleParser::readExtraProperties: can not read a data size\n")); |
1230 | 193 | f << "###"; |
1231 | 193 | ascii().addPos(pos); |
1232 | 193 | ascii().addNote(f.str().c_str()); |
1233 | 193 | continue; |
1234 | 193 | } |
1235 | 472 | if (dSize==1 && (dEntry.type()=="covr" || dEntry.type()=="cusg" || |
1236 | 26 | dEntry.type()=="ehnd" || dEntry.type()=="ornt" || |
1237 | 26 | dEntry.type()=="Coll" || dEntry.type()=="Dgok")) |
1238 | 0 | f << "val=" << input->readLong(1) << ","; |
1239 | 472 | else if (dSize==4 && (dEntry.type()=="copy" || dEntry.type()=="NTnt"|| dEntry.type()=="Ucpy")) |
1240 | 0 | f << "val=" << input->readLong(4) << ","; |
1241 | 472 | else if (dSize==6 && dEntry.type()=="Bkpr") { |
1242 | 0 | for (int i=0; i<2; ++i) { // fl0=fl1=1 |
1243 | 0 | val=static_cast<int>(input->readLong(1)); |
1244 | 0 | if (val) f << "fl" << i << "=" << val << ","; |
1245 | 0 | } |
1246 | 0 | f << "ids=["; // af84,4f8 | b291,de8c |
1247 | 0 | for (int i=0; i<2; ++i) f << std::hex << input->readULong(2) << std::dec << ","; |
1248 | 0 | f << "],"; |
1249 | 0 | } |
1250 | 472 | else if (dSize==20 && dEntry.type()=="nupd") { |
1251 | 0 | for (int i=0; i<10; ++i) { // f5=f7=1, f8=-256, f9=1|168 |
1252 | 0 | val=static_cast<int>(input->readLong(2)); |
1253 | 0 | if (val) f << "f" << i << "=" << val << ","; |
1254 | 0 | } |
1255 | 0 | } |
1256 | 472 | else if (dSize>7 && dEntry.type()=="dprf") { |
1257 | 4 | for (int i=0; i<3; ++i) { // f0=-1, f2=635f |
1258 | 3 | val=static_cast<int>(input->readLong(2)); |
1259 | 3 | if (val) f << "f" << i << "=" << val << ","; |
1260 | 3 | } |
1261 | 1 | auto dSz=static_cast<int>(input->readULong(1)); |
1262 | 1 | if (dSz+7<=dSize) { |
1263 | | // printer name |
1264 | 0 | std::string text(""); |
1265 | 0 | for (int i=0; i<dSz; ++i) text+=char(input->readULong(1)); |
1266 | 0 | f << text << ","; |
1267 | | // then 793530010cf85c010cf86001032fe80000000000000000010cf6180000004c01032fe8ffff |
1268 | 0 | } |
1269 | 1 | else |
1270 | 1 | f << "###dSz=" << dSz << ","; |
1271 | 1 | } |
1272 | 471 | else if (dSize>=1 && dEntry.type()=="psnt") { // find A4Small, |
1273 | 21 | auto dSz=static_cast<int>(input->readULong(1)); |
1274 | 21 | if (dSz+1<=dSize) { |
1275 | 21 | std::string text(""); |
1276 | 175 | for (int i=0; i<dSz; ++i) text+=char(input->readULong(1)); |
1277 | 21 | f << text << ","; |
1278 | 21 | } |
1279 | 0 | else |
1280 | 0 | f << "###dSz=" << dSz << ","; |
1281 | 21 | } |
1282 | 450 | else if (dEntry.type()=="feat") { // find InputSlot,Upper,ManualFeed,False,PageRegion,A4Small |
1283 | 16.3k | while (input->tell()<endPos) { |
1284 | 16.3k | auto dSz=static_cast<int>(input->readULong(1)); |
1285 | 16.3k | if (input->tell()+dSz>endPos) { |
1286 | 112 | MWAW_DEBUG_MSG(("StyleParser::readExtraProperties: can not read a feat string\n")); |
1287 | 112 | f << "###dSz=" << dSz << ","; |
1288 | 112 | break; |
1289 | 112 | } |
1290 | 16.1k | std::string text(""); |
1291 | 108k | for (int i=0; i<dSz; ++i) text+=char(input->readULong(1)); |
1292 | 16.1k | f << text << ","; |
1293 | 16.1k | } |
1294 | 134 | } |
1295 | 316 | else if (dSize>=1 && dEntry.type()=="Info") { |
1296 | 132 | std::string text(""); |
1297 | 5.18k | for (long i=0; i<dSize; ++i) text+=char(input->readULong(1)); |
1298 | 132 | f << text << ","; |
1299 | 132 | } |
1300 | 184 | else if (dEntry.type()=="ppnf") { |
1301 | 16 | auto dSz=static_cast<int>(input->readULong(2)); |
1302 | 16 | if (dSz+2<=dSize) { // A4Small |
1303 | 0 | std::string text(""); |
1304 | 0 | for (int i=0; i<dSz; ++i) text+=char(input->readULong(1)); |
1305 | 0 | f << text << ","; |
1306 | | /* then 000000006c61fd03ae816000554c7803ae8180220002480bfc44d00000000003ae8190000e4734041fccb400000000fe0200000000000103ae81d0000000c003ae81b00062666400000023 */ |
1307 | 0 | } |
1308 | 16 | else |
1309 | 16 | f << "###dSz=" << dSz << ","; |
1310 | 16 | } |
1311 | 168 | else { |
1312 | 168 | MWAW_DEBUG_MSG(("StyleParser::readExtraProperties: find unknown type\n")); |
1313 | 168 | f << "###unknown"; |
1314 | 168 | } |
1315 | 472 | if (input->tell()!=endPos) |
1316 | 232 | ascii().addDelimiter(input->tell(),'|'); |
1317 | 472 | ascii().addPos(dEntry.begin()); |
1318 | 472 | ascii().addNote(f.str().c_str()); |
1319 | 472 | ascii().addPos(endPos); |
1320 | 472 | ascii().addNote("_"); |
1321 | 472 | } |
1322 | 425 | return true; |
1323 | 569 | } |
1324 | | |
1325 | | bool StyleParser::readBackgroundColor(MWAWEntry const &entry) |
1326 | 1.56k | { |
1327 | 1.56k | MWAWInputStreamPtr input = getInput(); |
1328 | 1.56k | if (!entry.valid() || !input->checkPosition(entry.end())) { |
1329 | 65 | MWAW_DEBUG_MSG(("StyleParser::readBackgroundColor: the entry seems bad\n")); |
1330 | 65 | return false; |
1331 | 65 | } |
1332 | 1.50k | entry.setParsed(true); |
1333 | 1.50k | libmwaw::DebugStream f; |
1334 | 1.50k | f << "Entries(BgColor):"; |
1335 | 1.50k | if (entry.length()!=6) { |
1336 | 56 | MWAW_DEBUG_MSG(("StyleParser::readBackgroundColor: the entry size seems bad\n")); |
1337 | 56 | f << "###"; |
1338 | 56 | } |
1339 | 1.44k | else { |
1340 | 1.44k | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
1341 | 1.44k | unsigned char col[3]; |
1342 | 4.33k | for (auto &c : col) c=static_cast<unsigned char>(input->readULong(2)>>8); |
1343 | 1.44k | m_state->m_backgroundColor=MWAWColor(col[0], col[1], col[2]); |
1344 | 1.44k | f << m_state->m_backgroundColor << ","; |
1345 | 1.44k | } |
1346 | | |
1347 | 1.50k | ascii().addPos(entry.begin()); |
1348 | 1.50k | ascii().addNote(f.str().c_str()); |
1349 | 1.50k | ascii().addPos(entry.end()); |
1350 | 1.50k | ascii().addNote("_"); |
1351 | 1.50k | return true; |
1352 | 1.56k | } |
1353 | | |
1354 | | bool StyleParser::readMargins(MWAWEntry const &entry) |
1355 | 1.65k | { |
1356 | 1.65k | MWAWInputStreamPtr input = getInput(); |
1357 | 1.65k | if (!entry.valid() || !input->checkPosition(entry.end())) { |
1358 | 15 | MWAW_DEBUG_MSG(("StyleParser::readMargins: the entry seems bad\n")); |
1359 | 15 | return false; |
1360 | 15 | } |
1361 | 1.64k | entry.setParsed(true); |
1362 | 1.64k | libmwaw::DebugStream f; |
1363 | 1.64k | f << "Entries(Margins):"; |
1364 | 1.64k | if (entry.length()!=16) { |
1365 | 159 | MWAW_DEBUG_MSG(("StyleParser::readMargins: the entry size seems bad\n")); |
1366 | 159 | f << "###"; |
1367 | 159 | } |
1368 | 1.48k | else { |
1369 | 1.48k | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
1370 | 1.48k | float margins[4]; |
1371 | 1.48k | bool ok=true; |
1372 | 1.48k | f << "marg=["; |
1373 | 5.92k | for (auto &margin : margins) { |
1374 | 5.92k | margin=float(input->readULong(4))/72.0f/65536.0f; |
1375 | 5.92k | if (margin<0) { |
1376 | 0 | MWAW_DEBUG_MSG(("StyleParser::readMargins: some margin seems bad\n")); |
1377 | 0 | f << "###"; |
1378 | 0 | ok = false; |
1379 | 0 | } |
1380 | 5.92k | f << margin << ","; |
1381 | 5.92k | } |
1382 | 1.48k | f << "],"; |
1383 | 1.48k | if (ok) { // checkme: order |
1384 | 1.48k | getPageSpan().setMarginLeft(double(margins[0])); |
1385 | 1.48k | getPageSpan().setMarginTop(double(margins[1])); |
1386 | 1.48k | getPageSpan().setMarginRight(double(margins[2])); |
1387 | 1.48k | getPageSpan().setMarginBottom(double(margins[3])); |
1388 | 1.48k | } |
1389 | 1.48k | } |
1390 | | |
1391 | 1.64k | ascii().addPos(entry.begin()); |
1392 | 1.64k | ascii().addNote(f.str().c_str()); |
1393 | 1.64k | ascii().addPos(entry.end()); |
1394 | 1.64k | ascii().addNote("_"); |
1395 | 1.64k | return true; |
1396 | 1.65k | } |
1397 | | |
1398 | | bool StyleParser::readPrintInfo(MWAWEntry const &entry) |
1399 | 1.96k | { |
1400 | 1.96k | MWAWInputStreamPtr input = getInput(); |
1401 | 1.96k | if (!entry.valid() || !input->checkPosition(entry.end()) || entry.length() < 0x78) { |
1402 | 185 | MWAW_DEBUG_MSG(("StyleParser::readPrintInfo: zone size is invalid\n")); |
1403 | 185 | return false; |
1404 | 185 | } |
1405 | | |
1406 | 1.77k | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
1407 | 1.77k | libmwaw::DebugStream f; |
1408 | 1.77k | f << "Entries(PrintInfo):"; |
1409 | 1.77k | libmwaw::PrinterInfo info; |
1410 | 1.77k | if (!info.read(input)) { |
1411 | 1.29k | MWAW_DEBUG_MSG(("StyleParser::readPrintInfo: can not read print info\n")); |
1412 | 1.29k | return false; |
1413 | 1.29k | } |
1414 | 482 | entry.setParsed(true); |
1415 | 482 | f << info; |
1416 | | |
1417 | 482 | MWAWVec2i paperSize = info.paper().size(); |
1418 | 482 | MWAWVec2i pageSize = info.page().size(); |
1419 | 482 | if (pageSize.x() <= 0 || pageSize.y() <= 0 || |
1420 | 406 | paperSize.x() <= 0 || paperSize.y() <= 0) { |
1421 | 120 | MWAW_DEBUG_MSG(("StyleParser::readPrintInfo: the paper size seems bad\n")); |
1422 | 120 | f << "###"; |
1423 | 120 | ascii().addPos(entry.begin()); |
1424 | 120 | ascii().addNote(f.str().c_str()); |
1425 | 120 | ascii().addPos(entry.end()); |
1426 | 120 | ascii().addNote("_"); |
1427 | 120 | return true; |
1428 | 120 | } |
1429 | | |
1430 | | // define margin from print info |
1431 | 362 | MWAWVec2i lTopMargin= -1 * info.paper().pos(0); |
1432 | 362 | MWAWVec2i rBotMargin=info.paper().size() - info.page().size(); |
1433 | | |
1434 | 362 | getPageSpan().setMarginTop(lTopMargin.y()/72.0); |
1435 | 362 | getPageSpan().setMarginBottom(rBotMargin.y()/72.0); |
1436 | 362 | getPageSpan().setMarginLeft(lTopMargin.x()/72.0); |
1437 | 362 | getPageSpan().setMarginRight(rBotMargin.x()/72.0); |
1438 | 362 | getPageSpan().setFormLength(paperSize.y()/72.); |
1439 | 362 | getPageSpan().setFormWidth(paperSize.x()/72.); |
1440 | | |
1441 | 362 | ascii().addPos(entry.begin()); |
1442 | 362 | ascii().addNote(f.str().c_str()); |
1443 | 362 | ascii().addPos(entry.end()); |
1444 | 362 | ascii().addNote("_"); |
1445 | 362 | return true; |
1446 | 482 | } |
1447 | | |
1448 | | bool StyleParser::readStat(MWAWEntry const &entry) |
1449 | 1.29k | { |
1450 | 1.29k | MWAWInputStreamPtr input = getInput(); |
1451 | 1.29k | if (!entry.valid() || !input->checkPosition(entry.end())) { |
1452 | 42 | MWAW_DEBUG_MSG(("StyleParser::readStat: the entry seems bad\n")); |
1453 | 42 | return false; |
1454 | 42 | } |
1455 | 1.25k | entry.setParsed(true); |
1456 | 1.25k | libmwaw::DebugStream f; |
1457 | 1.25k | f << "Entries(Stat):"; |
1458 | 1.25k | if (entry.length()!=40) { |
1459 | 41 | MWAW_DEBUG_MSG(("StyleParser::readStat: the entry size seems bad\n")); |
1460 | 41 | f << "###"; |
1461 | 41 | } |
1462 | 1.21k | else { |
1463 | 1.21k | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
1464 | 1.21k | f << "ids=["; |
1465 | 3.63k | for (int i=0; i<2; ++i) f << std::hex << input->readULong(2) << std::dec << ","; |
1466 | 1.21k | f << "],"; |
1467 | 1.21k | int dim[4]; |
1468 | 4.84k | for (auto &d : dim) d=static_cast<int>(input->readLong(2)); |
1469 | 1.21k | f << "dim?=" << MWAWBox2i(MWAWVec2i(dim[1],dim[0]), MWAWVec2i(dim[3],dim[2])) << ","; |
1470 | 18.1k | for (int i=0; i<14; ++i) { // f4=0|-1, f5=0|-2292, f13=0|1|3 |
1471 | 16.9k | auto val=static_cast<int>(input->readLong(2)); |
1472 | 16.9k | if (val) |
1473 | 12.2k | f << "f" << i << "=" << val << ","; |
1474 | 16.9k | } |
1475 | 1.21k | } |
1476 | | |
1477 | 1.25k | ascii().addPos(entry.begin()); |
1478 | 1.25k | ascii().addNote(f.str().c_str()); |
1479 | 1.25k | ascii().addPos(entry.end()); |
1480 | 1.25k | ascii().addNote("_"); |
1481 | 1.25k | return true; |
1482 | 1.29k | } |
1483 | | |
1484 | | bool StyleParser::readTabWidth(MWAWEntry const &entry) |
1485 | 1.15k | { |
1486 | 1.15k | MWAWInputStreamPtr input = getInput(); |
1487 | 1.15k | if (!entry.valid() || !input->checkPosition(entry.end())) { |
1488 | 133 | MWAW_DEBUG_MSG(("StyleParser::readTabWidth: the entry seems bad\n")); |
1489 | 133 | return false; |
1490 | 133 | } |
1491 | 1.02k | entry.setParsed(true); |
1492 | 1.02k | libmwaw::DebugStream f; |
1493 | 1.02k | f << "Entries(TabWidth):"; |
1494 | 1.02k | if (entry.length()!=4) { |
1495 | 42 | MWAW_DEBUG_MSG(("StyleParser::readTabWidth: the entry size seems bad\n")); |
1496 | 42 | f << "###"; |
1497 | 42 | } |
1498 | 979 | else { |
1499 | 979 | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
1500 | 979 | f << "val=" << float(input->readLong(4))/72.f/65536.f; |
1501 | 979 | } |
1502 | | |
1503 | 1.02k | ascii().addPos(entry.begin()); |
1504 | 1.02k | ascii().addNote(f.str().c_str()); |
1505 | 1.02k | ascii().addPos(entry.end()); |
1506 | 1.02k | ascii().addNote("_"); |
1507 | 1.02k | return true; |
1508 | 1.15k | } |
1509 | | |
1510 | | bool StyleParser::readVersion(MWAWEntry const &entry) |
1511 | 3.00k | { |
1512 | 3.00k | MWAWInputStreamPtr input = getInput(); |
1513 | 3.00k | if (!entry.valid() || !input->checkPosition(entry.end())) { |
1514 | 37 | MWAW_DEBUG_MSG(("StyleParser::readVersion: the entry seems bad\n")); |
1515 | 37 | return false; |
1516 | 37 | } |
1517 | 2.97k | entry.setParsed(true); |
1518 | 2.97k | libmwaw::DebugStream f; |
1519 | 2.97k | f << "Entries(Version):"; |
1520 | 2.97k | if (entry.length()!=4) { |
1521 | 40 | MWAW_DEBUG_MSG(("StyleParser::readVersion: the entry size seems bad\n")); |
1522 | 40 | f << "###"; |
1523 | 40 | } |
1524 | 2.93k | else { |
1525 | 2.93k | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
1526 | | // find 0x160 for version 1.6, 0x191 for version 1.9.1 |
1527 | 2.93k | f << "vers=" << std::hex << input->readULong(2) << std::dec << ","; |
1528 | 2.93k | auto val=static_cast<int>(input->readULong(2)); |
1529 | 2.93k | if (val!=0x8000) |
1530 | 730 | f << "f0=" << std::hex << val << std::dec << ","; |
1531 | 2.93k | } |
1532 | | |
1533 | 2.97k | ascii().addPos(entry.begin()); |
1534 | 2.97k | ascii().addNote(f.str().c_str()); |
1535 | 2.97k | ascii().addPos(entry.end()); |
1536 | 2.97k | ascii().addNote("_"); |
1537 | 2.97k | return true; |
1538 | 3.00k | } |
1539 | | |
1540 | | //////////////////////////////////////////////////////////// |
1541 | | // send data |
1542 | | //////////////////////////////////////////////////////////// |
1543 | | int StyleParser::computeNumPages(MWAWEntry const &entry, bool unicodeChar) const |
1544 | 5.67k | { |
1545 | 5.67k | MWAWInputStreamPtr input = const_cast<StyleParser *>(this)->getInput(); |
1546 | 5.67k | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
1547 | 5.67k | int nPages=1; |
1548 | | |
1549 | 5.67k | int const cSize=unicodeChar ? 2 : 1; |
1550 | 17.0M | while (!input->isEnd() && input->tell()<entry.end()) { |
1551 | 17.0M | if (input->readLong(cSize)==0xc) |
1552 | 27.1k | nPages++; |
1553 | 17.0M | } |
1554 | 5.67k | return nPages; |
1555 | 5.67k | } |
1556 | | |
1557 | | bool StyleParser::sendText(MWAWEntry const &entry, bool unicodeChar) |
1558 | 6.24k | { |
1559 | 6.24k | if (!getTextListener()) { |
1560 | 0 | MWAW_DEBUG_MSG(("StyleParser::sendText: can not find the listener\n")); |
1561 | 0 | return false; |
1562 | 0 | } |
1563 | 6.24k | if (!entry.valid()) { |
1564 | | // ok no text |
1565 | 571 | return true; |
1566 | 571 | } |
1567 | 5.67k | MWAWInputStreamPtr input = getInput(); |
1568 | 5.67k | long debPos=entry.begin(); |
1569 | 5.67k | input->seek(debPos, librevenge::RVNG_SEEK_SET); |
1570 | | |
1571 | 5.67k | libmwaw::DebugStream f; |
1572 | 5.67k | f << "Entries(TEXT):"; |
1573 | 5.67k | getTextListener()->setFont(MWAWFont(3,12)); |
1574 | | |
1575 | 5.67k | int actPage=1; |
1576 | 5.67k | auto numFonts=static_cast<int>(m_state->m_fontList.size()); |
1577 | 5.67k | auto numParagraphs=static_cast<int>(m_state->m_paragraphList.size()); |
1578 | 5.67k | long endChar = entry.length(), endPos = entry.end(); |
1579 | 5.67k | int const cSize=unicodeChar ? 2 : 1; |
1580 | 17.0M | for (long i=0; i <= endChar; i+=cSize) { |
1581 | 17.0M | bool isEnd = i==endChar; |
1582 | 17.0M | int c=isEnd ? static_cast<int>(0) : static_cast<int>(input->readULong(cSize)); |
1583 | 17.0M | if (isEnd || c==0xd || c==0xc || c==0x2029) { |
1584 | 85.0k | ascii().addPos(debPos); |
1585 | 85.0k | ascii().addNote(f.str().c_str()); |
1586 | 85.0k | debPos = input->tell(); |
1587 | 85.0k | if (isEnd) break; |
1588 | 79.6k | f.str(""); |
1589 | 79.6k | f << "TEXT:"; |
1590 | 79.6k | } |
1591 | 17.0M | auto plcIt=m_state->m_posParagraphIdMap.find(i); |
1592 | 17.0M | if (plcIt != m_state->m_posParagraphIdMap.end()) { |
1593 | 27.5k | if (plcIt->second>=0 && plcIt->second<numParagraphs) |
1594 | 2.47k | getTextListener()->setParagraph(m_state->m_paragraphList[size_t(plcIt->second)]); |
1595 | 27.5k | f << "[Style:P" << plcIt->second << "]"; |
1596 | 27.5k | } |
1597 | 17.0M | plcIt=m_state->m_posFontIdMap.find(i); |
1598 | 17.0M | if (plcIt != m_state->m_posFontIdMap.end()) { |
1599 | 51.9k | if (plcIt->second>=0 && plcIt->second<numFonts) { |
1600 | 20.8k | auto const &font=m_state->m_fontList[size_t(plcIt->second)]; |
1601 | 20.8k | getTextListener()->setFont(font.m_font); |
1602 | 20.8k | if (font.hasPicture()) |
1603 | 452 | sendPicture(font.m_picture); |
1604 | 20.8k | } |
1605 | 51.9k | f << "[Style:C" << plcIt->second << "]"; |
1606 | 51.9k | } |
1607 | 17.0M | if (c>=0x100) |
1608 | 9.63M | f << "[" << std::hex << c << std::dec << "]"; |
1609 | 7.37M | else if (c) |
1610 | 2.33M | f << char(c); |
1611 | 17.0M | if (c==0xc) { |
1612 | 26.9k | newPage(++actPage); |
1613 | 26.9k | continue; |
1614 | 26.9k | } |
1615 | 16.9M | if (c==0 && !unicodeChar && !isEnd) { |
1616 | | // tex-edit accept control character, ... |
1617 | 82.5k | auto nextC=static_cast<unsigned char>(input->readULong(1)); |
1618 | 82.5k | if (nextC < 0x20) { |
1619 | 72.7k | i++; |
1620 | 72.7k | getTextListener()->insertChar('^'); |
1621 | 72.7k | getTextListener()->insertChar(uint8_t('@'+nextC)); |
1622 | 72.7k | continue; |
1623 | 72.7k | } |
1624 | 9.84k | input->seek(-1, librevenge::RVNG_SEEK_CUR); |
1625 | 9.84k | } |
1626 | 16.9M | switch (c) { |
1627 | 198k | case 0x1: |
1628 | 198k | if (m_state->m_posPictureMap.find(i)==m_state->m_posPictureMap.end() || |
1629 | 197k | !m_state->m_posPictureMap.find(i)->second.valid()) { |
1630 | 197k | MWAW_DEBUG_MSG(("StyleParser::sendPicture: can not find picture for id=%ld\n",i)); |
1631 | 197k | f << "[##pict]"; |
1632 | 197k | break; |
1633 | 197k | } |
1634 | 242 | sendPicture(m_state->m_posPictureMap.find(i)->second); |
1635 | 242 | break; |
1636 | 24.5k | case 0x9: |
1637 | 24.5k | getTextListener()->insertTab(); |
1638 | 24.5k | break; |
1639 | 1.29k | case 0x2028: |
1640 | 1.29k | getTextListener()->insertEOL(true); |
1641 | 1.29k | break; |
1642 | 17.3k | case 0xd: |
1643 | 52.7k | case 0x2029: |
1644 | 52.7k | getTextListener()->insertEOL(); |
1645 | 52.7k | break; |
1646 | 14.3k | case 0x11: // command key |
1647 | 14.3k | getTextListener()->insertUnicode(0x2318); |
1648 | 14.3k | break; |
1649 | 30.5k | case 0x14: // apple logo: check me |
1650 | 30.5k | getTextListener()->insertUnicode(0xf8ff); |
1651 | 30.5k | break; |
1652 | 4.77k | case 0xfffc: // image |
1653 | 4.77k | break; |
1654 | 16.5M | default: |
1655 | 16.5M | if (c < 0x20) f << "##[" << std::hex << c << std::dec << "]"; |
1656 | 16.5M | if (unicodeChar) |
1657 | 16.3M | getTextListener()->insertUnicode(uint32_t(c)); |
1658 | 276k | else |
1659 | 276k | i += getTextListener()->insertCharacter(static_cast<unsigned char>(c), input, endPos); |
1660 | 16.5M | break; |
1661 | 16.9M | } |
1662 | 16.9M | } |
1663 | 5.67k | return true; |
1664 | 5.67k | } |
1665 | | |
1666 | | // the pictures |
1667 | | bool StyleParser::sendPicture(StyleParserInternal::Picture const &pict) |
1668 | 694 | { |
1669 | 694 | if (!getTextListener()) { |
1670 | 0 | MWAW_DEBUG_MSG(("StyleParser::sendPicture: can not find the listener\n")); |
1671 | 0 | return false; |
1672 | 0 | } |
1673 | | |
1674 | 694 | MWAWInputStreamPtr input = getInput(); |
1675 | 694 | librevenge::RVNGBinaryData data; |
1676 | 694 | long pos = input->tell(); |
1677 | 694 | input->seek(pict.m_entry.begin(), librevenge::RVNG_SEEK_SET); |
1678 | 694 | input->readDataBlock(pict.m_entry.length(), data); |
1679 | 694 | input->seek(pos,librevenge::RVNG_SEEK_SET); |
1680 | | |
1681 | 694 | auto dataSz=int(data.size()); |
1682 | 694 | if (!dataSz) |
1683 | 0 | return false; |
1684 | 694 | MWAWPosition pictPos=MWAWPosition(MWAWVec2f(0,0),MWAWVec2f(pict.m_size), librevenge::RVNG_POINT); |
1685 | 694 | pictPos.setRelativePosition(MWAWPosition::Char); |
1686 | 694 | MWAWEmbeddedObject picture(data); |
1687 | 694 | getTextListener()->insertPicture(pictPos, picture); |
1688 | 694 | return true; |
1689 | 694 | } |
1690 | | |
1691 | | //////////////////////////////////////////////////////////// |
1692 | | // |
1693 | | // Low level |
1694 | | // |
1695 | | //////////////////////////////////////////////////////////// |
1696 | | |
1697 | | |
1698 | | //////////////////////////////////////////////////////////// |
1699 | | // read the header |
1700 | | //////////////////////////////////////////////////////////// |
1701 | | bool StyleParser::checkHeader(MWAWHeader *header, bool strict) |
1702 | 38.4k | { |
1703 | 38.4k | *m_state = StyleParserInternal::State(); |
1704 | 38.4k | MWAWInputStreamPtr input = getInput(); |
1705 | 38.4k | if (!input || !input->hasDataFork() || !input->checkPosition(40)) |
1706 | 140 | return false; |
1707 | 38.3k | input->seek(0, librevenge::RVNG_SEEK_SET); |
1708 | 38.3k | if (input->readULong(2)!=0x4348 || input->readULong(2)!=0x4e4b || |
1709 | 38.1k | input->readULong(2)!=0x100 || input->readULong(2)!=0) |
1710 | 311 | return false; |
1711 | 38.0k | if (strict && !readTypeEntryMap()) |
1712 | 3.23k | return false; |
1713 | 34.7k | setVersion(1); |
1714 | 34.7k | if (header) |
1715 | 13.4k | header->reset(MWAWDocument::MWAW_T_STYLE, version()); |
1716 | 34.7k | ascii().addPos(0); |
1717 | 34.7k | ascii().addNote("FileHeader:"); |
1718 | 34.7k | return true; |
1719 | 38.0k | } |
1720 | | |
1721 | | // vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: |