Version 5.2.6.1, tag libreoffice-5.2.6.1
[LibreOffice.git] / xmloff / source / core / xmluconv.cxx
blobf2b1f22f7da51d18f0d3ac8136f2ded62abd8c44
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.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;
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) 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);
299 return false;
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,
320 bool bAddTimeIf0AM )
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);
325 aDate += nValue;
326 fValue -= nValue;
327 double fCount;
328 if (nValue > 0)
329 fCount = ::rtl::math::approxFloor (log10((double)nValue)) + 1;
330 else if (nValue < 0)
331 fCount = ::rtl::math::approxFloor (log10((double)(nValue * -1))) + 1;
332 else
333 fCount = 0.0;
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;
340 if (fValue > 0.0)
342 bHasTime = true;
343 fValue *= 24;
344 fHoursValue = ::rtl::math::approxFloor (fValue);
345 fValue -= fHoursValue;
346 fValue *= 60;
347 fMinsValue = ::rtl::math::approxFloor (fValue);
348 fValue -= fMinsValue;
349 fValue *= 60;
350 fSecsValue = ::rtl::math::approxFloor (fValue);
351 fValue -= fSecsValue;
352 if (fValue > 0.0)
353 f100SecsValue = ::rtl::math::round( fValue, XML_MAXDIGITSCOUNT_TIME - nCount);
354 else
355 f100SecsValue = 0.0;
357 if (f100SecsValue == 1.0)
359 f100SecsValue = 0.0;
360 fSecsValue += 1.0;
362 if (fSecsValue >= 60.0)
364 fSecsValue -= 60.0;
365 fMinsValue += 1.0;
367 if (fMinsValue >= 60.0)
369 fMinsValue -= 60.0;
370 fHoursValue += 1.0;
372 if (fHoursValue >= 24.0)
374 fHoursValue -= 24.0;
375 aDate += 1;
378 sal_uInt16 nTemp = aDate.GetYear();
379 if (nTemp < 1000)
380 rBuffer.append( '0');
381 if (nTemp < 100)
382 rBuffer.append( '0');
383 if (nTemp < 10)
384 rBuffer.append( '0');
385 rBuffer.append( sal_Int32( nTemp));
386 rBuffer.append( '-');
387 nTemp = aDate.GetMonth();
388 if (nTemp < 10)
389 rBuffer.append( '0');
390 rBuffer.append( sal_Int32( nTemp));
391 rBuffer.append( '-');
392 nTemp = aDate.GetDay();
393 if (nTemp < 10)
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( ':');
403 if (fMinsValue < 10)
404 rBuffer.append( '0');
405 rBuffer.append( sal_Int32( fMinsValue));
406 rBuffer.append( ':');
407 if (fSecsValue < 10)
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);
431 if (bSuccess)
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;
447 return bSuccess;
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 )
459 return false;
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() )
471 mnNextTokenPos = -1;
473 else
475 rToken = maTokenString.copy( mnNextTokenPos );
476 mnNextTokenPos = -1;
479 return true;
482 static bool lcl_getPositions(const OUString& _sValue,OUString& _rContentX,OUString& _rContentY,OUString& _rContentZ)
484 if(_sValue.isEmpty() || _sValue[0] != '(')
485 return false;
487 sal_Int32 nPos(1L);
488 sal_Int32 nFound = _sValue.indexOf(' ', nPos);
490 if(nFound == -1 || nFound <= nPos)
491 return false;
493 _rContentX = _sValue.copy(nPos, nFound - nPos);
495 nPos = nFound + 1;
496 nFound = _sValue.indexOf(' ', nPos);
498 if(nFound == -1 || nFound <= nPos)
499 return false;
501 _rContentY = _sValue.copy(nPos, nFound - nPos);
503 nPos = nFound + 1;
504 nFound = _sValue.indexOf(')', nPos);
506 if(nFound == -1 || nFound <= nPos)
507 return false;
509 _rContentZ = _sValue.copy(nPos, nFound - nPos);
510 return true;
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) )
518 return false;
520 rtl_math_ConversionStatus eStatus;
522 rVector.setX(::rtl::math::stringToDouble(aContentX, '.',
523 ',', &eStatus));
525 if( eStatus != rtl_math_ConversionStatus_Ok )
526 return false;
528 rVector.setY(::rtl::math::stringToDouble(aContentY, '.',
529 ',', &eStatus));
531 if( eStatus != rtl_math_ConversionStatus_Ok )
532 return false;
534 rVector.setZ(::rtl::math::stringToDouble(aContentZ, '.',
535 ',', &eStatus));
538 return ( eStatus == rtl_math_ConversionStatus_Ok );
541 /** convert ::basegfx::B3DVector to string */
542 void SvXMLUnitConverter::convertB3DVector( OUStringBuffer &rBuffer, const ::basegfx::B3DVector& rVector )
544 rBuffer.append('(');
545 ::sax::Converter::convertDouble(rBuffer, rVector.getX());
546 rBuffer.append(' ');
547 ::sax::Converter::convertDouble(rBuffer, rVector.getY());
548 rBuffer.append(' ');
549 ::sax::Converter::convertDouble(rBuffer, rVector.getZ());
550 rBuffer.append(')');
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) )
559 return false;
561 if ( !convertDouble( rPosition.PositionX, aContentX ) )
562 return false;
563 if ( !convertDouble( rPosition.PositionY, aContentY ) )
564 return false;
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(
582 sal_Int16& rType,
583 const OUString& rNumFmt,
584 const OUString& rNumLetterSync,
585 bool bNumberNone ) const
587 bool bRet = true;
588 bool bExt = false;
590 sal_Int32 nLen = rNumFmt.getLength();
591 if( 0 == nLen )
593 if( bNumberNone )
594 rType = NumberingType::NUMBER_NONE;
595 else
596 bRet = false;
598 else if( 1 == nLen )
600 switch( rNumFmt[0] )
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 ) )
611 switch( rType )
613 case NumberingType::CHARS_LOWER_LETTER:
614 rType = NumberingType::CHARS_LOWER_LETTER_N;
615 break;
616 case NumberingType::CHARS_UPPER_LETTER:
617 rType = NumberingType::CHARS_UPPER_LETTER_N;
618 break;
622 else
624 bExt = true;
626 if( bExt )
628 Reference < XNumberingTypeInfo > xInfo = getNumTypeInfo();
629 if( xInfo.is() && xInfo->hasNumberingType( rNumFmt ) )
631 rType = xInfo->getNumberingType( rNumFmt );
633 else
635 rType = NumberingType::ARABIC;
639 return bRet;
642 void SvXMLUnitConverter::convertNumFormat( OUStringBuffer& rBuffer,
643 sal_Int16 nType ) const
645 enum XMLTokenEnum eFormat = XML_TOKEN_INVALID;
646 switch( nType )
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" );
661 break;
662 default:
663 break;
666 if( eFormat != XML_TOKEN_INVALID )
668 rBuffer.append( GetXMLToken(eFormat) );
670 else
672 Reference < XNumberingTypeInfo > xInfo = getNumTypeInfo();
673 if( xInfo.is() )
674 rBuffer.append( xInfo->getNumberingIdentifier( nType ) );
678 void SvXMLUnitConverter::convertNumLetterSync( OUStringBuffer& rBuffer,
679 sal_Int16 nType )
681 enum XMLTokenEnum eSync = XML_TOKEN_INVALID;
682 switch( nType )
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:
690 break;
692 case NumberingType::CHARS_UPPER_LETTER_N:
693 case NumberingType::CHARS_LOWER_LETTER_N:
694 eSync = XML_TRUE;
695 break;
697 case NumberingType::CHAR_SPECIAL:
698 case NumberingType::PAGE_DESCRIPTOR:
699 case NumberingType::BITMAP:
700 DBG_ASSERT( eSync != XML_TOKEN_INVALID, "invalid number format" );
701 break;
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());
715 if (nCount)
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());
732 if (nCount)
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
751 if( pEncoded )
752 *pEncoded = false;
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;
761 if( c < 0x00ffU )
763 bValidChar =
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 == '.') );
772 else
774 if( (c >= 0xf900U && c <= 0xfffeU) ||
775 (c >= 0x20ddU && c <= 0x20e0U))
777 bValidChar = false;
779 else if( (c >= 0x02bbU && c <= 0x02c1U) || c == 0x0559 ||
780 c == 0x06e5 || c == 0x06e6 )
782 bValidChar = true;
784 else if( c == 0x0387 )
786 bValidChar = i > 0;
788 else
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);
796 switch( nType )
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
803 bValidChar = true;
804 break;
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
810 bValidChar = i > 0;
811 break;
815 if( bValidChar )
817 aBuffer.append( c );
819 else
821 aBuffer.append( '_' );
822 if( c > 0x0fff )
823 aBuffer.append( static_cast< sal_Unicode >(
824 aHexTab[ (c >> 12) & 0x0f ] ) );
825 if( c > 0x00ff )
826 aBuffer.append( static_cast< sal_Unicode >(
827 aHexTab[ (c >> 8) & 0x0f ] ) );
828 if( c > 0x000f )
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( '_' );
834 if( pEncoded )
835 *pEncoded = true;
839 // check for length
840 if( aBuffer.getLength() > ((1<<15)-1) )
842 aBuffer = rName;
843 if( pEncoded )
844 *pEncoded = false;
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 )
856 return false;
858 nVal = 0;
859 for ( int i = 0; i < 8; i++ )
861 nVal = ( nVal << 4 )
862 | sal::static_int_cast< sal_uInt32 >( lcl_gethex( rValue[i] ) );
865 return true;
868 /** convert number (sal_uInt32) to string (hex) */
869 void SvXMLUnitConverter::convertHex( OUStringBuffer& rBuffer,
870 sal_uInt32 nVal )
872 for ( int i = 0; i < 8; i++ )
874 rBuffer.append( sal_Unicode( aHexTab[ nVal >> 28 ] ) );
875 nVal <<= 4;
879 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */