Coverage Report

Created: 2026-10-28 06:34

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libmwaw/src/lib/MacWrtProStructures.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 <algorithm>
35
#include <iomanip>
36
#include <iostream>
37
#include <limits>
38
#include <map>
39
#include <set>
40
#include <sstream>
41
42
#include <librevenge/librevenge.h>
43
44
#include "MWAWCell.hxx"
45
#include "MWAWTextListener.hxx"
46
#include "MWAWFont.hxx"
47
#include "MWAWFontConverter.hxx"
48
#include "MWAWHeader.hxx"
49
#include "MWAWParagraph.hxx"
50
#include "MWAWPosition.hxx"
51
#include "MWAWSection.hxx"
52
#include "MWAWTable.hxx"
53
54
#include "MacWrtProStructures.hxx"
55
#include "MacWrtProParser.hxx"
56
57
/** Internal: the structures of a MacWrtProStructures */
58
namespace MacWrtProStructuresInternal
59
{
60
//! Internal: the graphic structure
61
struct Graphic {
62
  enum Type { UNKNOWN, GRAPHIC, TEXT, NOTE };
63
  //! the constructor
64
  explicit Graphic(int vers)
65
77.2k
    : m_version(vers)
66
77.2k
    , m_type(-1)
67
77.2k
    , m_contentType(UNKNOWN)
68
77.2k
    , m_fileBlock(0)
69
77.2k
    , m_id(-1)
70
77.2k
    , m_attachment(false)
71
77.2k
    , m_page(-1)
72
77.2k
    , m_box()
73
77.2k
    , m_textPos(0)
74
    // II
75
77.2k
    , m_textboxType(0)
76
77.2k
    , m_headerFooterFlag(0)
77
77.2k
    , m_column(1)
78
77.2k
    , m_colSeparator(0)
79
77.2k
    , m_lastFlag(0)
80
    // 1 or 1.5
81
77.2k
    , m_baseline(0.)
82
77.2k
    , m_surfaceColor(MWAWColor::white())
83
77.2k
    , m_lineBorder()
84
77.2k
    , m_isHeader(false)
85
77.2k
    , m_row(0)
86
77.2k
    , m_col(0)
87
77.2k
    , m_textboxCellType(0)
88
    // all
89
77.2k
    , m_extra("")
90
77.2k
    , m_send(false)
91
77.2k
  {
92
309k
    for (auto &w : m_borderWList) w= 0;
93
77.2k
  }
94
95
  //! operator<<
96
  friend std::ostream &operator<<(std::ostream &o, Graphic const &bl)
97
0
  {
98
0
    if (bl.m_version==0) {
99
0
      switch (std::abs(bl.m_type)) {
100
0
      case 3:
101
0
        o << "textbox,";
102
0
        break;
103
0
      default:
104
0
        o << "type=" << bl.m_type << ",";
105
0
        break;
106
0
      }
107
0
      switch (bl.m_textboxType) {
108
0
      case 1: // a header zone
109
0
        o << "header,";
110
0
        break;
111
0
      case 2: // a footer zone
112
0
        o << "footer,";
113
0
        break;
114
0
      case 3: // a footnote zone
115
0
        o << "footnote,";
116
0
        break;
117
0
      case 0:
118
0
        break;
119
0
      default:
120
0
        MWAW_DEBUG_MSG(("MacWrtProStructures::Graphic::operator<<: find unknown textbox type\n"));
121
0
        o << "##fram[type]=" << bl.m_textboxType << ",";
122
0
        break;
123
0
      }
124
0
      switch (bl.m_headerFooterFlag) {
125
0
      case 1:
126
0
        o << "left[page],";
127
0
        break;
128
0
      case 2:
129
0
        o << "right[page],";
130
0
        break;
131
0
      case 3:
132
0
        o << "###page=" << bl.m_headerFooterFlag << ",";
133
0
        break;
134
0
      case 0:
135
0
      default: // all
136
0
        break;
137
0
      }
138
0
      if (bl.m_textPos) o << "textPos=" << bl.m_textPos << ",";
139
0
      if (bl.m_type<0) o << "background,";
140
0
    }
141
0
    else {
142
0
      switch (bl.m_contentType) {
143
0
      case GRAPHIC:
144
0
        o << "graphic,";
145
0
        if (bl.m_type != 8) {
146
0
          MWAW_DEBUG_MSG(("MacWrtProStructuresInternal::Graphic::operator<< unknown type\n"));
147
0
          o << "#type=" << bl.m_type << ",";
148
0
        }
149
0
        break;
150
0
      case NOTE:
151
0
        o << "note";
152
0
        break;
153
0
      case TEXT:
154
0
        o << "text";
155
0
        switch (bl.m_type) {
156
0
        case 3:
157
0
          o << "[table]";
158
0
          break;
159
0
        case 4:
160
0
          o << "[textbox/cell/note]";
161
0
          break;
162
0
        case 5:
163
0
          if (bl.m_textPos) o << "[pageBreak:" << bl.m_textPos << "]";
164
0
          break;
165
0
        case 6:
166
0
          if (bl.m_isHeader)
167
0
            o << "[header]";
168
0
          else
169
0
            o << "[footer]";
170
0
          break;
171
0
        case 7:
172
0
          o << "[footnote]";
173
0
          break;
174
0
        case 8:
175
0
          o << "[empty frame]";
176
0
          break;
177
0
        default:
178
0
          // v2: -1: can be the document zone, but not always
179
0
          MWAW_DEBUG_MSG(("MacWrtProStructuresInternal::Graphic::operator<< unknown type\n"));
180
0
          o << "[#" << bl.m_type << "]";
181
0
          break;
182
0
        }
183
0
        o << ",";
184
0
        break;
185
0
      case UNKNOWN:
186
0
#if !defined(__clang__)
187
0
      default:
188
0
#endif
189
0
        break;
190
0
      }
191
0
    }
192
0
    if (bl.m_column>1) {
193
0
      o << "col[num]=" << bl.m_column << ",";
194
0
      o << "col[sep]=" << bl.m_colSeparator << ",";
195
0
    }
196
0
    if (bl.m_id >= 0) o << "id=" << bl.m_id << ",";
197
0
    o << "box=" << bl.m_box << ",";
198
0
    static char const* const wh[] = { "L", "R", "T", "B" };
199
0
    if (bl.hasSameBorders()) {
200
0
      if (bl.m_borderWList[0] > 0)
201
0
        o << "bord[width]=" << bl.m_borderWList[0] << ",";
202
0
    }
203
0
    else {
204
0
      for (int i = 0; i < 4; ++i) {
205
0
        if (bl.m_borderWList[i] <= 0)
206
0
          continue;
207
0
        o << "bord" << wh[i] << "[width]=" << bl.m_borderWList[i] << ",";
208
0
      }
209
0
    }
210
0
    if (bl.m_contentType==TEXT && bl.m_type==4) {
211
0
      for (int i = 0; i < 4; ++i)
212
0
        o << "bord" << wh[i] << "[cell]=[" << bl.m_borderCellList[i] << "],";
213
0
    }
214
0
    if (bl.m_baseline < 0 || bl.m_baseline >0) o << "baseline=" << bl.m_baseline << ",";
215
0
    if (!bl.m_surfaceColor.isWhite())
216
0
      o << "col=" << bl.m_surfaceColor << ",";
217
0
    if (!bl.m_lineBorder.isEmpty())
218
0
      o << "line=" << bl.m_lineBorder << ",";
219
0
    if (bl.m_fileBlock > 0) o << "block=" << std::hex << bl.m_fileBlock << std::dec << ",";
220
0
    if (bl.m_extra.length())
221
0
      o << bl.m_extra << ",";
222
0
    return o;
223
0
  }
224
  //! update the style to include frame style
225
  void fillFrame(MWAWGraphicStyle &style) const
226
10.1k
  {
227
10.1k
    if (!m_surfaceColor.isWhite())
228
776
      style.setBackgroundColor(m_surfaceColor);
229
10.1k
    if (!hasBorders())
230
7.30k
      return;
231
14.0k
    for (int w=0; w < 4; ++w) {
232
11.2k
      MWAWBorder border(m_lineBorder);
233
11.2k
      border.m_width=m_borderWList[w]; // ok also for setAll
234
11.2k
      if (border.isEmpty())
235
2.68k
        continue;
236
8.55k
      static int const wh[] = { libmwaw::LeftBit, libmwaw::RightBit, libmwaw::TopBit, libmwaw::BottomBit};
237
8.55k
      style.setBorders(wh[w], border);
238
8.55k
    }
239
2.80k
  }
240
241
  //! returns true is this is a graphic zone
242
  bool isGraphic() const
243
113k
  {
244
113k
    return m_fileBlock > 0 && m_contentType == GRAPHIC;
245
113k
  }
246
  //! returns true is this is a text zone (or a not)
247
  bool isText() const
248
142k
  {
249
142k
    return m_fileBlock > 0 && (m_contentType == TEXT || m_contentType == NOTE);
250
142k
  }
251
  //! returns true is this is a table zone
252
  bool isTable() const
253
0
  {
254
0
    return m_fileBlock <= 0 && m_type == 3;
255
0
  }
256
  bool hasSameBorders() const
257
0
  {
258
0
    for (int i=1; i < 4; ++i) {
259
0
      if (m_borderWList[i] > m_borderWList[0] ||
260
0
          m_borderWList[i] < m_borderWList[0])
261
0
        return false;
262
0
    }
263
0
    return true;
264
0
  }
265
  bool hasBorders() const
266
10.1k
  {
267
10.1k
    if (m_lineBorder.m_color.isWhite() || m_lineBorder.isEmpty())
268
6.90k
      return false;
269
5.72k
    for (auto w : m_borderWList) {
270
5.72k
      if (w > 0)
271
2.80k
        return true;
272
5.72k
    }
273
393
    return false;
274
3.20k
  }
275
276
  MWAWPosition getPosition() const
277
12.1k
  {
278
12.1k
    MWAWPosition res;
279
12.1k
    if (m_attachment) {
280
2.13k
      res = MWAWPosition(MWAWVec2f(0,0), m_box.size(), librevenge::RVNG_POINT);
281
2.13k
      res.setRelativePosition(MWAWPosition::Char, MWAWPosition::XLeft, getRelativeYPos());
282
2.13k
    }
283
10.0k
    else {
284
10.0k
      res = MWAWPosition(m_box.min(), m_box.size(), librevenge::RVNG_POINT);
285
10.0k
      res.setRelativePosition(MWAWPosition::Page);
286
10.0k
      res.setPage(m_page);
287
10.0k
      res.m_wrapping = m_contentType==NOTE ? MWAWPosition::WRunThrough :
288
10.0k
                       MWAWPosition::WDynamic;
289
10.0k
    }
290
12.1k
    return res;
291
12.1k
  }
292
293
  MWAWPosition::YPos getRelativeYPos() const
294
2.13k
  {
295
2.13k
    float height = m_box.size()[1];
296
2.13k
    if (m_baseline < 0.25f*height) return MWAWPosition::YBottom;
297
489
    if (m_baseline < 0.75f*height) return MWAWPosition::YCenter;
298
463
    return MWAWPosition::YTop;
299
489
  }
300
  bool contains(MWAWBox2f const &box) const
301
11.1k
  {
302
11.1k
    return box[0][0] >= m_box[0][0] && box[0][1] >= m_box[0][1] &&
303
10.6k
           box[1][0] <= m_box[1][0] && box[1][1] <= m_box[1][1];
304
11.1k
  }
305
  bool intersects(MWAWBox2f const &box) const
306
12.2k
  {
307
12.2k
    if (box[0][0] >= m_box[1][0] || box[0][1] >= m_box[1][1] ||
308
9.30k
        box[1][0] <= m_box[0][0] || box[1][1] <= m_box[0][1])
309
12.1k
      return false;
310
134
    return true;
311
12.2k
  }
312
313
  //! the version
314
  int m_version;
315
316
  //! the type
317
  int m_type;
318
319
  //! the type 1.0 or 1.5
320
  Type m_contentType;
321
322
  //! the file block id
323
  int m_fileBlock;
324
325
  //! the graphic id
326
  int m_id;
327
328
  //! true if this is an attachment 1.0 or 1.5
329
  bool m_attachment;
330
331
  //! the page (if absolute)
332
  int m_page;
333
334
  //! the bdbox
335
  MWAWBox2f m_box;
336
337
  /** filled for pagebreak pos */
338
  int m_textPos;
339
340
  // vII
341
342
  //! the header footer type
343
  int m_textboxType;
344
  //! the header footer flag
345
  int m_headerFooterFlag;
346
347
  //! the number of columns
348
  int m_column;
349
  //! the columns separator
350
  float m_colSeparator;
351
352
353
  /** the last flag */
354
  int m_lastFlag;
355
356
  //
357
  //    v1.0 or v.15
358
  //
359
360
  //! the borders width
361
  double m_borderWList[4];
362
363
  //! the cell borders
364
  MWAWBorder m_borderCellList[4];
365
366
  //! the baseline ( in point 0=bottom aligned)
367
  float m_baseline;
368
369
  //! the background color
370
  MWAWColor m_surfaceColor;
371
372
  //! the line border
373
  MWAWBorder m_lineBorder;
374
375
  /** filled for header/footer */
376
  bool m_isHeader;
377
378
  /** number of row, filled for table */
379
  int m_row;
380
381
  /** number of columns, filled for table */
382
  int m_col;
383
384
  /** filled for textbox : 0: unknown/textbox, 1: cell, 2: textbox(opened)*/
385
  int m_textboxCellType;
386
387
  //! extra data
388
  std::string m_extra;
389
390
  //! true if we have send the data
391
  bool m_send;
392
};
393
394
//! Internal: a page
395
struct Page {
396
  //! the constructor
397
  Page()
398
10.6M
    : m_page(-1)
399
10.6M
    , m_graphicsList()
400
10.6M
    , m_extra("")
401
10.6M
    , m_send(false)
402
10.6M
  {
403
10.6M
  }
404
  //! operator<<
405
  friend std::ostream &operator<<(std::ostream &o, Page const &bl)
406
0
  {
407
0
    if (bl.m_page > 0) o << "page=" << bl.m_page << ",";
408
0
    if (bl.m_extra.length())
409
0
      o << bl.m_extra << ",";
410
0
    return o;
411
0
  }
412
  //! the page (if absolute)
413
  int m_page;
414
  //! the graphic list
415
  std::vector<std::shared_ptr<Graphic> > m_graphicsList;
416
  //! extra data
417
  std::string m_extra;
418
419
  //! true if we have send the data
420
  bool m_send;
421
};
422
423
////////////////////////////////////////
424
//! Internal: the fonts
425
struct Font {
426
  //! the constructor
427
  Font()
428
594k
    : m_font()
429
594k
    , m_flags(0)
430
594k
    , m_token(-1)
431
594k
  {
432
2.97M
    for (auto &val : m_values) val = 0;
433
594k
  }
434
  //! operator<<
435
  friend std::ostream &operator<<(std::ostream &o, Font const &font)
436
0
  {
437
0
    if (font.m_flags) o << "flags=" << std::hex << font.m_flags << std::dec << ",";
438
0
    for (int i = 0; i < 5; ++i) {
439
0
      if (!font.m_values[i]) continue;
440
0
      o << "f" << i << "=" << font.m_values[i] << ",";
441
0
    }
442
0
    switch (font.m_token) {
443
0
    case -1:
444
0
      break;
445
0
    default:
446
0
      o << "token=" << font.m_token << ",";
447
0
      break;
448
0
    }
449
0
    return o;
450
0
  }
451
452
  //! the font
453
  MWAWFont m_font;
454
  //! some unknown flag
455
  int m_flags;
456
  //! the token type(checkme)
457
  int m_token;
458
  //! unknown values
459
  int m_values[5];
460
};
461
462
////////////////////////////////////////
463
/** Internal: class to store the paragraph properties */
464
struct Paragraph final : public MWAWParagraph {
465
  //! Constructor
466
  Paragraph()
467
284k
    :  m_value(0)
468
284k
  {
469
284k
  }
470
212k
  Paragraph(Paragraph const &)=default;
471
  Paragraph &operator=(Paragraph const &)=default;
472
142k
  Paragraph &operator=(Paragraph &&)=default;
473
  //! destructor
474
  ~Paragraph() final;
475
  //! operator<<
476
  friend std::ostream &operator<<(std::ostream &o, Paragraph const &ind)
477
0
  {
478
0
    o << static_cast<MWAWParagraph const &>(ind);
479
0
    if (ind.m_value) o << "unkn=" << ind.m_value << ",";
480
0
    return o;
481
0
  }
482
  //! a unknown value
483
  int m_value;
484
};
485
486
Paragraph::~Paragraph()
487
497k
{
488
497k
}
489
490
////////////////////////////////////////
491
//! Internal: the cell of a MacWrtProStructure
492
struct Cell final : public MWAWCell {
493
  //! constructor
494
  Cell(MacWrtProStructures &parser, Graphic *graphic)
495
9.29k
    : MWAWCell()
496
9.29k
    , m_parser(parser)
497
9.29k
    , m_graphicId(0)
498
9.29k
  {
499
9.29k
    if (!graphic) return;
500
9.29k
    setBdBox(MWAWBox2f(graphic->m_box.min(), graphic->m_box.max()-MWAWVec2f(1,1)));
501
9.29k
    setBackgroundColor(graphic->m_surfaceColor);
502
9.29k
    m_graphicId = graphic->m_id;
503
46.4k
    for (int b=0; b<4; ++b) {
504
37.1k
      int const wh[4] = { libmwaw::LeftBit, libmwaw::RightBit,
505
37.1k
                          libmwaw::TopBit, libmwaw::BottomBit
506
37.1k
                        };
507
37.1k
      setBorders(wh[b], graphic->m_borderCellList[b]);
508
37.1k
    }
509
9.29k
  }
510
  //! destructor
511
  ~Cell() final;
512
  //! send the content
513
  bool sendContent(MWAWListenerPtr listener, MWAWTable &) final
514
10.0k
  {
515
10.0k
    if (m_graphicId > 0)
516
9.85k
      m_parser.send(m_graphicId);
517
190
    else if (listener) // try to avoid empty cell
518
190
      listener->insertChar(' ');
519
10.0k
    return true;
520
10.0k
  }
521
522
  //! the text parser
523
  MacWrtProStructures &m_parser;
524
  //! the graphic id
525
  int m_graphicId;
526
};
527
528
Cell::~Cell()
529
9.29k
{
530
9.29k
}
531
532
////////////////////////////////////////
533
////////////////////////////////////////
534
struct Table final : public MWAWTable {
535
  //! constructor
536
2.94k
  Table() : MWAWTable()
537
2.94k
  {
538
2.94k
  }
539
  //! destructor
540
  ~Table() final;
541
  //! return a cell corresponding to id
542
  Cell *get(int id)
543
0
  {
544
0
    if (id < 0 || id >= numCells()) {
545
0
      MWAW_DEBUG_MSG(("MacWrtProStructuresInternal::Table::get: cell %d does not exists\n",id));
546
0
      return nullptr;
547
0
    }
548
0
    return static_cast<Cell *>(MWAWTable::get(id).get());
549
0
  }
550
};
551
552
Table::~Table()
553
2.94k
{
554
2.94k
}
555
556
////////////////////////////////////////
557
//! Internal: the section of a MacWrtProStructures
558
struct Section {
559
  enum StartType { S_Line, S_Page, S_PageLeft, S_PageRight };
560
561
  //! constructor
562
  Section()
563
29.9k
    : m_start(S_Page)
564
29.9k
    , m_colsPos()
565
29.9k
    , m_textLength(0)
566
29.9k
    , m_extra("")
567
29.9k
  {
568
59.9k
    for (auto &id : m_headerIds) id=0;
569
59.9k
    for (auto &id : m_footerIds) id=0;
570
29.9k
  }
571
  //! returns a MWAWSection
572
  MWAWSection getSection() const
573
13.1k
  {
574
13.1k
    MWAWSection sec;
575
13.1k
    size_t numCols=m_colsPos.size()/2;
576
13.1k
    if (numCols <= 1)
577
8.51k
      return sec;
578
4.65k
    sec.m_columns.resize(numCols);
579
4.65k
    float prevPos=0;
580
16.9k
    for (size_t c=0; c < numCols; ++c) {
581
12.3k
      sec.m_columns[c].m_width = double(m_colsPos[2*c+1]-prevPos);
582
12.3k
      prevPos = m_colsPos[2*c+1];
583
12.3k
      sec.m_columns[c].m_widthUnit = librevenge::RVNG_POINT;
584
12.3k
      sec.m_columns[c].m_margins[libmwaw::Right] =
585
12.3k
        double(m_colsPos[2*c+1]-m_colsPos[2*c])/72.;
586
12.3k
    }
587
4.65k
    return sec;
588
13.1k
  }
589
  //! return the number of columns
590
  int numColumns() const
591
0
  {
592
0
    auto numCols=int(m_colsPos.size()/2);
593
0
    return numCols ? numCols : 1;
594
0
  }
595
  //! operator<<
596
  friend std::ostream &operator<<(std::ostream &o, Section const &sec)
597
0
  {
598
0
    switch (sec.m_start) {
599
0
    case S_Line:
600
0
      o << "newLine,";
601
0
      break;
602
0
    case S_Page:
603
0
      break;
604
0
    case S_PageLeft:
605
0
      o << "newPage[left],";
606
0
      break;
607
0
    case S_PageRight:
608
0
      o << "newPage[right],";
609
0
      break;
610
0
#if !defined(__clang__)
611
0
    default:
612
0
      break;
613
0
#endif
614
0
    }
615
0
    auto nColumns = size_t(sec.numColumns());
616
0
    if (nColumns != 1) {
617
0
      o << "nCols=" << nColumns << ",";
618
0
      o << "colsPos=[";
619
0
      for (size_t i = 0; i < 2*nColumns; i+=2)
620
0
        o << sec.m_colsPos[i] << ":" << sec.m_colsPos[i+1] << ",";
621
0
      o << "],";
622
0
    }
623
0
    if (sec.m_headerIds[0]) o << "sec.headerId=" << sec.m_headerIds[0] << ",";
624
0
    if (sec.m_headerIds[0]!=sec.m_headerIds[1]) o << "sec.headerId1=" << sec.m_headerIds[0] << ",";
625
0
    if (sec.m_footerIds[0]) o << "sec.footerId=" << sec.m_footerIds[0] << ",";
626
0
    if (sec.m_footerIds[0]!=sec.m_footerIds[1]) o << "sec.footerId1=" << sec.m_footerIds[0] << ",";
627
0
    if (sec.m_textLength) o << "nChar=" << sec.m_textLength << ",";
628
0
    if (sec.m_extra.length()) o << sec.m_extra;
629
0
    return o;
630
0
  }
631
  //! the way to start the new section
632
  StartType m_start;
633
  //! the columns position ( series of end columns <-> new column begin)
634
  std::vector<float> m_colsPos;
635
  //! the header graphic ids
636
  int m_headerIds[2];
637
  //! the footerer graphic ids
638
  int m_footerIds[2];
639
  //! the number of character in the sections
640
  long m_textLength;
641
  //! extra data
642
  std::string m_extra;
643
};
644
645
////////////////////////////////////////
646
//! Internal: the state of a MacWrtProStructures
647
struct State {
648
  //! constructor
649
  State()
650
47.3k
    : m_version(-1)
651
47.3k
    , m_numPages(1)
652
47.3k
    , m_inputData()
653
47.3k
    , m_fontsList()
654
47.3k
    , m_paragraphsList()
655
47.3k
    , m_pagesList()
656
47.3k
    , m_sectionsList()
657
47.3k
    , m_graphicsList()
658
47.3k
    , m_tablesMap()
659
47.3k
    , m_idGraphicMap()
660
47.3k
    , m_headersMap()
661
47.3k
    , m_footersMap()
662
47.3k
    , m_graphicsSendSet()
663
47.3k
  {
664
47.3k
  }
665
666
  //! try to set the line properties of a border
667
  static bool updateLineType(int lineType, MWAWBorder &border)
668
76.0k
  {
669
76.0k
    switch (lineType) {
670
930
    case 2:
671
930
      border.m_type=MWAWBorder::Double;
672
930
      border.m_widthsList.resize(3,2.);
673
930
      border.m_widthsList[1]=1.0;
674
930
      break;
675
275
    case 3:
676
275
      border.m_type=MWAWBorder::Double;
677
275
      border.m_widthsList.resize(3,1.);
678
275
      border.m_widthsList[2]=2.0;
679
275
      break;
680
149
    case 4:
681
149
      border.m_type=MWAWBorder::Double;
682
149
      border.m_widthsList.resize(3,1.);
683
149
      border.m_widthsList[0]=2.0;
684
149
      break;
685
63.6k
    case 1: // solid
686
63.6k
      break;
687
11.0k
    default:
688
11.0k
      return false;
689
76.0k
    }
690
65.0k
    return true;
691
76.0k
  }
692
693
  //! the file version
694
  int m_version;
695
696
  //! the number of pages
697
  int m_numPages;
698
699
  //! the input data
700
  librevenge::RVNGBinaryData m_inputData;
701
702
  //! the list of fonts
703
  std::vector<Font> m_fontsList;
704
  //! the list of paragraph
705
  std::vector<Paragraph> m_paragraphsList;
706
  //! the pages list (for MWII)
707
  std::vector<Page> m_pagesList;
708
  //! the list of section
709
  std::vector<Section> m_sectionsList;
710
  //! the list of graphic
711
  std::vector<std::shared_ptr<Graphic> > m_graphicsList;
712
  //! a map graphic id -> table
713
  std::map<int, std::shared_ptr<Table> > m_tablesMap;
714
  //! a map graphic id -> graphic
715
  std::map<int, std::shared_ptr<Graphic> > m_idGraphicMap;
716
  //! a map page -> header id
717
  std::map<int, int> m_headersMap;
718
  //! a map page -> footer id
719
  std::map<int, int> m_footersMap;
720
  //! a list of graphic use to avoid potential loop in bad file
721
  std::set<MWAWVec2i> m_graphicsSendSet;
722
};
723
724
}
725
726
727
////////////////////////////////////////////////////////////
728
// constructor/destructor, ...
729
////////////////////////////////////////////////////////////
730
MacWrtProStructures::MacWrtProStructures(MacWrtProParser &parser)
731
47.3k
  : m_parserState(parser.getParserState())
732
47.3k
  , m_mainParser(parser)
733
47.3k
  , m_state()
734
47.3k
  , m_asciiName()
735
47.3k
{
736
47.3k
  init();
737
47.3k
}
738
739
MacWrtProStructures::~MacWrtProStructures()
740
47.3k
{
741
47.3k
}
742
743
void MacWrtProStructures::init()
744
47.3k
{
745
47.3k
  m_state.reset(new MacWrtProStructuresInternal::State);
746
47.3k
}
747
748
int MacWrtProStructures::version() const
749
1.00M
{
750
1.00M
  if (m_state->m_version < 0)
751
18.2k
    m_state->m_version = m_parserState->m_version;
752
1.00M
  return m_state->m_version;
753
1.00M
}
754
755
MWAWTextListenerPtr &MacWrtProStructures::getTextListener()
756
9.42M
{
757
9.42M
  return m_parserState->m_textListener;
758
9.42M
}
759
760
int MacWrtProStructures::numPages() const
761
18.0k
{
762
18.0k
  return m_state->m_numPages;
763
18.0k
}
764
765
////////////////////////////////////////////////////////////
766
// update a page span
767
void MacWrtProStructures::updatePageSpan(int page, bool hasTitlePage, MWAWPageSpan &ps)
768
23.5k
{
769
23.5k
  if (version()==0) {
770
    // title page has no header/footer
771
4.90k
    if (hasTitlePage && page==0) {
772
1.49k
      ps.setPageSpan(1);
773
1.49k
      return;
774
1.49k
    }
775
    // hf is defined for all pages excepted the title page
776
3.40k
    int index=0;
777
6.73k
    for (size_t i = 0; i < m_state->m_pagesList.size(); ++i) {
778
4.78k
      if (i>=2) break;
779
3.33k
      auto const &pge = m_state->m_pagesList[i];
780
3.33k
      for (auto const &graphic : pge.m_graphicsList) {
781
235
        if (graphic->m_textboxType<1 || graphic->m_textboxType>2) continue;
782
1
        m_state->m_idGraphicMap[++index]=graphic;
783
1
        MWAWHeaderFooter hf(graphic->m_textboxType==1 ? MWAWHeaderFooter::HEADER : MWAWHeaderFooter::FOOTER,
784
1
                            graphic->m_headerFooterFlag==1 ? MWAWHeaderFooter::EVEN : graphic->m_headerFooterFlag==2 ? MWAWHeaderFooter::ODD : MWAWHeaderFooter::ALL);
785
1
        hf.m_subDocument=m_mainParser.getSubDocument(index);
786
1
        ps.setHeaderFooter(hf);
787
1
      }
788
3.33k
    }
789
3.40k
    ps.setPageSpan(m_state->m_numPages>page ? m_state->m_numPages-page : 100);
790
3.40k
    return;
791
4.90k
  }
792
18.6k
  ++page;
793
18.6k
  int numSimilar[2]= {1,1};
794
56.0k
  for (int st=0; st<2; ++st) {
795
37.3k
    auto const &map=st==0 ? m_state->m_headersMap : m_state->m_footersMap;
796
37.3k
    auto it=map.lower_bound(page);
797
37.3k
    if (it==map.end()) {
798
17.6k
      if (m_state->m_numPages>page)
799
621
        numSimilar[st]=m_state->m_numPages-page+1;
800
17.6k
      continue;
801
17.6k
    }
802
19.6k
    if (it->first!=page) {
803
363
      numSimilar[st]=it->first-page;
804
363
      continue;
805
363
    }
806
19.3k
    int id=it->second;
807
37.8k
    while (++it!=map.end() && it->second==id)
808
18.4k
      numSimilar[st]++;
809
19.3k
    if (!id) continue;
810
19.3k
    MWAWHeaderFooter hf(st==0 ? MWAWHeaderFooter::HEADER : MWAWHeaderFooter::FOOTER, MWAWHeaderFooter::ALL);
811
19.3k
    hf.m_subDocument=m_mainParser.getSubDocument(id);
812
19.3k
    ps.setHeaderFooter(hf);
813
19.3k
  }
814
18.6k
  ps.setPageSpan(std::min<int>(numSimilar[0],numSimilar[1]));
815
18.6k
}
816
817
////////////////////////////////////////////////////////////
818
// try to return the color/pattern, set the line properties
819
bool MacWrtProStructures::getColor(int colId, MWAWColor &color) const
820
221k
{
821
221k
  if (version()==0) {
822
    // MWII: 2:red 4: blue, ..
823
9.98k
    switch (colId) {
824
3.59k
    case 0:
825
3.59k
      color = 0xFFFFFF;
826
3.59k
      break;
827
0
    case 1:
828
0
      color = 0;
829
0
      break;
830
187
    case 2:
831
187
      color = 0xFF0000;
832
187
      break;
833
194
    case 3:
834
194
      color = 0x00FF00;
835
194
      break;
836
68
    case 4:
837
68
      color = 0x0000FF;
838
68
      break;
839
122
    case 5:
840
122
      color = 0x00FFFF;
841
122
      break; // cyan
842
383
    case 6:
843
383
      color = 0xFF00FF;
844
383
      break; // magenta
845
138
    case 7:
846
138
      color = 0xFFFF00;
847
138
      break; // yellow
848
5.29k
    default:
849
5.29k
      MWAW_DEBUG_MSG(("MacWrtProStructures::getColor: unknown color %d\n", colId));
850
5.29k
      return false;
851
9.98k
    }
852
9.98k
  }
853
211k
  else {
854
    /* 0: white, 38: yellow, 44: magenta, 36: red, 41: cyan, 39: green, 42: blue
855
       checkme: this probably corresponds to the following 81 gray/color palette...
856
    */
857
211k
    uint32_t const colorMap[] = {
858
211k
      0xFFFFFF, 0x0, 0x222222, 0x444444, 0x666666, 0x888888, 0xaaaaaa, 0xcccccc, 0xeeeeee,
859
211k
      0x440000, 0x663300, 0x996600, 0x002200, 0x003333, 0x003399, 0x000055, 0x330066, 0x660066,
860
211k
      0x770000, 0x993300, 0xcc9900, 0x004400, 0x336666, 0x0033ff, 0x000077, 0x660099, 0x990066,
861
211k
      0xaa0000, 0xcc3300, 0xffcc00, 0x006600, 0x006666, 0x0066ff, 0x0000aa, 0x663399, 0xcc0099,
862
211k
      0xdd0000, 0xff3300, 0xffff00, 0x008800, 0x009999, 0x0099ff, 0x0000dd, 0x9900cc, 0xff0099,
863
211k
      0xff3333, 0xff6600, 0xffff33, 0x00ee00, 0x00cccc, 0x00ccff, 0x3366ff, 0x9933ff, 0xff33cc,
864
211k
      0xff6666, 0xff6633, 0xffff66, 0x66ff66, 0x66cccc, 0x66ffff, 0x3399ff, 0x9966ff, 0xff66ff,
865
211k
      0xff9999, 0xff9966, 0xffff99, 0x99ff99, 0x66ffcc, 0x99ffff, 0x66ccff, 0x9999ff, 0xff99ff,
866
211k
      0xffcccc, 0xffcc99, 0xffffcc, 0xccffcc, 0x99ffcc, 0xccffff, 0x99ccff, 0xccccff, 0xffccff
867
211k
    };
868
211k
    if (colId < 0 || colId >= 81) {
869
19.4k
      MWAW_DEBUG_MSG(("MacWrtProStructures::getColor: unknown color %d\n", colId));
870
19.4k
      return false;
871
19.4k
    }
872
191k
    color = colorMap[colId];
873
191k
  }
874
196k
  return true;
875
221k
}
876
877
bool MacWrtProStructures::getPattern(int patId, float &patternPercent) const
878
113k
{
879
113k
  patternPercent=1.0f;
880
113k
  if (version()==0) // not implemented
881
0
    return false;
882
113k
  static float const defPercentPattern[64] = {
883
113k
    0.0f, 1.0f, 0.968750f, 0.93750f, 0.8750f, 0.750f, 0.50f, 0.250f,
884
113k
    0.250f, 0.18750f, 0.18750f, 0.1250f, 0.06250f, 0.06250f, 0.031250f, 0.015625f,
885
113k
    0.750f, 0.50f, 0.250f, 0.3750f, 0.250f, 0.1250f, 0.250f, 0.1250f,
886
113k
    0.750f, 0.50f, 0.250f, 0.3750f, 0.250f, 0.1250f, 0.250f, 0.1250f,
887
113k
    0.750f, 0.50f, 0.50f, 0.50f, 0.50f, 0.250f, 0.250f, 0.234375f,
888
113k
    0.6250f, 0.3750f, 0.1250f, 0.250f, 0.218750f, 0.218750f, 0.1250f, 0.093750f,
889
113k
    0.50f, 0.56250f, 0.43750f, 0.3750f, 0.218750f, 0.281250f, 0.18750f, 0.093750f,
890
113k
    0.593750f, 0.56250f, 0.515625f, 0.343750f, 0.31250f, 0.250f, 0.250f, 0.234375f,
891
113k
  };
892
113k
  if (patId <= 0 || patId>64) {
893
2.92k
    MWAW_DEBUG_MSG(("MacWrtProStructures::getPattern: unknown pattern %d\n", patId));
894
2.92k
    return false;
895
2.92k
  }
896
111k
  patternPercent=defPercentPattern[patId-1];
897
111k
  return true;
898
113k
}
899
900
bool MacWrtProStructures::getColor(int colId, int patId, MWAWColor &color) const
901
128k
{
902
128k
  if (!getColor(colId, color))
903
6.92k
    return false;
904
121k
  if (patId==0)
905
7.38k
    return true;
906
113k
  float percent;
907
113k
  if (!getPattern(patId,percent))
908
2.92k
    return false;
909
111k
  color=MWAWColor::barycenter(percent,color,1.f-percent,MWAWColor::white());
910
111k
  return true;
911
113k
}
912
913
////////////////////////////////////////////////////////////
914
//
915
// Intermediate level
916
//
917
////////////////////////////////////////////////////////////
918
bool MacWrtProStructures::createZones(std::shared_ptr<MWAWStream> &stream, int numPages)
919
18.2k
{
920
18.2k
  if (!stream)
921
0
    return false;
922
18.2k
  if (version() == 0)
923
4.24k
    return createZonesII(stream, numPages);
924
925
14.0k
  auto &input=stream->m_input;
926
14.0k
  auto &ascFile=stream->m_ascii;
927
14.0k
  long pos;
928
929
14.0k
  bool ok = readStyles(stream) && readCharStyles(stream);
930
14.0k
  if (ok) {
931
12.7k
    pos = input->tell();
932
12.7k
    if (!readSelection(stream)) {
933
0
      ascFile.addPos(pos);
934
0
      ascFile.addNote("Entries(Selection):#");
935
0
      input->seek(pos+16, librevenge::RVNG_SEEK_SET);
936
0
    }
937
938
12.7k
    pos = input->tell();
939
12.7k
    ok = readFontsName(stream);
940
12.7k
    if (!ok) {
941
366
      ascFile.addPos(pos);
942
366
      ascFile.addNote("Entries(FontsName):#");
943
366
    }
944
12.7k
  }
945
14.0k
  if (ok) {
946
12.4k
    pos = input->tell();
947
12.4k
    ok = readStructB(stream);
948
12.4k
    if (!ok) {
949
221
      ascFile.addPos(pos);
950
221
      ascFile.addNote("Entries(StructB):#");
951
221
    }
952
12.4k
  }
953
14.0k
  if (ok) {
954
12.1k
    pos = input->tell();
955
12.1k
    ok = readFontsDef(stream);
956
12.1k
    if (!ok) {
957
332
      ascFile.addPos(pos);
958
332
      ascFile.addNote("Entries(FontsDef):#");
959
332
    }
960
12.1k
  }
961
14.0k
  if (ok) {
962
11.8k
    pos = input->tell();
963
11.8k
    ok = readParagraphs(stream);
964
11.8k
    if (!ok) {
965
670
      ascFile.addPos(pos);
966
670
      ascFile.addNote("Entries(ParaZone):#");
967
670
    }
968
11.8k
  }
969
36.4k
  for (int st = 0; st < 2; ++st) {
970
25.2k
    if (!ok) break;
971
22.3k
    pos = input->tell();
972
22.3k
    std::vector<MacWrtProStructuresInternal::Section> sections;
973
22.3k
    ok = readSections(stream, sections);
974
22.3k
    if (!ok) {
975
0
      ascFile.addPos(pos);
976
0
      ascFile.addNote("Entries(Sections):#");
977
0
      break;
978
0
    }
979
22.3k
    if (st == 0) continue;
980
11.1k
    m_state->m_sectionsList = sections;
981
11.1k
  }
982
14.0k
  if (ok) {
983
11.1k
    pos = input->tell();
984
11.1k
    libmwaw::DebugStream f;
985
11.1k
    f << "Entries(UserName):";
986
    // username,
987
11.1k
    std::string res;
988
32.0k
    for (int i = 0; i < 2; ++i) {
989
21.7k
      ok = readString(input, res);
990
21.7k
      if (!ok) {
991
900
        f << "#" ;
992
900
        break;
993
900
      }
994
20.8k
      f << "'" << res << "',";
995
20.8k
    }
996
11.1k
    ascFile.addPos(pos);
997
11.1k
    ascFile.addNote(f.str().c_str());
998
11.1k
  }
999
14.0k
  if (ok) {
1000
10.2k
    pos = input->tell();
1001
10.2k
    ok = readGraphicsList(stream, numPages);
1002
10.2k
    if (!ok) {
1003
1.52k
      ascFile.addPos(pos);
1004
1.52k
      ascFile.addNote("Entries(Graphic):#");
1005
1.52k
    }
1006
10.2k
  }
1007
1008
14.0k
  pos = input->tell();
1009
14.0k
  ascFile.addPos(pos);
1010
14.0k
  ascFile.addNote("Entries(End)");
1011
1012
  // ok, now we can build the structures
1013
14.0k
  buildPageStructures();
1014
14.0k
  buildTableStructures();
1015
1016
14.0k
  return true;
1017
18.2k
}
1018
1019
bool MacWrtProStructures::createZonesII(std::shared_ptr<MWAWStream> &stream, int numPages)
1020
4.24k
{
1021
4.24k
  if (!stream) return false;
1022
4.24k
  if (version()) {
1023
0
    MWAW_DEBUG_MSG(("MacWrtProStructures::createZonesII: must be called for a MacWriteII file\n"));
1024
0
    return false;
1025
0
  }
1026
4.24k
  libmwaw::DebugStream f;
1027
4.24k
  auto &input=stream->m_input;
1028
4.24k
  auto &ascFile=stream->m_ascii;
1029
4.24k
  long pos;
1030
4.24k
  bool ok = readFontsName(stream);
1031
4.24k
  if (ok) {
1032
3.83k
    pos = input->tell();
1033
3.83k
    long val = long(input->readULong(4));
1034
3.83k
    if (val) {
1035
1.20k
      MWAW_DEBUG_MSG(("MacWrtProStructures::createZonesII: argh!!! find data after the fonts name zone. Trying to continue.\n"));
1036
1.20k
      f.str("");
1037
      // in QuarkXPress color
1038
1.20k
      f << "Entries(Color):#" << std::hex << val << std::dec;
1039
1040
1.20k
      ascFile.addPos(pos);
1041
1.20k
      ascFile.addNote(f.str().c_str());
1042
1.20k
    }
1043
2.62k
    else {
1044
2.62k
      ascFile.addPos(pos);
1045
2.62k
      ascFile.addNote("_");
1046
2.62k
    }
1047
3.83k
    ok = readCharStyles(stream);
1048
3.83k
  }
1049
4.24k
  if (ok)
1050
3.42k
    ok = readFontsDef(stream);
1051
4.24k
  if (ok)
1052
2.96k
    ok = readParagraphs(stream);
1053
  // FIXME: this code is bad, look for XPressGraph::readPagesListII which is very simillar
1054
4.24k
  if (ok)
1055
2.47k
    readPagesListII(stream, numPages);
1056
1057
4.24k
  pos = input->tell();
1058
4.24k
  if (input->checkPosition(pos+256)) {
1059
346
    MWAW_DEBUG_MSG(("MacWrtProStructures::createZonesII: oops, probable problem when reading the pages...\n"));
1060
346
  }
1061
4.24k
  ascFile.addPos(pos);
1062
4.24k
  ascFile.addNote("Entries(Page)[End]:");
1063
1064
4.24k
  int nPages = numPages;
1065
4.24k
  int nFootnotes=0;
1066
22.0k
  for (auto const &pages : m_state->m_pagesList) {
1067
22.0k
    bool mainBlock=true;
1068
22.0k
    for (auto const &graphic : pages.m_graphicsList) {
1069
888
      if (graphic->m_fileBlock>0) {
1070
272
        m_mainParser.parseDataZone(graphic->m_fileBlock, 0);
1071
272
        if (mainBlock)
1072
267
          nPages += m_mainParser.findNumHardBreaks(graphic->m_fileBlock);
1073
272
      }
1074
888
      if (graphic->m_textboxType==3) // footnote
1075
7
        m_state->m_idGraphicMap[--nFootnotes]=graphic;
1076
888
      mainBlock=false;
1077
888
    }
1078
22.0k
  }
1079
4.24k
  m_state->m_numPages = nPages;
1080
1081
4.24k
  return true;
1082
4.24k
}
1083
1084
////////////////////////////////////////////////////////////
1085
// try to find the main text zone and sent it
1086
bool MacWrtProStructures::sendMainZone()
1087
18.0k
{
1088
18.0k
  int vers = version();
1089
18.0k
  if (vers==0) {
1090
3.97k
    if (m_state->m_pagesList.size()>=3) {
1091
1.46k
      auto const &page=m_state->m_pagesList[2];
1092
1.46k
      if (!page.m_graphicsList.empty()) {
1093
141
        m_state->m_idGraphicMap[0]=page.m_graphicsList[0];
1094
141
        return send(0, true);
1095
141
      }
1096
1.46k
    }
1097
3.97k
  }
1098
14.0k
  else {
1099
39.0k
    for (size_t i = 0; i < m_state->m_graphicsList.size(); ++i) {
1100
28.6k
      auto graphic = m_state->m_graphicsList[i];
1101
28.6k
      if (!graphic->isText() || graphic->m_send) continue;
1102
17.5k
      if (vers == 1 && graphic->m_type != 5)
1103
13.8k
        continue;
1104
3.61k
      return send(graphic->m_id, true);
1105
17.5k
    }
1106
14.0k
  }
1107
  //ok the main zone can be empty
1108
14.2k
  std::shared_ptr<MacWrtProStructures> THIS
1109
14.2k
  (this, MWAW_shared_ptr_noop_deleter<MacWrtProStructures>());
1110
14.2k
  MacWrtProStructuresListenerState listenerState(THIS, true, vers);
1111
14.2k
  return true;
1112
18.0k
}
1113
1114
////////////////////////////////////////////////////////////
1115
// try to find the header and the pages break
1116
void MacWrtProStructures::buildPageStructures()
1117
14.0k
{
1118
  // first find the pages break
1119
14.0k
  std::set<long> set;
1120
14.0k
  int actPage = 0;
1121
52.1k
  for (auto const &graphic : m_state->m_graphicsList) {
1122
52.1k
    graphic->m_page = actPage ? actPage : 1; // mainly ok
1123
52.1k
    if (graphic->m_type != 5)
1124
38.8k
      continue;
1125
13.3k
    actPage++;
1126
13.3k
    set.insert(graphic->m_textPos);
1127
13.3k
  }
1128
14.0k
  long actSectPos = 0;
1129
23.9k
  for (auto const &sec : m_state->m_sectionsList) {
1130
23.9k
    if (sec.m_start != sec.S_Line) set.insert(actSectPos);
1131
23.9k
    actSectPos += sec.m_textLength;
1132
23.9k
  }
1133
14.0k
  std::vector<int> pagesBreak;
1134
14.0k
  pagesBreak.assign(set.begin(), set.end());
1135
1136
  // now associates the header/footer to each pages
1137
14.0k
  int nPages = m_state->m_numPages = int(pagesBreak.size());
1138
14.0k
  int actPagePos = 0;
1139
14.0k
  actPage = 0;
1140
14.0k
  actSectPos = 0;
1141
23.9k
  for (auto const &sec : m_state->m_sectionsList) {
1142
23.9k
    std::vector<int> listPages;
1143
23.9k
    actSectPos += sec.m_textLength;
1144
35.5k
    while (actPagePos < actSectPos) {
1145
28.5k
      listPages.push_back(actPage);
1146
28.5k
      if (actPage >= nPages-1 || pagesBreak[size_t(actPage+1)] > actSectPos)
1147
16.9k
        break;
1148
11.5k
      actPagePos=pagesBreak[size_t(++actPage)];
1149
11.5k
    }
1150
23.9k
    int headerId = 0, footerId = 0;
1151
71.7k
    for (int k = 0; k < 2; ++k) {
1152
47.8k
      if (sec.m_headerIds[k])
1153
44.7k
        headerId = sec.m_headerIds[k];
1154
47.8k
      if (sec.m_footerIds[k])
1155
43.7k
        footerId = sec.m_footerIds[k];
1156
47.8k
    }
1157
23.9k
    if (!headerId && !footerId) continue;
1158
27.9k
    for (auto p : listPages) {
1159
27.9k
      ++p;
1160
27.9k
      if (headerId && m_state->m_headersMap.find(p) == m_state->m_headersMap.end())
1161
16.5k
        m_state->m_headersMap[p] = headerId;
1162
27.9k
      if (footerId)
1163
27.4k
        m_state->m_footersMap[p] = footerId;
1164
27.9k
    }
1165
23.2k
  }
1166
  // finally mark the attachment
1167
14.0k
  auto const &listCalled = m_mainParser.getGraphicIdCalledByToken();
1168
14.0k
  for (auto id : listCalled) {
1169
2.70k
    if (m_state->m_idGraphicMap.find(id) == m_state->m_idGraphicMap.end()) {
1170
886
      MWAW_DEBUG_MSG(("MacWrtProStructures::buildPageStructures: can not find attachment block %d...\n",
1171
886
                      id));
1172
886
      continue;
1173
886
    }
1174
1.82k
    auto graphic = m_state->m_idGraphicMap.find(id)->second;
1175
1.82k
    graphic->m_attachment = true;
1176
1.82k
  }
1177
14.0k
}
1178
1179
////////////////////////////////////////////////////////////
1180
// try to find the main text zone and sent it
1181
void MacWrtProStructures::buildTableStructures()
1182
14.0k
{
1183
14.0k
  size_t numGraphics = m_state->m_graphicsList.size();
1184
56.2k
  for (size_t i = 0; i < numGraphics; ++i) {
1185
42.2k
    if (m_state->m_graphicsList[i]->m_type != 3)
1186
37.3k
      continue;
1187
4.85k
    auto table = m_state->m_graphicsList[i];
1188
4.85k
    std::vector<std::shared_ptr<MacWrtProStructuresInternal::Graphic> > graphicList;
1189
4.85k
    size_t j = i+1;
1190
14.8k
    for (; j < numGraphics; ++j) {
1191
12.3k
      auto cell = m_state->m_graphicsList[j];
1192
12.3k
      if (cell->m_type != 4)
1193
1.14k
        break;
1194
11.1k
      if (!table->contains(cell->m_box))
1195
1.09k
        break;
1196
10.0k
      bool ok = true;
1197
12.2k
      for (auto const &graphic : graphicList) {
1198
12.2k
        if (cell->intersects(graphic->m_box)) {
1199
134
          ok = false;
1200
134
          break;
1201
134
        }
1202
12.2k
      }
1203
10.0k
      if (!ok)
1204
134
        break;
1205
9.95k
      graphicList.push_back(cell);
1206
9.95k
    }
1207
4.85k
    if (j-1 >= i) i = j-1;
1208
1209
4.85k
    size_t numCells = graphicList.size();
1210
4.85k
    bool ok = numCells > 1;
1211
4.85k
    if (!ok && numCells == 1)
1212
663
      ok = table->m_col == 1 && table->m_row == 1;
1213
4.85k
    if (!ok) {
1214
1.90k
      MWAW_DEBUG_MSG(("MacWrtProStructures::buildTableStructures: find a table with %ld cells : ignored...\n", long(numCells)));
1215
1.90k
      continue;
1216
1.90k
    }
1217
1218
2.94k
    std::shared_ptr<MacWrtProStructuresInternal::Table> newTable(new MacWrtProStructuresInternal::Table);
1219
9.29k
    for (auto const &graphic : graphicList) {
1220
9.29k
      graphic->m_send = true;
1221
9.29k
      graphic->m_attachment = true;
1222
9.29k
      graphic->m_textboxCellType=1;
1223
9.29k
      newTable->add(std::shared_ptr<MacWrtProStructuresInternal::Cell>
1224
9.29k
                    (new MacWrtProStructuresInternal::Cell(*this, graphic.get())));
1225
9.29k
    }
1226
2.94k
    m_state->m_tablesMap[table->m_id]=newTable;
1227
2.94k
  }
1228
14.0k
}
1229
1230
////////////////////////////////////////////////////////////
1231
//
1232
// Low level
1233
//
1234
////////////////////////////////////////////////////////////
1235
1236
////////////////////////////////////////////////////////////
1237
// read the font names
1238
bool MacWrtProStructures::readFontsName(std::shared_ptr<MWAWStream> &stream)
1239
17.0k
{
1240
17.0k
  auto &input = stream->m_input;
1241
17.0k
  auto &ascFile = stream->m_ascii;
1242
17.0k
  long pos = input->tell();
1243
17.0k
  libmwaw::DebugStream f;
1244
1245
17.0k
  auto sz = long(input->readULong(4));
1246
17.0k
  if (sz == 0) {
1247
7.84k
    ascFile.addPos(pos);
1248
7.84k
    ascFile.addNote("_");
1249
7.84k
    return true;
1250
7.84k
  }
1251
9.18k
  int vers = version();
1252
9.18k
  long endPos = pos+4+sz;
1253
9.18k
  if (!stream->checkPosition(endPos)) {
1254
780
    MWAW_DEBUG_MSG(("MacWrtProStructures::readFontsName: file is too short\n"));
1255
780
    input->seek(pos, librevenge::RVNG_SEEK_SET);
1256
780
    return false;
1257
780
  }
1258
8.40k
  f << "Entries(FontsName):";
1259
8.40k
  auto N=static_cast<int>(input->readULong(2));
1260
8.40k
  if (3*N+2 > sz) {
1261
319
    MWAW_DEBUG_MSG(("MacWrtProStructures::readFontsName: can not read the number of fonts\n"));
1262
319
    input->seek(endPos, librevenge::RVNG_SEEK_SET);
1263
319
    f << "#";
1264
319
    ascFile.addPos(pos);
1265
319
    ascFile.addNote(f.str().c_str());
1266
319
    return true;
1267
319
  }
1268
1269
32.4k
  for (int ft = 0; ft < N; ++ft) {
1270
24.3k
    auto fId = static_cast<int>(input->readLong(2));
1271
24.3k
    f << "[id=" << fId << ",";
1272
33.4k
    for (int st = 0; st < 2; ++st) {
1273
29.1k
      auto sSz = static_cast<int>(input->readULong(1));
1274
29.1k
      if (long(input->tell())+sSz > endPos) {
1275
9.67k
        MWAW_DEBUG_MSG(("MacWrtProStructures::readFontsName: can not read the %d font\n", ft));
1276
9.67k
        f << "#";
1277
9.67k
        break;
1278
9.67k
      }
1279
19.4k
      std::string name("");
1280
160k
      for (int i = 0; i < sSz; ++i)
1281
141k
        name += char(input->readULong(1));
1282
19.4k
      if (name.length()) {
1283
10.1k
        if (st == 0)
1284
9.28k
          m_parserState->m_fontConverter->setCorrespondance(fId, name);
1285
10.1k
        f << name << ",";
1286
10.1k
      }
1287
19.4k
      if (vers)
1288
10.3k
        break;
1289
19.4k
    }
1290
24.3k
    f << "],";
1291
24.3k
  }
1292
1293
8.08k
  if (long(input->tell()) != endPos)
1294
768
    ascFile.addDelimiter(input->tell(),'|');
1295
8.08k
  input->seek(endPos, librevenge::RVNG_SEEK_SET);
1296
1297
8.08k
  ascFile.addPos(pos);
1298
8.08k
  ascFile.addNote(f.str().c_str());
1299
8.08k
  return true;
1300
8.40k
}
1301
1302
////////////////////////////////////////////////////////////
1303
// read the character properties
1304
bool MacWrtProStructures::readFontsDef(std::shared_ptr<MWAWStream> &stream)
1305
15.6k
{
1306
15.6k
  auto &input = stream->m_input;
1307
15.6k
  auto &ascFile = stream->m_ascii;
1308
15.6k
  long pos = input->tell();
1309
15.6k
  libmwaw::DebugStream f;
1310
1311
15.6k
  auto sz = long(input->readULong(4));
1312
15.6k
  if (sz == 0) {
1313
4.45k
    ascFile.addPos(pos);
1314
4.45k
    ascFile.addNote("_");
1315
4.45k
    return true;
1316
4.45k
  }
1317
11.1k
  long endPos = pos+4+sz;
1318
11.1k
  int expectedSize = version()==0 ? 10 : 20;
1319
11.1k
  if ((sz%expectedSize) != 0 || !stream->checkPosition(endPos)) {
1320
794
    MWAW_DEBUG_MSG(("MacWrtProStructures::readFontsDef: find an odd value for sz\n"));
1321
794
    input->seek(pos, librevenge::RVNG_SEEK_SET);
1322
794
    return false;
1323
794
  }
1324
1325
10.3k
  f << "Entries(FontsDef):";
1326
10.3k
  auto N = int(sz/expectedSize);
1327
10.3k
  f << "N=" << N;
1328
10.3k
  ascFile.addPos(pos);
1329
10.3k
  ascFile.addNote(f.str().c_str());
1330
1331
10.3k
  m_state->m_fontsList.resize(0);
1332
257k
  for (int n = 0; n < N; ++n) {
1333
247k
    pos = input->tell();
1334
247k
    MacWrtProStructuresInternal::Font font;
1335
247k
    if (!readFont(stream, font)) {
1336
0
      ascFile.addPos(pos);
1337
0
      ascFile.addNote("FontsDef-#");
1338
0
      input->seek(endPos, librevenge::RVNG_SEEK_SET);
1339
0
      return true;
1340
0
    }
1341
247k
    m_state->m_fontsList.push_back(font);
1342
247k
    f.str("");
1343
247k
    f << "FontsDef-C" << n << ":";
1344
247k
    f << font.m_font.getDebugString(m_parserState->m_fontConverter) << font << ",";
1345
247k
    ascFile.addPos(pos);
1346
247k
    ascFile.addNote(f.str().c_str());
1347
247k
  }
1348
10.3k
  return true;
1349
10.3k
}
1350
1351
bool MacWrtProStructures::readFont(std::shared_ptr<MWAWStream> &stream, MacWrtProStructuresInternal::Font &font)
1352
297k
{
1353
297k
  auto &input = stream->m_input;
1354
297k
  long pos = input->tell();
1355
297k
  int vers = version();
1356
297k
  libmwaw::DebugStream f;
1357
297k
  font = MacWrtProStructuresInternal::Font();
1358
297k
  font.m_values[0] = static_cast<int>(input->readLong(2)); // 1, 3 or 6
1359
297k
  auto val = static_cast<int>(input->readULong(2));
1360
297k
  if (val != 0xFFFF)
1361
285k
    font.m_font.setId(val);
1362
297k
  val = static_cast<int>(input->readULong(2));
1363
297k
  if (val != 0xFFFF)
1364
285k
    font.m_font.setSize(float(val)/4.f);
1365
297k
  if (vers >= 1)
1366
286k
    font.m_values[1] = static_cast<int>(input->readLong(2));
1367
297k
  auto flag = long(input->readULong(2));
1368
297k
  uint32_t flags=0;
1369
297k
  if (flag&0x1) flags |= MWAWFont::boldBit;
1370
297k
  if (flag&0x2) flags |= MWAWFont::italicBit;
1371
297k
  if (flag&0x4) font.m_font.setUnderlineStyle(MWAWFont::Line::Simple);
1372
297k
  if (flag&0x8) flags |= MWAWFont::embossBit;
1373
297k
  if (flag&0x10) flags |= MWAWFont::shadowBit;
1374
297k
  if (flag&0x20) font.m_font.set(MWAWFont::Script(40,librevenge::RVNG_PERCENT));
1375
297k
  if (flag&0x40) font.m_font.set(MWAWFont::Script(-40,librevenge::RVNG_PERCENT));
1376
297k
  if (flag&0x100) font.m_font.set(MWAWFont::Script::super());
1377
297k
  if (flag&0x200) font.m_font.setStrikeOutStyle(MWAWFont::Line::Simple);
1378
297k
  if (flag&0x400) flags |= MWAWFont::uppercaseBit;
1379
297k
  if (flag&0x800) flags |= MWAWFont::smallCapsBit;
1380
297k
  if (flag&0x1000) font.m_font.setUnderlineStyle(MWAWFont::Line::Simple);
1381
297k
  if (flag&0x2000) {
1382
17.9k
    font.m_font.setUnderlineStyle(MWAWFont::Line::Simple);
1383
17.9k
    font.m_font.setUnderlineType(MWAWFont::Line::Double);
1384
17.9k
  }
1385
297k
  if (flag&0x4000) flags |= MWAWFont::lowercaseBit;
1386
297k
  font.m_flags = (flag&0x8080L);
1387
1388
297k
  auto color = static_cast<int>(input->readULong(1));
1389
297k
  MWAWColor col;
1390
297k
  if (color != 1 && getColor(color, col))
1391
74.9k
    font.m_font.setColor(col);
1392
222k
  else if (color != 1)
1393
17.8k
    f << "#colId=" << color << ",";
1394
297k
  val = static_cast<int>(input->readULong(1)); // always 0x64 (unused?)
1395
297k
  if (val != 0x64) font.m_values[2] = val;
1396
297k
  if (vers == 1) {
1397
286k
    auto lang = static_cast<int>(input->readLong(2));
1398
286k
    switch (lang) {
1399
190k
    case 0:
1400
190k
      font.m_font.setLanguage("en_US");
1401
190k
      break;
1402
7.40k
    case 2:
1403
7.40k
      font.m_font.setLanguage("en_GB");
1404
7.40k
      break;
1405
7.46k
    case 3:
1406
7.46k
      font.m_font.setLanguage("de");
1407
7.46k
      break;
1408
81.1k
    default:
1409
81.1k
      f << "#lang=" << lang << ",";
1410
81.1k
      break;
1411
286k
    }
1412
286k
    font.m_token = static_cast<int>(input->readLong(2));
1413
286k
    auto spacings = static_cast<int>(input->readLong(2));
1414
286k
    if (spacings) {
1415
25.6k
      if (spacings < -50 || spacings > 100) {
1416
6.92k
        MWAW_DEBUG_MSG(("MacWrtProStructures::readFont: character spacings seems odd\n"));
1417
6.92k
        f << "#spacings=" << spacings << "%,";
1418
6.92k
        spacings = spacings < 0 ? -50 : 100;
1419
6.92k
      }
1420
25.6k
      float fSz = font.m_font.size();
1421
25.6k
      if (fSz <= 0) {
1422
2.82k
        MWAW_DEBUG_MSG(("MacWrtProStructures::readFont: expand called without fSize, assume 12pt\n"));
1423
2.82k
        fSz = 12;
1424
2.82k
      }
1425
25.6k
      font.m_font.setDeltaLetterSpacing(fSz *float(spacings)/100.f);
1426
25.6k
    }
1427
572k
    for (int i = 4; i < 5; ++i)
1428
286k
      font.m_values[i] = static_cast<int>(input->readLong(2));
1429
286k
    input->seek(pos+20, librevenge::RVNG_SEEK_SET);
1430
286k
  }
1431
297k
  font.m_font.setFlags(flags);
1432
297k
  font.m_font.m_extra = f.str();
1433
1434
297k
  return true;
1435
297k
}
1436
1437
////////////////////////////////////////////////////////////
1438
// read a paragraph and a list of paragraph
1439
bool MacWrtProStructures::readParagraphs(std::shared_ptr<MWAWStream> &stream)
1440
14.8k
{
1441
14.8k
  auto &input = stream->m_input;
1442
14.8k
  auto &ascFile = stream->m_ascii;
1443
14.8k
  long pos = input->tell();
1444
14.8k
  libmwaw::DebugStream f;
1445
14.8k
  int dataSz = version()==0 ? 202 : 192;
1446
1447
14.8k
  auto sz = long(input->readULong(4));
1448
14.8k
  if (sz == 0) {
1449
6.45k
    ascFile.addPos(pos);
1450
6.45k
    ascFile.addNote("_");
1451
6.45k
    return true;
1452
6.45k
  }
1453
8.36k
  long endPos = pos+sz;
1454
8.36k
  if ((sz%dataSz) != 0 || !stream->checkPosition(endPos)) {
1455
1.15k
    MWAW_DEBUG_MSG(("MacWrtProStructures::readParagraphs: find an odd value for sz\n"));
1456
1.15k
    input->seek(pos, librevenge::RVNG_SEEK_SET);
1457
1.15k
    return false;
1458
1.15k
  }
1459
1460
7.21k
  f << "Entries(ParaZone):";
1461
7.21k
  auto N = int(sz/dataSz);
1462
7.21k
  f << "N=" << N;
1463
7.21k
  ascFile.addPos(pos);
1464
7.21k
  ascFile.addNote(f.str().c_str());
1465
1466
7.21k
  m_state->m_paragraphsList.resize(0);
1467
117k
  for (int n = 0; n < N; ++n) {
1468
109k
    pos = input->tell();
1469
109k
    auto val = static_cast<int>(input->readLong(2));
1470
109k
    f.str("");
1471
109k
    f << "Entries(Paragraph)[" << n << "]:";
1472
109k
    if (val) f << "used?="<<val <<",";
1473
109k
    MacWrtProStructuresInternal::Paragraph para;
1474
109k
    if (!readParagraph(stream, para)) {
1475
1
      f << "#";
1476
1
      m_state->m_paragraphsList.push_back(MacWrtProStructuresInternal::Paragraph());
1477
1
      input->seek(pos+dataSz, librevenge::RVNG_SEEK_SET);
1478
1
    }
1479
109k
    else {
1480
109k
      f << para;
1481
109k
      m_state->m_paragraphsList.push_back(para);
1482
109k
    }
1483
109k
    ascFile.addPos(pos);
1484
109k
    ascFile.addNote(f.str().c_str());
1485
109k
  }
1486
7.21k
  return true;
1487
8.36k
}
1488
1489
bool MacWrtProStructures::readParagraph(std::shared_ptr<MWAWStream> &stream, MacWrtProStructuresInternal::Paragraph &para)
1490
142k
{
1491
142k
  auto &input = stream->m_input;
1492
142k
  auto &ascFile = stream->m_ascii;
1493
142k
  libmwaw::DebugStream f;
1494
142k
  int vers = version();
1495
142k
  long pos = input->tell(), endPos = pos+(vers == 0 ? 200: 190);
1496
142k
  para = MacWrtProStructuresInternal::Paragraph();
1497
1498
142k
  if (!stream->checkPosition(endPos)) {
1499
1
    MWAW_DEBUG_MSG(("MacWrtProStructures::readParagraph: file is too short\n"));
1500
1
    return false;
1501
1
  }
1502
142k
  int val, just = 0;
1503
142k
  if (vers == 0) {
1504
298
    just = static_cast<int>(input->readULong(2));
1505
298
    val = static_cast<int>(input->readLong(2));
1506
298
    if (val) f << "unkn=" << val << ",";
1507
298
  }
1508
142k
  para.m_margins[1] = double(input->readLong(4))/72.0/65536.;
1509
142k
  para.m_margins[0] = double(input->readLong(4))/72.0/65536.;
1510
142k
  para.m_margins[2] = double(input->readLong(4))/72.0/65536.;
1511
1512
1513
142k
  float spacings[3];
1514
426k
  for (auto &spacing : spacings) spacing = float(input->readLong(4))/65536.f;
1515
568k
  for (int i = 0; i < 3; ++i) {
1516
426k
    int dim = vers==0 ? static_cast<int>(input->readLong(4)) : static_cast<int>(input->readULong(1));
1517
426k
    bool inPoint = true;
1518
426k
    bool ok = true;
1519
426k
    switch (dim) {
1520
283k
    case 0: // point
1521
283k
      ok = spacings[i] < 721 && (i || spacings[0] > 0);
1522
283k
      spacings[i]/=72.f;
1523
283k
      break;
1524
145
    case -1:
1525
124k
    case 0xFF: // percent
1526
124k
      ok = (spacings[i] >= 0 && spacings[i]<46);
1527
124k
      if (i==0) spacings[i]+=1.0f;
1528
124k
      inPoint=false;
1529
124k
      break;
1530
18.4k
    default:
1531
18.4k
      f << "#inter[dim]=" << std::hex << dim << std::dec << ",";
1532
18.4k
      ok = spacings[i] < 721 && (i || spacings[0] > 0);
1533
18.4k
      spacings[i]/=72.f;
1534
18.4k
      break;
1535
426k
    }
1536
426k
    if (ok) {
1537
410k
      if (i == 0 && inPoint) {
1538
20.7k
        if (spacings[0] > 0)
1539
20.7k
          para.setInterline(double(spacings[0]), librevenge::RVNG_INCH, MWAWParagraph::AtLeast);
1540
0
        else if (spacings[0] < 0) f << "interline=" << spacings[0] << ",";
1541
20.7k
        continue;
1542
20.7k
      }
1543
389k
      para.m_spacings[i] = double(spacings[i]);
1544
389k
      if (inPoint && spacings[i] > 1) {
1545
1.34k
        MWAW_DEBUG_MSG(("MacWrtProStructures::readParagraph: spacings looks big decreasing it\n"));
1546
1.34k
        f << "#prevSpacings" << i << "=" << spacings[i] << ",";
1547
1.34k
        para.m_spacings[i] = 1.0;
1548
1.34k
      }
1549
387k
      else if (!inPoint && i && (spacings[i]<0 || spacings[i]>0)) {
1550
6.59k
        if (i==1) f << "spaceBef";
1551
6.25k
        else f  << "spaceAft";
1552
6.59k
        f << "=" << spacings[i] << "%,";
1553
        /** seems difficult to set bottom a percentage of the line unit,
1554
            so do the strict minimum... */
1555
6.59k
        *(para.m_spacings[i]) *= 10./72.;
1556
6.59k
      }
1557
389k
    }
1558
16.6k
    else
1559
16.6k
      f << "#spacings" << i << ",";
1560
426k
  }
1561
1562
142k
  if (vers==1) {
1563
141k
    just = static_cast<int>(input->readULong(1));
1564
141k
    input->seek(pos+28, librevenge::RVNG_SEEK_SET);
1565
141k
  }
1566
298
  else {
1567
298
    ascFile.addDelimiter(input->tell(),'|');
1568
298
  }
1569
  /* Note: when no extra tab the justification,
1570
           if there is a extra tab, this corresponds to the extra tab alignment :-~ */
1571
142k
  switch (just & 0x3) {
1572
114k
  case 0:
1573
114k
    break;
1574
8.71k
  case 1:
1575
8.71k
    para.m_justify = MWAWParagraph::JustificationCenter;
1576
8.71k
    break;
1577
8.49k
  case 2:
1578
8.49k
    para.m_justify = MWAWParagraph::JustificationRight;
1579
8.49k
    break;
1580
10.1k
  case 3:
1581
10.1k
    para.m_justify = MWAWParagraph::JustificationFull;
1582
10.1k
    break;
1583
0
  default:
1584
0
    break;
1585
142k
  }
1586
142k
  if (just & 0x40)
1587
3.41k
    para.m_breakStatus = MWAWParagraph::NoBreakWithNextBit;
1588
142k
  if (just & 0x80)
1589
4.90k
    para.m_breakStatus = para.m_breakStatus.get()|MWAWParagraph::NoBreakBit;
1590
142k
  if (just&0x3C) f << "#justify=" << std::hex << (just&0x3C) << std::dec << ",";
1591
390k
  for (int i = 0; i < 20; ++i) {
1592
381k
    pos = input->tell();
1593
381k
    MWAWTabStop newTab;
1594
381k
    auto type = static_cast<int>(input->readULong(1));
1595
381k
    switch (type & 3) {
1596
245k
    case 0:
1597
245k
      break;
1598
25.4k
    case 1:
1599
25.4k
      newTab.m_alignment = MWAWTabStop::CENTER;
1600
25.4k
      break;
1601
42.5k
    case 2:
1602
42.5k
      newTab.m_alignment = MWAWTabStop::RIGHT;
1603
42.5k
      break;
1604
67.6k
    case 3:
1605
67.6k
      newTab.m_alignment = MWAWTabStop::DECIMAL;
1606
67.6k
      break;
1607
0
    default:
1608
0
      break;
1609
381k
    }
1610
381k
    if (type & 0xfc) {
1611
129k
      MWAW_DEBUG_MSG(("MacWrtProStructures::readParagraph: tab type is odd\n"));
1612
129k
      f << "tabs" << i << "[#type]=" << std::hex << (type & 0xFc) << std::dec << ",";
1613
129k
    }
1614
381k
    auto leader = static_cast<int>(input->readULong(1));
1615
381k
    if (leader != 0x20)
1616
215k
      newTab.m_leaderCharacter = static_cast<uint16_t>(leader);
1617
381k
    unsigned long tabPos = input->readULong(4);
1618
381k
    if (tabPos == 0xFFFFFFFFL) { // no more tab
1619
132k
      ascFile.addDelimiter(pos,'|');
1620
132k
      break;
1621
132k
    }
1622
248k
    newTab.m_position = double(tabPos)/72./65536.;
1623
248k
    auto decimalChar = static_cast<int>(input->readULong(1));
1624
248k
    if (decimalChar && decimalChar != '.')
1625
136k
      newTab.m_decimalCharacter=static_cast<uint16_t>(decimalChar);
1626
248k
    val = static_cast<int>(input->readLong(1)); // always 0?
1627
248k
    if (val)
1628
147k
      f << "tab" << i << "[#unkn=" << std::hex << val << std::dec << "],";
1629
248k
    para.m_tabs->push_back(newTab);
1630
248k
    input->seek(pos+8, librevenge::RVNG_SEEK_SET);
1631
248k
  }
1632
1633
142k
  if (vers==1) {
1634
141k
    input->seek(endPos-2, librevenge::RVNG_SEEK_SET);
1635
141k
    para.m_value = static_cast<int>(input->readLong(2));
1636
141k
  }
1637
142k
  para.m_extra=f.str();
1638
1639
142k
  input->seek(endPos, librevenge::RVNG_SEEK_SET);
1640
142k
  return true;
1641
142k
}
1642
1643
////////////////////////////////////////////////////////////
1644
// read the styles ( character )
1645
bool MacWrtProStructures::readCharStyles(std::shared_ptr<MWAWStream> &stream)
1646
16.9k
{
1647
16.9k
  auto &input = stream->m_input;
1648
16.9k
  auto &ascFile = stream->m_ascii;
1649
16.9k
  long pos = input->tell();
1650
16.9k
  libmwaw::DebugStream f;
1651
16.9k
  int vers = version();
1652
1653
16.9k
  int N;
1654
16.9k
  int expectedSz = 0x42;
1655
16.9k
  if (version() == 1) {
1656
13.0k
    auto sz = long(input->readULong(4));
1657
13.0k
    if ((sz%0x42) != 0) {
1658
275
      MWAW_DEBUG_MSG(("MacWrtProStructures::readCharStyles: find an odd value for sz=%ld\n",sz));
1659
275
      input->seek(pos, librevenge::RVNG_SEEK_SET);
1660
275
      return false;
1661
275
    }
1662
12.7k
    N = int(sz/0x42);
1663
12.7k
  }
1664
3.83k
  else {
1665
3.83k
    N = static_cast<int>(input->readULong(2));
1666
3.83k
    expectedSz = 0x2a;
1667
3.83k
  }
1668
1669
16.6k
  if (N == 0) {
1670
7.91k
    ascFile.addPos(pos);
1671
7.91k
    ascFile.addNote("_");
1672
7.91k
    return true;
1673
7.91k
  }
1674
8.71k
  long actPos = input->tell();
1675
8.71k
  long endPos = actPos+long(N)*expectedSz;
1676
1677
8.71k
  if (!stream->checkPosition(endPos)) {
1678
420
    MWAW_DEBUG_MSG(("MacWrtProStructures::readCharStyles: file is too short\n"));
1679
420
    input->seek(pos, librevenge::RVNG_SEEK_SET);
1680
420
    return false;
1681
420
  }
1682
8.29k
  f << "Entries(CharStyles):N=" << N;
1683
8.29k
  ascFile.addPos(pos);
1684
8.29k
  ascFile.addNote(f.str().c_str());
1685
1686
26.0k
  for (int i = 0; i < N; ++i) {
1687
17.7k
    pos = input->tell();
1688
17.7k
    f.str("");
1689
17.7k
    f << "CharStyles-" << i << ":";
1690
17.7k
    auto sSz = static_cast<int>(input->readULong(1));
1691
17.7k
    if (sSz > 31) {
1692
899
      MWAW_DEBUG_MSG(("MacWrtProStructures::readCharStyles: string size seems odd\n"));
1693
899
      sSz = 31;
1694
899
      f << "#";
1695
899
    }
1696
17.7k
    std::string name("");
1697
296k
    for (int c = 0; c < sSz; ++c)
1698
278k
      name += char(input->readULong(1));
1699
17.7k
    f << name << ",";
1700
17.7k
    input->seek(pos+32, librevenge::RVNG_SEEK_SET);
1701
1702
17.7k
    if (vers == 1) {
1703
15.6k
      auto val = static_cast<int>(input->readLong(2));
1704
15.6k
      if (val) f << "unkn0=" << val << ",";
1705
15.6k
      val = static_cast<int>(input->readLong(2));
1706
15.6k
      if (val != -1) f << "unkn1=" << val << ",";
1707
15.6k
      f << "date=" << MacWrtProParser::convertDateToDebugString(unsigned(input->readULong(4))) << ","; // unsure
1708
15.6k
      val = static_cast<int>(input->readLong(2)); // small number between 0 and 2 (nextId?)
1709
15.6k
      if (val) f << "f0=" << val << ",";
1710
78.2k
      for (int j = 1; j < 5; ++j) { // [-1,0,1], [0,1 or ee], 0, 0
1711
62.6k
        val = static_cast<int>(input->readLong(1));
1712
62.6k
        if (val) f << "f" << j <<"=" << val << ",";
1713
62.6k
      }
1714
15.6k
    }
1715
17.7k
    MacWrtProStructuresInternal::Font font;
1716
17.7k
    if (!readFont(stream, font)) {
1717
0
      MWAW_DEBUG_MSG(("MacWrtProStructures::readCharStyles: can not read the font\n"));
1718
0
      f << "###";
1719
0
    }
1720
17.7k
    else
1721
17.7k
      f << font.m_font.getDebugString(m_parserState->m_fontConverter) << font << ",";
1722
1723
17.7k
    ascFile.addPos(pos);
1724
17.7k
    ascFile.addNote(f.str().c_str());
1725
1726
17.7k
    input->seek(pos+expectedSz, librevenge::RVNG_SEEK_SET);
1727
17.7k
  }
1728
8.29k
  return true;
1729
8.71k
}
1730
1731
////////////////////////////////////////////////////////////
1732
// read the styles ( paragraph + font)
1733
bool MacWrtProStructures::readStyles(std::shared_ptr<MWAWStream> &stream)
1734
14.0k
{
1735
14.0k
  auto &input = stream->m_input;
1736
14.0k
  auto &ascFile = stream->m_ascii;
1737
14.0k
  long pos = input->tell();
1738
14.0k
  libmwaw::DebugStream f;
1739
14.0k
  auto sz = long(input->readULong(4));
1740
14.0k
  if ((sz%0x106) != 0) {
1741
452
    MWAW_DEBUG_MSG(("MacWrtProStructures::readStyles: find an odd value for sz=%ld\n",sz));
1742
452
    input->seek(pos, librevenge::RVNG_SEEK_SET);
1743
452
    return false;
1744
452
  }
1745
13.5k
  auto N = int(sz/0x106);
1746
1747
13.5k
  if (N==0) {
1748
5.27k
    ascFile.addPos(pos);
1749
5.27k
    ascFile.addNote("_");
1750
5.27k
    return true;
1751
5.27k
  }
1752
1753
8.31k
  f << "Entries(Style):";
1754
8.31k
  f << "N=" << N;
1755
8.31k
  ascFile.addPos(pos);
1756
8.31k
  ascFile.addNote(f.str().c_str());
1757
1758
40.5k
  for (int i = 0; i < N; ++i) {
1759
32.8k
    pos = input->tell();
1760
32.8k
    if (!readStyle(stream, i)) {
1761
518
      f.str("");
1762
518
      f << "#Style-" << i << ":";
1763
518
      input->seek(pos, librevenge::RVNG_SEEK_SET);
1764
518
      ascFile.addPos(pos);
1765
518
      ascFile.addNote(f.str().c_str());
1766
518
      return false;
1767
518
    }
1768
32.8k
  }
1769
7.79k
  ascFile.addPos(input->tell());
1770
7.79k
  ascFile.addNote("_");
1771
1772
7.79k
  return true;
1773
8.31k
}
1774
1775
bool MacWrtProStructures::readStyle(std::shared_ptr<MWAWStream> &stream, int styleId)
1776
32.8k
{
1777
32.8k
  auto &input = stream->m_input;
1778
32.8k
  auto &ascFile = stream->m_ascii;
1779
32.8k
  long debPos = input->tell(), pos = debPos;
1780
32.8k
  libmwaw::DebugStream f;
1781
  // checkme something is odd here
1782
32.8k
  long dataSz = 0x106;
1783
32.8k
  long endPos = pos+dataSz;
1784
32.8k
  if (!stream->checkPosition(endPos)) {
1785
96
    MWAW_DEBUG_MSG(("MacWrtProStructures::readStyle: file is too short\n"));
1786
96
    return false;
1787
96
  }
1788
32.7k
  f << "Style-" << styleId << ":";
1789
32.7k
  auto strlen = static_cast<int>(input->readULong(1));
1790
32.7k
  if (!strlen || strlen > 31) {
1791
422
    MWAW_DEBUG_MSG(("MacWrtProStructures::readStyle: style name length seems bad!!\n"));
1792
422
    input->seek(pos, librevenge::RVNG_SEEK_SET);
1793
422
    return false;
1794
422
  }
1795
32.2k
  std::string name("");
1796
253k
  for (int i = 0; i < strlen; ++i) // default
1797
221k
    name+=char(input->readULong(1));
1798
32.2k
  f << name << ",";
1799
32.2k
  input->seek(pos+32, librevenge::RVNG_SEEK_SET); // probably end of name
1800
1801
32.2k
  int val;
1802
129k
  for (int i = 0; i < 3; ++i) { // 0 | [0,1,-1] | numTabs or idStyle?
1803
96.8k
    val = static_cast<int>(input->readLong(2));
1804
96.8k
    if (val) f << "f" << i << "=" << val << ",";
1805
96.8k
  }
1806
32.2k
  f << "date=" << MacWrtProParser::convertDateToDebugString(unsigned(input->readULong(4))) << ",";
1807
32.2k
  ascFile.addPos(pos);
1808
32.2k
  ascFile.addNote(f.str().c_str());
1809
1810
32.2k
  pos = input->tell();
1811
1812
32.2k
  f.str("");
1813
32.2k
  f << "Entries(Paragraph)[" << styleId << "]:";
1814
32.2k
  MacWrtProStructuresInternal::Paragraph para;
1815
32.2k
  if (!readParagraph(stream, para)) {
1816
0
    f << "#";
1817
0
    input->seek(pos+190, librevenge::RVNG_SEEK_SET);
1818
0
  }
1819
32.2k
  else
1820
32.2k
    f << para;
1821
32.2k
  ascFile.addPos(pos);
1822
32.2k
  ascFile.addNote(f.str().c_str());
1823
1824
32.2k
  pos = input->tell();
1825
32.2k
  f.str("");
1826
32.2k
  f << "Style-" << styleId << "(II):";
1827
32.2k
  val = static_cast<int>(input->readLong(2));
1828
32.2k
  if (val != -1) f << "nextId?=" << val << ",";
1829
32.2k
  val = static_cast<int>(input->readLong(1)); // -1 0 or 1
1830
32.2k
  if (val) f << "f0=" << val << ",";
1831
129k
  for (int i = 1; i < 4; ++i) { // 0, then 0|1
1832
96.8k
    val = static_cast<int>(input->readLong(i==3?1:2));
1833
96.8k
    if (val) f << "f" << i << "=" << val << ",";
1834
96.8k
  }
1835
32.2k
  ascFile.addPos(pos);
1836
32.2k
  ascFile.addNote(f.str().c_str());
1837
1838
32.2k
  pos = input->tell();
1839
32.2k
  MacWrtProStructuresInternal::Font font;
1840
32.2k
  if (!readFont(stream, font)) {
1841
0
    MWAW_DEBUG_MSG(("MacWrtProStructures::readStyle: end of style seems bad\n"));
1842
0
    ascFile.addPos(pos);
1843
0
    ascFile.addNote("Style:end###");
1844
0
    input->seek(endPos, librevenge::RVNG_SEEK_SET);
1845
0
    return true;
1846
0
  }
1847
1848
32.2k
  f.str("");
1849
32.2k
  f << "FontsDef:";
1850
32.2k
  f << font.m_font.getDebugString(m_parserState->m_fontConverter) << font << ",";
1851
32.2k
  ascFile.addPos(pos);
1852
32.2k
  ascFile.addNote(f.str().c_str());
1853
1854
32.2k
  pos = input->tell();
1855
1856
32.2k
  f.str("");
1857
32.2k
  f << "Style-" << styleId << "(end):";
1858
32.2k
  val = static_cast<int>(input->readLong(2));
1859
32.2k
  if (val!=-1) f << "unkn=" << val << ",";
1860
1861
32.2k
  ascFile.addPos(pos);
1862
32.2k
  ascFile.addNote(f.str().c_str());
1863
32.2k
  input->seek(endPos, librevenge::RVNG_SEEK_SET);
1864
32.2k
  return true;
1865
32.2k
}
1866
1867
////////////////////////////////////////////////////////////
1868
// read the pages
1869
bool MacWrtProStructures::readPagesListII(std::shared_ptr<MWAWStream> const &stream, int numPages)
1870
2.47k
{
1871
2.47k
  auto input=stream->m_input;
1872
2.47k
  long pos = input->tell();
1873
2.47k
  if (!stream->checkPosition(pos+50)) {
1874
394
    MWAW_DEBUG_MSG(("MacWrtProStructures::readPagesListII: can not find the page zone\n"));
1875
394
    return false;
1876
394
  }
1877
2.08k
  m_state->m_pagesList.resize(2+size_t(numPages));
1878
24.0k
  for (size_t p=0; p<2+size_t(numPages); ++p) {
1879
23.4k
    pos=input->tell();
1880
23.4k
    if (!readPageII(stream, int(p), m_state->m_pagesList[p])) {
1881
1.43k
      m_state->m_pagesList.resize(p);
1882
1.43k
      input->seek(pos,librevenge::RVNG_SEEK_SET);
1883
1.43k
      break;
1884
1.43k
    }
1885
23.4k
  }
1886
2.08k
  return true;
1887
2.47k
}
1888
1889
bool MacWrtProStructures::readPageII(std::shared_ptr<MWAWStream> const &stream, int wh, MacWrtProStructuresInternal::Page &page)
1890
23.4k
{
1891
23.4k
  auto input=stream->m_input;
1892
23.4k
  auto &ascFile=stream->m_ascii;
1893
23.4k
  long pos = input->tell();
1894
23.4k
  if (!stream->checkPosition(pos+12+66)) {
1895
1.43k
    MWAW_DEBUG_MSG(("MacWrtProStructures::readPageII: the zone is too short\n"));
1896
1.43k
    return false;
1897
1.43k
  }
1898
22.0k
  libmwaw::DebugStream f;
1899
22.0k
  std::string name;
1900
58.6k
  for (int i=0; i<4; ++i) {
1901
50.9k
    auto c=char(input->readULong(1));
1902
50.9k
    if (!c) break;
1903
36.6k
    name+=c;
1904
36.6k
  }
1905
22.0k
  if (!name.empty()) f << "name=" << name << ",";
1906
22.0k
  input->seek(pos+4, librevenge::RVNG_SEEK_SET);
1907
1908
22.0k
  page=MacWrtProStructuresInternal::Page();
1909
22.0k
  page.m_page = static_cast<int>(input->readLong(2));
1910
22.0k
  long val = input->readLong(1); // always -1 ?
1911
22.0k
  if (val>=1 && val<=5) {
1912
2.07k
    char const *what[]= {nullptr, "num", "Roman", "roman", "Alpha", "alpha"};
1913
2.07k
    f << "format=" << what[val] << ",";
1914
2.07k
  }
1915
19.9k
  else if (val != -1) f << "##format=" << val << ",";
1916
22.0k
  val = long(input->readULong(1)); // 0|80
1917
22.0k
  if (val) f << "fl=" << std::hex << val << std::dec << ",";
1918
66.0k
  for (int i = 0; i < 2; ++i) {
1919
44.0k
    int const expected[]= {0,1};
1920
44.0k
    val = input->readLong(2);
1921
44.0k
    if (val != expected[i]) f << "f" << i << "=" << val << ",";
1922
44.0k
  }
1923
22.0k
  page.m_extra=f.str();
1924
22.0k
  f.str("");
1925
22.0k
  f << "Entries(Page)[" << wh << "]:" << page;
1926
22.0k
  ascFile.addPos(pos);
1927
22.0k
  ascFile.addNote(f.str().c_str());
1928
22.0k
  int k=100*wh;
1929
22.4k
  while (!input->isEnd()) {
1930
22.4k
    pos=input->tell();
1931
22.4k
    auto graphic=std::make_shared<MacWrtProStructuresInternal::Graphic>(0);
1932
22.4k
    if (!readGraphicII(stream, ++k, page.m_graphicsList.empty(), *graphic)) {
1933
21.5k
      input->seek(pos, librevenge::RVNG_SEEK_SET);
1934
21.5k
      break;
1935
21.5k
    }
1936
888
    page.m_graphicsList.push_back(graphic);
1937
888
    if (graphic->m_lastFlag<0 || graphic->m_lastFlag>=2)
1938
479
      break;
1939
888
  }
1940
1941
22.0k
  return true;
1942
23.4k
}
1943
1944
bool MacWrtProStructures::readGraphicII(std::shared_ptr<MWAWStream> const &stream, int wh, bool mainBlock, MacWrtProStructuresInternal::Graphic &graphic)
1945
22.4k
{
1946
22.4k
  auto input=stream->m_input;
1947
22.4k
  auto &ascFile=stream->m_ascii;
1948
22.4k
  long pos = input->tell();
1949
22.4k
  libmwaw::DebugStream f;
1950
22.4k
  if (!stream->checkPosition(pos+76))
1951
1.12k
    return false;
1952
21.2k
  auto type = static_cast<int>(input->readLong(1)); // fd or 3
1953
21.2k
  long val;
1954
21.2k
  if (type<=-0x10 || type>=0x10) {
1955
6.14k
    input->seek(pos, librevenge::RVNG_SEEK_SET);
1956
6.14k
    return false;
1957
6.14k
  }
1958
15.1k
  long const expectedWidth[]= {
1959
15.1k
    -1, -1, -1, 76,
1960
15.1k
    -1, -1, -1, -1,
1961
15.1k
    -1, -1, -1, -1,
1962
15.1k
    -1, -1, -1, -1
1963
15.1k
  };
1964
15.1k
  long const len = expectedWidth[std::abs(type)];
1965
15.1k
  if (len==-1) {
1966
12.4k
    MWAW_DEBUG_MSG(("MacWrtProStructures::readGraphicII: unknown block %d\n", type));
1967
12.4k
    ascFile.addPos(pos);
1968
12.4k
    ascFile.addNote("Entries(Graphic):###");
1969
12.4k
    return false;
1970
12.4k
  }
1971
2.68k
  long endPos = pos+len;
1972
2.68k
  if (!stream->checkPosition(endPos)) {
1973
0
    input->seek(pos, librevenge::RVNG_SEEK_SET);
1974
0
    return false;
1975
0
  }
1976
2.68k
  graphic=MacWrtProStructuresInternal::Graphic(0);
1977
2.68k
  graphic.m_type=type;
1978
2.68k
  val = long(input->readULong(1)); // 0, 6a, 78, f2, fa : type ?
1979
2.68k
  if (val) f << "fl=" << std::hex << val << std::dec << ",";
1980
2.68k
  val = long(input->readULong(1));
1981
2.68k
  if (!mainBlock) {
1982
40
    graphic.m_textboxType=int(val>>6);
1983
40
    graphic.m_headerFooterFlag=int((val>>4)&3);
1984
40
    val &= 0xf;
1985
40
  }
1986
2.68k
  if (val) f << "f0=" << std::hex << val << std::dec << ",";
1987
2.68k
  f << "unkn0=[";
1988
18.7k
  for (int i = 0; i < 6; ++i) {
1989
16.0k
    val = long(input->readULong(i==0 ? 1 : 2));
1990
16.0k
    if (val==0) f << "_,";
1991
13.2k
    else f << std::hex << val << std::dec << ",";
1992
16.0k
  }
1993
2.68k
  f << "],";
1994
2.68k
  f << "unkn1=[";
1995
10.7k
  for (int i = 0; i < 3; ++i) { // big number ptr?, junk
1996
8.04k
    auto lVal = long(input->readULong(4));
1997
8.04k
    if (lVal==0) f << "_,";
1998
6.78k
    else f << std::hex << lVal << std::dec << ",";
1999
8.04k
  }
2000
2.68k
  f << "],";
2001
2.68k
  graphic.m_fileBlock = static_cast<int>(input->readULong(2));
2002
2.68k
  float dim[4];
2003
10.7k
  for (auto &d : dim) d = float(input->readLong(2));
2004
2.68k
  graphic.m_box = MWAWBox2f(MWAWVec2f(dim[1],dim[0]), MWAWVec2f(dim[3],dim[2]));
2005
2.68k
  if (dim[0]>dim[2] || dim[1]>dim[3] || (dim[2]<=0 && dim[3]<=0)) {
2006
    // bad box or (0,0,0,0) is clearly an indice of a problem
2007
1.74k
    input->seek(pos, librevenge::RVNG_SEEK_SET);
2008
1.74k
    return false;
2009
1.74k
  }
2010
4.69k
  for (int i = 0; i < 4; ++i) {
2011
    // 8000*4, probably the box decimal position ; unsure if 0x8000 means decal 0.5 pt or 0 pt, ...
2012
3.75k
    val = long(input->readULong(2));
2013
3.75k
    if (val != 0x8000) f << "g" << i+2 << "=" << float(val)/float(0x8000) << ",";
2014
3.75k
  }
2015
939
  graphic.m_textPos = int(input->readULong(1))<<16;
2016
939
  graphic.m_textPos += int(input->readULong(2));
2017
939
  if (graphic.m_textPos) {
2018
    // ok this is a soft page break block
2019
544
    graphic.m_page = graphic.m_fileBlock;
2020
544
    graphic.m_fileBlock = 0;
2021
544
  }
2022
939
  val = long(input->readULong(1));
2023
939
  if (val) f << "g6=" << std::hex << val << std::dec << ",";
2024
939
  f << "unkn=[";
2025
3.75k
  for (int i = 0; i < 3; ++i) { // often unkn[0]=unkn1[0] or unkn1[1], excepted when unkn1[0]==unkn1[1]==unkn1[2]
2026
2.81k
    auto lVal = long(input->readULong(4));
2027
2.81k
    if (lVal==0) f << "_,";
2028
1.80k
    else f << std::hex << lVal << std::dec << ",";
2029
2.81k
  }
2030
939
  f << "],";
2031
939
  graphic.m_column=int(input->readULong(1));
2032
939
  input->seek(1, librevenge::RVNG_SEEK_CUR);
2033
939
  graphic.m_colSeparator=float(input->readULong(4))/float(0x10000);
2034
939
  val=int(input->readLong(2)); // 0
2035
939
  if (val) f << "h0=" << val << ",";
2036
939
  val=int(input->readLong(2));
2037
939
  if (val) f << "nextPage=" << val+1 << ",";
2038
939
  auto ID=input->readULong(4); // 0 or big number if pageBreak
2039
939
  if (ID) f << "ID=" << std::hex << ID << std::dec << ",";
2040
939
  val=int(input->readLong(1)); // 0|ff
2041
939
  if (val!=-1) f << "k1=" << val << ",";
2042
939
  if (graphic.m_type==-3) endPos+=12;
2043
939
  if (val!=0)
2044
448
    endPos+=3;
2045
939
  if (!stream->checkPosition(endPos)) {
2046
51
    input->seek(pos, librevenge::RVNG_SEEK_SET);
2047
51
    return false;
2048
51
  }
2049
2050
888
  if (input->tell()!=endPos-1)
2051
564
    ascFile.addDelimiter(input->tell(),'|');
2052
888
  input->seek(endPos-1, librevenge::RVNG_SEEK_SET);
2053
888
  ascFile.addDelimiter(input->tell(),'|');
2054
888
  graphic.m_lastFlag=int(input->readLong(1));
2055
888
  if (graphic.m_lastFlag<0 || graphic.m_lastFlag>2) {
2056
452
    MWAW_DEBUG_MSG(("MacWrtProStructures::readGraphicII: unknown last value\n"));
2057
452
    f << "###isLast=" << graphic.m_lastFlag << ",";
2058
452
  }
2059
2060
888
  graphic.m_extra=f.str();
2061
888
  f.str("");
2062
888
  f << "Entries(Graphic)[" << wh << "]:" << graphic;
2063
888
  ascFile.addPos(pos);
2064
888
  ascFile.addNote(f.str().c_str());
2065
888
  return true;
2066
939
}
2067
2068
////////////////////////////////////////////////////////////
2069
// read the list of blocks
2070
bool MacWrtProStructures::readGraphicsList(std::shared_ptr<MWAWStream> &stream, int numPages)
2071
10.2k
{
2072
10.2k
  auto &input = stream->m_input;
2073
10.2k
  auto &ascFile = stream->m_ascii;
2074
10.2k
  long pos = input->tell();
2075
10.2k
  libmwaw::DebugStream f;
2076
2077
10.2k
  long endPos = pos+45;
2078
10.2k
  input->seek(endPos, librevenge::RVNG_SEEK_SET);
2079
10.2k
  if (long(input->tell()) != endPos) {
2080
943
    MWAW_DEBUG_MSG(("MacWrtProStructures::readGraphicsList: file is too short\n"));
2081
943
    input->seek(pos, librevenge::RVNG_SEEK_SET);
2082
943
    return false;
2083
943
  }
2084
9.35k
  input->seek(pos, librevenge::RVNG_SEEK_SET);
2085
9.35k
  f << "Entries(Graphic):";
2086
9.35k
  auto rev= static_cast<int>(input->readLong(4)); // 1 or 3
2087
9.35k
  f << "revision=" << rev << ",";
2088
9.35k
  auto uVal = input->readULong(4);
2089
9.35k
  if (uVal) f << "revision[min]=" << double(uVal)/60. << "',";
2090
9.35k
  long val;
2091
46.7k
  for (int i = 0; i < 4; ++i) { // [0|81|ff][0|03|33|63|ff][0|ff][0|ff]
2092
37.4k
    val = long(input->readULong(1));
2093
37.4k
    if (val) f << "flA" << i << "=" << std::hex << val << std::dec << ",";
2094
37.4k
  }
2095
9.35k
  val = input->readLong(4); // 0, 2, 46, 1479
2096
9.35k
  if (val) f << "f1=" << val << ",";
2097
46.7k
  for (int i = 0; i < 4; ++i) { // [0|1][0|74][0][0|4]
2098
37.4k
    val = long(input->readULong(1));
2099
37.4k
    if (val) f << "flB" << i << "=" << std::hex << val << std::dec << ",";
2100
37.4k
  }
2101
28.0k
  for (int i = 2; i < 4; ++i) { // [0|72] [0|a]
2102
18.7k
    val = input->readLong(2);
2103
18.7k
    if (val) f << "f" << i << "=" << val << ",";
2104
18.7k
  }
2105
9.35k
  val = long(input->readULong(4));
2106
9.35k
  if (val) f << "date=" << MacWrtProParser::convertDateToDebugString(unsigned(val)) << ",";
2107
2108
9.35k
  std::string str;
2109
9.35k
  if (!readString(input, str))
2110
452
    return false;
2111
8.90k
  if (str.length()) f << "dir='" << str << "',";
2112
8.90k
  val = input->readLong(2);
2113
8.90k
  if (val) f << "f4=" << val << ",";
2114
8.90k
  ascFile.addPos(pos);
2115
8.90k
  ascFile.addNote(f.str().c_str());
2116
2117
8.90k
  pos = input->tell();
2118
8.90k
  if (!stream->checkPosition(pos+6)) {
2119
131
    MWAW_DEBUG_MSG(("MacWrtProStructures::readGraphicsList: can not find the block zone\n"));
2120
131
    return false;
2121
131
  }
2122
8.77k
  f.str("");
2123
8.77k
  f << "Graphic-end:";
2124
8.77k
  ascFile.addPos(pos);
2125
8.77k
  ascFile.addNote(f.str().c_str());
2126
8.77k
  input->seek(6, librevenge::RVNG_SEEK_CUR);
2127
2128
8.77k
  int actPage=0;
2129
74.5k
  while (actPage<=numPages) {
2130
74.3k
    pos=input->tell();
2131
74.3k
    auto graphic = readGraphic(stream);
2132
74.3k
    if (!graphic) {
2133
22.1k
      input->seek(pos, librevenge::RVNG_SEEK_SET);
2134
22.1k
      if (stream->checkPosition(pos+2) && input->readULong(2)==0x7fff) {
2135
13.6k
        f.str("");
2136
13.6k
        f << "Graphic-Pg" << actPage++ << ",";
2137
13.6k
        ascFile.addPos(pos);
2138
13.6k
        ascFile.addNote(f.str().c_str());
2139
13.6k
        continue;
2140
13.6k
      }
2141
8.52k
      input->seek(pos, librevenge::RVNG_SEEK_SET);
2142
8.52k
      break;
2143
22.1k
    }
2144
52.1k
    m_state->m_graphicsList.push_back(graphic);
2145
52.1k
    if (m_state->m_idGraphicMap.find(graphic->m_id) != m_state->m_idGraphicMap.end()) {
2146
1.08k
      MWAW_DEBUG_MSG(("MacWrtProStructures::readGraphicsList: graphic %d already exists\n", graphic->m_id));
2147
1.08k
    }
2148
51.0k
    else
2149
51.0k
      m_state->m_idGraphicMap[graphic->m_id] = graphic;
2150
52.1k
    if (graphic->isGraphic() || graphic->isText())
2151
31.6k
      m_mainParser.parseDataZone(graphic->m_fileBlock, graphic->isGraphic() ? 1 : 0);
2152
52.1k
  }
2153
8.77k
  return true;
2154
8.90k
}
2155
2156
std::shared_ptr<MacWrtProStructuresInternal::Graphic> MacWrtProStructures::readGraphic(std::shared_ptr<MWAWStream> &stream)
2157
74.3k
{
2158
74.3k
  auto &input = stream->m_input;
2159
74.3k
  auto &ascFile = stream->m_ascii;
2160
74.3k
  long pos = input->tell();
2161
74.3k
  libmwaw::DebugStream f;
2162
74.3k
  int type=int(input->readLong(2));
2163
74.3k
  if (type<-3 || type>2) { // normally -2..1
2164
16.4k
    input->seek(pos, librevenge::RVNG_SEEK_SET);
2165
16.4k
    return std::shared_ptr<MacWrtProStructuresInternal::Graphic>();
2166
16.4k
  }
2167
57.8k
  f << "type=" << type << ",";
2168
57.8k
  auto sz = long(input->readULong(4));
2169
  // pat2*3?, dim[pt*65536], border[pt*65536], ?, [0|10|1c], 0, graphic?
2170
57.8k
  if (sz < 0x40) {
2171
1.16k
    input->seek(pos, librevenge::RVNG_SEEK_SET);
2172
1.16k
    return std::shared_ptr<MacWrtProStructuresInternal::Graphic>();
2173
1.16k
  }
2174
2175
56.7k
  long endPos = pos+sz+6;
2176
56.7k
  if (!stream->checkPosition(endPos)) {
2177
4.53k
    input->seek(pos, librevenge::RVNG_SEEK_SET);
2178
4.53k
    return std::shared_ptr<MacWrtProStructuresInternal::Graphic>();
2179
4.53k
  }
2180
2181
52.1k
  auto graphic=std::make_shared<MacWrtProStructuresInternal::Graphic>(1);
2182
52.1k
  long val;
2183
52.1k
  f << "pat?=[" << std::hex;
2184
156k
  for (int i = 0; i < 2; ++i)
2185
104k
    f << input->readULong(2) << ",";
2186
52.1k
  f << std::dec << "],";
2187
52.1k
  graphic->m_type = static_cast<int>(input->readULong(2));
2188
52.1k
  float dim[4];
2189
208k
  for (auto &d : dim) d = float(input->readLong(4))/65536.f;
2190
52.1k
  graphic->m_box = MWAWBox2f(MWAWVec2f(dim[1],dim[0]), MWAWVec2f(dim[3],dim[2]));
2191
2192
52.1k
  static int const wh[4] = { libmwaw::Top, libmwaw::Left, libmwaw::Bottom, libmwaw::Right };
2193
52.1k
  for (auto what : wh)
2194
208k
    graphic->m_borderWList[what]=double(input->readLong(4))/65536.;
2195
2196
  /* 4: pagebreak,
2197
     5: text
2198
     1: floating, 7: none(wrapping/attachment), b: attachment
2199
     0/a: table ?
2200
  */
2201
156k
  for (int i = 0; i < 2; ++i) {
2202
104k
    val = long(input->readULong(2));
2203
104k
    if (val)
2204
100k
      f << "fl" << i << "=" << std::hex << val << std::dec << ",";
2205
104k
  }
2206
52.1k
  val = input->readLong(2);
2207
52.1k
  if (val) f << "f0=" << val << ",";
2208
52.1k
  graphic->m_fileBlock = static_cast<int>(input->readLong(2));
2209
52.1k
  graphic->m_id = static_cast<int>(input->readLong(2));
2210
52.1k
  val = static_cast<int>(input->readLong(2)); // almost always 4 ( one time 0)
2211
52.1k
  if (val!=4)
2212
7.56k
    f << "bordOffset=" << val << ",";
2213
313k
  for (int i = 2; i < 7; ++i) {
2214
    /* always 0, except f3=-1 (in one file),
2215
       and in other file f4=1,f5=1,f6=1, */
2216
260k
    val = static_cast<int>(input->readLong(2));
2217
260k
    if (val) f << "f" << i << "=" << val << ",";
2218
260k
  }
2219
52.1k
  graphic->m_baseline = float(input->readLong(4))/65536.f;
2220
52.1k
  auto colorId = static_cast<int>(input->readLong(2));
2221
52.1k
  auto patId=static_cast<int>(input->readLong(2));
2222
52.1k
  MWAWColor color(MWAWColor::white());
2223
52.1k
  if (getColor(colorId, patId, color))
2224
47.8k
    graphic->m_surfaceColor = color;
2225
4.35k
  else
2226
4.35k
    f << "#colorId=" << colorId << ", #patId=" << patId << ",";
2227
2228
52.1k
  colorId = static_cast<int>(input->readLong(2));
2229
52.1k
  patId=static_cast<int>(input->readLong(2));
2230
52.1k
  if (getColor(colorId, patId, color))
2231
49.1k
    graphic->m_lineBorder.m_color = color;
2232
2.99k
  else
2233
2.99k
    f << "line[#colorId=" << colorId << ", #patId[line]=" << patId << "],";
2234
52.1k
  val = input->readLong(2);
2235
52.1k
  static double const w[9]= {0,0.5,1,2,4,6,8,10,12};
2236
52.1k
  if (val>0&&val<10)
2237
45.0k
    graphic->m_lineBorder.m_width = w[val-1];
2238
7.09k
  else
2239
7.09k
    f << "#lineWidth=" << val << ",";
2240
52.1k
  val = input->readLong(2);
2241
52.1k
  if (!m_state->updateLineType(static_cast<int>(val), graphic->m_lineBorder))
2242
7.03k
    f << "#line[type]=" << val << ",";
2243
52.1k
  auto contentType = static_cast<int>(input->readULong(1));
2244
52.1k
  switch (contentType) {
2245
47.8k
  case 0:
2246
47.8k
    graphic->m_contentType = MacWrtProStructuresInternal::Graphic::TEXT;
2247
47.8k
    break;
2248
3.22k
  case 1:
2249
3.22k
    graphic->m_contentType = MacWrtProStructuresInternal::Graphic::GRAPHIC;
2250
3.22k
    break;
2251
1.06k
  default:
2252
1.06k
    MWAW_DEBUG_MSG(("MacWrtProStructures::readGraphic: find unknown block content type\n"));
2253
1.06k
    f << "#contentType=" << contentType << ",";
2254
1.06k
    break;
2255
52.1k
  }
2256
2257
52.1k
  bool isNote = false;
2258
52.1k
  if (graphic->m_type==4 && sz == 0xa0) {
2259
    // this can be a note, let check
2260
8
    isNote=true;
2261
8
    static double const expectedWidth[4] = {5,5,19,5};
2262
8
    for (int i=0; i < 4; ++i) {
2263
8
      if (graphic->m_borderWList[i]<expectedWidth[i] ||
2264
8
          graphic->m_borderWList[i]>expectedWidth[i]) {
2265
8
        isNote = false;
2266
8
        break;
2267
8
      }
2268
8
    }
2269
8
  }
2270
52.1k
  if (isNote) {
2271
0
    long actPos = input->tell();
2272
0
    ascFile.addDelimiter(pos+118,'|');
2273
0
    input->seek(pos+118, librevenge::RVNG_SEEK_SET);
2274
0
    val = input->readLong(2);
2275
0
    isNote = val==0 || val==0x100;
2276
0
    if (isNote) {
2277
0
      float dim2[4];
2278
0
      for (auto &d : dim2) {
2279
0
        d = float(input->readLong(4))/65536.f;
2280
0
        if (!val && (d<0||d>0)) {
2281
0
          isNote = false;
2282
0
          break;
2283
0
        }
2284
0
      }
2285
0
      if (isNote && val) {
2286
        // ok, reset the box only if it is bigger
2287
0
        if (dim2[3]-dim2[1]>dim[3]-dim[1] && dim2[2]-dim2[0]>dim[2]-dim[0])
2288
0
          graphic->m_box=MWAWBox2f(MWAWVec2f(dim2[1],dim2[0]),MWAWVec2f(dim2[3],dim2[2]));
2289
0
      }
2290
0
    }
2291
0
    if (isNote) {
2292
0
      graphic->m_contentType = MacWrtProStructuresInternal::Graphic::NOTE;
2293
      // ok reset the border and the line color to gray
2294
0
      for (int i = 0; i < 4; ++i) {
2295
0
        if (i!=libmwaw::Top)
2296
0
          graphic->m_borderWList[i]=1;
2297
0
      }
2298
0
      graphic->m_lineBorder=MWAWBorder();
2299
0
      graphic->m_lineBorder.m_color=MWAWColor(128,128,128);
2300
2301
0
      if (val)
2302
0
        f << "note[closed],";
2303
0
      else
2304
0
        f << "note,";
2305
0
    }
2306
0
    input->seek(actPos, librevenge::RVNG_SEEK_SET);
2307
0
  }
2308
52.1k
  else if (graphic->m_type==4 && sz == 0x9a) {
2309
5.97k
    long actPos = input->tell();
2310
5.97k
    ascFile.addDelimiter(pos+110,'|');
2311
5.97k
    input->seek(pos+110, librevenge::RVNG_SEEK_SET);
2312
5.97k
    libmwaw::DebugStream f2;
2313
29.8k
    for (int i=0; i<4; ++i) {
2314
23.9k
      MWAWBorder border;
2315
23.9k
      colorId = static_cast<int>(input->readLong(2));
2316
23.9k
      patId=static_cast<int>(input->readLong(2));
2317
23.9k
      f2.str("");
2318
23.9k
      if (getColor(colorId, patId, color))
2319
21.4k
        border.m_color=color;
2320
2.50k
      else
2321
2.50k
        f2 << "#colorId=" << colorId << ", #patId=" << patId << ",";
2322
23.9k
      val= input->readLong(2);
2323
23.9k
      if (val > 0 && val < 10)
2324
19.9k
        border.m_width=w[val-1];
2325
3.98k
      else
2326
3.98k
        f2 << "#w[line]=" << val << ",";
2327
23.9k
      val= input->readLong(2);
2328
23.9k
      if (!m_state->updateLineType(static_cast<int>(val), border))
2329
4.02k
        f2 << "#border[type]=" << val << ",";
2330
23.9k
      val=input->readLong(2);
2331
23.9k
      if (int(val)!=i)
2332
5.59k
        f2 << "#id=" << val << ",";
2333
23.9k
      border.m_extra = f2.str();
2334
23.9k
      graphic->m_borderCellList[wh[i]]=border;
2335
23.9k
    }
2336
5.97k
    input->seek(actPos, librevenge::RVNG_SEEK_SET);
2337
5.97k
  }
2338
2339
52.1k
  graphic->m_extra = f.str();
2340
2341
52.1k
  f.str("");
2342
52.1k
  f << "Graphic-B" << m_state->m_graphicsList.size() << ":" << *graphic;
2343
52.1k
  ascFile.addPos(pos);
2344
52.1k
  ascFile.addNote(f.str().c_str());
2345
2346
52.1k
  if (long(input->tell()) != endPos)
2347
52.1k
    ascFile.addDelimiter(input->tell(), '|');
2348
2349
52.1k
  input->seek(endPos, librevenge::RVNG_SEEK_SET);
2350
2351
  // ok now read the end of the header
2352
52.1k
  pos = input->tell();
2353
52.1k
  if (stream->checkPosition(pos+6)) {
2354
51.9k
    f.str("");
2355
51.9k
    f << "Graphic-data-B" << m_state->m_graphicsList.size()<< "[" << graphic->m_type << "]:";
2356
51.9k
    switch (graphic->m_type) {
2357
4.85k
    case 3: { // table
2358
4.85k
      graphic->m_row = static_cast<int>(input->readLong(2));
2359
4.85k
      graphic->m_col = static_cast<int>(input->readLong(2));
2360
4.85k
      f << "numRow=" << graphic->m_row << ",";
2361
4.85k
      f << "numCol=" << graphic->m_col << ",";
2362
4.85k
      break;
2363
0
    }
2364
16.1k
    case 4: { // cell/textbox : no sure it contain data?
2365
16.1k
      val =  input->readLong(2); // always 0 ?
2366
16.1k
      if (val) f << "f0=" << val << ",";
2367
16.1k
      val = long(input->readULong(2)); // [0|10|1e|10c0|1cc0|a78a|a7a6|d0c0|dcc0]
2368
16.1k
      if (val) f << "fl?=" << std::hex << val << std::dec << ",";
2369
16.1k
      break;
2370
0
    }
2371
13.3k
    case 5: { // text or ?
2372
13.3k
      bool emptyBlock = graphic->m_fileBlock <= 0;
2373
13.3k
      val = long(input->readULong(2));  // always 0 ?
2374
13.3k
      if (emptyBlock) {
2375
8.50k
        if (val & 0xFF00)
2376
897
          f << "#f0=" << val << ",";
2377
8.50k
        graphic->m_textPos=int(((val&0xFF)<<16) | static_cast<int>(input->readULong(2)));
2378
8.50k
        f << "posC=" << graphic->m_textPos << ",";
2379
8.50k
      }
2380
4.80k
      else if (val) f << "f0=" << val << ",";
2381
13.3k
      val = long(input->readULong(2)); // 30c0[normal], 20c0|0[empty]
2382
13.3k
      f << "fl?=" << std::hex << val << ",";
2383
13.3k
      break;
2384
0
    }
2385
10.1k
    case 6: {
2386
50.8k
      for (int i = 0; i < 4; ++i) { // [10|d0],40, 0, 0
2387
40.7k
        val = long(input->readULong(1));
2388
40.7k
        f << "f" << i << "=" << val << ",";
2389
40.7k
      }
2390
10.1k
      val =  input->readLong(1);
2391
10.1k
      switch (val) {
2392
5.00k
      case 1:
2393
5.00k
        f << "header,";
2394
5.00k
        graphic->m_isHeader = true;
2395
5.00k
        break;
2396
4.94k
      case 2:
2397
4.94k
        f << "footer,";
2398
4.94k
        graphic->m_isHeader = false;
2399
4.94k
        break;
2400
225
      default:
2401
225
        MWAW_DEBUG_MSG(("MacWrtProStructures::readGraphic: find unknown header/footer type\n"));
2402
225
        f << "#type=" << val << ",";
2403
225
        break;
2404
10.1k
      }
2405
10.1k
      val =  input->readLong(1); // alway 1 ?
2406
10.1k
      if (val != 1) f << "f4=" << val << ",";
2407
10.1k
      break;
2408
10.1k
    }
2409
3.65k
    case 7: { // footnote: something here ?
2410
14.6k
      for (int i = 0; i < 3; ++i) { // 0, 0, [0|4000]
2411
10.9k
        val = long(input->readULong(2));
2412
10.9k
        f << "f" << i << "=" << std::hex << val << std::dec << ",";
2413
10.9k
      }
2414
3.65k
      break;
2415
10.1k
    }
2416
66
    case 8:
2417
66
      break; // graphic: clearly nothing
2418
3.68k
    default:
2419
3.68k
      break;
2420
51.9k
    }
2421
51.9k
    ascFile.addPos(pos);
2422
51.9k
    ascFile.addNote(f.str().c_str());
2423
51.9k
    input->seek(pos+6, librevenge::RVNG_SEEK_SET);
2424
51.9k
  }
2425
2426
52.1k
  return graphic;
2427
52.1k
}
2428
2429
////////////////////////////////////////////////////////////
2430
// read the column information zone : checkme
2431
bool MacWrtProStructures::readSections(std::shared_ptr<MWAWStream> &stream, std::vector<MacWrtProStructuresInternal::Section> &sections)
2432
22.3k
{
2433
22.3k
  auto &input = stream->m_input;
2434
22.3k
  auto &ascFile = stream->m_ascii;
2435
22.3k
  long pos = input->tell();
2436
22.3k
  libmwaw::DebugStream f;
2437
2438
22.3k
  auto sz = long(input->readULong(4));
2439
22.3k
  if (sz == 0) {
2440
8.67k
    ascFile.addPos(pos);
2441
8.67k
    ascFile.addNote("_");
2442
8.67k
    return true;
2443
8.67k
  }
2444
13.7k
  long endPos = pos+4+sz;
2445
13.7k
  if ((sz%0xd8)) {
2446
1.42k
    MWAW_DEBUG_MSG(("MacWrtProStructures::readSections: find an odd value for sz\n"));
2447
1.42k
    ascFile.addPos(pos);
2448
1.42k
    ascFile.addNote("Entries(Sections)#");
2449
1.42k
    input->seek(endPos, librevenge::RVNG_SEEK_SET);
2450
1.42k
    return true;
2451
1.42k
  }
2452
12.2k
  if (!stream->checkPosition(endPos)) {
2453
196
    MWAW_DEBUG_MSG(("MacWrtProStructures::readSections: section is outside of the input\n"));
2454
196
    return true;
2455
196
  }
2456
2457
12.0k
  auto N = int(sz/0xd8);
2458
12.0k
  f << "Entries(Section):";
2459
12.0k
  f << "N=" << N;
2460
12.0k
  ascFile.addPos(pos);
2461
12.0k
  ascFile.addNote(f.str().c_str());
2462
2463
42.0k
  for (int n = 0; n < N; ++n) {
2464
29.9k
    MacWrtProStructuresInternal::Section sec;
2465
29.9k
    pos = input->tell();
2466
29.9k
    f.str("");
2467
29.9k
    sec.m_textLength = long(input->readULong(4));
2468
29.9k
    long val =  input->readLong(4); // almost always 0 or a dim?
2469
29.9k
    if (val) f << "dim?=" << float(val)/65536.f << ",";
2470
29.9k
    auto startWay = static_cast<int>(input->readLong(2));
2471
29.9k
    switch (startWay) {
2472
11.3k
    case 1:
2473
11.3k
      sec.m_start = sec.S_Line;
2474
11.3k
      break;
2475
15.7k
    case 2:
2476
15.7k
      sec.m_start = sec.S_Page;
2477
15.7k
      break;
2478
130
    case 3:
2479
130
      sec.m_start = sec.S_PageLeft;
2480
130
      break;
2481
14
    case 4:
2482
14
      sec.m_start = sec.S_PageRight;
2483
14
      break;
2484
2.77k
    default:
2485
2.77k
      MWAW_DEBUG_MSG(("MacWrtProStructures::readSections: find an odd value for start\n"));
2486
2.77k
      f << "#start=" << startWay << ",";
2487
29.9k
    }
2488
29.9k
    val = input->readLong(2);
2489
29.9k
    if (val)
2490
28.1k
      f << "f0=" << val << ",";
2491
    // a flag ? and noused ?
2492
89.9k
    for (int i = 0; i < 2; ++i) {
2493
59.9k
      val = long(input->readULong(1));
2494
59.9k
      if (val == 0xFF) f << "fl" << i<< "=true,";
2495
59.2k
      else if (val) f << "fl" << i << "=" << std::hex << val << std::dec << ",";
2496
59.9k
    }
2497
2498
89.9k
    for (int st = 0; st < 2; ++st) {
2499
59.9k
      val = input->readLong(2); // alway 1 ?
2500
59.9k
      if (val != 1) f << "f" << 1+st << "=" << val << ",";
2501
      // another flag ?
2502
59.9k
      val = long(input->readULong(1));
2503
59.9k
      if (val) f << "fl" << st+2 << "=" << std::hex << val << std::dec << ",";
2504
59.9k
    }
2505
29.9k
    auto numColumns = static_cast<int>(input->readLong(2));
2506
29.9k
    if (numColumns < 1 || numColumns > 20) {
2507
2.93k
      MWAW_DEBUG_MSG(("MacWrtProStructures::readSections: bad number of columns\n"));
2508
2.93k
      f << "#nCol=" << numColumns << ",";
2509
2.93k
      numColumns = 1;
2510
2.93k
    }
2511
29.9k
    val = input->readLong(2); // find: 3, c, 24
2512
29.9k
    if (val) f << "f3=" << val << ",";
2513
119k
    for (int i = 4; i < 7; ++i) { // always 0 ?
2514
89.9k
      val = input->readLong(2);
2515
89.9k
      if (val)
2516
7.14k
        f << "f" << i << "=" << val << ",";
2517
89.9k
    }
2518
29.9k
    long actPos = input->tell();
2519
121k
    for (int c = 0; c < 2*numColumns; ++c)
2520
91.9k
      sec.m_colsPos.push_back(float(input->readLong(4))/65536.f);
2521
29.9k
    input->seek(actPos+20*8+4, librevenge::RVNG_SEEK_SET);
2522
    // 5 flags ( 1+unused?)
2523
209k
    for (int i = 0; i < 6; ++i) {
2524
179k
      val = long(input->readULong(1));
2525
179k
      if ((i!=5 && val!=1) || (i==5 && val))
2526
17.8k
        f << "g" << i << "=" << val << ",";
2527
179k
    }
2528
89.9k
    for (int st = 0; st < 2; ++st) { // pair, unpair?
2529
179k
      for (int i = 0; i < 2; ++i) { // header/footer
2530
119k
        val = input->readLong(2);
2531
119k
        if (val)
2532
8.10k
          f << "#h" << 2*st+i << "=" << val << ",";
2533
2534
119k
        val = input->readLong(2);
2535
119k
        if (i==0) sec.m_headerIds[st] = static_cast<int>(val);
2536
59.9k
        else sec.m_footerIds[st] = static_cast<int>(val);
2537
119k
      }
2538
59.9k
    }
2539
29.9k
    sec.m_extra=f.str();
2540
29.9k
    sections.push_back(sec);
2541
2542
29.9k
    f.str("");
2543
29.9k
    f << "Section" << "-" << n << ":" << sec;
2544
29.9k
    ascFile.addPos(pos);
2545
29.9k
    ascFile.addNote(f.str().c_str());
2546
29.9k
    input->seek(pos+0xd8, librevenge::RVNG_SEEK_SET);
2547
29.9k
  }
2548
2549
12.0k
  input->seek(endPos, librevenge::RVNG_SEEK_SET);
2550
12.0k
  return true;
2551
12.0k
}
2552
2553
////////////////////////////////////////////////////////////
2554
// read the selection zone
2555
bool MacWrtProStructures::readSelection(std::shared_ptr<MWAWStream> &stream)
2556
12.7k
{
2557
12.7k
  auto &input = stream->m_input;
2558
12.7k
  auto &ascFile = stream->m_ascii;
2559
12.7k
  long pos = input->tell();
2560
12.7k
  libmwaw::DebugStream f;
2561
2562
12.7k
  long endPos = pos+14;
2563
12.7k
  if (!stream->checkPosition(endPos)) {
2564
0
    MWAW_DEBUG_MSG(("MacWrtProStructures::readSelection: file is too short\n"));
2565
0
    return false;
2566
0
  }
2567
12.7k
  f << "Entries(Selection):";
2568
12.7k
  auto val = static_cast<int>(input->readLong(2));
2569
12.7k
  f << "f0=" << val << ","; // zone?
2570
12.7k
  val = static_cast<int>(input->readLong(4)); // -1, 0 or 8 : zone type?
2571
12.7k
  if (val == -1 || val == 0) { // checkme: none ?
2572
4.67k
    f << "*";
2573
4.67k
    ascFile.addPos(pos);
2574
4.67k
    ascFile.addNote(f.str().c_str());
2575
4.67k
    input->seek(pos+6, librevenge::RVNG_SEEK_SET);
2576
4.67k
    return true;
2577
4.67k
  }
2578
8.10k
  if (val!=8) f << "f1=" << val << ",";
2579
8.10k
  f << "char=";
2580
24.3k
  for (int i = 0; i < 2; ++i) {
2581
16.2k
    f << input->readULong(4);
2582
16.2k
    if (i==0) f << "x";
2583
8.10k
    else f << ",";
2584
16.2k
  }
2585
8.10k
  ascFile.addPos(pos);
2586
8.10k
  ascFile.addNote(f.str().c_str());
2587
2588
8.10k
  input->seek(endPos, librevenge::RVNG_SEEK_SET);
2589
8.10k
  return true;
2590
12.7k
}
2591
2592
////////////////////////////////////////////////////////////
2593
// read a string
2594
bool MacWrtProStructures::readString(MWAWInputStreamPtr input, std::string &res)
2595
31.1k
{
2596
31.1k
  res="";
2597
31.1k
  long pos = input->tell();
2598
31.1k
  auto sz = static_cast<int>(input->readLong(2));
2599
31.1k
  if (sz == 0) return true;
2600
12.1k
  if (sz < 0) {
2601
330
    input->seek(pos, librevenge::RVNG_SEEK_SET);
2602
330
    MWAW_DEBUG_MSG(("MacWrtProStructures::readString: odd value for size\n"));
2603
330
    return false;
2604
330
  }
2605
11.8k
  if (!input->checkPosition(pos+sz+2)) {
2606
684
    input->seek(pos, librevenge::RVNG_SEEK_SET);
2607
684
    MWAW_DEBUG_MSG(("MacWrtProStructures::readString: file is too short\n"));
2608
684
    return false;
2609
684
  }
2610
117k
  for (int i= 0; i < sz; ++i) {
2611
107k
    auto c = char(input->readULong(1));
2612
107k
    if (c) {
2613
106k
      res+=c;
2614
106k
      continue;
2615
106k
    }
2616
511
    if (i==sz-1) break;
2617
2618
338
    input->seek(pos, librevenge::RVNG_SEEK_SET);
2619
338
    MWAW_DEBUG_MSG(("MacWrtProStructures::readString: find odd character in string\n"));
2620
338
    return false;
2621
511
  }
2622
10.8k
  return true;
2623
11.1k
}
2624
2625
////////////////////////////////////////////////////////////
2626
// read an unknown zone
2627
bool MacWrtProStructures::readStructB(std::shared_ptr<MWAWStream> &stream)
2628
12.4k
{
2629
12.4k
  auto &input = stream->m_input;
2630
12.4k
  auto &ascFile = stream->m_ascii;
2631
12.4k
  long pos = input->tell();
2632
12.4k
  libmwaw::DebugStream f;
2633
2634
12.4k
  auto N = static_cast<int>(input->readULong(2));
2635
12.4k
  if (N==0) {
2636
4.59k
    ascFile.addPos(pos);
2637
4.59k
    ascFile.addNote("_");
2638
4.59k
    return true;
2639
4.59k
  }
2640
7.82k
  f << "Entries(StructB):N=" << N << ",";
2641
2642
  // CHECKME: find N=2 only one time ( and across a checksum zone ...)
2643
7.82k
  long endPos = pos+N*10+6;
2644
7.82k
  if (!stream->checkPosition(endPos)) {
2645
221
    MWAW_DEBUG_MSG(("MacWrtProStructures::readZonB: file is too short\n"));
2646
221
    input->seek(pos, librevenge::RVNG_SEEK_SET);
2647
221
    return false;
2648
221
  }
2649
7.60k
  auto val = static_cast<int>(input->readULong(2));
2650
7.60k
  if (val != 0x2af8)
2651
175
    f << "f0=" << std::hex << val << std::dec << ",";
2652
7.60k
  val = static_cast<int>(input->readULong(2));
2653
7.60k
  if (val) f << "f1=" << val << ",";
2654
2655
7.60k
  ascFile.addPos(pos);
2656
7.60k
  ascFile.addNote(f.str().c_str());
2657
2658
24.9k
  for (int n = 0; n < N; ++n) {
2659
17.3k
    pos = input->tell();
2660
17.3k
    f.str("");
2661
17.3k
    f << "StructB" << "-" << n;
2662
17.3k
    ascFile.addPos(pos);
2663
17.3k
    ascFile.addNote(f.str().c_str());
2664
17.3k
    input->seek(pos+10, librevenge::RVNG_SEEK_SET);
2665
17.3k
  }
2666
7.60k
  return true;
2667
7.82k
}
2668
2669
////////////////////////////////////////////////////////////
2670
// check if a block is sent
2671
bool MacWrtProStructures::isSent(int graphicId)
2672
2.07k
{
2673
2.07k
  if (m_state->m_idGraphicMap.find(graphicId) == m_state->m_idGraphicMap.end()) {
2674
563
    MWAW_DEBUG_MSG(("MacWrtProStructures::isSent: can not find the block %d\n", graphicId));
2675
563
    return true;
2676
563
  }
2677
1.51k
  return m_state->m_idGraphicMap.find(graphicId)->second->m_send;
2678
2.07k
}
2679
2680
////////////////////////////////////////////////////////////
2681
// send a block
2682
bool MacWrtProStructures::send(int graphicId, bool mainZone)
2683
59.6k
{
2684
59.6k
  MWAWTextListenerPtr listener=m_parserState->m_textListener;
2685
59.6k
  if (version()==0) {
2686
307
    if (m_state->m_idGraphicMap.find(graphicId)==m_state->m_idGraphicMap.end()) {
2687
0
      MWAW_DEBUG_MSG(("MacWrtProStructures::send: can not find the graphic %d\n", graphicId));
2688
0
      return false;
2689
0
    }
2690
307
    MWAWVec2i const gId(graphicId, 0);
2691
307
    if (m_state->m_graphicsSendSet.find(gId)!=m_state->m_graphicsSendSet.end()) {
2692
5
      MWAW_DEBUG_MSG(("MacWrtProStructures::send: oops find a loop for %d\n", graphicId));
2693
5
      return false;
2694
5
    }
2695
2696
302
    m_state->m_graphicsSendSet.insert(gId);
2697
302
    auto graphic=m_state->m_idGraphicMap.find(graphicId)->second;
2698
302
    graphic->m_send = true;
2699
302
    if (graphic->m_fileBlock>0)
2700
201
      m_mainParser.sendTextZone(graphic->m_fileBlock, mainZone);
2701
302
    m_state->m_graphicsSendSet.insert(gId);
2702
2703
302
    return true;
2704
307
  }
2705
59.3k
  if (m_state->m_idGraphicMap.find(graphicId) == m_state->m_idGraphicMap.end()) {
2706
5.30k
    MWAW_DEBUG_MSG(("MacWrtProStructures::send: can not find the block %d\n", graphicId));
2707
5.30k
    return false;
2708
5.30k
  }
2709
54.0k
  auto graphic = m_state->m_idGraphicMap.find(graphicId)->second;
2710
54.0k
  MWAWVec2i graphicIdMain(graphicId, (mainZone ? 1 : 0) + (graphic->m_textboxCellType ? 2 : 0)
2711
54.0k
                          +(!graphic->m_attachment ? 4 : 0));
2712
54.0k
  if (m_state->m_graphicsSendSet.find(graphicIdMain)!=m_state->m_graphicsSendSet.end()) {
2713
103
    MWAW_DEBUG_MSG(("MacWrtProStructures::send: oops find a loop for %d\n", graphicId));
2714
103
    return false;
2715
103
  }
2716
53.9k
  m_state->m_graphicsSendSet.insert(graphicIdMain);
2717
53.9k
  graphic->m_send = true;
2718
53.9k
  if (graphic->m_type == 4 && graphic->m_textboxCellType == 0) {
2719
6.84k
    graphic->m_textboxCellType = 2;
2720
6.84k
    MWAWGraphicStyle style;
2721
6.84k
    graphic->fillFrame(style);
2722
6.84k
    m_mainParser.sendTextBoxZone(graphicId, graphic->getPosition(), style);
2723
6.84k
    graphic->m_textboxCellType = 0;
2724
6.84k
  }
2725
47.0k
  else if (graphic->isText())
2726
30.6k
    m_mainParser.sendTextZone(graphic->m_fileBlock, mainZone);
2727
16.3k
  else if (graphic->isGraphic()) {
2728
3.20k
    MWAWGraphicStyle style;
2729
3.20k
    graphic->fillFrame(style);
2730
3.20k
    m_mainParser.sendPictureZone(graphic->m_fileBlock, graphic->getPosition(), style);
2731
3.20k
  }
2732
13.1k
  else if (graphic->m_type == 3) {
2733
6.91k
    if (m_state->m_tablesMap.find(graphicId) == m_state->m_tablesMap.end()) {
2734
1.77k
      MWAW_DEBUG_MSG(("MacWrtProStructures::send: can not find table with id=%d\n", graphicId));
2735
1.77k
    }
2736
5.14k
    else {
2737
5.14k
      bool needTextBox = listener && !graphic->m_attachment && graphic->m_textboxCellType == 0;
2738
5.14k
      if (needTextBox) {
2739
2.03k
        graphic->m_textboxCellType = 2;
2740
2.03k
        m_mainParser.sendTextBoxZone(graphicId, graphic->getPosition());
2741
2.03k
      }
2742
3.10k
      else {
2743
3.10k
        auto table = m_state->m_tablesMap.find(graphicId)->second;
2744
3.10k
        if (!table->sendTable(listener))
2745
298
          table->sendAsText(listener);
2746
3.10k
        graphic->m_textboxCellType = 0;
2747
3.10k
      }
2748
5.14k
    }
2749
6.91k
  }
2750
6.26k
  else if (graphic->m_type == 4 || graphic->m_type == 6) {
2751
    // probably ok, can be an empty cell, textbox, header/footer ..
2752
6.01k
    if (listener) listener->insertChar(' ');
2753
6.01k
  }
2754
244
  else if (graphic->m_type == 8) {   // empty frame
2755
60
    MWAWGraphicStyle style;
2756
60
    graphic->fillFrame(style);
2757
60
    m_mainParser.sendEmptyFrameZone(graphic->getPosition(), style);
2758
60
  }
2759
184
  else {
2760
184
    MWAW_DEBUG_MSG(("MacWrtProStructures::send: can not send block with type=%d\n", graphic->m_type));
2761
184
  }
2762
53.9k
  m_state->m_graphicsSendSet.erase(graphicIdMain);
2763
53.9k
  return true;
2764
54.0k
}
2765
2766
////////////////////////////////////////////////////////////
2767
// send the not sent data
2768
void MacWrtProStructures::flushExtra()
2769
18.0k
{
2770
18.0k
  int vers = version();
2771
18.0k
  MWAWTextListenerPtr listener=m_parserState->m_textListener;
2772
18.0k
  if (listener && listener->isSectionOpened()) {
2773
9.42k
    listener->closeSection();
2774
9.42k
    listener->openSection(MWAWSection());
2775
9.42k
  }
2776
18.0k
  if (version()==0) {
2777
#ifdef DEBUG
2778
    bool const checkHFs=true;
2779
#else
2780
3.97k
    bool const checkHFs=false;
2781
3.97k
#endif
2782
22.5k
    for (size_t i=checkHFs ? 0 : 2; i<m_state->m_pagesList.size(); ++i) {
2783
18.5k
      auto const &page = m_state->m_pagesList[i];
2784
18.5k
      for (auto const &graphic : page.m_graphicsList) {
2785
653
        if (graphic->m_send || graphic->m_fileBlock<=0 || graphic->m_textPos>0) continue;
2786
166
        int const id=1000;
2787
166
        m_state->m_idGraphicMap[id]=graphic;
2788
166
        send(id);
2789
166
      }
2790
18.5k
    }
2791
3.97k
  }
2792
14.0k
  else {
2793
    // first send the text
2794
66.2k
    for (size_t i = 0; i < m_state->m_graphicsList.size(); ++i) {
2795
52.1k
      auto graphic = m_state->m_graphicsList[i];
2796
52.1k
      if (graphic->m_send)
2797
31.9k
        continue;
2798
20.1k
      if (graphic->m_type == 6) {
2799
        /* Fixme: macwritepro can have one header/footer by page and one by default.
2800
           For the moment, we only print the first one :-~ */
2801
2.17k
        MWAW_DEBUG_MSG(("MacWrtProStructures::flushExtra: find some header/footer\n"));
2802
2.17k
        continue;
2803
2.17k
      }
2804
18.0k
      int id = vers == 0 ? int(i) : graphic->m_id;
2805
18.0k
      if (graphic->isText()) {
2806
        // force to non floating position
2807
6.29k
        graphic->m_attachment = true;
2808
6.29k
        send(id);
2809
6.29k
        if (listener) listener->insertEOL();
2810
6.29k
      }
2811
11.7k
      else if (graphic->m_type == 3) {
2812
        // force to non floating position
2813
629
        graphic->m_attachment = true;
2814
629
        send(id);
2815
629
      }
2816
18.0k
    }
2817
    // then send graphic
2818
52.1k
    for (auto const &graphic : m_state->m_graphicsList) {
2819
52.1k
      if (graphic->m_send)
2820
39.0k
        continue;
2821
13.1k
      if (graphic->isGraphic()) {
2822
        // force to non floating position
2823
1.20k
        graphic->m_attachment = true;
2824
1.20k
        send(graphic->m_id);
2825
1.20k
      }
2826
13.1k
    }
2827
14.0k
  }
2828
18.0k
}
2829
2830
////////////////////////////////////////////////////////////
2831
// interface with the listener
2832
MacWrtProStructuresListenerState::MacWrtProStructuresListenerState(std::shared_ptr<MacWrtProStructures> const &structures, bool mainZone, int version)
2833
36.4k
  : m_isMainZone(mainZone)
2834
36.4k
  , m_version(version)
2835
36.4k
  , m_actPage(0)
2836
36.4k
  , m_actTab(0)
2837
36.4k
  , m_numTab(0)
2838
36.4k
  , m_section(0)
2839
36.4k
  , m_numCols(1)
2840
36.4k
  , m_newPageDone(false)
2841
36.4k
  , m_structures(structures)
2842
36.4k
{
2843
36.4k
  if (!m_structures) {
2844
0
    MWAW_DEBUG_MSG(("MacWrtProStructuresListenerState::MacWrtProStructuresListenerState can not find structures parser\n"));
2845
0
    return;
2846
0
  }
2847
36.4k
  if (mainZone) {
2848
17.3k
    newPage();
2849
17.3k
    sendSection(0);
2850
17.3k
  }
2851
36.4k
}
2852
2853
MacWrtProStructuresListenerState::~MacWrtProStructuresListenerState()
2854
36.4k
{
2855
36.4k
}
2856
2857
bool MacWrtProStructuresListenerState::isSent(int graphicId)
2858
2.07k
{
2859
2.07k
  if (!m_structures) return false;
2860
2.07k
  return m_structures->isSent(graphicId);
2861
2.07k
}
2862
2863
bool MacWrtProStructuresListenerState::send(int graphicId)
2864
1.84k
{
2865
1.84k
  m_newPageDone = false;
2866
1.84k
  if (!m_structures) return false;
2867
1.84k
  int oldNumTab=m_numTab;
2868
1.84k
  bool ok=m_structures->send(graphicId);
2869
1.84k
  m_numTab=oldNumTab;
2870
1.84k
  return ok;
2871
1.84k
}
2872
2873
void MacWrtProStructuresListenerState::insertSoftPageBreak()
2874
5.17k
{
2875
5.17k
  if (m_newPageDone) return;
2876
1.52k
  newPage(true);
2877
1.52k
}
2878
2879
bool MacWrtProStructuresListenerState::newPage(bool softBreak)
2880
54.9k
{
2881
54.9k
  if (!m_structures || !m_isMainZone) {
2882
0
    MWAW_DEBUG_MSG(("MacWrtProStructuresListenerState::newPage: can not create a new page\n"));
2883
0
    return false;
2884
0
  }
2885
2886
  // first send all the floating data
2887
54.9k
  if (m_actPage == 0) {
2888
46.8k
    for (auto const &graphic : m_structures->m_state->m_graphicsList) {
2889
46.8k
      if (graphic->m_send || graphic->m_attachment) continue;
2890
33.7k
      if (graphic->m_type != 3 && graphic->m_type != 4 && graphic->m_type != 8) continue;
2891
9.79k
      m_structures->send(graphic->m_id);
2892
9.79k
    }
2893
17.3k
  }
2894
2895
54.9k
  m_structures->m_mainParser.newPage(++m_actPage, softBreak);
2896
54.9k
  m_actTab=0;
2897
54.9k
  m_newPageDone = true;
2898
54.9k
  double colSep;
2899
54.9k
  if (m_version==0 && m_structures->m_mainParser.numColumns(colSep)>1 && m_actPage>1) {
2900
0
    if (!softBreak || (m_actPage==2&&m_structures->m_mainParser.hasTitlePage())) {
2901
0
      MWAWTextListenerPtr listener=m_structures->getTextListener();
2902
0
      if (listener->isSectionOpened())
2903
0
        listener->closeSection();
2904
0
      sendSection(++m_section);
2905
0
    }
2906
0
  }
2907
54.9k
  return true;
2908
54.9k
}
2909
2910
std::vector<int> MacWrtProStructuresListenerState::getPageBreaksPos() const
2911
22.1k
{
2912
22.1k
  std::vector<int> res;
2913
22.1k
  if (!m_structures || !m_isMainZone) return res;
2914
3.12k
  if (m_version==0) {
2915
0
    for (size_t i=2 ; i<m_structures->m_state->m_pagesList.size(); ++i) {
2916
0
      for (auto const &graphic : m_structures->m_state->m_pagesList[i].m_graphicsList) {
2917
0
        if (graphic->m_textboxType!=0)
2918
0
          continue;
2919
0
        if (graphic->m_textPos) res.push_back(graphic->m_textPos);
2920
0
      }
2921
0
    }
2922
0
  }
2923
3.12k
  else {
2924
29.1k
    for (auto const &graphic : m_structures->m_state->m_graphicsList) {
2925
29.1k
      if (graphic->m_type != 5) continue;
2926
8.91k
      if (graphic->m_textPos) res.push_back(graphic->m_textPos);
2927
8.91k
    }
2928
3.12k
  }
2929
3.12k
  return res;
2930
22.1k
}
2931
2932
// ----------- character function ---------------------
2933
void MacWrtProStructuresListenerState::sendChar(char c)
2934
8.94M
{
2935
8.94M
  if (!m_structures) return;
2936
8.94M
  bool newPageDone = m_newPageDone;
2937
8.94M
  m_newPageDone = false;
2938
8.94M
  MWAWTextListenerPtr listener=m_structures->getTextListener();
2939
8.94M
  if (!listener) return;
2940
8.94M
  switch (c) {
2941
0
  case 0:
2942
0
    break; // ignore
2943
92.5k
  case 3: // footnote ok
2944
179k
  case 4: // figure ok
2945
258k
  case 5: // hyphen ok
2946
258k
    break;
2947
49.7k
  case 7:
2948
49.7k
    if (m_version==0) {
2949
0
      m_actTab = 0;
2950
0
      listener->insertEOL(true);
2951
0
    }
2952
49.7k
    else {
2953
49.7k
      MWAW_DEBUG_MSG(("MacWrtProStructuresListenerState::sendChar: Find odd char 0x7\n"));
2954
49.7k
    }
2955
49.7k
    break;
2956
70.1k
  case 0x9:
2957
70.1k
    if ((m_actTab++ < m_numTab) || m_actTab!=1)
2958
42.6k
      listener->insertTab();
2959
27.5k
    else // this case appears in list, 2.\tItem..., we do not always want a tab here
2960
27.5k
      listener->insertChar(' ');
2961
70.1k
    break;
2962
107k
  case 0xa:
2963
107k
    m_actTab = 0;
2964
107k
    if (newPageDone) break;
2965
106k
    listener->insertEOL();
2966
106k
    break; // soft break
2967
207k
  case 0xd:
2968
207k
    m_actTab = 0;
2969
207k
    if (newPageDone) break;
2970
206k
    listener->insertEOL();
2971
206k
    break;
2972
43.8k
  case 0xc:
2973
43.8k
    m_actTab = 0;
2974
43.8k
    if (m_isMainZone) newPage();
2975
43.8k
    break;
2976
43.1k
  case 0xb: // add a columnbreak
2977
43.1k
    m_actTab = 0;
2978
43.1k
    if (m_isMainZone) {
2979
18.4k
      if (m_numCols <= 1) newPage();
2980
2.68k
      else if (listener)
2981
2.68k
        listener->insertBreak(MWAWTextListener::ColumnBreak);
2982
18.4k
    }
2983
43.1k
    break;
2984
50.9k
  case 0xe:
2985
50.9k
    m_actTab = 0;
2986
50.9k
    if (!m_isMainZone) break;
2987
2988
    // create a new section here
2989
19.3k
    if (listener->isSectionOpened())
2990
18.0k
      listener->closeSection();
2991
19.3k
    sendSection(++m_section);
2992
19.3k
    break;
2993
168k
  case 2: // for MWII
2994
195k
  case 0x15:
2995
221k
  case 0x17:
2996
244k
  case 0x1a:
2997
244k
    break;
2998
17.8k
  case 0x1f: // some hyphen
2999
17.8k
    break;
3000
  /* 0x10 and 0x13 : bad character which can happen in conversion */
3001
7.85M
  default:
3002
7.85M
    listener->insertCharacter(static_cast<unsigned char>(c));
3003
7.85M
    break;
3004
8.94M
  }
3005
8.94M
}
3006
3007
// ----------- font function ---------------------
3008
bool MacWrtProStructuresListenerState::sendFont(int id)
3009
118k
{
3010
118k
  if (!m_structures) return false;
3011
118k
  if (!m_structures->getTextListener()) return true;
3012
118k
  if (id < 0 || id >= int(m_structures->m_state->m_fontsList.size())) {
3013
1.28k
    MWAW_DEBUG_MSG(("MacWrtProStructuresListenerState::sendFont: can not find font %d\n", id));
3014
1.28k
    return false;
3015
1.28k
  }
3016
117k
  m_structures->getTextListener()->setFont(m_structures->m_state->m_fontsList[size_t(id)].m_font);
3017
3018
117k
  return true;
3019
118k
}
3020
3021
// ----------- paragraph function ---------------------
3022
bool MacWrtProStructuresListenerState::sendParagraph(int id)
3023
103k
{
3024
103k
  if (!m_structures) return false;
3025
103k
  if (!m_structures->getTextListener()) return true;
3026
103k
  if (id < 0 || id >= int(m_structures->m_state->m_paragraphsList.size())) {
3027
2.02k
    MWAW_DEBUG_MSG(("MacWrtProStructuresListenerState::sendParagraph: can not find paragraph %d\n", id));
3028
2.02k
    return false;
3029
2.02k
  }
3030
101k
  auto const &para=m_structures->m_state->m_paragraphsList[size_t(id)];
3031
101k
  m_structures->getTextListener()->setParagraph(para);
3032
101k
  m_numTab = int(para.m_tabs->size());
3033
101k
  return true;
3034
103k
}
3035
3036
// ----------- section function ---------------------
3037
void MacWrtProStructuresListenerState::sendSection(int nSection)
3038
36.7k
{
3039
36.7k
  if (!m_structures) return;
3040
36.7k
  MWAWTextListenerPtr listener=m_structures->getTextListener();
3041
36.7k
  if (!listener) return;
3042
36.7k
  if (listener->isSectionOpened()) {
3043
365
    MWAW_DEBUG_MSG(("MacWrtProStructuresListenerState::sendSection: a section is already opened\n"));
3044
365
    listener->closeSection();
3045
365
  }
3046
36.7k
  if (m_version==0) {
3047
3.83k
    double colSep=0.16666;
3048
3.83k
    m_numCols = (nSection==0 && m_structures->m_mainParser.hasTitlePage()) ? 1 : m_structures->m_mainParser.numColumns(colSep);
3049
3.83k
    if (m_numCols > 10) {
3050
938
      MWAW_DEBUG_MSG(("MacWrtProStructuresListenerState::sendSection: num columns is to big, reset to 1\n"));
3051
938
      m_numCols = 1;
3052
938
    }
3053
3.83k
    MWAWSection sec;
3054
3.83k
    if (m_numCols>1)
3055
202
      sec.setColumns(m_numCols, (m_structures->m_mainParser.getPageWidth()-colSep*double(m_numCols-1))/double(m_numCols), librevenge::RVNG_INCH, colSep);
3056
3.83k
    listener->openSection(sec);
3057
3.83k
    return;
3058
3.83k
  }
3059
3060
32.9k
  if (nSection >= int(m_structures->m_state->m_sectionsList.size())) {
3061
19.7k
    MWAW_DEBUG_MSG(("MacWrtProStructuresListenerState::sendSection: can not find section %d\n", nSection));
3062
19.7k
    return;
3063
19.7k
  }
3064
13.1k
  auto const &section = m_structures->m_state->m_sectionsList[size_t(nSection)];
3065
13.1k
  if (nSection && section.m_start != section.S_Line) newPage();
3066
3067
13.1k
  listener->openSection(section.getSection());
3068
13.1k
  m_numCols = listener->getSection().numColumns();
3069
13.1k
}
3070
// vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: