1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2 /* libodfgen
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) 2002-2004 William Lachance (wrlach@gmail.com)
11 * Copyright (C) 2004 Fridrich Strba (fridrich.strba@bluewin.ch)
12 *
13 * For minor contributions see the git repository.
14 *
15 * Alternatively, the contents of this file may be used under the terms
16 * of the GNU Lesser General Public License Version 2.1 or later
17 * (LGPLv2.1+), in which case the provisions of the LGPLv2.1+ are
18 * applicable instead of those above.
19 *
20 * For further information visit http://libwpd.sourceforge.net
21 */
22
23 #include "SheetStyle.hxx"
24
25 #include <math.h>
26 #ifdef _MSC_VER
27 # include <minmax.h>
28 #endif
29 #include <string.h>
30
31 #include <sstream>
32 #include <string>
33
34 #include "DocumentElement.hxx"
35 #include "FilterInternal.hxx"
36 #include "NumberingStyle.hxx"
37 #include "TextRunStyle.hxx"
38
39 namespace libodfgen
40 {
getColumnName(int col)41 static std::string getColumnName(int col)
42 {
43 // note: we can also limit the maximal number of column. However,
44 // in this case, the current code must generate a valid string ;
45 // of course, the resulting formula will be invalid when col is
46 // too big (which seems ok and the best that we can do)
47 if (col<0)
48 {
49 ODFGEN_DEBUG_MSG(("libodfgen::getColumnName[SheetStyle.cxx]: called with invalid column %d\n", col));
50 return "ZZZZ"; // we must return something, ZZZZ must make the formula invalid...
51 }
52 std::string name(1, char(col%26+'A'));
53 col /= 26;
54 while (col>0)
55 {
56 --col;
57 name.insert(0, std::string(1,char(col%26+'A')));
58 col /= 26;
59 }
60 return name;
61 }
62 }
SheetCellStyle(const librevenge::RVNGPropertyList & xPropList,const char * psName)63 SheetCellStyle::SheetCellStyle(const librevenge::RVNGPropertyList &xPropList, const char *psName) :
64 Style(psName),
65 mPropList(xPropList)
66 {
67 }
68
writeStyle(OdfDocumentHandler * pHandler,SheetManager const & manager) const69 void SheetCellStyle::writeStyle(OdfDocumentHandler *pHandler, SheetManager const &manager) const
70 {
71 TagOpenElement styleOpen("style:style");
72 styleOpen.addAttribute("style:name", getName());
73 if (mPropList["style:parent-style-name"])
74 styleOpen.addAttribute("style:parent-style-name", mPropList["style:parent-style-name"]->getStr());
75 styleOpen.addAttribute("style:family", "table-cell");
76 if (mPropList["librevenge:numbering-name"])
77 {
78 librevenge::RVNGString numberingName=
79 manager.getNumberingManager().getStyleName(mPropList["librevenge:numbering-name"]->getStr());
80 if (numberingName.empty())
81 {
82 ODFGEN_DEBUG_MSG(("SheetCellStyle::writeStyle can not find numbering style %s\n", mPropList["librevenge:numbering-name"]->getStr().cstr()));
83 }
84 else
85 styleOpen.addAttribute("style:data-style-name", numberingName.cstr());
86 }
87 styleOpen.write(pHandler);
88
89 librevenge::RVNGPropertyList textProp;
90 SpanStyleManager::addSpanProperties(mPropList, textProp);
91 if (!textProp.empty())
92 {
93 pHandler->startElement("style:text-properties", textProp);
94 pHandler->endElement("style:text-properties");
95 }
96 // WLACH_REFACTORING: Only temporary.. a much better solution is to
97 // generalize this sort of thing into the "Style" superclass
98 librevenge::RVNGPropertyList stylePropList;
99 librevenge::RVNGPropertyList paragPropList;
100 librevenge::RVNGPropertyList::Iter i(mPropList);
101 bool paddingSet=false;
102 for (i.rewind(); i.next();)
103 {
104 auto len = (int) strlen(i.key());
105 if (i.child())
106 continue;
107 if (len > 3 && strncmp(i.key(), "fo:", 3)==0)
108 {
109 if (len==13 && !strcmp(i.key(), "fo:text-align"))
110 {
111 paragPropList.insert("fo:text-align", mPropList["fo:text-align"]->clone());
112 if (!mPropList["fo:margin-left"])
113 paragPropList.insert("fo:margin-left", "0cm");
114 }
115 else if (len==14 && !strcmp(i.key(), "fo:margin-left"))
116 paragPropList.insert("fo:margin-left", mPropList["fo:margin-left"]->clone());
117 else
118 {
119 if (len>=9 && strncmp(i.key(), "fo:padding", 9)==0)
120 paddingSet=true;
121 stylePropList.insert(i.key(), i()->clone());
122 }
123 }
124 else if (len>6 && strncmp(i.key(), "style:", 6)==0)
125 {
126 if (len > 22 && !strncmp(i.key(), "style:border-line-width", 23))
127 {
128 if (!strcmp(i.key(), "style:border-line-width") ||
129 !strcmp(i.key(), "style:border-line-width-left") ||
130 !strcmp(i.key(), "style:border-line-width-right") ||
131 !strcmp(i.key(), "style:border-line-width-top")||
132 !strcmp(i.key(), "style:border-line-width-bottom"))
133 stylePropList.insert(i.key(), i()->clone());
134 }
135 else if (len == 23 && !strcmp(i.key(), "style:text-align-source"))
136 stylePropList.insert(i.key(), i()->clone());
137 else if (len == 18 && !strcmp(i.key(), "style:cell-protect"))
138 stylePropList.insert(i.key(), i()->clone());
139 else if (len == 15 && !strcmp(i.key(), "style:direction"))
140 stylePropList.insert(i.key(), i()->clone());
141 else if (len == 18 && !strcmp(i.key(), "style:print-content"))
142 stylePropList.insert(i.key(), i()->clone());
143 else if (len == 20 && !strcmp(i.key(), "style:repeat-content"))
144 stylePropList.insert(i.key(), i()->clone());
145 else if (len == 20 && !strcmp(i.key(), "style:rotation-align"))
146 stylePropList.insert(i.key(), i()->clone());
147 else if (len == 20 && !strcmp(i.key(), "style:rotation-angle"))
148 stylePropList.insert(i.key(), i()->clone());
149 else if (len == 12 && !strcmp(i.key(), "style:shadow"))
150 stylePropList.insert(i.key(), i()->clone());
151 else if (len == 20 && !strcmp(i.key(), "style:vertical-align"))
152 stylePropList.insert(i.key(), i()->clone());
153 else if (len == 18 && !strcmp(i.key(), "style:writing-mode"))
154 stylePropList.insert(i.key(), i()->clone());
155 }
156 }
157 if (!paddingSet)
158 stylePropList.insert("fo:padding", "0.0382in");
159 pHandler->startElement("style:table-cell-properties", stylePropList);
160 pHandler->endElement("style:table-cell-properties");
161 if (!paragPropList.empty())
162 {
163 pHandler->startElement("style:paragraph-properties", paragPropList);
164 pHandler->endElement("style:paragraph-properties");
165 }
166 pHandler->endElement("style:style");
167 }
168
SheetRowStyle(const librevenge::RVNGPropertyList & propList,const char * psName)169 SheetRowStyle::SheetRowStyle(const librevenge::RVNGPropertyList &propList, const char *psName) :
170 Style(psName),
171 mPropList(propList)
172 {
173 }
174
writeStyle(OdfDocumentHandler * pHandler,SheetManager const &) const175 void SheetRowStyle::writeStyle(OdfDocumentHandler *pHandler, SheetManager const &) const
176 {
177 TagOpenElement styleOpen("style:style");
178 styleOpen.addAttribute("style:name", getName());
179 styleOpen.addAttribute("style:family", "table-row");
180 styleOpen.write(pHandler);
181
182 TagOpenElement stylePropertiesOpen("style:table-row-properties");
183 if (mPropList["style:row-height"])
184 stylePropertiesOpen.addAttribute("style:row-height", mPropList["style:row-height"]->getStr());
185 else if (mPropList["style:min-row-height"]) // min-row does not seem to work
186 stylePropertiesOpen.addAttribute("style:row-height", mPropList["style:min-row-height"]->getStr());
187 if (mPropList["style:use-optimal-row-height"])
188 stylePropertiesOpen.addAttribute("style:use-optimal-row-height", mPropList["style:use-optimal-row-height"]->getStr());
189 stylePropertiesOpen.addAttribute("fo:keep-together", "auto");
190 stylePropertiesOpen.write(pHandler);
191 pHandler->endElement("style:table-row-properties");
192
193 pHandler->endElement("style:style");
194 }
195
196
SheetStyle(const librevenge::RVNGPropertyList & xPropList,const char * psName,Style::Zone zone)197 SheetStyle::SheetStyle(const librevenge::RVNGPropertyList &xPropList, const char *psName, Style::Zone zone) :
198 Style(psName, zone), mPropList(xPropList), mColumns(nullptr),
199 mRowNameHash(), mRowStyleHash(), mCellNameHash(), mCellStyleHash()
200 {
201 mColumns = mPropList.child("librevenge:columns");
202 }
203
~SheetStyle()204 SheetStyle::~SheetStyle()
205 {
206 }
207
addColumnDefinitions(libodfgen::DocumentElementVector & storage) const208 void SheetStyle::addColumnDefinitions(libodfgen::DocumentElementVector &storage) const
209 {
210 if (!mColumns) return;
211 int col=1;
212 librevenge::RVNGPropertyListVector::Iter j(*mColumns);
213 for (j.rewind(); j.next(); ++col)
214 {
215 auto pTableColumnOpenElement = std::make_shared<TagOpenElement>("table:table-column");
216 librevenge::RVNGString sColumnStyleName;
217 sColumnStyleName.sprintf("%s_col%i", getName().cstr(), col);
218 pTableColumnOpenElement->addAttribute("table:style-name", sColumnStyleName);
219 if (j()["table:number-columns-repeated"] && j()["table:number-columns-repeated"]->getInt()>1)
220 pTableColumnOpenElement->addAttribute("table:number-columns-repeated",
221 j()["table:number-columns-repeated"]->getStr());
222
223 storage.push_back(pTableColumnOpenElement);
224
225 storage.push_back(std::make_shared<TagCloseElement>("table:table-column"));
226 }
227 }
228
writeStyle(OdfDocumentHandler * pHandler,SheetManager const & manager) const229 void SheetStyle::writeStyle(OdfDocumentHandler *pHandler, SheetManager const &manager) const
230 {
231 TagOpenElement styleOpen("style:style");
232 styleOpen.addAttribute("style:name", getName());
233 styleOpen.addAttribute("style:family", "table");
234 if (mPropList["style:master-page-name"])
235 styleOpen.addAttribute("style:master-page-name", mPropList["style:master-page-name"]->getStr());
236 styleOpen.write(pHandler);
237
238 TagOpenElement stylePropertiesOpen("style:table-properties");
239 stylePropertiesOpen.addAttribute("table:display", "true");
240 if (mPropList["table:align"])
241 stylePropertiesOpen.addAttribute("table:align", mPropList["table:align"]->getStr());
242 if (mPropList["fo:margin-left"])
243 stylePropertiesOpen.addAttribute("fo:margin-left", mPropList["fo:margin-left"]->getStr());
244 if (mPropList["fo:margin-right"])
245 stylePropertiesOpen.addAttribute("fo:margin-right", mPropList["fo:margin-right"]->getStr());
246 if (mPropList["style:width"])
247 stylePropertiesOpen.addAttribute("style:width", mPropList["style:width"]->getStr());
248 if (mPropList["fo:break-before"])
249 stylePropertiesOpen.addAttribute("fo:break-before", mPropList["fo:break-before"]->getStr());
250 if (mPropList["table:border-model"])
251 stylePropertiesOpen.addAttribute("table:border-model", mPropList["table:border-model"]->getStr());
252 stylePropertiesOpen.write(pHandler);
253
254 pHandler->endElement("style:table-properties");
255
256 pHandler->endElement("style:style");
257
258 if (mColumns)
259 {
260 librevenge::RVNGPropertyListVector::Iter j(*mColumns);
261 int col=1;
262 for (j.rewind(); j.next(); ++col)
263 {
264 TagOpenElement columnStyleOpen("style:style");
265 librevenge::RVNGString sColumnName;
266 sColumnName.sprintf("%s_col%i", getName().cstr(), col);
267 columnStyleOpen.addAttribute("style:name", sColumnName);
268 columnStyleOpen.addAttribute("style:family", "table-column");
269 columnStyleOpen.write(pHandler);
270
271 librevenge::RVNGPropertyList columnProperties(j());
272 if (columnProperties["table:number-columns-repeated"])
273 columnProperties.remove("table:number-columns-repeated");
274 pHandler->startElement("style:table-column-properties", columnProperties);
275 pHandler->endElement("style:table-column-properties");
276
277 pHandler->endElement("style:style");
278 }
279 }
280
281 std::map<librevenge::RVNGString, std::shared_ptr<SheetRowStyle> >::const_iterator rIt;
282 for (rIt=mRowStyleHash.begin(); rIt!=mRowStyleHash.end(); ++rIt)
283 {
284 if (!rIt->second) continue;
285 rIt->second->writeStyle(pHandler, manager);
286 }
287
288 std::map<librevenge::RVNGString, std::shared_ptr<SheetCellStyle> >::const_iterator cIt;
289 for (cIt=mCellStyleHash.begin(); cIt!=mCellStyleHash.end(); ++cIt)
290 {
291 if (!cIt->second) continue;
292 cIt->second->writeStyle(pHandler, manager);
293 }
294 }
295
addRow(const librevenge::RVNGPropertyList & propList)296 librevenge::RVNGString SheetStyle::addRow(const librevenge::RVNGPropertyList &propList)
297 {
298 // first remove unused data
299 librevenge::RVNGPropertyList pList;
300 librevenge::RVNGPropertyList::Iter i(propList);
301 for (i.rewind(); i.next();)
302 {
303 if (strncmp(i.key(), "librevenge:", 11)==0 ||
304 strcmp(i.key(), "table:number-rows-repeated")==0 || i.child())
305 continue;
306 pList.insert(i.key(),i()->clone());
307 }
308 librevenge::RVNGString hashKey = pList.getPropString();
309 std::map<librevenge::RVNGString, librevenge::RVNGString>::const_iterator iter =
310 mRowNameHash.find(hashKey);
311 if (iter!=mRowNameHash.end()) return iter->second;
312
313 librevenge::RVNGString name;
314 name.sprintf("%s_row%i", getName().cstr(), (int) mRowStyleHash.size());
315 mRowNameHash[hashKey]=name;
316 mRowStyleHash[name]=std::shared_ptr<SheetRowStyle>(new SheetRowStyle(propList, name.cstr()));
317 return name;
318 }
319
addCell(const librevenge::RVNGPropertyList & propList)320 librevenge::RVNGString SheetStyle::addCell(const librevenge::RVNGPropertyList &propList)
321 {
322 // first remove unused data
323 librevenge::RVNGPropertyList pList;
324 librevenge::RVNGPropertyList::Iter i(propList);
325 for (i.rewind(); i.next();)
326 {
327 if (strncmp(i.key(), "librevenge:", 11)==0 &&
328 strncmp(i.key(), "librevenge:numbering-name", 24)!=0)
329 continue;
330 if (strncmp(i.key(), "table:number-", 13)==0 &&
331 (strcmp(i.key(), "table:number-columns-repeated")==0 ||
332 strcmp(i.key(), "table:number-columns-spanned")==0 ||
333 strcmp(i.key(), "table:number-rows-spanned")==0 ||
334 strcmp(i.key(), "table:number-matrix-columns-spanned")==0 ||
335 strcmp(i.key(), "table:number-matrix-rows-spanned")==0))
336 continue;
337 if (i.child())
338 continue;
339
340 pList.insert(i.key(),i()->clone());
341 }
342 librevenge::RVNGString hashKey = pList.getPropString();
343 std::map<librevenge::RVNGString, librevenge::RVNGString>::const_iterator iter =
344 mCellNameHash.find(hashKey);
345 if (iter!=mCellNameHash.end()) return iter->second;
346
347 librevenge::RVNGString name;
348 name.sprintf("%s_cell%i", getName().cstr(), (int) mCellStyleHash.size());
349 mCellNameHash[hashKey]=name;
350 mCellStyleHash[name]=std::shared_ptr<SheetCellStyle>(new SheetCellStyle(propList, name.cstr()));
351 return name;
352 }
353
SheetManager(NumberingManager & numberingManager)354 SheetManager::SheetManager(NumberingManager &numberingManager) :
355 mpNumberingManager(numberingManager), mbSheetOpened(false), mSheetStyles()
356 {
357 }
358
~SheetManager()359 SheetManager::~SheetManager()
360 {
361 }
362
clean()363 void SheetManager::clean()
364 {
365 mSheetStyles.clear();
366 }
367
openSheet(const librevenge::RVNGPropertyList & xPropList,Style::Zone zone)368 bool SheetManager::openSheet(const librevenge::RVNGPropertyList &xPropList, Style::Zone zone)
369 {
370 if (mbSheetOpened)
371 {
372 ODFGEN_DEBUG_MSG(("SheetManager::oops: a sheet is already open\n"));
373 return false;
374 }
375 mbSheetOpened=true;
376 if (zone==Style::Z_Unknown)
377 zone=Style::Z_ContentAutomatic;
378
379 librevenge::RVNGString sTableName;
380 if (zone==Style::Z_StyleAutomatic)
381 sTableName.sprintf("Sheet_M%i", (int) mSheetStyles.size());
382 else
383 sTableName.sprintf("Sheet%i", (int) mSheetStyles.size());
384 std::shared_ptr<SheetStyle> sheet(new SheetStyle(xPropList, sTableName.cstr(), zone));
385 mSheetStyles.push_back(sheet);
386 return true;
387 }
388
closeSheet()389 bool SheetManager::closeSheet()
390 {
391 if (!mbSheetOpened)
392 {
393 ODFGEN_DEBUG_MSG(("SheetManager::oops: no sheet are opened\n"));
394 return false;
395 }
396 mbSheetOpened=false;
397 return true;
398 }
399
convertFormula(const librevenge::RVNGPropertyListVector & formula)400 librevenge::RVNGString SheetManager::convertFormula(const librevenge::RVNGPropertyListVector &formula)
401 {
402 char const *operators[] =
403 {
404 "(", ")", "+", "-", "*", "/", "=", "<>", ";", "<", ">", "<=", ">=", "^", "&", "!", "~", ":", "%", "{", "}", "|"
405 };
406 librevenge::RVNGString res("");
407 std::stringstream s;
408 s << "of:=";
409 for (unsigned long i=0; i<formula.count(); ++i)
410 {
411 librevenge::RVNGPropertyList const &list=formula[i];
412 if (!list["librevenge:type"])
413 {
414 ODFGEN_DEBUG_MSG(("SheetManager::convertFormula can not find %s formula type !!!\n", s.str().c_str()));
415 return res;
416 }
417 std::string type(list["librevenge:type"]->getStr().cstr());
418 if (type=="librevenge-operator")
419 {
420 if (!list["librevenge:operator"])
421 {
422 ODFGEN_DEBUG_MSG(("SheetManager::convertFormula can not find operator for formula[%s]!!!\n", s.str().c_str()));
423 return res;
424 }
425 std::string oper(list["librevenge:operator"]->getStr().cstr());
426 bool find=false;
427 for (auto &w : operators)
428 {
429 if (oper!=w) continue;
430 s << oper;
431 find=true;
432 break;
433 }
434 if (!find)
435 {
436 ODFGEN_DEBUG_MSG(("SheetManager::convertFormula find unknown operator for formula[%s]!!!\n", s.str().c_str()));
437 return res;
438 }
439 }
440 else if (type=="librevenge-function")
441 {
442 if (!list["librevenge:function"])
443 {
444 ODFGEN_DEBUG_MSG(("SheetManager::convertFormula can not find value for formula[%s]!!!\n", s.str().c_str()));
445 return res;
446 }
447 s << list["librevenge:function"]->getStr().cstr();
448 }
449 else if (type=="librevenge-number")
450 {
451 if (!list["librevenge:number"])
452 {
453 ODFGEN_DEBUG_MSG(("SheetManager::convertFormula can not find value for formula[%s]!!!\n", s.str().c_str()));
454 return res;
455 }
456 s << list["librevenge:number"]->getStr().cstr();
457 }
458 else if (type=="librevenge-text")
459 {
460 if (!list["librevenge:text"])
461 {
462 ODFGEN_DEBUG_MSG(("SheetManager::convertFormula can not find text for formula[%s]!!!\n", s.str().c_str()));
463 return res;
464 }
465 librevenge::RVNGString escaped;
466 escaped.appendEscapedXML(list["librevenge:text"]->getStr());
467 s << "\"" << escaped.cstr() << "\"";
468 }
469 else if (type=="librevenge-cell")
470 {
471 librevenge::RVNGString range=convertCellRange(list);
472 if (range.empty())
473 {
474 // look for special case: a complete row or column
475 if ((list["librevenge:column"] && list["librevenge:row"]) ||
476 (!list["librevenge:column"] && !list["librevenge:row"]))
477 return res;
478 if (i+2<formula.count() &&
479 formula[i+1]["librevenge:operator"] && formula[i+1]["librevenge:operator"]->getStr()==":" &&
480 formula[i+2]["librevenge:type"] && formula[i+2]["librevenge:type"]->getStr()=="librevenge-cell")
481 {
482 // cell followed by a range's operator and a cell, recreate the range cells...
483 auto rList(list);
484 if (list["librevenge:column"]) rList.insert("librevenge:start-column", list["librevenge:column"]->getStr());
485 if (list["librevenge:column-absolute"]) rList.insert("librevenge:start-column-absolute", list["librevenge:column-absolute"]->getStr());
486 if (list["librevenge:row"]) rList.insert("librevenge:start-row", list["librevenge:row"]->getStr());
487 if (list["librevenge:row-absolute"]) rList.insert("librevenge:start-row-absolute", list["librevenge:row-absolute"]->getStr());
488 if (formula[i+2]["librevenge:column"]) rList.insert("librevenge:end-column", formula[i+2]["librevenge:column"]->getStr());
489 if (formula[i+2]["librevenge:column-absolute"]) rList.insert("librevenge:end-column-absolute", formula[i+2]["librevenge:column-absolute"]->getStr());
490 if (formula[i+2]["librevenge:row"]) rList.insert("librevenge:end-row", formula[i+2]["librevenge:row"]->getStr());
491 if (formula[i+2]["librevenge:row-absolute"]) rList.insert("librevenge:end-row-absolute", formula[i+2]["librevenge:row-absolute"]->getStr());
492 i += 2;
493 range=convertRowOrColumnCellsRange(rList);
494 }
495 else
496 {
497 // isolated cell, recreate a range cells
498 auto rList(list);
499 if (list["librevenge:column"])
500 {
501 rList.insert("librevenge:start-column", list["librevenge:column"]->getStr());
502 rList.insert("librevenge:end-column", list["librevenge:column"]->getStr());
503 }
504 if (list["librevenge:column-absolute"])
505 {
506 rList.insert("librevenge:start-column-absolute", list["librevenge:column-absolute"]->getStr());
507 rList.insert("librevenge:end-column-absolute", list["librevenge:column-absolute"]->getStr());
508 }
509 if (list["librevenge:row"])
510 {
511 rList.insert("librevenge:start-row", list["librevenge:row"]->getStr());
512 rList.insert("librevenge:end-row", list["librevenge:row"]->getStr());
513 }
514 if (list["librevenge:row-absolute"])
515 {
516 rList.insert("librevenge:start-row-absolute", list["librevenge:row-absolute"]->getStr());
517 rList.insert("librevenge:end-row-absolute", list["librevenge:row-absolute"]->getStr());
518 }
519 range=convertRowOrColumnCellsRange(rList);
520 }
521 if (range.empty()) return res;
522 }
523 s << "[" << range.cstr() << "]";
524 }
525 else if (type=="librevenge-cells")
526 {
527 librevenge::RVNGString ranges=convertCellsRange(list);
528 if (ranges.empty()) ranges=convertRowOrColumnCellsRange(list); // check for columns or rows ranges
529 if (ranges.empty()) return res;
530 s << "[" << ranges.cstr() << "]";
531 }
532 else
533 {
534 ODFGEN_DEBUG_MSG(("SheetManager::convertFormula find unknown type %s!!!\n", type.c_str()));
535 return res;
536 }
537 }
538 return librevenge::RVNGString::escapeXML(s.str().c_str());
539 }
540
convertCellRange(const librevenge::RVNGPropertyList & list)541 librevenge::RVNGString SheetManager::convertCellRange(const librevenge::RVNGPropertyList &list)
542 {
543 std::stringstream s;
544 librevenge::RVNGString res("");
545 if (!list["librevenge:row"]||!list["librevenge:column"])
546 {
547 ODFGEN_DEBUG_MSG(("SheetManager::convertCellRange can not find cordinate!!!\n"));
548 return res;
549 }
550 int column=list["librevenge:column"]->getInt();
551 int row=list["librevenge:row"]->getInt();
552 if (column<0 || row<0)
553 {
554 ODFGEN_DEBUG_MSG(("SheetManager::convertCellRange: find bad coordinate!!!\n"));
555 return res;
556 }
557 if (list["librevenge:sheet-name"] || list["librevenge:sheet"])
558 {
559 if (list["librevenge:file-name"]) s << "'" << list["librevenge:file-name"]->getStr().cstr() << "'#";
560 if (list["librevenge:sheet-name"])
561 s << list["librevenge:sheet-name"]->getStr().cstr();
562 else
563 s << list["librevenge:sheet"]->getStr().cstr();
564 }
565 s << ".";
566 if (list["librevenge:column-absolute"] && list["librevenge:column-absolute"]->getInt()) s << "$";
567 s << libodfgen::getColumnName(column);
568 if (list["librevenge:row-absolute"] && list["librevenge:row-absolute"]->getInt()) s << "$";
569 s << row+1;
570 return s.str().c_str();
571 }
572
convertRowOrColumnCellsRange(const librevenge::RVNGPropertyList & list)573 librevenge::RVNGString SheetManager::convertRowOrColumnCellsRange(const librevenge::RVNGPropertyList &list)
574 {
575 std::stringstream s;
576 librevenge::RVNGString res("");
577 bool isColumn=true;
578 if (list["librevenge:start-row"]) // check if this is a row ranges
579 {
580 if (!list["librevenge:end-row"] || list["librevenge:start-column"]) return res;
581 isColumn=false;
582 }
583 else if (!list["librevenge:start-column"] || !list["librevenge:end-column"])
584 return res;
585 int dim1=list[isColumn ? "librevenge:start-column" : "librevenge:start-row"]->getInt();
586 int dim2=list[isColumn ? "librevenge:end-column" : "librevenge:end-row"]->getInt();
587 if (dim1<0 || dim2<dim1)
588 {
589 ODFGEN_DEBUG_MSG(("SheetManager::convertRowOrColumnCellsRange: find bad coordinates!!!\n"));
590 return res;
591 }
592 if (list["librevenge:sheet-name"] || list["librevenge:start-sheet-name"])
593 {
594 if (list["librevenge:file-name"]) s << "'" << list["librevenge:file-name"]->getStr().cstr() << "'#";
595 if (list["librevenge:sheet-name"])
596 s << list["librevenge:sheet-name"]->getStr().cstr();
597 else
598 s << list["librevenge:start-sheet-name"]->getStr().cstr();
599 }
600 s << ".";
601 if (isColumn)
602 {
603 if (list["librevenge:start-column-absolute"] && list["librevenge:start-column-absolute"]->getInt()) s << "$";
604 s << libodfgen::getColumnName(dim1);
605 s << ":";
606 if (list["librevenge:end-sheet-name"])
607 {
608 if (list["librevenge:file-name"]) s << "'" << list["librevenge:file-name"]->getStr().cstr() << "'#";
609 s << list["librevenge:end-sheet-name"]->getStr().cstr();
610 }
611 s << ".";
612 if (list["librevenge:end-column-absolute"] && list["librevenge:end-column-absolute"]->getInt()) s << "$";
613 s << libodfgen::getColumnName(dim2);
614 }
615 else
616 {
617 if (list["librevenge:start-row-absolute"] && list["librevenge:start-row-absolute"]->getInt()) s << "$";
618 s << dim1+1 << ":";
619 if (list["librevenge:end-sheet-name"])
620 {
621 if (list["librevenge:file-name"]) s << "'" << list["librevenge:file-name"]->getStr().cstr() << "'#";
622 s << list["librevenge:end-sheet-name"]->getStr().cstr();
623 }
624 s << ".";
625 if (list["librevenge:end-row-absolute"] && list["librevenge:end-row-absolute"]->getInt()) s << "$";
626 s << dim2+1;
627 }
628 return s.str().c_str();
629 }
630
convertCellsRange(const librevenge::RVNGPropertyList & list)631 librevenge::RVNGString SheetManager::convertCellsRange(const librevenge::RVNGPropertyList &list)
632 {
633 std::stringstream s;
634 librevenge::RVNGString res("");
635 if (!list["librevenge:start-row"]||!list["librevenge:start-column"])
636 {
637 ODFGEN_DEBUG_MSG(("SheetManager::convertCellsRange can not find cordinate!!!\n"));
638 return res;
639 }
640 int column=list["librevenge:start-column"]->getInt();
641 int row=list["librevenge:start-row"]->getInt();
642 if (column<0 || row<0)
643 {
644 ODFGEN_DEBUG_MSG(("SheetManager::convertCellsRange: find bad coordinate1!!!\n"));
645 return res;
646 }
647 if (list["librevenge:sheet-name"] || list["librevenge:start-sheet-name"])
648 {
649 if (list["librevenge:file-name"]) s << "'" << list["librevenge:file-name"]->getStr().cstr() << "'#";
650 if (list["librevenge:sheet-name"])
651 s << list["librevenge:sheet-name"]->getStr().cstr();
652 else
653 s << list["librevenge:start-sheet-name"]->getStr().cstr();
654 }
655 s << ".";
656 if (list["librevenge:start-column-absolute"] && list["librevenge:start-column-absolute"]->getInt()) s << "$";
657 s << libodfgen::getColumnName(column);
658 if (list["librevenge:start-row-absolute"] && list["librevenge:start-row-absolute"]->getInt()) s << "$";
659 s << row+1 << ":";
660 if (list["librevenge:end-sheet-name"])
661 {
662 if (list["librevenge:file-name"]) s << "'" << list["librevenge:file-name"]->getStr().cstr() << "'#";
663 s << list["librevenge:end-sheet-name"]->getStr().cstr();
664 }
665 s << ".";
666 if (list["librevenge:end-column"])
667 column=list["librevenge:end-column"]->getInt();
668 if (list["librevenge:end-row"])
669 row=list["librevenge:end-row"]->getInt();
670 if (column<0 || row<0)
671 {
672 ODFGEN_DEBUG_MSG(("SheetManager::convertCellsRange: find bad coordinate2!!!\n"));
673 return res;
674 }
675 if (list["librevenge:end-column-absolute"] && list["librevenge:end-column-absolute"]->getInt()) s << "$";
676 s << libodfgen::getColumnName(column);
677 if (list["librevenge:end-row-absolute"] && list["librevenge:end-row-absolute"]->getInt()) s << "$";
678 s << row+1;
679 return s.str().c_str();
680 }
681
write(OdfDocumentHandler * pHandler,Style::Zone zone) const682 void SheetManager::write(OdfDocumentHandler *pHandler, Style::Zone zone) const
683 {
684 for (const auto &sheetStyle : mSheetStyles)
685 {
686 if (sheetStyle && sheetStyle->getZone()==zone)
687 sheetStyle->writeStyle(pHandler, *this);
688 }
689 }
690
691 /* vim:set shiftwidth=4 softtabstop=4 noexpandtab: */
692