bump product version to 5.0.4.1
[LibreOffice.git] / xmloff / source / core / xmluconv.cxx
blobbbca3fe41d2f03d446fab1865a505b3397d0d9fb
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 = Reference<XNumberingTypeInfo>(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;
136 switch( nFieldUnit )
138 case FUNIT_MM:
139 eUnit = util::MeasureUnit::MM;
140 break;
141 case FUNIT_CM:
142 case FUNIT_M:
143 case FUNIT_KM:
144 eUnit = util::MeasureUnit::CM;
145 break;
146 case FUNIT_TWIP:
147 eUnit = util::MeasureUnit::TWIP;
148 break;
149 case FUNIT_POINT:
150 case FUNIT_PICA:
151 eUnit = util::MeasureUnit::POINT;
152 break;
153 case FUNIT_100TH_MM:
154 eUnit = util::MeasureUnit::MM_100TH;
155 break;
156 case FUNIT_INCH:
157 eUnit = util::MeasureUnit::INCH;
158 break;
159 default:
160 assert(false);
161 break;
163 return eUnit;
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,
173 nMin, nMax );
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 )
192 while( pMap->pName )
194 if( rValue.equalsAsciiL( pMap->pName, pMap->nNameLength ) )
196 rEnum = pMap->nValue;
197 return true;
199 ++pMap;
202 return false;
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(
208 sal_uInt16& rEnum,
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;
217 return true;
219 ++pMap;
221 return false;
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,
230 unsigned int nValue,
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 )
240 eTok = pMap->eToken;
241 break;
243 ++pMap;
246 // the map may have contained XML_TOKEN_INVALID
247 if( eTok == XML_TOKEN_INVALID )
248 eTok = eDefault;
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' )
259 return nChar - '0';
260 else if( nChar >= 'a' && nChar <= 'f' )
261 return nChar - 'a' + 10;
262 else if( nChar >= 'A' && nChar <= 'F' )
263 return nChar - 'A' + 10;
264 else
265 return 0;
268 static sal_Char aHexTab[] = "0123456789abcdef";
271 /** convert double number to string (using ::rtl::math) */
272 void SvXMLUnitConverter::convertDouble(OUStringBuffer& rBuffer,
273 double fNumber, bool bWriteUnits) const
275 ::sax::Converter::convertDouble(rBuffer, fNumber,
276 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, bool bLookForUnits) const
283 if(bLookForUnits)
285 sal_Int16 const eSrcUnit = ::sax::Converter::GetUnitFromString(
286 rString, m_pImpl->m_eCoreMeasureUnit);
288 return ::sax::Converter::convertDouble(rValue, rString,
289 eSrcUnit, m_pImpl->m_eCoreMeasureUnit);
291 else
293 return ::sax::Converter::convertDouble(rValue, rString);
297 /** get the Null Date of the XModel and set it to the UnitConverter */
298 bool SvXMLUnitConverter::setNullDate(const com::sun::star::uno::Reference <com::sun::star::frame::XModel>& xModel)
300 com::sun::star::uno::Reference <com::sun::star::util::XNumberFormatsSupplier> xNumberFormatsSupplier (xModel, com::sun::star::uno::UNO_QUERY);
301 if (xNumberFormatsSupplier.is())
303 const com::sun::star::uno::Reference <com::sun::star::beans::XPropertySet> xPropertySet = xNumberFormatsSupplier->getNumberFormatSettings();
304 return xPropertySet.is() && (xPropertySet->getPropertyValue(OUString(XML_NULLDATE)) >>= m_pImpl->m_aNullDate);
306 return false;
309 /** convert double to ISO Date Time String */
310 void SvXMLUnitConverter::convertDateTime(OUStringBuffer& rBuffer,
311 const double& fDateTime, bool const bAddTimeIf0AM)
313 convertDateTime(rBuffer, fDateTime, m_pImpl->m_aNullDate, bAddTimeIf0AM);
316 /** convert ISO Date Time String to double */
317 bool SvXMLUnitConverter::convertDateTime(double& fDateTime,
318 const OUString& rString)
320 return convertDateTime(fDateTime, rString, m_pImpl->m_aNullDate);
323 /** convert double to ISO Date Time String */
324 void SvXMLUnitConverter::convertDateTime( OUStringBuffer& rBuffer,
325 const double& fDateTime,
326 const com::sun::star::util::Date& aTempNullDate,
327 bool bAddTimeIf0AM )
329 double fValue = fDateTime;
330 sal_Int32 nValue = static_cast <sal_Int32> (::rtl::math::approxFloor (fValue));
331 Date aDate (aTempNullDate.Day, aTempNullDate.Month, aTempNullDate.Year);
332 aDate += nValue;
333 fValue -= nValue;
334 double fCount;
335 if (nValue > 0)
336 fCount = ::rtl::math::approxFloor (log10((double)nValue)) + 1;
337 else if (nValue < 0)
338 fCount = ::rtl::math::approxFloor (log10((double)(nValue * -1))) + 1;
339 else
340 fCount = 0.0;
341 sal_Int16 nCount = sal_Int16(fCount);
342 bool bHasTime(false);
343 double fHoursValue = 0;
344 double fMinsValue = 0;
345 double fSecsValue = 0;
346 double f100SecsValue = 0;
347 if (fValue > 0.0)
349 bHasTime = true;
350 fValue *= 24;
351 fHoursValue = ::rtl::math::approxFloor (fValue);
352 fValue -= fHoursValue;
353 fValue *= 60;
354 fMinsValue = ::rtl::math::approxFloor (fValue);
355 fValue -= fMinsValue;
356 fValue *= 60;
357 fSecsValue = ::rtl::math::approxFloor (fValue);
358 fValue -= fSecsValue;
359 if (fValue > 0.0)
360 f100SecsValue = ::rtl::math::round( fValue, XML_MAXDIGITSCOUNT_TIME - nCount);
361 else
362 f100SecsValue = 0.0;
364 if (f100SecsValue == 1.0)
366 f100SecsValue = 0.0;
367 fSecsValue += 1.0;
369 if (fSecsValue >= 60.0)
371 fSecsValue -= 60.0;
372 fMinsValue += 1.0;
374 if (fMinsValue >= 60.0)
376 fMinsValue -= 60.0;
377 fHoursValue += 1.0;
379 if (fHoursValue >= 24.0)
381 fHoursValue -= 24.0;
382 aDate += 1;
385 sal_uInt16 nTemp = aDate.GetYear();
386 if (nTemp < 1000)
387 rBuffer.append( '0');
388 if (nTemp < 100)
389 rBuffer.append( '0');
390 if (nTemp < 10)
391 rBuffer.append( '0');
392 rBuffer.append( sal_Int32( nTemp));
393 rBuffer.append( '-');
394 nTemp = aDate.GetMonth();
395 if (nTemp < 10)
396 rBuffer.append( '0');
397 rBuffer.append( sal_Int32( nTemp));
398 rBuffer.append( '-');
399 nTemp = aDate.GetDay();
400 if (nTemp < 10)
401 rBuffer.append( '0');
402 rBuffer.append( sal_Int32( nTemp));
403 if(bHasTime || bAddTimeIf0AM)
405 rBuffer.append( 'T');
406 if (fHoursValue < 10)
407 rBuffer.append( '0');
408 rBuffer.append( sal_Int32( fHoursValue));
409 rBuffer.append( ':');
410 if (fMinsValue < 10)
411 rBuffer.append( '0');
412 rBuffer.append( sal_Int32( fMinsValue));
413 rBuffer.append( ':');
414 if (fSecsValue < 10)
415 rBuffer.append( '0');
416 rBuffer.append( sal_Int32( fSecsValue));
417 if (f100SecsValue > 0.0)
419 OUString a100th( ::rtl::math::doubleToUString( fValue,
420 rtl_math_StringFormat_F,
421 XML_MAXDIGITSCOUNT_TIME - nCount, '.', true));
422 if ( a100th.getLength() > 2 )
424 rBuffer.append( '.');
425 rBuffer.append( a100th.copy( 2 ) ); // strip 0.
431 /** convert ISO Date Time String to double */
432 bool SvXMLUnitConverter::convertDateTime( double& fDateTime,
433 const OUString& rString, const com::sun::star::util::Date& aTempNullDate)
435 com::sun::star::util::DateTime aDateTime;
436 bool bSuccess = ::sax::Converter::parseDateTime(aDateTime, 0, rString);
438 if (bSuccess)
440 const Date aTmpNullDate(aTempNullDate.Day, aTempNullDate.Month, aTempNullDate.Year);
441 const Date aTempDate((sal_uInt16)aDateTime.Day, (sal_uInt16)aDateTime.Month, (sal_uInt16)aDateTime.Year);
442 const sal_Int32 nTage = aTempDate - aTmpNullDate;
443 double fTempDateTime = nTage;
444 double Hour = aDateTime.Hours;
445 double Min = aDateTime.Minutes;
446 double Sec = aDateTime.Seconds;
447 double NanoSec = aDateTime.NanoSeconds;
448 fTempDateTime += Hour / ::tools::Time::hourPerDay;
449 fTempDateTime += Min / ::tools::Time::minutePerDay;
450 fTempDateTime += Sec / ::tools::Time::secondPerDay;
451 fTempDateTime += NanoSec / ::tools::Time::nanoSecPerDay;
452 fDateTime = fTempDateTime;
454 return bSuccess;
458 SvXMLTokenEnumerator::SvXMLTokenEnumerator( const OUString& rString, sal_Unicode cSeparator /* = ' ' */ )
459 : maTokenString( rString ), mnNextTokenPos(0), mcSeparator( cSeparator )
463 bool SvXMLTokenEnumerator::getNextToken( OUString& rToken )
465 if( -1 == mnNextTokenPos )
466 return false;
468 int nTokenEndPos = maTokenString.indexOf( mcSeparator, mnNextTokenPos );
469 if( nTokenEndPos != -1 )
471 rToken = maTokenString.copy( mnNextTokenPos,
472 nTokenEndPos - mnNextTokenPos );
473 mnNextTokenPos = nTokenEndPos + 1;
475 // if the mnNextTokenPos is at the end of the string, we have
476 // to deliver an empty token
477 if( mnNextTokenPos > maTokenString.getLength() )
478 mnNextTokenPos = -1;
480 else
482 rToken = maTokenString.copy( mnNextTokenPos );
483 mnNextTokenPos = -1;
486 return true;
489 static bool lcl_getPositions(const OUString& _sValue,OUString& _rContentX,OUString& _rContentY,OUString& _rContentZ)
491 if(_sValue.isEmpty() || _sValue[0] != '(')
492 return false;
494 sal_Int32 nPos(1L);
495 sal_Int32 nFound = _sValue.indexOf(' ', nPos);
497 if(nFound == -1 || nFound <= nPos)
498 return false;
500 _rContentX = _sValue.copy(nPos, nFound - nPos);
502 nPos = nFound + 1;
503 nFound = _sValue.indexOf(' ', nPos);
505 if(nFound == -1 || nFound <= nPos)
506 return false;
508 _rContentY = _sValue.copy(nPos, nFound - nPos);
510 nPos = nFound + 1;
511 nFound = _sValue.indexOf(')', nPos);
513 if(nFound == -1 || nFound <= nPos)
514 return false;
516 _rContentZ = _sValue.copy(nPos, nFound - nPos);
517 return true;
520 /** convert string to ::basegfx::B3DVector */
521 bool SvXMLUnitConverter::convertB3DVector( ::basegfx::B3DVector& rVector, const OUString& rValue )
523 OUString aContentX,aContentY,aContentZ;
524 if ( !lcl_getPositions(rValue,aContentX,aContentY,aContentZ) )
525 return false;
527 rtl_math_ConversionStatus eStatus;
529 rVector.setX(::rtl::math::stringToDouble(aContentX, '.',
530 ',', &eStatus, NULL));
532 if( eStatus != rtl_math_ConversionStatus_Ok )
533 return false;
535 rVector.setY(::rtl::math::stringToDouble(aContentY, '.',
536 ',', &eStatus, NULL));
538 if( eStatus != rtl_math_ConversionStatus_Ok )
539 return false;
541 rVector.setZ(::rtl::math::stringToDouble(aContentZ, '.',
542 ',', &eStatus, NULL));
545 return ( eStatus == rtl_math_ConversionStatus_Ok );
548 /** convert ::basegfx::B3DVector to string */
549 void SvXMLUnitConverter::convertB3DVector( OUStringBuffer &rBuffer, const ::basegfx::B3DVector& rVector )
551 rBuffer.append('(');
552 ::sax::Converter::convertDouble(rBuffer, rVector.getX());
553 rBuffer.append(' ');
554 ::sax::Converter::convertDouble(rBuffer, rVector.getY());
555 rBuffer.append(' ');
556 ::sax::Converter::convertDouble(rBuffer, rVector.getZ());
557 rBuffer.append(')');
560 /** convert string to Position3D */
561 bool SvXMLUnitConverter::convertPosition3D( drawing::Position3D& rPosition,
562 const OUString& rValue )
564 OUString aContentX,aContentY,aContentZ;
565 if ( !lcl_getPositions(rValue,aContentX,aContentY,aContentZ) )
566 return false;
568 if ( !convertDouble( rPosition.PositionX, aContentX, true ) )
569 return false;
570 if ( !convertDouble( rPosition.PositionY, aContentY, true ) )
571 return false;
572 return convertDouble( rPosition.PositionZ, aContentZ, true );
575 /** convert Position3D to string */
576 void SvXMLUnitConverter::convertPosition3D( OUStringBuffer &rBuffer,
577 const drawing::Position3D& rPosition )
579 rBuffer.append( '(' );
580 convertDouble( rBuffer, rPosition.PositionX, true );
581 rBuffer.append( ' ' );
582 convertDouble( rBuffer, rPosition.PositionY, true );
583 rBuffer.append( ' ' );
584 convertDouble( rBuffer, rPosition.PositionZ, true );
585 rBuffer.append( ')' );
588 bool SvXMLUnitConverter::convertNumFormat(
589 sal_Int16& rType,
590 const OUString& rNumFmt,
591 const OUString& rNumLetterSync,
592 bool bNumberNone ) const
594 bool bRet = true;
595 bool bExt = false;
597 sal_Int32 nLen = rNumFmt.getLength();
598 if( 0 == nLen )
600 if( bNumberNone )
601 rType = NumberingType::NUMBER_NONE;
602 else
603 bRet = false;
605 else if( 1 == nLen )
607 switch( rNumFmt[0] )
609 case '1': rType = NumberingType::ARABIC; break;
610 case 'a': rType = NumberingType::CHARS_LOWER_LETTER; break;
611 case 'A': rType = NumberingType::CHARS_UPPER_LETTER; break;
612 case 'i': rType = NumberingType::ROMAN_LOWER; break;
613 case 'I': rType = NumberingType::ROMAN_UPPER; break;
614 default: bExt = true; break;
616 if( !bExt && IsXMLToken( rNumLetterSync, XML_TRUE ) )
618 switch( rType )
620 case NumberingType::CHARS_LOWER_LETTER:
621 rType = NumberingType::CHARS_LOWER_LETTER_N;
622 break;
623 case NumberingType::CHARS_UPPER_LETTER:
624 rType = NumberingType::CHARS_UPPER_LETTER_N;
625 break;
629 else
631 bExt = true;
633 if( bExt )
635 Reference < XNumberingTypeInfo > xInfo = getNumTypeInfo();
636 if( xInfo.is() && xInfo->hasNumberingType( rNumFmt ) )
638 rType = xInfo->getNumberingType( rNumFmt );
640 else
642 rType = NumberingType::ARABIC;
646 return bRet;
649 void SvXMLUnitConverter::convertNumFormat( OUStringBuffer& rBuffer,
650 sal_Int16 nType ) const
652 enum XMLTokenEnum eFormat = XML_TOKEN_INVALID;
653 switch( nType )
655 case NumberingType::CHARS_UPPER_LETTER: eFormat = XML_A_UPCASE; break;
656 case NumberingType::CHARS_LOWER_LETTER: eFormat = XML_A; break;
657 case NumberingType::ROMAN_UPPER: eFormat = XML_I_UPCASE; break;
658 case NumberingType::ROMAN_LOWER: eFormat = XML_I; break;
659 case NumberingType::ARABIC: eFormat = XML_1; break;
660 case NumberingType::CHARS_UPPER_LETTER_N: eFormat = XML_A_UPCASE; break;
661 case NumberingType::CHARS_LOWER_LETTER_N: eFormat = XML_A; break;
662 case NumberingType::NUMBER_NONE: eFormat = XML__EMPTY; break;
664 case NumberingType::CHAR_SPECIAL:
665 case NumberingType::PAGE_DESCRIPTOR:
666 case NumberingType::BITMAP:
667 DBG_ASSERT( eFormat != XML_TOKEN_INVALID, "invalid number format" );
668 break;
669 default:
670 break;
673 if( eFormat != XML_TOKEN_INVALID )
675 rBuffer.append( GetXMLToken(eFormat) );
677 else
679 Reference < XNumberingTypeInfo > xInfo = getNumTypeInfo();
680 if( xInfo.is() )
681 rBuffer.append( xInfo->getNumberingIdentifier( nType ) );
685 void SvXMLUnitConverter::convertNumLetterSync( OUStringBuffer& rBuffer,
686 sal_Int16 nType )
688 enum XMLTokenEnum eSync = XML_TOKEN_INVALID;
689 switch( nType )
691 case NumberingType::CHARS_UPPER_LETTER:
692 case NumberingType::CHARS_LOWER_LETTER:
693 case NumberingType::ROMAN_UPPER:
694 case NumberingType::ROMAN_LOWER:
695 case NumberingType::ARABIC:
696 case NumberingType::NUMBER_NONE:
697 break;
699 case NumberingType::CHARS_UPPER_LETTER_N:
700 case NumberingType::CHARS_LOWER_LETTER_N:
701 eSync = XML_TRUE;
702 break;
704 case NumberingType::CHAR_SPECIAL:
705 case NumberingType::PAGE_DESCRIPTOR:
706 case NumberingType::BITMAP:
707 DBG_ASSERT( eSync != XML_TOKEN_INVALID, "invalid number format" );
708 break;
710 if( eSync != XML_TOKEN_INVALID )
711 rBuffer.append( GetXMLToken(eSync) );
714 void SvXMLUnitConverter::convertPropertySet(uno::Sequence<beans::PropertyValue>& rProps,
715 const uno::Reference<beans::XPropertySet>& aProperties)
717 uno::Reference< beans::XPropertySetInfo > xPropertySetInfo = aProperties->getPropertySetInfo();
718 if (xPropertySetInfo.is())
720 uno::Sequence< beans::Property > aProps = xPropertySetInfo->getProperties();
721 const sal_Int32 nCount(aProps.getLength());
722 if (nCount)
724 rProps.realloc(nCount);
725 beans::PropertyValue* pProps = rProps.getArray();
726 for (sal_Int32 i = 0; i < nCount; i++, ++pProps)
728 pProps->Name = aProps[i].Name;
729 pProps->Value = aProperties->getPropertyValue(aProps[i].Name);
735 void SvXMLUnitConverter::convertPropertySet(uno::Reference<beans::XPropertySet>& rProperties,
736 const uno::Sequence<beans::PropertyValue>& aProps)
738 sal_Int32 nCount(aProps.getLength());
739 if (nCount)
741 uno::Reference< beans::XPropertySetInfo > xPropertySetInfo = rProperties->getPropertySetInfo();
742 if (xPropertySetInfo.is())
744 for (sal_Int32 i = 0; i < nCount; i++)
746 if (xPropertySetInfo->hasPropertyByName(aProps[i].Name))
747 rProperties->setPropertyValue(aProps[i].Name, aProps[i].Value);
754 OUString SvXMLUnitConverter::encodeStyleName(
755 const OUString& rName,
756 bool *pEncoded ) const
758 if( pEncoded )
759 *pEncoded = false;
761 sal_Int32 nLen = rName.getLength();
762 OUStringBuffer aBuffer( nLen );
764 for( sal_Int32 i = 0; i < nLen; i++ )
766 sal_Unicode c = rName[i];
767 bool bValidChar = false;
768 if( c < 0x00ffU )
770 bValidChar =
771 (c >= 0x0041 && c <= 0x005a) ||
772 (c >= 0x0061 && c <= 0x007a) ||
773 (c >= 0x00c0 && c <= 0x00d6) ||
774 (c >= 0x00d8 && c <= 0x00f6) ||
775 (c >= 0x00f8 && c <= 0x00ff) ||
776 ( i > 0 && ( (c >= 0x0030 && c <= 0x0039) ||
777 c == 0x00b7 || c == '-' || c == '.') );
779 else
781 if( (c >= 0xf900U && c <= 0xfffeU) ||
782 (c >= 0x20ddU && c <= 0x20e0U))
784 bValidChar = false;
786 else if( (c >= 0x02bbU && c <= 0x02c1U) || c == 0x0559 ||
787 c == 0x06e5 || c == 0x06e6 )
789 bValidChar = true;
791 else if( c == 0x0387 )
793 bValidChar = i > 0;
795 else
797 if (!m_pImpl->m_xCharClass.is())
799 this->m_pImpl->m_xCharClass = CharacterClassification::create( m_pImpl->m_xContext );
801 sal_Int16 nType = m_pImpl->m_xCharClass->getType(rName, i);
803 switch( nType )
805 case UnicodeType::UPPERCASE_LETTER: // Lu
806 case UnicodeType::LOWERCASE_LETTER: // Ll
807 case UnicodeType::TITLECASE_LETTER: // Lt
808 case UnicodeType::OTHER_LETTER: // Lo
809 case UnicodeType::LETTER_NUMBER: // Nl
810 bValidChar = true;
811 break;
812 case UnicodeType::NON_SPACING_MARK: // Ms
813 case UnicodeType::ENCLOSING_MARK: // Me
814 case UnicodeType::COMBINING_SPACING_MARK: //Mc
815 case UnicodeType::MODIFIER_LETTER: // Lm
816 case UnicodeType::DECIMAL_DIGIT_NUMBER: // Nd
817 bValidChar = i > 0;
818 break;
822 if( bValidChar )
824 aBuffer.append( c );
826 else
828 aBuffer.append( '_' );
829 if( c > 0x0fff )
830 aBuffer.append( static_cast< sal_Unicode >(
831 aHexTab[ (c >> 12) & 0x0f ] ) );
832 if( c > 0x00ff )
833 aBuffer.append( static_cast< sal_Unicode >(
834 aHexTab[ (c >> 8) & 0x0f ] ) );
835 if( c > 0x000f )
836 aBuffer.append( static_cast< sal_Unicode >(
837 aHexTab[ (c >> 4) & 0x0f ] ) );
838 aBuffer.append( static_cast< sal_Unicode >(
839 aHexTab[ c & 0x0f ] ) );
840 aBuffer.append( '_' );
841 if( pEncoded )
842 *pEncoded = true;
846 // check for length
847 if( aBuffer.getLength() > ((1<<15)-1) )
849 aBuffer = rName;
850 if( pEncoded )
851 *pEncoded = false;
855 return aBuffer.makeStringAndClear();
858 /** convert string (hex) to number (sal_uInt32) */
859 bool SvXMLUnitConverter::convertHex( sal_uInt32& nVal,
860 const OUString& rValue )
862 if( rValue.getLength() != 8 )
863 return false;
865 nVal = 0;
866 for ( int i = 0; i < 8; i++ )
868 nVal = ( nVal << 4 )
869 | sal::static_int_cast< sal_uInt32 >( lcl_gethex( rValue[i] ) );
872 return true;
875 /** convert number (sal_uInt32) to string (hex) */
876 void SvXMLUnitConverter::convertHex( OUStringBuffer& rBuffer,
877 sal_uInt32 nVal )
879 for ( int i = 0; i < 8; i++ )
881 rBuffer.append( sal_Unicode( aHexTab[ nVal >> 28 ] ) );
882 nVal <<= 4;
886 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */