Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
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.
15 : : *
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).
21 : : *
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.
26 : : *
27 : : ************************************************************************/
28 : :
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>
46 : :
47 : :
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;
54 : :
55 : : using namespace ::com::sun::star::uno;
56 : : using namespace ::com::sun::star::text;
57 : : using namespace ::xmloff::token;
58 : :
59 : :
60 [ # # ][ # # ]: 0 : TYPEINIT1( XMLSectionImportContext, SvXMLImportContext );
61 : :
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";
69 : :
70 : : enum XMLSectionToken
71 : : {
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
80 : : };
81 : :
82 : : static SvXMLTokenMapEntry aSectionTokenMap[] =
83 : : {
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
95 : : };
96 : :
97 : :
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 : 39 : 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 [ + - ][ + - ]: 39 : , bHasContent(sal_False)
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
123 : : {
124 : 39 : }
125 : :
126 [ + - ]: 39 : XMLSectionImportContext::~XMLSectionImportContext()
127 : : {
128 [ - + ]: 78 : }
129 : :
130 : 39 : void XMLSectionImportContext::StartElement(
131 : : const Reference<XAttributeList> & xAttrList)
132 : : {
133 : : // process attributes
134 [ + - ]: 39 : ProcessAttributes(xAttrList);
135 : :
136 : : // process index headers:
137 [ + - ]: 39 : sal_Bool bIsIndexHeader = IsXMLToken( GetLocalName(), XML_INDEX_TITLE );
138 [ + + ]: 39 : if (bIsIndexHeader)
139 : : {
140 : 28 : bValid = sal_True;
141 : : }
142 : :
143 [ + - ]: 39 : UniReference<XMLTextImportHelper> rHelper = GetImport().GetTextImport();
144 : :
145 : : // valid?
146 [ + - ]: 39 : if (bValid)
147 : : {
148 : : // create text section (as XPropertySet)
149 : : Reference<XMultiServiceFactory> xFactory(
150 [ + - ]: 39 : GetImport().GetModel(),UNO_QUERY);
151 [ + - ]: 39 : if (xFactory.is())
152 : : {
153 : : Reference<XInterface> xIfc =
154 [ + - ]: 39 : xFactory->createInstance( bIsIndexHeader ? sIndexHeaderSection
155 [ + + ][ + - ]: 39 : : sTextSection );
156 [ + - ]: 39 : if (xIfc.is())
157 : : {
158 [ + - ]: 39 : Reference<XPropertySet> xPropSet(xIfc, UNO_QUERY);
159 : :
160 : : // save PropertySet (for CreateChildContext)
161 [ + - ]: 39 : xSectionPropertySet = xPropSet;
162 : :
163 : : // name
164 [ + - ]: 39 : Reference<XNamed> xNamed(xPropSet, UNO_QUERY);
165 [ + - ][ + - ]: 39 : xNamed->setName(sName);
166 : :
167 : : // stylename?
168 [ + - ]: 39 : if (!sStyleName.isEmpty())
169 : : {
170 : : XMLPropStyleContext* pStyle = rHelper->
171 [ + - ][ + - ]: 39 : FindSectionStyle(sStyleName);
172 : :
173 [ + - ]: 39 : if (pStyle != NULL)
174 : : {
175 [ + - ]: 39 : pStyle->FillPropertySet( xPropSet );
176 : : }
177 : : }
178 : :
179 : : // IsVisible and condition (not for index headers)
180 [ + + ]: 39 : if (! bIsIndexHeader)
181 : : {
182 : 11 : Any aAny;
183 [ + - ]: 11 : aAny.setValue( &bIsVisible, ::getBooleanCppuType() );
184 [ + - ][ + - ]: 11 : xPropSet->setPropertyValue( sIsVisible, aAny );
185 : :
186 : : // #97450# hidden sections must be hidden on reload
187 : : // For backwards compatibilty, set flag only if it is
188 : : // present
189 [ - + ]: 11 : if( bIsCurrentlyVisibleOK )
190 : : {
191 : : aAny.setValue( &bIsCurrentlyVisible,
192 [ # # ]: 0 : ::getBooleanCppuType() );
193 [ # # ][ # # ]: 0 : xPropSet->setPropertyValue( sIsCurrentlyVisible, aAny);
194 : : }
195 : :
196 [ + + ]: 11 : if (bCondOK)
197 : : {
198 [ + - ]: 3 : aAny <<= sCond;
199 [ + - ][ + - ]: 3 : xPropSet->setPropertyValue( sCondition, aAny );
200 : 11 : }
201 : : }
202 : :
203 : : // password (only for regular sections)
204 [ + + ][ + - ]: 43 : if ( bSequenceOK &&
[ + + ]
205 [ + - ]: 4 : IsXMLToken(GetLocalName(), XML_SECTION) )
206 : : {
207 : 4 : Any aAny;
208 [ + - ]: 4 : aAny <<= aSequence;
209 [ + - ][ + - ]: 4 : xPropSet->setPropertyValue(sProtectionKey, aAny);
210 : : }
211 : :
212 : : // protection
213 : 39 : Any aAny;
214 [ + - ]: 39 : aAny.setValue( &bProtect, ::getBooleanCppuType() );
215 [ + - ][ + - ]: 39 : xPropSet->setPropertyValue( sIsProtected, aAny );
216 : :
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 [ + - ][ + - ]: 39 : 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 [ + - ]: 39 : OUString sMarkerString(RTL_CONSTASCII_USTRINGPARAM(sMarker));
228 [ + - ][ + - ]: 39 : rHelper->InsertString(sMarkerString);
229 : : rHelper->InsertControlCharacter(
230 [ + - ][ + - ]: 39 : ControlCharacter::APPEND_PARAGRAPH );
231 [ + - ][ + - ]: 39 : rHelper->InsertString(sMarkerString);
232 : :
233 : : // select first marker
234 [ + - ][ + - ]: 39 : rHelper->GetCursor()->gotoRange(xStart, sal_False);
[ + - ][ + - ]
235 [ + - ][ + - ]: 39 : rHelper->GetCursor()->goRight(1, sal_True);
[ + - ][ + - ]
236 : :
237 : : // convert section to XTextContent
238 : : Reference<XTextContent> xTextContent(xSectionPropertySet,
239 [ + - ]: 39 : UNO_QUERY);
240 : :
241 : : // and insert (over marker)
242 [ + - ][ + - ]: 39 : rHelper->GetText()->insertTextContent(
[ + - ]
243 [ + - ][ + - ]: 39 : rHelper->GetCursorAsRange(), xTextContent, sal_True );
[ + - ]
244 : :
245 : : // and delete first marker (in section)
246 [ + - ][ + - ]: 39 : rHelper->GetText()->insertString(
[ + - ]
247 [ + - ][ + - ]: 39 : rHelper->GetCursorAsRange(), sEmpty, sal_True);
[ + - ]
248 : :
249 : : // finally, check for redlines that should start at
250 : : // the section start node
251 [ + - ][ + - ]: 39 : rHelper->RedlineAdjustStartNodeCursor(sal_True); // start ???
252 : :
253 : : // xml:id for RDF metadata
254 [ + - ]: 39 : GetImport().SetXmlId(xIfc, sXmlId);
255 : 39 : }
256 : 39 : }
257 [ + - ]: 39 : }
258 : 39 : }
259 : :
260 : 39 : void XMLSectionImportContext::ProcessAttributes(
261 : : const Reference<XAttributeList> & xAttrList )
262 : : {
263 [ + - ]: 39 : SvXMLTokenMap aTokenMap(aSectionTokenMap);
264 : :
265 [ + - ][ + - ]: 39 : sal_Int16 nLength = xAttrList->getLength();
266 [ + + ]: 167 : for(sal_Int16 nAttr = 0; nAttr < nLength; nAttr++)
267 : : {
268 : 128 : OUString sLocalName;
269 : 128 : sal_uInt16 nNamePrefix = GetImport().GetNamespaceMap().
270 [ + - ]: 128 : GetKeyByAttrName( xAttrList->getNameByIndex(nAttr),
271 [ + - + - ]: 256 : &sLocalName );
272 [ + - ][ + - ]: 128 : OUString sAttr = xAttrList->getValueByIndex(nAttr);
273 : :
274 [ + - ][ + + : 128 : switch (aTokenMap.Get(nNamePrefix, sLocalName))
+ + + - +
+ - ]
275 : : {
276 : : case XML_TOK_SECTION_XMLID:
277 : 36 : sXmlId = sAttr;
278 : 36 : break;
279 : : case XML_TOK_SECTION_STYLE_NAME:
280 : 39 : sStyleName = sAttr;
281 : 39 : break;
282 : : case XML_TOK_SECTION_NAME:
283 : 39 : sName = sAttr;
284 : 39 : bValid = sal_True;
285 : 39 : break;
286 : : case XML_TOK_SECTION_CONDITION:
287 : : {
288 : 3 : OUString sTmp;
289 : 3 : sal_uInt16 nPrefix = GetImport().GetNamespaceMap().
290 [ + - ]: 3 : _GetKeyByAttrName( sAttr, &sTmp, sal_False );
291 [ + - ]: 3 : if( XML_NAMESPACE_OOOW == nPrefix )
292 : : {
293 : 3 : sCond = sTmp;
294 : 3 : bCondOK = sal_True;
295 : : }
296 : : else
297 : 3 : sCond = sAttr;
298 : : }
299 : 3 : break;
300 : : case XML_TOK_SECTION_DISPLAY:
301 [ + - ][ - + ]: 3 : if (IsXMLToken(sAttr, XML_TRUE))
302 : : {
303 : 0 : bIsVisible = sal_True;
304 : : }
305 [ + - ][ + - ]: 6 : else if ( IsXMLToken(sAttr, XML_NONE) ||
[ + - ][ + - ]
306 [ + - ]: 3 : IsXMLToken(sAttr, XML_CONDITION) )
307 : : {
308 : 3 : bIsVisible = sal_False;
309 : : }
310 : : // else: ignore
311 : 3 : break;
312 : : case XML_TOK_SECTION_IS_HIDDEN:
313 : : {
314 : 0 : bool bTmp(false);
315 [ # # ][ # # ]: 0 : if (::sax::Converter::convertBool(bTmp, sAttr))
316 : : {
317 : 0 : bIsCurrentlyVisible = !bTmp;
318 : 0 : bIsCurrentlyVisibleOK = sal_True;
319 : : }
320 : : }
321 : 0 : break;
322 : : case XML_TOK_SECTION_PROTECTION_KEY:
323 [ + - ]: 4 : ::sax::Converter::decodeBase64(aSequence, sAttr);
324 : 4 : bSequenceOK = sal_True;
325 : 4 : break;
326 : : case XML_TOK_SECTION_PROTECT:
327 : : {
328 : 4 : bool bTmp(false);
329 [ + - ][ + - ]: 4 : if (::sax::Converter::convertBool(bTmp, sAttr))
330 : : {
331 : 4 : bProtect = bTmp;
332 : : }
333 : : break;
334 : : }
335 : : default:
336 : : ; // ignore
337 : 0 : break;
338 : : }
339 [ + - ]: 167 : }
340 : 39 : }
341 : :
342 : 39 : void XMLSectionImportContext::EndElement()
343 : : {
344 : : // get rid of last paragraph
345 : : // (unless it's the only paragraph in the section)
346 [ + - ]: 39 : UniReference<XMLTextImportHelper> rHelper = GetImport().GetTextImport();
347 [ + - ][ + - ]: 39 : rHelper->GetCursor()->goRight(1, sal_False);
[ + - ][ + - ]
348 [ + - ]: 39 : if (bHasContent)
349 : : {
350 [ + - ][ + - ]: 39 : rHelper->GetCursor()->goLeft(1, sal_True);
[ + - ][ + - ]
351 [ + - ][ + - ]: 39 : rHelper->GetText()->insertString(rHelper->GetCursorAsRange(),
[ + - ][ + - ]
[ + - ]
352 [ + - ]: 39 : sEmpty, sal_True);
353 : : }
354 : :
355 : : // and delete second marker
356 [ + - ][ + - ]: 39 : rHelper->GetCursor()->goRight(1, sal_True);
[ + - ][ + - ]
357 [ + - ][ + - ]: 39 : rHelper->GetText()->insertString(rHelper->GetCursorAsRange(),
[ + - ][ + - ]
[ + - ]
358 [ + - ]: 39 : sEmpty, sal_True);
359 : :
360 : : // check for redlines to our endnode
361 [ + - ][ + - ]: 39 : rHelper->RedlineAdjustStartNodeCursor(sal_False);
[ + - ]
362 : 39 : }
363 : :
364 : 39 : SvXMLImportContext* XMLSectionImportContext::CreateChildContext(
365 : : sal_uInt16 nPrefix,
366 : : const OUString& rLocalName,
367 : : const Reference<XAttributeList> & xAttrList )
368 : : {
369 : 39 : SvXMLImportContext* pContext = NULL;
370 : :
371 : : // section-source (-dde) elements
372 [ + - - + ]: 78 : if ( (XML_NAMESPACE_TEXT == nPrefix) &&
[ - + ]
373 : 39 : IsXMLToken(rLocalName, XML_SECTION_SOURCE) )
374 : : {
375 : 0 : pContext = new XMLSectionSourceImportContext(GetImport(),
376 : : nPrefix, rLocalName,
377 [ # # ]: 0 : xSectionPropertySet);
378 : : }
379 [ - + # # ]: 39 : else if ( (XML_NAMESPACE_OFFICE == nPrefix) &&
[ - + ]
380 : 0 : IsXMLToken(rLocalName, XML_DDE_SOURCE) )
381 : : {
382 : 0 : pContext = new XMLSectionSourceDDEImportContext(GetImport(),
383 : : nPrefix, rLocalName,
384 [ # # ]: 0 : xSectionPropertySet);
385 : : }
386 : : else
387 : : {
388 : : // otherwise: text context
389 : 39 : pContext = GetImport().GetTextImport()->CreateTextChildContext(
390 : 39 : GetImport(), nPrefix, rLocalName, xAttrList,
391 [ + - ][ + - ]: 39 : XML_TEXT_TYPE_SECTION );
392 : :
393 : : // if that fails, default context
394 [ - + ]: 39 : if (NULL == pContext)
395 : : {
396 : 0 : pContext = new SvXMLImportContext( GetImport(),
397 [ # # ]: 0 : nPrefix, rLocalName );
398 : : }
399 : : else
400 : 39 : bHasContent = sal_True;
401 : : }
402 : :
403 : 39 : return pContext;
404 : : }
405 : :
406 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|