/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 | 69.0k | : m_type(P_Unknown) |
69 | 69.0k | , m_id(-1) |
70 | 69.0k | , m_extra("") |
71 | 69.0k | { |
72 | 69.0k | } |
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 | 3.40M | : m_type(-1) |
116 | 3.40M | , m_format(0) |
117 | 3.40M | , m_pictEntry() |
118 | 3.40M | , m_dataSize(0) |
119 | 3.40M | , m_dim(0,0) |
120 | 3.40M | , m_date(0xFFFFFFFF) |
121 | 3.40M | , m_extra("") |
122 | 3.40M | { |
123 | 3.40M | } |
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 | 63.8k | { |
148 | 63.8k | switch (m_type) { |
149 | 119 | case 2: |
150 | 119 | switch (m_format) { |
151 | 9 | case 1: |
152 | 18 | case 3: // must be roman |
153 | 18 | listener.insertField(MWAWField(MWAWField::PageNumber)); |
154 | 18 | break; |
155 | 52 | case 2: |
156 | 58 | case 4: // must be roman |
157 | 58 | listener.insertField(MWAWField(MWAWField::PageNumber)); |
158 | 58 | listener.insertUnicodeString(librevenge::RVNGString(" of ")); |
159 | 58 | listener.insertField(MWAWField(MWAWField::PageCount)); |
160 | 58 | break; |
161 | 43 | default: |
162 | 43 | listener.insertField(MWAWField(MWAWField::PageNumber)); |
163 | 43 | break; |
164 | 119 | } |
165 | 119 | return true; |
166 | 644 | case 0x15: |
167 | 660 | case 0x16: { |
168 | 660 | MWAWField field(m_type==0x15 ? MWAWField::Date : MWAWField::Time); |
169 | 660 | field.m_DTFormat=getDTFormat(); |
170 | 660 | listener.insertField(field); |
171 | 660 | return true; |
172 | 644 | } |
173 | 63.0k | default: |
174 | 63.0k | break; |
175 | 63.8k | } |
176 | 63.0k | return false; |
177 | 63.8k | } |
178 | | |
179 | | std::string Token::getDTFormat() const |
180 | 660 | { |
181 | 660 | switch (m_type) { |
182 | 644 | case 0x15: |
183 | 644 | switch (m_format) { |
184 | 1 | case 0xa: |
185 | 1 | return "%m/%d/%y"; |
186 | 590 | case 0xb: |
187 | 590 | return "%b %d, %Y"; |
188 | 0 | case 0xc: |
189 | 0 | 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 | 15 | case 0x10: |
197 | 15 | return "%B %d"; |
198 | 1 | case 0x11: |
199 | 1 | return "%a, %b %d, %Y"; |
200 | 9 | case 0x12: |
201 | 9 | return "%A, %B %d, %Y"; |
202 | 25 | default: |
203 | 25 | break; |
204 | 644 | } |
205 | 25 | break; |
206 | 25 | case 0x16: |
207 | 16 | switch (m_format) { |
208 | 0 | case 0x14: |
209 | 0 | return "%I:%M %p"; |
210 | 1 | case 0x15: |
211 | 1 | return "%I:%M:%S %p"; |
212 | 5 | case 0x16: |
213 | 5 | 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 | 10 | default: |
221 | 10 | break; |
222 | 16 | } |
223 | 10 | break; |
224 | 10 | default: |
225 | 0 | break; |
226 | 660 | } |
227 | 35 | return ""; |
228 | 660 | } |
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 | 208k | : m_pos() |
285 | 208k | , m_page(0) |
286 | 208k | , m_extra("") |
287 | 208k | { |
288 | 208k | } |
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 | 135k | : m_type(-1) |
311 | 135k | , m_numFonts(0) |
312 | 135k | , m_numRulers(0) |
313 | 135k | , m_numLines(0) |
314 | 135k | , m_numTokens(0) |
315 | 135k | , m_numChar(0) |
316 | 135k | , m_numCharPLC(0) |
317 | 135k | , m_numFrames(0) |
318 | 135k | , m_fontList() |
319 | 135k | , m_rulerList() |
320 | 135k | , m_tokenList() |
321 | 135k | , m_frameList() |
322 | 135k | , m_textEntry() |
323 | 135k | , m_posPLCMap() |
324 | 135k | , m_parsed(false) |
325 | 135k | , m_extra("") |
326 | 135k | { |
327 | 135k | } |
328 | | //! returns true if this is the main zone |
329 | | bool isMain() const |
330 | 61.5k | { |
331 | 61.5k | return m_type==3; |
332 | 61.5k | } |
333 | | //! check if the data read are or not ok |
334 | | bool ok() const |
335 | 43.8k | { |
336 | 43.8k | if (m_type<0 || m_type > 5) |
337 | 403 | return false; |
338 | 43.4k | if (m_numFonts<=0 || m_numRulers<=0 || m_numLines<0 || m_numTokens<=0 || m_numChar<0 || |
339 | 39.7k | m_numCharPLC<=0 || m_numFrames<0) |
340 | 7.27k | return false; |
341 | 36.1k | return true; |
342 | 43.4k | } |
343 | | //! returns the data size |
344 | | long size() const |
345 | 36.1k | { |
346 | 36.1k | return 22*m_numFonts+192*m_numRulers+6*m_numCharPLC |
347 | 36.1k | +18*m_numTokens+14*m_numLines+22*m_numFrames+m_numChar; |
348 | 36.1k | } |
349 | | //! returns true if the data has graphic |
350 | | bool hasGraphics() const |
351 | 486 | { |
352 | 515 | for (auto const &token : m_tokenList) { |
353 | 515 | if (token.m_type==4) |
354 | 0 | return true; |
355 | 515 | } |
356 | 486 | return false; |
357 | 486 | } |
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 | 112k | : m_fileIdFontIdMap() |
432 | 112k | , m_zonesList() |
433 | 112k | , m_version(-1) |
434 | 112k | , m_numPages(-1) |
435 | 112k | { |
436 | 112k | } |
437 | | //! returns the font id corresponding to a fId |
438 | | int getFId(int fileId) const |
439 | 880k | { |
440 | 880k | if (m_fileIdFontIdMap.find(fileId)==m_fileIdFontIdMap.end()) |
441 | 758k | return fileId; |
442 | 122k | return m_fileIdFontIdMap.find(fileId)->second; |
443 | 880k | } |
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 | 112k | : m_document(document) |
459 | 112k | , m_parserState(document.m_parserState) |
460 | 112k | , m_state(new GreatWksTextInternal::State) |
461 | 112k | , m_mainParser(&document.getMainParser()) |
462 | 112k | { |
463 | 112k | } |
464 | | |
465 | | GreatWksText::~GreatWksText() |
466 | 112k | { } |
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 | 22.1k | { |
477 | 22.1k | if (m_state->m_numPages >= 0) |
478 | 3.56k | return m_state->m_numPages; |
479 | | |
480 | 18.5k | int nPages=1; |
481 | 18.5k | for (auto const &zone : m_state->m_zonesList) { |
482 | 8.78k | if (!zone.isMain() || zone.m_frameList.empty()) |
483 | 3.52k | continue; |
484 | 5.25k | if (zone.m_frameList.back().m_page>1) |
485 | 3.56k | nPages = zone.m_frameList.back().m_page; |
486 | 5.25k | break; |
487 | 8.78k | } |
488 | | |
489 | 18.5k | return m_state->m_numPages = nPages; |
490 | 22.1k | } |
491 | | |
492 | | int GreatWksText::getFontId(int fileId) const |
493 | 31.1k | { |
494 | 31.1k | return m_state->getFId(fileId); |
495 | 31.1k | } |
496 | | |
497 | | int GreatWksText::numHFZones() const |
498 | 6.39k | { |
499 | 6.39k | int nHF=0; |
500 | 8.77k | for (auto const &zone : m_state->m_zonesList) { |
501 | 8.77k | if (zone.isMain()) |
502 | 6.39k | break; |
503 | 2.38k | nHF++; |
504 | 2.38k | } |
505 | 6.39k | return nHF; |
506 | 6.39k | } |
507 | | |
508 | | bool GreatWksText::canSendTextBoxAsGraphic(MWAWEntry const &entry) |
509 | 874 | { |
510 | 874 | if (!entry.valid()) |
511 | 47 | return false; |
512 | 827 | MWAWInputStreamPtr &input= m_parserState->m_input; |
513 | 827 | long pos=input->tell(); |
514 | 827 | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
515 | 827 | GreatWksTextInternal::Zone zone; |
516 | 827 | bool ok=!readZone(zone) ||!zone.hasGraphics(); |
517 | 827 | input->seek(pos, librevenge::RVNG_SEEK_SET); |
518 | 827 | return ok; |
519 | 874 | } |
520 | | |
521 | | bool GreatWksText::sendTextbox(MWAWEntry const &entry, MWAWListenerPtr listener) |
522 | 7.07k | { |
523 | 7.07k | 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 | 7.07k | if (!entry.valid()) |
528 | 706 | return false; |
529 | 6.37k | MWAWInputStreamPtr &input= m_parserState->m_input; |
530 | 6.37k | input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
531 | 6.37k | GreatWksTextInternal::Zone zone; |
532 | 6.37k | if (readZone(zone)) { |
533 | 2.64k | sendZone(zone, listener); |
534 | 2.64k | return true; |
535 | 2.64k | } |
536 | | |
537 | 3.72k | return sendSimpleTextbox(entry, listener); |
538 | 6.37k | } |
539 | | |
540 | | //////////////////////////////////////////////////////////// |
541 | | // Intermediate level |
542 | | //////////////////////////////////////////////////////////// |
543 | | bool GreatWksText::createZones(int expectedHF) |
544 | 21.4k | { |
545 | 21.4k | MWAWInputStreamPtr &input= m_parserState->m_input; |
546 | 21.4k | libmwaw::DebugFile &ascFile = m_parserState->m_asciiFile; |
547 | 21.4k | libmwaw::DebugStream f; |
548 | | |
549 | 21.4k | long pos = input->tell(); |
550 | 21.4k | f << "Entries(TZoneHeader):"; |
551 | 21.4k | auto val=static_cast<int>(input->readULong(2)); |
552 | 21.4k | if (val) |
553 | 16.2k | f << "numPages=" << val << ","; |
554 | 21.4k | val=static_cast<int>(input->readULong(2)); |
555 | 21.4k | if (val) // related to number of header/footer? |
556 | 12.2k | f << "f0=" << val << ","; |
557 | 21.4k | f << "height[total]=" << input->readLong(4) << ","; // checkme |
558 | 21.4k | ascFile.addDelimiter(input->tell(),'|'); |
559 | 21.4k | ascFile.addPos(pos); |
560 | 21.4k | ascFile.addNote(f.str().c_str()); |
561 | | |
562 | 21.4k | pos += 68; |
563 | 21.4k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
564 | | |
565 | 21.4k | if (!readFontNames()) { |
566 | 15.4k | MWAW_DEBUG_MSG(("GreatWksText::createZones: can not find the font names\n")); |
567 | 15.4k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
568 | 15.4k | } |
569 | | |
570 | 21.4k | bool findMainZone=false; |
571 | 21.4k | int nAuxi=0; |
572 | 43.1k | while (!input->isEnd()) { |
573 | 42.3k | pos=input->tell(); |
574 | 42.3k | GreatWksTextInternal::Zone zone; |
575 | 42.3k | if (!readZone(zone)) { |
576 | 30.4k | input->seek(pos,librevenge::RVNG_SEEK_SET); |
577 | 30.4k | if (findMainZone) |
578 | 6.35k | break; |
579 | | |
580 | 24.1k | if (!findNextZone() || !readZone(zone)) { |
581 | 14.3k | input->seek(pos,librevenge::RVNG_SEEK_SET); |
582 | 14.3k | break; |
583 | 14.3k | } |
584 | 24.1k | } |
585 | 21.6k | m_state->m_zonesList.push_back(zone); |
586 | 21.6k | if (zone.isMain()) |
587 | 6.41k | findMainZone=true; |
588 | 15.2k | else |
589 | 15.2k | nAuxi++; |
590 | 21.6k | } |
591 | 21.4k | if (nAuxi!=expectedHF) { |
592 | 4.71k | MWAW_DEBUG_MSG(("GreatWksText::createZones: unexpected HF zones: %d/%d\n", nAuxi, expectedHF)); |
593 | 4.71k | } |
594 | 21.4k | return findMainZone; |
595 | 21.4k | } |
596 | | |
597 | | bool GreatWksText::findNextZone() |
598 | 24.1k | { |
599 | 24.1k | MWAWInputStreamPtr &input= m_parserState->m_input; |
600 | | |
601 | 24.1k | long searchPos=input->tell(), pos=searchPos; |
602 | 24.1k | int const headerSize=24+22+184; |
603 | 24.1k | if (!input->checkPosition(pos+headerSize)) |
604 | 2.35k | return false; |
605 | | |
606 | | // first look for ruler |
607 | 21.7k | input->seek(pos+headerSize, librevenge::RVNG_SEEK_SET); |
608 | 9.92M | while (true) { |
609 | 9.92M | if (input->isEnd()) |
610 | 8.82k | return false; |
611 | 9.91M | pos = input->tell(); |
612 | 9.91M | unsigned long val=input->readULong(4); |
613 | 9.91M | if (val==0x20FFFF) |
614 | 18.0k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
615 | 9.89M | else if (val==0x20FFFFFF) |
616 | 17.4k | input->seek(pos-1, librevenge::RVNG_SEEK_SET); |
617 | 9.88M | else if (val==0xFFFFFFFF) |
618 | 278k | input->seek(pos-2, librevenge::RVNG_SEEK_SET); |
619 | 9.60M | else if (val==0xFFFFFF2E) |
620 | 10.7k | input->seek(pos-3, librevenge::RVNG_SEEK_SET); |
621 | 9.59M | else |
622 | 9.59M | continue; |
623 | 324k | if (input->readULong(4)!=0x20FFFF || input->readULong(4)!=0xFFFF2E00) { |
624 | 311k | input->seek(pos+4, librevenge::RVNG_SEEK_SET); |
625 | 311k | continue; |
626 | 311k | } |
627 | | // ok a empty tabs stop |
628 | 58.8k | while (!input->isEnd()) { |
629 | 58.5k | pos = input->tell(); |
630 | 58.5k | if (input->readULong(4)!=0x20FFFF || input->readULong(4)!=0xFFFF2E00) { |
631 | 12.6k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
632 | 12.6k | break; |
633 | 12.6k | } |
634 | 58.5k | } |
635 | 12.9k | break; |
636 | 324k | } |
637 | | |
638 | 12.9k | pos=input->tell(); |
639 | 12.9k | int nFonts=0; |
640 | 12.9k | GreatWksTextInternal::Zone zone; |
641 | 427k | while (true) { |
642 | 427k | long hSize=headerSize+22*nFonts++; |
643 | 427k | if (pos-hSize < searchPos) |
644 | 3.19k | break; |
645 | 423k | input->seek(pos-hSize, librevenge::RVNG_SEEK_SET); |
646 | 423k | if (input->readLong(4)) |
647 | 316k | continue; |
648 | 107k | auto val=static_cast<int>(input->readULong(2)); |
649 | 107k | if (val & 0xFEFE) |
650 | 24.0k | continue; |
651 | 83.0k | input->seek(2,librevenge::RVNG_SEEK_CUR); |
652 | 83.0k | if (input->readLong(2)!=nFonts) |
653 | 69.1k | continue; |
654 | 13.8k | input->seek(pos-hSize, librevenge::RVNG_SEEK_SET); |
655 | 13.8k | if (readZone(zone)) { |
656 | 9.75k | input->seek(pos-hSize, librevenge::RVNG_SEEK_SET); |
657 | 9.75k | return true; |
658 | 9.75k | } |
659 | 13.8k | } |
660 | | |
661 | 3.19k | MWAW_DEBUG_MSG(("GreatWksText::findNextZone: can not find begin of zone for pos=%lx\n", static_cast<long unsigned int>(pos))); |
662 | 3.19k | input->seek(searchPos, librevenge::RVNG_SEEK_SET); |
663 | 3.19k | return false; |
664 | 12.9k | } |
665 | | |
666 | | bool GreatWksText::readZone(GreatWksTextInternal::Zone &zone) |
667 | 73.1k | { |
668 | 73.1k | zone=GreatWksTextInternal::Zone(); |
669 | 73.1k | MWAWInputStreamPtr &input= m_parserState->m_input; |
670 | 73.1k | long pos=input->tell(); |
671 | 73.1k | long endPos=pos+24; |
672 | 73.1k | if (!input->checkPosition(endPos)) |
673 | 931 | return false; |
674 | | |
675 | 72.2k | libmwaw::DebugFile &ascFile = m_parserState->m_asciiFile; |
676 | 72.2k | libmwaw::DebugStream f; |
677 | 72.2k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
678 | 72.2k | if (input->readLong(4)) { |
679 | 22.7k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
680 | 22.7k | return false; |
681 | 22.7k | } |
682 | 144k | for (int i=0; i < 2; ++i) { |
683 | 97.4k | auto val=static_cast<int>(input->readLong(1)); |
684 | 97.4k | if (val==0) continue; |
685 | 19.0k | if (val!=1) |
686 | 2.37k | return false; |
687 | 16.6k | if (i==0) |
688 | 6.04k | f << "smartquote,"; |
689 | 10.5k | else |
690 | 10.5k | f << "hidepict,"; |
691 | 16.6k | } |
692 | 47.0k | zone.m_type=static_cast<int>(input->readLong(1)); |
693 | 47.0k | if (input->readLong(1)) { // simple|complex field |
694 | 3.22k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
695 | 3.22k | return false; |
696 | 3.22k | } |
697 | 43.8k | zone.m_numFonts=static_cast<int>(input->readULong(2)); |
698 | 43.8k | zone.m_numRulers=static_cast<int>(input->readULong(2)); |
699 | 43.8k | zone.m_numCharPLC=static_cast<int>(input->readULong(2)); |
700 | 43.8k | zone.m_numTokens=static_cast<int>(input->readULong(2)); |
701 | 43.8k | zone.m_numLines=static_cast<int>(input->readULong(2)); |
702 | 43.8k | zone.m_numFrames=static_cast<int>(input->readULong(2)); |
703 | 43.8k | zone.m_numChar=long(input->readULong(4)); |
704 | 43.8k | if (!zone.ok() || !input->checkPosition(endPos+zone.size())) { |
705 | 9.34k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
706 | 9.34k | return false; |
707 | 9.34k | } |
708 | 34.5k | zone.m_extra=f.str(); |
709 | 34.5k | f.str(""); |
710 | 34.5k | f << "Entries(HeaderText):" << zone; |
711 | 34.5k | if (input->tell()!=endPos) { |
712 | 0 | ascFile.addDelimiter(input->tell(),'|'); |
713 | 0 | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
714 | 0 | } |
715 | 34.5k | ascFile.addPos(pos); |
716 | 34.5k | ascFile.addNote(f.str().c_str()); |
717 | | |
718 | 882k | for (int i=0; i<zone.m_numFonts; ++i) { |
719 | 847k | pos = input->tell(); |
720 | 847k | f.str(""); |
721 | 847k | f << "Entries(FontDef)-F" << i << ":"; |
722 | | |
723 | 847k | MWAWFont font; |
724 | 847k | if (!readFont(font)) { |
725 | 0 | f << "###"; |
726 | 0 | font = MWAWFont(); |
727 | 0 | input->seek(pos+22, librevenge::RVNG_SEEK_SET); |
728 | 0 | } |
729 | 847k | zone.m_fontList.push_back(font); |
730 | 847k | f << font.getDebugString(m_parserState->m_fontConverter) << ","; |
731 | 847k | ascFile.addPos(pos); |
732 | 847k | ascFile.addNote(f.str().c_str()); |
733 | 847k | } |
734 | 34.5k | MWAWParagraph para; |
735 | 181k | for (int i=0; i<zone.m_numRulers; ++i) { |
736 | 146k | pos = input->tell(); |
737 | 146k | f.str(""); |
738 | 146k | f << "Entries(RulerDef)-R" << i << ":"; |
739 | 146k | if (!readRuler(para)) { |
740 | 0 | f << "###"; |
741 | 0 | para = MWAWParagraph(); |
742 | 0 | input->seek(pos+192, librevenge::RVNG_SEEK_SET); |
743 | 0 | } |
744 | 146k | zone.m_rulerList.push_back(para); |
745 | 146k | f << para; |
746 | 146k | ascFile.addPos(pos); |
747 | 146k | ascFile.addNote(f.str().c_str()); |
748 | 146k | } |
749 | | |
750 | 34.5k | pos=input->tell(); |
751 | 34.5k | f.str(""); |
752 | 34.5k | f << "Entries(CharPLC):"; |
753 | 34.5k | GreatWksTextInternal::PLC plc; |
754 | 34.5k | plc.m_type = GreatWksTextInternal::P_Font; |
755 | 34.5k | long textPos = 0; |
756 | 2.08M | for (int i=0; i < zone.m_numCharPLC; ++i) { |
757 | 2.04M | plc.m_id=static_cast<int>(input->readULong(2)); |
758 | 2.04M | zone.m_posPLCMap.insert |
759 | 2.04M | (std::multimap<long, GreatWksTextInternal::PLC>::value_type(textPos, plc)); |
760 | 2.04M | f << "F" << plc.m_id << ":" << std::hex << textPos << std::dec << ","; |
761 | 2.04M | textPos+= static_cast<int>(input->readULong(4)); |
762 | 2.04M | } |
763 | 34.5k | ascFile.addPos(pos); |
764 | 34.5k | ascFile.addNote(f.str().c_str()); |
765 | | // the token |
766 | 34.5k | plc.m_type = GreatWksTextInternal::P_Token; |
767 | 34.5k | textPos = 0; |
768 | 764k | for (int i=0; i < zone.m_numTokens; ++i) { |
769 | 729k | pos = input->tell(); |
770 | 729k | f.str(""); |
771 | 729k | plc.m_id=i; |
772 | 729k | f << "Entries(Token)-Tn" << i << ":"; |
773 | 729k | GreatWksTextInternal::Token tkn; |
774 | 729k | long numC; |
775 | 729k | 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 | 729k | zone.m_posPLCMap.insert |
782 | 729k | (std::multimap<long, GreatWksTextInternal::PLC>::value_type(textPos, plc)); |
783 | 729k | zone.m_tokenList.push_back(tkn); |
784 | 729k | f << tkn << ",pos=" << std::hex << textPos << std::dec; |
785 | 729k | textPos+= numC; |
786 | 729k | input->seek(pos+18, librevenge::RVNG_SEEK_SET); |
787 | 729k | ascFile.addPos(pos); |
788 | 729k | ascFile.addNote(f.str().c_str()); |
789 | 729k | } |
790 | 34.5k | if (!readZonePositions(zone)) |
791 | 0 | return false; |
792 | | // fill the text entry |
793 | 34.5k | pos=input->tell(); |
794 | 34.5k | zone.m_textEntry.setBegin(pos); |
795 | 34.5k | zone.m_textEntry.setLength(zone.m_numChar); |
796 | 34.5k | ascFile.addPos(pos); |
797 | 34.5k | ascFile.addNote("_"); |
798 | 34.5k | pos += zone.m_numChar; |
799 | 34.5k | ascFile.addPos(pos); |
800 | 34.5k | ascFile.addNote("_"); |
801 | | |
802 | 580k | for (auto &tkn : zone.m_tokenList) { |
803 | 580k | if (tkn.m_type != 4) |
804 | 573k | continue; |
805 | 6.97k | if (tkn.m_dataSize <= 0 || !input->checkPosition(pos+tkn.m_dataSize)) { |
806 | 6.03k | MWAW_DEBUG_MSG(("GreatWksText::readZone: can not determine the picture size\n")); |
807 | 6.03k | break; |
808 | 6.03k | } |
809 | 935 | tkn.m_pictEntry.setBegin(pos); |
810 | 935 | tkn.m_pictEntry.setLength(tkn.m_dataSize); |
811 | 935 | pos+=tkn.m_dataSize; |
812 | 935 | } |
813 | 34.5k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
814 | 34.5k | return true; |
815 | 34.5k | } |
816 | | |
817 | | bool GreatWksText::readZonePositions(GreatWksTextInternal::Zone &zone) |
818 | 34.5k | { |
819 | 34.5k | MWAWInputStreamPtr &input= m_parserState->m_input; |
820 | 34.5k | libmwaw::DebugFile &ascFile = m_parserState->m_asciiFile; |
821 | 34.5k | libmwaw::DebugStream f; |
822 | | |
823 | | // the line |
824 | 34.5k | GreatWksTextInternal::PLC plc; |
825 | 34.5k | plc.m_type = GreatWksTextInternal::P_Ruler; |
826 | 34.5k | long textPos = 0; |
827 | 34.5k | std::vector<long> linesPos; |
828 | 34.5k | linesPos.push_back(0); |
829 | 391k | for (int i=0; i < zone.m_numLines; ++i) { |
830 | 357k | long pos=input->tell(); |
831 | 357k | f.str(""); |
832 | 357k | plc.m_id=static_cast<int>(input->readULong(2)); |
833 | 357k | auto numC = long(input->readULong(4)); |
834 | 357k | f << "y=" << double(input->readLong(4))/65536.; |
835 | 357k | f << "->" << double(input->readLong(4))/65536.; |
836 | 357k | plc.m_extra=f.str(); |
837 | 357k | zone.m_posPLCMap.insert |
838 | 357k | (std::multimap<long, GreatWksTextInternal::PLC>::value_type(textPos, plc)); |
839 | 357k | f.str(""); |
840 | 357k | f << "Entries(Line)-L" << i << ":" << plc << ":" |
841 | 357k | << std::hex << textPos << std::dec; |
842 | 357k | textPos+=numC; |
843 | 357k | linesPos.push_back(textPos); |
844 | 357k | input->seek(pos+14, librevenge::RVNG_SEEK_SET); |
845 | 357k | ascFile.addPos(pos); |
846 | 357k | ascFile.addNote(f.str().c_str()); |
847 | 357k | } |
848 | | // the page dimension |
849 | 34.5k | plc.m_type = GreatWksTextInternal::P_Page; |
850 | 243k | for (int i=0; i < zone.m_numFrames; ++i) { |
851 | 208k | GreatWksTextInternal::Frame frame; |
852 | 208k | long pos=input->tell(); |
853 | 208k | plc.m_id=i; |
854 | 208k | f.str(""); |
855 | 208k | float dim[4]; |
856 | 835k | for (auto &d : dim) d=float(input->readLong(4))/65536.f; |
857 | 208k | frame.m_pos=MWAWBox2f(MWAWVec2f(dim[1],dim[0]),MWAWVec2f(dim[3],dim[2])); |
858 | 208k | auto val=static_cast<int>(input->readLong(2)); // always 0 |
859 | 208k | if (val) f << "#unkn=" << val << ","; |
860 | 208k | frame.m_page=static_cast<int>(input->readLong(2)); |
861 | 208k | auto line=static_cast<int>(input->readLong(2)); |
862 | 208k | plc.m_extra=f.str(); |
863 | 208k | if (line >= 0 && line < int(linesPos.size())) { |
864 | 87.5k | textPos=linesPos[size_t(line)]; |
865 | 87.5k | zone.m_posPLCMap.insert |
866 | 87.5k | (std::multimap<long, GreatWksTextInternal::PLC>::value_type(textPos, plc)); |
867 | 87.5k | if (textPos) |
868 | 8.43k | f << "pos=" << std::hex << textPos << std::dec; |
869 | 87.5k | } |
870 | 121k | else { |
871 | 121k | MWAW_DEBUG_MSG(("GreatWksText::readZone: can not find begin pos for page %d\n",line)); |
872 | 121k | f << "##pos[line]=" << line << ","; |
873 | 121k | } |
874 | 208k | frame.m_extra=f.str(); |
875 | 208k | zone.m_frameList.push_back(frame); |
876 | 208k | f.str(""); |
877 | 208k | f << "Entries(TFrames)-" << i << ":" << frame; |
878 | 208k | input->seek(pos+22, librevenge::RVNG_SEEK_SET); |
879 | 208k | ascFile.addPos(pos); |
880 | 208k | ascFile.addNote(f.str().c_str()); |
881 | 208k | } |
882 | 34.5k | return true; |
883 | 34.5k | } |
884 | | |
885 | | ////////////////////////////////////////////// |
886 | | // Fonts |
887 | | ////////////////////////////////////////////// |
888 | | bool GreatWksText::readFontNames() |
889 | 77.3k | { |
890 | 77.3k | MWAWInputStreamPtr &input= m_parserState->m_input; |
891 | 77.3k | long pos=input->tell(); |
892 | 77.3k | libmwaw::DebugFile &ascFile = m_parserState->m_asciiFile; |
893 | 77.3k | libmwaw::DebugStream f; |
894 | 77.3k | f << "Entries(FontNames):"; |
895 | 77.3k | auto sz= long(input->readULong(4)); |
896 | 77.3k | long endPos = input->tell()+sz; |
897 | 77.3k | if (sz < 2 || !input->checkPosition(endPos)) { |
898 | 44.2k | MWAW_DEBUG_MSG(("GreatWksText::readFontNames: can not read field size\n")); |
899 | 44.2k | f << "###"; |
900 | 44.2k | ascFile.addPos(pos); |
901 | 44.2k | ascFile.addNote(f.str().c_str()); |
902 | 44.2k | return false; |
903 | 44.2k | } |
904 | 33.0k | auto N=static_cast<int>(input->readLong(2)); |
905 | 33.0k | f << "N=" << N << ","; |
906 | 33.0k | if (N*5+2 > sz) { |
907 | 1.79k | MWAW_DEBUG_MSG(("GreatWksText::readFontNames: can not read N\n")); |
908 | 1.79k | f << "###"; |
909 | 1.79k | ascFile.addPos(pos); |
910 | 1.79k | ascFile.addNote(f.str().c_str()); |
911 | 1.79k | return false; |
912 | 1.79k | } |
913 | 31.2k | ascFile.addPos(pos); |
914 | 31.2k | ascFile.addNote(f.str().c_str()); |
915 | 1.82M | for (int i=0; i < N; ++i) { |
916 | 1.79M | pos = input->tell(); |
917 | 1.79M | f.str(""); |
918 | 1.79M | f << "FontNames-" << i << ":"; |
919 | 1.79M | auto fId=static_cast<int>(input->readULong(2)); |
920 | 1.79M | f << "fId=" << fId << ","; |
921 | 1.79M | auto val=static_cast<int>(input->readLong(2)); // always 0 ? |
922 | 1.79M | if (val) |
923 | 759k | f << "unkn=" << val << ","; |
924 | 1.79M | auto fSz=static_cast<int>(input->readULong(1)); |
925 | 1.79M | if (pos+5+fSz>endPos) { |
926 | 7.81k | MWAW_DEBUG_MSG(("GreatWksText::readFontNames: can not read font %d\n", i)); |
927 | 7.81k | f << "###"; |
928 | 7.81k | ascFile.addPos(pos); |
929 | 7.81k | ascFile.addNote(f.str().c_str()); |
930 | 7.81k | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
931 | 7.81k | return i>0; |
932 | 7.81k | } |
933 | 1.79M | std::string name(""); |
934 | 35.0M | for (int c=0; c < fSz; ++c) |
935 | 33.2M | name+=char(input->readULong(1)); |
936 | 1.79M | if (!name.empty()) |
937 | 630k | m_state->m_fileIdFontIdMap[fId]=m_parserState->m_fontConverter->getId(name); |
938 | 1.79M | if ((fSz%2)==0) |
939 | 1.44M | input->seek(1, librevenge::RVNG_SEEK_CUR); |
940 | | |
941 | 1.79M | f << "\"" << name << "\","; |
942 | 1.79M | ascFile.addPos(pos); |
943 | 1.79M | ascFile.addNote(f.str().c_str()); |
944 | 1.79M | } |
945 | 23.4k | pos = input->tell(); |
946 | 23.4k | if (pos!=endPos) { |
947 | 11.6k | MWAW_DEBUG_MSG(("GreatWksText::readFontNames: find extra data\n")); |
948 | 11.6k | ascFile.addPos(pos); |
949 | 11.6k | ascFile.addNote("FontNames:###"); |
950 | 11.6k | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
951 | 11.6k | } |
952 | 23.4k | return true; |
953 | 31.2k | } |
954 | | |
955 | | bool GreatWksText::readFont(MWAWFont &font) |
956 | 847k | { |
957 | 847k | font=MWAWFont(); |
958 | 847k | MWAWInputStreamPtr &input= m_parserState->m_input; |
959 | 847k | long pos=input->tell(); |
960 | 847k | long endPos=pos+22; |
961 | 847k | if (!input->checkPosition(endPos)) |
962 | 0 | return false; |
963 | | |
964 | 847k | libmwaw::DebugStream f; |
965 | 847k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
966 | 847k | auto val=static_cast<int>(input->readLong(2)); // small number between 0 and 5 |
967 | 847k | if (val==0) f << "unused,"; |
968 | 580k | else if (val!=1) f << "nbUsed=" << val << ","; |
969 | | // some dim dim[0]>dim[1]: minH, maxH ? |
970 | 847k | int dim[2]; |
971 | 1.69M | for (auto &d : dim) d=static_cast<int>(input->readLong(2)); |
972 | 847k | f << "dim?=" << dim[1] << "x" << dim[0] << ","; |
973 | | |
974 | 2.54M | for (int i=0; i < 2; ++i) { // f0=0|4(with italic), f1=0 |
975 | 1.69M | val=static_cast<int>(input->readLong(2)); |
976 | 1.69M | if (val) f << "f" << i << "=" << val << ","; |
977 | 1.69M | } |
978 | 847k | font.setId(m_state->getFId(static_cast<int>(input->readULong(2)))); |
979 | 847k | auto flag =static_cast<int>(input->readULong(2)); |
980 | 847k | uint32_t flags=0; |
981 | 847k | if (flag&0x1) flags |= MWAWFont::boldBit; |
982 | 847k | if (flag&0x2) flags |= MWAWFont::italicBit; |
983 | 847k | if (flag&0x4) font.setUnderlineStyle(MWAWFont::Line::Simple); |
984 | 847k | if (flag&0x8) flags |= MWAWFont::embossBit; |
985 | 847k | if (flag&0x10) flags |= MWAWFont::shadowBit; |
986 | 847k | if (flag&0x20) font.setDeltaLetterSpacing(-1); |
987 | 847k | if (flag&0x40) font.setDeltaLetterSpacing(1); |
988 | 847k | if (flag&0x100) font.set(MWAWFont::Script::super100()); |
989 | 847k | if (flag&0x200) font.set(MWAWFont::Script::sub100()); |
990 | 847k | if (flag&0x800) font.setStrikeOutStyle(MWAWFont::Line::Simple); |
991 | 847k | if (flag&0x2000) { |
992 | 203k | font.setUnderlineStyle(MWAWFont::Line::Simple); |
993 | 203k | font.setUnderlineType(MWAWFont::Line::Double); |
994 | 203k | } |
995 | 847k | flag &=0xD480; |
996 | 847k | if (flag) f << "#fl=" << std::hex << flag << std::dec << ","; |
997 | 847k | font.setFlags(flags); |
998 | 847k | font.setSize(float(input->readULong(2))); |
999 | 847k | unsigned char color[3]; |
1000 | 2.54M | for (auto &c : color) c = static_cast<unsigned char>(input->readULong(2)>>8); |
1001 | 847k | font.setColor(MWAWColor(color[0],color[1],color[2])); |
1002 | 847k | font.m_extra=f.str(); |
1003 | | |
1004 | 847k | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
1005 | 847k | return true; |
1006 | 847k | } |
1007 | | ////////////////////////////////////////////// |
1008 | | // Ruler |
1009 | | ////////////////////////////////////////////// |
1010 | | bool GreatWksText::readRuler(MWAWParagraph ¶) |
1011 | 146k | { |
1012 | 146k | para = MWAWParagraph(); |
1013 | 146k | MWAWInputStreamPtr &input= m_parserState->m_input; |
1014 | 146k | long pos=input->tell(); |
1015 | 146k | long endPos=pos+192; |
1016 | 146k | if (!input->checkPosition(endPos)) |
1017 | 0 | return false; |
1018 | | |
1019 | 146k | libmwaw::DebugStream f; |
1020 | 146k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1021 | 146k | auto val=static_cast<int>(input->readLong(2)); |
1022 | 146k | if (val==0) f << "unused,"; |
1023 | 113k | else if (val!=1) f << "nbUsed=" << val << ","; |
1024 | 146k | val=static_cast<int>(input->readLong(2)); |
1025 | 146k | switch (val) { |
1026 | 63.7k | case 0: |
1027 | 63.7k | break; |
1028 | 21.5k | case 1: |
1029 | 21.5k | para.m_justify = MWAWParagraph::JustificationCenter; |
1030 | 21.5k | break; |
1031 | 1.98k | case 2: |
1032 | 1.98k | para.m_justify = MWAWParagraph::JustificationRight ; |
1033 | 1.98k | break; |
1034 | 1.48k | case 3: |
1035 | 1.48k | para.m_justify = MWAWParagraph::JustificationFull; |
1036 | 1.48k | break; |
1037 | 57.9k | default: |
1038 | 57.9k | f << "#align" << val << ","; |
1039 | 57.9k | break; |
1040 | 146k | } |
1041 | 146k | para.m_marginsUnit=librevenge::RVNG_POINT; |
1042 | 146k | for (auto &margin : para.m_margins) |
1043 | 440k | margin = double(input->readLong(4))/65536.; |
1044 | 146k | para.m_margins[0]=*para.m_margins[0]-*para.m_margins[1]; |
1045 | 146k | double spacing[3]; |
1046 | 146k | for (double &i : spacing) |
1047 | 440k | i = double(input->readLong(4))/65536.; |
1048 | 146k | int unit[3]; |
1049 | 440k | for (auto &u : unit) u = static_cast<int>(input->readLong(1)); |
1050 | 146k | switch (unit[0]) { |
1051 | 4.46k | case 1: |
1052 | 6.71k | case 2: |
1053 | 7.53k | case 3: |
1054 | 8.90k | case 4: |
1055 | 15.9k | case 5: |
1056 | 15.9k | para.setInterline(spacing[0], librevenge::RVNG_POINT); |
1057 | 15.9k | break; |
1058 | 17.3k | case 6: |
1059 | 17.3k | para.setInterline(spacing[0], librevenge::RVNG_PERCENT); |
1060 | 17.3k | break; |
1061 | 113k | default: |
1062 | 113k | f << "#interline=" << spacing[0] << "[unit=" << unit[0] << "],"; |
1063 | 146k | } |
1064 | 440k | for (int w=1; w < 3; ++w) { |
1065 | 293k | if (unit[w]==6) |
1066 | 2.38k | para.m_spacings[w]=spacing[w]*12./72.; |
1067 | 291k | else if (unit[w]>0 && unit[w]<6) |
1068 | 72.2k | para.m_spacings[w]=spacing[w]/72.; |
1069 | 218k | else |
1070 | 218k | f << "#spac" << w << "=" << spacing[w] << "[unit=" << unit[w] << "],"; |
1071 | 293k | } |
1072 | 146k | val = static_cast<int>(input->readLong(1)); |
1073 | 146k | if (val) f << "#f0=" << val << ","; |
1074 | | |
1075 | 3.08M | for (int i=0; i < 20; ++i) { |
1076 | 2.93M | MWAWTabStop tab; |
1077 | 2.93M | val = static_cast<int>(input->readLong(1)); |
1078 | 2.93M | switch (val) { |
1079 | 1.59M | case 0: // left |
1080 | 1.59M | break; |
1081 | 145k | case 1: |
1082 | 145k | tab.m_alignment = MWAWTabStop::CENTER; |
1083 | 145k | break; |
1084 | 42.7k | case 2: |
1085 | 42.7k | tab.m_alignment = MWAWTabStop::RIGHT; |
1086 | 42.7k | break; |
1087 | 17.2k | case 3: |
1088 | 17.2k | tab.m_alignment = MWAWTabStop::DECIMAL; |
1089 | 17.2k | break; |
1090 | 1.13M | default: |
1091 | 1.13M | f << "#tab" << i << "[align]=" << val << ","; |
1092 | 1.13M | break; |
1093 | 2.93M | } |
1094 | 2.93M | auto leaderChar = char(input->readULong(1)); |
1095 | 2.93M | if (leaderChar) { |
1096 | 1.75M | int unicode= m_parserState->m_fontConverter->unicode(3, static_cast<unsigned char>(leaderChar)); |
1097 | 1.75M | if (unicode==-1) |
1098 | 430k | tab.m_leaderCharacter = uint16_t(leaderChar); |
1099 | 1.32M | else |
1100 | 1.32M | tab.m_leaderCharacter = uint16_t(unicode); |
1101 | 1.75M | } |
1102 | 2.93M | long tPos=input->readLong(4); |
1103 | 2.93M | if (tPos==-1) { |
1104 | 468k | input->seek(2, librevenge::RVNG_SEEK_CUR); |
1105 | 468k | continue; |
1106 | 468k | } |
1107 | 2.46M | tab.m_position=double(tPos)/72./65536.; |
1108 | 2.46M | auto decimalChar = char(input->readULong(1)); |
1109 | 2.46M | if (decimalChar) { |
1110 | 1.19M | int unicode= m_parserState->m_fontConverter->unicode(3, static_cast<unsigned char>(decimalChar)); |
1111 | 1.19M | if (unicode==-1) |
1112 | 544k | tab.m_decimalCharacter = uint16_t(decimalChar); |
1113 | 653k | else |
1114 | 653k | tab.m_decimalCharacter = uint16_t(unicode); |
1115 | 1.19M | } |
1116 | 2.46M | val = static_cast<int>(input->readLong(1)); |
1117 | 2.46M | if (val) f << "#tab" << i << "[f0=" << val << ","; |
1118 | 2.46M | para.m_tabs->push_back(tab); |
1119 | 2.46M | } |
1120 | 146k | para.m_extra=f.str(); |
1121 | | |
1122 | 146k | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
1123 | 146k | return true; |
1124 | 146k | } |
1125 | | |
1126 | | ////////////////////////////////////////////// |
1127 | | // Token |
1128 | | ////////////////////////////////////////////// |
1129 | | bool GreatWksText::readToken(GreatWksTextInternal::Token &token, long &nChar) |
1130 | 729k | { |
1131 | 729k | token = GreatWksTextInternal::Token(); |
1132 | 729k | MWAWInputStreamPtr &input= m_parserState->m_input; |
1133 | 729k | long pos=input->tell(); |
1134 | 729k | long endPos=pos+18; |
1135 | 729k | if (!input->checkPosition(endPos)) |
1136 | 0 | return false; |
1137 | | |
1138 | 729k | libmwaw::DebugStream f; |
1139 | 729k | token.m_type=static_cast<int>(input->readULong(1)); |
1140 | 729k | token.m_format=static_cast<int>(input->readULong(1)); |
1141 | 729k | nChar=input->readLong(4); |
1142 | 729k | if (token.m_type==0x15||token.m_type==0x16) |
1143 | 17.4k | token.m_date=static_cast<uint32_t>(input->readULong(4)); |
1144 | 712k | else if (token.m_type==4) { |
1145 | 12.5k | token.m_dataSize = input->readLong(4); |
1146 | 12.5k | float dim[2]; |
1147 | 25.1k | for (auto &d : dim) d = float(input->readLong(4))/65536.f; |
1148 | 12.5k | token.m_dim=MWAWVec2f(dim[0],dim[1]); // checkme |
1149 | 12.5k | } |
1150 | 729k | int nUnread=int(endPos-input->tell())/2; |
1151 | 4.99M | for (int i=0; i < nUnread; i++) { |
1152 | 4.26M | auto val=static_cast<int>(input->readLong(2)); |
1153 | 4.26M | if (val) f << "f" << i << "=" << val << ","; |
1154 | 4.26M | } |
1155 | 729k | token.m_extra=f.str(); |
1156 | | |
1157 | 729k | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
1158 | 729k | return true; |
1159 | 729k | } |
1160 | | |
1161 | | ////////////////////////////////////////////// |
1162 | | // send data |
1163 | | ////////////////////////////////////////////// |
1164 | | bool GreatWksText::sendMainText() |
1165 | 12.6k | { |
1166 | 12.6k | for (auto const &zone : m_state->m_zonesList) { |
1167 | 8.77k | if (!zone.isMain()) |
1168 | 2.38k | continue; |
1169 | 6.39k | return sendZone(zone); |
1170 | 8.77k | } |
1171 | 6.29k | return false; |
1172 | 12.6k | } |
1173 | | |
1174 | | bool GreatWksText::sendHF(int id) |
1175 | 2.26k | { |
1176 | 2.26k | for (auto const &zone : m_state->m_zonesList) { |
1177 | 2.26k | if (zone.isMain()) |
1178 | 0 | continue; |
1179 | 2.26k | if (id--==0) |
1180 | 2.26k | return sendZone(zone); |
1181 | 2.26k | } |
1182 | 0 | MWAW_DEBUG_MSG(("GreatWksText::sendHF: can not find a header/footer\n")); |
1183 | 0 | return false; |
1184 | 2.26k | } |
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 | 3.72k | { |
1202 | 3.72k | if (!listener) |
1203 | 1.13k | listener=m_parserState->getMainListener(); |
1204 | 3.72k | if (!listener || !listener->canWriteText()) { |
1205 | 0 | MWAW_DEBUG_MSG(("GreatWksText::sendSimpleTextbox: can not find a listener\n")); |
1206 | 0 | return false; |
1207 | 0 | } |
1208 | 3.72k | if (entry.length()<51) { |
1209 | 329 | MWAW_DEBUG_MSG(("GreatWksText::sendSimpleTextbox: the entry seems to short\n")); |
1210 | 329 | return false; |
1211 | 329 | } |
1212 | 3.39k | MWAWInputStreamPtr &input= m_parserState->m_input; |
1213 | 3.39k | long pos=entry.begin(); |
1214 | 3.39k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1215 | | |
1216 | 3.39k | libmwaw::DebugFile &ascFile = m_parserState->m_asciiFile; |
1217 | 3.39k | libmwaw::DebugStream f; |
1218 | 3.39k | f << "Entries(Texbox):"; |
1219 | 3.39k | bool ok = input->readLong(4)==0; |
1220 | 7.66k | for (int i=0; ok && i < 2; ++i) { |
1221 | 4.41k | auto val=static_cast<int>(input->readLong(1)); |
1222 | 4.41k | if (val==0) continue; |
1223 | 529 | if (val!=1) { |
1224 | 140 | f << "#fl" << i << "=" << val << ","; |
1225 | 140 | ok = false; |
1226 | 140 | break; |
1227 | 140 | } |
1228 | 389 | if (i==0) |
1229 | 221 | f << "smartquote,"; |
1230 | 168 | else |
1231 | 168 | f << "hidepict,"; |
1232 | 389 | } |
1233 | 3.39k | auto type=static_cast<int>(input->readLong(1)); |
1234 | 3.39k | if (ok) { |
1235 | 2.10k | if (type<0 || type>5) { |
1236 | 91 | f << "#type=" << type << ","; |
1237 | 91 | ok = false; |
1238 | 91 | } |
1239 | 2.01k | else if (type==1) |
1240 | 894 | f << "textbox[draw],"; |
1241 | 1.12k | else if (type!=2) |
1242 | 845 | f << "type=" << type << ","; |
1243 | 2.10k | } |
1244 | 3.39k | if (ok) ok=input->readLong(1)==1; |
1245 | | |
1246 | 3.39k | if (!ok) { |
1247 | 1.93k | MWAW_DEBUG_MSG(("GreatWksText::sendSimpleTextbox: the header seems bad\n")); |
1248 | 1.93k | f << "###"; |
1249 | 1.93k | ascFile.addPos(pos); |
1250 | 1.93k | ascFile.addNote(f.str().c_str()); |
1251 | 1.93k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1252 | 1.93k | return false; |
1253 | 1.93k | } |
1254 | 1.46k | MWAWFont font; |
1255 | 1.46k | font.setId(m_state->getFId(static_cast<int>(input->readULong(2)))); |
1256 | 1.46k | auto flag =static_cast<int>(input->readULong(2)); |
1257 | 1.46k | uint32_t flags=0; |
1258 | 1.46k | if (flag&0x1) flags |= MWAWFont::boldBit; |
1259 | 1.46k | if (flag&0x2) flags |= MWAWFont::italicBit; |
1260 | 1.46k | if (flag&0x4) font.setUnderlineStyle(MWAWFont::Line::Simple); |
1261 | 1.46k | if (flag&0x8) flags |= MWAWFont::embossBit; |
1262 | 1.46k | if (flag&0x10) flags |= MWAWFont::shadowBit; |
1263 | 1.46k | if (flag&0x20) font.setDeltaLetterSpacing(-1); |
1264 | 1.46k | if (flag&0x40) font.setDeltaLetterSpacing(1); |
1265 | 1.46k | if (flag&0x100) font.set(MWAWFont::Script::super100()); |
1266 | 1.46k | if (flag&0x200) font.set(MWAWFont::Script::sub100()); |
1267 | 1.46k | if (flag&0x800) font.setStrikeOutStyle(MWAWFont::Line::Simple); |
1268 | 1.46k | if (flag&0x2000) { |
1269 | 454 | font.setUnderlineStyle(MWAWFont::Line::Simple); |
1270 | 454 | font.setUnderlineType(MWAWFont::Line::Double); |
1271 | 454 | } |
1272 | 1.46k | flag &=0xD480; |
1273 | 1.46k | if (flag) f << "font[#fl]=" << std::hex << flag << std::dec << ","; |
1274 | 1.46k | font.setFlags(flags); |
1275 | 1.46k | font.setSize(float(input->readULong(2))); |
1276 | 1.46k | unsigned char color[3]; |
1277 | 4.38k | for (auto &c : color) c = static_cast<unsigned char>(input->readULong(2)>>8); |
1278 | 1.46k | font.setColor(MWAWColor(color[0],color[1],color[2])); |
1279 | 1.46k | f << "font=[" << font.getDebugString(m_parserState->m_fontConverter) << "],"; |
1280 | 1.46k | listener->setFont(font); |
1281 | | |
1282 | 1.46k | int val; |
1283 | 1.46k | f << "unkn=[" << std::hex; |
1284 | 10.2k | for (int i=0; i<6; i++) { // junk ? |
1285 | 8.77k | val=static_cast<int>(input->readULong(2)); |
1286 | 8.77k | if (val) |
1287 | 5.15k | f << val << ","; |
1288 | 3.62k | else |
1289 | 3.62k | f << "_,"; |
1290 | 8.77k | } |
1291 | 1.46k | f << std::dec << "],"; |
1292 | 1.46k | MWAWParagraph para; |
1293 | 1.46k | val=static_cast<int>(input->readLong(2)); |
1294 | 1.46k | switch (val) { |
1295 | 911 | case 0: |
1296 | 911 | break; |
1297 | 30 | case 1: |
1298 | 30 | para.m_justify = MWAWParagraph::JustificationCenter; |
1299 | 30 | break; |
1300 | 31 | case 2: |
1301 | 31 | para.m_justify = MWAWParagraph::JustificationRight ; |
1302 | 31 | break; |
1303 | 16 | case 3: |
1304 | 16 | para.m_justify = MWAWParagraph::JustificationFull; |
1305 | 16 | break; |
1306 | 475 | default: |
1307 | 475 | f << "#align" << val << ","; |
1308 | 475 | break; |
1309 | 1.46k | } |
1310 | 1.46k | f << para <<","; |
1311 | 1.46k | listener->setParagraph(para); |
1312 | 1.46k | double dim[4]; |
1313 | 5.85k | for (auto &d : dim) d=double(input->readLong(4))/65536.; |
1314 | 1.46k | f << "dim=" << dim[1] << "x" << dim[0] << "<->" << dim[3] << "x" << dim[2] << "," ; |
1315 | 1.46k | auto fSz=static_cast<int>(input->readULong(1)); |
1316 | 1.46k | if (50+fSz > entry.length()) { |
1317 | 74 | MWAW_DEBUG_MSG(("GreatWksText::sendSimpleTextbox: the text size seems too big\n")); |
1318 | 74 | f << "###"; |
1319 | 74 | ascFile.addPos(pos); |
1320 | 74 | ascFile.addNote(f.str().c_str()); |
1321 | 74 | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1322 | 74 | return false; |
1323 | 74 | } |
1324 | | |
1325 | 1.38k | ascFile.addPos(pos); |
1326 | 1.38k | ascFile.addNote(f.str().c_str()); |
1327 | | |
1328 | 1.38k | pos=input->tell(); |
1329 | 1.38k | f.str(""); |
1330 | 1.38k | f << "Entries(Text):"; |
1331 | 88.3k | for (int i=0; i < fSz; ++i) { |
1332 | 86.9k | auto c = char(input->readULong(1)); |
1333 | 86.9k | f << c; |
1334 | 86.9k | switch (c) { |
1335 | 7.42k | case 0x9: |
1336 | 7.42k | listener->insertTab(); |
1337 | 7.42k | break; |
1338 | 17.8k | case 0xd: |
1339 | 17.8k | listener->insertEOL(); |
1340 | 17.8k | break; |
1341 | 61.6k | default: |
1342 | 61.6k | listener->insertCharacter(static_cast<unsigned char>(c)); |
1343 | 61.6k | break; |
1344 | 86.9k | } |
1345 | 86.9k | } |
1346 | 1.38k | input->seek(entry.end(), librevenge::RVNG_SEEK_SET); |
1347 | 1.38k | ascFile.addPos(pos); |
1348 | 1.38k | ascFile.addNote(f.str().c_str()); |
1349 | 1.38k | return true; |
1350 | 1.38k | } |
1351 | | |
1352 | | bool GreatWksText::sendZone(GreatWksTextInternal::Zone const &zone, MWAWListenerPtr listener) |
1353 | 11.3k | { |
1354 | 11.3k | bool inLocalZone=false; |
1355 | 11.3k | if (listener) |
1356 | 1.11k | inLocalZone=true; |
1357 | 10.1k | else |
1358 | 10.1k | listener=m_parserState->getMainListener(); |
1359 | 11.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 | 11.3k | bool isMain = zone.isMain(); |
1364 | 11.3k | int actPage = 1, actCol = 0, numCol=1; |
1365 | 11.3k | if (isMain && !listener->canOpenSectionAddBreak()) { |
1366 | 4 | MWAW_DEBUG_MSG(("GreatWksText::sendZone: in a main zone, but can not open section\n")); |
1367 | 4 | isMain = false; |
1368 | 4 | } |
1369 | 11.3k | else if (isMain) { |
1370 | 6.39k | m_document.newPage(1); |
1371 | 6.39k | MWAWSection sec=m_document.getMainSection(); |
1372 | 6.39k | numCol = sec.numColumns(); |
1373 | 6.39k | if (numCol>1) { |
1374 | 4.12k | if (listener->isSectionOpened()) |
1375 | 0 | listener->closeSection(); |
1376 | 4.12k | listener->openSection(sec); |
1377 | 4.12k | } |
1378 | 6.39k | } |
1379 | 11.3k | if (!zone.m_textEntry.valid()) |
1380 | 262 | return true; |
1381 | 11.0k | MWAWInputStreamPtr &input= m_parserState->m_input; |
1382 | 11.0k | libmwaw::DebugFile &ascFile = m_parserState->m_asciiFile; |
1383 | 11.0k | libmwaw::DebugStream f; |
1384 | 11.0k | f << "Entries(Text):"; |
1385 | 11.0k | zone.m_parsed=true; |
1386 | 11.0k | long pos = zone.m_textEntry.begin(), endPos = zone.m_textEntry.end(); |
1387 | 11.0k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1388 | | |
1389 | 11.0k | long cPos=0; |
1390 | 1.95M | while (1) { |
1391 | 1.95M | long actPos = input->tell(); |
1392 | 1.95M | bool done = input->isEnd() || actPos==endPos; |
1393 | | |
1394 | 1.95M | char c = done ? char(0) : char(input->readULong(1)); |
1395 | 1.95M | if (pos!=actPos && (c==0xd || done)) { |
1396 | 65.9k | ascFile.addPos(pos); |
1397 | 65.9k | ascFile.addNote(f.str().c_str()); |
1398 | 65.9k | f.str(""); |
1399 | 65.9k | f << "Text:"; |
1400 | 65.9k | pos = actPos+1; |
1401 | 65.9k | } |
1402 | 1.95M | if (done) break; |
1403 | | |
1404 | 1.94M | auto pIt=zone.m_posPLCMap.find(cPos); |
1405 | 1.94M | GreatWksTextInternal::Token token; |
1406 | 2.11M | while (pIt!=zone.m_posPLCMap.end() && pIt->first==cPos) { |
1407 | 175k | GreatWksTextInternal::PLC const &plc=(pIt++)->second; |
1408 | 175k | f << "[" << plc << "]"; |
1409 | 175k | switch (plc.m_type) { |
1410 | 49.3k | case GreatWksTextInternal::P_Font: |
1411 | 49.3k | if (plc.m_id < 0 || plc.m_id >= static_cast<int>(zone.m_fontList.size())) { |
1412 | 4.77k | MWAW_DEBUG_MSG(("GreatWksText::sendZone: can not find font %d\n", plc.m_id)); |
1413 | 4.77k | break; |
1414 | 4.77k | } |
1415 | 44.5k | listener->setFont(zone.m_fontList[size_t(plc.m_id)]); |
1416 | 44.5k | break; |
1417 | 50.3k | case GreatWksTextInternal::P_Ruler: |
1418 | 50.3k | if (plc.m_id < 0 || plc.m_id >= static_cast<int>(zone.m_rulerList.size())) { |
1419 | 4.36k | MWAW_DEBUG_MSG(("GreatWksText::sendZone: can not find ruler %d\n", plc.m_id)); |
1420 | 4.36k | break; |
1421 | 4.36k | } |
1422 | 45.9k | listener->setParagraph(zone.m_rulerList[size_t(plc.m_id)]); |
1423 | 45.9k | break; |
1424 | 28.7k | case GreatWksTextInternal::P_Token: |
1425 | 28.7k | 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 | 28.7k | token=zone.m_tokenList[size_t(plc.m_id)]; |
1430 | 28.7k | break; |
1431 | 47.0k | case GreatWksTextInternal::P_Page: |
1432 | 47.0k | case GreatWksTextInternal::P_Unknown: |
1433 | | #if !defined(__clang__) |
1434 | | default: |
1435 | | #endif |
1436 | 47.0k | break; |
1437 | 175k | } |
1438 | 175k | } |
1439 | 1.94M | if (c!=0xd) f << c; |
1440 | 1.94M | switch (c) { |
1441 | 39.3k | case 0x4: { |
1442 | 39.3k | f << "[pict]"; |
1443 | 39.3k | if (token.m_type!=4 || !token.m_pictEntry.valid()) { |
1444 | 39.2k | MWAW_DEBUG_MSG(("GreatWksText::sendZone: can not find a picture\n")); |
1445 | 39.2k | f << "###"; |
1446 | 39.2k | break; |
1447 | 39.2k | } |
1448 | 35 | 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 | 35 | MWAWPosition pictPos(MWAWVec2f(0,0), token.m_dim, librevenge::RVNG_POINT); |
1453 | 35 | pictPos.setRelativePosition(MWAWPosition::Char, MWAWPosition::XLeft, MWAWPosition::YBottom); |
1454 | 35 | m_document.sendPicture(token.m_pictEntry, pictPos); |
1455 | 35 | break; |
1456 | 35 | } |
1457 | 17.8k | case 0x9: |
1458 | 17.8k | listener->insertTab(); |
1459 | 17.8k | break; |
1460 | 19.9k | case 0xb: |
1461 | 19.9k | f << "[colbreak]"; |
1462 | 19.9k | if (!isMain) { |
1463 | 2.34k | MWAW_DEBUG_MSG(("GreatWksText::sendZone: find column break in auxilliary block\n")); |
1464 | 2.34k | break; |
1465 | 2.34k | } |
1466 | 17.6k | if (actCol < numCol-1 && numCol > 1) { |
1467 | 12.8k | listener->insertBreak(MWAWListener::ColumnBreak); |
1468 | 12.8k | actCol++; |
1469 | 12.8k | } |
1470 | 4.71k | else { |
1471 | 4.71k | actCol = 0; |
1472 | 4.71k | m_document.newPage(++actPage); |
1473 | 4.71k | } |
1474 | 17.6k | break; |
1475 | 24.4k | case 0xc: |
1476 | 24.4k | f << "[pagebreak]"; |
1477 | 24.4k | if (!isMain) { |
1478 | 2.02k | f << "###"; |
1479 | 2.02k | MWAW_DEBUG_MSG(("GreatWksText::sendZone: find page break in auxilliary zone\n")); |
1480 | 2.02k | break; |
1481 | 2.02k | } |
1482 | 22.4k | m_document.newPage(++actPage); |
1483 | 22.4k | actCol = 0; |
1484 | 22.4k | break; |
1485 | 77.5k | case 0xd: |
1486 | 77.5k | listener->insertEOL(); |
1487 | 77.5k | break; |
1488 | 43.1k | case 2: // page number |
1489 | 56.9k | case 0x15: // date |
1490 | 63.8k | case 0x16: // time |
1491 | 63.8k | if (token.sendTo(*listener)) |
1492 | 779 | break; |
1493 | 63.0k | f << "###"; |
1494 | 63.0k | MWAW_DEBUG_MSG(("GreatWksText::sendZone: can not send token\n")); |
1495 | 63.0k | break; |
1496 | 1.70M | default: |
1497 | 1.70M | listener->insertCharacter(static_cast<unsigned char>(c)); |
1498 | 1.70M | break; |
1499 | 1.94M | } |
1500 | 1.94M | cPos++; |
1501 | 1.94M | } |
1502 | 11.0k | return true; |
1503 | 11.0k | } |
1504 | | // vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: |