1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <xmloff/xmluconv.hxx>
23 #include <com/sun/star/util/DateTime.hpp>
24 #include <com/sun/star/util/Date.hpp>
25 #include <tools/debug.hxx>
26 #include <rtl/ustrbuf.hxx>
27 #include <osl/diagnose.h>
28 #include <xmloff/xmlement.hxx>
29 #include <xmloff/xmltoken.hxx>
30 #include <rtl/math.hxx>
32 #include <tools/date.hxx>
33 #include <tools/time.hxx>
34 #include <tools/fldunit.hxx>
36 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
37 #include <com/sun/star/style/NumberingType.hpp>
38 #include <com/sun/star/text/DefaultNumberingProvider.hpp>
39 #include <com/sun/star/text/XDefaultNumberingProvider.hpp>
40 #include <com/sun/star/text/XNumberingTypeInfo.hpp>
41 #include <com/sun/star/i18n/CharacterClassification.hpp>
42 #include <com/sun/star/i18n/UnicodeType.hpp>
43 #include <basegfx/vector/b3dvector.hxx>
44 #include <comphelper/processfactory.hxx>
46 #include <sax/tools/converter.hxx>
49 using namespace com::sun::star
;
50 using namespace com::sun::star::uno
;
51 using namespace com::sun::star::lang
;
52 using namespace com::sun::star::text
;
53 using namespace com::sun::star::style
;
54 using namespace ::com::sun::star::i18n
;
55 using namespace ::xmloff::token
;
58 const sal_Int8 XML_MAXDIGITSCOUNT_TIME
= 11;
59 #define XML_NULLDATE "NullDate"
61 struct SvXMLUnitConverter::Impl
63 sal_Int16 m_eCoreMeasureUnit
; /*css::util::MeasureUnit*/
64 sal_Int16 m_eXMLMeasureUnit
; /*css::util::MeasureUnit*/
65 util::Date m_aNullDate
;
66 mutable uno::Reference
< text::XNumberingTypeInfo
> m_xNumTypeInfo
;
67 mutable uno::Reference
< i18n::XCharacterClassification
> m_xCharClass
;
68 uno::Reference
< uno::XComponentContext
> m_xContext
;
70 Impl(uno::Reference
<uno::XComponentContext
> const& xContext
,
71 sal_Int16
const eCoreMeasureUnit
,
72 sal_Int16
const eXMLMeasureUnit
)
73 : m_eCoreMeasureUnit(eCoreMeasureUnit
)
74 , m_eXMLMeasureUnit(eXMLMeasureUnit
)
75 , m_aNullDate(30, 12, 1899)
76 , m_xContext(xContext
)
78 OSL_ENSURE( m_xContext
.is(), "got no service manager" );
81 void createNumTypeInfo() const;
85 void SvXMLUnitConverter::Impl::createNumTypeInfo() const
87 Reference
<XDefaultNumberingProvider
> xDefNum
= DefaultNumberingProvider::create(m_xContext
);
88 m_xNumTypeInfo
.set(xDefNum
, uno::UNO_QUERY
);
91 const uno::Reference
< text::XNumberingTypeInfo
>&
92 SvXMLUnitConverter::getNumTypeInfo() const
94 if (!m_pImpl
->m_xNumTypeInfo
.is())
96 m_pImpl
->createNumTypeInfo();
98 return m_pImpl
->m_xNumTypeInfo
;
101 void SvXMLUnitConverter::SetCoreMeasureUnit(sal_Int16
const eCoreMeasureUnit
/*css::util::MeasureUnit*/)
103 m_pImpl
->m_eCoreMeasureUnit
= eCoreMeasureUnit
;
106 void SvXMLUnitConverter::SetXMLMeasureUnit(sal_Int16
const eXMLMeasureUnit
/*css::util::MeasureUnit*/)
108 m_pImpl
->m_eXMLMeasureUnit
= eXMLMeasureUnit
;
111 sal_Int16
SvXMLUnitConverter::GetXMLMeasureUnit() const
113 return m_pImpl
->m_eXMLMeasureUnit
;
116 /** constructs a SvXMLUnitConverter. The core measure unit is the
117 default unit for numerical measures, the XML measure unit is
118 the default unit for textual measures
121 SvXMLUnitConverter::SvXMLUnitConverter(
122 const uno::Reference
<uno::XComponentContext
>& xContext
,
123 sal_Int16
const eCoreMeasureUnit
,
124 sal_Int16
const eXMLMeasureUnit
)
125 : m_pImpl(new Impl(xContext
, eCoreMeasureUnit
, eXMLMeasureUnit
))
129 SvXMLUnitConverter::~SvXMLUnitConverter()
133 sal_Int16
SvXMLUnitConverter::GetMeasureUnit(FieldUnit
const nFieldUnit
)
135 sal_Int16 eUnit
= util::MeasureUnit::INCH
;
139 eUnit
= util::MeasureUnit::MM
;
144 eUnit
= util::MeasureUnit::CM
;
147 eUnit
= util::MeasureUnit::TWIP
;
151 eUnit
= util::MeasureUnit::POINT
;
154 eUnit
= util::MeasureUnit::MM_100TH
;
157 eUnit
= util::MeasureUnit::INCH
;
166 /** convert string to measure using optional min and max values*/
167 bool SvXMLUnitConverter::convertMeasureToCore( sal_Int32
& nValue
,
168 const OUString
& rString
,
169 sal_Int32 nMin
, sal_Int32 nMax
) const
171 return ::sax::Converter::convertMeasure( nValue
, rString
,
172 m_pImpl
->m_eCoreMeasureUnit
,
176 /** convert measure to string */
177 void SvXMLUnitConverter::convertMeasureToXML( OUStringBuffer
& rString
,
178 sal_Int32 nMeasure
) const
180 ::sax::Converter::convertMeasure( rString
, nMeasure
,
181 m_pImpl
->m_eCoreMeasureUnit
,
182 m_pImpl
->m_eXMLMeasureUnit
);
185 /** convert string to enum using given enum map, if the enum is
186 not found in the map, this method will return false
188 bool SvXMLUnitConverter::convertEnum( sal_uInt16
& rEnum
,
189 const OUString
& rValue
,
190 const SvXMLEnumStringMapEntry
*pMap
)
194 if( rValue
.equalsAsciiL( pMap
->pName
, pMap
->nNameLength
) )
196 rEnum
= pMap
->nValue
;
205 /** convert string to enum using given token map, if the enum is
206 not found in the map, this method will return false */
207 bool SvXMLUnitConverter::convertEnum(
209 const OUString
& rValue
,
210 const SvXMLEnumMapEntry
*pMap
)
212 while( pMap
->eToken
!= XML_TOKEN_INVALID
)
214 if( IsXMLToken( rValue
, pMap
->eToken
) )
216 rEnum
= pMap
->nValue
;
224 /** convert enum to string using given token map with an optional
225 default token. If the enum is not found in the map,
226 this method will either use the given default or return
227 false if no default is set */
228 bool SvXMLUnitConverter::convertEnum(
229 OUStringBuffer
& rBuffer
,
231 const SvXMLEnumMapEntry
*pMap
,
232 enum XMLTokenEnum eDefault
)
234 enum XMLTokenEnum eTok
= eDefault
;
236 while( pMap
->eToken
!= XML_TOKEN_INVALID
)
238 if( pMap
->nValue
== nValue
)
246 // the map may have contained XML_TOKEN_INVALID
247 if( eTok
== XML_TOKEN_INVALID
)
250 if( eTok
!= XML_TOKEN_INVALID
)
251 rBuffer
.append( GetXMLToken(eTok
) );
253 return (eTok
!= XML_TOKEN_INVALID
);
256 static int lcl_gethex( int nChar
)
258 if( nChar
>= '0' && nChar
<= '9' )
260 else if( nChar
>= 'a' && nChar
<= 'f' )
261 return nChar
- 'a' + 10;
262 else if( nChar
>= 'A' && nChar
<= 'F' )
263 return nChar
- 'A' + 10;
268 static sal_Char aHexTab
[] = "0123456789abcdef";
271 /** convert double number to string (using ::rtl::math) */
272 void SvXMLUnitConverter::convertDouble(OUStringBuffer
& rBuffer
,
273 double fNumber
) const
275 ::sax::Converter::convertDouble(rBuffer
, fNumber
,
276 true/*bWriteUnits*/, m_pImpl
->m_eCoreMeasureUnit
, m_pImpl
->m_eXMLMeasureUnit
);
279 /** convert string to double number (using ::rtl::math) */
280 bool SvXMLUnitConverter::convertDouble(double& rValue
,
281 const OUString
& rString
) const
283 sal_Int16
const eSrcUnit
= ::sax::Converter::GetUnitFromString(
284 rString
, m_pImpl
->m_eCoreMeasureUnit
);
286 return ::sax::Converter::convertDouble(rValue
, rString
,
287 eSrcUnit
, m_pImpl
->m_eCoreMeasureUnit
);
290 /** get the Null Date of the XModel and set it to the UnitConverter */
291 bool SvXMLUnitConverter::setNullDate(const css::uno::Reference
<css::frame::XModel
>& xModel
)
293 css::uno::Reference
<css::util::XNumberFormatsSupplier
> xNumberFormatsSupplier (xModel
, css::uno::UNO_QUERY
);
294 if (xNumberFormatsSupplier
.is())
296 const css::uno::Reference
<css::beans::XPropertySet
> xPropertySet
= xNumberFormatsSupplier
->getNumberFormatSettings();
297 return xPropertySet
.is() && (xPropertySet
->getPropertyValue(XML_NULLDATE
) >>= m_pImpl
->m_aNullDate
);
302 /** convert double to ISO Date Time String */
303 void SvXMLUnitConverter::convertDateTime(OUStringBuffer
& rBuffer
,
304 const double& fDateTime
, bool const bAddTimeIf0AM
)
306 convertDateTime(rBuffer
, fDateTime
, m_pImpl
->m_aNullDate
, bAddTimeIf0AM
);
309 /** convert ISO Date Time String to double */
310 bool SvXMLUnitConverter::convertDateTime(double& fDateTime
,
311 const OUString
& rString
)
313 return convertDateTime(fDateTime
, rString
, m_pImpl
->m_aNullDate
);
316 /** convert double to ISO Date Time String */
317 void SvXMLUnitConverter::convertDateTime( OUStringBuffer
& rBuffer
,
318 const double& fDateTime
,
319 const css::util::Date
& aTempNullDate
,
322 double fValue
= fDateTime
;
323 sal_Int32 nValue
= static_cast <sal_Int32
> (::rtl::math::approxFloor (fValue
));
324 Date
aDate (aTempNullDate
.Day
, aTempNullDate
.Month
, aTempNullDate
.Year
);
329 fCount
= ::rtl::math::approxFloor (log10((double)nValue
)) + 1;
331 fCount
= ::rtl::math::approxFloor (log10((double)(nValue
* -1))) + 1;
334 sal_Int16 nCount
= sal_Int16(fCount
);
335 bool bHasTime(false);
336 double fHoursValue
= 0;
337 double fMinsValue
= 0;
338 double fSecsValue
= 0;
339 double f100SecsValue
= 0;
344 fHoursValue
= ::rtl::math::approxFloor (fValue
);
345 fValue
-= fHoursValue
;
347 fMinsValue
= ::rtl::math::approxFloor (fValue
);
348 fValue
-= fMinsValue
;
350 fSecsValue
= ::rtl::math::approxFloor (fValue
);
351 fValue
-= fSecsValue
;
353 f100SecsValue
= ::rtl::math::round( fValue
, XML_MAXDIGITSCOUNT_TIME
- nCount
);
357 if (f100SecsValue
== 1.0)
362 if (fSecsValue
>= 60.0)
367 if (fMinsValue
>= 60.0)
372 if (fHoursValue
>= 24.0)
378 sal_uInt16 nTemp
= aDate
.GetYear();
380 rBuffer
.append( '0');
382 rBuffer
.append( '0');
384 rBuffer
.append( '0');
385 rBuffer
.append( sal_Int32( nTemp
));
386 rBuffer
.append( '-');
387 nTemp
= aDate
.GetMonth();
389 rBuffer
.append( '0');
390 rBuffer
.append( sal_Int32( nTemp
));
391 rBuffer
.append( '-');
392 nTemp
= aDate
.GetDay();
394 rBuffer
.append( '0');
395 rBuffer
.append( sal_Int32( nTemp
));
396 if(bHasTime
|| bAddTimeIf0AM
)
398 rBuffer
.append( 'T');
399 if (fHoursValue
< 10)
400 rBuffer
.append( '0');
401 rBuffer
.append( sal_Int32( fHoursValue
));
402 rBuffer
.append( ':');
404 rBuffer
.append( '0');
405 rBuffer
.append( sal_Int32( fMinsValue
));
406 rBuffer
.append( ':');
408 rBuffer
.append( '0');
409 rBuffer
.append( sal_Int32( fSecsValue
));
410 if (f100SecsValue
> 0.0)
412 OUString
a100th( ::rtl::math::doubleToUString( fValue
,
413 rtl_math_StringFormat_F
,
414 XML_MAXDIGITSCOUNT_TIME
- nCount
, '.', true));
415 if ( a100th
.getLength() > 2 )
417 rBuffer
.append( '.');
418 rBuffer
.append( a100th
.copy( 2 ) ); // strip 0.
424 /** convert ISO Date Time String to double */
425 bool SvXMLUnitConverter::convertDateTime( double& fDateTime
,
426 const OUString
& rString
, const css::util::Date
& aTempNullDate
)
428 css::util::DateTime aDateTime
;
429 bool bSuccess
= ::sax::Converter::parseDateTime(aDateTime
, nullptr, rString
);
433 const Date
aTmpNullDate(aTempNullDate
.Day
, aTempNullDate
.Month
, aTempNullDate
.Year
);
434 const Date
aTempDate((sal_uInt16
)aDateTime
.Day
, (sal_uInt16
)aDateTime
.Month
, (sal_uInt16
)aDateTime
.Year
);
435 const sal_Int32 nTage
= aTempDate
- aTmpNullDate
;
436 double fTempDateTime
= nTage
;
437 double Hour
= aDateTime
.Hours
;
438 double Min
= aDateTime
.Minutes
;
439 double Sec
= aDateTime
.Seconds
;
440 double NanoSec
= aDateTime
.NanoSeconds
;
441 fTempDateTime
+= Hour
/ ::tools::Time::hourPerDay
;
442 fTempDateTime
+= Min
/ ::tools::Time::minutePerDay
;
443 fTempDateTime
+= Sec
/ ::tools::Time::secondPerDay
;
444 fTempDateTime
+= NanoSec
/ ::tools::Time::nanoSecPerDay
;
445 fDateTime
= fTempDateTime
;
451 SvXMLTokenEnumerator::SvXMLTokenEnumerator( const OUString
& rString
, sal_Unicode cSeparator
/* = ' ' */ )
452 : maTokenString( rString
), mnNextTokenPos(0), mcSeparator( cSeparator
)
456 bool SvXMLTokenEnumerator::getNextToken( OUString
& rToken
)
458 if( -1 == mnNextTokenPos
)
461 int nTokenEndPos
= maTokenString
.indexOf( mcSeparator
, mnNextTokenPos
);
462 if( nTokenEndPos
!= -1 )
464 rToken
= maTokenString
.copy( mnNextTokenPos
,
465 nTokenEndPos
- mnNextTokenPos
);
466 mnNextTokenPos
= nTokenEndPos
+ 1;
468 // if the mnNextTokenPos is at the end of the string, we have
469 // to deliver an empty token
470 if( mnNextTokenPos
> maTokenString
.getLength() )
475 rToken
= maTokenString
.copy( mnNextTokenPos
);
482 static bool lcl_getPositions(const OUString
& _sValue
,OUString
& _rContentX
,OUString
& _rContentY
,OUString
& _rContentZ
)
484 if(_sValue
.isEmpty() || _sValue
[0] != '(')
488 sal_Int32 nFound
= _sValue
.indexOf(' ', nPos
);
490 if(nFound
== -1 || nFound
<= nPos
)
493 _rContentX
= _sValue
.copy(nPos
, nFound
- nPos
);
496 nFound
= _sValue
.indexOf(' ', nPos
);
498 if(nFound
== -1 || nFound
<= nPos
)
501 _rContentY
= _sValue
.copy(nPos
, nFound
- nPos
);
504 nFound
= _sValue
.indexOf(')', nPos
);
506 if(nFound
== -1 || nFound
<= nPos
)
509 _rContentZ
= _sValue
.copy(nPos
, nFound
- nPos
);
513 /** convert string to ::basegfx::B3DVector */
514 bool SvXMLUnitConverter::convertB3DVector( ::basegfx::B3DVector
& rVector
, const OUString
& rValue
)
516 OUString aContentX
,aContentY
,aContentZ
;
517 if ( !lcl_getPositions(rValue
,aContentX
,aContentY
,aContentZ
) )
520 rtl_math_ConversionStatus eStatus
;
522 rVector
.setX(::rtl::math::stringToDouble(aContentX
, '.',
525 if( eStatus
!= rtl_math_ConversionStatus_Ok
)
528 rVector
.setY(::rtl::math::stringToDouble(aContentY
, '.',
531 if( eStatus
!= rtl_math_ConversionStatus_Ok
)
534 rVector
.setZ(::rtl::math::stringToDouble(aContentZ
, '.',
538 return ( eStatus
== rtl_math_ConversionStatus_Ok
);
541 /** convert ::basegfx::B3DVector to string */
542 void SvXMLUnitConverter::convertB3DVector( OUStringBuffer
&rBuffer
, const ::basegfx::B3DVector
& rVector
)
545 ::sax::Converter::convertDouble(rBuffer
, rVector
.getX());
547 ::sax::Converter::convertDouble(rBuffer
, rVector
.getY());
549 ::sax::Converter::convertDouble(rBuffer
, rVector
.getZ());
553 /** convert string to Position3D */
554 bool SvXMLUnitConverter::convertPosition3D( drawing::Position3D
& rPosition
,
555 const OUString
& rValue
)
557 OUString aContentX
,aContentY
,aContentZ
;
558 if ( !lcl_getPositions(rValue
,aContentX
,aContentY
,aContentZ
) )
561 if ( !convertDouble( rPosition
.PositionX
, aContentX
) )
563 if ( !convertDouble( rPosition
.PositionY
, aContentY
) )
565 return convertDouble( rPosition
.PositionZ
, aContentZ
);
568 /** convert Position3D to string */
569 void SvXMLUnitConverter::convertPosition3D( OUStringBuffer
&rBuffer
,
570 const drawing::Position3D
& rPosition
)
572 rBuffer
.append( '(' );
573 convertDouble( rBuffer
, rPosition
.PositionX
);
574 rBuffer
.append( ' ' );
575 convertDouble( rBuffer
, rPosition
.PositionY
);
576 rBuffer
.append( ' ' );
577 convertDouble( rBuffer
, rPosition
.PositionZ
);
578 rBuffer
.append( ')' );
581 bool SvXMLUnitConverter::convertNumFormat(
583 const OUString
& rNumFmt
,
584 const OUString
& rNumLetterSync
,
585 bool bNumberNone
) const
590 sal_Int32 nLen
= rNumFmt
.getLength();
594 rType
= NumberingType::NUMBER_NONE
;
602 case '1': rType
= NumberingType::ARABIC
; break;
603 case 'a': rType
= NumberingType::CHARS_LOWER_LETTER
; break;
604 case 'A': rType
= NumberingType::CHARS_UPPER_LETTER
; break;
605 case 'i': rType
= NumberingType::ROMAN_LOWER
; break;
606 case 'I': rType
= NumberingType::ROMAN_UPPER
; break;
607 default: bExt
= true; break;
609 if( !bExt
&& IsXMLToken( rNumLetterSync
, XML_TRUE
) )
613 case NumberingType::CHARS_LOWER_LETTER
:
614 rType
= NumberingType::CHARS_LOWER_LETTER_N
;
616 case NumberingType::CHARS_UPPER_LETTER
:
617 rType
= NumberingType::CHARS_UPPER_LETTER_N
;
628 Reference
< XNumberingTypeInfo
> xInfo
= getNumTypeInfo();
629 if( xInfo
.is() && xInfo
->hasNumberingType( rNumFmt
) )
631 rType
= xInfo
->getNumberingType( rNumFmt
);
635 rType
= NumberingType::ARABIC
;
642 void SvXMLUnitConverter::convertNumFormat( OUStringBuffer
& rBuffer
,
643 sal_Int16 nType
) const
645 enum XMLTokenEnum eFormat
= XML_TOKEN_INVALID
;
648 case NumberingType::CHARS_UPPER_LETTER
: eFormat
= XML_A_UPCASE
; break;
649 case NumberingType::CHARS_LOWER_LETTER
: eFormat
= XML_A
; break;
650 case NumberingType::ROMAN_UPPER
: eFormat
= XML_I_UPCASE
; break;
651 case NumberingType::ROMAN_LOWER
: eFormat
= XML_I
; break;
652 case NumberingType::ARABIC
: eFormat
= XML_1
; break;
653 case NumberingType::CHARS_UPPER_LETTER_N
: eFormat
= XML_A_UPCASE
; break;
654 case NumberingType::CHARS_LOWER_LETTER_N
: eFormat
= XML_A
; break;
655 case NumberingType::NUMBER_NONE
: eFormat
= XML__EMPTY
; break;
657 case NumberingType::CHAR_SPECIAL
:
658 case NumberingType::PAGE_DESCRIPTOR
:
659 case NumberingType::BITMAP
:
660 DBG_ASSERT( eFormat
!= XML_TOKEN_INVALID
, "invalid number format" );
666 if( eFormat
!= XML_TOKEN_INVALID
)
668 rBuffer
.append( GetXMLToken(eFormat
) );
672 Reference
< XNumberingTypeInfo
> xInfo
= getNumTypeInfo();
674 rBuffer
.append( xInfo
->getNumberingIdentifier( nType
) );
678 void SvXMLUnitConverter::convertNumLetterSync( OUStringBuffer
& rBuffer
,
681 enum XMLTokenEnum eSync
= XML_TOKEN_INVALID
;
684 case NumberingType::CHARS_UPPER_LETTER
:
685 case NumberingType::CHARS_LOWER_LETTER
:
686 case NumberingType::ROMAN_UPPER
:
687 case NumberingType::ROMAN_LOWER
:
688 case NumberingType::ARABIC
:
689 case NumberingType::NUMBER_NONE
:
692 case NumberingType::CHARS_UPPER_LETTER_N
:
693 case NumberingType::CHARS_LOWER_LETTER_N
:
697 case NumberingType::CHAR_SPECIAL
:
698 case NumberingType::PAGE_DESCRIPTOR
:
699 case NumberingType::BITMAP
:
700 DBG_ASSERT( eSync
!= XML_TOKEN_INVALID
, "invalid number format" );
703 if( eSync
!= XML_TOKEN_INVALID
)
704 rBuffer
.append( GetXMLToken(eSync
) );
707 void SvXMLUnitConverter::convertPropertySet(uno::Sequence
<beans::PropertyValue
>& rProps
,
708 const uno::Reference
<beans::XPropertySet
>& aProperties
)
710 uno::Reference
< beans::XPropertySetInfo
> xPropertySetInfo
= aProperties
->getPropertySetInfo();
711 if (xPropertySetInfo
.is())
713 uno::Sequence
< beans::Property
> aProps
= xPropertySetInfo
->getProperties();
714 const sal_Int32
nCount(aProps
.getLength());
717 rProps
.realloc(nCount
);
718 beans::PropertyValue
* pProps
= rProps
.getArray();
719 for (sal_Int32 i
= 0; i
< nCount
; i
++, ++pProps
)
721 pProps
->Name
= aProps
[i
].Name
;
722 pProps
->Value
= aProperties
->getPropertyValue(aProps
[i
].Name
);
728 void SvXMLUnitConverter::convertPropertySet(uno::Reference
<beans::XPropertySet
>& rProperties
,
729 const uno::Sequence
<beans::PropertyValue
>& aProps
)
731 sal_Int32
nCount(aProps
.getLength());
734 uno::Reference
< beans::XPropertySetInfo
> xPropertySetInfo
= rProperties
->getPropertySetInfo();
735 if (xPropertySetInfo
.is())
737 for (sal_Int32 i
= 0; i
< nCount
; i
++)
739 if (xPropertySetInfo
->hasPropertyByName(aProps
[i
].Name
))
740 rProperties
->setPropertyValue(aProps
[i
].Name
, aProps
[i
].Value
);
747 OUString
SvXMLUnitConverter::encodeStyleName(
748 const OUString
& rName
,
749 bool *pEncoded
) const
754 sal_Int32 nLen
= rName
.getLength();
755 OUStringBuffer
aBuffer( nLen
);
757 for( sal_Int32 i
= 0; i
< nLen
; i
++ )
759 sal_Unicode c
= rName
[i
];
760 bool bValidChar
= false;
764 (c
>= 0x0041 && c
<= 0x005a) ||
765 (c
>= 0x0061 && c
<= 0x007a) ||
766 (c
>= 0x00c0 && c
<= 0x00d6) ||
767 (c
>= 0x00d8 && c
<= 0x00f6) ||
768 (c
>= 0x00f8 && c
<= 0x00ff) ||
769 ( i
> 0 && ( (c
>= 0x0030 && c
<= 0x0039) ||
770 c
== 0x00b7 || c
== '-' || c
== '.') );
774 if( (c
>= 0xf900U
&& c
<= 0xfffeU
) ||
775 (c
>= 0x20ddU
&& c
<= 0x20e0U
))
779 else if( (c
>= 0x02bbU
&& c
<= 0x02c1U
) || c
== 0x0559 ||
780 c
== 0x06e5 || c
== 0x06e6 )
784 else if( c
== 0x0387 )
790 if (!m_pImpl
->m_xCharClass
.is())
792 this->m_pImpl
->m_xCharClass
= CharacterClassification::create( m_pImpl
->m_xContext
);
794 sal_Int16 nType
= m_pImpl
->m_xCharClass
->getType(rName
, i
);
798 case UnicodeType::UPPERCASE_LETTER
: // Lu
799 case UnicodeType::LOWERCASE_LETTER
: // Ll
800 case UnicodeType::TITLECASE_LETTER
: // Lt
801 case UnicodeType::OTHER_LETTER
: // Lo
802 case UnicodeType::LETTER_NUMBER
: // Nl
805 case UnicodeType::NON_SPACING_MARK
: // Ms
806 case UnicodeType::ENCLOSING_MARK
: // Me
807 case UnicodeType::COMBINING_SPACING_MARK
: //Mc
808 case UnicodeType::MODIFIER_LETTER
: // Lm
809 case UnicodeType::DECIMAL_DIGIT_NUMBER
: // Nd
821 aBuffer
.append( '_' );
823 aBuffer
.append( static_cast< sal_Unicode
>(
824 aHexTab
[ (c
>> 12) & 0x0f ] ) );
826 aBuffer
.append( static_cast< sal_Unicode
>(
827 aHexTab
[ (c
>> 8) & 0x0f ] ) );
829 aBuffer
.append( static_cast< sal_Unicode
>(
830 aHexTab
[ (c
>> 4) & 0x0f ] ) );
831 aBuffer
.append( static_cast< sal_Unicode
>(
832 aHexTab
[ c
& 0x0f ] ) );
833 aBuffer
.append( '_' );
840 if( aBuffer
.getLength() > ((1<<15)-1) )
848 return aBuffer
.makeStringAndClear();
851 /** convert string (hex) to number (sal_uInt32) */
852 bool SvXMLUnitConverter::convertHex( sal_uInt32
& nVal
,
853 const OUString
& rValue
)
855 if( rValue
.getLength() != 8 )
859 for ( int i
= 0; i
< 8; i
++ )
862 | sal::static_int_cast
< sal_uInt32
>( lcl_gethex( rValue
[i
] ) );
868 /** convert number (sal_uInt32) to string (hex) */
869 void SvXMLUnitConverter::convertHex( OUStringBuffer
& rBuffer
,
872 for ( int i
= 0; i
< 8; i
++ )
874 rBuffer
.append( sal_Unicode( aHexTab
[ nVal
>> 28 ] ) );
879 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */