/src/libmwaw/src/lib/MsWrdTextStyles.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 | | #include <map> |
34 | | |
35 | | #include "MWAWTextListener.hxx" |
36 | | #include "MWAWSection.hxx" |
37 | | |
38 | | #include "MsWrdParser.hxx" |
39 | | #include "MsWrdStruct.hxx" |
40 | | #include "MsWrdText.hxx" |
41 | | |
42 | | #include "MsWrdTextStyles.hxx" |
43 | | |
44 | | /** Internal: the structures of a MsWrdTextStyles */ |
45 | | namespace MsWrdTextStylesInternal |
46 | | { |
47 | | //////////////////////////////////////// |
48 | | //! Internal: the state of a MsWrdTextStylesInternal |
49 | | struct State { |
50 | | //! constructor |
51 | | State() |
52 | 172k | : m_version(-1) |
53 | 172k | , m_defaultFont(2,12) |
54 | 172k | , m_nextStyleMap() |
55 | 172k | , m_fontList() |
56 | 172k | , m_paragraphList() |
57 | 172k | , m_sectionList() |
58 | 172k | , m_textstructParagraphList() |
59 | 172k | , m_styleFontMap() |
60 | 172k | , m_styleParagraphMap() |
61 | 172k | { |
62 | 172k | } |
63 | | //! the file version |
64 | | int m_version; |
65 | | |
66 | | //! the default font ( NewYork 12pt) |
67 | | MWAWFont m_defaultFont; |
68 | | |
69 | | //! a map styleId to next styleId |
70 | | std::map<int, int> m_nextStyleMap; |
71 | | |
72 | | //! the list of fonts |
73 | | std::vector<MsWrdStruct::Font> m_fontList; |
74 | | |
75 | | //! the list of paragraph |
76 | | std::vector<MsWrdStruct::Paragraph> m_paragraphList; |
77 | | |
78 | | //! the list of section |
79 | | std::vector<MsWrdStruct::Section> m_sectionList; |
80 | | |
81 | | //! the list of paragraph in textstruct |
82 | | std::vector<MsWrdStruct::Paragraph> m_textstructParagraphList; |
83 | | |
84 | | //! the list of fonts in style |
85 | | std::map<int, MsWrdStruct::Font> m_styleFontMap; |
86 | | |
87 | | //! the list of paragraph in style |
88 | | std::map<int, MsWrdStruct::Paragraph> m_styleParagraphMap; |
89 | | }; |
90 | | } |
91 | | |
92 | | //////////////////////////////////////////////////////////// |
93 | | // constructor/destructor, ... |
94 | | //////////////////////////////////////////////////////////// |
95 | | MsWrdTextStyles::MsWrdTextStyles(MsWrdText &textParser) |
96 | 172k | : m_parserState(textParser.getParserState()) |
97 | 172k | , m_state(new MsWrdTextStylesInternal::State) |
98 | 172k | , m_mainParser(textParser.m_mainParser) |
99 | 172k | , m_textParser(&textParser) |
100 | 172k | { |
101 | 172k | } |
102 | | |
103 | | MsWrdTextStyles::~MsWrdTextStyles() |
104 | 172k | { } |
105 | | |
106 | | int MsWrdTextStyles::version() const |
107 | 8.82M | { |
108 | 8.82M | if (m_state->m_version < 0) |
109 | 51.4k | m_state->m_version = m_parserState->m_version; |
110 | 8.82M | return m_state->m_version; |
111 | 8.82M | } |
112 | | |
113 | | MWAWFont const &MsWrdTextStyles::getDefaultFont() const |
114 | 0 | { |
115 | 0 | return m_state->m_defaultFont; |
116 | 0 | } |
117 | | |
118 | | //////////////////////////////////////////////////////////// |
119 | | // try to read a font |
120 | | //////////////////////////////////////////////////////////// |
121 | | bool MsWrdTextStyles::readFont(MsWrdStruct::Font &font, MsWrdTextStyles::ZoneType type) |
122 | 1.35M | { |
123 | 1.35M | bool mainZone = type==TextZone; |
124 | 1.35M | libmwaw::DebugStream f; |
125 | | |
126 | 1.35M | MWAWInputStreamPtr &input= m_parserState->m_input; |
127 | 1.35M | long pos = input->tell(); |
128 | 1.35M | auto sz = static_cast<int>(input->readULong(1)); |
129 | 1.35M | if (sz > 20 || sz == 3) { |
130 | 502k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
131 | 502k | return false; |
132 | 502k | } |
133 | | |
134 | 851k | if (sz == 0) return true; |
135 | | |
136 | 617k | auto flag = static_cast<int>(input->readULong(1)); |
137 | 617k | uint32_t flags = font.m_font->flags(); |
138 | 617k | if (flag&0x80) flags ^= MWAWFont::boldBit; |
139 | 617k | if (flag&0x40) flags ^= MWAWFont::italicBit; |
140 | 617k | if (flag&0x20) { |
141 | 98.3k | if (font.m_font->getStrikeOut().m_style==MWAWFont::Line::Simple) |
142 | 17.7k | font.m_font->setStrikeOutStyle(MWAWFont::Line::None); |
143 | 80.5k | else |
144 | 80.5k | font.m_font->setStrikeOutStyle(MWAWFont::Line::Simple); |
145 | 98.3k | } |
146 | 617k | if (flag&0x10) flags ^= MWAWFont::outlineBit; |
147 | 617k | if (flag&0x8) flags ^= MWAWFont::shadowBit; |
148 | 617k | if (flag&0x4) flags ^= MWAWFont::smallCapsBit; |
149 | 617k | if (flag&0x2) flags ^= MWAWFont::uppercaseBit; |
150 | 617k | if (flag&0x1) flags ^= MWAWFont::hiddenBit; |
151 | | |
152 | 617k | int what = 0; |
153 | | /* 01: horizontal decal, 2: vertical decal, 4; underline, 08: fSize, 10: set font, 20: font color, 40: ???(maybe reset) |
154 | | */ |
155 | 617k | if (sz >= 2) what = static_cast<int>(input->readULong(1)); |
156 | | |
157 | 617k | if (sz >= 4) { |
158 | 506k | auto fId = static_cast<int>(input->readULong(2)); |
159 | 506k | if (fId) { |
160 | 415k | if (mainZone && (what & 0x50)==0) f << "#fId,"; |
161 | 415k | font.m_font->setId(fId); |
162 | 415k | } |
163 | 91.4k | else if (what & 0x10) { |
164 | 9.02k | } |
165 | 506k | what &= 0xEF; |
166 | 506k | } |
167 | 110k | else if (what & 0x10) { |
168 | 3.50k | } |
169 | 617k | if (sz >= 5) { |
170 | 489k | float fSz = float(input->readULong(1))/2.0f; |
171 | 489k | if (fSz>0) { |
172 | 294k | if (mainZone && (what & 0x48)==0) f << "#fSz,"; |
173 | 294k | font.m_font->setSize(fSz); |
174 | 294k | } |
175 | 489k | what &= 0xF7; |
176 | 489k | } |
177 | | |
178 | 617k | if (sz >= 6) { |
179 | 478k | auto decal = static_cast<int>(input->readLong(1)); // unit point |
180 | 478k | if (decal) { |
181 | 389k | if (what & 0x2) |
182 | 166k | font.m_font->set(MWAWFont::Script(float(decal)/2.f, librevenge::RVNG_POINT)); |
183 | 222k | else |
184 | 222k | f << "#vDecal=" << decal; |
185 | 389k | } |
186 | 478k | what &= 0xFD; |
187 | 478k | } |
188 | 617k | if (sz >= 7) { |
189 | 470k | auto decal = static_cast<int>(input->readLong(1)); // unit point > 0 -> expand < 0: condensed |
190 | 470k | if (decal) { |
191 | 297k | if ((what & 0x1) == 0) f << "#hDecal=" << decal <<","; |
192 | 63.3k | else font.m_font->setDeltaLetterSpacing(float(decal)/16.0f); |
193 | 297k | } |
194 | 470k | what &= 0xFE; |
195 | 470k | } |
196 | | |
197 | 617k | if (sz >= 8) { |
198 | 459k | auto val = static_cast<int>(input->readULong(1)); |
199 | 459k | if (val & 0xF0) { |
200 | 210k | if (what & 0x20) { |
201 | 43.3k | MWAWColor col; |
202 | 43.3k | if (m_mainParser->getColor((val>>4),col)) |
203 | 27.8k | font.m_font->setColor(col); |
204 | 15.5k | else |
205 | 15.5k | f << "#fColor=" << (val>>4) << ","; |
206 | 43.3k | } |
207 | 166k | else |
208 | 166k | f << "#fColor=" << (val>>4) << ","; |
209 | 210k | } |
210 | 459k | what &= 0xDF; |
211 | | |
212 | 459k | if (val && (what & 0x4)) { |
213 | 233k | auto style=MWAWFont::Line::Simple; |
214 | 233k | switch ((val>>1)&0x7) { |
215 | 12.6k | case 4: |
216 | 12.6k | style=MWAWFont::Line::Dot; |
217 | 12.6k | break; |
218 | 32.9k | case 3: |
219 | 32.9k | font.m_font->setUnderlineType(MWAWFont::Line::Double); |
220 | 32.9k | break; |
221 | 39.1k | case 2: |
222 | 39.1k | font.m_font->setUnderlineWordFlag(true); |
223 | 39.1k | break; |
224 | 51.0k | case 1: |
225 | 51.0k | break; |
226 | 98.1k | default: |
227 | 98.1k | f << "#underline=" << ((val>>1) &0x7) << ","; |
228 | 98.1k | break; |
229 | 233k | } |
230 | 233k | if (font.m_font->getUnderline().m_style==style) |
231 | 3.83k | style=MWAWFont::Line::None; |
232 | 233k | font.m_font->setUnderlineStyle(style); |
233 | 233k | what &= 0xFB; |
234 | 233k | } |
235 | 226k | else if (val & 0xe) |
236 | 88.4k | f << "#underline?=" << ((val>>1) &0x7) << ","; |
237 | 459k | if (val & 0xF1) |
238 | 278k | f << "#underline[unkn]=" << std::hex << (val & 0xF1) << std::dec << ","; |
239 | 459k | } |
240 | 617k | if (what & 0x20) { |
241 | 8.33k | font.m_font->setColor(MWAWColor::black()); |
242 | 8.33k | what &= 0xDF; |
243 | 8.33k | } |
244 | 617k | if (what & 0x4) { |
245 | 40.1k | font.m_font->setUnderlineStyle(MWAWFont::Line::None); |
246 | 40.1k | what &= 0xFB; |
247 | 40.1k | } |
248 | 617k | if (what & 0x2) { |
249 | 20.0k | font.m_font->set(MWAWFont::Script(0, librevenge::RVNG_POINT)); |
250 | 20.0k | what &= 0xFD; |
251 | 20.0k | } |
252 | 617k | if (what & 0x1) { |
253 | 16.2k | font.m_font->setDeltaLetterSpacing(0); |
254 | 16.2k | what &= 0xFE; |
255 | 16.2k | } |
256 | 617k | font.m_unknown =what; |
257 | 617k | font.m_font->setFlags(flags); |
258 | | |
259 | 617k | bool ok = false; |
260 | 617k | if (mainZone && sz >= 10 && sz <= 12) { |
261 | 176k | auto wh = static_cast<int>(input->readULong(1)); |
262 | 176k | long pictPos = 0; |
263 | 705k | for (int i = 10; i < 13; i++) { |
264 | 529k | pictPos <<= 8; |
265 | 529k | if (i <= sz) pictPos += input->readULong(1); |
266 | 529k | } |
267 | 176k | long actPos = input->tell(); |
268 | 176k | if (m_mainParser->checkPicturePos(pictPos, wh)) { |
269 | 47.3k | ok = true; |
270 | 47.3k | input->seek(actPos, librevenge::RVNG_SEEK_SET); |
271 | 47.3k | font.m_picturePos = pictPos; |
272 | 47.3k | f << "pictWh=" << wh << ","; |
273 | 47.3k | } |
274 | 129k | else |
275 | 129k | input->seek(pos+1+8, librevenge::RVNG_SEEK_SET); |
276 | 176k | } |
277 | 617k | if (!ok && sz >= 9) { |
278 | 394k | auto wh = static_cast<int>(input->readLong(1)); |
279 | 394k | switch (wh) { |
280 | 10.6k | case -1: |
281 | 10.6k | ok = true; |
282 | 10.6k | break; |
283 | 99.9k | case 0: // line height ? |
284 | 99.9k | if (sz < 10) break; |
285 | 90.9k | font.m_size=float(input->readULong(1))/2.f; |
286 | 90.9k | ok = true; |
287 | 90.9k | break; |
288 | 283k | default: |
289 | 283k | break; |
290 | 394k | } |
291 | 394k | } |
292 | 617k | if (!ok && sz >= 9) { |
293 | 292k | input->seek(pos+1+8, librevenge::RVNG_SEEK_SET); |
294 | 292k | f << "#"; |
295 | 292k | } |
296 | 617k | if (long(input->tell()) != pos+1+sz) |
297 | 353k | m_parserState->m_asciiFile.addDelimiter(input->tell(), '|'); |
298 | | |
299 | 617k | input->seek(pos+1+sz, librevenge::RVNG_SEEK_SET); |
300 | 617k | font.m_extra = f.str(); |
301 | 617k | return true; |
302 | 617k | } |
303 | | |
304 | | bool MsWrdTextStyles::getFont(ZoneType type, int id, MsWrdStruct::Font &font) |
305 | 169k | { |
306 | 169k | MsWrdStruct::Font *fFont = nullptr; |
307 | 169k | switch (type) { |
308 | 143k | case TextZone: |
309 | 143k | if (id < 0 || id >= int(m_state->m_fontList.size())) |
310 | 0 | break; |
311 | 143k | fFont = &m_state->m_fontList[size_t(id)]; |
312 | 143k | break; |
313 | 25.4k | case StyleZone: |
314 | 25.4k | if (m_state->m_styleFontMap.find(id) == m_state->m_styleFontMap.end()) |
315 | 2.92k | break; |
316 | 22.5k | fFont = &m_state->m_styleFontMap.find(id)->second; |
317 | 22.5k | break; |
318 | 0 | case TextStructZone: |
319 | 0 | case InParagraphDefinition: |
320 | | #if !defined(__clang__) |
321 | | default: |
322 | | #endif |
323 | 0 | MWAW_DEBUG_MSG(("MsWrdTextStyles::getFont: do not know how to send this type of font\n")); |
324 | 0 | return false; |
325 | 169k | } |
326 | 169k | if (!fFont) { |
327 | 2.92k | MWAW_DEBUG_MSG(("MsWrdTextStyles::getFont: can not find font with %d[type=%d]\n", id, int(type))); |
328 | 2.92k | return false; |
329 | 2.92k | } |
330 | 166k | int fId = font.m_font->id(); |
331 | 166k | float fSz = font.m_font->size(); |
332 | 166k | font = *fFont; |
333 | 166k | if (font.m_font->id() < 0) |
334 | 118k | font.m_font->setId(fId); |
335 | 166k | if (font.m_font->size() <= 0) |
336 | 120k | font.m_font->setSize(fSz); |
337 | 166k | return true; |
338 | 169k | } |
339 | | |
340 | | void MsWrdTextStyles::setProperty(MsWrdStruct::Font const &font) |
341 | 708k | { |
342 | 708k | if (!m_parserState->m_textListener) return; |
343 | 708k | MsWrdStruct::Font tmp = font; |
344 | 708k | if (tmp.m_font->id() < 0) tmp.m_font->setId(m_state->m_defaultFont.id()); |
345 | 708k | if (tmp.m_font->size() <= 0) tmp.m_font->setSize(m_state->m_defaultFont.size()); |
346 | 708k | tmp.updateFontToFinalState(); |
347 | 708k | m_parserState->m_textListener->setFont(*tmp.m_font); |
348 | 708k | } |
349 | | |
350 | | //////////////////////////////////////////////////////////// |
351 | | // read/send the paragraph zone |
352 | | //////////////////////////////////////////////////////////// |
353 | | bool MsWrdTextStyles::getParagraph(ZoneType type, int id, MsWrdStruct::Paragraph ¶) |
354 | 969k | { |
355 | 969k | switch (type) { |
356 | 599k | case TextZone: |
357 | 599k | if (id < 0 || id >= int(m_state->m_paragraphList.size())) |
358 | 0 | break; |
359 | 599k | para = m_state->m_paragraphList[size_t(id)]; |
360 | 599k | return true; |
361 | 251k | case StyleZone: |
362 | 251k | if (m_state->m_styleParagraphMap.find(id) == m_state->m_styleParagraphMap.end()) |
363 | 102k | break; |
364 | 148k | para = m_state->m_styleParagraphMap.find(id)->second; |
365 | 148k | return true; |
366 | 119k | case TextStructZone: |
367 | 119k | if (id < 0 || id >= int(m_state->m_textstructParagraphList.size())) |
368 | 16.9k | break; |
369 | 102k | para = m_state->m_textstructParagraphList[size_t(id)]; |
370 | 102k | return true; |
371 | 0 | case InParagraphDefinition: |
372 | | #if !defined(__clang__) |
373 | | default: |
374 | | #endif |
375 | 0 | MWAW_DEBUG_MSG(("MsWrdTextStyles::getParagraph: do not know how to send this type of font\n")); |
376 | 0 | return false; |
377 | 969k | } |
378 | | |
379 | 119k | MWAW_DEBUG_MSG(("MsWrdTextStyles::getParagraph: can not find paragraph with %d[type=%d]\n", id, int(type))); |
380 | 119k | return false; |
381 | 969k | } |
382 | | |
383 | | void MsWrdTextStyles::sendDefaultParagraph() |
384 | 0 | { |
385 | 0 | if (!m_parserState->m_textListener) return; |
386 | 0 | m_parserState->m_textListener->setParagraph(MsWrdStruct::Paragraph(version())); |
387 | 0 | } |
388 | | |
389 | | bool MsWrdTextStyles::readParagraph(MsWrdStruct::Paragraph ¶, int dataSz) |
390 | 2.34M | { |
391 | 2.34M | int sz; |
392 | 2.34M | MWAWInputStreamPtr &input= m_parserState->m_input; |
393 | 2.34M | if (dataSz >= 0) |
394 | 2.33M | sz = dataSz; |
395 | 11.5k | else |
396 | 11.5k | sz = static_cast<int>(input->readULong(2)); |
397 | | |
398 | 2.34M | long pos = input->tell(); |
399 | 2.34M | long endPos = pos+sz; |
400 | | |
401 | 2.34M | if (sz == 0) return true; |
402 | 2.33M | if (!input->checkPosition(endPos)) return false; |
403 | | |
404 | 2.33M | int const vers = version(); |
405 | 2.33M | libmwaw::DebugStream f; |
406 | 2.33M | int numFont=0; |
407 | 11.1M | while (long(input->tell()) < endPos) { |
408 | 10.8M | long actPos = input->tell(); |
409 | | /* 5-16: basic paragraph properties |
410 | | 75-84: basic section properties |
411 | | other |
412 | | */ |
413 | 10.8M | if (para.read(input,endPos)) continue; |
414 | 5.03M | input->seek(actPos, librevenge::RVNG_SEEK_SET); |
415 | | |
416 | 5.03M | int wh = static_cast<int>(input->readULong(1)), val; |
417 | 5.03M | if (vers <= 3 && wh >= 0x36 && wh <= 0x45) { |
418 | | // this section data has different meaning in v3 and after... |
419 | 28.5k | input->seek(actPos, librevenge::RVNG_SEEK_SET); |
420 | 28.5k | break; |
421 | 28.5k | } |
422 | 5.00M | bool done = false; |
423 | 5.00M | long dSz = endPos-actPos; |
424 | 5.00M | switch (wh) { |
425 | 328k | case 0: |
426 | 328k | done = (actPos+1==endPos||(dataSz==2 && actPos+2==endPos)); |
427 | 328k | break; |
428 | 54.3k | case 0x38: |
429 | 54.3k | if (dSz < 4) break; |
430 | 51.3k | val = static_cast<int>(input->readLong(1)); |
431 | 51.3k | if (val != 2) f << "#shadType=" << val << ","; |
432 | 51.3k | f << "shad=" << float(input->readLong(2))/100.f << "%,"; |
433 | 51.3k | done = true; |
434 | 51.3k | break; |
435 | 32.7k | case 0x3a: // checkme: maybe plain |
436 | 32.7k | f << "f3a,"; |
437 | 32.7k | done = true; |
438 | 32.7k | break; |
439 | 85.5k | case 0x4d: { |
440 | 85.5k | if (dSz < 2) break; |
441 | 84.2k | val = static_cast<int>(input->readLong(1)); |
442 | 84.2k | para.m_modFont->m_font->set(MWAWFont::Script(float(val)/2.f,librevenge::RVNG_POINT)); |
443 | 84.2k | if (val==0) f << "pos[y]=0,"; |
444 | 84.2k | done = true; |
445 | 84.2k | break; |
446 | 85.5k | } |
447 | 82.5k | case 0x3c: // bold |
448 | 125k | case 0x3d: // italic? |
449 | 163k | case 0x3e: // strikeout (chekme) |
450 | 212k | case 0x3f: // outline (chekme) |
451 | 239k | case 0x40: // shadow (chekme) |
452 | 290k | case 0x41: // small caps (chekme) |
453 | 320k | case 0x42: // all caps (chekme) |
454 | 421k | case 0x43: // hidden (chekme) |
455 | 445k | case 0x45: // underline |
456 | 628k | case 0x4a: { |
457 | 628k | if (dSz < 2) break; |
458 | 623k | done = true; |
459 | 623k | val = static_cast<int>(input->readULong(1)); |
460 | 623k | if (wh == 0x4a) { |
461 | 181k | if (val > 4 && val < 40) |
462 | 17.7k | para.m_modFont->m_font->setSize(float(val)/2.0f); |
463 | 163k | else |
464 | 163k | f << "#fSize=" << val << ","; |
465 | 181k | break; |
466 | 181k | } |
467 | 441k | switch (wh) { |
468 | 81.9k | case 0x3c: |
469 | 124k | case 0x3d: |
470 | 162k | case 0x3e: |
471 | 210k | case 0x3f: |
472 | 236k | case 0x40: |
473 | 287k | case 0x41: |
474 | 317k | case 0x42: |
475 | 418k | case 0x43: |
476 | 418k | para.m_modFont->m_flags[wh-0x3c]=val; |
477 | 418k | break; |
478 | 23.6k | case 0x45: |
479 | 23.6k | para.m_modFont->m_flags[8]=val; |
480 | 23.6k | break; |
481 | 0 | default: |
482 | 0 | break; |
483 | 441k | } |
484 | 441k | break; |
485 | 441k | } |
486 | 441k | case 0x44: |
487 | 199k | if (dSz < 3) break; |
488 | 195k | done = true; |
489 | 195k | val = static_cast<int>(input->readULong(2)); |
490 | 195k | para.m_modFont->m_font->setId(val); |
491 | 195k | break; |
492 | 3.11k | case 0x2: // a small number between 0 and 4 |
493 | 113k | case 0x34: // 0 ( one time) |
494 | 162k | case 0x39: // 0 ( one time) |
495 | 290k | case 0x47: // 0 one time |
496 | 335k | case 0x49: // 0 ( one time) |
497 | 408k | case 0x4c: // 0, 6, -12 |
498 | 439k | case 0x5e: // 0 |
499 | 439k | if (dSz < 2) break; |
500 | 432k | done = true; |
501 | 432k | val = static_cast<int>(input->readLong(1)); |
502 | 432k | f << "f" << std::hex << wh << std::dec << "=" << val << ","; |
503 | 432k | break; |
504 | 122k | case 0x23: // alway 0 ? |
505 | 122k | if (dSz < 3) break; |
506 | 101k | done = true; |
507 | 101k | val = static_cast<int>(input->readLong(2)); |
508 | 101k | f << "f" << std::hex << wh << std::dec << "=" << val << ","; |
509 | 101k | break; |
510 | 26.6k | case 0x9f: // two small number: table range? |
511 | 26.6k | if (dSz < 3) break; |
512 | 24.6k | done = true; |
513 | 24.6k | f << "f" << std::hex << wh << "=["; |
514 | 74.0k | for (int i = 0; i < 2; i++) |
515 | 49.3k | f << input->readULong(1) << ","; |
516 | 24.6k | f << std::dec << "],"; |
517 | 24.6k | break; |
518 | 49.5k | case 0x50: // two small number |
519 | 49.5k | if (dSz < 4) break; |
520 | 45.6k | done = true; |
521 | 45.6k | f << "f" << std::hex << wh << std::dec << "=["; |
522 | 45.6k | f << input->readLong(1) << ","; |
523 | 45.6k | f << input->readLong(2) << ","; |
524 | 45.6k | f << "],"; |
525 | 45.6k | break; |
526 | 1.07M | case 0x4f: // a small int and a pos? |
527 | 1.07M | if (dSz < 4) break; |
528 | 1.05M | done = true; |
529 | 1.05M | f << "f" << std::hex << wh << std::dec << "=["; |
530 | 1.05M | f << input->readLong(1) << ","; |
531 | 1.05M | f << std::hex << input->readULong(2) << std::dec << "],"; |
532 | 1.05M | break; |
533 | 20.4k | case 0x9e: // two small number + a pos? |
534 | 20.4k | if (dSz < 5) break; |
535 | 18.8k | done = true; |
536 | 18.8k | f << "f" << std::hex << wh << std::dec << "=["; |
537 | 56.4k | for (int i = 0; i < 2; i++) |
538 | 37.6k | f << input->readLong(1) << ","; |
539 | 18.8k | f << std::hex << input->readULong(2) << std::dec << "],"; |
540 | 18.8k | break; |
541 | 142k | case 0x4e: |
542 | 187k | case 0x53: { // same as 4e ( new format ) |
543 | | // checkme: sometimes, we can have a list of font, do we need to |
544 | | // use only the last one? |
545 | 187k | if (numFont++) |
546 | 17.2k | f << "#font" << numFont-1 << "=[" |
547 | 17.2k | << para.m_font->m_font->getDebugString(m_parserState->m_fontConverter) |
548 | 17.2k | << "," << *para.m_font << "],"; |
549 | 187k | done = true; |
550 | 187k | para.m_font = MsWrdStruct::Font(); |
551 | 187k | if (!readFont(*para.m_font, InParagraphDefinition) || long(input->tell()) > endPos) { |
552 | 131k | done = false; |
553 | 131k | f << "#"; |
554 | 131k | break; |
555 | 131k | } |
556 | 56.7k | break; |
557 | 187k | } |
558 | 213k | case 0x5f: { // 4 index |
559 | 213k | if (dSz < 10) break; |
560 | 207k | done = true; |
561 | 207k | sz = static_cast<int>(input->readULong(1)); |
562 | 207k | if (sz != 8) f << "#sz=" << sz << ","; |
563 | 207k | f << "f5f=["; |
564 | 1.03M | for (int i = 0; i < 4; i++) f << input->readLong(2) << ","; |
565 | 207k | f << "],"; |
566 | 207k | break; |
567 | 213k | } |
568 | 37.1k | case 0x94: // checkme space between column divided by 2 (in table) ? |
569 | 37.1k | if (dSz < 3) break; |
570 | 35.7k | done = true; |
571 | 35.7k | val = static_cast<int>(input->readLong(2)); |
572 | 35.7k | f << "colSep[table]=" << 2*val/1440. << ","; |
573 | 35.7k | break; |
574 | 1.50M | default: |
575 | 1.50M | break; |
576 | 5.00M | } |
577 | 5.00M | if (!done) { |
578 | 1.98M | input->seek(actPos, librevenge::RVNG_SEEK_SET); |
579 | 1.98M | break; |
580 | 1.98M | } |
581 | 5.00M | } |
582 | 2.33M | if (long(input->tell()) != endPos) { |
583 | 2.01M | static bool first = true; |
584 | 2.01M | if (first) { |
585 | 25 | MWAW_DEBUG_MSG(("MsWrdTextStyles::readParagraph: can not read end of paragraph\n")); |
586 | 25 | first = false; |
587 | 25 | } |
588 | 2.01M | libmwaw::DebugFile &ascFile = m_parserState->m_asciiFile; |
589 | 2.01M | ascFile.addDelimiter(input->tell(),'|'); |
590 | 2.01M | f << "####"; |
591 | 2.01M | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
592 | 2.01M | } |
593 | 2.33M | para.m_extra += f.str(); |
594 | | |
595 | 2.33M | return true; |
596 | 2.33M | } |
597 | | |
598 | | //////////////////////////////////////////////////////////// |
599 | | // read the char/parag plc |
600 | | //////////////////////////////////////////////////////////// |
601 | | bool MsWrdTextStyles::readPLCList(MsWrdEntry const &entry) |
602 | 56.4k | { |
603 | 56.4k | if (entry.length() < 10 || (entry.length()%6) != 4) { |
604 | 6.80k | MWAW_DEBUG_MSG(("MsWrdTextStyles::readPLCList: the zone size seems odd\n")); |
605 | 6.80k | return false; |
606 | 6.80k | } |
607 | 49.5k | long pos = entry.begin(); |
608 | 49.5k | entry.setParsed(true); |
609 | 49.5k | MWAWInputStreamPtr &input= m_parserState->m_input; |
610 | 49.5k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
611 | 49.5k | libmwaw::DebugFile &ascFile = m_parserState->m_asciiFile; |
612 | 49.5k | libmwaw::DebugStream f; |
613 | 49.5k | f << entry.type() << ":"; |
614 | 49.5k | auto N=int(entry.length()/6); |
615 | 49.5k | std::vector<long> textPos; // limit of the text in the file |
616 | 49.5k | textPos.resize(size_t(N)+1); |
617 | 11.1M | for (auto &tPos : textPos) tPos = long(input->readULong(4)); |
618 | 49.5k | int const expectedSize = (version() <= 3) ? 0x80 : 0x200; |
619 | 11.1M | for (int i = 0; i < N; i++) { |
620 | 11.0M | if (!input->checkPosition(textPos[size_t(i)])) f << "#"; |
621 | | |
622 | 11.0M | auto defPos = long(input->readULong(2)); |
623 | 11.0M | f << std::hex << "[filePos?=" << textPos[size_t(i)] << ",dPos=" << defPos << std::dec << ","; |
624 | 11.0M | f << "],"; |
625 | | |
626 | 11.0M | MsWrdEntry plc; |
627 | 11.0M | plc.setType(entry.id() ? "ParagPLC" : "CharPLC"); |
628 | 11.0M | plc.setId(i); |
629 | 11.0M | plc.setBegin(defPos *expectedSize); |
630 | 11.0M | plc.setLength(expectedSize); |
631 | 11.0M | if (!input->checkPosition(plc.end())) { |
632 | 6.55M | f << "#PLC,"; |
633 | 6.55M | MWAW_DEBUG_MSG(("MsWrdTextStyles::readPLCList: plc def is outside the file\n")); |
634 | 6.55M | } |
635 | 4.51M | else { |
636 | 4.51M | long actPos = input->tell(); |
637 | 4.51M | MWAWVec2<long> fLimit(textPos[size_t(i)], textPos[size_t(i)+1]); |
638 | 4.51M | readPLC(plc, entry.id(), fLimit); |
639 | 4.51M | input->seek(actPos, librevenge::RVNG_SEEK_SET); |
640 | 4.51M | } |
641 | 11.0M | } |
642 | 49.5k | f << std::hex << "end?=" << textPos[size_t(N)] << ","; |
643 | | |
644 | 49.5k | ascFile.addPos(pos); |
645 | 49.5k | ascFile.addNote(f.str().c_str()); |
646 | | |
647 | 49.5k | ascFile.addPos(entry.end()); |
648 | 49.5k | ascFile.addNote("_"); |
649 | 49.5k | return true; |
650 | 56.4k | } |
651 | | |
652 | | bool MsWrdTextStyles::readPLC(MsWrdEntry &entry, int type, MWAWVec2<long> const &fLimit) |
653 | 4.75M | { |
654 | 4.75M | int const vers = version(); |
655 | 4.75M | int const expectedSize = (vers <= 3) ? 0x80 : 0x200; |
656 | 4.75M | int const posFactor = (vers <= 3) ? 1 : 2; |
657 | 4.75M | if (entry.length() != expectedSize) { |
658 | 0 | MWAW_DEBUG_MSG(("MsWrdTextStyles::readPLC: the zone size seems odd\n")); |
659 | 0 | return false; |
660 | 0 | } |
661 | 4.75M | MWAWInputStreamPtr &input= m_parserState->m_input; |
662 | 4.75M | input->seek(entry.end()-1, librevenge::RVNG_SEEK_SET); |
663 | 4.75M | auto N=static_cast<int>(input->readULong(1)); |
664 | 4.75M | if (N==0 || 5*(N+1) > entry.length()) { |
665 | 3.03M | MWAW_DEBUG_MSG(("MsWrdTextStyles::readPLC: the number of plc seems odd\n")); |
666 | 3.03M | return false; |
667 | 3.03M | } |
668 | | |
669 | 1.71M | long pos = entry.begin(); |
670 | 1.71M | entry.setParsed(true); |
671 | 1.71M | libmwaw::DebugFile &ascFile = m_parserState->m_asciiFile; |
672 | 1.71M | libmwaw::DebugStream f; |
673 | 1.71M | f << "Entries("<< entry.type() << ")[" << entry.id() << "]:N=" << N << ","; |
674 | | |
675 | 1.71M | input->seek(pos, librevenge::RVNG_SEEK_SET); |
676 | 1.71M | std::vector<long> filePos; |
677 | 1.71M | filePos.resize(size_t(N)+1); |
678 | 59.6M | for (auto &fPos : filePos) fPos = long(input->readULong(4)); |
679 | 1.71M | if (filePos[0] != fLimit[0]) { |
680 | 1.42M | MWAW_DEBUG_MSG(("MsWrdTextStyles::readPLC: bad first limit\n")); |
681 | 1.42M | return false; |
682 | 1.42M | } |
683 | 298k | std::map<int, int> mapPosId; |
684 | 298k | std::vector<int> decal; |
685 | 298k | decal.resize(size_t(N)); |
686 | 298k | size_t numData = type == 0 ? m_state->m_fontList.size() : |
687 | 298k | m_state->m_paragraphList.size(); |
688 | 298k | auto plcType = type == 0 ? MsWrdText::PLC::Font : MsWrdText::PLC::Paragraph; |
689 | 298k | auto &plcMap = m_textParser->getFilePLCMap(); |
690 | | |
691 | 9.81M | for (size_t i = 0; i < size_t(N); i++) { |
692 | 9.51M | decal[i] = static_cast<int>(input->readULong(1)); |
693 | 9.51M | int id = -1; |
694 | 9.51M | if (decal[i]) { |
695 | 7.46M | if (mapPosId.find(decal[i]) != mapPosId.end()) |
696 | 3.66M | id = mapPosId.find(decal[i])->second; |
697 | 3.79M | else { |
698 | 3.79M | id = int(numData++); |
699 | 3.79M | mapPosId[decal[i]] = id; |
700 | | |
701 | 3.79M | long actPos = input->tell(); |
702 | 3.79M | libmwaw::DebugStream f2; |
703 | 3.79M | f2 << entry.type() << "-"; |
704 | | |
705 | 3.79M | long dataPos = entry.begin()+posFactor*decal[i]; |
706 | 3.79M | if (type == 0) { |
707 | 943k | input->seek(dataPos, librevenge::RVNG_SEEK_SET); |
708 | 943k | f2 << "F" << id << ":"; |
709 | 943k | MsWrdStruct::Font font; |
710 | 943k | if (!readFont(font, TextZone)) { |
711 | 310k | font = MsWrdStruct::Font(); |
712 | 310k | f2 << "#"; |
713 | 310k | } |
714 | 632k | else |
715 | 632k | f2 << font.m_font->getDebugString(m_parserState->m_fontConverter) << font << ","; |
716 | 943k | m_state->m_fontList.push_back(font); |
717 | 943k | } |
718 | 2.85M | else { |
719 | 2.85M | MsWrdStruct::Paragraph para(vers); |
720 | 2.85M | f2 << "P" << id << ":"; |
721 | | |
722 | 2.85M | input->seek(dataPos, librevenge::RVNG_SEEK_SET); |
723 | 2.85M | auto sz = static_cast<int>(input->readLong(1)); |
724 | 2.85M | long endPos; |
725 | 2.85M | if (vers <= 3) { |
726 | 529k | sz++; |
727 | 529k | endPos = dataPos+sz; |
728 | 529k | } |
729 | 2.32M | else |
730 | 2.32M | endPos = dataPos+2*sz+1; |
731 | 2.85M | if (sz < 4 || endPos > entry.end()) { |
732 | 1.18M | MWAW_DEBUG_MSG(("MsWrdTextStyles::readPLC: can not read plcSz\n")); |
733 | 1.18M | f2 << "#"; |
734 | 1.18M | } |
735 | 1.66M | else { |
736 | 1.66M | auto stId = static_cast<int>(input->readLong(1)); |
737 | 1.66M | if (m_state->m_styleParagraphMap.find(stId)==m_state->m_styleParagraphMap.end()) { |
738 | 1.60M | MWAW_DEBUG_MSG(("MsWrdTextStyles::readPLC: can not find parent paragraph\n")); |
739 | 1.60M | f2 << "#"; |
740 | 1.60M | } |
741 | 65.8k | else |
742 | 65.8k | para.m_styleId = stId; |
743 | 1.66M | f2 << "sP" << stId << ","; |
744 | 1.66M | if (vers > 3) { |
745 | 1.35M | if (!para.m_info->read(input, endPos, vers)) { |
746 | 0 | f2 << "###info,"; |
747 | 0 | input->seek(dataPos+2+6, librevenge::RVNG_SEEK_SET); |
748 | 0 | } |
749 | | // osnole: do we need to check here if the paragraph is empty ? |
750 | | // ie. if (para.m_info->isEmpty()&&stId==0) |
751 | 1.35M | } |
752 | 309k | else { // always 0 ? |
753 | 309k | auto val = static_cast<int>(input->readLong(2)); |
754 | 309k | if (val) f << "g0=" << val << ","; |
755 | 309k | } |
756 | 1.66M | ascFile.addDelimiter(input->tell(),'|'); |
757 | 1.66M | if (readParagraph(para, int(endPos-input->tell()))) { |
758 | | #ifdef DEBUG_WITH_FILES |
759 | | para.print(f2, m_parserState->m_fontConverter); |
760 | | #endif |
761 | 1.66M | } |
762 | 0 | else { |
763 | 0 | para = MsWrdStruct::Paragraph(vers); |
764 | 0 | f2 << "#"; |
765 | 0 | } |
766 | 1.66M | } |
767 | 2.85M | m_state->m_paragraphList.push_back(para); |
768 | 2.85M | } |
769 | 3.79M | input->seek(actPos, librevenge::RVNG_SEEK_SET); |
770 | 3.79M | ascFile.addPos(dataPos); |
771 | 3.79M | ascFile.addNote(f2.str().c_str()); |
772 | 3.79M | } |
773 | 7.46M | } |
774 | 9.51M | f << std::hex << filePos[i] << std::dec; |
775 | 9.51M | MsWrdText::PLC plc(plcType, id); |
776 | 9.51M | plcMap.insert(std::multimap<long, MsWrdText::PLC>::value_type |
777 | 9.51M | (filePos[type == 0 ? i : i+1], plc)); |
778 | 9.51M | if (id >= 0) { |
779 | 7.46M | if (type==0) f << ":F" << id; |
780 | 6.00M | else f << ":P" << id; |
781 | 7.46M | } |
782 | 9.51M | f << ","; |
783 | 9.51M | } |
784 | | |
785 | 298k | ascFile.addPos(pos); |
786 | 298k | ascFile.addNote(f.str().c_str()); |
787 | | |
788 | 298k | ascFile.addPos(entry.end()); |
789 | 298k | ascFile.addNote("_"); |
790 | 298k | if (filePos[size_t(N)] != fLimit[1]) { |
791 | 242k | if (input->isEnd()) { |
792 | 0 | MWAW_DEBUG_MSG(("MsWrdTextStyles::readPLC: we are already at the end of the stream\n")); |
793 | 0 | return false; |
794 | 0 | } |
795 | 242k | MsWrdEntry nextEntry(entry); |
796 | 242k | nextEntry.setBegin(entry.begin()+expectedSize); |
797 | 242k | MWAWVec2<long> newLimit(filePos[size_t(N)], fLimit[1]); |
798 | 242k | readPLC(nextEntry,type,newLimit); |
799 | 242k | } |
800 | 298k | return true; |
801 | 298k | } |
802 | | |
803 | | //////////////////////////////////////////////////////////// |
804 | | // read the text structure |
805 | | //////////////////////////////////////////////////////////// |
806 | | bool MsWrdTextStyles::readTextStructList(MsWrdEntry &entry) |
807 | 11.6k | { |
808 | 11.6k | if (entry.length() < 19) { |
809 | 0 | MWAW_DEBUG_MSG(("MsWrdTextStyles::readTextStructList: the zone seems to short\n")); |
810 | 0 | return false; |
811 | 0 | } |
812 | 11.6k | int const vers = version(); |
813 | 11.6k | long pos = entry.begin(); |
814 | 11.6k | MWAWInputStreamPtr &input= m_parserState->m_input; |
815 | 11.6k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
816 | 11.6k | libmwaw::DebugFile &ascFile = m_parserState->m_asciiFile; |
817 | 11.6k | libmwaw::DebugStream f; |
818 | 11.6k | auto type = static_cast<int>(input->readLong(1)); |
819 | 11.6k | if (type != 1 && type != 2) { |
820 | 3.60k | MWAW_DEBUG_MSG(("MsWrdTextStyles::readTextStructList: find odd type %d\n", type)); |
821 | 3.60k | return false; |
822 | 3.60k | } |
823 | | |
824 | 8.07k | int num = 0; |
825 | 18.6k | while (type == 1) { |
826 | | /* probably a paragraph definition. Fixme: create a function */ |
827 | 11.6k | auto length = static_cast<int>(input->readULong(2)); |
828 | 11.6k | long endPos = pos+3+length; |
829 | 11.6k | if (endPos > entry.end()) { |
830 | 113 | ascFile.addPos(pos); |
831 | 113 | ascFile.addNote("TextStruct[paragraph]#"); |
832 | 113 | MWAW_DEBUG_MSG(("MsWrdTextStyles::readTextStructList: zone(paragraph) is too big\n")); |
833 | 113 | return false; |
834 | 113 | } |
835 | 11.5k | f.str(""); |
836 | 11.5k | f << "ParagPLC:tP" << num++<< "]:"; |
837 | 11.5k | MsWrdStruct::Paragraph para(vers); |
838 | 11.5k | input->seek(-2,librevenge::RVNG_SEEK_CUR); |
839 | 11.5k | if (readParagraph(para) && long(input->tell()) <= endPos) { |
840 | | #ifdef DEBUG_WITH_FILES |
841 | | para.print(f, m_parserState->m_fontConverter); |
842 | | #endif |
843 | 11.5k | } |
844 | 0 | else { |
845 | 0 | para = MsWrdStruct::Paragraph(vers); |
846 | 0 | f << "#"; |
847 | 0 | } |
848 | 11.5k | m_state->m_textstructParagraphList.push_back(para); |
849 | 11.5k | ascFile.addPos(pos); |
850 | 11.5k | ascFile.addNote(f.str().c_str()); |
851 | 11.5k | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
852 | | |
853 | 11.5k | pos = input->tell(); |
854 | 11.5k | type = static_cast<int>(input->readULong(1)); |
855 | 11.5k | if (type == 2) break; |
856 | 10.7k | if (type != 1) { |
857 | 176 | MWAW_DEBUG_MSG(("MsWrdTextStyles::readTextStructList: find odd type %d\n", type)); |
858 | 176 | return false; |
859 | 176 | } |
860 | 10.7k | } |
861 | 7.78k | input->seek(-1,librevenge::RVNG_SEEK_CUR); |
862 | 7.78k | return true; |
863 | 8.07k | } |
864 | | |
865 | | int MsWrdTextStyles::readPropertyModifier(bool &complex, std::string &extra) |
866 | 1.06M | { |
867 | 1.06M | MWAWInputStreamPtr &input= m_parserState->m_input; |
868 | 1.06M | long pos = input->tell(); |
869 | 1.06M | auto c = static_cast<int>(input->readULong(1)); |
870 | 1.06M | complex = false; |
871 | 1.06M | if (c&0x80) { // complex data, let get the id |
872 | 176k | complex=true; |
873 | 176k | return ((c&0x7F)<<8)|static_cast<int>(input->readULong(1)); |
874 | 176k | } |
875 | 884k | if (c==0) { |
876 | 433k | input->seek(pos+2, librevenge::RVNG_SEEK_SET); |
877 | 433k | return -1; |
878 | 433k | } |
879 | 450k | int id = -1; |
880 | 450k | libmwaw::DebugStream f; |
881 | 450k | MsWrdStruct::Paragraph para(version()); |
882 | 450k | input->seek(-1, librevenge::RVNG_SEEK_CUR); |
883 | 450k | if (readParagraph(para, 2)) { |
884 | 450k | id = int(m_state->m_textstructParagraphList.size()); |
885 | 450k | m_state->m_textstructParagraphList.push_back(para); |
886 | | #ifdef DEBUG_WITH_FILES |
887 | | f << "["; |
888 | | para.print(f, m_parserState->m_fontConverter); |
889 | | f << "]"; |
890 | | #endif |
891 | 450k | } |
892 | 0 | else { |
893 | 0 | input->seek(pos+1, librevenge::RVNG_SEEK_SET); |
894 | 0 | f << "#f" << std::hex << c << std::dec << "=" << static_cast<int>(input->readULong(1)); |
895 | 0 | } |
896 | 450k | extra = f.str(); |
897 | 450k | input->seek(pos+2, librevenge::RVNG_SEEK_SET); |
898 | 450k | return id; |
899 | 884k | } |
900 | | |
901 | | //////////////////////////////////////////////////////////// |
902 | | // read/send the section zone |
903 | | //////////////////////////////////////////////////////////// |
904 | | bool MsWrdTextStyles::getSection(ZoneType type, int id, MsWrdStruct::Section §ion) |
905 | 0 | { |
906 | 0 | switch (type) { |
907 | 0 | case TextZone: |
908 | 0 | if (id < 0 || id >= int(m_state->m_sectionList.size())) |
909 | 0 | break; |
910 | 0 | section = m_state->m_sectionList[size_t(id)]; |
911 | 0 | return true; |
912 | 0 | case StyleZone: |
913 | 0 | case TextStructZone: |
914 | 0 | case InParagraphDefinition: |
915 | | #if !defined(__clang__) |
916 | | default: |
917 | | #endif |
918 | 0 | MWAW_DEBUG_MSG(("MsWrdTextStyles::getSection do not know how to get this type of section\n")); |
919 | 0 | return false; |
920 | 0 | } |
921 | 0 | MWAW_DEBUG_MSG(("MsWrdTextStyles::getSection can not find this section\n")); |
922 | 0 | return false; |
923 | 0 | } |
924 | | |
925 | | bool MsWrdTextStyles::getSectionParagraph(ZoneType type, int id, MsWrdStruct::Paragraph ¶) |
926 | 0 | { |
927 | 0 | MsWrdStruct::Section sec; |
928 | 0 | if (!getSection(type, id, sec)) return false; |
929 | 0 | if (!sec.m_paragraphId.isSet()) return false; |
930 | 0 | return getParagraph(StyleZone, *sec.m_paragraphId, para); |
931 | 0 | } |
932 | | |
933 | | bool MsWrdTextStyles::getSectionFont(ZoneType type, int id, MsWrdStruct::Font &font) |
934 | 0 | { |
935 | 0 | MsWrdStruct::Section sec; |
936 | 0 | if (!getSection(type, id, sec)) return false; |
937 | | |
938 | 0 | if (!sec.m_paragraphId.isSet()) return false; |
939 | 0 | MsWrdStruct::Paragraph para(version()); |
940 | 0 | if (!getParagraph(StyleZone, *sec.m_paragraphId, para)) |
941 | 0 | return false; |
942 | | |
943 | 0 | if (para.m_font.isSet()) |
944 | 0 | font = para.m_font.get(); |
945 | 0 | else |
946 | 0 | return false; |
947 | 0 | return true; |
948 | 0 | } |
949 | | |
950 | | |
951 | | bool MsWrdTextStyles::readSection(MsWrdEntry &entry, std::vector<long> &cLimits) |
952 | 13.7k | { |
953 | 13.7k | if (entry.length() < 14 || (entry.length()%10) != 4) { |
954 | 3.24k | MWAW_DEBUG_MSG(("MsWrdTextStyles::readSection: the zone size seems odd\n")); |
955 | 3.24k | return false; |
956 | 3.24k | } |
957 | 10.4k | long pos = entry.begin(); |
958 | 10.4k | entry.setParsed(true); |
959 | 10.4k | MWAWInputStreamPtr &input= m_parserState->m_input; |
960 | 10.4k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
961 | 10.4k | libmwaw::DebugFile &ascFile = m_parserState->m_asciiFile; |
962 | 10.4k | libmwaw::DebugStream f; |
963 | 10.4k | f << "Section:"; |
964 | 10.4k | auto N=size_t(entry.length()/10); |
965 | 10.4k | cLimits.resize(N+1); |
966 | 4.08M | for (auto &limit : cLimits) limit = long(input->readULong(4)); |
967 | | |
968 | 10.4k | MsWrdText::PLC plc(MsWrdText::PLC::Section); |
969 | 10.4k | auto &plcMap = m_textParser->getTextPLCMap(); |
970 | 10.4k | long textLength = m_textParser->getMainTextLength(); |
971 | 4.08M | for (size_t i = 0; i < N; i++) { |
972 | 4.07M | MsWrdStruct::Section sec; |
973 | 4.07M | sec.m_type = static_cast<int>(input->readULong(1)); // 0|40|80|C0 |
974 | 4.07M | sec.m_flag = static_cast<int>(input->readULong(1)); // number between 2 and 7 |
975 | 4.07M | sec.m_id = int(i); |
976 | 4.07M | unsigned long filePos = input->readULong(4); |
977 | 4.07M | if (textLength && cLimits[i] > textLength) { |
978 | 1.32M | MWAW_DEBUG_MSG(("MsWrdTextStyles::readSection: text positions is bad...\n")); |
979 | 1.32M | f << "#"; |
980 | 1.32M | } |
981 | 2.74M | else { |
982 | 2.74M | plc.m_id = int(i); |
983 | 2.74M | plcMap.insert(std::multimap<long, MsWrdText::PLC>::value_type(cLimits[i],plc)); |
984 | 2.74M | } |
985 | 4.07M | f << std::hex << "cPos=" << cLimits[i] << ":[" << sec << ","; |
986 | 4.07M | if (filePos != 0xFFFFFFFFL) { |
987 | 3.98M | f << "pos=" << std::hex << filePos << std::dec << ","; |
988 | 3.98M | long actPos = input->tell(); |
989 | 3.98M | readSection(sec,long(filePos)); |
990 | 3.98M | input->seek(actPos, librevenge::RVNG_SEEK_SET); |
991 | 3.98M | } |
992 | 4.07M | f << "],"; |
993 | | |
994 | 4.07M | m_state->m_sectionList.push_back(sec); |
995 | 4.07M | } |
996 | 10.4k | ascFile.addPos(pos); |
997 | 10.4k | ascFile.addNote(f.str().c_str()); |
998 | | |
999 | 10.4k | ascFile.addPos(entry.end()); |
1000 | 10.4k | ascFile.addNote("_"); |
1001 | 10.4k | return true; |
1002 | 13.7k | } |
1003 | | |
1004 | | bool MsWrdTextStyles::readSection(MsWrdStruct::Section &sec, long debPos) |
1005 | 3.98M | { |
1006 | 3.98M | MWAWInputStreamPtr &input= m_parserState->m_input; |
1007 | 3.98M | if (!input->checkPosition(debPos)) { |
1008 | 2.83M | MWAW_DEBUG_MSG(("MsWrdTextStyles::readSection: can not find section data...\n")); |
1009 | 2.83M | return false; |
1010 | 2.83M | } |
1011 | 1.14M | int const vers = version(); |
1012 | 1.14M | input->seek(debPos, librevenge::RVNG_SEEK_SET); |
1013 | 1.14M | libmwaw::DebugFile &ascFile = m_parserState->m_asciiFile; |
1014 | 1.14M | libmwaw::DebugStream f; |
1015 | 1.14M | auto sz = static_cast<int>(input->readULong(1)); |
1016 | 1.14M | long endPos = debPos+sz+1; |
1017 | 1.14M | if (sz < 1 || sz >= 255) { |
1018 | 226k | MWAW_DEBUG_MSG(("MsWrdTextStyles::readSection: data section size seems bad...\n")); |
1019 | 226k | f << "Section-" << sec.m_id.get() << ":#" << sec; |
1020 | 226k | ascFile.addPos(debPos); |
1021 | 226k | ascFile.addNote(f.str().c_str()); |
1022 | 226k | return false; |
1023 | 226k | } |
1024 | 1.54M | while (input->tell() < endPos) { |
1025 | 1.53M | long pos = input->tell(); |
1026 | 1.53M | bool ok; |
1027 | 1.53M | if (vers <= 3) |
1028 | 783k | ok = sec.readV3(input, endPos); |
1029 | 750k | else |
1030 | 750k | ok = sec.read(input, endPos); |
1031 | 1.53M | if (ok) continue; |
1032 | 914k | f << "#"; |
1033 | 914k | ascFile.addDelimiter(pos,'|'); |
1034 | 914k | break; |
1035 | 1.53M | } |
1036 | 921k | f << "Section-S" << sec.m_id.get() << ":" << sec; |
1037 | 921k | ascFile.addPos(debPos); |
1038 | 921k | ascFile.addNote(f.str().c_str()); |
1039 | | |
1040 | 921k | ascFile.addPos(endPos); |
1041 | 921k | ascFile.addNote("_"); |
1042 | 921k | return true; |
1043 | 1.14M | } |
1044 | | |
1045 | | void MsWrdTextStyles::setProperty(MsWrdStruct::Section const &sec) |
1046 | 61.8k | { |
1047 | 61.8k | MWAWTextListenerPtr listener=m_parserState->m_textListener; |
1048 | 61.8k | if (!listener) return; |
1049 | 61.8k | if (listener->isHeaderFooterOpened()) { |
1050 | 7.55k | MWAW_DEBUG_MSG(("MsWrdTextStyles::setProperty: can not open a section in header/footer\n")); |
1051 | 7.55k | } |
1052 | 54.3k | else { |
1053 | 54.3k | int numCols = sec.m_col.get(); |
1054 | 54.3k | int actCols = listener->getSection().numColumns(); |
1055 | 54.3k | if (numCols >= 1 && actCols > 1 && sec.m_colBreak.get()) { |
1056 | 84 | if (!listener->isSectionOpened()) { |
1057 | 0 | MWAW_DEBUG_MSG(("MsWrdTextStyles::setProperty: section is not opened\n")); |
1058 | 0 | } |
1059 | 84 | else |
1060 | 84 | listener->insertBreak(MWAWTextListener::ColumnBreak); |
1061 | 84 | } |
1062 | 54.2k | else { |
1063 | 54.2k | if (listener->isSectionOpened()) |
1064 | 48.8k | listener->closeSection(); |
1065 | 54.2k | listener->openSection(sec.getSection(m_mainParser->getPageWidth())); |
1066 | 54.2k | } |
1067 | 54.3k | } |
1068 | 61.8k | } |
1069 | | |
1070 | | bool MsWrdTextStyles::sendSection(int id, int textStructId) |
1071 | 61.8k | { |
1072 | 61.8k | if (!m_parserState->m_textListener) return true; |
1073 | | |
1074 | 61.8k | if (id < 0 || id >= int(m_state->m_sectionList.size())) { |
1075 | 0 | MWAW_DEBUG_MSG(("MsWrdTextStyles::sendText: can not find new section\n")); |
1076 | 0 | return false; |
1077 | 0 | } |
1078 | 61.8k | auto section=m_state->m_sectionList[size_t(id)]; |
1079 | 61.8k | MsWrdStruct::Paragraph para(version()); |
1080 | 61.8k | if (textStructId >= 0 && |
1081 | 13.4k | getParagraph(MsWrdTextStyles::TextStructZone, textStructId, para) && |
1082 | 7.10k | para.m_section.isSet()) { |
1083 | 245 | section.insert(*para.m_section); |
1084 | 245 | } |
1085 | 61.8k | setProperty(section); |
1086 | 61.8k | return true; |
1087 | 61.8k | } |
1088 | | |
1089 | | //////////////////////////////////////////////////////////// |
1090 | | // read the styles |
1091 | | //////////////////////////////////////////////////////////// |
1092 | | std::map<int, int> const &MsWrdTextStyles::getNextStyleMap() const |
1093 | 0 | { |
1094 | 0 | return m_state->m_nextStyleMap; |
1095 | 0 | } |
1096 | | |
1097 | | bool MsWrdTextStyles::readStyles(MsWrdEntry &entry) |
1098 | 11.9k | { |
1099 | 11.9k | if (entry.length() < 6) { |
1100 | 322 | MWAW_DEBUG_MSG(("MsWrdTextStyles::readStyles: zone seems to short...\n")); |
1101 | 322 | return false; |
1102 | 322 | } |
1103 | 11.5k | m_state->m_styleFontMap.clear(); |
1104 | 11.5k | m_state->m_styleParagraphMap.clear(); |
1105 | 11.5k | m_state->m_nextStyleMap.clear(); |
1106 | 11.5k | entry.setParsed(true); |
1107 | 11.5k | libmwaw::DebugFile &ascFile = m_parserState->m_asciiFile; |
1108 | 11.5k | ascFile.addPos(entry.end()); |
1109 | 11.5k | ascFile.addNote("_"); |
1110 | | |
1111 | 11.5k | long pos = entry.begin(); |
1112 | 11.5k | libmwaw::DebugStream f; |
1113 | 11.5k | MWAWInputStreamPtr &input= m_parserState->m_input; |
1114 | 11.5k | input->seek(pos, librevenge::RVNG_SEEK_SET); |
1115 | 11.5k | f << entry << ":"; |
1116 | 11.5k | auto N = static_cast<int>(input->readLong(2)); |
1117 | 11.5k | if (N) f << "N?=" << N; |
1118 | 11.5k | ascFile.addPos(pos); |
1119 | 11.5k | ascFile.addNote(f.str().c_str()); |
1120 | | |
1121 | | // first find the different zone |
1122 | 11.5k | long debPos[4]; |
1123 | 11.5k | int const overOk[3]= {0,30,100}; // name, font, paragraph |
1124 | 35.3k | for (int st = 0; st < 3; st++) { |
1125 | 27.5k | debPos[st] = input->tell(); |
1126 | 27.5k | auto dataSz = static_cast<int>(input->readULong(2)); |
1127 | 27.5k | long endPos = debPos[st]+dataSz; |
1128 | 27.5k | if (dataSz < 2+N || endPos > entry.end()+overOk[st]) { |
1129 | 3.85k | ascFile.addPos(pos); |
1130 | 3.85k | ascFile.addNote("###Styles(bad)"); |
1131 | 3.85k | MWAW_DEBUG_MSG(("MsWrdTextStyles::readStyles: can not read styles(%d)...\n", st)); |
1132 | 3.85k | return false; |
1133 | 3.85k | } |
1134 | 23.7k | if (endPos > entry.end()) { |
1135 | 6.71k | entry.setEnd(endPos+1); |
1136 | 6.71k | MWAW_DEBUG_MSG(("MsWrdTextStyles::readStyles(%d): size seems incoherent...\n", st)); |
1137 | 6.71k | f.str(""); |
1138 | 6.71k | f << "#sz=" << dataSz << ","; |
1139 | 6.71k | ascFile.addPos(debPos[st]); |
1140 | 6.71k | ascFile.addNote(f.str().c_str()); |
1141 | 6.71k | } |
1142 | 23.7k | input->seek(endPos, librevenge::RVNG_SEEK_SET); |
1143 | 23.7k | } |
1144 | 7.73k | debPos[3] = input->tell(); |
1145 | | // read the styles parents |
1146 | 7.73k | std::vector<int> orig, order; |
1147 | 7.73k | if (readStylesHierarchy(entry, N, orig)) |
1148 | 7.40k | order=orderStyles(orig); |
1149 | | |
1150 | 7.73k | int N1=0; |
1151 | 7.73k | MsWrdEntry zone; |
1152 | 7.73k | zone.setBegin(debPos[0]); |
1153 | 7.73k | zone.setEnd(debPos[1]); |
1154 | 7.73k | if (!readStylesNames(zone, N, N1)) { |
1155 | 809 | N1=int(orig.size())-N; |
1156 | 809 | if (N1 < 0) |
1157 | 39 | return false; |
1158 | 809 | } |
1159 | | // ok, repair orig, and order if need |
1160 | 7.69k | if (int(orig.size()) < N+N1) |
1161 | 1.17k | orig.resize(size_t(N+N1), -1000); |
1162 | 7.69k | if (int(order.size()) < N+N1) { |
1163 | 391k | for (auto i = int(order.size()); i < N+N1; i++) |
1164 | 389k | order.push_back(i); |
1165 | 1.17k | } |
1166 | 7.69k | zone.setBegin(debPos[1]); |
1167 | 7.69k | zone.setEnd(debPos[2]); |
1168 | 7.69k | readStylesFont(zone, N, orig, order); |
1169 | | |
1170 | 7.69k | zone.setBegin(debPos[2]); |
1171 | 7.69k | zone.setEnd(debPos[3]); |
1172 | 7.69k | readStylesParagraph(zone, N, orig, order); |
1173 | 7.69k | return true; |
1174 | 7.73k | } |
1175 | | |
1176 | | bool MsWrdTextStyles::readStylesNames(MsWrdEntry const &zone, int N, int &Nnamed) |
1177 | 7.73k | { |
1178 | 7.73k | long pos = zone.begin(); |
1179 | 7.73k | MWAWInputStreamPtr &input= m_parserState->m_input; |
1180 | 7.73k | if (!zone.valid() || !input || !input->checkPosition(zone.end())) { |
1181 | 70 | MWAW_DEBUG_MSG(("MsWrdTextStyles::readStylesNames: zone(names) seems to short...\n")); |
1182 | 70 | return false; |
1183 | 70 | } |
1184 | 7.66k | input->seek(pos+2, librevenge::RVNG_SEEK_SET); |
1185 | 7.66k | libmwaw::DebugFile &ascFile = m_parserState->m_asciiFile; |
1186 | 7.66k | libmwaw::DebugStream f; |
1187 | 7.66k | f << "Styles(names):"; |
1188 | 7.66k | int actN=0; |
1189 | 791k | while (long(input->tell()) < zone.end()) { |
1190 | 788k | auto sz = static_cast<int>(input->readULong(1)); |
1191 | 788k | if (sz == 0) { |
1192 | 491k | f << "*"; |
1193 | 491k | actN++; |
1194 | 491k | continue; |
1195 | 491k | } |
1196 | 297k | if (sz == 0xFF) { |
1197 | 59.9k | f << "_"; |
1198 | 59.9k | actN++; |
1199 | 59.9k | continue; |
1200 | 59.9k | } |
1201 | 237k | pos = input->tell(); |
1202 | 237k | if (pos+sz > zone.end()) { |
1203 | 4.85k | MWAW_DEBUG_MSG(("MsWrdTextStyles::readStylesNames: zone(names) seems to short...\n")); |
1204 | 4.85k | f << "#"; |
1205 | 4.85k | ascFile.addNote(f.str().c_str()); |
1206 | 4.85k | input->seek(pos-1, librevenge::RVNG_SEEK_SET); |
1207 | 4.85k | break; |
1208 | 4.85k | } |
1209 | 232k | std::string s(""); |
1210 | 6.08M | for (int i = 0; i < sz; i++) s += char(input->readULong(1)); |
1211 | 232k | f << "N" << actN-N << "=" ; |
1212 | 232k | f << s << ","; |
1213 | 232k | actN++; |
1214 | 232k | } |
1215 | 7.66k | Nnamed=actN-N; |
1216 | 7.66k | if (Nnamed < 0) { |
1217 | 739 | MWAW_DEBUG_MSG(("MsWrdTextStyles::readStylesNames: zone(names) seems to short: stop...\n")); |
1218 | 739 | f << "#"; |
1219 | 739 | } |
1220 | 7.66k | ascFile.addPos(zone.begin()); |
1221 | 7.66k | ascFile.addNote(f.str().c_str()); |
1222 | 7.66k | return Nnamed >= 0; |
1223 | 7.73k | } |
1224 | | |
1225 | | bool MsWrdTextStyles::readStylesFont |
1226 | | (MsWrdEntry &zone, int N, std::vector<int> const &previous, std::vector<int> const &order) |
1227 | 7.69k | { |
1228 | 7.69k | libmwaw::DebugFile &ascFile = m_parserState->m_asciiFile; |
1229 | 7.69k | libmwaw::DebugStream f; |
1230 | 7.69k | long pos = zone.begin(); |
1231 | 7.69k | ascFile.addPos(pos); |
1232 | 7.69k | ascFile.addNote("Styles(font):"); |
1233 | | |
1234 | 7.69k | MWAWInputStreamPtr &input= m_parserState->m_input; |
1235 | 7.69k | input->seek(pos+2, librevenge::RVNG_SEEK_SET); |
1236 | 7.69k | size_t numElt = order.size(); |
1237 | 7.69k | std::vector<long> debPos; |
1238 | 7.69k | std::vector<int> dataSize; |
1239 | 7.69k | debPos.resize(numElt, 0); |
1240 | 7.69k | dataSize.resize(numElt, 0); |
1241 | 572k | for (size_t i = 0; i < numElt; i++) { |
1242 | 570k | pos = input->tell(); |
1243 | 570k | debPos[i] = pos; |
1244 | 570k | int sz = dataSize[i] = static_cast<int>(input->readULong(1)); |
1245 | 570k | if (sz == 0xFF) |
1246 | 49.5k | sz = 0; |
1247 | 520k | else if (pos+1+sz > zone.end()) { |
1248 | 5.94k | MWAW_DEBUG_MSG(("MsWrdTextStyles::readStylesFont: can not read a font\n")); |
1249 | 5.94k | if (i == 0) |
1250 | 858 | return false; |
1251 | 5.08k | numElt = i-1; |
1252 | 5.08k | break; |
1253 | 5.94k | } |
1254 | 564k | if (sz) |
1255 | 224k | input->seek(sz, librevenge::RVNG_SEEK_CUR); |
1256 | 339k | else { |
1257 | 339k | f.str(""); |
1258 | 339k | f << "CharPLC(sF" << int(i)-N << "):"; |
1259 | 339k | ascFile.addPos(pos); |
1260 | 339k | ascFile.addNote(f.str().c_str()); |
1261 | 339k | } |
1262 | 564k | } |
1263 | | |
1264 | 115M | for (auto id : order) { |
1265 | 115M | if (id < 0 || id >= int(numElt)) continue; |
1266 | 559k | int prevId = previous[size_t(id)]; |
1267 | 559k | MsWrdStruct::Font font; |
1268 | | // osnola:what is the difference between dataSize[(size_t)id]=0|0xFF |
1269 | 559k | if (prevId >= 0 && m_state->m_styleFontMap.find(prevId-N) != m_state->m_styleFontMap.end()) |
1270 | 390k | font = m_state->m_styleFontMap.find(prevId-N)->second; |
1271 | 559k | if (dataSize[size_t(id)] && dataSize[size_t(id)] != 0xFF) { |
1272 | 223k | input->seek(debPos[size_t(id)], librevenge::RVNG_SEEK_SET); |
1273 | | |
1274 | 223k | f.str(""); |
1275 | 223k | f << "CharPLC(sF" << id-int(N) << "):"; |
1276 | 223k | if (!readFont(font, StyleZone)) f << "#"; |
1277 | 156k | else if (id==int(N)) m_state->m_defaultFont=font.m_font.get(); |
1278 | 223k | f << "font=[" << font.m_font->getDebugString(m_parserState->m_fontConverter) << font << "],"; |
1279 | 223k | ascFile.addPos(debPos[size_t(id)]); |
1280 | 223k | ascFile.addNote(f.str().c_str()); |
1281 | 223k | } |
1282 | 559k | m_state->m_styleFontMap.insert(std::map<int, MsWrdStruct::Font>::value_type(id-N,font)); |
1283 | 559k | } |
1284 | 6.83k | return true; |
1285 | 7.69k | } |
1286 | | |
1287 | | bool MsWrdTextStyles::readStylesParagraph(MsWrdEntry &zone, int N, std::vector<int> const &previous, |
1288 | | std::vector<int> const &order) |
1289 | 7.69k | { |
1290 | 7.69k | int const vers=version(); |
1291 | 7.69k | int minSz = vers <= 3 ? 3 : 7; |
1292 | 7.69k | libmwaw::DebugFile &ascFile = m_parserState->m_asciiFile; |
1293 | 7.69k | libmwaw::DebugStream f; |
1294 | 7.69k | long pos = zone.begin(); |
1295 | 7.69k | ascFile.addPos(pos); |
1296 | 7.69k | ascFile.addNote("Styles(paragraph):"); |
1297 | | |
1298 | 7.69k | MWAWInputStreamPtr &input= m_parserState->m_input; |
1299 | 7.69k | input->seek(pos+2, librevenge::RVNG_SEEK_SET); |
1300 | 7.69k | size_t numElt = order.size(); |
1301 | 7.69k | std::vector<long> debPos; |
1302 | 7.69k | std::vector<int> dataSize; |
1303 | 7.69k | debPos.resize(numElt, 0); |
1304 | 7.69k | dataSize.resize(numElt, 0); |
1305 | 841k | for (size_t i = 0; i < numElt; i++) { |
1306 | 839k | pos = input->tell(); |
1307 | 839k | debPos[i] = pos; |
1308 | 839k | int sz = dataSize[i] = static_cast<int>(input->readULong(1)); |
1309 | 839k | if (sz != 0xFF && pos+1+sz > zone.end()) { |
1310 | 5.71k | MWAW_DEBUG_MSG(("MsWrdTextStyles::readStylesParagraph: can not read a paragraph\n")); |
1311 | 5.71k | if (i == 0) |
1312 | 632 | return false; |
1313 | 5.08k | numElt = i-1; |
1314 | 5.08k | break; |
1315 | 5.71k | } |
1316 | 833k | if (sz && sz != 0xFF) |
1317 | 298k | input->seek(sz, librevenge::RVNG_SEEK_CUR); |
1318 | 535k | else { |
1319 | 535k | f.str(""); |
1320 | 535k | f << "ParagPLC(sP" << int(i)-N << "):"; |
1321 | 535k | ascFile.addPos(pos); |
1322 | 535k | ascFile.addNote(f.str().c_str()); |
1323 | 535k | } |
1324 | 833k | } |
1325 | 118M | for (auto id : order) { |
1326 | 118M | if (id < 0 || id >= int(numElt)) continue; |
1327 | 828k | int prevId = previous[size_t(id)]; |
1328 | 828k | MsWrdStruct::Paragraph para(vers); |
1329 | 828k | if (prevId >= 0 && m_state->m_styleParagraphMap.find(prevId-N) != m_state->m_styleParagraphMap.end()) |
1330 | 552k | para = m_state->m_styleParagraphMap.find(prevId-N)->second; |
1331 | | /** osnola: update the font style here or after reading data ? */ |
1332 | 828k | if (m_state->m_styleFontMap.find(id-N) != m_state->m_styleFontMap.end()) |
1333 | 266k | para.m_font = m_state->m_styleFontMap.find(id-N)->second; |
1334 | 828k | if (dataSize[size_t(id)] != 0xFF) { |
1335 | 731k | f.str(""); |
1336 | 731k | f << "ParagPLC(sP" << id-N << "):"; |
1337 | 731k | if (dataSize[size_t(id)] < minSz) { |
1338 | 499k | MWAW_DEBUG_MSG(("MsWrdTextStyles::readStylesParagraph: zone(paragraph) the id seems bad...\n")); |
1339 | 499k | f << "#"; |
1340 | 499k | } |
1341 | 232k | else { |
1342 | 232k | input->seek(debPos[size_t(id)]+1, librevenge::RVNG_SEEK_SET); |
1343 | 232k | auto pId = static_cast<int>(input->readLong(1)); |
1344 | 232k | if (id >= N && pId != id-N) { |
1345 | 179k | MWAW_DEBUG_MSG(("MsWrdTextStyles::readStylesParagraph: zone(paragraph) the id seems bad...\n")); |
1346 | 179k | f << "#id=" << pId << ","; |
1347 | 179k | } |
1348 | 232k | auto val = static_cast<int>(input->readLong(2)); // always 0? |
1349 | 232k | if (val) f << "g0=" << val << ","; |
1350 | | |
1351 | 232k | if (vers > 3) { |
1352 | 188k | for (int j = 1; j < 3; j++) { // 0|90|c0,0|1 |
1353 | 125k | val = static_cast<int>(input->readLong(2)); |
1354 | 125k | if (val) f << "g" << j << "=" << std::hex << val << std::dec << ","; |
1355 | 125k | } |
1356 | 62.9k | } |
1357 | | |
1358 | 232k | if (dataSize[size_t(id)] != minSz && !readParagraph(para, dataSize[size_t(id)]-minSz)) |
1359 | 0 | f << "#"; |
1360 | | #ifdef DEBUG_WITH_FILES |
1361 | | para.print(f, m_parserState->m_fontConverter); |
1362 | | #endif |
1363 | 232k | } |
1364 | 731k | ascFile.addPos(debPos[size_t(id)]); |
1365 | 731k | ascFile.addNote(f.str().c_str()); |
1366 | 731k | } |
1367 | 828k | para.m_modFont.setSet(false); |
1368 | 828k | m_state->m_styleParagraphMap.insert |
1369 | 828k | (std::map<int, MsWrdStruct::Paragraph>::value_type(id-N,para)); |
1370 | 828k | } |
1371 | 7.06k | return true; |
1372 | 7.69k | } |
1373 | | |
1374 | | bool MsWrdTextStyles::readStylesHierarchy(MsWrdEntry &entry, int N, std::vector<int> &orig) |
1375 | 7.73k | { |
1376 | 7.73k | MWAWInputStreamPtr &input= m_parserState->m_input; |
1377 | 7.73k | long pos = input->tell(); |
1378 | 7.73k | libmwaw::DebugFile &ascFile = m_parserState->m_asciiFile; |
1379 | 7.73k | libmwaw::DebugStream f; |
1380 | 7.73k | f << "Styles(hierarchy):"; |
1381 | | |
1382 | 7.73k | auto N2 = static_cast<int>(input->readULong(2)); |
1383 | 7.73k | if (N2 < N) { |
1384 | 333 | MWAW_DEBUG_MSG(("MsWrdTextStyles::readStylesHierarchy: N seems too small...\n")); |
1385 | 333 | f << "#N=" << N2 << ","; |
1386 | 333 | ascFile.addPos(pos); |
1387 | 333 | ascFile.addNote("Styles(hierarchy):#"); // big problem |
1388 | 333 | return false; |
1389 | 333 | } |
1390 | 7.40k | if (pos+(N2+1)*2 > entry.end()) { |
1391 | 5.13k | if (N2>40) { |
1392 | 4.58k | MWAW_DEBUG_MSG(("MsWrdTextStyles::readStylesHierarchy: N seems very big...\n")); |
1393 | 4.58k | ascFile.addPos(pos); |
1394 | 4.58k | ascFile.addNote("Styles(hierarchy):#"); // big problem |
1395 | 4.58k | } |
1396 | 5.13k | f << "#"; |
1397 | 5.13k | } |
1398 | 7.40k | orig.resize(0); |
1399 | 7.40k | orig.resize(size_t(N2), -1000); |
1400 | 124M | for (int i = 0; i < N2; i++) { |
1401 | 124M | auto v0 = static_cast<int>(input->readLong(1)); // often 0 or i-N |
1402 | 124M | auto v1 = static_cast<int>(input->readLong(1)); |
1403 | 124M | f << "prev(sP"<< i-N << ")"; |
1404 | 124M | if (v1 == -34) { |
1405 | 16.3k | } |
1406 | 124M | else if (v1 < -N || v1+N >= N2) |
1407 | 30.9M | f << "=###" << v1; |
1408 | 93.4M | else { |
1409 | 93.4M | orig[size_t(i)] = v1+N; |
1410 | 93.4M | f << "=sP" << v1; |
1411 | 93.4M | } |
1412 | 124M | if (v0 < -N || v0+N >= N2) { |
1413 | 31.0M | f << "[###next" << v0 << "]"; |
1414 | 31.0M | m_state->m_nextStyleMap[i-N]=i-N; |
1415 | 31.0M | } |
1416 | 93.4M | else { |
1417 | 93.4M | m_state->m_nextStyleMap[i-N]=v0; |
1418 | 93.4M | if (v0==i-N) |
1419 | 8.21k | f << "*"; |
1420 | 93.4M | else if (v0) |
1421 | 3.98M | f << "[next" << v0 << "]"; |
1422 | 93.4M | } |
1423 | 124M | f << ","; |
1424 | 124M | } |
1425 | | |
1426 | 7.40k | ascFile.addPos(pos); |
1427 | 7.40k | ascFile.addNote(f.str().c_str()); |
1428 | | |
1429 | 7.40k | pos = input->tell(); |
1430 | 7.40k | if (pos < entry.end()) { |
1431 | 962 | ascFile.addPos(pos); |
1432 | 962 | ascFile.addNote("_"); |
1433 | 962 | } |
1434 | 6.44k | else if (pos > entry.end()) |
1435 | 5.11k | entry.setEnd(pos); |
1436 | | |
1437 | 7.40k | return true; |
1438 | 7.73k | } |
1439 | | |
1440 | | std::vector<int> MsWrdTextStyles::orderStyles(std::vector<int> const &previous) |
1441 | 7.40k | { |
1442 | 7.40k | std::vector<int> order, numChild; |
1443 | 7.40k | size_t N = previous.size(); |
1444 | 7.40k | numChild.resize(N, 0); |
1445 | 124M | for (auto id : previous) { |
1446 | 124M | if (id == -1000) continue; |
1447 | 93.4M | if (id < 0 || id >= int(N)) { |
1448 | 0 | MWAW_DEBUG_MSG(("MsWrdTextStyles::orderStyles: find a bad previous %d\n", id)); |
1449 | 0 | continue; |
1450 | 0 | } |
1451 | 93.4M | numChild[size_t(id)]++; |
1452 | 93.4M | } |
1453 | 7.40k | order.resize(N); |
1454 | 7.40k | size_t numElt = 0; |
1455 | 23.1k | while (numElt < N) { |
1456 | 19.0k | bool read = false; |
1457 | 394M | for (size_t i = 0; i < N; i++) { |
1458 | 394M | if (numChild[i]) continue; |
1459 | 124M | order[N-(++numElt)]=int(i); |
1460 | 124M | if (previous[i] >= 0 && previous[i] < int(N)) |
1461 | 93.4M | numChild[size_t(previous[i])]--; |
1462 | 124M | read = true; |
1463 | 124M | numChild[i]=-1; |
1464 | 124M | } |
1465 | 19.0k | if (read) continue; |
1466 | 3.29k | MWAW_DEBUG_MSG(("MsWrdTextStyles::orderStyles: find a loop, stop...\n")); |
1467 | 67.7M | for (size_t i = 0; i < N; i++) { |
1468 | 67.7M | if (numChild[i] != -1) |
1469 | 7.82k | order[N-(++numElt)]=int(i); |
1470 | 67.7M | } |
1471 | 3.29k | break; |
1472 | 19.0k | } |
1473 | 7.40k | return order; |
1474 | 7.40k | } |
1475 | | |
1476 | | // vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: |