Coverage Report

Created: 2026-09-06 07:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libmwaw/src/lib/MsWrdStruct.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 "MWAWDebug.hxx"
35
#include "MWAWFontConverter.hxx"
36
#include "MWAWInputStream.hxx"
37
#include "MWAWSection.hxx"
38
39
#include "MsWrdStruct.hxx"
40
41
namespace MsWrdStruct
42
{
43
// ------ font -------------
44
std::ostream &operator<<(std::ostream &o, Font const &font)
45
0
{
46
0
  char const *what[Font::NumFlags]= {
47
0
    "b", "it", "strikeout", "outline", "shadow", "smallCaps", "allCaps",
48
0
    "hidden", "underline"
49
0
  };
50
0
  for (int i=0; i < Font::NumFlags; i++) {
51
0
    if (!font.m_flags[i].isSet()) continue;
52
0
    o << what[i];
53
0
    switch (font.m_flags[i].get()) {
54
0
    case 0x80:
55
0
      o << "=noStyle";
56
0
      break;
57
0
    case 0:
58
0
      o << "=no";
59
0
      break;
60
0
    case 0x81:
61
0
      o << "=style";
62
0
      break;
63
0
    case 1:
64
0
      break;
65
0
    default:
66
0
      o << "=" << std::hex << font.m_flags[i].get() << std::dec << ",";
67
0
    }
68
0
    o << ",";
69
0
  }
70
0
  if (font.m_picturePos.get())
71
0
    o << "pict=" << std::hex << font.m_picturePos.get() << std::dec << ",";
72
0
  if (font.m_unknown.get())
73
0
    o << "ft=" << std::hex << font.m_unknown.get() << std::dec << ",";
74
0
  if (font.m_size.isSet() && (font.m_size.get() < font.m_font->size() ||
75
0
                              font.m_size.get() > font.m_font->size()))
76
0
    o << "#size2=" << font.m_size.get() << ",";
77
0
  if (font.m_value.isSet()) o << "id?=" << font.m_value.get() << ",";
78
0
  if (font.m_extra.length())
79
0
    o << font.m_extra << ",";
80
0
  return o;
81
0
}
82
83
void Font::insert(Font const &font, Font const *styleFont)
84
2.35M
{
85
2.35M
  updateFontToFinalState(styleFont);
86
2.35M
  if (!m_font.isSet())
87
1.35M
    m_font=font.m_font;
88
992k
  else if (font.m_font.isSet())
89
133k
    m_font->insert(font.m_font.get());
90
2.35M
  m_size.insert(font.m_size);
91
2.35M
  m_value.insert(font.m_value);
92
2.35M
  m_picturePos.insert(font.m_picturePos);
93
2.35M
  m_unknown.insert(font.m_unknown);
94
23.5M
  for (int i = 0; i < NumFlags; i++)
95
21.1M
    m_flags[i] = font.m_flags[i];
96
2.35M
  m_extra+=font.m_extra;
97
2.35M
}
98
99
void Font::updateFontToFinalState(Font const *styleFont)
100
3.06M
{
101
3.06M
  uint32_t res=0;
102
3.06M
  uint32_t const fl[NumFlags] = {
103
3.06M
    MWAWFont::boldBit, MWAWFont::italicBit, 0, MWAWFont::outlineBit,
104
3.06M
    MWAWFont::shadowBit, MWAWFont::smallCapsBit, MWAWFont::uppercaseBit, MWAWFont::hiddenBit, 0
105
3.06M
  };
106
3.06M
  if (m_font.isSet()) res = m_font->flags();
107
3.06M
  bool flagsMod = false;
108
30.6M
  for (int i=0; i < NumFlags; i++) {
109
27.5M
    if (!m_flags[i].isSet()) continue;
110
78.7k
    int action = m_flags[i].get();
111
78.7k
    if (action&0xFF7E) continue;
112
54.0k
    bool on = (action&1);
113
54.0k
    if ((action&0x80) && styleFont) {
114
17.5k
      bool prev=false;
115
17.5k
      if (i==2)
116
1.12k
        prev = styleFont->m_font->getStrikeOut().isSet();
117
16.3k
      else if (i==8)
118
3.53k
        prev = styleFont->m_font->getUnderline().isSet();
119
12.8k
      else
120
12.8k
        prev = styleFont->m_font->flags()&fl[i];
121
17.5k
      if (action==0x81)
122
13.3k
        on = prev;
123
4.13k
      else
124
4.13k
        on = !prev;
125
17.5k
    }
126
54.0k
    switch (i) {
127
15.4k
    case 2:
128
15.4k
      if (on)
129
1.16k
        m_font->setStrikeOutStyle(MWAWFont::Line::Simple);
130
14.2k
      else
131
14.2k
        m_font->setStrikeOutStyle(MWAWFont::Line::None);
132
15.4k
      break;
133
12.2k
    case 8:
134
12.2k
      if (on)
135
5.20k
        m_font->setUnderlineStyle(MWAWFont::Line::Simple);
136
7.05k
      else
137
7.05k
        m_font->setUnderlineStyle(MWAWFont::Line::None);
138
12.2k
      break;
139
26.3k
    default:
140
26.3k
      if (on) res|=fl[i];
141
15.3k
      else res &= ~(fl[i]);
142
26.3k
      flagsMod=true;
143
26.3k
      break;
144
54.0k
    }
145
54.0k
  }
146
3.06M
  if (flagsMod)
147
26.3k
    m_font->setFlags(res);
148
3.06M
}
149
150
// ------ section -------------
151
MWAWSection Section::getSection(double pageWidth) const
152
54.6k
{
153
54.6k
  MWAWSection sec;
154
54.6k
  int numCols = *m_col;
155
54.6k
  if (numCols <= 1)
156
54.2k
    return sec;
157
405
  MWAWSection::Column col;
158
405
  col.m_width=pageWidth/double(numCols);
159
405
  col.m_widthUnit=librevenge::RVNG_INCH;
160
405
  col.m_margins[libmwaw::Left] = col.m_margins[libmwaw::Right] = double(*m_colSep)/2.;
161
405
  sec.m_columns.resize(size_t(numCols), col);
162
405
  sec.m_columns[0].m_margins[libmwaw::Left] = 0;
163
405
  sec.m_columns[size_t(numCols-1)].m_margins[libmwaw::Right] = 0;
164
405
  sec.m_balanceText = true;
165
405
  return sec;
166
54.6k
}
167
168
bool Section::read(MWAWInputStreamPtr &input, long endPos)
169
9.28M
{
170
9.28M
  long pos = input->tell();
171
9.28M
  long dSz = endPos-pos;
172
9.28M
  if (dSz < 1) return false;
173
9.28M
  libmwaw::DebugStream f;
174
9.28M
  int c = static_cast<int>(input->readULong(1)), val;
175
9.28M
  switch (c) {
176
126k
  case 0x75: // column break
177
126k
    if (dSz < 2) return false;
178
125k
    val = static_cast<int>(input->readLong(1));
179
125k
    switch (val) {
180
3.65k
    case 0:
181
3.65k
      m_colBreak = false;
182
3.65k
      return true;
183
661
    case 1:
184
661
      m_colBreak = true;
185
661
      return true;
186
120k
    default:
187
120k
      f << "#f75=" << val << ",";
188
120k
      break;
189
125k
    }
190
120k
    break;
191
120k
  case 0x77: // num column
192
47.6k
    if (dSz<3) return false;
193
45.1k
    m_col = static_cast<int>(input->readLong(2))+1;
194
45.1k
    return true;
195
58.0k
  case 0x78:
196
58.0k
    if (dSz<3) return false;
197
56.4k
    m_colSep = float(input->readULong(2))/1440.f;
198
56.4k
    return true;
199
  // FIXME: UNKNOWN
200
18.7k
  case 0x80: // a small number: 0, 8, 10
201
61.6k
  case 0x76: // always 1 ?
202
88.6k
  case 0x79:
203
101k
  case 0x7d: // always 1
204
115k
  case 0x7e: // always 0
205
115k
    if (dSz<2) return false;
206
112k
    f << "f" << std::hex << c << std::dec << "=" << input->readLong(1) << ",";
207
112k
    break;
208
20.0k
  case 0x7b: // 2e1 3d08
209
189k
  case 0x7c: // 4da, 6a5, 15ff
210
189k
    if (dSz<3) return false;
211
184k
    f << "f" << std::hex << c << std::dec << "=";
212
184k
    f << std::hex << input->readULong(1) << std::dec << ":";
213
184k
    f << std::hex << input->readULong(1) << std::dec << ",";
214
184k
    break;
215
127k
  case 0x82: // find one time with 168 (related to 7e ?)
216
127k
    if (dSz<3) return false;
217
119k
    f << "f" << std::hex << c << std::dec << "=" << input->readLong(2) << ",";
218
119k
    break;
219
102k
  case 0x83:
220
110k
  case 0x84:
221
110k
    if (dSz < 3) return false;
222
108k
    val = static_cast<int>(input->readLong(2));
223
108k
    if (c == 0x83) f << "header[top]=" << val/1440. << ",";
224
8.23k
    else f << "header[bottom]=" << val/1440. << ",";
225
108k
    break;
226
8.51M
  default:
227
8.51M
    return false;
228
9.28M
  }
229
647k
  m_extra += f.str();
230
647k
  return true;
231
9.28M
}
232
233
// data seems very different in v3, so a new function....
234
bool Section::readV3(MWAWInputStreamPtr &input, long endPos)
235
3.02M
{
236
3.02M
  long pos = input->tell();
237
3.02M
  long dSz = endPos-pos;
238
3.02M
  if (dSz < 1) return false;
239
3.02M
  libmwaw::DebugStream f;
240
3.02M
  int wh = static_cast<int>(input->readULong(1)), val;
241
3.02M
  switch (wh) {
242
80.4k
  case 0x36:
243
80.4k
    if (dSz < 2) return false;
244
77.4k
    val = static_cast<int>(input->readLong(1));
245
77.4k
    switch (val) {
246
327
    case 0:
247
327
      f << "division=no,";
248
327
      break;
249
66
    case 1:
250
66
      f << "division=columns,";
251
66
      break;
252
27
    case 2:
253
27
      f << "division=page,";
254
27
      break; // default
255
119
    case 3:
256
119
      f << "division=evenpage,";
257
119
      break;
258
0
    case 4:
259
0
      f << "division=oddpage,";
260
0
      break;
261
76.9k
    default:
262
76.9k
      f << "#division=" << val << ",";
263
76.9k
      break;
264
77.4k
    }
265
77.4k
    break;
266
77.4k
  case 0x37:
267
25.1k
    if (dSz < 2) return false;
268
21.8k
    val = static_cast<int>(input->readLong(1));
269
21.8k
    switch (val) {
270
146
    case 0:
271
146
      break; // no front page
272
95
    case 1:
273
95
      f << "frontPage,";
274
95
      break;
275
21.6k
    default:
276
21.6k
      f << "#frontPage=" << val << ",";
277
21.6k
      break;
278
21.8k
    }
279
21.8k
    break;
280
48.5k
  case 0x3a:
281
48.5k
    if (dSz < 2) return false;
282
46.9k
    val = static_cast<int>(input->readLong(1));
283
46.9k
    switch (val) {
284
148
    case 1:
285
148
      f << "addNumbering,";
286
148
      break;
287
46.8k
    default:
288
46.8k
      f << "#addNumbering=" << val << ",";
289
46.8k
      break;
290
46.9k
    }
291
46.9k
    break;
292
46.9k
  case 0x3b:
293
36.0k
    if (dSz < 2) return false;
294
34.3k
    val = static_cast<int>(input->readLong(1));
295
34.3k
    switch (val) {
296
1.62k
    case 1:
297
1.62k
      f << "numbering=arabic,";
298
1.62k
      break; // normal
299
242
    case 2:
300
242
      f << "numbering=roman[upper],";
301
242
      break;
302
37
    case 3:
303
37
      f << "numbering=alpha[upper],";
304
37
      break;
305
21
    case 4:
306
21
      f << "numbering=alpha[lower],";
307
21
      break;
308
93
    case 5:
309
93
      f << "numbering=roman[lower],";
310
93
      break;
311
32.3k
    default:
312
32.3k
      f << "#numbering[type]=" << val << ",";
313
32.3k
      break;
314
34.3k
    }
315
34.3k
    break;
316
34.3k
  case 0x3e:
317
22.2k
    if (dSz < 2) return false;
318
20.4k
    val = static_cast<int>(input->readLong(1));
319
20.4k
    switch (val) {
320
33
    case 1:
321
33
      f << "newNumber=byPage,";
322
33
      break;
323
20.3k
    default:
324
20.3k
      f << "#newNumber=" << val << ",";
325
20.3k
      break;
326
20.4k
    }
327
20.4k
    break;
328
31.0k
  case 0x3f:
329
31.0k
    if (dSz < 2) return false;
330
29.3k
    val = static_cast<int>(input->readLong(1));
331
29.3k
    switch (val) {
332
134
    case 0:
333
134
      f << "footnote,";
334
134
      break;
335
204
    case 1:
336
204
      f << "endnote,";
337
204
      break; // default
338
29.0k
    default:
339
29.0k
      f << "#endnote=" << val << ",";
340
29.0k
      break;
341
29.3k
    }
342
29.3k
    break;
343
97.9k
  case 0x40:
344
97.9k
    if (dSz < 2) return false;
345
96.1k
    val = static_cast<int>(input->readLong(1));
346
96.1k
    switch (val) {
347
1.11k
    case 1:
348
1.11k
      f << "numberline=byDivision,";
349
1.11k
      break;
350
172
    case 2:
351
172
      f << "numberline=consecutive,";
352
172
      break;
353
94.8k
    default:
354
94.8k
      f << "#numberline=" << val << ",";
355
94.8k
      break;
356
96.1k
    }
357
96.1k
    break;
358
96.1k
  case 0x41: // 8 or a
359
51.0k
    if (dSz < 2) return false;
360
49.3k
    val = static_cast<int>(input->readLong(1));
361
49.3k
    f << "f41=" << std::hex << val << std::dec << ",";
362
49.3k
    break;
363
30.6k
  case 0x38:
364
43.5k
  case 0x39:
365
52.4k
  case 0x3c:
366
71.4k
  case 0x3d:
367
101k
  case 0x42:
368
127k
  case 0x43: // find 0x168
369
143k
  case 0x44:
370
166k
  case 0x45:
371
166k
    if (dSz < 3) return false;
372
148k
    val = static_cast<int>(input->readLong(2));
373
148k
    switch (wh) {
374
27.5k
    case 0x38:
375
27.5k
      m_col = static_cast<int>(val)+1;
376
27.5k
      break;
377
28.1k
    case 0x42:
378
28.1k
      f << "numberline[lines]=" << val << ",";
379
28.1k
      break;
380
11.4k
    case 0x39:
381
11.4k
      m_colSep = float(val)/1440.f;
382
11.4k
      break;
383
7.98k
    case 0x3c:
384
7.98k
      f << "numberingPos[T]=" << val/1440.0 << ",";
385
7.98k
      break;
386
17.6k
    case 0x3d:
387
17.6k
      f << "numberingPos[R]=" << val/1440.0 << ",";
388
17.6k
      break;
389
12.3k
    case 0x44:
390
12.3k
      f << "headerSize=" << val/1440.0 << ",";
391
12.3k
      break;
392
19.6k
    case 0x45:
393
19.6k
      f << "footerSize=" << val/1440.0 << ",";
394
19.6k
      break;
395
24.0k
    default:
396
24.0k
      f << "f" << std::hex << wh << std::dec << "=" << val << ",";
397
24.0k
      break;
398
148k
    }
399
148k
    break;
400
2.46M
  default:
401
2.46M
    return false;
402
3.02M
  }
403
524k
  m_extra += f.str();
404
524k
  return true;
405
3.02M
}
406
407
std::ostream &operator<<(std::ostream &o, Section const &section)
408
0
{
409
0
  if (section.m_type.get()) // 0|0x40|0x80|0xc0
410
0
    o << "type=" << std::hex << section.m_type.get() << std::dec << ",";
411
0
  if (section.m_paragraphId.isSet() && section.m_paragraphId.get() > -9999)
412
0
    o << "sP=" << section.m_paragraphId.get() << ",";
413
0
  if (section.m_col.isSet() && section.m_col.get() != 1)
414
0
    o << "cols=" << section.m_col.get() << ",";
415
0
  if (section.m_colSep.isSet())
416
0
    o << "colSep=" << section.m_colSep.get() << "in,";
417
0
  if (section.m_colBreak.get()) o << "colBreak,";
418
0
  if (section.m_flag.get())
419
0
    o << "fl=" << std::hex << section.m_flag.get() << std::dec << ",";
420
0
  if (section.m_extra.length()) o << section.m_extra << ",";
421
0
  return o;
422
0
}
423
424
// table
425
MWAWVariable<Table::Cell> &Table::getCell(int id)
426
700k
{
427
700k
  if (id < 0) {
428
0
    MWAW_DEBUG_MSG(("MsWrdStruct::Table::getCell: can not return a negative cell id\n"));
429
0
    return m_badCell;
430
0
  }
431
700k
  if (m_cells.size() <= size_t(id)) m_cells.resize(size_t(id)+1);
432
700k
  return m_cells[size_t(id)];
433
700k
}
434
435
bool Table::read(MWAWInputStreamPtr &input, long endPos)
436
10.1M
{
437
10.1M
  long pos = input->tell();
438
10.1M
  long dSz = endPos-pos;
439
10.1M
  if (dSz < 1) return false;
440
10.1M
  libmwaw::DebugStream f, f2;
441
10.1M
  int c = static_cast<int>(input->readULong(1)), val;
442
10.1M
  switch (c) {
443
30.6k
  case 0x98: { // tabs columns
444
30.6k
    auto sz = static_cast<int>(input->readULong(2));
445
30.6k
    if (!sz || dSz < 2+sz) return false;
446
17.9k
    auto N = static_cast<int>(input->readULong(1));
447
17.9k
    if (1+(N+1)*2 > sz) {
448
902
      MWAW_DEBUG_MSG(("MsWrdStruct::Table::read: table definition seems odd\n"));
449
902
      f << "#colDef";
450
902
      input->seek(pos+2+sz, librevenge::RVNG_SEEK_SET);
451
902
      break;
452
902
    }
453
84.8k
    for (int i=0; i <= N; i++)
454
67.8k
      m_columns->push_back(float(input->readLong(2))/20.0f);
455
17.0k
    int N1 = (sz-(N+1)*2-2);
456
43.0k
    for (int i=0; i < (N1+8)/10; i++) {
457
26.0k
      Cell cell;
458
26.0k
      int numElt= (N1-10*i)/2;
459
26.0k
      if (numElt>5) numElt=5;
460
26.0k
      f2.str("");
461
26.0k
      val = static_cast<int>(input->readULong(2));
462
26.0k
      switch (val) {
463
14.0k
      case 0:
464
14.0k
        break;
465
48
      case 0x4000:
466
48
        f2 << "empty,";
467
48
        break;
468
81
      case 0x8000:
469
81
        f2 << "merge,";
470
81
        break;
471
11.8k
      default:
472
11.8k
        f2 << "#type=" << std::hex << val << std::dec << ",";
473
26.0k
      }
474
26.0k
      if (numElt > 0) {
475
26.0k
        cell.m_borders.resize(size_t(numElt)-1);
476
108k
        for (int b = 0; b < numElt-1; b++) {
477
82.2k
          std::string bExtra;
478
82.2k
          cell.m_borders[size_t(b)] = getBorder(static_cast<int>(input->readULong(2)), bExtra);
479
82.2k
          if (bExtra.length())
480
0
            f2 << "#bord" << b << "=" << bExtra << ",";
481
82.2k
        }
482
26.0k
      }
483
26.0k
      cell.m_extra = f2.str();
484
26.0k
      m_cells.push_back(MWAWVariable<Cell>(cell));
485
26.0k
      m_cells.back().setSet(true);
486
26.0k
    }
487
17.0k
    input->seek(pos+2+sz, librevenge::RVNG_SEEK_SET);
488
17.0k
    return true;
489
17.0k
  }
490
67.7k
  case 0x92: // table alignment
491
67.7k
    if (dSz < 3) return false;
492
66.2k
    val = static_cast<int>(input->readULong(2));
493
66.2k
    switch (val&3) {
494
7.42k
    case 0:
495
7.42k
      m_justify = MWAWParagraph::JustificationLeft;
496
7.42k
      break;
497
2.23k
    case 1:
498
2.23k
      m_justify = MWAWParagraph::JustificationCenter;
499
2.23k
      break;
500
55.2k
    case 2:
501
55.2k
      m_justify = MWAWParagraph::JustificationRight;
502
55.2k
      break;
503
1.28k
    case 3:
504
1.28k
      m_justify = MWAWParagraph::JustificationFull;
505
1.28k
      break;
506
0
    default:
507
0
      break;
508
66.2k
    }
509
66.2k
    if (val&0xFFFC) f << "#align=" << std::hex << (val&0xFFFC) << std::dec << ",";
510
66.2k
    break;
511
16.3k
  case 0x93: // table alignment indent
512
16.3k
    if (dSz < 3) return false;
513
15.8k
    m_indent = float(input->readLong(2))/1440.f;
514
15.8k
    return true;
515
21.8k
  case 0x99: // table height DWIPP
516
21.8k
    if (dSz < 3) return false;
517
15.0k
    m_height = float(input->readLong(2))/1440.f;
518
15.0k
    return true;
519
29.3k
  case 0x9a: { // the table shading
520
29.3k
    if (dSz < 2) return false;
521
27.4k
    auto sz = static_cast<int>(input->readULong(1));
522
27.4k
    if (2+sz > dSz || (sz%2)) return false;
523
116k
    for (int i = 0; i < sz/2; i++) {
524
108k
      float backColor=1.f-float(input->readULong(2))/10000.f;
525
108k
      getCell(i)->m_backColor = backColor;
526
108k
    }
527
8.16k
    break;
528
27.4k
  }
529
770k
  case 0x9d: { // table cell shading
530
770k
    if (dSz < 6) return false;
531
756k
    val = static_cast<int>(input->readLong(1)); // a small number often 4
532
756k
    if (val!=4) f << "backColor[unkn?]=" << val << ",";
533
756k
    auto firstCol = static_cast<int>(input->readLong(1));
534
756k
    auto lastCol = static_cast<int>(input->readLong(1));
535
756k
    if (firstCol < 0 || lastCol < 0 || firstCol+1 > lastCol) {
536
746k
      input->seek(2, librevenge::RVNG_SEEK_CUR);
537
746k
      MWAW_DEBUG_MSG(("MsWrdStruct::Table::read: pb for background range\n"));
538
746k
      f << "###backRange=" << firstCol << "<->" << lastCol-1 << ",";
539
746k
      break;
540
746k
    }
541
9.83k
    float backColor = 1.f-float(input->readULong(2))/10000.f;
542
186k
    for (int i = firstCol; i < lastCol; i++)
543
177k
      getCell(i)->m_backColor = backColor;
544
9.83k
    break;
545
756k
  }
546
41.4k
  case 0xa0: { // table dimension modifier
547
41.4k
    if (dSz < 5) return false;
548
33.4k
    auto firstCol = static_cast<int>(input->readULong(1));
549
33.4k
    auto lastCol = static_cast<int>(input->readULong(1));
550
33.4k
    float dim=float(input->readLong(2))/20.0f;
551
33.4k
    f << "col[widthMod" << firstCol << "<->" << lastCol-1 << "]=" << dim<< ",";
552
33.4k
    if (m_columnsWidthMod->size()<=size_t(firstCol))
553
23.7k
      m_columnsWidthMod->resize(size_t(firstCol)+1, -1);
554
33.4k
    (*m_columnsWidthMod)[size_t(firstCol)]=dim;
555
33.4k
    break;
556
41.4k
  }
557
45.2k
  case 0xa3: {
558
45.2k
    if (dSz < 6) return false;
559
    // range 0: means A1
560
39.7k
    auto firstCol = static_cast<int>(input->readLong(1));
561
39.7k
    auto lastCol = static_cast<int>(input->readLong(1));
562
39.7k
    if (firstCol < 0 || lastCol < 0 || firstCol+1 > lastCol) {
563
19.4k
      input->seek(3, librevenge::RVNG_SEEK_CUR);
564
19.4k
      MWAW_DEBUG_MSG(("MsWrdStruct::Table::read: pb for mod color\n"));
565
19.4k
      f << "###backRange=" << firstCol << "<->" << lastCol-1 << ",";
566
19.4k
      break;
567
19.4k
    }
568
20.3k
    val = int(input->readULong(1));
569
20.3k
    size_t maxVal = 0;
570
20.3k
    if (val & 1) maxVal = 1;
571
20.3k
    if (val & 2) maxVal = 2;
572
20.3k
    if (val & 4) maxVal = 3;
573
20.3k
    if (val & 8) maxVal = 4;
574
20.3k
    if (val&0xF0) f << "borderMod[wh=#" << std::hex << int(val&0xF0) << std::dec << "],";
575
20.3k
    std::string bExtra;
576
20.3k
    MWAWBorder border = getBorder(static_cast<int>(input->readULong(2)), bExtra);
577
435k
    for (int i = firstCol; i < lastCol; i++) {
578
415k
      MWAWVariable<Cell> &cell = getCell(i);
579
415k
      if (cell->m_borders.size() < maxVal)
580
357k
        cell->m_borders.resize(maxVal);
581
415k
      if (val&1) cell->m_borders[0] = border;
582
415k
      if (val&2) cell->m_borders[1] = border;
583
415k
      if (val&4) cell->m_borders[2] = border;
584
415k
      if (val&8) cell->m_borders[3] = border;
585
415k
    }
586
20.3k
    if (bExtra.length()) f << "borderMod=" << bExtra << ",";
587
20.3k
    break;
588
39.7k
  }
589
9.10M
  default:
590
9.10M
    return false;
591
10.1M
  }
592
904k
  m_extra += f.str();
593
904k
  return true;
594
10.1M
}
595
596
void Table::insert(Table const &table)
597
8.59k
{
598
8.59k
  m_height.insert(table.m_height);
599
8.59k
  m_justify.insert(table.m_justify);
600
8.59k
  m_indent.insert(table.m_indent);
601
8.59k
  m_columns.insert(table.m_columns);
602
8.59k
  if (table.m_columnsWidthMod.isSet() && !m_columns->empty()
603
0
      && !table.m_columnsWidthMod->empty()) {
604
0
    size_t numCols=m_columns->size();
605
0
    std::vector<float> colWidth(numCols-1,0);
606
0
    for (size_t c=0; c+1<numCols; ++c)
607
0
      colWidth[c]=(*m_columns)[c+1]-(*m_columns)[c];
608
0
    for (size_t c=0; c<table.m_columnsWidthMod->size(); ++c) {
609
0
      if (c+1 >= numCols) break;
610
0
      if (table.m_columnsWidthMod.get()[c]<0) continue;
611
0
      colWidth[c]=table.m_columnsWidthMod.get()[c];
612
0
    }
613
0
    for (size_t c=0; c+1<numCols; ++c)
614
0
      (*m_columns)[c+1]=colWidth[c]+(*m_columns)[c];
615
0
  }
616
8.59k
  size_t tNumCells = table.m_cells.size();
617
8.59k
  if (tNumCells > m_cells.size())
618
1
    m_cells.resize(tNumCells, MWAWVariable<Cell>());
619
27.3k
  for (size_t i=0; i < tNumCells; i++) {
620
18.7k
    if (!m_cells[i].isSet())
621
4
      m_cells[i] = table.m_cells[i];
622
18.7k
    else if (table.m_cells[i].isSet())
623
18.7k
      m_cells[i]->insert(*table.m_cells[i]);
624
18.7k
  }
625
8.59k
  m_extra+=table.m_extra;
626
8.59k
}
627
628
std::ostream &operator<<(std::ostream &o, Table::Cell const &cell)
629
0
{
630
0
  if (cell.hasBorders()) {
631
0
    o << "borders=[";
632
0
    char const *wh[] = { "T", "L", "B", "R" };
633
0
    for (size_t i = 0; i < cell.m_borders.size() ; i++) {
634
0
      if (!cell.m_borders[i].isSet()) continue;
635
0
      if (i < 4) o << wh[i];
636
0
      else o << "#" << i;
637
0
      o << "=" << cell.m_borders[i].get() << ",";
638
0
    }
639
0
    o << "],";
640
0
  }
641
0
  if (cell.m_backColor.isSet()) o << "backColor=" << cell.m_backColor.get() << ",";
642
0
  if (cell.m_extra.length()) o << cell.m_extra;
643
0
  return o;
644
0
}
645
646
std::ostream &operator<<(std::ostream &o, Table const &table)
647
0
{
648
0
  if (table.m_height.isSet()) { // 0 means automatic
649
0
    if (table.m_height.get() > 0)
650
0
      o << "height[row]=" << table.m_height.get() << "[atLeast],";
651
0
    else if (table.m_height.get() < 0)
652
0
      o << "height[row]=" << table.m_height.get() << ",";
653
0
  }
654
0
  if (table.m_justify.isSet()) {
655
0
    switch (table.m_justify.get()) {
656
0
    case MWAWParagraph::JustificationLeft:
657
0
      o << "just=left,";
658
0
      break;
659
0
    case MWAWParagraph::JustificationCenter:
660
0
      o << "just=centered, ";
661
0
      break;
662
0
    case MWAWParagraph::JustificationRight:
663
0
      o << "just=right, ";
664
0
      break;
665
0
    case MWAWParagraph::JustificationFull:
666
0
      o << "just=full, ";
667
0
      break;
668
0
    case MWAWParagraph::JustificationFullAllLines:
669
0
      o << "just=fullAllLines, ";
670
0
      break;
671
#if !defined(__clang__)
672
    default:
673
      o << "just=" << table.m_justify.get() << ", ";
674
      break;
675
#endif
676
0
    }
677
0
  }
678
0
  if (table.m_indent.isSet()) o << "indent=" << table.m_indent.get() << ",";
679
0
  if (table.m_columns.isSet() && table.m_columns->size()) {
680
0
    o << "cols=[";
681
0
    for (auto const &col : table.m_columns.get())
682
0
      o << col << ",";
683
0
    o << "],";
684
0
  }
685
0
  if (table.m_columnsWidthMod.isSet() && table.m_columnsWidthMod->size()) {
686
0
    for (size_t i = 0; i < table.m_columnsWidthMod->size(); i++) {
687
0
      if (table.m_columnsWidthMod.get()[i] >= 0)
688
0
        o << "col" << i << "[width]=" << (*table.m_columnsWidthMod)[i] << ",";
689
0
    }
690
0
  }
691
0
  if (table.m_cells.size()) {
692
0
    o << "cells=[";
693
0
    for (auto const &cell : table.m_cells)
694
0
      o << "[" << cell.get() << "],";
695
0
    o << "],";
696
0
  }
697
0
  if (table.m_extra.length()) o << table.m_extra;
698
0
  return o;
699
0
}
700
701
// paragraph info
702
bool ParagraphInfo::read(MWAWInputStreamPtr &input, long endPos, int vers)
703
1.99M
{
704
1.99M
  long pos = input->tell();
705
1.99M
  if ((vers <= 3 && endPos < pos+2) || (vers > 3 && endPos < pos+6)) {
706
0
    MWAW_DEBUG_MSG(("ParagraphInfo::read: zone is too short\n"));
707
0
    return false;
708
0
  }
709
1.99M
  m_type = static_cast<int>(input->readULong(1)); // 0, 20(then ff), 40, 60(then ff)
710
1.99M
  m_numLines = static_cast<int>(input->readLong(1));
711
1.99M
  if (vers <= 3)
712
0
    return true;
713
1.99M
  m_dim->setX(float(input->readULong(2))/1440.f);
714
1.99M
  m_dim->setY(float(input->readLong(2))/72.f);
715
1.99M
  return true;
716
1.99M
}
717
void ParagraphInfo::insert(ParagraphInfo const &pInfo)
718
0
{
719
0
  m_type.insert(pInfo.m_type);
720
0
  m_dim.insert(pInfo.m_dim);
721
0
  m_numLines.insert(pInfo.m_numLines);
722
0
  m_error += pInfo.m_error;
723
0
}
724
725
// paragraph
726
Paragraph::~Paragraph()
727
129M
{
728
129M
}
729
730
bool Paragraph::read(MWAWInputStreamPtr &input, long endPos)
731
10.7M
{
732
10.7M
  long pos = input->tell();
733
10.7M
  bool sectionSet = m_section.isSet();
734
10.7M
  if (m_version > 3 && m_section->read(input,endPos))
735
396k
    return true;
736
10.3M
  if (m_version == 3 && m_section->readV3(input,endPos))
737
273k
    return true;
738
10.1M
  if (!sectionSet) m_section.setSet(false);
739
740
10.1M
  input->seek(pos, librevenge::RVNG_SEEK_SET);
741
10.1M
  bool tableSet = m_table.isSet();
742
10.1M
  if (m_table->read(input,endPos))
743
952k
    return true;
744
9.17M
  if (!tableSet) m_table.setSet(false);
745
746
9.17M
  input->seek(pos, librevenge::RVNG_SEEK_SET);
747
9.17M
  long dSz = endPos-pos;
748
9.17M
  if (dSz < 1) return false;
749
9.17M
  libmwaw::DebugStream f;
750
9.17M
  int c = static_cast<int>(input->readULong(1)), val;
751
9.17M
  switch (c) {
752
72.2k
  case 0x2: // sprmPIstd
753
72.2k
    if (dSz < 2) return false;
754
69.1k
    m_styleId = static_cast<int>(input->readLong(1));
755
69.1k
    break;
756
36.6k
  case 0x3: { // sprmPIstdPermute: checkme: alway find with 3,3,2,3
757
36.6k
    if (dSz < 2) return false;
758
34.3k
    auto num= static_cast<int>(input->readULong(1));
759
34.3k
    if (num<=0 || dSz < 2+num) return false;
760
9.54k
    MWAW_DEBUG_MSG(("Paragraph::read: find istd permute list, unimplemented\n"));
761
9.54k
    f << "istPerm=[";
762
332k
    for (int i = 0; i < num; i++)
763
323k
      f << input->readLong(1) << ",";
764
9.54k
    f << "],";
765
9.54k
    break;
766
34.3k
  }
767
62.4k
  case 0x5:
768
62.4k
    if (dSz < 2) return false;
769
56.8k
    val = static_cast<int>(input->readLong(1));
770
56.8k
    switch (val) {
771
6.06k
    case 0:
772
6.06k
      m_justify = MWAWParagraph::JustificationLeft;
773
6.06k
      return true;
774
7.57k
    case 1:
775
7.57k
      m_justify = MWAWParagraph::JustificationCenter;
776
7.57k
      return true;
777
2.14k
    case 2:
778
2.14k
      m_justify = MWAWParagraph::JustificationRight;
779
2.14k
      return true;
780
1.61k
    case 3:
781
1.61k
      m_justify = MWAWParagraph::JustificationFull;
782
1.61k
      return true;
783
39.4k
    default:
784
39.4k
      MWAW_DEBUG_MSG(("MsWrdStruct::Paragraph::read: can not read align\n"));
785
39.4k
      f << "#align=" << val << ",";
786
39.4k
      break;
787
56.8k
    }
788
39.4k
    break;
789
48.7k
  case 0x6: // a small number : always 1 ?
790
120k
  case 0x7:
791
175k
  case 0x8:
792
207k
  case 0x9:
793
239k
  case 0xe: // a small number always 0 ?
794
239k
    if (dSz < 2) return false;
795
219k
    val = static_cast<int>(input->readLong(1));
796
219k
    switch (c) {
797
66.6k
    case 7:
798
66.6k
      if (val==0)
799
7.17k
        m_breakStatus = m_breakStatus.get()&(~MWAWParagraph::NoBreakBit);
800
59.5k
      else
801
59.5k
        m_breakStatus = m_breakStatus.get()|MWAWParagraph::NoBreakBit;
802
66.6k
      f << "noBreak";
803
66.6k
      break;
804
46.7k
    case 8:
805
46.7k
      if (val==0)
806
4.17k
        m_breakStatus = m_breakStatus.get()&(~MWAWParagraph::NoBreakWithNextBit);
807
42.6k
      else
808
42.6k
        m_breakStatus = m_breakStatus.get()|MWAWParagraph::NoBreakWithNextBit;
809
46.7k
      f << "noBreakWithNext";
810
46.7k
      break;
811
30.4k
    case 9: // normally ok, ...
812
30.4k
      f << "pagebreakbefore";
813
30.4k
      break;
814
75.1k
    default:
815
75.1k
      f << "f" << std::hex << c << std::dec;
816
75.1k
      break;
817
219k
    }
818
219k
    if (val==0) f << "*";
819
201k
    else if (val != 1) f << "=" << val;
820
219k
    f << ",";
821
219k
    break;
822
504k
  case 0xa: {
823
504k
    if (dSz < 2) return false;
824
428k
    val = static_cast<int>(input->readLong(1));
825
428k
    MWAWBorder border;
826
428k
    switch (val) {
827
6.54k
    case 0:
828
6.54k
      break; // normal, checkme
829
3.29k
    case 1:
830
3.29k
      border.m_width = 2;
831
3.29k
      break;
832
2.31k
    case 2:
833
2.31k
      border.m_type = MWAWBorder::Double;
834
2.31k
      break;
835
2.88k
    case 3:
836
2.88k
      border.m_width = 2;
837
2.88k
      f << "border[shadow],";
838
2.88k
      break;
839
413k
    default:
840
413k
      f << "#borders=" << val << ",";
841
413k
      break;
842
428k
    }
843
428k
    m_bordersStyle = border;
844
428k
    break;
845
428k
  }
846
228k
  case 0xb:
847
228k
    if (dSz < 2) return false;
848
213k
    val = static_cast<int>(input->readULong(1));
849
213k
    if (val && val <= 0x10) {
850
186k
      if (m_borders.size() < 4)
851
56.7k
        resizeBorders(4);
852
186k
      if (val & 0x1)
853
181k
        m_borders[libmwaw::Top] = m_bordersStyle.get();
854
186k
      if (val & 0x2)
855
179k
        m_borders[libmwaw::Bottom] = m_bordersStyle.get();
856
      // val & 0x4
857
186k
      if ((val & 0x4) || val==0x10)
858
3.38k
        m_borders[libmwaw::Left] = m_bordersStyle.get();
859
186k
      if (val & 0x8)
860
181k
        m_borders[libmwaw::Right] = m_bordersStyle.get();
861
186k
      return true;
862
186k
    }
863
27.2k
    else if (val)
864
19.4k
      f << "#borders=" << val << ",";
865
27.2k
    break;
866
30.3k
  case 0xf: // tabs
867
54.1k
  case 0x17:  { // tabs
868
54.1k
    auto sz = static_cast<int>(input->readULong(1));
869
54.1k
    if (sz<2 || 2+sz > dSz) {
870
27.9k
      MWAW_DEBUG_MSG(("MsWrdStruct::Paragraph::read: can not read tab\n"));
871
27.9k
      return false;
872
27.9k
    }
873
26.2k
    int deletedSz=(c==0x17) ? 4 : 2;
874
26.2k
    auto N0 = static_cast<int>(input->readULong(1));
875
26.2k
    if (deletedSz*N0 > sz) {
876
11.1k
      MWAW_DEBUG_MSG(("MsWrdStruct::Paragraph::read: num of deleted tabs seems odd\n"));
877
11.1k
      return false;
878
11.1k
    }
879
15.0k
    if (N0) {
880
87.0k
      for (int i = 0; i < N0; i++)
881
78.8k
        m_deletedTabs.push_back(float(input->readLong(2))/1440.f);
882
8.16k
    }
883
15.0k
    if (c==0x17 && N0) {
884
783
      f << "del17=[";
885
5.27k
      for (int i = 0; i < N0; i++) { // always with 0x19 ?
886
4.49k
        val=static_cast<int>(input->readULong(2));
887
4.49k
        if (val==0x19)
888
24
          f << "_";
889
4.46k
        else
890
4.46k
          f << std::hex << val << std::dec << ",";
891
4.49k
      }
892
783
      f << "],";
893
783
    }
894
15.0k
    auto N = static_cast<int>(input->readULong(1));
895
15.0k
    if (N*3+deletedSz*N0+2 != sz) {
896
7.80k
      MWAW_DEBUG_MSG(("MsWrdStruct::Paragraph::read: num tab seems odd\n"));
897
7.80k
      f << "#";
898
7.80k
      m_extra += f.str();
899
7.80k
      return false;
900
7.80k
    }
901
7.23k
    std::vector<float> tabs;
902
7.23k
    tabs.resize(size_t(N));
903
18.6k
    for (auto &t : tabs) t = float(input->readLong(2))/1440.f;
904
18.6k
    for (auto const &tabPos : tabs) {
905
18.6k
      MWAWTabStop tab;
906
18.6k
      tab.m_position = double(tabPos);
907
18.6k
      val = static_cast<int>(input->readULong(1));
908
18.6k
      switch (val>>5) {
909
11.8k
      case 0:
910
11.8k
        break;
911
759
      case 1:
912
759
        tab.m_alignment = MWAWTabStop::CENTER;
913
759
        break;
914
407
      case 2:
915
407
        tab.m_alignment = MWAWTabStop::RIGHT;
916
407
        break;
917
615
      case 3:
918
615
        tab.m_alignment = MWAWTabStop::DECIMAL;
919
615
        break;
920
205
      case 4:
921
205
        tab.m_alignment = MWAWTabStop::BAR;
922
205
        break;
923
4.85k
      default:
924
4.85k
        f << "#tabAlign=" << int(val>>5) << ",";
925
4.85k
        break;
926
18.6k
      }
927
18.6k
      switch ((val>>2)&3) {
928
2.32k
      case 1:
929
2.32k
        tab.m_leaderCharacter = '.';
930
2.32k
        break;
931
1.67k
      case 2:
932
1.67k
        tab.m_leaderCharacter = '-';
933
1.67k
        break;
934
3.96k
      case 3:
935
3.96k
        tab.m_leaderCharacter = '_';
936
3.96k
        break;
937
10.7k
      case 0:
938
10.7k
      default:
939
10.7k
        break;
940
18.6k
      }
941
18.6k
      if (val & 0x13)
942
8.48k
        f << "#tabsFlags=" << std::hex << (val & 0x13) << ",";
943
18.6k
      m_tabs->push_back(tab);
944
18.6k
    }
945
7.23k
    break;
946
7.23k
  }
947
1.40M
  case 0x10: // right
948
1.46M
  case 0x11: // left
949
1.51M
  case 0x13: // first left
950
1.51M
    if (dSz < 3) return false;
951
1.48M
    val = static_cast<int>(input->readLong(2));
952
1.48M
    if (c == 0x13) m_margins[0] = val/1440.;
953
1.43M
    else if (c == 0x11) m_margins[1] = val/1440.;
954
1.37M
    else m_margins[2] = val/1440.;
955
1.48M
    return true;
956
83.0k
  case 0x14: // alignment : 240 normal, 480 : double, ..
957
83.0k
    if (dSz < 3) return false;
958
75.9k
    val = static_cast<int>(input->readLong(2));
959
75.9k
    m_interline=double(val)/1440.;
960
75.9k
    return true;
961
44.0k
  case 0x15: // spacing before DWIPP
962
103k
  case 0x16: // spacing after DWIPP
963
103k
    if (dSz < 3) return false;
964
93.4k
    val = static_cast<int>(input->readLong(2));
965
93.4k
    m_spacings[c-0x14] = double(val)/1440.;
966
93.4k
    return true;
967
232k
  case 0x18:
968
309k
  case 0x19:
969
309k
    if (dSz < 2) return false;
970
303k
    val = static_cast<int>(input->readULong(1));
971
303k
    if (c==0x18) m_inCell = (val!=0);
972
75.5k
    else m_tableDef = (val != 0);
973
303k
    if (val != 0 && val!=1) {
974
193k
      f << "#f" << std::hex << c << std::dec << "=" << val << ",";
975
193k
      break;
976
193k
    }
977
110k
    return true;
978
15.6k
  case 0x1a: // frame x,y,w
979
32.5k
  case 0x1b:
980
70.9k
  case 0x1c: {
981
70.9k
    if (dSz < 3) return false;
982
62.3k
    val = static_cast<int>(input->readLong(2));
983
62.3k
    char const *what[] = {"frameX", "frameY", "frameWidth" };
984
62.3k
    f << what[c-0x1a] << "=";
985
62.3k
    if (val < 0) {
986
10.8k
      val = -val;
987
10.8k
      int type=(val&0x1C)>>2;
988
10.8k
      if (c==0x1a) {
989
2.97k
        switch (type) {
990
33
        case 1:
991
33
          f << "center";
992
33
          break;
993
1.00k
        case 2:
994
1.00k
          f << "right";
995
1.00k
          break;
996
932
        case 3:
997
932
          f << "inside";
998
932
          break;
999
711
        case 4:
1000
711
          f << "outside";
1001
711
          break;
1002
298
        default:
1003
298
          f << "#" << type;
1004
298
          break;
1005
2.97k
        }
1006
2.97k
        val &= 0xFFE3;
1007
2.97k
      }
1008
7.86k
      else if (c==0x1b) {
1009
3.65k
        switch (type) {
1010
1.30k
        case 1:
1011
1.30k
          f << "top,";
1012
1.30k
          break;
1013
21
        case 2:
1014
21
          f << "center,";
1015
21
          break;
1016
127
        case 3:
1017
127
          f << "bottom,";
1018
127
          break;
1019
2.20k
        default:
1020
2.20k
          f << "#" << type;
1021
2.20k
          break;
1022
3.65k
        }
1023
3.65k
        val &= 0xFFE3;
1024
3.65k
      }
1025
10.8k
      if (val)
1026
10.2k
        f << "[" << val << "]";
1027
10.8k
      f << ",";
1028
10.8k
    }
1029
51.5k
    else f << val/1440. << ",";
1030
62.3k
    break;
1031
62.3k
  }
1032
96.3k
  case 0x1d:
1033
96.3k
    if (dSz < 2) return false;
1034
93.7k
    val = static_cast<int>(input->readULong(1));
1035
93.7k
    switch (val&3) {
1036
3.21k
    case 0:
1037
3.21k
      break; // column
1038
81.9k
    case 1:
1039
81.9k
      f << "Xrel=margin,";
1040
81.9k
      break;
1041
4.84k
    case 2:
1042
4.84k
      f << "Xrel=page,";
1043
4.84k
      break;
1044
3.76k
    default:
1045
3.76k
      f << "#Xrel=3,";
1046
3.76k
      break;
1047
93.7k
    }
1048
93.7k
    if (val&4) f << "Yrel=page,"; // def margin
1049
93.7k
    if (val&0xF8) f << "#rel=" << (val>>3) << ",";
1050
93.7k
    break;
1051
70.6k
  case 0x1e: // checkme: find one time in v3 (text struct file) with data 0x80
1052
106k
  case 0x1f:
1053
186k
  case 0x20:
1054
831k
  case 0x21:
1055
994k
  case 0x22: {
1056
994k
    if (dSz < 3) return false;
1057
955k
    std::string bExtra;
1058
955k
    MWAWBorder border = getBorder(static_cast<int>(input->readULong(2)), bExtra);
1059
955k
    if (bExtra.length())
1060
0
      f << "bord" << (c-0x1e) << "[" << bExtra << "],";
1061
955k
    if (c < 0x22) {
1062
798k
      size_t const wh[] = { libmwaw::Top, libmwaw::Left,
1063
798k
                            libmwaw::Bottom, libmwaw::Right
1064
798k
                          };
1065
798k
      size_t p = wh[c-0x1e];
1066
798k
      if (m_borders.size() <= p)
1067
340k
        resizeBorders(p+1);
1068
798k
      m_borders[p] = border;
1069
798k
    }
1070
157k
    else {
1071
157k
      if (m_borders.size() < 6)
1072
70.9k
        resizeBorders(6);
1073
157k
      m_borders[libmwaw::HMiddle] = border;
1074
157k
      m_borders[libmwaw::VMiddle] = border;
1075
157k
    }
1076
955k
    break;
1077
994k
  }
1078
74.2k
  case 0x24: { // distance to text (related to frame ?)
1079
74.2k
    if (dSz < 3) return false;
1080
67.5k
    val = static_cast<int>(input->readULong(2));
1081
67.5k
    if (val) f << "distToText=" << val/1440. << ",";
1082
67.5k
    break;
1083
74.2k
  }
1084
4.72M
  default:
1085
4.72M
    return false;
1086
9.17M
  }
1087
2.17M
  m_extra += f.str();
1088
2.17M
  return true;
1089
9.17M
}
1090
1091
// paragraph
1092
std::ostream &operator<<(std::ostream &o, Paragraph const &ind)
1093
0
{
1094
0
  if (ind.m_styleId.isSet())
1095
0
    o << "styleId[orig]=" << ind.m_styleId.get() << ",";
1096
0
  if (!ind.m_deletedTabs.empty()) {
1097
0
    o << "deletedTab=[";
1098
0
    for (auto const &val : ind.m_deletedTabs)
1099
0
      o << val << ",";
1100
0
    o << "],";
1101
0
  }
1102
0
  if (ind.m_interline.isSet())
1103
0
    o << "interline=" << *ind.m_interline << ",";
1104
0
  if (ind.m_info.isSet())
1105
0
    o << "dim=[" << *ind.m_info << "],";
1106
0
  o << static_cast<MWAWParagraph const &>(ind);
1107
0
  if (ind.m_bordersStyle.isSet())
1108
0
    o << "borders[style]=" << ind.m_bordersStyle.get() << ",";
1109
0
  if (ind.m_section.isSet()) o << ind.m_section.get() << ",";
1110
0
  if (ind.m_inCell.get()) o << "cell,";
1111
0
  if (ind.m_tableDef.get()) o << "table[def],";
1112
0
  if (ind.m_table.isSet()) o << "table=[" << ind.m_table.get() << "],";
1113
0
  return o;
1114
0
}
1115
1116
bool Paragraph::getFont(Font &font, Font const *styleFont) const
1117
653k
{
1118
653k
  bool res = true;
1119
653k
  if (m_font.isSet())
1120
94.7k
    font = m_font.get();
1121
558k
  else
1122
558k
    res = false;
1123
653k
  if (m_modFont.isSet()) {
1124
132k
    font.insert(*m_modFont, styleFont);
1125
132k
    res = true;
1126
132k
  }
1127
653k
  return res;
1128
653k
}
1129
1130
void Paragraph::updateParagraphToFinalState(Paragraph const *style)
1131
597k
{
1132
597k
  if (!m_interline.isSet()) return;
1133
111k
  double interline=*m_interline;
1134
111k
  if (interline<-1 || interline>1) {
1135
1.21k
    MWAW_DEBUG_MSG(("MsWrdStruct::Paragraph::updateParagraphToFinalState: interline spacing seems odd\n"));
1136
1.21k
    setInterline(1.0, librevenge::RVNG_PERCENT);
1137
1.21k
    return;
1138
1.21k
  }
1139
110k
  if (interline>0) {
1140
28.1k
    setInterline(interline, librevenge::RVNG_INCH, MWAWParagraph::AtLeast);
1141
28.1k
    return;
1142
28.1k
  }
1143
81.9k
  if (interline<0) {
1144
228
    setInterline(-interline, librevenge::RVNG_INCH);
1145
228
    return;
1146
228
  }
1147
  // checkme: what to do when m_interline=0, use the style interline or the para info?
1148
81.7k
  if (!style || !style->m_interline.isSet())
1149
9.81k
    return;
1150
71.9k
  interline=*style->m_interline;
1151
71.9k
  if (interline>0 && interline <=1)
1152
27.7k
    setInterline(interline, librevenge::RVNG_INCH, MWAWParagraph::AtLeast);
1153
44.2k
  else if (interline<0 && interline >=-1)
1154
10
    setInterline(-interline, librevenge::RVNG_INCH, MWAWParagraph::AtLeast);
1155
71.9k
}
1156
1157
void Paragraph::insert(Paragraph const &para, bool insertModif)
1158
351k
{
1159
351k
  if (m_tabs.isSet()) {
1160
412k
    for (int st=0; st<2; ++st) {
1161
274k
      std::vector<float> const &deletedTabs=st==0?para.m_deletedTabs:m_deletedTabs;
1162
274k
      for (auto const val : deletedTabs) {
1163
191k
        for (auto it=m_tabs->begin(); it!=m_tabs->end(); ++it) {
1164
158k
          if (it->m_position < double(val)-1e-3 || it->m_position > double(val)+1e-3)
1165
50.1k
            continue;
1166
108k
          m_tabs->erase(it);
1167
108k
          break;
1168
158k
        }
1169
141k
      }
1170
274k
    }
1171
137k
  }
1172
351k
  MWAWParagraph::insert(para);
1173
351k
  m_styleId.insert(para.m_styleId);
1174
351k
  m_interline.insert(para.m_interline);
1175
351k
  if (para.m_info.isSet() && para.m_info->isLineSet())
1176
154k
    m_info.insert(para.m_info);
1177
351k
  if (!m_font.isSet())
1178
214k
    m_font=para.m_font;
1179
137k
  else if (para.m_font.isSet())
1180
623
    m_font->insert(*para.m_font);
1181
351k
  if (insertModif)
1182
351k
    m_modFont->insert(*para.m_modFont);
1183
351k
  if (!m_section.isSet())
1184
339k
    m_section = para.m_section;
1185
12.9k
  else if (para.m_section.isSet())
1186
5.49k
    m_section->insert(*para.m_section);
1187
351k
  if (!m_bordersStyle.isSet() || para.m_bordersStyle.isSet())
1188
343k
    m_bordersStyle = para.m_bordersStyle;
1189
351k
  m_inCell.insert(para.m_inCell);
1190
351k
  if (!m_table.isSet())
1191
285k
    m_table = para.m_table;
1192
66.1k
  else if (para.m_table.isSet())
1193
8.59k
    m_table->insert(*para.m_table);
1194
351k
  m_tableDef.insert(para.m_tableDef);
1195
351k
}
1196
1197
void Paragraph::print(std::ostream &o, MWAWFontConverterPtr converter) const
1198
0
{
1199
0
  if (m_font.isSet())
1200
0
    o << "font=[" << m_font->m_font->getDebugString(converter) << m_font.get() << "],";
1201
0
  if (m_modFont.isSet())
1202
0
    o << "modifFont=[" << m_modFont->m_font->getDebugString(converter) << m_modFont.get() << "],";
1203
0
  o << *this;
1204
0
}
1205
1206
// generic
1207
MWAWBorder getBorder(int val, std::string &extra)
1208
1.05M
{
1209
1.05M
  MWAWBorder border;
1210
1.05M
  libmwaw::DebugStream f;
1211
1212
1.05M
  if (val & 0x3E00) f << "textSep=" << int((val& 0x3E00)>>9) << "pt";
1213
1.05M
  if (val & 0x4000) f << "shad,";
1214
1.05M
  if (val & 0x8000) f << "*";
1215
1.05M
  switch (val &0x1FF) {
1216
33.1k
  case 0:
1217
33.1k
    border.m_style = MWAWBorder::None;
1218
33.1k
    break;
1219
24.1k
  case 0x40:
1220
24.1k
    break; // normal
1221
8.52k
  case 0x49:
1222
8.52k
    border.m_type = MWAWBorder::Double;
1223
8.52k
    break;
1224
7.67k
  case 0x80:
1225
7.67k
    border.m_width = 2;
1226
7.67k
    break;
1227
2.96k
  case 0x180:
1228
2.96k
    border.m_style = MWAWBorder::Dot;
1229
2.96k
    break;
1230
1.20k
  case 0x1c0:
1231
1.20k
    border.m_width = 0.5;
1232
1.20k
    break;
1233
980k
  default:
1234
980k
    f << "#bType=" << std::hex << (val & 0x1FF) << std::dec;
1235
980k
    break;
1236
1.05M
  }
1237
1238
1.05M
  extra=f.str();
1239
1.05M
  return border;
1240
1.05M
}
1241
1242
}
1243
// vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: