LibreOffice Module xmloff (master) 1
xmluconv.cxx
Go to the documentation of this file.
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 <sal/config.h>
21
22#include <string_view>
23
24#include <xmloff/xmluconv.hxx>
25
26#include <com/sun/star/util/DateTime.hpp>
27#include <com/sun/star/util/Date.hpp>
28#include <rtl/ustrbuf.hxx>
29#include <osl/diagnose.h>
30#include <sal/log.hxx>
31#include <xmloff/xmlement.hxx>
32#include <xmloff/xmltoken.hxx>
33#include <rtl/math.hxx>
34
35#include <tools/date.hxx>
36#include <tools/time.hxx>
37#include <tools/fldunit.hxx>
38
39#include <com/sun/star/drawing/Position3D.hpp>
40#include <com/sun/star/frame/XModel.hpp>
41#include <com/sun/star/util/XNumberFormatsSupplier.hpp>
42#include <com/sun/star/style/NumberingType.hpp>
43#include <com/sun/star/text/DefaultNumberingProvider.hpp>
44#include <com/sun/star/text/XDefaultNumberingProvider.hpp>
45#include <com/sun/star/text/XNumberingTypeInfo.hpp>
46#include <com/sun/star/i18n/CharacterClassification.hpp>
47#include <com/sun/star/i18n/UnicodeType.hpp>
49
51
52
53using namespace com::sun::star;
54using namespace com::sun::star::uno;
55using namespace com::sun::star::lang;
56using namespace com::sun::star::text;
57using namespace com::sun::star::style;
58using namespace ::com::sun::star::i18n;
59using namespace ::xmloff::token;
60
61
63constexpr OUStringLiteral XML_NULLDATE = u"NullDate";
64
66{
67 sal_Int16 m_eCoreMeasureUnit; /*css::util::MeasureUnit*/
68 sal_Int16 m_eXMLMeasureUnit; /*css::util::MeasureUnit*/
70 util::Date m_aNullDate;
71 mutable uno::Reference< text::XNumberingTypeInfo > m_xNumTypeInfo;
72 mutable uno::Reference< i18n::XCharacterClassification > m_xCharClass;
73 uno::Reference< uno::XComponentContext > m_xContext;
74
75 Impl(uno::Reference<uno::XComponentContext> const& xContext,
76 sal_Int16 const eCoreMeasureUnit,
77 sal_Int16 const eXMLMeasureUnit,
79 : m_eCoreMeasureUnit(eCoreMeasureUnit)
80 , m_eXMLMeasureUnit(eXMLMeasureUnit)
81 , m_eODFVersion(nODFVersion)
82 , m_aNullDate(30, 12, 1899)
83 , m_xContext(xContext)
84 {
85 OSL_ENSURE( m_xContext.is(), "got no service manager" );
86 }
87
88 void createNumTypeInfo() const;
89};
90
91
93{
94 Reference<XDefaultNumberingProvider> xDefNum = DefaultNumberingProvider::create(m_xContext);
95 m_xNumTypeInfo.set(xDefNum, uno::UNO_QUERY);
96}
97
98const uno::Reference< text::XNumberingTypeInfo >&
100{
101 if (!m_pImpl->m_xNumTypeInfo.is())
102 {
103 m_pImpl->createNumTypeInfo();
104 }
105 return m_pImpl->m_xNumTypeInfo;
106}
107
108void SvXMLUnitConverter::SetCoreMeasureUnit(sal_Int16 const eCoreMeasureUnit/*css::util::MeasureUnit*/)
109{
110 m_pImpl->m_eCoreMeasureUnit = eCoreMeasureUnit;
111}
112
113void SvXMLUnitConverter::SetXMLMeasureUnit(sal_Int16 const eXMLMeasureUnit/*css::util::MeasureUnit*/)
114{
115 m_pImpl->m_eXMLMeasureUnit = eXMLMeasureUnit;
116}
117
119{
120 return m_pImpl->m_eXMLMeasureUnit;
121}
122
124{
125 return m_pImpl->m_eODFVersion;
126}
127
130{
131 m_pImpl->m_eODFVersion = nODFVersion;
132}
133
140 const uno::Reference<uno::XComponentContext>& xContext,
141 sal_Int16 const eCoreMeasureUnit,
142 sal_Int16 const eXMLMeasureUnit,
144: m_pImpl(new Impl(xContext, eCoreMeasureUnit, eXMLMeasureUnit, nODFVersion))
145{
146}
147
149{
150}
151
153{
154 sal_Int16 eUnit = util::MeasureUnit::INCH;
155 switch( nFieldUnit )
156 {
157 case FieldUnit::MM:
158 eUnit = util::MeasureUnit::MM;
159 break;
160 case FieldUnit::CM:
161 case FieldUnit::M:
162 case FieldUnit::KM:
163 eUnit = util::MeasureUnit::CM;
164 break;
165 case FieldUnit::TWIP:
166 eUnit = util::MeasureUnit::TWIP;
167 break;
168 case FieldUnit::POINT:
169 case FieldUnit::PICA:
170 eUnit = util::MeasureUnit::POINT;
171 break;
172 case FieldUnit::MM_100TH:
173 eUnit = util::MeasureUnit::MM_100TH;
174 break;
175 case FieldUnit::INCH:
176 eUnit = util::MeasureUnit::INCH;
177 break;
178 default:
179 assert(false);
180 break;
181 }
182 return eUnit;
183}
184
187 std::u16string_view rString,
188 sal_Int32 nMin, sal_Int32 nMax ) const
189{
190 return ::sax::Converter::convertMeasure( nValue, rString,
191 m_pImpl->m_eCoreMeasureUnit,
192 nMin, nMax );
193}
194
197 std::string_view rString,
198 sal_Int32 nMin, sal_Int32 nMax ) const
199{
200 return ::sax::Converter::convertMeasure( nValue, rString,
201 m_pImpl->m_eCoreMeasureUnit,
202 nMin, nMax );
203}
204
206void SvXMLUnitConverter::convertMeasureToXML( OUStringBuffer& rString,
207 sal_Int32 nMeasure ) const
208{
209 ::sax::Converter::convertMeasure( rString, nMeasure,
210 m_pImpl->m_eCoreMeasureUnit,
211 m_pImpl->m_eXMLMeasureUnit );
212}
213
215OUString SvXMLUnitConverter::convertMeasureToXML( sal_Int32 nMeasure ) const
216{
217 OUStringBuffer s;
219 m_pImpl->m_eCoreMeasureUnit,
220 m_pImpl->m_eXMLMeasureUnit );
221 return s.makeStringAndClear();
222}
223
228 std::u16string_view rValue,
230{
231 while( pMap->GetName() )
232 {
233 auto nameLength = pMap->GetNameLength();
234 if( static_cast<sal_Int32>(rValue.size()) == nameLength &&
235 rtl_ustr_asciil_reverseEquals_WithLength(
236 rValue.data(), pMap->GetName(), nameLength ) )
237 {
238 rEnum = pMap->GetValue();
239 return true;
240 }
241 ++pMap;
242 }
243
244 return false;
245}
246
250 sal_uInt16& rEnum,
251 std::u16string_view rValue,
253{
254 while( pMap->GetToken() != XML_TOKEN_INVALID )
255 {
256 if( IsXMLToken( rValue, pMap->GetToken() ) )
257 {
258 rEnum = pMap->GetValue();
259 return true;
260 }
261 ++pMap;
262 }
263 return false;
264}
265
269 sal_uInt16& rEnum,
270 std::string_view rValue,
272{
273 while( pMap->GetToken() != XML_TOKEN_INVALID )
274 {
275 if( IsXMLToken( rValue, pMap->GetToken() ) )
276 {
277 rEnum = pMap->GetValue();
278 return true;
279 }
280 ++pMap;
281 }
282 return false;
283}
284
290 OUStringBuffer& rBuffer,
291 sal_uInt16 nValue,
293 enum XMLTokenEnum eDefault)
294{
295 enum XMLTokenEnum eTok = eDefault;
296
297 while( pMap->GetToken() != XML_TOKEN_INVALID )
298 {
299 if( pMap->GetValue() == nValue )
300 {
301 eTok = pMap->GetToken();
302 break;
303 }
304 ++pMap;
305 }
306
307 // the map may have contained XML_TOKEN_INVALID
308 if( eTok == XML_TOKEN_INVALID )
309 eTok = eDefault;
310
311 if( eTok != XML_TOKEN_INVALID )
312 rBuffer.append( GetXMLToken(eTok) );
313
314 return (eTok != XML_TOKEN_INVALID);
315}
316
317static int lcl_gethex( int nChar )
318{
319 if( nChar >= '0' && nChar <= '9' )
320 return nChar - '0';
321 else if( nChar >= 'a' && nChar <= 'f' )
322 return nChar - 'a' + 10;
323 else if( nChar >= 'A' && nChar <= 'F' )
324 return nChar - 'A' + 10;
325 else
326 return 0;
327}
328
329const char aHexTab[] = "0123456789abcdef";
330
331
333void SvXMLUnitConverter::convertDouble(OUStringBuffer& rBuffer,
334 double fNumber) const
335{
336 ::sax::Converter::convertDouble(rBuffer, fNumber,
337 true/*bWriteUnits*/, m_pImpl->m_eCoreMeasureUnit, m_pImpl->m_eXMLMeasureUnit);
338}
339
342 std::u16string_view rString) const
343{
344 sal_Int16 const eSrcUnit = ::sax::Converter::GetUnitFromString(
345 rString, m_pImpl->m_eCoreMeasureUnit);
346
347 return ::sax::Converter::convertDouble(rValue, rString,
348 eSrcUnit, m_pImpl->m_eCoreMeasureUnit);
349}
350
353 std::string_view rString) const
354{
355 sal_Int16 const eSrcUnit = ::sax::Converter::GetUnitFromString(
356 rString, m_pImpl->m_eCoreMeasureUnit);
357
358 return ::sax::Converter::convertDouble(rValue, rString,
359 eSrcUnit, m_pImpl->m_eCoreMeasureUnit);
360}
361
363bool SvXMLUnitConverter::setNullDate(const css::uno::Reference <css::frame::XModel>& xModel)
364{
365 css::uno::Reference <css::util::XNumberFormatsSupplier> xNumberFormatsSupplier (xModel, css::uno::UNO_QUERY);
366 if (xNumberFormatsSupplier.is())
367 {
368 const css::uno::Reference <css::beans::XPropertySet> xPropertySet = xNumberFormatsSupplier->getNumberFormatSettings();
369 return xPropertySet.is() && (xPropertySet->getPropertyValue(XML_NULLDATE) >>= m_pImpl->m_aNullDate);
370 }
371 return false;
372}
373
375void SvXMLUnitConverter::convertDateTime(OUStringBuffer& rBuffer,
376 const double& fDateTime, bool const bAddTimeIf0AM)
377{
378 convertDateTime(rBuffer, fDateTime, m_pImpl->m_aNullDate, bAddTimeIf0AM);
379}
380
383 std::u16string_view rString) const
384{
385 return convertDateTime(fDateTime, rString, m_pImpl->m_aNullDate);
386}
387
390 std::string_view rString) const
391{
392 return convertDateTime(fDateTime, rString, m_pImpl->m_aNullDate);
393}
394
396void SvXMLUnitConverter::convertDateTime( OUStringBuffer& rBuffer,
397 const double& fDateTime,
398 const css::util::Date& aTempNullDate,
399 bool bAddTimeIf0AM )
400{
401 double fValue = fDateTime;
402 const sal_Int32 nDays = static_cast <sal_Int32> (::rtl::math::approxFloor (fValue));
403 Date aDate (aTempNullDate.Day, aTempNullDate.Month, aTempNullDate.Year);
404 aDate.AddDays( nDays);
405 fValue -= nDays;
406 const bool bHasTime = (fValue > 0.0);
407
408 sal_Int16 nTempYear = aDate.GetYear();
409 assert(nTempYear != 0);
410 if (nTempYear < 0)
411 {
412 rBuffer.append( '-');
413 nTempYear = -nTempYear;
414 }
415 if (nTempYear < 1000)
416 rBuffer.append( '0');
417 if (nTempYear < 100)
418 rBuffer.append( '0');
419 if (nTempYear < 10)
420 rBuffer.append( '0');
421 rBuffer.append( sal_Int32( nTempYear));
422 rBuffer.append( '-');
423 sal_uInt16 nTemp = aDate.GetMonth();
424 assert(1 <= nTemp && nTemp <= 12);
425 if (nTemp < 10)
426 rBuffer.append( '0');
427 rBuffer.append( sal_Int32( nTemp));
428 rBuffer.append( '-');
429 nTemp = aDate.GetDay();
430 assert(1 <= nTemp && nTemp <= 31);
431 if (nTemp < 10)
432 rBuffer.append( '0');
433 rBuffer.append( sal_Int32( nTemp));
434 if (!(bHasTime || bAddTimeIf0AM))
435 return;
436
437 double fCount;
438 if (nDays > 0)
439 fCount = ::rtl::math::approxFloor (log10(static_cast<double>(nDays))) + 1;
440 else if (nDays < 0)
441 fCount = ::rtl::math::approxFloor (log10(static_cast<double>(nDays * -1))) + 1;
442 else
443 fCount = 0.0;
444 const int nDigits = sal_Int16(fCount) + 4; // +4 for *86400 in seconds
445 const int nFractionDecimals = std::max( XML_MAXDIGITSCOUNT_TIME - nDigits, 0);
446
447 sal_uInt16 nHour, nMinute, nSecond;
448 double fFractionOfSecond;
449 // Pass the original date+time value for proper scaling and rounding.
450 tools::Time::GetClock( fDateTime, nHour, nMinute, nSecond, fFractionOfSecond, nFractionDecimals);
451
452 rBuffer.append( 'T');
453 if (nHour < 10)
454 rBuffer.append( '0');
455 rBuffer.append( sal_Int32( nHour));
456 rBuffer.append( ':');
457 if (nMinute < 10)
458 rBuffer.append( '0');
459 rBuffer.append( sal_Int32( nMinute));
460 rBuffer.append( ':');
461 if (nSecond < 10)
462 rBuffer.append( '0');
463 rBuffer.append( sal_Int32( nSecond));
464 if (!nFractionDecimals)
465 return;
466
467 // nFractionDecimals+1 to not round up what GetClock() carefully
468 // truncated.
469 OUString aFraction( ::rtl::math::doubleToUString( fFractionOfSecond,
470 rtl_math_StringFormat_F,
471 nFractionDecimals + 1, '.', true));
472 const sal_Int32 nLen = aFraction.getLength();
473 if ( nLen > 2 )
474 {
475 // Truncate nFractionDecimals+1 digit if it was not rounded to zero.
476 const sal_Int32 nCount = nLen - 2 - static_cast<int>(nLen > nFractionDecimals + 2);
477 rBuffer.append( '.');
478 rBuffer.append( aFraction.subView(2, nCount)); // strip 0.
479 }
480}
481
483template<typename V>
484static bool lcl_convertDateTime( double& fDateTime,
485 V rString, const css::util::Date& aTempNullDate)
486{
487 css::util::DateTime aDateTime;
488 bool bSuccess = ::sax::Converter::parseDateTime(aDateTime, rString);
489
490 if (bSuccess)
491 {
492 const Date aTmpNullDate(aTempNullDate.Day, aTempNullDate.Month, aTempNullDate.Year);
493 const Date aTempDate(aDateTime.Day, aDateTime.Month, aDateTime.Year);
494 const sal_Int32 nTage = aTempDate - aTmpNullDate;
495 double fTempDateTime = nTage;
496 double Hour = aDateTime.Hours;
497 double Min = aDateTime.Minutes;
498 double Sec = aDateTime.Seconds;
499 double NanoSec = aDateTime.NanoSeconds;
500 fTempDateTime += Hour / ::tools::Time::hourPerDay;
501 fTempDateTime += Min / ::tools::Time::minutePerDay;
502 fTempDateTime += Sec / ::tools::Time::secondPerDay;
503 fTempDateTime += NanoSec / ::tools::Time::nanoSecPerDay;
504 fDateTime = fTempDateTime;
505 }
506 return bSuccess;
507}
508
510 std::u16string_view rString, const css::util::Date& aTempNullDate)
511{
512 return lcl_convertDateTime(fDateTime, rString, aTempNullDate);
513}
516 std::string_view rString, const css::util::Date& aTempNullDate)
517{
518 return lcl_convertDateTime(fDateTime, rString, aTempNullDate);
519}
520
521
522SvXMLTokenEnumerator::SvXMLTokenEnumerator( std::u16string_view rString, sal_Unicode cSeparator /* = ' ' */ )
523: maTokenString( rString ), mnNextTokenPos(0), mcSeparator( cSeparator )
524{
525}
526
527bool SvXMLTokenEnumerator::getNextToken( std::u16string_view& rToken )
528{
529 if( std::u16string_view::npos == mnNextTokenPos )
530 return false;
531
532 size_t nTokenEndPos = maTokenString.find( mcSeparator, mnNextTokenPos );
533 if( nTokenEndPos != std::u16string_view::npos )
534 {
535 rToken = maTokenString.substr( mnNextTokenPos,
536 nTokenEndPos - mnNextTokenPos );
537 mnNextTokenPos = nTokenEndPos + 1;
538
539 // if the mnNextTokenPos is at the end of the string, we have
540 // to deliver an empty token
541 if( mnNextTokenPos > maTokenString.size() )
542 mnNextTokenPos = std::u16string_view::npos;
543 }
544 else
545 {
546 rToken = maTokenString.substr( mnNextTokenPos );
547 mnNextTokenPos = std::u16string_view::npos;
548 }
549
550 return true;
551}
552
553static bool lcl_getPositions(std::string_view _sValue, std::string_view& _rContentX, std::string_view& _rContentY, std::string_view& _rContentZ)
554{
555 if(_sValue.empty() || _sValue[0] != '(')
556 return false;
557
558 size_t nPos(1);
559 size_t nFound = _sValue.find(' ', nPos);
560
561 if(nFound == std::string_view::npos || nFound <= nPos)
562 return false;
563
564 _rContentX = _sValue.substr(nPos, nFound - nPos);
565
566 nPos = nFound + 1;
567 nFound = _sValue.find(' ', nPos);
568
569 if(nFound == std::string_view::npos || nFound <= nPos)
570 return false;
571
572 _rContentY = _sValue.substr(nPos, nFound - nPos);
573
574 nPos = nFound + 1;
575 nFound = _sValue.find(')', nPos);
576
577 if(nFound == std::string_view::npos || nFound <= nPos)
578 return false;
579
580 _rContentZ = _sValue.substr(nPos, nFound - nPos);
581 return true;
582
583}
584
586bool SvXMLUnitConverter::convertB3DVector( ::basegfx::B3DVector& rVector, std::string_view rValue )
587{
588 std::string_view aContentX,aContentY,aContentZ;
589 if ( !lcl_getPositions(rValue,aContentX,aContentY,aContentZ) )
590 return false;
591
592 rtl_math_ConversionStatus eStatus;
593
594 rVector.setX(::rtl::math::stringToDouble(aContentX, '.',
595 ',', &eStatus));
596
597 if( eStatus != rtl_math_ConversionStatus_Ok )
598 return false;
599
600 rVector.setY(::rtl::math::stringToDouble(aContentY, '.',
601 ',', &eStatus));
602
603 if( eStatus != rtl_math_ConversionStatus_Ok )
604 return false;
605
606 rVector.setZ(::rtl::math::stringToDouble(aContentZ, '.',
607 ',', &eStatus));
608
609
610 return ( eStatus == rtl_math_ConversionStatus_Ok );
611}
612
614void SvXMLUnitConverter::convertB3DVector( OUStringBuffer &rBuffer, const ::basegfx::B3DVector& rVector )
615{
616 rBuffer.append('(');
617 ::sax::Converter::convertDouble(rBuffer, rVector.getX());
618 rBuffer.append(' ');
619 ::sax::Converter::convertDouble(rBuffer, rVector.getY());
620 rBuffer.append(' ');
621 ::sax::Converter::convertDouble(rBuffer, rVector.getZ());
622 rBuffer.append(')');
623}
624
626bool SvXMLUnitConverter::convertPosition3D( drawing::Position3D& rPosition,
627 std::string_view rValue ) const
628{
629 std::string_view aContentX,aContentY,aContentZ;
630 if ( !lcl_getPositions(rValue,aContentX,aContentY,aContentZ) )
631 return false;
632
633 if ( !convertDouble( rPosition.PositionX, aContentX ) )
634 return false;
635 if ( !convertDouble( rPosition.PositionY, aContentY ) )
636 return false;
637 return convertDouble( rPosition.PositionZ, aContentZ );
638}
639
641void SvXMLUnitConverter::convertPosition3D( OUStringBuffer &rBuffer,
642 const drawing::Position3D& rPosition )
643{
644 rBuffer.append( '(' );
645 convertDouble( rBuffer, rPosition.PositionX );
646 rBuffer.append( ' ' );
647 convertDouble( rBuffer, rPosition.PositionY );
648 rBuffer.append( ' ' );
649 convertDouble( rBuffer, rPosition.PositionZ );
650 rBuffer.append( ')' );
651}
652
654 sal_Int16& rType,
655 const OUString& rNumFmt,
656 std::u16string_view rNumLetterSync,
657 bool bNumberNone ) const
658{
659 bool bRet = true;
660 bool bExt = false;
661
662 sal_Int32 nLen = rNumFmt.getLength();
663 if( 0 == nLen )
664 {
665 if( bNumberNone )
666 rType = NumberingType::NUMBER_NONE;
667 else
668 bRet = false;
669 }
670 else if( 1 == nLen )
671 {
672 switch( rNumFmt[0] )
673 {
674 case '1': rType = NumberingType::ARABIC; break;
675 case 'a': rType = NumberingType::CHARS_LOWER_LETTER; break;
676 case 'A': rType = NumberingType::CHARS_UPPER_LETTER; break;
677 case 'i': rType = NumberingType::ROMAN_LOWER; break;
678 case 'I': rType = NumberingType::ROMAN_UPPER; break;
679 default: bExt = true; break;
680 }
681 if( !bExt && IsXMLToken( rNumLetterSync, XML_TRUE ) )
682 {
683 switch( rType )
684 {
685 case NumberingType::CHARS_LOWER_LETTER:
686 rType = NumberingType::CHARS_LOWER_LETTER_N;
687 break;
688 case NumberingType::CHARS_UPPER_LETTER:
689 rType = NumberingType::CHARS_UPPER_LETTER_N;
690 break;
691 }
692 }
693 }
694 else
695 {
696 bExt = true;
697 }
698 if( bExt )
699 {
701 if( xInfo.is() && xInfo->hasNumberingType( rNumFmt ) )
702 {
703 rType = xInfo->getNumberingType( rNumFmt );
704 }
705 else
706 {
707 rType = NumberingType::ARABIC;
708 }
709 }
710
711 return bRet;
712}
713
714void SvXMLUnitConverter::convertNumFormat( OUStringBuffer& rBuffer,
715 sal_Int16 nType ) const
716{
717 enum XMLTokenEnum eFormat = XML_TOKEN_INVALID;
718 switch( nType )
719 {
720 case NumberingType::CHARS_UPPER_LETTER: eFormat = XML_A_UPCASE; break;
721 case NumberingType::CHARS_LOWER_LETTER: eFormat = XML_A; break;
722 case NumberingType::ROMAN_UPPER: eFormat = XML_I_UPCASE; break;
723 case NumberingType::ROMAN_LOWER: eFormat = XML_I; break;
724 case NumberingType::ARABIC: eFormat = XML_1; break;
725 case NumberingType::CHARS_UPPER_LETTER_N: eFormat = XML_A_UPCASE; break;
726 case NumberingType::CHARS_LOWER_LETTER_N: eFormat = XML_A; break;
727 case NumberingType::NUMBER_NONE: eFormat = XML__EMPTY; break;
728
729 case NumberingType::CHAR_SPECIAL:
730 case NumberingType::PAGE_DESCRIPTOR:
731 case NumberingType::BITMAP:
732 SAL_WARN_IF( eFormat == XML_TOKEN_INVALID, "xmloff", "invalid number format" );
733 break;
734 default:
735 break;
736 }
737
738 if( eFormat != XML_TOKEN_INVALID )
739 {
740 rBuffer.append( GetXMLToken(eFormat) );
741 }
742 else
743 {
745 if( xInfo.is() )
746 rBuffer.append( xInfo->getNumberingIdentifier( nType ) );
747 }
748}
749
750void SvXMLUnitConverter::convertNumLetterSync( OUStringBuffer& rBuffer,
751 sal_Int16 nType )
752{
753 enum XMLTokenEnum eSync = XML_TOKEN_INVALID;
754 switch( nType )
755 {
756 case NumberingType::CHARS_UPPER_LETTER:
757 case NumberingType::CHARS_LOWER_LETTER:
758 case NumberingType::ROMAN_UPPER:
759 case NumberingType::ROMAN_LOWER:
760 case NumberingType::ARABIC:
761 case NumberingType::NUMBER_NONE:
762 break;
763
764 case NumberingType::CHARS_UPPER_LETTER_N:
765 case NumberingType::CHARS_LOWER_LETTER_N:
766 eSync = XML_TRUE;
767 break;
768
769 case NumberingType::CHAR_SPECIAL:
770 case NumberingType::PAGE_DESCRIPTOR:
771 case NumberingType::BITMAP:
772 SAL_WARN_IF( eSync == XML_TOKEN_INVALID, "xmloff", "invalid number format" );
773 break;
774 }
775 if( eSync != XML_TOKEN_INVALID )
776 rBuffer.append( GetXMLToken(eSync) );
777}
778
779void SvXMLUnitConverter::convertPropertySet(uno::Sequence<beans::PropertyValue>& rProps,
780 const uno::Reference<beans::XPropertySet>& aProperties)
781{
782 uno::Reference< beans::XPropertySetInfo > xPropertySetInfo = aProperties->getPropertySetInfo();
783 if (!xPropertySetInfo.is())
784 return;
785
786 const uno::Sequence< beans::Property > aProps = xPropertySetInfo->getProperties();
787 if (aProps.hasElements())
788 {
789 rProps.realloc(aProps.getLength());
790 beans::PropertyValue* pProps = rProps.getArray();
791 for (const auto& rProp : aProps)
792 {
793 pProps->Name = rProp.Name;
794 pProps->Value = aProperties->getPropertyValue(rProp.Name);
795 ++pProps;
796 }
797 }
798}
799
800void SvXMLUnitConverter::convertPropertySet(uno::Reference<beans::XPropertySet> const & rProperties,
801 const uno::Sequence<beans::PropertyValue>& aProps)
802{
803 if (aProps.hasElements())
804 {
805 uno::Reference< beans::XPropertySetInfo > xPropertySetInfo = rProperties->getPropertySetInfo();
806 if (xPropertySetInfo.is())
807 {
808 for (const auto& rProp : aProps)
809 {
810 if (xPropertySetInfo->hasPropertyByName(rProp.Name))
811 rProperties->setPropertyValue(rProp.Name, rProp.Value);
812 }
813 }
814 }
815}
816
817
819 const OUString& rName,
820 bool *pEncoded ) const
821{
822 if( pEncoded )
823 *pEncoded = false;
824
825 sal_Int32 nLen = rName.getLength();
826 OUStringBuffer aBuffer( nLen*2 );
827
828 for( sal_Int32 i = 0; i < nLen; i++ )
829 {
830 sal_Unicode c = rName[i];
831 bool bValidChar = false;
832 if( c < 0x00ffU )
833 {
834 bValidChar =
835 (c >= 0x0041 && c <= 0x005a) ||
836 (c >= 0x0061 && c <= 0x007a) ||
837 (c >= 0x00c0 && c <= 0x00d6) ||
838 (c >= 0x00d8 && c <= 0x00f6) ||
839 (c >= 0x00f8 && c <= 0x00ff) ||
840 ( i > 0 && ( (c >= 0x0030 && c <= 0x0039) ||
841 c == 0x00b7 || c == '-' || c == '.') );
842 }
843 else
844 {
845 if( (c >= 0xf900U && c <= 0xfffeU) ||
846 (c >= 0x20ddU && c <= 0x20e0U))
847 {
848 bValidChar = false;
849 }
850 else if( (c >= 0x02bbU && c <= 0x02c1U) || c == 0x0559 ||
851 c == 0x06e5 || c == 0x06e6 )
852 {
853 bValidChar = true;
854 }
855 else if( c == 0x0387 )
856 {
857 bValidChar = i > 0;
858 }
859 else
860 {
861 if (!m_pImpl->m_xCharClass.is())
862 {
863 m_pImpl->m_xCharClass = CharacterClassification::create( m_pImpl->m_xContext );
864 }
865 sal_Int16 nType = m_pImpl->m_xCharClass->getType(rName, i);
866
867 switch( nType )
868 {
869 case UnicodeType::UPPERCASE_LETTER: // Lu
870 case UnicodeType::LOWERCASE_LETTER: // Ll
871 case UnicodeType::TITLECASE_LETTER: // Lt
872 case UnicodeType::OTHER_LETTER: // Lo
873 case UnicodeType::LETTER_NUMBER: // Nl
874 bValidChar = true;
875 break;
876 case UnicodeType::NON_SPACING_MARK: // Ms
877 case UnicodeType::ENCLOSING_MARK: // Me
878 case UnicodeType::COMBINING_SPACING_MARK: //Mc
879 case UnicodeType::MODIFIER_LETTER: // Lm
880 case UnicodeType::DECIMAL_DIGIT_NUMBER: // Nd
881 bValidChar = i > 0;
882 break;
883 }
884 }
885 }
886 if( bValidChar )
887 {
888 aBuffer.append( c );
889 }
890 else
891 {
892 aBuffer.append( '_' );
893 if( c > 0x0fff )
894 aBuffer.append( static_cast< sal_Unicode >(
895 aHexTab[ (c >> 12) & 0x0f ] ) );
896 if( c > 0x00ff )
897 aBuffer.append( static_cast< sal_Unicode >(
898 aHexTab[ (c >> 8) & 0x0f ] ) );
899 if( c > 0x000f )
900 aBuffer.append( static_cast< sal_Unicode >(
901 aHexTab[ (c >> 4) & 0x0f ] ) );
902 aBuffer.append( static_cast< sal_Unicode >(
903 aHexTab[ c & 0x0f ] ) );
904 aBuffer.append( '_' );
905 if( pEncoded )
906 *pEncoded = true;
907 }
908 }
909
910 // check for length
911 if( aBuffer.getLength() > ((1<<15)-1) )
912 {
913 aBuffer = rName;
914 if( pEncoded )
915 *pEncoded = false;
916 }
917
918
919 return aBuffer.makeStringAndClear();
920}
921
923bool SvXMLUnitConverter::convertHex( sal_uInt32& nVal, std::u16string_view rValue )
924{
925 if( rValue.size() != 8 )
926 return false;
927
928 nVal = 0;
929 for ( int i = 0; i < 8; i++ )
930 {
931 nVal = ( nVal << 4 )
932 | sal::static_int_cast< sal_uInt32 >( lcl_gethex( rValue[i] ) );
933 }
934
935 return true;
936}
937
939void SvXMLUnitConverter::convertHex( OUStringBuffer& rBuffer,
940 sal_uInt32 nVal )
941{
942 for ( int i = 0; i < 8; i++ )
943 {
944 rBuffer.append( sal_Unicode( aHexTab[ nVal >> 28 ] ) );
945 nVal <<= 4;
946 }
947}
948
949/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
PropertiesInfo aProperties
void AddDays(sal_Int32 nAddDays)
sal_Int16 GetYear() const
sal_uInt16 GetDay() const
sal_uInt16 GetMonth() const
std::u16string_view maTokenString
Definition: xmluconv.hxx:59
bool getNextToken(std::u16string_view &rToken)
Definition: xmluconv.cxx:527
sal_Unicode mcSeparator
Definition: xmluconv.hxx:61
SvXMLTokenEnumerator(std::u16string_view rString, sal_Unicode cSeparator=u' ')
Definition: xmluconv.cxx:522
bool convertPosition3D(css::drawing::Position3D &rPosition, std::string_view rValue) const
convert string to Position3D
SvtSaveOptions::ODFSaneDefaultVersion getSaneDefaultVersion() const
ODF version, only when exporting.
Definition: xmluconv.cxx:123
bool convertNumFormat(sal_Int16 &rType, const OUString &rNumFormat, std::u16string_view rNumLetterSync, bool bNumberNone=false) const
convert num-format and num-letter-sync values to NumberingType
Definition: xmluconv.cxx:653
struct SAL_DLLPRIVATE Impl
Definition: xmluconv.hxx:88
bool convertMeasureToCore(sal_Int32 &rValue, std::u16string_view rString, sal_Int32 nMin=SAL_MIN_INT32, sal_Int32 nMax=SAL_MAX_INT32) const
convert string to measure with meCoreMeasureUnit, using optional min and max values
Definition: xmluconv.cxx:186
SvXMLUnitConverter(const SvXMLUnitConverter &)=delete
void convertDateTime(OUStringBuffer &rBuffer, const double &fDateTime, bool const bAddTimeIf0AM=false)
convert double to ISO Date Time String
Definition: xmluconv.cxx:375
OUString encodeStyleName(const OUString &rName, bool *pEncoded=nullptr) const
Definition: xmluconv.cxx:818
void SetCoreMeasureUnit(sal_Int16 const eCoreMeasureUnit)
sets the default unit for numerical measures
Definition: xmluconv.cxx:108
static void convertPropertySet(css::uno::Sequence< css::beans::PropertyValue > &rProps, const css::uno::Reference< css::beans::XPropertySet > &aProperties)
void SetXMLMeasureUnit(sal_Int16 const eXMLMeasureUnit)
sets the default unit for textual measures
Definition: xmluconv.cxx:113
static bool convertHex(sal_uInt32 &nVal, std::u16string_view rValue)
convert string (hex) to number (sal_uInt32)
Definition: xmluconv.cxx:923
::std::unique_ptr< Impl > m_pImpl
Definition: xmluconv.hxx:89
static sal_Int16 GetMeasureUnit(FieldUnit const nFieldUnit)
Definition: xmluconv.cxx:152
sal_Int16 GetXMLMeasureUnit() const
gets the default unit for textual measures
Definition: xmluconv.cxx:118
void convertDouble(OUStringBuffer &rBuffer, double fNumber) const
convert double number to string (using ::rtl::math) and DO convert to export MapUnit using meCoreMeas...
Definition: xmluconv.cxx:333
bool setNullDate(const css::uno::Reference< css::frame::XModel > &xModel)
get the Null Date of the XModel and set it to the UnitConverter
Definition: xmluconv.cxx:363
static bool convertB3DVector(::basegfx::B3DVector &rVector, std::string_view rValue)
convert string to basegfx::B3DVector
Definition: xmluconv.cxx:586
void convertMeasureToXML(OUStringBuffer &rBuffer, sal_Int32 nMeasure) const
convert measure to string: from meCoreMeasureUnit to meXMLMeasureUnit
Definition: xmluconv.cxx:206
void overrideSaneDefaultVersion(SvtSaveOptions::ODFSaneDefaultVersion const)
Definition: xmluconv.cxx:128
static void convertNumLetterSync(OUStringBuffer &rBuffer, sal_Int16 nType)
Definition: xmluconv.cxx:750
static bool convertEnumImpl(sal_uInt16 &rEnum, std::u16string_view rValue, const SvXMLEnumMapEntry< sal_uInt16 > *pMap)
convert string to enum using given token map, if the enum is not found in the map,...
Definition: xmluconv.cxx:249
const css::uno::Reference< css::text::XNumberingTypeInfo > & getNumTypeInfo() const
gets XNumberingTypeInfo
Definition: xmluconv.cxx:99
void setX(TYPE fX)
void setY(TYPE fY)
void setZ(TYPE fZ)
static void convertDouble(OUStringBuffer &rBuffer, double fNumber, bool bWriteUnits, sal_Int16 nSourceUnit, sal_Int16 nTargetUnit)
static bool convertMeasure(sal_Int32 &rValue, std::u16string_view rString, sal_Int16 nTargetUnit=css::util::MeasureUnit::MM_100TH, sal_Int32 nMin=SAL_MIN_INT32, sal_Int32 nMax=SAL_MAX_INT32)
static bool parseDateTime(css::util::DateTime &rDateTime, std::u16string_view rString)
static sal_Int16 GetUnitFromString(std::u16string_view rString, sal_Int16 nDefaultUnit)
static const sal_Int64 nanoSecPerDay
static void GetClock(double fTimeInDays, sal_uInt16 &nHour, sal_uInt16 &nMinute, sal_uInt16 &nSecond, double &fFractionOfSecond, int nFractionDecimals)
static const sal_Int64 minutePerDay
static const sal_Int64 hourPerDay
static const sal_Int64 secondPerDay
int nCount
float u
FieldUnit
sal_Int16 nValue
sal_uInt16 nPos
#define SAL_WARN_IF(condition, area, stream)
int i
Handling of tokens in XML:
XMLTokenEnum
The enumeration of all XML tokens.
Definition: xmltoken.hxx:50
bool IsXMLToken(std::u16string_view rString, enum XMLTokenEnum eToken)
compare eToken to the string
Definition: xmltoken.cxx:3573
const OUString & GetXMLToken(enum XMLTokenEnum eToken)
return the OUString representation for eToken
Definition: xmltoken.cxx:3517
QPRO_FUNC_TYPE nType
Map a const char* (with length) to a sal_uInt16 value.
Definition: xmlement.hxx:71
EnumT GetValue() const
Definition: xmlement.hxx:81
const char * GetName() const
Definition: xmlement.hxx:79
sal_Int32 GetNameLength() const
Definition: xmlement.hxx:80
sal_Int16 m_eCoreMeasureUnit
Definition: xmluconv.cxx:67
uno::Reference< uno::XComponentContext > m_xContext
Definition: xmluconv.cxx:73
uno::Reference< text::XNumberingTypeInfo > m_xNumTypeInfo
Definition: xmluconv.cxx:71
uno::Reference< i18n::XCharacterClassification > m_xCharClass
Definition: xmluconv.cxx:72
Impl(uno::Reference< uno::XComponentContext > const &xContext, sal_Int16 const eCoreMeasureUnit, sal_Int16 const eXMLMeasureUnit, SvtSaveOptions::ODFSaneDefaultVersion const nODFVersion)
Definition: xmluconv.cxx:75
void createNumTypeInfo() const
Definition: xmluconv.cxx:92
sal_Int16 m_eXMLMeasureUnit
Definition: xmluconv.cxx:68
SvtSaveOptions::ODFSaneDefaultVersion m_eODFVersion
Definition: xmluconv.cxx:69
Reference< XModel > xModel
sal_uInt16 sal_Unicode
signed char sal_Int8
std::unique_ptr< char[]> aBuffer
const char aHexTab[]
Definition: xmluconv.cxx:329
constexpr OUStringLiteral XML_NULLDATE
Definition: xmluconv.cxx:63
static bool lcl_convertDateTime(double &fDateTime, V rString, const css::util::Date &aTempNullDate)
convert ISO Date Time String to double
Definition: xmluconv.cxx:484
const sal_Int8 XML_MAXDIGITSCOUNT_TIME
Definition: xmluconv.cxx:62
static int lcl_gethex(int nChar)
Definition: xmluconv.cxx:317
static bool lcl_getPositions(std::string_view _sValue, std::string_view &_rContentX, std::string_view &_rContentY, std::string_view &_rContentZ)
Definition: xmluconv.cxx:553