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
~WPSCellFormat()35 WPSCellFormat::~WPSCellFormat()
36 {
37 }
38
convertDTFormat(std::string const & dtFormat,librevenge::RVNGPropertyListVector & propVect)39 bool WPSCellFormat::convertDTFormat(std::string const &dtFormat, librevenge::RVNGPropertyListVector &propVect)
40 {
41 propVect.clear();
42 size_t len=dtFormat.size();
43 std::string text("");
44 librevenge::RVNGPropertyList list;
45 for (size_t c=0; c < len; ++c)
46 {
47 if (dtFormat[c]!='%' || c+1==len)
48 {
49 text+=dtFormat[c];
50 continue;
51 }
52 char ch=dtFormat[++c];
53 if (ch=='%')
54 {
55 text += '%';
56 continue;
57 }
58 if (!text.empty())
59 {
60 list.clear();
61 list.insert("librevenge:value-type", "text");
62 list.insert("librevenge:text", text.c_str());
63 propVect.append(list);
64 text.clear();
65 }
66 list.clear();
67 switch (ch)
68 {
69 case 'Y':
70 list.insert("number:style", "long");
71 WPS_FALLTHROUGH;
72 case 'y':
73 list.insert("librevenge:value-type", "year");
74 propVect.append(list);
75 break;
76 case 'B':
77 list.insert("number:style", "long");
78 WPS_FALLTHROUGH;
79 case 'b':
80 case 'h':
81 list.insert("librevenge:value-type", "month");
82 list.insert("number:textual", true);
83 propVect.append(list);
84 break;
85 case 'm':
86 list.insert("librevenge:value-type", "month");
87 propVect.append(list);
88 break;
89 case 'e':
90 list.insert("number:style", "long");
91 WPS_FALLTHROUGH;
92 case 'd':
93 list.insert("librevenge:value-type", "day");
94 propVect.append(list);
95 break;
96 case 'A':
97 list.insert("number:style", "long");
98 WPS_FALLTHROUGH;
99 case 'a':
100 list.insert("librevenge:value-type", "day-of-week");
101 propVect.append(list);
102 break;
103
104 case 'H':
105 list.insert("number:style", "long");
106 WPS_FALLTHROUGH;
107 case 'I':
108 list.insert("librevenge:value-type", "hours");
109 propVect.append(list);
110 break;
111 case 'M':
112 list.insert("librevenge:value-type", "minutes");
113 list.insert("number:style", "long");
114 propVect.append(list);
115 break;
116 case 'S':
117 list.insert("librevenge:value-type", "seconds");
118 list.insert("number:style", "long");
119 propVect.append(list);
120 break;
121 case 'p':
122 list.insert("librevenge:value-type", "text");
123 list.insert("librevenge:text", " ");
124 propVect.append(list);
125 list.clear();
126 list.insert("librevenge:value-type", "am-pm");
127 propVect.append(list);
128 break;
129 default:
130 WPS_DEBUG_MSG(("WPSCellFormat::convertDTFormat: find unimplement command %c(ignored)\n", ch));
131 }
132 }
133 if (!text.empty())
134 {
135 list.clear();
136 list.insert("librevenge:value-type", "text");
137 list.insert("librevenge:text", text.c_str());
138 propVect.append(list);
139 }
140 return propVect.count()!=0;
141 }
142
setBorders(int wh,WPSBorder const & border)143 void WPSCellFormat::setBorders(int wh, WPSBorder const &border)
144 {
145 int const allBits = WPSBorder::LeftBit|WPSBorder::RightBit|WPSBorder::TopBit|WPSBorder::BottomBit;
146 if (wh & (~allBits))
147 {
148 WPS_DEBUG_MSG(("WPSCellFormat::setBorders: unknown borders\n"));
149 return;
150 }
151 if (m_bordersList.size() < 4)
152 {
153 WPSBorder emptyBorder;
154 emptyBorder.m_style = WPSBorder::None;
155 m_bordersList.resize(4, emptyBorder);
156 }
157 if (wh & WPSBorder::LeftBit) m_bordersList[WPSBorder::Left] = border;
158 if (wh & WPSBorder::RightBit) m_bordersList[WPSBorder::Right] = border;
159 if (wh & WPSBorder::TopBit) m_bordersList[WPSBorder::Top] = border;
160 if (wh & WPSBorder::BottomBit) m_bordersList[WPSBorder::Bottom] = border;
161 }
162
addTo(librevenge::RVNGPropertyList & propList) const163 void WPSCellFormat::addTo(librevenge::RVNGPropertyList &propList) const
164 {
165
166 switch (m_hAlign)
167 {
168 case HALIGN_LEFT:
169 propList.insert("fo:text-align", "start");
170 propList.insert("style:text-align-source", "fix");
171 break;
172 case HALIGN_CENTER:
173 propList.insert("fo:text-align", "center");
174 propList.insert("style:text-align-source", "fix");
175 break;
176 case HALIGN_RIGHT:
177 propList.insert("fo:text-align", "end");
178 propList.insert("style:text-align-source", "fix");
179 break;
180 case HALIGN_FULL:
181 case HALIGN_DEFAULT:
182 default:
183 break;
184 }
185 switch (vAlignment())
186 {
187 case VALIGN_TOP:
188 propList.insert("style:vertical-align", "top");
189 break;
190 case VALIGN_CENTER:
191 propList.insert("style:vertical-align", "middle");
192 break;
193 case VALIGN_BOTTOM:
194 propList.insert("style:vertical-align", "bottom");
195 break;
196 case VALIGN_DEFAULT:
197 break; // default
198 default:
199 WPS_DEBUG_MSG(("WPSCellFormat::addTo: called with unknown valign=%d\n", vAlignment()));
200 }
201 switch (wrapping())
202 {
203 case WRAP_WRAP:
204 propList.insert("fo:wrap-option", "wrap");
205 break;
206 case WRAP_NO_WRAP:
207 propList.insert("fo:wrap-option", "no-wrap");
208 break;
209 case WRAP_DEFAULT:
210 break;
211 default:
212 WPS_DEBUG_MSG(("WPSCellFormat::addTo: called with unknown wrapping=%d\n", wrapping()));
213 }
214 if (m_rotation)
215 propList.insert("style:rotation-angle",m_rotation);
216
217 for (size_t c = 0; c < m_bordersList.size(); c++)
218 {
219 if (m_bordersList[c].isEmpty()) continue;
220 switch (c)
221 {
222 case WPSBorder::Left:
223 m_bordersList[c].addTo(propList, "left");
224 break;
225 case WPSBorder::Right:
226 m_bordersList[c].addTo(propList, "right");
227 break;
228 case WPSBorder::Top:
229 m_bordersList[c].addTo(propList, "top");
230 break;
231 case WPSBorder::Bottom:
232 m_bordersList[c].addTo(propList, "bottom");
233 break;
234 default:
235 WPS_DEBUG_MSG(("WPSContentListener::openTableCell: can not send %d border\n",int(c)));
236 break;
237 }
238 }
239 if (!backgroundColor().isWhite())
240 propList.insert("fo:background-color", backgroundColor().str().c_str());
241 if (m_protected)
242 propList.insert("style:cell-protect","protected");
243 propList.insert("fo:padding",0,librevenge::RVNG_POINT); // changme
244 }
245
getValueType() const246 std::string WPSCellFormat::getValueType() const
247 {
248 switch (m_format)
249 {
250 case F_NUMBER:
251 switch (m_subFormat)
252 {
253 case 0: // default
254 case 1: // decimal
255 case 5: // thousand
256 case 6: // fixed
257 case 7: // fraction
258 default:
259 return "float";
260 case 2:
261 return "scientific";
262 case 3:
263 return "percentage";
264 case 4:
265 return "currency";
266 }
267 case F_BOOLEAN:
268 return "boolean";
269 case F_DATE:
270 return "date";
271 case F_TIME:
272 return "time";
273 case F_TEXT:
274 case F_UNKNOWN:
275 default:
276 break;
277 }
278 return "float";
279 }
280
getNumberingProperties(librevenge::RVNGPropertyList & propList) const281 bool WPSCellFormat::getNumberingProperties(librevenge::RVNGPropertyList &propList) const
282 {
283 librevenge::RVNGPropertyListVector pVect;
284 switch (m_format)
285 {
286 case F_BOOLEAN:
287 propList.insert("librevenge:value-type", "boolean");
288 break;
289 case F_NUMBER:
290 if (m_digits>-1000)
291 propList.insert("number:decimal-places", m_digits);
292 switch (m_subFormat)
293 {
294 case 5: // thousand
295 propList.insert("number:grouping", true);
296 WPS_FALLTHROUGH;
297 case 0: // default
298 if (m_subFormat==0)
299 propList.remove("number:decimal-places");
300 WPS_FALLTHROUGH;
301 case 1: // decimal
302 propList.insert("librevenge:value-type", "number");
303 break;
304 case 2:
305 propList.insert("librevenge:value-type", "scientific");
306 break;
307 case 3:
308 propList.insert("librevenge:value-type", "percentage");
309 break;
310 case 6: // fixed
311 propList.insert("librevenge:value-type", "number");
312 propList.insert("number:min-integer-digits", m_digits+1);
313 propList.insert("number:decimal-places", 0);
314 break;
315 case 7:
316 propList.insert("librevenge:value-type", "fraction");
317 propList.insert("number:min-integer-digits", 0);
318 propList.insert("number:min-numerator-digits", 1);
319 propList.insert("number:min-denominator-digits", 1);
320 propList.remove("number:decimal-places");
321 break;
322 case 4:
323 {
324 // DOME: implement non us currency
325 propList.clear();
326 propList.insert("librevenge:value-type", "currency");
327 librevenge::RVNGPropertyList list;
328 list.insert("librevenge:value-type", "currency-symbol");
329 list.insert("number:language","en");
330 list.insert("number:country","US");
331 list.insert("librevenge:currency","$");
332 pVect.append(list);
333
334 list.clear();
335 list.insert("librevenge:value-type", "number");
336 if (m_digits>-1000)
337 list.insert("number:decimal-places", m_digits);
338 pVect.append(list);
339 break;
340 }
341 default:
342 return false;
343 }
344 break;
345 case F_DATE:
346 propList.insert("librevenge:value-type", "date");
347 propList.insert("number:automatic-order", "true");
348 if (!convertDTFormat(m_DTFormat.empty() ? "%m/%d/%Y" : m_DTFormat, pVect))
349 return false;
350 break;
351 case F_TIME:
352 propList.insert("librevenge:value-type", "time");
353 propList.insert("number:automatic-order", "true");
354 if (!convertDTFormat(m_DTFormat.empty() ? "%H:%M:%S" : m_DTFormat, pVect))
355 return false;
356 break;
357 case F_TEXT:
358 case F_UNKNOWN:
359 default:
360 return false;
361 }
362 propList.insert("librevenge:format", pVect);
363 return true;
364 }
365
compare(WPSCellFormat const & cell,bool onlyNumbering) const366 int WPSCellFormat::compare(WPSCellFormat const &cell, bool onlyNumbering) const
367 {
368 if (m_format<cell.m_format) return 1;
369 if (m_format>cell.m_format) return -1;
370 if (m_subFormat<cell.m_subFormat) return 1;
371 if (m_subFormat>cell.m_subFormat) return -1;
372 if (m_DTFormat<cell.m_DTFormat) return 1;
373 if (m_DTFormat>cell.m_DTFormat) return -1;
374 if (m_digits<cell.m_digits) return 1;
375 if (m_digits>cell.m_digits) return -1;
376 if (onlyNumbering) return 0;
377 int diff = int(m_hAlign) - int(cell.m_hAlign);
378 if (diff) return diff;
379 diff = int(m_vAlign) - int(cell.m_vAlign);
380 if (diff) return diff;
381 diff = int(m_wrapping) - int(cell.m_wrapping);
382 if (diff) return diff;
383 if (m_rotation<cell.m_rotation) return 1;
384 if (m_rotation>cell.m_rotation) return -1;
385 if (m_backgroundColor<cell.m_backgroundColor) return 1;
386 if (m_backgroundColor>cell.m_backgroundColor) return -1;
387 if (m_protected !=cell.m_protected) return m_protected ? 1 : -1;
388 diff = int(m_bordersList.size()) - int(cell.m_bordersList.size());
389 if (diff) return diff;
390 for (size_t c = 0; c < m_bordersList.size(); c++)
391 {
392 diff = m_bordersList[c].compare(cell.m_bordersList[c]);
393 if (diff) return diff;
394 }
395 return 0;
396 }
397
operator <<(std::ostream & o,WPSCellFormat const & cell)398 std::ostream &operator<<(std::ostream &o, WPSCellFormat const &cell)
399 {
400 o << "font=[" << cell.m_font << "],";
401 switch (cell.m_hAlign)
402 {
403 case WPSCellFormat::HALIGN_LEFT:
404 o << "left,";
405 break;
406 case WPSCellFormat::HALIGN_CENTER:
407 o << "centered,";
408 break;
409 case WPSCellFormat::HALIGN_RIGHT:
410 o << "right,";
411 break;
412 case WPSCellFormat::HALIGN_FULL:
413 o << "full,";
414 break;
415 case WPSCellFormat::HALIGN_DEFAULT:
416 default:
417 break; // default
418 }
419 switch (cell.m_vAlign)
420 {
421 case WPSCellFormat::VALIGN_TOP:
422 o << "yTop,";
423 break;
424 case WPSCellFormat::VALIGN_CENTER:
425 o << "yCenter,";
426 break;
427 case WPSCellFormat::VALIGN_BOTTOM:
428 o << "yBottom,";
429 break;
430 case WPSCellFormat::VALIGN_DEFAULT:
431 default:
432 break; // default
433 }
434 switch (cell.m_wrapping)
435 {
436 case WPSCellFormat::WRAP_WRAP:
437 o << "wrap,";
438 break;
439 case WPSCellFormat::WRAP_NO_WRAP:
440 o << "wrap[no],";
441 break;
442 case WPSCellFormat::WRAP_DEFAULT:
443 default:
444 break;
445 }
446 if (cell.m_rotation)
447 o << "rotation=" << cell.m_rotation << ",";
448 int subForm = cell.m_subFormat;
449 switch (cell.m_format)
450 {
451 case WPSCellFormat::F_BOOLEAN:
452 o << "boolean";
453 break;
454 case WPSCellFormat::F_TEXT:
455 o << "text";
456 if (subForm)
457 {
458 o << "[Fo" << subForm << "]";
459 subForm = 0;
460 }
461 break;
462 case WPSCellFormat::F_NUMBER:
463 o << "number";
464 switch (subForm)
465 {
466 case 1:
467 o << "[decimal]";
468 break;
469 case 2:
470 o << "[exp]";
471 break;
472 case 3:
473 o << "[percent]";
474 break;
475 case 4:
476 o << "[money]";
477 break;
478 case 5:
479 o << "[thousand]";
480 break;
481 case 6:
482 o << "[fixed]";
483 break;
484 case 7:
485 o << "[fraction]";
486 break;
487 default:
488 o << "[Fo" << subForm << "]";
489 break;
490 case 0:
491 break;
492 }
493 subForm=0;
494 break;
495 case WPSCellFormat::F_DATE:
496 o << "date[" << cell.getDTFormat() << "]";
497 break;
498 case WPSCellFormat::F_TIME:
499 o << "time[" << cell.getDTFormat() << "]";
500 break;
501 case WPSCellFormat::F_UNKNOWN:
502 default:
503 break; // default
504 }
505 if (subForm) o << "[format=#" << subForm << "]";
506 o << ",";
507
508 if (cell.m_digits>-1000) o << "digits=" << cell.m_digits << ",";
509 if (cell.m_protected) o << "protected,";
510 if (!cell.m_backgroundColor.isWhite())
511 o << "backColor=" << cell.m_backgroundColor << ",";
512 for (size_t i = 0; i < cell.m_bordersList.size(); i++)
513 {
514 if (cell.m_bordersList[i].m_style == WPSBorder::None)
515 continue;
516 o << "bord";
517 if (i < 6)
518 {
519 char const *wh[] = { "L", "R", "T", "B", "MiddleH", "MiddleV" };
520 o << wh[i];
521 }
522 else o << "[#wh=" << i << "]";
523 o << "=" << cell.m_bordersList[i] << ",";
524 }
525 return o;
526 }
527
528 ////////////////////////////////////////////////////////////
529 ////////////////////////////////////////////////////////////
~WPSCell()530 WPSCell::~WPSCell()
531 {
532 }
533
addTo(librevenge::RVNGPropertyList & propList) const534 void WPSCell::addTo(librevenge::RVNGPropertyList &propList) const
535 {
536 propList.insert("librevenge:column", position()[0]);
537 propList.insert("librevenge:row", position()[1]);
538
539 propList.insert("table:number-columns-spanned", numSpannedCells()[0]);
540 propList.insert("table:number-rows-spanned", numSpannedCells()[1]);
541
542 WPSCellFormat::addTo(propList);
543 }
544
operator <<(std::ostream & o,WPSCell const & cell)545 std::ostream &operator<<(std::ostream &o, WPSCell const &cell)
546 {
547 o << "C" << cell.m_position << ":";
548 if (cell.numSpannedCells()[0] != 1 || cell.numSpannedCells()[1] != 1)
549 o << "span=[" << cell.numSpannedCells()[0] << "," << cell.numSpannedCells()[1] << "],";
550 if (cell.m_box!=WPSBox2f())
551 o << "box=" << cell.m_box << ",";
552 if (cell.m_verticalSet) o << "ySet,";
553 o << static_cast<WPSCellFormat const &>(cell);
554
555 return o;
556 }
557
558 /* vim:set shiftwidth=4 softtabstop=4 noexpandtab: */
559