Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
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 :
10 : #include <com/sun/star/beans/PropertyAttribute.hpp>
11 : #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
12 : #include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp>
13 : #include <com/sun/star/graphic/GraphicProvider.hpp>
14 : #include <com/sun/star/io/UnexpectedEOFException.hpp>
15 : #include <com/sun/star/lang/XServiceInfo.hpp>
16 : #include <com/sun/star/text/XTextFrame.hpp>
17 : #include <com/sun/star/text/SizeType.hpp>
18 : #include <com/sun/star/text/HoriOrientation.hpp>
19 : #include <com/sun/star/text/VertOrientation.hpp>
20 : #include <com/sun/star/text/RelOrientation.hpp>
21 : #include <com/sun/star/text/WrapTextMode.hpp>
22 : #include <com/sun/star/text/TextContentAnchorType.hpp>
23 : #include <rtl/tencinfo.h>
24 : #include <svl/lngmisc.hxx>
25 : #include <unotools/ucbstreamhelper.hxx>
26 : #include <unotools/streamwrap.hxx>
27 : #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
28 : #include <rtl/ustring.hxx>
29 : #include <svtools/grfmgr.hxx>
30 : #include <vcl/graph.hxx>
31 : #include <vcl/outdev.hxx>
32 : #include <vcl/svapp.hxx>
33 : #include <vcl/wmf.hxx>
34 : #include <vcl/settings.hxx>
35 : #include <filter/msfilter/util.hxx>
36 : #include <filter/msfilter/escherex.hxx>
37 : #include <comphelper/string.hxx>
38 : #include <tools/globname.hxx>
39 : #include <tools/datetimeutils.hxx>
40 : #include <comphelper/classids.hxx>
41 : #include <comphelper/embeddedobjectcontainer.hxx>
42 : #include <sfx2/sfxbasemodel.hxx>
43 :
44 : #include <oox/mathml/import.hxx>
45 : #include <ooxml/resourceids.hxx>
46 : #include <ooxml/OOXMLFastTokens.hxx>
47 : #include <oox/token/namespaces.hxx>
48 : #include <oox/token/tokens.hxx>
49 : #include <dmapper/GraphicHelpers.hxx>
50 :
51 : #include <rtfsdrimport.hxx>
52 : #include <rtftokenizer.hxx>
53 : #include <rtflookahead.hxx>
54 : #include <rtfcharsets.hxx>
55 : #include <rtfreferenceproperties.hxx>
56 : #include <rtfskipdestination.hxx>
57 : #include <rtffly.hxx>
58 :
59 : #define TWIP_TO_MM100(TWIP) ((TWIP) >= 0 ? (((TWIP)*127L+36L)/72L) : (((TWIP)*127L-36L)/72L))
60 : #define MM100_TO_EMU(MM100) (MM100 * 360)
61 :
62 : using std::make_pair;
63 :
64 : namespace writerfilter {
65 : namespace rtftok {
66 :
67 21 : static Id lcl_getParagraphBorder(sal_uInt32 nIndex)
68 : {
69 : static const Id aBorderIds[] =
70 : {
71 : NS_ooxml::LN_CT_PBdr_top, NS_ooxml::LN_CT_PBdr_left, NS_ooxml::LN_CT_PBdr_bottom, NS_ooxml::LN_CT_PBdr_right
72 : };
73 :
74 21 : return aBorderIds[nIndex];
75 : }
76 :
77 12740 : static void lcl_putNestedAttribute(RTFSprms& rSprms, Id nParent, Id nId, RTFValue::Pointer_t pValue,
78 : RTFOverwrite eOverwrite = OVERWRITE_YES, bool bAttribute = true)
79 : {
80 12740 : RTFValue::Pointer_t pParent = rSprms.find(nParent);
81 12740 : if (!pParent.get())
82 : {
83 4063 : RTFSprms aAttributes;
84 4063 : if (nParent == NS_ooxml::LN_CT_TcPrBase_shd)
85 : {
86 : // RTF default is 'auto', see writerfilter::dmapper::CellColorHandler
87 5 : aAttributes.set(NS_ooxml::LN_CT_Shd_color, RTFValue::Pointer_t(new RTFValue(0x0a)));
88 5 : aAttributes.set(NS_ooxml::LN_CT_Shd_fill, RTFValue::Pointer_t(new RTFValue(0x0a)));
89 : }
90 8126 : RTFValue::Pointer_t pParentValue(new RTFValue(aAttributes));
91 4063 : rSprms.set(nParent, pParentValue, eOverwrite);
92 8126 : pParent = pParentValue;
93 : }
94 12740 : RTFSprms& rAttributes = (bAttribute ? pParent->getAttributes() : pParent->getSprms());
95 12740 : rAttributes.set(nId, pValue, eOverwrite);
96 12740 : }
97 :
98 1557 : static void lcl_putNestedSprm(RTFSprms& rSprms, Id nParent, Id nId, RTFValue::Pointer_t pValue, RTFOverwrite eOverwrite = OVERWRITE_NO_APPEND)
99 : {
100 1557 : lcl_putNestedAttribute(rSprms, nParent, nId, pValue, eOverwrite, false);
101 1557 : }
102 :
103 606 : static RTFValue::Pointer_t lcl_getNestedAttribute(RTFSprms& rSprms, Id nParent, Id nId)
104 : {
105 606 : RTFValue::Pointer_t pParent = rSprms.find(nParent);
106 606 : if (!pParent)
107 419 : return RTFValue::Pointer_t();
108 187 : RTFSprms& rAttributes = pParent->getAttributes();
109 187 : return rAttributes.find(nId);
110 : }
111 :
112 137 : static bool lcl_eraseNestedAttribute(RTFSprms& rSprms, Id nParent, Id nId)
113 : {
114 137 : RTFValue::Pointer_t pParent = rSprms.find(nParent);
115 137 : if (!pParent.get())
116 : // It doesn't even have a parent, we're done!
117 137 : return false;
118 0 : RTFSprms& rAttributes = pParent->getAttributes();
119 0 : return rAttributes.erase(nId);
120 : }
121 :
122 1213 : static RTFSprms& lcl_getLastAttributes(RTFSprms& rSprms, Id nId)
123 : {
124 1213 : RTFValue::Pointer_t p = rSprms.find(nId);
125 1213 : if (p.get() && p->getSprms().size())
126 1081 : return p->getSprms().back().second->getAttributes();
127 : else
128 : {
129 : SAL_WARN("writerfilter", "trying to set property when no type is defined");
130 132 : return rSprms;
131 1213 : }
132 : }
133 :
134 : static void
135 1334 : lcl_putBorderProperty(RTFStack& aStates, Id nId, RTFValue::Pointer_t pValue)
136 : {
137 1334 : RTFSprms* pAttributes = 0;
138 1334 : if (aStates.top().nBorderState == BORDER_PARAGRAPH_BOX)
139 5 : for (int i = 0; i < 4; i++)
140 : {
141 4 : RTFValue::Pointer_t p = aStates.top().aParagraphSprms.find(lcl_getParagraphBorder(i));
142 4 : if (p.get())
143 : {
144 4 : RTFSprms& rAttributes = p->getAttributes();
145 4 : rAttributes.set(nId, pValue);
146 : }
147 4 : }
148 1333 : else if (aStates.top().nBorderState == BORDER_CHARACTER)
149 : {
150 10 : RTFValue::Pointer_t pPointer = aStates.top().aCharacterSprms.find(NS_ooxml::LN_EG_RPrBase_bdr);
151 10 : if (pPointer.get())
152 : {
153 10 : RTFSprms& rAttributes = pPointer->getAttributes();
154 10 : rAttributes.set(nId, pValue);
155 10 : }
156 : }
157 : // Attributes of the last border type
158 1323 : else if (aStates.top().nBorderState == BORDER_PARAGRAPH)
159 63 : pAttributes = &lcl_getLastAttributes(aStates.top().aParagraphSprms, NS_ooxml::LN_CT_PrBase_pBdr);
160 1260 : else if (aStates.top().nBorderState == BORDER_CELL)
161 1150 : pAttributes = &lcl_getLastAttributes(aStates.top().aTableCellSprms, NS_ooxml::LN_CT_TcPrBase_tcBorders);
162 110 : else if (aStates.top().nBorderState == BORDER_PAGE)
163 0 : pAttributes = &lcl_getLastAttributes(aStates.top().aSectionSprms, NS_ooxml::LN_EG_SectPrContents_pgBorders);
164 1334 : if (pAttributes)
165 1213 : pAttributes->set(nId, pValue);
166 1334 : }
167 :
168 6 : static OString lcl_DTTM22OString(long lDTTM)
169 : {
170 6 : return DateTimeToOString(msfilter::util::DTTM2DateTime(lDTTM));
171 : }
172 :
173 6 : static writerfilter::Reference<Properties>::Pointer_t lcl_getBookmarkProperties(int nPos, OUString& rString)
174 : {
175 6 : RTFSprms aAttributes;
176 12 : RTFValue::Pointer_t pPos(new RTFValue(nPos));
177 6 : if (!rString.isEmpty())
178 : {
179 : // If present, this should be sent first.
180 3 : RTFValue::Pointer_t pString(new RTFValue(rString));
181 3 : aAttributes.set(NS_ooxml::LN_CT_Bookmark_name, pString);
182 : }
183 6 : aAttributes.set(NS_ooxml::LN_CT_MarkupRangeBookmark_id, pPos);
184 12 : return writerfilter::Reference<Properties>::Pointer_t(new RTFReferenceProperties(aAttributes));
185 : }
186 :
187 3 : static writerfilter::Reference<Properties>::Pointer_t lcl_getBookmarkProperties(int nPos)
188 : {
189 3 : OUString aStr;
190 3 : return lcl_getBookmarkProperties(nPos, aStr);
191 : }
192 :
193 0 : static const char* lcl_RtfToString(RTFKeyword nKeyword)
194 : {
195 0 : for (int i = 0; i < nRTFControlWords; i++)
196 : {
197 0 : if (nKeyword == aRTFControlWords[i].nIndex)
198 0 : return aRTFControlWords[i].sKeyword;
199 : }
200 0 : return NULL;
201 : }
202 :
203 167 : static util::DateTime lcl_getDateTime(RTFParserState& aState)
204 : {
205 : return util::DateTime(0 /*100sec*/, 0 /*sec*/, aState.nMinute, aState.nHour,
206 167 : aState.nDay, aState.nMonth, aState.nYear, false);
207 : }
208 :
209 1610 : static void lcl_DestinationToMath(OUStringBuffer& rDestinationText, oox::formulaimport::XmlStreamBuilder& rMathBuffer, bool& rMathNor)
210 : {
211 1610 : OUString aStr = rDestinationText.makeStringAndClear();
212 1610 : if (!aStr.isEmpty())
213 : {
214 589 : rMathBuffer.appendOpeningTag(M_TOKEN(r));
215 589 : if (rMathNor)
216 : {
217 9 : rMathBuffer.appendOpeningTag(M_TOKEN(rPr));
218 : // Same as M_TOKEN(lit)
219 9 : rMathBuffer.appendOpeningTag(M_TOKEN(nor));
220 9 : rMathBuffer.appendClosingTag(M_TOKEN(nor));
221 9 : rMathBuffer.appendClosingTag(M_TOKEN(rPr));
222 9 : rMathNor = false;
223 : }
224 589 : rMathBuffer.appendOpeningTag(M_TOKEN(t));
225 589 : rMathBuffer.appendCharacters(aStr);
226 589 : rMathBuffer.appendClosingTag(M_TOKEN(t));
227 589 : rMathBuffer.appendClosingTag(M_TOKEN(r));
228 1610 : }
229 1610 : }
230 :
231 312 : RTFDocumentImpl::RTFDocumentImpl(uno::Reference<uno::XComponentContext> const& xContext,
232 : uno::Reference<io::XInputStream> const& xInputStream,
233 : uno::Reference<lang::XComponent> const& xDstDoc,
234 : uno::Reference<frame::XFrame> const& xFrame,
235 : uno::Reference<task::XStatusIndicator> const& xStatusIndicator)
236 : : m_xContext(xContext),
237 : m_xInputStream(xInputStream),
238 : m_xDstDoc(xDstDoc),
239 : m_xFrame(xFrame),
240 : m_xStatusIndicator(xStatusIndicator),
241 : m_pMapperStream(NULL),
242 : m_aDefaultState(this),
243 : m_bSkipUnknown(false),
244 : m_aFontIndexes(),
245 : m_aColorTable(),
246 : m_bFirstRun(true),
247 : m_bNeedPap(true),
248 : m_bNeedCr(false),
249 : m_bNeedCrOrig(false),
250 : m_bNeedPar(true),
251 : m_bNeedFinalPar(false),
252 : m_aListTableSprms(),
253 : m_aSettingsTableAttributes(),
254 : m_aSettingsTableSprms(),
255 : m_xStorage(),
256 : m_nNestedCells(0),
257 : m_nTopLevelCells(0),
258 : m_nInheritingCells(0),
259 : m_nNestedCurrentCellX(0),
260 : m_nTopLevelCurrentCellX(0),
261 : m_nBackupTopLevelCurrentCellX(0),
262 : m_aTableBufferStack(1), // create top-level buffer already
263 : m_aSuperBuffer(),
264 : m_bHasFootnote(false),
265 : m_pSuperstream(0),
266 : m_nStreamType(0),
267 : m_nHeaderFooterPositions(),
268 : m_nGroupStartPos(0),
269 : m_aBookmarks(),
270 : m_aAuthors(),
271 : m_aFormfieldSprms(),
272 : m_aFormfieldAttributes(),
273 : m_nFormFieldType(FORMFIELD_NONE),
274 : m_aObjectSprms(),
275 : m_aObjectAttributes(),
276 : m_bObject(false),
277 : m_aFontTableEntries(),
278 : m_nCurrentFontIndex(0),
279 : m_nCurrentEncoding(0),
280 : m_nDefaultFontIndex(-1),
281 : m_aStyleTableEntries(),
282 : m_nCurrentStyleIndex(0),
283 : m_bFormField(false),
284 : m_bIsInFrame(false),
285 : m_aUnicodeBuffer(),
286 : m_aHexBuffer(),
287 : m_bMathNor(false),
288 : m_bIgnoreNextContSectBreak(false),
289 : m_nResetBreakOnSectBreak(RTF_invalid),
290 : m_bNeedSect(false), // done by checkFirstRun
291 : m_bWasInFrame(false),
292 : m_bHadPicture(false),
293 : m_bHadSect(false),
294 : m_nCellxMax(0),
295 312 : m_nListPictureId(0)
296 : {
297 : OSL_ASSERT(xInputStream.is());
298 312 : m_pInStream.reset(utl::UcbStreamHelper::CreateStream(xInputStream, true));
299 :
300 312 : m_xModelFactory.set(m_xDstDoc, uno::UNO_QUERY);
301 :
302 312 : uno::Reference<document::XDocumentPropertiesSupplier> xDocumentPropertiesSupplier(m_xDstDoc, uno::UNO_QUERY);
303 312 : if (xDocumentPropertiesSupplier.is())
304 296 : m_xDocumentProperties.set(xDocumentPropertiesSupplier->getDocumentProperties(), uno::UNO_QUERY);
305 :
306 312 : m_pGraphicHelper.reset(new oox::GraphicHelper(m_xContext, xFrame, m_xStorage));
307 :
308 312 : m_pTokenizer.reset(new RTFTokenizer(*this, m_pInStream.get(), m_xStatusIndicator));
309 312 : m_pSdrImport.reset(new RTFSdrImport(*this, m_xDstDoc));
310 312 : }
311 :
312 624 : RTFDocumentImpl::~RTFDocumentImpl()
313 : {
314 624 : }
315 :
316 1585896 : SvStream& RTFDocumentImpl::Strm()
317 : {
318 1585896 : return *m_pInStream;
319 : }
320 :
321 26646 : Stream& RTFDocumentImpl::Mapper()
322 : {
323 26646 : return *m_pMapperStream;
324 : }
325 :
326 25 : void RTFDocumentImpl::setSuperstream(RTFDocumentImpl *pSuperstream)
327 : {
328 25 : m_pSuperstream = pSuperstream;
329 25 : }
330 :
331 25 : void RTFDocumentImpl::setStreamType(Id nId)
332 : {
333 25 : m_nStreamType = nId;
334 25 : }
335 :
336 6 : void RTFDocumentImpl::setAuthor(OUString& rAuthor)
337 : {
338 6 : m_aAuthor = rAuthor;
339 6 : }
340 :
341 5 : void RTFDocumentImpl::setAuthorInitials(OUString& rAuthorInitials)
342 : {
343 5 : m_aAuthorInitials = rAuthorInitials;
344 5 : }
345 :
346 326 : bool RTFDocumentImpl::isSubstream() const
347 : {
348 326 : return m_pSuperstream != 0;
349 : }
350 :
351 25 : void RTFDocumentImpl::finishSubstream()
352 : {
353 25 : checkUnicode(/*bUnicode =*/ true, /*bHex =*/ true);
354 25 : }
355 :
356 25 : void RTFDocumentImpl::setIgnoreFirst(OUString& rIgnoreFirst)
357 : {
358 25 : m_aIgnoreFirst = rIgnoreFirst;
359 25 : }
360 :
361 16 : void RTFDocumentImpl::resolveSubstream(sal_Size nPos, Id nId)
362 : {
363 16 : OUString aStr;
364 16 : resolveSubstream(nPos, nId, aStr);
365 16 : }
366 25 : void RTFDocumentImpl::resolveSubstream(sal_Size nPos, Id nId, OUString& rIgnoreFirst)
367 : {
368 25 : sal_Size nCurrent = Strm().Tell();
369 : // Seek to header position, parse, then seek back.
370 25 : RTFDocumentImpl::Pointer_t pImpl(new RTFDocumentImpl(m_xContext, m_xInputStream, m_xDstDoc, m_xFrame, m_xStatusIndicator));
371 25 : pImpl->setSuperstream(this);
372 25 : pImpl->setStreamType(nId);
373 25 : pImpl->setIgnoreFirst(rIgnoreFirst);
374 25 : if (!m_aAuthor.isEmpty())
375 : {
376 6 : pImpl->setAuthor(m_aAuthor);
377 6 : m_aAuthor = "";
378 : }
379 25 : if (!m_aAuthorInitials.isEmpty())
380 : {
381 5 : pImpl->setAuthorInitials(m_aAuthorInitials);
382 5 : m_aAuthorInitials = "";
383 : }
384 25 : pImpl->m_nDefaultFontIndex = m_nDefaultFontIndex;
385 25 : pImpl->seek(nPos);
386 : SAL_INFO("writerfilter", "substream start");
387 25 : Mapper().substream(nId, pImpl);
388 : SAL_INFO("writerfilter", "substream end");
389 25 : Strm().Seek(nCurrent);
390 25 : nPos = 0;
391 25 : }
392 :
393 6108 : void RTFDocumentImpl::checkFirstRun()
394 : {
395 6108 : if (m_bFirstRun)
396 : {
397 : // output settings table
398 303 : writerfilter::Reference<Properties>::Pointer_t const pProp(new RTFReferenceProperties(m_aSettingsTableAttributes, m_aSettingsTableSprms));
399 606 : RTFReferenceTable::Entries_t aSettingsTableEntries;
400 303 : aSettingsTableEntries.insert(make_pair(0, pProp));
401 606 : writerfilter::Reference<Table>::Pointer_t const pTable(new RTFReferenceTable(aSettingsTableEntries));
402 303 : Mapper().table(NS_ooxml::LN_settings_settings, pTable);
403 : // start initial paragraph
404 303 : m_bFirstRun = false;
405 : assert(!m_bNeedSect);
406 303 : setNeedSect(); // first call that succeeds
407 :
408 : // set the requested default font, if there are none
409 606 : RTFValue::Pointer_t pFont = lcl_getNestedAttribute(m_aDefaultState.aCharacterSprms, NS_ooxml::LN_EG_RPrBase_rFonts, NS_ooxml::LN_CT_Fonts_ascii);
410 606 : RTFValue::Pointer_t pCurrentFont = lcl_getNestedAttribute(m_aStates.top().aCharacterSprms, NS_ooxml::LN_EG_RPrBase_rFonts, NS_ooxml::LN_CT_Fonts_ascii);
411 303 : if (pFont && !pCurrentFont)
412 317 : lcl_putNestedAttribute(m_aStates.top().aCharacterSprms, NS_ooxml::LN_EG_RPrBase_rFonts, NS_ooxml::LN_CT_Fonts_ascii, pFont);
413 : }
414 6108 : }
415 :
416 155 : bool RTFDocumentImpl::getFirstRun()
417 : {
418 155 : return m_bFirstRun;
419 : }
420 :
421 326 : void RTFDocumentImpl::setNeedPar(bool bNeedPar)
422 : {
423 326 : m_bNeedPar = bNeedPar;
424 326 : }
425 :
426 73192 : void RTFDocumentImpl::setNeedSect(bool bNeedSect)
427 : {
428 : // ignore setting before checkFirstRun - every keyword calls setNeedSect!
429 73192 : if (!m_bNeedSect && bNeedSect && !m_bFirstRun)
430 : {
431 315 : if (!m_pSuperstream) // no sections in header/footer!
432 : {
433 292 : Mapper().startSectionGroup();
434 : }
435 : // set flag in substream too - otherwise multiple startParagraphGroup
436 315 : m_bNeedSect = bNeedSect;
437 315 : Mapper().startParagraphGroup();
438 315 : setNeedPar(true);
439 : }
440 72877 : else if (m_bNeedSect && !bNeedSect)
441 : {
442 0 : m_bNeedSect = bNeedSect;
443 : }
444 73192 : }
445 :
446 5099 : writerfilter::Reference<Properties>::Pointer_t RTFDocumentImpl::getProperties(RTFSprms& rAttributes, RTFSprms& rSprms)
447 : {
448 5099 : int nStyle = m_aStates.top().nCurrentStyleIndex;
449 5099 : RTFReferenceTable::Entries_t::iterator it = m_aStyleTableEntries.find(nStyle);
450 5099 : if (it != m_aStyleTableEntries.end())
451 : {
452 358 : RTFReferenceProperties& rProps = *(RTFReferenceProperties*)it->second.get();
453 : // Get rid of direct formatting what is already in the style.
454 358 : rSprms.deduplicate(rProps.getSprms());
455 358 : rAttributes.deduplicate(rProps.getAttributes());
456 : }
457 5099 : writerfilter::Reference<Properties>::Pointer_t pRet(new RTFReferenceProperties(rAttributes, rSprms));
458 5099 : return pRet;
459 : }
460 :
461 5838 : void RTFDocumentImpl::checkNeedPap()
462 : {
463 5838 : if (m_bNeedPap)
464 : {
465 858 : m_bNeedPap = false; // reset early, so we can avoid recursion when calling ourselves
466 858 : if (!m_aStates.top().pCurrentBuffer)
467 : {
468 : writerfilter::Reference<Properties>::Pointer_t const pParagraphProperties(
469 1284 : getProperties(m_aStates.top().aParagraphAttributes, m_aStates.top().aParagraphSprms)
470 1284 : );
471 :
472 : // Writer will ignore a page break before a text frame, so guard it with empty paragraphs
473 696 : bool hasBreakBeforeFrame = m_aStates.top().aFrame.hasProperties() &&
474 696 : m_aStates.top().aParagraphSprms.find(NS_ooxml::LN_CT_PPrBase_pageBreakBefore).get();
475 642 : if (hasBreakBeforeFrame)
476 : {
477 0 : dispatchSymbol(RTF_PAR);
478 0 : m_bNeedPap = false;
479 : }
480 642 : Mapper().props(pParagraphProperties);
481 642 : if (hasBreakBeforeFrame)
482 0 : dispatchSymbol(RTF_PAR);
483 :
484 642 : if (m_aStates.top().aFrame.hasProperties())
485 : {
486 : writerfilter::Reference<Properties>::Pointer_t const pFrameProperties(
487 27 : new RTFReferenceProperties(RTFSprms(), m_aStates.top().aFrame.getSprms()));
488 27 : Mapper().props(pFrameProperties);
489 642 : }
490 : }
491 : else
492 : {
493 216 : RTFValue::Pointer_t pValue(new RTFValue(m_aStates.top().aParagraphAttributes, m_aStates.top().aParagraphSprms));
494 216 : m_aStates.top().pCurrentBuffer->push_back(
495 432 : Buf_t(BUFFER_PROPS, pValue));
496 : }
497 : }
498 5838 : }
499 :
500 4649 : void RTFDocumentImpl::runProps()
501 : {
502 4649 : if (!m_aStates.top().pCurrentBuffer)
503 : {
504 4371 : writerfilter::Reference<Properties>::Pointer_t const pProperties = getProperties(m_aStates.top().aCharacterAttributes, m_aStates.top().aCharacterSprms);
505 4371 : Mapper().props(pProperties);
506 : }
507 : else
508 : {
509 278 : RTFValue::Pointer_t pValue(new RTFValue(m_aStates.top().aCharacterAttributes, m_aStates.top().aCharacterSprms));
510 278 : m_aStates.top().pCurrentBuffer->push_back(Buf_t(BUFFER_PROPS, pValue));
511 : }
512 :
513 : // Delete the sprm, so the trackchange range will be started only once.
514 : // OTOH set a boolean flag, so we'll know we need to end the range later.
515 4649 : RTFValue::Pointer_t pTrackchange = m_aStates.top().aCharacterSprms.find(NS_ooxml::LN_trackchange);
516 4649 : if (pTrackchange.get())
517 : {
518 0 : m_aStates.top().bStartedTrackchange = true;
519 0 : m_aStates.top().aCharacterSprms.erase(NS_ooxml::LN_trackchange);
520 4649 : }
521 4649 : }
522 :
523 1033 : void RTFDocumentImpl::runBreak()
524 : {
525 1033 : sal_uInt8 sBreak[] = { 0xd };
526 1033 : Mapper().text(sBreak, 1);
527 1033 : m_bNeedCr = false;
528 1033 : }
529 :
530 334 : void RTFDocumentImpl::tableBreak()
531 : {
532 334 : runBreak();
533 334 : Mapper().endParagraphGroup();
534 334 : Mapper().startParagraphGroup();
535 334 : }
536 :
537 699 : void RTFDocumentImpl::parBreak()
538 : {
539 699 : checkFirstRun();
540 699 : checkNeedPap();
541 : // end previous paragraph
542 699 : Mapper().startCharacterGroup();
543 699 : runBreak();
544 699 : Mapper().endCharacterGroup();
545 699 : Mapper().endParagraphGroup();
546 :
547 699 : m_bHadPicture = false;
548 :
549 : // start new one
550 699 : Mapper().startParagraphGroup();
551 699 : }
552 :
553 312 : void RTFDocumentImpl::sectBreak(bool bFinal = false)
554 : {
555 : SAL_INFO("writerfilter", OSL_THIS_FUNC << ": final? " << bFinal << ", needed? " << m_bNeedSect);
556 312 : bool bNeedSect = m_bNeedSect;
557 312 : RTFValue::Pointer_t pBreak = m_aStates.top().aSectionSprms.find(NS_ooxml::LN_EG_SectPrContents_type);
558 312 : bool bContinuous = pBreak.get() && pBreak->getInt() == 0;
559 : // If there is no paragraph in this section, then insert a dummy one, as required by Writer,
560 : // unless this is the end of the doc, we had nothing since the last section break and this is not a continuous one.
561 312 : if (m_bNeedPar && !(bFinal && !m_bNeedSect && !bContinuous) && !isSubstream())
562 11 : dispatchSymbol(RTF_PAR);
563 : // It's allowed to not have a non-table paragraph at the end of an RTF doc, add it now if required.
564 312 : if (m_bNeedFinalPar && bFinal)
565 : {
566 2 : dispatchFlag(RTF_PARD);
567 2 : dispatchSymbol(RTF_PAR);
568 2 : m_bNeedSect = bNeedSect;
569 : }
570 633 : while (!m_nHeaderFooterPositions.empty())
571 : {
572 9 : std::pair<Id, sal_Size> aPair = m_nHeaderFooterPositions.front();
573 9 : m_nHeaderFooterPositions.pop();
574 9 : resolveSubstream(aPair.second, aPair.first);
575 : }
576 :
577 : // Normally a section break at the end of the doc is necessary. Unless the
578 : // last control word in the document is a section break itself.
579 312 : if (!bNeedSect || !m_bHadSect)
580 : {
581 : // In case the last section is a continuous one, we don't need to output a section break.
582 297 : if (bFinal && bContinuous)
583 69 : m_aStates.top().aSectionSprms.erase(NS_ooxml::LN_EG_SectPrContents_type);
584 : }
585 :
586 : // Section properties are a paragraph sprm.
587 624 : RTFValue::Pointer_t pValue(new RTFValue(m_aStates.top().aSectionAttributes, m_aStates.top().aSectionSprms));
588 624 : RTFSprms aAttributes;
589 624 : RTFSprms aSprms;
590 312 : aSprms.set(NS_ooxml::LN_CT_PPr_sectPr, pValue);
591 : writerfilter::Reference<Properties>::Pointer_t const pProperties(
592 312 : new RTFReferenceProperties(aAttributes, aSprms)
593 936 : );
594 : // The trick is that we send properties of the previous section right now, which will be exactly what dmapper expects.
595 312 : Mapper().props(pProperties);
596 312 : Mapper().endParagraphGroup();
597 312 : if (!m_pSuperstream)
598 289 : Mapper().endSectionGroup();
599 312 : m_bNeedPar = false;
600 624 : m_bNeedSect = false;
601 312 : }
602 :
603 25 : void RTFDocumentImpl::seek(sal_Size nPos)
604 : {
605 25 : Strm().Seek(nPos);
606 25 : }
607 :
608 521 : sal_uInt32 RTFDocumentImpl::getColorTable(sal_uInt32 nIndex)
609 : {
610 521 : if (!m_pSuperstream)
611 : {
612 519 : if (nIndex < m_aColorTable.size())
613 351 : return m_aColorTable[nIndex];
614 168 : return 0;
615 : }
616 : else
617 2 : return m_pSuperstream->getColorTable(nIndex);
618 : }
619 :
620 5597 : rtl_TextEncoding RTFDocumentImpl::getEncoding(int nFontIndex)
621 : {
622 5597 : if (!m_pSuperstream)
623 : {
624 5581 : std::map<int, rtl_TextEncoding>::iterator it = m_aFontEncodings.find(nFontIndex);
625 5581 : if (it != m_aFontEncodings.end())
626 2706 : return it->second;
627 2875 : return msfilter::util::getBestTextEncodingFromLocale(Application::GetSettings().GetLanguageTag().getLocale());
628 : }
629 : else
630 16 : return m_pSuperstream->getEncoding(nFontIndex);
631 : }
632 :
633 5258 : OUString RTFDocumentImpl::getFontName(int nIndex)
634 : {
635 5258 : if (!m_pSuperstream)
636 5254 : return m_aFontNames[nIndex];
637 : else
638 4 : return m_pSuperstream->getFontName(nIndex);
639 : }
640 :
641 6516 : int RTFDocumentImpl::getFontIndex(int nIndex)
642 : {
643 6516 : if (!m_pSuperstream)
644 6500 : return std::find(m_aFontIndexes.begin(), m_aFontIndexes.end(), nIndex) - m_aFontIndexes.begin();
645 : else
646 16 : return m_pSuperstream->getFontIndex(nIndex);
647 : }
648 :
649 636 : OUString RTFDocumentImpl::getStyleName(int nIndex)
650 : {
651 636 : if (!m_pSuperstream)
652 : {
653 629 : OUString aRet;
654 629 : if (m_aStyleNames.find(nIndex) != m_aStyleNames.end())
655 540 : aRet = m_aStyleNames[nIndex];
656 629 : return aRet;
657 : }
658 : else
659 7 : return m_pSuperstream->getStyleName(nIndex);
660 : }
661 :
662 678 : RTFParserState& RTFDocumentImpl::getDefaultState()
663 : {
664 678 : if (!m_pSuperstream)
665 654 : return m_aDefaultState;
666 : else
667 24 : return m_pSuperstream->getDefaultState();
668 : }
669 :
670 18 : oox::GraphicHelper& RTFDocumentImpl::getGraphicHelper()
671 : {
672 18 : return *m_pGraphicHelper;
673 : }
674 :
675 312 : void RTFDocumentImpl::resolve(Stream & rMapper)
676 : {
677 312 : m_pMapperStream = &rMapper;
678 312 : switch (m_pTokenizer->resolveParse())
679 : {
680 : case ERROR_OK:
681 : SAL_INFO("writerfilter", OSL_THIS_FUNC << ": finished without errors");
682 309 : break;
683 : case ERROR_GROUP_UNDER:
684 : SAL_INFO("writerfilter", OSL_THIS_FUNC << ": unmatched '}'");
685 0 : break;
686 : case ERROR_GROUP_OVER:
687 : SAL_INFO("writerfilter", OSL_THIS_FUNC << ": unmatched '{'");
688 2 : throw io::WrongFormatException(m_pTokenizer->getPosition(), uno::Reference< uno::XInterface >());
689 : break;
690 : case ERROR_EOF:
691 : SAL_INFO("writerfilter", OSL_THIS_FUNC << ": unexpected end of file");
692 0 : throw io::WrongFormatException(m_pTokenizer->getPosition(), uno::Reference< uno::XInterface >());
693 : break;
694 : case ERROR_HEX_INVALID:
695 : SAL_INFO("writerfilter", OSL_THIS_FUNC << ": invalid hex char");
696 0 : throw io::WrongFormatException(m_pTokenizer->getPosition(), uno::Reference< uno::XInterface >());
697 : break;
698 : case ERROR_CHAR_OVER:
699 : SAL_INFO("writerfilter", OSL_THIS_FUNC << ": characters after last '}'");
700 0 : break;
701 : }
702 309 : }
703 :
704 18 : int RTFDocumentImpl::resolvePict(bool bInline)
705 : {
706 18 : SvMemoryStream aStream;
707 18 : SvStream *pStream = 0;
708 18 : if (!m_pBinaryData.get())
709 : {
710 16 : pStream = &aStream;
711 16 : int b = 0, count = 2;
712 :
713 : // Feed the destination text to a stream.
714 16 : OString aStr = OUStringToOString(m_aStates.top().aDestinationText.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US);
715 16 : const char *str = aStr.getStr();
716 48102 : for (int i = 0; i < aStr.getLength(); ++i)
717 : {
718 48086 : char ch = str[i];
719 48086 : if (ch != 0x0d && ch != 0x0a && ch != 0x20)
720 : {
721 48086 : b = b << 4;
722 48086 : sal_Int8 parsed = m_pTokenizer->asHex(ch);
723 48086 : if (parsed == -1)
724 0 : return ERROR_HEX_INVALID;
725 48086 : b += parsed;
726 48086 : count--;
727 48086 : if (!count)
728 : {
729 24043 : aStream.WriteChar( (char)b );
730 24043 : count = 2;
731 24043 : b = 0;
732 : }
733 : }
734 16 : }
735 : }
736 : else
737 2 : pStream = m_pBinaryData.get();
738 :
739 18 : if (!pStream->Tell())
740 : // No destination text? Then we'll get it later.
741 0 : return 0;
742 :
743 : // Store, and get its URL.
744 18 : pStream->Seek(0);
745 36 : uno::Reference<io::XInputStream> xInputStream(new utl::OInputStreamWrapper(pStream));
746 18 : WMF_EXTERNALHEADER aExtHeader;
747 18 : aExtHeader.mapMode = m_aStates.top().aPicture.eWMetafile;
748 18 : aExtHeader.xExt = m_aStates.top().aPicture.nWidth;
749 18 : aExtHeader.yExt = m_aStates.top().aPicture.nHeight;
750 18 : WMF_EXTERNALHEADER* pExtHeader = &aExtHeader;
751 36 : uno::Reference<lang::XServiceInfo> xServiceInfo(m_aStates.top().aDrawingObject.xShape, uno::UNO_QUERY);
752 18 : if (xServiceInfo.is() && xServiceInfo->supportsService("com.sun.star.text.TextFrame"))
753 0 : pExtHeader = 0;
754 36 : OUString aGraphicUrl = m_pGraphicHelper->importGraphicObject(xInputStream, pExtHeader);
755 :
756 18 : if (m_aStates.top().aPicture.nStyle != BMPSTYLE_NONE)
757 : {
758 : // In case of PNG/JPEG, the real size is known, don't use the values
759 : // provided by picw and pich.
760 15 : OString aURLBS(OUStringToOString(aGraphicUrl, RTL_TEXTENCODING_UTF8));
761 15 : const char aURLBegin[] = "vnd.sun.star.GraphicObject:";
762 15 : if (aURLBS.compareTo(aURLBegin, RTL_CONSTASCII_LENGTH(aURLBegin)) == 0)
763 : {
764 15 : Graphic aGraphic = GraphicObject(aURLBS.copy(RTL_CONSTASCII_LENGTH(aURLBegin))).GetTransformedGraphic();
765 15 : Size aSize(aGraphic.GetPrefSize());
766 30 : MapMode aMap(MAP_100TH_MM);
767 15 : if (aGraphic.GetPrefMapMode().GetMapUnit() == MAP_PIXEL)
768 12 : aSize = Application::GetDefaultDevice()->PixelToLogic(aSize, aMap);
769 : else
770 3 : aSize = OutputDevice::LogicToLogic(aSize, aGraphic.GetPrefMapMode(), aMap);
771 15 : m_aStates.top().aPicture.nWidth = aSize.Width();
772 30 : m_aStates.top().aPicture.nHeight = aSize.Height();
773 15 : }
774 : }
775 :
776 : // Wrap it in an XShape.
777 36 : uno::Reference<drawing::XShape> xShape;
778 18 : if (m_xModelFactory.is())
779 18 : xShape.set(m_xModelFactory->createInstance("com.sun.star.drawing.GraphicObjectShape"), uno::UNO_QUERY);
780 36 : uno::Reference<beans::XPropertySet> xPropertySet(xShape, uno::UNO_QUERY);
781 36 : uno::Reference<drawing::XDrawPageSupplier> xDrawSupplier( m_xDstDoc, uno::UNO_QUERY);
782 18 : if ( xDrawSupplier.is() )
783 : {
784 18 : uno::Reference< drawing::XShapes > xShapes( xDrawSupplier->getDrawPage(), uno::UNO_QUERY );
785 18 : if ( xShapes.is() )
786 18 : xShapes->add( xShape );
787 : }
788 :
789 : // check if the picture is in an OLE object and if the \objdata element is used
790 : // (see RTF_OBJECT in RTFDocumentImpl::dispatchDestination)
791 18 : if (m_bObject)
792 : {
793 : // Set bitmap
794 0 : beans::PropertyValues aMediaProperties(1);
795 0 : aMediaProperties[0].Name = "URL";
796 0 : aMediaProperties[0].Value <<= aGraphicUrl;
797 0 : uno::Reference<graphic::XGraphicProvider> xGraphicProvider(graphic::GraphicProvider::create(m_xContext));
798 0 : uno::Reference<graphic::XGraphic> xGraphic = xGraphicProvider->queryGraphic(aMediaProperties);
799 0 : xPropertySet->setPropertyValue("Graphic", uno::Any(xGraphic));
800 :
801 : // Set the object size
802 0 : awt::Size aSize;
803 0 : aSize.Width = (m_aStates.top().aPicture.nGoalWidth ? m_aStates.top().aPicture.nGoalWidth : m_aStates.top().aPicture.nWidth);
804 0 : aSize.Height = (m_aStates.top().aPicture.nGoalHeight ? m_aStates.top().aPicture.nGoalHeight : m_aStates.top().aPicture.nHeight);
805 0 : xShape->setSize( aSize );
806 :
807 0 : RTFValue::Pointer_t pShapeValue(new RTFValue(xShape));
808 0 : m_aObjectAttributes.set(NS_ooxml::LN_shape, pShapeValue);
809 0 : return 0;
810 : }
811 :
812 18 : if (xPropertySet.is())
813 18 : xPropertySet->setPropertyValue("GraphicURL", uno::Any(aGraphicUrl));
814 :
815 18 : if (m_aStates.top().bInListpicture)
816 : {
817 : // Send the shape directly, no section is started, to additional properties will be ignored anyway.
818 3 : Mapper().startShape(xShape);
819 3 : Mapper().endShape();
820 3 : return 0;
821 : }
822 :
823 : // Send it to the dmapper.
824 30 : RTFSprms aSprms;
825 30 : RTFSprms aAttributes;
826 : // shape attribute
827 30 : RTFSprms aPicAttributes;
828 30 : RTFValue::Pointer_t pShapeValue(new RTFValue(xShape));
829 15 : aPicAttributes.set(NS_ooxml::LN_shape, pShapeValue);
830 : // pic sprm
831 30 : RTFSprms aGraphicDataAttributes;
832 30 : RTFSprms aGraphicDataSprms;
833 30 : RTFValue::Pointer_t pPicValue(new RTFValue(aPicAttributes));
834 15 : aGraphicDataSprms.set(NS_ooxml::LN_pic_pic, pPicValue);
835 : // graphicData sprm
836 30 : RTFSprms aGraphicAttributes;
837 30 : RTFSprms aGraphicSprms;
838 30 : RTFValue::Pointer_t pGraphicDataValue(new RTFValue(aGraphicDataAttributes, aGraphicDataSprms));
839 15 : aGraphicSprms.set(NS_ooxml::LN_CT_GraphicalObject_graphicData, pGraphicDataValue);
840 : // graphic sprm
841 30 : RTFValue::Pointer_t pGraphicValue(new RTFValue(aGraphicAttributes, aGraphicSprms));
842 : // extent sprm
843 30 : RTFSprms aExtentAttributes;
844 : int nXExt, nYExt;
845 15 : nXExt = (m_aStates.top().aPicture.nGoalWidth ? m_aStates.top().aPicture.nGoalWidth : m_aStates.top().aPicture.nWidth);
846 15 : nYExt = (m_aStates.top().aPicture.nGoalHeight ? m_aStates.top().aPicture.nGoalHeight : m_aStates.top().aPicture.nHeight);
847 15 : if (m_aStates.top().aPicture.nScaleX != 100)
848 7 : nXExt = (((long)m_aStates.top().aPicture.nScaleX) * ( nXExt - ( m_aStates.top().aPicture.nCropL + m_aStates.top().aPicture.nCropR ))) / 100L;
849 15 : if (m_aStates.top().aPicture.nScaleY != 100)
850 7 : nYExt = (((long)m_aStates.top().aPicture.nScaleY) * ( nYExt - ( m_aStates.top().aPicture.nCropT + m_aStates.top().aPicture.nCropB ))) / 100L;
851 30 : RTFValue::Pointer_t pXExtValue(new RTFValue(MM100_TO_EMU(nXExt)));
852 30 : RTFValue::Pointer_t pYExtValue(new RTFValue(MM100_TO_EMU(nYExt)));
853 15 : aExtentAttributes.set(NS_ooxml::LN_CT_PositiveSize2D_cx, pXExtValue);
854 15 : aExtentAttributes.set(NS_ooxml::LN_CT_PositiveSize2D_cy, pYExtValue);
855 30 : RTFValue::Pointer_t pExtentValue(new RTFValue(aExtentAttributes));
856 : // docpr sprm
857 30 : RTFSprms aDocprAttributes;
858 15 : for (RTFSprms::Iterator_t i = m_aStates.top().aCharacterAttributes.begin(); i != m_aStates.top().aCharacterAttributes.end(); ++i)
859 0 : if (i->first == NS_ooxml::LN_CT_NonVisualDrawingProps_name || i->first == NS_ooxml::LN_CT_NonVisualDrawingProps_descr)
860 0 : aDocprAttributes.set(i->first, i->second);
861 30 : RTFValue::Pointer_t pDocprValue(new RTFValue(aDocprAttributes));
862 15 : if (bInline)
863 : {
864 10 : RTFSprms aInlineAttributes;
865 10 : aInlineAttributes.set(NS_ooxml::LN_CT_Inline_distT, RTFValue::Pointer_t(new RTFValue(0)));
866 10 : aInlineAttributes.set(NS_ooxml::LN_CT_Inline_distB, RTFValue::Pointer_t(new RTFValue(0)));
867 10 : aInlineAttributes.set(NS_ooxml::LN_CT_Inline_distL, RTFValue::Pointer_t(new RTFValue(0)));
868 10 : aInlineAttributes.set(NS_ooxml::LN_CT_Inline_distR, RTFValue::Pointer_t(new RTFValue(0)));
869 20 : RTFSprms aInlineSprms;
870 10 : aInlineSprms.set(NS_ooxml::LN_CT_Inline_extent, pExtentValue);
871 10 : aInlineSprms.set(NS_ooxml::LN_CT_Inline_docPr, pDocprValue);
872 10 : aInlineSprms.set(NS_ooxml::LN_graphic_graphic, pGraphicValue);
873 : // inline sprm
874 20 : RTFValue::Pointer_t pValue(new RTFValue(aInlineAttributes, aInlineSprms));
875 20 : aSprms.set(NS_ooxml::LN_inline_inline, pValue);
876 : }
877 : else // anchored
878 : {
879 : // wrap sprm
880 5 : RTFSprms aAnchorWrapAttributes;
881 10 : RTFSprms aAnchorAttributes;
882 10 : RTFSprms aAnchorSprms;
883 5 : for (RTFSprms::Iterator_t i = m_aStates.top().aCharacterAttributes.begin(); i != m_aStates.top().aCharacterAttributes.end(); ++i)
884 : {
885 0 : if (i->first == NS_ooxml::LN_CT_WrapSquare_wrapText)
886 0 : aAnchorWrapAttributes.set(i->first, i->second);
887 : }
888 16 : for (RTFSprms::Iterator_t i = m_aStates.top().aCharacterSprms.begin(); i != m_aStates.top().aCharacterSprms.end(); ++i)
889 : {
890 11 : if (i->first == NS_ooxml::LN_EG_WrapType_wrapNone)
891 3 : aAnchorSprms.set(i->first, i->second);
892 : }
893 10 : RTFValue::Pointer_t pAnchorWrapValue(new RTFValue(aAnchorWrapAttributes));
894 5 : aAnchorSprms.set(NS_ooxml::LN_CT_Anchor_extent, pExtentValue);
895 5 : if (aAnchorWrapAttributes.size())
896 0 : aAnchorSprms.set(NS_ooxml::LN_EG_WrapType_wrapSquare, pAnchorWrapValue);
897 :
898 : // See OOXMLFastContextHandler::positionOffset(), we can't just put offset values in an RTFValue.
899 10 : RTFSprms aPoshSprms;
900 5 : if (m_aStates.top().aShape.nHoriOrientRelationToken > 0)
901 3 : aPoshSprms.set(NS_ooxml::LN_CT_PosH_relativeFrom, RTFValue::Pointer_t(new RTFValue(m_aStates.top().aShape.nHoriOrientRelationToken)));
902 5 : if (m_aStates.top().aShape.nLeft > 0)
903 4 : writerfilter::dmapper::PositionHandler::setPositionOffset(OUString::number(MM100_TO_EMU(m_aStates.top().aShape.nLeft)), false);
904 5 : aAnchorSprms.set(NS_ooxml::LN_CT_Anchor_positionH, RTFValue::Pointer_t(new RTFValue(aPoshSprms)));
905 :
906 10 : RTFSprms aPosvSprms;
907 5 : if (m_aStates.top().aShape.nVertOrientRelationToken > 0)
908 3 : aPosvSprms.set(NS_ooxml::LN_CT_PosV_relativeFrom, RTFValue::Pointer_t(new RTFValue(m_aStates.top().aShape.nVertOrientRelationToken)));
909 5 : if (m_aStates.top().aShape.nTop > 0)
910 4 : writerfilter::dmapper::PositionHandler::setPositionOffset(OUString::number(MM100_TO_EMU(m_aStates.top().aShape.nTop)), true);
911 5 : aAnchorSprms.set(NS_ooxml::LN_CT_Anchor_positionV, RTFValue::Pointer_t(new RTFValue(aPosvSprms)));
912 :
913 5 : aAnchorSprms.set(NS_ooxml::LN_CT_Anchor_docPr, pDocprValue);
914 5 : aAnchorSprms.set(NS_ooxml::LN_graphic_graphic, pGraphicValue);
915 : // anchor sprm
916 10 : RTFValue::Pointer_t pValue(new RTFValue(aAnchorAttributes, aAnchorSprms));
917 10 : aSprms.set(NS_ooxml::LN_anchor_anchor, pValue);
918 : }
919 30 : writerfilter::Reference<Properties>::Pointer_t const pProperties(new RTFReferenceProperties(aAttributes, aSprms));
920 15 : checkFirstRun();
921 :
922 15 : if (!m_aStates.top().pCurrentBuffer)
923 : {
924 11 : Mapper().props(pProperties);
925 : // Make sure we don't loose these properties with a too early reset.
926 11 : m_bHadPicture = true;
927 : }
928 : else
929 : {
930 4 : RTFValue::Pointer_t pValue(new RTFValue(aAttributes, aSprms));
931 4 : m_aStates.top().pCurrentBuffer->push_back(Buf_t(BUFFER_PROPS, pValue));
932 : }
933 :
934 33 : return 0;
935 : }
936 :
937 30613 : int RTFDocumentImpl::resolveChars(char ch)
938 : {
939 30613 : if (m_aStates.top().nInternalState == INTERNAL_BIN)
940 : {
941 2 : m_pBinaryData.reset(new SvMemoryStream());
942 2 : m_pBinaryData->WriteChar( ch );
943 25604 : for (int i = 0; i < m_aStates.top().nBinaryToRead - 1; ++i)
944 : {
945 25602 : Strm().ReadChar( ch );
946 25602 : m_pBinaryData->WriteChar( ch );
947 : }
948 2 : m_aStates.top().nInternalState = INTERNAL_NORMAL;
949 2 : return 0;
950 : }
951 :
952 30611 : if (m_aStates.top().nInternalState != INTERNAL_HEX)
953 7073 : checkUnicode(/*bUnicode =*/ false, /*bHex =*/ true);
954 :
955 30611 : OStringBuffer aBuf;
956 :
957 30611 : bool bUnicodeChecked = false;
958 30611 : bool bSkipped = false;
959 814103 : while(!Strm().IsEof() && (m_aStates.top().nInternalState == INTERNAL_HEX || (ch != '{' && ch != '}' && ch != '\\')))
960 : {
961 776419 : if (m_aStates.top().nInternalState == INTERNAL_HEX || (ch != 0x0d && ch != 0x0a))
962 : {
963 770893 : if (m_aStates.top().nCharsToSkip == 0)
964 : {
965 770748 : if (!bUnicodeChecked)
966 : {
967 30466 : checkUnicode(/*bUnicode =*/ true, /*bHex =*/ false);
968 30466 : bUnicodeChecked = true;
969 : }
970 770748 : aBuf.append(ch);
971 : }
972 : else
973 : {
974 145 : bSkipped = true;
975 145 : m_aStates.top().nCharsToSkip--;
976 : }
977 : }
978 : // read a single char if we're in hex mode
979 776419 : if (m_aStates.top().nInternalState == INTERNAL_HEX)
980 23538 : break;
981 752881 : Strm().ReadChar( ch );
982 : }
983 30611 : if (m_aStates.top().nInternalState != INTERNAL_HEX && !Strm().IsEof())
984 7073 : Strm().SeekRel(-1);
985 :
986 30611 : if (m_aStates.top().nInternalState == INTERNAL_HEX && m_aStates.top().nDestinationState != DESTINATION_LEVELNUMBERS)
987 : {
988 23500 : if (!bSkipped)
989 23408 : m_aHexBuffer.append(ch);
990 23500 : return 0;
991 : }
992 :
993 7111 : if (m_aStates.top().nDestinationState == DESTINATION_SKIP)
994 603 : return 0;
995 13016 : OString aStr = aBuf.makeStringAndClear();
996 6508 : if (m_aStates.top().nDestinationState == DESTINATION_LEVELNUMBERS)
997 : {
998 96 : if (aStr.toChar() != ';')
999 38 : m_aStates.top().aLevelNumbers.push_back(sal_Int32(ch));
1000 96 : return 0;
1001 : }
1002 :
1003 12824 : OUString aOUStr(OStringToOUString(aStr, m_aStates.top().nCurrentEncoding));
1004 : SAL_INFO("writerfilter", OSL_THIS_FUNC << ": collected '" << aOUStr << "'");
1005 :
1006 6412 : if (m_aStates.top().nDestinationState == DESTINATION_COLORTABLE)
1007 : {
1008 : // we hit a ';' at the end of each color entry
1009 404 : sal_uInt32 color = (m_aStates.top().aCurrentColor.nRed << 16) | ( m_aStates.top().aCurrentColor.nGreen << 8)
1010 404 : | m_aStates.top().aCurrentColor.nBlue;
1011 404 : m_aColorTable.push_back(color);
1012 : // set components back to zero
1013 404 : m_aStates.top().aCurrentColor = RTFColorTableEntry();
1014 : }
1015 6008 : else if (!aOUStr.isEmpty())
1016 5955 : text(aOUStr);
1017 :
1018 37023 : return 0;
1019 : }
1020 :
1021 10164 : bool RTFFrame::inFrame()
1022 : {
1023 10164 : return nW > 0
1024 10018 : || nH > 0
1025 10018 : || nX > 0
1026 20182 : || nY > 0;
1027 : }
1028 :
1029 95 : void RTFDocumentImpl::singleChar(sal_uInt8 nValue, bool bRunProps)
1030 : {
1031 95 : sal_uInt8 sValue[] = { nValue };
1032 95 : RTFBuffer_t* pCurrentBuffer = m_aStates.top().pCurrentBuffer;
1033 :
1034 95 : if (!pCurrentBuffer)
1035 : {
1036 92 : Mapper().startCharacterGroup();
1037 : // Should we send run properties?
1038 92 : if (bRunProps)
1039 2 : runProps();
1040 92 : Mapper().text(sValue, 1);
1041 92 : Mapper().endCharacterGroup();
1042 : }
1043 : else
1044 : {
1045 3 : pCurrentBuffer->push_back(Buf_t(BUFFER_STARTRUN));
1046 3 : RTFValue::Pointer_t pValue(new RTFValue(*sValue));
1047 3 : pCurrentBuffer->push_back(Buf_t(BUFFER_TEXT, pValue));
1048 3 : pCurrentBuffer->push_back(Buf_t(BUFFER_ENDRUN));
1049 : }
1050 95 : }
1051 :
1052 8380 : void RTFDocumentImpl::text(OUString& rString)
1053 : {
1054 8380 : if (rString.getLength() == 1 && m_aStates.top().nDestinationState != DESTINATION_DOCCOMM)
1055 : {
1056 : // No cheating! Tokenizer ignores bare \r and \n, their hex \'0d / \'0a form doesn't count, either.
1057 3500 : sal_Unicode ch = rString[0];
1058 3500 : if (ch == 0x0d || ch == 0x0a)
1059 1 : return;
1060 : }
1061 :
1062 8379 : bool bRet = true;
1063 8379 : switch (m_aStates.top().nDestinationState)
1064 : {
1065 : case DESTINATION_FONTTABLE:
1066 : case DESTINATION_FONTENTRY:
1067 : case DESTINATION_STYLESHEET:
1068 : case DESTINATION_STYLEENTRY:
1069 : case DESTINATION_REVISIONTABLE:
1070 : case DESTINATION_REVISIONENTRY:
1071 : {
1072 : // ; is the end of the entry
1073 1499 : bool bEnd = false;
1074 1499 : if (rString.endsWithAsciiL(";", 1))
1075 : {
1076 1347 : rString = rString.copy(0, rString.getLength() - 1);
1077 1347 : bEnd = true;
1078 : }
1079 1499 : m_aStates.top().aDestinationText.append(rString);
1080 1499 : if (bEnd)
1081 : {
1082 1347 : switch (m_aStates.top().nDestinationState)
1083 : {
1084 : case DESTINATION_FONTTABLE:
1085 : case DESTINATION_FONTENTRY:
1086 : {
1087 815 : OUString aName = m_aStates.top().aDestinationText.makeStringAndClear();
1088 815 : m_aFontNames[m_nCurrentFontIndex] = aName;
1089 815 : if (m_nCurrentEncoding > 0)
1090 : {
1091 694 : m_aFontEncodings[m_nCurrentFontIndex] = m_nCurrentEncoding;
1092 694 : m_nCurrentEncoding = 0;
1093 : }
1094 815 : m_aStates.top().aTableAttributes.set(NS_ooxml::LN_CT_Font_name, RTFValue::Pointer_t(new RTFValue(aName)));
1095 :
1096 : writerfilter::Reference<Properties>::Pointer_t const pProp(
1097 2445 : new RTFReferenceProperties(m_aStates.top().aTableAttributes, m_aStates.top().aTableSprms)
1098 3260 : );
1099 :
1100 : //See fdo#47347 initial invalid font entry properties are inserted first,
1101 : //so when we attempt to insert the correct ones, there's already an
1102 : //entry in the map for them, so the new ones aren't inserted.
1103 815 : RTFReferenceTable::Entries_t::iterator lb = m_aFontTableEntries.lower_bound(m_nCurrentFontIndex);
1104 815 : if (lb != m_aFontTableEntries.end() && !(m_aFontTableEntries.key_comp()(m_nCurrentFontIndex, lb->first)))
1105 0 : lb->second = pProp;
1106 : else
1107 1630 : m_aFontTableEntries.insert(lb, make_pair(m_nCurrentFontIndex, pProp));
1108 : }
1109 815 : break;
1110 : case DESTINATION_STYLESHEET:
1111 : case DESTINATION_STYLEENTRY:
1112 531 : if (m_aStates.top().aTableAttributes.find(NS_ooxml::LN_CT_Style_type))
1113 : {
1114 521 : OUString aName = m_aStates.top().aDestinationText.makeStringAndClear();
1115 521 : m_aStyleNames[m_nCurrentStyleIndex] = aName;
1116 1042 : RTFValue::Pointer_t pValue(new RTFValue(aName));
1117 521 : m_aStates.top().aTableAttributes.set(NS_ooxml::LN_CT_Style_styleId, pValue);
1118 521 : m_aStates.top().aTableSprms.set(NS_ooxml::LN_CT_Style_name, pValue);
1119 :
1120 : writerfilter::Reference<Properties>::Pointer_t const pProp(
1121 521 : new RTFReferenceProperties(mergeAttributes(), mergeSprms())
1122 1563 : );
1123 1042 : m_aStyleTableEntries.insert(make_pair(m_nCurrentStyleIndex, pProp));
1124 : }
1125 : else
1126 : SAL_INFO("writerfilter", "no RTF style type defined, ignoring");
1127 531 : break;
1128 : case DESTINATION_REVISIONTABLE:
1129 : case DESTINATION_REVISIONENTRY:
1130 1 : m_aAuthors[m_aAuthors.size()] = m_aStates.top().aDestinationText.makeStringAndClear();
1131 1 : break;
1132 0 : default: break;
1133 : }
1134 1347 : resetAttributes();
1135 1347 : resetSprms();
1136 : }
1137 : }
1138 1499 : break;
1139 : case DESTINATION_LEVELTEXT:
1140 : case DESTINATION_SHAPEPROPERTYNAME:
1141 : case DESTINATION_SHAPEPROPERTYVALUE:
1142 : case DESTINATION_BOOKMARKEND:
1143 : case DESTINATION_PICT:
1144 : case DESTINATION_SHAPEPROPERTYVALUEPICT:
1145 : case DESTINATION_FORMFIELDNAME:
1146 : case DESTINATION_FORMFIELDLIST:
1147 : case DESTINATION_DATAFIELD:
1148 : case DESTINATION_AUTHOR:
1149 : case DESTINATION_KEYWORDS:
1150 : case DESTINATION_OPERATOR:
1151 : case DESTINATION_COMPANY:
1152 : case DESTINATION_COMMENT:
1153 : case DESTINATION_OBJDATA:
1154 : case DESTINATION_ANNOTATIONDATE:
1155 : case DESTINATION_ANNOTATIONAUTHOR:
1156 : case DESTINATION_ANNOTATIONREFERENCE:
1157 : case DESTINATION_FALT:
1158 : case DESTINATION_PARAGRAPHNUMBERING_TEXTAFTER:
1159 : case DESTINATION_PARAGRAPHNUMBERING_TEXTBEFORE:
1160 : case DESTINATION_TITLE:
1161 : case DESTINATION_SUBJECT:
1162 : case DESTINATION_DOCCOMM:
1163 : case DESTINATION_ATNID:
1164 : case DESTINATION_ANNOTATIONREFERENCESTART:
1165 : case DESTINATION_ANNOTATIONREFERENCEEND:
1166 : case DESTINATION_MR:
1167 : case DESTINATION_MCHR:
1168 : case DESTINATION_MPOS:
1169 : case DESTINATION_MVERTJC:
1170 : case DESTINATION_MSTRIKEH:
1171 : case DESTINATION_MDEGHIDE:
1172 : case DESTINATION_MBEGCHR:
1173 : case DESTINATION_MSEPCHR:
1174 : case DESTINATION_MENDCHR:
1175 : case DESTINATION_MSUBHIDE:
1176 : case DESTINATION_MSUPHIDE:
1177 : case DESTINATION_MTYPE:
1178 : case DESTINATION_MGROW:
1179 2442 : m_aStates.top().aDestinationText.append(rString);
1180 2442 : break;
1181 : default:
1182 4438 : bRet = false;
1183 4438 : break;
1184 : }
1185 8379 : if (bRet)
1186 3941 : return;
1187 :
1188 4438 : if (!m_aIgnoreFirst.isEmpty() && m_aIgnoreFirst.equals(rString))
1189 : {
1190 0 : m_aIgnoreFirst = "";
1191 0 : return;
1192 : }
1193 :
1194 : // Are we in the middle of the table definition? (No cell defs yet, but we already have some cell props.)
1195 4439 : if (m_aStates.top().aTableCellSprms.find(NS_ooxml::LN_CT_TcPrBase_vAlign).get() &&
1196 1 : m_nTopLevelCells == 0)
1197 : {
1198 1 : m_aTableBufferStack.back().push_back(
1199 2 : Buf_t(BUFFER_UTEXT, RTFValue::Pointer_t(new RTFValue(rString))));
1200 1 : return;
1201 : }
1202 :
1203 4437 : checkFirstRun();
1204 4437 : checkNeedPap();
1205 :
1206 : // Don't return earlier, a bookmark start has to be in a paragraph group.
1207 4437 : if (m_aStates.top().nDestinationState == DESTINATION_BOOKMARKSTART)
1208 : {
1209 3 : m_aStates.top().aDestinationText.append(rString);
1210 3 : return;
1211 : }
1212 :
1213 4434 : RTFBuffer_t* pCurrentBuffer = m_aStates.top().pCurrentBuffer;
1214 :
1215 4434 : if (!pCurrentBuffer && m_aStates.top().nDestinationState != DESTINATION_FOOTNOTE)
1216 4163 : Mapper().startCharacterGroup();
1217 271 : else if (pCurrentBuffer)
1218 : {
1219 271 : RTFValue::Pointer_t pValue;
1220 271 : pCurrentBuffer->push_back(Buf_t(BUFFER_STARTRUN, pValue));
1221 : }
1222 :
1223 8868 : if (m_aStates.top().nDestinationState == DESTINATION_NORMAL
1224 47 : || m_aStates.top().nDestinationState == DESTINATION_FIELDRESULT
1225 4477 : || m_aStates.top().nDestinationState == DESTINATION_SHAPETEXT)
1226 4416 : runProps();
1227 :
1228 4434 : if (!pCurrentBuffer)
1229 4163 : Mapper().utext(reinterpret_cast<sal_uInt8 const*>(rString.getStr()), rString.getLength());
1230 : else
1231 : {
1232 271 : RTFValue::Pointer_t pValue(new RTFValue(rString));
1233 271 : pCurrentBuffer->push_back(Buf_t(BUFFER_UTEXT, pValue));
1234 : }
1235 :
1236 4434 : m_bNeedCr = true;
1237 :
1238 4434 : if (!pCurrentBuffer && m_aStates.top().nDestinationState != DESTINATION_FOOTNOTE)
1239 4163 : Mapper().endCharacterGroup();
1240 271 : else if(pCurrentBuffer)
1241 : {
1242 271 : RTFValue::Pointer_t pValue;
1243 271 : pCurrentBuffer->push_back(Buf_t(BUFFER_ENDRUN, pValue));
1244 : }
1245 : }
1246 :
1247 86 : void RTFDocumentImpl::prepareProperties(
1248 : RTFParserState & rState,
1249 : writerfilter::Reference<Properties>::Pointer_t & o_rpParagraphProperties,
1250 : writerfilter::Reference<Properties>::Pointer_t & o_rpFrameProperties,
1251 : writerfilter::Reference<Properties>::Pointer_t & o_rpTableRowProperties,
1252 : int const nCells, int const nCurrentCellX)
1253 : {
1254 172 : o_rpParagraphProperties = getProperties(
1255 86 : rState.aParagraphAttributes, rState.aParagraphSprms);
1256 :
1257 86 : if (rState.aFrame.hasProperties())
1258 : {
1259 : o_rpFrameProperties.reset(new RTFReferenceProperties(
1260 0 : RTFSprms(), rState.aFrame.getSprms()));
1261 : }
1262 :
1263 : // Table width.
1264 86 : RTFValue::Pointer_t const pUnitValue(new RTFValue(3));
1265 : lcl_putNestedAttribute(rState.aTableRowSprms,
1266 : NS_ooxml::LN_CT_TblPrBase_tblW, NS_ooxml::LN_CT_TblWidth_type,
1267 86 : pUnitValue);
1268 172 : RTFValue::Pointer_t const pWValue(new RTFValue(nCurrentCellX));
1269 : lcl_putNestedAttribute(rState.aTableRowSprms,
1270 86 : NS_ooxml::LN_CT_TblPrBase_tblW, NS_ooxml::LN_CT_TblWidth_w, pWValue);
1271 :
1272 172 : RTFValue::Pointer_t const pRowValue(new RTFValue(1));
1273 86 : if (nCells > 0)
1274 86 : rState.aTableRowSprms.set(NS_ooxml::LN_tblRow, pRowValue);
1275 :
1276 : RTFValue::Pointer_t const pCellMar =
1277 172 : rState.aTableRowSprms.find(NS_ooxml::LN_CT_TblPrBase_tblCellMar);
1278 86 : if (!pCellMar.get())
1279 : {
1280 : // If no cell margins are defined, the default left/right margin is 0 in Word, but not in Writer.
1281 86 : RTFSprms aAttributes;
1282 : aAttributes.set(NS_ooxml::LN_CT_TblWidth_type, RTFValue::Pointer_t(
1283 86 : new RTFValue(NS_ooxml::LN_Value_ST_TblWidth_dxa)));
1284 : aAttributes.set(NS_ooxml::LN_CT_TblWidth_w,
1285 86 : RTFValue::Pointer_t(new RTFValue(0)));
1286 : lcl_putNestedSprm(rState.aTableRowSprms,
1287 : NS_ooxml::LN_CT_TblPrBase_tblCellMar,
1288 : NS_ooxml::LN_CT_TblCellMar_left,
1289 86 : RTFValue::Pointer_t(new RTFValue(aAttributes)));
1290 : lcl_putNestedSprm(rState.aTableRowSprms,
1291 : NS_ooxml::LN_CT_TblPrBase_tblCellMar,
1292 : NS_ooxml::LN_CT_TblCellMar_right,
1293 86 : RTFValue::Pointer_t(new RTFValue(aAttributes)));
1294 : }
1295 :
1296 : o_rpTableRowProperties.reset(new RTFReferenceProperties(
1297 172 : rState.aTableRowAttributes, rState.aTableRowSprms));
1298 86 : }
1299 :
1300 86 : void RTFDocumentImpl::sendProperties(
1301 : writerfilter::Reference<Properties>::Pointer_t const& pParagraphProperties,
1302 : writerfilter::Reference<Properties>::Pointer_t const& pFrameProperties,
1303 : writerfilter::Reference<Properties>::Pointer_t const& pTableRowProperties)
1304 : {
1305 86 : Mapper().props(pParagraphProperties);
1306 :
1307 86 : if (pFrameProperties)
1308 : {
1309 0 : Mapper().props(pFrameProperties);
1310 : }
1311 :
1312 86 : Mapper().props(pTableRowProperties);
1313 :
1314 86 : tableBreak();
1315 86 : }
1316 :
1317 86 : void RTFDocumentImpl::replayRowBuffer(
1318 : RTFBuffer_t & rBuffer,
1319 : ::std::deque<RTFSprms> & rCellsSrpms,
1320 : ::std::deque<RTFSprms> & rCellsAttributes,
1321 : int const nCells)
1322 : {
1323 432 : for (int i = 0; i < nCells; ++i)
1324 : {
1325 346 : replayBuffer(rBuffer, &rCellsSrpms.front(), &rCellsAttributes.front());
1326 346 : rCellsSrpms.pop_front();
1327 346 : rCellsAttributes.pop_front();
1328 : }
1329 86 : for (size_t i = 0; i < rBuffer.size(); ++i)
1330 : {
1331 : SAL_WARN_IF( BUFFER_CELLEND == boost::get<0>(rBuffer[i]),
1332 : "writerfilter.rtf", "dropping table cell!");
1333 : }
1334 : assert(0 == rCellsSrpms.size());
1335 : assert(0 == rCellsAttributes.size());
1336 86 : }
1337 :
1338 365 : void RTFDocumentImpl::replayBuffer(RTFBuffer_t& rBuffer,
1339 : RTFSprms *const pSprms, RTFSprms const*const pAttributes)
1340 : {
1341 2180 : while (rBuffer.size())
1342 : {
1343 1698 : Buf_t aTuple(rBuffer.front());
1344 1698 : rBuffer.pop_front();
1345 1698 : if (boost::get<0>(aTuple) == BUFFER_PROPS)
1346 : {
1347 : writerfilter::Reference<Properties>::Pointer_t const pProp(
1348 : new RTFReferenceProperties(
1349 605 : boost::get<1>(aTuple)->getAttributes(),
1350 1210 : boost::get<1>(aTuple)->getSprms())
1351 1815 : );
1352 605 : Mapper().props(pProp);
1353 : }
1354 1093 : else if (boost::get<0>(aTuple) == BUFFER_NESTROW)
1355 : {
1356 6 : TableRowBuffer & rRowBuffer(*boost::get<2>(aTuple));
1357 :
1358 : replayRowBuffer(rRowBuffer.buffer, rRowBuffer.cellsSprms,
1359 6 : rRowBuffer.cellsAttributes, rRowBuffer.nCells);
1360 :
1361 : sendProperties(rRowBuffer.pParaProperties,
1362 6 : rRowBuffer.pFrameProperties, rRowBuffer.pRowProperties);
1363 : }
1364 1087 : else if (boost::get<0>(aTuple) == BUFFER_CELLEND)
1365 : {
1366 : assert(pSprms && pAttributes);
1367 248 : RTFValue::Pointer_t pValue(new RTFValue(1));
1368 248 : pSprms->set(NS_ooxml::LN_tblCell, pValue);
1369 : writerfilter::Reference<Properties>::Pointer_t const pTableCellProperties(
1370 496 : new RTFReferenceProperties(*pAttributes, *pSprms));
1371 248 : Mapper().props(pTableCellProperties);
1372 248 : tableBreak();
1373 496 : break;
1374 : }
1375 839 : else if (boost::get<0>(aTuple) == BUFFER_STARTRUN)
1376 274 : Mapper().startCharacterGroup();
1377 565 : else if (boost::get<0>(aTuple) == BUFFER_TEXT)
1378 : {
1379 3 : sal_uInt8 const nValue = boost::get<1>(aTuple)->getInt();
1380 3 : Mapper().text(&nValue, 1);
1381 : }
1382 562 : else if (boost::get<0>(aTuple) == BUFFER_UTEXT)
1383 : {
1384 272 : OUString const aString(boost::get<1>(aTuple)->getString());
1385 272 : Mapper().utext(reinterpret_cast<sal_uInt8 const*>(aString.getStr()), aString.getLength());
1386 : }
1387 290 : else if (boost::get<0>(aTuple) == BUFFER_ENDRUN)
1388 274 : Mapper().endCharacterGroup();
1389 16 : else if (boost::get<0>(aTuple) == BUFFER_PAR)
1390 14 : parBreak();
1391 2 : else if (boost::get<0>(aTuple) == BUFFER_STARTSHAPE)
1392 1 : m_pSdrImport->resolve(boost::get<1>(aTuple)->getShape(), false);
1393 1 : else if (boost::get<0>(aTuple) == BUFFER_ENDSHAPE)
1394 1 : m_pSdrImport->close();
1395 : else
1396 : assert(false);
1397 1450 : }
1398 :
1399 365 : }
1400 :
1401 5712 : int RTFDocumentImpl::dispatchDestination(RTFKeyword nKeyword)
1402 : {
1403 5712 : setNeedSect();
1404 5712 : checkUnicode(/*bUnicode =*/ true, /*bHex =*/ true);
1405 5712 : RTFSkipDestination aSkip(*this);
1406 5712 : switch (nKeyword)
1407 : {
1408 : case RTF_RTF:
1409 286 : break;
1410 : case RTF_FONTTBL:
1411 99 : m_aStates.top().nDestinationState = DESTINATION_FONTTABLE;
1412 99 : break;
1413 : case RTF_COLORTBL:
1414 83 : m_aStates.top().nDestinationState = DESTINATION_COLORTABLE;
1415 83 : break;
1416 : case RTF_STYLESHEET:
1417 81 : m_aStates.top().nDestinationState = DESTINATION_STYLESHEET;
1418 81 : break;
1419 : case RTF_FIELD:
1420 12 : m_aStates.top().nDestinationState = DESTINATION_FIELD;
1421 12 : break;
1422 : case RTF_FLDINST:
1423 : {
1424 : // Look for the field type
1425 12 : sal_Size nPos = Strm().Tell();
1426 12 : OStringBuffer aBuf;
1427 12 : char ch = 0;
1428 12 : bool bFoundCode = false;
1429 12 : bool bInKeyword = false;
1430 177 : while (!bFoundCode && ch != '}')
1431 : {
1432 153 : Strm().ReadChar( ch );
1433 153 : if ('\\' == ch)
1434 9 : bInKeyword = true;
1435 153 : if (!bInKeyword && isalnum(ch))
1436 70 : aBuf.append(ch);
1437 83 : else if (bInKeyword && isspace(ch))
1438 5 : bInKeyword = false;
1439 153 : if (!aBuf.isEmpty() && !isalnum(ch))
1440 12 : bFoundCode = true;
1441 : }
1442 12 : Strm().Seek(nPos);
1443 :
1444 : // Form data should be handled only for form fields if any
1445 12 : if (aBuf.toString().indexOf(OString("FORM")) != -1 )
1446 0 : m_bFormField = true;
1447 :
1448 12 : singleChar(0x13);
1449 12 : m_aStates.top().nDestinationState = DESTINATION_FIELDINSTRUCTION;
1450 : }
1451 12 : break;
1452 : case RTF_FLDRSLT:
1453 10 : m_aStates.top().nDestinationState = DESTINATION_FIELDRESULT;
1454 10 : break;
1455 : case RTF_LISTTABLE:
1456 16 : m_aStates.top().nDestinationState = DESTINATION_LISTTABLE;
1457 16 : break;
1458 : case RTF_LISTPICTURE:
1459 3 : m_aStates.top().nDestinationState = DESTINATION_LISTPICTURE;
1460 3 : m_aStates.top().bInListpicture = true;
1461 3 : break;
1462 : case RTF_LIST:
1463 20 : m_aStates.top().nDestinationState = DESTINATION_LISTENTRY;
1464 20 : break;
1465 : case RTF_LFOLEVEL:
1466 1 : m_aStates.top().nDestinationState = DESTINATION_LFOLEVEL;
1467 1 : m_aStates.top().aTableSprms.clear();
1468 1 : break;
1469 : case RTF_LISTOVERRIDETABLE:
1470 15 : m_aStates.top().nDestinationState = DESTINATION_LISTOVERRIDETABLE;
1471 15 : break;
1472 : case RTF_LISTOVERRIDE:
1473 19 : m_aStates.top().nDestinationState = DESTINATION_LISTOVERRIDEENTRY;
1474 19 : break;
1475 : case RTF_LISTLEVEL:
1476 56 : m_aStates.top().nDestinationState = DESTINATION_LISTLEVEL;
1477 56 : break;
1478 : case RTF_LEVELTEXT:
1479 57 : m_aStates.top().nDestinationState = DESTINATION_LEVELTEXT;
1480 57 : break;
1481 : case RTF_LEVELNUMBERS:
1482 58 : m_aStates.top().nDestinationState = DESTINATION_LEVELNUMBERS;
1483 58 : break;
1484 : case RTF_SHPPICT:
1485 8 : m_aStates.top().resetFrame();
1486 8 : m_aStates.top().nDestinationState = DESTINATION_SHPPICT;
1487 8 : break;
1488 : case RTF_PICT:
1489 18 : if (m_aStates.top().nDestinationState != DESTINATION_SHAPEPROPERTYVALUE)
1490 13 : m_aStates.top().nDestinationState = DESTINATION_PICT; // as character
1491 : else
1492 5 : m_aStates.top().nDestinationState = DESTINATION_SHAPEPROPERTYVALUEPICT; // anchored inside a shape
1493 18 : break;
1494 : case RTF_PICPROP:
1495 4 : m_aStates.top().nDestinationState = DESTINATION_PICPROP;
1496 4 : break;
1497 : case RTF_SP:
1498 595 : m_aStates.top().nDestinationState = DESTINATION_SHAPEPROPERTY;
1499 595 : break;
1500 : case RTF_SN:
1501 595 : m_aStates.top().nDestinationState = DESTINATION_SHAPEPROPERTYNAME;
1502 595 : break;
1503 : case RTF_SV:
1504 595 : m_aStates.top().nDestinationState = DESTINATION_SHAPEPROPERTYVALUE;
1505 595 : break;
1506 : case RTF_SHP:
1507 67 : m_bNeedCrOrig = m_bNeedCr;
1508 67 : m_aStates.top().nDestinationState = DESTINATION_SHAPE;
1509 67 : m_aStates.top().bInShape = true;
1510 67 : break;
1511 : case RTF_SHPINST:
1512 72 : m_aStates.top().nDestinationState = DESTINATION_SHAPEINSTRUCTION;
1513 72 : break;
1514 : case RTF_NESTTABLEPROPS:
1515 : // do not set any properties of outer table at nested table!
1516 6 : m_aStates.top().aTableCellSprms = m_aDefaultState.aTableCellSprms;
1517 6 : m_aStates.top().aTableCellAttributes =
1518 6 : m_aDefaultState.aTableCellAttributes;
1519 6 : m_aNestedTableCellsSprms.clear();
1520 6 : m_aNestedTableCellsAttributes.clear();
1521 6 : m_nNestedCells = 0;
1522 6 : m_aStates.top().nDestinationState = DESTINATION_NESTEDTABLEPROPERTIES;
1523 6 : break;
1524 : case RTF_HEADER:
1525 : case RTF_FOOTER:
1526 : case RTF_HEADERL:
1527 : case RTF_HEADERR:
1528 : case RTF_HEADERF:
1529 : case RTF_FOOTERL:
1530 : case RTF_FOOTERR:
1531 : case RTF_FOOTERF:
1532 18 : if (!m_pSuperstream)
1533 : {
1534 9 : Id nId = 0;
1535 9 : sal_Size nPos = m_nGroupStartPos - 1;
1536 9 : switch (nKeyword)
1537 : {
1538 6 : case RTF_HEADER: nId = NS_ooxml::LN_headerr; break;
1539 0 : case RTF_FOOTER: nId = NS_ooxml::LN_footerr; break;
1540 0 : case RTF_HEADERL: nId = NS_ooxml::LN_headerl; break;
1541 1 : case RTF_HEADERR: nId = NS_ooxml::LN_headerr; break;
1542 1 : case RTF_HEADERF: nId = NS_ooxml::LN_headerf; break;
1543 0 : case RTF_FOOTERL: nId = NS_ooxml::LN_footerl; break;
1544 0 : case RTF_FOOTERR: nId = NS_ooxml::LN_footerr; break;
1545 1 : case RTF_FOOTERF: nId = NS_ooxml::LN_footerf; break;
1546 0 : default: break;
1547 : }
1548 9 : m_nHeaderFooterPositions.push(make_pair(nId, nPos));
1549 9 : m_aStates.top().nDestinationState = DESTINATION_SKIP;
1550 : }
1551 18 : break;
1552 : case RTF_FOOTNOTE:
1553 18 : if (!m_pSuperstream)
1554 : {
1555 9 : Id nId = NS_ooxml::LN_footnote;
1556 :
1557 : // Check if this is an endnote.
1558 9 : OStringBuffer aBuf;
1559 : char ch;
1560 72 : for (int i = 0; i < 7; ++i)
1561 : {
1562 63 : Strm().ReadChar( ch );
1563 63 : aBuf.append(ch);
1564 : }
1565 18 : OString aKeyword = aBuf.makeStringAndClear();
1566 9 : if (aKeyword.equals("\\ftnalt"))
1567 0 : nId = NS_ooxml::LN_endnote;
1568 :
1569 9 : m_bHasFootnote = true;
1570 9 : if (m_aStates.top().pCurrentBuffer == &m_aSuperBuffer)
1571 5 : m_aStates.top().pCurrentBuffer = 0;
1572 9 : bool bCustomMark = false;
1573 18 : OUString aCustomMark;
1574 18 : while (m_aSuperBuffer.size())
1575 : {
1576 0 : Buf_t aTuple = m_aSuperBuffer.front();
1577 0 : m_aSuperBuffer.pop_front();
1578 0 : if (boost::get<0>(aTuple) == BUFFER_UTEXT)
1579 : {
1580 0 : aCustomMark = boost::get<1>(aTuple)->getString();
1581 0 : bCustomMark = true;
1582 : }
1583 0 : }
1584 9 : m_aStates.top().nDestinationState = DESTINATION_FOOTNOTE;
1585 9 : if (bCustomMark)
1586 0 : Mapper().startCharacterGroup();
1587 9 : resolveSubstream(m_nGroupStartPos - 1, nId, aCustomMark);
1588 9 : if (bCustomMark)
1589 : {
1590 0 : m_aStates.top().aCharacterAttributes.clear();
1591 0 : m_aStates.top().aCharacterSprms.clear();
1592 0 : RTFValue::Pointer_t pValue(new RTFValue(1));
1593 0 : m_aStates.top().aCharacterAttributes.set(NS_ooxml::LN_CT_FtnEdnRef_customMarkFollows, pValue);
1594 0 : text(aCustomMark);
1595 0 : Mapper().endCharacterGroup();
1596 : }
1597 18 : m_aStates.top().nDestinationState = DESTINATION_SKIP;
1598 : }
1599 18 : break;
1600 : case RTF_BKMKSTART:
1601 3 : m_aStates.top().nDestinationState = DESTINATION_BOOKMARKSTART;
1602 3 : break;
1603 : case RTF_BKMKEND:
1604 3 : m_aStates.top().nDestinationState = DESTINATION_BOOKMARKEND;
1605 3 : break;
1606 : case RTF_REVTBL:
1607 1 : m_aStates.top().nDestinationState = DESTINATION_REVISIONTABLE;
1608 1 : break;
1609 : case RTF_ANNOTATION:
1610 14 : if (!m_pSuperstream)
1611 : {
1612 7 : resolveSubstream(m_nGroupStartPos - 1, NS_ooxml::LN_annotation);
1613 7 : m_aStates.top().nDestinationState = DESTINATION_SKIP;
1614 : }
1615 : else
1616 : {
1617 : // If there is an author set, emit it now.
1618 7 : if (!m_aAuthor.isEmpty() || !m_aAuthorInitials.isEmpty())
1619 : {
1620 6 : RTFSprms aAttributes;
1621 6 : if (!m_aAuthor.isEmpty())
1622 : {
1623 6 : RTFValue::Pointer_t pValue(new RTFValue(m_aAuthor));
1624 6 : aAttributes.set(NS_ooxml::LN_CT_TrackChange_author, pValue);
1625 : }
1626 6 : if (!m_aAuthorInitials.isEmpty())
1627 : {
1628 5 : RTFValue::Pointer_t pValue(new RTFValue(m_aAuthorInitials));
1629 5 : aAttributes.set(NS_ooxml::LN_CT_Comment_initials, pValue);
1630 : }
1631 12 : writerfilter::Reference<Properties>::Pointer_t const pProperties(new RTFReferenceProperties(aAttributes));
1632 12 : Mapper().props(pProperties);
1633 : }
1634 : }
1635 14 : break;
1636 : case RTF_SHPTXT:
1637 : case RTF_DPTXBXTEXT:
1638 : {
1639 43 : bool bPictureFrame = false;
1640 372 : for (size_t i = 0; i < m_aStates.top().aShape.aProperties.size(); ++i)
1641 : {
1642 330 : std::pair<OUString, OUString>& rProperty = m_aStates.top().aShape.aProperties[i];
1643 330 : if (rProperty.first == "shapeType" && rProperty.second == OUString::number(ESCHER_ShpInst_PictureFrame))
1644 : {
1645 1 : bPictureFrame = true;
1646 1 : break;
1647 : }
1648 : }
1649 43 : if (bPictureFrame)
1650 : // Skip text on picture frames.
1651 1 : m_aStates.top().nDestinationState = DESTINATION_SKIP;
1652 : else
1653 : {
1654 42 : m_aStates.top().nDestinationState = DESTINATION_SHAPETEXT;
1655 42 : checkFirstRun();
1656 42 : dispatchFlag(RTF_PARD);
1657 42 : m_bNeedPap = true;
1658 42 : if (nKeyword == RTF_SHPTXT)
1659 : {
1660 32 : if (!m_aStates.top().pCurrentBuffer)
1661 31 : m_pSdrImport->resolve(m_aStates.top().aShape, false);
1662 : else
1663 : {
1664 1 : RTFValue::Pointer_t pValue(new RTFValue(m_aStates.top().aShape));
1665 1 : m_aStates.top().pCurrentBuffer->push_back(
1666 2 : Buf_t(BUFFER_STARTSHAPE, pValue));
1667 : }
1668 : }
1669 : }
1670 : }
1671 43 : break;
1672 : case RTF_FORMFIELD:
1673 0 : if (m_aStates.top().nDestinationState == DESTINATION_FIELDINSTRUCTION)
1674 0 : m_aStates.top().nDestinationState = DESTINATION_FORMFIELD;
1675 0 : break;
1676 : case RTF_FFNAME:
1677 0 : m_aStates.top().nDestinationState = DESTINATION_FORMFIELDNAME;
1678 0 : break;
1679 : case RTF_FFL:
1680 0 : m_aStates.top().nDestinationState = DESTINATION_FORMFIELDLIST;
1681 0 : break;
1682 : case RTF_DATAFIELD:
1683 0 : m_aStates.top().nDestinationState = DESTINATION_DATAFIELD;
1684 0 : break;
1685 : case RTF_INFO:
1686 75 : m_aStates.top().nDestinationState = DESTINATION_INFO;
1687 75 : break;
1688 : case RTF_CREATIM:
1689 58 : m_aStates.top().nDestinationState = DESTINATION_CREATIONTIME;
1690 58 : break;
1691 : case RTF_REVTIM:
1692 58 : m_aStates.top().nDestinationState = DESTINATION_REVISIONTIME;
1693 58 : break;
1694 : case RTF_PRINTIM:
1695 56 : m_aStates.top().nDestinationState = DESTINATION_PRINTTIME;
1696 56 : break;
1697 : case RTF_AUTHOR:
1698 14 : m_aStates.top().nDestinationState = DESTINATION_AUTHOR;
1699 14 : break;
1700 : case RTF_KEYWORDS:
1701 3 : m_aStates.top().nDestinationState = DESTINATION_KEYWORDS;
1702 3 : break;
1703 : case RTF_OPERATOR:
1704 3 : m_aStates.top().nDestinationState = DESTINATION_OPERATOR;
1705 3 : break;
1706 : case RTF_COMPANY:
1707 7 : m_aStates.top().nDestinationState = DESTINATION_COMPANY;
1708 7 : break;
1709 : case RTF_COMMENT:
1710 58 : m_aStates.top().nDestinationState = DESTINATION_COMMENT;
1711 58 : break;
1712 : case RTF_OBJECT:
1713 : {
1714 : // beginning of an OLE Object
1715 1 : m_aStates.top().nDestinationState = DESTINATION_OBJECT;
1716 :
1717 : // check if the object is in a special container (e.g. a table)
1718 1 : if (!m_aStates.top().pCurrentBuffer)
1719 : {
1720 : // the object is in a table or another container.
1721 : // Don't try to treate it as an OLE object (fdo#53594).
1722 : // Use the \result (RTF_RESULT) element of the object instead,
1723 : // the result element contain picture representing the OLE Object.
1724 0 : m_bObject = true;
1725 : }
1726 : }
1727 1 : break;
1728 : case RTF_OBJDATA:
1729 : // check if the object is in a special container (e.g. a table)
1730 1 : if (m_aStates.top().pCurrentBuffer)
1731 : {
1732 : // the object is in a table or another container.
1733 : // Use the \result (RTF_RESULT) element of the object instead,
1734 : // of the \objdata.
1735 1 : m_aStates.top().nDestinationState = DESTINATION_SKIP;
1736 : }
1737 : else
1738 : {
1739 0 : m_aStates.top().nDestinationState = DESTINATION_OBJDATA;
1740 : }
1741 1 : break;
1742 : case RTF_RESULT:
1743 1 : m_aStates.top().nDestinationState = DESTINATION_RESULT;
1744 1 : break;
1745 : case RTF_ATNDATE:
1746 6 : m_aStates.top().nDestinationState = DESTINATION_ANNOTATIONDATE;
1747 6 : break;
1748 : case RTF_ATNAUTHOR:
1749 6 : m_aStates.top().nDestinationState = DESTINATION_ANNOTATIONAUTHOR;
1750 6 : break;
1751 : case RTF_ATNREF:
1752 6 : m_aStates.top().nDestinationState = DESTINATION_ANNOTATIONREFERENCE;
1753 6 : break;
1754 : case RTF_FALT:
1755 136 : m_aStates.top().nDestinationState = DESTINATION_FALT;
1756 136 : break;
1757 : case RTF_FLYMAINCNT:
1758 2 : m_aStates.top().nDestinationState = DESTINATION_FLYMAINCONTENT;
1759 2 : break;
1760 : case RTF_LISTTEXT:
1761 : // Should be ignored by any reader that understands Word 97 through Word 2007 numbering.
1762 : case RTF_NONESTTABLES:
1763 : // This destination should be ignored by readers that support nested tables.
1764 15 : m_aStates.top().nDestinationState = DESTINATION_SKIP;
1765 15 : break;
1766 : case RTF_DO:
1767 24 : m_aStates.top().nDestinationState = DESTINATION_DRAWINGOBJECT;
1768 24 : break;
1769 : case RTF_PN:
1770 4 : m_aStates.top().nDestinationState = DESTINATION_PARAGRAPHNUMBERING;
1771 4 : break;
1772 : case RTF_PNTEXT:
1773 : // This destination should be ignored by readers that support paragraph numbering.
1774 0 : m_aStates.top().nDestinationState = DESTINATION_SKIP;
1775 0 : break;
1776 : case RTF_PNTXTA:
1777 3 : m_aStates.top().nDestinationState = DESTINATION_PARAGRAPHNUMBERING_TEXTAFTER;
1778 3 : break;
1779 : case RTF_PNTXTB:
1780 3 : m_aStates.top().nDestinationState = DESTINATION_PARAGRAPHNUMBERING_TEXTBEFORE;
1781 3 : break;
1782 : case RTF_TITLE:
1783 : // \title inside \upr but outside \ud should be ignored.
1784 13 : if (m_aStates.top().nDestinationState != DESTINATION_UPR)
1785 10 : m_aStates.top().nDestinationState = DESTINATION_TITLE;
1786 : else
1787 3 : m_aStates.top().nDestinationState = DESTINATION_SKIP;
1788 13 : break;
1789 : case RTF_SUBJECT:
1790 4 : m_aStates.top().nDestinationState = DESTINATION_SUBJECT;
1791 4 : break;
1792 : case RTF_DOCCOMM:
1793 5 : m_aStates.top().nDestinationState = DESTINATION_DOCCOMM;
1794 5 : break;
1795 : case RTF_ATRFSTART:
1796 6 : m_aStates.top().nDestinationState = DESTINATION_ANNOTATIONREFERENCESTART;
1797 6 : break;
1798 : case RTF_ATRFEND:
1799 6 : m_aStates.top().nDestinationState = DESTINATION_ANNOTATIONREFERENCEEND;
1800 6 : break;
1801 : case RTF_ATNID:
1802 6 : m_aStates.top().nDestinationState = DESTINATION_ATNID;
1803 6 : break;
1804 : case RTF_MMATH:
1805 : case RTF_MOMATHPARA:
1806 : // Nothing to do here (just enter the destination) till RTF_MMATHPR is implemented.
1807 113 : break;
1808 585 : case RTF_MR: m_aStates.top().nDestinationState = DESTINATION_MR; break;
1809 57 : case RTF_MCHR: m_aStates.top().nDestinationState = DESTINATION_MCHR; break;
1810 5 : case RTF_MPOS: m_aStates.top().nDestinationState = DESTINATION_MPOS; break;
1811 4 : case RTF_MVERTJC: m_aStates.top().nDestinationState = DESTINATION_MVERTJC; break;
1812 3 : case RTF_MSTRIKEH: m_aStates.top().nDestinationState = DESTINATION_MSTRIKEH; break;
1813 4 : case RTF_MDEGHIDE: m_aStates.top().nDestinationState = DESTINATION_MDEGHIDE; break;
1814 6 : case RTF_MTYPE: m_aStates.top().nDestinationState = DESTINATION_MTYPE; break;
1815 2 : case RTF_MGROW: m_aStates.top().nDestinationState = DESTINATION_MGROW; break;
1816 : case RTF_MHIDETOP:
1817 : case RTF_MHIDEBOT:
1818 : case RTF_MHIDELEFT:
1819 : case RTF_MHIDERIGHT:
1820 : // SmOoxmlImport::handleBorderBox will ignore these anyway, so silently ignore for now.
1821 12 : m_aStates.top().nDestinationState = DESTINATION_SKIP;
1822 12 : break;
1823 2 : case RTF_MSUBHIDE: m_aStates.top().nDestinationState = DESTINATION_MSUBHIDE; break;
1824 2 : case RTF_MSUPHIDE: m_aStates.top().nDestinationState = DESTINATION_MSUPHIDE; break;
1825 40 : case RTF_MBEGCHR: m_aStates.top().nDestinationState = DESTINATION_MBEGCHR; break;
1826 4 : case RTF_MSEPCHR: m_aStates.top().nDestinationState = DESTINATION_MSEPCHR; break;
1827 40 : case RTF_MENDCHR: m_aStates.top().nDestinationState = DESTINATION_MENDCHR; break;
1828 : case RTF_UPR:
1829 5 : m_aStates.top().nDestinationState = DESTINATION_UPR;
1830 5 : break;
1831 : case RTF_UD:
1832 : // Anything inside \ud is just normal Unicode content.
1833 5 : m_aStates.top().nDestinationState = DESTINATION_NORMAL;
1834 5 : break;
1835 : case RTF_BACKGROUND:
1836 1 : m_aStates.top().nDestinationState = DESTINATION_BACKGROUND;
1837 1 : m_aStates.top().bInBackground = true;
1838 1 : break;
1839 : case RTF_SHPGRP:
1840 : {
1841 5 : RTFLookahead aLookahead(Strm(), m_pTokenizer->getGroupStart());
1842 5 : if (!aLookahead.hasTable())
1843 : {
1844 3 : uno::Reference<drawing::XShapes> xGroupShape(m_xModelFactory->createInstance("com.sun.star.drawing.GroupShape"), uno::UNO_QUERY);
1845 6 : uno::Reference<drawing::XDrawPageSupplier> xDrawSupplier(m_xDstDoc, uno::UNO_QUERY);
1846 3 : if (xDrawSupplier.is())
1847 : {
1848 3 : uno::Reference<drawing::XShape> xShape(xGroupShape, uno::UNO_QUERY);
1849 3 : xDrawSupplier->getDrawPage()->add(xShape);
1850 : }
1851 3 : m_pSdrImport->pushParent(xGroupShape);
1852 6 : m_aStates.top().bCreatedShapeGroup = true;
1853 : }
1854 5 : m_aStates.top().nDestinationState = DESTINATION_SHAPEGROUP;
1855 5 : m_aStates.top().bInShapeGroup = true;
1856 : }
1857 5 : break;
1858 : case RTF_FTNSEP:
1859 53 : m_aStates.top().nDestinationState = DESTINATION_FOOTNOTESEPARATOR;
1860 53 : m_aStates.top().aCharacterAttributes.set(NS_ooxml::LN_CT_FtnEdn_type, RTFValue::Pointer_t(new RTFValue(NS_ooxml::LN_Value_wordprocessingml_ST_FtnEdn_separator)));
1861 53 : break;
1862 : default:
1863 : {
1864 : // Check if it's a math token.
1865 : RTFMathSymbol aSymbol;
1866 1296 : aSymbol.eKeyword = nKeyword;
1867 1296 : if (RTFTokenizer::lookupMathKeyword(aSymbol))
1868 : {
1869 1159 : m_aMathBuffer.appendOpeningTag(aSymbol.nToken);
1870 1159 : m_aStates.top().nDestinationState = aSymbol.eDestination;
1871 1159 : return 0;
1872 : }
1873 :
1874 : SAL_INFO("writerfilter", "TODO handle destination '" << lcl_RtfToString(nKeyword) << "'");
1875 : // Make sure we skip destinations (even without \*) till we don't handle them
1876 137 : m_aStates.top().nDestinationState = DESTINATION_SKIP;
1877 137 : aSkip.setParsed(false);
1878 : }
1879 137 : break;
1880 : }
1881 :
1882 4553 : return 0;
1883 : }
1884 :
1885 25951 : int RTFDocumentImpl::dispatchSymbol(RTFKeyword nKeyword)
1886 : {
1887 25951 : setNeedSect();
1888 25951 : if (nKeyword != RTF_HEXCHAR)
1889 2413 : checkUnicode(/*bUnicode =*/ true, /*bHex =*/ true);
1890 : else
1891 23538 : checkUnicode(/*bUnicode =*/ true, /*bHex =*/ false);
1892 25951 : RTFSkipDestination aSkip(*this);
1893 :
1894 25951 : if (RTF_LINE == nKeyword)
1895 : { // very special handling since text() will eat lone '\n'
1896 53 : singleChar('\n');
1897 53 : return 0;
1898 : }
1899 : // Trivial symbols
1900 25898 : sal_uInt8 cCh = 0;
1901 25898 : switch (nKeyword)
1902 : {
1903 43 : case RTF_TAB: cCh = '\t'; break;
1904 21 : case RTF_BACKSLASH: cCh = '\\'; break;
1905 23 : case RTF_LBRACE: cCh = '{'; break;
1906 20 : case RTF_RBRACE: cCh = '}'; break;
1907 9 : case RTF_EMDASH: cCh = 151; break;
1908 11 : case RTF_ENDASH: cCh = 150; break;
1909 15 : case RTF_BULLET: cCh = 149; break;
1910 16 : case RTF_LQUOTE: cCh = 145; break;
1911 13 : case RTF_RQUOTE: cCh = 146; break;
1912 22 : case RTF_LDBLQUOTE: cCh = 147; break;
1913 9 : case RTF_RDBLQUOTE: cCh = 148; break;
1914 25696 : default: break;
1915 : }
1916 25898 : if (cCh > 0)
1917 : {
1918 202 : OUString aStr(OStringToOUString(OString(cCh), RTL_TEXTENCODING_MS_1252));
1919 202 : text(aStr);
1920 202 : return 0;
1921 : }
1922 :
1923 25696 : switch (nKeyword)
1924 : {
1925 : case RTF_IGNORE:
1926 : {
1927 1022 : m_bSkipUnknown = true;
1928 1022 : aSkip.setReset(false);
1929 1022 : return 0;
1930 : }
1931 : break;
1932 : case RTF_PAR:
1933 : {
1934 645 : checkFirstRun();
1935 645 : bool bNeedPap = m_bNeedPap;
1936 645 : checkNeedPap();
1937 645 : if (bNeedPap)
1938 231 : runProps();
1939 645 : if (!m_aStates.top().pCurrentBuffer)
1940 : {
1941 629 : if (m_aStates.top().nDestinationState == DESTINATION_FOOTNOTESEPARATOR)
1942 : {
1943 : static const sal_Unicode uCR = 0xd;
1944 3 : Mapper().utext((const sal_uInt8*)&uCR, 1);
1945 : }
1946 : else
1947 626 : parBreak();
1948 : // Not in table? Reset max width.
1949 629 : m_nCellxMax = 0;
1950 : }
1951 16 : else if (m_aStates.top().nDestinationState != DESTINATION_SHAPETEXT)
1952 : {
1953 16 : RTFValue::Pointer_t pValue;
1954 16 : m_aStates.top().pCurrentBuffer->push_back(
1955 32 : Buf_t(BUFFER_PAR, pValue));
1956 : }
1957 : // but don't emit properties yet, since they may change till the first text token arrives
1958 645 : m_bNeedPap = true;
1959 645 : if (!m_aStates.top().aFrame.inFrame())
1960 618 : m_bNeedPar = false;
1961 645 : m_bNeedFinalPar = false;
1962 : }
1963 645 : break;
1964 : case RTF_SECT:
1965 : {
1966 14 : m_bHadSect = true;
1967 14 : if (m_bIgnoreNextContSectBreak)
1968 3 : m_bIgnoreNextContSectBreak = false;
1969 : else
1970 : {
1971 11 : sectBreak();
1972 11 : if (m_nResetBreakOnSectBreak != RTF_invalid)
1973 : { // this should run on _second_ \sect after \page
1974 2 : dispatchSymbol(m_nResetBreakOnSectBreak); // lazy reset
1975 2 : m_nResetBreakOnSectBreak = RTF_invalid;
1976 2 : m_bNeedSect = false; // dispatchSymbol set it
1977 : }
1978 : }
1979 : }
1980 14 : break;
1981 : case RTF_NOBREAK:
1982 : {
1983 25 : OUString aStr(SVT_HARD_SPACE);
1984 25 : text(aStr);
1985 : }
1986 25 : break;
1987 : case RTF_NOBRKHYPH:
1988 : {
1989 3 : OUString aStr(SVT_HARD_HYPHEN);
1990 3 : text(aStr);
1991 : }
1992 3 : break;
1993 : case RTF_OPTHYPH:
1994 : {
1995 14 : OUString aStr(SVT_SOFT_HYPHEN);
1996 14 : text(aStr);
1997 : }
1998 14 : break;
1999 : case RTF_HEXCHAR:
2000 23538 : m_aStates.top().nInternalState = INTERNAL_HEX;
2001 23538 : break;
2002 : case RTF_CELL:
2003 : case RTF_NESTCELL:
2004 : {
2005 248 : checkFirstRun();
2006 248 : if (m_bNeedPap)
2007 : {
2008 : // There were no runs in the cell, so we need to send paragraph and character properties here.
2009 58 : RTFValue::Pointer_t pPValue(new RTFValue(m_aStates.top().aParagraphAttributes, m_aStates.top().aParagraphSprms));
2010 58 : m_aTableBufferStack.back().push_back(
2011 116 : Buf_t(BUFFER_PROPS, pPValue));
2012 116 : RTFValue::Pointer_t pCValue(new RTFValue(m_aStates.top().aCharacterAttributes, m_aStates.top().aCharacterSprms));
2013 58 : m_aTableBufferStack.back().push_back(
2014 174 : Buf_t(BUFFER_PROPS, pCValue));
2015 : }
2016 :
2017 248 : RTFValue::Pointer_t pValue;
2018 248 : m_aTableBufferStack.back().push_back(
2019 496 : Buf_t(BUFFER_CELLEND, pValue));
2020 248 : m_bNeedPap = true;
2021 : }
2022 248 : break;
2023 : case RTF_NESTROW:
2024 : {
2025 : boost::shared_ptr<TableRowBuffer> const pBuffer(
2026 : new TableRowBuffer(
2027 6 : m_aTableBufferStack.back(),
2028 : m_aNestedTableCellsSprms,
2029 : m_aNestedTableCellsAttributes,
2030 6 : m_nNestedCells));
2031 6 : prepareProperties(m_aStates.top(),
2032 6 : pBuffer->pParaProperties,
2033 6 : pBuffer->pFrameProperties,
2034 6 : pBuffer->pRowProperties,
2035 30 : m_nNestedCells, m_nNestedCurrentCellX);
2036 :
2037 : assert(m_aStates.top().pCurrentBuffer == &m_aTableBufferStack.back());
2038 6 : if (m_aTableBufferStack.size() == 1)
2039 : {
2040 : throw io::WrongFormatException(
2041 0 : "mismatch between \\itap and number of \\nestrow", 0);
2042 : }
2043 : // note: there may be several states pointing to table buffer!
2044 21 : for (size_t i = 0; i < m_aStates.size(); ++i)
2045 : {
2046 15 : if (m_aStates[i].pCurrentBuffer == &m_aTableBufferStack.back())
2047 : {
2048 15 : m_aStates[i].pCurrentBuffer =
2049 15 : &m_aTableBufferStack[m_aTableBufferStack.size()-2];
2050 : }
2051 : }
2052 6 : m_aTableBufferStack.pop_back();
2053 6 : m_aTableBufferStack.back().push_back(
2054 12 : Buf_t(BUFFER_NESTROW, RTFValue::Pointer_t(), pBuffer));
2055 :
2056 6 : m_aNestedTableCellsSprms.clear();
2057 6 : m_aNestedTableCellsAttributes.clear();
2058 6 : m_nNestedCells = 0;
2059 6 : m_bNeedPap = true;
2060 : }
2061 6 : break;
2062 : case RTF_ROW:
2063 : {
2064 80 : bool bRestored = false;
2065 : // Ending a row, but no cells defined?
2066 : // See if there was an invalid table row reset, so we can restore cell infos to help invalid documents.
2067 80 : if (!m_nTopLevelCurrentCellX && m_nBackupTopLevelCurrentCellX)
2068 : {
2069 2 : restoreTableRowProperties();
2070 2 : bRestored = true;
2071 : }
2072 :
2073 : // If the right edge of the last cell (row width) is smaller than the width of some other row, mimic WW8TabDesc::CalcDefaults(): add a fake cell.
2074 80 : const int MINLAY = 23; // sw/inc/swtypes.hxx, minimal possible size of frames.
2075 80 : if ((m_nCellxMax - m_nTopLevelCurrentCellX) >= MINLAY)
2076 1 : dispatchValue(RTF_CELLX, m_nCellxMax);
2077 :
2078 80 : if (m_nTopLevelCells)
2079 : {
2080 : // Make a backup before we start popping elements
2081 79 : m_aTableInheritingCellsSprms = m_aTopLevelTableCellsSprms;
2082 79 : m_aTableInheritingCellsAttributes = m_aTopLevelTableCellsAttributes;
2083 79 : m_nInheritingCells = m_nTopLevelCells;
2084 : }
2085 : else
2086 : {
2087 : // No table definition? Then inherit from the previous row
2088 1 : m_aTopLevelTableCellsSprms = m_aTableInheritingCellsSprms;
2089 1 : m_aTopLevelTableCellsAttributes = m_aTableInheritingCellsAttributes;
2090 1 : m_nTopLevelCells = m_nInheritingCells;
2091 : }
2092 :
2093 160 : while (m_aTableBufferStack.size() > 1)
2094 : {
2095 : SAL_WARN("writerfilter.rtf", "dropping extra table buffer");
2096 : // note: there may be several states pointing to table buffer!
2097 0 : for (size_t i = 0; i < m_aStates.size(); ++i)
2098 : {
2099 0 : if (m_aStates[i].pCurrentBuffer == &m_aTableBufferStack.back())
2100 : {
2101 0 : m_aStates[i].pCurrentBuffer =
2102 0 : &m_aTableBufferStack.front();
2103 : }
2104 : }
2105 0 : m_aTableBufferStack.pop_back();
2106 : }
2107 :
2108 80 : replayRowBuffer(m_aTableBufferStack.back(),
2109 : m_aTopLevelTableCellsSprms, m_aTopLevelTableCellsAttributes,
2110 160 : m_nTopLevelCells);
2111 :
2112 80 : m_aStates.top().aTableCellSprms = m_aDefaultState.aTableCellSprms;
2113 80 : m_aStates.top().aTableCellAttributes = m_aDefaultState.aTableCellAttributes;
2114 :
2115 80 : writerfilter::Reference<Properties>::Pointer_t paraProperties;
2116 160 : writerfilter::Reference<Properties>::Pointer_t frameProperties;
2117 160 : writerfilter::Reference<Properties>::Pointer_t rowProperties;
2118 80 : prepareProperties(m_aStates.top(),
2119 : paraProperties, frameProperties, rowProperties,
2120 160 : m_nTopLevelCells, m_nTopLevelCurrentCellX);
2121 80 : sendProperties(paraProperties, frameProperties, rowProperties);
2122 :
2123 80 : m_bNeedPap = true;
2124 80 : m_bNeedFinalPar = true;
2125 80 : m_aTableBufferStack.back().clear();
2126 80 : m_nTopLevelCells = 0;
2127 :
2128 80 : if (bRestored)
2129 : // We restored cell definitions, clear these now.
2130 : // This is necessary, as later cell definitions want to overwrite the restored ones.
2131 82 : resetTableRowProperties();
2132 : }
2133 80 : break;
2134 : case RTF_COLUMN:
2135 : {
2136 1 : bool bColumns = false; // If we have multiple columns
2137 1 : RTFValue::Pointer_t pCols = m_aStates.top().aSectionSprms.find(NS_ooxml::LN_EG_SectPrContents_cols);
2138 1 : if (pCols.get())
2139 : {
2140 0 : RTFValue::Pointer_t pNum = pCols->getAttributes().find(NS_ooxml::LN_CT_Columns_num);
2141 0 : if (pNum.get() && pNum->getInt() > 1)
2142 0 : bColumns = true;
2143 : }
2144 1 : if (bColumns)
2145 : {
2146 0 : sal_uInt8 sBreak[] = { 0xe };
2147 0 : Mapper().startCharacterGroup();
2148 0 : Mapper().text(sBreak, 1);
2149 0 : Mapper().endCharacterGroup();
2150 : }
2151 : else
2152 1 : dispatchSymbol(RTF_PAGE);
2153 : }
2154 1 : break;
2155 : case RTF_CHFTN:
2156 : // Nothing to do, dmapper assumes this is the default.
2157 16 : break;
2158 : case RTF_PAGE:
2159 : {
2160 : // If we're inside a continuous section, we should send a section break, not a page one.
2161 60 : RTFValue::Pointer_t pBreak = m_aStates.top().aSectionSprms.find(NS_ooxml::LN_EG_SectPrContents_type);
2162 : // Unless we're on a title page.
2163 120 : RTFValue::Pointer_t pTitlePg = m_aStates.top().aSectionSprms.find(NS_ooxml::LN_EG_SectPrContents_titlePg);
2164 124 : if (((pBreak.get() && !pBreak->getInt())
2165 57 : || m_nResetBreakOnSectBreak == RTF_SBKNONE)
2166 64 : && !(pTitlePg.get() && pTitlePg->getInt()))
2167 : {
2168 3 : if (m_bWasInFrame)
2169 : {
2170 2 : dispatchSymbol(RTF_PAR);
2171 2 : m_bWasInFrame = false;
2172 : }
2173 3 : sectBreak();
2174 : // note: this will not affect the following section break
2175 : // but the one just pushed
2176 3 : dispatchFlag(RTF_SBKPAGE);
2177 3 : if (m_bNeedPar)
2178 3 : dispatchSymbol(RTF_PAR);
2179 3 : m_bIgnoreNextContSectBreak = true;
2180 : // arrange to clean up the syntetic RTF_SBKPAGE
2181 3 : m_nResetBreakOnSectBreak = RTF_SBKNONE;
2182 : }
2183 : else
2184 : {
2185 57 : checkNeedPap();
2186 57 : sal_uInt8 sBreak[] = { 0xc };
2187 57 : Mapper().text(sBreak, 1);
2188 57 : if (!m_bNeedPap)
2189 57 : parBreak();
2190 57 : m_bNeedCr = true;
2191 60 : }
2192 : }
2193 60 : break;
2194 : case RTF_CHPGN:
2195 : {
2196 2 : OUString aStr("PAGE");
2197 2 : singleChar(0x13);
2198 2 : text(aStr);
2199 2 : singleChar(0x14, true);
2200 2 : singleChar(0x15);
2201 : }
2202 2 : break;
2203 : case RTF_CHFTNSEP:
2204 : {
2205 : static const sal_Unicode uFtnEdnSep = 0x3;
2206 12 : Mapper().utext((const sal_uInt8*)&uFtnEdnSep, 1);
2207 : }
2208 12 : break;
2209 : default:
2210 : {
2211 : SAL_INFO("writerfilter", "TODO handle symbol '" << lcl_RtfToString(nKeyword) << "'");
2212 10 : aSkip.setParsed(false);
2213 : }
2214 10 : break;
2215 : }
2216 24674 : return 0;
2217 : }
2218 :
2219 : // Checks if rName is contained at least once in rProperties as a key.
2220 110 : bool lcl_findPropertyName(const std::vector<beans::PropertyValue>& rProperties, const OUString& rName)
2221 : {
2222 605 : for (std::vector<beans::PropertyValue>::const_iterator it = rProperties.begin(); it != rProperties.end(); ++it)
2223 : {
2224 517 : if (it->Name == rName)
2225 22 : return true;
2226 : }
2227 88 : return false;
2228 : }
2229 :
2230 113 : void RTFDocumentImpl::backupTableRowProperties()
2231 : {
2232 113 : if (m_nTopLevelCurrentCellX)
2233 : {
2234 72 : m_aBackupTableRowSprms = m_aStates.top().aTableRowSprms;
2235 72 : m_aBackupTableRowAttributes = m_aStates.top().aTableRowAttributes;
2236 72 : m_nBackupTopLevelCurrentCellX = m_nTopLevelCurrentCellX;
2237 : }
2238 113 : }
2239 :
2240 2 : void RTFDocumentImpl::restoreTableRowProperties()
2241 : {
2242 2 : m_aStates.top().aTableRowSprms = m_aBackupTableRowSprms;
2243 2 : m_aStates.top().aTableRowAttributes = m_aBackupTableRowAttributes;
2244 2 : m_nTopLevelCurrentCellX = m_nBackupTopLevelCurrentCellX;
2245 2 : }
2246 :
2247 115 : void RTFDocumentImpl::resetTableRowProperties()
2248 : {
2249 115 : m_aStates.top().aTableRowSprms = m_aDefaultState.aTableRowSprms;
2250 115 : m_aStates.top().aTableRowSprms.set(NS_ooxml::LN_CT_TblGridBase_gridCol, RTFValue::Pointer_t(new RTFValue(-1)), OVERWRITE_NO_APPEND);
2251 115 : m_aStates.top().aTableRowAttributes = m_aDefaultState.aTableRowAttributes;
2252 115 : if (DESTINATION_NESTEDTABLEPROPERTIES == m_aStates.top().nDestinationState)
2253 6 : m_nNestedCurrentCellX = 0;
2254 : else
2255 109 : m_nTopLevelCurrentCellX = 0;
2256 115 : }
2257 :
2258 14571 : int RTFDocumentImpl::dispatchFlag(RTFKeyword nKeyword)
2259 : {
2260 14571 : setNeedSect();
2261 14571 : checkUnicode(/*bUnicode =*/ true, /*bHex =*/ true);
2262 14571 : RTFSkipDestination aSkip(*this);
2263 14571 : int nParam = -1;
2264 14571 : int nSprm = -1;
2265 :
2266 : // Map all underline flags to a single sprm.
2267 14571 : switch (nKeyword)
2268 : {
2269 1 : case RTF_ULD: nSprm = 4; break;
2270 0 : case RTF_ULW: nSprm = 2; break;
2271 14570 : default: break;
2272 : }
2273 14571 : if (nSprm >= 0)
2274 : {
2275 1 : RTFValue::Pointer_t pValue(new RTFValue(nSprm));
2276 1 : m_aStates.top().aCharacterAttributes.set(NS_ooxml::LN_CT_Underline_val, pValue);
2277 1 : return 0;
2278 : }
2279 :
2280 : // Indentation
2281 14570 : switch (nKeyword)
2282 : {
2283 37 : case RTF_QC: nParam = 1; break;
2284 12 : case RTF_QJ: nParam = 3; break;
2285 224 : case RTF_QL: nParam = 0; break;
2286 20 : case RTF_QR: nParam = 2; break;
2287 0 : case RTF_QD: nParam = 4; break;
2288 14277 : default: break;
2289 : }
2290 14570 : if (nParam >= 0)
2291 : {
2292 293 : RTFValue::Pointer_t pValue(new RTFValue(nParam));
2293 293 : m_aStates.top().aParagraphSprms.set(NS_ooxml::LN_CT_PPrBase_jc, pValue);
2294 293 : m_bNeedPap = true;
2295 293 : return 0;
2296 : }
2297 :
2298 : // Font Alignment
2299 14277 : switch (nKeyword)
2300 : {
2301 : case RTF_FAFIXED:
2302 153 : case RTF_FAAUTO: nParam = NS_ooxml::LN_Value_wordprocessingml_ST_TextAlignment_auto; break;
2303 0 : case RTF_FAHANG: nParam = NS_ooxml::LN_Value_wordprocessingml_ST_TextAlignment_top; break;
2304 0 : case RTF_FACENTER: nParam = NS_ooxml::LN_Value_wordprocessingml_ST_TextAlignment_center; break;
2305 0 : case RTF_FAROMAN: nParam = NS_ooxml::LN_Value_wordprocessingml_ST_TextAlignment_baseline; break;
2306 0 : case RTF_FAVAR: nParam = NS_ooxml::LN_Value_wordprocessingml_ST_TextAlignment_bottom; break;
2307 14124 : default: break;
2308 : }
2309 14277 : if (nParam >= 0)
2310 : {
2311 153 : RTFValue::Pointer_t pValue(new RTFValue(nParam));
2312 153 : m_aStates.top().aParagraphSprms.set(NS_ooxml::LN_CT_PPrBase_textAlignment, pValue);
2313 153 : return 0;
2314 : }
2315 :
2316 : // Tab kind.
2317 14124 : switch (nKeyword)
2318 : {
2319 6 : case RTF_TQR: nParam = 2; break;
2320 1 : case RTF_TQC: nParam = 1; break;
2321 0 : case RTF_TQDEC: nParam = 3; break;
2322 14117 : default: break;
2323 : }
2324 14124 : if (nParam >= 0)
2325 : {
2326 7 : RTFValue::Pointer_t pValue(new RTFValue(nParam));
2327 7 : m_aStates.top().aTabAttributes.set(NS_ooxml::LN_CT_TabStop_val, pValue);
2328 7 : return 0;
2329 : }
2330 :
2331 : // Tab lead.
2332 14117 : switch (nKeyword)
2333 : {
2334 0 : case RTF_TLDOT: nParam = 1; break;
2335 0 : case RTF_TLMDOT: nParam = NS_ooxml::LN_Value_ST_TabTlc_middleDot; break;
2336 0 : case RTF_TLHYPH: nParam = 2; break;
2337 0 : case RTF_TLUL: nParam = 3; break;
2338 0 : case RTF_TLTH: nParam = 2; break; // thick line is not supported by dmapper, this is just a hack
2339 0 : case RTF_TLEQ: nParam = 0; break; // equal sign isn't, either
2340 14117 : default: break;
2341 : }
2342 14117 : if (nParam >= 0)
2343 : {
2344 0 : RTFValue::Pointer_t pValue(new RTFValue(nParam));
2345 0 : m_aStates.top().aTabAttributes.set(NS_ooxml::LN_CT_TabStop_leader, pValue);
2346 0 : return 0;
2347 : }
2348 :
2349 : // Border types
2350 : {
2351 14117 : switch (nKeyword)
2352 : {
2353 : // brdrhair and brdrs are the same, brdrw will make a difference
2354 : // map to values in ooxml/model.xml resource ST_Border
2355 35 : case RTF_BRDRHAIR: nParam = 5; break;
2356 299 : case RTF_BRDRS: nParam = 1; break;
2357 4 : case RTF_BRDRDOT: nParam = 6; break;
2358 0 : case RTF_BRDRDASH: nParam = 7; break;
2359 52 : case RTF_BRDRDB: nParam = 3; break;
2360 0 : case RTF_BRDRTNTHSG: nParam = 11; break;
2361 4 : case RTF_BRDRTNTHMG: nParam = 14; break;
2362 0 : case RTF_BRDRTNTHLG: nParam = 17; break;
2363 10 : case RTF_BRDRTHTNSG: nParam = 12; break;
2364 20 : case RTF_BRDRTHTNMG: nParam = 15; break;
2365 18 : case RTF_BRDRTHTNLG: nParam = 18; break;
2366 12 : case RTF_BRDREMBOSS: nParam = 24; break;
2367 12 : case RTF_BRDRENGRAVE: nParam = 25; break;
2368 22 : case RTF_BRDROUTSET: nParam = 18; break;
2369 20 : case RTF_BRDRINSET: nParam = 17; break;
2370 116 : case RTF_BRDRNONE: nParam = 0; break;
2371 13493 : default: break;
2372 : }
2373 14117 : if (nParam >= 0)
2374 : {
2375 624 : RTFValue::Pointer_t pValue(new RTFValue(nParam));
2376 624 : lcl_putBorderProperty(m_aStates, NS_ooxml::LN_CT_Border_val, pValue);
2377 624 : return 0;
2378 : }
2379 : }
2380 :
2381 : // Section breaks
2382 13493 : switch (nKeyword)
2383 : {
2384 75 : case RTF_SBKNONE: nParam = 0; break;
2385 0 : case RTF_SBKCOL: nParam = 1; break;
2386 6 : case RTF_SBKPAGE: nParam = 2; break;
2387 0 : case RTF_SBKEVEN: nParam = 3; break;
2388 0 : case RTF_SBKODD: nParam = 4; break;
2389 13412 : default: break;
2390 : }
2391 13493 : if (nParam >= 0)
2392 : {
2393 81 : if (m_nResetBreakOnSectBreak != RTF_invalid)
2394 : {
2395 1 : m_nResetBreakOnSectBreak = nKeyword;
2396 : }
2397 81 : RTFValue::Pointer_t pValue(new RTFValue(nParam));
2398 81 : m_aStates.top().aSectionSprms.set(NS_ooxml::LN_EG_SectPrContents_type, pValue);
2399 81 : return 0;
2400 : }
2401 :
2402 : // Footnote numbering
2403 13412 : switch (nKeyword)
2404 : {
2405 65 : case RTF_FTNNAR: nParam = NS_ooxml::LN_Value_ST_NumberFormat_decimal; break;
2406 0 : case RTF_FTNNALC: nParam = NS_ooxml::LN_Value_ST_NumberFormat_lowerLetter; break;
2407 0 : case RTF_FTNNAUC: nParam = NS_ooxml::LN_Value_ST_NumberFormat_upperLetter; break;
2408 0 : case RTF_FTNNRLC: nParam = NS_ooxml::LN_Value_ST_NumberFormat_lowerRoman; break;
2409 0 : case RTF_FTNNRUC: nParam = NS_ooxml::LN_Value_ST_NumberFormat_upperRoman; break;
2410 0 : case RTF_FTNNCHI: nParam = NS_ooxml::LN_Value_ST_NumberFormat_chicago; break;
2411 13347 : default: break;
2412 : }
2413 13412 : if (nParam >= 0)
2414 : {
2415 65 : RTFValue::Pointer_t pValue(new RTFValue(nParam));
2416 65 : lcl_putNestedSprm(m_aDefaultState.aParagraphSprms, NS_ooxml::LN_EG_SectPrContents_footnotePr, NS_ooxml::LN_CT_FtnProps_numFmt, pValue);
2417 65 : return 0;
2418 : }
2419 :
2420 : // Footnote restart type
2421 13347 : switch (nKeyword)
2422 : {
2423 0 : case RTF_FTNRSTPG: nParam = NS_ooxml::LN_Value_ST_RestartNumber_eachPage; break;
2424 0 : case RTF_FTNRESTART: nParam = NS_ooxml::LN_Value_ST_RestartNumber_eachSect; break;
2425 62 : case RTF_FTNRSTCONT: nParam = NS_ooxml::LN_Value_ST_RestartNumber_continuous; break;
2426 13285 : default: break;
2427 : }
2428 13347 : if (nParam >= 0)
2429 : {
2430 62 : RTFValue::Pointer_t pValue(new RTFValue(nParam));
2431 62 : lcl_putNestedSprm(m_aDefaultState.aParagraphSprms, NS_ooxml::LN_EG_SectPrContents_footnotePr, NS_ooxml::LN_EG_FtnEdnNumProps_numRestart, pValue);
2432 62 : return 0;
2433 : }
2434 :
2435 : // Endnote numbering
2436 13285 : switch (nKeyword)
2437 : {
2438 4 : case RTF_AFTNNAR: nParam = NS_ooxml::LN_Value_ST_NumberFormat_decimal; break;
2439 0 : case RTF_AFTNNALC: nParam = NS_ooxml::LN_Value_ST_NumberFormat_lowerLetter; break;
2440 0 : case RTF_AFTNNAUC: nParam = NS_ooxml::LN_Value_ST_NumberFormat_upperLetter; break;
2441 63 : case RTF_AFTNNRLC: nParam = NS_ooxml::LN_Value_ST_NumberFormat_lowerRoman; break;
2442 0 : case RTF_AFTNNRUC: nParam = NS_ooxml::LN_Value_ST_NumberFormat_upperRoman; break;
2443 0 : case RTF_AFTNNCHI: nParam = NS_ooxml::LN_Value_ST_NumberFormat_chicago; break;
2444 13218 : default: break;
2445 : }
2446 13285 : if (nParam >= 0)
2447 : {
2448 67 : RTFValue::Pointer_t pValue(new RTFValue(nParam));
2449 67 : lcl_putNestedSprm(m_aDefaultState.aParagraphSprms, NS_ooxml::LN_EG_SectPrContents_endnotePr, NS_ooxml::LN_CT_EdnProps_numFmt, pValue);
2450 67 : return 0;
2451 : }
2452 :
2453 : // Cell Text Flow
2454 13218 : switch (nKeyword)
2455 : {
2456 169 : case RTF_CLTXLRTB: nParam = 0; break;
2457 0 : case RTF_CLTXTBRL: nParam = 1; break;
2458 0 : case RTF_CLTXBTLR: nParam = 3; break;
2459 0 : case RTF_CLTXLRTBV: nParam = 4; break;
2460 0 : case RTF_CLTXTBRLV: nParam = 5; break;
2461 13049 : default: break;
2462 : }
2463 13218 : if (nParam >= 0)
2464 : {
2465 169 : RTFValue::Pointer_t pValue(new RTFValue(nParam));
2466 169 : m_aStates.top().aTableCellSprms.set(NS_ooxml::LN_CT_TcPrBase_textDirection, pValue);
2467 : }
2468 :
2469 : // Trivial paragraph flags
2470 13218 : switch (nKeyword)
2471 : {
2472 : case RTF_KEEP:
2473 3 : if (m_aStates.top().pCurrentBuffer != &m_aTableBufferStack.back())
2474 3 : nParam = NS_ooxml::LN_CT_PPrBase_keepLines;
2475 3 : break;
2476 : case RTF_KEEPN:
2477 76 : if (m_aStates.top().pCurrentBuffer != &m_aTableBufferStack.back())
2478 67 : nParam = NS_ooxml::LN_CT_PPrBase_keepNext;
2479 76 : break;
2480 : case RTF_INTBL:
2481 : {
2482 533 : m_aStates.top().pCurrentBuffer = &m_aTableBufferStack.back();
2483 533 : nParam = NS_ooxml::LN_inTbl;
2484 : }
2485 533 : break;
2486 : case RTF_PAGEBB:
2487 3 : nParam = NS_ooxml::LN_CT_PPrBase_pageBreakBefore;
2488 3 : break;
2489 : default:
2490 12603 : break;
2491 : }
2492 13218 : if (nParam >= 0)
2493 : {
2494 775 : RTFValue::Pointer_t pValue(new RTFValue(1));
2495 775 : m_aStates.top().aParagraphSprms.erase(NS_ooxml::LN_inTbl);
2496 775 : m_aStates.top().aParagraphSprms.set(nParam, pValue);
2497 775 : return 0;
2498 : }
2499 :
2500 12443 : switch (nKeyword)
2501 : {
2502 : case RTF_FNIL:
2503 : case RTF_FROMAN:
2504 : case RTF_FSWISS:
2505 : case RTF_FMODERN:
2506 : case RTF_FSCRIPT:
2507 : case RTF_FDECOR:
2508 : case RTF_FTECH:
2509 : case RTF_FBIDI:
2510 : // TODO ooxml:CT_Font_family seems to be ignored by the domain mapper
2511 1019 : break;
2512 : case RTF_ANSI:
2513 118 : m_aStates.top().nCurrentEncoding = RTL_TEXTENCODING_MS_1252;
2514 118 : break;
2515 : case RTF_PLAIN:
2516 : {
2517 327 : m_aStates.top().aCharacterSprms = getDefaultState().aCharacterSprms;
2518 327 : m_aStates.top().nCurrentEncoding = getEncoding(getFontIndex(m_nDefaultFontIndex));
2519 327 : m_aStates.top().aCharacterAttributes = getDefaultState().aCharacterAttributes;
2520 : }
2521 327 : break;
2522 : case RTF_PARD:
2523 552 : if (m_bHadPicture)
2524 1 : dispatchSymbol(RTF_PAR);
2525 : // \pard is allowed between \cell and \row, but in that case it should not reset the fact that we're inside a table.
2526 552 : m_aStates.top().aParagraphSprms = m_aDefaultState.aParagraphSprms;
2527 552 : m_aStates.top().aParagraphAttributes = m_aDefaultState.aParagraphAttributes;
2528 552 : if (m_nTopLevelCells == 0 && m_nNestedCells == 0)
2529 : {
2530 : // Reset that we're in a table.
2531 398 : m_aStates.top().pCurrentBuffer = 0;
2532 : }
2533 : else
2534 : {
2535 : // We are still in a table.
2536 154 : m_aStates.top().aParagraphSprms.set(NS_ooxml::LN_inTbl, RTFValue::Pointer_t(new RTFValue(1)));
2537 : }
2538 552 : m_aStates.top().resetFrame();
2539 552 : break;
2540 : case RTF_SECTD:
2541 : {
2542 91 : m_aStates.top().aSectionSprms = m_aDefaultState.aSectionSprms;
2543 91 : m_aStates.top().aSectionAttributes = m_aDefaultState.aSectionAttributes;
2544 : }
2545 91 : break;
2546 : case RTF_TROWD:
2547 : {
2548 : // Back these up, in case later we still need this info.
2549 113 : backupTableRowProperties();
2550 113 : resetTableRowProperties();
2551 : // In case the table definition is in the middle of the row
2552 : // (invalid), make sure table definition is emitted.
2553 113 : m_bNeedPap = true;
2554 : }
2555 113 : break;
2556 : case RTF_WIDCTLPAR:
2557 : case RTF_NOWIDCTLPAR:
2558 : {
2559 461 : RTFValue::Pointer_t pValue(new RTFValue(int(nKeyword == RTF_WIDCTLPAR)));
2560 461 : m_aStates.top().aParagraphSprms.set(NS_ooxml::LN_CT_PPrBase_widowControl, pValue);
2561 : }
2562 461 : break;
2563 : case RTF_BOX:
2564 : {
2565 1 : RTFSprms aAttributes;
2566 2 : RTFValue::Pointer_t pValue(new RTFValue(aAttributes));
2567 5 : for (int i = 0; i < 4; i++)
2568 4 : m_aStates.top().aParagraphSprms.set(lcl_getParagraphBorder(i), pValue);
2569 2 : m_aStates.top().nBorderState = BORDER_PARAGRAPH_BOX;
2570 : }
2571 1 : break;
2572 : case RTF_LTRSECT:
2573 : case RTF_RTLSECT:
2574 : {
2575 9 : RTFValue::Pointer_t pValue(new RTFValue(nKeyword == RTF_LTRSECT ? 0 : 1));
2576 9 : m_aStates.top().aParagraphSprms.set(NS_ooxml::LN_EG_SectPrContents_textDirection, pValue);
2577 : }
2578 9 : break;
2579 : case RTF_LTRPAR:
2580 : case RTF_RTLPAR:
2581 : {
2582 221 : RTFValue::Pointer_t pValue(new RTFValue(nKeyword == RTF_LTRPAR ? 0 : 1));
2583 221 : m_aStates.top().aParagraphSprms.set(NS_ooxml::LN_CT_PPrBase_textDirection, pValue);
2584 : }
2585 221 : break;
2586 : case RTF_LTRROW:
2587 : case RTF_RTLROW:
2588 : // dmapper does not support these.
2589 77 : break;
2590 : case RTF_LTRCH:
2591 : // dmapper does not support this.
2592 1185 : break;
2593 : case RTF_RTLCH:
2594 1178 : if (m_aDefaultState.nCurrentEncoding == RTL_TEXTENCODING_MS_1255)
2595 1 : m_aStates.top().nCurrentEncoding = m_aDefaultState.nCurrentEncoding;
2596 1178 : break;
2597 : case RTF_ULNONE:
2598 : {
2599 9 : RTFValue::Pointer_t pValue(new RTFValue(0));
2600 9 : m_aStates.top().aCharacterAttributes.set(NS_ooxml::LN_CT_Underline_val, pValue);
2601 : }
2602 9 : break;
2603 : case RTF_NONSHPPICT:
2604 : case RTF_MMATHPICT: // Picture group used by readers not understanding \moMath group
2605 0 : m_aStates.top().nDestinationState = DESTINATION_SKIP;
2606 0 : break;
2607 : case RTF_CLBRDRT:
2608 : case RTF_CLBRDRL:
2609 : case RTF_CLBRDRB:
2610 : case RTF_CLBRDRR:
2611 : {
2612 878 : RTFSprms aAttributes;
2613 1756 : RTFSprms aSprms;
2614 1756 : RTFValue::Pointer_t pValue(new RTFValue(aAttributes, aSprms));
2615 878 : switch (nKeyword)
2616 : {
2617 215 : case RTF_CLBRDRT: nParam = NS_ooxml::LN_CT_TcBorders_top; break;
2618 226 : case RTF_CLBRDRL: nParam = NS_ooxml::LN_CT_TcBorders_left; break;
2619 219 : case RTF_CLBRDRB: nParam = NS_ooxml::LN_CT_TcBorders_bottom; break;
2620 218 : case RTF_CLBRDRR: nParam = NS_ooxml::LN_CT_TcBorders_right; break;
2621 0 : default: break;
2622 : }
2623 878 : lcl_putNestedSprm(m_aStates.top().aTableCellSprms, NS_ooxml::LN_CT_TcPrBase_tcBorders, nParam, pValue);
2624 1756 : m_aStates.top().nBorderState = BORDER_CELL;
2625 : }
2626 878 : break;
2627 : case RTF_PGBRDRT:
2628 : case RTF_PGBRDRL:
2629 : case RTF_PGBRDRB:
2630 : case RTF_PGBRDRR:
2631 : {
2632 0 : RTFSprms aAttributes;
2633 0 : RTFSprms aSprms;
2634 0 : RTFValue::Pointer_t pValue(new RTFValue(aAttributes, aSprms));
2635 0 : switch (nKeyword)
2636 : {
2637 0 : case RTF_PGBRDRT: nParam = NS_ooxml::LN_CT_PageBorders_top; break;
2638 0 : case RTF_PGBRDRL: nParam = NS_ooxml::LN_CT_PageBorders_left; break;
2639 0 : case RTF_PGBRDRB: nParam = NS_ooxml::LN_CT_PageBorders_bottom; break;
2640 0 : case RTF_PGBRDRR: nParam = NS_ooxml::LN_CT_PageBorders_right; break;
2641 0 : default: break;
2642 : }
2643 0 : lcl_putNestedSprm(m_aStates.top().aSectionSprms, NS_ooxml::LN_EG_SectPrContents_pgBorders, nParam, pValue);
2644 0 : m_aStates.top().nBorderState = BORDER_PAGE;
2645 : }
2646 0 : break;
2647 : case RTF_BRDRT:
2648 : case RTF_BRDRL:
2649 : case RTF_BRDRB:
2650 : case RTF_BRDRR:
2651 : {
2652 13 : RTFSprms aAttributes;
2653 26 : RTFSprms aSprms;
2654 26 : RTFValue::Pointer_t pValue(new RTFValue(aAttributes, aSprms));
2655 13 : switch (nKeyword)
2656 : {
2657 3 : case RTF_BRDRT: nParam = lcl_getParagraphBorder(0); break;
2658 3 : case RTF_BRDRL: nParam = lcl_getParagraphBorder(1); break;
2659 4 : case RTF_BRDRB: nParam = lcl_getParagraphBorder(2); break;
2660 3 : case RTF_BRDRR: nParam = lcl_getParagraphBorder(3); break;
2661 0 : default: break;
2662 : }
2663 13 : lcl_putNestedSprm(m_aStates.top().aParagraphSprms, NS_ooxml::LN_CT_PrBase_pBdr, nParam, pValue);
2664 26 : m_aStates.top().nBorderState = BORDER_PARAGRAPH;
2665 : }
2666 13 : break;
2667 : case RTF_CHBRDR:
2668 : {
2669 2 : RTFSprms aAttributes;
2670 4 : RTFValue::Pointer_t pValue(new RTFValue(aAttributes));
2671 2 : m_aStates.top().aCharacterSprms.set(NS_ooxml::LN_EG_RPrBase_bdr, pValue);
2672 4 : m_aStates.top().nBorderState = BORDER_CHARACTER;
2673 : }
2674 2 : break;
2675 : case RTF_CLMGF:
2676 : {
2677 1 : RTFValue::Pointer_t pValue(new RTFValue(NS_ooxml::LN_Value_ST_Merge_restart));
2678 1 : m_aStates.top().aTableCellSprms.set(NS_ooxml::LN_CT_TcPrBase_hMerge, pValue);
2679 : }
2680 1 : break;
2681 : case RTF_CLMRG:
2682 : {
2683 1 : RTFValue::Pointer_t pValue(new RTFValue(NS_ooxml::LN_Value_ST_Merge_continue));
2684 1 : m_aStates.top().aTableCellSprms.set(NS_ooxml::LN_CT_TcPrBase_hMerge, pValue);
2685 : }
2686 1 : break;
2687 : case RTF_CLVMGF:
2688 : {
2689 3 : RTFValue::Pointer_t pValue(new RTFValue(NS_ooxml::LN_Value_ST_Merge_restart));
2690 3 : m_aStates.top().aTableCellSprms.set(NS_ooxml::LN_CT_TcPrBase_vMerge, pValue);
2691 : }
2692 3 : break;
2693 : case RTF_CLVMRG:
2694 : {
2695 0 : RTFValue::Pointer_t pValue(new RTFValue(NS_ooxml::LN_Value_ST_Merge_continue));
2696 0 : m_aStates.top().aTableCellSprms.set(NS_ooxml::LN_CT_TcPrBase_vMerge, pValue);
2697 : }
2698 0 : break;
2699 : case RTF_CLVERTALT:
2700 : case RTF_CLVERTALC:
2701 : case RTF_CLVERTALB:
2702 : {
2703 212 : switch (nKeyword)
2704 : {
2705 206 : case RTF_CLVERTALT: nParam = 0; break;
2706 1 : case RTF_CLVERTALC: nParam = 1; break;
2707 5 : case RTF_CLVERTALB: nParam = 3; break;
2708 0 : default: break;
2709 : }
2710 212 : RTFValue::Pointer_t pValue(new RTFValue(nParam));
2711 212 : m_aStates.top().aTableCellSprms.set(NS_ooxml::LN_CT_TcPrBase_vAlign, pValue);
2712 : }
2713 212 : break;
2714 : case RTF_TRKEEP:
2715 : {
2716 1 : RTFValue::Pointer_t pValue(new RTFValue(1));
2717 1 : m_aStates.top().aTableRowSprms.set(NS_ooxml::LN_CT_TrPrBase_cantSplit, pValue);
2718 : }
2719 1 : break;
2720 : case RTF_SECTUNLOCKED:
2721 : {
2722 62 : RTFValue::Pointer_t pValue(new RTFValue(int(!nParam)));
2723 62 : m_aStates.top().aSectionSprms.set(NS_ooxml::LN_EG_SectPrContents_formProt, pValue);
2724 : }
2725 62 : break;
2726 : case RTF_PGNDEC:
2727 : case RTF_PGNUCRM:
2728 : case RTF_PGNLCRM:
2729 : case RTF_PGNUCLTR:
2730 : case RTF_PGNLCLTR:
2731 : case RTF_PGNBIDIA:
2732 : case RTF_PGNBIDIB:
2733 : // These should be mapped to NS_ooxml::LN_EG_SectPrContents_pgNumType, but dmapper has no API for that at the moment.
2734 124 : break;
2735 : case RTF_LOCH:
2736 : // Noop, dmapper detects this automatically.
2737 1375 : break;
2738 : case RTF_HICH:
2739 850 : m_aStates.top().bIsCjk = true;
2740 850 : break;
2741 : case RTF_DBCH:
2742 1542 : m_aStates.top().bIsCjk = false;
2743 1542 : break;
2744 : case RTF_TITLEPG:
2745 : {
2746 11 : RTFValue::Pointer_t pValue(new RTFValue(1));
2747 11 : m_aStates.top().aSectionSprms.set(NS_ooxml::LN_EG_SectPrContents_titlePg, pValue);
2748 : }
2749 11 : break;
2750 : case RTF_SUPER:
2751 : {
2752 22 : if (!m_aStates.top().pCurrentBuffer)
2753 22 : m_aStates.top().pCurrentBuffer = &m_aSuperBuffer;
2754 :
2755 22 : RTFValue::Pointer_t pValue(new RTFValue("superscript"));
2756 22 : m_aStates.top().aCharacterSprms.set(NS_ooxml::LN_EG_RPrBase_vertAlign, pValue);
2757 : }
2758 22 : break;
2759 : case RTF_SUB:
2760 : {
2761 1 : RTFValue::Pointer_t pValue(new RTFValue("subscript"));
2762 1 : m_aStates.top().aCharacterSprms.set(NS_ooxml::LN_EG_RPrBase_vertAlign, pValue);
2763 : }
2764 1 : break;
2765 : case RTF_NOSUPERSUB:
2766 : {
2767 4 : if (m_aStates.top().pCurrentBuffer == &m_aSuperBuffer)
2768 : {
2769 1 : replayBuffer(m_aSuperBuffer, 0, 0);
2770 1 : m_aStates.top().pCurrentBuffer = 0;
2771 : }
2772 4 : m_aStates.top().aCharacterSprms.erase(NS_ooxml::LN_EG_RPrBase_vertAlign);
2773 : }
2774 4 : break;
2775 : case RTF_LINEPPAGE:
2776 : case RTF_LINECONT:
2777 : {
2778 3 : RTFValue::Pointer_t pValue(new RTFValue(nKeyword == RTF_LINEPPAGE ? 0 : 2));
2779 3 : lcl_putNestedAttribute(m_aStates.top().aSectionSprms,
2780 6 : NS_ooxml::LN_EG_SectPrContents_lnNumType, NS_ooxml::LN_CT_LineNumber_restart, pValue);
2781 : }
2782 3 : break;
2783 : case RTF_AENDDOC:
2784 : // Noop, this is the default in Writer.
2785 72 : break;
2786 : case RTF_AENDNOTES:
2787 : // Noop, Writer does not support having endnotes at the end of section.
2788 0 : break;
2789 : case RTF_AFTNRSTCONT:
2790 : // Noop, this is the default in Writer.
2791 62 : break;
2792 : case RTF_AFTNRESTART:
2793 : // Noop, Writer does not support restarting endnotes at each section.
2794 0 : break;
2795 : case RTF_FTNBJ:
2796 : // Noop, this is the default in Writer.
2797 83 : break;
2798 : case RTF_ENDDOC:
2799 : {
2800 0 : RTFValue::Pointer_t pValue(new RTFValue(NS_ooxml::LN_Value_ST_RestartNumber_eachSect));
2801 : lcl_putNestedSprm(m_aDefaultState.aParagraphSprms,
2802 : NS_ooxml::LN_EG_SectPrContents_footnotePr,
2803 0 : NS_ooxml::LN_EG_FtnEdnNumProps_numRestart, pValue);
2804 : }
2805 0 : break;
2806 : case RTF_NOLINE:
2807 137 : lcl_eraseNestedAttribute(m_aStates.top().aSectionSprms, NS_ooxml::LN_EG_SectPrContents_lnNumType, NS_ooxml::LN_CT_LineNumber_distance);
2808 137 : break;
2809 : case RTF_FORMSHADE:
2810 : // Noop, this is the default in Writer.
2811 65 : break;
2812 : case RTF_PNGBLIP:
2813 14 : m_aStates.top().aPicture.nStyle = BMPSTYLE_PNG;
2814 14 : break;
2815 : case RTF_JPEGBLIP:
2816 1 : m_aStates.top().aPicture.nStyle = BMPSTYLE_JPEG;
2817 1 : break;
2818 0 : case RTF_POSYT: m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_yAlign, NS_ooxml::LN_Value_wordprocessingml_ST_YAlign_top); break;
2819 0 : case RTF_POSYB: m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_yAlign, NS_ooxml::LN_Value_wordprocessingml_ST_YAlign_bottom); break;
2820 0 : case RTF_POSYC: m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_yAlign, NS_ooxml::LN_Value_wordprocessingml_ST_YAlign_center); break;
2821 0 : case RTF_POSYIN: m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_yAlign, NS_ooxml::LN_Value_wordprocessingml_ST_YAlign_inside); break;
2822 0 : case RTF_POSYOUT: m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_yAlign, NS_ooxml::LN_Value_wordprocessingml_ST_YAlign_outside); break;
2823 0 : case RTF_POSYIL: m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_yAlign, NS_ooxml::LN_Value_wordprocessingml_ST_YAlign_inline); break;
2824 :
2825 3 : case RTF_PHMRG: m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_hAnchor, NS_ooxml::LN_Value_wordprocessingml_ST_HAnchor_margin); break;
2826 2 : case RTF_PVMRG: m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_vAnchor, NS_ooxml::LN_Value_wordprocessingml_ST_VAnchor_margin); break;
2827 12 : case RTF_PHPG: m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_hAnchor, NS_ooxml::LN_Value_wordprocessingml_ST_HAnchor_page); break;
2828 14 : case RTF_PVPG: m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_vAnchor, NS_ooxml::LN_Value_wordprocessingml_ST_VAnchor_page); break;
2829 0 : case RTF_PHCOL: m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_hAnchor, NS_ooxml::LN_Value_wordprocessingml_ST_HAnchor_text); break;
2830 0 : case RTF_PVPARA: m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_vAnchor, NS_ooxml::LN_Value_wordprocessingml_ST_VAnchor_text); break;
2831 :
2832 0 : case RTF_POSXC: m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_xAlign, NS_ooxml::LN_Value_wordprocessingml_ST_XAlign_center); break;
2833 0 : case RTF_POSXI: m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_xAlign, NS_ooxml::LN_Value_wordprocessingml_ST_XAlign_inside); break;
2834 0 : case RTF_POSXO: m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_xAlign, NS_ooxml::LN_Value_wordprocessingml_ST_XAlign_outside); break;
2835 0 : case RTF_POSXL: m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_xAlign, NS_ooxml::LN_Value_wordprocessingml_ST_XAlign_left); break;
2836 0 : case RTF_POSXR: m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_xAlign, NS_ooxml::LN_Value_wordprocessingml_ST_XAlign_right); break;
2837 :
2838 : case RTF_DPLINE:
2839 : case RTF_DPRECT:
2840 : case RTF_DPELLIPSE:
2841 : case RTF_DPTXBX:
2842 : case RTF_DPPOLYLINE:
2843 : {
2844 24 : sal_Int32 nType = 0;
2845 24 : switch (nKeyword)
2846 : {
2847 : case RTF_DPLINE:
2848 4 : m_aStates.top().aDrawingObject.xShape.set(getModelFactory()->createInstance("com.sun.star.drawing.LineShape"), uno::UNO_QUERY);
2849 4 : break;
2850 : case RTF_DPPOLYLINE:
2851 : // The reason this is not a simple CustomShape is that in the old syntax we have no ViewBox info.
2852 4 : m_aStates.top().aDrawingObject.xShape.set(getModelFactory()->createInstance("com.sun.star.drawing.PolyLineShape"), uno::UNO_QUERY);
2853 4 : break;
2854 : case RTF_DPRECT:
2855 5 : m_aStates.top().aDrawingObject.xShape.set(getModelFactory()->createInstance("com.sun.star.drawing.RectangleShape"), uno::UNO_QUERY);
2856 5 : break;
2857 : case RTF_DPELLIPSE:
2858 0 : nType = ESCHER_ShpInst_Ellipse;
2859 0 : break;
2860 : case RTF_DPTXBX:
2861 : {
2862 11 : m_aStates.top().aDrawingObject.xShape.set(getModelFactory()->createInstance("com.sun.star.text.TextFrame"), uno::UNO_QUERY);
2863 11 : std::vector<beans::PropertyValue> aDefaults = m_pSdrImport->getTextFrameDefaults(false);
2864 121 : for (size_t i = 0; i < aDefaults.size(); ++i)
2865 : {
2866 110 : if (!lcl_findPropertyName(m_aStates.top().aDrawingObject.aPendingProperties, aDefaults[i].Name))
2867 88 : m_aStates.top().aDrawingObject.aPendingProperties.push_back(aDefaults[i]);
2868 : }
2869 11 : checkFirstRun();
2870 11 : Mapper().startShape(m_aStates.top().aDrawingObject.xShape);
2871 11 : m_aStates.top().aDrawingObject.bHadShapeText = true;
2872 : }
2873 11 : break;
2874 : default:
2875 0 : break;
2876 : }
2877 24 : if (nType)
2878 0 : m_aStates.top().aDrawingObject.xShape.set(getModelFactory()->createInstance("com.sun.star.drawing.CustomShape"), uno::UNO_QUERY);
2879 24 : uno::Reference<drawing::XDrawPageSupplier> xDrawSupplier( m_xDstDoc, uno::UNO_QUERY);
2880 24 : if (xDrawSupplier.is())
2881 : {
2882 24 : uno::Reference<drawing::XShapes> xShapes(xDrawSupplier->getDrawPage(), uno::UNO_QUERY);
2883 24 : if (xShapes.is() && nKeyword != RTF_DPTXBX)
2884 13 : xShapes->add(m_aStates.top().aDrawingObject.xShape);
2885 : }
2886 24 : if (nType)
2887 : {
2888 0 : uno::Reference<drawing::XEnhancedCustomShapeDefaulter> xDefaulter(m_aStates.top().aDrawingObject.xShape, uno::UNO_QUERY);
2889 0 : xDefaulter->createCustomShapeDefaults(OUString::number(nType));
2890 : }
2891 24 : m_aStates.top().aDrawingObject.xPropertySet.set(m_aStates.top().aDrawingObject.xShape, uno::UNO_QUERY);
2892 24 : std::vector<beans::PropertyValue>& rPendingProperties = m_aStates.top().aDrawingObject.aPendingProperties;
2893 157 : for (std::vector<beans::PropertyValue>::iterator i = rPendingProperties.begin(); i != rPendingProperties.end(); ++i)
2894 133 : m_aStates.top().aDrawingObject.xPropertySet->setPropertyValue(i->Name, i->Value);
2895 24 : m_pSdrImport->resolveDhgt(m_aStates.top().aDrawingObject.xPropertySet, m_aStates.top().aDrawingObject.nDhgt, /*bOldStyle=*/true);
2896 : }
2897 24 : break;
2898 : case RTF_DOBXMARGIN:
2899 : case RTF_DOBYMARGIN:
2900 : {
2901 1 : beans::PropertyValue aPropertyValue;
2902 1 : aPropertyValue.Name = (nKeyword == RTF_DOBXMARGIN ? OUString("HoriOrientRelation") : OUString("VertOrientRelation"));
2903 1 : aPropertyValue.Value <<= text::RelOrientation::PAGE_PRINT_AREA;
2904 1 : m_aStates.top().aDrawingObject.aPendingProperties.push_back(aPropertyValue);
2905 : }
2906 1 : break;
2907 : case RTF_DOBXPAGE:
2908 : case RTF_DOBYPAGE:
2909 : {
2910 29 : beans::PropertyValue aPropertyValue;
2911 29 : aPropertyValue.Name = (nKeyword == RTF_DOBXPAGE ? OUString("HoriOrientRelation") : OUString("VertOrientRelation"));
2912 29 : aPropertyValue.Value <<= text::RelOrientation::PAGE_FRAME;
2913 29 : m_aStates.top().aDrawingObject.aPendingProperties.push_back(aPropertyValue);
2914 : }
2915 29 : break;
2916 : case RTF_DOBYPARA:
2917 : {
2918 15 : beans::PropertyValue aPropertyValue;
2919 15 : aPropertyValue.Name = "VertOrientRelation";
2920 15 : aPropertyValue.Value <<= text::RelOrientation::FRAME;
2921 15 : m_aStates.top().aDrawingObject.aPendingProperties.push_back(aPropertyValue);
2922 : }
2923 15 : break;
2924 : case RTF_CONTEXTUALSPACE:
2925 : {
2926 2 : RTFValue::Pointer_t pValue(new RTFValue(1));
2927 2 : m_aStates.top().aParagraphSprms.set(NS_ooxml::LN_CT_PPrBase_contextualSpacing, pValue);
2928 : }
2929 2 : break;
2930 : case RTF_LINKSTYLES:
2931 : {
2932 1 : RTFValue::Pointer_t pValue(new RTFValue(1));
2933 1 : m_aSettingsTableSprms.set(NS_ooxml::LN_CT_Settings_linkStyles, pValue);
2934 : }
2935 1 : break;
2936 : case RTF_PNLVLBODY:
2937 : {
2938 3 : RTFValue::Pointer_t pValue(new RTFValue(2));
2939 3 : m_aStates.top().aTableAttributes.set(NS_ooxml::LN_CT_AbstractNum_nsid, pValue);
2940 : }
2941 3 : break;
2942 : case RTF_PNDEC:
2943 : {
2944 3 : RTFValue::Pointer_t pValue(new RTFValue(0)); // decimal, same as \levelnfc0
2945 3 : m_aStates.top().aTableSprms.set(NS_ooxml::LN_CT_Lvl_numFmt, pValue);
2946 : }
2947 3 : break;
2948 : case RTF_PNLVLBLT:
2949 : {
2950 1 : m_aStates.top().aTableAttributes.set(NS_ooxml::LN_CT_AbstractNum_nsid, RTFValue::Pointer_t(new RTFValue(1)));
2951 1 : m_aStates.top().aTableSprms.set(NS_ooxml::LN_CT_Lvl_numFmt, RTFValue::Pointer_t(new RTFValue(23))); // bullets, same as \levelnfc23
2952 : }
2953 1 : break;
2954 : case RTF_LANDSCAPE:
2955 3 : lcl_putNestedAttribute(m_aStates.top().aSectionSprms, NS_ooxml::LN_EG_SectPrContents_pgSz, NS_ooxml::LN_CT_PageSz_orient, RTFValue::Pointer_t(new RTFValue(1)));
2956 3 : break;
2957 : case RTF_FACINGP:
2958 3 : m_aSettingsTableSprms.set(NS_ooxml::LN_CT_Settings_evenAndOddHeaders, RTFValue::Pointer_t(new RTFValue(1)));
2959 3 : break;
2960 : case RTF_SHPBXPAGE:
2961 19 : m_aStates.top().aShape.nHoriOrientRelation = text::RelOrientation::PAGE_FRAME;
2962 19 : m_aStates.top().aShape.nHoriOrientRelationToken = NS_ooxml::LN_Value_wordprocessingDrawing_ST_RelFromH_page;
2963 19 : break;
2964 : case RTF_SHPBYPAGE:
2965 18 : m_aStates.top().aShape.nVertOrientRelation = text::RelOrientation::PAGE_FRAME;
2966 18 : m_aStates.top().aShape.nVertOrientRelationToken = NS_ooxml::LN_Value_wordprocessingDrawing_ST_RelFromV_page;
2967 18 : break;
2968 : case RTF_DPLINEHOLLOW:
2969 13 : m_aStates.top().aDrawingObject.nFLine = 0;
2970 13 : break;
2971 : case RTF_DPROUNDR:
2972 2 : if (m_aStates.top().aDrawingObject.xPropertySet.is())
2973 : // Seems this old syntax has no way to specify a custom radius, and this is the default
2974 2 : m_aStates.top().aDrawingObject.xPropertySet->setPropertyValue("CornerRadius", uno::makeAny(sal_Int32(83)));
2975 2 : break;
2976 : case RTF_NOWRAP:
2977 2 : m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_wrap, NS_ooxml::LN_Value_wordprocessingml_ST_Wrap_notBeside);
2978 2 : break;
2979 : case RTF_MNOR:
2980 9 : m_bMathNor = true;
2981 9 : break;
2982 : case RTF_REVISIONS:
2983 3 : m_aSettingsTableSprms.set(NS_ooxml::LN_CT_Settings_trackRevisions, RTFValue::Pointer_t(new RTFValue(1)));
2984 3 : break;
2985 : case RTF_BRDRSH:
2986 14 : lcl_putBorderProperty(m_aStates, NS_ooxml::LN_CT_Border_shadow, RTFValue::Pointer_t(new RTFValue(1)));
2987 14 : break;
2988 : default:
2989 : {
2990 : SAL_INFO("writerfilter", "TODO handle flag '" << lcl_RtfToString(nKeyword) << "'");
2991 1347 : aSkip.setParsed(false);
2992 : }
2993 1347 : break;
2994 : }
2995 12443 : return 0;
2996 : }
2997 :
2998 25691 : int RTFDocumentImpl::dispatchValue(RTFKeyword nKeyword, int nParam)
2999 : {
3000 25691 : setNeedSect();
3001 25691 : checkUnicode(/*bUnicode =*/ nKeyword != RTF_U, /*bHex =*/ true);
3002 25691 : RTFSkipDestination aSkip(*this);
3003 25691 : int nSprm = 0;
3004 51382 : RTFValue::Pointer_t pIntValue(new RTFValue(nParam));
3005 : // Trivial table sprms.
3006 25691 : switch (nKeyword)
3007 : {
3008 53 : case RTF_LEVELJC: nSprm = NS_ooxml::LN_CT_Lvl_lvlJc; break;
3009 57 : case RTF_LEVELNFC: nSprm = NS_ooxml::LN_CT_Lvl_numFmt; break;
3010 58 : case RTF_LEVELSTARTAT: nSprm = NS_ooxml::LN_CT_Lvl_start; break;
3011 3 : case RTF_LEVELPICTURE: nSprm = NS_ooxml::LN_CT_Lvl_lvlPicBulletId; break;
3012 25520 : default: break;
3013 : }
3014 25691 : if (nSprm > 0)
3015 : {
3016 171 : m_aStates.top().aTableSprms.set(nSprm, pIntValue);
3017 171 : return 0;
3018 : }
3019 : // Trivial character sprms.
3020 25520 : switch (nKeyword)
3021 : {
3022 719 : case RTF_FS: nSprm = NS_ooxml::LN_EG_RPrBase_sz; break;
3023 516 : case RTF_AFS: nSprm = NS_ooxml::LN_EG_RPrBase_szCs; break;
3024 0 : case RTF_ANIMTEXT: nSprm = NS_ooxml::LN_EG_RPrBase_effect; break;
3025 4 : case RTF_EXPNDTW: nSprm = NS_ooxml::LN_EG_RPrBase_spacing; break;
3026 250 : case RTF_KERNING: nSprm = NS_ooxml::LN_EG_RPrBase_kern; break;
3027 0 : case RTF_CHARSCALEX: nSprm = NS_ooxml::LN_EG_RPrBase_w; break;
3028 24031 : default: break;
3029 : }
3030 25520 : if (nSprm > 0)
3031 : {
3032 1489 : m_aStates.top().aCharacterSprms.set(nSprm, pIntValue);
3033 1489 : return 0;
3034 : }
3035 : // Trivial character attributes.
3036 24031 : switch (nKeyword)
3037 : {
3038 423 : case RTF_LANG: nSprm = NS_ooxml::LN_CT_Language_val; break;
3039 393 : case RTF_LANGFE: nSprm = NS_ooxml::LN_CT_Language_eastAsia; break;
3040 336 : case RTF_ALANG: nSprm = NS_ooxml::LN_CT_Language_bidi; break;
3041 22879 : default: break;
3042 : }
3043 24031 : if (nSprm > 0)
3044 : {
3045 1152 : LanguageTag aTag((LanguageType)nParam);
3046 2304 : RTFValue::Pointer_t pValue(new RTFValue(aTag.getBcp47()));
3047 1152 : lcl_putNestedAttribute(m_aStates.top().aCharacterSprms, NS_ooxml::LN_EG_RPrBase_lang, nSprm, pValue);
3048 : // Language is a character property, but we should store it at a paragraph level as well for fields.
3049 1152 : if (nKeyword == RTF_LANG && m_bNeedPap)
3050 412 : lcl_putNestedAttribute(m_aStates.top().aParagraphSprms, NS_ooxml::LN_EG_RPrBase_lang, nSprm, pValue);
3051 2304 : return 0;
3052 : }
3053 : // Trivial paragraph sprms.
3054 22879 : switch (nKeyword)
3055 : {
3056 84 : case RTF_ITAP: nSprm = NS_ooxml::LN_tblDepth; break;
3057 : case RTF_SBASEDON:
3058 390 : nSprm = NS_ooxml::LN_CT_Style_basedOn;
3059 390 : pIntValue.reset(new RTFValue(getStyleName(nParam)));
3060 390 : break;
3061 22405 : default: break;
3062 : }
3063 22879 : if (nSprm > 0)
3064 : {
3065 474 : m_aStates.top().aParagraphSprms.set(nSprm, pIntValue);
3066 474 : if (nKeyword == RTF_ITAP && nParam > 0)
3067 : {
3068 34 : while (m_aTableBufferStack.size() < sal::static_int_cast<size_t>(nParam))
3069 : {
3070 6 : m_aTableBufferStack.push_back(RTFBuffer_t());
3071 : }
3072 : // Invalid tables may omit INTBL after ITAP
3073 14 : dispatchFlag(RTF_INTBL); // sets newly pushed buffer as current
3074 : assert(m_aStates.top().pCurrentBuffer == &m_aTableBufferStack.back());
3075 : }
3076 474 : return 0;
3077 : }
3078 :
3079 : // Info group.
3080 22405 : switch (nKeyword)
3081 : {
3082 : case RTF_YR:
3083 : {
3084 172 : m_aStates.top().nYear = nParam;
3085 172 : nSprm = 1;
3086 : }
3087 172 : break;
3088 : case RTF_MO:
3089 : {
3090 172 : m_aStates.top().nMonth = nParam;
3091 172 : nSprm = 1;
3092 : }
3093 172 : break;
3094 : case RTF_DY:
3095 : {
3096 172 : m_aStates.top().nDay = nParam;
3097 172 : nSprm = 1;
3098 : }
3099 172 : break;
3100 : case RTF_HR:
3101 : {
3102 172 : m_aStates.top().nHour = nParam;
3103 172 : nSprm = 1;
3104 : }
3105 172 : break;
3106 : case RTF_MIN:
3107 : {
3108 172 : m_aStates.top().nMinute = nParam;
3109 172 : nSprm = 1;
3110 : }
3111 172 : break;
3112 : default:
3113 21545 : break;
3114 : }
3115 22405 : if (nSprm > 0)
3116 860 : return 0;
3117 :
3118 : // Frame size / position.
3119 21545 : Id nId = 0;
3120 21545 : switch (nKeyword)
3121 : {
3122 : case RTF_ABSW:
3123 17 : nId = NS_ooxml::LN_CT_FramePr_w;
3124 17 : break;
3125 : case RTF_ABSH:
3126 17 : nId = NS_ooxml::LN_CT_FramePr_h;
3127 17 : break;
3128 : case RTF_POSX:
3129 : {
3130 17 : nId = NS_ooxml::LN_CT_FramePr_x;
3131 17 : m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_xAlign, 0);
3132 : }
3133 17 : break;
3134 : case RTF_POSY:
3135 : {
3136 17 : nId = NS_ooxml::LN_CT_FramePr_y;
3137 17 : m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_yAlign, 0);
3138 : }
3139 17 : break;
3140 : default:
3141 21477 : break;
3142 : }
3143 :
3144 21545 : if (nId > 0)
3145 : {
3146 68 : m_bNeedPap = true;
3147 : // Don't try to support text frames inside tables for now.
3148 68 : if (m_aStates.top().pCurrentBuffer != &m_aTableBufferStack.back())
3149 68 : m_aStates.top().aFrame.setSprm(nId, nParam);
3150 :
3151 68 : return 0;
3152 : }
3153 :
3154 : // Then check for the more complex ones.
3155 21477 : switch (nKeyword)
3156 : {
3157 : case RTF_F:
3158 : case RTF_AF:
3159 6081 : if (nKeyword == RTF_F)
3160 2409 : nSprm = NS_ooxml::LN_CT_Fonts_ascii;
3161 : else
3162 3672 : nSprm = (m_aStates.top().bIsCjk ? NS_ooxml::LN_CT_Fonts_eastAsia : NS_ooxml::LN_CT_Fonts_cs);
3163 6081 : if (m_aStates.top().nDestinationState == DESTINATION_FONTTABLE || m_aStates.top().nDestinationState == DESTINATION_FONTENTRY)
3164 : {
3165 815 : m_aFontIndexes.push_back(nParam);
3166 815 : m_nCurrentFontIndex = getFontIndex(nParam);
3167 : }
3168 5266 : else if (m_aStates.top().nDestinationState == DESTINATION_LISTLEVEL)
3169 : {
3170 12 : RTFSprms aFontAttributes;
3171 12 : aFontAttributes.set(nSprm, RTFValue::Pointer_t(new RTFValue(m_aFontNames[getFontIndex(nParam)])));
3172 : // In the context of listlevels, \af seems to imply \f.
3173 12 : if (nKeyword == RTF_AF)
3174 7 : aFontAttributes.set(NS_ooxml::LN_CT_Fonts_ascii, RTFValue::Pointer_t(new RTFValue(m_aFontNames[getFontIndex(nParam)])));
3175 24 : RTFSprms aRunPropsSprms;
3176 12 : aRunPropsSprms.set(NS_ooxml::LN_EG_RPrBase_rFonts, RTFValue::Pointer_t(new RTFValue(aFontAttributes)));
3177 : // If there are multiple \f or \af tokens, only handle the first one.
3178 12 : if (!m_aStates.top().aTableSprms.find(NS_ooxml::LN_CT_Lvl_rPr))
3179 22 : m_aStates.top().aTableSprms.set(NS_ooxml::LN_CT_Lvl_rPr, RTFValue::Pointer_t(new RTFValue(RTFSprms(), aRunPropsSprms)));
3180 : }
3181 : else
3182 : {
3183 5254 : m_nCurrentFontIndex = getFontIndex(nParam);
3184 5254 : RTFValue::Pointer_t pValue(new RTFValue(getFontName(m_nCurrentFontIndex)));
3185 5254 : lcl_putNestedAttribute(m_aStates.top().aCharacterSprms, NS_ooxml::LN_EG_RPrBase_rFonts, nSprm, pValue);
3186 5254 : m_aStates.top().nCurrentEncoding = getEncoding(m_nCurrentFontIndex);
3187 : }
3188 6081 : break;
3189 : case RTF_RED:
3190 330 : m_aStates.top().aCurrentColor.nRed = nParam;
3191 330 : break;
3192 : case RTF_GREEN:
3193 330 : m_aStates.top().aCurrentColor.nGreen = nParam;
3194 330 : break;
3195 : case RTF_BLUE:
3196 330 : m_aStates.top().aCurrentColor.nBlue = nParam;
3197 330 : break;
3198 : case RTF_FCHARSET:
3199 : {
3200 : // we always send text to the domain mapper in OUString, so no
3201 : // need to send encoding info
3202 : int i;
3203 6965 : for (i = 0; i < nRTFEncodings; i++)
3204 : {
3205 6965 : if (aRTFEncodings[i].charset == nParam)
3206 803 : break;
3207 : }
3208 803 : if (i == nRTFEncodings)
3209 : // not found
3210 0 : return 0;
3211 :
3212 803 : m_nCurrentEncoding = rtl_getTextEncodingFromWindowsCodePage(aRTFEncodings[i].codepage);
3213 : }
3214 803 : break;
3215 : case RTF_ANSICPG:
3216 : {
3217 30 : m_aDefaultState.nCurrentEncoding = rtl_getTextEncodingFromWindowsCodePage(nParam);
3218 30 : m_aStates.top().nCurrentEncoding = rtl_getTextEncodingFromWindowsCodePage(nParam);
3219 : }
3220 30 : break;
3221 : case RTF_CPG:
3222 4 : m_nCurrentEncoding = rtl_getTextEncodingFromWindowsCodePage(nParam);
3223 4 : break;
3224 : case RTF_CF:
3225 : {
3226 314 : RTFSprms aAttributes;
3227 628 : RTFValue::Pointer_t pValue(new RTFValue(getColorTable(nParam)));
3228 314 : aAttributes.set(NS_ooxml::LN_CT_Color_val, pValue);
3229 628 : m_aStates.top().aCharacterSprms.set(NS_ooxml::LN_EG_RPrBase_color, RTFValue::Pointer_t(new RTFValue(aAttributes)));
3230 : }
3231 314 : break;
3232 : case RTF_S:
3233 : {
3234 698 : m_aStates.top().nCurrentStyleIndex = nParam;
3235 :
3236 698 : if (m_aStates.top().nDestinationState == DESTINATION_STYLESHEET || m_aStates.top().nDestinationState == DESTINATION_STYLEENTRY)
3237 : {
3238 462 : m_nCurrentStyleIndex = nParam;
3239 462 : RTFValue::Pointer_t pValue(new RTFValue(1));
3240 462 : m_aStates.top().aTableAttributes.set(NS_ooxml::LN_CT_Style_type, pValue); // paragraph style
3241 : }
3242 : else
3243 : {
3244 236 : OUString aName = getStyleName(nParam);
3245 236 : if (!aName.isEmpty())
3246 196 : m_aStates.top().aParagraphSprms.set(NS_ooxml::LN_CT_PPrBase_pStyle, RTFValue::Pointer_t(new RTFValue(aName)));
3247 : }
3248 : }
3249 698 : break;
3250 : case RTF_CS:
3251 62 : if (m_aStates.top().nDestinationState == DESTINATION_STYLESHEET || m_aStates.top().nDestinationState == DESTINATION_STYLEENTRY)
3252 : {
3253 59 : m_nCurrentStyleIndex = nParam;
3254 59 : RTFValue::Pointer_t pValue(new RTFValue(2));
3255 59 : m_aStates.top().aTableAttributes.set(NS_ooxml::LN_CT_Style_type, pValue); // character style
3256 : }
3257 : else
3258 : {
3259 3 : OUString aName = getStyleName(nParam);
3260 3 : if (!aName.isEmpty())
3261 3 : m_aStates.top().aCharacterSprms.set(NS_ooxml::LN_EG_RPrBase_rStyle, RTFValue::Pointer_t(new RTFValue(aName)));
3262 : }
3263 62 : break;
3264 : case RTF_DEFF:
3265 105 : m_nDefaultFontIndex = nParam;
3266 105 : break;
3267 : case RTF_DEFLANG:
3268 : case RTF_ADEFLANG:
3269 : {
3270 99 : LanguageTag aTag((LanguageType)nParam);
3271 198 : RTFValue::Pointer_t pValue(new RTFValue(aTag.getBcp47()));
3272 198 : lcl_putNestedAttribute(m_aStates.top().aCharacterSprms, (nKeyword == RTF_DEFLANG ? NS_ooxml::LN_EG_RPrBase_lang : NS_ooxml::LN_CT_Language_bidi), nSprm, pValue);
3273 : }
3274 99 : break;
3275 : case RTF_CHCBPAT:
3276 : {
3277 4 : RTFValue::Pointer_t pValue(new RTFValue(nParam ? getColorTable(nParam) : COL_AUTO));
3278 4 : lcl_putNestedAttribute(m_aStates.top().aCharacterSprms, NS_ooxml::LN_EG_RPrBase_shd, NS_ooxml::LN_CT_Shd_fill, pValue);
3279 : }
3280 4 : break;
3281 : case RTF_CLCBPAT:
3282 : {
3283 3 : RTFValue::Pointer_t pValue(new RTFValue(getColorTable(nParam)));
3284 3 : lcl_putNestedAttribute(m_aStates.top().aTableCellSprms,
3285 6 : NS_ooxml::LN_CT_TcPrBase_shd, NS_ooxml::LN_CT_Shd_fill, pValue);
3286 : }
3287 3 : break;
3288 : case RTF_CBPAT:
3289 2 : if (nParam)
3290 : {
3291 1 : RTFValue::Pointer_t pValue(new RTFValue(getColorTable(nParam)));
3292 1 : lcl_putNestedAttribute(m_aStates.top().aParagraphSprms, NS_ooxml::LN_CT_PrBase_shd, NS_ooxml::LN_CT_Shd_fill, pValue);
3293 : }
3294 2 : break;
3295 : case RTF_ULC:
3296 : {
3297 8 : RTFValue::Pointer_t pValue(new RTFValue(getColorTable(nParam)));
3298 8 : m_aStates.top().aCharacterSprms.set(0x6877, pValue);
3299 : }
3300 8 : break;
3301 : case RTF_HIGHLIGHT:
3302 : {
3303 1 : RTFValue::Pointer_t pValue(new RTFValue(getColorTable(nParam)));
3304 1 : m_aStates.top().aCharacterSprms.set(NS_ooxml::LN_EG_RPrBase_highlight, pValue);
3305 : }
3306 1 : break;
3307 : case RTF_UP:
3308 : case RTF_DN:
3309 : {
3310 2 : RTFValue::Pointer_t pValue(new RTFValue(nParam * (nKeyword == RTF_UP ? 1 : -1)));
3311 2 : m_aStates.top().aCharacterSprms.set(NS_ooxml::LN_EG_RPrBase_position, pValue);
3312 : }
3313 2 : break;
3314 : case RTF_HORZVERT:
3315 : {
3316 0 : RTFValue::Pointer_t pValue(new RTFValue(int(true)));
3317 0 : m_aStates.top().aCharacterAttributes.set(NS_ooxml::LN_CT_EastAsianLayout_vert, pValue);
3318 0 : if (nParam)
3319 : // rotate fits to a single line
3320 0 : m_aStates.top().aCharacterAttributes.set(NS_ooxml::LN_CT_EastAsianLayout_vertCompress, pValue);
3321 : }
3322 0 : break;
3323 : case RTF_EXPND:
3324 : {
3325 4 : RTFValue::Pointer_t pValue(new RTFValue(nParam/5));
3326 4 : m_aStates.top().aCharacterSprms.set(NS_ooxml::LN_EG_RPrBase_spacing, pValue);
3327 : }
3328 4 : break;
3329 : case RTF_TWOINONE:
3330 : {
3331 0 : RTFValue::Pointer_t pValue(new RTFValue(int(true)));
3332 0 : m_aStates.top().aCharacterAttributes.set(NS_ooxml::LN_CT_EastAsianLayout_combine, pValue);
3333 0 : if (nParam > 0)
3334 0 : m_aStates.top().aCharacterAttributes.set(NS_ooxml::LN_CT_EastAsianLayout_combineBrackets, pIntValue);
3335 : }
3336 0 : break;
3337 : case RTF_SL:
3338 : {
3339 : // This is similar to RTF_ABSH, negative value means 'exact', positive means 'at least'.
3340 204 : RTFValue::Pointer_t pValue(new RTFValue(NS_ooxml::LN_Value_wordprocessingml_ST_LineSpacingRule_atLeast));
3341 204 : if (nParam < 0)
3342 : {
3343 6 : pValue.reset(new RTFValue(NS_ooxml::LN_Value_wordprocessingml_ST_LineSpacingRule_exact));
3344 6 : pIntValue.reset(new RTFValue(-nParam));
3345 : }
3346 204 : m_aStates.top().aParagraphAttributes.set(NS_ooxml::LN_CT_Spacing_lineRule, pValue);
3347 204 : m_aStates.top().aParagraphAttributes.set(NS_ooxml::LN_CT_Spacing_line, pIntValue);
3348 : }
3349 204 : break;
3350 : case RTF_SLMULT:
3351 195 : if (nParam > 0)
3352 : {
3353 159 : RTFValue::Pointer_t pValue(new RTFValue(NS_ooxml::LN_Value_wordprocessingml_ST_LineSpacingRule_auto));
3354 159 : m_aStates.top().aParagraphAttributes.set(NS_ooxml::LN_CT_Spacing_lineRule, pValue);
3355 : }
3356 195 : break;
3357 : case RTF_BRDRW:
3358 : {
3359 : // dmapper expects it in 1/8 pt, we have it in twip - but avoid rounding 1 to 0
3360 491 : if (nParam > 1)
3361 456 : nParam = nParam * 2 / 5;
3362 491 : RTFValue::Pointer_t pValue(new RTFValue(nParam));
3363 491 : lcl_putBorderProperty(m_aStates, NS_ooxml::LN_CT_Border_sz, pValue);
3364 : }
3365 491 : break;
3366 : case RTF_BRDRCF:
3367 : {
3368 190 : RTFValue::Pointer_t pValue(new RTFValue(getColorTable(nParam)));
3369 190 : lcl_putBorderProperty(m_aStates, NS_ooxml::LN_CT_Border_color, pValue);
3370 : }
3371 190 : break;
3372 : case RTF_BRSP:
3373 : {
3374 : // dmapper expects it in points, we have it in twip
3375 15 : RTFValue::Pointer_t pValue(new RTFValue(nParam / 20));
3376 15 : lcl_putBorderProperty(m_aStates, NS_ooxml::LN_CT_Border_space, pValue);
3377 : }
3378 15 : break;
3379 : case RTF_TX:
3380 : {
3381 104 : m_aStates.top().aTabAttributes.set(NS_ooxml::LN_CT_TabStop_pos, pIntValue);
3382 104 : RTFValue::Pointer_t pValue(new RTFValue(m_aStates.top().aTabAttributes));
3383 104 : lcl_putNestedSprm(m_aStates.top().aParagraphSprms, NS_ooxml::LN_CT_PPrBase_tabs, NS_ooxml::LN_CT_Tabs_tab, pValue);
3384 104 : m_aStates.top().aTabAttributes.clear();
3385 : }
3386 104 : break;
3387 : case RTF_ILVL:
3388 16 : lcl_putNestedSprm(m_aStates.top().aParagraphSprms, NS_ooxml::LN_CT_PPrBase_numPr, NS_ooxml::LN_CT_NumPr_ilvl, pIntValue);
3389 16 : break;
3390 : case RTF_LISTTEMPLATEID:
3391 : // This one is not referenced anywhere, so it's pointless to store it at the moment.
3392 20 : break;
3393 : case RTF_LISTID:
3394 : {
3395 39 : if (m_aStates.top().nDestinationState == DESTINATION_LISTENTRY)
3396 20 : m_aStates.top().aTableAttributes.set(NS_ooxml::LN_CT_AbstractNum_abstractNumId, pIntValue);
3397 19 : else if (m_aStates.top().nDestinationState == DESTINATION_LISTOVERRIDEENTRY)
3398 19 : m_aStates.top().aTableSprms.set(NS_ooxml::LN_CT_Num_abstractNumId, pIntValue);
3399 : }
3400 39 : break;
3401 : case RTF_LS:
3402 : {
3403 46 : if (m_aStates.top().nDestinationState == DESTINATION_LISTOVERRIDEENTRY)
3404 19 : m_aStates.top().aTableAttributes.set(NS_ooxml::LN_CT_AbstractNum_nsid, pIntValue);
3405 : else
3406 27 : lcl_putNestedSprm(m_aStates.top().aParagraphSprms, NS_ooxml::LN_CT_PPrBase_tabs, NS_ooxml::LN_CT_NumPr_numId, pIntValue);
3407 : }
3408 46 : break;
3409 : case RTF_UC:
3410 27 : if ((SAL_MIN_INT16 <= nParam) && (nParam <= SAL_MAX_INT16))
3411 27 : m_aStates.top().nUc = nParam;
3412 27 : break;
3413 : case RTF_U:
3414 : // sal_Unicode is unsigned 16-bit, RTF may represent that as a
3415 : // signed SAL_MIN_INT16..SAL_MAX_INT16 or 0..SAL_MAX_UINT16. The
3416 : // static_cast() will do the right thing.
3417 149 : if ((SAL_MIN_INT16 <= nParam) && (nParam <= SAL_MAX_UINT16))
3418 : {
3419 149 : m_aUnicodeBuffer.append(static_cast<sal_Unicode>(nParam));
3420 149 : if (m_aStates.top().nDestinationState != DESTINATION_LEVELTEXT)
3421 144 : m_aStates.top().nCharsToSkip = m_aStates.top().nUc;
3422 : }
3423 149 : break;
3424 : case RTF_LEVELFOLLOW:
3425 : {
3426 58 : OUString sValue;
3427 58 : switch (nParam)
3428 : {
3429 : case 0:
3430 38 : sValue = "tab";
3431 38 : break;
3432 : case 1:
3433 1 : sValue = "space";
3434 1 : break;
3435 : case 2:
3436 19 : sValue = "nothing";
3437 19 : break;
3438 : }
3439 58 : if (!sValue.isEmpty())
3440 58 : m_aStates.top().aTableSprms.set(NS_ooxml::LN_CT_Lvl_suff, RTFValue::Pointer_t(new RTFValue(sValue)));
3441 : }
3442 58 : break;
3443 : case RTF_FPRQ:
3444 : {
3445 784 : sal_Int32 nValue = 0;
3446 784 : switch (nParam)
3447 : {
3448 : case 0:
3449 78 : nValue = NS_ooxml::LN_Value_ST_Pitch_default;
3450 78 : break;
3451 : case 1:
3452 32 : nValue = NS_ooxml::LN_Value_ST_Pitch_fixed;
3453 32 : break;
3454 : case 2:
3455 674 : nValue = NS_ooxml::LN_Value_ST_Pitch_variable;
3456 674 : break;
3457 : }
3458 784 : if (nValue)
3459 : {
3460 784 : RTFSprms aAttributes;
3461 784 : aAttributes.set(NS_ooxml::LN_CT_Pitch_val, RTFValue::Pointer_t(new RTFValue(nValue)));
3462 784 : m_aStates.top().aTableSprms.set(NS_ooxml::LN_CT_Font_pitch, RTFValue::Pointer_t(new RTFValue(aAttributes)));
3463 : }
3464 : }
3465 784 : break;
3466 : case RTF_LISTOVERRIDECOUNT:
3467 : // Ignore this for now, the exporter always emits it with a zero parameter.
3468 19 : break;
3469 : case RTF_PICSCALEX:
3470 13 : m_aStates.top().aPicture.nScaleX = nParam;
3471 13 : break;
3472 : case RTF_PICSCALEY:
3473 13 : m_aStates.top().aPicture.nScaleY = nParam;
3474 13 : break;
3475 : case RTF_PICW:
3476 14 : m_aStates.top().aPicture.nWidth = nParam;
3477 14 : break;
3478 : case RTF_PICH:
3479 14 : m_aStates.top().aPicture.nHeight = nParam;
3480 14 : break;
3481 : case RTF_PICWGOAL:
3482 15 : m_aStates.top().aPicture.nGoalWidth = TWIP_TO_MM100(nParam);
3483 15 : break;
3484 : case RTF_PICHGOAL:
3485 15 : m_aStates.top().aPicture.nGoalHeight = TWIP_TO_MM100(nParam);
3486 15 : break;
3487 10 : case RTF_PICCROPL: m_aStates.top().aPicture.nCropL = TWIP_TO_MM100(nParam); break;
3488 10 : case RTF_PICCROPR: m_aStates.top().aPicture.nCropR = TWIP_TO_MM100(nParam); break;
3489 10 : case RTF_PICCROPT: m_aStates.top().aPicture.nCropT = TWIP_TO_MM100(nParam); break;
3490 10 : case RTF_PICCROPB: m_aStates.top().aPicture.nCropB = TWIP_TO_MM100(nParam); break;
3491 : case RTF_SHPWRK:
3492 : {
3493 38 : int nValue = 0;
3494 38 : switch (nParam)
3495 : {
3496 37 : case 0: nValue = NS_ooxml::LN_Value_wordprocessingDrawing_ST_WrapText_bothSides; break;
3497 0 : case 1: nValue = NS_ooxml::LN_Value_wordprocessingDrawing_ST_WrapText_left; break;
3498 1 : case 2: nValue = NS_ooxml::LN_Value_wordprocessingDrawing_ST_WrapText_right; break;
3499 0 : case 3: nValue = NS_ooxml::LN_Value_wordprocessingDrawing_ST_WrapText_largest; break;
3500 0 : default: break;
3501 : }
3502 38 : RTFValue::Pointer_t pValue(new RTFValue(nValue));
3503 38 : m_aStates.top().aCharacterAttributes.set(NS_ooxml::LN_CT_WrapSquare_wrapText, pValue);
3504 : }
3505 38 : break;
3506 : case RTF_SHPWR:
3507 : {
3508 47 : switch (nParam)
3509 : {
3510 : case 1:
3511 0 : m_aStates.top().aShape.nWrap = com::sun::star::text::WrapTextMode_NONE; break;
3512 : case 2:
3513 4 : m_aStates.top().aShape.nWrap = com::sun::star::text::WrapTextMode_PARALLEL; break;
3514 : case 3:
3515 37 : m_aStates.top().aShape.nWrap = com::sun::star::text::WrapTextMode_THROUGHT; break;
3516 : case 4:
3517 1 : m_aStates.top().aShape.nWrap = com::sun::star::text::WrapTextMode_PARALLEL; break;
3518 : case 5:
3519 4 : m_aStates.top().aShape.nWrap = com::sun::star::text::WrapTextMode_THROUGHT; break;
3520 : }
3521 : }
3522 47 : break;
3523 : case RTF_CELLX:
3524 : {
3525 344 : int & rCurrentCellX((DESTINATION_NESTEDTABLEPROPERTIES ==
3526 344 : m_aStates.top().nDestinationState)
3527 : ? m_nNestedCurrentCellX
3528 344 : : m_nTopLevelCurrentCellX);
3529 344 : int nCellX = nParam - rCurrentCellX;
3530 344 : const int COL_DFLT_WIDTH = 41; // sw/source/filter/inc/wrtswtbl.hxx, minimal possible width of cells.
3531 344 : if (!nCellX)
3532 1 : nCellX = COL_DFLT_WIDTH;
3533 :
3534 : // If there is a negative left margin, then the first cellx is relative to that.
3535 344 : RTFValue::Pointer_t pTblInd = m_aStates.top().aTableRowSprms.find(NS_ooxml::LN_CT_TblPrBase_tblInd);
3536 344 : if (rCurrentCellX == 0 && pTblInd.get())
3537 : {
3538 63 : RTFValue::Pointer_t pWidth = pTblInd->getAttributes().find(NS_ooxml::LN_CT_TblWidth_w);
3539 63 : if (pWidth.get() && pWidth->getInt() < 0)
3540 43 : nCellX = -1 * (pWidth->getInt() - nParam);
3541 : }
3542 :
3543 344 : rCurrentCellX = nParam;
3544 688 : RTFValue::Pointer_t pXValue(new RTFValue(nCellX));
3545 344 : m_aStates.top().aTableRowSprms.set(NS_ooxml::LN_CT_TblGridBase_gridCol, pXValue, OVERWRITE_NO_APPEND);
3546 344 : if (DESTINATION_NESTEDTABLEPROPERTIES == m_aStates.top().nDestinationState)
3547 : {
3548 6 : m_nNestedCells++;
3549 : // Push cell properties.
3550 : m_aNestedTableCellsSprms.push_back(
3551 6 : m_aStates.top().aTableCellSprms);
3552 : m_aNestedTableCellsAttributes.push_back(
3553 6 : m_aStates.top().aTableCellAttributes);
3554 : }
3555 : else
3556 : {
3557 338 : m_nTopLevelCells++;
3558 : // Push cell properties.
3559 : m_aTopLevelTableCellsSprms.push_back(
3560 338 : m_aStates.top().aTableCellSprms);
3561 : m_aTopLevelTableCellsAttributes.push_back(
3562 338 : m_aStates.top().aTableCellAttributes);
3563 : }
3564 :
3565 344 : m_aStates.top().aTableCellSprms = m_aDefaultState.aTableCellSprms;
3566 344 : m_aStates.top().aTableCellAttributes = m_aDefaultState.aTableCellAttributes;
3567 : // We assume text after a row definition always belongs to the table, to handle text before the real INTBL token
3568 344 : dispatchFlag(RTF_INTBL);
3569 688 : m_nCellxMax = std::max(m_nCellxMax, nParam);
3570 : }
3571 344 : break;
3572 : case RTF_TRRH:
3573 : {
3574 6 : OUString hRule("auto");
3575 6 : if ( nParam < 0 )
3576 : {
3577 0 : RTFValue::Pointer_t pAbsValue(new RTFValue(-nParam));
3578 0 : pIntValue.swap( pAbsValue );
3579 :
3580 0 : hRule = "exact";
3581 : }
3582 6 : else if ( nParam > 0 )
3583 6 : hRule = "atLeast";
3584 :
3585 6 : lcl_putNestedAttribute(m_aStates.top().aTableRowSprms,
3586 12 : NS_ooxml::LN_CT_TrPrBase_trHeight, NS_ooxml::LN_CT_Height_val, pIntValue);
3587 :
3588 12 : RTFValue::Pointer_t pHRule(new RTFValue(hRule));
3589 6 : lcl_putNestedAttribute(m_aStates.top().aTableRowSprms,
3590 18 : NS_ooxml::LN_CT_TrPrBase_trHeight, NS_ooxml::LN_CT_Height_hRule, pHRule);
3591 : }
3592 6 : break;
3593 : case RTF_TRLEFT:
3594 : {
3595 : // the value is in twips
3596 63 : lcl_putNestedAttribute(m_aStates.top().aTableRowSprms,
3597 : NS_ooxml::LN_CT_TblPrBase_tblInd, NS_ooxml::LN_CT_TblWidth_type,
3598 126 : RTFValue::Pointer_t(new RTFValue(NS_ooxml::LN_Value_ST_TblWidth_dxa)));
3599 63 : lcl_putNestedAttribute(m_aStates.top().aTableRowSprms,
3600 : NS_ooxml::LN_CT_TblPrBase_tblInd, NS_ooxml::LN_CT_TblWidth_w,
3601 126 : RTFValue::Pointer_t(new RTFValue(nParam)));
3602 : }
3603 63 : break;
3604 : case RTF_COLS:
3605 1 : lcl_putNestedAttribute(m_aStates.top().aSectionSprms,
3606 2 : NS_ooxml::LN_EG_SectPrContents_cols, NS_ooxml::LN_CT_Columns_num, pIntValue);
3607 1 : break;
3608 : case RTF_COLSX:
3609 10 : lcl_putNestedAttribute(m_aStates.top().aSectionSprms,
3610 20 : NS_ooxml::LN_EG_SectPrContents_cols, NS_ooxml::LN_CT_Columns_space, pIntValue);
3611 10 : break;
3612 : case RTF_COLNO:
3613 0 : lcl_putNestedSprm(m_aStates.top().aSectionSprms,
3614 0 : NS_ooxml::LN_EG_SectPrContents_cols, NS_ooxml::LN_CT_Columns_col, pIntValue);
3615 0 : break;
3616 : case RTF_COLW:
3617 : case RTF_COLSR:
3618 : {
3619 0 : RTFSprms& rAttributes = lcl_getLastAttributes(m_aStates.top().aSectionSprms, NS_ooxml::LN_EG_SectPrContents_cols);
3620 0 : rAttributes.set((nKeyword == RTF_COLW ? NS_ooxml::LN_CT_Column_w : NS_ooxml::LN_CT_Column_space), pIntValue);
3621 : }
3622 0 : break;
3623 : case RTF_PAPERH: // fall through: set the default + current value
3624 : lcl_putNestedAttribute(m_aDefaultState.aSectionSprms,
3625 101 : NS_ooxml::LN_EG_SectPrContents_pgSz, NS_ooxml::LN_CT_PageSz_h, pIntValue, OVERWRITE_YES);
3626 : case RTF_PGHSXN:
3627 169 : lcl_putNestedAttribute(m_aStates.top().aSectionSprms,
3628 338 : NS_ooxml::LN_EG_SectPrContents_pgSz, NS_ooxml::LN_CT_PageSz_h, pIntValue, OVERWRITE_YES);
3629 169 : break;
3630 : case RTF_PAPERW: // fall through: set the default + current value
3631 : lcl_putNestedAttribute(m_aDefaultState.aSectionSprms,
3632 101 : NS_ooxml::LN_EG_SectPrContents_pgSz, NS_ooxml::LN_CT_PageSz_w, pIntValue, OVERWRITE_YES);
3633 : case RTF_PGWSXN:
3634 169 : lcl_putNestedAttribute(m_aStates.top().aSectionSprms,
3635 338 : NS_ooxml::LN_EG_SectPrContents_pgSz, NS_ooxml::LN_CT_PageSz_w, pIntValue, OVERWRITE_YES);
3636 169 : break;
3637 : case RTF_MARGL: // fall through: set the default + current value
3638 : lcl_putNestedAttribute(m_aDefaultState.aSectionSprms,
3639 99 : NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_left, pIntValue, OVERWRITE_YES);
3640 : case RTF_MARGLSXN:
3641 171 : lcl_putNestedAttribute(m_aStates.top().aSectionSprms,
3642 342 : NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_left, pIntValue, OVERWRITE_YES);
3643 171 : break;
3644 : case RTF_MARGR: // fall through: set the default + current value
3645 : lcl_putNestedAttribute(m_aDefaultState.aSectionSprms,
3646 99 : NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_right, pIntValue, OVERWRITE_YES);
3647 : case RTF_MARGRSXN:
3648 171 : lcl_putNestedAttribute(m_aStates.top().aSectionSprms,
3649 342 : NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_right, pIntValue, OVERWRITE_YES);
3650 171 : break;
3651 : case RTF_MARGT: // fall through: set the default + current value
3652 : lcl_putNestedAttribute(m_aDefaultState.aSectionSprms,
3653 97 : NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_top, pIntValue, OVERWRITE_YES);
3654 : case RTF_MARGTSXN:
3655 168 : lcl_putNestedAttribute(m_aStates.top().aSectionSprms,
3656 336 : NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_top, pIntValue, OVERWRITE_YES);
3657 168 : break;
3658 : case RTF_MARGB: // fall through: set the default + current value
3659 : lcl_putNestedAttribute(m_aDefaultState.aSectionSprms,
3660 96 : NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_bottom, pIntValue, OVERWRITE_YES);
3661 : case RTF_MARGBSXN:
3662 167 : lcl_putNestedAttribute(m_aStates.top().aSectionSprms,
3663 334 : NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_bottom, pIntValue, OVERWRITE_YES);
3664 167 : break;
3665 : case RTF_HEADERY:
3666 14 : lcl_putNestedAttribute(m_aStates.top().aSectionSprms,
3667 28 : NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_header, pIntValue, OVERWRITE_YES);
3668 14 : break;
3669 : case RTF_FOOTERY:
3670 13 : lcl_putNestedAttribute(m_aStates.top().aSectionSprms,
3671 26 : NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_footer, pIntValue, OVERWRITE_YES);
3672 13 : break;
3673 : case RTF_DEFTAB:
3674 68 : m_aSettingsTableSprms.set(NS_ooxml::LN_CT_Settings_defaultTabStop, pIntValue);
3675 68 : break;
3676 : case RTF_LINEMOD:
3677 3 : lcl_putNestedAttribute(m_aStates.top().aSectionSprms,
3678 6 : NS_ooxml::LN_EG_SectPrContents_lnNumType, NS_ooxml::LN_CT_LineNumber_countBy, pIntValue);
3679 3 : break;
3680 : case RTF_LINEX:
3681 16 : if (nParam)
3682 3 : lcl_putNestedAttribute(m_aStates.top().aSectionSprms,
3683 6 : NS_ooxml::LN_EG_SectPrContents_lnNumType, NS_ooxml::LN_CT_LineNumber_distance, pIntValue);
3684 16 : break;
3685 : case RTF_LINESTARTS:
3686 0 : lcl_putNestedAttribute(m_aStates.top().aSectionSprms,
3687 0 : NS_ooxml::LN_EG_SectPrContents_lnNumType, NS_ooxml::LN_CT_LineNumber_start, pIntValue);
3688 0 : break;
3689 : case RTF_REVAUTH:
3690 : case RTF_REVAUTHDEL:
3691 : {
3692 0 : RTFValue::Pointer_t pValue(new RTFValue(m_aAuthors[nParam]));
3693 0 : lcl_putNestedAttribute(m_aStates.top().aCharacterSprms,
3694 0 : NS_ooxml::LN_trackchange, NS_ooxml::LN_CT_TrackChange_author, pValue);
3695 : }
3696 0 : break;
3697 : case RTF_REVDTTM:
3698 : case RTF_REVDTTMDEL:
3699 : {
3700 0 : OUString aStr(OStringToOUString(lcl_DTTM22OString(nParam), m_aStates.top().nCurrentEncoding));
3701 0 : RTFValue::Pointer_t pValue(new RTFValue(aStr));
3702 0 : lcl_putNestedAttribute(m_aStates.top().aCharacterSprms,
3703 0 : NS_ooxml::LN_trackchange, NS_ooxml::LN_CT_TrackChange_date, pValue);
3704 : }
3705 0 : break;
3706 : case RTF_SHPLEFT:
3707 64 : m_aStates.top().aShape.nLeft = TWIP_TO_MM100(nParam);
3708 64 : break;
3709 : case RTF_SHPTOP:
3710 64 : m_aStates.top().aShape.nTop = TWIP_TO_MM100(nParam);
3711 64 : break;
3712 : case RTF_SHPRIGHT:
3713 62 : m_aStates.top().aShape.nRight = TWIP_TO_MM100(nParam);
3714 62 : break;
3715 : case RTF_SHPBOTTOM:
3716 62 : m_aStates.top().aShape.nBottom = TWIP_TO_MM100(nParam);
3717 62 : break;
3718 : case RTF_SHPZ:
3719 43 : m_aStates.top().aShape.oZ.reset(nParam);
3720 43 : break;
3721 : case RTF_FFTYPE:
3722 0 : switch (nParam)
3723 : {
3724 0 : case 0: m_nFormFieldType = FORMFIELD_TEXT; break;
3725 0 : case 1: m_nFormFieldType = FORMFIELD_CHECKBOX; break;
3726 0 : case 2: m_nFormFieldType = FORMFIELD_LIST; break;
3727 0 : default: m_nFormFieldType = FORMFIELD_NONE; break;
3728 : }
3729 0 : break;
3730 : case RTF_FFDEFRES:
3731 0 : if (m_nFormFieldType == FORMFIELD_CHECKBOX)
3732 0 : m_aFormfieldSprms.set(NS_ooxml::LN_CT_FFCheckBox_default, pIntValue);
3733 0 : else if (m_nFormFieldType == FORMFIELD_LIST)
3734 0 : m_aFormfieldSprms.set(NS_ooxml::LN_CT_FFDDList_default, pIntValue);
3735 0 : break;
3736 : case RTF_FFRES:
3737 0 : if (m_nFormFieldType == FORMFIELD_CHECKBOX)
3738 0 : m_aFormfieldSprms.set(NS_ooxml::LN_CT_FFCheckBox_checked, pIntValue);
3739 0 : else if (m_nFormFieldType == FORMFIELD_LIST)
3740 0 : m_aFormfieldSprms.set(NS_ooxml::LN_CT_FFDDList_result, pIntValue);
3741 0 : break;
3742 : case RTF_EDMINS:
3743 3 : if (m_xDocumentProperties.is())
3744 1 : m_xDocumentProperties->setEditingDuration(nParam);
3745 3 : break;
3746 : case RTF_NOFPAGES:
3747 : case RTF_NOFWORDS:
3748 : case RTF_NOFCHARS:
3749 : case RTF_NOFCHARSWS:
3750 12 : if (m_xDocumentProperties.is())
3751 : {
3752 4 : uno::Sequence<beans::NamedValue> aSet = m_xDocumentProperties->getDocumentStatistics();
3753 8 : OUString aName;
3754 4 : switch (nKeyword)
3755 : {
3756 1 : case RTF_NOFPAGES: aName = "PageCount"; nParam = 99; break;
3757 1 : case RTF_NOFWORDS: aName = "WordCount"; break;
3758 1 : case RTF_NOFCHARS: aName = "CharacterCount"; break;
3759 1 : case RTF_NOFCHARSWS: aName = "NonWhitespaceCharacterCount"; break;
3760 0 : default: break;
3761 : }
3762 4 : if (!aName.isEmpty())
3763 : {
3764 4 : bool bFound = false;
3765 4 : int nLen = aSet.getLength();
3766 10 : for (int i = 0; i < nLen; ++i)
3767 6 : if (aSet[i].Name.equals(aName))
3768 0 : aSet[i].Value = uno::makeAny(sal_Int32(nParam));
3769 4 : if (!bFound)
3770 : {
3771 4 : aSet.realloc(nLen + 1);
3772 4 : aSet[nLen].Name = aName;
3773 4 : aSet[nLen].Value = uno::makeAny(sal_Int32(nParam));
3774 : }
3775 4 : m_xDocumentProperties->setDocumentStatistics(aSet);
3776 4 : }
3777 : }
3778 12 : break;
3779 : case RTF_VERSION:
3780 3 : if (m_xDocumentProperties.is())
3781 1 : m_xDocumentProperties->setEditingCycles(nParam);
3782 3 : break;
3783 : case RTF_VERN:
3784 : // Ignore this for now, later the RTF writer version could be used to add hacks for older buggy writers.
3785 61 : break;
3786 : case RTF_FTNSTART:
3787 : lcl_putNestedSprm(m_aDefaultState.aParagraphSprms,
3788 67 : NS_ooxml::LN_EG_SectPrContents_footnotePr, NS_ooxml::LN_EG_FtnEdnNumProps_numStart, pIntValue);
3789 67 : break;
3790 : case RTF_AFTNSTART:
3791 : lcl_putNestedSprm(m_aDefaultState.aParagraphSprms,
3792 65 : NS_ooxml::LN_EG_SectPrContents_endnotePr, NS_ooxml::LN_EG_FtnEdnNumProps_numStart, pIntValue);
3793 65 : break;
3794 : case RTF_DFRMTXTX:
3795 4 : m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_hSpace, nParam);
3796 4 : break;
3797 : case RTF_DFRMTXTY:
3798 4 : m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_vSpace, nParam);
3799 4 : break;
3800 : case RTF_DXFRTEXT:
3801 : {
3802 2 : m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_hSpace, nParam);
3803 2 : m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_vSpace, nParam);
3804 : }
3805 2 : break;
3806 : case RTF_FLYVERT:
3807 : {
3808 2 : RTFVertOrient aVertOrient(nParam);
3809 2 : m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_yAlign, aVertOrient.GetAlign());
3810 2 : m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_vAnchor, aVertOrient.GetAnchor());
3811 : }
3812 2 : break;
3813 : case RTF_FLYHORZ:
3814 : {
3815 2 : RTFHoriOrient aHoriOrient(nParam);
3816 2 : m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_xAlign, aHoriOrient.GetAlign());
3817 2 : m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_hAnchor, aHoriOrient.GetAnchor());
3818 : }
3819 2 : break;
3820 : case RTF_FLYANCHOR:
3821 2 : m_aStates.top().aFrame.nAnchorType = nParam;
3822 2 : break;
3823 : case RTF_WMETAFILE:
3824 2 : m_aStates.top().aPicture.eWMetafile = nParam;
3825 2 : break;
3826 : case RTF_SB:
3827 371 : lcl_putNestedAttribute(m_aStates.top().aParagraphSprms,
3828 742 : NS_ooxml::LN_CT_PPrBase_spacing, NS_ooxml::LN_CT_Spacing_before, pIntValue, OVERWRITE_YES);
3829 371 : break;
3830 : case RTF_SA:
3831 391 : lcl_putNestedAttribute(m_aStates.top().aParagraphSprms,
3832 782 : NS_ooxml::LN_CT_PPrBase_spacing, NS_ooxml::LN_CT_Spacing_after, pIntValue, OVERWRITE_YES);
3833 391 : break;
3834 : case RTF_DPX:
3835 24 : m_aStates.top().aDrawingObject.nLeft = TWIP_TO_MM100(nParam);
3836 24 : break;
3837 : case RTF_DPY:
3838 24 : m_aStates.top().aDrawingObject.nTop = TWIP_TO_MM100(nParam);
3839 24 : break;
3840 : case RTF_DPXSIZE:
3841 24 : m_aStates.top().aDrawingObject.nRight = TWIP_TO_MM100(nParam);
3842 24 : break;
3843 : case RTF_DPYSIZE:
3844 24 : m_aStates.top().aDrawingObject.nBottom = TWIP_TO_MM100(nParam);
3845 24 : break;
3846 : case RTF_PNSTART:
3847 4 : m_aStates.top().aTableSprms.set(NS_ooxml::LN_CT_Lvl_start, pIntValue);
3848 4 : break;
3849 : case RTF_PNF:
3850 : {
3851 1 : RTFValue::Pointer_t pValue(new RTFValue(m_aFontNames[getFontIndex(nParam)]));
3852 2 : RTFSprms aAttributes;
3853 1 : aAttributes.set(NS_ooxml::LN_CT_Fonts_ascii, pValue);
3854 2 : lcl_putNestedSprm(m_aStates.top().aTableSprms, NS_ooxml::LN_CT_Lvl_rPr, NS_ooxml::LN_EG_RPrBase_rFonts, RTFValue::Pointer_t(new RTFValue(aAttributes)));
3855 : }
3856 1 : break;
3857 : case RTF_VIEWSCALE:
3858 73 : m_aSettingsTableAttributes.set(NS_ooxml::LN_CT_Zoom_percent, pIntValue);
3859 73 : break;
3860 : case RTF_BIN:
3861 : {
3862 2 : m_aStates.top().nInternalState = INTERNAL_BIN;
3863 2 : m_aStates.top().nBinaryToRead = nParam;
3864 : }
3865 2 : break;
3866 : case RTF_DPLINECOR:
3867 9 : m_aStates.top().aDrawingObject.nLineColorR = nParam; m_aStates.top().aDrawingObject.bHasLineColor = true;
3868 9 : break;
3869 : case RTF_DPLINECOG:
3870 9 : m_aStates.top().aDrawingObject.nLineColorG = nParam; m_aStates.top().aDrawingObject.bHasLineColor = true;
3871 9 : break;
3872 : case RTF_DPLINECOB:
3873 9 : m_aStates.top().aDrawingObject.nLineColorB = nParam; m_aStates.top().aDrawingObject.bHasLineColor = true;
3874 9 : break;
3875 : case RTF_DPFILLBGCR:
3876 5 : m_aStates.top().aDrawingObject.nFillColorR = nParam; m_aStates.top().aDrawingObject.bHasFillColor = true;
3877 5 : break;
3878 : case RTF_DPFILLBGCG:
3879 5 : m_aStates.top().aDrawingObject.nFillColorG = nParam; m_aStates.top().aDrawingObject.bHasFillColor = true;
3880 5 : break;
3881 : case RTF_DPFILLBGCB:
3882 5 : m_aStates.top().aDrawingObject.nFillColorB = nParam; m_aStates.top().aDrawingObject.bHasFillColor = true;
3883 5 : break;
3884 : case RTF_CLSHDNG:
3885 : {
3886 2 : int nValue = -1;
3887 2 : switch (nParam)
3888 : {
3889 0 : case 500: nValue = 2; break;
3890 0 : case 1000: nValue = 3; break;
3891 0 : case 1200: nValue = 37; break;
3892 2 : case 1500: nValue = 38; break;
3893 0 : case 2000: nValue = 4; break;
3894 0 : case 2500: nValue = 5; break;
3895 0 : case 3000: nValue = 6; break;
3896 0 : case 3500: nValue = 43; break;
3897 0 : case 3700: nValue = 44; break;
3898 0 : case 4000: nValue = 7; break;
3899 0 : case 4500: nValue = 46; break;
3900 0 : case 5000: nValue = 8; break;
3901 0 : case 5500: nValue = 49; break;
3902 0 : case 6000: nValue = 9; break;
3903 0 : case 6200: nValue = 51; break;
3904 0 : case 6500: nValue = 52; break;
3905 0 : case 7000: nValue = 10; break;
3906 0 : case 7500: nValue = 11; break;
3907 0 : case 8000: nValue = 12; break;
3908 0 : case 8500: nValue = 57; break;
3909 0 : case 8700: nValue = 58; break;
3910 0 : case 9000: nValue = 13; break;
3911 0 : case 9500: nValue = 60; break;
3912 0 : default: break;
3913 : }
3914 2 : if (nValue != -1)
3915 2 : lcl_putNestedAttribute(m_aStates.top().aTableCellSprms,
3916 4 : NS_ooxml::LN_CT_TcPrBase_shd, NS_ooxml::LN_CT_Shd_val, RTFValue::Pointer_t(new RTFValue(nValue)));
3917 : }
3918 2 : break;
3919 : case RTF_DODHGT:
3920 16 : m_aStates.top().aDrawingObject.nDhgt = nParam;
3921 16 : break;
3922 : case RTF_DPPOLYCOUNT:
3923 7 : if (nParam >= 0)
3924 : {
3925 7 : m_aStates.top().aDrawingObject.nPolyLineCount = nParam;
3926 7 : m_aStates.top().aDrawingObject.aPolyLinePoints.realloc(nParam);
3927 : }
3928 7 : break;
3929 : case RTF_DPPTX:
3930 : {
3931 14 : RTFDrawingObject& rDrawingObject = m_aStates.top().aDrawingObject;
3932 :
3933 14 : if (!rDrawingObject.aPolyLinePoints.hasElements())
3934 3 : dispatchValue(RTF_DPPOLYCOUNT, 2);
3935 :
3936 14 : rDrawingObject.aPolyLinePoints[rDrawingObject.aPolyLinePoints.getLength() - rDrawingObject.nPolyLineCount].X = TWIP_TO_MM100(nParam);
3937 : }
3938 14 : break;
3939 : case RTF_DPPTY:
3940 : {
3941 14 : RTFDrawingObject& rDrawingObject = m_aStates.top().aDrawingObject;
3942 14 : if (rDrawingObject.aPolyLinePoints.hasElements())
3943 : {
3944 14 : rDrawingObject.aPolyLinePoints[rDrawingObject.aPolyLinePoints.getLength() - rDrawingObject.nPolyLineCount].Y = TWIP_TO_MM100(nParam);
3945 14 : rDrawingObject.nPolyLineCount--;
3946 14 : if (rDrawingObject.nPolyLineCount == 0)
3947 : {
3948 7 : uno::Sequence< uno::Sequence<awt::Point> >aPointSequenceSequence(1);
3949 7 : aPointSequenceSequence[0] = rDrawingObject.aPolyLinePoints;
3950 7 : rDrawingObject.xPropertySet->setPropertyValue("PolyPolygon", uno::Any(aPointSequenceSequence));
3951 : }
3952 : }
3953 : }
3954 14 : break;
3955 : case RTF_SHPFBLWTXT:
3956 42 : if (nParam == 1)
3957 : {
3958 : // Shape is below text -> send it to the background.
3959 14 : m_aStates.top().aCharacterAttributes.erase(NS_ooxml::LN_CT_WrapSquare_wrapText);
3960 14 : m_aStates.top().aCharacterSprms.set(NS_ooxml::LN_EG_WrapType_wrapNone, RTFValue::Pointer_t(new RTFValue()));
3961 : }
3962 42 : break;
3963 : case RTF_CLPADB:
3964 : case RTF_CLPADL:
3965 : case RTF_CLPADR:
3966 : case RTF_CLPADT:
3967 : {
3968 12 : RTFSprms aAttributes;
3969 12 : aAttributes.set(NS_ooxml::LN_CT_TblWidth_type, RTFValue::Pointer_t(new RTFValue(NS_ooxml::LN_Value_ST_TblWidth_dxa)));
3970 12 : aAttributes.set(NS_ooxml::LN_CT_TblWidth_w, RTFValue::Pointer_t(new RTFValue(nParam)));
3971 12 : switch (nKeyword)
3972 : {
3973 : case RTF_CLPADB:
3974 3 : nSprm = NS_ooxml::LN_CT_TcMar_bottom;
3975 3 : break;
3976 : case RTF_CLPADL:
3977 3 : nSprm = NS_ooxml::LN_CT_TcMar_left;
3978 3 : break;
3979 : case RTF_CLPADR:
3980 3 : nSprm = NS_ooxml::LN_CT_TcMar_right;
3981 3 : break;
3982 : case RTF_CLPADT:
3983 3 : nSprm = NS_ooxml::LN_CT_TcMar_top;
3984 3 : break;
3985 : default:
3986 0 : break;
3987 : }
3988 12 : lcl_putNestedSprm(m_aStates.top().aTableCellSprms, NS_ooxml::LN_CT_TcPrBase_tcMar, nSprm, RTFValue::Pointer_t(new RTFValue(aAttributes)));
3989 : }
3990 12 : break;
3991 : case RTF_FI:
3992 208 : lcl_putNestedAttribute(m_aStates.top().aParagraphSprms, NS_ooxml::LN_CT_PPrBase_ind, NS_ooxml::LN_CT_Ind_firstLine, pIntValue);
3993 208 : break;
3994 : case RTF_LI:
3995 : {
3996 314 : lcl_putNestedAttribute(m_aStates.top().aParagraphSprms, NS_ooxml::LN_CT_PPrBase_ind, NS_ooxml::LN_CT_Ind_left, pIntValue);
3997 : // It turns out \li should reset the \fi inherited from the stylesheet.
3998 : // So set the direct formatting to zero, if we don't have such direct formatting yet.
3999 628 : lcl_putNestedAttribute(m_aStates.top().aParagraphSprms, NS_ooxml::LN_CT_PPrBase_ind, NS_ooxml::LN_CT_Ind_firstLine, RTFValue::Pointer_t(new RTFValue(0)),
4000 942 : OVERWRITE_NO_IGNORE, /*bAttribute=*/true);
4001 : }
4002 314 : break;
4003 : case RTF_RI:
4004 204 : lcl_putNestedAttribute(m_aStates.top().aParagraphSprms, NS_ooxml::LN_CT_PPrBase_ind, NS_ooxml::LN_CT_Ind_right, pIntValue);
4005 204 : break;
4006 : case RTF_LIN:
4007 200 : lcl_putNestedAttribute(m_aStates.top().aParagraphSprms, NS_ooxml::LN_CT_PPrBase_ind, NS_ooxml::LN_CT_Ind_start, pIntValue);
4008 200 : break;
4009 : case RTF_RIN:
4010 188 : lcl_putNestedAttribute(m_aStates.top().aParagraphSprms, NS_ooxml::LN_CT_PPrBase_ind, NS_ooxml::LN_CT_Ind_end, pIntValue);
4011 188 : break;
4012 : default:
4013 : {
4014 : SAL_INFO("writerfilter", "TODO handle value '" << lcl_RtfToString(nKeyword) << "'");
4015 5423 : aSkip.setParsed(false);
4016 : }
4017 5423 : break;
4018 : }
4019 47168 : return 0;
4020 : }
4021 :
4022 964 : int RTFDocumentImpl::dispatchToggle(RTFKeyword nKeyword, bool bParam, int nParam)
4023 : {
4024 964 : setNeedSect();
4025 964 : checkUnicode(/*bUnicode =*/ true, /*bHex =*/ true);
4026 964 : RTFSkipDestination aSkip(*this);
4027 964 : int nSprm = -1;
4028 1928 : RTFValue::Pointer_t pBoolValue(new RTFValue(int(!bParam || nParam != 0)));
4029 :
4030 : // Map all underline toggles to a single sprm.
4031 964 : switch (nKeyword)
4032 : {
4033 20 : case RTF_UL: nSprm = 1; break;
4034 0 : case RTF_ULDASH: nSprm = 7; break;
4035 0 : case RTF_ULDASHD: nSprm = 9; break;
4036 0 : case RTF_ULDASHDD: nSprm = 10; break;
4037 0 : case RTF_ULDB: nSprm = 3; break;
4038 0 : case RTF_ULHWAVE: nSprm = 27; break;
4039 0 : case RTF_ULLDASH: nSprm = 39; break;
4040 0 : case RTF_ULTH: nSprm = 6; break;
4041 0 : case RTF_ULTHD: nSprm = 20; break;
4042 0 : case RTF_ULTHDASH: nSprm = 23; break;
4043 0 : case RTF_ULTHDASHD: nSprm = 25; break;
4044 0 : case RTF_ULTHDASHDD: nSprm = 26; break;
4045 0 : case RTF_ULTHLDASH: nSprm = 55; break;
4046 0 : case RTF_ULULDBWAVE: nSprm = 43; break;
4047 0 : case RTF_ULWAVE: nSprm = 11; break;
4048 944 : default: break;
4049 : }
4050 964 : if (nSprm >= 0)
4051 : {
4052 20 : RTFValue::Pointer_t pValue(new RTFValue((!bParam || nParam != 0) ? nSprm : 0));
4053 20 : m_aStates.top().aCharacterAttributes.set(NS_ooxml::LN_CT_Underline_val, pValue);
4054 20 : return 0;
4055 : }
4056 :
4057 : // Accent characters (over dot / over coma).
4058 944 : switch (nKeyword)
4059 : {
4060 9 : case RTF_ACCNONE: nSprm = 0; break;
4061 0 : case RTF_ACCDOT: nSprm = 1; break;
4062 0 : case RTF_ACCCOMMA: nSprm = 2; break;
4063 0 : case RTF_ACCCIRCLE: nSprm = 3; break;
4064 0 : case RTF_ACCUNDERDOT: nSprm = 4; break;
4065 935 : default: break;
4066 : }
4067 944 : if (nSprm >= 0)
4068 : {
4069 9 : RTFValue::Pointer_t pValue(new RTFValue((!bParam || nParam != 0) ? nSprm : 0));
4070 9 : m_aStates.top().aCharacterSprms.set(NS_ooxml::LN_EG_RPrBase_em, pValue);
4071 9 : return 0;
4072 : }
4073 :
4074 : // Trivial character sprms.
4075 935 : switch (nKeyword)
4076 : {
4077 136 : case RTF_B: nSprm = NS_ooxml::LN_EG_RPrBase_b; break;
4078 22 : case RTF_AB: nSprm = NS_ooxml::LN_EG_RPrBase_bCs; break;
4079 414 : case RTF_I: nSprm = NS_ooxml::LN_EG_RPrBase_i; break;
4080 66 : case RTF_AI: nSprm = NS_ooxml::LN_EG_RPrBase_iCs; break;
4081 9 : case RTF_OUTL: nSprm = NS_ooxml::LN_EG_RPrBase_outline; break;
4082 9 : case RTF_SHAD: nSprm = NS_ooxml::LN_EG_RPrBase_shadow; break;
4083 0 : case RTF_V: nSprm = NS_ooxml::LN_EG_RPrBase_vanish; break;
4084 17 : case RTF_STRIKE: nSprm = NS_ooxml::LN_EG_RPrBase_strike; break;
4085 0 : case RTF_STRIKED: nSprm = NS_ooxml::LN_EG_RPrBase_dstrike; break;
4086 6 : case RTF_SCAPS: nSprm = NS_ooxml::LN_EG_RPrBase_smallCaps; break;
4087 0 : case RTF_IMPR: nSprm = NS_ooxml::LN_EG_RPrBase_imprint; break;
4088 1 : case RTF_CAPS: nSprm = NS_ooxml::LN_EG_RPrBase_caps; break;
4089 255 : default: break;
4090 : }
4091 935 : if (nSprm >= 0)
4092 : {
4093 680 : m_aStates.top().aCharacterSprms.set(nSprm, pBoolValue);
4094 680 : return 0;
4095 : }
4096 :
4097 255 : switch (nKeyword)
4098 : {
4099 : case RTF_ASPALPHA:
4100 146 : m_aStates.top().aParagraphSprms.set(NS_ooxml::LN_CT_PPrBase_autoSpaceDE, pBoolValue);
4101 146 : break;
4102 : case RTF_DELETED:
4103 : case RTF_REVISED:
4104 : {
4105 0 : RTFValue::Pointer_t pValue(new RTFValue(nKeyword == RTF_DELETED ? OOXML_del : OOXML_ins));
4106 0 : lcl_putNestedAttribute(m_aStates.top().aCharacterSprms,
4107 0 : NS_ooxml::LN_trackchange, NS_ooxml::LN_token, pValue);
4108 : }
4109 0 : break;
4110 : default:
4111 : {
4112 : SAL_INFO("writerfilter", "TODO handle toggle '" << lcl_RtfToString(nKeyword) << "'");
4113 109 : aSkip.setParsed(false);
4114 : }
4115 109 : break;
4116 : }
4117 1219 : return 0;
4118 : }
4119 :
4120 9455 : int RTFDocumentImpl::pushState()
4121 : {
4122 : //SAL_INFO("writerfilter", OSL_THIS_FUNC << " before push: " << m_pTokenizer->getGroup());
4123 :
4124 9455 : checkUnicode(/*bUnicode =*/ true, /*bHex =*/ true);
4125 9455 : m_nGroupStartPos = Strm().Tell();
4126 :
4127 9455 : if (m_aStates.empty())
4128 312 : m_aStates.push(m_aDefaultState);
4129 : else
4130 : {
4131 9143 : if (m_aStates.top().nDestinationState == DESTINATION_MR)
4132 299 : lcl_DestinationToMath(m_aStates.top().aDestinationText, m_aMathBuffer, m_bMathNor);
4133 9143 : m_aStates.push(m_aStates.top());
4134 : }
4135 9455 : m_aStates.top().aDestinationText.setLength(0);
4136 :
4137 9455 : m_pTokenizer->pushGroup();
4138 :
4139 9455 : switch (m_aStates.top().nDestinationState)
4140 : {
4141 : case DESTINATION_FONTTABLE:
4142 804 : m_aStates.top().nDestinationState = DESTINATION_FONTENTRY;
4143 804 : break;
4144 : case DESTINATION_STYLESHEET:
4145 539 : m_aStates.top().nDestinationState = DESTINATION_STYLEENTRY;
4146 539 : break;
4147 : case DESTINATION_FIELDRESULT:
4148 : case DESTINATION_SHAPETEXT:
4149 : case DESTINATION_FORMFIELD:
4150 : case DESTINATION_FIELDINSTRUCTION:
4151 : case DESTINATION_PICT:
4152 57 : m_aStates.top().nDestinationState = DESTINATION_NORMAL;
4153 57 : break;
4154 : case DESTINATION_MNUM:
4155 : case DESTINATION_MDEN:
4156 : case DESTINATION_ME:
4157 : case DESTINATION_MFNAME:
4158 : case DESTINATION_MLIM:
4159 : case DESTINATION_MSUB:
4160 : case DESTINATION_MSUP:
4161 : case DESTINATION_MDEG:
4162 : case DESTINATION_MOMATH:
4163 1272 : m_aStates.top().nDestinationState = DESTINATION_MR;
4164 1272 : break;
4165 : case DESTINATION_REVISIONTABLE:
4166 1 : m_aStates.top().nDestinationState = DESTINATION_REVISIONENTRY;
4167 1 : break;
4168 : default:
4169 6782 : break;
4170 : }
4171 :
4172 9455 : return 0;
4173 : }
4174 :
4175 521 : RTFSprms RTFDocumentImpl::mergeSprms()
4176 : {
4177 521 : RTFSprms aSprms;
4178 3126 : for (RTFSprms::Iterator_t i = m_aStates.top().aTableSprms.begin();
4179 2084 : i != m_aStates.top().aTableSprms.end(); ++i)
4180 521 : aSprms.set(i->first, i->second);
4181 6543 : for (RTFSprms::Iterator_t i = m_aStates.top().aCharacterSprms.begin();
4182 4362 : i != m_aStates.top().aCharacterSprms.end(); ++i)
4183 1660 : aSprms.set(i->first, i->second);
4184 4938 : for (RTFSprms::Iterator_t i = m_aStates.top().aParagraphSprms.begin();
4185 3292 : i != m_aStates.top().aParagraphSprms.end(); ++i)
4186 1125 : aSprms.set(i->first, i->second);
4187 521 : return aSprms;
4188 : }
4189 :
4190 1347 : void RTFDocumentImpl::resetSprms()
4191 : {
4192 1347 : m_aStates.top().aTableSprms.clear();
4193 1347 : m_aStates.top().aCharacterSprms.clear();
4194 1347 : m_aStates.top().aParagraphSprms.clear();
4195 1347 : }
4196 :
4197 521 : RTFSprms RTFDocumentImpl::mergeAttributes()
4198 : {
4199 521 : RTFSprms aAttributes;
4200 4689 : for (RTFSprms::Iterator_t i = m_aStates.top().aTableAttributes.begin();
4201 3126 : i != m_aStates.top().aTableAttributes.end(); ++i)
4202 1042 : aAttributes.set(i->first, i->second);
4203 1602 : for (RTFSprms::Iterator_t i = m_aStates.top().aCharacterAttributes.begin();
4204 1068 : i != m_aStates.top().aCharacterAttributes.end(); ++i)
4205 13 : aAttributes.set(i->first, i->second);
4206 2199 : for (RTFSprms::Iterator_t i = m_aStates.top().aParagraphAttributes.begin();
4207 1466 : i != m_aStates.top().aParagraphAttributes.end(); ++i)
4208 212 : aAttributes.set(i->first, i->second);
4209 521 : return aAttributes;
4210 : }
4211 :
4212 1347 : void RTFDocumentImpl::resetAttributes()
4213 : {
4214 1347 : m_aStates.top().aTableAttributes.clear();
4215 1347 : m_aStates.top().aCharacterAttributes.clear();
4216 1347 : m_aStates.top().aParagraphAttributes.clear();
4217 1347 : }
4218 :
4219 9452 : int RTFDocumentImpl::popState()
4220 : {
4221 : //SAL_INFO("writerfilter", OSL_THIS_FUNC << " before pop: m_pTokenizer->getGroup() " << m_pTokenizer->getGroup() <<
4222 : // ", dest state: " << m_aStates.top().nDestinationState);
4223 :
4224 9452 : checkUnicode(/*bUnicode =*/ true, /*bHex =*/ true);
4225 9452 : RTFParserState aState(m_aStates.top());
4226 9452 : m_bWasInFrame = aState.aFrame.inFrame();
4227 :
4228 9452 : switch (aState.nDestinationState)
4229 : {
4230 : case DESTINATION_FONTTABLE:
4231 : {
4232 99 : writerfilter::Reference<Table>::Pointer_t const pTable(new RTFReferenceTable(m_aFontTableEntries));
4233 99 : Mapper().table(NS_ooxml::LN_FONTTABLE, pTable);
4234 99 : if (m_nDefaultFontIndex >= 0)
4235 : {
4236 84 : RTFValue::Pointer_t pValue(new RTFValue(m_aFontNames[getFontIndex(m_nDefaultFontIndex)]));
4237 84 : lcl_putNestedAttribute(m_aDefaultState.aCharacterSprms, NS_ooxml::LN_EG_RPrBase_rFonts, NS_ooxml::LN_CT_Fonts_ascii, pValue);
4238 99 : }
4239 : }
4240 99 : break;
4241 : case DESTINATION_STYLESHEET:
4242 : {
4243 81 : writerfilter::Reference<Table>::Pointer_t const pTable(new RTFReferenceTable(m_aStyleTableEntries));
4244 81 : Mapper().table(NS_ooxml::LN_STYLESHEET, pTable);
4245 : }
4246 81 : break;
4247 : case DESTINATION_LISTOVERRIDETABLE:
4248 : {
4249 15 : RTFSprms aListTableAttributes;
4250 30 : writerfilter::Reference<Properties>::Pointer_t const pProp(new RTFReferenceProperties(aListTableAttributes, m_aListTableSprms));
4251 30 : RTFReferenceTable::Entries_t aListTableEntries;
4252 15 : aListTableEntries.insert(make_pair(0, pProp));
4253 30 : writerfilter::Reference<Table>::Pointer_t const pTable(new RTFReferenceTable(aListTableEntries));
4254 30 : Mapper().table(NS_ooxml::LN_NUMBERING, pTable);
4255 : }
4256 15 : break;
4257 : case DESTINATION_LISTENTRY:
4258 75 : for (RTFSprms::Iterator_t i = aState.aListLevelEntries.begin(); i != aState.aListLevelEntries.end(); ++i)
4259 55 : aState.aTableSprms.set(i->first, i->second, OVERWRITE_NO_APPEND);
4260 20 : break;
4261 : case DESTINATION_FIELDINSTRUCTION:
4262 : {
4263 12 : RTFValue::Pointer_t pValue(new RTFValue(m_aFormfieldAttributes, m_aFormfieldSprms));
4264 24 : RTFSprms aFFAttributes;
4265 24 : RTFSprms aFFSprms;
4266 12 : aFFSprms.set(NS_ooxml::LN_ffdata, pValue);
4267 24 : writerfilter::Reference<Properties>::Pointer_t const pProperties(new RTFReferenceProperties(aFFAttributes, aFFSprms));
4268 12 : Mapper().props(pProperties);
4269 12 : m_aFormfieldAttributes.clear();
4270 12 : m_aFormfieldSprms.clear();
4271 24 : singleChar(0x14);
4272 : }
4273 12 : break;
4274 : case DESTINATION_FIELDRESULT:
4275 10 : singleChar(0x15);
4276 10 : break;
4277 : case DESTINATION_LEVELTEXT:
4278 : {
4279 57 : OUString aStr = m_aStates.top().aDestinationText.makeStringAndClear();
4280 :
4281 : // The first character is the length of the string (the rest should be ignored).
4282 57 : sal_Int32 nLength(aStr.toChar());
4283 114 : OUString aValue;
4284 57 : if (nLength <= aStr.getLength())
4285 57 : aValue = aStr.copy(1, nLength);
4286 : else
4287 0 : aValue = aStr;
4288 114 : RTFValue::Pointer_t pValue(new RTFValue(aValue, true));
4289 114 : aState.aTableAttributes.set(NS_ooxml::LN_CT_LevelText_val, pValue);
4290 : }
4291 57 : break;
4292 : case DESTINATION_LEVELNUMBERS:
4293 58 : if (aState.aTableSprms.find(NS_ooxml::LN_CT_Lvl_lvlText))
4294 : {
4295 57 : RTFSprms& rAttributes = aState.aTableSprms.find(NS_ooxml::LN_CT_Lvl_lvlText)->getAttributes();
4296 57 : RTFValue::Pointer_t pValue = rAttributes.find(NS_ooxml::LN_CT_LevelText_val);
4297 114 : OUString aOrig = pValue->getString();
4298 :
4299 114 : OUStringBuffer aBuf;
4300 57 : sal_Int32 nReplaces = 1;
4301 139 : for (int i = 0; i < aOrig.getLength(); i++)
4302 : {
4303 328 : if (std::find(aState.aLevelNumbers.begin(), aState.aLevelNumbers.end(), i+1)
4304 328 : != aState.aLevelNumbers.end())
4305 : {
4306 38 : aBuf.append('%');
4307 : // '1.1.1' -> '%1.%2.%3', but '1.' (with '2.' prefix omitted) is %2.
4308 38 : aBuf.append(sal_Int32(nReplaces++ + aState.nListLevelNum + 1 - aState.aLevelNumbers.size()));
4309 : }
4310 : else
4311 44 : aBuf.append(aOrig.copy(i, 1));
4312 : }
4313 :
4314 114 : pValue->setString(aBuf.makeStringAndClear());
4315 : }
4316 58 : break;
4317 : case DESTINATION_SHAPEPROPERTYNAME:
4318 595 : aState.aShape.aProperties.push_back(make_pair(m_aStates.top().aDestinationText.makeStringAndClear(), OUString()));
4319 595 : break;
4320 : case DESTINATION_SHAPEPROPERTYVALUE:
4321 595 : if (aState.aShape.aProperties.size())
4322 : {
4323 594 : aState.aShape.aProperties.back().second = m_aStates.top().aDestinationText.makeStringAndClear();
4324 594 : if (m_aStates.top().bHadShapeText)
4325 10 : m_pSdrImport->append(aState.aShape.aProperties.back().first, aState.aShape.aProperties.back().second);
4326 584 : else if (aState.bInShapeGroup && !aState.bInShape && aState.aShape.aProperties.back().first == "rotation")
4327 : {
4328 : // Rotation should be applied on the groupshape itself, not on each shape.
4329 2 : aState.aShape.aGroupProperties.push_back(aState.aShape.aProperties.back());
4330 2 : aState.aShape.aProperties.pop_back();
4331 : }
4332 : }
4333 595 : break;
4334 : case DESTINATION_PICPROP:
4335 : case DESTINATION_SHAPEINSTRUCTION:
4336 : // Don't trigger a shape import in case we're only leaving the \shpinst of the groupshape itself.
4337 76 : if (!m_bObject && !aState.bInListpicture && !aState.bHadShapeText && !(aState.bInShapeGroup && !aState.bInShape))
4338 37 : m_pSdrImport->resolve(m_aStates.top().aShape, true);
4339 39 : else if (aState.bInShapeGroup && !aState.bInShape)
4340 : {
4341 : // End of a groupshape, as we're in shapegroup, but not in a real shape.
4342 7 : for (std::vector< std::pair<OUString, OUString> >::iterator i = aState.aShape.aGroupProperties.begin(); i != aState.aShape.aGroupProperties.end(); ++i)
4343 2 : m_pSdrImport->appendGroupProperty(i->first, i->second);
4344 5 : aState.aShape.aGroupProperties.clear();
4345 : }
4346 76 : break;
4347 : case DESTINATION_BOOKMARKSTART:
4348 : {
4349 3 : OUString aStr = m_aStates.top().aDestinationText.makeStringAndClear();
4350 3 : int nPos = m_aBookmarks.size();
4351 3 : m_aBookmarks[aStr] = nPos;
4352 3 : Mapper().props(lcl_getBookmarkProperties(nPos, aStr));
4353 : }
4354 3 : break;
4355 : case DESTINATION_BOOKMARKEND:
4356 3 : Mapper().props(lcl_getBookmarkProperties(m_aBookmarks[m_aStates.top().aDestinationText.makeStringAndClear()]));
4357 3 : break;
4358 : case DESTINATION_PICT:
4359 13 : resolvePict(true);
4360 13 : break;
4361 : case DESTINATION_FORMFIELDNAME:
4362 : {
4363 0 : RTFValue::Pointer_t pValue(new RTFValue(m_aStates.top().aDestinationText.makeStringAndClear()));
4364 0 : m_aFormfieldSprms.set(NS_ooxml::LN_CT_FFData_name, pValue);
4365 : }
4366 0 : break;
4367 : case DESTINATION_FORMFIELDLIST:
4368 : {
4369 0 : RTFValue::Pointer_t pValue(new RTFValue(m_aStates.top().aDestinationText.makeStringAndClear()));
4370 0 : m_aFormfieldSprms.set(NS_ooxml::LN_CT_FFDDList_listEntry, pValue);
4371 : }
4372 0 : break;
4373 : case DESTINATION_DATAFIELD:
4374 : {
4375 0 : OString aStr = OUStringToOString(m_aStates.top().aDestinationText.makeStringAndClear(), aState.nCurrentEncoding);
4376 : // decode hex dump
4377 0 : OStringBuffer aBuf;
4378 0 : const char *str = aStr.getStr();
4379 0 : int b = 0, count = 2;
4380 0 : for (int i = 0; i < aStr.getLength(); ++i)
4381 : {
4382 0 : char ch = str[i];
4383 0 : if (ch != 0x0d && ch != 0x0a)
4384 : {
4385 0 : b = b << 4;
4386 0 : sal_Int8 parsed = m_pTokenizer->asHex(ch);
4387 0 : if (parsed == -1)
4388 0 : return ERROR_HEX_INVALID;
4389 0 : b += parsed;
4390 0 : count--;
4391 0 : if (!count)
4392 : {
4393 0 : aBuf.append((char)b);
4394 0 : count = 2;
4395 0 : b = 0;
4396 : }
4397 : }
4398 : }
4399 0 : aStr = aBuf.makeStringAndClear();
4400 :
4401 : // ignore the first bytes
4402 0 : if (aStr.getLength() > 8)
4403 0 : aStr = aStr.copy(8);
4404 : // extract name
4405 0 : sal_Int32 nLength = aStr.toChar();
4406 0 : if (!aStr.isEmpty())
4407 0 : aStr = aStr.copy(1);
4408 0 : nLength = std::min(nLength, aStr.getLength());
4409 0 : OString aName = aStr.copy(0, nLength);
4410 0 : if (aStr.getLength() > nLength)
4411 0 : aStr = aStr.copy(nLength+1); // zero-terminated string
4412 : else
4413 0 : aStr = OString();
4414 : // extract default text
4415 0 : nLength = aStr.toChar();
4416 0 : if (!aStr.isEmpty())
4417 0 : aStr = aStr.copy(1);
4418 0 : RTFValue::Pointer_t pNValue(new RTFValue(OStringToOUString(aName, aState.nCurrentEncoding)));
4419 0 : m_aFormfieldSprms.set(NS_ooxml::LN_CT_FFData_name, pNValue);
4420 0 : if (nLength > 0)
4421 : {
4422 0 : OString aDefaultText = aStr.copy(0, std::min(nLength, aStr.getLength()));
4423 0 : RTFValue::Pointer_t pDValue(new RTFValue(OStringToOUString(aDefaultText, aState.nCurrentEncoding)));
4424 0 : m_aFormfieldSprms.set(NS_ooxml::LN_CT_FFTextInput_default, pDValue);
4425 : }
4426 :
4427 0 : m_bFormField = false;
4428 : }
4429 0 : break;
4430 : case DESTINATION_CREATIONTIME:
4431 58 : if (m_xDocumentProperties.is())
4432 56 : m_xDocumentProperties->setCreationDate(lcl_getDateTime(aState));
4433 58 : break;
4434 : case DESTINATION_REVISIONTIME:
4435 58 : if (m_xDocumentProperties.is())
4436 56 : m_xDocumentProperties->setModificationDate(lcl_getDateTime(aState));
4437 58 : break;
4438 : case DESTINATION_PRINTTIME:
4439 56 : if (m_xDocumentProperties.is())
4440 55 : m_xDocumentProperties->setPrintDate(lcl_getDateTime(aState));
4441 56 : break;
4442 : case DESTINATION_AUTHOR:
4443 14 : if (m_xDocumentProperties.is())
4444 12 : m_xDocumentProperties->setAuthor(m_aStates.top().aDestinationText.makeStringAndClear());
4445 14 : break;
4446 : case DESTINATION_KEYWORDS:
4447 3 : if (m_xDocumentProperties.is())
4448 3 : m_xDocumentProperties->setKeywords(comphelper::string::convertCommaSeparated(m_aStates.top().aDestinationText.makeStringAndClear()));
4449 3 : break;
4450 : case DESTINATION_COMMENT:
4451 58 : if (m_xDocumentProperties.is())
4452 56 : m_xDocumentProperties->setGenerator(m_aStates.top().aDestinationText.makeStringAndClear());
4453 58 : break;
4454 : case DESTINATION_SUBJECT:
4455 4 : if (m_xDocumentProperties.is())
4456 4 : m_xDocumentProperties->setSubject(m_aStates.top().aDestinationText.makeStringAndClear());
4457 4 : break;
4458 : case DESTINATION_DOCCOMM:
4459 5 : if (m_xDocumentProperties.is())
4460 5 : m_xDocumentProperties->setDescription(m_aStates.top().aDestinationText.makeStringAndClear());
4461 5 : break;
4462 : case DESTINATION_OPERATOR:
4463 : case DESTINATION_COMPANY:
4464 : {
4465 10 : OUString aName = aState.nDestinationState == DESTINATION_OPERATOR ? OUString("Operator") : OUString("Company");
4466 20 : uno::Any aValue = uno::makeAny(m_aStates.top().aDestinationText.makeStringAndClear());
4467 10 : if (m_xDocumentProperties.is())
4468 : {
4469 6 : uno::Reference<beans::XPropertyContainer> xUserDefinedProperties = m_xDocumentProperties->getUserDefinedProperties();
4470 12 : uno::Reference<beans::XPropertySet> xPropertySet(xUserDefinedProperties, uno::UNO_QUERY);
4471 12 : uno::Reference<beans::XPropertySetInfo> xPropertySetInfo = xPropertySet->getPropertySetInfo();
4472 6 : if (xPropertySetInfo->hasPropertyByName(aName))
4473 1 : xPropertySet->setPropertyValue(aName, aValue);
4474 : else
4475 11 : xUserDefinedProperties->addProperty(aName, beans::PropertyAttribute::REMOVABLE, aValue);
4476 10 : }
4477 : }
4478 10 : break;
4479 : case DESTINATION_OBJDATA:
4480 : {
4481 0 : m_pObjectData.reset(new SvMemoryStream());
4482 0 : int b = 0, count = 2;
4483 :
4484 : // Feed the destination text to a stream.
4485 0 : OString aStr = OUStringToOString(m_aStates.top().aDestinationText.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US);
4486 0 : const char *str = aStr.getStr();
4487 0 : for (int i = 0; i < aStr.getLength(); ++i)
4488 : {
4489 0 : char ch = str[i];
4490 0 : if (ch != 0x0d && ch != 0x0a)
4491 : {
4492 0 : b = b << 4;
4493 0 : sal_Int8 parsed = m_pTokenizer->asHex(ch);
4494 0 : if (parsed == -1)
4495 0 : return ERROR_HEX_INVALID;
4496 0 : b += parsed;
4497 0 : count--;
4498 0 : if (!count)
4499 : {
4500 0 : m_pObjectData->WriteChar( (char)b );
4501 0 : count = 2;
4502 0 : b = 0;
4503 : }
4504 : }
4505 : }
4506 :
4507 0 : if (m_pObjectData->Tell())
4508 : {
4509 0 : m_pObjectData->Seek(0);
4510 :
4511 : // Skip ObjectHeader
4512 : sal_uInt32 nData;
4513 0 : m_pObjectData->ReadUInt32( nData ); // OLEVersion
4514 0 : m_pObjectData->ReadUInt32( nData ); // FormatID
4515 0 : m_pObjectData->ReadUInt32( nData ); // ClassName
4516 0 : m_pObjectData->SeekRel(nData);
4517 0 : m_pObjectData->ReadUInt32( nData ); // TopicName
4518 0 : m_pObjectData->SeekRel(nData);
4519 0 : m_pObjectData->ReadUInt32( nData ); // ItemName
4520 0 : m_pObjectData->SeekRel(nData);
4521 0 : m_pObjectData->ReadUInt32( nData ); // NativeDataSize
4522 : }
4523 :
4524 0 : uno::Reference<io::XInputStream> xInputStream(new utl::OInputStreamWrapper(m_pObjectData.get()));
4525 0 : RTFValue::Pointer_t pStreamValue(new RTFValue(xInputStream));
4526 :
4527 0 : RTFSprms aOLEAttributes;
4528 0 : aOLEAttributes.set(NS_ooxml::LN_inputstream, pStreamValue);
4529 0 : RTFValue::Pointer_t pValue(new RTFValue(aOLEAttributes));
4530 0 : m_aObjectSprms.set(NS_ooxml::LN_OLEObject_OLEObject, pValue);
4531 : }
4532 0 : break;
4533 : case DESTINATION_OBJECT:
4534 : {
4535 1 : if (!m_bObject)
4536 : {
4537 : // if the object is in a special container we will use the \result
4538 : // element instead of the \objdata
4539 : // (see RTF_OBJECT in RTFDocumentImpl::dispatchDestination)
4540 1 : break;
4541 : }
4542 :
4543 0 : RTFSprms aObjAttributes;
4544 0 : RTFSprms aObjSprms;
4545 0 : RTFValue::Pointer_t pValue(new RTFValue(m_aObjectAttributes, m_aObjectSprms));
4546 0 : aObjSprms.set(NS_ooxml::LN_object, pValue);
4547 0 : writerfilter::Reference<Properties>::Pointer_t const pProperties(new RTFReferenceProperties(aObjAttributes, aObjSprms));
4548 0 : uno::Reference<drawing::XShape> xShape;
4549 0 : RTFValue::Pointer_t pShape = m_aObjectAttributes.find(NS_ooxml::LN_shape);
4550 : OSL_ASSERT(pShape.get());
4551 0 : if (pShape.get())
4552 0 : pShape->getAny() >>= xShape;
4553 0 : Mapper().startShape(xShape);
4554 0 : Mapper().props(pProperties);
4555 0 : Mapper().endShape();
4556 0 : m_aObjectAttributes.clear();
4557 0 : m_aObjectSprms.clear();
4558 0 : m_bObject = false;
4559 : }
4560 0 : break;
4561 : case DESTINATION_ANNOTATIONDATE:
4562 : {
4563 6 : OUString aStr(OStringToOUString(lcl_DTTM22OString(m_aStates.top().aDestinationText.makeStringAndClear().toInt32()),
4564 12 : aState.nCurrentEncoding));
4565 12 : RTFValue::Pointer_t pValue(new RTFValue(aStr));
4566 12 : RTFSprms aAnnAttributes;
4567 6 : aAnnAttributes.set(NS_ooxml::LN_CT_TrackChange_date, pValue);
4568 12 : writerfilter::Reference<Properties>::Pointer_t const pProperties(new RTFReferenceProperties(aAnnAttributes));
4569 12 : Mapper().props(pProperties);
4570 : }
4571 6 : break;
4572 : case DESTINATION_ANNOTATIONAUTHOR:
4573 6 : m_aAuthor = m_aStates.top().aDestinationText.makeStringAndClear();
4574 6 : break;
4575 : case DESTINATION_ATNID:
4576 6 : m_aAuthorInitials = m_aStates.top().aDestinationText.makeStringAndClear();
4577 6 : break;
4578 : case DESTINATION_ANNOTATIONREFERENCESTART:
4579 : case DESTINATION_ANNOTATIONREFERENCEEND:
4580 : {
4581 12 : OUString aStr = m_aStates.top().aDestinationText.makeStringAndClear();
4582 24 : RTFValue::Pointer_t pValue(new RTFValue(aStr.toInt32()));
4583 24 : RTFSprms aAttributes;
4584 12 : if (aState.nDestinationState == DESTINATION_ANNOTATIONREFERENCESTART)
4585 6 : aAttributes.set(NS_ooxml::LN_EG_RangeMarkupElements_commentRangeStart, pValue);
4586 : else
4587 6 : aAttributes.set(NS_ooxml::LN_EG_RangeMarkupElements_commentRangeEnd, pValue);
4588 24 : writerfilter::Reference<Properties>::Pointer_t pProperties(new RTFReferenceProperties(aAttributes));
4589 24 : Mapper().props(pProperties);
4590 : }
4591 12 : break;
4592 : case DESTINATION_ANNOTATIONREFERENCE:
4593 : {
4594 6 : OUString aStr = m_aStates.top().aDestinationText.makeStringAndClear();
4595 12 : RTFSprms aAnnAttributes;
4596 6 : aAnnAttributes.set(NS_ooxml::LN_CT_Markup_id, RTFValue::Pointer_t(new RTFValue(aStr.toInt32())));
4597 12 : Mapper().props(writerfilter::Reference<Properties>::Pointer_t(new RTFReferenceProperties(aAnnAttributes)));
4598 : }
4599 6 : break;
4600 : case DESTINATION_FALT:
4601 : {
4602 136 : OUString aStr(m_aStates.top().aDestinationText.makeStringAndClear());
4603 272 : RTFValue::Pointer_t pValue(new RTFValue(aStr));
4604 272 : aState.aTableSprms.set(NS_ooxml::LN_CT_Font_altName, pValue);
4605 : }
4606 136 : break;
4607 : case DESTINATION_DRAWINGOBJECT:
4608 24 : if (m_aStates.top().aDrawingObject.xShape.is())
4609 : {
4610 24 : RTFDrawingObject& rDrawing = m_aStates.top().aDrawingObject;
4611 24 : uno::Reference<drawing::XShape> xShape(rDrawing.xShape);
4612 48 : uno::Reference<beans::XPropertySet> xPropertySet(rDrawing.xPropertySet);
4613 :
4614 48 : uno::Reference<lang::XServiceInfo> xServiceInfo(xShape, uno::UNO_QUERY);
4615 24 : bool bTextFrame = xServiceInfo->supportsService("com.sun.star.text.TextFrame");
4616 :
4617 : // The default is certainly not inline, but then what Word supports is just at-character.
4618 24 : xPropertySet->setPropertyValue("AnchorType", uno::makeAny(text::TextContentAnchorType_AT_CHARACTER));
4619 :
4620 24 : if (bTextFrame)
4621 : {
4622 11 : xPropertySet->setPropertyValue("HoriOrientPosition", uno::makeAny((sal_Int32)rDrawing.nLeft));
4623 11 : xPropertySet->setPropertyValue("VertOrientPosition", uno::makeAny((sal_Int32)rDrawing.nTop));
4624 : }
4625 : else
4626 : {
4627 13 : xShape->setPosition(awt::Point(rDrawing.nLeft, rDrawing.nTop));
4628 : }
4629 24 : xShape->setSize(awt::Size(rDrawing.nRight, rDrawing.nBottom));
4630 :
4631 24 : if (rDrawing.bHasLineColor)
4632 9 : xPropertySet->setPropertyValue("LineColor", uno::makeAny(sal_uInt32((rDrawing.nLineColorR<<16) + (rDrawing.nLineColorG<<8) + rDrawing.nLineColorB)));
4633 24 : if (rDrawing.bHasFillColor)
4634 5 : xPropertySet->setPropertyValue("FillColor", uno::makeAny(sal_uInt32((rDrawing.nFillColorR<<16) + (rDrawing.nFillColorG<<8) + rDrawing.nFillColorB)));
4635 19 : else if (!bTextFrame)
4636 : // If there is no fill, the Word default is 100% transparency.
4637 8 : xPropertySet->setPropertyValue("FillTransparence", uno::makeAny(sal_Int32(100)));
4638 :
4639 24 : m_pSdrImport->resolveFLine(xPropertySet, rDrawing.nFLine);
4640 :
4641 24 : if (!m_aStates.top().aDrawingObject.bHadShapeText)
4642 : {
4643 13 : Mapper().startShape(xShape);
4644 : }
4645 48 : Mapper().endShape();
4646 : }
4647 24 : break;
4648 : case DESTINATION_SHAPE:
4649 67 : m_bNeedCr = m_bNeedCrOrig;
4650 67 : if (aState.aFrame.inFrame())
4651 : {
4652 : // parBreak modify m_aStates.top() so we can't apply resetFrame directly on aState
4653 2 : m_aStates.top().resetFrame();
4654 2 : parBreak();
4655 : // Save this state for later use, so we only reset frame status only for the first shape inside a frame.
4656 2 : aState = m_aStates.top();
4657 2 : m_bNeedPap = true;
4658 : }
4659 67 : break;
4660 : case DESTINATION_MOMATH:
4661 : {
4662 73 : m_aMathBuffer.appendClosingTag(M_TOKEN(oMath));
4663 :
4664 73 : SvGlobalName aGlobalName(SO3_SM_CLASSID);
4665 146 : comphelper::EmbeddedObjectContainer aContainer;
4666 146 : OUString aName;
4667 146 : uno::Reference<embed::XEmbeddedObject> xObject = aContainer.CreateEmbeddedObject(aGlobalName.GetByteSequence(), aName);
4668 146 : uno::Reference<util::XCloseable> xComponent(xObject->getComponent(), uno::UNO_QUERY);
4669 : // gcc4.4 (and 4.3 and possibly older) have a problem with dynamic_cast directly to the target class,
4670 : // so help it with an intermediate cast. I'm not sure what exactly the problem is, seems to be unrelated
4671 : // to RTLD_GLOBAL, so most probably a gcc bug.
4672 73 : oox::FormulaImportBase* pImport = dynamic_cast<oox::FormulaImportBase*>(dynamic_cast<SfxBaseModel*>(xComponent.get()));
4673 : assert( pImport != NULL );
4674 73 : if (pImport)
4675 73 : pImport->readFormulaOoxml(m_aMathBuffer);
4676 146 : RTFValue::Pointer_t pValue(new RTFValue(xObject));
4677 146 : RTFSprms aMathAttributes;
4678 73 : aMathAttributes.set(NS_ooxml::LN_starmath, pValue);
4679 146 : writerfilter::Reference<Properties>::Pointer_t const pProperties(new RTFReferenceProperties(aMathAttributes));
4680 73 : Mapper().props(pProperties);
4681 146 : m_aMathBuffer = oox::formulaimport::XmlStreamBuilder();
4682 : }
4683 73 : break;
4684 : case DESTINATION_MR:
4685 1311 : lcl_DestinationToMath(m_aStates.top().aDestinationText, m_aMathBuffer, m_bMathNor);
4686 1311 : break;
4687 : case DESTINATION_MF:
4688 35 : m_aMathBuffer.appendClosingTag(M_TOKEN(f));
4689 35 : break;
4690 : case DESTINATION_MFPR:
4691 21 : m_aMathBuffer.appendClosingTag(M_TOKEN(fPr));
4692 21 : break;
4693 : case DESTINATION_MCTRLPR:
4694 150 : m_aMathBuffer.appendClosingTag(M_TOKEN(ctrlPr));
4695 150 : break;
4696 : case DESTINATION_MNUM:
4697 35 : m_aMathBuffer.appendClosingTag(M_TOKEN(num));
4698 35 : break;
4699 : case DESTINATION_MDEN:
4700 35 : m_aMathBuffer.appendClosingTag(M_TOKEN(den));
4701 35 : break;
4702 : case DESTINATION_MACC:
4703 36 : m_aMathBuffer.appendClosingTag(M_TOKEN(acc));
4704 36 : break;
4705 : case DESTINATION_MACCPR:
4706 36 : m_aMathBuffer.appendClosingTag(M_TOKEN(accPr));
4707 36 : break;
4708 : case DESTINATION_MCHR:
4709 : case DESTINATION_MPOS:
4710 : case DESTINATION_MVERTJC:
4711 : case DESTINATION_MSTRIKEH:
4712 : case DESTINATION_MDEGHIDE:
4713 : case DESTINATION_MBEGCHR:
4714 : case DESTINATION_MSEPCHR:
4715 : case DESTINATION_MENDCHR:
4716 : case DESTINATION_MSUBHIDE:
4717 : case DESTINATION_MSUPHIDE:
4718 : case DESTINATION_MTYPE:
4719 : case DESTINATION_MGROW:
4720 : {
4721 169 : sal_Int32 nMathToken = 0;
4722 169 : switch (aState.nDestinationState)
4723 : {
4724 : case DESTINATION_MCHR:
4725 57 : nMathToken = M_TOKEN(chr);
4726 57 : break;
4727 : case DESTINATION_MPOS:
4728 5 : nMathToken = M_TOKEN(pos);
4729 5 : break;
4730 : case DESTINATION_MVERTJC:
4731 4 : nMathToken = M_TOKEN(vertJc);
4732 4 : break;
4733 : case DESTINATION_MSTRIKEH:
4734 3 : nMathToken = M_TOKEN(strikeH);
4735 3 : break;
4736 : case DESTINATION_MDEGHIDE:
4737 4 : nMathToken = M_TOKEN(degHide);
4738 4 : break;
4739 : case DESTINATION_MBEGCHR:
4740 40 : nMathToken = M_TOKEN(begChr);
4741 40 : break;
4742 : case DESTINATION_MSEPCHR:
4743 4 : nMathToken = M_TOKEN(sepChr);
4744 4 : break;
4745 : case DESTINATION_MENDCHR:
4746 40 : nMathToken = M_TOKEN(endChr);
4747 40 : break;
4748 : case DESTINATION_MSUBHIDE:
4749 2 : nMathToken = M_TOKEN(subHide);
4750 2 : break;
4751 : case DESTINATION_MSUPHIDE:
4752 2 : nMathToken = M_TOKEN(supHide);
4753 2 : break;
4754 : case DESTINATION_MTYPE:
4755 6 : nMathToken = M_TOKEN(type);
4756 6 : break;
4757 : case DESTINATION_MGROW:
4758 2 : nMathToken = M_TOKEN(grow);
4759 2 : break;
4760 : default:
4761 0 : break;
4762 : }
4763 :
4764 169 : oox::formulaimport::XmlStream::AttributeList aAttribs;
4765 169 : aAttribs[M_TOKEN(val)] = m_aStates.top().aDestinationText.makeStringAndClear();
4766 169 : m_aMathBuffer.appendOpeningTag(nMathToken, aAttribs);
4767 169 : m_aMathBuffer.appendClosingTag(nMathToken);
4768 : }
4769 169 : break;
4770 : case DESTINATION_ME:
4771 253 : m_aMathBuffer.appendClosingTag(M_TOKEN(e));
4772 253 : break;
4773 : case DESTINATION_MBAR:
4774 3 : m_aMathBuffer.appendClosingTag(M_TOKEN(bar));
4775 3 : break;
4776 : case DESTINATION_MBARPR:
4777 3 : m_aMathBuffer.appendClosingTag(M_TOKEN(barPr));
4778 3 : break;
4779 : case DESTINATION_MD:
4780 56 : m_aMathBuffer.appendClosingTag(M_TOKEN(d));
4781 56 : break;
4782 : case DESTINATION_MDPR:
4783 56 : m_aMathBuffer.appendClosingTag(M_TOKEN(dPr));
4784 56 : break;
4785 : case DESTINATION_MFUNC:
4786 12 : m_aMathBuffer.appendClosingTag(M_TOKEN(func));
4787 12 : break;
4788 : case DESTINATION_MFUNCPR:
4789 11 : m_aMathBuffer.appendClosingTag(M_TOKEN(funcPr));
4790 11 : break;
4791 : case DESTINATION_MFNAME:
4792 12 : m_aMathBuffer.appendClosingTag(M_TOKEN(fName));
4793 12 : break;
4794 : case DESTINATION_MLIMLOW:
4795 8 : m_aMathBuffer.appendClosingTag(M_TOKEN(limLow));
4796 8 : break;
4797 : case DESTINATION_MLIMLOWPR:
4798 5 : m_aMathBuffer.appendClosingTag(M_TOKEN(limLowPr));
4799 5 : break;
4800 : case DESTINATION_MLIM:
4801 14 : m_aMathBuffer.appendClosingTag(M_TOKEN(lim));
4802 14 : break;
4803 : case DESTINATION_MM:
4804 3 : m_aMathBuffer.appendClosingTag(M_TOKEN(m));
4805 3 : break;
4806 : case DESTINATION_MMPR:
4807 2 : m_aMathBuffer.appendClosingTag(M_TOKEN(mPr));
4808 2 : break;
4809 : case DESTINATION_MMR:
4810 6 : m_aMathBuffer.appendClosingTag(M_TOKEN(mr));
4811 6 : break;
4812 : case DESTINATION_MNARY:
4813 20 : m_aMathBuffer.appendClosingTag(M_TOKEN(nary));
4814 20 : break;
4815 : case DESTINATION_MNARYPR:
4816 20 : m_aMathBuffer.appendClosingTag(M_TOKEN(naryPr));
4817 20 : break;
4818 : case DESTINATION_MSUB:
4819 41 : m_aMathBuffer.appendClosingTag(M_TOKEN(sub));
4820 41 : break;
4821 : case DESTINATION_MSUP:
4822 69 : m_aMathBuffer.appendClosingTag(M_TOKEN(sup));
4823 69 : break;
4824 : case DESTINATION_MLIMUPP:
4825 6 : m_aMathBuffer.appendClosingTag(M_TOKEN(limUpp));
4826 6 : break;
4827 : case DESTINATION_MLIMUPPPR:
4828 4 : m_aMathBuffer.appendClosingTag(M_TOKEN(limUppPr));
4829 4 : break;
4830 : case DESTINATION_MGROUPCHR:
4831 6 : m_aMathBuffer.appendClosingTag(M_TOKEN(groupChr));
4832 6 : break;
4833 : case DESTINATION_MGROUPCHRPR:
4834 6 : m_aMathBuffer.appendClosingTag(M_TOKEN(groupChrPr));
4835 6 : break;
4836 : case DESTINATION_MBORDERBOX:
4837 3 : m_aMathBuffer.appendClosingTag(M_TOKEN(borderBox));
4838 3 : break;
4839 : case DESTINATION_MBORDERBOXPR:
4840 3 : m_aMathBuffer.appendClosingTag(M_TOKEN(borderBoxPr));
4841 3 : break;
4842 : case DESTINATION_MRAD:
4843 6 : m_aMathBuffer.appendClosingTag(M_TOKEN(rad));
4844 6 : break;
4845 : case DESTINATION_MRADPR:
4846 5 : m_aMathBuffer.appendClosingTag(M_TOKEN(radPr));
4847 5 : break;
4848 : case DESTINATION_MDEG:
4849 6 : m_aMathBuffer.appendClosingTag(M_TOKEN(deg));
4850 6 : break;
4851 : case DESTINATION_MSSUB:
4852 9 : m_aMathBuffer.appendClosingTag(M_TOKEN(sSub));
4853 9 : break;
4854 : case DESTINATION_MSSUBPR:
4855 5 : m_aMathBuffer.appendClosingTag(M_TOKEN(sSubPr));
4856 5 : break;
4857 : case DESTINATION_MSSUP:
4858 37 : m_aMathBuffer.appendClosingTag(M_TOKEN(sSup));
4859 37 : break;
4860 : case DESTINATION_MSSUPPR:
4861 20 : m_aMathBuffer.appendClosingTag(M_TOKEN(sSupPr));
4862 20 : break;
4863 : case DESTINATION_MSSUBSUP:
4864 6 : m_aMathBuffer.appendClosingTag(M_TOKEN(sSubSup));
4865 6 : break;
4866 : case DESTINATION_MSSUBSUPPR:
4867 4 : m_aMathBuffer.appendClosingTag(M_TOKEN(sSubSupPr));
4868 4 : break;
4869 : case DESTINATION_MSPRE:
4870 6 : m_aMathBuffer.appendClosingTag(M_TOKEN(sPre));
4871 6 : break;
4872 : case DESTINATION_MSPREPR:
4873 4 : m_aMathBuffer.appendClosingTag(M_TOKEN(sPrePr));
4874 4 : break;
4875 : case DESTINATION_MBOX:
4876 2 : m_aMathBuffer.appendClosingTag(M_TOKEN(box));
4877 2 : break;
4878 : case DESTINATION_MEQARR:
4879 6 : m_aMathBuffer.appendClosingTag(M_TOKEN(eqArr));
4880 6 : break;
4881 : case DESTINATION_SHAPEGROUP:
4882 5 : if (aState.bCreatedShapeGroup)
4883 3 : m_pSdrImport->popParent();
4884 5 : break;
4885 : default:
4886 4641 : break;
4887 : }
4888 :
4889 : // See if we need to end a track change
4890 9452 : if (aState.bStartedTrackchange)
4891 : {
4892 0 : RTFSprms aTCSprms;
4893 0 : RTFValue::Pointer_t pValue(new RTFValue(0));
4894 0 : aTCSprms.set(NS_ooxml::LN_endtrackchange, pValue);
4895 0 : writerfilter::Reference<Properties>::Pointer_t const pProperties(new RTFReferenceProperties(RTFSprms(), aTCSprms));
4896 0 : Mapper().props(pProperties);
4897 : }
4898 :
4899 : // This is the end of the doc, see if we need to close the last section.
4900 9452 : if (m_pTokenizer->getGroup() == 1 && !m_bFirstRun)
4901 : {
4902 : // \par means an empty paragraph at the end of footnotes/endnotes, but
4903 : // not in case of other substreams, like headers.
4904 302 : if (m_bNeedCr && !(m_nStreamType == NS_ooxml::LN_footnote || m_nStreamType == NS_ooxml::LN_endnote))
4905 25 : dispatchSymbol(RTF_PAR);
4906 302 : if (m_bNeedSect) // may be set by dispatchSymbol above!
4907 298 : sectBreak(true);
4908 : }
4909 :
4910 9452 : m_aStates.pop();
4911 :
4912 9452 : m_pTokenizer->popGroup();
4913 :
4914 : // list table
4915 9452 : switch (aState.nDestinationState)
4916 : {
4917 : case DESTINATION_LISTENTRY:
4918 : {
4919 20 : RTFValue::Pointer_t pValue(new RTFValue(aState.aTableAttributes, aState.aTableSprms));
4920 20 : m_aListTableSprms.set(NS_ooxml::LN_CT_Numbering_abstractNum, pValue, OVERWRITE_NO_APPEND);
4921 : }
4922 20 : break;
4923 : case DESTINATION_PARAGRAPHNUMBERING:
4924 : {
4925 4 : RTFValue::Pointer_t pIdValue = aState.aTableAttributes.find(NS_ooxml::LN_CT_AbstractNum_nsid);
4926 4 : if (pIdValue.get())
4927 : {
4928 : // Abstract numbering
4929 4 : RTFSprms aLeveltextAttributes;
4930 8 : OUString aTextValue;
4931 8 : RTFValue::Pointer_t pTextBefore = aState.aTableAttributes.find(NS_ooxml::LN_CT_LevelText_val);
4932 4 : if (pTextBefore.get())
4933 3 : aTextValue += pTextBefore->getString();
4934 4 : aTextValue += "%1";
4935 8 : RTFValue::Pointer_t pTextAfter = aState.aTableAttributes.find(NS_ooxml::LN_CT_LevelSuffix_val);
4936 4 : if (pTextAfter.get())
4937 3 : aTextValue += pTextAfter->getString();
4938 8 : RTFValue::Pointer_t pTextValue(new RTFValue(aTextValue));
4939 4 : aLeveltextAttributes.set(NS_ooxml::LN_CT_LevelText_val, pTextValue);
4940 :
4941 8 : RTFSprms aLevelAttributes;
4942 8 : RTFSprms aLevelSprms;
4943 8 : RTFValue::Pointer_t pIlvlValue(new RTFValue(0));
4944 4 : aLevelAttributes.set(NS_ooxml::LN_CT_Lvl_ilvl, pIlvlValue);
4945 :
4946 8 : RTFValue::Pointer_t pFmtValue = aState.aTableSprms.find(NS_ooxml::LN_CT_Lvl_numFmt);
4947 4 : if (pFmtValue.get())
4948 4 : aLevelSprms.set(NS_ooxml::LN_CT_Lvl_numFmt, pFmtValue);
4949 :
4950 8 : RTFValue::Pointer_t pStartatValue = aState.aTableSprms.find(NS_ooxml::LN_CT_Lvl_start);
4951 4 : if (pStartatValue.get())
4952 4 : aLevelSprms.set(NS_ooxml::LN_CT_Lvl_start, pStartatValue);
4953 :
4954 8 : RTFValue::Pointer_t pLeveltextValue(new RTFValue(aLeveltextAttributes));
4955 4 : aLevelSprms.set(NS_ooxml::LN_CT_Lvl_lvlText, pLeveltextValue);
4956 8 : RTFValue::Pointer_t pRunProps = aState.aTableSprms.find(NS_ooxml::LN_CT_Lvl_rPr);
4957 4 : if (pRunProps.get())
4958 1 : aLevelSprms.set(NS_ooxml::LN_CT_Lvl_rPr, pRunProps);
4959 :
4960 8 : RTFSprms aAbstractAttributes;
4961 8 : RTFSprms aAbstractSprms;
4962 4 : aAbstractAttributes.set(NS_ooxml::LN_CT_AbstractNum_abstractNumId, pIdValue);
4963 8 : RTFValue::Pointer_t pLevelValue(new RTFValue(aLevelAttributes, aLevelSprms));
4964 4 : aAbstractSprms.set(NS_ooxml::LN_CT_AbstractNum_lvl, pLevelValue, OVERWRITE_NO_APPEND);
4965 :
4966 8 : RTFSprms aListTableSprms;
4967 8 : RTFValue::Pointer_t pAbstractValue(new RTFValue(aAbstractAttributes, aAbstractSprms));
4968 : // It's important that Numbering_abstractNum and Numbering_num never overwrites previous values.
4969 4 : aListTableSprms.set(NS_ooxml::LN_CT_Numbering_abstractNum, pAbstractValue, OVERWRITE_NO_APPEND);
4970 :
4971 : // Numbering
4972 8 : RTFSprms aNumberingAttributes;
4973 8 : RTFSprms aNumberingSprms;
4974 4 : aNumberingAttributes.set(NS_ooxml::LN_CT_AbstractNum_nsid, pIdValue);
4975 4 : aNumberingSprms.set(NS_ooxml::LN_CT_Num_abstractNumId, pIdValue);
4976 8 : RTFValue::Pointer_t pNumberingValue(new RTFValue(aNumberingAttributes, aNumberingSprms));
4977 4 : aListTableSprms.set(NS_ooxml::LN_CT_Numbering_num, pNumberingValue, OVERWRITE_NO_APPEND);
4978 :
4979 : // Table
4980 8 : RTFSprms aListTableAttributes;
4981 8 : writerfilter::Reference<Properties>::Pointer_t const pProp(new RTFReferenceProperties(aListTableAttributes, aListTableSprms));
4982 :
4983 8 : RTFReferenceTable::Entries_t aListTableEntries;
4984 4 : aListTableEntries.insert(make_pair(0, pProp));
4985 8 : writerfilter::Reference<Table>::Pointer_t const pTable(new RTFReferenceTable(aListTableEntries));
4986 4 : Mapper().table(NS_ooxml::LN_NUMBERING, pTable);
4987 :
4988 : // Use it
4989 4 : lcl_putNestedSprm(m_aStates.top().aParagraphSprms, NS_ooxml::LN_CT_PPrBase_numPr, NS_ooxml::LN_CT_NumPr_ilvl, pIlvlValue);
4990 8 : lcl_putNestedSprm(m_aStates.top().aParagraphSprms, NS_ooxml::LN_CT_PPrBase_tabs, NS_ooxml::LN_CT_NumPr_numId, pIdValue);
4991 4 : }
4992 : }
4993 4 : break;
4994 : case DESTINATION_PARAGRAPHNUMBERING_TEXTAFTER:
4995 : {
4996 3 : RTFValue::Pointer_t pValue(new RTFValue(aState.aDestinationText.makeStringAndClear(), true));
4997 3 : m_aStates.top().aTableAttributes.set(NS_ooxml::LN_CT_LevelSuffix_val, pValue);
4998 : }
4999 3 : break;
5000 : case DESTINATION_PARAGRAPHNUMBERING_TEXTBEFORE:
5001 : {
5002 3 : RTFValue::Pointer_t pValue(new RTFValue(aState.aDestinationText.makeStringAndClear(), true));
5003 3 : m_aStates.top().aTableAttributes.set(NS_ooxml::LN_CT_LevelText_val, pValue);
5004 : }
5005 3 : break;
5006 : case DESTINATION_LISTLEVEL:
5007 : {
5008 56 : RTFValue::Pointer_t pInnerValue(new RTFValue(m_aStates.top().nListLevelNum++));
5009 56 : aState.aTableAttributes.set(NS_ooxml::LN_CT_Lvl_ilvl, pInnerValue);
5010 :
5011 112 : RTFValue::Pointer_t pValue(new RTFValue(aState.aTableAttributes, aState.aTableSprms));
5012 56 : if (m_aStates.top().nDestinationState != DESTINATION_LFOLEVEL)
5013 55 : m_aStates.top().aListLevelEntries.set(NS_ooxml::LN_CT_AbstractNum_lvl, pValue, OVERWRITE_NO_APPEND);
5014 : else
5015 57 : m_aStates.top().aTableSprms.set(NS_ooxml::LN_CT_NumLvl_lvl, pValue);
5016 : }
5017 56 : break;
5018 : case DESTINATION_LFOLEVEL:
5019 : {
5020 1 : RTFValue::Pointer_t pInnerValue(new RTFValue(m_aStates.top().nListLevelNum++));
5021 1 : aState.aTableAttributes.set(NS_ooxml::LN_CT_NumLvl_ilvl, pInnerValue);
5022 :
5023 2 : RTFValue::Pointer_t pValue(new RTFValue(aState.aTableAttributes, aState.aTableSprms));
5024 2 : m_aStates.top().aTableSprms.set(NS_ooxml::LN_CT_Num_lvlOverride, pValue);
5025 : }
5026 1 : break;
5027 : // list override table
5028 : case DESTINATION_LISTOVERRIDEENTRY:
5029 : {
5030 20 : if (m_aStates.top().nDestinationState == DESTINATION_LISTOVERRIDEENTRY)
5031 : { // copy properties upwards so upper popState inserts it
5032 1 : m_aStates.top().aTableAttributes = aState.aTableAttributes;
5033 1 : m_aStates.top().aTableSprms = aState.aTableSprms;
5034 : }
5035 : else
5036 : {
5037 : RTFValue::Pointer_t pValue(new RTFValue(
5038 19 : aState.aTableAttributes, aState.aTableSprms));
5039 19 : m_aListTableSprms.set(NS_ooxml::LN_CT_Numbering_num, pValue, OVERWRITE_NO_APPEND);
5040 : }
5041 : }
5042 20 : break;
5043 : case DESTINATION_LEVELTEXT:
5044 : {
5045 57 : RTFValue::Pointer_t pValue(new RTFValue(aState.aTableAttributes));
5046 57 : m_aStates.top().aTableSprms.set(NS_ooxml::LN_CT_Lvl_lvlText, pValue);
5047 : }
5048 57 : break;
5049 : case DESTINATION_LEVELNUMBERS:
5050 58 : m_aStates.top().aTableSprms = aState.aTableSprms;
5051 58 : break;
5052 : case DESTINATION_FIELDINSTRUCTION:
5053 12 : m_aStates.top().nFieldStatus = FIELD_INSTRUCTION;
5054 12 : break;
5055 : case DESTINATION_FIELDRESULT:
5056 10 : m_aStates.top().nFieldStatus = FIELD_RESULT;
5057 10 : break;
5058 : case DESTINATION_FIELD:
5059 13 : if (aState.nFieldStatus == FIELD_INSTRUCTION)
5060 2 : singleChar(0x15);
5061 13 : break;
5062 : case DESTINATION_SHAPEPROPERTYVALUEPICT:
5063 : {
5064 5 : m_aStates.top().aPicture = aState.aPicture;
5065 5 : m_aStates.top().aDestinationText = aState.aDestinationText;
5066 : }
5067 5 : break;
5068 : case DESTINATION_FALT:
5069 136 : m_aStates.top().aTableSprms = aState.aTableSprms;
5070 136 : break;
5071 : case DESTINATION_SHAPEPROPERTYNAME:
5072 : case DESTINATION_SHAPEPROPERTYVALUE:
5073 : case DESTINATION_SHAPEPROPERTY:
5074 : {
5075 1785 : m_aStates.top().aShape = aState.aShape;
5076 1785 : m_aStates.top().aPicture = aState.aPicture;
5077 1785 : m_aStates.top().aCharacterAttributes = aState.aCharacterAttributes;
5078 : }
5079 1785 : break;
5080 : case DESTINATION_FLYMAINCONTENT:
5081 : case DESTINATION_SHPPICT:
5082 : case DESTINATION_SHAPE:
5083 77 : m_aStates.top().aFrame = aState.aFrame;
5084 77 : if (aState.nDestinationState == DESTINATION_SHPPICT && !m_aStates.empty() && m_aStates.top().nDestinationState == DESTINATION_LISTPICTURE)
5085 : {
5086 3 : RTFSprms aAttributes;
5087 3 : aAttributes.set(NS_ooxml::LN_CT_NumPicBullet_numPicBulletId, RTFValue::Pointer_t(new RTFValue(m_nListPictureId++)));
5088 6 : RTFSprms aSprms;
5089 : // Dummy value, real picture is already sent to dmapper.
5090 3 : aSprms.set(NS_ooxml::LN_CT_NumPicBullet_pict, RTFValue::Pointer_t(new RTFValue(0)));
5091 6 : RTFValue::Pointer_t pValue(new RTFValue(aAttributes, aSprms));
5092 6 : m_aListTableSprms.set(NS_ooxml::LN_CT_Numbering_numPicBullet, pValue, OVERWRITE_NO_APPEND);
5093 : }
5094 77 : break;
5095 : case DESTINATION_TITLE:
5096 : {
5097 12 : if (m_aStates.top().nDestinationState == DESTINATION_TITLE)
5098 : // The parent is a title as well, just append what we have so far.
5099 2 : m_aStates.top().aDestinationText.append(aState.aDestinationText.makeStringAndClear());
5100 10 : else if (m_xDocumentProperties.is())
5101 8 : m_xDocumentProperties->setTitle(aState.aDestinationText.makeStringAndClear());
5102 : }
5103 12 : break;
5104 : case DESTINATION_SHAPETEXT:
5105 : // If we're leaving the shapetext group (it may have nested ones) and this is a shape, not an old drawingobject.
5106 42 : if (m_aStates.top().nDestinationState != DESTINATION_SHAPETEXT && !m_aStates.top().aDrawingObject.bHadShapeText)
5107 : {
5108 32 : m_aStates.top().bHadShapeText = true;
5109 32 : if (!m_aStates.top().pCurrentBuffer)
5110 31 : m_pSdrImport->close();
5111 : else
5112 1 : m_aStates.top().pCurrentBuffer->push_back(
5113 2 : Buf_t(BUFFER_ENDSHAPE));
5114 : }
5115 42 : break;
5116 : default:
5117 : {
5118 7138 : if (m_aStates.size() && m_aStates.top().nDestinationState == DESTINATION_PICT)
5119 11 : m_aStates.top().aPicture = aState.aPicture;
5120 : }
5121 7138 : break;
5122 : }
5123 :
5124 9452 : if (aState.pCurrentBuffer == &m_aSuperBuffer)
5125 : {
5126 : OSL_ASSERT(!m_aStates.empty() && m_aStates.top().pCurrentBuffer == 0);
5127 :
5128 23 : if (!m_bHasFootnote)
5129 18 : replayBuffer(m_aSuperBuffer, 0, 0);
5130 :
5131 23 : m_bHasFootnote = false;
5132 : }
5133 :
5134 9452 : return 0;
5135 : }
5136 :
5137 0 : ::std::string RTFDocumentImpl::getType() const
5138 : {
5139 0 : return "RTFDocumentImpl";
5140 : }
5141 :
5142 287 : uno::Reference<lang::XMultiServiceFactory> RTFDocumentImpl::getModelFactory()
5143 : {
5144 287 : return m_xModelFactory;
5145 : }
5146 :
5147 62 : bool RTFDocumentImpl::isInBackground()
5148 : {
5149 62 : return m_aStates.top().bInBackground;
5150 : }
5151 :
5152 217711 : RTFInternalState RTFDocumentImpl::getInternalState()
5153 : {
5154 217711 : return m_aStates.top().nInternalState;
5155 : }
5156 :
5157 23538 : void RTFDocumentImpl::setInternalState(RTFInternalState nInternalState)
5158 : {
5159 23538 : m_aStates.top().nInternalState = nInternalState;
5160 23538 : }
5161 :
5162 77183 : RTFDestinationState RTFDocumentImpl::getDestinationState()
5163 : {
5164 77183 : return m_aStates.top().nDestinationState;
5165 : }
5166 :
5167 433 : void RTFDocumentImpl::setDestinationState(RTFDestinationState nDestinationState)
5168 : {
5169 433 : m_aStates.top().nDestinationState = nDestinationState;
5170 433 : }
5171 :
5172 5 : void RTFDocumentImpl::setDestinationText(OUString& rString)
5173 : {
5174 5 : m_aStates.top().aDestinationText.setLength(0);
5175 5 : m_aStates.top().aDestinationText.append(rString);
5176 5 : }
5177 :
5178 73245 : bool RTFDocumentImpl::getSkipUnknown()
5179 : {
5180 73245 : return m_bSkipUnknown;
5181 : }
5182 :
5183 1022 : void RTFDocumentImpl::setSkipUnknown(bool bSkipUnknown)
5184 : {
5185 1022 : m_bSkipUnknown = bSkipUnknown;
5186 1022 : }
5187 :
5188 129360 : void RTFDocumentImpl::checkUnicode(bool bUnicode, bool bHex)
5189 : {
5190 129360 : if (bUnicode && !m_aUnicodeBuffer.isEmpty())
5191 : {
5192 142 : OUString aString = m_aUnicodeBuffer.makeStringAndClear();
5193 142 : text(aString);
5194 : }
5195 129360 : if (bHex && !m_aHexBuffer.isEmpty())
5196 : {
5197 2037 : OUString aString = OStringToOUString(m_aHexBuffer.makeStringAndClear(), m_aStates.top().nCurrentEncoding);
5198 2037 : text(aString);
5199 : }
5200 129360 : }
5201 :
5202 312 : RTFParserState::RTFParserState(RTFDocumentImpl *pDocumentImpl)
5203 : : m_pDocumentImpl(pDocumentImpl),
5204 : nInternalState(INTERNAL_NORMAL),
5205 : nDestinationState(DESTINATION_NORMAL),
5206 : nFieldStatus(FIELD_NONE),
5207 : nBorderState(BORDER_NONE),
5208 : aTableSprms(),
5209 : aTableAttributes(),
5210 : aCharacterSprms(),
5211 : aCharacterAttributes(),
5212 : aParagraphSprms(),
5213 : aParagraphAttributes(),
5214 : aSectionSprms(),
5215 : aSectionAttributes(),
5216 : aTableRowSprms(),
5217 : aTableRowAttributes(),
5218 : aTableCellSprms(),
5219 : aTableCellAttributes(),
5220 : aTabAttributes(),
5221 : aCurrentColor(),
5222 312 : nCurrentEncoding(rtl_getTextEncodingFromWindowsCharset(0)),
5223 : nUc(1),
5224 : nCharsToSkip(0),
5225 : nBinaryToRead(0),
5226 : nListLevelNum(0),
5227 : aListLevelEntries(),
5228 : aLevelNumbers(),
5229 : aPicture(),
5230 : aShape(),
5231 : aDrawingObject(),
5232 : aFrame(this),
5233 : bIsCjk(false),
5234 : nYear(0),
5235 : nMonth(0),
5236 : nDay(0),
5237 : nHour(0),
5238 : nMinute(0),
5239 : nCurrentStyleIndex(-1),
5240 : pCurrentBuffer(0),
5241 : bInListpicture(false),
5242 : bInBackground(false),
5243 : bHadShapeText(false),
5244 : bInShapeGroup(false),
5245 : bInShape(false),
5246 : bCreatedShapeGroup(false),
5247 624 : bStartedTrackchange(false)
5248 : {
5249 312 : }
5250 :
5251 562 : void RTFParserState::resetFrame()
5252 : {
5253 562 : aFrame = RTFFrame(this);
5254 562 : }
5255 :
5256 716 : RTFColorTableEntry::RTFColorTableEntry()
5257 : : nRed(0),
5258 : nGreen(0),
5259 716 : nBlue(0)
5260 : {
5261 716 : }
5262 :
5263 312 : RTFPicture::RTFPicture()
5264 : : nWidth(0),
5265 : nHeight(0),
5266 : nGoalWidth(0),
5267 : nGoalHeight(0),
5268 : nScaleX(100),
5269 : nScaleY(100),
5270 : nCropT(0),
5271 : nCropB(0),
5272 : nCropL(0),
5273 : nCropR(0),
5274 : eWMetafile(0),
5275 312 : nStyle(BMPSTYLE_NONE)
5276 : {
5277 312 : }
5278 :
5279 52448 : RTFShape::RTFShape()
5280 : : nLeft(0),
5281 : nTop(0),
5282 : nRight(0),
5283 : nBottom(0),
5284 : nHoriOrientRelation(0),
5285 : nVertOrientRelation(0),
5286 : nHoriOrientRelationToken(0),
5287 : nVertOrientRelationToken(0),
5288 52448 : nWrap(-1)
5289 : {
5290 52448 : }
5291 :
5292 312 : RTFDrawingObject::RTFDrawingObject()
5293 : : nLineColorR(0),
5294 : nLineColorG(0),
5295 : nLineColorB(0),
5296 : bHasLineColor(false),
5297 : nFillColorR(0),
5298 : nFillColorG(0),
5299 : nFillColorB(0),
5300 : bHasFillColor(false),
5301 : nDhgt(0),
5302 : nFLine(-1),
5303 : nPolyLineCount(0),
5304 312 : bHadShapeText(false)
5305 : {
5306 312 : }
5307 :
5308 874 : RTFFrame::RTFFrame(RTFParserState* pParserState)
5309 : : m_pParserState(pParserState),
5310 : nX(0),
5311 : nY(0),
5312 : nW(0),
5313 : nH(0),
5314 : nHoriPadding(0),
5315 : nVertPadding(0),
5316 : nHoriAlign(0),
5317 : nHoriAnchor(0),
5318 : nVertAlign(0),
5319 : nVertAnchor(0),
5320 : nHRule(NS_ooxml::LN_Value_wordprocessingml_ST_HeightRule_auto),
5321 874 : nAnchorType(0)
5322 : {
5323 874 : }
5324 :
5325 155 : void RTFFrame::setSprm(Id nId, Id nValue)
5326 : {
5327 155 : if (m_pParserState->m_pDocumentImpl->getFirstRun())
5328 : {
5329 11 : m_pParserState->m_pDocumentImpl->checkFirstRun();
5330 11 : m_pParserState->m_pDocumentImpl->setNeedPar(false);
5331 : }
5332 155 : switch (nId)
5333 : {
5334 : case NS_ooxml::LN_CT_FramePr_w:
5335 17 : nW = nValue;
5336 17 : break;
5337 : case NS_ooxml::LN_CT_FramePr_h:
5338 17 : nH = nValue;
5339 17 : break;
5340 : case NS_ooxml::LN_CT_FramePr_x:
5341 17 : nX = nValue;
5342 17 : break;
5343 : case NS_ooxml::LN_CT_FramePr_y:
5344 17 : nY = nValue;
5345 17 : break;
5346 : case NS_ooxml::LN_CT_FramePr_hSpace:
5347 6 : nHoriPadding = nValue;
5348 6 : break;
5349 : case NS_ooxml::LN_CT_FramePr_vSpace:
5350 6 : nVertPadding = nValue;
5351 6 : break;
5352 : case NS_ooxml::LN_CT_FramePr_xAlign:
5353 19 : nHoriAlign = nValue;
5354 19 : break;
5355 : case NS_ooxml::LN_CT_FramePr_hAnchor:
5356 17 : nHoriAnchor = nValue;
5357 17 : break;
5358 : case NS_ooxml::LN_CT_FramePr_yAlign:
5359 19 : nVertAlign = nValue;
5360 19 : break;
5361 : case NS_ooxml::LN_CT_FramePr_vAnchor:
5362 18 : nVertAnchor = nValue;
5363 18 : break;
5364 : case NS_ooxml::LN_CT_FramePr_wrap:
5365 2 : oWrap = nValue;
5366 2 : break;
5367 : default:
5368 0 : break;
5369 : }
5370 155 : }
5371 :
5372 27 : RTFSprms RTFFrame::getSprms()
5373 : {
5374 27 : RTFSprms sprms;
5375 :
5376 : static const Id pNames[] =
5377 : {
5378 : NS_ooxml::LN_CT_FramePr_x,
5379 : NS_ooxml::LN_CT_FramePr_y,
5380 : NS_ooxml::LN_CT_FramePr_hRule, // Make sure nHRule is processed before nH
5381 : NS_ooxml::LN_CT_FramePr_h,
5382 : NS_ooxml::LN_CT_FramePr_w,
5383 : NS_ooxml::LN_CT_FramePr_hSpace,
5384 : NS_ooxml::LN_CT_FramePr_vSpace,
5385 : NS_ooxml::LN_CT_FramePr_hAnchor,
5386 : NS_ooxml::LN_CT_FramePr_vAnchor,
5387 : NS_ooxml::LN_CT_FramePr_xAlign,
5388 : NS_ooxml::LN_CT_FramePr_yAlign,
5389 : NS_ooxml::LN_CT_FramePr_wrap,
5390 : NS_ooxml::LN_CT_FramePr_dropCap,
5391 : NS_ooxml::LN_CT_FramePr_lines
5392 : };
5393 :
5394 405 : for ( int i = 0, len = SAL_N_ELEMENTS(pNames); i < len; ++i )
5395 : {
5396 378 : Id nId = pNames[i];
5397 378 : RTFValue::Pointer_t pValue;
5398 :
5399 378 : switch ( nId )
5400 : {
5401 : case NS_ooxml::LN_CT_FramePr_x:
5402 27 : if ( nX != 0 )
5403 27 : pValue.reset(new RTFValue(nX));
5404 27 : break;
5405 : case NS_ooxml::LN_CT_FramePr_y:
5406 27 : if ( nY != 0 )
5407 27 : pValue.reset(new RTFValue(nY));
5408 27 : break;
5409 : case NS_ooxml::LN_CT_FramePr_h:
5410 27 : if ( nH != 0 )
5411 : {
5412 25 : if (nHRule == NS_ooxml::LN_Value_wordprocessingml_ST_HeightRule_exact)
5413 24 : pValue.reset(new RTFValue(-nH)); // The negative value just sets nHRule
5414 : else
5415 1 : pValue.reset(new RTFValue(nH));
5416 : }
5417 27 : break;
5418 : case NS_ooxml::LN_CT_FramePr_w:
5419 27 : if ( nW != 0 )
5420 27 : pValue.reset(new RTFValue(nW));
5421 27 : break;
5422 : case NS_ooxml::LN_CT_FramePr_hSpace:
5423 27 : if ( nHoriPadding != 0 )
5424 2 : pValue.reset(new RTFValue(nHoriPadding));
5425 27 : break;
5426 : case NS_ooxml::LN_CT_FramePr_vSpace:
5427 27 : if ( nVertPadding != 0 )
5428 2 : pValue.reset(new RTFValue(nVertPadding));
5429 27 : break;
5430 : case NS_ooxml::LN_CT_FramePr_hAnchor:
5431 : {
5432 27 : if ( nHoriAnchor == 0 )
5433 2 : nHoriAnchor = NS_ooxml::LN_Value_wordprocessingml_ST_HAnchor_margin;
5434 27 : pValue.reset(new RTFValue(nHoriAnchor));
5435 : }
5436 27 : break;
5437 : case NS_ooxml::LN_CT_FramePr_vAnchor:
5438 : {
5439 27 : if ( nVertAnchor == 0 )
5440 1 : nVertAnchor = NS_ooxml::LN_Value_wordprocessingml_ST_VAnchor_margin;
5441 27 : pValue.reset(new RTFValue(nVertAnchor));
5442 : }
5443 27 : break;
5444 : case NS_ooxml::LN_CT_FramePr_xAlign:
5445 27 : pValue.reset(new RTFValue(nHoriAlign));
5446 27 : break;
5447 : case NS_ooxml::LN_CT_FramePr_yAlign:
5448 27 : pValue.reset(new RTFValue(nVertAlign));
5449 27 : break;
5450 : case NS_ooxml::LN_CT_FramePr_hRule:
5451 : {
5452 27 : if ( nH < 0 )
5453 24 : nHRule = NS_ooxml::LN_Value_wordprocessingml_ST_HeightRule_exact;
5454 3 : else if ( nH > 0 )
5455 1 : nHRule = NS_ooxml::LN_Value_wordprocessingml_ST_HeightRule_atLeast;
5456 27 : pValue.reset(new RTFValue(nHRule));
5457 : }
5458 27 : break;
5459 : case NS_ooxml::LN_CT_FramePr_wrap:
5460 27 : if (oWrap)
5461 2 : pValue.reset(new RTFValue(*oWrap));
5462 27 : break;
5463 : default:
5464 54 : break;
5465 : }
5466 :
5467 378 : if (pValue.get())
5468 247 : sprms.set(nId, pValue);
5469 378 : }
5470 :
5471 27 : RTFSprms frameprSprms;
5472 54 : RTFValue::Pointer_t pFrameprValue(new RTFValue(sprms));
5473 27 : frameprSprms.set(NS_ooxml::LN_CT_PPrBase_framePr, pFrameprValue);
5474 :
5475 54 : return frameprSprms;
5476 : }
5477 :
5478 1370 : bool RTFFrame::hasProperties()
5479 : {
5480 4002 : return nX != 0 || nY != 0 || nW != 0 || nH != 0 ||
5481 3948 : nHoriPadding != 0 || nVertPadding != 0 ||
5482 5318 : nHoriAlign != 0 || nHoriAnchor != 0 || nVertAlign != 0 || nVertAnchor != 0 ||
5483 2686 : nAnchorType != 0;
5484 : }
5485 :
5486 : } // namespace rtftok
5487 42 : } // namespace writerfilter
5488 :
5489 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|