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 /* "This product is not manufactured, approved, or supported by
24 * Corel Corporation or Corel Corporation Limited."
25 */
26
27 #include <libodfgen/libodfgen.hxx>
28
29 #include <librevenge/librevenge.h>
30
31 #include <iomanip>
32 #include <locale>
33 #include <map>
34 #include <stack>
35 #include <sstream>
36 #include <string>
37
38 #include "DocumentElement.hxx"
39 #include "FilterInternal.hxx"
40
41 #include "InternalHandler.hxx"
42 #include "FontStyle.hxx"
43 #include "ListStyle.hxx"
44 #include "PageSpan.hxx"
45 #include "SheetStyle.hxx"
46 #include "TableStyle.hxx"
47
48 #include "OdcGenerator.hxx"
49 #include "OdfGenerator.hxx"
50
51 namespace
52 {
53
makePreciseStr(const double value)54 librevenge::RVNGString makePreciseStr(const double value)
55 {
56 std::ostringstream os;
57 os.imbue(std::locale::classic());
58 os << std::setprecision(8) << value;
59 return os.str().c_str();
60 }
61
62 }
63
64 class OdsGeneratorPrivate : public OdfGenerator
65 {
66 public:
67 enum Command { C_Document=0, C_PageSpan, C_Header, C_Footer, C_Sheet, C_SheetRow, C_SheetCell,
68 C_Chart, C_ChartDataLabel, C_ChartPlotArea, C_ChartSerie, C_ChartTextObject,
69 C_Span, C_Paragraph, C_Section, C_OrderedList, C_UnorderedList, C_ListElement,
70 C_Footnote, C_Comment, C_TextBox, C_Frame, C_Table, C_TableRow, C_TableCell,
71 C_Group
72 };
73 // the state we use for writing the final document
74 struct State
75 {
StateOdsGeneratorPrivate::State76 State() : mbStarted(false),
77 mbInSheet(false), mbInSheetShapes(false), mbInSheetRow(false), mbFirstInSheetRow(false), mbInSheetCell(false), miLastSheetRow(0), miLastSheetColumn(0),
78 mbInFootnote(false), mbInComment(false), mbInHeaderFooter(false), mbInFrame(false), mbFirstInFrame(false), mbInChart(false),
79 mbInGroup(false), mbInTable(false), mbInTextBox(false),
80 mbNewOdcGenerator(false), mbNewOdtGenerator(false)
81 {
82 }
canOpenFrameOdsGeneratorPrivate::State83 bool canOpenFrame() const
84 {
85 return mbStarted && mbInSheet && !mbInSheetCell && !mbInFootnote && !mbInComment
86 && !mbInHeaderFooter && !mbInFrame && !mbInChart;
87 }
88 bool mbStarted;
89
90 bool mbInSheet;
91 bool mbInSheetShapes;
92 bool mbInSheetRow;
93 bool mbFirstInSheetRow;
94 bool mbInSheetCell;
95 int miLastSheetRow;
96 int miLastSheetColumn;
97 bool mbInFootnote;
98 bool mbInComment;
99 bool mbInHeaderFooter;
100 bool mbInFrame;
101 bool mbFirstInFrame;
102 bool mbInChart;
103 bool mbInGroup;
104 bool mbInTable;
105 bool mbInTextBox;
106
107 bool mbNewOdcGenerator;
108 bool mbNewOdtGenerator;
109 };
110 // the odc state
111 struct OdcGeneratorState
112 {
OdcGeneratorStateOdsGeneratorPrivate::OdcGeneratorState113 explicit OdcGeneratorState(librevenge::RVNGString const &dir)
114 : mDir(dir)
115 , mContentElements()
116 , mInternalHandler(&mContentElements)
117 , mGenerator()
118 {
119 if (!mDir.empty()) return;
120 mGenerator.addDocumentHandler(&mInternalHandler,ODF_FLAT_XML);
121 }
~OdcGeneratorStateOdsGeneratorPrivate::OdcGeneratorState122 ~OdcGeneratorState()
123 {
124 }
getOdsGeneratorPrivate::OdcGeneratorState125 OdcGenerator &get()
126 {
127 return mGenerator;
128 }
129 librevenge::RVNGString mDir;
130 libodfgen::DocumentElementVector mContentElements;
131 InternalHandler mInternalHandler;
132 OdcGenerator mGenerator;
133 };
134
135 // the odt state
136 struct OdtGeneratorState
137 {
OdtGeneratorStateOdsGeneratorPrivate::OdtGeneratorState138 OdtGeneratorState() : mContentElements(), mInternalHandler(&mContentElements), mGenerator()
139 {
140 mGenerator.addDocumentHandler(&mInternalHandler,ODF_FLAT_XML);
141 }
~OdtGeneratorStateOdsGeneratorPrivate::OdtGeneratorState142 ~OdtGeneratorState()
143 {
144 }
getOdsGeneratorPrivate::OdtGeneratorState145 OdtGenerator &get()
146 {
147 return mGenerator;
148 }
149 libodfgen::DocumentElementVector mContentElements;
150 InternalHandler mInternalHandler;
151 OdtGenerator mGenerator;
152 };
153
154 OdsGeneratorPrivate();
155 ~OdsGeneratorPrivate() override;
addDocumentHandler(OdfDocumentHandler * pHandler,const OdfStreamType streamType)156 void addDocumentHandler(OdfDocumentHandler *pHandler, const OdfStreamType streamType)
157 {
158 if (!pHandler)
159 {
160 ODFGEN_DEBUG_MSG(("OdsGeneratorPrivate::addDocumentHandler: called without handler\n"));
161 return;
162 }
163 mDocumentStreamHandlers[streamType] = pHandler;
164 }
165 //
166 // command gestion
167 //
168
open(Command const command)169 void open(Command const command)
170 {
171 mCommandStack.push(command);
172 }
173 bool close(Command command);
174
175 //
176 // state gestion
177 //
178
179 // returns the actual state
getState()180 State &getState()
181 {
182 if (mStateStack.empty())
183 {
184 ODFGEN_DEBUG_MSG(("OdsGeneratorPrivate::getState: no state\n"));
185 mStateStack.push(State());
186 }
187 return mStateStack.top();
188 }
189 // push a state
pushState(State const & state)190 void pushState(State const &state)
191 {
192 mStateStack.push(state);
193 }
194 // pop a state
popState()195 void popState()
196 {
197 if (!mStateStack.empty())
198 mStateStack.pop();
199 else
200 {
201 ODFGEN_DEBUG_MSG(("OdsGeneratorPrivate::popState: no state\n"));
202 }
203 }
204 // check if we are in a sheetcell or in a comment
canWriteText() const205 bool canWriteText() const
206 {
207 if (mStateStack.empty() || mStateStack.top().mbInFootnote) return false;
208 return mStateStack.top().mbInComment || mStateStack.top().mbInSheetCell ||
209 mStateStack.top().mbInHeaderFooter || mStateStack.top().mbInTextBox;
210 }
canAddNewShape(bool add=true)211 bool canAddNewShape(bool add=true)
212 {
213 if (mStateStack.empty())
214 {
215 if (add)
216 {
217 ODFGEN_DEBUG_MSG(("OdsGeneratorPrivate::canAddNewShape: can not find the state!!!\n"));
218 }
219 return false;
220 }
221 State &state=mStateStack.top();
222 if (!state.mbStarted || !state.mbInSheet || state.mbInChart || state.mbInComment || state.mbInSheetRow)
223 {
224 if (add)
225 {
226 ODFGEN_DEBUG_MSG(("OdsGeneratorPrivate::canAddNewShape: call outside a sheet shapes zone!!!\n"));
227 }
228 return false;
229 }
230 if (add && !state.mbInSheetShapes)
231 {
232 getCurrentStorage()->push_back(std::make_shared<TagOpenElement>("table:shapes"));
233 state.mbInSheetShapes=true;
234 }
235 return true;
236 }
237
238 //
239 // auxilliar generator
240 //
createAuxiliarOdcGenerator()241 bool createAuxiliarOdcGenerator()
242 {
243 if (mAuxiliarOdcState)
244 {
245 ODFGEN_DEBUG_MSG(("OdsGeneratorPrivate::createAuxiliarOdcGenerator: already created\n"));
246 return false;
247 }
248 bool isFlat = mDocumentStreamHandlers.find(ODF_FLAT_XML)!=mDocumentStreamHandlers.end();
249 librevenge::RVNGString dir("");
250 if (!isFlat)
251 dir.sprintf("Object %i/", miObjectNumber++);
252 mAuxiliarOdcState.reset(new OdcGeneratorState(dir));
253 if (!isFlat)
254 {
255 createObjectFile(dir, "application/vnd.oasis.opendocument.chart", true);
256 librevenge::RVNGString file(dir);
257 file.append("content.xml");
258 mAuxiliarOdcState->mGenerator.addDocumentHandler
259 (&createObjectFile(file, "text/xml").mInternalHandler, ODF_CONTENT_XML);
260 file=dir;
261 file.append("meta.xml");
262 mAuxiliarOdcState->mGenerator.addDocumentHandler
263 (&createObjectFile(file, "text/xml").mInternalHandler, ODF_META_XML);
264 file=dir;
265 file.append("styles.xml");
266 mAuxiliarOdcState->mGenerator.addDocumentHandler
267 (&createObjectFile(file, "text/xml").mInternalHandler, ODF_STYLES_XML);
268 }
269 mAuxiliarOdcState->mGenerator.initStateWith(*this);
270 mAuxiliarOdcState->mGenerator.startDocument(librevenge::RVNGPropertyList());
271
272 return true;
273 }
sendAuxiliarOdcGenerator()274 bool sendAuxiliarOdcGenerator()
275 {
276 if (!mAuxiliarOdcState)
277 {
278 ODFGEN_DEBUG_MSG(("OdsGeneratorPrivate::sendAuxiliarOdcGenerator: data seems bad\n"));
279 return false;
280 }
281 mAuxiliarOdcState->mGenerator.endDocument();
282 if (mAuxiliarOdcState->mDir.empty() && mAuxiliarOdcState->mContentElements.empty())
283 {
284 ODFGEN_DEBUG_MSG(("OdsGeneratorPrivate::sendAuxiliarOdcGenerator: data seems bad\n"));
285 return false;
286 }
287 auto object=std::make_shared<TagOpenElement>("draw:object");
288 if (!mAuxiliarOdcState->mDir.empty())
289 {
290 object->addAttribute("xlink:href",mAuxiliarOdcState->mDir.cstr());
291 object->addAttribute("xlink:type","simple");
292 object->addAttribute("xlink:show","embed");
293 object->addAttribute("xlink:actuate","onLoad");
294 }
295 getCurrentStorage()->push_back(object);
296 getCurrentStorage()->insert(getCurrentStorage()->end(), mAuxiliarOdcState->mContentElements.begin(), mAuxiliarOdcState->mContentElements.end());
297 mAuxiliarOdcState->mContentElements.resize(0);
298 getCurrentStorage()->push_back(std::make_shared<TagCloseElement>("draw:object"));
299 return true;
300 }
resetAuxiliarOdcGenerator()301 void resetAuxiliarOdcGenerator()
302 {
303 mAuxiliarOdcState.reset();
304 }
checkOutsideOdc(char const * function) const305 bool checkOutsideOdc(char const *function) const
306 {
307 if (!mAuxiliarOdcState) return true;
308 if (!function) return false;
309 ODFGEN_DEBUG_MSG(("OdsGenerator::%s: call in chart\n", function));
310 return false;
311 }
createAuxiliarOdtGenerator()312 bool createAuxiliarOdtGenerator()
313 {
314 if (mAuxiliarOdtState)
315 {
316 ODFGEN_DEBUG_MSG(("OdsGeneratorPrivate::createAuxiliarOdtGenerator: already created\n"));
317 return false;
318 }
319 mAuxiliarOdtState.reset(new OdtGeneratorState);
320 mAuxiliarOdtState->mGenerator.initStateWith(*this);
321 mAuxiliarOdtState->mGenerator.startDocument(librevenge::RVNGPropertyList());
322 librevenge::RVNGPropertyList page;
323 page.insert("librevenge:num-pages", 1);
324 page.insert("fo:margin-left", 0.0, librevenge::RVNG_INCH);
325 page.insert("fo:margin-right", 0.0, librevenge::RVNG_INCH);
326 page.insert("fo:margin-top", 0.0, librevenge::RVNG_INCH);
327 page.insert("fo:margin-bottom", 0.0, librevenge::RVNG_INCH);
328 mAuxiliarOdtState->mGenerator.openPageSpan(page);
329
330 return true;
331 }
sendAuxiliarOdtGenerator()332 bool sendAuxiliarOdtGenerator()
333 {
334 if (!mAuxiliarOdtState)
335 {
336 ODFGEN_DEBUG_MSG(("OdsGeneratorPrivate::sendAuxiliarOdtGenerator: data seems bad\n"));
337 return false;
338 }
339 mAuxiliarOdtState->mGenerator.closePageSpan();
340 mAuxiliarOdtState->mGenerator.endDocument();
341 if (mAuxiliarOdtState->mContentElements.empty())
342 {
343 ODFGEN_DEBUG_MSG(("OdsGeneratorPrivate::sendAuxiliarOdtGenerator: data seems bad\n"));
344 return false;
345 }
346 getCurrentStorage()->push_back(std::make_shared<TagOpenElement>("draw:object"));
347 getCurrentStorage()->insert(getCurrentStorage()->end(), mAuxiliarOdtState->mContentElements.begin(), mAuxiliarOdtState->mContentElements.end());
348 mAuxiliarOdtState->mContentElements.resize(0);
349 getCurrentStorage()->push_back(std::make_shared<TagCloseElement>("draw:object"));
350 return true;
351 }
resetAuxiliarOdtGenerator()352 void resetAuxiliarOdtGenerator()
353 {
354 mAuxiliarOdtState.reset();
355 }
checkOutsideOdt(char const * function) const356 bool checkOutsideOdt(char const *function) const
357 {
358 if (!mAuxiliarOdtState) return true;
359 if (!function) return false;
360 ODFGEN_DEBUG_MSG(("OdsGenerator::%s: call in text auxilliar\n", function));
361 return false;
362 }
363
364 bool writeTargetDocument(OdfDocumentHandler *pHandler, OdfStreamType streamType) override;
365 void _writeStyles(OdfDocumentHandler *pHandler);
366 void _writeAutomaticStyles(OdfDocumentHandler *pHandler, OdfStreamType streamType);
367 void initPageManager();
368
369 std::stack<Command> mCommandStack;
370 std::stack<State> mStateStack;
371
372 // auxiliar odc handler to create data
373 std::shared_ptr<OdcGeneratorState> mAuxiliarOdcState;
374 // auxiliar odt handler to create data
375 std::shared_ptr<OdtGeneratorState> mAuxiliarOdtState;
376
377 // table styles
378 SheetManager mSheetManager;
379
380 // page manager
381 PageSpan *mpCurrentPageSpan;
382
383 //
384 private:
385 OdsGeneratorPrivate(const OdsGeneratorPrivate &);
386 OdsGeneratorPrivate &operator=(const OdsGeneratorPrivate &);
387
388 };
389
OdsGeneratorPrivate()390 OdsGeneratorPrivate::OdsGeneratorPrivate() : OdfGenerator(),
391 mCommandStack(),
392 mStateStack(),
393 mAuxiliarOdcState(), mAuxiliarOdtState(),
394 mSheetManager(mNumberingManager),
395 mpCurrentPageSpan(nullptr)
396 {
397 mStateStack.push(State());
398 initPageManager();
399 }
400
~OdsGeneratorPrivate()401 OdsGeneratorPrivate::~OdsGeneratorPrivate()
402 {
403 // clean up the mess we made
404 ODFGEN_DEBUG_MSG(("OdsGenerator: Cleaning up our mess..\n"));
405
406 ODFGEN_DEBUG_MSG(("OdsGenerator: Destroying the body elements\n"));
407 mSheetManager.clean();
408 }
409
close(Command command)410 bool OdsGeneratorPrivate::close(Command command)
411 {
412 if (mCommandStack.empty() || mCommandStack.top()!=command)
413 {
414 #ifdef DEBUG
415 static char const *wh[] =
416 {
417 "Document", "PageSpan", "Header", "Footer", "Sheet", "SheetRow", "SheetCell",
418 "Chart", "ChartDataLabel", "ChartPlotArea", "ChartSerie", "ChartTextObject",
419 "Span", "Paragraph", "Section", "OrderedListLevel", "UnorderedListLevel", "ListElement",
420 "Footnote", "Comment", "TextBox", "Frame", "Table", "TableRow", "TableCell",
421 "Group"
422 };
423 ODFGEN_DEBUG_MSG(("OdsGeneratorPrivate::close: unexpected %s\n", wh[command]));
424 #endif
425 return false;
426 }
427 mCommandStack.pop();
428 return true;
429 }
430
initPageManager()431 void OdsGeneratorPrivate::initPageManager()
432 {
433 librevenge::RVNGPropertyList page;
434 page.insert("fo:margin-bottom", "1in");
435 page.insert("fo:margin-left", "1in");
436 page.insert("fo:margin-right", "1in");
437 page.insert("fo:margin-top", "1in");
438 page.insert("fo:page-height", "11in");
439 page.insert("fo:page-width", "8.5in");
440 page.insert("style:print-orientation", "portrait");
441
442 librevenge::RVNGPropertyList footnoteSep;
443 footnoteSep.insert("style:adjustment","left");
444 footnoteSep.insert("style:color","#000000");
445 footnoteSep.insert("style:rel-width","25%");
446 footnoteSep.insert("style:distance-after-sep","0.0398in");
447 footnoteSep.insert("style:distance-before-sep","0.0398in");
448 footnoteSep.insert("style:width","0.0071in");
449 librevenge::RVNGPropertyListVector footnoteVector;
450 footnoteVector.append(footnoteSep);
451 page.insert("librevenge:footnote", footnoteVector);
452 page.insert("librevenge:master-page-name", "Standard");
453 mPageSpanManager.add(page);
454
455
456 footnoteSep.remove("style:distance-after-sep");
457 footnoteSep.remove("style:distance-before-sep");
458 footnoteSep.remove("style:width");
459 footnoteVector.clear();
460 footnoteVector.append(footnoteSep);
461 page.insert("librevenge:footnote", footnoteVector);
462 page.insert("librevenge:master-page-name", "EndNote");
463 mPageSpanManager.add(page);
464 }
465
OdsGenerator()466 OdsGenerator::OdsGenerator() : mpImpl(new OdsGeneratorPrivate())
467 {
468 }
469
~OdsGenerator()470 OdsGenerator::~OdsGenerator()
471 {
472 if (mpImpl)
473 delete mpImpl;
474 }
475
addDocumentHandler(OdfDocumentHandler * pHandler,const OdfStreamType streamType)476 void OdsGenerator::addDocumentHandler(OdfDocumentHandler *pHandler, const OdfStreamType streamType)
477 {
478 if (mpImpl)
479 mpImpl->addDocumentHandler(pHandler, streamType);
480 }
481
getObjectNames() const482 librevenge::RVNGStringVector OdsGenerator::getObjectNames() const
483 {
484 if (mpImpl)
485 return mpImpl->getObjectNames();
486 return librevenge::RVNGStringVector();
487 }
488
getObjectContent(librevenge::RVNGString const & objectName,OdfDocumentHandler * pHandler)489 bool OdsGenerator::getObjectContent(librevenge::RVNGString const &objectName, OdfDocumentHandler *pHandler)
490 {
491 if (!mpImpl)
492 return false;
493 return mpImpl->getObjectContent(objectName, pHandler);
494 }
495
_writeAutomaticStyles(OdfDocumentHandler * pHandler,OdfStreamType streamType)496 void OdsGeneratorPrivate::_writeAutomaticStyles(OdfDocumentHandler *pHandler, OdfStreamType streamType)
497 {
498 TagOpenElement("office:automatic-styles").write(pHandler);
499
500 if ((streamType == ODF_FLAT_XML) || (streamType == ODF_STYLES_XML))
501 {
502 mPageSpanManager.writePageStyles(pHandler, Style::Z_StyleAutomatic);
503 mSpanManager.write(pHandler, Style::Z_StyleAutomatic);
504 mParagraphManager.write(pHandler, Style::Z_StyleAutomatic);
505 mListManager.write(pHandler, Style::Z_StyleAutomatic);
506 mGraphicManager.write(pHandler, Style::Z_StyleAutomatic);
507 mNumberingManager.write(pHandler, Style::Z_StyleAutomatic);
508 mSheetManager.write(pHandler, Style::Z_StyleAutomatic);
509 }
510
511 if ((streamType == ODF_FLAT_XML) || (streamType == ODF_CONTENT_XML))
512 {
513 mPageSpanManager.writePageStyles(pHandler, Style::Z_ContentAutomatic);
514 mSpanManager.write(pHandler, Style::Z_ContentAutomatic);
515 mParagraphManager.write(pHandler, Style::Z_ContentAutomatic);
516 mListManager.write(pHandler, Style::Z_ContentAutomatic);
517 mGraphicManager.write(pHandler, Style::Z_ContentAutomatic);
518 mNumberingManager.write(pHandler, Style::Z_ContentAutomatic);
519 mSheetManager.write(pHandler, Style::Z_ContentAutomatic);
520 }
521
522 pHandler->endElement("office:automatic-styles");
523 }
524
_writeStyles(OdfDocumentHandler * pHandler)525 void OdsGeneratorPrivate::_writeStyles(OdfDocumentHandler *pHandler)
526 {
527 TagOpenElement("office:styles").write(pHandler);
528
529 mPageSpanManager.writePageStyles(pHandler, Style::Z_Style);
530
531 // style:default-style
532 // paragraph
533 TagOpenElement defaultParagraphStyleOpenElement("style:default-style");
534 defaultParagraphStyleOpenElement.addAttribute("style:family", "paragraph");
535 defaultParagraphStyleOpenElement.write(pHandler);
536 TagOpenElement defaultParagraphStylePropertiesOpenElement("style:paragraph-properties");
537 defaultParagraphStylePropertiesOpenElement.addAttribute("style:tab-stop-distance", "0.5in");
538 defaultParagraphStylePropertiesOpenElement.addAttribute("style:text-autospace", "ideograph-alpha");
539 defaultParagraphStylePropertiesOpenElement.addAttribute("style:punctuation-wrap", "hanging");
540 defaultParagraphStylePropertiesOpenElement.addAttribute("style:writing-mode", "page");
541 defaultParagraphStylePropertiesOpenElement.write(pHandler);
542 pHandler->endElement("style:paragraph-properties");
543 pHandler->endElement("style:default-style");
544
545 // graphic
546 TagOpenElement defaultGraphicStyleOpenElement("style:default-style");
547 defaultGraphicStyleOpenElement.addAttribute("style:family", "graphic");
548 defaultGraphicStyleOpenElement.write(pHandler);
549 TagOpenElement defaultGraphicStylePropertiesOpenElement("style:graphic-properties");
550 defaultGraphicStylePropertiesOpenElement.addAttribute("draw:fill","solid");
551 defaultGraphicStylePropertiesOpenElement.addAttribute("draw:fill-color","#ffffff");
552 defaultGraphicStylePropertiesOpenElement.addAttribute("draw:stroke","none");
553 defaultGraphicStylePropertiesOpenElement.addAttribute("draw:shadow","hidden");
554 defaultGraphicStylePropertiesOpenElement.write(pHandler);
555 pHandler->endElement("style:graphic-properties");
556 pHandler->endElement("style:default-style");
557
558 // table
559 TagOpenElement defaultTableStyleOpenElement("style:default-style");
560 defaultTableStyleOpenElement.addAttribute("style:family", "table");
561 defaultTableStyleOpenElement.write(pHandler);
562 pHandler->endElement("style:default-style");
563
564 // table-row
565 TagOpenElement defaultTableRowStyleOpenElement("style:default-style");
566 defaultTableRowStyleOpenElement.addAttribute("style:family", "table-row");
567 defaultTableRowStyleOpenElement.write(pHandler);
568 TagOpenElement defaultTableRowPropertiesOpenElement("style:table-row-properties");
569 defaultTableRowPropertiesOpenElement.addAttribute("fo:keep-together", "auto");
570 defaultTableRowPropertiesOpenElement.write(pHandler);
571 pHandler->endElement("style:table-row-properties");
572 pHandler->endElement("style:default-style");
573
574 // table-column
575 TagOpenElement defaultTableColumnStyleOpenElement("style:default-style");
576 defaultTableColumnStyleOpenElement.addAttribute("style:family", "table-column");
577 defaultTableColumnStyleOpenElement.write(pHandler);
578 pHandler->endElement("style:default-style");
579
580 // table-cell
581 TagOpenElement defaultTableCellStyleOpenElement("style:default-style");
582 defaultTableCellStyleOpenElement.addAttribute("style:family", "table-cell");
583 defaultTableCellStyleOpenElement.write(pHandler);
584 pHandler->endElement("style:default-style");
585
586 // basic style
587
588 // paragraph Standard
589 TagOpenElement standardStyleOpenElement("style:style");
590 standardStyleOpenElement.addAttribute("style:name", "Standard");
591 standardStyleOpenElement.addAttribute("style:family", "paragraph");
592 standardStyleOpenElement.addAttribute("style:class", "text");
593 standardStyleOpenElement.write(pHandler);
594 pHandler->endElement("style:style");
595
596 static char const *s_paraStyle[4*10] =
597 {
598 "Text_Body", "Text Body", "Standard", "text",
599 "Table_Contents", "Table Contents", "Text_Body", "extra",
600 "Table_Heading", "Table Heading", "Table_Contents", "extra",
601 "List", "List", "Text_Body", "list",
602 "Header", "Header", "Standard", "extra",
603 "Footer", "Footer", "Standard", "extra",
604 "Caption", "Caption", "Standard", "extra",
605 "Footnote", "Footnote", "Standard", "extra",
606 "Endnote", "Endnote", "Standard", "extra",
607 "Index", "Index", "Standard", "extra"
608 };
609 for (int i=0; i<10; ++i)
610 {
611 TagOpenElement paraOpenElement("style:style");
612 paraOpenElement.addAttribute("style:name", s_paraStyle[4*i]);
613 paraOpenElement.addAttribute("style:display-name", s_paraStyle[4*i+1]);
614 paraOpenElement.addAttribute("style:family", "paragraph");
615 paraOpenElement.addAttribute("style:parent-style-name", s_paraStyle[4*i+2]);
616 paraOpenElement.addAttribute("style:class", s_paraStyle[4*i+3]);
617 paraOpenElement.write(pHandler);
618 pHandler->endElement("style:style");
619 }
620
621 static char const *s_textStyle[2*4] =
622 {
623 "Footnote_Symbol", "Footnote Symbol", "Endnote_Symbol", "Endnote Symbol",
624 "Footnote_anchor", "Footnote anchor", "Endnote_anchor", "Endnote anchor"
625 };
626 for (int i=0; i<4; ++i)
627 {
628 TagOpenElement textOpenElement("style:style");
629 textOpenElement.addAttribute("style:name", s_textStyle[2*i]);
630 textOpenElement.addAttribute("style:display-name", s_textStyle[2*i]);
631 textOpenElement.addAttribute("style:family", "text");
632 textOpenElement.write(pHandler);
633 TagOpenElement textPropertiesOpenElement("style:text-properties");
634 textPropertiesOpenElement.addAttribute("style:text-position", "super 58%");
635 textPropertiesOpenElement.write(pHandler);
636 pHandler->endElement("style:text-properties");
637 pHandler->endElement("style:style");
638 }
639
640 mSpanManager.write(pHandler, Style::Z_Style);
641 mParagraphManager.write(pHandler, Style::Z_Style);
642 mListManager.write(pHandler, Style::Z_Style);
643 mFillManager.write(pHandler);
644 mGraphicManager.write(pHandler, Style::Z_Style);
645 pHandler->endElement("office:styles");
646 }
647
writeTargetDocument(OdfDocumentHandler * pHandler,OdfStreamType streamType)648 bool OdsGeneratorPrivate::writeTargetDocument(OdfDocumentHandler *pHandler, OdfStreamType streamType)
649 {
650 if (streamType == ODF_MANIFEST_XML)
651 {
652 pHandler->startDocument();
653 TagOpenElement manifestElement("manifest:manifest");
654 manifestElement.addAttribute("xmlns:manifest", "urn:oasis:names:tc:opendocument:xmlns:manifest:1.0");
655 manifestElement.addAttribute("manifest:version", "1.2", true);
656 manifestElement.write(pHandler);
657
658 TagOpenElement mainFile("manifest:file-entry");
659 mainFile.addAttribute("manifest:media-type", "application/vnd.oasis.opendocument.spreadsheet");
660 mainFile.addAttribute("manifest:full-path", "/");
661 mainFile.write(pHandler);
662 TagCloseElement("manifest:file-entry").write(pHandler);
663 appendFilesInManifest(pHandler);
664
665 TagCloseElement("manifest:manifest").write(pHandler);
666 pHandler->endDocument();
667 return true;
668 }
669
670 pHandler->startDocument();
671
672 if (streamType == ODF_FLAT_XML || streamType == ODF_CONTENT_XML)
673 {
674 ODFGEN_DEBUG_MSG(("OdsGenerator: Document Body: preamble\n"));
675 }
676
677 std::string const documentType=OdfGenerator::getDocumentType(streamType);
678 librevenge::RVNGPropertyList docContentPropList;
679 docContentPropList.insert("xmlns:office", "urn:oasis:names:tc:opendocument:xmlns:office:1.0");
680 docContentPropList.insert("xmlns:meta", "urn:oasis:names:tc:opendocument:xmlns:meta:1.0");
681 docContentPropList.insert("xmlns:dc", "http://purl.org/dc/elements/1.1/");
682 docContentPropList.insert("xmlns:config", "urn:oasis:names:tc:opendocument:xmlns:config:1.0");
683 docContentPropList.insert("xmlns:text", "urn:oasis:names:tc:opendocument:xmlns:text:1.0");
684 docContentPropList.insert("xmlns:table", "urn:oasis:names:tc:opendocument:xmlns:table:1.0");
685 docContentPropList.insert("xmlns:draw", "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0");
686 docContentPropList.insert("xmlns:of", "urn:oasis:names:tc:opendocument:xmlns:of:1.2");
687
688 docContentPropList.insert("xmlns:fo", "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0");
689 docContentPropList.insert("xmlns:xlink", "http://www.w3.org/1999/xlink");
690 docContentPropList.insert("xmlns:number", "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0");
691 docContentPropList.insert("xmlns:svg", "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0");
692 docContentPropList.insert("xmlns:chart", "urn:oasis:names:tc:opendocument:xmlns:chart:1.0");
693 docContentPropList.insert("xmlns:dr3d", "urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0");
694 docContentPropList.insert("xmlns:math", "http://www.w3.org/1998/Math/MathML");
695 docContentPropList.insert("xmlns:form", "urn:oasis:names:tc:opendocument:xmlns:form:1.0");
696 docContentPropList.insert("xmlns:script", "urn:oasis:names:tc:opendocument:xmlns:script:1.0");
697 docContentPropList.insert("xmlns:tableooo", "http://openoffice.org/2009/table");
698 docContentPropList.insert("xmlns:style", "urn:oasis:names:tc:opendocument:xmlns:style:1.0");
699 docContentPropList.insert("xmlns:calcext","urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0");
700 docContentPropList.insert("office:version", librevenge::RVNGPropertyFactory::newStringProp("1.2"));
701 if (streamType == ODF_FLAT_XML)
702 docContentPropList.insert("office:mimetype", "application/vnd.oasis.opendocument.spreadsheet");
703 pHandler->startElement(documentType.c_str(), docContentPropList);
704
705 if (streamType == ODF_FLAT_XML || streamType == ODF_META_XML)
706 writeDocumentMetaData(pHandler);
707
708 // write out the font styles
709 if (streamType == ODF_FLAT_XML || streamType == ODF_STYLES_XML || streamType == ODF_CONTENT_XML)
710 {
711 TagOpenElement("office:font-face-decls").write(pHandler);
712 mFontManager.write(pHandler, Style::Z_Font);
713 TagCloseElement("office:font-face-decls").write(pHandler);
714 }
715
716 // write default styles
717 if (streamType == ODF_FLAT_XML || streamType == ODF_STYLES_XML)
718 {
719 ODFGEN_DEBUG_MSG(("OdsGenerator: Document Body: Writing out the styles..\n"));
720 _writeStyles(pHandler);
721 }
722 // writing automatic style
723 if (streamType == ODF_FLAT_XML || streamType == ODF_STYLES_XML || streamType == ODF_CONTENT_XML)
724 _writeAutomaticStyles(pHandler, streamType);
725
726 // writing out the page masters
727 if (streamType == ODF_FLAT_XML || streamType == ODF_STYLES_XML)
728 {
729 TagOpenElement("office:master-styles").write(pHandler);
730 mPageSpanManager.writeMasterPages(pHandler);
731 pHandler->endElement("office:master-styles");
732 }
733 if (streamType == ODF_FLAT_XML || streamType == ODF_CONTENT_XML)
734 {
735 ODFGEN_DEBUG_MSG(("OdsGenerator: Document Body: Writing out the document..\n"));
736 // writing out the document
737 TagOpenElement("office:body").write(pHandler);
738 TagOpenElement("office:spreadsheet").write(pHandler);
739 sendStorage(mpBodyStorage.get(), pHandler);
740 pHandler->endElement("office:spreadsheet");
741 pHandler->endElement("office:body");
742 ODFGEN_DEBUG_MSG(("OdsGenerator: Document Body: Finished writing all doc els..\n"));
743 }
744 pHandler->endElement(documentType.c_str());
745
746 pHandler->endDocument();
747
748 return true;
749 }
750
751
setDocumentMetaData(const librevenge::RVNGPropertyList & propList)752 void OdsGenerator::setDocumentMetaData(const librevenge::RVNGPropertyList &propList)
753 {
754 mpImpl->setDocumentMetaData(propList);
755 }
756
defineEmbeddedFont(const librevenge::RVNGPropertyList & propList)757 void OdsGenerator::defineEmbeddedFont(const librevenge::RVNGPropertyList &propList)
758 {
759 mpImpl->defineEmbeddedFont(propList);
760 }
761
openPageSpan(const librevenge::RVNGPropertyList & propList)762 void OdsGenerator::openPageSpan(const librevenge::RVNGPropertyList &propList)
763 {
764 mpImpl->open(OdsGeneratorPrivate::C_PageSpan);
765 if (!mpImpl->checkOutsideOdc("openPageSpan") || !mpImpl->checkOutsideOdt("openPageSpan"))
766 return;
767 mpImpl->mpCurrentPageSpan = mpImpl->getPageSpanManager().add(propList);
768 }
769
closePageSpan()770 void OdsGenerator::closePageSpan()
771 {
772 if (!mpImpl->close(OdsGeneratorPrivate::C_PageSpan)) return;
773 }
774
defineSheetNumberingStyle(const librevenge::RVNGPropertyList & propList)775 void OdsGenerator::defineSheetNumberingStyle(const librevenge::RVNGPropertyList &propList)
776 {
777 mpImpl->getNumberingManager().addStyle(propList);
778 }
779
openSheet(const librevenge::RVNGPropertyList & propList)780 void OdsGenerator::openSheet(const librevenge::RVNGPropertyList &propList)
781 {
782 mpImpl->open(OdsGeneratorPrivate::C_Sheet);
783 OdsGeneratorPrivate::State state=mpImpl->getState();
784 state.mbInSheet=false;
785 mpImpl->pushState(state);
786 if (!mpImpl->checkOutsideOdc("openSheet") || !mpImpl->checkOutsideOdt("openSheet"))
787 return;
788 if (state.mbInSheet || state.mbInFrame || state.mbInFootnote || state.mbInComment || state.mbInHeaderFooter ||
789 mpImpl->mSheetManager.isSheetOpened())
790 {
791 ODFGEN_DEBUG_MSG(("OdsGenerator::openSheet can not be called!!!\n"));
792 return;
793 }
794
795 librevenge::RVNGPropertyList finalPropList(propList);
796 if (mpImpl->getCurrentStorage() == mpImpl->getBodyStorage())
797 {
798 if (mpImpl->mpCurrentPageSpan)
799 finalPropList.insert("style:master-page-name", mpImpl->mpCurrentPageSpan->getMasterName());
800 else
801 {
802 ODFGEN_DEBUG_MSG(("OdsGenerator::openSheet: can not find the current page\n"));
803 }
804 }
805
806 if (!mpImpl->mSheetManager.openSheet(finalPropList, Style::Z_ContentAutomatic)) return;
807 mpImpl->getState().mbInSheet=true;
808
809 SheetStyle *style=mpImpl->mSheetManager.actualSheet();
810 if (!style) return;
811 librevenge::RVNGString sTableName(style->getName());
812 auto pTableOpenElement = std::make_shared<TagOpenElement>("table:table");
813 if (propList["librevenge:sheet-name"])
814 pTableOpenElement->addAttribute("table:name", propList["librevenge:sheet-name"]->getStr());
815 else
816 pTableOpenElement->addAttribute("table:name", sTableName.cstr());
817 pTableOpenElement->addAttribute("table:style-name", sTableName.cstr());
818 mpImpl->getCurrentStorage()->push_back(pTableOpenElement);
819
820 /* TODO: open a table:shapes element
821 a environment to store the table content which must be merged in closeSheet
822 */
823 style->addColumnDefinitions(*mpImpl->getCurrentStorage());
824 }
825
closeSheet()826 void OdsGenerator::closeSheet()
827 {
828 if (!mpImpl->close(OdsGeneratorPrivate::C_Sheet))
829 return;
830 OdsGeneratorPrivate::State state=mpImpl->getState();
831 mpImpl->popState();
832 if (mpImpl->mAuxiliarOdcState || mpImpl->mAuxiliarOdtState || !state.mbInSheet) return;
833 if (state.mbInSheetShapes)
834 {
835 mpImpl->getCurrentStorage()->push_back(std::make_shared<TagCloseElement>("table:shapes"));
836 mpImpl->getState().mbInSheetShapes=false;
837 }
838 mpImpl->mSheetManager.closeSheet();
839 mpImpl->getCurrentStorage()->push_back(std::make_shared<TagCloseElement>("table:table"));
840 }
841
openSheetRow(const librevenge::RVNGPropertyList & propList)842 void OdsGenerator::openSheetRow(const librevenge::RVNGPropertyList &propList)
843 {
844 mpImpl->open(OdsGeneratorPrivate::C_SheetRow);
845 if (mpImpl->mAuxiliarOdcState || mpImpl->mAuxiliarOdtState) return;
846 OdsGeneratorPrivate::State state=mpImpl->getState();
847 SheetStyle *style=mpImpl->mSheetManager.actualSheet();
848
849 if (!state.mbInSheet || state.mbInComment || !style)
850 {
851 ODFGEN_DEBUG_MSG(("OdsGenerator::openSheetRow can not be called!!!\n"));
852 return;
853 }
854 if (state.mbInSheetShapes)
855 {
856 mpImpl->getCurrentStorage()->push_back(std::make_shared<TagCloseElement>("table:shapes"));
857 mpImpl->getState().mbInSheetShapes=false;
858 }
859
860 // check if we need to add some empty row
861 int row = propList["librevenge:row"] ? propList["librevenge:row"]->getInt() : -1;
862 if (row > state.miLastSheetRow)
863 {
864 librevenge::RVNGString sEmptyRowStyleName=style->addRow(librevenge::RVNGPropertyList());
865
866 auto pEmptyRowOpenElement = std::make_shared<TagOpenElement>("table:table-row");
867 pEmptyRowOpenElement->addAttribute("table:style-name", sEmptyRowStyleName);
868 librevenge::RVNGString numEmpty;
869 numEmpty.sprintf("%d", row-state.miLastSheetRow);
870 pEmptyRowOpenElement->addAttribute("table:number-rows-repeated", numEmpty);
871
872 mpImpl->getCurrentStorage()->push_back(pEmptyRowOpenElement);
873 mpImpl->getCurrentStorage()->push_back(std::make_shared<TagOpenElement>("table:table-cell"));
874 mpImpl->getCurrentStorage()->push_back(std::make_shared<TagCloseElement>("table:table-cell"));
875 mpImpl->getCurrentStorage()->push_back(std::make_shared<TagCloseElement>("table:table-row"));
876 }
877 else
878 row=state.miLastSheetRow;
879 int numRows=1;
880 if (propList["table:number-rows-repeated"] && propList["table:number-rows-repeated"]->getInt()>1)
881 numRows=propList["table:number-rows-repeated"]->getInt();
882 mpImpl->getState().miLastSheetRow=row+numRows;
883
884 state.miLastSheetColumn=0;
885 state.mbInSheetRow=state.mbFirstInSheetRow=true;
886 mpImpl->pushState(state);
887
888 librevenge::RVNGString sSheetRowStyleName=style->addRow(propList);
889 auto pSheetRowOpenElement = std::make_shared<TagOpenElement>("table:table-row");
890 pSheetRowOpenElement->addAttribute("table:style-name", sSheetRowStyleName);
891 if (numRows>1)
892 pSheetRowOpenElement->addAttribute("table:number-rows-repeated", propList["table:number-rows-repeated"]->getStr());
893 mpImpl->getCurrentStorage()->push_back(pSheetRowOpenElement);
894 }
895
closeSheetRow()896 void OdsGenerator::closeSheetRow()
897 {
898 if (!mpImpl->close(OdsGeneratorPrivate::C_SheetRow) || mpImpl->mAuxiliarOdcState || mpImpl->mAuxiliarOdtState) return;
899 OdsGeneratorPrivate::State state=mpImpl->getState();
900 if (!state.mbInSheetRow) return;
901 if (state.mbFirstInSheetRow)
902 {
903 auto pSheetCellOpenElement = std::make_shared<TagOpenElement>("table:table-cell");
904 pSheetCellOpenElement->addAttribute("table:number-columns-repeated","1");
905 mpImpl->getCurrentStorage()->push_back(pSheetCellOpenElement);
906 mpImpl->getCurrentStorage()->push_back(std::make_shared<TagCloseElement>("table:table-cell"));
907 }
908 mpImpl->popState();
909 mpImpl->getCurrentStorage()->push_back(std::make_shared<TagCloseElement>("table:table-row"));
910 }
911
openSheetCell(const librevenge::RVNGPropertyList & propList)912 void OdsGenerator::openSheetCell(const librevenge::RVNGPropertyList &propList)
913 {
914 mpImpl->open(OdsGeneratorPrivate::C_SheetCell);
915 if (mpImpl->mAuxiliarOdcState || mpImpl->mAuxiliarOdtState) return;
916 OdsGeneratorPrivate::State state=mpImpl->getState();
917 SheetStyle *style=mpImpl->mSheetManager.actualSheet();
918
919 if (!state.mbInSheetRow || state.mbInComment || !style)
920 {
921 ODFGEN_DEBUG_MSG(("OdsGenerator::openSheetCell can not be called!!!\n"));
922 return;
923 }
924 mpImpl->getState().mbFirstInSheetRow=false;
925 // check if we need to add empty column
926 int col = propList["librevenge:column"] ? propList["librevenge:column"]->getInt() : -1;
927 if (col > state.miLastSheetColumn)
928 {
929 auto pEmptyElement = std::make_shared<TagOpenElement>("table:table-cell");
930 librevenge::RVNGString numEmpty;
931 numEmpty.sprintf("%d", col-state.miLastSheetColumn);
932 pEmptyElement->addAttribute("table:number-columns-repeated", numEmpty);
933 mpImpl->getCurrentStorage()->push_back(pEmptyElement);
934 mpImpl->getCurrentStorage()->push_back(std::make_shared<TagCloseElement>("table:table-cell"));
935 }
936 else
937 col=state.miLastSheetColumn;
938 int numColumns=1;
939 if (propList["table:number-columns-repeated"] && propList["table:number-columns-repeated"]->getInt()>1)
940 numColumns=propList["table:number-columns-repeated"]->getInt();
941 mpImpl->getState().miLastSheetColumn=col+numColumns;
942
943 state.mbInSheetCell=true;
944 mpImpl->pushState(state);
945
946 if (propList["style:font-name"])
947 mpImpl->getFontManager().findOrAdd(propList["style:font-name"]->getStr().cstr());
948 librevenge::RVNGString sSheetCellStyleName=style->addCell(propList);
949
950 auto pSheetCellOpenElement = std::make_shared<TagOpenElement>("table:table-cell");
951 pSheetCellOpenElement->addAttribute("table:style-name", sSheetCellStyleName);
952 if (propList["table:number-columns-spanned"] && propList["table:number-columns-spanned"]->getInt()>1)
953 pSheetCellOpenElement->addAttribute("table:number-columns-spanned",
954 propList["table:number-columns-spanned"]->getStr().cstr());
955 if (propList["table:number-rows-spanned"] && propList["table:number-rows-spanned"]->getInt()>1)
956 pSheetCellOpenElement->addAttribute("table:number-rows-spanned",
957 propList["table:number-rows-spanned"]->getStr().cstr());
958 if (numColumns>1)
959 pSheetCellOpenElement->addAttribute("table:number-columns-repeated", propList["table:number-columns-repeated"]->getStr());
960 if (propList["table:number-matrix-columns-spanned"] && propList["table:number-matrix-columns-spanned"]->getInt()>1)
961 pSheetCellOpenElement->addAttribute("table:number-matrix-columns-spanned",
962 propList["table:number-matrix-columns-spanned"]->getStr().cstr());
963 if (propList["table:number-matrix-rows-spanned"] && propList["table:number-matrix-rows-spanned"]->getInt()>1)
964 pSheetCellOpenElement->addAttribute("table:number-matrix-rows-spanned",
965 propList["table:number-matrix-rows-spanned"]->getStr().cstr());
966
967 if (propList["librevenge:value-type"])
968 {
969 std::string valueType(propList["librevenge:value-type"]->getStr().cstr());
970 if (valueType=="double" || valueType=="scientific") valueType="float";
971 else if (valueType=="percent") valueType="percentage";
972 if (valueType=="float" || valueType=="percentage" || valueType=="currency")
973 {
974 pSheetCellOpenElement->addAttribute("calcext:value-type", valueType.c_str());
975 pSheetCellOpenElement->addAttribute("office:value-type", valueType.c_str());
976 if (propList["librevenge:value"])
977 {
978 if (!strncmp(propList["librevenge:value"]->getStr().cstr(),"nan",3) ||
979 !strncmp(propList["librevenge:value"]->getStr().cstr(),"NAN",3))
980 {
981 pSheetCellOpenElement->addAttribute("office:string-value", "");
982 pSheetCellOpenElement->addAttribute("office:value-type", "string");
983 pSheetCellOpenElement->addAttribute("calcext:value-type", "error");
984 }
985 else
986 {
987 // we need the maximum precision here, so we must avoid getStr() when possible
988 librevenge::RVNGString value;
989 if (propList["librevenge:value"]->getUnit()==librevenge::RVNG_GENERIC)
990 value = makePreciseStr(propList["librevenge:value"]->getDouble());
991 else if (propList["librevenge:value"]->getUnit()==librevenge::RVNG_PERCENT)
992 {
993 value = makePreciseStr(propList["librevenge:value"]->getDouble()*100.);
994 value.append('%');
995 }
996 else
997 value=propList["librevenge:value"]->getStr();
998 pSheetCellOpenElement->addAttribute("office:value-type", valueType.c_str());
999 pSheetCellOpenElement->addAttribute("office:value", value.cstr());
1000 }
1001 }
1002 }
1003 else if (valueType=="string" || valueType=="text")
1004 {
1005 pSheetCellOpenElement->addAttribute("office:value-type", "string");
1006 pSheetCellOpenElement->addAttribute("calcext:value-type", "string");
1007 }
1008 else if (valueType=="bool" || valueType=="boolean")
1009 {
1010 pSheetCellOpenElement->addAttribute("office:value-type", "boolean");
1011 pSheetCellOpenElement->addAttribute("calcext:value-type", "boolean");
1012 if (propList["librevenge:value"])
1013 pSheetCellOpenElement->addAttribute("office:boolean-value", propList["librevenge:value"]->getStr().cstr());
1014 }
1015 else if (valueType=="date")
1016 {
1017 pSheetCellOpenElement->addAttribute("office:value-type", "date");
1018 pSheetCellOpenElement->addAttribute("calcext:value-type", "date");
1019 if (propList["librevenge:day"] && propList["librevenge:month"] && propList["librevenge:year"])
1020 {
1021 librevenge::RVNGString date;
1022 if (propList["librevenge:hours"])
1023 {
1024 int minute=propList["librevenge:minutes"] ? propList["librevenge:minutes"]->getInt() : 0;
1025 int second=propList["librevenge:seconds"] ? propList["librevenge:seconds"]->getInt() : 0;
1026 date.sprintf("%04d-%02d-%02dT%02d:%02d:%02d", propList["librevenge:year"]->getInt(),
1027 propList["librevenge:month"]->getInt(), propList["librevenge:day"]->getInt(),
1028 propList["librevenge:hours"]->getInt(), minute, second);
1029 }
1030 else
1031 date.sprintf("%04d-%02d-%02d", propList["librevenge:year"]->getInt(),
1032 propList["librevenge:month"]->getInt(), propList["librevenge:day"]->getInt());
1033 pSheetCellOpenElement->addAttribute("office:date-value", date);
1034 }
1035 }
1036 else if (valueType=="time")
1037 {
1038 pSheetCellOpenElement->addAttribute("office:value-type", "time");
1039 pSheetCellOpenElement->addAttribute("calcext:value-type", "time");
1040 if (propList["librevenge:hours"])
1041 {
1042 int minute=propList["librevenge:minutes"] ? propList["librevenge:minutes"]->getInt() : 0;
1043 int second=propList["librevenge:seconds"] ? propList["librevenge:seconds"]->getInt() : 0;
1044 librevenge::RVNGString time;
1045 time.sprintf("PT%02dH%02dM%02dS", propList["librevenge:hours"]->getInt(), minute, second);
1046 pSheetCellOpenElement->addAttribute("office:time-value", time);
1047 }
1048 }
1049 else
1050 {
1051 ODFGEN_DEBUG_MSG(("OdsGenerator::openSheetCell: unexpected value type: %s\n", valueType.c_str()));
1052 }
1053 }
1054 librevenge::RVNGPropertyListVector const *formula=propList.child("librevenge:formula");
1055 if (formula)
1056 {
1057 librevenge::RVNGString finalFormula=SheetManager::convertFormula(*formula);
1058 if (!finalFormula.empty())
1059 pSheetCellOpenElement->addAttribute("table:formula", finalFormula);
1060 }
1061 mpImpl->getCurrentStorage()->push_back(pSheetCellOpenElement);
1062 }
1063
closeSheetCell()1064 void OdsGenerator::closeSheetCell()
1065 {
1066 if (!mpImpl->close(OdsGeneratorPrivate::C_SheetCell) || mpImpl->mAuxiliarOdcState || mpImpl->mAuxiliarOdtState) return;
1067 if (!mpImpl->getState().mbInSheetCell) return;
1068
1069 mpImpl->popState();
1070 mpImpl->getCurrentStorage()->push_back(std::make_shared<TagCloseElement>("table:table-cell"));
1071 }
1072
defineChartStyle(const librevenge::RVNGPropertyList & propList)1073 void OdsGenerator::defineChartStyle(const librevenge::RVNGPropertyList &propList)
1074 {
1075 mpImpl->defineChartStyle(propList);
1076 if (mpImpl->mAuxiliarOdcState)
1077 return mpImpl->mAuxiliarOdcState->get().defineChartStyle(propList);
1078 }
1079
openChart(const librevenge::RVNGPropertyList & propList)1080 void OdsGenerator::openChart(const librevenge::RVNGPropertyList &propList)
1081 {
1082 mpImpl->open(OdsGeneratorPrivate::C_Chart);
1083 OdsGeneratorPrivate::State state=mpImpl->getState();
1084 mpImpl->pushState(state);
1085 if (!mpImpl->checkOutsideOdc("openChart") || !mpImpl->checkOutsideOdt("openChart"))
1086 return;
1087 if (!state.mbFirstInFrame)
1088 {
1089 ODFGEN_DEBUG_MSG(("OdsGenerator::openChart must be called in a frame!!!\n"));
1090 return;
1091 }
1092 if (mpImpl->createAuxiliarOdcGenerator())
1093 {
1094 mpImpl->getState().mbInChart=true;
1095 mpImpl->getState().mbNewOdcGenerator=true;
1096 return mpImpl->mAuxiliarOdcState->get().openChart(propList);
1097 }
1098 }
1099
closeChart()1100 void OdsGenerator::closeChart()
1101 {
1102 if (!mpImpl->close(OdsGeneratorPrivate::C_Chart)) return;
1103 OdsGeneratorPrivate::State state=mpImpl->getState();
1104 mpImpl->popState();
1105 if (!mpImpl->mAuxiliarOdcState || !state.mbInChart) return;
1106 if (state.mbNewOdcGenerator)
1107 {
1108 mpImpl->mAuxiliarOdcState->get().closeChart();
1109 mpImpl->sendAuxiliarOdcGenerator();
1110 mpImpl->resetAuxiliarOdcGenerator();
1111 }
1112 }
1113
openChartPlotArea(const librevenge::RVNGPropertyList & propList)1114 void OdsGenerator::openChartPlotArea(const librevenge::RVNGPropertyList &propList)
1115 {
1116 mpImpl->open(OdsGeneratorPrivate::C_ChartPlotArea);
1117 OdsGeneratorPrivate::State state=mpImpl->getState();
1118 mpImpl->pushState(state);
1119 if (!mpImpl->mAuxiliarOdcState || !state.mbInChart)
1120 {
1121 ODFGEN_DEBUG_MSG(("OdsGenerator::openChartPlotArea called outside chart!!!\n"));
1122 return;
1123 }
1124 mpImpl->mAuxiliarOdcState->get().openChartPlotArea(propList);
1125 }
1126
closeChartPlotArea()1127 void OdsGenerator::closeChartPlotArea()
1128 {
1129 if (!mpImpl->close(OdsGeneratorPrivate::C_ChartPlotArea)) return;
1130 OdsGeneratorPrivate::State state=mpImpl->getState();
1131 mpImpl->popState();
1132 if (!mpImpl->mAuxiliarOdcState || !state.mbInChart) return;
1133 mpImpl->mAuxiliarOdcState->get().closeChartPlotArea();
1134 }
1135
openChartTextObject(const librevenge::RVNGPropertyList & propList)1136 void OdsGenerator::openChartTextObject(const librevenge::RVNGPropertyList &propList)
1137 {
1138 mpImpl->open(OdsGeneratorPrivate::C_ChartTextObject);
1139 OdsGeneratorPrivate::State state=mpImpl->getState();
1140 mpImpl->pushState(state);
1141 if (!mpImpl->mAuxiliarOdcState || !state.mbInChart)
1142 {
1143 ODFGEN_DEBUG_MSG(("OdsGenerator::openChartTextObject called outside chart!!!\n"));
1144 return;
1145 }
1146 mpImpl->mAuxiliarOdcState->get().openChartTextObject(propList);
1147 }
1148
closeChartTextObject()1149 void OdsGenerator::closeChartTextObject()
1150 {
1151 if (!mpImpl->close(OdsGeneratorPrivate::C_ChartTextObject)) return;
1152 OdsGeneratorPrivate::State state=mpImpl->getState();
1153 mpImpl->popState();
1154 if (!mpImpl->mAuxiliarOdcState || !state.mbInChart) return;
1155 mpImpl->mAuxiliarOdcState->get().closeChartTextObject();
1156 }
1157
insertChartAxis(const librevenge::RVNGPropertyList & axis)1158 void OdsGenerator::insertChartAxis(const librevenge::RVNGPropertyList &axis)
1159 {
1160 if (mpImpl->mAuxiliarOdtState) return;
1161 if (!mpImpl->mAuxiliarOdcState || !mpImpl->getState().mbInChart)
1162 {
1163 ODFGEN_DEBUG_MSG(("OdsGenerator::insertChartAxis call outside chart\n"));
1164 return;
1165 }
1166 mpImpl->mAuxiliarOdcState->get().insertChartAxis(axis);
1167 }
1168
openChartSerie(const librevenge::RVNGPropertyList & serie)1169 void OdsGenerator::openChartSerie(const librevenge::RVNGPropertyList &serie)
1170 {
1171 mpImpl->open(OdsGeneratorPrivate::C_ChartSerie);
1172 if (!mpImpl->mAuxiliarOdcState || !mpImpl->getState().mbInChart)
1173 {
1174 ODFGEN_DEBUG_MSG(("OdsGenerator::openChartSerie call outside chart\n"));
1175 return;
1176 }
1177 mpImpl->mAuxiliarOdcState->get().openChartSerie(serie);
1178 }
1179
closeChartSerie()1180 void OdsGenerator::closeChartSerie()
1181 {
1182 if (!mpImpl->close(OdsGeneratorPrivate::C_ChartSerie)) return;
1183 OdsGeneratorPrivate::State state=mpImpl->getState();
1184 if (!mpImpl->mAuxiliarOdcState || !state.mbInChart) return;
1185 mpImpl->mAuxiliarOdcState->get().closeChartSerie();
1186 }
1187
openHeader(const librevenge::RVNGPropertyList & propList)1188 void OdsGenerator::openHeader(const librevenge::RVNGPropertyList &propList)
1189 {
1190 mpImpl->open(OdsGeneratorPrivate::C_Header);
1191 OdsGeneratorPrivate::State state=mpImpl->getState();
1192 state.mbInHeaderFooter=true;
1193 mpImpl->pushState(state);
1194 if (mpImpl->mAuxiliarOdcState || mpImpl->mAuxiliarOdtState) return;
1195
1196 if (mpImpl->inHeaderFooter() || !mpImpl->mpCurrentPageSpan)
1197 {
1198 ODFGEN_DEBUG_MSG(("OdsGenerator::openHeader: can not open a header\n"));
1199 return;
1200 }
1201 mpImpl->startHeaderFooter(true, propList);
1202 if (!mpImpl->inHeaderFooter())
1203 return;
1204
1205 auto pHeaderFooterContentElements = std::make_shared<libodfgen::DocumentElementVector>();
1206 if (propList["librevenge:occurrence"] && (propList["librevenge:occurrence"]->getStr() == "even" ||
1207 propList["librevenge:occurrence"]->getStr() == "left"))
1208 mpImpl->mpCurrentPageSpan->setHeaderLeftContent(pHeaderFooterContentElements);
1209 else if (propList["librevenge:occurrence"] && propList["librevenge:occurrence"]->getStr() == "first")
1210 mpImpl->mpCurrentPageSpan->setHeaderFirstContent(pHeaderFooterContentElements);
1211 else if (propList["librevenge:occurrence"] && propList["librevenge:occurrence"]->getStr() == "last")
1212 mpImpl->mpCurrentPageSpan->setHeaderLastContent(pHeaderFooterContentElements);
1213 else
1214 mpImpl->mpCurrentPageSpan->setHeaderContent(pHeaderFooterContentElements);
1215 mpImpl->pushStorage(pHeaderFooterContentElements);
1216 }
1217
closeHeader()1218 void OdsGenerator::closeHeader()
1219 {
1220 if (!mpImpl->close(OdsGeneratorPrivate::C_Header)) return;
1221 mpImpl->popState();
1222 if (mpImpl->mAuxiliarOdcState || mpImpl->mAuxiliarOdtState) return;
1223 if (!mpImpl->inHeaderFooter())
1224 {
1225 ODFGEN_DEBUG_MSG(("OdsGenerator::closeHeader: no header/footer is already opened\n"));
1226 return;
1227 }
1228 mpImpl->endHeaderFooter();
1229 mpImpl->popStorage();
1230 }
1231
openFooter(const librevenge::RVNGPropertyList & propList)1232 void OdsGenerator::openFooter(const librevenge::RVNGPropertyList &propList)
1233 {
1234 mpImpl->open(OdsGeneratorPrivate::C_Footer);
1235 OdsGeneratorPrivate::State state=mpImpl->getState();
1236 state.mbInHeaderFooter=true;
1237 mpImpl->pushState(state);
1238 if (mpImpl->mAuxiliarOdcState || mpImpl->mAuxiliarOdtState) return;
1239
1240 if (mpImpl->inHeaderFooter() || !mpImpl->mpCurrentPageSpan)
1241 {
1242 ODFGEN_DEBUG_MSG(("OdtGenerator::openFooter: can not open a footer\n"));
1243 return;
1244 }
1245 mpImpl->startHeaderFooter(false, propList);
1246 if (!mpImpl->inHeaderFooter())
1247 return;
1248
1249 auto pHeaderFooterContentElements = std::make_shared<libodfgen::DocumentElementVector>();
1250 if (propList["librevenge:occurrence"] && (propList["librevenge:occurrence"]->getStr() == "even" ||
1251 propList["librevenge:occurrence"]->getStr() == "left"))
1252 mpImpl->mpCurrentPageSpan->setFooterLeftContent(pHeaderFooterContentElements);
1253 else if (propList["librevenge:occurrence"] && propList["librevenge:occurrence"]->getStr() == "first")
1254 mpImpl->mpCurrentPageSpan->setFooterFirstContent(pHeaderFooterContentElements);
1255 else if (propList["librevenge:occurrence"] && propList["librevenge:occurrence"]->getStr() == "last")
1256 mpImpl->mpCurrentPageSpan->setFooterLastContent(pHeaderFooterContentElements);
1257 else
1258 mpImpl->mpCurrentPageSpan->setFooterContent(pHeaderFooterContentElements);
1259 mpImpl->pushStorage(pHeaderFooterContentElements);
1260 }
1261
closeFooter()1262 void OdsGenerator::closeFooter()
1263 {
1264 if (!mpImpl->close(OdsGeneratorPrivate::C_Footer)) return;
1265 mpImpl->popState();
1266 if (mpImpl->mAuxiliarOdcState || mpImpl->mAuxiliarOdtState) return;
1267
1268 if (!mpImpl->inHeaderFooter())
1269 {
1270 ODFGEN_DEBUG_MSG(("OdtGenerator::closeFooter: no header/footer is already opened\n"));
1271 return;
1272 }
1273 mpImpl->endHeaderFooter();
1274 mpImpl->popStorage();
1275 }
1276
openSection(const librevenge::RVNGPropertyList & propList)1277 void OdsGenerator::openSection(const librevenge::RVNGPropertyList &propList)
1278 {
1279 mpImpl->open(OdsGeneratorPrivate::C_Section);
1280 if (mpImpl->mAuxiliarOdtState)
1281 return mpImpl->mAuxiliarOdtState->get().openSection(propList);
1282 ODFGEN_DEBUG_MSG(("OdsGenerator::openSection ignored\n"));
1283 }
1284
closeSection()1285 void OdsGenerator::closeSection()
1286 {
1287 if (!mpImpl->close(OdsGeneratorPrivate::C_Section)) return;
1288 if (mpImpl->mAuxiliarOdtState)
1289 return mpImpl->mAuxiliarOdtState->get().closeSection();
1290 }
1291
defineParagraphStyle(const librevenge::RVNGPropertyList & propList)1292 void OdsGenerator::defineParagraphStyle(const librevenge::RVNGPropertyList &propList)
1293 {
1294 mpImpl->defineParagraphStyle(propList);
1295 if (mpImpl->mAuxiliarOdcState)
1296 return mpImpl->mAuxiliarOdcState->get().defineParagraphStyle(propList);
1297 if (mpImpl->mAuxiliarOdtState)
1298 return mpImpl->mAuxiliarOdtState->get().defineParagraphStyle(propList);
1299 }
1300
openParagraph(const librevenge::RVNGPropertyList & propList)1301 void OdsGenerator::openParagraph(const librevenge::RVNGPropertyList &propList)
1302 {
1303 mpImpl->open(OdsGeneratorPrivate::C_Paragraph);
1304 if (mpImpl->mAuxiliarOdcState)
1305 return mpImpl->mAuxiliarOdcState->get().openParagraph(propList);
1306 if (mpImpl->mAuxiliarOdtState)
1307 return mpImpl->mAuxiliarOdtState->get().openParagraph(propList);
1308
1309 if (!mpImpl->canWriteText())
1310 {
1311 ODFGEN_DEBUG_MSG(("OdsGenerator::openParagraph: calls outside a text zone\n"));
1312 return;
1313 }
1314
1315 librevenge::RVNGPropertyList finalPropList(propList);
1316 if (mpImpl->getState().mbInSheetCell)
1317 finalPropList.insert("style:parent-style-name", "Table_Contents");
1318 else
1319 finalPropList.insert("style:parent-style-name", "Standard");
1320 mpImpl->openParagraph(finalPropList);
1321 }
1322
closeParagraph()1323 void OdsGenerator::closeParagraph()
1324 {
1325 if (!mpImpl->close(OdsGeneratorPrivate::C_Paragraph)) return;
1326 if (mpImpl->mAuxiliarOdcState)
1327 return mpImpl->mAuxiliarOdcState->get().closeParagraph();
1328 if (mpImpl->mAuxiliarOdtState)
1329 return mpImpl->mAuxiliarOdtState->get().closeParagraph();
1330 if (!mpImpl->canWriteText())
1331 return;
1332 mpImpl->closeParagraph();
1333 }
1334
defineCharacterStyle(const librevenge::RVNGPropertyList & propList)1335 void OdsGenerator::defineCharacterStyle(const librevenge::RVNGPropertyList &propList)
1336 {
1337 mpImpl->defineCharacterStyle(propList);
1338 if (mpImpl->mAuxiliarOdcState)
1339 return mpImpl->mAuxiliarOdcState->get().defineCharacterStyle(propList);
1340 if (mpImpl->mAuxiliarOdtState)
1341 return mpImpl->mAuxiliarOdtState->get().defineCharacterStyle(propList);
1342 }
1343
openSpan(const librevenge::RVNGPropertyList & propList)1344 void OdsGenerator::openSpan(const librevenge::RVNGPropertyList &propList)
1345 {
1346 mpImpl->open(OdsGeneratorPrivate::C_Span);
1347 if (mpImpl->mAuxiliarOdcState)
1348 return mpImpl->mAuxiliarOdcState->get().openSpan(propList);
1349 if (mpImpl->mAuxiliarOdtState)
1350 return mpImpl->mAuxiliarOdtState->get().openSpan(propList);
1351
1352 if (!mpImpl->canWriteText())
1353 {
1354 ODFGEN_DEBUG_MSG(("OdsGenerator::openSpan: not in text part\n"));
1355 return;
1356 }
1357 mpImpl->openSpan(propList);
1358 }
1359
closeSpan()1360 void OdsGenerator::closeSpan()
1361 {
1362 if (!mpImpl->close(OdsGeneratorPrivate::C_Span)) return;
1363 if (mpImpl->mAuxiliarOdcState)
1364 return mpImpl->mAuxiliarOdcState->get().closeSpan();
1365 if (mpImpl->mAuxiliarOdtState)
1366 return mpImpl->mAuxiliarOdtState->get().closeSpan();
1367 if (!mpImpl->canWriteText()) return;
1368 mpImpl->closeSpan();
1369 }
1370
openLink(const librevenge::RVNGPropertyList & propList)1371 void OdsGenerator::openLink(const librevenge::RVNGPropertyList &propList)
1372 {
1373 if (mpImpl->mAuxiliarOdcState)
1374 return mpImpl->mAuxiliarOdcState->get().openLink(propList);
1375 if (mpImpl->mAuxiliarOdtState)
1376 return mpImpl->mAuxiliarOdtState->get().openLink(propList);
1377 mpImpl->openLink(propList);
1378 }
1379
closeLink()1380 void OdsGenerator::closeLink()
1381 {
1382 if (mpImpl->mAuxiliarOdcState)
1383 return mpImpl->mAuxiliarOdcState->get().closeLink();
1384 if (mpImpl->mAuxiliarOdtState)
1385 return mpImpl->mAuxiliarOdtState->get().closeLink();
1386 mpImpl->closeLink();
1387 }
1388
1389
openOrderedListLevel(const librevenge::RVNGPropertyList & propList)1390 void OdsGenerator::openOrderedListLevel(const librevenge::RVNGPropertyList &propList)
1391 {
1392 mpImpl->open(OdsGeneratorPrivate::C_OrderedList);
1393 if (mpImpl->mAuxiliarOdcState)
1394 return mpImpl->mAuxiliarOdcState->get().openOrderedListLevel(propList);
1395 if (mpImpl->mAuxiliarOdtState)
1396 return mpImpl->mAuxiliarOdtState->get().openOrderedListLevel(propList);
1397 if (mpImpl->canWriteText() && !mpImpl->getState().mbInSheetCell)
1398 return mpImpl->openListLevel(propList,true);
1399 ODFGEN_DEBUG_MSG(("OdsGenerator::openOrderedListLevel: call outside a text zone\n"));
1400 }
1401
openUnorderedListLevel(const librevenge::RVNGPropertyList & propList)1402 void OdsGenerator::openUnorderedListLevel(const librevenge::RVNGPropertyList &propList)
1403 {
1404 mpImpl->open(OdsGeneratorPrivate::C_UnorderedList);
1405 if (mpImpl->mAuxiliarOdcState)
1406 return mpImpl->mAuxiliarOdcState->get().openUnorderedListLevel(propList);
1407 if (mpImpl->mAuxiliarOdtState)
1408 return mpImpl->mAuxiliarOdtState->get().openUnorderedListLevel(propList);
1409 if (mpImpl->canWriteText() && !mpImpl->getState().mbInSheetCell)
1410 return mpImpl->openListLevel(propList,false);
1411 ODFGEN_DEBUG_MSG(("OdsGenerator::openUnorderedListLevel: call outside a text zone\n"));
1412 }
1413
closeOrderedListLevel()1414 void OdsGenerator::closeOrderedListLevel()
1415 {
1416 if (!mpImpl->close(OdsGeneratorPrivate::C_OrderedList)) return;
1417 if (mpImpl->mAuxiliarOdcState)
1418 mpImpl->mAuxiliarOdcState->get().closeOrderedListLevel();
1419 if (mpImpl->mAuxiliarOdtState)
1420 mpImpl->mAuxiliarOdtState->get().closeOrderedListLevel();
1421 if (mpImpl->canWriteText() && !mpImpl->getState().mbInSheetCell)
1422 return mpImpl->closeListLevel();
1423 }
1424
closeUnorderedListLevel()1425 void OdsGenerator::closeUnorderedListLevel()
1426 {
1427 if (!mpImpl->close(OdsGeneratorPrivate::C_UnorderedList)) return;
1428 if (mpImpl->mAuxiliarOdcState)
1429 mpImpl->mAuxiliarOdcState->get().closeUnorderedListLevel();
1430 if (mpImpl->mAuxiliarOdtState)
1431 mpImpl->mAuxiliarOdtState->get().closeUnorderedListLevel();
1432 if (mpImpl->canWriteText() && !mpImpl->getState().mbInSheetCell)
1433 return mpImpl->closeListLevel();
1434 }
1435
openListElement(const librevenge::RVNGPropertyList & propList)1436 void OdsGenerator::openListElement(const librevenge::RVNGPropertyList &propList)
1437 {
1438 mpImpl->open(OdsGeneratorPrivate::C_ListElement);
1439 if (mpImpl->mAuxiliarOdcState)
1440 return mpImpl->mAuxiliarOdcState->get().openListElement(propList);
1441 if (mpImpl->mAuxiliarOdtState)
1442 return mpImpl->mAuxiliarOdtState->get().openListElement(propList);
1443 if (mpImpl->canWriteText())
1444 {
1445 if (mpImpl->getState().mbInSheetCell)
1446 return mpImpl->openParagraph(propList);
1447 return mpImpl->openListElement(propList);
1448 }
1449
1450 ODFGEN_DEBUG_MSG(("OdsGenerator::openListElement call outside a text zone\n"));
1451 return;
1452 }
1453
closeListElement()1454 void OdsGenerator::closeListElement()
1455 {
1456 if (!mpImpl->close(OdsGeneratorPrivate::C_ListElement)) return;
1457 if (mpImpl->mAuxiliarOdcState)
1458 return mpImpl->mAuxiliarOdcState->get().closeListElement();
1459 if (mpImpl->mAuxiliarOdtState)
1460 return mpImpl->mAuxiliarOdtState->get().closeListElement();
1461 if (mpImpl->canWriteText())
1462 {
1463 if (mpImpl->getState().mbInSheetCell)
1464 return mpImpl->closeParagraph();
1465 return mpImpl->closeListElement();
1466 }
1467 }
1468
openFootnote(const librevenge::RVNGPropertyList & propList)1469 void OdsGenerator::openFootnote(const librevenge::RVNGPropertyList &propList)
1470 {
1471 mpImpl->open(OdsGeneratorPrivate::C_Footnote);
1472 OdsGeneratorPrivate::State state=mpImpl->getState();
1473 state.mbInFootnote=true;
1474 mpImpl->pushState(state);
1475
1476 if (mpImpl->mAuxiliarOdtState)
1477 return mpImpl->mAuxiliarOdtState->get().openFootnote(propList);
1478 ODFGEN_DEBUG_MSG(("OdsGenerator::openFootnote ignored\n"));
1479 }
1480
closeFootnote()1481 void OdsGenerator::closeFootnote()
1482 {
1483 if (!mpImpl->close(OdsGeneratorPrivate::C_Footnote)) return;
1484 mpImpl->popState();
1485
1486 if (mpImpl->mAuxiliarOdtState)
1487 return mpImpl->mAuxiliarOdtState->get().closeFootnote();
1488 }
1489
openComment(const librevenge::RVNGPropertyList & propList)1490 void OdsGenerator::openComment(const librevenge::RVNGPropertyList &propList)
1491 {
1492 mpImpl->open(OdsGeneratorPrivate::C_Comment);
1493 OdsGeneratorPrivate::State state=mpImpl->getState();
1494 mpImpl->getState().mbInComment=false;
1495 mpImpl->pushState(state);
1496
1497 if (mpImpl->mAuxiliarOdtState)
1498 return mpImpl->mAuxiliarOdtState->get().openComment(propList);
1499 if (!mpImpl->checkOutsideOdc("openComment"))
1500 return;
1501 if (!state.mbInSheetCell)
1502 {
1503 ODFGEN_DEBUG_MSG(("OdsGenerator::openComment call outside a sheet cell!!!\n"));
1504 return;
1505 }
1506
1507 mpImpl->getState().mbInComment=true;
1508 mpImpl->pushListState();
1509
1510 mpImpl->getCurrentStorage()->push_back(std::make_shared<TagOpenElement>("office:annotation"));
1511 }
1512
closeComment()1513 void OdsGenerator::closeComment()
1514 {
1515 if (!mpImpl->close(OdsGeneratorPrivate::C_Comment)) return;
1516 OdsGeneratorPrivate::State state=mpImpl->getState();
1517 mpImpl->popState();
1518
1519 if (mpImpl->mAuxiliarOdtState)
1520 return mpImpl->mAuxiliarOdtState->get().closeComment();
1521
1522 if (mpImpl->mAuxiliarOdcState || !state.mbInComment) return;
1523 mpImpl->popListState();
1524 mpImpl->getCurrentStorage()->push_back(std::make_shared<TagCloseElement>("office:annotation"));
1525 }
1526
openTable(const librevenge::RVNGPropertyList & propList)1527 void OdsGenerator::openTable(const librevenge::RVNGPropertyList &propList)
1528 {
1529 OdsGeneratorPrivate::State state=mpImpl->getState();
1530 mpImpl->open(OdsGeneratorPrivate::C_Table);
1531 state.mbInTable=true;
1532 mpImpl->pushState(state);
1533 if (mpImpl->mAuxiliarOdtState)
1534 return mpImpl->mAuxiliarOdtState->get().openTable(propList);
1535 if (!mpImpl->checkOutsideOdc("openTable"))
1536 return;
1537 if (!state.mbInFrame)
1538 {
1539 ODFGEN_DEBUG_MSG(("OdsGenerator::openTable a table must be in a frame!!!\n"));
1540 return;
1541 }
1542 if (mpImpl->createAuxiliarOdtGenerator())
1543 {
1544 mpImpl->getState().mbNewOdtGenerator=true;
1545 return mpImpl->mAuxiliarOdtState->get().openTable(propList);
1546 }
1547 }
1548
closeTable()1549 void OdsGenerator::closeTable()
1550 {
1551 if (!mpImpl->close(OdsGeneratorPrivate::C_Table)) return;
1552 OdsGeneratorPrivate::State state=mpImpl->getState();
1553 mpImpl->popState();
1554 if (mpImpl->mAuxiliarOdcState || !state.mbInTable || !mpImpl->mAuxiliarOdtState) return;
1555 mpImpl->mAuxiliarOdtState->get().closeTable();
1556 if (state.mbNewOdtGenerator)
1557 {
1558 mpImpl->sendAuxiliarOdtGenerator();
1559 mpImpl->resetAuxiliarOdtGenerator();
1560 }
1561 }
1562
openTableRow(const librevenge::RVNGPropertyList & propList)1563 void OdsGenerator::openTableRow(const librevenge::RVNGPropertyList &propList)
1564 {
1565 mpImpl->open(OdsGeneratorPrivate::C_TableRow);
1566 if (mpImpl->mAuxiliarOdcState) return;
1567 if (mpImpl->mAuxiliarOdtState)
1568 return mpImpl->mAuxiliarOdtState->get().openTableRow(propList);
1569 }
1570
closeTableRow()1571 void OdsGenerator::closeTableRow()
1572 {
1573 if (!mpImpl->close(OdsGeneratorPrivate::C_TableRow)) return;
1574 if (mpImpl->mAuxiliarOdcState) return;
1575 if (mpImpl->mAuxiliarOdtState)
1576 return mpImpl->mAuxiliarOdtState->get().closeTableRow();
1577 }
1578
openTableCell(const librevenge::RVNGPropertyList & propList)1579 void OdsGenerator::openTableCell(const librevenge::RVNGPropertyList &propList)
1580 {
1581 mpImpl->open(OdsGeneratorPrivate::C_TableCell);
1582 if (mpImpl->mAuxiliarOdcState) return;
1583 if (mpImpl->mAuxiliarOdtState)
1584 return mpImpl->mAuxiliarOdtState->get().openTableCell(propList);
1585 }
1586
closeTableCell()1587 void OdsGenerator::closeTableCell()
1588 {
1589 if (!mpImpl->close(OdsGeneratorPrivate::C_TableCell)) return;
1590 if (mpImpl->mAuxiliarOdcState) return;
1591 if (mpImpl->mAuxiliarOdtState)
1592 return mpImpl->mAuxiliarOdtState->get().closeTableCell();
1593 }
1594
insertCoveredTableCell(const librevenge::RVNGPropertyList & propList)1595 void OdsGenerator::insertCoveredTableCell(const librevenge::RVNGPropertyList &propList)
1596 {
1597 if (mpImpl->mAuxiliarOdcState) return;
1598 if (mpImpl->mAuxiliarOdtState)
1599 return mpImpl->mAuxiliarOdtState->get().insertCoveredTableCell(propList);
1600 }
1601
1602
insertTab()1603 void OdsGenerator::insertTab()
1604 {
1605 if (mpImpl->mAuxiliarOdcState)
1606 return mpImpl->mAuxiliarOdcState->get().insertTab();
1607 if (mpImpl->mAuxiliarOdtState)
1608 return mpImpl->mAuxiliarOdtState->get().insertTab();
1609 if (!mpImpl->canWriteText())
1610 return;
1611 mpImpl->insertTab();
1612 }
1613
insertSpace()1614 void OdsGenerator::insertSpace()
1615 {
1616 if (mpImpl->mAuxiliarOdcState)
1617 return mpImpl->mAuxiliarOdcState->get().insertSpace();
1618 if (mpImpl->mAuxiliarOdtState)
1619 return mpImpl->mAuxiliarOdtState->get().insertSpace();
1620 if (!mpImpl->canWriteText())
1621 return;
1622 mpImpl->insertSpace();
1623 }
1624
insertLineBreak()1625 void OdsGenerator::insertLineBreak()
1626 {
1627 if (mpImpl->mAuxiliarOdcState)
1628 return mpImpl->mAuxiliarOdcState->get().insertLineBreak();
1629 if (mpImpl->mAuxiliarOdtState)
1630 return mpImpl->mAuxiliarOdtState->get().insertLineBreak();
1631 if (!mpImpl->canWriteText())
1632 return;
1633 mpImpl->insertLineBreak(mpImpl->getState().mbInSheetCell);
1634 }
1635
insertField(const librevenge::RVNGPropertyList & propList)1636 void OdsGenerator::insertField(const librevenge::RVNGPropertyList &propList)
1637 {
1638 if (!propList["librevenge:field-type"] || propList["librevenge:field-type"]->getStr().empty())
1639 return;
1640 if (mpImpl->mAuxiliarOdcState)
1641 return mpImpl->mAuxiliarOdcState->get().insertField(propList);
1642 if (mpImpl->mAuxiliarOdtState)
1643 return mpImpl->mAuxiliarOdtState->get().insertField(propList);
1644 mpImpl->insertField(propList);
1645 }
1646
insertText(const librevenge::RVNGString & text)1647 void OdsGenerator::insertText(const librevenge::RVNGString &text)
1648 {
1649 if (mpImpl->mAuxiliarOdcState)
1650 return mpImpl->mAuxiliarOdcState->get().insertText(text);
1651 if (mpImpl->mAuxiliarOdtState)
1652 return mpImpl->mAuxiliarOdtState->get().insertText(text);
1653 if (mpImpl->canWriteText())
1654 return mpImpl->insertText(text);
1655 ODFGEN_DEBUG_MSG(("OdsGenerator::insertText ignored\n"));
1656 }
1657
openFrame(const librevenge::RVNGPropertyList & propList)1658 void OdsGenerator::openFrame(const librevenge::RVNGPropertyList &propList)
1659 {
1660 mpImpl->open(OdsGeneratorPrivate::C_Frame);
1661 OdsGeneratorPrivate::State &prevState=mpImpl->getState();
1662 OdsGeneratorPrivate::State state=prevState;
1663 state.mbInFrame=state.mbFirstInFrame=true;
1664 mpImpl->pushState(state);
1665 mpImpl->pushListState();
1666 if (mpImpl->mAuxiliarOdtState)
1667 return mpImpl->mAuxiliarOdtState->get().openFrame(propList);
1668 if (!mpImpl->checkOutsideOdc("openFrame"))
1669 return;
1670 if (!state.mbInSheet || state.mbInComment)
1671 {
1672 ODFGEN_DEBUG_MSG(("OdsGenerator::openFrame call outside a sheet!!!\n"));
1673 return;
1674 }
1675
1676 if (!state.mbInSheetRow && !state.mbInSheetShapes)
1677 {
1678 mpImpl->getCurrentStorage()->push_back(std::make_shared<TagOpenElement>("table:shapes"));
1679 mpImpl->getState().mbInSheetShapes=prevState.mbInSheetShapes=true;
1680 }
1681
1682 librevenge::RVNGPropertyList pList(propList);
1683 if (!state.mbInSheetCell && propList["table:end-cell-address"])
1684 pList.remove("table:end-cell-address");
1685 if (!propList["text:anchor-type"] && !pList["table:end-cell-address"])
1686 pList.insert("text:anchor-type","paragraph");
1687 mpImpl->openFrame(pList);
1688 }
1689
closeFrame()1690 void OdsGenerator::closeFrame()
1691 {
1692 if (!mpImpl->close(OdsGeneratorPrivate::C_Frame)) return;
1693 OdsGeneratorPrivate::State state=mpImpl->getState();
1694 mpImpl->popListState();
1695 mpImpl->popState();
1696 if (mpImpl->mAuxiliarOdtState)
1697 return mpImpl->mAuxiliarOdtState->get().closeFrame();
1698 if (mpImpl->mAuxiliarOdcState || !state.mbInFrame) return;
1699 mpImpl->closeFrame();
1700 }
1701
insertBinaryObject(const librevenge::RVNGPropertyList & propList)1702 void OdsGenerator::insertBinaryObject(const librevenge::RVNGPropertyList &propList)
1703 {
1704 // Embedded objects without a frame simply don't make sense for us
1705 if (!mpImpl->getState().mbFirstInFrame)
1706 {
1707 ODFGEN_DEBUG_MSG(("OdsGenerator::insertBinaryObject: called outsided a frame\n"));
1708 return;
1709 }
1710 mpImpl->getState().mbFirstInFrame=false;
1711 if (mpImpl->mAuxiliarOdtState)
1712 return mpImpl->mAuxiliarOdtState->get().insertBinaryObject(propList);
1713 if (!mpImpl->checkOutsideOdc("insertBinaryObject"))
1714 return;
1715 mpImpl->insertBinaryObject(propList);
1716 }
1717
insertEquation(const librevenge::RVNGPropertyList & propList)1718 void OdsGenerator::insertEquation(const librevenge::RVNGPropertyList &propList)
1719 {
1720 // Embedded objects without a frame simply don't make sense for us
1721 if (!mpImpl->getState().mbFirstInFrame)
1722 {
1723 ODFGEN_DEBUG_MSG(("OdsGenerator::insertEquation: called outsided a frame\n"));
1724 return;
1725 }
1726 mpImpl->getState().mbFirstInFrame=false;
1727 if (mpImpl->mAuxiliarOdtState)
1728 return mpImpl->mAuxiliarOdtState->get().insertEquation(propList);
1729 if (!mpImpl->checkOutsideOdc("insertEquation"))
1730 return;
1731 mpImpl->insertEquation(propList);
1732 }
1733
openTextBox(const librevenge::RVNGPropertyList & propList)1734 void OdsGenerator::openTextBox(const librevenge::RVNGPropertyList &propList)
1735 {
1736 mpImpl->open(OdsGeneratorPrivate::C_TextBox);
1737
1738 OdsGeneratorPrivate::State state=mpImpl->getState();
1739 // Text box without a frame simply doesn't make sense for us
1740 if (!state.mbInFrame || !state.mbFirstInFrame)
1741 {
1742 ODFGEN_DEBUG_MSG(("OdsGenerator::openTextBox: called without frame\n"));
1743 return;
1744 }
1745 mpImpl->getState().mbFirstInFrame=false;
1746 mpImpl->pushState(state);
1747 mpImpl->pushListState();
1748
1749 if (mpImpl->mAuxiliarOdtState)
1750 return mpImpl->mAuxiliarOdtState->get().openTextBox(propList);
1751 if (!mpImpl->checkOutsideOdc("openTextBox"))
1752 return;
1753
1754 auto textBoxOpenElement = std::make_shared<TagOpenElement>("draw:text-box");
1755 if (propList["librevenge:next-frame-name"])
1756 {
1757 librevenge::RVNGString frameName;
1758 unsigned id=mpImpl->getFrameId(propList["librevenge:next-frame-name"]->getStr());
1759 frameName.sprintf("Object%i", id);
1760 textBoxOpenElement->addAttribute("draw:chain-next-name", frameName);
1761 }
1762 mpImpl->getCurrentStorage()->push_back(textBoxOpenElement);
1763 mpImpl->getState().mbInTextBox = true;
1764 }
1765
closeTextBox()1766 void OdsGenerator::closeTextBox()
1767 {
1768 if (!mpImpl->close(OdsGeneratorPrivate::C_TextBox))
1769 return;
1770 OdsGeneratorPrivate::State state=mpImpl->getState();
1771 mpImpl->popListState();
1772 mpImpl->popState();
1773
1774 if (mpImpl->mAuxiliarOdtState)
1775 return mpImpl->mAuxiliarOdtState->get().closeTextBox();
1776 if (mpImpl->mAuxiliarOdcState || !state.mbInTextBox)
1777 return;
1778 mpImpl->getCurrentStorage()->push_back(std::make_shared<TagCloseElement>("draw:text-box"));
1779 }
1780
startDocument(const librevenge::RVNGPropertyList & propList)1781 void OdsGenerator::startDocument(const librevenge::RVNGPropertyList &propList)
1782 {
1783 if (mpImpl->getState().mbStarted)
1784 {
1785 ODFGEN_DEBUG_MSG(("OdsGenerator::startDocument: document already started\n"));
1786 return;
1787 }
1788 mpImpl->getState().mbStarted=true;
1789 mpImpl->open(OdsGeneratorPrivate::C_Document);
1790 mpImpl->appendBodySettings(propList);
1791 }
1792
endDocument()1793 void OdsGenerator::endDocument()
1794 {
1795 if (!mpImpl->getState().mbStarted)
1796 {
1797 ODFGEN_DEBUG_MSG(("OdsGenerator::endDocument: document not started\n"));
1798 return;
1799 }
1800 if (mpImpl->mAuxiliarOdcState)
1801 {
1802 ODFGEN_DEBUG_MSG(("OdsGenerator::endDocument: auxiliar odc generator is open\n"));
1803 return;
1804 }
1805 if (mpImpl->mAuxiliarOdtState)
1806 {
1807 ODFGEN_DEBUG_MSG(("OdsGenerator::endDocument: auxiliar odt generator is open\n"));
1808 return;
1809 }
1810 mpImpl->getState().mbStarted=false;
1811
1812 if (!mpImpl->close(OdsGeneratorPrivate::C_Document)) return;
1813 // Write out the collected document
1814 mpImpl->writeTargetDocuments();
1815 }
1816
1817
openGroup(const librevenge::RVNGPropertyList & propList)1818 void OdsGenerator::openGroup(const librevenge::RVNGPropertyList &propList)
1819 {
1820 mpImpl->open(OdsGeneratorPrivate::C_Group);
1821 if (mpImpl->mAuxiliarOdtState)
1822 return mpImpl->mAuxiliarOdtState->get().openGroup(propList);
1823 if (!mpImpl->checkOutsideOdc("openGroup") || !mpImpl->canAddNewShape())
1824 return;
1825 OdsGeneratorPrivate::State state=mpImpl->getState();
1826 state.mbInGroup=true;
1827 mpImpl->pushState(state);
1828 mpImpl->openGroup(propList);
1829 }
1830
closeGroup()1831 void OdsGenerator::closeGroup()
1832 {
1833 if (!mpImpl->close(OdsGeneratorPrivate::C_Group))
1834 return;
1835 if (mpImpl->mAuxiliarOdtState)
1836 return mpImpl->mAuxiliarOdtState->get().closeGroup();
1837 if (mpImpl->mAuxiliarOdcState || !mpImpl->getState().mbInGroup)
1838 return;
1839 mpImpl->popState();
1840 mpImpl->closeGroup();
1841 }
1842
defineGraphicStyle(const librevenge::RVNGPropertyList & propList)1843 void OdsGenerator::defineGraphicStyle(const librevenge::RVNGPropertyList &propList)
1844 {
1845 if (mpImpl->mAuxiliarOdtState)
1846 return mpImpl->mAuxiliarOdtState->get().defineGraphicStyle(propList);
1847 mpImpl->defineGraphicStyle(propList);
1848 }
1849
drawRectangle(const librevenge::RVNGPropertyList & propList)1850 void OdsGenerator::drawRectangle(const librevenge::RVNGPropertyList &propList)
1851 {
1852 if (mpImpl->mAuxiliarOdtState)
1853 return mpImpl->mAuxiliarOdtState->get().drawRectangle(propList);
1854 if (!mpImpl->checkOutsideOdc("drawRectangle") || !mpImpl->canAddNewShape())
1855 return;
1856 mpImpl->drawRectangle(propList);
1857 }
1858
drawEllipse(const librevenge::RVNGPropertyList & propList)1859 void OdsGenerator::drawEllipse(const librevenge::RVNGPropertyList &propList)
1860 {
1861 if (mpImpl->mAuxiliarOdtState)
1862 return mpImpl->mAuxiliarOdtState->get().drawEllipse(propList);
1863 if (!mpImpl->checkOutsideOdc("drawEllipse") || !mpImpl->canAddNewShape())
1864 return;
1865 mpImpl->drawEllipse(propList);
1866 }
1867
1868
drawPolygon(const librevenge::RVNGPropertyList & propList)1869 void OdsGenerator::drawPolygon(const librevenge::RVNGPropertyList &propList)
1870 {
1871 if (mpImpl->mAuxiliarOdtState)
1872 return mpImpl->mAuxiliarOdtState->get().drawPolygon(propList);
1873 if (!mpImpl->checkOutsideOdc("drawPolygon") || !mpImpl->canAddNewShape())
1874 return;
1875 mpImpl->drawPolySomething(propList, true);
1876 }
1877
1878
drawPolyline(const librevenge::RVNGPropertyList & propList)1879 void OdsGenerator::drawPolyline(const librevenge::RVNGPropertyList &propList)
1880 {
1881 if (mpImpl->mAuxiliarOdtState)
1882 return mpImpl->mAuxiliarOdtState->get().drawPolyline(propList);
1883 if (!mpImpl->checkOutsideOdc("drawPolyline") || !mpImpl->canAddNewShape())
1884 return;
1885 mpImpl->drawPolySomething(propList, false);
1886 }
1887
1888
drawPath(const librevenge::RVNGPropertyList & propList)1889 void OdsGenerator::drawPath(const librevenge::RVNGPropertyList &propList)
1890 {
1891 if (mpImpl->mAuxiliarOdtState)
1892 return mpImpl->mAuxiliarOdtState->get().drawPath(propList);
1893 if (!mpImpl->checkOutsideOdc("drawPath") || !mpImpl->canAddNewShape())
1894 return;
1895 mpImpl->drawPath(propList);
1896 }
1897
drawConnector(const librevenge::RVNGPropertyList & propList)1898 void OdsGenerator::drawConnector(const librevenge::RVNGPropertyList &propList)
1899 {
1900 mpImpl->drawConnector(propList);
1901 }
1902
initStateWith(OdfGenerator const & orig)1903 void OdsGenerator::initStateWith(OdfGenerator const &orig)
1904 {
1905 mpImpl->initStateWith(orig);
1906 }
1907
registerEmbeddedImageHandler(const librevenge::RVNGString & mimeType,OdfEmbeddedImage imageHandler)1908 void OdsGenerator::registerEmbeddedImageHandler(const librevenge::RVNGString &mimeType, OdfEmbeddedImage imageHandler)
1909 {
1910 mpImpl->registerEmbeddedImageHandler(mimeType, imageHandler);
1911 }
1912
registerEmbeddedObjectHandler(const librevenge::RVNGString & mimeType,OdfEmbeddedObject objectHandler)1913 void OdsGenerator::registerEmbeddedObjectHandler(const librevenge::RVNGString &mimeType, OdfEmbeddedObject objectHandler)
1914 {
1915 mpImpl->registerEmbeddedObjectHandler(mimeType, objectHandler);
1916 }
1917
1918 /* vim:set shiftwidth=4 softtabstop=4 noexpandtab: */
1919