/src/libmwaw/src/lib/GreatWksText.cxx
Line | Count | Source |
1 | | /* -*- Mode: C++; c-default-style: "k&r"; indent-tabs-mode: nil; tab-width: 2; c-basic-offset: 2 -*- */ |
2 | | |
3 | | /* libmwaw |
4 | | * Version: MPL 2.0 / LGPLv2+ |
5 | | * |
6 | | * The contents of this file are subject to the Mozilla Public License Version |
7 | | * 2.0 (the "License"); you may not use this file except in compliance with |
8 | | * the License or as specified alternatively below. You may obtain a copy of |
9 | | * the License at http://www.mozilla.org/MPL/ |
10 | | * |
11 | | * Software distributed under the License is distributed on an "AS IS" basis, |
12 | | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
13 | | * for the specific language governing rights and limitations under the |
14 | | * License. |
15 | | * |
16 | | * Major Contributor(s): |
17 | | * Copyright (C) 2002 William Lachance (wrlach@gmail.com) |
18 | | * Copyright (C) 2002,2004 Marc Maurer (uwog@uwog.net) |
19 | | * Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba@bluewin.ch) |
20 | | * Copyright (C) 2006, 2007 Andrew Ziem |
21 | | * Copyright (C) 2011, 2012 Alonso Laurent (alonso@loria.fr) |
22 | | * |
23 | | * |
24 | | * All Rights Reserved. |
25 | | * |
26 | | * For minor contributions see the git repository. |
27 | | * |
28 | | * Alternatively, the contents of this file may be used under the terms of |
29 | | * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"), |
30 | | * in which case the provisions of the LGPLv2+ are applicable |
31 | | * instead of those above. |
32 | | */ |
33 | | |
34 | | #include <cstring> |
35 | | #include <iomanip> |
36 | | #include <iostream> |
37 | | #include <limits> |
38 | | #include <map> |
39 | | #include <sstream> |
40 | | |
41 | | #include <librevenge/librevenge.h> |
42 | | |
43 | | #include "MWAWDebug.hxx" |
44 | | #include "MWAWFont.hxx" |
45 | | #include "MWAWFontConverter.hxx" |
46 | | #include "MWAWGraphicListener.hxx" |
47 | | #include "MWAWListener.hxx" |
48 | | #include "MWAWParagraph.hxx" |
49 | | #include "MWAWParser.hxx" |
50 | | #include "MWAWPosition.hxx" |
51 | | #include "MWAWSection.hxx" |
52 | | #include "MWAWRSRCParser.hxx" |
53 | | |
54 | | #include "GreatWksDocument.hxx" |
55 | | |
56 | | #include "GreatWksText.hxx" |
57 | | |
58 | | /** Internal: the structures of a GreatWksText */ |
59 | | namespace GreatWksTextInternal |
60 | | { |
61 | | /** the different plc type */ |
62 | | enum PLCType { P_Font, P_Page, P_Ruler, P_Token, P_Unknown}; |
63 | | |
64 | | /** Internal : a PLC: used to store change of properties in GreatWksTextInternal::Zone */ |
65 | | struct PLC { |
66 | | /// the constructor |
67 | | PLC() |
68 | 137k | : m_type(P_Unknown) |
69 | 137k | , m_id(-1) |
70 | 137k | , m_extra("") |
71 | 137k | { |
72 | 137k | } |
73 | | //! operator<< |
74 | | friend std::ostream &operator<<(std::ostream &o, PLC const &plc); |
75 | | /** the PLC types */ |
76 | | PLCType m_type; |
77 | | /** the id */ |
78 | | int m_id; |
79 | | /** extra data */ |
80 | | std::string m_extra; |
81 | | }; |
82 | | std::ostream &operator<<(std::ostream &o, PLC const &plc) |
83 | 0 | { |
84 | 0 | switch (plc.m_type) { |
85 | 0 | case P_Font: |
86 | 0 | o << "F"; |
87 | 0 | break; |
88 | 0 | case P_Page: |
89 | 0 | o << "Pg"; |
90 | 0 | break; |
91 | 0 | case P_Ruler: |
92 | 0 | o << "R"; |
93 | 0 | break; |
94 | 0 | case P_Token: |
95 | 0 | o << "Tn"; |
96 | 0 | break; |
97 | 0 | case P_Unknown: |
98 | | #if !defined(__clang__) |
99 | | default: |
100 | | #endif |
101 | 0 | o << "#Unkn"; |
102 | 0 | break; |
103 | 0 | } |
104 | 0 | if (plc.m_id >= 0) o << plc.m_id; |
105 | 0 | else o << "_"; |
106 | 0 | if (plc.m_extra.length()) o << ":" << plc.m_extra; |
107 | 0 | return o; |
108 | 0 | } |
109 | | |
110 | | //////////////////////////////////////// |
111 | | //! Internal and low level: structure which stores a token for GreatWksText |
112 | | struct Token { |
113 | | //! constructor |
114 | | Token() |
115 | 11.8M | : m_type(-1) |
116 | 11.8M | , m_format(0) |
117 | 11.8M | , m_pictEntry() |
118 | 11.8M | , m_dataSize(0) |
119 | 11.8M | , m_dim(0,0) |
120 | 11.8M | , m_date(0xFFFFFFFF) |
121 | 11.8M | , m_extra("") |
122 | 11.8M | { |
123 | 11.8M | } |
124 | | //! returns a field format |
125 | | std::string getDTFormat() const; |
126 | | //! try to send the token to the listener |
127 | | bool sendTo(MWAWListener &listener) const; |
128 | | //! operator<< |
129 | | friend std::ostream &operator<<(std::ostream &o, Token const &tkn); |
130 | | //! the token type |
131 | | int m_type; |
132 | | //! the token format |
133 | | int m_format; |
134 | | //! the picture entry |
135 | | MWAWEntry m_pictEntry; |
136 | | //! the picture data size |
137 | | long m_dataSize; |
138 | | //! the picture dimension |
139 | | MWAWVec2f m_dim; |
140 | | //! the token date (0xFFFFFFFF means actual date) |
141 | | uint32_t m_date; |
142 | | //! extra data |
143 | | std::string m_extra; |
144 | | }; |
145 | | |
146 | | bool Token::sendTo(MWAWListener &listener) const |
147 | 297k | { |
148 | 297k | switch (m_type) { |
149 | 233 | case 2: |
150 | 233 | switch (m_format) { |
151 | 51 | case 1: |
152 | 58 | case 3: // must be roman |
153 | 58 | listener.insertField(MWAWField(MWAWField::PageNumber)); |
154 | 58 | break; |
155 | 125 | case 2: |
156 | 128 | case 4: // must be roman |
157 | 128 | listener.insertField(MWAWField(MWAWField::PageNumber)); |
158 | 128 | listener.insertUnicodeString(librevenge::RVNGString(" of ")); |
159 | 128 | listener.insertField(MWAWField(MWAWField::PageCount)); |
160 | 128 | break; |
161 | 47 | default: |
162 | 47 | listener.insertField(MWAWField(MWAWField::PageNumber)); |
163 | 47 | break; |
164 | 233 | } |
165 | 233 | return true; |
166 | 345 | case 0x15: |
167 | 368 | case 0x16: { |
168 | 368 | MWAWField field(m_type==0x15 ? MWAWField::Date : MWAWField::Time); |
169 | 368 | field.m_DTFormat=getDTFormat(); |
170 | 368 | listener.insertField(field); |
171 | 368 | return true; |
172 | 345 | } |
173 | 297k | default: |
174 | 297k | break; |
175 | 297k | } |
176 | 297k | return false; |
177 | 297k | } |
178 | | |
179 | | std::string Token::getDTFormat() const |
180 | 368 | { |
181 | 368 | switch (m_type) { |
182 | 345 | case 0x15: |
183 | 345 | switch (m_format) { |
184 | 0 | case 0xa: |
185 | 0 | return "%m/%d/%y"; |
186 | 312 | case 0xb: |
187 | 312 | return "%b %d, %Y"; |
188 | 1 | case 0xc: |
189 | 1 | return "%b %Y"; |
190 | 0 | case 0xd: |
191 | 0 | return "%b %d"; |
192 | 0 | case 0xe: |
193 | 0 | return "%B %d, %Y"; |
194 | 3 | case 0xf: |
195 | 3 | return "%B %Y"; |
196 | 0 | case 0x10: |
197 | 0 | return "%B %d"; |
198 | 0 | case 0x11: |
199 | 0 | return "%a, %b %d, %Y"; |
200 | 7 | case 0x12: |
201 | 7 | return "%A, %B %d, %Y"; |
202 | 22 | default: |
203 | 22 | break; |
204 | 345 | } |
205 | 22 | break; |
206 | 23 | case 0x16: |
207 | 23 | switch (m_format) { |
208 | 0 | case 0x14: |
209 | 0 | return "%I:%M %p"; |
210 | 0 | case 0x15: |
211 | 0 | return "%I:%M:%S %p"; |
212 | 3 | case 0x16: |
213 | 3 | return "%I:%M"; |
214 | 0 | case 0x17: |
215 | 0 | return "%I:%M:%S"; |
216 | 0 | case 0x18: |
217 | 0 | return "%H:%M"; |
218 | 0 | case 0x19: |
219 | 0 | return "%H:%M:%S"; |
220 | 20 | default: |
221 | 20 | break; |
222 | 23 | } |
223 | 20 | break; |
224 | 20 | default: |
225 | 0 | break; |
226 | 368 | } |
227 | 42 | return ""; |
228 | 368 | } |
229 | | |
230 | | std::ostream &operator<<(std::ostream &o, Token const &token) |
231 | 0 | { |
232 | 0 | switch (token.m_type) { |
233 | 0 | case 0: // none |
234 | 0 | break; |
235 | 0 | case 2: |
236 | 0 | switch (token.m_format) { |
237 | 0 | case 0: |
238 | 0 | o << "page,"; |
239 | 0 | break; |
240 | 0 | case 1: |
241 | 0 | o << "page/pagecount,"; |
242 | 0 | break; |
243 | 0 | case 2: |
244 | 0 | o << "page[roman],"; |
245 | 0 | break; |
246 | 0 | case 3: |
247 | 0 | o << "page/pagecount[roman],"; |
248 | 0 | break; |
249 | 0 | default: |
250 | 0 | o << "page[#m_format=" << token.m_format << "],"; |
251 | 0 | break; |
252 | 0 | } |
253 | 0 | break; |
254 | 0 | case 4: |
255 | 0 | o << "pict,dim="<< token.m_dim << ",sz=" << std::hex << token.m_dataSize << std::dec << ","; |
256 | 0 | break; |
257 | 0 | case 0x15: |
258 | 0 | case 0x16: { |
259 | 0 | o << (token.m_type==0x15 ? "date" : "time"); |
260 | 0 | std::string format=token.getDTFormat(); |
261 | 0 | if (!format.empty()) |
262 | 0 | o << "[" << format << "]"; |
263 | 0 | else |
264 | 0 | o << "[#format=" << token.m_format << "]"; |
265 | 0 | if (token.m_date != 0xFFFFFFFF) |
266 | 0 | o << ":val=" << std::hex << token.m_date << std::dec; |
267 | 0 | o << ","; |
268 | 0 | break; |
269 | 0 | } |
270 | 0 | default: |
271 | 0 | MWAW_DEBUG_MSG(("GreatWksTextInternal::Token: unknown type=%d\n", token.m_type)); |
272 | 0 | o << "#type=" << token.m_type << ","; |
273 | 0 | if (token.m_format) |
274 | 0 | o << "#format=" << token.m_format << ","; |
275 | 0 | } |
276 | 0 | o << token.m_extra; |
277 | 0 | return o; |
278 | 0 | } |
279 | | //////////////////////////////////////// |
280 | | //! Internal and low level: structure which stores a text position for GreatWksText |
281 | | struct Frame { |
282 | | //! constructor |
283 | | Frame() |
284 | 807k | : m_pos() |
285 | 807k | , m_page(0) |
286 | 807k | , m_extra("") |
287 | 807k | { |
288 | 807k | } |
289 | | //! operator<< |
290 | | friend std::ostream &operator<<(std::ostream &o, Frame const &frm) |
291 | 0 | { |
292 | 0 | o << "dim=" << frm.m_pos << ","; |
293 | 0 | if (frm.m_page) o << "page=" << frm.m_page << ","; |
294 | 0 | o << frm.m_extra; |
295 | 0 | return o; |
296 | 0 | } |
297 | | |
298 | | //! the frame position |
299 | | MWAWBox2f m_pos; |
300 | | //! the page |
301 | | int m_page; |
302 | | //! extra data |
303 | | std::string m_extra; |
304 | | }; |
305 | | //////////////////////////////////////// |
306 | | //! Internal and low level: structure which stores a text zone header for GreatWksText |
307 | | struct Zone { |
308 | | //! constructor |
309 | | Zone() |
310 | 302k | : m_type(-1) |
311 | 302k | , m_numFonts(0) |
312 | 302k | , m_numRulers(0) |
313 | 302k | , m_numLines(0) |
314 | 302k | , m_numTokens(0) |
315 | 302k | , m_numChar(0) |
316 | 302k | , m_numCharPLC(0) |
317 | 302k | , m_numFrames(0) |
318 | 302k | , m_fontList() |
319 | 302k | , m_rulerList() |
320 | 302k | , m_tokenList() |
321 | 302k | , m_frameList() |
322 | 302k | , m_textEntry() |
323 | 302k | , m_posPLCMap() |
324 | 302k | , m_parsed(false) |
325 | 302k | , m_extra("") |
326 | 302k | { |
327 | 302k | } |
328 | | //! returns true if this is the main zone |
329 | | bool isMain() const |
330 | 68.5k | { |
331 | 68.5k | return m_type==3; |
332 | 68.5k | } |
333 | | //! check if the data read are or not ok |
334 | | bool ok() const |
335 | 86.0k | { |
336 | 86.0k | if (m_type<0 || m_type > 5) |
337 | 1.12k | return false; |
338 | 84.9k | if (m_numFonts<=0 || m_numRulers<=0 || m_numLines<0 || m_numTokens<=0 || m_numChar<0 || |
339 | 75.4k | m_numCharPLC<=0 || m_numFrames<0) |
340 | 14.0k | return false; |
341 | 70.8k | return true; |
342 | 84.9k | } |
343 | | //! returns the data size |
344 | | long size() const |
345 | 70.8k | { |
346 | 70.8k | return 22*m_numFonts+192*m_numRulers+6*m_numCharPLC |
347 | 70.8k | +18*m_numTokens+14*m_numLines+22*m_numFrames+m_numChar; |
348 | 70.8k | } |
349 | | //! returns true if the data has graphic |
350 | | bool hasGraphics() const |
351 | 298 | { |
352 | 326 | for (auto const &token : m_tokenList) { |
353 | 326 | if (token.m_type==4) |
354 | 0 | return true; |
355 | 326 | } |
356 | 298 | return false; |
357 | 298 | } |
358 | | //! operator<< |
359 | | friend std::ostream &operator<<(std::ostream &o, Zone const &fr) |
360 | 0 | { |
361 | 0 | switch (fr.m_type) { |
362 | 0 | case 1: // in draw=textbox |
363 | 0 | o << "header/footer,"; |
364 | 0 | break; |
365 | 0 | case 2: |
366 | 0 | o << "textbox,"; |
367 | 0 | break; |
368 | 0 | case 3: |
369 | 0 | o << "main,"; |
370 | 0 | break; |
371 | 0 | default: |
372 | 0 | o << "#type=" << fr.m_type << ","; |
373 | 0 | break; |
374 | 0 | } |
375 | 0 | if (fr.m_numFonts) |
376 | 0 | o << "nFonts=" << fr.m_numFonts << ","; |
377 | 0 | if (fr.m_numRulers) |
378 | 0 | o << "nRulers=" << fr.m_numRulers << ","; |
379 | 0 | if (fr.m_numChar) |
380 | 0 | o << "length[text]=" << fr.m_numChar << ","; |
381 | 0 | if (fr.m_numCharPLC) |
382 | 0 | o << "char[plc]=" << fr.m_numCharPLC << ","; |
383 | 0 | if (fr.m_numLines) |
384 | 0 | o << "nLines=" << fr.m_numLines << ","; |
385 | 0 | if (fr.m_numTokens) |
386 | 0 | o << "nTokens=" << fr.m_numTokens << ","; |
387 | 0 | if (fr.m_numFrames) |
388 | 0 | o << "nFrames=" << fr.m_numFrames << ","; |
389 | 0 | o << fr.m_extra; |
390 | 0 | return o; |
391 | 0 | } |
392 | | //! the main type: 1=auxi, 3=main |
393 | | int m_type; |
394 | | //! the number of fonts |
395 | | int m_numFonts; |
396 | | //! the number of rulers |
397 | | int m_numRulers; |
398 | | //! the number of lines |
399 | | int m_numLines; |
400 | | //! the number of token |
401 | | int m_numTokens; |
402 | | //! the number of character |
403 | | long m_numChar; |
404 | | //! the number of char plc |
405 | | int m_numCharPLC; |
406 | | //! the number of frames (ie. one by column and one by pages ) |
407 | | int m_numFrames; |
408 | | //! the list of font |
409 | | std::vector<MWAWFont> m_fontList; |
410 | | //! the list of ruler |
411 | | std::vector<MWAWParagraph> m_rulerList; |
412 | | //! the list of token |
413 | | std::vector<Token> m_tokenList; |
414 | | //! the list of frame token |
415 | | std::vector<Frame> m_frameList; |
416 | | //! the text entry list |
417 | | MWAWEntry m_textEntry; |
418 | | //! a map text pos -> PLC |
419 | | std::multimap<long, PLC> m_posPLCMap; |
420 | | //! a bool to know if the data are send to the listener |
421 | | mutable bool m_parsed; |
422 | | //! extra data |
423 | | std::string m_extra; |
424 | | }; |
425 | | |
426 | | //////////////////////////////////////// |
427 | | //! Internal: the state of a GreatWksText |
428 | | struct State { |
429 | | //! constructor |
430 | | State() |
431 | 115k | : m_fileIdFontIdMap() |
432 | 115k | , m_zonesList() |
433 | 115k | , m_version(-1) |
434 | 115k | , m_numPages(-1) |
435 | 115k | { |
436 | 115k | } |
437 | | //! returns the font id corresponding to a fId |
438 | | int getFId(int fileId) const |
439 | 2.95M | { |
440 | 2.95M | if (m_fileIdFontIdMap.find(fileId)==m_fileIdFontIdMap.end()) |
441 | 2.80M | return fileId; |
442 | 141k | return m_fileIdFontIdMap.find(fileId)->second; |
443 | 2.95M | } |
444 | | //! a global map file font id-> fontconverter id |
445 | | std::map<int, int> m_fileIdFontIdMap; |
446 | | //! a list of text zone |
447 | | std::vector<Zone> m_zonesList; |
448 | | //! the file version |
449 | | mutable int m_version; |
450 | | int m_numPages /* the number of pages */; |
451 | | }; |
452 | | } |
453 | | |
454 | | //////////////////////////////////////////////////////////// |
455 | | // constructor/destructor, ... |
456 | | //////////////////////////////////////////////////////////// |
457 | | GreatWksText::GreatWksText(GreatWksDocument &document) |
458 | 115k | : m_document(document) |
459 | 115k | , m_parserState(document.m_parserState) |
460 | 115k | , m_state(new GreatWksTextInternal::State) |
461 | 115k | , m_mainParser(&document.getMainParser()) |
462 | 115k | { |
463 | 115k | } |
464 | | |
465 | | GreatWksText::~GreatWksText() |
466 | 115k | { } |
467 | | |
468 | | int GreatWksText::version() const |
469 | 0 | { |
470 | 0 | if (m_state->m_version < 0) |
471 | 0 | m_state->m_version = m_parserState->m_version; |
472 | 0 | return m_state->m_version; |
473 | 0 | } |
474 | | |
475 | | int GreatWksText::numPages() const |
476 | 19.2k | { |
477 | 19.2k | if (m_state->m_numPages >= 0) |
478 | 2.58k | return m_state->m_numPages; |
479 | | |
480 | 16.7k | int nPages=1; |
481 | 16.7k | for (auto const &zone : m_state->m_zonesList) { |
482 | 6.45k | if (!zone.isMain() || zone.m_frameList.empty()) |
483 | 2.35k | continue; |
484 | 4.10k | if (zone.m_frameList.back().m_page>1) |
485 | 2.58k | nPages = zone.m_frameList.back().m_page; |
486 | 4.10k | break; |
487 | 6.45k | } |
488 | | |
489 | 16.7k | return m_state->m_numPages = nPages; |
490 | 19.2k | } |
491 | | |
492 | | int GreatWksText::getFontId(int fileId) const |
493 | 59.1k | { |
494 | 59.1k | return m_state->getFId(fileId); |
495 | 59.1k | } |
496 | | |
497 | | int GreatWksText::numHFZones() const |
498 | 5.05k | { |
499 | 5.05k | int nHF=0; |
500 | 6.45k | for (auto const &zone : m_state->m_zonesList) { |
501 | 6.45k | if (zone.isMain()) |
502 | 5.05k | break; |
503 | 1.39k | nHF++; |
504 | 1.39k | } |
505 | 5.05k | return nHF; |
506 | 5.05k | } |
507 | | |
508 | | bool GreatWksText::canSendTextBoxAsGraphic(MWAWEntry const &entry) |
509 | 518 | { |
510 | 518 | if (!entry.valid()) |
511 | 35 | return false; |
512 | 483 | MWAWInputStreamPtr &input= m_parserState->m_input; |
513 | 483 | long pos=input->tell(); |
514 | 483 | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
515 | 483 | GreatWksTextInternal::Zone zone; |
516 | 483 | bool ok=!readZone(zone) ||!zone.hasGraphics(); |
517 | 483 | input->seek(pos, librevenge::RVNG_SEEK_SET); |
518 | 483 | return ok; |
519 | 518 | } |
520 | | |
521 | | bool GreatWksText::sendTextbox(MWAWEntry const &entry, MWAWListenerPtr listener) |
522 | 49.3k | { |
523 | 49.3k | if (!listener && !m_parserState->getMainListener()) { |
524 | 0 | MWAW_DEBUG_MSG(("GreatWksText::sendTextbox: can not find a listener\n")); |
525 | 0 | return false; |
526 | 0 | } |
527 | 49.3k | if (!entry.valid()) |
528 | 568 | return false; |
529 | 48.7k | MWAWInputStreamPtr &input= m_parserState->m_input; |
530 | 48.7k | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
531 | 48.7k | GreatWksTextInternal::Zone zone; |
532 | 48.7k | if (readZone(zone)) { |
533 | 4.00k | sendZone(zone, listener); |
534 | 4.00k | return true; |
535 | 4.00k | } |
536 | | |
537 | 44.7k | return sendSimpleTextbox(entry, listener); |
538 | 48.7k | } |
539 | | |
540 | | //////////////////////////////////////////////////////////// |
541 | | // Intermediate level |
542 | | //////////////////////////////////////////////////////////// |
543 | | bool GreatWksText::createZones(int expectedHF) |
544 | 20.9k | { |
545 | 20.9k | MWAWInputStreamPtr &input= m_parserState->m_input; |
546 | 20.9k | libmwaw::DebugFile &ascFile = m_parserState->m_asciiFile; |
547 | 20.9k | libmwaw::DebugStream f; |
548 | | |
549 | 20.9k | long pos = input->tell(); |
550 | 20.9k | f << "Entries(TZoneHeader):"; |
551 | 20.9k | auto val=static_cast<int>(input->readULong(2)); |
552 | 20.9k | if (val) |
553 | 15.6k | f << "numPages=" << val << ","; |
554 | 20.9k | val=static_cast<int>(input->readULong(2)); |
555 | 20.9k | if (val) // related to number of header/footer? |
556 | 11.9k | f << "f0=" << val << ","; |
557 | 20.9k | f << "height[total]=" << input->readLong(4) << ","; // checkme |
558 | 20.9k | ascFile.addDelimiter(input->tell(),'|'); |
559 | 20.9k | ascFile.addPos(pos); |
560 | 20.9k | ascFile.addNote(f.str().c_str()); |
561 | | |
562 | 20.9k | pos += 68; |
563 | 20.9k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
564 | | |
565 | 20.9k | if (!readFontNames()) { |
566 | 15.8k | MWAW_DEBUG_MSG(("GreatWksText::createZones: can not find the font names\n")); |
567 | 15.8k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
568 | 15.8k | } |
569 | | |
570 | 20.9k | bool findMainZone=false; |
571 | 20.9k | int nAuxi=0; |
572 | 58.4k | while (!input->isEnd()) { |
573 | 57.7k | pos=input->tell(); |
574 | 57.7k | GreatWksTextInternal::Zone zone; |
575 | 57.7k | if (!readZone(zone)) { |
576 | 47.0k | input->seek(pos,librevenge::RVNG_SEEK_SET); |
577 | 47.0k | if (findMainZone) |
578 | 5.02k | break; |
579 | | |
580 | 42.0k | if (!findNextZone() || !readZone(zone)) { |
581 | 15.2k | input->seek(pos,librevenge::RVNG_SEEK_SET); |
582 | 15.2k | break; |
583 | 15.2k | } |
584 | 42.0k | } |
585 | 37.4k | m_state->m_zonesList.push_back(zone); |
586 | 37.4k | if (zone.isMain()) |
587 | 5.06k | findMainZone=true; |
588 | 32.3k | else |
589 | 32.3k | nAuxi++; |
590 | 37.4k | } |
591 | 20.9k | if (nAuxi!=expectedHF) { |
592 | 5.37k | MWAW_DEBUG_MSG(("GreatWksText::createZones: unexpected HF zones: %d/%d\n", nAuxi, expectedHF)); |
593 | 5.37k | } |
594 | 20.9k | return findMainZone; |
595 | 20.9k | } |
596 | | |
597 | | bool GreatWksText::findNextZone() |
598 | 42.0k | { |
599 | 42.0k | MWAWInputStreamPtr &input= m_parserState->m_input; |
600 | | |
601 | 42.0k | long searchPos=input->tell(), pos=searchPos; |
602 | 42.0k | int const headerSize=24+22+184; |
603 | 42.0k | if (!input->checkPosition(pos+headerSize)) |
604 | 2.47k | return false; |
605 | | |
606 | | // first look for ruler |
607 | 39.5k | input->seek(pos+headerSize, librevenge::RVNG_SEEK_SET); |
608 | 38.6M | while (true) { |
609 | 38.6M | if (input->isEnd()) |
610 | 9.30k | return false; |
611 | 38.6M | pos = input->tell(); |
612 | 38.6M | unsigned long val=input->readULong(4); |
613 | 38.6M | if (val==0x20FFFF) |
614 | 26.7k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
615 | 38.6M | else if (val==0x20FFFFFF) |
616 | 28.8k | input->seek(pos-1, librevenge::RVNG_SEEK_SET); |
617 | 38.6M | else if (val==0xFFFFFFFF) |
618 | 787k | input->seek(pos-2, librevenge::RVNG_SEEK_SET); |
619 | 37.8M | else if (val==0xFFFFFF2E) |
620 | 22.3k | input->seek(pos-3, librevenge::RVNG_SEEK_SET); |
621 | 37.7M | else |
622 | 37.7M | continue; |
623 | 865k | if (input->readULong(4)!=0x20FFFF || input->readULong(4)!=0xFFFF2E00) { |
624 | 835k | input->seek(pos+4, librevenge::RVNG_SEEK_SET); |
625 | 835k | continue; |
626 | 835k | } |
627 | | // ok a empty tabs stop |
628 | 128k | while (!input->isEnd()) { |
629 | 128k | pos = input->tell(); |
630 | 128k | if (input->readULong(4)!=0x20FFFF || input->readULong(4)!=0xFFFF2E00) { |
631 | 30.0k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
632 | 30.0k | break; |
633 | 30.0k | } |
634 | 128k | } |
635 | 30.2k | break; |
636 | 865k | } |
637 | | |
638 | 30.2k | pos=input->tell(); |
639 | 30.2k | int nFonts=0; |
640 | 30.2k | GreatWksTextInternal::Zone zone; |
641 | 1.17M | while (true) { |
642 | 1.17M | long hSize=headerSize+22*nFonts++; |
643 | 1.17M | if (pos-hSize < searchPos) |
644 | 3.46k | break; |
645 | 1.17M | input->seek(pos-hSize, librevenge::RVNG_SEEK_SET); |
646 | 1.17M | if (input->readLong(4)) |
647 | 910k | continue; |
648 | 262k | auto val=static_cast<int>(input->readULong(2)); |
649 | 262k | if (val & 0xFEFE) |
650 | 43.4k | continue; |
651 | 219k | input->seek(2,librevenge::RVNG_SEEK_CUR); |
652 | 219k | if (input->readLong(2)!=nFonts) |
653 | 187k | continue; |
654 | 31.7k | input->seek(pos-hSize, librevenge::RVNG_SEEK_SET); |
655 | 31.7k | if (readZone(zone)) { |
656 | 26.8k | input->seek(pos-hSize, librevenge::RVNG_SEEK_SET); |
657 | 26.8k | return true; |
658 | 26.8k | } |
659 | 31.7k | } |
660 | | |
661 | 3.46k | MWAW_DEBUG_MSG(("GreatWksText::findNextZone: can not find begin of zone for pos=%lx\n", static_cast<long unsigned int>(pos))); |
662 | 3.46k | input->seek(searchPos, librevenge::RVNG_SEEK_SET); |
663 | 3.46k | return false; |
664 | 30.2k | } |
665 | | |
666 | | bool GreatWksText::readZone(GreatWksTextInternal::Zone &zone) |
667 | 165k | { |
668 | 165k | zone=GreatWksTextInternal::Zone(); |
669 | 165k | MWAWInputStreamPtr &input= m_parserState->m_input; |
670 | 165k | long pos=input->tell(); |
671 | 165k | long endPos=pos+24; |
672 | 165k | if (!input->checkPosition(endPos)) |
673 | 868 | return false; |
674 | | |
675 | 164k | libmwaw::DebugFile &ascFile = m_parserState->m_asciiFile; |
676 | 164k | libmwaw::DebugStream f; |
677 | 164k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
678 | 164k | if (input->readLong(4)) { |
679 | 67.1k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
680 | 67.1k | return false; |
681 | 67.1k | } |
682 | 286k | for (int i=0; i < 2; ++i) { |
683 | 193k | auto val=static_cast<int>(input->readLong(1)); |
684 | 193k | if (val==0) continue; |
685 | 49.1k | if (val!=1) |
686 | 3.83k | return false; |
687 | 45.3k | if (i==0) |
688 | 5.30k | f << "smartquote,"; |
689 | 40.0k | else |
690 | 40.0k | f << "hidepict,"; |
691 | 45.3k | } |
692 | 93.6k | zone.m_type=static_cast<int>(input->readLong(1)); |
693 | 93.6k | if (input->readLong(1)) { // simple|complex field |
694 | 7.57k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
695 | 7.57k | return false; |
696 | 7.57k | } |
697 | 86.0k | zone.m_numFonts=static_cast<int>(input->readULong(2)); |
698 | 86.0k | zone.m_numRulers=static_cast<int>(input->readULong(2)); |
699 | 86.0k | zone.m_numCharPLC=static_cast<int>(input->readULong(2)); |
700 | 86.0k | zone.m_numTokens=static_cast<int>(input->readULong(2)); |
701 | 86.0k | zone.m_numLines=static_cast<int>(input->readULong(2)); |
702 | 86.0k | zone.m_numFrames=static_cast<int>(input->readULong(2)); |
703 | 86.0k | zone.m_numChar=long(input->readULong(4)); |
704 | 86.0k | if (!zone.ok() || !input->checkPosition(endPos+zone.size())) { |
705 | 17.4k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
706 | 17.4k | return false; |
707 | 17.4k | } |
708 | 68.5k | zone.m_extra=f.str(); |
709 | 68.5k | f.str(""); |
710 | 68.5k | f << "Entries(HeaderText):" << zone; |
711 | 68.5k | if (input->tell()!=endPos) { |
712 | 0 | ascFile.addDelimiter(input->tell(),'|'); |
713 | 0 | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
714 | 0 | } |
715 | 68.5k | ascFile.addPos(pos); |
716 | 68.5k | ascFile.addNote(f.str().c_str()); |
717 | | |
718 | 2.95M | for (int i=0; i<zone.m_numFonts; ++i) { |
719 | 2.89M | pos = input->tell(); |
720 | 2.89M | f.str(""); |
721 | 2.89M | f << "Entries(FontDef)-F" << i << ":"; |
722 | | |
723 | 2.89M | MWAWFont font; |
724 | 2.89M | if (!readFont(font)) { |
725 | 0 | f << "###"; |
726 | 0 | font = MWAWFont(); |
727 | 0 | input->seek(pos+22, librevenge::RVNG_SEEK_SET); |
728 | 0 | } |
729 | 2.89M | zone.m_fontList.push_back(font); |
730 | 2.89M | f << font.getDebugString(m_parserState->m_fontConverter) << ","; |
731 | 2.89M | ascFile.addPos(pos); |
732 | 2.89M | ascFile.addNote(f.str().c_str()); |
733 | 2.89M | } |
734 | 68.5k | MWAWParagraph para; |
735 | 900k | for (int i=0; i<zone.m_numRulers; ++i) { |
736 | 832k | pos = input->tell(); |
737 | 832k | f.str(""); |
738 | 832k | f << "Entries(RulerDef)-R" << i << ":"; |
739 | 832k | if (!readRuler(para)) { |
740 | 0 | f << "###"; |
741 | 0 | para = MWAWParagraph(); |
742 | 0 | input->seek(pos+192, librevenge::RVNG_SEEK_SET); |
743 | 0 | } |
744 | 832k | zone.m_rulerList.push_back(para); |
745 | 832k | f << para; |
746 | 832k | ascFile.addPos(pos); |
747 | 832k | ascFile.addNote(f.str().c_str()); |
748 | 832k | } |
749 | | |
750 | 68.5k | pos=input->tell(); |
751 | 68.5k | f.str(""); |
752 | 68.5k | f << "Entries(CharPLC):"; |
753 | 68.5k | GreatWksTextInternal::PLC plc; |
754 | 68.5k | plc.m_type = GreatWksTextInternal::P_Font; |
755 | 68.5k | long textPos = 0; |
756 | 20.3M | for (int i=0; i < zone.m_numCharPLC; ++i) { |
757 | 20.2M | plc.m_id=static_cast<int>(input->readULong(2)); |
758 | 20.2M | zone.m_posPLCMap.insert |
759 | 20.2M | (std::multimap<long, GreatWksTextInternal::PLC>::value_type(textPos, plc)); |
760 | 20.2M | f << "F" << plc.m_id << ":" << std::hex << textPos << std::dec << ","; |
761 | 20.2M | textPos+= static_cast<int>(input->readULong(4)); |
762 | 20.2M | } |
763 | 68.5k | ascFile.addPos(pos); |
764 | 68.5k | ascFile.addNote(f.str().c_str()); |
765 | | // the token |
766 | 68.5k | plc.m_type = GreatWksTextInternal::P_Token; |
767 | 68.5k | textPos = 0; |
768 | 2.53M | for (int i=0; i < zone.m_numTokens; ++i) { |
769 | 2.46M | pos = input->tell(); |
770 | 2.46M | f.str(""); |
771 | 2.46M | plc.m_id=i; |
772 | 2.46M | f << "Entries(Token)-Tn" << i << ":"; |
773 | 2.46M | GreatWksTextInternal::Token tkn; |
774 | 2.46M | long numC; |
775 | 2.46M | if (!readToken(tkn,numC)) { |
776 | 0 | f << "###"; |
777 | 0 | tkn = GreatWksTextInternal::Token(); |
778 | 0 | input->seek(pos+2, librevenge::RVNG_SEEK_SET); |
779 | 0 | numC=input->readLong(2); |
780 | 0 | } |
781 | 2.46M | zone.m_posPLCMap.insert |
782 | 2.46M | (std::multimap<long, GreatWksTextInternal::PLC>::value_type(textPos, plc)); |
783 | 2.46M | zone.m_tokenList.push_back(tkn); |
784 | 2.46M | f << tkn << ",pos=" << std::hex << textPos << std::dec; |
785 | 2.46M | textPos+= numC; |
786 | 2.46M | input->seek(pos+18, librevenge::RVNG_SEEK_SET); |
787 | 2.46M | ascFile.addPos(pos); |
788 | 2.46M | ascFile.addNote(f.str().c_str()); |
789 | 2.46M | } |
790 | 68.5k | if (!readZonePositions(zone)) |
791 | 0 | return false; |
792 | | // fill the text entry |
793 | 68.5k | pos=input->tell(); |
794 | 68.5k | zone.m_textEntry.setBegin(pos); |
795 | 68.5k | zone.m_textEntry.setLength(zone.m_numChar); |
796 | 68.5k | ascFile.addPos(pos); |
797 | 68.5k | ascFile.addNote("_"); |
798 | 68.5k | pos += zone.m_numChar; |
799 | 68.5k | ascFile.addPos(pos); |
800 | 68.5k | ascFile.addNote("_"); |
801 | | |
802 | 1.88M | for (auto &tkn : zone.m_tokenList) { |
803 | 1.88M | if (tkn.m_type != 4) |
804 | 1.86M | continue; |
805 | 17.4k | if (tkn.m_dataSize <= 0 || !input->checkPosition(pos+tkn.m_dataSize)) { |
806 | 13.7k | MWAW_DEBUG_MSG(("GreatWksText::readZone: can not determine the picture size\n")); |
807 | 13.7k | break; |
808 | 13.7k | } |
809 | 3.67k | tkn.m_pictEntry.setBegin(pos); |
810 | 3.67k | tkn.m_pictEntry.setLength(tkn.m_dataSize); |
811 | 3.67k | pos+=tkn.m_dataSize; |
812 | 3.67k | } |
813 | 68.5k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
814 | 68.5k | return true; |
815 | 68.5k | } |
816 | | |
817 | | bool GreatWksText::readZonePositions(GreatWksTextInternal::Zone &zone) |
818 | 68.5k | { |
819 | 68.5k | MWAWInputStreamPtr &input= m_parserState->m_input; |
820 | 68.5k | libmwaw::DebugFile &ascFile = m_parserState->m_asciiFile; |
821 | 68.5k | libmwaw::DebugStream f; |
822 | | |
823 | | // the line |
824 | 68.5k | GreatWksTextInternal::PLC plc; |
825 | 68.5k | plc.m_type = GreatWksTextInternal::P_Ruler; |
826 | 68.5k | long textPos = 0; |
827 | 68.5k | std::vector<long> linesPos; |
828 | 68.5k | linesPos.push_back(0); |
829 | 1.35M | for (int i=0; i < zone.m_numLines; ++i) { |
830 | 1.29M | long pos=input->tell(); |
831 | 1.29M | f.str(""); |
832 | 1.29M | plc.m_id=static_cast<int>(input->readULong(2)); |
833 | 1.29M | auto numC = long(input->readULong(4)); |
834 | 1.29M | f << "y=" << double(input->readLong(4))/65536.; |
835 | 1.29M | f << "->" << double(input->readLong(4))/65536.; |
836 | 1.29M | plc.m_extra=f.str(); |
837 | 1.29M | zone.m_posPLCMap.insert |
838 | 1.29M | (std::multimap<long, GreatWksTextInternal::PLC>::value_type(textPos, plc)); |
839 | 1.29M | f.str(""); |
840 | 1.29M | f << "Entries(Line)-L" << i << ":" << plc << ":" |
841 | 1.29M | << std::hex << textPos << std::dec; |
842 | 1.29M | textPos+=numC; |
843 | 1.29M | linesPos.push_back(textPos); |
844 | 1.29M | input->seek(pos+14, librevenge::RVNG_SEEK_SET); |
845 | 1.29M | ascFile.addPos(pos); |
846 | 1.29M | ascFile.addNote(f.str().c_str()); |
847 | 1.29M | } |
848 | | // the page dimension |
849 | 68.5k | plc.m_type = GreatWksTextInternal::P_Page; |
850 | 875k | for (int i=0; i < zone.m_numFrames; ++i) { |
851 | 807k | GreatWksTextInternal::Frame frame; |
852 | 807k | long pos=input->tell(); |
853 | 807k | plc.m_id=i; |
854 | 807k | f.str(""); |
855 | 807k | float dim[4]; |
856 | 3.22M | for (auto &d : dim) d=float(input->readLong(4))/65536.f; |
857 | 807k | frame.m_pos=MWAWBox2f(MWAWVec2f(dim[1],dim[0]),MWAWVec2f(dim[3],dim[2])); |
858 | 807k | auto val=static_cast<int>(input->readLong(2)); // always 0 |
859 | 807k | if (val) f << "#unkn=" << val << ","; |
860 | 807k | frame.m_page=static_cast<int>(input->readLong(2)); |
861 | 807k | auto line=static_cast<int>(input->readLong(2)); |
862 | 807k | plc.m_extra=f.str(); |
863 | 807k | if (line >= 0 && line < int(linesPos.size())) { |
864 | 314k | textPos=linesPos[size_t(line)]; |
865 | 314k | zone.m_posPLCMap.insert |
866 | 314k | (std::multimap<long, GreatWksTextInternal::PLC>::value_type(textPos, plc)); |
867 | 314k | if (textPos) |
868 | 51.5k | f << "pos=" << std::hex << textPos << std::dec; |
869 | 314k | } |
870 | 492k | else { |
871 | 492k | MWAW_DEBUG_MSG(("GreatWksText::readZone: can not find begin pos for page %d\n",line)); |
872 | 492k | f << "##pos[line]=" << line << ","; |
873 | 492k | } |
874 | 807k | frame.m_extra=f.str(); |
875 | 807k | zone.m_frameList.push_back(frame); |
876 | 807k | f.str(""); |
877 | 807k | f << "Entries(TFrames)-" << i << ":" << frame; |
878 | 807k | input->seek(pos+22, librevenge::RVNG_SEEK_SET); |
879 | 807k | ascFile.addPos(pos); |
880 | 807k | ascFile.addNote(f.str().c_str()); |
881 | 807k | } |
882 | 68.5k | return true; |
883 | 68.5k | } |
884 | | |
885 | | ////////////////////////////////////////////// |
886 | | // Fonts |
887 | | ////////////////////////////////////////////// |
888 | | bool GreatWksText::readFontNames() |
889 | 75.4k | { |
890 | 75.4k | MWAWInputStreamPtr &input= m_parserState->m_input; |
891 | 75.4k | long pos=input->tell(); |
892 | 75.4k | libmwaw::DebugFile &ascFile = m_parserState->m_asciiFile; |
893 | 75.4k | libmwaw::DebugStream f; |
894 | 75.4k | f << "Entries(FontNames):"; |
895 | 75.4k | auto sz= long(input->readULong(4)); |
896 | 75.4k | long endPos = input->tell()+sz; |
897 | 75.4k | if (sz < 2 || !input->checkPosition(endPos)) { |
898 | 45.7k | MWAW_DEBUG_MSG(("GreatWksText::readFontNames: can not read field size\n")); |
899 | 45.7k | f << "###"; |
900 | 45.7k | ascFile.addPos(pos); |
901 | 45.7k | ascFile.addNote(f.str().c_str()); |
902 | 45.7k | return false; |
903 | 45.7k | } |
904 | 29.6k | auto N=static_cast<int>(input->readLong(2)); |
905 | 29.6k | f << "N=" << N << ","; |
906 | 29.6k | if (N*5+2 > sz) { |
907 | 1.67k | MWAW_DEBUG_MSG(("GreatWksText::readFontNames: can not read N\n")); |
908 | 1.67k | f << "###"; |
909 | 1.67k | ascFile.addPos(pos); |
910 | 1.67k | ascFile.addNote(f.str().c_str()); |
911 | 1.67k | return false; |
912 | 1.67k | } |
913 | 28.0k | ascFile.addPos(pos); |
914 | 28.0k | ascFile.addNote(f.str().c_str()); |
915 | 2.66M | for (int i=0; i < N; ++i) { |
916 | 2.64M | pos = input->tell(); |
917 | 2.64M | f.str(""); |
918 | 2.64M | f << "FontNames-" << i << ":"; |
919 | 2.64M | auto fId=static_cast<int>(input->readULong(2)); |
920 | 2.64M | f << "fId=" << fId << ","; |
921 | 2.64M | auto val=static_cast<int>(input->readLong(2)); // always 0 ? |
922 | 2.64M | if (val) |
923 | 1.11M | f << "unkn=" << val << ","; |
924 | 2.64M | auto fSz=static_cast<int>(input->readULong(1)); |
925 | 2.64M | if (pos+5+fSz>endPos) { |
926 | 7.14k | MWAW_DEBUG_MSG(("GreatWksText::readFontNames: can not read font %d\n", i)); |
927 | 7.14k | f << "###"; |
928 | 7.14k | ascFile.addPos(pos); |
929 | 7.14k | ascFile.addNote(f.str().c_str()); |
930 | 7.14k | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
931 | 7.14k | return i>0; |
932 | 7.14k | } |
933 | 2.63M | std::string name(""); |
934 | 53.0M | for (int c=0; c < fSz; ++c) |
935 | 50.3M | name+=char(input->readULong(1)); |
936 | 2.63M | if (!name.empty()) |
937 | 907k | m_state->m_fileIdFontIdMap[fId]=m_parserState->m_fontConverter->getId(name); |
938 | 2.63M | if ((fSz%2)==0) |
939 | 2.14M | input->seek(1, librevenge::RVNG_SEEK_CUR); |
940 | | |
941 | 2.63M | f << "\"" << name << "\","; |
942 | 2.63M | ascFile.addPos(pos); |
943 | 2.63M | ascFile.addNote(f.str().c_str()); |
944 | 2.63M | } |
945 | 20.8k | pos = input->tell(); |
946 | 20.8k | if (pos!=endPos) { |
947 | 11.3k | MWAW_DEBUG_MSG(("GreatWksText::readFontNames: find extra data\n")); |
948 | 11.3k | ascFile.addPos(pos); |
949 | 11.3k | ascFile.addNote("FontNames:###"); |
950 | 11.3k | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
951 | 11.3k | } |
952 | 20.8k | return true; |
953 | 28.0k | } |
954 | | |
955 | | bool GreatWksText::readFont(MWAWFont &font) |
956 | 2.89M | { |
957 | 2.89M | font=MWAWFont(); |
958 | 2.89M | MWAWInputStreamPtr &input= m_parserState->m_input; |
959 | 2.89M | long pos=input->tell(); |
960 | 2.89M | long endPos=pos+22; |
961 | 2.89M | if (!input->checkPosition(endPos)) |
962 | 0 | return false; |
963 | | |
964 | 2.89M | libmwaw::DebugStream f; |
965 | 2.89M | input->seek(pos, librevenge::RVNG_SEEK_SET); |
966 | 2.89M | auto val=static_cast<int>(input->readLong(2)); // small number between 0 and 5 |
967 | 2.89M | if (val==0) f << "unused,"; |
968 | 1.95M | else if (val!=1) f << "nbUsed=" << val << ","; |
969 | | // some dim dim[0]>dim[1]: minH, maxH ? |
970 | 2.89M | int dim[2]; |
971 | 5.78M | for (auto &d : dim) d=static_cast<int>(input->readLong(2)); |
972 | 2.89M | f << "dim?=" << dim[1] << "x" << dim[0] << ","; |
973 | | |
974 | 8.67M | for (int i=0; i < 2; ++i) { // f0=0|4(with italic), f1=0 |
975 | 5.78M | val=static_cast<int>(input->readLong(2)); |
976 | 5.78M | if (val) f << "f" << i << "=" << val << ","; |
977 | 5.78M | } |
978 | 2.89M | font.setId(m_state->getFId(static_cast<int>(input->readULong(2)))); |
979 | 2.89M | auto flag =static_cast<int>(input->readULong(2)); |
980 | 2.89M | uint32_t flags=0; |
981 | 2.89M | if (flag&0x1) flags |= MWAWFont::boldBit; |
982 | 2.89M | if (flag&0x2) flags |= MWAWFont::italicBit; |
983 | 2.89M | if (flag&0x4) font.setUnderlineStyle(MWAWFont::Line::Simple); |
984 | 2.89M | if (flag&0x8) flags |= MWAWFont::embossBit; |
985 | 2.89M | if (flag&0x10) flags |= MWAWFont::shadowBit; |
986 | 2.89M | if (flag&0x20) font.setDeltaLetterSpacing(-1); |
987 | 2.89M | if (flag&0x40) font.setDeltaLetterSpacing(1); |
988 | 2.89M | if (flag&0x100) font.set(MWAWFont::Script::super100()); |
989 | 2.89M | if (flag&0x200) font.set(MWAWFont::Script::sub100()); |
990 | 2.89M | if (flag&0x800) font.setStrikeOutStyle(MWAWFont::Line::Simple); |
991 | 2.89M | if (flag&0x2000) { |
992 | 792k | font.setUnderlineStyle(MWAWFont::Line::Simple); |
993 | 792k | font.setUnderlineType(MWAWFont::Line::Double); |
994 | 792k | } |
995 | 2.89M | flag &=0xD480; |
996 | 2.89M | if (flag) f << "#fl=" << std::hex << flag << std::dec << ","; |
997 | 2.89M | font.setFlags(flags); |
998 | 2.89M | font.setSize(float(input->readULong(2))); |
999 | 2.89M | unsigned char color[3]; |
1000 | 8.67M | for (auto &c : color) c = static_cast<unsigned char>(input->readULong(2)>>8); |
1001 | 2.89M | font.setColor(MWAWColor(color[0],color[1],color[2])); |
1002 | 2.89M | font.m_extra=f.str(); |
1003 | | |
1004 | 2.89M | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
1005 | 2.89M | return true; |
1006 | 2.89M | } |
1007 | | ////////////////////////////////////////////// |
1008 | | // Ruler |
1009 | | ////////////////////////////////////////////// |
1010 | | bool GreatWksText::readRuler(MWAWParagraph ¶) |
1011 | 832k | { |
1012 | 832k | para = MWAWParagraph(); |
1013 | 832k | MWAWInputStreamPtr &input= m_parserState->m_input; |
1014 | 832k | long pos=input->tell(); |
1015 | 832k | long endPos=pos+192; |
1016 | 832k | if (!input->checkPosition(endPos)) |
1017 | 0 | return false; |
1018 | | |
1019 | 832k | libmwaw::DebugStream f; |
1020 | 832k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1021 | 832k | auto val=static_cast<int>(input->readLong(2)); |
1022 | 832k | if (val==0) f << "unused,"; |
1023 | 598k | else if (val!=1) f << "nbUsed=" << val << ","; |
1024 | 832k | val=static_cast<int>(input->readLong(2)); |
1025 | 832k | switch (val) { |
1026 | 292k | case 0: |
1027 | 292k | break; |
1028 | 69.6k | case 1: |
1029 | 69.6k | para.m_justify = MWAWParagraph::JustificationCenter; |
1030 | 69.6k | break; |
1031 | 6.39k | case 2: |
1032 | 6.39k | para.m_justify = MWAWParagraph::JustificationRight ; |
1033 | 6.39k | break; |
1034 | 5.78k | case 3: |
1035 | 5.78k | para.m_justify = MWAWParagraph::JustificationFull; |
1036 | 5.78k | break; |
1037 | 457k | default: |
1038 | 457k | f << "#align" << val << ","; |
1039 | 457k | break; |
1040 | 832k | } |
1041 | 832k | para.m_marginsUnit=librevenge::RVNG_POINT; |
1042 | 832k | for (auto &margin : para.m_margins) |
1043 | 2.49M | margin = double(input->readLong(4))/65536.; |
1044 | 832k | para.m_margins[0]=*para.m_margins[0]-*para.m_margins[1]; |
1045 | 832k | double spacing[3]; |
1046 | 832k | for (double &i : spacing) |
1047 | 2.49M | i = double(input->readLong(4))/65536.; |
1048 | 832k | int unit[3]; |
1049 | 2.49M | for (auto &u : unit) u = static_cast<int>(input->readLong(1)); |
1050 | 832k | switch (unit[0]) { |
1051 | 29.2k | case 1: |
1052 | 44.4k | case 2: |
1053 | 51.5k | case 3: |
1054 | 64.6k | case 4: |
1055 | 73.9k | case 5: |
1056 | 73.9k | para.setInterline(spacing[0], librevenge::RVNG_POINT); |
1057 | 73.9k | break; |
1058 | 15.2k | case 6: |
1059 | 15.2k | para.setInterline(spacing[0], librevenge::RVNG_PERCENT); |
1060 | 15.2k | break; |
1061 | 743k | default: |
1062 | 743k | f << "#interline=" << spacing[0] << "[unit=" << unit[0] << "],"; |
1063 | 832k | } |
1064 | 2.49M | for (int w=1; w < 3; ++w) { |
1065 | 1.66M | if (unit[w]==6) |
1066 | 10.9k | para.m_spacings[w]=spacing[w]*12./72.; |
1067 | 1.65M | else if (unit[w]>0 && unit[w]<6) |
1068 | 215k | para.m_spacings[w]=spacing[w]/72.; |
1069 | 1.43M | else |
1070 | 1.43M | f << "#spac" << w << "=" << spacing[w] << "[unit=" << unit[w] << "],"; |
1071 | 1.66M | } |
1072 | 832k | val = static_cast<int>(input->readLong(1)); |
1073 | 832k | if (val) f << "#f0=" << val << ","; |
1074 | | |
1075 | 17.4M | for (int i=0; i < 20; ++i) { |
1076 | 16.6M | MWAWTabStop tab; |
1077 | 16.6M | val = static_cast<int>(input->readLong(1)); |
1078 | 16.6M | switch (val) { |
1079 | 8.09M | case 0: // left |
1080 | 8.09M | break; |
1081 | 793k | case 1: |
1082 | 793k | tab.m_alignment = MWAWTabStop::CENTER; |
1083 | 793k | break; |
1084 | 305k | case 2: |
1085 | 305k | tab.m_alignment = MWAWTabStop::RIGHT; |
1086 | 305k | break; |
1087 | 140k | case 3: |
1088 | 140k | tab.m_alignment = MWAWTabStop::DECIMAL; |
1089 | 140k | break; |
1090 | 7.31M | default: |
1091 | 7.31M | f << "#tab" << i << "[align]=" << val << ","; |
1092 | 7.31M | break; |
1093 | 16.6M | } |
1094 | 16.6M | auto leaderChar = char(input->readULong(1)); |
1095 | 16.6M | if (leaderChar) { |
1096 | 9.18M | int unicode= m_parserState->m_fontConverter->unicode(3, static_cast<unsigned char>(leaderChar)); |
1097 | 9.18M | if (unicode==-1) |
1098 | 3.17M | tab.m_leaderCharacter = uint16_t(leaderChar); |
1099 | 6.01M | else |
1100 | 6.01M | tab.m_leaderCharacter = uint16_t(unicode); |
1101 | 9.18M | } |
1102 | 16.6M | long tPos=input->readLong(4); |
1103 | 16.6M | if (tPos==-1) { |
1104 | 671k | input->seek(2, librevenge::RVNG_SEEK_CUR); |
1105 | 671k | continue; |
1106 | 671k | } |
1107 | 15.9M | tab.m_position=double(tPos)/72./65536.; |
1108 | 15.9M | auto decimalChar = char(input->readULong(1)); |
1109 | 15.9M | if (decimalChar) { |
1110 | 8.47M | int unicode= m_parserState->m_fontConverter->unicode(3, static_cast<unsigned char>(decimalChar)); |
1111 | 8.47M | if (unicode==-1) |
1112 | 3.40M | tab.m_decimalCharacter = uint16_t(decimalChar); |
1113 | 5.06M | else |
1114 | 5.06M | tab.m_decimalCharacter = uint16_t(unicode); |
1115 | 8.47M | } |
1116 | 15.9M | val = static_cast<int>(input->readLong(1)); |
1117 | 15.9M | if (val) f << "#tab" << i << "[f0=" << val << ","; |
1118 | 15.9M | para.m_tabs->push_back(tab); |
1119 | 15.9M | } |
1120 | 832k | para.m_extra=f.str(); |
1121 | | |
1122 | 832k | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
1123 | 832k | return true; |
1124 | 832k | } |
1125 | | |
1126 | | ////////////////////////////////////////////// |
1127 | | // Token |
1128 | | ////////////////////////////////////////////// |
1129 | | bool GreatWksText::readToken(GreatWksTextInternal::Token &token, long &nChar) |
1130 | 2.46M | { |
1131 | 2.46M | token = GreatWksTextInternal::Token(); |
1132 | 2.46M | MWAWInputStreamPtr &input= m_parserState->m_input; |
1133 | 2.46M | long pos=input->tell(); |
1134 | 2.46M | long endPos=pos+18; |
1135 | 2.46M | if (!input->checkPosition(endPos)) |
1136 | 0 | return false; |
1137 | | |
1138 | 2.46M | libmwaw::DebugStream f; |
1139 | 2.46M | token.m_type=static_cast<int>(input->readULong(1)); |
1140 | 2.46M | token.m_format=static_cast<int>(input->readULong(1)); |
1141 | 2.46M | nChar=input->readLong(4); |
1142 | 2.46M | if (token.m_type==0x15||token.m_type==0x16) |
1143 | 61.9k | token.m_date=static_cast<uint32_t>(input->readULong(4)); |
1144 | 2.40M | else if (token.m_type==4) { |
1145 | 37.5k | token.m_dataSize = input->readLong(4); |
1146 | 37.5k | float dim[2]; |
1147 | 75.0k | for (auto &d : dim) d = float(input->readLong(4))/65536.f; |
1148 | 37.5k | token.m_dim=MWAWVec2f(dim[0],dim[1]); // checkme |
1149 | 37.5k | } |
1150 | 2.46M | int nUnread=int(endPos-input->tell())/2; |
1151 | 16.9M | for (int i=0; i < nUnread; i++) { |
1152 | 14.4M | auto val=static_cast<int>(input->readLong(2)); |
1153 | 14.4M | if (val) f << "f" << i << "=" << val << ","; |
1154 | 14.4M | } |
1155 | 2.46M | token.m_extra=f.str(); |
1156 | | |
1157 | 2.46M | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
1158 | 2.46M | return true; |
1159 | 2.46M | } |
1160 | | |
1161 | | ////////////////////////////////////////////// |
1162 | | // send data |
1163 | | ////////////////////////////////////////////// |
1164 | | bool GreatWksText::sendMainText() |
1165 | 11.1k | { |
1166 | 11.1k | for (auto const &zone : m_state->m_zonesList) { |
1167 | 6.45k | if (!zone.isMain()) |
1168 | 1.39k | continue; |
1169 | 5.05k | return sendZone(zone); |
1170 | 6.45k | } |
1171 | 6.10k | return false; |
1172 | 11.1k | } |
1173 | | |
1174 | | bool GreatWksText::sendHF(int id) |
1175 | 1.30k | { |
1176 | 1.30k | for (auto const &zone : m_state->m_zonesList) { |
1177 | 1.30k | if (zone.isMain()) |
1178 | 0 | continue; |
1179 | 1.30k | if (id--==0) |
1180 | 1.30k | return sendZone(zone); |
1181 | 1.30k | } |
1182 | 0 | MWAW_DEBUG_MSG(("GreatWksText::sendHF: can not find a header/footer\n")); |
1183 | 0 | return false; |
1184 | 1.30k | } |
1185 | | |
1186 | | void GreatWksText::flushExtra() |
1187 | 0 | { |
1188 | 0 | MWAWListenerPtr listener=m_parserState->getMainListener(); |
1189 | 0 | if (!listener) { |
1190 | 0 | MWAW_DEBUG_MSG(("GreatWksText::flushExtra: can not find a listener\n")); |
1191 | 0 | return; |
1192 | 0 | } |
1193 | 0 | for (auto const &zone : m_state->m_zonesList) { |
1194 | 0 | if (zone.m_parsed) |
1195 | 0 | continue; |
1196 | 0 | sendZone(zone); |
1197 | 0 | } |
1198 | 0 | } |
1199 | | |
1200 | | bool GreatWksText::sendSimpleTextbox(MWAWEntry const &entry, MWAWListenerPtr listener) |
1201 | 44.7k | { |
1202 | 44.7k | if (!listener) |
1203 | 885 | listener=m_parserState->getMainListener(); |
1204 | 44.7k | if (!listener || !listener->canWriteText()) { |
1205 | 0 | MWAW_DEBUG_MSG(("GreatWksText::sendSimpleTextbox: can not find a listener\n")); |
1206 | 0 | return false; |
1207 | 0 | } |
1208 | 44.7k | if (entry.length()<51) { |
1209 | 3.94k | MWAW_DEBUG_MSG(("GreatWksText::sendSimpleTextbox: the entry seems to short\n")); |
1210 | 3.94k | return false; |
1211 | 3.94k | } |
1212 | 40.8k | MWAWInputStreamPtr &input= m_parserState->m_input; |
1213 | 40.8k | long pos=entry.begin(); |
1214 | 40.8k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1215 | | |
1216 | 40.8k | libmwaw::DebugFile &ascFile = m_parserState->m_asciiFile; |
1217 | 40.8k | libmwaw::DebugStream f; |
1218 | 40.8k | f << "Entries(Texbox):"; |
1219 | 40.8k | bool ok = input->readLong(4)==0; |
1220 | 56.0k | for (int i=0; ok && i < 2; ++i) { |
1221 | 16.2k | auto val=static_cast<int>(input->readLong(1)); |
1222 | 16.2k | if (val==0) continue; |
1223 | 2.26k | if (val!=1) { |
1224 | 992 | f << "#fl" << i << "=" << val << ","; |
1225 | 992 | ok = false; |
1226 | 992 | break; |
1227 | 992 | } |
1228 | 1.27k | if (i==0) |
1229 | 653 | f << "smartquote,"; |
1230 | 619 | else |
1231 | 619 | f << "hidepict,"; |
1232 | 1.27k | } |
1233 | 40.8k | auto type=static_cast<int>(input->readLong(1)); |
1234 | 40.8k | if (ok) { |
1235 | 7.34k | if (type<0 || type>5) { |
1236 | 816 | f << "#type=" << type << ","; |
1237 | 816 | ok = false; |
1238 | 816 | } |
1239 | 6.53k | else if (type==1) |
1240 | 688 | f << "textbox[draw],"; |
1241 | 5.84k | else if (type!=2) |
1242 | 5.57k | f << "type=" << type << ","; |
1243 | 7.34k | } |
1244 | 40.8k | if (ok) ok=input->readLong(1)==1; |
1245 | | |
1246 | 40.8k | if (!ok) { |
1247 | 38.8k | MWAW_DEBUG_MSG(("GreatWksText::sendSimpleTextbox: the header seems bad\n")); |
1248 | 38.8k | f << "###"; |
1249 | 38.8k | ascFile.addPos(pos); |
1250 | 38.8k | ascFile.addNote(f.str().c_str()); |
1251 | 38.8k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1252 | 38.8k | return false; |
1253 | 38.8k | } |
1254 | 1.92k | MWAWFont font; |
1255 | 1.92k | font.setId(m_state->getFId(static_cast<int>(input->readULong(2)))); |
1256 | 1.92k | auto flag =static_cast<int>(input->readULong(2)); |
1257 | 1.92k | uint32_t flags=0; |
1258 | 1.92k | if (flag&0x1) flags |= MWAWFont::boldBit; |
1259 | 1.92k | if (flag&0x2) flags |= MWAWFont::italicBit; |
1260 | 1.92k | if (flag&0x4) font.setUnderlineStyle(MWAWFont::Line::Simple); |
1261 | 1.92k | if (flag&0x8) flags |= MWAWFont::embossBit; |
1262 | 1.92k | if (flag&0x10) flags |= MWAWFont::shadowBit; |
1263 | 1.92k | if (flag&0x20) font.setDeltaLetterSpacing(-1); |
1264 | 1.92k | if (flag&0x40) font.setDeltaLetterSpacing(1); |
1265 | 1.92k | if (flag&0x100) font.set(MWAWFont::Script::super100()); |
1266 | 1.92k | if (flag&0x200) font.set(MWAWFont::Script::sub100()); |
1267 | 1.92k | if (flag&0x800) font.setStrikeOutStyle(MWAWFont::Line::Simple); |
1268 | 1.92k | if (flag&0x2000) { |
1269 | 641 | font.setUnderlineStyle(MWAWFont::Line::Simple); |
1270 | 641 | font.setUnderlineType(MWAWFont::Line::Double); |
1271 | 641 | } |
1272 | 1.92k | flag &=0xD480; |
1273 | 1.92k | if (flag) f << "font[#fl]=" << std::hex << flag << std::dec << ","; |
1274 | 1.92k | font.setFlags(flags); |
1275 | 1.92k | font.setSize(float(input->readULong(2))); |
1276 | 1.92k | unsigned char color[3]; |
1277 | 5.76k | for (auto &c : color) c = static_cast<unsigned char>(input->readULong(2)>>8); |
1278 | 1.92k | font.setColor(MWAWColor(color[0],color[1],color[2])); |
1279 | 1.92k | f << "font=[" << font.getDebugString(m_parserState->m_fontConverter) << "],"; |
1280 | 1.92k | listener->setFont(font); |
1281 | | |
1282 | 1.92k | int val; |
1283 | 1.92k | f << "unkn=[" << std::hex; |
1284 | 13.4k | for (int i=0; i<6; i++) { // junk ? |
1285 | 11.5k | val=static_cast<int>(input->readULong(2)); |
1286 | 11.5k | if (val) |
1287 | 6.59k | f << val << ","; |
1288 | 4.92k | else |
1289 | 4.92k | f << "_,"; |
1290 | 11.5k | } |
1291 | 1.92k | f << std::dec << "],"; |
1292 | 1.92k | MWAWParagraph para; |
1293 | 1.92k | val=static_cast<int>(input->readLong(2)); |
1294 | 1.92k | switch (val) { |
1295 | 978 | case 0: |
1296 | 978 | break; |
1297 | 19 | case 1: |
1298 | 19 | para.m_justify = MWAWParagraph::JustificationCenter; |
1299 | 19 | break; |
1300 | 25 | case 2: |
1301 | 25 | para.m_justify = MWAWParagraph::JustificationRight ; |
1302 | 25 | break; |
1303 | 116 | case 3: |
1304 | 116 | para.m_justify = MWAWParagraph::JustificationFull; |
1305 | 116 | break; |
1306 | 782 | default: |
1307 | 782 | f << "#align" << val << ","; |
1308 | 782 | break; |
1309 | 1.92k | } |
1310 | 1.92k | f << para <<","; |
1311 | 1.92k | listener->setParagraph(para); |
1312 | 1.92k | double dim[4]; |
1313 | 7.68k | for (auto &d : dim) d=double(input->readLong(4))/65536.; |
1314 | 1.92k | f << "dim=" << dim[1] << "x" << dim[0] << "<->" << dim[3] << "x" << dim[2] << "," ; |
1315 | 1.92k | auto fSz=static_cast<int>(input->readULong(1)); |
1316 | 1.92k | if (50+fSz > entry.length()) { |
1317 | 78 | MWAW_DEBUG_MSG(("GreatWksText::sendSimpleTextbox: the text size seems too big\n")); |
1318 | 78 | f << "###"; |
1319 | 78 | ascFile.addPos(pos); |
1320 | 78 | ascFile.addNote(f.str().c_str()); |
1321 | 78 | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1322 | 78 | return false; |
1323 | 78 | } |
1324 | | |
1325 | 1.84k | ascFile.addPos(pos); |
1326 | 1.84k | ascFile.addNote(f.str().c_str()); |
1327 | | |
1328 | 1.84k | pos=input->tell(); |
1329 | 1.84k | f.str(""); |
1330 | 1.84k | f << "Entries(Text):"; |
1331 | 96.3k | for (int i=0; i < fSz; ++i) { |
1332 | 94.4k | auto c = char(input->readULong(1)); |
1333 | 94.4k | f << c; |
1334 | 94.4k | switch (c) { |
1335 | 3.91k | case 0x9: |
1336 | 3.91k | listener->insertTab(); |
1337 | 3.91k | break; |
1338 | 10.0k | case 0xd: |
1339 | 10.0k | listener->insertEOL(); |
1340 | 10.0k | break; |
1341 | 80.4k | default: |
1342 | 80.4k | listener->insertCharacter(static_cast<unsigned char>(c)); |
1343 | 80.4k | break; |
1344 | 94.4k | } |
1345 | 94.4k | } |
1346 | 1.84k | input->seek(entry.end(), librevenge::RVNG_SEEK_SET); |
1347 | 1.84k | ascFile.addPos(pos); |
1348 | 1.84k | ascFile.addNote(f.str().c_str()); |
1349 | 1.84k | return true; |
1350 | 1.84k | } |
1351 | | |
1352 | | bool GreatWksText::sendZone(GreatWksTextInternal::Zone const &zone, MWAWListenerPtr listener) |
1353 | 10.3k | { |
1354 | 10.3k | bool inLocalZone=false; |
1355 | 10.3k | if (listener) |
1356 | 2.82k | inLocalZone=true; |
1357 | 7.54k | else |
1358 | 7.54k | listener=m_parserState->getMainListener(); |
1359 | 10.3k | if (!listener || !listener->canWriteText()) { |
1360 | 0 | MWAW_DEBUG_MSG(("GreatWksText::sendZone: can not find a listener\n")); |
1361 | 0 | return false; |
1362 | 0 | } |
1363 | 10.3k | bool isMain = zone.isMain(); |
1364 | 10.3k | int actPage = 1, actCol = 0, numCol=1; |
1365 | 10.3k | if (isMain && !listener->canOpenSectionAddBreak()) { |
1366 | 11 | MWAW_DEBUG_MSG(("GreatWksText::sendZone: in a main zone, but can not open section\n")); |
1367 | 11 | isMain = false; |
1368 | 11 | } |
1369 | 10.3k | else if (isMain) { |
1370 | 5.05k | m_document.newPage(1); |
1371 | 5.05k | MWAWSection sec=m_document.getMainSection(); |
1372 | 5.05k | numCol = sec.numColumns(); |
1373 | 5.05k | if (numCol>1) { |
1374 | 3.75k | if (listener->isSectionOpened()) |
1375 | 0 | listener->closeSection(); |
1376 | 3.75k | listener->openSection(sec); |
1377 | 3.75k | } |
1378 | 5.05k | } |
1379 | 10.3k | if (!zone.m_textEntry.valid()) |
1380 | 651 | return true; |
1381 | 9.72k | MWAWInputStreamPtr &input= m_parserState->m_input; |
1382 | 9.72k | libmwaw::DebugFile &ascFile = m_parserState->m_asciiFile; |
1383 | 9.72k | libmwaw::DebugStream f; |
1384 | 9.72k | f << "Entries(Text):"; |
1385 | 9.72k | zone.m_parsed=true; |
1386 | 9.72k | long pos = zone.m_textEntry.begin(), endPos = zone.m_textEntry.end(); |
1387 | 9.72k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1388 | | |
1389 | 9.72k | long cPos=0; |
1390 | 6.89M | while (1) { |
1391 | 6.89M | long actPos = input->tell(); |
1392 | 6.89M | bool done = input->isEnd() || actPos==endPos; |
1393 | | |
1394 | 6.89M | char c = done ? char(0) : char(input->readULong(1)); |
1395 | 6.89M | if (pos!=actPos && (c==0xd || done)) { |
1396 | 63.5k | ascFile.addPos(pos); |
1397 | 63.5k | ascFile.addNote(f.str().c_str()); |
1398 | 63.5k | f.str(""); |
1399 | 63.5k | f << "Text:"; |
1400 | 63.5k | pos = actPos+1; |
1401 | 63.5k | } |
1402 | 6.89M | if (done) break; |
1403 | | |
1404 | 6.88M | auto pIt=zone.m_posPLCMap.find(cPos); |
1405 | 6.88M | GreatWksTextInternal::Token token; |
1406 | 7.15M | while (pIt!=zone.m_posPLCMap.end() && pIt->first==cPos) { |
1407 | 267k | GreatWksTextInternal::PLC const &plc=(pIt++)->second; |
1408 | 267k | f << "[" << plc << "]"; |
1409 | 267k | switch (plc.m_type) { |
1410 | 38.3k | case GreatWksTextInternal::P_Font: |
1411 | 38.3k | if (plc.m_id < 0 || plc.m_id >= static_cast<int>(zone.m_fontList.size())) { |
1412 | 5.46k | MWAW_DEBUG_MSG(("GreatWksText::sendZone: can not find font %d\n", plc.m_id)); |
1413 | 5.46k | break; |
1414 | 5.46k | } |
1415 | 32.8k | listener->setFont(zone.m_fontList[size_t(plc.m_id)]); |
1416 | 32.8k | break; |
1417 | 42.0k | case GreatWksTextInternal::P_Ruler: |
1418 | 42.0k | if (plc.m_id < 0 || plc.m_id >= static_cast<int>(zone.m_rulerList.size())) { |
1419 | 4.33k | MWAW_DEBUG_MSG(("GreatWksText::sendZone: can not find ruler %d\n", plc.m_id)); |
1420 | 4.33k | break; |
1421 | 4.33k | } |
1422 | 37.7k | listener->setParagraph(zone.m_rulerList[size_t(plc.m_id)]); |
1423 | 37.7k | break; |
1424 | 30.8k | case GreatWksTextInternal::P_Token: |
1425 | 30.8k | if (plc.m_id < 0 || plc.m_id >= static_cast<int>(zone.m_tokenList.size())) { |
1426 | 0 | MWAW_DEBUG_MSG(("GreatWksText::sendZone: can not find token %d\n", plc.m_id)); |
1427 | 0 | break; |
1428 | 0 | } |
1429 | 30.8k | token=zone.m_tokenList[size_t(plc.m_id)]; |
1430 | 30.8k | break; |
1431 | 155k | case GreatWksTextInternal::P_Page: |
1432 | 155k | case GreatWksTextInternal::P_Unknown: |
1433 | | #if !defined(__clang__) |
1434 | | default: |
1435 | | #endif |
1436 | 155k | break; |
1437 | 267k | } |
1438 | 267k | } |
1439 | 6.88M | if (c!=0xd) f << c; |
1440 | 6.88M | switch (c) { |
1441 | 73.7k | case 0x4: { |
1442 | 73.7k | f << "[pict]"; |
1443 | 73.7k | if (token.m_type!=4 || !token.m_pictEntry.valid()) { |
1444 | 73.7k | MWAW_DEBUG_MSG(("GreatWksText::sendZone: can not find a picture\n")); |
1445 | 73.7k | f << "###"; |
1446 | 73.7k | break; |
1447 | 73.7k | } |
1448 | 17 | if (inLocalZone) { |
1449 | 0 | MWAW_DEBUG_MSG(("GreatWksText::sendZone: oops, can not send a picture in a graphic zone\n")); |
1450 | 0 | break; |
1451 | 0 | } |
1452 | 17 | MWAWPosition pictPos(MWAWVec2f(0,0), token.m_dim, librevenge::RVNG_POINT); |
1453 | 17 | pictPos.setRelativePosition(MWAWPosition::Char, MWAWPosition::XLeft, MWAWPosition::YBottom); |
1454 | 17 | m_document.sendPicture(token.m_pictEntry, pictPos); |
1455 | 17 | break; |
1456 | 17 | } |
1457 | 30.1k | case 0x9: |
1458 | 30.1k | listener->insertTab(); |
1459 | 30.1k | break; |
1460 | 25.3k | case 0xb: |
1461 | 25.3k | f << "[colbreak]"; |
1462 | 25.3k | if (!isMain) { |
1463 | 12.5k | MWAW_DEBUG_MSG(("GreatWksText::sendZone: find column break in auxilliary block\n")); |
1464 | 12.5k | break; |
1465 | 12.5k | } |
1466 | 12.7k | if (actCol < numCol-1 && numCol > 1) { |
1467 | 9.79k | listener->insertBreak(MWAWListener::ColumnBreak); |
1468 | 9.79k | actCol++; |
1469 | 9.79k | } |
1470 | 2.94k | else { |
1471 | 2.94k | actCol = 0; |
1472 | 2.94k | m_document.newPage(++actPage); |
1473 | 2.94k | } |
1474 | 12.7k | break; |
1475 | 34.8k | case 0xc: |
1476 | 34.8k | f << "[pagebreak]"; |
1477 | 34.8k | if (!isMain) { |
1478 | 13.8k | f << "###"; |
1479 | 13.8k | MWAW_DEBUG_MSG(("GreatWksText::sendZone: find page break in auxilliary zone\n")); |
1480 | 13.8k | break; |
1481 | 13.8k | } |
1482 | 20.9k | m_document.newPage(++actPage); |
1483 | 20.9k | actCol = 0; |
1484 | 20.9k | break; |
1485 | 77.2k | case 0xd: |
1486 | 77.2k | listener->insertEOL(); |
1487 | 77.2k | break; |
1488 | 260k | case 2: // page number |
1489 | 282k | case 0x15: // date |
1490 | 297k | case 0x16: // time |
1491 | 297k | if (token.sendTo(*listener)) |
1492 | 601 | break; |
1493 | 297k | f << "###"; |
1494 | 297k | MWAW_DEBUG_MSG(("GreatWksText::sendZone: can not send token\n")); |
1495 | 297k | break; |
1496 | 6.34M | default: |
1497 | 6.34M | listener->insertCharacter(static_cast<unsigned char>(c)); |
1498 | 6.34M | break; |
1499 | 6.88M | } |
1500 | 6.88M | cPos++; |
1501 | 6.88M | } |
1502 | 9.72k | return true; |
1503 | 9.72k | } |
1504 | | // vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: |