/src/libmwaw/src/lib/HanMacWrdJText.cxx
Line | Count | Source |
1 | | /* -*- Mode: C++; c-default-style: "k&r"; indent-tabs-mode: nil; tab-width: 2; c-basic-offset: 2 -*- */ |
2 | | |
3 | | /* libmwaw |
4 | | * Version: MPL 2.0 / LGPLv2+ |
5 | | * |
6 | | * The contents of this file are subject to the Mozilla Public License Version |
7 | | * 2.0 (the "License"); you may not use this file except in compliance with |
8 | | * the License or as specified alternatively below. You may obtain a copy of |
9 | | * the License at http://www.mozilla.org/MPL/ |
10 | | * |
11 | | * Software distributed under the License is distributed on an "AS IS" basis, |
12 | | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
13 | | * for the specific language governing rights and limitations under the |
14 | | * License. |
15 | | * |
16 | | * Major Contributor(s): |
17 | | * Copyright (C) 2002 William Lachance (wrlach@gmail.com) |
18 | | * Copyright (C) 2002,2004 Marc Maurer (uwog@uwog.net) |
19 | | * Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba@bluewin.ch) |
20 | | * Copyright (C) 2006, 2007 Andrew Ziem |
21 | | * Copyright (C) 2011, 2012 Alonso Laurent (alonso@loria.fr) |
22 | | * |
23 | | * |
24 | | * All Rights Reserved. |
25 | | * |
26 | | * For minor contributions see the git repository. |
27 | | * |
28 | | * Alternatively, the contents of this file may be used under the terms of |
29 | | * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"), |
30 | | * in which case the provisions of the LGPLv2+ are applicable |
31 | | * instead of those above. |
32 | | */ |
33 | | |
34 | | #include <iomanip> |
35 | | #include <iostream> |
36 | | #include <limits> |
37 | | #include <map> |
38 | | #include <sstream> |
39 | | |
40 | | #include <librevenge/librevenge.h> |
41 | | |
42 | | #include "MWAWTextListener.hxx" |
43 | | #include "MWAWDebug.hxx" |
44 | | #include "MWAWFont.hxx" |
45 | | #include "MWAWFontConverter.hxx" |
46 | | #include "MWAWGraphicListener.hxx" |
47 | | #include "MWAWParagraph.hxx" |
48 | | #include "MWAWPosition.hxx" |
49 | | #include "MWAWRSRCParser.hxx" |
50 | | #include "MWAWSection.hxx" |
51 | | #include "MWAWSubDocument.hxx" |
52 | | |
53 | | #include "HanMacWrdJParser.hxx" |
54 | | |
55 | | #include "HanMacWrdJText.hxx" |
56 | | |
57 | | /** Internal: the structures of a HanMacWrdJText */ |
58 | | namespace HanMacWrdJTextInternal |
59 | | { |
60 | | /** different PLC types */ |
61 | | enum PLCType { CHAR=0, RULER, LINE, TOKEN, Unknown}; |
62 | | /** Internal and low level: the PLC different types and their structures of a HanMacWrdJText */ |
63 | | struct PLC { |
64 | | //! constructor |
65 | | explicit PLC(PLCType w= Unknown, int id=0) |
66 | 195k | : m_type(w) |
67 | 195k | , m_id(id) |
68 | 195k | , m_extra("") {} |
69 | | //! operator<< |
70 | | friend std::ostream &operator<<(std::ostream &o, PLC const &plc) |
71 | 0 | { |
72 | 0 | switch (plc.m_type) { |
73 | 0 | case CHAR: |
74 | 0 | o << "F" << plc.m_id << ","; |
75 | 0 | break; |
76 | 0 | case LINE: |
77 | 0 | o << "L" << plc.m_id << ","; |
78 | 0 | break; |
79 | 0 | case RULER: |
80 | 0 | o << "R" << plc.m_id << ","; |
81 | 0 | break; |
82 | 0 | case TOKEN: |
83 | 0 | o << "T" << plc.m_id << ","; |
84 | 0 | break; |
85 | 0 | case Unknown: |
86 | 0 | #if !defined(__clang__) |
87 | 0 | default: |
88 | 0 | #endif |
89 | 0 | o << "#unknown" << plc.m_id << ","; |
90 | 0 | } |
91 | 0 | o << plc.m_extra; |
92 | 0 | return o; |
93 | 0 | } |
94 | | //! PLC type |
95 | | PLCType m_type; |
96 | | //! the indentificator |
97 | | int m_id; |
98 | | //! extra data |
99 | | std::string m_extra; |
100 | | }; |
101 | | |
102 | | /** Internal: class to store a token of a HanMacWrdJText */ |
103 | | struct Token { |
104 | | //! constructor |
105 | | Token() |
106 | 2.68k | : m_type(0) |
107 | 2.68k | , m_id(0) |
108 | 2.68k | , m_localId(0) |
109 | 2.68k | , m_bookmark("") |
110 | 2.68k | , m_length(0) |
111 | 2.68k | , m_extra("") |
112 | 2.68k | { |
113 | 2.68k | } |
114 | | //! operator<< |
115 | | friend std::ostream &operator<<(std::ostream &o, Token const &tk) |
116 | 0 | { |
117 | 0 | switch (tk.m_type) { // checkme |
118 | 0 | case 0: |
119 | 0 | break; |
120 | 0 | case 1: |
121 | 0 | o << "field,"; |
122 | 0 | break; |
123 | 0 | case 2: |
124 | 0 | o << "footnote,"; |
125 | 0 | break; |
126 | 0 | case 8: |
127 | 0 | o << "toc,"; |
128 | 0 | break; |
129 | 0 | case 0x20: |
130 | 0 | o << "bookmark,"; |
131 | 0 | break; |
132 | 0 | default: |
133 | 0 | o << "#type=" << tk.m_type << ","; |
134 | 0 | break; |
135 | 0 | } |
136 | 0 | if (tk.m_bookmark.length()) |
137 | 0 | o << "text[bookmark]=" << tk.m_bookmark << ","; |
138 | 0 | if (tk.m_id) |
139 | 0 | o << "zId=" << std::hex << tk.m_id << std::dec << ","; |
140 | 0 | if (tk.m_localId) |
141 | 0 | o << "id=" << tk.m_localId << ","; |
142 | 0 | if (tk.m_length) |
143 | 0 | o << "length=" << tk.m_length << ","; |
144 | 0 | o << tk.m_extra; |
145 | 0 | return o; |
146 | 0 | } |
147 | | //! the token type |
148 | | int m_type; |
149 | | //! the id ( to be send) |
150 | | long m_id; |
151 | | //! the local id |
152 | | int m_localId; |
153 | | //! the bookmark string |
154 | | std::string m_bookmark; |
155 | | //! the token length in caller text |
156 | | int m_length; |
157 | | //! extra string string |
158 | | std::string m_extra; |
159 | | }; |
160 | | |
161 | | /** Internal: class to store a section of a HanMacWrdJText */ |
162 | | struct Section { |
163 | | //! constructor |
164 | | Section() |
165 | 4.01k | : m_numCols(1) |
166 | 4.01k | , m_colWidth() |
167 | 4.01k | , m_colSep() |
168 | 4.01k | , m_id(0) |
169 | 4.01k | , m_extra("") |
170 | 4.01k | { |
171 | 4.01k | } |
172 | | //! returns a MWAWSection |
173 | | MWAWSection getSection() const |
174 | 2.36k | { |
175 | 2.36k | MWAWSection sec; |
176 | 2.36k | if (m_colWidth.size()==0) { |
177 | 0 | MWAW_DEBUG_MSG(("HanMacWrdJTextInternal::Section:getSection can not find any width\n")); |
178 | 0 | return sec; |
179 | 0 | } |
180 | 2.36k | if (m_numCols <= 1) |
181 | 1.59k | return sec; |
182 | 771 | bool hasSep = m_colWidth.size()==m_colSep.size(); |
183 | 771 | sec.m_columns.resize(size_t(m_numCols)); |
184 | 771 | if (m_colWidth.size()==size_t(m_numCols)) { |
185 | 156 | for (size_t c=0; c < size_t(m_numCols); c++) { |
186 | 116 | sec.m_columns[c].m_width = double(m_colWidth[c]); |
187 | 116 | sec.m_columns[c].m_widthUnit = librevenge::RVNG_POINT; |
188 | 116 | if (!hasSep) continue; |
189 | 116 | sec.m_columns[c].m_margins[libmwaw::Left]= |
190 | 116 | sec.m_columns[c].m_margins[libmwaw::Right]=double(m_colSep[c])/2.0/72.; |
191 | 116 | } |
192 | 40 | } |
193 | 731 | else { |
194 | 731 | if (m_colWidth.size()>1) { |
195 | 0 | MWAW_DEBUG_MSG(("HanMacWrdJTextInternal::Section:getSection colWidth is not coherent with numCols\n")); |
196 | 0 | } |
197 | 731 | sec.setColumns(m_numCols, double(m_colWidth[0]), librevenge::RVNG_POINT, |
198 | 731 | hasSep ? double(m_colSep[0])/72. : 0); |
199 | 731 | } |
200 | 771 | return sec; |
201 | 2.36k | } |
202 | | //! operator<< |
203 | | friend std::ostream &operator<<(std::ostream &o, Section const &sec) |
204 | 0 | { |
205 | 0 | if (sec.m_numCols!=1) |
206 | 0 | o << "numCols=" << sec.m_numCols << ","; |
207 | 0 | if (sec.m_colWidth.size()) { |
208 | 0 | o << "colWidth=["; |
209 | 0 | for (size_t i = 0; i < sec.m_colWidth.size(); i++) |
210 | 0 | o << sec.m_colWidth[i] << ":" << sec.m_colSep[i] << ","; |
211 | 0 | o << "],"; |
212 | 0 | } |
213 | 0 | if (sec.m_id) |
214 | 0 | o << "id=" << std::hex << sec.m_id << std::dec << ","; |
215 | 0 | o << sec.m_extra; |
216 | 0 | return o; |
217 | 0 | } |
218 | | //! the number of column |
219 | | int m_numCols; |
220 | | //! the columns width |
221 | | std::vector<double> m_colWidth; |
222 | | //! the columns separator width |
223 | | std::vector<double> m_colSep; |
224 | | //! the id |
225 | | long m_id; |
226 | | //! extra string string |
227 | | std::string m_extra; |
228 | | }; |
229 | | |
230 | | //! Internal: a struct used to store a text zone |
231 | | struct TextZone { |
232 | | //! enum used to define the zone type |
233 | | enum Type { T_Main=0, T_Header=1, T_Footer=2, T_Footnote=3, T_Textbox=4, |
234 | | T_Table=9, T_Comment=10, T_Unknown |
235 | | }; |
236 | | //! constructor |
237 | | TextZone() |
238 | 152k | : m_type(T_Unknown) |
239 | 152k | , m_entry() |
240 | 152k | , m_id(0) |
241 | 152k | , m_PLCMap() |
242 | 152k | , m_tokenList() |
243 | 152k | , m_parsed(false) |
244 | 152k | { |
245 | 152k | } |
246 | | |
247 | | //! the zone type |
248 | | Type m_type; |
249 | | //! the main entry |
250 | | MWAWEntry m_entry; |
251 | | //! the file zone id |
252 | | long m_id; |
253 | | //! the plc map |
254 | | std::multimap<long, PLC> m_PLCMap; |
255 | | //! the tokens list |
256 | | std::vector<Token> m_tokenList; |
257 | | |
258 | | //! true if the zone is sended |
259 | | mutable bool m_parsed; |
260 | | }; |
261 | | |
262 | | |
263 | | /** Internal: class to store the paragraph properties of a HanMacWrdJText */ |
264 | | struct Paragraph final : public MWAWParagraph { |
265 | | //! Constructor |
266 | | Paragraph() |
267 | 105k | : MWAWParagraph() |
268 | 105k | , m_type(0) |
269 | 105k | , m_addPageBreak(false) |
270 | 105k | { |
271 | 105k | } |
272 | 113k | Paragraph(Paragraph const &)=default; |
273 | | Paragraph &operator=(Paragraph const &)=default; |
274 | 52.9k | Paragraph &operator=(Paragraph &&)=default; |
275 | | //! destructor |
276 | | ~Paragraph() final; |
277 | | //! operator<< |
278 | | friend std::ostream &operator<<(std::ostream &o, Paragraph const &ind) |
279 | 0 | { |
280 | 0 | switch (ind.m_type) { |
281 | 0 | case 0: |
282 | 0 | break; |
283 | 0 | case 1: |
284 | 0 | o << "header,"; |
285 | 0 | break; |
286 | 0 | case 2: |
287 | 0 | o << "footer,"; |
288 | 0 | break; |
289 | 0 | case 5: |
290 | 0 | o << "footnote,"; |
291 | 0 | break; |
292 | 0 | default: |
293 | 0 | o << "#type=" << ind.m_type << ","; |
294 | 0 | break; |
295 | 0 | } |
296 | 0 | o << static_cast<MWAWParagraph const &>(ind) << ","; |
297 | 0 | if (ind.m_addPageBreak) o << "pageBreakBef,"; |
298 | 0 | return o; |
299 | 0 | } |
300 | | //! the type |
301 | | int m_type; |
302 | | //! flag to store a force page break |
303 | | bool m_addPageBreak; |
304 | | }; |
305 | | |
306 | | Paragraph::~Paragraph() |
307 | 219k | { |
308 | 219k | } |
309 | | |
310 | | //////////////////////////////////////// |
311 | | //! Internal: the state of a HanMacWrdJText |
312 | | struct State { |
313 | | //! constructor |
314 | | State() |
315 | 35.0k | : m_version(-1) |
316 | 35.0k | , m_fontList() |
317 | 35.0k | , m_paragraphList() |
318 | 35.0k | , m_sectionList() |
319 | 35.0k | , m_ftnTextId(0) |
320 | 35.0k | , m_ftnFirstPosList() |
321 | 35.0k | , m_textZoneList() |
322 | 35.0k | , m_idTextZoneMap() |
323 | 35.0k | , m_numPages(-1) |
324 | 35.0k | , m_actualPage(0) |
325 | 35.0k | { |
326 | 35.0k | } |
327 | | //! the file version |
328 | | mutable int m_version; |
329 | | /** the font list */ |
330 | | std::vector<MWAWFont> m_fontList; |
331 | | //! the list of paragraph |
332 | | std::vector<Paragraph> m_paragraphList; |
333 | | //! the list of section |
334 | | std::vector<Section> m_sectionList; |
335 | | //! the footnote zone id; |
336 | | long m_ftnTextId; |
337 | | //! the footnote begin positions |
338 | | std::vector<long> m_ftnFirstPosList; |
339 | | //! the list of text zone |
340 | | std::vector<TextZone> m_textZoneList; |
341 | | //! a map textId -> id in m_textZoneList |
342 | | std::map<long, int> m_idTextZoneMap; |
343 | | int m_numPages /* the number of pages */, m_actualPage /* the actual page */; |
344 | | }; |
345 | | |
346 | | //////////////////////////////////////// |
347 | | //! Internal: the subdocument of a HanMacWrdJText |
348 | | class SubDocument final : public MWAWSubDocument |
349 | | { |
350 | | protected: |
351 | | //! the subdocument type |
352 | | enum Type { S_TextZone, S_String }; |
353 | | public: |
354 | | //! constructor to call a textzone |
355 | | SubDocument(HanMacWrdJText &pars, MWAWInputStreamPtr const &input, long id, long cPos=0) |
356 | 1.79k | : MWAWSubDocument(pars.m_mainParser, input, MWAWEntry()) |
357 | 1.79k | , m_type(S_TextZone) |
358 | 1.79k | , m_textParser(&pars) |
359 | 1.79k | , m_id(id) |
360 | 1.79k | , m_cPos(cPos) |
361 | 1.79k | , m_bookmark("") {} |
362 | | //! constructor to send a string |
363 | | SubDocument(HanMacWrdJText &pars, MWAWInputStreamPtr const &input, std::string const &text) |
364 | 8 | : MWAWSubDocument(pars.m_mainParser, input, MWAWEntry()) |
365 | 8 | , m_type(S_String) |
366 | 8 | , m_textParser(&pars) |
367 | 8 | , m_id(0) |
368 | 8 | , m_cPos(0) |
369 | 8 | , m_bookmark(text) {} |
370 | | |
371 | | |
372 | | //! destructor |
373 | 1.80k | ~SubDocument() final {} |
374 | | |
375 | | //! operator!= |
376 | | bool operator!=(MWAWSubDocument const &doc) const final; |
377 | | |
378 | | //! the parser function |
379 | | void parse(MWAWListenerPtr &listener, libmwaw::SubDocumentType type) final; |
380 | | |
381 | | protected: |
382 | | /** the subdocument type */ |
383 | | Type m_type; |
384 | | /** the text parser */ |
385 | | HanMacWrdJText *m_textParser; |
386 | | //! the subdocument id |
387 | | long m_id; |
388 | | //! the first charecter position |
389 | | long m_cPos; |
390 | | //! the bookmark string |
391 | | std::string m_bookmark; |
392 | | private: |
393 | | SubDocument(SubDocument const &orig) = delete; |
394 | | SubDocument &operator=(SubDocument const &orig) = delete; |
395 | | }; |
396 | | |
397 | | void SubDocument::parse(MWAWListenerPtr &listener, libmwaw::SubDocumentType /*type*/) |
398 | 1.78k | { |
399 | 1.78k | if (!listener.get()) { |
400 | 0 | MWAW_DEBUG_MSG(("HanMacWrdJTextInternal::SubDocument::parse: no listener\n")); |
401 | 0 | return; |
402 | 0 | } |
403 | | |
404 | 1.78k | if (m_type==S_String) { |
405 | 8 | for (auto &c : m_bookmark) |
406 | 0 | listener->insertCharacter(static_cast<unsigned char>(c)); |
407 | 8 | return; |
408 | 8 | } |
409 | 1.77k | if (!m_textParser) { |
410 | 0 | MWAW_DEBUG_MSG(("HanMacWrdJTextInternal::SubDocument::parse: no parser\n")); |
411 | 0 | return; |
412 | 0 | } |
413 | 1.77k | long pos = m_input->tell(); |
414 | 1.77k | m_textParser->sendText(m_id, m_cPos); |
415 | 1.77k | m_input->seek(pos, librevenge::RVNG_SEEK_SET); |
416 | 1.77k | } |
417 | | |
418 | | bool SubDocument::operator!=(MWAWSubDocument const &doc) const |
419 | 14 | { |
420 | 14 | if (MWAWSubDocument::operator!=(doc)) return true; |
421 | 0 | auto const *sDoc = dynamic_cast<SubDocument const *>(&doc); |
422 | 0 | if (!sDoc) return true; |
423 | 0 | if (m_textParser != sDoc->m_textParser) return true; |
424 | 0 | if (m_type != sDoc->m_type) return true; |
425 | 0 | if (m_id != sDoc->m_id) return true; |
426 | 0 | if (m_cPos != sDoc->m_cPos) return true; |
427 | 0 | if (m_bookmark != sDoc->m_bookmark) return true; |
428 | 0 | return false; |
429 | 0 | } |
430 | | } |
431 | | |
432 | | //////////////////////////////////////////////////////////// |
433 | | // constructor/destructor, ... |
434 | | //////////////////////////////////////////////////////////// |
435 | | HanMacWrdJText::HanMacWrdJText(HanMacWrdJParser &parser) |
436 | 35.0k | : m_parserState(parser.getParserState()) |
437 | 35.0k | , m_state(new HanMacWrdJTextInternal::State) |
438 | 35.0k | , m_mainParser(&parser) |
439 | 35.0k | { |
440 | 35.0k | } |
441 | | |
442 | | HanMacWrdJText::~HanMacWrdJText() |
443 | 35.0k | { |
444 | 35.0k | } |
445 | | |
446 | | int HanMacWrdJText::version() const |
447 | 0 | { |
448 | 0 | if (m_state->m_version < 0) |
449 | 0 | m_state->m_version = m_parserState->m_version; |
450 | 0 | return m_state->m_version; |
451 | 0 | } |
452 | | |
453 | | int HanMacWrdJText::numPages() const |
454 | 12.5k | { |
455 | 12.5k | int nPages = 1; |
456 | 12.5k | for (auto const &zone : m_state->m_textZoneList) { |
457 | 8.68k | if (zone.m_type != HanMacWrdJTextInternal::TextZone::T_Main) |
458 | 2.30k | continue; |
459 | 6.38k | nPages = const_cast<HanMacWrdJText *>(this)->computeNumPages(zone); |
460 | 6.38k | break; |
461 | 8.68k | } |
462 | | // fixme: compute the number of page |
463 | 12.5k | m_state->m_numPages = nPages; |
464 | 12.5k | return nPages; |
465 | 12.5k | } |
466 | | |
467 | | std::vector<long> HanMacWrdJText::getTokenIdList() const |
468 | 12.5k | { |
469 | 12.5k | std::vector<long> res; |
470 | 151k | for (auto const &zone : m_state->m_textZoneList) { |
471 | 151k | for (auto const &token : zone.m_tokenList) { |
472 | 2.67k | if (token.m_type==1) |
473 | 28 | res.push_back(token.m_id); |
474 | 2.67k | } |
475 | 151k | } |
476 | 12.5k | return res; |
477 | 12.5k | } |
478 | | |
479 | | //////////////////////////////////////////////////////////// |
480 | | // Intermediate level |
481 | | //////////////////////////////////////////////////////////// |
482 | | |
483 | | //////////////////////////////////////////////////////////// |
484 | | // Text |
485 | | //////////////////////////////////////////////////////////// |
486 | | bool HanMacWrdJText::canSendTextAsGraphic(long id, long cPos) |
487 | 26 | { |
488 | 26 | if (m_state->m_idTextZoneMap.find(id)==m_state->m_idTextZoneMap.end()) { |
489 | 26 | MWAW_DEBUG_MSG(("HanMacWrdJText::canSendTextAsGraphic: can not find text zone with id %lx\n", static_cast<long unsigned int>(id))); |
490 | 26 | return false; |
491 | 26 | } |
492 | 0 | int zId = m_state->m_idTextZoneMap.find(id)->second; |
493 | 0 | if (zId < 0 || zId >= static_cast<int>(m_state->m_textZoneList.size())) |
494 | 0 | return false; |
495 | 0 | return canSendTextAsGraphic(m_state->m_textZoneList[size_t(zId)], cPos); |
496 | 0 | } |
497 | | |
498 | | bool HanMacWrdJText::canSendTextAsGraphic(HanMacWrdJTextInternal::TextZone const &zone, long cPos) |
499 | 0 | { |
500 | 0 | if (!zone.m_entry.valid()) |
501 | 0 | return false; |
502 | | |
503 | 0 | auto plcIt=zone.m_PLCMap.find(cPos); |
504 | 0 | while (plcIt != zone.m_PLCMap.end() && plcIt->first < cPos) |
505 | 0 | ++plcIt; |
506 | 0 | while (plcIt != zone.m_PLCMap.end()) { |
507 | 0 | auto const &plc = plcIt++->second; |
508 | 0 | if (plc.m_type!=HanMacWrdJTextInternal::TOKEN) continue; |
509 | 0 | if (plc.m_id < 0 || plc.m_id >= static_cast<int>(zone.m_tokenList.size())) |
510 | 0 | continue; |
511 | 0 | auto const &tkn=zone.m_tokenList[size_t(plc.m_id)]; |
512 | 0 | switch (tkn.m_type) { |
513 | 0 | case 1: |
514 | 0 | case 2: |
515 | 0 | case 0x20: |
516 | 0 | return false; |
517 | 0 | default: |
518 | 0 | break; |
519 | 0 | } |
520 | 0 | } |
521 | 0 | return true; |
522 | 0 | } |
523 | | |
524 | | bool HanMacWrdJText::sendText(long id, long cPos, MWAWListenerPtr listener) |
525 | 14.0k | { |
526 | 14.0k | if (m_state->m_idTextZoneMap.find(id)==m_state->m_idTextZoneMap.end()) { |
527 | 3.04k | MWAW_DEBUG_MSG(("HanMacWrdJText::sendText: can not find text zone with id %lx\n", static_cast<long unsigned int>(id))); |
528 | 3.04k | return false; |
529 | 3.04k | } |
530 | 11.0k | int zId = m_state->m_idTextZoneMap.find(id)->second; |
531 | 11.0k | if (zId < 0 || zId >= static_cast<int>(m_state->m_textZoneList.size())) |
532 | 0 | return false; |
533 | 11.0k | return sendText(m_state->m_textZoneList[size_t(zId)], cPos, listener); |
534 | 11.0k | } |
535 | | |
536 | | bool HanMacWrdJText::sendMainText() |
537 | 12.5k | { |
538 | 12.5k | for (auto &zone : m_state->m_textZoneList) { |
539 | 8.68k | if (zone.m_type != HanMacWrdJTextInternal::TextZone::T_Main) |
540 | 2.30k | continue; |
541 | 6.38k | sendText(zone,0); |
542 | 6.38k | return true; |
543 | 8.68k | } |
544 | 6.12k | MWAW_DEBUG_MSG(("HanMacWrdJText::sendText: can not find the main zone\n")); |
545 | 6.12k | return false; |
546 | 12.5k | } |
547 | | |
548 | | |
549 | | bool HanMacWrdJText::sendText(HanMacWrdJTextInternal::TextZone const &zone, long fPos, MWAWListenerPtr listener) |
550 | 17.3k | { |
551 | 17.3k | if (!zone.m_entry.valid()) { |
552 | 3.17k | MWAW_DEBUG_MSG(("HanMacWrdJText::sendText: call without entry\n")); |
553 | 3.17k | return false; |
554 | 3.17k | } |
555 | 14.2k | bool withLocalListener=false; |
556 | 14.2k | if (listener) |
557 | 0 | withLocalListener=true; |
558 | 14.2k | else |
559 | 14.2k | listener=m_parserState->m_textListener; |
560 | 14.2k | if (!listener) { |
561 | 0 | MWAW_DEBUG_MSG(("HanMacWrdJText::sendText: can not find the listener\n")); |
562 | 0 | return false; |
563 | 0 | } |
564 | | |
565 | 14.2k | zone.m_parsed=true; |
566 | 14.2k | librevenge::RVNGBinaryData data; |
567 | 14.2k | if (!m_mainParser->decodeZone(zone.m_entry, data)) { |
568 | 4 | MWAW_DEBUG_MSG(("HanMacWrdJText::sendText: can not decode a zone\n")); |
569 | 4 | m_parserState->m_asciiFile.addPos(zone.m_entry.begin()); |
570 | 4 | m_parserState->m_asciiFile.addNote("###"); |
571 | 4 | return false; |
572 | 4 | } |
573 | 14.2k | if (!data.size()) |
574 | 0 | return true; |
575 | 14.2k | if (fPos < 0 || 2*fPos > long(data.size())) { |
576 | 252 | MWAW_DEBUG_MSG(("HanMacWrdJText::sendText: first pos %ld is too big zone\n", fPos)); |
577 | 252 | return false; |
578 | 252 | } |
579 | | |
580 | 13.9k | MWAWInputStreamPtr input=MWAWInputStream::get(data, false); |
581 | 13.9k | if (!input) { |
582 | 0 | MWAW_DEBUG_MSG(("HanMacWrdJText::sendText: can not find my input\n")); |
583 | 0 | return false; |
584 | 0 | } |
585 | 13.9k | libmwaw::DebugFile asciiFile(input); |
586 | | |
587 | | #ifdef DEBUG_WITH_FILES |
588 | | if (fPos==0) { |
589 | | static int tId=0; |
590 | | std::stringstream s; |
591 | | s << "Text" << tId++; |
592 | | asciiFile.open(s.str()); |
593 | | } |
594 | | #endif |
595 | | |
596 | 13.9k | bool isMain = zone.m_type==HanMacWrdJTextInternal::TextZone::T_Main; |
597 | 13.9k | bool charOneIsEnd = zone.m_type==HanMacWrdJTextInternal::TextZone::T_Footnote || |
598 | 12.4k | zone.m_type==HanMacWrdJTextInternal::TextZone::T_Table; |
599 | | |
600 | 13.9k | long cPos=fPos, endCPos=-1; |
601 | 13.9k | int actPage = 1, actCol = 0, numCol=1, actSection = 1; |
602 | 13.9k | if (isMain) |
603 | 5.63k | m_mainParser->newPage(1); |
604 | 13.9k | if (isMain && !m_state->m_sectionList.size()) { |
605 | 3.99k | MWAW_DEBUG_MSG(("HanMacWrdJText::sendText: can not find section 0\n")); |
606 | 3.99k | } |
607 | 9.97k | else if (isMain) { |
608 | 1.63k | auto sec = m_state->m_sectionList[0]; |
609 | 1.63k | if (sec.m_numCols >= 1 && sec.m_colWidth.size() > 0) { |
610 | 1.63k | if (listener->isSectionOpened()) |
611 | 0 | listener->closeSection(); |
612 | 1.63k | listener->openSection(sec.getSection()); |
613 | 1.63k | numCol = listener->getSection().numColumns(); |
614 | 1.63k | } |
615 | 1.63k | } |
616 | 13.9k | long pos = 2*fPos; |
617 | 13.9k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
618 | 13.9k | libmwaw::DebugStream f; |
619 | 13.9k | f << "Entries(TextData):"; |
620 | | |
621 | 91.5k | while (true) { |
622 | 91.5k | if (cPos!=fPos) { |
623 | 77.5k | asciiFile.addPos(pos); |
624 | 77.5k | asciiFile.addNote(f.str().c_str()); |
625 | 77.5k | f.str(""); |
626 | 77.5k | f << "TextData:"; |
627 | 77.5k | pos = input->tell(); |
628 | 77.5k | } |
629 | 91.5k | auto plcIt=zone.m_PLCMap.find(cPos); |
630 | 91.5k | int expectedChar=0; |
631 | 91.5k | if (plcIt != zone.m_PLCMap.end()) { |
632 | 190k | while (plcIt != zone.m_PLCMap.end() && plcIt->first == cPos) { |
633 | 113k | auto const &plc = plcIt++->second; |
634 | 113k | f << "[" << plc << "]"; |
635 | 113k | switch (plc.m_type) { |
636 | 41.3k | case HanMacWrdJTextInternal::CHAR: { |
637 | 41.3k | if (plc.m_id < 0 || plc.m_id >= static_cast<int>(m_state->m_fontList.size())) { |
638 | 20.3k | MWAW_DEBUG_MSG(("HanMacWrdJText::sendText: can not find font\n")); |
639 | 20.3k | f << "[###font]"; |
640 | 20.3k | break; |
641 | 20.3k | } |
642 | 20.9k | listener->setFont(m_state->m_fontList[size_t(plc.m_id)]); |
643 | 20.9k | break; |
644 | 41.3k | } |
645 | 23.2k | case HanMacWrdJTextInternal::RULER: { |
646 | 23.2k | if (plc.m_id < 0 || plc.m_id >= static_cast<int>(m_state->m_paragraphList.size())) { |
647 | 8.77k | MWAW_DEBUG_MSG(("HanMacWrdJText::sendText: can not find paragraph\n")); |
648 | 8.77k | f << "[###paragraph]"; |
649 | 8.77k | break; |
650 | 8.77k | } |
651 | 14.4k | auto const ¶=m_state->m_paragraphList[size_t(plc.m_id)]; |
652 | 14.4k | if (isMain && para.m_addPageBreak) |
653 | 57 | m_mainParser->newPage(++actPage); |
654 | 14.4k | listener->setParagraph(para); |
655 | 14.4k | break; |
656 | 23.2k | } |
657 | 2.18k | case HanMacWrdJTextInternal::TOKEN: { |
658 | 2.18k | if (plc.m_id < 0 || plc.m_id >= static_cast<int>(zone.m_tokenList.size())) { |
659 | 0 | MWAW_DEBUG_MSG(("HanMacWrdJText::sendText: can not find token\n")); |
660 | 0 | f << "[###token]"; |
661 | 0 | break; |
662 | 0 | } |
663 | 2.18k | auto const &tkn=zone.m_tokenList[size_t(plc.m_id)]; |
664 | 2.18k | switch (tkn.m_type) { |
665 | 4 | case 1: |
666 | 4 | expectedChar=0x1; |
667 | 4 | if (withLocalListener) { |
668 | 0 | MWAW_DEBUG_MSG(("HanMacWrdJText::sendText: unexpected token type=1 in graphic\n")); |
669 | 0 | break; |
670 | 0 | } |
671 | 4 | m_mainParser->sendZone(tkn.m_id); |
672 | 4 | break; |
673 | 2.07k | case 2: { |
674 | 2.07k | expectedChar=0x11; |
675 | 2.07k | if (withLocalListener) { |
676 | 0 | MWAW_DEBUG_MSG(("HanMacWrdJText::sendText: can not insert footnote in graphic\n")); |
677 | 0 | break; |
678 | 0 | } |
679 | 2.07k | if (tkn.m_localId < 0 || tkn.m_localId >= int(m_state->m_ftnFirstPosList.size())) { |
680 | 283 | MWAW_DEBUG_MSG(("HanMacWrdJText::sendText: can not find footnote\n")); |
681 | 283 | f << "[###ftnote]"; |
682 | 283 | break; |
683 | 283 | } |
684 | 1.79k | MWAWSubDocumentPtr subdoc |
685 | 1.79k | (new HanMacWrdJTextInternal::SubDocument |
686 | 1.79k | (*this, input, m_state->m_ftnTextId, |
687 | 1.79k | m_state->m_ftnFirstPosList[size_t(tkn.m_localId)])); |
688 | 1.79k | m_parserState->m_textListener->insertNote(MWAWNote(MWAWNote::FootNote),subdoc); |
689 | 1.79k | break; |
690 | 2.07k | } |
691 | 0 | case 8: // TOC, ok to ignore |
692 | 0 | break; |
693 | 8 | case 0x20: |
694 | 8 | if (withLocalListener) { |
695 | 0 | MWAW_DEBUG_MSG(("HanMacWrdJText::sendText: can not insert bookmark in graphic\n")); |
696 | 0 | break; |
697 | 0 | } |
698 | 8 | else { |
699 | 8 | MWAWSubDocumentPtr subdoc(new HanMacWrdJTextInternal::SubDocument(*this, input, tkn.m_bookmark)); |
700 | 8 | m_parserState->m_textListener->insertComment(subdoc); |
701 | 8 | break; |
702 | 8 | } |
703 | 100 | default: |
704 | 100 | MWAW_DEBUG_MSG(("HanMacWrdJText::sendText: can not send token with type %d\n", tkn.m_type)); |
705 | 100 | break; |
706 | 2.18k | } |
707 | | |
708 | 2.18k | break; |
709 | 2.18k | } |
710 | 46.9k | case HanMacWrdJTextInternal::LINE: |
711 | 46.9k | case HanMacWrdJTextInternal::Unknown: |
712 | | #if !defined(__clang__) |
713 | | default: |
714 | | #endif |
715 | 46.9k | break; |
716 | 113k | } |
717 | 113k | } |
718 | 77.0k | endCPos = (plcIt != zone.m_PLCMap.end()) ? plcIt->first : -1; |
719 | 77.0k | } |
720 | 91.5k | if (input->isEnd()) |
721 | 8.86k | break; |
722 | 82.6k | if (expectedChar) { |
723 | 2.07k | if (static_cast<int>(input->readULong(1))==expectedChar) { |
724 | 82 | cPos++; |
725 | 82 | input->seek(1, librevenge::RVNG_SEEK_CUR); |
726 | 82 | } |
727 | 1.99k | else { |
728 | 1.99k | MWAW_DEBUG_MSG(("HanMacWrdJText::sendText: can not find expected char token\n")); |
729 | 1.99k | input->seek(-1, librevenge::RVNG_SEEK_CUR); |
730 | 1.99k | f << "###"; |
731 | 1.99k | } |
732 | 2.07k | } |
733 | 4.71M | while (endCPos<0 || cPos < endCPos) { |
734 | 4.64M | cPos++; |
735 | 4.64M | if (input->isEnd()) |
736 | 3.40k | break; |
737 | 4.64M | auto c = static_cast<int>(input->readULong(2)); |
738 | 4.64M | if (c==0) { |
739 | 114k | if (input->isEnd()) |
740 | 5.36k | break; |
741 | 109k | f << "#[0]"; |
742 | 109k | continue; |
743 | 114k | } |
744 | 4.52M | if (c==1 && charOneIsEnd) |
745 | 5.10k | return true; |
746 | 4.52M | switch (c) { |
747 | 2.81k | case 0x1000: |
748 | 2.81k | f << "[pgNum]"; |
749 | 2.81k | listener->insertField(MWAWField(MWAWField::PageNumber)); |
750 | 2.81k | break; |
751 | 2.59k | case 0x1001: |
752 | 2.59k | f << "[pgCount]"; |
753 | 2.59k | listener->insertField(MWAWField(MWAWField::PageCount)); |
754 | 2.59k | break; |
755 | 2.93k | case 0x1002: { |
756 | 2.93k | f << "[date]"; |
757 | 2.93k | MWAWField field(MWAWField::Date); |
758 | 2.93k | field.m_DTFormat="%A, %b %d, %Y"; |
759 | 2.93k | listener->insertField(field); |
760 | 2.93k | break; |
761 | 0 | } |
762 | 1.59k | case 0x1003: { |
763 | 1.59k | f << "[time]"; |
764 | 1.59k | MWAWField field(MWAWField::Time); |
765 | 1.59k | field.m_DTFormat="%I:%M %p"; |
766 | 1.59k | listener->insertField(field); |
767 | 1.59k | break; |
768 | 0 | } |
769 | 1.83k | case 0x1004: |
770 | 1.83k | f << "[title]"; |
771 | 1.83k | listener->insertField(MWAWField(MWAWField::Title)); |
772 | 1.83k | break; |
773 | 2.49k | case 0x1005: { |
774 | 2.49k | std::stringstream s; |
775 | 2.49k | f << "[section]"; |
776 | 2.49k | s << actSection; |
777 | 2.49k | listener->insertUnicodeString(librevenge::RVNGString(s.str().c_str())); |
778 | 2.49k | break; |
779 | 0 | } |
780 | 13.2k | case 2: |
781 | 13.2k | f << "[colBreak]"; |
782 | 13.2k | if (!isMain) { |
783 | 1.77k | MWAW_DEBUG_MSG(("HanMacWrdJText::sendText: find column break in auxilliary block\n")); |
784 | 1.77k | break; |
785 | 1.77k | } |
786 | 11.4k | if (actCol < numCol-1 && numCol > 1) { |
787 | 2.37k | listener->insertBreak(MWAWTextListener::ColumnBreak); |
788 | 2.37k | actCol++; |
789 | 2.37k | } |
790 | 9.11k | else { |
791 | 9.11k | actCol = 0; |
792 | 9.11k | m_mainParser->newPage(++actPage); |
793 | 9.11k | } |
794 | 11.4k | break; |
795 | 9.00k | case 3: |
796 | 9.00k | f << "[pageBreak]"; |
797 | 9.00k | if (isMain) { |
798 | 8.17k | m_mainParser->newPage(++actPage); |
799 | 8.17k | actCol = 0; |
800 | 8.17k | } |
801 | 9.00k | break; |
802 | 12.4k | case 4: |
803 | 12.4k | f << "[sectionBreak]"; |
804 | 12.4k | if (!isMain) { |
805 | 1.56k | MWAW_DEBUG_MSG(("HanMacWrdJText::sendText: find section in auxilliary block\n")); |
806 | 1.56k | break; |
807 | 1.56k | } |
808 | 10.8k | if (size_t(actSection) >= m_state->m_sectionList.size()) { |
809 | 10.1k | MWAW_DEBUG_MSG(("HanMacWrdJText::sendText: can not find section %d\n", actSection)); |
810 | 10.1k | break; |
811 | 10.1k | } |
812 | 732 | else { |
813 | 732 | auto const &sec = m_state->m_sectionList[size_t(actSection++)]; |
814 | 732 | actCol = 0; |
815 | 732 | if (listener->isSectionOpened()) |
816 | 732 | listener->closeSection(); |
817 | 732 | m_mainParser->newPage(++actPage); |
818 | 732 | listener->openSection(sec.getSection()); |
819 | 732 | numCol = listener->getSection().numColumns(); |
820 | 732 | } |
821 | 732 | break; |
822 | 4.33k | case 9: |
823 | 4.33k | f << char(c); |
824 | 4.33k | listener->insertTab(); |
825 | 4.33k | break; |
826 | 11.7k | case 0xd: |
827 | 11.7k | f << char(c); |
828 | 11.7k | listener->insertEOL(); |
829 | 11.7k | break; |
830 | 4.45M | default: { |
831 | 4.45M | if (c >= 0x1100 && c <= 0x11ff) // ok a footnote |
832 | 39.9k | break; |
833 | 4.41M | if (c <= 0x1f || c >= 0x100) { |
834 | 4.19M | f << "#[" << std::hex << c << std::dec << "]"; |
835 | 4.19M | MWAW_DEBUG_MSG(("HanMacWrdJText::sendText: find a odd char %x\n", static_cast<unsigned int>(c))); |
836 | 4.19M | break; |
837 | 4.19M | } |
838 | 224k | f << char(c); |
839 | 224k | listener->insertCharacter(static_cast<unsigned char>(c), input); |
840 | 224k | break; |
841 | 4.41M | } |
842 | 4.52M | } |
843 | 4.52M | } |
844 | 82.6k | } |
845 | 8.86k | return true; |
846 | 13.9k | } |
847 | | |
848 | | int HanMacWrdJText::computeNumPages(HanMacWrdJTextInternal::TextZone const &zone) |
849 | 6.38k | { |
850 | 6.38k | if (zone.m_type!=HanMacWrdJTextInternal::TextZone::T_Main) |
851 | 0 | return 1; |
852 | 6.38k | if (!zone.m_entry.valid()) |
853 | 764 | return 0; |
854 | 5.61k | librevenge::RVNGBinaryData data; |
855 | 5.61k | if (!m_mainParser->decodeZone(zone.m_entry, data) || !data.size()) |
856 | 3 | return 0; |
857 | | |
858 | 5.61k | MWAWInputStreamPtr input=MWAWInputStream::get(data, false); |
859 | 5.61k | if (!input) |
860 | 0 | return 0; |
861 | 5.61k | int nPages = 1, actCol = 0, numCol=1, actSection = 1; |
862 | | |
863 | 5.61k | if (m_state->m_sectionList.size()) { |
864 | 1.63k | auto const &sec = m_state->m_sectionList[0]; |
865 | 1.63k | if (sec.m_numCols >= 1) |
866 | 1.63k | numCol = sec.m_numCols; |
867 | 1.63k | } |
868 | 5.61k | input->seek(0, librevenge::RVNG_SEEK_SET); |
869 | 4.33M | while (!input->isEnd()) { |
870 | 4.32M | auto c = static_cast<int>(input->readULong(2)); |
871 | 4.32M | switch (c) { |
872 | 11.4k | case 2: |
873 | 11.4k | if (actCol < numCol-1 && numCol > 1) |
874 | 2.43k | actCol++; |
875 | 9.04k | else { |
876 | 9.04k | actCol = 0; |
877 | 9.04k | nPages++; |
878 | 9.04k | } |
879 | 11.4k | break; |
880 | 8.17k | case 3: |
881 | 8.17k | actCol = 0; |
882 | 8.17k | nPages++; |
883 | 8.17k | break; |
884 | 10.8k | case 4: { |
885 | 10.8k | if (size_t(actSection) >= m_state->m_sectionList.size()) |
886 | 10.1k | break; |
887 | 732 | actCol = 0; |
888 | 732 | nPages++; |
889 | 732 | auto const &sec = m_state->m_sectionList[size_t(actSection++)]; |
890 | 732 | numCol = sec.m_numCols >= 1 ? sec.m_numCols : 1; |
891 | 732 | break; |
892 | 10.8k | } |
893 | 4.29M | default: |
894 | 4.29M | break; |
895 | 4.32M | } |
896 | 4.32M | } |
897 | 5.61k | return nPages; |
898 | 5.61k | } |
899 | | |
900 | | void HanMacWrdJText::updateTextZoneTypes(std::map<long, int> const &idTypeMap) |
901 | 12.5k | { |
902 | 12.5k | auto numZones = static_cast<int>(m_state->m_textZoneList.size()); |
903 | 22.9k | for (auto const &it : idTypeMap) { |
904 | 22.9k | if (m_state->m_idTextZoneMap.find(it.first)==m_state->m_idTextZoneMap.end()) { |
905 | 7.31k | MWAW_DEBUG_MSG(("HanMacWrdJText::updateTextZoneTypes: can not find text zone with id %lx\n", static_cast<long unsigned int>(it.first))); |
906 | 7.31k | continue; |
907 | 7.31k | } |
908 | 15.6k | int zId = m_state->m_idTextZoneMap.find(it.first)->second; |
909 | 15.6k | if (zId < 0 || zId >= numZones) |
910 | 0 | continue; |
911 | 15.6k | m_state->m_textZoneList[size_t(zId)].m_type= |
912 | 15.6k | HanMacWrdJTextInternal::TextZone::Type(it.second); |
913 | 15.6k | } |
914 | 12.5k | } |
915 | | |
916 | | void HanMacWrdJText::updateFootnoteInformations(long const &textZId, std::vector<long> const &fPosList) |
917 | 4.92k | { |
918 | 4.92k | m_state->m_ftnTextId = textZId; |
919 | 4.92k | m_state->m_ftnFirstPosList = fPosList; |
920 | 4.92k | } |
921 | | |
922 | | bool HanMacWrdJText::readTextZonesList(MWAWEntry const &entry) |
923 | 7.17k | { |
924 | 7.17k | if (!entry.valid()) { |
925 | 0 | MWAW_DEBUG_MSG(("HanMacWrdJText::readTextZonesList: called without any entry\n")); |
926 | 0 | return false; |
927 | 0 | } |
928 | 7.17k | if (entry.length() == 8) { |
929 | 0 | MWAW_DEBUG_MSG(("HanMacWrdJText::readTextZonesList: find an empty zone\n")); |
930 | 0 | entry.setParsed(true); |
931 | 0 | return true; |
932 | 0 | } |
933 | 7.17k | if (entry.length() < 12) { |
934 | 0 | MWAW_DEBUG_MSG(("HanMacWrdJText::readTextZonesList: the entry seems too short\n")); |
935 | 0 | return false; |
936 | 0 | } |
937 | 7.17k | if (m_state->m_textZoneList.size()) { |
938 | 1.57k | MWAW_DEBUG_MSG(("HanMacWrdJText::readTextZonesList: oops the text zone list os ,not empty\n")); |
939 | 1.57k | } |
940 | 7.17k | long pos = entry.begin()+8; // skip header |
941 | 7.17k | long endPos = entry.end(); |
942 | | |
943 | 7.17k | MWAWInputStreamPtr input = m_parserState->m_input; |
944 | 7.17k | libmwaw::DebugFile &asciiFile = m_parserState->m_asciiFile; |
945 | 7.17k | libmwaw::DebugStream f; |
946 | 7.17k | entry.setParsed(true); |
947 | 7.17k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
948 | | // first read the header |
949 | 7.17k | f << entry.name() << "[header]:"; |
950 | 7.17k | HanMacWrdJZoneHeader mainHeader(true); |
951 | 7.17k | if (!m_mainParser->readClassicHeader(mainHeader,endPos) || mainHeader.m_fieldSize!=4) { |
952 | 608 | MWAW_DEBUG_MSG(("HanMacWrdJText::readTextZonesList: can not read an entry\n")); |
953 | 608 | f << "###sz=" << mainHeader.m_length; |
954 | 608 | asciiFile.addPos(pos); |
955 | 608 | asciiFile.addNote(f.str().c_str()); |
956 | 608 | return false; |
957 | 608 | } |
958 | 6.57k | long headerEnd=pos+4+mainHeader.m_length; |
959 | 6.57k | f << mainHeader; |
960 | 6.57k | long val; |
961 | 6.57k | f << "listId=[" << std::hex; |
962 | 6.57k | std::vector<long> listIds; |
963 | 160k | for (int i = 0; i < mainHeader.m_n; i++) { |
964 | 153k | val = long(input->readULong(4)); |
965 | 153k | m_state->m_idTextZoneMap[val]=i; |
966 | 153k | listIds.push_back(val); |
967 | 153k | f << val << ","; |
968 | 153k | } |
969 | 6.57k | f << std::dec << "],"; |
970 | 6.57k | asciiFile.addPos(pos); |
971 | 6.57k | asciiFile.addNote(f.str().c_str()); |
972 | 6.57k | if (input->tell()!=headerEnd) { |
973 | 6.54k | asciiFile.addDelimiter(input->tell(),'|'); |
974 | 6.54k | input->seek(headerEnd, librevenge::RVNG_SEEK_SET); |
975 | 6.54k | } |
976 | 6.57k | m_state->m_textZoneList.resize(size_t(mainHeader.m_n)); |
977 | 6.57k | if (mainHeader.m_n) |
978 | 6.50k | m_state->m_textZoneList[0].m_type=HanMacWrdJTextInternal::TextZone::T_Main; |
979 | 24.1k | for (int i = 0; i < mainHeader.m_n; i++) { |
980 | 19.8k | auto &zone=m_state->m_textZoneList[size_t(i)]; |
981 | 19.8k | zone.m_id = listIds[size_t(i)]; |
982 | | // first a field of size 0x26 |
983 | 19.8k | pos = input->tell(); |
984 | 19.8k | f.str(""); |
985 | 19.8k | f << entry.name() << "-A" << i << ":"; |
986 | 19.8k | f << "id=" << std::hex << listIds[size_t(i)] << std::dec << ","; |
987 | | |
988 | 19.8k | long dataSz = (pos+4>endPos) ? 0: long(input->readULong(4)); |
989 | 19.8k | long zoneEnd=pos+4+dataSz; |
990 | 19.8k | if (zoneEnd > endPos) { |
991 | 888 | MWAW_DEBUG_MSG(("HanMacWrdJText::readTextZonesList: can not read first zone size for id=%d\n",i)); |
992 | 888 | f << "###sz=" << dataSz; |
993 | 888 | asciiFile.addPos(pos); |
994 | 888 | asciiFile.addNote(f.str().c_str()); |
995 | 888 | return false; |
996 | 888 | } |
997 | 19.0k | if (dataSz < 38) { |
998 | 449 | MWAW_DEBUG_MSG(("HanMacWrdJText::readTextZonesList: first zone size for id=%d seems very short\n",i)); |
999 | 449 | f << "###"; |
1000 | 449 | } |
1001 | 18.5k | else { |
1002 | 18.5k | int sel[3]; |
1003 | 55.6k | for (auto &s : sel) s = static_cast<int>(input->readLong(4)); |
1004 | 18.5k | if (sel[0] || sel[1] || sel[2]) { |
1005 | 18.5k | f << "select=" << sel[1] << "x" << sel[0]; |
1006 | 18.5k | if (sel[1] != sel[2]) |
1007 | 601 | f << "[" << sel[2] << "]"; |
1008 | 18.5k | f << ","; |
1009 | 18.5k | } |
1010 | 18.5k | f << "listIds=[" << std::hex; // 5 or 6 id |
1011 | 129k | for (int j = 0; j < 6; j++) { |
1012 | 111k | val = long(input->readULong(4)); |
1013 | 111k | if (val) |
1014 | 95.3k | f << val << ","; |
1015 | 15.9k | else |
1016 | 15.9k | f << "_,"; |
1017 | 111k | } |
1018 | 18.5k | f << std::dec << "],"; |
1019 | 18.5k | auto N1 = static_cast<int>(input->readULong(2)); // correspond to next N1 |
1020 | 18.5k | f << "N=" << N1 << ","; |
1021 | 18.5k | } |
1022 | 19.0k | asciiFile.addPos(pos); |
1023 | 19.0k | asciiFile.addNote(f.str().c_str()); |
1024 | | |
1025 | 19.0k | input->seek(zoneEnd, librevenge::RVNG_SEEK_SET); |
1026 | 19.0k | f.str(""); |
1027 | 19.0k | f << entry.name() << "-B" << i << ":"; |
1028 | 19.0k | f << "id=" << std::hex << listIds[size_t(i)] << std::dec << ","; |
1029 | | |
1030 | 19.0k | pos = input->tell(); |
1031 | 19.0k | HanMacWrdJZoneHeader header(false); |
1032 | 19.0k | if (!m_mainParser->readClassicHeader(header,endPos) || header.m_fieldSize!=4) { |
1033 | 2.04k | MWAW_DEBUG_MSG(("HanMacWrdJText::readTextZonesList: can not read second zone %d\n", i)); |
1034 | 2.04k | f << "###" << header; |
1035 | 2.04k | asciiFile.addPos(pos); |
1036 | 2.04k | asciiFile.addNote(f.str().c_str()); |
1037 | 2.04k | if (header.m_length<16 || pos+4+header.m_length>endPos) |
1038 | 1.47k | return false; |
1039 | 573 | input->seek(pos+4+header.m_length, librevenge::RVNG_SEEK_SET); |
1040 | 573 | continue; |
1041 | 2.04k | } |
1042 | 16.9k | zoneEnd=pos+4+header.m_length; |
1043 | 16.9k | f << header; |
1044 | | /* h0,h1,h2 seems to correspond to freeBlock, 0, 8[totalblock=8*..], h3=1*/ |
1045 | 16.9k | f << "listId?=[" << std::hex; |
1046 | 42.8k | for (int j = 0; j < header.m_n; j++) { |
1047 | 25.9k | val = long(input->readULong(4)); |
1048 | 25.9k | f << val << ","; |
1049 | 25.9k | } |
1050 | 16.9k | f << std::dec << "],"; |
1051 | 16.9k | asciiFile.addPos(pos); |
1052 | 16.9k | asciiFile.addNote(f.str().c_str()); |
1053 | 16.9k | if (input->tell()!=zoneEnd) |
1054 | 16.9k | asciiFile.addDelimiter(input->tell(),'|'); |
1055 | 16.9k | input->seek(zoneEnd, librevenge::RVNG_SEEK_SET); |
1056 | 16.9k | } |
1057 | | |
1058 | 4.21k | pos = input->tell(); |
1059 | 4.21k | if (pos!=endPos) { |
1060 | 82 | f.str(""); |
1061 | 82 | f << entry.name() << "[last]:###"; |
1062 | 82 | MWAW_DEBUG_MSG(("HanMacWrdJText::readTextZonesList: find unexpected end of data\n")); |
1063 | 82 | asciiFile.addPos(pos); |
1064 | 82 | asciiFile.addNote(f.str().c_str()); |
1065 | 82 | } |
1066 | | |
1067 | 4.21k | return true; |
1068 | 6.57k | } |
1069 | | |
1070 | | bool HanMacWrdJText::readTextZone(MWAWEntry const &entry, int actZone) |
1071 | 17.4k | { |
1072 | 17.4k | if (!entry.valid()) { |
1073 | 0 | MWAW_DEBUG_MSG(("HanMacWrdJText::readTextZone: called without any entry\n")); |
1074 | 0 | return false; |
1075 | 0 | } |
1076 | 17.4k | if (entry.length() < 8+20*3) { |
1077 | 83 | MWAW_DEBUG_MSG(("HanMacWrdJText::readTextZone: the entry seems too short\n")); |
1078 | 83 | return false; |
1079 | 83 | } |
1080 | | |
1081 | 17.3k | MWAWInputStreamPtr input = m_parserState->m_input; |
1082 | 17.3k | libmwaw::DebugFile &asciiFile = m_parserState->m_asciiFile; |
1083 | 17.3k | libmwaw::DebugStream f; |
1084 | 17.3k | entry.setParsed(true); |
1085 | | |
1086 | 17.3k | long pos = entry.begin()+8; // skip header |
1087 | 17.3k | long endPos = entry.end(); |
1088 | 17.3k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1089 | | |
1090 | 17.3k | if (actZone >= static_cast<int>(m_state->m_textZoneList.size()) || actZone < 0) { |
1091 | 3.60k | MWAW_DEBUG_MSG(("HanMacWrdJText::readTextZone: find an unexpected zone\n")); |
1092 | 3.60k | if (actZone < 0) |
1093 | 0 | actZone = static_cast<int>(m_state->m_textZoneList.size()); |
1094 | 3.60k | m_state->m_textZoneList.resize(size_t(actZone)+1); |
1095 | 3.60k | } |
1096 | 17.3k | auto &zone = m_state->m_textZoneList[size_t(actZone)]; |
1097 | 17.3k | long val; |
1098 | | |
1099 | | // first read the char properties list |
1100 | 17.3k | std::vector<HanMacWrdJTextInternal::PLC> cPLCList; |
1101 | 17.3k | std::vector<MWAWVec2i> cPLCPosList; // 0:line, 1:char |
1102 | | |
1103 | 17.3k | f.str(""); |
1104 | 17.3k | f << entry.name() << "-char:"; |
1105 | | |
1106 | 17.3k | pos = input->tell(); |
1107 | 17.3k | HanMacWrdJZoneHeader header(false); |
1108 | 17.3k | bool ok = true; |
1109 | 17.3k | if (!m_mainParser->readClassicHeader(header,endPos) || header.m_fieldSize!=8) { |
1110 | 2.78k | MWAW_DEBUG_MSG(("HanMacWrdJText::readTextZone: can not read zone the char plc list\n")); |
1111 | 2.78k | f << "###"; |
1112 | 2.78k | asciiFile.addPos(pos); |
1113 | 2.78k | asciiFile.addNote(f.str().c_str()); |
1114 | 2.78k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1115 | 2.78k | ok = false; |
1116 | 2.78k | } |
1117 | 14.5k | else { |
1118 | 14.5k | f << header; |
1119 | 14.5k | long zoneEnd=pos+4+header.m_length; |
1120 | 14.5k | asciiFile.addPos(pos); |
1121 | 14.5k | asciiFile.addNote(f.str().c_str()); |
1122 | | |
1123 | 112k | for (int j = 0; j < header.m_n; j++) { |
1124 | 98.3k | pos = input->tell(); |
1125 | 98.3k | f.str(""); |
1126 | 98.3k | MWAWVec2i cPos; |
1127 | 98.3k | cPos[0] = static_cast<int>(input->readLong(2)); |
1128 | 98.3k | cPos[1] = static_cast<int>(input->readLong(2)); |
1129 | 98.3k | HanMacWrdJTextInternal::PLC plc; |
1130 | 98.3k | plc.m_type = HanMacWrdJTextInternal::CHAR; |
1131 | 98.3k | plc.m_id = static_cast<int>(input->readLong(2)); |
1132 | 98.3k | val = long(input->readULong(2)); // 0|1|4|5|f|26|2d|42|4e|4f|..|6a|6e|7a|7d |
1133 | 98.3k | if (val) f << "#f0=" << std::hex << val << std::dec << ","; |
1134 | 98.3k | plc.m_extra = f.str(); |
1135 | 98.3k | cPLCPosList.push_back(cPos); |
1136 | 98.3k | cPLCList.push_back(plc); |
1137 | | |
1138 | 98.3k | f.str(""); |
1139 | 98.3k | f << entry.name() << "-Char" << j << "]:lcPos=" << cPos << "," << plc; |
1140 | 98.3k | asciiFile.addPos(pos); |
1141 | 98.3k | asciiFile.addNote(f.str().c_str()); |
1142 | 98.3k | input->seek(pos+header.m_fieldSize, librevenge::RVNG_SEEK_SET); |
1143 | 98.3k | } |
1144 | | |
1145 | 14.5k | if (input->tell() != zoneEnd) { // junk ? |
1146 | 14.5k | asciiFile.addDelimiter(input->tell(),'|'); |
1147 | 14.5k | input->seek(zoneEnd, librevenge::RVNG_SEEK_SET); |
1148 | 14.5k | } |
1149 | 14.5k | } |
1150 | | |
1151 | | // second read the ruler list |
1152 | 17.3k | std::map<int, HanMacWrdJTextInternal::PLC> rLineRulerMap; |
1153 | | |
1154 | 17.3k | f.str(""); |
1155 | 17.3k | f << entry.name() << "-ruler:"; |
1156 | | |
1157 | 17.3k | pos = input->tell(); |
1158 | 17.3k | header=HanMacWrdJZoneHeader(false); |
1159 | 17.3k | if (!ok) { |
1160 | 2.78k | } |
1161 | 14.5k | else if (!m_mainParser->readClassicHeader(header,endPos) || header.m_fieldSize!=8) { |
1162 | 2.50k | MWAW_DEBUG_MSG(("HanMacWrdJText::readTextZone: can not read zone the ruler plc list\n")); |
1163 | 2.50k | f << "###"; |
1164 | 2.50k | asciiFile.addPos(pos); |
1165 | 2.50k | asciiFile.addNote(f.str().c_str()); |
1166 | 2.50k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1167 | 2.50k | ok = false; |
1168 | 2.50k | } |
1169 | 12.0k | else { |
1170 | 12.0k | f << header; |
1171 | 12.0k | long zoneEnd=pos+4+header.m_length; |
1172 | 12.0k | asciiFile.addPos(pos); |
1173 | 12.0k | asciiFile.addNote(f.str().c_str()); |
1174 | | |
1175 | 55.1k | for (int j = 0; j < header.m_n; j++) { |
1176 | 43.0k | pos = input->tell(); |
1177 | 43.0k | f.str(""); |
1178 | 43.0k | auto line = static_cast<int>(input->readLong(2)); |
1179 | 43.0k | HanMacWrdJTextInternal::PLC plc; |
1180 | 43.0k | plc.m_type = HanMacWrdJTextInternal::RULER; |
1181 | 43.0k | plc.m_id = static_cast<int>(input->readLong(2)); |
1182 | | |
1183 | 43.0k | val = long(input->readULong(4)); // find 0,000008a0, 023ddd20, 0046ddbb, 5808001d, 5808004e |
1184 | 43.0k | if (val) f << "#f0=" << std::hex << val << std::dec << ","; |
1185 | 43.0k | plc.m_extra = f.str(); |
1186 | 43.0k | if (rLineRulerMap.find(line) != rLineRulerMap.end()) { |
1187 | 2.15k | MWAW_DEBUG_MSG(("HanMacWrdJText::readTextZone: already find a ruler for line=%d\n",line)); |
1188 | 2.15k | f << "###"; |
1189 | 2.15k | } |
1190 | 40.8k | else |
1191 | 40.8k | rLineRulerMap[line]=plc; |
1192 | | |
1193 | 43.0k | f.str(""); |
1194 | 43.0k | f << entry.name() << "-Ruler" << j << "]:line=" << line << "," << plc; |
1195 | 43.0k | asciiFile.addPos(pos); |
1196 | 43.0k | asciiFile.addNote(f.str().c_str()); |
1197 | 43.0k | input->seek(pos+header.m_fieldSize, librevenge::RVNG_SEEK_SET); |
1198 | 43.0k | } |
1199 | | |
1200 | 12.0k | if (input->tell() != zoneEnd) { // junk ? |
1201 | 12.0k | asciiFile.addDelimiter(input->tell(),'|'); |
1202 | 12.0k | input->seek(zoneEnd, librevenge::RVNG_SEEK_SET); |
1203 | 12.0k | } |
1204 | 12.0k | } |
1205 | | |
1206 | | // now we can read the line position |
1207 | 17.3k | std::vector<long> linePosList; |
1208 | | |
1209 | 17.3k | f.str(""); |
1210 | 17.3k | f << entry.name() << "-line:"; |
1211 | 17.3k | pos = input->tell(); |
1212 | 17.3k | header=HanMacWrdJZoneHeader(false); |
1213 | 17.3k | if (!ok) { |
1214 | 5.29k | } |
1215 | 12.0k | else if (!m_mainParser->readClassicHeader(header,endPos) || header.m_fieldSize!=4) { |
1216 | 1.13k | MWAW_DEBUG_MSG(("HanMacWrdJText::readTextZone: can not read zone the line plc list\n")); |
1217 | 1.13k | f << "###"; |
1218 | 1.13k | asciiFile.addPos(pos); |
1219 | 1.13k | asciiFile.addNote(f.str().c_str()); |
1220 | 1.13k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1221 | 1.13k | ok = false; |
1222 | 1.13k | } |
1223 | 10.9k | else { |
1224 | 10.9k | f << header; |
1225 | 10.9k | long zoneEnd=pos+4+header.m_length; |
1226 | 10.9k | asciiFile.addPos(pos); |
1227 | 10.9k | asciiFile.addNote(f.str().c_str()); |
1228 | 10.9k | HanMacWrdJTextInternal::PLC plc; |
1229 | 10.9k | plc.m_type = HanMacWrdJTextInternal::LINE; |
1230 | | |
1231 | 10.9k | f << "linePos=[" << std::hex; |
1232 | 80.6k | for (int j = 0; j < header.m_n; j++) { |
1233 | 69.6k | long linePos = input->readLong(4); |
1234 | 69.6k | linePosList.push_back(linePos); |
1235 | 69.6k | plc.m_id = j; |
1236 | 69.6k | zone.m_PLCMap.insert |
1237 | 69.6k | (std::multimap<long, HanMacWrdJTextInternal::PLC>::value_type(linePos, plc)); |
1238 | 69.6k | f << linePos << ","; |
1239 | 69.6k | } |
1240 | 10.9k | f << std::dec << "],"; |
1241 | 10.9k | asciiFile.addPos(pos); |
1242 | 10.9k | asciiFile.addNote(f.str().c_str()); |
1243 | | |
1244 | 10.9k | if (input->tell() != zoneEnd) { // junk ? |
1245 | 10.9k | asciiFile.addDelimiter(input->tell(),'|'); |
1246 | 10.9k | input->seek(zoneEnd, librevenge::RVNG_SEEK_SET); |
1247 | 10.9k | } |
1248 | 10.9k | } |
1249 | | |
1250 | | // ok, we can now update the plc |
1251 | 17.3k | if (ok) { |
1252 | 10.9k | auto nLines = int(linePosList.size()); |
1253 | 36.6k | for (auto const &rIt : rLineRulerMap) { |
1254 | 36.6k | int line = rIt.first; |
1255 | 36.6k | if (line < 0 || line >= nLines) { |
1256 | 3.03k | MWAW_DEBUG_MSG(("HanMacWrdJText::readTextZone: build rule plc, can not find line %d\n", line)); |
1257 | 3.03k | continue; |
1258 | | |
1259 | 3.03k | } |
1260 | 33.5k | zone.m_PLCMap.insert |
1261 | 33.5k | (std::multimap<long, HanMacWrdJTextInternal::PLC>::value_type(linePosList[size_t(line)], rIt.second)); |
1262 | 33.5k | } |
1263 | 10.9k | size_t numCProp = cPLCPosList.size(); |
1264 | 10.9k | if (numCProp != cPLCList.size()) { |
1265 | 0 | MWAW_DEBUG_MSG(("HanMacWrdJText::readTextZone: cPLCPosList and cPLCList have not the same size\n")); |
1266 | 0 | if (numCProp > cPLCList.size()) |
1267 | 0 | numCProp = cPLCList.size(); |
1268 | 0 | } |
1269 | 68.2k | for (size_t i = 0; i < numCProp; i++) { |
1270 | 57.3k | int line = cPLCPosList[i][0]; |
1271 | 57.3k | if (line < 0 || line >= nLines) { |
1272 | 4.33k | MWAW_DEBUG_MSG(("HanMacWrdJText::readTextZone: build char plc, can not find line %d\n", line)); |
1273 | 4.33k | continue; |
1274 | 4.33k | } |
1275 | 52.9k | long cPos = linePosList[size_t(line)]+long(cPLCPosList[i][1]); |
1276 | 52.9k | zone.m_PLCMap.insert |
1277 | 52.9k | (std::multimap<long, HanMacWrdJTextInternal::PLC>::value_type(cPos, cPLCList[i])); |
1278 | 52.9k | } |
1279 | 10.9k | } |
1280 | 17.3k | asciiFile.addPos(endPos); |
1281 | 17.3k | asciiFile.addNote("_"); |
1282 | | |
1283 | | // now potentially a token zone, called with endPos-1 to avoid reading the last text zone |
1284 | 17.3k | readTextToken(endPos-1, zone); |
1285 | | |
1286 | 17.3k | pos = input->tell(); |
1287 | 17.3k | if (pos==endPos) { |
1288 | 17 | MWAW_DEBUG_MSG(("HanMacWrdJText::readTextZone: can not read find the last zone\n")); |
1289 | | |
1290 | 17 | return true; |
1291 | 17 | } |
1292 | | |
1293 | | // normally now the text data but check if there remains some intermediar unparsed zone |
1294 | 17.3k | auto dataSz = long(input->readULong(4)); |
1295 | 21.1k | while (dataSz>0 && pos+4+dataSz < endPos) { |
1296 | 3.80k | MWAW_DEBUG_MSG(("HanMacWrdJText::readTextZone: find some unparsed zone\n")); |
1297 | 3.80k | f.str(""); |
1298 | 3.80k | f << entry.name() << "-###:"; |
1299 | 3.80k | asciiFile.addPos(pos); |
1300 | 3.80k | asciiFile.addNote(f.str().c_str()); |
1301 | | |
1302 | 3.80k | pos = pos+4+dataSz; |
1303 | 3.80k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1304 | 3.80k | dataSz = long(input->readULong(4)); |
1305 | 3.80k | } |
1306 | 17.3k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1307 | | |
1308 | | // the text data |
1309 | 17.3k | f.str(""); |
1310 | 17.3k | f << entry.name() << "-text:"; |
1311 | 17.3k | dataSz = long(input->readULong(4)); |
1312 | 17.3k | if (pos+4+dataSz>endPos) { |
1313 | 1.11k | MWAW_DEBUG_MSG(("HanMacWrdJText::readTextZone: can not read last zone size\n")); |
1314 | 1.11k | f << "###sz=" << dataSz; |
1315 | 1.11k | asciiFile.addPos(pos); |
1316 | 1.11k | asciiFile.addNote(f.str().c_str()); |
1317 | 1.11k | return false; |
1318 | 1.11k | } |
1319 | | |
1320 | 16.2k | asciiFile.addPos(pos); |
1321 | 16.2k | asciiFile.addNote(f.str().c_str()); |
1322 | | |
1323 | 16.2k | zone.m_entry.setBegin(pos); |
1324 | 16.2k | zone.m_entry.setEnd(endPos); |
1325 | 16.2k | zone.m_entry.setName(entry.name()); |
1326 | | |
1327 | 16.2k | return true; |
1328 | 17.3k | } |
1329 | | |
1330 | | bool HanMacWrdJText::readTextToken(long endPos, HanMacWrdJTextInternal::TextZone &zone) |
1331 | 17.3k | { |
1332 | 17.3k | MWAWInputStreamPtr input = m_parserState->m_input; |
1333 | 17.3k | libmwaw::DebugFile &asciiFile = m_parserState->m_asciiFile; |
1334 | 17.3k | libmwaw::DebugStream f; |
1335 | 17.3k | long pos=input->tell(); |
1336 | 17.3k | if (pos+4>=endPos) |
1337 | 36 | return true; |
1338 | | |
1339 | 17.3k | f << "Entries(TextToken):"; |
1340 | 17.3k | HanMacWrdJZoneHeader header(false); |
1341 | 17.3k | if (!m_mainParser->readClassicHeader(header,endPos) || header.m_fieldSize!=16 || |
1342 | 14.8k | 16+16*header.m_n+4 > header.m_length) { |
1343 | 14.8k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1344 | 14.8k | return true; |
1345 | 14.8k | } |
1346 | 2.45k | int val; |
1347 | 7.37k | for (int i = 0; i < 2; i++) { // always 0? |
1348 | 4.91k | val = static_cast<int>(input->readLong(2)); |
1349 | 4.91k | if (val) f << "f" << i << "=" << val << ","; |
1350 | 4.91k | } |
1351 | 2.45k | f << header; |
1352 | 2.45k | long zoneEnd=pos+4+header.m_length; |
1353 | 2.45k | asciiFile.addPos(pos); |
1354 | 2.45k | asciiFile.addNote(f.str().c_str()); |
1355 | | |
1356 | 2.45k | HanMacWrdJTextInternal::PLC plc(HanMacWrdJTextInternal::TOKEN); |
1357 | 2.45k | std::vector<int> bkmIdList; |
1358 | 5.13k | for (int i = 0; i < header.m_n; i++) { |
1359 | 2.68k | pos = input->tell(); |
1360 | 2.68k | f.str(""); |
1361 | 2.68k | HanMacWrdJTextInternal::Token tkn; |
1362 | 2.68k | long fPos = input->readLong(4); |
1363 | | |
1364 | 2.68k | val = static_cast<int>(input->readLong(2)); // always 0 ? |
1365 | 2.68k | if (val) f << "f0=" << val << ","; |
1366 | 2.68k | tkn.m_length=static_cast<int>(input->readLong(2)); |
1367 | 2.68k | tkn.m_id = long(input->readULong(4)); |
1368 | | |
1369 | 2.68k | tkn.m_type=static_cast<int>(input->readLong(1)); |
1370 | 8.04k | for (int j=0; j < 2; j++) { // f1=0, f2=0|1[field]|11[footnote] |
1371 | 5.36k | val = static_cast<int>(input->readLong(1)); |
1372 | 5.36k | if (val) f << "f" << j+1 << "=" << val << ","; |
1373 | 5.36k | } |
1374 | 2.68k | tkn.m_localId = static_cast<int>(input->readLong(1)); |
1375 | 2.68k | tkn.m_extra = f.str(); |
1376 | 2.68k | zone.m_tokenList.push_back(tkn); |
1377 | 2.68k | if (tkn.m_type==0x20) |
1378 | 13 | bkmIdList.push_back(i); |
1379 | 2.68k | plc.m_id = i; |
1380 | 2.68k | zone.m_PLCMap.insert(std::multimap<long, HanMacWrdJTextInternal::PLC>::value_type(fPos, plc)); |
1381 | | |
1382 | 2.68k | f.str(""); |
1383 | 2.68k | f << "TextToken-" << i << ":"; |
1384 | 2.68k | if (fPos) f << "fPos=" << std::hex << fPos << std::dec << ","; |
1385 | 2.68k | f << tkn; |
1386 | 2.68k | asciiFile.addPos(pos); |
1387 | 2.68k | asciiFile.addNote(f.str().c_str()); |
1388 | 2.68k | input->seek(pos+16, librevenge::RVNG_SEEK_SET); |
1389 | 2.68k | } |
1390 | | |
1391 | 2.45k | if (input->tell() != zoneEnd) { |
1392 | 2.44k | asciiFile.addDelimiter(input->tell(),'|'); |
1393 | 2.44k | input->seek(zoneEnd, librevenge::RVNG_SEEK_SET); |
1394 | 2.44k | } |
1395 | | |
1396 | 2.45k | pos = input->tell(); |
1397 | | // next: we can find potential bookmark zone |
1398 | 2.46k | for (size_t i=0; i < bkmIdList.size(); i++) { |
1399 | 13 | pos = input->tell(); |
1400 | 13 | auto dataSz = long(input->readULong(4)); |
1401 | 13 | zoneEnd = pos+4+dataSz; |
1402 | 13 | if (input->isEnd() || dataSz<0 || zoneEnd >= endPos) { |
1403 | 11 | MWAW_DEBUG_MSG(("HanMacWrdJText::readTextToken: can not find bookmark text %d\n", int(i))); |
1404 | 11 | break; |
1405 | 11 | } |
1406 | | |
1407 | 2 | f.str(""); |
1408 | 2 | f << "TextToken-data" << i << ":"; |
1409 | 2 | asciiFile.addPos(pos); |
1410 | 2 | asciiFile.addNote(f.str().c_str()); |
1411 | 2 | auto fSz=static_cast<int>(input->readULong(1)); |
1412 | 2 | if (fSz == dataSz-2 || fSz==dataSz-1) { |
1413 | 1 | std::string bkmark(""); |
1414 | 1 | for (int c=0; c < fSz; c++) |
1415 | 0 | bkmark+=char(input->readULong(1)); |
1416 | 1 | f << bkmark; |
1417 | | |
1418 | 1 | zone.m_tokenList[size_t(bkmIdList[i])].m_bookmark=bkmark; |
1419 | 1 | } |
1420 | 1 | else { |
1421 | 1 | MWAW_DEBUG_MSG(("HanMacWrdJText::readTextToken: can not read bookmark text %d\n", int(i))); |
1422 | 1 | f << "###"; |
1423 | 1 | } |
1424 | 2 | asciiFile.addPos(pos); |
1425 | 2 | asciiFile.addNote(f.str().c_str()); |
1426 | | |
1427 | 2 | pos = zoneEnd; |
1428 | 2 | input->seek(zoneEnd, librevenge::RVNG_SEEK_SET); |
1429 | 2 | } |
1430 | 2.45k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1431 | 2.45k | return true; |
1432 | 17.3k | } |
1433 | | |
1434 | | //////////////////////////////////////////////////////////// |
1435 | | // Fonts |
1436 | | //////////////////////////////////////////////////////////// |
1437 | | |
1438 | | // a single font |
1439 | | bool HanMacWrdJText::readFont(MWAWFont &font, long endPos) |
1440 | 73.8k | { |
1441 | 73.8k | font = MWAWFont(-1, -1); |
1442 | | |
1443 | 73.8k | MWAWInputStreamPtr input = m_parserState->m_input; |
1444 | 73.8k | long pos = input->tell(), debPos=pos; |
1445 | 73.8k | if (endPos <= 0) { |
1446 | 73.8k | auto dataSz=long(input->readULong(4)); |
1447 | 73.8k | pos+=4; |
1448 | 73.8k | endPos=pos+dataSz; |
1449 | 73.8k | if (!input->checkPosition(endPos)) { |
1450 | 1.90k | MWAW_DEBUG_MSG(("HanMacWrdJText::readFont: pb reading font size\n")); |
1451 | 1.90k | input->seek(debPos, librevenge::RVNG_SEEK_SET); |
1452 | 1.90k | return false; |
1453 | 1.90k | } |
1454 | 73.8k | } |
1455 | 71.9k | long len=endPos-pos; |
1456 | 71.9k | if (len < 24) { |
1457 | 609 | MWAW_DEBUG_MSG(("HanMacWrdJText::readFont: the zone is too short\n")); |
1458 | 609 | input->seek(debPos, librevenge::RVNG_SEEK_SET); |
1459 | 609 | return false; |
1460 | 609 | } |
1461 | | |
1462 | 71.3k | libmwaw::DebugStream f; |
1463 | 71.3k | font.setId(static_cast<int>(input->readLong(2))); |
1464 | 71.3k | auto val = static_cast<int>(input->readLong(2)); |
1465 | 71.3k | if (val) f << "#f1=" << val << ","; |
1466 | 71.3k | font.setSize(float(input->readLong(4))/65536.f); |
1467 | 71.3k | float expand = float(input->readLong(4))/65536.f; |
1468 | 71.3k | if (expand < 0 || expand > 0) |
1469 | 735 | font.setDeltaLetterSpacing(expand*font.size()); |
1470 | 71.3k | float xScale = float(input->readLong(4))/65536.f; |
1471 | 71.3k | if (xScale < 1 || xScale > 1) |
1472 | 2.09k | font.setWidthStreching(xScale); |
1473 | | |
1474 | 71.3k | auto flag =static_cast<int>(input->readULong(2)); |
1475 | 71.3k | uint32_t flags=0; |
1476 | 71.3k | if (flag&1) { |
1477 | 134 | font.setUnderlineStyle(MWAWFont::Line::Simple); |
1478 | 134 | font.setUnderlineType(MWAWFont::Line::Double); |
1479 | 134 | } |
1480 | 71.3k | if (flag&2) |
1481 | 170 | font.setUnderlineStyle(MWAWFont::Line::Dot); |
1482 | 71.3k | if (flag&4) { |
1483 | 269 | font.setUnderlineStyle(MWAWFont::Line::Dot); |
1484 | 269 | font.setUnderlineWidth(2.0); |
1485 | 269 | } |
1486 | 71.3k | if (flag&8) |
1487 | 424 | font.setUnderlineStyle(MWAWFont::Line::Dash); |
1488 | 71.3k | if (flag&0x10) |
1489 | 1.06k | font.setStrikeOutStyle(MWAWFont::Line::Simple); |
1490 | 71.3k | if (flag&0x20) { |
1491 | 1.08k | font.setStrikeOutStyle(MWAWFont::Line::Simple); |
1492 | 1.08k | font.setStrikeOutType(MWAWFont::Line::Double); |
1493 | 1.08k | } |
1494 | 71.3k | if (flag&0xFFC0) |
1495 | 1.35k | f << "#flag0=" << std::hex << (flag&0xFFF2) << std::dec << ","; |
1496 | 71.3k | flag =static_cast<int>(input->readULong(2)); |
1497 | 71.3k | if (flag&1) flags |= MWAWFont::boldBit; |
1498 | 71.3k | if (flag&0x2) flags |= MWAWFont::italicBit; |
1499 | 71.3k | if (flag&0x4) flags |= MWAWFont::outlineBit; |
1500 | 71.3k | if (flag&0x8) flags |= MWAWFont::shadowBit; |
1501 | 71.3k | if (flag&0x10) flags |= MWAWFont::reverseVideoBit; |
1502 | 71.3k | if (flag&0x20) font.set(MWAWFont::Script::super100()); |
1503 | 71.3k | if (flag&0x40) font.set(MWAWFont::Script::sub100()); |
1504 | 71.3k | if (flag&0x80) { |
1505 | 4.62k | if (flag&0x20) |
1506 | 671 | font.set(MWAWFont::Script(48,librevenge::RVNG_PERCENT,58)); |
1507 | 3.95k | else if (flag&0x40) |
1508 | 3.91k | font.set(MWAWFont::Script(16,librevenge::RVNG_PERCENT,58)); |
1509 | 39 | else |
1510 | 39 | font.set(MWAWFont::Script::super()); |
1511 | 4.62k | } |
1512 | 71.3k | if (flag&0x100) { |
1513 | 3.92k | font.setOverlineStyle(MWAWFont::Line::Dot); |
1514 | 3.92k | font.setOverlineWidth(2.0); |
1515 | 3.92k | } |
1516 | 71.3k | if (flag&0x200) flags |= MWAWFont::boxedBit; |
1517 | 71.3k | if (flag&0x400) flags |= MWAWFont::boxedRoundedBit; |
1518 | 71.3k | if (flag&0x800) { |
1519 | 4.55k | font.setUnderlineStyle(MWAWFont::Line::Simple); |
1520 | 4.55k | font.setUnderlineWidth(0.5); |
1521 | 4.55k | } |
1522 | 71.3k | if (flag&0x1000) font.setUnderlineStyle(MWAWFont::Line::Simple); |
1523 | 71.3k | if (flag&0x2000) { |
1524 | 1.03k | font.setUnderlineStyle(MWAWFont::Line::Simple); |
1525 | 1.03k | font.setUnderlineWidth(2.0); |
1526 | 1.03k | } |
1527 | 71.3k | if (flag&0x4000) { |
1528 | 731 | font.setUnderlineStyle(MWAWFont::Line::Simple); |
1529 | 731 | font.setUnderlineWidth(3.0); |
1530 | 731 | } |
1531 | | |
1532 | 71.3k | if (flag&0x8000) { |
1533 | 685 | font.setUnderlineStyle(MWAWFont::Line::Simple); |
1534 | 685 | font.setUnderlineType(MWAWFont::Line::Double); |
1535 | 685 | font.setUnderlineWidth(0.5); |
1536 | 685 | } |
1537 | 71.3k | auto color = static_cast<int>(input->readLong(2)); |
1538 | 71.3k | MWAWColor col; |
1539 | 71.3k | if (color && m_mainParser->getColor(color, 1, col)) |
1540 | 80 | font.setColor(col); |
1541 | 71.2k | else if (color) |
1542 | 1.29k | f << "##fColor=" << color << ","; |
1543 | 71.3k | val = static_cast<int>(input->readLong(2)); |
1544 | 71.3k | if (val) f << "#unk=" << val << ","; |
1545 | 71.3k | if (len >= 28) { |
1546 | 213k | for (int i = 0; i < 2; i++) { |
1547 | 142k | val = static_cast<int>(input->readLong(2)); |
1548 | 142k | if (val) f << "#g" << i << "=" << val << ","; |
1549 | 142k | } |
1550 | 71.2k | } |
1551 | 71.3k | if (len >= 36) { |
1552 | 71.1k | color = static_cast<int>(input->readLong(2)); |
1553 | 71.1k | auto pattern = static_cast<int>(input->readLong(2)); |
1554 | 71.1k | if ((color || pattern) && m_mainParser->getColor(color, pattern, col)) |
1555 | 142 | font.setBackgroundColor(col); |
1556 | 70.9k | else if (color || pattern) |
1557 | 1.30k | f << "#backColor=" << color << ", #pattern=" << pattern << ","; |
1558 | 71.1k | } |
1559 | 71.3k | if (input->tell() != endPos) |
1560 | 71.2k | m_parserState->m_asciiFile.addDelimiter(input->tell(),'|'); |
1561 | 71.3k | font.setFlags(flags); |
1562 | 71.3k | font.m_extra = f.str(); |
1563 | | |
1564 | 71.3k | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
1565 | 71.3k | return true; |
1566 | 71.9k | } |
1567 | | |
1568 | | bool HanMacWrdJText::readFonts(MWAWEntry const &entry) |
1569 | 14.3k | { |
1570 | 14.3k | if (!entry.valid()) { |
1571 | 0 | MWAW_DEBUG_MSG(("HanMacWrdJText::readFonts: called without any entry\n")); |
1572 | 0 | return false; |
1573 | 0 | } |
1574 | 14.3k | if (entry.length() <= 8) { |
1575 | 0 | MWAW_DEBUG_MSG(("HanMacWrdJText::readFonts: the entry seems too short\n")); |
1576 | 0 | return false; |
1577 | 0 | } |
1578 | 14.3k | if (m_state->m_fontList.size()) { |
1579 | 993 | MWAW_DEBUG_MSG(("HanMacWrdJText::readFonts: oops the font list is not empty\n")); |
1580 | 993 | m_state->m_fontList.resize(0); |
1581 | 993 | } |
1582 | 14.3k | MWAWInputStreamPtr input = m_parserState->m_input; |
1583 | 14.3k | libmwaw::DebugFile &asciiFile = m_parserState->m_asciiFile; |
1584 | 14.3k | libmwaw::DebugStream f; |
1585 | 14.3k | entry.setParsed(true); |
1586 | | |
1587 | 14.3k | long pos = entry.begin()+8; // skip header |
1588 | 14.3k | long endPos = entry.end(); |
1589 | 14.3k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1590 | | |
1591 | | // first read the header |
1592 | 14.3k | f << entry.name() << "[header]:"; |
1593 | 14.3k | HanMacWrdJZoneHeader mainHeader(false); |
1594 | 14.3k | if (!m_mainParser->readClassicHeader(mainHeader,endPos) || mainHeader.m_fieldSize!=8) { |
1595 | 8.16k | MWAW_DEBUG_MSG(("HanMacWrdJText::readFonts: can not read the header\n")); |
1596 | 8.16k | f << "###sz=" << mainHeader.m_length; |
1597 | 8.16k | asciiFile.addPos(pos); |
1598 | 8.16k | asciiFile.addNote(f.str().c_str()); |
1599 | 8.16k | return false; |
1600 | 8.16k | } |
1601 | 6.20k | long headerEnd=pos+4+mainHeader.m_length; |
1602 | 6.20k | f << mainHeader; |
1603 | 6.20k | f << "unk=["; |
1604 | 115k | for (int i = 0; i < mainHeader.m_n; i++) { |
1605 | 109k | f << "["; |
1606 | 109k | long val = input->readLong(2); // always -2 ? |
1607 | 109k | if (val!=-2) |
1608 | 6.87k | f << val << ","; |
1609 | 102k | else |
1610 | 102k | f << "_,"; |
1611 | 109k | val = long(input->readULong(2)); // 0 or 5020 : junk? |
1612 | 109k | if (val) |
1613 | 102k | f << std::hex << val << std::dec << ","; |
1614 | 6.80k | else |
1615 | 6.80k | f << "_,"; |
1616 | 109k | val = long(input->readULong(4)); // id |
1617 | 109k | f << std::hex << val << std::dec; |
1618 | 109k | f << "]"; |
1619 | 109k | } |
1620 | 6.20k | f << "],"; |
1621 | 6.20k | if (input->tell()!=headerEnd) { |
1622 | 6.20k | asciiFile.addDelimiter(input->tell(),'|'); |
1623 | 6.20k | input->seek(headerEnd, librevenge::RVNG_SEEK_SET); |
1624 | 6.20k | } |
1625 | 6.20k | asciiFile.addPos(pos); |
1626 | 6.20k | asciiFile.addNote(f.str().c_str()); |
1627 | | |
1628 | 77.3k | for (int i = 0; i < mainHeader.m_n; i++) { |
1629 | 73.8k | pos = input->tell(); |
1630 | 73.8k | f.str(""); |
1631 | 73.8k | f << entry.name() << "-" << i << ":"; |
1632 | 73.8k | MWAWFont font(-1, -1); |
1633 | 73.8k | if (!readFont(font) || input->tell() > endPos) { |
1634 | 2.66k | MWAW_DEBUG_MSG(("HanMacWrdJText::readFonts: can not read font %d\n", i)); |
1635 | 2.66k | f << "###"; |
1636 | 2.66k | asciiFile.addPos(pos); |
1637 | 2.66k | asciiFile.addNote(f.str().c_str()); |
1638 | 2.66k | return false; |
1639 | 2.66k | } |
1640 | 71.1k | f << font.getDebugString(m_parserState->m_fontConverter) << ","; |
1641 | 71.1k | m_state->m_fontList.push_back(font); |
1642 | 71.1k | asciiFile.addPos(pos); |
1643 | 71.1k | asciiFile.addNote(f.str().c_str()); |
1644 | 71.1k | } |
1645 | 3.54k | asciiFile.addPos(endPos); |
1646 | 3.54k | asciiFile.addNote("_"); |
1647 | 3.54k | return true; |
1648 | 6.20k | } |
1649 | | |
1650 | | // the list of fonts |
1651 | | bool HanMacWrdJText::readFontNames(MWAWEntry const &entry) |
1652 | 2.29k | { |
1653 | 2.29k | if (!entry.valid()) { |
1654 | 0 | MWAW_DEBUG_MSG(("HanMacWrdJText::readFontNames: called without any entry\n")); |
1655 | 0 | return false; |
1656 | 0 | } |
1657 | 2.29k | if (entry.length() < 28) { |
1658 | 72 | MWAW_DEBUG_MSG(("HanMacWrdJText::readFontNames: the entry seems too short\n")); |
1659 | 72 | return false; |
1660 | 72 | } |
1661 | 2.22k | MWAWInputStreamPtr input = m_parserState->m_input; |
1662 | 2.22k | libmwaw::DebugFile &asciiFile = m_parserState->m_asciiFile; |
1663 | 2.22k | libmwaw::DebugStream f; |
1664 | 2.22k | entry.setParsed(true); |
1665 | | |
1666 | 2.22k | f << entry.name() << "[data]:"; |
1667 | | |
1668 | 2.22k | long pos = entry.begin()+8; // skip header |
1669 | 2.22k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1670 | 2.22k | int N, val; |
1671 | 2.22k | auto readDataSz = long(input->readULong(4)); |
1672 | 2.22k | if (readDataSz+12 != entry.length()) { |
1673 | 163 | MWAW_DEBUG_MSG(("HanMacWrdJText::readFontNames: the data size seems odd\n")); |
1674 | 163 | f << "##dataSz=" << readDataSz << ","; |
1675 | 163 | } |
1676 | 2.22k | N = static_cast<int>(input->readLong(2)); |
1677 | 2.22k | f << "N=" << N << ","; |
1678 | 2.22k | auto fieldSz = long(input->readULong(4)); |
1679 | 2.22k | if (fieldSz != 68) { |
1680 | 166 | MWAW_DEBUG_MSG(("HanMacWrdJText::readFontNames: the field size seems odd\n")); |
1681 | 166 | f << "##fieldSz=" << fieldSz << ","; |
1682 | 166 | } |
1683 | 8.89k | for (int i = 0; i < 3; i++) { //f1=f2=1 |
1684 | 6.66k | val = static_cast<int>(input->readLong(2)); |
1685 | 6.66k | if (val) f << "f" << i << "=" << val << ","; |
1686 | 6.66k | } |
1687 | 2.22k | auto id = long(input->readULong(4)); |
1688 | 2.22k | if (id) f << "id=" << std::hex << id << std::dec << ","; |
1689 | | |
1690 | 2.22k | long expectedSz = N*68+28; |
1691 | 2.22k | if (expectedSz != entry.length() && expectedSz+1 != entry.length()) { |
1692 | 162 | MWAW_DEBUG_MSG(("HanMacWrdJText::readFontNames: the entry size seems odd\n")); |
1693 | 162 | return false; |
1694 | 162 | } |
1695 | 2.06k | asciiFile.addPos(pos); |
1696 | 2.06k | asciiFile.addNote(f.str().c_str()); |
1697 | | |
1698 | 4.12k | for (int i = 0; i < N; i++) { |
1699 | 2.05k | pos = input->tell(); |
1700 | 2.05k | f.str(""); |
1701 | 2.05k | f << entry.name() << "-" << i << ":"; |
1702 | 2.05k | auto fId = static_cast<int>(input->readLong(2)); |
1703 | 2.05k | f << "fId=" << fId << ","; |
1704 | 2.05k | val = static_cast<int>(input->readLong(2)); |
1705 | 2.05k | if (val != fId) |
1706 | 41 | f << "#fId2=" << val << ","; |
1707 | 2.05k | auto fSz = static_cast<int>(input->readULong(1)); |
1708 | 2.05k | if (fSz+5 > 68) { |
1709 | 35 | f << "###fSz"; |
1710 | 35 | MWAW_DEBUG_MSG(("HanMacWrdJText::readFontNames: can not read a font\n")); |
1711 | 35 | } |
1712 | 2.02k | else { |
1713 | 2.02k | std::string name(""); |
1714 | 14.4k | for (int c = 0; c < fSz; c++) |
1715 | 12.4k | name += char(input->readULong(1)); |
1716 | 2.02k | f << name; |
1717 | 2.02k | m_parserState->m_fontConverter->setCorrespondance(fId, name); |
1718 | 2.02k | } |
1719 | 2.05k | asciiFile.addPos(pos); |
1720 | 2.05k | asciiFile.addNote(f.str().c_str()); |
1721 | 2.05k | input->seek(pos+68, librevenge::RVNG_SEEK_SET); |
1722 | 2.05k | } |
1723 | 2.06k | asciiFile.addPos(entry.end()); |
1724 | 2.06k | asciiFile.addNote("_"); |
1725 | 2.06k | return true; |
1726 | 2.22k | } |
1727 | | |
1728 | | //////////////////////////////////////////////////////////// |
1729 | | // Style |
1730 | | //////////////////////////////////////////////////////////// |
1731 | | bool HanMacWrdJText::readStyles(MWAWEntry const &entry) |
1732 | 9.35k | { |
1733 | 9.35k | if (!entry.valid()) { |
1734 | 0 | MWAW_DEBUG_MSG(("HanMacWrdJText::readStyles: called without any zone\n")); |
1735 | 0 | return false; |
1736 | 0 | } |
1737 | | |
1738 | 9.35k | long dataSz = entry.length(); |
1739 | 9.35k | if (dataSz < 4) { |
1740 | 0 | MWAW_DEBUG_MSG(("HanMacWrdJText::readStyles: the zone seems too short\n")); |
1741 | 0 | return false; |
1742 | 0 | } |
1743 | 9.35k | MWAWInputStreamPtr input = m_parserState->m_input; |
1744 | 9.35k | libmwaw::DebugFile &asciiFile = m_parserState->m_asciiFile; |
1745 | 9.35k | libmwaw::DebugStream f; |
1746 | 9.35k | entry.setParsed(true); |
1747 | | |
1748 | 9.35k | f << entry.name() << "[header]:"; |
1749 | | |
1750 | 9.35k | long pos = entry.begin()+8; // skip header |
1751 | 9.35k | long endPos = entry.end(); |
1752 | 9.35k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1753 | | |
1754 | 9.35k | HanMacWrdJZoneHeader mainHeader(false); |
1755 | 9.35k | if (!m_mainParser->readClassicHeader(mainHeader,endPos) || mainHeader.m_fieldSize!=4) { |
1756 | 1.34k | MWAW_DEBUG_MSG(("HanMacWrdJText::readStyles: can not read the header\n")); |
1757 | 1.34k | f << "###sz=" << mainHeader.m_length; |
1758 | 1.34k | asciiFile.addPos(pos); |
1759 | 1.34k | asciiFile.addNote(f.str().c_str()); |
1760 | 1.34k | return false; |
1761 | 1.34k | } |
1762 | 8.01k | long headerEnd=pos+4+mainHeader.m_length; |
1763 | 8.01k | f << mainHeader; |
1764 | | |
1765 | 8.01k | f << "listIds=[" << std::hex; |
1766 | 148k | for (int i = 0; i < mainHeader.m_n; i++) |
1767 | 140k | f << input->readULong(4) << ","; |
1768 | 8.01k | f << std::dec << "],"; |
1769 | 8.01k | input->seek(headerEnd, librevenge::RVNG_SEEK_SET); |
1770 | 8.01k | asciiFile.addPos(pos); |
1771 | 8.01k | asciiFile.addNote(f.str().c_str()); |
1772 | | |
1773 | 113k | for (int i = 0; i < mainHeader.m_n; i++) { |
1774 | 108k | f.str(""); |
1775 | 108k | f << entry.name() << "-" << i << ":"; |
1776 | 108k | pos = input->tell(); |
1777 | 108k | long fieldSz = long(input->readULong(4))+4; |
1778 | 108k | if (fieldSz < 0x1bc || pos+fieldSz > endPos) { |
1779 | 3.13k | f << "###"; |
1780 | 3.13k | asciiFile.addPos(pos); |
1781 | 3.13k | asciiFile.addNote(f.str().c_str()); |
1782 | | |
1783 | 3.13k | MWAW_DEBUG_MSG(("HanMacWrdJText::readStyles: can not read field %d\n", i)); |
1784 | 3.13k | return true; |
1785 | 3.13k | } |
1786 | 105k | auto val = static_cast<int>(input->readULong(1)); |
1787 | 105k | if (val != i) f << "#id=" << val << ","; |
1788 | | |
1789 | | // f0=c2|c6, f2=0|44, f3=1|14|15|16: fontId? |
1790 | 633k | for (int j=0; j < 5; j++) { |
1791 | 527k | val = static_cast<int>(input->readULong(1)); |
1792 | 527k | if (val) |
1793 | 211k | f << "f" << j << "=" << std::hex << val << std::dec << ","; |
1794 | 527k | } |
1795 | | /* g1=9|a|c|e|12|18: size ?, g5=1, g8=0|1, g25=0|18|30|48, g31=1, g35=0|1 */ |
1796 | 3.58M | for (int j=0; j < 33; j++) { |
1797 | 3.48M | val = static_cast<int>(input->readULong(2)); |
1798 | 3.48M | if (val) |
1799 | 524k | f << "g" << j << "=" << val << ","; |
1800 | 3.48M | } |
1801 | 527k | for (int j=0; j < 4; j++) { // b,b,b,0 |
1802 | 422k | val = static_cast<int>(input->readULong(1)); |
1803 | 422k | if ((j < 3 && val != 0xb) || (j==3 && val)) |
1804 | 1.92k | f << "h" << j << "=" << val << ","; |
1805 | 422k | } |
1806 | | |
1807 | 1.89M | for (int j=0; j < 17; j++) { // always 0 |
1808 | 1.79M | val = static_cast<int>(input->readULong(2)); |
1809 | 1.79M | if (val) |
1810 | 10.1k | f << "l" << j << "=" << val << ","; |
1811 | 1.79M | } |
1812 | 105k | asciiFile.addPos(pos); |
1813 | 105k | asciiFile.addNote(f.str().c_str()); |
1814 | 105k | long pos2 = input->tell(); |
1815 | 105k | f.str(""); |
1816 | 105k | f << entry.name() << "-" << i << "[B]:"; |
1817 | | // checkme probably f15=numTabs .. |
1818 | 5.38M | for (int j = 0; j < 50; j++) { |
1819 | 5.27M | val = static_cast<int>(input->readULong(2)); |
1820 | 5.27M | if ((j < 5 && val != 1) || (j >= 5 && val)) |
1821 | 11.8k | f << "f" << j << "=" << val << ","; |
1822 | 5.27M | } |
1823 | 5.38M | for (int j = 0; j < 50; j++) { |
1824 | 5.27M | val = static_cast<int>(input->readULong(2)); |
1825 | 5.27M | if (val) |
1826 | 4.38k | f << "g" << j << "=" << val << ","; |
1827 | 5.27M | } |
1828 | 4.64M | for (int j = 0; j < 43; j++) { |
1829 | 4.53M | val = static_cast<int>(input->readULong(2)); |
1830 | 4.53M | if (val) |
1831 | 8.92k | f << "h" << j << "=" << val << ","; |
1832 | 4.53M | } |
1833 | 105k | asciiFile.addPos(pos2); |
1834 | 105k | asciiFile.addNote(f.str().c_str()); |
1835 | | |
1836 | 105k | pos2 = input->tell(); |
1837 | 105k | f.str(""); |
1838 | 105k | f << entry.name() << "-" << i << "[C]:"; |
1839 | 105k | val = static_cast<int>(input->readLong(2)); |
1840 | 105k | if (val != -1) f << "unkn=" << val << ","; |
1841 | 105k | val = static_cast<int>(input->readLong(2)); |
1842 | 105k | if (val != i) f << "#id" << val << ","; |
1843 | 527k | for (int j = 0; j < 4; j++) { |
1844 | 422k | val = static_cast<int>(input->readLong(2)); |
1845 | 422k | if (val) f << "f" << j << "=" << val << ","; |
1846 | 422k | } |
1847 | 105k | auto fSz = static_cast<int>(input->readULong(1)); |
1848 | 105k | if (input->tell()+fSz > pos+fieldSz) { |
1849 | 180 | MWAW_DEBUG_MSG(("HanMacWrdJText::readStyles: can not read styleName\n")); |
1850 | 180 | f << "###"; |
1851 | 180 | } |
1852 | 105k | else { |
1853 | 105k | std::string name(""); |
1854 | 797k | for (int j = 0; j < fSz; j++) |
1855 | 692k | name +=char(input->readULong(1)); |
1856 | 105k | f << name; |
1857 | 105k | } |
1858 | 105k | asciiFile.addPos(pos2); |
1859 | 105k | asciiFile.addNote(f.str().c_str()); |
1860 | 105k | if (input->tell() != pos+fieldSz) |
1861 | 105k | asciiFile.addDelimiter(input->tell(),'|'); |
1862 | | |
1863 | 105k | input->seek(pos+fieldSz, librevenge::RVNG_SEEK_SET); |
1864 | 105k | } |
1865 | | |
1866 | 4.87k | if (!input->isEnd()) { |
1867 | 4.87k | asciiFile.addPos(input->tell()); |
1868 | 4.87k | asciiFile.addNote("_"); |
1869 | 4.87k | } |
1870 | 4.87k | return true; |
1871 | 8.01k | } |
1872 | | |
1873 | | //////////////////////////////////////////////////////////// |
1874 | | // Paragraph |
1875 | | //////////////////////////////////////////////////////////// |
1876 | | bool HanMacWrdJText::readParagraph(HanMacWrdJTextInternal::Paragraph ¶, long endPos) |
1877 | 52.9k | { |
1878 | 52.9k | para = HanMacWrdJTextInternal::Paragraph(); |
1879 | | |
1880 | 52.9k | MWAWInputStreamPtr input = m_parserState->m_input; |
1881 | 52.9k | long pos = input->tell(), debPos=pos; |
1882 | 52.9k | if (endPos <= 0) { |
1883 | 52.9k | auto dataSz=long(input->readULong(4)); |
1884 | 52.9k | pos+=4; |
1885 | 52.9k | endPos=pos+dataSz; |
1886 | 52.9k | if (!input->checkPosition(endPos)) { |
1887 | 1.43k | MWAW_DEBUG_MSG(("HanMacWrdJText::readParagraph: pb reading para size\n")); |
1888 | 1.43k | input->seek(debPos, librevenge::RVNG_SEEK_SET); |
1889 | 1.43k | return false; |
1890 | 1.43k | } |
1891 | 52.9k | } |
1892 | 51.5k | long len=endPos-pos; |
1893 | 51.5k | if (len < 102) { |
1894 | 715 | MWAW_DEBUG_MSG(("HanMacWrdJText::readParagraph: the zone is too short\n")); |
1895 | 715 | input->seek(debPos, librevenge::RVNG_SEEK_SET); |
1896 | 715 | return false; |
1897 | 715 | } |
1898 | | |
1899 | 50.8k | libmwaw::DebugStream f; |
1900 | 50.8k | libmwaw::DebugFile &asciiFile = m_parserState->m_asciiFile; |
1901 | 50.8k | auto flags = static_cast<int>(input->readULong(1)); |
1902 | 50.8k | if (flags&0x80) |
1903 | 76 | para.m_breakStatus = para.m_breakStatus.get()|MWAWParagraph::NoBreakWithNextBit; |
1904 | 50.8k | if (flags&0x40) |
1905 | 199 | para.m_breakStatus = para.m_breakStatus.get()|MWAWParagraph::NoBreakBit; |
1906 | 50.8k | if (flags&0x2) |
1907 | 148 | para.m_addPageBreak = true; |
1908 | 50.8k | if (flags&0x4) |
1909 | 81 | f << "linebreakByWord,"; |
1910 | | |
1911 | 50.8k | if (flags & 0x39) f << "#fl=" << std::hex << (flags&0x39) << std::dec << ","; |
1912 | | |
1913 | 50.8k | auto val = static_cast<int>(input->readLong(2)); |
1914 | 50.8k | if (val) f << "#f0=" << val << ","; |
1915 | 50.8k | val = static_cast<int>(input->readULong(2)); |
1916 | 50.8k | switch (val&3) { |
1917 | 35.2k | case 0: |
1918 | 35.2k | para.m_justify = MWAWParagraph::JustificationLeft; |
1919 | 35.2k | break; |
1920 | 5.19k | case 1: |
1921 | 5.19k | para.m_justify = MWAWParagraph::JustificationRight; |
1922 | 5.19k | break; |
1923 | 5.32k | case 2: |
1924 | 5.32k | para.m_justify = MWAWParagraph::JustificationCenter; |
1925 | 5.32k | break; |
1926 | 5.05k | case 3: |
1927 | 5.05k | para.m_justify = MWAWParagraph::JustificationFull; |
1928 | 5.05k | break; |
1929 | 0 | default: |
1930 | 0 | break; |
1931 | 50.8k | } |
1932 | 50.8k | if (val&0xFFFC) f << "#f1=" << val << ","; |
1933 | 50.8k | val = static_cast<int>(input->readLong(1)); |
1934 | 50.8k | if (val) f << "#f2=" << val << ","; |
1935 | 50.8k | para.m_type = static_cast<int>(input->readLong(2)); |
1936 | | |
1937 | 50.8k | float dim[3]; |
1938 | 152k | for (auto &d : dim) d = float(input->readLong(4))/65536.0f; |
1939 | 50.8k | para.m_marginsUnit = librevenge::RVNG_POINT; |
1940 | 50.8k | para.m_margins[0]=double(dim[1]); |
1941 | 50.8k | para.m_margins[1]=double(dim[0]); |
1942 | 50.8k | para.m_margins[2]=double(dim[2]); // ie. distance to right border - ... |
1943 | | |
1944 | 50.8k | for (auto &spacing : para.m_spacings) |
1945 | 152k | spacing = double(input->readLong(4))/65536.0; |
1946 | 50.8k | int spacingsUnit[3]; // 1=mm, ..., 4=pt, b=line |
1947 | 152k | for (auto &s : spacingsUnit) s= static_cast<int>(input->readULong(1)); |
1948 | 50.8k | if (spacingsUnit[0]==0xb) |
1949 | 46.5k | para.m_spacingsInterlineUnit = librevenge::RVNG_PERCENT; |
1950 | 4.32k | else |
1951 | 4.32k | para.m_spacingsInterlineUnit = librevenge::RVNG_POINT; |
1952 | 152k | for (int i = 1; i < 3; i++) // convert point|line -> inches |
1953 | 101k | para.m_spacings[i]= ((spacingsUnit[i]==0xb) ? 12.0 : 1.0)*(para.m_spacings[i].get())/72.0; |
1954 | | |
1955 | 50.8k | val = static_cast<int>(input->readLong(1)); |
1956 | 50.8k | if (val) f << "#f3=" << val << ","; |
1957 | 152k | for (int i = 0; i< 2; i++) { // one time f4=8000 |
1958 | 101k | val = static_cast<int>(input->readULong(2)); |
1959 | 101k | if (val) f << "#f" << i+4 << "=" << std::hex << val << std::dec << ","; |
1960 | 101k | } |
1961 | | // the borders |
1962 | 50.8k | char const *wh[5] = { "T", "L", "B", "R", "VSep" }; |
1963 | 50.8k | MWAWBorder borders[5]; |
1964 | 254k | for (auto &border : borders) border.m_width = double(input->readLong(4))/65536.; |
1965 | 304k | for (int d=0; d < 5; d++) { |
1966 | 254k | val = static_cast<int>(input->readULong(1)); |
1967 | 254k | switch (val) { |
1968 | 252k | case 0: // normal |
1969 | 252k | break; |
1970 | 450 | case 1: |
1971 | 450 | borders[d].m_type = MWAWBorder::Double; |
1972 | 450 | break; |
1973 | 122 | case 2: |
1974 | 122 | borders[d].m_type = MWAWBorder::Double; |
1975 | 122 | f << "bord" << wh[d] << "[ext=2],"; |
1976 | 122 | break; |
1977 | 211 | case 3: |
1978 | 211 | borders[d].m_type = MWAWBorder::Double; |
1979 | 211 | f << "bord" << wh[d] << "[int=2],"; |
1980 | 211 | break; |
1981 | 562 | default: |
1982 | 562 | f << "#bord" << wh[d] << "[style=" << val << "],"; |
1983 | 562 | break; |
1984 | 254k | } |
1985 | 254k | } |
1986 | 50.8k | int color[5], pattern[5]; |
1987 | 254k | for (auto &c : color) c = static_cast<int>(input->readULong(1)); |
1988 | 254k | for (auto &p : pattern) p= static_cast<int>(input->readULong(2)); |
1989 | 304k | for (int d=0; d < 5; d++) { |
1990 | 254k | if (!color[d] && !pattern[d]) |
1991 | 2.64k | continue; |
1992 | 251k | MWAWColor col; |
1993 | 251k | if (m_mainParser->getColor(color[d], pattern[d], col)) |
1994 | 248k | borders[d].m_color = col; |
1995 | 3.19k | else |
1996 | 3.19k | f << "#bord" << wh[d] << "[col=" << color[d] << ",pat=" << pattern[d] << "],"; |
1997 | 251k | } |
1998 | | // update the paragraph |
1999 | 50.8k | para.resizeBorders(6); |
2000 | 50.8k | libmwaw::Position const which[5] = { |
2001 | 50.8k | libmwaw::Top, libmwaw::Left, libmwaw::Bottom, libmwaw::Right, |
2002 | 50.8k | libmwaw::VMiddle |
2003 | 50.8k | }; |
2004 | 304k | for (int d=0; d < 5; d++) { |
2005 | 254k | if (borders[d].m_width <= 0) |
2006 | 252k | continue; |
2007 | 1.34k | para.m_borders[which[d]]=borders[d]; |
2008 | 1.34k | } |
2009 | 50.8k | val = static_cast<int>(input->readLong(1)); |
2010 | 50.8k | if (val) f << "#f6=" << val << ","; |
2011 | 50.8k | double bMargins[5]= {0,0,0,0,0}; |
2012 | 304k | for (int d = 0; d < 5; d++) { |
2013 | 254k | bMargins[d] = double(input->readLong(4))/256./65536./72.; |
2014 | 254k | if (bMargins[d] > 0 || bMargins[d] < 0) |
2015 | 9.84k | f << "bordMarg" << wh[d] << "=" << bMargins[d] << ","; |
2016 | 254k | } |
2017 | 50.8k | auto nTabs = static_cast<int>(input->readULong(1)); |
2018 | 50.8k | if (input->tell()+2+nTabs*12 > endPos) { |
2019 | 111 | MWAW_DEBUG_MSG(("HanMacWrdJText::readParagraph: can not read numbers of tab\n")); |
2020 | 111 | input->seek(debPos, librevenge::RVNG_SEEK_SET); |
2021 | 111 | return false; |
2022 | 111 | } |
2023 | 50.7k | val = static_cast<int>(input->readULong(2)); |
2024 | 50.7k | if (val) f << "#h3=" << val << ","; |
2025 | 50.7k | para.m_extra=f.str(); |
2026 | 50.7k | f.str(""); |
2027 | 50.7k | f << "Ruler:" << para; |
2028 | | |
2029 | 50.7k | asciiFile.addPos(debPos); |
2030 | 50.7k | asciiFile.addNote(f.str().c_str()); |
2031 | 106k | for (int i = 0; i < nTabs; i++) { |
2032 | 55.8k | pos = input->tell(); |
2033 | 55.8k | f.str(""); |
2034 | 55.8k | f << "Ruler[Tabs-" << i << "]:"; |
2035 | | |
2036 | 55.8k | MWAWTabStop tab; |
2037 | 55.8k | val = static_cast<int>(input->readULong(1)); |
2038 | 55.8k | switch (val) { |
2039 | 26.5k | case 0: |
2040 | 26.5k | break; |
2041 | 10.3k | case 1: |
2042 | 10.3k | tab.m_alignment = MWAWTabStop::CENTER; |
2043 | 10.3k | break; |
2044 | 3.59k | case 2: |
2045 | 3.59k | tab.m_alignment = MWAWTabStop::RIGHT; |
2046 | 3.59k | break; |
2047 | 10.6k | case 3: |
2048 | 10.6k | tab.m_alignment = MWAWTabStop::DECIMAL; |
2049 | 10.6k | break; |
2050 | 173 | case 4: |
2051 | 173 | tab.m_alignment = MWAWTabStop::BAR; |
2052 | 173 | break; |
2053 | 4.52k | default: |
2054 | 4.52k | f << "#type=" << val << ","; |
2055 | 4.52k | break; |
2056 | 55.8k | } |
2057 | 55.8k | val = static_cast<int>(input->readULong(1)); |
2058 | 55.8k | if (val) f << "barType=" << val << ","; |
2059 | 55.8k | val = static_cast<int>(input->readULong(2)); |
2060 | 55.8k | if (val) { |
2061 | 15.5k | int unicode= m_parserState->m_fontConverter->unicode(3, static_cast<unsigned char>(val)); |
2062 | 15.5k | if (unicode==-1) |
2063 | 4.29k | tab.m_decimalCharacter = uint16_t(val); |
2064 | 11.2k | else |
2065 | 11.2k | tab.m_decimalCharacter = uint16_t(unicode); |
2066 | 15.5k | } |
2067 | 55.8k | val = static_cast<int>(input->readULong(2)); |
2068 | 55.8k | if (val) { |
2069 | 5.02k | int unicode= m_parserState->m_fontConverter->unicode(3, static_cast<unsigned char>(val)); |
2070 | 5.02k | if (unicode==-1) |
2071 | 4.19k | tab.m_leaderCharacter = uint16_t(val); |
2072 | 835 | else |
2073 | 835 | tab.m_leaderCharacter = uint16_t(unicode); |
2074 | 5.02k | } |
2075 | 55.8k | val = static_cast<int>(input->readULong(2)); // 0|73|74|a044|f170|f1e0|f590 |
2076 | 55.8k | if (val) f << "f0=" << std::hex << val << std::dec << ","; |
2077 | | |
2078 | 55.8k | tab.m_position = double(input->readLong(4))/65536./72.; |
2079 | 55.8k | para.m_tabs->push_back(tab); |
2080 | 55.8k | f << tab; |
2081 | | |
2082 | 55.8k | asciiFile.addPos(pos); |
2083 | 55.8k | asciiFile.addNote(f.str().c_str()); |
2084 | 55.8k | input->seek(pos+12, librevenge::RVNG_SEEK_SET); |
2085 | 55.8k | } |
2086 | 50.7k | if (input->tell()!=endPos) { |
2087 | 50.7k | asciiFile.addDelimiter(input->tell(),'|'); |
2088 | 50.7k | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
2089 | 50.7k | } |
2090 | 50.7k | return true; |
2091 | 50.7k | } |
2092 | | |
2093 | | bool HanMacWrdJText::readParagraphs(MWAWEntry const &entry) |
2094 | 6.92k | { |
2095 | 6.92k | if (!entry.valid()) { |
2096 | 0 | MWAW_DEBUG_MSG(("HanMacWrdJText::readParagraphs: called without any entry\n")); |
2097 | 0 | return false; |
2098 | 0 | } |
2099 | 6.92k | if (entry.length() <= 8) { |
2100 | 0 | MWAW_DEBUG_MSG(("HanMacWrdJText::readParagraphs: the entry seems too short\n")); |
2101 | 0 | return false; |
2102 | 0 | } |
2103 | 6.92k | if (m_state->m_paragraphList.size()) { |
2104 | 328 | MWAW_DEBUG_MSG(("HanMacWrdJText::readParagraphs: oops the paragraph list is not empty\n")); |
2105 | 328 | m_state->m_paragraphList.resize(0); |
2106 | 328 | } |
2107 | | |
2108 | 6.92k | MWAWInputStreamPtr input = m_parserState->m_input; |
2109 | 6.92k | libmwaw::DebugFile &asciiFile = m_parserState->m_asciiFile; |
2110 | 6.92k | libmwaw::DebugStream f; |
2111 | 6.92k | entry.setParsed(true); |
2112 | | |
2113 | 6.92k | long pos = entry.begin()+8; // skip header |
2114 | 6.92k | long endPos = entry.end(); |
2115 | 6.92k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
2116 | | |
2117 | | // first read the header |
2118 | 6.92k | f << entry.name() << "[header]:"; |
2119 | 6.92k | HanMacWrdJZoneHeader mainHeader(false); |
2120 | 6.92k | if (!m_mainParser->readClassicHeader(mainHeader,endPos) || mainHeader.m_fieldSize!=12) { |
2121 | 1.38k | MWAW_DEBUG_MSG(("HanMacWrdJText::readParagraphs: can not read the header\n")); |
2122 | 1.38k | f << "###sz=" << mainHeader.m_length; |
2123 | 1.38k | asciiFile.addPos(pos); |
2124 | 1.38k | asciiFile.addNote(f.str().c_str()); |
2125 | 1.38k | return false; |
2126 | 1.38k | } |
2127 | 5.54k | long headerEnd=pos+4+mainHeader.m_length; |
2128 | 5.54k | f << mainHeader; |
2129 | | |
2130 | 5.54k | f << "unk=["; |
2131 | 71.2k | for (int i = 0; i < mainHeader.m_n; i++) { |
2132 | 65.7k | f << "["; |
2133 | 65.7k | long val = input->readLong(2); // always -2 ? |
2134 | 65.7k | if (val!=-2) |
2135 | 745 | f << "unkn0=" << val << ","; |
2136 | 65.7k | val = long(input->readULong(2)); // 0|1|2|5 |
2137 | 65.7k | if (val) |
2138 | 11.0k | f << "type=" << val << ","; |
2139 | 65.7k | val = long(input->readULong(4)); // a id |
2140 | 65.7k | if (val) |
2141 | 65.5k | f << "id1=" << std::hex << val << std::dec << ","; |
2142 | 65.7k | val = long(input->readULong(4)); |
2143 | 65.7k | if (val) |
2144 | 16.6k | f << "id2=" << std::hex << val << std::dec << ","; |
2145 | 65.7k | f << "]"; |
2146 | 65.7k | } |
2147 | 5.54k | f << "],"; |
2148 | 5.54k | if (input->tell()!=headerEnd) { |
2149 | 89 | asciiFile.addDelimiter(input->tell(),'|'); |
2150 | 89 | input->seek(headerEnd, librevenge::RVNG_SEEK_SET); |
2151 | 89 | } |
2152 | 5.54k | asciiFile.addPos(pos); |
2153 | 5.54k | asciiFile.addNote(f.str().c_str()); |
2154 | | |
2155 | 55.7k | for (int i = 0; i < mainHeader.m_n; i++) { |
2156 | 52.9k | pos = input->tell(); |
2157 | 52.9k | HanMacWrdJTextInternal::Paragraph paragraph; |
2158 | 52.9k | if (!readParagraph(paragraph) || input->tell() > endPos) { |
2159 | 2.81k | MWAW_DEBUG_MSG(("HanMacWrdJText::readParagraphs: can not read paragraph %d\n", i)); |
2160 | 2.81k | asciiFile.addPos(pos); |
2161 | 2.81k | asciiFile.addNote("Ruler###"); |
2162 | 2.81k | return false; |
2163 | 2.81k | } |
2164 | 50.1k | m_state->m_paragraphList.push_back(paragraph); |
2165 | 50.1k | } |
2166 | 2.73k | asciiFile.addPos(endPos); |
2167 | 2.73k | asciiFile.addNote("_"); |
2168 | 2.73k | return true; |
2169 | 5.54k | } |
2170 | | |
2171 | | //////////////////////////////////////////////////////////// |
2172 | | // the sections/footnotes |
2173 | | //////////////////////////////////////////////////////////// |
2174 | | bool HanMacWrdJText::readSections(MWAWEntry const &entry) |
2175 | 2.35k | { |
2176 | 2.35k | if (!entry.valid()) { |
2177 | 0 | MWAW_DEBUG_MSG(("HanMacWrdJText::readSections: called without any entry\n")); |
2178 | 0 | return false; |
2179 | 0 | } |
2180 | 2.35k | if (entry.length() < 20) { |
2181 | 31 | MWAW_DEBUG_MSG(("HanMacWrdJText::readSections: the entry seems too short\n")); |
2182 | 31 | return false; |
2183 | 31 | } |
2184 | 2.32k | if (m_state->m_sectionList.size()) { |
2185 | 6 | MWAW_DEBUG_MSG(("HanMacWrdJText::readSections: the list of section is not empty\n")); |
2186 | 6 | m_state->m_sectionList.resize(0); |
2187 | 6 | } |
2188 | 2.32k | long pos = entry.begin()+8; // skip header |
2189 | 2.32k | long endPos = entry.end(); |
2190 | | |
2191 | 2.32k | MWAWInputStreamPtr input = m_parserState->m_input; |
2192 | 2.32k | libmwaw::DebugFile &asciiFile = m_parserState->m_asciiFile; |
2193 | 2.32k | libmwaw::DebugStream f; |
2194 | 2.32k | entry.setParsed(true); |
2195 | 2.32k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
2196 | 2.32k | f << entry.name() << "[header]:"; |
2197 | 2.32k | long val; |
2198 | 6.97k | for (int i = 0; i < 2; i++) { // fl0=0|0 |
2199 | 4.65k | val = long(input->readULong(1)); |
2200 | 4.65k | if (val) f << "fl" << i << "=" << std::hex << val << std::hex << ","; |
2201 | 4.65k | } |
2202 | 9.30k | for (int i = 0; i < 3; i++) { // f0=1, f1=N, f2=0 |
2203 | 6.97k | val = input->readLong(2); |
2204 | 6.97k | if (val) f << "f" << i << "=" << val << ","; |
2205 | 6.97k | } |
2206 | 2.32k | asciiFile.addPos(pos); |
2207 | 2.32k | asciiFile.addNote(f.str().c_str()); |
2208 | | |
2209 | 2.32k | auto dataSz = long(input->readULong(4)); |
2210 | 2.32k | if (!dataSz) return true; |
2211 | | |
2212 | 2.21k | input->seek(-4, librevenge::RVNG_SEEK_CUR); |
2213 | 2.21k | pos = input->tell(); |
2214 | 2.21k | f.str(""); |
2215 | 2.21k | f << entry.name() << ":"; |
2216 | 2.21k | HanMacWrdJZoneHeader header(false); |
2217 | 2.21k | if (!m_mainParser->readClassicHeader(header,endPos) || header.m_fieldSize!=0x5c) { |
2218 | 200 | MWAW_DEBUG_MSG(("HanMacWrdJText::readSections: can not read second zone\n")); |
2219 | 200 | f << "###" << header; |
2220 | 200 | asciiFile.addPos(pos); |
2221 | 200 | asciiFile.addNote(f.str().c_str()); |
2222 | 200 | return false; |
2223 | 200 | } |
2224 | 2.01k | f << header; |
2225 | 2.01k | long zoneEnd=pos+4+header.m_length; |
2226 | 2.01k | asciiFile.addPos(pos); |
2227 | 2.01k | asciiFile.addNote(f.str().c_str()); |
2228 | | |
2229 | 6.02k | for (int i = 0; i < header.m_n; i++) { |
2230 | 4.01k | pos = input->tell(); |
2231 | 4.01k | f.str(""); |
2232 | 4.01k | HanMacWrdJTextInternal::Section sec; |
2233 | 4.01k | sec.m_id= input->readLong(2); |
2234 | 4.01k | val = input->readLong(2); // almost alway=id, but not always |
2235 | 4.01k | if (val != sec.m_id) |
2236 | 222 | f << "#id2=" << val << ","; |
2237 | 4.01k | val = input->readLong(2); // 0|1 |
2238 | 4.01k | if (val) f << "f0=" << val << ","; |
2239 | 4.01k | val = long(input->readULong(2)); |
2240 | 4.01k | auto numCol = int(val >> 12); |
2241 | 4.01k | if (numCol<=0 || numCol > 8) { |
2242 | 130 | MWAW_DEBUG_MSG(("HanMacWrdJText::readSections: can not determine the num of columns\n")); |
2243 | 130 | f << "#numCols=" << numCol << ","; |
2244 | 130 | numCol = 1; |
2245 | 130 | } |
2246 | 3.88k | else |
2247 | 3.88k | sec.m_numCols=numCol; |
2248 | 4.01k | bool differentWidth=(val & 0xFFF) == 0; |
2249 | 4.01k | if (val & 0x7FF) |
2250 | 79 | f << "#fl=" << std::hex << (val & 0xFFF) << ","; |
2251 | 4.01k | if (differentWidth) { |
2252 | 375 | for (int j = 0; j < numCol; j++) { |
2253 | 239 | sec.m_colWidth.push_back(double(input->readLong(4))/65536); |
2254 | 239 | sec.m_colSep.push_back(double(input->readLong(4))/65536); |
2255 | 239 | } |
2256 | 136 | } |
2257 | 3.87k | else { |
2258 | 3.87k | sec.m_colWidth.push_back(double(input->readLong(4))/65536); |
2259 | 3.87k | sec.m_colSep.push_back(double(input->readLong(4))/65536); |
2260 | 3.87k | } |
2261 | 4.01k | sec.m_extra = f.str(); |
2262 | 4.01k | m_state->m_sectionList.push_back(sec); |
2263 | | |
2264 | 4.01k | f.str(""); |
2265 | 4.01k | f << entry.name() << "-" << i << ":" << sec; |
2266 | | |
2267 | 4.01k | asciiFile.addDelimiter(input->tell(), '|'); |
2268 | 4.01k | asciiFile.addPos(pos); |
2269 | 4.01k | asciiFile.addNote(f.str().c_str()); |
2270 | 4.01k | input->seek(pos+0x5c, librevenge::RVNG_SEEK_SET); |
2271 | 4.01k | } |
2272 | 2.01k | input->seek(zoneEnd, librevenge::RVNG_SEEK_SET); |
2273 | | |
2274 | 2.01k | pos = input->tell(); |
2275 | 2.01k | if (pos!=endPos) { |
2276 | 47 | MWAW_DEBUG_MSG(("HanMacWrdJText::readSections: find unexpected end data\n")); |
2277 | 47 | f.str(""); |
2278 | 47 | f << entry.name() << "###:"; |
2279 | 47 | asciiFile.addPos(pos); |
2280 | 47 | asciiFile.addNote(f.str().c_str()); |
2281 | 47 | } |
2282 | 2.01k | return true; |
2283 | 2.21k | } |
2284 | | |
2285 | | bool HanMacWrdJText::readFtnPos(MWAWEntry const &entry) |
2286 | 2.19k | { |
2287 | 2.19k | if (!entry.valid()) { |
2288 | 0 | MWAW_DEBUG_MSG(("HanMacWrdJText::readFtnPos: called without any entry\n")); |
2289 | 0 | return false; |
2290 | 0 | } |
2291 | 2.19k | if (entry.length() < 16) { |
2292 | 21 | MWAW_DEBUG_MSG(("HanMacWrdJText::readFtnPos: the entry seems too short\n")); |
2293 | 21 | return false; |
2294 | 21 | } |
2295 | 2.17k | long pos = entry.begin()+8; // skip header |
2296 | 2.17k | long endPos = entry.end(); |
2297 | | |
2298 | 2.17k | MWAWInputStreamPtr input = m_parserState->m_input; |
2299 | 2.17k | libmwaw::DebugFile &asciiFile = m_parserState->m_asciiFile; |
2300 | 2.17k | libmwaw::DebugStream f; |
2301 | 2.17k | entry.setParsed(true); |
2302 | 2.17k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
2303 | 2.17k | f << entry.name() << "[header]:"; |
2304 | 2.17k | auto val = long(input->readULong(2)); // always 0x200 |
2305 | 2.17k | if (val!=0x2000) |
2306 | 106 | f << "f0=" << std::hex << val << std::dec << ","; |
2307 | 2.17k | val = input->readLong(2); // always 1 ? |
2308 | 2.17k | if (val != 1) |
2309 | 83 | f << "f1=" << val << ","; |
2310 | 2.17k | asciiFile.addPos(pos); |
2311 | 2.17k | asciiFile.addNote(f.str().c_str()); |
2312 | | |
2313 | 2.17k | auto dataSz = long(input->readULong(4)); |
2314 | 2.17k | if (!dataSz) return true; |
2315 | | |
2316 | 2.11k | input->seek(-4, librevenge::RVNG_SEEK_CUR); |
2317 | 2.11k | pos = input->tell(); |
2318 | 2.11k | f.str(""); |
2319 | 2.11k | f << entry.name() << ":"; |
2320 | 2.11k | HanMacWrdJZoneHeader header(false); |
2321 | 2.11k | if (!m_mainParser->readClassicHeader(header,endPos) || header.m_fieldSize!=20|| |
2322 | 1.96k | 16+20*header.m_n+28 > header.m_length) { |
2323 | 162 | MWAW_DEBUG_MSG(("HanMacWrdJText::readFtnPos: can not read second zone\n")); |
2324 | 162 | f << "###" << header; |
2325 | 162 | asciiFile.addPos(pos); |
2326 | 162 | asciiFile.addNote(f.str().c_str()); |
2327 | 162 | return false; |
2328 | 162 | } |
2329 | 1.95k | f << header; |
2330 | 1.95k | long zoneEnd=pos+4+header.m_length; |
2331 | 1.95k | asciiFile.addDelimiter(input->tell(),'|'); |
2332 | 1.95k | asciiFile.addPos(pos); |
2333 | 1.95k | asciiFile.addNote(f.str().c_str()); |
2334 | | |
2335 | 1.95k | input->seek(28, librevenge::RVNG_SEEK_CUR); |
2336 | 3.69k | for (int i = 0; i < header.m_n; i++) { |
2337 | 1.74k | pos = input->tell(); |
2338 | 1.74k | f.str(""); |
2339 | 1.74k | f << entry.name() << "-" << i << ":"; |
2340 | 1.74k | val = long(input->readULong(1)); |
2341 | 1.74k | if (val!=0x11) { |
2342 | 1 | MWAW_DEBUG_MSG(("HanMacWrdJText::readFtnPos: find unexpected type\n")); |
2343 | 1 | f << "#type=" << std::hex << val << std::dec << ","; |
2344 | 1 | } |
2345 | 1.74k | f << "id=" << input->readLong(1) << ","; |
2346 | 10.4k | for (int j = 0; j < 5; j++) { // always 0? |
2347 | 8.70k | val = input->readLong(2); |
2348 | 8.70k | if (val) f << "f" << j << "=" << val << ","; |
2349 | 8.70k | } |
2350 | | // the text id |
2351 | 1.74k | f << "zId[text]=" << std::hex << input->readULong(4) << std::dec << ","; |
2352 | | // the footnote id |
2353 | 1.74k | f << "zId[footnote]=" << std::hex << input->readULong(4) << std::dec << ","; |
2354 | 1.74k | asciiFile.addPos(pos); |
2355 | 1.74k | asciiFile.addNote(f.str().c_str()); |
2356 | 1.74k | input->seek(pos+20, librevenge::RVNG_SEEK_SET); |
2357 | 1.74k | } |
2358 | 1.95k | input->seek(zoneEnd, librevenge::RVNG_SEEK_SET); |
2359 | | |
2360 | 1.95k | pos = input->tell(); |
2361 | 1.95k | if (pos!=endPos) { |
2362 | 30 | MWAW_DEBUG_MSG(("HanMacWrdJText::readFtnPos: find unexpected end data\n")); |
2363 | 30 | f.str(""); |
2364 | 30 | f << entry.name() << "###:"; |
2365 | 30 | asciiFile.addPos(pos); |
2366 | 30 | asciiFile.addNote(f.str().c_str()); |
2367 | 30 | } |
2368 | 1.95k | return true; |
2369 | 2.11k | } |
2370 | | //////////////////////////////////////////////////////////// |
2371 | | // |
2372 | | // Low level |
2373 | | // |
2374 | | //////////////////////////////////////////////////////////// |
2375 | | |
2376 | | //! send data to the listener |
2377 | | |
2378 | | void HanMacWrdJText::flushExtra() |
2379 | 0 | { |
2380 | 0 | if (!m_parserState->m_textListener) return; |
2381 | |
|
2382 | | #ifdef DEBUG |
2383 | | for (auto &zone : m_state->m_textZoneList) { |
2384 | | if (zone.m_parsed) |
2385 | | continue; |
2386 | | |
2387 | | static bool first = true; |
2388 | | if (first) { |
2389 | | MWAW_DEBUG_MSG(("HanMacWrdJText::flushExtra: find some unsent zone\n")); |
2390 | | first = false; |
2391 | | } |
2392 | | sendText(zone,0); |
2393 | | m_parserState->m_textListener->insertEOL(); |
2394 | | } |
2395 | | #endif |
2396 | 0 | } |
2397 | | |
2398 | | // vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: |