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