LibreOffice Module xmloff (master)  1
XMLSectionImportContext.cxx
Go to the documentation of this file.
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 
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>
40 
41 
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;
48 
49 using namespace ::com::sun::star::uno;
50 using namespace ::com::sun::star::text;
51 using namespace ::xmloff::token;
52 
53 
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.
60 : SvXMLImportContext(rImport)
61 , bProtect(false)
62 , bCondOK(false)
63 , bIsVisible(true)
64 , bValid(false)
65 , bSequenceOK(false)
66 , bIsCurrentlyVisible(true)
67 , bIsCurrentlyVisibleOK(false)
68 , bHasContent(false)
69 {
70 }
71 
73 {
74 }
75 
77  const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
78 {
79  // process attributes
80  ProcessAttributes(xAttrList);
81 
82  // process index headers:
83  bool bIsIndexHeader = (nElement & TOKEN_MASK) == XML_INDEX_TITLE;
84  if (bIsIndexHeader)
85  {
86  bValid = true;
87  }
88 
90 
91  // valid?
92  if (!bValid)
93  return;
94 
95  // create text section (as XPropertySet)
96  Reference<XMultiServiceFactory> xFactory(
97  GetImport().GetModel(),UNO_QUERY);
98  if (!xFactory.is())
99  return;
100 
101  Reference<XInterface> xIfc =
102  xFactory->createInstance( bIsIndexHeader ? OUString("com.sun.star.text.IndexHeaderSection")
103  : OUString("com.sun.star.text.TextSection") );
104  if (!xIfc.is())
105  return;
106 
107  Reference<XPropertySet> xPropSet(xIfc, UNO_QUERY);
108 
109  // save PropertySet (for CreateChildContext)
110  xSectionPropertySet = xPropSet;
111 
112  // name
113  Reference<XNamed> xNamed(xPropSet, UNO_QUERY);
114  xNamed->setName(sName);
115 
116  // stylename?
117  if (!sStyleName.isEmpty())
118  {
119  XMLPropStyleContext* pStyle = rHelper->
120  FindSectionStyle(sStyleName);
121 
122  if (pStyle != nullptr)
123  {
124  pStyle->FillPropertySet( xPropSet );
125  }
126  }
127 
128  // IsVisible and condition (not for index headers)
129  if (! bIsIndexHeader)
130  {
131  xPropSet->setPropertyValue( "IsVisible", Any(bIsVisible) );
132 
133  // #97450# hidden sections must be hidden on reload
134  // For backwards compatibility, set flag only if it is
135  // present
137  {
138  xPropSet->setPropertyValue( "IsCurrentlyVisible", Any(bIsCurrentlyVisible));
139  }
140 
141  if (bCondOK)
142  {
143  xPropSet->setPropertyValue( "Condition", Any(sCond) );
144  }
145  }
146 
147  // password (only for regular sections)
148  if ( bSequenceOK &&
149  (nElement & TOKEN_MASK) == XML_SECTION )
150  {
151  xPropSet->setPropertyValue("ProtectionKey", Any(aSequence));
152  }
153 
154  // protection
155  xPropSet->setPropertyValue( "IsProtected", Any(bProtect) );
156 
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();
162 #ifndef DBG_UTIL
163  OUString sMarkerString(" ");
164 #else
165  OUString sMarkerString("X");
166 #endif
167  rHelper->InsertString(sMarkerString);
168  rHelper->InsertControlCharacter(
169  ControlCharacter::APPEND_PARAGRAPH );
170  rHelper->InsertString(sMarkerString);
171 
172  // select first marker
173  rHelper->GetCursor()->gotoRange(xStart, false);
174  rHelper->GetCursor()->goRight(1, true);
175 
176  // convert section to XTextContent
177  Reference<XTextContent> xTextContent(xSectionPropertySet,
178  UNO_QUERY);
179 
180  // and insert (over marker)
181  rHelper->GetText()->insertTextContent(
182  rHelper->GetCursorAsRange(), xTextContent, true );
183 
184  // and delete first marker (in section)
185  rHelper->GetText()->insertString(
186  rHelper->GetCursorAsRange(), "", true);
187 
188  // finally, check for redlines that should start at
189  // the section start node
190  rHelper->RedlineAdjustStartNodeCursor(); // start ???
191 
192  // xml:id for RDF metadata
193  GetImport().SetXmlId(xIfc, sXmlId);
194 }
195 
197  const Reference<XFastAttributeList> & xAttrList )
198 {
199  for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
200  {
201  switch (aIter.getToken())
202  {
203  case XML_ELEMENT(XML, XML_ID):
204  sXmlId = aIter.toString();
205  break;
207  sStyleName = aIter.toString();
208  break;
209  case XML_ELEMENT(TEXT, XML_NAME):
210  sName = aIter.toString();
211  bValid = true;
212  break;
214  {
215  OUString sValue = aIter.toString();
216  OUString sTmp;
217  sal_uInt16 nPrefix = GetImport().GetNamespaceMap().
218  GetKeyByAttrValueQName(sValue, &sTmp);
219  if( XML_NAMESPACE_OOOW == nPrefix )
220  {
221  sCond = sTmp;
222  bCondOK = true;
223  }
224  else
225  sCond = sValue;
226  }
227  break;
229  if (IsXMLToken(aIter, XML_TRUE))
230  {
231  bIsVisible = true;
232  }
233  else if ( IsXMLToken(aIter, XML_NONE) ||
234  IsXMLToken(aIter, XML_CONDITION) )
235  {
236  bIsVisible = false;
237  }
238  // else: ignore
239  break;
241  {
242  bool bTmp(false);
243  if (::sax::Converter::convertBool(bTmp, aIter.toView()))
244  {
245  bIsCurrentlyVisible = !bTmp;
246  bIsCurrentlyVisibleOK = true;
247  }
248  }
249  break;
251  ::comphelper::Base64::decode(aSequence, aIter.toString());
252  bSequenceOK = true;
253  break;
255  // compatibility with SRC629 (or earlier) versions
257  {
258  bool bTmp(false);
259  if (::sax::Converter::convertBool(bTmp, aIter.toView()))
260  {
261  bProtect = bTmp;
262  }
263  break;
264  }
265  default:
266  // ignore
267  XMLOFF_WARN_UNKNOWN("xmloff", aIter);
268  break;
269  }
270  }
271 }
272 
274 {
275  // get rid of last paragraph
276  // (unless it's the only paragraph in the section)
278  rHelper->GetCursor()->goRight(1, false);
279  if (bHasContent)
280  {
281  rHelper->GetCursor()->goLeft(1, true);
282  rHelper->GetText()->insertString(rHelper->GetCursorAsRange(),
283  "", true);
284  }
285 
286  // and delete second marker
287  rHelper->GetCursor()->goRight(1, true);
288  rHelper->GetText()->insertString(rHelper->GetCursorAsRange(),
289  "", true);
290 
291  // check for redlines to our endnode
292  rHelper->RedlineAdjustStartNodeCursor();
293 }
294 
295 css::uno::Reference< css::xml::sax::XFastContextHandler > XMLSectionImportContext::createFastChildContext(
296  sal_Int32 nElement,
297  const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
298 {
299  // section-source (-dde) elements
300  if ( nElement == XML_ELEMENT(TEXT, XML_SECTION_SOURCE) )
301  {
304  }
305  else if ( nElement == XML_ELEMENT(OFFICE, XML_DDE_SOURCE) )
306  {
309  }
310  else
311  {
312  // otherwise: text context
313  auto pContext = GetImport().GetTextImport()->CreateTextChildContext(
314  GetImport(), nElement, xAttrList, XMLTextType::Section );
315 
316  // if that fails, default context
317  if (pContext)
318  bHasContent = true;
319  else
320  XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
321  return pContext;
322  }
323 }
324 
325 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual void SAL_CALL startFastElement(sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList) override
css::uno::Sequence< sal_Int8 > aSequence
SvXMLImport & GetImport()
Definition: xmlictxt.hxx:59
SvXMLNamespaceMap & GetNamespaceMap()
Definition: xmlimp.hxx:398
bool IsXMLToken(std::u16string_view rString, enum XMLTokenEnum eToken)
compare eToken to the string
Definition: xmltoken.cxx:3501
FastAttributeList & castToFastAttributeList(const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList)
rtl::Reference< XMLTextImportHelper > const & GetTextImport()
Definition: xmlimp.hxx:600
#define XMLOFF_WARN_UNKNOWN(area, rIter)
Definition: xmlictxt.hxx:113
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &AttrList) override
virtual void FillPropertySet(const css::uno::Reference< css::beans::XPropertySet > &rPropSet)
Definition: prstylei.cxx:222
static void decode(css::uno::Sequence< sal_Int8 > &aPass, const OUString &sBuffer)
void ProcessAttributes(const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList)
css::uno::Reference< css::beans::XPropertySet > xSectionPropertySet
TextSection (as XPropertySet) for passing down to data source elements.
static bool convertBool(bool &rBool, std::u16string_view rString)
void SetXmlId(css::uno::Reference< css::uno::XInterface > const &i_xIfc, OUString const &i_rXmlId)
set the XmlId attribute of given UNO object (for RDF metadata)
Definition: xmlimp.cxx:1868
This class deliberately does not support XWeak, to improve performance when loading large documents...
Definition: xmlictxt.hxx:44
Handling of tokens in XML:
#define XML_ELEMENT(prefix, name)
Definition: xmlimp.hxx:97
Reference< XSingleServiceFactory > xFactory
constexpr sal_Int32 TOKEN_MASK
Definition: xmlimp.hxx:94
#define XMLOFF_WARN_UNKNOWN_ELEMENT(area, token)
Definition: xmlictxt.hxx:119
constexpr sal_uInt16 XML_NAMESPACE_OOOW
XMLSectionImportContext(SvXMLImport &rImport)
TEXT
virtual void SAL_CALL endFastElement(sal_Int32 nElement) override
endFastElement is called before a context will be destructed, but after an elements context has been ...
virtual ~XMLSectionImportContext() override