/src/libmwaw/src/lib/WriterPlsParser.cxx
Line | Count | Source |
1 | | /* -*- Mode: C++; c-default-style: "k&r"; indent-tabs-mode: nil; tab-width: 2; c-basic-offset: 2 -*- */ |
2 | | |
3 | | /* libmwaw |
4 | | * Version: MPL 2.0 / LGPLv2+ |
5 | | * |
6 | | * The contents of this file are subject to the Mozilla Public License Version |
7 | | * 2.0 (the "License"); you may not use this file except in compliance with |
8 | | * the License or as specified alternatively below. You may obtain a copy of |
9 | | * the License at http://www.mozilla.org/MPL/ |
10 | | * |
11 | | * Software distributed under the License is distributed on an "AS IS" basis, |
12 | | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
13 | | * for the specific language governing rights and limitations under the |
14 | | * License. |
15 | | * |
16 | | * Major Contributor(s): |
17 | | * Copyright (C) 2002 William Lachance (wrlach@gmail.com) |
18 | | * Copyright (C) 2002,2004 Marc Maurer (uwog@uwog.net) |
19 | | * Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba@bluewin.ch) |
20 | | * Copyright (C) 2006, 2007 Andrew Ziem |
21 | | * Copyright (C) 2011, 2012 Alonso Laurent (alonso@loria.fr) |
22 | | * |
23 | | * |
24 | | * All Rights Reserved. |
25 | | * |
26 | | * For minor contributions see the git repository. |
27 | | * |
28 | | * Alternatively, the contents of this file may be used under the terms of |
29 | | * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"), |
30 | | * in which case the provisions of the LGPLv2+ are applicable |
31 | | * instead of those above. |
32 | | */ |
33 | | |
34 | | #include <cstring> |
35 | | #include <iomanip> |
36 | | #include <iostream> |
37 | | #include <limits> |
38 | | #include <sstream> |
39 | | |
40 | | #include <librevenge/librevenge.h> |
41 | | |
42 | | #include "MWAWCell.hxx" |
43 | | #include "MWAWTextListener.hxx" |
44 | | #include "MWAWFont.hxx" |
45 | | #include "MWAWFontConverter.hxx" |
46 | | #include "MWAWHeader.hxx" |
47 | | #include "MWAWParagraph.hxx" |
48 | | #include "MWAWPosition.hxx" |
49 | | #include "MWAWPictMac.hxx" |
50 | | #include "MWAWPrinter.hxx" |
51 | | #include "MWAWSection.hxx" |
52 | | #include "MWAWSubDocument.hxx" |
53 | | #include "MWAWTable.hxx" |
54 | | |
55 | | #include "WriterPlsParser.hxx" |
56 | | |
57 | | /** Internal: the structures of a WriterPlsParser */ |
58 | | namespace WriterPlsParserInternal |
59 | | { |
60 | | //! Page informations |
61 | | struct PageInfo { |
62 | | PageInfo() |
63 | 4.06k | : m_firstLine(0) |
64 | 4.06k | , m_height(0) |
65 | 4.06k | , m_heightFromBegin(0) |
66 | 4.06k | { |
67 | 4.06k | std::memset(m_unknown, 0, sizeof(m_unknown)); |
68 | 4.06k | } |
69 | | friend std::ostream &operator<<(std::ostream &o, PageInfo const &p) |
70 | 0 | { |
71 | 0 | o << "firstLine=" << p.m_firstLine |
72 | 0 | << ", height=" << p.m_height |
73 | 0 | << ", height[fromStart]=" << p.m_heightFromBegin; |
74 | 0 | if (p.m_unknown[0] != 1) o << ", unkn0=" << p.m_unknown[0]; |
75 | 0 | if (p.m_unknown[1]) o << ", unkn1=" << p.m_unknown[1]; |
76 | 0 | return o; |
77 | 0 | } |
78 | | |
79 | | int m_firstLine; |
80 | | int m_unknown[2]; // 1 0 |
81 | | int m_height, m_heightFromBegin; |
82 | | }; |
83 | | |
84 | | //! Column informations |
85 | | struct ColumnInfo { |
86 | | ColumnInfo() |
87 | 3.44k | : m_firstLine(0) |
88 | 3.44k | , m_height(0) |
89 | 3.44k | , m_col(0) |
90 | 3.44k | , m_numCol(1) |
91 | 3.44k | { |
92 | 3.44k | std::memset(m_unknown, 0, sizeof(m_unknown)); |
93 | 3.44k | } |
94 | | friend std::ostream &operator<<(std::ostream &o, ColumnInfo const &c) |
95 | 0 | { |
96 | 0 | o << "firstLine=" << c.m_firstLine |
97 | 0 | << ", col=" << c.m_col << "/" << c.m_numCol |
98 | 0 | << ", height=" << c.m_height |
99 | 0 | << ", dim?=" << c.m_unknown[3]; |
100 | 0 | if (c.m_unknown[0]) o << ", unkn0=" << c.m_unknown[0]; |
101 | 0 | if (c.m_unknown[1] != 1) o << ", unkn1=" << c.m_unknown[1]; |
102 | 0 | if (c.m_unknown[2]) o << ", unkn2=" << c.m_unknown[2]; |
103 | 0 | return o; |
104 | 0 | } |
105 | | |
106 | | int m_firstLine; |
107 | | int m_unknown[4]; // 0 1 0 |
108 | | int m_height, m_col, m_numCol; |
109 | | }; |
110 | | |
111 | | //! Column informations in a table |
112 | | struct ColumnTableInfo { |
113 | | ColumnTableInfo() |
114 | 89.7M | : m_height(0) |
115 | 89.7M | , m_numData(0) |
116 | 89.7M | , m_flags(0) |
117 | 89.7M | { |
118 | 179M | for (auto &col : m_colX) col=0; |
119 | 269M | for (auto &text : m_textX) text=0; |
120 | 89.7M | } |
121 | | friend std::ostream &operator<<(std::ostream &o, ColumnTableInfo const &c) |
122 | 0 | { |
123 | 0 | o << "height=" << c.m_height |
124 | 0 | << ", numData=" << c.m_numData |
125 | 0 | << ", colX=" << c.m_colX[0] << "<->" << c.m_colX[1] |
126 | 0 | << ", textX=" << c.m_textX[0] << "<->" << c.m_textX[1]; |
127 | 0 | if (c.m_textX[0] != c.m_textX[2]) |
128 | 0 | o << ", textX[begin?]=" << c.m_textX[2]; |
129 | 0 | if (c.m_flags) o << ", flags=" << c.m_flags; |
130 | 0 | return o; |
131 | 0 | } |
132 | | |
133 | | int m_height; |
134 | | int m_numData; |
135 | | int m_colX[2]; // x : begin and end pos |
136 | | int m_textX[3]; // x : begin|end|begin pos |
137 | | int m_flags; // 0 |
138 | | }; |
139 | | |
140 | | //! Paragraph informations |
141 | | struct ParagraphInfo { |
142 | | ParagraphInfo() |
143 | 142k | : m_pos(0) |
144 | 142k | , m_type(-2) |
145 | 142k | , m_height(0) |
146 | 142k | , m_height2(0) |
147 | 142k | , m_width(0) |
148 | 142k | , m_numLines(0) |
149 | 142k | , m_linesHeight() |
150 | 142k | , m_unknowns() |
151 | 142k | { |
152 | 855k | for (auto &fl : m_flags) fl=0; |
153 | 142k | } |
154 | | int getType() const |
155 | 427k | { |
156 | 427k | if (m_type >= 8) return (m_type & 0x7); |
157 | 269k | return m_type; |
158 | 427k | } |
159 | | friend std::ostream &operator<<(std::ostream &o, ParagraphInfo const &p) |
160 | 0 | { |
161 | 0 | int type = p.m_type; |
162 | 0 | bool typeFlag = false; |
163 | 0 | if (type >= 8) { |
164 | 0 | typeFlag = true; |
165 | 0 | type &= 7; |
166 | 0 | } |
167 | 0 | switch (type) { |
168 | 0 | case 0: |
169 | 0 | o << "text"; |
170 | 0 | break; |
171 | 0 | case 1: |
172 | 0 | o << "section"; |
173 | 0 | break; |
174 | 0 | case 2: |
175 | 0 | o << "text2"; |
176 | 0 | break; |
177 | 0 | case 3: |
178 | 0 | o << "colBreak"; |
179 | 0 | break; |
180 | 0 | case 4: |
181 | 0 | o << "graphics"; |
182 | 0 | break; |
183 | 0 | case 5: |
184 | 0 | o << "table"; |
185 | 0 | break; |
186 | 0 |
|
187 | 0 | case -1: |
188 | 0 | o << "empty"; |
189 | 0 | break; |
190 | 0 | case -2: |
191 | 0 | break; |
192 | 0 | default: |
193 | 0 | o << "type=" << type; |
194 | 0 | break; |
195 | 0 | } |
196 | 0 | if (typeFlag) o << "[in table],"; |
197 | 0 | else o << ","; |
198 | 0 |
|
199 | 0 | if (p.m_pos) o << "pos=" << std::hex << p.m_pos << std::dec << ","; |
200 | 0 | o << "h=" << p.m_height << ","; |
201 | 0 | if (p.m_height2 != p.m_height) o << "h[next]=" << p.m_height2 << ","; |
202 | 0 | if (p.m_width) o << "w=" << p.m_width << ","; |
203 | 0 | if (type == 5) { |
204 | 0 | o << "numCols=" << p.m_numLines << ","; |
205 | 0 | if (!p.m_linesHeight.empty()) { |
206 | 0 | o << "numDataByCols=["; |
207 | 0 | for (auto i : p.m_linesHeight) |
208 | 0 | o << i << ","; |
209 | 0 | o << "],"; |
210 | 0 | } |
211 | 0 | } |
212 | 0 | else { |
213 | 0 | if (p.m_numLines) o << "numLines=" << p.m_numLines << ","; |
214 | 0 | if (!p.m_linesHeight.empty()) { |
215 | 0 | o << "lineH=["; |
216 | 0 | for (auto i : p.m_linesHeight) |
217 | 0 | o << i << ","; |
218 | 0 | o << "],"; |
219 | 0 | } |
220 | 0 | } |
221 | 0 | for (int i= 0; i < 6; i++) { |
222 | 0 | if (!p.m_flags[i]) continue; |
223 | 0 | o << "f" << i << "=" << std::hex << p.m_flags[i] << std::dec << ","; |
224 | 0 | } |
225 | 0 | if (p.m_unknowns.size()) { |
226 | 0 | o << "unkn=["; |
227 | 0 | for (auto unk : p.m_unknowns) { |
228 | 0 | if (unk) |
229 | 0 | o << unk << ","; |
230 | 0 | else |
231 | 0 | o << "_,"; |
232 | 0 | } |
233 | 0 | o << "],"; |
234 | 0 | } |
235 | 0 | return o; |
236 | 0 | } |
237 | | |
238 | | long m_pos; |
239 | | int m_type; |
240 | | |
241 | | int m_height, m_height2, m_width, m_numLines; |
242 | | std::vector<int> m_linesHeight; |
243 | | int m_flags[6]; |
244 | | std::vector<int> m_unknowns; |
245 | | }; |
246 | | |
247 | | //! Windows informations |
248 | | struct WindowsInfo { |
249 | | struct Zone { |
250 | | Zone() |
251 | 1.50M | : m_number(0) |
252 | 1.50M | , m_size(0) |
253 | 1.50M | , m_width(0) |
254 | 1.50M | { |
255 | 4.52M | for (auto &unk : m_unknown) unk = 0; |
256 | 1.50M | } |
257 | | bool empty() const |
258 | 0 | { |
259 | 0 | return m_number==0 && m_size==0; |
260 | 0 | } |
261 | | friend std::ostream &operator<<(std::ostream &o, Zone const &z) |
262 | 0 | { |
263 | 0 | o << "N=" << z.m_number << ", sz=" << std::hex << z.m_size << std::dec; |
264 | 0 | o << ", w=" << z.m_width; |
265 | 0 | for (int i = 0; i < 3; i++) { |
266 | 0 | if (!z.m_unknown[i]) continue; |
267 | 0 | o << ", f" << i << "=" << z.m_unknown[i]; |
268 | 0 | } |
269 | 0 | return o; |
270 | 0 | } |
271 | | int m_number; |
272 | | int m_size; |
273 | | int m_width; |
274 | | int m_unknown[3]; |
275 | | }; |
276 | | |
277 | | friend std::ostream &operator<<(std::ostream &o, WindowsInfo const &w); |
278 | | |
279 | | WindowsInfo() |
280 | 180k | : m_pageDim() |
281 | 180k | , m_headerY(0) |
282 | 180k | , m_footerY(0) |
283 | 180k | , m_pages() |
284 | 180k | , m_columns() |
285 | 180k | , m_paragraphs() |
286 | 180k | { |
287 | 180k | } |
288 | | |
289 | | bool dimensionInvalid() const |
290 | 35.1k | { |
291 | 35.1k | return (m_pageDim.x() < 0 || m_pageDim.y() < 0 || |
292 | 33.8k | m_headerY < 0 || m_footerY < 0 || |
293 | 33.1k | m_headerY+m_footerY > m_pageDim.y()); |
294 | 35.1k | } |
295 | | |
296 | | bool getColumnLimitsFor(int line, std::vector<int> &listPos); |
297 | | |
298 | | MWAWVec2i m_pageDim; |
299 | | int m_headerY, m_footerY; |
300 | | std::vector<PageInfo> m_pages; |
301 | | std::vector<ColumnInfo> m_columns; |
302 | | std::vector<ParagraphInfo> m_paragraphs; |
303 | | |
304 | | // ????, pages, columns, parag, ???, ???, ??? |
305 | | Zone m_zone[7]; |
306 | | }; |
307 | | |
308 | | bool WindowsInfo::getColumnLimitsFor(int line, std::vector<int> &listPos) |
309 | 29.0k | { |
310 | 29.0k | listPos.resize(0); |
311 | | |
312 | 29.0k | size_t numColumns = m_columns.size(); |
313 | 29.0k | size_t firstColumn = 0; // initialized to make clang analyzer happier |
314 | 29.0k | int numCols = 0; |
315 | 30.9k | for (size_t i = 0; i < numColumns; i++) { |
316 | 2.54k | if (m_columns[i].m_firstLine == line+2) { |
317 | 141 | numCols=m_columns[i].m_numCol; |
318 | 141 | firstColumn = i; |
319 | 141 | if (numCols > int(unsigned(numColumns - firstColumn))) |
320 | 88 | numCols = int(unsigned(numColumns - firstColumn)); |
321 | 141 | if (numCols <= 1 || m_columns[i].m_col != 1) return false; |
322 | 60 | break; |
323 | 141 | } |
324 | 2.39k | if (m_columns[i].m_firstLine > line+2) |
325 | 585 | return true; |
326 | 2.39k | } |
327 | 28.4k | if (numCols <= 1) |
328 | 28.3k | return true; |
329 | | |
330 | 60 | size_t numPara = m_paragraphs.size(); |
331 | 60 | listPos.resize(size_t(numCols)); |
332 | 150 | for (size_t i = 0; i < size_t(numCols); i++) { |
333 | 150 | ColumnInfo const &colInfo = m_columns[firstColumn++]; |
334 | 150 | int l = colInfo.m_firstLine-1; |
335 | 150 | if (l < 0 || l >= static_cast<int>(numPara)) { |
336 | 44 | MWAW_DEBUG_MSG(("WindowsInfo::getColumnLimitsFor: pb with line position\n")); |
337 | 44 | return false; |
338 | 44 | } |
339 | 106 | if (i && m_paragraphs[size_t(l)].getType() != 3) { |
340 | 16 | MWAW_DEBUG_MSG(("WindowsInfo::getColumnLimitsFor: can not find cols break\n")); |
341 | 16 | return false; |
342 | 16 | } |
343 | | |
344 | 90 | listPos[i] = (i == 0) ? l-1 : l; |
345 | 90 | } |
346 | 0 | return true; |
347 | 60 | } |
348 | | |
349 | | std::ostream &operator<<(std::ostream &o, WindowsInfo const &w) |
350 | 0 | { |
351 | 0 | if (w.m_pageDim.x() || w.m_pageDim.y()) |
352 | 0 | o << "pagesDim=" << w.m_pageDim << ","; |
353 | 0 | if (w.m_headerY) o << "header[Height]=" << w.m_headerY << ","; |
354 | 0 | if (w.m_footerY) o << "footer[Height]=" << w.m_footerY << ","; |
355 | 0 | for (int i = 0; i < 7; i++) { |
356 | 0 | if (w.m_zone[i].empty()) continue; |
357 | 0 | switch (i) { |
358 | 0 | case 1: |
359 | 0 | o << "zonePages"; |
360 | 0 | break; |
361 | 0 | case 2: |
362 | 0 | o << "zoneCols?"; |
363 | 0 | break; |
364 | 0 | case 3: |
365 | 0 | o << "zoneParag"; |
366 | 0 | break; |
367 | 0 | default: |
368 | 0 | o << "unkZone" << i; |
369 | 0 | break; |
370 | 0 | } |
371 | 0 | o << "=[" << w.m_zone[i] << "], "; |
372 | 0 | } |
373 | 0 | return o; |
374 | 0 | } |
375 | | |
376 | | //////////////////////////////////////// |
377 | | /** Internal: class to store the font properties */ |
378 | | struct Font { |
379 | | Font() |
380 | 4.58M | : m_font() |
381 | 4.58M | , m_firstChar(0) |
382 | 4.58M | { |
383 | 4.58M | } |
384 | | |
385 | | //! operator<< |
386 | | friend std::ostream &operator<<(std::ostream &o, Font const &f) |
387 | 0 | { |
388 | 0 | if (f.m_firstChar) o << "firstChar=" << f.m_firstChar << ","; |
389 | 0 | return o; |
390 | 0 | } |
391 | | //! the font |
392 | | MWAWFont m_font; |
393 | | //! the first character |
394 | | int m_firstChar; |
395 | | }; |
396 | | |
397 | | //////////////////////////////////////// |
398 | | /** Internal: class to store the line properties */ |
399 | | struct Line { |
400 | | Line() |
401 | 175M | : m_firstChar(0) |
402 | 175M | , m_height(0) |
403 | 175M | , m_width(0) |
404 | 175M | , m_maxFontSize(0) |
405 | 175M | { |
406 | 701M | for (auto &fl : m_flags) fl=0; |
407 | 175M | } |
408 | | |
409 | | //! operator<< |
410 | | friend std::ostream &operator<<(std::ostream &o, Line const &l) |
411 | 0 | { |
412 | 0 | if (l.m_firstChar) o << "firstChar=" << l.m_firstChar << ","; |
413 | 0 | o << "height=" << l.m_height << ", width=" << l.m_width; |
414 | 0 | for (int i = 0; i < 4; i++) { |
415 | 0 | if (!l.m_flags[i]) continue; |
416 | 0 | o << ", lF" << i << "=" << std::hex << l.m_flags[i] << std::dec; |
417 | 0 | } |
418 | 0 | return o; |
419 | 0 | } |
420 | | //! the first character |
421 | | int m_firstChar; |
422 | | int m_height/** the height */, m_width /** the width */; |
423 | | int m_maxFontSize; /** the maximum font size */ |
424 | | //! some flag |
425 | | int m_flags[4]; // flags[0] a small number : a,b,c |
426 | | }; |
427 | | |
428 | | //////////////////////////////////////// |
429 | | /** Internal: class to store the Graphic properties */ |
430 | | struct GraphicInfo { |
431 | | GraphicInfo() |
432 | 12.5M | : m_width(0) |
433 | 12.5M | , m_graphicWidth(0) |
434 | 12.5M | { |
435 | 88.1M | for (auto &fl : m_flags) fl=0; |
436 | 12.5M | } |
437 | | |
438 | | //! operator<< |
439 | | friend std::ostream &operator<<(std::ostream &o, GraphicInfo const &g) |
440 | 0 | { |
441 | 0 | o << "width=" << g.m_graphicWidth << ", width[line]=" << g.m_width; |
442 | 0 | for (int i = 0; i < 6; i++) { // m_flags[6] seems to be junk |
443 | 0 | if (!g.m_flags[i]) continue; |
444 | 0 | o << ", gF" << i << "=" << std::hex << g.m_flags[i] << std::dec; |
445 | 0 | } |
446 | 0 | return o; |
447 | 0 | } |
448 | | //! the first character |
449 | | int m_width/** the line width */, m_graphicWidth /** the graphic width */; |
450 | | //! some flag |
451 | | int m_flags[7]; |
452 | | }; |
453 | | |
454 | | //////////////////////////////////////// |
455 | | /** Internal: class to store the Section properties */ |
456 | | struct SectionInfo { |
457 | | SectionInfo() |
458 | 19.6M | : m_numCol(0) |
459 | 19.6M | { |
460 | 58.9M | for (auto &dim : m_dim) dim = 0; |
461 | 78.6M | for (auto &fl : m_flags) fl = 0; |
462 | 19.6M | } |
463 | | |
464 | | bool empty() const |
465 | 19.6M | { |
466 | 19.6M | if (m_numCol) return false; |
467 | 19.4M | for (auto dim : m_dim) |
468 | 58.4M | if (dim) return false; |
469 | 19.4M | for (auto fl : m_flags) |
470 | 77.8M | if (fl) return false; |
471 | 19.4M | return true; |
472 | 19.4M | } |
473 | | //! operator<< |
474 | | friend std::ostream &operator<<(std::ostream &o, SectionInfo const &s) |
475 | 0 | { |
476 | 0 | if (s.m_numCol) o << "numCols?=" << s.m_numCol << ","; |
477 | 0 | o << "dim?=["; |
478 | 0 | for (auto dim : s.m_dim) |
479 | 0 | o << dim << ","; |
480 | 0 | o << "],"; |
481 | 0 | for (int i = 0; i < 4; i++) { |
482 | 0 | if (!s.m_flags[i]) continue; |
483 | 0 | o << ", sF" << i << "=" << std::hex << s.m_flags[i] << std::dec; |
484 | 0 | } |
485 | 0 | return o; |
486 | 0 | } |
487 | | //! the number of columns(?) |
488 | | int m_numCol; |
489 | | //! unknown dimension |
490 | | int m_dim[3]; |
491 | | //! some flag |
492 | | int m_flags[4]; |
493 | | }; |
494 | | |
495 | | //////////////////////////////////////// |
496 | | /** Internal: class to store the beginning of all paragraph data */ |
497 | | struct ParagraphData { |
498 | | //! Constructor |
499 | | ParagraphData() |
500 | 716k | : m_type(-1) |
501 | 716k | , m_typeFlag(0) |
502 | 716k | , m_height(0) |
503 | 716k | , m_width(0) |
504 | 716k | , m_unknown(0) |
505 | 716k | , m_text("") |
506 | 716k | , m_fonts() |
507 | 716k | , m_endPos(0) |
508 | 716k | { |
509 | 1.43M | for (auto &indent : m_indent) indent=0; |
510 | 1.43M | for (auto &numData : m_numData) numData=0; |
511 | 716k | } |
512 | | //! operator<< |
513 | | friend std::ostream &operator<<(std::ostream &o, ParagraphData const &p) |
514 | 0 | { |
515 | 0 | switch (p.m_type) { |
516 | 0 | case 0: |
517 | 0 | o << "text"; |
518 | 0 | break; |
519 | 0 | case 1: |
520 | 0 | o << "section"; |
521 | 0 | break; // checkme find only one time before a colbreak |
522 | 0 | case 2: |
523 | 0 | o << "text2"; |
524 | 0 | break; // what is the difference with 1 |
525 | 0 | case 3: |
526 | 0 | o << "colBreak"; |
527 | 0 | break; // find only one time to change column |
528 | 0 | case 4: |
529 | 0 | o << "graphic"; |
530 | 0 | break; |
531 | 0 | case 5: |
532 | 0 | o << "table"; |
533 | 0 | break; |
534 | 0 | default: |
535 | 0 | o << "type=" << p.m_type; |
536 | 0 | break; |
537 | 0 | } |
538 | 0 | switch (p.m_typeFlag) { |
539 | 0 | case 0: |
540 | 0 | break; |
541 | 0 | case 0x80: |
542 | 0 | o << "[in table]"; |
543 | 0 | break; |
544 | 0 | default: |
545 | 0 | o << "[" << std::hex << p.m_typeFlag << std::dec << "],"; |
546 | 0 | } |
547 | 0 | o << ","; |
548 | 0 |
|
549 | 0 | o << "height=" << p.m_height << ","; |
550 | 0 | o << "witdh=" << p.m_width << ","; |
551 | 0 | if (p.m_indent[0]) o << "indent[left]=" << p.m_indent[0] << ","; |
552 | 0 | if (p.m_indent[1] != p.m_indent[0]) |
553 | 0 | o << "indent[firstPos]=" << p.m_indent[1] << ","; |
554 | 0 | if (p.m_text.length()) o << "text='" << p.m_text << "',"; |
555 | 0 | if (p.m_type==5) o << "numData[total]=" << p.m_unknown << ","; |
556 | 0 | else o << "unkn=" << p.m_unknown << ","; /* in text2: often 1, but can be 5|13|25|29 */ |
557 | 0 | return o; |
558 | 0 | } |
559 | | |
560 | | int m_type, m_typeFlag; |
561 | | int m_height, m_width; |
562 | | int m_indent[2]; // left indent and ? |
563 | | int m_unknown; |
564 | | |
565 | | std::string m_text; |
566 | | std::vector<Font> m_fonts; |
567 | | |
568 | | long m_endPos; // end of the data ( except if there is auxilliary data ) |
569 | | int m_numData[2]; // number of data[1] ( always font?), data[2] |
570 | | }; |
571 | | |
572 | | //////////////////////////////////////// |
573 | | //! Internal: the state of a WriterPlsParser |
574 | | struct State { |
575 | | //! constructor |
576 | | State() |
577 | 48.4k | : m_actPage(0) |
578 | 48.4k | , m_numPages(0) |
579 | 48.4k | , m_headerHeight(0) |
580 | 48.4k | , m_footerHeight(0) |
581 | 48.4k | { |
582 | 48.4k | } |
583 | | |
584 | | int m_actPage /** the actual page */, m_numPages /** the number of page of the final document */; |
585 | | |
586 | | //! the information ( 0: main, 1: header, 2: footer) |
587 | | WindowsInfo m_windows[3]; |
588 | | |
589 | | int m_headerHeight /** the header height if known */, |
590 | | m_footerHeight /** the footer height if known */; |
591 | | }; |
592 | | |
593 | | //////////////////////////////////////// |
594 | | //! Internal: the subdocument of a WriterPlsParser |
595 | | class SubDocument final : public MWAWSubDocument |
596 | | { |
597 | | public: |
598 | | SubDocument(WriterPlsParser &pars, MWAWInputStreamPtr const &input, int zoneId) |
599 | 78 | : MWAWSubDocument(&pars, input, MWAWEntry()), m_id(zoneId) |
600 | 78 | { |
601 | 78 | } |
602 | | |
603 | | //! destructor |
604 | 0 | ~SubDocument() final {} |
605 | | |
606 | | //! operator!= |
607 | | bool operator!=(MWAWSubDocument const &doc) const final |
608 | 0 | { |
609 | 0 | if (MWAWSubDocument::operator!=(doc)) return true; |
610 | 0 | auto const *sDoc = dynamic_cast<SubDocument const *>(&doc); |
611 | 0 | if (!sDoc) return true; |
612 | 0 | if (m_id != sDoc->m_id) return true; |
613 | 0 | return false; |
614 | 0 | } |
615 | | |
616 | | //! the parser function |
617 | | void parse(MWAWListenerPtr &listener, libmwaw::SubDocumentType type) final; |
618 | | |
619 | | protected: |
620 | | //! the subdocument id |
621 | | int m_id; |
622 | | }; |
623 | | |
624 | | void SubDocument::parse(MWAWListenerPtr &listener, libmwaw::SubDocumentType /*type*/) |
625 | 78 | { |
626 | 78 | if (!listener.get()) { |
627 | 0 | MWAW_DEBUG_MSG(("WriterPlsParserInternal::SubDocument::parse: no listener\n")); |
628 | 0 | return; |
629 | 0 | } |
630 | 78 | if (m_id != 1 && m_id != 2) { |
631 | 0 | MWAW_DEBUG_MSG(("WriterPlsParserInternal::SubDocument::parse: unknown zone\n")); |
632 | 0 | return; |
633 | 0 | } |
634 | 78 | auto *parser=dynamic_cast<WriterPlsParser *>(m_parser); |
635 | 78 | if (!parser) { |
636 | 0 | MWAW_DEBUG_MSG(("WriterPlsParserInternal::SubDocument::parse: no parser\n")); |
637 | 0 | return; |
638 | 0 | } |
639 | | |
640 | 78 | long pos = m_input->tell(); |
641 | 78 | parser->sendWindow(m_id); |
642 | 78 | m_input->seek(pos, librevenge::RVNG_SEEK_SET); |
643 | 78 | } |
644 | | } |
645 | | |
646 | | //////////////////////////////////////////////////////////// |
647 | | // constructor/destructor, ... |
648 | | //////////////////////////////////////////////////////////// |
649 | | WriterPlsParser::WriterPlsParser(MWAWInputStreamPtr const &input, MWAWRSRCParserPtr const &rsrcParser, MWAWHeader *header) |
650 | 20.5k | : MWAWTextParser(input, rsrcParser, header) |
651 | 20.5k | , m_state() |
652 | 20.5k | { |
653 | 20.5k | init(); |
654 | 20.5k | } |
655 | | |
656 | | WriterPlsParser::~WriterPlsParser() |
657 | 20.5k | { |
658 | 20.5k | } |
659 | | |
660 | | void WriterPlsParser::init() |
661 | 20.5k | { |
662 | 20.5k | resetTextListener(); |
663 | 20.5k | setAsciiName("main-1"); |
664 | | |
665 | 20.5k | m_state.reset(new WriterPlsParserInternal::State); |
666 | | |
667 | | // reduce the margin (in case, the page is not defined) |
668 | 20.5k | getPageSpan().setMargins(0.1); |
669 | 20.5k | } |
670 | | |
671 | | //////////////////////////////////////////////////////////// |
672 | | // position and height |
673 | | //////////////////////////////////////////////////////////// |
674 | | double WriterPlsParser::getTextHeight() const |
675 | 3.96k | { |
676 | 3.96k | return getPageSpan().getPageLength()-m_state->m_headerHeight/72.0-m_state->m_footerHeight/72.0; |
677 | 3.96k | } |
678 | | |
679 | | //////////////////////////////////////////////////////////// |
680 | | // new page |
681 | | //////////////////////////////////////////////////////////// |
682 | | void WriterPlsParser::newPage(int number) |
683 | 6.87k | { |
684 | 6.87k | if (number <= m_state->m_actPage || number > m_state->m_numPages) |
685 | 4.45k | return; |
686 | | |
687 | 4.83k | while (m_state->m_actPage < number) { |
688 | 2.41k | m_state->m_actPage++; |
689 | 2.41k | if (!getTextListener() || m_state->m_actPage == 1) |
690 | 2.41k | continue; |
691 | 1 | getTextListener()->insertBreak(MWAWTextListener::PageBreak); |
692 | 1 | } |
693 | 2.41k | } |
694 | | |
695 | | |
696 | | |
697 | | //////////////////////////////////////////////////////////// |
698 | | // the parser |
699 | | //////////////////////////////////////////////////////////// |
700 | | void WriterPlsParser::parse(librevenge::RVNGTextInterface *docInterface) |
701 | 7.33k | { |
702 | 7.33k | if (!getInput().get() || !checkHeader(nullptr)) throw(libmwaw::ParseException()); |
703 | 7.33k | bool ok = true; |
704 | 7.33k | try { |
705 | | // create the asciiFile |
706 | 7.33k | ascii().setStream(getInput()); |
707 | 7.33k | ascii().open(asciiName()); |
708 | | |
709 | 7.33k | checkHeader(nullptr); |
710 | 7.33k | ok = createZones(); |
711 | 7.33k | ascii().addPos(getInput()->tell()); |
712 | 7.33k | ascii().addNote("_"); |
713 | 7.33k | if (ok) { |
714 | 6.87k | createDocument(docInterface); |
715 | 6.87k | sendWindow(0); |
716 | 6.87k | } |
717 | | |
718 | 7.33k | ascii().reset(); |
719 | 7.33k | } |
720 | 7.33k | catch (...) { |
721 | 246 | MWAW_DEBUG_MSG(("WriterPlsParser::parse: exception catched when parsing\n")); |
722 | 246 | ok = false; |
723 | 246 | } |
724 | | |
725 | 7.33k | resetTextListener(); |
726 | 7.33k | if (!ok) throw(libmwaw::ParseException()); |
727 | 7.33k | } |
728 | | |
729 | | //////////////////////////////////////////////////////////// |
730 | | // create the document |
731 | | //////////////////////////////////////////////////////////// |
732 | | void WriterPlsParser::createDocument(librevenge::RVNGTextInterface *documentInterface) |
733 | 6.87k | { |
734 | 6.87k | if (!documentInterface) return; |
735 | 6.87k | if (getTextListener()) { |
736 | 0 | MWAW_DEBUG_MSG(("WriterPlsParser::createDocument: listener already exist\n")); |
737 | 0 | return; |
738 | 0 | } |
739 | | |
740 | | // update the page |
741 | 6.87k | m_state->m_actPage = 0; |
742 | | |
743 | | // create the page list |
744 | 6.87k | MWAWPageSpan ps(getPageSpan()); |
745 | 20.6k | for (int i = 1; i < 3; i++) { |
746 | 13.7k | if (m_state->m_windows[i].m_paragraphs.size() == 0) |
747 | 13.6k | continue; |
748 | 78 | MWAWHeaderFooter hF((i==1) ? MWAWHeaderFooter::HEADER : MWAWHeaderFooter::FOOTER, MWAWHeaderFooter::ALL); |
749 | 78 | hF.m_subDocument.reset(new WriterPlsParserInternal::SubDocument(*this, getInput(), i)); |
750 | 78 | ps.setHeaderFooter(hF); |
751 | 78 | } |
752 | | |
753 | 6.87k | m_state->m_numPages = int(m_state->m_windows[0].m_pages.size()); |
754 | 6.87k | ps.setPageSpan(m_state->m_numPages+1); |
755 | 6.87k | std::vector<MWAWPageSpan> pageList(1,ps); |
756 | | // |
757 | 6.87k | MWAWTextListenerPtr listen(new MWAWTextListener(*getParserState(), pageList, documentInterface)); |
758 | 6.87k | setTextListener(listen); |
759 | 6.87k | listen->startDocument(); |
760 | 6.87k | } |
761 | | |
762 | | |
763 | | //////////////////////////////////////////////////////////// |
764 | | // |
765 | | // Intermediate level |
766 | | // |
767 | | //////////////////////////////////////////////////////////// |
768 | | bool WriterPlsParser::createZones() |
769 | 7.33k | { |
770 | 7.33k | if (!readWindowsInfo(0) || !readPrintInfo()) |
771 | 0 | return false; |
772 | 21.4k | for (int st = 1; st < 4; st++) { |
773 | 21.2k | bool ok = true; |
774 | 21.2k | switch (st) { |
775 | 7.33k | case 1: |
776 | 7.33k | ok = m_state->m_headerHeight > 0; |
777 | 7.33k | break; |
778 | 7.04k | case 2: |
779 | 7.04k | ok = m_state->m_footerHeight > 0; |
780 | 7.04k | break; |
781 | 6.87k | default: |
782 | 6.87k | break; |
783 | 21.2k | } |
784 | 21.2k | if (!ok) continue; |
785 | 7.74k | if (st !=3 && !readWindowsInfo(st)) |
786 | 312 | return false; |
787 | 7.43k | if (!readWindowsZone(st==3 ? 0 : st)) |
788 | 6.85k | return (st==3); |
789 | 7.43k | } |
790 | | |
791 | 171 | return true; |
792 | 7.33k | } |
793 | | |
794 | | //////////////////////////////////////////////////////////// |
795 | | // |
796 | | // Low level |
797 | | // |
798 | | //////////////////////////////////////////////////////////// |
799 | | |
800 | | //////////////////////////////////////////////////////////// |
801 | | // read the header |
802 | | //////////////////////////////////////////////////////////// |
803 | | bool WriterPlsParser::checkHeader(MWAWHeader *header, bool /*strict*/) |
804 | 27.8k | { |
805 | 27.8k | *m_state = WriterPlsParserInternal::State(); |
806 | | |
807 | 27.8k | MWAWInputStreamPtr input = getInput(); |
808 | 27.8k | if (!input || !input->hasDataFork()) |
809 | 0 | return false; |
810 | | |
811 | 27.8k | int const headerSize=2; |
812 | 27.8k | if (!input->checkPosition(headerSize)) { |
813 | 0 | MWAW_DEBUG_MSG(("WriterPlsParser::checkHeader: file is too short\n")); |
814 | 0 | return false; |
815 | 0 | } |
816 | 27.8k | input->seek(0,librevenge::RVNG_SEEK_SET); |
817 | 27.8k | if (input->readULong(2) != 0x110) |
818 | 142 | return false; |
819 | 27.7k | ascii().addPos(0); |
820 | 27.7k | ascii().addNote("FileHeader"); |
821 | | |
822 | 27.7k | if (!readWindowsInfo(0) || !readPrintInfo()) |
823 | 4.29k | return false; |
824 | 23.4k | input->seek(2,librevenge::RVNG_SEEK_SET); |
825 | 23.4k | if (header) |
826 | 8.77k | header->reset(MWAWDocument::MWAW_T_WRITERPLUS, 1); |
827 | | |
828 | 23.4k | return true; |
829 | 27.7k | } |
830 | | |
831 | | bool WriterPlsParser::readWindowsInfo(int zone) |
832 | 35.9k | { |
833 | 35.9k | if (zone<0 || zone>=3) { |
834 | 0 | MWAW_DEBUG_MSG(("WriterPlsParser::readWindowsInfo:the zone seems bad\n")); |
835 | 0 | return false; |
836 | 0 | } |
837 | 35.9k | MWAWInputStreamPtr input = getInput(); |
838 | | |
839 | 35.9k | long debPos = input->tell(); |
840 | 35.9k | if (!input->checkPosition(debPos+0xf4)) { |
841 | 777 | MWAW_DEBUG_MSG(("WriterPlsParser::readWindowsInfo: file is too short\n")); |
842 | 777 | return false; |
843 | 777 | } |
844 | | |
845 | 35.1k | WriterPlsParserInternal::WindowsInfo info; |
846 | 35.1k | libmwaw::DebugStream f; |
847 | 35.1k | f << "Entries(WindowsZone)"; |
848 | 35.1k | switch (zone) { |
849 | 34.5k | case 0: |
850 | 34.5k | break; |
851 | 367 | case 1: |
852 | 367 | f << "[Header]"; |
853 | 367 | break; |
854 | 249 | case 2: |
855 | 249 | f << "[Footer]"; |
856 | 249 | break; |
857 | 0 | default: |
858 | 0 | f << "[Unknown]"; |
859 | 0 | break; |
860 | 35.1k | } |
861 | 35.1k | f << ":"; |
862 | 105k | for (int i = 0; i < 2; i++) { |
863 | 70.3k | auto val = static_cast<int>(input->readLong(1)); |
864 | 70.3k | f << "f" << i << "=" << val << ","; |
865 | 70.3k | } |
866 | 35.1k | f << "unkn=" << input->readLong(2); |
867 | | |
868 | 35.1k | long pos; |
869 | 246k | for (auto &i : info.m_zone) { |
870 | 246k | WriterPlsParserInternal::WindowsInfo::Zone infoZone; |
871 | 246k | infoZone.m_unknown[0] = static_cast<int>(input->readULong(1)); |
872 | 246k | infoZone.m_width = static_cast<int>(input->readULong(2)); |
873 | 246k | infoZone.m_unknown[1] = static_cast<int>(input->readULong(1)); |
874 | 246k | infoZone.m_unknown[2] = static_cast<int>(input->readULong(2)); |
875 | 246k | infoZone.m_size = static_cast<int>(input->readULong(2)); |
876 | 246k | infoZone.m_number = static_cast<int>(input->readULong(2)); |
877 | 246k | i = infoZone; |
878 | 246k | } |
879 | 35.1k | f << "," << info; |
880 | | |
881 | 35.1k | ascii().addPos(debPos); |
882 | 35.1k | ascii().addNote(f.str().c_str()); |
883 | | |
884 | 35.1k | pos = input->tell(); |
885 | 35.1k | ascii().addPos(pos); |
886 | 35.1k | ascii().addNote("WindowsZone(A-1)"); |
887 | 35.1k | ascii().addPos(pos+12); |
888 | 35.1k | ascii().addNote("WindowsZone(A-2)"); |
889 | 35.1k | ascii().addPos(pos+30); |
890 | 35.1k | ascii().addNote("WindowsZone(A-3)"); |
891 | 35.1k | ascii().addPos(pos+60); |
892 | 35.1k | ascii().addNote("WindowsZone(A-4)"); |
893 | 35.1k | ascii().addPos(pos+60+14); |
894 | 35.1k | ascii().addNote("WindowsZone(A-5)"); |
895 | 35.1k | ascii().addPos(pos+60+14*2); |
896 | 35.1k | ascii().addNote("WindowsZone(A-6)"); |
897 | | |
898 | 35.1k | pos = debPos+0xc2; |
899 | 35.1k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
900 | 35.1k | f.str(""); |
901 | 35.1k | f << "WindowsZone(A-7):"; |
902 | 35.1k | auto val = static_cast<int>(input->readLong(2)); |
903 | 35.1k | if (val) f << "unkn=" << val << ","; |
904 | 35.1k | auto width = static_cast<int>(input->readLong(2)); |
905 | 35.1k | info.m_footerY = static_cast<int>(input->readLong(2)); |
906 | 35.1k | info.m_headerY = static_cast<int>(input->readLong(2)); |
907 | 35.1k | auto height = static_cast<int>(input->readLong(2)); |
908 | 35.1k | info.m_pageDim = MWAWVec2i(width, height); |
909 | 35.1k | f << "page=" << info.m_pageDim << ","; |
910 | 35.1k | if (info.m_headerY) |
911 | 5.20k | f << "header[height]=" << info.m_headerY << ","; |
912 | 35.1k | if (info.m_footerY) |
913 | 5.22k | f << "footer[height]=" << info.m_footerY << ","; |
914 | 140k | for (int i = 0; i < 3; i++) // always 17 12 0 left|right ? |
915 | 105k | f << "f" << i << "=" << static_cast<int>(input->readLong(2)) << ","; |
916 | 35.1k | ascii().addPos(pos); |
917 | 35.1k | ascii().addNote(f.str().c_str()); |
918 | 35.1k | if (info.dimensionInvalid()) |
919 | 2.98k | return false; |
920 | 32.1k | if (zone == 0) { |
921 | 31.6k | m_state->m_headerHeight = info.m_headerY; |
922 | 31.6k | m_state->m_footerHeight = info.m_footerY; |
923 | 31.6k | } |
924 | 32.1k | pos = input->tell(); |
925 | 32.1k | f.str(""); |
926 | 32.1k | f << "WindowsZone(B):"; |
927 | 32.1k | int dim[4]; |
928 | 128k | for (auto &d : dim) d = static_cast<int>(input->readLong(2)); |
929 | 32.1k | f << "dim(?)=" << dim[1] << "x" << dim[0] << "-" << dim[3] << "x" << dim[2] << ","; |
930 | 96.5k | for (int i = 0; i < 2; i++) { |
931 | 64.3k | auto fl = static_cast<int>(input->readLong(1)); // almost always 0 except some time 1 |
932 | 64.3k | if (fl) f << "fl" << i << "=" << fl << ","; |
933 | 64.3k | } |
934 | 225k | for (int i = 0; i < 6; i++) { |
935 | 193k | int values[3]; |
936 | 193k | values[0] = static_cast<int>(input->readULong(1)); |
937 | 193k | values[1] = static_cast<int>(input->readLong(2)); |
938 | 193k | values[2] = static_cast<int>(input->readULong(1)); |
939 | 193k | if (values[0] == 0 && values[1] == 0 && values[2] == 0) continue; |
940 | 130k | f << "f" << i << "=[" << values[0] << ", w=" << values[1] |
941 | 130k | << ", " << std::hex << values[2] << std::dec << "],"; |
942 | 130k | } |
943 | | |
944 | 32.1k | m_state->m_windows[zone]=info; |
945 | | |
946 | 32.1k | ascii().addPos(pos); |
947 | 32.1k | ascii().addNote(f.str().c_str()); |
948 | | |
949 | 32.1k | return true; |
950 | 35.1k | } |
951 | | |
952 | | //////////////////////////////////////////////////////////// |
953 | | // read all the windows zone info |
954 | | //////////////////////////////////////////////////////////// |
955 | | bool WriterPlsParser::readWindowsZone(int zone) |
956 | 7.43k | { |
957 | 7.43k | if (zone<0 || zone>=3) { |
958 | 0 | MWAW_DEBUG_MSG(("WriterPlsParser::readWindowsZone:the zone seems bad\n")); |
959 | 0 | return false; |
960 | 0 | } |
961 | | |
962 | 7.43k | MWAWInputStreamPtr input = getInput(); |
963 | 7.43k | auto &wInfo = m_state->m_windows[zone]; |
964 | | |
965 | 7.43k | libmwaw::DebugStream f; |
966 | 25.8k | for (int wh=1; wh < 7; wh++) { |
967 | 24.9k | auto const &z = wInfo.m_zone[wh]; |
968 | 24.9k | int length = z.m_size; |
969 | 24.9k | if (!length) continue; |
970 | | |
971 | 13.4k | long pos = input->tell(); |
972 | 13.4k | input->seek(length, librevenge::RVNG_SEEK_CUR); |
973 | 13.4k | if (long(input->tell()) != pos+length) { |
974 | 919 | MWAW_DEBUG_MSG(("WriterPlsParser::readWindowsZone: zone is too short\n")); |
975 | 919 | return false; |
976 | 919 | } |
977 | 12.5k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
978 | | |
979 | 12.5k | bool ok = false; |
980 | 12.5k | switch (wh) { |
981 | 4.67k | case 1: |
982 | 4.67k | ok=readPageInfo(zone); |
983 | 4.67k | break; |
984 | 948 | case 2: |
985 | 948 | ok=readColInfo(zone); |
986 | 948 | break; |
987 | 6.28k | case 3: |
988 | | // need to get next block |
989 | 6.28k | ok = readParagraphInfo(zone); |
990 | 6.28k | if (!ok) return false; |
991 | 680 | break; |
992 | 680 | default: |
993 | 659 | break; |
994 | 12.5k | } |
995 | 6.96k | if (ok) continue; |
996 | | |
997 | 3.42k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
998 | 3.42k | if (z.m_number && (length % z.m_number) == 0) { |
999 | 2.09k | int dataSz = length / z.m_number; |
1000 | 1.26M | for (int i = 0; i < z.m_number; i++) { |
1001 | 1.26M | f.str(""); |
1002 | 1.26M | f << "Entries(Zone" << wh << ")-" << i << ":"; |
1003 | 1.26M | ascii().addPos(input->tell()); |
1004 | 1.26M | ascii().addNote(f.str().c_str()); |
1005 | 1.26M | input->seek(dataSz, librevenge::RVNG_SEEK_CUR); |
1006 | 1.26M | } |
1007 | 2.09k | } |
1008 | 1.32k | else { |
1009 | 1.32k | f.str(""); |
1010 | 1.32k | f << "Entries(Zone" << wh << "):"; |
1011 | 1.32k | ascii().addPos(input->tell()); |
1012 | 1.32k | ascii().addNote(f.str().c_str()); |
1013 | 1.32k | input->seek(length, librevenge::RVNG_SEEK_CUR); |
1014 | 1.32k | } |
1015 | 3.42k | } |
1016 | | |
1017 | 1.08k | for (int i = int(wInfo.m_paragraphs.size())-1; i >= 0; i--) { |
1018 | 621 | auto const &pInfo = wInfo.m_paragraphs[size_t(i)]; |
1019 | 621 | if (!pInfo.m_pos) continue; |
1020 | | |
1021 | 447 | input->seek(pInfo.m_pos, librevenge::RVNG_SEEK_SET); |
1022 | 447 | auto length = long(input->readULong(2)); |
1023 | 447 | auto length2 = long(input->readULong(2)); |
1024 | 447 | long endPos = pInfo.m_pos+4+length+length2; |
1025 | 447 | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
1026 | 447 | if (long(input->tell()) != endPos) { |
1027 | 315 | MWAW_DEBUG_MSG(("WriterPlsParser::readWindowsZone: data zone is too short\n")); |
1028 | 315 | return false; |
1029 | 315 | } |
1030 | 132 | switch (pInfo.getType()) { |
1031 | 32 | case 4: |
1032 | 32 | length = long(input->readULong(4)); |
1033 | 32 | input->seek(length, librevenge::RVNG_SEEK_CUR); |
1034 | 32 | if (long(input->tell()) != endPos+length+4) { |
1035 | 18 | MWAW_DEBUG_MSG(("WriterPlsParser::readWindowsZone: graphics zone is too short\n")); |
1036 | 18 | return false; |
1037 | 18 | } |
1038 | 14 | break; |
1039 | 100 | default: // 0,1,2,3, 5 : ok, other ? |
1040 | 100 | break; |
1041 | 132 | } |
1042 | 114 | return true; |
1043 | 132 | } |
1044 | 467 | return true; |
1045 | 914 | } |
1046 | | |
1047 | | //////////////////////////////////////////////////////////// |
1048 | | // send the windows zone info |
1049 | | //////////////////////////////////////////////////////////// |
1050 | | bool WriterPlsParser::sendWindow(int zone, MWAWVec2i limits) |
1051 | 185k | { |
1052 | 185k | MWAWTextListenerPtr listener=getTextListener(); |
1053 | 185k | if (!listener) { |
1054 | 0 | MWAW_DEBUG_MSG(("WriterPlsParser::sendWindow: can not find a listener\n")); |
1055 | 0 | return false; |
1056 | 0 | } |
1057 | 185k | if (zone<0 || zone>=3) { |
1058 | 0 | MWAW_DEBUG_MSG(("WriterPlsParser::sendWindow:the zone seems bad\n")); |
1059 | 0 | return false; |
1060 | 0 | } |
1061 | 185k | auto &wInfo = m_state->m_windows[zone]; |
1062 | | |
1063 | 185k | bool sendAll = limits[0] < 0; |
1064 | | |
1065 | 185k | auto maxPages = int(wInfo.m_pages.size()); |
1066 | 185k | if (maxPages == 0 || zone || !sendAll) maxPages = 1; |
1067 | | |
1068 | 185k | int actParag = 0; |
1069 | 185k | int actCol = 0, numCols = 0; |
1070 | 344k | for (int pg = 0; pg < maxPages; pg++) { |
1071 | 185k | int endParag = 0; |
1072 | 185k | if (!sendAll) { |
1073 | 178k | actParag = limits[0]; |
1074 | 178k | endParag = limits[1]; |
1075 | 178k | if (endParag <= actParag) { |
1076 | 25.4k | MWAW_DEBUG_MSG(("WriterPlsParser::sendWindow: pb2 with limits\n")); |
1077 | 25.4k | return true; |
1078 | 25.4k | } |
1079 | 178k | } |
1080 | 6.94k | else { |
1081 | 6.94k | if (zone == 0) { |
1082 | 6.87k | newPage(pg+1); |
1083 | 6.87k | actCol = numCols ? 1 : 0; |
1084 | 6.87k | } |
1085 | 6.94k | if (pg == maxPages-1 || wInfo.m_pages.size() == 0) |
1086 | 6.94k | endParag = int(wInfo.m_paragraphs.size()); |
1087 | 1 | else { |
1088 | 1 | endParag = wInfo.m_pages[size_t(pg)+1].m_firstLine-1; |
1089 | 1 | if (endParag == -1 || endParag < actParag) { |
1090 | 0 | MWAW_DEBUG_MSG(("WriterPlsParser::sendWindow: pb with page zone\n")); |
1091 | 0 | continue; |
1092 | 0 | } |
1093 | 1 | } |
1094 | 6.94k | } |
1095 | 159k | if (endParag > int(wInfo.m_paragraphs.size())) { |
1096 | 72.5k | MWAW_DEBUG_MSG(("WriterPlsParser::sendWindow: pb with limits\n")); |
1097 | 72.5k | endParag = int(wInfo.m_paragraphs.size()); |
1098 | 72.5k | } |
1099 | | |
1100 | 527k | for (int i = actParag; i < endParag; i++) { |
1101 | 368k | auto const &pInfo = wInfo.m_paragraphs[size_t(i)]; |
1102 | 368k | if (!pInfo.m_pos) { |
1103 | 6.11k | readText(pInfo); |
1104 | 6.11k | continue; |
1105 | 6.11k | } |
1106 | 362k | bool ok = true; |
1107 | 362k | switch (pInfo.getType()) { |
1108 | 3.20k | case 3: // col break: seems similar to an entry data (with a text zone which does not contain any character) |
1109 | 3.20k | if (numCols) { |
1110 | 0 | if (actCol >numCols) { |
1111 | 0 | MWAW_DEBUG_MSG(("WriterPlsParser::sendWindow: pb with col break\n")); |
1112 | 0 | } |
1113 | 0 | else { |
1114 | 0 | actCol++; |
1115 | 0 | listener->insertBreak(MWAWTextListener::ColumnBreak); |
1116 | 0 | } |
1117 | 0 | } |
1118 | 3.20k | MWAW_FALLTHROUGH; |
1119 | 96.3k | case 0: |
1120 | 135k | case 2: |
1121 | 135k | ok = readText(pInfo); |
1122 | 135k | break; |
1123 | 29.0k | case 1: { |
1124 | 29.0k | MWAWSection section; |
1125 | 29.0k | bool canCreateSection = sendAll && zone == 0 && actCol == numCols; |
1126 | 29.0k | if (findSection(zone, MWAWVec2i(i, endParag), section)) { |
1127 | 28.9k | if (!canCreateSection) { |
1128 | 19.6k | if (section.numColumns()>1) { |
1129 | 0 | MWAW_DEBUG_MSG(("WriterPlsParser::sendWindow: find a section in auxilliary zone\n")); |
1130 | 0 | } |
1131 | 19.6k | } |
1132 | 9.27k | else { |
1133 | 9.27k | if (listener->isSectionOpened()) |
1134 | 5.18k | listener->closeSection(); |
1135 | 9.27k | listener->openSection(section); |
1136 | 9.27k | numCols = listener->getSection().numColumns(); |
1137 | 9.27k | if (numCols<=1) numCols=0; |
1138 | 9.27k | actCol = numCols ? 1 : 0; |
1139 | 9.27k | canCreateSection = false; |
1140 | 9.27k | } |
1141 | 28.9k | } |
1142 | | |
1143 | 29.0k | ok = readSection(pInfo, canCreateSection); |
1144 | 29.0k | break; |
1145 | 96.3k | } |
1146 | 11.3k | case 4: |
1147 | 11.3k | ok = readGraphic(pInfo); |
1148 | 11.3k | break; |
1149 | 154k | case 5: |
1150 | 154k | if (pInfo.m_numLines + i <= endParag) { |
1151 | 147k | if ((ok = readTable(pInfo))) { |
1152 | 116k | listener->openTableRow(float(pInfo.m_height), librevenge::RVNG_POINT); |
1153 | | |
1154 | 295k | for (size_t j = 0; j < pInfo.m_linesHeight.size(); j++) { |
1155 | 178k | int numData = pInfo.m_linesHeight[j]; |
1156 | 178k | MWAWCell cell; |
1157 | 178k | cell.setPosition(MWAWVec2i(int(j), 0)); |
1158 | 178k | listener->openTableCell(cell); |
1159 | 178k | sendWindow(zone, MWAWVec2i(i+1, i+1+numData)); |
1160 | 178k | i += numData; |
1161 | 178k | listener->closeTableCell(); |
1162 | 178k | } |
1163 | | |
1164 | 116k | listener->closeTableRow(); |
1165 | 116k | listener->closeTable(); |
1166 | 116k | } |
1167 | 147k | } |
1168 | 7.35k | else { |
1169 | 7.35k | MWAW_DEBUG_MSG(("WriterPlsParser::sendWindow: table across a page\n")); |
1170 | 7.35k | } |
1171 | 154k | break; |
1172 | 31.2k | default: |
1173 | 31.2k | ok = readUnknown(pInfo); |
1174 | 31.2k | break; |
1175 | 362k | } |
1176 | 361k | if (!ok) { |
1177 | 142k | libmwaw::DebugStream f; |
1178 | 142k | f << "Entries(Unknown):" << pInfo; |
1179 | 142k | ascii().addPos(pInfo.m_pos); |
1180 | 142k | ascii().addNote(f.str().c_str()); |
1181 | 142k | } |
1182 | 361k | } |
1183 | 159k | actParag = endParag; |
1184 | 159k | } |
1185 | 159k | return true; |
1186 | 185k | } |
1187 | | |
1188 | | |
1189 | | /* |
1190 | | * find the column size which correspond to a limit |
1191 | | * |
1192 | | * Note: complex because we need to read the file in order to find the limit |
1193 | | */ |
1194 | | bool WriterPlsParser::findSection(int zone, MWAWVec2i limits, MWAWSection &sec) |
1195 | 29.0k | { |
1196 | 29.0k | if (zone<0 || zone>=3) { |
1197 | 0 | MWAW_DEBUG_MSG(("WriterPlsParser::findSection:the zone seems bad\n")); |
1198 | 0 | return false; |
1199 | 0 | } |
1200 | 29.0k | auto &wInfo = m_state->m_windows[zone]; |
1201 | | |
1202 | 29.0k | sec=MWAWSection(); |
1203 | 29.0k | std::vector<int> listPos; |
1204 | 29.0k | if (!wInfo.getColumnLimitsFor(limits[0], listPos)) |
1205 | 141 | return false; |
1206 | | |
1207 | 28.9k | size_t numPos = listPos.size(); |
1208 | 28.9k | if (!numPos) |
1209 | 28.9k | return true; |
1210 | 0 | if (listPos[numPos-1] >= limits[1]) { |
1211 | 0 | MWAW_DEBUG_MSG(("WriterPlsParser::findSection: columns across a page\n")); |
1212 | 0 | return false; |
1213 | 0 | } |
1214 | | |
1215 | 0 | MWAWInputStreamPtr input = getInput(); |
1216 | 0 | int totalSize = 0; |
1217 | 0 | for (auto &line : listPos) { |
1218 | 0 | long pos = wInfo.m_paragraphs[size_t(line)].m_pos; |
1219 | 0 | if (!pos) { |
1220 | 0 | MWAW_DEBUG_MSG(("WriterPlsParser::findSection: bad data pos\n")); |
1221 | 0 | return false; |
1222 | 0 | } |
1223 | 0 | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1224 | 0 | if (input->readLong(2)) { |
1225 | 0 | MWAW_DEBUG_MSG(("WriterPlsParser::findSection: find a text size\n")); |
1226 | 0 | return false; |
1227 | 0 | } |
1228 | 0 | input->seek(8, librevenge::RVNG_SEEK_CUR); // sz2 and type, h, indent |
1229 | 0 | auto val = static_cast<int>(input->readLong(2)); |
1230 | 0 | if (val <= 0 || long(input->tell()) != pos + 12) { |
1231 | 0 | MWAW_DEBUG_MSG(("WriterPlsParser::findSection: file is too short\n")); |
1232 | 0 | return false; |
1233 | 0 | } |
1234 | 0 | totalSize += val; |
1235 | 0 | MWAWSection::Column col; |
1236 | 0 | col.m_width=val; |
1237 | 0 | col.m_widthUnit=librevenge::RVNG_POINT; |
1238 | 0 | sec.m_columns.push_back(col); |
1239 | 0 | } |
1240 | 0 | if (sec.m_columns.size()==1) |
1241 | 0 | sec.m_columns.resize(0); |
1242 | 0 | if (totalSize >= int(72.*getPageWidth())) { |
1243 | 0 | MWAW_DEBUG_MSG(("WriterPlsParser::findSection: total size is too big\n")); |
1244 | 0 | return false; |
1245 | 0 | } |
1246 | 0 | return true; |
1247 | 0 | } |
1248 | | |
1249 | | //////////////////////////////////////////////////////////// |
1250 | | // read all the windows zone info |
1251 | | //////////////////////////////////////////////////////////// |
1252 | | bool WriterPlsParser::readPageInfo(int zone) |
1253 | 4.67k | { |
1254 | 4.67k | if (zone<0 || zone>=3) { |
1255 | 0 | MWAW_DEBUG_MSG(("WriterPlsParser::readPageInfo:the zone seems bad\n")); |
1256 | 0 | return false; |
1257 | 0 | } |
1258 | | |
1259 | 4.67k | MWAWInputStreamPtr input = getInput(); |
1260 | 4.67k | libmwaw::DebugStream f; |
1261 | | |
1262 | 4.67k | auto &wInfo = m_state->m_windows[zone]; |
1263 | 4.67k | int numPages = wInfo.m_zone[1].m_number; |
1264 | 4.67k | if (wInfo.m_zone[1].m_size != numPages * 10) { |
1265 | 712 | MWAW_DEBUG_MSG(("WriterPlsParser::readPageInfo: odd page size\n")); |
1266 | 712 | return false; |
1267 | 712 | } |
1268 | | |
1269 | 3.96k | int actNumLine = 0; |
1270 | 3.96k | auto maxHeight = int(72.*getTextHeight()+20.); |
1271 | 3.96k | if (maxHeight < 1000) maxHeight = 1000; |
1272 | 3.96k | int prevTotalHeight = 0; |
1273 | | |
1274 | 6.47k | for (int page = 0; page < numPages; page++) { |
1275 | 4.06k | long pos = input->tell(); |
1276 | 4.06k | WriterPlsParserInternal::PageInfo pInfo; |
1277 | 4.06k | pInfo.m_firstLine = static_cast<int>(input->readLong(2)); |
1278 | 4.06k | if ((page == 0 && pInfo.m_firstLine != 1) || pInfo.m_firstLine < actNumLine) |
1279 | 1.06k | return false; |
1280 | 2.99k | actNumLine=pInfo.m_firstLine; |
1281 | 5.99k | for (auto &unkn : pInfo.m_unknown) unkn = static_cast<int>(input->readLong(2)); |
1282 | 2.99k | pInfo.m_heightFromBegin = static_cast<int>(input->readULong(2)); |
1283 | 2.99k | if (pInfo.m_heightFromBegin < prevTotalHeight) return false; |
1284 | 2.98k | prevTotalHeight = pInfo.m_heightFromBegin; |
1285 | 2.98k | pInfo.m_height = static_cast<int>(input->readULong(2)); |
1286 | 2.98k | if (pInfo.m_height > maxHeight) return false; |
1287 | | |
1288 | 2.51k | wInfo.m_pages.push_back(pInfo); |
1289 | 2.51k | f.str(""); |
1290 | 2.51k | f << "Entries(PageInfo)-"<< page+1 << ":" << pInfo; |
1291 | | |
1292 | 2.51k | ascii().addPos(pos); |
1293 | 2.51k | ascii().addNote(f.str().c_str()); |
1294 | 2.51k | } |
1295 | | |
1296 | 2.41k | return true; |
1297 | 3.96k | } |
1298 | | |
1299 | | //////////////////////////////////////////////////////////// |
1300 | | // read a windows paragraph info |
1301 | | //////////////////////////////////////////////////////////// |
1302 | | MWAWParagraph WriterPlsParser::getParagraph(WriterPlsParserInternal::ParagraphData const &data) |
1303 | 64.5k | { |
1304 | 64.5k | MWAWParagraph para; |
1305 | | |
1306 | 64.5k | para.m_marginsUnit=librevenge::RVNG_POINT; |
1307 | | // decrease a little left indent to avoid some page width pb |
1308 | 64.5k | double left=double(data.m_indent[0])-20.-72.*getPageSpan().getMarginLeft(); |
1309 | 64.5k | if (left > 0) |
1310 | 15.6k | para.m_margins[1]=left; |
1311 | 64.5k | para.m_margins[0]=double(data.m_indent[1]-data.m_indent[0]); |
1312 | 64.5k | if (getTextListener() && getTextListener()->getSection().numColumns() > 1) |
1313 | 0 | return para; // too dangerous to set the paragraph width in this case... |
1314 | 64.5k | double right=getPageWidth()*72.-double(data.m_width); |
1315 | 64.5k | if (right > 0) |
1316 | 51.4k | para.m_margins[2]=right; |
1317 | 64.5k | return para; |
1318 | 64.5k | } |
1319 | | |
1320 | | bool WriterPlsParser::readParagraphInfo(int zone) |
1321 | 6.28k | { |
1322 | 6.28k | if (zone<0 || zone>=3) { |
1323 | 0 | MWAW_DEBUG_MSG(("WriterPlsParser::readParagraphInfo:the zone seems bad\n")); |
1324 | 0 | return false; |
1325 | 0 | } |
1326 | | |
1327 | 6.28k | libmwaw::DebugStream f; |
1328 | | |
1329 | 6.28k | MWAWInputStreamPtr input = getInput(); |
1330 | 6.28k | WriterPlsParserInternal::WindowsInfo &wInfo = m_state->m_windows[zone]; |
1331 | 6.28k | int numPara = wInfo.m_zone[3].m_number; |
1332 | 6.28k | long endPos = long(input->tell()) + wInfo.m_zone[3].m_size; |
1333 | | |
1334 | 6.28k | int para = 0; |
1335 | 145k | while (para <= numPara) { |
1336 | 145k | long pos = input->tell(); |
1337 | 145k | if (pos == endPos) break; |
1338 | 145k | if (pos > endPos) return false; |
1339 | 142k | WriterPlsParserInternal::ParagraphInfo pInfo; |
1340 | | |
1341 | 142k | f.str(""); |
1342 | 142k | f << "Entries(ParaInfo)-"<< para+1 << ":"; |
1343 | 142k | auto wh = static_cast<int>(input->readLong(1)); |
1344 | 142k | if ((wh%2) == 0) { |
1345 | 39.9k | if (wh < 4) return false; |
1346 | 165k | for (int i = 0; i < (wh-4)/2; i++) |
1347 | 128k | pInfo.m_unknowns.push_back(static_cast<int>(input->readULong(2))); |
1348 | 36.9k | pInfo.m_type = -1; |
1349 | 36.9k | pInfo.m_numLines = static_cast<int>(input->readULong(1)); // probably numLine |
1350 | 36.9k | pInfo.m_height = static_cast<int>(input->readULong(2)); |
1351 | 36.9k | f << pInfo; |
1352 | 36.9k | ascii().addPos(pos); |
1353 | 36.9k | ascii().addNote(f.str().c_str()); |
1354 | 36.9k | continue; |
1355 | 39.9k | } |
1356 | 102k | para++; |
1357 | 102k | pInfo.m_flags[0] = (wh>>1); |
1358 | 102k | pInfo.m_flags[1] = static_cast<int>(input->readULong(1)); // almost always 0 |
1359 | 102k | pInfo.m_type = static_cast<int>(input->readULong(1)); |
1360 | 102k | pInfo.m_numLines = static_cast<int>(input->readULong(1)); // or numColumns if type==5 |
1361 | 102k | pInfo.m_height = static_cast<int>(input->readULong(2)); |
1362 | 102k | pInfo.m_pos = long(input->readULong(4)); |
1363 | 102k | pInfo.m_flags[2] = static_cast<int>(input->readULong(1)); // almost always 0 |
1364 | 102k | pInfo.m_width = static_cast<int>(input->readULong(2)); |
1365 | 307k | for (int i = 3; i < 5; i++) |
1366 | 205k | pInfo.m_flags[i] = static_cast<int>(input->readULong(1)); |
1367 | 102k | if (pInfo.m_numLines!=1) { |
1368 | 862k | for (int i = 0; i < pInfo.m_numLines; i++) |
1369 | 813k | pInfo.m_linesHeight.push_back(static_cast<int>(input->readULong(1))); |
1370 | 48.9k | } |
1371 | 102k | pInfo.m_height2 = static_cast<int>(input->readULong(1)); |
1372 | 102k | wInfo.m_paragraphs.push_back(pInfo); |
1373 | 102k | f << pInfo; |
1374 | | |
1375 | 102k | ascii().addPos(pos); |
1376 | 102k | ascii().addNote(f.str().c_str()); |
1377 | | |
1378 | 102k | } |
1379 | | |
1380 | 680 | return true; |
1381 | 6.28k | } |
1382 | | |
1383 | | //////////////////////////////////////////////////////////// |
1384 | | // read all the windows col info ? |
1385 | | //////////////////////////////////////////////////////////// |
1386 | | bool WriterPlsParser::readColInfo(int zone) |
1387 | 948 | { |
1388 | 948 | if (zone<0 || zone>=3) { |
1389 | 0 | MWAW_DEBUG_MSG(("WriterPlsParser::readColInfo:the zone seems bad\n")); |
1390 | 0 | return false; |
1391 | 0 | } |
1392 | | |
1393 | 948 | libmwaw::DebugStream f; |
1394 | | |
1395 | 948 | WriterPlsParserInternal::WindowsInfo &wInfo = m_state->m_windows[zone]; |
1396 | 948 | int numCols = wInfo.m_zone[2].m_number; |
1397 | 948 | if (wInfo.m_zone[2].m_size != numCols * 16) { |
1398 | 503 | MWAW_DEBUG_MSG(("WriterPlsParser::readColInfo: odd col size\n")); |
1399 | 503 | return false; |
1400 | 503 | } |
1401 | | |
1402 | 445 | MWAWInputStreamPtr input = getInput(); |
1403 | 3.88k | for (int col = 0; col < numCols; col++) { |
1404 | 3.44k | long pos = input->tell(); |
1405 | 3.44k | WriterPlsParserInternal::ColumnInfo cInfo; |
1406 | 3.44k | cInfo.m_col = static_cast<int>(input->readLong(2)); |
1407 | 3.44k | cInfo.m_unknown[0] = static_cast<int>(input->readLong(2)); |
1408 | 3.44k | cInfo.m_numCol = static_cast<int>(input->readLong(2)); |
1409 | 3.44k | cInfo.m_firstLine = static_cast<int>(input->readLong(2)); |
1410 | 13.7k | for (int i = 1; i < 4; i++) |
1411 | 10.3k | cInfo.m_unknown[i] = static_cast<int>(input->readLong(2)); |
1412 | 3.44k | cInfo.m_height = static_cast<int>(input->readLong(2)); |
1413 | 3.44k | wInfo.m_columns.push_back(cInfo); |
1414 | | |
1415 | 3.44k | f.str(""); |
1416 | 3.44k | f << "Entries(ColInfo):" << cInfo; |
1417 | 3.44k | ascii().addPos(pos); |
1418 | 3.44k | ascii().addNote(f.str().c_str()); |
1419 | 3.44k | } |
1420 | | |
1421 | 445 | return true; |
1422 | 948 | } |
1423 | | |
1424 | | bool WriterPlsParser::readText(WriterPlsParserInternal::ParagraphInfo const &info) |
1425 | 141k | { |
1426 | 141k | WriterPlsParserInternal::ParagraphData data; |
1427 | 141k | std::vector<WriterPlsParserInternal::Line> lines; |
1428 | 141k | if (!info.m_pos) { |
1429 | 6.11k | MWAW_DEBUG_MSG(("WriterPlsParser::readText: pb with pos\n")); |
1430 | 6.11k | return false; |
1431 | 6.11k | } |
1432 | | |
1433 | 135k | if (!readParagraphData(info, true, data)) |
1434 | 71.1k | return false; |
1435 | | |
1436 | 64.5k | libmwaw::DebugStream f; |
1437 | | |
1438 | 64.5k | MWAWInputStreamPtr input = getInput(); |
1439 | 64.5k | long pos = input->tell(); |
1440 | 64.5k | f.str(""); |
1441 | 64.5k | f << "Paragraph" << data.m_type << "(II):"; |
1442 | | |
1443 | 64.5k | int numLines = data.m_numData[1]; |
1444 | 64.5k | if (!readLines(info, numLines, lines)) { |
1445 | 0 | MWAW_DEBUG_MSG(("WriterPlsParser::readText: pb with the lines\n")); |
1446 | 0 | lines.resize(0); |
1447 | 0 | input->seek(pos+numLines*16, librevenge::RVNG_SEEK_SET); |
1448 | 0 | f << "###lines,"; |
1449 | 0 | } |
1450 | 175M | for (int i = 0; i < numLines; i++) |
1451 | 175M | f << "line" << i << "=[" << lines[size_t(i)] << "],"; |
1452 | | |
1453 | 64.5k | if (long(input->tell()) != data.m_endPos) { |
1454 | 60.1k | ascii().addDelimiter(input->tell(), '|'); |
1455 | 60.1k | input->seek(data.m_endPos, librevenge::RVNG_SEEK_SET); |
1456 | 60.1k | f << "#endPos,"; |
1457 | 60.1k | } |
1458 | | |
1459 | 64.5k | ascii().addPos(pos); |
1460 | 64.5k | ascii().addNote(f.str().c_str()); |
1461 | | |
1462 | 64.5k | ascii().addPos(input->tell()); |
1463 | 64.5k | ascii().addNote("_"); |
1464 | | |
1465 | 64.5k | if (!getTextListener()) |
1466 | 0 | return true; |
1467 | 64.5k | std::string const &text = data.m_text; |
1468 | 64.5k | auto const &fonts = data.m_fonts; |
1469 | 64.5k | auto numChars = long(text.length()); |
1470 | 64.5k | size_t actFont = 0, numFonts = fonts.size(); |
1471 | 64.5k | int actLine = 0; |
1472 | 64.5k | numLines=int(lines.size()); |
1473 | 64.5k | MWAWParagraph para=getParagraph(data); |
1474 | | |
1475 | 64.5k | if (numLines == 0 && info.m_height > 0) { |
1476 | 37.7k | para.setInterline(info.m_height, librevenge::RVNG_POINT); |
1477 | 37.7k | getTextListener()->setParagraph(para); |
1478 | 37.7k | } |
1479 | 3.60M | for (long c = 0; c < numChars; c++) { |
1480 | 3.53M | if (actFont < numFonts && c == fonts[actFont].m_firstChar) |
1481 | 5.85k | getTextListener()->setFont(fonts[actFont++].m_font); |
1482 | 3.53M | if (actLine < numLines && c == lines[size_t(actLine)].m_firstChar) { |
1483 | 4.83k | if (actLine) getTextListener()->insertEOL(); |
1484 | 4.83k | if (numLines == 1 && info.m_height > lines[0].m_height) { |
1485 | 164 | para.setInterline(info.m_height, librevenge::RVNG_POINT); |
1486 | 164 | getTextListener()->setParagraph(para); |
1487 | 164 | } |
1488 | 4.67k | else if (lines[size_t(actLine)].m_height) { |
1489 | 3.99k | para.setInterline(lines[size_t(actLine)].m_height, librevenge::RVNG_POINT); |
1490 | 3.99k | getTextListener()->setParagraph(para); |
1491 | 3.99k | } |
1492 | 4.83k | actLine++; |
1493 | 4.83k | } |
1494 | | |
1495 | 3.53M | auto ch = static_cast<unsigned char>(text[size_t(c)]); |
1496 | 3.53M | if (ch == 0x9) |
1497 | 32.2k | getTextListener()->insertTab(); |
1498 | 3.50M | else |
1499 | 3.50M | getTextListener()->insertCharacter(ch); |
1500 | 3.53M | } |
1501 | 64.5k | if (info.getType() != 3) |
1502 | 62.8k | getTextListener()->insertEOL(); |
1503 | | |
1504 | 64.5k | return true; |
1505 | 64.5k | } |
1506 | | |
1507 | | bool WriterPlsParser::readSection(WriterPlsParserInternal::ParagraphInfo const &info, bool mainBlock) |
1508 | 29.0k | { |
1509 | 29.0k | WriterPlsParserInternal::ParagraphData data; |
1510 | | |
1511 | 29.0k | if (!info.m_pos) { |
1512 | 0 | MWAW_DEBUG_MSG(("WriterPlsParser::readSection: can not find the beginning pos\n")); |
1513 | 0 | return false; |
1514 | 0 | } |
1515 | | |
1516 | 29.0k | if (!readParagraphData(info, true, data)) |
1517 | 19.7k | return false; |
1518 | | |
1519 | 9.37k | libmwaw::DebugStream f; |
1520 | | |
1521 | 9.37k | MWAWInputStreamPtr input = getInput(); |
1522 | 9.37k | long pos = input->tell(); |
1523 | 9.37k | f.str(""); |
1524 | 9.37k | f << "Paragraph" << data.m_type << "(II):"; |
1525 | | |
1526 | 9.37k | int numData = data.m_numData[1]; |
1527 | 9.37k | if (numData != 1) { |
1528 | 9.01k | MWAW_DEBUG_MSG(("WriterPlsParser::readSection: unexpected num of data: %d \n", numData)); |
1529 | 9.01k | } |
1530 | | |
1531 | 9.37k | std::vector<WriterPlsParserInternal::SectionInfo> sections; |
1532 | 19.6M | for (int i = 0; i < numData; i++) { |
1533 | 19.6M | WriterPlsParserInternal::SectionInfo section; |
1534 | 58.9M | for (int j = 0; j < 2; j++) |
1535 | 39.3M | section.m_flags[j] = static_cast<int>(input->readLong(2)); |
1536 | 19.6M | section.m_numCol = static_cast<int>(input->readLong(2)); // checkme |
1537 | 58.9M | for (auto &dim : section.m_dim) dim = static_cast<int>(input->readLong(2)); |
1538 | 58.9M | for (int j = 2; j < 4; j++) |
1539 | 39.3M | section.m_flags[j] = static_cast<int>(input->readLong(2)); |
1540 | 19.6M | sections.push_back(section); |
1541 | 19.6M | if (!section.empty()) |
1542 | 189k | f << "section" << i << "=[" << section << "],"; |
1543 | 19.6M | } |
1544 | | |
1545 | 9.37k | if (long(input->tell()) != data.m_endPos) { |
1546 | 8.31k | ascii().addDelimiter(input->tell(), '|'); |
1547 | 8.31k | input->seek(data.m_endPos, librevenge::RVNG_SEEK_SET); |
1548 | 8.31k | f << "#endPos,"; |
1549 | 8.31k | } |
1550 | | |
1551 | 9.37k | if (getTextListener() && mainBlock) { |
1552 | 9 | if (!getTextListener()->isSectionOpened()) |
1553 | 9 | getTextListener()->openSection(MWAWSection()); |
1554 | 9 | } |
1555 | 9.37k | ascii().addPos(pos); |
1556 | 9.37k | ascii().addNote(f.str().c_str()); |
1557 | | |
1558 | 9.37k | ascii().addPos(input->tell()); |
1559 | 9.37k | ascii().addNote("_"); |
1560 | 9.37k | return true; |
1561 | 29.0k | } |
1562 | | |
1563 | | bool WriterPlsParser::readTable(WriterPlsParserInternal::ParagraphInfo const &info) |
1564 | 147k | { |
1565 | 147k | WriterPlsParserInternal::ParagraphData data; |
1566 | | |
1567 | 147k | if (!info.m_pos) { |
1568 | 0 | MWAW_DEBUG_MSG(("WriterPlsParser::readTable: can not find the beginning pos\n")); |
1569 | 0 | return false; |
1570 | 0 | } |
1571 | | |
1572 | 147k | if (!readParagraphData(info, true, data)) |
1573 | 30.4k | return false; |
1574 | | |
1575 | 117k | libmwaw::DebugStream f; |
1576 | | |
1577 | 117k | MWAWInputStreamPtr input = getInput(); |
1578 | 117k | long pos = input->tell(); |
1579 | 117k | f.str(""); |
1580 | 117k | f << "Paragraph" << data.m_type << "(II):"; |
1581 | | |
1582 | 117k | int numData = data.m_numData[1]; |
1583 | 117k | if (numData <= 1) { |
1584 | 84.2k | MWAW_DEBUG_MSG(("WriterPlsParser::readTable: unexpected num of data: %d \n", numData)); |
1585 | 84.2k | } |
1586 | | |
1587 | 117k | std::vector<WriterPlsParserInternal::ColumnTableInfo> columns; |
1588 | 89.8M | for (int i = 0; i < numData; i++) { |
1589 | 89.7M | WriterPlsParserInternal::ColumnTableInfo cols; |
1590 | 89.7M | cols.m_height = static_cast<int>(input->readLong(2)); |
1591 | 179M | for (auto &colX : cols.m_colX) colX = static_cast<int>(input->readLong(2)); |
1592 | 89.7M | cols.m_numData = static_cast<int>(input->readLong(2)); |
1593 | 89.7M | cols.m_flags = static_cast<int>(input->readLong(2)); |
1594 | 269M | for (auto &textX : cols.m_textX) textX = static_cast<int>(input->readLong(2)); |
1595 | | |
1596 | 89.7M | columns.push_back(cols); |
1597 | 89.7M | f << "col" << i << "=[" << cols << "],"; |
1598 | 89.7M | } |
1599 | | |
1600 | 117k | if (getTextListener()) { |
1601 | 117k | std::vector<float> colSize(static_cast<size_t>(numData)); |
1602 | 89.8M | for (int i = 0; i < numData; i++) { |
1603 | 89.7M | auto const &cols = columns[size_t(i)]; |
1604 | 89.7M | colSize[size_t(i)] = float(cols.m_colX[1]-cols.m_colX[0]); |
1605 | 89.7M | } |
1606 | 117k | MWAWTable table(MWAWTable::TableDimBit); |
1607 | 117k | table.setColsSize(colSize); |
1608 | | // use the same function than getParagraph to respect alignment |
1609 | 117k | int left=columns.empty() ? 0 : columns[0].m_colX[0]-20-int(72.*getPageSpan().getMarginLeft()); |
1610 | 117k | if (left) |
1611 | 35.2k | table.setAlignment(MWAWTable::Left, float(left)); |
1612 | 117k | getTextListener()->openTable(table); |
1613 | 117k | } |
1614 | | |
1615 | 117k | if (long(input->tell()) != data.m_endPos) { |
1616 | 113k | ascii().addDelimiter(input->tell(), '|'); |
1617 | 113k | input->seek(data.m_endPos, librevenge::RVNG_SEEK_SET); |
1618 | 113k | f << "#endPos,"; |
1619 | 113k | } |
1620 | | |
1621 | 117k | ascii().addPos(pos); |
1622 | 117k | ascii().addNote(f.str().c_str()); |
1623 | | |
1624 | 117k | ascii().addPos(input->tell()); |
1625 | 117k | ascii().addNote("_"); |
1626 | | |
1627 | 117k | return true; |
1628 | 147k | } |
1629 | | |
1630 | | bool WriterPlsParser::readGraphic(WriterPlsParserInternal::ParagraphInfo const &info) |
1631 | 11.3k | { |
1632 | 11.3k | WriterPlsParserInternal::ParagraphData data; |
1633 | | |
1634 | 11.3k | if (!info.m_pos) { |
1635 | 0 | MWAW_DEBUG_MSG(("WriterPlsParser::readGraphic: can not find the beginning pos\n")); |
1636 | 0 | return false; |
1637 | 0 | } |
1638 | | |
1639 | 11.3k | if (!readParagraphData(info, true, data)) |
1640 | 4.94k | return false; |
1641 | | |
1642 | 6.43k | libmwaw::DebugStream f; |
1643 | | |
1644 | 6.43k | MWAWInputStreamPtr input = getInput(); |
1645 | 6.43k | long pos = input->tell(); |
1646 | 6.43k | f.str(""); |
1647 | 6.43k | f << "Paragraph" << data.m_type << "(II):"; |
1648 | | |
1649 | 6.43k | int numData = data.m_numData[1]; |
1650 | 6.43k | if (numData != 1) { |
1651 | 6.12k | MWAW_DEBUG_MSG(("WriterPlsParser::readGraphic: unexpected num of data: %d \n", numData)); |
1652 | 6.12k | } |
1653 | | |
1654 | 6.43k | std::vector<WriterPlsParserInternal::GraphicInfo> graphicsInfos; |
1655 | 12.6M | for (int i = 0; i < numData; i++) { |
1656 | 12.5M | WriterPlsParserInternal::GraphicInfo gInfo; |
1657 | 12.5M | gInfo.m_flags[0] = static_cast<int>(input->readLong(1)); |
1658 | 12.5M | gInfo.m_width = static_cast<int>(input->readLong(2)); |
1659 | 12.5M | gInfo.m_flags[1] = static_cast<int>(input->readULong(1)); // |
1660 | 12.5M | gInfo.m_graphicWidth = static_cast<int>(input->readLong(2)); // total width |
1661 | 75.5M | for (int j = 2; j < 7; j++) |
1662 | 62.9M | gInfo.m_flags[j] = static_cast<int>(input->readLong(2)); |
1663 | 12.5M | f << "data" << i << "=[" << gInfo << "],"; |
1664 | 12.5M | graphicsInfos.push_back(gInfo); |
1665 | 12.5M | } |
1666 | 6.43k | if (long(input->tell()) != data.m_endPos) { |
1667 | 5.49k | ascii().addDelimiter(input->tell(), '|'); |
1668 | 5.49k | input->seek(data.m_endPos, librevenge::RVNG_SEEK_SET); |
1669 | 5.49k | f << "#endPos,"; |
1670 | 5.49k | } |
1671 | | |
1672 | 6.43k | ascii().addPos(pos); |
1673 | 6.43k | ascii().addNote(f.str().c_str()); |
1674 | | |
1675 | | // read the graphic: |
1676 | 6.43k | pos = input->tell(); |
1677 | 6.43k | auto length = long(input->readULong(4)); |
1678 | 6.43k | if (!length) { |
1679 | 2.87k | MWAW_DEBUG_MSG(("WriterPlsParser::readGraphic: find a zero size graphics\n")); |
1680 | 2.87k | ascii().addPos(pos); |
1681 | 2.87k | ascii().addNote("Entries(Graphic):#sz=0"); |
1682 | 2.87k | return true; |
1683 | 2.87k | } |
1684 | 3.56k | long endPos = pos+4+length; |
1685 | 3.56k | input->seek(length, librevenge::RVNG_SEEK_CUR); |
1686 | 3.56k | if (long(input->tell()) != endPos) { |
1687 | 2.37k | MWAW_DEBUG_MSG(("WriterPlsParser::readGraphic: file is too short\n")); |
1688 | 2.37k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1689 | 2.37k | return false; |
1690 | 2.37k | } |
1691 | | |
1692 | 1.18k | f.str(""); |
1693 | 1.18k | f << "Paragraph" << data.m_type << "(III):"; |
1694 | | |
1695 | 1.18k | MWAWBox2f box; |
1696 | 1.18k | input->seek(pos+4, librevenge::RVNG_SEEK_SET); |
1697 | 1.18k | auto res = MWAWPictData::check(input, static_cast<int>(length), box); |
1698 | 1.18k | if (res == MWAWPict::MWAW_R_BAD) { |
1699 | 666 | MWAW_DEBUG_MSG(("WriterPlsParser::readGraphic: can not find the picture\n")); |
1700 | 666 | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
1701 | 666 | return false; |
1702 | 666 | } |
1703 | | |
1704 | 523 | MWAWVec2f actualSize(0,0), naturalSize(actualSize); |
1705 | 523 | if (box.size().x() > 0 && box.size().y() > 0) { |
1706 | 84 | if (actualSize.x() <= 0 || actualSize.y() <= 0) actualSize = box.size(); |
1707 | 84 | naturalSize = box.size(); |
1708 | 84 | } |
1709 | 439 | else { |
1710 | 439 | MWAW_DEBUG_MSG(("WriterPlsParser::readGraphic: can not find the picture size\n")); |
1711 | 439 | actualSize = MWAWVec2f(100,100); |
1712 | 439 | } |
1713 | | |
1714 | 523 | MWAWPosition pictPos=MWAWPosition(MWAWVec2f(0,0),actualSize, librevenge::RVNG_POINT); |
1715 | 523 | pictPos.setRelativePosition(MWAWPosition::Char); |
1716 | 523 | pictPos.setNaturalSize(naturalSize); |
1717 | 523 | f << pictPos; |
1718 | | |
1719 | | // get the picture |
1720 | 523 | input->seek(pos+4, librevenge::RVNG_SEEK_SET); |
1721 | 523 | std::shared_ptr<MWAWPict> pict(MWAWPictData::get(input, static_cast<int>(length))); |
1722 | 523 | if (getTextListener()) { |
1723 | 523 | auto para=getTextListener()->getParagraph(); |
1724 | 523 | para.setInterline(info.m_height, librevenge::RVNG_POINT); |
1725 | 523 | getTextListener()->setParagraph(para); |
1726 | 523 | MWAWEmbeddedObject picture; |
1727 | 523 | if (pict && pict->getBinary(picture)) |
1728 | 520 | getTextListener()->insertPicture(pictPos, picture); |
1729 | 523 | getTextListener()->insertEOL(); |
1730 | 523 | para.setInterline(1.0, librevenge::RVNG_PERCENT); |
1731 | 523 | getTextListener()->setParagraph(para); |
1732 | 523 | } |
1733 | 523 | if (pict) |
1734 | 520 | ascii().skipZone(pos+4, pos+4+length-1); |
1735 | | |
1736 | 523 | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
1737 | | |
1738 | 523 | ascii().addPos(pos); |
1739 | 523 | ascii().addNote(f.str().c_str()); |
1740 | | |
1741 | 523 | ascii().addPos(endPos); |
1742 | 523 | ascii().addNote("_"); |
1743 | | |
1744 | 523 | return true; |
1745 | 1.18k | } |
1746 | | |
1747 | | //////////////////////////////////////////////////////////// |
1748 | | // read a paragraph |
1749 | | //////////////////////////////////////////////////////////// |
1750 | | bool WriterPlsParser::readUnknown(WriterPlsParserInternal::ParagraphInfo const &info) |
1751 | 31.2k | { |
1752 | 31.2k | WriterPlsParserInternal::ParagraphData data; |
1753 | 31.2k | if (!readParagraphData(info, true, data)) |
1754 | 13.4k | return false; |
1755 | | |
1756 | 17.7k | libmwaw::DebugStream f; |
1757 | | |
1758 | 17.7k | MWAWInputStreamPtr input = getInput(); |
1759 | 17.7k | long pos = input->tell(); |
1760 | 17.7k | f.str(""); |
1761 | 17.7k | f << "Paragraph" << data.m_type << "(II):"; |
1762 | | |
1763 | 17.7k | int numData = data.m_numData[1]; |
1764 | 30.0M | for (int i = 0; i < numData; i++) { |
1765 | 30.0M | f << "data" << i << "=["; |
1766 | 270M | for (int j = 0; j < 8; j++) { |
1767 | 240M | auto val = static_cast<int>(input->readLong(2)); |
1768 | 240M | if (!val) f << "_,"; |
1769 | 4.77M | else f << val << ","; |
1770 | 240M | } |
1771 | 30.0M | f << "],"; |
1772 | 30.0M | } |
1773 | 17.7k | if (long(input->tell()) != data.m_endPos) { |
1774 | 17.4k | ascii().addDelimiter(input->tell(), '|'); |
1775 | 17.4k | input->seek(data.m_endPos, librevenge::RVNG_SEEK_SET); |
1776 | 17.4k | f << "#"; |
1777 | 17.4k | } |
1778 | | |
1779 | 17.7k | ascii().addPos(pos); |
1780 | 17.7k | ascii().addNote(f.str().c_str()); |
1781 | | |
1782 | 17.7k | ascii().addPos(input->tell()); |
1783 | 17.7k | ascii().addNote("_"); |
1784 | | |
1785 | 17.7k | return true; |
1786 | 31.2k | } |
1787 | | |
1788 | | //////////////////////////////////////////////////////////// |
1789 | | // read the beginning of a paragraph data |
1790 | | //////////////////////////////////////////////////////////// |
1791 | | bool WriterPlsParser::readParagraphData(WriterPlsParserInternal::ParagraphInfo const &info, bool hasFonts, |
1792 | | WriterPlsParserInternal::ParagraphData &data) |
1793 | 355k | { |
1794 | 355k | libmwaw::DebugStream f; |
1795 | | |
1796 | 355k | MWAWInputStreamPtr input = getInput(); |
1797 | 355k | long pos = info.m_pos; |
1798 | 355k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1799 | | |
1800 | 355k | data = WriterPlsParserInternal::ParagraphData(); |
1801 | 355k | auto textLength = static_cast<int>(input->readLong(2)); |
1802 | 355k | auto length2 = static_cast<int>(input->readLong(2)); |
1803 | 355k | data.m_endPos = pos+4+textLength+length2; |
1804 | | |
1805 | 355k | if (textLength < 0 || length2 < 0 || !input->checkPosition(data.m_endPos)) { |
1806 | 126k | MWAW_DEBUG_MSG(("WriterPlsParser::readParagraphData: paragraph is too short\n")); |
1807 | 126k | return false; |
1808 | 126k | } |
1809 | 228k | if (textLength) { |
1810 | 19.5k | std::string &text = data.m_text; |
1811 | 6.74M | for (int i = 0; i < textLength; i++) { |
1812 | 6.74M | auto c = char(input->readULong(1)); |
1813 | 6.74M | if (c == '\0') return false; |
1814 | 6.72M | text += c; |
1815 | 6.72M | } |
1816 | 19.5k | } |
1817 | 215k | auto type = static_cast<int>(input->readULong(2)); |
1818 | 215k | data.m_type = (type & 7); |
1819 | 215k | data.m_typeFlag = (type & 0xFFF8); |
1820 | | |
1821 | 215k | f << "Entries(Paragraph" << data.m_type << "):"; |
1822 | | |
1823 | | // format type |
1824 | 215k | if (info.m_type != data.m_type + (data.m_typeFlag!=0 ? 8 : 0)) { |
1825 | 184k | MWAW_DEBUG_MSG(("WriterPlsParser::readParagraph: I find an unexpected type\n")); |
1826 | 184k | f << "#diffType=" << info.m_type << ","; |
1827 | 184k | } |
1828 | | |
1829 | 215k | data.m_height = static_cast<int>(input->readLong(2)); |
1830 | 215k | data.m_indent[0] = static_cast<int>(input->readLong(2)); // left indent ? |
1831 | 215k | data.m_width = static_cast<int>(input->readLong(2)); |
1832 | 215k | data.m_indent[1] = static_cast<int>(input->readLong(2)); // first pos indent ? |
1833 | 215k | data.m_unknown = static_cast<int>(input->readLong(2)); |
1834 | | |
1835 | 430k | for (auto &numData : data.m_numData) numData = static_cast<int>(input->readLong(2)); |
1836 | | |
1837 | 215k | auto &fonts = data.m_fonts; |
1838 | 215k | if (hasFonts) { |
1839 | 215k | long actPos = input->tell(); |
1840 | 215k | if (data.m_numData[0]<0 || !input->checkPosition(actPos+data.m_numData[0]*16)) { |
1841 | 59.2k | MWAW_DEBUG_MSG(("WriterPlsParser::readParagraph: pb reading the number of fonts\n")); |
1842 | 59.2k | f << "###numFonts=" << data.m_numData[0] << ","; |
1843 | 59.2k | } |
1844 | 156k | else if (!readFonts(data.m_numData[0], data.m_type, fonts)) { |
1845 | 0 | MWAW_DEBUG_MSG(("WriterPlsParser::readParagraph: pb with the fonts\n")); |
1846 | 0 | input->seek(actPos+data.m_numData[0]*16, librevenge::RVNG_SEEK_SET); |
1847 | 0 | } |
1848 | 215k | } |
1849 | | |
1850 | 215k | f << data; |
1851 | 4.80M | for (size_t i = 0; i < fonts.size(); i++) { |
1852 | 4.58M | f << "font" << i << "=["; |
1853 | | #ifdef DEBUG |
1854 | | f << fonts[i].m_font.getDebugString(getFontConverter()); |
1855 | | #endif |
1856 | 4.58M | f << fonts[i] << "],"; |
1857 | 4.58M | } |
1858 | 215k | ascii().addPos(pos); |
1859 | 215k | ascii().addNote(f.str().c_str()); |
1860 | | |
1861 | 215k | return true; |
1862 | 228k | } |
1863 | | |
1864 | | //////////////////////////////////////////////////////////// |
1865 | | // read a series of fonts |
1866 | | //////////////////////////////////////////////////////////// |
1867 | | bool WriterPlsParser::readFonts |
1868 | | (int nFonts, int type, std::vector<WriterPlsParserInternal::Font> &fonts) |
1869 | 156k | { |
1870 | 156k | fonts.resize(0); |
1871 | 156k | MWAWInputStreamPtr input = getInput(); |
1872 | 156k | bool hasFontExtra = true; |
1873 | 156k | switch (type) { |
1874 | 123k | case 0: // find in these case junk in the last part of font |
1875 | 127k | case 2: |
1876 | 131k | case 4: |
1877 | 131k | hasFontExtra = false; |
1878 | 131k | break; |
1879 | 24.3k | default: |
1880 | 24.3k | break; |
1881 | 156k | } |
1882 | 156k | int actPos = 0; |
1883 | 156k | libmwaw::DebugStream f; |
1884 | 4.74M | for (int i = 0; i < nFonts; i++) { |
1885 | 4.58M | if (!input->checkPosition(input->tell()+16)) { |
1886 | 0 | MWAW_DEBUG_MSG(("WriterPlsParser::readFonts: the zone seems too short\n")); |
1887 | 0 | break; |
1888 | 0 | } |
1889 | 4.58M | WriterPlsParserInternal::Font fInfo; |
1890 | 4.58M | f.str(""); |
1891 | 4.58M | auto val = static_cast<int>(input->readLong(2)); // 65|315 |
1892 | 4.58M | if (val) f << "dim?=" << val << ","; |
1893 | 18.3M | for (int j = 0; j < 3; j++) { // always 0: a color ? |
1894 | 13.7M | val = static_cast<int>(input->readLong(1)); |
1895 | 13.7M | if (val) f << "f" << j << "=" << val << ","; |
1896 | 13.7M | } |
1897 | 4.58M | MWAWFont &font = fInfo.m_font; |
1898 | 4.58M | font.setId(static_cast<int>(input->readULong(1))); |
1899 | 4.58M | auto flag = static_cast<int>(input->readULong(1)); |
1900 | 4.58M | uint32_t flags = 0; |
1901 | 4.58M | if (flag&0x1) flags |= MWAWFont::boldBit; |
1902 | 4.58M | if (flag&0x2) flags |= MWAWFont::italicBit; |
1903 | 4.58M | if (flag&0x4) font.setUnderlineStyle(MWAWFont::Line::Simple); |
1904 | 4.58M | if (flag&0x8) flags |= MWAWFont::embossBit; |
1905 | 4.58M | if (flag&0x10) flags |= MWAWFont::shadowBit; |
1906 | 4.58M | if (flag&0x60) |
1907 | 945k | f << "#fl=" << std::hex << (flag&0x60) << std::dec << ","; |
1908 | 4.58M | if (flag&0x80) f << "fl80,"; // frequent, find on complete line, |
1909 | | |
1910 | 4.58M | flag= static_cast<int>(input->readULong(1)); |
1911 | 4.58M | if (flag&2) font.set(MWAWFont::Script::super100()); |
1912 | 4.58M | if (flag&4) font.set(MWAWFont::Script::sub100()); |
1913 | 4.58M | if (flag&0x10) f << "flA10,";// also frequent, find on complete line |
1914 | 4.58M | if (flag&0xE9) f << "#flA=" << std::hex << (flag&0xE9) << std::dec << ","; |
1915 | 4.58M | font.setFlags(flags); |
1916 | 4.58M | val = static_cast<int>(input->readLong(1));// always 0 |
1917 | 4.58M | if (val) |
1918 | 2.19M | f << "#g0=" << val << ","; |
1919 | 4.58M | font.setSize(float(input->readLong(1))); |
1920 | 4.58M | fInfo.m_firstChar = actPos; |
1921 | 4.58M | auto nChar = static_cast<int>(input->readULong(2)); |
1922 | 4.58M | actPos += nChar; |
1923 | 4.58M | if (!hasFontExtra) |
1924 | 3.74M | input->seek(4, librevenge::RVNG_SEEK_CUR); |
1925 | 844k | else { // always 0 |
1926 | 2.53M | for (int j = 0; j < 2; j++) { |
1927 | 1.68M | val = static_cast<int>(input->readLong(2)); |
1928 | 1.68M | if (val) f << "g" << j+1 << "=" << val << ","; |
1929 | 1.68M | } |
1930 | 844k | } |
1931 | 4.58M | font.m_extra+=f.str(); |
1932 | 4.58M | fonts.push_back(fInfo); |
1933 | 4.58M | } |
1934 | | |
1935 | 156k | return true; |
1936 | 156k | } |
1937 | | |
1938 | | //////////////////////////////////////////////////////////// |
1939 | | // read a series of lines |
1940 | | //////////////////////////////////////////////////////////// |
1941 | | bool WriterPlsParser::readLines |
1942 | | (WriterPlsParserInternal::ParagraphInfo const &/*info*/, |
1943 | | int nLines, std::vector<WriterPlsParserInternal::Line> &lines) |
1944 | 64.5k | { |
1945 | 64.5k | lines.resize(0); |
1946 | 64.5k | MWAWInputStreamPtr input = getInput(); |
1947 | | |
1948 | 64.5k | int actPos = 0; |
1949 | 175M | for (int i = 0; i < nLines; i++) { |
1950 | 175M | WriterPlsParserInternal::Line lInfo; |
1951 | 175M | lInfo.m_height = static_cast<int>(input->readLong(2)); |
1952 | 175M | lInfo.m_maxFontSize = static_cast<int>(input->readLong(2)); // checkMe |
1953 | 175M | lInfo.m_width = static_cast<int>(input->readLong(2)); |
1954 | 175M | auto nChar = static_cast<int>(input->readLong(2)); |
1955 | 175M | lInfo.m_firstChar = actPos; |
1956 | 175M | actPos += nChar; |
1957 | | /* |
1958 | | f0 always 0 |
1959 | | f1 almost always 0, if not 1 |
1960 | | f2 almost always 0, if not 2, 3, 4, c |
1961 | | f3 almost always 0, if not 200, 400, 6465, 7600, dfc, e03, e04, e06 : junk? |
1962 | | */ |
1963 | 701M | for (auto &fl : lInfo.m_flags) fl = static_cast<int>(input->readLong(2)); |
1964 | 175M | lines.push_back(lInfo); |
1965 | 175M | } |
1966 | 64.5k | return true; |
1967 | 64.5k | } |
1968 | | |
1969 | | //////////////////////////////////////////////////////////// |
1970 | | // read the print info |
1971 | | //////////////////////////////////////////////////////////// |
1972 | | bool WriterPlsParser::readPrintInfo() |
1973 | 31.6k | { |
1974 | 31.6k | MWAWInputStreamPtr input = getInput(); |
1975 | 31.6k | long pos = input->tell(); |
1976 | 31.6k | libmwaw::DebugStream f; |
1977 | | // print info |
1978 | 31.6k | libmwaw::PrinterInfo info; |
1979 | 31.6k | if (!info.read(input)) return false; |
1980 | 31.2k | f << "Entries(PrintInfo):"<< info; |
1981 | | |
1982 | 31.2k | MWAWVec2i paperSize = info.paper().size(); |
1983 | 31.2k | MWAWVec2i pageSize = info.page().size(); |
1984 | 31.2k | if (pageSize.x() <= 0 || pageSize.y() <= 0 || |
1985 | 30.9k | paperSize.x() <= 0 || paperSize.y() <= 0) return false; |
1986 | | |
1987 | | // define margin from print info |
1988 | 30.7k | MWAWVec2i lTopMargin= -1 * info.paper().pos(0); |
1989 | 30.7k | MWAWVec2i rBotMargin=info.paper().size() - info.page().size(); |
1990 | | |
1991 | | // move margin left | top |
1992 | 30.7k | int decalX = lTopMargin.x() > 14 ? lTopMargin.x()-14 : 0; |
1993 | 30.7k | int decalY = lTopMargin.y() > 14 ? lTopMargin.y()-14 : 0; |
1994 | 30.7k | lTopMargin -= MWAWVec2i(decalX, decalY); |
1995 | 30.7k | rBotMargin += MWAWVec2i(decalX, decalY); |
1996 | | |
1997 | | // decrease right | bottom |
1998 | 30.7k | int rightMarg = rBotMargin.x() -50; |
1999 | 30.7k | if (rightMarg < 0) rightMarg=0; |
2000 | 30.7k | int botMarg = rBotMargin.y() -50; |
2001 | 30.7k | if (botMarg < 0) botMarg=0; |
2002 | | |
2003 | 30.7k | getPageSpan().setMarginTop(lTopMargin.y()/72.0); |
2004 | 30.7k | getPageSpan().setMarginBottom(botMarg/72.0); |
2005 | 30.7k | getPageSpan().setMarginLeft(lTopMargin.x()/72.0); |
2006 | 30.7k | getPageSpan().setMarginRight(rightMarg/72.0); |
2007 | 30.7k | getPageSpan().setFormLength(paperSize.y()/72.); |
2008 | 30.7k | getPageSpan().setFormWidth(paperSize.x()/72.); |
2009 | | |
2010 | 30.7k | ascii().addPos(pos); |
2011 | 30.7k | ascii().addNote(f.str().c_str()); |
2012 | | |
2013 | 30.7k | input->seek(pos+0x78, librevenge::RVNG_SEEK_SET); |
2014 | 30.7k | if (long(input->tell()) != pos+0x78) { |
2015 | 0 | MWAW_DEBUG_MSG(("WriterPlsParser::readPrintInfo: file is too short\n")); |
2016 | 0 | return false; |
2017 | 0 | } |
2018 | | |
2019 | 30.7k | return true; |
2020 | 30.7k | } |
2021 | | |
2022 | | // vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: |