Bump for 3.6-28
[LibreOffice.git] / xmloff / source / text / XMLSectionImportContext.cxx
blobf5be934b9ef30895321894b7094ad2a0cc732f57
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include "XMLSectionImportContext.hxx"
30 #include "XMLSectionSourceImportContext.hxx"
31 #include "XMLSectionSourceDDEImportContext.hxx"
32 #include <xmloff/xmlictxt.hxx>
33 #include <xmloff/xmlimp.hxx>
34 #include <xmloff/txtimp.hxx>
35 #include <xmloff/nmspmap.hxx>
36 #include "xmloff/xmlnmspe.hxx"
37 #include <xmloff/xmltoken.hxx>
38 #include <xmloff/prstylei.hxx>
39 #include <sax/tools/converter.hxx>
40 #include <com/sun/star/container/XNamed.hpp>
41 #include <com/sun/star/uno/Reference.h>
42 #include <com/sun/star/text/XTextContent.hpp>
43 #include <com/sun/star/beans/XPropertySet.hpp>
44 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
45 #include <com/sun/star/text/ControlCharacter.hpp>
48 using ::rtl::OUString;
49 using ::com::sun::star::beans::XPropertySet;
50 using ::com::sun::star::uno::Reference;
51 using ::com::sun::star::xml::sax::XAttributeList;
52 using ::com::sun::star::lang::XMultiServiceFactory;
53 using ::com::sun::star::container::XNamed;
55 using namespace ::com::sun::star::uno;
56 using namespace ::com::sun::star::text;
57 using namespace ::xmloff::token;
60 TYPEINIT1( XMLSectionImportContext, SvXMLImportContext );
62 const sal_Char sAPI_TextSection[] = "com.sun.star.text.TextSection";
63 const sal_Char sAPI_IndexHeaderSection[] = "com.sun.star.text.IndexHeaderSection";
64 const sal_Char sAPI_IsProtected[] = "IsProtected";
65 const sal_Char sAPI_Condition[] = "Condition";
66 const sal_Char sAPI_IsVisible[] = "IsVisible";
67 const sal_Char sAPI_IsCurrentlyVisible[] = "IsCurrentlyVisible";
68 const sal_Char sAPI_ProtectionKey[] = "ProtectionKey";
70 enum XMLSectionToken
72 XML_TOK_SECTION_XMLID,
73 XML_TOK_SECTION_STYLE_NAME,
74 XML_TOK_SECTION_NAME,
75 XML_TOK_SECTION_CONDITION,
76 XML_TOK_SECTION_DISPLAY,
77 XML_TOK_SECTION_PROTECT,
78 XML_TOK_SECTION_PROTECTION_KEY,
79 XML_TOK_SECTION_IS_HIDDEN
82 static SvXMLTokenMapEntry aSectionTokenMap[] =
84 { XML_NAMESPACE_XML , XML_ID, XML_TOK_SECTION_XMLID },
85 { XML_NAMESPACE_TEXT, XML_STYLE_NAME, XML_TOK_SECTION_STYLE_NAME },
86 { XML_NAMESPACE_TEXT, XML_NAME, XML_TOK_SECTION_NAME },
87 { XML_NAMESPACE_TEXT, XML_CONDITION, XML_TOK_SECTION_CONDITION },
88 { XML_NAMESPACE_TEXT, XML_DISPLAY, XML_TOK_SECTION_DISPLAY },
89 { XML_NAMESPACE_TEXT, XML_PROTECTED, XML_TOK_SECTION_PROTECT },
90 { XML_NAMESPACE_TEXT, XML_PROTECTION_KEY, XML_TOK_SECTION_PROTECTION_KEY},
91 { XML_NAMESPACE_TEXT, XML_IS_HIDDEN, XML_TOK_SECTION_IS_HIDDEN },
92 // compatibility with SRC629 (or earlier) versions
93 { XML_NAMESPACE_TEXT, XML_PROTECT, XML_TOK_SECTION_PROTECT },
94 XML_TOKEN_MAP_END
98 // section import: This one is fairly tricky due to a variety of
99 // limits of the core or the API. The main problem is that if you
100 // insert a section within another section, you can't move the cursor
101 // between the ends of the inner and the enclosing section. To avoid
102 // these problems, additional markers are first inserted and later deleted.
103 XMLSectionImportContext::XMLSectionImportContext(
104 SvXMLImport& rImport,
105 sal_uInt16 nPrfx,
106 const OUString& rLocalName )
107 : SvXMLImportContext(rImport, nPrfx, rLocalName)
108 , sTextSection(RTL_CONSTASCII_USTRINGPARAM(sAPI_TextSection))
109 , sIndexHeaderSection(RTL_CONSTASCII_USTRINGPARAM(sAPI_IndexHeaderSection))
110 , sCondition(RTL_CONSTASCII_USTRINGPARAM(sAPI_Condition))
111 , sIsVisible(RTL_CONSTASCII_USTRINGPARAM(sAPI_IsVisible))
112 , sProtectionKey(RTL_CONSTASCII_USTRINGPARAM(sAPI_ProtectionKey))
113 , sIsProtected(RTL_CONSTASCII_USTRINGPARAM(sAPI_IsProtected))
114 , sIsCurrentlyVisible(RTL_CONSTASCII_USTRINGPARAM(sAPI_IsCurrentlyVisible))
115 , bProtect(sal_False)
116 , bCondOK(sal_False)
117 , bIsVisible(sal_True)
118 , bValid(sal_False)
119 , bSequenceOK(sal_False)
120 , bIsCurrentlyVisible(sal_True)
121 , bIsCurrentlyVisibleOK(sal_False)
122 , bHasContent(sal_False)
126 XMLSectionImportContext::~XMLSectionImportContext()
130 void XMLSectionImportContext::StartElement(
131 const Reference<XAttributeList> & xAttrList)
133 // process attributes
134 ProcessAttributes(xAttrList);
136 // process index headers:
137 sal_Bool bIsIndexHeader = IsXMLToken( GetLocalName(), XML_INDEX_TITLE );
138 if (bIsIndexHeader)
140 bValid = sal_True;
143 UniReference<XMLTextImportHelper> rHelper = GetImport().GetTextImport();
145 // valid?
146 if (bValid)
148 // create text section (as XPropertySet)
149 Reference<XMultiServiceFactory> xFactory(
150 GetImport().GetModel(),UNO_QUERY);
151 if (xFactory.is())
153 Reference<XInterface> xIfc =
154 xFactory->createInstance( bIsIndexHeader ? sIndexHeaderSection
155 : sTextSection );
156 if (xIfc.is())
158 Reference<XPropertySet> xPropSet(xIfc, UNO_QUERY);
160 // save PropertySet (for CreateChildContext)
161 xSectionPropertySet = xPropSet;
163 // name
164 Reference<XNamed> xNamed(xPropSet, UNO_QUERY);
165 xNamed->setName(sName);
167 // stylename?
168 if (!sStyleName.isEmpty())
170 XMLPropStyleContext* pStyle = rHelper->
171 FindSectionStyle(sStyleName);
173 if (pStyle != NULL)
175 pStyle->FillPropertySet( xPropSet );
179 // IsVisible and condition (not for index headers)
180 if (! bIsIndexHeader)
182 Any aAny;
183 aAny.setValue( &bIsVisible, ::getBooleanCppuType() );
184 xPropSet->setPropertyValue( sIsVisible, aAny );
186 // #97450# hidden sections must be hidden on reload
187 // For backwards compatibilty, set flag only if it is
188 // present
189 if( bIsCurrentlyVisibleOK )
191 aAny.setValue( &bIsCurrentlyVisible,
192 ::getBooleanCppuType() );
193 xPropSet->setPropertyValue( sIsCurrentlyVisible, aAny);
196 if (bCondOK)
198 aAny <<= sCond;
199 xPropSet->setPropertyValue( sCondition, aAny );
203 // password (only for regular sections)
204 if ( bSequenceOK &&
205 IsXMLToken(GetLocalName(), XML_SECTION) )
207 Any aAny;
208 aAny <<= aSequence;
209 xPropSet->setPropertyValue(sProtectionKey, aAny);
212 // protection
213 Any aAny;
214 aAny.setValue( &bProtect, ::getBooleanCppuType() );
215 xPropSet->setPropertyValue( sIsProtected, aAny );
217 // insert marker, <paragraph>, marker; then insert
218 // section over the first marker character, and delete the
219 // last paragraph (and marker) when closing a section.
220 Reference<XTextRange> xStart =
221 rHelper->GetCursor()->getStart();
222 #ifndef DBG_UTIL
223 static const sal_Char sMarker[] = " ";
224 #else
225 static const sal_Char sMarker[] = "X";
226 #endif
227 OUString sMarkerString(RTL_CONSTASCII_USTRINGPARAM(sMarker));
228 rHelper->InsertString(sMarkerString);
229 rHelper->InsertControlCharacter(
230 ControlCharacter::APPEND_PARAGRAPH );
231 rHelper->InsertString(sMarkerString);
233 // select first marker
234 rHelper->GetCursor()->gotoRange(xStart, sal_False);
235 rHelper->GetCursor()->goRight(1, sal_True);
237 // convert section to XTextContent
238 Reference<XTextContent> xTextContent(xSectionPropertySet,
239 UNO_QUERY);
241 // and insert (over marker)
242 rHelper->GetText()->insertTextContent(
243 rHelper->GetCursorAsRange(), xTextContent, sal_True );
245 // and delete first marker (in section)
246 rHelper->GetText()->insertString(
247 rHelper->GetCursorAsRange(), sEmpty, sal_True);
249 // finally, check for redlines that should start at
250 // the section start node
251 rHelper->RedlineAdjustStartNodeCursor(sal_True); // start ???
253 // xml:id for RDF metadata
254 GetImport().SetXmlId(xIfc, sXmlId);
260 void XMLSectionImportContext::ProcessAttributes(
261 const Reference<XAttributeList> & xAttrList )
263 SvXMLTokenMap aTokenMap(aSectionTokenMap);
265 sal_Int16 nLength = xAttrList->getLength();
266 for(sal_Int16 nAttr = 0; nAttr < nLength; nAttr++)
268 OUString sLocalName;
269 sal_uInt16 nNamePrefix = GetImport().GetNamespaceMap().
270 GetKeyByAttrName( xAttrList->getNameByIndex(nAttr),
271 &sLocalName );
272 OUString sAttr = xAttrList->getValueByIndex(nAttr);
274 switch (aTokenMap.Get(nNamePrefix, sLocalName))
276 case XML_TOK_SECTION_XMLID:
277 sXmlId = sAttr;
278 break;
279 case XML_TOK_SECTION_STYLE_NAME:
280 sStyleName = sAttr;
281 break;
282 case XML_TOK_SECTION_NAME:
283 sName = sAttr;
284 bValid = sal_True;
285 break;
286 case XML_TOK_SECTION_CONDITION:
288 OUString sTmp;
289 sal_uInt16 nPrefix = GetImport().GetNamespaceMap().
290 _GetKeyByAttrName( sAttr, &sTmp, sal_False );
291 if( XML_NAMESPACE_OOOW == nPrefix )
293 sCond = sTmp;
294 bCondOK = sal_True;
296 else
297 sCond = sAttr;
299 break;
300 case XML_TOK_SECTION_DISPLAY:
301 if (IsXMLToken(sAttr, XML_TRUE))
303 bIsVisible = sal_True;
305 else if ( IsXMLToken(sAttr, XML_NONE) ||
306 IsXMLToken(sAttr, XML_CONDITION) )
308 bIsVisible = sal_False;
310 // else: ignore
311 break;
312 case XML_TOK_SECTION_IS_HIDDEN:
314 bool bTmp(false);
315 if (::sax::Converter::convertBool(bTmp, sAttr))
317 bIsCurrentlyVisible = !bTmp;
318 bIsCurrentlyVisibleOK = sal_True;
321 break;
322 case XML_TOK_SECTION_PROTECTION_KEY:
323 ::sax::Converter::decodeBase64(aSequence, sAttr);
324 bSequenceOK = sal_True;
325 break;
326 case XML_TOK_SECTION_PROTECT:
328 bool bTmp(false);
329 if (::sax::Converter::convertBool(bTmp, sAttr))
331 bProtect = bTmp;
333 break;
335 default:
336 ; // ignore
337 break;
342 void XMLSectionImportContext::EndElement()
344 // get rid of last paragraph
345 // (unless it's the only paragraph in the section)
346 UniReference<XMLTextImportHelper> rHelper = GetImport().GetTextImport();
347 rHelper->GetCursor()->goRight(1, sal_False);
348 if (bHasContent)
350 rHelper->GetCursor()->goLeft(1, sal_True);
351 rHelper->GetText()->insertString(rHelper->GetCursorAsRange(),
352 sEmpty, sal_True);
355 // and delete second marker
356 rHelper->GetCursor()->goRight(1, sal_True);
357 rHelper->GetText()->insertString(rHelper->GetCursorAsRange(),
358 sEmpty, sal_True);
360 // check for redlines to our endnode
361 rHelper->RedlineAdjustStartNodeCursor(sal_False);
364 SvXMLImportContext* XMLSectionImportContext::CreateChildContext(
365 sal_uInt16 nPrefix,
366 const OUString& rLocalName,
367 const Reference<XAttributeList> & xAttrList )
369 SvXMLImportContext* pContext = NULL;
371 // section-source (-dde) elements
372 if ( (XML_NAMESPACE_TEXT == nPrefix) &&
373 IsXMLToken(rLocalName, XML_SECTION_SOURCE) )
375 pContext = new XMLSectionSourceImportContext(GetImport(),
376 nPrefix, rLocalName,
377 xSectionPropertySet);
379 else if ( (XML_NAMESPACE_OFFICE == nPrefix) &&
380 IsXMLToken(rLocalName, XML_DDE_SOURCE) )
382 pContext = new XMLSectionSourceDDEImportContext(GetImport(),
383 nPrefix, rLocalName,
384 xSectionPropertySet);
386 else
388 // otherwise: text context
389 pContext = GetImport().GetTextImport()->CreateTextChildContext(
390 GetImport(), nPrefix, rLocalName, xAttrList,
391 XML_TEXT_TYPE_SECTION );
393 // if that fails, default context
394 if (NULL == pContext)
396 pContext = new SvXMLImportContext( GetImport(),
397 nPrefix, rLocalName );
399 else
400 bHasContent = sal_True;
403 return pContext;
406 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */