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>
72 mutable uno::Reference< i18n::XCharacterClassification >
m_xCharClass;
75 Impl(uno::Reference<uno::XComponentContext>
const& xContext,
76 sal_Int16
const eCoreMeasureUnit,
77 sal_Int16
const eXMLMeasureUnit,
85 OSL_ENSURE(
m_xContext.is(),
"got no service manager" );
98const uno::Reference< text::XNumberingTypeInfo >&
101 if (!
m_pImpl->m_xNumTypeInfo.is())
105 return m_pImpl->m_xNumTypeInfo;
110 m_pImpl->m_eCoreMeasureUnit = eCoreMeasureUnit;
115 m_pImpl->m_eXMLMeasureUnit = eXMLMeasureUnit;
120 return m_pImpl->m_eXMLMeasureUnit;
131 m_pImpl->m_eODFVersion = nODFVersion;
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))
154 sal_Int16 eUnit = util::MeasureUnit::INCH;
158 eUnit = util::MeasureUnit::MM;
163 eUnit = util::MeasureUnit::CM;
165 case FieldUnit::TWIP:
166 eUnit = util::MeasureUnit::TWIP;
168 case FieldUnit::POINT:
169 case FieldUnit::PICA:
170 eUnit = util::MeasureUnit::POINT;
172 case FieldUnit::MM_100TH:
173 eUnit = util::MeasureUnit::MM_100TH;
175 case FieldUnit::INCH:
176 eUnit = util::MeasureUnit::INCH;
187 std::u16string_view rString,
188 sal_Int32 nMin, sal_Int32 nMax )
const
190 return ::sax::Converter::convertMeasure(
nValue, rString,
197 std::string_view rString,
198 sal_Int32 nMin, sal_Int32 nMax )
const
200 return ::sax::Converter::convertMeasure(
nValue, rString,
207 sal_Int32 nMeasure )
const
221 return s.makeStringAndClear();
228 std::u16string_view rValue,
234 if(
static_cast<sal_Int32
>(rValue.size()) == nameLength &&
235 rtl_ustr_asciil_reverseEquals_WithLength(
236 rValue.data(), pMap->
GetName(), nameLength ) )
251 std::u16string_view rValue,
258 rEnum = pMap->GetValue();
270 std::string_view rValue,
277 rEnum = pMap->GetValue();
290 OUStringBuffer& rBuffer,
299 if( pMap->GetValue() == nValue )
301 eTok = pMap->GetToken();
319 if( nChar >=
'0' && nChar <=
'9' )
321 else if( nChar >=
'a' && nChar <=
'f' )
322 return nChar -
'a' + 10;
323 else if( nChar >=
'A' && nChar <=
'F' )
324 return nChar -
'A' + 10;
334 double fNumber)
const
342 std::u16string_view rString)
const
345 rString,
m_pImpl->m_eCoreMeasureUnit);
347 return ::sax::Converter::convertDouble(rValue, rString,
348 eSrcUnit,
m_pImpl->m_eCoreMeasureUnit);
353 std::string_view rString)
const
356 rString,
m_pImpl->m_eCoreMeasureUnit);
358 return ::sax::Converter::convertDouble(rValue, rString,
359 eSrcUnit,
m_pImpl->m_eCoreMeasureUnit);
365 css::uno::Reference <css::util::XNumberFormatsSupplier> xNumberFormatsSupplier (
xModel, css::uno::UNO_QUERY);
366 if (xNumberFormatsSupplier.is())
368 const css::uno::Reference <css::beans::XPropertySet> xPropertySet = xNumberFormatsSupplier->getNumberFormatSettings();
369 return xPropertySet.is() && (xPropertySet->getPropertyValue(
XML_NULLDATE) >>=
m_pImpl->m_aNullDate);
376 const double& fDateTime,
bool const bAddTimeIf0AM)
383 std::u16string_view rString)
const
390 std::string_view rString)
const
397 const double& fDateTime,
398 const css::util::Date& aTempNullDate,
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);
406 const bool bHasTime = (fValue > 0.0);
408 sal_Int16 nTempYear = aDate.
GetYear();
409 assert(nTempYear != 0);
412 rBuffer.append(
'-');
413 nTempYear = -nTempYear;
415 if (nTempYear < 1000)
416 rBuffer.append(
'0');
418 rBuffer.append(
'0');
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);
426 rBuffer.append(
'0');
427 rBuffer.append( sal_Int32( nTemp));
428 rBuffer.append(
'-');
430 assert(1 <= nTemp && nTemp <= 31);
432 rBuffer.append(
'0');
433 rBuffer.append( sal_Int32( nTemp));
434 if (!(bHasTime || bAddTimeIf0AM))
439 fCount = ::rtl::math::approxFloor (log10(
static_cast<double>(nDays))) + 1;
441 fCount = ::rtl::math::approxFloor (log10(
static_cast<double>(nDays * -1))) + 1;
444 const int nDigits = sal_Int16(fCount) + 4;
447 sal_uInt16 nHour, nMinute, nSecond;
448 double fFractionOfSecond;
452 rBuffer.append(
'T');
454 rBuffer.append(
'0');
455 rBuffer.append( sal_Int32( nHour));
456 rBuffer.append(
':');
458 rBuffer.append(
'0');
459 rBuffer.append( sal_Int32( nMinute));
460 rBuffer.append(
':');
462 rBuffer.append(
'0');
463 rBuffer.append( sal_Int32( nSecond));
464 if (!nFractionDecimals)
469 OUString aFraction( ::rtl::math::doubleToUString( fFractionOfSecond,
470 rtl_math_StringFormat_F,
471 nFractionDecimals + 1,
'.',
true));
472 const sal_Int32 nLen = aFraction.getLength();
476 const sal_Int32
nCount = nLen - 2 -
static_cast<int>(nLen > nFractionDecimals + 2);
477 rBuffer.append(
'.');
478 rBuffer.append( aFraction.subView(2,
nCount));
485 V rString,
const css::util::Date& aTempNullDate)
487 css::util::DateTime aDateTime;
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;
504 fDateTime = fTempDateTime;
510 std::u16string_view rString,
const css::util::Date& aTempNullDate)
516 std::string_view rString,
const css::util::Date& aTempNullDate)
523: maTokenString( rString ), mnNextTokenPos(0), mcSeparator( cSeparator )
533 if( nTokenEndPos != std::u16string_view::npos )
553static bool lcl_getPositions(std::string_view _sValue, std::string_view& _rContentX, std::string_view& _rContentY, std::string_view& _rContentZ)
555 if(_sValue.empty() || _sValue[0] !=
'(')
559 size_t nFound = _sValue.find(
' ',
nPos);
561 if(nFound == std::string_view::npos || nFound <=
nPos)
564 _rContentX = _sValue.substr(
nPos, nFound -
nPos);
567 nFound = _sValue.find(
' ',
nPos);
569 if(nFound == std::string_view::npos || nFound <=
nPos)
572 _rContentY = _sValue.substr(
nPos, nFound -
nPos);
575 nFound = _sValue.find(
')',
nPos);
577 if(nFound == std::string_view::npos || nFound <=
nPos)
580 _rContentZ = _sValue.substr(
nPos, nFound -
nPos);
588 std::string_view aContentX,aContentY,aContentZ;
592 rtl_math_ConversionStatus eStatus;
594 rVector.
setX(::rtl::math::stringToDouble(aContentX,
'.',
597 if( eStatus != rtl_math_ConversionStatus_Ok )
600 rVector.
setY(::rtl::math::stringToDouble(aContentY,
'.',
603 if( eStatus != rtl_math_ConversionStatus_Ok )
606 rVector.
setZ(::rtl::math::stringToDouble(aContentZ,
'.',
610 return ( eStatus == rtl_math_ConversionStatus_Ok );
627 std::string_view rValue )
const
629 std::string_view aContentX,aContentY,aContentZ;
642 const drawing::Position3D& rPosition )
644 rBuffer.append(
'(' );
646 rBuffer.append(
' ' );
648 rBuffer.append(
' ' );
650 rBuffer.append(
')' );
655 const OUString& rNumFmt,
656 std::u16string_view rNumLetterSync,
657 bool bNumberNone )
const
662 sal_Int32 nLen = rNumFmt.getLength();
666 rType = NumberingType::NUMBER_NONE;
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;
685 case NumberingType::CHARS_LOWER_LETTER:
686 rType = NumberingType::CHARS_LOWER_LETTER_N;
688 case NumberingType::CHARS_UPPER_LETTER:
689 rType = NumberingType::CHARS_UPPER_LETTER_N;
701 if( xInfo.is() && xInfo->hasNumberingType( rNumFmt ) )
703 rType = xInfo->getNumberingType( rNumFmt );
707 rType = NumberingType::ARABIC;
715 sal_Int16 nType )
const
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;
729 case NumberingType::CHAR_SPECIAL:
730 case NumberingType::PAGE_DESCRIPTOR:
731 case NumberingType::BITMAP:
746 rBuffer.append( xInfo->getNumberingIdentifier(
nType ) );
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:
764 case NumberingType::CHARS_UPPER_LETTER_N:
765 case NumberingType::CHARS_LOWER_LETTER_N:
769 case NumberingType::CHAR_SPECIAL:
770 case NumberingType::PAGE_DESCRIPTOR:
771 case NumberingType::BITMAP:
780 const uno::Reference<beans::XPropertySet>& aProperties)
782 uno::Reference< beans::XPropertySetInfo > xPropertySetInfo =
aProperties->getPropertySetInfo();
783 if (!xPropertySetInfo.is())
786 const uno::Sequence< beans::Property > aProps = xPropertySetInfo->getProperties();
787 if (aProps.hasElements())
789 rProps.realloc(aProps.getLength());
790 beans::PropertyValue* pProps = rProps.getArray();
791 for (
const auto& rProp : aProps)
793 pProps->Name = rProp.Name;
794 pProps->Value =
aProperties->getPropertyValue(rProp.Name);
801 const uno::Sequence<beans::PropertyValue>& aProps)
803 if (aProps.hasElements())
805 uno::Reference< beans::XPropertySetInfo > xPropertySetInfo = rProperties->getPropertySetInfo();
806 if (xPropertySetInfo.is())
808 for (
const auto& rProp : aProps)
810 if (xPropertySetInfo->hasPropertyByName(rProp.Name))
811 rProperties->setPropertyValue(rProp.Name, rProp.Value);
819 const OUString& rName,
820 bool *pEncoded )
const
825 sal_Int32 nLen = rName.getLength();
826 OUStringBuffer
aBuffer( nLen*2 );
828 for( sal_Int32
i = 0;
i < nLen;
i++ )
831 bool bValidChar =
false;
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 ==
'.') );
845 if( (c >= 0xf900U && c <= 0xfffeU) ||
846 (c >= 0x20ddU && c <= 0x20e0U))
850 else if( (c >= 0x02bbU && c <= 0x02c1U) || c == 0x0559 ||
851 c == 0x06e5 || c == 0x06e6 )
855 else if( c == 0x0387 )
861 if (!
m_pImpl->m_xCharClass.is())
863 m_pImpl->m_xCharClass = CharacterClassification::create(
m_pImpl->m_xContext );
869 case UnicodeType::UPPERCASE_LETTER:
870 case UnicodeType::LOWERCASE_LETTER:
871 case UnicodeType::TITLECASE_LETTER:
872 case UnicodeType::OTHER_LETTER:
873 case UnicodeType::LETTER_NUMBER:
876 case UnicodeType::NON_SPACING_MARK:
877 case UnicodeType::ENCLOSING_MARK:
878 case UnicodeType::COMBINING_SPACING_MARK:
879 case UnicodeType::MODIFIER_LETTER:
880 case UnicodeType::DECIMAL_DIGIT_NUMBER:
895 aHexTab[ (c >> 12) & 0x0f ] ) );
898 aHexTab[ (c >> 8) & 0x0f ] ) );
901 aHexTab[ (c >> 4) & 0x0f ] ) );
911 if(
aBuffer.getLength() > ((1<<15)-1) )
919 return aBuffer.makeStringAndClear();
925 if( rValue.size() != 8 )
929 for (
int i = 0;
i < 8;
i++ )
932 | sal::static_int_cast< sal_uInt32 >(
lcl_gethex( rValue[
i] ) );
942 for (
int i = 0;
i < 8;
i++ )
PropertiesInfo aProperties
void AddDays(sal_Int32 nAddDays)
sal_Int16 GetYear() const
sal_uInt16 GetDay() const
sal_uInt16 GetMonth() const
std::u16string_view maTokenString
bool getNextToken(std::u16string_view &rToken)
SvXMLTokenEnumerator(std::u16string_view rString, sal_Unicode cSeparator=u' ')
bool convertPosition3D(css::drawing::Position3D &rPosition, std::string_view rValue) const
convert string to Position3D
SvtSaveOptions::ODFSaneDefaultVersion getSaneDefaultVersion() const
ODF version, only when exporting.
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
struct SAL_DLLPRIVATE Impl
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
SvXMLUnitConverter(const SvXMLUnitConverter &)=delete
void convertDateTime(OUStringBuffer &rBuffer, const double &fDateTime, bool const bAddTimeIf0AM=false)
convert double to ISO Date Time String
OUString encodeStyleName(const OUString &rName, bool *pEncoded=nullptr) const
void SetCoreMeasureUnit(sal_Int16 const eCoreMeasureUnit)
sets the default unit for numerical measures
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
static bool convertHex(sal_uInt32 &nVal, std::u16string_view rValue)
convert string (hex) to number (sal_uInt32)
::std::unique_ptr< Impl > m_pImpl
static sal_Int16 GetMeasureUnit(FieldUnit const nFieldUnit)
sal_Int16 GetXMLMeasureUnit() const
gets the default unit for textual measures
void convertDouble(OUStringBuffer &rBuffer, double fNumber) const
convert double number to string (using ::rtl::math) and DO convert to export MapUnit using meCoreMeas...
bool setNullDate(const css::uno::Reference< css::frame::XModel > &xModel)
get the Null Date of the XModel and set it to the UnitConverter
static bool convertB3DVector(::basegfx::B3DVector &rVector, std::string_view rValue)
convert string to basegfx::B3DVector
void convertMeasureToXML(OUStringBuffer &rBuffer, sal_Int32 nMeasure) const
convert measure to string: from meCoreMeasureUnit to meXMLMeasureUnit
void overrideSaneDefaultVersion(SvtSaveOptions::ODFSaneDefaultVersion const)
static void convertNumLetterSync(OUStringBuffer &rBuffer, sal_Int16 nType)
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,...
const css::uno::Reference< css::text::XNumberingTypeInfo > & getNumTypeInfo() const
gets XNumberingTypeInfo
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)
#define SAL_WARN_IF(condition, area, stream)
Handling of tokens in XML:
XMLTokenEnum
The enumeration of all XML tokens.
bool IsXMLToken(std::u16string_view rString, enum XMLTokenEnum eToken)
compare eToken to the string
const OUString & GetXMLToken(enum XMLTokenEnum eToken)
return the OUString representation for eToken
Map a const char* (with length) to a sal_uInt16 value.
const char * GetName() const
sal_Int32 GetNameLength() const
sal_Int16 m_eCoreMeasureUnit
uno::Reference< uno::XComponentContext > m_xContext
uno::Reference< text::XNumberingTypeInfo > m_xNumTypeInfo
uno::Reference< i18n::XCharacterClassification > m_xCharClass
Impl(uno::Reference< uno::XComponentContext > const &xContext, sal_Int16 const eCoreMeasureUnit, sal_Int16 const eXMLMeasureUnit, SvtSaveOptions::ODFSaneDefaultVersion const nODFVersion)
void createNumTypeInfo() const
sal_Int16 m_eXMLMeasureUnit
SvtSaveOptions::ODFSaneDefaultVersion m_eODFVersion
Reference< XModel > xModel
std::unique_ptr< char[]> aBuffer
constexpr OUStringLiteral XML_NULLDATE
static bool lcl_convertDateTime(double &fDateTime, V rString, const css::util::Date &aTempNullDate)
convert ISO Date Time String to double
const sal_Int8 XML_MAXDIGITSCOUNT_TIME
static int lcl_gethex(int nChar)
static bool lcl_getPositions(std::string_view _sValue, std::string_view &_rContentX, std::string_view &_rContentY, std::string_view &_rContentZ)