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