1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "XMLSectionImportContext.hxx"
21 #include "XMLSectionSourceImportContext.hxx"
22 #include "XMLSectionSourceDDEImportContext.hxx"
23 #include <comphelper/base64.hxx>
24 #include <xmloff/xmlictxt.hxx>
25 #include <xmloff/xmlimp.hxx>
26 #include <xmloff/txtimp.hxx>
27 #include <xmloff/namespacemap.hxx>
28 #include <xmloff/xmlnamespace.hxx>
29 #include <xmloff/xmltoken.hxx>
30 #include <xmloff/prstylei.hxx>
31 #include <sal/log.hxx>
32 #include <sax/tools/converter.hxx>
33 #include <com/sun/star/container/XNamed.hpp>
34 #include <com/sun/star/frame/XModel.hpp>
35 #include <com/sun/star/uno/Reference.h>
36 #include <com/sun/star/text/XTextContent.hpp>
37 #include <com/sun/star/beans/XPropertySet.hpp>
38 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
39 #include <com/sun/star/text/ControlCharacter.hpp>
42 using ::com::sun::star::beans::XPropertySet
;
43 using ::com::sun::star::uno::Reference
;
44 using ::com::sun::star::xml::sax::XFastAttributeList
;
45 using ::com::sun::star::lang::XMultiServiceFactory
;
46 using ::com::sun::star::container::XNamed
;
48 using namespace ::com::sun::star::uno
;
49 using namespace ::com::sun::star::text
;
50 using namespace ::xmloff::token
;
53 // section import: This one is fairly tricky due to a variety of
54 // limits of the core or the API. The main problem is that if you
55 // insert a section within another section, you can't move the cursor
56 // between the ends of the inner and the enclosing section. To avoid
57 // these problems, additional markers are first inserted and later deleted.
58 XMLSectionImportContext::XMLSectionImportContext( SvXMLImport
& rImport
)
59 : SvXMLImportContext(rImport
)
65 , bIsCurrentlyVisible(true)
66 , bIsCurrentlyVisibleOK(false)
71 XMLSectionImportContext::~XMLSectionImportContext()
75 void XMLSectionImportContext::startFastElement( sal_Int32 nElement
,
76 const css::uno::Reference
< css::xml::sax::XFastAttributeList
>& xAttrList
)
79 ProcessAttributes(xAttrList
);
81 // process index headers:
82 bool bIsIndexHeader
= (nElement
& TOKEN_MASK
) == XML_INDEX_TITLE
;
88 rtl::Reference
<XMLTextImportHelper
> rHelper
= GetImport().GetTextImport();
94 // create text section (as XPropertySet)
95 Reference
<XMultiServiceFactory
> xFactory(
96 GetImport().GetModel(),UNO_QUERY
);
100 Reference
<XInterface
> xIfc
=
101 xFactory
->createInstance( bIsIndexHeader
? u
"com.sun.star.text.IndexHeaderSection"_ustr
102 : u
"com.sun.star.text.TextSection"_ustr
);
106 Reference
<XPropertySet
> xPropSet(xIfc
, UNO_QUERY
);
108 // save PropertySet (for CreateChildContext)
109 xSectionPropertySet
= xPropSet
;
112 Reference
<XNamed
> xNamed(xPropSet
, UNO_QUERY
);
113 xNamed
->setName(sName
);
116 if (!sStyleName
.isEmpty())
118 XMLPropStyleContext
* pStyle
= rHelper
->
119 FindSectionStyle(sStyleName
);
121 if (pStyle
!= nullptr)
123 pStyle
->FillPropertySet( xPropSet
);
127 // IsVisible and condition (not for index headers)
128 if (! bIsIndexHeader
)
130 xPropSet
->setPropertyValue( u
"IsVisible"_ustr
, Any(bIsVisible
) );
132 // #97450# hidden sections must be hidden on reload
133 // For backwards compatibility, set flag only if it is
135 if( bIsCurrentlyVisibleOK
)
137 xPropSet
->setPropertyValue( u
"IsCurrentlyVisible"_ustr
, Any(bIsCurrentlyVisible
));
142 xPropSet
->setPropertyValue( u
"Condition"_ustr
, Any(sCond
) );
146 // password (only for regular sections)
148 (nElement
& TOKEN_MASK
) == XML_SECTION
)
150 xPropSet
->setPropertyValue(u
"ProtectionKey"_ustr
, Any(aSequence
));
154 xPropSet
->setPropertyValue( u
"IsProtected"_ustr
, Any(bProtect
) );
156 // insert marker, <paragraph>, marker; then insert
157 // section over the first marker character, and delete the
158 // last paragraph (and marker) when closing a section.
159 Reference
<XTextRange
> xStart
=
160 rHelper
->GetCursor()->getStart();
162 OUString
sMarkerString(" ");
164 OUString
sMarkerString(u
"X"_ustr
);
166 rHelper
->InsertString(sMarkerString
);
167 rHelper
->InsertControlCharacter(
168 ControlCharacter::APPEND_PARAGRAPH
);
169 rHelper
->InsertString(sMarkerString
);
171 // select first marker
172 rHelper
->GetCursor()->gotoRange(xStart
, false);
173 rHelper
->GetCursor()->goRight(1, true);
175 // convert section to XTextContent
176 Reference
<XTextContent
> xTextContent(xSectionPropertySet
,
179 // and insert (over marker)
180 rHelper
->GetText()->insertTextContent(
181 rHelper
->GetCursorAsRange(), xTextContent
, true );
183 // and delete first marker (in section)
184 rHelper
->GetText()->insertString(
185 rHelper
->GetCursorAsRange(), u
""_ustr
, true);
187 // finally, check for redlines that should start at
188 // the section start node
189 rHelper
->RedlineAdjustStartNodeCursor(); // start ???
191 // xml:id for RDF metadata
192 GetImport().SetXmlId(xIfc
, sXmlId
);
195 void XMLSectionImportContext::ProcessAttributes(
196 const Reference
<XFastAttributeList
> & xAttrList
)
198 for( auto& aIter
: sax_fastparser::castToFastAttributeList(xAttrList
) )
200 switch (aIter
.getToken())
202 case XML_ELEMENT(XML
, XML_ID
):
203 sXmlId
= aIter
.toString();
205 case XML_ELEMENT(TEXT
, XML_STYLE_NAME
):
206 sStyleName
= aIter
.toString();
208 case XML_ELEMENT(TEXT
, XML_NAME
):
209 sName
= aIter
.toString();
212 case XML_ELEMENT(TEXT
, XML_CONDITION
):
214 OUString sValue
= aIter
.toString();
216 sal_uInt16 nPrefix
= GetImport().GetNamespaceMap().
217 GetKeyByAttrValueQName(sValue
, &sTmp
);
218 if( XML_NAMESPACE_OOOW
== nPrefix
)
227 case XML_ELEMENT(TEXT
, XML_DISPLAY
):
228 if (IsXMLToken(aIter
, XML_TRUE
))
232 else if ( IsXMLToken(aIter
, XML_NONE
) ||
233 IsXMLToken(aIter
, XML_CONDITION
) )
239 case XML_ELEMENT(TEXT
, XML_IS_HIDDEN
):
242 if (::sax::Converter::convertBool(bTmp
, aIter
.toView()))
244 bIsCurrentlyVisible
= !bTmp
;
245 bIsCurrentlyVisibleOK
= true;
249 case XML_ELEMENT(TEXT
, XML_PROTECTION_KEY
):
250 ::comphelper::Base64::decode(aSequence
, aIter
.toString());
253 case XML_ELEMENT(TEXT
, XML_PROTECTED
):
254 // compatibility with SRC629 (or earlier) versions
255 case XML_ELEMENT(TEXT
, XML_PROTECT
):
258 if (::sax::Converter::convertBool(bTmp
, aIter
.toView()))
266 XMLOFF_WARN_UNKNOWN("xmloff", aIter
);
272 void XMLSectionImportContext::endFastElement(sal_Int32
)
274 // get rid of last paragraph
275 // (unless it's the only paragraph in the section)
276 rtl::Reference
<XMLTextImportHelper
> rHelper
= GetImport().GetTextImport();
277 rHelper
->GetCursor()->goRight(1, false);
280 rHelper
->GetCursor()->goLeft(1, true);
281 rHelper
->GetText()->insertString(rHelper
->GetCursorAsRange(),
285 // and delete second marker
286 rHelper
->GetCursor()->goRight(1, true);
287 rHelper
->GetText()->insertString(rHelper
->GetCursorAsRange(),
290 // check for redlines to our endnode
291 rHelper
->RedlineAdjustStartNodeCursor();
294 css::uno::Reference
< css::xml::sax::XFastContextHandler
> XMLSectionImportContext::createFastChildContext(
296 const css::uno::Reference
< css::xml::sax::XFastAttributeList
>& xAttrList
)
298 // section-source (-dde) elements
299 if ( nElement
== XML_ELEMENT(TEXT
, XML_SECTION_SOURCE
) )
301 return new XMLSectionSourceImportContext(GetImport(),
302 xSectionPropertySet
);
304 else if ( nElement
== XML_ELEMENT(OFFICE
, XML_DDE_SOURCE
) )
306 return new XMLSectionSourceDDEImportContext(GetImport(),
307 xSectionPropertySet
);
311 // otherwise: text context
312 auto pContext
= GetImport().GetTextImport()->CreateTextChildContext(
313 GetImport(), nElement
, xAttrList
, XMLTextType::Section
);
315 // if that fails, default context
319 XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement
);
324 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */