1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_xmloff.hxx"
26 #include "XMLSectionImportContext.hxx"
27 #include "XMLSectionSourceImportContext.hxx"
28 #include "XMLSectionSourceDDEImportContext.hxx"
29 #include <xmloff/xmlictxt.hxx>
30 #include <xmloff/xmlimp.hxx>
31 #include <xmloff/txtimp.hxx>
32 #include <xmloff/nmspmap.hxx>
33 #include "xmloff/xmlnmspe.hxx"
34 #include <xmloff/xmltoken.hxx>
35 #include <xmloff/xmluconv.hxx>
36 #include <xmloff/prstylei.hxx>
37 #include <com/sun/star/container/XNamed.hpp>
38 #include <com/sun/star/uno/Reference.h>
39 #include <com/sun/star/text/XTextContent.hpp>
40 #include <com/sun/star/beans/XPropertySet.hpp>
41 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
42 #include <com/sun/star/text/ControlCharacter.hpp>
43
44
45 using ::rtl::OUString;
46 using ::com::sun::star::beans::XPropertySet;
47 using ::com::sun::star::uno::Reference;
48 using ::com::sun::star::xml::sax::XAttributeList;
49 using ::com::sun::star::lang::XMultiServiceFactory;
50 using ::com::sun::star::container::XNamed;
51
52 using namespace ::com::sun::star::uno;
53 using namespace ::com::sun::star::text;
54 using namespace ::xmloff::token;
55
56
57 TYPEINIT1( XMLSectionImportContext, SvXMLImportContext );
58
59 const sal_Char sAPI_TextSection[] = "com.sun.star.text.TextSection";
60 const sal_Char sAPI_IndexHeaderSection[] = "com.sun.star.text.IndexHeaderSection";
61 const sal_Char sAPI_IsProtected[] = "IsProtected";
62 const sal_Char sAPI_Condition[] = "Condition";
63 const sal_Char sAPI_IsVisible[] = "IsVisible";
64 const sal_Char sAPI_IsCurrentlyVisible[] = "IsCurrentlyVisible";
65 const sal_Char sAPI_ProtectionKey[] = "ProtectionKey";
66
67 enum XMLSectionToken
68 {
69 XML_TOK_SECTION_XMLID,
70 XML_TOK_SECTION_STYLE_NAME,
71 XML_TOK_SECTION_NAME,
72 XML_TOK_SECTION_CONDITION,
73 XML_TOK_SECTION_DISPLAY,
74 XML_TOK_SECTION_PROTECT,
75 XML_TOK_SECTION_PROTECTION_KEY,
76 XML_TOK_SECTION_IS_HIDDEN
77 };
78
79 static __FAR_DATA SvXMLTokenMapEntry aSectionTokenMap[] =
80 {
81 { XML_NAMESPACE_XML , XML_ID, XML_TOK_SECTION_XMLID },
82 { XML_NAMESPACE_TEXT, XML_STYLE_NAME, XML_TOK_SECTION_STYLE_NAME },
83 { XML_NAMESPACE_TEXT, XML_NAME, XML_TOK_SECTION_NAME },
84 { XML_NAMESPACE_TEXT, XML_CONDITION, XML_TOK_SECTION_CONDITION },
85 { XML_NAMESPACE_TEXT, XML_DISPLAY, XML_TOK_SECTION_DISPLAY },
86 { XML_NAMESPACE_TEXT, XML_PROTECTED, XML_TOK_SECTION_PROTECT },
87 { XML_NAMESPACE_TEXT, XML_PROTECTION_KEY, XML_TOK_SECTION_PROTECTION_KEY},
88 { XML_NAMESPACE_TEXT, XML_IS_HIDDEN, XML_TOK_SECTION_IS_HIDDEN },
89 // compatibility with SRC629 (or earlier) versions
90 { XML_NAMESPACE_TEXT, XML_PROTECT, XML_TOK_SECTION_PROTECT },
91 XML_TOKEN_MAP_END
92 };
93
94
95 // section import: This one is fairly tricky due to a variety of
96 // limits of the core or the API. The main problem is that if you
97 // insert a section within another section, you can't move the cursor
98 // between the ends of the inner and the enclosing section. To avoid
99 // these problems, additional markers are first inserted and later deleted.
XMLSectionImportContext(SvXMLImport & rImport,sal_uInt16 nPrfx,const OUString & rLocalName)100 XMLSectionImportContext::XMLSectionImportContext(
101 SvXMLImport& rImport,
102 sal_uInt16 nPrfx,
103 const OUString& rLocalName )
104 : SvXMLImportContext(rImport, nPrfx, rLocalName)
105 , sTextSection(RTL_CONSTASCII_USTRINGPARAM(sAPI_TextSection))
106 , sIndexHeaderSection(RTL_CONSTASCII_USTRINGPARAM(sAPI_IndexHeaderSection))
107 , sCondition(RTL_CONSTASCII_USTRINGPARAM(sAPI_Condition))
108 , sIsVisible(RTL_CONSTASCII_USTRINGPARAM(sAPI_IsVisible))
109 , sProtectionKey(RTL_CONSTASCII_USTRINGPARAM(sAPI_ProtectionKey))
110 , sIsProtected(RTL_CONSTASCII_USTRINGPARAM(sAPI_IsProtected))
111 , sIsCurrentlyVisible(RTL_CONSTASCII_USTRINGPARAM(sAPI_IsCurrentlyVisible))
112 , bProtect(sal_False)
113 , bCondOK(sal_False)
114 , bIsVisible(sal_True)
115 , bValid(sal_False)
116 , bSequenceOK(sal_False)
117 , bIsCurrentlyVisible(sal_True)
118 , bIsCurrentlyVisibleOK(sal_False)
119 , bHasContent(sal_False)
120 {
121 }
122
~XMLSectionImportContext()123 XMLSectionImportContext::~XMLSectionImportContext()
124 {
125 }
126
StartElement(const Reference<XAttributeList> & xAttrList)127 void XMLSectionImportContext::StartElement(
128 const Reference<XAttributeList> & xAttrList)
129 {
130 // process attributes
131 ProcessAttributes(xAttrList);
132
133 // process index headers:
134 sal_Bool bIsIndexHeader = IsXMLToken( GetLocalName(), XML_INDEX_TITLE );
135 if (bIsIndexHeader)
136 {
137 bValid = sal_True;
138 }
139
140 UniReference<XMLTextImportHelper> rHelper = GetImport().GetTextImport();
141
142 // valid?
143 if (bValid)
144 {
145 // create text section (as XPropertySet)
146 Reference<XMultiServiceFactory> xFactory(
147 GetImport().GetModel(),UNO_QUERY);
148 if (xFactory.is())
149 {
150 Reference<XInterface> xIfc =
151 xFactory->createInstance( bIsIndexHeader ? sIndexHeaderSection
152 : sTextSection );
153 if (xIfc.is())
154 {
155 Reference<XPropertySet> xPropSet(xIfc, UNO_QUERY);
156
157 // save PropertySet (for CreateChildContext)
158 xSectionPropertySet = xPropSet;
159
160 // name
161 Reference<XNamed> xNamed(xPropSet, UNO_QUERY);
162 xNamed->setName(sName);
163
164 // stylename?
165 if (sStyleName.getLength() > 0)
166 {
167 XMLPropStyleContext* pStyle = rHelper->
168 FindSectionStyle(sStyleName);
169
170 if (pStyle != NULL)
171 {
172 pStyle->FillPropertySet( xPropSet );
173 }
174 }
175
176 // IsVisible and condition (not for index headers)
177 if (! bIsIndexHeader)
178 {
179 Any aAny;
180 aAny.setValue( &bIsVisible, ::getBooleanCppuType() );
181 xPropSet->setPropertyValue( sIsVisible, aAny );
182
183 // #97450# hidden sections must be hidden on reload
184 // For backwards compatibility, set flag only if it is
185 // present
186 if( bIsCurrentlyVisibleOK )
187 {
188 aAny.setValue( &bIsCurrentlyVisible,
189 ::getBooleanCppuType() );
190 xPropSet->setPropertyValue( sIsCurrentlyVisible, aAny);
191 }
192
193 if (bCondOK)
194 {
195 aAny <<= sCond;
196 xPropSet->setPropertyValue( sCondition, aAny );
197 }
198 }
199
200 // password (only for regular sections)
201 if ( bSequenceOK &&
202 IsXMLToken(GetLocalName(), XML_SECTION) )
203 {
204 Any aAny;
205 aAny <<= aSequence;
206 xPropSet->setPropertyValue(sProtectionKey, aAny);
207 }
208
209 // protection
210 Any aAny;
211 aAny.setValue( &bProtect, ::getBooleanCppuType() );
212 xPropSet->setPropertyValue( sIsProtected, aAny );
213
214 // insert marker, <paragraph>, marker; then insert
215 // section over the first marker character, and delete the
216 // last paragraph (and marker) when closing a section.
217 Reference<XTextRange> xStart =
218 rHelper->GetCursor()->getStart();
219 #ifndef DBG_UTIL
220 static const sal_Char sMarker[] = " ";
221 #else
222 static const sal_Char sMarker[] = "X";
223 #endif
224 OUString sMarkerString(RTL_CONSTASCII_USTRINGPARAM(sMarker));
225 rHelper->InsertString(sMarkerString);
226 rHelper->InsertControlCharacter(
227 ControlCharacter::APPEND_PARAGRAPH );
228 rHelper->InsertString(sMarkerString);
229
230 // select first marker
231 rHelper->GetCursor()->gotoRange(xStart, sal_False);
232 rHelper->GetCursor()->goRight(1, sal_True);
233
234 // convert section to XTextContent
235 Reference<XTextContent> xTextContent(xSectionPropertySet,
236 UNO_QUERY);
237
238 // and insert (over marker)
239 rHelper->GetText()->insertTextContent(
240 rHelper->GetCursorAsRange(), xTextContent, sal_True );
241
242 // and delete first marker (in section)
243 rHelper->GetText()->insertString(
244 rHelper->GetCursorAsRange(), sEmpty, sal_True);
245
246 // finally, check for redlines that should start at
247 // the section start node
248 rHelper->RedlineAdjustStartNodeCursor(sal_True); // start ???
249
250 // xml:id for RDF metadata
251 GetImport().SetXmlId(xIfc, sXmlId);
252 }
253 }
254 }
255 }
256
ProcessAttributes(const Reference<XAttributeList> & xAttrList)257 void XMLSectionImportContext::ProcessAttributes(
258 const Reference<XAttributeList> & xAttrList )
259 {
260 SvXMLTokenMap aTokenMap(aSectionTokenMap);
261
262 sal_Int16 nLength = xAttrList->getLength();
263 for(sal_Int16 nAttr = 0; nAttr < nLength; nAttr++)
264 {
265 OUString sLocalName;
266 sal_uInt16 nNamePrefix = GetImport().GetNamespaceMap().
267 GetKeyByAttrName( xAttrList->getNameByIndex(nAttr),
268 &sLocalName );
269 OUString sAttr = xAttrList->getValueByIndex(nAttr);
270
271 switch (aTokenMap.Get(nNamePrefix, sLocalName))
272 {
273 case XML_TOK_SECTION_XMLID:
274 sXmlId = sAttr;
275 break;
276 case XML_TOK_SECTION_STYLE_NAME:
277 sStyleName = sAttr;
278 break;
279 case XML_TOK_SECTION_NAME:
280 sName = sAttr;
281 bValid = sal_True;
282 break;
283 case XML_TOK_SECTION_CONDITION:
284 {
285 OUString sTmp;
286 sal_uInt16 nPrefix = GetImport().GetNamespaceMap().
287 _GetKeyByAttrName( sAttr, &sTmp, sal_False );
288 if( XML_NAMESPACE_OOOW == nPrefix )
289 {
290 sCond = sTmp;
291 bCondOK = sal_True;
292 }
293 else
294 sCond = sAttr;
295 }
296 break;
297 case XML_TOK_SECTION_DISPLAY:
298 if (IsXMLToken(sAttr, XML_TRUE))
299 {
300 bIsVisible = sal_True;
301 }
302 else if ( IsXMLToken(sAttr, XML_NONE) ||
303 IsXMLToken(sAttr, XML_CONDITION) )
304 {
305 bIsVisible = sal_False;
306 }
307 // else: ignore
308 break;
309 case XML_TOK_SECTION_IS_HIDDEN:
310 {
311 sal_Bool bTmp;
312 if (SvXMLUnitConverter::convertBool(bTmp, sAttr))
313 {
314 bIsCurrentlyVisible = !bTmp;
315 bIsCurrentlyVisibleOK = sal_True;
316 }
317 }
318 break;
319 case XML_TOK_SECTION_PROTECTION_KEY:
320 SvXMLUnitConverter::decodeBase64(aSequence, sAttr);
321 bSequenceOK = sal_True;
322 break;
323 case XML_TOK_SECTION_PROTECT:
324 {
325 sal_Bool bTmp;
326 if (SvXMLUnitConverter::convertBool(bTmp, sAttr))
327 {
328 bProtect = bTmp;
329 }
330 break;
331 }
332 default:
333 ; // ignore
334 break;
335 }
336 }
337 }
338
EndElement()339 void XMLSectionImportContext::EndElement()
340 {
341 // get rid of last paragraph
342 // (unless it's the only paragraph in the section)
343 UniReference<XMLTextImportHelper> rHelper = GetImport().GetTextImport();
344 rHelper->GetCursor()->goRight(1, sal_False);
345 if (bHasContent)
346 {
347 rHelper->GetCursor()->goLeft(1, sal_True);
348 rHelper->GetText()->insertString(rHelper->GetCursorAsRange(),
349 sEmpty, sal_True);
350 }
351
352 // and delete second marker
353 rHelper->GetCursor()->goRight(1, sal_True);
354 rHelper->GetText()->insertString(rHelper->GetCursorAsRange(),
355 sEmpty, sal_True);
356
357 // check for redlines to our endnode
358 rHelper->RedlineAdjustStartNodeCursor(sal_False);
359 }
360
CreateChildContext(sal_uInt16 nPrefix,const OUString & rLocalName,const Reference<XAttributeList> & xAttrList)361 SvXMLImportContext* XMLSectionImportContext::CreateChildContext(
362 sal_uInt16 nPrefix,
363 const OUString& rLocalName,
364 const Reference<XAttributeList> & xAttrList )
365 {
366 SvXMLImportContext* pContext = NULL;
367
368 // section-source (-dde) elements
369 if ( (XML_NAMESPACE_TEXT == nPrefix) &&
370 IsXMLToken(rLocalName, XML_SECTION_SOURCE) )
371 {
372 pContext = new XMLSectionSourceImportContext(GetImport(),
373 nPrefix, rLocalName,
374 xSectionPropertySet);
375 }
376 else if ( (XML_NAMESPACE_OFFICE == nPrefix) &&
377 IsXMLToken(rLocalName, XML_DDE_SOURCE) )
378 {
379 pContext = new XMLSectionSourceDDEImportContext(GetImport(),
380 nPrefix, rLocalName,
381 xSectionPropertySet);
382 }
383 else
384 {
385 // otherwise: text context
386 pContext = GetImport().GetTextImport()->CreateTextChildContext(
387 GetImport(), nPrefix, rLocalName, xAttrList,
388 XML_TEXT_TYPE_SECTION );
389
390 // if that fails, default context
391 if (NULL == pContext)
392 {
393 pContext = new SvXMLImportContext( GetImport(),
394 nPrefix, rLocalName );
395 }
396 else
397 bHasContent = sal_True;
398 }
399
400 return pContext;
401 }
402
403