Coverage Report

Created: 2026-04-29 07:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libmwaw/src/lib/MsWksTable.cxx
Line
Count
Source
1
/* -*- Mode: C++; c-default-style: "k&r"; indent-tabs-mode: nil; tab-width: 2; c-basic-offset: 2 -*- */
2
3
/* libmwaw
4
* Version: MPL 2.0 / LGPLv2+
5
*
6
* The contents of this file are subject to the Mozilla Public License Version
7
* 2.0 (the "License"); you may not use this file except in compliance with
8
* the License or as specified alternatively below. You may obtain a copy of
9
* the License at http://www.mozilla.org/MPL/
10
*
11
* Software distributed under the License is distributed on an "AS IS" basis,
12
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13
* for the specific language governing rights and limitations under the
14
* License.
15
*
16
* Major Contributor(s):
17
* Copyright (C) 2002 William Lachance (wrlach@gmail.com)
18
* Copyright (C) 2002,2004 Marc Maurer (uwog@uwog.net)
19
* Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba@bluewin.ch)
20
* Copyright (C) 2006, 2007 Andrew Ziem
21
* Copyright (C) 2011, 2012 Alonso Laurent (alonso@loria.fr)
22
*
23
*
24
* All Rights Reserved.
25
*
26
* For minor contributions see the git repository.
27
*
28
* Alternatively, the contents of this file may be used under the terms of
29
* the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"),
30
* in which case the provisions of the LGPLv2+ are applicable
31
* instead of those above.
32
*/
33
34
#include <iomanip>
35
#include <iostream>
36
#include <map>
37
#include <sstream>
38
39
#include "libmwaw_internal.hxx"
40
41
#include "MWAWCell.hxx"
42
#include "MWAWListener.hxx"
43
#include "MWAWFont.hxx"
44
#include "MWAWFontConverter.hxx"
45
#include "MWAWGraphicStyle.hxx"
46
#include "MWAWParagraph.hxx"
47
#include "MWAWPictData.hxx"
48
#include "MWAWSubDocument.hxx"
49
#include "MWAWTable.hxx"
50
51
#include "MsWksGraph.hxx"
52
#include "MsWksDocument.hxx"
53
54
#include "MsWksTable.hxx"
55
56
/** Internal: the structures of a MsWksTable */
57
namespace MsWksTableInternal
58
{
59
////////////////////////////////////////
60
//! Internal: the chart of a MsWksTable
61
struct Chart {
62
  //! constructor
63
  explicit Chart(MsWksGraph::Style const &style)
64
5.64M
    : m_style(style)
65
5.64M
    , m_backgroundEntry()
66
5.64M
    , m_zoneId(-1)
67
5.64M
  {
68
16.9M
    for (auto &id : m_textZonesId) id=-1;
69
5.64M
  }
70
  //! empty constructor
71
  Chart()
72
862
    : m_style()
73
862
    , m_backgroundEntry()
74
862
    , m_zoneId(-1)
75
862
  {
76
2.58k
    for (auto &id : m_textZonesId) id=-1;
77
862
  }
78
79
  //! the graphic style
80
  MWAWGraphicStyle m_style;
81
  //! the three text pictures
82
  int m_textZonesId[3];
83
  //! the background entry
84
  MWAWEntry m_backgroundEntry;
85
  //! the chart zone id (in the graph parser )
86
  int m_zoneId;
87
};
88
89
90
////////////////////////////////////////
91
//! Internal: the table of a MsWksTable
92
struct Table {
93
  //! the cell content
94
  struct Cell {
95
    Cell()
96
37.0k
      : m_pos(-1,-1)
97
37.0k
      , m_font()
98
37.0k
      , m_text("")
99
37.0k
    {
100
37.0k
    }
101
    //! the cell position
102
    MWAWVec2i m_pos;
103
    //! the font
104
    MWAWFont m_font;
105
    //! the text
106
    std::string m_text;
107
  };
108
  //! constructor
109
  explicit Table(MsWksGraph::Style const &style)
110
206k
    : m_style(style)
111
206k
    , m_numRows(0)
112
206k
    , m_numCols(0)
113
206k
    , m_rowsDim()
114
206k
    , m_colsDim()
115
206k
    , m_font()
116
206k
    , m_cellsList()
117
206k
  {
118
206k
    m_style.m_surfaceColor = style.m_baseSurfaceColor;
119
206k
  }
120
  //! empty constructor
121
  Table()
122
112k
    : m_style()
123
112k
    , m_numRows(0)
124
112k
    , m_numCols(0)
125
112k
    ,  m_rowsDim()
126
112k
    , m_colsDim()
127
112k
    , m_font()
128
112k
    , m_cellsList()
129
112k
  {
130
112k
  }
131
132
  //! try to find a cell
133
  Cell const *getCell(MWAWVec2i const &pos) const
134
0
  {
135
0
    for (auto &cell : m_cellsList) {
136
0
      if (cell.m_pos == pos)
137
0
        return &cell;
138
0
    }
139
0
    return nullptr;
140
0
  }
141
142
  //! the graphic style
143
  MWAWGraphicStyle m_style;
144
  int m_numRows /** the number of rows*/, m_numCols/** the number of columns*/;
145
  std::vector<int> m_rowsDim/**the rows dimensions*/, m_colsDim/*the columns dimensions*/;
146
  //! the default font
147
  MWAWFont m_font;
148
  //! the list of cell
149
  std::vector<Cell> m_cellsList;
150
};
151
152
////////////////////////////////////////
153
//! Internal: the state of a MsWksTable
154
struct State {
155
  //! constructor
156
  State()
157
244k
    : m_version(-1)
158
244k
    , m_idChartMap()
159
244k
    , m_idTableMap()
160
244k
  {
161
244k
  }
162
163
  //! the version
164
  int m_version;
165
166
  //! the map id->chart
167
  std::map<int, Chart> m_idChartMap;
168
  //! the map id->table
169
  std::map<int, Table> m_idTableMap;
170
};
171
172
}
173
174
////////////////////////////////////////////////////////////
175
// constructor/destructor, ...
176
////////////////////////////////////////////////////////////
177
MsWksTable::MsWksTable(MWAWParser &parser, MsWksDocument &zone, MsWksGraph &graph)
178
244k
  : m_parserState(parser.getParserState())
179
244k
  , m_state(new MsWksTableInternal::State)
180
244k
  , m_mainParser(&parser)
181
244k
  , m_graphParser(&graph)
182
244k
  , m_zone(zone)
183
244k
{
184
244k
}
185
186
MsWksTable::~MsWksTable()
187
244k
{ }
188
189
int MsWksTable::version() const
190
6.61M
{
191
6.61M
  if (m_state->m_version < 0)
192
3.03k
    m_state->m_version = m_parserState->m_version;
193
6.61M
  return m_state->m_version;
194
6.61M
}
195
196
////////////////////////////////////////////////////////////
197
// table
198
////////////////////////////////////////////////////////////
199
bool MsWksTable::sendTable(int zoneId)
200
4.47k
{
201
4.47k
  MWAWListenerPtr listener=m_parserState->getMainListener();
202
4.47k
  if (!listener) return false;
203
204
4.47k
  if (m_state->m_idTableMap.find(zoneId)==m_state->m_idTableMap.end()) {
205
0
    MWAW_DEBUG_MSG(("MsWksTable::sendTable: can not find textbox %d\n", zoneId));
206
0
    return false;
207
0
  }
208
4.47k
  if (m_parserState->m_type==MWAWParserState::Spreadsheet) {
209
    /* inserting a table may cause problem when there happens in some
210
       ods file, so... */
211
3
    MWAW_DEBUG_MSG(("MsWksTable::sendTable: inserting a table in a spreadsheet is not implemented\n"));
212
3
    return false;
213
3
  }
214
215
4.47k
  auto &table = m_state->m_idTableMap.find(zoneId)->second;
216
217
  // open the table
218
4.47k
  size_t nCols = table.m_colsDim.size();
219
4.47k
  size_t nRows = table.m_rowsDim.size();
220
4.47k
  if (!nCols || !nRows) {
221
4.47k
    MWAW_DEBUG_MSG(("MsWksTable::sendTable: problem with dimensions\n"));
222
4.47k
    return false;
223
4.47k
  }
224
0
  std::vector<float> colsDims(nCols);
225
0
  for (size_t c = 0; c < nCols; c++) colsDims[c] = float(table.m_colsDim[c]);
226
0
  MWAWTable theTable(MWAWTable::TableDimBit);
227
0
  theTable.setColsSize(colsDims);
228
0
  listener->openTable(theTable);
229
230
0
  int const borderPos = libmwaw::TopBit | libmwaw::RightBit |
231
0
                        libmwaw::BottomBit | libmwaw::LeftBit;
232
0
  MWAWBorder border, internBorder;
233
0
  internBorder.m_width=0.5;
234
0
  internBorder.m_color=MWAWColor(0xC0,0xC0,0xC0);
235
0
  MWAWParagraph para;
236
0
  para.m_justify=MWAWParagraph::JustificationCenter;
237
0
  for (size_t row = 0; row < nRows; row++) {
238
0
    listener->openTableRow(float(table.m_rowsDim[row]), librevenge::RVNG_POINT);
239
240
0
    for (size_t col = 0; col < nCols; col++) {
241
0
      MWAWCell cell;
242
0
      MWAWVec2i cellPosition(MWAWVec2i(static_cast<int>(col),static_cast<int>(row)));
243
0
      cell.setPosition(cellPosition);
244
0
      cell.setBorders(borderPos, border);
245
0
      int internWhat=0;
246
0
      if (col!=0) internWhat|=libmwaw::LeftBit;
247
0
      if (col+1!=nCols) internWhat|=libmwaw::RightBit;
248
0
      if (row!=0) internWhat|=libmwaw::TopBit;
249
0
      if (row+1!=nRows) internWhat|=libmwaw::BottomBit;
250
0
      cell.setBorders(internWhat, internBorder);
251
0
      if (!table.m_style.m_surfaceColor.isWhite())
252
0
        cell.setBackgroundColor(table.m_style.m_surfaceColor);
253
0
      listener->openTableCell(cell);
254
0
      listener->setParagraph(para);
255
256
0
      auto const *tCell=table.getCell(cellPosition);
257
0
      if (tCell) {
258
0
        listener->setFont(tCell->m_font);
259
0
        size_t nChar = tCell->m_text.size();
260
0
        for (size_t ch = 0; ch < nChar; ch++) {
261
0
          auto c = static_cast<unsigned char>(tCell->m_text[ch]);
262
0
          switch (c) {
263
0
          case 0x9:
264
0
            MWAW_DEBUG_MSG(("MsWksTable::sendTable: find a tab\n"));
265
0
            listener->insertChar(' ');
266
0
            break;
267
0
          case 0xd:
268
0
            listener->insertEOL();
269
0
            break;
270
0
          default:
271
0
            listener->insertCharacter(c);
272
0
            break;
273
0
          }
274
0
        }
275
0
      }
276
277
0
      listener->closeTableCell();
278
0
    }
279
0
    listener->closeTableRow();
280
0
  }
281
282
  // close the table
283
0
  listener->closeTable();
284
0
  return true;
285
0
}
286
287
bool MsWksTable::readTable(int numCol, int numRow, int zoneId, MsWksGraph::Style const &style)
288
206k
{
289
206k
  int vers=version();
290
206k
  MWAWInputStreamPtr input=m_zone.getInput();
291
206k
  long actPos = input->tell();
292
206k
  libmwaw::DebugFile &ascFile = m_zone.ascii();
293
206k
  libmwaw::DebugStream f, f2;
294
206k
  f << "Entries(Table): ";
295
296
206k
  MsWksTableInternal::Table table(style);
297
206k
  table.m_numRows=numRow;
298
206k
  table.m_numCols=numCol;
299
  // first we read the dim
300
543k
  for (int i = 0; i < 2; i++) {
301
393k
    auto &dim = i==0 ? table.m_rowsDim : table.m_colsDim;
302
393k
    dim.resize(0);
303
393k
    auto sz = static_cast<int>(input->readLong(4));
304
393k
    if (i == 0 && sz != 2*table.m_numRows) return false;
305
374k
    if (i == 1 && sz != 2*table.m_numCols) return false;
306
307
340k
    if (i == 0) f << "rowS=(";
308
152k
    else f << "colS=(";
309
310
410k
    for (int j = 0; j < sz/2; j++) {
311
73.5k
      auto val = static_cast<int>(input->readLong(2));
312
313
73.5k
      if (val < -10) return false;
314
315
70.4k
      dim.push_back(val);
316
70.4k
      f << val << ",";
317
70.4k
    }
318
336k
    f << "), ";
319
336k
  }
320
321
149k
  long sz = input->readLong(4);
322
149k
  f << "szOfCells=" << sz;
323
149k
  ascFile.addPos(actPos);
324
149k
  ascFile.addNote(f.str().c_str());
325
326
149k
  actPos = input->tell();
327
149k
  long endPos = actPos+sz;
328
  // now we read the data for each size
329
149k
  while (input->tell() != endPos) {
330
37.0k
    f.str("");
331
37.0k
    actPos = input->tell();
332
37.0k
    MsWksTableInternal::Table::Cell cell;
333
37.0k
    auto y = static_cast<int>(input->readLong(2));
334
37.0k
    auto x = static_cast<int>(input->readLong(2));
335
37.0k
    cell.m_pos = MWAWVec2i(x,y);
336
37.0k
    if (x < 0 || y < 0 ||
337
37.0k
        x >= table.m_numCols || y >= table.m_numRows) return false;
338
339
0
    f << "Table:("<< cell.m_pos << "):";
340
0
    auto nbChar = static_cast<int>(input->readLong(1));
341
0
    if (nbChar < 0 || actPos+5+nbChar > endPos) return false;
342
343
0
    std::string fName("");
344
0
    for (int c = 0; c < nbChar; c++)
345
0
      fName +=char(input->readLong(1));
346
347
0
    input->seek(actPos+34, librevenge::RVNG_SEEK_SET);
348
0
    f << std::hex << "unk=" << input->readLong(2) << ", "; // 0|827
349
0
    auto v = static_cast<int>(input->readLong(2));
350
0
    if (v) f << "f0=" << v << ", ";
351
0
    auto fSize = static_cast<int>(input->readLong(2));
352
0
    v = static_cast<int>(input->readLong(2));
353
0
    if (v) f2 << "unkn0=" << v << ", ";
354
0
    auto fFlags = static_cast<int>(input->readLong(2));
355
356
0
    nbChar = static_cast<int>(input->readLong(4));
357
0
    if (nbChar <= 0 || input->tell()+nbChar > endPos) return false;
358
359
0
    v = static_cast<int>(input->readLong(2));
360
0
    if (v) f << "f1=" << v << ", ";
361
0
    auto fColors = static_cast<int>(input->readLong(2));
362
0
    v = static_cast<int>(input->readLong(2));
363
0
    if (v) f << "f2=" << v << ", ";
364
0
    auto bgColors = static_cast<int>(input->readLong(2));
365
0
    if (bgColors)
366
0
      f2 << std::dec << "bgColorId(?)=" << bgColors << ", "; // indexed
367
368
0
    cell.m_font=MWAWFont(m_parserState->m_fontConverter->getId(fName), float(fSize));
369
0
    uint32_t flags = 0;
370
0
    if (fFlags & 0x1) flags |= MWAWFont::boldBit;
371
0
    if (fFlags & 0x2) flags |= MWAWFont::italicBit;
372
0
    if (fFlags & 0x4) cell.m_font.setUnderlineStyle(MWAWFont::Line::Simple);
373
0
    if (fFlags & 0x8) flags |= MWAWFont::embossBit;
374
0
    if (fFlags & 0x10) flags |= MWAWFont::shadowBit;
375
0
    if (fFlags & 0x20) {
376
0
      if (vers==1)
377
0
        cell.m_font.set(MWAWFont::Script(20,librevenge::RVNG_PERCENT,80));
378
0
      else
379
0
        cell.m_font.set(MWAWFont::Script::super100());
380
0
    }
381
0
    if (fFlags & 0x40) {
382
0
      if (vers==1)
383
0
        cell.m_font.set(MWAWFont::Script(-20,librevenge::RVNG_PERCENT,80));
384
0
      else
385
0
        cell.m_font.set(MWAWFont::Script::sub100());
386
0
    }
387
0
    cell.m_font.setFlags(flags);
388
389
0
    if (fColors != 0xFF) {
390
0
      MWAWColor col;
391
0
      if (m_zone.getColor(fColors,col,3))
392
0
        cell.m_font.setColor(col);
393
0
      else
394
0
        f << "#colId=" << fColors << ",";
395
0
    }
396
0
    f << "[" << cell.m_font.getDebugString(m_parserState->m_fontConverter) << "," << f2.str()<< "],";
397
    // check what happens, if the size of text is greater than 4
398
0
    for (int c = 0; c < nbChar; c++)
399
0
      cell.m_text+=char(input->readLong(1));
400
0
    f << cell.m_text;
401
402
0
    table.m_cellsList.push_back(cell);
403
404
0
    ascFile.addPos(actPos);
405
0
    ascFile.addNote(f.str().c_str());
406
0
  }
407
112k
  if (m_state->m_idTableMap.find(zoneId)!=m_state->m_idTableMap.end()) {
408
0
    MWAW_DEBUG_MSG(("MsWksTable::readTable: oops a table with id=%d already exists\n", zoneId));
409
0
  }
410
112k
  else
411
112k
    m_state->m_idTableMap[zoneId]=table;
412
112k
  return true;
413
149k
}
414
415
////////////////////////////////////////////////////////////
416
// chart
417
////////////////////////////////////////////////////////////
418
419
void MsWksTable::setChartZoneId(int chartId, int zoneId)
420
862
{
421
862
  if (m_state->m_idChartMap.find(chartId)==m_state->m_idChartMap.end()) {
422
0
    MWAW_DEBUG_MSG(("MsWksTable::setChartZoneId: can not find chart %d\n", chartId));
423
0
    return;
424
0
  }
425
862
  auto &chart = m_state->m_idChartMap.find(chartId)->second;
426
862
  chart.m_zoneId = zoneId;
427
862
}
428
429
bool MsWksTable::sendChart(int chartId)
430
4
{
431
4
  MWAWListenerPtr listener=m_parserState->getMainListener();
432
4
  if (!listener) {
433
0
    MWAW_DEBUG_MSG(("MsWksTable::sendChart: can not find a listener\n"));
434
0
    return false;
435
0
  }
436
4
  if (m_state->m_idChartMap.find(chartId)==m_state->m_idChartMap.end()) {
437
0
    MWAW_DEBUG_MSG(("MsWksTable::sendChart: can not find chart %d\n", chartId));
438
0
    return false;
439
0
  }
440
4
  auto &chart = m_state->m_idChartMap.find(chartId)->second;
441
442
4
  MWAWInputStreamPtr input=m_zone.getInput();
443
4
  MWAWPosition chartPos;
444
4
  if (chart.m_zoneId < 0 || !m_graphParser->getZonePosition(chart.m_zoneId, MWAWPosition::Frame, chartPos)) {
445
0
    MWAW_DEBUG_MSG(("MsWksTable::sendChart: oops can not find chart bdbox %d[%d]\n", chartId, chart.m_zoneId));
446
0
    return false;
447
0
  }
448
4
  MWAWPosition pictPos(MWAWVec2f(0,0), chartPos.size(),librevenge::RVNG_POINT);
449
4
  pictPos.setRelativePosition(MWAWPosition::Frame, MWAWPosition::XLeft, MWAWPosition::YTop);
450
4
  if (chart.m_backgroundEntry.valid()) {
451
0
    long actPos = input->tell();
452
#ifdef DEBUG_WITH_FILES
453
    if (1) {
454
      librevenge::RVNGBinaryData file;
455
      input->seek(chart.m_backgroundEntry.begin(), librevenge::RVNG_SEEK_SET);
456
      input->readDataBlock(chart.m_backgroundEntry.length(), file);
457
      static int volatile pictName = 0;
458
      libmwaw::DebugStream f;
459
      f << "Pict-" << ++pictName << ".pct";
460
      libmwaw::Debug::dumpFile(file, f.str().c_str());
461
    }
462
#endif
463
464
0
    input->seek(chart.m_backgroundEntry.begin(), librevenge::RVNG_SEEK_SET);
465
0
    MWAWBox2f naturalBox;
466
0
    auto res = MWAWPictData::check(input, static_cast<int>(chart.m_backgroundEntry.length()), naturalBox);
467
0
    if (res == MWAWPict::MWAW_R_BAD) {
468
0
      MWAW_DEBUG_MSG(("MsWksTable::sendChart: can not find the picture\n"));
469
0
    }
470
0
    else {
471
0
      input->seek(chart.m_backgroundEntry.begin(), librevenge::RVNG_SEEK_SET);
472
0
      std::shared_ptr<MWAWPict> pict(MWAWPictData::get(input, static_cast<int>(chart.m_backgroundEntry.length())));
473
474
0
      MWAWEmbeddedObject picture;
475
0
      if (pict && pict->getBinary(picture))
476
0
        listener->insertPicture(pictPos, picture);
477
0
    }
478
0
    input->seek(actPos, librevenge::RVNG_SEEK_SET);
479
0
  }
480
16
  for (int i=0; i < 3; i++) {
481
12
    int cId=chart.m_textZonesId[i];
482
12
    MWAWPosition childPos;
483
12
    if (!m_graphParser->getZonePosition(cId, MWAWPosition::Frame, childPos)) {
484
0
      MWAW_DEBUG_MSG(("MsWksTable::sendChart: oops can not find chart bdbox for child %d[%d]\n", i, cId));
485
0
      continue;
486
0
    }
487
12
    MWAWPosition textPos(pictPos);
488
12
    textPos.setOrigin(childPos.origin()-chartPos.origin());
489
12
    textPos.setSize(childPos.size());
490
12
    m_graphParser->send(cId, textPos);
491
12
  }
492
493
4
  return true;
494
4
}
495
496
bool MsWksTable::readChart(int chartId, MsWksGraph::Style const &style)
497
6.40M
{
498
  // checkme: works for some chart, but not sure that it can work for all chart...
499
6.40M
  MWAWInputStreamPtr input=m_zone.getInput();
500
6.40M
  long pos = input->tell();
501
6.40M
  int const vers=version();
502
6.40M
  if (vers<=2 || (vers==3&&m_parserState->m_type!=MWAWParserState::Spreadsheet) ||
503
6.14M
      !input->checkPosition(pos+306))
504
758k
    return false;
505
506
5.64M
  libmwaw::DebugFile &ascFile = m_zone.ascii();
507
5.64M
  libmwaw::DebugStream f;
508
5.64M
  f << "Entries(Chart):";
509
510
5.64M
  MsWksTableInternal::Chart chart(style);
511
5.64M
  auto val = static_cast<int>(input->readLong(2));
512
5.64M
  switch (val) {
513
469k
  case 1:
514
469k
    f << "bar,";
515
469k
    break;
516
19.1k
  case 2:
517
19.1k
    f << "stacked,";
518
19.1k
    break;
519
725k
  case 3:
520
725k
    f << "line,";
521
725k
    break; // checkme
522
171
  case 4:
523
171
    f << "combo,";
524
171
    break; // checkme
525
259
  case 5:
526
259
    f << "pie,";
527
259
    break; // checkme
528
50.2k
  case 6:
529
50.2k
    f << "hi-lo-choose,";
530
50.2k
    break; // checkme
531
4.38M
  default:
532
4.38M
    f << "#type=val";
533
4.38M
    break;
534
5.64M
  }
535
28.2M
  for (int i = 0; i < 4; i++) {
536
22.5M
    val = static_cast<int>(input->readLong(2));
537
22.5M
    if (val) f << "col" << i << "=" << val << ",";
538
22.5M
  }
539
5.64M
  f << "rows=";
540
16.9M
  for (int i = 0; i < 2; i++) {
541
11.2M
    val = static_cast<int>(input->readLong(2));
542
11.2M
    f << val;
543
11.2M
    if (i==0) f << "-";
544
5.64M
    else f << ",";
545
11.2M
  }
546
5.64M
  val = static_cast<int>(input->readLong(2));
547
5.64M
  if (val) f << "colLabels=" << val << ",";
548
5.64M
  val = static_cast<int>(input->readLong(2));
549
5.64M
  if (val) f << "rowLabels=" << val << ",";
550
5.64M
  std::string name("");
551
5.64M
  auto sz = static_cast<int>(input->readULong(1));
552
5.64M
  if (sz > 31) {
553
305k
    MWAW_DEBUG_MSG(("MsWksTable::readChart: string size is too long\n"));
554
305k
    return false;
555
305k
  }
556
11.3M
  for (int i = 0; i < sz; i++) {
557
6.74M
    auto c = char(input->readLong(1));
558
6.74M
    if (!c) break;
559
5.99M
    name+=c;
560
5.99M
  }
561
5.34M
  f << name << ",";
562
5.34M
  input->seek(pos+50, librevenge::RVNG_SEEK_SET);
563
689M
  for (int i = 0; i < 128; i++) { // always 0 ?
564
684M
    val = static_cast<int>(input->readLong(2));
565
684M
    if (val) f << "g" << i << "=" << val << std::dec << ",";
566
684M
  }
567
5.34M
  ascFile.addPos(pos);
568
5.34M
  ascFile.addNote(f.str().c_str());
569
570
5.34M
  pos = input->tell();
571
5.34M
  ascFile.addPos(pos);
572
5.34M
  ascFile.addNote("Chart(II)");
573
5.34M
  input->seek(vers==3 ? 1992 : 2428, librevenge::RVNG_SEEK_CUR);
574
575
  // three textbox
576
15.0M
  for (int i = 0; i < 3; i++) {
577
12.7M
    pos = input->tell();
578
12.7M
    MWAWEntry childZone;
579
12.7M
    chart.m_textZonesId[i] = m_graphParser->getEntryPicture(-9999, childZone, false, i+2);
580
12.7M
    if (chart.m_textZonesId[i]<0) {
581
3.04M
      MWAW_DEBUG_MSG(("MsWksTable::readChart: can not find textbox\n"));
582
3.04M
      input->seek(pos, librevenge::RVNG_SEEK_SET);
583
3.04M
      return false;
584
3.04M
    }
585
12.7M
  }
586
  // the background picture
587
2.29M
  pos = input->tell();
588
2.29M
  auto dataSz = long(input->readULong(4));
589
2.29M
  auto smDataSz = long(input->readULong(2));
590
2.29M
  if (!dataSz || (dataSz&0xFFFF) != smDataSz || !input->checkPosition(pos+4+dataSz))
591
    // background picture not always present ( at least in v3)
592
2.17M
    input->seek(pos, librevenge::RVNG_SEEK_SET);
593
124k
  else {
594
124k
    MWAWEntry &background=chart.m_backgroundEntry;
595
124k
    background.setBegin(pos+4);
596
124k
    background.setLength(dataSz);
597
124k
    ascFile.skipZone(background.begin(), background.end()-1);
598
599
124k
    ascFile.addPos(pos);
600
124k
    ascFile.addNote("Chart(picture)");
601
124k
    input->seek(background.end(), librevenge::RVNG_SEEK_SET);
602
124k
  }
603
  // last the value ( by columns ? )
604
3.45M
  for (int i = 0; i < 4; i++) {
605
3.45M
    pos = input->tell();
606
3.45M
    dataSz = long(input->readULong(4));
607
3.45M
    if (dataSz > input->size() - pos - 4)
608
2.43M
      dataSz = input->size() - pos - 4;
609
3.45M
    if (dataSz%0x10) {
610
2.29M
      MWAW_DEBUG_MSG(("MsWksTable::readChart: can not read end last zone\n"));
611
2.29M
      input->seek(pos, librevenge::RVNG_SEEK_SET);
612
2.29M
      return false;
613
2.29M
    }
614
1.16M
    f.str("");
615
1.16M
    f << "Chart(A" << i << ")";
616
1.16M
    ascFile.addPos(pos);
617
1.16M
    ascFile.addNote(f.str().c_str());
618
1.16M
    auto numLine = int(dataSz/0x10);
619
2.56M
    for (int l = 0; l < numLine; l++) {
620
1.40M
      f.str("");
621
1.40M
      f << "Chart(A" << i << "-" << l << ")";
622
1.40M
      ascFile.addPos(pos+4+0x10*l);
623
1.40M
      ascFile.addNote(f.str().c_str());
624
1.40M
    }
625
1.16M
    if (input->seek(pos+4+dataSz, librevenge::RVNG_SEEK_SET) != 0) {
626
0
      MWAW_DEBUG_MSG(("MsWksTable::readChart: reading past the end\n"));
627
0
      return false;
628
0
    }
629
1.16M
  }
630
862
  if (m_state->m_idChartMap.find(chartId)!=m_state->m_idChartMap.end()) {
631
0
    MWAW_DEBUG_MSG(("MsWksTable::readChart: oops a chart with id=%d already exists\n", chartId));
632
0
  }
633
862
  else
634
862
    m_state->m_idChartMap[chartId]=chart;
635
862
  return true;
636
2.29M
}
637
638
// vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: