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";
72 XML_TOK_SECTION_XMLID
,
73 XML_TOK_SECTION_STYLE_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
},
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
,
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
)
117 , bIsVisible(sal_True
)
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
);
143 UniReference
<XMLTextImportHelper
> rHelper
= GetImport().GetTextImport();
148 // create text section (as XPropertySet)
149 Reference
<XMultiServiceFactory
> xFactory(
150 GetImport().GetModel(),UNO_QUERY
);
153 Reference
<XInterface
> xIfc
=
154 xFactory
->createInstance( bIsIndexHeader
? sIndexHeaderSection
158 Reference
<XPropertySet
> xPropSet(xIfc
, UNO_QUERY
);
160 // save PropertySet (for CreateChildContext)
161 xSectionPropertySet
= xPropSet
;
164 Reference
<XNamed
> xNamed(xPropSet
, UNO_QUERY
);
165 xNamed
->setName(sName
);
168 if (!sStyleName
.isEmpty())
170 XMLPropStyleContext
* pStyle
= rHelper
->
171 FindSectionStyle(sStyleName
);
175 pStyle
->FillPropertySet( xPropSet
);
179 // IsVisible and condition (not for index headers)
180 if (! bIsIndexHeader
)
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
189 if( bIsCurrentlyVisibleOK
)
191 aAny
.setValue( &bIsCurrentlyVisible
,
192 ::getBooleanCppuType() );
193 xPropSet
->setPropertyValue( sIsCurrentlyVisible
, aAny
);
199 xPropSet
->setPropertyValue( sCondition
, aAny
);
203 // password (only for regular sections)
205 IsXMLToken(GetLocalName(), XML_SECTION
) )
209 xPropSet
->setPropertyValue(sProtectionKey
, 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();
223 static const sal_Char sMarker
[] = " ";
225 static const sal_Char sMarker
[] = "X";
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
,
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
++)
269 sal_uInt16 nNamePrefix
= GetImport().GetNamespaceMap().
270 GetKeyByAttrName( xAttrList
->getNameByIndex(nAttr
),
272 OUString sAttr
= xAttrList
->getValueByIndex(nAttr
);
274 switch (aTokenMap
.Get(nNamePrefix
, sLocalName
))
276 case XML_TOK_SECTION_XMLID
:
279 case XML_TOK_SECTION_STYLE_NAME
:
282 case XML_TOK_SECTION_NAME
:
286 case XML_TOK_SECTION_CONDITION
:
289 sal_uInt16 nPrefix
= GetImport().GetNamespaceMap().
290 _GetKeyByAttrName( sAttr
, &sTmp
, sal_False
);
291 if( XML_NAMESPACE_OOOW
== nPrefix
)
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
;
312 case XML_TOK_SECTION_IS_HIDDEN
:
315 if (::sax::Converter::convertBool(bTmp
, sAttr
))
317 bIsCurrentlyVisible
= !bTmp
;
318 bIsCurrentlyVisibleOK
= sal_True
;
322 case XML_TOK_SECTION_PROTECTION_KEY
:
323 ::sax::Converter::decodeBase64(aSequence
, sAttr
);
324 bSequenceOK
= sal_True
;
326 case XML_TOK_SECTION_PROTECT
:
329 if (::sax::Converter::convertBool(bTmp
, sAttr
))
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
);
350 rHelper
->GetCursor()->goLeft(1, sal_True
);
351 rHelper
->GetText()->insertString(rHelper
->GetCursorAsRange(),
355 // and delete second marker
356 rHelper
->GetCursor()->goRight(1, sal_True
);
357 rHelper
->GetText()->insertString(rHelper
->GetCursorAsRange(),
360 // check for redlines to our endnode
361 rHelper
->RedlineAdjustStartNodeCursor(sal_False
);
364 SvXMLImportContext
* XMLSectionImportContext::CreateChildContext(
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(),
377 xSectionPropertySet
);
379 else if ( (XML_NAMESPACE_OFFICE
== nPrefix
) &&
380 IsXMLToken(rLocalName
, XML_DDE_SOURCE
) )
382 pContext
= new XMLSectionSourceDDEImportContext(GetImport(),
384 xSectionPropertySet
);
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
);
400 bHasContent
= sal_True
;
406 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */