Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* OdtGenerator: Collects sections and runs of text from a
3 : * wordperfect file (and styles to go along with them) and writes them
4 : * to a Writer target document
5 : *
6 : * This Source Code Form is subject to the terms of the Mozilla Public
7 : * License, v. 2.0. If a copy of the MPL was not distributed with this
8 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 : *
10 : * For further information visit http://libwpd.sourceforge.net
11 : */
12 :
13 : /* "This product is not manufactured, approved, or supported by
14 : * Corel Corporation or Corel Corporation Limited."
15 : */
16 :
17 : #include <libwpd/libwpd.h>
18 : #include <vector>
19 : #include <map>
20 : #include <stack>
21 : #include <string>
22 :
23 : #include "OdtGenerator.hxx"
24 : #include "DocumentElement.hxx"
25 : #include "TextRunStyle.hxx"
26 : #include "FontStyle.hxx"
27 : #include "ListStyle.hxx"
28 : #include "PageSpan.hxx"
29 : #include "SectionStyle.hxx"
30 : #include "TableStyle.hxx"
31 : #include "FilterInternal.hxx"
32 : #include "InternalHandler.hxx"
33 :
34 : // the state we use for writing the final document
35 : typedef struct _WriterDocumentState WriterDocumentState;
36 : struct _WriterDocumentState
37 : {
38 : _WriterDocumentState();
39 :
40 : bool mbFirstElement;
41 : bool mbFirstParagraphInPageSpan;
42 : bool mbInFakeSection;
43 : bool mbListElementOpenedAtCurrentLevel;
44 : bool mbTableCellOpened;
45 : bool mbHeaderRow;
46 : bool mbInNote;
47 : bool mbInTextBox;
48 : bool mbInFrame;
49 : };
50 :
51 : // list state
52 : typedef struct _WriterListState WriterListState;
53 0 : struct _WriterListState
54 : {
55 : _WriterListState();
56 :
57 : ListStyle *mpCurrentListStyle;
58 : unsigned int miCurrentListLevel;
59 : unsigned int miLastListLevel;
60 : unsigned int miLastListNumber;
61 : bool mbListContinueNumbering;
62 : bool mbListElementParagraphOpened;
63 : std::stack<bool> mbListElementOpened;
64 : };
65 :
66 : enum WriterListType { unordered, ordered };
67 :
68 0 : _WriterDocumentState::_WriterDocumentState() :
69 : mbFirstElement(true),
70 : mbFirstParagraphInPageSpan(true),
71 : mbInFakeSection(false),
72 : mbListElementOpenedAtCurrentLevel(false),
73 : mbTableCellOpened(false),
74 : mbHeaderRow(false),
75 : mbInNote(false),
76 : mbInTextBox(false),
77 0 : mbInFrame(false)
78 : {
79 0 : }
80 :
81 0 : _WriterListState::_WriterListState() :
82 : mpCurrentListStyle(0),
83 : miCurrentListLevel(0),
84 : miLastListLevel(0),
85 : miLastListNumber(0),
86 : mbListContinueNumbering(false),
87 : mbListElementParagraphOpened(false),
88 0 : mbListElementOpened()
89 : {
90 0 : }
91 :
92 : class OdtGeneratorPrivate
93 : {
94 : public:
95 : OdtGeneratorPrivate(OdfDocumentHandler *pHandler, const OdfStreamType streamType);
96 : ~OdtGeneratorPrivate();
97 : bool _writeTargetDocument(OdfDocumentHandler *pHandler);
98 : void _writeDefaultStyles(OdfDocumentHandler *pHandler);
99 : void _writeMasterPages(OdfDocumentHandler *pHandler);
100 : void _writePageLayouts(OdfDocumentHandler *pHandler);
101 :
102 : void _openListLevel(TagOpenElement *pListLevelOpenElement);
103 : void _closeListLevel();
104 :
105 : OdfEmbeddedObject _findEmbeddedObjectHandler(const WPXString &mimeType);
106 : OdfEmbeddedImage _findEmbeddedImageHandler(const WPXString &mimeType);
107 :
108 : OdfDocumentHandler *mpHandler;
109 : bool mbUsed; // whether or not it has been before (you can only use me once!)
110 :
111 : std::stack<WriterDocumentState> mWriterDocumentStates;
112 :
113 : std::stack<WriterListState> mWriterListStates;
114 :
115 : // paragraph styles
116 : ParagraphStyleManager mParagraphManager;
117 :
118 : // span styles
119 : SpanStyleManager mSpanManager;
120 :
121 : // font styles
122 : FontStyleManager mFontManager;
123 :
124 : // section styles
125 : std::vector<SectionStyle *> mSectionStyles;
126 :
127 : // table styles
128 : std::vector<TableStyle *> mTableStyles;
129 :
130 : // frame styles
131 : std::vector<DocumentElement *> mFrameStyles;
132 :
133 : std::vector<DocumentElement *> mFrameAutomaticStyles;
134 :
135 : // embedded object handlers
136 : std::map<WPXString, OdfEmbeddedObject, ltstr > mObjectHandlers;
137 : std::map<WPXString, OdfEmbeddedImage, ltstr > mImageHandlers;
138 :
139 : // metadata
140 : std::vector<DocumentElement *> mMetaData;
141 :
142 : // list styles
143 : unsigned int miNumListStyles;
144 :
145 : // content elements
146 : std::vector<DocumentElement *> mBodyElements;
147 : // the current set of elements that we're writing to
148 : std::vector<DocumentElement *> * mpCurrentContentElements;
149 :
150 : // page state
151 : std::vector<PageSpan *> mPageSpans;
152 : PageSpan *mpCurrentPageSpan;
153 : int miNumPageStyles;
154 :
155 : // list styles
156 : std::vector<ListStyle *> mListStyles;
157 :
158 : // object state
159 : unsigned miObjectNumber;
160 :
161 : // table state
162 : TableStyle *mpCurrentTableStyle;
163 :
164 : const OdfStreamType mxStreamType;
165 :
166 : const char *mpPassword;
167 :
168 : };
169 :
170 0 : OdtGeneratorPrivate::OdtGeneratorPrivate(OdfDocumentHandler *pHandler, const OdfStreamType streamType) :
171 : mpHandler(pHandler),
172 : mbUsed(false),
173 : mWriterDocumentStates(),
174 : mWriterListStates(),
175 : mParagraphManager(), mSpanManager(), mFontManager(),
176 : mSectionStyles(), mTableStyles(), mFrameStyles(), mFrameAutomaticStyles(),
177 : mObjectHandlers(), mImageHandlers(), mMetaData(),
178 : miNumListStyles(0),
179 : mBodyElements(),
180 : mpCurrentContentElements(&mBodyElements),
181 : mPageSpans(),
182 : mpCurrentPageSpan(0),
183 : miNumPageStyles(0),
184 : mListStyles(),
185 : miObjectNumber(0),
186 : mpCurrentTableStyle(0),
187 : mxStreamType(streamType),
188 0 : mpPassword(0)
189 : {
190 0 : mWriterDocumentStates.push(WriterDocumentState());
191 0 : mWriterListStates.push(WriterListState());
192 0 : }
193 :
194 0 : OdtGeneratorPrivate::~OdtGeneratorPrivate()
195 : {
196 : // clean up the mess we made
197 : WRITER_DEBUG_MSG(("WriterWordPerfect: Cleaning up our mess..\n"));
198 :
199 : WRITER_DEBUG_MSG(("Destroying the body elements\n"));
200 0 : for (std::vector<DocumentElement *>::iterator iterBody = mBodyElements.begin(); iterBody != mBodyElements.end(); ++iterBody)
201 : {
202 0 : delete (*iterBody);
203 0 : (*iterBody) = 0;
204 : }
205 :
206 0 : mParagraphManager.clean();
207 0 : mSpanManager.clean();
208 0 : mFontManager.clean();
209 :
210 0 : for (std::vector<ListStyle *>::iterator iterListStyles = mListStyles.begin();
211 0 : iterListStyles != mListStyles.end(); ++iterListStyles)
212 : {
213 0 : delete(*iterListStyles);
214 : }
215 0 : for (std::vector<SectionStyle *>::iterator iterSectionStyles = mSectionStyles.begin();
216 0 : iterSectionStyles != mSectionStyles.end(); ++iterSectionStyles)
217 : {
218 0 : delete(*iterSectionStyles);
219 : }
220 0 : for (std::vector<TableStyle *>::iterator iterTableStyles = mTableStyles.begin();
221 0 : iterTableStyles != mTableStyles.end(); ++iterTableStyles)
222 : {
223 0 : delete((*iterTableStyles));
224 : }
225 :
226 0 : for (std::vector<PageSpan *>::iterator iterPageSpans = mPageSpans.begin();
227 0 : iterPageSpans != mPageSpans.end(); ++iterPageSpans)
228 : {
229 0 : delete(*iterPageSpans);
230 : }
231 0 : for (std::vector<DocumentElement *>::iterator iterFrameStyles = mFrameStyles.begin();
232 0 : iterFrameStyles != mFrameStyles.end(); ++iterFrameStyles)
233 : {
234 0 : delete(*iterFrameStyles);
235 : }
236 0 : for (std::vector<DocumentElement *>::iterator iterFrameAutomaticStyles = mFrameAutomaticStyles.begin();
237 0 : iterFrameAutomaticStyles != mFrameAutomaticStyles.end(); ++iterFrameAutomaticStyles)
238 : {
239 0 : delete(*iterFrameAutomaticStyles);
240 : }
241 0 : for (std::vector<DocumentElement *>::iterator iterMetaData = mMetaData.begin();
242 0 : iterMetaData != mMetaData.end(); ++iterMetaData)
243 : {
244 0 : delete(*iterMetaData);
245 : }
246 0 : }
247 :
248 0 : OdfEmbeddedObject OdtGeneratorPrivate::_findEmbeddedObjectHandler(const WPXString &mimeType)
249 : {
250 0 : std::map<WPXString, OdfEmbeddedObject, ltstr>::iterator i = mObjectHandlers.find(mimeType);
251 0 : if (i != mObjectHandlers.end())
252 0 : return i->second;
253 :
254 0 : return 0;
255 : }
256 :
257 0 : OdfEmbeddedImage OdtGeneratorPrivate::_findEmbeddedImageHandler(const WPXString &mimeType)
258 : {
259 0 : std::map<WPXString, OdfEmbeddedImage, ltstr>::iterator i = mImageHandlers.find(mimeType);
260 0 : if (i != mImageHandlers.end())
261 0 : return i->second;
262 :
263 0 : return 0;
264 : }
265 :
266 0 : OdtGenerator::OdtGenerator(OdfDocumentHandler *pHandler, const OdfStreamType streamType) :
267 0 : mpImpl(new OdtGeneratorPrivate(pHandler, streamType))
268 : {
269 0 : }
270 :
271 0 : OdtGenerator::~OdtGenerator()
272 : {
273 0 : if (mpImpl)
274 0 : delete mpImpl;
275 0 : }
276 :
277 0 : void OdtGeneratorPrivate::_writeDefaultStyles(OdfDocumentHandler *pHandler)
278 : {
279 0 : TagOpenElement("office:styles").write(pHandler);
280 :
281 0 : TagOpenElement defaultParagraphStyleOpenElement("style:default-style");
282 0 : defaultParagraphStyleOpenElement.addAttribute("style:family", "paragraph");
283 0 : defaultParagraphStyleOpenElement.write(pHandler);
284 :
285 0 : TagOpenElement defaultParagraphStylePropertiesOpenElement("style:paragraph-properties");
286 0 : defaultParagraphStylePropertiesOpenElement.addAttribute("style:tab-stop-distance", "0.5in");
287 0 : defaultParagraphStylePropertiesOpenElement.write(pHandler);
288 0 : TagCloseElement defaultParagraphStylePropertiesCloseElement("style:paragraph-properties");
289 0 : defaultParagraphStylePropertiesCloseElement.write(pHandler);
290 :
291 0 : pHandler->endElement("style:default-style");
292 :
293 0 : TagOpenElement defaultTableRowStyleOpenElement("style:default-style");
294 0 : defaultTableRowStyleOpenElement.addAttribute("style:family", "table-row");
295 0 : defaultTableRowStyleOpenElement.write(pHandler);
296 :
297 0 : TagOpenElement defaultTableRowPropertiesOpenElement("style:table-row-properties");
298 0 : defaultTableRowPropertiesOpenElement.addAttribute("fo:keep-together", "auto");
299 0 : defaultTableRowPropertiesOpenElement.write(pHandler);
300 :
301 0 : pHandler->endElement("style:table-row-properties");
302 0 : pHandler->endElement("style:default-style");
303 :
304 0 : TagOpenElement standardStyleOpenElement("style:style");
305 0 : standardStyleOpenElement.addAttribute("style:name", "Standard");
306 0 : standardStyleOpenElement.addAttribute("style:family", "paragraph");
307 0 : standardStyleOpenElement.addAttribute("style:class", "text");
308 0 : standardStyleOpenElement.write(pHandler);
309 :
310 0 : pHandler->endElement("style:style");
311 :
312 0 : TagOpenElement textBodyStyleOpenElement("style:style");
313 0 : textBodyStyleOpenElement.addAttribute("style:name", "Text_Body");
314 0 : textBodyStyleOpenElement.addAttribute("style:display-name", "Text Body");
315 0 : textBodyStyleOpenElement.addAttribute("style:family", "paragraph");
316 0 : textBodyStyleOpenElement.addAttribute("style:parent-style-name", "Standard");
317 0 : textBodyStyleOpenElement.addAttribute("style:class", "text");
318 0 : textBodyStyleOpenElement.write(pHandler);
319 :
320 0 : pHandler->endElement("style:style");
321 :
322 0 : TagOpenElement tableContentsStyleOpenElement("style:style");
323 0 : tableContentsStyleOpenElement.addAttribute("style:name", "Table_Contents");
324 0 : tableContentsStyleOpenElement.addAttribute("style:display-name", "Table Contents");
325 0 : tableContentsStyleOpenElement.addAttribute("style:family", "paragraph");
326 0 : tableContentsStyleOpenElement.addAttribute("style:parent-style-name", "Text_Body");
327 0 : tableContentsStyleOpenElement.addAttribute("style:class", "extra");
328 0 : tableContentsStyleOpenElement.write(pHandler);
329 :
330 0 : pHandler->endElement("style:style");
331 :
332 0 : TagOpenElement tableHeadingStyleOpenElement("style:style");
333 0 : tableHeadingStyleOpenElement.addAttribute("style:name", "Table_Heading");
334 0 : tableHeadingStyleOpenElement.addAttribute("style:display-name", "Table Heading");
335 0 : tableHeadingStyleOpenElement.addAttribute("style:family", "paragraph");
336 0 : tableHeadingStyleOpenElement.addAttribute("style:parent-style-name", "Table_Contents");
337 0 : tableHeadingStyleOpenElement.addAttribute("style:class", "extra");
338 0 : tableHeadingStyleOpenElement.write(pHandler);
339 :
340 0 : pHandler->endElement("style:style");
341 :
342 0 : for (std::vector<DocumentElement *>::const_iterator iter = mFrameStyles.begin();
343 0 : iter != mFrameStyles.end(); ++iter)
344 0 : (*iter)->write(pHandler);
345 :
346 0 : pHandler->endElement("office:styles");
347 0 : }
348 :
349 0 : void OdtGeneratorPrivate::_writeMasterPages(OdfDocumentHandler *pHandler)
350 : {
351 0 : TagOpenElement("office:master-styles").write(mpHandler);
352 0 : int pageNumber = 1;
353 0 : for (unsigned int i=0; i<mPageSpans.size(); ++i)
354 : {
355 : bool bLastPage;
356 0 : (i == (mPageSpans.size() - 1)) ? bLastPage = true : bLastPage = false;
357 0 : mPageSpans[i]->writeMasterPages(pageNumber, i, bLastPage, pHandler);
358 0 : pageNumber += mPageSpans[i]->getSpan();
359 : }
360 0 : pHandler->endElement("office:master-styles");
361 0 : }
362 :
363 0 : void OdtGeneratorPrivate::_writePageLayouts(OdfDocumentHandler *pHandler)
364 : {
365 0 : for (unsigned int i=0; i<mPageSpans.size(); ++i)
366 : {
367 0 : mPageSpans[i]->writePageLayout(i, pHandler);
368 : }
369 0 : }
370 :
371 0 : bool OdtGeneratorPrivate::_writeTargetDocument(OdfDocumentHandler *pHandler)
372 : {
373 : WRITER_DEBUG_MSG(("WriterWordPerfect: Document Body: Printing out the header stuff..\n"));
374 :
375 : WRITER_DEBUG_MSG(("WriterWordPerfect: Document Body: Start Document\n"));
376 0 : mpHandler->startDocument();
377 :
378 : WRITER_DEBUG_MSG(("WriterWordPerfect: Document Body: preamble\n"));
379 0 : WPXPropertyList docContentPropList;
380 0 : docContentPropList.insert("xmlns:office", "urn:oasis:names:tc:opendocument:xmlns:office:1.0");
381 0 : docContentPropList.insert("xmlns:meta", "urn:oasis:names:tc:opendocument:xmlns:meta:1.0");
382 0 : docContentPropList.insert("xmlns:dc", "http://purl.org/dc/elements/1.1/");
383 0 : docContentPropList.insert("xmlns:config", "urn:oasis:names:tc:opendocument:xmlns:config:1.0");
384 0 : docContentPropList.insert("xmlns:text", "urn:oasis:names:tc:opendocument:xmlns:text:1.0");
385 0 : docContentPropList.insert("xmlns:table", "urn:oasis:names:tc:opendocument:xmlns:table:1.0");
386 0 : docContentPropList.insert("xmlns:draw", "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0");
387 0 : docContentPropList.insert("xmlns:fo", "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0");
388 0 : docContentPropList.insert("xmlns:xlink", "http://www.w3.org/1999/xlink");
389 0 : docContentPropList.insert("xmlns:number", "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0");
390 0 : docContentPropList.insert("xmlns:svg", "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0");
391 0 : docContentPropList.insert("xmlns:chart", "urn:oasis:names:tc:opendocument:xmlns:chart:1.0");
392 0 : docContentPropList.insert("xmlns:dr3d", "urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0");
393 0 : docContentPropList.insert("xmlns:math", "http://www.w3.org/1998/Math/MathML");
394 0 : docContentPropList.insert("xmlns:form", "urn:oasis:names:tc:opendocument:xmlns:form:1.0");
395 0 : docContentPropList.insert("xmlns:script", "urn:oasis:names:tc:opendocument:xmlns:script:1.0");
396 0 : docContentPropList.insert("xmlns:style", "urn:oasis:names:tc:opendocument:xmlns:style:1.0");
397 0 : docContentPropList.insert("office:version", "1.0");
398 0 : if (mxStreamType == ODF_FLAT_XML)
399 : {
400 0 : docContentPropList.insert("office:mimetype", "application/vnd.oasis.opendocument.text");
401 0 : mpHandler->startElement("office:document", docContentPropList);
402 : }
403 : else
404 0 : mpHandler->startElement("office:document-content", docContentPropList);
405 :
406 : // write out the metadata
407 0 : TagOpenElement("office:meta").write(mpHandler);
408 0 : for (std::vector<DocumentElement *>::const_iterator iterMetaData = mMetaData.begin(); iterMetaData != mMetaData.end(); ++iterMetaData)
409 : {
410 0 : (*iterMetaData)->write(mpHandler);
411 : }
412 0 : mpHandler->endElement("office:meta");
413 :
414 : // write out the font styles
415 0 : mFontManager.writeFontsDeclaration(mpHandler);
416 :
417 : WRITER_DEBUG_MSG(("WriterWordPerfect: Document Body: Writing out the styles..\n"));
418 :
419 : // write default styles
420 0 : _writeDefaultStyles(mpHandler);
421 :
422 0 : TagOpenElement("office:automatic-styles").write(mpHandler);
423 :
424 0 : for (std::vector<DocumentElement *>::const_iterator iterFrameAutomaticStyles = mFrameAutomaticStyles.begin();
425 0 : iterFrameAutomaticStyles != mFrameAutomaticStyles.end(); ++iterFrameAutomaticStyles)
426 : {
427 0 : (*iterFrameAutomaticStyles)->write(pHandler);
428 : }
429 :
430 0 : mFontManager.write(pHandler); // do nothing
431 0 : mParagraphManager.write(pHandler);
432 0 : mSpanManager.write(pHandler);
433 :
434 : // writing out the sections styles
435 0 : for (std::vector<SectionStyle *>::const_iterator iterSectionStyles = mSectionStyles.begin(); iterSectionStyles != mSectionStyles.end(); ++iterSectionStyles)
436 : {
437 0 : (*iterSectionStyles)->write(pHandler);
438 : }
439 :
440 : // writing out the lists styles
441 0 : for (std::vector<ListStyle *>::const_iterator iterListStyles = mListStyles.begin(); iterListStyles != mListStyles.end(); ++iterListStyles)
442 : {
443 0 : (*iterListStyles)->write(pHandler);
444 : }
445 :
446 : // writing out the table styles
447 0 : for (std::vector<TableStyle *>::const_iterator iterTableStyles = mTableStyles.begin(); iterTableStyles != mTableStyles.end(); ++iterTableStyles)
448 : {
449 0 : (*iterTableStyles)->write(pHandler);
450 : }
451 :
452 : // writing out the page masters
453 0 : _writePageLayouts(pHandler);
454 :
455 :
456 0 : pHandler->endElement("office:automatic-styles");
457 :
458 0 : _writeMasterPages(pHandler);
459 :
460 : WRITER_DEBUG_MSG(("WriterWordPerfect: Document Body: Writing out the document..\n"));
461 : // writing out the document
462 0 : TagOpenElement("office:body").write(mpHandler);
463 0 : TagOpenElement("office:text").write(mpHandler);
464 :
465 0 : for (std::vector<DocumentElement *>::const_iterator iterBodyElements = mBodyElements.begin(); iterBodyElements != mBodyElements.end(); ++iterBodyElements)
466 : {
467 0 : (*iterBodyElements)->write(pHandler);
468 : }
469 : WRITER_DEBUG_MSG(("WriterWordPerfect: Document Body: Finished writing all doc els..\n"));
470 :
471 0 : pHandler->endElement("office:text");
472 0 : pHandler->endElement("office:body");
473 0 : if (mxStreamType == ODF_FLAT_XML)
474 0 : pHandler->endElement("office:document");
475 : else
476 0 : pHandler->endElement("office:document-content");
477 :
478 0 : pHandler->endDocument();
479 :
480 0 : return true;
481 : }
482 :
483 :
484 0 : void OdtGenerator::setDocumentMetaData(const WPXPropertyList &propList)
485 : {
486 0 : WPXPropertyList::Iter i(propList);
487 0 : for (i.rewind(); i.next(); )
488 : {
489 : // filter out libwpd elements
490 0 : if (strncmp(i.key(), "libwpd", 6) != 0 && strncmp(i.key(), "dcterms", 7) != 0)
491 : {
492 0 : mpImpl->mMetaData.push_back(new TagOpenElement(i.key()));
493 0 : WPXString sStringValue(i()->getStr(), true);
494 0 : mpImpl->mMetaData.push_back(new CharDataElement(sStringValue.cstr()));
495 0 : mpImpl->mMetaData.push_back(new TagCloseElement(i.key()));
496 : }
497 0 : }
498 :
499 0 : }
500 :
501 0 : void OdtGenerator::openPageSpan(const WPXPropertyList &propList)
502 : {
503 0 : PageSpan *pPageSpan = new PageSpan(propList);
504 0 : mpImpl->mPageSpans.push_back(pPageSpan);
505 0 : mpImpl->mpCurrentPageSpan = pPageSpan;
506 0 : mpImpl->miNumPageStyles++;
507 :
508 0 : mpImpl->mWriterDocumentStates.top().mbFirstParagraphInPageSpan = true;
509 0 : }
510 :
511 0 : void OdtGenerator::openHeader(const WPXPropertyList &propList)
512 : {
513 0 : std::vector<DocumentElement *> * pHeaderFooterContentElements = new std::vector<DocumentElement *>;
514 :
515 0 : if (propList["libwpd:occurence"]->getStr() == "even")
516 0 : mpImpl->mpCurrentPageSpan->setHeaderLeftContent(pHeaderFooterContentElements);
517 : else
518 0 : mpImpl->mpCurrentPageSpan->setHeaderContent(pHeaderFooterContentElements);
519 :
520 0 : mpImpl->mpCurrentContentElements = pHeaderFooterContentElements;
521 0 : }
522 :
523 0 : void OdtGenerator::closeHeader()
524 : {
525 0 : mpImpl->mpCurrentContentElements = &(mpImpl->mBodyElements);
526 0 : }
527 :
528 0 : void OdtGenerator::openFooter(const WPXPropertyList &propList)
529 : {
530 0 : std::vector<DocumentElement *> * pHeaderFooterContentElements = new std::vector<DocumentElement *>;
531 :
532 0 : if (propList["libwpd:occurence"]->getStr() == "even")
533 0 : mpImpl->mpCurrentPageSpan->setFooterLeftContent(pHeaderFooterContentElements);
534 : else
535 0 : mpImpl->mpCurrentPageSpan->setFooterContent(pHeaderFooterContentElements);
536 :
537 0 : mpImpl->mpCurrentContentElements = pHeaderFooterContentElements;
538 0 : }
539 :
540 0 : void OdtGenerator::closeFooter()
541 : {
542 0 : mpImpl->mpCurrentContentElements = &(mpImpl->mBodyElements);
543 0 : }
544 :
545 0 : void OdtGenerator::openSection(const WPXPropertyList &propList, const WPXPropertyListVector &columns)
546 : {
547 0 : int iNumColumns = columns.count();
548 0 : double fSectionMarginLeft = 0.0;
549 0 : double fSectionMarginRight = 0.0;
550 0 : if (propList["fo:margin-left"])
551 0 : fSectionMarginLeft = propList["fo:margin-left"]->getDouble();
552 0 : if (propList["fo:margin-right"])
553 0 : fSectionMarginRight = propList["fo:margin-right"]->getDouble();
554 :
555 0 : if (iNumColumns > 1 || fSectionMarginLeft != 0 || fSectionMarginRight != 0)
556 : {
557 0 : WPXString sSectionName;
558 0 : sSectionName.sprintf("Section%i", mpImpl->mSectionStyles.size());
559 :
560 0 : SectionStyle *pSectionStyle = new SectionStyle(propList, columns, sSectionName.cstr());
561 0 : mpImpl->mSectionStyles.push_back(pSectionStyle);
562 :
563 0 : TagOpenElement *pSectionOpenElement = new TagOpenElement("text:section");
564 0 : pSectionOpenElement->addAttribute("text:style-name", pSectionStyle->getName());
565 0 : pSectionOpenElement->addAttribute("text:name", pSectionStyle->getName());
566 0 : mpImpl->mpCurrentContentElements->push_back(pSectionOpenElement);
567 : }
568 : else
569 0 : mpImpl->mWriterDocumentStates.top().mbInFakeSection = true;
570 0 : }
571 :
572 0 : void OdtGenerator::closeSection()
573 : {
574 0 : if (!mpImpl->mWriterDocumentStates.top().mbInFakeSection)
575 0 : mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("text:section"));
576 : else
577 0 : mpImpl->mWriterDocumentStates.top().mbInFakeSection = false;
578 0 : }
579 :
580 0 : void OdtGenerator::openParagraph(const WPXPropertyList &propList, const WPXPropertyListVector &tabStops)
581 : {
582 : // FIXMENOW: What happens if we open a footnote inside a table? do we then inherit the footnote's style
583 : // from "Table Contents"
584 :
585 0 : WPXPropertyList finalPropList(propList);
586 0 : if (mpImpl->mWriterDocumentStates.top().mbFirstParagraphInPageSpan && mpImpl->mpCurrentContentElements == &(mpImpl->mBodyElements))
587 : {
588 0 : WPXString sPageStyleName;
589 0 : sPageStyleName.sprintf("Page_Style_%i", mpImpl->miNumPageStyles);
590 0 : finalPropList.insert("style:master-page-name", sPageStyleName);
591 0 : mpImpl->mWriterDocumentStates.top().mbFirstElement = false;
592 0 : mpImpl->mWriterDocumentStates.top().mbFirstParagraphInPageSpan = false;
593 : }
594 :
595 0 : if (mpImpl->mWriterDocumentStates.top().mbTableCellOpened)
596 : {
597 0 : if (mpImpl->mWriterDocumentStates.top().mbHeaderRow)
598 0 : finalPropList.insert("style:parent-style-name", "Table_Heading");
599 : else
600 0 : finalPropList.insert("style:parent-style-name", "Table_Contents");
601 : }
602 : else
603 0 : finalPropList.insert("style:parent-style-name", "Standard");
604 :
605 0 : WPXString sName = mpImpl->mParagraphManager.findOrAdd(finalPropList, tabStops);
606 :
607 : // create a document element corresponding to the paragraph, and append it to our list of document elements
608 0 : TagOpenElement *pParagraphOpenElement = new TagOpenElement("text:p");
609 0 : pParagraphOpenElement->addAttribute("text:style-name", sName);
610 0 : mpImpl->mpCurrentContentElements->push_back(pParagraphOpenElement);
611 0 : }
612 :
613 0 : void OdtGenerator::closeParagraph()
614 : {
615 0 : mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("text:p"));
616 0 : }
617 :
618 0 : void OdtGenerator::openSpan(const WPXPropertyList &propList)
619 : {
620 0 : if (propList["style:font-name"])
621 0 : mpImpl->mFontManager.findOrAdd(propList["style:font-name"]->getStr().cstr());
622 :
623 : // Get the style
624 0 : WPXString sName = mpImpl->mSpanManager.findOrAdd(propList);
625 :
626 : // create a document element corresponding to the paragraph, and append it to our list of document elements
627 0 : TagOpenElement *pSpanOpenElement = new TagOpenElement("text:span");
628 0 : pSpanOpenElement->addAttribute("text:style-name", sName.cstr());
629 0 : mpImpl->mpCurrentContentElements->push_back(pSpanOpenElement);
630 0 : }
631 :
632 0 : void OdtGenerator::closeSpan()
633 : {
634 0 : mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("text:span"));
635 0 : }
636 :
637 0 : void OdtGenerator::defineOrderedListLevel(const WPXPropertyList &propList)
638 : {
639 0 : int id = 0;
640 0 : if (propList["libwpd:id"])
641 0 : id = propList["libwpd:id"]->getInt();
642 :
643 0 : OrderedListStyle *pOrderedListStyle = 0;
644 0 : if (mpImpl->mWriterListStates.top().mpCurrentListStyle && mpImpl->mWriterListStates.top().mpCurrentListStyle->getListID() == id)
645 0 : pOrderedListStyle = static_cast<OrderedListStyle *>(mpImpl->mWriterListStates.top().mpCurrentListStyle); // FIXME: using a dynamic cast here causes oo to crash?!
646 :
647 : // this rather appalling conditional makes sure we only start a new list (rather than continue an old
648 : // one) if: (1) we have no prior list OR (2) the prior list is actually definitively different
649 : // from the list that is just being defined (listIDs differ) OR (3) we can tell that the user actually
650 : // is starting a new list at level 1 (and only level 1)
651 0 : if (pOrderedListStyle == 0 || pOrderedListStyle->getListID() != id ||
652 0 : (propList["libwpd:level"] && propList["libwpd:level"]->getInt()==1 &&
653 0 : (propList["text:start-value"] && propList["text:start-value"]->getInt() != int(mpImpl->mWriterListStates.top().miLastListNumber+1))))
654 : {
655 : WRITER_DEBUG_MSG(("Attempting to create a new ordered list style (listid: %i)\n", id));
656 0 : WPXString sName;
657 0 : sName.sprintf("OL%i", mpImpl->miNumListStyles);
658 0 : mpImpl->miNumListStyles++;
659 0 : pOrderedListStyle = new OrderedListStyle(sName.cstr(), id);
660 0 : mpImpl->mListStyles.push_back(pOrderedListStyle);
661 0 : mpImpl->mWriterListStates.top().mpCurrentListStyle = pOrderedListStyle;
662 0 : mpImpl->mWriterListStates.top().mbListContinueNumbering = false;
663 0 : mpImpl->mWriterListStates.top().miLastListNumber = 0;
664 : }
665 : else
666 0 : mpImpl->mWriterListStates.top().mbListContinueNumbering = true;
667 :
668 : // Iterate through ALL list styles with the same WordPerfect list id and define a level if it is not already defined
669 : // This solves certain problems with lists that start and finish without reaching certain levels and then begin again
670 : // and reach those levels. See gradguide0405_PC.wpd in the regression suite
671 0 : for (std::vector<ListStyle *>::iterator iterOrderedListStyles = mpImpl->mListStyles.begin(); iterOrderedListStyles != mpImpl->mListStyles.end(); ++iterOrderedListStyles)
672 : {
673 0 : if ((* iterOrderedListStyles) && (* iterOrderedListStyles)->getListID() == id && propList["libwpd:level"])
674 0 : (* iterOrderedListStyles)->updateListLevel((propList["libwpd:level"]->getInt() - 1), propList);
675 : }
676 0 : }
677 :
678 0 : void OdtGenerator::defineUnorderedListLevel(const WPXPropertyList &propList)
679 : {
680 0 : int id = 0;
681 0 : if (propList["libwpd:id"])
682 0 : id = propList["libwpd:id"]->getInt();
683 :
684 0 : UnorderedListStyle *pUnorderedListStyle = 0;
685 0 : if (mpImpl->mWriterListStates.top().mpCurrentListStyle && mpImpl->mWriterListStates.top().mpCurrentListStyle->getListID() == id)
686 0 : pUnorderedListStyle = static_cast<UnorderedListStyle *>(mpImpl->mWriterListStates.top().mpCurrentListStyle); // FIXME: using a dynamic cast here causes oo to crash?!
687 :
688 0 : if (pUnorderedListStyle == 0)
689 : {
690 : WRITER_DEBUG_MSG(("Attempting to create a new unordered list style (listid: %i)\n", id));
691 0 : WPXString sName;
692 0 : sName.sprintf("UL%i", mpImpl->miNumListStyles);
693 0 : mpImpl->miNumListStyles++;
694 0 : pUnorderedListStyle = new UnorderedListStyle(sName.cstr(), id);
695 0 : mpImpl->mListStyles.push_back(pUnorderedListStyle);
696 0 : mpImpl->mWriterListStates.top().mpCurrentListStyle = pUnorderedListStyle;
697 : }
698 :
699 : // See comment in OdtGenerator::defineOrderedListLevel
700 0 : for (std::vector<ListStyle *>::iterator iterUnorderedListStyles = mpImpl->mListStyles.begin(); iterUnorderedListStyles != mpImpl->mListStyles.end(); ++iterUnorderedListStyles)
701 : {
702 0 : if ((* iterUnorderedListStyles) && (* iterUnorderedListStyles)->getListID() == id && propList["libwpd:level"])
703 0 : (* iterUnorderedListStyles)->updateListLevel((propList["libwpd:level"]->getInt() - 1), propList);
704 : }
705 0 : }
706 :
707 0 : void OdtGenerator::openOrderedListLevel(const WPXPropertyList &)
708 : {
709 0 : if (mpImpl->mWriterListStates.top().mbListElementParagraphOpened)
710 : {
711 0 : mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("text:p"));
712 0 : mpImpl->mWriterListStates.top().mbListElementParagraphOpened = false;
713 : }
714 0 : TagOpenElement *pListLevelOpenElement = new TagOpenElement("text:list");
715 0 : mpImpl->_openListLevel(pListLevelOpenElement);
716 :
717 0 : if (mpImpl->mWriterListStates.top().mbListContinueNumbering)
718 : {
719 0 : pListLevelOpenElement->addAttribute("text:continue-numbering", "true");
720 : }
721 :
722 0 : mpImpl->mpCurrentContentElements->push_back(pListLevelOpenElement);
723 0 : }
724 :
725 0 : void OdtGenerator::openUnorderedListLevel(const WPXPropertyList &)
726 : {
727 0 : if (mpImpl->mWriterListStates.top().mbListElementParagraphOpened)
728 : {
729 0 : mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("text:p"));
730 0 : mpImpl->mWriterListStates.top().mbListElementParagraphOpened = false;
731 : }
732 0 : TagOpenElement *pListLevelOpenElement = new TagOpenElement("text:list");
733 0 : mpImpl->_openListLevel(pListLevelOpenElement);
734 :
735 0 : mpImpl->mpCurrentContentElements->push_back(pListLevelOpenElement);
736 0 : }
737 :
738 0 : void OdtGeneratorPrivate::_openListLevel(TagOpenElement *pListLevelOpenElement)
739 : {
740 0 : if (!mWriterListStates.top().mbListElementOpened.empty() &&
741 0 : !mWriterListStates.top().mbListElementOpened.top())
742 : {
743 0 : mpCurrentContentElements->push_back(new TagOpenElement("text:list-item"));
744 0 : mWriterListStates.top().mbListElementOpened.top() = true;
745 : }
746 :
747 0 : mWriterListStates.top().mbListElementOpened.push(false);
748 0 : if (mWriterListStates.top().mbListElementOpened.size() == 1)
749 : {
750 0 : pListLevelOpenElement->addAttribute("text:style-name", mWriterListStates.top().mpCurrentListStyle->getName());
751 : }
752 0 : }
753 :
754 0 : void OdtGenerator::closeOrderedListLevel()
755 : {
756 0 : mpImpl->_closeListLevel();
757 0 : }
758 :
759 0 : void OdtGenerator::closeUnorderedListLevel()
760 : {
761 0 : mpImpl->_closeListLevel();
762 0 : }
763 :
764 0 : void OdtGeneratorPrivate::_closeListLevel()
765 : {
766 0 : if (mWriterListStates.top().mbListElementOpened.top())
767 : {
768 0 : mpCurrentContentElements->push_back(new TagCloseElement("text:list-item"));
769 0 : mWriterListStates.top().mbListElementOpened.top() = false;
770 : }
771 :
772 0 : mpCurrentContentElements->push_back(new TagCloseElement("text:list"));
773 :
774 0 : if (!mWriterListStates.top().mbListElementOpened.empty())
775 : {
776 0 : mWriterListStates.top().mbListElementOpened.pop();
777 : }
778 0 : }
779 :
780 0 : void OdtGenerator::openListElement(const WPXPropertyList &propList, const WPXPropertyListVector &tabStops)
781 : {
782 0 : mpImpl->mWriterListStates.top().miLastListLevel = mpImpl->mWriterListStates.top().miCurrentListLevel;
783 0 : if (mpImpl->mWriterListStates.top().miCurrentListLevel == 1)
784 0 : mpImpl->mWriterListStates.top().miLastListNumber++;
785 :
786 0 : if (mpImpl->mWriterListStates.top().mbListElementOpened.top())
787 : {
788 0 : mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("text:list-item"));
789 0 : mpImpl->mWriterListStates.top().mbListElementOpened.top() = false;
790 : }
791 :
792 0 : WPXPropertyList finalPropList(propList);
793 : #if 0
794 : // this property is ignored in TextRunStyle.c++
795 : finalPropList.insert("style:list-style-name", mpImpl->mWriterListStates.top().mpCurrentListStyle->getName());
796 : #endif
797 0 : finalPropList.insert("style:parent-style-name", "Standard");
798 0 : WPXString paragName = mpImpl->mParagraphManager.findOrAdd(finalPropList, tabStops);
799 :
800 0 : mpImpl->mpCurrentContentElements->push_back(new TagOpenElement("text:list-item"));
801 :
802 0 : TagOpenElement *pOpenListElementParagraph = new TagOpenElement("text:p");
803 0 : pOpenListElementParagraph->addAttribute("text:style-name", paragName);
804 0 : mpImpl->mpCurrentContentElements->push_back(pOpenListElementParagraph);
805 :
806 0 : if (mpImpl->mpCurrentContentElements == &(mpImpl->mBodyElements))
807 0 : mpImpl->mWriterDocumentStates.top().mbFirstParagraphInPageSpan = false;
808 :
809 0 : mpImpl->mWriterListStates.top().mbListElementOpened.top() = true;
810 0 : mpImpl->mWriterListStates.top().mbListElementParagraphOpened = true;
811 0 : mpImpl->mWriterListStates.top().mbListContinueNumbering = false;
812 0 : }
813 :
814 0 : void OdtGenerator::closeListElement()
815 : {
816 : // this code is kind of tricky, because we don't actually close the list element (because this list element
817 : // could contain another list level in OOo's implementation of lists). that is done in the closeListLevel
818 : // code (or when we open another list element)
819 :
820 0 : if (mpImpl->mWriterListStates.top().mbListElementParagraphOpened)
821 : {
822 0 : mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("text:p"));
823 0 : mpImpl->mWriterListStates.top().mbListElementParagraphOpened = false;
824 : }
825 0 : }
826 :
827 0 : void OdtGenerator::openFootnote(const WPXPropertyList &propList)
828 : {
829 0 : mpImpl->mWriterListStates.push(WriterListState());
830 0 : TagOpenElement *pOpenFootNote = new TagOpenElement("text:note");
831 0 : pOpenFootNote->addAttribute("text:note-class", "footnote");
832 0 : if (propList["libwpd:number"])
833 : {
834 0 : WPXString tmpString("ftn");
835 0 : tmpString.append(propList["libwpd:number"]->getStr());
836 0 : pOpenFootNote->addAttribute("text:id", tmpString);
837 : }
838 0 : mpImpl->mpCurrentContentElements->push_back(pOpenFootNote);
839 :
840 0 : TagOpenElement *pOpenFootCitation = new TagOpenElement("text:note-citation");
841 0 : if (propList["text:label"])
842 : {
843 0 : WPXString tmpString(propList["text:label"]->getStr(),true);
844 0 : pOpenFootCitation->addAttribute("text:label", tmpString);
845 : }
846 0 : mpImpl->mpCurrentContentElements->push_back(pOpenFootCitation);
847 :
848 0 : if (propList["text:label"])
849 0 : mpImpl->mpCurrentContentElements->push_back(new CharDataElement(propList["text:label"]->getStr().cstr()));
850 0 : else if (propList["libwpd:number"])
851 0 : mpImpl->mpCurrentContentElements->push_back(new CharDataElement(propList["libwpd:number"]->getStr().cstr()));
852 0 : mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("text:note-citation"));
853 :
854 0 : mpImpl->mpCurrentContentElements->push_back(new TagOpenElement("text:note-body"));
855 :
856 0 : mpImpl->mWriterDocumentStates.top().mbInNote = true;
857 0 : }
858 :
859 0 : void OdtGenerator::closeFootnote()
860 : {
861 0 : mpImpl->mWriterDocumentStates.top().mbInNote = false;
862 0 : if (mpImpl->mWriterListStates.size() > 1)
863 0 : mpImpl->mWriterListStates.pop();
864 :
865 0 : mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("text:note-body"));
866 0 : mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("text:note"));
867 0 : }
868 :
869 0 : void OdtGenerator::openEndnote(const WPXPropertyList &propList)
870 : {
871 0 : mpImpl->mWriterListStates.push(WriterListState());
872 0 : TagOpenElement *pOpenEndNote = new TagOpenElement("text:note");
873 0 : pOpenEndNote->addAttribute("text:note-class", "endnote");
874 0 : if (propList["libwpd:number"])
875 : {
876 0 : WPXString tmpString("edn");
877 0 : tmpString.append(propList["libwpd:number"]->getStr());
878 0 : pOpenEndNote->addAttribute("text:id", tmpString);
879 : }
880 0 : mpImpl->mpCurrentContentElements->push_back(pOpenEndNote);
881 :
882 0 : TagOpenElement *pOpenEndCitation = new TagOpenElement("text:note-citation");
883 0 : if (propList["text:label"])
884 : {
885 0 : WPXString tmpString(propList["text:label"]->getStr(),true);
886 0 : pOpenEndCitation->addAttribute("text:label", tmpString);
887 : }
888 0 : mpImpl->mpCurrentContentElements->push_back(pOpenEndCitation);
889 :
890 0 : if (propList["text:label"])
891 0 : mpImpl->mpCurrentContentElements->push_back(new CharDataElement(propList["text:label"]->getStr().cstr()));
892 0 : else if (propList["libwpd:number"])
893 0 : mpImpl->mpCurrentContentElements->push_back(new CharDataElement(propList["libwpd:number"]->getStr().cstr()));
894 0 : mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("text:note-citation"));
895 :
896 0 : mpImpl->mpCurrentContentElements->push_back(new TagOpenElement("text:note-body"));
897 :
898 0 : mpImpl->mWriterDocumentStates.top().mbInNote = true;
899 0 : }
900 :
901 0 : void OdtGenerator::closeEndnote()
902 : {
903 0 : mpImpl->mWriterDocumentStates.top().mbInNote = false;
904 0 : if (mpImpl->mWriterListStates.size() > 1)
905 0 : mpImpl->mWriterListStates.pop();
906 :
907 0 : mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("text:note-body"));
908 0 : mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("text:note"));
909 0 : }
910 :
911 0 : void OdtGenerator::openComment(const WPXPropertyList &)
912 : {
913 0 : mpImpl->mWriterListStates.push(WriterListState());
914 0 : mpImpl->mpCurrentContentElements->push_back(new TagOpenElement("office:annotation"));
915 :
916 0 : mpImpl->mWriterDocumentStates.top().mbInNote = true;
917 0 : }
918 :
919 0 : void OdtGenerator::closeComment()
920 : {
921 0 : mpImpl->mWriterDocumentStates.top().mbInNote = false;
922 0 : if (mpImpl->mWriterListStates.size() > 1)
923 0 : mpImpl->mWriterListStates.pop();
924 :
925 0 : mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("office:annotation"));
926 0 : }
927 :
928 0 : void OdtGenerator::openTable(const WPXPropertyList &propList, const WPXPropertyListVector &columns)
929 : {
930 0 : if (!mpImpl->mWriterDocumentStates.top().mbInNote)
931 : {
932 0 : WPXString sTableName;
933 0 : sTableName.sprintf("Table%i", mpImpl->mTableStyles.size());
934 :
935 : // FIXME: we base the table style off of the page's margin left, ignoring (potential) wordperfect margin
936 : // state which is transmitted inside the page. could this lead to unacceptable behaviour?
937 : // WLACH_REFACTORING: characterize this behaviour, probably should nip it at the bud within libwpd
938 0 : TableStyle *pTableStyle = new TableStyle(propList, columns, sTableName.cstr());
939 :
940 0 : if (mpImpl->mWriterDocumentStates.top().mbFirstElement && mpImpl->mpCurrentContentElements == &(mpImpl->mBodyElements))
941 : {
942 0 : WPXString sMasterPageName("Page_Style_1");
943 0 : pTableStyle->setMasterPageName(sMasterPageName);
944 0 : mpImpl->mWriterDocumentStates.top().mbFirstElement = false;
945 : }
946 :
947 0 : mpImpl->mTableStyles.push_back(pTableStyle);
948 :
949 0 : mpImpl->mpCurrentTableStyle = pTableStyle;
950 :
951 0 : TagOpenElement *pTableOpenElement = new TagOpenElement("table:table");
952 :
953 0 : pTableOpenElement->addAttribute("table:name", sTableName.cstr());
954 0 : pTableOpenElement->addAttribute("table:style-name", sTableName.cstr());
955 0 : mpImpl->mpCurrentContentElements->push_back(pTableOpenElement);
956 :
957 0 : for (int i=0; i<pTableStyle->getNumColumns(); ++i)
958 : {
959 0 : TagOpenElement *pTableColumnOpenElement = new TagOpenElement("table:table-column");
960 0 : WPXString sColumnStyleName;
961 0 : sColumnStyleName.sprintf("%s.Column%i", sTableName.cstr(), (i+1));
962 0 : pTableColumnOpenElement->addAttribute("table:style-name", sColumnStyleName.cstr());
963 0 : mpImpl->mpCurrentContentElements->push_back(pTableColumnOpenElement);
964 :
965 0 : TagCloseElement *pTableColumnCloseElement = new TagCloseElement("table:table-column");
966 0 : mpImpl->mpCurrentContentElements->push_back(pTableColumnCloseElement);
967 0 : }
968 : }
969 0 : }
970 :
971 0 : void OdtGenerator::openTableRow(const WPXPropertyList &propList)
972 : {
973 0 : if (mpImpl->mWriterDocumentStates.top().mbInNote)
974 : return;
975 0 : if (!mpImpl->mpCurrentTableStyle)
976 : {
977 : WRITER_DEBUG_MSG(("OdtGenerator::openTableRow called with no table\n"));
978 : return;
979 : }
980 0 : if (propList["libwpd:is-header-row"] && (propList["libwpd:is-header-row"]->getInt()))
981 : {
982 0 : mpImpl->mpCurrentContentElements->push_back(new TagOpenElement("table:table-header-rows"));
983 0 : mpImpl->mWriterDocumentStates.top().mbHeaderRow = true;
984 : }
985 :
986 0 : WPXString sTableRowStyleName;
987 0 : sTableRowStyleName.sprintf("%s.Row%i", mpImpl->mpCurrentTableStyle->getName().cstr(), mpImpl->mpCurrentTableStyle->getNumTableRowStyles());
988 0 : TableRowStyle *pTableRowStyle = new TableRowStyle(propList, sTableRowStyleName.cstr());
989 0 : mpImpl->mpCurrentTableStyle->addTableRowStyle(pTableRowStyle);
990 :
991 0 : TagOpenElement *pTableRowOpenElement = new TagOpenElement("table:table-row");
992 0 : pTableRowOpenElement->addAttribute("table:style-name", sTableRowStyleName);
993 0 : mpImpl->mpCurrentContentElements->push_back(pTableRowOpenElement);
994 : }
995 :
996 0 : void OdtGenerator::closeTableRow()
997 : {
998 0 : if (!mpImpl->mWriterDocumentStates.top().mbInNote && mpImpl->mpCurrentTableStyle)
999 : {
1000 0 : mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("table:table-row"));
1001 0 : if (mpImpl->mWriterDocumentStates.top().mbHeaderRow)
1002 : {
1003 0 : mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("table:table-header-rows"));
1004 0 : mpImpl->mWriterDocumentStates.top().mbHeaderRow = false;
1005 : }
1006 : }
1007 0 : }
1008 :
1009 0 : void OdtGenerator::openTableCell(const WPXPropertyList &propList)
1010 : {
1011 0 : if (mpImpl->mWriterDocumentStates.top().mbInNote)
1012 : return;
1013 0 : if (!mpImpl->mpCurrentTableStyle)
1014 : {
1015 : WRITER_DEBUG_MSG(("OdtGenerator::openTableCell called with no table\n"));
1016 : return;
1017 : }
1018 :
1019 0 : WPXString sTableCellStyleName;
1020 0 : sTableCellStyleName.sprintf( "%s.Cell%i", mpImpl->mpCurrentTableStyle->getName().cstr(), mpImpl->mpCurrentTableStyle->getNumTableCellStyles());
1021 0 : TableCellStyle *pTableCellStyle = new TableCellStyle(propList, sTableCellStyleName.cstr());
1022 0 : mpImpl->mpCurrentTableStyle->addTableCellStyle(pTableCellStyle);
1023 :
1024 0 : TagOpenElement *pTableCellOpenElement = new TagOpenElement("table:table-cell");
1025 0 : pTableCellOpenElement->addAttribute("table:style-name", sTableCellStyleName);
1026 0 : if (propList["table:number-columns-spanned"])
1027 : pTableCellOpenElement->addAttribute("table:number-columns-spanned",
1028 0 : propList["table:number-columns-spanned"]->getStr().cstr());
1029 0 : if (propList["table:number-rows-spanned"])
1030 : pTableCellOpenElement->addAttribute("table:number-rows-spanned",
1031 0 : propList["table:number-rows-spanned"]->getStr().cstr());
1032 : // pTableCellOpenElement->addAttribute("table:value-type", "string");
1033 0 : mpImpl->mpCurrentContentElements->push_back(pTableCellOpenElement);
1034 :
1035 0 : mpImpl->mWriterDocumentStates.top().mbTableCellOpened = true;
1036 : }
1037 :
1038 0 : void OdtGenerator::closeTableCell()
1039 : {
1040 0 : if (!mpImpl->mWriterDocumentStates.top().mbInNote && mpImpl->mpCurrentTableStyle)
1041 : {
1042 0 : mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("table:table-cell"));
1043 0 : mpImpl->mWriterDocumentStates.top().mbTableCellOpened = false;
1044 : }
1045 0 : }
1046 :
1047 0 : void OdtGenerator::insertCoveredTableCell(const WPXPropertyList &)
1048 : {
1049 0 : if (!mpImpl->mWriterDocumentStates.top().mbInNote && mpImpl->mpCurrentTableStyle)
1050 : {
1051 0 : mpImpl->mpCurrentContentElements->push_back(new TagOpenElement("table:covered-table-cell"));
1052 0 : mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("table:covered-table-cell"));
1053 : }
1054 0 : }
1055 :
1056 0 : void OdtGenerator::closeTable()
1057 : {
1058 0 : if (!mpImpl->mWriterDocumentStates.top().mbInNote)
1059 : {
1060 0 : mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("table:table"));
1061 : }
1062 0 : }
1063 :
1064 :
1065 0 : void OdtGenerator::insertTab()
1066 : {
1067 0 : mpImpl->mpCurrentContentElements->push_back(new TagOpenElement("text:tab"));
1068 0 : mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("text:tab"));
1069 0 : }
1070 :
1071 0 : void OdtGenerator::insertSpace()
1072 : {
1073 0 : mpImpl->mpCurrentContentElements->push_back(new TagOpenElement("text:s"));
1074 0 : mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("text:s"));
1075 0 : }
1076 :
1077 0 : void OdtGenerator::insertLineBreak()
1078 : {
1079 0 : mpImpl->mpCurrentContentElements->push_back(new TagOpenElement("text:line-break"));
1080 0 : mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("text:line-break"));
1081 0 : }
1082 :
1083 0 : void OdtGenerator::insertField(const WPXString &type, const WPXPropertyList &propList)
1084 : {
1085 0 : if (!type.len())
1086 0 : return;
1087 :
1088 0 : TagOpenElement *openElement = new TagOpenElement(type);
1089 0 : if (type == "text:page-number")
1090 0 : openElement->addAttribute("text:select-page", "current");
1091 :
1092 0 : if (propList["style:num-format"])
1093 0 : openElement->addAttribute("style:num-format", propList["style:num-format"]->getStr());
1094 :
1095 0 : mpImpl->mpCurrentContentElements->push_back(openElement);
1096 0 : mpImpl->mpCurrentContentElements->push_back(new TagCloseElement(type));
1097 : }
1098 :
1099 0 : void OdtGenerator::insertText(const WPXString &text)
1100 : {
1101 0 : DocumentElement *pText = new TextElement(text);
1102 0 : mpImpl->mpCurrentContentElements->push_back(pText);
1103 0 : }
1104 :
1105 0 : void OdtGenerator::openFrame(const WPXPropertyList &propList)
1106 : {
1107 0 : mpImpl->mWriterListStates.push(WriterListState());
1108 :
1109 : // First, let's create a Frame Style for this box
1110 0 : TagOpenElement *frameStyleOpenElement = new TagOpenElement("style:style");
1111 0 : WPXString frameStyleName;
1112 0 : frameStyleName.sprintf("GraphicFrame_%i", mpImpl->miObjectNumber);
1113 0 : frameStyleOpenElement->addAttribute("style:name", frameStyleName);
1114 0 : frameStyleOpenElement->addAttribute("style:family", "graphic");
1115 :
1116 0 : mpImpl->mFrameStyles.push_back(frameStyleOpenElement);
1117 :
1118 0 : TagOpenElement *frameStylePropertiesOpenElement = new TagOpenElement("style:graphic-properties");
1119 :
1120 0 : if (propList["text:anchor-type"])
1121 0 : frameStylePropertiesOpenElement->addAttribute("text:anchor-type", propList["text:anchor-type"]->getStr());
1122 : else
1123 0 : frameStylePropertiesOpenElement->addAttribute("text:anchor-type","paragraph");
1124 :
1125 0 : if (propList["text:anchor-page-number"])
1126 0 : frameStylePropertiesOpenElement->addAttribute("text:anchor-page-number", propList["text:anchor-page-number"]->getStr());
1127 :
1128 0 : if (propList["svg:x"])
1129 0 : frameStylePropertiesOpenElement->addAttribute("svg:x", propList["svg:x"]->getStr());
1130 :
1131 0 : if (propList["svg:y"])
1132 0 : frameStylePropertiesOpenElement->addAttribute("svg:y", propList["svg:y"]->getStr());
1133 :
1134 0 : if (propList["svg:width"])
1135 0 : frameStylePropertiesOpenElement->addAttribute("svg:width", propList["svg:width"]->getStr());
1136 :
1137 0 : if (propList["svg:height"])
1138 0 : frameStylePropertiesOpenElement->addAttribute("svg:height", propList["svg:height"]->getStr());
1139 :
1140 0 : if (propList["style:rel-width"])
1141 0 : frameStylePropertiesOpenElement->addAttribute("style:rel-width", propList["style:rel-width"]->getStr());
1142 :
1143 0 : if (propList["style:rel-height"])
1144 0 : frameStylePropertiesOpenElement->addAttribute("style:rel-height", propList["style:rel-height"]->getStr());
1145 :
1146 0 : if (propList["fo:max-width"])
1147 0 : frameStylePropertiesOpenElement->addAttribute("fo:max-width", propList["fo:max-width"]->getStr());
1148 :
1149 0 : if (propList["fo:max-height"])
1150 0 : frameStylePropertiesOpenElement->addAttribute("fo:max-height", propList["fo:max-height"]->getStr());
1151 :
1152 0 : if (propList["style:wrap"])
1153 0 : frameStylePropertiesOpenElement->addAttribute("style:wrap", propList["style:wrap"]->getStr());
1154 :
1155 0 : mpImpl->mFrameStyles.push_back(frameStylePropertiesOpenElement);
1156 :
1157 0 : mpImpl->mFrameStyles.push_back(new TagCloseElement("style:graphic-properties"));
1158 :
1159 0 : mpImpl->mFrameStyles.push_back(new TagCloseElement("style:style"));
1160 :
1161 : // Now, let's create an automatic style for this frame
1162 0 : TagOpenElement *frameAutomaticStyleElement = new TagOpenElement("style:style");
1163 0 : WPXString frameAutomaticStyleName;
1164 0 : frameAutomaticStyleName.sprintf("fr%i", mpImpl->miObjectNumber);
1165 0 : frameAutomaticStyleElement->addAttribute("style:name", frameAutomaticStyleName);
1166 0 : frameAutomaticStyleElement->addAttribute("style:family", "graphic");
1167 0 : frameAutomaticStyleElement->addAttribute("style:parent-style-name", frameStyleName);
1168 :
1169 0 : mpImpl->mFrameAutomaticStyles.push_back(frameAutomaticStyleElement);
1170 :
1171 0 : TagOpenElement *frameAutomaticStylePropertiesElement = new TagOpenElement("style:graphic-properties");
1172 0 : if (propList["style:horizontal-pos"])
1173 0 : frameAutomaticStylePropertiesElement->addAttribute("style:horizontal-pos", propList["style:horizontal-pos"]->getStr());
1174 : else
1175 0 : frameAutomaticStylePropertiesElement->addAttribute("style:horizontal-pos", "left");
1176 :
1177 0 : if (propList["style:horizontal-rel"])
1178 0 : frameAutomaticStylePropertiesElement->addAttribute("style:horizontal-rel", propList["style:horizontal-rel"]->getStr());
1179 : else
1180 0 : frameAutomaticStylePropertiesElement->addAttribute("style:horizontal-rel", "paragraph");
1181 :
1182 0 : if (propList["style:vertical-pos"])
1183 0 : frameAutomaticStylePropertiesElement->addAttribute("style:vertical-pos", propList["style:vertical-pos"]->getStr());
1184 : else
1185 0 : frameAutomaticStylePropertiesElement->addAttribute("style:vertical-pos", "top");
1186 :
1187 0 : if (propList["style:vertical-rel"])
1188 0 : frameAutomaticStylePropertiesElement->addAttribute("style:vertical-rel", propList["style:vertical-rel"]->getStr());
1189 : else
1190 0 : frameAutomaticStylePropertiesElement->addAttribute("style:vertical-rel", "page-content");
1191 :
1192 0 : if (propList["fo:max-width"])
1193 0 : frameAutomaticStylePropertiesElement->addAttribute("fo:max-width", propList["fo:max-width"]->getStr());
1194 :
1195 0 : if (propList["fo:max-height"])
1196 0 : frameAutomaticStylePropertiesElement->addAttribute("fo:max-height", propList["fo:max-height"]->getStr());
1197 :
1198 : // check if the frame has border, background attributes
1199 0 : if (propList["fo:border"])
1200 0 : frameAutomaticStylePropertiesElement->addAttribute("fo:border", propList["fo:border"]->getStr());
1201 0 : if (propList["style:border-line-width"])
1202 0 : frameAutomaticStylePropertiesElement->addAttribute("style:border-line-width", propList["style:border-line-width"]->getStr());
1203 0 : if (propList["fo:background-color"])
1204 0 : frameAutomaticStylePropertiesElement->addAttribute("fo:background-color", propList["fo:background-color"]->getStr());
1205 :
1206 0 : frameAutomaticStylePropertiesElement->addAttribute("draw:ole-draw-aspect", "1");
1207 :
1208 0 : mpImpl->mFrameAutomaticStyles.push_back(frameAutomaticStylePropertiesElement);
1209 :
1210 0 : mpImpl->mFrameAutomaticStyles.push_back(new TagCloseElement("style:graphic-properties"));
1211 :
1212 0 : mpImpl->mFrameAutomaticStyles.push_back(new TagCloseElement("style:style"));
1213 :
1214 : // And write the frame itself
1215 0 : TagOpenElement *drawFrameOpenElement = new TagOpenElement("draw:frame");
1216 :
1217 0 : drawFrameOpenElement->addAttribute("draw:style-name", frameAutomaticStyleName);
1218 0 : WPXString objectName;
1219 0 : objectName.sprintf("Object%i", mpImpl->miObjectNumber++);
1220 0 : drawFrameOpenElement->addAttribute("draw:name", objectName);
1221 0 : if (propList["text:anchor-type"])
1222 0 : drawFrameOpenElement->addAttribute("text:anchor-type", propList["text:anchor-type"]->getStr());
1223 : else
1224 0 : drawFrameOpenElement->addAttribute("text:anchor-type","paragraph");
1225 :
1226 0 : if (propList["text:anchor-page-number"])
1227 0 : drawFrameOpenElement->addAttribute("text:anchor-page-number", propList["text:anchor-page-number"]->getStr());
1228 :
1229 0 : if (propList["svg:x"])
1230 0 : drawFrameOpenElement->addAttribute("svg:x", propList["svg:x"]->getStr());
1231 :
1232 0 : if (propList["svg:y"])
1233 0 : drawFrameOpenElement->addAttribute("svg:y", propList["svg:y"]->getStr());
1234 :
1235 0 : if (propList["svg:width"])
1236 0 : drawFrameOpenElement->addAttribute("svg:width", propList["svg:width"]->getStr());
1237 :
1238 0 : if (propList["svg:height"])
1239 0 : drawFrameOpenElement->addAttribute("svg:height", propList["svg:height"]->getStr());
1240 :
1241 0 : if (propList["style:rel-width"])
1242 0 : drawFrameOpenElement->addAttribute("style:rel-width", propList["style:rel-width"]->getStr());
1243 :
1244 0 : if (propList["style:rel-height"])
1245 0 : drawFrameOpenElement->addAttribute("style:rel-height", propList["style:rel-height"]->getStr());
1246 :
1247 0 : mpImpl->mpCurrentContentElements->push_back(drawFrameOpenElement);
1248 :
1249 0 : mpImpl->mWriterDocumentStates.top().mbInFrame = true;
1250 0 : }
1251 :
1252 0 : void OdtGenerator::closeFrame()
1253 : {
1254 0 : if (mpImpl->mWriterListStates.size() > 1)
1255 0 : mpImpl->mWriterListStates.pop();
1256 :
1257 0 : mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("draw:frame"));
1258 :
1259 0 : mpImpl->mWriterDocumentStates.top().mbInFrame = false;
1260 0 : }
1261 :
1262 0 : void OdtGenerator::insertBinaryObject(const WPXPropertyList &propList, const WPXBinaryData &data)
1263 : {
1264 0 : if (!data.size())
1265 0 : return;
1266 0 : if (!mpImpl->mWriterDocumentStates.top().mbInFrame) // Embedded objects without a frame simply don't make sense for us
1267 0 : return;
1268 0 : if (!propList["libwpd:mimetype"])
1269 0 : return;
1270 :
1271 0 : OdfEmbeddedObject tmpObjectHandler = mpImpl->_findEmbeddedObjectHandler(propList["libwpd:mimetype"]->getStr());
1272 0 : OdfEmbeddedImage tmpImageHandler = mpImpl->_findEmbeddedImageHandler(propList["libwpd:mimetype"]->getStr());
1273 :
1274 0 : if (tmpObjectHandler || tmpImageHandler)
1275 : {
1276 0 : if (tmpObjectHandler)
1277 : {
1278 0 : std::vector<DocumentElement *> tmpContentElements;
1279 0 : InternalHandler tmpHandler(&tmpContentElements);
1280 :
1281 0 : if (tmpObjectHandler(data, &tmpHandler, ODF_FLAT_XML) && !tmpContentElements.empty())
1282 : {
1283 0 : mpImpl->mpCurrentContentElements->push_back(new TagOpenElement("draw:object"));
1284 0 : for (std::vector<DocumentElement *>::const_iterator iter = tmpContentElements.begin(); iter != tmpContentElements.end(); ++iter)
1285 0 : mpImpl->mpCurrentContentElements->push_back(*iter);
1286 0 : mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("draw:object"));
1287 0 : }
1288 : }
1289 0 : if (tmpImageHandler)
1290 : {
1291 0 : WPXBinaryData output;
1292 0 : if (tmpImageHandler(data, output))
1293 : {
1294 0 : mpImpl->mpCurrentContentElements->push_back(new TagOpenElement("draw:image"));
1295 :
1296 0 : mpImpl->mpCurrentContentElements->push_back(new TagOpenElement("office:binary-data"));
1297 :
1298 0 : WPXString binaryBase64Data = output.getBase64Data();
1299 :
1300 0 : mpImpl->mpCurrentContentElements->push_back(new CharDataElement(binaryBase64Data.cstr()));
1301 :
1302 0 : mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("office:binary-data"));
1303 :
1304 0 : mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("draw:image"));
1305 0 : }
1306 0 : }
1307 : }
1308 : else
1309 : // assuming we have a binary image or a object_ole that we can just insert as it is
1310 : {
1311 0 : if (propList["libwpd:mimetype"]->getStr() == "object/ole")
1312 0 : mpImpl->mpCurrentContentElements->push_back(new TagOpenElement("draw:object-ole"));
1313 : else
1314 0 : mpImpl->mpCurrentContentElements->push_back(new TagOpenElement("draw:image"));
1315 :
1316 0 : mpImpl->mpCurrentContentElements->push_back(new TagOpenElement("office:binary-data"));
1317 :
1318 0 : WPXString binaryBase64Data = data.getBase64Data();
1319 :
1320 0 : mpImpl->mpCurrentContentElements->push_back(new CharDataElement(binaryBase64Data.cstr()));
1321 :
1322 0 : mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("office:binary-data"));
1323 :
1324 0 : if (propList["libwpd:mimetype"]->getStr() == "object/ole")
1325 0 : mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("draw:object-ole"));
1326 : else
1327 0 : mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("draw:image"));
1328 : }
1329 : }
1330 :
1331 0 : void OdtGenerator::openTextBox(const WPXPropertyList &)
1332 : {
1333 0 : if (!mpImpl->mWriterDocumentStates.top().mbInFrame) // Text box without a frame simply doesn't make sense for us
1334 0 : return;
1335 0 : mpImpl->mWriterListStates.push(WriterListState());
1336 0 : mpImpl->mWriterDocumentStates.push(WriterDocumentState());
1337 0 : mpImpl->mpCurrentContentElements->push_back(new TagOpenElement("draw:text-box"));
1338 0 : mpImpl->mWriterDocumentStates.top().mbInTextBox = true;
1339 0 : mpImpl->mWriterDocumentStates.top().mbFirstElement = false;
1340 : }
1341 :
1342 0 : void OdtGenerator::closeTextBox()
1343 : {
1344 0 : if (!mpImpl->mWriterDocumentStates.top().mbInTextBox)
1345 0 : return;
1346 0 : if (mpImpl->mWriterListStates.size() > 1)
1347 0 : mpImpl->mWriterListStates.pop();
1348 0 : if (mpImpl->mWriterDocumentStates.size() > 1)
1349 0 : mpImpl->mWriterDocumentStates.pop();
1350 :
1351 0 : mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("draw:text-box"));
1352 : }
1353 :
1354 0 : void OdtGenerator::defineSectionStyle(WPXPropertyList const &, WPXPropertyListVector const &)
1355 : {
1356 0 : }
1357 :
1358 0 : void OdtGenerator::insertEquation(WPXPropertyList const &, WPXString const &)
1359 : {
1360 0 : }
1361 :
1362 0 : void OdtGenerator::endDocument()
1363 : {
1364 : // Write out the collected document
1365 0 : mpImpl->_writeTargetDocument(mpImpl->mpHandler);
1366 0 : }
1367 :
1368 0 : void OdtGenerator::startDocument()
1369 : {
1370 0 : }
1371 :
1372 0 : void OdtGenerator::closePageSpan()
1373 : {
1374 0 : }
1375 :
1376 0 : void OdtGenerator::definePageStyle(WPXPropertyList const &)
1377 : {
1378 0 : }
1379 :
1380 0 : void OdtGenerator::defineParagraphStyle(WPXPropertyList const &, WPXPropertyListVector const &)
1381 : {
1382 0 : }
1383 :
1384 0 : void OdtGenerator::defineCharacterStyle(WPXPropertyList const &)
1385 : {
1386 0 : }
1387 :
1388 0 : void OdtGenerator::registerEmbeddedObjectHandler(const WPXString &mimeType, OdfEmbeddedObject objectHandler)
1389 : {
1390 0 : mpImpl->mObjectHandlers[mimeType] = objectHandler;
1391 0 : }
1392 :
1393 0 : void OdtGenerator::registerEmbeddedImageHandler(const WPXString &mimeType, OdfEmbeddedImage imageHandler)
1394 : {
1395 0 : mpImpl->mImageHandlers[mimeType] = imageHandler;
1396 0 : }
1397 :
1398 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|