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