Coverage Report

Created: 2026-06-13 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libwps/src/lib/LotusStyleManager.cpp
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2
/* libwps
3
 * Version: MPL 2.0 / LGPLv2.1+
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 *
9
 * Major Contributor(s):
10
 * Copyright (C) 2006, 2007 Andrew Ziem
11
 * Copyright (C) 2004 Marc Maurer (uwog@uwog.net)
12
 * Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba@bluewin.ch)
13
 *
14
 * For minor contributions see the git repository.
15
 *
16
 * Alternatively, the contents of this file may be used under the terms
17
 * of the GNU Lesser General Public License Version 2.1 or later
18
 * (LGPLv2.1+), in which case the provisions of the LGPLv2.1+ are
19
 * applicable instead of those above.
20
 */
21
22
#include <stdlib.h>
23
#include <string.h>
24
25
#include <cmath>
26
#include <sstream>
27
#include <limits>
28
#include <stack>
29
30
#include <librevenge-stream/librevenge-stream.h>
31
32
#include "libwps_internal.h"
33
#include "libwps_tools_win.h"
34
35
#include "WKSContentListener.h"
36
#include "WPSCell.h"
37
#include "WPSEntry.h"
38
#include "WPSFont.h"
39
#include "WPSGraphicShape.h"
40
#include "WPSGraphicStyle.h"
41
#include "WPSStream.h"
42
43
#include "Lotus.h"
44
45
#include "LotusStyleManager.h"
46
47
namespace LotusStyleManagerInternal
48
{
49
//! small struct used to defined a font name
50
struct FontName
51
{
52
  //! constructor
53
  FontName()
54
9.05k
    : m_name()
55
9.05k
    , m_id(-2)
56
9.05k
  {
57
18.1k
    for (int &i : m_size) i=0;
58
9.05k
  }
59
  //! the font name
60
  std::string m_name;
61
  //! the font id
62
  int m_id;
63
  //! the font height, font size
64
  int m_size[2];
65
};
66
//! small struct used to defined color style
67
struct ColorStyle
68
{
69
  //! constructor
70
  ColorStyle()
71
126k
    : m_patternId(0)
72
126k
    , m_pattern()
73
126k
    , m_extra("")
74
126k
  {
75
126k
    m_colors[0]=m_colors[1]=m_colors[3]=WPSColor::white();
76
126k
    m_colors[2]=WPSColor::black();
77
126k
  }
78
  //! operator<<
79
  friend std::ostream &operator<<(std::ostream &o, ColorStyle const &color)
80
0
  {
81
0
    for (int i=0; i<4; ++i)
82
0
    {
83
0
      if ((i==2 && color.m_colors[i].isBlack()) || (i!=2 && color.m_colors[i].isWhite()))
84
0
        continue;
85
0
      static char const *wh[]= {"unkn0", "unkn1", "line", "surf" };
86
0
      o << "color[" << wh[i] << "]=" << color.m_colors[i] << ",";
87
0
    }
88
0
    if (color.m_patternId) // 0: none, 2:full
89
0
      o << "id[pattern]=" << color.m_patternId;
90
0
    if (!color.m_pattern.empty())
91
0
      o << "[" << color.m_pattern << "%],";
92
0
    o << color.m_extra;
93
0
    return o;
94
0
  }
95
  //! the color id : unknown0, unknown1, line, surface
96
  WPSColor m_colors[4];
97
  //! the pattern id
98
  int m_patternId;
99
  //! the pattern
100
  WPSGraphicStyle::Pattern m_pattern;
101
  //! extra data
102
  std::string m_extra;
103
};
104
105
//! small struct used to defined font style
106
struct FontStyle
107
{
108
  //! constructor
109
  explicit FontStyle(libwps_tools_win::Font::Type fontType)
110
91.1k
    : m_font()
111
91.1k
    , m_fontType(fontType)
112
91.1k
    , m_fontId(0)
113
91.1k
    , m_extra("")
114
91.1k
  {
115
91.1k
  }
116
  //! operator<<
117
  friend std::ostream &operator<<(std::ostream &o, FontStyle const &font)
118
0
  {
119
0
    o << font.m_font;
120
0
    if (font.m_fontId) o << "FN" << font.m_fontId << ",";
121
0
    o << font.m_extra;
122
0
    return o;
123
0
  }
124
  //! the font
125
  WPSFont m_font;
126
  //! the font type
127
  libwps_tools_win::Font::Type m_fontType;
128
  //! the font id
129
  int m_fontId;
130
  //! extra data
131
  std::string m_extra;
132
};
133
134
//! small struct used to defined format style
135
struct FormatStyle
136
{
137
  //! constructor
138
  FormatStyle()
139
3.67k
    : m_prefix("")
140
3.67k
    , m_suffix("")
141
3.67k
    , m_extra("")
142
3.67k
  {
143
3.67k
  }
144
  //! operator<<
145
  friend std::ostream &operator<<(std::ostream &o, FormatStyle const &format)
146
0
  {
147
0
    if (!format.m_prefix.empty())
148
0
      o << "prefix=" << format.m_prefix << ",";
149
0
    if (!format.m_suffix.empty())
150
0
      o << "suffix=" << format.m_suffix << ",";
151
0
    o << format.m_extra;
152
0
    return o;
153
0
  }
154
  //! the prefix
155
  std::string m_prefix;
156
  //! the suffix
157
  std::string m_suffix;
158
  //! extra data
159
  std::string m_extra;
160
};
161
162
//! small struct used to defined line style
163
struct LineStyle
164
{
165
  //! constructor
166
  LineStyle()
167
56.7k
    : m_width(1)
168
56.7k
    , m_color(WPSColor::black())
169
56.7k
    , m_dashId(0)
170
56.7k
    , m_extra("")
171
56.7k
  {
172
56.7k
  }
173
  //! operator<<
174
  friend std::ostream &operator<<(std::ostream &o, LineStyle const &line)
175
0
  {
176
0
    if (line.m_width<1 || line.m_width>1)
177
0
      o << "w=" << line.m_width << ",";
178
0
    if (!line.m_color.isBlack())
179
0
      o << "color=" << line.m_color << ",";
180
0
    if (line.m_dashId)
181
0
      o << "dashId=" << line.m_dashId << ",";
182
0
    o << line.m_extra;
183
0
    return o;
184
0
  }
185
  //! the line width
186
  float m_width;
187
  //! the line color
188
  WPSColor m_color;
189
  //! the dash id
190
  int m_dashId;
191
  //! extra data
192
  std::string m_extra;
193
};
194
195
//! small struct used to defined cell style
196
struct CellStyle
197
{
198
  //! constructor
199
  explicit CellStyle(libwps_tools_win::Font::Type fontType)
200
73.3k
    : m_borders(0)
201
73.3k
    , m_fontId(0)
202
73.3k
    , m_formatId(0)
203
73.3k
    , m_colorStyle()
204
73.3k
    , m_fontStyle(fontType)
205
73.3k
    , m_hAlign(WPSCellFormat::HALIGN_DEFAULT)
206
73.3k
    , m_vAlign(WPSCellFormat::VALIGN_DEFAULT)
207
73.3k
    , m_wrapping(WPSCellFormat::WRAP_DEFAULT)
208
73.3k
    , m_rotation(0)
209
73.3k
    , m_extra("")
210
73.3k
  {
211
366k
    for (int i=0; i<4; ++i)
212
293k
    {
213
293k
      m_bordersId[i]=0;
214
293k
      m_bordersStyle[i].m_style=WPSBorder::None;
215
293k
    }
216
146k
    for (int &i : m_colorsId) i=0;
217
73.3k
  }
218
  //! operator<<
219
  friend std::ostream &operator<<(std::ostream &o, CellStyle const &cell)
220
0
  {
221
0
    if (cell.m_fontId)
222
0
      o << "id[font]=FS" << cell.m_fontId << ",";
223
0
    for (int i=0; i<4; ++i)
224
0
    {
225
0
      if (cell.m_bordersId[i])
226
0
        o << "bord" << i << "=Li" << cell.m_bordersId[i] << ",";
227
0
    }
228
0
    for (int i=0; i<2; ++i)
229
0
    {
230
0
      if (cell.m_colorsId[i])
231
0
        o << (i==0 ? "color" : "color[shadow]") << "=Co" << cell.m_colorsId[i] << ",";
232
0
    }
233
0
    if (cell.m_rotation)
234
0
      o << "rotation=" << cell.m_rotation << ",";
235
0
    switch (cell.m_hAlign)
236
0
    {
237
0
    case WPSCellFormat::HALIGN_LEFT:
238
0
      o << "left,";
239
0
      break;
240
0
    case WPSCellFormat::HALIGN_CENTER:
241
0
      o << "centered,";
242
0
      break;
243
0
    case WPSCellFormat::HALIGN_RIGHT:
244
0
      o << "right,";
245
0
      break;
246
0
    case WPSCellFormat::HALIGN_FULL:
247
0
      o << "full,";
248
0
      break;
249
0
    case WPSCellFormat::HALIGN_DEFAULT:
250
0
    default:
251
0
      break; // default
252
0
    }
253
0
    switch (cell.m_vAlign)
254
0
    {
255
0
    case WPSCellFormat::VALIGN_TOP:
256
0
      o << "top,";
257
0
      break;
258
0
    case WPSCellFormat::VALIGN_CENTER:
259
0
      o << "yCentered,";
260
0
      break;
261
0
    case WPSCellFormat::VALIGN_BOTTOM:
262
0
      o << "bottom,";
263
0
      break;
264
0
    case WPSCellFormat::VALIGN_DEFAULT:
265
0
    default:
266
0
      break; // default
267
0
    }
268
0
    switch (cell.m_wrapping)
269
0
    {
270
0
    case WPSCellFormat::WRAP_WRAP:
271
0
      o << "wrap,";
272
0
      break;
273
0
    case WPSCellFormat::WRAP_NO_WRAP:
274
0
      o << "wrap[no],";
275
0
      break;
276
0
    case WPSCellFormat::WRAP_DEFAULT:
277
0
    default:
278
0
      break;
279
0
    }
280
0
    if (cell.m_borders)
281
0
    {
282
0
      o << "bord=";
283
0
      for (int i=0,depl=1; i<4; ++i, depl*=2)
284
0
      {
285
0
        if (cell.m_borders&depl)
286
0
        {
287
0
          static char const *wh[]= {"T","L","B","R"};
288
0
          o << wh[i];
289
0
        }
290
0
      }
291
0
      o << ",";
292
0
    }
293
0
    if (cell.m_formatId)
294
0
      o << "id[format]=Fo" << cell.m_formatId << ",";
295
0
    o << cell.m_extra;
296
0
    return o;
297
0
  }
298
  //! the borders
299
  int m_borders;
300
  //! the border line id
301
  int m_bordersId[4];
302
  //! the color id : surface, shadow ?
303
  int m_colorsId[2];
304
  //! the font id
305
  int m_fontId;
306
  //! the format id
307
  int m_formatId;
308
  // wk5
309
  //! the color style
310
  ColorStyle m_colorStyle;
311
  //! the font style
312
  FontStyle m_fontStyle;
313
  //! the horizontal align
314
  WPSCellFormat::HorizontalAlignment m_hAlign;
315
  //! the vertical align
316
  WPSCellFormat::VerticalAlignment m_vAlign;
317
  //! the wrapping
318
  WPSCellFormat::Wrapping m_wrapping;
319
  //! the rotation
320
  int m_rotation;
321
  //! the cell border
322
  WPSBorder m_bordersStyle[4];
323
  //! extra data
324
  std::string m_extra;
325
};
326
327
//! small struct used to defined cell style file entry
328
struct CellStyleEntry
329
{
330
  //! constructor
331
  explicit CellStyleEntry(std::shared_ptr<WPSStream> const &stream)
332
23.1k
    : m_stream(stream)
333
23.1k
    , m_parentId(-1)
334
23.1k
    , m_entry()
335
23.1k
  {
336
23.1k
  }
337
  //! the main strem
338
  std::shared_ptr<WPSStream> m_stream;
339
  //! the parent style id
340
  int m_parentId;
341
  //! the zone position
342
  WPSEntry m_entry;
343
};
344
345
//! small struct used to defined graphic style
346
struct GraphicStyle
347
{
348
  //! constructor
349
  GraphicStyle()
350
23.4k
    : m_lineId(0)
351
23.4k
    , m_lineStyle()
352
23.4k
    , m_patternId(0)
353
23.4k
    , m_extra("")
354
23.4k
  {
355
93.6k
    for (int &i : m_colorsId) i=-1;
356
23.4k
  }
357
  //! operator<<
358
  friend std::ostream &operator<<(std::ostream &o, GraphicStyle const &graphic)
359
0
  {
360
0
    if (graphic.m_lineId)
361
0
      o << "L" << graphic.m_lineId << ",";
362
0
    if (graphic.m_colorsId[0]>=0)
363
0
      o << "Co" << graphic.m_colorsId[0] << ",";
364
0
    if (graphic.m_colorsId[1]>=0)
365
0
      o << "shadow[color]=Co" << graphic.m_colorsId[1] << ",";
366
0
    o << graphic.m_extra;
367
0
    return o;
368
0
  }
369
  //! the line, shadow, surface, back pattern color id
370
  int m_colorsId[4];
371
  //! the border line id
372
  int m_lineId;
373
  //! the line style: 123 pc
374
  LineStyle m_lineStyle;
375
  //! the patten id: 123 pc
376
  int m_patternId;
377
  //! extra data
378
  std::string m_extra;
379
};
380
381
//! the state of LotusStyleManager
382
struct State
383
{
384
  //! constructor
385
  State()
386
83.7k
    :  m_version(-1)
387
83.7k
    , m_isUpdated(false)
388
83.7k
    , m_idCellStyleMap()
389
83.7k
    , m_idColorStyleMap()
390
83.7k
    , m_idFontStyleMap()
391
83.7k
    , m_idFormatStyleMap()
392
83.7k
    , m_idGraphicStyleMap()
393
83.7k
    , m_idLineStyleMap()
394
83.7k
    , m_idFontNameMap()
395
83.7k
    , m_idToParentStyleMap()
396
83.7k
    , m_idToCellStyleEntryMap()
397
83.7k
  {
398
83.7k
  }
399
  //! returns a color corresponding to an id between 0 and 7
400
  static bool getColor8(int id, WPSColor &color);
401
  //! returns a color corresponding to an id between 0 and 15
402
  static bool getColor16(int id, WPSColor &color);
403
  //! returns a color corresponding to an id
404
  static bool getColor256(int id, WPSColor &color);
405
  //! returns the pattern corresponding to a pattern id between 1 and 48
406
  static bool getPattern48(int id, WPSGraphicStyle::Pattern &pattern);
407
  //! returns the pattern corresponding to a pattern id between 1 and 64
408
  static bool getPattern64(int id, WPSGraphicStyle::Pattern &pattern);
409
410
  //! the file version
411
  int m_version;
412
  //! a flag to know if updateState was launched
413
  bool m_isUpdated;
414
  //! a map id to cell style
415
  std::map<int, CellStyle> m_idCellStyleMap;
416
  //! a map id to color style
417
  std::map<int, ColorStyle> m_idColorStyleMap;
418
  //! a map id to font style
419
  std::map<int, FontStyle> m_idFontStyleMap;
420
  //! a map id to format style
421
  std::map<int, FormatStyle> m_idFormatStyleMap;
422
  //! a map id to graphic style
423
  std::map<int, GraphicStyle> m_idGraphicStyleMap;
424
  //! a map id to line style
425
  std::map<int, LineStyle> m_idLineStyleMap;
426
427
  //! a map id to font name style
428
  std::map<int, FontName> m_idFontNameMap;
429
  //! a map style id to the cell style id
430
  std::map<int, int> m_idToParentStyleMap;
431
  //! a map cell style id to the cell style entry
432
  std::map<int, CellStyleEntry> m_idToCellStyleEntryMap;
433
};
434
435
bool State::getColor8(int id, WPSColor &color)
436
345k
{
437
345k
  if (id<0||id>=8)
438
0
  {
439
0
    WPS_DEBUG_MSG(("LotusStyleManagerInteranl::State::getColor8(): unknown color id: %d\n",id));
440
0
    return false;
441
0
  }
442
345k
  static uint32_t colorMap[]=
443
345k
  {
444
    // black, dark blue, green, cyan/gray, red, magenta, yellow, white?
445
345k
    0, 0xFF, 0xFF00, 0x7F7F7F, 0xFF0000, 0xFF00FF, 0xFFFF00, 0xFFFFFF
446
345k
  };
447
345k
  color=WPSColor(colorMap[id]);
448
345k
  return true;
449
345k
}
450
451
bool State::getColor16(int id, WPSColor &color)
452
94.2k
{
453
94.2k
  if (id<0||id>=16)
454
42.1k
  {
455
42.1k
    WPS_DEBUG_MSG(("LotusStyleManagerInteranl::State::getColor16(): unknown color id: %d\n",id));
456
42.1k
    return false;
457
42.1k
  }
458
52.1k
  static uint32_t colorMap[]=
459
52.1k
  {
460
52.1k
    0, 0xFFFFFF, 0xFF0000, 0x00FF00, 0x0000FF, 0xFFFF00, 0xFF00FF, 0x00FFFF,
461
52.1k
    0x7F0000, 0x007F00, 0x00007F, 0x7F7F00, 0x7F007F, 0x007F7F, 0x7F7F7F, 0x3F3F3F
462
52.1k
  };
463
52.1k
  color=WPSColor(colorMap[id]);
464
52.1k
  return true;
465
94.2k
}
466
467
bool State::getColor256(int id, WPSColor &color)
468
898k
{
469
898k
  if (id<0||id>=256)
470
9.63k
  {
471
9.63k
    WPS_DEBUG_MSG(("LotusStyleManagerInteranl::State::getColor256(): unknown color id: %d\n",id));
472
9.63k
    return false;
473
9.63k
  }
474
  // in one file, find 0xEF as current...
475
888k
  static const uint32_t colorMap[]=
476
888k
  {
477
888k
    0xffffff, 0xffcc99, 0xffffcc, 0xccff99, 0x99ff33, 0x99ff66, 0x99ff99, 0xccffcc, // 0
478
888k
    0xccffff, 0x99ccff, 0x6699ff, 0xccccff, 0xcc99ff, 0xffccff, 0xff99cc, 0xffffff,
479
888k
    0xffcccc, 0xffcc66, 0xffff99, 0xccff66, 0x99ff00, 0x66ff33, 0x66ff99, 0x99ffcc, // 10
480
888k
    0x99ffff, 0x3399ff, 0x6666ff, 0x9999ff, 0xcc66ff, 0xff99ff, 0xff66cc, 0xeeeeee,
481
888k
    0xff9999, 0xff9966, 0xffff66, 0xccff33, 0x66ff00, 0x66ff66, 0x33ff99, 0x66ffcc, // 20
482
888k
    0x66ffff, 0x0099ff, 0x3366ff, 0x9966ff, 0xcc66cc, 0xff66ff, 0xff6699, 0xdddddd,
483
888k
    0xff6666, 0xff9933, 0xffff33, 0xccff00, 0x33ff00, 0x33ff66, 0x00ff99, 0x33ffcc, // 30
484
888k
    0x33ffff, 0x0066ff, 0x0066cc, 0x9966cc, 0xcc33ff, 0xff33ff, 0xff3399, 0xcccccc,
485
888k
    0xff3333, 0xff6633, 0xffff00, 0xcccc33, 0x00ff00, 0x00ff66, 0x66cc99, 0x00ffcc, // 40
486
888k
    0x00ffff, 0x0033ff, 0x3366cc, 0x9933ff, 0xcc00ff, 0xff33cc, 0xff3366, 0xbbbbbb,
487
888k
    0xff0000, 0xff6600, 0xffcc33, 0xcccc00, 0x00ee00, 0x33ff33, 0x33cc99, 0x66cccc, // 50
488
888k
    0x66ccff, 0x0000ee, 0x3333ff, 0x9900ff, 0xcc00cc, 0xff00cc, 0xff0066, 0xaaaaaa,
489
888k
    0xcc0000, 0xff3300, 0xffcc00, 0x99cc33, 0x00dd00, 0x00ff33, 0x00cc99, 0x33cccc, // 60
490
888k
    0x33ccff, 0x0000dd, 0x3300ff, 0x6666cc, 0x9933cc, 0xcc33cc, 0xff0033, 0x999999,
491
888k
    0xbb0000, 0xee0000, 0xff9900, 0x99cc00, 0x00bb00, 0x33cc00, 0x33cc66, 0x00cccc, // 70
492
888k
    0x00ccff, 0x0000bb, 0x0000ff, 0x6633ff, 0x993399, 0xcc3399, 0xcc0033, 0x888888,
493
888k
    0xaa0000, 0xdd0000, 0xcc9933, 0x999933, 0x00aa00, 0x33cc33, 0x00cc66, 0x009999, // 80
494
888k
    0x0099cc, 0x0000aa, 0x0033cc, 0x6633cc, 0x9900cc, 0xcc0099, 0xcc0066, 0x777777,
495
888k
    0x990000, 0xcc3333, 0xcc9900, 0x999900, 0x008800, 0x00cc00, 0x339966, 0x339999, // 90
496
888k
    0x3399cc, 0x000088, 0x0000cc, 0x6600ff, 0x663399, 0x993366, 0xcc3366, 0x666666,
497
888k
    0x660000, 0xcc3300, 0xcc6633, 0x669900, 0x007700, 0x339933, 0x009966, 0x336666, // a0
498
888k
    0x336699, 0x000077, 0x3300cc, 0x3333cc, 0x663366, 0x990066, 0x990033, 0x555555,
499
888k
    0x550000, 0x993300, 0xcc6600, 0x669933, 0x005500, 0x339900, 0x336633, 0x006666, // b0
500
888k
    0x006699, 0x000055, 0x000099, 0x333399, 0x6600cc, 0x990099, 0x880000, 0x444444,
501
888k
    0x330000, 0x663300, 0x996633, 0x336600, 0x004400, 0x009900, 0x006633, 0x333333, // c0
502
888k
    0x003399, 0x000044, 0x000066, 0x330099, 0x660099, 0x660066, 0x770000, 0x333333,
503
888k
    0x220000, 0x440000, 0x996600, 0x333300, 0x002200, 0x006600, 0x003300, 0x003333, // d0
504
888k
    0x003366, 0x000022, 0x000033, 0x330066, 0x330033, 0x660033, 0x440000, 0x222222,
505
888k
    0xcc9966, 0xcc6666, 0xcccc99, 0xcccc66, 0x99cc66, 0x66cc66, 0x99cc99, 0x99ffcc, // e0
506
888k
    0x99cccc, 0x999999, 0x6699cc, 0x9999cc, 0xcc99cc, 0xcc9999, 0xcc6699, 0x111111,
507
888k
    0x996666, 0x993333, 0x999966, 0x666633, 0x66cc33, 0x009933, 0x669966, 0x66cc99, // f0
508
888k
    0x669999, 0x666666, 0x666699, 0x333366, 0x996699, 0x663333, 0x663366, 0x000000
509
888k
  };
510
888k
  color=WPSColor(colorMap[id]);
511
888k
  return true;
512
898k
}
513
514
bool State::getPattern48(int id, WPSGraphicStyle::Pattern &pat)
515
48.2k
{
516
48.2k
  if (id<=0 || id>=49)
517
4.18k
  {
518
4.18k
    WPS_DEBUG_MSG(("LotusStyleManagerInternal::State::getPattern48(): unknown pattern id: %d\n",id));
519
4.18k
    return false;
520
4.18k
  }
521
44.0k
  if (id==47 || id==48)
522
1.57k
  {
523
    // the gradient
524
1.57k
    static const uint16_t  patterns[]=
525
1.57k
    {
526
1.57k
      0x8814, 0x2241, 0x8800, 0xaa00, 0x2050, 0x8888, 0x8888, 0x502
527
1.57k
    };
528
1.57k
    pat.m_dim=Vec2i(8,8);
529
1.57k
    uint16_t const *ptr=&patterns[4*(id-47)];
530
1.57k
    pat.m_data.resize(8);
531
7.88k
    for (size_t i=0; i < 8; i+=2)
532
6.30k
    {
533
6.30k
      uint16_t val=*(ptr++);
534
6.30k
      pat.m_data[i]=static_cast<unsigned char>((val>>8) & 0xFF);
535
6.30k
      pat.m_data[i+1]=static_cast<unsigned char>(val & 0xFF);
536
6.30k
    }
537
1.57k
  }
538
44.0k
  return getPattern64(id, pat);
539
48.2k
}
540
541
bool State::getPattern64(int id, WPSGraphicStyle::Pattern &pat)
542
99.0k
{
543
99.0k
  if (id<=0 || id>=64)
544
6.25k
  {
545
6.25k
    WPS_DEBUG_MSG(("LotusStyleManagerInternal::State::getPattern64(): unknown pattern id: %d\n",id));
546
6.25k
    return false;
547
6.25k
  }
548
92.7k
  static const uint16_t  patterns[]=
549
92.7k
  {
550
92.7k
    0xffff, 0xffff, 0xffff, 0xffff, 0x0, 0x0, 0x0, 0x0, 0x50a, 0x1428, 0x50a0, 0x4182, 0xa851, 0xa245, 0x8a15, 0x2a54, // 1-4
551
92.7k
    0x2142, 0x8409, 0x1224, 0x4890, 0x102, 0x408, 0x1020, 0x4080, 0x1122, 0x4488, 0x1122, 0x4488, 0xeedd, 0xbb77, 0xeedd, 0xbb77,
552
92.7k
    0xaaaa, 0xaaaa, 0xaaaa, 0xaaaa, 0x8888, 0x8888, 0x8888, 0x8888, 0xa050, 0x2814, 0xa05, 0x8241, 0x158a, 0x45a2, 0x51a8, 0x542a, // 9-12
553
92.7k
    0x9048, 0x2412, 0x984, 0x4221, 0x8040, 0x2010, 0x804, 0x201, 0xff00, 0xff00, 0xff00, 0xff00, 0xff00, 0x0, 0xff00, 0x0,
554
92.7k
    0x44aa, 0x11aa, 0x44aa, 0x11aa, 0x182, 0x4428, 0x1028, 0x4482, 0xf874, 0x2247, 0x8f17, 0x2271, 0xaa00, 0xaa00, 0xaa00, 0xaa00, // 17-20
555
92.7k
    0xff88, 0x8888, 0xff88, 0x8888, 0xff80, 0x8080, 0x8080, 0x8080, 0xaa00, 0x8000, 0x8800, 0x8000, 0xbf00, 0xbfbf, 0xb0b0, 0xb0b0,
556
92.7k
    0xddff, 0x77ff, 0xddff, 0x77ff, 0xdd77, 0xdd77, 0xdd77, 0xdd77, 0xaa55, 0xaa55, 0xaa55, 0xaa55, 0x8822, 0x8822, 0x8822, 0x8822, // 25-28
557
92.7k
    0x8010, 0x220, 0x108, 0x4004, 0x8800, 0x2200, 0x8800, 0x2200, 0x8000, 0x800, 0x8000, 0x800, 0x40a0, 0x0, 0x40a, 0x0,
558
92.7k
    0x8040, 0x2000, 0x204, 0x800, 0x8000, 0x0, 0x0, 0x0, 0xb130, 0x31b, 0xd8c0, 0xc8d, 0xff80, 0x8080, 0xff08, 0x808, // 33-36
559
92.7k
    0x81c, 0x22c1, 0x8001, 0x204, 0x8244, 0x3944, 0x8201, 0x101, 0x55a0, 0x4040, 0x550a, 0x404, 0x384, 0x4830, 0xc02, 0x101,
560
92.7k
    0x8080, 0x413e, 0x808, 0x14e3, 0x1020, 0x54aa, 0xff02, 0x408, 0x7789, 0x8f8f, 0x7798, 0xf8f8, 0x8, 0x142a, 0x552a, 0x1408, // 41-44
561
92.7k
    0xf0f0, 0xf0f0, 0xf0f, 0xf0f, 0x9966, 0x6699, 0x9966, 0x6699, 0x4188, 0x00cc, 0x8008, 0x1422, 0x8888, 0x8805, 0x220, 0x4184,
562
92.7k
    0xff, 0xff00, 0xff, 0xff00, 0x55aa, 0x55aa, 0x55aa, 0x55aa, 0xff55, 0xff55, 0xff55, 0xff55, 0x8142, 0x2418, 0x1824, 0x4281, // 49-52
563
92.7k
    0xc0c0, 0xc0c0, 0xc0c0, 0xc0c0, 0x3399, 0xcc66, 0x3399, 0xcc66, 0x3366, 0xcc99, 0x3366, 0xcc99, 0x1188, 0x4422, 0x1188, 0x4422,
564
92.7k
    0xffcc, 0xff33, 0xffcc, 0xff33, 0xf0f0, 0x0f0f, 0xf0f0, 0x0f0f, 0xcc33, 0x3333, 0x33cc, 0xcccc, 0xf0f, 0xf0f, 0xf0f, 0xf0f,// 57-60
565
92.7k
    0xf0f0, 0xf0f0, 0xf0f0, 0xf0f0, 0, 0, 0xffff, 0xffff, 0xffff, 0xffff, 0, 0
566
92.7k
  };
567
92.7k
  pat.m_dim=Vec2i(8,8);
568
92.7k
  uint16_t const *ptr=&patterns[4*(id-1)];
569
92.7k
  pat.m_data.resize(8);
570
463k
  for (size_t i=0; i < 8; i+=2)
571
371k
  {
572
371k
    uint16_t val=*(ptr++);
573
371k
    pat.m_data[i]=static_cast<unsigned char>((val>>8) & 0xFF);
574
371k
    pat.m_data[i+1]=static_cast<unsigned char>(val & 0xFF);
575
371k
  }
576
92.7k
  return true;
577
99.0k
}
578
579
}
580
581
// constructor, destructor
582
LotusStyleManager::LotusStyleManager(LotusParser &parser)
583
41.9k
  : m_mainParser(parser)
584
41.9k
  , m_state(new LotusStyleManagerInternal::State)
585
41.9k
{
586
41.9k
}
587
588
LotusStyleManager::~LotusStyleManager()
589
41.9k
{
590
41.9k
}
591
592
void LotusStyleManager::cleanState()
593
41.8k
{
594
41.8k
  m_state.reset(new LotusStyleManagerInternal::State);
595
41.8k
}
596
597
void LotusStyleManager::updateState()
598
20.4k
{
599
20.4k
  if (m_state->m_isUpdated)
600
120
    return;
601
20.2k
  m_state->m_isUpdated=true;
602
  // try to update the font styles
603
20.2k
  for (auto &fIt : m_state->m_idFontStyleMap)
604
3.49k
  {
605
3.49k
    LotusStyleManagerInternal::FontStyle &font=fIt.second;
606
3.49k
    if (!font.m_fontId) continue;
607
1.18k
    WPSFont defFont;
608
1.18k
    if (!m_mainParser.getFont(font.m_fontId, defFont, font.m_fontType))
609
772
      continue;
610
409
    font.m_font.m_name = defFont.m_name;
611
409
  }
612
20.2k
}
613
614
int LotusStyleManager::version() const
615
100k
{
616
100k
  if (m_state->m_version<0)
617
4.56k
    m_state->m_version=m_mainParser.version();
618
100k
  return m_state->m_version;
619
100k
}
620
621
bool LotusStyleManager::getColor8(int cId, WPSColor &color) const
622
345k
{
623
345k
  return m_state->getColor8(cId, color);
624
345k
}
625
626
bool LotusStyleManager::getColor16(int cId, WPSColor &color) const
627
94.2k
{
628
94.2k
  return m_state->getColor16(cId, color);
629
94.2k
}
630
631
bool LotusStyleManager::getColor256(int cId, WPSColor &color) const
632
680k
{
633
680k
  return m_state->getColor256(cId, color);
634
680k
}
635
636
bool LotusStyleManager::getPattern64(int id, WPSGraphicStyle::Pattern &pattern) const
637
51.4k
{
638
51.4k
  return m_state->getPattern64(id, pattern);
639
51.4k
}
640
641
////////////////////////////////////////////////////////////
642
// styles
643
////////////////////////////////////////////////////////////
644
bool LotusStyleManager::readLineStyle(std::shared_ptr<WPSStream> stream, long endPos, int vers)
645
24.8k
{
646
24.8k
  if (!stream) return false;
647
24.8k
  RVNGInputStreamPtr &input = stream->m_input;
648
24.8k
  libwps::DebugFile &ascFile=stream->m_ascii;
649
24.8k
  libwps::DebugStream f;
650
651
24.8k
  long pos = input->tell();
652
24.8k
  const int expectedSize=vers==0 ? 8 : vers==1 ? 14 : 0;
653
24.8k
  if (endPos-pos!=expectedSize)   // only find in a WK3 mac file
654
363
  {
655
363
    WPS_DEBUG_MSG(("LotusStyleManager::readLineStyle: the zone size seems bad\n"));
656
363
    ascFile.addPos(pos-6);
657
363
    ascFile.addNote("Entries(LineStyle):###");
658
363
    return true;
659
363
  }
660
24.4k
  LotusStyleManagerInternal::LineStyle line;
661
24.4k
  auto id=int(libwps::readU8(input));
662
24.4k
  auto val=int(libwps::readU8(input)); // always 10?
663
24.4k
  if (val!=0x10)
664
2.47k
    f << "fl=" << std::hex << val << std::dec << ",";
665
24.4k
  val=int(libwps::readU16(input)); // 0 or small number
666
24.4k
  if (val) f << "f0=" << val << ",";
667
24.4k
  WPSColor color[2]= {WPSColor::black(), WPSColor::white()};
668
73.4k
  for (int i=0; i<2; ++i)
669
48.9k
  {
670
48.9k
    int col=vers==1 ? int(libwps::readU16(input)) : int(libwps::readU8(input));
671
48.9k
    if (col!=0xEF && !m_state->getColor256(col, color[i]))
672
610
    {
673
610
      f << "###col" << i << "=" << col << ",";
674
610
      continue;
675
610
    }
676
48.3k
    if ((i==0 && color[0].isBlack()) || (i==1 && color[1].isWhite()))
677
22.4k
      continue;
678
25.8k
    f << "col" << i << "=" << color[i] << ",";
679
25.8k
  }
680
24.4k
  WPSColor finalColor=color[0];
681
24.4k
  int patId;
682
24.4k
  if (vers==0)
683
19.0k
  {
684
19.0k
    val=int(libwps::readU16(input));
685
19.0k
    patId=(val&0x3f);
686
19.0k
    line.m_width=float((val>>6)&0xF);
687
19.0k
    line.m_dashId=(val>>11);
688
19.0k
  }
689
5.43k
  else // checkme
690
5.43k
  {
691
5.43k
    patId=int(libwps::readU16(input));
692
5.43k
    line.m_width=float(libwps::readU16(input))/256.f;
693
5.43k
    line.m_dashId=int(libwps::readU16(input));
694
5.43k
  }
695
24.4k
  if (patId!=1)
696
11.8k
  {
697
11.8k
    f << "pattern=" << patId << ",";
698
11.8k
    WPSGraphicStyle::Pattern pattern;
699
11.8k
    if (patId==0) // no pattern
700
5.28k
      line.m_width=0;
701
6.52k
    else if (patId==2)
702
150
      finalColor=color[1];
703
6.37k
    else if (m_state->getPattern48(patId, pattern))
704
6.03k
    {
705
6.03k
      pattern.m_colors[0]=color[1];
706
6.03k
      pattern.m_colors[1]=color[0];
707
6.03k
      pattern.getAverageColor(finalColor);
708
6.03k
    }
709
11.8k
  }
710
24.4k
  if (line.m_dashId) // no plain, so ...
711
2.39k
    finalColor=WPSColor::barycenter(0.5f, finalColor, 0.5f, WPSColor::white());
712
24.4k
  line.m_color=finalColor;
713
24.4k
  line.m_extra=f.str();
714
715
24.4k
  f.str("");
716
24.4k
  f << "Entries(LineStyle):L" << id << "," << line;
717
24.4k
  if (m_state->m_idLineStyleMap.find(id)!=m_state->m_idLineStyleMap.end())
718
15.5k
  {
719
15.5k
    WPS_DEBUG_MSG(("LotusStyleManager::readLineStyle: the line style %d already exists\n", id));
720
15.5k
    f << "###";
721
15.5k
  }
722
8.90k
  else
723
8.90k
    m_state->m_idLineStyleMap[id]=line;
724
24.4k
  ascFile.addPos(pos-6);
725
24.4k
  ascFile.addNote(f.str().c_str());
726
24.4k
  return true;
727
24.8k
}
728
729
bool LotusStyleManager::updateLineStyle(int lineId, WPSGraphicStyle &style) const
730
22.9k
{
731
22.9k
  if (lineId==0)
732
4.38k
    return true;
733
18.5k
  if (m_state->m_idLineStyleMap.find(lineId)==m_state->m_idLineStyleMap.end())
734
9.51k
  {
735
9.51k
    WPS_DEBUG_MSG(("LotusStyleManager::updateLineStyle: the line style %d does not exist\n", lineId));
736
9.51k
    return false;
737
9.51k
  }
738
9.00k
  auto const &line=m_state->m_idLineStyleMap.find(lineId)->second;
739
9.00k
  style.m_lineWidth=line.m_width;
740
9.00k
  style.m_lineColor=line.m_color;
741
9.00k
  return true;
742
18.5k
}
743
744
bool LotusStyleManager::readColorStyle(std::shared_ptr<WPSStream> stream, long endPos)
745
37.2k
{
746
37.2k
  if (!stream) return false;
747
37.2k
  RVNGInputStreamPtr &input = stream->m_input;
748
37.2k
  libwps::DebugFile &ascFile=stream->m_ascii;
749
37.2k
  libwps::DebugStream f;
750
751
37.2k
  long pos = input->tell();
752
37.2k
  int colorSz=1;
753
37.2k
  if (endPos-pos==7)
754
31.1k
    colorSz=1;
755
6.17k
  else if (endPos-pos==11)
756
5.96k
    colorSz=2;
757
212
  else
758
212
  {
759
212
    WPS_DEBUG_MSG(("LotusStyleManager::readColorStyle: the zone size seems bad\n"));
760
212
    ascFile.addPos(pos-6);
761
212
    ascFile.addNote("Entries(ColorStyle):###");
762
212
    return true;
763
212
  }
764
37.0k
  auto id=int(libwps::readU8(input));
765
37.0k
  auto val=int(libwps::readU8(input)); // always 20?
766
37.0k
  if (val!=0x20)
767
891
    f << "fl=" << std::hex << val << std::dec << ",";
768
37.0k
  LotusStyleManagerInternal::ColorStyle color;
769
37.0k
  for (auto &i : color.m_colors)
770
148k
  {
771
148k
    val=(colorSz==1) ? int(libwps::readU8(input)) : int(libwps::readU16(input));
772
148k
    if (val!=0xEF && !m_state->getColor256(val,i))
773
1.07k
    {
774
1.07k
      WPS_DEBUG_MSG(("LotusStyleManager::readColorStyle: can not read a color\n"));
775
1.07k
      f << "##colId=" << val << ",";
776
1.07k
    }
777
148k
  }
778
37.0k
  color.m_patternId=int(libwps::readU8(input));
779
37.0k
  if (color.m_patternId && !m_state->getPattern48(color.m_patternId, color.m_pattern))
780
1.62k
  {
781
1.62k
    WPS_DEBUG_MSG(("LotusStyleManager::readColorStyle: can not read a pattern\n"));
782
1.62k
    f << "##patId=" << color.m_patternId << ",";
783
1.62k
  }
784
785
37.0k
  color.m_extra=f.str();
786
787
37.0k
  f.str("");
788
37.0k
  f << "Entries(ColorStyle):Co" << id << "," << color;
789
37.0k
  if (m_state->m_idColorStyleMap.find(id)!=m_state->m_idColorStyleMap.end())
790
20.9k
  {
791
20.9k
    WPS_DEBUG_MSG(("LotusStyleManager::readColorStyle: the color style %d already exists\n", id));
792
20.9k
    f << "###";
793
20.9k
  }
794
16.1k
  else
795
16.1k
    m_state->m_idColorStyleMap[id]=color;
796
797
37.0k
  ascFile.addPos(pos-6);
798
37.0k
  ascFile.addNote(f.str().c_str());
799
37.0k
  return true;
800
37.2k
}
801
802
bool LotusStyleManager::updateSurfaceStyle(int colorId, WPSGraphicStyle &style) const
803
37.9k
{
804
37.9k
  if (colorId==0)
805
2.08k
    return true;
806
35.8k
  if (m_state->m_idColorStyleMap.find(colorId)==m_state->m_idColorStyleMap.end())
807
11.3k
  {
808
11.3k
    WPS_DEBUG_MSG(("LotusStyleManager::updateSurfaceStyle: the color style %d does not exist\n", colorId));
809
11.3k
    return false;
810
11.3k
  }
811
24.4k
  LotusStyleManagerInternal::ColorStyle const &color=m_state->m_idColorStyleMap.find(colorId)->second;
812
24.4k
  if (color.m_patternId==0) // empty
813
2.59k
    return true;
814
21.8k
  WPSColor finalColor=color.m_colors[2];
815
21.8k
  WPSGraphicStyle::Pattern pattern;
816
21.8k
  if (color.m_patternId==2)
817
352
    finalColor=color.m_colors[3];
818
21.5k
  else if (color.m_patternId>=47 && color.m_patternId<=48)
819
1.33k
  {
820
1.33k
    style.m_gradientType=WPSGraphicStyle::G_Linear;
821
1.33k
    style.m_gradientStopList.clear();
822
1.33k
    style.m_gradientStopList.push_back(WPSGraphicStyle::GradientStop(0.0, color.m_patternId==47 ? color.m_colors[2] : WPSColor::black()));
823
1.33k
    style.m_gradientStopList.push_back(WPSGraphicStyle::GradientStop(1.0, color.m_patternId==47 ? WPSColor::black() : color.m_colors[2]));
824
1.33k
  }
825
20.2k
  else if (color.m_patternId!=1 && m_state->getPattern48(color.m_patternId, pattern))
826
2.54k
  {
827
2.54k
    pattern.m_colors[0]=color.m_colors[3];
828
2.54k
    pattern.m_colors[1]=color.m_colors[2];
829
2.54k
    if (!pattern.getUniqueColor(finalColor))
830
2.44k
      style.setPattern(pattern);
831
2.54k
  }
832
833
21.8k
  if (!style.hasPattern() && !style.hasGradient())
834
17.9k
    style.setSurfaceColor(finalColor);
835
21.8k
  return true;
836
24.4k
}
837
838
bool LotusStyleManager::updateSurfaceStyle(int fColorId, int bColorId, int patternId, WPSGraphicStyle &style) const
839
32.3k
{
840
32.3k
  if (patternId==0)
841
9.76k
    return true;
842
22.5k
  WPSGraphicStyle::Pattern pattern;
843
22.5k
  if (!getColor256(fColorId, pattern.m_colors[0])||!getColor256(bColorId, pattern.m_colors[1]))
844
0
  {
845
0
    WPS_DEBUG_MSG(("LotusStyleManager::updateSurfaceStyle: can not find some colors\n"));
846
0
    return false;
847
0
  }
848
22.5k
  int const vers=version();
849
22.5k
  int const gradBegin=vers<4 ? 60 : 64;
850
22.5k
  if (patternId>=gradBegin && patternId<=gradBegin+3)
851
216
  {
852
216
    style.m_gradientType=WPSGraphicStyle::G_Linear;
853
216
    style.m_gradientStopList.clear();
854
216
    style.m_gradientStopList.push_back(WPSGraphicStyle::GradientStop(0.0, pattern.m_colors[1]));
855
216
    style.m_gradientStopList.push_back(WPSGraphicStyle::GradientStop(1.0, pattern.m_colors[0]));
856
216
    if (vers<4)
857
143
    {
858
143
      float const angles[]= {270, 90, 180, 0};
859
143
      style.m_gradientAngle=angles[patternId-gradBegin];
860
143
    }
861
73
    else
862
73
    {
863
73
      float const angles[]= {0, 180, 90, 270};
864
73
      style.m_gradientAngle=angles[patternId-gradBegin];
865
73
    }
866
216
    return true;
867
216
  }
868
22.3k
  if (!getPattern64(patternId, pattern))
869
2.29k
  {
870
2.29k
    WPS_DEBUG_MSG(("LotusStyleManager::updateSurfaceStyle: can not find the pattern\n"));
871
2.29k
    return false;
872
2.29k
  }
873
20.0k
  WPSColor color;
874
20.0k
  if (pattern.getUniqueColor(color))
875
5.63k
    style.setSurfaceColor(color);
876
14.4k
  else
877
14.4k
    style.m_pattern=pattern;
878
20.0k
  return true;
879
22.3k
}
880
881
bool LotusStyleManager::updateShadowStyle(int colorId, WPSGraphicStyle &style) const
882
2.37k
{
883
2.37k
  if (colorId==0)
884
0
    return true;
885
2.37k
  if (m_state->m_idColorStyleMap.find(colorId)==m_state->m_idColorStyleMap.end())
886
219
  {
887
219
    WPS_DEBUG_MSG(("LotusStyleManager::updateShadowStyle: the color style %d does not exist\n", colorId));
888
219
    return false;
889
219
  }
890
2.15k
  auto const &color=m_state->m_idColorStyleMap.find(colorId)->second;
891
2.15k
  if (color.m_patternId==0) // empty
892
58
    return true;
893
2.10k
  WPSColor finalColor=color.m_colors[2];
894
2.10k
  WPSGraphicStyle::Pattern pattern;
895
2.10k
  if (color.m_patternId==2)
896
83
    finalColor=color.m_colors[3];
897
2.01k
  else if (color.m_patternId!=1 && m_state->getPattern48(color.m_patternId, pattern))
898
1.76k
  {
899
1.76k
    pattern.m_colors[0]=color.m_colors[3];
900
1.76k
    pattern.m_colors[1]=color.m_colors[2];
901
1.76k
    pattern.getAverageColor(finalColor);
902
1.76k
  }
903
2.10k
  style.setShadowColor(finalColor);
904
2.10k
  style.m_shadowOffset=Vec2f(3,3);
905
2.10k
  return true;
906
2.15k
}
907
908
bool LotusStyleManager::readGraphicStyle(std::shared_ptr<WPSStream> stream, long endPos)
909
8.09k
{
910
8.09k
  if (!stream) return false;
911
8.09k
  RVNGInputStreamPtr &input = stream->m_input;
912
8.09k
  libwps::DebugFile &ascFile=stream->m_ascii;
913
8.09k
  libwps::DebugStream f;
914
915
8.09k
  long pos = input->tell();
916
8.09k
  if (endPos-pos!=13)   // only find in a WK3 mac file
917
254
  {
918
254
    WPS_DEBUG_MSG(("LotusStyleManager::readGraphicStyle: the zone size seems bad\n"));
919
254
    ascFile.addPos(pos-6);
920
254
    ascFile.addNote("Entries(GraphicStyle):###");
921
254
    return true;
922
254
  }
923
7.84k
  auto id=int(libwps::readU8(input));
924
7.84k
  LotusStyleManagerInternal::GraphicStyle style;
925
7.84k
  auto val=int(libwps::readU8(input)); // always 40?
926
7.84k
  if (val!=0x40)
927
3.35k
    f << "fl=" << std::hex << val << std::dec << ",";
928
39.2k
  for (int i=0; i<4; ++i)
929
31.3k
  {
930
31.3k
    val=int(libwps::readU8(input));
931
31.3k
    auto fl=int(libwps::readU8(input));
932
31.3k
    if (!val) continue;
933
20.7k
    if (i==0) f << "unknId=" << val << "[" << std::hex << fl << std::dec << ",";
934
17.8k
    else if (i==1)
935
5.35k
    {
936
5.35k
      if (fl!=0x10) f << "#fl[line]=" << std::hex << fl << std::dec << ",";
937
5.35k
      if (m_state->m_idLineStyleMap.find(val)==m_state->m_idLineStyleMap.end())
938
4.30k
      {
939
4.30k
        WPS_DEBUG_MSG(("LotusStyleManager::readGraphicStyle: the line style %d does not exists\n", val));
940
4.30k
        f << "###lineId=" << val << ",";
941
4.30k
      }
942
1.04k
      else
943
1.04k
        style.m_lineId=val;
944
5.35k
    }
945
12.4k
    else
946
12.4k
    {
947
12.4k
      if (fl!=0x20) f << "#fl[color" << i-2 << "]=" << std::hex << fl << std::dec << ",";
948
12.4k
      if (m_state->m_idColorStyleMap.find(val)==m_state->m_idColorStyleMap.end())
949
9.54k
      {
950
9.54k
        WPS_DEBUG_MSG(("LotusStyleManager::readGraphicStyle: the color style %d does not exists\n", val));
951
9.54k
        f << "###colorId[" << i-2 << "]=" << val << ",";
952
9.54k
      }
953
2.91k
      else
954
2.91k
        style.m_colorsId[i-2]=val;
955
12.4k
    }
956
20.7k
  }
957
31.3k
  for (int i=0; i<3; ++i)   //f0=f1=0|1|3|4 : a size?, f2=2|3|22
958
23.5k
  {
959
23.5k
    val=int(libwps::readU8(input));
960
23.5k
    if (val)
961
15.8k
      f << "f" << i << "=" << std::hex << val << std::dec << ",";
962
23.5k
  }
963
7.84k
  style.m_extra=f.str();
964
7.84k
  f.str("");
965
7.84k
  f << "Entries(GraphicStyle):G" << id << "," << style;
966
967
7.84k
  if (m_state->m_idGraphicStyleMap.find(id)!=m_state->m_idGraphicStyleMap.end())
968
5.32k
  {
969
5.32k
    WPS_DEBUG_MSG(("LotusStyleManager::readGraphicStyle: the graphic style %d already exists\n", id));
970
5.32k
    f << "###";
971
5.32k
  }
972
2.51k
  else
973
2.51k
    m_state->m_idGraphicStyleMap[id]=style;
974
975
7.84k
  ascFile.addPos(pos-6);
976
7.84k
  ascFile.addNote(f.str().c_str());
977
7.84k
  return true;
978
8.09k
}
979
980
bool LotusStyleManager::readGraphicStyleC9(std::shared_ptr<WPSStream> stream, long endPos)
981
7.81k
{
982
7.81k
  if (!stream) return false;
983
7.81k
  RVNGInputStreamPtr &input = stream->m_input;
984
7.81k
  libwps::DebugFile &ascFile=stream->m_ascii;
985
7.81k
  libwps::DebugStream f;
986
987
7.81k
  long pos = input->tell();
988
7.81k
  if (endPos-pos!=31)   // 123 file
989
41
  {
990
41
    WPS_DEBUG_MSG(("LotusStyleManager::readGraphicStyleC9: the zone size seems bad\n"));
991
41
    ascFile.addPos(pos-6);
992
41
    ascFile.addNote("Entries(GraphicStyle):###");
993
41
    return true;
994
41
  }
995
7.76k
  f << "Entries(GraphicStyle):";
996
7.76k
  auto id=int(libwps::readU8(input));
997
7.76k
  LotusStyleManagerInternal::GraphicStyle style;
998
7.76k
  f << "GS" << id << ",";
999
7.76k
  auto val=int(libwps::readU8(input)); // always 40?
1000
7.76k
  if (val!=0x40)
1001
240
    f << "fl=" << std::hex << val << std::dec << ",";
1002
7.76k
  val=int(libwps::readU32(input));
1003
7.76k
  if (val!=1) f << "used=" << val << ",";
1004
23.3k
  for (int i=0; i<2; ++i)   // line, shadow color?
1005
15.5k
  {
1006
15.5k
    style.m_colorsId[i]=int(libwps::readU8(input));
1007
15.5k
    val=int(libwps::readU8(input));
1008
15.5k
    WPSColor color;
1009
15.5k
    if (!getColor256(style.m_colorsId[i],color))
1010
0
      f << "##col=" << style.m_colorsId[i];
1011
15.5k
    else
1012
15.5k
    {
1013
15.5k
      if (i==0)
1014
7.76k
        style.m_lineStyle.m_color=color;
1015
15.5k
      f << color;
1016
15.5k
    }
1017
15.5k
    if (val) f << ":" << val << std::hex << std::dec;
1018
15.5k
    f << ",";
1019
15.5k
  }
1020
7.76k
  val=int(libwps::readU8(input)); // always 0
1021
7.76k
  if (val) f << "f0=" << val << ",";
1022
7.76k
  val=int(libwps::readU8(input));
1023
7.76k
  if (val)
1024
2.29k
  {
1025
2.29k
    style.m_lineStyle.m_width=float(val+1);
1026
2.29k
    f << "w=" << val << ",";
1027
2.29k
  }
1028
7.76k
  val=int(libwps::readU16(input)); // 0-32
1029
7.76k
  if (val==0x20)   // checkme, seems bad
1030
659
  {
1031
659
    f << "no[line],";
1032
659
    style.m_lineStyle.m_width=0;
1033
659
  }
1034
7.11k
  else if (val) f << "dash[id]=" << std::hex << val << std::dec << ",";
1035
23.3k
  for (int i=0; i<2; ++i)   // surface, pattern color
1036
15.5k
  {
1037
15.5k
    style.m_colorsId[3-i]=int(libwps::readU8(input));
1038
15.5k
    val=int(libwps::readU8(input));
1039
15.5k
    WPSColor color;
1040
15.5k
    if (!getColor256(style.m_colorsId[3-i],color))
1041
0
      f << "##col=" << style.m_colorsId[3-i] << ",";
1042
15.5k
    else
1043
15.5k
      f << color;
1044
15.5k
    if (val) f << std::hex << ":" << val << std::dec;
1045
15.5k
    f << ",";
1046
15.5k
  }
1047
7.76k
  style.m_patternId=int(libwps::readU8(input)); // 0 none, .. gradient 65..
1048
7.76k
  if (style.m_patternId) f << "pattern=" << style.m_patternId << ",";
1049
23.3k
  for (int i=0; i<2; ++i)
1050
15.5k
  {
1051
15.5k
    auto col=int(libwps::readU8(input));
1052
15.5k
    val=int(libwps::readU8(input));
1053
15.5k
    WPSColor color;
1054
15.5k
    if (!getColor256(col,color))
1055
0
      f << "##col=" << col;
1056
15.5k
    else
1057
15.5k
      f << color;
1058
15.5k
    if (val) f << std::hex << ":" << val;
1059
15.5k
    f << ",";
1060
15.5k
  }
1061
38.8k
  for (int i=0; i<4; ++i)   // f0=2, f2=200
1062
31.0k
  {
1063
31.0k
    val=int(libwps::readU16(input));
1064
31.0k
    if (val) f << "f" << i+1 << "=" << std::hex << val << std::dec << ",";
1065
31.0k
  }
1066
7.76k
  if (m_state->m_idGraphicStyleMap.find(id)!=m_state->m_idGraphicStyleMap.end())
1067
2.49k
  {
1068
2.49k
    WPS_DEBUG_MSG(("LotusStyleManager::readGraphicStyleC9: the graphic style %d already exists\n", id));
1069
2.49k
    f << "###";
1070
2.49k
  }
1071
5.27k
  else
1072
5.27k
    m_state->m_idGraphicStyleMap[id]=style;
1073
7.76k
  ascFile.addPos(pos-6);
1074
7.76k
  ascFile.addNote(f.str().c_str());
1075
7.76k
  return true;
1076
7.81k
}
1077
1078
bool LotusStyleManager::updateGraphicStyle(int graphicId, WPSGraphicStyle &style) const
1079
4.88k
{
1080
4.88k
  if (graphicId==0)
1081
37
    return true;
1082
4.85k
  if (m_state->m_idGraphicStyleMap.find(graphicId)==m_state->m_idGraphicStyleMap.end())
1083
1.60k
  {
1084
1.60k
    WPS_DEBUG_MSG(("LotusStyleManager::updateGraphicStyle: the graphic style %d does not exist\n", graphicId));
1085
1.60k
    return false;
1086
1.60k
  }
1087
3.24k
  auto const &graphic=m_state->m_idGraphicStyleMap.find(graphicId)->second;
1088
3.24k
  int const vers=version();
1089
3.24k
  if (vers>=4)
1090
647
  {
1091
647
    style.m_lineWidth=graphic.m_lineStyle.m_width;
1092
647
    style.m_lineColor=graphic.m_lineStyle.m_color;
1093
647
    updateSurfaceStyle(graphic.m_colorsId[2],graphic.m_colorsId[3],graphic.m_patternId, style);
1094
647
    return true;
1095
647
  }
1096
2.59k
  if (graphic.m_lineId)
1097
111
    updateLineStyle(graphic.m_lineId, style);
1098
2.59k
  if (graphic.m_colorsId[0]>0)
1099
530
    updateSurfaceStyle(graphic.m_colorsId[0], style);
1100
2.59k
  if (graphic.m_colorsId[1]>0)
1101
2.37k
    updateShadowStyle(graphic.m_colorsId[1], style);
1102
2.59k
  return true;
1103
3.24k
}
1104
1105
bool LotusStyleManager::readFontStyleA0(std::shared_ptr<WPSStream> stream, long endPos)
1106
11.7k
{
1107
11.7k
  if (!stream) return false;
1108
11.7k
  RVNGInputStreamPtr &input = stream->m_input;
1109
11.7k
  libwps::DebugFile &ascFile=stream->m_ascii;
1110
11.7k
  libwps::DebugStream f;
1111
1112
11.7k
  long pos = input->tell();
1113
11.7k
  if (endPos-pos!=12)
1114
65
  {
1115
65
    WPS_DEBUG_MSG(("LotusStyleManager::readFontStyleA0: the zone size seems bad\n"));
1116
65
    ascFile.addPos(pos-6);
1117
65
    ascFile.addNote("Entries(FontStyle):###");
1118
65
    return true;
1119
65
  }
1120
11.6k
  auto id=int(libwps::readU8(input));
1121
11.6k
  LotusStyleManagerInternal::FontStyle font(m_mainParser.getDefaultFontType());
1122
11.6k
  auto val=int(libwps::readU8(input)); // always 0?
1123
11.6k
  if (val)
1124
5.54k
    f << "fl=" << std::hex << val << std::dec << ",";
1125
35.0k
  for (int i=0; i<2; ++i)   // always 0?
1126
23.3k
  {
1127
23.3k
    val=int(libwps::readU8(input));
1128
23.3k
    if (val)
1129
8.84k
      f << "f" << i << "=" << val << ",";
1130
23.3k
  }
1131
11.6k
  val=int(libwps::readU8(input));
1132
11.6k
  if (val!=0xFF)
1133
5.13k
    f << "g0=" << std::hex << val << std::dec << ",";
1134
  // we can not read the font name here, because the font is defined after...
1135
11.6k
  font.m_fontId=int(libwps::readU8(input));
1136
11.6k
  val=int(libwps::readU16(input));
1137
11.6k
  if (val)
1138
8.92k
    font.m_font.m_size=val/32.;
1139
35.0k
  for (int i=0; i<2; ++i)
1140
23.3k
  {
1141
23.3k
    val=int(libwps::readU8(input));
1142
23.3k
    if (val==0xEF) continue;
1143
20.3k
    WPSColor color;
1144
20.3k
    if (!getColor256(val, color))
1145
0
      f << "#col" << i << "=" << std::hex << val << std::dec << ",";
1146
20.3k
    else if (i==0)
1147
10.4k
      font.m_font.m_color=color;
1148
9.90k
    else if (color!=font.m_font.m_color) //unsured
1149
9.07k
      f << "col[def]=" << color << ",";
1150
20.3k
  }
1151
11.6k
  val=int(libwps::readU8(input));
1152
11.6k
  if (val)
1153
6.69k
  {
1154
6.69k
    if (val&1) font.m_font.m_attributes |= WPS_BOLD_BIT;
1155
6.69k
    if (val&2) font.m_font.m_attributes |= WPS_ITALICS_BIT;
1156
6.69k
    if (val&4) font.m_font.m_attributes |= WPS_UNDERLINE_BIT;
1157
6.69k
    if (val&8) font.m_font.m_attributes |= WPS_OUTLINE_BIT;
1158
6.69k
    if (val&0x10) font.m_font.m_attributes |= WPS_SHADOW_BIT;
1159
6.69k
    if (val&0x20) font.m_font.m_spacing=-2;
1160
6.69k
    if (val&0x40) font.m_font.m_spacing=2;
1161
6.69k
    if (val&0x80) f << "flags[#80],";
1162
6.69k
  }
1163
11.6k
  val=int(libwps::readU8(input));
1164
11.6k
  if (val) // 0|18|20|24
1165
7.45k
    f << "h0=" << std::hex << val << std::dec << ",";
1166
11.6k
  font.m_extra=f.str();
1167
11.6k
  if (m_state->m_idFontStyleMap.find(id)!=m_state->m_idFontStyleMap.end())
1168
8.55k
  {
1169
8.55k
    WPS_DEBUG_MSG(("LotusStyleManager::readFontStyleA0: the font style %d already exists\n", id));
1170
8.55k
    f << "###";
1171
8.55k
  }
1172
3.14k
  else
1173
3.14k
    m_state->m_idFontStyleMap.insert
1174
3.14k
    (std::map<int,LotusStyleManagerInternal::FontStyle>::value_type(id,font));
1175
1176
11.6k
  f.str("");
1177
11.6k
  f << "Entries(FontStyle):FS" << id << "," << font;
1178
11.6k
  ascFile.addPos(pos-6);
1179
11.6k
  ascFile.addNote(f.str().c_str());
1180
11.6k
  return true;
1181
11.7k
}
1182
1183
bool LotusStyleManager::readFontStyleF0(std::shared_ptr<WPSStream> stream, long endPos)
1184
6.20k
{
1185
6.20k
  if (!stream) return false;
1186
6.20k
  RVNGInputStreamPtr &input = stream->m_input;
1187
6.20k
  libwps::DebugFile &ascFile=stream->m_ascii;
1188
6.20k
  libwps::DebugStream f;
1189
1190
6.20k
  long pos = input->tell();
1191
6.20k
  long sz=endPos-pos;
1192
6.20k
  if (sz<20)
1193
98
  {
1194
98
    WPS_DEBUG_MSG(("LotusStyleManager::readFontStyleF0: the zone size seems bad\n"));
1195
98
    ascFile.addPos(pos-6);
1196
98
    ascFile.addNote("Entries(FontStyle):###");
1197
98
    return true;
1198
98
  }
1199
6.10k
  auto id=int(libwps::readU8(input));
1200
6.10k
  LotusStyleManagerInternal::FontStyle font(m_mainParser.getDefaultFontType());
1201
6.10k
  if (id&8)
1202
2.66k
  {
1203
2.66k
    font.m_font.m_attributes |= WPS_BOLD_BIT;
1204
2.66k
    f << "bold,";
1205
2.66k
  }
1206
6.10k
  if (id&0x10)
1207
1.15k
  {
1208
1.15k
    font.m_font.m_attributes |= WPS_ITALICS_BIT;
1209
1.15k
    f << "italic,";
1210
1.15k
  }
1211
6.10k
  auto fSz=int(libwps::readU16(input));
1212
6.10k
  font.m_font.m_size=double(fSz)/256;
1213
6.10k
  auto val=int(libwps::readU16(input));
1214
6.10k
  if (val!=fSz)
1215
1.29k
    f << "sz2=" << double(val)/256 << ",";
1216
36.6k
  for (int i=0; i<5; ++i)   // always 0?
1217
30.5k
  {
1218
30.5k
    val=int(libwps::readU8(input));
1219
30.5k
    if (val)
1220
5.26k
      f << "f" << i << "=" << val << ",";
1221
30.5k
  }
1222
54.9k
  for (int i=0; i<8; ++i)   // fl2=background?, fl3=pattern?
1223
48.8k
  {
1224
    // fl0=0|c0, fl1=0|1, fl2=0|80, fl3=[0-5]0, fl4=0-4, fl5=0|50, fl6=0
1225
48.8k
    val=int(libwps::readU8(input));
1226
48.8k
    if (!val)
1227
35.7k
      continue;
1228
13.0k
    if (i==7)
1229
1.39k
      f << "font[id]=" << val << ",";
1230
11.6k
    else
1231
11.6k
      f << "fl" << i << "=" << std::hex << val << std::dec << ",";
1232
13.0k
  }
1233
6.10k
  val=int(libwps::readU8(input));
1234
6.10k
  WPSColor color;
1235
6.10k
  if (!getColor256(val, color)) f << "#colorId=" << val << ",";
1236
6.10k
  else
1237
6.10k
  {
1238
6.10k
    font.m_font.m_color=color;
1239
6.10k
    if (!color.isBlack()) f << "color=" << color << ",";
1240
6.10k
  }
1241
1242
6.10k
  std::string name("");
1243
37.8k
  for (long i=19; i<sz; ++i)
1244
37.3k
  {
1245
37.3k
    auto c=char(libwps::readU8(input));
1246
37.3k
    if (!c) break;
1247
31.7k
    name.push_back(c);
1248
31.7k
  }
1249
6.10k
  if (!name.empty())
1250
5.71k
  {
1251
5.71k
    font.m_font.m_name=libwps_tools_win::Font::unicodeString(name, font.m_fontType);
1252
5.71k
    auto fType=libwps_tools_win::Font::getFontType(font.m_font.m_name);
1253
5.71k
    if (fType!=libwps_tools_win::Font::UNKNOWN) font.m_fontType=fType;
1254
5.71k
    f << name << ",";
1255
5.71k
  }
1256
6.10k
  if (input->tell()!=endPos) ascFile.addDelimiter(input->tell(),'|');
1257
6.10k
  font.m_extra=f.str();
1258
1259
6.10k
  if (m_state->m_idFontStyleMap.find(id)!=m_state->m_idFontStyleMap.end())
1260
3.43k
  {
1261
3.43k
    WPS_DEBUG_MSG(("LotusStyleManager::readFontStyleA0: the font style %d already exists\n", id));
1262
3.43k
    f << "###";
1263
3.43k
  }
1264
2.66k
  else
1265
2.66k
    m_state->m_idFontStyleMap.insert
1266
2.66k
    (std::map<int,LotusStyleManagerInternal::FontStyle>::value_type(id,font));
1267
6.10k
  f.str("");
1268
6.10k
  f << "Entries(FontStyle):FS" << id << "," << font;
1269
6.10k
  ascFile.addPos(pos-6);
1270
6.10k
  ascFile.addNote(f.str().c_str());
1271
6.10k
  return true;
1272
6.20k
}
1273
1274
bool LotusStyleManager::updateFontStyle(int fontId, WPSFont &font, libwps_tools_win::Font::Type &fontType)
1275
67.1k
{
1276
67.1k
  if (fontId==0)
1277
29.8k
    return true;
1278
37.3k
  if (m_state->m_idFontStyleMap.find(fontId)==m_state->m_idFontStyleMap.end())
1279
31.0k
  {
1280
31.0k
    static bool first=true;
1281
31.0k
    if (first)
1282
5
    {
1283
5
      WPS_DEBUG_MSG(("LotusStyleManager::updateFontStyle: the font style %d does not exist\n", fontId));
1284
5
      first=false;
1285
5
    }
1286
31.0k
    return false;
1287
31.0k
  }
1288
6.29k
  auto const &fontStyle=m_state->m_idFontStyleMap.find(fontId)->second;
1289
6.29k
  font=fontStyle.m_font;
1290
6.29k
  fontType=fontStyle.m_fontType;
1291
6.29k
  return true;
1292
37.3k
}
1293
1294
bool LotusStyleManager::readFormatStyle(std::shared_ptr<WPSStream> stream, long endPos)
1295
2.48k
{
1296
2.48k
  if (!stream) return false;
1297
2.48k
  RVNGInputStreamPtr &input = stream->m_input;
1298
2.48k
  libwps::DebugFile &ascFile=stream->m_ascii;
1299
2.48k
  libwps::DebugStream f;
1300
1301
2.48k
  long pos = input->tell();
1302
2.48k
  if (endPos-pos<23)
1303
37
  {
1304
37
    WPS_DEBUG_MSG(("LotusStyleManager::readFormatStyle: the zone size seems bad\n"));
1305
37
    ascFile.addPos(pos-6);
1306
37
    ascFile.addNote("Entries(FormatStyle):###");
1307
37
    return true;
1308
37
  }
1309
2.45k
  auto id=int(libwps::readU8(input));
1310
2.45k
  LotusStyleManagerInternal::FormatStyle format;
1311
2.45k
  auto val=int(libwps::readU8(input)); // always 30?
1312
2.45k
  if (val!=0x30)
1313
1.63k
    f << "fl=" << std::hex << val << std::dec << ",";
1314
1315
26.9k
  for (int i=0; i<10; ++i) // always f1=100, other 0?
1316
24.5k
  {
1317
24.5k
    val=int(libwps::readU16(input));
1318
24.5k
    if (val) f << "f" << i << "=" << val << ",";
1319
24.5k
  }
1320
2.45k
  bool ok=true;
1321
5.25k
  for (int i=0; i<2; ++i)
1322
3.97k
  {
1323
3.97k
    val=int(libwps::readU8(input));
1324
3.97k
    if (val==0xf) continue;
1325
2.28k
    if (val!=0x3c)
1326
1.08k
    {
1327
1.08k
      WPS_DEBUG_MSG(("LotusStyleManager::readFormatStyle: find unknown type\n"));
1328
1.08k
      f << "###type=" << std::hex << val << std::dec << ",";
1329
1.08k
      ok=false;
1330
1.08k
      break;
1331
1.08k
    }
1332
1.19k
    auto dSz=int(libwps::readU8(input));
1333
1.19k
    if (input->tell()+dSz+1>endPos)
1334
79
    {
1335
79
      WPS_DEBUG_MSG(("LotusStyleManager::readFormatStyle: bad string size\n"));
1336
79
      f << "###size=" << std::hex << dSz << std::dec << ",";
1337
79
      ok=false;
1338
79
      break;
1339
79
    }
1340
1.11k
    std::string name("");
1341
12.2k
    for (int j=0; j<dSz; ++j)
1342
11.1k
      name += char(libwps::readU8(input));
1343
1.11k
    if (i==0)
1344
86
      format.m_prefix=name;
1345
1.03k
    else
1346
1.03k
      format.m_suffix=name;
1347
1.11k
  }
1348
2.45k
  if (ok && input->tell()+1<=endPos)
1349
1.28k
  {
1350
1.28k
    val=int(libwps::readU8(input));
1351
1.28k
    if (val!=0xc)
1352
368
      f << "g0=" << val << ",";
1353
1.28k
  }
1354
2.45k
  format.m_extra=f.str();
1355
1356
2.45k
  if (m_state->m_idFormatStyleMap.find(id)!=m_state->m_idFormatStyleMap.end())
1357
1.23k
  {
1358
1.23k
    WPS_DEBUG_MSG(("LotusStyleManager::readFormatStyle: the format style %d already exists\n", id));
1359
1.23k
    f << "###";
1360
1.23k
  }
1361
1.22k
  else
1362
1.22k
    m_state->m_idFormatStyleMap[id]=format;
1363
1364
2.45k
  f.str("");
1365
2.45k
  f << "Entries(FormatStyle):Fo" << id << "," << format;
1366
2.45k
  ascFile.addPos(pos-6);
1367
2.45k
  ascFile.addNote(f.str().c_str());
1368
2.45k
  return true;
1369
2.48k
}
1370
1371
bool LotusStyleManager::readCellStyleD2Data(LotusStyleManagerInternal::CellStyleEntry const &entry, std::set<int> &seen)
1372
19.3k
{
1373
19.3k
  if (!entry.m_stream || !entry.m_entry.valid() || entry.m_entry.length()!=33)
1374
0
  {
1375
0
    WPS_DEBUG_MSG(("LotusStyleManager::readCellStyleD2Data: can not find the stream\n"));
1376
0
    return false;
1377
0
  }
1378
19.3k
  LotusStyleManagerInternal::CellStyle cell(m_mainParser.getDefaultFontType());
1379
  // first retrieve the cell parent, if it exists
1380
19.3k
  bool hasParent=false;
1381
19.3k
  if (entry.m_parentId>=0)
1382
593
  {
1383
593
    int pId=-1;
1384
593
    if (m_state->m_idToParentStyleMap.find(entry.m_parentId)!=m_state->m_idToParentStyleMap.end())
1385
268
      pId=m_state->m_idToParentStyleMap.find(entry.m_parentId)->second;
1386
325
    else
1387
325
    {
1388
325
      WPS_DEBUG_MSG(("LotusStyleManager::readCellStyleD2Data: can not find main style %d\n", entry.m_parentId));
1389
325
    }
1390
593
    if (pId>=0 && m_state->m_idCellStyleMap.find(pId)==m_state->m_idCellStyleMap.end())
1391
173
    {
1392
173
      if (seen.find(pId)!=seen.end())
1393
22
      {
1394
22
        WPS_DEBUG_MSG(("LotusStyleManager::readCellStyleD2Data: oops find a loop\n"));
1395
22
      }
1396
151
      else if (m_state->m_idToCellStyleEntryMap.find(pId)!=m_state->m_idToCellStyleEntryMap.end())
1397
53
      {
1398
53
        seen.insert(pId);
1399
53
        readCellStyleD2Data(m_state->m_idToCellStyleEntryMap.find(pId)->second, seen);
1400
53
      }
1401
98
      else
1402
98
      {
1403
98
        WPS_DEBUG_MSG(("LotusStyleManager::readCellStyleD2Data: can not find the style %d\n", pId));
1404
98
      }
1405
173
    }
1406
593
    if (pId>=0 && m_state->m_idCellStyleMap.find(pId)!=m_state->m_idCellStyleMap.end())
1407
148
    {
1408
148
      cell=m_state->m_idCellStyleMap.find(pId)->second;
1409
148
      hasParent=true;
1410
148
    }
1411
593
  }
1412
1413
19.3k
  RVNGInputStreamPtr &input = entry.m_stream->m_input;
1414
19.3k
  libwps::DebugFile &ascFile = entry.m_stream->m_ascii;
1415
19.3k
  libwps::DebugStream f;
1416
1417
19.3k
  input->seek(entry.m_entry.begin(), librevenge::RVNG_SEEK_SET);
1418
19.3k
  auto id=int(libwps::readU8(input));
1419
19.3k
  auto val=int(libwps::readU8(input)); // always 50?
1420
19.3k
  if (val!=0x50)
1421
3.49k
    f << "fl=" << std::hex << val << std::dec << ",";
1422
19.3k
  auto &font=cell.m_fontStyle;
1423
19.3k
  val=int(libwps::readU32(input));
1424
19.3k
  if (val!=1) f << "num[used]=" << val << ",";
1425
19.3k
  val=int(libwps::readU8(input));
1426
19.3k
  if (val!=255) f << "f0=" << val << ";";
1427
19.3k
  val=int(libwps::readU8(input));
1428
19.3k
  if (val!=255)
1429
8.11k
  {
1430
8.11k
    font.m_fontId=val;
1431
8.11k
    WPSFont defFont;
1432
8.11k
    if (m_mainParser.getFont(font.m_fontId, defFont, font.m_fontType))
1433
1.75k
      font.m_font.m_name = defFont.m_name;
1434
8.11k
  }
1435
19.3k
  val=int(libwps::readU16(input)); // checkme what is this unit? 1de:18, 173: 14, 140: 12?, 778:72
1436
19.3k
  if (val!=0xFFFF)
1437
11.1k
    font.m_font.m_size=double(int(double(val)*3./80.+0.5));
1438
8.24k
  else if (!hasParent)
1439
8.12k
    font.m_font.m_size=12;
1440
19.3k
  val=int(libwps::readU16(input));
1441
19.3k
  if (val!=0xFFFF)
1442
10.4k
  {
1443
10.4k
    WPSColor color;
1444
10.4k
    if (!m_state->getColor256(val,font.m_font.m_color))
1445
2.56k
    {
1446
2.56k
      WPS_DEBUG_MSG(("LotusStyleManager::readCellStyleD2Data sorry, can not read the font color\n"));
1447
2.56k
      f << "###col=" << std::hex << val << std::dec << ",";
1448
2.56k
    }
1449
10.4k
  }
1450
58.1k
  for (int i=0; i<2; ++i)
1451
38.7k
  {
1452
38.7k
    val=int(libwps::readU8(input));
1453
38.7k
    if (val!=255) f << "f" << i+1 << "=" << val << ",";
1454
38.7k
  }
1455
19.3k
  val=int(libwps::readU8(input));
1456
19.3k
  if (val!=255)
1457
15.5k
  {
1458
15.5k
    font.m_font.m_attributes=0;
1459
15.5k
    if (val&1) font.m_font.m_attributes |= WPS_BOLD_BIT;
1460
15.5k
    if (val&2) font.m_font.m_attributes |= WPS_ITALICS_BIT;
1461
15.5k
    if (val&4) font.m_font.m_attributes |= WPS_UNDERLINE_BIT;
1462
15.5k
    if (val&0x40) font.m_font.m_attributes |= WPS_STRIKEOUT_BIT;
1463
15.5k
    val &= 0xB8;
1464
15.5k
    if (val) f << "font[fl]=" << std::hex << val << std::dec << ",";
1465
15.5k
  }
1466
19.3k
  val=int(libwps::readU8(input));
1467
19.3k
  if (val!=255)
1468
17.3k
  {
1469
17.3k
    switch (val&3)
1470
17.3k
    {
1471
11.8k
    case 0:
1472
11.8k
      break;
1473
2.83k
    case 1:
1474
2.83k
      font.m_font.m_attributes |= WPS_DOUBLE_UNDERLINE_BIT;
1475
2.83k
      break;
1476
666
    case 2:
1477
666
      font.m_font.m_attributes |= WPS_UNDERLINE_BIT;
1478
666
      f << "underline[w=2],";
1479
666
      break;
1480
2.00k
    default:
1481
2.00k
      WPS_DEBUG_MSG(("LotusStyleManager::readCellStyleD2Data sorry, find underline=3\n"));
1482
2.00k
      f << "##underline=3,";
1483
2.00k
      break;
1484
17.3k
    }
1485
17.3k
    val&=0xFC;
1486
17.3k
    if (val!=0x80) f << "f3=" << std::hex << val << std::dec << ",";
1487
17.3k
  }
1488
19.3k
  bool angleTypeNormal=true;
1489
116k
  for (int i=0; i<5; ++i)
1490
96.9k
  {
1491
96.9k
    val=i==4 ? int(libwps::readU16(input)) : int(libwps::readU8(input));
1492
96.9k
    if (val==0xFF) continue; // default
1493
76.7k
    switch (i)
1494
76.7k
    {
1495
12.6k
    case 0: // look like the inverse of font flags
1496
12.6k
      f << "font[fl2]=" << std::hex << ((~val)&0xFF) << std::dec << ",";
1497
12.6k
      break;
1498
17.9k
    case 2:
1499
17.9k
      switch (val&7)
1500
17.9k
      {
1501
5.45k
      case 0: // default
1502
5.45k
        break;
1503
1.50k
      case 1:
1504
1.50k
        cell.m_hAlign=WPSCellFormat::HALIGN_LEFT;
1505
1.50k
        break;
1506
491
      case 2:
1507
491
        cell.m_hAlign=WPSCellFormat::HALIGN_RIGHT;
1508
491
        break;
1509
3.74k
      case 3:
1510
3.74k
        cell.m_hAlign=WPSCellFormat::HALIGN_CENTER;
1511
3.74k
        break;
1512
3.45k
      case 4: // text:left, number:right
1513
3.45k
        f << "hAlign=def,";
1514
3.45k
        break;
1515
1.88k
      case 6:
1516
1.88k
        cell.m_hAlign=WPSCellFormat::HALIGN_FULL;
1517
1.88k
        break;
1518
1.44k
      default:
1519
1.44k
        f << "##hAlign=" << (val&7) << ",";
1520
17.9k
      }
1521
17.9k
      switch ((val>>4)&7)
1522
17.9k
      {
1523
9.18k
      case 0: // default
1524
9.18k
        break;
1525
2.87k
      case 1: // find it in basic style
1526
2.87k
        f << "#angle1,";
1527
2.87k
        break;
1528
570
      case 3:
1529
570
        cell.m_rotation=90;
1530
570
        break;
1531
328
      case 4:
1532
328
        cell.m_rotation=-90;
1533
328
        f << "angle[2spacings],";
1534
328
        break;
1535
2.56k
      case 5:
1536
2.56k
        cell.m_rotation=-90;
1537
2.56k
        break;
1538
1.31k
      case 6:
1539
1.31k
        angleTypeNormal=false;
1540
1.31k
        f << "angle[free],";
1541
1.31k
        break;
1542
1.13k
      default:
1543
1.13k
        f << "##angle=" << ((val>>4)&7) << ",";
1544
1.13k
        break;
1545
17.9k
      }
1546
17.9k
      val&=0x88;
1547
17.9k
      if (val) f << "#hAlign=" << std::hex << val << std::dec << ",";
1548
17.9k
      break;
1549
19.0k
    case 3:
1550
19.0k
      switch (val&3)
1551
19.0k
      {
1552
10.5k
      case 0: // default
1553
10.5k
      default:
1554
10.5k
        break;
1555
10.5k
      case 1:
1556
4.31k
        cell.m_vAlign=WPSCellFormat::VALIGN_TOP;
1557
4.31k
        break;
1558
1.15k
      case 2:
1559
1.15k
        cell.m_vAlign=WPSCellFormat::VALIGN_CENTER;
1560
1.15k
        break;
1561
3.02k
      case 3:
1562
3.02k
        cell.m_vAlign=WPSCellFormat::VALIGN_BOTTOM;
1563
3.02k
        break;
1564
19.0k
      }
1565
19.0k
      if (!(val&0x80))
1566
7.97k
      {
1567
7.97k
        f << "wrap[text],";
1568
7.97k
        cell.m_wrapping=WPSCellFormat::WRAP_WRAP;
1569
7.97k
      }
1570
19.0k
      val&=0x7C;
1571
19.0k
      if (val) f << "#vAlign=" << std::hex << val << std::dec << ",";
1572
19.0k
      break;
1573
18.0k
    case 4:
1574
18.0k
      if (!angleTypeNormal)
1575
1.31k
        cell.m_rotation=(val!=3600) ? val : 45;
1576
16.7k
      else if (val!=3600)
1577
7.77k
        f << "angle=" << val << ",";
1578
18.0k
      break;
1579
9.04k
    default:
1580
9.04k
    {
1581
9.04k
      int const expected[]= {0xFF, 0xFF, 0, 0xc0, 0};
1582
9.04k
      if (val!=expected[i]) f << "f" << i+4 << "=" << val << ",";
1583
9.04k
    }
1584
76.7k
    }
1585
76.7k
  }
1586
58.1k
  for (int i=0; i<2; ++i)
1587
38.7k
  {
1588
38.7k
    val=int(libwps::readU16(input));
1589
38.7k
    if (val==0xFFFF)
1590
20.0k
      continue;
1591
18.7k
    WPSColor color;
1592
18.7k
    std::string wh(i==0 ? "pattern" : "back");
1593
18.7k
    if (m_state->getColor256(val,color))
1594
13.3k
    {
1595
13.3k
      cell.m_colorStyle.m_colors[2+i]=color;
1596
13.3k
      if (!color.isWhite())
1597
10.1k
        f << "color[" << wh << "]=" << color << ",";
1598
13.3k
    }
1599
5.38k
    else
1600
5.38k
    {
1601
5.38k
      WPS_DEBUG_MSG(("LotusStyleManager::readCellStyleD2Data: sorry, can not read the back color\n"));
1602
5.38k
      f << "###col[" << wh << "]=" << std::hex << val << std::dec << ",";
1603
5.38k
    }
1604
18.7k
  }
1605
19.3k
  val=int(libwps::readU8(input));
1606
19.3k
  if (val!=0xFF)
1607
7.61k
    cell.m_colorStyle.m_patternId=val;
1608
11.7k
  else if (!hasParent)
1609
11.6k
    cell.m_colorStyle.m_patternId=2;
1610
19.3k
  if (val!=0xFF)
1611
7.61k
    f << "pattern=" << val << ",";
1612
19.3k
  val=int(libwps::readU16(input));
1613
19.3k
  if ((val>>8)==0x60)
1614
82
    f << "ST" << (val&0xFF) << ",";
1615
19.3k
  else if (val)
1616
511
  {
1617
511
    WPS_DEBUG_MSG(("LotusStyleManager::readCellStyleD2Data: sorry, find unexpected main style\n"));
1618
511
    f << "##ST" << std::hex << val << std::dec << "\n";
1619
511
  }
1620
19.3k
  cell.m_extra=f.str();
1621
19.3k
  f.str("");
1622
19.3k
  f << cell << "font=[" << font << "],";
1623
19.3k
  if (m_state->m_idCellStyleMap.find(id)!=m_state->m_idCellStyleMap.end())
1624
10.9k
  {
1625
10.9k
    WPS_DEBUG_MSG(("LotusStyleManager::readCellStyleD2Data: the cell style %d already exists\n", id));
1626
10.9k
    f << "###";
1627
10.9k
  }
1628
8.43k
  else
1629
8.43k
    m_state->m_idCellStyleMap.insert(std::map<int, LotusStyleManagerInternal::CellStyle>::value_type(id,cell));
1630
1631
19.3k
  ascFile.addDelimiter(input->tell(),'|');
1632
19.3k
  ascFile.addPos(entry.m_entry.begin()-6);
1633
19.3k
  ascFile.addNote(f.str().c_str());
1634
19.3k
  return true;
1635
19.3k
}
1636
1637
bool LotusStyleManager::readCellStyleD2(std::shared_ptr<WPSStream> stream, long endPos)
1638
33.5k
{
1639
33.5k
  if (!stream) return false;
1640
33.5k
  RVNGInputStreamPtr &input = stream->m_input;
1641
33.5k
  libwps::DebugFile &ascFile=stream->m_ascii;
1642
33.5k
  libwps::DebugStream f;
1643
1644
33.5k
  long pos = input->tell();
1645
33.5k
  int const vers=version();
1646
33.5k
  int expectedSize=vers<4 ? 21 : 33;
1647
33.5k
  if (endPos-pos!=expectedSize)
1648
1.18k
  {
1649
1.18k
    WPS_DEBUG_MSG(("LotusStyleManager::readCellStyleD2 the zone size seems bad\n"));
1650
1.18k
    ascFile.addPos(pos-6);
1651
1.18k
    ascFile.addNote("Entries(CellStyle):###");
1652
1.18k
    return true;
1653
1.18k
  }
1654
32.4k
  auto id=int(libwps::readU8(input));
1655
32.4k
  if (endPos-pos==33)   // 123
1656
23.1k
  {
1657
23.1k
    f << "Entries(CellStyle):Ce" << id << ",";
1658
23.1k
    ascFile.addPos(pos-6);
1659
23.1k
    ascFile.addNote(f.str().c_str());
1660
1661
23.1k
    LotusStyleManagerInternal::CellStyleEntry cellEntry(stream);
1662
23.1k
    cellEntry.m_entry.setBegin(pos);
1663
23.1k
    cellEntry.m_entry.setEnd(endPos);
1664
23.1k
    input->seek(pos+27, librevenge::RVNG_SEEK_SET);
1665
23.1k
    auto val=int(libwps::readU16(input));
1666
23.1k
    if (!val)
1667
18.7k
    {
1668
18.7k
      std::set<int> seen;
1669
18.7k
      seen.insert(id);
1670
18.7k
      return readCellStyleD2Data(cellEntry, seen);
1671
18.7k
    }
1672
    // we need to read the style first, so let defer the parsing of this field
1673
4.40k
    cellEntry.m_parentId=(val&0xFF);
1674
4.40k
    if (m_state->m_idToCellStyleEntryMap.find(id)!=m_state->m_idToCellStyleEntryMap.end())
1675
1.81k
    {
1676
1.81k
      WPS_DEBUG_MSG(("LotusStyleManager::readCellStyleD2Data: the cell style entry %d already exists\n", id));
1677
1.81k
      f << "###";
1678
1.81k
    }
1679
2.58k
    else
1680
2.58k
      m_state->m_idToCellStyleEntryMap.insert(std::map<int, LotusStyleManagerInternal::CellStyleEntry>::value_type(id,cellEntry));
1681
4.40k
    return true;
1682
23.1k
  }
1683
9.21k
  auto val=int(libwps::readU8(input)); // always 50?
1684
1685
9.21k
  LotusStyleManagerInternal::CellStyle cell(m_mainParser.getDefaultFontType());
1686
9.21k
  if (val!=0x50)
1687
2.27k
    f << "fl=" << std::hex << val << std::dec << ",";
1688
  // wk4
1689
27.6k
  for (int i=0; i<2; ++i)   // always 0?
1690
18.4k
  {
1691
18.4k
    val=int(libwps::readU8(input));
1692
18.4k
    if (val)
1693
4.09k
      f << "f" << i << "=" << val << ",";
1694
18.4k
  }
1695
82.9k
  for (int i=0; i<8; ++i)
1696
73.7k
  {
1697
73.7k
    val=int(libwps::readU8(input));
1698
73.7k
    auto fl=int(libwps::readU8(input));
1699
73.7k
    if (!val) continue;
1700
30.9k
    if (i<4)
1701
11.0k
    {
1702
11.0k
      if (fl!=0x10) f << "#fl[border" << i << "]=" << std::hex << fl << std::dec << ",";
1703
11.0k
      if (m_state->m_idLineStyleMap.find(val)==m_state->m_idLineStyleMap.end())
1704
10.8k
      {
1705
10.8k
        WPS_DEBUG_MSG(("LotusStyleManager::readCellStyleD2: the line style %d does not exists\n", val));
1706
10.8k
        f << "###borderId" << i << "=" << val << ",";
1707
10.8k
      }
1708
129
      else
1709
129
        cell.m_bordersId[i]=val;
1710
11.0k
    }
1711
19.8k
    else if (i==4 || i==7)
1712
9.58k
    {
1713
9.58k
      int wh=i==4 ? 0 : 1;
1714
9.58k
      if (fl!=0x20) f << "#fl[color" << wh << "]=" << std::hex << fl << std::dec << ",";
1715
9.58k
      if (m_state->m_idColorStyleMap.find(val)==m_state->m_idColorStyleMap.end())
1716
6.69k
      {
1717
6.69k
        WPS_DEBUG_MSG(("LotusStyleManager::readCellStyleD2: the color style %d does not exists\n", val));
1718
6.69k
        f << "###colorId[" << wh << "]=" << val << ",";
1719
6.69k
      }
1720
2.88k
      else
1721
2.88k
        cell.m_colorsId[wh]=val;
1722
9.58k
    }
1723
10.2k
    else if (i==5)
1724
6.16k
    {
1725
6.16k
      if (fl) f << "#fl[font]=" << std::hex << fl << std::dec << ",";
1726
6.16k
      if (m_state->m_idFontStyleMap.find(val)==m_state->m_idFontStyleMap.end())
1727
4.49k
      {
1728
4.49k
        WPS_DEBUG_MSG(("LotusStyleManager::readCellStyleD2: the font style %d does not exists\n", val));
1729
4.49k
        f << "###fontId=" << val << ",";
1730
4.49k
      }
1731
1.67k
      else
1732
1.67k
        cell.m_fontId=val;
1733
6.16k
    }
1734
4.13k
    else
1735
4.13k
    {
1736
4.13k
      if (fl!=0x30) f << "#fl[format]=" << std::hex << fl << std::dec << ",";
1737
4.13k
      if (m_state->m_idFormatStyleMap.find(val)==m_state->m_idFormatStyleMap.end())
1738
3.91k
      {
1739
3.91k
        WPS_DEBUG_MSG(("LotusStyleManager::readCellStyleD2: the format style %d does not exists\n", val));
1740
3.91k
        f << "###formatId=" << val << ",";
1741
3.91k
      }
1742
213
      else
1743
213
        cell.m_formatId=val;
1744
4.13k
    }
1745
30.9k
  }
1746
9.21k
  val=int(libwps::readU8(input));
1747
9.21k
  cell.m_borders=(val&0xF);
1748
9.21k
  val >>=4;
1749
  // small number 0|2
1750
9.21k
  if (val) f << "f2=" << val << ",";
1751
9.21k
  cell.m_extra=f.str();
1752
9.21k
  f.str("");
1753
9.21k
  f << "Entries(CellStyle):Ce" << id << "," << cell;
1754
1755
9.21k
  if (m_state->m_idCellStyleMap.find(id)!=m_state->m_idCellStyleMap.end())
1756
5.86k
  {
1757
5.86k
    WPS_DEBUG_MSG(("LotusStyleManager::readCellStyleD2: the cell style %d already exists\n", id));
1758
5.86k
    f << "###";
1759
5.86k
  }
1760
3.35k
  else
1761
3.35k
    m_state->m_idCellStyleMap.insert(std::map<int, LotusStyleManagerInternal::CellStyle>::value_type(id,cell));
1762
9.21k
  ascFile.addPos(pos-6);
1763
9.21k
  ascFile.addNote(f.str().c_str());
1764
9.21k
  return true;
1765
32.4k
}
1766
1767
bool LotusStyleManager::readCellStyleE6(std::shared_ptr<WPSStream> stream, long endPos)
1768
2.88k
{
1769
2.88k
  if (!stream) return false;
1770
2.88k
  RVNGInputStreamPtr &input = stream->m_input;
1771
2.88k
  libwps::DebugFile &ascFile=stream->m_ascii;
1772
2.88k
  libwps::DebugStream f;
1773
1774
2.88k
  long pos = input->tell();
1775
2.88k
  long sz=endPos-pos;
1776
2.88k
  if ((sz%15)!=10)
1777
374
  {
1778
374
    WPS_DEBUG_MSG(("LotusStyleManager::readCellStyleE6: the zone size seems bad\n"));
1779
374
    ascFile.addPos(pos-6);
1780
374
    ascFile.addNote("Entries(CellStyle):###");
1781
374
    return true;
1782
374
  }
1783
2.50k
  f << "Entries(CellStyle):";
1784
12.5k
  for (int i=0; i<4; ++i)
1785
10.0k
  {
1786
10.0k
    auto val=int(libwps::readU16(input));
1787
10.0k
    int const expected[]= {0x10, 0x100, 0x10, 0xe};
1788
10.0k
    if (val!=expected[i]) f << "f" << i << "=" << val << ",";
1789
10.0k
  }
1790
2.50k
  auto decalId=int(libwps::readU16(input));
1791
2.50k
  if (decalId)
1792
1.18k
  {
1793
1.18k
    decalId *= 256;
1794
1.18k
    f << "decal[id]=" << decalId;
1795
1.18k
  }
1796
2.50k
  ascFile.addPos(pos-6);
1797
2.50k
  ascFile.addNote(f.str().c_str());
1798
2.50k
  auto N=int(sz/15);
1799
2.50k
  auto fontType=m_mainParser.getDefaultFontType();
1800
47.3k
  for (int i=0; i<N; ++i)
1801
44.7k
  {
1802
44.7k
    pos=input->tell();
1803
44.7k
    f.str("");
1804
44.7k
    f << "CellStyle-" << i << ":";
1805
44.7k
    int id=decalId+int(libwps::readU8(input));
1806
44.7k
    f << "Ce" << id << ",";
1807
44.7k
    LotusStyleManagerInternal::CellStyle cell(fontType);
1808
44.7k
    auto fId=int(libwps::readU8(input));
1809
44.7k
    auto &font=cell.m_fontStyle;
1810
44.7k
    if (fId)
1811
30.8k
    {
1812
30.8k
      if (!updateFontStyle(fId, font.m_font, font.m_fontType))
1813
26.6k
        f << "#";
1814
30.8k
      f << "FS" << fId << ",";
1815
30.8k
    }
1816
268k
    for (int j=0; j<5; ++j)   // fl0=0|20|40, fl1=0|f|32|36|76|a8, fl2=XX, fl3=0-b|7c, fl4=0|2
1817
223k
    {
1818
223k
      auto val=int(libwps::readU8(input));
1819
223k
      if (j==0)
1820
44.7k
      {
1821
44.7k
        if (val&0x60)
1822
17.3k
        {
1823
17.3k
          int wh=((val>>5)&3);
1824
17.3k
          if (wh==1)
1825
4.80k
          {
1826
4.80k
            font.m_font.m_attributes |= WPS_UNDERLINE_BIT;
1827
4.80k
            f << "underline,";
1828
4.80k
          }
1829
12.5k
          else if (wh==2)
1830
4.93k
          {
1831
4.93k
            f << "underline[double],";
1832
4.93k
            font.m_font.m_attributes |= WPS_DOUBLE_UNDERLINE_BIT;
1833
4.93k
          }
1834
7.60k
          else
1835
7.60k
          {
1836
7.60k
            font.m_font.m_attributes |= WPS_UNDERLINE_BIT;
1837
7.60k
            f << "underline[w=2],"; // FIXME
1838
7.60k
          }
1839
17.3k
        }
1840
44.7k
        val&=0x9F;
1841
44.7k
      }
1842
223k
      if (!val) continue;
1843
146k
      if (j==1 || j==2)
1844
60.9k
      {
1845
60.9k
        WPSColor color;
1846
60.9k
        if (!getColor256(val, color)) f << "#colorId=" << val << ",";
1847
60.9k
        else
1848
60.9k
        {
1849
60.9k
          cell.m_colorStyle.m_colors[j==2 ? 3 : 2]=color;
1850
60.9k
          if (!color.isWhite()) f << "color" << j << "=" << color << ",";
1851
60.9k
        }
1852
60.9k
      }
1853
85.7k
      else if (j==3)
1854
30.2k
      {
1855
        // checkme: something is not right here...
1856
30.2k
        if (val==1 || val==3)
1857
4.74k
        {
1858
4.74k
          cell.m_colorStyle.m_patternId=2;
1859
4.74k
          f << "pat[low]=" << val << ",";
1860
4.74k
        }
1861
25.5k
        else
1862
25.5k
        {
1863
25.5k
          cell.m_colorStyle.m_patternId=(val>>2);
1864
25.5k
          f << "pat=" << (val>>2) << ",";
1865
25.5k
          if (val&3) f << "pat[low]=" << (val&3) << ",";
1866
25.5k
        }
1867
30.2k
      }
1868
55.4k
      else
1869
55.4k
        f << "fl" << j << "=" << std::hex << val << std::dec << ",";
1870
146k
    }
1871
44.7k
    int colors[4]; // TBLR
1872
44.7k
    int borders[4];
1873
44.7k
    unsigned long lVal=libwps::readU16(input);
1874
44.7k
    colors[0]=(lVal>>10)&0x1f;
1875
44.7k
    colors[1]=(lVal>>5)&0x1f;
1876
44.7k
    lVal&=0xC21F;
1877
44.7k
    if (lVal) f << "col[h0]=" << std::hex << lVal << std::dec << ",";
1878
44.7k
    lVal=libwps::readU16(input);
1879
44.7k
    colors[2]=(lVal>>5)&0x1f;
1880
44.7k
    colors[3]=(lVal>>0)&0x1f;
1881
44.7k
    borders[1]=(lVal>>10)&0xf;
1882
44.7k
    lVal&=0xC210;
1883
44.7k
    if (lVal) f << "col[h1]=" << std::hex << lVal << std::dec << ",";
1884
44.7k
    lVal=libwps::readU16(input);
1885
44.7k
    borders[0]=(lVal&0xf);
1886
44.7k
    borders[3]=((lVal>>4)&0xf);
1887
44.7k
    borders[2]=((lVal>>8)&0xf);
1888
44.7k
    lVal&=0xF000;
1889
44.7k
    if (lVal) f << "col[h2]=" << std::hex << lVal << std::dec << ",";
1890
223k
    for (int j=0; j<4; ++j)
1891
179k
    {
1892
179k
      if (!borders[j]) continue;
1893
94.2k
      WPSBorder border;
1894
94.2k
      switch (borders[j])
1895
94.2k
      {
1896
11.0k
      case 1:
1897
11.0k
        border.m_style=WPSBorder::Simple;
1898
11.0k
        break;
1899
6.83k
      case 2:
1900
6.83k
        border.m_style=WPSBorder::Simple;
1901
6.83k
        border.m_type=WPSBorder::Double;
1902
6.83k
        break;
1903
6.81k
      case 3:
1904
6.81k
        border.m_style=WPSBorder::Simple;
1905
6.81k
        border.m_width=2;
1906
6.81k
        break;
1907
6.34k
      case 4:
1908
6.34k
        border.m_style=WPSBorder::Dot; // 1x1
1909
6.34k
        break;
1910
6.04k
      case 5:
1911
6.04k
        border.m_style=WPSBorder::LargeDot; // 2x2
1912
6.04k
        break;
1913
4.98k
      case 6:
1914
4.98k
        border.m_style=WPSBorder::Dash; // 3x1
1915
4.98k
        break;
1916
6.52k
      case 7:
1917
6.52k
        border.m_style=WPSBorder::Dash; // 1x1 2x1
1918
6.52k
        break;
1919
5.65k
      case 8:
1920
5.65k
        border.m_style=WPSBorder::Dash; // 1x1 1x1 2x1
1921
5.65k
        break;
1922
40.0k
      default:
1923
40.0k
        WPS_DEBUG_MSG(("LotusStyleManager::readCellStyleE6: can not read some border format\n"));
1924
40.0k
        f << "##border" << j << "=" << borders[j] << ",";
1925
40.0k
        border.m_style=WPSBorder::Simple;
1926
40.0k
        break;
1927
94.2k
      }
1928
94.2k
      if (!getColor16(colors[j], border.m_color))
1929
42.1k
      {
1930
42.1k
        WPS_DEBUG_MSG(("LotusStyleManager::readCellStyleE6: can not read some color\n"));
1931
42.1k
        f << "##col" << j << "=" << colors[j] << ",";
1932
42.1k
      }
1933
94.2k
      char const *wh[]= {"T", "B", "L", "R"};
1934
94.2k
      f << "bord" << wh[j] << "=" << border << ",";
1935
94.2k
      cell.m_bordersStyle[j]=border;
1936
94.2k
    }
1937
44.7k
    f << "],";
1938
44.7k
    ascFile.addDelimiter(input->tell(),'|');
1939
44.7k
    if (m_state->m_idCellStyleMap.find(id)!=m_state->m_idCellStyleMap.end())
1940
30.9k
    {
1941
30.9k
      WPS_DEBUG_MSG(("LotusStyleManager::readCellStyleE6: the cell style %d already exists\n", id));
1942
30.9k
      f << "###id";
1943
30.9k
    }
1944
13.8k
    else
1945
13.8k
      m_state->m_idCellStyleMap.insert(std::map<int, LotusStyleManagerInternal::CellStyle>::value_type(id,cell));
1946
1947
44.7k
    input->seek(pos+15,librevenge::RVNG_SEEK_SET);
1948
44.7k
    ascFile.addPos(pos);
1949
44.7k
    ascFile.addNote(f.str().c_str());
1950
44.7k
  }
1951
2.50k
  return true;
1952
2.50k
}
1953
1954
bool LotusStyleManager::readStyleE6(std::shared_ptr<WPSStream> stream, long endPos)
1955
3.66k
{
1956
3.66k
  if (!stream) return false;
1957
3.66k
  RVNGInputStreamPtr &input = stream->m_input;
1958
3.66k
  libwps::DebugFile &ascFile=stream->m_ascii;
1959
3.66k
  libwps::DebugStream f;
1960
1961
3.66k
  long pos = input->tell();
1962
3.66k
  long sz=endPos-pos;
1963
3.66k
  if (sz!=8)
1964
416
  {
1965
416
    WPS_DEBUG_MSG(("LotusStyleManager::readStyleE6: the zone size seems bad\n"));
1966
416
    ascFile.addPos(pos-6);
1967
416
    ascFile.addNote("Entries(MainStyle):###");
1968
416
    return true;
1969
416
  }
1970
3.25k
  f << "Entries(MainStyle):";
1971
3.25k
  auto id=int(libwps::readU8(input));
1972
3.25k
  auto val=int(libwps::readU8(input)); // always 50?
1973
3.25k
  if (val!=0x60)
1974
1.09k
    f << "##type=" << std::hex << val << std::dec << ",";
1975
3.25k
  f << "ST" << id << ",";
1976
3.25k
  val=int(libwps::readU32(input));
1977
3.25k
  if (val) f << "used=" << val << ",";
1978
3.25k
  val=int(libwps::readU16(input));
1979
3.25k
  int cellId=-1;
1980
3.25k
  if ((val>>8)==0x50)
1981
2.67k
  {
1982
2.67k
    cellId=(val&0xFF);
1983
2.67k
    f << "Ce" << (val&0xFF) << ",";
1984
2.67k
  }
1985
573
  else if (val)
1986
489
  {
1987
489
    WPS_DEBUG_MSG(("LotusStyleManager::readStyleE6: find unexpected value\n"));
1988
489
    f << "##Ce" << std::hex << val << std::dec << ",";
1989
489
  }
1990
3.25k
  if (cellId>=0)
1991
2.67k
  {
1992
2.67k
    if (m_state->m_idToParentStyleMap.find(id)!=m_state->m_idToParentStyleMap.end())
1993
1.67k
    {
1994
1.67k
      WPS_DEBUG_MSG(("LotusStyleManager::readStyleE6: the cell style %d already exists\n", id));
1995
1.67k
      f << "###id";
1996
1.67k
    }
1997
1.00k
    else
1998
1.00k
      m_state->m_idToParentStyleMap.insert(std::map<int, int>::value_type(id,cellId));
1999
2.67k
  }
2000
3.25k
  ascFile.addPos(pos-6);
2001
3.25k
  ascFile.addNote(f.str().c_str());
2002
3.25k
  return true;
2003
3.66k
}
2004
2005
bool LotusStyleManager::updateCellStyle(int cellId, WPSCellFormat &format,
2006
                                        WPSFont &font, libwps_tools_win::Font::Type &fontType)
2007
1.16M
{
2008
1.16M
  if (cellId==0)
2009
543k
    return true;
2010
617k
  if (m_state->m_idCellStyleMap.find(cellId)==m_state->m_idCellStyleMap.end() &&
2011
576k
          m_state->m_idToCellStyleEntryMap.find(cellId)!=m_state->m_idToCellStyleEntryMap.end())
2012
540
  {
2013
540
    std::set<int> seen;
2014
540
    seen.insert(cellId);
2015
540
    readCellStyleD2Data(m_state->m_idToCellStyleEntryMap.find(cellId)->second, seen);
2016
540
  }
2017
617k
  if (m_state->m_idCellStyleMap.find(cellId)==m_state->m_idCellStyleMap.end())
2018
576k
  {
2019
576k
    static bool first=true;
2020
576k
    if (first)
2021
5
    {
2022
5
      WPS_DEBUG_MSG(("LotusStyleManager::updateCellStyle: the cell style %d does not exist\n", cellId));
2023
5
      first=false;
2024
5
    }
2025
576k
    return false;
2026
576k
  }
2027
40.9k
  int const vers=version();
2028
40.9k
  auto const &cellStyle=m_state->m_idCellStyleMap.find(cellId)->second;
2029
40.9k
  if (vers>=3)
2030
36.6k
  {
2031
36.6k
    font=cellStyle.m_fontStyle.m_font;
2032
36.6k
    fontType=cellStyle.m_fontStyle.m_fontType;
2033
36.6k
    format.setFont(font);
2034
36.6k
    format.setTextRotation(cellStyle.m_rotation);
2035
183k
    for (int i=0; i<4; ++i)
2036
146k
    {
2037
146k
      static int const wh[]= {WPSBorder::TopBit,WPSBorder::BottomBit,WPSBorder::LeftBit,WPSBorder::RightBit};
2038
146k
      format.setBorders(wh[i],cellStyle.m_bordersStyle[i]);
2039
146k
    }
2040
36.6k
  }
2041
  // wk1 or wk3
2042
40.9k
  if ((vers!=3 && cellStyle.m_colorsId[0]) || vers>=3)
2043
40.0k
  {
2044
40.0k
    if (vers!=3 && m_state->m_idColorStyleMap.find(cellStyle.m_colorsId[0])==m_state->m_idColorStyleMap.end())
2045
6.82k
    {
2046
6.82k
      WPS_DEBUG_MSG(("LotusStyleManager::updateCellStyle: the color style %d does not exist\n", cellStyle.m_colorsId[0]));
2047
6.82k
    }
2048
33.1k
    else
2049
33.1k
    {
2050
33.1k
      auto const &color= vers>=3 ? cellStyle.m_colorStyle
2051
33.1k
                         : m_state->m_idColorStyleMap.find(cellStyle.m_colorsId[0])->second;
2052
33.1k
      if (color.m_patternId)   // not empty
2053
25.7k
      {
2054
25.7k
        WPSColor finalColor=color.m_colors[2];
2055
25.7k
        WPSGraphicStyle::Pattern pattern;
2056
25.7k
        if (color.m_patternId==2)
2057
18.8k
          finalColor=color.m_colors[3];
2058
6.90k
        else if (color.m_patternId!=1 &&
2059
5.90k
                 ((vers<3 && m_state->getPattern48(color.m_patternId, pattern)) ||
2060
4.70k
                  (vers>=3 && m_state->getPattern64(color.m_patternId, pattern))))
2061
3.50k
        {
2062
3.50k
          pattern.m_colors[0]=color.m_colors[3];
2063
3.50k
          pattern.m_colors[1]=color.m_colors[2];
2064
3.50k
          pattern.getAverageColor(finalColor);
2065
3.50k
        }
2066
25.7k
        format.setBackgroundColor(finalColor);
2067
25.7k
      }
2068
33.1k
    }
2069
40.0k
  }
2070
40.9k
  if (vers==3) return true;
2071
31.0k
  if (cellStyle.m_hAlign!=WPSCellFormat::HALIGN_DEFAULT)
2072
10.5k
    format.setHAlignment(cellStyle.m_hAlign);
2073
31.0k
  if (cellStyle.m_vAlign!=WPSCellFormat::VALIGN_DEFAULT)
2074
5.50k
    format.setVAlignment(cellStyle.m_vAlign);
2075
31.0k
  if (cellStyle.m_wrapping!=WPSCellFormat::WRAP_DEFAULT)
2076
5.93k
    format.setWrapping(cellStyle.m_wrapping);
2077
  // wk3
2078
31.0k
  if (cellStyle.m_fontId>=0)
2079
31.0k
  {
2080
31.0k
    if (updateFontStyle(cellStyle.m_fontId, font, fontType))
2081
31.0k
      format.setFont(font);
2082
31.0k
  }
2083
31.0k
  if (!cellStyle.m_borders)
2084
28.8k
    return true;
2085
10.9k
  for (int i=0,depl=1; i<4; ++i, depl*=2)
2086
8.74k
  {
2087
8.74k
    if ((cellStyle.m_borders&depl)==0) continue;
2088
6.99k
    static int const wh[]= {WPSBorder::TopBit,WPSBorder::LeftBit,WPSBorder::BottomBit,WPSBorder::RightBit};
2089
6.99k
    WPSBorder border;
2090
6.99k
    format.setBorders(wh[i],border);
2091
6.99k
  }
2092
2.18k
  return true;
2093
31.0k
}
2094
2095
bool LotusStyleManager::readFMTFontName(std::shared_ptr<WPSStream> stream)
2096
12.5k
{
2097
12.5k
  if (!stream) return false;
2098
12.5k
  RVNGInputStreamPtr &input=stream->m_input;
2099
12.5k
  libwps::DebugFile &ascFile=stream->m_ascii;
2100
12.5k
  libwps::DebugStream f;
2101
2102
12.5k
  long pos = input->tell();
2103
12.5k
  auto type = int(libwps::read16(input));
2104
12.5k
  if (type!=0xae)
2105
0
  {
2106
0
    WPS_DEBUG_MSG(("LotusStyleManager::readFMTFontName: not a font name definition\n"));
2107
0
    return false;
2108
0
  }
2109
12.5k
  auto sz = long(libwps::readU16(input));
2110
12.5k
  long endPos=pos+4+sz;
2111
12.5k
  f << "Entries(FMTFont)[name]:";
2112
12.5k
  if (sz < 2)
2113
114
  {
2114
114
    WPS_DEBUG_MSG(("LotusStyleManager::readFMTFontName: the zone is too short\n"));
2115
114
    f << "###";
2116
114
    ascFile.addPos(pos);
2117
114
    ascFile.addNote(f.str().c_str());
2118
114
    return true;
2119
114
  }
2120
12.4k
  auto id=int(libwps::readU8(input));
2121
12.4k
  f << "id=" << id << ",";
2122
12.4k
  bool nameOk=true;
2123
12.4k
  std::string name("");
2124
97.9k
  for (long i=1; i<sz; ++i)
2125
97.2k
  {
2126
97.2k
    auto c=char(libwps::readU8(input));
2127
97.2k
    if (!c) break;
2128
85.5k
    if (nameOk && !(c==' ' || (c>='0'&&c<='9') || (c>='a'&&c<='z') || (c>='A'&&c<='Z')))
2129
2.83k
    {
2130
2.83k
      nameOk=false;
2131
2.83k
      WPS_DEBUG_MSG(("LotusStyleManager::readFMTFontName: find odd character in name\n"));
2132
2.83k
      f << "#";
2133
2.83k
    }
2134
85.5k
    name += c;
2135
85.5k
  }
2136
12.4k
  f << name << ",";
2137
12.4k
  if (m_state->m_idFontNameMap.find(id)!=m_state->m_idFontNameMap.end())
2138
7.91k
  {
2139
7.91k
    WPS_DEBUG_MSG(("LotusStyleManager::readFMTFontName: can not update font map for id=%d\n", id));
2140
7.91k
  }
2141
4.52k
  else
2142
4.52k
  {
2143
4.52k
    LotusStyleManagerInternal::FontName font;
2144
4.52k
    font.m_name=name;
2145
4.52k
    m_state->m_idFontNameMap[id]=font;
2146
4.52k
  }
2147
12.4k
  if (input->tell()!=endPos)
2148
2.38k
  {
2149
2.38k
    WPS_DEBUG_MSG(("LotusStyleManager::readFMTFontName: find extra data\n"));
2150
2.38k
    f << "###extra";
2151
2.38k
    input->seek(endPos, librevenge::RVNG_SEEK_SET);
2152
2.38k
  }
2153
12.4k
  ascFile.addPos(pos);
2154
12.4k
  ascFile.addNote(f.str().c_str());
2155
12.4k
  return true;
2156
12.5k
}
2157
2158
bool LotusStyleManager::readFMTFontId(std::shared_ptr<WPSStream> stream)
2159
2.28k
{
2160
2.28k
  if (!stream) return false;
2161
2.28k
  RVNGInputStreamPtr &input=stream->m_input;
2162
2.28k
  libwps::DebugFile &ascFile=stream->m_ascii;
2163
2.28k
  libwps::DebugStream f;
2164
2165
2.28k
  long pos = input->tell();
2166
2.28k
  auto type = int(libwps::read16(input));
2167
2.28k
  if (type!=0xb0)
2168
0
  {
2169
0
    WPS_DEBUG_MSG(("LotusStyleManager::readFMTFontId: not a font id definition\n"));
2170
0
    return false;
2171
0
  }
2172
2.28k
  auto sz = long(libwps::readU16(input));
2173
2.28k
  long endPos=pos+4+sz;
2174
2.28k
  f << "Entries(FMTFont)[ids]:";
2175
2.28k
  if ((sz%2)!=0)
2176
811
  {
2177
811
    WPS_DEBUG_MSG(("LotusStyleManager::readFMTFontId: the zone size is odd\n"));
2178
811
    f << "###";
2179
811
    ascFile.addPos(pos);
2180
811
    ascFile.addNote(f.str().c_str());
2181
811
    return true;
2182
811
  }
2183
1.47k
  f << "ids=[";
2184
1.47k
  bool isFirstError=true;
2185
12.0k
  for (int i=0; i<int(sz)/2; ++i)
2186
10.5k
  {
2187
10.5k
    auto id =int(libwps::readU16(input));
2188
10.5k
    f << id << ",";
2189
10.5k
    if (m_state->m_idFontNameMap.find(i)!=m_state->m_idFontNameMap.end())
2190
7.05k
      m_state->m_idFontNameMap.find(i)->second.m_id=id;
2191
3.53k
    else if (isFirstError)
2192
911
    {
2193
911
      isFirstError=false;
2194
911
      WPS_DEBUG_MSG(("LotusStyleManager::readFMTFontId: can not update some font map for id=%d\n", id));
2195
911
    }
2196
10.5k
  }
2197
1.47k
  f << "],";
2198
1.47k
  if (input->tell()!=endPos)
2199
0
  {
2200
0
    WPS_DEBUG_MSG(("LotusStyleManager::readFMTFontId: find extra data\n"));
2201
0
    f << "###extra";
2202
0
    input->seek(endPos, librevenge::RVNG_SEEK_SET);
2203
0
  }
2204
1.47k
  ascFile.addPos(pos);
2205
1.47k
  ascFile.addNote(f.str().c_str());
2206
1.47k
  return true;
2207
2.28k
}
2208
2209
bool LotusStyleManager::readFMTFontSize(std::shared_ptr<WPSStream> stream)
2210
2.33k
{
2211
2.33k
  if (!stream) return false;
2212
2.33k
  RVNGInputStreamPtr &input=stream->m_input;
2213
2.33k
  libwps::DebugFile &ascFile=stream->m_ascii;
2214
2.33k
  libwps::DebugStream f;
2215
2216
2.33k
  long pos = input->tell();
2217
2.33k
  auto type = int(libwps::read16(input));
2218
2.33k
  if (type!=0xaf && type!=0xb1)
2219
0
  {
2220
0
    WPS_DEBUG_MSG(("LotusStyleManager::readFMTFontSize: not a font size definition\n"));
2221
0
    return false;
2222
0
  }
2223
2.33k
  auto sz = long(libwps::readU16(input));
2224
2.33k
  long endPos=pos+4+sz;
2225
2.33k
  int const wh=type==0xaf ? 0 : 1;
2226
2.33k
  f << "Entries(FMTFont)[size" << wh << "]:";
2227
2.33k
  if ((sz%2)!=0)
2228
76
  {
2229
76
    WPS_DEBUG_MSG(("LotusStyleManager::readFMTFontSize: the zone size is odd\n"));
2230
76
    f << "###";
2231
76
    ascFile.addPos(pos);
2232
76
    ascFile.addNote(f.str().c_str());
2233
76
    return true;
2234
76
  }
2235
2.26k
  f << "size=[";
2236
2.26k
  bool isFirstError=true;
2237
23.1k
  for (int i=0; i<int(sz)/2; ++i)
2238
20.8k
  {
2239
20.8k
    auto size =int(libwps::readU16(input));
2240
20.8k
    f << size << ",";
2241
20.8k
    if (m_state->m_idFontNameMap.find(i)!=m_state->m_idFontNameMap.end())
2242
13.7k
      m_state->m_idFontNameMap.find(i)->second.m_size[wh]=size;
2243
7.11k
    else if (isFirstError)
2244
1.86k
    {
2245
1.86k
      isFirstError=false;
2246
1.86k
      WPS_DEBUG_MSG(("LotusStyleManager::readFMTFontSize: can not update some font map for size=%d\n", size));
2247
1.86k
    }
2248
20.8k
  }
2249
2.26k
  f << "],";
2250
2.26k
  if (input->tell()!=endPos)
2251
0
  {
2252
0
    WPS_DEBUG_MSG(("LotusStyleManager::readFMTFontSize: find extra data\n"));
2253
0
    f << "###extra";
2254
0
    input->seek(endPos, librevenge::RVNG_SEEK_SET);
2255
0
  }
2256
2.26k
  ascFile.addPos(pos);
2257
2.26k
  ascFile.addNote(f.str().c_str());
2258
2.26k
  return true;
2259
2.33k
}
2260
2261
bool LotusStyleManager::readMenuStyleE7(std::shared_ptr<WPSStream> stream, long endPos)
2262
5.62k
{
2263
5.62k
  if (!stream) return false;
2264
5.62k
  RVNGInputStreamPtr &input = stream->m_input;
2265
5.62k
  libwps::DebugFile &ascFile=stream->m_ascii;
2266
5.62k
  libwps::DebugStream f;
2267
2268
5.62k
  long pos = input->tell();
2269
5.62k
  if (endPos-pos<23)
2270
22
  {
2271
22
    WPS_DEBUG_MSG(("LotusStyleManager::readMenuStyleE7 the zone size seems bad\n"));
2272
22
    ascFile.addPos(pos-6);
2273
22
    ascFile.addNote("Entries(MenuStyle):###");
2274
22
    return true;
2275
22
  }
2276
5.59k
  f << "Entries(MenuStyle):";
2277
5.59k
  f << "id=" << libwps::readU16(input) << ",";
2278
16.7k
  for (int i=0; i<2; ++i)   // fl0=0|[048c]0FF, fl1=[04]00[0-3]
2279
11.1k
  {
2280
11.1k
    auto val=int(libwps::readU16(input));
2281
11.1k
    if (val) f << "fl" << i << "=" << std::hex << val << std::dec << ",";
2282
11.1k
  }
2283
5.59k
  std::string name;
2284
39.6k
  for (int i=0; i<16; ++i)
2285
39.5k
  {
2286
39.5k
    auto c=char(libwps::readU8(input));
2287
39.5k
    if (!c) break;
2288
34.0k
    name += c;
2289
34.0k
  }
2290
5.59k
  f << name << ",";
2291
5.59k
  input->seek(pos+22, librevenge::RVNG_SEEK_SET);
2292
5.59k
  name="";
2293
5.59k
  auto maxN=int(endPos-input->tell());
2294
56.4k
  for (int i=0; i<maxN; ++i)
2295
56.4k
  {
2296
56.4k
    auto c=char(libwps::readU8(input));
2297
56.4k
    if (!c) break;
2298
50.8k
    name += c;
2299
50.8k
  }
2300
5.59k
  f << name;
2301
5.59k
  if (input->tell() != endPos)
2302
258
    ascFile.addDelimiter(input->tell(),'|');
2303
5.59k
  ascFile.addPos(pos-6);
2304
5.59k
  ascFile.addNote(f.str().c_str());
2305
5.59k
  return true;
2306
5.62k
}
2307
2308
/* vim:set shiftwidth=4 softtabstop=4 noexpandtab: */