22 #include <string_view>
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>
33 #include <rtl/math.hxx>
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>
63 #define XML_NULLDATE "NullDate"
71 mutable uno::Reference< i18n::XCharacterClassification >
m_xCharClass;
74 Impl(uno::Reference<uno::XComponentContext>
const& xContext,
75 sal_Int16
const eCoreMeasureUnit,
76 sal_Int16
const eXMLMeasureUnit)
77 : m_eCoreMeasureUnit(eCoreMeasureUnit)
78 , m_eXMLMeasureUnit(eXMLMeasureUnit)
79 , m_aNullDate(30, 12, 1899)
80 , m_xContext(xContext)
82 OSL_ENSURE( m_xContext.is(),
"got no service manager" );
85 void createNumTypeInfo()
const;
92 m_xNumTypeInfo.set(xDefNum, uno::UNO_QUERY);
95 const uno::Reference< text::XNumberingTypeInfo >&
98 if (!
m_pImpl->m_xNumTypeInfo.is())
102 return m_pImpl->m_xNumTypeInfo;
107 m_pImpl->m_eCoreMeasureUnit = eCoreMeasureUnit;
112 m_pImpl->m_eXMLMeasureUnit = eXMLMeasureUnit;
117 return m_pImpl->m_eXMLMeasureUnit;
126 const uno::Reference<uno::XComponentContext>& xContext,
127 sal_Int16
const eCoreMeasureUnit,
128 sal_Int16
const eXMLMeasureUnit)
129 :
m_pImpl(new Impl(xContext, eCoreMeasureUnit, eXMLMeasureUnit))
139 sal_Int16 eUnit = util::MeasureUnit::INCH;
143 eUnit = util::MeasureUnit::MM;
148 eUnit = util::MeasureUnit::CM;
150 case FieldUnit::TWIP:
151 eUnit = util::MeasureUnit::TWIP;
153 case FieldUnit::POINT:
154 case FieldUnit::PICA:
155 eUnit = util::MeasureUnit::POINT;
157 case FieldUnit::MM_100TH:
158 eUnit = util::MeasureUnit::MM_100TH;
160 case FieldUnit::INCH:
161 eUnit = util::MeasureUnit::INCH;
172 std::u16string_view rString,
173 sal_Int32 nMin, sal_Int32 nMax )
const
175 return ::sax::Converter::convertMeasure( nValue, rString,
182 std::string_view rString,
183 sal_Int32 nMin, sal_Int32 nMax )
const
185 return ::sax::Converter::convertMeasure( nValue, rString,
192 sal_Int32 nMeasure )
const
206 return s.makeStringAndClear();
213 std::u16string_view
rValue,
219 if( static_cast<sal_Int32>(rValue.size()) == nameLength &&
220 rtl_ustr_asciil_reverseEquals_WithLength(
221 rValue.data(), pMap->
GetName(), nameLength ) )
236 std::u16string_view
rValue,
243 rEnum = pMap->GetValue();
262 rEnum = pMap->GetValue();
275 OUStringBuffer& rBuffer,
284 if( pMap->GetValue() == nValue )
286 eTok = pMap->GetToken();
304 if( nChar >=
'0' && nChar <=
'9' )
306 else if( nChar >=
'a' && nChar <=
'f' )
307 return nChar -
'a' + 10;
308 else if( nChar >=
'A' && nChar <=
'F' )
309 return nChar -
'A' + 10;
319 double fNumber)
const
327 std::u16string_view rString)
const
330 rString,
m_pImpl->m_eCoreMeasureUnit);
332 return ::sax::Converter::convertDouble(rValue, rString,
333 eSrcUnit,
m_pImpl->m_eCoreMeasureUnit);
339 css::uno::Reference <css::util::XNumberFormatsSupplier> xNumberFormatsSupplier (xModel, css::uno::UNO_QUERY);
340 if (xNumberFormatsSupplier.is())
342 const css::uno::Reference <css::beans::XPropertySet> xPropertySet = xNumberFormatsSupplier->getNumberFormatSettings();
343 return xPropertySet.is() && (xPropertySet->getPropertyValue(
XML_NULLDATE) >>=
m_pImpl->m_aNullDate);
350 const double& fDateTime,
bool const bAddTimeIf0AM)
357 std::u16string_view rString)
364 std::string_view rString)
371 const double& fDateTime,
372 const css::util::Date& aTempNullDate,
375 double fValue = fDateTime;
376 const sal_Int32 nDays = static_cast <sal_Int32> (::rtl::math::approxFloor (fValue));
377 Date aDate (aTempNullDate.Day, aTempNullDate.Month, aTempNullDate.Year);
378 aDate.AddDays( nDays);
380 const bool bHasTime = (fValue > 0.0);
382 sal_Int16 nTempYear = aDate.GetYear();
386 rBuffer.append(
'-');
387 nTempYear = -nTempYear;
389 if (nTempYear < 1000)
390 rBuffer.append(
'0');
392 rBuffer.append(
'0');
394 rBuffer.append(
'0');
395 rBuffer.append( sal_Int32( nTempYear));
396 rBuffer.append(
'-');
397 sal_uInt16 nTemp = aDate.GetMonth();
398 assert(1 <= nTemp && nTemp <= 12);
400 rBuffer.append(
'0');
401 rBuffer.append( sal_Int32( nTemp));
402 rBuffer.append(
'-');
403 nTemp = aDate.GetDay();
404 assert(1 <= nTemp && nTemp <= 31);
406 rBuffer.append(
'0');
407 rBuffer.append( sal_Int32( nTemp));
408 if (!(bHasTime || bAddTimeIf0AM))
413 fCount = ::rtl::math::approxFloor (log10(static_cast<double>(nDays))) + 1;
415 fCount = ::rtl::math::approxFloor (log10(static_cast<double>(nDays * -1))) + 1;
418 const int nDigits = sal_Int16(fCount) + 4;
421 sal_uInt16 nHour, nMinute, nSecond;
422 double fFractionOfSecond;
426 rBuffer.append(
'T');
428 rBuffer.append(
'0');
429 rBuffer.append( sal_Int32( nHour));
430 rBuffer.append(
':');
432 rBuffer.append(
'0');
433 rBuffer.append( sal_Int32( nMinute));
434 rBuffer.append(
':');
436 rBuffer.append(
'0');
437 rBuffer.append( sal_Int32( nSecond));
438 if (!nFractionDecimals)
443 OUString aFraction( ::rtl::math::doubleToUString( fFractionOfSecond,
444 rtl_math_StringFormat_F,
445 nFractionDecimals + 1,
'.',
true));
446 const sal_Int32 nLen = aFraction.getLength();
450 const sal_Int32
nCount = nLen - 2 -
static_cast<int>(nLen > nFractionDecimals + 2);
451 rBuffer.append(
'.');
452 rBuffer.append( aFraction.subView(2, nCount));
459 V rString,
const css::util::Date& aTempNullDate)
461 css::util::DateTime aDateTime;
466 const Date aTmpNullDate(aTempNullDate.Day, aTempNullDate.Month, aTempNullDate.Year);
467 const Date aTempDate(aDateTime.Day, aDateTime.Month, aDateTime.Year);
468 const sal_Int32 nTage = aTempDate - aTmpNullDate;
469 double fTempDateTime = nTage;
470 double Hour = aDateTime.Hours;
471 double Min = aDateTime.Minutes;
472 double Sec = aDateTime.Seconds;
473 double NanoSec = aDateTime.NanoSeconds;
478 fDateTime = fTempDateTime;
484 std::u16string_view rString,
const css::util::Date& aTempNullDate)
490 std::string_view rString,
const css::util::Date& aTempNullDate)
497 : maTokenString( rString ), mnNextTokenPos(0), mcSeparator( cSeparator )
507 if( nTokenEndPos != std::u16string_view::npos )
527 static bool lcl_getPositions(std::u16string_view _sValue, OUString& _rContentX, OUString& _rContentY, OUString& _rContentZ)
529 if(_sValue.empty() || _sValue[0] !=
'(')
533 size_t nFound = _sValue.find(
' ', nPos);
535 if(nFound == std::u16string_view::npos || nFound <= nPos)
538 _rContentX = _sValue.substr(nPos, nFound - nPos);
541 nFound = _sValue.find(
' ', nPos);
543 if(nFound == std::u16string_view::npos || nFound <= nPos)
546 _rContentY = _sValue.substr(nPos, nFound - nPos);
549 nFound = _sValue.find(
')', nPos);
551 if(nFound == std::u16string_view::npos || nFound <= nPos)
554 _rContentZ = _sValue.substr(nPos, nFound - nPos);
558 static bool lcl_getPositions(std::string_view _sValue,OUString& _rContentX,OUString& _rContentY,OUString& _rContentZ)
560 if(_sValue.empty() || _sValue[0] !=
'(')
564 size_t nFound = _sValue.find(
' ', nPos);
566 if(nFound == std::string_view::npos || nFound <= nPos)
569 _rContentX = OUString::fromUtf8(_sValue.substr(nPos, nFound - nPos));
572 nFound = _sValue.find(
' ', nPos);
574 if(nFound == std::string_view::npos || nFound <= nPos)
577 _rContentY = OUString::fromUtf8(_sValue.substr(nPos, nFound - nPos));
580 nFound = _sValue.find(
')', nPos);
582 if(nFound == std::string_view::npos || nFound <= nPos)
585 _rContentZ = OUString::fromUtf8(_sValue.substr(nPos, nFound - nPos));
593 OUString aContentX,aContentY,aContentZ;
597 rtl_math_ConversionStatus eStatus;
599 rVector.setX(::rtl::math::stringToDouble(aContentX,
'.',
602 if( eStatus != rtl_math_ConversionStatus_Ok )
605 rVector.setY(::rtl::math::stringToDouble(aContentY,
'.',
608 if( eStatus != rtl_math_ConversionStatus_Ok )
611 rVector.setZ(::rtl::math::stringToDouble(aContentZ,
'.',
615 return ( eStatus == rtl_math_ConversionStatus_Ok );
621 OUString aContentX,aContentY,aContentZ;
625 rtl_math_ConversionStatus eStatus;
627 rVector.setX(::rtl::math::stringToDouble(aContentX,
'.',
630 if( eStatus != rtl_math_ConversionStatus_Ok )
633 rVector.setY(::rtl::math::stringToDouble(aContentY,
'.',
636 if( eStatus != rtl_math_ConversionStatus_Ok )
639 rVector.setZ(::rtl::math::stringToDouble(aContentZ,
'.',
643 return ( eStatus == rtl_math_ConversionStatus_Ok );
662 OUString aContentX,aContentY,aContentZ;
675 const drawing::Position3D& rPosition )
677 rBuffer.append(
'(' );
679 rBuffer.append(
' ' );
681 rBuffer.append(
' ' );
683 rBuffer.append(
')' );
688 const OUString& rNumFmt,
689 std::u16string_view rNumLetterSync,
690 bool bNumberNone )
const
695 sal_Int32 nLen = rNumFmt.getLength();
699 rType = NumberingType::NUMBER_NONE;
707 case '1': rType = NumberingType::ARABIC;
break;
708 case 'a': rType = NumberingType::CHARS_LOWER_LETTER;
break;
709 case 'A': rType = NumberingType::CHARS_UPPER_LETTER;
break;
710 case 'i': rType = NumberingType::ROMAN_LOWER;
break;
711 case 'I': rType = NumberingType::ROMAN_UPPER;
break;
712 default: bExt =
true;
break;
718 case NumberingType::CHARS_LOWER_LETTER:
719 rType = NumberingType::CHARS_LOWER_LETTER_N;
721 case NumberingType::CHARS_UPPER_LETTER:
722 rType = NumberingType::CHARS_UPPER_LETTER_N;
734 if( xInfo.is() && xInfo->hasNumberingType( rNumFmt ) )
736 rType = xInfo->getNumberingType( rNumFmt );
740 rType = NumberingType::ARABIC;
748 sal_Int16 nType )
const
753 case NumberingType::CHARS_UPPER_LETTER: eFormat =
XML_A_UPCASE;
break;
754 case NumberingType::CHARS_LOWER_LETTER: eFormat =
XML_A;
break;
755 case NumberingType::ROMAN_UPPER: eFormat =
XML_I_UPCASE;
break;
756 case NumberingType::ROMAN_LOWER: eFormat =
XML_I;
break;
757 case NumberingType::ARABIC: eFormat =
XML_1;
break;
758 case NumberingType::CHARS_UPPER_LETTER_N: eFormat =
XML_A_UPCASE;
break;
759 case NumberingType::CHARS_LOWER_LETTER_N: eFormat =
XML_A;
break;
760 case NumberingType::NUMBER_NONE: eFormat =
XML__EMPTY;
break;
762 case NumberingType::CHAR_SPECIAL:
763 case NumberingType::PAGE_DESCRIPTOR:
764 case NumberingType::BITMAP:
779 rBuffer.append( xInfo->getNumberingIdentifier( nType ) );
789 case NumberingType::CHARS_UPPER_LETTER:
790 case NumberingType::CHARS_LOWER_LETTER:
791 case NumberingType::ROMAN_UPPER:
792 case NumberingType::ROMAN_LOWER:
793 case NumberingType::ARABIC:
794 case NumberingType::NUMBER_NONE:
797 case NumberingType::CHARS_UPPER_LETTER_N:
798 case NumberingType::CHARS_LOWER_LETTER_N:
802 case NumberingType::CHAR_SPECIAL:
803 case NumberingType::PAGE_DESCRIPTOR:
804 case NumberingType::BITMAP:
813 const uno::Reference<beans::XPropertySet>& aProperties)
815 uno::Reference< beans::XPropertySetInfo > xPropertySetInfo = aProperties->getPropertySetInfo();
816 if (!xPropertySetInfo.is())
819 const uno::Sequence< beans::Property > aProps = xPropertySetInfo->getProperties();
820 if (aProps.hasElements())
822 rProps.realloc(aProps.getLength());
823 beans::PropertyValue* pProps = rProps.getArray();
824 for (
const auto& rProp : aProps)
826 pProps->Name = rProp.Name;
827 pProps->Value = aProperties->getPropertyValue(rProp.Name);
834 const uno::Sequence<beans::PropertyValue>& aProps)
836 if (aProps.hasElements())
838 uno::Reference< beans::XPropertySetInfo > xPropertySetInfo = rProperties->getPropertySetInfo();
839 if (xPropertySetInfo.is())
841 for (
const auto& rProp : aProps)
843 if (xPropertySetInfo->hasPropertyByName(rProp.Name))
844 rProperties->setPropertyValue(rProp.Name, rProp.Value);
852 const OUString& rName,
853 bool *pEncoded )
const
858 sal_Int32 nLen = rName.getLength();
859 OUStringBuffer
aBuffer( nLen*2 );
861 for( sal_Int32
i = 0;
i < nLen;
i++ )
864 bool bValidChar =
false;
868 (c >= 0x0041 && c <= 0x005a) ||
869 (c >= 0x0061 && c <= 0x007a) ||
870 (c >= 0x00c0 && c <= 0x00d6) ||
871 (c >= 0x00d8 && c <= 0x00f6) ||
872 (c >= 0x00f8 && c <= 0x00ff) ||
873 (
i > 0 && ( (c >= 0x0030 && c <= 0x0039) ||
874 c == 0x00b7 || c ==
'-' || c ==
'.') );
878 if( (c >= 0xf900U && c <= 0xfffeU) ||
879 (c >= 0x20dd
U && c <= 0x20e0
U))
883 else if( (c >= 0x02bbU && c <= 0x02c1U) || c == 0x0559 ||
884 c == 0x06e5 || c == 0x06e6 )
888 else if( c == 0x0387 )
894 if (!
m_pImpl->m_xCharClass.is())
896 m_pImpl->m_xCharClass = CharacterClassification::create(
m_pImpl->m_xContext );
902 case UnicodeType::UPPERCASE_LETTER:
903 case UnicodeType::LOWERCASE_LETTER:
904 case UnicodeType::TITLECASE_LETTER:
905 case UnicodeType::OTHER_LETTER:
906 case UnicodeType::LETTER_NUMBER:
909 case UnicodeType::NON_SPACING_MARK:
910 case UnicodeType::ENCLOSING_MARK:
911 case UnicodeType::COMBINING_SPACING_MARK:
912 case UnicodeType::MODIFIER_LETTER:
913 case UnicodeType::DECIMAL_DIGIT_NUMBER:
925 aBuffer.append(
'_' );
927 aBuffer.append( static_cast< sal_Unicode >(
928 aHexTab[ (c >> 12) & 0x0f ] ) );
930 aBuffer.append( static_cast< sal_Unicode >(
931 aHexTab[ (c >> 8) & 0x0f ] ) );
933 aBuffer.append( static_cast< sal_Unicode >(
934 aHexTab[ (c >> 4) & 0x0f ] ) );
935 aBuffer.append( static_cast< sal_Unicode >(
936 aHexTab[ c & 0x0f ] ) );
937 aBuffer.append(
'_' );
944 if( aBuffer.getLength() > ((1<<15)-1) )
952 return aBuffer.makeStringAndClear();
958 if( rValue.size() != 8 )
962 for (
int i = 0;
i < 8;
i++ )
965 | sal::static_int_cast< sal_uInt32 >(
lcl_gethex( rValue[
i] ) );
975 for (
int i = 0;
i < 8;
i++ )
977 rBuffer.append(
sal_Unicode( aHexTab[ nVal >> 28 ] ) );
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 ...
void convertDouble(OUStringBuffer &rBuffer, double fNumber) const
convert double number to string (using ::rtl::math) and DO convert to export MapUnit using meCoreMeas...
sal_Int16 GetXMLMeasureUnit() const
gets the default unit for textual measures
static int lcl_gethex(int nChar)
std::u16string_view maTokenString
static bool convertB3DVector(::basegfx::B3DVector &rVector, std::u16string_view rValue)
convert string to basegfx::B3DVector
void SetXMLMeasureUnit(sal_Int16 const eXMLMeasureUnit)
sets the default unit for textual measures
bool IsXMLToken(std::u16string_view rString, enum XMLTokenEnum eToken)
compare eToken to the string
static bool parseDateTime(css::util::DateTime &rDateTime, std::u16string_view rString)
uno::Reference< text::XNumberingTypeInfo > m_xNumTypeInfo
sal_Int16 m_eCoreMeasureUnit
static void convertDouble(OUStringBuffer &rBuffer, double fNumber, bool bWriteUnits, sal_Int16 nSourceUnit, sal_Int16 nTargetUnit)
css::uno::Any const & rValue
void SetCoreMeasureUnit(sal_Int16 const eCoreMeasureUnit)
sets the default unit for numerical measures
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
XMLTokenEnum
The enumeration of all XML tokens.
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
SvXMLTokenEnumerator(std::u16string_view rString, sal_Unicode cSeparator=u' ')
Map a const char* (with length) to a sal_uInt16 value.
uno::Reference< uno::XComponentContext > m_xContext
const char * GetName() const
bool getNextToken(std::u16string_view &rToken)
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)
void convertDateTime(OUStringBuffer &rBuffer, const double &fDateTime, bool const bAddTimeIf0AM=false)
convert double to ISO Date Time String
sal_Int16 m_eXMLMeasureUnit
bool setNullDate(const css::uno::Reference< css::frame::XModel > &xModel)
get the Null Date of the XModel and set it to the UnitConverter
const uno::Reference< uno::XComponentContext > m_xContext
bool convertPosition3D(css::drawing::Position3D &rPosition, std::string_view rValue)
convert string to Position3D
static bool lcl_convertDateTime(double &fDateTime, V rString, const css::util::Date &aTempNullDate)
convert ISO Date Time String to double
static void convertNumLetterSync(OUStringBuffer &rBuffer, sal_Int16 nType)
std::unique_ptr< char[]> aBuffer
static sal_Int16 GetMeasureUnit(FieldUnit const nFieldUnit)
static bool lcl_getPositions(std::u16string_view _sValue, OUString &_rContentX, OUString &_rContentY, OUString &_rContentZ)
#define SAL_WARN_IF(condition, area, stream)
const OUString & GetXMLToken(enum XMLTokenEnum eToken)
return the OUString representation for eToken
Impl(uno::Reference< uno::XComponentContext > const &xContext, sal_Int16 const eCoreMeasureUnit, sal_Int16 const eXMLMeasureUnit)
const sal_Int8 XML_MAXDIGITSCOUNT_TIME
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, this method will return false
Handling of tokens in XML:
static sal_Int16 GetUnitFromString(std::u16string_view rString, sal_Int16 nDefaultUnit)
uno::Reference< i18n::XCharacterClassification > m_xCharClass
static void convertPropertySet(css::uno::Sequence< css::beans::PropertyValue > &rProps, const css::uno::Reference< css::beans::XPropertySet > &aProperties)
OUString encodeStyleName(const OUString &rName, bool *pEncoded=nullptr) const
sal_Int32 GetNameLength() const
const css::uno::Reference< css::text::XNumberingTypeInfo > & getNumTypeInfo() const
gets XNumberingTypeInfo
SvXMLUnitConverter(const SvXMLUnitConverter &)=delete
void convertMeasureToXML(OUStringBuffer &rBuffer, sal_Int32 nMeasure) const
convert measure to string: from meCoreMeasureUnit to meXMLMeasureUnit
static bool convertHex(sal_uInt32 &nVal, std::u16string_view rValue)
convert string (hex) to number (sal_uInt32)
void createNumTypeInfo() const
::std::unique_ptr< Impl > m_pImpl