Coverage Report

Created: 2026-04-29 07:28

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
214k
    : WPSCell()
52
214k
    , m_tableParser(parser)
53
214k
    , m_id(-1)
54
214k
    , m_strsId(-1)
55
214k
    , m_size()
56
214k
  {
57
214k
    WPSBorder emptyBorder;
58
214k
    emptyBorder.m_style = WPSBorder::None;
59
214k
    m_bordersList.resize(4, emptyBorder);
60
857k
    for (float &i : m_bordersSep) i = 0.0;
61
214k
  }
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
481
  {
70
481
    if (!listener) return true;
71
481
    auto *listen=dynamic_cast<WPSContentListener *>(listener.get());
72
481
    if (!listen)
73
0
    {
74
0
      WPS_DEBUG_MSG(("WPS8TableInternal::Cell::send: unexpected listener\n"));
75
0
      return true;
76
0
    }
77
481
    listen->openTableCell(*this);
78
481
    sendContent(listener);
79
481
    listen->closeTableCell();
80
481
    return true;
81
481
  }
82
83
  //! call when the content of a cell must be send
84
  bool sendContent(WPSListenerPtr &) final
85
1.06k
  {
86
1.06k
    m_tableParser.sendTextInCell(m_strsId, m_id);
87
1.06k
    return true;
88
1.06k
  }
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
214k
{
103
214k
}
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
339k
    : m_id(-1)
134
339k
    , m_parsed(false) {}
135
44.6k
  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
339k
{
149
339k
}
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
9.45k
    : m_version(-1)
170
9.45k
    , m_numPages(0)
171
9.45k
    , m_tableMap()
172
9.45k
    , m_MCLDTypes()
173
9.45k
  {
174
9.45k
    initTypeMaps();
175
9.45k
  }
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
9.45k
{
191
9.45k
  static int const MCLDTypes[] =
192
9.45k
  {
193
9.45k
    0, 0x22, 1, 0x22, 2, 0x22, 3, 0x22, 4, 0x22, 5, 0x22, 6, 0x22, 7, 0x22,
194
9.45k
    8, 0x22, 9, 0x22, 0xa, 0x22, 0xb, 0x1a, 0xc, 0x2, 0xd, 0x22, 0xe, 0x22,
195
9.45k
    0x11, 0x22, 0x12, 0x22, 0x13, 0x12, 0x14, 0x2, 0x15, 0x22, 0x16, 0x22, 0x17, 0x22,
196
9.45k
    0x18, 0x22, 0x19, 0x2, 0x1a, 0x2, 0x1d, 0x22, 0x1e, 0x22, 0x1f, 0x12,
197
9.45k
    0x20, 0x22, 0x21, 0x12, 0x22, 0x22, 0x23, 0x22, 0x24, 0x12, 0x25, 0x22, 0x26, 0x22, 0x27, 0x12,
198
9.45k
    0x28, 0x22, 0x29, 0x22, 0x2a, 0x12, 0x2b, 0x22, 0x2c, 0x12,
199
9.45k
    0x31, 0x18
200
9.45k
  };
201
406k
  for (int i = 0; i+1 < int(WPS_N_ELEMENTS(MCLDTypes)); i+=2)
202
397k
    m_MCLDTypes[MCLDTypes[i]] = MCLDTypes[i+1];
203
204
9.45k
}
205
}
206
207
////////////////////////////////////////////////////////////
208
// constructor/destructor
209
////////////////////////////////////////////////////////////
210
WPS8Table::WPS8Table(WPS8Parser &parser)
211
9.45k
  : m_listener()
212
9.45k
  , m_mainParser(parser)
213
9.45k
  , m_state(new WPS8TableInternal::State)
214
9.45k
  , m_asciiFile(parser.ascii())
215
9.45k
{
216
9.45k
}
217
218
WPS8Table::~WPS8Table()
219
9.45k
{
220
9.45k
}
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
8.15k
{
234
8.15k
  return m_state->m_numPages;
235
8.15k
}
236
237
void WPS8Table::sendTextInCell(int strsId, int cellId)
238
1.06k
{
239
1.06k
  m_mainParser.sendTextInCell(strsId, cellId);
240
1.06k
}
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
426
{
268
426
  if (!m_listener)
269
0
  {
270
0
    WPS_DEBUG_MSG(("WPS8Table::sendTable: listener is not set\n"));
271
0
    return true;
272
0
  }
273
426
  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
426
  auto pos = m_state->m_tableMap.find(tableId);
280
426
  if (pos == m_state->m_tableMap.end())
281
35
  {
282
35
    WPS_DEBUG_MSG(("WPS8Table::sendTable: can not find table with id=%d\n", tableId));
283
35
    if (inTextBox)
284
0
      m_mainParser.send(strsid);
285
35
    else
286
35
    {
287
      // OK, we revert to a textbox inserted as a character
288
35
      WPSPosition tablePos(Vec2f(), siz);
289
35
      tablePos.m_anchorTo = WPSPosition::CharBaseLine;
290
35
      tablePos.m_wrapping = WPSPosition::WDynamic;
291
292
35
      m_mainParser.sendTextBox(tablePos, strsid);
293
35
    }
294
35
    return true;
295
35
  }
296
297
391
  auto &table = pos->second;
298
391
  if (table.m_parsed)
299
120
    WPS_DEBUG_MSG(("WPS8Table::sendTable: table with id=%d is already parsed\n", tableId));
300
271
  else
301
271
    table.m_parsed = true;
302
  // first we need to update the strsid
303
1.57k
  for (int c = 0; c < table.numCells(); c++)
304
1.18k
  {
305
1.18k
    WPSCellPtr cell = table.getCell(c);
306
1.18k
    if (!cell) continue;
307
1.18k
    reinterpret_cast<WPS8TableInternal::Cell *>(cell.get())->m_strsId = strsid;
308
1.18k
  }
309
391
  if (!table.sendTable(m_listener))
310
181
    table.sendAsText(m_listener);
311
391
  return true;
312
426
}
313
314
////////////////////////////////////////////////////////////
315
// find all structures which correspond to the table
316
////////////////////////////////////////////////////////////
317
bool WPS8Table::readStructures(RVNGInputStreamPtr const &input)
318
8.15k
{
319
8.15k
  m_state->m_tableMap.clear();
320
321
8.15k
  auto const &nameTable = m_mainParser.getNameEntryMap();
322
8.15k
  auto pos = nameTable.lower_bound("MCLD");
323
884k
  while (pos != nameTable.end())
324
884k
  {
325
884k
    WPSEntry const &entry = pos++->second;
326
884k
    if (!entry.hasName("MCLD")) break;
327
876k
    if (!entry.hasType("MCLD")) continue;
328
329
689k
    readMCLD(input, entry);
330
689k
  }
331
332
8.15k
  return true;
333
8.15k
}
334
335
////////////////////////////////////////////////////////////
336
// low level
337
////////////////////////////////////////////////////////////
338
bool WPS8Table::readMCLD(RVNGInputStreamPtr input, WPSEntry const &entry)
339
689k
{
340
689k
  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
689k
  long page_offset = entry.begin();
348
689k
  long length = entry.length();
349
689k
  long endPage = entry.end();
350
351
689k
  if (length < 24)
352
47.8k
  {
353
47.8k
    WPS_DEBUG_MSG(("WPS8Table::readMCLD: warning: MCLD length=0x%lx\n", static_cast<unsigned long>(length)));
354
355
47.8k
    return false;
356
47.8k
  }
357
358
641k
  entry.setParsed();
359
641k
  input->seek(page_offset, librevenge::RVNG_SEEK_SET);
360
361
641k
  libwps::DebugStream f;
362
641k
  auto mZone = int(libwps::read32(input));
363
641k
  auto nTables = int(libwps::read32(input));
364
365
641k
  f << "maxUnknown=" << mZone << ", nTables= " << nTables;
366
641k
  if ((6+long(nTables)) * 4 > length) return false;
367
368
556k
  f << ", ids=(";
369
556k
  std::vector<int> listIds;
370
1.27M
  for (int i = 0; i < nTables; i++)
371
718k
  {
372
718k
    auto val = int(libwps::read32(input));
373
718k
    listIds.push_back(val);
374
718k
    f << val << ",";
375
718k
  }
376
556k
  f << ")";
377
378
556k
  ascii().addPos(page_offset);
379
556k
  ascii().addNote(f.str().c_str());
380
381
556k
  int mCounter = -1;
382
556k
  bool ok = true;
383
384
556k
  static char const *borderNames[] = { "T", "L", "R", "B" };
385
556k
  static int const borderPos[] =
386
556k
  { WPSBorder::Top, WPSBorder::Left, WPSBorder::Right, WPSBorder::Bottom};
387
556k
  static int const borderBit[] =
388
556k
  {
389
556k
    WPSBorder::TopBit, WPSBorder::LeftBit,
390
556k
    WPSBorder::RightBit, WPSBorder::BottomBit
391
556k
  };
392
556k
  long lastPosOk = input->tell();
393
705k
  while (input->tell() != endPage)
394
683k
  {
395
683k
    if (input->tell()+16 > endPage)
396
45.0k
    {
397
45.0k
      ok = false;
398
45.0k
      break;
399
45.0k
    }
400
401
638k
    mCounter++;
402
638k
    lastPosOk = input->tell();
403
404
638k
    WPS8Struct::FileData tableData;
405
638k
    auto sz = int(libwps::read16(input));
406
638k
    if (sz < 2 || lastPosOk+sz > endPage)
407
197k
    {
408
197k
      ok = false;
409
197k
      break;
410
197k
    }
411
412
441k
    std::string error;
413
441k
    if (!readBlockData(input, lastPosOk+sz,tableData, error))
414
414k
    {
415
414k
      f.str("");
416
414k
      f << tableData;
417
414k
      error = f.str();
418
414k
    }
419
420
441k
    f.str("");
421
441k
    int tableId = (mCounter < int(listIds.size())) ? listIds[size_t(mCounter)] : -1;
422
441k
    if (tableId < 0) f << "MCLD/Table[###unknownId]:";
423
87.9k
    else f << "MCLD/Table" << listIds[size_t(mCounter)]<<":";
424
425
441k
    auto N = int(libwps::readU32(input));
426
441k
    f << " nCells=" << N;
427
441k
    if (N < 0 || N > 100)
428
103k
    {
429
103k
      ok = false;
430
103k
      break;
431
103k
    }
432
433
337k
    WPS8TableInternal::Table table;
434
337k
    table.m_id = tableId;
435
436
    // point dim seems odd, we will need to update them
437
337k
    Vec2f totalRealDim(0,0), totalDataDim(0,0);
438
439
337k
    if (!tableData.m_recursData.empty())
440
97.7k
    {
441
97.7k
      f << ",(";
442
97.7k
      for (auto const &dt : tableData.m_recursData)
443
126k
      {
444
126k
        if (dt.isBad()) continue;
445
126k
        int const expectedTypes[] = { 2, 0x22 };
446
126k
        if (dt.id() < 0 || dt.id() > 1)
447
120k
        {
448
120k
          f << "##" << dt << ",";
449
120k
          continue;
450
120k
        }
451
5.50k
        if (expectedTypes[dt.id()]!=dt.type())
452
3.74k
        {
453
3.74k
          WPS_DEBUG_MSG(("WPS8Table::readMCLD: unexpected type for %d=%d\n", dt.id(), dt.type()));
454
3.74k
          f << "###" << dt << ",";
455
3.74k
          continue;
456
3.74k
        }
457
1.76k
        bool done = true;
458
1.76k
        switch (dt.id())
459
1.76k
        {
460
917
        case 0: // always set
461
917
          f << "f" << dt.id() << ", ";
462
917
          break;
463
848
        case 1: // always 0
464
848
          f << "f" << dt.id() << "=" << dt.m_value << ", ";
465
848
          break;
466
0
        default:
467
0
          done = false;
468
0
          break;
469
1.76k
        }
470
471
1.76k
        if (!done) f << "###" << dt << ",";
472
1.76k
      }
473
97.7k
      f << ")";
474
97.7k
    }
475
337k
    if (!error.empty()) f << ", ###err=" << error;
476
477
337k
    ascii().addPos(lastPosOk);
478
337k
    ascii().addNote(f.str().c_str());
479
480
551k
    for (size_t actualCell = 0; actualCell < size_t(N); actualCell++)
481
403k
    {
482
403k
      lastPosOk = input->tell();
483
403k
      sz = int(libwps::read16(input));
484
403k
      if (sz < 2 || lastPosOk+sz > endPage)
485
189k
      {
486
189k
        ok = false;
487
189k
        break;
488
189k
      }
489
490
214k
      WPS8Struct::FileData mainData;
491
214k
      error = "";
492
493
214k
      if (!readBlockData(input, lastPosOk+sz,mainData, error))
494
169k
      {
495
169k
        f.str("");
496
169k
        f << mainData;
497
169k
        error = f.str();
498
169k
      }
499
500
      // original position in point ( checkme)
501
214k
      float dim[4] = {  0, 0, 0, 0 };
502
503
214k
      f.str("");
504
214k
      f << "MCLD/Table";
505
214k
      if (tableId >= 0) f << tableId;
506
214k
      f << "(Cell" << actualCell <<"):";
507
508
214k
      auto cell = std::make_shared<WPS8TableInternal::Cell>(*this);
509
214k
      WPSCellPtr cellPtr(cell);
510
214k
      cell->m_id = int(actualCell);
511
512
214k
      libwps::DebugStream f2;
513
214k
      WPSColor cellColor[] = { WPSColor::black(), WPSColor::white() };
514
515
214k
      for (auto &dt : mainData.m_recursData)
516
319k
      {
517
319k
        if (dt.isBad()) continue;
518
319k
        if (m_state->m_MCLDTypes.find(dt.id())==m_state->m_MCLDTypes.end())
519
60.7k
        {
520
60.7k
          f << "##" << dt << ",";
521
60.7k
          continue;
522
60.7k
        }
523
259k
        if (m_state->m_MCLDTypes.find(dt.id())->second != dt.type())
524
164k
        {
525
164k
          WPS_DEBUG_MSG(("WPS8Table::readMCLD: unexpected type for %d=%d\n", dt.id(), dt.type()));
526
164k
          f << "###" << dt << ",";
527
164k
          continue;
528
164k
        }
529
530
94.5k
        bool done = true;
531
94.5k
        switch (dt.id())
532
94.5k
        {
533
2.25k
        case 0:
534
4.36k
        case 1:
535
6.55k
        case 2:
536
8.62k
        case 3: // min/max pos in point (96 dpi ?)
537
8.62k
          dim[dt.id()] = float(dt.m_value);
538
8.62k
          break;
539
2.04k
        case 4:
540
4.09k
        case 5: // look coherent with EOBJ info
541
4.09k
          if (dt.id() == 4) cell->m_size.setX(float(dt.m_value)/914400.f);
542
2.05k
          else cell->m_size.setY(float(dt.m_value)/914400.f);
543
4.09k
          break;
544
        // border size : unknown dim
545
        // [ 1, 3, 1, 3, ]
546
        // [ 0.666667, 1.33333, 0.666667, 1.33333, ]/30
547
2.03k
        case 6:
548
4.06k
        case 7:
549
6.08k
        case 8:
550
8.09k
        case 9:
551
8.09k
          cell->m_bordersSep[dt.id()-6] = float(dt.m_value)/914400.f;
552
8.09k
          break;
553
1.86k
        case 0xe: // always 0x20000000
554
1.86k
          if (dt.m_value != 0x20000000)
555
47
            f2 << "f" << dt.id() << "=" << std::hex << dt.m_value << std::dec << ",";
556
1.86k
          break;
557
1.81k
        case 0x12: //  0x0 or 0x997aa0 or 0x3fffe238 ?
558
1.81k
          f2 << "f" << dt.id() << "=" << std::hex << dt.m_value << std::dec << ",";
559
1.81k
          break;
560
1.80k
        case 0x13:   //find -1|6 here
561
1.80k
          f2 << "f" << dt.id() << "=" << int(int8_t(dt.m_value)) << ",";
562
1.80k
          break;
563
1.77k
        case 0x1d: // first color
564
3.55k
        case 0x1e: // second color
565
3.55k
          cellColor[dt.id()-0x1d] = dt.getRGBColor();
566
3.55k
          break;
567
1.68k
        case 0x1f:
568
1.68k
        {
569
1.68k
          float percent=0.5;
570
1.68k
          if (dt.m_value == 0) // no motif
571
1.60k
            break;
572
81
          if (dt.m_value >= 3 && dt.m_value <= 9)
573
32
            percent = float(dt.m_value)*0.1f; // gray motif
574
49
          else
575
49
            f2 << "backMotif=" << dt.m_value << ",";
576
81
          cell->setBackgroundColor(WPSColor::barycenter(percent,cellColor[0],1.f-percent,cellColor[1]));
577
81
          break;
578
1.68k
        }
579
        // the border color
580
1.84k
        case 0x20:
581
3.51k
        case 0x23:
582
5.09k
        case 0x26:
583
6.63k
        case 0x29:
584
6.63k
        {
585
6.63k
          int wh = (dt.id()-0x20)/3;
586
6.63k
          WPSBorder border = cell->borders()[size_t(borderPos[wh])];
587
6.63k
          border.m_color = dt.getRGBColor();
588
6.63k
          cell->setBorders(borderBit[wh], border);
589
6.63k
          break;
590
5.09k
        }
591
1.60k
        case 0x21:
592
3.10k
        case 0x24:
593
4.58k
        case 0x27:
594
6.06k
        case 0x2a:
595
6.06k
        {
596
6.06k
          std::string mess("");
597
6.06k
          int wh = (dt.id()-0x21)/3;
598
6.06k
          WPSBorder border = cell->borders()[size_t(borderPos[wh])];
599
6.06k
          dt.getBorderStyles(border.m_style, border.m_type, mess);
600
6.06k
          cell->setBorders(borderBit[wh], border);
601
6.06k
          if (mess.length())
602
0
            f2 << "bordStyle" << borderNames[wh] << "=[" << mess << "],";
603
6.06k
          break;
604
4.58k
        }
605
1.53k
        case 0x22:
606
3.03k
        case 0x25:
607
4.51k
        case 0x28:
608
5.98k
        case 0x2b: // often 20
609
5.98k
          f2 << "unknBord" << borderNames[(dt.id()-0x22)/3] << "=" << dt.m_value << ",";
610
5.98k
          break;
611
1.46k
        case 0x2c: // 1, 0, -1
612
1.46k
          switch (dt.m_value)
613
1.46k
          {
614
327
          case 0:
615
327
            break; // normal
616
1.13k
          case 0xFF: // also unset, diff with value = 1 ?
617
1.13k
            f2 << "#f" << dt.id() << "=" << std::hex << dt.m_value << std::dec << ",";
618
1.13k
            WPS_FALLTHROUGH;
619
1.13k
          case 1:
620
1.13k
            cell->setVerticalSet(false);
621
1.13k
            break;
622
2
          default:
623
2
            f2 << "f" << dt.id() << "=" << std::hex << dt.m_value << std::dec << ",";
624
2
            break;
625
1.46k
          }
626
1.46k
          break;
627
        // always 0,excepted 0x15 hich can be 0 or 1 ?
628
1.92k
        case 0xa:
629
3.81k
        case 0xb:
630
5.67k
        case 0xd:
631
7.51k
        case 0x11:
632
9.29k
        case 0x15:
633
11.0k
        case 0x16:
634
12.8k
        case 0x17:
635
12.8k
          if (dt.m_value == 0);
636
1.81k
          else if (dt.m_value > -10 && dt.m_value < 10)
637
1.77k
            f2 << "f" << dt.id() << "=" << dt.m_value << ",";
638
41
          else done = false;
639
12.8k
          break;
640
1.83k
        case 0x18:
641
1.83k
          switch (dt.m_value)
642
1.83k
          {
643
1.61k
          case 0:
644
1.61k
            cell->setVAlignment(WPSCellFormat::VALIGN_TOP);
645
1.61k
            break;
646
87
          case 1:
647
87
            cell->setVAlignment(WPSCellFormat::VALIGN_CENTER);
648
87
            break;
649
39
          case 2:
650
39
            cell->setVAlignment(WPSCellFormat::VALIGN_BOTTOM);
651
39
            break;
652
87
          default:
653
87
            if (dt.m_value > -10 && dt.m_value < 10)
654
0
              f2 << "f" << dt.id() << "=" << dt.m_value << ",";
655
87
            else
656
87
              done = false;
657
87
            break;
658
1.83k
          }
659
1.83k
          break;
660
22.9k
        case 0xc:
661
24.6k
        case 0x14:
662
26.4k
        case 0x19:
663
28.1k
        case 0x1a: // flag ?
664
28.1k
          if (dt.isTrue())
665
22.8k
            f2 << "f" << dt.id() << ", ";
666
5.36k
          else
667
5.36k
            f2 << "f" << dt.id() << "=false, ";
668
28.1k
          break;
669
0
        default:
670
0
          done = false;
671
0
          break;
672
94.5k
        }
673
674
94.5k
        if (!done)
675
128
          f2 << dt << ",";
676
94.5k
      }
677
678
214k
      cell->setBox(WPSBox2f(Vec2f(dim[1],dim[0]),Vec2f(dim[3],dim[2])));
679
214k
      totalRealDim += cell->m_size;
680
214k
      totalDataDim += cell->box().size();
681
214k
      table.add(cellPtr);
682
683
214k
      f << *cell;
684
214k
      if (!f2.str().empty())
685
0
        f << ", unk=(" << f2.str() << ")";
686
687
214k
      if (!error.empty()) f << ",###err=" << error;
688
214k
      input->seek(lastPosOk+sz, librevenge::RVNG_SEEK_SET);
689
690
214k
      ascii().addPos(lastPosOk);
691
214k
      ascii().addNote(f.str().c_str());
692
214k
    }
693
337k
    if (!ok) break;
694
695
148k
    float factor[2] = { 1, 1};
696
148k
    if (totalDataDim[0] > 0) factor[0] = 72.f*totalRealDim[0]/totalDataDim[0];
697
148k
    if (totalDataDim[1] > 0) factor[1] = 72.f*totalRealDim[1]/totalDataDim[1];
698
183k
    for (int c = 0; c < table.numCells(); c++)
699
35.1k
    {
700
35.1k
      auto cell = table.getCell(c);
701
35.1k
      if (!cell) continue;
702
35.1k
      WPSBox2f box=cell->box();
703
35.1k
      cell->setBox(WPSBox2f(Vec2f(box[0][0]*factor[0], box[0][1]*factor[1]),
704
35.1k
                            Vec2f(box[1][0]*factor[0], box[1][1]*factor[1])));
705
35.1k
    }
706
707
148k
    if (tableId >=0) m_state->m_tableMap[tableId] = table;
708
103k
    else
709
103k
    {
710
103k
      WPS_DEBUG_MSG(("WPS8Table::readMCLD: find a table with negative id\n"));
711
103k
    }
712
148k
  }
713
714
556k
  if (!ok)
715
534k
  {
716
534k
    WPS_DEBUG_MSG(("WPS8Table::readMCLD: stopped prematively"));
717
534k
    ascii().addPos(lastPosOk);
718
534k
    ascii().addNote("###MCLD");
719
534k
  }
720
556k
  return ok;
721
556k
}
722
// vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: