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