File: | home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx |
Warning: | line 103, column 19 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 "rtfdocumentimpl.hxx" | ||||
11 | #include <algorithm> | ||||
12 | #include <memory> | ||||
13 | #include <com/sun/star/embed/XEmbeddedObject.hpp> | ||||
14 | #include <com/sun/star/beans/PropertyAttribute.hpp> | ||||
15 | #include <com/sun/star/io/WrongFormatException.hpp> | ||||
16 | #include <com/sun/star/lang/XServiceInfo.hpp> | ||||
17 | #include <com/sun/star/lang/XMultiServiceFactory.hpp> | ||||
18 | #include <com/sun/star/text/TextContentAnchorType.hpp> | ||||
19 | #include <i18nlangtag/languagetag.hxx> | ||||
20 | #include <unotools/ucbstreamhelper.hxx> | ||||
21 | #include <unotools/streamwrap.hxx> | ||||
22 | #include <com/sun/star/drawing/XDrawPageSupplier.hpp> | ||||
23 | #include <filter/msfilter/util.hxx> | ||||
24 | #include <filter/msfilter/rtfutil.hxx> | ||||
25 | #include <comphelper/string.hxx> | ||||
26 | #include <tools/diagnose_ex.h> | ||||
27 | #include <tools/globname.hxx> | ||||
28 | #include <tools/datetimeutils.hxx> | ||||
29 | #include <comphelper/classids.hxx> | ||||
30 | #include <comphelper/embeddedobjectcontainer.hxx> | ||||
31 | #include <svl/lngmisc.hxx> | ||||
32 | #include <sfx2/sfxbasemodel.hxx> | ||||
33 | #include <sfx2/classificationhelper.hxx> | ||||
34 | #include <oox/mathml/import.hxx> | ||||
35 | #include <ooxml/resourceids.hxx> | ||||
36 | #include <oox/token/namespaces.hxx> | ||||
37 | #include <oox/drawingml/drawingmltypes.hxx> | ||||
38 | #include <rtl/uri.hxx> | ||||
39 | #include <rtl/tencinfo.h> | ||||
40 | #include <sal/log.hxx> | ||||
41 | #include <osl/diagnose.h> | ||||
42 | #include <oox/helper/graphichelper.hxx> | ||||
43 | #include <vcl/wmfexternal.hxx> | ||||
44 | #include <vcl/graph.hxx> | ||||
45 | #include <vcl/settings.hxx> | ||||
46 | #include <vcl/svapp.hxx> | ||||
47 | #include "rtfsdrimport.hxx" | ||||
48 | #include "rtfreferenceproperties.hxx" | ||||
49 | #include "rtfskipdestination.hxx" | ||||
50 | #include "rtftokenizer.hxx" | ||||
51 | #include "rtflookahead.hxx" | ||||
52 | |||||
53 | using namespace com::sun::star; | ||||
54 | |||||
55 | namespace | ||||
56 | { | ||||
57 | /// Returns an util::DateTime from a 'YYYY. MM. DD.' string. | ||||
58 | util::DateTime getDateTimeFromUserProp(const OUString& rString) | ||||
59 | { | ||||
60 | util::DateTime aRet; | ||||
61 | sal_Int32 nLen = rString.getLength(); | ||||
62 | if (nLen >= 4) | ||||
63 | { | ||||
64 | aRet.Year = rString.copy(0, 4).toInt32(); | ||||
65 | |||||
66 | if (nLen >= 8 && rString.match(". ", 4)) | ||||
67 | { | ||||
68 | aRet.Month = rString.copy(6, 2).toInt32(); | ||||
69 | |||||
70 | if (nLen >= 12 && rString.match(". ", 8)) | ||||
71 | aRet.Day = rString.copy(10, 2).toInt32(); | ||||
72 | } | ||||
73 | } | ||||
74 | return aRet; | ||||
75 | } | ||||
76 | } // anonymous namespace | ||||
77 | |||||
78 | namespace writerfilter::rtftok | ||||
79 | { | ||||
80 | Id getParagraphBorder(sal_uInt32 nIndex) | ||||
81 | { | ||||
82 | static const Id aBorderIds[] = { NS_ooxml::LN_CT_PBdr_top, NS_ooxml::LN_CT_PBdr_left, | ||||
83 | NS_ooxml::LN_CT_PBdr_bottom, NS_ooxml::LN_CT_PBdr_right }; | ||||
84 | |||||
85 | return aBorderIds[nIndex]; | ||||
86 | } | ||||
87 | |||||
88 | void putNestedAttribute(RTFSprms& rSprms, Id nParent, Id nId, const RTFValue::Pointer_t& pValue, | ||||
89 | RTFOverwrite eOverwrite, bool bAttribute) | ||||
90 | { | ||||
91 | RTFValue::Pointer_t pParent = rSprms.find(nParent, /*bFirst=*/true, /*bForWrite=*/true); | ||||
92 | if (!pParent) | ||||
93 | { | ||||
94 | RTFSprms aAttributes; | ||||
95 | if (nParent
| ||||
96 | { | ||||
97 | // RTF default is 'auto', see writerfilter::dmapper::CellColorHandler | ||||
98 | aAttributes.set(NS_ooxml::LN_CT_Shd_color, new RTFValue(sal_uInt32(COL_AUTO))); | ||||
99 | aAttributes.set(NS_ooxml::LN_CT_Shd_fill, new RTFValue(sal_uInt32(COL_AUTO))); | ||||
100 | } | ||||
101 | auto pParentValue = new RTFValue(aAttributes); | ||||
102 | rSprms.set(nParent, pParentValue, eOverwrite); | ||||
103 | pParent = pParentValue; | ||||
| |||||
104 | } | ||||
105 | RTFSprms& rAttributes = (bAttribute ? pParent->getAttributes() : pParent->getSprms()); | ||||
106 | rAttributes.set(nId, pValue, eOverwrite); | ||||
107 | } | ||||
108 | |||||
109 | void putNestedSprm(RTFSprms& rSprms, Id nParent, Id nId, const RTFValue::Pointer_t& pValue, | ||||
110 | RTFOverwrite eOverwrite) | ||||
111 | { | ||||
112 | putNestedAttribute(rSprms, nParent, nId, pValue, eOverwrite, false); | ||||
113 | } | ||||
114 | |||||
115 | RTFValue::Pointer_t getNestedAttribute(RTFSprms& rSprms, Id nParent, Id nId) | ||||
116 | { | ||||
117 | RTFValue::Pointer_t pParent = rSprms.find(nParent); | ||||
118 | if (!pParent) | ||||
119 | return RTFValue::Pointer_t(); | ||||
120 | RTFSprms& rAttributes = pParent->getAttributes(); | ||||
121 | return rAttributes.find(nId); | ||||
122 | } | ||||
123 | |||||
124 | RTFValue::Pointer_t getNestedSprm(RTFSprms& rSprms, Id nParent, Id nId) | ||||
125 | { | ||||
126 | RTFValue::Pointer_t pParent = rSprms.find(nParent); | ||||
127 | if (!pParent) | ||||
128 | return RTFValue::Pointer_t(); | ||||
129 | RTFSprms& rInner = pParent->getSprms(); | ||||
130 | return rInner.find(nId); | ||||
131 | } | ||||
132 | |||||
133 | bool eraseNestedAttribute(RTFSprms& rSprms, Id nParent, Id nId) | ||||
134 | { | ||||
135 | RTFValue::Pointer_t pParent = rSprms.find(nParent); | ||||
136 | if (!pParent) | ||||
137 | // It doesn't even have a parent, we're done. | ||||
138 | return false; | ||||
139 | RTFSprms& rAttributes = pParent->getAttributes(); | ||||
140 | return rAttributes.erase(nId); | ||||
141 | } | ||||
142 | |||||
143 | RTFSprms& getLastAttributes(RTFSprms& rSprms, Id nId) | ||||
144 | { | ||||
145 | RTFValue::Pointer_t p = rSprms.find(nId); | ||||
146 | if (p && !p->getSprms().empty()) | ||||
147 | return p->getSprms().back().second->getAttributes(); | ||||
148 | |||||
149 | SAL_WARN("writerfilter.rtf", "trying to set property when no type is defined")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN , "writerfilter.rtf")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "trying to set property when no type is defined" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "149" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "trying to set property when no type is defined" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "trying to set property when no type is defined"; :: sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "149" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "trying to set property when no type is defined") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "149" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "trying to set property when no type is defined" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "trying to set property when no type is defined"; :: sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "149" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||
150 | return rSprms; | ||||
151 | } | ||||
152 | |||||
153 | void putBorderProperty(RTFStack& aStates, Id nId, const RTFValue::Pointer_t& pValue) | ||||
154 | { | ||||
155 | RTFSprms* pAttributes = nullptr; | ||||
156 | if (aStates.top().getBorderState() == RTFBorderState::PARAGRAPH_BOX) | ||||
157 | for (int i = 0; i < 4; i++) | ||||
158 | { | ||||
159 | RTFValue::Pointer_t p = aStates.top().getParagraphSprms().find(getParagraphBorder(i)); | ||||
160 | if (p) | ||||
161 | { | ||||
162 | RTFSprms& rAttributes = p->getAttributes(); | ||||
163 | rAttributes.set(nId, pValue); | ||||
164 | } | ||||
165 | } | ||||
166 | else if (aStates.top().getBorderState() == RTFBorderState::CHARACTER) | ||||
167 | { | ||||
168 | RTFValue::Pointer_t pPointer | ||||
169 | = aStates.top().getCharacterSprms().find(NS_ooxml::LN_EG_RPrBase_bdr); | ||||
170 | if (pPointer) | ||||
171 | { | ||||
172 | RTFSprms& rAttributes = pPointer->getAttributes(); | ||||
173 | rAttributes.set(nId, pValue); | ||||
174 | } | ||||
175 | } | ||||
176 | // Attributes of the last border type | ||||
177 | else if (aStates.top().getBorderState() == RTFBorderState::PARAGRAPH) | ||||
178 | pAttributes | ||||
179 | = &getLastAttributes(aStates.top().getParagraphSprms(), NS_ooxml::LN_CT_PrBase_pBdr); | ||||
180 | else if (aStates.top().getBorderState() == RTFBorderState::CELL) | ||||
181 | pAttributes = &getLastAttributes(aStates.top().getTableCellSprms(), | ||||
182 | NS_ooxml::LN_CT_TcPrBase_tcBorders); | ||||
183 | else if (aStates.top().getBorderState() == RTFBorderState::PAGE) | ||||
184 | pAttributes = &getLastAttributes(aStates.top().getSectionSprms(), | ||||
185 | NS_ooxml::LN_EG_SectPrContents_pgBorders); | ||||
186 | if (pAttributes) | ||||
187 | pAttributes->set(nId, pValue); | ||||
188 | } | ||||
189 | |||||
190 | OString DTTM22OString(long nDTTM) | ||||
191 | { | ||||
192 | return DateTimeToOString(msfilter::util::DTTM2DateTime(nDTTM)); | ||||
193 | } | ||||
194 | |||||
195 | static RTFSprms lcl_getBookmarkProperties(int nPos, const OUString& rString) | ||||
196 | { | ||||
197 | RTFSprms aAttributes; | ||||
198 | auto pPos = new RTFValue(nPos); | ||||
199 | if (!rString.isEmpty()) | ||||
200 | { | ||||
201 | // If present, this should be sent first. | ||||
202 | auto pString = new RTFValue(rString); | ||||
203 | aAttributes.set(NS_ooxml::LN_CT_Bookmark_name, pString); | ||||
204 | } | ||||
205 | aAttributes.set(NS_ooxml::LN_CT_MarkupRangeBookmark_id, pPos); | ||||
206 | return aAttributes; | ||||
207 | } | ||||
208 | |||||
209 | const char* keywordToString(RTFKeyword nKeyword) | ||||
210 | { | ||||
211 | for (int i = 0; i < nRTFControlWords; i++) | ||||
212 | { | ||||
213 | if (nKeyword == aRTFControlWords[i].GetIndex()) | ||||
214 | return aRTFControlWords[i].GetKeyword(); | ||||
215 | } | ||||
216 | return nullptr; | ||||
217 | } | ||||
218 | |||||
219 | static util::DateTime lcl_getDateTime(RTFParserState const& aState) | ||||
220 | { | ||||
221 | return { 0 /*100sec*/, | ||||
222 | 0 /*sec*/, | ||||
223 | aState.getMinute(), | ||||
224 | aState.getHour(), | ||||
225 | aState.getDay(), | ||||
226 | aState.getMonth(), | ||||
227 | static_cast<sal_Int16>(aState.getYear()), | ||||
228 | false }; | ||||
229 | } | ||||
230 | |||||
231 | static void lcl_DestinationToMath(OUStringBuffer* pDestinationText, | ||||
232 | oox::formulaimport::XmlStreamBuilder& rMathBuffer, bool& rMathNor) | ||||
233 | { | ||||
234 | if (!pDestinationText) | ||||
235 | return; | ||||
236 | OUString aStr = pDestinationText->makeStringAndClear(); | ||||
237 | if (aStr.isEmpty()) | ||||
238 | return; | ||||
239 | rMathBuffer.appendOpeningTag(M_TOKEN(r)(::oox::NMSP_officeMath | ::oox::XML_r)); | ||||
240 | if (rMathNor) | ||||
241 | { | ||||
242 | rMathBuffer.appendOpeningTag(M_TOKEN(rPr)(::oox::NMSP_officeMath | ::oox::XML_rPr)); | ||||
243 | // Same as M_TOKEN(lit) | ||||
244 | rMathBuffer.appendOpeningTag(M_TOKEN(nor)(::oox::NMSP_officeMath | ::oox::XML_nor)); | ||||
245 | rMathBuffer.appendClosingTag(M_TOKEN(nor)(::oox::NMSP_officeMath | ::oox::XML_nor)); | ||||
246 | rMathBuffer.appendClosingTag(M_TOKEN(rPr)(::oox::NMSP_officeMath | ::oox::XML_rPr)); | ||||
247 | rMathNor = false; | ||||
248 | } | ||||
249 | rMathBuffer.appendOpeningTag(M_TOKEN(t)(::oox::NMSP_officeMath | ::oox::XML_t)); | ||||
250 | rMathBuffer.appendCharacters(aStr); | ||||
251 | rMathBuffer.appendClosingTag(M_TOKEN(t)(::oox::NMSP_officeMath | ::oox::XML_t)); | ||||
252 | rMathBuffer.appendClosingTag(M_TOKEN(r)(::oox::NMSP_officeMath | ::oox::XML_r)); | ||||
253 | } | ||||
254 | |||||
255 | RTFDocumentImpl::RTFDocumentImpl(uno::Reference<uno::XComponentContext> const& xContext, | ||||
256 | uno::Reference<io::XInputStream> const& xInputStream, | ||||
257 | uno::Reference<lang::XComponent> const& xDstDoc, | ||||
258 | uno::Reference<frame::XFrame> const& xFrame, | ||||
259 | uno::Reference<task::XStatusIndicator> const& xStatusIndicator, | ||||
260 | const utl::MediaDescriptor& rMediaDescriptor) | ||||
261 | : m_xContext(xContext) | ||||
262 | , m_xInputStream(xInputStream) | ||||
263 | , m_xDstDoc(xDstDoc) | ||||
264 | , m_xFrame(xFrame) | ||||
265 | , m_xStatusIndicator(xStatusIndicator) | ||||
266 | , m_pMapperStream(nullptr) | ||||
267 | , m_aDefaultState(this) | ||||
268 | , m_bSkipUnknown(false) | ||||
269 | , m_bFirstRun(true) | ||||
270 | , m_bFirstRunException(false) | ||||
271 | , m_bNeedPap(true) | ||||
272 | , m_bNeedCr(false) | ||||
273 | , m_bNeedCrOrig(false) | ||||
274 | , m_bNeedPar(true) | ||||
275 | , m_bNeedFinalPar(false) | ||||
276 | , m_nNestedCells(0) | ||||
277 | , m_nTopLevelCells(0) | ||||
278 | , m_nInheritingCells(0) | ||||
279 | , m_nNestedTRLeft(0) | ||||
280 | , m_nTopLevelTRLeft(0) | ||||
281 | , m_nNestedCurrentCellX(0) | ||||
282 | , m_nTopLevelCurrentCellX(0) | ||||
283 | , m_nBackupTopLevelCurrentCellX(0) | ||||
284 | , m_aTableBufferStack(1) // create top-level buffer already | ||||
285 | , m_pSuperstream(nullptr) | ||||
286 | , m_nStreamType(0) | ||||
287 | , m_nGroupStartPos(0) | ||||
288 | , m_nFormFieldType(RTFFormFieldType::NONE) | ||||
289 | , m_bObject(false) | ||||
290 | , m_nCurrentFontIndex(0) | ||||
291 | , m_nCurrentEncoding(-1) | ||||
292 | , m_nDefaultFontIndex(-1) | ||||
293 | , m_nCurrentStyleIndex(0) | ||||
294 | , m_bFormField(false) | ||||
295 | , m_bMathNor(false) | ||||
296 | , m_bIgnoreNextContSectBreak(false) | ||||
297 | , m_nResetBreakOnSectBreak(RTF_invalid) | ||||
298 | , m_bNeedSect(false) // done by checkFirstRun | ||||
299 | , m_bWasInFrame(false) | ||||
300 | , m_bHadPicture(false) | ||||
301 | , m_bHadSect(false) | ||||
302 | , m_nCellxMax(0) | ||||
303 | , m_nListPictureId(0) | ||||
304 | , m_bIsNewDoc(!rMediaDescriptor.getUnpackedValueOrDefault("InsertMode", false)) | ||||
305 | , m_rMediaDescriptor(rMediaDescriptor) | ||||
306 | , m_hasRHeader(false) | ||||
307 | , m_hasFHeader(false) | ||||
308 | , m_hasRFooter(false) | ||||
309 | , m_hasFFooter(false) | ||||
310 | , m_bAfterCellBeforeRow(false) | ||||
311 | { | ||||
312 | OSL_ASSERT(xInputStream.is())do { if (true && (!(xInputStream.is()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "312" ": "), "OSL_ASSERT: %s", "xInputStream.is()"); } } while (false); | ||||
313 | m_pInStream = utl::UcbStreamHelper::CreateStream(xInputStream, true); | ||||
314 | |||||
315 | m_xModelFactory.set(m_xDstDoc, uno::UNO_QUERY); | ||||
316 | |||||
317 | uno::Reference<document::XDocumentPropertiesSupplier> xDocumentPropertiesSupplier( | ||||
318 | m_xDstDoc, uno::UNO_QUERY); | ||||
319 | if (xDocumentPropertiesSupplier.is()) | ||||
320 | m_xDocumentProperties = xDocumentPropertiesSupplier->getDocumentProperties(); | ||||
321 | |||||
322 | m_pGraphicHelper = std::make_shared<oox::GraphicHelper>(m_xContext, xFrame, oox::StorageRef()); | ||||
323 | |||||
324 | m_pTokenizer = new RTFTokenizer(*this, m_pInStream.get(), m_xStatusIndicator); | ||||
325 | m_pSdrImport = new RTFSdrImport(*this, m_xDstDoc); | ||||
326 | } | ||||
327 | |||||
328 | RTFDocumentImpl::~RTFDocumentImpl() = default; | ||||
329 | |||||
330 | SvStream& RTFDocumentImpl::Strm() { return *m_pInStream; } | ||||
331 | |||||
332 | void RTFDocumentImpl::setSuperstream(RTFDocumentImpl* pSuperstream) | ||||
333 | { | ||||
334 | m_pSuperstream = pSuperstream; | ||||
335 | } | ||||
336 | |||||
337 | bool RTFDocumentImpl::isSubstream() const { return m_pSuperstream != nullptr; } | ||||
338 | |||||
339 | void RTFDocumentImpl::finishSubstream() { checkUnicode(/*bUnicode =*/true, /*bHex =*/true); } | ||||
340 | |||||
341 | void RTFDocumentImpl::resolveSubstream(std::size_t nPos, Id nId) | ||||
342 | { | ||||
343 | resolveSubstream(nPos, nId, OUString()); | ||||
344 | } | ||||
345 | void RTFDocumentImpl::resolveSubstream(std::size_t nPos, Id nId, OUString const& rIgnoreFirst) | ||||
346 | { | ||||
347 | sal_uInt64 const nCurrent = Strm().Tell(); | ||||
348 | // Seek to header position, parse, then seek back. | ||||
349 | auto pImpl = new RTFDocumentImpl(m_xContext, m_xInputStream, m_xDstDoc, m_xFrame, | ||||
350 | m_xStatusIndicator, m_rMediaDescriptor); | ||||
351 | pImpl->setSuperstream(this); | ||||
352 | pImpl->m_nStreamType = nId; | ||||
353 | pImpl->m_aIgnoreFirst = rIgnoreFirst; | ||||
354 | if (!m_aAuthor.isEmpty()) | ||||
355 | { | ||||
356 | pImpl->m_aAuthor = m_aAuthor; | ||||
357 | m_aAuthor.clear(); | ||||
358 | } | ||||
359 | if (!m_aAuthorInitials.isEmpty()) | ||||
360 | { | ||||
361 | pImpl->m_aAuthorInitials = m_aAuthorInitials; | ||||
362 | m_aAuthorInitials.clear(); | ||||
363 | } | ||||
364 | pImpl->m_nDefaultFontIndex = m_nDefaultFontIndex; | ||||
365 | pImpl->Strm().Seek(nPos); | ||||
366 | SAL_INFO("writerfilter.rtf", "substream start")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO , "writerfilter.rtf")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "substream start") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "366" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "substream start"), 0); } else { ::std ::ostringstream sal_detail_stream; sal_detail_stream << "substream start"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "366" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "substream start") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "366" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "substream start"), 0); } else { ::std ::ostringstream sal_detail_stream; sal_detail_stream << "substream start"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "366" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||
367 | Mapper().substream(nId, pImpl); | ||||
368 | SAL_INFO("writerfilter.rtf", "substream end")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO , "writerfilter.rtf")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "substream end") == 1 ) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "368" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "substream end"), 0); } else { ::std:: ostringstream sal_detail_stream; sal_detail_stream << "substream end" ; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "368" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "substream end") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "368" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "substream end"), 0); } else { ::std:: ostringstream sal_detail_stream; sal_detail_stream << "substream end" ; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "368" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||
369 | Strm().Seek(nCurrent); | ||||
370 | } | ||||
371 | |||||
372 | void RTFDocumentImpl::outputSettingsTable() | ||||
373 | { | ||||
374 | writerfilter::Reference<Properties>::Pointer_t pProp | ||||
375 | = new RTFReferenceProperties(m_aSettingsTableAttributes, m_aSettingsTableSprms); | ||||
376 | RTFReferenceTable::Entries_t aSettingsTableEntries; | ||||
377 | aSettingsTableEntries.insert(std::make_pair(0, pProp)); | ||||
378 | writerfilter::Reference<Table>::Pointer_t pTable = new RTFReferenceTable(aSettingsTableEntries); | ||||
379 | Mapper().table(NS_ooxml::LN_settings_settings, pTable); | ||||
380 | } | ||||
381 | |||||
382 | void RTFDocumentImpl::checkFirstRun() | ||||
383 | { | ||||
384 | if (!m_bFirstRun) | ||||
385 | return; | ||||
386 | |||||
387 | outputSettingsTable(); | ||||
388 | // start initial paragraph | ||||
389 | m_bFirstRun = false; | ||||
390 | assert(!m_bNeedSect || m_bFirstRunException)(static_cast <bool> (!m_bNeedSect || m_bFirstRunException ) ? void (0) : __assert_fail ("!m_bNeedSect || m_bFirstRunException" , "/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" , 390, __extension__ __PRETTY_FUNCTION__)); | ||||
391 | setNeedSect(true); // first call that succeeds | ||||
392 | |||||
393 | // set the requested default font, if there are none | ||||
394 | RTFValue::Pointer_t pFont | ||||
395 | = getNestedAttribute(m_aDefaultState.getCharacterSprms(), NS_ooxml::LN_EG_RPrBase_rFonts, | ||||
396 | NS_ooxml::LN_CT_Fonts_ascii); | ||||
397 | RTFValue::Pointer_t pCurrentFont | ||||
398 | = getNestedAttribute(m_aStates.top().getCharacterSprms(), NS_ooxml::LN_EG_RPrBase_rFonts, | ||||
399 | NS_ooxml::LN_CT_Fonts_ascii); | ||||
400 | if (pFont && !pCurrentFont) | ||||
401 | putNestedAttribute(m_aStates.top().getCharacterSprms(), NS_ooxml::LN_EG_RPrBase_rFonts, | ||||
402 | NS_ooxml::LN_CT_Fonts_ascii, pFont); | ||||
403 | } | ||||
404 | |||||
405 | void RTFDocumentImpl::setNeedPar(bool bNeedPar) { m_bNeedPar = bNeedPar; } | ||||
406 | |||||
407 | void RTFDocumentImpl::setNeedSect(bool bNeedSect) | ||||
408 | { | ||||
409 | if (!m_bNeedSect && bNeedSect && m_bFirstRun) | ||||
410 | { | ||||
411 | RTFLookahead aLookahead(Strm(), m_pTokenizer->getGroupStart()); | ||||
412 | if (aLookahead.hasTable() && aLookahead.hasColumns()) | ||||
413 | { | ||||
414 | m_bFirstRunException = true; | ||||
415 | } | ||||
416 | } | ||||
417 | |||||
418 | // ignore setting before checkFirstRun - every keyword calls setNeedSect! | ||||
419 | // except the case of a table in a multicolumn section | ||||
420 | if (!m_bNeedSect && bNeedSect && (!m_bFirstRun || m_bFirstRunException)) | ||||
421 | { | ||||
422 | if (!m_pSuperstream) // no sections in header/footer! | ||||
423 | { | ||||
424 | Mapper().startSectionGroup(); | ||||
425 | } | ||||
426 | // set flag in substream too - otherwise multiple startParagraphGroup | ||||
427 | m_bNeedSect = bNeedSect; | ||||
428 | Mapper().startParagraphGroup(); | ||||
429 | setNeedPar(true); | ||||
430 | } | ||||
431 | else if (m_bNeedSect && !bNeedSect) | ||||
432 | { | ||||
433 | m_bNeedSect = bNeedSect; | ||||
434 | } | ||||
435 | } | ||||
436 | |||||
437 | /// Copy rProps to rStyleAttributes and rStyleSprms, but in case of nested sprms, copy their children as toplevel sprms/attributes. | ||||
438 | static void lcl_copyFlatten(RTFReferenceProperties& rProps, RTFSprms& rStyleAttributes, | ||||
439 | RTFSprms& rStyleSprms) | ||||
440 | { | ||||
441 | for (auto& rSprm : rProps.getSprms()) | ||||
442 | { | ||||
443 | // createStyleProperties() puts properties to rPr, but here we need a flat list. | ||||
444 | if (rSprm.first == NS_ooxml::LN_CT_Style_rPr) | ||||
445 | { | ||||
446 | // rPr can have both attributes and SPRMs, copy over both types. | ||||
447 | RTFSprms& rRPrSprms = rSprm.second->getSprms(); | ||||
448 | for (const auto& rRPrSprm : rRPrSprms) | ||||
449 | rStyleSprms.set(rRPrSprm.first, rRPrSprm.second); | ||||
450 | |||||
451 | RTFSprms& rRPrAttributes = rSprm.second->getAttributes(); | ||||
452 | for (const auto& rRPrAttribute : rRPrAttributes) | ||||
453 | rStyleAttributes.set(rRPrAttribute.first, rRPrAttribute.second); | ||||
454 | } | ||||
455 | else | ||||
456 | rStyleSprms.set(rSprm.first, rSprm.second); | ||||
457 | } | ||||
458 | |||||
459 | RTFSprms& rAttributes = rProps.getAttributes(); | ||||
460 | for (const auto& rAttribute : rAttributes) | ||||
461 | rStyleAttributes.set(rAttribute.first, rAttribute.second); | ||||
462 | } | ||||
463 | |||||
464 | writerfilter::Reference<Properties>::Pointer_t | ||||
465 | RTFDocumentImpl::getProperties(const RTFSprms& rAttributes, RTFSprms const& rSprms, Id nStyleType) | ||||
466 | { | ||||
467 | RTFSprms aSprms(rSprms); | ||||
468 | RTFValue::Pointer_t pAbstractList; | ||||
469 | int nAbstractListId = -1; | ||||
470 | RTFValue::Pointer_t pNumId | ||||
471 | = getNestedSprm(aSprms, NS_ooxml::LN_CT_PPrBase_numPr, NS_ooxml::LN_CT_NumPr_numId); | ||||
472 | if (pNumId) | ||||
473 | { | ||||
474 | // We have a numbering, look up the abstract list for property | ||||
475 | // deduplication and duplication. | ||||
476 | auto itNumId = m_aListOverrideTable.find(pNumId->getInt()); | ||||
477 | if (itNumId != m_aListOverrideTable.end()) | ||||
478 | { | ||||
479 | nAbstractListId = itNumId->second; | ||||
480 | auto itAbstract = m_aListTable.find(nAbstractListId); | ||||
481 | if (itAbstract != m_aListTable.end()) | ||||
482 | pAbstractList = itAbstract->second; | ||||
483 | } | ||||
484 | } | ||||
485 | |||||
486 | if (pAbstractList) | ||||
487 | { | ||||
488 | auto it = m_aInvalidListTableFirstIndents.find(nAbstractListId); | ||||
489 | if (it != m_aInvalidListTableFirstIndents.end()) | ||||
490 | aSprms.deduplicateList(it->second); | ||||
491 | } | ||||
492 | |||||
493 | int nStyle = 0; | ||||
494 | if (!m_aStates.empty()) | ||||
495 | nStyle = m_aStates.top().getCurrentStyleIndex(); | ||||
496 | auto it = m_aStyleTableEntries.find(nStyle); | ||||
497 | if (it != m_aStyleTableEntries.end()) | ||||
498 | { | ||||
499 | // cloneAndDeduplicate() wants to know about only a single "style", so | ||||
500 | // let's merge paragraph and character style properties here. | ||||
501 | auto itChar = m_aStyleTableEntries.end(); | ||||
502 | if (!m_aStates.empty()) | ||||
503 | { | ||||
504 | int nCharStyle = m_aStates.top().getCurrentCharacterStyleIndex(); | ||||
505 | itChar = m_aStyleTableEntries.find(nCharStyle); | ||||
506 | } | ||||
507 | |||||
508 | RTFSprms aStyleSprms; | ||||
509 | RTFSprms aStyleAttributes; | ||||
510 | // Ensure the paragraph style is a flat list. | ||||
511 | // Take paragraph style into account for character properties as well, | ||||
512 | // as paragraph style may contain character properties. | ||||
513 | RTFReferenceProperties& rProps = *static_cast<RTFReferenceProperties*>(it->second.get()); | ||||
514 | lcl_copyFlatten(rProps, aStyleAttributes, aStyleSprms); | ||||
515 | |||||
516 | if (itChar != m_aStyleTableEntries.end()) | ||||
517 | { | ||||
518 | // Found active character style, then update aStyleSprms/Attributes. | ||||
519 | if (!nStyleType || nStyleType == NS_ooxml::LN_Value_ST_StyleType_character) | ||||
520 | { | ||||
521 | RTFReferenceProperties& rCharProps | ||||
522 | = *static_cast<RTFReferenceProperties*>(itChar->second.get()); | ||||
523 | lcl_copyFlatten(rCharProps, aStyleAttributes, aStyleSprms); | ||||
524 | } | ||||
525 | } | ||||
526 | |||||
527 | // Get rid of direct formatting what is already in the style. | ||||
528 | RTFSprms const sprms(aSprms.cloneAndDeduplicate(aStyleSprms, nStyleType, true)); | ||||
529 | RTFSprms const attributes( | ||||
530 | rAttributes.cloneAndDeduplicate(aStyleAttributes, nStyleType, true)); | ||||
531 | return new RTFReferenceProperties(attributes, sprms); | ||||
532 | } | ||||
533 | |||||
534 | if (pAbstractList) | ||||
535 | aSprms.duplicateList(pAbstractList); | ||||
536 | writerfilter::Reference<Properties>::Pointer_t pRet | ||||
537 | = new RTFReferenceProperties(rAttributes, aSprms); | ||||
538 | return pRet; | ||||
539 | } | ||||
540 | |||||
541 | void RTFDocumentImpl::checkNeedPap() | ||||
542 | { | ||||
543 | if (!m_bNeedPap) | ||||
544 | return; | ||||
545 | |||||
546 | m_bNeedPap = false; // reset early, so we can avoid recursion when calling ourselves | ||||
547 | |||||
548 | if (m_aStates.empty()) | ||||
549 | return; | ||||
550 | |||||
551 | if (!m_aStates.top().getCurrentBuffer()) | ||||
552 | { | ||||
553 | writerfilter::Reference<Properties>::Pointer_t const pParagraphProperties(getProperties( | ||||
554 | m_aStates.top().getParagraphAttributes(), m_aStates.top().getParagraphSprms(), | ||||
555 | NS_ooxml::LN_Value_ST_StyleType_paragraph)); | ||||
556 | |||||
557 | // Writer will ignore a page break before a text frame, so guard it with empty paragraphs | ||||
558 | bool hasBreakBeforeFrame | ||||
559 | = m_aStates.top().getFrame().hasProperties() | ||||
560 | && m_aStates.top().getParagraphSprms().find(NS_ooxml::LN_CT_PPrBase_pageBreakBefore); | ||||
561 | if (hasBreakBeforeFrame) | ||||
562 | { | ||||
563 | dispatchSymbol(RTF_PAR); | ||||
564 | m_bNeedPap = false; | ||||
565 | } | ||||
566 | Mapper().props(pParagraphProperties); | ||||
567 | if (hasBreakBeforeFrame) | ||||
568 | dispatchSymbol(RTF_PAR); | ||||
569 | |||||
570 | if (m_aStates.top().getFrame().hasProperties()) | ||||
571 | { | ||||
572 | writerfilter::Reference<Properties>::Pointer_t const pFrameProperties( | ||||
573 | new RTFReferenceProperties(RTFSprms(), m_aStates.top().getFrame().getSprms())); | ||||
574 | Mapper().props(pFrameProperties); | ||||
575 | } | ||||
576 | } | ||||
577 | else | ||||
578 | { | ||||
579 | auto pValue = new RTFValue(m_aStates.top().getParagraphAttributes(), | ||||
580 | m_aStates.top().getParagraphSprms()); | ||||
581 | bufferProperties(*m_aStates.top().getCurrentBuffer(), pValue, nullptr); | ||||
582 | } | ||||
583 | } | ||||
584 | |||||
585 | void RTFDocumentImpl::runProps() | ||||
586 | { | ||||
587 | if (!m_aStates.top().getCurrentBuffer()) | ||||
588 | { | ||||
589 | Reference<Properties>::Pointer_t const pProperties = getProperties( | ||||
590 | m_aStates.top().getCharacterAttributes(), m_aStates.top().getCharacterSprms(), | ||||
591 | NS_ooxml::LN_Value_ST_StyleType_character); | ||||
592 | Mapper().props(pProperties); | ||||
593 | } | ||||
594 | else | ||||
595 | { | ||||
596 | auto pValue = new RTFValue(m_aStates.top().getCharacterAttributes(), | ||||
597 | m_aStates.top().getCharacterSprms()); | ||||
598 | bufferProperties(*m_aStates.top().getCurrentBuffer(), pValue, nullptr); | ||||
599 | } | ||||
600 | |||||
601 | // Delete the sprm, so the trackchange range will be started only once. | ||||
602 | // OTOH set a boolean flag, so we'll know we need to end the range later. | ||||
603 | RTFValue::Pointer_t pTrackchange | ||||
604 | = m_aStates.top().getCharacterSprms().find(NS_ooxml::LN_trackchange); | ||||
605 | if (pTrackchange) | ||||
606 | { | ||||
607 | m_aStates.top().setStartedTrackchange(true); | ||||
608 | m_aStates.top().getCharacterSprms().erase(NS_ooxml::LN_trackchange); | ||||
609 | } | ||||
610 | } | ||||
611 | |||||
612 | void RTFDocumentImpl::runBreak() | ||||
613 | { | ||||
614 | sal_uInt8 const sBreak[] = { 0xd }; | ||||
615 | Mapper().text(sBreak, 1); | ||||
616 | m_bNeedCr = false; | ||||
617 | } | ||||
618 | |||||
619 | void RTFDocumentImpl::tableBreak() | ||||
620 | { | ||||
621 | runBreak(); | ||||
622 | Mapper().endParagraphGroup(); | ||||
623 | Mapper().startParagraphGroup(); | ||||
624 | } | ||||
625 | |||||
626 | void RTFDocumentImpl::parBreak() | ||||
627 | { | ||||
628 | checkFirstRun(); | ||||
629 | checkNeedPap(); | ||||
630 | // end previous paragraph | ||||
631 | Mapper().startCharacterGroup(); | ||||
632 | runBreak(); | ||||
633 | Mapper().endCharacterGroup(); | ||||
634 | Mapper().endParagraphGroup(); | ||||
635 | |||||
636 | m_bHadPicture = false; | ||||
637 | |||||
638 | // start new one | ||||
639 | Mapper().startParagraphGroup(); | ||||
640 | } | ||||
641 | |||||
642 | void RTFDocumentImpl::sectBreak(bool bFinal) | ||||
643 | { | ||||
644 | SAL_INFO("writerfilter.rtf", __func__ << ": final? " << bFinal << ", needed? " << m_bNeedSect)do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO , "writerfilter.rtf")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << __func__ << ": final? " << bFinal << ", needed? " << m_bNeedSect) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "644" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << __func__ << ": final? " << bFinal << ", needed? " << m_bNeedSect), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << __func__ << ": final? " << bFinal << ", needed? " << m_bNeedSect; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "644" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << __func__ << ": final? " << bFinal << ", needed? " << m_bNeedSect) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "644" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << __func__ << ": final? " << bFinal << ", needed? " << m_bNeedSect), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << __func__ << ": final? " << bFinal << ", needed? " << m_bNeedSect; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "644" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||
645 | bool bNeedSect = m_bNeedSect; | ||||
646 | RTFValue::Pointer_t pBreak | ||||
647 | = m_aStates.top().getSectionSprms().find(NS_ooxml::LN_EG_SectPrContents_type); | ||||
648 | bool bContinuous | ||||
649 | = pBreak | ||||
650 | && pBreak->getInt() | ||||
651 | == static_cast<sal_Int32>(NS_ooxml::LN_Value_ST_SectionMark_continuous); | ||||
652 | // If there is no paragraph in this section, then insert a dummy one, as required by Writer, | ||||
653 | // unless this is the end of the doc, we had nothing since the last section break and this is not a continuous one. | ||||
654 | // Also, when pasting, it's fine to not have any paragraph inside the document at all. | ||||
655 | if (m_bNeedPar && (!bFinal || m_bNeedSect || bContinuous) && !isSubstream() && m_bIsNewDoc) | ||||
656 | dispatchSymbol(RTF_PAR); | ||||
657 | // It's allowed to not have a non-table paragraph at the end of an RTF doc, add it now if required. | ||||
658 | if (m_bNeedFinalPar && bFinal) | ||||
659 | { | ||||
660 | dispatchFlag(RTF_PARD); | ||||
661 | dispatchSymbol(RTF_PAR); | ||||
662 | m_bNeedSect = bNeedSect; | ||||
663 | } | ||||
664 | while (!m_nHeaderFooterPositions.empty()) | ||||
665 | { | ||||
666 | std::pair<Id, std::size_t> aPair = m_nHeaderFooterPositions.front(); | ||||
667 | m_nHeaderFooterPositions.pop(); | ||||
668 | resolveSubstream(aPair.second, aPair.first); | ||||
669 | } | ||||
670 | |||||
671 | // Normally a section break at the end of the doc is necessary. Unless the | ||||
672 | // last control word in the document is a section break itself. | ||||
673 | if (!bNeedSect || !m_bHadSect) | ||||
674 | { | ||||
675 | // In case the last section is a continuous one, we don't need to output a section break. | ||||
676 | if (bFinal && bContinuous) | ||||
677 | m_aStates.top().getSectionSprms().erase(NS_ooxml::LN_EG_SectPrContents_type); | ||||
678 | } | ||||
679 | |||||
680 | // Section properties are a paragraph sprm. | ||||
681 | auto pValue | ||||
682 | = new RTFValue(m_aStates.top().getSectionAttributes(), m_aStates.top().getSectionSprms()); | ||||
683 | RTFSprms aAttributes; | ||||
684 | RTFSprms aSprms; | ||||
685 | aSprms.set(NS_ooxml::LN_CT_PPr_sectPr, pValue); | ||||
686 | writerfilter::Reference<Properties>::Pointer_t pProperties | ||||
687 | = new RTFReferenceProperties(aAttributes, aSprms); | ||||
688 | |||||
689 | if (bFinal && !m_pSuperstream) | ||||
690 | // This is the end of the document, not just the end of e.g. a header. | ||||
691 | // This makes sure that dmapper can set DontBalanceTextColumns=true for this section if necessary. | ||||
692 | Mapper().markLastSectionGroup(); | ||||
693 | |||||
694 | // The trick is that we send properties of the previous section right now, which will be exactly what dmapper expects. | ||||
695 | Mapper().props(pProperties); | ||||
696 | Mapper().endParagraphGroup(); | ||||
697 | |||||
698 | // End Section | ||||
699 | if (!m_pSuperstream) | ||||
700 | { | ||||
701 | m_hasFHeader = false; | ||||
702 | m_hasRHeader = false; | ||||
703 | m_hasRFooter = false; | ||||
704 | m_hasFFooter = false; | ||||
705 | Mapper().endSectionGroup(); | ||||
706 | } | ||||
707 | m_bNeedPar = false; | ||||
708 | m_bNeedSect = false; | ||||
709 | } | ||||
710 | |||||
711 | Color RTFDocumentImpl::getColorTable(sal_uInt32 nIndex) | ||||
712 | { | ||||
713 | if (!m_pSuperstream) | ||||
714 | { | ||||
715 | if (nIndex < m_aColorTable.size()) | ||||
716 | return m_aColorTable[nIndex]; | ||||
717 | return 0; | ||||
718 | } | ||||
719 | |||||
720 | return m_pSuperstream->getColorTable(nIndex); | ||||
721 | } | ||||
722 | |||||
723 | rtl_TextEncoding RTFDocumentImpl::getEncoding(int nFontIndex) | ||||
724 | { | ||||
725 | if (!m_pSuperstream) | ||||
726 | { | ||||
727 | auto it = m_aFontEncodings.find(nFontIndex); | ||||
728 | if (it != m_aFontEncodings.end()) | ||||
729 | // We have a font encoding associated to this font. | ||||
730 | return it->second; | ||||
731 | if (m_aDefaultState.getCurrentEncoding() != rtl_getTextEncodingFromWindowsCharset(0)) | ||||
732 | // We have a default encoding. | ||||
733 | return m_aDefaultState.getCurrentEncoding(); | ||||
734 | // Guess based on locale. | ||||
735 | return msfilter::util::getBestTextEncodingFromLocale( | ||||
736 | Application::GetSettings().GetLanguageTag().getLocale()); | ||||
737 | } | ||||
738 | |||||
739 | return m_pSuperstream->getEncoding(nFontIndex); | ||||
740 | } | ||||
741 | |||||
742 | OUString RTFDocumentImpl::getFontName(int nIndex) | ||||
743 | { | ||||
744 | if (!m_pSuperstream) | ||||
745 | return m_aFontNames[nIndex]; | ||||
746 | |||||
747 | return m_pSuperstream->getFontName(nIndex); | ||||
748 | } | ||||
749 | |||||
750 | int RTFDocumentImpl::getFontIndex(int nIndex) | ||||
751 | { | ||||
752 | if (!m_pSuperstream) | ||||
753 | return std::find(m_aFontIndexes.begin(), m_aFontIndexes.end(), nIndex) | ||||
754 | - m_aFontIndexes.begin(); | ||||
755 | |||||
756 | return m_pSuperstream->getFontIndex(nIndex); | ||||
757 | } | ||||
758 | |||||
759 | OUString RTFDocumentImpl::getStyleName(int nIndex) | ||||
760 | { | ||||
761 | if (!m_pSuperstream) | ||||
762 | { | ||||
763 | OUString aRet; | ||||
764 | if (m_aStyleNames.find(nIndex) != m_aStyleNames.end()) | ||||
765 | aRet = m_aStyleNames[nIndex]; | ||||
766 | return aRet; | ||||
767 | } | ||||
768 | |||||
769 | return m_pSuperstream->getStyleName(nIndex); | ||||
770 | } | ||||
771 | |||||
772 | Id RTFDocumentImpl::getStyleType(int nIndex) | ||||
773 | { | ||||
774 | if (!m_pSuperstream) | ||||
775 | { | ||||
776 | Id nRet = 0; | ||||
777 | if (m_aStyleTypes.find(nIndex) != m_aStyleTypes.end()) | ||||
778 | nRet = m_aStyleTypes[nIndex]; | ||||
779 | return nRet; | ||||
780 | } | ||||
781 | |||||
782 | return m_pSuperstream->getStyleType(nIndex); | ||||
783 | } | ||||
784 | |||||
785 | RTFParserState& RTFDocumentImpl::getDefaultState() | ||||
786 | { | ||||
787 | if (!m_pSuperstream) | ||||
788 | return m_aDefaultState; | ||||
789 | |||||
790 | return m_pSuperstream->getDefaultState(); | ||||
791 | } | ||||
792 | |||||
793 | oox::GraphicHelper& RTFDocumentImpl::getGraphicHelper() { return *m_pGraphicHelper; } | ||||
794 | |||||
795 | bool RTFDocumentImpl::isStyleSheetImport() | ||||
796 | { | ||||
797 | if (m_aStates.empty()) | ||||
798 | return false; | ||||
799 | Destination eDestination = m_aStates.top().getDestination(); | ||||
800 | return eDestination == Destination::STYLESHEET || eDestination == Destination::STYLEENTRY; | ||||
801 | } | ||||
802 | |||||
803 | void RTFDocumentImpl::resolve(Stream& rMapper) | ||||
804 | { | ||||
805 | m_pMapperStream = &rMapper; | ||||
806 | switch (m_pTokenizer->resolveParse()) | ||||
807 | { | ||||
808 | case RTFError::OK: | ||||
809 | SAL_INFO("writerfilter.rtf", "RTFDocumentImpl::resolve: finished without errors")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO , "writerfilter.rtf")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "RTFDocumentImpl::resolve: finished without errors" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "809" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "RTFDocumentImpl::resolve: finished without errors" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "RTFDocumentImpl::resolve: finished without errors" ; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "809" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "RTFDocumentImpl::resolve: finished without errors" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "809" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "RTFDocumentImpl::resolve: finished without errors" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "RTFDocumentImpl::resolve: finished without errors" ; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "809" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||
810 | break; | ||||
811 | case RTFError::GROUP_UNDER: | ||||
812 | SAL_INFO("writerfilter.rtf", "RTFDocumentImpl::resolve: unmatched '}'")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO , "writerfilter.rtf")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "RTFDocumentImpl::resolve: unmatched '}'" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "812" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "RTFDocumentImpl::resolve: unmatched '}'" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "RTFDocumentImpl::resolve: unmatched '}'"; ::sal::detail ::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf"), ( "/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "812" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "RTFDocumentImpl::resolve: unmatched '}'") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "812" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "RTFDocumentImpl::resolve: unmatched '}'" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "RTFDocumentImpl::resolve: unmatched '}'"; ::sal::detail ::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf"), ( "/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "812" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||
813 | break; | ||||
814 | case RTFError::GROUP_OVER: | ||||
815 | SAL_INFO("writerfilter.rtf", "RTFDocumentImpl::resolve: unmatched '{'")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO , "writerfilter.rtf")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "RTFDocumentImpl::resolve: unmatched '{'" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "815" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "RTFDocumentImpl::resolve: unmatched '{'" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "RTFDocumentImpl::resolve: unmatched '{'"; ::sal::detail ::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf"), ( "/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "815" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "RTFDocumentImpl::resolve: unmatched '{'") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "815" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "RTFDocumentImpl::resolve: unmatched '{'" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "RTFDocumentImpl::resolve: unmatched '{'"; ::sal::detail ::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf"), ( "/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "815" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||
816 | throw io::WrongFormatException(m_pTokenizer->getPosition()); | ||||
817 | break; | ||||
818 | case RTFError::UNEXPECTED_EOF: | ||||
819 | SAL_INFO("writerfilter.rtf", "RTFDocumentImpl::resolve: unexpected end of file")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO , "writerfilter.rtf")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "RTFDocumentImpl::resolve: unexpected end of file" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "819" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "RTFDocumentImpl::resolve: unexpected end of file" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "RTFDocumentImpl::resolve: unexpected end of file"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "819" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "RTFDocumentImpl::resolve: unexpected end of file" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "819" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "RTFDocumentImpl::resolve: unexpected end of file" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "RTFDocumentImpl::resolve: unexpected end of file"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "819" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||
820 | throw io::WrongFormatException(m_pTokenizer->getPosition()); | ||||
821 | break; | ||||
822 | case RTFError::HEX_INVALID: | ||||
823 | SAL_INFO("writerfilter.rtf", "RTFDocumentImpl::resolve: invalid hex char")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO , "writerfilter.rtf")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "RTFDocumentImpl::resolve: invalid hex char" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "823" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "RTFDocumentImpl::resolve: invalid hex char" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "RTFDocumentImpl::resolve: invalid hex char"; ::sal ::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "823" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "RTFDocumentImpl::resolve: invalid hex char") == 1 ) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "823" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "RTFDocumentImpl::resolve: invalid hex char" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "RTFDocumentImpl::resolve: invalid hex char"; ::sal ::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "823" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||
824 | throw io::WrongFormatException(m_pTokenizer->getPosition()); | ||||
825 | break; | ||||
826 | case RTFError::CHAR_OVER: | ||||
827 | SAL_INFO("writerfilter.rtf", "RTFDocumentImpl::resolve: characters after last '}'")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO , "writerfilter.rtf")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "RTFDocumentImpl::resolve: characters after last '}'" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "827" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "RTFDocumentImpl::resolve: characters after last '}'" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "RTFDocumentImpl::resolve: characters after last '}'" ; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "827" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "RTFDocumentImpl::resolve: characters after last '}'" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "827" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "RTFDocumentImpl::resolve: characters after last '}'" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "RTFDocumentImpl::resolve: characters after last '}'" ; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "827" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||
828 | break; | ||||
829 | case RTFError::CLASSIFICATION: | ||||
830 | SAL_INFO("writerfilter.rtf",do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO , "writerfilter.rtf")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "RTFDocumentImpl::resolve: classification prevented paste" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "831" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "RTFDocumentImpl::resolve: classification prevented paste" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "RTFDocumentImpl::resolve: classification prevented paste" ; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "831" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "RTFDocumentImpl::resolve: classification prevented paste" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "831" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "RTFDocumentImpl::resolve: classification prevented paste" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "RTFDocumentImpl::resolve: classification prevented paste" ; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "831" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false) | ||||
831 | "RTFDocumentImpl::resolve: classification prevented paste")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO , "writerfilter.rtf")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "RTFDocumentImpl::resolve: classification prevented paste" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "831" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "RTFDocumentImpl::resolve: classification prevented paste" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "RTFDocumentImpl::resolve: classification prevented paste" ; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "831" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "RTFDocumentImpl::resolve: classification prevented paste" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "831" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "RTFDocumentImpl::resolve: classification prevented paste" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "RTFDocumentImpl::resolve: classification prevented paste" ; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "831" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||
832 | break; | ||||
833 | } | ||||
834 | } | ||||
835 | |||||
836 | void RTFDocumentImpl::resolvePict(bool const bInline, uno::Reference<drawing::XShape> const& rShape) | ||||
837 | { | ||||
838 | SvMemoryStream aStream; | ||||
839 | SvStream* pStream = nullptr; | ||||
840 | if (!m_pBinaryData) | ||||
841 | { | ||||
842 | pStream = &aStream; | ||||
843 | int b = 0; | ||||
844 | int count = 2; | ||||
845 | |||||
846 | // Feed the destination text to a stream. | ||||
847 | OString aStr = OUStringToOString(m_aStates.top().getDestinationText().makeStringAndClear(), | ||||
848 | RTL_TEXTENCODING_ASCII_US(((rtl_TextEncoding) 11))); | ||||
849 | for (int i = 0; i < aStr.getLength(); ++i) | ||||
850 | { | ||||
851 | char ch = aStr[i]; | ||||
852 | if (ch != 0x0d && ch != 0x0a && ch != 0x20) | ||||
853 | { | ||||
854 | b = b << 4; | ||||
855 | sal_Int8 parsed = msfilter::rtfutil::AsHex(ch); | ||||
856 | if (parsed == -1) | ||||
857 | return; | ||||
858 | b += parsed; | ||||
859 | count--; | ||||
860 | if (!count) | ||||
861 | { | ||||
862 | aStream.WriteChar(static_cast<char>(b)); | ||||
863 | count = 2; | ||||
864 | b = 0; | ||||
865 | } | ||||
866 | } | ||||
867 | } | ||||
868 | } | ||||
869 | else | ||||
870 | pStream = m_pBinaryData.get(); | ||||
871 | |||||
872 | if (!pStream->Tell()) | ||||
873 | // No destination text? Then we'll get it later. | ||||
874 | return; | ||||
875 | |||||
876 | SvMemoryStream aDIBStream; | ||||
877 | if (m_aStates.top().getPicture().eStyle == RTFBmpStyle::DIBITMAP) | ||||
878 | { | ||||
879 | // Construct a BITMAPFILEHEADER structure before the real data. | ||||
880 | SvStream& rBodyStream = *pStream; | ||||
881 | aDIBStream.WriteChar('B'); | ||||
882 | aDIBStream.WriteChar('M'); | ||||
883 | // The size of the real data. | ||||
884 | aDIBStream.WriteUInt32(rBodyStream.Tell()); | ||||
885 | // Reserved. | ||||
886 | aDIBStream.WriteUInt32(0); | ||||
887 | // The offset of the real data, i.e. the size of the header, including this number. | ||||
888 | aDIBStream.WriteUInt32(14); | ||||
889 | rBodyStream.Seek(0); | ||||
890 | aDIBStream.WriteStream(rBodyStream); | ||||
891 | pStream = &aDIBStream; | ||||
892 | } | ||||
893 | |||||
894 | // Store, and get its URL. | ||||
895 | pStream->Seek(0); | ||||
896 | uno::Reference<io::XInputStream> xInputStream(new utl::OInputStreamWrapper(pStream)); | ||||
897 | WmfExternal aExtHeader; | ||||
898 | aExtHeader.mapMode = m_aStates.top().getPicture().eWMetafile; | ||||
899 | aExtHeader.xExt = sal_uInt16( | ||||
900 | std::clamp<sal_Int32>(m_aStates.top().getPicture().nWidth, 0, | ||||
901 | SAL_MAX_UINT16((sal_uInt16) 0xFFFF))); //TODO: better way to handle out-of-bounds values? | ||||
902 | aExtHeader.yExt = sal_uInt16( | ||||
903 | std::clamp<sal_Int32>(m_aStates.top().getPicture().nHeight, 0, | ||||
904 | SAL_MAX_UINT16((sal_uInt16) 0xFFFF))); //TODO: better way to handle out-of-bounds values? | ||||
905 | WmfExternal* pExtHeader = &aExtHeader; | ||||
906 | uno::Reference<lang::XServiceInfo> xServiceInfo(m_aStates.top().getDrawingObject().getShape(), | ||||
907 | uno::UNO_QUERY); | ||||
908 | if (xServiceInfo.is() && xServiceInfo->supportsService("com.sun.star.text.TextFrame")) | ||||
909 | pExtHeader = nullptr; | ||||
910 | |||||
911 | uno::Reference<graphic::XGraphic> xGraphic | ||||
912 | = m_pGraphicHelper->importGraphic(xInputStream, pExtHeader); | ||||
913 | |||||
914 | if (m_aStates.top().getPicture().eStyle != RTFBmpStyle::NONE) | ||||
915 | { | ||||
916 | // In case of PNG/JPEG, the real size is known, don't use the values | ||||
917 | // provided by picw and pich. | ||||
918 | |||||
919 | Graphic aGraphic(xGraphic); | ||||
920 | Size aSize(aGraphic.GetPrefSize()); | ||||
921 | MapMode aMap(MapUnit::Map100thMM); | ||||
922 | if (aGraphic.GetPrefMapMode().GetMapUnit() == MapUnit::MapPixel) | ||||
923 | aSize = Application::GetDefaultDevice()->PixelToLogic(aSize, aMap); | ||||
924 | else | ||||
925 | aSize = OutputDevice::LogicToLogic(aSize, aGraphic.GetPrefMapMode(), aMap); | ||||
926 | m_aStates.top().getPicture().nWidth = aSize.Width(); | ||||
927 | m_aStates.top().getPicture().nHeight = aSize.Height(); | ||||
928 | } | ||||
929 | |||||
930 | // Wrap it in an XShape. | ||||
931 | uno::Reference<drawing::XShape> xShape(rShape); | ||||
932 | if (xShape.is()) | ||||
933 | { | ||||
934 | uno::Reference<lang::XServiceInfo> xSI(xShape, uno::UNO_QUERY_THROW); | ||||
935 | if (!xSI->supportsService("com.sun.star.drawing.GraphicObjectShape")) | ||||
936 | { | ||||
937 | // it's sometimes an error to get here - but it's possible to have | ||||
938 | // a \pict inside the \shptxt of a \shp of shapeType 202 "TextBox" | ||||
939 | // and in that case xShape is the text frame; we actually need a | ||||
940 | // new GraphicObject then (example: fdo37691-1.rtf) | ||||
941 | SAL_INFO("writerfilter.rtf",do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO , "writerfilter.rtf")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "cannot set graphic on existing shape, creating a new GraphicObjectShape" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "942" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "cannot set graphic on existing shape, creating a new GraphicObjectShape" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "cannot set graphic on existing shape, creating a new GraphicObjectShape" ; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "942" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "cannot set graphic on existing shape, creating a new GraphicObjectShape" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "942" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "cannot set graphic on existing shape, creating a new GraphicObjectShape" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "cannot set graphic on existing shape, creating a new GraphicObjectShape" ; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "942" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false) | ||||
942 | "cannot set graphic on existing shape, creating a new GraphicObjectShape")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO , "writerfilter.rtf")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "cannot set graphic on existing shape, creating a new GraphicObjectShape" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "942" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "cannot set graphic on existing shape, creating a new GraphicObjectShape" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "cannot set graphic on existing shape, creating a new GraphicObjectShape" ; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "942" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "cannot set graphic on existing shape, creating a new GraphicObjectShape" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "942" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "cannot set graphic on existing shape, creating a new GraphicObjectShape" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "cannot set graphic on existing shape, creating a new GraphicObjectShape" ; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "942" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||
943 | xShape.clear(); | ||||
944 | } | ||||
945 | } | ||||
946 | if (!xShape.is()) | ||||
947 | { | ||||
948 | if (m_xModelFactory.is()) | ||||
949 | xShape.set(m_xModelFactory->createInstance("com.sun.star.drawing.GraphicObjectShape"), | ||||
950 | uno::UNO_QUERY); | ||||
951 | uno::Reference<drawing::XDrawPageSupplier> const xDrawSupplier(m_xDstDoc, uno::UNO_QUERY); | ||||
952 | if (xDrawSupplier.is()) | ||||
953 | { | ||||
954 | uno::Reference<drawing::XShapes> xShapes = xDrawSupplier->getDrawPage(); | ||||
955 | if (xShapes.is()) | ||||
956 | xShapes->add(xShape); | ||||
957 | } | ||||
958 | } | ||||
959 | |||||
960 | uno::Reference<beans::XPropertySet> xPropertySet(xShape, uno::UNO_QUERY); | ||||
961 | |||||
962 | if (xPropertySet.is()) | ||||
963 | xPropertySet->setPropertyValue("Graphic", uno::Any(xGraphic)); | ||||
964 | |||||
965 | // check if the picture is in an OLE object and if the \objdata element is used | ||||
966 | // (see RTF_OBJECT in RTFDocumentImpl::dispatchDestination) | ||||
967 | if (m_bObject) | ||||
968 | { | ||||
969 | // Set the object size | ||||
970 | awt::Size aSize; | ||||
971 | aSize.Width | ||||
972 | = (m_aStates.top().getPicture().nGoalWidth ? m_aStates.top().getPicture().nGoalWidth | ||||
973 | : m_aStates.top().getPicture().nWidth); | ||||
974 | aSize.Height | ||||
975 | = (m_aStates.top().getPicture().nGoalHeight ? m_aStates.top().getPicture().nGoalHeight | ||||
976 | : m_aStates.top().getPicture().nHeight); | ||||
977 | xShape->setSize(aSize); | ||||
978 | |||||
979 | // Replacement graphic is inline by default, see oox::vml::SimpleShape::implConvertAndInsert(). | ||||
980 | xPropertySet->setPropertyValue("AnchorType", | ||||
981 | uno::makeAny(text::TextContentAnchorType_AS_CHARACTER)); | ||||
982 | |||||
983 | auto pShapeValue = new RTFValue(xShape); | ||||
984 | m_aObjectAttributes.set(NS_ooxml::LN_shape, pShapeValue); | ||||
985 | return; | ||||
986 | } | ||||
987 | |||||
988 | if (m_aStates.top().getInListpicture()) | ||||
989 | { | ||||
990 | // Send the shape directly, no section is started, to additional properties will be ignored anyway. | ||||
991 | Mapper().startShape(xShape); | ||||
992 | Mapper().endShape(); | ||||
993 | return; | ||||
994 | } | ||||
995 | |||||
996 | // Send it to the dmapper. | ||||
997 | RTFSprms aSprms; | ||||
998 | RTFSprms aAttributes; | ||||
999 | // shape attribute | ||||
1000 | RTFSprms aPicAttributes; | ||||
1001 | auto pShapeValue = new RTFValue(xShape); | ||||
1002 | aPicAttributes.set(NS_ooxml::LN_shape, pShapeValue); | ||||
1003 | // pic sprm | ||||
1004 | RTFSprms aGraphicDataAttributes; | ||||
1005 | RTFSprms aGraphicDataSprms; | ||||
1006 | auto pPicValue = new RTFValue(aPicAttributes); | ||||
1007 | aGraphicDataSprms.set(NS_ooxml::LN_pic_pic, pPicValue); | ||||
1008 | // graphicData sprm | ||||
1009 | RTFSprms aGraphicAttributes; | ||||
1010 | RTFSprms aGraphicSprms; | ||||
1011 | auto pGraphicDataValue = new RTFValue(aGraphicDataAttributes, aGraphicDataSprms); | ||||
1012 | aGraphicSprms.set(NS_ooxml::LN_CT_GraphicalObject_graphicData, pGraphicDataValue); | ||||
1013 | // graphic sprm | ||||
1014 | auto pGraphicValue = new RTFValue(aGraphicAttributes, aGraphicSprms); | ||||
1015 | // extent sprm | ||||
1016 | RTFSprms aExtentAttributes; | ||||
1017 | int nXExt = (m_aStates.top().getPicture().nGoalWidth ? m_aStates.top().getPicture().nGoalWidth | ||||
1018 | : m_aStates.top().getPicture().nWidth); | ||||
1019 | int nYExt = (m_aStates.top().getPicture().nGoalHeight ? m_aStates.top().getPicture().nGoalHeight | ||||
1020 | : m_aStates.top().getPicture().nHeight); | ||||
1021 | if (m_aStates.top().getPicture().nScaleX != 100) | ||||
1022 | nXExt = (static_cast<long>(m_aStates.top().getPicture().nScaleX) | ||||
1023 | * (nXExt | ||||
1024 | - (m_aStates.top().getPicture().nCropL + m_aStates.top().getPicture().nCropR))) | ||||
1025 | / 100L; | ||||
1026 | if (m_aStates.top().getPicture().nScaleY != 100) | ||||
1027 | nYExt = (static_cast<long>(m_aStates.top().getPicture().nScaleY) | ||||
1028 | * (nYExt | ||||
1029 | - (m_aStates.top().getPicture().nCropT + m_aStates.top().getPicture().nCropB))) | ||||
1030 | / 100L; | ||||
1031 | if (m_aStates.top().getInShape()) | ||||
1032 | { | ||||
1033 | // Picture in shape: it looks like pib picture, so we will stretch the picture to shape size (tdf#49893) | ||||
1034 | nXExt = m_aStates.top().getShape().getRight() - m_aStates.top().getShape().getLeft(); | ||||
1035 | nYExt = m_aStates.top().getShape().getBottom() - m_aStates.top().getShape().getTop(); | ||||
1036 | } | ||||
1037 | auto pXExtValue = new RTFValue(oox::drawingml::convertHmmToEmu(nXExt)); | ||||
1038 | auto pYExtValue = new RTFValue(oox::drawingml::convertHmmToEmu(nYExt)); | ||||
1039 | aExtentAttributes.set(NS_ooxml::LN_CT_PositiveSize2D_cx, pXExtValue); | ||||
1040 | aExtentAttributes.set(NS_ooxml::LN_CT_PositiveSize2D_cy, pYExtValue); | ||||
1041 | auto pExtentValue = new RTFValue(aExtentAttributes); | ||||
1042 | // docpr sprm | ||||
1043 | RTFSprms aDocprAttributes; | ||||
1044 | for (const auto& rCharacterAttribute : m_aStates.top().getCharacterAttributes()) | ||||
1045 | if (rCharacterAttribute.first == NS_ooxml::LN_CT_NonVisualDrawingProps_name | ||||
1046 | || rCharacterAttribute.first == NS_ooxml::LN_CT_NonVisualDrawingProps_descr) | ||||
1047 | aDocprAttributes.set(rCharacterAttribute.first, rCharacterAttribute.second); | ||||
1048 | auto pDocprValue = new RTFValue(aDocprAttributes); | ||||
1049 | if (bInline) | ||||
1050 | { | ||||
1051 | RTFSprms aInlineAttributes; | ||||
1052 | aInlineAttributes.set(NS_ooxml::LN_CT_Inline_distT, new RTFValue(0)); | ||||
1053 | aInlineAttributes.set(NS_ooxml::LN_CT_Inline_distB, new RTFValue(0)); | ||||
1054 | aInlineAttributes.set(NS_ooxml::LN_CT_Inline_distL, new RTFValue(0)); | ||||
1055 | aInlineAttributes.set(NS_ooxml::LN_CT_Inline_distR, new RTFValue(0)); | ||||
1056 | RTFSprms aInlineSprms; | ||||
1057 | aInlineSprms.set(NS_ooxml::LN_CT_Inline_extent, pExtentValue); | ||||
1058 | aInlineSprms.set(NS_ooxml::LN_CT_Inline_docPr, pDocprValue); | ||||
1059 | aInlineSprms.set(NS_ooxml::LN_graphic_graphic, pGraphicValue); | ||||
1060 | // inline sprm | ||||
1061 | auto pValue = new RTFValue(aInlineAttributes, aInlineSprms); | ||||
1062 | aSprms.set(NS_ooxml::LN_inline_inline, pValue); | ||||
1063 | } | ||||
1064 | else // anchored | ||||
1065 | { | ||||
1066 | // wrap sprm | ||||
1067 | RTFSprms aAnchorWrapAttributes; | ||||
1068 | m_aStates.top().getShape().getAnchorAttributes().set( | ||||
1069 | NS_ooxml::LN_CT_Anchor_behindDoc, | ||||
1070 | new RTFValue((m_aStates.top().getShape().getInBackground()) ? 1 : 0)); | ||||
1071 | RTFSprms aAnchorSprms; | ||||
1072 | for (const auto& rCharacterAttribute : m_aStates.top().getCharacterAttributes()) | ||||
1073 | { | ||||
1074 | if (rCharacterAttribute.first == NS_ooxml::LN_CT_WrapSquare_wrapText) | ||||
1075 | aAnchorWrapAttributes.set(rCharacterAttribute.first, rCharacterAttribute.second); | ||||
1076 | } | ||||
1077 | sal_Int32 nWrap = -1; | ||||
1078 | for (auto& rCharacterSprm : m_aStates.top().getCharacterSprms()) | ||||
1079 | { | ||||
1080 | if (rCharacterSprm.first == NS_ooxml::LN_EG_WrapType_wrapNone | ||||
1081 | || rCharacterSprm.first == NS_ooxml::LN_EG_WrapType_wrapTight) | ||||
1082 | { | ||||
1083 | nWrap = rCharacterSprm.first; | ||||
1084 | |||||
1085 | // If there is a wrap polygon prepared by RTFSdrImport, pick it up here. | ||||
1086 | if (rCharacterSprm.first == NS_ooxml::LN_EG_WrapType_wrapTight | ||||
1087 | && !m_aStates.top().getShape().getWrapPolygonSprms().empty()) | ||||
1088 | rCharacterSprm.second->getSprms().set( | ||||
1089 | NS_ooxml::LN_CT_WrapTight_wrapPolygon, | ||||
1090 | new RTFValue(RTFSprms(), m_aStates.top().getShape().getWrapPolygonSprms())); | ||||
1091 | |||||
1092 | aAnchorSprms.set(rCharacterSprm.first, rCharacterSprm.second); | ||||
1093 | } | ||||
1094 | } | ||||
1095 | |||||
1096 | if (m_aStates.top().getShape().getWrapSprm().first != 0) | ||||
1097 | // Replay of a buffered shape, wrap sprm there has priority over | ||||
1098 | // character sprms of the current state. | ||||
1099 | aAnchorSprms.set(m_aStates.top().getShape().getWrapSprm().first, | ||||
1100 | m_aStates.top().getShape().getWrapSprm().second); | ||||
1101 | |||||
1102 | aAnchorSprms.set(NS_ooxml::LN_CT_Anchor_extent, pExtentValue); | ||||
1103 | if (!aAnchorWrapAttributes.empty() && nWrap == -1) | ||||
1104 | aAnchorSprms.set(NS_ooxml::LN_EG_WrapType_wrapSquare, | ||||
1105 | new RTFValue(aAnchorWrapAttributes)); | ||||
1106 | |||||
1107 | // See OOXMLFastContextHandler::positionOffset(), we can't just put offset values in an RTFValue. | ||||
1108 | RTFSprms aPoshAttributes; | ||||
1109 | RTFSprms aPoshSprms; | ||||
1110 | if (m_aStates.top().getShape().getHoriOrientRelationToken() > 0) | ||||
1111 | aPoshAttributes.set( | ||||
1112 | NS_ooxml::LN_CT_PosH_relativeFrom, | ||||
1113 | new RTFValue(m_aStates.top().getShape().getHoriOrientRelationToken())); | ||||
1114 | if (m_aStates.top().getShape().getLeft() != 0) | ||||
1115 | { | ||||
1116 | Mapper().positionOffset(OUString::number(oox::drawingml::convertHmmToEmu( | ||||
1117 | m_aStates.top().getShape().getLeft())), | ||||
1118 | /*bVertical=*/false); | ||||
1119 | aPoshSprms.set(NS_ooxml::LN_CT_PosH_posOffset, new RTFValue()); | ||||
1120 | } | ||||
1121 | aAnchorSprms.set(NS_ooxml::LN_CT_Anchor_positionH, | ||||
1122 | new RTFValue(aPoshAttributes, aPoshSprms)); | ||||
1123 | |||||
1124 | RTFSprms aPosvAttributes; | ||||
1125 | RTFSprms aPosvSprms; | ||||
1126 | if (m_aStates.top().getShape().getVertOrientRelationToken() > 0) | ||||
1127 | aPosvAttributes.set( | ||||
1128 | NS_ooxml::LN_CT_PosV_relativeFrom, | ||||
1129 | new RTFValue(m_aStates.top().getShape().getVertOrientRelationToken())); | ||||
1130 | if (m_aStates.top().getShape().getTop() != 0) | ||||
1131 | { | ||||
1132 | Mapper().positionOffset(OUString::number(oox::drawingml::convertHmmToEmu( | ||||
1133 | m_aStates.top().getShape().getTop())), | ||||
1134 | /*bVertical=*/true); | ||||
1135 | aPosvSprms.set(NS_ooxml::LN_CT_PosV_posOffset, new RTFValue()); | ||||
1136 | } | ||||
1137 | aAnchorSprms.set(NS_ooxml::LN_CT_Anchor_positionV, | ||||
1138 | new RTFValue(aPosvAttributes, aPosvSprms)); | ||||
1139 | |||||
1140 | aAnchorSprms.set(NS_ooxml::LN_CT_Anchor_docPr, pDocprValue); | ||||
1141 | aAnchorSprms.set(NS_ooxml::LN_graphic_graphic, pGraphicValue); | ||||
1142 | // anchor sprm | ||||
1143 | auto pValue = new RTFValue(m_aStates.top().getShape().getAnchorAttributes(), aAnchorSprms); | ||||
1144 | aSprms.set(NS_ooxml::LN_anchor_anchor, pValue); | ||||
1145 | } | ||||
1146 | writerfilter::Reference<Properties>::Pointer_t pProperties | ||||
1147 | = new RTFReferenceProperties(aAttributes, aSprms); | ||||
1148 | checkFirstRun(); | ||||
1149 | |||||
1150 | if (!m_aStates.top().getCurrentBuffer()) | ||||
1151 | { | ||||
1152 | Mapper().props(pProperties); | ||||
1153 | // Make sure we don't lose these properties with a too early reset. | ||||
1154 | m_bHadPicture = true; | ||||
1155 | } | ||||
1156 | else | ||||
1157 | { | ||||
1158 | auto pValue = new RTFValue(aAttributes, aSprms); | ||||
1159 | bufferProperties(*m_aStates.top().getCurrentBuffer(), pValue, nullptr); | ||||
1160 | } | ||||
1161 | } | ||||
1162 | |||||
1163 | RTFError RTFDocumentImpl::resolveChars(char ch) | ||||
1164 | { | ||||
1165 | if (m_aStates.top().getInternalState() == RTFInternalState::BIN) | ||||
1166 | { | ||||
1167 | m_pBinaryData = std::make_shared<SvMemoryStream>(); | ||||
1168 | m_pBinaryData->WriteChar(ch); | ||||
1169 | for (int i = 0; i < m_aStates.top().getBinaryToRead() - 1; ++i) | ||||
1170 | { | ||||
1171 | Strm().ReadChar(ch); | ||||
1172 | m_pBinaryData->WriteChar(ch); | ||||
1173 | } | ||||
1174 | m_aStates.top().setInternalState(RTFInternalState::NORMAL); | ||||
1175 | return RTFError::OK; | ||||
1176 | } | ||||
1177 | |||||
1178 | OStringBuffer aBuf(512); | ||||
1179 | |||||
1180 | bool bUnicodeChecked = false; | ||||
1181 | bool bSkipped = false; | ||||
1182 | |||||
1183 | while (!Strm().eof() | ||||
1184 | && (m_aStates.top().getInternalState() == RTFInternalState::HEX | ||||
1185 | || (ch != '{' && ch != '}' && ch != '\\'))) | ||||
1186 | { | ||||
1187 | if (m_aStates.top().getInternalState() == RTFInternalState::HEX | ||||
1188 | || (ch != 0x0d && ch != 0x0a)) | ||||
1189 | { | ||||
1190 | if (m_aStates.top().getCharsToSkip() == 0) | ||||
1191 | { | ||||
1192 | if (!bUnicodeChecked) | ||||
1193 | { | ||||
1194 | checkUnicode(/*bUnicode =*/true, /*bHex =*/false); | ||||
1195 | bUnicodeChecked = true; | ||||
1196 | } | ||||
1197 | aBuf.append(ch); | ||||
1198 | } | ||||
1199 | else | ||||
1200 | { | ||||
1201 | bSkipped = true; | ||||
1202 | m_aStates.top().getCharsToSkip()--; | ||||
1203 | } | ||||
1204 | } | ||||
1205 | |||||
1206 | // read a single char if we're in hex mode | ||||
1207 | if (m_aStates.top().getInternalState() == RTFInternalState::HEX) | ||||
1208 | break; | ||||
1209 | |||||
1210 | if (RTL_TEXTENCODING_MS_932(((rtl_TextEncoding) 60)) == m_aStates.top().getCurrentEncoding()) | ||||
1211 | { | ||||
1212 | unsigned char uch = ch; | ||||
1213 | if ((uch >= 0x80 && uch <= 0x9F) || uch >= 0xE0) | ||||
1214 | { | ||||
1215 | // read second byte of 2-byte Shift-JIS - may be \ { } | ||||
1216 | Strm().ReadChar(ch); | ||||
1217 | if (m_aStates.top().getCharsToSkip() == 0) | ||||
1218 | { | ||||
1219 | // fdo#79384: Word will reject Shift-JIS following \loch | ||||
1220 | // but apparently OOo could read and (worse) write such documents | ||||
1221 | SAL_INFO_IF(m_aStates.top().getRunType() != RTFParserState::RunType::DBCH,do { if (true && (m_aStates.top().getRunType() != RTFParserState ::RunType::DBCH)) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO , "writerfilter.rtf")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "invalid Shift-JIS without DBCH" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "1222" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "invalid Shift-JIS without DBCH"), 0 ); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "invalid Shift-JIS without DBCH"; ::sal::detail::log ( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "1222" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "invalid Shift-JIS without DBCH") == 1) { ::sal_detail_log ( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "1222" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "invalid Shift-JIS without DBCH"), 0 ); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "invalid Shift-JIS without DBCH"; ::sal::detail::log ( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "1222" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false) | ||||
1222 | "writerfilter.rtf", "invalid Shift-JIS without DBCH")do { if (true && (m_aStates.top().getRunType() != RTFParserState ::RunType::DBCH)) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO , "writerfilter.rtf")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "invalid Shift-JIS without DBCH" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "1222" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "invalid Shift-JIS without DBCH"), 0 ); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "invalid Shift-JIS without DBCH"; ::sal::detail::log ( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "1222" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "invalid Shift-JIS without DBCH") == 1) { ::sal_detail_log ( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "1222" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "invalid Shift-JIS without DBCH"), 0 ); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "invalid Shift-JIS without DBCH"; ::sal::detail::log ( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "1222" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||
1223 | assert(bUnicodeChecked)(static_cast <bool> (bUnicodeChecked) ? void (0) : __assert_fail ("bUnicodeChecked", "/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" , 1223, __extension__ __PRETTY_FUNCTION__)); | ||||
1224 | aBuf.append(ch); | ||||
1225 | } | ||||
1226 | else | ||||
1227 | { | ||||
1228 | assert(bSkipped)(static_cast <bool> (bSkipped) ? void (0) : __assert_fail ("bSkipped", "/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" , 1228, __extension__ __PRETTY_FUNCTION__)); | ||||
1229 | // anybody who uses \ucN with Shift-JIS is insane | ||||
1230 | m_aStates.top().getCharsToSkip()--; | ||||
1231 | } | ||||
1232 | } | ||||
1233 | } | ||||
1234 | |||||
1235 | Strm().ReadChar(ch); | ||||
1236 | } | ||||
1237 | if (m_aStates.top().getInternalState() != RTFInternalState::HEX && !Strm().eof()) | ||||
1238 | Strm().SeekRel(-1); | ||||
1239 | |||||
1240 | if (m_aStates.top().getInternalState() == RTFInternalState::HEX | ||||
1241 | && m_aStates.top().getDestination() != Destination::LEVELNUMBERS) | ||||
1242 | { | ||||
1243 | if (!bSkipped) | ||||
1244 | { | ||||
1245 | // note: apparently \'0d\'0a is interpreted as 2 breaks, not 1 | ||||
1246 | if ((ch == '\r' || ch == '\n') | ||||
1247 | && m_aStates.top().getDestination() != Destination::DOCCOMM | ||||
1248 | && m_aStates.top().getDestination() != Destination::LEVELNUMBERS | ||||
1249 | && m_aStates.top().getDestination() != Destination::LEVELTEXT) | ||||
1250 | { | ||||
1251 | checkUnicode(/*bUnicode =*/false, /*bHex =*/true); | ||||
1252 | dispatchSymbol(RTF_PAR); | ||||
1253 | } | ||||
1254 | else | ||||
1255 | { | ||||
1256 | m_aHexBuffer.append(ch); | ||||
1257 | } | ||||
1258 | } | ||||
1259 | return RTFError::OK; | ||||
1260 | } | ||||
1261 | |||||
1262 | if (m_aStates.top().getDestination() == Destination::SKIP) | ||||
1263 | return RTFError::OK; | ||||
1264 | OString aStr = aBuf.makeStringAndClear(); | ||||
1265 | if (m_aStates.top().getDestination() == Destination::LEVELNUMBERS) | ||||
1266 | { | ||||
1267 | if (aStr.toChar() != ';') | ||||
1268 | m_aStates.top().getLevelNumbers().push_back(sal_Int32(ch)); | ||||
1269 | return RTFError::OK; | ||||
1270 | } | ||||
1271 | |||||
1272 | SAL_INFO("writerfilter.rtf",do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO , "writerfilter.rtf")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "RTFDocumentImpl::resolveChars: collected '" << OStringToOUString(aStr, m_aStates.top().getCurrentEncoding ()) << "'") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "1274" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "RTFDocumentImpl::resolveChars: collected '" << OStringToOUString(aStr, m_aStates.top().getCurrentEncoding ()) << "'"), 0); } else { ::std::ostringstream sal_detail_stream ; sal_detail_stream << "RTFDocumentImpl::resolveChars: collected '" << OStringToOUString(aStr, m_aStates.top().getCurrentEncoding ()) << "'"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "1274" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "RTFDocumentImpl::resolveChars: collected '" << OStringToOUString(aStr, m_aStates.top().getCurrentEncoding() ) << "'") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "1274" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "RTFDocumentImpl::resolveChars: collected '" << OStringToOUString(aStr, m_aStates.top().getCurrentEncoding ()) << "'"), 0); } else { ::std::ostringstream sal_detail_stream ; sal_detail_stream << "RTFDocumentImpl::resolveChars: collected '" << OStringToOUString(aStr, m_aStates.top().getCurrentEncoding ()) << "'"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "1274" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false) | ||||
1273 | "RTFDocumentImpl::resolveChars: collected '"do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO , "writerfilter.rtf")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "RTFDocumentImpl::resolveChars: collected '" << OStringToOUString(aStr, m_aStates.top().getCurrentEncoding ()) << "'") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "1274" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "RTFDocumentImpl::resolveChars: collected '" << OStringToOUString(aStr, m_aStates.top().getCurrentEncoding ()) << "'"), 0); } else { ::std::ostringstream sal_detail_stream ; sal_detail_stream << "RTFDocumentImpl::resolveChars: collected '" << OStringToOUString(aStr, m_aStates.top().getCurrentEncoding ()) << "'"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "1274" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "RTFDocumentImpl::resolveChars: collected '" << OStringToOUString(aStr, m_aStates.top().getCurrentEncoding() ) << "'") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "1274" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "RTFDocumentImpl::resolveChars: collected '" << OStringToOUString(aStr, m_aStates.top().getCurrentEncoding ()) << "'"), 0); } else { ::std::ostringstream sal_detail_stream ; sal_detail_stream << "RTFDocumentImpl::resolveChars: collected '" << OStringToOUString(aStr, m_aStates.top().getCurrentEncoding ()) << "'"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "1274" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false) | ||||
1274 | << OStringToOUString(aStr, m_aStates.top().getCurrentEncoding()) << "'")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO , "writerfilter.rtf")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "RTFDocumentImpl::resolveChars: collected '" << OStringToOUString(aStr, m_aStates.top().getCurrentEncoding ()) << "'") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "1274" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "RTFDocumentImpl::resolveChars: collected '" << OStringToOUString(aStr, m_aStates.top().getCurrentEncoding ()) << "'"), 0); } else { ::std::ostringstream sal_detail_stream ; sal_detail_stream << "RTFDocumentImpl::resolveChars: collected '" << OStringToOUString(aStr, m_aStates.top().getCurrentEncoding ()) << "'"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "1274" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "RTFDocumentImpl::resolveChars: collected '" << OStringToOUString(aStr, m_aStates.top().getCurrentEncoding() ) << "'") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "1274" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "RTFDocumentImpl::resolveChars: collected '" << OStringToOUString(aStr, m_aStates.top().getCurrentEncoding ()) << "'"), 0); } else { ::std::ostringstream sal_detail_stream ; sal_detail_stream << "RTFDocumentImpl::resolveChars: collected '" << OStringToOUString(aStr, m_aStates.top().getCurrentEncoding ()) << "'"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "1274" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||
1275 | |||||
1276 | if (m_aStates.top().getDestination() == Destination::COLORTABLE) | ||||
1277 | { | ||||
1278 | // we hit a ';' at the end of each color entry | ||||
1279 | m_aColorTable.push_back(m_aStates.top().getCurrentColor().GetColor()); | ||||
1280 | // set components back to zero | ||||
1281 | m_aStates.top().getCurrentColor() = RTFColorTableEntry(); | ||||
1282 | } | ||||
1283 | else if (!aStr.isEmpty()) | ||||
1284 | m_aHexBuffer.append(aStr); | ||||
1285 | |||||
1286 | checkUnicode(/*bUnicode =*/false, /*bHex =*/true); | ||||
1287 | return RTFError::OK; | ||||
1288 | } | ||||
1289 | |||||
1290 | bool RTFFrame::inFrame() const { return m_nW > 0 || m_nH > 0 || m_nX > 0 || m_nY > 0; } | ||||
1291 | |||||
1292 | void RTFDocumentImpl::singleChar(sal_uInt8 nValue, bool bRunProps) | ||||
1293 | { | ||||
1294 | sal_uInt8 sValue[] = { nValue }; | ||||
1295 | RTFBuffer_t* pCurrentBuffer = m_aStates.top().getCurrentBuffer(); | ||||
1296 | |||||
1297 | if (!pCurrentBuffer) | ||||
1298 | { | ||||
1299 | Mapper().startCharacterGroup(); | ||||
1300 | // Should we send run properties? | ||||
1301 | if (bRunProps) | ||||
1302 | runProps(); | ||||
1303 | Mapper().text(sValue, 1); | ||||
1304 | Mapper().endCharacterGroup(); | ||||
1305 | } | ||||
1306 | else | ||||
1307 | { | ||||
1308 | pCurrentBuffer->push_back(Buf_t(BUFFER_STARTRUN, nullptr, nullptr)); | ||||
1309 | auto pValue = new RTFValue(*sValue); | ||||
1310 | pCurrentBuffer->push_back(Buf_t(BUFFER_TEXT, pValue, nullptr)); | ||||
1311 | pCurrentBuffer->push_back(Buf_t(BUFFER_ENDRUN, nullptr, nullptr)); | ||||
1312 | } | ||||
1313 | } | ||||
1314 | |||||
1315 | void RTFDocumentImpl::text(OUString& rString) | ||||
1316 | { | ||||
1317 | if (rString.getLength() == 1 && m_aStates.top().getDestination() != Destination::DOCCOMM) | ||||
1318 | { | ||||
1319 | // No cheating! Tokenizer ignores bare \r and \n, their hex \'0d / \'0a form doesn't count, either. | ||||
1320 | sal_Unicode ch = rString[0]; | ||||
1321 | if (ch == 0x0d || ch == 0x0a) | ||||
1322 | return; | ||||
1323 | } | ||||
1324 | |||||
1325 | bool bRet = true; | ||||
1326 | switch (m_aStates.top().getDestination()) | ||||
1327 | { | ||||
1328 | // Note: in fonttbl there may or may not be groups; in stylesheet | ||||
1329 | // and revtbl groups are mandatory | ||||
1330 | case Destination::FONTTABLE: | ||||
1331 | case Destination::FONTENTRY: | ||||
1332 | case Destination::STYLEENTRY: | ||||
1333 | case Destination::LISTNAME: | ||||
1334 | case Destination::REVISIONENTRY: | ||||
1335 | { | ||||
1336 | // ; is the end of the entry | ||||
1337 | bool bEnd = false; | ||||
1338 | if (rString.endsWith(";")) | ||||
1339 | { | ||||
1340 | rString = rString.copy(0, rString.getLength() - 1); | ||||
1341 | bEnd = true; | ||||
1342 | } | ||||
1343 | m_aStates.top().appendDestinationText(rString); | ||||
1344 | if (bEnd) | ||||
1345 | { | ||||
1346 | // always clear, necessary in case of group-less fonttable | ||||
1347 | OUString const aName | ||||
1348 | = m_aStates.top().getCurrentDestinationText()->makeStringAndClear(); | ||||
1349 | switch (m_aStates.top().getDestination()) | ||||
1350 | { | ||||
1351 | case Destination::FONTTABLE: | ||||
1352 | case Destination::FONTENTRY: | ||||
1353 | { | ||||
1354 | m_aFontNames[m_nCurrentFontIndex] = aName; | ||||
1355 | if (m_nCurrentEncoding >= 0) | ||||
1356 | { | ||||
1357 | m_aFontEncodings[m_nCurrentFontIndex] = m_nCurrentEncoding; | ||||
1358 | m_nCurrentEncoding = -1; | ||||
1359 | } | ||||
1360 | m_aStates.top().getTableAttributes().set(NS_ooxml::LN_CT_Font_name, | ||||
1361 | new RTFValue(aName)); | ||||
1362 | |||||
1363 | writerfilter::Reference<Properties>::Pointer_t const pProp( | ||||
1364 | new RTFReferenceProperties(m_aStates.top().getTableAttributes(), | ||||
1365 | m_aStates.top().getTableSprms())); | ||||
1366 | |||||
1367 | //See fdo#47347 initial invalid font entry properties are inserted first, | ||||
1368 | //so when we attempt to insert the correct ones, there's already an | ||||
1369 | //entry in the map for them, so the new ones aren't inserted. | ||||
1370 | auto lb = m_aFontTableEntries.lower_bound(m_nCurrentFontIndex); | ||||
1371 | if (lb != m_aFontTableEntries.end() | ||||
1372 | && !(m_aFontTableEntries.key_comp()(m_nCurrentFontIndex, lb->first))) | ||||
1373 | lb->second = pProp; | ||||
1374 | else | ||||
1375 | m_aFontTableEntries.insert(lb, | ||||
1376 | std::make_pair(m_nCurrentFontIndex, pProp)); | ||||
1377 | } | ||||
1378 | break; | ||||
1379 | case Destination::STYLEENTRY: | ||||
1380 | { | ||||
1381 | RTFValue::Pointer_t pType | ||||
1382 | = m_aStates.top().getTableAttributes().find(NS_ooxml::LN_CT_Style_type); | ||||
1383 | if (pType) | ||||
1384 | { | ||||
1385 | // Word strips whitespace around style names. | ||||
1386 | m_aStyleNames[m_nCurrentStyleIndex] = aName.trim(); | ||||
1387 | m_aStyleTypes[m_nCurrentStyleIndex] = pType->getInt(); | ||||
1388 | auto pValue = new RTFValue(aName.trim()); | ||||
1389 | m_aStates.top().getTableAttributes().set(NS_ooxml::LN_CT_Style_styleId, | ||||
1390 | pValue); | ||||
1391 | m_aStates.top().getTableSprms().set(NS_ooxml::LN_CT_Style_name, pValue); | ||||
1392 | |||||
1393 | writerfilter::Reference<Properties>::Pointer_t const pProp( | ||||
1394 | createStyleProperties()); | ||||
1395 | m_aStyleTableEntries.insert( | ||||
1396 | std::make_pair(m_nCurrentStyleIndex, pProp)); | ||||
1397 | } | ||||
1398 | else | ||||
1399 | SAL_INFO("writerfilter.rtf", "no RTF style type defined, ignoring")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO , "writerfilter.rtf")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "no RTF style type defined, ignoring" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "1399" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "no RTF style type defined, ignoring" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "no RTF style type defined, ignoring"; ::sal::detail ::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf"), ( "/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "1399" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "no RTF style type defined, ignoring") == 1) { :: sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "1399" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "no RTF style type defined, ignoring" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "no RTF style type defined, ignoring"; ::sal::detail ::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf"), ( "/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "1399" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||
1400 | break; | ||||
1401 | } | ||||
1402 | case Destination::LISTNAME: | ||||
1403 | // TODO: what can be done with a list name? | ||||
1404 | break; | ||||
1405 | case Destination::REVISIONENTRY: | ||||
1406 | m_aAuthors[m_aAuthors.size()] = aName; | ||||
1407 | break; | ||||
1408 | default: | ||||
1409 | break; | ||||
1410 | } | ||||
1411 | resetAttributes(); | ||||
1412 | resetSprms(); | ||||
1413 | } | ||||
1414 | } | ||||
1415 | break; | ||||
1416 | case Destination::LEVELTEXT: | ||||
1417 | case Destination::SHAPEPROPERTYNAME: | ||||
1418 | case Destination::SHAPEPROPERTYVALUE: | ||||
1419 | case Destination::BOOKMARKEND: | ||||
1420 | case Destination::PICT: | ||||
1421 | case Destination::SHAPEPROPERTYVALUEPICT: | ||||
1422 | case Destination::FORMFIELDNAME: | ||||
1423 | case Destination::FORMFIELDLIST: | ||||
1424 | case Destination::DATAFIELD: | ||||
1425 | case Destination::AUTHOR: | ||||
1426 | case Destination::KEYWORDS: | ||||
1427 | case Destination::OPERATOR: | ||||
1428 | case Destination::COMPANY: | ||||
1429 | case Destination::COMMENT: | ||||
1430 | case Destination::OBJDATA: | ||||
1431 | case Destination::OBJCLASS: | ||||
1432 | case Destination::ANNOTATIONDATE: | ||||
1433 | case Destination::ANNOTATIONAUTHOR: | ||||
1434 | case Destination::ANNOTATIONREFERENCE: | ||||
1435 | case Destination::FALT: | ||||
1436 | case Destination::PARAGRAPHNUMBERING_TEXTAFTER: | ||||
1437 | case Destination::PARAGRAPHNUMBERING_TEXTBEFORE: | ||||
1438 | case Destination::TITLE: | ||||
1439 | case Destination::SUBJECT: | ||||
1440 | case Destination::DOCCOMM: | ||||
1441 | case Destination::ATNID: | ||||
1442 | case Destination::ANNOTATIONREFERENCESTART: | ||||
1443 | case Destination::ANNOTATIONREFERENCEEND: | ||||
1444 | case Destination::MR: | ||||
1445 | case Destination::MCHR: | ||||
1446 | case Destination::MPOS: | ||||
1447 | case Destination::MVERTJC: | ||||
1448 | case Destination::MSTRIKEH: | ||||
1449 | case Destination::MDEGHIDE: | ||||
1450 | case Destination::MBEGCHR: | ||||
1451 | case Destination::MSEPCHR: | ||||
1452 | case Destination::MENDCHR: | ||||
1453 | case Destination::MSUBHIDE: | ||||
1454 | case Destination::MSUPHIDE: | ||||
1455 | case Destination::MTYPE: | ||||
1456 | case Destination::MGROW: | ||||
1457 | case Destination::INDEXENTRY: | ||||
1458 | case Destination::TOCENTRY: | ||||
1459 | case Destination::PROPNAME: | ||||
1460 | case Destination::STATICVAL: | ||||
1461 | m_aStates.top().appendDestinationText(rString); | ||||
1462 | break; | ||||
1463 | case Destination::GENERATOR: | ||||
1464 | // don't enlarge space sequences, eg. it was saved in LibreOffice | ||||
1465 | if (!rString.startsWithIgnoreAsciiCase("Microsoft")) | ||||
1466 | m_aSettingsTableSprms.set(NS_ooxml::LN_CT_Settings_longerSpaceSequence, | ||||
1467 | new RTFValue(0)); | ||||
1468 | break; | ||||
1469 | default: | ||||
1470 | bRet = false; | ||||
1471 | break; | ||||
1472 | } | ||||
1473 | if (bRet) | ||||
1474 | return; | ||||
1475 | |||||
1476 | if (!m_aIgnoreFirst.isEmpty() && m_aIgnoreFirst == rString) | ||||
1477 | { | ||||
1478 | m_aIgnoreFirst.clear(); | ||||
1479 | return; | ||||
1480 | } | ||||
1481 | |||||
1482 | // Are we in the middle of the table definition? (No cell defs yet, but we already have some cell props.) | ||||
1483 | if (m_aStates.top().getTableCellSprms().find(NS_ooxml::LN_CT_TcPrBase_vAlign) | ||||
1484 | && m_nTopLevelCells == 0) | ||||
1485 | { | ||||
1486 | m_aTableBufferStack.back().emplace_back( | ||||
1487 | Buf_t(BUFFER_UTEXT, new RTFValue(rString), nullptr)); | ||||
1488 | return; | ||||
1489 | } | ||||
1490 | |||||
1491 | checkFirstRun(); | ||||
1492 | checkNeedPap(); | ||||
1493 | |||||
1494 | // Don't return earlier, a bookmark start has to be in a paragraph group. | ||||
1495 | if (m_aStates.top().getDestination() == Destination::BOOKMARKSTART) | ||||
1496 | { | ||||
1497 | m_aStates.top().appendDestinationText(rString); | ||||
1498 | return; | ||||
1499 | } | ||||
1500 | |||||
1501 | RTFBuffer_t* pCurrentBuffer = m_aStates.top().getCurrentBuffer(); | ||||
1502 | |||||
1503 | if (!pCurrentBuffer && m_aStates.top().getDestination() != Destination::FOOTNOTE) | ||||
1504 | Mapper().startCharacterGroup(); | ||||
1505 | else if (pCurrentBuffer) | ||||
1506 | { | ||||
1507 | RTFValue::Pointer_t pValue; | ||||
1508 | pCurrentBuffer->push_back(Buf_t(BUFFER_STARTRUN, pValue, nullptr)); | ||||
1509 | } | ||||
1510 | |||||
1511 | if (m_aStates.top().getDestination() == Destination::NORMAL | ||||
1512 | || m_aStates.top().getDestination() == Destination::FIELDRESULT | ||||
1513 | || m_aStates.top().getDestination() == Destination::SHAPETEXT) | ||||
1514 | runProps(); | ||||
1515 | |||||
1516 | if (!pCurrentBuffer) | ||||
1517 | Mapper().utext(reinterpret_cast<sal_uInt8 const*>(rString.getStr()), rString.getLength()); | ||||
1518 | else | ||||
1519 | { | ||||
1520 | auto pValue = new RTFValue(rString); | ||||
1521 | pCurrentBuffer->push_back(Buf_t(BUFFER_UTEXT, pValue, nullptr)); | ||||
1522 | } | ||||
1523 | |||||
1524 | m_bNeedCr = true; | ||||
1525 | |||||
1526 | if (!pCurrentBuffer && m_aStates.top().getDestination() != Destination::FOOTNOTE) | ||||
1527 | Mapper().endCharacterGroup(); | ||||
1528 | else if (pCurrentBuffer) | ||||
1529 | { | ||||
1530 | RTFValue::Pointer_t pValue; | ||||
1531 | pCurrentBuffer->push_back(Buf_t(BUFFER_ENDRUN, pValue, nullptr)); | ||||
1532 | } | ||||
1533 | } | ||||
1534 | |||||
1535 | void RTFDocumentImpl::prepareProperties( | ||||
1536 | RTFParserState& rState, writerfilter::Reference<Properties>::Pointer_t& o_rpParagraphProperties, | ||||
1537 | writerfilter::Reference<Properties>::Pointer_t& o_rpFrameProperties, | ||||
1538 | writerfilter::Reference<Properties>::Pointer_t& o_rpTableRowProperties, int const nCells, | ||||
1539 | int const nCurrentCellX) | ||||
1540 | { | ||||
1541 | o_rpParagraphProperties | ||||
1542 | = getProperties(rState.getParagraphAttributes(), rState.getParagraphSprms(), | ||||
1543 | NS_ooxml::LN_Value_ST_StyleType_paragraph); | ||||
1544 | |||||
1545 | if (rState.getFrame().hasProperties()) | ||||
| |||||
1546 | { | ||||
1547 | o_rpFrameProperties = new RTFReferenceProperties(RTFSprms(), rState.getFrame().getSprms()); | ||||
1548 | } | ||||
1549 | |||||
1550 | // Table width. | ||||
1551 | RTFValue::Pointer_t const pTableWidthProps | ||||
1552 | = rState.getTableRowSprms().find(NS_ooxml::LN_CT_TblPrBase_tblW); | ||||
1553 | if (!pTableWidthProps) | ||||
1554 | { | ||||
1555 | auto pUnitValue = new RTFValue(3); | ||||
1556 | putNestedAttribute(rState.getTableRowSprms(), NS_ooxml::LN_CT_TblPrBase_tblW, | ||||
1557 | NS_ooxml::LN_CT_TblWidth_type, pUnitValue); | ||||
1558 | auto pWValue = new RTFValue(nCurrentCellX); | ||||
1559 | putNestedAttribute(rState.getTableRowSprms(), NS_ooxml::LN_CT_TblPrBase_tblW, | ||||
1560 | NS_ooxml::LN_CT_TblWidth_w, pWValue); | ||||
1561 | } | ||||
1562 | |||||
1563 | if (nCells > 0) | ||||
1564 | rState.getTableRowSprms().set(NS_ooxml::LN_tblRow, new RTFValue(1)); | ||||
1565 | |||||
1566 | RTFValue::Pointer_t const pCellMar | ||||
1567 | = rState.getTableRowSprms().find(NS_ooxml::LN_CT_TblPrBase_tblCellMar); | ||||
1568 | if (!pCellMar) | ||||
1569 | { | ||||
1570 | // If no cell margins are defined, the default left/right margin is 0 in Word, but not in Writer. | ||||
1571 | RTFSprms aAttributes; | ||||
1572 | aAttributes.set(NS_ooxml::LN_CT_TblWidth_type, | ||||
1573 | new RTFValue(NS_ooxml::LN_Value_ST_TblWidth_dxa)); | ||||
1574 | aAttributes.set(NS_ooxml::LN_CT_TblWidth_w, new RTFValue(0)); | ||||
1575 | putNestedSprm(rState.getTableRowSprms(), NS_ooxml::LN_CT_TblPrBase_tblCellMar, | ||||
1576 | NS_ooxml::LN_CT_TblCellMar_left, new RTFValue(aAttributes)); | ||||
1577 | putNestedSprm(rState.getTableRowSprms(), NS_ooxml::LN_CT_TblPrBase_tblCellMar, | ||||
1578 | NS_ooxml::LN_CT_TblCellMar_right, new RTFValue(aAttributes)); | ||||
1579 | } | ||||
1580 | |||||
1581 | o_rpTableRowProperties | ||||
1582 | = new RTFReferenceProperties(rState.getTableRowAttributes(), rState.getTableRowSprms()); | ||||
1583 | } | ||||
1584 | |||||
1585 | void RTFDocumentImpl::sendProperties( | ||||
1586 | writerfilter::Reference<Properties>::Pointer_t const& pParagraphProperties, | ||||
1587 | writerfilter::Reference<Properties>::Pointer_t const& pFrameProperties, | ||||
1588 | writerfilter::Reference<Properties>::Pointer_t const& pTableRowProperties) | ||||
1589 | { | ||||
1590 | Mapper().props(pParagraphProperties); | ||||
1591 | |||||
1592 | if (pFrameProperties) | ||||
1593 | { | ||||
1594 | Mapper().props(pFrameProperties); | ||||
1595 | } | ||||
1596 | |||||
1597 | Mapper().props(pTableRowProperties); | ||||
1598 | |||||
1599 | tableBreak(); | ||||
1600 | } | ||||
1601 | |||||
1602 | void RTFDocumentImpl::replayRowBuffer(RTFBuffer_t& rBuffer, ::std::deque<RTFSprms>& rCellsSrpms, | ||||
1603 | ::std::deque<RTFSprms>& rCellsAttributes, int const nCells) | ||||
1604 | { | ||||
1605 | for (int i = 0; i < nCells; ++i) | ||||
1606 | { | ||||
1607 | replayBuffer(rBuffer, &rCellsSrpms.front(), &rCellsAttributes.front()); | ||||
1608 | rCellsSrpms.pop_front(); | ||||
1609 | rCellsAttributes.pop_front(); | ||||
1610 | } | ||||
1611 | for (Buf_t& i : rBuffer) | ||||
1612 | { | ||||
1613 | SAL_WARN_IF(BUFFER_CELLEND == std::get<0>(i), "writerfilter.rtf", "dropping table cell!")do { if (true && (BUFFER_CELLEND == std::get<0> (i))) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN , "writerfilter.rtf")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "dropping table cell!" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "1613" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "dropping table cell!"), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "dropping table cell!"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "1613" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "dropping table cell!") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "1613" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "dropping table cell!"), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "dropping table cell!"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "1613" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||
1614 | } | ||||
1615 | assert(rCellsSrpms.empty())(static_cast <bool> (rCellsSrpms.empty()) ? void (0) : __assert_fail ("rCellsSrpms.empty()", "/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" , 1615, __extension__ __PRETTY_FUNCTION__)); | ||||
1616 | assert(rCellsAttributes.empty())(static_cast <bool> (rCellsAttributes.empty()) ? void ( 0) : __assert_fail ("rCellsAttributes.empty()", "/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" , 1616, __extension__ __PRETTY_FUNCTION__)); | ||||
1617 | } | ||||
1618 | |||||
1619 | void RTFDocumentImpl::replayBuffer(RTFBuffer_t& rBuffer, RTFSprms* const pSprms, | ||||
1620 | RTFSprms const* const pAttributes) | ||||
1621 | { | ||||
1622 | while (!rBuffer.empty()) | ||||
1623 | { | ||||
1624 | Buf_t aTuple(rBuffer.front()); | ||||
1625 | rBuffer.pop_front(); | ||||
1626 | if (std::get<0>(aTuple) == BUFFER_PROPS) | ||||
1627 | { | ||||
1628 | // Construct properties via getProperties() and not directly, to take care of deduplication. | ||||
1629 | writerfilter::Reference<Properties>::Pointer_t const pProp(getProperties( | ||||
1630 | std::get<1>(aTuple)->getAttributes(), std::get<1>(aTuple)->getSprms(), 0)); | ||||
1631 | Mapper().props(pProp); | ||||
1632 | } | ||||
1633 | else if (std::get<0>(aTuple) == BUFFER_NESTROW) | ||||
1634 | { | ||||
1635 | TableRowBuffer& rRowBuffer(*std::get<2>(aTuple)); | ||||
1636 | |||||
1637 | replayRowBuffer(rRowBuffer.GetBuffer(), rRowBuffer.GetCellsSprms(), | ||||
1638 | rRowBuffer.GetCellsAttributes(), rRowBuffer.GetCells()); | ||||
1639 | |||||
1640 | sendProperties(rRowBuffer.GetParaProperties(), rRowBuffer.GetFrameProperties(), | ||||
1641 | rRowBuffer.GetRowProperties()); | ||||
1642 | } | ||||
1643 | else if (std::get<0>(aTuple) == BUFFER_CELLEND) | ||||
1644 | { | ||||
1645 | assert(pSprms && pAttributes)(static_cast <bool> (pSprms && pAttributes) ? void (0) : __assert_fail ("pSprms && pAttributes", "/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" , 1645, __extension__ __PRETTY_FUNCTION__)); | ||||
1646 | auto pValue = new RTFValue(1); | ||||
1647 | pSprms->set(NS_ooxml::LN_tblCell, pValue); | ||||
1648 | writerfilter::Reference<Properties>::Pointer_t const pTableCellProperties( | ||||
1649 | new RTFReferenceProperties(*pAttributes, *pSprms)); | ||||
1650 | Mapper().props(pTableCellProperties); | ||||
1651 | tableBreak(); | ||||
1652 | break; | ||||
1653 | } | ||||
1654 | else if (std::get<0>(aTuple) == BUFFER_STARTRUN) | ||||
1655 | Mapper().startCharacterGroup(); | ||||
1656 | else if (std::get<0>(aTuple) == BUFFER_TEXT) | ||||
1657 | { | ||||
1658 | sal_uInt8 const nValue = std::get<1>(aTuple)->getInt(); | ||||
1659 | Mapper().text(&nValue, 1); | ||||
1660 | } | ||||
1661 | else if (std::get<0>(aTuple) == BUFFER_UTEXT) | ||||
1662 | { | ||||
1663 | OUString const aString(std::get<1>(aTuple)->getString()); | ||||
1664 | Mapper().utext(reinterpret_cast<sal_uInt8 const*>(aString.getStr()), | ||||
1665 | aString.getLength()); | ||||
1666 | } | ||||
1667 | else if (std::get<0>(aTuple) == BUFFER_ENDRUN) | ||||
1668 | Mapper().endCharacterGroup(); | ||||
1669 | else if (std::get<0>(aTuple) == BUFFER_PAR) | ||||
1670 | parBreak(); | ||||
1671 | else if (std::get<0>(aTuple) == BUFFER_STARTSHAPE) | ||||
1672 | m_pSdrImport->resolve(std::get<1>(aTuple)->getShape(), false, RTFSdrImport::SHAPE); | ||||
1673 | else if (std::get<0>(aTuple) == BUFFER_RESOLVESHAPE) | ||||
1674 | { | ||||
1675 | // Make sure there is no current buffer while replaying the shape, | ||||
1676 | // otherwise it gets re-buffered. | ||||
1677 | RTFBuffer_t* pCurrentBuffer = m_aStates.top().getCurrentBuffer(); | ||||
1678 | m_aStates.top().setCurrentBuffer(nullptr); | ||||
1679 | |||||
1680 | // Set current shape during replay, needed by e.g. wrap in | ||||
1681 | // background. | ||||
1682 | m_aStates.top().getShape() = std::get<1>(aTuple)->getShape(); | ||||
1683 | |||||
1684 | m_pSdrImport->resolve(std::get<1>(aTuple)->getShape(), true, RTFSdrImport::SHAPE); | ||||
1685 | m_aStates.top().setCurrentBuffer(pCurrentBuffer); | ||||
1686 | } | ||||
1687 | else if (std::get<0>(aTuple) == BUFFER_ENDSHAPE) | ||||
1688 | m_pSdrImport->close(); | ||||
1689 | else if (std::get<0>(aTuple) == BUFFER_RESOLVESUBSTREAM) | ||||
1690 | { | ||||
1691 | RTFSprms& rAttributes = std::get<1>(aTuple)->getAttributes(); | ||||
1692 | std::size_t nPos = rAttributes.find(0)->getInt(); | ||||
1693 | Id nId = rAttributes.find(1)->getInt(); | ||||
1694 | OUString aCustomMark = rAttributes.find(2)->getString(); | ||||
1695 | resolveSubstream(nPos, nId, aCustomMark); | ||||
1696 | } | ||||
1697 | else if (std::get<0>(aTuple) == BUFFER_PICTURE) | ||||
1698 | m_aStates.top().getPicture() = std::get<1>(aTuple)->getPicture(); | ||||
1699 | else if (std::get<0>(aTuple) == BUFFER_SETSTYLE) | ||||
1700 | { | ||||
1701 | if (!m_aStates.empty()) | ||||
1702 | m_aStates.top().setCurrentStyleIndex(std::get<1>(aTuple)->getInt()); | ||||
1703 | } | ||||
1704 | else | ||||
1705 | assert(false)(static_cast <bool> (false) ? void (0) : __assert_fail ( "false", "/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" , 1705, __extension__ __PRETTY_FUNCTION__)); | ||||
1706 | } | ||||
1707 | } | ||||
1708 | |||||
1709 | bool findPropertyName(const std::vector<beans::PropertyValue>& rProperties, const OUString& rName) | ||||
1710 | { | ||||
1711 | return std::any_of( | ||||
1712 | rProperties.begin(), rProperties.end(), | ||||
1713 | [&rName](const beans::PropertyValue& rProperty) { return rProperty.Name == rName; }); | ||||
1714 | } | ||||
1715 | |||||
1716 | void RTFDocumentImpl::backupTableRowProperties() | ||||
1717 | { | ||||
1718 | if (m_nTopLevelCurrentCellX) | ||||
1719 | { | ||||
1720 | m_aBackupTableRowSprms = m_aStates.top().getTableRowSprms(); | ||||
1721 | m_aBackupTableRowAttributes = m_aStates.top().getTableRowAttributes(); | ||||
1722 | m_nBackupTopLevelCurrentCellX = m_nTopLevelCurrentCellX; | ||||
1723 | } | ||||
1724 | } | ||||
1725 | |||||
1726 | void RTFDocumentImpl::restoreTableRowProperties() | ||||
1727 | { | ||||
1728 | m_aStates.top().getTableRowSprms() = m_aBackupTableRowSprms; | ||||
1729 | m_aStates.top().getTableRowAttributes() = m_aBackupTableRowAttributes; | ||||
1730 | m_nTopLevelCurrentCellX = m_nBackupTopLevelCurrentCellX; | ||||
1731 | } | ||||
1732 | |||||
1733 | void RTFDocumentImpl::resetTableRowProperties() | ||||
1734 | { | ||||
1735 | m_aStates.top().getTableRowSprms() = m_aDefaultState.getTableRowSprms(); | ||||
1736 | m_aStates.top().getTableRowSprms().set(NS_ooxml::LN_CT_TblGridBase_gridCol, new RTFValue(-1), | ||||
1737 | RTFOverwrite::NO_APPEND); | ||||
1738 | m_aStates.top().getTableRowAttributes() = m_aDefaultState.getTableRowAttributes(); | ||||
1739 | if (Destination::NESTEDTABLEPROPERTIES == m_aStates.top().getDestination()) | ||||
1740 | { | ||||
1741 | m_nNestedTRLeft = 0; | ||||
1742 | m_nNestedCurrentCellX = 0; | ||||
1743 | } | ||||
1744 | else | ||||
1745 | { | ||||
1746 | m_nTopLevelTRLeft = 0; | ||||
1747 | m_nTopLevelCurrentCellX = 0; | ||||
1748 | } | ||||
1749 | } | ||||
1750 | |||||
1751 | RTFError RTFDocumentImpl::dispatchToggle(RTFKeyword nKeyword, bool bParam, int nParam) | ||||
1752 | { | ||||
1753 | setNeedSect(true); | ||||
1754 | checkUnicode(/*bUnicode =*/true, /*bHex =*/true); | ||||
1755 | RTFSkipDestination aSkip(*this); | ||||
1756 | int nSprm = -1; | ||||
1757 | tools::SvRef<RTFValue> pBoolValue(new RTFValue(int(!bParam || nParam != 0))); | ||||
1758 | |||||
1759 | // Underline toggles. | ||||
1760 | switch (nKeyword) | ||||
1761 | { | ||||
1762 | case RTF_UL: | ||||
1763 | nSprm = NS_ooxml::LN_Value_ST_Underline_single; | ||||
1764 | break; | ||||
1765 | case RTF_ULDASH: | ||||
1766 | nSprm = NS_ooxml::LN_Value_ST_Underline_dash; | ||||
1767 | break; | ||||
1768 | case RTF_ULDASHD: | ||||
1769 | nSprm = NS_ooxml::LN_Value_ST_Underline_dotDash; | ||||
1770 | break; | ||||
1771 | case RTF_ULDASHDD: | ||||
1772 | nSprm = NS_ooxml::LN_Value_ST_Underline_dotDotDash; | ||||
1773 | break; | ||||
1774 | case RTF_ULDB: | ||||
1775 | nSprm = NS_ooxml::LN_Value_ST_Underline_double; | ||||
1776 | break; | ||||
1777 | case RTF_ULHWAVE: | ||||
1778 | nSprm = NS_ooxml::LN_Value_ST_Underline_wavyHeavy; | ||||
1779 | break; | ||||
1780 | case RTF_ULLDASH: | ||||
1781 | nSprm = NS_ooxml::LN_Value_ST_Underline_dashLong; | ||||
1782 | break; | ||||
1783 | case RTF_ULTH: | ||||
1784 | nSprm = NS_ooxml::LN_Value_ST_Underline_thick; | ||||
1785 | break; | ||||
1786 | case RTF_ULTHD: | ||||
1787 | nSprm = NS_ooxml::LN_Value_ST_Underline_dottedHeavy; | ||||
1788 | break; | ||||
1789 | case RTF_ULTHDASH: | ||||
1790 | nSprm = NS_ooxml::LN_Value_ST_Underline_dashedHeavy; | ||||
1791 | break; | ||||
1792 | case RTF_ULTHDASHD: | ||||
1793 | nSprm = NS_ooxml::LN_Value_ST_Underline_dashDotHeavy; | ||||
1794 | break; | ||||
1795 | case RTF_ULTHDASHDD: | ||||
1796 | nSprm = NS_ooxml::LN_Value_ST_Underline_dashDotDotHeavy; | ||||
1797 | break; | ||||
1798 | case RTF_ULTHLDASH: | ||||
1799 | nSprm = NS_ooxml::LN_Value_ST_Underline_dashLongHeavy; | ||||
1800 | break; | ||||
1801 | case RTF_ULULDBWAVE: | ||||
1802 | nSprm = NS_ooxml::LN_Value_ST_Underline_wavyDouble; | ||||
1803 | break; | ||||
1804 | case RTF_ULWAVE: | ||||
1805 | nSprm = NS_ooxml::LN_Value_ST_Underline_wave; | ||||
1806 | break; | ||||
1807 | default: | ||||
1808 | break; | ||||
1809 | } | ||||
1810 | if (nSprm >= 0) | ||||
1811 | { | ||||
1812 | auto pValue | ||||
1813 | = new RTFValue((!bParam || nParam != 0) ? nSprm : NS_ooxml::LN_Value_ST_Underline_none); | ||||
1814 | m_aStates.top().getCharacterAttributes().set(NS_ooxml::LN_CT_Underline_val, pValue); | ||||
1815 | return RTFError::OK; | ||||
1816 | } | ||||
1817 | |||||
1818 | // Accent characters (over dot / over comma). | ||||
1819 | switch (nKeyword) | ||||
1820 | { | ||||
1821 | case RTF_ACCNONE: | ||||
1822 | nSprm = NS_ooxml::LN_Value_ST_Em_none; | ||||
1823 | break; | ||||
1824 | case RTF_ACCDOT: | ||||
1825 | nSprm = NS_ooxml::LN_Value_ST_Em_dot; | ||||
1826 | break; | ||||
1827 | case RTF_ACCCOMMA: | ||||
1828 | nSprm = NS_ooxml::LN_Value_ST_Em_comma; | ||||
1829 | break; | ||||
1830 | case RTF_ACCCIRCLE: | ||||
1831 | nSprm = NS_ooxml::LN_Value_ST_Em_circle; | ||||
1832 | break; | ||||
1833 | case RTF_ACCUNDERDOT: | ||||
1834 | nSprm = NS_ooxml::LN_Value_ST_Em_underDot; | ||||
1835 | break; | ||||
1836 | default: | ||||
1837 | break; | ||||
1838 | } | ||||
1839 | if (nSprm >= 0) | ||||
1840 | { | ||||
1841 | auto pValue = new RTFValue((!bParam || nParam != 0) ? nSprm : 0); | ||||
1842 | m_aStates.top().getCharacterSprms().set(NS_ooxml::LN_EG_RPrBase_em, pValue); | ||||
1843 | return RTFError::OK; | ||||
1844 | } | ||||
1845 | |||||
1846 | // Trivial character sprms. | ||||
1847 | switch (nKeyword) | ||||
1848 | { | ||||
1849 | case RTF_B: | ||||
1850 | case RTF_AB: | ||||
1851 | switch (m_aStates.top().getRunType()) | ||||
1852 | { | ||||
1853 | case RTFParserState::RunType::HICH: | ||||
1854 | case RTFParserState::RunType::RTLCH_LTRCH_1: | ||||
1855 | case RTFParserState::RunType::LTRCH_RTLCH_2: | ||||
1856 | case RTFParserState::RunType::DBCH: | ||||
1857 | nSprm = NS_ooxml::LN_EG_RPrBase_bCs; | ||||
1858 | break; | ||||
1859 | case RTFParserState::RunType::NONE: | ||||
1860 | case RTFParserState::RunType::LOCH: | ||||
1861 | case RTFParserState::RunType::LTRCH_RTLCH_1: | ||||
1862 | case RTFParserState::RunType::RTLCH_LTRCH_2: | ||||
1863 | default: | ||||
1864 | nSprm = NS_ooxml::LN_EG_RPrBase_b; | ||||
1865 | break; | ||||
1866 | } | ||||
1867 | break; | ||||
1868 | case RTF_I: | ||||
1869 | case RTF_AI: | ||||
1870 | switch (m_aStates.top().getRunType()) | ||||
1871 | { | ||||
1872 | case RTFParserState::RunType::HICH: | ||||
1873 | case RTFParserState::RunType::RTLCH_LTRCH_1: | ||||
1874 | case RTFParserState::RunType::LTRCH_RTLCH_2: | ||||
1875 | case RTFParserState::RunType::DBCH: | ||||
1876 | nSprm = NS_ooxml::LN_EG_RPrBase_iCs; | ||||
1877 | break; | ||||
1878 | case RTFParserState::RunType::NONE: | ||||
1879 | case RTFParserState::RunType::LOCH: | ||||
1880 | case RTFParserState::RunType::LTRCH_RTLCH_1: | ||||
1881 | case RTFParserState::RunType::RTLCH_LTRCH_2: | ||||
1882 | default: | ||||
1883 | nSprm = NS_ooxml::LN_EG_RPrBase_i; | ||||
1884 | break; | ||||
1885 | } | ||||
1886 | break; | ||||
1887 | case RTF_OUTL: | ||||
1888 | nSprm = NS_ooxml::LN_EG_RPrBase_outline; | ||||
1889 | break; | ||||
1890 | case RTF_SHAD: | ||||
1891 | nSprm = NS_ooxml::LN_EG_RPrBase_shadow; | ||||
1892 | break; | ||||
1893 | case RTF_V: | ||||
1894 | nSprm = NS_ooxml::LN_EG_RPrBase_vanish; | ||||
1895 | break; | ||||
1896 | case RTF_STRIKE: | ||||
1897 | nSprm = NS_ooxml::LN_EG_RPrBase_strike; | ||||
1898 | break; | ||||
1899 | case RTF_STRIKED: | ||||
1900 | nSprm = NS_ooxml::LN_EG_RPrBase_dstrike; | ||||
1901 | break; | ||||
1902 | case RTF_SCAPS: | ||||
1903 | nSprm = NS_ooxml::LN_EG_RPrBase_smallCaps; | ||||
1904 | break; | ||||
1905 | case RTF_IMPR: | ||||
1906 | nSprm = NS_ooxml::LN_EG_RPrBase_imprint; | ||||
1907 | break; | ||||
1908 | case RTF_CAPS: | ||||
1909 | nSprm = NS_ooxml::LN_EG_RPrBase_caps; | ||||
1910 | break; | ||||
1911 | default: | ||||
1912 | break; | ||||
1913 | } | ||||
1914 | if (nSprm >= 0) | ||||
1915 | { | ||||
1916 | m_aStates.top().getCharacterSprms().set(nSprm, pBoolValue); | ||||
1917 | return RTFError::OK; | ||||
1918 | } | ||||
1919 | |||||
1920 | switch (nKeyword) | ||||
1921 | { | ||||
1922 | case RTF_ASPALPHA: | ||||
1923 | m_aStates.top().getParagraphSprms().set(NS_ooxml::LN_CT_PPrBase_autoSpaceDE, | ||||
1924 | pBoolValue); | ||||
1925 | break; | ||||
1926 | case RTF_DELETED: | ||||
1927 | case RTF_REVISED: | ||||
1928 | { | ||||
1929 | auto pValue = new RTFValue(nKeyword == RTF_DELETED ? oox::XML_del : oox::XML_ins); | ||||
1930 | putNestedAttribute(m_aStates.top().getCharacterSprms(), NS_ooxml::LN_trackchange, | ||||
1931 | NS_ooxml::LN_token, pValue); | ||||
1932 | } | ||||
1933 | break; | ||||
1934 | case RTF_SBAUTO: | ||||
1935 | putNestedAttribute(m_aStates.top().getParagraphSprms(), NS_ooxml::LN_CT_PPrBase_spacing, | ||||
1936 | NS_ooxml::LN_CT_Spacing_beforeAutospacing, pBoolValue); | ||||
1937 | break; | ||||
1938 | case RTF_SAAUTO: | ||||
1939 | putNestedAttribute(m_aStates.top().getParagraphSprms(), NS_ooxml::LN_CT_PPrBase_spacing, | ||||
1940 | NS_ooxml::LN_CT_Spacing_afterAutospacing, pBoolValue); | ||||
1941 | break; | ||||
1942 | case RTF_FACINGP: | ||||
1943 | m_aSettingsTableSprms.set(NS_ooxml::LN_CT_Settings_evenAndOddHeaders, pBoolValue); | ||||
1944 | break; | ||||
1945 | case RTF_HYPHAUTO: | ||||
1946 | m_aSettingsTableSprms.set(NS_ooxml::LN_CT_Settings_autoHyphenation, pBoolValue); | ||||
1947 | break; | ||||
1948 | case RTF_HYPHPAR: | ||||
1949 | m_aStates.top().getParagraphSprms().set(NS_ooxml::LN_CT_PPrBase_suppressAutoHyphens, | ||||
1950 | new RTFValue(int(bParam && nParam == 0))); | ||||
1951 | break; | ||||
1952 | default: | ||||
1953 | { | ||||
1954 | SAL_INFO("writerfilter.rtf",do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO , "writerfilter.rtf")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "TODO handle toggle '" << keywordToString(nKeyword) << "'") == 1) { ::sal_detail_log ( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "1955" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "TODO handle toggle '" << keywordToString (nKeyword) << "'"), 0); } else { ::std::ostringstream sal_detail_stream ; sal_detail_stream << "TODO handle toggle '" << keywordToString (nKeyword) << "'"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "1955" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "TODO handle toggle '" << keywordToString(nKeyword ) << "'") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "1955" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "TODO handle toggle '" << keywordToString (nKeyword) << "'"), 0); } else { ::std::ostringstream sal_detail_stream ; sal_detail_stream << "TODO handle toggle '" << keywordToString (nKeyword) << "'"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "1955" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false) | ||||
1955 | "TODO handle toggle '" << keywordToString(nKeyword) << "'")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO , "writerfilter.rtf")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "TODO handle toggle '" << keywordToString(nKeyword) << "'") == 1) { ::sal_detail_log ( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "1955" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "TODO handle toggle '" << keywordToString (nKeyword) << "'"), 0); } else { ::std::ostringstream sal_detail_stream ; sal_detail_stream << "TODO handle toggle '" << keywordToString (nKeyword) << "'"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "1955" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "TODO handle toggle '" << keywordToString(nKeyword ) << "'") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "1955" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "TODO handle toggle '" << keywordToString (nKeyword) << "'"), 0); } else { ::std::ostringstream sal_detail_stream ; sal_detail_stream << "TODO handle toggle '" << keywordToString (nKeyword) << "'"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "1955" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||
1956 | aSkip.setParsed(false); | ||||
1957 | } | ||||
1958 | break; | ||||
1959 | } | ||||
1960 | return RTFError::OK; | ||||
1961 | } | ||||
1962 | |||||
1963 | RTFError RTFDocumentImpl::pushState() | ||||
1964 | { | ||||
1965 | //SAL_INFO("writerfilter.rtf", __func__ << " before push: " << m_pTokenizer->getGroup()); | ||||
1966 | |||||
1967 | checkUnicode(/*bUnicode =*/true, /*bHex =*/true); | ||||
1968 | m_nGroupStartPos = Strm().Tell(); | ||||
1969 | |||||
1970 | if (m_aStates.empty()) | ||||
1971 | m_aStates.push(m_aDefaultState); | ||||
1972 | else | ||||
1973 | { | ||||
1974 | // fdo#85812 group resets run type of _current_ and new state (but not RTL) | ||||
1975 | if (m_aStates.top().getRunType() != RTFParserState::RunType::LTRCH_RTLCH_2 | ||||
1976 | && m_aStates.top().getRunType() != RTFParserState::RunType::RTLCH_LTRCH_2) | ||||
1977 | { | ||||
1978 | m_aStates.top().setRunType(RTFParserState::RunType::NONE); | ||||
1979 | } | ||||
1980 | |||||
1981 | if (m_aStates.top().getDestination() == Destination::MR) | ||||
1982 | lcl_DestinationToMath(m_aStates.top().getCurrentDestinationText(), m_aMathBuffer, | ||||
1983 | m_bMathNor); | ||||
1984 | m_aStates.push(m_aStates.top()); | ||||
1985 | } | ||||
1986 | m_aStates.top().getDestinationText().setLength(0); // was copied: always reset! | ||||
1987 | |||||
1988 | m_pTokenizer->pushGroup(); | ||||
1989 | |||||
1990 | switch (m_aStates.top().getDestination()) | ||||
1991 | { | ||||
1992 | case Destination::FONTTABLE: | ||||
1993 | // this is a "faked" destination for the font entry | ||||
1994 | m_aStates.top().setCurrentDestinationText(&m_aStates.top().getDestinationText()); | ||||
1995 | m_aStates.top().setDestination(Destination::FONTENTRY); | ||||
1996 | break; | ||||
1997 | case Destination::STYLESHEET: | ||||
1998 | // this is a "faked" destination for the style sheet entry | ||||
1999 | m_aStates.top().setCurrentDestinationText(&m_aStates.top().getDestinationText()); | ||||
2000 | m_aStates.top().setDestination(Destination::STYLEENTRY); | ||||
2001 | { | ||||
2002 | // the *default* is \s0 i.e. paragraph style default | ||||
2003 | // this will be overwritten by \sN \csN \dsN \tsN | ||||
2004 | m_nCurrentStyleIndex = 0; | ||||
2005 | auto pValue = new RTFValue(NS_ooxml::LN_Value_ST_StyleType_paragraph); | ||||
2006 | m_aStates.top().getTableAttributes().set(NS_ooxml::LN_CT_Style_type, pValue); | ||||
2007 | } | ||||
2008 | break; | ||||
2009 | case Destination::FIELDRESULT: | ||||
2010 | case Destination::SHAPETEXT: | ||||
2011 | case Destination::FORMFIELD: | ||||
2012 | case Destination::FIELDINSTRUCTION: | ||||
2013 | case Destination::PICT: | ||||
2014 | m_aStates.top().setDestination(Destination::NORMAL); | ||||
2015 | break; | ||||
2016 | case Destination::MNUM: | ||||
2017 | case Destination::MDEN: | ||||
2018 | case Destination::ME: | ||||
2019 | case Destination::MFNAME: | ||||
2020 | case Destination::MLIM: | ||||
2021 | case Destination::MSUB: | ||||
2022 | case Destination::MSUP: | ||||
2023 | case Destination::MDEG: | ||||
2024 | case Destination::MOMATH: | ||||
2025 | m_aStates.top().setDestination(Destination::MR); | ||||
2026 | break; | ||||
2027 | case Destination::REVISIONTABLE: | ||||
2028 | // this is a "faked" destination for the revision table entry | ||||
2029 | m_aStates.top().setCurrentDestinationText(&m_aStates.top().getDestinationText()); | ||||
2030 | m_aStates.top().setDestination(Destination::REVISIONENTRY); | ||||
2031 | break; | ||||
2032 | default: | ||||
2033 | break; | ||||
2034 | } | ||||
2035 | |||||
2036 | // If this is true, then ooxml:endtrackchange will be generated. Make sure | ||||
2037 | // we don't generate more ooxml:endtrackchange than ooxml:trackchange: new | ||||
2038 | // state does not inherit this flag. | ||||
2039 | m_aStates.top().setStartedTrackchange(false); | ||||
2040 | |||||
2041 | return RTFError::OK; | ||||
2042 | } | ||||
2043 | |||||
2044 | writerfilter::Reference<Properties>::Pointer_t RTFDocumentImpl::createStyleProperties() | ||||
2045 | { | ||||
2046 | int nBasedOn = 0; | ||||
2047 | RTFValue::Pointer_t pBasedOn | ||||
2048 | = m_aStates.top().getTableSprms().find(NS_ooxml::LN_CT_Style_basedOn); | ||||
2049 | if (pBasedOn) | ||||
2050 | nBasedOn = pBasedOn->getInt(); | ||||
2051 | if (nBasedOn == 0) | ||||
2052 | { | ||||
2053 | // No parent style, then mimic what Word does: ignore attributes which | ||||
2054 | // would set a margin as formatting, but with a default value. | ||||
2055 | for (const auto& nId : | ||||
2056 | { NS_ooxml::LN_CT_Ind_firstLine, NS_ooxml::LN_CT_Ind_left, NS_ooxml::LN_CT_Ind_right, | ||||
2057 | NS_ooxml::LN_CT_Ind_start, NS_ooxml::LN_CT_Ind_end }) | ||||
2058 | { | ||||
2059 | RTFValue::Pointer_t pValue = getNestedAttribute(m_aStates.top().getParagraphSprms(), | ||||
2060 | NS_ooxml::LN_CT_PPrBase_ind, nId); | ||||
2061 | if (pValue && pValue->getInt() == 0) | ||||
2062 | eraseNestedAttribute(m_aStates.top().getParagraphSprms(), | ||||
2063 | NS_ooxml::LN_CT_PPrBase_ind, nId); | ||||
2064 | } | ||||
2065 | } | ||||
2066 | |||||
2067 | RTFValue::Pointer_t pParaProps = new RTFValue(m_aStates.top().getParagraphAttributes(), | ||||
2068 | m_aStates.top().getParagraphSprms()); | ||||
2069 | RTFValue::Pointer_t pCharProps = new RTFValue(m_aStates.top().getCharacterAttributes(), | ||||
2070 | m_aStates.top().getCharacterSprms()); | ||||
2071 | |||||
2072 | // resetSprms will clean up this modification | ||||
2073 | m_aStates.top().getTableSprms().set(NS_ooxml::LN_CT_Style_pPr, pParaProps); | ||||
2074 | m_aStates.top().getTableSprms().set(NS_ooxml::LN_CT_Style_rPr, pCharProps); | ||||
2075 | |||||
2076 | writerfilter::Reference<Properties>::Pointer_t pProps(new RTFReferenceProperties( | ||||
2077 | m_aStates.top().getTableAttributes(), m_aStates.top().getTableSprms())); | ||||
2078 | return pProps; | ||||
2079 | } | ||||
2080 | |||||
2081 | /** 2 different representations of the styles are needed: | ||||
2082 | |||||
2083 | 1) flat content, as read from the input file: | ||||
2084 | stored in m_aStyleTableEntries, used as reference input for | ||||
2085 | deduplication both here and for hard formatting in getProperties() | ||||
2086 | |||||
2087 | 2) real content, with proper override of sprms/attributes where it differs | ||||
2088 | from parent style; this is produced here and sent to domain mapper | ||||
2089 | */ | ||||
2090 | RTFReferenceTable::Entries_t RTFDocumentImpl::deduplicateStyleTable() | ||||
2091 | { | ||||
2092 | RTFReferenceTable::Entries_t ret; | ||||
2093 | for (auto const& it : m_aStyleTableEntries) | ||||
2094 | { | ||||
2095 | auto pStyle = it.second; | ||||
2096 | ret[it.first] = pStyle; | ||||
2097 | // ugly downcasts here, but can't easily replace the members with | ||||
2098 | // RTFReferenceProperties because dmapper wants SvRef<Properties> anyway | ||||
2099 | RTFValue::Pointer_t const pBasedOn( | ||||
2100 | static_cast<RTFReferenceProperties&>(*pStyle).getSprms().find( | ||||
2101 | NS_ooxml::LN_CT_Style_basedOn)); | ||||
2102 | if (pBasedOn) | ||||
2103 | { | ||||
2104 | int const nBasedOn(pBasedOn->getInt()); | ||||
2105 | // don't deduplicate yourself - especially a potential problem for the default style. | ||||
2106 | if (it.first == nBasedOn) | ||||
2107 | continue; | ||||
2108 | |||||
2109 | auto const itParent(m_aStyleTableEntries.find(nBasedOn)); // definition as read! | ||||
2110 | if (itParent != m_aStyleTableEntries.end()) | ||||
2111 | { | ||||
2112 | auto const pStyleType( | ||||
2113 | static_cast<RTFReferenceProperties&>(*pStyle).getAttributes().find( | ||||
2114 | NS_ooxml::LN_CT_Style_type)); | ||||
2115 | assert(pStyleType)(static_cast <bool> (pStyleType) ? void (0) : __assert_fail ("pStyleType", "/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" , 2115, __extension__ __PRETTY_FUNCTION__)); | ||||
2116 | int const nStyleType(pStyleType->getInt()); | ||||
2117 | RTFSprms const sprms( | ||||
2118 | static_cast<RTFReferenceProperties&>(*pStyle).getSprms().cloneAndDeduplicate( | ||||
2119 | static_cast<RTFReferenceProperties&>(*itParent->second).getSprms(), | ||||
2120 | nStyleType)); | ||||
2121 | RTFSprms const attributes( | ||||
2122 | static_cast<RTFReferenceProperties&>(*pStyle) | ||||
2123 | .getAttributes() | ||||
2124 | .cloneAndDeduplicate( | ||||
2125 | static_cast<RTFReferenceProperties&>(*itParent->second).getAttributes(), | ||||
2126 | nStyleType)); | ||||
2127 | |||||
2128 | ret[it.first] = new RTFReferenceProperties(attributes, sprms); | ||||
2129 | } | ||||
2130 | else | ||||
2131 | { | ||||
2132 | SAL_WARN("writerfilter.rtf", "parent style not found: " << nBasedOn)do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN , "writerfilter.rtf")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "parent style not found: " << nBasedOn) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "2132" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "parent style not found: " << nBasedOn ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "parent style not found: " << nBasedOn; ::sal ::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "2132" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "parent style not found: " << nBasedOn) == 1 ) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "2132" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "parent style not found: " << nBasedOn ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "parent style not found: " << nBasedOn; ::sal ::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "2132" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||
2133 | } | ||||
2134 | } | ||||
2135 | } | ||||
2136 | assert(ret.size() == m_aStyleTableEntries.size())(static_cast <bool> (ret.size() == m_aStyleTableEntries .size()) ? void (0) : __assert_fail ("ret.size() == m_aStyleTableEntries.size()" , "/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" , 2136, __extension__ __PRETTY_FUNCTION__)); | ||||
2137 | return ret; | ||||
2138 | } | ||||
2139 | |||||
2140 | void RTFDocumentImpl::resetSprms() | ||||
2141 | { | ||||
2142 | m_aStates.top().getTableSprms().clear(); | ||||
2143 | m_aStates.top().getCharacterSprms().clear(); | ||||
2144 | m_aStates.top().getParagraphSprms().clear(); | ||||
2145 | } | ||||
2146 | |||||
2147 | void RTFDocumentImpl::resetAttributes() | ||||
2148 | { | ||||
2149 | m_aStates.top().getTableAttributes().clear(); | ||||
2150 | m_aStates.top().getCharacterAttributes().clear(); | ||||
2151 | m_aStates.top().getParagraphAttributes().clear(); | ||||
2152 | } | ||||
2153 | |||||
2154 | static bool lcl_containsProperty(const uno::Sequence<beans::Property>& rProperties, | ||||
2155 | const OUString& rName) | ||||
2156 | { | ||||
2157 | return std::any_of(rProperties.begin(), rProperties.end(), | ||||
2158 | [&](const beans::Property& rProperty) { return rProperty.Name == rName; }); | ||||
2159 | } | ||||
2160 | |||||
2161 | RTFError RTFDocumentImpl::beforePopState(RTFParserState& rState) | ||||
2162 | { | ||||
2163 | switch (rState.getDestination()) | ||||
2164 | { | ||||
2165 | case Destination::FONTTABLE: | ||||
2166 | { | ||||
2167 | writerfilter::Reference<Table>::Pointer_t const pTable( | ||||
2168 | new RTFReferenceTable(m_aFontTableEntries)); | ||||
2169 | Mapper().table(NS_ooxml::LN_FONTTABLE, pTable); | ||||
2170 | if (m_nDefaultFontIndex >= 0) | ||||
2171 | { | ||||
2172 | auto pValue = new RTFValue(m_aFontNames[getFontIndex(m_nDefaultFontIndex)]); | ||||
2173 | putNestedAttribute(m_aDefaultState.getCharacterSprms(), | ||||
2174 | NS_ooxml::LN_EG_RPrBase_rFonts, NS_ooxml::LN_CT_Fonts_ascii, | ||||
2175 | pValue); | ||||
2176 | } | ||||
2177 | } | ||||
2178 | break; | ||||
2179 | case Destination::STYLESHEET: | ||||
2180 | { | ||||
2181 | RTFReferenceTable::Entries_t const pStyleTableDeduplicated(deduplicateStyleTable()); | ||||
2182 | writerfilter::Reference<Table>::Pointer_t const pTable( | ||||
2183 | new RTFReferenceTable(pStyleTableDeduplicated)); | ||||
2184 | Mapper().table(NS_ooxml::LN_STYLESHEET, pTable); | ||||
2185 | } | ||||
2186 | break; | ||||
2187 | case Destination::LISTOVERRIDETABLE: | ||||
2188 | { | ||||
2189 | RTFSprms aListTableAttributes; | ||||
2190 | writerfilter::Reference<Properties>::Pointer_t pProp | ||||
2191 | = new RTFReferenceProperties(aListTableAttributes, m_aListTableSprms); | ||||
2192 | RTFReferenceTable::Entries_t aListTableEntries; | ||||
2193 | aListTableEntries.insert(std::make_pair(0, pProp)); | ||||
2194 | writerfilter::Reference<Table>::Pointer_t const pTable( | ||||
2195 | new RTFReferenceTable(aListTableEntries)); | ||||
2196 | Mapper().table(NS_ooxml::LN_NUMBERING, pTable); | ||||
2197 | } | ||||
2198 | break; | ||||
2199 | case Destination::LISTENTRY: | ||||
2200 | for (const auto& rListLevelEntry : rState.getListLevelEntries()) | ||||
2201 | rState.getTableSprms().set(rListLevelEntry.first, rListLevelEntry.second, | ||||
2202 | RTFOverwrite::NO_APPEND); | ||||
2203 | break; | ||||
2204 | case Destination::FIELDINSTRUCTION: | ||||
2205 | { | ||||
2206 | auto pValue = new RTFValue(m_aFormfieldAttributes, m_aFormfieldSprms); | ||||
2207 | RTFSprms aFFAttributes; | ||||
2208 | RTFSprms aFFSprms; | ||||
2209 | aFFSprms.set(NS_ooxml::LN_ffdata, pValue); | ||||
2210 | if (!m_aStates.top().getCurrentBuffer()) | ||||
2211 | { | ||||
2212 | writerfilter::Reference<Properties>::Pointer_t pProperties | ||||
2213 | = new RTFReferenceProperties(aFFAttributes, aFFSprms); | ||||
2214 | Mapper().props(pProperties); | ||||
2215 | } | ||||
2216 | else | ||||
2217 | { | ||||
2218 | auto pFFValue = new RTFValue(aFFAttributes, aFFSprms); | ||||
2219 | bufferProperties(*m_aStates.top().getCurrentBuffer(), pFFValue, nullptr); | ||||
2220 | } | ||||
2221 | m_aFormfieldAttributes.clear(); | ||||
2222 | m_aFormfieldSprms.clear(); | ||||
2223 | singleChar(cFieldSep); | ||||
2224 | } | ||||
2225 | break; | ||||
2226 | case Destination::FIELDRESULT: | ||||
2227 | singleChar(cFieldEnd); | ||||
2228 | |||||
2229 | if (!m_aPicturePath.isEmpty()) | ||||
2230 | { | ||||
2231 | // Read the picture into m_aStates.top().aDestinationText. | ||||
2232 | pushState(); | ||||
2233 | dispatchDestination(RTF_PICT); | ||||
2234 | if (m_aPicturePath.endsWith(".png")) | ||||
2235 | dispatchFlag(RTF_PNGBLIP); | ||||
2236 | OUString aFileURL = m_rMediaDescriptor.getUnpackedValueOrDefault( | ||||
2237 | utl::MediaDescriptor::PROP_URL(), OUString()); | ||||
2238 | OUString aPictureURL; | ||||
2239 | try | ||||
2240 | { | ||||
2241 | aPictureURL = rtl::Uri::convertRelToAbs(aFileURL, m_aPicturePath); | ||||
2242 | } | ||||
2243 | catch (const rtl::MalformedUriException& rException) | ||||
2244 | { | ||||
2245 | SAL_WARN("writerfilter.rtf",do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN , "writerfilter.rtf")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "rtl::Uri::convertRelToAbs() failed: " << rException.getMessage()) == 1) { ::sal_detail_log( ( ::SAL_DETAIL_LOG_LEVEL_WARN), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "2246" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "rtl::Uri::convertRelToAbs() failed: " << rException.getMessage()), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "rtl::Uri::convertRelToAbs() failed: " << rException.getMessage(); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "2246" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "rtl::Uri::convertRelToAbs() failed: " << rException .getMessage()) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "2246" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "rtl::Uri::convertRelToAbs() failed: " << rException.getMessage()), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "rtl::Uri::convertRelToAbs() failed: " << rException.getMessage(); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "2246" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false) | ||||
2246 | "rtl::Uri::convertRelToAbs() failed: " << rException.getMessage())do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN , "writerfilter.rtf")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "rtl::Uri::convertRelToAbs() failed: " << rException.getMessage()) == 1) { ::sal_detail_log( ( ::SAL_DETAIL_LOG_LEVEL_WARN), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "2246" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "rtl::Uri::convertRelToAbs() failed: " << rException.getMessage()), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "rtl::Uri::convertRelToAbs() failed: " << rException.getMessage(); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "2246" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "rtl::Uri::convertRelToAbs() failed: " << rException .getMessage()) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "2246" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "rtl::Uri::convertRelToAbs() failed: " << rException.getMessage()), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "rtl::Uri::convertRelToAbs() failed: " << rException.getMessage(); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "2246" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||
2247 | } | ||||
2248 | |||||
2249 | if (!aPictureURL.isEmpty()) | ||||
2250 | { | ||||
2251 | SvFileStream aStream(aPictureURL, StreamMode::READ); | ||||
2252 | if (aStream.IsOpen()) | ||||
2253 | { | ||||
2254 | OUStringBuffer aBuf; | ||||
2255 | while (aStream.good()) | ||||
2256 | { | ||||
2257 | unsigned char ch = 0; | ||||
2258 | aStream.ReadUChar(ch); | ||||
2259 | if (ch < 16) | ||||
2260 | aBuf.append("0"); | ||||
2261 | aBuf.append(OUString::number(ch, 16)); | ||||
2262 | } | ||||
2263 | m_aStates.top().getDestinationText() = aBuf; | ||||
2264 | } | ||||
2265 | } | ||||
2266 | popState(); | ||||
2267 | m_aPicturePath.clear(); | ||||
2268 | } | ||||
2269 | |||||
2270 | break; | ||||
2271 | case Destination::LEVELTEXT: | ||||
2272 | { | ||||
2273 | if (&m_aStates.top().getDestinationText() | ||||
2274 | != m_aStates.top().getCurrentDestinationText()) | ||||
2275 | break; // not for nested group | ||||
2276 | OUString aStr = m_aStates.top().getCurrentDestinationText()->makeStringAndClear(); | ||||
2277 | |||||
2278 | // The first character is the length of the string (the rest should be ignored). | ||||
2279 | sal_Int32 nLength(aStr.toChar()); | ||||
2280 | OUString aValue; | ||||
2281 | if (nLength < aStr.getLength()) | ||||
2282 | aValue = aStr.copy(1, nLength); | ||||
2283 | else | ||||
2284 | aValue = aStr; | ||||
2285 | auto pValue = new RTFValue(aValue, true); | ||||
2286 | rState.getTableAttributes().set(NS_ooxml::LN_CT_LevelText_val, pValue); | ||||
2287 | } | ||||
2288 | break; | ||||
2289 | case Destination::LEVELNUMBERS: | ||||
2290 | { | ||||
2291 | bool bNestedLevelNumbers = false; | ||||
2292 | if (m_aStates.size() > 1) | ||||
2293 | // Current destination is levelnumbers and parent destination is levelnumbers as well. | ||||
2294 | bNestedLevelNumbers | ||||
2295 | = m_aStates[m_aStates.size() - 2].getDestination() == Destination::LEVELNUMBERS; | ||||
2296 | if (!bNestedLevelNumbers && rState.getTableSprms().find(NS_ooxml::LN_CT_Lvl_lvlText)) | ||||
2297 | { | ||||
2298 | RTFSprms& rAttributes | ||||
2299 | = rState.getTableSprms().find(NS_ooxml::LN_CT_Lvl_lvlText)->getAttributes(); | ||||
2300 | RTFValue::Pointer_t pValue = rAttributes.find(NS_ooxml::LN_CT_LevelText_val); | ||||
2301 | if (pValue && rState.getLevelNumbersValid()) | ||||
2302 | { | ||||
2303 | OUString aOrig = pValue->getString(); | ||||
2304 | |||||
2305 | OUStringBuffer aBuf(aOrig.getLength() * 2); | ||||
2306 | sal_Int32 nReplaces = 1; | ||||
2307 | for (int i = 0; i < aOrig.getLength(); i++) | ||||
2308 | { | ||||
2309 | if (std::find(rState.getLevelNumbers().begin(), | ||||
2310 | rState.getLevelNumbers().end(), i + 1) | ||||
2311 | != rState.getLevelNumbers().end()) | ||||
2312 | { | ||||
2313 | aBuf.append('%'); | ||||
2314 | // '1.1.1' -> '%1.%2.%3', but '1.' (with '2.' prefix omitted) is %2. | ||||
2315 | aBuf.append(sal_Int32(nReplaces++ + rState.getListLevelNum() + 1 | ||||
2316 | - rState.getLevelNumbers().size())); | ||||
2317 | } | ||||
2318 | else | ||||
2319 | aBuf.append(aOrig[i]); | ||||
2320 | } | ||||
2321 | |||||
2322 | pValue->setString(aBuf.makeStringAndClear()); | ||||
2323 | } | ||||
2324 | else if (pValue) | ||||
2325 | // Have a value, but levelnumbers is not valid -> ignore it. | ||||
2326 | pValue->setString(OUString()); | ||||
2327 | } | ||||
2328 | break; | ||||
2329 | } | ||||
2330 | case Destination::SHAPEPROPERTYNAME: | ||||
2331 | if (&m_aStates.top().getDestinationText() | ||||
2332 | != m_aStates.top().getCurrentDestinationText()) | ||||
2333 | break; // not for nested group | ||||
2334 | rState.getShape().getProperties().emplace_back( | ||||
2335 | m_aStates.top().getCurrentDestinationText()->makeStringAndClear(), OUString()); | ||||
2336 | break; | ||||
2337 | case Destination::SHAPEPROPERTYVALUE: | ||||
2338 | if (!rState.getShape().getProperties().empty()) | ||||
2339 | { | ||||
2340 | rState.getShape().getProperties().back().second | ||||
2341 | = m_aStates.top().getCurrentDestinationText()->makeStringAndClear(); | ||||
2342 | if (m_aStates.top().getHadShapeText()) | ||||
2343 | m_pSdrImport->append(rState.getShape().getProperties().back().first, | ||||
2344 | rState.getShape().getProperties().back().second); | ||||
2345 | else if (rState.getInShapeGroup() && !rState.getInShape() | ||||
2346 | && rState.getShape().getProperties().back().first == "rotation") | ||||
2347 | { | ||||
2348 | // Rotation should be applied on the groupshape itself, not on each shape. | ||||
2349 | rState.getShape().getGroupProperties().push_back( | ||||
2350 | rState.getShape().getProperties().back()); | ||||
2351 | rState.getShape().getProperties().pop_back(); | ||||
2352 | } | ||||
2353 | } | ||||
2354 | break; | ||||
2355 | case Destination::PICPROP: | ||||
2356 | case Destination::SHAPEINSTRUCTION: | ||||
2357 | if (m_aStates.size() > 1 | ||||
2358 | && m_aStates[m_aStates.size() - 2].getDestination() | ||||
2359 | == Destination::SHAPEINSTRUCTION) | ||||
2360 | { | ||||
2361 | // Do not resolve shape if shape instruction destination is inside other shape instruction | ||||
2362 | } | ||||
2363 | else if (!m_bObject && !rState.getInListpicture() && !rState.getHadShapeText() | ||||
2364 | && (!rState.getInShapeGroup() || rState.getInShape())) | ||||
2365 | { | ||||
2366 | // Don't trigger a shape import in case we're only leaving the \shpinst of the groupshape itself. | ||||
2367 | RTFSdrImport::ShapeOrPict eType | ||||
2368 | = (rState.getDestination() == Destination::SHAPEINSTRUCTION) | ||||
2369 | ? RTFSdrImport::SHAPE | ||||
2370 | : RTFSdrImport::PICT; | ||||
2371 | if (!m_aStates.top().getCurrentBuffer() || eType != RTFSdrImport::SHAPE) | ||||
2372 | m_pSdrImport->resolve(m_aStates.top().getShape(), true, eType); | ||||
2373 | else | ||||
2374 | { | ||||
2375 | // Shape inside table: buffer the import to have correct anchor position. | ||||
2376 | // Also buffer the RTFPicture of the state stack as it contains | ||||
2377 | // the shape size. | ||||
2378 | auto pPictureValue = new RTFValue(m_aStates.top().getPicture()); | ||||
2379 | m_aStates.top().getCurrentBuffer()->push_back( | ||||
2380 | Buf_t(BUFFER_PICTURE, pPictureValue, nullptr)); | ||||
2381 | auto pValue = new RTFValue(m_aStates.top().getShape()); | ||||
2382 | |||||
2383 | // Buffer wrap type. | ||||
2384 | for (const auto& rCharacterSprm : m_aStates.top().getCharacterSprms()) | ||||
2385 | { | ||||
2386 | if (rCharacterSprm.first == NS_ooxml::LN_EG_WrapType_wrapNone | ||||
2387 | || rCharacterSprm.first == NS_ooxml::LN_EG_WrapType_wrapTight) | ||||
2388 | { | ||||
2389 | m_aStates.top().getShape().getWrapSprm() = rCharacterSprm; | ||||
2390 | break; | ||||
2391 | } | ||||
2392 | } | ||||
2393 | |||||
2394 | m_aStates.top().getCurrentBuffer()->push_back( | ||||
2395 | Buf_t(BUFFER_RESOLVESHAPE, pValue, nullptr)); | ||||
2396 | } | ||||
2397 | } | ||||
2398 | else if (rState.getInShapeGroup() && !rState.getInShape()) | ||||
2399 | { | ||||
2400 | // End of a groupshape, as we're in shapegroup, but not in a real shape. | ||||
2401 | for (const auto& rGroupProperty : rState.getShape().getGroupProperties()) | ||||
2402 | m_pSdrImport->appendGroupProperty(rGroupProperty.first, rGroupProperty.second); | ||||
2403 | rState.getShape().getGroupProperties().clear(); | ||||
2404 | } | ||||
2405 | break; | ||||
2406 | case Destination::BOOKMARKSTART: | ||||
2407 | { | ||||
2408 | if (&m_aStates.top().getDestinationText() | ||||
2409 | != m_aStates.top().getCurrentDestinationText()) | ||||
2410 | break; // not for nested group | ||||
2411 | OUString aStr = m_aStates.top().getCurrentDestinationText()->makeStringAndClear(); | ||||
2412 | int nPos = m_aBookmarks.size(); | ||||
2413 | m_aBookmarks[aStr] = nPos; | ||||
2414 | if (!m_aStates.top().getCurrentBuffer()) | ||||
2415 | Mapper().props(new RTFReferenceProperties(lcl_getBookmarkProperties(nPos, aStr))); | ||||
2416 | else | ||||
2417 | bufferProperties(*m_aStates.top().getCurrentBuffer(), | ||||
2418 | new RTFValue(lcl_getBookmarkProperties(nPos, aStr)), nullptr); | ||||
2419 | } | ||||
2420 | break; | ||||
2421 | case Destination::BOOKMARKEND: | ||||
2422 | { | ||||
2423 | if (&m_aStates.top().getDestinationText() | ||||
2424 | != m_aStates.top().getCurrentDestinationText()) | ||||
2425 | break; // not for nested group | ||||
2426 | OUString aStr = m_aStates.top().getCurrentDestinationText()->makeStringAndClear(); | ||||
2427 | if (!m_aStates.top().getCurrentBuffer()) | ||||
2428 | Mapper().props(new RTFReferenceProperties( | ||||
2429 | lcl_getBookmarkProperties(m_aBookmarks[aStr], aStr))); | ||||
2430 | else | ||||
2431 | bufferProperties(*m_aStates.top().getCurrentBuffer(), | ||||
2432 | new RTFValue(lcl_getBookmarkProperties(m_aBookmarks[aStr], aStr)), | ||||
2433 | nullptr); | ||||
2434 | } | ||||
2435 | break; | ||||
2436 | case Destination::INDEXENTRY: | ||||
2437 | case Destination::TOCENTRY: | ||||
2438 | { | ||||
2439 | if (&m_aStates.top().getDestinationText() | ||||
2440 | != m_aStates.top().getCurrentDestinationText()) | ||||
2441 | break; // not for nested group | ||||
2442 | OUString str(m_aStates.top().getCurrentDestinationText()->makeStringAndClear()); | ||||
2443 | // dmapper expects this as a field, so let's fake something... | ||||
2444 | auto const field((Destination::INDEXENTRY == rState.getDestination()) | ||||
2445 | ? OUStringLiteral(u"XE") | ||||
2446 | : OUStringLiteral(u"TC")); | ||||
2447 | str = field + " \"" + str.replaceAll("\"", "\\\"") + "\""; | ||||
2448 | singleChar(cFieldStart); | ||||
2449 | Mapper().utext(reinterpret_cast<sal_uInt8 const*>(str.getStr()), str.getLength()); | ||||
2450 | singleChar(cFieldSep); | ||||
2451 | // no result | ||||
2452 | singleChar(cFieldEnd); | ||||
2453 | } | ||||
2454 | break; | ||||
2455 | case Destination::FORMFIELDNAME: | ||||
2456 | { | ||||
2457 | if (&m_aStates.top().getDestinationText() | ||||
2458 | != m_aStates.top().getCurrentDestinationText()) | ||||
2459 | break; // not for nested group | ||||
2460 | auto pValue | ||||
2461 | = new RTFValue(m_aStates.top().getCurrentDestinationText()->makeStringAndClear()); | ||||
2462 | m_aFormfieldSprms.set(NS_ooxml::LN_CT_FFData_name, pValue); | ||||
2463 | } | ||||
2464 | break; | ||||
2465 | case Destination::FORMFIELDLIST: | ||||
2466 | { | ||||
2467 | if (&m_aStates.top().getDestinationText() | ||||
2468 | != m_aStates.top().getCurrentDestinationText()) | ||||
2469 | break; // not for nested group | ||||
2470 | auto pValue | ||||
2471 | = new RTFValue(m_aStates.top().getCurrentDestinationText()->makeStringAndClear()); | ||||
2472 | m_aFormfieldSprms.set(NS_ooxml::LN_CT_FFDDList_listEntry, pValue); | ||||
2473 | } | ||||
2474 | break; | ||||
2475 | case Destination::DATAFIELD: | ||||
2476 | { | ||||
2477 | if (m_bFormField) | ||||
2478 | { | ||||
2479 | if (&m_aStates.top().getDestinationText() | ||||
2480 | != m_aStates.top().getCurrentDestinationText()) | ||||
2481 | break; // not for nested group | ||||
2482 | OString aStr = OUStringToOString( | ||||
2483 | m_aStates.top().getCurrentDestinationText()->makeStringAndClear(), | ||||
2484 | rState.getCurrentEncoding()); | ||||
2485 | // decode hex dump | ||||
2486 | OStringBuffer aBuf; | ||||
2487 | int b = 0; | ||||
2488 | int count = 2; | ||||
2489 | for (int i = 0; i < aStr.getLength(); ++i) | ||||
2490 | { | ||||
2491 | char ch = aStr[i]; | ||||
2492 | if (ch != 0x0d && ch != 0x0a) | ||||
2493 | { | ||||
2494 | b = b << 4; | ||||
2495 | sal_Int8 parsed = msfilter::rtfutil::AsHex(ch); | ||||
2496 | if (parsed == -1) | ||||
2497 | return RTFError::HEX_INVALID; | ||||
2498 | b += parsed; | ||||
2499 | count--; | ||||
2500 | if (!count) | ||||
2501 | { | ||||
2502 | aBuf.append(static_cast<char>(b)); | ||||
2503 | count = 2; | ||||
2504 | b = 0; | ||||
2505 | } | ||||
2506 | } | ||||
2507 | } | ||||
2508 | aStr = aBuf.makeStringAndClear(); | ||||
2509 | |||||
2510 | // ignore the first bytes | ||||
2511 | if (aStr.getLength() > 8) | ||||
2512 | aStr = aStr.copy(8); | ||||
2513 | // extract name | ||||
2514 | sal_Int32 nLength = aStr.toChar(); | ||||
2515 | if (!aStr.isEmpty()) | ||||
2516 | aStr = aStr.copy(1); | ||||
2517 | nLength = std::min(nLength, aStr.getLength()); | ||||
2518 | OString aName = aStr.copy(0, nLength); | ||||
2519 | if (aStr.getLength() > nLength) | ||||
2520 | aStr = aStr.copy(nLength + 1); // zero-terminated string | ||||
2521 | else | ||||
2522 | aStr.clear(); | ||||
2523 | // extract default text | ||||
2524 | nLength = aStr.toChar(); | ||||
2525 | if (!aStr.isEmpty()) | ||||
2526 | aStr = aStr.copy(1); | ||||
2527 | auto pNValue = new RTFValue(OStringToOUString(aName, rState.getCurrentEncoding())); | ||||
2528 | m_aFormfieldSprms.set(NS_ooxml::LN_CT_FFData_name, pNValue); | ||||
2529 | if (nLength > 0) | ||||
2530 | { | ||||
2531 | OString aDefaultText = aStr.copy(0, std::min(nLength, aStr.getLength())); | ||||
2532 | auto pDValue = new RTFValue( | ||||
2533 | OStringToOUString(aDefaultText, rState.getCurrentEncoding())); | ||||
2534 | m_aFormfieldSprms.set(NS_ooxml::LN_CT_FFTextInput_default, pDValue); | ||||
2535 | } | ||||
2536 | |||||
2537 | m_bFormField = false; | ||||
2538 | } | ||||
2539 | } | ||||
2540 | break; | ||||
2541 | case Destination::CREATIONTIME: | ||||
2542 | if (m_xDocumentProperties.is()) | ||||
2543 | m_xDocumentProperties->setCreationDate(lcl_getDateTime(rState)); | ||||
2544 | break; | ||||
2545 | case Destination::REVISIONTIME: | ||||
2546 | if (m_xDocumentProperties.is()) | ||||
2547 | m_xDocumentProperties->setModificationDate(lcl_getDateTime(rState)); | ||||
2548 | break; | ||||
2549 | case Destination::PRINTTIME: | ||||
2550 | if (m_xDocumentProperties.is()) | ||||
2551 | m_xDocumentProperties->setPrintDate(lcl_getDateTime(rState)); | ||||
2552 | break; | ||||
2553 | case Destination::AUTHOR: | ||||
2554 | if (&m_aStates.top().getDestinationText() | ||||
2555 | != m_aStates.top().getCurrentDestinationText()) | ||||
2556 | break; // not for nested group | ||||
2557 | if (m_xDocumentProperties.is()) | ||||
2558 | m_xDocumentProperties->setAuthor( | ||||
2559 | m_aStates.top().getCurrentDestinationText()->makeStringAndClear()); | ||||
2560 | break; | ||||
2561 | case Destination::KEYWORDS: | ||||
2562 | if (&m_aStates.top().getDestinationText() | ||||
2563 | != m_aStates.top().getCurrentDestinationText()) | ||||
2564 | break; // not for nested group | ||||
2565 | if (m_xDocumentProperties.is()) | ||||
2566 | m_xDocumentProperties->setKeywords(comphelper::string::convertCommaSeparated( | ||||
2567 | m_aStates.top().getCurrentDestinationText()->makeStringAndClear())); | ||||
2568 | break; | ||||
2569 | case Destination::COMMENT: | ||||
2570 | if (&m_aStates.top().getDestinationText() | ||||
2571 | != m_aStates.top().getCurrentDestinationText()) | ||||
2572 | break; // not for nested group | ||||
2573 | if (m_xDocumentProperties.is()) | ||||
2574 | m_xDocumentProperties->setGenerator( | ||||
2575 | m_aStates.top().getCurrentDestinationText()->makeStringAndClear()); | ||||
2576 | break; | ||||
2577 | case Destination::SUBJECT: | ||||
2578 | if (&m_aStates.top().getDestinationText() | ||||
2579 | != m_aStates.top().getCurrentDestinationText()) | ||||
2580 | break; // not for nested group | ||||
2581 | if (m_xDocumentProperties.is()) | ||||
2582 | m_xDocumentProperties->setSubject( | ||||
2583 | m_aStates.top().getCurrentDestinationText()->makeStringAndClear()); | ||||
2584 | break; | ||||
2585 | case Destination::TITLE: | ||||
2586 | { | ||||
2587 | if (&m_aStates.top().getDestinationText() | ||||
2588 | != m_aStates.top().getCurrentDestinationText()) | ||||
2589 | break; // not for nested group | ||||
2590 | if (m_xDocumentProperties.is()) | ||||
2591 | m_xDocumentProperties->setTitle( | ||||
2592 | rState.getCurrentDestinationText()->makeStringAndClear()); | ||||
2593 | } | ||||
2594 | break; | ||||
2595 | |||||
2596 | case Destination::DOCCOMM: | ||||
2597 | if (&m_aStates.top().getDestinationText() | ||||
2598 | != m_aStates.top().getCurrentDestinationText()) | ||||
2599 | break; // not for nested group | ||||
2600 | if (m_xDocumentProperties.is()) | ||||
2601 | m_xDocumentProperties->setDescription( | ||||
2602 | m_aStates.top().getCurrentDestinationText()->makeStringAndClear()); | ||||
2603 | break; | ||||
2604 | case Destination::OPERATOR: | ||||
2605 | case Destination::COMPANY: | ||||
2606 | { | ||||
2607 | if (&m_aStates.top().getDestinationText() | ||||
2608 | != m_aStates.top().getCurrentDestinationText()) | ||||
2609 | break; // not for nested group | ||||
2610 | OUString aName = rState.getDestination() == Destination::OPERATOR ? OUString("Operator") | ||||
2611 | : OUString("Company"); | ||||
2612 | uno::Any aValue | ||||
2613 | = uno::makeAny(m_aStates.top().getCurrentDestinationText()->makeStringAndClear()); | ||||
2614 | if (m_xDocumentProperties.is()) | ||||
2615 | { | ||||
2616 | uno::Reference<beans::XPropertyContainer> xUserDefinedProperties | ||||
2617 | = m_xDocumentProperties->getUserDefinedProperties(); | ||||
2618 | uno::Reference<beans::XPropertySet> xPropertySet(xUserDefinedProperties, | ||||
2619 | uno::UNO_QUERY); | ||||
2620 | uno::Reference<beans::XPropertySetInfo> xPropertySetInfo | ||||
2621 | = xPropertySet->getPropertySetInfo(); | ||||
2622 | if (xPropertySetInfo->hasPropertyByName(aName)) | ||||
2623 | xPropertySet->setPropertyValue(aName, aValue); | ||||
2624 | else | ||||
2625 | xUserDefinedProperties->addProperty(aName, beans::PropertyAttribute::REMOVABLE, | ||||
2626 | aValue); | ||||
2627 | } | ||||
2628 | } | ||||
2629 | break; | ||||
2630 | case Destination::OBJDATA: | ||||
2631 | { | ||||
2632 | if (&m_aStates.top().getDestinationText() | ||||
2633 | != m_aStates.top().getCurrentDestinationText()) | ||||
2634 | break; // not for nested group | ||||
2635 | |||||
2636 | RTFError eError = handleEmbeddedObject(); | ||||
2637 | if (eError != RTFError::OK) | ||||
2638 | return eError; | ||||
2639 | } | ||||
2640 | break; | ||||
2641 | case Destination::OBJCLASS: | ||||
2642 | { | ||||
2643 | auto pValue | ||||
2644 | = new RTFValue(m_aStates.top().getCurrentDestinationText()->makeStringAndClear()); | ||||
2645 | m_aOLEAttributes.set(NS_ooxml::LN_CT_OLEObject_ProgID, pValue); | ||||
2646 | break; | ||||
2647 | } | ||||
2648 | case Destination::OBJECT: | ||||
2649 | { | ||||
2650 | if (!m_bObject) | ||||
2651 | { | ||||
2652 | // if the object is in a special container we will use the \result | ||||
2653 | // element instead of the \objdata | ||||
2654 | // (see RTF_OBJECT in RTFDocumentImpl::dispatchDestination) | ||||
2655 | break; | ||||
2656 | } | ||||
2657 | |||||
2658 | RTFSprms aObjectSprms; | ||||
2659 | auto pOLEValue = new RTFValue(m_aOLEAttributes); | ||||
2660 | aObjectSprms.set(NS_ooxml::LN_OLEObject_OLEObject, pOLEValue); | ||||
2661 | |||||
2662 | RTFSprms aObjAttributes; | ||||
2663 | RTFSprms aObjSprms; | ||||
2664 | auto pValue = new RTFValue(m_aObjectAttributes, aObjectSprms); | ||||
2665 | aObjSprms.set(NS_ooxml::LN_object, pValue); | ||||
2666 | writerfilter::Reference<Properties>::Pointer_t pProperties | ||||
2667 | = new RTFReferenceProperties(aObjAttributes, aObjSprms); | ||||
2668 | uno::Reference<drawing::XShape> xShape; | ||||
2669 | RTFValue::Pointer_t pShape = m_aObjectAttributes.find(NS_ooxml::LN_shape); | ||||
2670 | OSL_ASSERT(pShape)do { if (true && (!(pShape))) { sal_detail_logFormat( (SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "2670" ": "), "OSL_ASSERT: %s", "pShape"); } } while (false ); | ||||
2671 | if (pShape) | ||||
2672 | pShape->getAny() >>= xShape; | ||||
2673 | if (xShape.is()) | ||||
2674 | { | ||||
2675 | Mapper().startShape(xShape); | ||||
2676 | Mapper().props(pProperties); | ||||
2677 | Mapper().endShape(); | ||||
2678 | } | ||||
2679 | m_aObjectAttributes.clear(); | ||||
2680 | m_aOLEAttributes.clear(); | ||||
2681 | m_bObject = false; | ||||
2682 | } | ||||
2683 | break; | ||||
2684 | case Destination::ANNOTATIONDATE: | ||||
2685 | { | ||||
2686 | if (&m_aStates.top().getDestinationText() | ||||
2687 | != m_aStates.top().getCurrentDestinationText()) | ||||
2688 | break; // not for nested group | ||||
2689 | OUString aStr(OStringToOUString( | ||||
2690 | DTTM22OString( | ||||
2691 | m_aStates.top().getCurrentDestinationText()->makeStringAndClear().toInt32()), | ||||
2692 | rState.getCurrentEncoding())); | ||||
2693 | auto pValue = new RTFValue(aStr); | ||||
2694 | RTFSprms aAnnAttributes; | ||||
2695 | aAnnAttributes.set(NS_ooxml::LN_CT_TrackChange_date, pValue); | ||||
2696 | writerfilter::Reference<Properties>::Pointer_t pProperties | ||||
2697 | = new RTFReferenceProperties(aAnnAttributes); | ||||
2698 | Mapper().props(pProperties); | ||||
2699 | } | ||||
2700 | break; | ||||
2701 | case Destination::ANNOTATIONAUTHOR: | ||||
2702 | if (&m_aStates.top().getDestinationText() | ||||
2703 | != m_aStates.top().getCurrentDestinationText()) | ||||
2704 | break; // not for nested group | ||||
2705 | m_aAuthor = m_aStates.top().getCurrentDestinationText()->makeStringAndClear(); | ||||
2706 | break; | ||||
2707 | case Destination::ATNID: | ||||
2708 | if (&m_aStates.top().getDestinationText() | ||||
2709 | != m_aStates.top().getCurrentDestinationText()) | ||||
2710 | break; // not for nested group | ||||
2711 | m_aAuthorInitials = m_aStates.top().getCurrentDestinationText()->makeStringAndClear(); | ||||
2712 | break; | ||||
2713 | case Destination::ANNOTATIONREFERENCESTART: | ||||
2714 | case Destination::ANNOTATIONREFERENCEEND: | ||||
2715 | { | ||||
2716 | if (&m_aStates.top().getDestinationText() | ||||
2717 | != m_aStates.top().getCurrentDestinationText()) | ||||
2718 | break; // not for nested group | ||||
2719 | OUString aStr = m_aStates.top().getCurrentDestinationText()->makeStringAndClear(); | ||||
2720 | auto pValue = new RTFValue(aStr.toInt32()); | ||||
2721 | RTFSprms aAttributes; | ||||
2722 | if (rState.getDestination() == Destination::ANNOTATIONREFERENCESTART) | ||||
2723 | aAttributes.set(NS_ooxml::LN_EG_RangeMarkupElements_commentRangeStart, pValue); | ||||
2724 | else | ||||
2725 | aAttributes.set(NS_ooxml::LN_EG_RangeMarkupElements_commentRangeEnd, pValue); | ||||
2726 | writerfilter::Reference<Properties>::Pointer_t pProperties | ||||
2727 | = new RTFReferenceProperties(aAttributes); | ||||
2728 | if (!m_aStates.top().getCurrentBuffer()) | ||||
2729 | { | ||||
2730 | Mapper().props(pProperties); | ||||
2731 | } | ||||
2732 | else | ||||
2733 | { | ||||
2734 | auto const pValue2 = new RTFValue(aAttributes, RTFSprms()); | ||||
2735 | bufferProperties(*m_aStates.top().getCurrentBuffer(), pValue2, nullptr); | ||||
2736 | } | ||||
2737 | } | ||||
2738 | break; | ||||
2739 | case Destination::ANNOTATIONREFERENCE: | ||||
2740 | { | ||||
2741 | if (&m_aStates.top().getDestinationText() | ||||
2742 | != m_aStates.top().getCurrentDestinationText()) | ||||
2743 | break; // not for nested group | ||||
2744 | OUString aStr = m_aStates.top().getCurrentDestinationText()->makeStringAndClear(); | ||||
2745 | RTFSprms aAnnAttributes; | ||||
2746 | aAnnAttributes.set(NS_ooxml::LN_CT_Markup_id, new RTFValue(aStr.toInt32())); | ||||
2747 | Mapper().props(new RTFReferenceProperties(aAnnAttributes)); | ||||
2748 | } | ||||
2749 | break; | ||||
2750 | case Destination::FALT: | ||||
2751 | { | ||||
2752 | if (&m_aStates.top().getDestinationText() | ||||
2753 | != m_aStates.top().getCurrentDestinationText()) | ||||
2754 | break; // not for nested group | ||||
2755 | OUString aStr(m_aStates.top().getCurrentDestinationText()->makeStringAndClear()); | ||||
2756 | auto pValue = new RTFValue(aStr); | ||||
2757 | rState.getTableSprms().set(NS_ooxml::LN_CT_Font_altName, pValue); | ||||
2758 | } | ||||
2759 | break; | ||||
2760 | case Destination::DRAWINGOBJECT: | ||||
2761 | if (m_aStates.top().getDrawingObject().getShape().is()) | ||||
2762 | { | ||||
2763 | RTFDrawingObject& rDrawing = m_aStates.top().getDrawingObject(); | ||||
2764 | const uno::Reference<drawing::XShape>& xShape(rDrawing.getShape()); | ||||
2765 | const uno::Reference<beans::XPropertySet>& xPropertySet(rDrawing.getPropertySet()); | ||||
2766 | |||||
2767 | uno::Reference<lang::XServiceInfo> xServiceInfo(xShape, uno::UNO_QUERY); | ||||
2768 | bool bTextFrame = xServiceInfo->supportsService("com.sun.star.text.TextFrame"); | ||||
2769 | |||||
2770 | // The default is certainly not inline, but then what Word supports is just at-character. | ||||
2771 | xPropertySet->setPropertyValue( | ||||
2772 | "AnchorType", uno::makeAny(text::TextContentAnchorType_AT_CHARACTER)); | ||||
2773 | |||||
2774 | if (bTextFrame) | ||||
2775 | { | ||||
2776 | xPropertySet->setPropertyValue("HoriOrientPosition", | ||||
2777 | uno::makeAny(rDrawing.getLeft())); | ||||
2778 | xPropertySet->setPropertyValue("VertOrientPosition", | ||||
2779 | uno::makeAny(rDrawing.getTop())); | ||||
2780 | } | ||||
2781 | else | ||||
2782 | { | ||||
2783 | xShape->setPosition(awt::Point(rDrawing.getLeft(), rDrawing.getTop())); | ||||
2784 | } | ||||
2785 | xShape->setSize(awt::Size(rDrawing.getRight(), rDrawing.getBottom())); | ||||
2786 | |||||
2787 | if (rDrawing.getHasLineColor()) | ||||
2788 | { | ||||
2789 | uno::Any aLineColor = uno::makeAny(sal_uInt32((rDrawing.getLineColorR() << 16) | ||||
2790 | + (rDrawing.getLineColorG() << 8) | ||||
2791 | + rDrawing.getLineColorB())); | ||||
2792 | uno::Any aLineWidth; | ||||
2793 | RTFSdrImport::resolveLineColorAndWidth(bTextFrame, xPropertySet, aLineColor, | ||||
2794 | aLineWidth); | ||||
2795 | } | ||||
2796 | if (rDrawing.getHasFillColor()) | ||||
2797 | xPropertySet->setPropertyValue( | ||||
2798 | "FillColor", uno::makeAny(sal_uInt32((rDrawing.getFillColorR() << 16) | ||||
2799 | + (rDrawing.getFillColorG() << 8) | ||||
2800 | + rDrawing.getFillColorB()))); | ||||
2801 | else if (!bTextFrame) | ||||
2802 | // If there is no fill, the Word default is 100% transparency. | ||||
2803 | xPropertySet->setPropertyValue("FillTransparence", | ||||
2804 | uno::makeAny(sal_Int32(100))); | ||||
2805 | |||||
2806 | RTFSdrImport::resolveFLine(xPropertySet, rDrawing.getFLine()); | ||||
2807 | |||||
2808 | if (!m_aStates.top().getDrawingObject().getHadShapeText()) | ||||
2809 | { | ||||
2810 | Mapper().startShape(xShape); | ||||
2811 | } | ||||
2812 | Mapper().endShape(); | ||||
2813 | } | ||||
2814 | break; | ||||
2815 | case Destination::PICT: | ||||
2816 | // fdo#79319 ignore picture data if it's really a shape | ||||
2817 | if (!m_pSdrImport->isFakePict()) | ||||
2818 | { | ||||
2819 | resolvePict(true, m_pSdrImport->getCurrentShape()); | ||||
2820 | } | ||||
2821 | m_bNeedFinalPar = true; | ||||
2822 | break; | ||||
2823 | case Destination::SHAPE: | ||||
2824 | m_bNeedFinalPar = true; | ||||
2825 | m_bNeedCr = m_bNeedCrOrig; | ||||
2826 | if (rState.getFrame().inFrame()) | ||||
2827 | { | ||||
2828 | // parBreak() modifies m_aStates.top() so we can't apply resetFrame() directly on aState | ||||
2829 | resetFrame(); | ||||
2830 | parBreak(); | ||||
2831 | // Save this state for later use, so we only reset frame status only for the first shape inside a frame. | ||||
2832 | rState = m_aStates.top(); | ||||
2833 | m_bNeedPap = true; | ||||
2834 | } | ||||
2835 | break; | ||||
2836 | case Destination::MOMATH: | ||||
2837 | { | ||||
2838 | m_aMathBuffer.appendClosingTag(M_TOKEN(oMath)(::oox::NMSP_officeMath | ::oox::XML_oMath)); | ||||
2839 | |||||
2840 | SvGlobalName aGlobalName(SO3_SM_CLASSID0x078B7ABA, 0x54FC, 0x457F, 0x85, 0x51, 0x61, 0x47, 0xE7, 0x76 , 0xA9, 0x97); | ||||
2841 | comphelper::EmbeddedObjectContainer aContainer; | ||||
2842 | OUString aName; | ||||
2843 | uno::Reference<embed::XEmbeddedObject> xObject | ||||
2844 | = aContainer.CreateEmbeddedObject(aGlobalName.GetByteSequence(), aName); | ||||
2845 | if (xObject) // rhbz#1766990 starmath might not be available | ||||
2846 | { | ||||
2847 | uno::Reference<util::XCloseable> xComponent(xObject->getComponent(), | ||||
2848 | uno::UNO_SET_THROW); | ||||
2849 | // gcc4.4 (and 4.3 and possibly older) have a problem with dynamic_cast directly to the target class, | ||||
2850 | // so help it with an intermediate cast. I'm not sure what exactly the problem is, seems to be unrelated | ||||
2851 | // to RTLD_GLOBAL, so most probably a gcc bug. | ||||
2852 | auto& rImport = dynamic_cast<oox::FormulaImportBase&>( | ||||
2853 | dynamic_cast<SfxBaseModel&>(*xComponent)); | ||||
2854 | rImport.readFormulaOoxml(m_aMathBuffer); | ||||
2855 | |||||
2856 | auto pValue = new RTFValue(xObject); | ||||
2857 | RTFSprms aMathAttributes; | ||||
2858 | aMathAttributes.set(NS_ooxml::LN_starmath, pValue); | ||||
2859 | writerfilter::Reference<Properties>::Pointer_t pProperties | ||||
2860 | = new RTFReferenceProperties(aMathAttributes); | ||||
2861 | Mapper().props(pProperties); | ||||
2862 | } | ||||
2863 | |||||
2864 | m_aMathBuffer = oox::formulaimport::XmlStreamBuilder(); | ||||
2865 | } | ||||
2866 | break; | ||||
2867 | case Destination::MR: | ||||
2868 | lcl_DestinationToMath(m_aStates.top().getCurrentDestinationText(), m_aMathBuffer, | ||||
2869 | m_bMathNor); | ||||
2870 | break; | ||||
2871 | case Destination::MF: | ||||
2872 | m_aMathBuffer.appendClosingTag(M_TOKEN(f)(::oox::NMSP_officeMath | ::oox::XML_f)); | ||||
2873 | break; | ||||
2874 | case Destination::MFPR: | ||||
2875 | m_aMathBuffer.appendClosingTag(M_TOKEN(fPr)(::oox::NMSP_officeMath | ::oox::XML_fPr)); | ||||
2876 | break; | ||||
2877 | case Destination::MCTRLPR: | ||||
2878 | m_aMathBuffer.appendClosingTag(M_TOKEN(ctrlPr)(::oox::NMSP_officeMath | ::oox::XML_ctrlPr)); | ||||
2879 | break; | ||||
2880 | case Destination::MNUM: | ||||
2881 | m_aMathBuffer.appendClosingTag(M_TOKEN(num)(::oox::NMSP_officeMath | ::oox::XML_num)); | ||||
2882 | break; | ||||
2883 | case Destination::MDEN: | ||||
2884 | m_aMathBuffer.appendClosingTag(M_TOKEN(den)(::oox::NMSP_officeMath | ::oox::XML_den)); | ||||
2885 | break; | ||||
2886 | case Destination::MACC: | ||||
2887 | m_aMathBuffer.appendClosingTag(M_TOKEN(acc)(::oox::NMSP_officeMath | ::oox::XML_acc)); | ||||
2888 | break; | ||||
2889 | case Destination::MACCPR: | ||||
2890 | m_aMathBuffer.appendClosingTag(M_TOKEN(accPr)(::oox::NMSP_officeMath | ::oox::XML_accPr)); | ||||
2891 | break; | ||||
2892 | case Destination::MCHR: | ||||
2893 | case Destination::MPOS: | ||||
2894 | case Destination::MVERTJC: | ||||
2895 | case Destination::MSTRIKEH: | ||||
2896 | case Destination::MDEGHIDE: | ||||
2897 | case Destination::MBEGCHR: | ||||
2898 | case Destination::MSEPCHR: | ||||
2899 | case Destination::MENDCHR: | ||||
2900 | case Destination::MSUBHIDE: | ||||
2901 | case Destination::MSUPHIDE: | ||||
2902 | case Destination::MTYPE: | ||||
2903 | case Destination::MGROW: | ||||
2904 | { | ||||
2905 | sal_Int32 nMathToken = 0; | ||||
2906 | switch (rState.getDestination()) | ||||
2907 | { | ||||
2908 | case Destination::MCHR: | ||||
2909 | nMathToken = M_TOKEN(chr)(::oox::NMSP_officeMath | ::oox::XML_chr); | ||||
2910 | break; | ||||
2911 | case Destination::MPOS: | ||||
2912 | nMathToken = M_TOKEN(pos)(::oox::NMSP_officeMath | ::oox::XML_pos); | ||||
2913 | break; | ||||
2914 | case Destination::MVERTJC: | ||||
2915 | nMathToken = M_TOKEN(vertJc)(::oox::NMSP_officeMath | ::oox::XML_vertJc); | ||||
2916 | break; | ||||
2917 | case Destination::MSTRIKEH: | ||||
2918 | nMathToken = M_TOKEN(strikeH)(::oox::NMSP_officeMath | ::oox::XML_strikeH); | ||||
2919 | break; | ||||
2920 | case Destination::MDEGHIDE: | ||||
2921 | nMathToken = M_TOKEN(degHide)(::oox::NMSP_officeMath | ::oox::XML_degHide); | ||||
2922 | break; | ||||
2923 | case Destination::MBEGCHR: | ||||
2924 | nMathToken = M_TOKEN(begChr)(::oox::NMSP_officeMath | ::oox::XML_begChr); | ||||
2925 | break; | ||||
2926 | case Destination::MSEPCHR: | ||||
2927 | nMathToken = M_TOKEN(sepChr)(::oox::NMSP_officeMath | ::oox::XML_sepChr); | ||||
2928 | break; | ||||
2929 | case Destination::MENDCHR: | ||||
2930 | nMathToken = M_TOKEN(endChr)(::oox::NMSP_officeMath | ::oox::XML_endChr); | ||||
2931 | break; | ||||
2932 | case Destination::MSUBHIDE: | ||||
2933 | nMathToken = M_TOKEN(subHide)(::oox::NMSP_officeMath | ::oox::XML_subHide); | ||||
2934 | break; | ||||
2935 | case Destination::MSUPHIDE: | ||||
2936 | nMathToken = M_TOKEN(supHide)(::oox::NMSP_officeMath | ::oox::XML_supHide); | ||||
2937 | break; | ||||
2938 | case Destination::MTYPE: | ||||
2939 | nMathToken = M_TOKEN(type)(::oox::NMSP_officeMath | ::oox::XML_type); | ||||
2940 | break; | ||||
2941 | case Destination::MGROW: | ||||
2942 | nMathToken = M_TOKEN(grow)(::oox::NMSP_officeMath | ::oox::XML_grow); | ||||
2943 | break; | ||||
2944 | default: | ||||
2945 | break; | ||||
2946 | } | ||||
2947 | |||||
2948 | oox::formulaimport::XmlStream::AttributeList aAttribs; | ||||
2949 | aAttribs[M_TOKEN(val)(::oox::NMSP_officeMath | ::oox::XML_val)] | ||||
2950 | = m_aStates.top().getCurrentDestinationText()->makeStringAndClear(); | ||||
2951 | m_aMathBuffer.appendOpeningTag(nMathToken, aAttribs); | ||||
2952 | m_aMathBuffer.appendClosingTag(nMathToken); | ||||
2953 | } | ||||
2954 | break; | ||||
2955 | case Destination::ME: | ||||
2956 | m_aMathBuffer.appendClosingTag(M_TOKEN(e)(::oox::NMSP_officeMath | ::oox::XML_e)); | ||||
2957 | break; | ||||
2958 | case Destination::MBAR: | ||||
2959 | m_aMathBuffer.appendClosingTag(M_TOKEN(bar)(::oox::NMSP_officeMath | ::oox::XML_bar)); | ||||
2960 | break; | ||||
2961 | case Destination::MBARPR: | ||||
2962 | m_aMathBuffer.appendClosingTag(M_TOKEN(barPr)(::oox::NMSP_officeMath | ::oox::XML_barPr)); | ||||
2963 | break; | ||||
2964 | case Destination::MD: | ||||
2965 | m_aMathBuffer.appendClosingTag(M_TOKEN(d)(::oox::NMSP_officeMath | ::oox::XML_d)); | ||||
2966 | break; | ||||
2967 | case Destination::MDPR: | ||||
2968 | m_aMathBuffer.appendClosingTag(M_TOKEN(dPr)(::oox::NMSP_officeMath | ::oox::XML_dPr)); | ||||
2969 | break; | ||||
2970 | case Destination::MFUNC: | ||||
2971 | m_aMathBuffer.appendClosingTag(M_TOKEN(func)(::oox::NMSP_officeMath | ::oox::XML_func)); | ||||
2972 | break; | ||||
2973 | case Destination::MFUNCPR: | ||||
2974 | m_aMathBuffer.appendClosingTag(M_TOKEN(funcPr)(::oox::NMSP_officeMath | ::oox::XML_funcPr)); | ||||
2975 | break; | ||||
2976 | case Destination::MFNAME: | ||||
2977 | m_aMathBuffer.appendClosingTag(M_TOKEN(fName)(::oox::NMSP_officeMath | ::oox::XML_fName)); | ||||
2978 | break; | ||||
2979 | case Destination::MLIMLOW: | ||||
2980 | m_aMathBuffer.appendClosingTag(M_TOKEN(limLow)(::oox::NMSP_officeMath | ::oox::XML_limLow)); | ||||
2981 | break; | ||||
2982 | case Destination::MLIMLOWPR: | ||||
2983 | m_aMathBuffer.appendClosingTag(M_TOKEN(limLowPr)(::oox::NMSP_officeMath | ::oox::XML_limLowPr)); | ||||
2984 | break; | ||||
2985 | case Destination::MLIM: | ||||
2986 | m_aMathBuffer.appendClosingTag(M_TOKEN(lim)(::oox::NMSP_officeMath | ::oox::XML_lim)); | ||||
2987 | break; | ||||
2988 | case Destination::MM: | ||||
2989 | m_aMathBuffer.appendClosingTag(M_TOKEN(m)(::oox::NMSP_officeMath | ::oox::XML_m)); | ||||
2990 | break; | ||||
2991 | case Destination::MMPR: | ||||
2992 | m_aMathBuffer.appendClosingTag(M_TOKEN(mPr)(::oox::NMSP_officeMath | ::oox::XML_mPr)); | ||||
2993 | break; | ||||
2994 | case Destination::MMR: | ||||
2995 | m_aMathBuffer.appendClosingTag(M_TOKEN(mr)(::oox::NMSP_officeMath | ::oox::XML_mr)); | ||||
2996 | break; | ||||
2997 | case Destination::MNARY: | ||||
2998 | m_aMathBuffer.appendClosingTag(M_TOKEN(nary)(::oox::NMSP_officeMath | ::oox::XML_nary)); | ||||
2999 | break; | ||||
3000 | case Destination::MNARYPR: | ||||
3001 | m_aMathBuffer.appendClosingTag(M_TOKEN(naryPr)(::oox::NMSP_officeMath | ::oox::XML_naryPr)); | ||||
3002 | break; | ||||
3003 | case Destination::MSUB: | ||||
3004 | m_aMathBuffer.appendClosingTag(M_TOKEN(sub)(::oox::NMSP_officeMath | ::oox::XML_sub)); | ||||
3005 | break; | ||||
3006 | case Destination::MSUP: | ||||
3007 | m_aMathBuffer.appendClosingTag(M_TOKEN(sup)(::oox::NMSP_officeMath | ::oox::XML_sup)); | ||||
3008 | break; | ||||
3009 | case Destination::MLIMUPP: | ||||
3010 | m_aMathBuffer.appendClosingTag(M_TOKEN(limUpp)(::oox::NMSP_officeMath | ::oox::XML_limUpp)); | ||||
3011 | break; | ||||
3012 | case Destination::MLIMUPPPR: | ||||
3013 | m_aMathBuffer.appendClosingTag(M_TOKEN(limUppPr)(::oox::NMSP_officeMath | ::oox::XML_limUppPr)); | ||||
3014 | break; | ||||
3015 | case Destination::MGROUPCHR: | ||||
3016 | m_aMathBuffer.appendClosingTag(M_TOKEN(groupChr)(::oox::NMSP_officeMath | ::oox::XML_groupChr)); | ||||
3017 | break; | ||||
3018 | case Destination::MGROUPCHRPR: | ||||
3019 | m_aMathBuffer.appendClosingTag(M_TOKEN(groupChrPr)(::oox::NMSP_officeMath | ::oox::XML_groupChrPr)); | ||||
3020 | break; | ||||
3021 | case Destination::MBORDERBOX: | ||||
3022 | m_aMathBuffer.appendClosingTag(M_TOKEN(borderBox)(::oox::NMSP_officeMath | ::oox::XML_borderBox)); | ||||
3023 | break; | ||||
3024 | case Destination::MBORDERBOXPR: | ||||
3025 | m_aMathBuffer.appendClosingTag(M_TOKEN(borderBoxPr)(::oox::NMSP_officeMath | ::oox::XML_borderBoxPr)); | ||||
3026 | break; | ||||
3027 | case Destination::MRAD: | ||||
3028 | m_aMathBuffer.appendClosingTag(M_TOKEN(rad)(::oox::NMSP_officeMath | ::oox::XML_rad)); | ||||
3029 | break; | ||||
3030 | case Destination::MRADPR: | ||||
3031 | m_aMathBuffer.appendClosingTag(M_TOKEN(radPr)(::oox::NMSP_officeMath | ::oox::XML_radPr)); | ||||
3032 | break; | ||||
3033 | case Destination::MDEG: | ||||
3034 | m_aMathBuffer.appendClosingTag(M_TOKEN(deg)(::oox::NMSP_officeMath | ::oox::XML_deg)); | ||||
3035 | break; | ||||
3036 | case Destination::MSSUB: | ||||
3037 | m_aMathBuffer.appendClosingTag(M_TOKEN(sSub)(::oox::NMSP_officeMath | ::oox::XML_sSub)); | ||||
3038 | break; | ||||
3039 | case Destination::MSSUBPR: | ||||
3040 | m_aMathBuffer.appendClosingTag(M_TOKEN(sSubPr)(::oox::NMSP_officeMath | ::oox::XML_sSubPr)); | ||||
3041 | break; | ||||
3042 | case Destination::MSSUP: | ||||
3043 | m_aMathBuffer.appendClosingTag(M_TOKEN(sSup)(::oox::NMSP_officeMath | ::oox::XML_sSup)); | ||||
3044 | break; | ||||
3045 | case Destination::MSSUPPR: | ||||
3046 | m_aMathBuffer.appendClosingTag(M_TOKEN(sSupPr)(::oox::NMSP_officeMath | ::oox::XML_sSupPr)); | ||||
3047 | break; | ||||
3048 | case Destination::MSSUBSUP: | ||||
3049 | m_aMathBuffer.appendClosingTag(M_TOKEN(sSubSup)(::oox::NMSP_officeMath | ::oox::XML_sSubSup)); | ||||
3050 | break; | ||||
3051 | case Destination::MSSUBSUPPR: | ||||
3052 | m_aMathBuffer.appendClosingTag(M_TOKEN(sSubSupPr)(::oox::NMSP_officeMath | ::oox::XML_sSubSupPr)); | ||||
3053 | break; | ||||
3054 | case Destination::MSPRE: | ||||
3055 | m_aMathBuffer.appendClosingTag(M_TOKEN(sPre)(::oox::NMSP_officeMath | ::oox::XML_sPre)); | ||||
3056 | break; | ||||
3057 | case Destination::MSPREPR: | ||||
3058 | m_aMathBuffer.appendClosingTag(M_TOKEN(sPrePr)(::oox::NMSP_officeMath | ::oox::XML_sPrePr)); | ||||
3059 | break; | ||||
3060 | case Destination::MBOX: | ||||
3061 | m_aMathBuffer.appendClosingTag(M_TOKEN(box)(::oox::NMSP_officeMath | ::oox::XML_box)); | ||||
3062 | break; | ||||
3063 | case Destination::MEQARR: | ||||
3064 | m_aMathBuffer.appendClosingTag(M_TOKEN(eqArr)(::oox::NMSP_officeMath | ::oox::XML_eqArr)); | ||||
3065 | break; | ||||
3066 | case Destination::SHAPEGROUP: | ||||
3067 | if (rState.getCreatedShapeGroup()) | ||||
3068 | m_pSdrImport->popParent(); | ||||
3069 | break; | ||||
3070 | case Destination::PROPNAME: | ||||
3071 | if (&m_aStates.top().getDestinationText() | ||||
3072 | != m_aStates.top().getCurrentDestinationText()) | ||||
3073 | break; // not for nested group | ||||
3074 | rState.setPropName(m_aStates.top().getCurrentDestinationText()->makeStringAndClear()); | ||||
3075 | break; | ||||
3076 | case Destination::STATICVAL: | ||||
3077 | if (&m_aStates.top().getDestinationText() | ||||
3078 | != m_aStates.top().getCurrentDestinationText()) | ||||
3079 | break; // not for nested group | ||||
3080 | if (m_xDocumentProperties.is()) | ||||
3081 | { | ||||
3082 | // Find out what is the key, value type and value we want to set. | ||||
3083 | uno::Reference<beans::XPropertyContainer> xPropertyContainer | ||||
3084 | = m_xDocumentProperties->getUserDefinedProperties(); | ||||
3085 | const OUString& rKey = m_aStates.top().getPropName(); | ||||
3086 | OUString aStaticVal | ||||
3087 | = m_aStates.top().getCurrentDestinationText()->makeStringAndClear(); | ||||
3088 | uno::Any aAny; | ||||
3089 | if (m_aStates.top().getPropType() == cppu::UnoType<OUString>::get()) | ||||
3090 | aAny <<= aStaticVal; | ||||
3091 | else if (m_aStates.top().getPropType() == cppu::UnoType<sal_Int32>::get()) | ||||
3092 | aAny <<= aStaticVal.toInt32(); | ||||
3093 | else if (m_aStates.top().getPropType() == cppu::UnoType<bool>::get()) | ||||
3094 | aAny <<= aStaticVal.toBoolean(); | ||||
3095 | else if (m_aStates.top().getPropType() == cppu::UnoType<util::DateTime>::get()) | ||||
3096 | aAny <<= getDateTimeFromUserProp(aStaticVal); | ||||
3097 | else if (m_aStates.top().getPropType() == cppu::UnoType<double>::get()) | ||||
3098 | aAny <<= aStaticVal.toDouble(); | ||||
3099 | |||||
3100 | xPropertyContainer->addProperty(rKey, beans::PropertyAttribute::REMOVABLE, aAny); | ||||
3101 | } | ||||
3102 | break; | ||||
3103 | case Destination::USERPROPS: | ||||
3104 | { | ||||
3105 | // These are the imported properties. | ||||
3106 | uno::Reference<document::XDocumentProperties> xDocumentProperties | ||||
3107 | = m_xDocumentProperties; | ||||
3108 | |||||
3109 | // These are the real document properties. | ||||
3110 | uno::Reference<document::XDocumentPropertiesSupplier> xDocumentPropertiesSupplier( | ||||
3111 | m_xDstDoc, uno::UNO_QUERY); | ||||
3112 | if (xDocumentPropertiesSupplier.is()) | ||||
3113 | m_xDocumentProperties = xDocumentPropertiesSupplier->getDocumentProperties(); | ||||
3114 | |||||
3115 | if (m_xDocumentProperties.is()) | ||||
3116 | { | ||||
3117 | if (!m_bIsNewDoc) | ||||
3118 | { | ||||
3119 | // Check classification. | ||||
3120 | if (!SfxClassificationHelper::ShowPasteInfo(SfxClassificationHelper::CheckPaste( | ||||
3121 | xDocumentProperties, m_xDocumentProperties))) | ||||
3122 | return RTFError::CLASSIFICATION; | ||||
3123 | } | ||||
3124 | |||||
3125 | uno::Reference<beans::XPropertyContainer> xClipboardPropertyContainer | ||||
3126 | = xDocumentProperties->getUserDefinedProperties(); | ||||
3127 | uno::Reference<beans::XPropertyContainer> xDocumentPropertyContainer | ||||
3128 | = m_xDocumentProperties->getUserDefinedProperties(); | ||||
3129 | uno::Reference<beans::XPropertySet> xClipboardPropertySet( | ||||
3130 | xClipboardPropertyContainer, uno::UNO_QUERY); | ||||
3131 | uno::Reference<beans::XPropertySet> xDocumentPropertySet(xDocumentPropertyContainer, | ||||
3132 | uno::UNO_QUERY); | ||||
3133 | const uno::Sequence<beans::Property> aClipboardProperties | ||||
3134 | = xClipboardPropertySet->getPropertySetInfo()->getProperties(); | ||||
3135 | uno::Sequence<beans::Property> aDocumentProperties | ||||
3136 | = xDocumentPropertySet->getPropertySetInfo()->getProperties(); | ||||
3137 | |||||
3138 | for (const beans::Property& rProperty : aClipboardProperties) | ||||
3139 | { | ||||
3140 | const OUString& rKey = rProperty.Name; | ||||
3141 | uno::Any aValue = xClipboardPropertySet->getPropertyValue(rKey); | ||||
3142 | |||||
3143 | try | ||||
3144 | { | ||||
3145 | if (lcl_containsProperty(aDocumentProperties, rKey)) | ||||
3146 | { | ||||
3147 | // When pasting, don't update existing properties. | ||||
3148 | if (!m_bIsNewDoc) | ||||
3149 | xDocumentPropertySet->setPropertyValue(rKey, aValue); | ||||
3150 | } | ||||
3151 | else | ||||
3152 | xDocumentPropertyContainer->addProperty( | ||||
3153 | rKey, beans::PropertyAttribute::REMOVABLE, aValue); | ||||
3154 | } | ||||
3155 | catch (const uno::Exception&) | ||||
3156 | { | ||||
3157 | TOOLS_WARN_EXCEPTION("writerfilter.rtf", "failed to set property " << rKey)do { css::uno::Any tools_warn_exception( DbgGetCaughtException () ); do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN , "writerfilter.rtf")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "failed to set property " << rKey << " " << exceptionToString(tools_warn_exception )) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ( "writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "3157" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "failed to set property " << rKey << " " << exceptionToString(tools_warn_exception )), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "failed to set property " << rKey << " " << exceptionToString(tools_warn_exception); ::sal::detail ::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("writerfilter.rtf"), ( "/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "3157" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "failed to set property " << rKey << " " << exceptionToString(tools_warn_exception)) == 1) { :: sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "3157" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "failed to set property " << rKey << " " << exceptionToString(tools_warn_exception )), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "failed to set property " << rKey << " " << exceptionToString(tools_warn_exception); ::sal::detail ::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("writerfilter.rtf"), ( "/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "3157" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); } while (false); | ||||
3158 | } | ||||
3159 | } | ||||
3160 | } | ||||
3161 | } | ||||
3162 | break; | ||||
3163 | default: | ||||
3164 | break; | ||||
3165 | } | ||||
3166 | |||||
3167 | return RTFError::OK; | ||||
3168 | } | ||||
3169 | |||||
3170 | void RTFDocumentImpl::afterPopState(RTFParserState& rState) | ||||
3171 | { | ||||
3172 | // list table | ||||
3173 | switch (rState.getDestination()) | ||||
3174 | { | ||||
3175 | case Destination::LISTENTRY: | ||||
3176 | { | ||||
3177 | auto pValue = new RTFValue(rState.getTableAttributes(), rState.getTableSprms()); | ||||
3178 | m_aListTableSprms.set(NS_ooxml::LN_CT_Numbering_abstractNum, pValue, | ||||
3179 | RTFOverwrite::NO_APPEND); | ||||
3180 | m_aListTable[rState.getCurrentListIndex()] = pValue; | ||||
3181 | m_nListLevel = -1; | ||||
3182 | m_aInvalidListTableFirstIndents[rState.getCurrentListIndex()] | ||||
3183 | = m_aInvalidListLevelFirstIndents; | ||||
3184 | m_aInvalidListLevelFirstIndents.clear(); | ||||
3185 | } | ||||
3186 | break; | ||||
3187 | case Destination::PARAGRAPHNUMBERING: | ||||
3188 | { | ||||
3189 | RTFValue::Pointer_t pIdValue | ||||
3190 | = rState.getTableAttributes().find(NS_ooxml::LN_CT_AbstractNum_nsid); | ||||
3191 | if (pIdValue && !m_aStates.empty()) | ||||
3192 | { | ||||
3193 | // Abstract numbering | ||||
3194 | RTFSprms aLeveltextAttributes; | ||||
3195 | OUString aTextValue; | ||||
3196 | RTFValue::Pointer_t pTextBefore | ||||
3197 | = rState.getTableAttributes().find(NS_ooxml::LN_CT_LevelText_val); | ||||
3198 | if (pTextBefore) | ||||
3199 | aTextValue += pTextBefore->getString(); | ||||
3200 | aTextValue += "%1"; | ||||
3201 | RTFValue::Pointer_t pTextAfter | ||||
3202 | = rState.getTableAttributes().find(NS_ooxml::LN_CT_LevelSuffix_val); | ||||
3203 | if (pTextAfter) | ||||
3204 | aTextValue += pTextAfter->getString(); | ||||
3205 | auto pTextValue = new RTFValue(aTextValue); | ||||
3206 | aLeveltextAttributes.set(NS_ooxml::LN_CT_LevelText_val, pTextValue); | ||||
3207 | |||||
3208 | RTFSprms aLevelAttributes; | ||||
3209 | RTFSprms aLevelSprms; | ||||
3210 | auto pIlvlValue = new RTFValue(0); | ||||
3211 | aLevelAttributes.set(NS_ooxml::LN_CT_Lvl_ilvl, pIlvlValue); | ||||
3212 | |||||
3213 | RTFValue::Pointer_t pFmtValue | ||||
3214 | = rState.getTableSprms().find(NS_ooxml::LN_CT_Lvl_numFmt); | ||||
3215 | if (pFmtValue) | ||||
3216 | aLevelSprms.set(NS_ooxml::LN_CT_Lvl_numFmt, pFmtValue); | ||||
3217 | |||||
3218 | RTFValue::Pointer_t pStartatValue | ||||
3219 | = rState.getTableSprms().find(NS_ooxml::LN_CT_Lvl_start); | ||||
3220 | if (pStartatValue) | ||||
3221 | aLevelSprms.set(NS_ooxml::LN_CT_Lvl_start, pStartatValue); | ||||
3222 | |||||
3223 | auto pLeveltextValue = new RTFValue(aLeveltextAttributes); | ||||
3224 | aLevelSprms.set(NS_ooxml::LN_CT_Lvl_lvlText, pLeveltextValue); | ||||
3225 | RTFValue::Pointer_t pRunProps | ||||
3226 | = rState.getTableSprms().find(NS_ooxml::LN_CT_Lvl_rPr); | ||||
3227 | if (pRunProps) | ||||
3228 | aLevelSprms.set(NS_ooxml::LN_CT_Lvl_rPr, pRunProps); | ||||
3229 | |||||
3230 | RTFSprms aAbstractAttributes; | ||||
3231 | RTFSprms aAbstractSprms; | ||||
3232 | aAbstractAttributes.set(NS_ooxml::LN_CT_AbstractNum_abstractNumId, pIdValue); | ||||
3233 | auto pLevelValue = new RTFValue(aLevelAttributes, aLevelSprms); | ||||
3234 | aAbstractSprms.set(NS_ooxml::LN_CT_AbstractNum_lvl, pLevelValue, | ||||
3235 | RTFOverwrite::NO_APPEND); | ||||
3236 | |||||
3237 | RTFSprms aListTableSprms; | ||||
3238 | auto pAbstractValue = new RTFValue(aAbstractAttributes, aAbstractSprms); | ||||
3239 | // It's important that Numbering_abstractNum and Numbering_num never overwrites previous values. | ||||
3240 | aListTableSprms.set(NS_ooxml::LN_CT_Numbering_abstractNum, pAbstractValue, | ||||
3241 | RTFOverwrite::NO_APPEND); | ||||
3242 | |||||
3243 | // Numbering | ||||
3244 | RTFSprms aNumberingAttributes; | ||||
3245 | RTFSprms aNumberingSprms; | ||||
3246 | aNumberingAttributes.set(NS_ooxml::LN_CT_AbstractNum_nsid, pIdValue); | ||||
3247 | aNumberingSprms.set(NS_ooxml::LN_CT_Num_abstractNumId, pIdValue); | ||||
3248 | auto pNumberingValue = new RTFValue(aNumberingAttributes, aNumberingSprms); | ||||
3249 | aListTableSprms.set(NS_ooxml::LN_CT_Numbering_num, pNumberingValue, | ||||
3250 | RTFOverwrite::NO_APPEND); | ||||
3251 | |||||
3252 | // Table | ||||
3253 | RTFSprms aListTableAttributes; | ||||
3254 | writerfilter::Reference<Properties>::Pointer_t pProp | ||||
3255 | = new RTFReferenceProperties(aListTableAttributes, aListTableSprms); | ||||
3256 | |||||
3257 | RTFReferenceTable::Entries_t aListTableEntries; | ||||
3258 | aListTableEntries.insert(std::make_pair(0, pProp)); | ||||
3259 | writerfilter::Reference<Table>::Pointer_t const pTable( | ||||
3260 | new RTFReferenceTable(aListTableEntries)); | ||||
3261 | Mapper().table(NS_ooxml::LN_NUMBERING, pTable); | ||||
3262 | |||||
3263 | // Use it | ||||
3264 | putNestedSprm(m_aStates.top().getParagraphSprms(), NS_ooxml::LN_CT_PPrBase_numPr, | ||||
3265 | NS_ooxml::LN_CT_NumPr_ilvl, pIlvlValue); | ||||
3266 | putNestedSprm(m_aStates.top().getParagraphSprms(), NS_ooxml::LN_CT_PPrBase_numPr, | ||||
3267 | NS_ooxml::LN_CT_NumPr_numId, pIdValue); | ||||
3268 | } | ||||
3269 | } | ||||
3270 | break; | ||||
3271 | case Destination::PARAGRAPHNUMBERING_TEXTAFTER: | ||||
3272 | if (!m_aStates.empty()) | ||||
3273 | { | ||||
3274 | // FIXME: don't use pDestinationText, points to popped state | ||||
3275 | auto pValue = new RTFValue(rState.getDestinationText().makeStringAndClear(), true); | ||||
3276 | m_aStates.top().getTableAttributes().set(NS_ooxml::LN_CT_LevelSuffix_val, pValue); | ||||
3277 | } | ||||
3278 | break; | ||||
3279 | case Destination::PARAGRAPHNUMBERING_TEXTBEFORE: | ||||
3280 | if (!m_aStates.empty()) | ||||
3281 | { | ||||
3282 | // FIXME: don't use pDestinationText, points to popped state | ||||
3283 | auto pValue = new RTFValue(rState.getDestinationText().makeStringAndClear(), true); | ||||
3284 | m_aStates.top().getTableAttributes().set(NS_ooxml::LN_CT_LevelText_val, pValue); | ||||
3285 | } | ||||
3286 | break; | ||||
3287 | case Destination::LISTNAME: | ||||
3288 | break; | ||||
3289 | case Destination::LISTLEVEL: | ||||
3290 | if (!m_aStates.empty()) | ||||
3291 | { | ||||
3292 | auto pInnerValue = new RTFValue(m_aStates.top().getListLevelNum()++); | ||||
3293 | rState.getTableAttributes().set(NS_ooxml::LN_CT_Lvl_ilvl, pInnerValue); | ||||
3294 | |||||
3295 | auto pValue = new RTFValue(rState.getTableAttributes(), rState.getTableSprms()); | ||||
3296 | if (m_aStates.top().getDestination() != Destination::LFOLEVEL) | ||||
3297 | m_aStates.top().getListLevelEntries().set(NS_ooxml::LN_CT_AbstractNum_lvl, | ||||
3298 | pValue, RTFOverwrite::NO_APPEND); | ||||
3299 | else | ||||
3300 | m_aStates.top().getTableSprms().set(NS_ooxml::LN_CT_NumLvl_lvl, pValue); | ||||
3301 | } | ||||
3302 | break; | ||||
3303 | case Destination::LFOLEVEL: | ||||
3304 | if (!m_aStates.empty()) | ||||
3305 | { | ||||
3306 | auto pInnerValue = new RTFValue(m_aStates.top().getListLevelNum()++); | ||||
3307 | rState.getTableAttributes().set(NS_ooxml::LN_CT_NumLvl_ilvl, pInnerValue); | ||||
3308 | |||||
3309 | auto pValue = new RTFValue(rState.getTableAttributes(), rState.getTableSprms()); | ||||
3310 | m_aStates.top().getTableSprms().set(NS_ooxml::LN_CT_Num_lvlOverride, pValue, | ||||
3311 | RTFOverwrite::NO_APPEND); | ||||
3312 | } | ||||
3313 | break; | ||||
3314 | // list override table | ||||
3315 | case Destination::LISTOVERRIDEENTRY: | ||||
3316 | if (!m_aStates.empty()) | ||||
3317 | { | ||||
3318 | if (m_aStates.top().getDestination() == Destination::LISTOVERRIDEENTRY) | ||||
3319 | { | ||||
3320 | // copy properties upwards so upper popState() inserts it | ||||
3321 | m_aStates.top().getTableAttributes() = rState.getTableAttributes(); | ||||
3322 | m_aStates.top().getTableSprms() = rState.getTableSprms(); | ||||
3323 | } | ||||
3324 | else | ||||
3325 | { | ||||
3326 | auto pValue = new RTFValue(rState.getTableAttributes(), rState.getTableSprms()); | ||||
3327 | m_aListTableSprms.set(NS_ooxml::LN_CT_Numbering_num, pValue, | ||||
3328 | RTFOverwrite::NO_APPEND); | ||||
3329 | m_aListOverrideTable[rState.getCurrentListOverrideIndex()] | ||||
3330 | = rState.getCurrentListIndex(); | ||||
3331 | } | ||||
3332 | } | ||||
3333 | break; | ||||
3334 | case Destination::LEVELTEXT: | ||||
3335 | if (!m_aStates.empty()) | ||||
3336 | { | ||||
3337 | auto pValue = new RTFValue(rState.getTableAttributes()); | ||||
3338 | m_aStates.top().getTableSprms().set(NS_ooxml::LN_CT_Lvl_lvlText, pValue); | ||||
3339 | } | ||||
3340 | break; | ||||
3341 | case Destination::LEVELNUMBERS: | ||||
3342 | if (!m_aStates.empty()) | ||||
3343 | { | ||||
3344 | m_aStates.top().getTableSprms() = rState.getTableSprms(); | ||||
3345 | if (m_aStates.top().getDestination() == Destination::LEVELNUMBERS | ||||
3346 | || m_aStates.top().getDestination() == Destination::LISTLEVEL) | ||||
3347 | // Parent state is level number or list level, current state is | ||||
3348 | // level numbers: mark parent as invalid as well if necessary. | ||||
3349 | m_aStates.top().setLevelNumbersValid(rState.getLevelNumbersValid()); | ||||
3350 | } | ||||
3351 | break; | ||||
3352 | case Destination::FIELDINSTRUCTION: | ||||
3353 | if (!m_aStates.empty()) | ||||
3354 | m_aStates.top().setFieldStatus(RTFFieldStatus::INSTRUCTION); | ||||
3355 | break; | ||||
3356 | case Destination::FIELDRESULT: | ||||
3357 | if (!m_aStates.empty()) | ||||
3358 | m_aStates.top().setFieldStatus(RTFFieldStatus::RESULT); | ||||
3359 | break; | ||||
3360 | case Destination::FIELD: | ||||
3361 | if (rState.getFieldStatus() == RTFFieldStatus::INSTRUCTION) | ||||
3362 | singleChar(cFieldEnd); | ||||
3363 | break; | ||||
3364 | case Destination::SHAPEPROPERTYVALUEPICT: | ||||
3365 | if (!m_aStates.empty()) | ||||
3366 | { | ||||
3367 | m_aStates.top().getPicture() = rState.getPicture(); | ||||
3368 | // both \sp and \sv are destinations, copy the text up-ward for later | ||||
3369 | m_aStates.top().getDestinationText() = rState.getDestinationText(); | ||||
3370 | } | ||||
3371 | break; | ||||
3372 | case Destination::FALT: | ||||
3373 | if (!m_aStates.empty()) | ||||
3374 | m_aStates.top().getTableSprms() = rState.getTableSprms(); | ||||
3375 | break; | ||||
3376 | case Destination::SHAPEPROPERTYNAME: | ||||
3377 | case Destination::SHAPEPROPERTYVALUE: | ||||
3378 | case Destination::SHAPEPROPERTY: | ||||
3379 | if (!m_aStates.empty()) | ||||
3380 | { | ||||
3381 | m_aStates.top().getShape() = rState.getShape(); | ||||
3382 | m_aStates.top().getPicture() = rState.getPicture(); | ||||
3383 | m_aStates.top().getCharacterAttributes() = rState.getCharacterAttributes(); | ||||
3384 | } | ||||
3385 | break; | ||||
3386 | case Destination::SHAPEINSTRUCTION: | ||||
3387 | if (!m_aStates.empty() | ||||
3388 | && m_aStates.top().getDestination() == Destination::SHAPEINSTRUCTION) | ||||
3389 | { | ||||
3390 | // Shape instruction inside other shape instruction: just copy new shape settings: | ||||
3391 | // it will be resolved on end of topmost shape instruction destination | ||||
3392 | m_aStates.top().getShape() = rState.getShape(); | ||||
3393 | m_aStates.top().getPicture() = rState.getPicture(); | ||||
3394 | m_aStates.top().getCharacterSprms() = rState.getCharacterSprms(); | ||||
3395 | m_aStates.top().getCharacterAttributes() = rState.getCharacterAttributes(); | ||||
3396 | } | ||||
3397 | break; | ||||
3398 | case Destination::FLYMAINCONTENT: | ||||
3399 | case Destination::SHPPICT: | ||||
3400 | case Destination::SHAPE: | ||||
3401 | if (!m_aStates.empty()) | ||||
3402 | { | ||||
3403 | m_aStates.top().getFrame() = rState.getFrame(); | ||||
3404 | if (rState.getDestination() == Destination::SHPPICT | ||||
3405 | && m_aStates.top().getDestination() == Destination::LISTPICTURE) | ||||
3406 | { | ||||
3407 | RTFSprms aAttributes; | ||||
3408 | aAttributes.set(NS_ooxml::LN_CT_NumPicBullet_numPicBulletId, | ||||
3409 | new RTFValue(m_nListPictureId++)); | ||||
3410 | RTFSprms aSprms; | ||||
3411 | // Dummy value, real picture is already sent to dmapper. | ||||
3412 | aSprms.set(NS_ooxml::LN_CT_NumPicBullet_pict, new RTFValue(0)); | ||||
3413 | auto pValue = new RTFValue(aAttributes, aSprms); | ||||
3414 | m_aListTableSprms.set(NS_ooxml::LN_CT_Numbering_numPicBullet, pValue, | ||||
3415 | RTFOverwrite::NO_APPEND); | ||||
3416 | } | ||||
3417 | } | ||||
3418 | break; | ||||
3419 | case Destination::SHAPETEXT: | ||||
3420 | if (!m_aStates.empty()) | ||||
3421 | { | ||||
3422 | // If we're leaving the shapetext group (it may have nested ones) and this is a shape, not an old drawingobject. | ||||
3423 | if (m_aStates.top().getDestination() != Destination::SHAPETEXT | ||||
3424 | && !m_aStates.top().getDrawingObject().getHadShapeText()) | ||||
3425 | { | ||||
3426 | m_aStates.top().setHadShapeText(true); | ||||
3427 | if (!m_aStates.top().getCurrentBuffer()) | ||||
3428 | m_pSdrImport->close(); | ||||
3429 | else | ||||
3430 | m_aStates.top().getCurrentBuffer()->push_back( | ||||
3431 | Buf_t(BUFFER_ENDSHAPE, nullptr, nullptr)); | ||||
3432 | } | ||||
3433 | |||||
3434 | // It's allowed to declare these inside the shape text, and they | ||||
3435 | // are expected to have an effect for the whole shape. | ||||
3436 | if (rState.getDrawingObject().getLeft()) | ||||
3437 | m_aStates.top().getDrawingObject().setLeft(rState.getDrawingObject().getLeft()); | ||||
3438 | if (rState.getDrawingObject().getTop()) | ||||
3439 | m_aStates.top().getDrawingObject().setTop(rState.getDrawingObject().getTop()); | ||||
3440 | if (rState.getDrawingObject().getRight()) | ||||
3441 | m_aStates.top().getDrawingObject().setRight( | ||||
3442 | rState.getDrawingObject().getRight()); | ||||
3443 | if (rState.getDrawingObject().getBottom()) | ||||
3444 | m_aStates.top().getDrawingObject().setBottom( | ||||
3445 | rState.getDrawingObject().getBottom()); | ||||
3446 | } | ||||
3447 | break; | ||||
3448 | case Destination::PROPNAME: | ||||
3449 | if (m_aStates.top().getDestination() == Destination::USERPROPS) | ||||
3450 | m_aStates.top().setPropName(rState.getPropName()); | ||||
3451 | break; | ||||
3452 | default: | ||||
3453 | { | ||||
3454 | if (!m_aStates.empty() && m_aStates.top().getDestination() == Destination::PICT) | ||||
3455 | m_aStates.top().getPicture() = rState.getPicture(); | ||||
3456 | } | ||||
3457 | break; | ||||
3458 | } | ||||
3459 | } | ||||
3460 | |||||
3461 | RTFError RTFDocumentImpl::popState() | ||||
3462 | { | ||||
3463 | //SAL_INFO("writerfilter", __func__ << " before pop: m_pTokenizer->getGroup() " << m_pTokenizer->getGroup() << | ||||
3464 | // ", dest state: " << m_aStates.top().eDestination); | ||||
3465 | |||||
3466 | checkUnicode(/*bUnicode =*/true, /*bHex =*/true); | ||||
3467 | RTFParserState aState(m_aStates.top()); | ||||
3468 | m_bWasInFrame = aState.getFrame().inFrame(); | ||||
3469 | |||||
3470 | // dmapper expects some content in header/footer, so if there would be nothing, add an empty paragraph. | ||||
3471 | if (m_pTokenizer->getGroup() == 1 && m_bFirstRun) | ||||
3472 | { | ||||
3473 | switch (m_nStreamType) | ||||
3474 | { | ||||
3475 | case NS_ooxml::LN_headerl: | ||||
3476 | case NS_ooxml::LN_headerr: | ||||
3477 | case NS_ooxml::LN_headerf: | ||||
3478 | case NS_ooxml::LN_footerl: | ||||
3479 | case NS_ooxml::LN_footerr: | ||||
3480 | case NS_ooxml::LN_footerf: | ||||
3481 | dispatchSymbol(RTF_PAR); | ||||
3482 | break; | ||||
3483 | } | ||||
3484 | } | ||||
3485 | |||||
3486 | RTFError eError = beforePopState(aState); | ||||
3487 | if (eError != RTFError::OK) | ||||
3488 | return eError; | ||||
3489 | |||||
3490 | // See if we need to end a track change | ||||
3491 | if (aState.getStartedTrackchange()) | ||||
3492 | { | ||||
3493 | RTFSprms aTCSprms; | ||||
3494 | auto pValue = new RTFValue(0); | ||||
3495 | aTCSprms.set(NS_ooxml::LN_endtrackchange, pValue); | ||||
3496 | if (!m_aStates.top().getCurrentBuffer()) | ||||
3497 | Mapper().props(new RTFReferenceProperties(RTFSprms(), aTCSprms)); | ||||
3498 | else | ||||
3499 | bufferProperties(*m_aStates.top().getCurrentBuffer(), | ||||
3500 | new RTFValue(RTFSprms(), aTCSprms), nullptr); | ||||
3501 | } | ||||
3502 | |||||
3503 | // This is the end of the doc, see if we need to close the last section. | ||||
3504 | if (m_pTokenizer->getGroup() == 1 && !m_bFirstRun) | ||||
3505 | { | ||||
3506 | // \par means an empty paragraph at the end of footnotes/endnotes, but | ||||
3507 | // not in case of other substreams, like headers. | ||||
3508 | if (m_bNeedCr && m_nStreamType != NS_ooxml::LN_footnote | ||||
3509 | && m_nStreamType != NS_ooxml::LN_endnote && m_bIsNewDoc) | ||||
3510 | dispatchSymbol(RTF_PAR); | ||||
3511 | if (m_bNeedSect) // may be set by dispatchSymbol above! | ||||
3512 | sectBreak(true); | ||||
3513 | } | ||||
3514 | |||||
3515 | m_aStates.pop(); | ||||
3516 | |||||
3517 | m_pTokenizer->popGroup(); | ||||
3518 | |||||
3519 | afterPopState(aState); | ||||
3520 | |||||
3521 | if (aState.getCurrentBuffer() == &m_aSuperBuffer) | ||||
3522 | { | ||||
3523 | OSL_ASSERT(!m_aStates.empty() && m_aStates.top().getCurrentBuffer() == nullptr)do { if (true && (!(!m_aStates.empty() && m_aStates .top().getCurrentBuffer() == nullptr))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "3523" ": "), "OSL_ASSERT: %s", "!m_aStates.empty() && m_aStates.top().getCurrentBuffer() == nullptr" ); } } while (false); | ||||
3524 | |||||
3525 | if (!m_aSuperBuffer.empty()) | ||||
3526 | replayBuffer(m_aSuperBuffer, nullptr, nullptr); | ||||
3527 | } | ||||
3528 | |||||
3529 | if (!m_aStates.empty() && m_aStates.top().getTableRowWidthAfter() > 0 | ||||
3530 | && aState.getTableRowWidthAfter() == 0) | ||||
3531 | // An RTF_ROW in the inner group already parsed nTableRowWidthAfter, | ||||
3532 | // don't do it again in the outer state later. | ||||
3533 | m_aStates.top().setTableRowWidthAfter(0); | ||||
3534 | |||||
3535 | if (m_nResetBreakOnSectBreak != RTF_invalid && !m_aStates.empty()) | ||||
3536 | { | ||||
3537 | // Section break type created for \page still has an effect in the | ||||
3538 | // outer state as well. | ||||
3539 | RTFValue::Pointer_t pType | ||||
3540 | = aState.getSectionSprms().find(NS_ooxml::LN_EG_SectPrContents_type); | ||||
3541 | if (pType) | ||||
3542 | m_aStates.top().getSectionSprms().set(NS_ooxml::LN_EG_SectPrContents_type, pType); | ||||
3543 | } | ||||
3544 | |||||
3545 | return RTFError::OK; | ||||
3546 | } | ||||
3547 | |||||
3548 | RTFError RTFDocumentImpl::handleEmbeddedObject() | ||||
3549 | { | ||||
3550 | OString aStr | ||||
3551 | = OUStringToOString(m_aStates.top().getCurrentDestinationText()->makeStringAndClear(), | ||||
3552 | RTL_TEXTENCODING_ASCII_US(((rtl_TextEncoding) 11))); | ||||
3553 | std::unique_ptr<SvStream> pStream(new SvMemoryStream()); | ||||
3554 | if (!msfilter::rtfutil::ExtractOLE2FromObjdata(aStr, *pStream)) | ||||
3555 | return RTFError::HEX_INVALID; | ||||
3556 | |||||
3557 | uno::Reference<io::XInputStream> xInputStream( | ||||
3558 | new utl::OSeekableInputStreamWrapper(pStream.release(), /*_bOwner=*/true)); | ||||
3559 | auto pStreamValue = new RTFValue(xInputStream); | ||||
3560 | m_aOLEAttributes.set(NS_ooxml::LN_inputstream, pStreamValue); | ||||
3561 | |||||
3562 | return RTFError::OK; | ||||
3563 | } | ||||
3564 | |||||
3565 | bool RTFDocumentImpl::isInBackground() { return m_aStates.top().getInBackground(); } | ||||
3566 | |||||
3567 | RTFInternalState RTFDocumentImpl::getInternalState() { return m_aStates.top().getInternalState(); } | ||||
3568 | |||||
3569 | void RTFDocumentImpl::setInternalState(RTFInternalState nInternalState) | ||||
3570 | { | ||||
3571 | m_aStates.top().setInternalState(nInternalState); | ||||
3572 | } | ||||
3573 | |||||
3574 | Destination RTFDocumentImpl::getDestination() { return m_aStates.top().getDestination(); } | ||||
3575 | |||||
3576 | void RTFDocumentImpl::setDestination(Destination eDestination) | ||||
3577 | { | ||||
3578 | m_aStates.top().setDestination(eDestination); | ||||
3579 | } | ||||
3580 | |||||
3581 | // this is a questionably named method that is used only in a very special | ||||
3582 | // situation where it looks like the "current" buffer is needed? | ||||
3583 | void RTFDocumentImpl::setDestinationText(OUString const& rString) | ||||
3584 | { | ||||
3585 | m_aStates.top().getDestinationText().setLength(0); | ||||
3586 | m_aStates.top().getDestinationText().append(rString); | ||||
3587 | } | ||||
3588 | |||||
3589 | bool RTFDocumentImpl::getSkipUnknown() { return m_bSkipUnknown; } | ||||
3590 | |||||
3591 | void RTFDocumentImpl::setSkipUnknown(bool bSkipUnknown) { m_bSkipUnknown = bSkipUnknown; } | ||||
3592 | |||||
3593 | static auto FilterControlChars(Destination const destination, OUString const& rString) -> OUString | ||||
3594 | { | ||||
3595 | if (destination == Destination::LEVELNUMBERS || destination == Destination::LEVELTEXT) | ||||
3596 | { // control characters are magic here! | ||||
3597 | return rString; | ||||
3598 | } | ||||
3599 | OUStringBuffer buf(rString.getLength()); | ||||
3600 | for (sal_Int32 i = 0; i < rString.getLength(); ++i) | ||||
3601 | { | ||||
3602 | sal_Unicode const ch(rString[i]); | ||||
3603 | if (!linguistic::IsControlChar(ch) || ch == '\r' || ch == '\n' || ch == '\t') | ||||
3604 | { | ||||
3605 | buf.append(ch); | ||||
3606 | } | ||||
3607 | else | ||||
3608 | { | ||||
3609 | SAL_INFO("writerfilter.rtf", "filtering control character")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO , "writerfilter.rtf")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "filtering control character" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf" ), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "3609" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "filtering control character"), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "filtering control character"; ::sal::detail::log( ( ::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "3609" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "filtering control character") == 1) { ::sal_detail_log ( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "3609" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "filtering control character"), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "filtering control character"; ::sal::detail::log( ( ::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter.rtf"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdocumentimpl.cxx" ":" "3609" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||
3610 | } | ||||
3611 | } | ||||
3612 | return buf.makeStringAndClear(); | ||||
3613 | } | ||||
3614 | |||||
3615 | void RTFDocumentImpl::checkUnicode(bool bUnicode, bool bHex) | ||||
3616 | { | ||||
3617 | if (bUnicode && !m_aUnicodeBuffer.isEmpty()) | ||||
3618 | { | ||||
3619 | OUString aString = m_aUnicodeBuffer.toString(); | ||||
3620 | m_aUnicodeBuffer.setLength(0); | ||||
3621 | aString = FilterControlChars(m_aStates.top().getDestination(), aString); | ||||
3622 | text(aString); | ||||
3623 | } | ||||
3624 | if (bHex && !m_aHexBuffer.isEmpty()) | ||||
3625 | { | ||||
3626 | rtl_TextEncoding nEncoding = m_aStates.top().getCurrentEncoding(); | ||||
3627 | if (m_aStates.top().getDestination() == Destination::FONTENTRY | ||||
3628 | && m_aStates.top().getCurrentEncoding() == RTL_TEXTENCODING_SYMBOL(((rtl_TextEncoding) 10))) | ||||
3629 | nEncoding = RTL_TEXTENCODING_MS_1252(((rtl_TextEncoding) 1)); | ||||
3630 | OUString aString = OStringToOUString(m_aHexBuffer.toString(), nEncoding); | ||||
3631 | m_aHexBuffer.setLength(0); | ||||
3632 | aString = FilterControlChars(m_aStates.top().getDestination(), aString); | ||||
3633 | text(aString); | ||||
3634 | } | ||||
3635 | } | ||||
3636 | |||||
3637 | RTFParserState::RTFParserState(RTFDocumentImpl* pDocumentImpl) | ||||
3638 | : m_pDocumentImpl(pDocumentImpl) | ||||
3639 | , m_nInternalState(RTFInternalState::NORMAL) | ||||
3640 | , m_eDestination(Destination::NORMAL) | ||||
3641 | , m_eFieldStatus(RTFFieldStatus::NONE) | ||||
3642 | , m_nBorderState(RTFBorderState::NONE) | ||||
3643 | , m_nCurrentEncoding(rtl_getTextEncodingFromWindowsCharset(0)) | ||||
3644 | , m_nUc(1) | ||||
3645 | , m_nCharsToSkip(0) | ||||
3646 | , m_nBinaryToRead(0) | ||||
3647 | , m_nListLevelNum(0) | ||||
3648 | , m_bLevelNumbersValid(true) | ||||
3649 | , m_aFrame(this) | ||||
3650 | , m_eRunType(RunType::NONE) | ||||
3651 | , m_nYear(0) | ||||
3652 | , m_nMonth(0) | ||||
3653 | , m_nDay(0) | ||||
3654 | , m_nHour(0) | ||||
3655 | , m_nMinute(0) | ||||
3656 | , m_pCurrentDestinationText(nullptr) | ||||
3657 | , m_nCurrentStyleIndex(-1) | ||||
3658 | , m_nCurrentCharacterStyleIndex(-1) | ||||
3659 | , m_pCurrentBuffer(nullptr) | ||||
3660 | , m_bInListpicture(false) | ||||
3661 | , m_bInBackground(false) | ||||
3662 | , m_bHadShapeText(false) | ||||
3663 | , m_bInShapeGroup(false) | ||||
3664 | , m_bInShape(false) | ||||
3665 | , m_bCreatedShapeGroup(false) | ||||
3666 | , m_bStartedTrackchange(false) | ||||
3667 | , m_nTableRowWidthAfter(0) | ||||
3668 | { | ||||
3669 | } | ||||
3670 | |||||
3671 | void RTFDocumentImpl::resetFrame() { m_aStates.top().getFrame() = RTFFrame(&m_aStates.top()); } | ||||
3672 | |||||
3673 | void RTFDocumentImpl::bufferProperties(RTFBuffer_t& rBuffer, const RTFValue::Pointer_t& pValue, | ||||
3674 | const tools::SvRef<TableRowBuffer>& pTableProperties) | ||||
3675 | { | ||||
3676 | rBuffer.emplace_back( | ||||
3677 | Buf_t(BUFFER_SETSTYLE, new RTFValue(m_aStates.top().getCurrentStyleIndex()), nullptr)); | ||||
3678 | rBuffer.emplace_back(Buf_t(BUFFER_PROPS, pValue, pTableProperties)); | ||||
3679 | } | ||||
3680 | |||||
3681 | RTFShape::RTFShape() = default; | ||||
3682 | |||||
3683 | RTFDrawingObject::RTFDrawingObject() = default; | ||||
3684 | |||||
3685 | RTFFrame::RTFFrame(RTFParserState* pParserState) | ||||
3686 | : m_pDocumentImpl(pParserState->getDocumentImpl()) | ||||
3687 | , m_nX(0) | ||||
3688 | , m_nY(0) | ||||
3689 | , m_nW(0) | ||||
3690 | , m_nH(0) | ||||
3691 | , m_nHoriPadding(0) | ||||
3692 | , m_nVertPadding(0) | ||||
3693 | , m_nHoriAlign(0) | ||||
3694 | , m_nHoriAnchor(0) | ||||
3695 | , m_nVertAlign(0) | ||||
3696 | , m_nVertAnchor(0) | ||||
3697 | , m_nHRule(NS_ooxml::LN_Value_doc_ST_HeightRule_auto) | ||||
3698 | { | ||||
3699 | } | ||||
3700 | |||||
3701 | void RTFFrame::setSprm(Id nId, Id nValue) | ||||
3702 | { | ||||
3703 | if (m_pDocumentImpl->getFirstRun() && !m_pDocumentImpl->isStyleSheetImport()) | ||||
3704 | { | ||||
3705 | m_pDocumentImpl->checkFirstRun(); | ||||
3706 | m_pDocumentImpl->setNeedPar(false); | ||||
3707 | } | ||||
3708 | switch (nId) | ||||
3709 | { | ||||
3710 | case NS_ooxml::LN_CT_FramePr_w: | ||||
3711 | m_nW = nValue; | ||||
3712 | break; | ||||
3713 | case NS_ooxml::LN_CT_FramePr_h: | ||||
3714 | m_nH = nValue; | ||||
3715 | break; | ||||
3716 | case NS_ooxml::LN_CT_FramePr_x: | ||||
3717 | m_nX = nValue; | ||||
3718 | break; | ||||
3719 | case NS_ooxml::LN_CT_FramePr_y: | ||||
3720 | m_nY = nValue; | ||||
3721 | break; | ||||
3722 | case NS_ooxml::LN_CT_FramePr_hSpace: | ||||
3723 | m_nHoriPadding = nValue; | ||||
3724 | break; | ||||
3725 | case NS_ooxml::LN_CT_FramePr_vSpace: | ||||
3726 | m_nVertPadding = nValue; | ||||
3727 | break; | ||||
3728 | case NS_ooxml::LN_CT_FramePr_xAlign: | ||||
3729 | m_nHoriAlign = nValue; | ||||
3730 | break; | ||||
3731 | case NS_ooxml::LN_CT_FramePr_hAnchor: | ||||
3732 | m_nHoriAnchor = nValue; | ||||
3733 | break; | ||||
3734 | case NS_ooxml::LN_CT_FramePr_yAlign: | ||||
3735 | m_nVertAlign = nValue; | ||||
3736 | break; | ||||
3737 | case NS_ooxml::LN_CT_FramePr_vAnchor: | ||||
3738 | m_nVertAnchor = nValue; | ||||
3739 | break; | ||||
3740 | case NS_ooxml::LN_CT_FramePr_wrap: | ||||
3741 | m_oWrap = nValue; | ||||
3742 | break; | ||||
3743 | default: | ||||
3744 | break; | ||||
3745 | } | ||||
3746 | } | ||||
3747 | |||||
3748 | RTFSprms RTFFrame::getSprms() | ||||
3749 | { | ||||
3750 | RTFSprms sprms; | ||||
3751 | |||||
3752 | static const Id pNames[] | ||||
3753 | = { NS_ooxml::LN_CT_FramePr_x, NS_ooxml::LN_CT_FramePr_y, | ||||
3754 | NS_ooxml::LN_CT_FramePr_hRule, // Make sure nHRule is processed before nH | ||||
3755 | NS_ooxml::LN_CT_FramePr_h, NS_ooxml::LN_CT_FramePr_w, | ||||
3756 | NS_ooxml::LN_CT_FramePr_hSpace, NS_ooxml::LN_CT_FramePr_vSpace, | ||||
3757 | NS_ooxml::LN_CT_FramePr_hAnchor, NS_ooxml::LN_CT_FramePr_vAnchor, | ||||
3758 | NS_ooxml::LN_CT_FramePr_xAlign, NS_ooxml::LN_CT_FramePr_yAlign, | ||||
3759 | NS_ooxml::LN_CT_FramePr_wrap, NS_ooxml::LN_CT_FramePr_dropCap, | ||||
3760 | NS_ooxml::LN_CT_FramePr_lines }; | ||||
3761 | |||||
3762 | for (Id nId : pNames) | ||||
3763 | { | ||||
3764 | RTFValue::Pointer_t pValue; | ||||
3765 | |||||
3766 | switch (nId) | ||||
3767 | { | ||||
3768 | case NS_ooxml::LN_CT_FramePr_x: | ||||
3769 | if (m_nX != 0) | ||||
3770 | pValue = new RTFValue(m_nX); | ||||
3771 | break; | ||||
3772 | case NS_ooxml::LN_CT_FramePr_y: | ||||
3773 | if (m_nY != 0) | ||||
3774 | pValue = new RTFValue(m_nY); | ||||
3775 | break; | ||||
3776 | case NS_ooxml::LN_CT_FramePr_h: | ||||
3777 | if (m_nH != 0) | ||||
3778 | { | ||||
3779 | if (m_nHRule == NS_ooxml::LN_Value_doc_ST_HeightRule_exact) | ||||
3780 | pValue = new RTFValue(-m_nH); // The negative value just sets nHRule | ||||
3781 | else | ||||
3782 | pValue = new RTFValue(m_nH); | ||||
3783 | } | ||||
3784 | break; | ||||
3785 | case NS_ooxml::LN_CT_FramePr_w: | ||||
3786 | if (m_nW != 0) | ||||
3787 | pValue = new RTFValue(m_nW); | ||||
3788 | break; | ||||
3789 | case NS_ooxml::LN_CT_FramePr_hSpace: | ||||
3790 | if (m_nHoriPadding != 0) | ||||
3791 | pValue = new RTFValue(m_nHoriPadding); | ||||
3792 | break; | ||||
3793 | case NS_ooxml::LN_CT_FramePr_vSpace: | ||||
3794 | if (m_nVertPadding != 0) | ||||
3795 | pValue = new RTFValue(m_nVertPadding); | ||||
3796 | break; | ||||
3797 | case NS_ooxml::LN_CT_FramePr_hAnchor: | ||||
3798 | { | ||||
3799 | if (m_nHoriAnchor == 0) | ||||
3800 | m_nHoriAnchor = NS_ooxml::LN_Value_doc_ST_HAnchor_margin; | ||||
3801 | pValue = new RTFValue(m_nHoriAnchor); | ||||
3802 | } | ||||
3803 | break; | ||||
3804 | case NS_ooxml::LN_CT_FramePr_vAnchor: | ||||
3805 | { | ||||
3806 | if (m_nVertAnchor == 0) | ||||
3807 | m_nVertAnchor = NS_ooxml::LN_Value_doc_ST_VAnchor_margin; | ||||
3808 | pValue = new RTFValue(m_nVertAnchor); | ||||
3809 | } | ||||
3810 | break; | ||||
3811 | case NS_ooxml::LN_CT_FramePr_xAlign: | ||||
3812 | pValue = new RTFValue(m_nHoriAlign); | ||||
3813 | break; | ||||
3814 | case NS_ooxml::LN_CT_FramePr_yAlign: | ||||
3815 | pValue = new RTFValue(m_nVertAlign); | ||||
3816 | break; | ||||
3817 | case NS_ooxml::LN_CT_FramePr_hRule: | ||||
3818 | { | ||||
3819 | if (m_nH < 0) | ||||
3820 | m_nHRule = NS_ooxml::LN_Value_doc_ST_HeightRule_exact; | ||||
3821 | else if (m_nH > 0) | ||||
3822 | m_nHRule = NS_ooxml::LN_Value_doc_ST_HeightRule_atLeast; | ||||
3823 | pValue = new RTFValue(m_nHRule); | ||||
3824 | } | ||||
3825 | break; | ||||
3826 | case NS_ooxml::LN_CT_FramePr_wrap: | ||||
3827 | if (m_oWrap) | ||||
3828 | pValue = new RTFValue(*m_oWrap); | ||||
3829 | break; | ||||
3830 | default: | ||||
3831 | break; | ||||
3832 | } | ||||
3833 | |||||
3834 | if (pValue) | ||||
3835 | sprms.set(nId, pValue); | ||||
3836 | } | ||||
3837 | |||||
3838 | RTFSprms frameprSprms; | ||||
3839 | frameprSprms.set(NS_ooxml::LN_CT_PPrBase_framePr, new RTFValue(sprms)); | ||||
3840 | return frameprSprms; | ||||
3841 | } | ||||
3842 | |||||
3843 | bool RTFFrame::hasProperties() const | ||||
3844 | { | ||||
3845 | return m_nX != 0 || m_nY != 0 || m_nW != 0 || m_nH != 0 || m_nHoriPadding != 0 | ||||
3846 | || m_nVertPadding != 0 || m_nHoriAlign != 0 || m_nHoriAnchor != 0 || m_nVertAlign != 0 | ||||
3847 | || m_nVertAnchor != 0; | ||||
3848 | } | ||||
3849 | |||||
3850 | } // namespace writerfilter | ||||
3851 | |||||
3852 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |
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 | * This file incorporates work covered by the following license notice: |
10 | * |
11 | * Licensed to the Apache Software Foundation (ASF) under one or more |
12 | * contributor license agreements. See the NOTICE file distributed |
13 | * with this work for additional information regarding copyright |
14 | * ownership. The ASF licenses this file to you under the Apache |
15 | * License, Version 2.0 (the "License"); you may not use this file |
16 | * except in compliance with the License. You may obtain a copy of |
17 | * the License at http://www.apache.org/licenses/LICENSE-2.0 . |
18 | */ |
19 | #ifndef INCLUDED_TOOLS_REF_HXX |
20 | #define INCLUDED_TOOLS_REF_HXX |
21 | |
22 | #include <sal/config.h> |
23 | #include <cassert> |
24 | #include <tools/toolsdllapi.h> |
25 | #include <utility> |
26 | |
27 | /** |
28 | This implements similar functionality to boost::intrusive_ptr |
29 | */ |
30 | |
31 | namespace tools { |
32 | |
33 | /** T must be a class that extends SvRefBase */ |
34 | template<typename T> class SAL_DLLPUBLIC_RTTI__attribute__ ((type_visibility("default"))) SvRef final { |
35 | public: |
36 | SvRef(): pObj(nullptr) {} |
37 | |
38 | SvRef(SvRef&& rObj) noexcept |
39 | { |
40 | pObj = rObj.pObj; |
41 | rObj.pObj = nullptr; |
42 | } |
43 | |
44 | SvRef(SvRef const & rObj): pObj(rObj.pObj) |
45 | { |
46 | if (pObj != nullptr) pObj->AddNextRef(); |
47 | } |
48 | |
49 | SvRef(T * pObjP): pObj(pObjP) |
50 | { |
51 | if (pObj != nullptr) pObj->AddFirstRef(); |
52 | } |
53 | |
54 | ~SvRef() |
55 | { |
56 | if (pObj != nullptr) pObj->ReleaseRef(); |
57 | } |
58 | |
59 | void clear() |
60 | { |
61 | if (pObj != nullptr) { |
62 | T * pRefObj = pObj; |
63 | pObj = nullptr; |
64 | pRefObj->ReleaseRef(); |
65 | } |
66 | } |
67 | |
68 | SvRef & operator =(SvRef const & rObj) |
69 | { |
70 | if (rObj.pObj != nullptr) { |
71 | rObj.pObj->AddNextRef(); |
72 | } |
73 | T * pRefObj = pObj; |
74 | pObj = rObj.pObj; |
75 | if (pRefObj != nullptr) { |
76 | pRefObj->ReleaseRef(); |
77 | } |
78 | return *this; |
79 | } |
80 | |
81 | SvRef & operator =(SvRef && rObj) |
82 | { |
83 | if (pObj != nullptr) { |
84 | pObj->ReleaseRef(); |
85 | } |
86 | pObj = rObj.pObj; |
87 | rObj.pObj = nullptr; |
88 | return *this; |
89 | } |
90 | |
91 | bool is() const { return pObj != nullptr; } |
92 | |
93 | explicit operator bool() const { return is(); } |
94 | |
95 | T * get() const { return pObj; } |
96 | |
97 | T * operator ->() const { assert(pObj != nullptr)(static_cast <bool> (pObj != nullptr) ? void (0) : __assert_fail ("pObj != nullptr", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx" , 97, __extension__ __PRETTY_FUNCTION__)); return pObj; } |
98 | |
99 | T & operator *() const { assert(pObj != nullptr)(static_cast <bool> (pObj != nullptr) ? void (0) : __assert_fail ("pObj != nullptr", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx" , 99, __extension__ __PRETTY_FUNCTION__)); return *pObj; } |
100 | |
101 | bool operator ==(const SvRef<T> &rhs) const { return pObj == rhs.pObj; } |
102 | bool operator !=(const SvRef<T> &rhs) const { return !(*this == rhs); } |
103 | |
104 | private: |
105 | T * pObj; |
106 | }; |
107 | |
108 | /** |
109 | * This implements similar functionality to std::make_shared. |
110 | */ |
111 | template<typename T, typename... Args> |
112 | SvRef<T> make_ref(Args&& ... args) |
113 | { |
114 | return SvRef<T>(new T(std::forward<Args>(args)...)); |
115 | } |
116 | |
117 | } |
118 | |
119 | /** Classes that want to be referenced-counted via SvRef<T>, should extend this base class */ |
120 | class TOOLS_DLLPUBLIC__attribute__ ((visibility("default"))) SvRefBase |
121 | { |
122 | // work around a clang 3.5 optimization bug: if the bNoDelete is *first* |
123 | // it mis-compiles "if (--nRefCount == 0)" and never deletes any object |
124 | unsigned int nRefCount : 31; |
125 | // the only reason this is not bool is because MSVC cannot handle mixed type bitfields |
126 | unsigned int bNoDelete : 1; |
127 | |
128 | protected: |
129 | virtual ~SvRefBase() COVERITY_NOEXCEPT_FALSE; |
130 | |
131 | public: |
132 | SvRefBase() : nRefCount(0), bNoDelete(1) {} |
133 | SvRefBase(const SvRefBase &) : nRefCount(0), bNoDelete(1) {} |
134 | |
135 | SvRefBase & operator=(const SvRefBase &) { return *this; } |
136 | |
137 | void RestoreNoDelete() |
138 | { bNoDelete = 1; } |
139 | |
140 | void AddNextRef() |
141 | { |
142 | assert( nRefCount < (1 << 30) && "Do not add refs to dead objects" )(static_cast <bool> (nRefCount < (1 << 30) && "Do not add refs to dead objects") ? void (0) : __assert_fail ("nRefCount < (1 << 30) && \"Do not add refs to dead objects\"" , "/home/maarten/src/libreoffice/core/include/tools/ref.hxx", 142, __extension__ __PRETTY_FUNCTION__)); |
143 | ++nRefCount; |
144 | } |
145 | |
146 | void AddFirstRef() |
147 | { |
148 | assert( nRefCount < (1 << 30) && "Do not add refs to dead objects" )(static_cast <bool> (nRefCount < (1 << 30) && "Do not add refs to dead objects") ? void (0) : __assert_fail ("nRefCount < (1 << 30) && \"Do not add refs to dead objects\"" , "/home/maarten/src/libreoffice/core/include/tools/ref.hxx", 148, __extension__ __PRETTY_FUNCTION__)); |
149 | if( bNoDelete ) |
150 | bNoDelete = 0; |
151 | ++nRefCount; |
152 | } |
153 | |
154 | void ReleaseRef() |
155 | { |
156 | assert( nRefCount >= 1)(static_cast <bool> (nRefCount >= 1) ? void (0) : __assert_fail ("nRefCount >= 1", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx" , 156, __extension__ __PRETTY_FUNCTION__)); |
157 | if( --nRefCount == 0 && !bNoDelete) |
158 | { |
159 | // I'm not sure about the original purpose of this line, but right now |
160 | // it serves the purpose that anything that attempts to do an AddRef() |
161 | // after an object is deleted will trip an assert. |
162 | nRefCount = 1 << 30; |
163 | delete this; |
164 | } |
165 | } |
166 | |
167 | unsigned int GetRefCount() const |
168 | { return nRefCount; } |
169 | }; |
170 | |
171 | template<typename T> |
172 | class SvCompatWeakBase; |
173 | |
174 | /** SvCompatWeakHdl acts as an intermediary between SvCompatWeakRef<T> and T. |
175 | */ |
176 | template<typename T> |
177 | class SvCompatWeakHdl final : public SvRefBase |
178 | { |
179 | friend class SvCompatWeakBase<T>; |
180 | T* _pObj; |
181 | |
182 | SvCompatWeakHdl( T* pObj ) : _pObj( pObj ) {} |
183 | |
184 | public: |
185 | void ResetWeakBase( ) { _pObj = nullptr; } |
186 | T* GetObj() { return _pObj; } |
187 | }; |
188 | |
189 | /** We only have one place that extends this, in include/sfx2/frame.hxx, class SfxFrame. |
190 | Its function is to notify the SvCompatWeakHdl when an SfxFrame object is deleted. |
191 | */ |
192 | template<typename T> |
193 | class SvCompatWeakBase |
194 | { |
195 | tools::SvRef< SvCompatWeakHdl<T> > _xHdl; |
196 | |
197 | public: |
198 | /** Does not use initializer due to compiler warnings, |
199 | because the lifetime of the _xHdl object can exceed the lifetime of this class. |
200 | */ |
201 | SvCompatWeakBase( T* pObj ) { _xHdl = new SvCompatWeakHdl<T>( pObj ); } |
202 | |
203 | ~SvCompatWeakBase() { _xHdl->ResetWeakBase(); } |
204 | |
205 | SvCompatWeakHdl<T>* GetHdl() { return _xHdl.get(); } |
206 | }; |
207 | |
208 | /** We only have one weak reference in LO, in include/sfx2/frame.hxx, class SfxFrameWeak. |
209 | */ |
210 | template<typename T> |
211 | class SAL_WARN_UNUSED__attribute__((warn_unused)) SvCompatWeakRef |
212 | { |
213 | tools::SvRef< SvCompatWeakHdl<T> > _xHdl; |
214 | public: |
215 | SvCompatWeakRef( ) {} |
216 | SvCompatWeakRef( T* pObj ) |
217 | { if( pObj ) _xHdl = pObj->GetHdl(); } |
218 | #if defined(__COVERITY__) |
219 | ~SvCompatWeakRef() COVERITY_NOEXCEPT_FALSE {} |
220 | #endif |
221 | SvCompatWeakRef& operator = ( T * pObj ) |
222 | { _xHdl = pObj ? pObj->GetHdl() : nullptr; return *this; } |
223 | bool is() const |
224 | { return _xHdl.is() && _xHdl->GetObj(); } |
225 | explicit operator bool() const { return is(); } |
226 | T* operator -> () const |
227 | { return _xHdl.is() ? _xHdl->GetObj() : nullptr; } |
228 | operator T* () const |
229 | { return _xHdl.is() ? _xHdl->GetObj() : nullptr; } |
230 | }; |
231 | |
232 | #endif |
233 | |
234 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |