Line data Source code
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 :
20 : #include <rtl/ref.hxx>
21 : #include <rtl/ustrbuf.hxx>
22 : #include <osl/diagnose.h>
23 : #include <com/sun/star/i18n/CharacterClassification.hpp>
24 : #include <com/sun/star/i18n/UnicodeType.hpp>
25 : #include <com/sun/star/util/MeasureUnit.hpp>
26 : #include <sax/tools/converter.hxx>
27 : #include <comphelper/processfactory.hxx>
28 : #include <xmloff/nmspmap.hxx>
29 : #include <xmloff/xmlnmspe.hxx>
30 : #include "IgnoreTContext.hxx"
31 : #include "RenameElemTContext.hxx"
32 : #include "ProcAttrTContext.hxx"
33 : #include "ProcAddAttrTContext.hxx"
34 : #include "MergeElemTContext.hxx"
35 : #include "CreateElemTContext.hxx"
36 : #include "MutableAttrList.hxx"
37 : #include "TransformerActions.hxx"
38 : #include "ElemTransformerAction.hxx"
39 : #include "PropertyActionsOOo.hxx"
40 : #include "TransformerTokenMap.hxx"
41 :
42 : #include "TransformerBase.hxx"
43 : #include "TContextVector.hxx"
44 :
45 : using namespace ::osl;
46 : using namespace ::xmloff::token;
47 : using namespace ::com::sun::star;
48 : using namespace ::com::sun::star::uno;
49 : using namespace ::com::sun::star::beans;
50 : using namespace ::com::sun::star::lang;
51 : using namespace ::com::sun::star::i18n;
52 : using namespace ::com::sun::star::xml::sax;
53 :
54 : namespace
55 : {
56 6 : bool lcl_ConvertAttr( OUString & rOutAttribute, sal_Int32 nParam )
57 : {
58 6 : bool bResult = false;
59 : enum XMLTokenEnum eTokenToRename =
60 6 : static_cast< enum XMLTokenEnum >( nParam & 0xffff );
61 12 : if( eTokenToRename != XML_TOKEN_INVALID &&
62 6 : IsXMLToken( rOutAttribute, eTokenToRename ))
63 : {
64 : enum XMLTokenEnum eReplacementToken =
65 3 : static_cast< enum XMLTokenEnum >( nParam >> 16 );
66 3 : rOutAttribute = GetXMLToken( eReplacementToken );
67 3 : bResult = true;
68 : }
69 6 : return bResult;
70 : }
71 : } // anonymous namespace
72 :
73 8663 : XMLTransformerContext *XMLTransformerBase::CreateContext( sal_uInt16 nPrefix,
74 : const OUString& rLocalName, const OUString& rQName )
75 : {
76 8663 : XMLTransformerActions::key_type aKey( nPrefix, rLocalName );
77 : XMLTransformerActions::const_iterator aIter =
78 8663 : GetElemActions().find( aKey );
79 :
80 8663 : if( !(aIter == GetElemActions().end()) )
81 : {
82 3585 : sal_uInt32 nActionType = (*aIter).second.m_nActionType;
83 3585 : if( (nActionType & XML_ETACTION_USER_DEFINED) != 0 )
84 : {
85 : XMLTransformerContext *pContext =
86 1297 : CreateUserDefinedContext( (*aIter).second,
87 2594 : rQName );
88 : OSL_ENSURE( pContext && !pContext->IsPersistent(),
89 : "unknown or not persistent action" );
90 1297 : return pContext;
91 : }
92 :
93 2288 : switch( nActionType )
94 : {
95 : case XML_ETACTION_COPY_CONTENT:
96 : return new XMLIgnoreTransformerContext( *this, rQName, false,
97 4 : false );
98 : case XML_ETACTION_COPY:
99 0 : return new XMLTransformerContext( *this, rQName );
100 : case XML_ETACTION_RENAME_ELEM:
101 : return new XMLRenameElemTransformerContext( *this, rQName,
102 55 : (*aIter).second.GetQNamePrefixFromParam1(),
103 55 : (*aIter).second.GetQNameTokenFromParam1() );
104 : case XML_ETACTION_RENAME_ELEM_ADD_ATTR:
105 : return new XMLRenameElemTransformerContext( *this, rQName,
106 2 : (*aIter).second.GetQNamePrefixFromParam1(),
107 2 : (*aIter).second.GetQNameTokenFromParam1(),
108 2 : (*aIter).second.GetQNamePrefixFromParam2(),
109 2 : (*aIter).second.GetQNameTokenFromParam2(),
110 8 : static_cast< XMLTokenEnum >( (*aIter).second.m_nParam3 ) );
111 : case XML_ETACTION_RENAME_ELEM_PROC_ATTRS:
112 : return new XMLProcAttrTransformerContext( *this, rQName,
113 113 : (*aIter).second.GetQNamePrefixFromParam1(),
114 113 : (*aIter).second.GetQNameTokenFromParam1(),
115 226 : static_cast< sal_uInt16 >( (*aIter).second.m_nParam2 ) );
116 : case XML_ETACTION_RENAME_ELEM_ADD_PROC_ATTR:
117 : return new XMLProcAddAttrTransformerContext( *this, rQName,
118 10 : (*aIter).second.GetQNamePrefixFromParam1(),
119 10 : (*aIter).second.GetQNameTokenFromParam1(),
120 : static_cast< sal_uInt16 >(
121 10 : (*aIter).second.m_nParam3 >> 16 ),
122 10 : (*aIter).second.GetQNamePrefixFromParam2(),
123 10 : (*aIter).second.GetQNameTokenFromParam2(),
124 : static_cast< XMLTokenEnum >(
125 50 : (*aIter).second.m_nParam3 & 0xffff ) );
126 : case XML_ETACTION_RENAME_ELEM_COND:
127 : {
128 0 : const XMLTransformerContext *pCurrent = GetCurrentContext();
129 0 : if( pCurrent->HasQName(
130 0 : (*aIter).second.GetQNamePrefixFromParam2(),
131 0 : (*aIter).second.GetQNameTokenFromParam2() ) )
132 : return new XMLRenameElemTransformerContext( *this, rQName,
133 0 : (*aIter).second.GetQNamePrefixFromParam1(),
134 0 : (*aIter).second.GetQNameTokenFromParam1() );
135 : }
136 0 : break;
137 : case XML_ETACTION_RENAME_ELEM_PROC_ATTRS_COND:
138 : {
139 10 : const XMLTransformerContext *pCurrent = GetCurrentContext();
140 10 : if( pCurrent->HasQName(
141 10 : (*aIter).second.GetQNamePrefixFromParam3(),
142 20 : (*aIter).second.GetQNameTokenFromParam3() ) )
143 : return new XMLProcAttrTransformerContext( *this, rQName,
144 10 : (*aIter).second.GetQNamePrefixFromParam1(),
145 10 : (*aIter).second.GetQNameTokenFromParam1(),
146 20 : static_cast< sal_uInt16 >( (*aIter).second.m_nParam2 ) );
147 : else
148 : return new XMLProcAttrTransformerContext( *this, rQName,
149 0 : static_cast< sal_uInt16 >( (*aIter).second.m_nParam2 ) );
150 : }
151 : case XML_ETACTION_PROC_ATTRS:
152 : return new XMLProcAttrTransformerContext( *this, rQName,
153 2073 : static_cast< sal_uInt16 >( (*aIter).second.m_nParam1 ) );
154 : case XML_ETACTION_PROC_ATTRS_COND:
155 : {
156 16 : const XMLTransformerContext *pCurrent = GetCurrentContext();
157 16 : if( pCurrent->HasQName(
158 16 : (*aIter).second.GetQNamePrefixFromParam1(),
159 32 : (*aIter).second.GetQNameTokenFromParam1() ) )
160 : return new XMLProcAttrTransformerContext( *this, rQName,
161 16 : static_cast< sal_uInt16 >( (*aIter).second.m_nParam2 ) );
162 : }
163 0 : break;
164 : case XML_ETACTION_MOVE_ATTRS_TO_ELEMS:
165 : return new XMLCreateElemTransformerContext( *this, rQName,
166 5 : static_cast< sal_uInt16 >( (*aIter).second.m_nParam1 ) );
167 : case XML_ETACTION_MOVE_ELEMS_TO_ATTRS:
168 : return new XMLMergeElemTransformerContext( *this, rQName,
169 0 : static_cast< sal_uInt16 >( (*aIter).second.m_nParam1 ) );
170 : default:
171 : OSL_ENSURE( false, "unknown action" );
172 0 : break;
173 : }
174 : }
175 :
176 : // default is copying
177 5078 : return new XMLTransformerContext( *this, rQName );
178 : }
179 :
180 0 : XMLTransformerActions *XMLTransformerBase::GetUserDefinedActions( sal_uInt16 )
181 : {
182 0 : return 0;
183 : }
184 :
185 157 : XMLTransformerBase::XMLTransformerBase( XMLTransformerActionInit *pInit,
186 : ::xmloff::token::XMLTokenEnum *pTKMapInit )
187 : throw () :
188 157 : m_pNamespaceMap( new SvXMLNamespaceMap ),
189 157 : m_pReplaceNamespaceMap( new SvXMLNamespaceMap ),
190 157 : m_pContexts( new XMLTransformerContextVector ),
191 157 : m_pElemActions( new XMLTransformerActions( pInit ) ),
192 785 : m_pTokenMap( new XMLTransformerTokenMap( pTKMapInit ) )
193 : {
194 157 : GetNamespaceMap().Add( GetXMLToken(XML_NP_XLINK), GetXMLToken(XML_N_XLINK), XML_NAMESPACE_XLINK );
195 157 : GetNamespaceMap().Add( GetXMLToken(XML_NP_DC), GetXMLToken(XML_N_DC), XML_NAMESPACE_DC );
196 157 : GetNamespaceMap().Add( GetXMLToken(XML_NP_MATH), GetXMLToken(XML_N_MATH), XML_NAMESPACE_MATH );
197 157 : GetNamespaceMap().Add( GetXMLToken(XML_NP_OOO), GetXMLToken(XML_N_OOO), XML_NAMESPACE_OOO );
198 157 : GetNamespaceMap().Add( GetXMLToken(XML_NP_DOM), GetXMLToken(XML_N_DOM), XML_NAMESPACE_DOM );
199 157 : GetNamespaceMap().Add( GetXMLToken(XML_NP_OOOW), GetXMLToken(XML_N_OOOW), XML_NAMESPACE_OOOW );
200 157 : GetNamespaceMap().Add( GetXMLToken(XML_NP_OOOC), GetXMLToken(XML_N_OOOC), XML_NAMESPACE_OOOC );
201 157 : }
202 :
203 314 : XMLTransformerBase::~XMLTransformerBase() throw ()
204 : {
205 157 : delete m_pNamespaceMap;
206 157 : delete m_pReplaceNamespaceMap;
207 157 : delete m_pContexts;
208 157 : delete m_pElemActions;
209 157 : delete m_pTokenMap;
210 157 : }
211 :
212 51 : void SAL_CALL XMLTransformerBase::startDocument()
213 : throw( SAXException, RuntimeException, std::exception )
214 : {
215 51 : m_xHandler->startDocument();
216 51 : }
217 :
218 50 : void SAL_CALL XMLTransformerBase::endDocument()
219 : throw( SAXException, RuntimeException, std::exception)
220 : {
221 50 : m_xHandler->endDocument();
222 50 : }
223 :
224 9801 : void SAL_CALL XMLTransformerBase::startElement( const OUString& rName,
225 : const Reference< XAttributeList >& rAttrList )
226 : throw(SAXException, RuntimeException, std::exception)
227 : {
228 9801 : SvXMLNamespaceMap *pRewindMap = 0;
229 :
230 9801 : bool bRect = rName == "presentation:show-shape";
231 : (void)bRect;
232 :
233 : // Process namespace attributes. This must happen before creating the
234 : // context, because namespace decaration apply to the element name itself.
235 9801 : XMLMutableAttributeList *pMutableAttrList = 0;
236 9801 : Reference< XAttributeList > xAttrList( rAttrList );
237 9801 : sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
238 26044 : for( sal_Int16 i=0; i < nAttrCount; i++ )
239 : {
240 16243 : const OUString& rAttrName = xAttrList->getNameByIndex( i );
241 48729 : if( ( rAttrName.getLength() >= 5 ) &&
242 17351 : ( rAttrName.startsWith( GetXMLToken(XML_XMLNS) ) ) &&
243 1108 : ( rAttrName.getLength() == 5 || ':' == rAttrName[5] ) )
244 : {
245 554 : if( !pRewindMap )
246 : {
247 53 : pRewindMap = m_pNamespaceMap;
248 53 : m_pNamespaceMap = new SvXMLNamespaceMap( *m_pNamespaceMap );
249 : }
250 554 : const OUString& rAttrValue = xAttrList->getValueByIndex( i );
251 :
252 554 : OUString aPrefix( ( rAttrName.getLength() == 5 )
253 : ? OUString()
254 1108 : : rAttrName.copy( 6 ) );
255 : // Add namespace, but only if it is known.
256 554 : sal_uInt16 nKey = m_pNamespaceMap->AddIfKnown( aPrefix, rAttrValue );
257 : // If namespace is unknown, try to match a name with similar
258 : // TC Id an version
259 554 : if( XML_NAMESPACE_UNKNOWN == nKey )
260 : {
261 63 : OUString aTestName( rAttrValue );
262 63 : if( SvXMLNamespaceMap::NormalizeOasisURN( aTestName ) )
263 7 : nKey = m_pNamespaceMap->AddIfKnown( aPrefix, aTestName );
264 : }
265 : // If that namespace is not known, too, add it as unknown
266 554 : if( XML_NAMESPACE_UNKNOWN == nKey )
267 63 : nKey = m_pNamespaceMap->Add( aPrefix, rAttrValue );
268 :
269 554 : const OUString& rRepName = m_pReplaceNamespaceMap->GetNameByKey( nKey );
270 554 : if( !rRepName.isEmpty() )
271 : {
272 373 : if( !pMutableAttrList )
273 : {
274 48 : pMutableAttrList = new XMLMutableAttributeList( xAttrList );
275 48 : xAttrList = pMutableAttrList;
276 : }
277 :
278 373 : pMutableAttrList->SetValueByIndex( i, rRepName );
279 554 : }
280 : }
281 16243 : }
282 :
283 : // Get element's namespace and local name.
284 19602 : OUString aLocalName;
285 : sal_uInt16 nPrefix =
286 9801 : m_pNamespaceMap->GetKeyByAttrName( rName, &aLocalName );
287 :
288 : // If there are contexts already, call a CreateChildContext at the topmost
289 : // context. Otherwise, create a default context.
290 19602 : ::rtl::Reference < XMLTransformerContext > xContext;
291 9801 : if( !m_pContexts->empty() )
292 : {
293 19502 : xContext = m_pContexts->back()->CreateChildContext( nPrefix,
294 : aLocalName,
295 : rName,
296 19502 : xAttrList );
297 : }
298 : else
299 : {
300 50 : xContext = CreateContext( nPrefix, aLocalName, rName );
301 : }
302 :
303 : OSL_ENSURE( xContext.is(), "XMLTransformerBase::startElement: missing context" );
304 9801 : if( !xContext.is() )
305 0 : xContext = new XMLTransformerContext( *this, rName );
306 :
307 : // Remember old namespace map.
308 9801 : if( pRewindMap )
309 53 : xContext->SetRewindMap( pRewindMap );
310 :
311 : // Push context on stack.
312 9801 : m_pContexts->push_back( xContext );
313 :
314 : // Call a startElement at the new context.
315 19602 : xContext->StartElement( xAttrList );
316 9801 : }
317 :
318 9801 : void SAL_CALL XMLTransformerBase::endElement( const OUString&
319 : #if OSL_DEBUG_LEVEL > 0
320 : rName
321 : #endif
322 : )
323 : throw(SAXException, RuntimeException, std::exception)
324 : {
325 9801 : if( !m_pContexts->empty() )
326 : {
327 : // Get topmost context
328 9801 : ::rtl::Reference< XMLTransformerContext > xContext = m_pContexts->back();
329 :
330 : #if OSL_DEBUG_LEVEL > 0
331 : OSL_ENSURE( xContext->GetQName() == rName,
332 : "XMLTransformerBase::endElement: popped context has wrong lname" );
333 : #endif
334 :
335 : // Call a EndElement at the current context.
336 9801 : xContext->EndElement();
337 :
338 : // and remove it from the stack.
339 9801 : m_pContexts->pop_back();
340 :
341 : // Get a namespace map to rewind.
342 9801 : SvXMLNamespaceMap *pRewindMap = xContext->GetRewindMap();
343 :
344 : // Delete the current context.
345 9801 : xContext = 0;
346 :
347 : // Rewind a namespace map.
348 9801 : if( pRewindMap )
349 : {
350 53 : delete m_pNamespaceMap;
351 53 : m_pNamespaceMap = pRewindMap;
352 9801 : }
353 : }
354 9801 : }
355 :
356 22800 : void SAL_CALL XMLTransformerBase::characters( const OUString& rChars )
357 : throw(SAXException, RuntimeException, std::exception)
358 : {
359 22800 : if( !m_pContexts->empty() )
360 : {
361 22725 : m_pContexts->back()->Characters( rChars );
362 : }
363 22800 : }
364 :
365 14 : void SAL_CALL XMLTransformerBase::ignorableWhitespace( const OUString& rWhitespaces )
366 : throw(SAXException, RuntimeException, std::exception)
367 : {
368 14 : m_xHandler->ignorableWhitespace( rWhitespaces );
369 14 : }
370 :
371 0 : void SAL_CALL XMLTransformerBase::processingInstruction( const OUString& rTarget,
372 : const OUString& rData )
373 : throw(SAXException, RuntimeException, std::exception)
374 : {
375 0 : m_xHandler->processingInstruction( rTarget, rData );
376 0 : }
377 :
378 45 : void SAL_CALL XMLTransformerBase::setDocumentLocator( const Reference< XLocator >& rLocator )
379 : throw(SAXException, RuntimeException, std::exception)
380 : {
381 45 : m_xLocator = rLocator;
382 45 : }
383 :
384 : // XExtendedDocumentHandler
385 0 : void SAL_CALL XMLTransformerBase::startCDATA() throw(SAXException, RuntimeException, std::exception)
386 : {
387 0 : if( m_xExtHandler.is() )
388 0 : m_xExtHandler->startCDATA();
389 0 : }
390 :
391 0 : void SAL_CALL XMLTransformerBase::endCDATA() throw(RuntimeException, std::exception)
392 : {
393 0 : if( m_xExtHandler.is() )
394 0 : m_xExtHandler->endCDATA();
395 0 : }
396 :
397 14 : void SAL_CALL XMLTransformerBase::comment( const OUString& rComment )
398 : throw(SAXException, RuntimeException, std::exception)
399 : {
400 14 : if( m_xExtHandler.is() )
401 0 : m_xExtHandler->comment( rComment );
402 14 : }
403 :
404 0 : void SAL_CALL XMLTransformerBase::allowLineBreak()
405 : throw(SAXException, RuntimeException, std::exception)
406 : {
407 0 : if( m_xExtHandler.is() )
408 0 : m_xExtHandler->allowLineBreak();
409 0 : }
410 :
411 399 : void SAL_CALL XMLTransformerBase::unknown( const OUString& rString )
412 : throw(SAXException, RuntimeException, std::exception)
413 : {
414 399 : if( m_xExtHandler.is() )
415 0 : m_xExtHandler->unknown( rString );
416 399 : }
417 :
418 : // XInitialize
419 75 : void SAL_CALL XMLTransformerBase::initialize( const Sequence< Any >& aArguments )
420 : throw(Exception, RuntimeException, std::exception)
421 : {
422 75 : const sal_Int32 nAnyCount = aArguments.getLength();
423 75 : const Any* pAny = aArguments.getConstArray();
424 :
425 293 : for( sal_Int32 nIndex = 0; nIndex < nAnyCount; nIndex++, pAny++ )
426 : {
427 : // use isAssignableFrom instead of comparing the types to
428 : // allow XExtendedDocumentHandler instead of XDocumentHandler (used in
429 : // writeOasis2OOoLibraryElement in sfx2).
430 : // The Any shift operator can't be used to query the type because it
431 : // uses queryInterface, and the model also has a XPropertySet interface.
432 :
433 : // document handler
434 218 : if( cppu::UnoType<XDocumentHandler>::get().isAssignableFrom( pAny->getValueType() ) )
435 75 : m_xHandler.set( *pAny, UNO_QUERY );
436 :
437 : // property set to transport data across
438 218 : if( cppu::UnoType<XPropertySet>::get().isAssignableFrom( pAny->getValueType() ) )
439 47 : m_xPropSet.set( *pAny, UNO_QUERY );
440 :
441 : // xmodel
442 218 : if( cppu::UnoType<com::sun::star::frame::XModel>::get().isAssignableFrom( pAny->getValueType() ) )
443 4 : mxModel.set( *pAny, UNO_QUERY );
444 : }
445 :
446 75 : if( m_xPropSet.is() )
447 : {
448 47 : Any aAny;
449 94 : OUString sRelPath, sName;
450 : Reference< XPropertySetInfo > xPropSetInfo =
451 94 : m_xPropSet->getPropertySetInfo();
452 94 : OUString sPropName( "StreamRelPath" );
453 47 : if( xPropSetInfo->hasPropertyByName(sPropName) )
454 : {
455 43 : aAny = m_xPropSet->getPropertyValue(sPropName);
456 43 : aAny >>= sRelPath;
457 : }
458 47 : sPropName = "StreamName";
459 47 : if( xPropSetInfo->hasPropertyByName(sPropName) )
460 : {
461 43 : aAny = m_xPropSet->getPropertyValue(sPropName);
462 43 : aAny >>= sName;
463 : }
464 47 : if( !sName.isEmpty() )
465 : {
466 43 : m_aExtPathPrefix = "../";
467 :
468 : // If there is a rel path within a package, then append
469 : // additional '../'. If the rel path contains an ':', then it is
470 : // an absolute URI (or invalid URI, because zip files don't
471 : // permit ':'), and it will be ignored.
472 43 : if( !sRelPath.isEmpty() )
473 : {
474 0 : sal_Int32 nColPos = sRelPath.indexOf( ':' );
475 : OSL_ENSURE( -1 == nColPos,
476 : "StreamRelPath contains ':', absolute URI?" );
477 :
478 0 : if( -1 == nColPos )
479 : {
480 0 : OUString sTmp = m_aExtPathPrefix;
481 0 : sal_Int32 nPos = 0;
482 0 : do
483 : {
484 0 : m_aExtPathPrefix += sTmp;
485 0 : nPos = sRelPath.indexOf( '/', nPos + 1 );
486 : }
487 0 : while( -1 != nPos );
488 : }
489 : }
490 :
491 47 : }
492 : }
493 :
494 : assert(m_xHandler.is()); // can't do anything without that
495 75 : }
496 :
497 104 : static sal_Int16 lcl_getUnit( const OUString& rValue )
498 : {
499 104 : if( rValue.endsWithIgnoreAsciiCase( "cm" ) )
500 102 : return util::MeasureUnit::CM;
501 2 : else if ( rValue.endsWithIgnoreAsciiCase( "mm" ) )
502 0 : return util::MeasureUnit::MM;
503 : else
504 2 : return util::MeasureUnit::INCH;
505 : }
506 :
507 2323 : XMLMutableAttributeList *XMLTransformerBase::ProcessAttrList(
508 : Reference< XAttributeList >& rAttrList, sal_uInt16 nActionMap,
509 : bool bClone )
510 : {
511 2323 : XMLMutableAttributeList *pMutableAttrList = 0;
512 2323 : XMLTransformerActions *pActions = GetUserDefinedActions( nActionMap );
513 : OSL_ENSURE( pActions, "go no actions" );
514 2323 : if( pActions )
515 : {
516 2323 : sal_Int16 nAttrCount = rAttrList.is() ? rAttrList->getLength() : 0;
517 5683 : for( sal_Int16 i=0; i < nAttrCount; ++i )
518 : {
519 3360 : const OUString& rAttrName = rAttrList->getNameByIndex( i );
520 6720 : const OUString& rAttrValue = rAttrList->getValueByIndex( i );
521 6720 : OUString aLocalName;
522 3360 : sal_uInt16 nPrefix = GetNamespaceMap().GetKeyByAttrName( rAttrName,
523 3360 : &aLocalName );
524 :
525 6720 : XMLTransformerActions::key_type aKey( nPrefix, aLocalName );
526 : XMLTransformerActions::const_iterator aIter =
527 3360 : pActions->find( aKey );
528 3360 : if( !(aIter == pActions->end() ) )
529 : {
530 2407 : if( !pMutableAttrList )
531 : {
532 : pMutableAttrList = new XMLMutableAttributeList( rAttrList,
533 1766 : bClone );
534 1766 : rAttrList = pMutableAttrList;
535 : }
536 :
537 2407 : sal_uInt32 nAction = (*aIter).second.m_nActionType;
538 2407 : bool bRename = false;
539 2407 : switch( nAction )
540 : {
541 : case XML_ATACTION_RENAME:
542 418 : bRename = true;
543 418 : break;
544 : case XML_ATACTION_COPY:
545 0 : break;
546 : case XML_ATACTION_REMOVE:
547 : case XML_ATACTION_STYLE_DISPLAY_NAME:
548 0 : pMutableAttrList->RemoveAttributeByIndex( i );
549 0 : --i;
550 0 : --nAttrCount;
551 0 : break;
552 : case XML_ATACTION_RENAME_IN2INCH:
553 0 : bRename = true;
554 : case XML_ATACTION_IN2INCH:
555 : {
556 10 : OUString aAttrValue( rAttrValue );
557 10 : if( ReplaceSingleInWithInch( aAttrValue ) )
558 10 : pMutableAttrList->SetValueByIndex( i, aAttrValue );
559 : }
560 10 : break;
561 : case XML_ATACTION_INS2INCHS:
562 : {
563 0 : OUString aAttrValue( rAttrValue );
564 0 : if( ReplaceInWithInch( aAttrValue ) )
565 0 : pMutableAttrList->SetValueByIndex( i, aAttrValue );
566 : }
567 0 : break;
568 : case XML_ATACTION_RENAME_INCH2IN:
569 8 : bRename = true;
570 : case XML_ATACTION_INCH2IN:
571 : {
572 177 : OUString aAttrValue( rAttrValue );
573 177 : if( ReplaceSingleInchWithIn( aAttrValue ) )
574 0 : pMutableAttrList->SetValueByIndex( i, aAttrValue );
575 : }
576 177 : break;
577 : case XML_ATACTION_INCHS2INS:
578 : {
579 0 : OUString aAttrValue( rAttrValue );
580 0 : if( ReplaceInchWithIn( aAttrValue ) )
581 0 : pMutableAttrList->SetValueByIndex( i, aAttrValue );
582 : }
583 0 : break;
584 : case XML_ATACTION_TWIPS2IN:
585 : {
586 0 : OUString aAttrValue( rAttrValue );
587 :
588 0 : XMLTransformerBase::ReplaceSingleInchWithIn( aAttrValue );
589 0 : if( isWriter() )
590 : {
591 0 : sal_Int16 const nDestUnit = lcl_getUnit(aAttrValue);
592 :
593 : // convert twips value to inch
594 : sal_Int32 nMeasure;
595 0 : if (::sax::Converter::convertMeasure(nMeasure,
596 : aAttrValue, util::MeasureUnit::MM_100TH))
597 : {
598 :
599 : // #i13778#,#i36248# apply correct twip-to-1/100mm
600 0 : nMeasure = (sal_Int32)( nMeasure >= 0
601 0 : ? ((nMeasure*127+36)/72)
602 0 : : ((nMeasure*127-36)/72) );
603 :
604 0 : OUStringBuffer aBuffer;
605 : ::sax::Converter::convertMeasure(aBuffer,
606 : nMeasure, util::MeasureUnit::MM_100TH,
607 0 : nDestUnit );
608 0 : aAttrValue = aBuffer.makeStringAndClear();
609 : }
610 : }
611 :
612 0 : pMutableAttrList->SetValueByIndex( i, aAttrValue );
613 : }
614 0 : break;
615 : case XML_ATACTION_RENAME_DECODE_STYLE_NAME_REF:
616 0 : bRename = true;
617 : case XML_ATACTION_DECODE_STYLE_NAME:
618 : case XML_ATACTION_DECODE_STYLE_NAME_REF:
619 : {
620 974 : OUString aAttrValue( rAttrValue );
621 974 : if( DecodeStyleName(aAttrValue) )
622 88 : pMutableAttrList->SetValueByIndex( i, aAttrValue );
623 : }
624 974 : break;
625 : case XML_ATACTION_ENCODE_STYLE_NAME:
626 : {
627 20 : OUString aAttrValue( rAttrValue );
628 20 : if( EncodeStyleName(aAttrValue) )
629 : {
630 0 : pMutableAttrList->SetValueByIndex( i, aAttrValue );
631 : OUString aNewAttrQName(
632 0 : GetNamespaceMap().GetQNameByKey(
633 : nPrefix,
634 : ::xmloff::token::GetXMLToken(
635 0 : XML_DISPLAY_NAME ) ) );
636 : pMutableAttrList->AddAttribute( aNewAttrQName,
637 0 : rAttrValue );
638 20 : }
639 : }
640 20 : break;
641 : case XML_ATACTION_RENAME_ENCODE_STYLE_NAME_REF:
642 20 : bRename = true;
643 : case XML_ATACTION_ENCODE_STYLE_NAME_REF:
644 : {
645 608 : OUString aAttrValue( rAttrValue );
646 608 : if( EncodeStyleName(aAttrValue) )
647 6 : pMutableAttrList->SetValueByIndex( i, aAttrValue );
648 : }
649 608 : break;
650 : case XML_ATACTION_RENAME_NEG_PERCENT:
651 0 : bRename = true;
652 : case XML_ATACTION_NEG_PERCENT:
653 : {
654 0 : OUString aAttrValue( rAttrValue );
655 0 : if( NegPercent( aAttrValue ) )
656 0 : pMutableAttrList->SetValueByIndex( i, aAttrValue );
657 : }
658 0 : break;
659 : case XML_ATACTION_RENAME_ADD_NAMESPACE_PREFIX:
660 29 : bRename = true;
661 : case XML_ATACTION_ADD_NAMESPACE_PREFIX:
662 : {
663 46 : OUString aAttrValue( rAttrValue );
664 : sal_uInt16 nValPrefix =
665 : static_cast<sal_uInt16>(
666 29 : bRename ? (*aIter).second.m_nParam2
667 75 : : (*aIter).second.m_nParam1);
668 46 : if( AddNamespacePrefix( aAttrValue, nValPrefix ) )
669 46 : pMutableAttrList->SetValueByIndex( i, aAttrValue );
670 : }
671 46 : break;
672 : case XML_ATACTION_ADD_APP_NAMESPACE_PREFIX:
673 : {
674 0 : OUString aAttrValue( rAttrValue );
675 : sal_uInt16 nValPrefix =
676 0 : static_cast<sal_uInt16>((*aIter).second.m_nParam1);
677 0 : if( IsXMLToken( GetClass(), XML_SPREADSHEET ) )
678 0 : nValPrefix = XML_NAMESPACE_OOOC;
679 0 : else if( IsXMLToken( GetClass(), XML_TEXT ) )
680 0 : nValPrefix = XML_NAMESPACE_OOOW;
681 0 : if( AddNamespacePrefix( aAttrValue, nValPrefix ) )
682 0 : pMutableAttrList->SetValueByIndex( i, aAttrValue );
683 : }
684 0 : break;
685 : case XML_ATACTION_RENAME_REMOVE_NAMESPACE_PREFIX:
686 0 : bRename = true;
687 : case XML_ATACTION_REMOVE_NAMESPACE_PREFIX:
688 : {
689 9 : OUString aAttrValue( rAttrValue );
690 : sal_uInt16 nValPrefix =
691 : static_cast<sal_uInt16>(
692 0 : bRename ? (*aIter).second.m_nParam2
693 9 : : (*aIter).second.m_nParam1);
694 9 : if( RemoveNamespacePrefix( aAttrValue, nValPrefix ) )
695 9 : pMutableAttrList->SetValueByIndex( i, aAttrValue );
696 : }
697 9 : break;
698 : case XML_ATACTION_REMOVE_ANY_NAMESPACE_PREFIX:
699 : {
700 0 : OUString aAttrValue( rAttrValue );
701 0 : if( RemoveNamespacePrefix( aAttrValue ) )
702 0 : pMutableAttrList->SetValueByIndex( i, aAttrValue );
703 : }
704 0 : break;
705 : case XML_ATACTION_URI_OOO:
706 : {
707 20 : OUString aAttrValue( rAttrValue );
708 20 : if( ConvertURIToOASIS( aAttrValue,
709 20 : static_cast< bool >((*aIter).second.m_nParam1)))
710 6 : pMutableAttrList->SetValueByIndex( i, aAttrValue );
711 : }
712 20 : break;
713 : case XML_ATACTION_URI_OASIS:
714 : {
715 18 : OUString aAttrValue( rAttrValue );
716 18 : if( ConvertURIToOOo( aAttrValue,
717 18 : static_cast< bool >((*aIter).second.m_nParam1)))
718 0 : pMutableAttrList->SetValueByIndex( i, aAttrValue );
719 : }
720 18 : break;
721 : case XML_ATACTION_RENAME_ATTRIBUTE:
722 : {
723 3 : OUString aAttrValue( rAttrValue );
724 : RenameAttributeValue(
725 : aAttrValue,
726 3 : (*aIter).second.m_nParam1,
727 3 : (*aIter).second.m_nParam2,
728 9 : (*aIter).second.m_nParam3 );
729 3 : pMutableAttrList->SetValueByIndex( i, aAttrValue );
730 : }
731 3 : break;
732 : case XML_ATACTION_RNG2ISO_DATETIME:
733 : {
734 0 : OUString aAttrValue( rAttrValue );
735 0 : if( ConvertRNGDateTimeToISO( aAttrValue ))
736 0 : pMutableAttrList->SetValueByIndex( i, aAttrValue );
737 : }
738 0 : break;
739 : case XML_ATACTION_RENAME_RNG2ISO_DATETIME:
740 : {
741 0 : OUString aAttrValue( rAttrValue );
742 0 : if( ConvertRNGDateTimeToISO( aAttrValue ))
743 0 : pMutableAttrList->SetValueByIndex( i, aAttrValue );
744 0 : bRename = true;
745 : }
746 0 : break;
747 : case XML_ATACTION_IN2TWIPS:
748 : {
749 0 : OUString aAttrValue( rAttrValue );
750 0 : XMLTransformerBase::ReplaceSingleInWithInch( aAttrValue );
751 :
752 0 : if( isWriter() )
753 : {
754 0 : sal_Int16 const nDestUnit = lcl_getUnit(aAttrValue);
755 :
756 : // convert inch value to twips and export as faked inch
757 : sal_Int32 nMeasure;
758 0 : if (::sax::Converter::convertMeasure(nMeasure,
759 : aAttrValue, util::MeasureUnit::MM_100TH))
760 : {
761 :
762 : // #i13778#,#i36248#/ apply correct 1/100mm-to-twip conversion
763 0 : nMeasure = (sal_Int32)( nMeasure >= 0
764 0 : ? ((nMeasure*72+63)/127)
765 0 : : ((nMeasure*72-63)/127) );
766 :
767 0 : OUStringBuffer aBuffer;
768 : ::sax::Converter::convertMeasure( aBuffer,
769 : nMeasure, util::MeasureUnit::MM_100TH,
770 0 : nDestUnit );
771 0 : aAttrValue = aBuffer.makeStringAndClear();
772 : }
773 : }
774 :
775 0 : pMutableAttrList->SetValueByIndex( i, aAttrValue );
776 : }
777 0 : break;
778 : case XML_ATACTION_SVG_WIDTH_HEIGHT_OOO:
779 : {
780 102 : OUString aAttrValue( rAttrValue );
781 102 : ReplaceSingleInchWithIn( aAttrValue );
782 :
783 102 : sal_Int16 const nDestUnit = lcl_getUnit( aAttrValue );
784 :
785 : sal_Int32 nMeasure;
786 102 : if (::sax::Converter::convertMeasure(nMeasure,
787 : aAttrValue, util::MeasureUnit::MM_100TH))
788 : {
789 :
790 102 : if( nMeasure > 0 )
791 102 : nMeasure -= 1;
792 0 : else if( nMeasure < 0 )
793 0 : nMeasure += 1;
794 :
795 :
796 102 : OUStringBuffer aBuffer;
797 : ::sax::Converter::convertMeasure(aBuffer, nMeasure,
798 102 : util::MeasureUnit::MM_100TH, nDestUnit);
799 102 : aAttrValue = aBuffer.makeStringAndClear();
800 : }
801 :
802 102 : pMutableAttrList->SetValueByIndex( i, aAttrValue );
803 : }
804 102 : break;
805 : case XML_ATACTION_SVG_WIDTH_HEIGHT_OASIS:
806 : {
807 2 : OUString aAttrValue( rAttrValue );
808 2 : ReplaceSingleInWithInch( aAttrValue );
809 :
810 2 : sal_Int16 const nDestUnit = lcl_getUnit( aAttrValue );
811 :
812 : sal_Int32 nMeasure;
813 2 : if (::sax::Converter::convertMeasure(nMeasure,
814 : aAttrValue, util::MeasureUnit::MM_100TH))
815 : {
816 :
817 0 : if( nMeasure > 0 )
818 0 : nMeasure += 1;
819 0 : else if( nMeasure < 0 )
820 0 : nMeasure -= 1;
821 :
822 :
823 0 : OUStringBuffer aBuffer;
824 : ::sax::Converter::convertMeasure(aBuffer, nMeasure,
825 0 : util::MeasureUnit::MM_100TH, nDestUnit );
826 0 : aAttrValue = aBuffer.makeStringAndClear();
827 : }
828 :
829 2 : pMutableAttrList->SetValueByIndex( i, aAttrValue );
830 : }
831 2 : break;
832 : case XML_ATACTION_DECODE_ID:
833 : {
834 0 : const sal_Int32 nLen = rAttrValue.getLength();
835 0 : OUStringBuffer aBuffer;
836 :
837 : sal_Int32 pos;
838 0 : for( pos = 0; pos < nLen; pos++ )
839 : {
840 0 : sal_Unicode c = rAttrValue[pos];
841 0 : if( (c >= '0') && (c <= '9') )
842 0 : aBuffer.append( c );
843 : else
844 0 : aBuffer.append( (sal_Int32)c );
845 : }
846 :
847 0 : pMutableAttrList->SetValueByIndex( i, aBuffer.makeStringAndClear() );
848 : }
849 0 : break;
850 : // #i50322# - special handling for the
851 : // transparency of writer background graphics.
852 : case XML_ATACTION_WRITER_BACK_GRAPHIC_TRANSPARENCY:
853 : {
854 : // determine, if it's the transparency of a document style
855 0 : XMLTransformerContext* pFirstContext = (*m_pContexts)[0].get();
856 0 : OUString aFirstContextLocalName;
857 : /* sal_uInt16 nFirstContextPrefix = */
858 0 : GetNamespaceMap().GetKeyByAttrName( pFirstContext->GetQName(),
859 0 : &aFirstContextLocalName );
860 : bool bIsDocumentStyle(
861 : ::xmloff::token::IsXMLToken( aFirstContextLocalName,
862 0 : XML_DOCUMENT_STYLES ) );
863 : // no conversion of transparency value for document
864 : // styles, because former OpenOffice.org version writes
865 : // writes always a transparency value of 100% and doesn't
866 : // read the value. Thus, it's intepreted as 0%
867 0 : if ( !bIsDocumentStyle )
868 : {
869 0 : OUString aAttrValue( rAttrValue );
870 0 : NegPercent(aAttrValue);
871 0 : pMutableAttrList->SetValueByIndex( i, aAttrValue );
872 : }
873 0 : bRename = true;
874 : }
875 0 : break;
876 : case XML_ATACTION_SHAPEID:
877 : {
878 0 : OUString sNewValue( "shape" );
879 0 : sNewValue += rAttrValue;
880 0 : pMutableAttrList->SetValueByIndex( i, sNewValue );
881 0 : break;
882 : }
883 :
884 : default:
885 : OSL_ENSURE( false, "unknown action" );
886 0 : break;
887 : }
888 :
889 2407 : if( bRename )
890 : {
891 : OUString aNewAttrQName(
892 475 : GetNamespaceMap().GetQNameByKey(
893 475 : (*aIter).second.GetQNamePrefixFromParam1(),
894 : ::xmloff::token::GetXMLToken(
895 1425 : (*aIter).second.GetQNameTokenFromParam1()) ) );
896 : pMutableAttrList->RenameAttributeByIndex( i,
897 475 : aNewAttrQName );
898 : }
899 : }
900 3360 : }
901 : }
902 :
903 2323 : return pMutableAttrList;
904 : }
905 :
906 758 : bool XMLTransformerBase::ReplaceSingleInchWithIn( OUString& rValue )
907 : {
908 758 : bool bRet = false;
909 758 : sal_Int32 nPos = rValue.getLength();
910 1516 : while( nPos && rValue[nPos-1] <= ' ' )
911 0 : --nPos;
912 1516 : if( nPos > 2 &&
913 1516 : ('c'==rValue[nPos-2] || 'C'==rValue[nPos-2]) &&
914 1200 : ('h'==rValue[nPos-1] || 'H'==rValue[nPos-1]) )
915 : {
916 0 : rValue =rValue.copy( 0, nPos-2 );
917 0 : bRet = true;
918 : }
919 :
920 758 : return bRet;
921 : }
922 :
923 30 : bool XMLTransformerBase::ReplaceInchWithIn( OUString& rValue )
924 : {
925 30 : bool bRet = false;
926 30 : sal_Int32 nPos = 1;
927 426 : while( nPos < rValue.getLength()-3 )
928 : {
929 366 : sal_Unicode c = rValue[nPos];
930 366 : if( 'i'==c || 'I'==c )
931 : {
932 10 : c = rValue[nPos-1];
933 10 : if( (c >= '0' && c <= '9') || '.' == c )
934 : {
935 0 : c = rValue[nPos+1];
936 0 : if( 'n'==c || 'N'==c )
937 : {
938 0 : c = rValue[nPos+2];
939 0 : if( 'c'==c || 'C'==c )
940 : {
941 0 : c = rValue[nPos+3];
942 0 : if( 'h'==c || 'H'==c )
943 : {
944 0 : rValue = rValue.replaceAt( nPos,
945 0 : 4, GetXMLToken(XML_UNIT_INCH) );
946 0 : nPos += 2;
947 0 : bRet = true;
948 0 : continue;
949 : }
950 : }
951 : }
952 : }
953 : }
954 366 : ++nPos;
955 : }
956 :
957 30 : return bRet;
958 : }
959 :
960 816 : bool XMLTransformerBase::ReplaceSingleInWithInch( OUString& rValue )
961 : {
962 816 : bool bRet = false;
963 :
964 816 : sal_Int32 nPos = rValue.getLength();
965 1632 : while( nPos && rValue[nPos-1] <= ' ' )
966 0 : --nPos;
967 1632 : if( nPos > 2 &&
968 1316 : ('i'==rValue[nPos-2] ||
969 1948 : 'I'==rValue[nPos-2]) &&
970 316 : ('n'==rValue[nPos-1] ||
971 0 : 'N'==rValue[nPos-1]) )
972 : {
973 316 : nPos -= 2;
974 632 : rValue = rValue.replaceAt( nPos, rValue.getLength() - nPos,
975 632 : GetXMLToken(XML_INCH) );
976 316 : bRet = true;
977 : }
978 :
979 816 : return bRet;
980 : }
981 :
982 12 : bool XMLTransformerBase::ReplaceInWithInch( OUString& rValue )
983 : {
984 12 : bool bRet = false;
985 12 : sal_Int32 nPos = 1;
986 214 : while( nPos < rValue.getLength()-1 )
987 : {
988 190 : sal_Unicode c = rValue[nPos];
989 190 : if( 'i'==c || 'I'==c )
990 : {
991 11 : c = rValue[nPos-1];
992 11 : if( (c >= '0' && c <= '9') || '.' == c )
993 : {
994 0 : c = rValue[nPos+1];
995 0 : if( 'n'==c || 'N'==c )
996 : {
997 0 : rValue = rValue.replaceAt( nPos,
998 0 : 2, GetXMLToken(XML_INCH) );
999 0 : nPos += 4;
1000 0 : bRet = true;
1001 0 : continue;
1002 : }
1003 : }
1004 : }
1005 190 : ++nPos;
1006 : }
1007 :
1008 12 : return bRet;
1009 : }
1010 :
1011 993 : bool XMLTransformerBase::EncodeStyleName( OUString& rName ) const
1012 : {
1013 : static const sal_Char aHexTab[] = "0123456789abcdef";
1014 :
1015 993 : bool bEncoded = false;
1016 :
1017 993 : sal_Int32 nLen = rName.getLength();
1018 993 : OUStringBuffer aBuffer( nLen );
1019 :
1020 5250 : for( sal_Int32 i = 0; i < nLen; i++ )
1021 : {
1022 4257 : sal_Unicode c = rName[i];
1023 4257 : bool bValidChar = false;
1024 4257 : if( c < 0x00ffU )
1025 : {
1026 : bValidChar =
1027 3314 : (c >= 0x0041 && c <= 0x005a) ||
1028 2520 : (c >= 0x0061 && c <= 0x007a) ||
1029 0 : (c >= 0x00c0 && c <= 0x00d6) ||
1030 0 : (c >= 0x00d8 && c <= 0x00f6) ||
1031 8407 : (c >= 0x00f8 && c <= 0x00ff) ||
1032 943 : ( i > 0 && ( (c >= 0x0030 && c <= 0x0039) ||
1033 4370 : c == 0x00b7 || c == '-' || c == '.') );
1034 : }
1035 : else
1036 : {
1037 0 : if( (c >= 0xf900U && c <= 0xfffeU) ||
1038 0 : (c >= 0x20ddU && c <= 0x20e0U))
1039 : {
1040 0 : bValidChar = false;
1041 : }
1042 0 : else if( (c >= 0x02bbU && c <= 0x02c1U) || c == 0x0559 ||
1043 0 : c == 0x06e5 || c == 0x06e6 )
1044 : {
1045 0 : bValidChar = true;
1046 : }
1047 0 : else if( c == 0x0387 )
1048 : {
1049 0 : bValidChar = i > 0;
1050 : }
1051 : else
1052 : {
1053 0 : if( !xCharClass.is() )
1054 : {
1055 : const_cast < XMLTransformerBase * >(this)
1056 0 : ->xCharClass = CharacterClassification::create( comphelper::getProcessComponentContext() );
1057 : }
1058 0 : sal_Int16 nType = xCharClass->getType( rName, i );
1059 :
1060 0 : switch( nType )
1061 : {
1062 : case UnicodeType::UPPERCASE_LETTER: // Lu
1063 : case UnicodeType::LOWERCASE_LETTER: // Ll
1064 : case UnicodeType::TITLECASE_LETTER: // Lt
1065 : case UnicodeType::OTHER_LETTER: // Lo
1066 : case UnicodeType::LETTER_NUMBER: // Nl
1067 0 : bValidChar = true;
1068 0 : break;
1069 : case UnicodeType::NON_SPACING_MARK: // Ms
1070 : case UnicodeType::ENCLOSING_MARK: // Me
1071 : case UnicodeType::COMBINING_SPACING_MARK: //Mc
1072 : case UnicodeType::MODIFIER_LETTER: // Lm
1073 : case UnicodeType::DECIMAL_DIGIT_NUMBER: // Nd
1074 0 : bValidChar = i > 0;
1075 0 : break;
1076 : }
1077 : }
1078 : }
1079 4257 : if( bValidChar )
1080 : {
1081 4150 : aBuffer.append( c );
1082 : }
1083 : else
1084 : {
1085 107 : aBuffer.append( '_' );
1086 107 : if( c > 0x0fff )
1087 : aBuffer.append( static_cast< sal_Unicode >(
1088 0 : aHexTab[ (c >> 12) & 0x0f ] ) );
1089 107 : if( c > 0x00ff )
1090 : aBuffer.append( static_cast< sal_Unicode >(
1091 0 : aHexTab[ (c >> 8) & 0x0f ] ) );
1092 107 : if( c > 0x000f )
1093 : aBuffer.append( static_cast< sal_Unicode >(
1094 107 : aHexTab[ (c >> 4) & 0x0f ] ) );
1095 : aBuffer.append( static_cast< sal_Unicode >(
1096 107 : aHexTab[ c & 0x0f ] ) );
1097 107 : aBuffer.append( '_' );
1098 107 : bEncoded = true;
1099 : }
1100 : }
1101 :
1102 993 : if( aBuffer.getLength() > (1<<15)-1 )
1103 0 : bEncoded = false;
1104 :
1105 993 : if( bEncoded )
1106 95 : rName = aBuffer.makeStringAndClear();
1107 993 : return bEncoded;
1108 : }
1109 :
1110 1550 : bool XMLTransformerBase::DecodeStyleName( OUString& rName )
1111 : {
1112 1550 : bool bEncoded = false;
1113 :
1114 1550 : sal_Int32 nLen = rName.getLength();
1115 1550 : OUStringBuffer aBuffer( nLen );
1116 :
1117 1550 : bool bWithinHex = false;
1118 1550 : sal_Unicode cEnc = 0;
1119 12631 : for( sal_Int32 i = 0; i < nLen; i++ )
1120 : {
1121 11081 : sal_Unicode c = rName[i];
1122 11081 : if( '_' == c )
1123 : {
1124 700 : if( bWithinHex )
1125 : {
1126 350 : aBuffer.append( cEnc );
1127 350 : cEnc = 0;
1128 : }
1129 : else
1130 : {
1131 350 : bEncoded = true;
1132 : }
1133 700 : bWithinHex = !bWithinHex;
1134 : }
1135 10381 : else if( bWithinHex )
1136 : {
1137 : sal_Unicode cDigit;
1138 700 : if( c >= '0' && c <= '9' )
1139 : {
1140 700 : cDigit = c - '0';
1141 : }
1142 0 : else if( c >= 'a' && c <= 'f' )
1143 : {
1144 0 : cDigit = c - 'a' + 10;
1145 : }
1146 0 : else if( c >= 'A' && c <= 'F' )
1147 : {
1148 0 : cDigit = c - 'A' + 10;
1149 : }
1150 : else
1151 : {
1152 : // error
1153 0 : bEncoded = false;
1154 0 : break;
1155 : }
1156 700 : cEnc = (cEnc << 4) + cDigit;
1157 : }
1158 : else
1159 : {
1160 9681 : aBuffer.append( c );
1161 : }
1162 : }
1163 :
1164 1550 : if( bEncoded )
1165 311 : rName = aBuffer.makeStringAndClear();
1166 1550 : return bEncoded;
1167 : }
1168 :
1169 17 : bool XMLTransformerBase::NegPercent( OUString& rValue )
1170 : {
1171 17 : bool bRet = false;
1172 17 : bool bNeg = false;
1173 17 : double nVal = 0;
1174 :
1175 17 : sal_Int32 nPos = 0;
1176 17 : sal_Int32 nLen = rValue.getLength();
1177 :
1178 : // skip white space
1179 34 : while( nPos < nLen && ' ' == rValue[nPos] )
1180 0 : nPos++;
1181 :
1182 17 : if( nPos < nLen && '-' == rValue[nPos] )
1183 : {
1184 0 : bNeg = true;
1185 0 : nPos++;
1186 : }
1187 :
1188 : // get number
1189 109 : while( nPos < nLen &&
1190 75 : '0' <= rValue[nPos] &&
1191 29 : '9' >= rValue[nPos] )
1192 : {
1193 : // TODO: check overflow!
1194 29 : nVal *= 10;
1195 29 : nVal += (rValue[nPos] - '0');
1196 29 : nPos++;
1197 : }
1198 17 : if( nPos < nLen && '.' == rValue[nPos] )
1199 : {
1200 0 : nPos++;
1201 0 : double nDiv = 1.;
1202 :
1203 0 : while( nPos < nLen &&
1204 0 : '0' <= rValue[nPos] &&
1205 0 : '9' >= rValue[nPos] )
1206 : {
1207 : // TODO: check overflow!
1208 0 : nDiv *= 10;
1209 0 : nVal += ( static_cast<double>(rValue[nPos] - '0') / nDiv );
1210 0 : nPos++;
1211 : }
1212 : }
1213 :
1214 : // skip white space
1215 34 : while( nPos < nLen && ' ' == rValue[nPos] )
1216 0 : nPos++;
1217 :
1218 17 : if( nPos < nLen && '%' == rValue[nPos] )
1219 : {
1220 17 : if( bNeg )
1221 0 : nVal = -nVal;
1222 17 : nVal += .5;
1223 :
1224 17 : sal_Int32 nIntVal = 100 - static_cast<sal_Int32>( nVal );
1225 :
1226 17 : rValue = OUString::number(nIntVal) + "%";
1227 :
1228 17 : bRet = true;
1229 : }
1230 :
1231 17 : return bRet;
1232 : }
1233 :
1234 52 : bool XMLTransformerBase::AddNamespacePrefix( OUString& rName,
1235 : sal_uInt16 nPrefix ) const
1236 : {
1237 52 : rName = GetNamespaceMap().GetQNameByKey( nPrefix, rName, false );
1238 52 : return true;
1239 : }
1240 :
1241 9 : bool XMLTransformerBase::RemoveNamespacePrefix( OUString& rName,
1242 : sal_uInt16 nPrefixOnly ) const
1243 : {
1244 9 : OUString aLocalName;
1245 : sal_uInt16 nPrefix =
1246 9 : GetNamespaceMap()._GetKeyByAttrName( rName, &aLocalName, false );
1247 18 : bool bRet = XML_NAMESPACE_UNKNOWN != nPrefix &&
1248 18 : (USHRT_MAX == nPrefixOnly || nPrefix == nPrefixOnly);
1249 9 : if( bRet )
1250 9 : rName = aLocalName;
1251 :
1252 9 : return bRet;
1253 : }
1254 :
1255 26 : bool XMLTransformerBase::ConvertURIToOASIS( OUString& rURI,
1256 : bool bSupportPackage ) const
1257 : {
1258 26 : bool bRet = false;
1259 26 : if( !m_aExtPathPrefix.isEmpty() && !rURI.isEmpty() )
1260 : {
1261 12 : bool bRel = false;
1262 12 : switch( rURI[0] )
1263 : {
1264 : case '#':
1265 : // no rel path, but
1266 : // for package URIs, the '#' has to be removed
1267 11 : if( bSupportPackage )
1268 : {
1269 11 : rURI = rURI.copy( 1 );
1270 11 : bRet = true;
1271 : }
1272 11 : break;
1273 : case '/':
1274 : // no rel path; nothing to do
1275 0 : break;
1276 : case '.':
1277 : // a rel path; to keep URI simple, remove './', if there
1278 1 : bRel = true;
1279 1 : if( rURI.getLength() > 1 && '/' == rURI[1] )
1280 : {
1281 0 : rURI = rURI.copy( 2 );
1282 0 : bRet = true;
1283 : }
1284 1 : break;
1285 : default:
1286 : // check for a RFC2396 schema
1287 : {
1288 0 : bRel = true;
1289 0 : sal_Int32 nPos = 1;
1290 0 : sal_Int32 nLen = rURI.getLength();
1291 0 : while( nPos < nLen )
1292 : {
1293 0 : switch( rURI[nPos] )
1294 : {
1295 : case '/':
1296 : // a relative path segement
1297 0 : nPos = nLen; // leave loop
1298 0 : break;
1299 : case ':':
1300 : // a schema
1301 0 : bRel = false;
1302 0 : nPos = nLen; // leave loop
1303 0 : break;
1304 : default:
1305 : // we don't care about any other characters
1306 0 : break;
1307 : }
1308 0 : ++nPos;
1309 : }
1310 : }
1311 : }
1312 :
1313 12 : if( bRel )
1314 : {
1315 1 : OUString sTmp( m_aExtPathPrefix );
1316 1 : sTmp += rURI;
1317 1 : rURI = sTmp;
1318 1 : bRet = true;
1319 : }
1320 : }
1321 :
1322 26 : return bRet;
1323 : }
1324 :
1325 18 : bool XMLTransformerBase::ConvertURIToOOo( OUString& rURI,
1326 : bool bSupportPackage ) const
1327 : {
1328 18 : bool bRet = false;
1329 18 : if( !rURI.isEmpty() )
1330 : {
1331 18 : bool bPackage = false;
1332 18 : switch( rURI[0] )
1333 : {
1334 : case '/':
1335 : // no rel path; nothing to do
1336 0 : break;
1337 : case '.':
1338 : // a rel path
1339 0 : if( rURI.startsWith( m_aExtPathPrefix ) )
1340 : {
1341 : // an external URI; remove '../'
1342 0 : rURI = rURI.copy( m_aExtPathPrefix.getLength() );
1343 0 : bRet = true;
1344 : }
1345 : else
1346 : {
1347 0 : bPackage = true;
1348 : }
1349 0 : break;
1350 : default:
1351 : // check for a RFC2396 schema
1352 : {
1353 18 : bPackage = true;
1354 18 : sal_Int32 nPos = 1;
1355 18 : sal_Int32 nLen = rURI.getLength();
1356 576 : while( nPos < nLen )
1357 : {
1358 540 : switch( rURI[nPos] )
1359 : {
1360 : case '/':
1361 : // a relative path segement within the package
1362 0 : nPos = nLen; // leave loop
1363 0 : break;
1364 : case ':':
1365 : // a schema
1366 0 : bPackage = false;
1367 0 : nPos = nLen; // leave loop
1368 0 : break;
1369 : default:
1370 : // we don't care about any other characters
1371 540 : break;
1372 : }
1373 540 : ++nPos;
1374 : }
1375 : }
1376 : }
1377 :
1378 18 : if( bPackage && bSupportPackage )
1379 : {
1380 0 : OUString sTmp( '#' );
1381 0 : if( rURI.startsWith( "./" ) )
1382 0 : rURI = rURI.copy( 2 );
1383 0 : sTmp += rURI;
1384 0 : rURI = sTmp;
1385 0 : bRet = true;
1386 : }
1387 : }
1388 :
1389 18 : return bRet;
1390 : }
1391 :
1392 3 : bool XMLTransformerBase::RenameAttributeValue(
1393 : OUString& rOutAttributeValue,
1394 : sal_Int32 nParam1,
1395 : sal_Int32 nParam2,
1396 : sal_Int32 nParam3 )
1397 : {
1398 6 : return ( lcl_ConvertAttr( rOutAttributeValue, nParam1) ||
1399 3 : lcl_ConvertAttr( rOutAttributeValue, nParam2) ||
1400 3 : lcl_ConvertAttr( rOutAttributeValue, nParam3) );
1401 : }
1402 :
1403 : // static
1404 0 : bool XMLTransformerBase::ConvertRNGDateTimeToISO( OUString& rDateTime )
1405 : {
1406 0 : if( !rDateTime.isEmpty() &&
1407 0 : rDateTime.indexOf( '.' ) != -1 )
1408 : {
1409 0 : rDateTime = rDateTime.replace( '.', ',');
1410 0 : return true;
1411 : }
1412 :
1413 0 : return false;
1414 : }
1415 :
1416 18 : XMLTokenEnum XMLTransformerBase::GetToken( const OUString& rStr ) const
1417 : {
1418 : XMLTransformerTokenMap::const_iterator aIter =
1419 18 : m_pTokenMap->find( rStr );
1420 18 : if( aIter == m_pTokenMap->end() )
1421 0 : return XML_TOKEN_END;
1422 : else
1423 18 : return (*aIter).second;
1424 : }
1425 :
1426 :
1427 :
1428 26 : const XMLTransformerContext *XMLTransformerBase::GetCurrentContext() const
1429 : {
1430 : OSL_ENSURE( !m_pContexts->empty(), "empty stack" );
1431 :
1432 :
1433 26 : return m_pContexts->empty() ? 0 : m_pContexts->back().get();
1434 : }
1435 :
1436 0 : const XMLTransformerContext *XMLTransformerBase::GetAncestorContext(
1437 : sal_uInt32 n ) const
1438 : {
1439 : XMLTransformerContextVector::size_type nSize =
1440 0 : m_pContexts->size();
1441 : XMLTransformerContextVector::size_type nPos =
1442 0 : static_cast<XMLTransformerContextVector::size_type>( n );
1443 :
1444 : OSL_ENSURE( nSize >nPos+2 , "invalid context" );
1445 :
1446 0 : return nSize > nPos+2 ? (*m_pContexts)[nSize-(nPos+2)].get() : 0;
1447 : }
1448 :
1449 9 : bool XMLTransformerBase::isWriter() const
1450 : {
1451 9 : Reference< XServiceInfo > xSI( mxModel, UNO_QUERY );
1452 31 : return xSI.is() &&
1453 46 : ( xSI->supportsService("com.sun.star.text.TextDocument") ||
1454 29 : xSI->supportsService("com.sun.star.text.WebDocument") ||
1455 28 : xSI->supportsService("com.sun.star.text.GlobalDocument") );
1456 : }
1457 :
1458 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|