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::XAttributeList
;
45 using ::com::sun::star::xml::sax::XFastAttributeList
;
46 using ::com::sun::star::lang::XMultiServiceFactory
;
47 using ::com::sun::star::container::XNamed
;
49 using namespace ::com::sun::star::uno
;
50 using namespace ::com::sun::star::text
;
51 using namespace ::xmloff::token
;
54 // section import: This one is fairly tricky due to a variety of
55 // limits of the core or the API. The main problem is that if you
56 // insert a section within another section, you can't move the cursor
57 // between the ends of the inner and the enclosing section. To avoid
58 // these problems, additional markers are first inserted and later deleted.
59 XMLSectionImportContext::XMLSectionImportContext( SvXMLImport
& rImport
)
60 : SvXMLImportContext(rImport
)
66 , bIsCurrentlyVisible(true)
67 , bIsCurrentlyVisibleOK(false)
72 XMLSectionImportContext::~XMLSectionImportContext()
76 void XMLSectionImportContext::startFastElement( sal_Int32 nElement
,
77 const css::uno::Reference
< css::xml::sax::XFastAttributeList
>& xAttrList
)
80 ProcessAttributes(xAttrList
);
82 // process index headers:
83 bool bIsIndexHeader
= (nElement
& TOKEN_MASK
) == XML_INDEX_TITLE
;
89 rtl::Reference
<XMLTextImportHelper
> rHelper
= GetImport().GetTextImport();
95 // create text section (as XPropertySet)
96 Reference
<XMultiServiceFactory
> xFactory(
97 GetImport().GetModel(),UNO_QUERY
);
101 Reference
<XInterface
> xIfc
=
102 xFactory
->createInstance( bIsIndexHeader
? OUString("com.sun.star.text.IndexHeaderSection")
103 : OUString("com.sun.star.text.TextSection") );
107 Reference
<XPropertySet
> xPropSet(xIfc
, UNO_QUERY
);
109 // save PropertySet (for CreateChildContext)
110 xSectionPropertySet
= xPropSet
;
113 Reference
<XNamed
> xNamed(xPropSet
, UNO_QUERY
);
114 xNamed
->setName(sName
);
117 if (!sStyleName
.isEmpty())
119 XMLPropStyleContext
* pStyle
= rHelper
->
120 FindSectionStyle(sStyleName
);
122 if (pStyle
!= nullptr)
124 pStyle
->FillPropertySet( xPropSet
);
128 // IsVisible and condition (not for index headers)
129 if (! bIsIndexHeader
)
131 xPropSet
->setPropertyValue( "IsVisible", Any(bIsVisible
) );
133 // #97450# hidden sections must be hidden on reload
134 // For backwards compatibility, set flag only if it is
136 if( bIsCurrentlyVisibleOK
)
138 xPropSet
->setPropertyValue( "IsCurrentlyVisible", Any(bIsCurrentlyVisible
));
143 xPropSet
->setPropertyValue( "Condition", Any(sCond
) );
147 // password (only for regular sections)
149 (nElement
& TOKEN_MASK
) == XML_SECTION
)
151 xPropSet
->setPropertyValue("ProtectionKey", Any(aSequence
));
155 xPropSet
->setPropertyValue( "IsProtected", Any(bProtect
) );
157 // insert marker, <paragraph>, marker; then insert
158 // section over the first marker character, and delete the
159 // last paragraph (and marker) when closing a section.
160 Reference
<XTextRange
> xStart
=
161 rHelper
->GetCursor()->getStart();
163 OUString
sMarkerString(" ");
165 OUString
sMarkerString("X");
167 rHelper
->InsertString(sMarkerString
);
168 rHelper
->InsertControlCharacter(
169 ControlCharacter::APPEND_PARAGRAPH
);
170 rHelper
->InsertString(sMarkerString
);
172 // select first marker
173 rHelper
->GetCursor()->gotoRange(xStart
, false);
174 rHelper
->GetCursor()->goRight(1, true);
176 // convert section to XTextContent
177 Reference
<XTextContent
> xTextContent(xSectionPropertySet
,
180 // and insert (over marker)
181 rHelper
->GetText()->insertTextContent(
182 rHelper
->GetCursorAsRange(), xTextContent
, true );
184 // and delete first marker (in section)
185 rHelper
->GetText()->insertString(
186 rHelper
->GetCursorAsRange(), "", true);
188 // finally, check for redlines that should start at
189 // the section start node
190 rHelper
->RedlineAdjustStartNodeCursor(); // start ???
192 // xml:id for RDF metadata
193 GetImport().SetXmlId(xIfc
, sXmlId
);
196 void XMLSectionImportContext::ProcessAttributes(
197 const Reference
<XFastAttributeList
> & xAttrList
)
199 for( auto& aIter
: sax_fastparser::castToFastAttributeList(xAttrList
) )
201 switch (aIter
.getToken())
203 case XML_ELEMENT(XML
, XML_ID
):
204 sXmlId
= aIter
.toString();
206 case XML_ELEMENT(TEXT
, XML_STYLE_NAME
):
207 sStyleName
= aIter
.toString();
209 case XML_ELEMENT(TEXT
, XML_NAME
):
210 sName
= aIter
.toString();
213 case XML_ELEMENT(TEXT
, XML_CONDITION
):
215 OUString sValue
= aIter
.toString();
217 sal_uInt16 nPrefix
= GetImport().GetNamespaceMap().
218 GetKeyByAttrValueQName(sValue
, &sTmp
);
219 if( XML_NAMESPACE_OOOW
== nPrefix
)
228 case XML_ELEMENT(TEXT
, XML_DISPLAY
):
229 if (IsXMLToken(aIter
, XML_TRUE
))
233 else if ( IsXMLToken(aIter
, XML_NONE
) ||
234 IsXMLToken(aIter
, XML_CONDITION
) )
240 case XML_ELEMENT(TEXT
, XML_IS_HIDDEN
):
243 if (::sax::Converter::convertBool(bTmp
, aIter
.toView()))
245 bIsCurrentlyVisible
= !bTmp
;
246 bIsCurrentlyVisibleOK
= true;
250 case XML_ELEMENT(TEXT
, XML_PROTECTION_KEY
):
251 ::comphelper::Base64::decode(aSequence
, aIter
.toString());
254 case XML_ELEMENT(TEXT
, XML_PROTECTED
):
255 // compatibility with SRC629 (or earlier) versions
256 case XML_ELEMENT(TEXT
, XML_PROTECT
):
259 if (::sax::Converter::convertBool(bTmp
, aIter
.toView()))
267 XMLOFF_WARN_UNKNOWN("xmloff", aIter
);
273 void XMLSectionImportContext::endFastElement(sal_Int32
)
275 // get rid of last paragraph
276 // (unless it's the only paragraph in the section)
277 rtl::Reference
<XMLTextImportHelper
> rHelper
= GetImport().GetTextImport();
278 rHelper
->GetCursor()->goRight(1, false);
281 rHelper
->GetCursor()->goLeft(1, true);
282 rHelper
->GetText()->insertString(rHelper
->GetCursorAsRange(),
286 // and delete second marker
287 rHelper
->GetCursor()->goRight(1, true);
288 rHelper
->GetText()->insertString(rHelper
->GetCursorAsRange(),
291 // check for redlines to our endnode
292 rHelper
->RedlineAdjustStartNodeCursor();
295 css::uno::Reference
< css::xml::sax::XFastContextHandler
> XMLSectionImportContext::createFastChildContext(
297 const css::uno::Reference
< css::xml::sax::XFastAttributeList
>& xAttrList
)
299 // section-source (-dde) elements
300 if ( nElement
== XML_ELEMENT(TEXT
, XML_SECTION_SOURCE
) )
302 return new XMLSectionSourceImportContext(GetImport(),
303 xSectionPropertySet
);
305 else if ( nElement
== XML_ELEMENT(OFFICE
, XML_DDE_SOURCE
) )
307 return new XMLSectionSourceDDEImportContext(GetImport(),
308 xSectionPropertySet
);
312 // otherwise: text context
313 auto pContext
= GetImport().GetTextImport()->CreateTextChildContext(
314 GetImport(), nElement
, xAttrList
, XMLTextType::Section
);
316 // if that fails, default context
320 XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement
);
325 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */