Coverage Report

Created: 2026-09-06 07:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libstaroffice/src/lib/StarObjectNumericRuler.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
/* libstaroffice
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 <cstring>
35
#include <iomanip>
36
#include <iostream>
37
#include <limits>
38
#include <map>
39
#include <sstream>
40
41
#include <librevenge/librevenge.h>
42
43
#include "StarObjectNumericRuler.hxx"
44
45
#include "STOFFListener.hxx"
46
#include "STOFFPageSpan.hxx"
47
48
#include "StarAttribute.hxx"
49
#include "StarBitmap.hxx"
50
#include "StarFormatManager.hxx"
51
#include "StarItemPool.hxx"
52
#include "StarObject.hxx"
53
#include "StarState.hxx"
54
#include "StarWriterStruct.hxx"
55
#include "StarZone.hxx"
56
#include "SWFieldManager.hxx"
57
58
/** Internal: the structures of a StarObjectNumericRuler */
59
namespace StarObjectNumericRulerInternal
60
{
61
////////////////////////////////////////
62
//! Internal: the state of a StarObjectNumericRuler
63
struct State {
64
  //! constructor
65
  State()
66
254
    : m_nameToListMap()
67
254
    , m_simplifyNameToListMap()
68
254
  {
69
254
  }
70
  //! a map list name to list
71
  std::map<librevenge::RVNGString, std::shared_ptr<STOFFList> > m_nameToListMap;
72
  //! a map list simpl name to list
73
  std::map<librevenge::RVNGString, std::shared_ptr<STOFFList> > m_simplifyNameToListMap;
74
};
75
76
}
77
78
////////////////////////////////////////////////////////////
79
// constructor/destructor, ...
80
////////////////////////////////////////////////////////////
81
StarObjectNumericRuler::StarObjectNumericRuler(StarObject const &orig, bool duplicateState)
82
254
  : StarObject(orig, duplicateState)
83
254
  , m_numericRulerState(new StarObjectNumericRulerInternal::State)
84
254
{
85
254
}
86
87
StarObjectNumericRuler::~StarObjectNumericRuler()
88
254
{
89
254
}
90
91
////////////////////////////////////////////////////////////
92
// send data
93
////////////////////////////////////////////////////////////
94
std::shared_ptr<STOFFList> StarObjectNumericRuler::getList(librevenge::RVNGString const &name) const
95
179
{
96
179
  if (name.empty())
97
0
    return std::shared_ptr<STOFFList>();
98
179
  if (m_numericRulerState->m_nameToListMap.find(name)!=m_numericRulerState->m_nameToListMap.end())
99
109
    return m_numericRulerState->m_nameToListMap.find(name)->second;
100
70
  auto simpName=libstoff::simplifyString(name);
101
70
  if (m_numericRulerState->m_simplifyNameToListMap.find(simpName)!=m_numericRulerState->m_simplifyNameToListMap.end())
102
0
    return m_numericRulerState->m_simplifyNameToListMap.find(simpName)->second;
103
70
  STOFF_DEBUG_MSG(("StarObjectNumericRuler::getList: can not find list with name %s\n", name.cstr()));
104
70
  return std::shared_ptr<STOFFList>();
105
70
}
106
107
////////////////////////////////////////////////////////////
108
// the parser
109
////////////////////////////////////////////////////////////
110
bool StarObjectNumericRuler::read(StarZone &zone)
111
254
try
112
254
{
113
254
  STOFFInputStreamPtr input=zone.input();
114
254
  libstoff::DebugFile &ascFile=zone.ascii();
115
254
  if (!zone.readSWHeader()) {
116
5
    STOFF_DEBUG_MSG(("StarObjectNumericRuler::read: can not read the header\n"));
117
5
    return false;
118
5
  }
119
249
  zone.readStringsPool();
120
  // sw_sw3num.cxx::Sw3IoImp::InNumRules
121
510
  while (!input->isEnd()) {
122
510
    long pos=input->tell();
123
510
    bool done=false;
124
510
    switch (input->peek()) {
125
239
    case '0':
126
253
    case 'R': {
127
253
      std::shared_ptr<STOFFList> list;
128
253
      done=StarObjectNumericRuler::readList(zone,list);
129
253
      if (!done || !list) break;
130
252
      if (list->m_name.empty()) {
131
0
        STOFF_DEBUG_MSG(("StarObjectNumericRuler::read: can not find the list name\n"));
132
0
        break;
133
0
      }
134
252
      if (m_numericRulerState->m_nameToListMap.find(list->m_name)!=m_numericRulerState->m_nameToListMap.end()) {
135
0
        STOFF_DEBUG_MSG(("StarObjectNumericRuler::read: oops a list with name %s already exists\n", list->m_name.cstr()));
136
0
      }
137
252
      else {
138
252
        m_numericRulerState->m_nameToListMap[list->m_name]=list;
139
252
        auto simpName=libstoff::simplifyString(list->m_name);
140
252
        if (m_numericRulerState->m_simplifyNameToListMap.find(simpName)==m_numericRulerState->m_simplifyNameToListMap.end())
141
252
          m_numericRulerState->m_simplifyNameToListMap[simpName]=list;
142
252
      }
143
252
      break;
144
252
    }
145
257
    default:
146
257
      break;
147
510
    }
148
510
    if (done && input->tell()>pos)
149
252
      continue;
150
258
    unsigned char type;
151
258
    input->seek(pos, librevenge::RVNG_SEEK_SET);
152
258
    if (!zone.openSWRecord(type)) {
153
6
      input->seek(pos, librevenge::RVNG_SEEK_SET);
154
6
      break;
155
6
    }
156
252
    libstoff::DebugStream f;
157
252
    f << "StarNumericList[list-" << type << "]:";
158
252
    done=false;
159
252
    switch (type) {
160
0
    case '+': { // extra outline
161
0
      zone.openFlagZone();
162
0
      auto N=int(input->readULong(1));
163
0
      f << "N=" << N << ",";
164
0
      zone.closeFlagZone();
165
0
      if (input->tell()+3*N>zone.getRecordLastPosition()) {
166
0
        STOFF_DEBUG_MSG(("StarObjectNumericRuler::read: nExtraOutline seems bad\n"));
167
0
        f << "###,";
168
0
        break;
169
0
      }
170
0
      f << "levSpace=[";
171
0
      for (int i=0; i<N; ++i)
172
0
        f << input->readULong(1) << ":" << input->readULong(2) << ",";
173
0
      f << "],";
174
0
      break;
175
0
    }
176
0
    case '?':
177
0
      STOFF_DEBUG_MSG(("StarObjectNumericRuler::read: reading inHugeRecord(TEST_HUGE_DOCS) is not implemented\n"));
178
0
      break;
179
243
    case 'Z':
180
243
      done=true;
181
243
      break;
182
9
    default:
183
9
      STOFF_DEBUG_MSG(("StarObjectNumericRuler::read: find unimplemented type\n"));
184
9
      f << "###type,";
185
9
      break;
186
252
    }
187
252
    if (!zone.closeSWRecord(type, "StarNumericList")) {
188
0
      input->seek(pos, librevenge::RVNG_SEEK_SET);
189
0
      break;
190
0
    }
191
252
    ascFile.addPos(pos);
192
252
    ascFile.addNote(f.str().c_str());
193
194
252
    if (done)
195
243
      break;
196
252
  }
197
249
  if (!input->isEnd()) {
198
6
    STOFF_DEBUG_MSG(("StarObjectNumericRuler::read: find extra data\n"));
199
6
    ascFile.addPos(input->tell());
200
6
    ascFile.addNote("StarNumericList:###extra");
201
6
  }
202
249
  return true;
203
249
}
204
254
catch (...)
205
254
{
206
0
  return false;
207
0
}
208
209
bool StarObjectNumericRuler::readLevel(StarZone &zone, STOFFListLevel &level)
210
164
{
211
164
  STOFFInputStreamPtr input=zone.input();
212
164
  libstoff::DebugFile &ascFile=zone.ascii();
213
164
  unsigned char type;
214
164
  long pos=input->tell();
215
164
  if (input->peek()!='n' || !zone.openSWRecord(type)) {
216
58
    input->seek(pos, librevenge::RVNG_SEEK_SET);
217
58
    return false;
218
58
  }
219
106
  libstoff::DebugStream f;
220
106
  f << "Entries(StarNumericList)[level-" << zone.getRecordLevel() << "]:";
221
  // sw_sw3num.cxx Sw3IoImp::InNumFmt
222
106
  level=STOFFListLevel();
223
106
  std::vector<uint32_t> string;
224
106
  librevenge::RVNGString fontName;
225
528
  for (int i=0; i<4; ++i) {
226
424
    if (!zone.readString(string)) {
227
2
      STOFF_DEBUG_MSG(("StarObjectNumericRuler::readLevel: can not read a string\n"));
228
2
      f << "###string";
229
2
      ascFile.addPos(pos);
230
2
      ascFile.addNote(f.str().c_str());
231
232
2
      zone.closeSWRecord('n', "StarNumericList");
233
2
      return true;
234
2
    }
235
422
    if (string.empty()) continue;
236
176
    static char const* const wh[]= {"prefix", "postfix", "fontname", "fontstyle"};
237
176
    f << wh[i] << "=" << libstoff::getString(string).cstr() << ",";
238
176
    if (i==0) level.m_propertyList.insert("style:num-prefix",libstoff::getString(string));
239
176
    else if (i==1) level.m_propertyList.insert("style:num-suffix",libstoff::getString(string));
240
88
    else if (i==2) fontName=libstoff::getString(string);
241
176
  }
242
104
  auto format=int(input->readULong(2));
243
104
  auto eType=int(input->readULong(1));
244
104
  auto cBullet=uint8_t(input->readULong(1));
245
104
  int maxLevel=0;
246
104
  if (zone.isCompatibleWith(0x201))
247
104
    maxLevel=int(input->readULong(1));
248
0
  else {
249
0
    bool hasLevel;
250
0
    *input >> hasLevel;
251
0
    if (hasLevel) maxLevel=10;
252
0
  }
253
104
  level.m_startValue=int(input->readULong(2));
254
104
  auto adjust=int(input->readULong(1));
255
104
  unsigned long leftSpace=input->readULong(4);
256
104
  long firstLineOffset=input->readLong(4);
257
104
  auto fontFamily=int(input->readULong(1));
258
104
  auto fontPitch=int(input->readULong(1));
259
104
  auto charSet=int(input->readULong(1));
260
104
  bool isSymbolFont=false;
261
104
  if (!fontName.empty()) {
262
    // todo find where other font characteristic are stored
263
86
    level.m_font.reset(new STOFFFont);
264
86
    STOFFFont &font=*level.m_font;
265
86
    font.m_propertyList.insert("style:font-name", fontName);
266
86
    if (fontName=="StarBats" || fontName=="StarMath") {
267
0
      isSymbolFont=true;
268
0
      font.m_propertyList.insert("style:font-charset","x-symbol");
269
0
    }
270
86
  }
271
104
  if (format!=0xFFFF) f << "nFmt=" << format << ",";
272
104
  if (eType<=4 || eType==9 || eType==10) {
273
0
    char const *wh[]= {"A", "a", "I", "i", "1", "", "", "", "", "A"/*UPPER_LETTER_N*/, "a"/*LOWER_LETTER_N*/};
274
0
    level.m_propertyList.insert("style:num-format", wh[eType]);
275
0
    level.m_type=STOFFListLevel::NUMBER;
276
0
    f << "type=" << wh[eType] << ",";
277
0
  }
278
104
  else if (eType==5) {
279
18
    level.m_propertyList.insert("text:bullet-char", " ");
280
18
    level.m_type=STOFFListLevel::NONE;
281
18
    f << "none,";
282
18
  }
283
86
  else if (eType==6) {
284
86
    level.m_type=STOFFListLevel::BULLET;
285
86
    std::vector<uint8_t> buffer(1, cBullet);
286
86
    std::vector<uint32_t> res;
287
86
    std::vector<size_t> positions;
288
    // checkme if fontname is StarBats or StarMath, this does not works very well...
289
86
    auto encoding=(charSet==0 && isSymbolFont) ? StarEncoding::E_SYMBOL : StarEncoding::getEncodingForId(charSet);
290
86
    StarEncoding::convert(buffer, encoding, res, positions);
291
86
    level.m_propertyList.insert("text:bullet-char", libstoff::getString(res));
292
86
    f << "bullet=" << libstoff::getString(res).cstr() << ",";
293
86
  }
294
0
  else {
295
0
    STOFF_DEBUG_MSG(("StarObjectNumericRuler::readLevel: unimplemented format\n"));
296
    // PAGEDESC, BITMAP
297
0
    level.m_type=STOFFListLevel::BULLET;
298
0
    librevenge::RVNGString bullet;
299
0
    libstoff::appendUnicode(0x2022, bullet); // checkme
300
0
    level.m_propertyList.insert("text:bullet-char", bullet);
301
0
    f << "#eType=" << eType << "," << "cBullet=" << cBullet << ",";
302
0
  }
303
104
  if (maxLevel) f << "nUpperLevel=" << maxLevel << ",";
304
104
  if (level.m_startValue) f << "start=" << level.m_startValue << ",";
305
104
  if (adjust>=0 && adjust<=5) {
306
104
    char const *wh[]= {"left", "right", "justify", "center", "justify"/*block line*/, "end"};
307
104
    level.m_propertyList.insert("fo:text-align", wh[adjust]);
308
104
    f << wh[adjust] << ",";
309
104
  }
310
0
  else {
311
0
    STOFF_DEBUG_MSG(("StarObjectNumericRuler::readLevel: unknown adjust\n"));
312
0
    f << "#adjust=" << adjust << ",";
313
0
  }
314
315
104
  if (leftSpace || firstLineOffset) { // checkme
316
86
    f << "left[offset]=" << leftSpace << ",";
317
86
    level.m_propertyList.insert("fo:margin-left", 0.05*double(long(leftSpace)+(firstLineOffset<0 ? -firstLineOffset: 0)), librevenge::RVNG_POINT);
318
86
  }
319
104
  if (firstLineOffset) {
320
86
    level.m_propertyList.insert("fo:text-indent", 0.05*double(firstLineOffset), librevenge::RVNG_POINT);
321
86
    f << "firstLine[offset]=" << firstLineOffset << ",";
322
86
  }
323
104
  if (fontFamily) f << "family[font]=" << fontFamily << ",";
324
104
  if (fontPitch) f << "pitch[font]=" << fontPitch << ",";
325
104
  if (charSet) f << "char[set]=" << charSet << ",";
326
327
104
  int cFlags=zone.openFlagZone();
328
104
  zone.closeFlagZone();
329
104
  if (cFlags&0xF0) f << "cFlags=" << (cFlags>>4) << ",";
330
104
  if (zone.isCompatibleWith(0x17, 0x22)) // the character format
331
0
    f << "nFmt=" << input->readULong(2) << ",";
332
104
  if (zone.isCompatibleWith(0x17,0x22, 0x101,0x201)) { // ignored by old LibreOffice
333
0
    f << "bRelSpace=" << input->readULong(1) << ",";
334
0
    f << "nRelLSpace=" << input->readLong(4) << ",";
335
0
  }
336
104
  if (zone.isCompatibleWith(0x17,0x22, 0x101)) {
337
104
    auto charTextDistance=int(input->readULong(2));
338
104
    if (charTextDistance) {
339
0
      level.m_propertyList.insert("text:min-label-distance", 0.05*double(charTextDistance), librevenge::RVNG_POINT);
340
0
      f << "nTextOffset=" << charTextDistance << ",";
341
0
    }
342
104
    if (input->tell()<zone.getRecordLastPosition() && eType==8) {
343
0
      f << "width=" << input->readLong(4) << ",";
344
0
      f << "height=" << input->readLong(4) << ",";
345
0
      auto cF=int(input->readULong(1));
346
0
      if (cF&1) f << "nVer[brush]=" << input->readULong(2) << ",";
347
0
      if (cF&2) f << "nVer[vertOrient]=" << input->readULong(2) << ",";
348
0
    }
349
104
  }
350
104
  ascFile.addPos(pos);
351
104
  ascFile.addNote(f.str().c_str());
352
104
  zone.closeSWRecord('n', "StarNumericList");
353
104
  return true;
354
106
}
355
356
bool StarObjectNumericRuler::readList(StarZone &zone, std::shared_ptr<STOFFList> &list)
357
413
{
358
413
  STOFFInputStreamPtr input=zone.input();
359
413
  libstoff::DebugFile &ascFile=zone.ascii();
360
413
  unsigned char type;
361
413
  long pos=input->tell();
362
413
  if ((input->peek()!='0' && input->peek()!='R') || !zone.openSWRecord(type)) {
363
28
    input->seek(pos, librevenge::RVNG_SEEK_SET);
364
28
    return false;
365
28
  }
366
  // sw_sw3num.cxx::Sw3IoImp::InNumRule
367
385
  libstoff::DebugStream f;
368
385
  f << "Entries(StarNumericList)[" << zone.getRecordLevel() << "]:";
369
385
  int val;
370
385
  librevenge::RVNGString name;
371
385
  if (zone.isCompatibleWith(0x201)) {
372
297
    auto cFlags=int(zone.openFlagZone());
373
297
    auto nStringId=int(input->readULong(2));
374
297
    if (nStringId==0xFFFF)
375
0
      ;
376
297
    else if (!zone.getPoolName(nStringId, name))
377
2
      f << "###name=" << nStringId << ",";
378
295
    else if (!name.empty())
379
294
      f << name.cstr() << ",";
380
297
    if (cFlags&0x10) {
381
14
      val=int(input->readULong(2));     // 3<<11+1<<10+(num1,num2,...,num5,bul1,...,bul5)
382
14
      if (val!=0xFFFF) f << "frmtId=" << val << ",";
383
14
      val=int(input->readULong(2));
384
14
      if (val) f << "poolHelpId=" << val << ",";
385
14
      val=int(input->readULong(1));
386
14
      if (val) f << "poolHelpFileId=" << val << ",";
387
14
    }
388
297
    if (cFlags&0x20) f << "invalid,";
389
297
    if (cFlags&0x40) f << "continuous,";
390
297
    if ((cFlags&0x80) && zone.isCompatibleWith(0x211)) f << "absolute[spaces],";
391
297
  }
392
385
  val=int(input->readULong(1));
393
  // initialise list to default
394
385
  list.reset(new STOFFList(val==0));
395
385
  if (val==0) f << "outline,";  // OUTLINE_RULE, NUM_RULE
396
118
  else if (val!=1) {
397
104
    STOFF_DEBUG_MSG(("StarObjectNumericRuler::readList: unknown type\n"));
398
104
    f << "##eType=" << val << ",";
399
104
  }
400
385
  list->m_name=name;
401
385
  STOFFListLevel defLevel;
402
385
  defLevel.m_type=STOFFListLevel::NUMBER;
403
385
  defLevel.m_propertyList.insert("style:num-format", "1");
404
4.23k
  for (int i=0; i<10; ++i) list->set(i+1, defLevel);
405
385
  if (zone.isCompatibleWith(0x201))
406
297
    zone.closeFlagZone();
407
385
  auto nFormat=int(input->readULong(1));
408
385
  long lastPos=zone.getRecordLastPosition();
409
385
  f << "nFormat=" << nFormat << ",";
410
385
  if (input->tell()+nFormat>lastPos) {
411
12
    STOFF_DEBUG_MSG(("StarObjectNumericRuler::readList: nFormat seems bad\n"));
412
12
    f << "###,";
413
12
    ascFile.addPos(pos);
414
12
    ascFile.addNote(f.str().c_str());
415
12
    zone.closeSWRecord(type, "StarNumericList");
416
12
    return true;
417
12
  }
418
373
  std::vector<int> levels;
419
373
  f << "lvl=[";
420
1.17k
  for (int i=0; i<nFormat; ++i) {
421
801
    levels.push_back(int(input->readULong(1)));
422
801
    f  << levels.back() << ",";
423
801
  }
424
373
  f << "],";
425
373
  ascFile.addPos(pos);
426
373
  ascFile.addNote(f.str().c_str());
427
428
373
  int nKnownFormat=nFormat>10 ? 10 : nFormat;
429
479
  for (int i=0; i<nKnownFormat; ++i) {
430
164
    pos=input->tell();
431
164
    STOFFListLevel level;
432
164
    if (StarObjectNumericRuler::readLevel(zone, level)) {
433
106
      list->set(levels[size_t(i)]+1, level);
434
106
      continue;
435
106
    }
436
58
    STOFF_DEBUG_MSG(("StarObjectNumericRuler::readList: can not read a format\n"));
437
58
    input->seek(pos, librevenge::RVNG_SEEK_SET);
438
58
    break;
439
164
  }
440
441
373
  zone.closeSWRecord(type, "StarNumericList");
442
373
  return true;
443
385
}
444
445
bool StarObjectNumericRuler::readAttributeLevel(StarZone &zone, int vers, long lastPos, STOFFListLevel &level)
446
75.0k
{
447
75.0k
  STOFFInputStreamPtr input=zone.input();
448
75.0k
  long pos=input->tell();
449
75.0k
  libstoff::DebugFile &ascFile=zone.ascii();
450
75.0k
  libstoff::DebugStream f;
451
75.0k
  f << "Entries(StarAttribute)[" << zone.getRecordLevel() << "]:paraBullet,";
452
453
75.0k
  level=STOFFListLevel();
454
  // svx_bulitem.cxx SvxBulletItem::SvxBulletItem
455
75.0k
  uint16_t style;
456
75.0k
  *input >> style;
457
75.0k
  uint16_t charSet=0;
458
75.0k
  bool isSymbolFont=false;
459
75.0k
  int alignement=-1;
460
75.0k
  if (style==128) {
461
252
    f << "bitmap,";
462
252
    StarBitmap bitmap;
463
252
    librevenge::RVNGBinaryData data;
464
252
    std::string dType;
465
252
    if (!bitmap.readBitmap(zone, true, lastPos, data, dType)) {
466
252
      f << "###BM,";
467
252
      ascFile.addPos(pos);
468
252
      ascFile.addNote(f.str().c_str());
469
252
      return false;
470
252
    }
471
252
  }
472
74.8k
  else {
473
74.8k
    f << "type=" << style << ",";
474
    // SvxBulletItem::CreateFont
475
74.8k
    f << "font=[";
476
74.8k
    level.m_font.reset(new STOFFFont);
477
74.8k
    auto &font=*level.m_font;
478
479
74.8k
    STOFFColor col;
480
74.8k
    if (!input->readColor(col)) {
481
3.32k
      STOFF_DEBUG_MSG(("StarObjectNumericRuler::readAttributeLevel: can not read a color\n"));
482
3.32k
      f << "###color,";
483
3.32k
      ascFile.addPos(pos);
484
3.32k
      ascFile.addNote(f.str().c_str());
485
3.32k
      return false;
486
3.32k
    }
487
71.5k
    else {
488
71.5k
      font.m_propertyList.insert("fo:color", col.str().c_str());
489
71.5k
      if (!col.isBlack())
490
17.0k
        f << "color=" << col << ",";
491
71.5k
    }
492
71.5k
    uint16_t family, pitch, align, weight, underline, strikeOut, italic;
493
71.5k
    *input >> family >> charSet >> pitch >> align >> weight >> underline >> strikeOut >> italic;
494
71.5k
    alignement=int(align);
495
71.5k
    if (family) f << "family=" << family << ",";
496
71.5k
    if (charSet) f << "charSet=" << charSet << ",";
497
71.5k
    if (pitch) f << "pitch=" << pitch << ",";
498
71.5k
    if (weight) f << "weight=" << weight << ",";
499
71.5k
    if (underline) f << "underline=" << underline << ",";
500
71.5k
    if (strikeOut) f << "strikeOut=" << strikeOut << ",";
501
71.5k
    if (italic) f << "italic=" << italic << ",";
502
71.5k
    std::vector<uint32_t> text;
503
71.5k
    if (!zone.readString(text)) {
504
6.60k
      STOFF_DEBUG_MSG(("StarObjectNumericRuler::readAttributeLevel: can not read a name\n"));
505
6.60k
      f << "###fontName,";
506
6.60k
      ascFile.addPos(pos);
507
6.60k
      ascFile.addNote(f.str().c_str());
508
6.60k
      return false;
509
6.60k
    }
510
64.9k
    if (!text.empty()) {
511
51.4k
      auto name=libstoff::getString(text);
512
51.4k
      font.m_propertyList.insert("style:font-name", name);
513
51.4k
      f << name.cstr() << ",";
514
51.4k
      if (name=="StarBats" || name=="StarMath") {
515
7.64k
        font.m_propertyList.insert("style:font-charset","x-symbol");
516
7.64k
        isSymbolFont=true;
517
7.64k
      }
518
51.4k
    }
519
64.9k
    if (vers==1) f << "size=" << input->readLong(4) << "x" << input->readLong(4) << ",";
520
64.9k
    bool outline, shadow, transparent;
521
64.9k
    *input >> outline >>  shadow >>  transparent;
522
64.9k
    if (outline) f << "outline,";
523
64.9k
    if (shadow) f << "shadow,";
524
64.9k
    if (transparent) f << "transparent,";
525
64.9k
    f << "],";
526
    //
527
    // time to update the font
528
    //
529
64.9k
    font.m_propertyList.insert("style:font-pitch", pitch==1 ? "fixed" : "variable");
530
64.9k
    if (weight==5)
531
8.49k
      font.m_propertyList.insert("fo:font-weight", "normal");
532
56.4k
    else if (weight==8)
533
2.65k
      font.m_propertyList.insert("fo:font-weight", "bold");
534
53.7k
    else if (weight>=1 && weight<=9)
535
1.77k
      font.m_propertyList.insert("fo:font-weight", weight*100, librevenge::RVNG_GENERIC);
536
52.0k
    else // 10: WEIGHT_BLACK
537
52.0k
      font.m_propertyList.insert("fo:font-weight", "normal");
538
64.9k
    switch (underline) {
539
21.0k
    case 0: // none
540
21.3k
    case 4: // unknown
541
21.3k
      font.m_propertyList.insert("style:text-underline-type", "none");
542
21.3k
      break;
543
6.30k
    case 1: // single
544
7.39k
    case 2: // double
545
7.39k
      font.m_propertyList.insert("style:text-underline-type", underline==1 ? "single" : "double");
546
7.39k
      font.m_propertyList.insert("style:text-underline-style", "solid");
547
7.39k
      break;
548
497
    case 3: // dot
549
1.22k
    case 5: // dash
550
1.58k
    case 6: // long-dash
551
1.80k
    case 7: // dash-dot
552
2.30k
    case 8: // dash-dot-dot
553
2.30k
      font.m_propertyList.insert("style:text-underline-type", "single");
554
2.30k
      font.m_propertyList.insert("style:text-underline-style", underline==3 ? "dotted" : underline==5 ? "dash" :
555
1.80k
                                 underline==6 ? "long-dash" : underline==7 ? "dot-dash" : "dot-dot-dash");
556
2.30k
      break;
557
248
    case 9: // small wave
558
767
    case 10: // wave
559
1.11k
    case 11: // double wave
560
1.11k
      font.m_propertyList.insert("style:text-underline-type", underline==11 ? "single" : "double");
561
1.11k
      font.m_propertyList.insert("style:text-underline-style", "wave");
562
1.11k
      if (underline==9)
563
248
        font.m_propertyList.insert("style:text-underline-width", "thin");
564
1.11k
      break;
565
597
    case 12: // bold
566
1.99k
    case 13: // bold dot
567
2.61k
    case 14: // bold dash
568
6.03k
    case 15: // bold long-dash
569
6.36k
    case 16: // bold dash-dot
570
6.63k
    case 17: // bold dash-dot-dot
571
7.03k
    case 18: { // bold wave
572
7.03k
      char const *wh[]= {"solid", "dotted", "dash", "long-dash", "dot-dash", "dot-dot-dash", "wave"};
573
7.03k
      font.m_propertyList.insert("style:text-underline-type", "single");
574
7.03k
      font.m_propertyList.insert("style:text-underline-style", wh[underline-12]);
575
7.03k
      font.m_propertyList.insert("style:text-underline-width", "thick");
576
7.03k
      break;
577
6.63k
    }
578
25.7k
    default:
579
25.7k
      font.m_propertyList.insert("style:text-underline-type", "none");
580
25.7k
      STOFF_DEBUG_MSG(("StarObjectNumericRuler::readAttributeLevel: find unknown underline enum=%d\n", underline));
581
25.7k
      break;
582
64.9k
    }
583
64.9k
    switch (strikeOut) {
584
25.2k
    case 0: // none
585
25.2k
      font.m_propertyList.insert("style:text-line-through-type", "none");
586
25.2k
      break;
587
439
    case 1: // single
588
1.73k
    case 2: // double
589
1.73k
      font.m_propertyList.insert("style:text-line-through-type", strikeOut==1 ? "single" : "double");
590
1.73k
      font.m_propertyList.insert("style:text-line-through-style", "solid");
591
1.73k
      break;
592
445
    case 3: // dontknow
593
445
      break;
594
3.03k
    case 4: // bold
595
3.03k
      font.m_propertyList.insert("style:text-line-through-type", "single");
596
3.03k
      font.m_propertyList.insert("style:text-line-through-style", "solid");
597
3.03k
      font.m_propertyList.insert("style:text-line-through-width", "thick");
598
3.03k
      break;
599
2.28k
    case 5: // slash
600
2.82k
    case 6: // X
601
2.82k
      font.m_propertyList.insert("style:text-line-through-type", "single");
602
2.82k
      font.m_propertyList.insert("style:text-line-through-style", "solid");
603
2.82k
      font.m_propertyList.insert("style:text-line-through-text", strikeOut==5 ? "/" : "X");
604
2.82k
      break;
605
31.5k
    default:
606
31.5k
      font.m_propertyList.insert("style:text-line-through-type", "none");
607
31.5k
      STOFF_DEBUG_MSG(("StarObjectNumericRuler::readAttributeLevel: find unknown crossedout enum=%d\n", strikeOut));
608
31.5k
      break;
609
64.9k
    }
610
64.9k
    if (italic==1)
611
602
      font.m_propertyList.insert("fo:font-style", "oblique");
612
64.3k
    else if (italic==2)
613
548
      font.m_propertyList.insert("fo:font-style", "italic");
614
63.7k
    else if (italic) {
615
23.0k
      STOFF_DEBUG_MSG(("StarObjectNumericRuler::readAttributeLevel: find unknown posture enum=%d\n", italic));
616
23.0k
    }
617
64.9k
    font.m_propertyList.insert("style:text-outline", outline);
618
64.9k
    font.m_propertyList.insert("fo:text-shadow", shadow ? "1pt 1pt" : "none");
619
64.9k
  }
620
64.9k
  auto width=int(input->readLong(4));
621
64.9k
  auto start=int(input->readULong(2));
622
64.9k
  auto justify=int(input->readULong(1));
623
64.9k
  auto symbol=int(input->readULong(1));
624
64.9k
  auto scale=int(input->readULong(2));
625
64.9k
  if (width) f << "width=" << width << ",";
626
64.9k
  if (start) f << "start=" << start << ",";
627
64.9k
  if (justify) f << "justify=" << justify << ",";
628
64.9k
  if (symbol) f << "symbol=" << symbol << ",";
629
64.9k
  if (scale) f << "scale=" << scale << ",";
630
631
64.9k
  if (style<=4) {
632
5.86k
    char const *wh[]= {"A", "a", "I", "i", "1"};
633
5.86k
    level.m_propertyList.insert("style:num-format", wh[style]);
634
5.86k
    level.m_type=STOFFListLevel::NUMBER;
635
5.86k
  }
636
59.0k
  else if (style==5 || (style==6 && symbol==0)) {
637
8.45k
    level.m_propertyList.insert("text:bullet-char", " ");
638
8.45k
    level.m_type=STOFFListLevel::NONE;
639
8.45k
  }
640
50.5k
  else if (style==6) {
641
14.5k
    level.m_type=STOFFListLevel::BULLET;
642
14.5k
    std::vector<uint8_t> buffer(1, uint8_t(symbol));
643
14.5k
    std::vector<uint32_t> res;
644
14.5k
    std::vector<size_t> positions;
645
14.5k
    auto encoding=(charSet==0 && isSymbolFont) ? StarEncoding::E_SYMBOL : StarEncoding::getEncodingForId(charSet);
646
14.5k
    StarEncoding::convert(buffer, encoding, res, positions);
647
14.5k
    level.m_propertyList.insert("text:bullet-char", libstoff::getString(res));
648
14.5k
  }
649
36.0k
  else {
650
36.0k
    STOFF_DEBUG_MSG(("StarObjectNumericRuler::readAttributeLevel: unimplemented style %d\n", style));
651
    // BITMAP
652
36.0k
    level.m_type=STOFFListLevel::BULLET;
653
36.0k
    librevenge::RVNGString bullet;
654
36.0k
    libstoff::appendUnicode(0x2022, bullet); // checkme
655
36.0k
    level.m_propertyList.insert("text:bullet-char", bullet);
656
36.0k
  }
657
64.9k
  if (alignement>=0 && alignement<6) {
658
40.9k
    char const *wh[]= {"left", "right", "justify", "center", "justify"/*block line*/, "end"};
659
40.9k
    level.m_propertyList.insert("fo:text-align", wh[alignement]);
660
40.9k
  }
661
24.0k
  else if (alignement>=0) {
662
24.0k
    STOFF_DEBUG_MSG(("StarObjectNumericRuler::readAttributeLevel: unknown align %d\n", alignement));
663
24.0k
  }
664
665
159k
  for (int i=0; i<2; ++i) {
666
117k
    std::vector<uint32_t> text;
667
117k
    if (!zone.readString(text)) {
668
22.4k
      STOFF_DEBUG_MSG(("StarObjectNumericRuler::readAttributeLevel: can not read a name\n"));
669
22.4k
      f << "###text,";
670
22.4k
      break;
671
22.4k
    }
672
94.8k
    else if (text.empty())
673
64.5k
      continue;
674
30.3k
    f << (i==0 ? "prefix" : "suffix") << "=" << libstoff::getString(text).cstr() << ",";
675
30.3k
    if (i==0) level.m_propertyList.insert("style:num-prefix",libstoff::getString(text));
676
9.59k
    else if (i==1) level.m_propertyList.insert("style:num-suffix",libstoff::getString(text));
677
30.3k
  }
678
679
64.9k
  ascFile.addPos(pos);
680
64.9k
  ascFile.addNote(f.str().c_str());
681
64.9k
  return input->tell()<=lastPos;
682
75.0k
}
683
684
// vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: