Coverage Report

Created: 2026-07-20 07:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libwps/src/lib/WPSCell.cpp
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2
/* libwps
3
 * Version: MPL 2.0 / LGPLv2.1+
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 *
9
 * Major Contributor(s):
10
 * Copyright (C) 2009, 2011 Alonso Laurent (alonso@loria.fr)
11
 * Copyright (C) 2006, 2007 Andrew Ziem
12
 * Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba@bluewin.ch)
13
 * Copyright (C) 2004 Marc Maurer (uwog@uwog.net)
14
 * Copyright (C) 2003-2005 William Lachance (william.lachance@sympatico.ca)
15
 *
16
 * For minor contributions see the git repository.
17
 *
18
 * Alternatively, the contents of this file may be used under the terms
19
 * of the GNU Lesser General Public License Version 2.1 or later
20
 * (LGPLv2.1+), in which case the provisions of the LGPLv2.1+ are
21
 * applicable instead of those above.
22
 *
23
 * For further information visit http://libwps.sourceforge.net
24
 */
25
26
#include <stdio.h>
27
#include <time.h>
28
29
#include <sstream>
30
31
#include <librevenge/librevenge.h>
32
33
#include "WPSCell.h"
34
35
WPSCellFormat::~WPSCellFormat()
36
34.9M
{
37
34.9M
}
38
39
bool WPSCellFormat::convertDTFormat(std::string const &dtFormat, librevenge::RVNGPropertyListVector &propVect)
40
20.9k
{
41
20.9k
  propVect.clear();
42
20.9k
  size_t len=dtFormat.size();
43
20.9k
  std::string text("");
44
20.9k
  librevenge::RVNGPropertyList list;
45
122k
  for (size_t c=0; c < len; ++c)
46
101k
  {
47
101k
    if (dtFormat[c]!='%' || c+1==len)
48
46.0k
    {
49
46.0k
      text+=dtFormat[c];
50
46.0k
      continue;
51
46.0k
    }
52
55.1k
    char ch=dtFormat[++c];
53
55.1k
    if (ch=='%')
54
116
    {
55
116
      text += '%';
56
116
      continue;
57
116
    }
58
55.0k
    if (!text.empty())
59
30.5k
    {
60
30.5k
      list.clear();
61
30.5k
      list.insert("librevenge:value-type", "text");
62
30.5k
      list.insert("librevenge:text", text.c_str());
63
30.5k
      propVect.append(list);
64
30.5k
      text.clear();
65
30.5k
    }
66
55.0k
    list.clear();
67
55.0k
    switch (ch)
68
55.0k
    {
69
783
    case 'Y':
70
783
      list.insert("number:style", "long");
71
783
      WPS_FALLTHROUGH;
72
7.04k
    case 'y':
73
7.04k
      list.insert("librevenge:value-type", "year");
74
7.04k
      propVect.append(list);
75
7.04k
      break;
76
2.83k
    case 'B':
77
2.83k
      list.insert("number:style", "long");
78
2.83k
      WPS_FALLTHROUGH;
79
6.15k
    case 'b':
80
6.15k
    case 'h':
81
6.15k
      list.insert("librevenge:value-type", "month");
82
6.15k
      list.insert("number:textual", true);
83
6.15k
      propVect.append(list);
84
6.15k
      break;
85
5.34k
    case 'm':
86
5.34k
      list.insert("librevenge:value-type", "month");
87
5.34k
      propVect.append(list);
88
5.34k
      break;
89
8
    case 'e':
90
8
      list.insert("number:style", "long");
91
8
      WPS_FALLTHROUGH;
92
10.2k
    case 'd':
93
10.2k
      list.insert("librevenge:value-type", "day");
94
10.2k
      propVect.append(list);
95
10.2k
      break;
96
314
    case 'A':
97
314
      list.insert("number:style", "long");
98
314
      WPS_FALLTHROUGH;
99
335
    case 'a':
100
335
      list.insert("librevenge:value-type", "day-of-week");
101
335
      propVect.append(list);
102
335
      break;
103
104
4.57k
    case 'H':
105
4.57k
      list.insert("number:style", "long");
106
4.57k
      WPS_FALLTHROUGH;
107
8.75k
    case 'I':
108
8.75k
      list.insert("librevenge:value-type", "hours");
109
8.75k
      propVect.append(list);
110
8.75k
      break;
111
8.48k
    case 'M':
112
8.48k
      list.insert("librevenge:value-type", "minutes");
113
8.48k
      list.insert("number:style", "long");
114
8.48k
      propVect.append(list);
115
8.48k
      break;
116
4.40k
    case 'S':
117
4.40k
      list.insert("librevenge:value-type", "seconds");
118
4.40k
      list.insert("number:style", "long");
119
4.40k
      propVect.append(list);
120
4.40k
      break;
121
4.18k
    case 'p':
122
4.18k
      list.insert("librevenge:value-type", "text");
123
4.18k
      list.insert("librevenge:text", " ");
124
4.18k
      propVect.append(list);
125
4.18k
      list.clear();
126
4.18k
      list.insert("librevenge:value-type", "am-pm");
127
4.18k
      propVect.append(list);
128
4.18k
      break;
129
148
    default:
130
148
      WPS_DEBUG_MSG(("WPSCellFormat::convertDTFormat: find unimplement command %c(ignored)\n", ch));
131
55.0k
    }
132
55.0k
  }
133
20.9k
  if (!text.empty())
134
1.10k
  {
135
1.10k
    list.clear();
136
1.10k
    list.insert("librevenge:value-type", "text");
137
1.10k
    list.insert("librevenge:text", text.c_str());
138
1.10k
    propVect.append(list);
139
1.10k
  }
140
20.9k
  return propVect.count()!=0;
141
20.9k
}
142
143
void WPSCellFormat::setBorders(int wh, WPSBorder const &border)
144
2.07M
{
145
2.07M
  int const allBits = WPSBorder::LeftBit|WPSBorder::RightBit|WPSBorder::TopBit|WPSBorder::BottomBit;
146
2.07M
  if (wh & (~allBits))
147
0
  {
148
0
    WPS_DEBUG_MSG(("WPSCellFormat::setBorders: unknown borders\n"));
149
0
    return;
150
0
  }
151
2.07M
  if (m_bordersList.size() < 4)
152
852k
  {
153
852k
    WPSBorder emptyBorder;
154
852k
    emptyBorder.m_style = WPSBorder::None;
155
852k
    m_bordersList.resize(4, emptyBorder);
156
852k
  }
157
2.07M
  if (wh & WPSBorder::LeftBit) m_bordersList[WPSBorder::Left] = border;
158
2.07M
  if (wh & WPSBorder::RightBit) m_bordersList[WPSBorder::Right] = border;
159
2.07M
  if (wh & WPSBorder::TopBit) m_bordersList[WPSBorder::Top] = border;
160
2.07M
  if (wh & WPSBorder::BottomBit) m_bordersList[WPSBorder::Bottom] = border;
161
2.07M
}
162
163
void WPSCellFormat::addTo(librevenge::RVNGPropertyList &propList) const
164
9.00M
{
165
166
9.00M
  switch (m_hAlign)
167
9.00M
  {
168
79.6k
  case HALIGN_LEFT:
169
79.6k
    propList.insert("fo:text-align", "start");
170
79.6k
    propList.insert("style:text-align-source", "fix");
171
79.6k
    break;
172
111k
  case HALIGN_CENTER:
173
111k
    propList.insert("fo:text-align", "center");
174
111k
    propList.insert("style:text-align-source", "fix");
175
111k
    break;
176
82.2k
  case HALIGN_RIGHT:
177
82.2k
    propList.insert("fo:text-align", "end");
178
82.2k
    propList.insert("style:text-align-source", "fix");
179
82.2k
    break;
180
14.8k
  case HALIGN_FULL:
181
8.72M
  case HALIGN_DEFAULT:
182
8.72M
  default:
183
8.72M
    break;
184
9.00M
  }
185
9.00M
  switch (vAlignment())
186
9.00M
  {
187
25.3k
  case VALIGN_TOP:
188
25.3k
    propList.insert("style:vertical-align", "top");
189
25.3k
    break;
190
12.0k
  case VALIGN_CENTER:
191
12.0k
    propList.insert("style:vertical-align", "middle");
192
12.0k
    break;
193
233k
  case VALIGN_BOTTOM:
194
233k
    propList.insert("style:vertical-align", "bottom");
195
233k
    break;
196
8.73M
  case VALIGN_DEFAULT:
197
8.73M
    break; // default
198
0
  default:
199
0
    WPS_DEBUG_MSG(("WPSCellFormat::addTo: called with unknown valign=%d\n", vAlignment()));
200
9.00M
  }
201
9.00M
  switch (wrapping())
202
9.00M
  {
203
29.3k
  case WRAP_WRAP:
204
29.3k
    propList.insert("fo:wrap-option", "wrap");
205
29.3k
    break;
206
0
  case WRAP_NO_WRAP:
207
0
    propList.insert("fo:wrap-option", "no-wrap");
208
0
    break;
209
8.97M
  case WRAP_DEFAULT:
210
8.97M
    break;
211
0
  default:
212
0
    WPS_DEBUG_MSG(("WPSCellFormat::addTo: called with unknown wrapping=%d\n", wrapping()));
213
9.00M
  }
214
9.00M
  if (m_rotation)
215
157k
    propList.insert("style:rotation-angle",m_rotation);
216
217
11.0M
  for (size_t c = 0; c < m_bordersList.size(); c++)
218
2.00M
  {
219
2.00M
    if (m_bordersList[c].isEmpty()) continue;
220
961k
    switch (c)
221
961k
    {
222
328k
    case WPSBorder::Left:
223
328k
      m_bordersList[c].addTo(propList, "left");
224
328k
      break;
225
145k
    case WPSBorder::Right:
226
145k
      m_bordersList[c].addTo(propList, "right");
227
145k
      break;
228
367k
    case WPSBorder::Top:
229
367k
      m_bordersList[c].addTo(propList, "top");
230
367k
      break;
231
119k
    case WPSBorder::Bottom:
232
119k
      m_bordersList[c].addTo(propList, "bottom");
233
119k
      break;
234
0
    default:
235
0
      WPS_DEBUG_MSG(("WPSContentListener::openTableCell: can not send %d border\n",int(c)));
236
0
      break;
237
961k
    }
238
961k
  }
239
9.00M
  if (!backgroundColor().isWhite())
240
171k
    propList.insert("fo:background-color", backgroundColor().str().c_str());
241
9.00M
  if (m_protected)
242
102k
    propList.insert("style:cell-protect","protected");
243
9.00M
  propList.insert("fo:padding",0,librevenge::RVNG_POINT); // changme
244
9.00M
}
245
246
std::string WPSCellFormat::getValueType() const
247
5.66M
{
248
5.66M
  switch (m_format)
249
5.66M
  {
250
203k
  case F_NUMBER:
251
203k
    switch (m_subFormat)
252
203k
    {
253
72.1k
    case 0: // default
254
165k
    case 1: // decimal
255
178k
    case 5: // thousand
256
178k
    case 6: // fixed
257
179k
    case 7: // fraction
258
179k
    default:
259
179k
      return "float";
260
7.39k
    case 2:
261
7.39k
      return "scientific";
262
4.25k
    case 3:
263
4.25k
      return "percentage";
264
12.2k
    case 4:
265
12.2k
      return "currency";
266
203k
    }
267
0
  case F_BOOLEAN:
268
0
    return "boolean";
269
0
  case F_DATE:
270
0
    return "date";
271
0
  case F_TIME:
272
0
    return "time";
273
5.18k
  case F_TEXT:
274
5.46M
  case F_UNKNOWN:
275
5.46M
  default:
276
5.46M
    break;
277
5.66M
  }
278
5.46M
  return "float";
279
5.66M
}
280
281
bool WPSCellFormat::getNumberingProperties(librevenge::RVNGPropertyList &propList) const
282
91.3k
{
283
91.3k
  librevenge::RVNGPropertyListVector pVect;
284
91.3k
  switch (m_format)
285
91.3k
  {
286
5.79k
  case F_BOOLEAN:
287
5.79k
    propList.insert("librevenge:value-type", "boolean");
288
5.79k
    break;
289
64.5k
  case F_NUMBER:
290
64.5k
    if (m_digits>-1000)
291
57.0k
      propList.insert("number:decimal-places", m_digits);
292
64.5k
    switch (m_subFormat)
293
64.5k
    {
294
736
    case 5: // thousand
295
736
      propList.insert("number:grouping", true);
296
736
      WPS_FALLTHROUGH;
297
10.2k
    case 0: // default
298
10.2k
      if (m_subFormat==0)
299
9.52k
        propList.remove("number:decimal-places");
300
10.2k
      WPS_FALLTHROUGH;
301
35.9k
    case 1: // decimal
302
35.9k
      propList.insert("librevenge:value-type", "number");
303
35.9k
      break;
304
9.09k
    case 2:
305
9.09k
      propList.insert("librevenge:value-type", "scientific");
306
9.09k
      break;
307
7.44k
    case 3:
308
7.44k
      propList.insert("librevenge:value-type", "percentage");
309
7.44k
      break;
310
2.13k
    case 6: // fixed
311
2.13k
      propList.insert("librevenge:value-type", "number");
312
2.13k
      propList.insert("number:min-integer-digits", m_digits+1);
313
2.13k
      propList.insert("number:decimal-places", 0);
314
2.13k
      break;
315
140
    case 7:
316
140
      propList.insert("librevenge:value-type", "fraction");
317
140
      propList.insert("number:min-integer-digits", 0);
318
140
      propList.insert("number:min-numerator-digits", 1);
319
140
      propList.insert("number:min-denominator-digits", 1);
320
140
      propList.remove("number:decimal-places");
321
140
      break;
322
9.86k
    case 4:
323
9.86k
    {
324
      // DOME: implement non us currency
325
9.86k
      propList.clear();
326
9.86k
      propList.insert("librevenge:value-type", "currency");
327
9.86k
      librevenge::RVNGPropertyList list;
328
9.86k
      list.insert("librevenge:value-type", "currency-symbol");
329
9.86k
      list.insert("number:language","en");
330
9.86k
      list.insert("number:country","US");
331
9.86k
      list.insert("librevenge:currency","$");
332
9.86k
      pVect.append(list);
333
334
9.86k
      list.clear();
335
9.86k
      list.insert("librevenge:value-type", "number");
336
9.86k
      if (m_digits>-1000)
337
9.80k
        list.insert("number:decimal-places", m_digits);
338
9.86k
      pVect.append(list);
339
9.86k
      break;
340
10.2k
    }
341
0
    default:
342
0
      return false;
343
64.5k
    }
344
64.5k
    break;
345
64.5k
  case F_DATE:
346
12.5k
    propList.insert("librevenge:value-type", "date");
347
12.5k
    propList.insert("number:automatic-order", "true");
348
12.5k
    if (!convertDTFormat(m_DTFormat.empty() ? "%m/%d/%Y" : m_DTFormat, pVect))
349
36
      return false;
350
12.4k
    break;
351
12.4k
  case F_TIME:
352
8.49k
    propList.insert("librevenge:value-type", "time");
353
8.49k
    propList.insert("number:automatic-order", "true");
354
8.49k
    if (!convertDTFormat(m_DTFormat.empty() ? "%H:%M:%S" : m_DTFormat, pVect))
355
0
      return false;
356
8.49k
    break;
357
8.49k
  case F_TEXT:
358
0
  case F_UNKNOWN:
359
0
  default:
360
0
    return false;
361
91.3k
  }
362
91.3k
  propList.insert("librevenge:format", pVect);
363
91.3k
  return true;
364
91.3k
}
365
366
int WPSCellFormat::compare(WPSCellFormat const &cell, bool onlyNumbering) const
367
11.2M
{
368
11.2M
  if (m_format<cell.m_format) return 1;
369
10.9M
  if (m_format>cell.m_format) return -1;
370
10.3M
  if (m_subFormat<cell.m_subFormat) return 1;
371
10.0M
  if (m_subFormat>cell.m_subFormat) return -1;
372
8.40M
  if (m_DTFormat<cell.m_DTFormat) return 1;
373
8.30M
  if (m_DTFormat>cell.m_DTFormat) return -1;
374
8.17M
  if (m_digits<cell.m_digits) return 1;
375
7.73M
  if (m_digits>cell.m_digits) return -1;
376
6.02M
  if (onlyNumbering) return 0;
377
356k
  int diff = int(m_hAlign) - int(cell.m_hAlign);
378
356k
  if (diff) return diff;
379
338k
  diff = int(m_vAlign) - int(cell.m_vAlign);
380
338k
  if (diff) return diff;
381
337k
  diff = int(m_wrapping) - int(cell.m_wrapping);
382
337k
  if (diff) return diff;
383
337k
  if (m_rotation<cell.m_rotation) return 1;
384
337k
  if (m_rotation>cell.m_rotation) return -1;
385
337k
  if (m_backgroundColor<cell.m_backgroundColor) return 1;
386
332k
  if (m_backgroundColor>cell.m_backgroundColor) return -1;
387
326k
  if (m_protected !=cell.m_protected) return m_protected ? 1 : -1;
388
326k
  diff = int(m_bordersList.size()) - int(cell.m_bordersList.size());
389
326k
  if (diff) return diff;
390
370k
  for (size_t c = 0; c < m_bordersList.size(); c++)
391
54.0k
  {
392
54.0k
    diff = m_bordersList[c].compare(cell.m_bordersList[c]);
393
54.0k
    if (diff) return diff;
394
54.0k
  }
395
316k
  return 0;
396
325k
}
397
398
std::ostream &operator<<(std::ostream &o, WPSCellFormat const &cell)
399
0
{
400
0
  o << "font=[" << cell.m_font << "],";
401
0
  switch (cell.m_hAlign)
402
0
  {
403
0
  case WPSCellFormat::HALIGN_LEFT:
404
0
    o << "left,";
405
0
    break;
406
0
  case WPSCellFormat::HALIGN_CENTER:
407
0
    o << "centered,";
408
0
    break;
409
0
  case WPSCellFormat::HALIGN_RIGHT:
410
0
    o << "right,";
411
0
    break;
412
0
  case WPSCellFormat::HALIGN_FULL:
413
0
    o << "full,";
414
0
    break;
415
0
  case WPSCellFormat::HALIGN_DEFAULT:
416
0
  default:
417
0
    break; // default
418
0
  }
419
0
  switch (cell.m_vAlign)
420
0
  {
421
0
  case WPSCellFormat::VALIGN_TOP:
422
0
    o << "yTop,";
423
0
    break;
424
0
  case WPSCellFormat::VALIGN_CENTER:
425
0
    o << "yCenter,";
426
0
    break;
427
0
  case WPSCellFormat::VALIGN_BOTTOM:
428
0
    o << "yBottom,";
429
0
    break;
430
0
  case WPSCellFormat::VALIGN_DEFAULT:
431
0
  default:
432
0
    break; // default
433
0
  }
434
0
  switch (cell.m_wrapping)
435
0
  {
436
0
  case WPSCellFormat::WRAP_WRAP:
437
0
    o << "wrap,";
438
0
    break;
439
0
  case WPSCellFormat::WRAP_NO_WRAP:
440
0
    o << "wrap[no],";
441
0
    break;
442
0
  case WPSCellFormat::WRAP_DEFAULT:
443
0
  default:
444
0
    break;
445
0
  }
446
0
  if (cell.m_rotation)
447
0
    o << "rotation=" << cell.m_rotation << ",";
448
0
  int subForm = cell.m_subFormat;
449
0
  switch (cell.m_format)
450
0
  {
451
0
  case WPSCellFormat::F_BOOLEAN:
452
0
    o << "boolean";
453
0
    break;
454
0
  case WPSCellFormat::F_TEXT:
455
0
    o << "text";
456
0
    if (subForm)
457
0
    {
458
0
      o << "[Fo" << subForm << "]";
459
0
      subForm = 0;
460
0
    }
461
0
    break;
462
0
  case WPSCellFormat::F_NUMBER:
463
0
    o << "number";
464
0
    switch (subForm)
465
0
    {
466
0
    case 1:
467
0
      o << "[decimal]";
468
0
      break;
469
0
    case 2:
470
0
      o << "[exp]";
471
0
      break;
472
0
    case 3:
473
0
      o << "[percent]";
474
0
      break;
475
0
    case 4:
476
0
      o << "[money]";
477
0
      break;
478
0
    case 5:
479
0
      o << "[thousand]";
480
0
      break;
481
0
    case 6:
482
0
      o << "[fixed]";
483
0
      break;
484
0
    case 7:
485
0
      o << "[fraction]";
486
0
      break;
487
0
    default:
488
0
      o << "[Fo" << subForm << "]";
489
0
      break;
490
0
    case 0:
491
0
      break;
492
0
    }
493
0
    subForm=0;
494
0
    break;
495
0
  case WPSCellFormat::F_DATE:
496
0
    o << "date[" << cell.getDTFormat() << "]";
497
0
    break;
498
0
  case WPSCellFormat::F_TIME:
499
0
    o << "time[" << cell.getDTFormat() << "]";
500
0
    break;
501
0
  case WPSCellFormat::F_UNKNOWN:
502
0
  default:
503
0
    break; // default
504
0
  }
505
0
  if (subForm) o << "[format=#" << subForm << "]";
506
0
  o << ",";
507
508
0
  if (cell.m_digits>-1000) o << "digits=" << cell.m_digits << ",";
509
0
  if (cell.m_protected) o << "protected,";
510
0
  if (!cell.m_backgroundColor.isWhite())
511
0
    o << "backColor=" << cell.m_backgroundColor << ",";
512
0
  for (size_t i = 0; i < cell.m_bordersList.size(); i++)
513
0
  {
514
0
    if (cell.m_bordersList[i].m_style == WPSBorder::None)
515
0
      continue;
516
0
    o << "bord";
517
0
    if (i < 6)
518
0
    {
519
0
      char const *wh[] = { "L", "R", "T", "B", "MiddleH", "MiddleV" };
520
0
      o << wh[i];
521
0
    }
522
0
    else o << "[#wh=" << i << "]";
523
0
    o << "=" << cell.m_bordersList[i] << ",";
524
0
  }
525
0
  return o;
526
0
}
527
528
////////////////////////////////////////////////////////////
529
////////////////////////////////////////////////////////////
530
WPSCell::~WPSCell()
531
{
532
}
533
534
void WPSCell::addTo(librevenge::RVNGPropertyList &propList) const
535
9.00M
{
536
9.00M
  propList.insert("librevenge:column", position()[0]);
537
9.00M
  propList.insert("librevenge:row", position()[1]);
538
539
9.00M
  propList.insert("table:number-columns-spanned", numSpannedCells()[0]);
540
9.00M
  propList.insert("table:number-rows-spanned", numSpannedCells()[1]);
541
542
9.00M
  WPSCellFormat::addTo(propList);
543
9.00M
}
544
545
std::ostream &operator<<(std::ostream &o, WPSCell const &cell)
546
0
{
547
0
  o << "C" << cell.m_position << ":";
548
0
  if (cell.numSpannedCells()[0] != 1 || cell.numSpannedCells()[1] != 1)
549
0
    o << "span=[" << cell.numSpannedCells()[0] << "," << cell.numSpannedCells()[1] << "],";
550
0
  if (cell.m_box!=WPSBox2f())
551
0
    o << "box=" << cell.m_box << ",";
552
0
  if (cell.m_verticalSet) o << "ySet,";
553
0
  o << static_cast<WPSCellFormat const &>(cell);
554
555
0
  return o;
556
0
}
557
558
/* vim:set shiftwidth=4 softtabstop=4 noexpandtab: */