Coverage Report

Created: 2026-06-13 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libmwaw/src/lib/StyleParser.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 <set>
38
#include <sstream>
39
40
#include <librevenge/librevenge.h>
41
42
#include "MWAWTextListener.hxx"
43
#include "MWAWFont.hxx"
44
#include "MWAWFontConverter.hxx"
45
#include "MWAWHeader.hxx"
46
#include "MWAWParagraph.hxx"
47
#include "MWAWPictData.hxx"
48
#include "MWAWPosition.hxx"
49
#include "MWAWPrinter.hxx"
50
#include "MWAWRSRCParser.hxx"
51
#include "MWAWSubDocument.hxx"
52
53
#include "StyleParser.hxx"
54
55
/** Internal: the structures of a StyleParser */
56
namespace StyleParserInternal
57
{
58
//! small structure used to store picture data in StyleParser
59
struct Picture {
60
  //! constructor
61
  Picture()
62
63.9k
    : m_size(0,0)
63
63.9k
    , m_entry()
64
63.9k
  {
65
63.9k
  }
66
  //! returns true if the picture is valid
67
  bool valid() const
68
21.0k
  {
69
21.0k
    return m_entry.valid();
70
21.0k
  }
71
  //! the picture size in point
72
  MWAWVec2i m_size;
73
  //! the picture entry
74
  MWAWEntry m_entry;
75
};
76
77
//! small structure used to store a font and a picture
78
struct Font {
79
  //! constructor
80
  Font()
81
55.6k
    : m_font()
82
55.6k
    , m_picture()
83
55.6k
  {
84
55.6k
  }
85
  //! returns true if the picture is valid
86
  bool hasPicture() const
87
20.8k
  {
88
20.8k
    return m_picture.valid();
89
20.8k
  }
90
  //! the font
91
  MWAWFont m_font;
92
  //! the picture
93
  Picture m_picture;
94
};
95
96
////////////////////////////////////////
97
//! Internal: the state of a StyleParser
98
struct State {
99
  //! constructor
100
  State()
101
66.3k
    : m_entryMap()
102
66.3k
    , m_unicodeChar(false)
103
66.3k
    , m_textEntry()
104
66.3k
    , m_backgroundColor(MWAWColor::white())
105
66.3k
    , m_fontIdToFinalIdList()
106
66.3k
    , m_fontList()
107
66.3k
    , m_paragraphList()
108
66.3k
    , m_posFontIdMap()
109
66.3k
    , m_posParagraphIdMap()
110
66.3k
    , m_posPictureMap()
111
66.3k
    , m_actPage(0)
112
66.3k
    , m_numPages(0)
113
66.3k
  {
114
66.3k
  }
115
  //! the map type to entry
116
  std::map<std::string, MWAWEntry> m_entryMap;
117
  //! true if the character are unicode character
118
  bool m_unicodeChar;
119
  //! the text entry
120
  MWAWEntry m_textEntry;
121
  //! the background color
122
  MWAWColor m_backgroundColor;
123
  //! list of font final id
124
  std::vector<int> m_fontIdToFinalIdList;
125
  //! the list of font style
126
  std::vector<Font> m_fontList;
127
  //! the list of paragraph style
128
  std::vector<MWAWParagraph> m_paragraphList;
129
  //! a map pos->font id
130
  std::map<long, int> m_posFontIdMap;
131
  //! a map pos->paragraphId
132
  std::map<long, int> m_posParagraphIdMap;
133
  //! a map pos->pictEntry
134
  std::map<long, Picture> m_posPictureMap;
135
  int m_actPage /** the actual page */, m_numPages /** the number of page of the final document */;
136
};
137
138
}
139
140
////////////////////////////////////////////////////////////
141
// constructor/destructor, ...
142
////////////////////////////////////////////////////////////
143
StyleParser::StyleParser(MWAWInputStreamPtr const &input, MWAWRSRCParserPtr const &rsrcParser, MWAWHeader *header)
144
27.8k
  : MWAWTextParser(input, rsrcParser, header)
145
27.8k
  , m_state(new StyleParserInternal::State)
146
27.8k
{
147
27.8k
  getPageSpan().setMargins(0.1);
148
27.8k
}
149
150
StyleParser::~StyleParser()
151
27.8k
{
152
27.8k
}
153
154
////////////////////////////////////////////////////////////
155
// new page
156
////////////////////////////////////////////////////////////
157
void StyleParser::newPage(int number)
158
26.9k
{
159
26.9k
  if (number <= m_state->m_actPage || number > m_state->m_numPages)
160
0
    return;
161
162
54.9k
  while (m_state->m_actPage < number) {
163
28.0k
    m_state->m_actPage++;
164
28.0k
    if (!getTextListener() || m_state->m_actPage == 1)
165
1.11k
      continue;
166
26.9k
    getTextListener()->insertBreak(MWAWTextListener::PageBreak);
167
26.9k
  }
168
26.9k
}
169
170
////////////////////////////////////////////////////////////
171
// the parser
172
////////////////////////////////////////////////////////////
173
void StyleParser::parse(librevenge::RVNGTextInterface *docInterface)
174
10.6k
{
175
10.6k
  if (!getInput().get() || !checkHeader(nullptr))  throw(libmwaw::ParseException());
176
10.6k
  bool ok = false;
177
10.6k
  try {
178
    // create the asciiFile
179
10.6k
    ascii().setStream(getInput());
180
10.6k
    ascii().open("main-1");
181
10.6k
    checkHeader(nullptr);
182
10.6k
    ok = createZones();
183
10.6k
    if (ok) {
184
6.24k
      createDocument(docInterface);
185
6.24k
      sendText(m_state->m_textEntry, m_state->m_unicodeChar);
186
6.24k
    }
187
10.6k
    ascii().reset();
188
10.6k
  }
189
10.6k
  catch (...) {
190
0
    MWAW_DEBUG_MSG(("StyleParser::parse: exception catched when parsing\n"));
191
0
    ok = false;
192
0
  }
193
194
10.6k
  resetTextListener();
195
10.6k
  if (!ok) throw(libmwaw::ParseException());
196
10.6k
}
197
198
////////////////////////////////////////////////////////////
199
// create the document
200
////////////////////////////////////////////////////////////
201
void StyleParser::createDocument(librevenge::RVNGTextInterface *documentInterface)
202
6.24k
{
203
6.24k
  if (!documentInterface) return;
204
6.24k
  if (getTextListener()) {
205
0
    MWAW_DEBUG_MSG(("StyleParser::createDocument: listener already exist\n"));
206
0
    return;
207
0
  }
208
209
  // update the page
210
6.24k
  m_state->m_actPage = 0;
211
212
  // create the page list
213
6.24k
  int numPages=m_state->m_textEntry.valid() ? computeNumPages(m_state->m_textEntry, m_state->m_unicodeChar) : 1;
214
6.24k
  m_state->m_numPages = numPages;
215
6.24k
  MWAWPageSpan ps(getPageSpan());
216
6.24k
  ps.setPageSpan(m_state->m_numPages+1);
217
6.24k
  if (!m_state->m_backgroundColor.isWhite())
218
1.15k
    ps.setBackgroundColor(m_state->m_backgroundColor);
219
6.24k
  std::vector<MWAWPageSpan> pageList(1,ps);
220
6.24k
  MWAWTextListenerPtr listen(new MWAWTextListener(*getParserState(), pageList, documentInterface));
221
6.24k
  setTextListener(listen);
222
6.24k
  listen->startDocument();
223
6.24k
}
224
225
226
////////////////////////////////////////////////////////////
227
//
228
// Intermediate level
229
//
230
////////////////////////////////////////////////////////////
231
bool StyleParser::createZones()
232
10.6k
{
233
10.6k
  if (!readTypeEntryMap())
234
1.44k
    return false;
235
9.21k
  libmwaw::DebugStream f;
236
9.21k
  auto &entryMap = m_state->m_entryMap;
237
238
  // basic data
239
9.21k
  auto it = entryMap.find("vers");
240
9.21k
  if (it != entryMap.end()) {
241
3.00k
    MWAWEntry const &entry = it++->second;
242
3.00k
    readVersion(entry);
243
3.00k
  }
244
9.21k
  it = entryMap.find("bgcl");
245
9.21k
  if (it != entryMap.end()) {
246
1.56k
    MWAWEntry const &entry = it++->second;
247
1.56k
    readBackgroundColor(entry);
248
1.56k
  }
249
9.21k
  it = entryMap.find("marg");
250
9.21k
  if (it != entryMap.end()) {
251
1.65k
    MWAWEntry const &entry = it++->second;
252
1.65k
    readMargins(entry);
253
1.65k
  }
254
9.21k
  it = entryMap.find("prec");
255
9.21k
  if (it != entryMap.end()) {
256
1.96k
    MWAWEntry const &entry = it++->second;
257
1.96k
    readPrintInfo(entry);
258
1.96k
  }
259
9.21k
  it = entryMap.find("stat");
260
9.21k
  if (it != entryMap.end()) {
261
1.29k
    MWAWEntry const &entry = it++->second;
262
1.29k
    readStat(entry);
263
1.29k
  }
264
9.21k
  it = entryMap.find("tabw");
265
9.21k
  if (it != entryMap.end()) {
266
1.15k
    MWAWEntry const &entry = it++->second;
267
1.15k
    readTabWidth(entry);
268
1.15k
  }
269
9.21k
  bool findTextEntry=false;
270
9.21k
  it = entryMap.find("text");
271
9.21k
  if (it != entryMap.end()) {
272
1.52k
    findTextEntry=true;
273
1.52k
    MWAWEntry const &entry = it++->second;
274
1.52k
    entry.setParsed(true);
275
1.52k
    m_state->m_unicodeChar=false;
276
1.52k
    m_state->m_textEntry=entry;
277
1.52k
  }
278
9.21k
  it = entryMap.find("utxt");
279
9.21k
  if (it != entryMap.end()) {
280
4.72k
    findTextEntry=true;
281
4.72k
    MWAWEntry const &entry = it++->second;
282
4.72k
    entry.setParsed(true);
283
4.72k
    m_state->m_unicodeChar=true;
284
4.72k
    m_state->m_textEntry=entry;
285
4.72k
  }
286
287
  // font
288
289
  //  v1.9
290
9.21k
  it = entryMap.find("cfor");
291
9.21k
  if (it != entryMap.end()) {
292
2.07k
    MWAWEntry const &entry = it++->second;
293
2.07k
    readFormats(entry);
294
2.07k
  }
295
  //   or v1.6
296
9.21k
  it = entryMap.find("font");
297
9.21k
  if (it != entryMap.end()) {
298
877
    MWAWEntry const &entry = it++->second;
299
877
    readFontCorr(entry);
300
877
  }
301
9.21k
  it = entryMap.find("fntb");
302
9.21k
  if (it != entryMap.end()) {
303
1.15k
    MWAWEntry const &entry = it++->second;
304
1.15k
    readFontNames(entry);
305
1.15k
  }
306
9.21k
  it = entryMap.find("styl");
307
9.21k
  if (it != entryMap.end()) {
308
1.38k
    MWAWEntry const &entry = it++->second;
309
1.38k
    readStyleTable(entry);
310
1.38k
  }
311
  // v1.6 or v1.9
312
9.21k
  it = entryMap.find("runa");
313
9.21k
  if (it != entryMap.end()) {
314
4.39k
    MWAWEntry const &entry = it++->second;
315
4.39k
    readPLCs(entry, false);
316
4.39k
  }
317
318
  // para
319
9.21k
  it = entryMap.find("rule");
320
9.21k
  if (it != entryMap.end()) {
321
1.93k
    MWAWEntry const &entry = it++->second;
322
1.93k
    readRules(entry);
323
1.93k
  }
324
9.21k
  it = entryMap.find("para");
325
9.21k
  if (it != entryMap.end()) {
326
3.88k
    MWAWEntry const &entry = it++->second;
327
3.88k
    readPLCs(entry, true);
328
3.88k
  }
329
330
  // image
331
9.21k
  it = entryMap.find("soup");
332
9.21k
  if (it != entryMap.end()) {
333
1.83k
    MWAWEntry const &entry = it++->second;
334
1.83k
    readPictures(entry);
335
1.83k
  }
336
337
  // extra
338
9.21k
  it = entryMap.find("xprc");
339
9.21k
  if (it != entryMap.end()) {
340
1.38k
    MWAWEntry const &entry = it++->second;
341
1.38k
    readExtraProperties(entry);
342
1.38k
  }
343
344
  // other
345
42.5k
  for (auto const &iter : entryMap) {
346
42.5k
    MWAWEntry const &entry=iter.second;
347
42.5k
    if (entry.isParsed()) continue;
348
9.23k
    f.str("");
349
9.23k
    f << "Entries(" << entry.type() << "):";
350
9.23k
    ascii().addPos(entry.begin());
351
9.23k
    ascii().addNote(f.str().c_str());
352
9.23k
    ascii().addPos(entry.end());
353
9.23k
    ascii().addNote("_");
354
9.23k
  }
355
9.21k
  return m_state->m_textEntry.valid() || findTextEntry;
356
10.6k
}
357
358
bool StyleParser::readTypeEntryMap()
359
24.7k
{
360
24.7k
  MWAWInputStreamPtr input = getInput();
361
24.7k
  if (!input->checkPosition(16)) return false;
362
24.7k
  input->seek(8, librevenge::RVNG_SEEK_SET);
363
24.7k
  long pos=input->tell();
364
24.7k
  libmwaw::DebugStream f;
365
24.7k
  f << "Entries(ZoneList):";
366
24.7k
  int val;
367
24.7k
  auto N=static_cast<int>(input->readLong(2));
368
24.7k
  f << "N=" << N+1 << ",";
369
24.7k
  if (!input->checkPosition(16+16*(N+1))) return false;
370
97.4k
  for (int i=0; i<3; ++i) { //  always 0
371
73.0k
    val=static_cast<int>(input->readLong(2));
372
73.0k
    if (val)
373
15.4k
      f << "f" << i << "=" << val << ",";
374
73.0k
  }
375
24.3k
  ascii().addPos(pos);
376
24.3k
  ascii().addNote(f.str().c_str());
377
24.3k
  m_state->m_entryMap.clear();
378
24.3k
  bool ok=false;
379
4.09M
  for (int i=0; i<=N; ++i) {
380
4.07M
    pos=input->tell();
381
4.07M
    f.str("");
382
4.07M
    f << "ZoneList-" << i << ":";
383
4.07M
    std::string wh("");
384
20.3M
    for (int c=0; c<4; ++c) wh+=char(input->readULong(1));
385
4.07M
    f << wh << ",";
386
4.07M
    if (wh=="text" || wh=="utxt") ok=true;
387
12.2M
    for (int j=0; j<2; ++j) {
388
      // always 0
389
8.14M
      val=static_cast<int>(input->readLong(2));
390
8.14M
      if (val)
391
5.29M
        f << "f" << i << "=" << val << ",";
392
8.14M
    }
393
4.07M
    MWAWEntry entry;
394
4.07M
    entry.setType(wh);
395
4.07M
    entry.setBegin(long(input->readLong(4)));
396
4.07M
    entry.setLength(long(input->readLong(4)));
397
4.07M
    f << std::hex << entry.begin() << "<->" << entry.end() << ",";
398
4.07M
    if (!entry.length()) {
399
      // ok if the document is empty
400
745k
      if (wh=="text" || wh=="utxt")
401
4.80k
        m_state->m_entryMap[wh]=entry;
402
745k
    }
403
3.32M
    else if (entry.begin()<16+16*(N+1) || !input->checkPosition(entry.end()) ||
404
3.22M
             m_state->m_entryMap.find(wh)!=m_state->m_entryMap.end()) {
405
3.22M
      MWAW_DEBUG_MSG(("StyleParser::readTypeEntryMap: find some bad entry"));
406
3.22M
      f << "###";
407
3.22M
    }
408
104k
    else
409
104k
      m_state->m_entryMap[wh]=entry;
410
4.07M
    ascii().addPos(pos);
411
4.07M
    ascii().addNote(f.str().c_str());
412
4.07M
  }
413
24.3k
  ascii().addPos(input->tell());
414
24.3k
  ascii().addNote("_");
415
24.3k
  return ok && !m_state->m_entryMap.empty();
416
24.7k
}
417
418
////////////////////////////////////////////////////////////
419
// font
420
////////////////////////////////////////////////////////////
421
bool StyleParser::readFontNames(MWAWEntry const &entry)
422
1.15k
{
423
1.15k
  MWAWInputStreamPtr input = getInput();
424
1.15k
  if (!entry.valid() || !input->checkPosition(entry.end())) {
425
42
    MWAW_DEBUG_MSG(("StyleParser::readFontNames: the entry seems bad\n"));
426
42
    return false;
427
42
  }
428
1.11k
  entry.setParsed(true);
429
1.11k
  libmwaw::DebugStream f;
430
1.11k
  f << "Entries(Font)[names]:";
431
1.11k
  input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
432
1.11k
  long endPos=entry.end();
433
8.81k
  while (input->tell()<endPos) {
434
8.38k
    long actPos=input->tell();
435
8.38k
    auto dSz=static_cast<int>(input->readULong(1));
436
8.38k
    if (!dSz || actPos+1+dSz > endPos) {
437
683
      MWAW_DEBUG_MSG(("StyleParser::readFontNames: can not read some entry\n"));
438
683
      ascii().addDelimiter(input->tell(),'|');
439
683
      f << "###";
440
683
      break;
441
683
    }
442
7.70k
    std::string name("");
443
112k
    for (int i=0; i<dSz; ++i) name+=char(input->readULong(1));
444
7.70k
    f << name << ",";
445
7.70k
    m_state->m_fontIdToFinalIdList.push_back(getFontConverter()->getId(name));
446
7.70k
  }
447
1.11k
  ascii().addPos(entry.begin());
448
1.11k
  ascii().addNote(f.str().c_str());
449
1.11k
  ascii().addPos(entry.end());
450
1.11k
  ascii().addNote("_");
451
1.11k
  return true;
452
1.15k
}
453
454
bool StyleParser::readFontCorr(MWAWEntry const &entry)
455
877
{
456
877
  MWAWInputStreamPtr input = getInput();
457
877
  if (!entry.valid() || !input->checkPosition(entry.end())) {
458
19
    MWAW_DEBUG_MSG(("StyleParser::readFontCorr: the entry seems bad\n"));
459
19
    return false;
460
19
  }
461
858
  entry.setParsed(true);
462
858
  libmwaw::DebugStream f;
463
858
  f << "Entries(Font)[correspondance]:";
464
858
  if (entry.length()%32) {
465
15
    MWAW_DEBUG_MSG(("StyleParser::readFontCorr: the entry size seems bad\n"));
466
15
    f << "###";
467
15
    ascii().addPos(entry.begin());
468
15
    ascii().addNote(f.str().c_str());
469
15
    ascii().addPos(entry.end());
470
15
    ascii().addNote("_");
471
15
    return true;
472
15
  }
473
474
843
  ascii().addPos(entry.begin());
475
843
  ascii().addNote(f.str().c_str());
476
843
  ascii().addPos(entry.end());
477
843
  ascii().addNote("_");
478
479
843
  input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
480
843
  auto N=int(entry.length()/30);
481
5.11k
  for (int j=0; j<N; ++j) {
482
4.26k
    long pos=input->tell();
483
4.26k
    f.str("");
484
4.26k
    f << "Font-" << j << ":";
485
4.26k
    f << "id=" << input->readULong(2);
486
68.2k
    for (int i=0; i<15; ++i) { // except f5, always 0
487
64.0k
      auto val=static_cast<int>(input->readULong(2));
488
64.0k
      if (!val)
489
28.4k
        continue;
490
35.5k
      if (i==5) // pos in fntb
491
2.28k
        f << "pos=" << val << ",";
492
33.2k
      else
493
33.2k
        f << "f" << i << "=" << val << ",";
494
35.5k
    }
495
4.26k
    ascii().addPos(pos);
496
4.26k
    ascii().addNote(f.str().c_str());
497
4.26k
    input->seek(pos+32, librevenge::RVNG_SEEK_SET);
498
4.26k
  }
499
843
  return true;
500
858
}
501
502
bool StyleParser::readStyleTable(MWAWEntry const &entry)
503
1.38k
{
504
1.38k
  MWAWInputStreamPtr input = getInput();
505
1.38k
  if (!entry.valid() || !input->checkPosition(entry.end())) {
506
145
    MWAW_DEBUG_MSG(("StyleParser::readStyleTable: the entry seems bad\n"));
507
145
    return false;
508
145
  }
509
1.24k
  entry.setParsed(true);
510
1.24k
  libmwaw::DebugStream f;
511
1.24k
  f << "Entries(Style):";
512
1.24k
  if (entry.length()%20) {
513
96
    MWAW_DEBUG_MSG(("StyleParser::readStyleTable: the entry size seems bad\n"));
514
96
    f << "###";
515
96
    ascii().addPos(entry.begin());
516
96
    ascii().addNote(f.str().c_str());
517
96
    ascii().addPos(entry.end());
518
96
    ascii().addNote("_");
519
96
    return true;
520
96
  }
521
522
1.14k
  ascii().addPos(entry.begin());
523
1.14k
  ascii().addNote(f.str().c_str());
524
1.14k
  ascii().addPos(entry.end());
525
1.14k
  ascii().addNote("_");
526
527
1.14k
  input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
528
1.14k
  auto N=int(entry.length()/20);
529
1.14k
  m_state->m_fontList.clear();
530
39.3k
  for (int i=0; i<N; ++i) {
531
38.1k
    long pos=input->tell();
532
38.1k
    StyleParserInternal::Font font;
533
38.1k
    f.str("");
534
38.1k
    long used = input->readLong(4);
535
38.1k
    int dim[2];
536
76.3k
    for (auto &d : dim) d = static_cast<int>(input->readLong(2));
537
38.1k
    f << "height?=" << dim[0] << ":" << dim[1] << ",";
538
38.1k
    auto fId=static_cast<int>(input->readLong(2));
539
38.1k
    if (fId < 0 && -fId<=static_cast<int>(m_state->m_fontIdToFinalIdList.size()))
540
1.66k
      font.m_font.setId(m_state->m_fontIdToFinalIdList[size_t(-fId-1)]);
541
36.5k
    else if (fId>0) // checkme, never seen
542
18.9k
      font.m_font.setId(fId);
543
17.5k
    else {
544
17.5k
      MWAW_DEBUG_MSG(("StyleParser::readStyleTable: the font id seems bad\n"));
545
17.5k
      f << "##fId=" << fId << ",";
546
17.5k
    }
547
38.1k
    auto flag=static_cast<int>(input->readULong(1));
548
38.1k
    uint32_t flags = 0;
549
38.1k
    if (flag&0x1) flags |= MWAWFont::boldBit;
550
38.1k
    if (flag&0x2) flags |= MWAWFont::italicBit;
551
38.1k
    if (flag&0x4) font.m_font.setUnderlineStyle(MWAWFont::Line::Simple);
552
38.1k
    if (flag&0x8) flags |= MWAWFont::embossBit;
553
38.1k
    if (flag&0x10) flags |= MWAWFont::shadowBit;
554
38.1k
    if (flag&0x20) font.m_font.setDeltaLetterSpacing(-1.);
555
38.1k
    if (flag&0x40) font.m_font.setDeltaLetterSpacing(1.);
556
38.1k
    if (flag&0x80) f << "#flags=" << std::hex << (flag&0x80) << std::dec << ",";
557
38.1k
    flag=static_cast<int>(input->readULong(1));
558
38.1k
    if (flag) f << "#flags1=" << std::hex << flag << std::dec << ",";
559
38.1k
    font.m_font.setSize(float(input->readULong(2)));
560
38.1k
    font.m_font.setFlags(flags);
561
38.1k
    unsigned char col[3];
562
114k
    for (auto &c : col) c = static_cast<unsigned char>(input->readULong(2)>>8);
563
38.1k
    font.m_font.setColor(MWAWColor(col[0],col[1],col[2]));
564
38.1k
    font.m_font.m_extra=f.str();
565
38.1k
    m_state->m_fontList.push_back(font);
566
567
38.1k
    f.str("");
568
38.1k
    f << "Style-" << i << ":";
569
38.1k
    if (used!=1) f << "used?=" << used << ",";
570
#ifdef DEBUG
571
    f << ",font=[" << font.m_font.getDebugString(getFontConverter()) << "]";
572
#endif
573
38.1k
    ascii().addPos(pos);
574
38.1k
    ascii().addNote(f.str().c_str());
575
38.1k
    input->seek(pos+20, librevenge::RVNG_SEEK_SET);
576
38.1k
  }
577
1.14k
  return true;
578
1.24k
}
579
580
bool StyleParser::readFormats(MWAWEntry const &entry)
581
2.07k
{
582
2.07k
  MWAWInputStreamPtr input = getInput();
583
2.07k
  if (!entry.valid() || !input->checkPosition(entry.end()) || entry.length()<24) {
584
206
    MWAW_DEBUG_MSG(("StyleParser::readFormats: the entry seems bad\n"));
585
206
    return false;
586
206
  }
587
1.86k
  entry.setParsed(true);
588
1.86k
  input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
589
1.86k
  ascii().addPos(entry.end());
590
1.86k
  ascii().addNote("_");
591
1.86k
  libmwaw::DebugStream f;
592
1.86k
  f << "Entries(Format):";
593
1.86k
  int val;
594
13.0k
  for (int i=0; i<6; ++i) { // f5=0|18
595
11.2k
    val=static_cast<int>(input->readLong(2));
596
11.2k
    if (val)
597
1.33k
      f << "f" << i << "=" << val << ",";
598
11.2k
  }
599
1.86k
  std::string marker("");
600
9.34k
  for (int i=0; i<4; ++i) marker+=char(input->readULong(1));
601
1.86k
  if (marker!="list") {
602
334
    MWAW_DEBUG_MSG(("StyleParser::readFormats: can not find the list marker\n"));
603
334
    f << "###";
604
334
    ascii().addPos(entry.begin());
605
334
    ascii().addNote(f.str().c_str());
606
334
    return false;
607
334
  }
608
1.53k
  auto N=static_cast<int>(input->readLong(4));
609
1.53k
  f << "N=" << N << ",";
610
4.60k
  for (int i=0; i<2; ++i) { // always 0
611
3.06k
    val=static_cast<int>(input->readLong(2));
612
3.06k
    if (val)
613
69
      f << "g" << i << "=" << val << ",";
614
3.06k
  }
615
616
1.53k
  input->seek(entry.begin()+24, librevenge::RVNG_SEEK_SET);
617
1.53k
  ascii().addPos(entry.begin());
618
1.53k
  ascii().addNote(f.str().c_str());
619
620
19.0k
  for (int form=0; form<N; ++form) {
621
18.5k
    long pos=input->tell();
622
18.5k
    marker="";
623
92.5k
    for (int c=0; c<4; ++c) marker+=char(input->readLong(1));
624
18.5k
    long dSz=static_cast<int>(input->readLong(4));
625
18.5k
    long endPos=pos+8+dSz;
626
18.5k
    if (marker!="reco" || dSz<8 || endPos>entry.end()) {
627
994
      input->seek(pos, librevenge::RVNG_SEEK_SET);
628
994
      MWAW_DEBUG_MSG(("StyleParser::readFormats: can not read some format\n"));
629
994
      break;
630
994
    }
631
17.5k
    StyleParserInternal::Font font;
632
17.5k
    f.str("");
633
17.5k
    f << "Format-C" << form << ":";
634
17.5k
    long N1=static_cast<int>(input->readULong(4));
635
17.5k
    f << "N1=" << N1 << ",";
636
52.5k
    for (int i=0; i<2; ++i) { // always 0
637
35.0k
      val=static_cast<int>(input->readLong(2));
638
35.0k
      if (val)
639
630
        f << "f" << i << "=" << val << ",";
640
35.0k
    }
641
17.5k
    if (dSz<8+12*N1) {
642
768
      MWAW_DEBUG_MSG(("StyleParser::readFormats: N1 is bad\n"));
643
768
      f << "###N1,";
644
768
      input->seek(endPos, librevenge::RVNG_SEEK_SET);
645
768
      ascii().addPos(pos);
646
768
      ascii().addNote(f.str().c_str());
647
768
      m_state->m_fontList.push_back(font);
648
768
      continue;
649
768
    }
650
16.7k
    ascii().addPos(pos);
651
16.7k
    ascii().addNote(f.str().c_str());
652
16.7k
    std::string type("");
653
87.3k
    for (long i=0; i<N1; ++i) {
654
74.0k
      pos=input->tell();
655
74.0k
      f.str("");
656
74.0k
      f << "Format-C" << form << "-" << i << ":";
657
74.0k
      marker=type="";
658
370k
      for (int c=0; c<4; ++c) marker+=char(input->readULong(1));
659
370k
      for (int c=0; c<4; ++c) type+=char(input->readULong(1));
660
74.0k
      f << marker << "[" << type << "],";
661
74.0k
      dSz=input->readLong(4);
662
74.0k
      if (dSz<0 || pos+12+dSz>endPos) {
663
3.48k
        MWAW_DEBUG_MSG(("StyleParser::readFormats: can not read a subformat\n"));
664
3.48k
        input->seek(pos, librevenge::RVNG_SEEK_SET);
665
3.48k
        break;
666
3.48k
      }
667
70.5k
      if (type=="enum" || type=="TEXT") {
668
        // font
669
14.1k
        std::string string("");
670
121k
        for (long c=0; c<dSz; ++c) string+=char(input->readULong(1));
671
14.1k
        f << string;
672
14.1k
        if (marker=="font")
673
13.7k
          font.m_font.setId(getFontConverter()->getId(string));
674
335
        else {
675
335
          MWAW_DEBUG_MSG(("StyleParser::readFormats: unknown marker\n"));
676
335
          f << "###";
677
335
        }
678
14.1k
      }
679
56.4k
      else if (dSz==1 && type=="bool") {
680
5.86k
        val=static_cast<int>(input->readLong(1));
681
5.86k
        f << val;
682
5.86k
        if (val<0 || val>1) {
683
171
          MWAW_DEBUG_MSG(("StyleParser::readFormats: find some old bool value\n"));
684
171
          f << "###";
685
171
        }
686
5.69k
        else if (val==0)
687
9
          ;
688
5.68k
        else if (marker=="bold")
689
539
          font.m_font.setFlags(font.m_font.flags()|MWAWFont::boldBit);
690
5.14k
        else if (marker=="cond")
691
583
          font.m_font.setDeltaLetterSpacing(-1.);
692
4.56k
        else if (marker=="ital")
693
847
          font.m_font.setFlags(font.m_font.flags()|MWAWFont::italicBit);
694
3.71k
        else if (marker=="outl")
695
770
          font.m_font.setFlags(font.m_font.flags()|MWAWFont::embossBit);
696
2.94k
        else if (marker=="pexp")
697
607
          font.m_font.setDeltaLetterSpacing(1.);
698
2.33k
        else if (marker=="shad")
699
731
          font.m_font.setFlags(font.m_font.flags()|MWAWFont::shadowBit);
700
1.60k
        else if (marker=="strk")
701
453
          font.m_font.setStrikeOutStyle(MWAWFont::Line::Simple);
702
1.15k
        else if (marker=="undl")
703
762
          font.m_font.setUnderlineStyle(MWAWFont::Line::Simple);
704
391
        else {
705
391
          MWAW_DEBUG_MSG(("StyleParser::readFormats: unknown marker\n"));
706
391
          f << "###";
707
391
        }
708
5.86k
      }
709
50.5k
      else if (dSz==2 && type=="shor") {
710
15.8k
        val=static_cast<int>(input->readLong(2));
711
15.8k
        f << val;
712
15.8k
        if (marker=="fnt#") // fontId, ok to ignore
713
13.4k
          ;
714
2.34k
        else if (marker=="objb" || marker=="pptm") // CHECKME
715
982
          f << "##";
716
1.36k
        else {
717
1.36k
          MWAW_DEBUG_MSG(("StyleParser::readFormats: unknown marker\n"));
718
1.36k
          f << "###";
719
1.36k
        }
720
15.8k
      }
721
34.7k
      else if (dSz==4 && type=="long") {
722
15.8k
        val=static_cast<int>(input->readLong(4));
723
15.8k
        if (marker=="ptxe") // always 2000?
724
14.7k
          f << float(val)/65536.f;
725
1.09k
        else {
726
1.09k
          MWAW_DEBUG_MSG(("StyleParser::readFormats: unknown marker\n"));
727
1.09k
          f << "###" << val;
728
1.09k
        }
729
15.8k
      }
730
18.8k
      else if (dSz==4 && type=="fixd") {
731
13.8k
        float value=float(input->readLong(4))/65536.f;
732
13.8k
        f << value;
733
13.8k
        if (marker=="ptsz")
734
12.8k
          font.m_font.setSize(value);
735
991
        else if (marker=="xshf")
736
485
          font.m_font.set(MWAWFont::Script(value,librevenge::RVNG_POINT));
737
506
        else {
738
506
          MWAW_DEBUG_MSG(("StyleParser::readFormats: unknown marker\n"));
739
506
          f << "###";
740
506
        }
741
13.8k
      }
742
4.99k
      else if (dSz==4 && type=="QDpt") {
743
        // objs
744
27
        int dim[2];
745
54
        for (int &j : dim) j=static_cast<int>(input->readLong(2));
746
27
        font.m_picture.m_size=MWAWVec2i(dim[1],dim[0]);
747
27
        f << font.m_picture.m_size;
748
27
      }
749
4.96k
      else if (dSz==6 && type=="cRGB") {
750
1.82k
        unsigned char col[3];
751
5.46k
        for (auto &c : col) c=static_cast<unsigned char>(input->readULong(2)>>8);
752
1.82k
        MWAWColor color(col[0],col[1],col[2]);
753
1.82k
        f << color;
754
1.82k
        if (marker=="colr")
755
770
          font.m_font.setColor(color);
756
1.05k
        else if (marker=="pbcl")
757
963
          font.m_font.setBackgroundColor(color);
758
90
        else {
759
90
          MWAW_DEBUG_MSG(("StyleParser::readFormats: unknown marker\n"));
760
90
          f << "###";
761
90
        }
762
1.82k
      }
763
3.14k
      else if (type=="PICT" && dSz) {
764
480
        if (marker=="obj ") {
765
460
          font.m_picture.m_entry.setBegin(pos+12);
766
460
          font.m_picture.m_entry.setLength(dSz);
767
460
        }
768
20
        else {
769
20
          MWAW_DEBUG_MSG(("StyleParser::readFormats: unknown marker\n"));
770
20
          f << "###";
771
20
        }
772
#ifdef DEBUG_WITH_FILES
773
        ascii().skipZone(pos+12, pos+12+dSz-1);
774
        librevenge::RVNGBinaryData file;
775
        input->seek(pos+12, librevenge::RVNG_SEEK_SET);
776
        input->readDataBlock(dSz, file);
777
        static int volatile pictName = 0;
778
        libmwaw::DebugStream f2;
779
        f2 << "PICT-" << ++pictName << ".pct";
780
        libmwaw::Debug::dumpFile(file, f2.str().c_str());
781
#endif
782
480
      }
783
2.66k
      else {
784
2.66k
        MWAW_DEBUG_MSG(("StyleParser::readFormats: unknown type\n"));
785
2.66k
        f << "###type";
786
2.66k
      }
787
70.5k
      if (dSz%2) ++dSz;
788
70.5k
      input->seek(pos+12+dSz, librevenge::RVNG_SEEK_SET);
789
70.5k
      ascii().addPos(pos);
790
70.5k
      ascii().addNote(f.str().c_str());
791
70.5k
    }
792
16.7k
    m_state->m_fontList.push_back(font);
793
16.7k
    if (input->tell()==endPos) continue;
794
795
3.64k
    input->seek(endPos, librevenge::RVNG_SEEK_SET);
796
3.64k
    MWAW_DEBUG_MSG(("StyleParser::readFormats: find extra data\n"));
797
3.64k
    f.str("");
798
3.64k
    f << "Format-" << form << ":###extra";
799
3.64k
    ascii().addPos(pos);
800
3.64k
    ascii().addNote(f.str().c_str());
801
3.64k
  }
802
1.53k
  if (input->tell()!=entry.end()) {
803
1.01k
    MWAW_DEBUG_MSG(("StyleParser::readFormats: find extra data\n"));
804
1.01k
    ascii().addPos(input->tell());
805
1.01k
    ascii().addNote("Format:###extra");
806
1.01k
  }
807
1.53k
  return true;
808
1.86k
}
809
////////////////////////////////////////////////////////////
810
// rules/plc
811
////////////////////////////////////////////////////////////
812
bool StyleParser::readRules(MWAWEntry const &entry)
813
1.93k
{
814
1.93k
  MWAWInputStreamPtr input = getInput();
815
1.93k
  if (!entry.valid() || !input->checkPosition(entry.end()) || entry.length()<24) {
816
125
    MWAW_DEBUG_MSG(("StyleParser::readRules: the entry seems bad\n"));
817
125
    return false;
818
125
  }
819
820
1.81k
  entry.setParsed(true);
821
1.81k
  ascii().addPos(entry.end());
822
1.81k
  ascii().addNote("_");
823
824
1.81k
  input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
825
1.81k
  long pos=input->tell();
826
1.81k
  libmwaw::DebugStream f;
827
1.81k
  f << "Entries(Rule):";
828
1.81k
  int val;
829
10.8k
  for (int i=0; i<5; ++i) {
830
9.05k
    val=static_cast<int>(input->readLong(2));
831
9.05k
    if (val)
832
4.83k
      f << "f" << i << "=" << val << ",";
833
9.05k
  }
834
1.81k
  val=static_cast<int>(input->readLong(2));
835
1.81k
  if (val!=24) // always 18?
836
1.42k
    f << "f5=" << val << ",";
837
1.81k
  std::string marker("");
838
9.05k
  for (int i=0; i<4; ++i) marker+=char(input->readULong(1));
839
1.81k
  if (marker!="list") {
840
1.24k
    MWAW_DEBUG_MSG(("StyleParser::readRules: can not find the list marker\n"));
841
1.24k
    f << "###";
842
1.24k
    ascii().addPos(pos);
843
1.24k
    ascii().addNote(f.str().c_str());
844
1.24k
    return false;
845
1.24k
  }
846
564
  auto N=static_cast<int>(input->readLong(4));
847
564
  f << "N=" << N << ",";
848
1.69k
  for (int i=0; i<2; ++i) { // always 0
849
1.12k
    val=static_cast<int>(input->readLong(2));
850
1.12k
    if (val)
851
11
      f << "g" << i << "=" << val << ",";
852
1.12k
  }
853
564
  ascii().addPos(pos);
854
564
  ascii().addNote(f.str().c_str());
855
856
564
  m_state->m_paragraphList.clear();
857
3.57k
  for (int r=0; r<N; ++r) {
858
3.41k
    pos=input->tell();
859
3.41k
    if (!input->checkPosition(pos+8))
860
2
      break;
861
3.40k
    f.str("");
862
3.40k
    f << "Rule-P" << r << ":";
863
3.40k
    marker="";
864
17.0k
    for (int i=0; i<4; ++i) marker+=char(input->readULong(1));
865
3.40k
    long dSz=input->readLong(4);
866
3.40k
    long endPos=pos+8+dSz;
867
3.40k
    if (marker!="reco" || dSz<8 || !input->checkPosition(endPos)) {
868
397
      MWAW_DEBUG_MSG(("StyleParser::readRules: can not read a rule\n"));
869
397
      input->seek(pos, librevenge::RVNG_SEEK_SET);
870
397
      break;
871
397
    }
872
3.01k
    long N1=static_cast<int>(input->readULong(4));
873
3.01k
    f << "N1=" << N1 << ",";
874
9.03k
    for (int i=0; i<2; ++i) { // always 0
875
6.02k
      val=static_cast<int>(input->readLong(2));
876
6.02k
      if (val)
877
299
        f << "f" << i << "=" << val << ",";
878
6.02k
    }
879
3.01k
    MWAWParagraph para;
880
3.01k
    if (dSz<8+12*N1) {
881
113
      MWAW_DEBUG_MSG(("StyleParser::readRules: N1 is bad\n"));
882
113
      f << "###N1,";
883
113
      input->seek(endPos, librevenge::RVNG_SEEK_SET);
884
113
      ascii().addPos(pos);
885
113
      ascii().addNote(f.str().c_str());
886
113
      m_state->m_paragraphList.push_back(para);
887
113
      continue;
888
113
    }
889
2.89k
    ascii().addPos(pos);
890
2.89k
    ascii().addNote(f.str().c_str());
891
892
2.89k
    std::string type("");
893
7.62k
    for (long i=0; i<N1; ++i) {
894
5.03k
      pos=input->tell();
895
5.03k
      f.str("");
896
5.03k
      f << "Rule-P" << r << "-" << i << ":";
897
5.03k
      marker=type="";
898
25.1k
      for (int c=0; c<4; ++c) marker+=char(input->readULong(1));
899
25.1k
      for (int c=0; c<4; ++c) type+=char(input->readULong(1));
900
5.03k
      f << marker << "[" << type << "],";
901
5.03k
      dSz=input->readLong(4);
902
5.03k
      if (dSz<0 || pos+12+dSz>endPos) {
903
308
        MWAW_DEBUG_MSG(("StyleParser::readRules: can not read a subrule\n"));
904
308
        input->seek(pos, librevenge::RVNG_SEEK_SET);
905
308
        break;
906
308
      }
907
4.73k
      if (type=="enum") {
908
2.41k
        std::string string("");
909
12.2k
        for (long c=0; c<dSz; ++c) string+=char(input->readULong(1));
910
2.41k
        f << string;
911
2.41k
        if (marker=="pjst") {
912
2.17k
          if (string=="cent")
913
187
            para.m_justify = MWAWParagraph::JustificationCenter;
914
1.98k
          else if (string=="rght")
915
359
            para.m_justify = MWAWParagraph::JustificationRight;
916
1.62k
          else if (string=="full")
917
508
            para.m_justify = MWAWParagraph::JustificationFull;
918
1.11k
          else if (string!="left") {
919
476
            MWAW_DEBUG_MSG(("StyleParser::readRules: find unexpected align\n"));
920
476
            f << "###align,";
921
476
          }
922
2.17k
        }
923
244
        else if (marker=="BBRD") { // bottom border
924
125
          if (string=="DTDL") {
925
43
            MWAWBorder border;
926
43
            border.m_style=MWAWBorder::Dot;
927
43
            para.m_borders.resize(libmwaw::Bottom+1);
928
43
            para.m_borders[libmwaw::Bottom]=border;
929
43
          }
930
82
          else if (string=="SLDL") {
931
51
            para.m_borders.resize(libmwaw::Bottom+1);
932
51
            para.m_borders[libmwaw::Bottom]=MWAWBorder();
933
51
          }
934
31
          else if (string=="THKL") {
935
25
            MWAWBorder border;
936
25
            border.m_width=2;
937
25
            para.m_borders.resize(libmwaw::Bottom+1);
938
25
            para.m_borders[libmwaw::Bottom]=border;
939
25
          }
940
6
          else {
941
6
            MWAW_DEBUG_MSG(("StyleParser::readRules: sorry, unknown bottom border\n"));
942
6
            f << "###";
943
6
          }
944
125
        }
945
119
        else {
946
119
          MWAW_DEBUG_MSG(("StyleParser::readRules: unexpected marker\n"));
947
119
          f << "###";
948
119
        }
949
2.41k
      }
950
2.31k
      else if (type=="fixd" && dSz==4) {
951
        // riin[right], lein[left], fidt[firstIndent], spaf[after], spbe[before]
952
1.40k
        double value=double(input->readLong(4))/65536.;
953
1.40k
        f << value;
954
1.40k
        if (marker=="ledg")
955
308
          para.setInterline(1.0+value, librevenge::RVNG_PERCENT);
956
1.09k
        else if (marker=="lein")
957
324
          para.m_margins[1]=value/72.;
958
768
        else if (marker=="riin")
959
77
          para.m_margins[2]=value/72.;
960
691
        else if (marker=="fidt")
961
174
          para.m_margins[0]=value/72.;
962
517
        else if (marker=="spbe")
963
40
          para.m_spacings[1]=value/72.;
964
477
        else if (marker=="spaf")
965
85
          para.m_spacings[2]=value/72.;
966
392
        else {
967
392
          MWAW_DEBUG_MSG(("StyleParser::readRules: unexpected marker\n"));
968
392
          f << "###";
969
392
        }
970
1.40k
      }
971
915
      else {
972
915
        MWAW_DEBUG_MSG(("StyleParser::readRules: unknown type\n"));
973
915
        f << "###type";
974
915
      }
975
4.73k
      if (dSz%2) ++dSz;
976
4.73k
      input->seek(pos+12+dSz, librevenge::RVNG_SEEK_SET);
977
4.73k
      ascii().addPos(pos);
978
4.73k
      ascii().addNote(f.str().c_str());
979
4.73k
    }
980
2.89k
    m_state->m_paragraphList.push_back(para);
981
2.89k
    if (input->tell()==endPos) continue;
982
983
412
    input->seek(endPos, librevenge::RVNG_SEEK_SET);
984
412
    MWAW_DEBUG_MSG(("StyleParser::readRules: find extra data\n"));
985
412
    f.str("");
986
412
    f << "Rule-P" << r << ":###extra";
987
412
    ascii().addPos(pos);
988
412
    ascii().addNote(f.str().c_str());
989
412
  }
990
564
  if (input->tell()!=entry.end()) {
991
384
    MWAW_DEBUG_MSG(("StyleParser::readRules: find extra data\n"));
992
384
    ascii().addPos(input->tell());
993
384
    ascii().addNote("Rule:###extra");
994
384
  }
995
564
  return true;
996
1.81k
}
997
998
bool StyleParser::readPLCs(MWAWEntry const &entry, bool para)
999
8.27k
{
1000
8.27k
  MWAWInputStreamPtr input = getInput();
1001
8.27k
  if (!entry.valid() || !input->checkPosition(entry.end()) || (entry.length()%8)!=0) {
1002
133
    MWAW_DEBUG_MSG(("StyleParser::readPLCs: the entry seems bad\n"));
1003
133
    return false;
1004
133
  }
1005
8.13k
  entry.setParsed(true);
1006
8.13k
  libmwaw::DebugStream f;
1007
8.13k
  if (!para)
1008
4.29k
    f << "Entries(PLC)[char]:";
1009
3.84k
  else
1010
3.84k
    f << "Entries(PLC)[para]:";
1011
8.13k
  std::map<long, int> &map=para ? m_state->m_posParagraphIdMap : m_state->m_posFontIdMap;
1012
8.13k
  input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
1013
8.13k
  char wh=para ? 'P' : 'S';
1014
8.13k
  auto N=int(entry.length()/8);
1015
4.23M
  for (int i=0; i<N; ++i) {
1016
4.22M
    auto pos=long(input->readULong(4));
1017
4.22M
    auto id=static_cast<int>(input->readLong(4));
1018
4.22M
    f << pos;
1019
4.22M
    if (id!=-1) f << ":" << wh << id;
1020
4.22M
    f << ",";
1021
4.22M
    if (map.find(pos)!=map.end()) {
1022
3.21M
      MWAW_DEBUG_MSG(("StyleParser::readPLCs: pos %ld already exists\n", pos));
1023
3.21M
      f << "###";
1024
3.21M
    }
1025
1.00M
    else
1026
1.00M
      map[pos]=id;
1027
4.22M
  }
1028
8.13k
  ascii().addPos(entry.begin());
1029
8.13k
  ascii().addNote(f.str().c_str());
1030
8.13k
  ascii().addPos(entry.end());
1031
8.13k
  ascii().addNote("_");
1032
8.13k
  return true;
1033
8.27k
}
1034
1035
////////////////////////////////////////////////////////////
1036
// picture
1037
////////////////////////////////////////////////////////////
1038
bool StyleParser::readPictures(MWAWEntry const &entry)
1039
1.83k
{
1040
1.83k
  MWAWInputStreamPtr input = getInput();
1041
1.83k
  if (!entry.valid() || !input->checkPosition(entry.end())) {
1042
21
    MWAW_DEBUG_MSG(("StyleParser::readPictures: the entry seems bad\n"));
1043
21
    return false;
1044
21
  }
1045
1046
1.81k
  entry.setParsed(true);
1047
1.81k
  ascii().addPos(entry.begin());
1048
1.81k
  ascii().addNote("Entries(Picture):");
1049
1.81k
  ascii().addPos(entry.end());
1050
1.81k
  ascii().addNote("_");
1051
1.81k
  input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
1052
1053
1.81k
  std::string type;
1054
6.15k
  while (input->tell()<entry.end()) {
1055
5.82k
    long pos=input->tell();
1056
5.82k
    if (!input->checkPosition(pos+24))
1057
77
      break;
1058
5.75k
    libmwaw::DebugStream f;
1059
5.75k
    f << "Picture:";
1060
5.75k
    auto pictPos=long(input->readULong(4));
1061
5.75k
    if (pictPos) f << "pictPos=" << pictPos << ",";
1062
5.75k
    StyleParserInternal::Picture pict;
1063
5.75k
    type="";
1064
28.7k
    for (int i=0; i<4; ++i) type+=char(input->readULong(1));
1065
5.75k
    f << type << ",";
1066
5.75k
    int val;
1067
17.2k
    for (int i=0; i<2; ++i) { // always 0?
1068
11.5k
      val=static_cast<int>(input->readLong(2));
1069
11.5k
      if (val)
1070
4.47k
        f << "f" << i << "=" << val << ",";
1071
11.5k
    }
1072
5.75k
    long dSz=input->readLong(4);
1073
5.75k
    if (dSz<0 || !input->checkPosition(pos+24+dSz)) {
1074
1.40k
      input->seek(pos, librevenge::RVNG_SEEK_SET);
1075
1.40k
      break;
1076
1.40k
    }
1077
4.34k
    int dim[2];
1078
8.69k
    for (auto &d : dim) d=static_cast<int>(input->readULong(2));
1079
4.34k
    pict.m_size = MWAWVec2i(dim[1],dim[0]);
1080
4.34k
    f << "sz=" << pict.m_size << ",";
1081
13.0k
    for (int i=0; i<2; ++i) { // always 0
1082
8.69k
      val=static_cast<int>(input->readLong(2));
1083
8.69k
      if (val)
1084
4.46k
        f << "f" << i+2 << "=" << val << ",";
1085
8.69k
    }
1086
1087
4.34k
    ascii().addPos(pos);
1088
4.34k
    ascii().addNote(f.str().c_str());
1089
4.34k
    if (!dSz) continue;
1090
1091
2.65k
    pict.m_entry.setBegin(pos+24);
1092
2.65k
    pict.m_entry.setLength(dSz);
1093
2.65k
    if (m_state->m_posPictureMap.find(pictPos) != m_state->m_posPictureMap.end()) {
1094
123
      MWAW_DEBUG_MSG(("StyleParser::readPictures: a picture already exist at %ld\n", pictPos));
1095
123
    }
1096
2.53k
    else
1097
2.53k
      m_state->m_posPictureMap[pictPos]=pict;
1098
#ifdef DEBUG_WITH_FILES
1099
    ascii().skipZone(pos+24, pos+24+dSz-1);
1100
    librevenge::RVNGBinaryData file;
1101
    input->seek(pos+24, librevenge::RVNG_SEEK_SET);
1102
    input->readDataBlock(dSz, file);
1103
    static int volatile pictName = 0;
1104
    libmwaw::DebugStream f2;
1105
    f2 << "PICT-" << ++pictName << ".pct";
1106
    libmwaw::Debug::dumpFile(file, f2.str().c_str());
1107
#endif
1108
2.65k
    input->seek(pos+24+dSz, librevenge::RVNG_SEEK_SET);
1109
2.65k
  }
1110
1.81k
  if (input->tell()!=entry.end()) {
1111
1.66k
    MWAW_DEBUG_MSG(("StyleParser::readPictures: find extra data\n"));
1112
1.66k
    ascii().addPos(input->tell());
1113
1.66k
    ascii().addNote("Picture:###extra");
1114
1.66k
  }
1115
1.81k
  return true;
1116
1117
1.83k
}
1118
////////////////////////////////////////////////////////////
1119
// other
1120
////////////////////////////////////////////////////////////
1121
bool StyleParser::readExtraProperties(MWAWEntry const &entry)
1122
1.38k
{
1123
1.38k
  MWAWInputStreamPtr input = getInput();
1124
1.38k
  if (!entry.valid() || !input->checkPosition(entry.end()) || entry.length()<16) {
1125
76
    MWAW_DEBUG_MSG(("StyleParser::readExtraProperties: the entry seems bad\n"));
1126
76
    return false;
1127
76
  }
1128
1.31k
  entry.setParsed(true);
1129
1.31k
  input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
1130
1.31k
  ascii().addPos(entry.end());
1131
1.31k
  ascii().addNote("_");
1132
1.31k
  libmwaw::DebugStream f;
1133
1.31k
  f << "Entries(XProp):";
1134
1.31k
  std::string marker("");
1135
6.56k
  for (int c=0; c<4; ++c) marker+=char(input->readULong(1));
1136
1.31k
  if (marker!="grow" && marker!="More") {
1137
619
    MWAW_DEBUG_MSG(("StyleParser::readExtraProperties: can not find main marker\n"));
1138
619
    f << "###marker=" << marker << ",";
1139
619
    ascii().addPos(entry.begin());
1140
619
    ascii().addNote(f.str().c_str());
1141
619
    return true;
1142
619
  }
1143
693
  f << marker << ",";
1144
693
  int val;
1145
4.15k
  for (int i=0; i<5; ++i) {
1146
3.46k
    val=static_cast<int>(input->readLong(2));
1147
3.46k
    static const int expected[]= {1,0,0x4000,0,0};
1148
3.46k
    if (val!=expected[i])
1149
1.89k
      f << "f" << i << "=" << val << ",";
1150
3.46k
  }
1151
693
  auto N=static_cast<int>(input->readULong(2));
1152
693
  f << "N=" << N << ",";
1153
693
  if (16*(N+1)>entry.length()) {
1154
24
    MWAW_DEBUG_MSG(("StyleParser::readExtraProperties: can not read the number of entry\n"));
1155
24
    f << "###";
1156
24
    ascii().addPos(entry.begin());
1157
24
    ascii().addNote(f.str().c_str());
1158
24
    return true;
1159
24
  }
1160
669
  ascii().addPos(entry.begin());
1161
669
  ascii().addNote(f.str().c_str());
1162
669
  std::vector<MWAWEntry> entryList;
1163
3.27k
  for (int x=0; x<N; ++x) {
1164
2.60k
    long pos=input->tell();
1165
2.60k
    f.str("");
1166
2.60k
    f << "XProp-" << x << ":";
1167
2.60k
    marker="";
1168
13.0k
    for (int c=0; c<4; ++c) marker+=char(input->readULong(1));
1169
2.60k
    f << marker << ",";
1170
2.60k
    int id=1;
1171
2.60k
    if (marker!="Info") {
1172
2.40k
      id=static_cast<int>(input->readLong(4));
1173
2.40k
      if (id!=1) f << "id=" << id << ",";
1174
2.40k
    }
1175
195
    else {
1176
195
      std::string type;
1177
975
      for (int c=0; c<4; ++c) type+=char(input->readULong(1));
1178
195
      f << type << ",";
1179
195
    }
1180
7.80k
    for (int i=0; i<2; ++i) {
1181
5.20k
      val=static_cast<int>(input->readLong(2));
1182
5.20k
      static const int expected[]= {0x4000,0};
1183
5.20k
      if (val==expected[i])
1184
1.19k
        continue;
1185
4.01k
      f << "f" << i << "=" << val << ",";
1186
4.01k
    }
1187
2.60k
    long dPos=input->readLong(4);
1188
2.60k
    f << "pos=" << dPos << ",";
1189
2.60k
    ascii().addPos(pos);
1190
2.60k
    ascii().addNote(f.str().c_str());
1191
1192
2.60k
    if (dPos>0 && 16*(N+1)+dPos<entry.length()) {
1193
720
      MWAWEntry dEntry;
1194
720
      dEntry.setType(marker);
1195
720
      dEntry.setId(id);
1196
720
      dEntry.setBegin(entry.begin()+16*(N+1)+dPos);
1197
720
      entryList.push_back(dEntry);
1198
720
    }
1199
1.88k
    else if (dPos) {
1200
1.41k
      ascii().addPos(pos);
1201
1.41k
      ascii().addNote("###");
1202
1.41k
      MWAW_DEBUG_MSG(("StyleParser::readExtraProperties: dataPos seems bad\n"));
1203
1.41k
    }
1204
2.60k
  }
1205
1206
669
  long pos=input->tell();
1207
669
  if (pos==entry.end() && entryList.empty())
1208
100
    return true;
1209
569
  auto dSize=long(input->readULong(4));
1210
569
  f.str("");
1211
569
  f << "XProp[dataSz]:sz=" << dSize << ",";
1212
569
  if (dSize<0 || !input->checkPosition(pos+4+dSize)) {
1213
144
    MWAW_DEBUG_MSG(("StyleParser::readExtraProperties: can not read data size\n"));
1214
144
    f << "###";
1215
144
    ascii().addPos(pos);
1216
144
    ascii().addNote(f.str().c_str());
1217
144
    return true;
1218
144
  }
1219
425
  ascii().addPos(pos);
1220
425
  ascii().addNote(f.str().c_str());
1221
1222
665
  for (auto const &dEntry : entryList) {
1223
665
    f.str("");
1224
665
    f << "XProp[" << dEntry.type() << "-" << dEntry.id() << "]:";
1225
665
    input->seek(dEntry.begin(), librevenge::RVNG_SEEK_SET);
1226
665
    dSize=long(input->readULong(4));
1227
665
    long endPos=dEntry.begin()+4+dSize;
1228
665
    if (dSize<0 || !input->checkPosition(endPos)) {
1229
193
      MWAW_DEBUG_MSG(("StyleParser::readExtraProperties: can not read a data size\n"));
1230
193
      f << "###";
1231
193
      ascii().addPos(pos);
1232
193
      ascii().addNote(f.str().c_str());
1233
193
      continue;
1234
193
    }
1235
472
    if (dSize==1 && (dEntry.type()=="covr" || dEntry.type()=="cusg" ||
1236
26
                     dEntry.type()=="ehnd" || dEntry.type()=="ornt" ||
1237
26
                     dEntry.type()=="Coll" || dEntry.type()=="Dgok"))
1238
0
      f << "val=" << input->readLong(1) << ",";
1239
472
    else if (dSize==4 && (dEntry.type()=="copy" || dEntry.type()=="NTnt"|| dEntry.type()=="Ucpy"))
1240
0
      f << "val=" << input->readLong(4) << ",";
1241
472
    else if (dSize==6 && dEntry.type()=="Bkpr") {
1242
0
      for (int i=0; i<2; ++i) { // fl0=fl1=1
1243
0
        val=static_cast<int>(input->readLong(1));
1244
0
        if (val) f << "fl" << i << "=" << val << ",";
1245
0
      }
1246
0
      f << "ids=["; // af84,4f8 | b291,de8c
1247
0
      for (int i=0; i<2; ++i) f << std::hex << input->readULong(2) << std::dec << ",";
1248
0
      f << "],";
1249
0
    }
1250
472
    else if (dSize==20 && dEntry.type()=="nupd") {
1251
0
      for (int i=0; i<10; ++i) { // f5=f7=1, f8=-256, f9=1|168
1252
0
        val=static_cast<int>(input->readLong(2));
1253
0
        if (val) f << "f" << i << "=" << val << ",";
1254
0
      }
1255
0
    }
1256
472
    else if (dSize>7 && dEntry.type()=="dprf") {
1257
4
      for (int i=0; i<3; ++i) { // f0=-1, f2=635f
1258
3
        val=static_cast<int>(input->readLong(2));
1259
3
        if (val) f << "f" << i << "=" << val << ",";
1260
3
      }
1261
1
      auto dSz=static_cast<int>(input->readULong(1));
1262
1
      if (dSz+7<=dSize) {
1263
        // printer name
1264
0
        std::string text("");
1265
0
        for (int i=0; i<dSz; ++i) text+=char(input->readULong(1));
1266
0
        f << text << ",";
1267
        // then 793530010cf85c010cf86001032fe80000000000000000010cf6180000004c01032fe8ffff
1268
0
      }
1269
1
      else
1270
1
        f << "###dSz=" << dSz << ",";
1271
1
    }
1272
471
    else if (dSize>=1 && dEntry.type()=="psnt") { // find A4Small,
1273
21
      auto dSz=static_cast<int>(input->readULong(1));
1274
21
      if (dSz+1<=dSize) {
1275
21
        std::string text("");
1276
175
        for (int i=0; i<dSz; ++i) text+=char(input->readULong(1));
1277
21
        f << text << ",";
1278
21
      }
1279
0
      else
1280
0
        f << "###dSz=" << dSz << ",";
1281
21
    }
1282
450
    else if (dEntry.type()=="feat") { // find InputSlot,Upper,ManualFeed,False,PageRegion,A4Small
1283
16.3k
      while (input->tell()<endPos) {
1284
16.3k
        auto dSz=static_cast<int>(input->readULong(1));
1285
16.3k
        if (input->tell()+dSz>endPos) {
1286
112
          MWAW_DEBUG_MSG(("StyleParser::readExtraProperties: can not read a feat string\n"));
1287
112
          f << "###dSz=" << dSz << ",";
1288
112
          break;
1289
112
        }
1290
16.1k
        std::string text("");
1291
108k
        for (int i=0; i<dSz; ++i) text+=char(input->readULong(1));
1292
16.1k
        f << text << ",";
1293
16.1k
      }
1294
134
    }
1295
316
    else if (dSize>=1 && dEntry.type()=="Info") {
1296
132
      std::string text("");
1297
5.18k
      for (long i=0; i<dSize; ++i) text+=char(input->readULong(1));
1298
132
      f << text << ",";
1299
132
    }
1300
184
    else if (dEntry.type()=="ppnf") {
1301
16
      auto dSz=static_cast<int>(input->readULong(2));
1302
16
      if (dSz+2<=dSize) { // A4Small
1303
0
        std::string text("");
1304
0
        for (int i=0; i<dSz; ++i) text+=char(input->readULong(1));
1305
0
        f << text << ",";
1306
        /* then 000000006c61fd03ae816000554c7803ae8180220002480bfc44d00000000003ae8190000e4734041fccb400000000fe0200000000000103ae81d0000000c003ae81b00062666400000023 */
1307
0
      }
1308
16
      else
1309
16
        f << "###dSz=" << dSz << ",";
1310
16
    }
1311
168
    else {
1312
168
      MWAW_DEBUG_MSG(("StyleParser::readExtraProperties: find unknown type\n"));
1313
168
      f << "###unknown";
1314
168
    }
1315
472
    if (input->tell()!=endPos)
1316
232
      ascii().addDelimiter(input->tell(),'|');
1317
472
    ascii().addPos(dEntry.begin());
1318
472
    ascii().addNote(f.str().c_str());
1319
472
    ascii().addPos(endPos);
1320
472
    ascii().addNote("_");
1321
472
  }
1322
425
  return true;
1323
569
}
1324
1325
bool StyleParser::readBackgroundColor(MWAWEntry const &entry)
1326
1.56k
{
1327
1.56k
  MWAWInputStreamPtr input = getInput();
1328
1.56k
  if (!entry.valid() || !input->checkPosition(entry.end())) {
1329
65
    MWAW_DEBUG_MSG(("StyleParser::readBackgroundColor: the entry seems bad\n"));
1330
65
    return false;
1331
65
  }
1332
1.50k
  entry.setParsed(true);
1333
1.50k
  libmwaw::DebugStream f;
1334
1.50k
  f << "Entries(BgColor):";
1335
1.50k
  if (entry.length()!=6) {
1336
56
    MWAW_DEBUG_MSG(("StyleParser::readBackgroundColor: the entry size seems bad\n"));
1337
56
    f << "###";
1338
56
  }
1339
1.44k
  else {
1340
1.44k
    input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
1341
1.44k
    unsigned char col[3];
1342
4.33k
    for (auto &c : col) c=static_cast<unsigned char>(input->readULong(2)>>8);
1343
1.44k
    m_state->m_backgroundColor=MWAWColor(col[0], col[1], col[2]);
1344
1.44k
    f << m_state->m_backgroundColor << ",";
1345
1.44k
  }
1346
1347
1.50k
  ascii().addPos(entry.begin());
1348
1.50k
  ascii().addNote(f.str().c_str());
1349
1.50k
  ascii().addPos(entry.end());
1350
1.50k
  ascii().addNote("_");
1351
1.50k
  return true;
1352
1.56k
}
1353
1354
bool StyleParser::readMargins(MWAWEntry const &entry)
1355
1.65k
{
1356
1.65k
  MWAWInputStreamPtr input = getInput();
1357
1.65k
  if (!entry.valid() || !input->checkPosition(entry.end())) {
1358
15
    MWAW_DEBUG_MSG(("StyleParser::readMargins: the entry seems bad\n"));
1359
15
    return false;
1360
15
  }
1361
1.64k
  entry.setParsed(true);
1362
1.64k
  libmwaw::DebugStream f;
1363
1.64k
  f << "Entries(Margins):";
1364
1.64k
  if (entry.length()!=16) {
1365
159
    MWAW_DEBUG_MSG(("StyleParser::readMargins: the entry size seems bad\n"));
1366
159
    f << "###";
1367
159
  }
1368
1.48k
  else {
1369
1.48k
    input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
1370
1.48k
    float margins[4];
1371
1.48k
    bool ok=true;
1372
1.48k
    f << "marg=[";
1373
5.92k
    for (auto &margin : margins) {
1374
5.92k
      margin=float(input->readULong(4))/72.0f/65536.0f;
1375
5.92k
      if (margin<0) {
1376
0
        MWAW_DEBUG_MSG(("StyleParser::readMargins: some margin seems bad\n"));
1377
0
        f << "###";
1378
0
        ok = false;
1379
0
      }
1380
5.92k
      f << margin << ",";
1381
5.92k
    }
1382
1.48k
    f << "],";
1383
1.48k
    if (ok) { // checkme: order
1384
1.48k
      getPageSpan().setMarginLeft(double(margins[0]));
1385
1.48k
      getPageSpan().setMarginTop(double(margins[1]));
1386
1.48k
      getPageSpan().setMarginRight(double(margins[2]));
1387
1.48k
      getPageSpan().setMarginBottom(double(margins[3]));
1388
1.48k
    }
1389
1.48k
  }
1390
1391
1.64k
  ascii().addPos(entry.begin());
1392
1.64k
  ascii().addNote(f.str().c_str());
1393
1.64k
  ascii().addPos(entry.end());
1394
1.64k
  ascii().addNote("_");
1395
1.64k
  return true;
1396
1.65k
}
1397
1398
bool StyleParser::readPrintInfo(MWAWEntry const &entry)
1399
1.96k
{
1400
1.96k
  MWAWInputStreamPtr input = getInput();
1401
1.96k
  if (!entry.valid() || !input->checkPosition(entry.end()) || entry.length() < 0x78) {
1402
185
    MWAW_DEBUG_MSG(("StyleParser::readPrintInfo: zone size is invalid\n"));
1403
185
    return false;
1404
185
  }
1405
1406
1.77k
  input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
1407
1.77k
  libmwaw::DebugStream f;
1408
1.77k
  f << "Entries(PrintInfo):";
1409
1.77k
  libmwaw::PrinterInfo info;
1410
1.77k
  if (!info.read(input)) {
1411
1.29k
    MWAW_DEBUG_MSG(("StyleParser::readPrintInfo: can not read print info\n"));
1412
1.29k
    return false;
1413
1.29k
  }
1414
482
  entry.setParsed(true);
1415
482
  f << info;
1416
1417
482
  MWAWVec2i paperSize = info.paper().size();
1418
482
  MWAWVec2i pageSize = info.page().size();
1419
482
  if (pageSize.x() <= 0 || pageSize.y() <= 0 ||
1420
406
      paperSize.x() <= 0 || paperSize.y() <= 0) {
1421
120
    MWAW_DEBUG_MSG(("StyleParser::readPrintInfo: the paper size seems bad\n"));
1422
120
    f << "###";
1423
120
    ascii().addPos(entry.begin());
1424
120
    ascii().addNote(f.str().c_str());
1425
120
    ascii().addPos(entry.end());
1426
120
    ascii().addNote("_");
1427
120
    return true;
1428
120
  }
1429
1430
  // define margin from print info
1431
362
  MWAWVec2i lTopMargin= -1 * info.paper().pos(0);
1432
362
  MWAWVec2i rBotMargin=info.paper().size() - info.page().size();
1433
1434
362
  getPageSpan().setMarginTop(lTopMargin.y()/72.0);
1435
362
  getPageSpan().setMarginBottom(rBotMargin.y()/72.0);
1436
362
  getPageSpan().setMarginLeft(lTopMargin.x()/72.0);
1437
362
  getPageSpan().setMarginRight(rBotMargin.x()/72.0);
1438
362
  getPageSpan().setFormLength(paperSize.y()/72.);
1439
362
  getPageSpan().setFormWidth(paperSize.x()/72.);
1440
1441
362
  ascii().addPos(entry.begin());
1442
362
  ascii().addNote(f.str().c_str());
1443
362
  ascii().addPos(entry.end());
1444
362
  ascii().addNote("_");
1445
362
  return true;
1446
482
}
1447
1448
bool StyleParser::readStat(MWAWEntry const &entry)
1449
1.29k
{
1450
1.29k
  MWAWInputStreamPtr input = getInput();
1451
1.29k
  if (!entry.valid() || !input->checkPosition(entry.end())) {
1452
42
    MWAW_DEBUG_MSG(("StyleParser::readStat: the entry seems bad\n"));
1453
42
    return false;
1454
42
  }
1455
1.25k
  entry.setParsed(true);
1456
1.25k
  libmwaw::DebugStream f;
1457
1.25k
  f << "Entries(Stat):";
1458
1.25k
  if (entry.length()!=40) {
1459
41
    MWAW_DEBUG_MSG(("StyleParser::readStat: the entry size seems bad\n"));
1460
41
    f << "###";
1461
41
  }
1462
1.21k
  else {
1463
1.21k
    input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
1464
1.21k
    f << "ids=[";
1465
3.63k
    for (int i=0; i<2; ++i) f << std::hex << input->readULong(2) << std::dec << ",";
1466
1.21k
    f << "],";
1467
1.21k
    int dim[4];
1468
4.84k
    for (auto &d : dim) d=static_cast<int>(input->readLong(2));
1469
1.21k
    f << "dim?=" << MWAWBox2i(MWAWVec2i(dim[1],dim[0]), MWAWVec2i(dim[3],dim[2])) << ",";
1470
18.1k
    for (int i=0; i<14; ++i) { // f4=0|-1, f5=0|-2292, f13=0|1|3
1471
16.9k
      auto val=static_cast<int>(input->readLong(2));
1472
16.9k
      if (val)
1473
12.2k
        f << "f" << i << "=" << val << ",";
1474
16.9k
    }
1475
1.21k
  }
1476
1477
1.25k
  ascii().addPos(entry.begin());
1478
1.25k
  ascii().addNote(f.str().c_str());
1479
1.25k
  ascii().addPos(entry.end());
1480
1.25k
  ascii().addNote("_");
1481
1.25k
  return true;
1482
1.29k
}
1483
1484
bool StyleParser::readTabWidth(MWAWEntry const &entry)
1485
1.15k
{
1486
1.15k
  MWAWInputStreamPtr input = getInput();
1487
1.15k
  if (!entry.valid() || !input->checkPosition(entry.end())) {
1488
133
    MWAW_DEBUG_MSG(("StyleParser::readTabWidth: the entry seems bad\n"));
1489
133
    return false;
1490
133
  }
1491
1.02k
  entry.setParsed(true);
1492
1.02k
  libmwaw::DebugStream f;
1493
1.02k
  f << "Entries(TabWidth):";
1494
1.02k
  if (entry.length()!=4) {
1495
42
    MWAW_DEBUG_MSG(("StyleParser::readTabWidth: the entry size seems bad\n"));
1496
42
    f << "###";
1497
42
  }
1498
979
  else {
1499
979
    input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
1500
979
    f << "val=" << float(input->readLong(4))/72.f/65536.f;
1501
979
  }
1502
1503
1.02k
  ascii().addPos(entry.begin());
1504
1.02k
  ascii().addNote(f.str().c_str());
1505
1.02k
  ascii().addPos(entry.end());
1506
1.02k
  ascii().addNote("_");
1507
1.02k
  return true;
1508
1.15k
}
1509
1510
bool StyleParser::readVersion(MWAWEntry const &entry)
1511
3.00k
{
1512
3.00k
  MWAWInputStreamPtr input = getInput();
1513
3.00k
  if (!entry.valid() || !input->checkPosition(entry.end())) {
1514
37
    MWAW_DEBUG_MSG(("StyleParser::readVersion: the entry seems bad\n"));
1515
37
    return false;
1516
37
  }
1517
2.97k
  entry.setParsed(true);
1518
2.97k
  libmwaw::DebugStream f;
1519
2.97k
  f << "Entries(Version):";
1520
2.97k
  if (entry.length()!=4) {
1521
40
    MWAW_DEBUG_MSG(("StyleParser::readVersion: the entry size seems bad\n"));
1522
40
    f << "###";
1523
40
  }
1524
2.93k
  else {
1525
2.93k
    input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
1526
    // find 0x160 for version 1.6, 0x191 for version 1.9.1
1527
2.93k
    f << "vers=" << std::hex << input->readULong(2) << std::dec << ",";
1528
2.93k
    auto val=static_cast<int>(input->readULong(2));
1529
2.93k
    if (val!=0x8000)
1530
730
      f << "f0=" << std::hex << val << std::dec << ",";
1531
2.93k
  }
1532
1533
2.97k
  ascii().addPos(entry.begin());
1534
2.97k
  ascii().addNote(f.str().c_str());
1535
2.97k
  ascii().addPos(entry.end());
1536
2.97k
  ascii().addNote("_");
1537
2.97k
  return true;
1538
3.00k
}
1539
1540
////////////////////////////////////////////////////////////
1541
// send data
1542
////////////////////////////////////////////////////////////
1543
int StyleParser::computeNumPages(MWAWEntry const &entry, bool unicodeChar) const
1544
5.67k
{
1545
5.67k
  MWAWInputStreamPtr input = const_cast<StyleParser *>(this)->getInput();
1546
5.67k
  input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
1547
5.67k
  int nPages=1;
1548
1549
5.67k
  int const cSize=unicodeChar ? 2 : 1;
1550
17.0M
  while (!input->isEnd() && input->tell()<entry.end()) {
1551
17.0M
    if (input->readLong(cSize)==0xc)
1552
27.1k
      nPages++;
1553
17.0M
  }
1554
5.67k
  return nPages;
1555
5.67k
}
1556
1557
bool StyleParser::sendText(MWAWEntry const &entry, bool unicodeChar)
1558
6.24k
{
1559
6.24k
  if (!getTextListener()) {
1560
0
    MWAW_DEBUG_MSG(("StyleParser::sendText: can not find the listener\n"));
1561
0
    return false;
1562
0
  }
1563
6.24k
  if (!entry.valid()) {
1564
    // ok no text
1565
571
    return true;
1566
571
  }
1567
5.67k
  MWAWInputStreamPtr input = getInput();
1568
5.67k
  long debPos=entry.begin();
1569
5.67k
  input->seek(debPos, librevenge::RVNG_SEEK_SET);
1570
1571
5.67k
  libmwaw::DebugStream f;
1572
5.67k
  f << "Entries(TEXT):";
1573
5.67k
  getTextListener()->setFont(MWAWFont(3,12));
1574
1575
5.67k
  int actPage=1;
1576
5.67k
  auto numFonts=static_cast<int>(m_state->m_fontList.size());
1577
5.67k
  auto numParagraphs=static_cast<int>(m_state->m_paragraphList.size());
1578
5.67k
  long endChar = entry.length(), endPos = entry.end();
1579
5.67k
  int const cSize=unicodeChar ? 2 : 1;
1580
17.0M
  for (long i=0; i <= endChar; i+=cSize) {
1581
17.0M
    bool isEnd = i==endChar;
1582
17.0M
    int c=isEnd ? static_cast<int>(0) : static_cast<int>(input->readULong(cSize));
1583
17.0M
    if (isEnd || c==0xd || c==0xc || c==0x2029) {
1584
85.0k
      ascii().addPos(debPos);
1585
85.0k
      ascii().addNote(f.str().c_str());
1586
85.0k
      debPos = input->tell();
1587
85.0k
      if (isEnd) break;
1588
79.6k
      f.str("");
1589
79.6k
      f << "TEXT:";
1590
79.6k
    }
1591
17.0M
    auto plcIt=m_state->m_posParagraphIdMap.find(i);
1592
17.0M
    if (plcIt != m_state->m_posParagraphIdMap.end()) {
1593
27.5k
      if (plcIt->second>=0 && plcIt->second<numParagraphs)
1594
2.47k
        getTextListener()->setParagraph(m_state->m_paragraphList[size_t(plcIt->second)]);
1595
27.5k
      f << "[Style:P" << plcIt->second << "]";
1596
27.5k
    }
1597
17.0M
    plcIt=m_state->m_posFontIdMap.find(i);
1598
17.0M
    if (plcIt != m_state->m_posFontIdMap.end()) {
1599
51.9k
      if (plcIt->second>=0 && plcIt->second<numFonts) {
1600
20.8k
        auto const &font=m_state->m_fontList[size_t(plcIt->second)];
1601
20.8k
        getTextListener()->setFont(font.m_font);
1602
20.8k
        if (font.hasPicture())
1603
452
          sendPicture(font.m_picture);
1604
20.8k
      }
1605
51.9k
      f << "[Style:C" << plcIt->second << "]";
1606
51.9k
    }
1607
17.0M
    if (c>=0x100)
1608
9.63M
      f << "[" << std::hex << c << std::dec << "]";
1609
7.37M
    else if (c)
1610
2.33M
      f << char(c);
1611
17.0M
    if (c==0xc) {
1612
26.9k
      newPage(++actPage);
1613
26.9k
      continue;
1614
26.9k
    }
1615
16.9M
    if (c==0 && !unicodeChar && !isEnd) {
1616
      // tex-edit accept control character, ...
1617
82.5k
      auto nextC=static_cast<unsigned char>(input->readULong(1));
1618
82.5k
      if (nextC < 0x20) {
1619
72.7k
        i++;
1620
72.7k
        getTextListener()->insertChar('^');
1621
72.7k
        getTextListener()->insertChar(uint8_t('@'+nextC));
1622
72.7k
        continue;
1623
72.7k
      }
1624
9.84k
      input->seek(-1, librevenge::RVNG_SEEK_CUR);
1625
9.84k
    }
1626
16.9M
    switch (c) {
1627
198k
    case 0x1:
1628
198k
      if (m_state->m_posPictureMap.find(i)==m_state->m_posPictureMap.end() ||
1629
197k
          !m_state->m_posPictureMap.find(i)->second.valid()) {
1630
197k
        MWAW_DEBUG_MSG(("StyleParser::sendPicture: can not find picture for id=%ld\n",i));
1631
197k
        f << "[##pict]";
1632
197k
        break;
1633
197k
      }
1634
242
      sendPicture(m_state->m_posPictureMap.find(i)->second);
1635
242
      break;
1636
24.5k
    case 0x9:
1637
24.5k
      getTextListener()->insertTab();
1638
24.5k
      break;
1639
1.29k
    case 0x2028:
1640
1.29k
      getTextListener()->insertEOL(true);
1641
1.29k
      break;
1642
17.3k
    case 0xd:
1643
52.7k
    case 0x2029:
1644
52.7k
      getTextListener()->insertEOL();
1645
52.7k
      break;
1646
14.3k
    case 0x11: // command key
1647
14.3k
      getTextListener()->insertUnicode(0x2318);
1648
14.3k
      break;
1649
30.5k
    case 0x14: // apple logo: check me
1650
30.5k
      getTextListener()->insertUnicode(0xf8ff);
1651
30.5k
      break;
1652
4.77k
    case 0xfffc: // image
1653
4.77k
      break;
1654
16.5M
    default:
1655
16.5M
      if (c < 0x20) f  << "##[" << std::hex << c << std::dec << "]";
1656
16.5M
      if (unicodeChar)
1657
16.3M
        getTextListener()->insertUnicode(uint32_t(c));
1658
276k
      else
1659
276k
        i += getTextListener()->insertCharacter(static_cast<unsigned char>(c), input, endPos);
1660
16.5M
      break;
1661
16.9M
    }
1662
16.9M
  }
1663
5.67k
  return true;
1664
5.67k
}
1665
1666
// the pictures
1667
bool StyleParser::sendPicture(StyleParserInternal::Picture const &pict)
1668
694
{
1669
694
  if (!getTextListener()) {
1670
0
    MWAW_DEBUG_MSG(("StyleParser::sendPicture: can not find the listener\n"));
1671
0
    return false;
1672
0
  }
1673
1674
694
  MWAWInputStreamPtr input = getInput();
1675
694
  librevenge::RVNGBinaryData data;
1676
694
  long pos = input->tell();
1677
694
  input->seek(pict.m_entry.begin(), librevenge::RVNG_SEEK_SET);
1678
694
  input->readDataBlock(pict.m_entry.length(), data);
1679
694
  input->seek(pos,librevenge::RVNG_SEEK_SET);
1680
1681
694
  auto dataSz=int(data.size());
1682
694
  if (!dataSz)
1683
0
    return false;
1684
694
  MWAWPosition pictPos=MWAWPosition(MWAWVec2f(0,0),MWAWVec2f(pict.m_size), librevenge::RVNG_POINT);
1685
694
  pictPos.setRelativePosition(MWAWPosition::Char);
1686
694
  MWAWEmbeddedObject picture(data);
1687
694
  getTextListener()->insertPicture(pictPos, picture);
1688
694
  return true;
1689
694
}
1690
1691
////////////////////////////////////////////////////////////
1692
//
1693
// Low level
1694
//
1695
////////////////////////////////////////////////////////////
1696
1697
1698
////////////////////////////////////////////////////////////
1699
// read the header
1700
////////////////////////////////////////////////////////////
1701
bool StyleParser::checkHeader(MWAWHeader *header, bool strict)
1702
38.4k
{
1703
38.4k
  *m_state = StyleParserInternal::State();
1704
38.4k
  MWAWInputStreamPtr input = getInput();
1705
38.4k
  if (!input || !input->hasDataFork() || !input->checkPosition(40))
1706
140
    return false;
1707
38.3k
  input->seek(0, librevenge::RVNG_SEEK_SET);
1708
38.3k
  if (input->readULong(2)!=0x4348 || input->readULong(2)!=0x4e4b ||
1709
38.1k
      input->readULong(2)!=0x100 || input->readULong(2)!=0)
1710
311
    return false;
1711
38.0k
  if (strict && !readTypeEntryMap())
1712
3.23k
    return false;
1713
34.7k
  setVersion(1);
1714
34.7k
  if (header)
1715
13.4k
    header->reset(MWAWDocument::MWAW_T_STYLE, version());
1716
34.7k
  ascii().addPos(0);
1717
34.7k
  ascii().addNote("FileHeader:");
1718
34.7k
  return true;
1719
38.0k
}
1720
1721
// vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: