Coverage Report

Created: 2026-07-20 07:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libwps/src/lib/WPS8Table.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) 2009, 2011 Alonso Laurent (alonso@loria.fr)
11
 * Copyright (C) 2006, 2007 Andrew Ziem
12
 * Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba@bluewin.ch)
13
 * Copyright (C) 2004 Marc Maurer (uwog@uwog.net)
14
 * Copyright (C) 2003-2005 William Lachance (william.lachance@sympatico.ca)
15
 *
16
 * For minor contributions see the git repository.
17
 *
18
 * Alternatively, the contents of this file may be used under the terms
19
 * of the GNU Lesser General Public License Version 2.1 or later
20
 * (LGPLv2.1+), in which case the provisions of the LGPLv2.1+ are
21
 * applicable instead of those above.
22
 *
23
 * For further information visit http://libwps.sourceforge.net
24
 */
25
26
#include <iomanip>
27
#include <iostream>
28
29
#include <librevenge/librevenge.h>
30
31
#include "WPSCell.h"
32
#include "WPSContentListener.h"
33
#include "WPSEntry.h"
34
#include "WPSPosition.h"
35
#include "WPSTable.h"
36
37
#include "WPS8.h"
38
#include "WPS8Struct.h"
39
40
#include "WPS8Table.h"
41
42
43
/** Internal: the structures of a WPS8Table */
44
namespace WPS8TableInternal
45
{
46
/** Internal: class to store a basic cell with borders */
47
struct Cell final : public WPSCell
48
{
49
  //! constructor
50
  explicit Cell(WPS8Table &parser)
51
755k
    : WPSCell()
52
755k
    , m_tableParser(parser)
53
755k
    , m_id(-1)
54
755k
    , m_strsId(-1)
55
755k
    , m_size()
56
755k
  {
57
755k
    WPSBorder emptyBorder;
58
755k
    emptyBorder.m_style = WPSBorder::None;
59
755k
    m_bordersList.resize(4, emptyBorder);
60
3.02M
    for (float &i : m_bordersSep) i = 0.0;
61
755k
  }
62
  //! virtual destructor
63
  ~Cell() final;
64
65
  //! operator<<
66
  friend std::ostream &operator<<(std::ostream &o, Cell const &cell);
67
  //! call when a cell must be send
68
  bool send(WPSListenerPtr &listener) final
69
366
  {
70
366
    if (!listener) return true;
71
366
    auto *listen=dynamic_cast<WPSContentListener *>(listener.get());
72
366
    if (!listen)
73
0
    {
74
0
      WPS_DEBUG_MSG(("WPS8TableInternal::Cell::send: unexpected listener\n"));
75
0
      return true;
76
0
    }
77
366
    listen->openTableCell(*this);
78
366
    sendContent(listener);
79
366
    listen->closeTableCell();
80
366
    return true;
81
366
  }
82
83
  //! call when the content of a cell must be send
84
  bool sendContent(WPSListenerPtr &) final
85
863
  {
86
863
    m_tableParser.sendTextInCell(m_strsId, m_id);
87
863
    return true;
88
863
  }
89
90
  //! the actual parser
91
  WPS8Table &m_tableParser;
92
  //! the cell id
93
  int m_id;
94
  //! the strsId
95
  mutable int m_strsId;
96
  //! frame size in inches
97
  Vec2f m_size;
98
  //! border text separator T,L,R,B ( checkme, not sure )
99
  float m_bordersSep[4];
100
};
101
Cell::~Cell()
102
755k
{
103
755k
}
104
//! operator<< for a Cell
105
std::ostream &operator<<(std::ostream &o, Cell const &cell)
106
0
{
107
0
  o << reinterpret_cast<WPSCell const &>(cell);
108
0
  if (cell.m_size.x() > 0 || cell.m_size.y() > 0) o << "size=" << cell.m_size << ",";
109
0
  bool hasBSize = false;
110
0
  for (float i : cell.m_bordersSep)
111
0
  {
112
0
    if (i <= 0)
113
0
      continue;
114
0
    hasBSize = true;
115
0
    break;
116
0
  }
117
0
  if (hasBSize)
118
0
  {
119
0
    o << "borderSep?=[";
120
0
    for (float i : cell.m_bordersSep)
121
0
      if (i > 0) o << i << ",";
122
0
      else o << "_,";
123
0
    o << "],";
124
0
  }
125
0
  return o;
126
0
}
127
128
/** Internal: class to store a table: list of cells */
129
struct Table final : public WPSTable
130
{
131
  //! constructor
132
  Table()
133
644k
    : m_id(-1)
134
644k
    , m_parsed(false) {}
135
134k
  Table &operator=(Table const &)=default;
136
  //! destructor
137
  ~Table() final;
138
  //! operator<<
139
  friend std::ostream &operator<<(std::ostream &o, Table const &table);
140
  //! the table id
141
  int m_id;
142
143
  //! a bool to know if the table has been parsed
144
  mutable bool m_parsed;
145
};
146
147
Table::~Table()
148
644k
{
149
644k
}
150
151
//! operator<< for a Table
152
std::ostream &operator<<(std::ostream &o, Table const &table)
153
0
{
154
0
  o << "id=" << table.m_id << ",";
155
0
  for (int i = 0; i < table.numCells(); i++)
156
0
  {
157
0
    WPSCellPtr cell = const_cast<Table &>(table).getCell(i);
158
0
    if (!cell) continue;
159
0
    o << "cell" << i << "=[" << *reinterpret_cast<Cell const *>(cell.get()) << "],";
160
0
  }
161
0
  return o;
162
0
}
163
164
/** Internal: the state of a WPS8Table */
165
struct State
166
{
167
  //! constructor
168
  State()
169
11.2k
    : m_version(-1)
170
11.2k
    , m_numPages(0)
171
11.2k
    , m_tableMap()
172
11.2k
    , m_MCLDTypes()
173
11.2k
  {
174
11.2k
    initTypeMaps();
175
11.2k
  }
176
177
  //! initialize the type map
178
  void initTypeMaps();
179
  //! the version
180
  int m_version;
181
  //! the number page
182
  int m_numPages;
183
  //! a map id -> table
184
  std::map<int, Table> m_tableMap;
185
  //! the MCLD type
186
  std::map<int,int> m_MCLDTypes;
187
};
188
189
void State::initTypeMaps()
190
11.2k
{
191
11.2k
  static int const MCLDTypes[] =
192
11.2k
  {
193
11.2k
    0, 0x22, 1, 0x22, 2, 0x22, 3, 0x22, 4, 0x22, 5, 0x22, 6, 0x22, 7, 0x22,
194
11.2k
    8, 0x22, 9, 0x22, 0xa, 0x22, 0xb, 0x1a, 0xc, 0x2, 0xd, 0x22, 0xe, 0x22,
195
11.2k
    0x11, 0x22, 0x12, 0x22, 0x13, 0x12, 0x14, 0x2, 0x15, 0x22, 0x16, 0x22, 0x17, 0x22,
196
11.2k
    0x18, 0x22, 0x19, 0x2, 0x1a, 0x2, 0x1d, 0x22, 0x1e, 0x22, 0x1f, 0x12,
197
11.2k
    0x20, 0x22, 0x21, 0x12, 0x22, 0x22, 0x23, 0x22, 0x24, 0x12, 0x25, 0x22, 0x26, 0x22, 0x27, 0x12,
198
11.2k
    0x28, 0x22, 0x29, 0x22, 0x2a, 0x12, 0x2b, 0x22, 0x2c, 0x12,
199
11.2k
    0x31, 0x18
200
11.2k
  };
201
484k
  for (int i = 0; i+1 < int(WPS_N_ELEMENTS(MCLDTypes)); i+=2)
202
473k
    m_MCLDTypes[MCLDTypes[i]] = MCLDTypes[i+1];
203
204
11.2k
}
205
}
206
207
////////////////////////////////////////////////////////////
208
// constructor/destructor
209
////////////////////////////////////////////////////////////
210
WPS8Table::WPS8Table(WPS8Parser &parser)
211
11.2k
  : m_listener()
212
11.2k
  , m_mainParser(parser)
213
11.2k
  , m_state(new WPS8TableInternal::State)
214
11.2k
  , m_asciiFile(parser.ascii())
215
11.2k
{
216
11.2k
}
217
218
WPS8Table::~WPS8Table()
219
11.2k
{
220
11.2k
}
221
222
////////////////////////////////////////////////////////////
223
// update the positions and send data to the listener
224
////////////////////////////////////////////////////////////
225
int WPS8Table::version() const
226
0
{
227
0
  if (m_state->m_version <= 0)
228
0
    m_state->m_version = m_mainParser.version();
229
0
  return m_state->m_version;
230
0
}
231
232
int WPS8Table::numPages() const
233
9.83k
{
234
9.83k
  return m_state->m_numPages;
235
9.83k
}
236
237
void WPS8Table::sendTextInCell(int strsId, int cellId)
238
863
{
239
863
  m_mainParser.sendTextInCell(strsId, cellId);
240
863
}
241
242
////////////////////////////////////////////////////////////
243
// update the positions and send data to the listener
244
////////////////////////////////////////////////////////////
245
void WPS8Table::computePositions() const
246
0
{
247
0
  m_state->m_numPages = 0;
248
0
}
249
250
void WPS8Table::flushExtra()
251
0
{
252
0
  if (m_listener.get() == nullptr) return;
253
254
0
  for (auto const &table : m_state->m_tableMap)
255
0
  {
256
0
    if (table.second.m_parsed) continue;
257
0
    int strsid = m_mainParser.getTableSTRSId(table.second.m_id);
258
0
    if (strsid < 0) continue;
259
0
    sendTable(Vec2f(100.,100.),  table.second.m_id, strsid);
260
0
  }
261
0
}
262
263
////////////////////////////////////////////////////////////
264
// send a table id
265
////////////////////////////////////////////////////////////
266
bool WPS8Table::sendTable(Vec2f const &siz, int tableId, int strsid, bool inTextBox)
267
360
{
268
360
  if (!m_listener)
269
0
  {
270
0
    WPS_DEBUG_MSG(("WPS8Table::sendTable: listener is not set\n"));
271
0
    return true;
272
0
  }
273
360
  if (strsid <= 0)
274
0
  {
275
0
    WPS_DEBUG_MSG(("WPS8Table::sendTable: strsid is not set\n"));
276
0
    return false;
277
0
  }
278
279
360
  auto pos = m_state->m_tableMap.find(tableId);
280
360
  if (pos == m_state->m_tableMap.end())
281
49
  {
282
49
    WPS_DEBUG_MSG(("WPS8Table::sendTable: can not find table with id=%d\n", tableId));
283
49
    if (inTextBox)
284
0
      m_mainParser.send(strsid);
285
49
    else
286
49
    {
287
      // OK, we revert to a textbox inserted as a character
288
49
      WPSPosition tablePos(Vec2f(), siz);
289
49
      tablePos.m_anchorTo = WPSPosition::CharBaseLine;
290
49
      tablePos.m_wrapping = WPSPosition::WDynamic;
291
292
49
      m_mainParser.sendTextBox(tablePos, strsid);
293
49
    }
294
49
    return true;
295
49
  }
296
297
311
  auto &table = pos->second;
298
311
  if (table.m_parsed)
299
102
    WPS_DEBUG_MSG(("WPS8Table::sendTable: table with id=%d is already parsed\n", tableId));
300
209
  else
301
209
    table.m_parsed = true;
302
  // first we need to update the strsid
303
1.26k
  for (int c = 0; c < table.numCells(); c++)
304
951
  {
305
951
    WPSCellPtr cell = table.getCell(c);
306
951
    if (!cell) continue;
307
951
    reinterpret_cast<WPS8TableInternal::Cell *>(cell.get())->m_strsId = strsid;
308
951
  }
309
311
  if (!table.sendTable(m_listener))
310
157
    table.sendAsText(m_listener);
311
311
  return true;
312
360
}
313
314
////////////////////////////////////////////////////////////
315
// find all structures which correspond to the table
316
////////////////////////////////////////////////////////////
317
bool WPS8Table::readStructures(RVNGInputStreamPtr const &input)
318
9.83k
{
319
9.83k
  m_state->m_tableMap.clear();
320
321
9.83k
  auto const &nameTable = m_mainParser.getNameEntryMap();
322
9.83k
  auto pos = nameTable.lower_bound("MCLD");
323
1.30M
  while (pos != nameTable.end())
324
1.30M
  {
325
1.30M
    WPSEntry const &entry = pos++->second;
326
1.30M
    if (!entry.hasName("MCLD")) break;
327
1.29M
    if (!entry.hasType("MCLD")) continue;
328
329
1.03M
    readMCLD(input, entry);
330
1.03M
  }
331
332
9.83k
  return true;
333
9.83k
}
334
335
////////////////////////////////////////////////////////////
336
// low level
337
////////////////////////////////////////////////////////////
338
bool WPS8Table::readMCLD(RVNGInputStreamPtr input, WPSEntry const &entry)
339
1.03M
{
340
1.03M
  if (!entry.hasType(entry.name()))
341
0
  {
342
0
    WPS_DEBUG_MSG(("WPS8Table::readMCLD: warning: MCLD name=%s, type=%s\n",
343
0
                   entry.name().c_str(), entry.type().c_str()));
344
0
    return false;
345
0
  }
346
347
1.03M
  long page_offset = entry.begin();
348
1.03M
  long length = entry.length();
349
1.03M
  long endPage = entry.end();
350
351
1.03M
  if (length < 24)
352
34.6k
  {
353
34.6k
    WPS_DEBUG_MSG(("WPS8Table::readMCLD: warning: MCLD length=0x%lx\n", static_cast<unsigned long>(length)));
354
355
34.6k
    return false;
356
34.6k
  }
357
358
1.00M
  entry.setParsed();
359
1.00M
  input->seek(page_offset, librevenge::RVNG_SEEK_SET);
360
361
1.00M
  libwps::DebugStream f;
362
1.00M
  auto mZone = int(libwps::read32(input));
363
1.00M
  auto nTables = int(libwps::read32(input));
364
365
1.00M
  f << "maxUnknown=" << mZone << ", nTables= " << nTables;
366
1.00M
  if ((6+long(nTables)) * 4 > length) return false;
367
368
925k
  f << ", ids=(";
369
925k
  std::vector<int> listIds;
370
2.53M
  for (int i = 0; i < nTables; i++)
371
1.61M
  {
372
1.61M
    auto val = int(libwps::read32(input));
373
1.61M
    listIds.push_back(val);
374
1.61M
    f << val << ",";
375
1.61M
  }
376
925k
  f << ")";
377
378
925k
  ascii().addPos(page_offset);
379
925k
  ascii().addNote(f.str().c_str());
380
381
925k
  int mCounter = -1;
382
925k
  bool ok = true;
383
384
925k
  static char const *borderNames[] = { "T", "L", "R", "B" };
385
925k
  static int const borderPos[] =
386
925k
  { WPSBorder::Top, WPSBorder::Left, WPSBorder::Right, WPSBorder::Bottom};
387
925k
  static int const borderBit[] =
388
925k
  {
389
925k
    WPSBorder::TopBit, WPSBorder::LeftBit,
390
925k
    WPSBorder::RightBit, WPSBorder::BottomBit
391
925k
  };
392
925k
  long lastPosOk = input->tell();
393
1.21M
  while (input->tell() != endPage)
394
1.17M
  {
395
1.17M
    if (input->tell()+16 > endPage)
396
125k
    {
397
125k
      ok = false;
398
125k
      break;
399
125k
    }
400
401
1.04M
    mCounter++;
402
1.04M
    lastPosOk = input->tell();
403
404
1.04M
    WPS8Struct::FileData tableData;
405
1.04M
    auto sz = int(libwps::read16(input));
406
1.04M
    if (sz < 2 || lastPosOk+sz > endPage)
407
240k
    {
408
240k
      ok = false;
409
240k
      break;
410
240k
    }
411
412
805k
    std::string error;
413
805k
    if (!readBlockData(input, lastPosOk+sz,tableData, error))
414
771k
    {
415
771k
      f.str("");
416
771k
      f << tableData;
417
771k
      error = f.str();
418
771k
    }
419
420
805k
    f.str("");
421
805k
    int tableId = (mCounter < int(listIds.size())) ? listIds[size_t(mCounter)] : -1;
422
805k
    if (tableId < 0) f << "MCLD/Table[###unknownId]:";
423
177k
    else f << "MCLD/Table" << listIds[size_t(mCounter)]<<":";
424
425
805k
    auto N = int(libwps::readU32(input));
426
805k
    f << " nCells=" << N;
427
805k
    if (N < 0 || N > 100)
428
163k
    {
429
163k
      ok = false;
430
163k
      break;
431
163k
    }
432
433
642k
    WPS8TableInternal::Table table;
434
642k
    table.m_id = tableId;
435
436
    // point dim seems odd, we will need to update them
437
642k
    Vec2f totalRealDim(0,0), totalDataDim(0,0);
438
439
642k
    if (!tableData.m_recursData.empty())
440
331k
    {
441
331k
      f << ",(";
442
331k
      for (auto const &dt : tableData.m_recursData)
443
381k
      {
444
381k
        if (dt.isBad()) continue;
445
381k
        int const expectedTypes[] = { 2, 0x22 };
446
381k
        if (dt.id() < 0 || dt.id() > 1)
447
315k
        {
448
315k
          f << "##" << dt << ",";
449
315k
          continue;
450
315k
        }
451
66.3k
        if (expectedTypes[dt.id()]!=dt.type())
452
64.5k
        {
453
64.5k
          WPS_DEBUG_MSG(("WPS8Table::readMCLD: unexpected type for %d=%d\n", dt.id(), dt.type()));
454
64.5k
          f << "###" << dt << ",";
455
64.5k
          continue;
456
64.5k
        }
457
1.81k
        bool done = true;
458
1.81k
        switch (dt.id())
459
1.81k
        {
460
924
        case 0: // always set
461
924
          f << "f" << dt.id() << ", ";
462
924
          break;
463
886
        case 1: // always 0
464
886
          f << "f" << dt.id() << "=" << dt.m_value << ", ";
465
886
          break;
466
0
        default:
467
0
          done = false;
468
0
          break;
469
1.81k
        }
470
471
1.81k
        if (!done) f << "###" << dt << ",";
472
1.81k
      }
473
331k
      f << ")";
474
331k
    }
475
642k
    if (!error.empty()) f << ", ###err=" << error;
476
477
642k
    ascii().addPos(lastPosOk);
478
642k
    ascii().addNote(f.str().c_str());
479
480
1.39M
    for (size_t actualCell = 0; actualCell < size_t(N); actualCell++)
481
1.10M
    {
482
1.10M
      lastPosOk = input->tell();
483
1.10M
      sz = int(libwps::read16(input));
484
1.10M
      if (sz < 2 || lastPosOk+sz > endPage)
485
351k
      {
486
351k
        ok = false;
487
351k
        break;
488
351k
      }
489
490
755k
      WPS8Struct::FileData mainData;
491
755k
      error = "";
492
493
755k
      if (!readBlockData(input, lastPosOk+sz,mainData, error))
494
684k
      {
495
684k
        f.str("");
496
684k
        f << mainData;
497
684k
        error = f.str();
498
684k
      }
499
500
      // original position in point ( checkme)
501
755k
      float dim[4] = {  0, 0, 0, 0 };
502
503
755k
      f.str("");
504
755k
      f << "MCLD/Table";
505
755k
      if (tableId >= 0) f << tableId;
506
755k
      f << "(Cell" << actualCell <<"):";
507
508
755k
      auto cell = std::make_shared<WPS8TableInternal::Cell>(*this);
509
755k
      WPSCellPtr cellPtr(cell);
510
755k
      cell->m_id = int(actualCell);
511
512
755k
      libwps::DebugStream f2;
513
755k
      WPSColor cellColor[] = { WPSColor::black(), WPSColor::white() };
514
515
755k
      for (auto &dt : mainData.m_recursData)
516
650k
      {
517
650k
        if (dt.isBad()) continue;
518
650k
        if (m_state->m_MCLDTypes.find(dt.id())==m_state->m_MCLDTypes.end())
519
209k
        {
520
209k
          f << "##" << dt << ",";
521
209k
          continue;
522
209k
        }
523
441k
        if (m_state->m_MCLDTypes.find(dt.id())->second != dt.type())
524
340k
        {
525
340k
          WPS_DEBUG_MSG(("WPS8Table::readMCLD: unexpected type for %d=%d\n", dt.id(), dt.type()));
526
340k
          f << "###" << dt << ",";
527
340k
          continue;
528
340k
        }
529
530
100k
        bool done = true;
531
100k
        switch (dt.id())
532
100k
        {
533
2.34k
        case 0:
534
4.52k
        case 1:
535
6.82k
        case 2:
536
8.98k
        case 3: // min/max pos in point (96 dpi ?)
537
8.98k
          dim[dt.id()] = float(dt.m_value);
538
8.98k
          break;
539
2.16k
        case 4:
540
4.30k
        case 5: // look coherent with EOBJ info
541
4.30k
          if (dt.id() == 4) cell->m_size.setX(float(dt.m_value)/914400.f);
542
2.14k
          else cell->m_size.setY(float(dt.m_value)/914400.f);
543
4.30k
          break;
544
        // border size : unknown dim
545
        // [ 1, 3, 1, 3, ]
546
        // [ 0.666667, 1.33333, 0.666667, 1.33333, ]/30
547
2.12k
        case 6:
548
4.22k
        case 7:
549
6.32k
        case 8:
550
8.41k
        case 9:
551
8.41k
          cell->m_bordersSep[dt.id()-6] = float(dt.m_value)/914400.f;
552
8.41k
          break;
553
1.94k
        case 0xe: // always 0x20000000
554
1.94k
          if (dt.m_value != 0x20000000)
555
37
            f2 << "f" << dt.id() << "=" << std::hex << dt.m_value << std::dec << ",";
556
1.94k
          break;
557
1.89k
        case 0x12: //  0x0 or 0x997aa0 or 0x3fffe238 ?
558
1.89k
          f2 << "f" << dt.id() << "=" << std::hex << dt.m_value << std::dec << ",";
559
1.89k
          break;
560
1.88k
        case 0x13:   //find -1|6 here
561
1.88k
          f2 << "f" << dt.id() << "=" << int(int8_t(dt.m_value)) << ",";
562
1.88k
          break;
563
1.87k
        case 0x1d: // first color
564
3.74k
        case 0x1e: // second color
565
3.74k
          cellColor[dt.id()-0x1d] = dt.getRGBColor();
566
3.74k
          break;
567
1.77k
        case 0x1f:
568
1.77k
        {
569
1.77k
          float percent=0.5;
570
1.77k
          if (dt.m_value == 0) // no motif
571
1.69k
            break;
572
80
          if (dt.m_value >= 3 && dt.m_value <= 9)
573
34
            percent = float(dt.m_value)*0.1f; // gray motif
574
46
          else
575
46
            f2 << "backMotif=" << dt.m_value << ",";
576
80
          cell->setBackgroundColor(WPSColor::barycenter(percent,cellColor[0],1.f-percent,cellColor[1]));
577
80
          break;
578
1.77k
        }
579
        // the border color
580
1.87k
        case 0x20:
581
3.41k
        case 0x23:
582
4.90k
        case 0x26:
583
6.37k
        case 0x29:
584
6.37k
        {
585
6.37k
          int wh = (dt.id()-0x20)/3;
586
6.37k
          WPSBorder border = cell->borders()[size_t(borderPos[wh])];
587
6.37k
          border.m_color = dt.getRGBColor();
588
6.37k
          cell->setBorders(borderBit[wh], border);
589
6.37k
          break;
590
4.90k
        }
591
1.57k
        case 0x21:
592
2.96k
        case 0x24:
593
4.35k
        case 0x27:
594
5.72k
        case 0x2a:
595
5.72k
        {
596
5.72k
          std::string mess("");
597
5.72k
          int wh = (dt.id()-0x21)/3;
598
5.72k
          WPSBorder border = cell->borders()[size_t(borderPos[wh])];
599
5.72k
          dt.getBorderStyles(border.m_style, border.m_type, mess);
600
5.72k
          cell->setBorders(borderBit[wh], border);
601
5.72k
          if (mess.length())
602
0
            f2 << "bordStyle" << borderNames[wh] << "=[" << mess << "],";
603
5.72k
          break;
604
4.35k
        }
605
1.43k
        case 0x22:
606
2.82k
        case 0x25:
607
4.21k
        case 0x28:
608
5.58k
        case 0x2b: // often 20
609
5.58k
          f2 << "unknBord" << borderNames[(dt.id()-0x22)/3] << "=" << dt.m_value << ",";
610
5.58k
          break;
611
1.36k
        case 0x2c: // 1, 0, -1
612
1.36k
          switch (dt.m_value)
613
1.36k
          {
614
411
          case 0:
615
411
            break; // normal
616
940
          case 0xFF: // also unset, diff with value = 1 ?
617
940
            f2 << "#f" << dt.id() << "=" << std::hex << dt.m_value << std::dec << ",";
618
940
            WPS_FALLTHROUGH;
619
954
          case 1:
620
954
            cell->setVerticalSet(false);
621
954
            break;
622
1
          default:
623
1
            f2 << "f" << dt.id() << "=" << std::hex << dt.m_value << std::dec << ",";
624
1
            break;
625
1.36k
          }
626
1.36k
          break;
627
        // always 0,excepted 0x15 hich can be 0 or 1 ?
628
1.98k
        case 0xa:
629
3.94k
        case 0xb:
630
5.87k
        case 0xd:
631
7.79k
        case 0x11:
632
9.65k
        case 0x15:
633
11.5k
        case 0x16:
634
13.3k
        case 0x17:
635
13.3k
          if (dt.m_value == 0);
636
1.89k
          else if (dt.m_value > -10 && dt.m_value < 10)
637
1.85k
            f2 << "f" << dt.id() << "=" << dt.m_value << ",";
638
40
          else done = false;
639
13.3k
          break;
640
2.10k
        case 0x18:
641
2.10k
          switch (dt.m_value)
642
2.10k
          {
643
1.69k
          case 0:
644
1.69k
            cell->setVAlignment(WPSCellFormat::VALIGN_TOP);
645
1.69k
            break;
646
131
          case 1:
647
131
            cell->setVAlignment(WPSCellFormat::VALIGN_CENTER);
648
131
            break;
649
185
          case 2:
650
185
            cell->setVAlignment(WPSCellFormat::VALIGN_BOTTOM);
651
185
            break;
652
102
          default:
653
102
            if (dt.m_value > -10 && dt.m_value < 10)
654
0
              f2 << "f" << dt.id() << "=" << dt.m_value << ",";
655
102
            else
656
102
              done = false;
657
102
            break;
658
2.10k
          }
659
2.10k
          break;
660
27.0k
        case 0xc:
661
28.9k
        case 0x14:
662
30.7k
        case 0x19:
663
32.5k
        case 0x1a: // flag ?
664
32.5k
          if (dt.isTrue())
665
26.9k
            f2 << "f" << dt.id() << ", ";
666
5.59k
          else
667
5.59k
            f2 << "f" << dt.id() << "=false, ";
668
32.5k
          break;
669
0
        default:
670
0
          done = false;
671
0
          break;
672
100k
        }
673
674
100k
        if (!done)
675
142
          f2 << dt << ",";
676
100k
      }
677
678
755k
      cell->setBox(WPSBox2f(Vec2f(dim[1],dim[0]),Vec2f(dim[3],dim[2])));
679
755k
      totalRealDim += cell->m_size;
680
755k
      totalDataDim += cell->box().size();
681
755k
      table.add(cellPtr);
682
683
755k
      f << *cell;
684
755k
      if (!f2.str().empty())
685
0
        f << ", unk=(" << f2.str() << ")";
686
687
755k
      if (!error.empty()) f << ",###err=" << error;
688
755k
      input->seek(lastPosOk+sz, librevenge::RVNG_SEEK_SET);
689
690
755k
      ascii().addPos(lastPosOk);
691
755k
      ascii().addNote(f.str().c_str());
692
755k
    }
693
642k
    if (!ok) break;
694
695
290k
    float factor[2] = { 1, 1};
696
290k
    if (totalDataDim[0] > 0) factor[0] = 72.f*totalRealDim[0]/totalDataDim[0];
697
290k
    if (totalDataDim[1] > 0) factor[1] = 72.f*totalRealDim[1]/totalDataDim[1];
698
409k
    for (int c = 0; c < table.numCells(); c++)
699
119k
    {
700
119k
      auto cell = table.getCell(c);
701
119k
      if (!cell) continue;
702
119k
      WPSBox2f box=cell->box();
703
119k
      cell->setBox(WPSBox2f(Vec2f(box[0][0]*factor[0], box[0][1]*factor[1]),
704
119k
                            Vec2f(box[1][0]*factor[0], box[1][1]*factor[1])));
705
119k
    }
706
707
290k
    if (tableId >=0) m_state->m_tableMap[tableId] = table;
708
156k
    else
709
156k
    {
710
156k
      WPS_DEBUG_MSG(("WPS8Table::readMCLD: find a table with negative id\n"));
711
156k
    }
712
290k
  }
713
714
925k
  if (!ok)
715
880k
  {
716
880k
    WPS_DEBUG_MSG(("WPS8Table::readMCLD: stopped prematively"));
717
880k
    ascii().addPos(lastPosOk);
718
880k
    ascii().addNote("###MCLD");
719
880k
  }
720
925k
  return ok;
721
925k
}
722
// vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: